@akagilnc/pi-workflow-roles 0.1.4745 → 0.1.4772
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 +278 -590
- package/dist/headless-host/production-host.js +284 -596
- package/dist/migrate-book-topology.js +1255 -1087
- package/dist/notary-source-run.js +12 -2
- package/dist/public-cli/invocation.js +11 -8
- package/dist/public-cli/main.js +250 -563
- package/dist/public-cli/post-admission.js +96 -131
- package/dist/public-cli/run-lifecycle.js +25 -4
- package/dist/role-run-relocation.js +19 -18
- package/package.json +1 -1
- package/src/book-topology-migration-placement.ts +9 -1
- package/src/book-topology-runs-migrator.ts +156 -4
- package/src/notary-source-run.ts +18 -2
- package/src/public-cli/cli.ts +0 -5
- package/src/public-cli/config.ts +0 -1
- package/src/public-cli/countersign-run.ts +1 -1
- package/src/public-cli/diarist-run.ts +1 -1
- package/src/public-cli/invocation.ts +13 -9
- package/src/public-cli/post-admission.ts +124 -187
- package/src/public-cli/run-lifecycle.ts +42 -4
- package/src/role-run-relocation.ts +27 -30
- package/dist/public-cli/public-run-credentials.js +0 -49
- package/src/public-cli/public-run-credentials.ts +0 -71
|
@@ -10,11 +10,12 @@ import { writeFile } from "node:fs/promises";
|
|
|
10
10
|
import { isAbsolute, join, resolve } from "node:path";
|
|
11
11
|
import { buildAutoResumeContinuationPrompt, buildResumeContinuationPrompt, RESUME_TRANSPORT_ENVELOPE, } from "./run-lifecycle.js";
|
|
12
12
|
import { CliUsageError } from "./cli-errors.js";
|
|
13
|
-
import { bindAdmittedTicketNumber, buildInstructionTransportPrompt, freezeAttachmentsIntoRun, } from "./invocation.js";
|
|
13
|
+
import { bindAdmittedTicketNumber, buildInstructionTransportPrompt, freezeAttachmentsIntoRun, relocateAdmittedRunToTicket, } from "./invocation.js";
|
|
14
14
|
import { readRecordedSubmissionRows } from "../submission-ledger.js";
|
|
15
15
|
import { pathContainedIn } from "../activation-ledger-topology.js";
|
|
16
16
|
import { pickEngineAxis } from "../package-resources/engine-material.js";
|
|
17
17
|
import { resolveHostAwareSessionAvailability } from "../session-identity.js";
|
|
18
|
+
import { rewriteRunDirectoryPathValue } from "../role-run-relocation.js";
|
|
18
19
|
import { isOfficerReviewSeat } from "../host-contracts.js";
|
|
19
20
|
import { deliverCaseDossierAsAttachment } from "./case-dossier-delivery.js";
|
|
20
21
|
/** Original error bytes, never relabeled — a secondary fact riding beside a classified cause. */
|
|
@@ -35,13 +36,31 @@ function isStationChildOfficerDialogue(role, env) {
|
|
|
35
36
|
}
|
|
36
37
|
import { mintEngineDetourInvocationScope, readInvocationSelectedHost, withEngineDetourInvocationScope, } from "../engine-detour-usage.js";
|
|
37
38
|
import { projectHostTransitionPriorNative } from "../host-transition-prior-native.js";
|
|
38
|
-
import {
|
|
39
|
-
import { acquireRunWriterLease, clearCurrentCourt, clearTypedProviderHttpObservation, describeErrorIdentity, markRunRunning, readCurrentCourt, recordCurrentCourt, renderResumeCommand, RunWriterLeaseHeldError, } from "./run-lifecycle.js";
|
|
39
|
+
import { clearCurrentCourt, clearTypedProviderHttpObservation, describeErrorIdentity, markRunRunning, readCurrentCourt, recordCurrentCourt, renderResumeCommand, } from "./run-lifecycle.js";
|
|
40
40
|
import { processCancelDiagnostic, processCancelSignalName, } from "./process-cancel.js";
|
|
41
41
|
import { homeFromRunDirectory } from "../activation-ledger-topology.js";
|
|
42
42
|
import { attemptProducedFreshSubmission, classifyPostAdmissionFailure, controlledFailureInputFromResolution, exitCodeForTerminalOutcome, explicitInternalKnownFailureClassificationInput, formatCliDiagnostic, formatTerminalResult, inspectJudgeSession, isLawfulTypedTerminalOutcome, presentFailureTerminal, presentStructuralRejection, resolveAuditedRunnerFailureResolution, resolveControlledFailureResumeObservation, settleFailureTerminalResult, settleHostEndedNoReceipt, attachRecordedSubmissions, } from "./settlement.js";
|
|
43
43
|
import {} from "./terminal.js";
|
|
44
44
|
import { ensureRealArtifactsDirectory, persistReturnedRunState, runWithAutoResumeLoop, TurnDispatchedFailure, } from "./auto-resume.js";
|
|
45
|
+
function projectRelocatedTurnIdentity(request, result, admitted, relocation) {
|
|
46
|
+
const rewrite = (value) => rewriteRunDirectoryPathValue(value, relocation.oldRunDirectory, relocation.newRunDirectory);
|
|
47
|
+
const mutableRequest = request;
|
|
48
|
+
mutableRequest.runDirectory = admitted.runDirectory;
|
|
49
|
+
mutableRequest.principal = admitted.principal;
|
|
50
|
+
const activation = mutableRequest.activation;
|
|
51
|
+
if (activation !== null && typeof activation === "object" && !Array.isArray(activation)) {
|
|
52
|
+
for (const field of ["taskPath", "packetPath", "prerequisitesPath", "inputPath", "requestManifestPath"]) {
|
|
53
|
+
const record = activation;
|
|
54
|
+
if (field in record)
|
|
55
|
+
record[field] = rewrite(record[field]);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
if (result.terminal !== undefined) {
|
|
59
|
+
for (const artifact of result.terminal.artifacts) {
|
|
60
|
+
artifact.path = rewrite(artifact.path);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
45
64
|
/** #855: process-cancel settlement never re-enters auto-resume. */
|
|
46
65
|
function withProcessCancelSkipAutoResume(result, signal) {
|
|
47
66
|
if (processCancelSignalName(signal) === undefined) {
|
|
@@ -110,11 +129,10 @@ export const POST_ADMISSION_CLEANUP_DIAGNOSTIC_ENTRY_TYPE = "ak_post_admission_c
|
|
|
110
129
|
* redundant second copy (#840 bounce class 1: 同一业务规则只保留一个权威实现).
|
|
111
130
|
*/
|
|
112
131
|
async function recordBestEffortPostDispatchDiagnostic(admitted, env, diagnostic, io) {
|
|
113
|
-
io.stderr(formatCliDiagnostic(diagnostic));
|
|
114
132
|
const payload = { diagnostic, recordedAt: new Date().toISOString() };
|
|
133
|
+
let retentionFailure;
|
|
115
134
|
try {
|
|
116
135
|
await env.sessionAppender(env.principalAuthority, admitted.principal, POST_ADMISSION_CLEANUP_DIAGNOSTIC_ENTRY_TYPE, payload);
|
|
117
|
-
return;
|
|
118
136
|
}
|
|
119
137
|
catch (appendError) {
|
|
120
138
|
try {
|
|
@@ -122,9 +140,19 @@ async function recordBestEffortPostDispatchDiagnostic(admitted, env, diagnostic,
|
|
|
122
140
|
await writeFile(join(artifactsDir, `post-admission-diagnostic-${randomUUID()}.json`), `${JSON.stringify({ version: 1, ...payload }, null, 2)}\n`, { encoding: "utf8", flag: "wx" });
|
|
123
141
|
}
|
|
124
142
|
catch (artifactError) {
|
|
125
|
-
|
|
143
|
+
retentionFailure =
|
|
144
|
+
`post-dispatch diagnostic durable retention failed on both channels (best-effort continue): dossier=${describeErrorIdentity(appendError)}; artifact=${describeErrorIdentity(artifactError)}`;
|
|
126
145
|
}
|
|
127
146
|
}
|
|
147
|
+
try {
|
|
148
|
+
io.stderr(formatCliDiagnostic(diagnostic));
|
|
149
|
+
if (retentionFailure !== undefined) {
|
|
150
|
+
io.stderr(formatCliDiagnostic(retentionFailure));
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
catch {
|
|
154
|
+
// Presentation is best-effort beside an already-formed host terminal.
|
|
155
|
+
}
|
|
128
156
|
}
|
|
129
157
|
/**
|
|
130
158
|
* Factory-seat resume method-material face (#833): one authority for
|
|
@@ -325,15 +353,19 @@ export async function dispatchPostAdmissionTurn(input) {
|
|
|
325
353
|
if (ticketNumber !== undefined)
|
|
326
354
|
await bindAdmittedTicketNumber(admitted, ticketNumber);
|
|
327
355
|
}
|
|
356
|
+
// #863: shared post-admission bind must relocate unbound→ticket in-home
|
|
357
|
+
// before lease release (work-seat self-report and any prior board bind).
|
|
358
|
+
const relocation = await relocateAdmittedRunToTicket(admitted, env.principalAuthority, lease);
|
|
359
|
+
if (relocation !== undefined) {
|
|
360
|
+
projectRelocatedTurnIdentity(request, result, admitted, relocation);
|
|
361
|
+
}
|
|
328
362
|
if (adapters.afterDispatch !== undefined)
|
|
329
363
|
await adapters.afterDispatch(admitted, lease);
|
|
330
364
|
return result;
|
|
331
365
|
}
|
|
332
366
|
catch (error) {
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
if (primaryFailure) {
|
|
336
|
-
await recordBestEffortPostDispatchDiagnostic(admitted, env, `afterDispatch failed beside primary terminal (best-effort continue): ${describeErrorIdentity(error)}`, io);
|
|
367
|
+
if (result.terminal !== undefined) {
|
|
368
|
+
await recordBestEffortPostDispatchDiagnostic(admitted, env, `afterDispatch failed beside host terminal (best-effort continue): ${describeErrorIdentity(error)}`, io);
|
|
337
369
|
return result;
|
|
338
370
|
}
|
|
339
371
|
return {
|
|
@@ -350,13 +382,8 @@ export async function dispatchPostAdmissionTurn(input) {
|
|
|
350
382
|
}
|
|
351
383
|
};
|
|
352
384
|
try {
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
return {
|
|
356
|
-
...(await presentControlledFailure(admitted, withEngineDetourInvocationScope(missingCredential, request.invocationScopeId), adapters, env.principalAuthority, io, persistRunState)),
|
|
357
|
-
...deferredPersist,
|
|
358
|
-
};
|
|
359
|
-
}
|
|
385
|
+
// #987: do not pre-block or classify host dispatch from AK credential
|
|
386
|
+
// catalog facts. Per-invocation runner/host evidence owns provider identity.
|
|
360
387
|
// #617 DK-4: capture previous invocation host before markRunRunning overwrites it.
|
|
361
388
|
// Single authority projectHostTransitionPriorNative classifies the prior native volume.
|
|
362
389
|
// Same-run resume (#637) keeps host identity on the run's invocation page.
|
|
@@ -549,11 +576,10 @@ export async function dispatchPostAdmissionTurn(input) {
|
|
|
549
576
|
const runnerKnownFailure = adapters.resolveRunnerKnownFailure !== undefined && sessionFile !== ""
|
|
550
577
|
? await adapters.resolveRunnerKnownFailure({ result, sessionFile })
|
|
551
578
|
: result.knownFailure;
|
|
552
|
-
const credentialFailure = postRunMissingCredentialFailure(result, env.model, env.credentials);
|
|
553
579
|
resolution = await resolveAuditedRunnerFailureResolution({
|
|
554
580
|
runner: runnerKnownFailure,
|
|
555
581
|
sessionFile,
|
|
556
|
-
credential:
|
|
582
|
+
credential: undefined,
|
|
557
583
|
runDirectory: admitted.runDirectory,
|
|
558
584
|
});
|
|
559
585
|
// A direct, current signal from the host/runner itself (timeout / host
|
|
@@ -573,7 +599,6 @@ export async function dispatchPostAdmissionTurn(input) {
|
|
|
573
599
|
const directHostFailureSignal = result.timedOut
|
|
574
600
|
|| result.knownFailure !== undefined
|
|
575
601
|
|| runnerKnownFailure !== undefined
|
|
576
|
-
|| credentialFailure !== undefined
|
|
577
602
|
|| processCancelName !== undefined;
|
|
578
603
|
hostSignalFailed =
|
|
579
604
|
directHostFailureSignal
|
|
@@ -679,24 +704,7 @@ export async function dispatchPostAdmissionTurn(input) {
|
|
|
679
704
|
await persistReturnedRunState(admitted, env.principalAuthority, { lawful: true });
|
|
680
705
|
}
|
|
681
706
|
catch (error) {
|
|
682
|
-
|
|
683
|
-
// submissions (attachRecordedSubmissions above). A real run-state
|
|
684
|
-
// persistence failure here must surface loudly through the same
|
|
685
|
-
// controlled-failure seam every other dispatch-time failure in
|
|
686
|
-
// this function uses (ADR 0080: one settlement disposition owner)
|
|
687
|
-
// — not escape uncaught to auto-resume's dispatch-retry path,
|
|
688
|
-
// whose exhausted-budget terminal carries no recorded submissions
|
|
689
|
-
// at all. skipRunStateWrite: the write that just threw is the same
|
|
690
|
-
// write presentControlledFailure would otherwise retry — don't
|
|
691
|
-
// call a known-failing operation twice.
|
|
692
|
-
const failed = await settleAfterTurnStarted(admitted, withEngineDetourInvocationScope({
|
|
693
|
-
timedOut: false,
|
|
694
|
-
code: null,
|
|
695
|
-
stderr: "",
|
|
696
|
-
thrown: error,
|
|
697
|
-
skipRunStateWrite: true,
|
|
698
|
-
}, request.invocationScopeId), adapters, env.principalAuthority, io, persistRunState);
|
|
699
|
-
return await finishAfterTurn(withProcessCancelSkipAutoResume({ ...failed, turnDispatched: true, ...deferredPersist }, env.signal));
|
|
707
|
+
await recordBestEffortPostDispatchDiagnostic(admitted, env, `run-state persistence failed beside host terminal (best-effort continue): ${describeErrorIdentity(error)}`, io);
|
|
700
708
|
}
|
|
701
709
|
}
|
|
702
710
|
// Lawful persist + present is the caller's stop seam (auto-resume loop /
|
|
@@ -768,19 +776,7 @@ export async function dispatchPostAdmissionTurn(input) {
|
|
|
768
776
|
await persistReturnedRunState(admitted, env.principalAuthority, { lawful: true });
|
|
769
777
|
}
|
|
770
778
|
catch (error) {
|
|
771
|
-
|
|
772
|
-
// branch above — route through the shared controlled-failure seam so
|
|
773
|
-
// the real failure surfaces loudly instead of escaping uncaught to
|
|
774
|
-
// auto-resume's dispatch-retry path with no recorded submissions.
|
|
775
|
-
// skipRunStateWrite: don't retry the write that just threw.
|
|
776
|
-
const failed = await settleAfterTurnStarted(admitted, withEngineDetourInvocationScope({
|
|
777
|
-
timedOut: false,
|
|
778
|
-
code: null,
|
|
779
|
-
stderr: "",
|
|
780
|
-
thrown: error,
|
|
781
|
-
skipRunStateWrite: true,
|
|
782
|
-
}, request.invocationScopeId), adapters, env.principalAuthority, io, persistRunState);
|
|
783
|
-
return await finishAfterTurn(withProcessCancelSkipAutoResume({ ...failed, turnDispatched: true, ...deferredPersist }, env.signal));
|
|
779
|
+
await recordBestEffortPostDispatchDiagnostic(admitted, env, `run-state persistence failed beside host terminal (best-effort continue): ${describeErrorIdentity(error)}`, io);
|
|
784
780
|
}
|
|
785
781
|
}
|
|
786
782
|
// #855 cancel re-read lives in finishAfterTurn (before afterDispatch).
|
|
@@ -793,17 +789,20 @@ export async function dispatchPostAdmissionTurn(input) {
|
|
|
793
789
|
});
|
|
794
790
|
}
|
|
795
791
|
finally {
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
792
|
+
// Public manual resume (#987) holds no package writer lease.
|
|
793
|
+
if (lease !== undefined) {
|
|
794
|
+
try {
|
|
795
|
+
await lease.release();
|
|
796
|
+
}
|
|
797
|
+
catch (error) {
|
|
798
|
+
// lease.release() is documented best-effort and never rejects in the
|
|
799
|
+
// production acquireRunWriterLease implementation (createWriterLease
|
|
800
|
+
// reports cleanup failures via callback, never throws) — this guard is
|
|
801
|
+
// structural only: an uncaught throw from a finally block silently
|
|
802
|
+
// replaces whatever the try already returned, including a properly
|
|
803
|
+
// tagged turnDispatched:true result (#840 r9 判词 class 1 boundary).
|
|
804
|
+
io.stderr(formatCliDiagnostic(`writer lease release failed unexpectedly (best-effort continue): ${describeErrorIdentity(error)}`));
|
|
805
|
+
}
|
|
807
806
|
}
|
|
808
807
|
}
|
|
809
808
|
}
|
|
@@ -951,8 +950,10 @@ export async function prepareSummonsResumeMaterials(runDirectory, summons) {
|
|
|
951
950
|
*/
|
|
952
951
|
export async function runPostAdmissionSeatResume(input) {
|
|
953
952
|
let request = input.request;
|
|
954
|
-
// Load once for runDirectory / structural rejection / afterAdmittedLoad
|
|
955
|
-
//
|
|
953
|
+
// Load once for runDirectory / structural rejection / afterAdmittedLoad.
|
|
954
|
+
// Court identity for public manual resume is judged in the turn builder
|
|
955
|
+
// (#987: no package writer-lease gate before host CLI resume). Station-child
|
|
956
|
+
// auto-resume still acquires the shared lease in runWithAutoResumeLoop.
|
|
956
957
|
let loaded;
|
|
957
958
|
try {
|
|
958
959
|
loaded = await input.load(request);
|
|
@@ -981,8 +982,9 @@ export async function runPostAdmissionSeatResume(input) {
|
|
|
981
982
|
let preparedCleanup;
|
|
982
983
|
const buildRequestAfterLease = async () => {
|
|
983
984
|
let openCourtAttemptId;
|
|
984
|
-
// Build uses the admitted
|
|
985
|
-
//
|
|
985
|
+
// Build uses the admitted for this resume (rehydrated when open court
|
|
986
|
+
// materials ride). Settlement identity stays on the outer admitted.
|
|
987
|
+
// Name kept for station-child callers that still build under lease.
|
|
986
988
|
let admittedForBuild = loaded.admitted;
|
|
987
989
|
// Bare resume: open-court pointer is the continue signal (not ledger seal).
|
|
988
990
|
if (request.summons === undefined) {
|
|
@@ -1043,9 +1045,10 @@ export async function runPostAdmissionSeatResume(input) {
|
|
|
1043
1045
|
}
|
|
1044
1046
|
return turnRequest;
|
|
1045
1047
|
};
|
|
1046
|
-
// Court recovery / open
|
|
1048
|
+
// Court recovery / open, then dispatch. Public manual resume does not take a
|
|
1049
|
+
// package writer lease before the host CLI (#987 / ADR 0080 one-shot).
|
|
1047
1050
|
// Station-child same-ticket/same-parent resume is call-local auto-resume
|
|
1048
|
-
// (#840 / #416)
|
|
1051
|
+
// (#840 / #416) and still acquires the shared lease in its loop.
|
|
1049
1052
|
// afterAdmittedPrepare runs inside this try so mint failure and cleanup share one finally.
|
|
1050
1053
|
try {
|
|
1051
1054
|
if (input.afterAdmittedPrepare !== undefined) {
|
|
@@ -1217,74 +1220,41 @@ export async function runPostAdmissionResumable(input) {
|
|
|
1217
1220
|
});
|
|
1218
1221
|
}
|
|
1219
1222
|
/**
|
|
1220
|
-
* Manual resume:
|
|
1221
|
-
* short-circuit (#833 / #416). Court open
|
|
1222
|
-
*
|
|
1223
|
-
*
|
|
1223
|
+
* Manual resume: pass-through to the host CLI resume — no package writer-lease
|
|
1224
|
+
* pre-gate (#987), no sealed-accepted short-circuit (#833 / #416). Court open
|
|
1225
|
+
* (summons / message / open court) is built when using buildRequestAfterLease;
|
|
1226
|
+
* sole-final stays per-attempt. Station-child auto-resume keeps shared lease
|
|
1227
|
+
* acquire in runWithAutoResumeLoop + dispatchAfterWriterLease.
|
|
1224
1228
|
*/
|
|
1225
1229
|
export async function runPostAdmissionManualResume(input) {
|
|
1226
1230
|
const { admitted, env, io, adapters, effectiveEngine, buildRequestAfterLease, } = input;
|
|
1227
1231
|
let request = input.request;
|
|
1228
1232
|
// #617 DK-3: manual resume writes the live seat/env model (same as new legs).
|
|
1229
1233
|
const effectiveModel = env.model;
|
|
1230
|
-
let lease;
|
|
1231
|
-
let staleWriterLeaseReclaimed;
|
|
1232
|
-
try {
|
|
1233
|
-
lease = await acquireRunWriterLease(admitted.runDirectory, (diagnostic, kind) => {
|
|
1234
|
-
// Record the typed fact before the fallible sink: if io.stderr throws
|
|
1235
|
-
// (acquire deliberately swallows diagnostic-sink failures), the reclaim
|
|
1236
|
-
// still happened and must stay observable.
|
|
1237
|
-
if (kind === "stale-reclaimed")
|
|
1238
|
-
staleWriterLeaseReclaimed = true;
|
|
1239
|
-
io.stderr(diagnostic);
|
|
1240
|
-
});
|
|
1241
|
-
}
|
|
1242
|
-
catch (error) {
|
|
1243
|
-
if (error instanceof RunWriterLeaseHeldError) {
|
|
1244
|
-
io.stderr(formatCliDiagnostic(error.message));
|
|
1245
|
-
// A held rejection after our own reclaim must still carry the fact that
|
|
1246
|
-
// this caller reclaimed the stale lock — e.g. another resumer re-locked
|
|
1247
|
-
// before our retry create (#629).
|
|
1248
|
-
return {
|
|
1249
|
-
exitCode: 1,
|
|
1250
|
-
...(staleWriterLeaseReclaimed === true
|
|
1251
|
-
? { staleWriterLeaseReclaimed: true }
|
|
1252
|
-
: {}),
|
|
1253
|
-
};
|
|
1254
|
-
}
|
|
1255
|
-
throw error;
|
|
1256
|
-
}
|
|
1257
1234
|
// Explicit public resume is a new counting unit — mint once for this call.
|
|
1258
1235
|
const invocationScopeId = mintEngineDetourInvocationScope({
|
|
1259
1236
|
...(effectiveEngine === undefined ? {} : { effectiveEngine }),
|
|
1260
1237
|
});
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1238
|
+
if (request === undefined) {
|
|
1239
|
+
if (buildRequestAfterLease === undefined) {
|
|
1240
|
+
throw new Error("runPostAdmissionManualResume requires request or buildRequestAfterLease");
|
|
1241
|
+
}
|
|
1242
|
+
request = await buildRequestAfterLease();
|
|
1243
|
+
}
|
|
1244
|
+
request = withEngineDetourInvocationScope(request, invocationScopeId);
|
|
1245
|
+
const result = await dispatchPostAdmissionTurn({
|
|
1246
|
+
admitted,
|
|
1247
|
+
env: {
|
|
1248
|
+
...env,
|
|
1249
|
+
...(effectiveModel === undefined ? {} : { model: effectiveModel }),
|
|
1250
|
+
...(admitted.correlationId === undefined
|
|
1251
|
+
? {}
|
|
1252
|
+
: { correlationId: admitted.correlationId }),
|
|
1272
1253
|
},
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
...(effectiveModel === undefined ? {} : { model: effectiveModel }),
|
|
1278
|
-
...(admitted.correlationId === undefined
|
|
1279
|
-
? {}
|
|
1280
|
-
: { correlationId: admitted.correlationId }),
|
|
1281
|
-
},
|
|
1282
|
-
io,
|
|
1283
|
-
request: turnRequest,
|
|
1284
|
-
lease,
|
|
1285
|
-
adapters,
|
|
1286
|
-
...(effectiveEngine === undefined ? {} : { effectiveEngine }),
|
|
1287
|
-
}),
|
|
1254
|
+
io,
|
|
1255
|
+
request,
|
|
1256
|
+
adapters,
|
|
1257
|
+
...(effectiveEngine === undefined ? {} : { effectiveEngine }),
|
|
1288
1258
|
});
|
|
1289
1259
|
if (result.terminal !== undefined &&
|
|
1290
1260
|
isLawfulTypedTerminalOutcome(result.terminal.roleOutcome)) {
|
|
@@ -1298,10 +1268,5 @@ export async function runPostAdmissionManualResume(input) {
|
|
|
1298
1268
|
if (result.terminal !== undefined) {
|
|
1299
1269
|
result.terminal.autoResumeCount = 0;
|
|
1300
1270
|
}
|
|
1301
|
-
return
|
|
1302
|
-
...result,
|
|
1303
|
-
...(staleWriterLeaseReclaimed === true
|
|
1304
|
-
? { staleWriterLeaseReclaimed: true }
|
|
1305
|
-
: {}),
|
|
1306
|
-
};
|
|
1271
|
+
return result;
|
|
1307
1272
|
}
|
|
@@ -15,6 +15,7 @@ import { readLatestTypedProviderHttpObservation, } from "../typed-provider-http.
|
|
|
15
15
|
export { clearTypedProviderHttpObservation, recordTypedProviderHttpStatus, readLatestTypedProviderHttpObservation, } from "../typed-provider-http.js";
|
|
16
16
|
import { parseCollectorRepository } from "../collector-config.js";
|
|
17
17
|
import { interpretDurableCourtTicketNumbers, sameCourtTicketNumbers, } from "../diarist-contracts.js";
|
|
18
|
+
import { rewriteAdmittedRoleRunPage, rewriteRunDirectoryPathValue, } from "../role-run-relocation.js";
|
|
18
19
|
import { appendEngineSessionMaterial, engineSessionMaterialFromOptions, pickEngineAxis, } from "../package-resources/engine-material.js";
|
|
19
20
|
import { recordEffectiveInvocationModel, requireAuthorityRef, isReviewerLens, } from "./invocation.js";
|
|
20
21
|
/** Providers eligible for v1 typed-429 resume (Codex / xAI only).
|
|
@@ -209,14 +210,15 @@ async function readRoleRunStateDisk(runDirectory) {
|
|
|
209
210
|
return undefined;
|
|
210
211
|
if (typeof record.admittedRequestPath !== "string")
|
|
211
212
|
return undefined;
|
|
212
|
-
const
|
|
213
|
+
const storedRunDirectory = typeof record.runDirectory === "string" && record.runDirectory.trim() !== ""
|
|
213
214
|
? record.runDirectory
|
|
214
215
|
: runDirectory;
|
|
216
|
+
const runDir = runDirectory;
|
|
215
217
|
// Principal wire stays uninterpreted — authority owns legacy sessionFile fallback.
|
|
216
218
|
const principalWire = {
|
|
217
|
-
sessionDirectory: record.sessionDirectory,
|
|
219
|
+
sessionDirectory: rewriteRunDirectoryPathValue(record.sessionDirectory, storedRunDirectory, runDirectory),
|
|
218
220
|
...(typeof record.sessionFile === "string"
|
|
219
|
-
? { sessionFile: record.sessionFile }
|
|
221
|
+
? { sessionFile: rewriteRunDirectoryPathValue(record.sessionFile, storedRunDirectory, runDirectory) }
|
|
220
222
|
: {}),
|
|
221
223
|
};
|
|
222
224
|
let resumable;
|
|
@@ -242,7 +244,7 @@ async function readRoleRunStateDisk(runDirectory) {
|
|
|
242
244
|
bookKey: record.bookKey,
|
|
243
245
|
projectRoot: record.projectRoot,
|
|
244
246
|
runDirectory: runDir,
|
|
245
|
-
admittedRequestPath: record.admittedRequestPath,
|
|
247
|
+
admittedRequestPath: rewriteRunDirectoryPathValue(record.admittedRequestPath, storedRunDirectory, runDirectory),
|
|
246
248
|
principalWire,
|
|
247
249
|
...(phase === undefined ? {} : { phase }),
|
|
248
250
|
...(resumable === undefined ? {} : { resumable }),
|
|
@@ -1017,6 +1019,13 @@ async function loadResumableRunRecord(home, runId, authority) {
|
|
|
1017
1019
|
const raw = JSON.parse(await readFile(run.admittedRequestPath, "utf8"));
|
|
1018
1020
|
if (raw !== null && typeof raw === "object" && !Array.isArray(raw)) {
|
|
1019
1021
|
const record = raw;
|
|
1022
|
+
const storedRunDirectory = typeof record.runDirectory === "string" && record.runDirectory.trim() !== ""
|
|
1023
|
+
? record.runDirectory
|
|
1024
|
+
: run.runDirectory;
|
|
1025
|
+
rewriteAdmittedRoleRunPage(record, [{
|
|
1026
|
+
oldRunDirectory: storedRunDirectory,
|
|
1027
|
+
newRunDirectory: run.runDirectory,
|
|
1028
|
+
}]);
|
|
1020
1029
|
if (typeof record.instruction === "string") {
|
|
1021
1030
|
instruction = record.instruction;
|
|
1022
1031
|
}
|
|
@@ -1201,6 +1210,18 @@ async function loadResumableRunRecord(home, runId, authority) {
|
|
|
1201
1210
|
else if (mergedSet.tickets !== undefined) {
|
|
1202
1211
|
courtTicketNumbers = mergedSet.tickets;
|
|
1203
1212
|
}
|
|
1213
|
+
const sourceRunLeaf = basename(sourceRunPath ?? "").split("@");
|
|
1214
|
+
const referencedRunId = sourceRun?.runId ?? sourceRunLeaf[0];
|
|
1215
|
+
const referencedRole = sourceRun?.role ?? sourceRunLeaf[1];
|
|
1216
|
+
if (referencedRunId !== undefined && referencedRunId !== "") {
|
|
1217
|
+
const currentSourceRunDirectory = await findRunDirectoryById(home, referencedRunId, run.bookKey, referencedRole);
|
|
1218
|
+
if (currentSourceRunDirectory !== undefined) {
|
|
1219
|
+
sourceRunPath = currentSourceRunDirectory;
|
|
1220
|
+
if (sourceRun !== undefined) {
|
|
1221
|
+
sourceRun = { ...sourceRun, runDirectory: currentSourceRunDirectory };
|
|
1222
|
+
}
|
|
1223
|
+
}
|
|
1224
|
+
}
|
|
1204
1225
|
return {
|
|
1205
1226
|
run,
|
|
1206
1227
|
principal,
|
|
@@ -132,6 +132,21 @@ function rewriteSummonsMaterials(value, rewrites) {
|
|
|
132
132
|
value.attachmentPaths = value.attachmentPaths.map((path) => rewriteRunDirectoryPathValueAgainstRewrites(path, rewrites));
|
|
133
133
|
}
|
|
134
134
|
}
|
|
135
|
+
/** Project one admitted page in memory after its containing run moved. */
|
|
136
|
+
export function rewriteAdmittedRoleRunPage(page, rewrites) {
|
|
137
|
+
rewriteRunDirectoryPathFieldsAgainstRewrites(page, ADMITTED_PAGE_FIELDS, rewrites);
|
|
138
|
+
rewriteSourceRunLocator(page.sourceRun, rewrites);
|
|
139
|
+
if (Array.isArray(page.attachments)) {
|
|
140
|
+
for (const attachment of page.attachments) {
|
|
141
|
+
if (isPlainObject(attachment)) {
|
|
142
|
+
rewriteRunDirectoryPathFieldsAgainstRewrites(attachment, ["frozenPath"], rewrites);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
if (isPlainObject(page.principal)) {
|
|
147
|
+
rewriteRunDirectoryPathFieldsAgainstRewrites(page.principal, ["sessionDirectory", "sessionFile"], rewrites);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
135
150
|
async function rewriteJsonObjectFile(path, fields, rewrites) {
|
|
136
151
|
if (!existsSync(path))
|
|
137
152
|
return;
|
|
@@ -307,9 +322,9 @@ async function rewriteNestedMachinePathPages(pagesDirectory, rewrites) {
|
|
|
307
322
|
/**
|
|
308
323
|
* Rewrite admitted-request / invocation / run-state path fields (attachment
|
|
309
324
|
* frozenPath / summons.attachmentPaths pointers only), then nested package-owned
|
|
310
|
-
* session seams
|
|
311
|
-
* `pagesDirectory` is where the pages
|
|
312
|
-
*
|
|
325
|
+
* session seams. Callers may rewrite before or after the filesystem move/copy:
|
|
326
|
+
* `pagesDirectory` is where the pages currently live on disk; path strings that
|
|
327
|
+
* still name `oldRunDirectory` become `newRunDirectory`. `crossRunRewrites`
|
|
313
328
|
* covers officer/parent pointers that landed under a different final placement.
|
|
314
329
|
*/
|
|
315
330
|
export async function rewriteRoleRunDurablePages(input) {
|
|
@@ -318,21 +333,7 @@ export async function rewriteRoleRunDurablePages(input) {
|
|
|
318
333
|
const admittedPath = join(pagesDirectory, "admitted-request.json");
|
|
319
334
|
if (existsSync(admittedPath)) {
|
|
320
335
|
const page = JSON.parse(await readFile(admittedPath, "utf8"));
|
|
321
|
-
|
|
322
|
-
// Nested notary typed locator — same value family as top-level sourceRunPath.
|
|
323
|
-
rewriteSourceRunLocator(page.sourceRun, rewrites);
|
|
324
|
-
if (Array.isArray(page.attachments)) {
|
|
325
|
-
for (const attachment of page.attachments) {
|
|
326
|
-
if (isPlainObject(attachment)) {
|
|
327
|
-
// Pointer only — never open or mutate frozen attachment bytes.
|
|
328
|
-
rewriteRunDirectoryPathFieldsAgainstRewrites(attachment, ["frozenPath"], rewrites);
|
|
329
|
-
}
|
|
330
|
-
}
|
|
331
|
-
}
|
|
332
|
-
// Nested principal wire (sessionDirectory/sessionFile) when present.
|
|
333
|
-
if (isPlainObject(page.principal)) {
|
|
334
|
-
rewriteRunDirectoryPathFieldsAgainstRewrites(page.principal, ["sessionDirectory", "sessionFile"], rewrites);
|
|
335
|
-
}
|
|
336
|
+
rewriteAdmittedRoleRunPage(page, rewrites);
|
|
336
337
|
await writeFile(admittedPath, `${JSON.stringify(page, null, 2)}\n`, "utf8");
|
|
337
338
|
}
|
|
338
339
|
const invocationPath = join(pagesDirectory, "invocation.json");
|
package/package.json
CHANGED
|
@@ -397,7 +397,15 @@ export async function findPlacedMigratingRun(
|
|
|
397
397
|
const preferred = destPathFromSourceRelative(booksDirectory, bookKey, sourceRelative);
|
|
398
398
|
if (preferred !== undefined) {
|
|
399
399
|
const hit = matches.find((path) => path === preferred);
|
|
400
|
-
|
|
400
|
+
if (hit !== undefined) return placedRunFromPath(hit);
|
|
401
|
+
// T9 may have used the board ticket to move an historical unbound leaf
|
|
402
|
+
// under `<ticket>/runs`. The complete leaf is the placement identity;
|
|
403
|
+
// when it remains unique, downstream record/mixed/T11 consumers must
|
|
404
|
+
// follow that authoritative T9 result rather than re-derive unbound.
|
|
405
|
+
if (sourceRelative.replaceAll("\\", "/").startsWith("unbound/runs/")) {
|
|
406
|
+
return uniquePlacedRun(leafName, matches);
|
|
407
|
+
}
|
|
408
|
+
return undefined;
|
|
401
409
|
}
|
|
402
410
|
// Historical flat `runs/<leaf>` alias after T9 nested the unique complete leaf.
|
|
403
411
|
if (isFlatRunsRelative(sourceRelative, leafName)) {
|