@akagilnc/pi-workflow-roles 0.1.3837 → 0.1.3884
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/README.md +2 -2
- package/README.zh-CN.md +3 -3
- package/dist/acp-host/production-host.js +22736 -22720
- package/dist/engine-detour-tool.js +2 -2
- package/dist/engine-detour.js +23 -7
- package/dist/headless-host/production-host.js +4926 -4926
- package/dist/host-descriptions.js +5 -2
- package/dist/merger-contracts.js +23 -42
- package/dist/merger-git-state.js +69 -42
- package/dist/merger-role.js +30 -41
- package/dist/pi/role-turn-host.js +20 -92
- package/dist/public-cli/invocation.js +12 -39
- package/dist/public-cli/load-production-acp-host.js +1 -1
- package/dist/public-cli/load-production-external-host.js +10 -0
- package/dist/public-cli/load-production-headless-host.js +1 -1
- package/dist/public-cli/main.js +314 -433
- package/dist/public-cli/option-definitions.js +5 -5
- package/dist/public-cli/run-lifecycle.js +0 -2
- package/dist/public-role-summons.js +7 -49
- package/dist/reviewer-agent.js +1 -0
- package/dist/reviewer-child-executor.js +3 -2
- package/dist/role-activation-flags.js +50 -0
- package/dist/role-runtime.js +9 -16
- package/extensions/role-runtime.ts +0 -3
- package/package.json +1 -1
- package/scripts/build-package.mjs +2 -2
- package/souls/merger.md +1 -1
- package/src/acp-host/production-host.ts +31 -94
- package/src/acp-host/role-turn-host.ts +178 -263
- package/src/diagnostic-tail.ts +18 -0
- package/src/engine-detour-tool.ts +5 -4
- package/src/engine-detour.ts +44 -9
- package/src/external-host-turn-loop.ts +172 -0
- package/src/headless-host/production-host.ts +10 -7
- package/src/headless-host/role-turn-host.ts +271 -263
- package/src/host-descriptions.ts +5 -2
- package/src/host-session-record.ts +41 -0
- package/src/merger-contracts.ts +24 -38
- package/src/merger-git-state.ts +67 -37
- package/src/merger-role.ts +52 -48
- package/src/pi/role-turn-host.ts +18 -93
- package/src/prepared-role-turn.ts +68 -0
- package/src/public-cli/cli.ts +11 -20
- package/src/public-cli/invocation.ts +13 -44
- package/src/public-cli/load-production-acp-host.ts +2 -1
- package/src/public-cli/load-production-external-host.ts +17 -0
- package/src/public-cli/load-production-headless-host.ts +2 -1
- package/src/public-cli/merger-run.ts +2 -113
- package/src/public-cli/option-definitions.ts +5 -5
- package/src/public-cli/run-lifecycle.ts +0 -2
- package/src/public-role-summons.ts +12 -69
- package/src/reviewer-agent.ts +12 -1
- package/src/reviewer-child-executor.ts +10 -2
- package/src/role-activation-flags.ts +53 -0
- package/src/{acp-host/role-envelope.ts → role-envelope.ts} +28 -84
- package/src/role-runtime-dependencies.ts +89 -0
- package/src/role-runtime.ts +16 -17
- package/src/{acp-host/session-identity.ts → session-identity.ts} +6 -6
- /package/src/{acp-host/mcp-relay.mjs → mcp-relay.mjs} +0 -0
|
@@ -552,7 +552,7 @@ const NOTARY_OPTIONS = [
|
|
|
552
552
|
},
|
|
553
553
|
];
|
|
554
554
|
const MERGER_OPTIONS = [
|
|
555
|
-
// Merger project face
|
|
555
|
+
// Merger project face: worktree whose Git materials are handed to the role.
|
|
556
556
|
{
|
|
557
557
|
id: "project",
|
|
558
558
|
owner: "merger",
|
|
@@ -563,8 +563,8 @@ const MERGER_OPTIONS = [
|
|
|
563
563
|
repeatable: false,
|
|
564
564
|
form: "option",
|
|
565
565
|
description: {
|
|
566
|
-
en: "Project root
|
|
567
|
-
zh: "
|
|
566
|
+
en: "Project root whose Git merge materials are read (defaults to cwd).",
|
|
567
|
+
zh: "读取 Git merge 材料的项目根(默认 cwd)。",
|
|
568
568
|
},
|
|
569
569
|
},
|
|
570
570
|
bindOwner("merger", SHARED_ATTACH_SEMANTICS),
|
|
@@ -1003,10 +1003,10 @@ const ROLE_COMMAND_HELP = {
|
|
|
1003
1003
|
},
|
|
1004
1004
|
merger: {
|
|
1005
1005
|
command: "merger",
|
|
1006
|
-
summary: "
|
|
1006
|
+
summary: "Reconcile merge materials in a worktree (escalate when nothing to merge).",
|
|
1007
1007
|
usage: ["ak-role merger [options] <instruction>"],
|
|
1008
1008
|
examples: [
|
|
1009
|
-
'ak-role merger --project /path/to/worktree "Reconcile the
|
|
1009
|
+
'ak-role merger --project /path/to/worktree "Reconcile the merge."',
|
|
1010
1010
|
],
|
|
1011
1011
|
},
|
|
1012
1012
|
inspector: {
|
|
@@ -997,7 +997,6 @@ async function loadResumableRunRecord(home, runId, authority) {
|
|
|
997
997
|
const d = record.derived;
|
|
998
998
|
if (typeof d.targetObjectId === "string" &&
|
|
999
999
|
typeof d.sourceObjectId === "string" &&
|
|
1000
|
-
typeof d.automaticMergeTreeId === "string" &&
|
|
1001
1000
|
Array.isArray(d.expectedConflictPaths) &&
|
|
1002
1001
|
Array.isArray(d.resolutionScope) &&
|
|
1003
1002
|
d.expectedConflictPaths.every((p) => typeof p === "string") &&
|
|
@@ -1005,7 +1004,6 @@ async function loadResumableRunRecord(home, runId, authority) {
|
|
|
1005
1004
|
derived = {
|
|
1006
1005
|
targetObjectId: d.targetObjectId,
|
|
1007
1006
|
sourceObjectId: d.sourceObjectId,
|
|
1008
|
-
automaticMergeTreeId: d.automaticMergeTreeId,
|
|
1009
1007
|
expectedConflictPaths: d.expectedConflictPaths,
|
|
1010
1008
|
resolutionScope: d.resolutionScope,
|
|
1011
1009
|
};
|
|
@@ -100,24 +100,17 @@ async function createSummonEnv(options) {
|
|
|
100
100
|
let roleTurnHost = piHost;
|
|
101
101
|
if (hostName !== "pi") {
|
|
102
102
|
const { lookupHostFamily } = await import("./host-descriptions.js");
|
|
103
|
-
const {
|
|
103
|
+
const { createLazyProductionExternalHost } = await import("./public-cli/load-production-external-host.js");
|
|
104
104
|
if (lookupHostFamily(hostName) === void 0) {
|
|
105
105
|
throw new Error(
|
|
106
106
|
`public role summons host unregistered: host=${hostName} seat=${options.role}`
|
|
107
107
|
);
|
|
108
108
|
}
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
packageRoot: options.packageRoot,
|
|
115
|
-
principalAuthority
|
|
116
|
-
})
|
|
117
|
-
);
|
|
118
|
-
return (await hostPromise).executeTurn(request);
|
|
119
|
-
}
|
|
120
|
-
};
|
|
109
|
+
roleTurnHost = createLazyProductionExternalHost({
|
|
110
|
+
packageRoot: options.packageRoot,
|
|
111
|
+
hostName,
|
|
112
|
+
principalAuthority
|
|
113
|
+
});
|
|
121
114
|
}
|
|
122
115
|
const { loadHostProvidersTable, projectHostFacingProvider } = await import("./public-cli/host-providers.js");
|
|
123
116
|
const hostFacingSelection = options.seat.selection === void 0 ? void 0 : projectHostFacingProvider(
|
|
@@ -151,8 +144,7 @@ async function summonPublicRole(options) {
|
|
|
151
144
|
} = await import("./public-cli/config.js");
|
|
152
145
|
const credentials = options.credentials ?? await loadCredentialProviders(agentDir);
|
|
153
146
|
const config = await loadPublicCliConfig(home);
|
|
154
|
-
const
|
|
155
|
-
const seat = resolveEffectiveSeat(config, options.role, credentials, invocation);
|
|
147
|
+
const seat = resolveEffectiveSeat(config, options.role, credentials);
|
|
156
148
|
const env = {
|
|
157
149
|
...await createSummonEnv({
|
|
158
150
|
role: options.role,
|
|
@@ -264,38 +256,6 @@ async function summonPublicRole(options) {
|
|
|
264
256
|
...stderr === void 0 || stderr === "" ? {} : { stderr }
|
|
265
257
|
};
|
|
266
258
|
}
|
|
267
|
-
async function parentInvocationHost(sourceRunDirectory) {
|
|
268
|
-
const { readFile } = await import("node:fs/promises");
|
|
269
|
-
const path = join(sourceRunDirectory, "invocation.json");
|
|
270
|
-
let text;
|
|
271
|
-
try {
|
|
272
|
-
text = await readFile(path, "utf8");
|
|
273
|
-
} catch (error) {
|
|
274
|
-
const code = error instanceof Error && "code" in error ? error.code : void 0;
|
|
275
|
-
throw new Error(
|
|
276
|
-
`parent invocation.json required for gate source run at ${path}: ${code ?? (error instanceof Error ? error.message : String(error))}`,
|
|
277
|
-
{ cause: error }
|
|
278
|
-
);
|
|
279
|
-
}
|
|
280
|
-
let raw;
|
|
281
|
-
try {
|
|
282
|
-
raw = JSON.parse(text);
|
|
283
|
-
} catch (error) {
|
|
284
|
-
throw new Error(
|
|
285
|
-
`parent invocation.json unreadable at ${path}: ${error instanceof Error ? error.message : String(error)}`,
|
|
286
|
-
{ cause: error }
|
|
287
|
-
);
|
|
288
|
-
}
|
|
289
|
-
if (typeof raw !== "object" || raw === null || Array.isArray(raw)) {
|
|
290
|
-
throw new Error(`parent invocation.json has non-object shape at ${path}`);
|
|
291
|
-
}
|
|
292
|
-
const host = raw.host;
|
|
293
|
-
if (host === void 0) return void 0;
|
|
294
|
-
if (typeof host !== "string" || host.trim() === "") {
|
|
295
|
-
throw new Error(`parent invocation.json host must be a non-empty string at ${path}`);
|
|
296
|
-
}
|
|
297
|
-
return host;
|
|
298
|
-
}
|
|
299
259
|
async function summonGateOfficer(options) {
|
|
300
260
|
let home = options.home;
|
|
301
261
|
if (home === void 0) {
|
|
@@ -309,7 +269,6 @@ async function summonGateOfficer(options) {
|
|
|
309
269
|
submission: options.submission
|
|
310
270
|
});
|
|
311
271
|
}
|
|
312
|
-
const parentHost = await parentInvocationHost(options.sourceRunDirectory);
|
|
313
272
|
const common = {
|
|
314
273
|
cwd: options.cwd,
|
|
315
274
|
...home === void 0 ? {} : { home },
|
|
@@ -318,7 +277,6 @@ async function summonGateOfficer(options) {
|
|
|
318
277
|
...options.signal === void 0 ? {} : { signal: options.signal },
|
|
319
278
|
...options.reask === void 0 ? {} : { reviewReask: options.reask },
|
|
320
279
|
...gateReviewInstruction === void 0 ? {} : { gateReviewInstruction },
|
|
321
|
-
...parentHost === void 0 ? {} : { host: parentHost },
|
|
322
280
|
...options.roleTurnHost === void 0 ? {} : { roleTurnHost: options.roleTurnHost },
|
|
323
281
|
...options.createRunId === void 0 ? {} : { createRunId: options.createRunId }
|
|
324
282
|
};
|
package/dist/reviewer-agent.js
CHANGED
|
@@ -76,6 +76,7 @@ export function createReviewerAgentRunner(dependencies = {}) {
|
|
|
76
76
|
...(dependencies.packageRoot === undefined
|
|
77
77
|
? {}
|
|
78
78
|
: { packageRoot: dependencies.packageRoot }),
|
|
79
|
+
...(options.getFlag === undefined ? {} : { getFlag: options.getFlag }),
|
|
79
80
|
});
|
|
80
81
|
const disposition = await workspaceOwner.dispose(workspace);
|
|
81
82
|
return [leg.axis, Object.freeze({ status: "successful", report: child.report, usage: child.usage, target: batch.target, prompt: child.prompt, workspaceDisposition: disposition })];
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { createEngineDetourToolDefinition } from "./engine-detour-tool.js";
|
|
2
|
-
import {
|
|
2
|
+
import { resolveEngineName } from "./engine-detour.js";
|
|
3
3
|
import { appendEngineSessionMaterial, engineSessionMaterialFromOptions, } from "./package-resources/engine-material.js";
|
|
4
4
|
import { readPackageMaterial } from "./session-opening-materials.js";
|
|
5
5
|
import { hasUpstreamErrorTestimony, isNonSuccessHttpStatus } from "./upstream-error-testimony.js";
|
|
@@ -98,7 +98,8 @@ export async function executeReviewerChild(workspace, leg, context, options = {}
|
|
|
98
98
|
const selection = await parentSelection(context);
|
|
99
99
|
const { openPiInProcessSession } = await import("./pi/in-process-session.js");
|
|
100
100
|
const { createRecordSession } = await import("./archivist-record-entry.js");
|
|
101
|
-
|
|
101
|
+
// One gate with parent registration (#818): request flag, else pi child env.
|
|
102
|
+
const engineName = resolveEngineName(options.getFlag);
|
|
102
103
|
const engineMaterial = engineName === undefined
|
|
103
104
|
? undefined
|
|
104
105
|
: options.packageRoot === undefined || options.packageRoot.trim() === ""
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { packagedRoleInputFlag, packagedRolePhaseFlag } from "./packaged-role-registry.js";
|
|
2
|
+
/** Project closed RoleTurnActivation onto the shared host flag map. */
|
|
3
|
+
export function projectActivationFlags(request) {
|
|
4
|
+
const activation = request.activation;
|
|
5
|
+
const flags = new Map([["ak-role", activation.role]]);
|
|
6
|
+
const inputFlag = packagedRoleInputFlag(activation.role);
|
|
7
|
+
const phaseFlag = packagedRolePhaseFlag(activation.role);
|
|
8
|
+
if ("phase" in activation && phaseFlag !== undefined)
|
|
9
|
+
flags.set(phaseFlag, activation.phase);
|
|
10
|
+
if (inputFlag !== undefined) {
|
|
11
|
+
const path = "taskPath" in activation ? activation.taskPath
|
|
12
|
+
: "packetPath" in activation ? activation.packetPath
|
|
13
|
+
: "casePath" in activation ? activation.casePath
|
|
14
|
+
: "inputPath" in activation ? activation.inputPath
|
|
15
|
+
: "sourceRun" in activation ? activation.sourceRun
|
|
16
|
+
: undefined;
|
|
17
|
+
if (path !== undefined)
|
|
18
|
+
flags.set(inputFlag, path);
|
|
19
|
+
}
|
|
20
|
+
if (activation.role === "fixer" && activation.prerequisitesPath !== undefined) {
|
|
21
|
+
flags.set("ak-fixer-prerequisites", activation.prerequisitesPath);
|
|
22
|
+
}
|
|
23
|
+
if (activation.role === "reviewer") {
|
|
24
|
+
flags.set("ak-review-base", activation.baseRevision);
|
|
25
|
+
flags.set("ak-review-authority-refs", JSON.stringify(activation.authorityRefs));
|
|
26
|
+
if (activation.ticketNumber !== undefined) {
|
|
27
|
+
flags.set("ak-review-ticket-number", String(activation.ticketNumber));
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
// countersign ticketNumber stays on activation/admission/invocation only —
|
|
31
|
+
// no private transport flag (inner-gate material path deleted in #632).
|
|
32
|
+
if (activation.role === "notary" && activation.ticketNumber !== undefined) {
|
|
33
|
+
flags.set("ak-notary-ticket-number", String(activation.ticketNumber));
|
|
34
|
+
}
|
|
35
|
+
if (activation.role === "gleaner-left") {
|
|
36
|
+
flags.set("ak-gleaner-left-base", activation.baseRevision);
|
|
37
|
+
}
|
|
38
|
+
if (activation.role === "collector") {
|
|
39
|
+
flags.set("ak-collector-repo", activation.repo);
|
|
40
|
+
// #676 D1: pr optional at admission; omit flag when role binds from materials.
|
|
41
|
+
if (activation.pr !== undefined)
|
|
42
|
+
flags.set("ak-collector-pr", activation.pr);
|
|
43
|
+
if (activation.requestManifestPath !== undefined) {
|
|
44
|
+
flags.set("ak-collector-request-manifest", activation.requestManifestPath);
|
|
45
|
+
}
|
|
46
|
+
if (activation.waitMs !== undefined)
|
|
47
|
+
flags.set("ak-collector-wait-ms", activation.waitMs);
|
|
48
|
+
}
|
|
49
|
+
return flags;
|
|
50
|
+
}
|
package/dist/role-runtime.js
CHANGED
|
@@ -1090,7 +1090,12 @@ export function createRoleRuntimeExtension(dependencies) {
|
|
|
1090
1090
|
async runDispatch(dispatch, options) {
|
|
1091
1091
|
if (dependencies.runReviewerDispatch === undefined)
|
|
1092
1092
|
throw new Error("Reviewer runtime dependencies are not configured");
|
|
1093
|
-
|
|
1093
|
+
// #818: request-scoped engine flag reaches axis sub-session via same RoleHost
|
|
1094
|
+
// that parent registerEngineDetourTool reads — never ambient process.env.
|
|
1095
|
+
return dependencies.runReviewerDispatch(dispatch, {
|
|
1096
|
+
...options,
|
|
1097
|
+
getFlag: (name) => roleHost.getFlag(name),
|
|
1098
|
+
});
|
|
1094
1099
|
},
|
|
1095
1100
|
...(dependencies.shutdownReviewerAgent === undefined
|
|
1096
1101
|
? {}
|
|
@@ -1171,19 +1176,12 @@ export function createRoleRuntimeExtension(dependencies) {
|
|
|
1171
1176
|
return dependencies.loadDiaristSoul();
|
|
1172
1177
|
},
|
|
1173
1178
|
});
|
|
1174
|
-
let sessionMergerGitState = dependencies.mergerGitState;
|
|
1175
1179
|
const merger = createMergerRoleRuntime(roleHost, {
|
|
1176
1180
|
async loadSoul() { if (!dependencies.loadMergerSoul)
|
|
1177
1181
|
throw new Error("Merger runtime dependencies are not configured"); return dependencies.loadMergerSoul(); },
|
|
1178
1182
|
async loadInput(path) { if (!dependencies.loadMergerInput)
|
|
1179
1183
|
throw new Error("Merger runtime dependencies are not configured"); return dependencies.loadMergerInput(path); },
|
|
1180
|
-
|
|
1181
|
-
activeMerge() { if (!sessionMergerGitState)
|
|
1182
|
-
throw new Error("Merger runtime dependencies are not configured"); return sessionMergerGitState.activeMerge(); },
|
|
1183
|
-
completedMerge(mergeCommitId, automaticMergeTreeId) { if (!sessionMergerGitState)
|
|
1184
|
-
throw new Error("Merger runtime dependencies are not configured"); return sessionMergerGitState.completedMerge(mergeCommitId, automaticMergeTreeId); },
|
|
1185
|
-
},
|
|
1186
|
-
}, hostActions);
|
|
1184
|
+
});
|
|
1187
1185
|
// #676 E: shared envelope owns collector lifecycle (mode/fork, tool surface,
|
|
1188
1186
|
// event gates). Role module supplies business activate/tools/materials only.
|
|
1189
1187
|
let activeCollector;
|
|
@@ -1463,11 +1461,6 @@ export function createRoleRuntimeExtension(dependencies) {
|
|
|
1463
1461
|
auditor,
|
|
1464
1462
|
diarist,
|
|
1465
1463
|
merger: async () => {
|
|
1466
|
-
if (dependencies.mergerGitState === undefined) {
|
|
1467
|
-
sessionMergerGitState = dependencies.createMergerGitState?.(ctx.cwd);
|
|
1468
|
-
}
|
|
1469
|
-
if (sessionMergerGitState === undefined)
|
|
1470
|
-
throw new Error("Merger runtime dependencies are not configured");
|
|
1471
1464
|
await merger.activate();
|
|
1472
1465
|
},
|
|
1473
1466
|
};
|
|
@@ -1567,8 +1560,8 @@ export function createRoleRuntimeExtension(dependencies) {
|
|
|
1567
1560
|
}
|
|
1568
1561
|
}
|
|
1569
1562
|
await executeActivationStage(entry.role, activationStage(entry.role, runtime), { clock, writeTrace });
|
|
1570
|
-
// #357 T2 / #378 / #380 / #391: any role+engine activation registers the package detour tool once.
|
|
1571
|
-
// Gate is env
|
|
1563
|
+
// #357 T2 / #378 / #380 / #391 / #818: any role+engine activation registers the package detour tool once.
|
|
1564
|
+
// Gate is resolveEngineName (RoleHost flag → env fallback) — no per-engine execute branch; no role-module spawn.
|
|
1572
1565
|
if (!engineDetourRegistered) {
|
|
1573
1566
|
engineDetourRegistered = registerEngineDetourTool(roleHost, hostActions);
|
|
1574
1567
|
}
|
|
@@ -32,7 +32,6 @@ import { loadPackagedCanonicalSkillBinding } from "../src/package-resources/meth
|
|
|
32
32
|
import { JUDGE_OUTPUT_TOOL_NAME } from "../src/package-contracts/judge-output.ts";
|
|
33
33
|
import { readOAuthKeepaliveProviders } from "../src/oauth-keepalive.ts";
|
|
34
34
|
import {
|
|
35
|
-
createProductionMergerGitState,
|
|
36
35
|
formatNavigatorRoleHelp,
|
|
37
36
|
} from "../src/role-runtime.ts";
|
|
38
37
|
import { loadAuditorSoulFromSubjectInput } from "../src/auditor-soul.ts";
|
|
@@ -160,8 +159,6 @@ export default function roleRuntime(pi: ExtensionAPI): void {
|
|
|
160
159
|
},
|
|
161
160
|
loadMergerSoul: () => loadMainRoleSessionMaterials("merger"),
|
|
162
161
|
loadMergerInput: async (path) => JSON.parse(await readFile(path, "utf8")),
|
|
163
|
-
createMergerGitState: (repositoryRoot) =>
|
|
164
|
-
createProductionMergerGitState(repositoryRoot),
|
|
165
162
|
async loadCanonicalSkillBinding(name) {
|
|
166
163
|
// Coder TDD (#109) and Reviewer code-review (#111) are package-owned.
|
|
167
164
|
// Optional Fixer diagnosing-bugs is available via --skill without this binding.
|
package/package.json
CHANGED
|
@@ -109,7 +109,7 @@ export async function buildAcpProductionHost(
|
|
|
109
109
|
});
|
|
110
110
|
// role-envelope resolves ./mcp-relay.mjs from import.meta.url — keep it beside the bundle.
|
|
111
111
|
await copyFile(
|
|
112
|
-
resolve("src/
|
|
112
|
+
resolve("src/mcp-relay.mjs"),
|
|
113
113
|
join(dirname(outfile), "mcp-relay.mjs"),
|
|
114
114
|
);
|
|
115
115
|
}
|
|
@@ -136,7 +136,7 @@ export async function buildHeadlessProductionHost(
|
|
|
136
136
|
// Shared envelope resolves ./mcp-relay.mjs from import.meta.url of the bundle
|
|
137
137
|
// (#645 headless reuses the ACP relay for AK tools under --mcp-config).
|
|
138
138
|
await copyFile(
|
|
139
|
-
resolve("src/
|
|
139
|
+
resolve("src/mcp-relay.mjs"),
|
|
140
140
|
join(dirname(outfile), "mcp-relay.mjs"),
|
|
141
141
|
);
|
|
142
142
|
}
|
package/souls/merger.md
CHANGED
|
@@ -6,108 +6,44 @@
|
|
|
6
6
|
* factory does not create a run-scoped agent home, does not rewrite HOME, and
|
|
7
7
|
* does not copy or scrub credentials. Sitian records on the run are the dossier.
|
|
8
8
|
*/
|
|
9
|
-
import {
|
|
10
|
-
import { fileURLToPath } from "node:url";
|
|
9
|
+
import { randomUUID } from "node:crypto";
|
|
11
10
|
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
15
|
-
import {
|
|
16
|
-
import
|
|
17
|
-
import { createProductionMergerGitState } from "../merger-git-state.ts";
|
|
18
|
-
import { createNativeNavigatorSessionFactory, createNavigatorAttendance } from "../navigator-attendance.ts";
|
|
19
|
-
import { loadNavigatorWorkContext } from "../navigator-work-context.ts";
|
|
20
|
-
import { loadNotarySourceRunLocator } from "../notary-source-run.ts";
|
|
21
|
-
import { loadPackagedCanonicalSkillBinding } from "../package-resources/method-skill-binding.ts";
|
|
22
|
-
import { createPerDispatchReviewerAgent } from "../reviewer-agent.ts";
|
|
23
|
-
import { formatNavigatorRoleHelp, type RoleRuntimeDependencies } from "../role-runtime.ts";
|
|
24
|
-
import { createReviewerPinnedGitReader } from "../reviewer-pinned-git.ts";
|
|
25
|
-
import { loadAuditorSoulFromSubjectInput } from "../auditor-soul.ts";
|
|
26
|
-
import { loadGatekeeperSessionMaterials, loadMainRoleSessionMaterials } from "../session-opening-materials.ts";
|
|
11
|
+
import type { DurablePrincipalAuthority, RoleTurnHost, RoleTurnRequest } from "../host-contracts.ts";
|
|
12
|
+
import { prepareRoleEnvelope } from "../role-envelope.ts";
|
|
13
|
+
import type { RoleRuntimeDependencies } from "../role-runtime.ts";
|
|
14
|
+
import { createRoleRuntimeDependencies } from "../role-runtime-dependencies.ts";
|
|
15
|
+
import { createSessionIdentityAuthority } from "../session-identity.ts";
|
|
27
16
|
import { acpStdioArgs, resolveAcpBinary, type AcpHostDescription } from "./description.ts";
|
|
28
|
-
import {
|
|
29
|
-
|
|
17
|
+
import {
|
|
18
|
+
connectAcpStdio,
|
|
19
|
+
createAcpRoleTurnHost,
|
|
20
|
+
type AcpRoleTurnHostConfig,
|
|
21
|
+
} from "./role-turn-host.ts";
|
|
30
22
|
import { ensureSeatProfileSoul } from "./seat-profile-soul.ts";
|
|
31
|
-
import { createAcpSessionIdentityAuthority } from "./session-identity.ts";
|
|
32
23
|
|
|
33
24
|
export type ProductionAcpHostOptions = Readonly<{
|
|
34
25
|
packageRoot: string;
|
|
35
26
|
principalAuthority: DurablePrincipalAuthority;
|
|
36
27
|
description: AcpHostDescription;
|
|
28
|
+
/** Seat-table host key (e.g. grok-build). */
|
|
29
|
+
hostName: string;
|
|
37
30
|
}>;
|
|
38
31
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
)
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
loadJudgeSoul: () => loadMainRoleSessionMaterials("judge"),
|
|
53
|
-
loadFixerSoul: () => loadMainRoleSessionMaterials("fixer"),
|
|
54
|
-
loadFixPacket: (path) => readFile(path, "utf8"),
|
|
55
|
-
loadCoderSoul: () => loadMainRoleSessionMaterials("coder"),
|
|
56
|
-
loadCoderTask: (path) => readFile(path, "utf8"),
|
|
57
|
-
loadReviewerSoul: () => loadMainRoleSessionMaterials("reviewer"),
|
|
58
|
-
createReviewerPinnedGitReader: () => createReviewerPinnedGitReader(),
|
|
59
|
-
createReviewerIssueFetcher: () => createGhIssueSoftFetcher(),
|
|
60
|
-
loadCollectorSoul: () => loadMainRoleSessionMaterials("collector"),
|
|
61
|
-
loadCollectorHandbookSeed: () => readFile(collectorHandbookSeedPath, "utf8"),
|
|
62
|
-
createCollectorTransport: () => createGhCollectorGitHubTransport(),
|
|
63
|
-
loadDoctorSoul: () => loadMainRoleSessionMaterials("doctor"),
|
|
64
|
-
loadDoctorCase,
|
|
65
|
-
loadInspectorSoul: () => loadMainRoleSessionMaterials("inspector"),
|
|
66
|
-
loadGatekeeperSoul: () => loadGatekeeperSessionMaterials("gatekeeper"),
|
|
67
|
-
loadNavigatorSoul: () => loadMainRoleSessionMaterials("navigator"),
|
|
68
|
-
loadAuditorSoul: () => loadAuditorSoulFromSubjectInput(),
|
|
69
|
-
loadNotarySoul: () => loadMainRoleSessionMaterials("notary"),
|
|
70
|
-
loadCountersignSoul: () => loadMainRoleSessionMaterials("countersign"),
|
|
71
|
-
loadGleanerLeftSoul: () => loadMainRoleSessionMaterials("gleaner-left"),
|
|
72
|
-
loadDiaristSoul: () => loadMainRoleSessionMaterials("diarist"),
|
|
73
|
-
loadNotarySourceRun: loadNotarySourceRunLocator,
|
|
74
|
-
loadMergerSoul: () => loadMainRoleSessionMaterials("merger"),
|
|
75
|
-
loadMergerInput: async (path) => JSON.parse(await readFile(path, "utf8")),
|
|
76
|
-
createMergerGitState: (repositoryRoot) => createProductionMergerGitState(repositoryRoot),
|
|
77
|
-
async loadCanonicalSkillBinding(name) {
|
|
78
|
-
if (name === "tdd") {
|
|
79
|
-
return loadPackagedCanonicalSkillBinding(packageRoot, "tdd");
|
|
80
|
-
}
|
|
81
|
-
if (name === "code-review") {
|
|
82
|
-
return loadPackagedCanonicalSkillBinding(packageRoot, "code-review");
|
|
83
|
-
}
|
|
84
|
-
return loadHomeCanonicalSkillBinding(name);
|
|
85
|
-
},
|
|
86
|
-
// #590: doctor compliance still on disposeCompliance path; judge→auditor is gate queue (#756).
|
|
87
|
-
auditDoctorCompliance: (options) => doctorAuditor(options),
|
|
88
|
-
runReviewerDispatch: (dispatch, options) => reviewerAgent.run(dispatch, options),
|
|
89
|
-
shutdownReviewerAgent: () => reviewerAgent.shutdown(),
|
|
90
|
-
loadNavigatorWorkContext: (options) => loadNavigatorWorkContext({
|
|
91
|
-
context: options.context,
|
|
92
|
-
role: options.role,
|
|
93
|
-
...(options.getFlag === undefined ? {} : { getFlag: options.getFlag }),
|
|
94
|
-
}),
|
|
95
|
-
createNavigatorAttendance: (options) => createNavigatorAttendance({
|
|
96
|
-
context: options.context,
|
|
97
|
-
role: options.role,
|
|
98
|
-
phase: options.phase,
|
|
99
|
-
subjectKey: options.subjectKey,
|
|
100
|
-
subject: options.subject,
|
|
101
|
-
authority: options.authority,
|
|
102
|
-
invocationId: options.invocationId,
|
|
103
|
-
loadSoul: () => loadMainRoleSessionMaterials("navigator"),
|
|
104
|
-
loadRoutePlaybook: () => readFile(navigatorRoutePlaybookPath, "utf8"),
|
|
105
|
-
loadRoleHelp: async (role) => formatNavigatorRoleHelp(role),
|
|
106
|
-
createSession: navigatorSessionFactory,
|
|
107
|
-
...(options.contextError === undefined ? {} : { contextError: options.contextError }),
|
|
108
|
-
onEvent: options.onEvent,
|
|
32
|
+
function createComposedAcpRoleTurnHost(
|
|
33
|
+
config: Omit<AcpRoleTurnHostConfig, "prepare"> & {
|
|
34
|
+
readonly roleRuntimeDependencies: RoleRuntimeDependencies;
|
|
35
|
+
readonly socketPath?: (request: RoleTurnRequest) => string;
|
|
36
|
+
},
|
|
37
|
+
) {
|
|
38
|
+
return createAcpRoleTurnHost({
|
|
39
|
+
...config,
|
|
40
|
+
prepare: (request) => prepareRoleEnvelope({
|
|
41
|
+
request,
|
|
42
|
+
dependencies: config.roleRuntimeDependencies,
|
|
43
|
+
sessionFile: config.sessionIdentity.resolveSessionFile(request.principal),
|
|
44
|
+
socketPath: config.socketPath?.(request) ?? `/tmp/ak-acp-mcp-${randomUUID()}.sock`,
|
|
109
45
|
}),
|
|
110
|
-
};
|
|
46
|
+
});
|
|
111
47
|
}
|
|
112
48
|
|
|
113
49
|
/**
|
|
@@ -116,7 +52,7 @@ export function createAcpRoleRuntimeDependencies(packageRoot: string): RoleRunti
|
|
|
116
52
|
* is sitian-only.
|
|
117
53
|
*/
|
|
118
54
|
export function createProductionAcpRoleTurnHost(options: ProductionAcpHostOptions): RoleTurnHost {
|
|
119
|
-
const { packageRoot, principalAuthority, description } = options;
|
|
55
|
+
const { packageRoot, principalAuthority, description, hostName } = options;
|
|
120
56
|
const env: NodeJS.ProcessEnv = {
|
|
121
57
|
...process.env,
|
|
122
58
|
...description.childEnv,
|
|
@@ -124,10 +60,11 @@ export function createProductionAcpRoleTurnHost(options: ProductionAcpHostOption
|
|
|
124
60
|
};
|
|
125
61
|
|
|
126
62
|
return createComposedAcpRoleTurnHost({
|
|
127
|
-
|
|
63
|
+
hostName,
|
|
64
|
+
sessionIdentity: createSessionIdentityAuthority(principalAuthority, description.sessionBindingFile),
|
|
128
65
|
boundResume: description.boundResume,
|
|
129
66
|
modelPassing: description.modelPassing,
|
|
130
|
-
roleRuntimeDependencies:
|
|
67
|
+
roleRuntimeDependencies: createRoleRuntimeDependencies(packageRoot),
|
|
131
68
|
async connect(request) {
|
|
132
69
|
const seatProfile = description.seatProfileSoul;
|
|
133
70
|
const profileName = seatProfile === undefined
|