Commit graph

145 commits

Author SHA1 Message Date
8bf97cc834
fix(execute): every test file on the Test first line is read, locked and copied
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 14:42:12 +02:00
6f342a2cdc
fix(plan): the Files reader gives 6.3.0's answer in the three known regressions
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 14:21:56 +02:00
10ac9c5231
fix(review): round 10 of the release review of 6.3.0, for 6.3.1
Round 10 (0f400d3..a1e0e50, WARN: 0 BLOCKER, 11 MAJOR): six findings, by
operator choice. Each began with a test that failed on a1e0e50 on its
assertion, every case on its own; suite 2236 (2234/0/2).

- Files: a new line inside a description opens a new entry when it opens
  with a plain file with a slash, or with one alone on the line or followed
  by a colon or a dash ("src/cli.mjs", "package.json", "Makefile - a
  target"); "child_process.spawnSync, path.join", "Node.js 22 only" and
  "index.js and the CLI" stay description (ecd9da6f).
- Files: a numbered list item (`1.` or `1)`) is an entry, its marker
  dropped like `-` (b4215783).
- Files: a backticked capitalised name is a file only alone in its entry
  before any description; `Parser` inside one is not (39a57fee).
- Files: a backticked span that is no path (`x()`:) starts no description
  with its colon (882cc82a); a plain file with a colon starts it wherever it
  stands ("the entry cli.mjs: wires parse", a6bd9c8c).
- Measured over all 939 Files: fields in the .md files under the
  marketplace and the test repo (560 of them in the 48 plan.md files outside
  worktrees): 0 read differently from a1e0e50, tests-only changed in 0.
- The trailing-json fence reader is built on plan-schema's fenceTracker:
  a ~~~ fence is a fence, so a ```json line inside one no longer swallows
  the review's own block or hides its BLOCKER ids (0d94c5fe). This also
  closes a gate hole in 6.3.0 and a1e0e50: a last block written as ~~~json
  holding a BLOCKER, after a clean ```json block, passed with exit 0; now 2.
- Kept on purpose: a fence line indented four spaces or more still counts
  in that reader (fenceTracker's new anyIndent). Markdown's three-space
  rule made a BLOCKER block inside a list item, four spaces in, invisible,
  and the gate passed it with exit 0 (seen while fixing, before commit); a
  ```json line in a code block indented four spaces fails the gate closed.
  Both are pinned in the 0d94c5fe test.
- The fieldPaths doc names rounds 1-10 (it said 1-7).

Not in this round (operator 2026-10-11): F8 754723c1 (an info string
" json" fails closed, as in 6.3.0), F9 88de9e6b, F10 164c5bd0, F11
e70b28b7 (dc3a467e). F1 878e3960: this title carries a scope; the three
earlier commits are left as they are.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 13:36:17 +02:00
a1e0e50451
fix: round 9 of the release review of 6.3.0, for 6.3.1
Round 9 (0f400d3..a10018f, WARN: 0 BLOCKER, 12 MAJOR): seven findings and
three brief notes, by operator choice. Each finding began with a test that
failed on a10018f on its assertion; suite 2230 (2228/0/2).

- A check refused for its comment (a quote, $, backtick or backslash) keeps
  its command and its reason, and every reader refuses it out loud: a nested
  ## Verification bullet stays a criterion (PLAN_VERIFICATION_NOT_RUNNABLE)
  and a brief SC warns (BRIEF_SC_NOT_RUNNABLE). It was folded into a
  sub-point or read as prose, a regression from a10018f. Readers that took a
  command as runnable (the end-to-end lists) skip a refused one.
- The verdict gate reads the last fenced block's info string and body from
  one reading, and exits 2 unless the info string is exactly json: a last
  block opened as ```json {x} held a BLOCKER the gate passed with exit 0
  (also in 6.3.0). A last block never closed is exit 2 too.
- One fence reader (findings-schema fencedBlocks) for the gate and every
  trailing-json reader: a fence closes only on a run at least as long as its
  opener, as in Markdown, so a four-backtick example of a json block is one
  block; CRLF and an indented fence read alike in the gate and the readers.
- Files: a description runs on past a comma and onto the next line until a
  new entry starts (a list item on a new line, or a backticked path), and a
  plain path followed by a colon starts its description. Measured over all
  939 Files: fields in the .md files under the marketplace and the test repo
  (560 of them in the 48 plan.md files outside worktrees): 0 read
  differently, tests-only changed in 0.
- The test lock compares --cmd by its words, so other blanks between the
  same words are the step's command.
- release-check decides "two files" on real paths: one review.md reached
  through a symlinked --repo is one file.
- Brief notes: red proof's stopped control run has its own test (green at
  once, red with the branch deleted); the two tests that assumed jest is not
  installed run with a PATH that finds only git (red on a10018f with a jest
  on PATH, green now); the Files: reader's doc states the measured counts
  (520 fields in 48 plan files at rounds 7-8, not "182 plans"; 560 now).

Not in this round (operator 2026-10-11): a144e9ce, 1dc2e785, dc3a467e,
2fa88853, 26873fa5.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 12:49:01 +02:00
a10018f9d3
fix: round 8 of the release review of 6.3.0, for 6.3.1
Round 8 (0f400d3..29b4ac9, BLOCK: 1 BLOCKER, 12 MAJOR, 1 MINOR). Each fix
began with a test that failed on 29b4ac9 (13 tests, all red there); suite
2221 (2219/0/2).

- BLOCKER: a backticked check whose trailing comment holds a quote, $,
  backtick or backslash is refused, not dropped. The comment was never
  screened, while the executor hands the Verify span as written to red
  proof, the test lock and the done line inside --cmd "...", where a $(...)
  runs and a quote ends the argument. trekplan's text and the reviewer's
  NOT RUN table say so.
- A span that is only a comment is not-a-command, not a placeholder. The
  dropComment text says the allowlist still refuses a word with a # in it.
- The criteria runner, comparison-gate and end-state-gate use isMain: they
  did nothing and exited 0 under a symlinked path. The test now refuses any
  process.argv[1] comparison outside lib/util/is-main.mjs.
- Files: in a field with backticked paths, a plain word counts only before
  the entry's description (a dash, or a colon after the path); a name with
  no slash only first in its entry or after and/or/+/&. "mocks
  fs.readFileSync", "runs on Node.js 22.x" or "no change to package.json"
  no longer make a tests-only step look like it builds something.
  Lowercase makefile, rakefile and justfile are build files. Measured on the
  520 Files: fields in 48 plans of the marketplace and the test repo:
  3 fields read differently (two notes no longer read as files, one
  duplicate name dropped), tests-only changed in 0.
- The test lock compares --cmd without its trailing comment, and the test
  lock and the done line read a stop with stoppedBy, the one reading.
  red-proof drops its second reading, spawnError.
- release-check reads a relative --review in --repo or, when only that one
  exists, from the current directory as 6.3.0 did; two different files are
  exit 2, never guessed. The runbook says so.
- One trailing-json reader: a closing fence may be longer than three
  backticks, in the block reader and the verdict gate alike, and the review
  validator and the synthesis digest use it, so three backticks inside a
  JSON string no longer hide a BLOCKER from the remediation-step check.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 10:43:56 +02:00
29b4ac91b3
fix: round 7 of the release review of 6.3.0, for 6.3.1
Round 7 (516dffa..45aa9e1, WARN: 12 MAJOR, 0 BLOCKER) and the fence defect
found while writing its review.md. Each fix began with a test that failed on
0f400d3 (v6.3.0); suite 2208 (2206/0/2), 14 tests more.

- Tests-only (operator 2026-10-11): the plan's Files: alone decides, and the
  text says so (red-proof, trekexecute Sub-step B, step-implementer,
  HANDOVER-CONTRACTS). red-proof no longer reads the step's diff, so a change
  already in the tree when the step began no longer counts against it, and a
  plan placed outside .claude/ reads the same. The round-6 test that had the
  diff overrule the plan is rewritten to the new rule.
- The Files: reader keeps a plain file beside a backticked path
  (", Dockerfile", "the CLI entry src/cli.mjs", "and Makefile"). Measured on
  the 520 Files: fields in 182 plans: no field reads differently.
- Red proof reports a command its timeout killed as killed after the timeout,
  not "could not start"; the release check tells a timeout from output past
  its buffer and from another signal. One reading of a stop
  (criteria-runner stoppedBy) for red proof, the criteria runner and the
  release check.
- A trailing `# comment` is dropped in a backticked check too, and in a
  command passed as written, so the words screened are the words run.
- The release check reads a relative --review in --repo.
- The 15-minute timeout is defined once (criteria-runner.mjs).
- The findings check reads each cited file once per validation.
- One isMain helper (lib/util/is-main.mjs) for every CLI: the 31 copies of
  the realpath guard and the 20 modules still on the file:// guard, which
  exited 0 having done nothing under a symlink or a path with a space.
- The Bash guard writes its no-one-to-ask refusal once, on a direct condition.
- The findings check ends a ```json block only at a fence on its own line, so
  three backticks inside a JSON string no longer end it (also in 6.2.0).
- Brief-conformance notes: a test for test-lock green on exit 127 (it
  passed at once; it fails when 127 is read as could-not-run); the prose now
  names the git revision `@~1` as the one leading-@ exception.

Not changed: the example plan's steps 1-2 keep their tests-only warning
(operator decision 2026-10-09; the r5 test records it). Brief note 4 (a
Regression: whose runner is not installed goes to the fix rounds) is a
routing question for the operator.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 09:11:57 +02:00
45aa9e107a
fix: round 6 of the release review of 6.3.0
Round 6 (v6.2.0..c3641ff, WARN: 11 MAJOR, 3 MINOR; 0 BLOCKER). The round-5
fixes hold (code-correctness-reviewer); three of the new MAJOR were side
effects of running checks with no shell. Each fixed behind a test that
failed first on c3641ff.

- git checks stay in the repo too: no path that climbs out with .., starts
  at / or reads <rev>:../x, and no --no-index (both reviewers).
- A trailing `# comment` on a shell-fence line is dropped: with no shell,
  its words made an honest check NOT RUN, among them the first check of the
  shipped example plan.
- A glob reaches `node --test` only on Node 21 and later, which expands it
  itself; on an older Node it is refused with that reason (engines >=18).
- With no shell, exit 126/127 is the test program's own: red proof reads it
  as a red (the control run still tells an environment fault apart), the
  done line and the test lock as a failure.
- A runner that could not start (not installed) is NOT RUN in the criteria
  runner and not-run (exit 2) in regression-check, as red-proof and
  done-line already said; never a red suite.
- Tests-only: a backticked `Makefile` alone in its entry is a path, and red
  proof confirms the plan's tests-only reading against the step's own diff
  (the altitude finding: the diff is a fact, the Files: prose is not).
- release-check stops a suite that never ends (15 minutes) and reads it as
  not measured (exit 2).
- The two lines this release added to pre-bash-executor.mjs are ASCII.
- MINOR: git and the other runners share one plain-word pattern.

Not in this round: MINOR f00a2eb8 (shared norm/ticked-path and isMain
helpers) and MINOR on plan-review-dedup's repeated tokenizing.

Suite 2194 (2192/0/2).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 01:07:47 +02:00
c3641ffa42
fix: round 5 of the release review of 6.3.0, the structural fix
Round 5 (v6.2.0..d37e538, WARN: 11 MAJOR, 2 MINOR). The patching did not
converge (the same two places every round), so the operator chose a
structural fix on 2026-10-11. Each change behind a test that failed first.

- A check runs with no shell. criteria-runner's runCommand starts the runner
  with the very words the screen checked (spawnSync(words[0], words.slice(1)),
  without NODE_TEST_CONTEXT); Phase 7 criteria, Regression: (its exec copy is
  gone, MINOR 0e98d5c7), proof of red, the done line and the test lock all
  run through it. No quote, glob, tilde or variable can rewrite a checked
  word any more. The screen stays and says why: a word that means something
  else in a shell (quote, backslash, $, brace, leading ~) is refused; a glob
  reaches only node --test, which expands its own patterns (sh read
  `tests/.?/` as `tests/../`); no path climbs out with .. or starts at /;
  a word starting with @ is refused (pytest reads @file as more arguments).
- The K6 plan-file sweep has v6.2.0's own Files: reader again (516dffa):
  backticked paths, and plain words only in a field without them. The
  shared reader from round 3 planned directories a description named and
  dropped paths v6.2.0 planned. fieldPaths stays for the tests-only check,
  with a path test on spans (`parse()`, `p.parse()` are no paths), plain
  descriptions ignored when the field has backticked paths, dotfiles,
  backslash paths and glued spans read.
- Skill frontmatter reads a value as YAML does: trailing space is nothing,
  and a comment ends a plain value, a flow list or a block indicator
  (`model: opus # pinned`). A comment that cuts a plain description, or is
  the whole value, is still a hazard.
- release-check reads the diff with --no-renames: a test moved into an
  allowed place after the review shows as removed.
- The example plan's step 2 heading no longer says "must FAIL initially";
  steps 1-2 keep the tests-only warning (operator 2026-10-09, 73262b6).

Open: MINOR c1fef1ad (one shared isMain helper) is not in this round.
Measured: 0 of 463 Files: fields with backticked paths (520 fields in 182
plans across the marketplace repos) carry another path-like word.

Suite 2185 (2183/0/2).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 00:38:42 +02:00
ab6dcd838e
fix: round 4 of the release review of 6.3.0
Round 4 (v6.2.0..41ea8fc, WARN: 9 MAJOR, 3 MINOR); the nine MAJOR fixed,
each behind a test that failed first (operator 2026-10-10). Three were
regressions from round 3's shared Files: reader.

- fieldPaths keeps a backticked path with punctuation after it and one
  inside a note, a directory (docs/) and a glob (src/*.mjs) in plain text,
  and app/(auth)/x.ts whole; a bare word counts only alone and capitalised
  (Makefile), so "format" or "v6.3.0" in a description is no path. The K6
  sweep plans what v6.2.0 planned for `a.mjs`: and `b.mjs`.
- skill frontmatter: a quoted value may carry a YAML comment after it.
- criteria runner: no word with a leading ~ (sh expands it), and nothing
  after `make test` (another target would run).
- release-check: scope_sha_end must be a commit sha (a ref name passed
  coverage whatever was reviewed), and README lines changed after the review
  may differ only in the badge's version. The round-3 leading-zero example
  is 7 characters now, the shortest sha accepted.

The three MINOR (one word screen for git, the exec copy in regression-check,
a shared isMain helper) are not in this round.

Suite 2175 (2173/0/2).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 23:48:52 +02:00
0e612c88ac
fix: round 3 of the release review of 6.3.0
Round 3 (v6.2.0..96cb977, BLOCK: 1 BLOCKER, 8 MAJOR, 2 MINOR), each fixed
behind a test that failed first.

- Every allowlisted runner, not only git, takes plain words and a short list
  of options that only read: an option that writes a file or loads code
  (--test-reporter-destination, --outputFile, --junitxml, --basetemp,
  --import, --config, -p, -o, -exec, a reporter path) is on no list; after
  `npm test --` only paths follow; `make test` takes no VAR=value. A built-in
  node test reporter (tap, spec, dot, junit, lcov) stays allowed.
- /trekexecute: a restore the guard refuses (destructive git, in the mode
  that shows no prompts) or the operator declines is never recorded as
  reverted: simplify = "revert-refused" and the run stops before review; a
  refused step revert is reported with its paths.
- stepTestsOnly: a fixture document under tests/ is a test file, "e.g." is
  not a path, ./ is dropped; the plan-file sweep reads Files: with the same
  reader (fieldPaths); the validator hands its parsed fields over.
- plan-validator --steps-from asks for Verify: on a 1.8 plan too.
- skill frontmatter: a value starting with # is a hazard; a quote after an
  escaped backslash closes the value. Routing reads kind tags with hasOwn.
- release-check reads scope_sha_end as written (an all-digit sha keeps its
  leading zero), and Voyage's own artifacts under .claude/projects/ and
  .claude/voyage/ committed after the review do not count as unreviewed.

Suite 2170 (2168/0/2).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 23:25:24 +02:00
ed87cc668d
fix: round 2 of the release review of 6.3.0
Round 2 (v6.2.0..0d044f6, BLOCK: 2 BLOCKER, 11 MAJOR, 1 MINOR), each fixed
behind a test that failed first.

- The git runner checks only words /bin/sh passes through unchanged (no
  quote, backslash, $, glob or brace) and refuses --output and its
  abbreviations: round 1's --output refusal was bypassed by quoting.
- fieldPaths: backticked paths are kept as written, parentheses and all; in
  plain text every path-like word counts, and a parenthesised note does not.
- plan-validator --steps-from reads the plan's ## Verification for an
  appended End-to-end step, and warns instead of failing under --soft.
- regression-check prints progress_status, the value progress.json takes;
  /trekexecute copies it.
- release-check: a plugin in a subdirectory is checked in its own directory,
  the suite is not run when a cheaper check already makes the answer exit 2,
  and a bad argument or a crash is exit 2.
- Skill routing looks a skill up among skills only, and builds the corpus
  vectors once.
- /trekexecute Phase 7.2 says plainly that remediation steps in the review
  template's own form stop with a re-plan; making them runnable is a later
  order (operator 2026-10-10).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 22:43:38 +02:00
bef9c5b3ac
fix: the findings of the release review of 6.3.0
The review of v6.2.0..f669b87 (BLOCK: 1 BLOCKER, 12 MAJOR, 1 MINOR), each
fixed behind a test that failed first, or, for the two missing tests, a test
shown to fail on a stub of the branch it covers.

- Review steps appended by /trekexecute Phase 7.2 are held to the step rules
  on any plan version: plan-validator --steps-from <N> (on a plan below 1.8 a
  template review step validated and was executed).
- The guard refuses where no one can be asked also when its rules will not
  load; the wave merge path names that refusal instead of MERGE_REFUSED.
  Tests for the classifier-error refusal and post-approval-log's own check.
- release-check: the version files may change only in their version after
  the review (JSON compared without it), README diff lines are read inside
  hunks only, an unreadable diff is exit 2, and npm test runs without
  NODE_TEST_CONTEXT.
- What counts as a step of only tests: a note in parentheses is not a path,
  and a data file under specs/ is not a test. End-to-end: rides on the last
  step that builds behaviour (validator hint, trekplan, template).
- A removed line is cited as <rev>:<path>:<line> (findings-schema hint,
  trekreview re-ask).
- skill-lint counts a trailing newline as no line; regression-check takes
  commandEnv from lib/util/command-env.mjs; CLAUDE.md names four mode-read
  exemptions.
- /security-review, older than v6.2.0: the criteria runner refuses git
  --output, which writes a file.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 22:12:12 +02:00
33b58f460a
fix: the fix round before 6.3.0 (order 10)
1. A step of only tests can never be proven red. One reading,
   stepTestsOnly (lib/parsers/plan-schema.mjs, test paths from the new
   lib/util/test-path.mjs): the plan validator warns PLAN_STEP_TESTS_ONLY,
   red-proof --plan/--step adds tests_only to a not-red-at-base, and
   /trekexecute and the step helper send such a step straight up to the
   plan instead of into fix rounds that cannot succeed. /trekplan, the plan
   template and plan-critic (dimension 8, still 12) say the test belongs in
   the step that builds the behaviour.
2. Timing tests under load: the hook helper's kill limit is 30 s and per
   call overridable; SC #14 passes on the fastest of up to three runs
   against the same 800 ms limit (tests/helpers/timing.mjs).
3. The example plan's On failure lines open with a K11 word.
4. /trekreview saves the reviewer's whole answer for the findings check and
   names FINDING_PROSE_LINE_OUT_OF_RANGE (error: re-ask; warning: report).
5. The criteria runner's commands run without NODE_TEST_CONTEXT
   (commandEnv, moved to lib/util/command-env.mjs).
6. The resolver returns effort only when the brief's phase signal sets one;
   the four commands said it always did.

Also: the K2 hook tests used fixed session ids in a per-user temp dir, so
two suites running at once took each other's approval records; the ids are
now unique per run.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 22:16:12 +02:00
3c18fdb5f7
merge: main (7a skills workshop, 9 rettepakke, 7b researching-sources, 8 release runbook) into wave2-kobling
Union lines resolved: CLAUDE.md command table keeps main's /trekresearch
and /trekplan rows and this branch's /trekexecute row. README's
architecture block now counts the three skills main ships (it said 2
after 7b added researching-sources).

Contracts run against the real ones on the merged tree: K10/K11 (plan
validator refuses a piped Regression:, warns on an unknown On failure:;
regression-check passes/fails/absent/unrunnable), S2 (skills/test-first
and skills/debugging exist, voyage:<name> form as 7a chose), K7 (real
review_version 1.1 WARN -> 0, a BLOCK copy -> 1, a 1.0 review with no
verdict -> 2). npm test: 2102 / 2100 pass / 0 fail / 2 skipped.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 21:25:18 +02:00
920fbd3c47
feat(trekexecute): couple the executor to the review gate, the plan approval and the step checks
Wave 2, order 6. /trekexecute now:
- refuses a plan whose logged approval does not cover its current sha256
  (K2, approval-log verify --kind plan), before step 1;
- runs the step check (K9) and the step's optional Regression: (K10, new
  lib/verification/regression-check.mjs through the criteria runner) at step
  end, before the checkpoint; exit 2 is "not measured", never green;
- runs the architecture rules (K5) and the plan-file sweep (K6) after the last
  step; a violation or a file outside the plan turns completed into partial;
- reviews by itself in the closing run (Phase 7.2): run the thing, /simplify,
  /trekreview, verdict-gate; a BLOCK adds the review's remediation steps after
  the plan validator accepts them and the operator re-approves the plan, capped
  at TREKEXECUTE_MAX_REVIEW_ROUNDS (3);
- makes the main-merge gate a lock on the verdict: BLOCK or undecided keeps
  the merge closed; when open, the executor merges and the guard's question is
  the one question (operator decision 2026-10-08). The --gates pause before
  the wave merge-back is gone for the same reason.

The guard refuses a merge into main and a push in the permission mode that
shows no prompts, since no one can be asked (operator decision 2026-10-09; two
mode-read exemptions approved by the operator).

progress.json gains optional coupling fields (Handover 5); the validator
rejects the runner's exitCode in plan_verification.failed_criteria (C15).
Pointer lines name the skills test-first and debugging (S2).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 19:22:00 +02:00
6c1bf40014
merge: main (7a skills workshop) into wave2-rettepakke
Wave 2 merge order 7a -> 9: brings e589a02 into order 9's branch.
No conflicts. Full suite on the merged tree: 2043 (2041 pass / 0 fail /
2 skipped) = main's 2014 + this branch's 29.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 19:12:45 +02:00
255b6b4bf8
feat(trekplan): Regression and On failure step rules, and trial 2's minor fixes
The minor points (B8-B12, C13, C14, C16, C17) of the second voyage-lekerepo
trial (2026-10-08), each verified against the code and started with a test
that failed first.

- K10: optional step field `Regression:` - one command the criteria runner
  allows, unpiped; plan-validator refuses one that can never run
  (PLAN_STEP_REGRESSION_NOT_RUNNABLE). Any plan_version, no bump.
- K11: `On failure:` opens with revert | retry | skip | escalate, or the
  validator warns (PLAN_STEP_ON_FAILURE_UNKNOWN); onFailureAction in
  plan-schema.
- B8 (operator decision 2026-10-08): minors open after the last critic round
  are listed numbered in the Phase 10 summary; the ones the operator picks are
  fixed and get one more round (--extra-round when the 3 are spent).
- B11: plan-review dedup merges two reviewers' findings on the same file:line
  with the same content (trial pair: Jaccard 0.44, overlap 0.83); the Jaccard
  threshold for every other pair is unchanged.
- B12: /trekbrief Step 4c says the reviewer runs in the background and is
  waited for, not "foreground, blocking".
- C13: the Phase 4 size count includes .mjs, .cjs, .mts, .cts.
- C14: --evidence shows the first output line on PASS rows.
- C16: findings-schema checks path:line citations in finding prose (error) and
  in the prose around the block (warning) against the file.
- C17: git-historian gets the brief, never proposes changing a frozen file,
  and names the remote from `git remote -v`.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 21:42:21 +02:00
cc832fd430
feat(skills): skill workshop, test-first and debugging preloaded into the step helper
The workshop (ordre 7a, contracts S1 and S2): a form check
(lib/skills/skill-lint.mjs) that follows Claude Code's own skill fields,
and a model-free routing test (lib/skills/routing.mjs) over every skill,
the 7 commands and the 21 spawnable agents, reading the eval cases
themselves (evals/skill-*, 3 fire / 2 quiet / 1 effect, tagged with the
event they came from). Thresholds pinned, never lowered.

The two skills were written against failures measured first in helpers
without them: red only as an import crash, the whole suite run from a
hand-made file list instead of the repo's own command, and an
unreproduced fix shipped under authority pressure. step-implementer
preloads both through its skills: line; no tool list change.

Credits: addyosmani/agent-skills @9d0c60d, obra/superpowers @8ca22db,
mattpocock/skills @c55ee46 (MIT), Anthropic skill-creator (Apache-2.0).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 21:38:58 +02:00
b0d96a2d53
fix: close what an independent review found in the trial 2 fixes
- The pre-compact hook read only a checkpoint that started with `git commit`,
  so every plan in the new `git add … && git commit` form rebuilt nothing, and
  an empty match also skipped the session-state refresh. It now finds the
  commit anywhere in the span and always refreshes; first test for the hook.
- A sub-bullet that carries its own command stays a criterion (folding it
  left the command unrun); the shallowest bullet sets the base indent.
- Only a MINOR/SUGGESTION /code-review finding outside the range is released
  from forbidding ALLOW: a MAJOR one may be a break cited at an unchanged
  caller.
- `reuse` is an improvement category; the session-spec template stages too;
  a negated bash 3.2 constraint, an env prefix and `bash -c` are handled.
- Stale comment, Declined-to-Judge wording and rule-key counts brought in line.

Tests fail on 7c11c2a first (9 of 24).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 15:21:56 +02:00
7c11c2aa9f
fix: the second lekerepo trial's faults that made a result wrong or misleading
voyage-lekerepo trial 2 (2026-10-08), report section A; the operator decided
they are fixed before the next release:
- A1: a /code-review finding whose category is simplification, efficiency,
  style or readability enters as CODE_REVIEW_IMPROVEMENT (MINOR), not MAJOR.
- A2: recommended_action is the engine's own fix when transcribed, otherwise
  a test-first step; never the failure scenario dressed as a remedy.
- A3: a /code-review finding outside the exact range it was given is declined
  and listed, but no longer holds ALLOW back; /security-review's still does.
- A4: the manifest must_contain recipe uses grep -E -e ... -- so a pattern
  like --sep is not read as an option.
- A5: indented sub-points belong to their criterion (counted), and a
  criterion with sub-points and no command warns BRIEF_SC_SUBPOINTS.
- A6: a brief requiring bash 3.2 whose criterion runs plain bash warns
  BRIEF_SC_BASH_NOT_PINNED; /trekbrief proposes /bin/bash.
- A7: the plan template's and /trekplan's checkpoints stage the step's files.

Tests fail on 5f9faee first (tests/lib/trial2-fixes.test.mjs, 11 of 14).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 15:12:07 +02:00
5f9faeed4a
fix: close the six defects an independent review found in the trial fixes
Independent read-only review of c56f852..2d29966 (2026-10-08), each defect
reproduced by the reviewer; each new test fails on that code.

- test-lock green ran ANY allowlisted command: `green --cmd "git status"`
  marked a red step green and the stop guard let it stop. The lock now
  stores the step's test command (`lock --cmd`); `green` runs only that
  one (a different --cmd, or a lock without one, exits 2). trekexecute D1
  calls `green` with no command, which also removes the quoting hazard.
- plan-gate --accept-open worked at round 1 and passed the gate; it now
  refuses while rounds are left.
- findings-schema --repo-root swallowed a following flag, or took a root
  that does not exist, and silently skipped the line check: exit 2.
- brief-review-stamp hashed only the body, so a changed `framing` or
  `research_topics` stayed "current"; it now covers the reviewed
  frontmatter too (only the post-review stamps are left out).
- red-proof red_kind read an assertion message naming SyntaxError as a
  load error; the signatures are now specific.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 07:17:45 +02:00
2d29966f51
fix(plan): an open MAJOR stops the plan; after the last round the operator decides
voyage-lekerepo trial (2026-10-06) point 6, operator decision 2026-10-08
(«samme skala, og du spør»): the critics rated a non-discriminating test
minor in round 3, there was no way to fix it after the last round, it was
built, and /trekreview called the same weakness MAJOR (MISSING_TEST).

- plan-critic, scope-guardian: rate on the review catalogue's tiers; a test
  that cannot fail on a wrong implementation is major, never minor.
- plan-gate: an open MAJOR stops (PLAN_GATE_OPEN_MAJOR: revise and run the
  next round; PLAN_GATE_OPEN_MAJOR_FINAL after the last round: ask the
  operator). --accept-open records "build as is" after their yes, bound to
  the round and the plan hash; never for a blocker.
- trekplan Phase 9: REVISE after the last round asks fix now (one extra
  round) or build as is, instead of carrying the majors silently.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 07:07:00 +02:00
1b5218e8f4
fix(plan): every exploration agent runs; the brief is reviewed again only when it changed
voyage-lekerepo trial (2026-10-06) point 14, operator decision 2026-10-08
(«alle agenter, ny briefsjekk bare ved endring»):

- trekplan: the "Adaptive" hard rule (a 10-file project does not need 7
  agents) contradicted Phase 5 ("All agents run for all codebase sizes");
  it is gone, in line with quality before cost.
- brief-review-stamp.mjs: /trekbrief stamps the brief body when its
  brief-reviewer gate passes; /trekplan Phase 4b skips its own review only
  while the stamp is current. Stale (edited) or absent (another producer,
  or a gate that did not pass) reviews as before. Additive optional
  frontmatter fields, documented in Handover 1.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 07:01:44 +02:00
393b8e5a0a
fix(guards): a step whose test is seen green may stop while it waits for its controller
voyage-lekerepo trial (2026-10-06) point 7, operator decision 2026-10-08
(«grønt merke på låsen»): the stop guard blocked Stop three times while the
executor waited for the controller, with the step's test already green.

- test-lock.mjs green --cmd "<Verify>" runs the step's test command (same
  allowlist + denylist as done-line) and records green_at only on exit 0;
  pending clears it; a new lock starts without it.
- stop-test-lock lets a green-marked lock stop; the write guard still
  refuses the locked test files.
- trekexecute: D1 marks green after a PASS; each fix round marks pending.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 06:59:14 +02:00
81dc5af680
fix: the trial's mechanical faults -- approval label, import path, stats, annotate path, red kind
voyage-lekerepo end-to-end trial (2026-10-06), report points 8, 10, 12, 15, 16:

- approval-log: «Approve (Recommended)» / «Godkjenn (anbefalt)» is the
  approval it labels; the suffix never turns a hollow answer into a yes.
- trekexecute Phase 8: the state-file block imports atomic-write through
  ${CLAUDE_PLUGIN_ROOT}; a relative import only ran with cwd = plugin root
  (the test runs the block from another directory).
- trekreview, trekresearch, trekcontinue: stats go through stats-append like
  the other commands, and a failed write is reported, never skipped
  silently (closes the open STATE finding for all three). The schema
  fixture's stale line refs for these and trekplan are re-measured.
- annotate prints an absolute path, so file://{$ANNOT_HTML} is a live link.
- red-proof: `red_kind` = load-error | test-failure on a proven red.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 06:53:15 +02:00
609eb35015
fix(review): the review keeps the findings that are right
voyage-lekerepo end-to-end trial (2026-10-06), report points 1, 5, 11:

- engine-findings: recommended_action is "Fix <file:line> so this no longer
  happens: <failure scenario>", not "Resolve: <title>" (8 of 8 engine
  findings were set aside as actionability:empty); the coordinator never
  sets an engine finding aside for Actionability.
- findings-schema --repo-root: a cited line past the end of an existing
  file is FINDING_LINE_OUT_OF_RANGE, so Phase 5's bounded re-ask fixes it
  before the coordinator sees it. The reviewers' instruction said "the
  actual line number from the diff"; it now says the file's own line,
  never the patch's.
- fill-finding-ids.mjs: the coordinator (no shell) writes @@ID_<n>@@ and
  trekreview Phase 7 computes them over (file, line, rule_key); an
  unresolved placeholder or a wrong 40-hex id fails. The 4-field id with
  `title` the docs named is gone; the code always used three.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 06:48:13 +02:00
c56f852ab6
fix(validate): a check that can never run is caught when the brief or plan is written
voyage-lekerepo end-to-end trial (2026-10-06), report points 2, 3, 4, 9:
11 of 13 brief criteria were NOT RUN at review with no warning in /trekbrief;
a plan `git grep` criterion passed validator, gate and three critic rounds,
then felled the run in Phase 7; the End-to-end field and Phase 7's text
search never met; a prose Verify left the test command undefined.

- criteria-runner: runnableCheck() screens a declared check without running
  it (same allowlist; an npm run script is not looked up at write time);
  /bin/bash tests/<script> allowed; the plan report carries end_to_end,
  verified when a passed criterion runs a step's End-to-end command (the
  older text form still counts).
- plan-validator 1.8: PLAN_VERIFICATION_NOT_RUNNABLE,
  PLAN_STEP_VERIFY_NOT_RUNNABLE, PLAN_END_TO_END_NOT_RUNNABLE,
  PLAN_END_TO_END_NOT_VERIFIED (the gate inherits them).
- brief-validator: BRIEF_SC_NOT_RUNNABLE warning; /trekbrief offers a
  tests/ script; brief-reviewer no longer proposes unrunnable commands.
- trekexecute: Phase 7 copies end_to_end from the runner; Verify's test
  command is its first backticked span.

Measured on the trial's own brief and plan: 11 warnings (the 11 NOT RUN),
and the plan stops on V5 git grep and the unlisted End-to-end command.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 06:42:33 +02:00
ca6ee8779a
merge: wave 1 order 1 (executor) into main
CLAUDE.md command table: each row from its owner (trekplan from order 3,
trekexecute from order 1, trekreview from order 5).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 20:42:47 +02:00
47864f91b4
merge: wave 1 order 4 (guards) into main
CLAUDE.md: the review paragraph (order 5) and the guards paragraph
(order 4) are both kept (planned union line).

The launch gate went red on the merged tree: post-approval-log reads
the session's permission_mode, and its regression test feeds that value.
Both were untracked when the branch ran its suite, so the gate never saw
them there. Operator decision 2026-10-06: a counted exemption in a new
class (mode-read: 3 + 1 hits), and the binding-rule sentence in CLAUDE.md
names it. An extra hit in either file turns the gate red again (checked).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 20:41:21 +02:00
21c28df3bc
merge: wave 1 order 2 (intent) into main
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 20:37:12 +02:00
885d515c3b
merge: wave 1 order 3 (plan and design) into main
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 20:36:31 +02:00
44dcc779a9
fix(execute): the step loop survives an adversarial review
An independent review of abc3083 found 15 defects, the two worst verified
in scratch repos. Each fix started with a test that failed.

- Proof of red could be "proven" by the environment: a start point
  unpacked with git archive had no node_modules and no .git, so any test
  failed there. The start point is now a git clone --shared checked out at
  start_sha, gitignored top-level entries are linked in, and a control run
  (start point + the change) must pass, or the result is not-run.
- The Test first file was never committed (the template lists it apart
  from Files:) and leaked into the next step's diff. The step's scope is
  now Files: + test files, staged at the checkpoint.
- New files outside Files: were invisible to every check. Every untracked
  file is registered with --intent-to-add; a revert unregisters them.
- The floor guard paired renames (foo.test.js -> .bak read as clean) and
  missed skipIf and node's t.skip/t.todo; prose files no longer count as
  stubs.
- Phase 7.5 audited from the last step's start_sha; it now uses the run's
  session_start_sha.
- The done line is written after the checkpoint and checked with --commit.
- fix_rounds never passes 5; attempts are never reset; re-control keeps
  the spec/quality verdicts and earlier floor-guard rulings; the closed
  stop list maps every existing stop; failed vs stopped made consistent;
  the controller's effort is said, not assumed.

Tests: 1470 (1468 pass, 0 fail, 2 skipped).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 20:17:39 +02:00
f5ca220bc0
feat(plan): plan 1.8, the plan gate, the design part and the plan-side checks
Wave 1, order 3 (P3 plan mode as the start, P2 design as its own part, P9
plan side). Contracts K3-K6 for the later merges.

- plan_version 1.8 (1.7 plans stay valid): Test first on every step, one
  End-to-end ("run the thing") step, optional Interface in / Interface out /
  Review focus fields, a ceremony class in the header (absent =
  architectural), and for architectural plans a ## Design part: module map
  without cycles, architecture rules that name their enforcer and the step
  that proves them, a requirements check asked as keep / change.
- K3 lib/validators/plan-gate.mjs: the critic verdict is recorded INSIDE the
  plan (Claude Code's plan approval hands a hook only the plan file's text),
  bound to the hash taken before the reviewers read it; 0 go / 1 stop / 2
  could not run; at most 3 critic rounds, then stop and ask.
- K5 lib/verification/arch-rules.mjs: runs the target repo's own
  dependency-cruiser or import-linter (installs nothing; 2 = not measured,
  never green); --prove --rule shows pass -> fail on a planted violation of
  that rule -> pass. Verified against dependency-cruiser 18.5.0 and
  import-linter 2.15; madge 8.0.0 left out (missed a planted .mjs cycle).
- K6 lib/verification/plan-scope-sweep.mjs: changed files no step names.
- /trekplan Phases 8-10: design part, bounded critic loop, the gate before
  "execute", a plan-mode path through ExitPlanMode (not yet run end to end
  inside plan mode). plan-critic 10 -> 12 dimensions; scope-guardian checks
  the ceremony.
- Fixed on the way: plan-validator and plan-review-dedup used the
  file://argv[1] main guard (no-op under a symlink or a space); CRLF plans
  failed every manifest; the dedup dropped finding severity.

Borrowed, credited in place: obra/superpowers, Kiro (docs), addyosmani/
agent-skills, mattpocock/skills, GitHub Spec Kit, bashebr/ai-native-sdlc,
Boris Cherny's public threads.

Suite 1497 (1495 / 0 / 2), 86 new tests.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 20:10:57 +02:00
2ee8137e7c
feat(hooks): wave-1 guards -- approval ask, plan gate, test lock, post-edit check
Wave-1 order 4 (P7, P12, the P9 test lock, the P3 plan-approval guard).
All command hooks; none runs a model.

- P12: pre-bash-executor answers permissionDecision "ask" before merge
  into main, push, tag/publish and destructive git (holds in auto mode).
  post-approval-log writes exactly what the person was asked to the K2
  approval log: merge/push to main as `merge`, tag/publish as `release`,
  with a one-hour expiry; nothing when no person was asked.
- P3: pre-plan-gate runs the K3 plan gate on a Voyage plan leaving plan
  mode and sends a refused plan back; "not measured" asks, never passes.
- P9: lib/util/test-lock.mjs (K8). pre-write-executor refuses edits to
  locked test files; stop-test-lock refuses "done" for the locking
  session (stop_hook_active guarded).
- P7: post-edit-check runs the target repo's own formatter/linter per
  edit, only during a Voyage plan run or after opt-in
  (.claude/voyage-guards.json); lib/verification/step-check.mjs (K9) fails
  the step on findings; no tool reads "not measured", never green.
- STORM cap matcher also names `Agent` (the tool's name since 2.1.63).
- Mod precondition stated in README, SECURITY.md and every PreToolUse stop
  guard: Voyage's guards are deterministic only when no installed mod
  handles `tool.check`.

K2, K3 and K5 are stubbed in tests until orders 2 and 3 are merged.
Two independent review rounds; every finding has a regression test.
Suite 1600 (1598 pass / 0 fail / 2 skipped).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 20:09:32 +02:00
22e792ce19
fix(review): a review with a control that did not run stops a merge
Operator decision 2026-10-06. Before, a WARN that existed only because a
reviewer or engine never reported (e.g. /security-review without an origin
remote) mapped to verdict-gate exit 0, so a review nobody performed in full
was green. Now `missing-reviewer:` / `unattributable-payload` in the JSON
block's allow_blocked_by is exit 2 (could not decide, never green); a WARN
for a MAJOR or a set-aside finding still passes with its reasons. A 1.1
review must carry allow_blocked_by.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 20:06:29 +02:00
40f6ae1177
fix(review): close the gate's fail-open paths an independent review found
An adversarial read of d88245c reproduced 15 problems; all fixed here, each
with a test that fails on the old code.

- verdict-gate: a greener verdict must be backed by the LAST fence being a
  `json` block of the right shape, with no BLOCKER in the JSON (any case),
  in `## Findings (BLOCKER)`, or a differing finding-id list; two verdict
  lines and more than one file argument are exit 2. ({}, null, lowercase
  "blocker", a trailing ```jsonc and a later json fence all gave exit 0.)
- engine-findings: a transcribed "narrower" key can no longer lower an
  engine tier; absolute paths under --repo-root match the scope; "12" lines
  parse; an empty scope is an error; out-of-scope engine findings are
  unverified (`engine:out-of-scope`) and forbid ALLOW.
- recurrence: the catch-all engine keys and keys normalised from unknown
  ones are never proposed; the same unfixed finding in two iterations is not
  a recurrence; proposals are validated before they are offered; \r/U+2028
  and damaged markers are refused; writes go through a symlinked CLAUDE.md.
  Prose points --repo at the session directory, not the git toplevel.
- Workflow substrate: engines are counted from what arrived, and the
  verdict's floor is recomputed from the coordinator's findings; now tested
  by running the script with stubbed Workflow globals. Two literal NUL bytes
  written as \u0000 (git saw the file as binary).
- Trimming keeps Pass 1's "Also flagged by" provenance; `## Declined to
  Judge` and remediation steps are required from review_version 1.1 only
  (N-1); the zero-diff review now carries the JSON block the gate needs.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 20:03:16 +02:00
abc3083c1e
feat(execute): one fresh helper per step, a controller on the diff, proof by command
/trekexecute no longer builds steps itself. Each plan step is built by one
fresh helper (new agent step-implementer: opus, effort high, no Agent tool)
and judged by one controller (a general helper on opus) that reads the
diff from a recorded start_sha and gives two verdicts, spec and quality.
Fix rounds go up, maximum 5: three fixes by a fresh helper, then back to
the plan, then to the operator. No cheaper-model ladder.

Proof is a command, never the model's word:
- lib/verification/red-proof.mjs: the step's test must fail at the start
  point and pass at the result (exit 0/1/2; 2 is never green). Reproduces
  the 02243c6 red-first measurement (6 of 55) through the shim fixture.
- lib/verification/test-integrity.mjs: the floor guard on the diff
  (removed asserts, skipped/deleted tests, muted checks, stubs, loosened
  thresholds). Over the last 150 commits: 149 clean, 1 real finding.
- lib/verification/done-line.mjs: DONE step N only when the test command
  exits 0.

Test first is required from plan_version 1.8. The test lock (K8) is used
through its CLI and reported as not-locked while it is missing. A run
stops only on a closed list of four classes; every other call goes into a
decision log with its cost if wrong. Without a passing run-the-thing
criterion the result is not verified end to end, never green.

Handover 5 gains optional per-step start_sha, report_path, red_proof,
test_lock, fix_rounds (0-5) and run-level decisions and end_to_end; old
progress files still validate and resume.

No isolation on the helper: measured, a worktree-isolated subagent
branches from the default branch (02f320f), not the executor's HEAD
(2c89a6b), so it would miss the earlier steps.

Borrowings credited in commands/trekexecute.md ## Credits (Superpowers,
ai-native-sdlc, Kiro, GitHub Spec Kit, agent-skills, Cherny).

Tests: 1411 -> 1457 (1455 pass, 0 fail, 2 skipped).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 19:58:18 +02:00
d88245c06e
feat(review): the review is a gate - verdict in the file, CC engine, project memory
Ordre 5 (wave 1, P11 + P5), review_version 1.1.

- K7: `verdict: ALLOW | WARN | BLOCK` is required in review.md (strict
  error, soft warning for 1.0 reviews). New CLI lib/review/verdict-gate.mjs:
  0 = ALLOW/WARN, 1 = BLOCK, 2 = could not decide (never green); a verdict
  greener than the file's own BLOCKERs or JSON block is exit 2. Realpath
  main guard (the old file:// guard exits 0 under a symlink - measured).
- No finding is struck for length: succinctness trims only MINOR/SUGGESTION
  text (catalogue tier), keeps BLOCKER/MAJOR whole, counts trims; the
  coordinator lists what it declined to judge.
- Claude Code's /code-review and /security-review run as the engine via the
  Skill tool (never --fix/--comment/--post/ultra); lib/review/engine-findings.mjs
  turns their findings into a reviewer payload; two catalogue keys
  (CODE_REVIEW_DEFECT, SECURITY_REVIEW_VULNERABILITY), catalogue 12 -> 14.
  An engine that did not run forbids ALLOW.
- Every BLOCKER is written as a numbered `### Step R<n>` with its source
  finding (strict error REVIEW_MISSING_REMEDIATION_STEP).
- P5: lib/review/recurrence.mjs - a finding class in two review.md files
  (current + git history, no new store) becomes one proposal, routed by the
  catalogue's memory_route; written only between Voyage markers in
  .claude/rules/voyage-review-lessons.md under a size budget, CLAUDE.md gets
  a pointer only; the operator approves every line (Phase 8.7).
- Workflow substrate: catalogue enum in step; a missing reviewer or engine
  forbids ALLOW there too (it returned ALLOW on zero findings before).
- Fixtures review-run-A/B said WARN over a BLOCKER; now BLOCK.

Borrowed and credited in code: Superpowers (declined-to-judge), ai-native-sdlc
(cap only nits; mistake/fix/check), Spec Kit (managed block; converge steps),
Pocock (retro routing), Kiro (verdict file + gate; evidence per lesson),
Cherny (engine -> brief control order; review -> memory; budget).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 19:45:52 +02:00
5244d2e8e8
feat(brief): ceremony by size, one question round, logged and committed approvals
P1 (order 2, wave 1). /trekbrief puts the task in a size class
(ceremony: small|bounded|architectural, K1; heaviest in doubt, said
aloud, overridable, only moved up) that sets the question budget and the
review cap, and asks one round of questions: facts looked up, never
asked; recommendation first; ranked by impact x uncertainty with a
visible Deferred list; stop when the next three answers can be predicted.
"høres bra ut", "gjør som du vil" and an empty answer are not approval.

K2: lib/util/approval-log.mjs, an append-only hash-chained log in the
target repo (.claude/voyage/approvals.jsonl) bound to the approved
content's sha256; append/verify (0/1/2), answer, digest. Committed by
lib/util/artifact-commit.mjs: the log always, the brief and plan only
with artifact_store: git (operator decision 2026-10-06). /trekplan
Phase 1 halts on a broken, diverged, missing or mismatched log entry;
Phase 11 logs and commits an explicit plan approval before any handoff.

Both new brief fields are optional: no brief_version bump. The
main-module guard in intent-approval.mjs and brief-validator.mjs now
compares real paths. Borrowings credited in the prose and module headers.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 19:44:42 +02:00
cb68c4f125
fix(execute): the Phase 8 payload goes on stdin; /trekreview findings closed
/trekreview of 5680591..84a0621 (verdict WARN: 0 BLOCKER, 3 MAJOR, 1 MINOR,
1 MAJOR suppressed as unverified for length only). All closed red -> green:

- Suppressed MAJOR 1d0171a7 (verified live): Phase 8 spliced {plan-path}
  into a single-quoted --payload. A lone quote broke the shell parse (event
  lost, no written:false to report); a quoted pair ran a command
  substitution and still reported written:true. event-emit now reads
  `--payload -` from stdin and the three Phase 8 blocks pass the payload
  through a quoted heredoc. Checked under bash and zsh.
- 570ba19b: the SC5 set-step extractor read line by line and never saw the
  wrapped Step 0 sentinel (`blocked`); it now matches across the break and
  the test asserts `blocked` is read.
- c69a865a: the Phase 9 line_ref in jsonl-schemas.md was 9 lines off. Both
  trekexecute rows are now pinned to the exact span by a test.
- 0004fa23 (MINOR): the gates_mode_flag_override block says what to do on
  written:false (print the reason, continue).
- emit() docstring no longer says failures are swallowed silently.
- 7ffaede5: chosen to KEEP the prose-only legacy `passed` tolerance, because
  a public-plugin run started under the 6.1.0 prose would otherwise re-run
  every finished step on resume; recorded as an accepted deviation in the
  (local-only) brief. No code change.

Suite 1400 (1398/0/2), was 1393.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 18:16:46 +02:00
27d586841a
fix(stats): event-emit lands without the env var and reports every failure
event-emit returned {written:false, reason:'CLAUDE_PLUGIN_DATA unset'} whenever the harness did not export the variable - the normal case for the Bash tool - so /trekexecute's Phase 8 events never landed. It now resolves the directory through stats-append's resolveStatsDir (one resolver; opts.path still wins, so intent-approval is unchanged). The CLI uses the realpath isMain() guard (the file:// guard was a silent no-op under a symlink or a path with a space) and exits 1 on every written:false - usage error, payload-not-json, failed write - instead of always 0. KNOWN_EVENTS gains main-merge-approved, main-merge-declined and gates_mode_flag_override, which /trekexecute emits by design. Header, intent-approval docstring (comment only), docs/operations.md and the README autonomy sentence (wrong state names, 'records each transition') updated.

Red: 10 of 20 tests fail on the pre-fix code - 7 new (CLI lands with CLAUDE_PLUGIN_DATA empty / absent, unwritable target exit 1, usage error exit 1, symlink, space path, known events) and 3 inverted contracts. Regression guards (green on arrival): never throws when unwritable; no second copy of the fallback directory name.

Inverted (the contract this changes, not deleted): emit with no CLAUDE_PLUGIN_DATA (silent skip) -> lands under a pinned HOME; never throws when unwritable -> a genuinely unwritable target (env {} now resolves to the real home); resolveStatsPath({}) === null -> the fallback path; malformed --payload exit 0 -> exit 1.

Readers checked: otel-export keys on 'event', yardstick counts only user_input, cache-analyzer and research-loop-cap name event-emit only in comments. Verify 268/268 (stats-event-emit, intent-approval, doc-consistency, otel-export-validators, yardstick). Suite 1376 (1374/0/2); non-hook lines in the real trekexecute-stats.jsonl 60 before and after.

Voyage order 20261005T104513Z-1250514346, plan step 2/5.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 17:35:11 +02:00
8a56187341
fix(validators): the progress validator knows stopped and blocked
/trekexecute writes run status stopped (dirty-tree stop, entry-condition stop, escalation) and step status blocked (Step 0 sandbox sentinel); the validator rejected the first and warned on the second. Both are real states lib/util/session-orders.mjs already reads (ENDED_BAD), so the validator learns them. The step-status list is exported as PROGRESS_STEP_STATUSES (was an inline literal) so tests check prose against it instead of keeping a copy. docs/HANDOVER-CONTRACTS.md Handover 5 rows updated.

Red: 3 of 4 new tests fail on the pre-fix code (stopped run status, PROGRESS_STEP_STATUSES export, blocked step status). Regression guard (green on arrival): every run status but completed stays resumable.
progress-validator 16/16. Suite 1368 (1366/0/2).

Voyage order 20261005T104513Z-1250514346, plan step 1/5.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 17:32:54 +02:00
3f073b7bd7
fix(docs): the order fields stand on all five surfaces (green)
/trekbrief Phase 7 says the writer adds order_id / order_claimed_at /
order_reason (never typed by the model) and that the yardstick joins use on
order_id; the fixture row lists them in `fields`, EXPORT_DENYLIST names them,
and its stale line_ref (657-672) now reads 961-976; the allowlist header
names them as dropped; docs/architecture.md Stats explains them.

/trekbrief --approve now runs Phase 7 after a successful stamp, with fixed
values (mode "approve", 0 turns, brief_quality/research_topics/auto_research
from the brief's frontmatter, auto_result "manual", intent_approved true).
Valgt fordi PM 04.10 (point 3): fix the code, not the criterion - the
approval must leave the trekbrief record. Measured hole: okf-wiki v1-k has
brief-approved 04.10 17:12Z and trekplan 17:29Z, but only a 03.10 trekbrief
record with intent_approved false. CLAUDE.md, README.md and
docs/command-modes.md say so. The manual path is unchanged.

npm test 1309 -> 1362 (1360 pass / 0 fail / 2 skip).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-04 19:55:17 +02:00
43e6a2b23a
fix(stats): a trekbrief record carries the order Voyage runs, written by the writer (green)
appendStatsRecord(kind, record, env, { cwd }): for kind trekbrief it drops
every order_* key the record came with and adds attributeOrder()'s three
keys (lib/stats/claimed-order.mjs), resolving the mailbox from the record's
project_dir when that lies inside cwd. Other kinds are written untouched.

The CLI guard compares real paths (realpathSync on argv[1] and on
import.meta.url). The old `import.meta.url === file://${argv[1]}` was a
silent no-op - exit 0, nothing written - under a symlink and under a path
with a space (measured 04.10). Valgt realpath fordi `resolve()` alone fixes
only the space.

stats-landing 15/15; intent-approval, claimed-order, proevesett green.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-04 19:50:32 +02:00
2337d7f2ac
feat(stats): the recorder finds the one claimed order Voyage runs (green) [skip-docs]
lib/stats/claimed-order.mjs reads <coord>/<mailbox>/orders/claimed/ the way
repo-mailbox's claim verb writes it (read, never called): the stem is the id,
the .claim sidecar gives claimed-at, every .md counts toward "several".
Mailboxes come from two independent git calls (toplevel basename, the claim
script's rule; and the main repo behind a linked worktree), with GIT_DIR /
GIT_WORK_TREE dropped and a 5 s timeout. A project_dir outside cwd cannot
steer the lookup. Never throws, never guesses, starts nothing.

Valgt: identity = file stem, not frontmatter, fordi the claim script moves
<id>.md and never reads the frontmatter; a quoted order-id would otherwise
never join.

claimed-order.test.mjs 20/20.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-04 19:49:11 +02:00
d70e3d2af7
fix(execute): clear the wave record only on the main-merge gate's confirm (green)
1. Step 6 cleared the orders dir before Phase 8's main-merge gate asked,
   so a declined gate lost the merged-waves record and the next run
   prepared wave 1 again on merged code. The clear now sits only under
   the gate's "On confirm" (wave path, next-wave none, Step 4 passed);
   Step 6 and a declined gate keep the record, so a re-run goes
   next-wave none -> Step 4 -> back to the gate.
2. The gate's Decline row and Recovery surface now say what holds on the
   wave path: the waves are already merged on the current branch,
   nothing is finalized, the record is kept, and re-running the same
   command (not --resume, which Phase 2.5 runs as a single session)
   re-runs master verification and returns to the gate. The branch name
   is trek/{slug}/session-N; the push-before-cleanup note now holds only
   where the push succeeded. The single-session --resume line stays.
3. The report footer adds the multi-session way to continue.
4. wave.json stores the branch the wave was prepared on (write
   --branch); Step 3's status call passes the current branch and stops,
   touching nothing, when the main checkout is on another branch.

npm test: 1277 tests, 1275 pass, 0 fail, 2 skipped.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-02 16:24:33 +02:00
a915b9d4b0
fix(execute): the multi-session path never force-deletes (green)
One invariant closes the data-loss class: Phase 2.55, 2.6 and 7.6 remove
worktrees only with `git worktree remove` without force and branches only
with `git branch -d`. Whatever git refuses (a worktree with changes, an
unmerged or checked-out branch) is kept, reported with what the user can
do, and never retried with force; every unmerged trek/{slug}/* branch
survives every failure path. Step 1 stops on a branch or worktree left
by an earlier attempt instead of deleting it. After a merged wave, a
progress file is dropped from its worktree only when untracked and
byte-identical to its archived copy, so the happy path still cleans up.

B1: Step 3 refuses to merge into a dirty main checkout, and tells a
refused merge (no MERGE_HEAD: stop, keep wave.json) from a real conflict
(abort, Step 5 keeps the branches).
B2: Phase 2.5, Check 4 and Step 0 take the main checkout from the first
`git worktree list` entry and refuse to run from a linked worktree.
B3: wave.json and merged-waves.json carry the plan's sha256 and refuse
another plan or version, naming the run that holds the orders dir and
the clear command; Step 0 stops on that. Step 6 clears the orders dir
when every wave is merged AND Step 4 passed, no longer keyed on the
Phase 8 label the wave path cannot reach.
Also: every session-orders.mjs call runs from the main checkout with a
main-relative plan path; Check 1 no longer counts .claude/trekplan-sessions/
as a dirty tree (it blocked every re-run after a failed wave); a stuck
wave has a documented non-force way out; Hard rule 12 states the
invariant. The test file only narrows one call-site filter that also
matched Step 0's plugin-root existence check.

npm test: 1273 tests, 1271 pass, 0 fail, 2 skipped.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-02 16:18:33 +02:00
dbc07b4006
fix(execute): never tear down a running or merged wave; keep progress past cleanup (green)
Seven defects from an independent review of the 6.0 session-order flow,
all verified against the text before fixing:

1. Step 3 branched only on pending/failed/stopped/unreadable, so a session
   still writing in-progress (or in_progress) next to a failed one had its
   live worktree force-removed. status now classifies each session as
   completed, running (no file, pending, in-progress, in_progress, or any
   unknown status) or ended-bad (failed, stopped, partial, blocked,
   unreadable), keeping the raw status; Step 3 stops on any running FIRST
   and touches no worktree, branch or wave.json.
2. The Phase 2.5 wave-in-flight guard was cwd-relative; from a subdirectory
   it missed wave.json and Check 4 force-removed the wave. The guard is now
   anchored at the git toplevel, and Check 4 opens with a block that refuses
   to clean while wave.json exists.
3. Step 6 read progress files from worktrees that Step 3/5 had removed. A
   new archive subcommand copies each to orders/wave-W-session-N.progress.json
   before any worktree goes; Step 6 and Phase 8 read the copies.
4. NO_WAVE always prepared the lowest wave, so a re-run after a wave-2
   failure re-ran wave 1. record-merged writes orders/merged-waves.json
   after each merged wave (Step 5 keeps it); next-wave returns the lowest
   unmerged wave or none (then Step 4). Phase 8 clears the orders dir only
   after a completed report; the record refuses another plan's path.
5. Phase 7.6 named a deleted worktree and promised an unwired re-run. The
   order now names the main checkout and says the recovery session's own
   audit is the check.
6. (test side, previous commit) progress paths are asserted literally.
7. Hard rule 12 now carries the awaiting-sessions exception.

npm test: 1262 tests, 1260 pass, 0 fail, 2 skipped.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-02 12:09:12 +02:00
219e40cd91
feat(execute)!: hand waves over as session orders, never start Claude Code (green)
Operator decision 27.09.2026: Voyage works the PM way, so nothing in it
starts Claude Code. Work that needs another session becomes an order plus
a starter line the user gives a session they open themselves; Voyage
never starts the session.

/trekexecute's multi-session path (Phase 2.6) now prepares one wave at a
time: worktree per session, then lib/util/session-orders.mjs writes one
order per session (worktree, steps, done-condition, starter) plus
orders/wave.json, and the run stops. Running the same command again reads
each session's progress file (status mode), merges sequentially with
push-before-cleanup as before, and prepares the next wave. Phase 2.5 skips
the destructive pre-flight while a wave is in flight. Phase 7.6 recovery is
handed over the same way. Hard rule 21: never start Claude Code.

Removed with it, because they existed only for launched children: the
ANTHROPIC_API_KEY billing check (and its dry-run line and Hard rule 1
exception), the hooks-fire version precheck, the safety preamble, the
scoped-tool/turn/budget flags, templates/headless-launch-template.md, the
decomposer's launch.sh (now orders.md), /trekplan's "launch", the README
billing and MCP tuning sections, and scripts/q3-cache-prefix-experiment.mjs
(an experiment that spawned the binary; its results stay in docs/).
/trekresearch's deep-research pre-gate no longer runs the binary for its
version; the post-hoc check was already the authoritative guard.

Chose orders + starters over in-session subagents because the order's done
criterion asks for exactly that, and because /trekexecute disallows the
Agent tool on purpose (Hard rule 10); reopening that is a separate change.

Gate: 54 -> 0 hit lines outside EXEMPT. npm test 1250 (1245 pass, 0 fail,
5 skipped: 3 are the retired-reference scan without its local list).
verify.sh 7/0. The fixture run (tests/lib/session-orders.test.mjs) writes
two orders and wave.json for wave 1 and leaves a trap binary untouched.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-27 15:35:22 +02:00
3892a835dd
test(proevesett): a case for the intent gate; case 5's error comes from code; graders see what they claim
New case plan-halts-without-intent-approval (expectation committed before
its first run): a 2.1 brief WITH phase_signals and no intent marker.
Graders: intent-approval.mjs --check ran; the trace carries the gate's own
JSON code for BRIEF_INTENT_NOT_APPROVED; no Agent; no plan.md.

review-requires-project: the arg parser now has a CLI that checks the
required flag and prints 'Error: --project <dir> is required.' + usage
(exit 1, code ARG_REQUIRED_MISSING). trekreview.md runs it with
$ARGUMENTS (it passed "$@", which the Bash tool never has, so the parser
never ran — 0 Bash calls in the PM's case-5 traces) and relays its stderr
instead of composing the line. The grader project-required (reply regex,
unstable on backticks) is replaced by parser-ran + names-missing-project
(trace, the parser's JSON code), the same form as names-rule.

Graders: no-error-code is bound to the validator's JSON output form and
covers every REVIEW_* code (WRONG_TYPE and VERSION_FORMAT were missing);
says-pass/says-fail reject a preceding NOT and a longer word; every case
with no-write also gets no-bash-write (redirect, tee, touch, cp, mv, rm,
sed -i in the Bash command). Checked on the PM's 10 recorded traces: no
false positive; known-positive/negative still split.

Red 348aa95 6/7 → green 7/7. Suite 1231: 1229 pass / 0 fail / 2 skip.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-23 09:28:38 +02:00