@akagilnc/pi-workflow-roles 0.1.5365 → 0.1.5375

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.
Files changed (170) hide show
  1. package/dist/acp-host/production-host.js +5585 -5655
  2. package/dist/activation-ledger-git.js +2 -2
  3. package/dist/activation-ledger-topology.js +1 -7
  4. package/dist/analyst-entry.js +4 -8
  5. package/dist/analyst-gate-cycles-read.js +3 -11
  6. package/dist/analyst-index.js +3 -9
  7. package/dist/analyst-ledger.js +1 -11
  8. package/dist/analyst-metric-families/acceptance-success-rework.js +1 -3
  9. package/dist/analyst-metric-families/round-timeline.js +1 -3
  10. package/dist/analyst-page.js +2 -2
  11. package/dist/archivist-record-topology.js +2 -2
  12. package/dist/audit-escalation.js +2 -1
  13. package/dist/auditor-soul.js +2 -1
  14. package/dist/collector-config.js +6 -8
  15. package/dist/compliance-transport.js +2 -1
  16. package/dist/countersign-contracts.js +2 -1
  17. package/dist/diarist-contracts.js +3 -2
  18. package/dist/doctor-contracts.js +1 -3
  19. package/dist/doctor-evidence.js +7 -8
  20. package/dist/dossier-resolution.js +1 -3
  21. package/dist/engine-detour-usage.js +1 -3
  22. package/dist/gatekeeper-role.js +2 -9
  23. package/dist/gleaner-left-contracts.js +2 -1
  24. package/dist/headless-host/description.js +14 -17
  25. package/dist/headless-host/production-host.js +1665 -1737
  26. package/dist/host-session-record.js +3 -2
  27. package/dist/inspector-contracts.js +2 -1
  28. package/dist/ledger-session-read.js +1 -3
  29. package/dist/merger-contracts.js +9 -9
  30. package/dist/migrate-book-topology.js +348 -314
  31. package/dist/navigator-attendance.js +9 -11
  32. package/dist/navigator-invocation-identity.js +3 -2
  33. package/dist/navigator-public-session.js +3 -5
  34. package/dist/navigator-session-contracts.js +8 -10
  35. package/dist/navigator-work-base.js +5 -8
  36. package/dist/notary-contracts.js +3 -5
  37. package/dist/package-contracts/auditor-output.js +1 -3
  38. package/dist/package-contracts/fixer-packet.js +3 -6
  39. package/dist/package-contracts/gatekeeper-output.js +1 -3
  40. package/dist/package-contracts/navigator-output.js +8 -8
  41. package/dist/package-contracts/terminating-infrastructure.js +5 -9
  42. package/dist/package-contracts/terminating-tools.js +4 -3
  43. package/dist/public-cli/analyst-run.js +3 -2
  44. package/dist/public-cli/auto-resume.js +4 -9
  45. package/dist/public-cli/cli.js +66 -64
  46. package/dist/public-cli/config.js +12 -11
  47. package/dist/public-cli/countersign-run.js +1 -3
  48. package/dist/public-cli/host-providers.js +7 -14
  49. package/dist/public-cli/instruction-seat-run.js +69 -43
  50. package/dist/public-cli/invocation.js +141 -136
  51. package/dist/public-cli/main.js +1919 -1968
  52. package/dist/public-cli/post-admission.js +89 -89
  53. package/dist/public-cli/role-seat-runtime.js +29 -0
  54. package/dist/public-cli/run-lifecycle.js +20 -32
  55. package/dist/public-cli/settlement.js +10 -26
  56. package/dist/public-cli/turn-request.js +14 -0
  57. package/dist/public-role-summons.js +23 -35
  58. package/dist/receipt-delivery-policy.js +1 -3
  59. package/dist/role-run-placement.js +7 -5
  60. package/dist/role-run-relocation.js +12 -19
  61. package/dist/run-terminal-artifacts.js +1 -11
  62. package/dist/run-ticket-number.js +2 -4
  63. package/dist/session-assistant-usage.js +2 -1
  64. package/dist/session-dialogue.js +1 -14
  65. package/dist/sitian-reader.js +2 -4
  66. package/dist/submission-correctable-error.js +2 -1
  67. package/dist/submission-errors.js +2 -1
  68. package/dist/submission-gate.js +2 -1
  69. package/dist/submission-ledger.js +4 -5
  70. package/dist/ticket-provenance-contracts.js +1 -3
  71. package/dist/ticket-provenance.js +2 -1
  72. package/dist/typed-provider-http.js +4 -7
  73. package/dist/unknown-value.js +28 -0
  74. package/dist/user-dialogue-stdin.js +2 -1
  75. package/package.json +1 -1
  76. package/src/acp-host/role-turn-host.ts +4 -2
  77. package/src/activation-ledger-git.ts +3 -2
  78. package/src/activation-ledger-topology.ts +4 -12
  79. package/src/analyst-entry.ts +3 -11
  80. package/src/analyst-gate-cycles-read.ts +3 -15
  81. package/src/analyst-index.ts +3 -13
  82. package/src/analyst-ledger.ts +2 -16
  83. package/src/analyst-metric-families/acceptance-success-rework.ts +2 -4
  84. package/src/analyst-metric-families/round-timeline.ts +2 -4
  85. package/src/analyst-page.ts +2 -2
  86. package/src/archivist-record-topology.ts +2 -2
  87. package/src/audit-escalation.ts +2 -1
  88. package/src/auditor-soul.ts +3 -1
  89. package/src/book-topology-migration-placement.ts +8 -21
  90. package/src/book-topology-migrators-t11.ts +16 -15
  91. package/src/book-topology-mixed-volume-migrators.ts +3 -6
  92. package/src/book-topology-record-class-migrators.ts +7 -10
  93. package/src/book-topology-runs-migrator.ts +4 -3
  94. package/src/collector-config.ts +7 -9
  95. package/src/compliance-transport.ts +2 -1
  96. package/src/countersign-contracts.ts +2 -1
  97. package/src/diarist-contracts.ts +3 -2
  98. package/src/doctor-contracts.ts +3 -1
  99. package/src/doctor-evidence.ts +8 -7
  100. package/src/doctor-role.ts +4 -2
  101. package/src/dossier-resolution.ts +2 -4
  102. package/src/engine-detour-tool.ts +0 -2
  103. package/src/engine-detour-usage.ts +2 -4
  104. package/src/external-host-turn-loop.ts +3 -1
  105. package/src/factory-board.ts +1 -8
  106. package/src/gatekeeper-role.ts +2 -10
  107. package/src/gleaner-left-contracts.ts +3 -1
  108. package/src/headless-host/description.ts +15 -18
  109. package/src/headless-host/role-turn-host.ts +10 -9
  110. package/src/host-session-record.ts +4 -2
  111. package/src/inspector-contracts.ts +2 -1
  112. package/src/ledger-session-read.ts +2 -5
  113. package/src/merger-contracts.ts +10 -9
  114. package/src/navigator-attendance.ts +10 -12
  115. package/src/navigator-invocation-identity.ts +3 -2
  116. package/src/navigator-public-session.ts +4 -6
  117. package/src/navigator-session-contracts.ts +8 -11
  118. package/src/navigator-work-base.ts +5 -8
  119. package/src/navigator-work-context.ts +2 -1
  120. package/src/notary-contracts.ts +4 -6
  121. package/src/oauth-keepalive.ts +5 -18
  122. package/src/package-contracts/auditor-output.ts +2 -4
  123. package/src/package-contracts/fixer-packet.ts +4 -6
  124. package/src/package-contracts/gatekeeper-output.ts +2 -4
  125. package/src/package-contracts/judge-output.ts +0 -1
  126. package/src/package-contracts/navigator-output.ts +8 -8
  127. package/src/package-contracts/terminating-infrastructure.ts +6 -20
  128. package/src/package-contracts/terminating-tools.ts +8 -12
  129. package/src/pi/adapter.ts +0 -1
  130. package/src/pi/role-turn-host.ts +0 -1
  131. package/src/public-cli/analyst-run.ts +4 -2
  132. package/src/public-cli/auto-resume.ts +5 -12
  133. package/src/public-cli/cli.ts +77 -83
  134. package/src/public-cli/config.ts +16 -27
  135. package/src/public-cli/countersign-run.ts +2 -4
  136. package/src/public-cli/host-providers.ts +10 -27
  137. package/src/public-cli/instruction-seat-run.ts +87 -58
  138. package/src/public-cli/invocation.ts +159 -172
  139. package/src/public-cli/post-admission.ts +115 -103
  140. package/src/public-cli/role-seat-runtime.ts +72 -0
  141. package/src/public-cli/run-lifecycle.ts +27 -67
  142. package/src/public-cli/settlement.ts +11 -33
  143. package/src/public-cli/terminal.ts +2 -17
  144. package/src/public-cli/turn-request.ts +26 -0
  145. package/src/public-role-summons.ts +24 -48
  146. package/src/receipt-delivery-policy.ts +1 -4
  147. package/src/reviewer-role.ts +0 -1
  148. package/src/role-envelope.ts +5 -3
  149. package/src/role-run-placement.ts +9 -10
  150. package/src/role-run-relocation.ts +13 -23
  151. package/src/role-runtime.ts +9 -15
  152. package/src/run-terminal-artifacts.ts +2 -16
  153. package/src/run-ticket-number.ts +4 -10
  154. package/src/session-assistant-usage.ts +3 -1
  155. package/src/session-dialogue.ts +1 -4
  156. package/src/session-identity.ts +0 -1
  157. package/src/sitian-reader.ts +2 -4
  158. package/src/submission-correctable-error.ts +3 -1
  159. package/src/submission-errors.ts +2 -1
  160. package/src/submission-gate.ts +3 -1
  161. package/src/submission-ledger.ts +5 -6
  162. package/src/ticket-provenance-contracts.ts +1 -4
  163. package/src/ticket-provenance.ts +3 -1
  164. package/src/ticket-snapshot.ts +2 -4
  165. package/src/ticket-trajectory.ts +1 -8
  166. package/src/typed-provider-http.ts +5 -15
  167. package/src/unknown-value.ts +34 -0
  168. package/src/user-dialogue-stdin.ts +3 -1
  169. package/src/worker-role.ts +2 -5
  170. package/src/worker-submission-gates.ts +5 -7
@@ -10,6 +10,7 @@ import { writeFile } from "node:fs/promises";
10
10
  import { isAbsolute, join, resolve } from "node:path";
11
11
  import { buildAutoResumeContinuationPrompt, findRunDirectoryById, readRoleRunState, RESUME_TRANSPORT_ENVELOPE, } from "./run-lifecycle.js";
12
12
  import { CliUsageError } from "./cli-errors.js";
13
+ import { projectPublicTurnAxes } from "./turn-request.js";
13
14
  import { bindAdmittedTicketNumber, buildInstructionTransportPrompt, freezeAttachmentsIntoRun, relocateAdmittedRunToTicket, } from "./invocation.js";
14
15
  import { readRecordedSubmissionRows } from "../submission-ledger.js";
15
16
  import { readDeclaredTicketNumber } from "../run-ticket-number.js";
@@ -41,14 +42,15 @@ import { homeFromRunDirectory } from "../activation-ledger-topology.js";
41
42
  import { recordRunStart } from "../host-session-record.js";
42
43
  import { attemptProducedFreshSubmission, classifyPostAdmissionFailure, controlledFailureInputFromResolution, exitCodeForTerminalOutcome, explicitInternalKnownFailureClassificationInput, formatCliDiagnostic, formatErrorCauseDetail, formatTerminalResult, inspectJudgeSession, isLawfulTypedTerminalOutcome, presentFailureTerminal, publishedFailureErrorPath, presentStructuralRejection, resolveAuditedRunnerFailureResolution, resolveControlledFailureResumeObservation, settleFailureTerminalResult, settleHostEndedNoReceipt, attachRecordedSubmissions, rewritePublishedFailureErrorPath, } from "./settlement.js";
43
44
  import {} from "./terminal.js";
44
- import { ensureRealArtifactsDirectory, persistReturnedRunState, runWithAutoResumeLoop, TurnDispatchedFailure, } from "./auto-resume.js";
45
+ import { ensureRealArtifactsDirectory, persistReturnedRunState, runWithAutoResumeLoop, TurnDispatchedFailure, writeHardenedArtifactFile, } from "./auto-resume.js";
46
+ import { isRecord, errorText } from "../unknown-value.js";
45
47
  function projectRelocatedTurnIdentity(request, result, admitted, relocation) {
46
48
  const rewrite = (value) => rewriteRunDirectoryPathValue(value, relocation.oldRunDirectory, relocation.newRunDirectory);
47
49
  const mutableRequest = request;
48
50
  mutableRequest.runDirectory = admitted.runDirectory;
49
51
  mutableRequest.principal = admitted.principal;
50
52
  const activation = mutableRequest.activation;
51
- if (activation !== null && typeof activation === "object" && !Array.isArray(activation)) {
53
+ if (isRecord(activation)) {
52
54
  for (const field of ["taskPath", "packetPath", "prerequisitesPath", "inputPath", "requestManifestPath"]) {
53
55
  const record = activation;
54
56
  if (field in record)
@@ -131,7 +133,10 @@ async function recordBestEffortPostDispatchDiagnostic(admitted, env, diagnostic,
131
133
  catch (appendError) {
132
134
  try {
133
135
  const artifactsDir = await ensureRealArtifactsDirectory(admitted.runDirectory);
134
- await writeFile(join(artifactsDir, `post-admission-diagnostic-${randomUUID()}.json`), `${JSON.stringify({ version: 1, ...payload }, null, 2)}\n`, { encoding: "utf8", flag: "wx" });
136
+ await writeHardenedArtifactFile(artifactsDir, "post-admission-diagnostic", {
137
+ version: 1,
138
+ ...payload,
139
+ });
135
140
  }
136
141
  catch (artifactError) {
137
142
  retentionFailure =
@@ -348,7 +353,7 @@ export async function dispatchPostAdmissionTurn(input) {
348
353
  continue;
349
354
  }
350
355
  const payload = row.accepted;
351
- if (payload === null || typeof payload !== "object" || Array.isArray(payload))
356
+ if (!isRecord(payload))
352
357
  continue;
353
358
  ticketNumber = readDeclaredTicketNumber(payload.ticketNumber);
354
359
  if (ticketNumber !== undefined)
@@ -817,13 +822,8 @@ export function resumeTurnRequestProjectionOptions(admitted, request, env, summo
817
822
  prompt = "";
818
823
  }
819
824
  return {
820
- packageRoot: env.packageRoot,
821
- home: env.home,
825
+ ...projectPublicTurnAxes(env),
822
826
  ...(env.host === undefined ? {} : { host: env.host }),
823
- agentDir: env.agentDir,
824
- ...(env.model === undefined ? {} : { model: env.model }),
825
- ...pickEngineAxis(env),
826
- ...(env.timeoutMs === undefined ? {} : { timeoutMs: env.timeoutMs }),
827
827
  ...(env.correlationId === undefined && admitted.correlationId === undefined
828
828
  ? {}
829
829
  : { correlationId: env.correlationId ?? admitted.correlationId }),
@@ -839,13 +839,8 @@ export function resumeTurnRequestProjectionOptions(admitted, request, env, summo
839
839
  export function roleTurnOptions(env, admitted, continuation) {
840
840
  const correlationId = env.correlationId ?? admitted.correlationId;
841
841
  return {
842
- packageRoot: env.packageRoot,
843
- home: env.home,
842
+ ...projectPublicTurnAxes(env),
844
843
  ...(env.host === undefined ? {} : { host: env.host }),
845
- agentDir: env.agentDir,
846
- ...(env.model === undefined ? {} : { model: env.model }),
847
- ...pickEngineAxis(env),
848
- ...(env.timeoutMs === undefined ? {} : { timeoutMs: env.timeoutMs }),
849
844
  ...(correlationId === undefined || correlationId.trim() === ""
850
845
  ? {}
851
846
  : { correlationId }),
@@ -872,6 +867,44 @@ async function dispatchAfterWriterLease(input) {
872
867
  }
873
868
  }
874
869
  }
870
+ /**
871
+ * One auto-resume dispatch: deferred run-state persist settles on the same
872
+ * path for station-child and ordinary in-call retries. The caller owns how
873
+ * the turn request is built and which correlation id the env carries.
874
+ */
875
+ async function runSettledAutoResumeLoop(input) {
876
+ const adapters = withOnceSuccessfulBeforeDispatch(input.adapters);
877
+ const dispatchEnv = input.dispatchEnv ?? input.env;
878
+ return runWithAutoResumeLoop({
879
+ admitted: input.admitted,
880
+ principalAuthority: input.env.principalAuthority,
881
+ io: input.io,
882
+ sessionAppender: input.env.sessionAppender,
883
+ autoResumeLimit: input.env.autoResumeLimit,
884
+ ...(input.env.signal === undefined ? {} : { signal: input.env.signal }),
885
+ buildInitialPayload: input.buildInitialPayload,
886
+ buildResumePayload: input.buildResumePayload,
887
+ dispatch: async (payload, lease, _isFirst, attemptIo) => dispatchAfterWriterLease({
888
+ ...(lease === undefined ? {} : { lease }),
889
+ build: () => input.toRequest(payload),
890
+ dispatch: async (request) => {
891
+ const result = await dispatchPostAdmissionTurn({
892
+ admitted: input.admitted,
893
+ env: dispatchEnv,
894
+ io: attemptIo,
895
+ request,
896
+ ...(lease === undefined ? {} : { lease }),
897
+ adapters,
898
+ persistRunState: false,
899
+ ...(input.effectiveEngine === undefined
900
+ ? {}
901
+ : { effectiveEngine: input.effectiveEngine }),
902
+ });
903
+ return settleDeferredPersist(input.admitted, input.env.principalAuthority, adapters, attemptIo, result);
904
+ },
905
+ }),
906
+ });
907
+ }
875
908
  function isAlreadyFrozenSummonsAttachment(runDirectory, attachmentPath) {
876
909
  const absolute = isAbsolute(attachmentPath)
877
910
  ? attachmentPath
@@ -1018,65 +1051,45 @@ export async function runPostAdmissionSeatResume(input) {
1018
1051
  try {
1019
1052
  if (env.stationChild === true) {
1020
1053
  let firstTurn;
1021
- const stationAdapters = withOnceSuccessfulBeforeDispatch(adapters);
1022
1054
  // One public call → one detour scope across in-place auto-resume dispatches.
1023
1055
  const invocationScopeId = mintEngineDetourInvocationScope({
1024
1056
  ...(input.effectiveEngine === undefined
1025
1057
  ? {}
1026
1058
  : { effectiveEngine: input.effectiveEngine }),
1027
1059
  });
1028
- return await runWithAutoResumeLoop({
1060
+ return await runSettledAutoResumeLoop({
1029
1061
  admitted: loaded.admitted,
1030
- principalAuthority: env.principalAuthority,
1062
+ env,
1031
1063
  io: input.io,
1032
- sessionAppender: env.sessionAppender,
1033
- autoResumeLimit: env.autoResumeLimit,
1034
- ...(env.signal === undefined ? {} : { signal: env.signal }),
1064
+ adapters,
1065
+ ...(input.effectiveEngine === undefined
1066
+ ? {}
1067
+ : { effectiveEngine: input.effectiveEngine }),
1035
1068
  buildInitialPayload: () => ({ resumeTurn: false }),
1036
1069
  buildResumePayload: () => ({ resumeTurn: true }),
1037
- // Same as public manual resume: prior-court sealed acceptance is not a
1038
- // redispatch brake (#833). New-court station-child turns still auto-resume.
1039
- dispatch: async (payload, lease, _isFirst, attemptIo) => dispatchAfterWriterLease({
1040
- ...(lease === undefined ? {} : { lease }),
1041
- build: async () => {
1042
- // #840 r8 判词 class 2: this call-local retry must keep this
1043
- // court's frozen summons / 交卷 body / attachments verbatim
1044
- // (same object as firstTurn) and project only the minimal
1045
- // host-needed resume trigger — never engine handbook material,
1046
- // which would replace a 审核循环 same-ticket continuation with a bare outsourcing
1047
- // 「重新读」 envelope (#755 contract, resumeTurnRequestProjectionOptions
1048
- // above). RESUME_TRANSPORT_ENVELOPE is the same package-owned,
1049
- // non-semantic trigger that projection already uses for a
1050
- // same-ticket summons carrying no instruction/attachments.
1051
- if (payload.resumeTurn && firstTurn !== undefined) {
1052
- return {
1053
- ...firstTurn,
1054
- continuation: {
1055
- kind: "resume",
1056
- prompt: RESUME_TRANSPORT_ENVELOPE,
1057
- },
1058
- };
1059
- }
1060
- const turnRequest = withEngineDetourInvocationScope(await buildRequestAfterLease(), invocationScopeId);
1061
- firstTurn = turnRequest;
1062
- return turnRequest;
1063
- },
1064
- dispatch: async (turnRequest) => {
1065
- const result = await dispatchPostAdmissionTurn({
1066
- admitted: loaded.admitted,
1067
- env,
1068
- io: attemptIo,
1069
- request: turnRequest,
1070
- ...(lease === undefined ? {} : { lease }),
1071
- adapters: stationAdapters,
1072
- persistRunState: false,
1073
- ...(input.effectiveEngine === undefined
1074
- ? {}
1075
- : { effectiveEngine: input.effectiveEngine }),
1076
- });
1077
- return settleDeferredPersist(loaded.admitted, env.principalAuthority, stationAdapters, attemptIo, result);
1078
- },
1079
- }),
1070
+ toRequest: async (payload) => {
1071
+ // #840 r8 判词 class 2: this call-local retry must keep this
1072
+ // court's frozen summons / 交卷 body / attachments verbatim
1073
+ // (same object as firstTurn) and project only the minimal
1074
+ // host-needed resume trigger — never engine handbook material,
1075
+ // which would replace a 审核循环 same-ticket continuation with a bare outsourcing
1076
+ // 「重新读」 envelope (#755 contract, resumeTurnRequestProjectionOptions
1077
+ // above). RESUME_TRANSPORT_ENVELOPE is the same package-owned,
1078
+ // non-semantic trigger that projection already uses for a
1079
+ // same-ticket summons carrying no instruction/attachments.
1080
+ if (payload.resumeTurn && firstTurn !== undefined) {
1081
+ return {
1082
+ ...firstTurn,
1083
+ continuation: {
1084
+ kind: "resume",
1085
+ prompt: RESUME_TRANSPORT_ENVELOPE,
1086
+ },
1087
+ };
1088
+ }
1089
+ const turnRequest = withEngineDetourInvocationScope(await buildRequestAfterLease(), invocationScopeId);
1090
+ firstTurn = turnRequest;
1091
+ return turnRequest;
1092
+ },
1080
1093
  });
1081
1094
  }
1082
1095
  const resumed = await runPostAdmissionManualResume({
@@ -1155,7 +1168,7 @@ async function presentResumeFailurePointer(io, thrown, publish) {
1155
1168
  cause.thrownCause = formatErrorCauseDetail(thrown.cause);
1156
1169
  }
1157
1170
  presentStructuralRejection({
1158
- message: thrown instanceof Error ? thrown.message : String(thrown),
1171
+ message: errorText(thrown),
1159
1172
  cause,
1160
1173
  }, io);
1161
1174
  }
@@ -1208,39 +1221,26 @@ export async function runPostAdmissionOneShot(input) {
1208
1221
  */
1209
1222
  export async function runPostAdmissionResumable(input) {
1210
1223
  const { admitted, env, io, buildInitialRequest, buildResumeRequest, effectiveEngine } = input;
1211
- const adapters = withOnceSuccessfulBeforeDispatch(input.adapters);
1212
1224
  // One public call → one detour scope across in-place auto-resume dispatches.
1213
1225
  const invocationScopeId = mintEngineDetourInvocationScope({
1214
1226
  ...(effectiveEngine === undefined ? {} : { effectiveEngine }),
1215
1227
  });
1216
1228
  const buildScopedInitial = () => withEngineDetourInvocationScope(buildInitialRequest(), invocationScopeId);
1217
1229
  const buildScopedResume = () => withEngineDetourInvocationScope(buildResumeRequest(), invocationScopeId);
1218
- return runWithAutoResumeLoop({
1230
+ return runSettledAutoResumeLoop({
1219
1231
  admitted,
1220
- principalAuthority: env.principalAuthority,
1232
+ env,
1221
1233
  io,
1222
- sessionAppender: env.sessionAppender,
1223
- autoResumeLimit: env.autoResumeLimit,
1224
- ...(env.signal === undefined ? {} : { signal: env.signal }),
1234
+ adapters: input.adapters,
1235
+ ...(effectiveEngine === undefined ? {} : { effectiveEngine }),
1236
+ // Ordinary in-call retry keeps the admitted correlation when one was stored.
1237
+ dispatchEnv: {
1238
+ ...env,
1239
+ ...(admitted.correlationId === undefined ? {} : { correlationId: admitted.correlationId }),
1240
+ },
1225
1241
  buildInitialPayload: buildScopedInitial,
1226
1242
  buildResumePayload: buildScopedResume,
1227
- dispatch: async (request, lease, _isFirst, attemptIo) => {
1228
- const result = await dispatchPostAdmissionTurn({
1229
- admitted,
1230
- env: {
1231
- ...env,
1232
- ...(admitted.correlationId === undefined ? {} : { correlationId: admitted.correlationId }),
1233
- },
1234
- io: attemptIo,
1235
- request,
1236
- ...(lease === undefined ? {} : { lease }),
1237
- adapters,
1238
- persistRunState: false,
1239
- // #600: every attempt (initial + auto-resume) writes seat engine when present.
1240
- ...(effectiveEngine === undefined ? {} : { effectiveEngine }),
1241
- });
1242
- return settleDeferredPersist(admitted, env.principalAuthority, adapters, attemptIo, result);
1243
- },
1243
+ toRequest: async (request) => request,
1244
1244
  });
1245
1245
  }
1246
1246
  /**
@@ -0,0 +1,29 @@
1
+ /**
2
+ * One seat-runtime assembly for the public CLI and nested summons.
3
+ * Order is host selection, the caller's argv parse, the missing-model fact,
4
+ * then host-facing provider projection. Callers own how a missing model is shown.
5
+ */
6
+ import { pickEngineAxis } from "../package-resources/engine-material.js";
7
+ import { resolvedSeatWithModel, } from "./config.js";
8
+ import { loadHostProvidersTable, projectHostFacingProvider, } from "./host-providers.js";
9
+ import { composeRoleTurnHostAdapters, selectRoleTurnHost, } from "./role-turn-host-resolution.js";
10
+ export function openRoleSeatRuntime(input) {
11
+ const hostAdapters = composeRoleTurnHostAdapters(input.resolution, input.principalAuthority);
12
+ const roleTurnHost = selectRoleTurnHost(hostAdapters, {
13
+ role: input.role,
14
+ seat: input.seat,
15
+ });
16
+ input.afterHost?.();
17
+ const seatWithModel = resolvedSeatWithModel(input.seat);
18
+ if (seatWithModel === undefined)
19
+ return { ok: false };
20
+ const projected = input.hostFacingModel ?? projectHostFacingProvider(seatWithModel.selection, seatWithModel.host, loadHostProvidersTable(input.home), input.home);
21
+ return {
22
+ ok: true,
23
+ roleTurnHost,
24
+ hostAdapters,
25
+ ...(projected === undefined ? {} : { model: projected }),
26
+ ...pickEngineAxis(seatWithModel),
27
+ host: seatWithModel.host,
28
+ };
29
+ }
@@ -17,7 +17,8 @@ import { parseCollectorRepository } from "../collector-config.js";
17
17
  import { rewriteAdmittedRoleRunPage, rewriteRunDirectoryPathValue, } from "../role-run-relocation.js";
18
18
  import { appendEngineSessionMaterial, engineSessionMaterialFromOptions, pickEngineAxis, } from "../package-resources/engine-material.js";
19
19
  import { packagedResumeSourcePath, packagedRoleMetadata, } from "../packaged-role-registry.js";
20
- import { recordEffectiveInvocationModel, requireAuthorityRef, isReviewerLens, } from "./invocation.js";
20
+ import { admittedReviewerBaseFault, recordEffectiveInvocationModel, requireAuthorityRef, isReviewerLens, } from "./invocation.js";
21
+ import { isRecord, errorText, isEnoent } from "../unknown-value.js";
21
22
  /** Providers eligible for v1 typed-429 resume (Codex / xAI only).
22
23
  * @deprecated v1 429-only gate removed by #416 (owner 2026-08-22: "根本不要有限制"). Kept for compatibility; do not use for new branching.
23
24
  */
@@ -72,7 +73,7 @@ export async function writeRoleRunState(runDirectory, record) {
72
73
  await writeFile(join(runDirectory, RUN_STATE_FILE), `${JSON.stringify(payload, null, 2)}\n`, "utf8");
73
74
  }
74
75
  function parseSameTicketSummonsMaterials(raw) {
75
- if (raw === null || typeof raw !== "object" || Array.isArray(raw))
76
+ if (!isRecord(raw))
76
77
  return undefined;
77
78
  const record = raw;
78
79
  const instruction = typeof record.instruction === "string" ? record.instruction : undefined;
@@ -84,9 +85,7 @@ function parseSameTicketSummonsMaterials(raw) {
84
85
  ? record.sourceRunPath
85
86
  : undefined;
86
87
  let sourceRun;
87
- if (record.sourceRun !== null &&
88
- typeof record.sourceRun === "object" &&
89
- !Array.isArray(record.sourceRun)) {
88
+ if (isRecord(record.sourceRun)) {
90
89
  const sr = record.sourceRun;
91
90
  if (typeof sr.runId === "string" &&
92
91
  sr.runId.trim() !== "" &&
@@ -119,7 +118,7 @@ function parseSameTicketSummonsMaterials(raw) {
119
118
  };
120
119
  }
121
120
  function parseCurrentCourtState(raw) {
122
- if (raw === null || typeof raw !== "object" || Array.isArray(raw))
121
+ if (!isRecord(raw))
123
122
  return undefined;
124
123
  const record = raw;
125
124
  if (typeof record.courtAttemptId !== "string" || record.courtAttemptId.length === 0) {
@@ -150,7 +149,7 @@ async function readRoleRunStateRaw(runDirectory) {
150
149
  return raw;
151
150
  }
152
151
  function parseRoleRunIdentity(raw, runDirectory) {
153
- if (raw === null || typeof raw !== "object" || Array.isArray(raw)) {
152
+ if (!isRecord(raw)) {
154
153
  throw new TypeError("Invalid run-state.json");
155
154
  }
156
155
  const record = raw;
@@ -202,8 +201,7 @@ async function readRoleRunStateDisk(runDirectory) {
202
201
  };
203
202
  let resumable;
204
203
  if (record.resumable !== undefined && record.resumable !== null) {
205
- if (typeof record.resumable === "object" &&
206
- !Array.isArray(record.resumable)) {
204
+ if (isRecord(record.resumable)) {
207
205
  const r = record.resumable;
208
206
  if (r.httpStatus === 429 &&
209
207
  typeof r.provider === "string" &&
@@ -767,7 +765,7 @@ export async function readRunParentPath(runDirectory) {
767
765
  return undefined;
768
766
  throw error;
769
767
  }
770
- if (raw === null || typeof raw !== "object" || Array.isArray(raw)) {
768
+ if (!isRecord(raw)) {
771
769
  return undefined;
772
770
  }
773
771
  const record = raw;
@@ -916,7 +914,7 @@ async function loadResumableRunRecord(home, runId, authority) {
916
914
  let sourceRun;
917
915
  try {
918
916
  const raw = JSON.parse(await readFile(run.admittedRequestPath, "utf8"));
919
- if (raw !== null && typeof raw === "object" && !Array.isArray(raw)) {
917
+ if (isRecord(raw)) {
920
918
  const record = raw;
921
919
  const storedRunDirectory = typeof record.runDirectory === "string" && record.runDirectory.trim() !== ""
922
920
  ? record.runDirectory
@@ -983,9 +981,7 @@ async function loadResumableRunRecord(home, runId, authority) {
983
981
  if (typeof record.caseRunsPath === "string" && record.caseRunsPath.trim() !== "") {
984
982
  caseRunsPath = record.caseRunsPath;
985
983
  }
986
- if (record.caseIdentity !== null &&
987
- typeof record.caseIdentity === "object" &&
988
- !Array.isArray(record.caseIdentity)) {
984
+ if (isRecord(record.caseIdentity)) {
989
985
  const ci = record.caseIdentity;
990
986
  if (typeof ci.issueNumber === "number" &&
991
987
  Number.isSafeInteger(ci.issueNumber) &&
@@ -999,9 +995,7 @@ async function loadResumableRunRecord(home, runId, authority) {
999
995
  if (typeof record.sourceRunPath === "string" && record.sourceRunPath.trim() !== "") {
1000
996
  sourceRunPath = record.sourceRunPath;
1001
997
  }
1002
- if (record.sourceRun !== null &&
1003
- typeof record.sourceRun === "object" &&
1004
- !Array.isArray(record.sourceRun)) {
998
+ if (isRecord(record.sourceRun)) {
1005
999
  const sr = record.sourceRun;
1006
1000
  if (typeof sr.runId === "string" &&
1007
1001
  sr.runId.trim() !== "" &&
@@ -1029,9 +1023,7 @@ async function loadResumableRunRecord(home, runId, authority) {
1029
1023
  record.mergerInputPath.trim() !== "") {
1030
1024
  mergerInputPath = record.mergerInputPath;
1031
1025
  }
1032
- if (record.derived !== null &&
1033
- typeof record.derived === "object" &&
1034
- !Array.isArray(record.derived)) {
1026
+ if (isRecord(record.derived)) {
1035
1027
  const d = record.derived;
1036
1028
  if (typeof d.targetObjectId === "string" &&
1037
1029
  typeof d.sourceObjectId === "string" &&
@@ -1061,9 +1053,7 @@ async function loadResumableRunRecord(home, runId, authority) {
1061
1053
  let model;
1062
1054
  try {
1063
1055
  const invocationRaw = JSON.parse(await readFile(join(run.runDirectory, "invocation.json"), "utf8"));
1064
- if (invocationRaw !== null &&
1065
- typeof invocationRaw === "object" &&
1066
- !Array.isArray(invocationRaw)) {
1056
+ if (isRecord(invocationRaw)) {
1067
1057
  const rec = invocationRaw;
1068
1058
  if (typeof rec.provider === "string" && typeof rec.model === "string") {
1069
1059
  model = {
@@ -1087,9 +1077,7 @@ async function loadResumableRunRecord(home, runId, authority) {
1087
1077
  if (error instanceof CliUsageError) {
1088
1078
  throw error;
1089
1079
  }
1090
- if (!(error instanceof Error &&
1091
- "code" in error &&
1092
- error.code === "ENOENT")) {
1080
+ if (!isEnoent(error)) {
1093
1081
  throw new CliUsageError(`role run invocation identity is unreadable: ${runId}`, { cause: error });
1094
1082
  }
1095
1083
  }
@@ -1263,11 +1251,11 @@ function admitResumedRole(loaded) {
1263
1251
  }
1264
1252
  case "review-basis": {
1265
1253
  const rawBase = fields.baseRevision;
1266
- if (rawBase === undefined || rawBase.trim() === "") {
1267
- throw new CliUsageError(`role run admitted reviewer base revision is missing: ${runId}`);
1268
- }
1269
- if (/\s/.test(rawBase) || rawBase.startsWith("-")) {
1270
- throw new CliUsageError(`role run admitted reviewer base revision is damaged: ${runId}`);
1254
+ const baseFault = admittedReviewerBaseFault(rawBase);
1255
+ if (baseFault !== undefined || rawBase === undefined) {
1256
+ throw new CliUsageError(baseFault === "damaged"
1257
+ ? `role run admitted reviewer base revision is damaged: ${runId}`
1258
+ : `role run admitted reviewer base revision is missing: ${runId}`);
1271
1259
  }
1272
1260
  const lens = fields.lens;
1273
1261
  if (!isReviewerLens(lens)) {
@@ -1331,7 +1319,7 @@ function admitResumedRole(loaded) {
1331
1319
  parsedRepository = parseCollectorRepository(repositoryDisplay);
1332
1320
  }
1333
1321
  catch (error) {
1334
- const detail = error instanceof Error ? error.message : String(error);
1322
+ const detail = errorText(error);
1335
1323
  throw new CliUsageError(detail, { cause: error });
1336
1324
  }
1337
1325
  if (parsedRepository.canonical !== repository) {
@@ -167,6 +167,7 @@ function coordinatesFromAdmitted(authority, admitted) {
167
167
  return authority.decode(admitted.principal);
168
168
  }
169
169
  import { coalesceSubmissionRows, exitCodeForTerminalOutcome, formatTerminalResult, isLawfulTypedTerminalOutcome, adviceNavigatorFact, } from "./terminal.js";
170
+ import { isEnoent, isMissingPathError, isRecord } from "../unknown-value.js";
170
171
  export { exitCodeForTerminalOutcome, formatTerminalResult, isLawfulTypedTerminalOutcome, };
171
172
  // A resumable public Terminal omits artifact paths (#108); its actual error
172
173
  // publication remains available only to the CLI's resume presentation seam.
@@ -239,7 +240,7 @@ export async function inspectJudgeSession(sessionFile) {
239
240
  return { state: "present" };
240
241
  }
241
242
  catch (error) {
242
- if (isMissingPathError(error))
243
+ if (isEnoent(error))
243
244
  return { state: "missing" };
244
245
  return {
245
246
  state: "unreadable",
@@ -493,18 +494,6 @@ export function explicitInternalKnownFailureClassificationInput(failure) {
493
494
  * the budget to start a cold full host turn (owner 2026-09-17 #959).
494
495
  */
495
496
  export const NAVIGATOR_POST_ROLE_GRACE_MS = 10_000;
496
- function isMissingPathError(error) {
497
- return (error instanceof Error &&
498
- "code" in error &&
499
- error.code === "ENOENT");
500
- }
501
- /** Face clear only: path not enterable as a face (ENOENT or file mid-path). */
502
- function isAbsentFacePathError(error) {
503
- return (error instanceof Error &&
504
- "code" in error &&
505
- (error.code === "ENOENT" ||
506
- error.code === "ENOTDIR"));
507
- }
508
497
  /**
509
498
  * Preserve session-read failure identity as a typed session cause.
510
499
  * SyntaxError keeps its name so durable settlement does not wash malformed JSONL
@@ -665,7 +654,7 @@ async function loadBoundAuditorVolumes(sessionFile) {
665
654
  parentEntries = await readBoundSessionEntries(sessionFile);
666
655
  }
667
656
  catch (error) {
668
- if (isMissingPathError(error))
657
+ if (isEnoent(error))
669
658
  return undefined;
670
659
  throw sessionReadFailure(error, "failed to read parent session for auditor binding");
671
660
  }
@@ -682,7 +671,7 @@ async function loadBoundAuditorVolumes(sessionFile) {
682
671
  sawAnyDirectory = true;
683
672
  }
684
673
  catch (error) {
685
- if (isMissingPathError(error))
674
+ if (isEnoent(error))
686
675
  continue;
687
676
  throw sessionReadFailure(error, "failed to read bound auditor session directory");
688
677
  }
@@ -887,7 +876,7 @@ export async function resolveAuditedRunnerFailureResolution(input) {
887
876
  return resolutionOf(terminatingFailure);
888
877
  }
889
878
  catch (error) {
890
- if (!isMissingPathError(error)) {
879
+ if (!isEnoent(error)) {
891
880
  const failure = sessionReadFailure(error, "failed to recover typed terminating-tool failure");
892
881
  return resolutionOf({
893
882
  cause: "session",
@@ -1005,9 +994,6 @@ export function controlledFailureInputFromResolution(resolution) {
1005
994
  : {}),
1006
995
  };
1007
996
  }
1008
- function isRecord(value) {
1009
- return typeof value === "object" && value !== null && !Array.isArray(value);
1010
- }
1011
997
  function safelyRead(object, key) {
1012
998
  try {
1013
999
  return { readable: true, value: object[key] };
@@ -1024,9 +1010,7 @@ function toolResultText(message) {
1024
1010
  return "";
1025
1011
  return content
1026
1012
  .map((part) => {
1027
- if (typeof part === "object" &&
1028
- part !== null &&
1029
- !Array.isArray(part) &&
1013
+ if (isRecord(part) &&
1030
1014
  typeof part.text === "string") {
1031
1015
  return part.text;
1032
1016
  }
@@ -1611,7 +1595,7 @@ async function extractNavigatorFactFromAdmittedSession(sessionFile) {
1611
1595
  return extractNavigatorFact(entries);
1612
1596
  }
1613
1597
  catch (error) {
1614
- if (isMissingPathError(error)) {
1598
+ if (isEnoent(error)) {
1615
1599
  return {
1616
1600
  disposition: "unavailable",
1617
1601
  source: "unknown",
@@ -1638,7 +1622,7 @@ async function removeFaceIfPresent(path) {
1638
1622
  // force:true already ignores ENOENT; ENOTDIR = face path not enterable
1639
1623
  // (artifacts-as-file mid-path) — same absent-face semantics as the reader.
1640
1624
  // Other errno stay loud (失败诚实).
1641
- if (isAbsentFacePathError(error))
1625
+ if (isMissingPathError(error))
1642
1626
  return;
1643
1627
  throw error;
1644
1628
  }
@@ -1722,7 +1706,7 @@ async function readLawfulSettlementEntries(sessionFile) {
1722
1706
  }
1723
1707
  catch (error) {
1724
1708
  // Missing path is absence of a lawful outcome; callers classify via session inspect.
1725
- if (isMissingPathError(error))
1709
+ if (isEnoent(error))
1726
1710
  return undefined;
1727
1711
  // Malformed JSONL and other read failures keep typed session identity.
1728
1712
  throw error instanceof Error &&
@@ -2028,7 +2012,7 @@ function countersignTerminalFromEntries(entries) {
2028
2012
  continue;
2029
2013
  if (entry.customType !== SECRETARIAT_GATE_OFFICER_ENTRY_TYPE)
2030
2014
  continue;
2031
- const data = entry.data !== null && typeof entry.data === "object" && !Array.isArray(entry.data)
2015
+ const data = isRecord(entry.data)
2032
2016
  ? entry.data
2033
2017
  : undefined;
2034
2018
  if (data === undefined || !packagedDurableOfficerEntry(data.officer))
@@ -2,6 +2,20 @@ import { pickEngineAxis } from "../package-resources/engine-material.js";
2
2
  import { packagedRoleActivationFlags, packagedRoleMetadata, } from "../packaged-role-registry.js";
3
3
  import { installedMethodSkillPath } from "./machine-method-skills.js";
4
4
  import { parentRunPathFromGatePointerInstruction } from "./run-lifecycle.js";
5
+ /**
6
+ * Env axes shared by every public turn projection.
7
+ * Callers add correlation, continuation, host, and station-only fields.
8
+ */
9
+ export function projectPublicTurnAxes(env) {
10
+ return {
11
+ packageRoot: env.packageRoot,
12
+ home: env.home,
13
+ agentDir: env.agentDir,
14
+ ...(env.model === undefined ? {} : { model: env.model }),
15
+ ...pickEngineAxis(env),
16
+ ...(env.timeoutMs === undefined ? {} : { timeoutMs: env.timeoutMs }),
17
+ };
18
+ }
5
19
  export function projectRoleTurnRequest(admitted, roleDetails, options) {
6
20
  const cwd = admitted.projectRoot ?? admitted.repoRoot ?? admitted.cwd;
7
21
  if (cwd === undefined)