review(#4097): CI test ratchet exclusion, coverage report size cap and count clamping, sparc 0.3.5 / testgen 0.3.3, sanitize receipts

Co-Authored-By: RuFlo <ruv@ruv.net>
This commit is contained in:
RuFlo committed 2026-10-12 11:15:50 -04:00
1 parent 6fe5706dfb
commit b4cbd4be9f
21 files changed
+139 -82

No files matched your search

+19 -8
View File
@@ -1,8 +1,8 @@
# October 12 issue fixes and verification
Worktree: `/home/ruv/work/ruflo-fixes-20261012`
Worktree: `<repo>`
Branch: `fix/oct12-verified-issues`
Final base: `3209ba266750908ea88fb0bc69672e106478bbef` (parent fast-forwarded main during review). All repair changes remain uncommitted. No push, merge, publication, credential changes, or Anthropic execution was performed by this worker.
Final base: `3209ba266750908ea88fb0bc69672e106478bbef` (parent fast-forwarded main during review). This section describes the state when the repair was first validated, before it was committed. No merge, publication, credential changes, or Anthropic execution was performed by this worker.
## Issue mapping
@@ -16,7 +16,7 @@ Final base: `3209ba266750908ea88fb0bc69672e106478bbef` (parent fast-forwarded ma
| #4087 | Qualified phase agents, including exactly `ruflo-goals:goal-planner` and `ruflo-swarm:architect`; added missing-plugin preflight without silent substitutions or expanded permissions. | Checks assert the exact six phase-agent references and resolve each shipped agent file/frontmatter. |
| #4088 | Qualified SPARC command and skill invocations throughout command text, skill instructions, README, and examples, including init's specification suggestion. | Recursive command/skill Markdown scan rejects unqualified aliases and resolves qualified references to shipped files. The separately registered `/sparc-mod` stays unchanged. |
Both plugin smoke scripts now run their prompt regression contracts. No dependency, version, lockfile, SONA, mission, or MCP testgen runtime changes are included.
Both plugin smoke scripts now run their prompt regression contracts. No dependency, lockfile, SONA, mission, or MCP testgen runtime changes were in the first validated state; the review addendum below adds plugin version bumps.
## Reproduction and results
@@ -42,14 +42,14 @@ Initial reproductions ran on `aac16fbdb3af21c0ddb989aaff4513a9ec1aaca5`. The cov
Validation commands (all run from the worktree root; each candidate run exited 0). Coverage, TDD, type-check and witness results below predate the final SPARC-only lifecycle edit; they were not rerun because those files did not change:
```bash
node --import /home/ruv/work/ruflo-fixes-20261012-task/validation-tools/node_modules/tsx/dist/loader.mjs tests/regression/oct12-coverage.test.cjs
node --import <validation-tools>/node_modules/tsx/dist/loader.mjs tests/regression/oct12-coverage.test.cjs
node plugins/ruflo-sparc/tests/contracts.regression.cjs
node plugins/ruflo-testgen/tests/tdd-workflow.regression.cjs
node /home/ruv/work/ruflo-fixes-20261012-task/validation-tools/node_modules/vitest/vitest.mjs run --config tests/regression/oct12.vitest.config.mjs
node <validation-tools>/node_modules/vitest/vitest.mjs run --config tests/regression/oct12.vitest.config.mjs
bash plugins/ruflo-sparc/scripts/smoke.sh
bash plugins/ruflo-testgen/scripts/smoke.sh
node scripts/smoke-witness-marker-drift.mjs
node /home/ruv/work/ruflo-fixes-20261012-task/validation-tools/node_modules/typescript/bin/tsc --noEmit --strict --skipLibCheck --target ES2022 --module NodeNext --moduleResolution NodeNext --types node --typeRoots /usr/lib/node_modules/@claude-flow/cli/node_modules/@types v3/@claude-flow/cli/src/commands/coverage-reader.ts
node <validation-tools>/node_modules/typescript/bin/tsc --noEmit --strict --skipLibCheck --target ES2022 --module NodeNext --moduleResolution NodeNext --types node --typeRoots /usr/lib/node_modules/@claude-flow/cli/node_modules/@types v3/@claude-flow/cli/src/commands/coverage-reader.ts
git diff --check
```
@@ -70,7 +70,7 @@ The lifecycle changes are prompt contracts, not executable transactional storage
Initial red commands, captured before implementing each corresponding fix:
```bash
ESBUILD_MODULE=/home/ruv/.npm/_npx/fd45a72a545557e9/node_modules/esbuild node tests/regression/oct12-coverage.test.cjs
ESBUILD_MODULE=<path-to-esbuild> node tests/regression/oct12-coverage.test.cjs
node tests/regression/oct12-sparc.test.cjs
node tests/regression/oct12-tdd-workflow.test.cjs
```
@@ -79,7 +79,7 @@ These historical paths/harness versions explain the paths in the before receipts
## Separately assessed upstream work
The parent supplied current issue #4085/#4087 bodies, `pr4081.patch`, and `pr4081-checks.txt` under `/home/ruv/work/ruflo-fixes-20261012-task/`. Local `gh api repos/ruvnet/ruflo/issues/4082` could not reach GitHub. The authorized ruOS desktop shell read was rejected because approval is required and policy is `never`; it was not retried or escalated. External reads and integration were handled by the parent.
The parent supplied current issue #4085/#4087 bodies, `pr4081.patch`, and `pr4081-checks.txt` under `<repo>-task/`. Local `gh api repos/ruvnet/ruflo/issues/4082` could not reach GitHub. The authorized ruOS desktop shell read was rejected because approval is required and policy is `never`; it was not retried or escalated. External reads and integration were handled by the parent.
**#4080 / PR4081:** inspected the supplied patch. It restores serialized SONA state when `LearningBridge` loads its neural instance, persists synchronously before cleanup, exposes `NeuralLearningSystem.serialize/deserialize`, and includes persistence/restore/degradation regressions. The current patch pins CLI memory exactly to `3.1.0`, rather than a caret range. Its synchronous best-effort save is not a concurrency/crash-durability guarantee. No part of this patch was duplicated or applied here.
@@ -94,3 +94,14 @@ Parent-supplied checks for head `4059c29`: **119 passed, 3 skipped, zero failure
- The initial out-of-scope testgen runtime experiment and mock tests were removed. Missing-plugin graceful degradation remains its existing deliberate contract. Signal-termination/result parsing observations are deferred for a separately scoped review, not counted as #4085 fixes.
- Required parent/repository/nested instructions were read before edits. Existing coordination was inspected: policy `legacy`, zero rules, valid empty ledger; no tracked collaboration-session adapter was found in `.harness`. A one-agent coordination record was initialized. Memory recall returned `Database not found`; no learning-memory success receipt is claimed. The installed CLI reported daemon auto-start during recall; `ruflo daemon stop` then reported it was not running, and subsequent CLI coordination disabled auto-start. No AI worker or external model execution was requested.
- `source-sha256.txt` binds the final modified source/tests/configuration, including untracked files, to their bytes. Parent inspection and independent rerun are the next integration step. All changes remain uncommitted.
## Review addendum (independent review of PR #4097)
A second reviewer reproduced #4082–#4084 on the published 3.56.7 CLI and on this branch with fixtures built from scratch (an lcov file with a zero-line file, a large and a small file; a vitest-style `coverage-final.json`; a Jest `coverage-summary.json` with `"pct": "Unknown"`). 3.56.7 listed the zero-line file as 0.0% critical and reported 33.0% overall for a 98.0% weighted report, found no data for `coverage-final.json`, and crashed on the Jest summary with `overallBranchCoverage.toFixed is not a function`; this branch fixes all three. Changes made in review:
- `scripts/ci-test-excluded.txt` now lists `tests/regression/oct12-coverage.test.cjs`, which root vitest had picked up and failed the CI test ratchet on (it has its own `node --test` runner, and needs Node 22+ to load a `.ts` file).
- The coverage reader ignores a report larger than 64 MiB or that is not a regular file, and clamps impossible lcov counts (hits above found, negative counts), with two tests in `hooks-coverage-disk.test.ts`.
- `ruflo-sparc` 0.3.5 and `ruflo-testgen` 0.3.3 (plugin changes reach marketplace users only after a version bump), with changelog entries.
- Absolute home paths in these receipts were replaced with placeholders.
Not covered by this PR: the same literal `--success true` post-task pattern appears in about 45 other plugin agents and skills (for example `ruflo-security-audit/skills/security-scan`). SPARC verification covers instruction contracts, not a live model session.
@@ -3,7 +3,7 @@ TAP version 13
not ok 1 - \#4082 empty instrumented file is fully covered, not a gap
---
duration_ms: 2.797531
location: '/home/ruv/work/ruflo-fixes-20261012/tests/regression/oct12-coverage.test.cjs:18:1'
location: '<repo>/tests/regression/oct12-coverage.test.cjs:18:1'
failureType: 'testCodeFailure'
error: |-
Expected values to be strictly equal:
@@ -16,7 +16,7 @@ not ok 1 - \#4082 empty instrumented file is fully covered, not a gap
actual: 0
operator: 'strictEqual'
stack: |-
TestContext.<anonymous> (/home/ruv/work/ruflo-fixes-20261012/tests/regression/oct12-coverage.test.cjs:20:10)
TestContext.<anonymous> (<repo>/tests/regression/oct12-coverage.test.cjs:20:10)
Test.runInAsyncScope (node:async_hooks:206:9)
Test.run (node:internal/test_runner/test:796:25)
Test.processPendingSubtests (node:internal/test_runner/test:526:18)
@@ -30,7 +30,7 @@ not ok 1 - \#4082 empty instrumented file is fully covered, not a gap
not ok 2 - \#4082 pct-only summaries preserve explicit zero and nonzero percentages
---
duration_ms: 0.32945
location: '/home/ruv/work/ruflo-fixes-20261012/tests/regression/oct12-coverage.test.cjs:23:1'
location: '<repo>/tests/regression/oct12-coverage.test.cjs:23:1'
failureType: 'testCodeFailure'
error: |-
Expected values to be strictly equal:
@@ -43,7 +43,7 @@ not ok 2 - \#4082 pct-only summaries preserve explicit zero and nonzero percenta
actual: 0
operator: 'strictEqual'
stack: |-
TestContext.<anonymous> (/home/ruv/work/ruflo-fixes-20261012/tests/regression/oct12-coverage.test.cjs:25:10)
TestContext.<anonymous> (<repo>/tests/regression/oct12-coverage.test.cjs:25:10)
Test.runInAsyncScope (node:async_hooks:206:9)
Test.run (node:internal/test_runner/test:796:25)
Test.processPendingSubtests (node:internal/test_runner/test:526:18)
@@ -56,7 +56,7 @@ not ok 2 - \#4082 pct-only summaries preserve explicit zero and nonzero percenta
not ok 3 - \#4083 LCOV aggregates counts for every metric, including unterminated last record
---
duration_ms: 0.659871
location: '/home/ruv/work/ruflo-fixes-20261012/tests/regression/oct12-coverage.test.cjs:28:1'
location: '<repo>/tests/regression/oct12-coverage.test.cjs:28:1'
failureType: 'testCodeFailure'
error: |-
overallLineCoverage
@@ -70,7 +70,7 @@ not ok 3 - \#4083 LCOV aggregates counts for every metric, including unterminate
actual: 55
operator: 'strictEqual'
stack: |-
TestContext.<anonymous> (/home/ruv/work/ruflo-fixes-20261012/tests/regression/oct12-coverage.test.cjs:31:130)
TestContext.<anonymous> (<repo>/tests/regression/oct12-coverage.test.cjs:31:130)
Test.runInAsyncScope (node:async_hooks:206:9)
Test.run (node:internal/test_runner/test:796:25)
Test.processPendingSubtests (node:internal/test_runner/test:526:18)
@@ -83,7 +83,7 @@ not ok 3 - \#4083 LCOV aggregates counts for every metric, including unterminate
not ok 4 - \#4084 Istanbul final and NYC counters count unique lines and individual branch arms
---
duration_ms: 3.514771
location: '/home/ruv/work/ruflo-fixes-20261012/tests/regression/oct12-coverage.test.cjs:33:1'
location: '<repo>/tests/regression/oct12-coverage.test.cjs:33:1'
failureType: 'testCodeFailure'
error: |-
Expected values to be strictly equal:
@@ -96,7 +96,7 @@ not ok 4 - \#4084 Istanbul final and NYC counters count unique lines and individ
actual: false
operator: 'strictEqual'
stack: |-
TestContext.<anonymous> (/home/ruv/work/ruflo-fixes-20261012/tests/regression/oct12-coverage.test.cjs:41:14)
TestContext.<anonymous> (<repo>/tests/regression/oct12-coverage.test.cjs:41:14)
Test.runInAsyncScope (node:async_hooks:206:9)
Test.run (node:internal/test_runner/test:796:25)
Test.processPendingSubtests (node:internal/test_runner/test:526:18)
@@ -109,7 +109,7 @@ not ok 4 - \#4084 Istanbul final and NYC counters count unique lines and individ
not ok 5 - empty or malformed reports do not hide a valid fallback
---
duration_ms: 1.672041
location: '/home/ruv/work/ruflo-fixes-20261012/tests/regression/oct12-coverage.test.cjs:48:1'
location: '<repo>/tests/regression/oct12-coverage.test.cjs:48:1'
failureType: 'testCodeFailure'
error: |-
Expected values to be strictly equal:
@@ -124,7 +124,7 @@ not ok 5 - empty or malformed reports do not hide a valid fallback
actual: 'coverage/coverage-summary.json'
operator: 'strictEqual'
stack: |-
TestContext.<anonymous> (/home/ruv/work/ruflo-fixes-20261012/tests/regression/oct12-coverage.test.cjs:55:12)
TestContext.<anonymous> (<repo>/tests/regression/oct12-coverage.test.cjs:55:12)
Test.runInAsyncScope (node:async_hooks:206:9)
Test.run (node:internal/test_runner/test:796:25)
Test.processPendingSubtests (node:internal/test_runner/test:526:18)
@@ -28,7 +28,7 @@ ok 5 - empty or malformed reports do not hide a valid fallback
not ok 6 - Istanbul empty-file Unknown sentinel yields numeric 100% in totals and entries
---
duration_ms: 3.057651
location: '/home/ruv/work/ruflo-fixes-20261012/tests/regression/oct12-coverage.test.cjs:64:1'
location: '<repo>/tests/regression/oct12-coverage.test.cjs:64:1'
failureType: 'testCodeFailure'
error: |-
Expected values to be strictly equal:
@@ -41,7 +41,7 @@ not ok 6 - Istanbul empty-file Unknown sentinel yields numeric 100% in totals an
actual: 'Unknown'
operator: 'strictEqual'
stack: |-
TestContext.<anonymous> (/home/ruv/work/ruflo-fixes-20261012/tests/regression/oct12-coverage.test.cjs:68:10)
TestContext.<anonymous> (<repo>/tests/regression/oct12-coverage.test.cjs:68:10)
Test.runInAsyncScope (node:async_hooks:206:9)
Test.run (node:internal/test_runner/test:796:25)
Test.processPendingSubtests (node:internal/test_runner/test:526:18)
@@ -53,7 +53,7 @@ not ok 6 - Istanbul empty-file Unknown sentinel yields numeric 100% in totals an
not ok 7 - legacy NYC summary reports remain readable
---
duration_ms: 1.124631
location: '/home/ruv/work/ruflo-fixes-20261012/tests/regression/oct12-coverage.test.cjs:71:1'
location: '<repo>/tests/regression/oct12-coverage.test.cjs:71:1'
failureType: 'testCodeFailure'
error: |-
Expected values to be strictly equal:
@@ -66,7 +66,7 @@ not ok 7 - legacy NYC summary reports remain readable
actual: false
operator: 'strictEqual'
stack: |-
TestContext.<anonymous> (/home/ruv/work/ruflo-fixes-20261012/tests/regression/oct12-coverage.test.cjs:73:10)
TestContext.<anonymous> (<repo>/tests/regression/oct12-coverage.test.cjs:73:10)
Test.runInAsyncScope (node:async_hooks:206:9)
Test.run (node:internal/test_runner/test:796:25)
Test.processPendingSubtests (node:internal/test_runner/test:526:18)
@@ -1,5 +1,5 @@
RUN v4.1.0 /home/ruv/work/ruflo-fixes-20261012
RUN v4.1.0 <repo>
❯ v3/@claude-flow/cli/__tests__/hooks-coverage-disk.test.ts (3 tests | 3 failed) 25ms
× does not route or suggest tests for empty instrumented files 18ms
@@ -1,5 +1,5 @@
RUN v4.1.0 /home/ruv/work/ruflo-fixes-20261012
RUN v4.1.0 <repo>
Test Files 2 passed (2)
@@ -38,7 +38,7 @@ ok 7 - legacy NYC summary reports remain readable
not ok 8 - pct-only files retain their percentage but unknown aggregate counts stay conservative
---
duration_ms: 2.672092
location: '/home/ruv/work/ruflo-fixes-20261012/tests/regression/oct12-coverage.test.cjs:75:1'
location: '<repo>/tests/regression/oct12-coverage.test.cjs:75:1'
failureType: 'testCodeFailure'
error: |-
Expected values to be strictly equal:
@@ -51,7 +51,7 @@ not ok 8 - pct-only files retain their percentage but unknown aggregate counts s
actual: 100
operator: 'strictEqual'
stack: |-
TestContext.<anonymous> (/home/ruv/work/ruflo-fixes-20261012/tests/regression/oct12-coverage.test.cjs:78:69)
TestContext.<anonymous> (<repo>/tests/regression/oct12-coverage.test.cjs:78:69)
Test.runInAsyncScope (node:async_hooks:206:9)
Test.run (node:internal/test_runner/test:796:25)
Test.processPendingSubtests (node:internal/test_runner/test:526:18)
@@ -63,7 +63,7 @@ not ok 8 - pct-only files retain their percentage but unknown aggregate counts s
not ok 9 - mixed counted and uncounted files cannot claim a fully covered aggregate
---
duration_ms: 1.4818
location: '/home/ruv/work/ruflo-fixes-20261012/tests/regression/oct12-coverage.test.cjs:81:1'
location: '<repo>/tests/regression/oct12-coverage.test.cjs:81:1'
failureType: 'testCodeFailure'
error: |-
Expected values to be strictly equal:
@@ -76,7 +76,7 @@ not ok 9 - mixed counted and uncounted files cannot claim a fully covered aggreg
actual: 100
operator: 'strictEqual'
stack: |-
TestContext.<anonymous> (/home/ruv/work/ruflo-fixes-20261012/tests/regression/oct12-coverage.test.cjs:84:12)
TestContext.<anonymous> (<repo>/tests/regression/oct12-coverage.test.cjs:84:12)
Test.runInAsyncScope (node:async_hooks:206:9)
Test.run (node:internal/test_runner/test:796:25)
Test.processPendingSubtests (node:internal/test_runner/test:526:18)
@@ -93,7 +93,7 @@ ok 10 - valid supplied aggregate percentages including zero take precedence
not ok 11 - incomplete or invalid counts do not manufacture a percentage
---
duration_ms: 7.111804
location: '/home/ruv/work/ruflo-fixes-20261012/tests/regression/oct12-coverage.test.cjs:93:1'
location: '<repo>/tests/regression/oct12-coverage.test.cjs:93:1'
failureType: 'testCodeFailure'
error: |-
Expected values to be strictly equal:
@@ -106,7 +106,7 @@ not ok 11 - incomplete or invalid counts do not manufacture a percentage
actual: 100
operator: 'strictEqual'
stack: |-
TestContext.<anonymous> (/home/ruv/work/ruflo-fixes-20261012/tests/regression/oct12-coverage.test.cjs:97:12)
TestContext.<anonymous> (<repo>/tests/regression/oct12-coverage.test.cjs:97:12)
Test.runInAsyncScope (node:async_hooks:206:9)
Test.run (node:internal/test_runner/test:796:25)
Test.processPendingSubtests (node:internal/test_runner/test:526:18)
@@ -3,7 +3,7 @@ TAP version 13
not ok 1 - \#4086 status enumerates all keys and retrieves exact current values
---
duration_ms: 3.527511
location: '/home/ruv/work/ruflo-fixes-20261012/tests/regression/oct12-sparc.test.cjs:8:1'
location: '<repo>/tests/regression/oct12-sparc.test.cjs:8:1'
failureType: 'testCodeFailure'
error: |-
The input did not match the regular expression /memory_list/. Input:
@@ -40,7 +40,7 @@ not ok 1 - \#4086 status enumerates all keys and retrieves exact current values
operator: 'match'
stack: |-
TestContext.<anonymous> (/home/ruv/work/ruflo-fixes-20261012/tests/regression/oct12-sparc.test.cjs:10:10)
TestContext.<anonymous> (<repo>/tests/regression/oct12-sparc.test.cjs:10:10)
Test.runInAsyncScope (node:async_hooks:206:9)
Test.run (node:internal/test_runner/test:796:25)
Test.processPendingSubtests (node:internal/test_runner/test:526:18)
@@ -53,7 +53,7 @@ not ok 1 - \#4086 status enumerates all keys and retrieves exact current values
not ok 2 - \#4087 every explicit phase agent resolves to a shipped plugin agent
---
duration_ms: 0.52273
location: '/home/ruv/work/ruflo-fixes-20261012/tests/regression/oct12-sparc.test.cjs:15:1'
location: '<repo>/tests/regression/oct12-sparc.test.cjs:15:1'
failureType: 'testCodeFailure'
error: |-
The input did not match the regular expression /^ruflo-[a-z-]+:[a-z-]+$/. Input:
@@ -66,7 +66,7 @@ not ok 2 - \#4087 every explicit phase agent resolves to a shipped plugin agent
actual: 'researcher'
operator: 'match'
stack: |-
TestContext.<anonymous> (/home/ruv/work/ruflo-fixes-20261012/tests/regression/oct12-sparc.test.cjs:19:12)
TestContext.<anonymous> (<repo>/tests/regression/oct12-sparc.test.cjs:19:12)
Test.runInAsyncScope (node:async_hooks:206:9)
Test.run (node:internal/test_runner/test:796:25)
Test.processPendingSubtests (node:internal/test_runner/test:526:18)
@@ -78,7 +78,7 @@ not ok 2 - \#4087 every explicit phase agent resolves to a shipped plugin agent
not ok 3 - \#4088 SPARC command references resolve to the shipped command filename
---
duration_ms: 0.52056
location: '/home/ruv/work/ruflo-fixes-20261012/tests/regression/oct12-sparc.test.cjs:25:1'
location: '<repo>/tests/regression/oct12-sparc.test.cjs:25:1'
failureType: 'testCodeFailure'
error: 'plugins/ruflo-sparc/commands/ruflo-sparc.md'
code: 'ERR_ASSERTION'
@@ -183,7 +183,7 @@ not ok 3 - \#4088 SPARC command references resolve to the shipped command filena
operator: 'doesNotMatch'
stack: |-
TestContext.<anonymous> (/home/ruv/work/ruflo-fixes-20261012/tests/regression/oct12-sparc.test.cjs:29:12)
TestContext.<anonymous> (<repo>/tests/regression/oct12-sparc.test.cjs:29:12)
Test.runInAsyncScope (node:async_hooks:206:9)
Test.run (node:internal/test_runner/test:796:25)
Test.processPendingSubtests (node:internal/test_runner/test:526:18)
@@ -8,7 +8,7 @@ ok 1 - \#4086 status enumerates all keys and retrieves exact current values
not ok 2 - \#4087 every explicit phase agent resolves to a shipped plugin agent
---
duration_ms: 3.304492
location: '/home/ruv/work/ruflo-fixes-20261012/tests/regression/oct12-sparc.test.cjs:15:1'
location: '<repo>/tests/regression/oct12-sparc.test.cjs:15:1'
failureType: 'testCodeFailure'
error: |-
Expected values to be strictly deep-equal:
@@ -42,7 +42,7 @@ not ok 2 - \#4087 every explicit phase agent resolves to a shipped plugin agent
5: 'ruflo-core:reviewer'
operator: 'deepStrictEqual'
stack: |-
TestContext.<anonymous> (/home/ruv/work/ruflo-fixes-20261012/tests/regression/oct12-sparc.test.cjs:17:10)
TestContext.<anonymous> (<repo>/tests/regression/oct12-sparc.test.cjs:17:10)
Test.runInAsyncScope (node:async_hooks:206:9)
Test.run (node:internal/test_runner/test:796:25)
Test.processPendingSubtests (node:internal/test_runner/test:526:18)
@@ -18,7 +18,7 @@ ok 3 - \#4088 SPARC command references resolve to the shipped command filename
not ok 4 - \#4086 initialize active state and timestamp every phase/gate state write
---
duration_ms: 2.341811
location: '/home/ruv/work/ruflo-fixes-20261012/plugins/ruflo-sparc/tests/contracts.regression.cjs:41:1'
location: '<repo>/plugins/ruflo-sparc/tests/contracts.regression.cjs:41:1'
failureType: 'testCodeFailure'
error: |-
The input did not match the regular expression /"status": "active"/. Input:
@@ -43,7 +43,7 @@ not ok 4 - \#4086 initialize active state and timestamp every phase/gate state w
operator: 'match'
stack: |-
TestContext.<anonymous> (/home/ruv/work/ruflo-fixes-20261012/plugins/ruflo-sparc/tests/contracts.regression.cjs:42:10)
TestContext.<anonymous> (<repo>/plugins/ruflo-sparc/tests/contracts.regression.cjs:42:10)
Test.runInAsyncScope (node:async_hooks:206:9)
Test.run (node:internal/test_runner/test:796:25)
Test.processPendingSubtests (node:internal/test_runner/test:526:18)
@@ -55,7 +55,7 @@ not ok 4 - \#4086 initialize active state and timestamp every phase/gate state w
not ok 5 - \#4086 active status filters explicit completion and orders legacy timestamps
---
duration_ms: 0.4607
location: '/home/ruv/work/ruflo-fixes-20261012/plugins/ruflo-sparc/tests/contracts.regression.cjs:51:1'
location: '<repo>/plugins/ruflo-sparc/tests/contracts.regression.cjs:51:1'
failureType: 'testCodeFailure'
error: |-
The input did not match the regular expression /Exclude.*status === "complete"/. Input:
@@ -82,7 +82,7 @@ not ok 5 - \#4086 active status filters explicit completion and orders legacy ti
operator: 'match'
stack: |-
TestContext.<anonymous> (/home/ruv/work/ruflo-fixes-20261012/plugins/ruflo-sparc/tests/contracts.regression.cjs:53:10)
TestContext.<anonymous> (<repo>/plugins/ruflo-sparc/tests/contracts.regression.cjs:53:10)
Test.runInAsyncScope (node:async_hooks:206:9)
Test.run (node:internal/test_runner/test:796:25)
Test.processPendingSubtests (node:internal/test_runner/test:526:18)
@@ -94,7 +94,7 @@ not ok 5 - \#4086 active status filters explicit completion and orders legacy ti
not ok 6 - \#4086 advance closes phase five only after its gate and refuses completed records
---
duration_ms: 0.41762
location: '/home/ruv/work/ruflo-fixes-20261012/plugins/ruflo-sparc/tests/contracts.regression.cjs:59:1'
location: '<repo>/plugins/ruflo-sparc/tests/contracts.regression.cjs:59:1'
failureType: 'testCodeFailure'
error: |-
The input did not match the regular expression /status === "complete".*refuse/. Input:
@@ -145,7 +145,7 @@ not ok 6 - \#4086 advance closes phase five only after its gate and refuses comp
operator: 'match'
stack: |-
TestContext.<anonymous> (/home/ruv/work/ruflo-fixes-20261012/plugins/ruflo-sparc/tests/contracts.regression.cjs:61:10)
TestContext.<anonymous> (<repo>/plugins/ruflo-sparc/tests/contracts.regression.cjs:61:10)
Test.runInAsyncScope (node:async_hooks:206:9)
Test.run (node:internal/test_runner/test:796:25)
Test.processPendingSubtests (node:internal/test_runner/test:526:18)
@@ -157,7 +157,7 @@ not ok 6 - \#4086 advance closes phase five only after its gate and refuses comp
not ok 7 - \#4086 refine closes exact state once only after final gate evidence passes
---
duration_ms: 0.80853
location: '/home/ruv/work/ruflo-fixes-20261012/plugins/ruflo-sparc/tests/contracts.regression.cjs:69:1'
location: '<repo>/plugins/ruflo-sparc/tests/contracts.regression.cjs:69:1'
failureType: 'testCodeFailure'
error: |-
The input did not match the regular expression /final gate evidence.*passes/. Input:
@@ -430,7 +430,7 @@ not ok 7 - \#4086 refine closes exact state once only after final gate evidence
operator: 'match'
stack: |-
TestContext.<anonymous> (/home/ruv/work/ruflo-fixes-20261012/plugins/ruflo-sparc/tests/contracts.regression.cjs:71:10)
TestContext.<anonymous> (<repo>/plugins/ruflo-sparc/tests/contracts.regression.cjs:71:10)
Test.runInAsyncScope (node:async_hooks:206:9)
Test.run (node:internal/test_runner/test:796:25)
Test.processPendingSubtests (node:internal/test_runner/test:526:18)
@@ -13,9 +13,9 @@ ok 2 - \#4087 every explicit phase agent resolves to a shipped plugin agent
not ok 3 - \#4088 SPARC command references resolve to the shipped command filename
---
duration_ms: 1.749161
location: '/home/ruv/work/ruflo-fixes-20261012/plugins/ruflo-sparc/tests/contracts.regression.cjs:27:1'
location: '<repo>/plugins/ruflo-sparc/tests/contracts.regression.cjs:27:1'
failureType: 'testCodeFailure'
error: '/home/ruv/work/ruflo-fixes-20261012/plugins/ruflo-sparc/README.md'
error: '<repo>/plugins/ruflo-sparc/README.md'
code: 'ERR_ASSERTION'
name: 'AssertionError'
expected:
@@ -182,7 +182,7 @@ not ok 3 - \#4088 SPARC command references resolve to the shipped command filena
operator: 'doesNotMatch'
stack: |-
TestContext.<anonymous> (/home/ruv/work/ruflo-fixes-20261012/plugins/ruflo-sparc/tests/contracts.regression.cjs:32:12)
TestContext.<anonymous> (<repo>/plugins/ruflo-sparc/tests/contracts.regression.cjs:32:12)
Test.runInAsyncScope (node:async_hooks:206:9)
Test.run (node:internal/test_runner/test:796:25)
Test.processPendingSubtests (node:internal/test_runner/test:526:18)
@@ -8,7 +8,7 @@ ok 1 - \#4085 green target and regression records observed outcome
not ok 2 - \#4085 target still red records observed outcome
---
duration_ms: 2.004941
location: '/home/ruv/work/ruflo-fixes-20261012/tests/regression/oct12-tdd-workflow.test.cjs:19:48'
location: '<repo>/tests/regression/oct12-tdd-workflow.test.cjs:19:48'
failureType: 'testCodeFailure'
error: |-
Expected values to be strictly equal:
@@ -21,7 +21,7 @@ not ok 2 - \#4085 target still red records observed outcome
actual: true
operator: 'strictEqual'
stack: |-
TestContext.<anonymous> (/home/ruv/work/ruflo-fixes-20261012/tests/regression/oct12-tdd-workflow.test.cjs:26:30)
TestContext.<anonymous> (<repo>/tests/regression/oct12-tdd-workflow.test.cjs:26:30)
Test.runInAsyncScope (node:async_hooks:206:9)
Test.run (node:internal/test_runner/test:796:25)
Test.processPendingSubtests (node:internal/test_runner/test:526:18)
@@ -33,7 +33,7 @@ not ok 2 - \#4085 target still red records observed outcome
not ok 3 - \#4085 regression broken records observed outcome
---
duration_ms: 0.74057
location: '/home/ruv/work/ruflo-fixes-20261012/tests/regression/oct12-tdd-workflow.test.cjs:19:48'
location: '<repo>/tests/regression/oct12-tdd-workflow.test.cjs:19:48'
failureType: 'testCodeFailure'
error: |-
Expected values to be strictly equal:
@@ -46,7 +46,7 @@ not ok 3 - \#4085 regression broken records observed outcome
actual: true
operator: 'strictEqual'
stack: |-
TestContext.<anonymous> (/home/ruv/work/ruflo-fixes-20261012/tests/regression/oct12-tdd-workflow.test.cjs:26:30)
TestContext.<anonymous> (<repo>/tests/regression/oct12-tdd-workflow.test.cjs:26:30)
Test.runInAsyncScope (node:async_hooks:206:9)
Test.run (node:internal/test_runner/test:796:25)
Test.processPendingSubtests (node:internal/test_runner/test:526:18)
@@ -58,7 +58,7 @@ not ok 3 - \#4085 regression broken records observed outcome
not ok 4 - \#4085 abandoned records observed outcome
---
duration_ms: 0.801321
location: '/home/ruv/work/ruflo-fixes-20261012/tests/regression/oct12-tdd-workflow.test.cjs:19:48'
location: '<repo>/tests/regression/oct12-tdd-workflow.test.cjs:19:48'
failureType: 'testCodeFailure'
error: |-
Expected values to be strictly equal:
@@ -71,7 +71,7 @@ not ok 4 - \#4085 abandoned records observed outcome
actual: true
operator: 'strictEqual'
stack: |-
TestContext.<anonymous> (/home/ruv/work/ruflo-fixes-20261012/tests/regression/oct12-tdd-workflow.test.cjs:26:30)
TestContext.<anonymous> (<repo>/tests/regression/oct12-tdd-workflow.test.cjs:26:30)
Test.runInAsyncScope (node:async_hooks:206:9)
Test.run (node:internal/test_runner/test:796:25)
Test.processPendingSubtests (node:internal/test_runner/test:526:18)
@@ -83,7 +83,7 @@ not ok 4 - \#4085 abandoned records observed outcome
not ok 5 - \#4085 interrupted runner records observed outcome
---
duration_ms: 0.81648
location: '/home/ruv/work/ruflo-fixes-20261012/tests/regression/oct12-tdd-workflow.test.cjs:19:48'
location: '<repo>/tests/regression/oct12-tdd-workflow.test.cjs:19:48'
failureType: 'testCodeFailure'
error: |-
Expected values to be strictly equal:
@@ -96,7 +96,7 @@ not ok 5 - \#4085 interrupted runner records observed outcome
actual: true
operator: 'strictEqual'
stack: |-
TestContext.<anonymous> (/home/ruv/work/ruflo-fixes-20261012/tests/regression/oct12-tdd-workflow.test.cjs:26:30)
TestContext.<anonymous> (<repo>/tests/regression/oct12-tdd-workflow.test.cjs:26:30)
Test.runInAsyncScope (node:async_hooks:206:9)
Test.run (node:internal/test_runner/test:796:25)
Test.processPendingSubtests (node:internal/test_runner/test:526:18)
@@ -108,7 +108,7 @@ not ok 5 - \#4085 interrupted runner records observed outcome
not ok 6 - \#4085 target not run records observed outcome
---
duration_ms: 1.910411
location: '/home/ruv/work/ruflo-fixes-20261012/tests/regression/oct12-tdd-workflow.test.cjs:19:48'
location: '<repo>/tests/regression/oct12-tdd-workflow.test.cjs:19:48'
failureType: 'testCodeFailure'
error: |-
Expected values to be strictly equal:
@@ -121,7 +121,7 @@ not ok 6 - \#4085 target not run records observed outcome
actual: true
operator: 'strictEqual'
stack: |-
TestContext.<anonymous> (/home/ruv/work/ruflo-fixes-20261012/tests/regression/oct12-tdd-workflow.test.cjs:26:30)
TestContext.<anonymous> (<repo>/tests/regression/oct12-tdd-workflow.test.cjs:26:30)
Test.runInAsyncScope (node:async_hooks:206:9)
Test.run (node:internal/test_runner/test:796:25)
Test.processPendingSubtests (node:internal/test_runner/test:526:18)
@@ -133,7 +133,7 @@ not ok 6 - \#4085 target not run records observed outcome
not ok 7 - \#4085 regression not run records observed outcome
---
duration_ms: 0.765121
location: '/home/ruv/work/ruflo-fixes-20261012/tests/regression/oct12-tdd-workflow.test.cjs:19:48'
location: '<repo>/tests/regression/oct12-tdd-workflow.test.cjs:19:48'
failureType: 'testCodeFailure'
error: |-
Expected values to be strictly equal:
@@ -146,7 +146,7 @@ not ok 7 - \#4085 regression not run records observed outcome
actual: true
operator: 'strictEqual'
stack: |-
TestContext.<anonymous> (/home/ruv/work/ruflo-fixes-20261012/tests/regression/oct12-tdd-workflow.test.cjs:26:30)
TestContext.<anonymous> (<repo>/tests/regression/oct12-tdd-workflow.test.cjs:26:30)
Test.runInAsyncScope (node:async_hooks:206:9)
Test.run (node:internal/test_runner/test:796:25)
Test.processPendingSubtests (node:internal/test_runner/test:526:18)
@@ -1,7 +1,7 @@
{
"name": "ruflo-sparc",
"description": "SPARC methodology — Specification, Pseudocode, Architecture, Refinement, Completion phases with gate checks",
"version": "0.3.4",
"version": "0.3.5",
"author": {
"name": "ruvnet",
"url": "https://github.com/ruvnet"
@@ -1,7 +1,7 @@
{
"name": "ruflo-sparc",
"description": "SPARC methodology \u2014 Specification, Pseudocode, Architecture, Refinement, Completion phases with gate checks",
"version": "0.3.4",
"version": "0.3.5",
"author": {
"name": "ruvnet",
"url": "https://github.com/ruvnet"
+3
View File
@@ -2,6 +2,9 @@
Newest first. One `## <version> — <date>` heading per version, then `feat:`, `fix:`, `breaking:` and `chore:` bullets (ADR-478). Built from git history; this is the whole history.
## 0.3.5 — 2026-10-12
- fix: status lists every workflow with exact paginated reads (not a semantic top-10), completed workflows are closed (`status: "complete"`) and refuse another advance (#4086); the orchestrator and phase skills name the registered `ruflo-core:researcher`, `ruflo-goals:goal-planner`, `ruflo-swarm:architect`, `ruflo-core:coder`, `ruflo-testgen:tester` and `ruflo-core:reviewer` agents (#4087); commands are written as `/ruflo-sparc:ruflo-sparc <verb>`, the form that exists (#4088)
## 0.3.4 — 2026-10-08
- feat: native Codex hooks (`.codex-plugin`, `hooks/codex-hooks.json`, generated `codex-hook.cjs`) reusing the existing guard, screen and status functions
- fix: allow native freeform tool inputs in the Codex adapter and version the Codex hook repair
+2 -2
View File
@@ -7,9 +7,9 @@ step() { printf "→ %s ... " "$1"; }
ok() { printf "PASS\n"; PASS=$((PASS+1)); }
bad() { printf "FAIL: %s\n" "$1"; FAIL=$((FAIL+1)); }
step "1. plugin.json declares 0.3.4 with new keywords"
step "1. plugin.json declares 0.3.5 with new keywords"
v=$(grep -E '"version"' "$ROOT/.claude-plugin/plugin.json" | grep -oE '[0-9]+\.[0-9]+\.[0-9]+' | head -1)
if [[ "$v" != "0.3.4" ]]; then bad "expected 0.3.4, got '$v'"; else
if [[ "$v" != "0.3.5" ]]; then bad "expected 0.3.5, got '$v'"; else
miss=""
for k in mcp phase-gates quality-gates; do
grep -q "\"$k\"" "$ROOT/.claude-plugin/plugin.json" || miss="$miss $k"
@@ -1,7 +1,7 @@
{
"name": "ruflo-testgen",
"description": "Test gap detection, coverage analysis, and automated test generation — drives the testgaps background worker via hooks_worker-dispatch; SPARC Refinement-phase canonical owner",
"version": "0.3.2",
"version": "0.3.3",
"author": {
"name": "ruvnet",
"url": "https://github.com/ruvnet"
+3
View File
@@ -2,6 +2,9 @@
Newest first. One `## <version> — <date>` heading per version, then `feat:`, `fix:`, `breaking:` and `chore:` bullets (ADR-478). Built from git history; this is the whole history.
## 0.3.3 — 2026-10-12
- fix: tdd-workflow reports the observed validation outcome to `hooks_post-task` instead of a literal `success: true` (#4085)
## 0.3.2 — 2026-10-11
- fix: tdd-repair now enforces that the failing test is not edited (original bytes restored, attempt scored failed with `test-file-modified`) instead of only asking in the prompt, with a node:test; docs no longer claim Bash is a sandbox with no network or arbitrary writes
- fix: testgen command put user text inside double quotes in shell commands; test-gaps used a `--limit` flag `coverage-gaps` does not have
+2 -2
View File
@@ -7,9 +7,9 @@ step() { printf "→ %s ... " "$1"; }
ok() { printf "PASS\n"; PASS=$((PASS+1)); }
bad() { printf "FAIL: %s\n" "$1"; FAIL=$((FAIL+1)); }
step "1. plugin.json declares 0.3.2 with new keywords"
step "1. plugin.json declares 0.3.3 with new keywords"
v=$(grep -E '"version"' "$ROOT/.claude-plugin/plugin.json" | grep -oE '[0-9]+\.[0-9]+\.[0-9]+' | head -1)
if [[ "$v" != "0.3.2" ]]; then bad "expected 0.3.2, got '$v'"; else
if [[ "$v" != "0.3.3" ]]; then bad "expected 0.3.3, got '$v'"; else
miss=""
for k in mcp tdd-london-school coverage-routing; do
grep -q "\"$k\"" "$ROOT/.claude-plugin/plugin.json" || miss="$miss $k"
+1
View File
@@ -95,3 +95,4 @@ plugins/ruflo-mods/tests/protector.test.ts
plugins/ruflo-mods/tests/selfcheck.test.ts
plugins/ruflo-testgen/scripts/tdd-repair/tdd-repair.test.mjs
plugins/ruflo-core/scripts/command-recording-switch.test.cjs
tests/regression/oct12-coverage.test.cjs
@@ -67,4 +67,19 @@ describe('coverage hooks disk integration (#4082–#4084)', () => {
}
expect(callMCPTool).not.toHaveBeenCalled();
});
it("clamps impossible LCOV counts so a corrupt report cannot exceed 100% or go negative", async () => {
writeFileSync("coverage/lcov.info", "SF:over.ts\nLF:10\nLH:99\nBRF:4\nBRH:-3\nend_of_record\n");
const gaps = await run("coverage-gaps");
const summary = (gaps.data as any).summary;
expect(summary.overallLineCoverage).toBe(100);
expect(summary.overallBranchCoverage).toBe(0);
});
it("ignores a coverage report larger than the size cap instead of loading it into memory", async () => {
const valid = "SF:big.ts\nLF:10\nLH:10\nend_of_record\n";
writeFileSync("coverage/lcov.info", Buffer.concat([Buffer.from(valid), Buffer.alloc(65 * 1024 * 1024, 0x20)]));
writeFileSync("coverage/coverage-final.json", JSON.stringify({ "src/x.ts": {
s: { 0: 1 }, f: {}, b: {}, statementMap: { 0: { start: { line: 1 } } } } }));
const gaps = await run("coverage-gaps");
expect((gaps.data as any).source).toBe("coverage/coverage-final.json");
});
});
@@ -1,6 +1,20 @@
import { existsSync, readFileSync } from 'node:fs';
import { readFileSync, statSync } from 'node:fs';
import { join } from 'node:path';
/** Coverage reports are build output the project controls: refuse anything large enough to stall or exhaust the process. */
const MAX_REPORT_BYTES = 64 * 1024 * 1024;
/** The file's text, or undefined when it is missing, not a regular file, unreadable, or over the size cap. */
function readReport(path: string): string | undefined {
try {
const stat = statSync(path);
if (!stat.isFile() || stat.size > MAX_REPORT_BYTES) return undefined;
return readFileSync(path, 'utf-8');
} catch {
return undefined;
}
}
interface CoverageFileEntry {
filePath: string;
lines: number;
@@ -40,10 +54,10 @@ export function readCoverageFromDisk(): CoverageData {
// 1. Try coverage-summary.json (Jest/Istanbul)
for (const relPath of ['coverage/coverage-summary.json', 'coverage-summary.json']) {
const summaryPath = join(cwd, relPath);
if (existsSync(summaryPath)) {
const text = readReport(join(cwd, relPath));
if (text !== undefined) {
try {
const raw = JSON.parse(readFileSync(summaryPath, 'utf-8'));
const raw = JSON.parse(text);
const report = parseCoverageSummaryJson(raw, relPath);
if (report.found) return report;
} catch {
@@ -54,10 +68,9 @@ export function readCoverageFromDisk(): CoverageData {
// 2. Try lcov.info
for (const relPath of ['coverage/lcov.info', 'lcov.info']) {
const lcovPath = join(cwd, relPath);
if (existsSync(lcovPath)) {
const raw = readReport(join(cwd, relPath));
if (raw !== undefined) {
try {
const raw = readFileSync(lcovPath, 'utf-8');
const report = parseLcovInfo(raw, relPath);
if (report.found) return report;
} catch {
@@ -68,8 +81,10 @@ export function readCoverageFromDisk(): CoverageData {
// Istanbul's raw counter map (Jest, Vitest, nyc).
for (const relPath of ['coverage/coverage-final.json', 'coverage-final.json', '.nyc_output/out.json']) {
const text = readReport(join(cwd, relPath));
if (text === undefined) continue;
try {
const raw = JSON.parse(readFileSync(join(cwd, relPath), 'utf-8'));
const raw = JSON.parse(text);
const report = parseIstanbulCoverage(raw, relPath);
if (report.found) return report;
const legacy = parseCoverageSummaryJson(raw, relPath);
@@ -140,6 +155,10 @@ function parseLcovInfo(raw: string, source: string): CoverageData {
let totalLH = 0, totalLF = 0, totalBH = 0, totalBF = 0, totalFH = 0, totalFF = 0;
const flushRecord = () => {
if (currentFile) {
// A corrupt record cannot report more hits than lines, or a negative count.
linesHit = Math.min(linesHit, linesFound);
branchesHit = Math.min(branchesHit, branchesFound);
functionsHit = Math.min(functionsHit, functionsFound);
totalLH += linesHit; totalLF += linesFound;
totalBH += branchesHit; totalBF += branchesFound;
totalFH += functionsHit; totalFF += functionsFound;
@@ -162,17 +181,17 @@ function parseLcovInfo(raw: string, source: string): CoverageData {
branchesHit = 0; branchesFound = 0;
functionsHit = 0; functionsFound = 0;
} else if (trimmed.startsWith('LH:')) {
linesHit = parseInt(trimmed.slice(3), 10) || 0;
linesHit = count(trimmed.slice(3));
} else if (trimmed.startsWith('LF:')) {
linesFound = parseInt(trimmed.slice(3), 10) || 0;
linesFound = count(trimmed.slice(3));
} else if (trimmed.startsWith('BRH:')) {
branchesHit = parseInt(trimmed.slice(4), 10) || 0;
branchesHit = count(trimmed.slice(4));
} else if (trimmed.startsWith('BRF:')) {
branchesFound = parseInt(trimmed.slice(4), 10) || 0;
branchesFound = count(trimmed.slice(4));
} else if (trimmed.startsWith('FNH:')) {
functionsHit = parseInt(trimmed.slice(4), 10) || 0;
functionsHit = count(trimmed.slice(4));
} else if (trimmed.startsWith('FNF:')) {
functionsFound = parseInt(trimmed.slice(4), 10) || 0;
functionsFound = count(trimmed.slice(4));
} else if (trimmed === 'end_of_record') {
flushRecord();
currentFile = '';
@@ -197,6 +216,11 @@ function parseLcovInfo(raw: string, source: string): CoverageData {
}
/** A non-negative integer count; anything else in a report line is treated as 0. */
function count(text: string): number {
const n = parseInt(text, 10);
return Number.isFinite(n) && n > 0 ? n : 0;
}
type Metric = { total?: number; covered?: number; pct?: number | string };
function ratio(covered: number, total: number): number {
return total > 0 ? covered / total * 100 : 100;