@akagilnc/pi-workflow-roles 0.1.3648 → 0.1.3652

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 (66) hide show
  1. package/dist/acp-host/production-host.js +2919 -1750
  2. package/dist/activation-ledger-session.js +105 -0
  3. package/dist/activation-ledger.js +139 -0
  4. package/dist/activation-trace.js +33 -0
  5. package/dist/agent-start-materials.js +11 -0
  6. package/dist/auditor-role.js +12 -0
  7. package/dist/canonical-skill-binding.js +64 -0
  8. package/dist/collector-identity.js +151 -0
  9. package/dist/collector-receipt.js +95 -0
  10. package/dist/collector-role.js +441 -0
  11. package/dist/countersign-role.js +28 -0
  12. package/dist/diarist-role.js +29 -0
  13. package/dist/doctor-role.js +74 -0
  14. package/dist/fixer-bash-seatbelt.js +13 -0
  15. package/dist/gatekeeper-pass-envelope.js +72 -0
  16. package/dist/gleaner-left-role.js +26 -0
  17. package/dist/inspector-role.js +29 -0
  18. package/dist/judge-role.js +106 -0
  19. package/dist/merger-role.js +66 -0
  20. package/dist/navigator-role.js +12 -0
  21. package/dist/notary-role.js +137 -0
  22. package/dist/oauth-keepalive.js +158 -0
  23. package/dist/package-contracts/terminating-tools.js +2 -16
  24. package/dist/packaged-role-registry.js +1 -18
  25. package/dist/pi/adapter.js +211 -0
  26. package/dist/pi/role-turn-host.js +0 -2
  27. package/dist/public-cli/instruction-seat-run.js +2 -6
  28. package/dist/public-cli/invocation.js +0 -7
  29. package/dist/public-cli/main.js +94 -191
  30. package/dist/public-cli/option-definitions.js +0 -14
  31. package/dist/public-cli/registry.js +1 -2
  32. package/dist/public-cli/run-lifecycle.js +1 -3
  33. package/dist/public-cli/settlement.js +0 -10
  34. package/dist/public-role-summons.js +0 -14
  35. package/dist/reviewer-child-executor.js +163 -70
  36. package/dist/reviewer-construction.js +2 -2
  37. package/dist/reviewer-role.js +159 -0
  38. package/dist/reviewer-settlement.js +66 -0
  39. package/dist/role-runtime.js +1394 -0
  40. package/dist/stderr-jsonl.js +26 -0
  41. package/dist/tool-execution-observation.js +141 -0
  42. package/dist/worker-role.js +343 -0
  43. package/dist/worker-submission-gates.js +305 -0
  44. package/extensions/role-runtime.ts +1 -2
  45. package/package.json +1 -1
  46. package/src/acp-host/production-host.ts +0 -1
  47. package/src/host-contracts.ts +0 -2
  48. package/src/package-contracts/terminating-tools.ts +1 -19
  49. package/src/packaged-role-registry.ts +1 -19
  50. package/src/pi/role-turn-host.ts +0 -2
  51. package/src/public-cli/cli.ts +1 -5
  52. package/src/public-cli/instruction-seat-run.ts +5 -14
  53. package/src/public-cli/invocation.ts +3 -21
  54. package/src/public-cli/option-definitions.ts +0 -16
  55. package/src/public-cli/registry.ts +1 -2
  56. package/src/public-cli/run-lifecycle.ts +0 -6
  57. package/src/public-cli/settlement.ts +0 -32
  58. package/src/public-cli/terminal.ts +0 -1
  59. package/src/public-role-summons.ts +0 -15
  60. package/src/reviewer-child-executor.ts +199 -98
  61. package/src/reviewer-construction.ts +3 -3
  62. package/src/role-runtime.ts +1 -33
  63. package/dist/package-contracts/evidence-child-output.js +0 -31
  64. package/souls/evidence-child.md +0 -1
  65. package/src/evidence-child-role.ts +0 -22
  66. package/src/package-contracts/evidence-child-output.ts +0 -46
@@ -11,7 +11,6 @@ import { COUNTERSIGN_OUTPUT_TOOL_NAME } from "./countersign-contracts.js";
11
11
  import { GLEANER_LEFT_OUTPUT_TOOL_NAME } from "./gleaner-left-contracts.js";
12
12
  import { INSPECTOR_OUTPUT_TOOL_NAME } from "./inspector-contracts.js";
13
13
  import { AUDITOR_OUTPUT_TOOL_NAME } from "./package-contracts/auditor-output.js";
14
- import { EVIDENCE_CHILD_OUTPUT_TOOL_NAME } from "./package-contracts/evidence-child-output.js";
15
14
  import {
16
15
  DIARIST_OUTPUT_TOOL_NAME,
17
16
  DIARIST_SOURCES_FLAG
@@ -36,12 +35,6 @@ const AUDITOR_PUBLIC_SESSION_MATERIALS = [
36
35
  "souls/audit-law.md",
37
36
  "souls/quality-law.md"
38
37
  ];
39
- const EVIDENCE_CHILD_SESSION_MATERIALS = [
40
- "CLAUDE.md",
41
- "souls/evidence-child.md",
42
- "souls/audit-law.md",
43
- "souls/quality-law.md"
44
- ];
45
38
  const PUBLIC_ROLE_RECORDS = [
46
39
  {
47
40
  role: "judge",
@@ -195,7 +188,7 @@ const PUBLIC_ROLE_RECORDS = [
195
188
  activationStage: "load-and-install",
196
189
  sessionMaterials: ["CLAUDE.md", "souls/navigator.md"]
197
190
  },
198
- // #675: 审刑院 / evidence-child are roles like any other — public ak-role entries.
191
+ // #675: 审刑院 is a role like any other — public ak-role entry. (#744: evidence-child deleted)
199
192
  {
200
193
  role: "auditor",
201
194
  phases: [null],
@@ -205,15 +198,6 @@ const PUBLIC_ROLE_RECORDS = [
205
198
  activationStage: "load-and-install",
206
199
  sessionMaterials: AUDITOR_PUBLIC_SESSION_MATERIALS
207
200
  },
208
- {
209
- role: "evidence-child",
210
- phases: [null],
211
- outputTool: EVIDENCE_CHILD_OUTPUT_TOOL_NAME,
212
- inputFlag: void 0,
213
- phaseFlag: void 0,
214
- activationStage: "load-and-install",
215
- sessionMaterials: EVIDENCE_CHILD_SESSION_MATERIALS
216
- },
217
201
  // #708 / ADR 0075 `diarist-is-role`: 起居郎 is a seat like any other. The
218
202
  // frozen source catalog rides the shared input-flag seam; it is absent for a
219
203
  // true-unbound summons (no ticket → no diary).
@@ -246,7 +230,6 @@ function packagedRoleOutputTool(role) {
246
230
  }
247
231
  export {
248
232
  AUDITOR_PUBLIC_SESSION_MATERIALS,
249
- EVIDENCE_CHILD_SESSION_MATERIALS,
250
233
  INSPECTOR_SESSION_MATERIALS,
251
234
  NOTARY_SESSION_MATERIALS,
252
235
  PACKAGED_ROLE_REGISTRY,
@@ -0,0 +1,211 @@
1
+ import { parseSkillBlock, } from "@earendil-works/pi-coding-agent";
2
+ import { requireGatekeeperPass } from "../gatekeeper-pass-envelope.js";
3
+ import { createOAuthKeepalive } from "../oauth-keepalive.js";
4
+ import { createRoleRuntimeExtension } from "../role-runtime.js";
5
+ import { renderAgentStartMaterials } from "../agent-start-materials.js";
6
+ const piContexts = new WeakMap();
7
+ /** Pi-only entrypoint adapter around the host-neutral shared composition. */
8
+ export function createPiRoleRuntimeExtension(dependencies, options = {}) {
9
+ return (pi) => createRoleRuntimeExtension(dependencies)(createPiRoleHostAdapter(pi, options));
10
+ }
11
+ /** Project Pi's activation context onto the package-owned host contract. */
12
+ function projectPiContext(context, transcriptFromContext) {
13
+ const sessionManager = context.sessionManager;
14
+ const host = {
15
+ cwd: context.cwd,
16
+ mode: context.mode,
17
+ model: context.model === undefined ? undefined : { provider: context.model.provider },
18
+ sessionManager: {
19
+ getLeafEntry: () => context.sessionManager.getLeafEntry(),
20
+ getLeafId: () => context.sessionManager.getLeafId(),
21
+ getEntries: () => context.sessionManager.getEntries(),
22
+ getSessionDir: () => context.sessionManager.getSessionDir(),
23
+ getSessionFile: () => context.sessionManager.getSessionFile(),
24
+ getHeader: () => context.sessionManager.getHeader(),
25
+ setSessionFile: (path) => sessionManager.setSessionFile(path),
26
+ appendCustomEntry: (customType, data) => sessionManager.appendCustomEntry(customType, data),
27
+ },
28
+ ...(context.signal === undefined ? {} : { signal: context.signal }),
29
+ ...(context.ui === undefined ? {} : { ui: { notify: (message, type) => context.ui.notify(message, type) } }),
30
+ ...(transcriptFromContext === undefined ? {} : { transcript: () => transcriptFromContext(context) }),
31
+ abort: () => context.abort(),
32
+ };
33
+ piContexts.set(host, context);
34
+ return host;
35
+ }
36
+ /** Recover the Pi context only at the Pi composition boundary. */
37
+ export function toPiContext(context) {
38
+ const piContext = piContexts.get(context);
39
+ if (piContext === undefined)
40
+ throw new Error("Host context is not backed by the Pi adapter");
41
+ return piContext;
42
+ }
43
+ /** Gatekeeper receives HostContext directly (#518 §1③) without recovering raw ExtensionContext via WeakMap. */
44
+ function requirePiGatekeeperPass(options) {
45
+ return requireGatekeeperPass({
46
+ context: options.context,
47
+ subject: options.subject,
48
+ ...(options.signal === undefined ? {} : { signal: options.signal }),
49
+ hostActions: {
50
+ failInfrastructure(error, _context, toolCallId) {
51
+ options.hostActions.failInfrastructure(error, options.context, toolCallId);
52
+ },
53
+ bindSubmissionNonPass: options.hostActions.bindSubmissionNonPass,
54
+ },
55
+ toolCallId: options.toolCallId,
56
+ });
57
+ }
58
+ function toPiResult(result) {
59
+ return result;
60
+ }
61
+ /** Fold a host before_agent_start return: push readingMaterial into the provider-visible
62
+ * systemPrompt via the shared renderer and strip the typed field before Pi sees it. */
63
+ function foldBeforeAgentStartReturn(result) {
64
+ if (result === undefined || result === null || typeof result !== "object")
65
+ return undefined;
66
+ const record = result;
67
+ const { systemPrompt, readingMaterial } = record;
68
+ const folded = readingMaterial === undefined
69
+ ? systemPrompt
70
+ : renderAgentStartMaterials(systemPrompt ?? "", [readingMaterial]);
71
+ return folded === undefined ? {} : { systemPrompt: folded };
72
+ }
73
+ function toPiToolDefinition(tool, projectContext) {
74
+ return {
75
+ name: tool.name,
76
+ label: tool.label,
77
+ description: tool.description,
78
+ ...(tool.promptSnippet === undefined ? {} : { promptSnippet: tool.promptSnippet }),
79
+ parameters: tool.parameters,
80
+ execute: async (toolCallId, params, signal, update, context) => toPiResult(await tool.execute(toolCallId, params, signal, update === undefined ? undefined : (result) => update(toPiResult(result)), projectContext(context))),
81
+ };
82
+ }
83
+ /** Pi composition boundary. Each consumed capability is adapted explicitly. */
84
+ export function createPiRoleHostAdapter(pi, options = {}) {
85
+ const keepalive = createOAuthKeepalive(options.oauthKeepalive);
86
+ const host = {
87
+ deliverSubmissionRejection(rejection) {
88
+ pi.sendMessage({
89
+ customType: "ak-role-submission-rejection",
90
+ content: "The terminal submission was rejected because it was not the sole tool call in its turn. Correct the call pattern and resubmit.",
91
+ display: true,
92
+ details: rejection,
93
+ }, { triggerTurn: true, deliverAs: "followUp" });
94
+ },
95
+ capabilities: {
96
+ skillExpansion(prompt) {
97
+ const parsed = parseSkillBlock(prompt);
98
+ if (parsed == null)
99
+ return undefined;
100
+ const userMessage = parsed.userMessage ?? "";
101
+ return Object.freeze({
102
+ name: parsed.name,
103
+ location: parsed.location,
104
+ content: parsed.content,
105
+ userMessage,
106
+ });
107
+ },
108
+ },
109
+ registerFlag: (name, definition) => pi.registerFlag(name, definition),
110
+ getFlag: (name) => pi.getFlag(name),
111
+ registerTool: (tool) => pi.registerTool(toPiToolDefinition(tool, (context) => projectPiContext(context, options.transcriptFromContext))),
112
+ getAllTools: () => pi.getAllTools().map(({ name, sourceInfo }) => ({
113
+ name,
114
+ ...(sourceInfo?.path === undefined ? {} : { sourceInfo: { path: sourceInfo.path } }),
115
+ })),
116
+ setActiveTools: (names) => pi.setActiveTools(names),
117
+ getActiveTools: () => pi.getActiveTools(),
118
+ requireGatekeeperPass: requirePiGatekeeperPass,
119
+ on(...registration) {
120
+ const context = (value) => projectPiContext(value, options.transcriptFromContext);
121
+ if (registration[0] === "before_agent_start") {
122
+ const [, handler] = registration;
123
+ pi.on("before_agent_start", (value, ctx) => {
124
+ const result = handler({ prompt: value.prompt, systemPrompt: value.systemPrompt, systemPromptOptions: value.systemPromptOptions }, context(ctx));
125
+ if (result instanceof Promise)
126
+ return result.then(foldBeforeAgentStartReturn);
127
+ return foldBeforeAgentStartReturn(result);
128
+ });
129
+ }
130
+ else if (registration[0] === "input") {
131
+ const [, handler] = registration;
132
+ pi.on("input", (value, ctx) => handler({ text: value.text, ...(value.images === undefined ? {} : { images: value.images }), source: value.source }, context(ctx)));
133
+ }
134
+ else if (registration[0] === "tool_call") {
135
+ const [, handler] = registration;
136
+ pi.on("tool_call", (value, ctx) => handler({ toolName: value.toolName, toolCallId: value.toolCallId, input: value.input }, context(ctx)));
137
+ }
138
+ else if (registration[0] === "tool_result") {
139
+ const [, handler] = registration;
140
+ pi.on("tool_result", (value, ctx) => handler({ toolName: value.toolName, toolCallId: value.toolCallId, isError: value.isError, content: (value.content ?? []).map((part) => part.type === "text" ? { type: "text", text: part.text } : { type: "image", data: part.data, mimeType: part.mimeType }), details: value.details }, context(ctx)));
141
+ }
142
+ else if (registration[0] === "session_start") {
143
+ const [, handler] = registration;
144
+ pi.on("session_start", (value, ctx) => handler({ reason: value.reason }, context(ctx)));
145
+ }
146
+ else if (registration[0] === "session_shutdown") {
147
+ const [, handler] = registration;
148
+ pi.on("session_shutdown", (_value, ctx) => handler({}, context(ctx)));
149
+ }
150
+ else if (registration[0] === "after_provider_response") {
151
+ const [, handler] = registration;
152
+ pi.on("after_provider_response", (value, ctx) => handler({ status: value.status }, context(ctx)));
153
+ }
154
+ else if (registration[0] === "agent_end") {
155
+ const [, handler] = registration;
156
+ pi.on("agent_end", (value, ctx) => handler({
157
+ messages: value.messages.map((message) => ({
158
+ role: message.role,
159
+ content: "content" in message && Array.isArray(message.content) ? message.content.map((part) => part.type === "text"
160
+ ? { type: "text", text: part.text }
161
+ : part.type === "toolCall"
162
+ ? { type: "toolCall", id: part.id, name: part.name, arguments: part.arguments }
163
+ : { type: part.type }) : [],
164
+ ...("toolName" in message && typeof message.toolName === "string" ? { toolName: message.toolName } : {}),
165
+ ...("isError" in message && typeof message.isError === "boolean" ? { isError: message.isError } : {}),
166
+ ...("stopReason" in message && typeof message.stopReason === "string" ? { stopReason: message.stopReason } : {}),
167
+ })),
168
+ }, context(ctx)));
169
+ }
170
+ else if (registration[0] === "turn_end") {
171
+ const [, handler] = registration;
172
+ pi.on("turn_end", (value, ctx) => handler({
173
+ turnIndex: value.turnIndex,
174
+ calls: value.toolResults.map((result) => ({
175
+ toolCallId: result.toolCallId,
176
+ toolName: result.toolName,
177
+ })),
178
+ }, context(ctx)));
179
+ }
180
+ else if (registration[0] === "agent_settled") {
181
+ const [, handler] = registration;
182
+ pi.on("agent_settled", (_value, ctx) => handler({}, context(ctx)));
183
+ }
184
+ else if (registration[0] === "tool_execution_start") {
185
+ const [, handler] = registration;
186
+ pi.on("tool_execution_start", (value, ctx) => handler({ toolName: value.toolName, toolCallId: value.toolCallId }, context(ctx)));
187
+ }
188
+ else if (registration[0] === "tool_execution_update") {
189
+ const [, handler] = registration;
190
+ pi.on("tool_execution_update", (value, ctx) => handler({ toolName: value.toolName, toolCallId: value.toolCallId, partialResult: value.partialResult }, context(ctx)));
191
+ }
192
+ else {
193
+ const [, handler] = registration;
194
+ pi.on("tool_execution_end", (value, ctx) => handler({ toolName: value.toolName, toolCallId: value.toolCallId, isError: value.isError }, context(ctx)));
195
+ }
196
+ },
197
+ ...(typeof pi.getCommands === "function" ? { getCommands: () => pi.getCommands().map(({ name }) => ({ name })) } : {}),
198
+ };
199
+ return {
200
+ host,
201
+ appendEntry: (customType, data) => pi.appendEntry(customType, data),
202
+ sendMessage: (message, sendOptions) => pi.sendMessage({
203
+ customType: message.customType,
204
+ content: message.content,
205
+ display: message.display ?? false,
206
+ details: message.details,
207
+ }, sendOptions),
208
+ startKeepalive: (context) => keepalive.start(toPiContext(context)),
209
+ stopKeepalive: () => keepalive.stop(),
210
+ };
211
+ }
@@ -127,8 +127,6 @@ function buildActivationFlagArgs(activation) {
127
127
  return ["--ak-role", "navigator"];
128
128
  case "auditor":
129
129
  return ["--ak-role", "auditor"];
130
- case "evidence-child":
131
- return ["--ak-role", "evidence-child"];
132
130
  case "diarist":
133
131
  return [
134
132
  "--ak-role",
@@ -1,11 +1,11 @@
1
1
  import { engineSessionMaterialFromOptions } from "../package-resources/engine-material.js";
2
2
  import { readRunTicketNumber } from "../run-ticket-number.js";
3
3
  import { CliUsageError } from "./cli-errors.js";
4
- import { admitAuditorInvocation, admitEvidenceChildInvocation, admitGatekeeperInvocation, admitNavigatorInvocation, bindAdmittedTicketNumber, buildInstructionTransportPrompt, persistAdmittedSourceRunPath, } from "./invocation.js";
4
+ import { admitAuditorInvocation, admitGatekeeperInvocation, admitNavigatorInvocation, bindAdmittedTicketNumber, buildInstructionTransportPrompt, persistAdmittedSourceRunPath, } from "./invocation.js";
5
5
  import { prepareSummonsResumeMaterials, runPostAdmissionOneShot, runPostAdmissionSeatResume, resumeTurnRequestProjectionOptions, } from "./post-admission.js";
6
6
  import { loadResumableInstructionSeatRun, markRunAdmitted, } from "./run-lifecycle.js";
7
7
  import { applyInstructionTicketProbe, probeInstructionTicket, ticketNumberFromProbe, tryResumeSameTicketSeatRun, } from "./seat-ticket-binding.js";
8
- import { presentStructuralRejection, readEngineDetourInfrastructureFailure, trySettleAuditorTerminalResult, trySettleEvidenceChildTerminalResult, trySettleGatekeeperTerminalResult, trySettleNavigatorTerminalResult, } from "./settlement.js";
8
+ import { presentStructuralRejection, readEngineDetourInfrastructureFailure, trySettleAuditorTerminalResult, trySettleGatekeeperTerminalResult, trySettleNavigatorTerminalResult, } from "./settlement.js";
9
9
  import { projectRoleTurnRequest, } from "./turn-request.js";
10
10
  /** Project an admitted instruction-seat invocation onto the host-neutral turn request. */
11
11
  export function buildInstructionSeatTurnRequest(admitted, options) {
@@ -25,8 +25,6 @@ function instructionSeatAdapters(options) {
25
25
  return trySettleNavigatorTerminalResult(admitted, authority, scope);
26
26
  case "auditor":
27
27
  return trySettleAuditorTerminalResult(admitted, authority, scope);
28
- case "evidence-child":
29
- return trySettleEvidenceChildTerminalResult(admitted, authority, scope);
30
28
  }
31
29
  },
32
30
  // Accepted receipts and failure terminals both present via shared path.
@@ -58,8 +56,6 @@ async function admitInstructionSeat(role, options) {
58
56
  return admitNavigatorInvocation(options);
59
57
  case "auditor":
60
58
  return admitAuditorInvocation(options);
61
- case "evidence-child":
62
- return admitEvidenceChildInvocation(options);
63
59
  }
64
60
  }
65
61
  export async function runPublicInstructionSeatResume(request, env, io) {
@@ -369,9 +369,6 @@ export function parseNavigatorArgv(args) {
369
369
  export function parseAuditorArgv(args) {
370
370
  return parseInstructionArgv(args, "auditor");
371
371
  }
372
- export function parseEvidenceChildArgv(args) {
373
- return parseInstructionArgv(args, "evidence-child");
374
- }
375
372
  export function parseDiaristArgv(args) {
376
373
  return parseInstructionArgv(args, "diarist");
377
374
  }
@@ -621,10 +618,6 @@ export async function admitNavigatorInvocation(options) {
621
618
  export async function admitAuditorInvocation(options) {
622
619
  return admitStandardMaterialInvocation("auditor", options);
623
620
  }
624
- /** Admit a public evidence-child run (#675). */
625
- export async function admitEvidenceChildInvocation(options) {
626
- return admitStandardMaterialInvocation("evidence-child", options);
627
- }
628
621
  /**
629
622
  * Admit a direct Diarist (起居郎) run (#708): freeze attachments, persist the
630
623
  * request, reserve session placement — same instruction-seat face.