Skip to content

Releases: noderaven/parallel-lanes

v1.6.0

Choose a tag to compare

@noderaven noderaven released this 12 Oct 20:58
cb49a10

This release changes who runs which checks. Before 1.6.0 every task ran the project's whole check inventory before committing. Now a task runs the checks that cover what it changed, widening to the project's checks when it touches shared paths, and integration and a fresh verify own the full inventory. An autonomous run whose verify fails can now attempt a bounded repair instead of stopping.

Performance mechanisms validated; elapsed-time improvement not yet established.

What's improved

  • Tasks no longer run the whole suite by default. Before 1.6.0, every implementer ran the project's full check inventory before each commit, and so did every task fixer and the final fixer. Now a task runs the checks that cover what it changed. It falls back to the full suite only when it touches shared paths, changes files outside its brief, or the agent forces it.
  • The full suite runs where it counts. Integration runs it once on the merged result, and verify runs it again, fresh, at the delivered head. Acceptance still reads only verify, so the final guarantee is unchanged.
  • Fixers stay focused. Task fixers and the autonomous final fixer run the tests that cover their change, not the whole suite.
  • A failing verify no longer has to end an autonomous run. Up to 2 bounded repair attempts, each followed by a fresh verify and a re-review, can fix a real check failure at the delivered head. Previously the run ended unaccepted and handed the failure back to you.
  • Relaunches skip setup for finished lanes. A lane whose tasks are all done and reviewed no longer reruns its setup commands.
  • You can see what ran. Each task check leaves an evidence file saying which checks it picked and why. Autopsy now counts task-check calls by selection, whole-suite runs by role, repairs and setup skips. The dry run summarises the check policy before launch.

Measured on sb1, the first real run (details under Testing). The same plan had been drafted for 1.5 with no lane commands, so on 1.5.2 every task would have run the full inventory.

  • Measured: 26 of the 30 task checks were targeted, median 80 s, 2,286 s in all. The full inventory took 586 s at the start of the run and 869 s at verify.
  • Estimated, not measured: had those 26 calls each run the full inventory at 586–869 s, they would have taken about 15,200–22,600 s. That is roughly 3.6–5.6 hours of check time not spent, summed across lanes.
  • Estimated, not measured: on the run's critical path, 10 targeted calls took 985 s against an estimated 5,900–8,700 s at full-inventory cost, roughly 80–130 minutes. A different critical path, or five Unity suites contending at once, would change this figure. It is not a measured elapsed-time saving.

Highlights

  • task_checks in the manifest: per-task check lists, keyed by task id. test is required and non-empty; an absent lint or build inherits the lane's commands; a batch uses its last task's entry. Task checks are never part of the final inventory.
  • widen_paths: paths whose changes make a task run the project's checks instead of its targeted list (shared contracts, configuration).
  • scripts/task-checks: the workflow builds the call; the implementer runs it once before committing. It selects lane (no entry, as before 1.6.0), targeted or widened, records every reason in order (no_entry, no_files, outside_files, widen_path, forced, git_failed), and writes evidence to <ledger>/checks/task-<unit>.<n>.json. The evidence is a record and a count: nothing reads it to accept, skip or reuse checks.
  • Check ownership: task fixers run focused tests; reviewers read the task-check evidence; integration runs the delivery inventory once; the final fixer runs focused checks in autonomous runs (every project command in supervised runs, as before); verify runs the full inventory at the delivered head, fresh, every time. The table is in reference.md, "Check ownership".
  • Bounded repair after a failing verify (autonomous runs only): at most 2 per run (repairs_spent carries earlier launches'), only for a real failing exit at the verified head on a clean checkout (not a timeout or a signal), and only while enough agents are free for the repair, its verify and the re-review that must follow. Each repair is one Opus agent, verify repair <n>, followed by a fresh verify and a re-review of the repair. Supervised runs reject as before.
  • Setup skip: lanes with no pending work skip their setup commands on a relaunch; the report lists them in setup_skipped.
  • Dry run: a checks summary (final inventory size, units with and without an entry, widen_paths count, repair limit) and a warning when changes to shared files will not widen task checks.
  • Autopsy 5: new counters for task-check calls (by selection, reasons, failures), project test runs (whole-suite executions by role), repairs and setup skips. The legacy full_suite_runs is kept.
  • run-checks --descends-from SHA, used by repair to confirm the head it repaired.

Behaviour to know

  • A task whose changes fall outside its Files list, or under widen_paths, runs project-wide checks; an agent can force that with --force-full '<why>'. A lane whose setup differs from the project's widens to its own checks, since its worktree never ran the project's setup; integration still runs every check.
  • A break that crosses lanes and that no targeted list covers now surfaces at integration rather than in the task.
  • Manifests without task_checks behave as before 1.6.0: every task runs its lane's checks.

Testing

  • node tests/run-tests.mjs: 1268 pass, 16 skipped, 0 fail on Windows locally; CI passed on Ubuntu (Node 22 and 24), macOS and Windows (Ubuntu Node 22: 1284 tests, 1279 pass, 5 skipped, 0 fail).
  • The Python-backed tests also pass on Python 3.8.20 (216 tests).
  • First real run, sb1 (the maintainer's Unity 6 game, engine installed from the release branch before release): 24 tasks (3 prelude, 5 lanes, 4 join), 65 agents, one launch, 273 min, accepted; verify passed first time, so repair was not exercised. Measured from the run's evidence files:
    • 30 task-check calls: 26 targeted (median 80 s, 2,286 s in all) and 4 widened (all prelude tasks touching shared Core paths, median 586 s, 2,328 s in all). The project's whole suite took 731 s at integration and 867 s at verify.
    • Integration ran the full inventory once, and it passed first time. Verify ran it again at the delivered head and it passed.
    • Fixers ran focused filters, not the whole suite.
    • Not exercised in this run: repair (verify passed) and setup skip (the project has no setup commands).
    • No speed percentage: sb1 has no matched run on 1.5.2 to compare with. One run cannot establish an elapsed-time gain.

Compatibility

  • Additive manifest fields (task_checks, widen_paths, repairs_spent); manifests without them run as before.
  • New report fields: check_policy, setup_skipped, final.repairs.
  • Autopsy version 5; repair and setup counters read unavailable on archives from older engines.

Upgrade

In your clone:

git pull && bash install.sh

v1.5.2

Choose a tag to compare

@noderaven noderaven released this 11 Oct 22:52
f36f7ff

This release adds the audit handoff: scripts/audit reconstructs an archived run from its history folder, with every value naming its source and saying whether the evidence for it is present, missing, stale, conflicting or unavailable. Missing evidence is never shown as a pass.

Highlights

  • scripts/audit RUN_FOLDER [--repo DIR] [--head REF] [--out DIR] [--json] writes audit.json and audit.md (UTF-8) to RUN_FOLDER/audit/ and prints a short summary.
    • Per task: the requirement and its version, placement, rulings and changes, commits, review coverage, and four status fields kept apart: committed, reviewed, verified and accepted. A review of an earlier head is stale, not reviewed.
    • Run level: launches, code outside every recorded task range, checks, acceptance, commits after the delivered revision, and open work.
    • Acceptance: the run's verdict, the check-verify gate and any acceptance the user recorded are shown separately. The audit re-applies the engine's acceptance rules to the verify evidence (revision, results, clean tree), so a match from check-verify alone is not taken as proof.
  • Archive boundary: audit reads only files inside the run folder (symlinks and junctions resolved) and git objects, read-only. It never reads the live paths in the manifest. An input that resolves outside the folder exits 2 and nothing is written. An --out inside the run's ledger or launch dirs is refused, and writes never follow an existing file or link.
  • Privacy: configured commands (every group, setup included, any length) are replaced by <check:<id>> in one pass. Other recorded text is quoted as written, and audit.md starts by saying it holds local paths and recorded text and is not meant to be shared as-is.
  • check-verify --ledger DIR is an archive mode: it reads only the archive's own <wf>.json, needs a finite launch end time (otherwise the new status unavailable, reason verify_evidence_time_untrusted), and needs no cygpath outside Windows.
  • tool-outcomes --audit-exit N: the hand-back's "Run tools" line now reports the audit and its gap count. It still never mentions acceptance.

Behaviour to know

  • The hand-back runs audit after autopsy and before tool-outcomes. After the user accepts named reasons with ledger accept, the session reruns archive-run, audit and tool-outcomes, so the override reaches the archive.
  • The audit is informational. It never changes acceptance, the gate or the exit codes of the run.
  • On archives from older engines many values read unavailable (no acceptance object, no saved verify evidence, no review heads). That is reported, never filled in.

Testing

  • node tests/run-tests.mjs: 1156 tests, 1142 pass, 14 skipped, 0 fail on Windows locally; CI passed on Ubuntu (Node 22 and 24), macOS and Windows.
  • The new and changed test files also pass on Python 3.8.20 (122 tests).
  • audit was run on temp copies of all 24 archived runs on the maintainer's machine. Every one exits 0, and none of their configured commands appears in either report. r151, r152 and r153 read accepted with no gaps; r150 reads accepted with one gap (15 commits after its delivered revision); r142 reads accepted (gate unavailable); l131 reads unverified, as its own result does.
  • A Windows junction that points outside the run folder is refused, on Python 3.14 and 3.8.
  • Built by parallel-lanes run r153 (1.5.1 engine, its first real launch): 8 tasks (2 prelude, 4 lanes, 2 join), 25 agents, 118 min, 1 ruling, every task approved in its first review, 23 of 26 final-review findings fixed, 3 declined (one commit-message slip), none open, accepted with check-verify match. CI then caught one test that copied a run folder without its file times on Linux and macOS; it was fixed before the release commit.

Compatibility

  • Additive: no engine change and no ledger migration. check-verify's live mode, its statuses and exit codes are unchanged; --ledger and the unavailable status exist only in archive mode.
  • tool-outcomes without --audit-exit now adds "audit not run" to the Run tools line; the other parts are unchanged.

Upgrade

In your clone:

git pull && bash install.sh

Then start a new session, or run /clear, so the skill and hooks reload. Do not install while a parallel-lanes run is in progress: its agents use the installed helper scripts.

v1.5.1

Choose a tag to compare

@noderaven noderaven released this 11 Oct 16:32
dba816f

This release keeps the conditions each launch started under. doctor's result is saved with the launch it was checked for, autopsy shows it beside the slowdowns, and the hand-back gets a one-line summary of the run tools, kept apart from whether the work was accepted.

Highlights

  • doctor records every check's outcome (checks: passed, warning, failed or skipped) with observed_at, doctor_version and run_id. A check that recorded nothing shows as skipped (not_recorded), never as passed. --save FILE keeps the JSON result; a save that is refused (a path inside the project) or fails prints "result not saved" and never changes doctor's exit code.
  • ledger conditions binds a saved doctor result to one launch as doctor-<wf>.json in the run's ledger, with the launch's wf id and setup ordinal. It refuses a reused observation, a second snapshot for one setup, a rebinding with other content, a file that is not a doctor result, and a ledger with no setup. No ledger event is added, so status and resume behave as before.
  • autopsy shows "Launch conditions" per launch (autopsy_version 4, keys launch_conditions and orphan_snapshots):
    • worded as observed before the launch; a warning beside a related slowdown is a "possible contributor", never a cause;
    • a snapshot that cannot be trusted (wrong run, observed after the launch started or before the previous launch ended, duplicate setup, unreadable) is reported as inconsistent and never shown as a condition;
    • details are rebuilt from fixed patterns only, so no path, URL, file name or command reaches the report; a reading doctor could not take is "could not be read" and is never a contributor;
    • runs archived before 1.5.1 say "launch conditions unavailable".
  • scripts/tool-outcomes prints the hand-back's "Run tools" line (doctor, archive, autopsy, cleanup). It takes doctor's part from autopsy's checked binding, so it never shows conditions under the wrong launch, and it never mentions acceptance. --json gives fixed states.
  • Task briefs accept bold **Consumes:** / **Produces:** labels, the forms derive-lanes already accepted. Before, a plan with bold labels got the right lanes but briefs without the Produces blocks of the tasks they consume.

Behaviour to know

  • A transient relaunch now runs doctor first. A hard failure there turns the stop into a real stop (the spend is recorded and the lock released). In git mode with status.showUntrackedFiles=no, untracked files left by the run's own checks now stop the relaunch at doctor instead of producing an unverified run.
  • The session binds the snapshot right after the Workflow call, using the real launch's wf id (never the dry run's). A refusal never stops the run; the hand-back line says why the conditions were not recorded.

Smaller changes

  • autopsy parses each configured check command once instead of on every call.
  • One shared holdLock test helper.
  • Real-transcript regression fixtures (from r150 and r142, trimmed and scrubbed) for the three autopsy false positives fixed around 1.5.0.

Testing

  • node tests/run-tests.mjs: 1065 tests, 1051 pass, 14 skipped, 0 fail on Windows locally; CI passed on Ubuntu (Node 22 and 24), macOS and Windows.
  • The new and changed test files also pass on Python 3.8.20 (176 pass, 1 skipped).
  • Built by parallel-lanes run r152 (1.5.0 engine): 9 tasks in 5 lanes plus 2 join tasks (one an end-to-end test of the whole chain), 26 agents, 59 min, no rulings, every task approved in its first review, 16 final-review findings fixed and none open, accepted with check-verify match.

Compatibility

  • Additive: doctor's existing JSON keys and exit codes, ledger status, resume and run-report's output are unchanged.
  • autopsy's format moves to autopsy_version 4; history redoes older autopsies automatically.

Upgrade

In your clone:

git pull && bash install.sh

Then start a new session, or run /clear, so the skill and hooks reload. Do not install while a parallel-lanes run is in progress: its agents use the installed helper scripts.

v1.5.0

Choose a tag to compare

@noderaven noderaven released this 11 Oct 01:57
0ec2283

This release adds run tools: every run can explain itself afterwards, every launch is checked first, and finished runs are tidied without losing the way back. An outside review before release found ten defects, plus two more found while verifying them; all are fixed here with regression tests.

Highlights

  • scripts/doctor runs before every launch. Hard failures stop the flow: no git identity, a base branch that is behind or diverged from its upstream (or cannot be compared) on a new run, no usable Python, a dirty checkout, a broken shadow repo. Warnings go in the dry-run header: memory, disk, a Python alias, heavy processes, other active runs, Defender coverage of the work folders, and concurrency. It never writes or fetches.

  • scripts/autopsy explains one archived run. It writes autopsy.json and autopsy.md and prints a short summary:

    • what got done, and time by phase, lane and agent, with tool time as a union of spans and the critical path labelled an estimate;
    • check executions, named by check id (test#1, <lane>.test#1), each marked ran or inferred depending on whether the shell control flow proves it ran; full-suite totals count only proven runs;
    • tokens, with buckets that have no usage data shown as unavailable rather than zero;
    • slowdowns from structured evidence, with a suggestion for each, and unexplained time as open questions.

    It writes no command text, prompts or tool output. Background runs end only at Claude Code's own completion notice or a terminal poll result, as an upper bound; notification-shaped text an agent reads from a file never counts. Agents with lost tool results are marked partial, not idle.

  • scripts/archive-run and scripts/history. Runs are copied into one history folder (PL_HISTORY_DIR, default <config dir>/parallel-lanes/history) with an index.json; --reindex rebuilds the index, imported layouts included. history compares runs: recurring slowdowns, token trends and runs with too little data. The index is guarded by an OS-level lock that is released when its holder exits, so a crashed archive-run never leaves a lock to take over.

  • scripts/cleanup tidies a finished, archived run. It plans by default and acts only with --yes:

    • it first writes a verified restore point (refs, a checked git bundle, and the restore commands);
    • it removes only run-owned worktrees and branches, never with --force or -D;
    • it holds the run's lock and the main checkout's lock while it acts, and rechecks each item right before removing it;
    • after the PR merges, it switches the main checkout to the base and fast-forwards it.
  • scripts/run-checks times each command (started, ended, duration_s). check-verify still compares only group, command and exit.

Fixes from the pre-release review

  • cleanup, and the integration step's lane cleanup, could delete untracked files hidden by status.showUntrackedFiles=no. Every cleanliness check and removal now sees all untracked files, and a failed git status keeps the item.
  • autopsy copied configured check commands into its reports; checks are now named by id.
  • Text that only mentioned a check (an echo, a grep, a heredoc body, a parser probe) counted as a test run; only commands in executable position count now.
  • A background run's first mention counted as its measured end, missing tool results became zero tool time, a later failure in a compound command was blamed on an earlier heredoc write, a needed rerun after a Bash edit was called redundant, and a run with no usage data showed zero tokens. Each now reports partial, unavailable or nothing, rather than a guess.
  • The history index's stale-lock takeover could admit two writers; it is replaced by an OS lock.

Behaviour to know

  • Ignored files (build output, node_modules, an ignored .env) do not keep a worktree, and git worktree remove deletes them. Copy any ignored file you still need out of a worktree before cleanup --yes.
  • autopsy counts are lower bounds: checks run through a wrapper (bash -c, a script) are not seen, and inferred runs may not have happened.

Testing

  • node tests/run-tests.mjs: 1004 tests, 990 pass, 14 skipped, 0 fail on Windows locally; CI passed on Ubuntu (Node 22 and 24), macOS and Windows.
  • Built by parallel-lanes run r150 (1.4.4 engine): 15 tasks in 5 lanes, 44 agents, 134 min, accepted with check-verify match. The review fixes were built by run r151 (1.4.4 engine): 8 tasks in 4 lanes, 25 agents, about 79 min, every task approved in its first review, 19 final-review findings fixed, accepted with check-verify match.
  • The corrected autopsy and history were rerun on a copy of 21 archived runs: no command text in any output.

Compatibility

  • New scripts only add behaviour; run-report's output is unchanged.
  • autopsy's own format is new in this release (autopsy_version 3).

Upgrade

In your clone:

git pull && bash install.sh

Then start a new session, or run /clear, so the skill and hooks reload. Do not install while a parallel-lanes run is in progress: its agents use the installed helper scripts.

v1.4.4

Choose a tag to compare

@noderaven noderaven released this 10 Oct 21:06
af9a44b

This release fixes six findings from the 2026-10-10 audit, plus three defects found in its review, each with a regression test. Most of it makes accepted mean more: checks that passed only because of an uncommitted file, approvals given against an older spec, and one fix settling several different findings no longer count.

Highlights

  • Checks with untracked files present do not cover the delivered commit. run-checks now records untracked_before and untracked_after (the ?? lines of git status --porcelain --untracked-files=all). An untracked file present before the checks makes them checks_unclean, so the run is unverified, not accepted; a file only the checks themselves create is a warning. check-verify compares the new lists. Ignored files are not covered.
  • Approvals record the spec. ledger reviewed takes an optional SPEC argument (- for none) and records spec_sha256; on resume, an approval whose spec changed is stale. An approval from before 1.4.4 records no spec, so in a run with a spec it is reviewed again once, also after a later launch's setup or a removed spec. The 9-argument form still works.
  • Distinct findings on one line stay separate. The final review merges findings only when location and issue text match; different issues at one place keep their own ids (same_location links them), so fixing one cannot settle another.
  • Reserved ids are rejected. Task and lane ids that are JavaScript property names (__proto__, constructor, toString, ...) are refused at validation, and id lookups use own properties only.
  • run-report shows damaged transcripts. unreadable_lines (per agent and in total) counts lines that are not valid JSON or not valid UTF-8; such an agent's totals are partial (output_tokens unavailable, the lower bound in output_tokens_min). A U+2028 inside a string is read correctly.
  • The installer fails safely. settings.json must hold exactly one JSON object: an empty file, several documents, an array or invalid JSON stop both uninstall and update before anything is removed or replaced.

Behaviour change to know

Earlier steps of a run (integration, the e2e and post-integrate hooks, the final fixer) run the project's checks in the feature checkout. If those checks write files that are not gitignored (coverage output, test results), the files are still there when verify runs, and the run comes back unverified with checks_unclean. Ignore known disposable output in .gitignore; never ignore source a check needs. reference.md "Report" describes the guarantee and its limits.

Testing

  • node tests/run-tests.mjs: 842 tests, 830 pass, 12 skipped, 0 fail on Windows locally; CI passed on Ubuntu (Node 22 and 24), macOS and Windows.
  • Built by parallel-lanes run r144 (1.4.3 engine): 9 tasks in 5 lanes, 28 agents, 51 min, accepted with check-verify match. An outside review then reproduced three more defects (legacy approvals regaining validity after a later setup, empty or multi-document settings passing validation, invalid UTF-8 hiding lost counts); all three are fixed here with tests.

Compatibility

  • run-checks output, verify results and run-report output gain fields; existing fields keep their meaning.
  • Verify evidence written by an older run-checks (no untracked lists) is checks_unclean under 1.4.4.
  • Resuming a run started before 1.4.4 that has a spec reviews its earlier approvals once more.

Upgrade

In your clone:

git pull && bash install.sh

Then start a new session, or run /clear, so the skill and hooks reload. Do not install while a parallel-lanes run is in progress: its agents use the installed helper scripts.

v1.4.3

Choose a tag to compare

@noderaven noderaven released this 10 Oct 18:41
d8e0c21

This release makes the running skill version visible and records it with every run.

Highlights

  • See which version is running. scripts/build stamps VERSION into run.workflow.js: the workflow's description reads parallel-lanes v1.4.3: Execute an implementation plan... in the workflow view and notifications, and the first log line of every run, dry runs included, is parallel-lanes v1.4.3 loaded. The version comes from the script that actually runs, so a stale copy shows its own version. (#19)
  • The version is recorded. Every workflow result, dry runs included, has a top-level version, and scripts/run-report outputs engine_version (saved in each <plan>.<run_id>.report.json). Runs from earlier versions report "unavailable". (#19)
  • The build checks VERSION. A VERSION that is not one x.y.z version fails the build and writes nothing.

Testing

  • node tests/run-tests.mjs: 790 tests, 0 failures on Windows locally; CI passed on Ubuntu (Node 22 and 24), macOS and Windows.
  • New: tests/version.test.mjs (the stamped description and script, no placeholder left, a malformed VERSION refused, the first log line and the version in dry-run and invalid results) and a run-report test for engine_version.

Compatibility

  • No manifest or ledger format changes. Workflow results gain version; run-report output gains engine_version.
  • For contributors: a VERSION bump must commit the rebuilt run.workflow.js with it (the build freshness test fails otherwise).

Upgrade

In your clone:

git pull && bash install.sh

Then restart Claude Code, or run /clear, so the skill and hooks reload. Do not install while a parallel-lanes run is in progress: its agents use the installed helper scripts.

v1.4.2

Choose a tag to compare

@noderaven noderaven released this 10 Oct 07:00
2728846

This release acts on the r140 measurement report: agents run checks and edit files the way that cost the least time there, and the session no longer reports accepted when the verify agent's report disagrees with the saved check evidence.

Highlights

  • Agents run checks without losing them. Every agent prompt now says: when your role runs checks, ask for a 600000 ms timeout, read the tool result to see whether the command finished, moved to the background or was stopped, and treat a background command as finished only on its completion notice or exit status, never on a line of its output (a failing run may never print it). Before running a check again, read the earlier run's result or stop it and confirm it ended; do not finish while a required check is unresolved. In r140, commands moved to the background at the 120 s default six times, and one agent waited 8.3 min for an output line a failing run never printed.
  • Agents edit files with their editing tools. Every agent prompt now says to change file contents with Edit and Write: text written through heredocs, sed or inline scripts can be corrupted by shell quoting. Project tools that change files (generators such as scripts/build, formatters, codemods) stay fine. In r140 two such mistakes (an apostrophe, a \b) cost the final fix about 10.6 min.
  • scripts/check-verify and a fail-closed hand-back. At hand-back the session compares the verify agent's report with the scripts/run-checks JSON saved during the same launch (<ledger_dir>/checks/verify-<sha>.json):
    <python> <skill_dir>/scripts/check-verify <transcript dir> <manifest file>.
    It prints one JSON line with a status: match or not_required (exit 0); missing, stale, mismatch or invalid (exit 1, with reasons verify_evidence_missing, verify_evidence_stale, verify_mismatch, verify_invalid); exit 2 for usage or unreadable inputs. It checks types (booleans and integers are not interchangeable), field presence, and the commit sha before building a path, and treats evidence written before the launch started as stale. The session reports accepted and removes the run's marker only when the workflow accepted the run and check-verify exited 0 with match or not_required. Every other outcome, a checker error included, is unverified.

What check-verify does not do

It is a consistency check, not an independent guarantee: it does not re-run the checks. It cannot catch an agent that writes or alters both copies consistently, execution details both copies agree on (checkout and branch are not compared), or a session that skips it. Evidence is one file per commit, overwritten by each verify attempt; the freshness check keeps an older file from passing for a new launch, and per-attempt records are later work. reference.md "Verify evidence" describes this and the recovery: the session re-runs the checks itself into session-verify-<sha>.json, and the user may accept the run explicitly with ledger accept (recorded as an override, not a match).

Fixes

  • tests/install.test.mjs ran the registered hook commands with bare sh, which is not on PATH when the suite starts from PowerShell or cmd. It now uses the shell Claude Code runs hooks with: Git Bash on Windows, sh elsewhere (dash on Ubuntu still checks POSIX quoting). This was the known issue listed in 1.4.1. (#17)
  • result_paths() moved from scripts/run-report into scripts/_shell.py, shared by run-report and check-verify; run-report behaves as before.

Testing

  • node tests/run-tests.mjs, 786 tests, 0 failures everywhere. CI: Ubuntu (Node 22 and 24) 784 pass, 2 skipped, about 21 s; macOS 785 pass, 1 skipped, 37 s; Windows 774 pass, 12 skipped, 74 s. Every job also checks that the suite leaves the checkout unchanged.
  • New: tests/check-verify.test.mjs (every status and exit code, type and presence checks, malformed sha, stale evidence, and the documented recovery commands run end to end), agentRules() unit tests plus the every-prompt rule check, the no-commands acceptance invariant, and instruction checks for SKILL.md and reference.md (these check the session's instructions, not enforced behaviour).
  • Built by parallel-lanes run r142 (1.4.1 engine, Windows): 3 tasks in 2 lanes, 14 agents, 25.8 min; each task approved at its first review; 4 minor final-review findings fixed and re-reviewed; accepted, and the new check-verify returned match on the run's own evidence.

Compatibility

  • No manifest, ledger or workflow result format changes.
  • Every agent prompt is about 150 words longer (the two rules).
  • The hand-back now needs check-verify: a session following the 1.4.2 SKILL.md runs it before reporting accepted. An older ledger's evidence (written by run-checks before 1.4.0, without the tracked lists) does not match a 1.4.x report; that only matters when checking an old run.

Upgrade

In your clone:

git pull && bash install.sh

Then restart Claude Code, or run /clear, so the skill and hooks reload.

v1.4.1

Choose a tag to compare

@noderaven noderaven released this 10 Oct 06:01
d286e80

This release makes the test suite run its files in parallel. Nothing in the skill's runtime behaviour changes.

Highlights

  • New test runner: node tests/run-tests.mjs. It names every tests/*.test.mjs to node --test, so each file runs in its own process, four at a time by default (PL_TEST_CONCURRENCY or --concurrency N to change it; other arguments go to node --test). It exits with node's exit code, and 2 on a usage error. (#15, #16)
  • Why it is faster: node --test tests/ loads tests/index.js, which imports every test file one after another in a single process, so the suite never ran files in parallel. That command still works, but the runner is now the documented one, and CI uses it.
  • No silent passes when nested: node --test sets NODE_TEST_CONTEXT in the processes it starts, and a node --test that inherits it runs nothing and exits 0. The runner removes it, so a run started from inside a test process still runs and reports failures.

Measurements

Windows 11 (20 cores), Node 24.17.0, the v1.4.0 suite (754 tests). Every run passed with the same counts and left nothing in the checkout.

One suite alone, python3 through the app alias (see Notes):

Command Runs (s)
node --test tests/ 266.6, 268.2, 268.8
one file at a time, separate processes 272.1, 273.8, 278.2
two at a time 147.1, 147.2, 147.7
four at a time 93.4, 94.8, 96.6

After putting Python\bin first on PATH: one suite alone took 130.0, 130.7, 130.8 s with two at a time and 96.4, 97.2, 97.3 s with four. Four suites at once in separate checkouts, as four lanes run them (one round): 299.1-300.6 s per suite through node --test tests/, 214.4-216.2 s with two at a time, 200.2-200.7 s with four.

Testing

  • node tests/run-tests.mjs, 761 tests, 0 failures everywhere. CI: Ubuntu (Node 22 and 24) 759 pass, 2 skipped, about 20 s; macOS 760 pass, 1 skipped, 45 s; Windows 749 pass, 12 skipped, 121 s (about 243 s through node --test tests/ before #15). Every job also checks that the suite leaves the checkout unchanged.
  • tests/run-tests.test.mjs (7 tests) runs the runner against fixture files: one process per file, the default and overridden concurrency, failures passed through, option pass-through, a nested start, usage errors. The default test failed before each default change.

Notes

  • Windows, python3 through the app alias: if python3 resolves to %LOCALAPPDATA%\Microsoft\WindowsApps\python3.exe (the Python install manager's app execution alias), each start goes through Windows app activation. On one machine that cost about 55 ms per start (76 ms against 21 ms through %LOCALAPPDATA%\Python\bin\python3.exe, the same interpreter), and the suite starts Python several hundred times. Putting %LOCALAPPDATA%\Python\bin before WindowsApps on PATH avoids it. On that machine the two-at-a-time median fell from 147 s to 131 s after the change (separate sessions, not a controlled comparison).
  • Known issue: two checks in tests/install.test.mjs start sh by name, so the suite fails there when started from PowerShell or cmd, where sh is not on PATH. Run it from Git Bash (as before) until this is fixed.

Upgrade

In your clone:

git pull && bash install.sh

Then run the tests with node tests/run-tests.mjs.

Measurement clarification (edited after release): the 147 s to 131 s figure is a before/after observation from separate sessions, not a controlled comparison of the two PATH orders.

v1.4.0

Choose a tag to compare

@noderaven noderaven released this 10 Oct 03:57
99be619

This release fixes the eight issues and one hardening point an external audit of v1.3.1 found (F1-F8, H1). The common thread: acceptance: accepted could claim more than its evidence showed, and two runs could share one checkout.

Highlights

  • Accepted means the delivered commit was checked. run-checks reports tracked_before and tracked_after (the git status --porcelain --untracked-files=no lines before the first command and after the last). Checks that ran on uncommitted or staged tracked changes, checks that changed a tracked file, and a verify result without those lists now give the reason checks_unclean, so the run is unverified, never accepted. Untracked build output stays a warning. (F1)
  • One run per checkout. In git mode scripts/setup takes a checkout lock (checkout-<st_dev>-<st_ino>.lock, keyed by the file identity of the checkout's top level, so another spelling or a subdirectory of the same checkout is the same lock). A second run on the same checkout is refused with exit 4 before any branch switch. A lock whose run has no launch lock is taken over; runs in separate worktrees of one repo are not blocked. (F4)
  • Only the owner releases a lock. active-run release RUN_ID STATUS|--remove --owner TOKEN needs the owner token and refuses another token with exit 4. Acquire, takeover, release and remove run under a per-run mutex directory (PL_MUTEX_WAIT seconds, default 10). (H1)
  • A schedule pre-flight cannot meet stops the run. Pre-flight reports undeclared dependencies on another task's real code as code_deps. One the run order cannot meet stops the run before any task, in both autonomy modes and without an adjudicator: status preflight_conflicts with preflight.schedule entries naming the move (for example move T2 to join, or into T1's lane after it). A dependency the order already meets only adds context. (F8)
  • The final review is bound to one commit. The result records final.lens_heads. When a lens reports a head that is not a commit sha, or the lenses report different commits, final.review_problem says so and acceptance adds review_unbound. (F2)

What changed

  • Final verify includes lane checks: one inventory (finalChecks: global checks, then the checks lane overrides add) drives the dry run's Verify entry, the verify prompt (with each lane's setup override) and acceptance, so a lane-only test runs at the delivered commit. (F3)
  • Final findings need an accounted fix: a finding with no disposition stays open, and a disposition or re-review result with empty or whitespace-only evidence leaves it open. (F7)
  • Shadow repos keep exact bytes: a new shadow writes info/attributes (* -text -eol -filter -ident -working-tree-encoding), which outranks the project's .gitattributes and the user's core.attributesFile, so an untouched CRLF file under text=auto is no longer a false conflict and writeback keeps bytes. Conflict detection hashes with the shadow's attributes. (F5)
  • Ids: task ids and lane ids that differ only in letter case, and task, lane or run ids that are Windows device names (CON, NUL, COM1, ...), are rejected. (F6)
  • Test suite: the Python snippets in tests/io.test.mjs and tests/platform.test.mjs no longer leave scripts/__pycache__, which made the next suite run in the same checkout fail with EISDIR. CI now fails when the suite leaves the checkout changed.
  • Docs: SKILL.md passes --owner <token> to every release and covers preflight.schedule and a refused checkout; reference.md documents the new fields, reasons and locks; README gets troubleshooting rows. Superpowers 7.0.0 ships the same prompts parallel-lanes uses as 6.4.2.

Testing

  • node --test tests/: 754 tests, 0 failures everywhere. CI: Ubuntu (Node 22 and 24) 752 pass, 2 skipped; macOS 753 pass, 1 skipped; Windows 742 pass, 12 skipped; every job also checks that the suite leaves the checkout unchanged. Locally on native Windows 11 (Git Bash) the suite ran twice in a row in one checkout with git status --porcelain empty after each run.
  • The new tests fail against the 1.3.1 code (1.4.0 tests/ over the v1.3.1 sources): the acceptance, active-run and run-checks cases, 8 checkout-lock cases in setup-script, 6 attribute cases in shadow, 20 cases in run (lens heads, lane checks, pre-flight schedule, findings), and validate (the new helpers do not exist there).
  • Built by a parallel-lanes run (r140, on 1.3.1) that ended accepted: 11 tasks, each approved at its first review with no fix rounds; integration with no conflicts; 13 minor final findings, all fixed and re-reviewed; 32 agents, no adjudications. Two follow-up commits after the run fix the bytecode cache found during it.

Compatibility

  • Manifests and ledgers from 1.3.x keep working, except a manifest with case-only duplicate ids or Windows device names, which now fails validation.
  • active-run release needs --owner <token> (exit 2 without it). The token is what active-run acquire printed; a resume acquires again. A lock left by a session that ended is still taken over with --takeover.
  • Shadow mode: a shadow made before 1.4.0 keeps its old representation (no attributes override), which is right for resuming its run; a new run gets a new shadow.
  • The active-run directory now also holds checkout-*.lock files while git-mode runs are set up.

Upgrade

In your clone:

git pull && bash install.sh

Then restart Claude Code, or run /clear, so the hooks reload.

v1.3.1

Choose a tag to compare

@noderaven noderaven released this 10 Oct 00:52
8895d23

Highlights

  • Every ruling reaches every agent. Pre-flight and adjudicator rulings are kept for the whole run and given to every task prompt and final lens under "Rulings already made for this run (binding)", so implementers no longer re-decide settled points.
  • Fix commits get their own messages. A task fix round commits with fix: address review findings for Task <id> (a batch: for Batch <first>-<last>), the final fix with fix: address the final review findings, and a post-integration fix with fix: make the post-integration check pass. A retry that adds to a task's first commit with no review findings behind it uses chore: continue Task <id>. Reviewers are told these are not commit-rule findings (in nw1, 9 of 19 final findings were repeated commit messages).
  • Less repeated work at the end of a run. The project checks run once at the delivered commit, before the final re-review, and the re-review is given their result instead of rerunning the suite. run-checks writes command output to a log file and prints one JSON line with a tail of each command.
  • Fewer, sharper warnings. cannot_verify entries are structured ({requirement, source, why, check_by}) and only ones that name a plan or spec source become acceptance warnings. Minor findings from approved task reviews go to the final lenses as a checklist (T<n>-<k>), and the ones no lens raised are listed in final.task_minors_open. Final findings on the exact same file and line (or the same commit) are combined, keeping the other texts as also_reported.

What changed

  • Agent heads are checked: a head an agent reports must be a commit sha (7 to 40 hex digits). Anything else (in a live test run the final fix reported see-below) counts as no head, and a final fix that reports one leaves its findings open and its commits marked unreviewed.
  • derive-lanes: a ; inside parentheses or backticks no longer splits a Files clause, so notes such as (lines 34, 64; required keys) keep the paths after them. A line that leaves a backtick or ( open falls back to splitting on every ;, with a warning.
  • Shadow repos: the shadow repo's config sets core.autocrlf=false, so lane worktrees hold the project's exact bytes and writeback keeps CRLF files as they are. abs_dir ignores CDPATH.
  • Manifest and records: hooks is optional (defaults to {}); the result records every agent's model and effort (agent_settings); the dry run returns notices (the launch line computed by the script); ledger ended DIR STATUS AGENTS RULINGS records a launch's spend.
  • run-report: reads effort from the run's own record, and prints unavailable instead of 0 when no output-token count is complete.
  • Git identity: before building a manifest, the skill checks that the project has a git identity (git var GIT_COMMITTER_IDENT), since every task commits and a missing identity fails partway through a run.
  • Docs: the Workflow concurrency cap (CLAUDE_CODE_WORKFLOW_MAX_CONCURRENT_AGENTS), that the launch message reaches every agent with priority over the plan (so answer the dry-run table with a plain yes), reasons that earlier trims cut from SKILL.md restored (still under 3000 words), and Windows support is no longer called preliminary.
  • Node 22 is the minimum for the test suite (Node 18 and 20 are end of life); CI's Node 18 job is now Node 22.

Testing

  • node --test tests/: 675 tests. Linux and macOS: 674 pass, 1 Windows-only test skipped. Windows (windows-latest): 664 pass, 11 skipped, the same tests and reasons as in 1.3.0.
  • Built by a parallel-lanes run (r131) that ended accepted: 9 tasks reviewed and approved, post-integration and E2E checks passed, and 9 of 10 final findings fixed (1 declined with a reason). A full review of that run, plus a live run of the new workflow on a throwaway project, found seven more issues, fixed before release (the head check above, the derive-lanes fallback, the continuation message only on retries, a resume note that no longer warns, and test and doc fixes).

Compatibility

  • Manifests and ledgers from 1.3.0 keep working.
  • Shadow mode, once after upgrading: a shadow made by 1.3.0 lacked core.autocrlf=false. On a machine with core.autocrlf=true (Git for Windows' default), the first setup after the upgrade sees every text file in its lane worktrees as modified, lists them as discarded edits, saves a preserved ref, and checks them out again. Nothing a task committed is lost.

Upgrade

In your clone:

git pull && bash install.sh

Then restart Claude Code, or run /clear, so the hooks reload.