@akagilnc/pi-workflow-roles 0.1.3572 → 0.1.3621

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 (129) hide show
  1. package/dist/acp-host/production-host.js +20239 -10556
  2. package/dist/analyst-gate-cycles-read.js +387 -0
  3. package/dist/archivist-record-entry.js +22 -1
  4. package/dist/audit-escalation.js +6 -0
  5. package/dist/auditor-soul.js +74 -0
  6. package/dist/collector-config.js +86 -0
  7. package/dist/collector-evidence.js +316 -0
  8. package/dist/collector-github.js +527 -0
  9. package/dist/collector-ledger.js +853 -0
  10. package/dist/collector-tool-schemas.js +33 -0
  11. package/dist/compliance-transport.js +104 -52
  12. package/dist/diarist-mechanical.js +411 -0
  13. package/dist/diarist-ticket-resolution.js +177 -0
  14. package/dist/diarist.js +311 -0
  15. package/dist/doctor-auditor.js +25 -0
  16. package/dist/doctor-contracts.js +2 -0
  17. package/dist/doctor-evidence.js +142 -0
  18. package/dist/gatekeeper-role.js +104 -81
  19. package/dist/host-transition-prior-native.js +78 -0
  20. package/dist/institutional-resolution.js +1 -95
  21. package/dist/judge-auditor.js +26 -0
  22. package/dist/ledger-session-read.js +227 -0
  23. package/dist/merger-git-state.js +78 -0
  24. package/dist/navigator-attendance.js +15 -7
  25. package/dist/navigator-public-session.js +170 -0
  26. package/dist/navigator-session-contracts.js +36 -40
  27. package/dist/notary-source-run.js +122 -0
  28. package/dist/package-contracts/auditor-output.js +66 -0
  29. package/dist/package-contracts/evidence-child-output.js +34 -0
  30. package/dist/package-contracts/judge-output.js +2 -0
  31. package/dist/package-contracts/terminating-tools.js +25 -2
  32. package/dist/package-resources/method-skill.js +254 -0
  33. package/dist/packaged-role-registry.js +36 -0
  34. package/dist/pi/durable-principal.js +61 -0
  35. package/dist/pi/in-process-session.js +25 -6
  36. package/dist/pi/known-failure.js +52 -0
  37. package/dist/pi/role-turn-host.js +430 -0
  38. package/dist/public-cli/auto-resume.js +414 -0
  39. package/dist/public-cli/cli-errors.js +8 -0
  40. package/dist/public-cli/cli-io.js +1 -0
  41. package/dist/public-cli/command-renderer.js +5 -0
  42. package/dist/public-cli/doctor-run.js +84 -0
  43. package/dist/public-cli/inspector-run.js +136 -0
  44. package/dist/public-cli/instruction-seat-run.js +256 -0
  45. package/dist/public-cli/invocation.js +2225 -0
  46. package/dist/public-cli/judge-run.js +118 -0
  47. package/dist/public-cli/load-production-acp-host.js +40 -0
  48. package/dist/public-cli/main.js +1140 -652
  49. package/dist/public-cli/notary-run.js +161 -0
  50. package/dist/public-cli/option-definitions.js +1192 -0
  51. package/dist/public-cli/post-admission.js +667 -0
  52. package/dist/public-cli/public-run-credentials.js +49 -0
  53. package/dist/public-cli/registry.js +4 -1
  54. package/dist/public-cli/reviewer-dispatch-rejection.js +77 -0
  55. package/dist/public-cli/run-lifecycle.js +1344 -0
  56. package/dist/public-cli/seat-ticket-binding.js +113 -0
  57. package/dist/public-cli/settlement.js +3441 -0
  58. package/dist/public-cli/terminal.js +135 -0
  59. package/dist/public-cli/turn-request.js +25 -0
  60. package/dist/public-role-summons.js +301 -0
  61. package/dist/receipt-delivery-policy.js +10 -0
  62. package/dist/reviewer-child-executor.js +80 -8
  63. package/dist/reviewer-execution-ledger.js +2 -1
  64. package/dist/run-terminal-artifacts.js +195 -0
  65. package/dist/run-ticket-number.js +40 -0
  66. package/dist/session-assistant-usage.js +107 -0
  67. package/dist/shape-unreadable-failure.js +34 -0
  68. package/dist/submission-errors.js +3 -0
  69. package/dist/submission-ledger.js +388 -0
  70. package/dist/ticket-provenance-contracts.js +115 -0
  71. package/dist/ticket-provenance.js +340 -0
  72. package/extensions/role-runtime.ts +7 -0
  73. package/package.json +1 -1
  74. package/scripts/build-package.mjs +2 -1
  75. package/souls/doctor-auditor.md +1 -0
  76. package/souls/evidence-child.md +1 -0
  77. package/src/acp-host/production-host.ts +3 -0
  78. package/src/acp-host/role-envelope.ts +2 -2
  79. package/src/acp-host/role-turn-host.ts +9 -1
  80. package/src/analyst-gate-cycles-read.ts +37 -2
  81. package/src/archivist-record-entry.ts +45 -1
  82. package/src/audit-escalation.ts +17 -0
  83. package/src/auditor-role.ts +22 -0
  84. package/src/auditor-soul.ts +42 -0
  85. package/src/compliance-transport.ts +177 -66
  86. package/src/doctor-auditor.ts +10 -14
  87. package/src/doctor-contracts.ts +1 -0
  88. package/src/doctor-role.ts +2 -2
  89. package/src/evidence-child-role.ts +22 -0
  90. package/src/gatekeeper-pass-envelope.ts +109 -0
  91. package/src/gatekeeper-role.ts +145 -104
  92. package/src/host-contracts.ts +9 -1
  93. package/src/institutional-resolution.ts +8 -163
  94. package/src/judge-auditor.ts +10 -15
  95. package/src/judge-role.ts +8 -0
  96. package/src/navigator-attendance.ts +25 -9
  97. package/src/navigator-public-session.ts +217 -0
  98. package/src/navigator-session-contracts.ts +61 -54
  99. package/src/notary-source-run.ts +3 -1
  100. package/src/package-contracts/auditor-output.ts +82 -0
  101. package/src/package-contracts/evidence-child-output.ts +51 -0
  102. package/src/package-contracts/judge-output.ts +1 -0
  103. package/src/package-contracts/reviewer-output.ts +2 -2
  104. package/src/package-contracts/terminating-tools.ts +31 -1
  105. package/src/packaged-role-registry.ts +43 -0
  106. package/src/pi/adapter.ts +2 -1
  107. package/src/pi/in-process-session.ts +38 -12
  108. package/src/pi/role-turn-host.ts +34 -0
  109. package/src/public-cli/cli.ts +14 -6
  110. package/src/public-cli/instruction-seat-run.ts +289 -50
  111. package/src/public-cli/invocation.ts +66 -25
  112. package/src/public-cli/option-definitions.ts +61 -0
  113. package/src/public-cli/post-admission.ts +7 -1
  114. package/src/public-cli/registry.ts +4 -1
  115. package/src/public-cli/run-lifecycle.ts +22 -3
  116. package/src/public-cli/settlement.ts +120 -5
  117. package/src/public-cli/terminal.ts +2 -0
  118. package/src/public-role-summons.ts +431 -0
  119. package/src/receipt-delivery-policy.ts +10 -0
  120. package/src/reviewer-agent.ts +1 -1
  121. package/src/reviewer-child-executor.ts +114 -12
  122. package/src/reviewer-execution-ledger.ts +3 -2
  123. package/src/role-runtime.ts +158 -17
  124. package/src/session-assistant-usage.ts +119 -0
  125. package/src/session-opening-materials.ts +1 -1
  126. package/src/shape-unreadable-failure.ts +49 -0
  127. package/src/submission-errors.ts +3 -0
  128. package/dist/evidence-child-executor.js +0 -829
  129. package/src/evidence-child-executor.ts +0 -1140
@@ -0,0 +1,135 @@
1
+ /**
2
+ * Terminal result: typed semantic regions for one admitted Role run (ADR 0052 / #106).
3
+ * Presentation may rearrange labels/order; only regions and typed facts are stable.
4
+ *
5
+ * Free-text cells are JSON-string encoded so legitimate newlines/tabs cannot forge
6
+ * extra rows or shift column boundaries (note / fix.summary / decision question / reason).
7
+ */
8
+ import { isPublicCallableRole, renderPublicAkRoleCommand, } from "./command-renderer.js";
9
+ /** Encode one free-text Terminal cell. JSON string form cannot embed raw tab/newline. */
10
+ export function encodeTerminalField(value) {
11
+ return JSON.stringify(value);
12
+ }
13
+ /** Lawful typed terminal results exit zero (including audit_escalation). */
14
+ export function isLawfulTypedTerminalOutcome(outcome) {
15
+ return outcome.kind === "accepted" || outcome.kind === "audit_escalation" || outcome.kind === "no_receipt";
16
+ }
17
+ export function exitCodeForTerminalOutcome(outcome) {
18
+ return isLawfulTypedTerminalOutcome(outcome) ? 0 : 1;
19
+ }
20
+ export function buildResidualIncompleteTerminalOutcome(input) {
21
+ return {
22
+ kind: "incomplete",
23
+ role: input.role,
24
+ status: "incomplete",
25
+ decision: "no-usable-result",
26
+ candidate: input.candidate,
27
+ diagnostic: input.diagnostic,
28
+ acceptedReceipt: false,
29
+ decisiveFacts: {
30
+ decision: "no-usable-result",
31
+ candidate: input.candidate,
32
+ diagnostic: input.diagnostic,
33
+ acceptedReceipt: false,
34
+ },
35
+ };
36
+ }
37
+ /** Public free-text stand-in when an exact Role run ID is stripped outside resume.command. */
38
+ export const REDACTED_RUN_ID_TOKEN = "[run-id]";
39
+ /**
40
+ * Remove an exact Role run ID from untrusted free text at the public Terminal boundary.
41
+ * Private durable artifacts keep the original bytes; only resume.command may disclose it.
42
+ */
43
+ export function redactExactRunId(text, runId) {
44
+ if (runId.length === 0)
45
+ return text;
46
+ if (!text.includes(runId))
47
+ return text;
48
+ return text.split(runId).join(REDACTED_RUN_ID_TOKEN);
49
+ }
50
+ /**
51
+ * Build a recommendation navigator fact. Command is always registry-rendered;
52
+ * any model-authored command string is ignored.
53
+ */
54
+ export function recommendationNavigatorFact(input) {
55
+ void input.modelCommand;
56
+ if (!isPublicCallableRole(input.next.role)) {
57
+ return {
58
+ disposition: "unavailable",
59
+ source: "unknown",
60
+ reason: `recommended role is not a public callable seat: ${input.next.role}`,
61
+ };
62
+ }
63
+ const command = renderPublicAkRoleCommand(input.next);
64
+ return {
65
+ disposition: "recommendation",
66
+ next: input.next,
67
+ reason: input.reason,
68
+ ...(command === undefined ? {} : { command }),
69
+ ...(input.route === undefined ? {} : { route: input.route }),
70
+ ...(input.advisoryDiagnostic === undefined ? {} : { advisoryDiagnostic: input.advisoryDiagnostic }),
71
+ };
72
+ }
73
+ /**
74
+ * Present one Terminal result for humans. Labels, row order, wording, and layout
75
+ * are unfrozen (ADR 0052). Machine consumers and tests must read typed
76
+ * TerminalResult / settlement owners — never bite this presentation.
77
+ */
78
+ export function formatTerminalResult(result) {
79
+ const lines = [];
80
+ lines.push("role\toutcome\tstatus");
81
+ const outcomeStatus = result.roleOutcome.kind === "failure"
82
+ ? result.roleOutcome.cause
83
+ : result.roleOutcome.status;
84
+ lines.push(`${result.roleOutcome.role}\t${result.roleOutcome.kind}\t${encodeTerminalField(outcomeStatus)}`);
85
+ if (result.roleOutcome.kind === "failure") {
86
+ lines.push(`diagnostic\t${encodeTerminalField(result.roleOutcome.diagnostic)}`);
87
+ }
88
+ const facts = result.roleOutcome.decisiveFacts;
89
+ for (const [key, value] of Object.entries(facts)) {
90
+ if (value === undefined)
91
+ continue;
92
+ const rendered = typeof value === "string" ? value : JSON.stringify(value);
93
+ lines.push(`fact\t${encodeTerminalField(key)}\t${encodeTerminalField(rendered)}`);
94
+ }
95
+ lines.push(`navigator\t${result.navigator.disposition}`);
96
+ if (result.navigator.advisoryDiagnostic !== undefined) {
97
+ lines.push(`navigator-advisory\t${encodeTerminalField(result.navigator.advisoryDiagnostic)}`);
98
+ }
99
+ if (result.navigator.disposition === "recommendation") {
100
+ lines.push(`next\t${result.navigator.next.role}\t${result.navigator.next.phase ?? "none"}`);
101
+ lines.push(`reason\t${encodeTerminalField(result.navigator.reason)}`);
102
+ if (result.navigator.command !== undefined) {
103
+ lines.push(`command\t${encodeTerminalField(result.navigator.command)}`);
104
+ }
105
+ }
106
+ else if (result.navigator.disposition === "unavailable") {
107
+ lines.push(`unavailable\t${result.navigator.source}\t${encodeTerminalField(result.navigator.reason)}`);
108
+ }
109
+ for (const artifact of result.artifacts) {
110
+ lines.push(`artifact\t${artifact.kind}\t${encodeTerminalField(artifact.path)}`);
111
+ }
112
+ // Gate region is unfrozen presentation of typed facts (ADR 0052) — machines
113
+ // read result.gate, never these row labels.
114
+ if (result.gate !== undefined) {
115
+ lines.push(`gate\t${encodeTerminalField(result.gate.actualSeats.join(","))}\t${result.gate.rounds.length}`);
116
+ for (const round of result.gate.rounds) {
117
+ const reason = round.dispatch.kind === "historical_dispatch"
118
+ && round.dispatch.reason !== undefined
119
+ ? encodeTerminalField(round.dispatch.reason)
120
+ : "";
121
+ lines.push(`gate-round\t${round.roundIndex}\t${round.dispatch.kind}\t${round.dispatch.officer}\t${reason}\t${round.officer.seat}\t${encodeTerminalField(round.officer.status)}\t${encodeTerminalField(JSON.stringify(round.officer.findings))}`);
122
+ }
123
+ }
124
+ if (result.resume !== undefined) {
125
+ // Resumable failure: run ID is revealed only inside the complete resume command.
126
+ lines.push(`resume\t${encodeTerminalField(result.resume.command)}`);
127
+ }
128
+ else if (result.runId !== undefined) {
129
+ lines.push(`run\t${encodeTerminalField(result.runId)}`);
130
+ }
131
+ if (result.autoResumeCount !== undefined) {
132
+ lines.push(`autoResumeCount\t${encodeTerminalField(String(result.autoResumeCount))}`);
133
+ }
134
+ return `${lines.join("\n")}\n`;
135
+ }
@@ -0,0 +1,25 @@
1
+ export function projectRoleTurnRequest(admitted, roleDetails, options) {
2
+ const cwd = admitted.projectRoot ?? admitted.repoRoot ?? admitted.cwd;
3
+ if (cwd === undefined)
4
+ throw new Error("admitted invocation missing working directory");
5
+ if (admitted.principal === undefined)
6
+ throw new Error("admitted invocation missing principal");
7
+ // #617 DK-3: turn model is the live seat/env model only — never the admitted
8
+ // birth model. Resume and new legs share this projection.
9
+ return {
10
+ principal: admitted.principal,
11
+ activation: roleDetails.activation,
12
+ methods: roleDetails.methods ?? [],
13
+ continuation: options.continuation,
14
+ ...(options.model === undefined ? {} : { model: options.model }),
15
+ ...(options.engine === undefined ? {} : { engine: options.engine }),
16
+ cwd,
17
+ home: options.home,
18
+ agentDir: options.agentDir,
19
+ runDirectory: admitted.runDirectory,
20
+ ...(options.correlationId === undefined || options.correlationId.trim() === ""
21
+ ? {}
22
+ : { correlationId: options.correlationId }),
23
+ ...(options.timeoutMs === undefined ? {} : { timeoutMs: options.timeoutMs }),
24
+ };
25
+ }
@@ -0,0 +1,301 @@
1
+ import { existsSync } from "node:fs";
2
+ import { join } from "node:path";
3
+ const AK_ROLE_PACKAGE_ROOT_ENV = "AK_ROLE_PACKAGE_ROOT";
4
+ function createCapturingIo() {
5
+ const chunks = [];
6
+ return {
7
+ io: {
8
+ stdout() {
9
+ },
10
+ stderr(text) {
11
+ chunks.push(text);
12
+ }
13
+ },
14
+ stderrText: () => chunks.join("")
15
+ };
16
+ }
17
+ function parentDir(path) {
18
+ const end = path.endsWith("/") || path.endsWith("\\") ? path.slice(0, -1) : path;
19
+ const idx = Math.max(end.lastIndexOf("/"), end.lastIndexOf("\\"));
20
+ if (idx <= 0) return end;
21
+ return end.slice(0, idx);
22
+ }
23
+ function walkPackageRoot(start) {
24
+ let dir = start;
25
+ for (let i = 0; i < 12; i += 1) {
26
+ if (existsSync(join(dir, "package.json")) && existsSync(join(dir, "souls"))) {
27
+ return dir;
28
+ }
29
+ const parent = parentDir(dir);
30
+ if (parent === dir) break;
31
+ dir = parent;
32
+ }
33
+ return void 0;
34
+ }
35
+ function resolveSummonsPackageRoot(explicit) {
36
+ if (typeof explicit === "string" && explicit.trim() !== "") {
37
+ return explicit;
38
+ }
39
+ const fromEnv = process.env[AK_ROLE_PACKAGE_ROOT_ENV];
40
+ if (typeof fromEnv === "string" && fromEnv.trim() !== "") {
41
+ return fromEnv;
42
+ }
43
+ const fromCwd = walkPackageRoot(process.cwd());
44
+ if (fromCwd !== void 0) return fromCwd;
45
+ try {
46
+ const metaUrl = import.meta.url;
47
+ if (typeof metaUrl === "string" && metaUrl.startsWith("file:")) {
48
+ const filePath = decodeURIComponent(metaUrl.slice("file://".length));
49
+ const fromMeta = walkPackageRoot(parentDir(filePath));
50
+ if (fromMeta !== void 0) return fromMeta;
51
+ }
52
+ } catch {
53
+ }
54
+ throw new Error(
55
+ "public role summons cannot resolve package root (pass packageRoot or set AK_ROLE_PACKAGE_ROOT)"
56
+ );
57
+ }
58
+ async function resolveSummonHome(options) {
59
+ if (options.home !== void 0 && options.home.trim() !== "") {
60
+ return options.home;
61
+ }
62
+ const { tryHomeFromAkRolesPath, packageMachineHome } = await import("./activation-ledger-topology.js");
63
+ const fromCwd = tryHomeFromAkRolesPath(options.cwd);
64
+ if (fromCwd !== void 0 && fromCwd.length > 0) return fromCwd;
65
+ return packageMachineHome();
66
+ }
67
+ function projectSeatEngine(seat) {
68
+ return seat.engine === void 0 ? {} : { engine: seat.engine };
69
+ }
70
+ function projectSeatHost(seat) {
71
+ return seat.host === void 0 ? {} : { host: seat.host };
72
+ }
73
+ function projectSeatModel(seat) {
74
+ return seat.selection === void 0 ? {} : { model: seat.selection };
75
+ }
76
+ async function createSummonEnv(options) {
77
+ const [{ piDurablePrincipalAuthority }, { appendPiSessionCustomEntry, createPiRoleTurnHost }] = await Promise.all([
78
+ import("./pi/durable-principal.js"),
79
+ import("./pi/role-turn-host.js")
80
+ ]);
81
+ const principalAuthority = piDurablePrincipalAuthority;
82
+ const piRecords = {
83
+ async recordLaunchedPiIdentity(runDirectory, identity) {
84
+ const { recordLaunchedPiIdentity } = await import("./public-cli/invocation.js");
85
+ return recordLaunchedPiIdentity(runDirectory, identity);
86
+ },
87
+ async recordLaunchedRolePackageIdentity(runDirectory, identity) {
88
+ const { recordLaunchedRolePackageIdentity } = await import("./public-cli/invocation.js");
89
+ return recordLaunchedRolePackageIdentity(runDirectory, identity);
90
+ },
91
+ async observeLaunchedRolePackageIdentity(root, roleEntry) {
92
+ const { observeLaunchedRolePackageIdentity } = await import("./public-cli/invocation.js");
93
+ return observeLaunchedRolePackageIdentity(root, roleEntry);
94
+ }
95
+ };
96
+ const piHost = createPiRoleTurnHost({
97
+ packageRoot: options.packageRoot,
98
+ principalAuthority,
99
+ ...options.extraPiArgs === void 0 || options.extraPiArgs.length === 0 ? {} : { extraPiArgs: options.extraPiArgs },
100
+ ...piRecords
101
+ });
102
+ const hostName = options.seat.host ?? "pi";
103
+ let roleTurnHost = piHost;
104
+ if (hostName !== "pi") {
105
+ const { lookupHostDescription } = await import("./host-descriptions.js");
106
+ const { loadProductionAcpHostFactory } = await import("./public-cli/load-production-acp-host.js");
107
+ if (lookupHostDescription(hostName) === void 0) {
108
+ throw new Error(
109
+ `public role summons host unregistered: host=${hostName} seat=${options.role}`
110
+ );
111
+ }
112
+ let hostPromise;
113
+ roleTurnHost = {
114
+ executeTurn: async (request) => {
115
+ hostPromise ??= loadProductionAcpHostFactory(options.packageRoot, hostName).then(
116
+ (create) => create({
117
+ packageRoot: options.packageRoot,
118
+ principalAuthority
119
+ })
120
+ );
121
+ return (await hostPromise).executeTurn(request);
122
+ }
123
+ };
124
+ }
125
+ return {
126
+ home: options.home,
127
+ principalAuthority,
128
+ agentDir: options.agentDir,
129
+ sessionAppender: appendPiSessionCustomEntry,
130
+ packageRoot: options.packageRoot,
131
+ roleTurnHost,
132
+ cwd: options.cwd,
133
+ credentials: options.credentials,
134
+ ...projectSeatModel(options.seat),
135
+ ...projectSeatEngine(options.seat),
136
+ ...projectSeatHost(options.seat)
137
+ };
138
+ }
139
+ async function summonPublicRole(options) {
140
+ const packageRoot = resolveSummonsPackageRoot(options.packageRoot);
141
+ const home = await resolveSummonHome(options);
142
+ const agentDir = options.agentDir ?? process.env.PI_CODING_AGENT_DIR ?? join(home, ".pi", "agent");
143
+ const {
144
+ loadCredentialProviders,
145
+ loadPublicCliConfig,
146
+ resolveEffectiveSeat
147
+ } = await import("./public-cli/config.js");
148
+ const credentials = options.credentials ?? await loadCredentialProviders(agentDir);
149
+ const config = await loadPublicCliConfig(home);
150
+ const seat = resolveEffectiveSeat(config, options.role, credentials);
151
+ const env = {
152
+ ...await createSummonEnv({
153
+ role: options.role,
154
+ home,
155
+ agentDir,
156
+ cwd: options.cwd,
157
+ packageRoot,
158
+ credentials,
159
+ seat,
160
+ ...options.extraPiArgs === void 0 ? {} : { extraPiArgs: options.extraPiArgs }
161
+ }),
162
+ // Host config passthrough only — same face as public CLI (#422 / #675).
163
+ ...config.autoResumeLimit === void 0 ? {} : { autoResumeLimit: config.autoResumeLimit },
164
+ // Parent cancellation reaches the nested activation's own turn dispatch.
165
+ ...options.signal === void 0 ? {} : { signal: options.signal }
166
+ };
167
+ const captured = options.io === void 0 ? createCapturingIo() : void 0;
168
+ const io = options.io ?? captured.io;
169
+ let result;
170
+ switch (options.role) {
171
+ case "notary": {
172
+ const [{ runPublicNotary }, { parseNotaryArgv }] = await Promise.all([
173
+ import("./public-cli/notary-run.js"),
174
+ import("./public-cli/invocation.js")
175
+ ]);
176
+ result = await runPublicNotary(options.argv, env, io, parseNotaryArgv);
177
+ break;
178
+ }
179
+ case "inspector": {
180
+ const [{ runPublicInspector }, { parseInspectorArgv }] = await Promise.all([
181
+ import("./public-cli/inspector-run.js"),
182
+ import("./public-cli/invocation.js")
183
+ ]);
184
+ result = await runPublicInspector(options.argv, env, io, parseInspectorArgv);
185
+ break;
186
+ }
187
+ case "auditor": {
188
+ const [{ runPublicInstructionSeat }, { parseAuditorArgv }] = await Promise.all([
189
+ import("./public-cli/instruction-seat-run.js"),
190
+ import("./public-cli/invocation.js")
191
+ ]);
192
+ result = await runPublicInstructionSeat(
193
+ options.argv,
194
+ env,
195
+ io,
196
+ "auditor",
197
+ parseAuditorArgv
198
+ );
199
+ break;
200
+ }
201
+ case "evidence-child": {
202
+ const [{ runPublicInstructionSeat }, { parseEvidenceChildArgv }] = await Promise.all([
203
+ import("./public-cli/instruction-seat-run.js"),
204
+ import("./public-cli/invocation.js")
205
+ ]);
206
+ result = await runPublicInstructionSeat(
207
+ options.argv,
208
+ env,
209
+ io,
210
+ "evidence-child",
211
+ parseEvidenceChildArgv
212
+ );
213
+ break;
214
+ }
215
+ case "navigator": {
216
+ const [{ runPublicInstructionSeat }, { parseNavigatorArgv }] = await Promise.all([
217
+ import("./public-cli/instruction-seat-run.js"),
218
+ import("./public-cli/invocation.js")
219
+ ]);
220
+ result = await runPublicInstructionSeat(
221
+ options.argv,
222
+ env,
223
+ io,
224
+ "navigator",
225
+ parseNavigatorArgv
226
+ );
227
+ break;
228
+ }
229
+ case "gatekeeper": {
230
+ const [{ runPublicInstructionSeat }, { parseGatekeeperArgv }] = await Promise.all([
231
+ import("./public-cli/instruction-seat-run.js"),
232
+ import("./public-cli/invocation.js")
233
+ ]);
234
+ result = await runPublicInstructionSeat(
235
+ options.argv,
236
+ env,
237
+ io,
238
+ "gatekeeper",
239
+ parseGatekeeperArgv
240
+ );
241
+ break;
242
+ }
243
+ case "judge": {
244
+ const [{ runPublicJudge }, { parseJudgeArgv }] = await Promise.all([
245
+ import("./public-cli/judge-run.js"),
246
+ import("./public-cli/invocation.js")
247
+ ]);
248
+ result = await runPublicJudge(options.argv, env, io, parseJudgeArgv);
249
+ break;
250
+ }
251
+ case "doctor": {
252
+ const [{ runPublicDoctor }, { parseDoctorArgv }] = await Promise.all([
253
+ import("./public-cli/doctor-run.js"),
254
+ import("./public-cli/invocation.js")
255
+ ]);
256
+ result = await runPublicDoctor(options.argv, env, io, parseDoctorArgv);
257
+ break;
258
+ }
259
+ }
260
+ const stderr = captured?.stderrText();
261
+ const runDirectory = result.admitted?.runDirectory;
262
+ return {
263
+ exitCode: result.exitCode,
264
+ ...result.terminal === void 0 ? {} : { terminal: result.terminal },
265
+ ...typeof runDirectory === "string" && runDirectory.trim() !== "" ? { runDirectory } : {},
266
+ ...stderr === void 0 || stderr === "" ? {} : { stderr }
267
+ };
268
+ }
269
+ async function summonGateOfficer(options) {
270
+ let home = options.home;
271
+ if (home === void 0) {
272
+ const { homeFromRunDirectory } = await import("./activation-ledger-topology.js");
273
+ home = homeFromRunDirectory(options.sourceRunDirectory);
274
+ }
275
+ if (options.officer === "notary") {
276
+ return summonPublicRole({
277
+ role: "notary",
278
+ argv: ["--source-run", options.sourceRunDirectory, "--project", options.cwd],
279
+ cwd: options.cwd,
280
+ ...home === void 0 ? {} : { home },
281
+ ...options.packageRoot === void 0 ? {} : { packageRoot: options.packageRoot },
282
+ ...options.io === void 0 ? {} : { io: options.io },
283
+ ...options.signal === void 0 ? {} : { signal: options.signal }
284
+ });
285
+ }
286
+ return summonPublicRole({
287
+ role: "inspector",
288
+ argv: [`\u5377\u5B97\u6307\u9488\uFF1A${options.sourceRunDirectory}`],
289
+ cwd: options.cwd,
290
+ ...home === void 0 ? {} : { home },
291
+ ...options.packageRoot === void 0 ? {} : { packageRoot: options.packageRoot },
292
+ ...options.io === void 0 ? {} : { io: options.io },
293
+ ...options.signal === void 0 ? {} : { signal: options.signal }
294
+ });
295
+ }
296
+ export {
297
+ AK_ROLE_PACKAGE_ROOT_ENV,
298
+ resolveSummonsPackageRoot,
299
+ summonGateOfficer,
300
+ summonPublicRole
301
+ };
@@ -60,6 +60,16 @@ function createReceiptDeliveryPolicy() {
60
60
  recordDeliveryRequest() {
61
61
  deliveryTurns = Math.min(RECEIPT_DELIVERY_TURN_LIMIT, deliveryTurns + 1);
62
62
  },
63
+ /**
64
+ * A nested session settled without an accepted receipt after spending its own
65
+ * delivery budget. Adopt its facts and close this budget: another prompt would
66
+ * open an independent session, not a delivery request on the settled one.
67
+ */
68
+ recordNestedNoReceipt(facts) {
69
+ terminalToolCalled = terminalToolCalled || facts.terminalToolCalled;
70
+ rejectedReceipts.push(...facts.rejectedReceipts);
71
+ deliveryTurns = RECEIPT_DELIVERY_TURN_LIMIT;
72
+ },
63
73
  nextAction() {
64
74
  if (accepted) return "accepted";
65
75
  return deliveryTurns < RECEIPT_DELIVERY_TURN_LIMIT ? "request-delivery" : "no-receipt";
@@ -1,4 +1,4 @@
1
- import { executeEvidenceChild } from "./evidence-child-executor.js";
1
+ import { auditorRunDirectory } from "./auditor-dossier-tool.js";
2
2
  /**
3
3
  * Single conversion at the Reviewer adapter boundary: shared child classifications
4
4
  * become Reviewer failure classifications without a second error taxonomy.
@@ -12,15 +12,87 @@ export function projectSharedChildFailure(error) {
12
12
  }
13
13
  return error;
14
14
  }
15
- /** Reviewer policy adapter over the shared evidence-child lifecycle seam. */
15
+ function failureClassification(cause) {
16
+ if (cause === "provider")
17
+ return "provider";
18
+ if (cause === "output"
19
+ || cause === "timeout"
20
+ || cause === "activation"
21
+ || cause === "session"
22
+ || cause === "unrecognized") {
23
+ return "child";
24
+ }
25
+ return "unknown";
26
+ }
27
+ function reportFromSummon(summoned) {
28
+ const outcome = summoned.terminal?.roleOutcome;
29
+ if (outcome === undefined) {
30
+ throw Object.assign(new Error(`Evidence-child public summon produced no terminal (exit ${summoned.exitCode})`), { evidenceChildFailure: "child" });
31
+ }
32
+ if (outcome.kind === "failure") {
33
+ throw Object.assign(new Error(outcome.diagnostic), {
34
+ evidenceChildFailure: failureClassification(outcome.cause),
35
+ });
36
+ }
37
+ if (outcome.kind === "accepted") {
38
+ // No field-presence reject (ADR 0055 / #675). Keep original accepted bytes:
39
+ // report key when present, otherwise the whole decisiveFacts body.
40
+ const facts = outcome.decisiveFacts;
41
+ if (Object.hasOwn(facts, "report"))
42
+ return facts.report;
43
+ return facts;
44
+ }
45
+ throw Object.assign(new Error("Evidence-child public summon returned no accepted report body"), { evidenceChildFailure: "child" });
46
+ }
47
+ /** Reviewer evidence leg via the public evidence-child activation path (#675). */
16
48
  export async function executeReviewerChild(workspace, leg, context, options = {}) {
17
49
  try {
18
- return await executeEvidenceChild(workspace, leg.prompt, context, {
19
- ...(options.signal === undefined ? {} : { signal: options.signal }),
20
- ...(options.credentialScratchParent === undefined ? {} : { credentialScratchParent: options.credentialScratchParent }),
21
- ...(options.runDirectory === undefined ? {} : { runDirectory: options.runDirectory }),
22
- ...(options.packageRoot === undefined ? {} : { packageRoot: options.packageRoot }),
23
- });
50
+ if (options.signal?.aborted) {
51
+ throw Object.assign(new DOMException("The operation was aborted.", "AbortError"), {
52
+ evidenceChildFailure: "child",
53
+ });
54
+ }
55
+ const runDirectory = options.runDirectory ?? auditorRunDirectory(context);
56
+ const pointer = runDirectory === undefined
57
+ ? ""
58
+ : `\n卷宗指针:${runDirectory}`;
59
+ const argv = [`${String(leg.prompt)}${pointer}`];
60
+ const summon = options.summonEvidenceChild
61
+ ?? (async (nextArgv, childSignal) => {
62
+ const { summonPublicRole } = await import("./public-role-summons.js");
63
+ // Parent run home owns nested public seats; leg workspace cwd is a bare worktree.
64
+ let home;
65
+ if (runDirectory !== undefined) {
66
+ const { homeFromRunDirectory } = await import("./activation-ledger-topology.js");
67
+ // Hard path resolve: fail loud — no packageMachineHome fallback (#604 / #675).
68
+ home = homeFromRunDirectory(runDirectory);
69
+ }
70
+ return summonPublicRole({
71
+ role: "evidence-child",
72
+ argv: nextArgv,
73
+ cwd: workspace,
74
+ ...(home === undefined ? {} : { home }),
75
+ ...(options.packageRoot === undefined ? {} : { packageRoot: options.packageRoot }),
76
+ ...(childSignal === undefined ? {} : { signal: childSignal }),
77
+ });
78
+ });
79
+ const summoned = await summon(argv, options.signal);
80
+ if (options.signal?.aborted) {
81
+ throw Object.assign(new DOMException("The operation was aborted.", "AbortError"), {
82
+ evidenceChildFailure: "child",
83
+ });
84
+ }
85
+ const report = reportFromSummon(summoned);
86
+ const { usageFromPublicSummon } = await import("./session-assistant-usage.js");
87
+ // Real session usage when present; no session → token-zero without inventing cost.
88
+ const usage = (await usageFromPublicSummon(summoned)) ?? {
89
+ input: 0,
90
+ output: 0,
91
+ cacheRead: 0,
92
+ cacheWrite: 0,
93
+ totalTokens: 0,
94
+ };
95
+ return { report, usage, prompt: leg.prompt };
24
96
  }
25
97
  catch (error) {
26
98
  throw projectSharedChildFailure(error);
@@ -129,7 +129,8 @@ export function createReviewerExecutionLedger() {
129
129
  if (!sameReviewerPinnedTarget(event.target, accepted.target))
130
130
  throw new Error("Runner target does not match shared pinned target");
131
131
  if (event.status === "successful") {
132
- if (typeof event.report !== "string" || event.report.length === 0 || event.failure !== undefined)
132
+ // Report field required; no type/blank reshape gate (ADR 0055 / #675).
133
+ if (event.report === undefined || event.failure !== undefined)
133
134
  throw new Error("Successful settlement requires a report");
134
135
  }
135
136
  else if (event.failure === undefined || event.report !== undefined) {