@akagilnc/pi-workflow-roles 0.1.5368 → 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 (165) hide show
  1. package/dist/acp-host/production-host.js +719 -776
  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 +721 -780
  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 +3 -8
  45. package/dist/public-cli/cli.js +9 -8
  46. package/dist/public-cli/config.js +8 -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 +4 -3
  50. package/dist/public-cli/invocation.js +9 -8
  51. package/dist/public-cli/main.js +1531 -1567
  52. package/dist/public-cli/post-admission.js +4 -3
  53. package/dist/public-cli/run-lifecycle.js +14 -26
  54. package/dist/public-cli/settlement.js +10 -26
  55. package/dist/public-role-summons.js +3 -2
  56. package/dist/receipt-delivery-policy.js +1 -3
  57. package/dist/role-run-placement.js +3 -5
  58. package/dist/role-run-relocation.js +12 -19
  59. package/dist/run-terminal-artifacts.js +1 -11
  60. package/dist/run-ticket-number.js +2 -4
  61. package/dist/session-assistant-usage.js +2 -1
  62. package/dist/session-dialogue.js +1 -14
  63. package/dist/sitian-reader.js +2 -4
  64. package/dist/submission-correctable-error.js +2 -1
  65. package/dist/submission-errors.js +2 -1
  66. package/dist/submission-gate.js +2 -1
  67. package/dist/submission-ledger.js +4 -5
  68. package/dist/ticket-provenance-contracts.js +1 -3
  69. package/dist/ticket-provenance.js +2 -1
  70. package/dist/typed-provider-http.js +4 -7
  71. package/dist/unknown-value.js +28 -0
  72. package/dist/user-dialogue-stdin.js +2 -1
  73. package/package.json +1 -1
  74. package/src/acp-host/role-turn-host.ts +4 -2
  75. package/src/activation-ledger-git.ts +3 -2
  76. package/src/activation-ledger-topology.ts +4 -12
  77. package/src/analyst-entry.ts +3 -11
  78. package/src/analyst-gate-cycles-read.ts +3 -15
  79. package/src/analyst-index.ts +3 -13
  80. package/src/analyst-ledger.ts +2 -16
  81. package/src/analyst-metric-families/acceptance-success-rework.ts +2 -4
  82. package/src/analyst-metric-families/round-timeline.ts +2 -4
  83. package/src/analyst-page.ts +2 -2
  84. package/src/archivist-record-topology.ts +2 -2
  85. package/src/audit-escalation.ts +2 -1
  86. package/src/auditor-soul.ts +3 -1
  87. package/src/book-topology-migration-placement.ts +5 -16
  88. package/src/book-topology-migrators-t11.ts +16 -15
  89. package/src/book-topology-mixed-volume-migrators.ts +3 -6
  90. package/src/book-topology-record-class-migrators.ts +7 -10
  91. package/src/book-topology-runs-migrator.ts +4 -3
  92. package/src/collector-config.ts +7 -9
  93. package/src/compliance-transport.ts +2 -1
  94. package/src/countersign-contracts.ts +2 -1
  95. package/src/diarist-contracts.ts +3 -2
  96. package/src/doctor-contracts.ts +3 -1
  97. package/src/doctor-evidence.ts +8 -7
  98. package/src/doctor-role.ts +4 -2
  99. package/src/dossier-resolution.ts +2 -4
  100. package/src/engine-detour-tool.ts +0 -2
  101. package/src/engine-detour-usage.ts +2 -4
  102. package/src/external-host-turn-loop.ts +3 -1
  103. package/src/factory-board.ts +1 -8
  104. package/src/gatekeeper-role.ts +2 -10
  105. package/src/gleaner-left-contracts.ts +3 -1
  106. package/src/headless-host/description.ts +15 -18
  107. package/src/headless-host/role-turn-host.ts +10 -9
  108. package/src/host-session-record.ts +4 -2
  109. package/src/inspector-contracts.ts +2 -1
  110. package/src/ledger-session-read.ts +2 -5
  111. package/src/merger-contracts.ts +10 -9
  112. package/src/navigator-attendance.ts +10 -12
  113. package/src/navigator-invocation-identity.ts +3 -2
  114. package/src/navigator-public-session.ts +4 -6
  115. package/src/navigator-session-contracts.ts +8 -11
  116. package/src/navigator-work-base.ts +5 -8
  117. package/src/navigator-work-context.ts +2 -1
  118. package/src/notary-contracts.ts +4 -6
  119. package/src/oauth-keepalive.ts +5 -18
  120. package/src/package-contracts/auditor-output.ts +2 -4
  121. package/src/package-contracts/fixer-packet.ts +4 -6
  122. package/src/package-contracts/gatekeeper-output.ts +2 -4
  123. package/src/package-contracts/judge-output.ts +0 -1
  124. package/src/package-contracts/navigator-output.ts +8 -8
  125. package/src/package-contracts/terminating-infrastructure.ts +6 -20
  126. package/src/package-contracts/terminating-tools.ts +8 -12
  127. package/src/pi/adapter.ts +0 -1
  128. package/src/pi/role-turn-host.ts +0 -1
  129. package/src/public-cli/analyst-run.ts +4 -2
  130. package/src/public-cli/auto-resume.ts +4 -11
  131. package/src/public-cli/cli.ts +10 -10
  132. package/src/public-cli/config.ts +8 -27
  133. package/src/public-cli/countersign-run.ts +2 -4
  134. package/src/public-cli/host-providers.ts +10 -27
  135. package/src/public-cli/instruction-seat-run.ts +5 -3
  136. package/src/public-cli/invocation.ts +11 -10
  137. package/src/public-cli/post-admission.ts +5 -3
  138. package/src/public-cli/run-lifecycle.ts +20 -41
  139. package/src/public-cli/settlement.ts +11 -33
  140. package/src/public-role-summons.ts +4 -3
  141. package/src/receipt-delivery-policy.ts +1 -4
  142. package/src/reviewer-role.ts +0 -1
  143. package/src/role-envelope.ts +5 -3
  144. package/src/role-run-placement.ts +4 -10
  145. package/src/role-run-relocation.ts +13 -23
  146. package/src/role-runtime.ts +9 -15
  147. package/src/run-terminal-artifacts.ts +2 -16
  148. package/src/run-ticket-number.ts +4 -10
  149. package/src/session-assistant-usage.ts +3 -1
  150. package/src/session-dialogue.ts +1 -4
  151. package/src/session-identity.ts +0 -1
  152. package/src/sitian-reader.ts +2 -4
  153. package/src/submission-correctable-error.ts +3 -1
  154. package/src/submission-errors.ts +2 -1
  155. package/src/submission-gate.ts +3 -1
  156. package/src/submission-ledger.ts +5 -6
  157. package/src/ticket-provenance-contracts.ts +1 -4
  158. package/src/ticket-provenance.ts +3 -1
  159. package/src/ticket-snapshot.ts +2 -4
  160. package/src/ticket-trajectory.ts +1 -8
  161. package/src/typed-provider-http.ts +5 -15
  162. package/src/unknown-value.ts +34 -0
  163. package/src/user-dialogue-stdin.ts +3 -1
  164. package/src/worker-role.ts +2 -5
  165. package/src/worker-submission-gates.ts +5 -7
@@ -43,13 +43,14 @@ import { recordRunStart } from "../host-session-record.js";
43
43
  import { attemptProducedFreshSubmission, classifyPostAdmissionFailure, controlledFailureInputFromResolution, exitCodeForTerminalOutcome, explicitInternalKnownFailureClassificationInput, formatCliDiagnostic, formatErrorCauseDetail, formatTerminalResult, inspectJudgeSession, isLawfulTypedTerminalOutcome, presentFailureTerminal, publishedFailureErrorPath, presentStructuralRejection, resolveAuditedRunnerFailureResolution, resolveControlledFailureResumeObservation, settleFailureTerminalResult, settleHostEndedNoReceipt, attachRecordedSubmissions, rewritePublishedFailureErrorPath, } from "./settlement.js";
44
44
  import {} from "./terminal.js";
45
45
  import { ensureRealArtifactsDirectory, persistReturnedRunState, runWithAutoResumeLoop, TurnDispatchedFailure, writeHardenedArtifactFile, } from "./auto-resume.js";
46
+ import { isRecord, errorText } from "../unknown-value.js";
46
47
  function projectRelocatedTurnIdentity(request, result, admitted, relocation) {
47
48
  const rewrite = (value) => rewriteRunDirectoryPathValue(value, relocation.oldRunDirectory, relocation.newRunDirectory);
48
49
  const mutableRequest = request;
49
50
  mutableRequest.runDirectory = admitted.runDirectory;
50
51
  mutableRequest.principal = admitted.principal;
51
52
  const activation = mutableRequest.activation;
52
- if (activation !== null && typeof activation === "object" && !Array.isArray(activation)) {
53
+ if (isRecord(activation)) {
53
54
  for (const field of ["taskPath", "packetPath", "prerequisitesPath", "inputPath", "requestManifestPath"]) {
54
55
  const record = activation;
55
56
  if (field in record)
@@ -352,7 +353,7 @@ export async function dispatchPostAdmissionTurn(input) {
352
353
  continue;
353
354
  }
354
355
  const payload = row.accepted;
355
- if (payload === null || typeof payload !== "object" || Array.isArray(payload))
356
+ if (!isRecord(payload))
356
357
  continue;
357
358
  ticketNumber = readDeclaredTicketNumber(payload.ticketNumber);
358
359
  if (ticketNumber !== undefined)
@@ -1167,7 +1168,7 @@ async function presentResumeFailurePointer(io, thrown, publish) {
1167
1168
  cause.thrownCause = formatErrorCauseDetail(thrown.cause);
1168
1169
  }
1169
1170
  presentStructuralRejection({
1170
- message: thrown instanceof Error ? thrown.message : String(thrown),
1171
+ message: errorText(thrown),
1171
1172
  cause,
1172
1173
  }, io);
1173
1174
  }
@@ -18,6 +18,7 @@ import { rewriteAdmittedRoleRunPage, rewriteRunDirectoryPathValue, } from "../ro
18
18
  import { appendEngineSessionMaterial, engineSessionMaterialFromOptions, pickEngineAxis, } from "../package-resources/engine-material.js";
19
19
  import { packagedResumeSourcePath, packagedRoleMetadata, } from "../packaged-role-registry.js";
20
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
  }
@@ -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))
@@ -3,6 +3,7 @@ import { existsSync } from "node:fs";
3
3
  import { realpath } from "node:fs/promises";
4
4
  import { join } from "node:path";
5
5
  import { promisify } from "node:util";
6
+ import { isRecord, errorText } from "./unknown-value.js";
6
7
  const AK_ROLE_PACKAGE_ROOT_ENV = "AK_ROLE_PACKAGE_ROOT";
7
8
  const execFileAsync = promisify(execFile);
8
9
  function createCapturingIo() {
@@ -291,7 +292,7 @@ async function summonParallelReviewerLenses(options) {
291
292
  if (error instanceof AggregateError) {
292
293
  return [error.message, ...error.errors.map(describeFailure)].join("\n");
293
294
  }
294
- return error instanceof Error ? error.message : String(error);
295
+ return errorText(error);
295
296
  };
296
297
  const failedResult = (error) => ({
297
298
  exitCode: 1,
@@ -472,7 +473,7 @@ async function summonGateOfficer(options) {
472
473
  const correlationId = parentRunId;
473
474
  const { isSafePositiveTicketNumber, readBoardTicketNumber } = await import("./run-ticket-number.js");
474
475
  const parentTicket = await readBoardTicketNumber(options.sourceRunDirectory);
475
- const submittedTicket = options.submission !== null && typeof options.submission === "object" && !Array.isArray(options.submission) ? options.submission.ticketNumber : void 0;
476
+ const submittedTicket = isRecord(options.submission) ? options.submission.ticketNumber : void 0;
476
477
  const courtTicket = isSafePositiveTicketNumber(submittedTicket) ? submittedTicket : parentTicket;
477
478
  const instruction = options.reask ?? gateReviewInstruction ?? "";
478
479
  return summonPublicRole({
@@ -1,8 +1,6 @@
1
+ import { isRecord } from "./unknown-value.js";
1
2
  const RECEIPT_DELIVERY_TURN_LIMIT = 2;
2
3
  const NO_RECEIPT_LIFECYCLE_ENTRY_TYPE = "ak-no-receipt-lifecycle";
3
- function isRecord(value) {
4
- return typeof value === "object" && value !== null && !Array.isArray(value);
5
- }
6
4
  function parseNoReceiptLifecycleFacts(input) {
7
5
  if (!isRecord(input) || typeof input.terminalToolCalled !== "boolean" || input.deliveryTurns !== RECEIPT_DELIVERY_TURN_LIMIT || input.sessionCompletion !== "settled-without-accepted-receipt" || input.acceptedReceipt !== false || typeof input.runPointer !== "string" || input.runPointer.trim() === "" || typeof input.attemptPointer !== "string" || input.attemptPointer.trim() === "" || !Array.isArray(input.rejectedReceipts) || !input.rejectedReceipts.every((item) => isRecord(item) && typeof item.reason === "string")) {
8
6
  throw new TypeError("malformed no-receipt lifecycle facts");
@@ -5,9 +5,7 @@ import {
5
5
  ensureRealDirectoryTree
6
6
  } from "./activation-ledger-topology.js";
7
7
  import { requireSafePositiveTicketNumber } from "./run-ticket-number.js";
8
- function isMissingPathError(error) {
9
- return error instanceof Error && "code" in error && error.code === "ENOENT";
10
- }
8
+ import { isEnoent } from "./unknown-value.js";
11
9
  async function listBookRunDirectories(bookDir) {
12
10
  const out = [];
13
11
  const seen = /* @__PURE__ */ new Set();
@@ -16,7 +14,7 @@ async function listBookRunDirectories(bookDir) {
16
14
  try {
17
15
  entries = await readdir(runsDir, { withFileTypes: true });
18
16
  } catch (error) {
19
- if (isMissingPathError(error)) return;
17
+ if (isEnoent(error)) return;
20
18
  throw error;
21
19
  }
22
20
  for (const entry of entries) {
@@ -32,7 +30,7 @@ async function listBookRunDirectories(bookDir) {
32
30
  try {
33
31
  subjects = await readdir(bookDir, { withFileTypes: true });
34
32
  } catch (error) {
35
- if (isMissingPathError(error)) return out.sort();
33
+ if (isEnoent(error)) return out.sort();
36
34
  throw error;
37
35
  }
38
36
  for (const subject of subjects) {
@@ -10,6 +10,7 @@ import { existsSync } from "node:fs";
10
10
  import { readdir, readFile, writeFile } from "node:fs/promises";
11
11
  import { join, sep } from "node:path";
12
12
  import { AUDITOR_PARENT_ATTEMPT_BINDING_ENTRY_TYPE } from "./compliance-transport.js";
13
+ import { isRecord, isEnoent } from "./unknown-value.js";
13
14
  const ADMITTED_PAGE_FIELDS = [
14
15
  "runDirectory",
15
16
  "admittedRequestPath",
@@ -39,11 +40,6 @@ const OFFICER_POINTER_FIELDS = ["sessionFile", "runDirectory"];
39
40
  const SITIAN_RECORD_FIELDS = ["sessionParent"];
40
41
  const SESSION_HEADER_FIELDS = ["parentSession"];
41
42
  const BINDING_PARENT_FIELDS = ["sessionFile"];
42
- function isEnoent(error) {
43
- return (error instanceof Error &&
44
- "code" in error &&
45
- error.code === "ENOENT");
46
- }
47
43
  /** Rewrite one path value that points at or under oldRunDirectory. */
48
44
  export function rewriteRunDirectoryPathValue(value, oldRunDirectory, newRunDirectory) {
49
45
  if (typeof value !== "string")
@@ -111,18 +107,15 @@ function collectRewrites(input) {
111
107
  }
112
108
  return out;
113
109
  }
114
- function isPlainObject(value) {
115
- return value !== null && typeof value === "object" && !Array.isArray(value);
116
- }
117
110
  /** Typed notary/source-run locator: only runDirectory is a path. */
118
111
  function rewriteSourceRunLocator(value, rewrites) {
119
- if (!isPlainObject(value))
112
+ if (!isRecord(value))
120
113
  return;
121
114
  rewriteRunDirectoryPathFieldsAgainstRewrites(value, SOURCE_RUN_LOCATOR_FIELDS, rewrites);
122
115
  }
123
116
  /** Same-ticket summons materials: typed source-run + frozen attachment pointers. */
124
117
  function rewriteSummonsMaterials(value, rewrites) {
125
- if (!isPlainObject(value))
118
+ if (!isRecord(value))
126
119
  return;
127
120
  rewriteRunDirectoryPathFieldsAgainstRewrites(value, SUMMONS_PATH_FIELDS, rewrites);
128
121
  rewriteSourceRunLocator(value.sourceRun, rewrites);
@@ -137,12 +130,12 @@ export function rewriteAdmittedRoleRunPage(page, rewrites) {
137
130
  rewriteSourceRunLocator(page.sourceRun, rewrites);
138
131
  if (Array.isArray(page.attachments)) {
139
132
  for (const attachment of page.attachments) {
140
- if (isPlainObject(attachment)) {
133
+ if (isRecord(attachment)) {
141
134
  rewriteRunDirectoryPathFieldsAgainstRewrites(attachment, ["frozenPath"], rewrites);
142
135
  }
143
136
  }
144
137
  }
145
- if (isPlainObject(page.principal)) {
138
+ if (isRecord(page.principal)) {
146
139
  rewriteRunDirectoryPathFieldsAgainstRewrites(page.principal, ["sessionDirectory", "sessionFile"], rewrites);
147
140
  }
148
141
  }
@@ -150,7 +143,7 @@ async function rewriteOfficerPointerFile(path, rewrites) {
150
143
  if (!existsSync(path))
151
144
  return;
152
145
  const page = JSON.parse(await readFile(path, "utf8"));
153
- if (!isPlainObject(page))
146
+ if (!isRecord(page))
154
147
  return;
155
148
  // Only the typed direct-officer pointer shape — never arbitrary .pointer.json.
156
149
  if (page.kind !== "direct-officer-run-pointer")
@@ -190,7 +183,7 @@ async function rewriteSitianRecordsJsonl(path, rewrites) {
190
183
  out.push(line);
191
184
  continue;
192
185
  }
193
- if (!isPlainObject(parsed)) {
186
+ if (!isRecord(parsed)) {
194
187
  out.push(line);
195
188
  continue;
196
189
  }
@@ -241,7 +234,7 @@ async function rewriteSessionTranscriptBindings(path, rewrites) {
241
234
  out.push(line);
242
235
  continue;
243
236
  }
244
- if (!isPlainObject(parsed)) {
237
+ if (!isRecord(parsed)) {
245
238
  out.push(line);
246
239
  continue;
247
240
  }
@@ -254,8 +247,8 @@ async function rewriteSessionTranscriptBindings(path, rewrites) {
254
247
  }
255
248
  else if (parsed.type === "custom" &&
256
249
  parsed.customType === AUDITOR_PARENT_ATTEMPT_BINDING_ENTRY_TYPE &&
257
- isPlainObject(parsed.data) &&
258
- isPlainObject(parsed.data.parent)) {
250
+ isRecord(parsed.data) &&
251
+ isRecord(parsed.data.parent)) {
259
252
  const parent = parsed.data.parent;
260
253
  const before = parent.sessionFile;
261
254
  rewriteRunDirectoryPathFieldsAgainstRewrites(parent, BINDING_PARENT_FIELDS, rewrites);
@@ -343,11 +336,11 @@ export async function rewriteRoleRunDurablePages(input) {
343
336
  const page = JSON.parse(await readFile(statePath, "utf8"));
344
337
  const before = JSON.stringify(page);
345
338
  rewriteRunDirectoryPathFieldsAgainstRewrites(page, RUN_STATE_PAGE_FIELDS, rewrites);
346
- if (isPlainObject(page.principal)) {
339
+ if (isRecord(page.principal)) {
347
340
  rewriteRunDirectoryPathFieldsAgainstRewrites(page.principal, ["sessionDirectory", "sessionFile"], rewrites);
348
341
  }
349
342
  // Open court summons: source-run locators + frozen attachment path pointers.
350
- if (isPlainObject(page.currentCourt)) {
343
+ if (isRecord(page.currentCourt)) {
351
344
  rewriteSummonsMaterials(page.currentCourt.summons, rewrites);
352
345
  }
353
346
  if (JSON.stringify(page) !== before) {
@@ -9,6 +9,7 @@
9
9
  import { readdir, readFile } from "node:fs/promises";
10
10
  import { basename, dirname, join } from "node:path";
11
11
  import { roleRunArtifactsDirectory } from "./role-run-placement.js";
12
+ import { isRecord, errorText, isMissingPathError } from "./unknown-value.js";
12
13
  export const RUN_TERMINAL_ARTIFACT_FILES = [
13
14
  "report.json",
14
15
  "error.json",
@@ -26,17 +27,6 @@ export const RUN_TERMINAL_ERROR_FALLBACK_RELATIVE_PATHS = [
26
27
  ];
27
28
  /** Unique open-ended failure names: error.<uuid>.json (publisher stem + uuid). */
28
29
  const UNIQUE_ERROR_FALLBACK_NAME = /^error\.[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\.json$/i;
29
- function isMissingPathError(error) {
30
- return (error instanceof Error
31
- && "code" in error
32
- && (error.code === "ENOENT" || error.code === "ENOTDIR"));
33
- }
34
- function errorText(error) {
35
- return error instanceof Error ? error.message : String(error);
36
- }
37
- function isRecord(value) {
38
- return typeof value === "object" && value !== null && !Array.isArray(value);
39
- }
40
30
  /**
41
31
  * Minimum producer-owned face shared by settlement terminal artifacts
42
32
  * (report / error / audit-incomplete). Consumer-driven: enough to identify a
@@ -1,9 +1,7 @@
1
1
  import { readFile } from "node:fs/promises";
2
2
  import { join } from "node:path";
3
+ import { isEnoent, isRecord } from "./unknown-value.js";
3
4
  const MIGRATION_TICKET_DERIVATION_PAGE = "migration-ticket-derivation.json";
4
- function isEnoent(error) {
5
- return error instanceof Error && "code" in error && error.code === "ENOENT";
6
- }
7
5
  function isSafePositiveTicketNumber(value) {
8
6
  return typeof value === "number" && Number.isSafeInteger(value) && value >= 1;
9
7
  }
@@ -30,7 +28,7 @@ function ticketFromRecord(record) {
30
28
  async function readJsonObject(path) {
31
29
  try {
32
30
  const raw = JSON.parse(await readFile(path, "utf8"));
33
- if (raw === null || typeof raw !== "object" || Array.isArray(raw)) {
31
+ if (!isRecord(raw)) {
34
32
  return void 0;
35
33
  }
36
34
  return raw;
@@ -1,4 +1,5 @@
1
1
  import { join } from "node:path";
2
+ import { errorText } from "./unknown-value.js";
2
3
  export async function readAssistantUsageFromSessionFile(sessionFile) {
3
4
  const { readFile } = await import("node:fs/promises");
4
5
  let text;
@@ -19,7 +20,7 @@ export async function readAssistantUsageFromSessionFile(sessionFile) {
19
20
  .map((line) => JSON.parse(line));
20
21
  }
21
22
  catch (error) {
22
- throw new Error(`session usage parse failed (${sessionFile}): ${error instanceof Error ? error.message : String(error)}`, { cause: error });
23
+ throw new Error(`session usage parse failed (${sessionFile}): ${errorText(error)}`, { cause: error });
23
24
  }
24
25
  let total = 0;
25
26
  let input = 0;
@@ -1,17 +1,4 @@
1
- /**
2
- * 对话事实适配(ADR 0075 `dialogue-only` / `no-tool-output` / `speaker-required`)。
3
- *
4
- * 「对话」=人类输入内容 + 助手回话内容,由各宿主的**结构化会话事件**适配而来。
5
- * 排除按来源、不按正文:说话人自己写下的文字一律原样保留,其中引用了 ADR 段落
6
- * 或工具结果也不删(#901 Out of Scope「不做正文过滤」)。
7
- *
8
- * 不入录的是工具结果载荷、附件记录与注入块——它们是独立的机器事件,不是谁说的话。
9
- *
10
- * 适配规则按宿主并列,不硬套某一宿主的类型名;一行产出 0..n 条对话事实。
11
- */
12
- function isRecord(value) {
13
- return typeof value === "object" && value !== null && !Array.isArray(value);
14
- }
1
+ import { isRecord } from "./unknown-value.js";
15
2
  /**
16
3
  * 原生 id:行级或消息体级主键的单一实现(bound 解析与落盘共用)。
17
4
  * Pi/CC:行上 `uuid`/`id`;Codex:`response_item.payload.id`(或 `message.id`)。
@@ -1,8 +1,6 @@
1
1
  import { existsSync } from "node:fs";
2
2
  import { readFile } from "node:fs/promises";
3
- function isRecord(value) {
4
- return typeof value === "object" && value !== null && !Array.isArray(value);
5
- }
3
+ import { isRecord, errorText } from "./unknown-value.js";
6
4
  async function readSitianRecords(recordFile) {
7
5
  if (!existsSync(recordFile)) {
8
6
  return { records: [], diagnostics: [] };
@@ -32,7 +30,7 @@ async function readSitianRecords(recordFile) {
32
30
  kind: "malformed",
33
31
  line: index + 1,
34
32
  raw: line,
35
- error: error instanceof Error ? error.message : String(error)
33
+ error: errorText(error)
36
34
  });
37
35
  }
38
36
  }
@@ -1,4 +1,5 @@
1
1
  import { GatekeeperDecisionError, ParentQueueReaskError, WorkerCommitReminderError, WorkerPrefixReminderError, WorkerUnfinishedReasonReminderError, } from "./submission-errors.js";
2
+ import { errorText } from "./unknown-value.js";
2
3
  /** Shared, unforgeable identity for submission errors that the same session may correct. */
3
4
  const correctableSubmissionErrorBrand = Symbol("ak-roles.correctable-submission-error");
4
5
  export class CorrectableSubmissionError extends Error {
@@ -25,7 +26,7 @@ export function isCorrectableExecuteError(error) {
25
26
  * Consumed by the ACP envelope tool catch; host adapters wrap transport shape only.
26
27
  */
27
28
  export function projectCorrectableExecuteRejection(error) {
28
- const diagnostic = error instanceof Error ? error.message : String(error);
29
+ const diagnostic = errorText(error);
29
30
  if (error instanceof GatekeeperDecisionError) {
30
31
  return { diagnostic, details: { ...error.result } };
31
32
  }
@@ -1,4 +1,5 @@
1
1
  import { readableGateItem } from "./readable-gate-item.js";
2
+ import { isRecord } from "./unknown-value.js";
2
3
  /**
3
4
  * Tool-result text the parent model sees (#753 / #750 evidence).
4
5
  * continue | escalate → officer receipt verbatim (JSON when structured).
@@ -61,7 +62,7 @@ export function unreadableDiscriminatorNotice(field, received) {
61
62
  }
62
63
  /** The received discriminator only — never the rest of the receipt. */
63
64
  export function receivedDiscriminator(receipt, field) {
64
- if (receipt === null || typeof receipt !== "object" || Array.isArray(receipt))
65
+ if (!isRecord(receipt))
65
66
  return undefined;
66
67
  if (!Object.hasOwn(receipt, field))
67
68
  return undefined;
@@ -10,7 +10,7 @@ export function latestQueueStatus(terminal) {
10
10
  if (outcome.kind !== "accepted")
11
11
  return undefined;
12
12
  const latest = outcome.payloads?.[outcome.payloads.length - 1];
13
- if (latest !== null && typeof latest === "object" && !Array.isArray(latest)) {
13
+ if (isRecord(latest)) {
14
14
  const status = latest.status;
15
15
  if (typeof status === "string" && status.trim() !== "")
16
16
  return status;
@@ -29,6 +29,7 @@ export function latestQueuePayload(terminal) {
29
29
  return payloads.length === 0 ? undefined : payloads[payloads.length - 1];
30
30
  }
31
31
  import { sessionFileFromPublicSummon } from "./session-assistant-usage.js";
32
+ import { isRecord } from "./unknown-value.js";
32
33
  /**
33
34
  * Shared-envelope default officer summon (ADR 0018).
34
35
  * Role modules must not own this drive seam — only project results.
@@ -7,6 +7,7 @@ import { findRunDirectoryById } from "./public-cli/run-lifecycle.js";
7
7
  import { isCorrectableExecuteError } from "./submission-correctable-error.js";
8
8
  import { failOnInfrastructureFailureDeclaration, infrastructureFailureDiagnostic } from "./package-contracts/terminating-infrastructure.js";
9
9
  import { REVIEW_SUBMISSION_OUTPUT_TOOL_NAME } from "./review-submission.js";
10
+ import { isRecord, errorText } from "./unknown-value.js";
10
11
  /**
11
12
  * Admitted run identity for the ledger subject.
12
13
  * Prefer AK_ROLE_RUN_DIR via sole runDirectory→runId parser (public-CLI correlation);
@@ -464,9 +465,7 @@ export function createSubmissionLedgerHost(host, outputTools, failInfrastructure
464
465
  // host-failure seam. Tool identity comes from the registry map.
465
466
  const reviewEscalate = tool.name === REVIEW_SUBMISSION_OUTPUT_TOOL_NAME
466
467
  && infrastructureFailureDiagnostic(params) !== undefined
467
- && params !== null
468
- && typeof params === "object"
469
- && !Array.isArray(params)
468
+ && isRecord(params)
470
469
  && params.status === "escalate";
471
470
  if (!reviewEscalate) {
472
471
  failOnInfrastructureFailureDeclaration(params, {
@@ -485,7 +484,7 @@ export function createSubmissionLedgerHost(host, outputTools, failInfrastructure
485
484
  toolCallId,
486
485
  outcome: "correctable-rejection",
487
486
  code: "typed-bounce",
488
- diagnostic: error instanceof Error ? error.message : String(error),
487
+ diagnostic: errorText(error),
489
488
  role,
490
489
  accepted: params,
491
490
  });
@@ -497,7 +496,7 @@ export function createSubmissionLedgerHost(host, outputTools, failInfrastructure
497
496
  attemptId,
498
497
  toolCallId,
499
498
  outcome: "infrastructure",
500
- diagnostic: error instanceof Error ? error.message : String(error),
499
+ diagnostic: errorText(error),
501
500
  role,
502
501
  accepted: params,
503
502
  });