@akagilnc/pi-workflow-roles 0.1.1751

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 (192) hide show
  1. package/LICENSE +202 -0
  2. package/README.md +104 -0
  3. package/README.zh-CN.md +133 -0
  4. package/THIRD_PARTY_NOTICES.md +60 -0
  5. package/dist/activation-ledger-git.js +68 -0
  6. package/dist/activation-ledger-session.js +120 -0
  7. package/dist/activation-ledger-topology.js +239 -0
  8. package/dist/activation-reconciliation.js +61 -0
  9. package/dist/audit-escalation.js +108 -0
  10. package/dist/auditor-dossier-tool.js +35 -0
  11. package/dist/canonical-json.js +78 -0
  12. package/dist/compliance-transport.js +77 -0
  13. package/dist/doctor-contracts.js +172 -0
  14. package/dist/dossier-resolution.js +103 -0
  15. package/dist/evidence-child-executor.js +661 -0
  16. package/dist/exact-utf8.js +12 -0
  17. package/dist/git-object-id.js +7 -0
  18. package/dist/in-process-session.js +50 -0
  19. package/dist/merger-contracts.js +76 -0
  20. package/dist/navigator-attendance.js +995 -0
  21. package/dist/navigator-invocation-identity.js +220 -0
  22. package/dist/open-tool-schema.js +39 -0
  23. package/dist/package-contracts/collector-output.js +50 -0
  24. package/dist/package-contracts/fixer-output.js +72 -0
  25. package/dist/package-contracts/fixer-packet.js +77 -0
  26. package/dist/package-contracts/judge-output.js +17 -0
  27. package/dist/package-contracts/reviewer-output.js +82 -0
  28. package/dist/package-contracts/terminating-tools.js +173 -0
  29. package/dist/package-contracts/worker-output.js +13 -0
  30. package/dist/package-owned-tool-idle.js +104 -0
  31. package/dist/packaged-role-registry.js +34 -0
  32. package/dist/public-cli/main.js +23867 -0
  33. package/dist/public-command-renderer.js +20 -0
  34. package/dist/reviewer-agent.js +93 -0
  35. package/dist/reviewer-child-executor.js +23 -0
  36. package/dist/reviewer-construction.js +95 -0
  37. package/dist/reviewer-dispatch.js +77 -0
  38. package/dist/reviewer-execution-ledger.js +160 -0
  39. package/dist/reviewer-failure-diagnostic.js +17 -0
  40. package/dist/reviewer-git-snapshot.js +38 -0
  41. package/dist/reviewer-pinned-git.js +146 -0
  42. package/dist/reviewer-preflight-error.js +15 -0
  43. package/dist/reviewer-prompt-identity.js +10 -0
  44. package/dist/reviewer-scope-prompt.js +21 -0
  45. package/dist/reviewer-workspace.js +151 -0
  46. package/dist/sha256.js +5 -0
  47. package/dist/sitian-record-entry.js +33 -0
  48. package/dist/stderr-jsonl.js +26 -0
  49. package/dist/stream-idle-guard.js +75 -0
  50. package/dist/tool-execution-observation.js +141 -0
  51. package/dist/uuidv7.js +21 -0
  52. package/dist/work-subject-identity.js +53 -0
  53. package/extensions/role-runtime.ts +303 -0
  54. package/package.json +69 -0
  55. package/packets/fixer-prerequisites.json +6 -0
  56. package/packets/fixer-repair.md +5 -0
  57. package/packets/judge-apply.md +77 -0
  58. package/packets/judge-authority.md +64 -0
  59. package/packets/judge-plan.md +55 -0
  60. package/packets/judge-review.md +49 -0
  61. package/packets/judge-submission.md +34 -0
  62. package/resources/methods/code-review/SKILL.md +92 -0
  63. package/resources/methods/code-review/agents/openai.yaml +3 -0
  64. package/resources/methods/code-review/provenance.json +26 -0
  65. package/resources/methods/diagnosing-bugs/SKILL.md +134 -0
  66. package/resources/methods/diagnosing-bugs/agents/openai.yaml +3 -0
  67. package/resources/methods/diagnosing-bugs/provenance.json +31 -0
  68. package/resources/methods/diagnosing-bugs/scripts/hitl-loop.template.sh +41 -0
  69. package/resources/methods/resolving-merge-conflicts/SKILL.md +14 -0
  70. package/resources/methods/resolving-merge-conflicts/agents/openai.yaml +3 -0
  71. package/resources/methods/resolving-merge-conflicts/provenance.json +26 -0
  72. package/resources/methods/tdd/SKILL.md +38 -0
  73. package/resources/methods/tdd/agents/openai.yaml +3 -0
  74. package/resources/methods/tdd/mocking.md +59 -0
  75. package/resources/methods/tdd/provenance.json +36 -0
  76. package/resources/methods/tdd/tests.md +77 -0
  77. package/resources/navigator-route-playbook.md +32 -0
  78. package/schemas/tool-execution-observation.schema.json +107 -0
  79. package/scripts/build-package.mjs +65 -0
  80. package/scripts/generate-tool-execution-observation-schema.ts +7 -0
  81. package/souls/coder.md +10 -0
  82. package/souls/collector.md +11 -0
  83. package/souls/doctor-auditor.md +23 -0
  84. package/souls/doctor.md +8 -0
  85. package/souls/fixer-auditor.md +33 -0
  86. package/souls/fixer.md +13 -0
  87. package/souls/judge-auditor.md +33 -0
  88. package/souls/judge.md +74 -0
  89. package/souls/merger.md +5 -0
  90. package/souls/navigator.md +5 -0
  91. package/souls/reviewer-auditor.md +25 -0
  92. package/souls/reviewer.md +11 -0
  93. package/src/activation-ledger-git.ts +96 -0
  94. package/src/activation-ledger-session.ts +188 -0
  95. package/src/activation-ledger-topology.ts +301 -0
  96. package/src/activation-ledger.ts +240 -0
  97. package/src/activation-reconciliation.ts +163 -0
  98. package/src/activation-trace.ts +38 -0
  99. package/src/audit-escalation.ts +177 -0
  100. package/src/auditor-dossier-tool.ts +48 -0
  101. package/src/auditor-soul.ts +28 -0
  102. package/src/canonical-json.ts +74 -0
  103. package/src/canonical-skill-binding.ts +107 -0
  104. package/src/collector-config.ts +89 -0
  105. package/src/collector-evidence.ts +461 -0
  106. package/src/collector-github.ts +656 -0
  107. package/src/collector-identity.ts +161 -0
  108. package/src/collector-ledger.ts +827 -0
  109. package/src/collector-receipt.ts +87 -0
  110. package/src/collector-role.ts +592 -0
  111. package/src/collector-tool-schemas.ts +19 -0
  112. package/src/compliance-transport.ts +130 -0
  113. package/src/doctor-auditor.ts +53 -0
  114. package/src/doctor-contracts.ts +166 -0
  115. package/src/doctor-evidence.ts +47 -0
  116. package/src/doctor-role.ts +18 -0
  117. package/src/dossier-resolution.ts +137 -0
  118. package/src/evidence-child-executor.ts +775 -0
  119. package/src/exact-utf8.ts +9 -0
  120. package/src/factory-board.ts +1822 -0
  121. package/src/git-object-id.ts +11 -0
  122. package/src/human-format.ts +65 -0
  123. package/src/in-process-session.ts +78 -0
  124. package/src/judge-auditor.ts +55 -0
  125. package/src/judge-recording-anti-forge.ts +53 -0
  126. package/src/judge-role.ts +160 -0
  127. package/src/merger-contracts.ts +71 -0
  128. package/src/merger-git-state.ts +76 -0
  129. package/src/merger-role.ts +60 -0
  130. package/src/navigator-attendance.ts +1254 -0
  131. package/src/navigator-invocation-identity.ts +446 -0
  132. package/src/open-tool-schema.ts +46 -0
  133. package/src/package-contracts/collector-output.ts +109 -0
  134. package/src/package-contracts/fixer-output.ts +81 -0
  135. package/src/package-contracts/fixer-packet.ts +93 -0
  136. package/src/package-contracts/judge-output.ts +39 -0
  137. package/src/package-contracts/reviewer-output.ts +115 -0
  138. package/src/package-contracts/terminating-tools.ts +259 -0
  139. package/src/package-contracts/worker-output.ts +36 -0
  140. package/src/package-owned-tool-idle.ts +134 -0
  141. package/src/package-resources/method-skill-binding.ts +87 -0
  142. package/src/package-resources/method-skill.ts +358 -0
  143. package/src/packaged-role-registry.ts +36 -0
  144. package/src/public-cli/cli-errors.ts +11 -0
  145. package/src/public-cli/cli-io.ts +4 -0
  146. package/src/public-cli/cli.ts +912 -0
  147. package/src/public-cli/coder-run.ts +575 -0
  148. package/src/public-cli/collector-run.ts +375 -0
  149. package/src/public-cli/command-renderer.ts +8 -0
  150. package/src/public-cli/config.ts +346 -0
  151. package/src/public-cli/doctor-run.ts +355 -0
  152. package/src/public-cli/explicit-internal.ts +274 -0
  153. package/src/public-cli/fixer-run.ts +587 -0
  154. package/src/public-cli/host-pi-runtime.ts +112 -0
  155. package/src/public-cli/invocation.ts +1958 -0
  156. package/src/public-cli/judge-run.ts +507 -0
  157. package/src/public-cli/main.ts +15 -0
  158. package/src/public-cli/merger-run.ts +681 -0
  159. package/src/public-cli/public-run-credentials.ts +71 -0
  160. package/src/public-cli/registry.ts +153 -0
  161. package/src/public-cli/reviewer-run.ts +561 -0
  162. package/src/public-cli/run-lifecycle.ts +884 -0
  163. package/src/public-cli/settlement.ts +3765 -0
  164. package/src/public-cli/terminal.ts +325 -0
  165. package/src/public-command-renderer.ts +43 -0
  166. package/src/reviewer-agent.ts +94 -0
  167. package/src/reviewer-auditor.ts +53 -0
  168. package/src/reviewer-child-executor.ts +31 -0
  169. package/src/reviewer-construction.ts +137 -0
  170. package/src/reviewer-dispatch.ts +94 -0
  171. package/src/reviewer-execution-ledger.ts +206 -0
  172. package/src/reviewer-failure-diagnostic.ts +18 -0
  173. package/src/reviewer-git-snapshot.ts +53 -0
  174. package/src/reviewer-pinned-git.ts +144 -0
  175. package/src/reviewer-preflight-error.ts +14 -0
  176. package/src/reviewer-prompt-identity.ts +17 -0
  177. package/src/reviewer-role.ts +193 -0
  178. package/src/reviewer-scope-prompt.ts +24 -0
  179. package/src/reviewer-settlement.ts +63 -0
  180. package/src/reviewer-workspace.ts +111 -0
  181. package/src/role-runtime.ts +884 -0
  182. package/src/sha256.ts +6 -0
  183. package/src/sitian-record-entry.ts +57 -0
  184. package/src/stderr-jsonl.ts +28 -0
  185. package/src/stream-idle-guard.ts +98 -0
  186. package/src/ticket-snapshot.ts +662 -0
  187. package/src/ticket-trajectory.ts +1000 -0
  188. package/src/tool-execution-observation.ts +168 -0
  189. package/src/uuidv7.ts +1 -0
  190. package/src/work-subject-identity.ts +94 -0
  191. package/src/worker-role.ts +434 -0
  192. package/src/worker-submission-gates.ts +225 -0
@@ -0,0 +1,681 @@
1
+ /**
2
+ * Public Merger Role run: derive active-merge envelope → force package
3
+ * merge-only method → explicit Internal activate → settle Terminal result (#114).
4
+ * Controlled-failure settlement reuses the #107 shared owner.
5
+ */
6
+ import { mkdir, writeFile } from "node:fs/promises";
7
+ import { join, resolve } from "node:path";
8
+
9
+ import { resolveBookKeyFromGit } from "../activation-ledger-git.ts";
10
+ import {
11
+ activationBookDirectory,
12
+ ensureRealDirectoryTree,
13
+ resolveActivationLedgerHome,
14
+ } from "../activation-ledger-topology.ts";
15
+ import {
16
+ loadPackagedMethodSkillMaterial,
17
+ resolvePackagedMethodSkillPath,
18
+ type PackagedMethodSkillMaterial,
19
+ type PackagedMethodSkillProvenance,
20
+ } from "../package-resources/method-skill.ts";
21
+ import { uuidv7 } from "../uuidv7.ts";
22
+ import {
23
+ runExplicitInternalActivation,
24
+ type ExplicitInternalKnownFailure,
25
+ type ExplicitInternalPiRunner,
26
+ type ExplicitInternalPiResult,
27
+ } from "./explicit-internal.ts";
28
+ import { CliUsageError } from "./cli-errors.ts";
29
+ import {
30
+ admitMergerInvocation,
31
+ buildMergerTransportPrompt,
32
+ MergerEnvelopeDerivationError,
33
+ roleRunSessionFile,
34
+ type AdmittedMergerInvocation,
35
+ } from "./invocation.ts";
36
+ import {
37
+ type CredentialProviders,
38
+ type SeatModelConfig,
39
+ } from "./config.ts";
40
+ import {
41
+ missingCredentialPreDispatchFailure,
42
+ postRunMissingCredentialFailure,
43
+ } from "./public-run-credentials.ts";
44
+ import {
45
+ acquireRunWriterLease,
46
+ clearTypedProviderHttpObservation,
47
+ isSessionPrincipalAvailable,
48
+ isV1ResumableFailure,
49
+ loadResumableMergerRun,
50
+ markRunAdmitted,
51
+ markRunResumable,
52
+ markRunRunning,
53
+ markRunTerminal,
54
+ renderResumeCommand,
55
+ RESUME_TRANSPORT_ENVELOPE,
56
+ RunWriterLeaseHeldError,
57
+ type RunWriterLease,
58
+ readTypedHttp429Observation,
59
+ } from "./run-lifecycle.ts";
60
+ import {
61
+ classifyPostAdmissionFailure,
62
+ exitCodeForTerminalOutcome,
63
+ formatCliDiagnostic,
64
+ formatTerminalResult,
65
+ hasLawfulMergerTerminalResult,
66
+ inspectJudgeSession,
67
+ presentFailureTerminal,
68
+ presentStructuralRejection,
69
+ explicitInternalKnownFailureClassificationInput,
70
+ resolveAuditedRunnerKnownFailure,
71
+ settleFailureTerminalResult,
72
+ trySettleMergerTerminalResult,
73
+ } from "./settlement.ts";
74
+ import type { CliIo } from "./cli-io.ts";
75
+ import type {
76
+ ControlledFailureCause,
77
+ TerminalResult,
78
+ } from "./terminal.ts";
79
+
80
+ export type MergerRunEnv = {
81
+ home: string;
82
+ agentDir: string;
83
+ packageRoot: string;
84
+ cwd: string;
85
+ correlationId?: string;
86
+ piRunner?: ExplicitInternalPiRunner;
87
+ model?: SeatModelConfig;
88
+ credentials?: CredentialProviders;
89
+ createRunId?: () => string;
90
+ extraPiArgs?: readonly string[];
91
+ timeoutMs?: number;
92
+ };
93
+
94
+ function buildModelArgs(model: SeatModelConfig | undefined): string[] {
95
+ if (model === undefined) return [];
96
+ return [
97
+ "--provider",
98
+ model.provider,
99
+ "--model",
100
+ model.model,
101
+ "--thinking",
102
+ model.thinking,
103
+ ];
104
+ }
105
+
106
+ /**
107
+ * Build Internal activation extra-args for an admitted Merger run.
108
+ * Package resolving-merge-conflicts Skill is forced via --skill; ambient home off.
109
+ * Transport prompt forces `/skill:resolving-merge-conflicts` expansion first.
110
+ */
111
+ export function buildMergerActivationExtraArgs(
112
+ admitted: AdmittedMergerInvocation,
113
+ options: {
114
+ packageRoot: string;
115
+ model?: SeatModelConfig;
116
+ extraPiArgs?: readonly string[];
117
+ },
118
+ ): string[] {
119
+ const prompt = buildMergerTransportPrompt(admitted);
120
+ const skillPath = resolvePackagedMethodSkillPath(
121
+ options.packageRoot,
122
+ "resolving-merge-conflicts",
123
+ );
124
+ return [
125
+ "--no-skills",
126
+ "--skill",
127
+ skillPath,
128
+ "--no-prompt-templates",
129
+ "--no-themes",
130
+ "--no-context-files",
131
+ "--session",
132
+ admitted.sessionFile,
133
+ "--session-dir",
134
+ admitted.sessionDirectory,
135
+ ...(options.extraPiArgs ?? []),
136
+ "--ak-role",
137
+ "merger",
138
+ "--ak-merger-input",
139
+ admitted.mergerInputPath,
140
+ "--mode",
141
+ "json",
142
+ ...buildModelArgs(options.model),
143
+ prompt,
144
+ ];
145
+ }
146
+
147
+ /**
148
+ * Reopen the exact Merger Pi session for resume. Preserves derived input and
149
+ * package method binding; does not resubmit the original instruction.
150
+ */
151
+ export function buildMergerResumeActivationExtraArgs(
152
+ admitted: AdmittedMergerInvocation,
153
+ options: {
154
+ packageRoot: string;
155
+ model?: SeatModelConfig;
156
+ extraPiArgs?: readonly string[];
157
+ },
158
+ ): string[] {
159
+ const skillPath = resolvePackagedMethodSkillPath(
160
+ options.packageRoot,
161
+ "resolving-merge-conflicts",
162
+ );
163
+ return [
164
+ "--no-skills",
165
+ "--skill",
166
+ skillPath,
167
+ "--no-prompt-templates",
168
+ "--no-themes",
169
+ "--no-context-files",
170
+ "--session",
171
+ admitted.sessionFile,
172
+ "--session-dir",
173
+ admitted.sessionDirectory,
174
+ ...(options.extraPiArgs ?? []),
175
+ "--ak-role",
176
+ "merger",
177
+ "--ak-merger-input",
178
+ admitted.mergerInputPath,
179
+ "--mode",
180
+ "json",
181
+ ...buildModelArgs(options.model),
182
+ RESUME_TRANSPORT_ENVELOPE,
183
+ ];
184
+ }
185
+
186
+ async function presentControlledFailure(
187
+ admitted: AdmittedMergerInvocation,
188
+ failureInput: {
189
+ timedOut: boolean;
190
+ code: number | null;
191
+ stderr: string;
192
+ thrown?: unknown;
193
+ knownFailure?: ExplicitInternalKnownFailure;
194
+ knownCause?: ControlledFailureCause;
195
+ knownIdentity?: {
196
+ readonly name?: string;
197
+ readonly code?: string | number;
198
+ };
199
+ knownDiagnostic?: string;
200
+ },
201
+ io: CliIo,
202
+ ): Promise<{
203
+ exitCode: number;
204
+ admitted: AdmittedMergerInvocation;
205
+ terminal: TerminalResult;
206
+ }> {
207
+ const hasThrown = Object.hasOwn(failureInput, "thrown");
208
+ const session =
209
+ !hasThrown &&
210
+ !failureInput.timedOut &&
211
+ failureInput.knownFailure === undefined &&
212
+ failureInput.knownCause === undefined
213
+ ? await inspectJudgeSession(admitted.sessionFile)
214
+ : undefined;
215
+ const failure = classifyPostAdmissionFailure({
216
+ timedOut: failureInput.timedOut,
217
+ code: failureInput.code,
218
+ stderr: failureInput.stderr,
219
+ ...(hasThrown ? { thrown: failureInput.thrown } : {}),
220
+ ...explicitInternalKnownFailureClassificationInput(failureInput.knownFailure),
221
+ ...(failureInput.knownCause === undefined
222
+ ? {}
223
+ : { knownCause: failureInput.knownCause }),
224
+ ...(failureInput.knownIdentity === undefined
225
+ ? {}
226
+ : { knownIdentity: failureInput.knownIdentity }),
227
+ ...(failureInput.knownDiagnostic === undefined
228
+ ? {}
229
+ : { knownDiagnostic: failureInput.knownDiagnostic }),
230
+ ...(session === undefined ? {} : { session }),
231
+ });
232
+
233
+ const hasLawfulTerminalResult = await hasLawfulMergerTerminalResult(admitted);
234
+ const typedHttp429 = await readTypedHttp429Observation(admitted.runDirectory);
235
+ const sessionPrincipalAvailable = await isSessionPrincipalAvailable(
236
+ admitted.sessionFile,
237
+ );
238
+ const resumable =
239
+ sessionPrincipalAvailable &&
240
+ isV1ResumableFailure({
241
+ hasLawfulTerminalResult,
242
+ ...(typedHttp429 === undefined ? {} : { typedHttp429 }),
243
+ });
244
+ if (resumable && typedHttp429 !== undefined) {
245
+ await markRunResumable(admitted.runDirectory, typedHttp429);
246
+ } else {
247
+ await markRunTerminal(admitted.runDirectory).catch(() => undefined);
248
+ }
249
+
250
+ const terminal = await settleFailureTerminalResult(
251
+ admitted,
252
+ failure,
253
+ resumable
254
+ ? { resume: { command: renderResumeCommand(admitted.runId) } }
255
+ : {},
256
+ );
257
+ presentFailureTerminal(terminal, io);
258
+ return {
259
+ exitCode: exitCodeForTerminalOutcome(terminal.roleOutcome),
260
+ admitted,
261
+ terminal,
262
+ };
263
+ }
264
+
265
+ async function dispatchAdmittedMerger(input: {
266
+ admitted: AdmittedMergerInvocation;
267
+ env: MergerRunEnv;
268
+ io: CliIo;
269
+ extraArgs: string[];
270
+ lease: RunWriterLease;
271
+ methodMaterial: PackagedMethodSkillMaterial;
272
+ }): Promise<{
273
+ exitCode: number;
274
+ admitted: AdmittedMergerInvocation;
275
+ terminal?: TerminalResult;
276
+ }> {
277
+ const { admitted, env, io, extraArgs, lease, methodMaterial } = input;
278
+ try {
279
+ const missingCredential = missingCredentialPreDispatchFailure(
280
+ env.model,
281
+ env.credentials,
282
+ );
283
+ if (missingCredential !== undefined) {
284
+ return await presentControlledFailure(
285
+ admitted,
286
+ missingCredential,
287
+ io,
288
+ );
289
+ }
290
+ await markRunRunning(admitted.runDirectory);
291
+ await clearTypedProviderHttpObservation(admitted.runDirectory);
292
+
293
+ const childEnv: NodeJS.ProcessEnv = {
294
+ ...process.env,
295
+ HOME: env.home,
296
+ PI_CODING_AGENT_DIR: env.agentDir,
297
+ AK_ROLE_RUN_DIR: admitted.runDirectory,
298
+ };
299
+ if (env.correlationId !== undefined && env.correlationId.trim() !== "") {
300
+ childEnv.AK_CORRELATION_ID = env.correlationId;
301
+ }
302
+
303
+ let result: ExplicitInternalPiResult;
304
+ try {
305
+ result = await runExplicitInternalActivation({
306
+ packageRoot: env.packageRoot,
307
+ extraArgs,
308
+ cwd: admitted.projectRoot,
309
+ home: env.home,
310
+ agentDir: env.agentDir,
311
+ env: childEnv,
312
+ timeoutMs: env.timeoutMs,
313
+ ...(env.piRunner === undefined ? {} : { runner: env.piRunner }),
314
+ });
315
+ } catch (error) {
316
+ return await presentControlledFailure(
317
+ admitted,
318
+ {
319
+ timedOut: false,
320
+ code: null,
321
+ stderr: "",
322
+ thrown: error,
323
+ },
324
+ io,
325
+ );
326
+ }
327
+
328
+ try {
329
+ await writeFile(
330
+ join(admitted.runDirectory, "stderr.log"),
331
+ result.stderr,
332
+ "utf8",
333
+ );
334
+ } catch {
335
+ // continue to lawful / controlled-failure settlement
336
+ }
337
+
338
+ let lawful: TerminalResult | undefined;
339
+ try {
340
+ lawful = await trySettleMergerTerminalResult(admitted, {
341
+ methodProvenance: methodMaterial.provenance,
342
+ methodSkillPath: methodMaterial.skillPath,
343
+ methodSkillConfiguredPath: resolvePackagedMethodSkillPath(
344
+ env.packageRoot,
345
+ "resolving-merge-conflicts",
346
+ ),
347
+ });
348
+ } catch (error) {
349
+ return await presentControlledFailure(
350
+ admitted,
351
+ {
352
+ timedOut: false,
353
+ code: result.code,
354
+ stderr: result.stderr,
355
+ thrown: error,
356
+ },
357
+ io,
358
+ );
359
+ }
360
+ if (lawful !== undefined) {
361
+ await markRunTerminal(admitted.runDirectory).catch(() => undefined);
362
+ io.stdout(formatTerminalResult(lawful));
363
+ return {
364
+ exitCode: exitCodeForTerminalOutcome(lawful.roleOutcome),
365
+ admitted,
366
+ terminal: lawful,
367
+ };
368
+ }
369
+
370
+ const credentialFailure = postRunMissingCredentialFailure(
371
+ result,
372
+ env.model,
373
+ env.credentials,
374
+ );
375
+ const knownFailure = await resolveAuditedRunnerKnownFailure({
376
+ runner: result.knownFailure,
377
+ sessionFile: admitted.sessionFile,
378
+ credential: credentialFailure,
379
+ });
380
+ return await presentControlledFailure(
381
+ admitted,
382
+ {
383
+ timedOut: result.timedOut,
384
+ code: result.code,
385
+ stderr: result.stderr,
386
+ ...(knownFailure === undefined ? {} : { knownFailure }),
387
+ },
388
+ io,
389
+ );
390
+ } finally {
391
+ await lease.release();
392
+ }
393
+ }
394
+
395
+ async function loadMergerMethodMaterial(
396
+ packageRoot: string,
397
+ ): Promise<PackagedMethodSkillMaterial> {
398
+ return await loadPackagedMethodSkillMaterial(
399
+ packageRoot,
400
+ "resolving-merge-conflicts",
401
+ );
402
+ }
403
+
404
+ /**
405
+ * Structural admit shell when envelope derivation fails: keeps role-correct
406
+ * Terminal identity for honest activation-class settlement without inventing
407
+ * parents/conflicts (those stay empty; the gate never receives a guessed packet).
408
+ */
409
+ async function admitMergerShellForActivationFailure(options: {
410
+ home: string;
411
+ cwd: string;
412
+ instruction: string;
413
+ project?: string;
414
+ createRunId?: () => string;
415
+ }): Promise<AdmittedMergerInvocation> {
416
+ const projectRoot = resolve(options.project ?? options.cwd);
417
+ const bookKey = resolveBookKeyFromGit(projectRoot);
418
+ const ledgerHome = resolveActivationLedgerHome(() => options.home);
419
+ const runId = (options.createRunId ?? uuidv7)();
420
+ const runDirectory = join(
421
+ activationBookDirectory(ledgerHome, bookKey),
422
+ "runs",
423
+ `${runId}@merger`,
424
+ );
425
+ const sessionDirectory = join(runDirectory, "session");
426
+ const sessionFile = roleRunSessionFile(sessionDirectory);
427
+ ensureRealDirectoryTree(ledgerHome, sessionDirectory);
428
+ await mkdir(runDirectory, { recursive: true });
429
+ const emptyDerived = {
430
+ targetObjectId: "",
431
+ sourceObjectId: "",
432
+ automaticMergeTreeId: "",
433
+ expectedConflictPaths: [] as string[],
434
+ resolutionScope: [] as string[],
435
+ };
436
+ const admittedRequestPath = join(runDirectory, "admitted-request.json");
437
+ const mergerInputPath = join(runDirectory, "merger-input.json");
438
+ await writeFile(
439
+ admittedRequestPath,
440
+ `${JSON.stringify(
441
+ {
442
+ role: "merger",
443
+ runId,
444
+ bookKey,
445
+ projectRoot,
446
+ instruction: options.instruction,
447
+ instructionEmpty: false,
448
+ mergerInputPath,
449
+ derived: emptyDerived,
450
+ attachments: [],
451
+ },
452
+ null,
453
+ 2,
454
+ )}\n`,
455
+ "utf8",
456
+ );
457
+ return {
458
+ role: "merger",
459
+ runId,
460
+ bookKey,
461
+ projectRoot,
462
+ instruction: options.instruction,
463
+ instructionEmpty: false,
464
+ attachments: [],
465
+ runDirectory,
466
+ sessionDirectory,
467
+ sessionFile,
468
+ admittedRequestPath,
469
+ mergerInputPath,
470
+ derived: emptyDerived,
471
+ };
472
+ }
473
+
474
+ export async function runPublicMerger(
475
+ argv: readonly string[],
476
+ env: MergerRunEnv,
477
+ io: CliIo,
478
+ parseMergerArgv: (args: readonly string[]) => {
479
+ instruction: string;
480
+ attachmentPaths: string[];
481
+ project?: string;
482
+ },
483
+ ): Promise<{
484
+ exitCode: number;
485
+ admitted?: AdmittedMergerInvocation;
486
+ terminal?: TerminalResult;
487
+ }> {
488
+ let parsed: {
489
+ instruction: string;
490
+ attachmentPaths: string[];
491
+ project?: string;
492
+ };
493
+ try {
494
+ parsed = parseMergerArgv(argv);
495
+ } catch (error) {
496
+ if (error instanceof CliUsageError) {
497
+ presentStructuralRejection(error, io);
498
+ return { exitCode: 2 };
499
+ }
500
+ throw error;
501
+ }
502
+
503
+ let admitted: AdmittedMergerInvocation;
504
+ try {
505
+ admitted = await admitMergerInvocation({
506
+ home: env.home,
507
+ cwd: env.cwd,
508
+ instruction: parsed.instruction,
509
+ attachmentPaths: parsed.attachmentPaths,
510
+ ...(parsed.project === undefined ? {} : { project: parsed.project }),
511
+ ...(env.createRunId === undefined ? {} : { createRunId: env.createRunId }),
512
+ });
513
+ } catch (error) {
514
+ if (error instanceof CliUsageError) {
515
+ presentStructuralRejection(error, io);
516
+ return { exitCode: 2 };
517
+ }
518
+ if (error instanceof MergerEnvelopeDerivationError) {
519
+ // No active merge / incomplete conflict set: honest activation failure.
520
+ // Place a shell admitted run so Terminal identity stays role-correct.
521
+ const shell = await admitMergerShellForActivationFailure({
522
+ home: env.home,
523
+ cwd: env.cwd,
524
+ instruction: parsed.instruction,
525
+ ...(parsed.project === undefined ? {} : { project: parsed.project }),
526
+ ...(env.createRunId === undefined
527
+ ? {}
528
+ : { createRunId: env.createRunId }),
529
+ });
530
+ await markRunAdmitted(shell);
531
+ return await presentControlledFailure(
532
+ shell,
533
+ {
534
+ timedOut: false,
535
+ code: null,
536
+ stderr: "",
537
+ thrown: error,
538
+ knownCause: "activation",
539
+ knownDiagnostic: error.message,
540
+ },
541
+ io,
542
+ );
543
+ }
544
+ throw error;
545
+ }
546
+
547
+ await markRunAdmitted(admitted);
548
+
549
+ let lease: RunWriterLease;
550
+ try {
551
+ lease = await acquireRunWriterLease(admitted.runDirectory);
552
+ } catch (error) {
553
+ if (error instanceof RunWriterLeaseHeldError) {
554
+ presentStructuralRejection(error, io);
555
+ return { exitCode: 2 };
556
+ }
557
+ throw error;
558
+ }
559
+
560
+ let methodMaterial: PackagedMethodSkillMaterial;
561
+ try {
562
+ methodMaterial = await loadMergerMethodMaterial(env.packageRoot);
563
+ } catch (error) {
564
+ await lease.release();
565
+ return await presentControlledFailure(
566
+ admitted,
567
+ {
568
+ timedOut: false,
569
+ code: null,
570
+ stderr: "",
571
+ thrown: error,
572
+ knownCause: "activation",
573
+ },
574
+ io,
575
+ );
576
+ }
577
+
578
+ const extraArgs = buildMergerActivationExtraArgs(admitted, {
579
+ packageRoot: env.packageRoot,
580
+ ...(env.model === undefined ? {} : { model: env.model }),
581
+ ...(env.extraPiArgs === undefined ? {} : { extraPiArgs: env.extraPiArgs }),
582
+ });
583
+
584
+ return await dispatchAdmittedMerger({
585
+ admitted,
586
+ env,
587
+ io,
588
+ extraArgs,
589
+ lease,
590
+ methodMaterial,
591
+ });
592
+ }
593
+
594
+ /**
595
+ * Resume a previously admitted Merger Role run after a typed HTTP 429.
596
+ * Restores derived input/session identity; model override is temporary.
597
+ */
598
+ export async function runPublicMergerResume(
599
+ argv: readonly string[],
600
+ env: MergerRunEnv,
601
+ io: CliIo,
602
+ ): Promise<{
603
+ exitCode: number;
604
+ admitted?: AdmittedMergerInvocation;
605
+ terminal?: TerminalResult;
606
+ }> {
607
+ const runId = argv[0];
608
+ if (runId === undefined || runId.trim() === "" || runId.startsWith("-")) {
609
+ presentStructuralRejection(
610
+ new CliUsageError("usage: ak-role resume <runId>"),
611
+ io,
612
+ );
613
+ return { exitCode: 2 };
614
+ }
615
+ if (argv.length > 1) {
616
+ presentStructuralRejection(
617
+ new CliUsageError("resume takes exactly one run id"),
618
+ io,
619
+ );
620
+ return { exitCode: 2 };
621
+ }
622
+
623
+ let loaded;
624
+ try {
625
+ loaded = await loadResumableMergerRun(env.home, runId);
626
+ } catch (error) {
627
+ if (error instanceof CliUsageError) {
628
+ presentStructuralRejection(error, io);
629
+ return { exitCode: 2 };
630
+ }
631
+ throw error;
632
+ }
633
+
634
+ const { admitted } = loaded;
635
+
636
+ let lease: RunWriterLease;
637
+ try {
638
+ lease = await acquireRunWriterLease(admitted.runDirectory);
639
+ } catch (error) {
640
+ if (error instanceof RunWriterLeaseHeldError) {
641
+ io.stderr(formatCliDiagnostic(error.message));
642
+ return { exitCode: 1 };
643
+ }
644
+ throw error;
645
+ }
646
+
647
+ let methodMaterial: PackagedMethodSkillMaterial;
648
+ try {
649
+ methodMaterial = await loadMergerMethodMaterial(env.packageRoot);
650
+ } catch (error) {
651
+ await lease.release();
652
+ return await presentControlledFailure(
653
+ admitted,
654
+ {
655
+ timedOut: false,
656
+ code: null,
657
+ stderr: "",
658
+ thrown: error,
659
+ knownCause: "activation",
660
+ },
661
+ io,
662
+ );
663
+ }
664
+
665
+ const extraArgs = buildMergerResumeActivationExtraArgs(admitted, {
666
+ packageRoot: env.packageRoot,
667
+ ...(env.model === undefined ? {} : { model: env.model }),
668
+ ...(env.extraPiArgs === undefined ? {} : { extraPiArgs: env.extraPiArgs }),
669
+ });
670
+
671
+ return await dispatchAdmittedMerger({
672
+ admitted,
673
+ env,
674
+ io,
675
+ extraArgs,
676
+ lease,
677
+ methodMaterial,
678
+ });
679
+ }
680
+
681
+ export type { ExplicitInternalKnownFailure, PackagedMethodSkillProvenance };