@akagilnc/pi-workflow-roles 0.1.4802 → 0.1.4870

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/dist/acp-host/production-host.js +19434 -18218
  2. package/dist/analyst-book-key.js +63 -0
  3. package/dist/analyst-cohort.js +167 -0
  4. package/dist/analyst-entry.js +320 -0
  5. package/dist/analyst-index.js +247 -0
  6. package/dist/analyst-ledger.js +561 -0
  7. package/dist/analyst-median.js +16 -0
  8. package/dist/analyst-metric-families/acceptance-success-rework.js +249 -0
  9. package/dist/analyst-metric-families/b2-frame-buckets-actions.js +189 -0
  10. package/dist/analyst-metric-families/gate-cycles.js +77 -0
  11. package/dist/analyst-metric-families/leg-wall-clock.js +56 -0
  12. package/dist/analyst-metric-families/round-timeline.js +126 -0
  13. package/dist/analyst-metric-families.js +23 -0
  14. package/dist/analyst-metric-family.js +11 -0
  15. package/dist/analyst-model-groups.js +135 -0
  16. package/dist/analyst-page.js +182 -0
  17. package/dist/atomic-write.js +23 -0
  18. package/dist/auditor-soul.js +1 -1
  19. package/dist/countersign-contracts.js +0 -2
  20. package/dist/diarist-contracts.js +0 -1
  21. package/dist/doctor-contracts.js +2 -2
  22. package/dist/gatekeeper-role.js +15 -16
  23. package/dist/gleaner-left-contracts.js +0 -2
  24. package/dist/headless-host/production-host.js +16967 -15749
  25. package/dist/host-contracts.js +0 -4
  26. package/dist/inspector-contracts.js +0 -2
  27. package/dist/institutional-resolution.js +4 -2
  28. package/dist/merger-contracts.js +0 -2
  29. package/dist/migrate-book-topology.js +3908 -3089
  30. package/dist/navigator-public-session.js +4 -3
  31. package/dist/notary-contracts.js +0 -2
  32. package/dist/package-contracts/auditor-output.js +0 -1
  33. package/dist/package-contracts/collector-output.js +0 -2
  34. package/dist/package-contracts/fixer-output.js +0 -2
  35. package/dist/package-contracts/gatekeeper-output.js +0 -2
  36. package/dist/package-contracts/judge-output.js +0 -2
  37. package/dist/package-contracts/navigator-output.js +0 -2
  38. package/dist/package-contracts/reviewer-output.js +0 -2
  39. package/dist/package-contracts/terminating-tools.js +32 -92
  40. package/dist/package-contracts/worker-output.js +0 -4
  41. package/dist/packaged-role-registry.js +518 -36
  42. package/dist/pi/role-turn-host.js +2 -1
  43. package/dist/public-cli/analyst-run.js +185 -0
  44. package/dist/public-cli/cli.js +885 -0
  45. package/dist/public-cli/config.js +12 -9
  46. package/dist/public-cli/countersign-run.js +4 -311
  47. package/dist/public-cli/instruction-seat-run.js +628 -158
  48. package/dist/public-cli/invocation.js +806 -1550
  49. package/dist/public-cli/main.js +6962 -9882
  50. package/dist/public-cli/option-definitions.js +51 -99
  51. package/dist/public-cli/post-admission.js +30 -2
  52. package/dist/public-cli/run-lifecycle.js +234 -353
  53. package/dist/public-cli/seat-ticket-binding.js +6 -0
  54. package/dist/public-cli/settlement.js +261 -675
  55. package/dist/public-cli/turn-request.js +76 -0
  56. package/dist/public-role-summons.js +38 -112
  57. package/dist/role-activation-flags.js +23 -45
  58. package/dist/secretariat-contracts.js +0 -2
  59. package/dist/session-identity.js +17 -8
  60. package/dist/session-opening-materials.js +3 -2
  61. package/extensions/role-runtime.ts +6 -80
  62. package/package.json +1 -1
  63. package/src/acp-host/role-turn-host.ts +4 -1
  64. package/src/analyst-metric-families/acceptance-success-rework.ts +3 -2
  65. package/src/auditor-role.ts +1 -2
  66. package/src/auditor-soul.ts +1 -1
  67. package/src/collector-role.ts +2 -2
  68. package/src/countersign-contracts.ts +0 -1
  69. package/src/countersign-role.ts +1 -1
  70. package/src/diarist-contracts.ts +0 -1
  71. package/src/diarist-role.ts +0 -1
  72. package/src/doctor-auditor.ts +1 -2
  73. package/src/doctor-contracts.ts +1 -1
  74. package/src/doctor-role.ts +3 -2
  75. package/src/external-host-turn-loop.ts +1 -1
  76. package/src/factory-board.ts +10 -7
  77. package/src/gatekeeper-role.ts +16 -10
  78. package/src/gleaner-left-contracts.ts +0 -1
  79. package/src/gleaner-left-role.ts +0 -1
  80. package/src/headless-host/role-turn-host.ts +7 -1
  81. package/src/host-contracts.ts +10 -6
  82. package/src/inspector-contracts.ts +0 -1
  83. package/src/inspector-role.ts +0 -2
  84. package/src/institutional-resolution.ts +6 -4
  85. package/src/judge-role.ts +3 -3
  86. package/src/merger-contracts.ts +0 -1
  87. package/src/merger-role.ts +2 -2
  88. package/src/navigator-public-session.ts +7 -6
  89. package/src/navigator-work-context.ts +6 -8
  90. package/src/notary-contracts.ts +0 -1
  91. package/src/notary-role.ts +2 -3
  92. package/src/package-contracts/auditor-output.ts +0 -1
  93. package/src/package-contracts/collector-output.ts +0 -1
  94. package/src/package-contracts/fixer-output.ts +0 -1
  95. package/src/package-contracts/gatekeeper-output.ts +0 -1
  96. package/src/package-contracts/judge-output.ts +0 -1
  97. package/src/package-contracts/navigator-output.ts +0 -1
  98. package/src/package-contracts/reviewer-output.ts +0 -1
  99. package/src/package-contracts/terminating-tools.ts +27 -99
  100. package/src/package-contracts/worker-output.ts +0 -2
  101. package/src/packaged-role-registry.ts +604 -35
  102. package/src/pi/role-turn-host.ts +2 -1
  103. package/src/public-cli/cli.ts +64 -259
  104. package/src/public-cli/config.ts +18 -10
  105. package/src/public-cli/countersign-run.ts +14 -449
  106. package/src/public-cli/instruction-seat-run.ts +758 -277
  107. package/src/public-cli/invocation.ts +1097 -2051
  108. package/src/public-cli/option-definitions.ts +62 -127
  109. package/src/public-cli/post-admission.ts +47 -2
  110. package/src/public-cli/run-lifecycle.ts +303 -613
  111. package/src/public-cli/seat-ticket-binding.ts +6 -0
  112. package/src/public-cli/settlement.ts +399 -1185
  113. package/src/public-cli/turn-request.ts +92 -1
  114. package/src/public-role-summons.ts +44 -128
  115. package/src/reviewer-role.ts +3 -2
  116. package/src/role-activation-flags.ts +20 -41
  117. package/src/role-runtime-dependencies.ts +25 -26
  118. package/src/role-runtime.ts +121 -232
  119. package/src/secretariat-contracts.ts +0 -1
  120. package/src/secretariat-role.ts +0 -2
  121. package/src/session-identity.ts +23 -8
  122. package/src/session-opening-materials.ts +2 -1
  123. package/src/worker-role.ts +3 -4
  124. package/dist/doctor-auditor.js +0 -25
  125. package/dist/public-cli/diarist-run.js +0 -130
  126. package/dist/public-cli/doctor-run.js +0 -87
  127. package/dist/public-cli/inspector-run.js +0 -151
  128. package/dist/public-cli/judge-run.js +0 -114
  129. package/dist/public-cli/notary-run.js +0 -174
  130. package/dist/public-cli/reviewer-run.js +0 -339
  131. package/src/public-cli/coder-run.ts +0 -255
  132. package/src/public-cli/collector-run.ts +0 -189
  133. package/src/public-cli/diarist-run.ts +0 -233
  134. package/src/public-cli/doctor-run.ts +0 -167
  135. package/src/public-cli/fixer-run.ts +0 -265
  136. package/src/public-cli/gleaner-left-run.ts +0 -167
  137. package/src/public-cli/inspector-run.ts +0 -261
  138. package/src/public-cli/judge-run.ts +0 -196
  139. package/src/public-cli/merger-run.ts +0 -294
  140. package/src/public-cli/notary-run.ts +0 -279
  141. package/src/public-cli/reviewer-run.ts +0 -480
  142. package/src/public-cli/secretariat-run.ts +0 -265
@@ -21,7 +21,8 @@ import type {
21
21
  RoleTurnRequest,
22
22
  RoleTurnResult,
23
23
  } from "../host-contracts.ts";
24
- import { ExplicitInternalActivationError, isOfficerReviewSeat } from "../host-contracts.ts";
24
+ import { ExplicitInternalActivationError } from "../host-contracts.ts";
25
+ import { isOfficerReviewSeat } from "../packaged-role-registry.ts";
25
26
  import { applyEngineChildEnv, ENGINE_MODEL_FLAG_NAME, normalizeEngineName } from "../engine-detour.ts";
26
27
  import { projectActivationFlags } from "../role-activation-flags.ts";
27
28
  import { encodeUserDialogueStdin } from "../user-dialogue-stdin.ts";
@@ -44,6 +44,7 @@ import {
44
44
  projectHostFacingProvider,
45
45
  renderHostProvidersTable,
46
46
  } from "./host-providers.ts";
47
+ import { packagedModelParent } from "../packaged-role-registry.ts";
47
48
  import { seatModelOnly } from "./registry.ts";
48
49
  import { CliUsageError } from "./cli-errors.ts";
49
50
  import type { CliIo } from "./cli-io.ts";
@@ -60,22 +61,9 @@ import {
60
61
  } from "./role-turn-host-resolution.ts";
61
62
  import {
62
63
  parseAnalystArgv,
63
- parseCoderArgv,
64
- parseCollectorArgv,
65
- parseCountersignArgv,
66
- parseDiaristArgv,
67
- parseSecretariatArgv,
68
- parseGleanerLeftArgv,
69
- parseDoctorArgv,
70
- parseFixerArgv,
71
- parseGatekeeperArgv,
72
- parseJudgeArgv,
73
- parseInspectorArgv,
74
- parseMergerArgv,
75
- parseNavigatorArgv,
76
- parseAuditorArgv,
77
- parseNotaryArgv,
78
- parseReviewerArgv,
64
+ parsePublicSeatArgv,
65
+ type PublicSeatArgvOwner,
66
+ type PublicSeatParse,
79
67
  } from "./invocation.ts";
80
68
  import {
81
69
  createTypedOptionConsumer,
@@ -83,24 +71,13 @@ import {
83
71
  projectCommandHelp,
84
72
  projectOwnerOptions,
85
73
  PUBLIC_NAVIGATOR_HELP_NOTE,
74
+ PUBLIC_ROLE_OPTION_OWNERS,
86
75
  renderHumanOwnerOptionLines,
87
76
  type PublicOptionDefinition,
77
+ type PublicRoleOptionOwner,
88
78
  type TypedOptionConsumer,
89
79
  } from "./option-definitions.ts";
90
- import { runPublicCoder, runPublicCoderResume } from "./coder-run.ts";
91
80
  import { runPublicInstructionSeat, runPublicInstructionSeatResume } from "./instruction-seat-run.ts";
92
- import { runPublicCollector, runPublicCollectorResume } from "./collector-run.ts";
93
- import { runPublicCountersign, runPublicCountersignResume } from "./countersign-run.ts";
94
- import { runPublicDiarist, runPublicDiaristResume } from "./diarist-run.ts";
95
- import { runPublicSecretariat, runPublicSecretariatResume } from "./secretariat-run.ts";
96
- import { runPublicGleanerLeft, runPublicGleanerLeftResume } from "./gleaner-left-run.ts";
97
- import { runPublicDoctor, runPublicDoctorResume } from "./doctor-run.ts";
98
- import { runPublicFixer, runPublicFixerResume } from "./fixer-run.ts";
99
- import { runPublicNotary, runPublicNotaryResume } from "./notary-run.ts";
100
- import { runPublicInspector, runPublicInspectorResume } from "./inspector-run.ts";
101
- import { runPublicJudge, runPublicResume } from "./judge-run.ts";
102
- import { runPublicMerger, runPublicMergerResume } from "./merger-run.ts";
103
- import { runPublicReviewer, runPublicReviewerResume } from "./reviewer-run.ts";
104
81
  import { runPublicAnalyst } from "./analyst-run.ts";
105
82
  import {
106
83
  AUTO_RESUME_LIMIT,
@@ -108,44 +85,9 @@ import {
108
85
  type PublicResumeRequest,
109
86
  } from "./run-lifecycle.ts";
110
87
 
111
- /**
112
- * Single authoritative resume dispatch (#633): durable role → seat + public
113
- * resume runner. Seat-specific loader validation, turn projection, and
114
- * adapters live in each seat's resume module.
115
- */
116
- const RESUME_SEAT_DISPATCH: Record<
117
- NonNullable<Awaited<ReturnType<typeof peekRoleRunRole>>>,
118
- {
119
- readonly seat: PublicCallableRole;
120
- readonly run: (
121
- request: PublicResumeRequest,
122
- env: PostAdmissionEnv,
123
- io: CliIo,
124
- ) => Promise<{
125
- exitCode: number;
126
- terminal?: TerminalResult;
127
- }>;
128
- }
129
- > = {
130
- judge: { seat: "judge", run: runPublicResume },
131
- coder: { seat: "coder", run: runPublicCoderResume },
132
- fixer: { seat: "fixer", run: runPublicFixerResume },
133
- reviewer: { seat: "reviewer", run: runPublicReviewerResume },
134
- merger: { seat: "merger", run: runPublicMergerResume },
135
- countersign: { seat: "countersign", run: runPublicCountersignResume },
136
- "gleaner-left": { seat: "gleaner-left", run: runPublicGleanerLeftResume },
137
- collector: { seat: "collector", run: runPublicCollectorResume },
138
- doctor: { seat: "doctor", run: runPublicDoctorResume },
139
- notary: { seat: "notary", run: runPublicNotaryResume },
140
- inspector: { seat: "inspector", run: runPublicInspectorResume },
141
- gatekeeper: { seat: "gatekeeper", run: runPublicInstructionSeatResume },
142
- navigator: { seat: "navigator", run: runPublicInstructionSeatResume },
143
- auditor: { seat: "auditor", run: runPublicInstructionSeatResume },
144
- diarist: { seat: "diarist", run: runPublicDiaristResume },
145
- secretariat: { seat: "secretariat", run: runPublicSecretariatResume },
146
- };
147
88
  import {
148
89
  INTERNAL_ROLE_ENTRYPOINT_RELATIVE,
90
+ PUBLIC_CALLABLE_ROLES,
149
91
  isPublicCallableRole,
150
92
  isPublicCliSupportCommand,
151
93
  isPublicConfigurableSeat,
@@ -169,29 +111,37 @@ export { CliUsageError } from "./cli-errors.ts";
169
111
  export type { CliIo } from "./cli-io.ts";
170
112
 
171
113
  /**
172
- * Sole production map: public role command → argv parser + option definitions.
173
- * cli handlers and help consume this table; no parallel spelling set (#342).
114
+ * Sole production map: public role command → one argv parse + that owner's option row.
115
+ * Seat option values are assigned in parsePublicSeatArgv. Analyst stays deterministic.
116
+ */
117
+ function publicSeatArgv(owner: PublicSeatArgvOwner) {
118
+ return {
119
+ parse: (args: readonly string[]) => parsePublicSeatArgv(owner, args),
120
+ options: optionsForOwner(owner),
121
+ };
122
+ }
123
+
124
+ type PublicRoleArgvTable = {
125
+ [K in PublicRoleOptionOwner]: K extends "analyst"
126
+ ? {
127
+ readonly parse: typeof parseAnalystArgv;
128
+ readonly options: readonly PublicOptionDefinition[];
129
+ }
130
+ : ReturnType<typeof publicSeatArgv>;
131
+ };
132
+
133
+ /**
134
+ * One argv row per public owner. Seats come from PUBLIC_ROLE_OPTION_OWNERS
135
+ * (composition-root roles plus the deterministic analyst command).
174
136
  */
175
- export const PUBLIC_ROLE_ARGV = {
176
- judge: { parse: parseJudgeArgv, options: optionsForOwner("judge") },
177
- countersign: { parse: parseCountersignArgv, options: optionsForOwner("countersign") },
178
- "gleaner-left": { parse: parseGleanerLeftArgv, options: optionsForOwner("gleaner-left") },
179
- coder: { parse: parseCoderArgv, options: optionsForOwner("coder") },
180
- fixer: { parse: parseFixerArgv, options: optionsForOwner("fixer") },
181
- collector: { parse: parseCollectorArgv, options: optionsForOwner("collector") },
182
- doctor: { parse: parseDoctorArgv, options: optionsForOwner("doctor") },
183
- merger: { parse: parseMergerArgv, options: optionsForOwner("merger") },
184
- notary: { parse: parseNotaryArgv, options: optionsForOwner("notary") },
185
- inspector: { parse: parseInspectorArgv, options: optionsForOwner("inspector") },
186
- reviewer: { parse: parseReviewerArgv, options: optionsForOwner("reviewer") },
187
- gatekeeper: { parse: parseGatekeeperArgv, options: optionsForOwner("gatekeeper") },
188
- navigator: { parse: parseNavigatorArgv, options: optionsForOwner("navigator") },
189
- auditor: { parse: parseAuditorArgv, options: optionsForOwner("auditor") },
190
- diarist: { parse: parseDiaristArgv, options: optionsForOwner("diarist") },
191
- secretariat: { parse: parseSecretariatArgv, options: optionsForOwner("secretariat") },
192
- /** Deterministic analysis seat (#336) — argv parse only; no LLM admission. */
193
- analyst: { parse: parseAnalystArgv, options: optionsForOwner("analyst") },
194
- } as const;
137
+ export const PUBLIC_ROLE_ARGV = Object.fromEntries(
138
+ PUBLIC_ROLE_OPTION_OWNERS.map((owner) => [
139
+ owner,
140
+ owner === "analyst"
141
+ ? { parse: parseAnalystArgv, options: optionsForOwner("analyst") }
142
+ : publicSeatArgv(owner),
143
+ ]),
144
+ ) as PublicRoleArgvTable;
195
145
 
196
146
  /** Global public options — same typed table as role rows (#342). */
197
147
  export const PUBLIC_GLOBAL_OPTIONS: readonly PublicOptionDefinition[] =
@@ -259,51 +209,25 @@ export type CliEnv = {
259
209
  io?: CliIo;
260
210
  /**
261
211
  * Injectable host-neutral turn host (tests). Production composes the Pi
262
- * adapter once per dispatch from packageRoot + seat extraPiArgs/timeout.
212
+ * adapter once per dispatch from packageRoot + extraPiArgs/timeout.
263
213
  */
264
214
  roleTurnHost?: RoleTurnHost;
265
215
  /** Composition-root-owned unique named adapter table. */
266
216
  hostAdapters?: readonly NamedRoleTurnHostAdapter[];
267
217
  /** Optional caller correlation id (#78 host channel). */
268
218
  correlationId?: string;
269
- /** Extra Pi args for Judge runs (tests: faux provider). */
270
- judgeExtraPiArgs?: readonly string[];
271
- /** Override Judge role-run timeout (tests). */
272
- judgeTimeoutMs?: number;
273
- /** Extra Pi args for Coder runs (tests: faux provider). */
274
- coderExtraPiArgs?: readonly string[];
275
- /** Override Coder role-run timeout (tests). */
276
- coderTimeoutMs?: number;
277
- /** Extra Pi args for Collector runs (tests: faux provider). */
278
- collectorExtraPiArgs?: readonly string[];
279
- /** Override Collector role-run timeout (tests). */
280
- collectorTimeoutMs?: number;
281
- /** Extra Pi args for Doctor runs (tests: faux provider). */
282
- doctorExtraPiArgs?: readonly string[];
283
- /** Override Doctor role-run timeout (tests). */
284
- doctorTimeoutMs?: number;
285
- /** Extra Pi args for Fixer runs (tests: faux provider). */
286
- fixerExtraPiArgs?: readonly string[];
287
- /** Override Fixer role-run timeout (tests). */
288
- fixerTimeoutMs?: number;
289
- /** Extra Pi args for Reviewer runs (tests: faux provider). */
290
- reviewerExtraPiArgs?: readonly string[];
291
- /** Override Reviewer role-run timeout (tests). */
292
- reviewerTimeoutMs?: number;
293
- /** Extra Pi args for Merger runs (tests: faux provider). */
294
- mergerExtraPiArgs?: readonly string[];
295
- /** Override Merger role-run timeout (tests). */
296
- mergerTimeoutMs?: number;
297
- /** Extra Pi args for Notary runs (tests: faux provider). */
298
- notaryExtraPiArgs?: readonly string[];
299
- /** Override Notary role-run timeout (tests). */
300
- notaryTimeoutMs?: number;
219
+ /** Extra Pi args for the dispatched public seat (tests: faux provider). */
220
+ extraPiArgs?: readonly string[];
221
+ /** Override the dispatched public seat's role-run timeout (tests). */
222
+ timeoutMs?: number;
301
223
  createRunId?: () => string;
302
224
  /**
303
225
  * #724: set by the `new` support verb before role dispatch; seat runners
304
226
  * skip same-ticket auto-resume. Not a public flag — the verb is the choice.
305
227
  */
306
228
  freshSummons?: true;
229
+ /** Typed ticket already on this summons. Not a public argv flag. */
230
+ boundTicketNumber?: number;
307
231
  /**
308
232
  * #855: process-level cancel (SIGTERM/SIGINT/SIGHUP). Nested turns receive
309
233
  * the same signal so hosts can gracefully stop children.
@@ -330,42 +254,8 @@ function createRoleEnvironment(
330
254
  afterHost?: () => void,
331
255
  ) {
332
256
  const role = options.role;
333
- const extraPiArgs =
334
- role === "coder"
335
- ? env.coderExtraPiArgs
336
- : role === "fixer"
337
- ? env.fixerExtraPiArgs
338
- : role === "reviewer"
339
- ? env.reviewerExtraPiArgs
340
- : role === "merger"
341
- ? env.mergerExtraPiArgs
342
- : role === "judge"
343
- ? env.judgeExtraPiArgs
344
- : role === "collector"
345
- ? env.collectorExtraPiArgs
346
- : role === "doctor"
347
- ? env.doctorExtraPiArgs
348
- : role === "notary"
349
- ? env.notaryExtraPiArgs
350
- : undefined;
351
- const timeoutMs =
352
- role === "coder"
353
- ? env.coderTimeoutMs
354
- : role === "fixer"
355
- ? env.fixerTimeoutMs
356
- : role === "reviewer"
357
- ? env.reviewerTimeoutMs
358
- : role === "merger"
359
- ? env.mergerTimeoutMs
360
- : role === "judge"
361
- ? env.judgeTimeoutMs
362
- : role === "collector"
363
- ? env.collectorTimeoutMs
364
- : role === "doctor"
365
- ? env.doctorTimeoutMs
366
- : role === "notary"
367
- ? env.notaryTimeoutMs
368
- : undefined;
257
+ const extraPiArgs = env.extraPiArgs;
258
+ const timeoutMs = env.timeoutMs;
369
259
 
370
260
  // #617/#178/#788/#840: host first, then model; nested child seat selects own host.
371
261
  const hostAdapters = composeRoleTurnHostAdapters(
@@ -417,6 +307,9 @@ function createRoleEnvironment(
417
307
  ? {}
418
308
  : { autoResumeLimit: options.config.autoResumeLimit }),
419
309
  ...(env.freshSummons === true ? { freshSummons: true as const } : {}),
310
+ ...(env.boundTicketNumber === undefined
311
+ ? {}
312
+ : { boundTicketNumber: env.boundTicketNumber }),
420
313
  ...(env.signal === undefined ? {} : { signal: env.signal }),
421
314
  };
422
315
  }
@@ -878,7 +771,7 @@ export function projectConfigSeatDisplay(
878
771
  seat: PublicConfigurableSeat,
879
772
  ): ConfigDisplaySeat {
880
773
  const disk = config.seats[seat];
881
- if (seat === "notary" || seat === "inspector") {
774
+ if (packagedModelParent(seat) !== undefined) {
882
775
  const resolved = resolveConfiguredProvinceOfficer(config, seat);
883
776
  return {
884
777
  seat,
@@ -913,8 +806,8 @@ export function projectConfigDisplaySeats(
913
806
  for (const seat of diskSeats) {
914
807
  rows.set(seat, projectConfigSeatDisplay(config, seat));
915
808
  }
916
- for (const seat of ["notary", "inspector"] as const) {
917
- if (rows.has(seat)) continue;
809
+ for (const seat of PUBLIC_CALLABLE_ROLES) {
810
+ if (packagedModelParent(seat) === undefined || rows.has(seat)) continue;
918
811
  const projected = projectConfigSeatDisplay(config, seat);
919
812
  if (projected.source === "inherit-gatekeeper") {
920
813
  rows.set(seat, projected);
@@ -1314,26 +1207,19 @@ export async function runAkRole(
1314
1207
  env.credentials ?? (await loadCredentialProviders(agentDir));
1315
1208
  const resumeRequest = parseResumeRequest(parsed.args);
1316
1209
  const resumeRole = await peekRoleRunRole(home, resumeRequest.runId);
1317
- // #633: single authoritative resume dispatch — the seat follows the
1318
- // durable admitted role; missing durable role keeps the judge path.
1319
- const dispatch =
1320
- resumeRole === undefined
1321
- ? RESUME_SEAT_DISPATCH.judge
1322
- : RESUME_SEAT_DISPATCH[resumeRole];
1323
- // #617 DK-4 / #178: resume resolves model/host/engine from the live seat
1324
- // table exactly as a new leg would (flag → persistent → officer inherit;
1325
- // model still none → error). Cross-host resume delivers prior native
1326
- // records as context to the target host.
1210
+ // Missing durable role keeps the judge seat table. The resume entry
1211
+ // itself is one function; it reads the stored run.
1212
+ const seatRole = resumeRole ?? "judge";
1327
1213
  const seat = resolveEffectiveSeat(
1328
1214
  config,
1329
- dispatch.seat,
1215
+ seatRole,
1330
1216
  credentials,
1331
1217
  invocationFromParsed(parsed),
1332
1218
  );
1333
- const result = await dispatch.run(
1219
+ const result = await runPublicInstructionSeatResume(
1334
1220
  resumeRequest,
1335
1221
  createRoleEnvironment(env, {
1336
- role: dispatch.seat,
1222
+ role: seatRole,
1337
1223
  home,
1338
1224
  agentDir,
1339
1225
  cwd,
@@ -1353,94 +1239,13 @@ export async function runAkRole(
1353
1239
  throw new CliUsageError(`unhandled support command: ${parsed.command}`);
1354
1240
  }
1355
1241
 
1356
- // Public LLM role commands share one #178 spine (host → argv once → missing-model → run).
1357
- if (parsed.command === "judge") {
1358
- return await dispatchPublicRoleCommand(
1359
- env, home, io, parsed, "judge", PUBLIC_ROLE_ARGV.judge.parse,
1360
- (args, roleEnv, once) => runPublicJudge(args, roleEnv, io, once),
1361
- );
1362
- }
1363
- if (parsed.command === "countersign") {
1364
- return await dispatchPublicRoleCommand(
1365
- env, home, io, parsed, "countersign", PUBLIC_ROLE_ARGV.countersign.parse,
1366
- (args, roleEnv, once) => runPublicCountersign(args, roleEnv, io, once),
1367
- );
1368
- }
1369
- if (parsed.command === "gleaner-left") {
1370
- return await dispatchPublicRoleCommand(
1371
- env, home, io, parsed, "gleaner-left", PUBLIC_ROLE_ARGV["gleaner-left"].parse,
1372
- (args, roleEnv, once) => runPublicGleanerLeft(args, roleEnv, io, once),
1373
- );
1374
- }
1375
- if (parsed.command === "diarist") {
1376
- return await dispatchPublicRoleCommand(
1377
- env, home, io, parsed, "diarist", PUBLIC_ROLE_ARGV.diarist.parse,
1378
- (args, roleEnv, once) => runPublicDiarist(args, roleEnv, io, once),
1379
- );
1380
- }
1381
- if (parsed.command === "secretariat") {
1382
- return await dispatchPublicRoleCommand(
1383
- env, home, io, parsed, "secretariat", PUBLIC_ROLE_ARGV.secretariat.parse,
1384
- (args, roleEnv, once) => runPublicSecretariat(args, roleEnv, io, once),
1385
- );
1386
- }
1387
- if (parsed.command === "coder") {
1388
- return await dispatchPublicRoleCommand(
1389
- env, home, io, parsed, "coder", PUBLIC_ROLE_ARGV.coder.parse,
1390
- (args, roleEnv, once) => runPublicCoder(args, roleEnv, io, once),
1391
- );
1392
- }
1393
- if (parsed.command === "fixer") {
1394
- return await dispatchPublicRoleCommand(
1395
- env, home, io, parsed, "fixer", PUBLIC_ROLE_ARGV.fixer.parse,
1396
- (args, roleEnv, once) => runPublicFixer(args, roleEnv, io, once),
1397
- );
1398
- }
1399
- if (parsed.command === "collector") {
1400
- return await dispatchPublicRoleCommand(
1401
- env, home, io, parsed, "collector", PUBLIC_ROLE_ARGV.collector.parse,
1402
- (args, roleEnv, once) => runPublicCollector(args, roleEnv, io, once),
1403
- );
1404
- }
1405
- if (parsed.command === "reviewer") {
1406
- return await dispatchPublicRoleCommand(
1407
- env, home, io, parsed, "reviewer", PUBLIC_ROLE_ARGV.reviewer.parse,
1408
- (args, roleEnv, once) => runPublicReviewer(args, roleEnv, io, once),
1409
- );
1410
- }
1411
- if (parsed.command === "doctor") {
1412
- return await dispatchPublicRoleCommand(
1413
- env, home, io, parsed, "doctor", PUBLIC_ROLE_ARGV.doctor.parse,
1414
- (args, roleEnv, once) => runPublicDoctor(args, roleEnv, io, once),
1415
- );
1416
- }
1417
- if (parsed.command === "notary") {
1418
- return await dispatchPublicRoleCommand(
1419
- env, home, io, parsed, "notary", PUBLIC_ROLE_ARGV.notary.parse,
1420
- (args, roleEnv, once) => runPublicNotary(args, roleEnv, io, once),
1421
- );
1422
- }
1423
- if (parsed.command === "inspector") {
1424
- return await dispatchPublicRoleCommand(
1425
- env, home, io, parsed, "inspector", PUBLIC_ROLE_ARGV.inspector.parse,
1426
- (args, roleEnv, once) => runPublicInspector(args, roleEnv, io, once),
1427
- );
1428
- }
1429
- if (parsed.command === "merger") {
1430
- return await dispatchPublicRoleCommand(
1431
- env, home, io, parsed, "merger", PUBLIC_ROLE_ARGV.merger.parse,
1432
- (args, roleEnv, once) => runPublicMerger(args, roleEnv, io, once),
1433
- );
1434
- }
1435
- if (
1436
- parsed.command === "gatekeeper"
1437
- || parsed.command === "navigator"
1438
- || parsed.command === "auditor"
1439
- ) {
1440
- const seat = parsed.command;
1242
+ // Public LLM role commands share one spine: registry parser → one runner.
1243
+ if (parsed.command !== undefined && isPublicCallableRole(parsed.command)) {
1244
+ const role = parsed.command;
1441
1245
  return await dispatchPublicRoleCommand(
1442
- env, home, io, parsed, seat, PUBLIC_ROLE_ARGV[seat].parse,
1443
- (args, roleEnv, once) => runPublicInstructionSeat(args, roleEnv, io, seat, once),
1246
+ env, home, io, parsed, role,
1247
+ (args) => PUBLIC_ROLE_ARGV[role].parse(args) as PublicSeatParse,
1248
+ (args, roleEnv, once) => runPublicInstructionSeat(args, roleEnv, io, role, once),
1444
1249
  );
1445
1250
  }
1446
1251
 
@@ -11,6 +11,11 @@ import {
11
11
  pickEngineAxis,
12
12
  } from "../package-resources/engine-material.ts";
13
13
  import { resolveConfiguredProvinceOfficer } from "../institutional-resolution.ts";
14
+ import {
15
+ PUBLIC_ROLE_RECORDS,
16
+ packagedModelParent,
17
+ packagedProvinceConfig,
18
+ } from "../packaged-role-registry.ts";
14
19
  import {
15
20
  PUBLIC_CALLABLE_ROLES,
16
21
  PUBLIC_CONFIGURABLE_SEATS,
@@ -23,17 +28,20 @@ import {
23
28
  type PublicThinkingLevel,
24
29
  } from "./registry.ts";
25
30
 
26
- /** Province officers that may carry a persistent model override (#453). */
27
- export const GATE_OFFICER_SEATS = [
28
- "gatekeeper",
29
- "inspector",
30
- "notary",
31
- ] as const;
31
+ /** Province officers that may carry a persistent model override (#453). Registry order. */
32
+ type ProvinceConfigRole = Extract<
33
+ (typeof PUBLIC_ROLE_RECORDS)[number],
34
+ { readonly provinceConfig: true }
35
+ >["role"];
36
+
37
+ export const GATE_OFFICER_SEATS: readonly ProvinceConfigRole[] = PUBLIC_ROLE_RECORDS.flatMap(
38
+ (record) => ("provinceConfig" in record && record.provinceConfig === true ? [record.role] : []),
39
+ );
32
40
 
33
41
  export type GateOfficerSeat = (typeof GATE_OFFICER_SEATS)[number];
34
42
 
35
43
  export function isGateOfficerSeat(value: string): value is GateOfficerSeat {
36
- return (GATE_OFFICER_SEATS as readonly string[]).includes(value);
44
+ return packagedProvinceConfig(value);
37
45
  }
38
46
 
39
47
  export type CredentialProviders = {
@@ -191,7 +199,7 @@ export function clearPersistentSeatConfig(
191
199
  if (previous === undefined) return config;
192
200
  // Callable province seats keep independent host/engine residuals after model clear.
193
201
  if (
194
- (seat === "notary" || seat === "inspector") &&
202
+ packagedModelParent(seat) !== undefined &&
195
203
  (previous.engine !== undefined || previous.host !== undefined)
196
204
  ) {
197
205
  return {
@@ -558,7 +566,7 @@ function parseSeatModelConfig(value: unknown, seat: string): PersistentSeatConfi
558
566
  // model clear. All other seats keep provider/model.
559
567
  if (!hasProvider) {
560
568
  if (
561
- (seat === "notary" || seat === "inspector") &&
569
+ packagedModelParent(seat) !== undefined &&
562
570
  (typeof raw.engine === "string" || typeof raw.host === "string")
563
571
  ) {
564
572
  if (raw.thinking !== undefined) {
@@ -715,7 +723,7 @@ function resolveBaseSeat(
715
723
  seat: PublicConfigurableSeat,
716
724
  ): UnhostedEffectiveSeat {
717
725
  // #620: subordinate officers consume institutional-resolution authority result.
718
- if (seat === "notary" || seat === "inspector") {
726
+ if (packagedModelParent(seat) !== undefined) {
719
727
  const resolved = resolveConfiguredProvinceOfficer(config, seat);
720
728
  return {
721
729
  seat,