@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.
- package/dist/acp-host/production-host.js +20239 -10556
- package/dist/analyst-gate-cycles-read.js +387 -0
- package/dist/archivist-record-entry.js +22 -1
- package/dist/audit-escalation.js +6 -0
- package/dist/auditor-soul.js +74 -0
- package/dist/collector-config.js +86 -0
- package/dist/collector-evidence.js +316 -0
- package/dist/collector-github.js +527 -0
- package/dist/collector-ledger.js +853 -0
- package/dist/collector-tool-schemas.js +33 -0
- package/dist/compliance-transport.js +104 -52
- package/dist/diarist-mechanical.js +411 -0
- package/dist/diarist-ticket-resolution.js +177 -0
- package/dist/diarist.js +311 -0
- package/dist/doctor-auditor.js +25 -0
- package/dist/doctor-contracts.js +2 -0
- package/dist/doctor-evidence.js +142 -0
- package/dist/gatekeeper-role.js +104 -81
- package/dist/host-transition-prior-native.js +78 -0
- package/dist/institutional-resolution.js +1 -95
- package/dist/judge-auditor.js +26 -0
- package/dist/ledger-session-read.js +227 -0
- package/dist/merger-git-state.js +78 -0
- package/dist/navigator-attendance.js +15 -7
- package/dist/navigator-public-session.js +170 -0
- package/dist/navigator-session-contracts.js +36 -40
- package/dist/notary-source-run.js +122 -0
- package/dist/package-contracts/auditor-output.js +66 -0
- package/dist/package-contracts/evidence-child-output.js +34 -0
- package/dist/package-contracts/judge-output.js +2 -0
- package/dist/package-contracts/terminating-tools.js +25 -2
- package/dist/package-resources/method-skill.js +254 -0
- package/dist/packaged-role-registry.js +36 -0
- package/dist/pi/durable-principal.js +61 -0
- package/dist/pi/in-process-session.js +25 -6
- package/dist/pi/known-failure.js +52 -0
- package/dist/pi/role-turn-host.js +430 -0
- package/dist/public-cli/auto-resume.js +414 -0
- package/dist/public-cli/cli-errors.js +8 -0
- package/dist/public-cli/cli-io.js +1 -0
- package/dist/public-cli/command-renderer.js +5 -0
- package/dist/public-cli/doctor-run.js +84 -0
- package/dist/public-cli/inspector-run.js +136 -0
- package/dist/public-cli/instruction-seat-run.js +256 -0
- package/dist/public-cli/invocation.js +2225 -0
- package/dist/public-cli/judge-run.js +118 -0
- package/dist/public-cli/load-production-acp-host.js +40 -0
- package/dist/public-cli/main.js +1140 -652
- package/dist/public-cli/notary-run.js +161 -0
- package/dist/public-cli/option-definitions.js +1192 -0
- package/dist/public-cli/post-admission.js +667 -0
- package/dist/public-cli/public-run-credentials.js +49 -0
- package/dist/public-cli/registry.js +4 -1
- package/dist/public-cli/reviewer-dispatch-rejection.js +77 -0
- package/dist/public-cli/run-lifecycle.js +1344 -0
- package/dist/public-cli/seat-ticket-binding.js +113 -0
- package/dist/public-cli/settlement.js +3441 -0
- package/dist/public-cli/terminal.js +135 -0
- package/dist/public-cli/turn-request.js +25 -0
- package/dist/public-role-summons.js +301 -0
- package/dist/receipt-delivery-policy.js +10 -0
- package/dist/reviewer-child-executor.js +80 -8
- package/dist/reviewer-execution-ledger.js +2 -1
- package/dist/run-terminal-artifacts.js +195 -0
- package/dist/run-ticket-number.js +40 -0
- package/dist/session-assistant-usage.js +107 -0
- package/dist/shape-unreadable-failure.js +34 -0
- package/dist/submission-errors.js +3 -0
- package/dist/submission-ledger.js +388 -0
- package/dist/ticket-provenance-contracts.js +115 -0
- package/dist/ticket-provenance.js +340 -0
- package/extensions/role-runtime.ts +7 -0
- package/package.json +1 -1
- package/scripts/build-package.mjs +2 -1
- package/souls/doctor-auditor.md +1 -0
- package/souls/evidence-child.md +1 -0
- package/src/acp-host/production-host.ts +3 -0
- package/src/acp-host/role-envelope.ts +2 -2
- package/src/acp-host/role-turn-host.ts +9 -1
- package/src/analyst-gate-cycles-read.ts +37 -2
- package/src/archivist-record-entry.ts +45 -1
- package/src/audit-escalation.ts +17 -0
- package/src/auditor-role.ts +22 -0
- package/src/auditor-soul.ts +42 -0
- package/src/compliance-transport.ts +177 -66
- package/src/doctor-auditor.ts +10 -14
- package/src/doctor-contracts.ts +1 -0
- package/src/doctor-role.ts +2 -2
- package/src/evidence-child-role.ts +22 -0
- package/src/gatekeeper-pass-envelope.ts +109 -0
- package/src/gatekeeper-role.ts +145 -104
- package/src/host-contracts.ts +9 -1
- package/src/institutional-resolution.ts +8 -163
- package/src/judge-auditor.ts +10 -15
- package/src/judge-role.ts +8 -0
- package/src/navigator-attendance.ts +25 -9
- package/src/navigator-public-session.ts +217 -0
- package/src/navigator-session-contracts.ts +61 -54
- package/src/notary-source-run.ts +3 -1
- package/src/package-contracts/auditor-output.ts +82 -0
- package/src/package-contracts/evidence-child-output.ts +51 -0
- package/src/package-contracts/judge-output.ts +1 -0
- package/src/package-contracts/reviewer-output.ts +2 -2
- package/src/package-contracts/terminating-tools.ts +31 -1
- package/src/packaged-role-registry.ts +43 -0
- package/src/pi/adapter.ts +2 -1
- package/src/pi/in-process-session.ts +38 -12
- package/src/pi/role-turn-host.ts +34 -0
- package/src/public-cli/cli.ts +14 -6
- package/src/public-cli/instruction-seat-run.ts +289 -50
- package/src/public-cli/invocation.ts +66 -25
- package/src/public-cli/option-definitions.ts +61 -0
- package/src/public-cli/post-admission.ts +7 -1
- package/src/public-cli/registry.ts +4 -1
- package/src/public-cli/run-lifecycle.ts +22 -3
- package/src/public-cli/settlement.ts +120 -5
- package/src/public-cli/terminal.ts +2 -0
- package/src/public-role-summons.ts +431 -0
- package/src/receipt-delivery-policy.ts +10 -0
- package/src/reviewer-agent.ts +1 -1
- package/src/reviewer-child-executor.ts +114 -12
- package/src/reviewer-execution-ledger.ts +3 -2
- package/src/role-runtime.ts +158 -17
- package/src/session-assistant-usage.ts +119 -0
- package/src/session-opening-materials.ts +1 -1
- package/src/shape-unreadable-failure.ts +49 -0
- package/src/submission-errors.ts +3 -0
- package/dist/evidence-child-executor.js +0 -829
- 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 {
|
|
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
|
-
|
|
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
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
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
|
-
|
|
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) {
|