@akagilnc/pi-workflow-roles 0.1.3771 → 0.1.3783
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 +330 -181
- package/dist/headless-host/description.js +77 -0
- package/dist/headless-host/mcp-relay.mjs +119 -0
- package/dist/headless-host/production-host.js +26590 -0
- package/dist/host-descriptions.js +44 -3
- package/dist/public-cli/load-production-external-host.js +19 -0
- package/dist/public-cli/load-production-headless-host.js +36 -0
- package/dist/public-cli/main.js +242 -162
- package/dist/public-role-summons.js +40 -5
- package/package.json +1 -1
- package/scripts/build-package.mjs +28 -0
- package/src/acp-host/role-envelope.ts +141 -84
- package/src/acp-host/role-turn-host.ts +12 -0
- package/src/headless-host/description.ts +123 -0
- package/src/headless-host/production-host.ts +75 -0
- package/src/headless-host/role-turn-host.ts +424 -0
- package/src/host-descriptions.ts +53 -6
- package/src/public-cli/cli.ts +2 -2
- package/src/public-cli/load-production-external-host.ts +29 -0
- package/src/public-cli/load-production-headless-host.ts +48 -0
- package/src/public-cli/main.ts +5 -0
- package/src/public-role-summons.ts +62 -9
|
@@ -65,6 +65,12 @@ export type PublicSummonRequest = {
|
|
|
65
65
|
* Never folded into argv / parent-run lookup keys (ADR 0079 卷宗指针 stays pure).
|
|
66
66
|
*/
|
|
67
67
|
readonly gateReviewInstruction?: string;
|
|
68
|
+
/**
|
|
69
|
+
* Parent-invocation host axis (#617 / #645). Nested institutional legs inherit
|
|
70
|
+
* the live parent `--host` so a single public entry does not require mutating
|
|
71
|
+
* persistent seat host. Seat model/thinking stay on the officer seat table.
|
|
72
|
+
*/
|
|
73
|
+
readonly host?: string;
|
|
68
74
|
/**
|
|
69
75
|
* Offline test inject — same face as public CLI env.roleTurnHost. Production
|
|
70
76
|
* summons leave this unset and use the seat-resolved host.
|
|
@@ -211,14 +217,13 @@ async function createSummonEnv(options: {
|
|
|
211
217
|
const hostName = options.seat.host ?? "pi";
|
|
212
218
|
let roleTurnHost = piHost;
|
|
213
219
|
if (hostName !== "pi") {
|
|
214
|
-
const {
|
|
215
|
-
const {
|
|
216
|
-
"./public-cli/load-production-
|
|
220
|
+
const { lookupHostFamily } = await import("./host-descriptions.ts");
|
|
221
|
+
const { loadProductionExternalHostFactory } = await import(
|
|
222
|
+
"./public-cli/load-production-external-host.ts"
|
|
217
223
|
);
|
|
218
|
-
// #729:
|
|
219
|
-
//
|
|
220
|
-
|
|
221
|
-
if (lookupHostDescription(hostName) === undefined) {
|
|
224
|
+
// #729 / #645: description tables are the sole host authority — family
|
|
225
|
+
// dispatch (ACP vs headless) is data-driven. Unregistered keys fail closed.
|
|
226
|
+
if (lookupHostFamily(hostName) === undefined) {
|
|
222
227
|
throw new Error(
|
|
223
228
|
`public role summons host unregistered: host=${hostName} seat=${options.role}`,
|
|
224
229
|
);
|
|
@@ -226,7 +231,7 @@ async function createSummonEnv(options: {
|
|
|
226
231
|
let hostPromise: Promise<RoleTurnHost> | undefined;
|
|
227
232
|
roleTurnHost = {
|
|
228
233
|
executeTurn: async (request) => {
|
|
229
|
-
hostPromise ??=
|
|
234
|
+
hostPromise ??= loadProductionExternalHostFactory(options.packageRoot, hostName).then(
|
|
230
235
|
(create) =>
|
|
231
236
|
create({
|
|
232
237
|
packageRoot: options.packageRoot,
|
|
@@ -286,7 +291,10 @@ export async function summonPublicRole(
|
|
|
286
291
|
const credentials =
|
|
287
292
|
options.credentials ?? (await loadCredentialProviders(agentDir));
|
|
288
293
|
const config = await loadPublicCliConfig(home);
|
|
289
|
-
|
|
294
|
+
// Nested legs inherit parent invocation host when provided (#645 review path).
|
|
295
|
+
// Model/thinking stay on the officer seat — host-only inherit (seat-table law).
|
|
296
|
+
const invocation = options.host === undefined ? undefined : { host: options.host };
|
|
297
|
+
const seat = resolveEffectiveSeat(config, options.role, credentials, invocation);
|
|
290
298
|
const env = {
|
|
291
299
|
...(await createSummonEnv({
|
|
292
300
|
role: options.role,
|
|
@@ -412,6 +420,47 @@ export async function summonPublicRole(
|
|
|
412
420
|
}
|
|
413
421
|
|
|
414
422
|
/** Gate officer summons: notary/auditor via --source-run; inspector via pointer instruction. */
|
|
423
|
+
/**
|
|
424
|
+
* Read parent invocation host so nested officers inherit live --host only (#645).
|
|
425
|
+
* Gate source runs necessarily own invocation.json — missing page, bad JSON, or
|
|
426
|
+
* bad shape stay loud (failure-honesty). Absent host field is lawful (seat default).
|
|
427
|
+
*/
|
|
428
|
+
async function parentInvocationHost(sourceRunDirectory: string): Promise<string | undefined> {
|
|
429
|
+
const { readFile } = await import("node:fs/promises");
|
|
430
|
+
const path = join(sourceRunDirectory, "invocation.json");
|
|
431
|
+
let text: string;
|
|
432
|
+
try {
|
|
433
|
+
text = await readFile(path, "utf8");
|
|
434
|
+
} catch (error) {
|
|
435
|
+
const code =
|
|
436
|
+
error instanceof Error && "code" in error
|
|
437
|
+
? (error as NodeJS.ErrnoException).code
|
|
438
|
+
: undefined;
|
|
439
|
+
throw new Error(
|
|
440
|
+
`parent invocation.json required for gate source run at ${path}: ${code ?? (error instanceof Error ? error.message : String(error))}`,
|
|
441
|
+
{ cause: error },
|
|
442
|
+
);
|
|
443
|
+
}
|
|
444
|
+
let raw: unknown;
|
|
445
|
+
try {
|
|
446
|
+
raw = JSON.parse(text) as unknown;
|
|
447
|
+
} catch (error) {
|
|
448
|
+
throw new Error(
|
|
449
|
+
`parent invocation.json unreadable at ${path}: ${error instanceof Error ? error.message : String(error)}`,
|
|
450
|
+
{ cause: error },
|
|
451
|
+
);
|
|
452
|
+
}
|
|
453
|
+
if (typeof raw !== "object" || raw === null || Array.isArray(raw)) {
|
|
454
|
+
throw new Error(`parent invocation.json has non-object shape at ${path}`);
|
|
455
|
+
}
|
|
456
|
+
const host = (raw as Record<string, unknown>).host;
|
|
457
|
+
if (host === undefined) return undefined;
|
|
458
|
+
if (typeof host !== "string" || host.trim() === "") {
|
|
459
|
+
throw new Error(`parent invocation.json host must be a non-empty string at ${path}`);
|
|
460
|
+
}
|
|
461
|
+
return host;
|
|
462
|
+
}
|
|
463
|
+
|
|
415
464
|
export async function summonGateOfficer(options: {
|
|
416
465
|
readonly officer: "inspector" | "notary" | "auditor";
|
|
417
466
|
readonly sourceRunDirectory: string;
|
|
@@ -452,6 +501,9 @@ export async function summonGateOfficer(options: {
|
|
|
452
501
|
submission: options.submission,
|
|
453
502
|
});
|
|
454
503
|
}
|
|
504
|
+
// Inherit parent live --host only so review roundtrip stays on one host without
|
|
505
|
+
// mutating persistent seat tables (#645). Officer model/thinking stay seat-owned.
|
|
506
|
+
const parentHost = await parentInvocationHost(options.sourceRunDirectory);
|
|
455
507
|
const common = {
|
|
456
508
|
cwd: options.cwd,
|
|
457
509
|
...(home === undefined ? {} : { home }),
|
|
@@ -462,6 +514,7 @@ export async function summonGateOfficer(options: {
|
|
|
462
514
|
...(gateReviewInstruction === undefined
|
|
463
515
|
? {}
|
|
464
516
|
: { gateReviewInstruction }),
|
|
517
|
+
...(parentHost === undefined ? {} : { host: parentHost }),
|
|
465
518
|
...(options.roleTurnHost === undefined ? {} : { roleTurnHost: options.roleTurnHost }),
|
|
466
519
|
...(options.createRunId === undefined ? {} : { createRunId: options.createRunId }),
|
|
467
520
|
} as const;
|