@akagilnc/pi-workflow-roles 0.1.5365 → 0.1.5375
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 +5585 -5655
- package/dist/activation-ledger-git.js +2 -2
- package/dist/activation-ledger-topology.js +1 -7
- package/dist/analyst-entry.js +4 -8
- package/dist/analyst-gate-cycles-read.js +3 -11
- package/dist/analyst-index.js +3 -9
- package/dist/analyst-ledger.js +1 -11
- package/dist/analyst-metric-families/acceptance-success-rework.js +1 -3
- package/dist/analyst-metric-families/round-timeline.js +1 -3
- package/dist/analyst-page.js +2 -2
- package/dist/archivist-record-topology.js +2 -2
- package/dist/audit-escalation.js +2 -1
- package/dist/auditor-soul.js +2 -1
- package/dist/collector-config.js +6 -8
- package/dist/compliance-transport.js +2 -1
- package/dist/countersign-contracts.js +2 -1
- package/dist/diarist-contracts.js +3 -2
- package/dist/doctor-contracts.js +1 -3
- package/dist/doctor-evidence.js +7 -8
- package/dist/dossier-resolution.js +1 -3
- package/dist/engine-detour-usage.js +1 -3
- package/dist/gatekeeper-role.js +2 -9
- package/dist/gleaner-left-contracts.js +2 -1
- package/dist/headless-host/description.js +14 -17
- package/dist/headless-host/production-host.js +1665 -1737
- package/dist/host-session-record.js +3 -2
- package/dist/inspector-contracts.js +2 -1
- package/dist/ledger-session-read.js +1 -3
- package/dist/merger-contracts.js +9 -9
- package/dist/migrate-book-topology.js +348 -314
- package/dist/navigator-attendance.js +9 -11
- package/dist/navigator-invocation-identity.js +3 -2
- package/dist/navigator-public-session.js +3 -5
- package/dist/navigator-session-contracts.js +8 -10
- package/dist/navigator-work-base.js +5 -8
- package/dist/notary-contracts.js +3 -5
- package/dist/package-contracts/auditor-output.js +1 -3
- package/dist/package-contracts/fixer-packet.js +3 -6
- package/dist/package-contracts/gatekeeper-output.js +1 -3
- package/dist/package-contracts/navigator-output.js +8 -8
- package/dist/package-contracts/terminating-infrastructure.js +5 -9
- package/dist/package-contracts/terminating-tools.js +4 -3
- package/dist/public-cli/analyst-run.js +3 -2
- package/dist/public-cli/auto-resume.js +4 -9
- package/dist/public-cli/cli.js +66 -64
- package/dist/public-cli/config.js +12 -11
- package/dist/public-cli/countersign-run.js +1 -3
- package/dist/public-cli/host-providers.js +7 -14
- package/dist/public-cli/instruction-seat-run.js +69 -43
- package/dist/public-cli/invocation.js +141 -136
- package/dist/public-cli/main.js +1919 -1968
- package/dist/public-cli/post-admission.js +89 -89
- package/dist/public-cli/role-seat-runtime.js +29 -0
- package/dist/public-cli/run-lifecycle.js +20 -32
- package/dist/public-cli/settlement.js +10 -26
- package/dist/public-cli/turn-request.js +14 -0
- package/dist/public-role-summons.js +23 -35
- package/dist/receipt-delivery-policy.js +1 -3
- package/dist/role-run-placement.js +7 -5
- package/dist/role-run-relocation.js +12 -19
- package/dist/run-terminal-artifacts.js +1 -11
- package/dist/run-ticket-number.js +2 -4
- package/dist/session-assistant-usage.js +2 -1
- package/dist/session-dialogue.js +1 -14
- package/dist/sitian-reader.js +2 -4
- package/dist/submission-correctable-error.js +2 -1
- package/dist/submission-errors.js +2 -1
- package/dist/submission-gate.js +2 -1
- package/dist/submission-ledger.js +4 -5
- package/dist/ticket-provenance-contracts.js +1 -3
- package/dist/ticket-provenance.js +2 -1
- package/dist/typed-provider-http.js +4 -7
- package/dist/unknown-value.js +28 -0
- package/dist/user-dialogue-stdin.js +2 -1
- package/package.json +1 -1
- package/src/acp-host/role-turn-host.ts +4 -2
- package/src/activation-ledger-git.ts +3 -2
- package/src/activation-ledger-topology.ts +4 -12
- package/src/analyst-entry.ts +3 -11
- package/src/analyst-gate-cycles-read.ts +3 -15
- package/src/analyst-index.ts +3 -13
- package/src/analyst-ledger.ts +2 -16
- package/src/analyst-metric-families/acceptance-success-rework.ts +2 -4
- package/src/analyst-metric-families/round-timeline.ts +2 -4
- package/src/analyst-page.ts +2 -2
- package/src/archivist-record-topology.ts +2 -2
- package/src/audit-escalation.ts +2 -1
- package/src/auditor-soul.ts +3 -1
- package/src/book-topology-migration-placement.ts +8 -21
- package/src/book-topology-migrators-t11.ts +16 -15
- package/src/book-topology-mixed-volume-migrators.ts +3 -6
- package/src/book-topology-record-class-migrators.ts +7 -10
- package/src/book-topology-runs-migrator.ts +4 -3
- package/src/collector-config.ts +7 -9
- package/src/compliance-transport.ts +2 -1
- package/src/countersign-contracts.ts +2 -1
- package/src/diarist-contracts.ts +3 -2
- package/src/doctor-contracts.ts +3 -1
- package/src/doctor-evidence.ts +8 -7
- package/src/doctor-role.ts +4 -2
- package/src/dossier-resolution.ts +2 -4
- package/src/engine-detour-tool.ts +0 -2
- package/src/engine-detour-usage.ts +2 -4
- package/src/external-host-turn-loop.ts +3 -1
- package/src/factory-board.ts +1 -8
- package/src/gatekeeper-role.ts +2 -10
- package/src/gleaner-left-contracts.ts +3 -1
- package/src/headless-host/description.ts +15 -18
- package/src/headless-host/role-turn-host.ts +10 -9
- package/src/host-session-record.ts +4 -2
- package/src/inspector-contracts.ts +2 -1
- package/src/ledger-session-read.ts +2 -5
- package/src/merger-contracts.ts +10 -9
- package/src/navigator-attendance.ts +10 -12
- package/src/navigator-invocation-identity.ts +3 -2
- package/src/navigator-public-session.ts +4 -6
- package/src/navigator-session-contracts.ts +8 -11
- package/src/navigator-work-base.ts +5 -8
- package/src/navigator-work-context.ts +2 -1
- package/src/notary-contracts.ts +4 -6
- package/src/oauth-keepalive.ts +5 -18
- package/src/package-contracts/auditor-output.ts +2 -4
- package/src/package-contracts/fixer-packet.ts +4 -6
- package/src/package-contracts/gatekeeper-output.ts +2 -4
- package/src/package-contracts/judge-output.ts +0 -1
- package/src/package-contracts/navigator-output.ts +8 -8
- package/src/package-contracts/terminating-infrastructure.ts +6 -20
- package/src/package-contracts/terminating-tools.ts +8 -12
- package/src/pi/adapter.ts +0 -1
- package/src/pi/role-turn-host.ts +0 -1
- package/src/public-cli/analyst-run.ts +4 -2
- package/src/public-cli/auto-resume.ts +5 -12
- package/src/public-cli/cli.ts +77 -83
- package/src/public-cli/config.ts +16 -27
- package/src/public-cli/countersign-run.ts +2 -4
- package/src/public-cli/host-providers.ts +10 -27
- package/src/public-cli/instruction-seat-run.ts +87 -58
- package/src/public-cli/invocation.ts +159 -172
- package/src/public-cli/post-admission.ts +115 -103
- package/src/public-cli/role-seat-runtime.ts +72 -0
- package/src/public-cli/run-lifecycle.ts +27 -67
- package/src/public-cli/settlement.ts +11 -33
- package/src/public-cli/terminal.ts +2 -17
- package/src/public-cli/turn-request.ts +26 -0
- package/src/public-role-summons.ts +24 -48
- package/src/receipt-delivery-policy.ts +1 -4
- package/src/reviewer-role.ts +0 -1
- package/src/role-envelope.ts +5 -3
- package/src/role-run-placement.ts +9 -10
- package/src/role-run-relocation.ts +13 -23
- package/src/role-runtime.ts +9 -15
- package/src/run-terminal-artifacts.ts +2 -16
- package/src/run-ticket-number.ts +4 -10
- package/src/session-assistant-usage.ts +3 -1
- package/src/session-dialogue.ts +1 -4
- package/src/session-identity.ts +0 -1
- package/src/sitian-reader.ts +2 -4
- package/src/submission-correctable-error.ts +3 -1
- package/src/submission-errors.ts +2 -1
- package/src/submission-gate.ts +3 -1
- package/src/submission-ledger.ts +5 -6
- package/src/ticket-provenance-contracts.ts +1 -4
- package/src/ticket-provenance.ts +3 -1
- package/src/ticket-snapshot.ts +2 -4
- package/src/ticket-trajectory.ts +1 -8
- package/src/typed-provider-http.ts +5 -15
- package/src/unknown-value.ts +34 -0
- package/src/user-dialogue-stdin.ts +3 -1
- package/src/worker-role.ts +2 -5
- package/src/worker-submission-gates.ts +5 -7
|
@@ -346,6 +346,8 @@ import {
|
|
|
346
346
|
type TerminalRoleOutcome,
|
|
347
347
|
} from "./terminal.ts";
|
|
348
348
|
|
|
349
|
+
import { isEnoent, isMissingPathError, isRecord } from "../unknown-value.ts";
|
|
350
|
+
|
|
349
351
|
export type { ControlledFailureCause };
|
|
350
352
|
|
|
351
353
|
export {
|
|
@@ -467,7 +469,7 @@ export async function inspectJudgeSession(
|
|
|
467
469
|
await readFile(sessionFile, "utf8");
|
|
468
470
|
return { state: "present" };
|
|
469
471
|
} catch (error) {
|
|
470
|
-
if (
|
|
472
|
+
if (isEnoent(error)) return { state: "missing" };
|
|
471
473
|
return {
|
|
472
474
|
state: "unreadable",
|
|
473
475
|
diagnostic:
|
|
@@ -834,24 +836,6 @@ type SessionEntry = {
|
|
|
834
836
|
parentSession?: string;
|
|
835
837
|
};
|
|
836
838
|
|
|
837
|
-
function isMissingPathError(error: unknown): boolean {
|
|
838
|
-
return (
|
|
839
|
-
error instanceof Error &&
|
|
840
|
-
"code" in error &&
|
|
841
|
-
(error as { code?: unknown }).code === "ENOENT"
|
|
842
|
-
);
|
|
843
|
-
}
|
|
844
|
-
|
|
845
|
-
/** Face clear only: path not enterable as a face (ENOENT or file mid-path). */
|
|
846
|
-
function isAbsentFacePathError(error: unknown): boolean {
|
|
847
|
-
return (
|
|
848
|
-
error instanceof Error &&
|
|
849
|
-
"code" in error &&
|
|
850
|
-
((error as { code?: unknown }).code === "ENOENT" ||
|
|
851
|
-
(error as { code?: unknown }).code === "ENOTDIR")
|
|
852
|
-
);
|
|
853
|
-
}
|
|
854
|
-
|
|
855
839
|
/**
|
|
856
840
|
* Preserve session-read failure identity as a typed session cause.
|
|
857
841
|
* SyntaxError keeps its name so durable settlement does not wash malformed JSONL
|
|
@@ -1064,7 +1048,7 @@ async function loadBoundAuditorVolumes(
|
|
|
1064
1048
|
try {
|
|
1065
1049
|
parentEntries = await readBoundSessionEntries(sessionFile);
|
|
1066
1050
|
} catch (error) {
|
|
1067
|
-
if (
|
|
1051
|
+
if (isEnoent(error)) return undefined;
|
|
1068
1052
|
throw sessionReadFailure(error, "failed to read parent session for auditor binding");
|
|
1069
1053
|
}
|
|
1070
1054
|
const parentId = parentEntries.find((entry) => entry.type === "session")?.id;
|
|
@@ -1078,7 +1062,7 @@ async function loadBoundAuditorVolumes(
|
|
|
1078
1062
|
names = await readdir(childDirectory);
|
|
1079
1063
|
sawAnyDirectory = true;
|
|
1080
1064
|
} catch (error) {
|
|
1081
|
-
if (
|
|
1065
|
+
if (isEnoent(error)) continue;
|
|
1082
1066
|
throw sessionReadFailure(error, "failed to read bound auditor session directory");
|
|
1083
1067
|
}
|
|
1084
1068
|
for (const file of names.filter((name) => name.endsWith(".jsonl")).sort().reverse()) {
|
|
@@ -1313,7 +1297,7 @@ export async function resolveAuditedRunnerFailureResolution(input: {
|
|
|
1313
1297
|
);
|
|
1314
1298
|
if (terminatingFailure !== undefined) return resolutionOf(terminatingFailure);
|
|
1315
1299
|
} catch (error) {
|
|
1316
|
-
if (!
|
|
1300
|
+
if (!isEnoent(error)) {
|
|
1317
1301
|
const failure = sessionReadFailure(error, "failed to recover typed terminating-tool failure");
|
|
1318
1302
|
return resolutionOf({
|
|
1319
1303
|
cause: "session",
|
|
@@ -1459,10 +1443,6 @@ export function controlledFailureInputFromResolution(
|
|
|
1459
1443
|
};
|
|
1460
1444
|
}
|
|
1461
1445
|
|
|
1462
|
-
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
1463
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
1464
|
-
}
|
|
1465
|
-
|
|
1466
1446
|
function safelyRead(object: object, key: string): { readable: true; value: unknown } | { readable: false } {
|
|
1467
1447
|
try {
|
|
1468
1448
|
return { readable: true, value: (object as Record<string, unknown>)[key] };
|
|
@@ -1478,9 +1458,7 @@ function toolResultText(message: SessionMessage): string {
|
|
|
1478
1458
|
return content
|
|
1479
1459
|
.map((part) => {
|
|
1480
1460
|
if (
|
|
1481
|
-
|
|
1482
|
-
part !== null &&
|
|
1483
|
-
!Array.isArray(part) &&
|
|
1461
|
+
isRecord(part) &&
|
|
1484
1462
|
typeof (part as { text?: unknown }).text === "string"
|
|
1485
1463
|
) {
|
|
1486
1464
|
return (part as { text: string }).text;
|
|
@@ -2234,7 +2212,7 @@ async function extractNavigatorFactFromAdmittedSession(
|
|
|
2234
2212
|
const entries = await readBoundSessionEntries(sessionFile);
|
|
2235
2213
|
return extractNavigatorFact(entries);
|
|
2236
2214
|
} catch (error) {
|
|
2237
|
-
if (
|
|
2215
|
+
if (isEnoent(error)) {
|
|
2238
2216
|
return {
|
|
2239
2217
|
disposition: "unavailable",
|
|
2240
2218
|
source: "unknown",
|
|
@@ -2261,7 +2239,7 @@ async function removeFaceIfPresent(path: string): Promise<void> {
|
|
|
2261
2239
|
// force:true already ignores ENOENT; ENOTDIR = face path not enterable
|
|
2262
2240
|
// (artifacts-as-file mid-path) — same absent-face semantics as the reader.
|
|
2263
2241
|
// Other errno stay loud (失败诚实).
|
|
2264
|
-
if (
|
|
2242
|
+
if (isMissingPathError(error)) return;
|
|
2265
2243
|
throw error;
|
|
2266
2244
|
}
|
|
2267
2245
|
}
|
|
@@ -2392,7 +2370,7 @@ async function readLawfulSettlementEntries(
|
|
|
2392
2370
|
return await readBoundSessionEntries(sessionFile);
|
|
2393
2371
|
} catch (error) {
|
|
2394
2372
|
// Missing path is absence of a lawful outcome; callers classify via session inspect.
|
|
2395
|
-
if (
|
|
2373
|
+
if (isEnoent(error)) return undefined;
|
|
2396
2374
|
// Malformed JSONL and other read failures keep typed session identity.
|
|
2397
2375
|
throw error instanceof Error &&
|
|
2398
2376
|
(error as { knownCause?: unknown }).knownCause === "session"
|
|
@@ -2839,7 +2817,7 @@ function countersignTerminalFromEntries(
|
|
|
2839
2817
|
if (entry?.type !== "custom") continue;
|
|
2840
2818
|
if (entry.customType !== SECRETARIAT_GATE_OFFICER_ENTRY_TYPE) continue;
|
|
2841
2819
|
const data =
|
|
2842
|
-
|
|
2820
|
+
isRecord(entry.data)
|
|
2843
2821
|
? (entry.data as Record<string, unknown>)
|
|
2844
2822
|
: undefined;
|
|
2845
2823
|
if (data === undefined || !packagedDurableOfficerEntry(data.officer)) continue;
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
*/
|
|
8
8
|
import type { NoReceiptLifecycleFacts } from "../receipt-delivery-policy.ts";
|
|
9
9
|
import type { ControlledFailureCause } from "../host-contracts.ts";
|
|
10
|
+
import type { PackagedRole } from "../packaged-role-registry.ts";
|
|
10
11
|
|
|
11
12
|
export type { ControlledFailureCause } from "../host-contracts.ts";
|
|
12
13
|
|
|
@@ -22,23 +23,7 @@ export type TerminalArtifactRef = {
|
|
|
22
23
|
};
|
|
23
24
|
|
|
24
25
|
/** Public callable roles that currently produce Terminal outcomes. */
|
|
25
|
-
export type TerminalRoleName =
|
|
26
|
-
| "judge"
|
|
27
|
-
| "coder"
|
|
28
|
-
| "fixer"
|
|
29
|
-
| "collector"
|
|
30
|
-
| "doctor"
|
|
31
|
-
| "reviewer"
|
|
32
|
-
| "merger"
|
|
33
|
-
| "notary"
|
|
34
|
-
| "countersign"
|
|
35
|
-
| "gleaner-left"
|
|
36
|
-
| "inspector"
|
|
37
|
-
| "gatekeeper"
|
|
38
|
-
| "navigator"
|
|
39
|
-
| "auditor"
|
|
40
|
-
| "diarist"
|
|
41
|
-
| "secretariat";
|
|
26
|
+
export type TerminalRoleName = PackagedRole;
|
|
42
27
|
|
|
43
28
|
export type NoReceiptTerminalOutcome = NoReceiptLifecycleFacts & {
|
|
44
29
|
kind: "no_receipt";
|
|
@@ -27,6 +27,32 @@ export type ResumeModelConfig = {
|
|
|
27
27
|
readonly thinking?: PublicThinkingLevel;
|
|
28
28
|
};
|
|
29
29
|
|
|
30
|
+
/**
|
|
31
|
+
* Env axes shared by every public turn projection.
|
|
32
|
+
* Callers add correlation, continuation, host, and station-only fields.
|
|
33
|
+
*/
|
|
34
|
+
export function projectPublicTurnAxes(env: {
|
|
35
|
+
readonly packageRoot: string;
|
|
36
|
+
readonly home: string;
|
|
37
|
+
readonly agentDir: string;
|
|
38
|
+
readonly model?: SeatModelConfig;
|
|
39
|
+
readonly engine?: string;
|
|
40
|
+
readonly engineModel?: string;
|
|
41
|
+
readonly timeoutMs?: number;
|
|
42
|
+
}): Pick<
|
|
43
|
+
RoleTurnRequestProjectionOptions,
|
|
44
|
+
"packageRoot" | "home" | "agentDir" | "model" | "engine" | "engineModel" | "timeoutMs"
|
|
45
|
+
> {
|
|
46
|
+
return {
|
|
47
|
+
packageRoot: env.packageRoot,
|
|
48
|
+
home: env.home,
|
|
49
|
+
agentDir: env.agentDir,
|
|
50
|
+
...(env.model === undefined ? {} : { model: env.model }),
|
|
51
|
+
...pickEngineAxis(env),
|
|
52
|
+
...(env.timeoutMs === undefined ? {} : { timeoutMs: env.timeoutMs }),
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
|
|
30
56
|
export type RoleTurnRequestProjectionOptions = {
|
|
31
57
|
packageRoot: string;
|
|
32
58
|
home: string;
|
|
@@ -25,12 +25,12 @@ import type {
|
|
|
25
25
|
} from "./host-contracts.ts";
|
|
26
26
|
import type { TerminalResult } from "./public-cli/terminal.ts";
|
|
27
27
|
import type { HostSelectionFailure, NamedRoleTurnHostAdapter } from "./public-cli/role-turn-host-resolution.ts";
|
|
28
|
-
|
|
28
|
+
|
|
29
|
+
import { isRecord, errorText } from "./unknown-value.ts";
|
|
29
30
|
|
|
30
31
|
/** Env published by the parent activation so nested summons never re-derive root. */
|
|
31
32
|
export const AK_ROLE_PACKAGE_ROOT_ENV = "AK_ROLE_PACKAGE_ROOT" as const;
|
|
32
33
|
|
|
33
|
-
|
|
34
34
|
export type PublicSummonRole =
|
|
35
35
|
| "inspector"
|
|
36
36
|
| "notary"
|
|
@@ -210,18 +210,6 @@ async function resolveSummonHome(options: PublicSummonRequest): Promise<string>
|
|
|
210
210
|
return packageMachineHome();
|
|
211
211
|
}
|
|
212
212
|
|
|
213
|
-
/** Seat axes only — no parent-env fallback (#675 / #617 DK-3 / #883). */
|
|
214
|
-
function projectSeatEngine(seat: EffectiveSeat): {
|
|
215
|
-
engine?: string;
|
|
216
|
-
engineModel?: string;
|
|
217
|
-
} {
|
|
218
|
-
return pickEngineAxis(seat);
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
function projectSeatHost(seat: EffectiveSeat): { host?: string } {
|
|
222
|
-
return seat.host === undefined ? {} : { host: seat.host };
|
|
223
|
-
}
|
|
224
|
-
|
|
225
213
|
function hostSelectionFailureFromUnknown(error: unknown): HostSelectionFailure | undefined {
|
|
226
214
|
if (typeof error !== "object" || error === null) return undefined;
|
|
227
215
|
if ((error as { name?: unknown }).name !== "HostSelectionError") return undefined;
|
|
@@ -273,18 +261,17 @@ async function createSummonEnv(
|
|
|
273
261
|
const [
|
|
274
262
|
{ piDurablePrincipalAuthority },
|
|
275
263
|
{ appendPiSessionCustomEntry },
|
|
276
|
-
{
|
|
277
|
-
{ missingResolvedSeatModelMessage
|
|
264
|
+
{ openRoleSeatRuntime },
|
|
265
|
+
{ missingResolvedSeatModelMessage },
|
|
278
266
|
] = await Promise.all([
|
|
279
267
|
import("./pi/durable-principal.ts"),
|
|
280
268
|
import("./pi/role-turn-host.ts"),
|
|
281
|
-
import("./public-cli/role-
|
|
269
|
+
import("./public-cli/role-seat-runtime.ts"),
|
|
282
270
|
import("./public-cli/config.ts"),
|
|
283
271
|
]);
|
|
284
272
|
const principalAuthority = options.principalAuthority ?? piDurablePrincipalAuthority;
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
{
|
|
273
|
+
const opened = openRoleSeatRuntime({
|
|
274
|
+
resolution: {
|
|
288
275
|
packageRoot: options.packageRoot,
|
|
289
276
|
...(options.roleTurnHost === undefined ? {} : { roleTurnHost: options.roleTurnHost }),
|
|
290
277
|
...(options.hostAdapters === undefined ? {} : { hostAdapters: options.hostAdapters }),
|
|
@@ -293,29 +280,19 @@ async function createSummonEnv(
|
|
|
293
280
|
: { extraPiArgs: options.extraPiArgs }),
|
|
294
281
|
...(options.timeoutMs === undefined ? {} : { timeoutMs: options.timeoutMs }),
|
|
295
282
|
},
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
283
|
+
principalAuthority,
|
|
284
|
+
role: options.role,
|
|
285
|
+
seat: options.seat,
|
|
286
|
+
home: options.home,
|
|
287
|
+
...(afterHost === undefined ? {} : { afterHost }),
|
|
288
|
+
...(options.hostFacingModel === undefined ? {} : { hostFacingModel: options.hostFacingModel }),
|
|
289
|
+
});
|
|
290
|
+
if (!opened.ok) {
|
|
301
291
|
return {
|
|
302
292
|
ok: false,
|
|
303
293
|
missingModelMessage: missingResolvedSeatModelMessage(options.role),
|
|
304
294
|
};
|
|
305
295
|
}
|
|
306
|
-
const hostName = seatWithModel.host ?? "pi";
|
|
307
|
-
let hostFacingSelection: RoleTurnModelConfig | undefined = options.hostFacingModel;
|
|
308
|
-
if (hostFacingSelection === undefined) {
|
|
309
|
-
const { loadHostProvidersTable, projectHostFacingProvider } = await import(
|
|
310
|
-
"./public-cli/host-providers.ts"
|
|
311
|
-
);
|
|
312
|
-
hostFacingSelection = projectHostFacingProvider(
|
|
313
|
-
seatWithModel.selection,
|
|
314
|
-
hostName,
|
|
315
|
-
loadHostProvidersTable(options.home),
|
|
316
|
-
options.home,
|
|
317
|
-
);
|
|
318
|
-
}
|
|
319
296
|
return {
|
|
320
297
|
ok: true,
|
|
321
298
|
env: {
|
|
@@ -324,12 +301,13 @@ async function createSummonEnv(
|
|
|
324
301
|
agentDir: options.agentDir,
|
|
325
302
|
sessionAppender: appendPiSessionCustomEntry,
|
|
326
303
|
packageRoot: options.packageRoot,
|
|
327
|
-
roleTurnHost,
|
|
304
|
+
roleTurnHost: opened.roleTurnHost,
|
|
328
305
|
cwd: options.cwd,
|
|
329
306
|
credentials: options.credentials,
|
|
330
|
-
...(
|
|
331
|
-
...
|
|
332
|
-
...
|
|
307
|
+
...(opened.model === undefined ? {} : { model: opened.model }),
|
|
308
|
+
...(opened.engine === undefined ? {} : { engine: opened.engine }),
|
|
309
|
+
...(opened.engineModel === undefined ? {} : { engineModel: opened.engineModel }),
|
|
310
|
+
host: opened.host,
|
|
333
311
|
...(options.timeoutMs === undefined ? {} : { timeoutMs: options.timeoutMs }),
|
|
334
312
|
},
|
|
335
313
|
};
|
|
@@ -344,16 +322,14 @@ export async function summonPublicRole(
|
|
|
344
322
|
): Promise<PublicSummonResult> {
|
|
345
323
|
const packageRoot = resolveSummonsPackageRoot(options.packageRoot);
|
|
346
324
|
const home = await resolveSummonHome(options);
|
|
347
|
-
const agentDir =
|
|
348
|
-
options.agentDir
|
|
349
|
-
?? process.env.PI_CODING_AGENT_DIR
|
|
350
|
-
?? join(home, ".pi", "agent");
|
|
351
325
|
const {
|
|
352
326
|
loadCredentialProviders,
|
|
353
327
|
loadPublicCliConfig,
|
|
354
328
|
resolveEffectiveSeat,
|
|
329
|
+
resolvePublicAgentDir,
|
|
355
330
|
validatePublicCliConfigAxes,
|
|
356
331
|
} = await import("./public-cli/config.ts");
|
|
332
|
+
const agentDir = resolvePublicAgentDir(options.agentDir, home);
|
|
357
333
|
const credentials =
|
|
358
334
|
options.credentials ?? (await loadCredentialProviders(agentDir));
|
|
359
335
|
const config = await loadPublicCliConfig(home);
|
|
@@ -616,7 +592,7 @@ export async function summonParallelReviewerLenses(options: {
|
|
|
616
592
|
if (error instanceof AggregateError) {
|
|
617
593
|
return [error.message, ...error.errors.map(describeFailure)].join("\n");
|
|
618
594
|
}
|
|
619
|
-
return
|
|
595
|
+
return errorText(error);
|
|
620
596
|
};
|
|
621
597
|
const failedResult = (error: unknown): PublicSummonResult => ({
|
|
622
598
|
exitCode: 1,
|
|
@@ -864,7 +840,7 @@ export async function summonGateOfficer(options: {
|
|
|
864
840
|
const correlationId = parentRunId;
|
|
865
841
|
const { isSafePositiveTicketNumber, readBoardTicketNumber } = await import("./run-ticket-number.ts");
|
|
866
842
|
const parentTicket = await readBoardTicketNumber(options.sourceRunDirectory);
|
|
867
|
-
const submittedTicket =
|
|
843
|
+
const submittedTicket = isRecord(options.submission)
|
|
868
844
|
? (options.submission as { ticketNumber?: unknown }).ticketNumber
|
|
869
845
|
: undefined;
|
|
870
846
|
const courtTicket = isSafePositiveTicketNumber(submittedTicket) ? submittedTicket : parentTicket;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { isRecord } from "./unknown-value.ts";
|
|
1
2
|
/** Shared accepted-receipt delivery budget for role, auditor, and Navigator sessions (#288). */
|
|
2
3
|
export const RECEIPT_DELIVERY_TURN_LIMIT = 2 as const;
|
|
3
4
|
|
|
@@ -14,10 +15,6 @@ export type NoReceiptLifecycleFacts = {
|
|
|
14
15
|
acceptedReceipt: false;
|
|
15
16
|
};
|
|
16
17
|
|
|
17
|
-
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
18
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
19
|
-
}
|
|
20
|
-
|
|
21
18
|
/** Read only the facts required by Terminal consumers; persisted extensions are ignored. */
|
|
22
19
|
export function parseNoReceiptLifecycleFacts(input: unknown): NoReceiptLifecycleFacts {
|
|
23
20
|
if (!isRecord(input)
|
package/src/reviewer-role.ts
CHANGED
|
@@ -41,7 +41,6 @@ export type ReviewerRoleDependencies = {
|
|
|
41
41
|
};
|
|
42
42
|
export type ReviewerRoleHostActions = { failInfrastructure(error: unknown, ctx: HostContext, toolCallId?: string): never };
|
|
43
43
|
|
|
44
|
-
|
|
45
44
|
export type ReviewerActivation = Readonly<{
|
|
46
45
|
fixedBaseRevision: string;
|
|
47
46
|
soul: string;
|
package/src/role-envelope.ts
CHANGED
|
@@ -35,6 +35,8 @@ import {
|
|
|
35
35
|
} from "./navigator-invocation-identity.ts";
|
|
36
36
|
import { serializeThrownValue } from "./serialize-thrown-value.ts";
|
|
37
37
|
|
|
38
|
+
import { isRecord, errorText } from "./unknown-value.ts";
|
|
39
|
+
|
|
38
40
|
export { projectActivationFlags };
|
|
39
41
|
|
|
40
42
|
type Handler = HostEventRegistration[1];
|
|
@@ -158,7 +160,7 @@ export async function prepareRoleEnvelope(options: {
|
|
|
158
160
|
try {
|
|
159
161
|
await appendFile(sessionFile, line, "utf8");
|
|
160
162
|
} catch (error) {
|
|
161
|
-
const diagnostic =
|
|
163
|
+
const diagnostic = errorText(error);
|
|
162
164
|
armDurableWriteFailure?.(customType, diagnostic);
|
|
163
165
|
}
|
|
164
166
|
});
|
|
@@ -291,7 +293,7 @@ export async function prepareRoleEnvelope(options: {
|
|
|
291
293
|
content: ContentPart[],
|
|
292
294
|
): void {
|
|
293
295
|
if (infrastructureRoundFailure !== undefined) return;
|
|
294
|
-
const record =
|
|
296
|
+
const record = isRecord(details)
|
|
295
297
|
? details as Record<string, unknown>
|
|
296
298
|
: undefined;
|
|
297
299
|
const isInfra = record !== undefined && (
|
|
@@ -336,7 +338,7 @@ export async function prepareRoleEnvelope(options: {
|
|
|
336
338
|
content: ContentPart[];
|
|
337
339
|
details: Record<string, unknown>;
|
|
338
340
|
} {
|
|
339
|
-
const diagnostic =
|
|
341
|
+
const diagnostic = errorText(error);
|
|
340
342
|
const content: ContentPart[] = [{ type: "text", text: diagnostic }];
|
|
341
343
|
const errorCode = typeof (error as unknown as { code?: unknown })?.code === "string"
|
|
342
344
|
? (error as unknown as { code: string }).code
|
|
@@ -7,6 +7,8 @@ import {
|
|
|
7
7
|
} from "./activation-ledger-topology.ts";
|
|
8
8
|
import { requireSafePositiveTicketNumber } from "./run-ticket-number.ts";
|
|
9
9
|
|
|
10
|
+
import { isEnoent } from "./unknown-value.ts";
|
|
11
|
+
|
|
10
12
|
export type RoleRunSubject =
|
|
11
13
|
| { readonly ticketNumber: number }
|
|
12
14
|
| { readonly unbound: true };
|
|
@@ -19,14 +21,6 @@ export type RoleRunPlacement = {
|
|
|
19
21
|
readonly attachmentsDirectory: string;
|
|
20
22
|
};
|
|
21
23
|
|
|
22
|
-
function isMissingPathError(error: unknown): boolean {
|
|
23
|
-
return (
|
|
24
|
-
error instanceof Error &&
|
|
25
|
-
"code" in error &&
|
|
26
|
-
(error as NodeJS.ErrnoException).code === "ENOENT"
|
|
27
|
-
);
|
|
28
|
-
}
|
|
29
|
-
|
|
30
24
|
/**
|
|
31
25
|
* Sole book-level run directory walk: flat legacy `runs/` plus each
|
|
32
26
|
* `subject/runs/` child (ticket / unbound). One authority for read-side
|
|
@@ -42,7 +36,7 @@ export async function listBookRunDirectories(bookDir: string): Promise<string[]>
|
|
|
42
36
|
try {
|
|
43
37
|
entries = await readdir(runsDir, { withFileTypes: true });
|
|
44
38
|
} catch (error) {
|
|
45
|
-
if (
|
|
39
|
+
if (isEnoent(error)) return;
|
|
46
40
|
throw error;
|
|
47
41
|
}
|
|
48
42
|
for (const entry of entries) {
|
|
@@ -60,7 +54,7 @@ export async function listBookRunDirectories(bookDir: string): Promise<string[]>
|
|
|
60
54
|
try {
|
|
61
55
|
subjects = await readdir(bookDir, { withFileTypes: true });
|
|
62
56
|
} catch (error) {
|
|
63
|
-
if (
|
|
57
|
+
if (isEnoent(error)) return out.sort();
|
|
64
58
|
throw error;
|
|
65
59
|
}
|
|
66
60
|
for (const subject of subjects) {
|
|
@@ -107,6 +101,11 @@ export function roleRunArtifactsDirectory(runDirectory: string): string {
|
|
|
107
101
|
return join(runDirectory, "artifacts");
|
|
108
102
|
}
|
|
109
103
|
|
|
104
|
+
/** Canonical unbound placement: a run directory under `<book>/unbound/runs/`. */
|
|
105
|
+
export function isUnboundRunDirectory(runDirectory: string): boolean {
|
|
106
|
+
return runDirectory.replaceAll("\\", "/").includes("/unbound/runs/");
|
|
107
|
+
}
|
|
108
|
+
|
|
110
109
|
/** The placement seam owns creation for both new runs and resumed legacy runs. */
|
|
111
110
|
export function ensureRoleRunDirectory(
|
|
112
111
|
ledgerHome: string,
|
|
@@ -12,6 +12,8 @@ import { join, sep } from "node:path";
|
|
|
12
12
|
|
|
13
13
|
import { AUDITOR_PARENT_ATTEMPT_BINDING_ENTRY_TYPE } from "./compliance-transport.ts";
|
|
14
14
|
|
|
15
|
+
import { isRecord, isEnoent } from "./unknown-value.ts";
|
|
16
|
+
|
|
15
17
|
const ADMITTED_PAGE_FIELDS = [
|
|
16
18
|
"runDirectory",
|
|
17
19
|
"admittedRequestPath",
|
|
@@ -50,14 +52,6 @@ export type RunDirectoryPathRewrite = {
|
|
|
50
52
|
readonly newRunDirectory: string;
|
|
51
53
|
};
|
|
52
54
|
|
|
53
|
-
function isEnoent(error: unknown): boolean {
|
|
54
|
-
return (
|
|
55
|
-
error instanceof Error &&
|
|
56
|
-
"code" in error &&
|
|
57
|
-
(error as NodeJS.ErrnoException).code === "ENOENT"
|
|
58
|
-
);
|
|
59
|
-
}
|
|
60
|
-
|
|
61
55
|
/** Rewrite one path value that points at or under oldRunDirectory. */
|
|
62
56
|
export function rewriteRunDirectoryPathValue(
|
|
63
57
|
value: unknown,
|
|
@@ -158,16 +152,12 @@ function collectRewrites(input: {
|
|
|
158
152
|
return out;
|
|
159
153
|
}
|
|
160
154
|
|
|
161
|
-
function isPlainObject(value: unknown): value is Record<string, unknown> {
|
|
162
|
-
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
163
|
-
}
|
|
164
|
-
|
|
165
155
|
/** Typed notary/source-run locator: only runDirectory is a path. */
|
|
166
156
|
function rewriteSourceRunLocator(
|
|
167
157
|
value: unknown,
|
|
168
158
|
rewrites: readonly RunDirectoryPathRewrite[],
|
|
169
159
|
): void {
|
|
170
|
-
if (!
|
|
160
|
+
if (!isRecord(value)) return;
|
|
171
161
|
rewriteRunDirectoryPathFieldsAgainstRewrites(
|
|
172
162
|
value,
|
|
173
163
|
SOURCE_RUN_LOCATOR_FIELDS,
|
|
@@ -180,7 +170,7 @@ function rewriteSummonsMaterials(
|
|
|
180
170
|
value: unknown,
|
|
181
171
|
rewrites: readonly RunDirectoryPathRewrite[],
|
|
182
172
|
): void {
|
|
183
|
-
if (!
|
|
173
|
+
if (!isRecord(value)) return;
|
|
184
174
|
rewriteRunDirectoryPathFieldsAgainstRewrites(
|
|
185
175
|
value,
|
|
186
176
|
SUMMONS_PATH_FIELDS,
|
|
@@ -204,12 +194,12 @@ export function rewriteAdmittedRoleRunPage(
|
|
|
204
194
|
rewriteSourceRunLocator(page.sourceRun, rewrites);
|
|
205
195
|
if (Array.isArray(page.attachments)) {
|
|
206
196
|
for (const attachment of page.attachments) {
|
|
207
|
-
if (
|
|
197
|
+
if (isRecord(attachment)) {
|
|
208
198
|
rewriteRunDirectoryPathFieldsAgainstRewrites(attachment, ["frozenPath"], rewrites);
|
|
209
199
|
}
|
|
210
200
|
}
|
|
211
201
|
}
|
|
212
|
-
if (
|
|
202
|
+
if (isRecord(page.principal)) {
|
|
213
203
|
rewriteRunDirectoryPathFieldsAgainstRewrites(
|
|
214
204
|
page.principal,
|
|
215
205
|
["sessionDirectory", "sessionFile"],
|
|
@@ -224,7 +214,7 @@ async function rewriteOfficerPointerFile(
|
|
|
224
214
|
): Promise<void> {
|
|
225
215
|
if (!existsSync(path)) return;
|
|
226
216
|
const page = JSON.parse(await readFile(path, "utf8")) as unknown;
|
|
227
|
-
if (!
|
|
217
|
+
if (!isRecord(page)) return;
|
|
228
218
|
// Only the typed direct-officer pointer shape — never arbitrary .pointer.json.
|
|
229
219
|
if (page.kind !== "direct-officer-run-pointer") return;
|
|
230
220
|
const before = JSON.stringify(page);
|
|
@@ -267,7 +257,7 @@ async function rewriteSitianRecordsJsonl(
|
|
|
267
257
|
out.push(line);
|
|
268
258
|
continue;
|
|
269
259
|
}
|
|
270
|
-
if (!
|
|
260
|
+
if (!isRecord(parsed)) {
|
|
271
261
|
out.push(line);
|
|
272
262
|
continue;
|
|
273
263
|
}
|
|
@@ -325,7 +315,7 @@ async function rewriteSessionTranscriptBindings(
|
|
|
325
315
|
out.push(line);
|
|
326
316
|
continue;
|
|
327
317
|
}
|
|
328
|
-
if (!
|
|
318
|
+
if (!isRecord(parsed)) {
|
|
329
319
|
out.push(line);
|
|
330
320
|
continue;
|
|
331
321
|
}
|
|
@@ -341,8 +331,8 @@ async function rewriteSessionTranscriptBindings(
|
|
|
341
331
|
} else if (
|
|
342
332
|
parsed.type === "custom" &&
|
|
343
333
|
parsed.customType === AUDITOR_PARENT_ATTEMPT_BINDING_ENTRY_TYPE &&
|
|
344
|
-
|
|
345
|
-
|
|
334
|
+
isRecord(parsed.data) &&
|
|
335
|
+
isRecord(parsed.data.parent)
|
|
346
336
|
) {
|
|
347
337
|
const parent = parsed.data.parent;
|
|
348
338
|
const before = parent.sessionFile;
|
|
@@ -454,7 +444,7 @@ export async function rewriteRoleRunDurablePages(input: {
|
|
|
454
444
|
RUN_STATE_PAGE_FIELDS,
|
|
455
445
|
rewrites,
|
|
456
446
|
);
|
|
457
|
-
if (
|
|
447
|
+
if (isRecord(page.principal)) {
|
|
458
448
|
rewriteRunDirectoryPathFieldsAgainstRewrites(
|
|
459
449
|
page.principal,
|
|
460
450
|
["sessionDirectory", "sessionFile"],
|
|
@@ -462,7 +452,7 @@ export async function rewriteRoleRunDurablePages(input: {
|
|
|
462
452
|
);
|
|
463
453
|
}
|
|
464
454
|
// Open court summons: source-run locators + frozen attachment path pointers.
|
|
465
|
-
if (
|
|
455
|
+
if (isRecord(page.currentCourt)) {
|
|
466
456
|
rewriteSummonsMaterials(page.currentCourt.summons, rewrites);
|
|
467
457
|
}
|
|
468
458
|
if (JSON.stringify(page) !== before) {
|
package/src/role-runtime.ts
CHANGED
|
@@ -188,7 +188,7 @@ function decodeReviewerAdmittedInputs(getFlag: (name: string) => unknown): Revie
|
|
|
188
188
|
parsed = JSON.parse(rawAuthorityRefs);
|
|
189
189
|
} catch (error) {
|
|
190
190
|
throw new Error(
|
|
191
|
-
`Reviewer authority refs transport error: JSON decode failed: ${
|
|
191
|
+
`Reviewer authority refs transport error: JSON decode failed: ${errorText(error)}`,
|
|
192
192
|
);
|
|
193
193
|
}
|
|
194
194
|
if (!Array.isArray(parsed) || parsed.some((ref) => typeof ref !== "string")) {
|
|
@@ -297,6 +297,8 @@ export type { GatekeeperResult, GatekeeperSubject, SubmissionGateNonPassResult,
|
|
|
297
297
|
import { ParentQueueReaskError, unreadableDiscriminatorNotice } from "./submission-errors.ts";
|
|
298
298
|
import { REVIEW_QUEUE_STATUSES } from "./review-submission.ts";
|
|
299
299
|
|
|
300
|
+
import { isRecord, errorText, isEnoent } from "./unknown-value.ts";
|
|
301
|
+
|
|
300
302
|
export {
|
|
301
303
|
DOCTOR_EVIDENCE_TOOL_NAME,
|
|
302
304
|
DOCTOR_OUTPUT_TOOL_NAME,
|
|
@@ -507,7 +509,7 @@ export function publicNavigatorSettlement(role: string, phase: NavigatorPhase, e
|
|
|
507
509
|
return { kind: "role_infrastructure_failure", role, phase };
|
|
508
510
|
}
|
|
509
511
|
// accepted/human — project role/phase status; classifier already rejected infra/contradiction.
|
|
510
|
-
const details =
|
|
512
|
+
const details = isRecord(event.details)
|
|
511
513
|
? event.details as Record<string, unknown>
|
|
512
514
|
: {};
|
|
513
515
|
const status = typeof details.status === "string"
|
|
@@ -710,7 +712,7 @@ export function createNavigatorRoleRuntime(
|
|
|
710
712
|
dependencies.recordRoutePlaybookReadFailure?.(undefined);
|
|
711
713
|
if (content.trim() !== "") parts.push(content);
|
|
712
714
|
} catch (error) {
|
|
713
|
-
const message =
|
|
715
|
+
const message = errorText(error);
|
|
714
716
|
if (message.trim() !== "") {
|
|
715
717
|
dependencies.recordRoutePlaybookReadFailure?.(message);
|
|
716
718
|
parts.push(message);
|
|
@@ -854,7 +856,7 @@ export function createDiaristRoleRuntime(
|
|
|
854
856
|
soulTag: "diarist",
|
|
855
857
|
beforeAccept: async ({ parameters, ctx }) => {
|
|
856
858
|
const submitted =
|
|
857
|
-
|
|
859
|
+
isRecord(parameters)
|
|
858
860
|
? (parameters as Record<string, unknown>)
|
|
859
861
|
: undefined;
|
|
860
862
|
// Routing belongs to the public seam after this tool call has returned.
|
|
@@ -1073,7 +1075,7 @@ export function createRoleRuntimeExtension(
|
|
|
1073
1075
|
): void => {
|
|
1074
1076
|
if (attendance === undefined) return;
|
|
1075
1077
|
const recordDisposeFailure = (error: unknown): void => {
|
|
1076
|
-
const diagnostic =
|
|
1078
|
+
const diagnostic = errorText(error);
|
|
1077
1079
|
try {
|
|
1078
1080
|
sitianReport({
|
|
1079
1081
|
level: "event",
|
|
@@ -1087,7 +1089,7 @@ export function createRoleRuntimeExtension(
|
|
|
1087
1089
|
try {
|
|
1088
1090
|
envelopeHost.appendEntry?.("ak-navigator-dispose-failure", {
|
|
1089
1091
|
diagnostic,
|
|
1090
|
-
recordFailure:
|
|
1092
|
+
recordFailure: errorText(recordError),
|
|
1091
1093
|
});
|
|
1092
1094
|
} catch {
|
|
1093
1095
|
// Failure already diagnosed; recording must not create unhandled rejection (#959).
|
|
@@ -1655,15 +1657,7 @@ export function createRoleRuntimeExtension(
|
|
|
1655
1657
|
try {
|
|
1656
1658
|
await recordTypedProviderHttpStatus(runDir, { httpStatus: status, provider });
|
|
1657
1659
|
} catch (error) {
|
|
1658
|
-
if (
|
|
1659
|
-
status >= 200 &&
|
|
1660
|
-
status < 300 &&
|
|
1661
|
-
error instanceof Error &&
|
|
1662
|
-
"code" in error &&
|
|
1663
|
-
(error as { code?: unknown }).code === "ENOENT"
|
|
1664
|
-
) {
|
|
1665
|
-
return;
|
|
1666
|
-
}
|
|
1660
|
+
if (status >= 200 && status < 300 && isEnoent(error)) return;
|
|
1667
1661
|
failInfrastructure(error, ctx);
|
|
1668
1662
|
}
|
|
1669
1663
|
};
|