@akagilnc/pi-workflow-roles 0.1.5015 → 0.1.5063

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 (95) hide show
  1. package/README.md +2 -2
  2. package/README.zh-CN.md +2 -2
  3. package/THIRD_PARTY_NOTICES.md +8 -8
  4. package/dist/acp-host/production-host.js +525 -978
  5. package/dist/headless-host/description.js +0 -2
  6. package/dist/headless-host/production-host.js +528 -1014
  7. package/dist/host-descriptions.js +2 -3
  8. package/dist/migrate-book-topology.js +7 -12
  9. package/dist/packaged-role-registry.js +20 -18
  10. package/dist/pi/role-turn-host.js +3 -27
  11. package/dist/public-cli/cli.js +23 -2
  12. package/dist/public-cli/countersign-run.js +13 -8
  13. package/dist/public-cli/instruction-seat-run.js +75 -107
  14. package/dist/public-cli/invocation.js +13 -32
  15. package/dist/public-cli/machine-method-skills.js +150 -0
  16. package/dist/public-cli/main.js +549 -679
  17. package/dist/public-cli/post-admission.js +10 -5
  18. package/dist/public-cli/registry.js +2 -1
  19. package/dist/public-cli/run-lifecycle.js +12 -15
  20. package/dist/public-cli/seat-ticket-binding.js +5 -8
  21. package/dist/public-cli/settlement.js +12 -99
  22. package/dist/public-cli/turn-request.js +16 -8
  23. package/dist/public-role-summons.js +8 -3
  24. package/package.json +5 -1
  25. package/resources/countersign-ticket-issue.md +5 -0
  26. package/resources/diarist-collect.md +1 -0
  27. package/resources/secretariat-ticket-identity.md +15 -0
  28. package/scripts/build-package.mjs +1 -6
  29. package/src/headless-host/description.ts +0 -3
  30. package/src/headless-host/role-turn-host.ts +2 -23
  31. package/src/host-contracts.ts +2 -23
  32. package/src/host-descriptions.ts +2 -3
  33. package/src/packaged-role-registry.ts +17 -16
  34. package/src/pi/adapter.ts +0 -27
  35. package/src/pi/role-turn-host.ts +3 -31
  36. package/src/public-cli/cli.ts +24 -2
  37. package/src/public-cli/countersign-run.ts +17 -10
  38. package/src/public-cli/instruction-seat-run.ts +75 -105
  39. package/src/public-cli/invocation.ts +10 -38
  40. package/src/public-cli/machine-method-skills.ts +153 -0
  41. package/src/public-cli/post-admission.ts +12 -6
  42. package/src/public-cli/registry.ts +1 -0
  43. package/src/public-cli/run-lifecycle.ts +12 -13
  44. package/src/public-cli/seat-ticket-binding.ts +5 -8
  45. package/src/public-cli/settlement.ts +6 -138
  46. package/src/public-cli/turn-request.ts +24 -16
  47. package/src/public-role-summons.ts +16 -3
  48. package/src/reviewer-role.ts +1 -12
  49. package/src/role-envelope.ts +0 -13
  50. package/src/role-runtime-dependencies.ts +0 -13
  51. package/src/role-runtime.ts +4 -56
  52. package/src/worker-role.ts +1 -81
  53. package/dist/method-host-plugin/.claude-plugin/plugin.json +0 -5
  54. package/dist/method-host-plugin/skills/ak-cross-m-review/CONTEXT.md +0 -48
  55. package/dist/method-host-plugin/skills/ak-cross-m-review/LICENSE +0 -21
  56. package/dist/method-host-plugin/skills/ak-cross-m-review/SKILL.md +0 -170
  57. package/dist/method-host-plugin/skills/ak-cross-m-review/prompts/cmr-completeness.md +0 -118
  58. package/dist/method-host-plugin/skills/ak-cross-m-review/prompts/cmr-reviewer.md +0 -128
  59. package/dist/method-host-plugin/skills/ak-cross-m-review/provenance.json +0 -41
  60. package/dist/method-host-plugin/skills/diagnosing-bugs/SKILL.md +0 -134
  61. package/dist/method-host-plugin/skills/diagnosing-bugs/agents/openai.yaml +0 -3
  62. package/dist/method-host-plugin/skills/diagnosing-bugs/provenance.json +0 -31
  63. package/dist/method-host-plugin/skills/diagnosing-bugs/scripts/hitl-loop.template.sh +0 -41
  64. package/dist/method-host-plugin/skills/resolving-merge-conflicts/SKILL.md +0 -14
  65. package/dist/method-host-plugin/skills/resolving-merge-conflicts/agents/openai.yaml +0 -3
  66. package/dist/method-host-plugin/skills/resolving-merge-conflicts/provenance.json +0 -26
  67. package/dist/method-host-plugin/skills/tdd/SKILL.md +0 -38
  68. package/dist/method-host-plugin/skills/tdd/agents/openai.yaml +0 -3
  69. package/dist/method-host-plugin/skills/tdd/mocking.md +0 -59
  70. package/dist/method-host-plugin/skills/tdd/provenance.json +0 -36
  71. package/dist/method-host-plugin/skills/tdd/tests.md +0 -77
  72. package/dist/package-resources/method-skill.js +0 -259
  73. package/resources/method-host-plugin/.claude-plugin/plugin.json +0 -5
  74. package/resources/methods/ak-cross-m-review/CONTEXT.md +0 -48
  75. package/resources/methods/ak-cross-m-review/LICENSE +0 -21
  76. package/resources/methods/ak-cross-m-review/SKILL.md +0 -170
  77. package/resources/methods/ak-cross-m-review/prompts/cmr-completeness.md +0 -118
  78. package/resources/methods/ak-cross-m-review/prompts/cmr-reviewer.md +0 -128
  79. package/resources/methods/ak-cross-m-review/provenance.json +0 -41
  80. package/resources/methods/diagnosing-bugs/SKILL.md +0 -134
  81. package/resources/methods/diagnosing-bugs/agents/openai.yaml +0 -3
  82. package/resources/methods/diagnosing-bugs/provenance.json +0 -31
  83. package/resources/methods/diagnosing-bugs/scripts/hitl-loop.template.sh +0 -41
  84. package/resources/methods/resolving-merge-conflicts/SKILL.md +0 -14
  85. package/resources/methods/resolving-merge-conflicts/agents/openai.yaml +0 -3
  86. package/resources/methods/resolving-merge-conflicts/provenance.json +0 -26
  87. package/resources/methods/tdd/SKILL.md +0 -38
  88. package/resources/methods/tdd/agents/openai.yaml +0 -3
  89. package/resources/methods/tdd/mocking.md +0 -59
  90. package/resources/methods/tdd/provenance.json +0 -36
  91. package/resources/methods/tdd/tests.md +0 -77
  92. package/src/canonical-skill-binding.ts +0 -118
  93. package/src/host-native-method.ts +0 -185
  94. package/src/package-resources/method-skill-binding.ts +0 -60
  95. package/src/package-resources/method-skill.ts +0 -363
@@ -1127,11 +1127,10 @@ async function runHasFormedSessionPrincipal(runDirectory: string): Promise<boole
1127
1127
  /**
1128
1128
  * Locate the latest retained run for one seat under a book (#637 / #747).
1129
1129
  * Same walk surface as findRunDirectoryById (listBookRunDirectories). Match by
1130
- * parent run path (officer / gate seats, #747 / #987). A typed ticket number
1131
- * does not select a run. runId is UUIDv7 — lexicographic max is latest among
1132
- * runs that formed a session principal. No parallel index. Public ticket-number
1133
- * selection of a prior run was deleted (#987 Result 7); callers use explicit
1134
- * `ak-role resume <runId>`.
1130
+ * parent run path (officer / gate seats, #747 / #987), narrowed to a supplied
1131
+ * typed ticket for same-ticket gate re-summons. runId is UUIDv7 — lexicographic
1132
+ * max is latest among runs that formed a session principal. No parallel index;
1133
+ * callers can use explicit `ak-role resume <runId>`.
1135
1134
  * Only a truly missing book directory means no history; damage/permission errors propagate.
1136
1135
  */
1137
1136
  export async function findLatestRunIdForSeatTicket(input: {
@@ -1148,12 +1147,8 @@ export async function findLatestRunIdForSeatTicket(input: {
1148
1147
  const bookDir = activationBookDirectory(ledgerHome, input.bookKey);
1149
1148
  let runDirectories: string[];
1150
1149
  try {
1151
- // A typed ticket narrows the existing walk surface to that ticket's runs;
1152
- // same-parent matching below still selects the actual prior leg.
1153
1150
  runDirectories = await listBookRunDirectories(
1154
- input.ticketNumber === undefined
1155
- ? bookDir
1156
- : join(bookDir, String(input.ticketNumber)),
1151
+ input.ticketNumber === undefined ? bookDir : join(bookDir, String(input.ticketNumber)),
1157
1152
  );
1158
1153
  } catch (error) {
1159
1154
  if (errorCodeOf(error) === "ENOENT") return undefined;
@@ -1167,7 +1162,9 @@ export async function findLatestRunIdForSeatTicket(input: {
1167
1162
  const runId = entry.slice(0, entry.length - suffix.length);
1168
1163
  if (runId.length === 0) continue;
1169
1164
  const parentPath = await readRunParentPath(runDirectory);
1170
- if (parentPath !== input.parentRunPath) continue;
1165
+ // The parent's ticket can change after this child was admitted. Within one
1166
+ // book the run leaf is its stable identity; directory placement is not.
1167
+ if (parentPath !== input.parentRunPath && basename(parentPath ?? "") !== basename(input.parentRunPath)) continue;
1171
1168
  // Durable fact: never resume-select a provisional that never formed principal.
1172
1169
  if (!(await runHasFormedSessionPrincipal(runDirectory))) continue;
1173
1170
  if (best === undefined || runId > best) best = runId;
@@ -1328,6 +1325,7 @@ async function loadResumableRunRecord(
1328
1325
  home: string,
1329
1326
  runId: string,
1330
1327
  authority: DurablePrincipalAuthority,
1328
+ allowUnformedAdmitted = false,
1331
1329
  ): Promise<{
1332
1330
  readonly run: RoleRunRecord;
1333
1331
  readonly principal: DurablePrincipal;
@@ -1350,7 +1348,7 @@ async function loadResumableRunRecord(
1350
1348
  throw new CliUsageError(`unknown role run id: ${runId}`);
1351
1349
  }
1352
1350
  const { run, principal } = materialized;
1353
- if (!(await isDurablePrincipalAvailable(principal, authority))) {
1351
+ if (!(allowUnformedAdmitted && run.state === "admitted") && !(await isDurablePrincipalAvailable(principal, authority))) {
1354
1352
  throw new CliUsageError(
1355
1353
  `role run Pi session principal is unavailable: ${runId}`,
1356
1354
  );
@@ -1757,8 +1755,9 @@ export async function loadResumablePublicRole(
1757
1755
  home: string,
1758
1756
  runId: string,
1759
1757
  authority: DurablePrincipalAuthority,
1758
+ allowUnformedAdmitted = false,
1760
1759
  ): Promise<LoadedResumablePublicRole> {
1761
- const loaded = await loadResumableRunRecord(home, runId, authority);
1760
+ const loaded = await loadResumableRunRecord(home, runId, authority, allowUnformedAdmitted);
1762
1761
  return seatLoadedResult(loaded, admitResumedRole(loaded));
1763
1762
  }
1764
1763
 
@@ -1,10 +1,9 @@
1
1
  /**
2
2
  * Shared same-parent resume seam for gate / officer seats (#635 / #637 / #747 / #987).
3
3
  *
4
- * Lookup key is parent run path only (#747 / #987 Result 7). Public seats no
5
- * longer select a prior run by ticket number — callers use explicit
6
- * `ak-role resume <runId>`. Officer and gate countersign same-parent re-summons
7
- * keep this seam. Lookup/resume failures propagate (失败诚实) — never wash into
4
+ * Lookup uses the parent run path; a typed ticket narrows same-ticket gate
5
+ * re-summons, never creates an issue identity. Callers can also use explicit
6
+ * `ak-role resume <runId>`. Lookup/resume failures propagate (失败诚实) — never wash into
8
7
  * a fresh mint. Returns undefined when the caller declared an explicit fresh
9
8
  * summons (`ak-role new`) or when no prior run exists; both mint new.
10
9
  * freshSummons is required so no seat can drift back into its own skip branch.
@@ -18,7 +17,7 @@ import {
18
17
 
19
18
  /**
20
19
  * Sole same-seat → resume decision by parent run path (#637 / #724 / #747 / #987).
21
- * A typed ticket number is a bind key, not a resume key. When a prior run is
20
+ * A supplied typed ticket only narrows the prior-run search. When a prior run is
22
21
  * found, resume carries this summons' materials. Lookup/resume failures
23
22
  * propagate (失败诚实) — never wash into a fresh mint. Returns undefined when
24
23
  * the caller declared an explicit fresh summons (`ak-role new`), the parent
@@ -45,9 +44,7 @@ export async function tryResumeSameTicketSeatRun<T>(input: {
45
44
  bookKey: resolveBookKeyFromGit(input.projectRoot),
46
45
  role: input.role,
47
46
  parentRunPath: input.parentRunPath,
48
- ...(input.ticketNumber === undefined
49
- ? {}
50
- : { ticketNumber: input.ticketNumber }),
47
+ ...(input.ticketNumber === undefined ? {} : { ticketNumber: input.ticketNumber }),
51
48
  });
52
49
  if (previousRunId === undefined) return undefined;
53
50
  return await input.resume(previousRunId, input.summons);
@@ -92,14 +92,6 @@ import {
92
92
  SECRETARIAT_COUNTERSIGN_TERMINAL_FACT_KEY,
93
93
  SECRETARIAT_GATE_OFFICER_ENTRY_TYPE,
94
94
  } from "../secretariat-contracts.ts";
95
- import {
96
- observePackagedMethodSkillInvocation,
97
- resolvePackagedMethodSkillPath,
98
- type ObservedPackagedMethodSkillInvocation,
99
- type PackagedMethodSkillMaterial,
100
- type PackagedMethodSkillName,
101
- type PackagedMethodSkillProvenance,
102
- } from "../package-resources/method-skill.ts";
103
95
  import {
104
96
  classifyPackagedRoleTerminalResult,
105
97
  findLatestDurablePackagedRoleTerminal,
@@ -2482,21 +2474,14 @@ async function publishAcceptedTerminalArtifacts(
2482
2474
  ];
2483
2475
  }
2484
2476
 
2485
- type MethodPublicationOptions = {
2486
- readonly methodProvenance?: PackagedMethodSkillProvenance;
2487
- readonly methodSkillPath?: string;
2488
- readonly methodSkillConfiguredPath?: string;
2489
- };
2490
-
2491
2477
  /** Publish one accepted seat's report/evidence face from the shared leaf table. */
2492
2478
  export async function publishSeatAcceptedArtifacts(
2493
2479
  admitted: AdmittedRoleInvocation,
2494
2480
  roleOutcome: TerminalRoleOutcome,
2495
2481
  coordinates: DurablePrincipalCoordinates,
2496
2482
  entries: readonly SessionEntry[] = [],
2497
- options: MethodPublicationOptions = {},
2498
2483
  ): Promise<TerminalArtifactRef[]> {
2499
- return publishDeclaredSeatArtifacts(admitted, roleOutcome, coordinates, entries, options);
2484
+ return publishDeclaredSeatArtifacts(admitted, roleOutcome, coordinates, entries);
2500
2485
  }
2501
2486
 
2502
2487
  /**
@@ -2623,13 +2608,12 @@ async function settleSealedAcceptedOrToolResidual(
2623
2608
  /**
2624
2609
  * One settlement for every registered seat. The registry `settlement` leaf
2625
2610
  * picks sealed ledger, sealed-or-residual, or the accepted-tool scan.
2626
- * Seat evidence and the observed-method tail stay on the artifact face.
2611
+ * Seat evidence stays on the artifact face.
2627
2612
  */
2628
2613
  async function settleSeat(
2629
2614
  admitted: AdmittedRoleInvocation,
2630
2615
  authority: DurablePrincipalAuthority,
2631
2616
  scope: SettlementCourtScope | undefined,
2632
- options: MethodPublicationOptions,
2633
2617
  ): Promise<TerminalResult | undefined> {
2634
2618
  const record = packagedRoleMetadata(admitted.role);
2635
2619
  if (record === undefined) {
@@ -2642,7 +2626,7 @@ async function settleSeat(
2642
2626
  roleOutcome: Extract<TerminalRoleOutcome, { kind: "accepted" | "audit_escalation" }>,
2643
2627
  coordinates: DurablePrincipalCoordinates,
2644
2628
  entries: readonly SessionEntry[],
2645
- ) => publishDeclaredSeatArtifacts(admitted, roleOutcome, coordinates, entries, options);
2629
+ ) => publishDeclaredSeatArtifacts(admitted, roleOutcome, coordinates, entries);
2646
2630
  if (record.settlement === "residual") {
2647
2631
  return settleSealedAcceptedOrToolResidual(
2648
2632
  admitted,
@@ -2669,10 +2653,9 @@ async function settleSeat(
2669
2653
  export async function trySettleSeatTerminalResult(
2670
2654
  admitted: AdmittedRoleInvocation,
2671
2655
  authority: DurablePrincipalAuthority,
2672
- options: MethodPublicationOptions = {},
2673
2656
  scope?: SettlementCourtScope,
2674
2657
  ): Promise<TerminalResult | undefined> {
2675
- return settleSeat(admitted, authority, scope, options);
2658
+ return settleSeat(admitted, authority, scope);
2676
2659
  }
2677
2660
 
2678
2661
  /**
@@ -2682,10 +2665,9 @@ export async function trySettleSeatTerminalResult(
2682
2665
  export async function settleSeatTerminalResult(
2683
2666
  admitted: AdmittedRoleInvocation,
2684
2667
  authority: DurablePrincipalAuthority,
2685
- options: MethodPublicationOptions = {},
2686
2668
  scope?: SettlementCourtScope,
2687
2669
  ): Promise<TerminalResult> {
2688
- const settled = await settleSeat(admitted, authority, scope, options);
2670
+ const settled = await settleSeat(admitted, authority, scope);
2689
2671
  if (settled === undefined) {
2690
2672
  const label = admitted.role.charAt(0).toUpperCase() + admitted.role.slice(1);
2691
2673
  throw new Error(
@@ -2695,71 +2677,6 @@ export async function settleSeatTerminalResult(
2695
2677
  return settled;
2696
2678
  }
2697
2679
 
2698
- function sessionMessageText(message: SessionMessage | undefined): string {
2699
- if (message === undefined) return "";
2700
- if (typeof message.content === "string") return message.content;
2701
- if (!Array.isArray(message.content)) return "";
2702
- const parts: string[] = [];
2703
- for (const part of message.content) {
2704
- if (
2705
- typeof part === "object" &&
2706
- part !== null &&
2707
- !Array.isArray(part) &&
2708
- (part as { type?: unknown }).type === "text" &&
2709
- typeof (part as { text?: unknown }).text === "string"
2710
- ) {
2711
- parts.push((part as { text: string }).text);
2712
- }
2713
- }
2714
- return parts.join("\n");
2715
- }
2716
-
2717
- /**
2718
- * Locations a loaded packaged method may be observed at.
2719
- * The name is the loaded material; the configured path is the package copy.
2720
- */
2721
- export function observedMethodSkillOptions(
2722
- packageRoot: string,
2723
- material: PackagedMethodSkillMaterial,
2724
- ): {
2725
- readonly methodProvenance: PackagedMethodSkillProvenance;
2726
- readonly methodSkillPath: string;
2727
- readonly methodSkillConfiguredPath: string;
2728
- } {
2729
- return {
2730
- methodProvenance: material.provenance,
2731
- methodSkillPath: material.skillPath,
2732
- methodSkillConfiguredPath: resolvePackagedMethodSkillPath(packageRoot, material.name),
2733
- };
2734
- }
2735
-
2736
- /**
2737
- * Observe packaged method Skill expansions from the session.
2738
- * The skill name is the caller's packaged method; home locations never count.
2739
- */
2740
- function extractObservedMethodInvocations(
2741
- entries: readonly SessionEntry[],
2742
- options: {
2743
- readonly name: PackagedMethodSkillName;
2744
- readonly allowedLocations: readonly string[];
2745
- },
2746
- ): readonly ObservedPackagedMethodSkillInvocation[] {
2747
- const observed: ObservedPackagedMethodSkillInvocation[] = [];
2748
- for (const entry of entries) {
2749
- if (entry?.type !== "message") continue;
2750
- const message = entry.message;
2751
- if (message?.role !== "user") continue;
2752
- const text = sessionMessageText(message);
2753
- if (text.length === 0) continue;
2754
- const hit = observePackagedMethodSkillInvocation(text, {
2755
- name: options.name,
2756
- allowedLocations: options.allowedLocations,
2757
- });
2758
- if (hit !== undefined) observed.push(hit);
2759
- }
2760
- return Object.freeze(observed);
2761
- }
2762
-
2763
2680
  /**
2764
2681
  * #836: cost and the auditor's no-receipt facts ride beside the role's
2765
2682
  * testimony on the current attempt's candidate entry. Absence is omitted,
@@ -2834,49 +2751,11 @@ function doctorReportFacts(
2834
2751
  };
2835
2752
  }
2836
2753
 
2837
- function observedMethodTail(
2838
- face: PackagedArtifactFace,
2839
- entries: readonly SessionEntry[],
2840
- options: {
2841
- readonly methodProvenance?: PackagedMethodSkillProvenance;
2842
- readonly methodSkillPath?: string;
2843
- readonly methodSkillConfiguredPath?: string;
2844
- },
2845
- ): Record<string, unknown> {
2846
- if (face.method === undefined) return {};
2847
- if (face.method === "optional") {
2848
- return options.methodProvenance === undefined
2849
- ? {}
2850
- : { methodProvenance: options.methodProvenance };
2851
- }
2852
- if (
2853
- options.methodProvenance === undefined
2854
- || options.methodSkillPath === undefined
2855
- || options.methodSkillConfiguredPath === undefined
2856
- ) {
2857
- throw new Error("observed method publication is missing packaged method coordinates");
2858
- }
2859
- const methodInvocations = extractObservedMethodInvocations(entries, {
2860
- name: options.methodProvenance.name,
2861
- allowedLocations: [options.methodSkillPath, options.methodSkillConfiguredPath],
2862
- });
2863
- return {
2864
- methodProvenance: options.methodProvenance,
2865
- methodInvocationObserved: methodInvocations.length > 0,
2866
- methodInvocations,
2867
- };
2868
- }
2869
-
2870
2754
  async function publishDeclaredSeatArtifacts(
2871
2755
  admitted: AdmittedRoleInvocation,
2872
2756
  roleOutcome: TerminalRoleOutcome,
2873
2757
  coordinates: DurablePrincipalCoordinates,
2874
2758
  entries: readonly SessionEntry[],
2875
- options: {
2876
- readonly methodProvenance?: PackagedMethodSkillProvenance;
2877
- readonly methodSkillPath?: string;
2878
- readonly methodSkillConfiguredPath?: string;
2879
- } = {},
2880
2759
  ): Promise<TerminalArtifactRef[]> {
2881
2760
  const face = seatArtifactFace(admitted.role);
2882
2761
  const phase = face.reportPhase === true
@@ -2898,7 +2777,6 @@ async function publishDeclaredSeatArtifacts(
2898
2777
  sessionFile: coordinates.sessionFile,
2899
2778
  admittedRequestPath: admitted.admittedRequestPath,
2900
2779
  attachments: acceptedArtifactAttachmentRefs(admitted.attachments),
2901
- ...observedMethodTail(face, entries, options),
2902
2780
  },
2903
2781
  });
2904
2782
  }
@@ -3040,18 +2918,8 @@ export async function trySettlePublicSeat(
3040
2918
  admitted: AdmittedRoleInvocation,
3041
2919
  authority: DurablePrincipalAuthority,
3042
2920
  scope: { readonly courtAttemptId?: string } | undefined,
3043
- material: PackagedMethodSkillMaterial | undefined,
3044
- packageRoot: string,
3045
2921
  ): Promise<TerminalResult | undefined> {
3046
- const face = seatArtifactFace(admitted.role);
3047
- if (face.method === "observed" && material === undefined) return undefined;
3048
- const options: MethodPublicationOptions =
3049
- face.method === "observed" && material !== undefined
3050
- ? observedMethodSkillOptions(packageRoot, material)
3051
- : face.method === "optional" && material !== undefined
3052
- ? { methodProvenance: material.provenance }
3053
- : {};
3054
- return settleSeat(admitted, authority, scope, options);
2922
+ return settleSeat(admitted, authority, scope);
3055
2923
  }
3056
2924
 
3057
2925
  /**
@@ -10,16 +10,13 @@ import type {
10
10
  RoleTurnRequest,
11
11
  } from "../host-contracts.ts";
12
12
  import { pickEngineAxis } from "../package-resources/engine-material.ts";
13
- import {
14
- resolvePackagedMethodSkillPath,
15
- type PackagedMethodSkillName,
16
- } from "../package-resources/method-skill.ts";
17
13
  import {
18
14
  packagedRoleActivationFlags,
19
15
  packagedRoleMetadata,
20
16
  } from "../packaged-role-registry.ts";
21
17
  import type { SeatModelConfig } from "./config.ts";
22
18
  import type { AdmittedRoleInvocation } from "./invocation.ts";
19
+ import { installedMethodSkillPath } from "./machine-method-skills.ts";
23
20
  import { parentRunPathFromGatePointerInstruction } from "./run-lifecycle.ts";
24
21
  import type { PublicThinkingLevel } from "./registry.ts";
25
22
 
@@ -33,6 +30,7 @@ export type ResumeModelConfig = {
33
30
  export type RoleTurnRequestProjectionOptions = {
34
31
  packageRoot: string;
35
32
  home: string;
33
+ host?: string;
36
34
  agentDir: string;
37
35
  model?: SeatModelConfig;
38
36
  engine?: string;
@@ -103,7 +101,7 @@ export function projectRoleTurnRequest(
103
101
  */
104
102
  export function packagedSettleSkill(
105
103
  admitted: AdmittedRoleInvocation,
106
- ): PackagedMethodSkillName | undefined {
104
+ ): string | undefined {
107
105
  const record = packagedRoleMetadata(admitted.role);
108
106
  if (record === undefined) return undefined;
109
107
  if ("applyMethod" in record && record.applyMethod !== undefined) {
@@ -148,33 +146,43 @@ function activationForAdmitted(admitted: AdmittedRoleInvocation): RoleTurnActiva
148
146
  }
149
147
 
150
148
  /** Skill bindings declared on the composition-root record for this admitted run. */
151
- function methodBindings(
152
- admitted: AdmittedRoleInvocation,
153
- packageRoot: string,
154
- ): readonly MethodBinding[] {
149
+ export function requiredMethodSkills(admitted: AdmittedRoleInvocation): readonly string[] {
155
150
  const record = packagedRoleMetadata(admitted.role);
156
- const names: PackagedMethodSkillName[] = [];
151
+ const names: string[] = [];
157
152
  if (record !== undefined && "methodSkills" in record && record.methodSkills !== undefined) {
158
153
  names.push(...record.methodSkills);
159
154
  }
160
155
  const apply = packagedSettleSkill(admitted);
161
156
  if (apply !== undefined && !names.includes(apply)) names.push(apply);
162
- return names.map((name) => ({
163
- kind: "skill" as const,
164
- path: resolvePackagedMethodSkillPath(packageRoot, name),
165
- }));
157
+ return names;
158
+ }
159
+
160
+ function methodBindings(
161
+ admitted: AdmittedRoleInvocation,
162
+ home: string,
163
+ host: string | undefined,
164
+ ): readonly MethodBinding[] {
165
+ if (host !== undefined && host !== "pi") return [];
166
+ return requiredMethodSkills(admitted).flatMap((name) => {
167
+ const path = installedMethodSkillPath(home, name);
168
+ return path === undefined ? [] : [{
169
+ kind: "skill" as const,
170
+ path,
171
+ }];
172
+ });
166
173
  }
167
174
 
168
175
  /** Registry activation and method bindings for one admitted public seat. */
169
176
  export function admittedSeatTurnDetails(
170
177
  admitted: AdmittedRoleInvocation,
171
- packageRoot: string,
178
+ home: string,
179
+ host: string | undefined,
172
180
  ): {
173
181
  readonly activation: RoleTurnActivation;
174
182
  readonly methods: readonly MethodBinding[];
175
183
  } {
176
184
  return {
177
185
  activation: activationForAdmitted(admitted),
178
- methods: methodBindings(admitted, packageRoot),
186
+ methods: methodBindings(admitted, home, host),
179
187
  };
180
188
  }
@@ -535,7 +535,16 @@ export async function summonPublicRole(
535
535
  }
536
536
 
537
537
  const stderr = captured?.stderrText();
538
- const runDirectory = result.admitted?.runDirectory;
538
+ // A parked officer can return its court diarist's escalation verbatim. The
539
+ // terminal's independent run, not the parked officer, is the gate pointer.
540
+ const runDirectory = result.terminal !== undefined
541
+ && result.terminal.roleOutcome.role !== options.role
542
+ && typeof result.terminal.runId === "string"
543
+ ? await (await import("./public-cli/run-lifecycle.ts")).findRunDirectoryById(
544
+ home,
545
+ result.terminal.runId,
546
+ )
547
+ : result.admitted?.runDirectory;
539
548
  return {
540
549
  exitCode: result.exitCode,
541
550
  ...(result.terminal === undefined ? {} : { terminal: result.terminal }),
@@ -851,8 +860,12 @@ export async function summonGateOfficer(options: {
851
860
  `countersign gate summon requires parent runId from sourceRunDirectory: ${options.sourceRunDirectory}`,
852
861
  );
853
862
  }
854
- const { readBoardTicketNumber } = await import("./run-ticket-number.ts");
863
+ const { isSafePositiveTicketNumber, readBoardTicketNumber } = await import("./run-ticket-number.ts");
855
864
  const parentTicket = await readBoardTicketNumber(options.sourceRunDirectory);
865
+ const submittedTicket = options.submission !== null && typeof options.submission === "object" && !Array.isArray(options.submission)
866
+ ? (options.submission as { ticketNumber?: unknown }).ticketNumber
867
+ : undefined;
868
+ const courtTicket = isSafePositiveTicketNumber(submittedTicket) ? submittedTicket : parentTicket;
856
869
  // Argv instruction = reask or parent payload bytes only (never a fabricated line).
857
870
  const instruction = options.reask ?? gateReviewInstruction ?? "";
858
871
  return summonPublicRole({
@@ -861,7 +874,7 @@ export async function summonGateOfficer(options: {
861
874
  ...common,
862
875
  correlationId,
863
876
  parentRunPath: options.sourceRunDirectory,
864
- ...(parentTicket === undefined ? {} : { boundTicketNumber: parentTicket }),
877
+ ...(courtTicket === undefined ? {} : { boundTicketNumber: courtTicket }),
865
878
  });
866
879
  }
867
880
  // Inspector: argv stays pure 卷宗指针 (#747 parentRunPath lookup key).
@@ -3,8 +3,6 @@ import { Type } from "typebox";
3
3
  import { openToolObjectFromUnion } from "./open-tool-schema.ts";
4
4
  import { withTerminatingOutputDeclarations } from "./package-contracts/terminating-infrastructure.ts";
5
5
 
6
- import type { AnyCanonicalSkillBinding, CanonicalSkillBinding } from "./canonical-skill-binding.ts";
7
- export type { CanonicalSkillBinding };
8
6
  import { REVIEWER_OUTPUT_TOOL_NAME, type ReviewerIntent } from "./package-contracts/reviewer-output.ts";
9
7
 
10
8
  export { REVIEWER_OUTPUT_TOOL_NAME };
@@ -59,7 +57,6 @@ export const reviewerOutputSchema = withTerminatingOutputDeclarations(
59
57
  );
60
58
  export type ReviewerRoleDependencies = {
61
59
  loadSoul(): Promise<string>;
62
- loadCanonicalSkillBinding(name: "ak-cross-m-review"): Promise<AnyCanonicalSkillBinding>;
63
60
  };
64
61
  export type ReviewerRoleHostActions = { failInfrastructure(error: unknown, ctx: HostContext, toolCallId?: string): never };
65
62
 
@@ -67,8 +64,6 @@ export type ReviewerRoleHostActions = { failInfrastructure(error: unknown, ctx:
67
64
  export type ReviewerActivation = Readonly<{
68
65
  fixedBaseRevision: string;
69
66
  soul: string;
70
- /** Frozen ak-cross-m-review binding — envelope owns expansion capture against this data. */
71
- skillBinding: CanonicalSkillBinding<"ak-cross-m-review">;
72
67
  }>;
73
68
 
74
69
  /**
@@ -84,7 +79,6 @@ export function createReviewerRoleRuntime(
84
79
  activate(ctx: HostContext | undefined, admitted: ReviewerAdmittedInputs): Promise<ReviewerActivation>;
85
80
  } {
86
81
  let soul: string | undefined;
87
- let binding: CanonicalSkillBinding<"ak-cross-m-review"> | undefined;
88
82
  let registered = false;
89
83
  let fixedBaseRevision: string | undefined;
90
84
 
@@ -93,15 +87,12 @@ export function createReviewerRoleRuntime(
93
87
  soul = (await dependencies.loadSoul()).trim();
94
88
  if (!soul) throw new Error("Reviewer soul is empty");
95
89
  fixedBaseRevision = admitted.baseRevision;
96
- const loaded = await dependencies.loadCanonicalSkillBinding("ak-cross-m-review");
97
- if (loaded.name !== "ak-cross-m-review") throw new Error("Canonical Skill binding loader returned tdd for ak-cross-m-review");
98
- binding = loaded;
99
90
 
100
91
  if (!registered) {
101
92
  registered = true;
102
93
  pi.registerTool({ name: REVIEWER_OUTPUT_TOOL_NAME, label: "御史台输出", description: "提交御史台终局回执。本席自调 ak-cross-m-review skill。", promptSnippet: "提交御史台终局回执", parameters: reviewerOutputSchema,
103
94
  async execute(_id: string, parameters: unknown): Promise<HostToolResult<unknown>> {
104
- if (!soul || !binding) throw new Error("御史台输入未装载");
95
+ if (!soul) throw new Error("御史台输入未装载");
105
96
  return {
106
97
  content: [],
107
98
  details: parameters,
@@ -111,11 +102,9 @@ export function createReviewerRoleRuntime(
111
102
  }
112
103
  const activatedSoul = soul;
113
104
  const activatedBase = fixedBaseRevision;
114
- const activatedBinding = binding;
115
105
  return Object.freeze({
116
106
  fixedBaseRevision: activatedBase,
117
107
  soul: activatedSoul,
118
- skillBinding: activatedBinding,
119
108
  });
120
109
  },
121
110
  };
@@ -22,7 +22,6 @@ import type {
22
22
  RoleTurnKnownFailure,
23
23
  RoleTurnRequest,
24
24
  } from "./host-contracts.ts";
25
- import { hostMethodSkills, installWorkspaceMethodSkills } from "./host-native-method.ts";
26
25
  import { packagedRoleOutputTool } from "./packaged-role-registry.ts";
27
26
  import {
28
27
  createRoleRuntimeExtension,
@@ -219,10 +218,6 @@ export async function prepareRoleEnvelope(options: {
219
218
  deliverSubmissionRejection(_value) {
220
219
  // #836 删 1/A4.5: do not arm closeRound retry with「终局交卷并非本轮唯一工具调用」.
221
220
  },
222
- capabilities: {
223
- // #922: native loaders own expansion; package does not pre-read bodies (ADR 0032).
224
- skillExpansion() { return undefined; },
225
- },
226
221
  registerFlag(name, definition) { if (!flags.has(name) && definition.default !== undefined) flags.set(name, definition.default); },
227
222
  getFlag(name) { return flags.get(name); },
228
223
  registerTool(tool) { tools.set(tool.name, tool); },
@@ -730,14 +725,6 @@ export async function prepareRoleEnvelope(options: {
730
725
  }
731
726
  const jsonSchema = terminatingToolJsonSchema(terminating.parameters);
732
727
 
733
- if (request.host === "codex" && hostMethodSkills(request.methods).length > 0) {
734
- const packageRoot = options.dependencies.packageRoot;
735
- if (typeof packageRoot !== "string" || packageRoot === "") {
736
- throw new Error("codex project Skill catalog requires packageRoot");
737
- }
738
- await installWorkspaceMethodSkills(request.cwd, packageRoot);
739
- }
740
-
741
728
  return {
742
729
  mcpServers: [{
743
730
  name: `ak-${request.activation.role}`,
@@ -7,7 +7,6 @@ import { loadDoctorCase } from "./doctor-evidence.ts";
7
7
  import { createNativeNavigatorSessionFactory, createNavigatorAttendance } from "./navigator-attendance.ts";
8
8
  import { loadNavigatorWorkContext } from "./navigator-work-context.ts";
9
9
  import { loadNotarySourceRunLocator } from "./notary-source-run.ts";
10
- import { loadPackagedCanonicalSkillBinding } from "./package-resources/method-skill-binding.ts";
11
10
  import { formatNavigatorRoleHelp, type RoleRuntimeDependencies } from "./role-runtime.ts";
12
11
  import {
13
12
  loadAuditorReferenceMaterialsFromSubjectInput,
@@ -58,18 +57,6 @@ export function createRoleRuntimeDependencies(packageRoot: string): RoleRuntimeD
58
57
  loadDoctorCase,
59
58
  loadNotarySourceRun: loadNotarySourceRunLocator,
60
59
  loadMergerInput: async (path) => JSON.parse(await readFile(path, "utf8")),
61
- async loadCanonicalSkillBinding(name) {
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
- }
72
- },
73
60
  // #590: doctor compliance still on disposeCompliance path; judge→auditor is gate queue (#756).
74
61
  auditDoctorCompliance: (options) => doctorAuditor(options),
75
62
  loadNavigatorWorkContext: (options) => loadNavigatorWorkContext({