Phase 2: A workspace has a display label #483
No reviewers
Labels
No labels
agent-ready
bug
contract
documentation
duplicate
enhancement
good first issue
help wanted
invalid
needs-human
needs-input
question
wontfix
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
iterative-works/iw-cli!483
Loading…
Reference in a new issue
No description provided.
Delete branch "IW-476-phase-02"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Phase 2 of IW-476. A worktree now carries two names, each with one job.
WorktreePath.sessionName,<project>-<key>. Unchanged. It is the tmux session name, and under herdr it is the stringLiveHerdrOpsderives the checkout path from.WorktreePath.workspaceLabel,key.value. Written once when the workspace is created, and read back by nothing.TerminalWorkspaceOps.createcarries both. Under herdr the label reachesherdr worktree open --label, so the sidebar row readsIW-476rather thaniw-cli-IW-476, and an effort row readsmail-capturerather thaniw-cli-mail-capture. Under tmux the label is accepted and discarded — tmux has no display name distinct from its session name.This is the phase the user sees. Phase 1 changed no sidebar text.
Changes
core/model/WorktreePath.scala—workspaceLabelas a derived method, besidedirectoryNameandsessionName. No third case-class parameter, no branch onWorktreeKey.core/commands/CommandEnv.scala—TerminalWorkspaceOps.createwidened to(name, label, workDir), with scaladoc stating which name addresses, which displays, and that no implementation may read a label back. No default onlabel, so the compiler names every call site.UnavailableWorkspaceOps,LiveTmuxOps,LiveHerdrOps) and the test fake follow.LiveHerdrOps.createforwardslabel— notname— toHerdrAdapter.openWorktree.Start.scala,Open.scala,CaskServer.scala, plus two compile-forced test call sites.docs/api/WorktreeTypes.md— documentsworkspaceLabeland fixes a staleissueId: IssueIdsignature that predates this issue (the code has takenkey: WorktreeKeysince effort worktrees landed).⚠️ This phase ships manually unverified
No automated tier reaches herdr. All E2E BATS suites force
IW_WORKSPACE_BACKEND=tmux, and no seam was extracted — Michal's recorded decision inanalysis.md(RESOLVED: How is the herdr behaviour actually verified?).Two manual checklists are outstanding, and together they gate the final PR to main — not this PR. Phase 1's and Phase 2's, both recorded in
implementation-log.mdunder Deferred manual verification. They run in one live-herdr session; theiw startitems go first because they create the worktrees Phase 1'siw open/iw rmitems need.Accepted risks, stated plainly
The label rule is proved one layer above the code that sends it.
FakeTerminalWorkspaceOps.CreateCall.labelrecords what the command handed the port;LiveCommandEnv.scala:728, which actually sends it to herdr, is covered by nothing. A change that passednamethere would keep every automated tier green.Two label conventions will coexist in one sidebar. A worktree created from the browser keeps
<project>-<key>; one created byiw startgets<key>. Both resolve by path, so this is cosmetic. The dashboard's own worktree-creation path is deliberately out of scope and tracked as IW-477; the call site carries a comment saying so.Deferring the manual check has a cost. The label rule and the docs are both written before anyone has seen the sidebar. If herdr does not nest worktrees under a project row the way
analysis.mdrecords, both need a follow-up change and the published skills need a second rebuild.Testing
TDD in two moves, so the assertions could be proved RED honestly. The port widening landed first with every call site passing
sessionNametwice — compiling and green, but proving nothing. The.labelassertions then went in and were confirmed RED (obtainedtestproject-IWLE-400/testproject-IWLE-123whereIWLE-400/IWLE-123was expected), and only then did the call sites pass the real label.core/test/WorktreePathTest.scala— 3 tests: the label for an issue key, for an effort key, and that it differs fromsessionNameanddirectoryName.StartHarnessTest/OpenHarnessTest— the only automated proof of the issue's first acceptance criterion.core.test186/186,dashboard.test241/241,./iw ./test e2eexit 0 with 190 passing. No BATS file modified.Code review
0 critical, 2 warnings, 5 suggestions across six review skills —
review-phase-02-20260830-113230.md.Both warnings described one shape:
nameandlabelalways travel together but pass as two loose same-typed positional strings, so a transposed call compiles silently and would misbehave differently per backend (tmux readsname, herdr readslabel). Fixed at the three call sites with named arguments, which removes the risk without changing the port signature the phase context specifies. The fullerWorkspaceIdentity(name, label)bundling isLESSONS.mdentry 14, proposed for a new tracker issue.The security reviewer confirmed the change is security-neutral: the label reaches a discrete argv element with no shell on the path,
IssueId/EffortSlugparsing forbids a leading-so it cannot be read as a flag, and it reaches no HTML rendering path.A worktree now carries two names, each with one job. sessionName addresses it — the tmux session name, and the string LiveHerdrOps derives the checkout path from. workspaceLabel is what a person reads. - WorktreePath.workspaceLabel is key.value, a derived method beside directoryName and sessionName. No third case-class parameter and no branch on WorktreeKey. - TerminalWorkspaceOps.create carries both names. Its scaladoc states which addresses, which displays, and that no implementation may read a label back: a label the user renames must not change what any operation resolves. There is no default on label, so the compiler names every call site. - LiveHerdrOps.create forwards the label — not the name — to HerdrAdapter.openWorktree, so the herdr sidebar row reads IW-476 rather than iw-cli-IW-476, and an effort row reads mail-capture rather than iw-cli-mail-capture. LiveTmuxOps accepts the label and discards it; tmux has no display name apart from its session name. - CaskServer passes the session name as both, deliberately and with a comment. The dashboard's own worktree-creation path is out of scope, tracked as IW-477, so two label conventions will coexist in one sidebar. Both resolve by path, so the difference is cosmetic. - docs/api/WorktreeTypes.md documents workspaceLabel and corrects a stale issueId: IssueId signature that predates this issue — the code has taken key: WorktreeKey since effort worktrees landed. The widening took two moves so the assertions could be proved RED honestly: every call site first passed sessionName twice, which compiles and stays green while proving nothing, then the .label assertions went in and failed, and only then did the call sites pass the real label. Code review: 6 skills, 0 critical, 2 warnings. Both described one shape — name and label always travel together but pass as two loose same-typed positional strings, and a transposed call would misbehave differently per backend. The three call sites now pass named arguments, which removes the risk without changing the signature the phase context specifies. The fuller WorkspaceIdentity bundling is LESSONS.md entry 14, for a new tracker issue. The manual herdr checklist is deferred to the final PR by Michal's decision, so this phase ships manually unverified. No automated tier reaches herdr, and the label rule is proved one layer above LiveCommandEnv.scala:728, which is the code that actually sends it. Issue: IW-476 🤖 Generated with Claude Code