Summary
PR #98 sanitizes the unit worktree directory (workspace.open_unit_workspace: unit_worktrees_dir(run_dir) / safe_segment(unit_key)) and the failed dir, but unit_branch_name (workspace.py:62-67) still builds the git branch bmad-loop/{run_id}/{unit_key} from the raw key. A unit key containing git-ref-illegal sequences (:, ?, [, \\, space, .., @{, a trailing .lock, leading/trailing /…) now gets past the filesystem layer only to fail at branch_exists/worktree_add with an invalid-ref error.
Not a reader-mismatch bug: the branch is stored on task.branch at open time and every consumer (_merge_local, discard_worktree, close_unit_workspace) uses the stored value — the failure is purely at creation time. Pre-existing behavior, but after #98 the dir/branch pair is inconsistently hardened, which can read as a false sense of safety.
Fix direction
Sanitize the branch segment too. Note git ref rules ≠ Windows filename rules, so safe_segment alone is not sufficient (e.g. .., @{, trailing .lock are ref-illegal but filename-legal): either a dedicated ref-segment sanitizer (same identity-for-clean-input + digest-suffix contract as safe_segment), or safe_segment plus a git check-ref-format --branch validation pass with the digest fallback.
Surfaced by the consumer audit of PR #98.
Refs: #74, #98
Summary
PR #98 sanitizes the unit worktree directory (
workspace.open_unit_workspace:unit_worktrees_dir(run_dir) / safe_segment(unit_key)) and the failed dir, butunit_branch_name(workspace.py:62-67) still builds the git branchbmad-loop/{run_id}/{unit_key}from the raw key. A unit key containing git-ref-illegal sequences (:,?,[,\\, space,..,@{, a trailing.lock, leading/trailing/…) now gets past the filesystem layer only to fail atbranch_exists/worktree_addwith an invalid-ref error.Not a reader-mismatch bug: the branch is stored on
task.branchat open time and every consumer (_merge_local,discard_worktree,close_unit_workspace) uses the stored value — the failure is purely at creation time. Pre-existing behavior, but after #98 the dir/branch pair is inconsistently hardened, which can read as a false sense of safety.Fix direction
Sanitize the branch segment too. Note git ref rules ≠ Windows filename rules, so
safe_segmentalone is not sufficient (e.g...,@{, trailing.lockare ref-illegal but filename-legal): either a dedicated ref-segment sanitizer (same identity-for-clean-input + digest-suffix contract assafe_segment), orsafe_segmentplus agit check-ref-format --branchvalidation pass with the digest fallback.Surfaced by the consumer audit of PR #98.
Refs: #74, #98