@resolveio/server-lib 22.3.145 → 22.3.147
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/util/ai-runner-manager-autopilot.d.ts +3 -0
- package/util/ai-runner-manager-autopilot.js +12 -0
- package/util/ai-runner-manager-autopilot.js.map +1 -1
- package/util/ai-runner-manager-policy.d.ts +121 -0
- package/util/ai-runner-manager-policy.js +802 -36
- package/util/ai-runner-manager-policy.js.map +1 -1
|
@@ -47,6 +47,8 @@ var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
|
|
|
47
47
|
return to.concat(ar || Array.prototype.slice.call(from));
|
|
48
48
|
};
|
|
49
49
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
50
|
+
exports.buildResolveIOAIManagerHotfixFirstReleasePolicy = buildResolveIOAIManagerHotfixFirstReleasePolicy;
|
|
51
|
+
exports.isResolveIOAIManagerSafeAutoDispatch = isResolveIOAIManagerSafeAutoDispatch;
|
|
50
52
|
exports.normalizeResolveIOAIManagerFailureClass = normalizeResolveIOAIManagerFailureClass;
|
|
51
53
|
exports.fingerprintResolveIOAIManagerBlocker = fingerprintResolveIOAIManagerBlocker;
|
|
52
54
|
exports.hashResolveIOAIManagerEvidence = hashResolveIOAIManagerEvidence;
|
|
@@ -56,9 +58,11 @@ exports.buildResolveIOAIManagerRecoveryActionPacket = buildResolveIOAIManagerRec
|
|
|
56
58
|
exports.decideResolveIOAIManagerRecoveryActionDispatch = decideResolveIOAIManagerRecoveryActionDispatch;
|
|
57
59
|
exports.appendResolveIOAIManagerRecoveryActionDispatch = appendResolveIOAIManagerRecoveryActionDispatch;
|
|
58
60
|
exports.buildResolveIOAIManagerRecoveryExecutionDirective = buildResolveIOAIManagerRecoveryExecutionDirective;
|
|
61
|
+
exports.assessResolveIOAIManagerEvidenceChange = assessResolveIOAIManagerEvidenceChange;
|
|
59
62
|
exports.decideResolveIOAIManagerRecoveryGate = decideResolveIOAIManagerRecoveryGate;
|
|
60
63
|
exports.buildResolveIOAIManagerRecoveryPlan = buildResolveIOAIManagerRecoveryPlan;
|
|
61
64
|
exports.decideResolveIOAIManagerPolicy = decideResolveIOAIManagerPolicy;
|
|
65
|
+
exports.buildResolveIOAIManagerRecoveryReplayMatrix = buildResolveIOAIManagerRecoveryReplayMatrix;
|
|
62
66
|
function cleanText(value, max) {
|
|
63
67
|
if (max === void 0) { max = 2000; }
|
|
64
68
|
return String(value || '').replace(/\s+/g, ' ').trim().slice(0, max);
|
|
@@ -92,6 +96,323 @@ function cleanList(values, limit, max) {
|
|
|
92
96
|
}
|
|
93
97
|
return result;
|
|
94
98
|
}
|
|
99
|
+
function releaseStatusIsBlocked(value) {
|
|
100
|
+
return /fail|error|blocked|missing|empty|not ready|not_ready|denied|invalid|timeout|stale/i.test(value);
|
|
101
|
+
}
|
|
102
|
+
function releaseStatusIsTerminalDeploy(value) {
|
|
103
|
+
return /requested|queued|in.?progress|completed|complete|success|succeeded|pass|passed|published|deployed|failed|error|blocked/i.test(value);
|
|
104
|
+
}
|
|
105
|
+
function buildReleaseAllowedActions(action) {
|
|
106
|
+
if (action === 'wait_for_active_deploy') {
|
|
107
|
+
return ['wait_for_current_deploy_result', 'collect_current_deploy_log', 'refresh_release_snapshot'];
|
|
108
|
+
}
|
|
109
|
+
if (action === 'block_duplicate_deploy') {
|
|
110
|
+
return ['collect_existing_deploy_evidence', 'hotfix_release_artifact', 'request_force_deploy_with_reason'];
|
|
111
|
+
}
|
|
112
|
+
if (action === 'block_duplicate_publish') {
|
|
113
|
+
return ['collect_existing_publish_evidence', 'hotfix_release_artifact', 'request_force_publish_with_reason'];
|
|
114
|
+
}
|
|
115
|
+
if (action === 'review_force_deploy') {
|
|
116
|
+
return ['verify_force_deploy_reason', 'rerun_failed_release_gate_once', 'record_force_deploy_evidence'];
|
|
117
|
+
}
|
|
118
|
+
if (action === 'deploy_new_artifact_after_release_gate') {
|
|
119
|
+
return ['verify_new_artifact_fingerprint', 'run_release_gate_once', 'record_publish_deploy_evidence'];
|
|
120
|
+
}
|
|
121
|
+
if (action === 'build_artifact_first') {
|
|
122
|
+
return ['build_missing_release_artifact', 'record_artifact_fingerprint', 'run_release_gate_once'];
|
|
123
|
+
}
|
|
124
|
+
return ['hotfix_live_runner_or_release_artifact', 'rerun_failed_release_gate_only', 'record_release_evidence'];
|
|
125
|
+
}
|
|
126
|
+
function hotfixStep(id, label, channel, options) {
|
|
127
|
+
if (options === void 0) { options = {}; }
|
|
128
|
+
return {
|
|
129
|
+
id: id,
|
|
130
|
+
label: label,
|
|
131
|
+
channel: channel,
|
|
132
|
+
safeToAutoRun: options.safeToAutoRun === true,
|
|
133
|
+
requiresFullDeploy: options.requiresFullDeploy === true,
|
|
134
|
+
requiredEvidence: options.requiredEvidence || [],
|
|
135
|
+
successEvidence: options.successEvidence || [],
|
|
136
|
+
blockedBy: options.blockedBy || []
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
function buildHotfixFirstReleasePlan(input) {
|
|
140
|
+
var surface = cleanText(input.surface || 'runner', 80)
|
|
141
|
+
.toLowerCase()
|
|
142
|
+
.replace(/[^a-z0-9]+/g, '_')
|
|
143
|
+
.replace(/^_+|_+$/g, '') || 'runner';
|
|
144
|
+
var commonAcceptance = [
|
|
145
|
+
'failed release gate is rerun once and passes',
|
|
146
|
+
'artifact fingerprint or hotfix evidence is recorded',
|
|
147
|
+
'operator console shows no active duplicate deploy blocker'
|
|
148
|
+
];
|
|
149
|
+
if (input.action === 'wait_for_active_deploy') {
|
|
150
|
+
return {
|
|
151
|
+
planId: "".concat(surface, ":wait_for_active_deploy"),
|
|
152
|
+
label: 'Wait For Active Deploy',
|
|
153
|
+
recommendedChannel: 'release_artifact',
|
|
154
|
+
reason: input.reason,
|
|
155
|
+
fullDeployAvoided: true,
|
|
156
|
+
steps: [
|
|
157
|
+
hotfixStep('collect_active_deploy_log', 'Collect active deploy log', 'release_artifact', {
|
|
158
|
+
safeToAutoRun: true,
|
|
159
|
+
requiredEvidence: ['active deploy id or release operation id'],
|
|
160
|
+
successEvidence: ['terminal deploy status and release log captured']
|
|
161
|
+
})
|
|
162
|
+
],
|
|
163
|
+
acceptanceEvidence: commonAcceptance,
|
|
164
|
+
escalationTriggers: ['active deploy exceeds timeout', 'active deploy fails without a release log']
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
if (input.action === 'deploy_new_artifact_after_release_gate') {
|
|
168
|
+
return {
|
|
169
|
+
planId: "".concat(surface, ":deploy_new_artifact_after_release_gate"),
|
|
170
|
+
label: 'Deploy New Artifact After Release Gate',
|
|
171
|
+
recommendedChannel: 'new_artifact_deploy',
|
|
172
|
+
reason: input.reason,
|
|
173
|
+
fullDeployAvoided: false,
|
|
174
|
+
steps: [
|
|
175
|
+
hotfixStep('verify_new_artifact_fingerprint', 'Verify new artifact fingerprint', 'new_artifact_deploy', {
|
|
176
|
+
safeToAutoRun: true,
|
|
177
|
+
requiresFullDeploy: true,
|
|
178
|
+
requiredEvidence: ['current artifact fingerprint differs from last deployed fingerprint'],
|
|
179
|
+
successEvidence: ['release gate permits one full deploy']
|
|
180
|
+
})
|
|
181
|
+
],
|
|
182
|
+
acceptanceEvidence: [
|
|
183
|
+
'new artifact fingerprint recorded',
|
|
184
|
+
'release gate passed before full deploy',
|
|
185
|
+
'deploy/publish result recorded'
|
|
186
|
+
],
|
|
187
|
+
escalationTriggers: ['artifact fingerprint matches last deploy', 'release gate fails']
|
|
188
|
+
};
|
|
189
|
+
}
|
|
190
|
+
if (input.action === 'build_artifact_first') {
|
|
191
|
+
return {
|
|
192
|
+
planId: "".concat(surface, ":build_artifact_first"),
|
|
193
|
+
label: 'Build Artifact First',
|
|
194
|
+
recommendedChannel: 'artifact_build',
|
|
195
|
+
reason: input.reason,
|
|
196
|
+
fullDeployAvoided: true,
|
|
197
|
+
steps: [
|
|
198
|
+
hotfixStep('build_once_record_fingerprint', 'Build once and record fingerprint', 'artifact_build', {
|
|
199
|
+
safeToAutoRun: false,
|
|
200
|
+
requiredEvidence: ['missing artifact fingerprint', 'release gate reason for building'],
|
|
201
|
+
successEvidence: ['artifact fingerprint recorded before any deploy']
|
|
202
|
+
})
|
|
203
|
+
],
|
|
204
|
+
acceptanceEvidence: ['artifact fingerprint exists', 'no deploy queued before release gate'],
|
|
205
|
+
escalationTriggers: ['build repeats without a new fingerprint', 'build failure lacks compile log']
|
|
206
|
+
};
|
|
207
|
+
}
|
|
208
|
+
if (input.action === 'review_force_deploy') {
|
|
209
|
+
return {
|
|
210
|
+
planId: "".concat(surface, ":review_force_deploy"),
|
|
211
|
+
label: 'Review Force Deploy',
|
|
212
|
+
recommendedChannel: 'force_deploy_review',
|
|
213
|
+
reason: input.reason,
|
|
214
|
+
fullDeployAvoided: false,
|
|
215
|
+
steps: [
|
|
216
|
+
hotfixStep('verify_force_deploy_reason', 'Verify force deploy reason', 'force_deploy_review', {
|
|
217
|
+
requiredEvidence: ['explicit force_deploy reason', 'why hotfix cannot resolve the release blocker'],
|
|
218
|
+
successEvidence: ['one allowed deploy attempt is recorded with reason']
|
|
219
|
+
})
|
|
220
|
+
],
|
|
221
|
+
acceptanceEvidence: ['force deploy evidence recorded', 'duplicate fingerprint exception is auditable'],
|
|
222
|
+
escalationTriggers: ['force deploy reason is empty', 'same force deploy fails twice']
|
|
223
|
+
};
|
|
224
|
+
}
|
|
225
|
+
return {
|
|
226
|
+
planId: "".concat(surface, ":").concat(input.action),
|
|
227
|
+
label: input.action === 'block_duplicate_deploy'
|
|
228
|
+
? 'Hotfix Or Force Deploy'
|
|
229
|
+
: input.action === 'block_duplicate_publish'
|
|
230
|
+
? 'Hotfix Or Force Publish'
|
|
231
|
+
: 'Hotfix Release Artifact',
|
|
232
|
+
recommendedChannel: input.action === 'block_duplicate_publish'
|
|
233
|
+
? 'release_artifact'
|
|
234
|
+
: input.releaseBlocked ? 'release_artifact' : 'static_ui',
|
|
235
|
+
reason: input.reason,
|
|
236
|
+
fullDeployAvoided: true,
|
|
237
|
+
steps: [
|
|
238
|
+
hotfixStep('static_ui_hotfix', 'Static UI hotfix', 'static_ui', {
|
|
239
|
+
safeToAutoRun: true,
|
|
240
|
+
requiredEvidence: ['built dist path', 'target S3 bucket and CloudFront distribution', 'changed frontend bundle or asset list'],
|
|
241
|
+
successEvidence: ['S3 upload result', 'CloudFront invalidation id', 'public bundle contains expected hotfix marker']
|
|
242
|
+
}),
|
|
243
|
+
hotfixStep('backend_js_hotfix', 'Backend JS hotfix', 'backend_js', {
|
|
244
|
+
requiredEvidence: ['compiled JS artifact path', 'target backend host', 'diff limited to runner/operator code'],
|
|
245
|
+
successEvidence: ['remote file checksum', 'service restart or process reload evidence', 'self-test passes']
|
|
246
|
+
}),
|
|
247
|
+
hotfixStep('config_seed_cache_restart', 'Config, seed, cache, or restart repair', 'config', {
|
|
248
|
+
safeToAutoRun: true,
|
|
249
|
+
requiredEvidence: ['exact config/seed/cache key or process name', 'why no product artifact changed'],
|
|
250
|
+
successEvidence: ['release gate rerun result', 'operator console release snapshot refreshed']
|
|
251
|
+
})
|
|
252
|
+
],
|
|
253
|
+
acceptanceEvidence: commonAcceptance,
|
|
254
|
+
escalationTriggers: [
|
|
255
|
+
'hotfix changes customer-facing product code outside the release artifact',
|
|
256
|
+
'same release gate fails twice after hotfix evidence',
|
|
257
|
+
'same publish fingerprint is retried without force_publish evidence',
|
|
258
|
+
'force deploy is requested without a reason'
|
|
259
|
+
]
|
|
260
|
+
};
|
|
261
|
+
}
|
|
262
|
+
function buildResolveIOAIManagerHotfixFirstReleasePolicy(input) {
|
|
263
|
+
if (input === void 0) { input = {}; }
|
|
264
|
+
var surface = cleanText(input.surface || 'runner', 120);
|
|
265
|
+
var deployStatus = cleanText(input.deployStatus, 160);
|
|
266
|
+
var publishStatus = cleanText(input.publishStatus, 160);
|
|
267
|
+
var sampleDataStatus = cleanText(input.sampleDataStatus, 160);
|
|
268
|
+
var deployFingerprint = cleanText(input.deployFingerprint, 240);
|
|
269
|
+
var lastDeployFingerprint = cleanText(input.lastDeployFingerprint, 240);
|
|
270
|
+
var publishFingerprint = cleanText(input.publishFingerprint, 240);
|
|
271
|
+
var lastPublishFingerprint = cleanText(input.lastPublishFingerprint, 240);
|
|
272
|
+
var fingerprintMatchesLast = !!deployFingerprint && !!lastDeployFingerprint && deployFingerprint === lastDeployFingerprint;
|
|
273
|
+
var publishFingerprintMatchesLast = !!publishFingerprint && !!lastPublishFingerprint && publishFingerprint === lastPublishFingerprint;
|
|
274
|
+
var releaseBlocked = [deployStatus, publishStatus, sampleDataStatus].some(releaseStatusIsBlocked);
|
|
275
|
+
var duplicateDeployBlocked = fingerprintMatchesLast
|
|
276
|
+
&& input.forceDeploy !== true
|
|
277
|
+
&& releaseStatusIsTerminalDeploy([deployStatus, publishStatus].filter(Boolean).join(' '));
|
|
278
|
+
var duplicatePublishBlocked = publishFingerprintMatchesLast
|
|
279
|
+
&& input.forcePublish !== true
|
|
280
|
+
&& releaseStatusIsBlocked(publishStatus)
|
|
281
|
+
&& releaseStatusIsTerminalDeploy(publishStatus);
|
|
282
|
+
var recommendedAction = 'hotfix_release_artifact';
|
|
283
|
+
var label = 'Hotfix Release Artifact';
|
|
284
|
+
var reason = 'Repair the live runner/operator code, release config, domain, seed-data, or release artifact and rerun only the failed release gate.';
|
|
285
|
+
var fullDeployAllowed = false;
|
|
286
|
+
if (input.activeDeploy === true) {
|
|
287
|
+
recommendedAction = 'wait_for_active_deploy';
|
|
288
|
+
label = 'Wait For Active Deploy';
|
|
289
|
+
reason = 'A deploy is already queued or running; collect that result before spending another deploy cycle.';
|
|
290
|
+
}
|
|
291
|
+
else if (duplicateDeployBlocked) {
|
|
292
|
+
recommendedAction = 'block_duplicate_deploy';
|
|
293
|
+
label = 'Block Duplicate Deploy';
|
|
294
|
+
reason = 'The same artifact fingerprint already has release status; hotfix or provide explicit force_deploy evidence before rerunning it.';
|
|
295
|
+
}
|
|
296
|
+
else if (duplicatePublishBlocked) {
|
|
297
|
+
recommendedAction = 'block_duplicate_publish';
|
|
298
|
+
label = 'Block Duplicate Publish';
|
|
299
|
+
reason = 'The same publish fingerprint already has release status; hotfix the release artifact or provide explicit force_publish evidence before rerunning publish.';
|
|
300
|
+
}
|
|
301
|
+
else if ((fingerprintMatchesLast && input.forceDeploy === true) || (publishFingerprintMatchesLast && input.forcePublish === true)) {
|
|
302
|
+
recommendedAction = 'review_force_deploy';
|
|
303
|
+
label = 'Review Force Deploy';
|
|
304
|
+
reason = input.forcePublish === true
|
|
305
|
+
? 'force_publish was explicitly requested for a repeated publish artifact; require a reason and rerun only the failed release gate.'
|
|
306
|
+
: 'force_deploy was explicitly requested for a repeated artifact; require a reason and rerun only the failed release gate.';
|
|
307
|
+
fullDeployAllowed = true;
|
|
308
|
+
}
|
|
309
|
+
else if (input.hasNewArtifact === false && !releaseBlocked) {
|
|
310
|
+
recommendedAction = 'build_artifact_first';
|
|
311
|
+
label = 'Build Artifact First';
|
|
312
|
+
reason = 'No release artifact fingerprint is available yet; build once, record the fingerprint, and avoid repeated deploys.';
|
|
313
|
+
}
|
|
314
|
+
else if (input.hasNewArtifact === true && !releaseBlocked) {
|
|
315
|
+
recommendedAction = 'deploy_new_artifact_after_release_gate';
|
|
316
|
+
label = 'Deploy New Artifact After Release Gate';
|
|
317
|
+
reason = 'A new artifact can be deployed after the release gate proves the artifact is new and ready.';
|
|
318
|
+
fullDeployAllowed = true;
|
|
319
|
+
}
|
|
320
|
+
var allowedActions = buildReleaseAllowedActions(recommendedAction);
|
|
321
|
+
var hotfixPlan = buildHotfixFirstReleasePlan({
|
|
322
|
+
action: recommendedAction,
|
|
323
|
+
surface: surface,
|
|
324
|
+
reason: reason,
|
|
325
|
+
releaseBlocked: releaseBlocked
|
|
326
|
+
});
|
|
327
|
+
return {
|
|
328
|
+
policy: 'hotfix_first',
|
|
329
|
+
surface: surface,
|
|
330
|
+
recommendedAction: recommendedAction,
|
|
331
|
+
label: label,
|
|
332
|
+
reason: reason,
|
|
333
|
+
hotfixPreferred: recommendedAction !== 'deploy_new_artifact_after_release_gate' && recommendedAction !== 'review_force_deploy',
|
|
334
|
+
fullDeployAllowed: fullDeployAllowed,
|
|
335
|
+
duplicateDeployBlocked: duplicateDeployBlocked,
|
|
336
|
+
duplicatePublishBlocked: duplicatePublishBlocked,
|
|
337
|
+
forceDeployRequiredToRepeat: true,
|
|
338
|
+
forcePublishRequiredToRepeat: true,
|
|
339
|
+
statuses: {
|
|
340
|
+
deploy: deployStatus,
|
|
341
|
+
publish: publishStatus,
|
|
342
|
+
sampleData: sampleDataStatus
|
|
343
|
+
},
|
|
344
|
+
fingerprints: {
|
|
345
|
+
current: deployFingerprint,
|
|
346
|
+
last: lastDeployFingerprint,
|
|
347
|
+
matchesLast: fingerprintMatchesLast,
|
|
348
|
+
publishCurrent: publishFingerprint,
|
|
349
|
+
publishLast: lastPublishFingerprint,
|
|
350
|
+
publishMatchesLast: publishFingerprintMatchesLast
|
|
351
|
+
},
|
|
352
|
+
hotfixPlan: hotfixPlan,
|
|
353
|
+
allowedActions: allowedActions,
|
|
354
|
+
forbiddenActions: [
|
|
355
|
+
'rerun full builder loop for a release-only blocker',
|
|
356
|
+
'queue duplicate deploy without force_deploy evidence',
|
|
357
|
+
'queue duplicate publish without force_publish evidence',
|
|
358
|
+
'publish/deploy again before reading the failed release log',
|
|
359
|
+
'change core workflow after business proof passed unless release evidence proves it is required'
|
|
360
|
+
],
|
|
361
|
+
requiredEvidence: [
|
|
362
|
+
'failed release gate log or active deploy result',
|
|
363
|
+
'deploy artifact fingerprint comparison',
|
|
364
|
+
'publish artifact fingerprint comparison when publish is the failed gate',
|
|
365
|
+
'hotfix/config/seed/domain change evidence when no new product artifact is needed',
|
|
366
|
+
'force_deploy or force_publish reason when repeating the same fingerprint'
|
|
367
|
+
]
|
|
368
|
+
};
|
|
369
|
+
}
|
|
370
|
+
function isResolveIOAIManagerSafeAutoDispatch(input) {
|
|
371
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j;
|
|
372
|
+
var normalizedInput = typeof input === 'string'
|
|
373
|
+
? { dispatchAction: input }
|
|
374
|
+
: (input || {});
|
|
375
|
+
var dispatchAction = cleanText(normalizedInput.dispatchAction || ((_a = normalizedInput.directive) === null || _a === void 0 ? void 0 : _a.dispatchAction), 120);
|
|
376
|
+
var directiveAllowed = (_b = normalizedInput.directive) === null || _b === void 0 ? void 0 : _b.allowed;
|
|
377
|
+
var actionAutoRunnable = (_c = normalizedInput.action) === null || _c === void 0 ? void 0 : _c.autoRunnable;
|
|
378
|
+
var productRepairAllowed = ((_d = normalizedInput.directive) === null || _d === void 0 ? void 0 : _d.canRunProductRepair) === true
|
|
379
|
+
|| ((_e = normalizedInput.directive) === null || _e === void 0 ? void 0 : _e.productRepairAllowed) === true
|
|
380
|
+
|| ((_f = normalizedInput.action) === null || _f === void 0 ? void 0 : _f.productRepairAllowed) === true;
|
|
381
|
+
var expensiveModelAllowed = ((_g = normalizedInput.directive) === null || _g === void 0 ? void 0 : _g.canRunExpensiveModel) === true
|
|
382
|
+
|| ((_h = normalizedInput.directive) === null || _h === void 0 ? void 0 : _h.expensiveModelAllowed) === true
|
|
383
|
+
|| ((_j = normalizedInput.action) === null || _j === void 0 ? void 0 : _j.expensiveModelAllowed) === true;
|
|
384
|
+
if (!dispatchAction || dispatchAction === 'park_manual') {
|
|
385
|
+
return false;
|
|
386
|
+
}
|
|
387
|
+
if (directiveAllowed === false || actionAutoRunnable === false) {
|
|
388
|
+
return false;
|
|
389
|
+
}
|
|
390
|
+
if ([
|
|
391
|
+
'run_evidence_probe',
|
|
392
|
+
'run_read_only_diagnosis',
|
|
393
|
+
'run_infra_repair',
|
|
394
|
+
'run_compile_repair'
|
|
395
|
+
].includes(dispatchAction)) {
|
|
396
|
+
return true;
|
|
397
|
+
}
|
|
398
|
+
if (dispatchAction === 'run_release_repair') {
|
|
399
|
+
return normalizedInput.includeReleaseRepair !== false;
|
|
400
|
+
}
|
|
401
|
+
if (dispatchAction === 'run_journey_contract_repair') {
|
|
402
|
+
return normalizedInput.includeJourneyContractRepair !== false && productRepairAllowed !== true;
|
|
403
|
+
}
|
|
404
|
+
if (dispatchAction === 'run_business_assertion_repair') {
|
|
405
|
+
return normalizedInput.includeBusinessProofRepair === true
|
|
406
|
+
&& productRepairAllowed !== true
|
|
407
|
+
&& expensiveModelAllowed !== true;
|
|
408
|
+
}
|
|
409
|
+
if (dispatchAction === 'run_targeted_product_repair') {
|
|
410
|
+
return normalizedInput.includeProductRepair === true
|
|
411
|
+
&& productRepairAllowed === true
|
|
412
|
+
&& expensiveModelAllowed !== true;
|
|
413
|
+
}
|
|
414
|
+
return dispatchAction === 'advance' || dispatchAction === 'continue_gate';
|
|
415
|
+
}
|
|
95
416
|
function isoNow(value) {
|
|
96
417
|
if (value instanceof Date) {
|
|
97
418
|
return value.toISOString();
|
|
@@ -399,13 +720,23 @@ function buildResolveIOAIManagerRecoveryActionPacket(input) {
|
|
|
399
720
|
|| checkpoint.status === 'parked'
|
|
400
721
|
|| checkpoint.attempts >= checkpoint.maxAttemptsBeforePark;
|
|
401
722
|
var stopWhen = Array.from(new Set(__spreadArray(__spreadArray([], __read(probe.stopConditions), false), __read((requireNewEvidence ? ['same blocker fingerprint and same evidence hash after probe'] : [])), false).map(function (entry) { return cleanText(entry, 500); }).filter(Boolean))).slice(0, 30);
|
|
402
|
-
var resetLoopWhen = Array.from(new Set(__spreadArray(__spreadArray(__spreadArray([], __read(checkpoint.loopResetEvidence), false), __read(probe.loopResetEvidence), false), __read((requireNewEvidence ? [
|
|
723
|
+
var resetLoopWhen = Array.from(new Set(__spreadArray(__spreadArray(__spreadArray([], __read(checkpoint.loopResetEvidence), false), __read(probe.loopResetEvidence), false), __read((requireNewEvidence ? [
|
|
724
|
+
'new material evidence: changed blocker, validated diagnosis/journey, business proof, compile/infra/release proof, or new actionable trace',
|
|
725
|
+
'weak hash-only evidence does not reset the loop'
|
|
726
|
+
] : [])), false).map(function (entry) { return cleanText(entry, 500); }).filter(Boolean))).slice(0, 30);
|
|
403
727
|
var nextCommands = probe.steps
|
|
404
728
|
.map(function (step) { return cleanText(step.commandHint || "".concat(step.kind, ":").concat(step.id), 500); })
|
|
405
729
|
.filter(Boolean)
|
|
406
730
|
.slice(0, 12);
|
|
731
|
+
var releasePolicy = mode === 'repair_release'
|
|
732
|
+
? buildResolveIOAIManagerHotfixFirstReleasePolicy({
|
|
733
|
+
surface: 'manager_recovery',
|
|
734
|
+
deployStatus: checkpoint.stepType,
|
|
735
|
+
publishStatus: checkpoint.lane
|
|
736
|
+
})
|
|
737
|
+
: undefined;
|
|
407
738
|
var now = isoNow(input.now);
|
|
408
|
-
return __assign(__assign({ actionId: stableHash('mgr-action', {
|
|
739
|
+
return __assign(__assign(__assign({ actionId: stableHash('mgr-action', {
|
|
409
740
|
checkpointId: checkpoint.checkpointId,
|
|
410
741
|
probeId: probe.probeId,
|
|
411
742
|
mode: mode,
|
|
@@ -413,12 +744,16 @@ function buildResolveIOAIManagerRecoveryActionPacket(input) {
|
|
|
413
744
|
blockerFingerprint: checkpoint.blockerFingerprint
|
|
414
745
|
}), checkpointId: checkpoint.checkpointId, probeId: probe.probeId, recoveryClass: checkpoint.recoveryClass, mode: mode, label: recoveryActionLabelFor(mode, checkpoint), lane: checkpoint.lane, stepType: checkpoint.stepType, primaryStepKind: (primaryStep === null || primaryStep === void 0 ? void 0 : primaryStep.kind) || 'none', objective: mode === 'collect_evidence'
|
|
415
746
|
? probe.objective
|
|
416
|
-
: cleanText(checkpoint.objective || probe.objective, 1000), evidenceOnly: evidenceOnly, autoRunnable: recoveryActionAutoRunnable(mode, probe), productRepairAllowed: checkpoint.productRepairAllowed && !evidenceOnly && checkpoint.status !== 'parked', expensiveModelAllowed: checkpoint.expensiveModelAllowed && checkpoint.status !== 'parked', canResetLoopAfterEvidence: resetLoopWhen.length > 0, maxAttemptsBeforePark: checkpoint.maxAttemptsBeforePark, requiredArtifacts: probe.requiredArtifacts.slice(0, 20), nextCommands:
|
|
747
|
+
: cleanText(checkpoint.objective || probe.objective, 1000), evidenceOnly: evidenceOnly, autoRunnable: recoveryActionAutoRunnable(mode, probe), productRepairAllowed: checkpoint.productRepairAllowed && !evidenceOnly && checkpoint.status !== 'parked', expensiveModelAllowed: checkpoint.expensiveModelAllowed && checkpoint.status !== 'parked', canResetLoopAfterEvidence: resetLoopWhen.length > 0, maxAttemptsBeforePark: checkpoint.maxAttemptsBeforePark, requiredArtifacts: probe.requiredArtifacts.slice(0, 20), nextCommands: releasePolicy
|
|
748
|
+
? Array.from(new Set(__spreadArray(__spreadArray([], __read(nextCommands), false), __read(releasePolicy.allowedActions), false))).slice(0, 12)
|
|
749
|
+
: nextCommands, successCriteria: releasePolicy
|
|
750
|
+
? Array.from(new Set(__spreadArray(__spreadArray([], __read(probe.acceptanceEvidence), false), __read(releasePolicy.requiredEvidence), false))).slice(0, 20)
|
|
751
|
+
: probe.acceptanceEvidence.slice(0, 20), retryPolicy: {
|
|
417
752
|
allowImmediateRetry: checkpoint.status !== 'parked' && mode !== 'manual_review',
|
|
418
753
|
requireNewEvidence: requireNewEvidence,
|
|
419
754
|
resetLoopWhen: resetLoopWhen,
|
|
420
755
|
stopWhen: stopWhen
|
|
421
|
-
} }, (mode === 'collect_evidence' ? { blockedReason: 'Manager parked this loop until the recovery action records new evidence.' } : {})), { createdAt: now });
|
|
756
|
+
} }, (releasePolicy ? { releasePolicy: releasePolicy } : {})), (mode === 'collect_evidence' ? { blockedReason: 'Manager parked this loop until the recovery action records new evidence.' } : {})), { createdAt: now });
|
|
422
757
|
}
|
|
423
758
|
function dispatchActionForMode(mode) {
|
|
424
759
|
var map = {
|
|
@@ -592,7 +927,7 @@ function recoveryDirectiveReason(action, decision, current) {
|
|
|
592
927
|
].filter(Boolean).join(' | ');
|
|
593
928
|
}
|
|
594
929
|
function buildResolveIOAIManagerRecoveryExecutionDirective(input) {
|
|
595
|
-
var _a, _b, _c, _d;
|
|
930
|
+
var _a, _b, _c, _d, _e;
|
|
596
931
|
var action = input.action;
|
|
597
932
|
var dispatchDecision = input.dispatchDecision || decideResolveIOAIManagerRecoveryActionDispatch({
|
|
598
933
|
action: action,
|
|
@@ -606,7 +941,7 @@ function buildResolveIOAIManagerRecoveryExecutionDirective(input) {
|
|
|
606
941
|
var stepType = cleanText((action === null || action === void 0 ? void 0 : action.stepType) || ((_b = input.current) === null || _b === void 0 ? void 0 : _b.stepType) || '', 120);
|
|
607
942
|
var rerunReason = recoveryDirectiveReason(action, dispatchDecision, input.current);
|
|
608
943
|
var surface = cleanText(input.surface || 'runner', 120);
|
|
609
|
-
return __assign(__assign({ directiveId: stableHash('mgr-directive', {
|
|
944
|
+
return __assign(__assign(__assign({ directiveId: stableHash('mgr-directive', {
|
|
610
945
|
surface: surface,
|
|
611
946
|
actionId: (action === null || action === void 0 ? void 0 : action.actionId) || '',
|
|
612
947
|
dispatchAction: dispatchAction,
|
|
@@ -614,14 +949,100 @@ function buildResolveIOAIManagerRecoveryExecutionDirective(input) {
|
|
|
614
949
|
evidenceHash: ((_c = dispatchDecision.dispatchRecord) === null || _c === void 0 ? void 0 : _c.evidenceHash) || ((_d = input.current) === null || _d === void 0 ? void 0 : _d.evidenceHash) || ''
|
|
615
950
|
}), surface: surface, dispatchAction: dispatchAction, phase: phase, allowed: dispatchDecision.allowed, status: dispatchDecision.status, reason: dispatchDecision.reason, lane: lane, stepType: stepType, nextActionLabel: cleanText(action === null || action === void 0 ? void 0 : action.label, 160) || dispatchAction, rerunReason: rerunReason, evidenceOnly: (action === null || action === void 0 ? void 0 : action.evidenceOnly) !== false || dispatchAction === 'run_evidence_probe', autoRunnable: (action === null || action === void 0 ? void 0 : action.autoRunnable) === true, productRepairAllowed: (action === null || action === void 0 ? void 0 : action.productRepairAllowed) === true, expensiveModelAllowed: (action === null || action === void 0 ? void 0 : action.expensiveModelAllowed) === true, canRunProductRepair: dispatchDecision.canRunProductRepair, canRunExpensiveModel: dispatchDecision.canRunExpensiveModel, canResetLoopAfterEvidence: (action === null || action === void 0 ? void 0 : action.canResetLoopAfterEvidence) === true, requiresNewEvidence: dispatchDecision.requiresNewEvidence, newEvidence: dispatchDecision.newEvidence, maxAttemptsBeforePark: Math.max(1, Number((action === null || action === void 0 ? void 0 : action.maxAttemptsBeforePark) || 1) || 1), requiredArtifacts: cleanList(action === null || action === void 0 ? void 0 : action.requiredArtifacts, 20, 500), nextCommands: cleanList(action === null || action === void 0 ? void 0 : action.nextCommands, 20, 500), successCriteria: cleanList(action === null || action === void 0 ? void 0 : action.successCriteria, 20, 500), forbiddenActions: (action === null || action === void 0 ? void 0 : action.productRepairAllowed) === true
|
|
616
951
|
? []
|
|
617
|
-
:
|
|
952
|
+
: Array.from(new Set(__spreadArray([
|
|
953
|
+
'Do not run product-code repair from this directive unless canRunProductRepair is true.'
|
|
954
|
+
], __read((((_e = action === null || action === void 0 ? void 0 : action.releasePolicy) === null || _e === void 0 ? void 0 : _e.forbiddenActions) || [])), false))).slice(0, 20) }, (dispatchDecision.dispatchRecord ? { dispatchRecord: dispatchDecision.dispatchRecord } : {})), ((action === null || action === void 0 ? void 0 : action.releasePolicy) ? { releasePolicy: action.releasePolicy } : {})), { createdAt: now });
|
|
618
955
|
}
|
|
619
|
-
function
|
|
956
|
+
function newListEntries(current, previous) {
|
|
620
957
|
var existing = new Set(previous.map(function (entry) { return cleanText(entry, 500); }).filter(Boolean));
|
|
621
|
-
return current
|
|
622
|
-
|
|
623
|
-
return
|
|
624
|
-
|
|
958
|
+
return current
|
|
959
|
+
.map(function (entry) { return cleanText(entry, 500); })
|
|
960
|
+
.filter(function (entry) { return entry && !existing.has(entry); });
|
|
961
|
+
}
|
|
962
|
+
function recordLane(value) {
|
|
963
|
+
return cleanText(value === null || value === void 0 ? void 0 : value.lane, 80);
|
|
964
|
+
}
|
|
965
|
+
function recordStepType(value) {
|
|
966
|
+
return cleanText(value === null || value === void 0 ? void 0 : value.stepType, 80);
|
|
967
|
+
}
|
|
968
|
+
function recordFailureClass(value) {
|
|
969
|
+
var valueText = cleanText(value === null || value === void 0 ? void 0 : value.failureClass, 80);
|
|
970
|
+
return valueText ? normalizeResolveIOAIManagerFailureClass(valueText) : '';
|
|
971
|
+
}
|
|
972
|
+
function materialEvidenceText(record, paths) {
|
|
973
|
+
if (paths === void 0) { paths = []; }
|
|
974
|
+
return __spreadArray([
|
|
975
|
+
cleanText(record === null || record === void 0 ? void 0 : record.blocker, 1200),
|
|
976
|
+
cleanText(record === null || record === void 0 ? void 0 : record.summary, 1200)
|
|
977
|
+
], __read(paths.map(function (path) { return cleanText(path, 500); })), false).filter(Boolean).join(' ').toLowerCase();
|
|
978
|
+
}
|
|
979
|
+
function hasMaterialEvidenceLanguage(text) {
|
|
980
|
+
return /(business|assertion|proof|before|after|dom|trace|stack|network|mongo|query|diff|scope|diagnosis|journey|contract|workflow|compile|build|preflight|infra|chrome|puppeteer|release|publish|deploy|sample|seed|route|auth|hydration|performance|slow|owner|root.?cause|repro|pdf|export|upload|import|filter|invoice|saved|calculated|comparison|report)/i.test(text);
|
|
981
|
+
}
|
|
982
|
+
function assessResolveIOAIManagerEvidenceChange(previous, current, fallbackObjective) {
|
|
983
|
+
var currentRecord = current || {};
|
|
984
|
+
var previousRecord = previous;
|
|
985
|
+
var previousEvidenceHash = previousRecord ? cleanText(previousRecord.evidenceHash, 160) || hashResolveIOAIManagerEvidence(previousRecord) : '';
|
|
986
|
+
var currentEvidenceHash = hashResolveIOAIManagerEvidence(currentRecord);
|
|
987
|
+
var previousBlockerFingerprint = previousRecord
|
|
988
|
+
? cleanText(previousRecord.blockerFingerprint, 160) || resolveResolveIOAIManagerBlockerFingerprint(previousRecord, fallbackObjective)
|
|
989
|
+
: '';
|
|
990
|
+
var currentBlockerFingerprint = resolveResolveIOAIManagerBlockerFingerprint(currentRecord, fallbackObjective);
|
|
991
|
+
var previousChangedFiles = cleanList(previousRecord === null || previousRecord === void 0 ? void 0 : previousRecord.changedFiles, 80, 500);
|
|
992
|
+
var currentChangedFiles = cleanList(currentRecord.changedFiles, 80, 500);
|
|
993
|
+
var previousArtifactPaths = cleanList(previousRecord === null || previousRecord === void 0 ? void 0 : previousRecord.artifactPaths, 80, 500);
|
|
994
|
+
var currentArtifactPaths = cleanList(currentRecord.artifactPaths, 80, 500);
|
|
995
|
+
var addedChangedFiles = newListEntries(currentChangedFiles, previousChangedFiles);
|
|
996
|
+
var addedArtifactPaths = newListEntries(currentArtifactPaths, previousArtifactPaths);
|
|
997
|
+
var signals = [];
|
|
998
|
+
if (previousEvidenceHash && currentEvidenceHash !== previousEvidenceHash) {
|
|
999
|
+
signals.push('evidence_hash_changed');
|
|
1000
|
+
}
|
|
1001
|
+
if (previousBlockerFingerprint && currentBlockerFingerprint !== previousBlockerFingerprint) {
|
|
1002
|
+
signals.push('blocker_fingerprint_changed');
|
|
1003
|
+
}
|
|
1004
|
+
if (recordLane(previousRecord) && recordLane(previousRecord) !== recordLane(currentRecord)) {
|
|
1005
|
+
signals.push('lane_changed');
|
|
1006
|
+
}
|
|
1007
|
+
if (recordStepType(previousRecord) && recordStepType(previousRecord) !== recordStepType(currentRecord)) {
|
|
1008
|
+
signals.push('step_type_changed');
|
|
1009
|
+
}
|
|
1010
|
+
if (recordFailureClass(previousRecord) && recordFailureClass(previousRecord) !== recordFailureClass(currentRecord)) {
|
|
1011
|
+
signals.push('failure_class_changed');
|
|
1012
|
+
}
|
|
1013
|
+
if (addedChangedFiles.length) {
|
|
1014
|
+
signals.push('changed_files_added');
|
|
1015
|
+
}
|
|
1016
|
+
if (addedArtifactPaths.length) {
|
|
1017
|
+
signals.push('artifact_paths_added');
|
|
1018
|
+
}
|
|
1019
|
+
if (isPassingOutcome(currentRecord)) {
|
|
1020
|
+
signals.push('passing_outcome');
|
|
1021
|
+
}
|
|
1022
|
+
var changed = signals.length > 0;
|
|
1023
|
+
var evidenceText = materialEvidenceText(currentRecord, addedArtifactPaths);
|
|
1024
|
+
var pathOrSummaryHasMaterialSignal = hasMaterialEvidenceLanguage(evidenceText);
|
|
1025
|
+
var proof = signals.includes('passing_outcome');
|
|
1026
|
+
var structuralChange = signals.some(function (signal) { return /blocker_fingerprint_changed|lane_changed|step_type_changed|failure_class_changed/.test(signal); });
|
|
1027
|
+
var materialArtifact = addedArtifactPaths.length > 0 && pathOrSummaryHasMaterialSignal;
|
|
1028
|
+
var materialChangedFiles = addedChangedFiles.length > 0
|
|
1029
|
+
&& /diagnosis|owner|scope|diff|root.?cause|failing path|stack|trace|business|proof|compile|release|deploy|workflow|journey/i.test(evidenceText);
|
|
1030
|
+
var material = proof || structuralChange || materialArtifact || materialChangedFiles;
|
|
1031
|
+
var strength = proof
|
|
1032
|
+
? 'proof'
|
|
1033
|
+
: material
|
|
1034
|
+
? 'material'
|
|
1035
|
+
: changed
|
|
1036
|
+
? 'weak'
|
|
1037
|
+
: 'none';
|
|
1038
|
+
return {
|
|
1039
|
+
changed: changed,
|
|
1040
|
+
material: material,
|
|
1041
|
+
strength: strength,
|
|
1042
|
+
signals: signals,
|
|
1043
|
+
evidenceHash: currentEvidenceHash,
|
|
1044
|
+
blockerFingerprint: currentBlockerFingerprint
|
|
1045
|
+
};
|
|
625
1046
|
}
|
|
626
1047
|
function proposedActionIsProductRepair(value) {
|
|
627
1048
|
var normalized = cleanText(value, 120);
|
|
@@ -632,16 +1053,21 @@ function decideResolveIOAIManagerRecoveryGate(input) {
|
|
|
632
1053
|
var checkpoint = input.checkpoint;
|
|
633
1054
|
var hasCurrent = !!input.current;
|
|
634
1055
|
var current = input.current || {};
|
|
635
|
-
var
|
|
636
|
-
?
|
|
637
|
-
:
|
|
638
|
-
|
|
1056
|
+
var assessment = hasCurrent
|
|
1057
|
+
? assessResolveIOAIManagerEvidenceChange(checkpoint, current, checkpoint.objective)
|
|
1058
|
+
: {
|
|
1059
|
+
changed: false,
|
|
1060
|
+
material: false,
|
|
1061
|
+
strength: 'none',
|
|
1062
|
+
signals: [],
|
|
1063
|
+
evidenceHash: checkpoint.evidenceHash,
|
|
1064
|
+
blockerFingerprint: checkpoint.blockerFingerprint
|
|
1065
|
+
};
|
|
1066
|
+
var blockerFingerprint = assessment.blockerFingerprint;
|
|
1067
|
+
var evidenceHash = assessment.evidenceHash;
|
|
639
1068
|
var changedFiles = hasCurrent ? cleanList(current.changedFiles, 80, 500) : checkpoint.changedFiles;
|
|
640
1069
|
var artifactPaths = hasCurrent ? cleanList(current.artifactPaths, 80, 500) : checkpoint.artifactPaths;
|
|
641
|
-
var evidenceChanged =
|
|
642
|
-
|| blockerFingerprint !== checkpoint.blockerFingerprint
|
|
643
|
-
|| listHasNewEntry(changedFiles, checkpoint.changedFiles)
|
|
644
|
-
|| listHasNewEntry(artifactPaths, checkpoint.artifactPaths);
|
|
1070
|
+
var evidenceChanged = assessment.changed;
|
|
645
1071
|
var proposedAction = cleanText(input.proposedAction || checkpoint.allowedAction, 120);
|
|
646
1072
|
var productRepairRequested = proposedActionIsProductRepair(proposedAction);
|
|
647
1073
|
var missingEvidence = checkpoint.requiredEvidence.filter(function (required) {
|
|
@@ -659,7 +1085,7 @@ function decideResolveIOAIManagerRecoveryGate(input) {
|
|
|
659
1085
|
});
|
|
660
1086
|
var makeDecision = function (action, reason, overrides) {
|
|
661
1087
|
if (overrides === void 0) { overrides = {}; }
|
|
662
|
-
return (__assign({ action: action, reason: reason, canRunProductRepair: checkpoint.productRepairAllowed, canRunExpensiveModel: checkpoint.expensiveModelAllowed, shouldResetLoopBudget: false, shouldIncrementAttempt: action === 'allow', newEvidence: evidenceChanged, blockerFingerprint: blockerFingerprint, evidenceHash: evidenceHash, missingEvidence: missingEvidence, checkpoint: __assign(__assign({}, checkpoint), { updatedAt: isoNow(input.now) }) }, overrides));
|
|
1088
|
+
return (__assign({ action: action, reason: reason, canRunProductRepair: checkpoint.productRepairAllowed, canRunExpensiveModel: checkpoint.expensiveModelAllowed, shouldResetLoopBudget: false, shouldIncrementAttempt: action === 'allow', newEvidence: evidenceChanged, materialEvidence: assessment.material, evidenceStrength: assessment.strength, evidenceSignals: assessment.signals, blockerFingerprint: blockerFingerprint, evidenceHash: evidenceHash, missingEvidence: missingEvidence, checkpoint: __assign(__assign({}, checkpoint), { updatedAt: isoNow(input.now) }) }, overrides));
|
|
663
1089
|
};
|
|
664
1090
|
if (checkpoint.status === 'complete') {
|
|
665
1091
|
return makeDecision('complete', 'recovery_gate_checkpoint_already_complete', {
|
|
@@ -689,6 +1115,13 @@ function decideResolveIOAIManagerRecoveryGate(input) {
|
|
|
689
1115
|
shouldIncrementAttempt: false
|
|
690
1116
|
});
|
|
691
1117
|
}
|
|
1118
|
+
if (checkpoint.status === 'parked' && evidenceChanged && !assessment.material) {
|
|
1119
|
+
return makeDecision('collect_new_evidence', 'recovery_gate_weak_evidence_requires_material_signal', {
|
|
1120
|
+
canRunProductRepair: false,
|
|
1121
|
+
canRunExpensiveModel: false,
|
|
1122
|
+
shouldIncrementAttempt: false
|
|
1123
|
+
});
|
|
1124
|
+
}
|
|
692
1125
|
if (checkpoint.attempts >= checkpoint.maxAttemptsBeforePark && !evidenceChanged) {
|
|
693
1126
|
return makeDecision('collect_new_evidence', 'recovery_gate_attempt_limit_requires_new_evidence', {
|
|
694
1127
|
canRunProductRepair: false,
|
|
@@ -696,11 +1129,18 @@ function decideResolveIOAIManagerRecoveryGate(input) {
|
|
|
696
1129
|
shouldIncrementAttempt: false
|
|
697
1130
|
});
|
|
698
1131
|
}
|
|
1132
|
+
if (checkpoint.attempts >= checkpoint.maxAttemptsBeforePark && evidenceChanged && !assessment.material) {
|
|
1133
|
+
return makeDecision('collect_new_evidence', 'recovery_gate_attempt_limit_requires_material_evidence', {
|
|
1134
|
+
canRunProductRepair: false,
|
|
1135
|
+
canRunExpensiveModel: false,
|
|
1136
|
+
shouldIncrementAttempt: false
|
|
1137
|
+
});
|
|
1138
|
+
}
|
|
699
1139
|
if (evidenceChanged) {
|
|
700
1140
|
var currentFailureClass = normalizeResolveIOAIManagerFailureClass(current.failureClass);
|
|
701
1141
|
var currentCanRunProductRepair = checkpoint.productRepairAllowed
|
|
702
1142
|
|| !/^(infra|compile|diagnosis|release)$/i.test(currentFailureClass);
|
|
703
|
-
return makeDecision('allow', '
|
|
1143
|
+
return makeDecision('allow', 'recovery_gate_new_material_evidence_unblocks_retry', {
|
|
704
1144
|
canRunProductRepair: currentCanRunProductRepair,
|
|
705
1145
|
canRunExpensiveModel: checkpoint.expensiveModelAllowed || currentCanRunProductRepair,
|
|
706
1146
|
shouldResetLoopBudget: true
|
|
@@ -812,8 +1252,8 @@ function buildResolveIOAIManagerRecoveryPlan(input) {
|
|
|
812
1252
|
'Do not rerun the same prompt or same repair.',
|
|
813
1253
|
'Show the repeated blocker and evidence hash.',
|
|
814
1254
|
'Collect a new artifact: failing DOM state, stack trace, network response, Mongo delta, compile log, or revised diagnosis.',
|
|
815
|
-
'Reset the loop only after the
|
|
816
|
-
], ['same failure count', 'blocker fingerprint', 'evidence hash'], ['changed
|
|
1255
|
+
'Reset the loop only after material evidence changes the blocker, proof, diagnosis, journey, or actionable trace.'
|
|
1256
|
+
], ['same failure count', 'blocker fingerprint', 'evidence hash'], ['changed blocker fingerprint', 'business/compile/infra/release proof artifact', 'revised diagnosis or journey contract', 'new actionable trace or data delta'], ['alternate between two failed patches', 'increase loop budget without evidence', 'hide the park reason']);
|
|
817
1257
|
}
|
|
818
1258
|
if (failureClass === 'journey') {
|
|
819
1259
|
return makePlan('journey_contract_repair', 'Repair Journey Contract', 'Fix the first/next/last workflow contract before app code work continues.', 'journey_contract_repair', false, true, [
|
|
@@ -824,12 +1264,12 @@ function buildResolveIOAIManagerRecoveryPlan(input) {
|
|
|
824
1264
|
], ['validated journey_contract JSON', 'CTA-to-action mapping', 'workflow QA assertions'], ['journey validation passes', 'new workflow QA rows generated'], ['build empty routes', 'add link-only dashboard actions', 'defer workflow design to wow pass']);
|
|
825
1265
|
}
|
|
826
1266
|
if (failureClass === 'release') {
|
|
827
|
-
return makePlan('release_repair', 'Repair Release Gate', 'Repair deploy/publish/sample-data release evidence
|
|
1267
|
+
return makePlan('release_repair', 'Repair Release Gate', 'Repair deploy/publish/sample-data release evidence with a hotfix-first path before any repeated full deploy.', 'release_repair_only', false, false, [
|
|
828
1268
|
'Read the deploy/publish/sample-data log.',
|
|
829
1269
|
'Identify whether the blocker is domain, asset, seed data, route, permission, or CDN.',
|
|
830
|
-
'
|
|
1270
|
+
'Prefer backend hotfix, release config, domain, cache, or seed-data repair when the product artifact already has business proof.',
|
|
831
1271
|
'Rerun only the failed release gate.'
|
|
832
|
-
], ['deploy or publish log', 'sample-data status', 'failed release gate rerun'], ['release gate passes', 'new release blocker hash'], ['change core workflow after business QA passed', 'mark accepted from scorecard only', 'rerun full builder loop']);
|
|
1272
|
+
], ['deploy or publish log', 'sample-data status', 'failed release gate rerun'], ['release gate passes', 'new release blocker hash'], ['change core workflow after business QA passed', 'mark accepted from scorecard only', 'rerun full builder loop', 'repeat deploy of same artifact without force_deploy evidence']);
|
|
833
1273
|
}
|
|
834
1274
|
if (failureClass === 'business' || failureClass === 'qa_evidence' || failureClass === 'route') {
|
|
835
1275
|
return makePlan('business_proof_repair', 'Repair Business Proof', 'Fix the exact failing workflow assertion and prove before/action/after behavior.', 'business_repair', true, true, [
|
|
@@ -867,20 +1307,33 @@ function collectOpenTail(records) {
|
|
|
867
1307
|
return tail;
|
|
868
1308
|
}
|
|
869
1309
|
function countSameFailure(records, current) {
|
|
870
|
-
var currentKey =
|
|
1310
|
+
var currentKey = failureKey(current);
|
|
871
1311
|
var count = 0;
|
|
872
1312
|
for (var index = records.length - 1; index >= 0; index -= 1) {
|
|
873
1313
|
var record = records[index];
|
|
874
1314
|
if (isPassingOutcome(record)) {
|
|
875
1315
|
break;
|
|
876
1316
|
}
|
|
877
|
-
if (
|
|
1317
|
+
if (failureKey(record) !== currentKey) {
|
|
878
1318
|
break;
|
|
879
1319
|
}
|
|
880
1320
|
count += 1;
|
|
881
1321
|
}
|
|
882
1322
|
return count;
|
|
883
1323
|
}
|
|
1324
|
+
function previousRecordForPolicy(history, current, currentWasExplicit) {
|
|
1325
|
+
if (!history.length) {
|
|
1326
|
+
return undefined;
|
|
1327
|
+
}
|
|
1328
|
+
if (!currentWasExplicit) {
|
|
1329
|
+
return history.length > 1 ? history[history.length - 2] : undefined;
|
|
1330
|
+
}
|
|
1331
|
+
var last = history[history.length - 1];
|
|
1332
|
+
if (failureEvidenceKey(last) === failureEvidenceKey(current)) {
|
|
1333
|
+
return history.length > 1 ? history[history.length - 2] : undefined;
|
|
1334
|
+
}
|
|
1335
|
+
return last;
|
|
1336
|
+
}
|
|
884
1337
|
function countPingPong(records, current) {
|
|
885
1338
|
var tail = collectOpenTail(records).filter(function (record) {
|
|
886
1339
|
return cleanText(record.lane, 80) === cleanText(current.lane, 80)
|
|
@@ -907,14 +1360,24 @@ function countPingPong(records, current) {
|
|
|
907
1360
|
}
|
|
908
1361
|
function decideResolveIOAIManagerPolicy(input) {
|
|
909
1362
|
var history = Array.isArray(input.history) ? input.history : [];
|
|
1363
|
+
var currentWasExplicit = !!input.current;
|
|
910
1364
|
var current = input.current || history[history.length - 1] || {};
|
|
911
1365
|
var failureClass = normalizeResolveIOAIManagerFailureClass(current.failureClass);
|
|
912
1366
|
var blockerFingerprint = resolveResolveIOAIManagerBlockerFingerprint(current);
|
|
913
1367
|
var evidenceHash = hashResolveIOAIManagerEvidence(current);
|
|
914
|
-
var previous = history
|
|
1368
|
+
var previous = previousRecordForPolicy(history, current, currentWasExplicit);
|
|
915
1369
|
var previousSameFailure = previous && failureKey(previous) === failureKey(current);
|
|
916
|
-
var
|
|
917
|
-
|
|
1370
|
+
var evidenceAssessment = previousSameFailure
|
|
1371
|
+
? assessResolveIOAIManagerEvidenceChange(previous, current)
|
|
1372
|
+
: {
|
|
1373
|
+
changed: false,
|
|
1374
|
+
material: false,
|
|
1375
|
+
strength: 'none',
|
|
1376
|
+
signals: [],
|
|
1377
|
+
evidenceHash: evidenceHash,
|
|
1378
|
+
blockerFingerprint: blockerFingerprint
|
|
1379
|
+
};
|
|
1380
|
+
var newEvidence = !!previousSameFailure && evidenceAssessment.changed;
|
|
918
1381
|
var sameFailureCount = countSameFailure(history, current);
|
|
919
1382
|
var pingPongCount = countPingPong(history, current);
|
|
920
1383
|
var maxSameFailureRepeats = Math.max(1, Number(input.maxSameFailureRepeats || 3) || 3);
|
|
@@ -928,6 +1391,9 @@ function decideResolveIOAIManagerPolicy(input) {
|
|
|
928
1391
|
sameFailureCount: sameFailureCount,
|
|
929
1392
|
pingPongCount: pingPongCount,
|
|
930
1393
|
newEvidence: newEvidence,
|
|
1394
|
+
materialEvidence: evidenceAssessment.material,
|
|
1395
|
+
evidenceStrength: evidenceAssessment.strength,
|
|
1396
|
+
evidenceSignals: evidenceAssessment.signals,
|
|
931
1397
|
loopBudgetShouldReset: false,
|
|
932
1398
|
productRepairFailure: !infraClasses.has(failureClass) && !ignoredClasses.has(failureClass)
|
|
933
1399
|
};
|
|
@@ -976,8 +1442,10 @@ function decideResolveIOAIManagerPolicy(input) {
|
|
|
976
1442
|
if (pingPongCount >= maxPingPongTransitions) {
|
|
977
1443
|
return withPlan('park_ping_pong', 'manager_policy_ping_pong_failure_loop');
|
|
978
1444
|
}
|
|
979
|
-
if (sameFailureCount >= maxSameFailureRepeats && !
|
|
980
|
-
return withPlan('park_repeated_failure',
|
|
1445
|
+
if (sameFailureCount >= maxSameFailureRepeats && !evidenceAssessment.material) {
|
|
1446
|
+
return withPlan('park_repeated_failure', newEvidence
|
|
1447
|
+
? 'manager_policy_same_failure_with_weak_evidence'
|
|
1448
|
+
: 'manager_policy_same_failure_without_new_evidence');
|
|
981
1449
|
}
|
|
982
1450
|
if (infraClasses.has(failureClass)) {
|
|
983
1451
|
return withPlan('retry_infra', 'manager_policy_infra_failure_routes_to_infra_repair', {
|
|
@@ -985,13 +1453,311 @@ function decideResolveIOAIManagerPolicy(input) {
|
|
|
985
1453
|
});
|
|
986
1454
|
}
|
|
987
1455
|
if (newEvidence || !previousSameFailure) {
|
|
1456
|
+
if (newEvidence && !evidenceAssessment.material) {
|
|
1457
|
+
return withPlan('continue', 'manager_policy_weak_evidence_does_not_reset_loop_budget');
|
|
1458
|
+
}
|
|
988
1459
|
return withPlan('continue', newEvidence
|
|
989
|
-
? '
|
|
1460
|
+
? 'manager_policy_new_material_evidence_resets_loop_budget'
|
|
990
1461
|
: 'manager_policy_new_failure_or_lane', {
|
|
991
|
-
loopBudgetShouldReset: true
|
|
1462
|
+
loopBudgetShouldReset: true,
|
|
1463
|
+
materialEvidence: newEvidence ? true : base.materialEvidence,
|
|
1464
|
+
evidenceStrength: newEvidence ? evidenceAssessment.strength : base.evidenceStrength
|
|
992
1465
|
});
|
|
993
1466
|
}
|
|
994
1467
|
return withPlan('continue', 'manager_policy_retry_below_repeat_limit');
|
|
995
1468
|
}
|
|
1469
|
+
function buildReplayDirectiveFromPlan(input) {
|
|
1470
|
+
var checkpoint = buildResolveIOAIManagerRecoveryCheckpoint({
|
|
1471
|
+
plan: input.plan,
|
|
1472
|
+
current: input.current,
|
|
1473
|
+
now: input.now
|
|
1474
|
+
});
|
|
1475
|
+
var probe = buildResolveIOAIManagerRecoveryEvidenceProbe({
|
|
1476
|
+
checkpoint: checkpoint,
|
|
1477
|
+
current: input.current,
|
|
1478
|
+
now: input.now
|
|
1479
|
+
});
|
|
1480
|
+
var action = buildResolveIOAIManagerRecoveryActionPacket({
|
|
1481
|
+
plan: input.plan,
|
|
1482
|
+
checkpoint: checkpoint,
|
|
1483
|
+
probe: probe,
|
|
1484
|
+
current: input.current,
|
|
1485
|
+
now: input.now
|
|
1486
|
+
});
|
|
1487
|
+
var dispatch = decideResolveIOAIManagerRecoveryActionDispatch({
|
|
1488
|
+
action: action,
|
|
1489
|
+
current: input.current,
|
|
1490
|
+
now: input.now
|
|
1491
|
+
});
|
|
1492
|
+
return buildResolveIOAIManagerRecoveryExecutionDirective({
|
|
1493
|
+
action: action,
|
|
1494
|
+
dispatchDecision: dispatch,
|
|
1495
|
+
current: input.current,
|
|
1496
|
+
surface: input.surface,
|
|
1497
|
+
now: input.now
|
|
1498
|
+
});
|
|
1499
|
+
}
|
|
1500
|
+
function replayCaseFromDirective(input) {
|
|
1501
|
+
var _a;
|
|
1502
|
+
var directive = input.directive;
|
|
1503
|
+
var safeAutoDispatch = isResolveIOAIManagerSafeAutoDispatch({
|
|
1504
|
+
dispatchAction: directive.dispatchAction,
|
|
1505
|
+
directive: directive,
|
|
1506
|
+
includeJourneyContractRepair: input.expectedSafeAutoDispatch && directive.dispatchAction === 'run_journey_contract_repair',
|
|
1507
|
+
includeReleaseRepair: input.expectedSafeAutoDispatch && directive.dispatchAction === 'run_release_repair',
|
|
1508
|
+
includeProductRepair: false
|
|
1509
|
+
});
|
|
1510
|
+
return __assign(__assign({ caseId: input.caseId, surface: input.surface, pass: input.pass && safeAutoDispatch === input.expectedSafeAutoDispatch, action: input.action, reason: input.reason, recoveryClass: cleanText(((_a = directive.dispatchRecord) === null || _a === void 0 ? void 0 : _a.mode) || directive.phase, 120), dispatchAction: directive.dispatchAction, safeAutoDispatch: safeAutoDispatch, expectedSafeAutoDispatch: input.expectedSafeAutoDispatch, productRepairAllowed: directive.canRunProductRepair === true, loopBudgetShouldReset: input.loopBudgetShouldReset === true, materialEvidence: input.materialEvidence === true, evidenceStrength: input.evidenceStrength || 'none' }, (directive.releasePolicy ? {
|
|
1511
|
+
hotfixFirst: directive.releasePolicy.policy === 'hotfix_first',
|
|
1512
|
+
fullDeployAllowed: directive.releasePolicy.fullDeployAllowed
|
|
1513
|
+
} : {})), { details: __assign({ phase: directive.phase, allowed: directive.allowed, reason: directive.reason, releasePolicy: directive.releasePolicy }, (input.details || {})) });
|
|
1514
|
+
}
|
|
1515
|
+
function buildResolveIOAIManagerRecoveryReplayMatrix(input) {
|
|
1516
|
+
var _a, _b;
|
|
1517
|
+
if (input === void 0) { input = {}; }
|
|
1518
|
+
var surface = cleanText(input.surface || 'runner', 120);
|
|
1519
|
+
var maxSameFailureRepeats = Math.max(1, Number(input.maxSameFailureRepeats || 2) || 2);
|
|
1520
|
+
var includeReleaseRepair = input.includeReleaseRepair !== false;
|
|
1521
|
+
var includeJourneyContractRepair = input.includeJourneyContractRepair !== false;
|
|
1522
|
+
var cases = [];
|
|
1523
|
+
var infraPolicy = decideResolveIOAIManagerPolicy({
|
|
1524
|
+
history: [
|
|
1525
|
+
{ lane: 'qa', stepType: 'workflow_qa', outcome: 'needs_repair', failureClass: 'infra', blocker: 'Chrome executable missing.', evidenceHash: 'chrome-missing' }
|
|
1526
|
+
],
|
|
1527
|
+
current: { lane: 'qa', stepType: 'workflow_qa', outcome: 'needs_repair', failureClass: 'infra', blocker: 'Chrome executable missing.', evidenceHash: 'chrome-missing' },
|
|
1528
|
+
maxSameFailureRepeats: maxSameFailureRepeats
|
|
1529
|
+
});
|
|
1530
|
+
var infraDirective = buildResolveIOAIManagerRecoveryExecutionDirective({
|
|
1531
|
+
action: infraPolicy.recoveryAction,
|
|
1532
|
+
current: { lane: 'qa', stepType: 'workflow_qa', outcome: 'needs_repair', failureClass: 'infra', blocker: 'Chrome executable missing.', evidenceHash: 'chrome-missing' },
|
|
1533
|
+
surface: surface
|
|
1534
|
+
});
|
|
1535
|
+
cases.push(replayCaseFromDirective({
|
|
1536
|
+
caseId: 'infra_routes_to_infra_repair',
|
|
1537
|
+
surface: surface,
|
|
1538
|
+
action: infraPolicy.action,
|
|
1539
|
+
reason: infraPolicy.reason,
|
|
1540
|
+
directive: infraDirective,
|
|
1541
|
+
expectedSafeAutoDispatch: true,
|
|
1542
|
+
pass: infraPolicy.action === 'retry_infra'
|
|
1543
|
+
&& infraPolicy.recoveryPlan.recoveryClass === 'infra_repair'
|
|
1544
|
+
&& infraDirective.dispatchAction === 'run_infra_repair'
|
|
1545
|
+
&& infraDirective.canRunProductRepair === false,
|
|
1546
|
+
details: { recoveryClass: infraPolicy.recoveryPlan.recoveryClass }
|
|
1547
|
+
}));
|
|
1548
|
+
var releasePlan = buildResolveIOAIManagerRecoveryPlan({
|
|
1549
|
+
action: 'continue',
|
|
1550
|
+
reason: 'publish failed after business proof',
|
|
1551
|
+
failureClass: 'release',
|
|
1552
|
+
lane: 'publish',
|
|
1553
|
+
stepType: 'test_deploy',
|
|
1554
|
+
blocker: 'Domain publish failed for the current artifact.'
|
|
1555
|
+
});
|
|
1556
|
+
var releaseCurrent = {
|
|
1557
|
+
lane: 'publish',
|
|
1558
|
+
stepType: 'test_deploy',
|
|
1559
|
+
outcome: 'needs_repair',
|
|
1560
|
+
failureClass: 'release',
|
|
1561
|
+
blocker: 'Domain publish failed for the current artifact.',
|
|
1562
|
+
evidenceHash: 'release-domain-publish-failed',
|
|
1563
|
+
artifactPaths: ['runner-evidence/release-status.json']
|
|
1564
|
+
};
|
|
1565
|
+
var releaseDirective = buildReplayDirectiveFromPlan({
|
|
1566
|
+
surface: surface,
|
|
1567
|
+
plan: releasePlan,
|
|
1568
|
+
current: releaseCurrent
|
|
1569
|
+
});
|
|
1570
|
+
cases.push(replayCaseFromDirective({
|
|
1571
|
+
caseId: 'release_uses_hotfix_first_repair',
|
|
1572
|
+
surface: surface,
|
|
1573
|
+
action: 'continue',
|
|
1574
|
+
reason: 'publish failed after business proof',
|
|
1575
|
+
directive: releaseDirective,
|
|
1576
|
+
expectedSafeAutoDispatch: includeReleaseRepair,
|
|
1577
|
+
pass: releasePlan.recoveryClass === 'release_repair'
|
|
1578
|
+
&& releaseDirective.dispatchAction === 'run_release_repair'
|
|
1579
|
+
&& ((_a = releaseDirective.releasePolicy) === null || _a === void 0 ? void 0 : _a.policy) === 'hotfix_first'
|
|
1580
|
+
&& ((_b = releaseDirective.releasePolicy) === null || _b === void 0 ? void 0 : _b.fullDeployAllowed) === false
|
|
1581
|
+
&& releaseDirective.canRunProductRepair === false,
|
|
1582
|
+
details: { recoveryClass: releasePlan.recoveryClass }
|
|
1583
|
+
}));
|
|
1584
|
+
var journeyPlan = buildResolveIOAIManagerRecoveryPlan({
|
|
1585
|
+
action: 'continue',
|
|
1586
|
+
reason: 'journey contract missing first next last',
|
|
1587
|
+
failureClass: 'journey',
|
|
1588
|
+
lane: 'plan',
|
|
1589
|
+
stepType: 'journey_contract',
|
|
1590
|
+
blocker: 'Journey contract does not map the hub CTA to an action.'
|
|
1591
|
+
});
|
|
1592
|
+
var journeyDirective = buildReplayDirectiveFromPlan({
|
|
1593
|
+
surface: surface,
|
|
1594
|
+
plan: journeyPlan,
|
|
1595
|
+
current: {
|
|
1596
|
+
lane: 'plan',
|
|
1597
|
+
stepType: 'journey_contract',
|
|
1598
|
+
outcome: 'needs_repair',
|
|
1599
|
+
failureClass: 'journey',
|
|
1600
|
+
blocker: 'Journey contract does not map the hub CTA to an action.',
|
|
1601
|
+
evidenceHash: 'journey-contract-invalid'
|
|
1602
|
+
}
|
|
1603
|
+
});
|
|
1604
|
+
cases.push(replayCaseFromDirective({
|
|
1605
|
+
caseId: 'journey_repair_is_safe_only_for_aicoder_surfaces',
|
|
1606
|
+
surface: surface,
|
|
1607
|
+
action: 'continue',
|
|
1608
|
+
reason: 'journey contract missing first next last',
|
|
1609
|
+
directive: journeyDirective,
|
|
1610
|
+
expectedSafeAutoDispatch: includeJourneyContractRepair,
|
|
1611
|
+
pass: journeyPlan.recoveryClass === 'journey_contract_repair'
|
|
1612
|
+
&& journeyDirective.dispatchAction === 'run_journey_contract_repair'
|
|
1613
|
+
&& journeyDirective.canRunProductRepair === false,
|
|
1614
|
+
details: { recoveryClass: journeyPlan.recoveryClass }
|
|
1615
|
+
}));
|
|
1616
|
+
var weakPolicy = decideResolveIOAIManagerPolicy({
|
|
1617
|
+
history: [
|
|
1618
|
+
{ lane: 'repair', stepType: 'repair', outcome: 'needs_repair', failureClass: 'product_code', blocker: 'Save action still throws TypeError.', evidenceHash: 'save-before' },
|
|
1619
|
+
{ lane: 'repair', stepType: 'repair', outcome: 'needs_repair', failureClass: 'product_code', blocker: 'Save action still throws TypeError.', evidenceHash: 'renamed-hash-only' }
|
|
1620
|
+
],
|
|
1621
|
+
current: { lane: 'repair', stepType: 'repair', outcome: 'needs_repair', failureClass: 'product_code', blocker: 'Save action still throws TypeError.', evidenceHash: 'renamed-hash-only' },
|
|
1622
|
+
maxSameFailureRepeats: maxSameFailureRepeats
|
|
1623
|
+
});
|
|
1624
|
+
var weakDirective = buildResolveIOAIManagerRecoveryExecutionDirective({
|
|
1625
|
+
action: weakPolicy.recoveryAction,
|
|
1626
|
+
current: { lane: 'repair', stepType: 'repair', outcome: 'needs_repair', failureClass: 'product_code', blocker: 'Save action still throws TypeError.', evidenceHash: 'renamed-hash-only' },
|
|
1627
|
+
surface: surface
|
|
1628
|
+
});
|
|
1629
|
+
cases.push(replayCaseFromDirective({
|
|
1630
|
+
caseId: 'weak_hash_only_evidence_stays_parked',
|
|
1631
|
+
surface: surface,
|
|
1632
|
+
action: weakPolicy.action,
|
|
1633
|
+
reason: weakPolicy.reason,
|
|
1634
|
+
directive: weakDirective,
|
|
1635
|
+
expectedSafeAutoDispatch: true,
|
|
1636
|
+
pass: weakPolicy.action === 'park_repeated_failure'
|
|
1637
|
+
&& weakPolicy.materialEvidence === false
|
|
1638
|
+
&& weakPolicy.loopBudgetShouldReset === false
|
|
1639
|
+
&& weakDirective.dispatchAction === 'run_evidence_probe',
|
|
1640
|
+
loopBudgetShouldReset: weakPolicy.loopBudgetShouldReset,
|
|
1641
|
+
materialEvidence: weakPolicy.materialEvidence,
|
|
1642
|
+
evidenceStrength: weakPolicy.evidenceStrength,
|
|
1643
|
+
details: { evidenceSignals: weakPolicy.evidenceSignals }
|
|
1644
|
+
}));
|
|
1645
|
+
var materialPolicy = decideResolveIOAIManagerPolicy({
|
|
1646
|
+
history: [
|
|
1647
|
+
{ lane: 'repair', stepType: 'repair', outcome: 'needs_repair', failureClass: 'product_code', blocker: 'Save action still throws TypeError.', evidenceHash: 'save-before', artifactPaths: ['qa/save-before.log'] },
|
|
1648
|
+
{
|
|
1649
|
+
lane: 'repair',
|
|
1650
|
+
stepType: 'repair',
|
|
1651
|
+
outcome: 'needs_repair',
|
|
1652
|
+
failureClass: 'product_code',
|
|
1653
|
+
blocker: 'Save action still throws TypeError.',
|
|
1654
|
+
summary: 'New DOM trace proves the click reaches the method with an undefined id.',
|
|
1655
|
+
evidenceHash: 'save-dom-trace',
|
|
1656
|
+
artifactPaths: ['qa/save-before.log', 'qa/save-dom-trace.json']
|
|
1657
|
+
}
|
|
1658
|
+
],
|
|
1659
|
+
current: {
|
|
1660
|
+
lane: 'repair',
|
|
1661
|
+
stepType: 'repair',
|
|
1662
|
+
outcome: 'needs_repair',
|
|
1663
|
+
failureClass: 'product_code',
|
|
1664
|
+
blocker: 'Save action still throws TypeError.',
|
|
1665
|
+
summary: 'New DOM trace proves the click reaches the method with an undefined id.',
|
|
1666
|
+
evidenceHash: 'save-dom-trace',
|
|
1667
|
+
artifactPaths: ['qa/save-before.log', 'qa/save-dom-trace.json']
|
|
1668
|
+
},
|
|
1669
|
+
maxSameFailureRepeats: maxSameFailureRepeats
|
|
1670
|
+
});
|
|
1671
|
+
cases.push({
|
|
1672
|
+
caseId: 'material_evidence_resets_loop_budget',
|
|
1673
|
+
surface: surface,
|
|
1674
|
+
pass: materialPolicy.action === 'continue'
|
|
1675
|
+
&& materialPolicy.materialEvidence === true
|
|
1676
|
+
&& materialPolicy.loopBudgetShouldReset === true,
|
|
1677
|
+
action: materialPolicy.action,
|
|
1678
|
+
reason: materialPolicy.reason,
|
|
1679
|
+
recoveryClass: materialPolicy.recoveryPlan.recoveryClass,
|
|
1680
|
+
dispatchAction: materialPolicy.recoveryAction.mode,
|
|
1681
|
+
safeAutoDispatch: false,
|
|
1682
|
+
expectedSafeAutoDispatch: false,
|
|
1683
|
+
productRepairAllowed: materialPolicy.recoveryAction.productRepairAllowed,
|
|
1684
|
+
loopBudgetShouldReset: materialPolicy.loopBudgetShouldReset,
|
|
1685
|
+
materialEvidence: materialPolicy.materialEvidence,
|
|
1686
|
+
evidenceStrength: materialPolicy.evidenceStrength,
|
|
1687
|
+
details: { evidenceSignals: materialPolicy.evidenceSignals }
|
|
1688
|
+
});
|
|
1689
|
+
var productPlan = buildResolveIOAIManagerRecoveryPlan({
|
|
1690
|
+
action: 'continue',
|
|
1691
|
+
reason: 'business proof still failing',
|
|
1692
|
+
failureClass: 'product_code',
|
|
1693
|
+
lane: 'repair',
|
|
1694
|
+
stepType: 'repair',
|
|
1695
|
+
blocker: 'Save action still throws TypeError.',
|
|
1696
|
+
productRepairFailure: true
|
|
1697
|
+
});
|
|
1698
|
+
var productDirective = buildReplayDirectiveFromPlan({
|
|
1699
|
+
surface: surface,
|
|
1700
|
+
plan: productPlan,
|
|
1701
|
+
current: {
|
|
1702
|
+
lane: 'repair',
|
|
1703
|
+
stepType: 'repair',
|
|
1704
|
+
outcome: 'needs_repair',
|
|
1705
|
+
failureClass: 'product_code',
|
|
1706
|
+
blocker: 'Save action still throws TypeError.',
|
|
1707
|
+
evidenceHash: 'save-product-repair'
|
|
1708
|
+
}
|
|
1709
|
+
});
|
|
1710
|
+
var productSafe = isResolveIOAIManagerSafeAutoDispatch({
|
|
1711
|
+
dispatchAction: productDirective.dispatchAction,
|
|
1712
|
+
directive: productDirective,
|
|
1713
|
+
includeProductRepair: input.includeProductRepair === true
|
|
1714
|
+
});
|
|
1715
|
+
cases.push({
|
|
1716
|
+
caseId: 'product_repair_requires_explicit_operator_policy',
|
|
1717
|
+
surface: surface,
|
|
1718
|
+
pass: productPlan.recoveryClass === 'product_code_repair'
|
|
1719
|
+
&& productDirective.dispatchAction === 'run_targeted_product_repair'
|
|
1720
|
+
&& productSafe === false,
|
|
1721
|
+
action: 'continue',
|
|
1722
|
+
reason: 'business proof still failing',
|
|
1723
|
+
recoveryClass: productPlan.recoveryClass,
|
|
1724
|
+
dispatchAction: productDirective.dispatchAction,
|
|
1725
|
+
safeAutoDispatch: productSafe,
|
|
1726
|
+
expectedSafeAutoDispatch: false,
|
|
1727
|
+
productRepairAllowed: productDirective.canRunProductRepair,
|
|
1728
|
+
loopBudgetShouldReset: false,
|
|
1729
|
+
materialEvidence: false,
|
|
1730
|
+
evidenceStrength: 'none',
|
|
1731
|
+
details: { phase: productDirective.phase, allowed: productDirective.allowed }
|
|
1732
|
+
});
|
|
1733
|
+
var duplicateReleasePolicy = buildResolveIOAIManagerHotfixFirstReleasePolicy({
|
|
1734
|
+
surface: surface,
|
|
1735
|
+
deployFingerprint: "".concat(surface, "-artifact-sha"),
|
|
1736
|
+
lastDeployFingerprint: "".concat(surface, "-artifact-sha"),
|
|
1737
|
+
deployStatus: 'completed',
|
|
1738
|
+
publishStatus: 'published'
|
|
1739
|
+
});
|
|
1740
|
+
cases.push({
|
|
1741
|
+
caseId: 'duplicate_release_fingerprint_blocks_full_deploy',
|
|
1742
|
+
surface: surface,
|
|
1743
|
+
pass: duplicateReleasePolicy.recommendedAction === 'block_duplicate_deploy'
|
|
1744
|
+
&& duplicateReleasePolicy.duplicateDeployBlocked === true
|
|
1745
|
+
&& duplicateReleasePolicy.fullDeployAllowed === false,
|
|
1746
|
+
action: duplicateReleasePolicy.recommendedAction,
|
|
1747
|
+
reason: duplicateReleasePolicy.reason,
|
|
1748
|
+
recoveryClass: 'release_repair',
|
|
1749
|
+
dispatchAction: 'run_release_repair',
|
|
1750
|
+
safeAutoDispatch: includeReleaseRepair,
|
|
1751
|
+
expectedSafeAutoDispatch: includeReleaseRepair,
|
|
1752
|
+
productRepairAllowed: false,
|
|
1753
|
+
loopBudgetShouldReset: false,
|
|
1754
|
+
materialEvidence: false,
|
|
1755
|
+
evidenceStrength: 'none',
|
|
1756
|
+
hotfixFirst: true,
|
|
1757
|
+
fullDeployAllowed: duplicateReleasePolicy.fullDeployAllowed,
|
|
1758
|
+
details: { releasePolicy: duplicateReleasePolicy }
|
|
1759
|
+
});
|
|
1760
|
+
return cases;
|
|
1761
|
+
}
|
|
996
1762
|
|
|
997
1763
|
//# sourceMappingURL=ai-runner-manager-policy.js.map
|