@akagilnc/pi-workflow-roles 0.1.3572 → 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 (129) hide show
  1. package/dist/acp-host/production-host.js +20239 -10556
  2. package/dist/analyst-gate-cycles-read.js +387 -0
  3. package/dist/archivist-record-entry.js +22 -1
  4. package/dist/audit-escalation.js +6 -0
  5. package/dist/auditor-soul.js +74 -0
  6. package/dist/collector-config.js +86 -0
  7. package/dist/collector-evidence.js +316 -0
  8. package/dist/collector-github.js +527 -0
  9. package/dist/collector-ledger.js +853 -0
  10. package/dist/collector-tool-schemas.js +33 -0
  11. package/dist/compliance-transport.js +104 -52
  12. package/dist/diarist-mechanical.js +411 -0
  13. package/dist/diarist-ticket-resolution.js +177 -0
  14. package/dist/diarist.js +311 -0
  15. package/dist/doctor-auditor.js +25 -0
  16. package/dist/doctor-contracts.js +2 -0
  17. package/dist/doctor-evidence.js +142 -0
  18. package/dist/gatekeeper-role.js +104 -81
  19. package/dist/host-transition-prior-native.js +78 -0
  20. package/dist/institutional-resolution.js +1 -95
  21. package/dist/judge-auditor.js +26 -0
  22. package/dist/ledger-session-read.js +227 -0
  23. package/dist/merger-git-state.js +78 -0
  24. package/dist/navigator-attendance.js +15 -7
  25. package/dist/navigator-public-session.js +170 -0
  26. package/dist/navigator-session-contracts.js +36 -40
  27. package/dist/notary-source-run.js +122 -0
  28. package/dist/package-contracts/auditor-output.js +66 -0
  29. package/dist/package-contracts/evidence-child-output.js +34 -0
  30. package/dist/package-contracts/judge-output.js +2 -0
  31. package/dist/package-contracts/terminating-tools.js +25 -2
  32. package/dist/package-resources/method-skill.js +254 -0
  33. package/dist/packaged-role-registry.js +36 -0
  34. package/dist/pi/durable-principal.js +61 -0
  35. package/dist/pi/in-process-session.js +25 -6
  36. package/dist/pi/known-failure.js +52 -0
  37. package/dist/pi/role-turn-host.js +430 -0
  38. package/dist/public-cli/auto-resume.js +414 -0
  39. package/dist/public-cli/cli-errors.js +8 -0
  40. package/dist/public-cli/cli-io.js +1 -0
  41. package/dist/public-cli/command-renderer.js +5 -0
  42. package/dist/public-cli/doctor-run.js +84 -0
  43. package/dist/public-cli/inspector-run.js +136 -0
  44. package/dist/public-cli/instruction-seat-run.js +256 -0
  45. package/dist/public-cli/invocation.js +2225 -0
  46. package/dist/public-cli/judge-run.js +118 -0
  47. package/dist/public-cli/load-production-acp-host.js +40 -0
  48. package/dist/public-cli/main.js +1140 -652
  49. package/dist/public-cli/notary-run.js +161 -0
  50. package/dist/public-cli/option-definitions.js +1192 -0
  51. package/dist/public-cli/post-admission.js +667 -0
  52. package/dist/public-cli/public-run-credentials.js +49 -0
  53. package/dist/public-cli/registry.js +4 -1
  54. package/dist/public-cli/reviewer-dispatch-rejection.js +77 -0
  55. package/dist/public-cli/run-lifecycle.js +1344 -0
  56. package/dist/public-cli/seat-ticket-binding.js +113 -0
  57. package/dist/public-cli/settlement.js +3441 -0
  58. package/dist/public-cli/terminal.js +135 -0
  59. package/dist/public-cli/turn-request.js +25 -0
  60. package/dist/public-role-summons.js +301 -0
  61. package/dist/receipt-delivery-policy.js +10 -0
  62. package/dist/reviewer-child-executor.js +80 -8
  63. package/dist/reviewer-execution-ledger.js +2 -1
  64. package/dist/run-terminal-artifacts.js +195 -0
  65. package/dist/run-ticket-number.js +40 -0
  66. package/dist/session-assistant-usage.js +107 -0
  67. package/dist/shape-unreadable-failure.js +34 -0
  68. package/dist/submission-errors.js +3 -0
  69. package/dist/submission-ledger.js +388 -0
  70. package/dist/ticket-provenance-contracts.js +115 -0
  71. package/dist/ticket-provenance.js +340 -0
  72. package/extensions/role-runtime.ts +7 -0
  73. package/package.json +1 -1
  74. package/scripts/build-package.mjs +2 -1
  75. package/souls/doctor-auditor.md +1 -0
  76. package/souls/evidence-child.md +1 -0
  77. package/src/acp-host/production-host.ts +3 -0
  78. package/src/acp-host/role-envelope.ts +2 -2
  79. package/src/acp-host/role-turn-host.ts +9 -1
  80. package/src/analyst-gate-cycles-read.ts +37 -2
  81. package/src/archivist-record-entry.ts +45 -1
  82. package/src/audit-escalation.ts +17 -0
  83. package/src/auditor-role.ts +22 -0
  84. package/src/auditor-soul.ts +42 -0
  85. package/src/compliance-transport.ts +177 -66
  86. package/src/doctor-auditor.ts +10 -14
  87. package/src/doctor-contracts.ts +1 -0
  88. package/src/doctor-role.ts +2 -2
  89. package/src/evidence-child-role.ts +22 -0
  90. package/src/gatekeeper-pass-envelope.ts +109 -0
  91. package/src/gatekeeper-role.ts +145 -104
  92. package/src/host-contracts.ts +9 -1
  93. package/src/institutional-resolution.ts +8 -163
  94. package/src/judge-auditor.ts +10 -15
  95. package/src/judge-role.ts +8 -0
  96. package/src/navigator-attendance.ts +25 -9
  97. package/src/navigator-public-session.ts +217 -0
  98. package/src/navigator-session-contracts.ts +61 -54
  99. package/src/notary-source-run.ts +3 -1
  100. package/src/package-contracts/auditor-output.ts +82 -0
  101. package/src/package-contracts/evidence-child-output.ts +51 -0
  102. package/src/package-contracts/judge-output.ts +1 -0
  103. package/src/package-contracts/reviewer-output.ts +2 -2
  104. package/src/package-contracts/terminating-tools.ts +31 -1
  105. package/src/packaged-role-registry.ts +43 -0
  106. package/src/pi/adapter.ts +2 -1
  107. package/src/pi/in-process-session.ts +38 -12
  108. package/src/pi/role-turn-host.ts +34 -0
  109. package/src/public-cli/cli.ts +14 -6
  110. package/src/public-cli/instruction-seat-run.ts +289 -50
  111. package/src/public-cli/invocation.ts +66 -25
  112. package/src/public-cli/option-definitions.ts +61 -0
  113. package/src/public-cli/post-admission.ts +7 -1
  114. package/src/public-cli/registry.ts +4 -1
  115. package/src/public-cli/run-lifecycle.ts +22 -3
  116. package/src/public-cli/settlement.ts +120 -5
  117. package/src/public-cli/terminal.ts +2 -0
  118. package/src/public-role-summons.ts +431 -0
  119. package/src/receipt-delivery-policy.ts +10 -0
  120. package/src/reviewer-agent.ts +1 -1
  121. package/src/reviewer-child-executor.ts +114 -12
  122. package/src/reviewer-execution-ledger.ts +3 -2
  123. package/src/role-runtime.ts +158 -17
  124. package/src/session-assistant-usage.ts +119 -0
  125. package/src/session-opening-materials.ts +1 -1
  126. package/src/shape-unreadable-failure.ts +49 -0
  127. package/src/submission-errors.ts +3 -0
  128. package/dist/evidence-child-executor.js +0 -829
  129. package/src/evidence-child-executor.ts +0 -1140
@@ -1,33 +1,53 @@
1
1
  /**
2
- * Shared instruction-seat run (#639 repair seam): gatekeeper and navigator are
3
- * the same admit → turn-request → post-admission → settle shape, parameterized
4
- * by seat. Same direction as the settlement one-shot shared skeleton. cli.ts
5
- * calls this parameterized module directly; no per-seat wrappers.
2
+ * Shared instruction-seat run (#639 / #675 / #637): gatekeeper, navigator, auditor,
3
+ * and evidence-child share admit → turn-request → post-admission → settle.
4
+ * Same-ticket re-summons resume the seat's previous run via the shared public
5
+ * tryResumeSameTicketSeatRun seam (inspector/notary/countersign face) — no
6
+ * independent run/rebind/nest path.
6
7
  */
7
8
  import type { DurablePrincipalAuthority, RoleTurnRequest } from "../host-contracts.ts";
8
9
  import { engineSessionMaterialFromOptions } from "../package-resources/engine-material.ts";
10
+ import { readRunTicketNumber } from "../run-ticket-number.ts";
9
11
  import { CliUsageError } from "./cli-errors.ts";
10
12
  import {
13
+ admitAuditorInvocation,
14
+ admitEvidenceChildInvocation,
11
15
  admitGatekeeperInvocation,
12
16
  admitNavigatorInvocation,
17
+ bindAdmittedTicketNumber,
13
18
  buildInstructionTransportPrompt,
19
+ type AdmittedAuditorInvocation,
20
+ type AdmittedEvidenceChildInvocation,
14
21
  type AdmittedGatekeeperInvocation,
15
22
  type AdmittedNavigatorInvocation,
16
23
  type ParseInstructionArgvResult,
17
24
  } from "./invocation.ts";
18
25
  import {
26
+ prepareSummonsResumeMaterials,
19
27
  runPostAdmissionOneShot,
20
28
  runPostAdmissionSeatResume,
21
29
  resumeTurnRequestProjectionOptions,
30
+ type PostAdmissionAdapters,
22
31
  type PostAdmissionEnv,
23
32
  } from "./post-admission.ts";
24
33
  import {
25
34
  loadResumableInstructionSeatRun,
26
35
  markRunAdmitted,
27
36
  type PublicResumeRequest,
37
+ type SameTicketSummonsMaterials,
28
38
  } from "./run-lifecycle.ts";
39
+ import {
40
+ applyInstructionTicketProbe,
41
+ probeInstructionTicket,
42
+ ticketNumberFromProbe,
43
+ tryResumeSameTicketSeatRun,
44
+ type InstructionTicketProbe,
45
+ } from "./seat-ticket-binding.ts";
29
46
  import {
30
47
  presentStructuralRejection,
48
+ readEngineDetourInfrastructureFailure,
49
+ trySettleAuditorTerminalResult,
50
+ trySettleEvidenceChildTerminalResult,
31
51
  trySettleGatekeeperTerminalResult,
32
52
  trySettleNavigatorTerminalResult,
33
53
  } from "./settlement.ts";
@@ -38,11 +58,17 @@ import {
38
58
  type RoleTurnRequestProjectionOptions,
39
59
  } from "./turn-request.ts";
40
60
 
41
- export type InstructionSeatRole = "gatekeeper" | "navigator";
61
+ export type InstructionSeatRole =
62
+ | "gatekeeper"
63
+ | "navigator"
64
+ | "auditor"
65
+ | "evidence-child";
42
66
 
43
67
  export type AdmittedInstructionSeatInvocation =
44
68
  | AdmittedGatekeeperInvocation
45
- | AdmittedNavigatorInvocation;
69
+ | AdmittedNavigatorInvocation
70
+ | AdmittedAuditorInvocation
71
+ | AdmittedEvidenceChildInvocation;
46
72
 
47
73
  export type InstructionSeatRunEnv = PostAdmissionEnv & {
48
74
  principalAuthority: DurablePrincipalAuthority;
@@ -65,26 +91,81 @@ export function buildInstructionSeatTurnRequest(
65
91
  );
66
92
  }
67
93
 
68
- function instructionSeatAdapters() {
94
+ function instructionSeatAdapters(options?: {
95
+ beforeDispatch?: (
96
+ admitted: AdmittedInstructionSeatInvocation,
97
+ ) => void | Promise<void>;
98
+ }): PostAdmissionAdapters<AdmittedInstructionSeatInvocation> {
69
99
  return {
70
100
  trySettle: (
71
101
  admitted: AdmittedInstructionSeatInvocation,
72
102
  authority: DurablePrincipalAuthority,
73
103
  scope?: { readonly courtAttemptId?: string },
74
- ) =>
75
- admitted.role === "gatekeeper"
76
- ? trySettleGatekeeperTerminalResult(admitted, authority, scope)
77
- : trySettleNavigatorTerminalResult(admitted, authority, scope),
104
+ ) => {
105
+ switch (admitted.role) {
106
+ case "gatekeeper":
107
+ return trySettleGatekeeperTerminalResult(admitted, authority, scope);
108
+ case "navigator":
109
+ return trySettleNavigatorTerminalResult(admitted, authority, scope);
110
+ case "auditor":
111
+ return trySettleAuditorTerminalResult(admitted, authority, scope);
112
+ case "evidence-child":
113
+ return trySettleEvidenceChildTerminalResult(admitted, authority, scope);
114
+ }
115
+ },
78
116
  // Accepted receipts and failure terminals both present via shared path.
79
117
  shouldPresentSettled: () => true,
118
+ // #675 / #357 T2: failInfrastructure abort after engine-detour tool failure must not
119
+ // wash the durable toolResult diagnostic (same seam as reviewer-run / judge-run).
120
+ resolveRunnerKnownFailure: async ({
121
+ result,
122
+ sessionFile,
123
+ }: {
124
+ result: { knownFailure?: import("../host-contracts.ts").RoleTurnKnownFailure };
125
+ sessionFile: string;
126
+ }) => {
127
+ const infrastructureFailure = await readEngineDetourInfrastructureFailure(sessionFile);
128
+ return infrastructureFailure === undefined
129
+ ? result.knownFailure
130
+ : {
131
+ cause: infrastructureFailure.cause,
132
+ diagnostic: infrastructureFailure.diagnostic,
133
+ ...(infrastructureFailure.identity === undefined
134
+ ? {}
135
+ : { identity: infrastructureFailure.identity }),
136
+ };
137
+ },
138
+ ...(options?.beforeDispatch === undefined
139
+ ? {}
140
+ : { beforeDispatch: options.beforeDispatch }),
80
141
  };
81
142
  }
82
143
 
144
+ async function admitInstructionSeat(
145
+ role: InstructionSeatRole,
146
+ options: Parameters<typeof admitGatekeeperInvocation>[0],
147
+ ): Promise<AdmittedInstructionSeatInvocation> {
148
+ switch (role) {
149
+ case "gatekeeper":
150
+ return admitGatekeeperInvocation(options);
151
+ case "navigator":
152
+ return admitNavigatorInvocation(options);
153
+ case "auditor":
154
+ return admitAuditorInvocation(options);
155
+ case "evidence-child":
156
+ return admitEvidenceChildInvocation(options);
157
+ }
158
+ }
159
+
83
160
  export async function runPublicInstructionSeatResume(
84
161
  request: PublicResumeRequest,
85
162
  env: InstructionSeatRunEnv,
86
163
  io: CliIo,
87
- ): Promise<{ exitCode: number; terminal?: TerminalResult }> {
164
+ ): Promise<{
165
+ exitCode: number;
166
+ admitted?: AdmittedInstructionSeatInvocation;
167
+ terminal?: TerminalResult;
168
+ }> {
88
169
  return await runPostAdmissionSeatResume({
89
170
  request,
90
171
  env,
@@ -94,15 +175,62 @@ export async function runPublicInstructionSeatResume(
94
175
  effective.runId,
95
176
  env.principalAuthority,
96
177
  ),
97
- buildTurnRequest: (admitted, effective) => buildInstructionSeatTurnRequest(
98
- admitted,
99
- resumeTurnRequestProjectionOptions(admitted, effective, env),
100
- ),
178
+ buildTurnRequest: async (admitted, effective) => {
179
+ const summonsPrepared = await prepareSummonsResumeMaterials(
180
+ admitted.runDirectory,
181
+ effective.summons,
182
+ );
183
+ return buildInstructionSeatTurnRequest(
184
+ admitted,
185
+ resumeTurnRequestProjectionOptions(
186
+ admitted,
187
+ effective,
188
+ env,
189
+ summonsPrepared,
190
+ ),
191
+ );
192
+ },
101
193
  adapters: instructionSeatAdapters(),
102
194
  ...(env.engine === undefined ? {} : { effectiveEngine: env.engine }),
103
195
  });
104
196
  }
105
197
 
198
+ /** Scope auditor subject/source-run env for the duration of one seat turn. */
199
+ async function withAuditorSoulEnv<
200
+ T,
201
+ >(options: {
202
+ readonly subject?: "judge" | "doctor";
203
+ readonly sourceRunDirectory?: string;
204
+ readonly run: () => Promise<T>;
205
+ }): Promise<T> {
206
+ if (options.subject === undefined && options.sourceRunDirectory === undefined) {
207
+ return options.run();
208
+ }
209
+ const { AK_ROLE_AUDITOR_SUBJECT_ENV, AK_ROLE_AUDITOR_SOURCE_RUN_ENV } = await import(
210
+ "../auditor-soul.ts"
211
+ );
212
+ const priorSubject = process.env[AK_ROLE_AUDITOR_SUBJECT_ENV];
213
+ const priorSource = process.env[AK_ROLE_AUDITOR_SOURCE_RUN_ENV];
214
+ if (options.subject !== undefined) {
215
+ process.env[AK_ROLE_AUDITOR_SUBJECT_ENV] = options.subject;
216
+ }
217
+ if (options.sourceRunDirectory !== undefined) {
218
+ process.env[AK_ROLE_AUDITOR_SOURCE_RUN_ENV] = options.sourceRunDirectory;
219
+ }
220
+ try {
221
+ return await options.run();
222
+ } finally {
223
+ if (options.subject !== undefined) {
224
+ if (priorSubject === undefined) delete process.env[AK_ROLE_AUDITOR_SUBJECT_ENV];
225
+ else process.env[AK_ROLE_AUDITOR_SUBJECT_ENV] = priorSubject;
226
+ }
227
+ if (options.sourceRunDirectory !== undefined) {
228
+ if (priorSource === undefined) delete process.env[AK_ROLE_AUDITOR_SOURCE_RUN_ENV];
229
+ else process.env[AK_ROLE_AUDITOR_SOURCE_RUN_ENV] = priorSource;
230
+ }
231
+ }
232
+ }
233
+
106
234
  export async function runPublicInstructionSeat(
107
235
  argv: readonly string[],
108
236
  env: InstructionSeatRunEnv,
@@ -114,10 +242,106 @@ export async function runPublicInstructionSeat(
114
242
  admitted?: AdmittedInstructionSeatInvocation;
115
243
  terminal?: TerminalResult;
116
244
  }> {
245
+ let parsed: ParseInstructionArgvResult;
246
+ try {
247
+ parsed = parseArgv(argv);
248
+ } catch (error) {
249
+ if (error instanceof CliUsageError) {
250
+ presentStructuralRejection(error, io);
251
+ return { exitCode: 2 };
252
+ }
253
+ throw error;
254
+ }
255
+
256
+ let auditorSubject: "judge" | "doctor" | undefined;
257
+ let auditorSourceRun: string | undefined;
258
+ let auditorSourceTicket: number | undefined;
259
+ let ticketProbe: InstructionTicketProbe | undefined;
260
+
261
+ // #637: same ticket → resume prior seat run with this summons' materials.
262
+ // Auditor inherits ticket from source-run (notary face); other instruction seats
263
+ // probe instruction (inspector face). No bare catch→fresh: lookup/resume failures
264
+ // surface; only true absence of a prior run mints new.
265
+ const projectRoot = parsed.project ?? env.cwd;
266
+ if (role === "auditor") {
267
+ if (parsed.subject !== "judge" && parsed.subject !== "doctor") {
268
+ presentStructuralRejection(
269
+ new CliUsageError("auditor --subject requires judge|doctor"),
270
+ io,
271
+ );
272
+ return { exitCode: 2 };
273
+ }
274
+ auditorSubject = parsed.subject;
275
+ const source = typeof parsed.sourceRun === "string" ? parsed.sourceRun.trim() : "";
276
+ if (source === "") {
277
+ presentStructuralRejection(
278
+ new CliUsageError("auditor --source-run requires a run locator"),
279
+ io,
280
+ );
281
+ return { exitCode: 2 };
282
+ }
283
+ try {
284
+ const { resolveNotarySourceRunLocator } = await import("../notary-source-run.ts");
285
+ const resolved = await resolveNotarySourceRunLocator({
286
+ projectRoot,
287
+ sourceRun: source,
288
+ home: env.home,
289
+ });
290
+ auditorSourceRun = resolved.runDirectory;
291
+ auditorSourceTicket = await readRunTicketNumber(resolved.runDirectory);
292
+ } catch (error) {
293
+ presentStructuralRejection(
294
+ new CliUsageError(error instanceof Error ? error.message : String(error)),
295
+ io,
296
+ );
297
+ return { exitCode: 2 };
298
+ }
299
+ } else {
300
+ // Inspector face: unconditional probe (same seam as inspector-run.ts).
301
+ ticketProbe = await probeInstructionTicket(
302
+ parsed.instruction,
303
+ projectRoot,
304
+ env,
305
+ );
306
+ }
307
+
308
+ const probedTicketNumber =
309
+ auditorSourceTicket
310
+ ?? (ticketProbe === undefined ? undefined : ticketNumberFromProbe(ticketProbe));
311
+
312
+ if (probedTicketNumber !== undefined) {
313
+ const summons: SameTicketSummonsMaterials = {
314
+ instruction: parsed.instruction,
315
+ instructionEmpty: parsed.instruction.trim() === "",
316
+ attachmentPaths: parsed.attachmentPaths,
317
+ };
318
+ const resumed = await withAuditorSoulEnv({
319
+ ...(auditorSubject === undefined ? {} : { subject: auditorSubject }),
320
+ ...(auditorSourceRun === undefined
321
+ ? {}
322
+ : { sourceRunDirectory: auditorSourceRun }),
323
+ run: () =>
324
+ tryResumeSameTicketSeatRun({
325
+ home: env.home,
326
+ projectRoot,
327
+ role,
328
+ ticketNumber: probedTicketNumber,
329
+ freshSummons: env.freshSummons,
330
+ summons,
331
+ resume: (runId, materials) =>
332
+ runPublicInstructionSeatResume(
333
+ { runId, ...(materials === undefined ? {} : { summons: materials }) },
334
+ env,
335
+ io,
336
+ ),
337
+ }),
338
+ });
339
+ if (resumed !== undefined) return resumed;
340
+ }
341
+
117
342
  let admitted: AdmittedInstructionSeatInvocation;
118
343
  try {
119
- const parsed = parseArgv(argv);
120
- const options = {
344
+ admitted = await admitInstructionSeat(role, {
121
345
  home: env.home,
122
346
  principalAuthority: env.principalAuthority,
123
347
  cwd: env.cwd,
@@ -127,11 +351,7 @@ export async function runPublicInstructionSeat(
127
351
  ...(env.createRunId === undefined ? {} : { createRunId: env.createRunId }),
128
352
  ...(env.model === undefined ? {} : { model: env.model }),
129
353
  ...(env.correlationId === undefined ? {} : { correlationId: env.correlationId }),
130
- };
131
- admitted =
132
- role === "gatekeeper"
133
- ? await admitGatekeeperInvocation(options)
134
- : await admitNavigatorInvocation(options);
354
+ });
135
355
  } catch (error) {
136
356
  if (error instanceof CliUsageError) {
137
357
  presentStructuralRejection(error, io);
@@ -140,36 +360,55 @@ export async function runPublicInstructionSeat(
140
360
  throw error;
141
361
  }
142
362
 
143
- await markRunAdmitted(admitted, env.principalAuthority);
144
-
145
- const turnRequest = buildInstructionSeatTurnRequest(admitted, {
146
- packageRoot: env.packageRoot,
147
- home: env.home,
148
- agentDir: env.agentDir,
149
- ...(env.model === undefined ? {} : { model: env.model }),
150
- ...(env.engine === undefined ? {} : { engine: env.engine }),
151
- ...(env.timeoutMs === undefined ? {} : { timeoutMs: env.timeoutMs }),
152
- ...(env.correlationId === undefined || env.correlationId.trim() === ""
363
+ return await withAuditorSoulEnv({
364
+ ...(auditorSubject === undefined ? {} : { subject: auditorSubject }),
365
+ ...(auditorSourceRun === undefined
153
366
  ? {}
154
- : { correlationId: env.correlationId }),
155
- continuation: {
156
- kind: "initial",
157
- prompt: buildInstructionTransportPrompt(
367
+ : { sourceRunDirectory: auditorSourceRun }),
368
+ run: async () => {
369
+ await markRunAdmitted(admitted, env.principalAuthority);
370
+
371
+ const turnRequest = buildInstructionSeatTurnRequest(admitted, {
372
+ packageRoot: env.packageRoot,
373
+ home: env.home,
374
+ agentDir: env.agentDir,
375
+ ...(env.model === undefined ? {} : { model: env.model }),
376
+ ...(env.engine === undefined ? {} : { engine: env.engine }),
377
+ ...(env.timeoutMs === undefined ? {} : { timeoutMs: env.timeoutMs }),
378
+ ...(env.correlationId === undefined || env.correlationId.trim() === ""
379
+ ? {}
380
+ : { correlationId: env.correlationId }),
381
+ continuation: {
382
+ kind: "initial",
383
+ prompt: buildInstructionTransportPrompt(
384
+ admitted,
385
+ engineSessionMaterialFromOptions({
386
+ ...(env.engine === undefined ? {} : { engine: env.engine }),
387
+ packageRoot: env.packageRoot,
388
+ }),
389
+ ),
390
+ },
391
+ });
392
+
393
+ return await runPostAdmissionOneShot({
158
394
  admitted,
159
- engineSessionMaterialFromOptions({
160
- ...(env.engine === undefined ? {} : { engine: env.engine }),
161
- packageRoot: env.packageRoot,
395
+ env,
396
+ io,
397
+ request: turnRequest,
398
+ adapters: instructionSeatAdapters({
399
+ beforeDispatch: async (admittedSeat) => {
400
+ // #635/#637: ticket bind inside controlled-failure boundary.
401
+ // Auditor inherits source-run ticket (notary face).
402
+ // Other seats: same applyInstructionTicketProbe as inspector-run.
403
+ if (auditorSourceTicket !== undefined) {
404
+ await bindAdmittedTicketNumber(admittedSeat, auditorSourceTicket);
405
+ } else if (ticketProbe !== undefined) {
406
+ await applyInstructionTicketProbe(admittedSeat, ticketProbe);
407
+ }
408
+ },
162
409
  }),
163
- ),
410
+ ...(env.engine === undefined ? {} : { effectiveEngine: env.engine }),
411
+ });
164
412
  },
165
413
  });
166
-
167
- return await runPostAdmissionOneShot({
168
- admitted,
169
- env,
170
- io,
171
- request: turnRequest,
172
- adapters: instructionSeatAdapters(),
173
- ...(env.engine === undefined ? {} : { effectiveEngine: env.engine }),
174
- });
175
414
  }
@@ -73,12 +73,7 @@ import {
73
73
  type OptionOwner,
74
74
  type PublicOptionDefinition,
75
75
  } from "./option-definitions.ts";
76
- import { loadPublicCliConfig } from "./config.ts";
77
76
  import type { PublicThinkingLevel } from "./registry.ts";
78
- import {
79
- resolveInstitutionalSeatSelections,
80
- writeInstitutionalResolutionPage,
81
- } from "../institutional-resolution.ts";
82
77
 
83
78
  export type FrozenAttachment = {
84
79
  /** Original caller path retained only as provenance. */
@@ -151,6 +146,14 @@ export type AdmittedNavigatorInvocation = AdmittedRoleInvocationBase & {
151
146
  readonly role: "navigator";
152
147
  };
153
148
 
149
+ export type AdmittedAuditorInvocation = AdmittedRoleInvocationBase & {
150
+ readonly role: "auditor";
151
+ };
152
+
153
+ export type AdmittedEvidenceChildInvocation = AdmittedRoleInvocationBase & {
154
+ readonly role: "evidence-child";
155
+ };
156
+
154
157
  export type AdmittedDiaristInvocation = AdmittedRoleInvocationBase & {
155
158
  readonly role: "diarist";
156
159
  };
@@ -238,6 +241,8 @@ export type AdmittedRoleInvocation =
238
241
  | AdmittedInspectorInvocation
239
242
  | AdmittedGatekeeperInvocation
240
243
  | AdmittedNavigatorInvocation
244
+ | AdmittedAuditorInvocation
245
+ | AdmittedEvidenceChildInvocation
241
246
  | AdmittedDiaristInvocation
242
247
  | AdmittedCoderInvocation
243
248
  | AdmittedFixerInvocation
@@ -367,10 +372,6 @@ async function writeRoleInvocationLedger(
367
372
  `${JSON.stringify(identity, null, 2)}\n`,
368
373
  "utf8",
369
374
  );
370
- const home = homeFromRunDirectory(source.runDirectory);
371
- const config = await loadPublicCliConfig(home);
372
- const institutionalPage = resolveInstitutionalSeatSelections(config, effectiveModel);
373
- await writeInstitutionalResolutionPage(source.runDirectory, institutionalPage);
374
375
  }
375
376
 
376
377
  /**
@@ -417,20 +418,6 @@ export async function recordEffectiveInvocationModel(
417
418
  `${JSON.stringify(next, null, 2)}\n`,
418
419
  "utf8",
419
420
  );
420
- const effectiveModel: InvocationEffectiveModel | undefined =
421
- typeof next.provider === "string" && typeof next.model === "string"
422
- ? {
423
- provider: next.provider,
424
- model: next.model,
425
- ...(typeof next.thinking === "string"
426
- ? { thinking: next.thinking }
427
- : {}),
428
- }
429
- : undefined;
430
- const home = homeFromRunDirectory(runDirectory);
431
- const config = await loadPublicCliConfig(home);
432
- const institutionalPage = resolveInstitutionalSeatSelections(config, effectiveModel);
433
- await writeInstitutionalResolutionPage(runDirectory, institutionalPage);
434
421
  }
435
422
 
436
423
  /** Merge observed launch-time fields into the single existing invocation.json identity page. */
@@ -583,6 +570,10 @@ export type ParseInstructionArgvResult = {
583
570
  instruction: string;
584
571
  attachmentPaths: string[];
585
572
  project?: string;
573
+ /** Auditor only — audited subject selecting soul materials (#675 owner). */
574
+ subject?: "judge" | "doctor";
575
+ /** Auditor source-run locator — same input surface for direct and nested (#675). */
576
+ sourceRun?: string;
586
577
  };
587
578
 
588
579
  /** Judge/Countersign 命令面同形:--project/--attach/opaque instruction。 */
@@ -612,10 +603,12 @@ export function parsePositiveTicketNumber(
612
603
  /** 共享解析体:同形 owner 的 argv → instruction/attachments/project。 */
613
604
  function parseInstructionArgv(
614
605
  args: readonly string[],
615
- owner: "judge" | "countersign" | "inspector" | "gatekeeper" | "navigator" | "diarist",
606
+ owner: "judge" | "countersign" | "inspector" | "gatekeeper" | "navigator" | "auditor" | "evidence-child" | "diarist",
616
607
  ): ParseInstructionArgvResult {
617
608
  const attachmentPaths: string[] = [];
618
609
  let project: string | undefined;
610
+ let subject: "judge" | "doctor" | undefined;
611
+ let sourceRun: string | undefined;
619
612
  const positional: string[] = [];
620
613
  const tokens = [...args];
621
614
  const definitions = roleOptions(owner);
@@ -637,6 +630,24 @@ function parseInstructionArgv(
637
630
  project = requireOptionPath(taken.def.canonical, taken.value);
638
631
  continue;
639
632
  }
633
+ if (taken.def.id === "subject") {
634
+ const raw = typeof taken.value === "string" ? taken.value.trim() : "";
635
+ if (raw !== "judge" && raw !== "doctor") {
636
+ throw new CliUsageError(
637
+ `auditor --subject must be judge|doctor, got ${taken.value ?? "(missing)"}`,
638
+ );
639
+ }
640
+ subject = raw;
641
+ continue;
642
+ }
643
+ if (taken.def.id === "source-run") {
644
+ const raw = typeof taken.value === "string" ? taken.value.trim() : "";
645
+ if (raw === "") {
646
+ throw new CliUsageError("auditor --source-run requires a run locator");
647
+ }
648
+ sourceRun = raw;
649
+ continue;
650
+ }
640
651
  throw new CliUsageError(`unknown ${owner} option: ${taken.def.canonical}`);
641
652
  }
642
653
  const token = tokens.shift()!;
@@ -651,6 +662,8 @@ function parseInstructionArgv(
651
662
  instruction: positional.join(" "),
652
663
  attachmentPaths,
653
664
  ...(project === undefined ? {} : { project }),
665
+ ...(subject === undefined ? {} : { subject }),
666
+ ...(sourceRun === undefined ? {} : { sourceRun }),
654
667
  };
655
668
  }
656
669
 
@@ -852,6 +865,17 @@ export function parseNavigatorArgv(args: readonly string[]): ParseNavigatorArgvR
852
865
  return parseInstructionArgv(args, "navigator");
853
866
  }
854
867
 
868
+ export type ParseAuditorArgvResult = ParseInstructionArgvResult;
869
+ export type ParseEvidenceChildArgvResult = ParseInstructionArgvResult;
870
+
871
+ export function parseAuditorArgv(args: readonly string[]): ParseAuditorArgvResult {
872
+ return parseInstructionArgv(args, "auditor");
873
+ }
874
+
875
+ export function parseEvidenceChildArgv(args: readonly string[]): ParseEvidenceChildArgvResult {
876
+ return parseInstructionArgv(args, "evidence-child");
877
+ }
878
+
855
879
  export function parseDiaristArgv(args: readonly string[]): ParseDiaristArgvResult {
856
880
  return parseInstructionArgv(args, "diarist");
857
881
  }
@@ -1064,7 +1088,7 @@ export type AdmitDiaristInvocationOptions = AdmitInspectorInvocationOptions;
1064
1088
  * Ticket binding is post-admission via shared seat LLM path (#635).
1065
1089
  */
1066
1090
  async function admitStandardMaterialInvocation<
1067
- R extends "judge" | "inspector" | "gatekeeper" | "navigator" | "diarist",
1091
+ R extends "judge" | "inspector" | "gatekeeper" | "navigator" | "auditor" | "evidence-child" | "diarist",
1068
1092
  >(
1069
1093
  role: R,
1070
1094
  options: AdmitJudgeInvocationOptions & { correlationId?: string },
@@ -1184,6 +1208,23 @@ export async function admitNavigatorInvocation(
1184
1208
  return admitStandardMaterialInvocation("navigator", options);
1185
1209
  }
1186
1210
 
1211
+ export type AdmitAuditorInvocationOptions = AdmitInspectorInvocationOptions;
1212
+ export type AdmitEvidenceChildInvocationOptions = AdmitInspectorInvocationOptions;
1213
+
1214
+ /** Admit a public 审刑院 run (#675). */
1215
+ export async function admitAuditorInvocation(
1216
+ options: AdmitAuditorInvocationOptions,
1217
+ ): Promise<AdmittedAuditorInvocation> {
1218
+ return admitStandardMaterialInvocation("auditor", options);
1219
+ }
1220
+
1221
+ /** Admit a public evidence-child run (#675). */
1222
+ export async function admitEvidenceChildInvocation(
1223
+ options: AdmitEvidenceChildInvocationOptions,
1224
+ ): Promise<AdmittedEvidenceChildInvocation> {
1225
+ return admitStandardMaterialInvocation("evidence-child", options);
1226
+ }
1227
+
1187
1228
  /**
1188
1229
  * Admit a direct Diarist (起居郎) run (#708): freeze attachments, persist the
1189
1230
  * request, reserve session placement — same instruction-seat face.