You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
dl blooop/devlaunch@test/branc-title_123 names the tab devlaunch@test/branc-title-123. The underscore is now a dash. feat/ABC_123
reads feat/abc-123, so the case goes as well. Measured against main at
0.50.0, by calling WorkspaceId::label directly:
test/branc-title_123 -> id devlaunch-test-branc-title-123-hx1w label devlaunch@test/branc-title-123
feat/ABC_123 -> id devlaunch-feat-abc-123-ktsk label devlaunch@feat/abc-123
Why it happens
Nothing is filtering the title for safety. sanitize_title
(rust/devlaunch-core/src/flows/launch.rs) drops control characters, $, a
backtick and a backslash, and finds nothing to do on this path: a derived name
never holds any of them.
The reshaping is slug
(rust/devlaunch-core/src/domain/workspace_id.rs), which lowercases and
collapses every run of non-alphanumerics to one dash. That rule belongs to the id, and the id has to obey it: it names a devpod workspace and it is the
container's hostname, so it has to be a DNS label. WorkspaceId::label is
defined as a rendering of the id rather than a second reading of the spec,
which is what keeps a tab matchable by eye against a dl --ls row, so it
inherits the id's alphabet wholesale.
Why that is worth revisiting
A tab is not a DNS label and not a devpod name. #626 made exactly this argument
for the / and put the branch's slashes back, and the same argument covers _, . and the case: all of them are inert in every sink the label reaches. The OSC
2 escape is BEL-terminated, herdr tab rename takes the label as argv with no
shell, and the container's PS1 line is shell-quoted and re-expanded rather
than re-parsed, so only $, a backtick and a backslash would ever act, and sanitize_title already drops those.
So #626 was a half-step. It restored one of the four things the id's alphabet
takes off a branch name and left the other three, on no principle that
distinguishes them.
The decision this needs
Not "stop filtering" but what a tab is a rendering of, decided once:
The id, as today. The tab and a dl --ls row stay matchable character for
character apart from the separators. feature/auth and Feature_auth keep
reading alike, which is the same ambiguity Spell the branch's slashes in the name a tab reads #626 removed for slashes.
The branch as typed, cut to the id's budget with the id's
segment-dropping. A tab then says what you typed, and the price is that the
readable half of a tab no longer matches the readable half of the id: a
reader matching devlaunch@Feature_auth against devlaunch-feature-auth-3j1t has to know the slug rule to see they are one
workspace.
Whichever wins, docs/workspaces.md's renderings table is where it is written
down, and the length budget, the dropped middle segments and the four-character
suffix are not in question either way.
Worth pinning in the same change: the label's alphabet is currently asserted in a_label_holds_one_at_and_nothing_else_a_shell_or_a_terminal_reads
(workspace_id.rs), which would have to move with the decision, and the_prompt_that_repaints_the_title_renders_it_as_text
(flows/provision.rs) is where a new character earns its keep by being rendered
through a real bash prompt.
dl blooop/devlaunch@test/branc-title_123names the tabdevlaunch@test/branc-title-123. The underscore is now a dash.feat/ABC_123reads
feat/abc-123, so the case goes as well. Measured againstmainat0.50.0, by calling
WorkspaceId::labeldirectly:Why it happens
Nothing is filtering the title for safety.
sanitize_title(
rust/devlaunch-core/src/flows/launch.rs) drops control characters,$, abacktick and a backslash, and finds nothing to do on this path: a derived name
never holds any of them.
The reshaping is
slug(
rust/devlaunch-core/src/domain/workspace_id.rs), which lowercases andcollapses every run of non-alphanumerics to one dash. That rule belongs to the
id, and the id has to obey it: it names a devpod workspace and it is the
container's hostname, so it has to be a DNS label.
WorkspaceId::labelisdefined as a rendering of the id rather than a second reading of the spec,
which is what keeps a tab matchable by eye against a
dl --lsrow, so itinherits the id's alphabet wholesale.
Why that is worth revisiting
A tab is not a DNS label and not a devpod name. #626 made exactly this argument
for the
/and put the branch's slashes back, and the same argument covers_,.and the case: all of them are inert in every sink the label reaches. The OSC2 escape is BEL-terminated,
herdr tab renametakes the label as argv with noshell, and the container's
PS1line is shell-quoted and re-expanded ratherthan re-parsed, so only
$, a backtick and a backslash would ever act, andsanitize_titlealready drops those.So #626 was a half-step. It restored one of the four things the id's alphabet
takes off a branch name and left the other three, on no principle that
distinguishes them.
The decision this needs
Not "stop filtering" but what a tab is a rendering of, decided once:
dl --lsrow stay matchable character forcharacter apart from the separators.
feature/authandFeature_authkeepreading alike, which is the same ambiguity Spell the branch's slashes in the name a tab reads #626 removed for slashes.
segment-dropping. A tab then says what you typed, and the price is that the
readable half of a tab no longer matches the readable half of the id: a
reader matching
devlaunch@Feature_authagainstdevlaunch-feature-auth-3j1thas to know the slug rule to see they are oneworkspace.
Whichever wins,
docs/workspaces.md's renderings table is where it is writtendown, and the length budget, the dropped middle segments and the four-character
suffix are not in question either way.
Worth pinning in the same change: the label's alphabet is currently asserted in
a_label_holds_one_at_and_nothing_else_a_shell_or_a_terminal_reads(
workspace_id.rs), which would have to move with the decision, andthe_prompt_that_repaints_the_title_renders_it_as_text(
flows/provision.rs) is where a new character earns its keep by being renderedthrough a real bash prompt.