@nexrall/code-core 1.4.0 → 1.4.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.
- package/dist/agent/loop.d.ts +1 -1
- package/dist/agent/loop.d.ts.map +1 -1
- package/dist/agent/loop.js +29 -8
- package/dist/agent/testIntegrity.d.ts +6 -0
- package/dist/agent/testIntegrity.d.ts.map +1 -1
- package/dist/agent/testIntegrity.js +50 -0
- package/dist/tools/executor.d.ts.map +1 -1
- package/dist/tools/executor.js +11 -1
- package/package.json +1 -1
package/dist/agent/loop.d.ts
CHANGED
|
@@ -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): void;
|
|
56
|
+
export declare function ledgerRecord(ledger: ProgressLedger, toolName: string, input: Record<string, unknown> | undefined, ok: boolean, output?: string): 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
|
/**
|
package/dist/agent/loop.d.ts.map
CHANGED
|
@@ -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,
|
|
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"}
|
package/dist/agent/loop.js
CHANGED
|
@@ -551,7 +551,7 @@ function createLedger() {
|
|
|
551
551
|
return { filesTouched: new Map(), verifications: [], testIntegrity: [], epoch: 0 };
|
|
552
552
|
}
|
|
553
553
|
/** Record one tool call's effect on the ledger (deterministic, no model call). */
|
|
554
|
-
function ledgerRecord(ledger, toolName, input, ok) {
|
|
554
|
+
function ledgerRecord(ledger, toolName, input, ok, output) {
|
|
555
555
|
if (exports.WRITE_TOOL_NAMES.has(toolName)) {
|
|
556
556
|
if (!ok)
|
|
557
557
|
return; // a FAILED write changed nothing — not a durable fact
|
|
@@ -565,10 +565,22 @@ function ledgerRecord(ledger, toolName, input, ok) {
|
|
|
565
565
|
}
|
|
566
566
|
// Reward-hacking guard: if this write WEAKENED a test file, record it so the
|
|
567
567
|
// signal survives compaction and can be surfaced before the agent finishes.
|
|
568
|
-
const
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
568
|
+
const reasons = [];
|
|
569
|
+
// write_file overwrites carry a marker computed by the executor (which had the
|
|
570
|
+
// prior on-disk content) — it detects REMOVED assertions/cases, not just
|
|
571
|
+
// additive skips/tautologies. Prefer it when present.
|
|
572
|
+
const markerReasons = toolName === 'write_file' ? (0, testIntegrity_1.decodeTestIntegrityMarker)(output) : [];
|
|
573
|
+
if (markerReasons.length) {
|
|
574
|
+
reasons.push(...markerReasons);
|
|
575
|
+
}
|
|
576
|
+
else {
|
|
577
|
+
const ti = (0, testIntegrity_1.analyzeWriteToolForTestIntegrity)(toolName, input);
|
|
578
|
+
if (ti?.suspicious)
|
|
579
|
+
reasons.push(...ti.findings.map((f) => f.reason));
|
|
580
|
+
}
|
|
581
|
+
if (reasons.length && p) {
|
|
582
|
+
for (const reason of reasons) {
|
|
583
|
+
ledger.testIntegrity.push({ path: p, reason });
|
|
572
584
|
}
|
|
573
585
|
if (ledger.testIntegrity.length > LEDGER_MAX_NOTES * 2) {
|
|
574
586
|
ledger.testIntegrity.splice(0, ledger.testIntegrity.length - LEDGER_MAX_NOTES);
|
|
@@ -1110,16 +1122,25 @@ async function runAgentLoop(initialMessages, options) {
|
|
|
1110
1122
|
}
|
|
1111
1123
|
}
|
|
1112
1124
|
}
|
|
1125
|
+
// Capture the raw output (may carry the invisible test-integrity
|
|
1126
|
+
// marker from a write_file overwrite) for the ledger, then strip the
|
|
1127
|
+
// marker so neither the UI (onToolResult) nor the model ever see it.
|
|
1128
|
+
let rawOutput;
|
|
1129
|
+
if (name === 'write_file' && result.output) {
|
|
1130
|
+
rawOutput = result.output;
|
|
1131
|
+
result.output = (0, testIntegrity_1.stripTestIntegrityMarker)(result.output);
|
|
1132
|
+
}
|
|
1113
1133
|
// Notify caller about result
|
|
1114
1134
|
options.onToolResult(name, result);
|
|
1115
|
-
return { block: { ...block, id }, result };
|
|
1135
|
+
return { block: { ...block, id }, result, rawOutput };
|
|
1116
1136
|
}));
|
|
1117
1137
|
// Track whether files were mutated / verified this run, for the one-shot
|
|
1118
1138
|
// end-of-task nudge below (GAP D — see declaration above).
|
|
1119
|
-
for (const { block, result } of toolResults) {
|
|
1139
|
+
for (const { block, result, rawOutput } of toolResults) {
|
|
1120
1140
|
const ok = result.error === undefined;
|
|
1121
1141
|
// GAP E — feed every successful effect into the deterministic ledger.
|
|
1122
|
-
|
|
1142
|
+
// rawOutput carries the (already-stripped-from-view) test-integrity marker.
|
|
1143
|
+
ledgerRecord(ledger, block.name, block.input, ok, rawOutput ?? result.output);
|
|
1123
1144
|
if (!ok)
|
|
1124
1145
|
continue; // failed calls don't count either way
|
|
1125
1146
|
if (exports.WRITE_TOOL_NAMES.has(block.name))
|
|
@@ -53,4 +53,10 @@ export declare function analyzeTestEdit(path: string, oldText: string, newText:
|
|
|
53
53
|
* - write_file: ('', content) — additive-only detection (no prior content here)
|
|
54
54
|
*/
|
|
55
55
|
export declare function analyzeWriteToolForTestIntegrity(toolName: string, input: Record<string, unknown> | undefined): TestIntegrityResult | null;
|
|
56
|
+
/** Encode findings as an invisible marker to append to a tool's output string. */
|
|
57
|
+
export declare function encodeTestIntegrityMarker(findings: TestEditFinding[]): string;
|
|
58
|
+
/** Extract weakening reasons from a tool output that may carry the marker. */
|
|
59
|
+
export declare function decodeTestIntegrityMarker(output: string | undefined): string[];
|
|
60
|
+
/** Strip the (invisible) marker from output before it is shown to the model. */
|
|
61
|
+
export declare function stripTestIntegrityMarker(output: string | undefined): string;
|
|
56
62
|
//# sourceMappingURL=testIntegrity.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"testIntegrity.d.ts","sourceRoot":"","sources":["../../src/agent/testIntegrity.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAEH,MAAM,WAAW,eAAe;IAC9B,gEAAgE;IAChE,MAAM,EAAE,MAAM,CAAC;IACf,0CAA0C;IAC1C,IAAI,EAAE,YAAY,GAAG,mBAAmB,GAAG,iBAAiB,GAAG,kBAAkB,GAAG,gBAAgB,CAAC;CACtG;AAED,MAAM,WAAW,mBAAmB;IAClC,UAAU,EAAE,OAAO,CAAC;IACpB,UAAU,EAAE,OAAO,CAAC;IACpB,QAAQ,EAAE,eAAe,EAAE,CAAC;CAC7B;AAQD,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAGhD;AA4ED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,mBAAmB,CAmDnG;AAED;;;;;;;GAOG;AACH,wBAAgB,gCAAgC,CAC9C,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,GACzC,mBAAmB,GAAG,IAAI,
|
|
1
|
+
{"version":3,"file":"testIntegrity.d.ts","sourceRoot":"","sources":["../../src/agent/testIntegrity.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAEH,MAAM,WAAW,eAAe;IAC9B,gEAAgE;IAChE,MAAM,EAAE,MAAM,CAAC;IACf,0CAA0C;IAC1C,IAAI,EAAE,YAAY,GAAG,mBAAmB,GAAG,iBAAiB,GAAG,kBAAkB,GAAG,gBAAgB,CAAC;CACtG;AAED,MAAM,WAAW,mBAAmB;IAClC,UAAU,EAAE,OAAO,CAAC;IACpB,UAAU,EAAE,OAAO,CAAC;IACpB,QAAQ,EAAE,eAAe,EAAE,CAAC;CAC7B;AAQD,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAGhD;AA4ED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,mBAAmB,CAmDnG;AAED;;;;;;;GAOG;AACH,wBAAgB,gCAAgC,CAC9C,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,GACzC,mBAAmB,GAAG,IAAI,CA8B5B;AAcD,kFAAkF;AAClF,wBAAgB,yBAAyB,CAAC,QAAQ,EAAE,eAAe,EAAE,GAAG,MAAM,CAI7E;AAED,8EAA8E;AAC9E,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,EAAE,CAQ9E;AAED,gFAAgF;AAChF,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAQ3E"}
|
|
@@ -32,6 +32,9 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
32
32
|
exports.isTestFile = isTestFile;
|
|
33
33
|
exports.analyzeTestEdit = analyzeTestEdit;
|
|
34
34
|
exports.analyzeWriteToolForTestIntegrity = analyzeWriteToolForTestIntegrity;
|
|
35
|
+
exports.encodeTestIntegrityMarker = encodeTestIntegrityMarker;
|
|
36
|
+
exports.decodeTestIntegrityMarker = decodeTestIntegrityMarker;
|
|
37
|
+
exports.stripTestIntegrityMarker = stripTestIntegrityMarker;
|
|
35
38
|
// ── Is this a test file? ──────────────────────────────────────────────────────
|
|
36
39
|
// Covers the common conventions across JS/TS, Python, Go, Java/Kotlin, Ruby,
|
|
37
40
|
// Rust, PHP, C#. Path-based (fast, language-agnostic).
|
|
@@ -192,8 +195,55 @@ function analyzeWriteToolForTestIntegrity(toolName, input) {
|
|
|
192
195
|
if (toolName === 'write_file') {
|
|
193
196
|
const content = typeof input.content === 'string' ? input.content : '';
|
|
194
197
|
// No prior content available at this layer → additive-only ('' → content).
|
|
198
|
+
// The executor closes this gap: when write_file OVERWRITES an existing test
|
|
199
|
+
// file it has the prior on-disk content, runs the full old→new analysis, and
|
|
200
|
+
// embeds a TEST_INTEGRITY_MARKER in its output which ledgerRecord parses.
|
|
195
201
|
return analyzeTestEdit(path, '', content);
|
|
196
202
|
}
|
|
197
203
|
return null;
|
|
198
204
|
}
|
|
205
|
+
// ── write_file overwrite bridge ────────────────────────────────────────────────
|
|
206
|
+
// A write_file that overwrites an existing test file can silently REMOVE
|
|
207
|
+
// assertions / test cases — invisible to analyzeWriteToolForTestIntegrity above
|
|
208
|
+
// because the prior content isn't available at the loop layer. The executor DOES
|
|
209
|
+
// have the prior content (it reads it to preserve mode / run the cross-file
|
|
210
|
+
// check), so it runs analyzeTestEdit(path, priorContent, newContent) and, when
|
|
211
|
+
// suspicious, appends a machine-readable marker to its tool output. ledgerRecord
|
|
212
|
+
// parses that marker so a write_file overwrite gets the exact same ledger entry
|
|
213
|
+
// and pre-finish nudge as an edit_file weakening would.
|
|
214
|
+
const TEST_INTEGRITY_MARKER_OPEN = '\u0000NEXRALL_TEST_INTEGRITY\u0000';
|
|
215
|
+
const TEST_INTEGRITY_MARKER_CLOSE = '\u0000/NEXRALL_TEST_INTEGRITY\u0000';
|
|
216
|
+
/** Encode findings as an invisible marker to append to a tool's output string. */
|
|
217
|
+
function encodeTestIntegrityMarker(findings) {
|
|
218
|
+
if (!findings.length)
|
|
219
|
+
return '';
|
|
220
|
+
const payload = findings.map((f) => f.reason).join('\u0001');
|
|
221
|
+
return `${TEST_INTEGRITY_MARKER_OPEN}${payload}${TEST_INTEGRITY_MARKER_CLOSE}`;
|
|
222
|
+
}
|
|
223
|
+
/** Extract weakening reasons from a tool output that may carry the marker. */
|
|
224
|
+
function decodeTestIntegrityMarker(output) {
|
|
225
|
+
if (!output)
|
|
226
|
+
return [];
|
|
227
|
+
const start = output.indexOf(TEST_INTEGRITY_MARKER_OPEN);
|
|
228
|
+
if (start === -1)
|
|
229
|
+
return [];
|
|
230
|
+
const from = start + TEST_INTEGRITY_MARKER_OPEN.length;
|
|
231
|
+
const end = output.indexOf(TEST_INTEGRITY_MARKER_CLOSE, from);
|
|
232
|
+
if (end === -1)
|
|
233
|
+
return [];
|
|
234
|
+
return output.slice(from, end).split('\u0001').filter(Boolean);
|
|
235
|
+
}
|
|
236
|
+
/** Strip the (invisible) marker from output before it is shown to the model. */
|
|
237
|
+
function stripTestIntegrityMarker(output) {
|
|
238
|
+
if (!output)
|
|
239
|
+
return output ?? '';
|
|
240
|
+
const start = output.indexOf(TEST_INTEGRITY_MARKER_OPEN);
|
|
241
|
+
if (start === -1)
|
|
242
|
+
return output;
|
|
243
|
+
const end = output.indexOf(TEST_INTEGRITY_MARKER_CLOSE, start);
|
|
244
|
+
if (end === -1)
|
|
245
|
+
return output;
|
|
246
|
+
const cleaned = output.slice(0, start) + output.slice(end + TEST_INTEGRITY_MARKER_CLOSE.length);
|
|
247
|
+
return cleaned.replace(/\n{3,}/g, '\n\n').trimEnd();
|
|
248
|
+
}
|
|
199
249
|
//# sourceMappingURL=testIntegrity.js.map
|
|
@@ -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;
|
|
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"}
|
package/dist/tools/executor.js
CHANGED
|
@@ -44,6 +44,7 @@ const child_process_1 = require("child_process");
|
|
|
44
44
|
const sandbox_1 = require("./sandbox");
|
|
45
45
|
const auth_1 = require("../auth");
|
|
46
46
|
const editCompleteness_1 = require("../agent/editCompleteness");
|
|
47
|
+
const testIntegrity_1 = require("../agent/testIntegrity");
|
|
47
48
|
const crossFile_1 = require("../agent/crossFile");
|
|
48
49
|
const client_1 = require("../api/client");
|
|
49
50
|
const symbols_1 = require("./symbols");
|
|
@@ -370,7 +371,16 @@ async function writeFile(input, workDir) {
|
|
|
370
371
|
return { output: `Created ${resolved} (${lines} lines, ${bytes} bytes)` };
|
|
371
372
|
}
|
|
372
373
|
const xfile = crossFileBreakageWarning(resolved, normalizeLF(priorContent), normalizeLF(content), workDir ?? process.cwd());
|
|
373
|
-
|
|
374
|
+
// Reward-hacking guard: a write_file that OVERWRITES an existing test file can
|
|
375
|
+
// silently drop assertions / test cases. The loop layer can't see the prior
|
|
376
|
+
// content — but we can (we just read it). Run the full old→new analysis and
|
|
377
|
+
// embed an invisible marker that ledgerRecord parses, so this path gets the
|
|
378
|
+
// same ledger entry + pre-finish nudge as an edit_file weakening would.
|
|
379
|
+
let tiMarker = '';
|
|
380
|
+
const ti = (0, testIntegrity_1.analyzeTestEdit)(resolved, normalizeLF(priorContent), normalizeLF(content));
|
|
381
|
+
if (ti.suspicious)
|
|
382
|
+
tiMarker = (0, testIntegrity_1.encodeTestIntegrityMarker)(ti.findings);
|
|
383
|
+
return { output: `Overwrote ${resolved} (${lines} lines, ${bytes} bytes)${xfile}${tiMarker}` };
|
|
374
384
|
}
|
|
375
385
|
catch (err) {
|
|
376
386
|
return { error: err.message };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nexrall/code-core",
|
|
3
|
-
"version": "1.4.
|
|
3
|
+
"version": "1.4.1",
|
|
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)",
|