@akagilnc/pi-workflow-roles 0.1.5504 → 0.1.5571
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/README.md +1 -1
- package/README.zh-CN.md +1 -1
- package/dist/acp-host/production-host.js +5965 -5994
- package/dist/analyst-gate-cycles-read.js +23 -55
- package/dist/analyst-ledger.js +21 -35
- package/dist/analyst-metric-families/acceptance-success-rework.js +25 -1
- package/dist/analyst-metric-families/round-timeline.js +2 -5
- package/dist/archivist-record-pointer.js +38 -30
- package/dist/auditor-dossier-tool.js +4 -3
- package/dist/auditor-soul.js +3 -11
- package/dist/doctor-evidence.js +3 -3
- package/dist/engine-detour-usage.js +6 -14
- package/dist/headless-host/production-host.js +5316 -5324
- package/dist/host-descriptions.js +0 -4
- package/dist/host-session-record.js +266 -267
- package/dist/migrate-book-topology.js +1314 -696
- package/dist/notary-source-run.js +1 -1
- package/dist/packaged-role-registry.js +5 -44
- package/dist/pi/role-turn-host.js +53 -3
- package/dist/public-cli/auto-resume.js +8 -47
- package/dist/public-cli/instruction-seat-run.js +5 -3
- package/dist/public-cli/invocation.js +51 -56
- package/dist/public-cli/main.js +1916 -1748
- package/dist/public-cli/post-admission.js +96 -55
- package/dist/public-cli/run-lifecycle.js +27 -53
- package/dist/public-cli/settlement.js +157 -302
- package/dist/role-run-placement.js +1 -11
- package/dist/role-run-relocation.js +72 -50
- package/dist/run-dossier-files.js +30 -0
- package/dist/run-dossier.js +322 -0
- package/dist/run-terminal-artifacts.js +68 -197
- package/dist/run-ticket-number.js +16 -3
- package/dist/session-identity.js +49 -18
- package/dist/sitian-appender.js +13 -16
- package/dist/sitian-facade.js +11 -0
- package/dist/sitian-reader.js +44 -29
- package/dist/submission-gate.js +1 -1
- package/dist/ticket-provenance.js +22 -7
- package/package.json +1 -1
- package/scripts/build-package.mjs +2 -0
- package/src/acp-host/production-host.ts +1 -1
- package/src/acp-host/role-turn-host.ts +9 -2
- package/src/analyst-gate-cycles-read.ts +26 -60
- package/src/analyst-ledger.ts +27 -42
- package/src/analyst-metric-families/acceptance-success-rework.ts +24 -1
- package/src/analyst-metric-families/gate-cycles.ts +1 -1
- package/src/analyst-metric-families/round-timeline.ts +2 -5
- package/src/analyst-page.ts +3 -3
- package/src/archivist-record-entry.ts +2 -2
- package/src/archivist-record-pointer.ts +50 -36
- package/src/auditor-dossier-tool.ts +7 -5
- package/src/auditor-soul.ts +3 -9
- package/src/book-topology-migration-placement.ts +16 -3
- package/src/book-topology-record-class-migrators.ts +4 -2
- package/src/book-topology-runs-migrator.ts +6 -3
- package/src/doctor-contracts.ts +1 -1
- package/src/doctor-evidence.ts +2 -2
- package/src/engine-detour-tool.ts +1 -1
- package/src/engine-detour-usage.ts +6 -16
- package/src/external-host-turn-loop.ts +25 -0
- package/src/headless-host/production-host.ts +1 -4
- package/src/headless-host/role-turn-host.ts +54 -20
- package/src/host-descriptions.ts +0 -6
- package/src/host-session-record.ts +224 -140
- package/src/notary-source-run.ts +1 -1
- package/src/packaged-role-registry.ts +1 -50
- package/src/pi/adapter.ts +50 -7
- package/src/pi/role-turn-host.ts +51 -3
- package/src/public-cli/auto-resume.ts +7 -43
- package/src/public-cli/instruction-seat-run.ts +9 -2
- package/src/public-cli/invocation.ts +61 -87
- package/src/public-cli/post-admission.ts +111 -72
- package/src/public-cli/run-lifecycle.ts +27 -72
- package/src/public-cli/settlement.ts +193 -418
- package/src/public-cli/terminal.ts +1 -1
- package/src/role-run-placement.ts +2 -13
- package/src/role-run-relocation.ts +71 -68
- package/src/role-runtime.ts +6 -10
- package/src/run-dossier-files.ts +33 -0
- package/src/run-dossier.ts +357 -0
- package/src/run-terminal-artifacts.ts +83 -237
- package/src/run-ticket-number.ts +41 -11
- package/src/session-identity.ts +52 -20
- package/src/sitian-appender.ts +17 -18
- package/src/sitian-facade.ts +22 -0
- package/src/sitian-reader.ts +62 -32
- package/src/submission-gate.ts +1 -1
- package/src/ticket-provenance.ts +20 -7
- package/src/ticket-trajectory.ts +10 -10
|
@@ -26,10 +26,11 @@ import {
|
|
|
26
26
|
relocateAdmittedRunToTicket,
|
|
27
27
|
} from "./invocation.ts";
|
|
28
28
|
import { readRecordedSubmissionRows } from "../submission-ledger.ts";
|
|
29
|
-
import { readDeclaredTicketNumber } from "../run-ticket-number.ts";
|
|
29
|
+
import { parseTicketNumber, readDeclaredTicketNumber } from "../run-ticket-number.ts";
|
|
30
30
|
import { pathContainedIn } from "../activation-ledger-topology.ts";
|
|
31
31
|
import { pickEngineAxis } from "../package-resources/engine-material.ts";
|
|
32
32
|
import { readStoredHostSessionId } from "../session-identity.ts";
|
|
33
|
+
import { reportRunRecord } from "../sitian-facade.ts";
|
|
33
34
|
import {
|
|
34
35
|
createReceiptDeliveryPolicy,
|
|
35
36
|
deliveryLimitFromConfig,
|
|
@@ -86,7 +87,6 @@ import {
|
|
|
86
87
|
type CatchableProcessSignal,
|
|
87
88
|
} from "./process-cancel.ts";
|
|
88
89
|
import { DEFAULT_ROLE_TURN_HOST } from "../host-descriptions.ts";
|
|
89
|
-
import { recordRunStart } from "../host-session-record.ts";
|
|
90
90
|
import {
|
|
91
91
|
classifyPostAdmissionFailure,
|
|
92
92
|
exitCodeForTerminalOutcome,
|
|
@@ -112,7 +112,6 @@ import {
|
|
|
112
112
|
type TerminalResult,
|
|
113
113
|
} from "./terminal.ts";
|
|
114
114
|
import {
|
|
115
|
-
ensureRealArtifactsDirectory,
|
|
116
115
|
persistReturnedRunState,
|
|
117
116
|
presentTerminal,
|
|
118
117
|
runWithAutoResumeLoop,
|
|
@@ -175,6 +174,7 @@ async function settleProcessCancelAfterTurn<A extends AdmittedRoleInvocation, T
|
|
|
175
174
|
deferredPersist: { needsPersist?: true } | Record<string, never>;
|
|
176
175
|
invocationScopeId: string | undefined;
|
|
177
176
|
notePackageFault?: (diagnostic: string) => void | Promise<void>;
|
|
177
|
+
courtAttemptId?: string;
|
|
178
178
|
}): Promise<{
|
|
179
179
|
exitCode: number;
|
|
180
180
|
admitted: A;
|
|
@@ -205,6 +205,7 @@ async function settleProcessCancelAfterTurn<A extends AdmittedRoleInvocation, T
|
|
|
205
205
|
input.io,
|
|
206
206
|
input.persistRunState,
|
|
207
207
|
input.notePackageFault,
|
|
208
|
+
input.courtAttemptId,
|
|
208
209
|
);
|
|
209
210
|
return {
|
|
210
211
|
...failed,
|
|
@@ -379,7 +380,7 @@ export type ControlledFailureInput = {
|
|
|
379
380
|
knownDetails?: Readonly<Record<string, unknown>>;
|
|
380
381
|
/**
|
|
381
382
|
* A real failure this package hit while handling the call (e.g. the
|
|
382
|
-
* stderr
|
|
383
|
+
* stderr log-line write). Recorded beside the host's report; never a
|
|
383
384
|
* cause, and never written into the host's open `details`.
|
|
384
385
|
*/
|
|
385
386
|
packageFact?: PackageSideFact;
|
|
@@ -473,6 +474,8 @@ export async function presentControlledFailure<
|
|
|
473
474
|
io: CliIo,
|
|
474
475
|
persistRunState = true,
|
|
475
476
|
notePackageFault?: (diagnostic: string) => void | Promise<void>,
|
|
477
|
+
/** Open-court identity already on the turn request / currentCourt (#1161). */
|
|
478
|
+
courtAttemptId?: string,
|
|
476
479
|
): Promise<{
|
|
477
480
|
exitCode: number;
|
|
478
481
|
admitted: A;
|
|
@@ -545,6 +548,9 @@ export async function presentControlledFailure<
|
|
|
545
548
|
const settled = await settleFailureTerminalResult(admitted, failure, authority, {
|
|
546
549
|
recordAttemptHistory: true,
|
|
547
550
|
...(notePackageFault === undefined ? {} : { notePackageFault }),
|
|
551
|
+
...(courtAttemptId === undefined || courtAttemptId.length === 0
|
|
552
|
+
? {}
|
|
553
|
+
: { courtAttemptId }),
|
|
548
554
|
...(failureInput.invocationScopeId === undefined ||
|
|
549
555
|
failureInput.invocationScopeId.length === 0
|
|
550
556
|
? {}
|
|
@@ -588,6 +594,7 @@ async function settleAfterTurnStarted<
|
|
|
588
594
|
io: CliIo,
|
|
589
595
|
persistRunState: boolean,
|
|
590
596
|
notePackageFault?: (diagnostic: string) => void | Promise<void>,
|
|
597
|
+
courtAttemptId?: string,
|
|
591
598
|
): Promise<{ exitCode: number; admitted: A; terminal: T }> {
|
|
592
599
|
try {
|
|
593
600
|
return (await presentControlledFailure(
|
|
@@ -598,6 +605,7 @@ async function settleAfterTurnStarted<
|
|
|
598
605
|
io,
|
|
599
606
|
persistRunState,
|
|
600
607
|
notePackageFault,
|
|
608
|
+
courtAttemptId,
|
|
601
609
|
)) as { exitCode: number; admitted: A; terminal: T };
|
|
602
610
|
} catch (error) {
|
|
603
611
|
throw new TurnDispatchedFailure(error);
|
|
@@ -666,18 +674,12 @@ function settlementScopeForTurn(request: RoleTurnRequest): SettlementCourtScope
|
|
|
666
674
|
*
|
|
667
675
|
* The caller owns the live delivery policy; the request projects its next send.
|
|
668
676
|
*/
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
env: PostAdmissionEnv;
|
|
677
|
+
/** Bare in-call催交 resume: hostSessionId absent; adapter is the sole load authority. */
|
|
678
|
+
function buildReceiptDeliveryRequest(input: {
|
|
672
679
|
request: RoleTurnRequest;
|
|
673
680
|
receiptDelivery: ReturnType<typeof createReceiptDeliveryPolicy>;
|
|
674
|
-
}):
|
|
675
|
-
const {
|
|
676
|
-
const hostSessionId = await readStoredHostSessionId(
|
|
677
|
-
env.host,
|
|
678
|
-
env.principalAuthority,
|
|
679
|
-
admitted.principal,
|
|
680
|
-
);
|
|
681
|
+
}): RoleTurnRequest {
|
|
682
|
+
const { request, receiptDelivery } = input;
|
|
681
683
|
return {
|
|
682
684
|
...request,
|
|
683
685
|
continuation: {
|
|
@@ -686,7 +688,6 @@ async function buildReceiptDeliveryRequest<A extends AdmittedRoleInvocation>(inp
|
|
|
686
688
|
...receiptDelivery.deliveryState(),
|
|
687
689
|
deliveryTurns: receiptDelivery.issuedDeliveryRequests() + 1,
|
|
688
690
|
}),
|
|
689
|
-
...(hostSessionId === undefined ? {} : { hostSessionId }),
|
|
690
691
|
},
|
|
691
692
|
deliveryRequestLimit: receiptDelivery.limit,
|
|
692
693
|
};
|
|
@@ -760,20 +761,16 @@ async function settleCompletedHostTurn<
|
|
|
760
761
|
// machinery once the retry budget is exhausted.
|
|
761
762
|
let stderrLogWriteFailure: unknown;
|
|
762
763
|
try {
|
|
763
|
-
|
|
764
|
-
join(admitted.runDirectory, "stderr.log"),
|
|
765
|
-
result.stderr,
|
|
766
|
-
"utf8",
|
|
767
|
-
);
|
|
764
|
+
reportRunRecord(admitted.runDirectory, "stderr", { text: result.stderr }, "post-admission");
|
|
768
765
|
} catch (error) {
|
|
769
766
|
stderrLogWriteFailure = error;
|
|
770
|
-
// Best-effort: stderr
|
|
767
|
+
// Best-effort: the stderr log line is secondary to the host terminal. A write
|
|
771
768
|
// failure leaves a durable note and, on a host failure, rides in
|
|
772
769
|
// packageFact. It does not become the cause.
|
|
773
770
|
await recordBestEffortPostDispatchDiagnostic(
|
|
774
771
|
admitted,
|
|
775
772
|
env,
|
|
776
|
-
`stderr
|
|
773
|
+
`stderr log write failed (best-effort continue): ${describeErrorIdentity(error)}`,
|
|
777
774
|
io,
|
|
778
775
|
);
|
|
779
776
|
}
|
|
@@ -781,7 +778,7 @@ async function settleCompletedHostTurn<
|
|
|
781
778
|
// Host facts are resolved before trySettle. A host failure skips trySettle
|
|
782
779
|
// so a later read cannot replace that report. A clean host whose settlement
|
|
783
780
|
// read throws is noted above and is not turned into a failure terminal.
|
|
784
|
-
// stderr
|
|
781
|
+
// the stderr log line and run-state writes are notes beside the host terminal.
|
|
785
782
|
let settled: T | undefined;
|
|
786
783
|
let settledOutcome:
|
|
787
784
|
| { exitCode: number; admitted: A; terminal: T; turnDispatched: true }
|
|
@@ -841,6 +838,9 @@ async function settleCompletedHostTurn<
|
|
|
841
838
|
deferredPersist,
|
|
842
839
|
invocationScopeId: request.invocationScopeId,
|
|
843
840
|
notePackageFault: courtScope.notePackageFault,
|
|
841
|
+
...(courtScope.courtAttemptId === undefined
|
|
842
|
+
? {}
|
|
843
|
+
: { courtAttemptId: courtScope.courtAttemptId }),
|
|
844
844
|
}),
|
|
845
845
|
) };
|
|
846
846
|
}
|
|
@@ -892,6 +892,7 @@ async function settleCompletedHostTurn<
|
|
|
892
892
|
io,
|
|
893
893
|
persistRunState,
|
|
894
894
|
courtScope.notePackageFault,
|
|
895
|
+
courtScope.courtAttemptId,
|
|
895
896
|
);
|
|
896
897
|
return { kind: "settled", outcome: await finishAfterTurn(
|
|
897
898
|
withProcessCancelSkipAutoResume(
|
|
@@ -904,6 +905,64 @@ async function settleCompletedHostTurn<
|
|
|
904
905
|
return { kind: "still-missing" };
|
|
905
906
|
}
|
|
906
907
|
|
|
908
|
+
/**
|
|
909
|
+
* #858 / #1071: the first identifiable ticketNumber field declaration among the
|
|
910
|
+
* run's sealed rows files an unbound run (integer, digit string, or leading #N
|
|
911
|
+
* token). Terminal rows match settlement (#881): accepted and audit-escalation —
|
|
912
|
+
* an escalated submission still carries the original role params. Later
|
|
913
|
+
* receipts remain untouched; prose note/report is never consulted; this seam
|
|
914
|
+
* does not adjudicate a ticket change. Runs in the public call's own process
|
|
915
|
+
* (no role leg writes the run's current.json).
|
|
916
|
+
*/
|
|
917
|
+
export async function bindSealedTicketNumber(admitted: AdmittedRoleInvocation): Promise<void> {
|
|
918
|
+
if (admitted.ticketNumber !== undefined) return;
|
|
919
|
+
const rows = await readRecordedSubmissionRows(
|
|
920
|
+
admitted.projectRoot,
|
|
921
|
+
admitted.runId,
|
|
922
|
+
ledgerReadScope(admitted),
|
|
923
|
+
);
|
|
924
|
+
let ticketNumber: number | undefined;
|
|
925
|
+
for (const row of rows) {
|
|
926
|
+
if (
|
|
927
|
+
row.role !== admitted.role
|
|
928
|
+
|| (row.kind !== "accepted" && row.kind !== "audit-escalation")
|
|
929
|
+
) {
|
|
930
|
+
continue;
|
|
931
|
+
}
|
|
932
|
+
const payload = row.accepted;
|
|
933
|
+
if (!isRecord(payload)) continue;
|
|
934
|
+
ticketNumber = readDeclaredTicketNumber(
|
|
935
|
+
(payload as { ticketNumber?: unknown }).ticketNumber,
|
|
936
|
+
);
|
|
937
|
+
if (ticketNumber !== undefined) break;
|
|
938
|
+
}
|
|
939
|
+
if (ticketNumber !== undefined) await bindAdmittedTicketNumber(admitted, ticketNumber);
|
|
940
|
+
}
|
|
941
|
+
|
|
942
|
+
/**
|
|
943
|
+
* The ticket a diarist asserted on a completed submission, whether or not the
|
|
944
|
+
* rest of that submission was later accepted (a bounds reask does not unsay the
|
|
945
|
+
* ticket). Before this ran in the leg's accept hook; the leg now only appends its
|
|
946
|
+
* ledger rows and the public call's own process binds the ticket from them.
|
|
947
|
+
*/
|
|
948
|
+
export async function bindDiaristAssertedTicketNumber(admitted: AdmittedRoleInvocation): Promise<void> {
|
|
949
|
+
if (admitted.ticketNumber !== undefined) return;
|
|
950
|
+
const rows = await readRecordedSubmissionRows(
|
|
951
|
+
admitted.projectRoot,
|
|
952
|
+
admitted.runId,
|
|
953
|
+
ledgerReadScope(admitted),
|
|
954
|
+
);
|
|
955
|
+
for (const row of rows) {
|
|
956
|
+
if (row.role !== admitted.role || !isRecord(row.accepted)) continue;
|
|
957
|
+
if (row.accepted.status !== "completed" || !("ticketNumber" in row.accepted)) continue;
|
|
958
|
+
const ticketNumber = parseTicketNumber(row.accepted.ticketNumber);
|
|
959
|
+
if (ticketNumber !== undefined) {
|
|
960
|
+
await bindAdmittedTicketNumber(admitted, ticketNumber);
|
|
961
|
+
return;
|
|
962
|
+
}
|
|
963
|
+
}
|
|
964
|
+
}
|
|
965
|
+
|
|
907
966
|
export async function dispatchPostAdmissionTurn<
|
|
908
967
|
A extends AdmittedRoleInvocation,
|
|
909
968
|
T extends TerminalResult = TerminalResult,
|
|
@@ -991,6 +1050,7 @@ export async function dispatchPostAdmissionTurn<
|
|
|
991
1050
|
io,
|
|
992
1051
|
persistRunState,
|
|
993
1052
|
courtScope.notePackageFault,
|
|
1053
|
+
courtScope.courtAttemptId,
|
|
994
1054
|
)),
|
|
995
1055
|
turnDispatched: true as const,
|
|
996
1056
|
skipAutoResume: true as const,
|
|
@@ -1042,29 +1102,7 @@ export async function dispatchPostAdmissionTurn<
|
|
|
1042
1102
|
// an escalated submission still carries the original role params.
|
|
1043
1103
|
// Later receipts remain untouched; prose note/report is never consulted;
|
|
1044
1104
|
// this seam does not adjudicate a ticket change.
|
|
1045
|
-
|
|
1046
|
-
const rows = await readRecordedSubmissionRows(
|
|
1047
|
-
admitted.projectRoot,
|
|
1048
|
-
admitted.runId,
|
|
1049
|
-
ledgerReadScope(admitted),
|
|
1050
|
-
);
|
|
1051
|
-
let ticketNumber: number | undefined;
|
|
1052
|
-
for (const row of rows) {
|
|
1053
|
-
if (
|
|
1054
|
-
row.role !== admitted.role
|
|
1055
|
-
|| (row.kind !== "accepted" && row.kind !== "audit-escalation")
|
|
1056
|
-
) {
|
|
1057
|
-
continue;
|
|
1058
|
-
}
|
|
1059
|
-
const payload = row.accepted;
|
|
1060
|
-
if (!isRecord(payload)) continue;
|
|
1061
|
-
ticketNumber = readDeclaredTicketNumber(
|
|
1062
|
-
(payload as { ticketNumber?: unknown }).ticketNumber,
|
|
1063
|
-
);
|
|
1064
|
-
if (ticketNumber !== undefined) break;
|
|
1065
|
-
}
|
|
1066
|
-
if (ticketNumber !== undefined) await bindAdmittedTicketNumber(admitted, ticketNumber);
|
|
1067
|
-
}
|
|
1105
|
+
await bindSealedTicketNumber(admitted);
|
|
1068
1106
|
// #863: shared post-admission bind must relocate unbound→ticket in-home
|
|
1069
1107
|
// before lease release (work-seat self-report and any prior board bind).
|
|
1070
1108
|
const relocation = await relocateAdmittedRunToTicket(admitted, env.principalAuthority, lease);
|
|
@@ -1102,6 +1140,7 @@ export async function dispatchPostAdmissionTurn<
|
|
|
1102
1140
|
io,
|
|
1103
1141
|
persistRunState,
|
|
1104
1142
|
courtScope.notePackageFault,
|
|
1143
|
+
courtScope.courtAttemptId,
|
|
1105
1144
|
)) as { exitCode: number; admitted: A; terminal: T },
|
|
1106
1145
|
...(result.turnDispatched === true ? { turnDispatched: true as const } : {}),
|
|
1107
1146
|
...(result.skipAutoResume === true ? { skipAutoResume: true as const } : {}),
|
|
@@ -1140,6 +1179,7 @@ export async function dispatchPostAdmissionTurn<
|
|
|
1140
1179
|
io,
|
|
1141
1180
|
persistRunState,
|
|
1142
1181
|
courtScope.notePackageFault,
|
|
1182
|
+
courtScope.courtAttemptId,
|
|
1143
1183
|
)) as { exitCode: number; admitted: A; terminal: T };
|
|
1144
1184
|
return { ...settled, ...deferredPersist };
|
|
1145
1185
|
}
|
|
@@ -1160,7 +1200,7 @@ export async function dispatchPostAdmissionTurn<
|
|
|
1160
1200
|
turnRequest = { ...turnRequest, stationChild: env.stationChild };
|
|
1161
1201
|
}
|
|
1162
1202
|
// Selected host axis rides the shared Host envelope for in-turn tools
|
|
1163
|
-
// (detour usage ledger) — never a pre-spawn
|
|
1203
|
+
// (detour usage ledger) — never a pre-spawn current.json reread.
|
|
1164
1204
|
if (typeof env.host === "string" && env.host.trim() !== "") {
|
|
1165
1205
|
turnRequest = { ...turnRequest, host: env.host.trim() };
|
|
1166
1206
|
}
|
|
@@ -1186,7 +1226,6 @@ export async function dispatchPostAdmissionTurn<
|
|
|
1186
1226
|
// host CLI's native resume. Nothing here may gate, redirect or reshape
|
|
1187
1227
|
// that dispatch on prior conclusions, row counts or report presence;
|
|
1188
1228
|
// the authoritative post-turn settlement reads whatever really happened.
|
|
1189
|
-
recordRunStart(admitted.runDirectory);
|
|
1190
1229
|
turnDispatched = true;
|
|
1191
1230
|
result = await env.roleTurnHost.executeTurn(turnRequest);
|
|
1192
1231
|
} catch (error) {
|
|
@@ -1207,6 +1246,7 @@ export async function dispatchPostAdmissionTurn<
|
|
|
1207
1246
|
io,
|
|
1208
1247
|
persistRunState,
|
|
1209
1248
|
courtScope.notePackageFault,
|
|
1249
|
+
courtScope.courtAttemptId,
|
|
1210
1250
|
);
|
|
1211
1251
|
return await finishAfterTurn(
|
|
1212
1252
|
withProcessCancelSkipAutoResume(
|
|
@@ -1248,11 +1288,9 @@ export async function dispatchPostAdmissionTurn<
|
|
|
1248
1288
|
let deliveryResult: RoleTurnResult;
|
|
1249
1289
|
let deliveryTurnRequest: RoleTurnRequest;
|
|
1250
1290
|
try {
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
// Host and the other axes already selected on this turn ride the
|
|
1255
|
-
// shared projection. The pre-projection request does not have them.
|
|
1291
|
+
// Host and the other axes already selected on this turn ride the
|
|
1292
|
+
// shared projection. The pre-projection request does not have them.
|
|
1293
|
+
const deliveryRequest = buildReceiptDeliveryRequest({
|
|
1256
1294
|
request: turnRequest,
|
|
1257
1295
|
receiptDelivery,
|
|
1258
1296
|
});
|
|
@@ -1281,6 +1319,8 @@ export async function dispatchPostAdmissionTurn<
|
|
|
1281
1319
|
env.principalAuthority,
|
|
1282
1320
|
io,
|
|
1283
1321
|
persistRunState,
|
|
1322
|
+
courtScope.notePackageFault,
|
|
1323
|
+
courtScope.courtAttemptId,
|
|
1284
1324
|
);
|
|
1285
1325
|
return await finishAfterTurn(
|
|
1286
1326
|
withProcessCancelSkipAutoResume(
|
|
@@ -1361,6 +1401,9 @@ export async function dispatchPostAdmissionTurn<
|
|
|
1361
1401
|
deferredPersist,
|
|
1362
1402
|
invocationScopeId: request.invocationScopeId,
|
|
1363
1403
|
notePackageFault: courtScope.notePackageFault,
|
|
1404
|
+
...(courtScope.courtAttemptId === undefined
|
|
1405
|
+
? {}
|
|
1406
|
+
: { courtAttemptId: courtScope.courtAttemptId }),
|
|
1364
1407
|
}),
|
|
1365
1408
|
);
|
|
1366
1409
|
}
|
|
@@ -1758,6 +1801,9 @@ export async function runPostAdmissionSeatResume<
|
|
|
1758
1801
|
}
|
|
1759
1802
|
}
|
|
1760
1803
|
|
|
1804
|
+
// Public explicit resume: attach the stored native id when the caller
|
|
1805
|
+
// left it unset (399c3c8c). In-call auto-resume / 催交 / gate retry omit
|
|
1806
|
+
// the field; those load inside the host adapter (host-contracts).
|
|
1761
1807
|
let turnRequest = await input.buildTurnRequest(admittedForBuild, request);
|
|
1762
1808
|
if (
|
|
1763
1809
|
turnRequest.continuation.kind === "resume"
|
|
@@ -1872,7 +1918,7 @@ export async function runPostAdmissionSeatResume<
|
|
|
1872
1918
|
await presentResumeFailurePointer(
|
|
1873
1919
|
input.io,
|
|
1874
1920
|
error,
|
|
1875
|
-
(failure) =>
|
|
1921
|
+
(failure) => writeResumeDiagnostic(
|
|
1876
1922
|
loaded.admitted.runDirectory,
|
|
1877
1923
|
loaded.admitted.runId,
|
|
1878
1924
|
failure,
|
|
@@ -1904,13 +1950,13 @@ async function pointExistingRunFailure(
|
|
|
1904
1950
|
record = await readRoleRunState(runDirectory, authority);
|
|
1905
1951
|
} catch {
|
|
1906
1952
|
await presentResumeFailurePointer(io, thrown, (failure) =>
|
|
1907
|
-
|
|
1953
|
+
writeResumeDiagnostic(runDirectory, runId, failure),
|
|
1908
1954
|
);
|
|
1909
1955
|
return true;
|
|
1910
1956
|
}
|
|
1911
1957
|
if (record === undefined) return false;
|
|
1912
1958
|
await presentResumeFailurePointer(io, thrown, (failure) =>
|
|
1913
|
-
|
|
1959
|
+
writeResumeDiagnostic(runDirectory, runId, failure, record.role),
|
|
1914
1960
|
);
|
|
1915
1961
|
return true;
|
|
1916
1962
|
}
|
|
@@ -1966,27 +2012,20 @@ async function presentResumeFailurePointer(
|
|
|
1966
2012
|
}
|
|
1967
2013
|
}
|
|
1968
2014
|
|
|
1969
|
-
async function
|
|
2015
|
+
async function writeResumeDiagnostic(
|
|
1970
2016
|
runDirectory: string,
|
|
1971
2017
|
runId: string,
|
|
1972
2018
|
failure: ControlledFailure,
|
|
1973
2019
|
role?: AdmittedRoleInvocation["role"],
|
|
1974
2020
|
): Promise<string> {
|
|
1975
|
-
|
|
1976
|
-
|
|
1977
|
-
|
|
1978
|
-
|
|
1979
|
-
|
|
1980
|
-
|
|
1981
|
-
|
|
1982
|
-
|
|
1983
|
-
...(failure.cause === undefined ? {} : { cause: failure.cause }),
|
|
1984
|
-
...(failure.identity === undefined ? {} : { identity: failure.identity }),
|
|
1985
|
-
...(failure.details === undefined ? {} : { details: failure.details }),
|
|
1986
|
-
}, null, 2)}\n`,
|
|
1987
|
-
{ encoding: "utf8", flag: "wx" },
|
|
1988
|
-
);
|
|
1989
|
-
return path;
|
|
2021
|
+
return reportRunRecord(runDirectory, "resume-diagnostic", {
|
|
2022
|
+
runId,
|
|
2023
|
+
...(role === undefined ? {} : { role }),
|
|
2024
|
+
diagnostic: failure.diagnostic,
|
|
2025
|
+
...(failure.cause === undefined ? {} : { cause: failure.cause }),
|
|
2026
|
+
...(failure.identity === undefined ? {} : { identity: failure.identity }),
|
|
2027
|
+
...(failure.details === undefined ? {} : { details: failure.details }),
|
|
2028
|
+
}, "post-admission").recordFile;
|
|
1990
2029
|
}
|
|
1991
2030
|
|
|
1992
2031
|
/**
|
|
@@ -63,6 +63,7 @@ import {
|
|
|
63
63
|
type ReviewerLens,
|
|
64
64
|
} from "./invocation.ts";
|
|
65
65
|
|
|
66
|
+
import { readPageSync, writeSectionSync } from "../run-dossier.ts";
|
|
66
67
|
import { isRecord, errorText, isEnoent } from "../unknown-value.ts";
|
|
67
68
|
|
|
68
69
|
export type RoleRunState = "admitted" | "running" | "resumable" | "terminal";
|
|
@@ -83,7 +84,6 @@ export type RoleRunRecord = {
|
|
|
83
84
|
/** Exact Pi session file principal reopened on resume (not directory-latest). */
|
|
84
85
|
readonly sessionFile: string;
|
|
85
86
|
readonly runDirectory: string;
|
|
86
|
-
readonly admittedRequestPath: string;
|
|
87
87
|
/** Coder/Fixer — preserved for resume continuation. */
|
|
88
88
|
readonly phase?: CoderPhase | FixerPhase;
|
|
89
89
|
};
|
|
@@ -154,7 +154,6 @@ export function buildAutoResumeContinuationPrompt(options: {
|
|
|
154
154
|
).join("\n");
|
|
155
155
|
}
|
|
156
156
|
|
|
157
|
-
const RUN_STATE_FILE = "run-state.json";
|
|
158
157
|
const WRITER_LOCK_FILE = "writer.lock";
|
|
159
158
|
|
|
160
159
|
export async function writeRoleRunState(
|
|
@@ -162,15 +161,11 @@ export async function writeRoleRunState(
|
|
|
162
161
|
record: Omit<RoleRunRecord, "runDirectory">,
|
|
163
162
|
): Promise<void> {
|
|
164
163
|
const payload: RoleRunRecord = { ...record, runDirectory };
|
|
165
|
-
|
|
166
|
-
join(runDirectory, RUN_STATE_FILE),
|
|
167
|
-
`${JSON.stringify(payload, null, 2)}\n`,
|
|
168
|
-
"utf8",
|
|
169
|
-
);
|
|
164
|
+
writeSectionSync(runDirectory, "runState", { ...payload });
|
|
170
165
|
}
|
|
171
166
|
|
|
172
167
|
/**
|
|
173
|
-
* Uninterpreted principal wire as stored on run-state.
|
|
168
|
+
* Uninterpreted principal wire as stored on the state.jsonl run-state row.
|
|
174
169
|
* Legacy rows may omit sessionFile; only DurablePrincipalAuthority decodes it.
|
|
175
170
|
*/
|
|
176
171
|
type RoleRunPrincipalWire = {
|
|
@@ -186,7 +181,6 @@ type RoleRunStateDisk = {
|
|
|
186
181
|
readonly bookKey: string;
|
|
187
182
|
readonly projectRoot: string;
|
|
188
183
|
readonly runDirectory: string;
|
|
189
|
-
readonly admittedRequestPath: string;
|
|
190
184
|
readonly principalWire: RoleRunPrincipalWire;
|
|
191
185
|
readonly phase?: CoderPhase | FixerPhase;
|
|
192
186
|
/** Open court turn (#637); omit when no unsealed current court. */
|
|
@@ -263,20 +257,13 @@ function parseCurrentCourtState(raw: unknown): CurrentCourtState | undefined {
|
|
|
263
257
|
}
|
|
264
258
|
|
|
265
259
|
async function readRoleRunStateRaw(runDirectory: string): Promise<unknown | undefined> {
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
// identity — callers route it through the controlled-failure seam
|
|
274
|
-
// (markRunRunning/markRunTerminal/recordCurrentCourt)
|
|
275
|
-
// instead of it being relabeled "run state missing" (#836).
|
|
276
|
-
if (errorCodeOf(error) === "ENOENT") return undefined;
|
|
277
|
-
throw error;
|
|
278
|
-
}
|
|
279
|
-
return raw;
|
|
260
|
+
// Only true absence (no state.jsonl run-state row) is a lawful "no run state
|
|
261
|
+
// yet". A real read failure (EISDIR, EACCES, ...) or an illegal latest payload
|
|
262
|
+
// is genuine infrastructure/data damage and must keep its own identity —
|
|
263
|
+
// callers route it through the controlled-failure seam
|
|
264
|
+
// (markRunRunning/markRunTerminal/recordCurrentCourt) instead of it being
|
|
265
|
+
// relabeled "run state missing" (#836). readPageSync throws those.
|
|
266
|
+
return readPageSync(runDirectory, "runState");
|
|
280
267
|
}
|
|
281
268
|
|
|
282
269
|
function parseRoleRunIdentity(raw: unknown, runDirectory: string): {
|
|
@@ -287,15 +274,15 @@ function parseRoleRunIdentity(raw: unknown, runDirectory: string): {
|
|
|
287
274
|
readonly state: RoleRunState;
|
|
288
275
|
} {
|
|
289
276
|
if (!isRecord(raw)) {
|
|
290
|
-
throw new TypeError("Invalid run-state
|
|
277
|
+
throw new TypeError("Invalid state.jsonl run-state");
|
|
291
278
|
}
|
|
292
279
|
const record = raw;
|
|
293
280
|
if (typeof record.runId !== "string" || record.runId.trim() === "") {
|
|
294
|
-
throw new TypeError("Invalid run-state
|
|
281
|
+
throw new TypeError("Invalid state.jsonl run-state");
|
|
295
282
|
}
|
|
296
283
|
const role = typeof record.role === "string" ? packagedRoleMetadata(record.role)?.role : undefined;
|
|
297
284
|
if (role === undefined) {
|
|
298
|
-
throw new TypeError("Invalid run-state
|
|
285
|
+
throw new TypeError("Invalid state.jsonl run-state");
|
|
299
286
|
}
|
|
300
287
|
if (
|
|
301
288
|
record.state !== "admitted" &&
|
|
@@ -303,9 +290,9 @@ function parseRoleRunIdentity(raw: unknown, runDirectory: string): {
|
|
|
303
290
|
record.state !== "resumable" &&
|
|
304
291
|
record.state !== "terminal"
|
|
305
292
|
) {
|
|
306
|
-
throw new TypeError("Invalid run-state
|
|
293
|
+
throw new TypeError("Invalid state.jsonl run-state");
|
|
307
294
|
}
|
|
308
|
-
if (typeof record.bookKey !== "string") throw new TypeError("Invalid run-state
|
|
295
|
+
if (typeof record.bookKey !== "string") throw new TypeError("Invalid state.jsonl run-state");
|
|
309
296
|
return {
|
|
310
297
|
runId: record.runId,
|
|
311
298
|
role,
|
|
@@ -322,9 +309,8 @@ async function readRoleRunStateDisk(
|
|
|
322
309
|
if (raw === undefined) return undefined;
|
|
323
310
|
const identity = parseRoleRunIdentity(raw, runDirectory);
|
|
324
311
|
const record = raw as Record<string, unknown>;
|
|
325
|
-
if (typeof record.projectRoot !== "string") throw new TypeError("Invalid run-state
|
|
326
|
-
if (typeof record.sessionDirectory !== "string") throw new TypeError("Invalid run-state
|
|
327
|
-
if (typeof record.admittedRequestPath !== "string") throw new TypeError("Invalid run-state.json");
|
|
312
|
+
if (typeof record.projectRoot !== "string") throw new TypeError("Invalid state.jsonl run-state");
|
|
313
|
+
if (typeof record.sessionDirectory !== "string") throw new TypeError("Invalid state.jsonl run-state");
|
|
328
314
|
const storedRunDirectory =
|
|
329
315
|
typeof record.runDirectory === "string" && record.runDirectory.trim() !== ""
|
|
330
316
|
? record.runDirectory
|
|
@@ -353,11 +339,6 @@ async function readRoleRunStateDisk(
|
|
|
353
339
|
bookKey: identity.bookKey,
|
|
354
340
|
projectRoot: record.projectRoot,
|
|
355
341
|
runDirectory: runDir,
|
|
356
|
-
admittedRequestPath: rewriteRunDirectoryPathValue(
|
|
357
|
-
record.admittedRequestPath,
|
|
358
|
-
storedRunDirectory,
|
|
359
|
-
runDirectory,
|
|
360
|
-
) as string,
|
|
361
342
|
principalWire,
|
|
362
343
|
...(phase === undefined ? {} : { phase }),
|
|
363
344
|
...(currentCourt === undefined ? {} : { currentCourt }),
|
|
@@ -379,15 +360,10 @@ async function writeRoleRunStateDisk(
|
|
|
379
360
|
...(disk.principalWire.sessionFile === undefined
|
|
380
361
|
? {}
|
|
381
362
|
: { sessionFile: disk.principalWire.sessionFile }),
|
|
382
|
-
admittedRequestPath: disk.admittedRequestPath,
|
|
383
363
|
...(disk.phase === undefined ? {} : { phase: disk.phase }),
|
|
384
364
|
...(disk.currentCourt === undefined ? {} : { currentCourt: disk.currentCourt }),
|
|
385
365
|
};
|
|
386
|
-
|
|
387
|
-
join(runDirectory, RUN_STATE_FILE),
|
|
388
|
-
`${JSON.stringify(payload, null, 2)}\n`,
|
|
389
|
-
"utf8",
|
|
390
|
-
);
|
|
366
|
+
writeSectionSync(runDirectory, "runState", payload);
|
|
391
367
|
}
|
|
392
368
|
|
|
393
369
|
/** One authority.decode of the uninterpreted wire → record + opaque principal (frozen wire itself). */
|
|
@@ -408,7 +384,6 @@ function materializeRoleRunFromDisk(
|
|
|
408
384
|
sessionDirectory: coordinates.sessionDirectory,
|
|
409
385
|
sessionFile: coordinates.sessionFile,
|
|
410
386
|
runDirectory: disk.runDirectory,
|
|
411
|
-
admittedRequestPath: disk.admittedRequestPath,
|
|
412
387
|
...(disk.phase === undefined ? {} : { phase: disk.phase }),
|
|
413
388
|
},
|
|
414
389
|
};
|
|
@@ -467,7 +442,6 @@ export async function markRunAdmitted(
|
|
|
467
442
|
projectRoot: admitted.projectRoot,
|
|
468
443
|
sessionDirectory,
|
|
469
444
|
sessionFile,
|
|
470
|
-
admittedRequestPath: admitted.admittedRequestPath,
|
|
471
445
|
...(workerPhase === undefined ? {} : { phase: workerPhase }),
|
|
472
446
|
});
|
|
473
447
|
}
|
|
@@ -475,7 +449,7 @@ export async function markRunAdmitted(
|
|
|
475
449
|
/**
|
|
476
450
|
* Shared dispatch execution seam: transition to running, then record the
|
|
477
451
|
* effective launch model (initial or resume override) and the authoritative
|
|
478
|
-
* seat engine/host onto invocation.
|
|
452
|
+
* seat engine/host onto the invocation section.
|
|
479
453
|
* Role runners must not coordinate lifecycle ledger writes themselves.
|
|
480
454
|
* Engine axis is authoritative here (#617): present string is written; omit/undefined
|
|
481
455
|
* clears any prior engine key so unset-engine + resume does not keep a stale value.
|
|
@@ -945,19 +919,8 @@ export function parentRunPathFromGatePointerInstruction(
|
|
|
945
919
|
export async function readRunParentPath(
|
|
946
920
|
runDirectory: string,
|
|
947
921
|
): Promise<string | undefined> {
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
raw = JSON.parse(
|
|
951
|
-
await readFile(join(runDirectory, "admitted-request.json"), "utf8"),
|
|
952
|
-
);
|
|
953
|
-
} catch (error) {
|
|
954
|
-
if (errorCodeOf(error) === "ENOENT") return undefined;
|
|
955
|
-
throw error;
|
|
956
|
-
}
|
|
957
|
-
if (!isRecord(raw)) {
|
|
958
|
-
return undefined;
|
|
959
|
-
}
|
|
960
|
-
const record = raw;
|
|
922
|
+
const record = readPageSync(runDirectory, "admitted");
|
|
923
|
+
if (record === undefined) return undefined;
|
|
961
924
|
if (typeof record.sourceRunPath === "string" && record.sourceRunPath.trim() !== "") {
|
|
962
925
|
return record.sourceRunPath;
|
|
963
926
|
}
|
|
@@ -1127,7 +1090,7 @@ async function loadResumableRunRecord(
|
|
|
1127
1090
|
throw new CliUsageError(`unknown role run id: ${runId}`);
|
|
1128
1091
|
}
|
|
1129
1092
|
const { run, principal } = materialized;
|
|
1130
|
-
// Reconstruct admitted identity from durable run record + admitted
|
|
1093
|
+
// Reconstruct admitted identity from durable run record + the admitted section.
|
|
1131
1094
|
let instruction = "";
|
|
1132
1095
|
let instructionEmpty = true;
|
|
1133
1096
|
let attachments: FrozenAttachment[] = [];
|
|
@@ -1155,11 +1118,9 @@ async function loadResumableRunRecord(
|
|
|
1155
1118
|
let sourceRunPath: string | undefined;
|
|
1156
1119
|
let sourceRun: NotarySourceRunLocator | undefined;
|
|
1157
1120
|
try {
|
|
1158
|
-
const
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
if (isRecord(raw)) {
|
|
1162
|
-
const record = raw as Record<string, unknown>;
|
|
1121
|
+
const record = readPageSync(run.runDirectory, "admitted");
|
|
1122
|
+
if (record === undefined) throw new Error("state.jsonl has no admitted-request row");
|
|
1123
|
+
{
|
|
1163
1124
|
const storedRunDirectory =
|
|
1164
1125
|
typeof record.runDirectory === "string" && record.runDirectory.trim() !== ""
|
|
1165
1126
|
? record.runDirectory
|
|
@@ -1318,13 +1279,8 @@ async function loadResumableRunRecord(
|
|
|
1318
1279
|
}
|
|
1319
1280
|
let model: InvocationEffectiveModel | undefined;
|
|
1320
1281
|
try {
|
|
1321
|
-
const
|
|
1322
|
-
|
|
1323
|
-
);
|
|
1324
|
-
if (
|
|
1325
|
-
isRecord(invocationRaw)
|
|
1326
|
-
) {
|
|
1327
|
-
const rec = invocationRaw as Record<string, unknown>;
|
|
1282
|
+
const rec = readPageSync(run.runDirectory, "invocation");
|
|
1283
|
+
if (rec !== undefined) {
|
|
1328
1284
|
if (typeof rec.provider === "string" && typeof rec.model === "string") {
|
|
1329
1285
|
model = {
|
|
1330
1286
|
provider: rec.provider,
|
|
@@ -1423,7 +1379,6 @@ function resumedBaseAdmitted(loaded: {
|
|
|
1423
1379
|
attachments: loaded.admittedFields.attachments,
|
|
1424
1380
|
runDirectory: loaded.run.runDirectory,
|
|
1425
1381
|
principal: loaded.principal,
|
|
1426
|
-
admittedRequestPath: loaded.run.admittedRequestPath,
|
|
1427
1382
|
...(loaded.admittedFields.model === undefined ? {} : { model: loaded.admittedFields.model }),
|
|
1428
1383
|
...restoredTicketFields(loaded.admittedFields),
|
|
1429
1384
|
};
|