specrails-core 5.5.0 → 5.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -3,6 +3,6 @@ export interface ExitHonestyFinding {
3
3
  failures: number | null;
4
4
  sample: string;
5
5
  }
6
- /** A failure count > 0 in a summary line, or a failure-marker line, in the output of a command that exited 0. */
6
+ /** A failure count in a runner summary, or a failure-marker line, despite exit 0. */
7
7
  export declare function exitCodeContradiction(exitCode: number | null, output: string): ExitHonestyFinding | null;
8
8
  export declare function exitHonestyReason(findings: ReadonlyArray<ExitHonestyFinding>): string;
@@ -1,25 +1,75 @@
1
- /** Lines that only a test runner prints when something failed. Kept narrow: a green run mentions "0 failed", never `FAIL:` / `✗` / `AssertionError` / `Error:` stack heads. */
2
- const FAILURE_LINE = /^\s*(?:FAIL(?:ED)?\b[:\s]|✗|✖|×\s|not ok\b|AssertionError\b|(?:Type|Reference|Syntax|Range)Error:)/m;
3
- const FAILED_COUNT = /\b(\d+)\s+(?:failed|failures?|failing)\b/gi;
4
- const PASS_ONLY = /\b0\s+(?:failed|failures?|failing)\b/i;
5
- /** A failure count > 0 in a summary line, or a failure-marker line, in the output of a command that exited 0. */
1
+ import { stripVTControlCharacters } from 'node:util';
2
+ // Counts belong to runner summaries, never arbitrary prose or test names.
3
+ // In particular, TAP's "# Subtest: ... non-404 failures" is not a count.
4
+ const FAILURE_LINE = /^\s*(?:FAIL(?:ED)?\b(?:[:\s]|$)|✗|✖|×\s|not ok\b)/;
5
+ const ERROR_LINE = /^\s*(?:AssertionError\b|(?:Type|Reference|Syntax|Range)Error:)/;
6
+ const FAILED_COUNT = /^(\d+)\s+(?:failed|failures?|failing)$/i;
7
+ const SUMMARY_LABEL = /^(?:(?:[\w -]*tests?|test files|test suites|suites)\s*:\s*|(?:tests?|test files|test suites|suites)\s+)(?=\d)/i;
8
+ const SUMMARY_ITEM = /\d+\s+(?:passed|passing|failed|failures?|failing|skipped|pending|todo|cancelled|total|tests?)/gi;
9
+ const TAP_FAIL = /^# fail (\d+)\s*$/;
10
+ const TAP_EXPECTED_FAILURE = /^not ok\b.*\s#\s*(?:TODO|SKIP)\b/i;
11
+ /** Parse the entire summary grammar before interpreting any number as a count. */
12
+ function failureCounts(line) {
13
+ const tap = TAP_FAIL.exec(line);
14
+ if (tap)
15
+ return [Number(tap[1])];
16
+ // Common runner suffixes: Vitest's "(5)" and Mocha's "(12ms)".
17
+ const body = line.replace(SUMMARY_LABEL, '').replace(/\s+\(\d+(?:\.\d+)?(?:ms|s)?\)$/, '');
18
+ const items = [...body.matchAll(SUMMARY_ITEM)];
19
+ if (!items.length || items[0].index !== 0)
20
+ return [];
21
+ let end = 0;
22
+ const counts = [];
23
+ for (const item of items) {
24
+ if (end && !/^(?:\s*[,|]\s*|\s+)$/.test(body.slice(end, item.index)))
25
+ return [];
26
+ const failed = FAILED_COUNT.exec(item[0]);
27
+ if (failed)
28
+ counts.push(Number(failed[1]));
29
+ end = item.index + item[0].length;
30
+ }
31
+ return end === body.length ? counts : [];
32
+ }
33
+ function completeTail(output) {
34
+ const start = Math.max(0, output.length - 16_000);
35
+ if (start === 0 || output[start - 1] === '\n')
36
+ return output.slice(start);
37
+ const newline = output.indexOf('\n', start);
38
+ return newline === -1 ? '' : output.slice(newline + 1);
39
+ }
40
+ /** A failure count in a runner summary, or a failure-marker line, despite exit 0. */
6
41
  export function exitCodeContradiction(exitCode, output) {
7
42
  if (exitCode !== 0)
8
43
  return null;
9
- const tail = output.slice(-16_000);
44
+ const clean = stripVTControlCharacters(output);
45
+ // Do not turn the middle of a truncated test name into a summary or marker.
46
+ const tail = completeTail(clean);
10
47
  let failures = null;
11
- for (const match of tail.matchAll(FAILED_COUNT)) {
12
- const n = Number(match[1]);
13
- if (Number.isFinite(n) && n > 0)
14
- failures = Math.max(failures ?? 0, n);
48
+ let countSample = '';
49
+ let marker = '';
50
+ let error = '';
51
+ let zeroSummary = false;
52
+ for (const raw of tail.split('\n')) {
53
+ const line = raw.trim();
54
+ if (!marker && FAILURE_LINE.test(line) && !TAP_EXPECTED_FAILURE.test(line))
55
+ marker = line;
56
+ if (!error && ERROR_LINE.test(line))
57
+ error = line;
58
+ for (const n of failureCounts(line)) {
59
+ if (n === 0)
60
+ zeroSummary = true;
61
+ if (Number.isFinite(n) && n > 0 && n > (failures ?? 0)) {
62
+ failures = n;
63
+ countSample = line;
64
+ }
65
+ }
15
66
  }
16
- const marker = FAILURE_LINE.exec(tail);
17
- if (failures === null && !marker)
18
- return null;
19
- if (failures === null && marker && PASS_ONLY.test(tail) && !/^\s*FAIL(?:ED)?\b[:\s]/m.test(tail))
67
+ // A green summary may accompany expected exception diagnostics, but cannot
68
+ // erase an explicit failed test or another suite's positive failure count.
69
+ const sample = marker || countSample || (!zeroSummary ? error : '');
70
+ if (!sample)
20
71
  return null;
21
- const sample = (marker ? tail.slice(marker.index, marker.index + 160).split('\n')[0] : tail.match(/^.*\b\d+\s+(?:failed|failures?|failing)\b.*$/im)?.[0]) ?? '';
22
- return { command: '', failures, sample: sample.trim() };
72
+ return { command: '', failures, sample: sample.slice(0, 160) };
23
73
  }
24
74
  export function exitHonestyReason(findings) {
25
75
  const parts = findings.map(item => `\`${item.command}\` exited 0 but its output reports ${item.failures !== null ? `${item.failures} failing test${item.failures === 1 ? '' : 's'}` : 'a failure'} (${JSON.stringify(item.sample)})`);
@@ -1 +1 @@
1
- {"version":3,"file":"exit-code-honesty.js","sourceRoot":"","sources":["../../../src/agent-runtime/compact/exit-code-honesty.ts"],"names":[],"mappings":"AAUA,+KAA+K;AAC/K,MAAM,YAAY,GAAG,qGAAqG,CAAA;AAC1H,MAAM,YAAY,GAAG,4CAA4C,CAAA;AACjE,MAAM,SAAS,GAAG,uCAAuC,CAAA;AAEzD,iHAAiH;AACjH,MAAM,UAAU,qBAAqB,CAAC,QAAuB,EAAE,MAAc;IAC3E,IAAI,QAAQ,KAAK,CAAC;QAAE,OAAO,IAAI,CAAA;IAC/B,MAAM,IAAI,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,CAAA;IAClC,IAAI,QAAQ,GAAkB,IAAI,CAAA;IAClC,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,QAAQ,CAAC,YAAY,CAAC,EAAE,CAAC;QAAC,MAAM,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;QAAC,IAAI,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC;YAAE,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,QAAQ,IAAI,CAAC,EAAE,CAAC,CAAC,CAAA;IAAC,CAAC;IACvJ,MAAM,MAAM,GAAG,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IACtC,IAAI,QAAQ,KAAK,IAAI,IAAI,CAAC,MAAM;QAAE,OAAO,IAAI,CAAA;IAC7C,IAAI,QAAQ,KAAK,IAAI,IAAI,MAAM,IAAI,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,yBAAyB,CAAC,IAAI,CAAC,IAAI,CAAC;QAAE,OAAO,IAAI,CAAA;IAC7G,MAAM,MAAM,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,KAAK,GAAG,GAAG,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,gDAAgD,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAA;IAC/J,OAAO,EAAE,OAAO,EAAE,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC,IAAI,EAAE,EAAE,CAAA;AACzD,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,QAA2C;IAC3E,MAAM,KAAK,GAAG,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,KAAK,IAAI,CAAC,OAAO,sCAAsC,IAAI,CAAC,QAAQ,KAAK,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,QAAQ,gBAAgB,IAAI,CAAC,QAAQ,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,WAAW,KAAK,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAA;IACrO,OAAO,0EAA0E,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,sLAAsL,CAAA;AACzR,CAAC"}
1
+ {"version":3,"file":"exit-code-honesty.js","sourceRoot":"","sources":["../../../src/agent-runtime/compact/exit-code-honesty.ts"],"names":[],"mappings":"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"}
@@ -118,6 +118,14 @@ Run and resume emit JSON lines: `workflow-event` (the durable ledger events), `a
118
118
 
119
119
  `runtime api` returns `{type:"runtime-api",apiVersion:1,coreVersion:"..."}` without invoking providers. Hosts can send a JSON configuration through stdin to `runtime validate --stdin` (maximum 2 MiB), avoiding temporary files and platform-specific shell quoting. It is mutually exclusive with `--config`. Use `runtime status --context <file> --compact` for process/UI integration: it retains the run and trace identities, phase status and visits, `pendingApproval`, `pendingQuestion`, usage, the completion verdict and the acceptance summary while omitting accumulated outputs, history and frozen context. Omit `--compact` for full inspection.
120
120
 
121
+ ## Verification output and correction limits
122
+
123
+ The `exit-code-honesty` guardrail catches test harnesses that print failures but exit with code 0. It recognizes complete count summaries (including TAP `# fail N`, Jest/Vitest test totals and Mocha-style counts) and explicit failure markers. Passing test names such as `rethrows non-404 failures` are descriptions, not failure counts. ANSI colors and Windows line endings are normalized; a partial line at the diagnostic tail boundary is discarded. TAP TODO/SKIP results are not treated as ordinary failed tests. A green suite does not erase another suite's explicit failure.
124
+
125
+ This is a conservative text diagnostic over the last 16,000 characters of captured output, not a universal parser for every test framework. Test commands must still propagate real failures through their exit status. When the guardrail rejects output, the log includes the matching line so the reported failure can be checked against the runner's results.
126
+
127
+ Verification failures return to the fixer. `limits.maxAttempts` bounds fixer invocations (default: 3), after which Core blocks with `Implementation correction limit reached`. An explicit resume grants a fresh budget. If the fixer repeatedly reports no defect, inspect the quoted verification evidence before resuming; rerunning an unchanged command cannot correct a diagnostic false positive.
128
+
121
129
  ## Questions and approvals
122
130
 
123
131
  The graph pauses through LangGraph interrupts; the host resumes it with the matching answer.
package/docs/ci-cd.md CHANGED
@@ -4,10 +4,11 @@ Core's release workflow publishes the **same npm tarball that passed CI**. It do
4
4
 
5
5
  ## Quality gates
6
6
 
7
- `CI` runs for branch pushes, pull requests to `main`, and manual dispatches. It has read-only repository permissions, cancels superseded runs on the same branch/PR, and has bounded job timeouts.
7
+ `CI` runs for pushes to `main`, pull requests to `main`, and manual dispatches. Feature branches are checked through their PR, avoiding two complete matrix runs for every update. The post-merge main push still runs the entire release gate. It has read-only repository permissions, cancels superseded runs on the same branch/PR, and has bounded job timeouts.
8
8
 
9
9
  - Typecheck/build on the exact supported Node minimum, **20.19.0**.
10
10
  - Full Vitest and release-guard tests on **Linux, macOS and Windows**, with **Node 20.19.0, 22 and 24**.
11
+ - Windows distributes the two slow runtime integration suites across three jobs by collected test locations; a fourth job runs every other test file. Parameterized cases stay together. The partition runner checks its selected inventory against Vitest before running, failing if any assigned test is missing or extra. Linux/macOS and coverage run the complete suite without partitioning.
11
12
  - Coverage on Node 24 with the existing configured thresholds (not lowered).
12
13
  - A checksum-verified actionlint binary validates workflow syntax, expressions and action inputs (shellcheck is not included).
13
14
  - A checksum-verified Gitleaks binary scans Git history with redacted output.
@@ -19,13 +20,15 @@ Local checks, after installing dependencies:
19
20
 
20
21
  ```sh
21
22
  npm run ci # typecheck, guard regressions, coverage, packaged-consumer smoke
22
- npm run test:scripts # hermetic release regressions only
23
+ npm run test:scripts # hermetic release and CI partition regressions
23
24
  npm run check:package # build and consumer smoke; prints its temporary artifact directory
24
25
  # To choose where the verified tarball is kept:
25
26
  node scripts/verify-package.mjs /absolute/path/to/temporary-package-output
26
27
  ```
27
28
 
28
- The package check may download the tarball's production dependencies from npm. Its generated output directory should be outside the checkout. Release-guard unit tests are hermetic and do not access npm or GitHub.
29
+ To reproduce a Windows test partition locally, run `node scripts/ci-tests.mjs runtime-1` (or `runtime-2`, `runtime-3`, `general`). Add `--list-only` to a runtime partition to verify its inventory without executing tests.
30
+
31
+ The package check reuses the npm dependency cache (including the cache populated by `npm ci` and setup-node) with `--prefer-offline`; it may download missing production dependencies from npm. The temporary consumer, user configuration and credential isolation remain in place. Its generated output directory should be outside the checkout. Release-guard unit tests are hermetic and do not access npm or GitHub.
29
32
 
30
33
  ## Automatic release
31
34
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "specrails-core",
3
- "version": "5.5.0",
3
+ "version": "5.5.1",
4
4
  "description": "Provider-independent AI agent workflow system for Claude Code, Codex, Gemini CLI, and Kimi Code",
5
5
  "type": "module",
6
6
  "exports": {
@@ -72,7 +72,7 @@
72
72
  "test:coverage": "npm run build && vitest run --coverage",
73
73
  "dogfood": "npm run build && node bin/specrails-core.mjs init --yes",
74
74
  "prepack": "npm run build",
75
- "test:scripts": "node --test scripts/release-utils.test.mjs",
75
+ "test:scripts": "node --test scripts/release-utils.test.mjs scripts/ci-tests.test.mjs",
76
76
  "check:package": "npm run build && node scripts/verify-package.mjs",
77
77
  "ci": "npm run typecheck && npm run test:scripts && npm run test:coverage && npm run check:package"
78
78
  },