@caupulican/pi-agent-core 0.86.14 → 0.90.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 (58) hide show
  1. package/dist/agent-loop.d.ts +2 -13
  2. package/dist/agent-loop.d.ts.map +1 -1
  3. package/dist/agent-loop.js +279 -146
  4. package/dist/agent-loop.js.map +1 -1
  5. package/dist/agent.d.ts +5 -1
  6. package/dist/agent.d.ts.map +1 -1
  7. package/dist/agent.js +4 -0
  8. package/dist/agent.js.map +1 -1
  9. package/dist/compaction/branch-summarization.d.ts.map +1 -1
  10. package/dist/compaction/branch-summarization.js +11 -15
  11. package/dist/compaction/branch-summarization.js.map +1 -1
  12. package/dist/compaction/compaction.d.ts +3 -0
  13. package/dist/compaction/compaction.d.ts.map +1 -1
  14. package/dist/compaction/compaction.js +37 -46
  15. package/dist/compaction/compaction.js.map +1 -1
  16. package/dist/compaction/loop.d.ts +4 -0
  17. package/dist/compaction/loop.d.ts.map +1 -1
  18. package/dist/compaction/loop.js +7 -2
  19. package/dist/compaction/loop.js.map +1 -1
  20. package/dist/compaction/utils.d.ts +1 -1
  21. package/dist/compaction/utils.d.ts.map +1 -1
  22. package/dist/compaction/utils.js +13 -41
  23. package/dist/compaction/utils.js.map +1 -1
  24. package/dist/compaction/verification.js +2 -2
  25. package/dist/compaction/verification.js.map +1 -1
  26. package/dist/index.d.ts +2 -0
  27. package/dist/index.d.ts.map +1 -1
  28. package/dist/index.js +4 -0
  29. package/dist/index.js.map +1 -1
  30. package/dist/provider-request-estimator.d.ts +6 -0
  31. package/dist/provider-request-estimator.d.ts.map +1 -0
  32. package/dist/provider-request-estimator.js +105 -0
  33. package/dist/provider-request-estimator.js.map +1 -0
  34. package/dist/provider-request-planner.d.ts +15 -0
  35. package/dist/provider-request-planner.d.ts.map +1 -0
  36. package/dist/provider-request-planner.js +168 -0
  37. package/dist/provider-request-planner.js.map +1 -0
  38. package/dist/provider-tool-projection.d.ts +7 -0
  39. package/dist/provider-tool-projection.d.ts.map +1 -0
  40. package/dist/provider-tool-projection.js +140 -0
  41. package/dist/provider-tool-projection.js.map +1 -0
  42. package/dist/tool-failure-memory.d.ts +8 -0
  43. package/dist/tool-failure-memory.d.ts.map +1 -1
  44. package/dist/tool-failure-memory.js +163 -70
  45. package/dist/tool-failure-memory.js.map +1 -1
  46. package/dist/tool-failure-recovery-gate.d.ts +60 -0
  47. package/dist/tool-failure-recovery-gate.d.ts.map +1 -0
  48. package/dist/tool-failure-recovery-gate.js +386 -0
  49. package/dist/tool-failure-recovery-gate.js.map +1 -0
  50. package/dist/tool-failure-recovery-protocol.d.ts +15 -0
  51. package/dist/tool-failure-recovery-protocol.d.ts.map +1 -0
  52. package/dist/tool-failure-recovery-protocol.js +43 -0
  53. package/dist/tool-failure-recovery-protocol.js.map +1 -0
  54. package/dist/types.d.ts +115 -8
  55. package/dist/types.d.ts.map +1 -1
  56. package/dist/types.js +12 -0
  57. package/dist/types.js.map +1 -1
  58. package/package.json +2 -2
@@ -0,0 +1,386 @@
1
+ import { getToolExecutionUnchangedRetryLimit } from "@caupulican/pi-ai/tool-repair-registry";
2
+ import { getToolExecutionKey, getToolFailureRecordExecutionKey, } from "./tool-failure-memory.js";
3
+ import { isAgentToolFailureRecoveryAuthority } from "./types.js";
4
+ const MAX_BLOCKED_REPLAYS_PER_FAILURE = 2;
5
+ const BASE_FAILURE_EXECUTIONS_PER_OPERATION = 1;
6
+ const MAX_RECOVERY_PROBES_PER_OPERATION = 1;
7
+ const MAX_REJECTIONS_PER_OPERATION = 4;
8
+ export const TOOL_FAILURE_RECOVERY_ACCOUNTING_WAVE_SIZE = 4;
9
+ const MAX_FAILURES_PER_FAMILY = TOOL_FAILURE_RECOVERY_ACCOUNTING_WAVE_SIZE;
10
+ const MAX_FAILURES_PER_RUN = 12;
11
+ const MAX_RECOVERY_STATES = 64;
12
+ const MAX_RECOVERY_TARGETS = 8;
13
+ const MAX_RECOVERY_ACTIONS = 8;
14
+ const MAX_TARGET_KIND_CHARS = 64;
15
+ const MAX_TARGET_SCOPE_CHARS = 32_768;
16
+ const MAX_ACTION_INSTRUCTION_CHARS = 160;
17
+ const MAX_RECOVERY_GUIDANCE_CHARS = 320;
18
+ const TARGET_KIND_PATTERN = /^[a-z0-9][a-z0-9._:-]*$/;
19
+ /**
20
+ * Owns run-scoped execution admission and bounded unresolved-failure budgets.
21
+ *
22
+ * Recovery authority is exact and tool-owned. A failed tool declares opaque backend-specific targets;
23
+ * a loaded recovery tool may teach actions only for the same authority and target kind. Only raw
24
+ * successful repair evidence with byte-exact scope can reopen one probe. Argument text and hooks have
25
+ * no recovery authority.
26
+ */
27
+ export class ToolFailureRecoveryGate {
28
+ constructor() {
29
+ this.statesByExecutionKey = new Map();
30
+ this.failuresByFamily = new Map();
31
+ this.totalFailures = 0;
32
+ }
33
+ planFailure(failedTool, args, failureCode, availableTools, reservation) {
34
+ const targets = readFailureTargets(failedTool, args, failureCode);
35
+ const actions = readAvailableRecoveryActions(availableTools, targets);
36
+ const unchangedRetryRemaining = this.hasUnchangedRetryRemaining(failedTool, args, failureCode, reservation);
37
+ return {
38
+ targets,
39
+ guidance: formatRecoveryGuidance(failureCode, actions, unchangedRetryRemaining),
40
+ };
41
+ }
42
+ admit(tool, args, record) {
43
+ const stateCapacityHalt = this.halted;
44
+ if (stateCapacityHalt) {
45
+ return {
46
+ kind: "blocked",
47
+ record: stateCapacityHalt.record,
48
+ exhausted: true,
49
+ diagnostic: stateCapacityHalt.diagnostic,
50
+ };
51
+ }
52
+ const executionKey = getToolExecutionKey(tool.name, args);
53
+ let state = this.statesByExecutionKey.get(executionKey);
54
+ if (!state && record && getToolFailureRecordExecutionKey(record) === executionKey) {
55
+ state = this.getOrCreateState(executionKey, record, readFailureTargets(tool, args, record.failureCode));
56
+ }
57
+ if (this.halted) {
58
+ return {
59
+ kind: "blocked",
60
+ record: this.halted.record,
61
+ exhausted: true,
62
+ diagnostic: this.halted.diagnostic,
63
+ };
64
+ }
65
+ if (!state)
66
+ return { kind: "allowed" };
67
+ if (record)
68
+ state.record = record;
69
+ const automaticExecutionLimit = BASE_FAILURE_EXECUTIONS_PER_OPERATION + getToolExecutionUnchangedRetryLimit(state.record.failureCode);
70
+ if (state.reservedExecutions < automaticExecutionLimit) {
71
+ state.reservedExecutions++;
72
+ state.blockedReplays = 0;
73
+ return { kind: "allowed", reservation: { executionKey } };
74
+ }
75
+ if (state.recoveryAvailable && state.recoveryProbes < MAX_RECOVERY_PROBES_PER_OPERATION) {
76
+ state.recoveryAvailable = false;
77
+ state.recoveryProbes++;
78
+ state.reservedExecutions++;
79
+ state.blockedReplays = 0;
80
+ return { kind: "allowed", reservation: { executionKey } };
81
+ }
82
+ state.blockedReplays++;
83
+ if (state.blockedReplays >= MAX_BLOCKED_REPLAYS_PER_FAILURE) {
84
+ const diagnostic = `Recovery circuit opened after ${state.blockedReplays} blocked replays of ${state.record.failureCode}.`;
85
+ this.halted = { record: state.record, diagnostic };
86
+ return { kind: "blocked", record: state.record, exhausted: true, diagnostic };
87
+ }
88
+ return { kind: "blocked", record: state.record, exhausted: false };
89
+ }
90
+ apply(effect) {
91
+ if (!effect || this.halted)
92
+ return undefined;
93
+ if (effect.kind === "success") {
94
+ this.observeSuccess(effect.tool, effect.args, effect.evidenceResult);
95
+ return undefined;
96
+ }
97
+ this.observeFailure(effect.record, effect.args, effect.targets ?? [], effect.reservation);
98
+ return this.halted;
99
+ }
100
+ isHalted() {
101
+ return this.halted !== undefined;
102
+ }
103
+ getHalt() {
104
+ return this.halted;
105
+ }
106
+ hasUnchangedRetryRemaining(tool, args, failureCode, reservation) {
107
+ const retryLimit = getToolExecutionUnchangedRetryLimit(failureCode);
108
+ if (retryLimit === 0)
109
+ return false;
110
+ const executionKey = getToolExecutionKey(tool.name, args);
111
+ const state = this.statesByExecutionKey.get(executionKey);
112
+ const executionsIncludingCurrent = state
113
+ ? state.reservedExecutions + (reservation?.executionKey === executionKey ? 0 : 1)
114
+ : 1;
115
+ return executionsIncludingCurrent < BASE_FAILURE_EXECUTIONS_PER_OPERATION + retryLimit;
116
+ }
117
+ getOrCreateState(executionKey, record, targets) {
118
+ const existing = this.statesByExecutionKey.get(executionKey);
119
+ if (existing)
120
+ return existing;
121
+ const state = {
122
+ record,
123
+ recoveryTargets: targets,
124
+ reservedExecutions: 0,
125
+ failures: 0,
126
+ failureFamilyCounts: new Map(),
127
+ recoveryProbes: 0,
128
+ blockedReplays: 0,
129
+ recoveryAvailable: false,
130
+ };
131
+ if (this.statesByExecutionKey.size >= MAX_RECOVERY_STATES) {
132
+ this.halted = {
133
+ record,
134
+ diagnostic: `Recovery circuit opened at the ${MAX_RECOVERY_STATES}-operation state bound.`,
135
+ };
136
+ return state;
137
+ }
138
+ this.statesByExecutionKey.set(executionKey, state);
139
+ return state;
140
+ }
141
+ observeFailure(record, args, targets, reservation) {
142
+ const executionKey = getToolExecutionKey(record.tool, args);
143
+ const state = this.getOrCreateState(executionKey, record, targets);
144
+ if (this.halted)
145
+ return;
146
+ state.record = record;
147
+ state.recoveryTargets = targets;
148
+ state.recoveryAvailable = false;
149
+ state.blockedReplays = 0;
150
+ if (reservation?.executionKey !== executionKey)
151
+ state.reservedExecutions++;
152
+ state.failures++;
153
+ this.totalFailures++;
154
+ const familyKey = `${record.tool}\0${record.failureCode}`;
155
+ const familyFailures = (this.failuresByFamily.get(familyKey) ?? 0) + 1;
156
+ this.failuresByFamily.set(familyKey, familyFailures);
157
+ state.failureFamilyCounts.set(familyKey, (state.failureFamilyCounts.get(familyKey) ?? 0) + 1);
158
+ const operationFailureLimit = record.state === "failed"
159
+ ? BASE_FAILURE_EXECUTIONS_PER_OPERATION +
160
+ getToolExecutionUnchangedRetryLimit(record.failureCode) +
161
+ MAX_RECOVERY_PROBES_PER_OPERATION
162
+ : MAX_REJECTIONS_PER_OPERATION;
163
+ if (state.failures >= operationFailureLimit) {
164
+ this.halted = {
165
+ record,
166
+ diagnostic: `Recovery circuit opened after ${state.failures} failed outcomes for one operation.`,
167
+ };
168
+ return;
169
+ }
170
+ if (familyFailures >= MAX_FAILURES_PER_FAMILY) {
171
+ this.halted = {
172
+ record,
173
+ diagnostic: `Recovery circuit opened after ${familyFailures} failures in one tool failure family.`,
174
+ };
175
+ return;
176
+ }
177
+ if (this.totalFailures >= MAX_FAILURES_PER_RUN) {
178
+ this.halted = {
179
+ record,
180
+ diagnostic: `Recovery circuit opened after ${this.totalFailures} tool failures in one run.`,
181
+ };
182
+ }
183
+ }
184
+ observeSuccess(tool, args, result) {
185
+ const successfulExecutionKey = getToolExecutionKey(tool.name, args);
186
+ const evidenceTargets = readRecoveryEvidenceTargets(tool, args, result);
187
+ for (const [executionKey, state] of this.statesByExecutionKey) {
188
+ if (executionKey === successfulExecutionKey) {
189
+ this.clearResolvedState(executionKey, state);
190
+ continue;
191
+ }
192
+ if (state.recoveryProbes < MAX_RECOVERY_PROBES_PER_OPERATION &&
193
+ hasSharedRecoveryTarget(state.recoveryTargets, evidenceTargets)) {
194
+ state.recoveryAvailable = true;
195
+ state.blockedReplays = 0;
196
+ }
197
+ }
198
+ }
199
+ clearResolvedState(executionKey, state) {
200
+ this.statesByExecutionKey.delete(executionKey);
201
+ this.totalFailures = Math.max(0, this.totalFailures - state.failures);
202
+ for (const [familyKey, stateFailures] of state.failureFamilyCounts) {
203
+ const remaining = (this.failuresByFamily.get(familyKey) ?? 0) - stateFailures;
204
+ if (remaining > 0)
205
+ this.failuresByFamily.set(familyKey, remaining);
206
+ else
207
+ this.failuresByFamily.delete(familyKey);
208
+ }
209
+ }
210
+ }
211
+ function readFailureTargets(tool, args, failureCode) {
212
+ try {
213
+ const contract = tool.failureRecovery;
214
+ const getTargets = contract?.getFailureTargets;
215
+ if (!getTargets)
216
+ return [];
217
+ const targets = Reflect.apply(getTargets, contract, [args, { failureCode }]);
218
+ return sanitizeRecoveryTargets(targets);
219
+ }
220
+ catch {
221
+ return [];
222
+ }
223
+ }
224
+ function sanitizeRecoveryTargets(value) {
225
+ if (!Array.isArray(value))
226
+ return [];
227
+ const targets = [];
228
+ for (const candidate of value) {
229
+ if (targets.length >= MAX_RECOVERY_TARGETS)
230
+ break;
231
+ if (!candidate || typeof candidate !== "object" || Array.isArray(candidate))
232
+ continue;
233
+ const { authority, kind, scope } = candidate;
234
+ if (!isAgentToolFailureRecoveryAuthority(authority) || !validTargetKind(kind) || !validTargetScope(scope)) {
235
+ continue;
236
+ }
237
+ if (targets.some((target) => sameRecoveryTarget(target, { authority, kind, scope })))
238
+ continue;
239
+ targets.push({ authority, kind, scope });
240
+ }
241
+ return targets;
242
+ }
243
+ function validTargetKind(value) {
244
+ return (typeof value === "string" &&
245
+ value.length > 0 &&
246
+ value.length <= MAX_TARGET_KIND_CHARS &&
247
+ TARGET_KIND_PATTERN.test(value));
248
+ }
249
+ function validTargetScope(value) {
250
+ return (typeof value === "string" && value.length > 0 && value.length <= MAX_TARGET_SCOPE_CHARS && !value.includes("\0"));
251
+ }
252
+ function readAvailableRecoveryActions(tools, targets) {
253
+ if (targets.length === 0)
254
+ return [];
255
+ const actions = [];
256
+ const seen = new Set();
257
+ for (const tool of tools) {
258
+ for (const candidate of readDeclaredRecoveryActions(tool)) {
259
+ if (actions.length >= MAX_RECOVERY_ACTIONS)
260
+ return actions;
261
+ const action = parseRecoveryAction(candidate);
262
+ if (!action ||
263
+ !targets.some((target) => target.authority === action.authority && target.kind === action.targetKind)) {
264
+ continue;
265
+ }
266
+ const instruction = truncate(action.instruction.trim(), MAX_ACTION_INSTRUCTION_CHARS);
267
+ if (!instruction)
268
+ continue;
269
+ const key = `${tool.name}\0${action.kind}\0${instruction}`;
270
+ if (seen.has(key))
271
+ continue;
272
+ seen.add(key);
273
+ actions.push({ toolName: tool.name, kind: action.kind, instruction });
274
+ }
275
+ }
276
+ return actions;
277
+ }
278
+ function readDeclaredRecoveryActions(tool) {
279
+ try {
280
+ const declared = tool.failureRecovery?.actions;
281
+ if (!Array.isArray(declared))
282
+ return [];
283
+ const actions = [];
284
+ const count = Math.min(declared.length, MAX_RECOVERY_ACTIONS);
285
+ for (let index = 0; index < count; index++)
286
+ actions.push(declared[index]);
287
+ return actions;
288
+ }
289
+ catch {
290
+ return [];
291
+ }
292
+ }
293
+ function parseRecoveryAction(value) {
294
+ try {
295
+ if (!value || typeof value !== "object" || Array.isArray(value))
296
+ return undefined;
297
+ const candidate = value;
298
+ if (!isAgentToolFailureRecoveryAuthority(candidate.authority) ||
299
+ !validTargetKind(candidate.targetKind) ||
300
+ typeof candidate.instruction !== "string") {
301
+ return undefined;
302
+ }
303
+ if (candidate.kind === "correct") {
304
+ return {
305
+ kind: candidate.kind,
306
+ authority: candidate.authority,
307
+ targetKind: candidate.targetKind,
308
+ instruction: candidate.instruction,
309
+ };
310
+ }
311
+ if (candidate.kind !== "repair" || typeof candidate.getEvidence !== "function")
312
+ return undefined;
313
+ const getEvidence = candidate.getEvidence;
314
+ return {
315
+ kind: candidate.kind,
316
+ authority: candidate.authority,
317
+ targetKind: candidate.targetKind,
318
+ instruction: candidate.instruction,
319
+ getEvidence: (params, result) => Reflect.apply(getEvidence, value, [params, result]),
320
+ };
321
+ }
322
+ catch {
323
+ return undefined;
324
+ }
325
+ }
326
+ function readRecoveryEvidenceTargets(tool, args, result) {
327
+ const targets = [];
328
+ for (const candidate of readDeclaredRecoveryActions(tool)) {
329
+ const action = parseRecoveryAction(candidate);
330
+ if (targets.length >= MAX_RECOVERY_TARGETS || !action || action.kind !== "repair" || !action.getEvidence) {
331
+ continue;
332
+ }
333
+ let scopes;
334
+ try {
335
+ scopes = action.getEvidence(args, result);
336
+ }
337
+ catch {
338
+ continue;
339
+ }
340
+ if (!Array.isArray(scopes))
341
+ continue;
342
+ for (const scope of scopes) {
343
+ if (targets.length >= MAX_RECOVERY_TARGETS)
344
+ break;
345
+ if (!validTargetScope(scope))
346
+ continue;
347
+ const target = { authority: action.authority, kind: action.targetKind, scope };
348
+ if (!targets.some((candidate) => sameRecoveryTarget(candidate, target)))
349
+ targets.push(target);
350
+ }
351
+ }
352
+ return targets;
353
+ }
354
+ function formatRecoveryGuidance(failureCode, actions, unchangedRetryRemaining) {
355
+ const hasTimeoutRetryPolicy = getToolExecutionUnchangedRetryLimit(failureCode) > 0;
356
+ const timeoutPolicy = hasTimeoutRetryPolicy
357
+ ? unchangedRetryRemaining
358
+ ? "Timeout policy allows 1 unchanged retry; if it fails, never retry unchanged."
359
+ : "Timeout unchanged retry exhausted; never retry unchanged."
360
+ : undefined;
361
+ if (actions.length === 0) {
362
+ if (timeoutPolicy)
363
+ return `${timeoutPolicy} Change/narrow operation, or report blocker.`;
364
+ return "No loaded tool declares recovery. Never retry unchanged. Use materially different operation justified by diagnostic/schema, or report blocker.";
365
+ }
366
+ const available = actions.map((action) => `${action.toolName} ${action.kind}: ${action.instruction}`).join(" ");
367
+ const hasRepair = actions.some((action) => action.kind === "repair");
368
+ const authority = hasRepair
369
+ ? "Only exact matching repair evidence grants 1 probe; else change operation."
370
+ : "Actions require changed operation; unchanged remains blocked.";
371
+ return truncate(`${timeoutPolicy ? `${timeoutPolicy} ` : ""}Loaded actions: ${available} ${authority}`, MAX_RECOVERY_GUIDANCE_CHARS);
372
+ }
373
+ function truncate(value, maxChars) {
374
+ if (value.length <= maxChars)
375
+ return value;
376
+ return `${value.slice(0, maxChars - 1)}…`;
377
+ }
378
+ function sameRecoveryTarget(left, right) {
379
+ return left.authority === right.authority && left.kind === right.kind && left.scope === right.scope;
380
+ }
381
+ function hasSharedRecoveryTarget(left, right) {
382
+ if (left.length > right.length)
383
+ return hasSharedRecoveryTarget(right, left);
384
+ return left.some((target) => right.some((candidate) => sameRecoveryTarget(target, candidate)));
385
+ }
386
+ //# sourceMappingURL=tool-failure-recovery-gate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tool-failure-recovery-gate.js","sourceRoot":"","sources":["../src/tool-failure-recovery-gate.ts"],"names":[],"mappings":"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","sourcesContent":["import { getToolExecutionUnchangedRetryLimit } from \"@caupulican/pi-ai/tool-repair-registry\";\nimport {\n\tgetToolExecutionKey,\n\tgetToolFailureRecordExecutionKey,\n\ttype ToolFailureMemoryRecord,\n} from \"./tool-failure-memory.ts\";\nimport type {\n\tAgentTool,\n\tAgentToolFailureRecoveryAuthority,\n\tAgentToolFailureRecoveryTarget,\n\tAgentToolResult,\n} from \"./types.ts\";\nimport { isAgentToolFailureRecoveryAuthority } from \"./types.ts\";\n\nconst MAX_BLOCKED_REPLAYS_PER_FAILURE = 2;\nconst BASE_FAILURE_EXECUTIONS_PER_OPERATION = 1;\nconst MAX_RECOVERY_PROBES_PER_OPERATION = 1;\nconst MAX_REJECTIONS_PER_OPERATION = 4;\nexport const TOOL_FAILURE_RECOVERY_ACCOUNTING_WAVE_SIZE = 4;\nconst MAX_FAILURES_PER_FAMILY = TOOL_FAILURE_RECOVERY_ACCOUNTING_WAVE_SIZE;\nconst MAX_FAILURES_PER_RUN = 12;\nconst MAX_RECOVERY_STATES = 64;\nconst MAX_RECOVERY_TARGETS = 8;\nconst MAX_RECOVERY_ACTIONS = 8;\nconst MAX_TARGET_KIND_CHARS = 64;\nconst MAX_TARGET_SCOPE_CHARS = 32_768;\nconst MAX_ACTION_INSTRUCTION_CHARS = 160;\nconst MAX_RECOVERY_GUIDANCE_CHARS = 320;\nconst TARGET_KIND_PATTERN = /^[a-z0-9][a-z0-9._:-]*$/;\n\nexport interface ToolFailureExecutionReservation {\n\texecutionKey: string;\n}\n\nexport interface ToolFailureRecoveryPlan {\n\ttargets: readonly AgentToolFailureRecoveryTarget[];\n\tguidance: string;\n}\n\nexport type ToolFailureRecoveryGateEffect =\n\t| {\n\t\t\tkind: \"failure\";\n\t\t\trecord: ToolFailureMemoryRecord;\n\t\t\targs: unknown;\n\t\t\ttargets?: readonly AgentToolFailureRecoveryTarget[];\n\t\t\treservation?: ToolFailureExecutionReservation;\n\t }\n\t| { kind: \"success\"; tool: AgentTool<any>; args: unknown; evidenceResult: AgentToolResult<any> };\n\nexport type ToolFailureRecoveryAdmission =\n\t| { kind: \"allowed\"; reservation?: ToolFailureExecutionReservation }\n\t| { kind: \"blocked\"; record: ToolFailureMemoryRecord; exhausted: boolean; diagnostic?: string };\n\ninterface FailureRecoveryState {\n\trecord: ToolFailureMemoryRecord;\n\trecoveryTargets: readonly AgentToolFailureRecoveryTarget[];\n\treservedExecutions: number;\n\tfailures: number;\n\tfailureFamilyCounts: Map<string, number>;\n\trecoveryProbes: number;\n\tblockedReplays: number;\n\trecoveryAvailable: boolean;\n}\n\ninterface AvailableRecoveryAction {\n\ttoolName: string;\n\tkind: \"correct\" | \"repair\";\n\tinstruction: string;\n}\n\ninterface ParsedRecoveryAction {\n\tkind: \"correct\" | \"repair\";\n\tauthority: AgentToolFailureRecoveryAuthority;\n\ttargetKind: string;\n\tinstruction: string;\n\tgetEvidence?: (params: unknown, result: AgentToolResult<unknown>) => unknown;\n}\n\nexport interface ToolFailureRecoveryHalt {\n\trecord: ToolFailureMemoryRecord;\n\tdiagnostic: string;\n}\n\n/**\n * Owns run-scoped execution admission and bounded unresolved-failure budgets.\n *\n * Recovery authority is exact and tool-owned. A failed tool declares opaque backend-specific targets;\n * a loaded recovery tool may teach actions only for the same authority and target kind. Only raw\n * successful repair evidence with byte-exact scope can reopen one probe. Argument text and hooks have\n * no recovery authority.\n */\nexport class ToolFailureRecoveryGate {\n\tprivate readonly statesByExecutionKey = new Map<string, FailureRecoveryState>();\n\tprivate readonly failuresByFamily = new Map<string, number>();\n\tprivate totalFailures = 0;\n\tprivate halted: ToolFailureRecoveryHalt | undefined;\n\n\tplanFailure(\n\t\tfailedTool: AgentTool<any>,\n\t\targs: unknown,\n\t\tfailureCode: string,\n\t\tavailableTools: readonly AgentTool<any>[],\n\t\treservation: ToolFailureExecutionReservation | undefined,\n\t): ToolFailureRecoveryPlan {\n\t\tconst targets = readFailureTargets(failedTool, args, failureCode);\n\t\tconst actions = readAvailableRecoveryActions(availableTools, targets);\n\t\tconst unchangedRetryRemaining = this.hasUnchangedRetryRemaining(failedTool, args, failureCode, reservation);\n\t\treturn {\n\t\t\ttargets,\n\t\t\tguidance: formatRecoveryGuidance(failureCode, actions, unchangedRetryRemaining),\n\t\t};\n\t}\n\n\tadmit(\n\t\ttool: AgentTool<any>,\n\t\targs: unknown,\n\t\trecord: ToolFailureMemoryRecord | undefined,\n\t): ToolFailureRecoveryAdmission {\n\t\tconst stateCapacityHalt = this.halted;\n\t\tif (stateCapacityHalt) {\n\t\t\treturn {\n\t\t\t\tkind: \"blocked\",\n\t\t\t\trecord: stateCapacityHalt.record,\n\t\t\t\texhausted: true,\n\t\t\t\tdiagnostic: stateCapacityHalt.diagnostic,\n\t\t\t};\n\t\t}\n\n\t\tconst executionKey = getToolExecutionKey(tool.name, args);\n\t\tlet state = this.statesByExecutionKey.get(executionKey);\n\t\tif (!state && record && getToolFailureRecordExecutionKey(record) === executionKey) {\n\t\t\tstate = this.getOrCreateState(executionKey, record, readFailureTargets(tool, args, record.failureCode));\n\t\t}\n\t\tif (this.halted) {\n\t\t\treturn {\n\t\t\t\tkind: \"blocked\",\n\t\t\t\trecord: this.halted.record,\n\t\t\t\texhausted: true,\n\t\t\t\tdiagnostic: this.halted.diagnostic,\n\t\t\t};\n\t\t}\n\t\tif (!state) return { kind: \"allowed\" };\n\n\t\tif (record) state.record = record;\n\t\tconst automaticExecutionLimit =\n\t\t\tBASE_FAILURE_EXECUTIONS_PER_OPERATION + getToolExecutionUnchangedRetryLimit(state.record.failureCode);\n\t\tif (state.reservedExecutions < automaticExecutionLimit) {\n\t\t\tstate.reservedExecutions++;\n\t\t\tstate.blockedReplays = 0;\n\t\t\treturn { kind: \"allowed\", reservation: { executionKey } };\n\t\t}\n\t\tif (state.recoveryAvailable && state.recoveryProbes < MAX_RECOVERY_PROBES_PER_OPERATION) {\n\t\t\tstate.recoveryAvailable = false;\n\t\t\tstate.recoveryProbes++;\n\t\t\tstate.reservedExecutions++;\n\t\t\tstate.blockedReplays = 0;\n\t\t\treturn { kind: \"allowed\", reservation: { executionKey } };\n\t\t}\n\n\t\tstate.blockedReplays++;\n\t\tif (state.blockedReplays >= MAX_BLOCKED_REPLAYS_PER_FAILURE) {\n\t\t\tconst diagnostic = `Recovery circuit opened after ${state.blockedReplays} blocked replays of ${state.record.failureCode}.`;\n\t\t\tthis.halted = { record: state.record, diagnostic };\n\t\t\treturn { kind: \"blocked\", record: state.record, exhausted: true, diagnostic };\n\t\t}\n\t\treturn { kind: \"blocked\", record: state.record, exhausted: false };\n\t}\n\n\tapply(effect: ToolFailureRecoveryGateEffect | undefined): ToolFailureRecoveryHalt | undefined {\n\t\tif (!effect || this.halted) return undefined;\n\t\tif (effect.kind === \"success\") {\n\t\t\tthis.observeSuccess(effect.tool, effect.args, effect.evidenceResult);\n\t\t\treturn undefined;\n\t\t}\n\t\tthis.observeFailure(effect.record, effect.args, effect.targets ?? [], effect.reservation);\n\t\treturn this.halted;\n\t}\n\n\tisHalted(): boolean {\n\t\treturn this.halted !== undefined;\n\t}\n\n\tgetHalt(): ToolFailureRecoveryHalt | undefined {\n\t\treturn this.halted;\n\t}\n\n\tprivate hasUnchangedRetryRemaining(\n\t\ttool: AgentTool<any>,\n\t\targs: unknown,\n\t\tfailureCode: string,\n\t\treservation: ToolFailureExecutionReservation | undefined,\n\t): boolean {\n\t\tconst retryLimit = getToolExecutionUnchangedRetryLimit(failureCode);\n\t\tif (retryLimit === 0) return false;\n\t\tconst executionKey = getToolExecutionKey(tool.name, args);\n\t\tconst state = this.statesByExecutionKey.get(executionKey);\n\t\tconst executionsIncludingCurrent = state\n\t\t\t? state.reservedExecutions + (reservation?.executionKey === executionKey ? 0 : 1)\n\t\t\t: 1;\n\t\treturn executionsIncludingCurrent < BASE_FAILURE_EXECUTIONS_PER_OPERATION + retryLimit;\n\t}\n\n\tprivate getOrCreateState(\n\t\texecutionKey: string,\n\t\trecord: ToolFailureMemoryRecord,\n\t\ttargets: readonly AgentToolFailureRecoveryTarget[],\n\t): FailureRecoveryState {\n\t\tconst existing = this.statesByExecutionKey.get(executionKey);\n\t\tif (existing) return existing;\n\t\tconst state: FailureRecoveryState = {\n\t\t\trecord,\n\t\t\trecoveryTargets: targets,\n\t\t\treservedExecutions: 0,\n\t\t\tfailures: 0,\n\t\t\tfailureFamilyCounts: new Map(),\n\t\t\trecoveryProbes: 0,\n\t\t\tblockedReplays: 0,\n\t\t\trecoveryAvailable: false,\n\t\t};\n\t\tif (this.statesByExecutionKey.size >= MAX_RECOVERY_STATES) {\n\t\t\tthis.halted = {\n\t\t\t\trecord,\n\t\t\t\tdiagnostic: `Recovery circuit opened at the ${MAX_RECOVERY_STATES}-operation state bound.`,\n\t\t\t};\n\t\t\treturn state;\n\t\t}\n\t\tthis.statesByExecutionKey.set(executionKey, state);\n\t\treturn state;\n\t}\n\n\tprivate observeFailure(\n\t\trecord: ToolFailureMemoryRecord,\n\t\targs: unknown,\n\t\ttargets: readonly AgentToolFailureRecoveryTarget[],\n\t\treservation: ToolFailureExecutionReservation | undefined,\n\t): void {\n\t\tconst executionKey = getToolExecutionKey(record.tool, args);\n\t\tconst state = this.getOrCreateState(executionKey, record, targets);\n\t\tif (this.halted) return;\n\t\tstate.record = record;\n\t\tstate.recoveryTargets = targets;\n\t\tstate.recoveryAvailable = false;\n\t\tstate.blockedReplays = 0;\n\t\tif (reservation?.executionKey !== executionKey) state.reservedExecutions++;\n\n\t\tstate.failures++;\n\t\tthis.totalFailures++;\n\t\tconst familyKey = `${record.tool}\\0${record.failureCode}`;\n\t\tconst familyFailures = (this.failuresByFamily.get(familyKey) ?? 0) + 1;\n\t\tthis.failuresByFamily.set(familyKey, familyFailures);\n\t\tstate.failureFamilyCounts.set(familyKey, (state.failureFamilyCounts.get(familyKey) ?? 0) + 1);\n\n\t\tconst operationFailureLimit =\n\t\t\trecord.state === \"failed\"\n\t\t\t\t? BASE_FAILURE_EXECUTIONS_PER_OPERATION +\n\t\t\t\t\tgetToolExecutionUnchangedRetryLimit(record.failureCode) +\n\t\t\t\t\tMAX_RECOVERY_PROBES_PER_OPERATION\n\t\t\t\t: MAX_REJECTIONS_PER_OPERATION;\n\t\tif (state.failures >= operationFailureLimit) {\n\t\t\tthis.halted = {\n\t\t\t\trecord,\n\t\t\t\tdiagnostic: `Recovery circuit opened after ${state.failures} failed outcomes for one operation.`,\n\t\t\t};\n\t\t\treturn;\n\t\t}\n\t\tif (familyFailures >= MAX_FAILURES_PER_FAMILY) {\n\t\t\tthis.halted = {\n\t\t\t\trecord,\n\t\t\t\tdiagnostic: `Recovery circuit opened after ${familyFailures} failures in one tool failure family.`,\n\t\t\t};\n\t\t\treturn;\n\t\t}\n\t\tif (this.totalFailures >= MAX_FAILURES_PER_RUN) {\n\t\t\tthis.halted = {\n\t\t\t\trecord,\n\t\t\t\tdiagnostic: `Recovery circuit opened after ${this.totalFailures} tool failures in one run.`,\n\t\t\t};\n\t\t}\n\t}\n\n\tprivate observeSuccess(tool: AgentTool<any>, args: unknown, result: AgentToolResult<any>): void {\n\t\tconst successfulExecutionKey = getToolExecutionKey(tool.name, args);\n\t\tconst evidenceTargets = readRecoveryEvidenceTargets(tool, args, result);\n\t\tfor (const [executionKey, state] of this.statesByExecutionKey) {\n\t\t\tif (executionKey === successfulExecutionKey) {\n\t\t\t\tthis.clearResolvedState(executionKey, state);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (\n\t\t\t\tstate.recoveryProbes < MAX_RECOVERY_PROBES_PER_OPERATION &&\n\t\t\t\thasSharedRecoveryTarget(state.recoveryTargets, evidenceTargets)\n\t\t\t) {\n\t\t\t\tstate.recoveryAvailable = true;\n\t\t\t\tstate.blockedReplays = 0;\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate clearResolvedState(executionKey: string, state: FailureRecoveryState): void {\n\t\tthis.statesByExecutionKey.delete(executionKey);\n\t\tthis.totalFailures = Math.max(0, this.totalFailures - state.failures);\n\t\tfor (const [familyKey, stateFailures] of state.failureFamilyCounts) {\n\t\t\tconst remaining = (this.failuresByFamily.get(familyKey) ?? 0) - stateFailures;\n\t\t\tif (remaining > 0) this.failuresByFamily.set(familyKey, remaining);\n\t\t\telse this.failuresByFamily.delete(familyKey);\n\t\t}\n\t}\n}\n\nfunction readFailureTargets(\n\ttool: AgentTool<any>,\n\targs: unknown,\n\tfailureCode: string,\n): readonly AgentToolFailureRecoveryTarget[] {\n\ttry {\n\t\tconst contract = tool.failureRecovery;\n\t\tconst getTargets = contract?.getFailureTargets;\n\t\tif (!getTargets) return [];\n\t\tconst targets = Reflect.apply(getTargets, contract, [args, { failureCode }]);\n\t\treturn sanitizeRecoveryTargets(targets);\n\t} catch {\n\t\treturn [];\n\t}\n}\n\nfunction sanitizeRecoveryTargets(value: unknown): readonly AgentToolFailureRecoveryTarget[] {\n\tif (!Array.isArray(value)) return [];\n\tconst targets: AgentToolFailureRecoveryTarget[] = [];\n\tfor (const candidate of value) {\n\t\tif (targets.length >= MAX_RECOVERY_TARGETS) break;\n\t\tif (!candidate || typeof candidate !== \"object\" || Array.isArray(candidate)) continue;\n\t\tconst { authority, kind, scope } = candidate as { authority?: unknown; kind?: unknown; scope?: unknown };\n\t\tif (!isAgentToolFailureRecoveryAuthority(authority) || !validTargetKind(kind) || !validTargetScope(scope)) {\n\t\t\tcontinue;\n\t\t}\n\t\tif (targets.some((target) => sameRecoveryTarget(target, { authority, kind, scope }))) continue;\n\t\ttargets.push({ authority, kind, scope });\n\t}\n\treturn targets;\n}\n\nfunction validTargetKind(value: unknown): value is string {\n\treturn (\n\t\ttypeof value === \"string\" &&\n\t\tvalue.length > 0 &&\n\t\tvalue.length <= MAX_TARGET_KIND_CHARS &&\n\t\tTARGET_KIND_PATTERN.test(value)\n\t);\n}\n\nfunction validTargetScope(value: unknown): value is string {\n\treturn (\n\t\ttypeof value === \"string\" && value.length > 0 && value.length <= MAX_TARGET_SCOPE_CHARS && !value.includes(\"\\0\")\n\t);\n}\n\nfunction readAvailableRecoveryActions(\n\ttools: readonly AgentTool<any>[],\n\ttargets: readonly AgentToolFailureRecoveryTarget[],\n): readonly AvailableRecoveryAction[] {\n\tif (targets.length === 0) return [];\n\tconst actions: AvailableRecoveryAction[] = [];\n\tconst seen = new Set<string>();\n\tfor (const tool of tools) {\n\t\tfor (const candidate of readDeclaredRecoveryActions(tool)) {\n\t\t\tif (actions.length >= MAX_RECOVERY_ACTIONS) return actions;\n\t\t\tconst action = parseRecoveryAction(candidate);\n\t\t\tif (\n\t\t\t\t!action ||\n\t\t\t\t!targets.some((target) => target.authority === action.authority && target.kind === action.targetKind)\n\t\t\t) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tconst instruction = truncate(action.instruction.trim(), MAX_ACTION_INSTRUCTION_CHARS);\n\t\t\tif (!instruction) continue;\n\t\t\tconst key = `${tool.name}\\0${action.kind}\\0${instruction}`;\n\t\t\tif (seen.has(key)) continue;\n\t\t\tseen.add(key);\n\t\t\tactions.push({ toolName: tool.name, kind: action.kind, instruction });\n\t\t}\n\t}\n\treturn actions;\n}\n\nfunction readDeclaredRecoveryActions(tool: AgentTool<any>): readonly unknown[] {\n\ttry {\n\t\tconst declared = tool.failureRecovery?.actions;\n\t\tif (!Array.isArray(declared)) return [];\n\t\tconst actions: unknown[] = [];\n\t\tconst count = Math.min(declared.length, MAX_RECOVERY_ACTIONS);\n\t\tfor (let index = 0; index < count; index++) actions.push(declared[index]);\n\t\treturn actions;\n\t} catch {\n\t\treturn [];\n\t}\n}\n\nfunction parseRecoveryAction(value: unknown): ParsedRecoveryAction | undefined {\n\ttry {\n\t\tif (!value || typeof value !== \"object\" || Array.isArray(value)) return undefined;\n\t\tconst candidate = value as {\n\t\t\tkind?: unknown;\n\t\t\tauthority?: unknown;\n\t\t\ttargetKind?: unknown;\n\t\t\tinstruction?: unknown;\n\t\t\tgetEvidence?: unknown;\n\t\t};\n\t\tif (\n\t\t\t!isAgentToolFailureRecoveryAuthority(candidate.authority) ||\n\t\t\t!validTargetKind(candidate.targetKind) ||\n\t\t\ttypeof candidate.instruction !== \"string\"\n\t\t) {\n\t\t\treturn undefined;\n\t\t}\n\t\tif (candidate.kind === \"correct\") {\n\t\t\treturn {\n\t\t\t\tkind: candidate.kind,\n\t\t\t\tauthority: candidate.authority,\n\t\t\t\ttargetKind: candidate.targetKind,\n\t\t\t\tinstruction: candidate.instruction,\n\t\t\t};\n\t\t}\n\t\tif (candidate.kind !== \"repair\" || typeof candidate.getEvidence !== \"function\") return undefined;\n\t\tconst getEvidence = candidate.getEvidence;\n\t\treturn {\n\t\t\tkind: candidate.kind,\n\t\t\tauthority: candidate.authority,\n\t\t\ttargetKind: candidate.targetKind,\n\t\t\tinstruction: candidate.instruction,\n\t\t\tgetEvidence: (params, result) => Reflect.apply(getEvidence, value, [params, result]),\n\t\t};\n\t} catch {\n\t\treturn undefined;\n\t}\n}\n\nfunction readRecoveryEvidenceTargets(\n\ttool: AgentTool<any>,\n\targs: unknown,\n\tresult: AgentToolResult<any>,\n): readonly AgentToolFailureRecoveryTarget[] {\n\tconst targets: AgentToolFailureRecoveryTarget[] = [];\n\tfor (const candidate of readDeclaredRecoveryActions(tool)) {\n\t\tconst action = parseRecoveryAction(candidate);\n\t\tif (targets.length >= MAX_RECOVERY_TARGETS || !action || action.kind !== \"repair\" || !action.getEvidence) {\n\t\t\tcontinue;\n\t\t}\n\t\tlet scopes: unknown;\n\t\ttry {\n\t\t\tscopes = action.getEvidence(args, result);\n\t\t} catch {\n\t\t\tcontinue;\n\t\t}\n\t\tif (!Array.isArray(scopes)) continue;\n\t\tfor (const scope of scopes) {\n\t\t\tif (targets.length >= MAX_RECOVERY_TARGETS) break;\n\t\t\tif (!validTargetScope(scope)) continue;\n\t\t\tconst target = { authority: action.authority, kind: action.targetKind, scope };\n\t\t\tif (!targets.some((candidate) => sameRecoveryTarget(candidate, target))) targets.push(target);\n\t\t}\n\t}\n\treturn targets;\n}\n\nfunction formatRecoveryGuidance(\n\tfailureCode: string,\n\tactions: readonly AvailableRecoveryAction[],\n\tunchangedRetryRemaining: boolean,\n): string {\n\tconst hasTimeoutRetryPolicy = getToolExecutionUnchangedRetryLimit(failureCode) > 0;\n\tconst timeoutPolicy = hasTimeoutRetryPolicy\n\t\t? unchangedRetryRemaining\n\t\t\t? \"Timeout policy allows 1 unchanged retry; if it fails, never retry unchanged.\"\n\t\t\t: \"Timeout unchanged retry exhausted; never retry unchanged.\"\n\t\t: undefined;\n\tif (actions.length === 0) {\n\t\tif (timeoutPolicy) return `${timeoutPolicy} Change/narrow operation, or report blocker.`;\n\t\treturn \"No loaded tool declares recovery. Never retry unchanged. Use materially different operation justified by diagnostic/schema, or report blocker.\";\n\t}\n\tconst available = actions.map((action) => `${action.toolName} ${action.kind}: ${action.instruction}`).join(\" \");\n\tconst hasRepair = actions.some((action) => action.kind === \"repair\");\n\tconst authority = hasRepair\n\t\t? \"Only exact matching repair evidence grants 1 probe; else change operation.\"\n\t\t: \"Actions require changed operation; unchanged remains blocked.\";\n\treturn truncate(\n\t\t`${timeoutPolicy ? `${timeoutPolicy} ` : \"\"}Loaded actions: ${available} ${authority}`,\n\t\tMAX_RECOVERY_GUIDANCE_CHARS,\n\t);\n}\n\nfunction truncate(value: string, maxChars: number): string {\n\tif (value.length <= maxChars) return value;\n\treturn `${value.slice(0, maxChars - 1)}…`;\n}\n\nfunction sameRecoveryTarget(left: AgentToolFailureRecoveryTarget, right: AgentToolFailureRecoveryTarget): boolean {\n\treturn left.authority === right.authority && left.kind === right.kind && left.scope === right.scope;\n}\n\nfunction hasSharedRecoveryTarget(\n\tleft: readonly AgentToolFailureRecoveryTarget[],\n\tright: readonly AgentToolFailureRecoveryTarget[],\n): boolean {\n\tif (left.length > right.length) return hasSharedRecoveryTarget(right, left);\n\treturn left.some((target) => right.some((candidate) => sameRecoveryTarget(target, candidate)));\n}\n"]}
@@ -0,0 +1,15 @@
1
+ export declare const TOOL_FAILURE_RECOVERY_PROTOCOL_NAME = "mandatory_tool_failure_recovery";
2
+ export declare const TOOL_FAILURE_RECOVERY_PROTOCOL_VERSION = 1;
3
+ export declare const MANDATORY_TOOL_FAILURE_RECOVERY_RULE = "MANDATORY AND NON-NEGOTIABLE.";
4
+ export declare function mandatoryToolFailureRecoveryMetadata(): {
5
+ MUST: true;
6
+ };
7
+ export declare const MANDATORY_TOOL_FAILURE_RECOVERY_PROTOCOL_PROMPT: string;
8
+ export interface MandatoryToolFailureDeliveryData {
9
+ tool: string;
10
+ failureCode: string;
11
+ diagnostic: string;
12
+ requiredAction: string;
13
+ }
14
+ export declare function appendMandatoryToolFailureDeliveryPrompt(systemPrompt: string, failure: MandatoryToolFailureDeliveryData): string;
15
+ //# sourceMappingURL=tool-failure-recovery-protocol.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tool-failure-recovery-protocol.d.ts","sourceRoot":"","sources":["../src/tool-failure-recovery-protocol.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,mCAAmC,oCAAoC,CAAC;AACrF,eAAO,MAAM,sCAAsC,IAAI,CAAC;AACxD,eAAO,MAAM,oCAAoC,kCAAkC,CAAC;AAEpF,wBAAgB,oCAAoC,IAAI;IACvD,IAAI,EAAE,IAAI,CAAC;CACX,CAIA;AAED,eAAO,MAAM,+CAA+C,QAShD,CAAC;AASb,MAAM,WAAW,gCAAgC;IAChD,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,cAAc,EAAE,MAAM,CAAC;CACvB;AAED,wBAAgB,wCAAwC,CACvD,YAAY,EAAE,MAAM,EACpB,OAAO,EAAE,gCAAgC,GACvC,MAAM,CAiBR"}
@@ -0,0 +1,43 @@
1
+ export const TOOL_FAILURE_RECOVERY_PROTOCOL_NAME = "mandatory_tool_failure_recovery";
2
+ export const TOOL_FAILURE_RECOVERY_PROTOCOL_VERSION = 1;
3
+ export const MANDATORY_TOOL_FAILURE_RECOVERY_RULE = "MANDATORY AND NON-NEGOTIABLE.";
4
+ export function mandatoryToolFailureRecoveryMetadata() {
5
+ return {
6
+ MUST: true,
7
+ };
8
+ }
9
+ export const MANDATORY_TOOL_FAILURE_RECOVERY_PROTOCOL_PROMPT = [
10
+ `MANDATORY TOOL FAILURE RECOVERY v${TOOL_FAILURE_RECOVERY_PROTOCOL_VERSION}`,
11
+ MANDATORY_TOOL_FAILURE_RECOVERY_RULE,
12
+ "Harness contract:",
13
+ "- Failure record binds execution. MUST:true: repair; if impossible, perform next_action; never retry first.",
14
+ "- Do not repeat an unchanged operation. Irrelevant argument changes never recover it.",
15
+ "- A blocked call preserves tool-result pairing but runs no hook/tool code.",
16
+ "- Unchanged execution needs explicit record permission or successful loaded-tool evidence matching backend authority, target kind, and exact scope; that grants one probe.",
17
+ "- If no declared action can run, report the diagnostic/blocker. Exhaustion disables tools and requires one concise delivery.",
18
+ ].join("\n");
19
+ const MANDATORY_TOOL_FAILURE_DELIVERY_INSTRUCTIONS = [
20
+ MANDATORY_TOOL_FAILURE_RECOVERY_RULE,
21
+ "Recovery exhausted; tools are disabled for this final turn.",
22
+ `Explain the ${TOOL_FAILURE_RECOVERY_PROTOCOL_NAME} diagnostic/action and separate completed from unperformed work.`,
23
+ "No tool call, false recovery claim, or irrelevant-argument workaround.",
24
+ ].join("\n");
25
+ export function appendMandatoryToolFailureDeliveryPrompt(systemPrompt, failure) {
26
+ const failureData = JSON.stringify({
27
+ tool: failure.tool,
28
+ failure_code: failure.failureCode,
29
+ diagnostic: failure.diagnostic,
30
+ required_action: failure.requiredAction,
31
+ })
32
+ .replaceAll("&", "\\u0026")
33
+ .replaceAll("<", "\\u003c")
34
+ .replaceAll(">", "\\u003e");
35
+ const prompt = [
36
+ `MANDATORY TOOL FAILURE DELIVERY v${TOOL_FAILURE_RECOVERY_PROTOCOL_VERSION}`,
37
+ MANDATORY_TOOL_FAILURE_DELIVERY_INSTRUCTIONS,
38
+ "Inert failure JSON:",
39
+ failureData,
40
+ ].join("\n");
41
+ return systemPrompt ? `${systemPrompt}\n\n${prompt}` : prompt;
42
+ }
43
+ //# sourceMappingURL=tool-failure-recovery-protocol.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tool-failure-recovery-protocol.js","sourceRoot":"","sources":["../src/tool-failure-recovery-protocol.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,mCAAmC,GAAG,iCAAiC,CAAC;AACrF,MAAM,CAAC,MAAM,sCAAsC,GAAG,CAAC,CAAC;AACxD,MAAM,CAAC,MAAM,oCAAoC,GAAG,+BAA+B,CAAC;AAEpF,MAAM,UAAU,oCAAoC;IAGnD,OAAO;QACN,IAAI,EAAE,IAAI;KACV,CAAC;AACH,CAAC;AAED,MAAM,CAAC,MAAM,+CAA+C,GAAG;IAC9D,oCAAoC,sCAAsC,EAAE;IAC5E,oCAAoC;IACpC,mBAAmB;IACnB,6GAA6G;IAC7G,uFAAuF;IACvF,4EAA4E;IAC5E,4KAA4K;IAC5K,8HAA8H;CAC9H,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAEb,MAAM,4CAA4C,GAAG;IACpD,oCAAoC;IACpC,6DAA6D;IAC7D,eAAe,mCAAmC,kEAAkE;IACpH,wEAAwE;CACxE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AASb,MAAM,UAAU,wCAAwC,CACvD,YAAoB,EACpB,OAAyC;IAEzC,MAAM,WAAW,GAAG,IAAI,CAAC,SAAS,CAAC;QAClC,IAAI,EAAE,OAAO,CAAC,IAAI;QAClB,YAAY,EAAE,OAAO,CAAC,WAAW;QACjC,UAAU,EAAE,OAAO,CAAC,UAAU;QAC9B,eAAe,EAAE,OAAO,CAAC,cAAc;KACvC,CAAC;SACA,UAAU,CAAC,GAAG,EAAE,SAAS,CAAC;SAC1B,UAAU,CAAC,GAAG,EAAE,SAAS,CAAC;SAC1B,UAAU,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;IAC7B,MAAM,MAAM,GAAG;QACd,oCAAoC,sCAAsC,EAAE;QAC5E,4CAA4C;QAC5C,qBAAqB;QACrB,WAAW;KACX,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACb,OAAO,YAAY,CAAC,CAAC,CAAC,GAAG,YAAY,OAAO,MAAM,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC;AAC/D,CAAC","sourcesContent":["export const TOOL_FAILURE_RECOVERY_PROTOCOL_NAME = \"mandatory_tool_failure_recovery\";\nexport const TOOL_FAILURE_RECOVERY_PROTOCOL_VERSION = 1;\nexport const MANDATORY_TOOL_FAILURE_RECOVERY_RULE = \"MANDATORY AND NON-NEGOTIABLE.\";\n\nexport function mandatoryToolFailureRecoveryMetadata(): {\n\tMUST: true;\n} {\n\treturn {\n\t\tMUST: true,\n\t};\n}\n\nexport const MANDATORY_TOOL_FAILURE_RECOVERY_PROTOCOL_PROMPT = [\n\t`MANDATORY TOOL FAILURE RECOVERY v${TOOL_FAILURE_RECOVERY_PROTOCOL_VERSION}`,\n\tMANDATORY_TOOL_FAILURE_RECOVERY_RULE,\n\t\"Harness contract:\",\n\t\"- Failure record binds execution. MUST:true: repair; if impossible, perform next_action; never retry first.\",\n\t\"- Do not repeat an unchanged operation. Irrelevant argument changes never recover it.\",\n\t\"- A blocked call preserves tool-result pairing but runs no hook/tool code.\",\n\t\"- Unchanged execution needs explicit record permission or successful loaded-tool evidence matching backend authority, target kind, and exact scope; that grants one probe.\",\n\t\"- If no declared action can run, report the diagnostic/blocker. Exhaustion disables tools and requires one concise delivery.\",\n].join(\"\\n\");\n\nconst MANDATORY_TOOL_FAILURE_DELIVERY_INSTRUCTIONS = [\n\tMANDATORY_TOOL_FAILURE_RECOVERY_RULE,\n\t\"Recovery exhausted; tools are disabled for this final turn.\",\n\t`Explain the ${TOOL_FAILURE_RECOVERY_PROTOCOL_NAME} diagnostic/action and separate completed from unperformed work.`,\n\t\"No tool call, false recovery claim, or irrelevant-argument workaround.\",\n].join(\"\\n\");\n\nexport interface MandatoryToolFailureDeliveryData {\n\ttool: string;\n\tfailureCode: string;\n\tdiagnostic: string;\n\trequiredAction: string;\n}\n\nexport function appendMandatoryToolFailureDeliveryPrompt(\n\tsystemPrompt: string,\n\tfailure: MandatoryToolFailureDeliveryData,\n): string {\n\tconst failureData = JSON.stringify({\n\t\ttool: failure.tool,\n\t\tfailure_code: failure.failureCode,\n\t\tdiagnostic: failure.diagnostic,\n\t\trequired_action: failure.requiredAction,\n\t})\n\t\t.replaceAll(\"&\", \"\\\\u0026\")\n\t\t.replaceAll(\"<\", \"\\\\u003c\")\n\t\t.replaceAll(\">\", \"\\\\u003e\");\n\tconst prompt = [\n\t\t`MANDATORY TOOL FAILURE DELIVERY v${TOOL_FAILURE_RECOVERY_PROTOCOL_VERSION}`,\n\t\tMANDATORY_TOOL_FAILURE_DELIVERY_INSTRUCTIONS,\n\t\t\"Inert failure JSON:\",\n\t\tfailureData,\n\t].join(\"\\n\");\n\treturn systemPrompt ? `${systemPrompt}\\n\\n${prompt}` : prompt;\n}\n"]}