specrails-core 6.2.1 → 6.2.2

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,7 +3,7 @@ import { contentDigest } from '../canonical-json.js';
3
3
  import { advisoryMemory } from './project-memory.js';
4
4
  import { executeVerification, validateVerificationRequest } from '../../../pipeline/pipeline-state.js';
5
5
  import { withScopeDefault } from '../../change-scope.js';
6
- import { verificationFailureSummary } from '../../verification-diagnostics.js';
6
+ import { verificationDiagnosticPriority, verificationFailureSummary } from '../../verification-diagnostics.js';
7
7
  import { boundedText, json, paramsSchema, positiveInteger } from './shared.js';
8
8
  /** Keep real subprocess diagnostics in committed outputs for subsequent agents.
9
9
  * The full command evidence remains in the receipt; prioritize failed checks
@@ -17,15 +17,23 @@ function verificationDiagnostics(receipt) {
17
17
  const limit = Math.min(8_000, remaining);
18
18
  const source = stripVTControlCharacters([command.stdout ?? '', command.stderr ?? '', command.output].join('\n'));
19
19
  const lines = source.split('\n');
20
- const failures = [];
21
- let used = 0;
22
- for (let i = 0; command.exitCode !== 0 && i < lines.length && used < 6_000; i++) {
23
- if (!/^\s*(?:not ok\b|[✖✗]\s|test at\b|FAIL\b|Error:|AssertionError\b|error:)/.test(lines[i]))
20
+ // Reserve the bounded facts before contextual blocks: a source dump or a
21
+ // long warning next to the first failure must not hide later diagnostics.
22
+ const failures = command.exitCode !== 0 ? verificationFailureSummary(command) : [];
23
+ let used = failures.reduce((total, line) => total + line.length + 1, 0);
24
+ const anchors = command.exitCode !== 0 ? lines.map((line, index) => ({ line, index, priority: verificationDiagnosticPriority(line) }))
25
+ .filter((anchor) => anchor.priority !== undefined)
26
+ .sort((a, b) => a.priority - b.priority || a.index - b.index) : [];
27
+ const selected = new Set();
28
+ for (const { line, index } of anchors) {
29
+ if (used >= 6_000)
30
+ break;
31
+ if (selected.has(line.trim()))
24
32
  continue;
25
- const excerpt = lines.slice(Math.max(0, i - 2), i + 28).join('\n').slice(0, 6_000 - used);
33
+ selected.add(line.trim());
34
+ const excerpt = lines.slice(Math.max(0, index - 2), index + 28).join('\n').slice(0, 6_000 - used);
26
35
  failures.push(excerpt);
27
- used += excerpt.length;
28
- i += 27;
36
+ used += excerpt.length + 1;
29
37
  }
30
38
  const failureText = failures.join('\n').slice(0, Math.min(6_000, limit));
31
39
  const tailBudget = Math.max(0, limit - failureText.length - (failureText ? 1 : 0));
@@ -1,4 +1,8 @@
1
1
  import type { CommandReceipt } from '../pipeline/pipeline-state.js';
2
+ /** Shared ordering for summary facts and contextual excerpts. Input is an
3
+ * ANSI-normalized output line; ordinary warnings and quoted source are not
4
+ * failure anchors. Lower ranks reserve space for the actual error first. */
5
+ export declare function verificationDiagnosticPriority(raw: string): number | undefined;
2
6
  /** Exact subprocess facts, not an AI diagnosis or a waiver of the failed check.
3
7
  * Separate them from source dumps, reserving space for each kind of fact. */
4
8
  export declare function verificationFailureSummary(command: Pick<CommandReceipt, 'stdout' | 'stderr' | 'output'>): string[];
@@ -1,24 +1,38 @@
1
1
  import { stripVTControlCharacters } from 'node:util';
2
+ /** Shared ordering for summary facts and contextual excerpts. Input is an
3
+ * ANSI-normalized output line; ordinary warnings and quoted source are not
4
+ * failure anchors. Lower ranks reserve space for the actual error first. */
5
+ export function verificationDiagnosticPriority(raw) {
6
+ const line = raw.trim();
7
+ if (/node:internal\//.test(line) || /^[✖✗]\s+failing tests:/.test(line)
8
+ || /^(?:[✖✗]\s+)?(?:\d+\s+problems?\s+\(\s*)?0 errors?(?:,\s*\d+ warnings?)?\)?$/.test(line))
9
+ return undefined;
10
+ const compiler = /^(?!['"`]|(?:actual|expected|source):).+(?:\(\d+,\d+\)|:\d+(?::\d+)?)(?::|\s+-)?\s+(?:fatal\s+)?error\b/.test(line)
11
+ || /^(?:fatal\s+)?error(?:\s+[A-Z][A-Z0-9]*\d+)?\s*:/.test(line);
12
+ if (compiler || /^(?:AssertionError\b|\w*Error(?:\s+\[[^\]]+\])?:|code:)/.test(line))
13
+ return 0;
14
+ if (/^(?:not ok\b|[✖✗]\s|FAIL\b)/.test(line))
15
+ return 1;
16
+ if (/^expected:/.test(line))
17
+ return 2;
18
+ if (/^(?:test at\b|location:|at .+:\d+(?::\d+)?\)?$)/.test(line))
19
+ return 3;
20
+ return undefined;
21
+ }
2
22
  /** Exact subprocess facts, not an AI diagnosis or a waiver of the failed check.
3
23
  * Separate them from source dumps, reserving space for each kind of fact. */
4
24
  export function verificationFailureSummary(command) {
5
25
  const source = stripVTControlCharacters([command.stdout ?? '', command.stderr ?? '', command.output].join('\n'));
6
26
  const lines = source.split('\n').map(line => line.trim());
7
- const groups = [
8
- /^(?:not ok\b|[✖✗]\s|FAIL\b)/,
9
- /^(?:AssertionError\b|\w*Error:|error:|code:)/,
10
- /^expected:/,
11
- /^(?:test at\b|location:|at .+:\d+(?::\d+)?\)?$)/,
12
- ];
13
27
  const selected = new Set();
14
28
  const facts = [];
15
- for (const pattern of groups) {
29
+ for (const priority of [0, 1, 2, 3]) {
16
30
  let remaining = 750;
17
31
  let count = 0;
18
32
  for (const line of lines) {
19
33
  if (remaining <= 0 || count >= 3)
20
34
  break;
21
- if (!pattern.test(line) || /node:internal\//.test(line) || /^[✖✗]\s+failing tests:/.test(line) || selected.has(line))
35
+ if (verificationDiagnosticPriority(line) !== priority || selected.has(line))
22
36
  continue;
23
37
  const bounded = line.slice(0, Math.min(512, remaining - 1));
24
38
  if (!bounded)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "specrails-core",
3
- "version": "6.2.1",
3
+ "version": "6.2.2",
4
4
  "description": "Agent workflow engine for specrails-desktop: provider-independent installer and programmatic agent runtime for Claude Code and Codex",
5
5
  "type": "module",
6
6
  "exports": {