@akagilnc/pi-workflow-roles 0.1.1883 → 0.1.1918
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/dist/evidence-child-executor.js +153 -16
- package/dist/navigator-attendance.js +64 -29
- package/dist/public-cli/main.js +786 -373
- package/dist/reviewer-child-executor.js +1 -1
- package/dist/typed-provider-http.js +60 -0
- package/dist/upstream-error-testimony.js +19 -0
- package/package.json +1 -1
- package/scripts/build-package.mjs +2 -0
- package/src/evidence-child-executor.ts +177 -24
- package/src/factory-board.ts +60 -3
- package/src/navigator-attendance.ts +86 -33
- package/src/public-cli/cli.ts +96 -39
- package/src/public-cli/coder-run.ts +36 -11
- package/src/public-cli/collector-run.ts +8 -3
- package/src/public-cli/doctor-run.ts +1 -0
- package/src/public-cli/explicit-internal.ts +61 -19
- package/src/public-cli/fixer-run.ts +36 -11
- package/src/public-cli/invocation.ts +137 -101
- package/src/public-cli/judge-run.ts +39 -11
- package/src/public-cli/merger-run.ts +36 -11
- package/src/public-cli/reviewer-run.ts +35 -11
- package/src/public-cli/run-lifecycle.ts +89 -76
- package/src/public-cli/settlement.ts +256 -66
- package/src/reviewer-child-executor.ts +1 -1
- package/src/role-runtime.ts +18 -8
- package/src/ticket-frontmatter.ts +94 -0
- package/src/ticket-trajectory.ts +145 -5
- package/src/typed-provider-http.ts +99 -0
- package/src/upstream-error-testimony.ts +45 -0
|
@@ -36,8 +36,8 @@ import {
|
|
|
36
36
|
markRunResumable,
|
|
37
37
|
markRunRunning,
|
|
38
38
|
markRunTerminal,
|
|
39
|
-
readTypedHttp429Observation,
|
|
40
39
|
renderResumeCommand,
|
|
40
|
+
type TypedProviderHttpObservation,
|
|
41
41
|
RESUME_TRANSPORT_ENVELOPE,
|
|
42
42
|
RunWriterLeaseHeldError,
|
|
43
43
|
type RunWriterLease,
|
|
@@ -52,7 +52,9 @@ import {
|
|
|
52
52
|
isLawfulTypedTerminalOutcome,
|
|
53
53
|
presentFailureTerminal,
|
|
54
54
|
presentStructuralRejection,
|
|
55
|
-
|
|
55
|
+
resolveAuditedRunnerFailureResolution,
|
|
56
|
+
resolveControlledFailureResumeObservation,
|
|
57
|
+
controlledFailureInputFromResolution,
|
|
56
58
|
explicitInternalKnownFailureClassificationInput,
|
|
57
59
|
settleJudgeFailureTerminalResult,
|
|
58
60
|
trySettleJudgeTerminalResult,
|
|
@@ -171,6 +173,9 @@ async function presentControlledFailure(
|
|
|
171
173
|
stderr: string;
|
|
172
174
|
thrown?: unknown;
|
|
173
175
|
knownFailure?: ExplicitInternalKnownFailure;
|
|
176
|
+
/** Pre-resolved typed-HTTP outcome — no second sidecar read when settled. */
|
|
177
|
+
typedHttpObservationSettled?: true;
|
|
178
|
+
typedHttpObservation?: TypedProviderHttpObservation;
|
|
174
179
|
},
|
|
175
180
|
io: CliIo,
|
|
176
181
|
): Promise<{
|
|
@@ -180,10 +185,25 @@ async function presentControlledFailure(
|
|
|
180
185
|
}> {
|
|
181
186
|
// Own-key presence, not value: `throw undefined` must not look like "no throw".
|
|
182
187
|
const hasThrown = Object.hasOwn(failureInput, "thrown");
|
|
188
|
+
// v1 resume observation: reuse audited resolution when present; otherwise one
|
|
189
|
+
// controlled read. Non-absence failures fold into knownFailure — never escape.
|
|
190
|
+
const resumeObservation = await resolveControlledFailureResumeObservation({
|
|
191
|
+
runDirectory: admitted.runDirectory,
|
|
192
|
+
...(failureInput.typedHttpObservationSettled === true
|
|
193
|
+
? {
|
|
194
|
+
typedHttpObservationSettled: true as const,
|
|
195
|
+
...(failureInput.typedHttpObservation === undefined
|
|
196
|
+
? {}
|
|
197
|
+
: { typedHttpObservation: failureInput.typedHttpObservation }),
|
|
198
|
+
}
|
|
199
|
+
: {}),
|
|
200
|
+
});
|
|
201
|
+
const knownFailure =
|
|
202
|
+
failureInput.knownFailure ?? resumeObservation.observationReadFailure;
|
|
183
203
|
const session =
|
|
184
204
|
!hasThrown &&
|
|
185
205
|
!failureInput.timedOut &&
|
|
186
|
-
|
|
206
|
+
knownFailure === undefined
|
|
187
207
|
? await inspectJudgeSession(admitted.sessionFile)
|
|
188
208
|
: undefined;
|
|
189
209
|
const failure = classifyPostAdmissionFailure({
|
|
@@ -191,7 +211,7 @@ async function presentControlledFailure(
|
|
|
191
211
|
code: failureInput.code,
|
|
192
212
|
stderr: failureInput.stderr,
|
|
193
213
|
...(hasThrown ? { thrown: failureInput.thrown } : {}),
|
|
194
|
-
...explicitInternalKnownFailureClassificationInput(
|
|
214
|
+
...explicitInternalKnownFailureClassificationInput(knownFailure),
|
|
195
215
|
...(session === undefined ? {} : { session }),
|
|
196
216
|
});
|
|
197
217
|
|
|
@@ -199,7 +219,7 @@ async function presentControlledFailure(
|
|
|
199
219
|
// absence of a lawful Judge result, and a durable exact Pi session principal.
|
|
200
220
|
// Lawful presence is session-owned and must not depend on artifact publication.
|
|
201
221
|
const hasLawfulTerminalResult = await hasLawfulJudgeTerminalResult(admitted);
|
|
202
|
-
const typedHttp429 =
|
|
222
|
+
const typedHttp429 = resumeObservation.typedHttp429;
|
|
203
223
|
const sessionPrincipalAvailable = await isSessionPrincipalAvailable(
|
|
204
224
|
admitted.sessionFile,
|
|
205
225
|
);
|
|
@@ -269,8 +289,9 @@ async function dispatchAdmittedJudge(input: {
|
|
|
269
289
|
// and role-runtime can record typed provider HTTP observations.
|
|
270
290
|
AK_ROLE_RUN_DIR: admitted.runDirectory,
|
|
271
291
|
};
|
|
272
|
-
|
|
273
|
-
|
|
292
|
+
const correlationId = admitted.correlationId ?? env.correlationId;
|
|
293
|
+
if (correlationId !== undefined && correlationId.trim() !== "") {
|
|
294
|
+
childEnv.AK_CORRELATION_ID = correlationId;
|
|
274
295
|
}
|
|
275
296
|
|
|
276
297
|
let result: ExplicitInternalPiResult;
|
|
@@ -355,10 +376,11 @@ async function dispatchAdmittedJudge(input: {
|
|
|
355
376
|
env.model,
|
|
356
377
|
env.credentials,
|
|
357
378
|
);
|
|
358
|
-
const
|
|
379
|
+
const resolution = await resolveAuditedRunnerFailureResolution({
|
|
359
380
|
runner: result.knownFailure,
|
|
360
381
|
sessionFile: admitted.sessionFile,
|
|
361
382
|
credential: credentialFailure,
|
|
383
|
+
runDirectory: admitted.runDirectory,
|
|
362
384
|
});
|
|
363
385
|
return await presentControlledFailure(
|
|
364
386
|
admitted,
|
|
@@ -366,7 +388,7 @@ async function dispatchAdmittedJudge(input: {
|
|
|
366
388
|
timedOut: result.timedOut,
|
|
367
389
|
code: result.code,
|
|
368
390
|
stderr: result.stderr,
|
|
369
|
-
...(
|
|
391
|
+
...controlledFailureInputFromResolution(resolution),
|
|
370
392
|
},
|
|
371
393
|
io,
|
|
372
394
|
);
|
|
@@ -429,7 +451,10 @@ export async function runPublicJudge(
|
|
|
429
451
|
|
|
430
452
|
return await dispatchAdmittedJudge({
|
|
431
453
|
admitted,
|
|
432
|
-
env
|
|
454
|
+
env: {
|
|
455
|
+
...env,
|
|
456
|
+
...(admitted.correlationId === undefined ? {} : { correlationId: admitted.correlationId }),
|
|
457
|
+
},
|
|
433
458
|
io,
|
|
434
459
|
extraArgs,
|
|
435
460
|
lease,
|
|
@@ -499,7 +524,10 @@ export async function runPublicResume(
|
|
|
499
524
|
|
|
500
525
|
return await dispatchAdmittedJudge({
|
|
501
526
|
admitted,
|
|
502
|
-
env
|
|
527
|
+
env: {
|
|
528
|
+
...env,
|
|
529
|
+
...(admitted.correlationId === undefined ? {} : { correlationId: admitted.correlationId }),
|
|
530
|
+
},
|
|
503
531
|
io,
|
|
504
532
|
extraArgs,
|
|
505
533
|
lease,
|
|
@@ -50,7 +50,7 @@ import {
|
|
|
50
50
|
RESUME_TRANSPORT_ENVELOPE,
|
|
51
51
|
RunWriterLeaseHeldError,
|
|
52
52
|
type RunWriterLease,
|
|
53
|
-
|
|
53
|
+
type TypedProviderHttpObservation,
|
|
54
54
|
} from "./run-lifecycle.ts";
|
|
55
55
|
import {
|
|
56
56
|
classifyPostAdmissionFailure,
|
|
@@ -62,7 +62,9 @@ import {
|
|
|
62
62
|
presentFailureTerminal,
|
|
63
63
|
presentStructuralRejection,
|
|
64
64
|
explicitInternalKnownFailureClassificationInput,
|
|
65
|
-
|
|
65
|
+
resolveAuditedRunnerFailureResolution,
|
|
66
|
+
resolveControlledFailureResumeObservation,
|
|
67
|
+
controlledFailureInputFromResolution,
|
|
66
68
|
settleFailureTerminalResult,
|
|
67
69
|
trySettleMergerTerminalResult,
|
|
68
70
|
} from "./settlement.ts";
|
|
@@ -192,6 +194,8 @@ async function presentControlledFailure(
|
|
|
192
194
|
readonly code?: string | number;
|
|
193
195
|
};
|
|
194
196
|
knownDiagnostic?: string;
|
|
197
|
+
typedHttpObservationSettled?: true;
|
|
198
|
+
typedHttpObservation?: TypedProviderHttpObservation;
|
|
195
199
|
},
|
|
196
200
|
io: CliIo,
|
|
197
201
|
): Promise<{
|
|
@@ -200,10 +204,23 @@ async function presentControlledFailure(
|
|
|
200
204
|
terminal: TerminalResult;
|
|
201
205
|
}> {
|
|
202
206
|
const hasThrown = Object.hasOwn(failureInput, "thrown");
|
|
207
|
+
const resumeObservation = await resolveControlledFailureResumeObservation({
|
|
208
|
+
runDirectory: admitted.runDirectory,
|
|
209
|
+
...(failureInput.typedHttpObservationSettled === true
|
|
210
|
+
? {
|
|
211
|
+
typedHttpObservationSettled: true as const,
|
|
212
|
+
...(failureInput.typedHttpObservation === undefined
|
|
213
|
+
? {}
|
|
214
|
+
: { typedHttpObservation: failureInput.typedHttpObservation }),
|
|
215
|
+
}
|
|
216
|
+
: {}),
|
|
217
|
+
});
|
|
218
|
+
const knownFailure =
|
|
219
|
+
failureInput.knownFailure ?? resumeObservation.observationReadFailure;
|
|
203
220
|
const session =
|
|
204
221
|
!hasThrown &&
|
|
205
222
|
!failureInput.timedOut &&
|
|
206
|
-
|
|
223
|
+
knownFailure === undefined &&
|
|
207
224
|
failureInput.knownCause === undefined
|
|
208
225
|
? await inspectJudgeSession(admitted.sessionFile)
|
|
209
226
|
: undefined;
|
|
@@ -212,7 +229,7 @@ async function presentControlledFailure(
|
|
|
212
229
|
code: failureInput.code,
|
|
213
230
|
stderr: failureInput.stderr,
|
|
214
231
|
...(hasThrown ? { thrown: failureInput.thrown } : {}),
|
|
215
|
-
...explicitInternalKnownFailureClassificationInput(
|
|
232
|
+
...explicitInternalKnownFailureClassificationInput(knownFailure),
|
|
216
233
|
...(failureInput.knownCause === undefined
|
|
217
234
|
? {}
|
|
218
235
|
: { knownCause: failureInput.knownCause }),
|
|
@@ -226,7 +243,7 @@ async function presentControlledFailure(
|
|
|
226
243
|
});
|
|
227
244
|
|
|
228
245
|
const hasLawfulTerminalResult = await hasLawfulMergerTerminalResult(admitted);
|
|
229
|
-
const typedHttp429 =
|
|
246
|
+
const typedHttp429 = resumeObservation.typedHttp429;
|
|
230
247
|
const sessionPrincipalAvailable = await isSessionPrincipalAvailable(
|
|
231
248
|
admitted.sessionFile,
|
|
232
249
|
);
|
|
@@ -291,8 +308,9 @@ async function dispatchAdmittedMerger(input: {
|
|
|
291
308
|
PI_CODING_AGENT_DIR: env.agentDir,
|
|
292
309
|
AK_ROLE_RUN_DIR: admitted.runDirectory,
|
|
293
310
|
};
|
|
294
|
-
|
|
295
|
-
|
|
311
|
+
const correlationId = admitted.correlationId ?? env.correlationId;
|
|
312
|
+
if (correlationId !== undefined && correlationId.trim() !== "") {
|
|
313
|
+
childEnv.AK_CORRELATION_ID = correlationId;
|
|
296
314
|
}
|
|
297
315
|
|
|
298
316
|
let result: ExplicitInternalPiResult;
|
|
@@ -367,10 +385,11 @@ async function dispatchAdmittedMerger(input: {
|
|
|
367
385
|
env.model,
|
|
368
386
|
env.credentials,
|
|
369
387
|
);
|
|
370
|
-
const
|
|
388
|
+
const resolution = await resolveAuditedRunnerFailureResolution({
|
|
371
389
|
runner: result.knownFailure,
|
|
372
390
|
sessionFile: admitted.sessionFile,
|
|
373
391
|
credential: credentialFailure,
|
|
392
|
+
runDirectory: admitted.runDirectory,
|
|
374
393
|
});
|
|
375
394
|
return await presentControlledFailure(
|
|
376
395
|
admitted,
|
|
@@ -378,7 +397,7 @@ async function dispatchAdmittedMerger(input: {
|
|
|
378
397
|
timedOut: result.timedOut,
|
|
379
398
|
code: result.code,
|
|
380
399
|
stderr: result.stderr,
|
|
381
|
-
...(
|
|
400
|
+
...controlledFailureInputFromResolution(resolution),
|
|
382
401
|
},
|
|
383
402
|
io,
|
|
384
403
|
);
|
|
@@ -571,7 +590,10 @@ export async function runPublicMerger(
|
|
|
571
590
|
|
|
572
591
|
return await dispatchAdmittedMerger({
|
|
573
592
|
admitted,
|
|
574
|
-
env
|
|
593
|
+
env: {
|
|
594
|
+
...env,
|
|
595
|
+
...(admitted.correlationId === undefined ? {} : { correlationId: admitted.correlationId }),
|
|
596
|
+
},
|
|
575
597
|
io,
|
|
576
598
|
extraArgs,
|
|
577
599
|
lease,
|
|
@@ -658,7 +680,10 @@ export async function runPublicMergerResume(
|
|
|
658
680
|
|
|
659
681
|
return await dispatchAdmittedMerger({
|
|
660
682
|
admitted,
|
|
661
|
-
env
|
|
683
|
+
env: {
|
|
684
|
+
...env,
|
|
685
|
+
...(admitted.correlationId === undefined ? {} : { correlationId: admitted.correlationId }),
|
|
686
|
+
},
|
|
662
687
|
io,
|
|
663
688
|
extraArgs,
|
|
664
689
|
lease,
|
|
@@ -44,11 +44,11 @@ import {
|
|
|
44
44
|
markRunResumable,
|
|
45
45
|
markRunRunning,
|
|
46
46
|
markRunTerminal,
|
|
47
|
-
readTypedHttp429Observation,
|
|
48
47
|
renderResumeCommand,
|
|
49
48
|
RESUME_TRANSPORT_ENVELOPE,
|
|
50
49
|
RunWriterLeaseHeldError,
|
|
51
50
|
type RunWriterLease,
|
|
51
|
+
type TypedProviderHttpObservation,
|
|
52
52
|
} from "./run-lifecycle.ts";
|
|
53
53
|
import {
|
|
54
54
|
classifyPostAdmissionFailure,
|
|
@@ -60,7 +60,9 @@ import {
|
|
|
60
60
|
isLawfulTypedTerminalOutcome,
|
|
61
61
|
presentFailureTerminal,
|
|
62
62
|
presentStructuralRejection,
|
|
63
|
-
|
|
63
|
+
resolveAuditedRunnerFailureResolution,
|
|
64
|
+
resolveControlledFailureResumeObservation,
|
|
65
|
+
controlledFailureInputFromResolution,
|
|
64
66
|
explicitInternalKnownFailureClassificationInput,
|
|
65
67
|
settleFailureTerminalResult,
|
|
66
68
|
trySettleReviewerTerminalResult,
|
|
@@ -186,6 +188,8 @@ async function presentControlledFailure(
|
|
|
186
188
|
stderr: string;
|
|
187
189
|
thrown?: unknown;
|
|
188
190
|
knownFailure?: ExplicitInternalKnownFailure;
|
|
191
|
+
typedHttpObservationSettled?: true;
|
|
192
|
+
typedHttpObservation?: TypedProviderHttpObservation;
|
|
189
193
|
},
|
|
190
194
|
io: CliIo,
|
|
191
195
|
): Promise<{
|
|
@@ -194,10 +198,23 @@ async function presentControlledFailure(
|
|
|
194
198
|
terminal: TerminalResult;
|
|
195
199
|
}> {
|
|
196
200
|
const hasThrown = Object.hasOwn(failureInput, "thrown");
|
|
201
|
+
const resumeObservation = await resolveControlledFailureResumeObservation({
|
|
202
|
+
runDirectory: admitted.runDirectory,
|
|
203
|
+
...(failureInput.typedHttpObservationSettled === true
|
|
204
|
+
? {
|
|
205
|
+
typedHttpObservationSettled: true as const,
|
|
206
|
+
...(failureInput.typedHttpObservation === undefined
|
|
207
|
+
? {}
|
|
208
|
+
: { typedHttpObservation: failureInput.typedHttpObservation }),
|
|
209
|
+
}
|
|
210
|
+
: {}),
|
|
211
|
+
});
|
|
212
|
+
const knownFailure =
|
|
213
|
+
failureInput.knownFailure ?? resumeObservation.observationReadFailure;
|
|
197
214
|
const session =
|
|
198
215
|
!hasThrown &&
|
|
199
216
|
!failureInput.timedOut &&
|
|
200
|
-
|
|
217
|
+
knownFailure === undefined
|
|
201
218
|
? await inspectJudgeSession(admitted.sessionFile)
|
|
202
219
|
: undefined;
|
|
203
220
|
const failure = classifyPostAdmissionFailure({
|
|
@@ -205,12 +222,12 @@ async function presentControlledFailure(
|
|
|
205
222
|
code: failureInput.code,
|
|
206
223
|
stderr: failureInput.stderr,
|
|
207
224
|
...(hasThrown ? { thrown: failureInput.thrown } : {}),
|
|
208
|
-
...explicitInternalKnownFailureClassificationInput(
|
|
225
|
+
...explicitInternalKnownFailureClassificationInput(knownFailure),
|
|
209
226
|
...(session === undefined ? {} : { session }),
|
|
210
227
|
});
|
|
211
228
|
|
|
212
229
|
const hasLawfulTerminalResult = await hasLawfulReviewerTerminalResult(admitted);
|
|
213
|
-
const typedHttp429 =
|
|
230
|
+
const typedHttp429 = resumeObservation.typedHttp429;
|
|
214
231
|
const sessionPrincipalAvailable = await isSessionPrincipalAvailable(
|
|
215
232
|
admitted.sessionFile,
|
|
216
233
|
);
|
|
@@ -276,8 +293,9 @@ async function dispatchAdmittedReviewer(input: {
|
|
|
276
293
|
PI_CODING_AGENT_DIR: env.agentDir,
|
|
277
294
|
AK_ROLE_RUN_DIR: admitted.runDirectory,
|
|
278
295
|
};
|
|
279
|
-
|
|
280
|
-
|
|
296
|
+
const correlationId = admitted.correlationId ?? env.correlationId;
|
|
297
|
+
if (correlationId !== undefined && correlationId.trim() !== "") {
|
|
298
|
+
childEnv.AK_CORRELATION_ID = correlationId;
|
|
281
299
|
}
|
|
282
300
|
|
|
283
301
|
let result: ExplicitInternalPiResult;
|
|
@@ -367,7 +385,7 @@ async function dispatchAdmittedReviewer(input: {
|
|
|
367
385
|
env.model,
|
|
368
386
|
env.credentials,
|
|
369
387
|
);
|
|
370
|
-
const
|
|
388
|
+
const resolution = await resolveAuditedRunnerFailureResolution({
|
|
371
389
|
runner: result.knownFailure,
|
|
372
390
|
sessionFile: admitted.sessionFile,
|
|
373
391
|
credential: credentialFailure,
|
|
@@ -379,7 +397,7 @@ async function dispatchAdmittedReviewer(input: {
|
|
|
379
397
|
timedOut: result.timedOut,
|
|
380
398
|
code: result.code,
|
|
381
399
|
stderr: result.stderr,
|
|
382
|
-
...(
|
|
400
|
+
...controlledFailureInputFromResolution(resolution),
|
|
383
401
|
},
|
|
384
402
|
io,
|
|
385
403
|
);
|
|
@@ -467,7 +485,10 @@ export async function runPublicReviewer(
|
|
|
467
485
|
|
|
468
486
|
return await dispatchAdmittedReviewer({
|
|
469
487
|
admitted,
|
|
470
|
-
env
|
|
488
|
+
env: {
|
|
489
|
+
...env,
|
|
490
|
+
...(admitted.correlationId === undefined ? {} : { correlationId: admitted.correlationId }),
|
|
491
|
+
},
|
|
471
492
|
io,
|
|
472
493
|
extraArgs,
|
|
473
494
|
lease,
|
|
@@ -553,7 +574,10 @@ export async function runPublicReviewerResume(
|
|
|
553
574
|
|
|
554
575
|
return await dispatchAdmittedReviewer({
|
|
555
576
|
admitted,
|
|
556
|
-
env
|
|
577
|
+
env: {
|
|
578
|
+
...env,
|
|
579
|
+
...(admitted.correlationId === undefined ? {} : { correlationId: admitted.correlationId }),
|
|
580
|
+
},
|
|
557
581
|
io,
|
|
558
582
|
extraArgs,
|
|
559
583
|
lease,
|
|
@@ -12,6 +12,15 @@ import {
|
|
|
12
12
|
resolveActivationLedgerHome,
|
|
13
13
|
} from "../activation-ledger-topology.ts";
|
|
14
14
|
import { CliUsageError } from "./cli-errors.ts";
|
|
15
|
+
import {
|
|
16
|
+
readLatestTypedProviderHttpObservation,
|
|
17
|
+
} from "../typed-provider-http.ts";
|
|
18
|
+
export {
|
|
19
|
+
clearTypedProviderHttpObservation,
|
|
20
|
+
recordTypedProviderHttpStatus,
|
|
21
|
+
readLatestTypedProviderHttpObservation,
|
|
22
|
+
type TypedProviderHttpObservation,
|
|
23
|
+
} from "../typed-provider-http.ts";
|
|
15
24
|
import type { FixerPhase } from "../package-contracts/fixer-output.ts";
|
|
16
25
|
import type { FixerPrerequisite } from "../package-contracts/fixer-packet.ts";
|
|
17
26
|
import {
|
|
@@ -65,7 +74,6 @@ export type RoleRunRecord = {
|
|
|
65
74
|
export const RESUME_TRANSPORT_ENVELOPE = "[ak-role:resume-continue]" as const;
|
|
66
75
|
|
|
67
76
|
const RUN_STATE_FILE = "run-state.json";
|
|
68
|
-
const TYPED_HTTP_FILE = "typed-provider-http.json";
|
|
69
77
|
const WRITER_LOCK_FILE = "writer.lock";
|
|
70
78
|
|
|
71
79
|
export function isV1ResumableProvider(
|
|
@@ -74,84 +82,14 @@ export function isV1ResumableProvider(
|
|
|
74
82
|
return (V1_RESUMABLE_PROVIDERS as readonly string[]).includes(provider);
|
|
75
83
|
}
|
|
76
84
|
|
|
77
|
-
function typedProviderHttpPath(runDirectory: string): string {
|
|
78
|
-
return join(runDirectory, TYPED_HTTP_FILE);
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
/**
|
|
82
|
-
* Clear any prior attempt's typed provider HTTP observation.
|
|
83
|
-
* Each initial/resume dispatch must start without inherited 429 evidence so
|
|
84
|
-
* only the current attempt can qualify v1 resume.
|
|
85
|
-
*/
|
|
86
|
-
export async function clearTypedProviderHttpObservation(
|
|
87
|
-
runDirectory: string,
|
|
88
|
-
): Promise<void> {
|
|
89
|
-
try {
|
|
90
|
-
await unlink(typedProviderHttpPath(runDirectory));
|
|
91
|
-
} catch (error) {
|
|
92
|
-
if (
|
|
93
|
-
error instanceof Error &&
|
|
94
|
-
"code" in error &&
|
|
95
|
-
(error as { code?: unknown }).code === "ENOENT"
|
|
96
|
-
) {
|
|
97
|
-
return;
|
|
98
|
-
}
|
|
99
|
-
throw error;
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
/**
|
|
104
|
-
* Record a typed provider HTTP status observation for the admitted run.
|
|
105
|
-
* The latest observation is authoritative: only a current HTTP 429 from
|
|
106
|
-
* Codex/xAI is retained for v1 resume; any other status or provider clears
|
|
107
|
-
* prior within-attempt 429 evidence. Never inspects diagnostic prose.
|
|
108
|
-
*/
|
|
109
|
-
export async function recordTypedProviderHttpStatus(
|
|
110
|
-
runDirectory: string,
|
|
111
|
-
observation: { readonly httpStatus: number; readonly provider: string },
|
|
112
|
-
): Promise<void> {
|
|
113
|
-
if (
|
|
114
|
-
observation.httpStatus === 429 &&
|
|
115
|
-
isV1ResumableProvider(observation.provider)
|
|
116
|
-
) {
|
|
117
|
-
const body: TypedHttp429Observation = {
|
|
118
|
-
httpStatus: 429,
|
|
119
|
-
provider: observation.provider,
|
|
120
|
-
};
|
|
121
|
-
await writeFile(
|
|
122
|
-
typedProviderHttpPath(runDirectory),
|
|
123
|
-
`${JSON.stringify(body)}\n`,
|
|
124
|
-
"utf8",
|
|
125
|
-
);
|
|
126
|
-
return;
|
|
127
|
-
}
|
|
128
|
-
// Non-qualifying latest response supersedes any earlier 429 in this attempt.
|
|
129
|
-
await clearTypedProviderHttpObservation(runDirectory);
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
/**
|
|
133
|
-
* Read a durable typed HTTP 429 observation. Returns undefined unless both
|
|
134
|
-
* httpStatus === 429 and provider is a v1-resumable provider are present as
|
|
135
|
-
* typed fields (never inferred from prose).
|
|
136
|
-
*/
|
|
137
85
|
export async function readTypedHttp429Observation(
|
|
138
86
|
runDirectory: string,
|
|
139
87
|
): Promise<TypedHttp429Observation | undefined> {
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
return undefined;
|
|
146
|
-
}
|
|
147
|
-
const record = raw as Record<string, unknown>;
|
|
148
|
-
if (record.httpStatus !== 429) return undefined;
|
|
149
|
-
if (typeof record.provider !== "string") return undefined;
|
|
150
|
-
if (!isV1ResumableProvider(record.provider)) return undefined;
|
|
151
|
-
return { httpStatus: 429, provider: record.provider };
|
|
152
|
-
} catch {
|
|
153
|
-
return undefined;
|
|
154
|
-
}
|
|
88
|
+
const observation = await readLatestTypedProviderHttpObservation(runDirectory);
|
|
89
|
+
if (observation === undefined) return undefined;
|
|
90
|
+
if (observation.httpStatus !== 429) return undefined;
|
|
91
|
+
if (!isV1ResumableProvider(observation.provider)) return undefined;
|
|
92
|
+
return { httpStatus: 429, provider: observation.provider };
|
|
155
93
|
}
|
|
156
94
|
|
|
157
95
|
/**
|
|
@@ -453,8 +391,40 @@ type LoadedAdmittedRequestFields = {
|
|
|
453
391
|
readonly baseRevision?: string;
|
|
454
392
|
readonly mergerInputPath?: string;
|
|
455
393
|
readonly derived?: DerivedMergerEnvelope;
|
|
394
|
+
readonly correlationId?: string;
|
|
395
|
+
readonly ticketNumber?: number;
|
|
456
396
|
};
|
|
457
397
|
|
|
398
|
+
/** Restore optional correlation + typed ticketNumber from a durable admitted page. */
|
|
399
|
+
function parsePersistedTicketIdentity(
|
|
400
|
+
record: Record<string, unknown>,
|
|
401
|
+
): { correlationId?: string; ticketNumber?: number } {
|
|
402
|
+
const correlationId =
|
|
403
|
+
typeof record.correlationId === "string" && record.correlationId.trim() !== ""
|
|
404
|
+
? record.correlationId
|
|
405
|
+
: undefined;
|
|
406
|
+
const ticketNumber =
|
|
407
|
+
typeof record.ticketNumber === "number" &&
|
|
408
|
+
Number.isInteger(record.ticketNumber) &&
|
|
409
|
+
record.ticketNumber >= 1
|
|
410
|
+
? record.ticketNumber
|
|
411
|
+
: undefined;
|
|
412
|
+
return {
|
|
413
|
+
...(correlationId === undefined ? {} : { correlationId }),
|
|
414
|
+
...(ticketNumber === undefined ? {} : { ticketNumber }),
|
|
415
|
+
};
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
function restoredTicketFields(fields: LoadedAdmittedRequestFields): {
|
|
419
|
+
correlationId?: string;
|
|
420
|
+
ticketNumber?: number;
|
|
421
|
+
} {
|
|
422
|
+
return {
|
|
423
|
+
...(fields.correlationId === undefined ? {} : { correlationId: fields.correlationId }),
|
|
424
|
+
...(fields.ticketNumber === undefined ? {} : { ticketNumber: fields.ticketNumber }),
|
|
425
|
+
};
|
|
426
|
+
}
|
|
427
|
+
|
|
458
428
|
async function loadResumableRunRecord(
|
|
459
429
|
home: string,
|
|
460
430
|
runId: string,
|
|
@@ -495,6 +465,8 @@ async function loadResumableRunRecord(
|
|
|
495
465
|
let baseRevision: string | undefined;
|
|
496
466
|
let mergerInputPath: string | undefined;
|
|
497
467
|
let derived: DerivedMergerEnvelope | undefined;
|
|
468
|
+
let correlationId: string | undefined;
|
|
469
|
+
let ticketNumber: number | undefined;
|
|
498
470
|
try {
|
|
499
471
|
const raw: unknown = JSON.parse(
|
|
500
472
|
await readFile(run.admittedRequestPath, "utf8"),
|
|
@@ -564,12 +536,46 @@ async function loadResumableRunRecord(
|
|
|
564
536
|
};
|
|
565
537
|
}
|
|
566
538
|
}
|
|
539
|
+
const fromAdmitted = parsePersistedTicketIdentity(record);
|
|
540
|
+
correlationId = fromAdmitted.correlationId;
|
|
541
|
+
ticketNumber = fromAdmitted.ticketNumber;
|
|
567
542
|
}
|
|
568
543
|
} catch {
|
|
569
544
|
throw new CliUsageError(
|
|
570
545
|
`role run admitted request is unreadable: ${runId}`,
|
|
571
546
|
);
|
|
572
547
|
}
|
|
548
|
+
if (correlationId === undefined || ticketNumber === undefined) {
|
|
549
|
+
try {
|
|
550
|
+
const invocationRaw: unknown = JSON.parse(
|
|
551
|
+
await readFile(join(run.runDirectory, "invocation.json"), "utf8"),
|
|
552
|
+
);
|
|
553
|
+
if (
|
|
554
|
+
invocationRaw !== null &&
|
|
555
|
+
typeof invocationRaw === "object" &&
|
|
556
|
+
!Array.isArray(invocationRaw)
|
|
557
|
+
) {
|
|
558
|
+
const fromInvocation = parsePersistedTicketIdentity(
|
|
559
|
+
invocationRaw as Record<string, unknown>,
|
|
560
|
+
);
|
|
561
|
+
if (correlationId === undefined) correlationId = fromInvocation.correlationId;
|
|
562
|
+
if (ticketNumber === undefined) ticketNumber = fromInvocation.ticketNumber;
|
|
563
|
+
}
|
|
564
|
+
} catch (error) {
|
|
565
|
+
if (
|
|
566
|
+
!(
|
|
567
|
+
error instanceof Error &&
|
|
568
|
+
"code" in error &&
|
|
569
|
+
(error as { code?: unknown }).code === "ENOENT"
|
|
570
|
+
)
|
|
571
|
+
) {
|
|
572
|
+
throw new CliUsageError(
|
|
573
|
+
`role run invocation identity is unreadable: ${runId}`,
|
|
574
|
+
{ cause: error },
|
|
575
|
+
);
|
|
576
|
+
}
|
|
577
|
+
}
|
|
578
|
+
}
|
|
573
579
|
return {
|
|
574
580
|
run,
|
|
575
581
|
observation: run.resumable,
|
|
@@ -585,6 +591,8 @@ async function loadResumableRunRecord(
|
|
|
585
591
|
...(baseRevision === undefined ? {} : { baseRevision }),
|
|
586
592
|
...(mergerInputPath === undefined ? {} : { mergerInputPath }),
|
|
587
593
|
...(derived === undefined ? {} : { derived }),
|
|
594
|
+
...(correlationId === undefined ? {} : { correlationId }),
|
|
595
|
+
...(ticketNumber === undefined ? {} : { ticketNumber }),
|
|
588
596
|
},
|
|
589
597
|
};
|
|
590
598
|
}
|
|
@@ -639,6 +647,7 @@ export async function loadResumableJudgeRun(
|
|
|
639
647
|
sessionDirectory: loaded.run.sessionDirectory,
|
|
640
648
|
sessionFile: loaded.run.sessionFile,
|
|
641
649
|
admittedRequestPath: loaded.run.admittedRequestPath,
|
|
650
|
+
...restoredTicketFields(loaded.admittedFields),
|
|
642
651
|
};
|
|
643
652
|
return {
|
|
644
653
|
admitted,
|
|
@@ -692,6 +701,7 @@ export async function loadResumableCoderRun(
|
|
|
692
701
|
sessionFile: loaded.run.sessionFile,
|
|
693
702
|
admittedRequestPath: loaded.run.admittedRequestPath,
|
|
694
703
|
taskPath,
|
|
704
|
+
...restoredTicketFields(loaded.admittedFields),
|
|
695
705
|
};
|
|
696
706
|
return {
|
|
697
707
|
admitted,
|
|
@@ -750,6 +760,7 @@ export async function loadResumableFixerRun(
|
|
|
750
760
|
? {}
|
|
751
761
|
: { prerequisitesPath: loaded.admittedFields.prerequisitesPath }),
|
|
752
762
|
prerequisites,
|
|
763
|
+
...restoredTicketFields(loaded.admittedFields),
|
|
753
764
|
};
|
|
754
765
|
return {
|
|
755
766
|
admitted,
|
|
@@ -795,6 +806,7 @@ export async function loadResumableReviewerRun(
|
|
|
795
806
|
sessionFile: loaded.run.sessionFile,
|
|
796
807
|
admittedRequestPath: loaded.run.admittedRequestPath,
|
|
797
808
|
baseRevision,
|
|
809
|
+
...restoredTicketFields(loaded.admittedFields),
|
|
798
810
|
};
|
|
799
811
|
return {
|
|
800
812
|
admitted,
|
|
@@ -854,6 +866,7 @@ export async function loadResumableMergerRun(
|
|
|
854
866
|
admittedRequestPath: loaded.run.admittedRequestPath,
|
|
855
867
|
mergerInputPath,
|
|
856
868
|
derived,
|
|
869
|
+
...restoredTicketFields(loaded.admittedFields),
|
|
857
870
|
};
|
|
858
871
|
return {
|
|
859
872
|
admitted,
|