voyage/tests/commands
Kjell Tore Guttormsen 63e78c5ec0 fix(trekexecute): make parallel-mode plan delivery portable and gitignore-tolerant
Two independent defects took down a real voyage on macOS today
(llm-ingestion-okf, wave 1, zero steps executed). Both paths led to the same
end state: the worktree had no plan.

1. Phase 2.6 Step 2a' derived the project relpath with
   `realpath --relative-to`, which is GNU coreutils only. On BSD realpath
   (macOS default) the substitution fails silently: PROJECT_REL ends up
   empty, `mkdir -p "$wt/"` and `cp ... "$wt//"` both succeed, and
   brief.md/plan.md land at the worktree root where no child session looks.
   The portable form existed only as a prose note saying an operator "may
   substitute" it — the note was prose, the code was what ran. The block now
   uses `python3 -c os.path.relpath` (stdlib), resolves both operands with
   bare realpath (identical on BSD and GNU, and correct across the macOS
   /var -> /private/var symlink), and aborts loudly when the relpath is
   empty or escapes the repo instead of dropping files at the root. The
   coreutils note is deleted rather than extended: two forms means the next
   reader picks, and that pick is what failed.

   Measured on this machine 2026-08-31 (Intel Mac, no coreutils):
   `realpath --relative-to=...` -> `realpath: illegal option -- -`;
   bare `realpath /Users/ktg/.claude` -> correct path, exit 0.

2. Phase 2.55 Check 2 ran `git add {plan-path}` unconditionally. When the
   project directory is gitignored (`.claude/projects/` is tool-managed and
   local-only — normal, not exotic) the add refuses and the plan never
   reaches HEAD. Check 2 now probes with `git check-ignore` and branches:
   tracked -> nothing; untracked -> add + commit as before; ignored -> step
   aside and let Step 2a' be the delivery path. `git add -f` was rejected as
   the fix: forcing operator-local artifacts into history publishes them to
   whatever remote the repo pushes to. A `check-ignore` exit code other than
   0 or 1 is fatal and stops execution — a probe that failed is not a probe
   that answered "not ignored".

Also fixed in the same block: `[ -d research ] && cp -r ...` as the last
statement of the loop body made a project without research/ exit the wave
non-zero.

TDD, Iron Law: tests/commands/trekexecute-parallel-portability.test.mjs
extracts both shell blocks from commands/trekexecute.md by grep-able anchor
and executes them, so the tests bind to what an agent actually copies. The
assertions check FILE PLACEMENT, not exit status — the whole defect is that
the broken form exits 0. Controls, all present before the fix: a
known-positive BSD-realpath stub (bare path resolves, GNU flag rejected with
`illegal option`), a negative control running the old GNU form under that
stub and asserting plan.md lands at the worktree root, a known-positive
Check 2 arm where a non-ignored plan is still added and committed, and a
stubbed fatal `git check-ignore` (128). Red first: 7 failed, 2 passed (the
two controls). Green after: 9/9.

Suite 1013 (1011/0/2) -> 1022 (1020/0/2). No version bump, no release.

Order: 20260831T214411Z-941965142-from-.claude (from .claude).

Co-Authored-By: Claude <claude-opus-5>
2026-08-31 23:53:55 +02:00
..
trekbrief.test.mjs feat(trekbrief): add fable tier option to Phase 3.5 loop 2026-07-02 17:02:56 +02:00
trekcontinue.test.mjs feat(voyage)!: bulk content rewrite ultra -> voyage/trek prose [skip-docs] 2026-05-05 15:08:20 +02:00
trekendsession.test.mjs fix(trekendsession): release v5.9.1 - eager-exec blocks crashed command load 2026-07-03 01:11:02 +02:00
trekexecute-parallel-portability.test.mjs fix(trekexecute): make parallel-mode plan delivery portable and gitignore-tolerant 2026-08-31 23:53:55 +02:00
trekexecute.test.mjs feat(voyage): surface iterations_remaining signal in trekexecute 2026-06-20 21:33:21 +02:00
trekplan.test.mjs refactor(voyage): S31 — V15 trim plan-export to headless-only (decompose alias) 2026-06-20 09:23:21 +02:00
trekresearch-engine.test.mjs test(trekresearch): pin deep-research adapter output contract 2026-06-30 13:38:09 +02:00
trekresearch.test.mjs fix(research-loop-cap): resolve the data root in code so the loop can run 2026-08-12 22:26:46 +02:00
trekreview.test.mjs feat(voyage): S11 — NW2 part B, integrate opt-in --workflow flag 2026-06-18 17:22:09 +02:00