@akagilnc/pi-workflow-roles 0.1.4021 → 0.1.4062

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 (74) hide show
  1. package/dist/acp-host/production-host.js +682 -355
  2. package/dist/doctor-auditor.js +1 -1
  3. package/dist/dossier-resolution.js +21 -8
  4. package/dist/gatekeeper-role.js +34 -27
  5. package/dist/headless-host/description.js +7 -8
  6. package/dist/headless-host/production-host.js +709 -369
  7. package/dist/host-contracts.js +16 -0
  8. package/dist/inspector-contracts.js +8 -0
  9. package/dist/navigator-attendance.js +2 -0
  10. package/dist/navigator-public-session.js +18 -34
  11. package/dist/navigator-session-contracts.js +19 -0
  12. package/dist/packaged-role-registry.js +1 -1
  13. package/dist/pi/known-failure.js +3 -4
  14. package/dist/pi/role-turn-host.js +43 -13
  15. package/dist/public-cli/auto-resume.js +20 -7
  16. package/dist/public-cli/case-dossier-delivery.js +60 -1
  17. package/dist/public-cli/diarist-run.js +9 -23
  18. package/dist/public-cli/inspector-run.js +17 -3
  19. package/dist/public-cli/instruction-seat-run.js +12 -7
  20. package/dist/public-cli/judge-run.js +3 -1
  21. package/dist/public-cli/main.js +440 -222
  22. package/dist/public-cli/notary-run.js +7 -4
  23. package/dist/public-cli/post-admission.js +66 -59
  24. package/dist/public-cli/run-lifecycle.js +3 -0
  25. package/dist/public-cli/settlement.js +78 -58
  26. package/dist/public-cli/terminal.js +1 -11
  27. package/dist/public-role-summons.js +8 -0
  28. package/dist/submission-ledger.js +139 -19
  29. package/dist/user-dialogue-stdin.js +33 -0
  30. package/extensions/role-runtime.ts +1 -0
  31. package/package.json +1 -1
  32. package/resources/836-deleted-machine-instruction-inventory.md +1 -1
  33. package/src/doctor-auditor.ts +1 -1
  34. package/src/dossier-resolution.ts +26 -8
  35. package/src/external-host-turn-loop.ts +9 -0
  36. package/src/gatekeeper-pass-envelope.ts +6 -0
  37. package/src/gatekeeper-role.ts +47 -28
  38. package/src/headless-host/description.ts +8 -11
  39. package/src/headless-host/role-turn-host.ts +20 -5
  40. package/src/host-contracts.ts +30 -7
  41. package/src/inspector-contracts.ts +7 -0
  42. package/src/judge-role.ts +4 -0
  43. package/src/navigator-attendance.ts +2 -0
  44. package/src/navigator-public-session.ts +19 -55
  45. package/src/navigator-session-contracts.ts +39 -0
  46. package/src/navigator-work-context.ts +3 -4
  47. package/src/notary-role.ts +1 -0
  48. package/src/packaged-role-registry.ts +1 -1
  49. package/src/pi/adapter.ts +19 -4
  50. package/src/pi/known-failure.ts +3 -4
  51. package/src/pi/role-turn-host.ts +48 -14
  52. package/src/public-cli/auto-resume.ts +57 -20
  53. package/src/public-cli/case-dossier-delivery.ts +86 -1
  54. package/src/public-cli/cli.ts +2 -2
  55. package/src/public-cli/collector-run.ts +3 -1
  56. package/src/public-cli/countersign-run.ts +34 -27
  57. package/src/public-cli/diarist-run.ts +10 -27
  58. package/src/public-cli/inspector-run.ts +26 -2
  59. package/src/public-cli/instruction-seat-run.ts +20 -10
  60. package/src/public-cli/invocation.ts +2 -0
  61. package/src/public-cli/judge-run.ts +3 -1
  62. package/src/public-cli/notary-run.ts +13 -4
  63. package/src/public-cli/post-admission.ts +74 -65
  64. package/src/public-cli/reviewer-run.ts +3 -1
  65. package/src/public-cli/run-lifecycle.ts +3 -0
  66. package/src/public-cli/settlement.ts +105 -80
  67. package/src/public-cli/terminal.ts +7 -16
  68. package/src/public-role-summons.ts +31 -7
  69. package/src/role-envelope.ts +9 -30
  70. package/src/role-runtime-dependencies.ts +1 -0
  71. package/src/role-runtime.ts +95 -19
  72. package/src/submission-ledger.ts +195 -26
  73. package/src/user-dialogue-stdin.ts +37 -0
  74. package/src/worker-role.ts +4 -0
@@ -8,7 +8,7 @@ export const DOCTOR_AUDIT_TOOL_NAME = "ak_doctor_audit_decision";
8
8
  */
9
9
  export function createPiDoctorAuditor() {
10
10
  return async (options) => {
11
- const dossier = resolveAuditDossier();
11
+ const dossier = resolveAuditDossier(options.context);
12
12
  requireAuditMaterials(dossier);
13
13
  const subjects = readDoctorAuditSubjects(options.context);
14
14
  requireAuditMaterials(subjects);
@@ -1,23 +1,36 @@
1
1
  /**
2
2
  * Unique dossier-resolution seam for 审刑院 (#233).
3
- * Machine pointers only: cwd + AK_ROLE_RUN_DIR. No latest-run / mtime / global scan.
3
+ * Machine pointers only: cwd + per-turn HostContext (Pi child env fallback).
4
+ * No latest-run / mtime / global scan.
4
5
  */
5
6
  import { existsSync, statSync } from "node:fs";
6
7
  import { resolve } from "node:path";
8
+ import { runDirectoryFromHostContext } from "./host-contracts.js";
7
9
  export const AUDIT_RUN_DIR_ENV = "AK_ROLE_RUN_DIR";
8
10
  export const DOCTOR_CANDIDATE_ENTRY_TYPE = "ak_doctor_audit_candidate";
11
+ function isHostContext(value) {
12
+ return "sessionManager" in value;
13
+ }
14
+ function dossierPointerFrom(source) {
15
+ if (source !== undefined && isHostContext(source)) {
16
+ return runDirectoryFromHostContext(source);
17
+ }
18
+ const env = source ?? process.env;
19
+ const raw = env[AUDIT_RUN_DIR_ENV];
20
+ return typeof raw === "string" && raw.trim() !== "" ? raw : undefined;
21
+ }
9
22
  /**
10
- * Resolve the per-run dossier pointer injected by the public CLI.
23
+ * Resolve the per-run dossier pointer.
11
24
  *
25
+ * ACP/headless: typed HostContext.runDirectory.
26
+ * Pi child: HostContext projected from env, or env fallback when no context.
12
27
  * Absent pointer = bare Pi internal seam (ADR 0052): audit proceeds; the model
13
- * self-locates the dossier from its own fall-volume position per soul. Public CLI
14
- * always injects the pointer — only then does the machine validate the path.
15
- * Concurrent runs stay isolated because a present pointer is per-process.
28
+ * self-locates the dossier from its own fall-volume position per soul.
16
29
  */
17
- export function resolveAuditDossier(env = process.env) {
18
- const raw = env[AUDIT_RUN_DIR_ENV];
30
+ export function resolveAuditDossier(source) {
31
+ const raw = dossierPointerFrom(source);
19
32
  // Bare Pi activation seam: no machine gate when the pointer was never injected.
20
- if (typeof raw !== "string" || raw.trim() === "") {
33
+ if (raw === undefined) {
21
34
  return { status: "ok" };
22
35
  }
23
36
  const runDirectory = resolve(raw);
@@ -84,15 +84,26 @@ function projectOfficerDecision(officer, decision, fallbackStatus) {
84
84
  return { status: "needs_reask", officer, receipt };
85
85
  }
86
86
  /**
87
- * Project a public-role terminal onto the gate queue surface.
88
- * Host failure stays failure; recorded officer payloads ride beside it (#836 A.3).
89
- * Multiple recorded payloads are all kept — code does not pick last-wins.
87
+ * This-court officer payloads for the parent return path (#879).
88
+ * Only settlement-scoped roleOutcome.payloads (courtAttempt seal) carry this-court
89
+ * identity. Never guess from undivided submissions — sole row included — history
90
+ * stays on terminal.submissions (#836 presentation).
90
91
  */
91
- function officerPayloads(terminal) {
92
+ function thisCourtOfficerPayloads(terminal) {
92
93
  const outcome = terminal?.roleOutcome;
93
94
  if (outcome !== undefined && (outcome.kind === "accepted" || outcome.kind === "audit_escalation")) {
94
- return outcome.payloads ?? terminal?.submissions ?? [];
95
+ if (outcome.payloads !== undefined && outcome.payloads.length > 0)
96
+ return outcome.payloads;
97
+ }
98
+ if (outcome?.kind === "failure" && outcome.payloads !== undefined && outcome.payloads.length > 0) {
99
+ return outcome.payloads;
95
100
  }
101
+ // No sole-row identity guess: undivided submissions are not this-court (#879).
102
+ return [];
103
+ }
104
+ /** Failure/transport channel may still surface every recorded payload beside the failure (#836 A.3). */
105
+ function officerFailurePayloads(terminal) {
106
+ const outcome = terminal?.roleOutcome;
96
107
  if (outcome?.kind === "failure")
97
108
  return outcome.payloads ?? terminal?.submissions ?? [];
98
109
  return terminal?.submissions ?? [];
@@ -101,32 +112,24 @@ function projectOfficerPayloads(officer, payloads, fallbackStatus) {
101
112
  if (payloads.length === 0) {
102
113
  return projectOfficerDecision(officer, undefined, fallbackStatus);
103
114
  }
104
- // Present every recorded payload; queue only the latest conclusion so a reask
105
- // can converge (#836 呈现 ≠ 排队).
106
- const queued = projectOfficerDecision(officer, payloads[payloads.length - 1], fallbackStatus);
107
- if (payloads.length === 1)
108
- return queued;
109
- if (queued.status === "pass"
110
- || queued.status === "bounce"
111
- || queued.status === "escalate"
112
- || queued.status === "needs_reask") {
113
- return { ...queued, receipt: payloads };
114
- }
115
- return queued;
115
+ // This-court multi-submit: queue the latest seal of THIS court only (#836 呈现≠排队).
116
+ // Single this-court seal is the common path. Never fold history into an array receipt.
117
+ return projectOfficerDecision(officer, payloads[payloads.length - 1], fallbackStatus);
116
118
  }
117
119
  function projectOfficerTerminal(officer, summoned) {
118
120
  const terminal = summoned.terminal;
119
121
  const outcome = terminal?.roleOutcome;
120
- const recorded = officerPayloads(terminal);
122
+ const thisCourt = thisCourtOfficerPayloads(terminal);
121
123
  if (outcome === undefined) {
122
124
  const detail = summoned.stderr ?? "";
125
+ const failurePayloads = officerFailurePayloads(terminal);
123
126
  return {
124
127
  status: "transport_failure",
125
128
  stage: officer,
126
129
  reason: detail.length > 0
127
130
  ? `${gateSeatLabel(officer)} public summon exit ${summoned.exitCode}: ${detail}`
128
131
  : `${gateSeatLabel(officer)} public summon produced no terminal (exit ${summoned.exitCode})`,
129
- submission: recorded.length > 0 ? recorded : summoned,
132
+ submission: failurePayloads.length > 0 ? failurePayloads : summoned,
130
133
  };
131
134
  }
132
135
  if (outcome.kind === "no_receipt") {
@@ -140,30 +143,33 @@ function projectOfficerTerminal(officer, summoned) {
140
143
  };
141
144
  }
142
145
  if (outcome.kind === "failure") {
146
+ const failurePayloads = officerFailurePayloads(terminal);
143
147
  return {
144
148
  status: "transport_failure",
145
149
  stage: officer,
146
150
  reason: outcome.diagnostic,
147
- submission: recorded.length > 0 ? recorded : outcome.decisiveFacts,
151
+ submission: failurePayloads.length > 0 ? failurePayloads : outcome.decisiveFacts,
148
152
  };
149
153
  }
150
154
  if (outcome.kind === "audit_escalation") {
151
155
  return {
152
156
  status: "escalate",
153
157
  officer,
154
- receipt: recorded.length === 1 ? recorded[0] : recorded,
158
+ // This-court receipt only (#879) — historical rows remain on terminal.submissions.
159
+ receipt: thisCourt.length > 0 ? thisCourt[thisCourt.length - 1] : retainedReceipt(outcome),
155
160
  };
156
161
  }
157
162
  if (outcome.kind === "accepted") {
158
163
  // outcome.status is the fixture/compat leaf: production settlement leaves
159
164
  // it undefined once payloads are recorded, so this only matters when a
160
165
  // caller still supplies status without any recorded payload (#836 hang).
161
- return projectOfficerPayloads(officer, recorded, outcome.status);
166
+ return projectOfficerPayloads(officer, thisCourt, outcome.status);
162
167
  }
163
168
  return {
164
169
  status: "needs_reask",
165
170
  officer,
166
- receipt: recorded.length > 0 ? recorded : retainedReceipt(outcome),
171
+ // This-court receipt only (#879).
172
+ receipt: thisCourt.length > 0 ? thisCourt[thisCourt.length - 1] : retainedReceipt(outcome),
167
173
  };
168
174
  }
169
175
  /**
@@ -188,12 +194,12 @@ export async function projectGatekeeperRun(options) {
188
194
  },
189
195
  };
190
196
  }
191
- // #836: officers receive the whole parent run directory pointer and find the
192
- // submission themselves — code no longer picks latest toolCall leaf (A7.1–A7.3).
197
+ // #879: binding pointer = parent run directory; dialogue content = this-turn
198
+ // typed payload passed explicitly (never latest-toolCall recovery, A7.1–A7.3).
193
199
  let summoned;
194
200
  try {
195
201
  const summon = options.summonOfficer
196
- ?? (async (nextOfficer, sourceRunDirectory, officerSignal, reask) => {
202
+ ?? (async (nextOfficer, sourceRunDirectory, officerSignal, reask, nextSubmission) => {
197
203
  const { summonGateOfficer } = await import("./public-role-summons.js");
198
204
  return summonGateOfficer({
199
205
  officer: nextOfficer,
@@ -201,13 +207,14 @@ export async function projectGatekeeperRun(options) {
201
207
  cwd: options.context.cwd ?? process.cwd(),
202
208
  ...(officerSignal === undefined ? {} : { signal: officerSignal }),
203
209
  ...(reask === undefined ? {} : { reask }),
210
+ ...(nextSubmission === undefined ? {} : { submission: nextSubmission }),
204
211
  ...(options.home === undefined ? {} : { home: options.home }),
205
212
  ...(options.packageRoot === undefined ? {} : { packageRoot: options.packageRoot }),
206
213
  ...(options.roleTurnHost === undefined ? {} : { roleTurnHost: options.roleTurnHost }),
207
214
  ...(options.createRunId === undefined ? {} : { createRunId: options.createRunId }),
208
215
  });
209
216
  });
210
- summoned = await summon(officer, runDirectory, options.signal, options.reask);
217
+ summoned = await summon(officer, runDirectory, options.signal, options.reask, options.submission);
211
218
  }
212
219
  catch (error) {
213
220
  return {
@@ -17,13 +17,13 @@ export function resolveHeadlessBinary(description, operatorHome) {
17
17
  }
18
18
  /**
19
19
  * Build one Claude print-mode argv for a single process turn.
20
- * Shape: `<promptFlag> <prompt> <fixedArgs…> <system/schema/mcp/model/effort/session…>`.
20
+ * Shape: `<promptFlag> <fixedArgs…> <system/schema/mcp/model/effort/session…>`.
21
+ * User dialogue rides stdin, not an argv element (#879 / ARG_MAX).
21
22
  */
22
23
  export function headlessTurnArgs(options) {
23
24
  const { description } = options;
24
25
  const args = [
25
26
  description.promptFlag,
26
- options.prompt,
27
27
  ...description.fixedArgs,
28
28
  description.systemPromptFlag,
29
29
  options.systemPromptPath,
@@ -308,8 +308,8 @@ function codexMcpConfigArgs(mcpServers) {
308
308
  }
309
309
  /**
310
310
  * Build one `codex exec` / `codex exec resume` argv (#646).
311
- * New: `exec --approve-for-me … prompt`.
312
- * Resume: `exec --approve-for-me resume <thread_id> … prompt`.
311
+ * New: `exec --approve-for-me … -- -` (prompt on stdin).
312
+ * Resume: `exec --approve-for-me resume <thread_id> … -- -`.
313
313
  * Approval stays on the parent command so new and resumed turns use Codex's
314
314
  * automatic review with its workspace-write sandbox.
315
315
  */
@@ -346,10 +346,9 @@ export function codexTurnArgs(options) {
346
346
  if (options.skipGitRepoCheck === true) {
347
347
  args.push("--skip-git-repo-check");
348
348
  }
349
- // Prompt last as positional. `--` stops option parsing so a leading `-`
350
- // (markdown lists, pasted flags, rulings) is not eaten by clap (codex tip:
351
- // "use '-- -s'"). Same for new and resume — both end here.
352
- args.push("--", options.prompt);
349
+ // `-` after `--` is Codex's stdin prompt sentinel. `--` still stops option
350
+ // parsing; the user body itself is not an argv element (#879 / ARG_MAX).
351
+ args.push("--", "-");
353
352
  return args;
354
353
  }
355
354
  /**