@resolveio/server-lib 22.3.128 → 22.3.130

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,38 @@
1
+ export type ResolveIOAIManagerAction = 'continue' | 'retry_infra' | 'reset_loop_budget' | 'park_repeated_failure' | 'park_ping_pong' | 'manual_handoff';
2
+ export interface ResolveIOAIManagerFailureRecord {
3
+ outcome?: string;
4
+ lane?: string;
5
+ stepType?: string;
6
+ failureClass?: string;
7
+ blocker?: string;
8
+ blockerFingerprint?: string;
9
+ evidenceHash?: string;
10
+ changedFiles?: string[];
11
+ artifactPaths?: string[];
12
+ summary?: string;
13
+ recordedAt?: Date | string;
14
+ }
15
+ export interface ResolveIOAIManagerPolicyInput {
16
+ history?: ResolveIOAIManagerFailureRecord[];
17
+ current?: ResolveIOAIManagerFailureRecord;
18
+ maxSameFailureRepeats?: number;
19
+ maxPingPongTransitions?: number;
20
+ infraFailureClasses?: string[];
21
+ ignoredFailureClasses?: string[];
22
+ }
23
+ export interface ResolveIOAIManagerPolicyDecision {
24
+ action: ResolveIOAIManagerAction;
25
+ reason: string;
26
+ failureClass: string;
27
+ blockerFingerprint: string;
28
+ evidenceHash: string;
29
+ sameFailureCount: number;
30
+ pingPongCount: number;
31
+ newEvidence: boolean;
32
+ loopBudgetShouldReset: boolean;
33
+ productRepairFailure: boolean;
34
+ }
35
+ export declare function normalizeResolveIOAIManagerFailureClass(value: any): string;
36
+ export declare function fingerprintResolveIOAIManagerBlocker(value: any): string;
37
+ export declare function hashResolveIOAIManagerEvidence(record: ResolveIOAIManagerFailureRecord | undefined): string;
38
+ export declare function decideResolveIOAIManagerPolicy(input: ResolveIOAIManagerPolicyInput): ResolveIOAIManagerPolicyDecision;
@@ -0,0 +1,234 @@
1
+ "use strict";
2
+ var __assign = (this && this.__assign) || function () {
3
+ __assign = Object.assign || function(t) {
4
+ for (var s, i = 1, n = arguments.length; i < n; i++) {
5
+ s = arguments[i];
6
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
7
+ t[p] = s[p];
8
+ }
9
+ return t;
10
+ };
11
+ return __assign.apply(this, arguments);
12
+ };
13
+ var __values = (this && this.__values) || function(o) {
14
+ var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
15
+ if (m) return m.call(o);
16
+ if (o && typeof o.length === "number") return {
17
+ next: function () {
18
+ if (o && i >= o.length) o = void 0;
19
+ return { value: o && o[i++], done: !o };
20
+ }
21
+ };
22
+ throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
23
+ };
24
+ Object.defineProperty(exports, "__esModule", { value: true });
25
+ exports.normalizeResolveIOAIManagerFailureClass = normalizeResolveIOAIManagerFailureClass;
26
+ exports.fingerprintResolveIOAIManagerBlocker = fingerprintResolveIOAIManagerBlocker;
27
+ exports.hashResolveIOAIManagerEvidence = hashResolveIOAIManagerEvidence;
28
+ exports.decideResolveIOAIManagerPolicy = decideResolveIOAIManagerPolicy;
29
+ function cleanText(value, max) {
30
+ if (max === void 0) { max = 2000; }
31
+ return String(value || '').replace(/\s+/g, ' ').trim().slice(0, max);
32
+ }
33
+ function cleanList(values, limit, max) {
34
+ var e_1, _a;
35
+ if (limit === void 0) { limit = 40; }
36
+ if (max === void 0) { max = 500; }
37
+ if (!Array.isArray(values)) {
38
+ return [];
39
+ }
40
+ var result = [];
41
+ try {
42
+ for (var values_1 = __values(values), values_1_1 = values_1.next(); !values_1_1.done; values_1_1 = values_1.next()) {
43
+ var value = values_1_1.value;
44
+ var normalized = cleanText(value, max);
45
+ if (normalized && !result.includes(normalized)) {
46
+ result.push(normalized);
47
+ }
48
+ if (result.length >= limit) {
49
+ break;
50
+ }
51
+ }
52
+ }
53
+ catch (e_1_1) { e_1 = { error: e_1_1 }; }
54
+ finally {
55
+ try {
56
+ if (values_1_1 && !values_1_1.done && (_a = values_1.return)) _a.call(values_1);
57
+ }
58
+ finally { if (e_1) throw e_1.error; }
59
+ }
60
+ return result;
61
+ }
62
+ function stableHash(prefix, value) {
63
+ var normalized = typeof value === 'string'
64
+ ? cleanText(value, 12000)
65
+ : JSON.stringify(value || {});
66
+ var hash = 0;
67
+ for (var index = 0; index < normalized.length; index += 1) {
68
+ hash = ((hash << 5) - hash + normalized.charCodeAt(index)) | 0;
69
+ }
70
+ return "".concat(prefix, "-").concat(Math.abs(hash).toString(36) || '0');
71
+ }
72
+ function normalizeResolveIOAIManagerFailureClass(value) {
73
+ var normalized = cleanText(value, 80)
74
+ .toLowerCase()
75
+ .replace(/[\s-]+/g, '_');
76
+ if (!normalized) {
77
+ return 'unknown';
78
+ }
79
+ if (/^(qa_infra|infrastructure|harness|puppeteer|chrome|mongo|port|startup)$/.test(normalized)) {
80
+ return 'infra';
81
+ }
82
+ if (/^(build|compile|typescript|tsc|angular_build|ng_build)$/.test(normalized)) {
83
+ return 'compile';
84
+ }
85
+ if (/^(false_pass|route_only|missing_business_proof)$/.test(normalized)) {
86
+ return 'business';
87
+ }
88
+ return normalized.slice(0, 80);
89
+ }
90
+ function fingerprintResolveIOAIManagerBlocker(value) {
91
+ var normalized = cleanText(value, 4000)
92
+ .toLowerCase()
93
+ .replace(/[a-f0-9]{16,}/g, '<id>')
94
+ .replace(/\b\d{2,}\b/g, '<n>')
95
+ .replace(/\bline\s+<n>\b/g, 'line <n>')
96
+ .replace(/https?:\/\/\S+/g, '<url>')
97
+ .replace(/\s+/g, ' ')
98
+ .trim();
99
+ return stableHash('mgr-blocker', normalized);
100
+ }
101
+ function hashResolveIOAIManagerEvidence(record) {
102
+ if (!record) {
103
+ return stableHash('mgr-evidence', '');
104
+ }
105
+ var explicit = cleanText(record.evidenceHash, 120);
106
+ if (explicit) {
107
+ return explicit;
108
+ }
109
+ return stableHash('mgr-evidence', {
110
+ failureClass: normalizeResolveIOAIManagerFailureClass(record.failureClass),
111
+ blocker: cleanText(record.blocker || record.summary, 2000),
112
+ changedFiles: cleanList(record.changedFiles, 80, 500).sort(),
113
+ artifactPaths: cleanList(record.artifactPaths, 80, 500).sort()
114
+ });
115
+ }
116
+ function failureKey(record) {
117
+ if (!record) {
118
+ return '';
119
+ }
120
+ var failureClass = normalizeResolveIOAIManagerFailureClass(record.failureClass);
121
+ var blockerFingerprint = cleanText(record.blockerFingerprint, 120)
122
+ || fingerprintResolveIOAIManagerBlocker(record.blocker || record.summary || '');
123
+ return "".concat(cleanText(record.lane, 80), ":").concat(cleanText(record.stepType, 80), ":").concat(failureClass, ":").concat(blockerFingerprint);
124
+ }
125
+ function failureEvidenceKey(record) {
126
+ return "".concat(failureKey(record), ":").concat(hashResolveIOAIManagerEvidence(record));
127
+ }
128
+ function isPassingOutcome(record) {
129
+ return /^(pass|accepted|ready_to_publish|published|ready_for_merge|complete|completed)$/i.test(cleanText(record === null || record === void 0 ? void 0 : record.outcome, 80));
130
+ }
131
+ function isManualOutcome(record) {
132
+ return /^(manual_handoff|park_manual|stopped)$/i.test(cleanText(record === null || record === void 0 ? void 0 : record.outcome, 80));
133
+ }
134
+ function collectOpenTail(records) {
135
+ var tail = [];
136
+ for (var index = records.length - 1; index >= 0; index -= 1) {
137
+ var record = records[index];
138
+ if (isPassingOutcome(record)) {
139
+ break;
140
+ }
141
+ tail.unshift(record);
142
+ }
143
+ return tail;
144
+ }
145
+ function countSameFailure(records, current) {
146
+ var currentKey = failureEvidenceKey(current);
147
+ var count = 0;
148
+ for (var index = records.length - 1; index >= 0; index -= 1) {
149
+ var record = records[index];
150
+ if (isPassingOutcome(record)) {
151
+ break;
152
+ }
153
+ if (failureEvidenceKey(record) !== currentKey) {
154
+ break;
155
+ }
156
+ count += 1;
157
+ }
158
+ return count;
159
+ }
160
+ function countPingPong(records, current) {
161
+ var tail = collectOpenTail(records).filter(function (record) {
162
+ return cleanText(record.lane, 80) === cleanText(current.lane, 80)
163
+ && cleanText(record.stepType, 80) === cleanText(current.stepType, 80);
164
+ });
165
+ if (tail.length < 4) {
166
+ return 0;
167
+ }
168
+ var keys = tail.map(failureKey).filter(Boolean);
169
+ var last = keys.slice(-6);
170
+ if (last.length < 4) {
171
+ return 0;
172
+ }
173
+ var distinct = Array.from(new Set(last));
174
+ if (distinct.length !== 2) {
175
+ return 0;
176
+ }
177
+ for (var index = 2; index < last.length; index += 1) {
178
+ if (last[index] !== last[index - 2]) {
179
+ return 0;
180
+ }
181
+ }
182
+ return last.length - 1;
183
+ }
184
+ function decideResolveIOAIManagerPolicy(input) {
185
+ var history = Array.isArray(input.history) ? input.history : [];
186
+ var current = input.current || history[history.length - 1] || {};
187
+ var failureClass = normalizeResolveIOAIManagerFailureClass(current.failureClass);
188
+ var blockerFingerprint = cleanText(current.blockerFingerprint, 120)
189
+ || fingerprintResolveIOAIManagerBlocker(current.blocker || current.summary || '');
190
+ var evidenceHash = hashResolveIOAIManagerEvidence(current);
191
+ var previous = history.length > 1 ? history[history.length - 2] : undefined;
192
+ var previousSameFailure = previous && failureKey(previous) === failureKey(current);
193
+ var previousEvidenceHash = previousSameFailure ? hashResolveIOAIManagerEvidence(previous) : '';
194
+ var newEvidence = !!previousSameFailure && !!previousEvidenceHash && previousEvidenceHash !== evidenceHash;
195
+ var sameFailureCount = countSameFailure(history, current);
196
+ var pingPongCount = countPingPong(history, current);
197
+ var maxSameFailureRepeats = Math.max(1, Number(input.maxSameFailureRepeats || 3) || 3);
198
+ var maxPingPongTransitions = Math.max(3, Number(input.maxPingPongTransitions || 3) || 3);
199
+ var infraClasses = new Set((input.infraFailureClasses || ['infra', 'compile']).map(normalizeResolveIOAIManagerFailureClass));
200
+ var ignoredClasses = new Set((input.ignoredFailureClasses || []).map(normalizeResolveIOAIManagerFailureClass));
201
+ var base = {
202
+ failureClass: failureClass,
203
+ blockerFingerprint: blockerFingerprint,
204
+ evidenceHash: evidenceHash,
205
+ sameFailureCount: sameFailureCount,
206
+ pingPongCount: pingPongCount,
207
+ newEvidence: newEvidence,
208
+ loopBudgetShouldReset: false,
209
+ productRepairFailure: !infraClasses.has(failureClass) && !ignoredClasses.has(failureClass)
210
+ };
211
+ if (isPassingOutcome(current)) {
212
+ return __assign(__assign({}, base), { action: 'reset_loop_budget', reason: 'manager_policy_progress_passed', loopBudgetShouldReset: true, productRepairFailure: false });
213
+ }
214
+ if (isManualOutcome(current)) {
215
+ return __assign(__assign({}, base), { action: 'manual_handoff', reason: 'manager_policy_manual_or_stopped' });
216
+ }
217
+ if (infraClasses.has(failureClass)) {
218
+ return __assign(__assign({}, base), { action: 'retry_infra', reason: 'manager_policy_infra_failure_routes_to_infra_repair', productRepairFailure: false });
219
+ }
220
+ if (pingPongCount >= maxPingPongTransitions) {
221
+ return __assign(__assign({}, base), { action: 'park_ping_pong', reason: 'manager_policy_ping_pong_failure_loop' });
222
+ }
223
+ if (sameFailureCount >= maxSameFailureRepeats && !newEvidence) {
224
+ return __assign(__assign({}, base), { action: 'park_repeated_failure', reason: 'manager_policy_same_failure_without_new_evidence' });
225
+ }
226
+ if (newEvidence || !previousSameFailure) {
227
+ return __assign(__assign({}, base), { action: 'continue', reason: newEvidence
228
+ ? 'manager_policy_new_evidence_resets_loop_budget'
229
+ : 'manager_policy_new_failure_or_lane', loopBudgetShouldReset: true });
230
+ }
231
+ return __assign(__assign({}, base), { action: 'continue', reason: 'manager_policy_retry_below_repeat_limit' });
232
+ }
233
+
234
+ //# sourceMappingURL=ai-runner-manager-policy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/util/ai-runner-manager-policy.ts"],"names":[],"mappings":"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","file":"ai-runner-manager-policy.js","sourcesContent":["export type ResolveIOAIManagerAction =\n\t| 'continue'\n\t| 'retry_infra'\n\t| 'reset_loop_budget'\n\t| 'park_repeated_failure'\n\t| 'park_ping_pong'\n\t| 'manual_handoff';\n\nexport interface ResolveIOAIManagerFailureRecord {\n\toutcome?: string;\n\tlane?: string;\n\tstepType?: string;\n\tfailureClass?: string;\n\tblocker?: string;\n\tblockerFingerprint?: string;\n\tevidenceHash?: string;\n\tchangedFiles?: string[];\n\tartifactPaths?: string[];\n\tsummary?: string;\n\trecordedAt?: Date | string;\n}\n\nexport interface ResolveIOAIManagerPolicyInput {\n\thistory?: ResolveIOAIManagerFailureRecord[];\n\tcurrent?: ResolveIOAIManagerFailureRecord;\n\tmaxSameFailureRepeats?: number;\n\tmaxPingPongTransitions?: number;\n\tinfraFailureClasses?: string[];\n\tignoredFailureClasses?: string[];\n}\n\nexport interface ResolveIOAIManagerPolicyDecision {\n\taction: ResolveIOAIManagerAction;\n\treason: string;\n\tfailureClass: string;\n\tblockerFingerprint: string;\n\tevidenceHash: string;\n\tsameFailureCount: number;\n\tpingPongCount: number;\n\tnewEvidence: boolean;\n\tloopBudgetShouldReset: boolean;\n\tproductRepairFailure: boolean;\n}\n\nfunction cleanText(value: any, max = 2000): string {\n\treturn String(value || '').replace(/\\s+/g, ' ').trim().slice(0, max);\n}\n\nfunction cleanList(values: any, limit = 40, max = 500): string[] {\n\tif (!Array.isArray(values)) {\n\t\treturn [];\n\t}\n\tconst result: string[] = [];\n\tfor (const value of values) {\n\t\tconst normalized = cleanText(value, max);\n\t\tif (normalized && !result.includes(normalized)) {\n\t\t\tresult.push(normalized);\n\t\t}\n\t\tif (result.length >= limit) {\n\t\t\tbreak;\n\t\t}\n\t}\n\treturn result;\n}\n\nfunction stableHash(prefix: string, value: any): string {\n\tconst normalized = typeof value === 'string'\n\t\t? cleanText(value, 12000)\n\t\t: JSON.stringify(value || {});\n\tlet hash = 0;\n\tfor (let index = 0; index < normalized.length; index += 1) {\n\t\thash = ((hash << 5) - hash + normalized.charCodeAt(index)) | 0;\n\t}\n\treturn `${prefix}-${Math.abs(hash).toString(36) || '0'}`;\n}\n\nexport function normalizeResolveIOAIManagerFailureClass(value: any): string {\n\tconst normalized = cleanText(value, 80)\n\t\t.toLowerCase()\n\t\t.replace(/[\\s-]+/g, '_');\n\tif (!normalized) {\n\t\treturn 'unknown';\n\t}\n\tif (/^(qa_infra|infrastructure|harness|puppeteer|chrome|mongo|port|startup)$/.test(normalized)) {\n\t\treturn 'infra';\n\t}\n\tif (/^(build|compile|typescript|tsc|angular_build|ng_build)$/.test(normalized)) {\n\t\treturn 'compile';\n\t}\n\tif (/^(false_pass|route_only|missing_business_proof)$/.test(normalized)) {\n\t\treturn 'business';\n\t}\n\treturn normalized.slice(0, 80);\n}\n\nexport function fingerprintResolveIOAIManagerBlocker(value: any): string {\n\tconst normalized = cleanText(value, 4000)\n\t\t.toLowerCase()\n\t\t.replace(/[a-f0-9]{16,}/g, '<id>')\n\t\t.replace(/\\b\\d{2,}\\b/g, '<n>')\n\t\t.replace(/\\bline\\s+<n>\\b/g, 'line <n>')\n\t\t.replace(/https?:\\/\\/\\S+/g, '<url>')\n\t\t.replace(/\\s+/g, ' ')\n\t\t.trim();\n\treturn stableHash('mgr-blocker', normalized);\n}\n\nexport function hashResolveIOAIManagerEvidence(record: ResolveIOAIManagerFailureRecord | undefined): string {\n\tif (!record) {\n\t\treturn stableHash('mgr-evidence', '');\n\t}\n\tconst explicit = cleanText(record.evidenceHash, 120);\n\tif (explicit) {\n\t\treturn explicit;\n\t}\n\treturn stableHash('mgr-evidence', {\n\t\tfailureClass: normalizeResolveIOAIManagerFailureClass(record.failureClass),\n\t\tblocker: cleanText(record.blocker || record.summary, 2000),\n\t\tchangedFiles: cleanList(record.changedFiles, 80, 500).sort(),\n\t\tartifactPaths: cleanList(record.artifactPaths, 80, 500).sort()\n\t});\n}\n\nfunction failureKey(record: ResolveIOAIManagerFailureRecord | undefined): string {\n\tif (!record) {\n\t\treturn '';\n\t}\n\tconst failureClass = normalizeResolveIOAIManagerFailureClass(record.failureClass);\n\tconst blockerFingerprint = cleanText(record.blockerFingerprint, 120)\n\t\t|| fingerprintResolveIOAIManagerBlocker(record.blocker || record.summary || '');\n\treturn `${cleanText(record.lane, 80)}:${cleanText(record.stepType, 80)}:${failureClass}:${blockerFingerprint}`;\n}\n\nfunction failureEvidenceKey(record: ResolveIOAIManagerFailureRecord | undefined): string {\n\treturn `${failureKey(record)}:${hashResolveIOAIManagerEvidence(record)}`;\n}\n\nfunction isPassingOutcome(record: ResolveIOAIManagerFailureRecord | undefined): boolean {\n\treturn /^(pass|accepted|ready_to_publish|published|ready_for_merge|complete|completed)$/i.test(cleanText(record?.outcome, 80));\n}\n\nfunction isManualOutcome(record: ResolveIOAIManagerFailureRecord | undefined): boolean {\n\treturn /^(manual_handoff|park_manual|stopped)$/i.test(cleanText(record?.outcome, 80));\n}\n\nfunction collectOpenTail(records: ResolveIOAIManagerFailureRecord[]): ResolveIOAIManagerFailureRecord[] {\n\tconst tail: ResolveIOAIManagerFailureRecord[] = [];\n\tfor (let index = records.length - 1; index >= 0; index -= 1) {\n\t\tconst record = records[index];\n\t\tif (isPassingOutcome(record)) {\n\t\t\tbreak;\n\t\t}\n\t\ttail.unshift(record);\n\t}\n\treturn tail;\n}\n\nfunction countSameFailure(records: ResolveIOAIManagerFailureRecord[], current: ResolveIOAIManagerFailureRecord): number {\n\tconst currentKey = failureEvidenceKey(current);\n\tlet count = 0;\n\tfor (let index = records.length - 1; index >= 0; index -= 1) {\n\t\tconst record = records[index];\n\t\tif (isPassingOutcome(record)) {\n\t\t\tbreak;\n\t\t}\n\t\tif (failureEvidenceKey(record) !== currentKey) {\n\t\t\tbreak;\n\t\t}\n\t\tcount += 1;\n\t}\n\treturn count;\n}\n\nfunction countPingPong(records: ResolveIOAIManagerFailureRecord[], current: ResolveIOAIManagerFailureRecord): number {\n\tconst tail = collectOpenTail(records).filter((record) => {\n\t\treturn cleanText(record.lane, 80) === cleanText(current.lane, 80)\n\t\t\t&& cleanText(record.stepType, 80) === cleanText(current.stepType, 80);\n\t});\n\tif (tail.length < 4) {\n\t\treturn 0;\n\t}\n\tconst keys = tail.map(failureKey).filter(Boolean);\n\tconst last = keys.slice(-6);\n\tif (last.length < 4) {\n\t\treturn 0;\n\t}\n\tconst distinct = Array.from(new Set(last));\n\tif (distinct.length !== 2) {\n\t\treturn 0;\n\t}\n\tfor (let index = 2; index < last.length; index += 1) {\n\t\tif (last[index] !== last[index - 2]) {\n\t\t\treturn 0;\n\t\t}\n\t}\n\treturn last.length - 1;\n}\n\nexport function decideResolveIOAIManagerPolicy(input: ResolveIOAIManagerPolicyInput): ResolveIOAIManagerPolicyDecision {\n\tconst history = Array.isArray(input.history) ? input.history : [];\n\tconst current = input.current || history[history.length - 1] || {};\n\tconst failureClass = normalizeResolveIOAIManagerFailureClass(current.failureClass);\n\tconst blockerFingerprint = cleanText(current.blockerFingerprint, 120)\n\t\t|| fingerprintResolveIOAIManagerBlocker(current.blocker || current.summary || '');\n\tconst evidenceHash = hashResolveIOAIManagerEvidence(current);\n\tconst previous = history.length > 1 ? history[history.length - 2] : undefined;\n\tconst previousSameFailure = previous && failureKey(previous) === failureKey(current);\n\tconst previousEvidenceHash = previousSameFailure ? hashResolveIOAIManagerEvidence(previous) : '';\n\tconst newEvidence = !!previousSameFailure && !!previousEvidenceHash && previousEvidenceHash !== evidenceHash;\n\tconst sameFailureCount = countSameFailure(history, current);\n\tconst pingPongCount = countPingPong(history, current);\n\tconst maxSameFailureRepeats = Math.max(1, Number(input.maxSameFailureRepeats || 3) || 3);\n\tconst maxPingPongTransitions = Math.max(3, Number(input.maxPingPongTransitions || 3) || 3);\n\tconst infraClasses = new Set((input.infraFailureClasses || ['infra', 'compile']).map(normalizeResolveIOAIManagerFailureClass));\n\tconst ignoredClasses = new Set((input.ignoredFailureClasses || []).map(normalizeResolveIOAIManagerFailureClass));\n\tconst base = {\n\t\tfailureClass,\n\t\tblockerFingerprint,\n\t\tevidenceHash,\n\t\tsameFailureCount,\n\t\tpingPongCount,\n\t\tnewEvidence,\n\t\tloopBudgetShouldReset: false,\n\t\tproductRepairFailure: !infraClasses.has(failureClass) && !ignoredClasses.has(failureClass)\n\t};\n\tif (isPassingOutcome(current)) {\n\t\treturn {\n\t\t\t...base,\n\t\t\taction: 'reset_loop_budget',\n\t\t\treason: 'manager_policy_progress_passed',\n\t\t\tloopBudgetShouldReset: true,\n\t\t\tproductRepairFailure: false\n\t\t};\n\t}\n\tif (isManualOutcome(current)) {\n\t\treturn {\n\t\t\t...base,\n\t\t\taction: 'manual_handoff',\n\t\t\treason: 'manager_policy_manual_or_stopped'\n\t\t};\n\t}\n\tif (infraClasses.has(failureClass)) {\n\t\treturn {\n\t\t\t...base,\n\t\t\taction: 'retry_infra',\n\t\t\treason: 'manager_policy_infra_failure_routes_to_infra_repair',\n\t\t\tproductRepairFailure: false\n\t\t};\n\t}\n\tif (pingPongCount >= maxPingPongTransitions) {\n\t\treturn {\n\t\t\t...base,\n\t\t\taction: 'park_ping_pong',\n\t\t\treason: 'manager_policy_ping_pong_failure_loop'\n\t\t};\n\t}\n\tif (sameFailureCount >= maxSameFailureRepeats && !newEvidence) {\n\t\treturn {\n\t\t\t...base,\n\t\t\taction: 'park_repeated_failure',\n\t\t\treason: 'manager_policy_same_failure_without_new_evidence'\n\t\t};\n\t}\n\tif (newEvidence || !previousSameFailure) {\n\t\treturn {\n\t\t\t...base,\n\t\t\taction: 'continue',\n\t\t\treason: newEvidence\n\t\t\t\t? 'manager_policy_new_evidence_resets_loop_budget'\n\t\t\t\t: 'manager_policy_new_failure_or_lane',\n\t\t\tloopBudgetShouldReset: true\n\t\t};\n\t}\n\treturn {\n\t\t...base,\n\t\taction: 'continue',\n\t\treason: 'manager_policy_retry_below_repeat_limit'\n\t};\n}\n"]}
@@ -97,6 +97,8 @@ export interface ResolveIOAICoderV6StepRecord {
97
97
  summary: string;
98
98
  blocker?: string;
99
99
  blockerFingerprint?: string;
100
+ failureClass?: string;
101
+ evidenceHash?: string;
100
102
  changedFiles?: string[];
101
103
  artifactPaths?: string[];
102
104
  nextAction?: ResolveIOAICoderV6ContinuationDecision['action'];
@@ -150,6 +152,8 @@ export interface ResolveIOAICoderV6StepInput {
150
152
  runtimeMs?: number;
151
153
  summary?: string;
152
154
  blocker?: string;
155
+ failureClass?: string;
156
+ evidenceHash?: string;
153
157
  primaryWorkflowId?: string;
154
158
  activeWorkflowStep?: string;
155
159
  workflowQaRows?: ResolveIOAICoderV6WorkflowQaRow[];
@@ -54,6 +54,7 @@ exports.recordResolveIOAICoderV6Step = recordResolveIOAICoderV6Step;
54
54
  exports.decideResolveIOAICoderV6Continuation = decideResolveIOAICoderV6Continuation;
55
55
  exports.buildResolveIOAICoderV6DiagnoseFirstPrompt = buildResolveIOAICoderV6DiagnoseFirstPrompt;
56
56
  exports.buildResolveIOAICoderV6Incident = buildResolveIOAICoderV6Incident;
57
+ var ai_runner_manager_policy_1 = require("./ai-runner-manager-policy");
57
58
  var LANES = ['intake', 'plan', 'build', 'qa', 'repair', 'review', 'publish'];
58
59
  function isoNow(value) {
59
60
  if (value instanceof Date) {
@@ -156,6 +157,33 @@ function fingerprintResolveIOAICoderV6Blocker(value) {
156
157
  }
157
158
  return "aicoder-v6-".concat(Math.abs(hash).toString(36));
158
159
  }
160
+ function classifyResolveIOAICoderV6FailureClass(step) {
161
+ var explicit = cleanText(step.failureClass, 80).toLowerCase().replace(/[\s-]+/g, '_');
162
+ if (explicit) {
163
+ return explicit;
164
+ }
165
+ if (step.outcome === 'infra_retry') {
166
+ return 'infra';
167
+ }
168
+ var text = "".concat(step.stepType || '', "\n").concat(step.lane || '', "\n").concat(step.blocker || '', "\n").concat(step.summary || '').toLowerCase();
169
+ if (/\b(puppeteer|chrome|browser executable|mongo|port|startup|settings\.json|node_modules|npm install|cache|lock)\b/.test(text)) {
170
+ return 'infra';
171
+ }
172
+ if (/\b(ts[0-9]{3,5}|typescript|compile|build failed|ng build|cannot find name|module not found|syntax error)\b/.test(text)
173
+ || step.stepType === 'build') {
174
+ return 'compile';
175
+ }
176
+ if (step.stepType === 'journey_contract' || step.stepType === 'journey_validation') {
177
+ return 'journey';
178
+ }
179
+ if (step.stepType === 'workflow_qa' || step.lane === 'qa') {
180
+ return 'business';
181
+ }
182
+ if (step.stepType === 'publish' || step.stepType === 'test_deploy' || step.stepType === 'live_deploy' || step.lane === 'publish') {
183
+ return 'release';
184
+ }
185
+ return 'product_code';
186
+ }
159
187
  function buildResolveIOAICoderV6Budget(existing) {
160
188
  return {
161
189
  maxPromptTokensPerNonInitialStep: Number((existing === null || existing === void 0 ? void 0 : existing.maxPromptTokensPerNonInitialStep) || 4000),
@@ -257,6 +285,14 @@ function recordResolveIOAICoderV6Step(bundle, step) {
257
285
  var outputTokens = cleanNumber(step.outputTokens);
258
286
  var runtimeMs = cleanNumber(step.runtimeMs);
259
287
  var blocker = cleanText(step.blocker, 1200);
288
+ var failureClass = classifyResolveIOAICoderV6FailureClass({
289
+ outcome: step.outcome,
290
+ lane: step.lane,
291
+ stepType: step.stepType,
292
+ blocker: blocker,
293
+ summary: step.summary,
294
+ failureClass: step.failureClass
295
+ });
260
296
  var previousWorkflowMemory = bundle.aiCoderV6WorkflowMemory || {};
261
297
  var activeWorkflowStep = cleanText(step.activeWorkflowStep || previousWorkflowMemory.activeWorkflowStep, 200);
262
298
  var explicitCompletedSteps = cleanList(step.completedWorkflowSteps, 40, 240);
@@ -283,11 +319,26 @@ function recordResolveIOAICoderV6Step(bundle, step) {
283
319
  summary: cleanText(step.summary || blocker || step.outcome, 1200),
284
320
  blocker: blocker || undefined,
285
321
  blockerFingerprint: blocker ? fingerprintResolveIOAICoderV6Blocker(blocker) : undefined,
322
+ failureClass: failureClass,
286
323
  changedFiles: cleanList(step.changedFiles, 80, 500),
287
324
  artifactPaths: cleanList(step.artifactPaths, 80, 500),
288
325
  nextAction: step.nextAction,
289
326
  recordedAt: now
290
327
  };
328
+ record.evidenceHash = cleanText(step.evidenceHash, 120)
329
+ || (0, ai_runner_manager_policy_1.hashResolveIOAIManagerEvidence)(record);
330
+ var previousRecord = bundle.aiCoderV6StepHistory[bundle.aiCoderV6StepHistory.length - 1];
331
+ var managerDecision = (0, ai_runner_manager_policy_1.decideResolveIOAIManagerPolicy)({
332
+ history: __spreadArray(__spreadArray([], __read(bundle.aiCoderV6StepHistory), false), [record], false),
333
+ current: record,
334
+ maxSameFailureRepeats: buildResolveIOAICoderV6Budget(bundle.aiCoderV6Budget).maxRepeatedNoProgress + 1
335
+ });
336
+ var nextLoopCount = managerDecision.loopBudgetShouldReset
337
+ || (previousRecord === null || previousRecord === void 0 ? void 0 : previousRecord.failureClass) !== record.failureClass
338
+ || (previousRecord === null || previousRecord === void 0 ? void 0 : previousRecord.blockerFingerprint) !== record.blockerFingerprint
339
+ || (previousRecord === null || previousRecord === void 0 ? void 0 : previousRecord.evidenceHash) !== record.evidenceHash
340
+ ? 1
341
+ : bundle.aiCoderV6Budget.loopCount + 1;
291
342
  var previousLane = bundle.aiCoderV6LaneMemory[step.lane];
292
343
  var laneMemory = __assign(__assign({}, bundle.aiCoderV6LaneMemory), (_a = {}, _a[step.lane] = __assign(__assign({}, previousLane), { model: record.model || previousLane.model, threadKey: record.threadKey || previousLane.threadKey, activeStep: step.stepType, activeBlocker: record.blocker || previousLane.activeBlocker || '', activeQaRow: step.activeQaRow || previousLane.activeQaRow, changedFiles: ((_b = record.changedFiles) === null || _b === void 0 ? void 0 : _b.length) ? record.changedFiles : previousLane.changedFiles, artifactPaths: ((_c = record.artifactPaths) === null || _c === void 0 ? void 0 : _c.length) ? record.artifactPaths : previousLane.artifactPaths, latestPromptVersion: record.promptVersion || previousLane.latestPromptVersion, latestPromptTokenEstimate: promptTokens || previousLane.latestPromptTokenEstimate, updatedAt: now }), _a));
293
344
  var complete = step.outcome === 'published' || step.outcome === 'ready_to_publish';
@@ -301,7 +352,7 @@ function recordResolveIOAICoderV6Step(bundle, step) {
301
352
  blockedWorkflowStep: blockedWorkflowStep,
302
353
  businessProofArtifacts: businessProofArtifacts,
303
354
  updatedAt: now
304
- }, aiCoderV6StepHistory: __spreadArray(__spreadArray([], __read(bundle.aiCoderV6StepHistory), false), [record], false).slice(-120), aiCoderV6Budget: __assign(__assign({}, bundle.aiCoderV6Budget), { totalPromptTokenEstimate: bundle.aiCoderV6Budget.totalPromptTokenEstimate + promptTokens, totalInputTokens: bundle.aiCoderV6Budget.totalInputTokens + inputTokens, totalCachedInputTokens: bundle.aiCoderV6Budget.totalCachedInputTokens + cachedInputTokens, totalOutputTokens: bundle.aiCoderV6Budget.totalOutputTokens + outputTokens, totalRuntimeMs: bundle.aiCoderV6Budget.totalRuntimeMs + runtimeMs, loopCount: bundle.aiCoderV6Budget.loopCount + 1 }) });
355
+ }, aiCoderV6StepHistory: __spreadArray(__spreadArray([], __read(bundle.aiCoderV6StepHistory), false), [record], false).slice(-120), aiCoderV6Budget: __assign(__assign({}, bundle.aiCoderV6Budget), { totalPromptTokenEstimate: bundle.aiCoderV6Budget.totalPromptTokenEstimate + promptTokens, totalInputTokens: bundle.aiCoderV6Budget.totalInputTokens + inputTokens, totalCachedInputTokens: bundle.aiCoderV6Budget.totalCachedInputTokens + cachedInputTokens, totalOutputTokens: bundle.aiCoderV6Budget.totalOutputTokens + outputTokens, totalRuntimeMs: bundle.aiCoderV6Budget.totalRuntimeMs + runtimeMs, loopCount: nextLoopCount }) });
305
356
  }
306
357
  function decideResolveIOAICoderV6Continuation(bundle) {
307
358
  var history = bundle.aiCoderV6StepHistory || [];
@@ -321,7 +372,14 @@ function decideResolveIOAICoderV6Continuation(bundle) {
321
372
  repeatedNoProgressCount += 1;
322
373
  }
323
374
  }
324
- var budgetExceeded = budget.loopCount >= budget.maxLoopsPerRun
375
+ var managerDecision = (0, ai_runner_manager_policy_1.decideResolveIOAIManagerPolicy)({
376
+ history: history,
377
+ current: last,
378
+ maxSameFailureRepeats: budget.maxRepeatedNoProgress + 1,
379
+ maxPingPongTransitions: 3,
380
+ infraFailureClasses: ['infra']
381
+ });
382
+ var budgetExceeded = (budget.loopCount >= budget.maxLoopsPerRun && !managerDecision.loopBudgetShouldReset)
325
383
  || budget.totalPromptTokenEstimate >= budget.maxTotalPromptTokens
326
384
  || ((last === null || last === void 0 ? void 0 : last.promptTokenEstimate) || 0) > budget.maxPromptTokensPerNonInitialStep * 2;
327
385
  if (budgetExceeded) {
@@ -334,6 +392,26 @@ function decideResolveIOAICoderV6Continuation(bundle) {
334
392
  budgetExceeded: budgetExceeded
335
393
  };
336
394
  }
395
+ if (managerDecision.action === 'park_ping_pong') {
396
+ return {
397
+ action: 'park',
398
+ reason: 'aicoder_v6_ping_pong_no_progress',
399
+ nextLane: (last === null || last === void 0 ? void 0 : last.lane) || bundle.aiCoderV6SupervisorState.activeLane,
400
+ nextStep: (last === null || last === void 0 ? void 0 : last.stepType) || bundle.aiCoderV6SupervisorState.activeStep,
401
+ repeatedNoProgressCount: managerDecision.pingPongCount,
402
+ budgetExceeded: false
403
+ };
404
+ }
405
+ if (managerDecision.action === 'park_repeated_failure') {
406
+ return {
407
+ action: 'park',
408
+ reason: 'aicoder_v6_repeated_no_progress',
409
+ nextLane: (last === null || last === void 0 ? void 0 : last.lane) || bundle.aiCoderV6SupervisorState.activeLane,
410
+ nextStep: (last === null || last === void 0 ? void 0 : last.stepType) || bundle.aiCoderV6SupervisorState.activeStep,
411
+ repeatedNoProgressCount: managerDecision.sameFailureCount,
412
+ budgetExceeded: false
413
+ };
414
+ }
337
415
  if (repeatedNoProgressCount > budget.maxRepeatedNoProgress) {
338
416
  return {
339
417
  action: 'park',