@nexrall/code-core 1.4.1 → 1.4.3

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.
@@ -0,0 +1,68 @@
1
+ /**
2
+ * Claim-vs-Evidence Guard — deterministic verification-hallucination detection.
3
+ *
4
+ * THE PROBLEM (the core of "verification hallucination", unsolved by every
5
+ * frontier coding agent):
6
+ * When an agent finishes, it writes a natural-language summary. Under pressure
7
+ * to appear done, it frequently CLAIMS verification it never performed:
8
+ * "I ran the full test suite and all 42 tests pass."
9
+ * "Verified the build succeeds and the feature works correctly."
10
+ * …while in this session it ran NO test/build command at all, or the one it
11
+ * ran FAILED. The user reads the confident claim and believes the work is
12
+ * done. Prompt instructions ("don't lie") don't fix it — there is no
13
+ * structural check that a stated verification actually happened and passed.
14
+ *
15
+ * THE APPROACH (deterministic — the evidence side is machine-tracked):
16
+ * The ProgressLedger already records, from structured tool data (not model
17
+ * output), every verification command that ran this session and whether it
18
+ * PASSED or FAILED. This guard scans the agent's FINAL message for explicit
19
+ * verification claims ("tests pass", "build succeeds", "verified it works")
20
+ * and compares them against that ledger:
21
+ * - claim present + NO passing verification on record → contradiction
22
+ * - claim present + the latest matching run FAILED → contradiction
23
+ * A contradiction triggers a one-shot nudge asking the agent to either run a
24
+ * real verification and let it pass, or remove the unsupported claim. It is a
25
+ * nudge (not a hard block): the ledger only knows about recognised verify
26
+ * commands, so a legitimate manual/out-of-band check should be allowed to
27
+ * stand once the agent says so.
28
+ *
29
+ * Only the CLAIM detection is heuristic (text). The EVIDENCE is fully
30
+ * deterministic, so the guard never fabricates a contradiction out of thin
31
+ * air — it can only flag a claim that the machine record does not support.
32
+ */
33
+ /** A single verification record as kept by the ProgressLedger. */
34
+ export interface VerificationRecord {
35
+ /** The command (or tool) that ran, e.g. "npm test" / "run_api_tests". */
36
+ cmd: string;
37
+ /** true = the verification PASSED, false = it FAILED. */
38
+ ok: boolean;
39
+ /** Mutation epoch it ran at (bumped on each source write). */
40
+ epoch: number;
41
+ }
42
+ export interface ClaimEvidenceResult {
43
+ /** The agent's text contains a concrete verification claim. */
44
+ claimed: boolean;
45
+ /** The claim is NOT backed by a passing verification in the ledger. */
46
+ contradicted: boolean;
47
+ /** Short phrases from the text that read as verification claims (for the nudge). */
48
+ claimPhrases: string[];
49
+ /** Human-readable reason for the contradiction (empty when not contradicted). */
50
+ reason: string;
51
+ }
52
+ /**
53
+ * Does the agent's final text make a concrete verification claim? Returns the
54
+ * matched phrases (deduped, capped) so the nudge can quote them back. Phrases
55
+ * preceded by a hedge/conditional within the same clause are ignored.
56
+ */
57
+ export declare function detectVerificationClaims(text: string): string[];
58
+ /**
59
+ * Compare the agent's final message against the deterministic verification
60
+ * ledger. `currentEpoch` is the ledger's current mutation epoch; a passing
61
+ * verification only counts as current evidence if no source write happened
62
+ * after it (i.e. its epoch === currentEpoch) — a pass from BEFORE the latest
63
+ * edit no longer proves the current code works.
64
+ */
65
+ export declare function checkClaimEvidence(finalText: string, verifications: VerificationRecord[], currentEpoch: number): ClaimEvidenceResult;
66
+ /** Build the one-shot nudge message body for a contradicted claim. */
67
+ export declare function claimEvidenceNudgeText(result: ClaimEvidenceResult): string;
68
+ //# sourceMappingURL=claimEvidence.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claimEvidence.d.ts","sourceRoot":"","sources":["../../src/agent/claimEvidence.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AAEH,kEAAkE;AAClE,MAAM,WAAW,kBAAkB;IACjC,yEAAyE;IACzE,GAAG,EAAE,MAAM,CAAC;IACZ,yDAAyD;IACzD,EAAE,EAAE,OAAO,CAAC;IACZ,8DAA8D;IAC9D,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,mBAAmB;IAClC,+DAA+D;IAC/D,OAAO,EAAE,OAAO,CAAC;IACjB,uEAAuE;IACvE,YAAY,EAAE,OAAO,CAAC;IACtB,oFAAoF;IACpF,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,iFAAiF;IACjF,MAAM,EAAE,MAAM,CAAC;CAChB;AAiCD;;;;GAIG;AACH,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAwB/D;AAED;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAChC,SAAS,EAAE,MAAM,EACjB,aAAa,EAAE,kBAAkB,EAAE,EACnC,YAAY,EAAE,MAAM,GACnB,mBAAmB,CA4BrB;AAED,sEAAsE;AACtE,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,mBAAmB,GAAG,MAAM,CAQ1E"}
@@ -0,0 +1,146 @@
1
+ "use strict";
2
+ /**
3
+ * Claim-vs-Evidence Guard — deterministic verification-hallucination detection.
4
+ *
5
+ * THE PROBLEM (the core of "verification hallucination", unsolved by every
6
+ * frontier coding agent):
7
+ * When an agent finishes, it writes a natural-language summary. Under pressure
8
+ * to appear done, it frequently CLAIMS verification it never performed:
9
+ * "I ran the full test suite and all 42 tests pass."
10
+ * "Verified the build succeeds and the feature works correctly."
11
+ * …while in this session it ran NO test/build command at all, or the one it
12
+ * ran FAILED. The user reads the confident claim and believes the work is
13
+ * done. Prompt instructions ("don't lie") don't fix it — there is no
14
+ * structural check that a stated verification actually happened and passed.
15
+ *
16
+ * THE APPROACH (deterministic — the evidence side is machine-tracked):
17
+ * The ProgressLedger already records, from structured tool data (not model
18
+ * output), every verification command that ran this session and whether it
19
+ * PASSED or FAILED. This guard scans the agent's FINAL message for explicit
20
+ * verification claims ("tests pass", "build succeeds", "verified it works")
21
+ * and compares them against that ledger:
22
+ * - claim present + NO passing verification on record → contradiction
23
+ * - claim present + the latest matching run FAILED → contradiction
24
+ * A contradiction triggers a one-shot nudge asking the agent to either run a
25
+ * real verification and let it pass, or remove the unsupported claim. It is a
26
+ * nudge (not a hard block): the ledger only knows about recognised verify
27
+ * commands, so a legitimate manual/out-of-band check should be allowed to
28
+ * stand once the agent says so.
29
+ *
30
+ * Only the CLAIM detection is heuristic (text). The EVIDENCE is fully
31
+ * deterministic, so the guard never fabricates a contradiction out of thin
32
+ * air — it can only flag a claim that the machine record does not support.
33
+ */
34
+ Object.defineProperty(exports, "__esModule", { value: true });
35
+ exports.detectVerificationClaims = detectVerificationClaims;
36
+ exports.checkClaimEvidence = checkClaimEvidence;
37
+ exports.claimEvidenceNudgeText = claimEvidenceNudgeText;
38
+ // Verification-claim phrases. Each must assert that a check RAN and SUCCEEDED —
39
+ // not a mere intention ("you should run the tests") or a request. We require an
40
+ // outcome word (pass/succeed/green/works/confirmed) tied to a verification noun
41
+ // (test/suite/build/lint/typecheck/compile) OR a small set of standalone idioms
42
+ // ("all tests pass", "everything works", "verified"). Kept deliberately tight to
43
+ // avoid flagging hedged language ("this should work", "the tests would pass").
44
+ const CLAIM_RES = [
45
+ // "(all) tests pass / passed / are passing / pass successfully"
46
+ /\b(?:all\s+)?(?:unit\s+|integration\s+|the\s+)?tests?\s+(?:now\s+)?(?:pass(?:es|ed|ing)?|are\s+passing|succeed(?:ed|s)?|are\s+green)\b/i,
47
+ // "the test suite passes / passed"
48
+ /\btest\s+suite\s+(?:now\s+)?(?:pass(?:es|ed)?|succeed(?:ed|s)?|is\s+green)\b/i,
49
+ // "the build succeeds / passes / is green / compiles (cleanly)"
50
+ /\b(?:the\s+)?build\s+(?:now\s+)?(?:succeed(?:ed|s)?|pass(?:es|ed)?|is\s+green|compiles?(?:\s+clean(?:ly)?)?)\b/i,
51
+ // "compiles / compiled without errors", "type-checks pass", "lint passes"
52
+ /\b(?:compil(?:es|ed)|type[-\s]?check(?:s|ed|ing)?|typecheck(?:s|ed|ing)?|lint(?:s|ing)?)\s+(?:pass(?:es|ed)?|succeed(?:ed|s)?|clean(?:ly)?|without\s+(?:errors?|warnings?))\b/i,
53
+ // "I ran/verified/confirmed the tests|build" (past-tense execution + a check noun)
54
+ /\b(?:i\s+|we\s+)?(?:ran|executed|verified|confirmed)\s+(?:the\s+|all\s+)?(?:tests?|test\s+suite|build|lint|typecheck|type\s+check)\b/i,
55
+ // strong standalone idioms
56
+ /\ball\s+(?:tests?\s+)?(?:pass|passing|green)\b/i,
57
+ /\beverything\s+(?:passes|works|is\s+working|is\s+green)\b/i,
58
+ /\bverified\s+(?:that\s+)?(?:it|the\s+\w+)\s+works?\b/i,
59
+ /\bconfirmed\s+(?:that\s+)?(?:it|everything|the\s+\w+)\s+works?\b/i,
60
+ ];
61
+ // Hedge / conditional markers that turn a "pass" phrase into an intention rather
62
+ // than a claim of fact ("this WOULD make the tests pass", "you SHOULD run the
63
+ // tests", "hopefully the build succeeds"). If one appears shortly BEFORE the
64
+ // matched phrase, we don't treat it as a concrete claim.
65
+ const HEDGE_RE = /\b(?:should|would|could|might|may|will|to\s+make|so\s+that|in\s+theory|hopefully|expect(?:ed)?\s+to|meant\s+to|supposed\s+to|need\s+to|please|make\s+sure|ensure|let'?s|if\s+)\b/i;
66
+ /**
67
+ * Does the agent's final text make a concrete verification claim? Returns the
68
+ * matched phrases (deduped, capped) so the nudge can quote them back. Phrases
69
+ * preceded by a hedge/conditional within the same clause are ignored.
70
+ */
71
+ function detectVerificationClaims(text) {
72
+ if (!text || typeof text !== 'string')
73
+ return [];
74
+ const found = new Set();
75
+ for (const re of CLAIM_RES) {
76
+ const flags = re.flags.includes('g') ? re.flags : re.flags + 'g';
77
+ const g = new RegExp(re.source, flags);
78
+ let m;
79
+ while ((m = g.exec(text))) {
80
+ if (!m[0]) {
81
+ if (g.lastIndex === m.index)
82
+ g.lastIndex++;
83
+ continue;
84
+ }
85
+ // Look back a short window for a hedge marker in the same clause (stop at a
86
+ // sentence/clause boundary so a hedge in a PRIOR sentence doesn't suppress a
87
+ // genuine claim here).
88
+ const from = Math.max(0, m.index - 60);
89
+ const before = text.slice(from, m.index);
90
+ const clause = before.split(/[.!?;\n]/).pop() ?? before;
91
+ if (!HEDGE_RE.test(clause)) {
92
+ found.add(m[0].trim().replace(/\s+/g, ' ').toLowerCase());
93
+ }
94
+ if (g.lastIndex === m.index)
95
+ g.lastIndex++;
96
+ if (found.size >= 5)
97
+ break;
98
+ }
99
+ if (found.size >= 5)
100
+ break;
101
+ }
102
+ return [...found];
103
+ }
104
+ /**
105
+ * Compare the agent's final message against the deterministic verification
106
+ * ledger. `currentEpoch` is the ledger's current mutation epoch; a passing
107
+ * verification only counts as current evidence if no source write happened
108
+ * after it (i.e. its epoch === currentEpoch) — a pass from BEFORE the latest
109
+ * edit no longer proves the current code works.
110
+ */
111
+ function checkClaimEvidence(finalText, verifications, currentEpoch) {
112
+ const claimPhrases = detectVerificationClaims(finalText);
113
+ if (claimPhrases.length === 0) {
114
+ return { claimed: false, contradicted: false, claimPhrases: [], reason: '' };
115
+ }
116
+ const recognised = verifications ?? [];
117
+ // Evidence that supports a "it works now" claim: a PASS at the CURRENT epoch
118
+ // (no edit invalidated it since). Passes at an older epoch are stale.
119
+ const currentPasses = recognised.filter((v) => v.ok && v.epoch === currentEpoch);
120
+ const currentFails = recognised.filter((v) => !v.ok && v.epoch === currentEpoch);
121
+ if (currentPasses.length > 0) {
122
+ // There is a fresh passing verification — the claim is supported.
123
+ return { claimed: true, contradicted: false, claimPhrases, reason: '' };
124
+ }
125
+ let reason;
126
+ if (recognised.length === 0) {
127
+ reason = 'no build/test/lint/typecheck command was run this session';
128
+ }
129
+ else if (currentFails.length > 0) {
130
+ reason = `the most recent verification (${currentFails[currentFails.length - 1].cmd}) FAILED and has not since passed`;
131
+ }
132
+ else {
133
+ // Only stale passes (from before the latest edit) exist.
134
+ reason = 'the last passing verification predates your most recent code change, so it no longer proves the current code works';
135
+ }
136
+ return { claimed: true, contradicted: true, claimPhrases, reason };
137
+ }
138
+ /** Build the one-shot nudge message body for a contradicted claim. */
139
+ function claimEvidenceNudgeText(result) {
140
+ const quoted = result.claimPhrases.map((p) => `"${p}"`).join(', ');
141
+ return ('STOP — verification check. Your summary claims verification ' +
142
+ `(${quoted}) but ${result.reason}. ` +
143
+ 'Do not state that tests pass / the build succeeds / it works unless a command actually proved it THIS session on the CURRENT code. ' +
144
+ 'Either: (1) run the real build/test/lint/typecheck command now and fix anything that fails, then finish — or (2) if you genuinely cannot run it here (no test suite, environment limitation, out of scope), remove/soften the claim and state plainly what you did and did NOT verify. Do not repeat an unverified pass claim.');
145
+ }
146
+ //# sourceMappingURL=claimEvidence.js.map
@@ -53,7 +53,7 @@ export interface ProgressLedger {
53
53
  }
54
54
  export declare function createLedger(): ProgressLedger;
55
55
  /** Record one tool call's effect on the ledger (deterministic, no model call). */
56
- export declare function ledgerRecord(ledger: ProgressLedger, toolName: string, input: Record<string, unknown> | undefined, ok: boolean, output?: string): void;
56
+ export declare function ledgerRecord(ledger: ProgressLedger, toolName: string, input: Record<string, unknown> | undefined, ok: boolean, output?: string, exitCode?: number): void;
57
57
  /** Render the ledger as a compact, verbatim block for the compaction preamble. */
58
58
  export declare function ledgerSummary(ledger: ProgressLedger): string;
59
59
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"loop.d.ts","sourceRoot":"","sources":["../../src/agent/loop.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,OAAO,EAMP,gBAAgB,EACjB,MAAM,UAAU,CAAC;AAqKlB,wBAAgB,oBAAoB,CAClC,WAAW,EAAE,MAAM,GAAG,SAAS,EAC/B,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GACnC,MAAM,CAWR;AA8RD,+EAA+E;AAC/E,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,OAAO,EAAE,GAAG,MAAM,CAM7D;AAsBD,iFAAiF;AACjF,eAAO,MAAM,gBAAgB,aAA+G,CAAC;AAC7I,gGAAgG;AAChG,eAAO,MAAM,aAAa,QAA2J,CAAC;AAEtL;;;;;;;;;;;;GAYG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,OAAO,EAAE,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAK5E;AAUD;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAAC,QAAQ,EAAE,OAAO,EAAE,GAAG,MAAM,CAwBxD;AAoBD,MAAM,WAAW,cAAc;IAC7B,YAAY,EAAE,GAAG,CAAC,MAAM,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC3D,aAAa,EAAE,KAAK,CAAC;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,OAAO,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAClE,qFAAqF;IACrF,aAAa,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACvD;;;;OAIG;IACH,KAAK,EAAE,MAAM,CAAC;CACf;AAED,wBAAgB,YAAY,IAAI,cAAc,CAE7C;AAED,kFAAkF;AAClF,wBAAgB,YAAY,CAC1B,MAAM,EAAE,cAAc,EACtB,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,EAC1C,EAAE,EAAE,OAAO,EACX,MAAM,CAAC,EAAE,MAAM,GACd,IAAI,CA4CN;AAED,kFAAkF;AAClF,wBAAgB,aAAa,CAAC,MAAM,EAAE,cAAc,GAAG,MAAM,CA6B5D;AAmBD;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,OAAO,EAAE,GAAG,MAAM,CAmB/D;AA2FD,wBAAsB,YAAY,CAChC,eAAe,EAAE,OAAO,EAAE,EAC1B,OAAO,EAAE,gBAAgB,GACxB,OAAO,CAAC,OAAO,EAAE,CAAC,CAufpB"}
1
+ {"version":3,"file":"loop.d.ts","sourceRoot":"","sources":["../../src/agent/loop.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,OAAO,EAMP,gBAAgB,EACjB,MAAM,UAAU,CAAC;AAsKlB,wBAAgB,oBAAoB,CAClC,WAAW,EAAE,MAAM,GAAG,SAAS,EAC/B,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GACnC,MAAM,CAWR;AA8RD,+EAA+E;AAC/E,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,OAAO,EAAE,GAAG,MAAM,CAM7D;AAsBD,iFAAiF;AACjF,eAAO,MAAM,gBAAgB,aAA+G,CAAC;AAC7I,gGAAgG;AAChG,eAAO,MAAM,aAAa,QAA2J,CAAC;AAEtL;;;;;;;;;;;;GAYG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,OAAO,EAAE,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAK5E;AAUD;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAAC,QAAQ,EAAE,OAAO,EAAE,GAAG,MAAM,CAwBxD;AAoBD,MAAM,WAAW,cAAc;IAC7B,YAAY,EAAE,GAAG,CAAC,MAAM,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC3D,aAAa,EAAE,KAAK,CAAC;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,OAAO,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAClE,qFAAqF;IACrF,aAAa,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACvD;;;;OAIG;IACH,KAAK,EAAE,MAAM,CAAC;CACf;AAED,wBAAgB,YAAY,IAAI,cAAc,CAE7C;AAED,kFAAkF;AAClF,wBAAgB,YAAY,CAC1B,MAAM,EAAE,cAAc,EACtB,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,EAC1C,EAAE,EAAE,OAAO,EACX,MAAM,CAAC,EAAE,MAAM,EACf,QAAQ,CAAC,EAAE,MAAM,GAChB,IAAI,CAoDN;AAED,kFAAkF;AAClF,wBAAgB,aAAa,CAAC,MAAM,EAAE,cAAc,GAAG,MAAM,CA6B5D;AAmBD;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,OAAO,EAAE,GAAG,MAAM,CAmB/D;AA2FD,wBAAsB,YAAY,CAChC,eAAe,EAAE,OAAO,EAAE,EAC1B,OAAO,EAAE,gBAAgB,GACxB,OAAO,CAAC,OAAO,EAAE,CAAC,CA2kBpB"}
@@ -51,6 +51,7 @@ const sandbox_1 = require("../tools/sandbox");
51
51
  const index_1 = require("../plugins/index");
52
52
  const testIntegrity_1 = require("./testIntegrity");
53
53
  const flaky_1 = require("./flaky");
54
+ const claimEvidence_1 = require("./claimEvidence");
54
55
  const fs = __importStar(require("fs"));
55
56
  const path = __importStar(require("path"));
56
57
  const child_process_1 = require("child_process");
@@ -551,7 +552,7 @@ function createLedger() {
551
552
  return { filesTouched: new Map(), verifications: [], testIntegrity: [], epoch: 0 };
552
553
  }
553
554
  /** Record one tool call's effect on the ledger (deterministic, no model call). */
554
- function ledgerRecord(ledger, toolName, input, ok, output) {
555
+ function ledgerRecord(ledger, toolName, input, ok, output, exitCode) {
555
556
  if (exports.WRITE_TOOL_NAMES.has(toolName)) {
556
557
  if (!ok)
557
558
  return; // a FAILED write changed nothing — not a durable fact
@@ -592,8 +593,16 @@ function ledgerRecord(ledger, toolName, input, ok, output) {
592
593
  if (cmd && exports.VERIFY_CMD_RE.test(cmd)) {
593
594
  // Record BOTH outcomes: a FAILED test/build is the single most important
594
595
  // fact to carry across a compaction (it tells the agent work is NOT done).
595
- // ok===true means the command exited 0 (executor sets error on non-zero).
596
- ledger.verifications.push({ cmd: cmd.slice(0, 120), ok, epoch: ledger.epoch });
596
+ //
597
+ // CRITICAL: `ok` is `result.error === undefined`, which is TRUE even when a
598
+ // test suite exits non-zero (the executor doesn't set `error` for a plain
599
+ // command failure — only for timeout/abort/spawn-fail). So `ok` alone would
600
+ // record a FAILING `npm test` as PASSED. The executor now reports the real
601
+ // process exit code via `exitCode`; a non-zero exit means the verification
602
+ // FAILED regardless of `ok`. Fall back to `ok` only when no exitCode is
603
+ // available (older tools / non-bash paths).
604
+ const passed = exitCode !== undefined ? exitCode === 0 : ok;
605
+ ledger.verifications.push({ cmd: cmd.slice(0, 120), ok: passed, epoch: ledger.epoch });
597
606
  if (ledger.verifications.length > LEDGER_MAX_NOTES * 2) {
598
607
  ledger.verifications.splice(0, ledger.verifications.length - LEDGER_MAX_NOTES);
599
608
  }
@@ -821,6 +830,10 @@ async function runAgentLoop(initialMessages, options) {
821
830
  // Flaky-test guard: commands already nudged about, so we only warn about a
822
831
  // newly-detected flaky command once.
823
832
  const flakyNudgedCmds = new Set();
833
+ // Claim-vs-evidence guard: fire the "you claimed verified but there's no
834
+ // passing verification" nudge at most once, so a genuinely un-testable task
835
+ // (the agent explains it can't run tests) still ends instead of looping.
836
+ let claimEvidenceNudged = false;
824
837
  // GAP E — deterministic progress ledger, preserved verbatim across compactions.
825
838
  const ledger = createLedger();
826
839
  try {
@@ -967,6 +980,31 @@ async function runAgentLoop(initialMessages, options) {
967
980
  .map(b => b.tool_use_id)
968
981
  .filter((id) => !!id));
969
982
  const toolUseBlocks = assistantMessage.content.filter((block) => block.type === 'tool_use' && !serverSideResultIds.has(block.id));
983
+ // ─── TRUNCATED-TOOL-CALL GUARD ──────────────────────────────────────────
984
+ // When Anthropic cuts a response off at `max_tokens` mid-stream, the SDK's
985
+ // partial-JSON parser (used to show live tool-call args while streaming)
986
+ // can still successfully parse an INCOMPLETE argument object — e.g. a
987
+ // multi_edit whose `edits` array lost its last, still-in-progress element
988
+ // (or came out empty/missing), or an edit_file whose `new_string` got cut
989
+ // mid-string. The result LOOKS like valid JSON and often passes basic
990
+ // "is edits a non-empty array" checks, so the tool executor either (a)
991
+ // throws a confusing generic error ("edits must be a non-empty array")
992
+ // with no indication WHY, or worse (b) silently applies a SUBSET of the
993
+ // edits the model actually intended, with zero error at all — a genuine
994
+ // partial-write bug, not just an unclear message.
995
+ //
996
+ // Only the LAST content block in the message can possibly be affected —
997
+ // every earlier block already finished streaming (and was validated by
998
+ // Anthropic) before the model moved on, so truncation can only land on
999
+ // whatever was still being generated when the ceiling was hit. If that
1000
+ // last block is a tool_use AND stop_reason is 'max_tokens', refuse to
1001
+ // execute it blindly: return a clear, actionable error instead so the
1002
+ // model retries with a smaller call, rather than either failing
1003
+ // mysteriously or silently mutating a file incompletely.
1004
+ const lastBlock = assistantMessage.content[assistantMessage.content.length - 1];
1005
+ const truncatedToolUseId = assistantMessage.stopReason === 'max_tokens' && lastBlock?.type === 'tool_use'
1006
+ ? lastBlock.id
1007
+ : undefined;
970
1008
  // 4. If no tool use → agent produced a final text response.
971
1009
  // But if the user queued a follow-up while we were working, fold it in as the
972
1010
  // next user turn and keep going instead of ending (Claude-Code style).
@@ -1041,6 +1079,27 @@ async function runAgentLoop(initialMessages, options) {
1041
1079
  });
1042
1080
  continue;
1043
1081
  }
1082
+ // Claim-vs-evidence guard: the core of verification-hallucination. The agent
1083
+ // is about to finish; if its final message CLAIMS a verification ("tests
1084
+ // pass", "build succeeds", "verified it works") that the deterministic ledger
1085
+ // does NOT back with a PASSING run on the current code, challenge it once.
1086
+ // The claim side is heuristic text; the evidence side is machine-tracked, so
1087
+ // we only flag claims the record actively contradicts.
1088
+ if (!claimEvidenceNudged) {
1089
+ const finalText = assistantMessage.content
1090
+ .filter((b) => b.type === 'text' && typeof b.text === 'string')
1091
+ .map((b) => b.text)
1092
+ .join('\n');
1093
+ const ce = (0, claimEvidence_1.checkClaimEvidence)(finalText, ledger.verifications, ledger.epoch);
1094
+ if (ce.contradicted) {
1095
+ claimEvidenceNudged = true;
1096
+ messages.push({
1097
+ role: 'user',
1098
+ content: [{ type: 'text', text: (0, claimEvidence_1.claimEvidenceNudgeText)(ce) }],
1099
+ });
1100
+ continue;
1101
+ }
1102
+ }
1044
1103
  runSimpleHooks(hooks.PostMessageComplete, options.workDir);
1045
1104
  completedCleanly = true;
1046
1105
  break;
@@ -1050,9 +1109,33 @@ async function runAgentLoop(initialMessages, options) {
1050
1109
  const { id, name, input } = block;
1051
1110
  // Notify caller about pending tool use
1052
1111
  options.onToolUse(name, input);
1112
+ let result;
1113
+ // Checked BEFORE requesting permission: no point asking the user to
1114
+ // approve a diff/preview built from possibly-garbage truncated input
1115
+ // (see the guard comment above toolUseBlocks) — refuse immediately.
1116
+ if (id === truncatedToolUseId) {
1117
+ // This is the LAST block of a message that Anthropic cut off at
1118
+ // max_tokens — its `input` may be an incomplete/partial object that
1119
+ // happened to parse successfully (see the guard above). Refuse to
1120
+ // execute it blindly: a confusing generic validation error, or a
1121
+ // silent partial write, are both worse than a clear explanation the
1122
+ // model can act on immediately (retry with a smaller call).
1123
+ result = {
1124
+ error: `This tool call (${name}) was CUT OFF because the response hit the model's output-token limit ` +
1125
+ `mid-generation (stop_reason: max_tokens) — its arguments may be incomplete or missing fields ` +
1126
+ `entirely, so it was NOT executed to avoid a silent partial edit. Retry with a SMALLER call: ` +
1127
+ (name === 'multi_edit' || name === 'edit_file'
1128
+ ? 'split this into fewer edits per call (or call edit_file once per change instead of one large multi_edit), '
1129
+ : name === 'write_file'
1130
+ ? 'write the file in smaller chunks via write_file + edit_file follow-ups instead of one large write_file, '
1131
+ : '') +
1132
+ `so the full response fits comfortably under the per-turn output budget.`,
1133
+ };
1134
+ options.onToolResult(name, result);
1135
+ return { block: { ...block, id }, result };
1136
+ }
1053
1137
  // Request permission
1054
1138
  const description = humanDescription(name, input);
1055
- let result;
1056
1139
  let permitted;
1057
1140
  try {
1058
1141
  permitted = await options.requestPermission({ tool: name, input, description });
@@ -1140,14 +1223,20 @@ async function runAgentLoop(initialMessages, options) {
1140
1223
  const ok = result.error === undefined;
1141
1224
  // GAP E — feed every successful effect into the deterministic ledger.
1142
1225
  // rawOutput carries the (already-stripped-from-view) test-integrity marker.
1143
- ledgerRecord(ledger, block.name, block.input, ok, rawOutput ?? result.output);
1226
+ // exitCode lets the ledger tell a PASSED verification from a FAILED one
1227
+ // (a `npm test` that exits non-zero is not an `error`, but it IS a fail).
1228
+ ledgerRecord(ledger, block.name, block.input, ok, rawOutput ?? result.output, result.exitCode);
1144
1229
  if (!ok)
1145
1230
  continue; // failed calls don't count either way
1146
1231
  if (exports.WRITE_TOOL_NAMES.has(block.name))
1147
1232
  filesMutatedSinceVerify = true;
1148
1233
  else if (block.name === 'bash' && exports.VERIFY_CMD_RE.test(String(block.input?.command ?? ''))) {
1149
- ranVerificationCmd = true;
1150
- filesMutatedSinceVerify = false; // verified — reset until the next mutation
1234
+ // Only a PASSING verification satisfies the verify-nudge. A test suite that
1235
+ // ran but FAILED (non-zero exit) must NOT count as "verified"otherwise the
1236
+ // agent could run a failing build once and then finish unchallenged.
1237
+ ranVerificationCmd = result.exitCode === undefined ? true : result.exitCode === 0;
1238
+ if (ranVerificationCmd)
1239
+ filesMutatedSinceVerify = false; // verified — reset until the next mutation
1151
1240
  }
1152
1241
  }
1153
1242
  // 6. Build tool_result message and append to history
@@ -1 +1 @@
1
- {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/api/client.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,UAAU,EAA8B,UAAU,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAKrH,eAAO,MAAM,QAAQ,4BAA4B,CAAC;AAiBlD,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,CAAC,EAAE,UAAU,CAAC;IACjB,aAAa,CAAC,EAAE,aAAa,GAAG,IAAI,CAAC;IACrC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE;QAAE,OAAO,EAAE,OAAO,CAAA;KAAE,CAAC;IACnC,oFAAoF;IACpF,UAAU,CAAC,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;KAAE,CAAC,CAAC;IACjG,6EAA6E;IAC7E,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAWD,wBAAsB,UAAU,CAC9B,QAAQ,EAAE,OAAO,EAAE,EACnB,OAAO,EAAE,iBAAiB,EAC1B,OAAO,EAAE,CAAC,CAAC,EAAE,QAAQ,KAAK,IAAI,GAC7B,OAAO,CAAC,OAAO,CAAC,CA8WlB;AAID,wBAAsB,UAAU,IAAI,OAAO,CAAC,MAAM,CAAC,CAalD;AAID,wBAAsB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAgB1E;AAID,wBAAsB,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAkBhF"}
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/api/client.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,UAAU,EAA8B,UAAU,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAKrH,eAAO,MAAM,QAAQ,4BAA4B,CAAC;AAiBlD,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,CAAC,EAAE,UAAU,CAAC;IACjB,aAAa,CAAC,EAAE,aAAa,GAAG,IAAI,CAAC;IACrC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE;QAAE,OAAO,EAAE,OAAO,CAAA;KAAE,CAAC;IACnC,oFAAoF;IACpF,UAAU,CAAC,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;KAAE,CAAC,CAAC;IACjG,6EAA6E;IAC7E,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAWD,wBAAsB,UAAU,CAC9B,QAAQ,EAAE,OAAO,EAAE,EACnB,OAAO,EAAE,iBAAiB,EAC1B,OAAO,EAAE,CAAC,CAAC,EAAE,QAAQ,KAAK,IAAI,GAC7B,OAAO,CAAC,OAAO,CAAC,CA4XlB;AAID,wBAAsB,UAAU,IAAI,OAAO,CAAC,MAAM,CAAC,CAalD;AAID,wBAAsB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAgB1E;AAID,wBAAsB,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAkBhF"}
@@ -236,9 +236,22 @@ async function streamChat(messages, options, onEvent) {
236
236
  contentBlocks.push({ type: 'text', text: fullText });
237
237
  }
238
238
  contentBlocks.push(...toolUseBlocks);
239
+ // Anthropic's stop_reason travels inside the nested `message` object the
240
+ // backend forwards verbatim (routes/code.js's `sendEvent(res, {type:
241
+ // 'message_complete', message})` — `message` is the raw Anthropic SDK
242
+ // message, which always has stop_reason). 'max_tokens' means the model's
243
+ // output was cut off mid-generation — if the last content block is a
244
+ // tool_use, its `input` may be a truncated JSON object that still happened
245
+ // to parse (e.g. a multi_edit whose `edits` array lost its last, still-
246
+ // in-progress element, or came out empty/missing entirely) without any
247
+ // error at all. The agent loop uses this to refuse executing that block
248
+ // blindly instead of silently applying a partial edit.
249
+ const nestedMessage = evt.message;
250
+ const stopReason = typeof nestedMessage?.stop_reason === 'string' ? nestedMessage.stop_reason : null;
239
251
  completedMessage = {
240
252
  role: 'assistant',
241
253
  content: contentBlocks,
254
+ stopReason,
242
255
  };
243
256
  onEvent({ type: 'message_complete', message: completedMessage });
244
257
  break;
package/dist/index.d.ts CHANGED
@@ -7,6 +7,7 @@ export * from './agent/testIntegrity';
7
7
  export * from './agent/editCompleteness';
8
8
  export * from './agent/crossFile';
9
9
  export * from './agent/flaky';
10
+ export * from './agent/claimEvidence';
10
11
  export * from './mcp/client';
11
12
  export * from './mcp/httpClient';
12
13
  export * from './mcp/manager';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAC;AACxB,cAAc,cAAc,CAAC;AAC7B,cAAc,cAAc,CAAC;AAC7B,cAAc,kBAAkB,CAAC;AACjC,cAAc,cAAc,CAAC;AAC7B,cAAc,uBAAuB,CAAC;AACtC,cAAc,0BAA0B,CAAC;AACzC,cAAc,mBAAmB,CAAC;AAClC,cAAc,eAAe,CAAC;AAC9B,cAAc,cAAc,CAAC;AAC7B,cAAc,kBAAkB,CAAC;AACjC,cAAc,eAAe,CAAC;AAC9B,cAAc,sBAAsB,CAAC;AACrC,cAAc,mBAAmB,CAAC;AAClC,cAAc,oBAAoB,CAAC;AACnC,cAAc,qBAAqB,CAAC;AACpC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,iBAAiB,CAAC;AAChC,cAAc,qBAAqB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAC;AACxB,cAAc,cAAc,CAAC;AAC7B,cAAc,cAAc,CAAC;AAC7B,cAAc,kBAAkB,CAAC;AACjC,cAAc,cAAc,CAAC;AAC7B,cAAc,uBAAuB,CAAC;AACtC,cAAc,0BAA0B,CAAC;AACzC,cAAc,mBAAmB,CAAC;AAClC,cAAc,eAAe,CAAC;AAC9B,cAAc,uBAAuB,CAAC;AACtC,cAAc,cAAc,CAAC;AAC7B,cAAc,kBAAkB,CAAC;AACjC,cAAc,eAAe,CAAC;AAC9B,cAAc,sBAAsB,CAAC;AACrC,cAAc,mBAAmB,CAAC;AAClC,cAAc,oBAAoB,CAAC;AACnC,cAAc,qBAAqB,CAAC;AACpC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,iBAAiB,CAAC;AAChC,cAAc,qBAAqB,CAAC"}
package/dist/index.js CHANGED
@@ -23,6 +23,7 @@ __exportStar(require("./agent/testIntegrity"), exports);
23
23
  __exportStar(require("./agent/editCompleteness"), exports);
24
24
  __exportStar(require("./agent/crossFile"), exports);
25
25
  __exportStar(require("./agent/flaky"), exports);
26
+ __exportStar(require("./agent/claimEvidence"), exports);
26
27
  __exportStar(require("./mcp/client"), exports);
27
28
  __exportStar(require("./mcp/httpClient"), exports);
28
29
  __exportStar(require("./mcp/manager"), exports);
@@ -1 +1 @@
1
- {"version":3,"file":"executor.d.ts","sourceRoot":"","sources":["../../src/tools/executor.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAC3C,OAAO,EAAyB,KAAK,aAAa,EAAE,MAAM,WAAW,CAAC;AAk9DtE,wBAAsB,WAAW,CAC/B,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC9B,WAAW,CAAC,EAAE;IAAE,OAAO,EAAE,OAAO,CAAA;CAAE,EAClC,OAAO,CAAC,EAAE,aAAa,EACvB,OAAO,CAAC,EAAE,MAAM,EAChB,UAAU,CAAC,EAAE,MAAM,GAClB,OAAO,CAAC,UAAU,CAAC,CAiBrB"}
1
+ {"version":3,"file":"executor.d.ts","sourceRoot":"","sources":["../../src/tools/executor.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAC3C,OAAO,EAAyB,KAAK,aAAa,EAAE,MAAM,WAAW,CAAC;AAw9DtE,wBAAsB,WAAW,CAC/B,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC9B,WAAW,CAAC,EAAE;IAAE,OAAO,EAAE,OAAO,CAAA;CAAE,EAClC,OAAO,CAAC,EAAE,aAAa,EACvB,OAAO,CAAC,EAAE,MAAM,EAChB,UAAU,CAAC,EAAE,MAAM,GAClB,OAAO,CAAC,UAAU,CAAC,CAiBrB"}
@@ -735,10 +735,16 @@ async function bash(input, abortSignal, sandbox, workDir) {
735
735
  resolve({ error: 'Command stopped by user', interrupted: true, output: body || undefined });
736
736
  }
737
737
  else if (code !== 0) {
738
- resolve(prependNote({ output: body + `\n[Exit code: ${code ?? signal ?? 'unknown'}]` }));
738
+ // Non-zero exit = the command FAILED (a test suite reporting failures, a
739
+ // build error, a lint failure). We deliberately DON'T set `error` here:
740
+ // the model must see the failing output and react, and treating it as a
741
+ // hard error would break stall-guard/retry semantics. Instead expose the
742
+ // exit code as structured data so the ProgressLedger can record this
743
+ // verification as FAILED (not PASSED). Signal-only exit → code 128+sig-ish.
744
+ resolve(prependNote({ output: body + `\n[Exit code: ${code ?? signal ?? 'unknown'}]`, exitCode: code ?? 1 }));
739
745
  }
740
746
  else {
741
- resolve(prependNote({ output: body }));
747
+ resolve(prependNote({ output: body, exitCode: 0 }));
742
748
  }
743
749
  };
744
750
  child.stdout?.on('data', (chunk) => appendOutput(chunk.toString('utf-8')));
package/dist/types.d.ts CHANGED
@@ -18,6 +18,16 @@ export type ContentBlock = TextBlock | ToolUseBlock | ToolResultBlock;
18
18
  export interface Message {
19
19
  role: 'user' | 'assistant';
20
20
  content: ContentBlock[];
21
+ /**
22
+ * Anthropic's stop_reason for this turn, when known (only set on a freshly
23
+ * streamed assistant message, never on a historical/replayed one). 'max_tokens'
24
+ * means the model's output was CUT OFF mid-generation — if the last block is a
25
+ * tool_use, its `input` may be a truncated/partial JSON object (missing required
26
+ * fields, or an array that looks complete but stopped early) that happened to
27
+ * still parse successfully. Callers MUST check this before trusting a tool_use
28
+ * block was fully intended by the model, not silently mangled by the ceiling.
29
+ */
30
+ stopReason?: string | null;
21
31
  }
22
32
  export interface SSETextEvent {
23
33
  type: 'text';
@@ -67,6 +77,15 @@ export interface ToolResult {
67
77
  output?: string;
68
78
  error?: string;
69
79
  interrupted?: boolean;
80
+ /**
81
+ * Process exit code for bash commands. 0 = success, non-zero = the command
82
+ * FAILED (e.g. a test suite that reported failures). This is kept SEPARATE
83
+ * from `error` on purpose: a failing `npm test` is a legitimate, non-error
84
+ * tool result (the model should see the failures and react) — but the
85
+ * ProgressLedger needs it to tell a PASSED verification from a FAILED one.
86
+ * Undefined for non-bash tools or when no exit code is available.
87
+ */
88
+ exitCode?: number;
70
89
  }
71
90
  export interface AuthConfig {
72
91
  token: string;
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nexrall/code-core",
3
- "version": "1.4.1",
3
+ "version": "1.4.3",
4
4
  "description": "Core agent loop, tools, and extension primitives for Nexrall Code — embed an AI coding agent in any Node.js application.",
5
5
  "license": "MIT",
6
6
  "author": "Nexrall <support@nexrall.com> (https://nexrall.com)",