@resolveio/server-lib 22.3.158 → 22.3.160
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/methods/ai-terminal.d.ts +1 -0
- package/methods/ai-terminal.js +133 -3
- package/methods/ai-terminal.js.map +1 -1
- package/package.json +1 -1
- package/util/ai-run-evidence-adapters.d.ts +37 -0
- package/util/ai-run-evidence-adapters.js +988 -79
- package/util/ai-run-evidence-adapters.js.map +1 -1
- package/util/ai-run-evidence.d.ts +1 -1
- package/util/ai-run-evidence.js.map +1 -1
- package/util/ai-runner-manager-autopilot.d.ts +99 -1
- package/util/ai-runner-manager-autopilot.js +370 -41
- package/util/ai-runner-manager-autopilot.js.map +1 -1
- package/util/ai-runner-manager-policy.d.ts +159 -0
- package/util/ai-runner-manager-policy.js +782 -30
- package/util/ai-runner-manager-policy.js.map +1 -1
- package/util/aicoder-runner-v6.d.ts +93 -3
- package/util/aicoder-runner-v6.js +699 -27
- package/util/aicoder-runner-v6.js.map +1 -1
- package/util/support-runner-v5.d.ts +192 -2
- package/util/support-runner-v5.js +1140 -74
- package/util/support-runner-v5.js.map +1 -1
|
@@ -47,9 +47,14 @@ 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.estimateResolveIOAIManagerRetryExpectedValue = estimateResolveIOAIManagerRetryExpectedValue;
|
|
51
|
+
exports.decideResolveIOAIManagerAutonomyPolicy = decideResolveIOAIManagerAutonomyPolicy;
|
|
50
52
|
exports.normalizeResolveIOAIManagerHotfixEvidence = normalizeResolveIOAIManagerHotfixEvidence;
|
|
53
|
+
exports.evaluateResolveIOAIManagerHotfixGitProof = evaluateResolveIOAIManagerHotfixGitProof;
|
|
51
54
|
exports.validateResolveIOAIManagerHotfixEvidence = validateResolveIOAIManagerHotfixEvidence;
|
|
55
|
+
exports.buildResolveIOAIManagerHotfixEvidenceRecord = buildResolveIOAIManagerHotfixEvidenceRecord;
|
|
52
56
|
exports.decideResolveIOAIManagerHotfixContinuation = decideResolveIOAIManagerHotfixContinuation;
|
|
57
|
+
exports.decideResolveIOAIManagerHotfixCommitGuard = decideResolveIOAIManagerHotfixCommitGuard;
|
|
53
58
|
exports.buildResolveIOAIManagerHotfixFirstReleasePolicy = buildResolveIOAIManagerHotfixFirstReleasePolicy;
|
|
54
59
|
exports.isResolveIOAIManagerSafeAutoDispatch = isResolveIOAIManagerSafeAutoDispatch;
|
|
55
60
|
exports.normalizeResolveIOAIManagerFailureClass = normalizeResolveIOAIManagerFailureClass;
|
|
@@ -114,6 +119,291 @@ var HOTFIX_CHANNELS = new Set([
|
|
|
114
119
|
function cleanObject(value) {
|
|
115
120
|
return value && typeof value === 'object' && !Array.isArray(value) ? value : {};
|
|
116
121
|
}
|
|
122
|
+
function normalizeAutonomyMode(value) {
|
|
123
|
+
var normalized = cleanText(value, 120).toLowerCase().replace(/[\s-]+/g, '_');
|
|
124
|
+
if (/^(monitor|monitor_only|watch|watch_only)$/.test(normalized)) {
|
|
125
|
+
return 'monitor_only';
|
|
126
|
+
}
|
|
127
|
+
if (/^(auto|auto_retry|auto_retry_within_budget|autonomous|within_budget)$/.test(normalized)) {
|
|
128
|
+
return 'auto_retry_within_budget';
|
|
129
|
+
}
|
|
130
|
+
return 'manual_only';
|
|
131
|
+
}
|
|
132
|
+
function normalizeManagerEvidenceStrength(value) {
|
|
133
|
+
var normalized = cleanText(value, 40).toLowerCase().replace(/[\s-]+/g, '_');
|
|
134
|
+
if (normalized === 'proof') {
|
|
135
|
+
return 'proof';
|
|
136
|
+
}
|
|
137
|
+
if (normalized === 'material' || normalized === 'strong') {
|
|
138
|
+
return 'material';
|
|
139
|
+
}
|
|
140
|
+
if (normalized === 'weak') {
|
|
141
|
+
return 'weak';
|
|
142
|
+
}
|
|
143
|
+
return 'none';
|
|
144
|
+
}
|
|
145
|
+
function nonNegativeMoney(value) {
|
|
146
|
+
var parsed = Number(value);
|
|
147
|
+
return Number.isFinite(parsed) && parsed > 0 ? parsed : 0;
|
|
148
|
+
}
|
|
149
|
+
function finiteNumber(value) {
|
|
150
|
+
var parsed = Number(value);
|
|
151
|
+
return Number.isFinite(parsed) ? parsed : undefined;
|
|
152
|
+
}
|
|
153
|
+
function clampNumber(value, min, max) {
|
|
154
|
+
return Math.min(max, Math.max(min, value));
|
|
155
|
+
}
|
|
156
|
+
function isCheapEvidenceAutonomyAction(value) {
|
|
157
|
+
var action = cleanText(value, 120);
|
|
158
|
+
return !action || /^(run_evidence_probe|run_read_only_diagnosis|advance|continue_gate|park_manual)$/.test(action);
|
|
159
|
+
}
|
|
160
|
+
function estimateResolveIOAIManagerRetryExpectedValue(input) {
|
|
161
|
+
var e_2, _a;
|
|
162
|
+
if (input === void 0) { input = {}; }
|
|
163
|
+
var dispatchAction = cleanText(input.dispatchAction, 120);
|
|
164
|
+
var failureClass = normalizeResolveIOAIManagerFailureClass(input.failureClass);
|
|
165
|
+
var recoveryClass = cleanText(input.recoveryClass, 120);
|
|
166
|
+
var evidenceStrength = normalizeManagerEvidenceStrength(input.evidenceStrength);
|
|
167
|
+
var evidenceSignals = cleanList(input.evidenceSignals, 12, 120);
|
|
168
|
+
var projectedActionCostUsd = nonNegativeMoney(input.projectedActionCostUsd);
|
|
169
|
+
var budgetHardUsd = nonNegativeMoney(input.budgetHardUsd);
|
|
170
|
+
var materialEvidence = input.materialEvidence === true || evidenceStrength === 'material' || evidenceStrength === 'proof';
|
|
171
|
+
var newEvidence = input.newEvidence === true;
|
|
172
|
+
var signals = [];
|
|
173
|
+
var score = 0.1;
|
|
174
|
+
if (dispatchAction === 'run_evidence_probe') {
|
|
175
|
+
score = 0.75;
|
|
176
|
+
signals.push('cheap_evidence_probe');
|
|
177
|
+
}
|
|
178
|
+
else if (dispatchAction === 'run_read_only_diagnosis') {
|
|
179
|
+
score = 0.65;
|
|
180
|
+
signals.push('read_only_diagnosis');
|
|
181
|
+
}
|
|
182
|
+
else if (dispatchAction === 'advance' || dispatchAction === 'continue_gate') {
|
|
183
|
+
score = 0.55;
|
|
184
|
+
signals.push('gate_continuation');
|
|
185
|
+
}
|
|
186
|
+
else if (dispatchAction === 'run_infra_repair') {
|
|
187
|
+
score = 0.4;
|
|
188
|
+
signals.push('bounded_infra_repair');
|
|
189
|
+
}
|
|
190
|
+
else if (dispatchAction === 'run_compile_repair') {
|
|
191
|
+
score = 0.4;
|
|
192
|
+
signals.push('bounded_compile_repair');
|
|
193
|
+
}
|
|
194
|
+
else if (dispatchAction === 'run_release_repair') {
|
|
195
|
+
score = 0.3;
|
|
196
|
+
signals.push('bounded_release_repair');
|
|
197
|
+
}
|
|
198
|
+
else if (dispatchAction === 'run_journey_contract_repair' || dispatchAction === 'run_business_assertion_repair') {
|
|
199
|
+
score = 0.25;
|
|
200
|
+
signals.push('bounded_workflow_or_proof_repair');
|
|
201
|
+
}
|
|
202
|
+
else if (dispatchAction === 'run_targeted_product_repair') {
|
|
203
|
+
score = 0.15;
|
|
204
|
+
signals.push('targeted_product_repair');
|
|
205
|
+
}
|
|
206
|
+
if (evidenceStrength === 'proof') {
|
|
207
|
+
score += 0.3;
|
|
208
|
+
signals.push('proof_evidence');
|
|
209
|
+
}
|
|
210
|
+
else if (materialEvidence) {
|
|
211
|
+
score += 0.2;
|
|
212
|
+
signals.push('material_evidence');
|
|
213
|
+
}
|
|
214
|
+
else if (newEvidence) {
|
|
215
|
+
score += 0.1;
|
|
216
|
+
signals.push('new_evidence');
|
|
217
|
+
}
|
|
218
|
+
else if (evidenceStrength === 'weak') {
|
|
219
|
+
score -= 0.15;
|
|
220
|
+
signals.push('weak_evidence');
|
|
221
|
+
}
|
|
222
|
+
else if (!isCheapEvidenceAutonomyAction(dispatchAction)) {
|
|
223
|
+
score -= 0.25;
|
|
224
|
+
signals.push('no_material_evidence');
|
|
225
|
+
}
|
|
226
|
+
if ((failureClass === 'infra' || /infra/i.test(recoveryClass)) && dispatchAction === 'run_infra_repair') {
|
|
227
|
+
score += 0.15;
|
|
228
|
+
signals.push('failure_matches_infra_repair');
|
|
229
|
+
}
|
|
230
|
+
if ((failureClass === 'compile' || /compile/i.test(recoveryClass)) && dispatchAction === 'run_compile_repair') {
|
|
231
|
+
score += 0.15;
|
|
232
|
+
signals.push('failure_matches_compile_repair');
|
|
233
|
+
}
|
|
234
|
+
if (/release|publish|deploy/i.test("".concat(failureClass, " ").concat(recoveryClass)) && dispatchAction === 'run_release_repair') {
|
|
235
|
+
score += 0.1;
|
|
236
|
+
signals.push('failure_matches_release_repair');
|
|
237
|
+
}
|
|
238
|
+
if (projectedActionCostUsd >= 5) {
|
|
239
|
+
score -= 0.3;
|
|
240
|
+
signals.push('high_projected_cost');
|
|
241
|
+
}
|
|
242
|
+
else if (projectedActionCostUsd >= 2) {
|
|
243
|
+
score -= 0.18;
|
|
244
|
+
signals.push('medium_projected_cost');
|
|
245
|
+
}
|
|
246
|
+
else if (projectedActionCostUsd >= 1) {
|
|
247
|
+
score -= 0.08;
|
|
248
|
+
signals.push('low_projected_cost');
|
|
249
|
+
}
|
|
250
|
+
if (budgetHardUsd > 0 && projectedActionCostUsd > budgetHardUsd * 0.5) {
|
|
251
|
+
score -= 0.2;
|
|
252
|
+
signals.push('large_fraction_of_remaining_budget');
|
|
253
|
+
}
|
|
254
|
+
if (input.sameEvidenceAlreadyAttempted === true) {
|
|
255
|
+
score -= 0.35;
|
|
256
|
+
signals.push('same_evidence_already_attempted');
|
|
257
|
+
}
|
|
258
|
+
try {
|
|
259
|
+
for (var evidenceSignals_1 = __values(evidenceSignals), evidenceSignals_1_1 = evidenceSignals_1.next(); !evidenceSignals_1_1.done; evidenceSignals_1_1 = evidenceSignals_1.next()) {
|
|
260
|
+
var signal = evidenceSignals_1_1.value;
|
|
261
|
+
if (/passing_outcome|business|proof|diagnosis|compile|infra|release|artifact|fingerprint_changed|evidence_hash_changed/i.test(signal)) {
|
|
262
|
+
score += 0.03;
|
|
263
|
+
signals.push("evidence_signal:".concat(signal));
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
catch (e_2_1) { e_2 = { error: e_2_1 }; }
|
|
268
|
+
finally {
|
|
269
|
+
try {
|
|
270
|
+
if (evidenceSignals_1_1 && !evidenceSignals_1_1.done && (_a = evidenceSignals_1.return)) _a.call(evidenceSignals_1);
|
|
271
|
+
}
|
|
272
|
+
finally { if (e_2) throw e_2.error; }
|
|
273
|
+
}
|
|
274
|
+
var rounded = Number(clampNumber(score, -1, 1).toFixed(2));
|
|
275
|
+
var minScore = 0;
|
|
276
|
+
return {
|
|
277
|
+
score: rounded,
|
|
278
|
+
minScore: minScore,
|
|
279
|
+
positive: rounded >= minScore,
|
|
280
|
+
source: 'estimated',
|
|
281
|
+
confidence: evidenceStrength === 'proof' || materialEvidence ? 'medium' : 'low',
|
|
282
|
+
reason: rounded >= minScore
|
|
283
|
+
? 'estimated_retry_value_is_non_negative'
|
|
284
|
+
: 'estimated_retry_value_is_negative',
|
|
285
|
+
signals: Array.from(new Set(signals)).slice(0, 16)
|
|
286
|
+
};
|
|
287
|
+
}
|
|
288
|
+
function decideResolveIOAIManagerAutonomyPolicy(input) {
|
|
289
|
+
var _a;
|
|
290
|
+
if (input === void 0) { input = {}; }
|
|
291
|
+
var mode = normalizeAutonomyMode(input.mode);
|
|
292
|
+
var currentSpendUsd = nonNegativeMoney(input.currentSpendUsd);
|
|
293
|
+
var projectedActionCostUsd = nonNegativeMoney(input.projectedActionCostUsd);
|
|
294
|
+
var projectedSpendUsd = currentSpendUsd + projectedActionCostUsd;
|
|
295
|
+
var budgetSoftUsd = nonNegativeMoney(input.budgetSoftUsd);
|
|
296
|
+
var budgetHardUsd = nonNegativeMoney(input.budgetHardUsd);
|
|
297
|
+
var softBudgetExceeded = budgetSoftUsd > 0 && projectedSpendUsd >= budgetSoftUsd;
|
|
298
|
+
var hardBudgetExceeded = budgetHardUsd > 0 && projectedSpendUsd > budgetHardUsd;
|
|
299
|
+
var dispatchAction = cleanText(input.dispatchAction, 120);
|
|
300
|
+
var evidenceStrength = normalizeManagerEvidenceStrength(input.evidenceStrength);
|
|
301
|
+
var evidenceSignals = cleanList(input.evidenceSignals, 12, 120);
|
|
302
|
+
var materialEvidence = input.materialEvidence === true || evidenceStrength === 'material' || evidenceStrength === 'proof';
|
|
303
|
+
var newEvidence = input.newEvidence === true;
|
|
304
|
+
var evidenceBacked = materialEvidence || newEvidence || evidenceSignals.some(function (signal) { return /material|proof|business|compile|infra|release|diagnosis|journey|workflow|artifact|hash_changed|fingerprint_changed/i.test(signal); });
|
|
305
|
+
var cheapEvidenceAction = isCheapEvidenceAutonomyAction(dispatchAction);
|
|
306
|
+
var expectedValueEstimate = estimateResolveIOAIManagerRetryExpectedValue({
|
|
307
|
+
dispatchAction: dispatchAction,
|
|
308
|
+
projectedActionCostUsd: projectedActionCostUsd,
|
|
309
|
+
currentSpendUsd: currentSpendUsd,
|
|
310
|
+
budgetHardUsd: budgetHardUsd,
|
|
311
|
+
evidenceStrength: evidenceStrength,
|
|
312
|
+
materialEvidence: materialEvidence,
|
|
313
|
+
newEvidence: newEvidence,
|
|
314
|
+
evidenceSignals: evidenceSignals,
|
|
315
|
+
sameEvidenceAlreadyAttempted: input.sameEvidenceAlreadyAttempted === true
|
|
316
|
+
});
|
|
317
|
+
var providedExpectedValue = finiteNumber(input.expectedValueScore);
|
|
318
|
+
var expectedValueKnown = providedExpectedValue !== undefined;
|
|
319
|
+
var expectedValueScore = expectedValueKnown ? providedExpectedValue : expectedValueEstimate.score;
|
|
320
|
+
var minExpectedValue = (_a = finiteNumber(input.minExpectedValueScore)) !== null && _a !== void 0 ? _a : expectedValueEstimate.minScore;
|
|
321
|
+
var expectedValuePositive = expectedValueScore >= minExpectedValue;
|
|
322
|
+
var expectedValueSource = expectedValueKnown ? 'provided' : 'estimated';
|
|
323
|
+
var requiredEvidence = __spreadArray(__spreadArray(__spreadArray(__spreadArray([
|
|
324
|
+
'mode',
|
|
325
|
+
'projectedActionCostUsd'
|
|
326
|
+
], __read((budgetHardUsd > 0 ? ['budgetHardUsd'] : [])), false), __read((budgetSoftUsd > 0 ? ['budgetSoftUsd'] : [])), false), __read((dispatchAction ? ['dispatchAction'] : [])), false), __read((cheapEvidenceAction ? [] : ['materialEvidence or newEvidence', 'expectedValueScore when available'])), false);
|
|
327
|
+
var forbiddenActions = [];
|
|
328
|
+
var canAutoDispatch = false;
|
|
329
|
+
var canManualDispatch = true;
|
|
330
|
+
var blocked = false;
|
|
331
|
+
var requiresHumanApproval = true;
|
|
332
|
+
var reason = '';
|
|
333
|
+
var recommendedControl = mode;
|
|
334
|
+
if (mode === 'monitor_only') {
|
|
335
|
+
canManualDispatch = false;
|
|
336
|
+
reason = 'monitor_only_blocks_runner_dispatch';
|
|
337
|
+
forbiddenActions.push('Do not run recovery, repair, QA, publish, deploy, or customer reply actions while in Monitor Only mode.');
|
|
338
|
+
}
|
|
339
|
+
else if (mode === 'manual_only') {
|
|
340
|
+
reason = 'manual_only_requires_operator_dispatch';
|
|
341
|
+
forbiddenActions.push('Do not auto-dispatch manager recovery actions in Manual Only mode.');
|
|
342
|
+
}
|
|
343
|
+
else if (hardBudgetExceeded) {
|
|
344
|
+
blocked = true;
|
|
345
|
+
canAutoDispatch = false;
|
|
346
|
+
canManualDispatch = input.operatorApproved === true;
|
|
347
|
+
reason = 'auto_retry_budget_hard_cap_would_be_exceeded';
|
|
348
|
+
recommendedControl = 'increase_budget_or_manual';
|
|
349
|
+
forbiddenActions.push('Do not auto-dispatch because projected spend exceeds the hard budget.');
|
|
350
|
+
}
|
|
351
|
+
else if (!cheapEvidenceAction && !evidenceBacked) {
|
|
352
|
+
canAutoDispatch = false;
|
|
353
|
+
requiresHumanApproval = true;
|
|
354
|
+
reason = 'auto_retry_requires_material_evidence';
|
|
355
|
+
forbiddenActions.push('Do not auto-dispatch repair work until a deterministic artifact, changed blocker fingerprint, or material proof is recorded.');
|
|
356
|
+
}
|
|
357
|
+
else if (!cheapEvidenceAction && !expectedValuePositive) {
|
|
358
|
+
canAutoDispatch = false;
|
|
359
|
+
requiresHumanApproval = true;
|
|
360
|
+
reason = 'auto_retry_expected_value_not_positive';
|
|
361
|
+
forbiddenActions.push('Do not auto-dispatch repair work when the expected value score is below the configured minimum.');
|
|
362
|
+
}
|
|
363
|
+
else {
|
|
364
|
+
canAutoDispatch = true;
|
|
365
|
+
requiresHumanApproval = softBudgetExceeded;
|
|
366
|
+
reason = softBudgetExceeded
|
|
367
|
+
? 'auto_retry_soft_budget_warning_requires_review'
|
|
368
|
+
: 'auto_retry_within_budget_allows_auto_dispatch';
|
|
369
|
+
if (softBudgetExceeded) {
|
|
370
|
+
forbiddenActions.push('Do not escalate to a more expensive model or broader repair without operator review after soft budget warning.');
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
return {
|
|
374
|
+
mode: mode,
|
|
375
|
+
canAutoDispatch: canAutoDispatch,
|
|
376
|
+
canManualDispatch: canManualDispatch,
|
|
377
|
+
blocked: blocked,
|
|
378
|
+
requiresHumanApproval: requiresHumanApproval,
|
|
379
|
+
reason: reason,
|
|
380
|
+
currentSpendUsd: currentSpendUsd,
|
|
381
|
+
projectedActionCostUsd: projectedActionCostUsd,
|
|
382
|
+
projectedSpendUsd: projectedSpendUsd,
|
|
383
|
+
budgetSoftUsd: budgetSoftUsd,
|
|
384
|
+
budgetHardUsd: budgetHardUsd,
|
|
385
|
+
softBudgetExceeded: softBudgetExceeded,
|
|
386
|
+
hardBudgetExceeded: hardBudgetExceeded,
|
|
387
|
+
dispatchAction: dispatchAction,
|
|
388
|
+
expectedValueScore: expectedValueScore,
|
|
389
|
+
minExpectedValueScore: minExpectedValue,
|
|
390
|
+
expectedValueKnown: expectedValueKnown,
|
|
391
|
+
expectedValueSource: expectedValueSource,
|
|
392
|
+
expectedValuePositive: expectedValuePositive,
|
|
393
|
+
evidenceStrength: evidenceStrength,
|
|
394
|
+
materialEvidence: materialEvidence,
|
|
395
|
+
newEvidence: newEvidence,
|
|
396
|
+
evidenceBacked: evidenceBacked,
|
|
397
|
+
evidenceSignals: evidenceSignals,
|
|
398
|
+
recommendedControl: recommendedControl,
|
|
399
|
+
forbiddenActions: forbiddenActions,
|
|
400
|
+
requiredEvidence: requiredEvidence
|
|
401
|
+
};
|
|
402
|
+
}
|
|
403
|
+
function cleanDateString(value) {
|
|
404
|
+
var date = value instanceof Date ? value : new Date(value || Date.now());
|
|
405
|
+
return Number.isNaN(date.getTime()) ? new Date().toISOString() : date.toISOString();
|
|
406
|
+
}
|
|
117
407
|
function normalizeHotfixChannel(value) {
|
|
118
408
|
var normalized = cleanText(value, 120).toLowerCase().replace(/[\s-]+/g, '_');
|
|
119
409
|
return HOTFIX_CHANNELS.has(normalized) ? normalized : '';
|
|
@@ -185,6 +475,7 @@ function normalizeResolveIOAIManagerHotfixEvidence(value, policy) {
|
|
|
185
475
|
sourceCommitSha: cleanText(source.sourceCommitSha || source.source_commit_sha || source.gitCommitSha || source.git_commit_sha || source.commitSha || source.commit_sha, 120),
|
|
186
476
|
githubCommitUrl: cleanText(source.githubCommitUrl || source.github_commit_url || source.gitCommitUrl || source.git_commit_url || source.commitUrl || source.commit_url, 500),
|
|
187
477
|
gitCommitStatus: cleanText(source.gitCommitStatus || source.git_commit_status || source.githubCommitStatus || source.github_commit_status, 160),
|
|
478
|
+
gitPushStatus: cleanText(source.gitPushStatus || source.git_push_status || source.githubPushStatus || source.github_push_status || source.githubCommitReachableStatus || source.github_commit_reachable_status, 160),
|
|
188
479
|
committedAt: source.committedAt || source.committed_at,
|
|
189
480
|
forceDeployReason: cleanText(source.forceDeployReason || source.force_deploy_reason, 1000),
|
|
190
481
|
hotfixCannotResolveReason: cleanText(source.hotfixCannotResolveReason || source.hotfix_cannot_resolve_reason, 1000),
|
|
@@ -204,8 +495,96 @@ function pushMissing(blockers, condition, message) {
|
|
|
204
495
|
function hotfixRequiresGithubCommit(channel) {
|
|
205
496
|
return /^(backend_js|static_ui|config|seed_data|release_artifact|new_artifact_deploy|artifact_build)$/.test(channel);
|
|
206
497
|
}
|
|
207
|
-
function
|
|
208
|
-
|
|
498
|
+
function extractGithubCommitSha(value) {
|
|
499
|
+
var _a;
|
|
500
|
+
var match = cleanText(value, 500).match(/^https:\/\/github\.com\/[A-Za-z0-9_.-]+\/[A-Za-z0-9_.-]+\/commit\/([a-f0-9]{40})(?:$|[?#/])/i);
|
|
501
|
+
return ((_a = match === null || match === void 0 ? void 0 : match[1]) === null || _a === void 0 ? void 0 : _a.toLowerCase()) || '';
|
|
502
|
+
}
|
|
503
|
+
function isFullGitCommitSha(value) {
|
|
504
|
+
return /^[a-f0-9]{40}$/i.test(cleanText(value, 120));
|
|
505
|
+
}
|
|
506
|
+
function isStrongRemoteChecksum(value) {
|
|
507
|
+
return /^[a-f0-9]{12,128}$/i.test(cleanText(value, 160));
|
|
508
|
+
}
|
|
509
|
+
function githubCommitProofBlockers(value, channel) {
|
|
510
|
+
var blockers = [];
|
|
511
|
+
var sourceCommitSha = cleanText(value.sourceCommitSha, 120);
|
|
512
|
+
var githubCommitUrl = cleanText(value.githubCommitUrl, 500);
|
|
513
|
+
var gitCommitStatus = cleanText(value.gitCommitStatus, 160);
|
|
514
|
+
var remoteCommitProofStatus = cleanText(value.gitPushStatus || value.gitCommitStatus, 160);
|
|
515
|
+
var urlCommitSha = extractGithubCommitSha(githubCommitUrl);
|
|
516
|
+
if (!sourceCommitSha || !githubCommitUrl) {
|
|
517
|
+
blockers.push("".concat(channel, " hotfix requires sourceCommitSha, githubCommitUrl, and passed gitPushStatus so live hotfixes are backed by a GitHub commit pushed before continuation."));
|
|
518
|
+
return blockers;
|
|
519
|
+
}
|
|
520
|
+
if (!isFullGitCommitSha(sourceCommitSha)) {
|
|
521
|
+
blockers.push("".concat(channel, " hotfix sourceCommitSha must be a full 40-character git SHA."));
|
|
522
|
+
}
|
|
523
|
+
if (!urlCommitSha) {
|
|
524
|
+
blockers.push("".concat(channel, " hotfix githubCommitUrl must be a GitHub commit URL ending in a full 40-character git SHA."));
|
|
525
|
+
}
|
|
526
|
+
else if (isFullGitCommitSha(sourceCommitSha) && urlCommitSha !== sourceCommitSha.toLowerCase()) {
|
|
527
|
+
blockers.push("".concat(channel, " hotfix githubCommitUrl commit SHA must match sourceCommitSha."));
|
|
528
|
+
}
|
|
529
|
+
if (!remoteCommitProofStatus) {
|
|
530
|
+
blockers.push("".concat(channel, " hotfix requires passed gitPushStatus or gitCommitStatus so the manager knows the hotfix commit is present on GitHub before continuation."));
|
|
531
|
+
}
|
|
532
|
+
else if (!hotfixStatusPassed(remoteCommitProofStatus)) {
|
|
533
|
+
blockers.push("".concat(channel, " hotfix gitPushStatus or gitCommitStatus must be passed before continuation."));
|
|
534
|
+
}
|
|
535
|
+
if (gitCommitStatus && gitCommitStatus !== remoteCommitProofStatus && !hotfixStatusPassed(gitCommitStatus)) {
|
|
536
|
+
blockers.push("".concat(channel, " hotfix gitCommitStatus must be passed when provided."));
|
|
537
|
+
}
|
|
538
|
+
return blockers;
|
|
539
|
+
}
|
|
540
|
+
function evaluateResolveIOAIManagerHotfixGitProof(value, channelHint) {
|
|
541
|
+
if (channelHint === void 0) { channelHint = ''; }
|
|
542
|
+
var normalized = normalizeResolveIOAIManagerHotfixEvidence(value);
|
|
543
|
+
var source = (normalized || cleanObject(value));
|
|
544
|
+
var channel = (channelHint || (normalized === null || normalized === void 0 ? void 0 : normalized.channel) || source.channel || '');
|
|
545
|
+
var required = hotfixRequiresGithubCommit(channel);
|
|
546
|
+
var sourceCommitSha = cleanText(source.sourceCommitSha || source.source_commit_sha || source.gitCommitSha || source.git_commit_sha || source.commitSha || source.commit_sha, 120);
|
|
547
|
+
var githubCommitUrl = cleanText(source.githubCommitUrl || source.github_commit_url || source.gitCommitUrl || source.git_commit_url || source.commitUrl || source.commit_url, 500);
|
|
548
|
+
var githubCommitSha = extractGithubCommitSha(githubCommitUrl);
|
|
549
|
+
var gitCommitStatus = cleanText(source.gitCommitStatus || source.git_commit_status || source.githubCommitStatus || source.github_commit_status, 160);
|
|
550
|
+
var gitPushStatus = cleanText(source.gitPushStatus || source.git_push_status || source.githubPushStatus || source.github_push_status || source.githubCommitReachableStatus || source.github_commit_reachable_status || gitCommitStatus, 160);
|
|
551
|
+
var blockers = required
|
|
552
|
+
? githubCommitProofBlockers({
|
|
553
|
+
channel: channel,
|
|
554
|
+
target: (normalized === null || normalized === void 0 ? void 0 : normalized.target) || {},
|
|
555
|
+
sourceCommitSha: sourceCommitSha,
|
|
556
|
+
githubCommitUrl: githubCommitUrl,
|
|
557
|
+
gitCommitStatus: gitCommitStatus,
|
|
558
|
+
gitPushStatus: gitPushStatus
|
|
559
|
+
}, channel)
|
|
560
|
+
: [];
|
|
561
|
+
var status = !required
|
|
562
|
+
? 'not_required'
|
|
563
|
+
: (!sourceCommitSha || !githubCommitUrl || !gitPushStatus)
|
|
564
|
+
? 'missing'
|
|
565
|
+
: blockers.length
|
|
566
|
+
? 'invalid'
|
|
567
|
+
: 'passed';
|
|
568
|
+
var passed = !required || status === 'passed';
|
|
569
|
+
return {
|
|
570
|
+
required: required,
|
|
571
|
+
status: status,
|
|
572
|
+
passed: passed,
|
|
573
|
+
managerMustCommitBeforeHotfix: required && !passed,
|
|
574
|
+
channel: channel,
|
|
575
|
+
sourceCommitSha: sourceCommitSha,
|
|
576
|
+
githubCommitUrl: githubCommitUrl,
|
|
577
|
+
githubCommitSha: githubCommitSha,
|
|
578
|
+
gitCommitStatus: gitCommitStatus,
|
|
579
|
+
gitPushStatus: gitPushStatus,
|
|
580
|
+
blockers: blockers,
|
|
581
|
+
nextCommands: required && !passed
|
|
582
|
+
? ['commit_and_push_hotfix_to_github', 'verify_github_commit_url_and_push_status', 'record_hotfix_evidence']
|
|
583
|
+
: [],
|
|
584
|
+
requiredEvidence: required
|
|
585
|
+
? ['full 40-character sourceCommitSha', 'matching GitHub commit URL', 'passed gitPushStatus or gitCommitStatus']
|
|
586
|
+
: []
|
|
587
|
+
};
|
|
209
588
|
}
|
|
210
589
|
function validateResolveIOAIManagerHotfixEvidence(value, options) {
|
|
211
590
|
var _a, _b, _c, _d;
|
|
@@ -224,6 +603,7 @@ function validateResolveIOAIManagerHotfixEvidence(value, options) {
|
|
|
224
603
|
hotfixSatisfied: false,
|
|
225
604
|
requiredEvidence: ((_b = (_a = policy === null || policy === void 0 ? void 0 : policy.hotfixPlan) === null || _a === void 0 ? void 0 : _a.steps) === null || _b === void 0 ? void 0 : _b.flatMap(function (step) { return step.requiredEvidence; })) || [],
|
|
226
605
|
successEvidence: ((_d = (_c = policy === null || policy === void 0 ? void 0 : policy.hotfixPlan) === null || _c === void 0 ? void 0 : _c.steps) === null || _d === void 0 ? void 0 : _d.flatMap(function (step) { return step.successEvidence; })) || [],
|
|
606
|
+
githubCommitGuard: evaluateResolveIOAIManagerHotfixGitProof(value),
|
|
227
607
|
policy: policy,
|
|
228
608
|
nextAction: 'record_hotfix_evidence'
|
|
229
609
|
};
|
|
@@ -237,20 +617,24 @@ function validateResolveIOAIManagerHotfixEvidence(value, options) {
|
|
|
237
617
|
var successEvidence = (step === null || step === void 0 ? void 0 : step.successEvidence) || [];
|
|
238
618
|
var policyAllowsFullDeploy = (policy === null || policy === void 0 ? void 0 : policy.fullDeployAllowed) === true;
|
|
239
619
|
var policyBlocksDuplicate = (policy === null || policy === void 0 ? void 0 : policy.duplicateDeployBlocked) === true || (policy === null || policy === void 0 ? void 0 : policy.duplicatePublishBlocked) === true;
|
|
620
|
+
var githubCommitGuard = evaluateResolveIOAIManagerHotfixGitProof(normalized, channel);
|
|
240
621
|
if (normalized.fullDeployRequested && !policyAllowsFullDeploy && channel !== 'force_deploy_review' && channel !== 'new_artifact_deploy') {
|
|
241
622
|
blockers.push('Full deploy requested but hotfix-first policy does not allow a full deploy for this release state.');
|
|
242
623
|
}
|
|
243
624
|
if (normalized.fullDeployRequested && policyBlocksDuplicate && !normalized.forceDeployReason && channel !== 'force_deploy_review') {
|
|
244
625
|
blockers.push('Duplicate deploy/publish fingerprint requires force deploy/publish evidence before any full deploy.');
|
|
245
626
|
}
|
|
246
|
-
if (
|
|
247
|
-
|
|
627
|
+
if (githubCommitGuard.required) {
|
|
628
|
+
blockers.push.apply(blockers, __spreadArray([], __read(githubCommitGuard.blockers), false));
|
|
248
629
|
}
|
|
249
630
|
if (channel === 'backend_js') {
|
|
250
631
|
pushMissing(blockers, !!normalized.compiledArtifactPath, 'Backend JS hotfix requires compiledArtifactPath.');
|
|
251
632
|
pushMissing(blockers, !!target.host, 'Backend JS hotfix requires target.host.');
|
|
252
633
|
pushMissing(blockers, !!target.path, 'Backend JS hotfix requires target.path.');
|
|
253
634
|
pushMissing(blockers, !!(normalized.remoteChecksumAfter || normalized.remoteChecksum), 'Backend JS hotfix requires remote checksum after replacement.');
|
|
635
|
+
if ((normalized.remoteChecksumAfter || normalized.remoteChecksum) && !isStrongRemoteChecksum(normalized.remoteChecksumAfter || normalized.remoteChecksum || '')) {
|
|
636
|
+
blockers.push('Backend JS hotfix remote checksum after replacement must be a strong hex checksum, not a label or placeholder.');
|
|
637
|
+
}
|
|
254
638
|
pushMissing(blockers, !!(normalized.restartEvidence || normalized.serviceRestartEvidence), 'Backend JS hotfix requires restart evidence.');
|
|
255
639
|
pushMissing(blockers, hotfixStatusPassed(normalized.healthCheckStatus), 'Backend JS hotfix requires passed healthCheckStatus.');
|
|
256
640
|
pushMissing(blockers, hotfixStatusPassed(normalized.selfTestStatus), 'Backend JS hotfix requires passed selfTestStatus.');
|
|
@@ -342,21 +726,228 @@ function validateResolveIOAIManagerHotfixEvidence(value, options) {
|
|
|
342
726
|
requiredEvidence: requiredEvidence,
|
|
343
727
|
successEvidence: successEvidence,
|
|
344
728
|
normalized: normalized,
|
|
729
|
+
githubCommitGuard: githubCommitGuard,
|
|
345
730
|
policy: policy,
|
|
346
731
|
nextAction: nextAction
|
|
347
732
|
};
|
|
348
733
|
}
|
|
349
|
-
function
|
|
734
|
+
function mergeHotfixEvidenceRecordInput(input) {
|
|
735
|
+
var e_3, _a;
|
|
736
|
+
var merged = __assign({}, cleanObject(input.evidence));
|
|
737
|
+
var directFields = [
|
|
738
|
+
'channel',
|
|
739
|
+
'status',
|
|
740
|
+
'target',
|
|
741
|
+
'compiledArtifactPath',
|
|
742
|
+
'builtDistPath',
|
|
743
|
+
'remoteChecksumBefore',
|
|
744
|
+
'remoteChecksumAfter',
|
|
745
|
+
'remoteChecksum',
|
|
746
|
+
'restartEvidence',
|
|
747
|
+
'healthCheckStatus',
|
|
748
|
+
'selfTestStatus',
|
|
749
|
+
'releaseGateStatus',
|
|
750
|
+
's3UploadResult',
|
|
751
|
+
'cloudfrontInvalidationId',
|
|
752
|
+
'publicProof',
|
|
753
|
+
'configChangeEvidence',
|
|
754
|
+
'seedDataEvidence',
|
|
755
|
+
'cacheInvalidationEvidence',
|
|
756
|
+
'serviceRestartEvidence',
|
|
757
|
+
'releaseArtifactFingerprint',
|
|
758
|
+
'lastReleaseArtifactFingerprint',
|
|
759
|
+
'sourceCommitSha',
|
|
760
|
+
'githubCommitUrl',
|
|
761
|
+
'gitCommitStatus',
|
|
762
|
+
'gitPushStatus',
|
|
763
|
+
'committedAt',
|
|
764
|
+
'forceDeployReason',
|
|
765
|
+
'hotfixCannotResolveReason',
|
|
766
|
+
'fullDeployRequested',
|
|
767
|
+
'recordedAt'
|
|
768
|
+
];
|
|
769
|
+
try {
|
|
770
|
+
for (var directFields_1 = __values(directFields), directFields_1_1 = directFields_1.next(); !directFields_1_1.done; directFields_1_1 = directFields_1.next()) {
|
|
771
|
+
var field = directFields_1_1.value;
|
|
772
|
+
var value = input[field];
|
|
773
|
+
if (value !== undefined && value !== null && value !== '') {
|
|
774
|
+
merged[field] = value;
|
|
775
|
+
}
|
|
776
|
+
}
|
|
777
|
+
}
|
|
778
|
+
catch (e_3_1) { e_3 = { error: e_3_1 }; }
|
|
779
|
+
finally {
|
|
780
|
+
try {
|
|
781
|
+
if (directFields_1_1 && !directFields_1_1.done && (_a = directFields_1.return)) _a.call(directFields_1);
|
|
782
|
+
}
|
|
783
|
+
finally { if (e_3) throw e_3.error; }
|
|
784
|
+
}
|
|
785
|
+
return merged;
|
|
786
|
+
}
|
|
787
|
+
function resolveHotfixEvidenceRequiredFields(channel) {
|
|
788
|
+
var fields = ['channel'];
|
|
789
|
+
if (hotfixRequiresGithubCommit(channel)) {
|
|
790
|
+
fields.push('sourceCommitSha', 'githubCommitUrl', 'gitPushStatus');
|
|
791
|
+
}
|
|
792
|
+
if (channel === 'backend_js') {
|
|
793
|
+
fields.push('compiledArtifactPath', 'target.host', 'target.path', 'remoteChecksumAfter', 'restartEvidence', 'healthCheckStatus', 'selfTestStatus');
|
|
794
|
+
}
|
|
795
|
+
else if (channel === 'static_ui') {
|
|
796
|
+
fields.push('builtDistPath', 'target.bucket', 'target.distributionId', 's3UploadResult', 'cloudfrontInvalidationId', 'publicProof');
|
|
797
|
+
}
|
|
798
|
+
else if (channel === 'config') {
|
|
799
|
+
fields.push('target.configKey', 'configChangeEvidence', 'releaseGateStatus');
|
|
800
|
+
}
|
|
801
|
+
else if (channel === 'seed_data') {
|
|
802
|
+
fields.push('target.seedKey', 'seedDataEvidence', 'releaseGateStatus');
|
|
803
|
+
}
|
|
804
|
+
else if (channel === 'cache_invalidation') {
|
|
805
|
+
fields.push('target.cacheKey', 'cacheInvalidationEvidence', 'releaseGateStatus_or_healthCheckStatus');
|
|
806
|
+
}
|
|
807
|
+
else if (channel === 'service_restart') {
|
|
808
|
+
fields.push('target.processName', 'serviceRestartEvidence', 'healthCheckStatus', 'selfTestStatus');
|
|
809
|
+
}
|
|
810
|
+
else if (channel === 'release_artifact') {
|
|
811
|
+
fields.push('releaseArtifactFingerprint', 'releaseGateStatus');
|
|
812
|
+
}
|
|
813
|
+
else if (channel === 'new_artifact_deploy') {
|
|
814
|
+
fields.push('releaseArtifactFingerprint', 'lastReleaseArtifactFingerprint', 'releaseGateStatus');
|
|
815
|
+
}
|
|
816
|
+
else if (channel === 'artifact_build') {
|
|
817
|
+
fields.push('releaseArtifactFingerprint');
|
|
818
|
+
}
|
|
819
|
+
else if (channel === 'force_deploy_review') {
|
|
820
|
+
fields.push('forceDeployReason', 'hotfixCannotResolveReason');
|
|
821
|
+
}
|
|
822
|
+
return Array.from(new Set(fields));
|
|
823
|
+
}
|
|
824
|
+
function hotfixEvidenceFieldPresent(evidence, field) {
|
|
825
|
+
if (!evidence) {
|
|
826
|
+
return false;
|
|
827
|
+
}
|
|
828
|
+
var target = evidence.target || {};
|
|
829
|
+
switch (field) {
|
|
830
|
+
case 'channel':
|
|
831
|
+
return !!evidence.channel;
|
|
832
|
+
case 'sourceCommitSha':
|
|
833
|
+
return isFullGitCommitSha(evidence.sourceCommitSha || '');
|
|
834
|
+
case 'githubCommitUrl':
|
|
835
|
+
return !!extractGithubCommitSha(evidence.githubCommitUrl || '');
|
|
836
|
+
case 'gitPushStatus':
|
|
837
|
+
return hotfixStatusPassed(evidence.gitPushStatus) || hotfixStatusPassed(evidence.gitCommitStatus);
|
|
838
|
+
case 'compiledArtifactPath':
|
|
839
|
+
return !!cleanText(evidence.compiledArtifactPath, 500);
|
|
840
|
+
case 'builtDistPath':
|
|
841
|
+
return !!cleanText(evidence.builtDistPath, 500);
|
|
842
|
+
case 'remoteChecksumAfter':
|
|
843
|
+
return !!cleanText(evidence.remoteChecksumAfter || evidence.remoteChecksum, 160);
|
|
844
|
+
case 'restartEvidence':
|
|
845
|
+
return !!cleanText(evidence.restartEvidence || evidence.serviceRestartEvidence, 1000);
|
|
846
|
+
case 'serviceRestartEvidence':
|
|
847
|
+
return !!cleanText(evidence.serviceRestartEvidence || evidence.restartEvidence, 1000);
|
|
848
|
+
case 'healthCheckStatus':
|
|
849
|
+
return hotfixStatusPassed(evidence.healthCheckStatus);
|
|
850
|
+
case 'selfTestStatus':
|
|
851
|
+
return hotfixStatusPassed(evidence.selfTestStatus);
|
|
852
|
+
case 'releaseGateStatus':
|
|
853
|
+
return hotfixStatusPassed(evidence.releaseGateStatus);
|
|
854
|
+
case 'releaseGateStatus_or_healthCheckStatus':
|
|
855
|
+
return hotfixStatusPassed(evidence.releaseGateStatus) || hotfixStatusPassed(evidence.healthCheckStatus);
|
|
856
|
+
case 's3UploadResult':
|
|
857
|
+
return !!cleanText(evidence.s3UploadResult, 1000);
|
|
858
|
+
case 'cloudfrontInvalidationId':
|
|
859
|
+
return !!cleanText(evidence.cloudfrontInvalidationId, 240);
|
|
860
|
+
case 'publicProof':
|
|
861
|
+
return !!cleanText(evidence.publicProof, 1000);
|
|
862
|
+
case 'configChangeEvidence':
|
|
863
|
+
return !!cleanText(evidence.configChangeEvidence, 1000);
|
|
864
|
+
case 'seedDataEvidence':
|
|
865
|
+
return !!cleanText(evidence.seedDataEvidence, 1000);
|
|
866
|
+
case 'cacheInvalidationEvidence':
|
|
867
|
+
return !!cleanText(evidence.cacheInvalidationEvidence, 1000);
|
|
868
|
+
case 'releaseArtifactFingerprint':
|
|
869
|
+
return !!cleanText(evidence.releaseArtifactFingerprint, 240);
|
|
870
|
+
case 'lastReleaseArtifactFingerprint':
|
|
871
|
+
return !!cleanText(evidence.lastReleaseArtifactFingerprint, 240);
|
|
872
|
+
case 'forceDeployReason':
|
|
873
|
+
return !!cleanText(evidence.forceDeployReason, 1000);
|
|
874
|
+
case 'hotfixCannotResolveReason':
|
|
875
|
+
return !!cleanText(evidence.hotfixCannotResolveReason, 1000);
|
|
876
|
+
case 'target.host':
|
|
877
|
+
return !!cleanText(target.host, 200);
|
|
878
|
+
case 'target.path':
|
|
879
|
+
return !!cleanText(target.path, 500);
|
|
880
|
+
case 'target.bucket':
|
|
881
|
+
return !!cleanText(target.bucket, 200);
|
|
882
|
+
case 'target.distributionId':
|
|
883
|
+
return !!cleanText(target.distributionId, 200);
|
|
884
|
+
case 'target.configKey':
|
|
885
|
+
return !!cleanText(target.configKey, 200);
|
|
886
|
+
case 'target.seedKey':
|
|
887
|
+
return !!cleanText(target.seedKey, 200);
|
|
888
|
+
case 'target.cacheKey':
|
|
889
|
+
return !!cleanText(target.cacheKey, 200);
|
|
890
|
+
case 'target.processName':
|
|
891
|
+
return !!cleanText(target.processName, 200);
|
|
892
|
+
default:
|
|
893
|
+
return false;
|
|
894
|
+
}
|
|
895
|
+
}
|
|
896
|
+
function buildResolveIOAIManagerHotfixEvidenceRecord(input) {
|
|
350
897
|
var _a, _b;
|
|
351
898
|
if (input === void 0) { input = {}; }
|
|
899
|
+
var merged = mergeHotfixEvidenceRecordInput(input);
|
|
900
|
+
var normalized = normalizeResolveIOAIManagerHotfixEvidence(merged, input.policy);
|
|
901
|
+
var validation = validateResolveIOAIManagerHotfixEvidence(merged, { policy: input.policy });
|
|
902
|
+
var channel = validation.channel || (normalized === null || normalized === void 0 ? void 0 : normalized.channel) || ((_b = (_a = input.policy) === null || _a === void 0 ? void 0 : _a.hotfixPlan) === null || _b === void 0 ? void 0 : _b.recommendedChannel) || '';
|
|
903
|
+
var requiredFields = resolveHotfixEvidenceRequiredFields(channel);
|
|
904
|
+
var missingFields = requiredFields.filter(function (field) { return !hotfixEvidenceFieldPresent(normalized, field); });
|
|
905
|
+
var recordedAt = cleanDateString(input.now || (normalized === null || normalized === void 0 ? void 0 : normalized.recordedAt) || new Date());
|
|
906
|
+
var githubCommitGuard = validation.githubCommitGuard || evaluateResolveIOAIManagerHotfixGitProof(normalized || merged, channel);
|
|
907
|
+
return {
|
|
908
|
+
recordId: cleanText(input.recordId, 160) || "hotfix-".concat(fingerprintResolveIOAIManagerBlocker("".concat(channel, ":").concat(githubCommitGuard.sourceCommitSha, ":").concat(recordedAt))),
|
|
909
|
+
recordedAt: recordedAt,
|
|
910
|
+
recordedBy: cleanText(input.recordedBy || 'manager', 160),
|
|
911
|
+
source: cleanText(input.source || 'unknown', 80),
|
|
912
|
+
reason: cleanText(input.reason, 1000),
|
|
913
|
+
channel: channel,
|
|
914
|
+
status: validation.status,
|
|
915
|
+
nextAction: validation.nextAction,
|
|
916
|
+
valid: validation.valid,
|
|
917
|
+
hotfixSatisfied: validation.hotfixSatisfied,
|
|
918
|
+
fullDeployAllowed: validation.fullDeployAllowed,
|
|
919
|
+
fullDeployBlocked: validation.fullDeployBlocked,
|
|
920
|
+
requiredFields: requiredFields,
|
|
921
|
+
missingFields: missingFields,
|
|
922
|
+
evidence: normalized,
|
|
923
|
+
validation: validation,
|
|
924
|
+
sourceCommitSha: githubCommitGuard.sourceCommitSha,
|
|
925
|
+
githubCommitUrl: githubCommitGuard.githubCommitUrl,
|
|
926
|
+
gitPushStatus: githubCommitGuard.gitPushStatus,
|
|
927
|
+
githubCommitRequired: githubCommitGuard.required,
|
|
928
|
+
githubCommitProofPassed: githubCommitGuard.passed,
|
|
929
|
+
commitProofStatus: githubCommitGuard.status,
|
|
930
|
+
managerMustCommitBeforeHotfix: githubCommitGuard.managerMustCommitBeforeHotfix,
|
|
931
|
+
githubCommitGuard: githubCommitGuard,
|
|
932
|
+
readyForReleaseGate: validation.valid === true && validation.nextAction === 'rerun_release_gate',
|
|
933
|
+
readyForContinuation: validation.valid === true && validation.hotfixSatisfied === true && hotfixStatusPassed(normalized === null || normalized === void 0 ? void 0 : normalized.releaseGateStatus)
|
|
934
|
+
};
|
|
935
|
+
}
|
|
936
|
+
function decideResolveIOAIManagerHotfixContinuation(input) {
|
|
937
|
+
var e_4, _a;
|
|
938
|
+
var _b, _c;
|
|
939
|
+
if (input === void 0) { input = {}; }
|
|
352
940
|
var validation = validateResolveIOAIManagerHotfixEvidence(input.evidence, { policy: input.policy });
|
|
353
941
|
var failureClass = cleanText(input.failureClass, 120) || 'release';
|
|
354
|
-
var blockerText = cleanText(input.blocker || validation.blockers.join('; ') || ((
|
|
942
|
+
var blockerText = cleanText(input.blocker || validation.blockers.join('; ') || ((_b = validation.normalized) === null || _b === void 0 ? void 0 : _b.hotfixCannotResolveReason), 1000);
|
|
355
943
|
var blockerFingerprint = fingerprintResolveIOAIManagerBlocker(blockerText || "".concat(validation.channel, ":").concat(validation.status, ":").concat(validation.nextAction));
|
|
356
944
|
var baseBlockers = __spreadArray([], __read(validation.blockers), false);
|
|
945
|
+
var githubCommitGuard = validation.githubCommitGuard || evaluateResolveIOAIManagerHotfixGitProof(input.evidence, validation.channel);
|
|
946
|
+
var needsGithubCommitProof = githubCommitGuard.managerMustCommitBeforeHotfix
|
|
947
|
+
|| validation.blockers.some(function (blocker) { return /sourceCommitSha|githubCommitUrl|gitPushStatus|gitCommitStatus|GitHub commit|pushed/i.test(blocker); });
|
|
357
948
|
var repeatedFailure = input.repeatedFailure === true;
|
|
358
949
|
var releaseGatePassed = input.releaseGatePassed === true
|
|
359
|
-
|| hotfixStatusPassed((
|
|
950
|
+
|| hotfixStatusPassed((_c = validation.normalized) === null || _c === void 0 ? void 0 : _c.releaseGateStatus);
|
|
360
951
|
var action = validation.nextAction;
|
|
361
952
|
var canContinueRun = false;
|
|
362
953
|
var canRunFullDeploy = validation.fullDeployAllowed;
|
|
@@ -364,13 +955,38 @@ function decideResolveIOAIManagerHotfixContinuation(input) {
|
|
|
364
955
|
var shouldPark = false;
|
|
365
956
|
var reason = '';
|
|
366
957
|
var nextCommands = [];
|
|
367
|
-
if (
|
|
958
|
+
if (githubCommitGuard.managerMustCommitBeforeHotfix) {
|
|
959
|
+
action = 'record_hotfix_evidence';
|
|
960
|
+
reason = githubCommitGuard.blockers.length
|
|
961
|
+
? "Manager hotfix cannot continue until the hotfix is committed and pushed: ".concat(githubCommitGuard.blockers.join('; '))
|
|
962
|
+
: 'Manager hotfix cannot continue until sourceCommitSha, githubCommitUrl, and passed gitPushStatus prove the hotfix is on GitHub.';
|
|
963
|
+
nextCommands.push.apply(nextCommands, __spreadArray(__spreadArray([], __read(githubCommitGuard.nextCommands), false), ['rerun_hotfix_evidence_validator'], false));
|
|
964
|
+
try {
|
|
965
|
+
for (var _d = __values(githubCommitGuard.blockers), _e = _d.next(); !_e.done; _e = _d.next()) {
|
|
966
|
+
var blocker = _e.value;
|
|
967
|
+
if (!baseBlockers.includes(blocker)) {
|
|
968
|
+
baseBlockers.push(blocker);
|
|
969
|
+
}
|
|
970
|
+
}
|
|
971
|
+
}
|
|
972
|
+
catch (e_4_1) { e_4 = { error: e_4_1 }; }
|
|
973
|
+
finally {
|
|
974
|
+
try {
|
|
975
|
+
if (_e && !_e.done && (_a = _d.return)) _a.call(_d);
|
|
976
|
+
}
|
|
977
|
+
finally { if (e_4) throw e_4.error; }
|
|
978
|
+
}
|
|
979
|
+
}
|
|
980
|
+
else if (!validation.valid || validation.status === 'missing' || validation.status === 'incomplete') {
|
|
368
981
|
action = validation.nextAction === 'request_force_deploy_reason'
|
|
369
982
|
? 'request_force_deploy_reason'
|
|
370
983
|
: 'record_hotfix_evidence';
|
|
371
984
|
reason = validation.blockers.length
|
|
372
985
|
? "Hotfix evidence is not complete: ".concat(validation.blockers.join('; '))
|
|
373
986
|
: 'Hotfix evidence is missing; record the hotfix target, checksum, restart, health, and self-test proof before continuing.';
|
|
987
|
+
if (needsGithubCommitProof) {
|
|
988
|
+
nextCommands.push('commit_and_push_hotfix_to_github', 'verify_github_commit_url_and_push_status');
|
|
989
|
+
}
|
|
374
990
|
nextCommands.push('record_hotfix_evidence', 'rerun_hotfix_evidence_validator');
|
|
375
991
|
}
|
|
376
992
|
else if (validation.fullDeployAllowed) {
|
|
@@ -415,13 +1031,49 @@ function decideResolveIOAIManagerHotfixContinuation(input) {
|
|
|
415
1031
|
warnings: validation.warnings,
|
|
416
1032
|
requiredEvidence: validation.requiredEvidence,
|
|
417
1033
|
successEvidence: validation.successEvidence,
|
|
418
|
-
nextCommands: nextCommands,
|
|
1034
|
+
nextCommands: Array.from(new Set(nextCommands)),
|
|
419
1035
|
failureClass: failureClass,
|
|
420
1036
|
blockerFingerprint: blockerFingerprint,
|
|
1037
|
+
githubCommitGuard: githubCommitGuard,
|
|
421
1038
|
validation: validation,
|
|
422
1039
|
recordedAt: isoNow(input.now)
|
|
423
1040
|
};
|
|
424
1041
|
}
|
|
1042
|
+
function decideResolveIOAIManagerHotfixCommitGuard(input) {
|
|
1043
|
+
if (input === void 0) { input = {}; }
|
|
1044
|
+
var normalized = normalizeResolveIOAIManagerHotfixEvidence(input.evidence, input.policy);
|
|
1045
|
+
var validation = validateResolveIOAIManagerHotfixEvidence(input.evidence, { policy: input.policy });
|
|
1046
|
+
var githubCommitGuard = validation.githubCommitGuard || evaluateResolveIOAIManagerHotfixGitProof(input.evidence, validation.channel);
|
|
1047
|
+
var active = !!normalized || githubCommitGuard.required === true;
|
|
1048
|
+
var hotfixCommitBlockers = validation.blockers.filter(function (blocker) { return /sourceCommitSha|githubCommitUrl|gitPushStatus|gitCommitStatus|GitHub commit|pushed/i.test(blocker); });
|
|
1049
|
+
var blockers = Array.from(new Set(__spreadArray(__spreadArray([], __read((githubCommitGuard.blockers || [])), false), __read(hotfixCommitBlockers), false)));
|
|
1050
|
+
var blocked = active && (githubCommitGuard.managerMustCommitBeforeHotfix === true
|
|
1051
|
+
|| (githubCommitGuard.required === true && githubCommitGuard.passed !== true)
|
|
1052
|
+
|| hotfixCommitBlockers.length > 0);
|
|
1053
|
+
var nextCommands = blocked
|
|
1054
|
+
? Array.from(new Set(__spreadArray(__spreadArray([], __read((githubCommitGuard.nextCommands || [])), false), [
|
|
1055
|
+
'commit_and_push_hotfix_to_github',
|
|
1056
|
+
'verify_github_commit_url_and_push_status',
|
|
1057
|
+
'record_hotfix_evidence'
|
|
1058
|
+
], false)))
|
|
1059
|
+
: [];
|
|
1060
|
+
return {
|
|
1061
|
+
active: active,
|
|
1062
|
+
blocked: blocked,
|
|
1063
|
+
reason: blocked
|
|
1064
|
+
? (blockers.length
|
|
1065
|
+
? "Hotfix continuation is blocked until GitHub commit proof is recorded: ".concat(blockers.join('; '))
|
|
1066
|
+
: 'Hotfix continuation is blocked until sourceCommitSha, githubCommitUrl, and passed gitPushStatus prove the hotfix is pushed to GitHub.')
|
|
1067
|
+
: (active ? 'Hotfix GitHub commit proof is recorded.' : 'No hotfix commit guard is active.'),
|
|
1068
|
+
nextAction: blocked ? 'record_hotfix_evidence' : 'continue',
|
|
1069
|
+
channel: validation.channel || githubCommitGuard.channel || '',
|
|
1070
|
+
blockers: blockers,
|
|
1071
|
+
nextCommands: nextCommands,
|
|
1072
|
+
requiredEvidence: githubCommitGuard.requiredEvidence,
|
|
1073
|
+
githubCommitGuard: githubCommitGuard,
|
|
1074
|
+
validation: validation
|
|
1075
|
+
};
|
|
1076
|
+
}
|
|
425
1077
|
function releaseStatusIsBlocked(value) {
|
|
426
1078
|
return /fail|error|blocked|missing|empty|not ready|not_ready|denied|invalid|timeout|stale/i.test(value);
|
|
427
1079
|
}
|
|
@@ -563,17 +1215,17 @@ function buildHotfixFirstReleasePlan(input) {
|
|
|
563
1215
|
steps: [
|
|
564
1216
|
hotfixStep('static_ui_hotfix', 'Static UI hotfix', 'static_ui', {
|
|
565
1217
|
safeToAutoRun: true,
|
|
566
|
-
requiredEvidence: ['built dist path', 'target S3 bucket and CloudFront distribution', 'changed frontend bundle or asset list'],
|
|
567
|
-
successEvidence: ['S3 upload result', 'CloudFront invalidation id', 'public bundle contains expected hotfix marker']
|
|
1218
|
+
requiredEvidence: ['sourceCommitSha, githubCommitUrl, and passed gitPushStatus', 'built dist path', 'target S3 bucket and CloudFront distribution', 'changed frontend bundle or asset list'],
|
|
1219
|
+
successEvidence: ['GitHub commit and push proof', 'S3 upload result', 'CloudFront invalidation id', 'public bundle contains expected hotfix marker']
|
|
568
1220
|
}),
|
|
569
1221
|
hotfixStep('backend_js_hotfix', 'Backend JS hotfix', 'backend_js', {
|
|
570
|
-
requiredEvidence: ['compiled JS artifact path', 'target backend host', 'diff limited to runner/operator code'],
|
|
571
|
-
successEvidence: ['remote file checksum', 'service restart or process reload evidence', 'self-test passes']
|
|
1222
|
+
requiredEvidence: ['sourceCommitSha, githubCommitUrl, and passed gitPushStatus', 'compiled JS artifact path', 'target backend host', 'diff limited to runner/operator code'],
|
|
1223
|
+
successEvidence: ['GitHub commit and push proof', 'remote file checksum', 'service restart or process reload evidence', 'self-test passes']
|
|
572
1224
|
}),
|
|
573
1225
|
hotfixStep('config_seed_cache_restart', 'Config, seed, cache, or restart repair', 'config', {
|
|
574
1226
|
safeToAutoRun: true,
|
|
575
|
-
requiredEvidence: ['exact config/seed/cache key or process name', 'why no product artifact changed'],
|
|
576
|
-
successEvidence: ['release gate rerun result', 'operator console release snapshot refreshed']
|
|
1227
|
+
requiredEvidence: ['sourceCommitSha, githubCommitUrl, and passed gitPushStatus', 'exact config/seed/cache key or process name', 'why no product artifact changed'],
|
|
1228
|
+
successEvidence: ['GitHub commit and push proof', 'release gate rerun result', 'operator console release snapshot refreshed']
|
|
577
1229
|
})
|
|
578
1230
|
],
|
|
579
1231
|
acceptanceEvidence: commonAcceptance,
|
|
@@ -1030,6 +1682,48 @@ function recoveryActionAutoRunnable(mode, probe) {
|
|
|
1030
1682
|
}
|
|
1031
1683
|
return probe.steps.some(function (step) { return step.commandHint || step.kind === 'rerun_same_gate' || step.kind === 'release_status' || step.kind === 'diff_scope_check'; });
|
|
1032
1684
|
}
|
|
1685
|
+
function recoveryActionCostCeilingUsd(mode) {
|
|
1686
|
+
var _a;
|
|
1687
|
+
var map = {
|
|
1688
|
+
advance: 0,
|
|
1689
|
+
collect_evidence: 0.25,
|
|
1690
|
+
read_only_diagnosis: 1,
|
|
1691
|
+
repair_infra: 0.5,
|
|
1692
|
+
repair_compile: 1.5,
|
|
1693
|
+
repair_journey_contract: 2,
|
|
1694
|
+
repair_business_assertion: 1.5,
|
|
1695
|
+
repair_release: 0.75,
|
|
1696
|
+
targeted_product_repair: 5,
|
|
1697
|
+
manual_review: 0,
|
|
1698
|
+
continue_gate: 0
|
|
1699
|
+
};
|
|
1700
|
+
return (_a = map[mode]) !== null && _a !== void 0 ? _a : 1;
|
|
1701
|
+
}
|
|
1702
|
+
function recoveryActionRequiredStateTransition(mode) {
|
|
1703
|
+
var map = {
|
|
1704
|
+
advance: 'current gate advances without repair after existing proof is accepted',
|
|
1705
|
+
collect_evidence: 'blockerFingerprint or evidenceHash changes with material proof, or run remains parked',
|
|
1706
|
+
read_only_diagnosis: 'diagnosis gate becomes valid or records a blocked-reproduction reason',
|
|
1707
|
+
repair_infra: 'infra preflight changes from failed/blocked to passed, or records a new infra blocker',
|
|
1708
|
+
repair_compile: 'compile/startup status changes from failed to passed, or records a new compile blocker',
|
|
1709
|
+
repair_journey_contract: 'journey contract validates with first/next/last workflow proof',
|
|
1710
|
+
repair_business_assertion: 'business assertion changes from missing/failed to passed with artifact proof',
|
|
1711
|
+
repair_release: 'hotfix/release gate changes from blocked to passed, rerun_release_gate, or parked manual',
|
|
1712
|
+
targeted_product_repair: 'owner-scoped diff is produced and deterministic proof advances to QA',
|
|
1713
|
+
manual_review: 'operator records one explicit decision',
|
|
1714
|
+
continue_gate: 'current gate records accepted proof and advances'
|
|
1715
|
+
};
|
|
1716
|
+
return map[mode] || 'runner records a validated state transition before continuing';
|
|
1717
|
+
}
|
|
1718
|
+
function recoveryActionProofRequiredBeforeContinuation(mode) {
|
|
1719
|
+
return mode !== 'advance' && mode !== 'continue_gate' && mode !== 'manual_review';
|
|
1720
|
+
}
|
|
1721
|
+
function recoveryActionExitCriteria(input) {
|
|
1722
|
+
return Array.from(new Set(__spreadArray(__spreadArray([
|
|
1723
|
+
"exact dispatch action ".concat(input.dispatchAction, " completed or was parked"),
|
|
1724
|
+
input.requiredStateTransition
|
|
1725
|
+
], __read((recoveryActionProofRequiredBeforeContinuation(input.mode) ? ['do not continue runner until required proof artifact is attached'] : [])), false), __read(input.stopWhen), false).map(function (entry) { return cleanText(entry, 500); }).filter(Boolean))).slice(0, 30);
|
|
1726
|
+
}
|
|
1033
1727
|
function buildResolveIOAIManagerRecoveryActionPacket(input) {
|
|
1034
1728
|
var checkpoint = input.checkpoint;
|
|
1035
1729
|
var probe = input.probe || buildResolveIOAIManagerRecoveryEvidenceProbe({
|
|
@@ -1061,6 +1755,15 @@ function buildResolveIOAIManagerRecoveryActionPacket(input) {
|
|
|
1061
1755
|
publishStatus: checkpoint.lane
|
|
1062
1756
|
})
|
|
1063
1757
|
: undefined;
|
|
1758
|
+
var allowedDispatchAction = dispatchActionForMode(mode);
|
|
1759
|
+
var requiredStateTransition = recoveryActionRequiredStateTransition(mode);
|
|
1760
|
+
var proofRequiredBeforeContinuation = recoveryActionProofRequiredBeforeContinuation(mode);
|
|
1761
|
+
var exitCriteria = recoveryActionExitCriteria({
|
|
1762
|
+
mode: mode,
|
|
1763
|
+
dispatchAction: allowedDispatchAction,
|
|
1764
|
+
requiredStateTransition: requiredStateTransition,
|
|
1765
|
+
stopWhen: stopWhen
|
|
1766
|
+
});
|
|
1064
1767
|
var now = isoNow(input.now);
|
|
1065
1768
|
return __assign(__assign(__assign({ actionId: stableHash('mgr-action', {
|
|
1066
1769
|
checkpointId: checkpoint.checkpointId,
|
|
@@ -1068,13 +1771,13 @@ function buildResolveIOAIManagerRecoveryActionPacket(input) {
|
|
|
1068
1771
|
mode: mode,
|
|
1069
1772
|
evidenceHash: checkpoint.evidenceHash,
|
|
1070
1773
|
blockerFingerprint: checkpoint.blockerFingerprint
|
|
1071
|
-
}), 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'
|
|
1774
|
+
}), checkpointId: checkpoint.checkpointId, probeId: probe.probeId, recoveryClass: checkpoint.recoveryClass, mode: mode, singleActionOnly: true, allowedDispatchAction: allowedDispatchAction, 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'
|
|
1072
1775
|
? probe.objective
|
|
1073
|
-
: 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
|
|
1776
|
+
: 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', costCeilingUsd: recoveryActionCostCeilingUsd(mode), requiredStateTransition: requiredStateTransition, proofRequiredBeforeContinuation: proofRequiredBeforeContinuation, canResetLoopAfterEvidence: resetLoopWhen.length > 0, maxAttemptsBeforePark: checkpoint.maxAttemptsBeforePark, requiredArtifacts: probe.requiredArtifacts.slice(0, 20), nextCommands: releasePolicy
|
|
1074
1777
|
? Array.from(new Set(__spreadArray(__spreadArray([], __read(nextCommands), false), __read(releasePolicy.allowedActions), false))).slice(0, 12)
|
|
1075
1778
|
: nextCommands, successCriteria: releasePolicy
|
|
1076
1779
|
? Array.from(new Set(__spreadArray(__spreadArray([], __read(probe.acceptanceEvidence), false), __read(releasePolicy.requiredEvidence), false))).slice(0, 20)
|
|
1077
|
-
: probe.acceptanceEvidence.slice(0, 20), retryPolicy: {
|
|
1780
|
+
: probe.acceptanceEvidence.slice(0, 20), exitCriteria: exitCriteria, retryPolicy: {
|
|
1078
1781
|
allowImmediateRetry: checkpoint.status !== 'parked' && mode !== 'manual_review',
|
|
1079
1782
|
requireNewEvidence: requireNewEvidence,
|
|
1080
1783
|
resetLoopWhen: resetLoopWhen,
|
|
@@ -1111,6 +1814,7 @@ function buildRecoveryDispatchRecord(action, dispatchAction, status, reason, cur
|
|
|
1111
1814
|
}), actionId: action.actionId, checkpointId: action.checkpointId, probeId: action.probeId, mode: action.mode, dispatchAction: dispatchAction, status: status, evidenceHash: evidenceHash, blockerFingerprint: blockerFingerprint, productRepairAllowed: action.productRepairAllowed && dispatchAction === 'run_targeted_product_repair', expensiveModelAllowed: action.expensiveModelAllowed && dispatchAction !== 'run_evidence_probe', reason: reason, artifactPaths: artifactPaths }, (status === 'started' ? { startedAt: createdAt } : {})), (status === 'completed' ? { completedAt: createdAt } : {})), { createdAt: createdAt });
|
|
1112
1815
|
}
|
|
1113
1816
|
function decideResolveIOAIManagerRecoveryActionDispatch(input) {
|
|
1817
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m;
|
|
1114
1818
|
var action = input.action;
|
|
1115
1819
|
var history = Array.isArray(input.history) ? input.history.filter(Boolean).slice(-50) : [];
|
|
1116
1820
|
var current = input.current || {};
|
|
@@ -1128,6 +1832,7 @@ function decideResolveIOAIManagerRecoveryActionDispatch(input) {
|
|
|
1128
1832
|
};
|
|
1129
1833
|
}
|
|
1130
1834
|
var dispatchAction = dispatchActionForMode(action.mode);
|
|
1835
|
+
var allowedDispatchAction = action.allowedDispatchAction || dispatchAction;
|
|
1131
1836
|
var evidenceHash = current.evidenceHash || action.checkpointId || action.actionId;
|
|
1132
1837
|
var blockerFingerprint = resolveResolveIOAIManagerBlockerFingerprint(current, action.objective);
|
|
1133
1838
|
var sameActionHistory = history.filter(function (entry) { return entry.actionId === action.actionId; });
|
|
@@ -1137,11 +1842,20 @@ function decideResolveIOAIManagerRecoveryActionDispatch(input) {
|
|
|
1137
1842
|
var completedDispatch = sameEvidenceHistory.find(function (entry) { return entry.status === 'completed' || entry.status === 'failed'; });
|
|
1138
1843
|
var newEvidence = sameActionHistory.length > 0 && sameEvidenceHistory.length === 0;
|
|
1139
1844
|
var requiresNewEvidence = action.retryPolicy.requireNewEvidence === true;
|
|
1845
|
+
var sameEvidenceAlreadyAttempted = !!completedDispatch && requiresNewEvidence && !newEvidence;
|
|
1140
1846
|
var manualOnly = action.mode === 'manual_review' || !action.autoRunnable;
|
|
1141
1847
|
var productDispatch = dispatchAction === 'run_targeted_product_repair';
|
|
1142
1848
|
var expensiveDispatch = !['run_evidence_probe', 'advance', 'continue_gate', 'park_manual'].includes(dispatchAction);
|
|
1143
|
-
|
|
1144
|
-
|
|
1849
|
+
var evidenceAssessment = assessResolveIOAIManagerEvidenceChange(undefined, current, action.objective);
|
|
1850
|
+
var autonomyPolicy = input.autonomyPolicy
|
|
1851
|
+
? decideResolveIOAIManagerAutonomyPolicy(__assign(__assign({}, (input.autonomyPolicy || {})), { dispatchAction: dispatchAction, projectedActionCostUsd: (_b = (_a = input.autonomyPolicy) === null || _a === void 0 ? void 0 : _a.projectedActionCostUsd) !== null && _b !== void 0 ? _b : action.costCeilingUsd, newEvidence: (_d = (_c = input.autonomyPolicy) === null || _c === void 0 ? void 0 : _c.newEvidence) !== null && _d !== void 0 ? _d : newEvidence, materialEvidence: (_f = (_e = input.autonomyPolicy) === null || _e === void 0 ? void 0 : _e.materialEvidence) !== null && _f !== void 0 ? _f : evidenceAssessment.material, evidenceStrength: (_h = (_g = input.autonomyPolicy) === null || _g === void 0 ? void 0 : _g.evidenceStrength) !== null && _h !== void 0 ? _h : evidenceAssessment.strength, evidenceSignals: (_k = (_j = input.autonomyPolicy) === null || _j === void 0 ? void 0 : _j.evidenceSignals) !== null && _k !== void 0 ? _k : evidenceAssessment.signals, sameEvidenceAlreadyAttempted: (_m = (_l = input.autonomyPolicy) === null || _l === void 0 ? void 0 : _l.sameEvidenceAlreadyAttempted) !== null && _m !== void 0 ? _m : sameEvidenceAlreadyAttempted, operatorApproved: input.operatorApproved }))
|
|
1852
|
+
: undefined;
|
|
1853
|
+
var autonomyBlocksDispatch = !!autonomyPolicy && (autonomyPolicy.mode === 'monitor_only'
|
|
1854
|
+
|| (autonomyPolicy.requiresHumanApproval === true && input.operatorApproved !== true)
|
|
1855
|
+
|| (autonomyPolicy.canAutoDispatch !== true && input.operatorApproved !== true)
|
|
1856
|
+
|| (autonomyPolicy.blocked === true && autonomyPolicy.canManualDispatch !== true));
|
|
1857
|
+
if (autonomyBlocksDispatch) {
|
|
1858
|
+
var record_1 = buildRecoveryDispatchRecord(action, 'park_manual', 'parked', "recovery_dispatch_blocked_by_autonomy_policy:".concat((autonomyPolicy === null || autonomyPolicy === void 0 ? void 0 : autonomyPolicy.reason) || 'unknown'), current, input.now);
|
|
1145
1859
|
return {
|
|
1146
1860
|
dispatchAction: 'park_manual',
|
|
1147
1861
|
allowed: false,
|
|
@@ -1152,11 +1866,12 @@ function decideResolveIOAIManagerRecoveryActionDispatch(input) {
|
|
|
1152
1866
|
shouldRecordDispatch: true,
|
|
1153
1867
|
requiresNewEvidence: requiresNewEvidence,
|
|
1154
1868
|
newEvidence: newEvidence,
|
|
1869
|
+
autonomyPolicy: autonomyPolicy,
|
|
1155
1870
|
dispatchRecord: record_1
|
|
1156
1871
|
};
|
|
1157
1872
|
}
|
|
1158
|
-
if (
|
|
1159
|
-
var record_2 = buildRecoveryDispatchRecord(action, 'park_manual', 'parked', '
|
|
1873
|
+
if (action.singleActionOnly === true && allowedDispatchAction !== dispatchAction) {
|
|
1874
|
+
var record_2 = buildRecoveryDispatchRecord(action, 'park_manual', 'parked', 'recovery_dispatch_action_not_in_packet_contract', current, input.now);
|
|
1160
1875
|
return {
|
|
1161
1876
|
dispatchAction: 'park_manual',
|
|
1162
1877
|
allowed: false,
|
|
@@ -1167,9 +1882,42 @@ function decideResolveIOAIManagerRecoveryActionDispatch(input) {
|
|
|
1167
1882
|
shouldRecordDispatch: true,
|
|
1168
1883
|
requiresNewEvidence: true,
|
|
1169
1884
|
newEvidence: newEvidence,
|
|
1885
|
+
autonomyPolicy: autonomyPolicy,
|
|
1170
1886
|
dispatchRecord: record_2
|
|
1171
1887
|
};
|
|
1172
1888
|
}
|
|
1889
|
+
if (manualOnly && input.operatorApproved !== true) {
|
|
1890
|
+
var record_3 = buildRecoveryDispatchRecord(action, 'park_manual', 'parked', 'recovery_dispatch_requires_manual_review', current, input.now);
|
|
1891
|
+
return {
|
|
1892
|
+
dispatchAction: 'park_manual',
|
|
1893
|
+
allowed: false,
|
|
1894
|
+
reason: record_3.reason,
|
|
1895
|
+
status: 'parked',
|
|
1896
|
+
canRunProductRepair: false,
|
|
1897
|
+
canRunExpensiveModel: false,
|
|
1898
|
+
shouldRecordDispatch: true,
|
|
1899
|
+
requiresNewEvidence: requiresNewEvidence,
|
|
1900
|
+
newEvidence: newEvidence,
|
|
1901
|
+
autonomyPolicy: autonomyPolicy,
|
|
1902
|
+
dispatchRecord: record_3
|
|
1903
|
+
};
|
|
1904
|
+
}
|
|
1905
|
+
if (productDispatch && action.productRepairAllowed !== true) {
|
|
1906
|
+
var record_4 = buildRecoveryDispatchRecord(action, 'park_manual', 'parked', 'recovery_dispatch_product_repair_not_allowed', current, input.now);
|
|
1907
|
+
return {
|
|
1908
|
+
dispatchAction: 'park_manual',
|
|
1909
|
+
allowed: false,
|
|
1910
|
+
reason: record_4.reason,
|
|
1911
|
+
status: 'parked',
|
|
1912
|
+
canRunProductRepair: false,
|
|
1913
|
+
canRunExpensiveModel: false,
|
|
1914
|
+
shouldRecordDispatch: true,
|
|
1915
|
+
requiresNewEvidence: true,
|
|
1916
|
+
newEvidence: newEvidence,
|
|
1917
|
+
autonomyPolicy: autonomyPolicy,
|
|
1918
|
+
dispatchRecord: record_4
|
|
1919
|
+
};
|
|
1920
|
+
}
|
|
1173
1921
|
if (activeDispatch) {
|
|
1174
1922
|
return {
|
|
1175
1923
|
dispatchAction: 'park_manual',
|
|
@@ -1180,22 +1928,24 @@ function decideResolveIOAIManagerRecoveryActionDispatch(input) {
|
|
|
1180
1928
|
canRunExpensiveModel: false,
|
|
1181
1929
|
shouldRecordDispatch: false,
|
|
1182
1930
|
requiresNewEvidence: true,
|
|
1183
|
-
newEvidence: false
|
|
1931
|
+
newEvidence: false,
|
|
1932
|
+
autonomyPolicy: autonomyPolicy
|
|
1184
1933
|
};
|
|
1185
1934
|
}
|
|
1186
|
-
if (
|
|
1187
|
-
var
|
|
1935
|
+
if (sameEvidenceAlreadyAttempted) {
|
|
1936
|
+
var record_5 = buildRecoveryDispatchRecord(action, 'park_manual', 'parked', 'recovery_dispatch_same_evidence_already_attempted', current, input.now);
|
|
1188
1937
|
return {
|
|
1189
1938
|
dispatchAction: 'park_manual',
|
|
1190
1939
|
allowed: false,
|
|
1191
|
-
reason:
|
|
1940
|
+
reason: record_5.reason,
|
|
1192
1941
|
status: 'parked',
|
|
1193
1942
|
canRunProductRepair: false,
|
|
1194
1943
|
canRunExpensiveModel: false,
|
|
1195
1944
|
shouldRecordDispatch: true,
|
|
1196
1945
|
requiresNewEvidence: true,
|
|
1197
1946
|
newEvidence: false,
|
|
1198
|
-
|
|
1947
|
+
autonomyPolicy: autonomyPolicy,
|
|
1948
|
+
dispatchRecord: record_5
|
|
1199
1949
|
};
|
|
1200
1950
|
}
|
|
1201
1951
|
var status = dispatchAction === 'advance' || dispatchAction === 'continue_gate'
|
|
@@ -1212,6 +1962,7 @@ function decideResolveIOAIManagerRecoveryActionDispatch(input) {
|
|
|
1212
1962
|
shouldRecordDispatch: true,
|
|
1213
1963
|
requiresNewEvidence: requiresNewEvidence,
|
|
1214
1964
|
newEvidence: newEvidence,
|
|
1965
|
+
autonomyPolicy: autonomyPolicy,
|
|
1215
1966
|
dispatchRecord: record
|
|
1216
1967
|
};
|
|
1217
1968
|
}
|
|
@@ -1258,6 +2009,7 @@ function buildResolveIOAIManagerRecoveryExecutionDirective(input) {
|
|
|
1258
2009
|
var dispatchDecision = input.dispatchDecision || decideResolveIOAIManagerRecoveryActionDispatch({
|
|
1259
2010
|
action: action,
|
|
1260
2011
|
current: input.current,
|
|
2012
|
+
autonomyPolicy: input.autonomyPolicy,
|
|
1261
2013
|
now: input.now
|
|
1262
2014
|
});
|
|
1263
2015
|
var dispatchAction = dispatchDecision.dispatchAction;
|
|
@@ -1267,17 +2019,17 @@ function buildResolveIOAIManagerRecoveryExecutionDirective(input) {
|
|
|
1267
2019
|
var stepType = cleanText((action === null || action === void 0 ? void 0 : action.stepType) || ((_b = input.current) === null || _b === void 0 ? void 0 : _b.stepType) || '', 120);
|
|
1268
2020
|
var rerunReason = recoveryDirectiveReason(action, dispatchDecision, input.current);
|
|
1269
2021
|
var surface = cleanText(input.surface || 'runner', 120);
|
|
1270
|
-
return __assign(__assign(__assign({ directiveId: stableHash('mgr-directive', {
|
|
2022
|
+
return __assign(__assign(__assign(__assign(__assign({ directiveId: stableHash('mgr-directive', {
|
|
1271
2023
|
surface: surface,
|
|
1272
2024
|
actionId: (action === null || action === void 0 ? void 0 : action.actionId) || '',
|
|
1273
2025
|
dispatchAction: dispatchAction,
|
|
1274
2026
|
reason: dispatchDecision.reason,
|
|
1275
2027
|
evidenceHash: ((_c = dispatchDecision.dispatchRecord) === null || _c === void 0 ? void 0 : _c.evidenceHash) || ((_d = input.current) === null || _d === void 0 ? void 0 : _d.evidenceHash) || ''
|
|
1276
|
-
}), 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
|
|
2028
|
+
}), surface: surface, dispatchAction: dispatchAction, phase: phase, allowed: dispatchDecision.allowed, status: dispatchDecision.status, reason: dispatchDecision.reason, singleActionOnly: (action === null || action === void 0 ? void 0 : action.singleActionOnly) !== false, allowedDispatchAction: (action === null || action === void 0 ? void 0 : action.allowedDispatchAction) || dispatchAction, 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, costCeilingUsd: Math.max(0, Number((action === null || action === void 0 ? void 0 : action.costCeilingUsd) || 0) || 0), requiredStateTransition: cleanText(action === null || action === void 0 ? void 0 : action.requiredStateTransition, 500), proofRequiredBeforeContinuation: (action === null || action === void 0 ? void 0 : action.proofRequiredBeforeContinuation) === true, canRunProductRepair: dispatchDecision.canRunProductRepair, canRunExpensiveModel: dispatchDecision.canRunExpensiveModel, canResetLoopAfterEvidence: (action === null || action === void 0 ? void 0 : action.canResetLoopAfterEvidence) === true, requiresNewEvidence: dispatchDecision.requiresNewEvidence, newEvidence: dispatchDecision.newEvidence }, (dispatchDecision.autonomyPolicy ? { autonomyPolicy: dispatchDecision.autonomyPolicy } : {})), { 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), exitCriteria: cleanList(action === null || action === void 0 ? void 0 : action.exitCriteria, 30, 500), forbiddenActions: (action === null || action === void 0 ? void 0 : action.productRepairAllowed) === true
|
|
1277
2029
|
? []
|
|
1278
2030
|
: Array.from(new Set(__spreadArray([
|
|
1279
2031
|
'Do not run product-code repair from this directive unless canRunProductRepair is true.'
|
|
1280
|
-
], __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 });
|
|
2032
|
+
], __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 });
|
|
1281
2033
|
}
|
|
1282
2034
|
function newListEntries(current, previous) {
|
|
1283
2035
|
var existing = new Set(previous.map(function (entry) { return cleanText(entry, 500); }).filter(Boolean));
|