@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
@@ -7,11 +7,20 @@ import type {
7
7
  DurablePrincipal,
8
8
  MethodBinding,
9
9
  RoleTurnActivation,
10
- RoleTurnModelConfig,
11
10
  RoleTurnRequest,
12
11
  } from "../host-contracts.ts";
13
12
  import { pickEngineAxis } from "../package-resources/engine-material.ts";
13
+ import {
14
+ resolvePackagedMethodSkillPath,
15
+ type PackagedMethodSkillName,
16
+ } from "../package-resources/method-skill.ts";
17
+ import {
18
+ packagedRoleActivationFlags,
19
+ packagedRoleMetadata,
20
+ } from "../packaged-role-registry.ts";
14
21
  import type { SeatModelConfig } from "./config.ts";
22
+ import type { AdmittedRoleInvocation } from "./invocation.ts";
23
+ import { parentRunPathFromGatePointerInstruction } from "./run-lifecycle.ts";
15
24
  import type { PublicThinkingLevel } from "./registry.ts";
16
25
 
17
26
  /** Structural model shape shared by the seam so seat/env sources fit. */
@@ -93,3 +102,85 @@ export function projectRoleTurnRequest(
93
102
  ...(options.stationChild === undefined ? {} : { stationChild: options.stationChild }),
94
103
  };
95
104
  }
105
+
106
+ /**
107
+ * Packaged method this admitted run settles with.
108
+ * Coder carries one only on apply. Other seats read `settleMethod`.
109
+ */
110
+ export function packagedSettleSkill(
111
+ admitted: AdmittedRoleInvocation,
112
+ ): PackagedMethodSkillName | undefined {
113
+ const record = packagedRoleMetadata(admitted.role);
114
+ if (record === undefined) return undefined;
115
+ if ("applyMethod" in record && record.applyMethod !== undefined) {
116
+ return "phase" in admitted && admitted.phase === "apply" ? record.applyMethod : undefined;
117
+ }
118
+ if ("settleMethod" in record && record.settleMethod !== undefined) return record.settleMethod;
119
+ return undefined;
120
+ }
121
+
122
+ function readAdmittedPath(admitted: AdmittedRoleInvocation, path: string): unknown {
123
+ let current: unknown = admitted;
124
+ for (const key of path.split(".")) {
125
+ if (current === null || typeof current !== "object") return undefined;
126
+ current = (current as Record<string, unknown>)[key];
127
+ }
128
+ return current;
129
+ }
130
+
131
+ /** Activation object for one admitted run. Field copies come from the composition-root record. */
132
+ function activationForAdmitted(admitted: AdmittedRoleInvocation): RoleTurnActivation {
133
+ if (packagedRoleMetadata(admitted.role) === undefined) {
134
+ throw new Error(`no turn projection for ${admitted.role}`);
135
+ }
136
+ const activation: Record<string, unknown> = { role: admitted.role };
137
+ for (const spec of packagedRoleActivationFlags(admitted.role)) {
138
+ let value = readAdmittedPath(admitted, spec.from ?? spec.field);
139
+ if (spec.fallback === "gate-pointer") {
140
+ const trimmed = typeof value === "string" ? value.trim() : "";
141
+ value = trimmed !== ""
142
+ ? trimmed
143
+ : parentRunPathFromGatePointerInstruction(admitted.instruction);
144
+ if (typeof value !== "string" || value === "") continue;
145
+ }
146
+ if (value === undefined) continue;
147
+ if (spec.text === true) {
148
+ if (typeof value !== "number") continue;
149
+ value = String(value);
150
+ }
151
+ activation[spec.field] = value;
152
+ }
153
+ return activation as RoleTurnActivation;
154
+ }
155
+
156
+ /** Skill bindings declared on the composition-root record for this admitted run. */
157
+ function methodBindings(
158
+ admitted: AdmittedRoleInvocation,
159
+ packageRoot: string,
160
+ ): readonly MethodBinding[] {
161
+ const record = packagedRoleMetadata(admitted.role);
162
+ const names: PackagedMethodSkillName[] = [];
163
+ if (record !== undefined && "methodSkills" in record && record.methodSkills !== undefined) {
164
+ names.push(...record.methodSkills);
165
+ }
166
+ const apply = packagedSettleSkill(admitted);
167
+ if (apply !== undefined && !names.includes(apply)) names.push(apply);
168
+ return names.map((name) => ({
169
+ kind: "skill" as const,
170
+ path: resolvePackagedMethodSkillPath(packageRoot, name),
171
+ }));
172
+ }
173
+
174
+ /** Registry activation and method bindings for one admitted public seat. */
175
+ export function admittedSeatTurnDetails(
176
+ admitted: AdmittedRoleInvocation,
177
+ packageRoot: string,
178
+ ): {
179
+ readonly activation: RoleTurnActivation;
180
+ readonly methods: readonly MethodBinding[];
181
+ } {
182
+ return {
183
+ activation: activationForAdmitted(admitted),
184
+ methods: methodBindings(admitted, packageRoot),
185
+ };
186
+ }
@@ -498,132 +498,45 @@ export async function summonPublicRole(
498
498
  return { ok: await run(prepared.env, () => parsedArgv) };
499
499
  }
500
500
 
501
+ const [{ runPublicInstructionSeat, runPublicInstructionSeatResume }, { PUBLIC_ROLE_ARGV }] = await Promise.all([
502
+ import("./public-cli/instruction-seat-run.ts"),
503
+ import("./public-cli/cli.ts"),
504
+ ]);
505
+ const { packagedRoleMetadata } = await import("./packaged-role-registry.ts");
506
+ const record = packagedRoleMetadata(options.role);
507
+ const parse = ((args: readonly string[]) =>
508
+ PUBLIC_ROLE_ARGV[options.role].parse(args)) as (args: readonly string[]) => import("./public-cli/invocation.ts").PublicSeatParse;
509
+ const resumeRunId = record?.summonResume === true
510
+ && typeof options.resumeRunId === "string"
511
+ && options.resumeRunId.trim() !== ""
512
+ ? options.resumeRunId.trim()
513
+ : undefined;
501
514
  let result: {
502
515
  exitCode: number;
503
516
  terminal?: TerminalResult;
504
517
  admitted?: { readonly runDirectory?: string };
505
518
  };
506
- switch (options.role) {
507
- case "notary": {
508
- const [{ runPublicNotary }, { parseNotaryArgv }] = await Promise.all([
509
- import("./public-cli/notary-run.ts"),
510
- import("./public-cli/invocation.ts"),
511
- ]);
512
- const stepped = await runPrepared(parseNotaryArgv, (env, once) =>
513
- runPublicNotary(options.argv, env as never, io, once));
514
- if ("fail" in stepped) return stepped.fail;
515
- result = stepped.ok;
516
- break;
517
- }
518
- case "inspector": {
519
- const [{ runPublicInspector }, { parseInspectorArgv }] = await Promise.all([
520
- import("./public-cli/inspector-run.ts"),
521
- import("./public-cli/invocation.ts"),
522
- ]);
523
- const stepped = await runPrepared(parseInspectorArgv, (env, once) =>
524
- runPublicInspector(options.argv, env as never, io, once));
525
- if ("fail" in stepped) return stepped.fail;
526
- result = stepped.ok;
527
- break;
528
- }
529
- case "auditor":
530
- case "navigator":
531
- case "gatekeeper": {
532
- const seat = options.role;
533
- const [{ runPublicInstructionSeat, runPublicInstructionSeatResume }, invocation] = await Promise.all([
534
- import("./public-cli/instruction-seat-run.ts"),
535
- import("./public-cli/invocation.ts"),
536
- ]);
537
- const parse =
538
- seat === "auditor"
539
- ? invocation.parseAuditorArgv
540
- : seat === "navigator"
541
- ? invocation.parseNavigatorArgv
542
- : invocation.parseGatekeeperArgv;
543
- const resumeRunId = typeof options.resumeRunId === "string" && options.resumeRunId.trim() !== ""
544
- ? options.resumeRunId.trim()
545
- : undefined;
546
- if (resumeRunId !== undefined) {
547
- // Host CLI resume — same face as `ak-role resume <runId> [message]`.
548
- // Instruction/materials ride summons.instruction (not package memory).
549
- const instruction = options.argv[0] ?? "";
550
- const stepped = await runPrepared(parse, (env) =>
551
- runPublicInstructionSeatResume(
552
- {
553
- runId: resumeRunId,
554
- summons: {
555
- instruction,
556
- instructionEmpty: instruction.trim() === "",
557
- },
558
- },
559
- env as never,
560
- io,
561
- ));
562
- if ("fail" in stepped) return stepped.fail;
563
- result = stepped.ok;
564
- } else {
565
- const stepped = await runPrepared(parse, (env, once) =>
566
- runPublicInstructionSeat(options.argv, env as never, io, seat, once));
567
- if ("fail" in stepped) return stepped.fail;
568
- result = stepped.ok;
569
- }
570
- break;
571
- }
572
- case "judge": {
573
- const [{ runPublicJudge }, { parseJudgeArgv }] = await Promise.all([
574
- import("./public-cli/judge-run.ts"),
575
- import("./public-cli/invocation.ts"),
576
- ]);
577
- const stepped = await runPrepared(parseJudgeArgv, (env, once) =>
578
- runPublicJudge(options.argv, env as never, io, once));
579
- if ("fail" in stepped) return stepped.fail;
580
- result = stepped.ok;
581
- break;
582
- }
583
- case "doctor": {
584
- const [{ runPublicDoctor }, { parseDoctorArgv }] = await Promise.all([
585
- import("./public-cli/doctor-run.ts"),
586
- import("./public-cli/invocation.ts"),
587
- ]);
588
- const stepped = await runPrepared(parseDoctorArgv, (env, once) =>
589
- runPublicDoctor(options.argv, env as never, io, once));
590
- if ("fail" in stepped) return stepped.fail;
591
- result = stepped.ok;
592
- break;
593
- }
594
- case "diarist": {
595
- const [{ runPublicDiarist }, { parseDiaristArgv }] = await Promise.all([
596
- import("./public-cli/diarist-run.ts"),
597
- import("./public-cli/invocation.ts"),
598
- ]);
599
- const stepped = await runPrepared(parseDiaristArgv, (env, once) =>
600
- runPublicDiarist(options.argv, env as never, io, once));
601
- if ("fail" in stepped) return stepped.fail;
602
- result = stepped.ok;
603
- break;
604
- }
605
- case "countersign": {
606
- const [{ runPublicCountersign }, { parseCountersignArgv }] = await Promise.all([
607
- import("./public-cli/countersign-run.ts"),
608
- import("./public-cli/invocation.ts"),
609
- ]);
610
- const stepped = await runPrepared(parseCountersignArgv, (env, once) =>
611
- runPublicCountersign(options.argv, env as never, io, once));
612
- if ("fail" in stepped) return stepped.fail;
613
- result = stepped.ok;
614
- break;
615
- }
616
- case "reviewer": {
617
- const [{ runPublicReviewer }, { parseReviewerArgv }] = await Promise.all([
618
- import("./public-cli/reviewer-run.ts"),
619
- import("./public-cli/invocation.ts"),
620
- ]);
621
- const stepped = await runPrepared(parseReviewerArgv, (env, once) =>
622
- runPublicReviewer(options.argv, env as never, io, once));
623
- if ("fail" in stepped) return stepped.fail;
624
- result = stepped.ok;
625
- break;
626
- }
519
+ if (resumeRunId !== undefined) {
520
+ const instruction = options.argv[0] ?? "";
521
+ const stepped = await runPrepared(parse, (env) =>
522
+ runPublicInstructionSeatResume(
523
+ {
524
+ runId: resumeRunId,
525
+ summons: {
526
+ instruction,
527
+ instructionEmpty: instruction.trim() === "",
528
+ },
529
+ },
530
+ env as never,
531
+ io,
532
+ ));
533
+ if ("fail" in stepped) return stepped.fail;
534
+ result = stepped.ok;
535
+ } else {
536
+ const stepped = await runPrepared(parse, (env, once) =>
537
+ runPublicInstructionSeat(options.argv, env as never, io, options.role, once));
538
+ if ("fail" in stepped) return stepped.fail;
539
+ result = stepped.ok;
627
540
  }
628
541
 
629
542
  const stderr = captured?.stderrText();
@@ -1105,20 +1018,22 @@ export async function summonGateOfficer(options: {
1105
1018
  ...(options.hostAdapters === undefined ? {} : { hostAdapters: options.hostAdapters }),
1106
1019
  ...(options.createRunId === undefined ? {} : { createRunId: options.createRunId }),
1107
1020
  } as const;
1108
- if (options.officer === "notary") {
1021
+ const { packagedGateSummon } = await import("./packaged-role-registry.ts");
1022
+ const gateSummon = packagedGateSummon(options.officer);
1023
+ if (gateSummon === "source-run") {
1109
1024
  // #753/#879: reask or verbatim body rides summons.instruction / first-mint prompt.
1110
1025
  // Binding stays --source-run (never folded into content).
1111
1026
  return summonPublicRole({
1112
- role: "notary",
1027
+ role: options.officer,
1113
1028
  argv: ["--source-run", options.sourceRunDirectory, "--project", options.cwd],
1114
1029
  ...common,
1115
1030
  });
1116
1031
  }
1117
- if (options.officer === "auditor") {
1032
+ if (gateSummon === "subject-source") {
1118
1033
  // #756: judge compliance path — same queue law as notary/inspector.
1119
1034
  // Binding pointer on argv; dialogue content rides gateReviewInstruction.
1120
1035
  return summonPublicRole({
1121
- role: "auditor",
1036
+ role: options.officer,
1122
1037
  argv: [
1123
1038
  "--subject",
1124
1039
  "judge",
@@ -1129,13 +1044,14 @@ export async function summonGateOfficer(options: {
1129
1044
  ...common,
1130
1045
  });
1131
1046
  }
1132
- if (options.officer === "countersign") {
1047
+ if (gateSummon === "parent-instruction") {
1133
1048
  // #969 / #987: Secretariat submission gate → 给事中.
1134
1049
  // Dialogue / identity instruction = parent typed payload 原话 (ADR 0079) or reask;
1135
1050
  // no code-authored summons prose (#924). Gate resume key = parentRunPath
1136
1051
  // (sourceRunDirectory); board ticket handoff is bind-only, never a resume
1137
1052
  // lookup (#987 Result 7). Receipt ticketNumber stays payload content.
1138
1053
  // correlationId only on this officer — notary/auditor/inspector stay untouched.
1054
+ // Gate resume key is the parent run directory. The board ticket only binds.
1139
1055
  const { runIdFromRunDirectory } = await import("./run-terminal-artifacts.ts");
1140
1056
  const correlationId = runIdFromRunDirectory(options.sourceRunDirectory);
1141
1057
  if (correlationId === undefined || correlationId.trim() === "") {
@@ -1148,7 +1064,7 @@ export async function summonGateOfficer(options: {
1148
1064
  // Argv instruction = reask or parent payload bytes only (never a fabricated line).
1149
1065
  const instruction = options.reask ?? gateReviewInstruction ?? "";
1150
1066
  return summonPublicRole({
1151
- role: "countersign",
1067
+ role: options.officer,
1152
1068
  argv: ["--project", options.cwd, "--", instruction],
1153
1069
  ...common,
1154
1070
  correlationId,
@@ -1159,7 +1075,7 @@ export async function summonGateOfficer(options: {
1159
1075
  // Inspector: argv stays pure 卷宗指针 (#747 parentRunPath lookup key).
1160
1076
  // Content (body/reask) rides env → summons.instruction / first-mint prompt.
1161
1077
  return summonPublicRole({
1162
- role: "inspector",
1078
+ role: options.officer,
1163
1079
  argv: [`卷宗指针:${options.sourceRunDirectory}`],
1164
1080
  ...common,
1165
1081
  });
@@ -5,7 +5,8 @@ import { withTerminatingOutputDeclarations } from "./package-contracts/terminati
5
5
 
6
6
  import type { AnyCanonicalSkillBinding, CanonicalSkillBinding } from "./canonical-skill-binding.ts";
7
7
  export type { CanonicalSkillBinding };
8
- import { REVIEWER_ACCEPTED_TEXT, REVIEWER_OUTPUT_TOOL_NAME, type ReviewerIntent } from "./package-contracts/reviewer-output.ts";
8
+ import { packagedRoleAcceptedText } from "./packaged-role-registry.ts";
9
+ import { REVIEWER_OUTPUT_TOOL_NAME, type ReviewerIntent } from "./package-contracts/reviewer-output.ts";
9
10
 
10
11
  export { REVIEWER_OUTPUT_TOOL_NAME };
11
12
  export type { ReviewerIntent };
@@ -103,7 +104,7 @@ export function createReviewerRoleRuntime(
103
104
  async execute(_id: string, parameters: unknown): Promise<HostToolResult<unknown>> {
104
105
  if (!soul || !binding) throw new Error("御史台输入未装载");
105
106
  return {
106
- content: [{ type: "text" as const, text: REVIEWER_ACCEPTED_TEXT }],
107
+ content: [{ type: "text" as const, text: packagedRoleAcceptedText("reviewer") }],
107
108
  details: parameters,
108
109
  terminate: true as const,
109
110
  };
@@ -4,54 +4,33 @@
4
4
  * Host adapters only deliver these flags (ACP/headless getFlag map; pi argv pairs).
5
5
  */
6
6
  import type { RoleTurnRequest } from "./host-contracts.ts";
7
- import { packagedRoleInputFlag, packagedRolePhaseFlag } from "./packaged-role-registry.ts";
7
+ import { packagedRoleActivationFlags } from "./packaged-role-registry.ts";
8
8
 
9
- /** Project closed RoleTurnActivation onto the shared host flag map. */
9
+ /**
10
+ * Project closed RoleTurnActivation onto the shared host flag map.
11
+ * Seat flag names and fields come from the composition-root record.
12
+ * countersign ticketNumber stays off this map (no private transport flag, #632).
13
+ */
10
14
  export function projectActivationFlags(request: RoleTurnRequest): Map<string, boolean | string> {
11
15
  const activation = request.activation;
12
16
  const flags = new Map<string, boolean | string>([["ak-role", activation.role]]);
13
17
  if (request.stationChild === true) {
14
18
  flags.set("ak-station-child", true);
15
19
  }
16
- const inputFlag = packagedRoleInputFlag(activation.role);
17
- const phaseFlag = packagedRolePhaseFlag(activation.role);
18
- if ("phase" in activation && phaseFlag !== undefined) flags.set(phaseFlag, activation.phase);
19
- if (inputFlag !== undefined) {
20
- const path = "taskPath" in activation ? activation.taskPath
21
- : "packetPath" in activation ? activation.packetPath
22
- : "casePath" in activation ? activation.casePath
23
- : "inputPath" in activation ? activation.inputPath
24
- : "sourceRun" in activation ? activation.sourceRun
25
- : undefined;
26
- if (path !== undefined) flags.set(inputFlag, path);
27
- }
28
- if (activation.role === "fixer" && activation.prerequisitesPath !== undefined) {
29
- flags.set("ak-fixer-prerequisites", activation.prerequisitesPath);
30
- }
31
- if (activation.role === "reviewer") {
32
- flags.set("ak-review-base", activation.baseRevision);
33
- flags.set("ak-review-lens", activation.lens);
34
- flags.set("ak-review-authority-refs", JSON.stringify(activation.authorityRefs));
35
- if (activation.ticketNumber !== undefined) {
36
- flags.set("ak-review-ticket-number", String(activation.ticketNumber));
37
- }
38
- }
39
- // countersign ticketNumber stays on activation/admission/invocation only —
40
- // no private transport flag (inner-gate material path deleted in #632).
41
- if (activation.role === "notary" && activation.ticketNumber !== undefined) {
42
- flags.set("ak-notary-ticket-number", String(activation.ticketNumber));
43
- }
44
- if (activation.role === "gleaner-left") {
45
- flags.set("ak-gleaner-left-base", activation.baseRevision);
46
- }
47
- if (activation.role === "collector") {
48
- flags.set("ak-collector-repo", activation.repo);
49
- // #676 D1: pr optional at admission; omit flag when role binds from materials.
50
- if (activation.pr !== undefined) flags.set("ak-collector-pr", activation.pr);
51
- if (activation.requestManifestPath !== undefined) {
52
- flags.set("ak-collector-request-manifest", activation.requestManifestPath);
53
- }
54
- if (activation.waitMs !== undefined) flags.set("ak-collector-wait-ms", activation.waitMs);
20
+ const values = activation as Record<string, unknown>;
21
+ for (const spec of packagedRoleActivationFlags(activation.role)) {
22
+ if (spec.flag === undefined) continue;
23
+ const text = activationFlagText(values[spec.field]);
24
+ if (text !== undefined) flags.set(spec.flag, text);
55
25
  }
56
26
  return flags;
57
27
  }
28
+
29
+ function activationFlagText(value: unknown): string | undefined {
30
+ if (typeof value === "string") return value;
31
+ if (typeof value === "number") return String(value);
32
+ if (Array.isArray(value) && value.every((item) => typeof item === "string")) {
33
+ return JSON.stringify(value);
34
+ }
35
+ return undefined;
36
+ }
@@ -1,7 +1,6 @@
1
1
  import { readFile } from "node:fs/promises";
2
2
  import { join } from "node:path";
3
3
 
4
- import { loadCanonicalSkillBinding as loadHomeCanonicalSkillBinding } from "./canonical-skill-binding.ts";
5
4
  import { createGhCollectorGitHubTransport } from "./collector-github.ts";
6
5
  import { createPiDoctorAuditor } from "./doctor-auditor.ts";
7
6
  import { loadDoctorCase } from "./doctor-evidence.ts";
@@ -14,19 +13,31 @@ import {
14
13
  loadAuditorReferenceMaterialsFromSubjectInput,
15
14
  loadAuditorSoulFromSubjectInput,
16
15
  } from "./auditor-soul.ts";
16
+ import { packagedRoleMetadata, type PackagedRole } from "./packaged-role-registry.ts";
17
17
  import {
18
- loadGatekeeperSessionMaterials,
19
18
  loadMainRoleReferenceMaterials,
20
19
  loadMainRoleSessionMaterials,
21
20
  } from "./session-opening-materials.ts";
22
21
 
22
+ function usesSubjectSoul(role: string): boolean {
23
+ const record = packagedRoleMetadata(role);
24
+ return record !== undefined && "soulSource" in record && record.soulSource === "subject";
25
+ }
26
+
23
27
  /** Single packaged source for reference materials across production composition roots. */
24
28
  export function loadPackagedRoleReferenceMaterials(role: Parameters<NonNullable<RoleRuntimeDependencies["loadRoleReferenceMaterials"]>>[0]): Promise<string> {
25
- return role === "auditor"
29
+ return usesSubjectSoul(role)
26
30
  ? loadAuditorReferenceMaterialsFromSubjectInput()
27
31
  : loadMainRoleReferenceMaterials(role);
28
32
  }
29
33
 
34
+ /** One production soul loader. Subject seats read the subject input; every other seat reads its record. */
35
+ export function loadRegisteredRoleSoul(role: PackagedRole): Promise<string> {
36
+ return usesSubjectSoul(role)
37
+ ? loadAuditorSoulFromSubjectInput()
38
+ : loadMainRoleSessionMaterials(role);
39
+ }
40
+
30
41
  /** Host-neutral packaged role runtime deps for the parent-process envelope. */
31
42
  export function createRoleRuntimeDependencies(packageRoot: string): RoleRuntimeDependencies {
32
43
  // packageRoot is the install root (resources/ lives there). Never resolve via
@@ -39,37 +50,25 @@ export function createRoleRuntimeDependencies(packageRoot: string): RoleRuntimeD
39
50
  return {
40
51
  packageRoot,
41
52
  loadRoleReferenceMaterials: loadPackagedRoleReferenceMaterials,
42
- loadJudgeSoul: () => loadMainRoleSessionMaterials("judge"),
43
- loadFixerSoul: () => loadMainRoleSessionMaterials("fixer"),
53
+ loadRoleSoul: loadRegisteredRoleSoul,
44
54
  loadFixPacket: (path) => readFile(path, "utf8"),
45
- loadCoderSoul: () => loadMainRoleSessionMaterials("coder"),
46
55
  loadCoderTask: (path) => readFile(path, "utf8"),
47
- loadReviewerSoul: () => loadMainRoleSessionMaterials("reviewer"),
48
- loadCollectorSoul: () => loadMainRoleSessionMaterials("collector"),
49
56
  loadCollectorHandbookSeed: () => readFile(collectorHandbookSeedPath, "utf8"),
50
57
  createCollectorTransport: () => createGhCollectorGitHubTransport(),
51
- loadDoctorSoul: () => loadMainRoleSessionMaterials("doctor"),
52
58
  loadDoctorCase,
53
- loadInspectorSoul: () => loadMainRoleSessionMaterials("inspector"),
54
- loadGatekeeperSoul: () => loadGatekeeperSessionMaterials("gatekeeper"),
55
- loadNavigatorSoul: () => loadMainRoleSessionMaterials("navigator"),
56
- loadAuditorSoul: () => loadAuditorSoulFromSubjectInput(),
57
- loadNotarySoul: () => loadMainRoleSessionMaterials("notary"),
58
- loadCountersignSoul: () => loadMainRoleSessionMaterials("countersign"),
59
- loadGleanerLeftSoul: () => loadMainRoleSessionMaterials("gleaner-left"),
60
- loadDiaristSoul: () => loadMainRoleSessionMaterials("diarist"),
61
- loadSecretariatSoul: () => loadMainRoleSessionMaterials("secretariat"),
62
59
  loadNotarySourceRun: loadNotarySourceRunLocator,
63
- loadMergerSoul: () => loadMainRoleSessionMaterials("merger"),
64
60
  loadMergerInput: async (path) => JSON.parse(await readFile(path, "utf8")),
65
61
  async loadCanonicalSkillBinding(name) {
66
- if (name === "tdd") {
67
- return loadPackagedCanonicalSkillBinding(packageRoot, "tdd");
68
- }
69
- if (name === "ak-cross-m-review") {
70
- return loadPackagedCanonicalSkillBinding(packageRoot, "ak-cross-m-review");
62
+ switch (name) {
63
+ case "tdd":
64
+ return loadPackagedCanonicalSkillBinding(packageRoot, name);
65
+ case "ak-cross-m-review":
66
+ return loadPackagedCanonicalSkillBinding(packageRoot, name);
67
+ default: {
68
+ const unexpected: never = name;
69
+ throw new Error(`Canonical skill is not packaged: ${String(unexpected)}`);
70
+ }
71
71
  }
72
- return loadHomeCanonicalSkillBinding(name);
73
72
  },
74
73
  // #590: doctor compliance still on disposeCompliance path; judge→auditor is gate queue (#756).
75
74
  auditDoctorCompliance: (options) => doctorAuditor(options),
@@ -86,7 +85,7 @@ export function createRoleRuntimeDependencies(packageRoot: string): RoleRuntimeD
86
85
  subject: options.subject,
87
86
  authority: options.authority,
88
87
  invocationId: options.invocationId,
89
- loadSoul: () => loadMainRoleSessionMaterials("navigator"),
88
+ loadSoul: () => loadRegisteredRoleSoul("navigator"),
90
89
  loadRoutePlaybook: () => readFile(navigatorRoutePlaybookPath, "utf8"),
91
90
  loadRoleHelp: async (role) => formatNavigatorRoleHelp(role),
92
91
  createSession: navigatorSessionFactory,