Verdict and comment readbacks only; reconstructed candidate/ copies and queue-91/r2 left untracked. Co-Authored-By: Claude Opus 5.5 <[email protected]>
4.0 KiB
Row draft: row 41 follow-ups, gate spelling tests and real workspace path
Drafted by Filbert, 2026-10-11, at Sage's request. Not a row yet and not
started. Sources: agents/filbert/work/s6/BUILD.md ("Darkwing's other
round 3 notes", "Follow-ups"), Darkwing's s6-review/review-r3.md
("Mutants", fix 2 under R5) and review-r4.md (mutant table, note 2).
Proposed row fields
- piece: "Row 41 follow-ups: gate spelling tests and the real workspace path"
- owner: filbert
- reviewers: darkwing
- issues: a new Gitea issue (none yet), linked to #1523
- after: row 41 done
- required: false
- gate: "darkwing approves; harness, seat and cli tests, every scripts/test-*.sh green on Sage's gate rerun; Mw, Mx, My and Mz killed"
- brief: a section in a plan file Sage picks. The text is below.
Brief text
Problem
Row 41's gate (packages/harness/src/gate.mjs) checks every spelling of
a file name a harness might open: curly and straight apostrophes,
NFC and NFD, the narrow no-break space before AM/PM. Darkwing's round 3
and round 4 mutants Mw, Mx, My and Mz survive the whole harness suite
(56 pass, 0 fail, in r4/mut/summary.txt). The code is right. The tests
don't pin it:
| Mutant | Change | Spell-edge cases it flips from refuse to allow |
|---|---|---|
| Mw | the AM/PM regex without i |
1, lowercase am |
| Mx | ' replaced once, not globally |
2, two apostrophes |
| My | any lstat error skips the spelling |
10, a path below a respelled self-loop |
| Mz | spellings() skips normalise |
3 to 6: @ prefix, NBSP before AM, file://, %27 |
Under Mw, Mx and Mz, Pi would open the outside file. My is milder: on
ELOOP Pi's access() fails too and nothing opens, but the same skip
would also pass EACCES.
Separately, workspaceDir() (packages/seat/src/session.mjs:46) joins
the configured dataRoot without resolving it. A dataRoot on a
symlink then reaches the harness as the given path, in the policy's
workspace and in MOSAIC_WORKSPACE. R5 is fixed in the gate (it checks a
relative path against both the given and the real base), so this is
hygiene, not a hole (Darkwing, round 4 note 2).
Owner and reviewer
- Owner: Filbert, after row 41.
- Reviewer: Darkwing.
Files owned
packages/harness/tests/gate.test.mjs, packages/seat/src/session.mjs
(or packages/cli/src/launcher.mjs, the packet says which), their tests,
the READMEs that describe the workspace path, and
agents/filbert/work/<row dir>/.
What ships
gate.test.mjscases, in both harness modes, from Darkwing'sr3/probe/spell-edges.mjs: lowercaseam(1), two apostrophes (2), an@prefix and afile://path with and without%27(3, 5, 6), NBSP before AM in the asked name (4), and a path below a respelled self-loop (10). Each case asserts the refusal and its reason. Tests only, no gate change, unless a case shows a real gap.- The workspace path is the real path. The workspace directory is made
by the launcher (
mkdirSync,launcher.mjs:159) afterworkspaceDir()returns, so either realpath thedataRootinsideworkspaceDir(), or realpath the workspace once in the launcher after themkdir. The packet says which and why. The policy, the runner's cwd andMOSAIC_WORKSPACEthen all carry one path. A test with adataRootbehind a symlink asserts all three. - The mutant run: Mw, Mx, My and Mz rerun against the candidate, each killed, plus one mutant that drops the realpath and is killed.
Out of scope
- The Ma leftover (a
fake-adapter.mjsoutliving a harness run) and the other BUILD.md follow-ups (commit.test.mjspausedCommit,test-task.sh's Docker-only check, the conversationshim.mjsleftover). Sage may add Ma here, because it is the same package; the others belong to their own packages. - Any change to the gate's spelling logic itself.
Gate
Darkwing approves naming the candidate. Harness, seat and cli suites and
every scripts/test-*.sh are green on Sage's gate rerun. The four
survivors and the realpath mutant are killed in the packet's mutant run.