@akagilnc/pi-workflow-roles 0.1.3565 → 0.1.3621

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 (142) hide show
  1. package/README.md +4 -1
  2. package/README.zh-CN.md +1 -1
  3. package/dist/acp-host/production-host.js +18477 -8099
  4. package/dist/analyst-gate-cycles-read.js +387 -0
  5. package/dist/archivist-record-entry.js +22 -1
  6. package/dist/audit-escalation.js +6 -0
  7. package/dist/auditor-soul.js +74 -0
  8. package/dist/collector-config.js +86 -0
  9. package/dist/collector-evidence.js +316 -0
  10. package/dist/collector-github.js +527 -0
  11. package/dist/collector-ledger.js +853 -0
  12. package/dist/collector-tool-schemas.js +33 -0
  13. package/dist/compliance-transport.js +104 -52
  14. package/dist/diarist-contracts.js +72 -0
  15. package/dist/diarist-mechanical.js +411 -0
  16. package/dist/diarist-ticket-resolution.js +177 -0
  17. package/dist/diarist.js +311 -0
  18. package/dist/doctor-auditor.js +25 -0
  19. package/dist/doctor-contracts.js +2 -0
  20. package/dist/doctor-evidence.js +142 -0
  21. package/dist/gatekeeper-role.js +104 -81
  22. package/dist/host-transition-prior-native.js +78 -0
  23. package/dist/institutional-resolution.js +1 -95
  24. package/dist/judge-auditor.js +26 -0
  25. package/dist/ledger-session-read.js +227 -0
  26. package/dist/merger-git-state.js +78 -0
  27. package/dist/navigator-attendance.js +15 -7
  28. package/dist/navigator-public-session.js +170 -0
  29. package/dist/navigator-session-contracts.js +36 -40
  30. package/dist/notary-source-run.js +122 -0
  31. package/dist/package-contracts/auditor-output.js +66 -0
  32. package/dist/package-contracts/evidence-child-output.js +34 -0
  33. package/dist/package-contracts/judge-output.js +2 -0
  34. package/dist/package-contracts/terminating-tools.js +44 -3
  35. package/dist/package-resources/method-skill.js +254 -0
  36. package/dist/packaged-role-registry.js +56 -0
  37. package/dist/pi/durable-principal.js +61 -0
  38. package/dist/pi/in-process-session.js +25 -6
  39. package/dist/pi/known-failure.js +52 -0
  40. package/dist/pi/role-turn-host.js +430 -0
  41. package/dist/public-cli/auto-resume.js +414 -0
  42. package/dist/public-cli/cli-errors.js +8 -0
  43. package/dist/public-cli/cli-io.js +1 -0
  44. package/dist/public-cli/command-renderer.js +5 -0
  45. package/dist/public-cli/doctor-run.js +84 -0
  46. package/dist/public-cli/inspector-run.js +136 -0
  47. package/dist/public-cli/instruction-seat-run.js +256 -0
  48. package/dist/public-cli/invocation.js +2225 -0
  49. package/dist/public-cli/judge-run.js +118 -0
  50. package/dist/public-cli/load-production-acp-host.js +40 -0
  51. package/dist/public-cli/main.js +1511 -1124
  52. package/dist/public-cli/notary-run.js +161 -0
  53. package/dist/public-cli/option-definitions.js +1192 -0
  54. package/dist/public-cli/post-admission.js +667 -0
  55. package/dist/public-cli/public-run-credentials.js +49 -0
  56. package/dist/public-cli/registry.js +8 -2
  57. package/dist/public-cli/reviewer-dispatch-rejection.js +77 -0
  58. package/dist/public-cli/run-lifecycle.js +1344 -0
  59. package/dist/public-cli/seat-ticket-binding.js +113 -0
  60. package/dist/public-cli/settlement.js +3441 -0
  61. package/dist/public-cli/terminal.js +135 -0
  62. package/dist/public-cli/turn-request.js +25 -0
  63. package/dist/public-role-summons.js +301 -0
  64. package/dist/receipt-delivery-policy.js +10 -0
  65. package/dist/reviewer-child-executor.js +80 -8
  66. package/dist/reviewer-execution-ledger.js +2 -1
  67. package/dist/run-terminal-artifacts.js +195 -0
  68. package/dist/run-ticket-number.js +40 -0
  69. package/dist/session-assistant-usage.js +107 -0
  70. package/dist/shape-unreadable-failure.js +34 -0
  71. package/dist/submission-errors.js +3 -0
  72. package/dist/submission-ledger.js +388 -0
  73. package/dist/ticket-provenance-contracts.js +115 -0
  74. package/dist/ticket-provenance.js +340 -0
  75. package/extensions/role-runtime.ts +8 -0
  76. package/package.json +1 -1
  77. package/resources/diarist-collect.md +6 -10
  78. package/scripts/build-package.mjs +2 -1
  79. package/souls/diarist.md +9 -0
  80. package/souls/doctor-auditor.md +1 -0
  81. package/souls/evidence-child.md +1 -0
  82. package/src/acp-host/production-host.ts +4 -0
  83. package/src/acp-host/role-envelope.ts +4 -3
  84. package/src/acp-host/role-turn-host.ts +9 -1
  85. package/src/analyst-gate-cycles-read.ts +37 -2
  86. package/src/archivist-record-entry.ts +45 -1
  87. package/src/audit-escalation.ts +17 -0
  88. package/src/auditor-role.ts +22 -0
  89. package/src/auditor-soul.ts +42 -0
  90. package/src/compliance-transport.ts +177 -66
  91. package/src/diarist-contracts.ts +88 -0
  92. package/src/diarist-role.ts +60 -0
  93. package/src/diarist.ts +253 -179
  94. package/src/doctor-auditor.ts +10 -14
  95. package/src/doctor-contracts.ts +1 -0
  96. package/src/doctor-role.ts +2 -2
  97. package/src/evidence-child-role.ts +22 -0
  98. package/src/gatekeeper-pass-envelope.ts +109 -0
  99. package/src/gatekeeper-role.ts +145 -104
  100. package/src/host-contracts.ts +15 -2
  101. package/src/institutional-resolution.ts +8 -163
  102. package/src/judge-auditor.ts +10 -15
  103. package/src/judge-role.ts +8 -0
  104. package/src/navigator-attendance.ts +25 -9
  105. package/src/navigator-public-session.ts +217 -0
  106. package/src/navigator-session-contracts.ts +61 -54
  107. package/src/notary-source-run.ts +3 -1
  108. package/src/package-contracts/auditor-output.ts +82 -0
  109. package/src/package-contracts/evidence-child-output.ts +51 -0
  110. package/src/package-contracts/judge-output.ts +1 -0
  111. package/src/package-contracts/reviewer-output.ts +2 -2
  112. package/src/package-contracts/terminating-tools.ts +53 -3
  113. package/src/packaged-role-registry.ts +63 -0
  114. package/src/pi/adapter.ts +2 -1
  115. package/src/pi/in-process-session.ts +38 -12
  116. package/src/pi/role-turn-host.ts +42 -0
  117. package/src/public-cli/cli.ts +43 -6
  118. package/src/public-cli/countersign-run.ts +9 -129
  119. package/src/public-cli/diarist-run.ts +312 -0
  120. package/src/public-cli/instruction-seat-run.ts +289 -50
  121. package/src/public-cli/invocation.ts +87 -25
  122. package/src/public-cli/option-definitions.ts +79 -0
  123. package/src/public-cli/post-admission.ts +9 -3
  124. package/src/public-cli/registry.ts +7 -1
  125. package/src/public-cli/run-lifecycle.ts +53 -6
  126. package/src/public-cli/settlement.ts +170 -7
  127. package/src/public-cli/terminal.ts +4 -1
  128. package/src/public-role-summons.ts +431 -0
  129. package/src/receipt-delivery-policy.ts +10 -0
  130. package/src/reviewer-agent.ts +1 -1
  131. package/src/reviewer-child-executor.ts +114 -12
  132. package/src/reviewer-execution-ledger.ts +3 -2
  133. package/src/role-runtime.ts +275 -23
  134. package/src/session-assistant-usage.ts +119 -0
  135. package/src/session-opening-materials.ts +1 -1
  136. package/src/shape-unreadable-failure.ts +49 -0
  137. package/src/submission-errors.ts +3 -0
  138. package/src/ticket-provenance-contracts.ts +1 -0
  139. package/src/ticket-provenance.ts +0 -23
  140. package/dist/evidence-child-executor.js +0 -829
  141. package/src/diarist-llm-collector.ts +0 -324
  142. package/src/evidence-child-executor.ts +0 -1140
@@ -34,6 +34,9 @@ export type OptionOwner =
34
34
  | "inspector"
35
35
  | "gatekeeper"
36
36
  | "navigator"
37
+ | "auditor"
38
+ | "evidence-child"
39
+ | "diarist"
37
40
  | "analyst";
38
41
 
39
42
  /**
@@ -422,11 +425,54 @@ const NAVIGATOR_OPTIONS = [
422
425
  bindOwner("navigator", SHARED_ATTACH_SEMANTICS),
423
426
  ] as const satisfies readonly PublicOptionDefinition[];
424
427
 
428
+ const AUDITOR_OPTIONS = [
429
+ bindOwner("auditor", SHARED_PROJECT_SEMANTICS),
430
+ bindOwner("auditor", SHARED_ATTACH_SEMANTICS),
431
+ {
432
+ id: "subject",
433
+ owner: "auditor",
434
+ canonical: "--subject",
435
+ aliases: [],
436
+ valueMetavar: "judge|doctor",
437
+ required: true,
438
+ repeatable: false,
439
+ form: "option",
440
+ description: {
441
+ en: "Required audited subject: judge or doctor (selects judge-auditor.md / doctor-auditor.md).",
442
+ zh: "必填受审对象:judge 或 doctor(装 judge-auditor.md / doctor-auditor.md)。",
443
+ },
444
+ },
445
+ {
446
+ id: "source-run",
447
+ owner: "auditor",
448
+ canonical: "--source-run",
449
+ aliases: [],
450
+ valueMetavar: "runId@role|path",
451
+ required: true,
452
+ repeatable: false,
453
+ form: "option",
454
+ description: {
455
+ en: "Required source run locator of the audited subject volume (same input for direct and nested summons).",
456
+ zh: "必填受审卷宗 locator(直调与传召同一输入面)。",
457
+ },
458
+ },
459
+ ] as const satisfies readonly PublicOptionDefinition[];
460
+
461
+ const EVIDENCE_CHILD_OPTIONS = [
462
+ bindOwner("evidence-child", SHARED_PROJECT_SEMANTICS),
463
+ bindOwner("evidence-child", SHARED_ATTACH_SEMANTICS),
464
+ ] as const satisfies readonly PublicOptionDefinition[];
465
+
425
466
  const COUNTERSIGN_OPTIONS = [
426
467
  bindOwner("countersign", SHARED_PROJECT_SEMANTICS),
427
468
  bindOwner("countersign", SHARED_ATTACH_SEMANTICS),
428
469
  ] as const satisfies readonly PublicOptionDefinition[];
429
470
 
471
+ const DIARIST_OPTIONS = [
472
+ bindOwner("diarist", SHARED_PROJECT_SEMANTICS),
473
+ bindOwner("diarist", SHARED_ATTACH_SEMANTICS),
474
+ ] as const satisfies readonly PublicOptionDefinition[];
475
+
430
476
  const CODER_OPTIONS = [
431
477
  {
432
478
  id: "phase",
@@ -784,6 +830,9 @@ export const PUBLIC_OPTION_TABLE = {
784
830
  inspector: INSPECTOR_OPTIONS,
785
831
  gatekeeper: GATEKEEPER_OPTIONS,
786
832
  navigator: NAVIGATOR_OPTIONS,
833
+ auditor: AUDITOR_OPTIONS,
834
+ "evidence-child": EVIDENCE_CHILD_OPTIONS,
835
+ diarist: DIARIST_OPTIONS,
787
836
  analyst: ANALYST_OPTIONS,
788
837
  } as const satisfies Record<OptionOwner, readonly PublicOptionDefinition[]>;
789
838
 
@@ -804,6 +853,9 @@ export const PUBLIC_ROLE_OPTION_OWNERS = [
804
853
  "inspector",
805
854
  "gatekeeper",
806
855
  "navigator",
856
+ "auditor",
857
+ "evidence-child",
858
+ "diarist",
807
859
  "analyst",
808
860
  ] as const satisfies readonly PublicRoleOptionOwner[];
809
861
 
@@ -1201,6 +1253,33 @@ const ROLE_COMMAND_HELP = {
1201
1253
  'ak-role navigator "刚完成 coder apply 收敛,下一步?"',
1202
1254
  ],
1203
1255
  },
1256
+ auditor: {
1257
+ command: "auditor",
1258
+ summary: "Direct Auditor (审刑院) compliance audit: pass, revise, or escalate.",
1259
+ usage: ["ak-role auditor --subject <judge|doctor> --source-run <runId@role|path> [options] [instruction]"],
1260
+ examples: [
1261
+ 'ak-role auditor --subject judge --source-run 01abc…@judge --attach ./dossier "审:本 run 是否合规。"',
1262
+ 'ak-role auditor --subject doctor --source-run 01abc…@doctor "审:太医候选是否合规。"',
1263
+ ],
1264
+ },
1265
+ "evidence-child": {
1266
+ command: "evidence-child",
1267
+ summary: "Direct evidence-child fact gathering; submit one report.",
1268
+ usage: ["ak-role evidence-child [options] [instruction]"],
1269
+ examples: [
1270
+ 'ak-role evidence-child "查:本工作树 diff 与票面是否一致。"',
1271
+ ],
1272
+ },
1273
+ diarist: {
1274
+ command: "diarist",
1275
+ summary:
1276
+ "Direct Diarist (起居郎) pass: gather and organize this case's decision basis into its 起居录.",
1277
+ usage: ["ak-role diarist [options] [instruction]"],
1278
+ examples: [
1279
+ 'ak-role diarist "整理 #708 的本案依据。"',
1280
+ 'ak-role diarist --attach ./design.md "补录本轮设计修订。"',
1281
+ ],
1282
+ },
1204
1283
  notary: {
1205
1284
  command: "notary",
1206
1285
  summary: "Direct Notary document check (quote fidelity + ticket alignment); zero prompt/attachment.",
@@ -110,6 +110,12 @@ export type PostAdmissionEnv = {
110
110
  sessionAppender: SessionCustomEntryAppender;
111
111
  autoResumeLimit?: number;
112
112
  createRunId?: () => string;
113
+ /**
114
+ * Parent cancellation for a nested public summon (#675). Every dispatched turn
115
+ * carries it so an aborted parent terminates the nested activation; a CLI
116
+ * process has no parent and leaves it absent.
117
+ */
118
+ signal?: AbortSignal;
113
119
  /**
114
120
  * #724 explicit fresh summons (`ak-role new <role>`): skip same-ticket auto-resume
115
121
  * and mint a new run. Absent on ordinary role commands and on `ak-role resume`.
@@ -302,7 +308,7 @@ export async function dispatchPostAdmissionTurn<
302
308
  piSessionFile: principalCoordinates.sessionFile,
303
309
  })
304
310
  : undefined;
305
- turnRequest = request;
311
+ turnRequest = env.signal === undefined ? request : { ...request, signal: env.signal };
306
312
  if (hostTransition !== undefined) {
307
313
  turnRequest = { ...turnRequest, hostTransition };
308
314
  }
@@ -324,8 +330,8 @@ export async function dispatchPostAdmissionTurn<
324
330
 
325
331
  await markRunRunning(admitted.runDirectory, env.model, effectiveEngine, env.host);
326
332
  await clearTypedProviderHttpObservation(admitted.runDirectory);
327
- // beforeDispatch (e.g. countersign diarist station) runs after running is
328
- // marked — its failures must settle the run, not leave it permanently running.
333
+ // beforeDispatch (seat-owned pre-turn work) runs after running is marked —
334
+ // its failures must settle the run, not leave it permanently running.
329
335
  if (adapters.beforeDispatch !== undefined) {
330
336
  try {
331
337
  await adapters.beforeDispatch(admitted);
@@ -99,13 +99,19 @@ const STARTUP_CANDIDATES: Record<PublicConfigurableSeat, readonly ModelRef[]> =
99
99
  // #620: subordinate officers inherit gatekeeper; no package startup model.
100
100
  notary: [],
101
101
  // #453/#620/#639: gatekeeper callable but no package startup model — caller
102
- // configures it or the institutional resolution applies on the province path.
102
+ // configures it or inherits on the province path.
103
103
  gatekeeper: [],
104
104
  inspector: [],
105
105
  navigator: [
106
106
  { provider: "openai-codex", model: "gpt-5.6-luna", thinking: "medium" },
107
107
  { provider: "xai", model: "grok-4.5", thinking: "high" },
108
108
  ],
109
+ // #675: auditor / evidence-child public seats — no package startup; caller configures.
110
+ auditor: [],
111
+ "evidence-child": [],
112
+ // #708 `diarist-seat-default`: owner-set initial value; changed in the seat
113
+ // table like any other seat. No engine axis, package-default host.
114
+ diarist: [{ provider: "xai", model: "grok-4.5", thinking: "medium" }],
109
115
  };
110
116
 
111
117
  export function publicStartupCandidates(
@@ -44,6 +44,7 @@ import {
44
44
  type AdmittedCoderInvocation,
45
45
  type AdmittedCountersignInvocation,
46
46
  type AdmittedCollectorInvocation,
47
+ type AdmittedDiaristInvocation,
47
48
  type AdmittedDoctorInvocation,
48
49
  type AdmittedInspectorInvocation,
49
50
  type AdmittedNotaryInvocation,
@@ -95,7 +96,10 @@ export type RoleRunRecord = {
95
96
  | "gleaner-left"
96
97
  | "inspector"
97
98
  | "gatekeeper"
98
- | "navigator";
99
+ | "navigator"
100
+ | "auditor"
101
+ | "evidence-child"
102
+ | "diarist";
99
103
  readonly state: RoleRunState;
100
104
  readonly bookKey: string;
101
105
  readonly projectRoot: string;
@@ -348,7 +352,10 @@ async function readRoleRunStateDisk(
348
352
  record.role !== "gleaner-left" &&
349
353
  record.role !== "inspector" &&
350
354
  record.role !== "gatekeeper" &&
351
- record.role !== "navigator"
355
+ record.role !== "navigator" &&
356
+ record.role !== "auditor" &&
357
+ record.role !== "evidence-child" &&
358
+ record.role !== "diarist"
352
359
  ) {
353
360
  return undefined;
354
361
  }
@@ -1444,8 +1451,18 @@ export type LoadedResumableGleanerLeftRun = {
1444
1451
  readonly observation?: TypedHttp429Observation;
1445
1452
  };
1446
1453
 
1454
+ export type LoadedResumableDiaristRun = {
1455
+ readonly admitted: AdmittedDiaristInvocation;
1456
+ readonly run: RoleRunRecord;
1457
+ readonly observation?: TypedHttp429Observation;
1458
+ };
1459
+
1447
1460
  export type LoadedResumableInstructionSeatRun = {
1448
- readonly admitted: AdmittedGatekeeperInvocation | AdmittedNavigatorInvocation;
1461
+ readonly admitted:
1462
+ | AdmittedGatekeeperInvocation
1463
+ | AdmittedNavigatorInvocation
1464
+ | import("./invocation.ts").AdmittedAuditorInvocation
1465
+ | import("./invocation.ts").AdmittedEvidenceChildInvocation;
1449
1466
  readonly run: RoleRunRecord;
1450
1467
  readonly observation?: TypedHttp429Observation;
1451
1468
  };
@@ -1637,7 +1654,7 @@ export async function loadResumableReviewerRun(
1637
1654
 
1638
1655
  /**
1639
1656
  * Load a resumable Countersign run for resume (#599). Ticket binding and
1640
- * attachments restore from the admitted request; diarist does not re-run.
1657
+ * attachments restore from the admitted request.
1641
1658
  */
1642
1659
  export async function loadResumableCountersignRun(
1643
1660
  home: string,
@@ -1667,7 +1684,12 @@ export async function loadResumableInstructionSeatRun(
1667
1684
  authority: DurablePrincipalAuthority,
1668
1685
  ): Promise<LoadedResumableInstructionSeatRun> {
1669
1686
  const loaded = await loadResumableRunRecord(home, runId, authority);
1670
- if (loaded.run.role !== "gatekeeper" && loaded.run.role !== "navigator") {
1687
+ if (
1688
+ loaded.run.role !== "gatekeeper"
1689
+ && loaded.run.role !== "navigator"
1690
+ && loaded.run.role !== "auditor"
1691
+ && loaded.run.role !== "evidence-child"
1692
+ ) {
1671
1693
  throw new CliUsageError(
1672
1694
  `role run ${runId} belongs to ${loaded.run.role}, not an instruction seat`,
1673
1695
  );
@@ -1675,7 +1697,11 @@ export async function loadResumableInstructionSeatRun(
1675
1697
  const admitted = {
1676
1698
  role: loaded.run.role,
1677
1699
  ...resumedBaseAdmitted(loaded),
1678
- } as AdmittedGatekeeperInvocation | AdmittedNavigatorInvocation;
1700
+ } as
1701
+ | AdmittedGatekeeperInvocation
1702
+ | AdmittedNavigatorInvocation
1703
+ | import("./invocation.ts").AdmittedAuditorInvocation
1704
+ | import("./invocation.ts").AdmittedEvidenceChildInvocation;
1679
1705
  return seatLoadedResult(loaded, admitted);
1680
1706
  }
1681
1707
 
@@ -1704,6 +1730,24 @@ export async function loadResumableGleanerLeftRun(
1704
1730
  return seatLoadedResult(loaded, admitted);
1705
1731
  }
1706
1732
 
1733
+ export async function loadResumableDiaristRun(
1734
+ home: string,
1735
+ runId: string,
1736
+ authority: DurablePrincipalAuthority,
1737
+ ): Promise<LoadedResumableDiaristRun> {
1738
+ const loaded = await loadResumableRunRecord(home, runId, authority);
1739
+ if (loaded.run.role !== "diarist") {
1740
+ throw new CliUsageError(
1741
+ `role run ${runId} belongs to ${loaded.run.role}, not diarist`,
1742
+ );
1743
+ }
1744
+ const admitted: AdmittedDiaristInvocation = {
1745
+ role: "diarist",
1746
+ ...resumedBaseAdmitted(loaded),
1747
+ };
1748
+ return seatLoadedResult(loaded, admitted);
1749
+ }
1750
+
1707
1751
  export type LoadedResumableMergerRun = {
1708
1752
  readonly admitted: AdmittedMergerInvocation;
1709
1753
  readonly run: RoleRunRecord;
@@ -1929,6 +1973,9 @@ export async function peekRoleRunRole(
1929
1973
  | "inspector"
1930
1974
  | "gatekeeper"
1931
1975
  | "navigator"
1976
+ | "auditor"
1977
+ | "evidence-child"
1978
+ | "diarist"
1932
1979
  | undefined
1933
1980
  > {
1934
1981
  const runDirectory = await findRunDirectoryById(home, runId);
@@ -24,6 +24,7 @@ import { AUDITOR_SOUL_ROLES } from "../auditor-soul.ts";
24
24
  import { DOCTOR_AUDIT_TOOL_NAME } from "../doctor-auditor.ts";
25
25
  import { JUDGE_AUDIT_TOOL_NAME } from "../judge-auditor.ts";
26
26
  import type { RoleTurnKnownFailure } from "../host-contracts.ts";
27
+ import { stampShapeUnreadableDetails } from "../shape-unreadable-failure.ts";
27
28
  import { knownFailureFromProviderStop } from "../pi/known-failure.ts";
28
29
  import { readReviewerDispatchRejection } from "./reviewer-dispatch-rejection.ts";
29
30
  import {
@@ -98,6 +99,11 @@ import {
98
99
  gleanerLeftDecisiveFacts,
99
100
  validateRecordedGleanerLeftOutput,
100
101
  } from "../gleaner-left-contracts.ts";
102
+ import {
103
+ DIARIST_OUTPUT_TOOL_NAME,
104
+ diaristDecisiveFacts,
105
+ validateRecordedDiaristOutput,
106
+ } from "../diarist-contracts.ts";
101
107
  import {
102
108
  INSPECTOR_OUTPUT_TOOL_NAME,
103
109
  inspectorDecisiveFacts,
@@ -113,6 +119,17 @@ import {
113
119
  navigatorDecisiveFacts,
114
120
  validateRecordedNavigatorOutput,
115
121
  } from "../package-contracts/navigator-output.ts";
122
+ import {
123
+ AUDITOR_OUTPUT_TOOL_NAME,
124
+ auditorDecisiveFacts,
125
+ projectLawfulAuditorOutput,
126
+ validateRecordedAuditorOutput,
127
+ } from "../package-contracts/auditor-output.ts";
128
+ import {
129
+ EVIDENCE_CHILD_OUTPUT_TOOL_NAME,
130
+ evidenceChildDecisiveFacts,
131
+ validateRecordedEvidenceChildOutput,
132
+ } from "../package-contracts/evidence-child-output.ts";
116
133
  import {
117
134
  observePackagedMethodSkillInvocation,
118
135
  type ObservedPackagedMethodSkillInvocation,
@@ -145,6 +162,7 @@ import {
145
162
  type AdmittedJudgeInvocation,
146
163
  type AdmittedMergerInvocation,
147
164
  type AdmittedCountersignInvocation,
165
+ type AdmittedDiaristInvocation,
148
166
  type AdmittedGleanerLeftInvocation,
149
167
  type AdmittedInspectorInvocation,
150
168
  type AdmittedGatekeeperInvocation,
@@ -1217,9 +1235,11 @@ function typedFailedTerminatingToolKnownFailure(
1217
1235
  const diagnostic = isRecord(textPart) ? textPart.text : undefined;
1218
1236
  // Durable details already carry fact + typed evidence from envelope one-shot projection (#475).
1219
1237
  // Do not re-parse retained compliance responses here.
1238
+ // Host infrastructure must NOT map to cause=output — that cause is reserved for
1239
+ // shape-unreadable retained candidates (ADR 0055 / #675 producer→consumer diversion).
1220
1240
  const details = isRecord(message.details) ? message.details : classification.fact;
1221
1241
  return {
1222
- cause: "output",
1242
+ cause: "activation",
1223
1243
  identity: { name: message.toolName, code: message.toolCallId },
1224
1244
  ...(typeof diagnostic === "string" && diagnostic.trim() !== "" ? { diagnostic } : {}),
1225
1245
  details,
@@ -1483,6 +1503,16 @@ function auditNoReceiptDecisiveFact(candidate: object): Record<string, unknown>
1483
1503
  }
1484
1504
  }
1485
1505
 
1506
+ /** Typed unreadable audit leg beside accepted parent candidate (ADR 0055 / #675). */
1507
+ function auditUnreadableDecisiveFact(candidate: object): Record<string, unknown> {
1508
+ const projected = safelyRead(candidate, "auditUnreadable");
1509
+ if (!projected.readable || projected.value === undefined) return {};
1510
+ if (typeof projected.value !== "object" || projected.value === null || Array.isArray(projected.value)) {
1511
+ return { auditUnreadable: projected.value };
1512
+ }
1513
+ return { auditUnreadable: projected.value as Record<string, unknown> };
1514
+ }
1515
+
1486
1516
  /** Countersign terminal projection — escalate keeps decisionGate; continue keeps fix (#572 / ADR 0074). */
1487
1517
  function countersignDecisiveFacts(
1488
1518
  verdict: object,
@@ -1525,6 +1555,7 @@ function judgeDecisiveFacts(
1525
1555
  const facts: Record<string, unknown> = {
1526
1556
  judgeStatus,
1527
1557
  ...auditNoReceiptDecisiveFact(verdict),
1558
+ ...auditUnreadableDecisiveFact(verdict),
1528
1559
  };
1529
1560
  const statusBase = judgeStatus;
1530
1561
  if (statusBase === "continue") {
@@ -1689,7 +1720,10 @@ function collectorDecisiveFacts(
1689
1720
  function doctorDecisiveFacts(output: DoctorOutput): Record<string, unknown> {
1690
1721
  const candidate = output as unknown as object;
1691
1722
  const status = safelyRead(candidate, "status");
1692
- const facts: Record<string, unknown> = { ...auditNoReceiptDecisiveFact(candidate) };
1723
+ const facts: Record<string, unknown> = {
1724
+ ...auditNoReceiptDecisiveFact(candidate),
1725
+ ...auditUnreadableDecisiveFact(candidate),
1726
+ };
1693
1727
  if (status.readable && typeof status.value === "string") facts.doctorStatus = status.value;
1694
1728
  const statusBase =
1695
1729
  status.readable && typeof status.value === "string"
@@ -3360,7 +3394,10 @@ type SeatAcceptedSettlementSpec = {
3360
3394
  | "gleaner-left"
3361
3395
  | "inspector"
3362
3396
  | "gatekeeper"
3363
- | "navigator";
3397
+ | "navigator"
3398
+ | "auditor"
3399
+ | "evidence-child"
3400
+ | "diarist";
3364
3401
  readonly toolName: string;
3365
3402
  readonly nonUsableDiagnostic: string;
3366
3403
  readonly projectAccepted: (
@@ -3387,7 +3424,10 @@ async function settleLawfulSeatAcceptedTerminalResult(
3387
3424
  | AdmittedGleanerLeftInvocation
3388
3425
  | AdmittedInspectorInvocation
3389
3426
  | AdmittedGatekeeperInvocation
3390
- | AdmittedNavigatorInvocation,
3427
+ | AdmittedNavigatorInvocation
3428
+ | import("./invocation.ts").AdmittedAuditorInvocation
3429
+ | import("./invocation.ts").AdmittedEvidenceChildInvocation
3430
+ | AdmittedDiaristInvocation,
3391
3431
  authority: DurablePrincipalAuthority,
3392
3432
  spec: SeatAcceptedSettlementSpec,
3393
3433
  scope?: SettlementCourtScope,
@@ -3428,7 +3468,7 @@ async function settleLawfulSeatAcceptedTerminalResult(
3428
3468
  return settleFailureTerminalResult(admitted, {
3429
3469
  cause: "output",
3430
3470
  diagnostic: residual.diagnostic,
3431
- details: { candidate: residual.candidate, acceptedReceipt: false },
3471
+ details: stampShapeUnreadableDetails(residual.candidate),
3432
3472
  }, authority);
3433
3473
  }
3434
3474
  if (
@@ -3446,7 +3486,7 @@ async function settleLawfulSeatAcceptedTerminalResult(
3446
3486
  return settleFailureTerminalResult(admitted, {
3447
3487
  cause: "output",
3448
3488
  diagnostic: spec.nonUsableDiagnostic,
3449
- details: { candidate: acceptedNonUsable, acceptedReceipt: false },
3489
+ details: stampShapeUnreadableDetails(acceptedNonUsable),
3450
3490
  }, authority);
3451
3491
  }
3452
3492
  return undefined;
@@ -3457,7 +3497,7 @@ async function settleLawfulSeatAcceptedTerminalResult(
3457
3497
  {
3458
3498
  cause: "output",
3459
3499
  diagnostic: spec.nonUsableDiagnostic,
3460
- details: { candidate: roleOutcome.decisiveFacts, acceptedReceipt: false },
3500
+ details: stampShapeUnreadableDetails(roleOutcome.decisiveFacts),
3461
3501
  },
3462
3502
  authority,
3463
3503
  );
@@ -3651,6 +3691,46 @@ export async function trySettleGleanerLeftTerminalResult(
3651
3691
  return settleLawfulGleanerLeftTerminalResult(admitted, authority, scope);
3652
3692
  }
3653
3693
 
3694
+ /** Lawful Diarist accepted outcome (completed 入录选择, #708). */
3695
+ export type LawfulDiaristRoleOutcome = {
3696
+ kind: "accepted";
3697
+ role: "diarist";
3698
+ status: string;
3699
+ decisiveFacts: Readonly<Record<string, unknown>>;
3700
+ };
3701
+
3702
+ async function settleLawfulDiaristTerminalResult(
3703
+ admitted: AdmittedDiaristInvocation,
3704
+ authority: DurablePrincipalAuthority,
3705
+ scope?: SettlementCourtScope,
3706
+ ): Promise<TerminalResult | undefined> {
3707
+ return settleLawfulSeatAcceptedTerminalResult(admitted, authority, {
3708
+ role: "diarist",
3709
+ toolName: DIARIST_OUTPUT_TOOL_NAME,
3710
+ nonUsableDiagnostic: "起居郎回执无显式 completed",
3711
+ tryAcceptDetails: tryAcceptWithValidator(validateRecordedDiaristOutput),
3712
+ projectAccepted: (sealed) => {
3713
+ const output = validateRecordedDiaristOutput(sealed.decisiveFacts);
3714
+ const accepted: LawfulDiaristRoleOutcome = {
3715
+ kind: "accepted",
3716
+ role: "diarist",
3717
+ status: sealed.status,
3718
+ decisiveFacts: diaristDecisiveFacts(output),
3719
+ };
3720
+ return accepted;
3721
+ },
3722
+ }, scope);
3723
+ }
3724
+
3725
+ /** Try to settle a lawful Diarist Terminal; undefined only for genuine absence. */
3726
+ export async function trySettleDiaristTerminalResult(
3727
+ admitted: AdmittedDiaristInvocation,
3728
+ authority: DurablePrincipalAuthority,
3729
+ scope?: SettlementCourtScope,
3730
+ ): Promise<TerminalResult | undefined> {
3731
+ return settleLawfulDiaristTerminalResult(admitted, authority, scope);
3732
+ }
3733
+
3654
3734
  /** Lawful Inspector accepted outcome (pass/bounce/escalate). */
3655
3735
  export type LawfulInspectorRoleOutcome = {
3656
3736
  kind: "accepted";
@@ -3770,6 +3850,89 @@ export async function trySettleNavigatorTerminalResult(
3770
3850
  return settleLawfulNavigatorTerminalResult(admitted, authority, scope);
3771
3851
  }
3772
3852
 
3853
+ /** Lawful Auditor accepted outcome (pass/revise/escalate, #675). */
3854
+ export type LawfulAuditorRoleOutcome = {
3855
+ kind: "accepted";
3856
+ role: "auditor";
3857
+ status: string;
3858
+ decisiveFacts: Readonly<Record<string, unknown>>;
3859
+ };
3860
+
3861
+ async function settleLawfulAuditorTerminalResult(
3862
+ admitted: import("./invocation.ts").AdmittedAuditorInvocation,
3863
+ authority: DurablePrincipalAuthority,
3864
+ scope?: SettlementCourtScope,
3865
+ ): Promise<TerminalResult | undefined> {
3866
+ return settleLawfulSeatAcceptedTerminalResult(admitted, authority, {
3867
+ role: "auditor",
3868
+ toolName: AUDITOR_OUTPUT_TOOL_NAME,
3869
+ nonUsableDiagnostic: "审刑院回执无显式 pass/revise/escalate",
3870
+ // Only pass/revise/escalate are lawful releases. Unreadable mystery status
3871
+ // fails closed with candidate retained for parent ComplianceCandidateUnreadableError.
3872
+ tryAcceptDetails: (details) => projectLawfulAuditorOutput(details) !== undefined,
3873
+ projectAccepted: (sealed) => {
3874
+ const lawful = projectLawfulAuditorOutput(sealed.decisiveFacts);
3875
+ if (lawful === undefined) {
3876
+ throw new Error("auditor projectAccepted requires lawful pass/revise/escalate");
3877
+ }
3878
+ const accepted: LawfulAuditorRoleOutcome = {
3879
+ kind: "accepted",
3880
+ role: "auditor",
3881
+ status: lawful.status,
3882
+ decisiveFacts: auditorDecisiveFacts(lawful),
3883
+ };
3884
+ return accepted;
3885
+ },
3886
+ }, scope);
3887
+ }
3888
+
3889
+ export async function trySettleAuditorTerminalResult(
3890
+ admitted: import("./invocation.ts").AdmittedAuditorInvocation,
3891
+ authority: DurablePrincipalAuthority,
3892
+ scope?: SettlementCourtScope,
3893
+ ): Promise<TerminalResult | undefined> {
3894
+ return settleLawfulAuditorTerminalResult(admitted, authority, scope);
3895
+ }
3896
+
3897
+ /** Lawful Evidence-Child accepted outcome (#675). */
3898
+ export type LawfulEvidenceChildRoleOutcome = {
3899
+ kind: "accepted";
3900
+ role: "evidence-child";
3901
+ status: string;
3902
+ decisiveFacts: Readonly<Record<string, unknown>>;
3903
+ };
3904
+
3905
+ async function settleLawfulEvidenceChildTerminalResult(
3906
+ admitted: import("./invocation.ts").AdmittedEvidenceChildInvocation,
3907
+ authority: DurablePrincipalAuthority,
3908
+ scope?: SettlementCourtScope,
3909
+ ): Promise<TerminalResult | undefined> {
3910
+ return settleLawfulSeatAcceptedTerminalResult(admitted, authority, {
3911
+ role: "evidence-child",
3912
+ toolName: EVIDENCE_CHILD_OUTPUT_TOOL_NAME,
3913
+ nonUsableDiagnostic: "取证回执无报告正文",
3914
+ tryAcceptDetails: tryAcceptWithValidator(validateRecordedEvidenceChildOutput),
3915
+ projectAccepted: (sealed) => {
3916
+ const output = validateRecordedEvidenceChildOutput(sealed.decisiveFacts);
3917
+ const accepted: LawfulEvidenceChildRoleOutcome = {
3918
+ kind: "accepted",
3919
+ role: "evidence-child",
3920
+ status: "report",
3921
+ decisiveFacts: evidenceChildDecisiveFacts(output),
3922
+ };
3923
+ return accepted;
3924
+ },
3925
+ }, scope);
3926
+ }
3927
+
3928
+ export async function trySettleEvidenceChildTerminalResult(
3929
+ admitted: import("./invocation.ts").AdmittedEvidenceChildInvocation,
3930
+ authority: DurablePrincipalAuthority,
3931
+ scope?: SettlementCourtScope,
3932
+ ): Promise<TerminalResult | undefined> {
3933
+ return settleLawfulEvidenceChildTerminalResult(admitted, authority, scope);
3934
+ }
3935
+
3773
3936
  /** Try to settle a lawful Coder Terminal; undefined only for genuine absence. */
3774
3937
  export async function trySettleCoderTerminalResult(
3775
3938
  admitted: AdmittedCoderInvocation,
@@ -40,7 +40,10 @@ export type TerminalRoleName =
40
40
  | "gleaner-left"
41
41
  | "inspector"
42
42
  | "gatekeeper"
43
- | "navigator";
43
+ | "navigator"
44
+ | "auditor"
45
+ | "evidence-child"
46
+ | "diarist";
44
47
 
45
48
  /** Merger/Collector residual only — Notary/audit residual abolished (#475). */
46
49
  export type ResidualIncompleteTerminalOutcome = {