Commit graph

17 commits

Author SHA1 Message Date
ed6699da58
refactor(simplify): one source per rule, shared test helpers, a faster isolation test [skip-docs]
/simplify over a97efb6..HEAD (the plan_version 1.9 / trial-4 delivery).

- coordinator-contract: engine names come from engine-findings ENGINES;
  one markedMajorCodeReview predicate under both lowering checks;
  isEngineFinding everywhere; the unreachable branch (c) of
  illegalBriefLowering folded into (e).
- armB workflow: RULE_KEYS = Object.keys(RULE_TIERS); the engine map is a
  literal pinned equal to ENGINES by the workflow test.
- plan-schema: usesFilesGrammar() is the one 1.9 check (validator, sweep,
  testFirstFiles, stepTestsOnlyFromFields); opensEntry built on opensChunk.
- plan-validator: one issue builder for the Files and Test first grammar.
- plan-scope-sweep: the 1.9 and the 6.2.0 reader are one if/else.
- artifact-commit: TRAILER_RE/trailerProblem no longer exported (no
  importer); the order comment says the CLI finds the repo root first.
- tests: the lock drivers in session-id-isolation (d) run side by side per
  mode (~100 s -> ~30 s); a shared artifact-repo helper; severityRank and
  extractFindingsBlock reused; childEnv(env) without a spread; one copy of
  the PLAN_VERSION_CURRENT check.

Plan readers: validator errors/warnings, plannedPaths, fieldPaths,
testFirstFiles and stepTestsOnlyFromFields compared byte for byte against
HEAD over 510 plans / 1692 steps plus 210 synthetic 1.7-1.9 cases: same.
Suite 2384 (2382/0/2).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 21:06:47 +02:00
3009c5eddb
fix(plan): a 1.9 Test first names its test only on a line that opens with File:
The step check read File: anywhere on the Test first lines, so a 1.9 plan whose only File: stood mid-line validated while the executor, K6 and the red proof read no test file. From 1.9 checkSteps reads the test the way testFirstFiles does; below 1.9 it reads as before (decision 16). Found by the step 5 controller in /trekexecute --session 2; fixed on the operator's decision.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 17:44:23 +02:00
fc157c3ad5
feat(plan): the Test first File line follows the 1.9 grammar [skip-docs]
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 16:18:53 +02:00
3e1a811c60
feat(plan): read Files by the 1.9 grammar, warn on unticked paths below it [skip-docs]
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 16:09:25 +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
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
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
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
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
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
3683ae0070 chore(voyage): release v5.0.0 — remove bespoke playground + /trekrevise + Handover 8; render produced artifacts to HTML + link, annotate via /playground
The v4.2/v4.3 bespoke playground SPA (~388 KB), the /trekrevise command,
Handover 8 (annotation → revision), the supporting lib/ modules
(anchor-parser, annotation-digest, markdown-write, revision-guard), the
Playwright e2e suite, and the @playwright/test / @axe-core/playwright
devDeps are removed. A browser walkthrough found the playground borderline
unusable, and it duplicated the official /playground plugin's
document-critique / diff-review templates.

In their place: scripts/render-artifact.mjs — a small, zero-dependency
renderer that turns a brief/plan/review .md into a self-contained,
design-system-styled, zero-network .html (frontmatter folded into a
<details> block). /trekbrief, /trekplan, and /trekreview call it on their
last step and print the file:// link; to annotate, run /playground
(document-critique) on the .md and paste the generated prompt back.

Resolves the v4.3.1-deferred findings as moot (their target files are
deleted). npm test green: 509 tests, 507 pass, 0 fail, 2 skipped.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-12 14:05:07 +02:00
cc7228ea17 feat(voyage): add markdown-write.mjs + revision-guard.mjs + forward-compat policy comments — v4.2 Step 1
- lib/util/markdown-write.mjs: serializeFrontmatter (subset matches frontmatter.mjs parser), atomicWriteMarkdown (single tmp+rename, body bytes verbatim), readAndUpdate (read+mutate+write).
- lib/util/revision-guard.mjs: revisionGuard(path, mutator, validator) — backup -> mutate -> validate -> restore-on-fail. Extracted from /trekrevise prompt so rollback can be unit-tested.
- 12 tests for markdown-write, including 6-key source_annotations round-trip + walk-all-fixtures regression.
- 6 tests for revision-guard: applied/rolled-back/mutator-failed/sha256 stability/pre-existing-bak abort.
- Forward-compat policy comments in 3 validators (brief/plan/review) — non-functional pin against future strict-key refactors.

Pass: 508/510 (was 490; +18 net from v4.2 Step 1, 2 skipped Docker)
2026-05-09 12:48:40 +02:00
a1f256d000 feat(voyage): emit MANIFEST_PROFILE_DRIFT warning in plan-validator strict mode — brief assumption 7
Step 20 of v4.1 — implements drift detection in plan-validator.mjs per
brief Assumptions block 7: "Mismatch (e.g. korrupt manuell endring)
emitterer MANIFEST_PROFILE_DRIFT-warning fra plan-validator i --strict-modus."

Logic (after validateAllManifests in validatePlanContent):
  1. Strict-mode only — soft mode never emits drift warnings.
  2. Plan frontmatter must declare 'profile: <name>' to establish baseline.
  3. For each step manifest, if profile_used is set AND differs from plan
     profile, emit warning (NOT error) with code MANIFEST_PROFILE_DRIFT
     and location 'step N: profile_used = X, plan profile = Y'.

Forward-compat preserved: drift is a warning, plan remains valid:true.
Operators see the drift in --strict mode without parsing breaking.

New files:
  tests/validators/plan-validator-profile-drift.test.mjs — 4 tests
  tests/fixtures/plan-profile-drift.md                   — drift fixture

Tests verify:
  1. drift detected in strict mode → MANIFEST_PROFILE_DRIFT in warnings
  2. drift NOT detected in soft mode → strict gate honored
  3. matching profile → no drift warning
  4. no plan-level profile → drift detection silent (no baseline)

Tests: 479 pass + 2 skipped (Docker not installed).
2026-05-09 10:02:53 +02:00
Kjell Tore Guttormsen
f68cd950dd feat(ultraplan-local): Spor 1 wave 2 — 5 validators + doc-consistency, 108 tests grønn [skip-docs]
5 nye validator-moduler (alle m/ CLI-shim for invokering fra commands):
- brief-validator.mjs — frontmatter (type, brief_version, task, slug, research_topics, research_status), state machine (research_topics > 0 + skipped requires brief_quality: partial), body sections (Intent/Goal/Success Criteria)
- research-validator.mjs — type=ultraresearch-brief, confidence ∈ [0,1], dimensions ≥ 1, body sections, --dir mode for batch validering
- plan-validator.mjs — wrapper over plan-schema + manifest-yaml; håndhever step-count == manifest-count, plan_version=1.7
- progress-validator.mjs — schema_version, status enum, current_step in range, step shape, checkResumeReadiness
- architecture-discovery.mjs — EKSTERN KONTRAKT: drift-WARN ikke drift-FAIL; tolererer non-canonical filnavn, surfacer loose files som warnings

Doc-consistency-test pinning prose vs source-of-truth:
- agents/*.md count == CLAUDE.md agent-tabell rader
- commands/*.md mentioned i CLAUDE.md
- command frontmatter.name == filnavn
- templates/plan-template.md plan_version 1.7 invariant
- settings.json kun kjente scopes (ultraplan, ultraresearch)
- settings.json ingen exploration eller agentTeam (vestigial guard etter Spor 0)
- CLAUDE.md refererer alle 4 pipeline-commands

Wave 1 + Wave 2 = 108 tester grønn.

[skip-docs]: Test-infrastrukturen er ikke user-facing før Spor 1 wiring lander; README/CLAUDE.md oppdateres når commands faktisk endrer atferd (neste commit).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-01 05:39:47 +02:00