mirror of
https://github.com/ruvnet/ruflo.git
synced 2026-10-23 03:47:00 +09:00
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:
1 parent
6fe5706dfb
commit
b4cbd4be9f
21 files changed
+139
-82
No files matched your search
@@ -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"
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in new issue
Block a user