@akagilnc/pi-workflow-roles 0.1.4489 → 0.1.4503
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/acp-host/production-host.js +372 -181
- package/dist/headless-host/production-host.js +372 -181
- package/dist/public-cli/countersign-run.js +214 -155
- package/dist/public-cli/diarist-run.js +4 -1
- package/dist/public-cli/invocation.js +129 -21
- package/dist/public-cli/main.js +372 -181
- package/package.json +1 -1
- package/src/public-cli/countersign-run.ts +326 -218
- package/src/public-cli/diarist-run.ts +4 -0
- package/src/public-cli/invocation.ts +205 -23
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { engineSessionMaterialFromOptions, pickEngineAxis } from "../package-resources/engine-material.js";
|
|
1
|
+
import { engineSessionMaterialFromOptions, pickEngineAxis, } from "../package-resources/engine-material.js";
|
|
2
2
|
import { CliUsageError } from "./cli-errors.js";
|
|
3
|
-
import { projectCourtTicketNumbers
|
|
3
|
+
import { projectCourtTicketNumbers } from "../diarist-contracts.js";
|
|
4
4
|
import { isSafePositiveTicketNumber } from "../run-ticket-number.js";
|
|
5
|
-
import { admitCountersignInvocation, bindAdmittedTicketNumber, bindCourtTicketNumbersOnAdmitted, buildCountersignTransportPrompt, relocateAdmittedRunToTicket, } from "./invocation.js";
|
|
5
|
+
import { admitCountersignInvocation, bindAdmittedTicketNumber, bindCourtTicketNumbersOnAdmitted, buildCountersignTransportPrompt, freezePreparedAttachmentsIntoRun, materializeCountersignInvocation, relocateAdmittedRunToTicket, withPreparedAttachments, } from "./invocation.js";
|
|
6
6
|
import { prepareSummonsResumeMaterials, presentControlledFailure, runPostAdmissionOneShot, runPostAdmissionSeatResume, resumeTurnRequestProjectionOptions, StationChildExhaustedError, } from "./post-admission.js";
|
|
7
|
-
import { loadResumableCountersignRun, markRunAdmitted,
|
|
7
|
+
import { loadResumableCountersignRun, markRunAdmitted, } from "./run-lifecycle.js";
|
|
8
8
|
import { tryResumeSameTicketSeatRun } from "./seat-ticket-binding.js";
|
|
9
9
|
import { presentStructuralRejection, trySettleCountersignTerminalResult, } from "./settlement.js";
|
|
10
10
|
import { projectRoleTurnRequest, } from "./turn-request.js";
|
|
@@ -36,11 +36,13 @@ function courtTicketNumbersFromOutcome(roleOutcome, principalTicket) {
|
|
|
36
36
|
const payloads = roleOutcome.kind === "accepted" ||
|
|
37
37
|
roleOutcome.kind === "audit_escalation" ||
|
|
38
38
|
roleOutcome.kind === "failure"
|
|
39
|
-
? roleOutcome.payloads ?? []
|
|
39
|
+
? (roleOutcome.payloads ?? [])
|
|
40
40
|
: [];
|
|
41
41
|
let latest;
|
|
42
42
|
for (const payload of payloads) {
|
|
43
|
-
if (typeof payload !== "object" ||
|
|
43
|
+
if (typeof payload !== "object" ||
|
|
44
|
+
payload === null ||
|
|
45
|
+
Array.isArray(payload)) {
|
|
44
46
|
continue;
|
|
45
47
|
}
|
|
46
48
|
const record = payload;
|
|
@@ -57,12 +59,12 @@ function courtTicketNumbersFromOutcome(roleOutcome, principalTicket) {
|
|
|
57
59
|
if (members.length === 0) {
|
|
58
60
|
// Literal [] is the intentional principal-only replace; non-empty garbage is not.
|
|
59
61
|
if (raw.length === 0) {
|
|
60
|
-
latest =
|
|
62
|
+
latest =
|
|
63
|
+
projectCourtTicketNumbers([], { principalTicket }) ?? undefined;
|
|
61
64
|
}
|
|
62
65
|
continue;
|
|
63
66
|
}
|
|
64
|
-
latest =
|
|
65
|
-
projectCourtTicketNumbers(raw, { principalTicket }) ?? undefined;
|
|
67
|
+
latest = projectCourtTicketNumbers(raw, { principalTicket }) ?? undefined;
|
|
66
68
|
}
|
|
67
69
|
return latest;
|
|
68
70
|
}
|
|
@@ -75,10 +77,12 @@ function courtDiaristEscalated(roleOutcome) {
|
|
|
75
77
|
if (roleOutcome.kind !== "accepted")
|
|
76
78
|
return false;
|
|
77
79
|
return (roleOutcome.payloads ?? []).some((payload) => {
|
|
78
|
-
if (typeof payload !== "object" ||
|
|
80
|
+
if (typeof payload !== "object" ||
|
|
81
|
+
payload === null ||
|
|
82
|
+
Array.isArray(payload))
|
|
79
83
|
return false;
|
|
80
84
|
const record = payload;
|
|
81
|
-
return record.status === "escalate" || record.countersignStatus === "escalate";
|
|
85
|
+
return (record.status === "escalate" || record.countersignStatus === "escalate");
|
|
82
86
|
});
|
|
83
87
|
}
|
|
84
88
|
/**
|
|
@@ -116,13 +120,17 @@ export async function invokeCourtDiarist(input, env, io) {
|
|
|
116
120
|
io: quietIo,
|
|
117
121
|
...(env.credentials === undefined ? {} : { credentials: env.credentials }),
|
|
118
122
|
...(env.signal === undefined ? {} : { signal: env.signal }),
|
|
119
|
-
...(input.correlationId === undefined
|
|
123
|
+
...(input.correlationId === undefined
|
|
124
|
+
? {}
|
|
125
|
+
: { correlationId: input.correlationId }),
|
|
120
126
|
...(input.boundTicketNumber === undefined
|
|
121
127
|
? {}
|
|
122
128
|
: { boundTicketNumber: input.boundTicketNumber }),
|
|
123
129
|
// Child seat selects from the composition-root table. Do not pass the
|
|
124
130
|
// already-selected parent adapter (#840 / ADR 0082: --host 旗标>席位配置>缺省 pi).
|
|
125
|
-
...(env.hostAdapters === undefined
|
|
131
|
+
...(env.hostAdapters === undefined
|
|
132
|
+
? {}
|
|
133
|
+
: { hostAdapters: env.hostAdapters }),
|
|
126
134
|
});
|
|
127
135
|
const roleOutcome = result.terminal?.roleOutcome;
|
|
128
136
|
// Escalate routing is a boolean over the preserved sequence (#881). Reasons and
|
|
@@ -143,7 +151,8 @@ export async function invokeCourtDiarist(input, env, io) {
|
|
|
143
151
|
},
|
|
144
152
|
};
|
|
145
153
|
}
|
|
146
|
-
const asserted = result.admitted
|
|
154
|
+
const asserted = result.admitted
|
|
155
|
+
?.ticketNumber;
|
|
147
156
|
if (isSafePositiveTicketNumber(asserted)) {
|
|
148
157
|
const courtTicketNumbers = courtTicketNumbersFromOutcome(roleOutcome, asserted);
|
|
149
158
|
return {
|
|
@@ -230,9 +239,14 @@ export async function runPublicCountersign(argv, env, io, parseCountersignArgv)
|
|
|
230
239
|
instruction: parsed.instruction,
|
|
231
240
|
attachmentPaths: parsed.attachmentPaths,
|
|
232
241
|
...(parsed.project === undefined ? {} : { project: parsed.project }),
|
|
233
|
-
...(env.createRunId === undefined
|
|
242
|
+
...(env.createRunId === undefined
|
|
243
|
+
? {}
|
|
244
|
+
: { createRunId: env.createRunId }),
|
|
234
245
|
...(env.model === undefined ? {} : { model: env.model }),
|
|
235
|
-
...(env.correlationId === undefined
|
|
246
|
+
...(env.correlationId === undefined
|
|
247
|
+
? {}
|
|
248
|
+
: { correlationId: env.correlationId }),
|
|
249
|
+
deferPersistence: true,
|
|
236
250
|
});
|
|
237
251
|
}
|
|
238
252
|
catch (error) {
|
|
@@ -242,152 +256,197 @@ export async function runPublicCountersign(argv, env, io, parseCountersignArgv)
|
|
|
242
256
|
}
|
|
243
257
|
throw error;
|
|
244
258
|
}
|
|
245
|
-
|
|
246
|
-
//
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
if (env.runCourtDiaristStation === undefined) {
|
|
257
|
-
const outcome = await invokeCourtDiarist({
|
|
258
|
-
instruction: parsed.instruction,
|
|
259
|
-
projectRoot: admitted.projectRoot,
|
|
260
|
-
failureLabel: "unbound summons",
|
|
261
|
-
correlationId: admitted.runId,
|
|
262
|
-
}, env, io);
|
|
263
|
-
identityDiaristRan = true;
|
|
264
|
-
if (outcome.identity.kind === "escalate") {
|
|
265
|
-
// 御批: 识别不了就上抛 — settle on the admitted countersign run.
|
|
266
|
-
return await presentControlledFailure(admitted, {
|
|
267
|
-
timedOut: false,
|
|
268
|
-
code: null,
|
|
269
|
-
stderr: "",
|
|
270
|
-
thrown: new Error("court diarist station escalated (cannot identify court target)"),
|
|
271
|
-
}, countersignAdapters(), env.principalAuthority, io);
|
|
272
|
-
}
|
|
273
|
-
// Typed failure terminal (verification / infra / non-zero without escalate)
|
|
274
|
-
// is not 真无票 — settle controlled failure on the admitted run (失败诚实).
|
|
275
|
-
// Only a true missing lawful typed terminal keeps the r5 unbound-continue.
|
|
276
|
-
if (outcome.failedWithoutEscalate !== undefined) {
|
|
277
|
-
return await presentControlledFailure(admitted, {
|
|
278
|
-
timedOut: false,
|
|
279
|
-
code: null,
|
|
280
|
-
stderr: "",
|
|
281
|
-
thrown: new Error(outcome.failedWithoutEscalate.diagnostic),
|
|
282
|
-
}, countersignAdapters(), env.principalAuthority, io);
|
|
283
|
-
}
|
|
284
|
-
// Missing lawful 起居郎 terminal is not countersign body failure: leave
|
|
285
|
-
// unbound and continue (true-unbound face). Escalate / typed failure above;
|
|
286
|
-
// bound refresh still fails honest via runCountersignCourtDiaristStation.
|
|
287
|
-
if (outcome.identity.kind === "ticket") {
|
|
288
|
-
const assertedTicket = outcome.identity.ticketNumber;
|
|
289
|
-
typedTicket = assertedTicket;
|
|
290
|
-
// #871: identity may hand a co-review set; absent field defaults to [main].
|
|
291
|
-
typedCourtTicketNumbers = outcome.identity.courtTicketNumbers;
|
|
292
|
-
const summons = {
|
|
293
|
-
instruction: parsed.instruction,
|
|
294
|
-
instructionEmpty: parsed.instruction.trim() === "",
|
|
295
|
-
attachmentPaths: parsed.attachmentPaths,
|
|
259
|
+
// One owner spans prepare, lookup/load/resume or new-run materialization.
|
|
260
|
+
// It preserves both causes when its final cleanup also fails.
|
|
261
|
+
try {
|
|
262
|
+
return await withPreparedAttachments(parsed.attachmentPaths, async (preparedAttachments) => {
|
|
263
|
+
const materializeAdmission = async () => {
|
|
264
|
+
await materializeCountersignInvocation(admitted, {
|
|
265
|
+
home: env.home,
|
|
266
|
+
principalAuthority: env.principalAuthority,
|
|
267
|
+
preparedAttachments,
|
|
268
|
+
...(env.model === undefined ? {} : { model: env.model }),
|
|
269
|
+
});
|
|
296
270
|
};
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
271
|
+
// #637 / #771 / ADR 0079: ticket identity is the 起居郎 LLM typed assertion
|
|
272
|
+
// (never mechanical matching of summons text). Resolve that typed key before
|
|
273
|
+
// materializing a run: same-ticket re-summons write only to the retained run.
|
|
274
|
+
// Controlled failures materialize below so they still have a durable page. The test
|
|
275
|
+
// seam `runCourtDiaristStation` defers identity to beforeDispatch; generic
|
|
276
|
+
// hook failures stay on the parent call-local budget, exhausted nested
|
|
277
|
+
// station children still skip parent auto-resume (#840 父子不层叠).
|
|
278
|
+
let typedTicket;
|
|
279
|
+
let typedCourtTicketNumbers;
|
|
280
|
+
let identityDiaristRan = false;
|
|
281
|
+
if (env.runCourtDiaristStation === undefined) {
|
|
282
|
+
let outcome;
|
|
283
|
+
try {
|
|
284
|
+
// The identity child cannot name the newly minted countersign id as parent:
|
|
285
|
+
// same-ticket lookup may intentionally never materialize that run. A selected
|
|
286
|
+
// retained run receives its normally correlated refresh child during resume.
|
|
287
|
+
outcome = await invokeCourtDiarist({
|
|
288
|
+
instruction: parsed.instruction,
|
|
289
|
+
projectRoot: admitted.projectRoot,
|
|
290
|
+
failureLabel: "unbound summons",
|
|
291
|
+
}, env, io);
|
|
292
|
+
}
|
|
293
|
+
catch (error) {
|
|
294
|
+
await materializeAdmission();
|
|
295
|
+
await markRunAdmitted(admitted, env.principalAuthority);
|
|
296
|
+
return await presentControlledFailure(admitted, { timedOut: false, code: null, stderr: "", thrown: error }, countersignAdapters(), env.principalAuthority, io);
|
|
297
|
+
}
|
|
298
|
+
identityDiaristRan = true;
|
|
299
|
+
if (outcome.identity.kind === "escalate") {
|
|
300
|
+
// 御批: 识别不了就上抛 — materialize and settle this countersign run.
|
|
301
|
+
await materializeAdmission();
|
|
302
|
+
await markRunAdmitted(admitted, env.principalAuthority);
|
|
303
|
+
return await presentControlledFailure(admitted, {
|
|
304
|
+
timedOut: false,
|
|
305
|
+
code: null,
|
|
306
|
+
stderr: "",
|
|
307
|
+
thrown: new Error("court diarist station escalated (cannot identify court target)"),
|
|
308
|
+
}, countersignAdapters(), env.principalAuthority, io);
|
|
309
|
+
}
|
|
310
|
+
// Typed failure terminal (verification / infra / non-zero without escalate)
|
|
311
|
+
// is not 真无票 — settle controlled failure on the admitted run (失败诚实).
|
|
312
|
+
// Only a true missing lawful typed terminal keeps the r5 unbound-continue.
|
|
313
|
+
if (outcome.failedWithoutEscalate !== undefined) {
|
|
314
|
+
await materializeAdmission();
|
|
315
|
+
await markRunAdmitted(admitted, env.principalAuthority);
|
|
316
|
+
return await presentControlledFailure(admitted, {
|
|
317
|
+
timedOut: false,
|
|
318
|
+
code: null,
|
|
319
|
+
stderr: "",
|
|
320
|
+
thrown: new Error(outcome.failedWithoutEscalate.diagnostic),
|
|
321
|
+
}, countersignAdapters(), env.principalAuthority, io);
|
|
322
|
+
}
|
|
323
|
+
// Missing lawful 起居郎 terminal is not countersign body failure: leave
|
|
324
|
+
// unbound and continue (true-unbound face). Escalate / typed failure above;
|
|
325
|
+
// bound refresh still fails honest via runCountersignCourtDiaristStation.
|
|
326
|
+
if (outcome.identity.kind === "ticket") {
|
|
327
|
+
const assertedTicket = outcome.identity.ticketNumber;
|
|
328
|
+
typedTicket = assertedTicket;
|
|
329
|
+
// #871: identity may hand a co-review set; absent field defaults to [main].
|
|
330
|
+
typedCourtTicketNumbers = outcome.identity.courtTicketNumbers;
|
|
331
|
+
const summons = {
|
|
332
|
+
instruction: parsed.instruction,
|
|
333
|
+
instructionEmpty: parsed.instruction.trim() === "",
|
|
334
|
+
};
|
|
335
|
+
const resumed = await tryResumeSameTicketSeatRun({
|
|
336
|
+
home: env.home,
|
|
337
|
+
projectRoot: admitted.projectRoot,
|
|
338
|
+
role: "countersign",
|
|
339
|
+
ticketNumber: typedTicket,
|
|
340
|
+
freshSummons: env.freshSummons,
|
|
341
|
+
summons,
|
|
342
|
+
resume: async (runId, materials) => {
|
|
343
|
+
// Consume the same pre-identity snapshot into the retained run; never
|
|
344
|
+
// reopen caller paths after identity has run.
|
|
345
|
+
const retained = await loadResumableCountersignRun(env.home, runId, env.principalAuthority);
|
|
346
|
+
if (retained.admitted === undefined) {
|
|
347
|
+
throw new Error(`retained countersign run disappeared before resume: ${runId}`);
|
|
348
|
+
}
|
|
349
|
+
const frozenPaths = (await freezePreparedAttachmentsIntoRun(preparedAttachments, retained.admitted.runDirectory, `s-${Date.now().toString(36)}`)).map((attachment) => attachment.frozenPath);
|
|
350
|
+
const preparedMaterials = {
|
|
351
|
+
...(materials ?? {}),
|
|
352
|
+
...(frozenPaths.length === 0
|
|
353
|
+
? {}
|
|
354
|
+
: { attachmentPaths: frozenPaths }),
|
|
355
|
+
};
|
|
356
|
+
// Identity 起居郎 asserted unbound (no issue face). Resume still runs
|
|
357
|
+
// the bound refresh station under the typed key (ADR 0075: 每次过庭都跑是调用者用法).
|
|
358
|
+
// #871: hand the identity set so resume can whole-replace the run fact
|
|
359
|
+
// when this summons produced a new typed set (never union).
|
|
360
|
+
return await runPublicCountersignResume({
|
|
361
|
+
runId,
|
|
362
|
+
summons: preparedMaterials,
|
|
363
|
+
}, {
|
|
364
|
+
...env,
|
|
365
|
+
...(typedCourtTicketNumbers === undefined
|
|
366
|
+
? {}
|
|
367
|
+
: { pendingCourtTicketNumbers: typedCourtTicketNumbers }),
|
|
368
|
+
}, io);
|
|
369
|
+
},
|
|
370
|
+
});
|
|
371
|
+
if (resumed !== undefined) {
|
|
372
|
+
return resumed;
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
// No prior run was selected. Materialize this invocation now; true-unbound,
|
|
377
|
+
// first-ticket and deferred test-seam paths all retain their own durable page.
|
|
378
|
+
await materializeAdmission();
|
|
379
|
+
await markRunAdmitted(admitted, env.principalAuthority);
|
|
380
|
+
if (identityDiaristRan && typedTicket !== undefined) {
|
|
381
|
+
try {
|
|
382
|
+
await bindAdmittedTicketNumber(admitted, typedTicket);
|
|
308
383
|
await relocateAdmittedRunToTicket(admitted, env.principalAuthority);
|
|
309
|
-
|
|
310
|
-
//
|
|
311
|
-
//
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
384
|
+
// First court: explicit set wins; omitted field → single-ticket face [main].
|
|
385
|
+
// Set persistence is outside beforeDispatch — route write failures into the
|
|
386
|
+
// same controlled-failure settlement as station children (#871 B7).
|
|
387
|
+
await bindCourtTicketNumbersOnAdmitted(admitted, typedCourtTicketNumbers ?? [typedTicket]);
|
|
388
|
+
}
|
|
389
|
+
catch (error) {
|
|
390
|
+
return await presentControlledFailure(admitted, {
|
|
391
|
+
timedOut: false,
|
|
392
|
+
code: null,
|
|
393
|
+
stderr: "",
|
|
394
|
+
thrown: error,
|
|
395
|
+
}, countersignAdapters(), env.principalAuthority, io);
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
const turnProjection = {
|
|
399
|
+
packageRoot: env.packageRoot,
|
|
400
|
+
home: env.home,
|
|
401
|
+
agentDir: env.agentDir,
|
|
402
|
+
...(env.model === undefined ? {} : { model: env.model }),
|
|
403
|
+
...pickEngineAxis(env),
|
|
404
|
+
...(env.timeoutMs === undefined ? {} : { timeoutMs: env.timeoutMs }),
|
|
405
|
+
...(env.correlationId === undefined || env.correlationId.trim() === ""
|
|
406
|
+
? {}
|
|
407
|
+
: { correlationId: env.correlationId }),
|
|
408
|
+
continuation: {
|
|
409
|
+
kind: "initial",
|
|
410
|
+
prompt: buildCountersignTransportPrompt(admitted, engineSessionMaterialFromOptions({
|
|
411
|
+
...pickEngineAxis(env),
|
|
412
|
+
packageRoot: env.packageRoot,
|
|
413
|
+
})),
|
|
323
414
|
},
|
|
415
|
+
};
|
|
416
|
+
// Mutable shell: ticket bind re-projects activation before executeTurn.
|
|
417
|
+
const turnRequest = buildCountersignTurnRequest(admitted, turnProjection);
|
|
418
|
+
const result = await runPostAdmissionOneShot({
|
|
419
|
+
admitted,
|
|
420
|
+
env,
|
|
421
|
+
io,
|
|
422
|
+
request: turnRequest,
|
|
423
|
+
adapters: countersignAdapters({
|
|
424
|
+
beforeDispatch: async (admittedSeat, lease) => {
|
|
425
|
+
// Dossier pointer delivery rides post-admission after this hook (#709).
|
|
426
|
+
if (!identityDiaristRan) {
|
|
427
|
+
// Test seam (or any deferred identity): station owns assert + bind.
|
|
428
|
+
await runCountersignCourtDiaristStation(admittedSeat, env, io);
|
|
429
|
+
}
|
|
430
|
+
else if (typedTicket !== undefined) {
|
|
431
|
+
await runCountersignCourtDiaristStation(admittedSeat, env, io);
|
|
432
|
+
}
|
|
433
|
+
await relocateAdmittedRunToTicket(admittedSeat, env.principalAuthority, lease);
|
|
434
|
+
Object.assign(turnRequest, buildCountersignTurnRequest(admittedSeat, turnProjection));
|
|
435
|
+
},
|
|
436
|
+
}),
|
|
437
|
+
...(env.engine === undefined ? {} : { effectiveEngine: env.engine }),
|
|
324
438
|
});
|
|
325
|
-
if (resumed !== undefined) {
|
|
326
|
-
return resumed;
|
|
327
|
-
}
|
|
328
|
-
}
|
|
329
|
-
}
|
|
330
|
-
if (identityDiaristRan && typedTicket !== undefined) {
|
|
331
|
-
try {
|
|
332
|
-
await bindAdmittedTicketNumber(admitted, typedTicket);
|
|
333
439
|
await relocateAdmittedRunToTicket(admitted, env.principalAuthority);
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
return
|
|
341
|
-
timedOut: false,
|
|
342
|
-
code: null,
|
|
343
|
-
stderr: "",
|
|
344
|
-
thrown: error,
|
|
345
|
-
}, countersignAdapters(), env.principalAuthority, io);
|
|
440
|
+
return result;
|
|
441
|
+
});
|
|
442
|
+
}
|
|
443
|
+
catch (error) {
|
|
444
|
+
if (error instanceof CliUsageError) {
|
|
445
|
+
presentStructuralRejection(error, io);
|
|
446
|
+
return { exitCode: 2 };
|
|
346
447
|
}
|
|
448
|
+
throw error;
|
|
347
449
|
}
|
|
348
|
-
const turnProjection = {
|
|
349
|
-
packageRoot: env.packageRoot,
|
|
350
|
-
home: env.home,
|
|
351
|
-
agentDir: env.agentDir,
|
|
352
|
-
...(env.model === undefined ? {} : { model: env.model }),
|
|
353
|
-
...pickEngineAxis(env),
|
|
354
|
-
...(env.timeoutMs === undefined ? {} : { timeoutMs: env.timeoutMs }),
|
|
355
|
-
...(env.correlationId === undefined || env.correlationId.trim() === ""
|
|
356
|
-
? {}
|
|
357
|
-
: { correlationId: env.correlationId }),
|
|
358
|
-
continuation: {
|
|
359
|
-
kind: "initial",
|
|
360
|
-
prompt: buildCountersignTransportPrompt(admitted, engineSessionMaterialFromOptions({
|
|
361
|
-
...pickEngineAxis(env),
|
|
362
|
-
packageRoot: env.packageRoot,
|
|
363
|
-
})),
|
|
364
|
-
},
|
|
365
|
-
};
|
|
366
|
-
// Mutable shell: ticket bind re-projects activation before executeTurn.
|
|
367
|
-
const turnRequest = buildCountersignTurnRequest(admitted, turnProjection);
|
|
368
|
-
const result = await runPostAdmissionOneShot({
|
|
369
|
-
admitted,
|
|
370
|
-
env,
|
|
371
|
-
io,
|
|
372
|
-
request: turnRequest,
|
|
373
|
-
adapters: countersignAdapters({
|
|
374
|
-
beforeDispatch: async (admittedSeat, lease) => {
|
|
375
|
-
// Dossier pointer delivery rides post-admission after this hook (#709).
|
|
376
|
-
if (!identityDiaristRan) {
|
|
377
|
-
// Test seam (or any deferred identity): station owns assert + bind.
|
|
378
|
-
await runCountersignCourtDiaristStation(admittedSeat, env, io);
|
|
379
|
-
}
|
|
380
|
-
else if (typedTicket !== undefined) {
|
|
381
|
-
await runCountersignCourtDiaristStation(admittedSeat, env, io);
|
|
382
|
-
}
|
|
383
|
-
await relocateAdmittedRunToTicket(admittedSeat, env.principalAuthority, lease);
|
|
384
|
-
Object.assign(turnRequest, buildCountersignTurnRequest(admittedSeat, turnProjection));
|
|
385
|
-
},
|
|
386
|
-
}),
|
|
387
|
-
...(env.engine === undefined ? {} : { effectiveEngine: env.engine }),
|
|
388
|
-
});
|
|
389
|
-
await relocateAdmittedRunToTicket(admitted, env.principalAuthority);
|
|
390
|
-
return result;
|
|
391
450
|
}
|
|
392
451
|
function countersignAdapters(options) {
|
|
393
452
|
return {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { engineSessionMaterialFromOptions, pickEngineAxis } from "../package-resources/engine-material.js";
|
|
2
2
|
import { CliUsageError } from "./cli-errors.js";
|
|
3
|
-
import { admitDiaristInvocation, bindAdmittedTicketNumber, buildInstructionTransportPrompt, relocateAdmittedRunToTicket, } from "./invocation.js";
|
|
3
|
+
import { admitDiaristInvocation, bindAdmittedTicketNumber, buildInstructionTransportPrompt, relocateAdmittedRunToTicket, recordAdmittedCorrelation, } from "./invocation.js";
|
|
4
4
|
import { prepareSummonsResumeMaterials, runPostAdmissionOneShot, runPostAdmissionSeatResume, resumeTurnRequestProjectionOptions, } from "./post-admission.js";
|
|
5
5
|
import { loadResumableDiaristRun, markRunAdmitted, } from "./run-lifecycle.js";
|
|
6
6
|
import { tryResumeSameTicketSeatRun } from "./seat-ticket-binding.js";
|
|
@@ -30,6 +30,9 @@ function diaristAdapters(env) {
|
|
|
30
30
|
shouldPresentSettled: () => true,
|
|
31
31
|
// Resume interrupted state: board ticket already on pages, run still under unbound/.
|
|
32
32
|
beforeDispatch: async (admitted, lease) => {
|
|
33
|
+
if (env.correlationId !== undefined && env.correlationId.trim() !== "") {
|
|
34
|
+
await recordAdmittedCorrelation(admitted, env.correlationId);
|
|
35
|
+
}
|
|
33
36
|
await bindAndRelocateDiaristIfBoardBound(admitted, env.principalAuthority, lease);
|
|
34
37
|
},
|
|
35
38
|
// First post-turn assert: accept hook wrote board pages; relocate before lease release.
|