@akagilnc/pi-workflow-roles 0.1.5598 → 0.1.5614
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 +406 -366
- package/dist/compliance-transport.js +2 -5
- package/dist/doctor-auditor.js +1 -1
- package/dist/gatekeeper-role.js +1 -1
- package/dist/headless-host/production-host.js +370 -330
- package/dist/migrate-book-topology.js +301 -291
- package/dist/navigator-public-session.js +4 -4
- package/dist/navigator-work-base.js +5 -30
- package/dist/packaged-role-registry.js +4 -2
- package/dist/pi/role-turn-host.js +10 -1
- package/dist/public-cli/instruction-seat-run.js +133 -38
- package/dist/public-cli/invocation.js +23 -26
- package/dist/public-cli/main.js +250 -179
- package/dist/public-cli/option-definitions.js +19 -0
- package/dist/public-cli/post-admission.js +23 -22
- package/dist/public-cli/run-lifecycle.js +2 -14
- package/dist/public-cli/turn-request.js +4 -9
- package/dist/public-role-summons.js +5 -3
- package/dist/role-run-placement.js +7 -1
- package/package.json +1 -1
- package/scripts/build-package.mjs +2 -3
- package/src/audited-run-identity.ts +30 -0
- package/src/compliance-transport.ts +1 -4
- package/src/doctor-auditor.ts +1 -1
- package/src/gatekeeper-role.ts +1 -1
- package/src/host-contracts.ts +6 -1
- package/src/navigator-public-session.ts +9 -5
- package/src/navigator-work-base.ts +19 -34
- package/src/notary-role.ts +12 -21
- package/src/packaged-role-registry.ts +4 -4
- package/src/pi/role-turn-host.ts +11 -1
- package/src/public-cli/instruction-seat-run.ts +162 -42
- package/src/public-cli/invocation.ts +35 -26
- package/src/public-cli/option-definitions.ts +20 -0
- package/src/public-cli/post-admission.ts +28 -22
- package/src/public-cli/run-lifecycle.ts +2 -17
- package/src/public-cli/turn-request.ts +9 -8
- package/src/public-role-summons.ts +17 -6
- package/src/role-envelope.ts +4 -0
- package/src/role-run-placement.ts +10 -1
- package/src/role-runtime.ts +54 -31
- package/dist/auditor-dossier-tool.js +0 -47
- package/src/auditor-dossier-tool.ts +0 -63
|
@@ -121,6 +121,11 @@ export type PublicSummonRequest = {
|
|
|
121
121
|
* (#946 / ADR 0082).
|
|
122
122
|
*/
|
|
123
123
|
readonly stationChild?: boolean;
|
|
124
|
+
/**
|
|
125
|
+
* Navigator nest work-context locator (#1166). Request-scoped internal path —
|
|
126
|
+
* never dialogue content; never shared parent process.env across await.
|
|
127
|
+
*/
|
|
128
|
+
readonly navigatorWorkContextPath?: string;
|
|
124
129
|
};
|
|
125
130
|
|
|
126
131
|
const execFileAsync = promisify(execFile);
|
|
@@ -421,6 +426,10 @@ export async function summonPublicRole(
|
|
|
421
426
|
? {}
|
|
422
427
|
: { correlationId: options.correlationId }),
|
|
423
428
|
...(options.createRunId === undefined ? {} : { createRunId: options.createRunId }),
|
|
429
|
+
...(options.navigatorWorkContextPath === undefined
|
|
430
|
+
|| options.navigatorWorkContextPath.trim() === ""
|
|
431
|
+
? {}
|
|
432
|
+
: { navigatorWorkContextPath: options.navigatorWorkContextPath }),
|
|
424
433
|
},
|
|
425
434
|
};
|
|
426
435
|
} catch (error) {
|
|
@@ -746,13 +755,13 @@ export async function summonGateOfficer(options: {
|
|
|
746
755
|
/**
|
|
747
756
|
* Plain-language re-ask when the prior officer reply was not three-state (#753 / #756).
|
|
748
757
|
* Officers: reviewReask → same-ticket resume summons.instruction.
|
|
749
|
-
* Never concatenated into argv (
|
|
758
|
+
* Never concatenated into argv (binding stays on --source-run / parentRunPath).
|
|
750
759
|
*/
|
|
751
760
|
readonly reask?: string;
|
|
752
761
|
/**
|
|
753
762
|
* In-flight parent 交卷 body (tool-call arguments). Relayed verbatim as officer
|
|
754
763
|
* dialogue content when reask is absent (#879). Binding pointer stays on
|
|
755
|
-
* --source-run /
|
|
764
|
+
* --source-run / parentRunPath — never a content substitute.
|
|
756
765
|
*/
|
|
757
766
|
readonly submission?: unknown;
|
|
758
767
|
/** Pi-adapter inject — forwarded to summonPublicRole (not a parent-host override). */
|
|
@@ -808,6 +817,7 @@ export async function summonGateOfficer(options: {
|
|
|
808
817
|
if (gateSummon === "subject-source") {
|
|
809
818
|
// #756: judge compliance path — same queue law as notary/inspector.
|
|
810
819
|
// Binding pointer on argv; dialogue content rides gateReviewInstruction.
|
|
820
|
+
// #1166: no code-authored 卷宗指针 instruction — identity is startup material.
|
|
811
821
|
return summonPublicRole({
|
|
812
822
|
role: options.officer,
|
|
813
823
|
argv: [
|
|
@@ -815,7 +825,8 @@ export async function summonGateOfficer(options: {
|
|
|
815
825
|
"judge",
|
|
816
826
|
"--source-run",
|
|
817
827
|
options.sourceRunDirectory,
|
|
818
|
-
|
|
828
|
+
"--project",
|
|
829
|
+
options.cwd,
|
|
819
830
|
],
|
|
820
831
|
...common,
|
|
821
832
|
});
|
|
@@ -850,11 +861,11 @@ export async function summonGateOfficer(options: {
|
|
|
850
861
|
...(courtTicket === undefined ? {} : { boundTicketNumber: courtTicket }),
|
|
851
862
|
});
|
|
852
863
|
}
|
|
853
|
-
// Inspector:
|
|
854
|
-
//
|
|
864
|
+
// Inspector: bind via --source-run (same face as notary); dialogue rides env.
|
|
865
|
+
// #1166: no code-authored 卷宗指针 instruction — identity is startup material.
|
|
855
866
|
return summonPublicRole({
|
|
856
867
|
role: options.officer,
|
|
857
|
-
argv: [
|
|
868
|
+
argv: ["--source-run", options.sourceRunDirectory, "--project", options.cwd],
|
|
858
869
|
...common,
|
|
859
870
|
});
|
|
860
871
|
}
|
package/src/role-envelope.ts
CHANGED
|
@@ -178,6 +178,10 @@ export async function prepareRoleEnvelope(options: {
|
|
|
178
178
|
...(request.courtAttemptId === undefined ? {} : { courtAttemptId: request.courtAttemptId }),
|
|
179
179
|
...(request.invocationScopeId === undefined ? {} : { invocationScopeId: request.invocationScopeId }),
|
|
180
180
|
...(request.host === undefined || request.host.trim() === "" ? {} : { host: request.host.trim() }),
|
|
181
|
+
...(request.navigatorWorkContextPath === undefined
|
|
182
|
+
|| request.navigatorWorkContextPath.trim() === ""
|
|
183
|
+
? {}
|
|
184
|
+
: { navigatorWorkContextPath: request.navigatorWorkContextPath }),
|
|
181
185
|
sessionManager: {
|
|
182
186
|
getLeafEntry: () => sessionEntries.at(-1) as ReturnType<HostContext["sessionManager"]["getLeafEntry"]>,
|
|
183
187
|
getLeafId: () => runId,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { readdir } from "node:fs/promises";
|
|
2
|
-
import { basename, dirname, join } from "node:path";
|
|
2
|
+
import { basename, dirname, join, resolve } from "node:path";
|
|
3
3
|
|
|
4
4
|
import {
|
|
5
5
|
activationBookDirectory,
|
|
@@ -54,6 +54,15 @@ export function runDirectoryOfSessionFile(sessionFile: string): string {
|
|
|
54
54
|
return dirname(dirname(sessionFile));
|
|
55
55
|
}
|
|
56
56
|
|
|
57
|
+
/** Climb session/session.jsonl → run directory when the host exposes a session file. */
|
|
58
|
+
export function auditorRunDirectory(context: {
|
|
59
|
+
readonly sessionManager?: { getSessionFile?: () => string | undefined };
|
|
60
|
+
}): string | undefined {
|
|
61
|
+
const sessionFile = context.sessionManager?.getSessionFile?.();
|
|
62
|
+
if (sessionFile === undefined) return undefined;
|
|
63
|
+
return resolve(runDirectoryOfSessionFile(sessionFile));
|
|
64
|
+
}
|
|
65
|
+
|
|
57
66
|
/** `<run>/session` → run directory. */
|
|
58
67
|
export function runDirectoryFromSessionDirectory(sessionDirectory: string): string {
|
|
59
68
|
return dirname(sessionDirectory);
|
package/src/role-runtime.ts
CHANGED
|
@@ -106,8 +106,13 @@ import {
|
|
|
106
106
|
type AuditorRuntimeDependencies,
|
|
107
107
|
} from "./auditor-role.ts";
|
|
108
108
|
|
|
109
|
+
import {
|
|
110
|
+
auditedRunIdentityFromDirectory,
|
|
111
|
+
auditedRunIdentityMaterial,
|
|
112
|
+
} from "./audited-run-identity.ts";
|
|
109
113
|
import { formatNavigatorReport, NAVIGATOR_EVENT_TYPE, NAVIGATOR_ROUTE_PLAYBOOK_FAILURE_ENTRY, navigatorSubjectKey, navigatorUnavailableError, subjectPath, type NavigatorAttendance, type NavigatorAttendanceOptions, type NavigatorEvent, type NavigatorPhase, type NavigatorReport, type NavigatorSettlement, type NavigatorSubjectProvenance, type NavigatorWorkContext } from "./navigator-attendance.ts";
|
|
110
114
|
import { loadNavigatorWorkBaseSuffix } from "./navigator-work-base.ts";
|
|
115
|
+
import { AK_ROLE_AUDITOR_SOURCE_RUN_ENV } from "./auditor-soul.ts";
|
|
111
116
|
import {
|
|
112
117
|
buildNavigatorInfrastructureFailureFact,
|
|
113
118
|
classifyPackagedRoleTerminalResult,
|
|
@@ -690,7 +695,7 @@ export function createNavigatorRoleRuntime(
|
|
|
690
695
|
const loadRoutePlaybook = dependencies.loadRoutePlaybook
|
|
691
696
|
?? (() => readPackageMaterial("resources/navigator-route-playbook.md"));
|
|
692
697
|
let playbookRead: Promise<string> | undefined;
|
|
693
|
-
roleHost.on("before_agent_start", async (event) => {
|
|
698
|
+
roleHost.on("before_agent_start", async (event, ctx) => {
|
|
694
699
|
const basePrompt = typeof event.systemPrompt === "string" ? event.systemPrompt : "";
|
|
695
700
|
const parts: string[] = [];
|
|
696
701
|
try {
|
|
@@ -705,8 +710,10 @@ export function createNavigatorRoleRuntime(
|
|
|
705
710
|
parts.push(message);
|
|
706
711
|
}
|
|
707
712
|
}
|
|
708
|
-
const
|
|
709
|
-
|
|
713
|
+
const work = await loadNavigatorWorkBaseSuffix(
|
|
714
|
+
ctx.sessionManager?.getSessionDir?.(),
|
|
715
|
+
ctx.navigatorWorkContextPath,
|
|
716
|
+
);
|
|
710
717
|
if (work !== undefined && work.trim() !== "") parts.push(work);
|
|
711
718
|
if (parts.length === 0) return;
|
|
712
719
|
const text = parts.join("\n\n");
|
|
@@ -723,7 +730,7 @@ export function createAuditorRoleRuntime(
|
|
|
723
730
|
roleHost: RoleHost,
|
|
724
731
|
dependencies: AuditorRuntimeDependencies,
|
|
725
732
|
) {
|
|
726
|
-
|
|
733
|
+
return createFiledOfficerRuntime(
|
|
727
734
|
roleHost,
|
|
728
735
|
{
|
|
729
736
|
role: "auditor",
|
|
@@ -732,24 +739,39 @@ export function createAuditorRoleRuntime(
|
|
|
732
739
|
},
|
|
733
740
|
dependencies,
|
|
734
741
|
);
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
742
|
+
}
|
|
743
|
+
|
|
744
|
+
function isAuditedIdentitySeat(role: string): boolean {
|
|
745
|
+
return role === "notary" || role === "inspector" || role === "auditor" || role === "countersign";
|
|
746
|
+
}
|
|
747
|
+
|
|
748
|
+
/** Resolve audited-run directory for identity material — this-leg flags / admitted page first. */
|
|
749
|
+
function resolveAuditedSourceRunDirectory(
|
|
750
|
+
roleHost: RoleHost,
|
|
751
|
+
ctx: HostContext,
|
|
752
|
+
role: string,
|
|
753
|
+
): string | undefined {
|
|
754
|
+
const notary = roleHost.getFlag(NOTARY_SOURCE_RUN_FLAG.name);
|
|
755
|
+
if (typeof notary === "string" && notary.trim() !== "") return notary.trim();
|
|
756
|
+
const inspector = roleHost.getFlag(INSPECTOR_SOURCE_RUN_FLAG.name);
|
|
757
|
+
if (typeof inspector === "string" && inspector.trim() !== "") return inspector.trim();
|
|
758
|
+
// This-leg admitted binding wins over shared auditor env (#1166 J3).
|
|
759
|
+
const runDirectory = runDirectoryFromHostContext(ctx);
|
|
760
|
+
if (runDirectory !== undefined) {
|
|
761
|
+
const admitted = readPageSync(runDirectory, "admitted");
|
|
762
|
+
if (typeof admitted?.sourceRunPath === "string" && admitted.sourceRunPath.trim() !== "") {
|
|
763
|
+
return admitted.sourceRunPath.trim();
|
|
764
|
+
}
|
|
765
|
+
}
|
|
766
|
+
// Auditor env is request-scoped soul binding for the auditor seat only.
|
|
767
|
+
if (role === "auditor") {
|
|
768
|
+
const auditor =
|
|
769
|
+
typeof process.env[AK_ROLE_AUDITOR_SOURCE_RUN_ENV] === "string"
|
|
770
|
+
? process.env[AK_ROLE_AUDITOR_SOURCE_RUN_ENV].trim()
|
|
771
|
+
: "";
|
|
772
|
+
if (auditor !== "") return auditor;
|
|
773
|
+
}
|
|
774
|
+
return undefined;
|
|
753
775
|
}
|
|
754
776
|
|
|
755
777
|
/**
|
|
@@ -1220,15 +1242,16 @@ export function createRoleRuntimeExtension(
|
|
|
1220
1242
|
if (reading === undefined) return;
|
|
1221
1243
|
return { readingMaterial: reading };
|
|
1222
1244
|
});
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1245
|
+
// #1166 / ADR 0087: four audit seats share one audited-run identity material.
|
|
1246
|
+
// Notary also emits identity from its own before_agent_start; skip double fold.
|
|
1247
|
+
roleHost.on("before_agent_start", (_event, ctx) => {
|
|
1248
|
+
const role = selectedRole ?? roleHost.getFlag(ROLE_FLAG.name);
|
|
1249
|
+
if (typeof role !== "string" || !isAuditedIdentitySeat(role) || role === "notary") return;
|
|
1250
|
+
const sourceDirectory = resolveAuditedSourceRunDirectory(roleHost, ctx, role);
|
|
1251
|
+
if (sourceDirectory === undefined) return;
|
|
1252
|
+
const identity = auditedRunIdentityFromDirectory(sourceDirectory);
|
|
1253
|
+
if (identity === undefined) return;
|
|
1254
|
+
return { readingMaterial: auditedRunIdentityMaterial(identity) };
|
|
1232
1255
|
});
|
|
1233
1256
|
roleHost.on("tool_result", async (event, ctx) => {
|
|
1234
1257
|
const role = selectedRole;
|
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
import { join, resolve } from "node:path";
|
|
2
|
-
import { RUN_HISTORY_FILE, RUN_LOG_FILE, runCurrentPath } from "./run-dossier.js";
|
|
3
|
-
import {
|
|
4
|
-
runDirectoryOfSessionFile,
|
|
5
|
-
sessionFileOf
|
|
6
|
-
} from "./role-run-placement.js";
|
|
7
|
-
import { Type } from "typebox";
|
|
8
|
-
const AUDITOR_DOSSIER_TOOL_NAME = "ak_get_run_dossier";
|
|
9
|
-
function auditorRunDirectory(context) {
|
|
10
|
-
const sessionFile = context.sessionManager?.getSessionFile?.();
|
|
11
|
-
if (sessionFile === void 0) return void 0;
|
|
12
|
-
return resolve(runDirectoryOfSessionFile(sessionFile));
|
|
13
|
-
}
|
|
14
|
-
function createAuditorDossierTool(runDirectory) {
|
|
15
|
-
return {
|
|
16
|
-
name: AUDITOR_DOSSIER_TOOL_NAME,
|
|
17
|
-
description: "\u5B9A\u4F4D\u672C\u5BA1\u8BA1\u5E2D\u7ED1\u5B9A\u7684 run \u5377\u5B97\u53CA\u5176\u8BC1\u636E\u5165\u53E3\u3002",
|
|
18
|
-
// #836 r16 class 3: execute() ignores `_params` entirely — a closed root
|
|
19
|
-
// only rejects the role for saying more.
|
|
20
|
-
parameters: Type.Object({}, { additionalProperties: true }),
|
|
21
|
-
async execute(_id, _params) {
|
|
22
|
-
if (runDirectory === void 0) {
|
|
23
|
-
return {
|
|
24
|
-
content: [{ type: "text", text: "\u672C\u5BA1\u8BA1\u5E2D\u65E0\u7ED1\u5B9A run \u5377\u5B97\u8BB0\u5F55\u3002" }],
|
|
25
|
-
details: void 0
|
|
26
|
-
};
|
|
27
|
-
}
|
|
28
|
-
const details = {
|
|
29
|
-
runDirectory,
|
|
30
|
-
current: runCurrentPath(runDirectory),
|
|
31
|
-
parentSessionCandidate: sessionFileOf(runDirectory),
|
|
32
|
-
attachments: join(runDirectory, "attachments"),
|
|
33
|
-
log: join(runDirectory, RUN_LOG_FILE),
|
|
34
|
-
history: join(runDirectory, RUN_HISTORY_FILE)
|
|
35
|
-
};
|
|
36
|
-
return {
|
|
37
|
-
content: [{ type: "text", text: JSON.stringify(details) }],
|
|
38
|
-
details
|
|
39
|
-
};
|
|
40
|
-
}
|
|
41
|
-
};
|
|
42
|
-
}
|
|
43
|
-
export {
|
|
44
|
-
AUDITOR_DOSSIER_TOOL_NAME,
|
|
45
|
-
auditorRunDirectory,
|
|
46
|
-
createAuditorDossierTool
|
|
47
|
-
};
|
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
import { join, resolve } from "node:path";
|
|
2
|
-
|
|
3
|
-
import { RUN_HISTORY_FILE, RUN_LOG_FILE, runCurrentPath } from "./run-dossier.ts";
|
|
4
|
-
import type { AgentToolResult, ExtensionContext } from "@earendil-works/pi-coding-agent";
|
|
5
|
-
import type { HostContext } from "./host-contracts.ts";
|
|
6
|
-
import {
|
|
7
|
-
runDirectoryOfSessionFile,
|
|
8
|
-
sessionFileOf,
|
|
9
|
-
} from "./role-run-placement.ts";
|
|
10
|
-
import { Type } from "typebox";
|
|
11
|
-
|
|
12
|
-
export const AUDITOR_DOSSIER_TOOL_NAME = "ak_get_run_dossier" as const;
|
|
13
|
-
|
|
14
|
-
export type AuditorDossierLocation = {
|
|
15
|
-
readonly runDirectory: string;
|
|
16
|
-
readonly current: string;
|
|
17
|
-
readonly parentSessionCandidate: string;
|
|
18
|
-
readonly attachments: string;
|
|
19
|
-
readonly log: string;
|
|
20
|
-
readonly history: string;
|
|
21
|
-
};
|
|
22
|
-
|
|
23
|
-
/** Resolve the exact run binding already carried by the parent record session. */
|
|
24
|
-
export function auditorRunDirectory(context: ExtensionContext | HostContext): string | undefined {
|
|
25
|
-
const sessionFile = context.sessionManager?.getSessionFile?.();
|
|
26
|
-
if (sessionFile === undefined) return undefined;
|
|
27
|
-
// Sole layout: <run>/session/session.jsonl → climb two levels to the run directory.
|
|
28
|
-
return resolve(runDirectoryOfSessionFile(sessionFile));
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
/** The one shared, run-bound dossier locator exposed to every auditor seat. */
|
|
32
|
-
export function createAuditorDossierTool(
|
|
33
|
-
runDirectory: string | undefined,
|
|
34
|
-
) {
|
|
35
|
-
return {
|
|
36
|
-
name: AUDITOR_DOSSIER_TOOL_NAME,
|
|
37
|
-
description: "定位本审计席绑定的 run 卷宗及其证据入口。",
|
|
38
|
-
// #836 r16 class 3: execute() ignores `_params` entirely — a closed root
|
|
39
|
-
// only rejects the role for saying more.
|
|
40
|
-
parameters: Type.Object({}, { additionalProperties: true }),
|
|
41
|
-
async execute(_id: string, _params: unknown): Promise<AgentToolResult<AuditorDossierLocation | undefined>> {
|
|
42
|
-
if (runDirectory === undefined) {
|
|
43
|
-
return {
|
|
44
|
-
content: [{ type: "text", text: "本审计席无绑定 run 卷宗记录。" }],
|
|
45
|
-
details: undefined,
|
|
46
|
-
};
|
|
47
|
-
}
|
|
48
|
-
// #836: whole run directory pointer — officer finds materials; no leaf preference (A7.2).
|
|
49
|
-
const details: AuditorDossierLocation = {
|
|
50
|
-
runDirectory,
|
|
51
|
-
current: runCurrentPath(runDirectory),
|
|
52
|
-
parentSessionCandidate: sessionFileOf(runDirectory),
|
|
53
|
-
attachments: join(runDirectory, "attachments"),
|
|
54
|
-
log: join(runDirectory, RUN_LOG_FILE),
|
|
55
|
-
history: join(runDirectory, RUN_HISTORY_FILE),
|
|
56
|
-
};
|
|
57
|
-
return {
|
|
58
|
-
content: [{ type: "text", text: JSON.stringify(details) }],
|
|
59
|
-
details,
|
|
60
|
-
};
|
|
61
|
-
},
|
|
62
|
-
};
|
|
63
|
-
}
|