@resolveio/server-lib 22.3.127 → 22.3.129

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,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"]}
@@ -1,5 +1,5 @@
1
1
  export type ResolveIOAICoderV6Lane = 'intake' | 'plan' | 'build' | 'qa' | 'repair' | 'review' | 'publish';
2
- export type ResolveIOAICoderV6StepType = 'intake' | 'plan' | 'task' | 'build' | 'qa' | 'repair' | 'review' | 'test_deploy' | 'live_deploy' | 'publish' | 'cleanup';
2
+ export type ResolveIOAICoderV6StepType = 'intake' | 'journey_contract' | 'journey_validation' | 'plan' | 'task' | 'workflow_build' | 'workflow_qa' | 'build' | 'qa' | 'repair' | 'review' | 'test_deploy' | 'live_deploy' | 'publish' | 'cleanup';
3
3
  export type ResolveIOAICoderV6Outcome = 'pass' | 'needs_repair' | 'retry_same_step' | 'park_manual' | 'budget_stop' | 'infra_retry' | 'ready_to_publish' | 'published';
4
4
  export type ResolveIOAICoderV6RunKind = 'initial_builder' | 'terminal_helper';
5
5
  export interface ResolveIOAICoderV6Budget {
@@ -37,6 +37,27 @@ export interface ResolveIOAICoderV6LaneMemory {
37
37
  latestPromptTokenEstimate?: number;
38
38
  updatedAt: string;
39
39
  }
40
+ export interface ResolveIOAICoderV6WorkflowQaRow {
41
+ index?: number;
42
+ workflowId?: string;
43
+ stepId?: string;
44
+ route?: string;
45
+ action?: string;
46
+ assertion?: string;
47
+ expectedState?: string;
48
+ status?: string;
49
+ artifactPaths?: string[];
50
+ }
51
+ export interface ResolveIOAICoderV6WorkflowMemory {
52
+ journeyContractPath: string;
53
+ primaryWorkflowId: string;
54
+ activeWorkflowStep: string;
55
+ workflowQaRows: ResolveIOAICoderV6WorkflowQaRow[];
56
+ completedWorkflowSteps: string[];
57
+ blockedWorkflowStep: string;
58
+ businessProofArtifacts: string[];
59
+ updatedAt: string;
60
+ }
40
61
  export interface ResolveIOAICoderV6SupervisorState {
41
62
  version: 'v6';
42
63
  runKind: ResolveIOAICoderV6RunKind;
@@ -76,6 +97,8 @@ export interface ResolveIOAICoderV6StepRecord {
76
97
  summary: string;
77
98
  blocker?: string;
78
99
  blockerFingerprint?: string;
100
+ failureClass?: string;
101
+ evidenceHash?: string;
79
102
  changedFiles?: string[];
80
103
  artifactPaths?: string[];
81
104
  nextAction?: ResolveIOAICoderV6ContinuationDecision['action'];
@@ -94,6 +117,7 @@ export interface ResolveIOAICoderV6StateBundle {
94
117
  aiCoderRunnerVersion: 'v6';
95
118
  aiCoderV6SupervisorState: ResolveIOAICoderV6SupervisorState;
96
119
  aiCoderV6LaneMemory: Record<ResolveIOAICoderV6Lane, ResolveIOAICoderV6LaneMemory>;
120
+ aiCoderV6WorkflowMemory: ResolveIOAICoderV6WorkflowMemory;
97
121
  aiCoderV6StepHistory: ResolveIOAICoderV6StepRecord[];
98
122
  aiCoderV6Budget: ResolveIOAICoderV6Budget;
99
123
  aiCoderV6RunnerIncidents: ResolveIOAICoderV6RunnerIncident[];
@@ -107,6 +131,7 @@ export interface ResolveIOAICoderV6InitializeInput {
107
131
  description?: string;
108
132
  approvedScopeRequirements?: string[];
109
133
  branchName?: string;
134
+ journeyContractPath?: string;
110
135
  defaultModel?: string;
111
136
  laneThreadKeys?: Partial<Record<ResolveIOAICoderV6Lane, string>>;
112
137
  processLease?: ResolveIOAICoderV6SupervisorState['processLease'];
@@ -127,6 +152,14 @@ export interface ResolveIOAICoderV6StepInput {
127
152
  runtimeMs?: number;
128
153
  summary?: string;
129
154
  blocker?: string;
155
+ failureClass?: string;
156
+ evidenceHash?: string;
157
+ primaryWorkflowId?: string;
158
+ activeWorkflowStep?: string;
159
+ workflowQaRows?: ResolveIOAICoderV6WorkflowQaRow[];
160
+ completedWorkflowSteps?: string[];
161
+ blockedWorkflowStep?: string;
162
+ businessProofArtifacts?: string[];
130
163
  changedFiles?: string[];
131
164
  artifactPaths?: string[];
132
165
  activeQaRow?: ResolveIOAICoderV6LaneMemory['activeQaRow'];
@@ -154,6 +187,8 @@ export declare function buildResolveIOAICoderV6DiagnoseFirstPrompt(lines: {
154
187
  activeBlocker?: string;
155
188
  laneSummary?: string;
156
189
  currentQaRow?: ResolveIOAICoderV6LaneMemory['activeQaRow'];
190
+ journeyContractPath?: string;
191
+ activeWorkflowStep?: string;
157
192
  artifactPaths?: string[];
158
193
  changedFiles?: string[];
159
194
  }): string[];
@@ -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) {
@@ -102,6 +103,47 @@ function cleanNumber(value) {
102
103
  var parsed = Number(value);
103
104
  return Number.isFinite(parsed) && parsed > 0 ? Math.floor(parsed) : 0;
104
105
  }
106
+ function cleanWorkflowQaRows(values, limit) {
107
+ var e_2, _a;
108
+ if (limit === void 0) { limit = 40; }
109
+ if (!Array.isArray(values)) {
110
+ return [];
111
+ }
112
+ var rows = [];
113
+ try {
114
+ for (var values_2 = __values(values), values_2_1 = values_2.next(); !values_2_1.done; values_2_1 = values_2.next()) {
115
+ var value = values_2_1.value;
116
+ if (!value || typeof value !== 'object') {
117
+ continue;
118
+ }
119
+ var row = {
120
+ index: cleanNumber(value.index) || undefined,
121
+ workflowId: cleanText(value.workflowId || value.workflow_id, 160) || undefined,
122
+ stepId: cleanText(value.stepId || value.step_id, 160) || undefined,
123
+ route: cleanText(value.route, 240) || undefined,
124
+ action: cleanText(value.action, 500) || undefined,
125
+ assertion: cleanText(value.assertion, 700) || undefined,
126
+ expectedState: cleanText(value.expectedState || value.expected_state, 500) || undefined,
127
+ status: cleanText(value.status, 120) || undefined,
128
+ artifactPaths: cleanList(value.artifactPaths || value.artifact_paths, 20, 500)
129
+ };
130
+ if (row.workflowId || row.stepId || row.route || row.action || row.assertion) {
131
+ rows.push(row);
132
+ }
133
+ if (rows.length >= limit) {
134
+ break;
135
+ }
136
+ }
137
+ }
138
+ catch (e_2_1) { e_2 = { error: e_2_1 }; }
139
+ finally {
140
+ try {
141
+ if (values_2_1 && !values_2_1.done && (_a = values_2.return)) _a.call(values_2);
142
+ }
143
+ finally { if (e_2) throw e_2.error; }
144
+ }
145
+ return rows;
146
+ }
105
147
  function fingerprintResolveIOAICoderV6Blocker(value) {
106
148
  var text = cleanText(value, 4000)
107
149
  .toLowerCase()
@@ -115,6 +157,33 @@ function fingerprintResolveIOAICoderV6Blocker(value) {
115
157
  }
116
158
  return "aicoder-v6-".concat(Math.abs(hash).toString(36));
117
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
+ }
118
187
  function buildResolveIOAICoderV6Budget(existing) {
119
188
  return {
120
189
  maxPromptTokensPerNonInitialStep: Number((existing === null || existing === void 0 ? void 0 : existing.maxPromptTokensPerNonInitialStep) || 4000),
@@ -137,6 +206,7 @@ function initializeResolveIOAICoderV6State(input) {
137
206
  var existing = input.existing || {};
138
207
  var existingSupervisor = existing.aiCoderV6SupervisorState;
139
208
  var existingLaneMemory = existing.aiCoderV6LaneMemory || {};
209
+ var existingWorkflowMemory = existing.aiCoderV6WorkflowMemory || {};
140
210
  var scope = cleanList(input.approvedScopeRequirements, 24, 240).join(' | ')
141
211
  || cleanText(input.description, 1000)
142
212
  || cleanText(input.title, 300);
@@ -186,6 +256,16 @@ function initializeResolveIOAICoderV6State(input) {
186
256
  updatedAt: now
187
257
  },
188
258
  aiCoderV6LaneMemory: laneMemory,
259
+ aiCoderV6WorkflowMemory: {
260
+ journeyContractPath: cleanText(input.journeyContractPath || existingWorkflowMemory.journeyContractPath || 'docs/APP_JOURNEY_CONTRACT.md', 500),
261
+ primaryWorkflowId: cleanText(existingWorkflowMemory.primaryWorkflowId, 200),
262
+ activeWorkflowStep: cleanText(existingWorkflowMemory.activeWorkflowStep, 200),
263
+ workflowQaRows: cleanWorkflowQaRows(existingWorkflowMemory.workflowQaRows, 80),
264
+ completedWorkflowSteps: cleanList(existingWorkflowMemory.completedWorkflowSteps, 80, 240),
265
+ blockedWorkflowStep: cleanText(existingWorkflowMemory.blockedWorkflowStep, 240),
266
+ businessProofArtifacts: cleanList(existingWorkflowMemory.businessProofArtifacts, 80, 500),
267
+ updatedAt: existingWorkflowMemory.updatedAt || now
268
+ },
189
269
  aiCoderV6StepHistory: Array.isArray(existing.aiCoderV6StepHistory)
190
270
  ? existing.aiCoderV6StepHistory.slice(-100)
191
271
  : [],
@@ -205,6 +285,25 @@ function recordResolveIOAICoderV6Step(bundle, step) {
205
285
  var outputTokens = cleanNumber(step.outputTokens);
206
286
  var runtimeMs = cleanNumber(step.runtimeMs);
207
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
+ });
296
+ var previousWorkflowMemory = bundle.aiCoderV6WorkflowMemory || {};
297
+ var activeWorkflowStep = cleanText(step.activeWorkflowStep || previousWorkflowMemory.activeWorkflowStep, 200);
298
+ var explicitCompletedSteps = cleanList(step.completedWorkflowSteps, 40, 240);
299
+ var completedWorkflowSteps = Array.from(new Set(__spreadArray(__spreadArray(__spreadArray([], __read(cleanList(previousWorkflowMemory.completedWorkflowSteps, 80, 240)), false), __read(explicitCompletedSteps), false), __read((step.outcome === 'pass' && activeWorkflowStep ? [activeWorkflowStep] : [])), false))).slice(-80);
300
+ var businessProofArtifacts = Array.from(new Set(__spreadArray(__spreadArray(__spreadArray([], __read(cleanList(previousWorkflowMemory.businessProofArtifacts, 80, 500)), false), __read(cleanList(step.businessProofArtifacts, 40, 500)), false), __read((step.stepType === 'workflow_qa' ? cleanList(step.artifactPaths, 40, 500) : [])), false))).slice(-80);
301
+ var workflowQaRows = step.workflowQaRows !== undefined
302
+ ? cleanWorkflowQaRows(step.workflowQaRows, 80)
303
+ : cleanWorkflowQaRows(previousWorkflowMemory.workflowQaRows, 80);
304
+ var blockedWorkflowStep = cleanText(step.blockedWorkflowStep
305
+ || ((step.outcome === 'needs_repair' || step.outcome === 'park_manual') ? activeWorkflowStep : '')
306
+ || previousWorkflowMemory.blockedWorkflowStep, 240);
208
307
  var record = {
209
308
  stepType: step.stepType,
210
309
  outcome: step.outcome,
@@ -220,16 +319,40 @@ function recordResolveIOAICoderV6Step(bundle, step) {
220
319
  summary: cleanText(step.summary || blocker || step.outcome, 1200),
221
320
  blocker: blocker || undefined,
222
321
  blockerFingerprint: blocker ? fingerprintResolveIOAICoderV6Blocker(blocker) : undefined,
322
+ failureClass: failureClass,
223
323
  changedFiles: cleanList(step.changedFiles, 80, 500),
224
324
  artifactPaths: cleanList(step.artifactPaths, 80, 500),
225
325
  nextAction: step.nextAction,
226
326
  recordedAt: now
227
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;
228
342
  var previousLane = bundle.aiCoderV6LaneMemory[step.lane];
229
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));
230
344
  var complete = step.outcome === 'published' || step.outcome === 'ready_to_publish';
231
345
  var parked = step.outcome === 'park_manual' || step.outcome === 'budget_stop';
232
- return __assign(__assign({}, bundle), { aiCoderV6SupervisorState: __assign(__assign({}, bundle.aiCoderV6SupervisorState), { status: complete ? 'complete' : (parked ? 'parked' : 'active'), activeLane: step.lane, activeStep: step.stepType, activeBlocker: record.blocker || '', lastGoodCheckpoint: step.outcome === 'pass' || complete ? step.stepType : bundle.aiCoderV6SupervisorState.lastGoodCheckpoint, artifactLinks: Array.from(new Set(__spreadArray(__spreadArray([], __read(bundle.aiCoderV6SupervisorState.artifactLinks), false), __read((record.artifactPaths || [])), false))).slice(-80), updatedAt: now }), aiCoderV6LaneMemory: laneMemory, 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 }) });
346
+ return __assign(__assign({}, bundle), { aiCoderV6SupervisorState: __assign(__assign({}, bundle.aiCoderV6SupervisorState), { status: complete ? 'complete' : (parked ? 'parked' : 'active'), activeLane: step.lane, activeStep: step.stepType, activeBlocker: record.blocker || '', lastGoodCheckpoint: step.outcome === 'pass' || complete ? step.stepType : bundle.aiCoderV6SupervisorState.lastGoodCheckpoint, artifactLinks: Array.from(new Set(__spreadArray(__spreadArray([], __read(bundle.aiCoderV6SupervisorState.artifactLinks), false), __read((record.artifactPaths || [])), false))).slice(-80), updatedAt: now }), aiCoderV6LaneMemory: laneMemory, aiCoderV6WorkflowMemory: {
347
+ journeyContractPath: cleanText(previousWorkflowMemory.journeyContractPath || 'docs/APP_JOURNEY_CONTRACT.md', 500),
348
+ primaryWorkflowId: cleanText(step.primaryWorkflowId || previousWorkflowMemory.primaryWorkflowId, 200),
349
+ activeWorkflowStep: activeWorkflowStep,
350
+ workflowQaRows: workflowQaRows,
351
+ completedWorkflowSteps: completedWorkflowSteps,
352
+ blockedWorkflowStep: blockedWorkflowStep,
353
+ businessProofArtifacts: businessProofArtifacts,
354
+ updatedAt: now
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 }) });
233
356
  }
234
357
  function decideResolveIOAICoderV6Continuation(bundle) {
235
358
  var history = bundle.aiCoderV6StepHistory || [];
@@ -249,7 +372,14 @@ function decideResolveIOAICoderV6Continuation(bundle) {
249
372
  repeatedNoProgressCount += 1;
250
373
  }
251
374
  }
252
- 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)
253
383
  || budget.totalPromptTokenEstimate >= budget.maxTotalPromptTokens
254
384
  || ((last === null || last === void 0 ? void 0 : last.promptTokenEstimate) || 0) > budget.maxPromptTokensPerNonInitialStep * 2;
255
385
  if (budgetExceeded) {
@@ -262,6 +392,26 @@ function decideResolveIOAICoderV6Continuation(bundle) {
262
392
  budgetExceeded: budgetExceeded
263
393
  };
264
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
+ }
265
415
  if (repeatedNoProgressCount > budget.maxRepeatedNoProgress) {
266
416
  return {
267
417
  action: 'park',
@@ -328,6 +478,8 @@ function buildResolveIOAICoderV6DiagnoseFirstPrompt(lines) {
328
478
  lines.activeBlocker ? "Active blocker: ".concat(cleanText(lines.activeBlocker, 800)) : '',
329
479
  ((_a = lines.currentQaRow) === null || _a === void 0 ? void 0 : _a.workflow) ? "Current QA row: ".concat(cleanText(lines.currentQaRow.workflow, 300)) : '',
330
480
  ((_b = lines.currentQaRow) === null || _b === void 0 ? void 0 : _b.route) ? "Current QA route: ".concat(cleanText(lines.currentQaRow.route, 300)) : '',
481
+ lines.journeyContractPath ? "Journey contract: ".concat(cleanText(lines.journeyContractPath, 240)) : '',
482
+ lines.activeWorkflowStep ? "Active workflow step: ".concat(cleanText(lines.activeWorkflowStep, 240)) : '',
331
483
  cleanList(lines.changedFiles, 12, 200).length ? "Changed files: ".concat(cleanList(lines.changedFiles, 12, 200).join(', ')) : '',
332
484
  cleanList(lines.artifactPaths, 12, 240).length ? "Artifacts: ".concat(cleanList(lines.artifactPaths, 12, 240).join(', ')) : ''
333
485
  ].filter(Boolean);