@nexus-cortex/core 4.69.1 → 4.71.0

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.
Files changed (70) hide show
  1. package/dist/adapters/ChatCompletionsAPIAdapter.d.ts +17 -2
  2. package/dist/adapters/ChatCompletionsAPIAdapter.d.ts.map +1 -1
  3. package/dist/adapters/ChatCompletionsAPIAdapter.js +26 -3
  4. package/dist/adapters/ChatCompletionsAPIAdapter.js.map +1 -1
  5. package/dist/adapters/MessagesAPIAdapter.d.ts.map +1 -1
  6. package/dist/adapters/MessagesAPIAdapter.js +15 -0
  7. package/dist/adapters/MessagesAPIAdapter.js.map +1 -1
  8. package/dist/models/cards/deepseek/deepseek-v4-flash-vision-exp.d.ts +28 -0
  9. package/dist/models/cards/deepseek/deepseek-v4-flash-vision-exp.d.ts.map +1 -0
  10. package/dist/models/cards/deepseek/deepseek-v4-flash-vision-exp.js +47 -0
  11. package/dist/models/cards/deepseek/deepseek-v4-flash-vision-exp.js.map +1 -0
  12. package/dist/models/cards/deepseek/index.d.ts +5 -2
  13. package/dist/models/cards/deepseek/index.d.ts.map +1 -1
  14. package/dist/models/cards/deepseek/index.js +5 -2
  15. package/dist/models/cards/deepseek/index.js.map +1 -1
  16. package/dist/models/configurators/DeepSeekConfigurator.d.ts +5 -0
  17. package/dist/models/configurators/DeepSeekConfigurator.d.ts.map +1 -1
  18. package/dist/models/configurators/DeepSeekConfigurator.js +2 -0
  19. package/dist/models/configurators/DeepSeekConfigurator.js.map +1 -1
  20. package/dist/models/configurators/XAIConfigurator.d.ts +3 -0
  21. package/dist/models/configurators/XAIConfigurator.d.ts.map +1 -1
  22. package/dist/models/configurators/XAIConfigurator.js +1 -0
  23. package/dist/models/configurators/XAIConfigurator.js.map +1 -1
  24. package/dist/models/registry/ModularModelRegistry.d.ts.map +1 -1
  25. package/dist/models/registry/ModularModelRegistry.js +1 -0
  26. package/dist/models/registry/ModularModelRegistry.js.map +1 -1
  27. package/dist/orchestrator/CortexOrchestrator.d.ts +23 -0
  28. package/dist/orchestrator/CortexOrchestrator.d.ts.map +1 -1
  29. package/dist/orchestrator/CortexOrchestrator.js +628 -22
  30. package/dist/orchestrator/CortexOrchestrator.js.map +1 -1
  31. package/dist/orchestrator/imageTtl.d.ts +37 -0
  32. package/dist/orchestrator/imageTtl.d.ts.map +1 -0
  33. package/dist/orchestrator/imageTtl.js +72 -0
  34. package/dist/orchestrator/imageTtl.js.map +1 -0
  35. package/dist/orchestrator/inactionGuard.d.ts +42 -0
  36. package/dist/orchestrator/inactionGuard.d.ts.map +1 -0
  37. package/dist/orchestrator/inactionGuard.js +47 -0
  38. package/dist/orchestrator/inactionGuard.js.map +1 -0
  39. package/dist/orchestrator/requirementsVerification.d.ts +43 -0
  40. package/dist/orchestrator/requirementsVerification.d.ts.map +1 -0
  41. package/dist/orchestrator/requirementsVerification.js +87 -0
  42. package/dist/orchestrator/requirementsVerification.js.map +1 -0
  43. package/dist/tools/ToolProfile.d.ts +9 -0
  44. package/dist/tools/ToolProfile.d.ts.map +1 -1
  45. package/dist/tools/ToolProfile.js +26 -3
  46. package/dist/tools/ToolProfile.js.map +1 -1
  47. package/dist/tools/registries/BaseToolRegistry.d.ts.map +1 -1
  48. package/dist/tools/registries/BaseToolRegistry.js +42 -1
  49. package/dist/tools/registries/BaseToolRegistry.js.map +1 -1
  50. package/dist/training/DecisionPriorInjector.d.ts +7 -0
  51. package/dist/training/DecisionPriorInjector.d.ts.map +1 -1
  52. package/dist/training/DecisionPriorInjector.js +22 -0
  53. package/dist/training/DecisionPriorInjector.js.map +1 -1
  54. package/dist/training/DecisionStore.d.ts +39 -0
  55. package/dist/training/DecisionStore.d.ts.map +1 -1
  56. package/dist/training/DecisionStore.js +94 -0
  57. package/dist/training/DecisionStore.js.map +1 -1
  58. package/dist/training/errorFamily.d.ts +15 -0
  59. package/dist/training/errorFamily.d.ts.map +1 -0
  60. package/dist/training/errorFamily.js +40 -0
  61. package/dist/training/errorFamily.js.map +1 -0
  62. package/dist/training/loopLadder.d.ts +35 -0
  63. package/dist/training/loopLadder.d.ts.map +1 -0
  64. package/dist/training/loopLadder.js +58 -0
  65. package/dist/training/loopLadder.js.map +1 -0
  66. package/dist/training/toolOutcome.d.ts +20 -0
  67. package/dist/training/toolOutcome.d.ts.map +1 -0
  68. package/dist/training/toolOutcome.js +100 -0
  69. package/dist/training/toolOutcome.js.map +1 -0
  70. package/package.json +3 -3
@@ -0,0 +1,37 @@
1
+ /**
2
+ * imageTtl — request-build-time image eviction (backlog item 7 addendum,
3
+ * MEASURED 2026-08-25): on deepseek-v4-flash-vision-exp an image ANYWHERE in
4
+ * the request disables cache reads for the ENTIRE request (probe: identical
5
+ * repeat cached=0 while a text-only request hit the same 896-token prefix).
6
+ * The image's own ≤384 tokens are irrelevant — one stale image forfeits the
7
+ * ~31× cache-hit discount on every subsequent turn.
8
+ *
9
+ * Fix: after the image has been visible for CORTEX_IMAGE_TTL_TURNS assistant
10
+ * responses (default 3 — enough to look, act, and confirm), the outgoing
11
+ * REQUEST COPY replaces the image block with a deterministic text stub. The
12
+ * session history is never rewritten (append-only invariant; the model can
13
+ * always ReadImage again). The one-time prefix bust at the TTL boundary is
14
+ * the good kind: it restores caching for the rest of the session, and the
15
+ * stub is byte-stable so the prefix re-stabilizes immediately.
16
+ *
17
+ * Pure — applied in convertToCanonicalMessages' request pipeline. MUST NOT
18
+ * mutate the input blocks/arrays (cached wrappers share the content array;
19
+ * same contract as the repair pass: swap arrays, never edit blocks).
20
+ */
21
+ import type { CanonicalMessage } from '../adapters/FormatAdapter.interface.js';
22
+ /** Resolve the TTL from env. Returns null when eviction is DISABLED
23
+ * ('off'/'never'/'0'); otherwise a positive integer (default 3). */
24
+ export declare function resolveImageTtlTurns(env?: NodeJS.ProcessEnv): number | null;
25
+ /** Deterministic stub — NO timestamps or counters, so the request prefix is
26
+ * byte-stable on every build after the eviction boundary. */
27
+ export declare function imageEvictionStub(): {
28
+ type: 'text';
29
+ text: string;
30
+ };
31
+ /**
32
+ * Replace image blocks older than `ttl` assistant responses with the stub,
33
+ * on a request copy. An image's age = number of assistant-role messages
34
+ * appearing AFTER its message in the array.
35
+ */
36
+ export declare function applyImageTtlForRequest(messages: CanonicalMessage[], ttl?: number | null): CanonicalMessage[];
37
+ //# sourceMappingURL=imageTtl.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"imageTtl.d.ts","sourceRoot":"","sources":["../../src/orchestrator/imageTtl.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,wCAAwC,CAAC;AAE/E;qEACqE;AACrE,wBAAgB,oBAAoB,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,MAAM,GAAG,IAAI,CAKxF;AAED;8DAC8D;AAC9D,wBAAgB,iBAAiB,IAAI;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAKlE;AAED;;;;GAIG;AACH,wBAAgB,uBAAuB,CACrC,QAAQ,EAAE,gBAAgB,EAAE,EAC5B,GAAG,GAAE,MAAM,GAAG,IAA6B,GAC1C,gBAAgB,EAAE,CAsBpB"}
@@ -0,0 +1,72 @@
1
+ /**
2
+ * imageTtl — request-build-time image eviction (backlog item 7 addendum,
3
+ * MEASURED 2026-08-25): on deepseek-v4-flash-vision-exp an image ANYWHERE in
4
+ * the request disables cache reads for the ENTIRE request (probe: identical
5
+ * repeat cached=0 while a text-only request hit the same 896-token prefix).
6
+ * The image's own ≤384 tokens are irrelevant — one stale image forfeits the
7
+ * ~31× cache-hit discount on every subsequent turn.
8
+ *
9
+ * Fix: after the image has been visible for CORTEX_IMAGE_TTL_TURNS assistant
10
+ * responses (default 3 — enough to look, act, and confirm), the outgoing
11
+ * REQUEST COPY replaces the image block with a deterministic text stub. The
12
+ * session history is never rewritten (append-only invariant; the model can
13
+ * always ReadImage again). The one-time prefix bust at the TTL boundary is
14
+ * the good kind: it restores caching for the rest of the session, and the
15
+ * stub is byte-stable so the prefix re-stabilizes immediately.
16
+ *
17
+ * Pure — applied in convertToCanonicalMessages' request pipeline. MUST NOT
18
+ * mutate the input blocks/arrays (cached wrappers share the content array;
19
+ * same contract as the repair pass: swap arrays, never edit blocks).
20
+ */
21
+ /** Resolve the TTL from env. Returns null when eviction is DISABLED
22
+ * ('off'/'never'/'0'); otherwise a positive integer (default 3). */
23
+ export function resolveImageTtlTurns(env = process.env) {
24
+ const raw = (env.CORTEX_IMAGE_TTL_TURNS ?? '').trim().toLowerCase();
25
+ if (raw === 'off' || raw === 'never' || raw === '0')
26
+ return null;
27
+ if (/^\d+$/.test(raw) && Number(raw) > 0)
28
+ return Number(raw);
29
+ return 3;
30
+ }
31
+ /** Deterministic stub — NO timestamps or counters, so the request prefix is
32
+ * byte-stable on every build after the eviction boundary. */
33
+ export function imageEvictionStub() {
34
+ return {
35
+ type: 'text',
36
+ text: '[image evicted from context to restore prompt caching — run ReadImage on the file again if you need to see it]',
37
+ };
38
+ }
39
+ /**
40
+ * Replace image blocks older than `ttl` assistant responses with the stub,
41
+ * on a request copy. An image's age = number of assistant-role messages
42
+ * appearing AFTER its message in the array.
43
+ */
44
+ export function applyImageTtlForRequest(messages, ttl = resolveImageTtlTurns()) {
45
+ if (ttl === null)
46
+ return messages;
47
+ // Suffix counts of assistant messages, computed once.
48
+ const assistantsAfter = new Array(messages.length);
49
+ let count = 0;
50
+ for (let i = messages.length - 1; i >= 0; i--) {
51
+ assistantsAfter[i] = count;
52
+ if (messages[i].role === 'assistant')
53
+ count++;
54
+ }
55
+ let changed = false;
56
+ const out = messages.map((msg, i) => {
57
+ if (msg.role !== 'user')
58
+ return msg;
59
+ if (assistantsAfter[i] < ttl)
60
+ return msg;
61
+ if (!msg.content.some((b) => b.type === 'image'))
62
+ return msg;
63
+ changed = true;
64
+ // Swap the content ARRAY; never mutate shared blocks (cache contract).
65
+ return {
66
+ ...msg,
67
+ content: msg.content.map((b) => (b.type === 'image' ? imageEvictionStub() : b)),
68
+ };
69
+ });
70
+ return changed ? out : messages;
71
+ }
72
+ //# sourceMappingURL=imageTtl.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"imageTtl.js","sourceRoot":"","sources":["../../src/orchestrator/imageTtl.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAIH;qEACqE;AACrE,MAAM,UAAU,oBAAoB,CAAC,MAAyB,OAAO,CAAC,GAAG;IACvE,MAAM,GAAG,GAAG,CAAC,GAAG,CAAC,sBAAsB,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IACpE,IAAI,GAAG,KAAK,KAAK,IAAI,GAAG,KAAK,OAAO,IAAI,GAAG,KAAK,GAAG;QAAE,OAAO,IAAI,CAAC;IACjE,IAAI,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC;QAAE,OAAO,MAAM,CAAC,GAAG,CAAC,CAAC;IAC7D,OAAO,CAAC,CAAC;AACX,CAAC;AAED;8DAC8D;AAC9D,MAAM,UAAU,iBAAiB;IAC/B,OAAO;QACL,IAAI,EAAE,MAAM;QACZ,IAAI,EAAE,gHAAgH;KACvH,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,uBAAuB,CACrC,QAA4B,EAC5B,MAAqB,oBAAoB,EAAE;IAE3C,IAAI,GAAG,KAAK,IAAI;QAAE,OAAO,QAAQ,CAAC;IAClC,sDAAsD;IACtD,MAAM,eAAe,GAAG,IAAI,KAAK,CAAS,QAAQ,CAAC,MAAM,CAAC,CAAC;IAC3D,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,KAAK,IAAI,CAAC,GAAG,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;QAC9C,eAAe,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC;QAC3B,IAAI,QAAQ,CAAC,CAAC,CAAE,CAAC,IAAI,KAAK,WAAW;YAAE,KAAK,EAAE,CAAC;IACjD,CAAC;IACD,IAAI,OAAO,GAAG,KAAK,CAAC;IACpB,MAAM,GAAG,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE;QAClC,IAAI,GAAG,CAAC,IAAI,KAAK,MAAM;YAAE,OAAO,GAAG,CAAC;QACpC,IAAI,eAAe,CAAC,CAAC,CAAE,GAAG,GAAG;YAAE,OAAO,GAAG,CAAC;QAC1C,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,OAAO,CAAC;YAAE,OAAO,GAAG,CAAC;QAC7D,OAAO,GAAG,IAAI,CAAC;QACf,uEAAuE;QACvE,OAAO;YACL,GAAG,GAAG;YACN,OAAO,EAAE,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC,iBAAiB,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;SAChF,CAAC;IACJ,CAAC,CAAC,CAAC;IACH,OAAO,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC;AAClC,CAAC"}
@@ -0,0 +1,42 @@
1
+ /**
2
+ * inactionGuard — the loop ladder's INVERSE (docs/HARNESS_IMPROVEMENT_BACKLOG.md
3
+ * item 2). TB2 2×2 evidence: persist-frame arms produced never-acted /
4
+ * over-deliberated failures (5 pro-persist, 2 each flash arm, 0 pro-lifted) —
5
+ * the model reasons to the output wall with ZERO tool calls, so every
6
+ * existing guard (which all count tool calls) is blind to it.
7
+ *
8
+ * Mechanism: extends the R18b/R32 empty-response-retry precedent to
9
+ * ACTLESS-VERBOSE responses — one injected "act first" steering retry,
10
+ * bounded, fallback-accept. Default OFF (`CORTEX_INACTION_NUDGE=true` arms
11
+ * it; bench/server profiles arm, interactive CLI stays off until specificity
12
+ * is proven broadly).
13
+ */
14
+ export interface InactionCheckInput {
15
+ /** Total visible text+thinking characters of the final assistant response. */
16
+ responseChars: number;
17
+ /** Tool_use blocks in THIS assistant response (0 at the natural exit). */
18
+ toolUseBlocksThisResponse: number;
19
+ /** Tool calls executed across the ENTIRE turn so far. */
20
+ executedToolCallsThisTurn: number;
21
+ /** Tools offered on the request (0 = pure-chat, guard never fires). */
22
+ toolsOffered: number;
23
+ /** Orchestrator turn counter (0 = first turn of the session). v1 gate:
24
+ * only the first turn — later turns of a conversation are much more
25
+ * likely to be legitimately analytic follow-ups. */
26
+ turnNumber: number;
27
+ /** Single-nudge bound (mirrors emptyResponseRetryUsed). */
28
+ alreadyNudged: boolean;
29
+ }
30
+ /** Resolve arming + threshold from env. Default OFF; threshold default 4000
31
+ * chars (the TB2 never-acted signature was multi-thousand-char reasoning
32
+ * dumps — short direct answers must never trigger). */
33
+ export declare function resolveInactionConfig(env?: NodeJS.ProcessEnv): {
34
+ enabled: boolean;
35
+ minChars: number;
36
+ };
37
+ /** Should the inaction nudge fire? Pure — all state passed in. */
38
+ export declare function shouldNudgeInaction(input: InactionCheckInput, env?: NodeJS.ProcessEnv): boolean;
39
+ /** The injected steering text (system-reminder-wrapped by the caller's
40
+ * standard synthetic-user-message shape). */
41
+ export declare function formatInactionNudge(): string;
42
+ //# sourceMappingURL=inactionGuard.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inactionGuard.d.ts","sourceRoot":"","sources":["../../src/orchestrator/inactionGuard.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,MAAM,WAAW,kBAAkB;IACjC,8EAA8E;IAC9E,aAAa,EAAE,MAAM,CAAC;IACtB,0EAA0E;IAC1E,yBAAyB,EAAE,MAAM,CAAC;IAClC,yDAAyD;IACzD,yBAAyB,EAAE,MAAM,CAAC;IAClC,uEAAuE;IACvE,YAAY,EAAE,MAAM,CAAC;IACrB;;yDAEqD;IACrD,UAAU,EAAE,MAAM,CAAC;IACnB,2DAA2D;IAC3D,aAAa,EAAE,OAAO,CAAC;CACxB;AAED;;wDAEwD;AACxD,wBAAgB,qBAAqB,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG;IAC3E,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;CAClB,CAKA;AAED,kEAAkE;AAClE,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,kBAAkB,EACzB,GAAG,GAAE,MAAM,CAAC,UAAwB,GACnC,OAAO,CAST;AAED;8CAC8C;AAC9C,wBAAgB,mBAAmB,IAAI,MAAM,CAM5C"}
@@ -0,0 +1,47 @@
1
+ /**
2
+ * inactionGuard — the loop ladder's INVERSE (docs/HARNESS_IMPROVEMENT_BACKLOG.md
3
+ * item 2). TB2 2×2 evidence: persist-frame arms produced never-acted /
4
+ * over-deliberated failures (5 pro-persist, 2 each flash arm, 0 pro-lifted) —
5
+ * the model reasons to the output wall with ZERO tool calls, so every
6
+ * existing guard (which all count tool calls) is blind to it.
7
+ *
8
+ * Mechanism: extends the R18b/R32 empty-response-retry precedent to
9
+ * ACTLESS-VERBOSE responses — one injected "act first" steering retry,
10
+ * bounded, fallback-accept. Default OFF (`CORTEX_INACTION_NUDGE=true` arms
11
+ * it; bench/server profiles arm, interactive CLI stays off until specificity
12
+ * is proven broadly).
13
+ */
14
+ /** Resolve arming + threshold from env. Default OFF; threshold default 4000
15
+ * chars (the TB2 never-acted signature was multi-thousand-char reasoning
16
+ * dumps — short direct answers must never trigger). */
17
+ export function resolveInactionConfig(env = process.env) {
18
+ const enabled = (env.CORTEX_INACTION_NUDGE ?? '').trim().toLowerCase() === 'true';
19
+ const raw = env.CORTEX_INACTION_MIN_CHARS?.trim();
20
+ const minChars = raw && /^\d+$/.test(raw) && Number(raw) > 0 ? Number(raw) : 4000;
21
+ return { enabled, minChars };
22
+ }
23
+ /** Should the inaction nudge fire? Pure — all state passed in. */
24
+ export function shouldNudgeInaction(input, env = process.env) {
25
+ const cfg = resolveInactionConfig(env);
26
+ if (!cfg.enabled)
27
+ return false;
28
+ if (input.alreadyNudged)
29
+ return false;
30
+ if (input.toolsOffered === 0)
31
+ return false; // pure-chat request
32
+ if (input.turnNumber !== 0)
33
+ return false; // conservative v1: first turn only
34
+ if (input.toolUseBlocksThisResponse > 0)
35
+ return false;
36
+ if (input.executedToolCallsThisTurn > 0)
37
+ return false; // it acted earlier this turn
38
+ return input.responseChars >= cfg.minChars;
39
+ }
40
+ /** The injected steering text (system-reminder-wrapped by the caller's
41
+ * standard synthetic-user-message shape). */
42
+ export function formatInactionNudge() {
43
+ return ('You produced a long analysis but ran no commands. Act first: run at least ' +
44
+ 'one tool call to ground or execute your plan (inspect the actual files/state, ' +
45
+ 'or make the first concrete change), then answer. Do not restate the plan.');
46
+ }
47
+ //# sourceMappingURL=inactionGuard.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inactionGuard.js","sourceRoot":"","sources":["../../src/orchestrator/inactionGuard.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAmBH;;wDAEwD;AACxD,MAAM,UAAU,qBAAqB,CAAC,MAAyB,OAAO,CAAC,GAAG;IAIxE,MAAM,OAAO,GAAG,CAAC,GAAG,CAAC,qBAAqB,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,KAAK,MAAM,CAAC;IAClF,MAAM,GAAG,GAAG,GAAG,CAAC,yBAAyB,EAAE,IAAI,EAAE,CAAC;IAClD,MAAM,QAAQ,GAAG,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAClF,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAC;AAC/B,CAAC;AAED,kEAAkE;AAClE,MAAM,UAAU,mBAAmB,CACjC,KAAyB,EACzB,MAAyB,OAAO,CAAC,GAAG;IAEpC,MAAM,GAAG,GAAG,qBAAqB,CAAC,GAAG,CAAC,CAAC;IACvC,IAAI,CAAC,GAAG,CAAC,OAAO;QAAE,OAAO,KAAK,CAAC;IAC/B,IAAI,KAAK,CAAC,aAAa;QAAE,OAAO,KAAK,CAAC;IACtC,IAAI,KAAK,CAAC,YAAY,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC,CAAC,oBAAoB;IAChE,IAAI,KAAK,CAAC,UAAU,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC,CAAC,mCAAmC;IAC7E,IAAI,KAAK,CAAC,yBAAyB,GAAG,CAAC;QAAE,OAAO,KAAK,CAAC;IACtD,IAAI,KAAK,CAAC,yBAAyB,GAAG,CAAC;QAAE,OAAO,KAAK,CAAC,CAAC,6BAA6B;IACpF,OAAO,KAAK,CAAC,aAAa,IAAI,GAAG,CAAC,QAAQ,CAAC;AAC7C,CAAC;AAED;8CAC8C;AAC9C,MAAM,UAAU,mBAAmB;IACjC,OAAO,CACL,4EAA4E;QAC5E,gFAAgF;QAChF,2EAA2E,CAC5E,CAAC;AACJ,CAAC"}
@@ -0,0 +1,43 @@
1
+ /**
2
+ * requirementsVerification — EndTurn Stage 4 (docs/HARNESS_IMPROVEMENT_BACKLOG.md
3
+ * item 1). The as-shipped gate verifies CITATIONS (Stage 2 grounding, Stage 3
4
+ * coordinates) but not TASK REQUIREMENTS: a wrong-artifact finish passes with
5
+ * honest citations and a legitimate empty `verification` ("none asked") —
6
+ * TB2's 2nd-largest failure class (20 wrong-artifact fails, 11 in
7
+ * flash-persist alone). Stage 4 makes the model re-read the task statement
8
+ * and attest each stated requirement.
9
+ *
10
+ * Armed by CORTEX_ENDTURN_REQUIREMENTS=true (off by default; the
11
+ * persist+EndTurn bench cell and server profiles arm it). Pure — the
12
+ * orchestrator supplies all state.
13
+ */
14
+ export interface RequirementRow {
15
+ requirement: string;
16
+ satisfied_by: string;
17
+ verified_how: string;
18
+ }
19
+ export interface RequirementsVerdict {
20
+ ok: boolean;
21
+ /** Rejection text to surface on the EndTurn tool_result (Stage-2 style). */
22
+ nudge?: string;
23
+ }
24
+ export declare function resolveEndTurnRequirementsMode(env?: NodeJS.ProcessEnv): boolean;
25
+ /** Conservative imperative/task-shape heuristic: does the user text ask for
26
+ * work (vs. a question/discussion)? False negatives are acceptable (no
27
+ * nudge); false positives are the cost to avoid. */
28
+ export declare function isTaskShaped(userText: string): boolean;
29
+ /**
30
+ * Stage 4: verify the `requirements` attestation. Caller gates on
31
+ * resolveEndTurnRequirementsMode() — this function assumes armed mode.
32
+ */
33
+ export declare function verifyRequirements(input: {
34
+ /** Raw `requirements` value from the EndTurn tool input. */
35
+ requirements: unknown;
36
+ /** Raw `verification` value from the EndTurn tool input. */
37
+ verification: unknown;
38
+ /** The turn's real user prompt text (empty string when unknown). */
39
+ userTaskText: string;
40
+ /** Did this turn run Edit/Write/Bash/NotebookEdit? */
41
+ turnUsedMutatingTool: boolean;
42
+ }): RequirementsVerdict;
43
+ //# sourceMappingURL=requirementsVerification.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"requirementsVerification.d.ts","sourceRoot":"","sources":["../../src/orchestrator/requirementsVerification.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,MAAM,WAAW,cAAc;IAC7B,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,mBAAmB;IAClC,EAAE,EAAE,OAAO,CAAC;IACZ,4EAA4E;IAC5E,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,wBAAgB,8BAA8B,CAC5C,GAAG,GAAE,MAAM,CAAC,UAAwB,GACnC,OAAO,CAET;AAED;;qDAEqD;AACrD,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAKtD;AAID;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE;IACxC,4DAA4D;IAC5D,YAAY,EAAE,OAAO,CAAC;IACtB,4DAA4D;IAC5D,YAAY,EAAE,OAAO,CAAC;IACtB,oEAAoE;IACpE,YAAY,EAAE,MAAM,CAAC;IACrB,sDAAsD;IACtD,oBAAoB,EAAE,OAAO,CAAC;CAC/B,GAAG,mBAAmB,CAoEtB"}
@@ -0,0 +1,87 @@
1
+ /**
2
+ * requirementsVerification — EndTurn Stage 4 (docs/HARNESS_IMPROVEMENT_BACKLOG.md
3
+ * item 1). The as-shipped gate verifies CITATIONS (Stage 2 grounding, Stage 3
4
+ * coordinates) but not TASK REQUIREMENTS: a wrong-artifact finish passes with
5
+ * honest citations and a legitimate empty `verification` ("none asked") —
6
+ * TB2's 2nd-largest failure class (20 wrong-artifact fails, 11 in
7
+ * flash-persist alone). Stage 4 makes the model re-read the task statement
8
+ * and attest each stated requirement.
9
+ *
10
+ * Armed by CORTEX_ENDTURN_REQUIREMENTS=true (off by default; the
11
+ * persist+EndTurn bench cell and server profiles arm it). Pure — the
12
+ * orchestrator supplies all state.
13
+ */
14
+ export function resolveEndTurnRequirementsMode(env = process.env) {
15
+ return (env.CORTEX_ENDTURN_REQUIREMENTS ?? '').trim().toLowerCase() === 'true';
16
+ }
17
+ /** Conservative imperative/task-shape heuristic: does the user text ask for
18
+ * work (vs. a question/discussion)? False negatives are acceptable (no
19
+ * nudge); false positives are the cost to avoid. */
20
+ export function isTaskShaped(userText) {
21
+ if (!userText || userText.length < 8)
22
+ return false;
23
+ return /\b(fix|add|implement|create|write|build|make|update|refactor|convert|generate|install|configure|set up|setup|remove|delete|rename|migrate|optimi[sz]e|debug|repair|extract|compress|decompress|parse|train|deploy|run)\b/i.test(userText);
24
+ }
25
+ const UNVERIFIED_RE = /^\s*unverified\s*$/i;
26
+ /**
27
+ * Stage 4: verify the `requirements` attestation. Caller gates on
28
+ * resolveEndTurnRequirementsMode() — this function assumes armed mode.
29
+ */
30
+ export function verifyRequirements(input) {
31
+ const reqs = Array.isArray(input.requirements) ? input.requirements : null;
32
+ const verification = Array.isArray(input.verification) ? input.verification : [];
33
+ // 4a — task-shaped turn with no requirements enumerated.
34
+ if ((!reqs || reqs.length === 0) && isTaskShaped(input.userTaskText)) {
35
+ return {
36
+ ok: false,
37
+ nudge: 'EndTurn REJECTED (requirements) — this turn has a stated task but you enumerated no requirements. ' +
38
+ 'Re-read the task statement and list EACH stated requirement in `requirements` ' +
39
+ '[{requirement, satisfied_by, verified_how}]: `satisfied_by` = what in your artifact satisfies it; ' +
40
+ '`verified_how` = the command/observation that proves it, or the literal string "UNVERIFIED". ' +
41
+ 'Then call EndTurn again.',
42
+ };
43
+ }
44
+ // 4b — malformed rows.
45
+ if (reqs) {
46
+ const bad = reqs.findIndex((r) => !r ||
47
+ typeof r !== 'object' ||
48
+ typeof r.requirement !== 'string' ||
49
+ typeof r.satisfied_by !== 'string' ||
50
+ typeof r.verified_how !== 'string');
51
+ if (bad !== -1) {
52
+ return {
53
+ ok: false,
54
+ nudge: `EndTurn REJECTED (requirements) — row ${bad + 1} is malformed. Each row must be ` +
55
+ '{requirement, satisfied_by, verified_how} (strings). Use "UNVERIFIED" as verified_how ' +
56
+ 'when you did not verify a requirement — do not omit the field. Then call EndTurn again.',
57
+ };
58
+ }
59
+ // 4c — unverified rows must be nudged ONCE toward verification.
60
+ const unverified = reqs.filter((r) => UNVERIFIED_RE.test(r.verified_how));
61
+ if (unverified.length > 0) {
62
+ const names = unverified
63
+ .slice(0, 3)
64
+ .map((r) => `"${r.requirement.slice(0, 80)}"`)
65
+ .join(', ');
66
+ return {
67
+ ok: false,
68
+ nudge: `EndTurn REJECTED (requirements) — ${unverified.length} requirement(s) are UNVERIFIED: ${names}. ` +
69
+ 'For each: either RUN the check that proves it (then put the command + observed result in ' +
70
+ '`verified_how`), or move it to `open_items` with a one-line justification and delete the row. ' +
71
+ 'Then call EndTurn again.',
72
+ };
73
+ }
74
+ }
75
+ // 4d — mutating turn that ran no checks at all.
76
+ if (input.turnUsedMutatingTool && verification.length === 0) {
77
+ return {
78
+ ok: false,
79
+ nudge: 'EndTurn REJECTED (verification) — you modified files this turn but `verification` is empty: ' +
80
+ 'no build/test/lint/behavior check was run. Run at least one check that exercises what you ' +
81
+ 'changed and list it with the real result line, or state in `open_items` why no check is ' +
82
+ 'possible. Then call EndTurn again.',
83
+ };
84
+ }
85
+ return { ok: true };
86
+ }
87
+ //# sourceMappingURL=requirementsVerification.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"requirementsVerification.js","sourceRoot":"","sources":["../../src/orchestrator/requirementsVerification.ts"],"names":[],"mappings":"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"}
@@ -29,6 +29,15 @@ export declare function resolveToolProfile(env?: NodeJS.ProcessEnv): ToolProfile
29
29
  * — the dsh anchored-standard point). 'full' or unknown → no anchor.
30
30
  */
31
31
  export declare function resolveToolAnchor(env?: NodeJS.ProcessEnv, cardAnchor?: string | null): ToolProfileName | null;
32
+ /**
33
+ * CORTEX_TOOL_ANCHOR_PERSIST — frame selection for an armed anchor (backlog
34
+ * item 5). 'lifted' (default): the anchor lifts at the first tool_result
35
+ * boundary and the session's full profile applies. 'persist': the anchored
36
+ * surface stays the ONLY surface for the whole session (the TB2 persist
37
+ * frame, previously an installed-copy patch). Precedence: env override >
38
+ * card frameProfile > 'lifted'. Irrelevant when no anchor is armed.
39
+ */
40
+ export declare function resolveFrameProfile(env?: NodeJS.ProcessEnv, cardFrame?: string | null): 'lifted' | 'persist';
32
41
  /** Do MCP / management / context tools ride along? Narrow arms suppress them
33
42
  * (surface leak otherwise); full and lean keep them. */
34
43
  export declare function isNarrowProfile(profile?: ToolProfileName): boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"ToolProfile.d.ts","sourceRoot":"","sources":["../../src/tools/ToolProfile.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,MAAM,MAAM,eAAe,GAAG,MAAM,GAAG,MAAM,GAAG,WAAW,GAAG,WAAW,GAAG,WAAW,CAAC;AAoBxF,wBAAgB,kBAAkB,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,eAAe,CAIxF;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAC/B,GAAG,GAAE,MAAM,CAAC,UAAwB,EACpC,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,GACzB,eAAe,GAAG,IAAI,CASxB;AAED;yDACyD;AACzD,wBAAgB,eAAe,CAAC,OAAO,GAAE,eAAsC,GAAG,OAAO,CAExF;AAED;;;;;;;;GAQG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,SAAS;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,aAAa,CAAC,EAAE,MAAM,CAAA;CAAE,EACjF,KAAK,EAAE,CAAC,EAAE,EACV,OAAO,GAAE,eAAsC,GAC9C,CAAC,EAAE,CAML;AAED;8EAC8E;AAC9E,wBAAgB,sBAAsB,CACpC,IAAI,EAAE,MAAM,EACZ,UAAU,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,EAChD,OAAO,GAAE,eAAsC,GAC9C,OAAO,CAOT"}
1
+ {"version":3,"file":"ToolProfile.d.ts","sourceRoot":"","sources":["../../src/tools/ToolProfile.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,MAAM,MAAM,eAAe,GAAG,MAAM,GAAG,MAAM,GAAG,WAAW,GAAG,WAAW,GAAG,WAAW,CAAC;AAwBxF,wBAAgB,kBAAkB,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,eAAe,CAIxF;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAC/B,GAAG,GAAE,MAAM,CAAC,UAAwB,EACpC,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,GACzB,eAAe,GAAG,IAAI,CASxB;AAED;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CACjC,GAAG,GAAE,MAAM,CAAC,UAAwB,EACpC,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,GACxB,QAAQ,GAAG,SAAS,CAOtB;AAED;yDACyD;AACzD,wBAAgB,eAAe,CAAC,OAAO,GAAE,eAAsC,GAAG,OAAO,CAExF;AAED;;;;;;;;GAQG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,SAAS;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,aAAa,CAAC,EAAE,MAAM,CAAA;CAAE,EACjF,KAAK,EAAE,CAAC,EAAE,EACV,OAAO,GAAE,eAAsC,GAC9C,CAAC,EAAE,CAML;AAED;8EAC8E;AAC9E,wBAAgB,sBAAsB,CACpC,IAAI,EAAE,MAAM,EACZ,UAAU,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,EAChD,OAAO,GAAE,eAAsC,GAC9C,OAAO,CAOT"}
@@ -28,11 +28,15 @@ const ALWAYS_KEEP = new Set(['EndTurn', 'AskUserQuestion']);
28
28
  const BASH_ONLY = new Set(['Bash', ...ALWAYS_KEEP]);
29
29
  /** bash-plus: the minimal-harness arm (BASH_PLUS_SPEC.md, R61) — the Pi/dsh
30
30
  * surface class: shell + structural file ops, nothing else. The shell-native
31
- * small-model graduation target and P1 anchoring-A/B arm. */
32
- const BASH_PLUS = new Set(['Bash', 'Read', 'Edit', 'Write', ...ALWAYS_KEEP]);
31
+ * small-model graduation target and P1 anchoring-A/B arm.
32
+ * ReadImage rides the practical doors (item 7): the orchestrator's VISION
33
+ * GATE strips it for non-vision cards BEFORE profile filtering, so set
34
+ * membership changes nothing for existing text-only frames — a vision card
35
+ * under a narrow door gets door+ReadImage (the vision-arm shape). */
36
+ const BASH_PLUS = new Set(['Bash', 'Read', 'Edit', 'Write', 'ReadImage', ...ALWAYS_KEEP]);
33
37
  /** bash-edit: the dsh-Minimal shape — shell + structural editor ONLY (their
34
38
  * bash + str_replace_editor). The deepseek home-door candidate. */
35
- const BASH_EDIT = new Set(['Bash', 'Edit', ...ALWAYS_KEEP]);
39
+ const BASH_EDIT = new Set(['Bash', 'Edit', 'ReadImage', ...ALWAYS_KEEP]);
36
40
  export function resolveToolProfile(env = process.env) {
37
41
  const raw = (env.CORTEX_TOOL_PROFILE ?? 'full').trim().toLowerCase();
38
42
  if (raw === 'lean' || raw === 'bash-only' || raw === 'bash-plus' || raw === 'bash-edit')
@@ -58,6 +62,25 @@ export function resolveToolAnchor(env = process.env, cardAnchor) {
58
62
  return card;
59
63
  return null;
60
64
  }
65
+ /**
66
+ * CORTEX_TOOL_ANCHOR_PERSIST — frame selection for an armed anchor (backlog
67
+ * item 5). 'lifted' (default): the anchor lifts at the first tool_result
68
+ * boundary and the session's full profile applies. 'persist': the anchored
69
+ * surface stays the ONLY surface for the whole session (the TB2 persist
70
+ * frame, previously an installed-copy patch). Precedence: env override >
71
+ * card frameProfile > 'lifted'. Irrelevant when no anchor is armed.
72
+ */
73
+ export function resolveFrameProfile(env = process.env, cardFrame) {
74
+ const raw = (env.CORTEX_TOOL_ANCHOR_PERSIST ?? '').trim().toLowerCase();
75
+ if (raw === 'true' || raw === '1' || raw === 'persist')
76
+ return 'persist';
77
+ if (raw === 'false' || raw === '0' || raw === 'off' || raw === 'lifted')
78
+ return 'lifted';
79
+ const card = (cardFrame ?? '').trim().toLowerCase();
80
+ if (card === 'persist')
81
+ return 'persist';
82
+ return 'lifted';
83
+ }
61
84
  /** Do MCP / management / context tools ride along? Narrow arms suppress them
62
85
  * (surface leak otherwise); full and lean keep them. */
63
86
  export function isNarrowProfile(profile = resolveToolProfile()) {
@@ -1 +1 @@
1
- {"version":3,"file":"ToolProfile.js","sourceRoot":"","sources":["../../src/tools/ToolProfile.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ToolProfile.js","sourceRoot":"","sources":["../../src/tools/ToolProfile.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"BaseToolRegistry.d.ts","sourceRoot":"","sources":["../../../src/tools/registries/BaseToolRegistry.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,uBAAuB,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAgnErG;;GAEG;AACH,qBAAa,gBAAiB,YAAW,YAAY;IACnD,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAuC;;IAS7D;;OAEG;IACH,WAAW,IAAI,uBAAuB,EAAE;IAIxC;;OAEG;IACH,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,uBAAuB,GAAG,SAAS;IAI1D;;OAEG;IACH,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAI9B;;OAEG;IACH,kBAAkB,CAAC,QAAQ,EAAE,YAAY,GAAG,uBAAuB,EAAE;IAIrE;;OAEG;IACH,YAAY,IAAI,MAAM;CAGvB;AAGD,eAAO,MAAM,gBAAgB,kBAAyB,CAAC"}
1
+ {"version":3,"file":"BaseToolRegistry.d.ts","sourceRoot":"","sources":["../../../src/tools/registries/BaseToolRegistry.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,uBAAuB,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAypErG;;GAEG;AACH,qBAAa,gBAAiB,YAAW,YAAY;IACnD,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAuC;;IAS7D;;OAEG;IACH,WAAW,IAAI,uBAAuB,EAAE;IAIxC;;OAEG;IACH,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,uBAAuB,GAAG,SAAS;IAI1D;;OAEG;IACH,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAI9B;;OAEG;IACH,kBAAkB,CAAC,QAAQ,EAAE,YAAY,GAAG,uBAAuB,EAAE;IAIrE;;OAEG;IACH,YAAY,IAAI,MAAM;CAGvB;AAGD,eAAO,MAAM,gBAAgB,kBAAyB,CAAC"}
@@ -20,7 +20,7 @@ const BASE_TOOLS = [
20
20
  By default, it reads up to 2000 lines starting from the beginning of the file.
21
21
  When you already know which part of the file you need, only read that part. This can be important for larger files.
22
22
  Results are returned using cat -n format, with line numbers starting at 1.
23
- This tool can read images (PNG, JPG, etc), PDFs (.pdf — for large PDFs provide the pages parameter, max 20 pages per request), and Jupyter notebooks (.ipynb — returns all cells with outputs).
23
+ This tool reads TEXT files. For images (PNG/JPG/GIF/WebP) use the ReadImage tool when available Read on a binary file returns unusable bytes.
24
24
  Do NOT re-read a file you just edited to verify — Edit would have errored if the change failed, and the harness tracks file state for you.`,
25
25
  schema: {
26
26
  type: 'object',
@@ -113,6 +113,33 @@ GUIDANCE:
113
113
  version: '1.0.0'
114
114
  }
115
115
  },
116
+ {
117
+ name: 'ReadImage',
118
+ description: `Load an image file (PNG, JPEG, GIF, or WebP) so you can SEE it — the image is attached to the conversation as visual input on the next message. Use this to inspect screenshots, diagrams, charts, rendered output, or video frames (extract frames first, e.g. via ffmpeg).
119
+
120
+ GUIDANCE:
121
+ - Only available when the active model supports image input.
122
+ - Format is detected from file content (magic bytes), not the extension.
123
+ - Large images: the provider downscales (~800x800) — no need to resize first unless over the 32 MiB limit.
124
+ - Unsupported formats (BMP/TIFF/PDF): convert first (e.g. Bash + Python PIL), then ReadImage.`,
125
+ schema: {
126
+ type: 'object',
127
+ properties: {
128
+ file_path: {
129
+ type: 'string',
130
+ description: 'Path to the image file (absolute, or relative to the working directory).'
131
+ }
132
+ },
133
+ required: ['file_path']
134
+ },
135
+ category: 'base',
136
+ discoveryTier: 'essential', // vision-gated; must be on TURN 1 (deferred loading hid it behind SearchTools — live-probe finding 2026-08-25),
137
+ metadata: {
138
+ immutable: true,
139
+ executionEnvironment: 'client',
140
+ version: '1.0.0'
141
+ }
142
+ },
116
143
  {
117
144
  name: 'Edit',
118
145
  description: `Performs exact string replacements in files.
@@ -950,6 +977,7 @@ Use plan mode for tasks with genuine ambiguity — multiple reasonable architect
950
977
 
951
978
  - citations: list EACH specific reference in your draft with the exact verbatim source you copied it from this turn. If you cannot produce the verbatim source, the reference is unverified — delete it from your answer and do not list it (quote the code instead of asserting a coordinate). Inventing one is a failed answer, exactly like a non-matching edit old_string.
952
979
  - verification: list each build/test/lint command you actually ran with the real result line you saw. Do not list a command you did not run.
980
+ - requirements: re-read the ORIGINAL task statement and list each requirement it states, with what in your artifact satisfies it and the command/observation that proves it (or the literal "UNVERIFIED"). Finishing without checking the artifact against the stated task is the most common failed answer.
953
981
  - self_review: re-read your draft as a skeptical reviewer — what you did NOT check, what is assumed/possibly wrong, what one more tool call would verify. This pass exists to catch your own mistakes before they ship.
954
982
  - summary / open_items: what you delivered and any gaps — do not hide them.
955
983
 
@@ -981,6 +1009,19 @@ After EndTurn returns, act on your own self_review, then produce your final plai
981
1009
  required: ['command', 'observed_result']
982
1010
  }
983
1011
  },
1012
+ requirements: {
1013
+ type: 'array',
1014
+ description: 'Each requirement STATED in the original task, checked against your artifact. Empty array = the turn had no stated task. verified_how is the command/observation proving the requirement is met, or the literal string "UNVERIFIED".',
1015
+ items: {
1016
+ type: 'object',
1017
+ properties: {
1018
+ requirement: { type: 'string', description: 'A requirement as stated in the task.' },
1019
+ satisfied_by: { type: 'string', description: 'What in your artifact satisfies it.' },
1020
+ verified_how: { type: 'string', description: 'The command/observation that proves it — or "UNVERIFIED".' }
1021
+ },
1022
+ required: ['requirement', 'satisfied_by', 'verified_how']
1023
+ }
1024
+ },
984
1025
  summary: {
985
1026
  type: 'string',
986
1027
  description: 'One sentence: what you delivered this turn.'