@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,53 @@
1
+ import { resolve } from "node:path";
2
+ import {
3
+ physicalPathIdentity,
4
+ physicallyContainedIn,
5
+ resolveActivationLedgerHome
6
+ } from "./activation-ledger-topology.js";
7
+ function issueRoot(value) {
8
+ const normalized = value.replaceAll("\\", "/");
9
+ const marker = ".ak/work/issues/";
10
+ const index = normalized.indexOf(marker);
11
+ if (index < 0) return void 0;
12
+ const issue = normalized.slice(index + marker.length).split("/")[0]?.split("#")[0];
13
+ return issue === void 0 || issue === "" ? void 0 : normalized.slice(0, index + marker.length) + issue;
14
+ }
15
+ function workIdentityFromCwd(cwd) {
16
+ const resolvedCwd = resolve(cwd, ".");
17
+ const cwdIssue = issueRoot(resolvedCwd);
18
+ if (cwdIssue !== void 0) return cwdIssue;
19
+ if (resolvedCwd.includes("/.ak/work/")) return resolvedCwd;
20
+ return void 0;
21
+ }
22
+ function isMachineLedgerSessionPath(sessionPath) {
23
+ return physicallyContainedIn(resolveActivationLedgerHome(), sessionPath);
24
+ }
25
+ function subjectPath(sessionDir, cwd = process.cwd()) {
26
+ if (sessionDir === "") {
27
+ return workIdentityFromCwd(cwd) ?? resolve(cwd, ".ak/work");
28
+ }
29
+ const resolvedSession = resolve(cwd, sessionDir || ".ak/work");
30
+ if (isMachineLedgerSessionPath(resolvedSession)) {
31
+ return workIdentityFromCwd(cwd) ?? resolve(cwd, ".ak/work");
32
+ }
33
+ const issue = issueRoot(resolvedSession);
34
+ if (issue !== void 0) return issue;
35
+ const runsMarker = "/runs/";
36
+ const runsIndex = resolvedSession.indexOf(runsMarker);
37
+ if (runsIndex >= 0) {
38
+ return resolvedSession.slice(0, runsIndex);
39
+ }
40
+ return resolvedSession;
41
+ }
42
+ function workSubjectKeyFromProjectRoot(projectRoot) {
43
+ return subjectPath("", projectRoot);
44
+ }
45
+ function workSubjectKeysEqual(left, right) {
46
+ return physicalPathIdentity(left) === physicalPathIdentity(right);
47
+ }
48
+ export {
49
+ issueRoot,
50
+ subjectPath,
51
+ workSubjectKeyFromProjectRoot,
52
+ workSubjectKeysEqual
53
+ };
@@ -0,0 +1,303 @@
1
+ import { readFile } from "node:fs/promises";
2
+ import { fileURLToPath } from "node:url";
3
+ import { resolve } from "node:path";
4
+
5
+ import { loadDoctorCase } from "../src/doctor-evidence.ts";
6
+ import { loadAdmittedJudgeRequest } from "../src/public-cli/invocation.ts";
7
+
8
+ import {
9
+ buildSessionContext,
10
+ convertToLlm,
11
+ serializeConversation,
12
+ type ExtensionAPI,
13
+ type ExtensionContext,
14
+ } from "@earendil-works/pi-coding-agent";
15
+ import type { Message } from "@earendil-works/pi-ai";
16
+
17
+ import { createGhCollectorGitHubTransport } from "../src/collector-github.ts";
18
+ import { createReviewerAgentRunner } from "../src/reviewer-agent.ts";
19
+ import { createReviewerPinnedGitReader } from "../src/reviewer-dispatch.ts";
20
+ import { createPiReviewerAuditor } from "../src/reviewer-auditor.ts";
21
+ import { createPiDoctorAuditor } from "../src/doctor-auditor.ts";
22
+ import {
23
+ createNativeNavigatorSessionFactory,
24
+ createNavigatorAttendance,
25
+ navigatorUnavailableError,
26
+ navigatorSessionDirectory,
27
+ navigatorSubjectKey,
28
+ navigatorSubjectKeyForInput,
29
+ registerNavigatorModelCommand,
30
+ subjectPath,
31
+ type NavigatorSubjectProvenance,
32
+ type NavigatorTargetRole,
33
+ } from "../src/navigator-attendance.ts";
34
+ import { loadCanonicalSkillBinding as loadHomeCanonicalSkillBinding } from "../src/canonical-skill-binding.ts";
35
+ import { loadPackagedCanonicalSkillBinding } from "../src/package-resources/method-skill-binding.ts";
36
+ import { JUDGE_OUTPUT_TOOL_NAME } from "../src/package-contracts/judge-output.ts";
37
+ import {
38
+ createProductionMergerGitState,
39
+ createRoleRuntimeExtension,
40
+ ROLE_FLAG,
41
+ } from "../src/role-runtime.ts";
42
+ import {
43
+ packagedRoleInputFlag,
44
+ packagedRoleMetadata,
45
+ } from "../src/packaged-role-registry.ts";
46
+ import { createPiJudgeAuditor } from "../src/judge-auditor.ts";
47
+ const extensionPath = fileURLToPath(import.meta.url);
48
+ const packageRoot = fileURLToPath(new URL("..", import.meta.url));
49
+ const judgeSoulPath = fileURLToPath(new URL("../souls/judge.md", import.meta.url));
50
+ const fixerSoulPath = fileURLToPath(new URL("../souls/fixer.md", import.meta.url));
51
+ const coderSoulPath = fileURLToPath(new URL("../souls/coder.md", import.meta.url));
52
+ const reviewerSoulPath = fileURLToPath(new URL("../souls/reviewer.md", import.meta.url));
53
+ const collectorSoulPath = fileURLToPath(new URL("../souls/collector.md", import.meta.url));
54
+ const doctorSoulPath = fileURLToPath(new URL("../souls/doctor.md", import.meta.url));
55
+ const navigatorSoulPath = fileURLToPath(new URL("../souls/navigator.md", import.meta.url));
56
+ const navigatorRoutePlaybookPath = fileURLToPath(new URL("../resources/navigator-route-playbook.md", import.meta.url));
57
+ const mergerSoulPath = fileURLToPath(new URL("../souls/merger.md", import.meta.url));
58
+
59
+ function navigatorInputReference(pi: ExtensionAPI, role: string): string | undefined {
60
+ const name = packagedRoleInputFlag(role);
61
+ const value = name === undefined ? undefined : pi.getFlag(name);
62
+ return typeof value === "string" && value !== "" ? resolve(value) : undefined;
63
+ }
64
+
65
+ // Cold `pi -e <extension> --help` must cover installed-package process startup under CI load.
66
+ // This bound is process-startup budget only — not settlement-to-visible presentation latency.
67
+ export const NAVIGATOR_LIVE_HELP_TIMEOUT_MS = 30_000;
68
+
69
+ /**
70
+ * Subprocess live help (disk-reread via fresh pi -e). Kept for cold-install proofs.
71
+ * Production Navigator prepare must not call this on the post-role grace path — under
72
+ * concurrent CI load each role's pi --help alone can exceed the accepted 3s grace.
73
+ */
74
+ export async function loadNavigatorRoleHelp(
75
+ pi: Pick<ExtensionAPI, "exec">,
76
+ extensionPath: string,
77
+ cwd: string,
78
+ role: NavigatorTargetRole,
79
+ ): Promise<string> {
80
+ const result = await pi.exec("pi", ["--no-extensions", "--no-skills", "--no-prompt-templates", "--no-themes", "--no-context-files", "-e", extensionPath, "--ak-role", role, "--help"], { cwd, timeout: NAVIGATOR_LIVE_HELP_TIMEOUT_MS });
81
+ if (result.killed) {
82
+ throw new Error(`live help unavailable for ${role}: process did not settle`, { cause: result });
83
+ }
84
+ if (result.code !== 0) throw new Error(`live help unavailable for ${role}: process exited with code ${result.code}`, { cause: result });
85
+ return result.stdout || result.stderr;
86
+ }
87
+
88
+ /**
89
+ * In-process role help for Navigator prepare. Same loaded package/module the role
90
+ * is already running — no child pi. Public command surface is ak-role (ADR 0052).
91
+ */
92
+ export function formatInProcessNavigatorRoleHelp(role: NavigatorTargetRole): string {
93
+ const metadata = packagedRoleMetadata(role);
94
+ const lines = [
95
+ `Usage: ak-role ${role}`,
96
+ ROLE_FLAG.definition.description,
97
+ ];
98
+ if (metadata?.inputFlag !== undefined) {
99
+ lines.push(` --${metadata.inputFlag} <value> ${role} input material`);
100
+ }
101
+ if (metadata?.phaseFlag !== undefined) {
102
+ lines.push(
103
+ ` --${metadata.phaseFlag} <value> ${role} phase: ${(metadata.phases.filter((p) => p !== null) as string[]).join(" | ")}`,
104
+ );
105
+ }
106
+ lines.push(`Public next-command form: ak-role ${role}`);
107
+ return lines.join("\n");
108
+ }
109
+
110
+ /**
111
+ * Role-input document bytes win verbatim over work-root file authority when non-empty.
112
+ * Absent or whitespace-only input yields to fileAuthority; neither remains undefined.
113
+ */
114
+ export function resolveNavigatorAuthorityMaterial(
115
+ roleInput: string | undefined,
116
+ fileAuthority: string | undefined,
117
+ ): string | undefined {
118
+ if (roleInput !== undefined && roleInput.trim() !== "") return roleInput;
119
+ if (fileAuthority !== undefined && fileAuthority.trim() !== "") return fileAuthority;
120
+ return undefined;
121
+ }
122
+
123
+
124
+ function projectJudgeTranscriptForAudit(messages: Message[]): Message[] {
125
+ return messages.map((message) => {
126
+ if (message.role !== "assistant") return message;
127
+ return {
128
+ ...message,
129
+ content: message.content.map((part) => {
130
+ if (part.type !== "toolCall" || part.name !== JUDGE_OUTPUT_TOOL_NAME) {
131
+ return part;
132
+ }
133
+ const { evidence: _evidence, ...adjudicativeArguments } = part.arguments;
134
+ return { ...part, arguments: adjudicativeArguments };
135
+ }),
136
+ };
137
+ });
138
+ }
139
+
140
+ export function transcriptFromContext(ctx: ExtensionContext): string {
141
+ const context = buildSessionContext(
142
+ [...ctx.sessionManager.getEntries()],
143
+ ctx.sessionManager.getLeafId(),
144
+ );
145
+ return serializeConversation(
146
+ projectJudgeTranscriptForAudit(convertToLlm(context.messages)),
147
+ );
148
+ }
149
+
150
+ export async function loadNavigatorWorkContext(
151
+ pi: Pick<ExtensionAPI, "getFlag">,
152
+ options: { context: ExtensionContext; role: string },
153
+ ): Promise<{ subjectKey: string; subject: string; authority: string; subjectProvenance: NavigatorSubjectProvenance }> {
154
+ const reference = navigatorInputReference(pi as ExtensionAPI, options.role);
155
+ const input = reference === undefined || options.role === "doctor" ? undefined : await readFile(reference, "utf8");
156
+ const subjectRoot = subjectPath(reference ?? options.context.sessionManager.getSessionDir(), options.context.cwd);
157
+ let subjectKey = reference === undefined
158
+ ? subjectRoot
159
+ : navigatorSubjectKeyForInput(subjectRoot, reference, options.context.cwd);
160
+ let subject = input ?? `work subject: ${subjectKey}`;
161
+ let subjectProvenance: NavigatorSubjectProvenance = input === undefined ? "placeholder" : "role_input";
162
+ if (options.role === "doctor" && reference !== undefined) {
163
+ const patient = await loadDoctorCase(reference);
164
+ subject = JSON.stringify({ identity: patient.identity, cost: patient.cost });
165
+ subjectProvenance = "role_input";
166
+ }
167
+ // Public ak-role run: admitted request is the typed Navigator work-context source.
168
+ // Classification failure here stays source=context (distinct from model/session/transport).
169
+ const publicRunDir = process.env.AK_ROLE_RUN_DIR;
170
+ if (
171
+ options.role === "judge" &&
172
+ typeof publicRunDir === "string" &&
173
+ publicRunDir.trim() !== ""
174
+ ) {
175
+ let admitted;
176
+ try {
177
+ admitted = await loadAdmittedJudgeRequest(publicRunDir);
178
+ } catch (error) {
179
+ throw navigatorUnavailableError("context", error);
180
+ }
181
+ if (admitted === undefined) {
182
+ throw navigatorUnavailableError(
183
+ "context",
184
+ new Error("public Judge admitted request was missing or malformed"),
185
+ );
186
+ }
187
+ if (!admitted.instructionEmpty && admitted.instruction.trim() !== "") {
188
+ const prose = admitted.instruction;
189
+ subjectProvenance = "role_input";
190
+ subject = prose;
191
+ subjectKey = navigatorSubjectKey(subjectRoot, prose, subjectProvenance);
192
+ return { subjectKey, subject, authority: prose, subjectProvenance };
193
+ }
194
+ // Structurally empty public request: placeholder work context, no invented task.
195
+ return {
196
+ subjectKey: subjectRoot,
197
+ subject: `work subject: ${subjectRoot}`,
198
+ authority: "",
199
+ subjectProvenance: "placeholder",
200
+ };
201
+ }
202
+ // True short-circuit: non-whitespace role-input is authority verbatim.
203
+ // Do not probe work-root authority files once input already supplies material.
204
+ if (input !== undefined && input.trim() !== "") {
205
+ return { subjectKey, subject, authority: input, subjectProvenance };
206
+ }
207
+ const workRoot = subjectRoot.includes("/.ak/work/") ? subjectRoot : undefined;
208
+ const authorityFiles = workRoot === undefined ? [] : [
209
+ resolve(workRoot, "authority.md"),
210
+ resolve(workRoot, "authority.txt"),
211
+ resolve(workRoot, "design-v2/owner-direction.md"),
212
+ ];
213
+ let authorityMaterial: string | undefined;
214
+ for (const path of authorityFiles) {
215
+ try {
216
+ const content = await readFile(path, "utf8");
217
+ if (content.trim() !== "") {
218
+ authorityMaterial = content;
219
+ break;
220
+ }
221
+ } catch (error) {
222
+ if (!(error instanceof Error && "code" in error && (error as NodeJS.ErrnoException).code === "ENOENT")) throw error;
223
+ }
224
+ }
225
+ // Absent or whitespace-only input yields to the existing file fallback.
226
+ const authority = resolveNavigatorAuthorityMaterial(input, authorityMaterial);
227
+ if (authority === undefined) {
228
+ // Bare developer seams (judge -p, etc.) supply the prompt only at
229
+ // before_agent_start. session_start absence is a soft placeholder, not a
230
+ // permanent context poison — prepare still fails honestly if nothing arrives.
231
+ return {
232
+ subjectKey: subjectRoot,
233
+ subject: `work subject: ${subjectRoot}`,
234
+ authority: "",
235
+ subjectProvenance: "placeholder",
236
+ };
237
+ }
238
+ return { subjectKey, subject, authority, subjectProvenance };
239
+ }
240
+
241
+ export default function roleRuntime(pi: ExtensionAPI): void {
242
+ const reviewerAgent = createReviewerAgentRunner();
243
+ registerNavigatorModelCommand(pi);
244
+ const navigatorSessionFactory = createNativeNavigatorSessionFactory();
245
+ createRoleRuntimeExtension({
246
+ loadJudgeSoul: () => readFile(judgeSoulPath, "utf8"),
247
+ loadFixerSoul: () => readFile(fixerSoulPath, "utf8"),
248
+ loadFixPacket: (path) => readFile(path, "utf8"),
249
+ loadCoderSoul: () => readFile(coderSoulPath, "utf8"),
250
+ loadCoderTask: (path) => readFile(path, "utf8"),
251
+ loadReviewerSoul: () => readFile(reviewerSoulPath, "utf8"),
252
+ createReviewerPinnedGitReader: () => createReviewerPinnedGitReader(),
253
+ loadCollectorSoul: () => readFile(collectorSoulPath, "utf8"),
254
+ createCollectorTransport: () => createGhCollectorGitHubTransport(),
255
+ collectorPackageExtensionPath: extensionPath,
256
+ loadDoctorSoul: () => readFile(doctorSoulPath, "utf8"),
257
+ loadDoctorCase,
258
+ auditDoctorCompliance: createPiDoctorAuditor(),
259
+ loadNavigatorWorkContext: (options) => loadNavigatorWorkContext(pi, options),
260
+ createNavigatorAttendance: (options) => {
261
+ const sessionDir = navigatorSessionDirectory(options.context, options.subjectKey);
262
+ return createNavigatorAttendance({
263
+ context: options.context,
264
+ role: options.role,
265
+ phase: options.phase,
266
+ subjectKey: options.subjectKey,
267
+ sessionDir,
268
+ sessionDirectory: (subjectKey) => navigatorSessionDirectory(options.context, subjectKey),
269
+ subject: options.subject,
270
+ authority: options.authority,
271
+ invocationId: options.invocationId,
272
+ loadSoul: () => readFile(navigatorSoulPath, "utf8"),
273
+ loadRoutePlaybook: () => readFile(navigatorRoutePlaybookPath, "utf8"),
274
+ // In-process help: subprocess pi --help is reserved for cold-install proofs.
275
+ // N child pi processes cannot fit the accepted 3s post-role grace under CI load.
276
+ loadRoleHelp: async (role) => formatInProcessNavigatorRoleHelp(role),
277
+ createSession: navigatorSessionFactory,
278
+ contextError: options.contextError,
279
+ onEvent: options.onEvent,
280
+ });
281
+ },
282
+ loadMergerSoul: () => readFile(mergerSoulPath, "utf8"),
283
+ loadMergerInput: async (path) => JSON.parse(await readFile(path, "utf8")),
284
+ createMergerGitState: (repositoryRoot) =>
285
+ createProductionMergerGitState(repositoryRoot),
286
+ async loadCanonicalSkillBinding(name) {
287
+ // Coder TDD (#109) and Reviewer code-review (#111) are package-owned.
288
+ // Optional Fixer diagnosing-bugs is available via --skill without this binding.
289
+ if (name === "tdd") {
290
+ return loadPackagedCanonicalSkillBinding(packageRoot, "tdd");
291
+ }
292
+ if (name === "code-review") {
293
+ return loadPackagedCanonicalSkillBinding(packageRoot, "code-review");
294
+ }
295
+ return loadHomeCanonicalSkillBinding(name);
296
+ },
297
+ runReviewerDispatch: (dispatch, options) => reviewerAgent.run(dispatch, options),
298
+ shutdownReviewerAgent: () => reviewerAgent.shutdown(),
299
+ transcriptFromContext,
300
+ auditSoulCompliance: createPiJudgeAuditor(),
301
+ auditReviewerCompliance: createPiReviewerAuditor(),
302
+ })(pi);
303
+ }
package/package.json ADDED
@@ -0,0 +1,69 @@
1
+ {
2
+ "name": "@akagilnc/pi-workflow-roles",
3
+ "version": "0.1.1751",
4
+ "description": "Soul-bound workflow roles for Pi",
5
+ "type": "module",
6
+ "license": "Apache-2.0",
7
+ "keywords": [
8
+ "pi-package"
9
+ ],
10
+ "bin": {
11
+ "ak-role": "./dist/public-cli/main.js"
12
+ },
13
+ "files": [
14
+ "dist",
15
+ "extensions",
16
+ "scripts/generate-tool-execution-observation-schema.ts",
17
+ "scripts/build-package.mjs",
18
+ "src",
19
+ "souls",
20
+ "schemas",
21
+ "packets",
22
+ "resources",
23
+ "README.md",
24
+ "LICENSE",
25
+ "THIRD_PARTY_NOTICES.md"
26
+ ],
27
+ "scripts": {
28
+ "build": "tsx scripts/generate-tool-execution-observation-schema.ts && tsc -p tsconfig.build.json && node scripts/build-package.mjs",
29
+ "prepack": "npm run build",
30
+ "test": "pnpm run test:all",
31
+ "test:fast": "node --import tsx --test test/unit/**/*.test.ts test/contract/**/*.test.ts",
32
+ "test:integration": "node --import tsx --test test/unit/**/*.test.ts test/contract/**/*.test.ts test/integration/**/*.test.ts",
33
+ "test:all": "node scripts/run-test-all.mjs",
34
+ "test:adjudication": "node --import tsx --test test/adjudication/**/*.test.ts",
35
+ "typecheck": "tsc --noEmit"
36
+ },
37
+ "pi": {
38
+ "extensions": []
39
+ },
40
+ "engines": {
41
+ "node": ">=22.19.0"
42
+ },
43
+ "packageManager": "pnpm@11.20.0",
44
+ "peerDependencies": {
45
+ "@earendil-works/pi-ai": "*",
46
+ "@earendil-works/pi-coding-agent": "*",
47
+ "typebox": "*"
48
+ },
49
+ "peerDependenciesMeta": {
50
+ "@earendil-works/pi-ai": {
51
+ "optional": true
52
+ },
53
+ "@earendil-works/pi-coding-agent": {
54
+ "optional": true
55
+ },
56
+ "typebox": {
57
+ "optional": true
58
+ }
59
+ },
60
+ "devDependencies": {
61
+ "@earendil-works/pi-ai": "0.84.1",
62
+ "@earendil-works/pi-coding-agent": "0.84.1",
63
+ "@types/node": "latest",
64
+ "esbuild": "^0.28.1",
65
+ "tsx": "latest",
66
+ "typebox": "1.3.8",
67
+ "typescript": "latest"
68
+ }
69
+ }
@@ -0,0 +1,6 @@
1
+ [
2
+ {
3
+ "id": "owner.choice",
4
+ "requirement": "The controlling owner decision required before this repair exists."
5
+ }
6
+ ]
@@ -0,0 +1,5 @@
1
+ # Fixer repair instructions
2
+
3
+ Repair and verify the caller-assigned findings. Treat this document as opaque prose: its headings and wording have no machine semantics.
4
+
5
+ Search the authorized scope for every same-pattern occurrence, preserve unrelated behavior, run the required checks, and report each finding class through the typed Fixer output.
@@ -0,0 +1,77 @@
1
+ # Apply evidence packet (contributor template)
2
+
3
+ This file is a **repository-contributor template** for a manually supplied Apply
4
+ (executable-proof) artifact. The filename identifies an **evidence burden**, not
5
+ a verdict, phase flag, transition, or required predecessor/successor.
6
+
7
+ Selection, composition, and use are **caller-owned** (ADR 0010). Apply posture
8
+ semantics remain solely in `souls/judge.md`. Git commit identity owns the code
9
+ snapshot and any reviewed range. This template creates no receipt envelope,
10
+ audit, runtime enforcement, trust tier, production hook, or package surface.
11
+
12
+ ## Sealed upstream identities
13
+
14
+ Digests seal **artifact-byte identity only**. They do not prove truth,
15
+ acceptance, or freshness.
16
+
17
+ | Artifact | Repository-relative path | SHA-256 of exact bytes |
18
+ | --- | --- | --- |
19
+ | Authority materials | | |
20
+ | Plan materials | | |
21
+
22
+ ## Target and range identity
23
+
24
+ | Kind | Full SHA | Meaning |
25
+ | --- | --- | --- |
26
+ | **Target commit** (required for code/apply facts) | | Complete snapshot under claim |
27
+ | **Range base** (only if a range is claimed) | | Base snapshot from which the reviewed delta starts |
28
+ | **Range target** (only if a range is claimed) | | Target snapshot at which that delta ends |
29
+
30
+ Distinguish carefully:
31
+
32
+ - **path + SHA-256** → exact bytes of a named artifact
33
+ - **full target commit SHA** → complete code snapshot under claim
34
+ - **full base + target SHAs** → identify only the reviewed delta (not a commit-set membership rule or range syntax)
35
+ - **tests / seam / boundary observations** → behavioral evidence
36
+
37
+ None of these alone proves truth or acceptance.
38
+
39
+ ## Construction evidence
40
+
41
+ ### Live code and tests
42
+
43
+ | Claim | Evidence (path, command, or observation) | Binds to target SHA? |
44
+ | --- | --- | --- |
45
+ | | | yes/no |
46
+
47
+ Use `file:line` **only where applicable** to a concrete claim. Do not invent
48
+ blanket line citations.
49
+
50
+ ### Real production-seam evidence
51
+
52
+ | Seam / module owner | How the claim crosses the real seam | Result |
53
+ | --- | --- | --- |
54
+ | | | |
55
+
56
+ ### Boundary evidence
57
+
58
+ | Boundary condition | How it was actually reached | Result |
59
+ | --- | --- | --- |
60
+ | | | |
61
+
62
+ ### Guardrail triad (only when adding or approving a guardrail)
63
+
64
+ Complete this section **only** if the change adds or approves a guardrail;
65
+ otherwise record `N/A — no guardrail added or approved` with disposition.
66
+
67
+ | Question | Answer |
68
+ | --- | --- |
69
+ | 1. Which real, reproducible failure proves this guardrail is needed? | |
70
+ | 2. Which seam owns the invariant it protects? | |
71
+ | 3. Why is deleting or simplifying the root cause insufficient for this failure class? | |
72
+
73
+ ## Explicit non-claims
74
+
75
+ - Filename is not a verdict and does not imply Apply convergence.
76
+ - This template does not define or alter role receipts, Soul audit, or runtime gates.
77
+ - Instantiation does not route work to any role or require a successor packet.
@@ -0,0 +1,64 @@
1
+ # Authority evidence packet (contributor template)
2
+
3
+ This file is a **repository-contributor template** for a manually supplied
4
+ Authority-evidence artifact. The filename identifies an **evidence burden**, not
5
+ a verdict, phase flag, transition, or required predecessor/successor.
6
+
7
+ Selection, composition, and use are **caller-owned** (ADR 0010). This template
8
+ does not restate or amend Judge law in `souls/judge.md`. It creates no routing,
9
+ next-role, package memory, resume semantics, timeout budget, or trust tier.
10
+
11
+ ## Identity seal
12
+
13
+ Every supplied artifact is identified by:
14
+
15
+ | Field | Value |
16
+ | --- | --- |
17
+ | Repository-relative path | |
18
+ | SHA-256 of exact bytes | |
19
+
20
+ A digest seals **identity only**. It does not prove truth, acceptance, or
21
+ freshness. Judge independently checks claims against the supplied current
22
+ target. This packet does **not** require Apply-level executable proof.
23
+
24
+ ## Authority items
25
+
26
+ Record each item the contributor wants examined under the Authority burden.
27
+ Do not invent Apply fixtures, blanket `file:line` demands, or implementation
28
+ recipes here.
29
+
30
+ ### Clauses
31
+
32
+ | ID | Clause | Notes |
33
+ | --- | --- | --- |
34
+ | A1 | | |
35
+
36
+ ### Decisions
37
+
38
+ | ID | Decision | 陛下 | Notes |
39
+ | --- | --- | --- | --- |
40
+ | D1 | | | |
41
+
42
+ ### Counterexamples
43
+
44
+ | ID | Counterexample | Why it matters |
45
+ | --- | --- | --- |
46
+ | C1 | | |
47
+
48
+ ### Boundaries
49
+
50
+ | ID | In-scope / out-of-scope boundary |
51
+ | --- | --- |
52
+ | B1 | |
53
+
54
+ ### Unresolved 陛下 choices
55
+
56
+ | ID | Open choice | Options | Blocking? |
57
+ | --- | --- | --- | --- |
58
+ | U1 | | | |
59
+
60
+ ## Explicit non-claims
61
+
62
+ - Filename is not a verdict and does not imply convergence.
63
+ - Instantiation does not start, order, or require any role call.
64
+ - No mechanical schema/runtime enforcement is claimed by this template.
@@ -0,0 +1,55 @@
1
+ # Plan evidence packet (contributor template)
2
+
3
+ This file is a **repository-contributor template** for a manually supplied Plan
4
+ (construction-readiness) artifact. The filename identifies an **evidence
5
+ burden**, not a verdict, phase flag, transition, or required
6
+ predecessor/successor.
7
+
8
+ Selection, composition, and use are **caller-owned** (ADR 0010). Plan posture
9
+ semantics remain solely in `souls/judge.md`. This template does not restate or
10
+ amend that law. It creates no routing, topology, role-order, package memory, or
11
+ proof that construction occurred.
12
+
13
+ ## Sealed authority identity
14
+
15
+ Bind the authority materials this plan consumes. Digests seal identity only—not
16
+ truth, acceptance, or freshness.
17
+
18
+ | Artifact | Repository-relative path | SHA-256 of exact bytes |
19
+ | --- | --- | --- |
20
+ | Authority packet / inputs | | |
21
+
22
+ ## Planned changes — five readiness facts
23
+
24
+ For **each** proposed change, record exactly these five facts. Do not demand
25
+ fixture pseudocode or blanket `file:line` here.
26
+
27
+ ### Change P1
28
+
29
+ | Fact | Content |
30
+ | --- | --- |
31
+ | **Behavior** | Observable requirement or defect addressed |
32
+ | **Owner** | Deep module / seam that owns the behavior |
33
+ | **Red** | Counterexample that must fail before the fix |
34
+ | **Green** | Observable result that proves the fix |
35
+ | **Scope** | What deliberately stays unchanged |
36
+
37
+ ### Change P2
38
+
39
+ | Fact | Content |
40
+ | --- | --- |
41
+ | **Behavior** | |
42
+ | **Owner** | |
43
+ | **Red** | |
44
+ | **Green** | |
45
+ | **Scope** | |
46
+
47
+ Add P3… as needed. Every planned change must be reconcilable to the sealed
48
+ authority identity above and must carry all five facts.
49
+
50
+ ## Explicit non-claims
51
+
52
+ - Filename is not a verdict and does not authorize or prove Apply success.
53
+ - This packet does not claim construction already happened.
54
+ - No orchestration, next-role, or stage-machine semantics arise from this file.
55
+ - No mechanical schema/runtime enforcement is claimed by this template.
@@ -0,0 +1,49 @@
1
+ # Review evidence packet (contributor template)
2
+
3
+ This file is a **repository-contributor template** for a manually supplied
4
+ Review (finding-adjudication) artifact. The filename identifies an **evidence
5
+ burden**, not a verdict, phase flag, transition, or required
6
+ predecessor/successor.
7
+
8
+ Selection, composition, and use are **caller-owned** (ADR 0010). This template
9
+ records adjudication evidence only. It does **not** define Reviewer protocol,
10
+ alter Reviewer method/audit, or alter Collector ledger semantics. Judge Review
11
+ posture meaning remains in `souls/judge.md`. No generic Reviewer/Collector
12
+ provider law is introduced (ADR 0011).
13
+
14
+ ## Sealed authority identity
15
+
16
+ | Artifact | Repository-relative path | SHA-256 of exact bytes |
17
+ | --- | --- | --- |
18
+ | Authority materials | | |
19
+
20
+ A digest seals identity only—not truth, acceptance, or freshness.
21
+
22
+ ## Fixed reviewed range
23
+
24
+ Every finding and disposition in this packet concerns **one immutable range**
25
+ and current target facts. A changed target or range requires a **new**
26
+ artifact/digest; do not silently mutate this packet.
27
+
28
+ | Field | Full SHA |
29
+ | --- | --- |
30
+ | Range base commit | |
31
+ | Range target commit | |
32
+ | Current target facts bind to | |
33
+
34
+ ## Findings and dispositions
35
+
36
+ Bind each independent finding to sealed authority, the fixed range above, and
37
+ current facts. Every finding needs an explicit disposition.
38
+
39
+ | Finding ID | Claim | Authority binding | Evidence on current target/range | Disposition | Disposition evidence |
40
+ | --- | --- | --- | --- | --- | --- |
41
+ | F1 | | | | sustained / rejected / deferred / other | |
42
+
43
+ ## Explicit non-claims
44
+
45
+ - Filename is not a verdict and does not imply Review convergence.
46
+ - This packet defines no required review order, repetition count, or return path
47
+ to any role.
48
+ - No routing, next-role, stage machine, or provider-universal protocol arises here.
49
+ - No mechanical schema/runtime enforcement is claimed by this template.