@akagilnc/pi-workflow-roles 0.1.5368 → 0.1.5382
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 +1192 -1195
- 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/collector-tool-schemas.js +18 -0
- package/dist/compliance-transport.js +2 -1
- package/dist/countersign-contracts.js +2 -1
- package/dist/diarist-contracts.js +29 -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/filed-submission.js +28 -0
- package/dist/gatekeeper-role.js +8 -19
- package/dist/gleaner-left-contracts.js +18 -1
- package/dist/headless-host/description.js +14 -17
- package/dist/headless-host/production-host.js +1210 -1215
- package/dist/host-session-record.js +3 -2
- package/dist/inspector-contracts.js +2 -1
- package/dist/judge-role.js +8 -16
- package/dist/ledger-session-read.js +1 -3
- package/dist/merger-contracts.js +9 -9
- package/dist/migrate-book-topology.js +610 -321
- 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/reviewer-output.js +16 -0
- package/dist/package-contracts/terminating-infrastructure.js +5 -9
- package/dist/package-contracts/terminating-tools.js +4 -3
- package/dist/package-contracts/worker-output.js +18 -2
- package/dist/public-cli/analyst-run.js +3 -2
- package/dist/public-cli/auto-resume.js +3 -8
- package/dist/public-cli/cli.js +9 -8
- package/dist/public-cli/config.js +8 -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 +12 -14
- package/dist/public-cli/invocation.js +9 -8
- package/dist/public-cli/main.js +1820 -1599
- package/dist/public-cli/post-admission.js +4 -3
- package/dist/public-cli/run-lifecycle.js +14 -26
- package/dist/public-cli/settlement.js +10 -26
- package/dist/public-role-summons.js +3 -2
- package/dist/receipt-delivery-policy.js +1 -3
- package/dist/role-run-placement.js +3 -5
- package/dist/role-run-relocation.js +12 -19
- package/dist/role-submission-declarations.js +131 -0
- package/dist/run-terminal-artifacts.js +1 -11
- package/dist/run-ticket-number.js +2 -4
- package/dist/secretariat-contracts.js +23 -1
- 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 +6 -8
- 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-role.ts +2 -8
- package/src/auditor-soul.ts +3 -1
- package/src/book-topology-migration-placement.ts +5 -16
- 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/collector-role.ts +5 -28
- package/src/compliance-transport.ts +2 -1
- package/src/countersign-contracts.ts +2 -1
- package/src/countersign-role.ts +2 -7
- package/src/diarist-contracts.ts +40 -2
- package/src/diarist-role.ts +4 -44
- package/src/doctor-contracts.ts +3 -1
- package/src/doctor-evidence.ts +8 -7
- package/src/doctor-role.ts +20 -13
- 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/filed-submission.ts +44 -0
- package/src/gatekeeper-role.ts +8 -24
- package/src/gleaner-left-contracts.ts +29 -2
- package/src/gleaner-left-role.ts +4 -32
- 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/inspector-role.ts +2 -7
- package/src/judge-role.ts +12 -24
- package/src/ledger-session-read.ts +2 -5
- package/src/merger-contracts.ts +10 -9
- package/src/merger-role.ts +5 -8
- 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-role.ts +2 -8
- 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/notary-role.ts +5 -20
- 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/reviewer-output.ts +25 -0
- package/src/package-contracts/terminating-infrastructure.ts +6 -20
- package/src/package-contracts/terminating-tools.ts +8 -12
- package/src/package-contracts/worker-output.ts +43 -5
- 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 +4 -11
- package/src/public-cli/cli.ts +10 -10
- package/src/public-cli/config.ts +8 -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 +14 -15
- package/src/public-cli/invocation.ts +11 -10
- package/src/public-cli/post-admission.ts +5 -3
- package/src/public-cli/run-lifecycle.ts +20 -41
- package/src/public-cli/settlement.ts +11 -33
- package/src/public-role-summons.ts +4 -3
- package/src/receipt-delivery-policy.ts +1 -4
- package/src/reviewer-role.ts +7 -36
- package/src/role-envelope.ts +5 -3
- package/src/role-run-placement.ts +4 -10
- package/src/role-run-relocation.ts +13 -23
- package/src/role-runtime.ts +16 -50
- package/src/role-submission-declarations.ts +143 -0
- package/src/run-terminal-artifacts.ts +2 -16
- package/src/run-ticket-number.ts +4 -10
- package/src/secretariat-contracts.ts +35 -0
- package/src/secretariat-role.ts +4 -40
- 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 +10 -9
- 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 +63 -83
- package/src/worker-submission-gates.ts +8 -7
|
@@ -12,6 +12,7 @@ import { readFileSync } from "node:fs";
|
|
|
12
12
|
import { join } from "node:path";
|
|
13
13
|
|
|
14
14
|
import type { SeatModelConfig } from "./config.ts";
|
|
15
|
+
import { isEnoent, isRecord } from "../unknown-value.ts";
|
|
15
16
|
|
|
16
17
|
/** host → seat-provider → host-facing provider. */
|
|
17
18
|
export type HostProvidersTable = Readonly<
|
|
@@ -31,25 +32,19 @@ export function hermesProviderModelsCachePath(home: string): string {
|
|
|
31
32
|
}
|
|
32
33
|
|
|
33
34
|
export function parseHostProvidersTable(value: unknown): HostProvidersTable {
|
|
34
|
-
if (
|
|
35
|
+
if (!isRecord(value)) {
|
|
35
36
|
throw new Error("host-providers.json must be an object");
|
|
36
37
|
}
|
|
37
38
|
const out: Record<string, Record<string, string>> = {};
|
|
38
|
-
for (const [host, byProvider] of Object.entries(value
|
|
39
|
+
for (const [host, byProvider] of Object.entries(value)) {
|
|
39
40
|
if (host.trim() === "") {
|
|
40
41
|
throw new Error("host-providers.json host key must be non-empty");
|
|
41
42
|
}
|
|
42
|
-
if (
|
|
43
|
-
byProvider === null ||
|
|
44
|
-
typeof byProvider !== "object" ||
|
|
45
|
-
Array.isArray(byProvider)
|
|
46
|
-
) {
|
|
43
|
+
if (!isRecord(byProvider)) {
|
|
47
44
|
throw new Error(`host-providers.json[${host}] must be an object`);
|
|
48
45
|
}
|
|
49
46
|
const providers: Record<string, string> = {};
|
|
50
|
-
for (const [seatProvider, hostProvider] of Object.entries(
|
|
51
|
-
byProvider as Record<string, unknown>,
|
|
52
|
-
)) {
|
|
47
|
+
for (const [seatProvider, hostProvider] of Object.entries(byProvider)) {
|
|
53
48
|
if (seatProvider.trim() === "") {
|
|
54
49
|
throw new Error(
|
|
55
50
|
`host-providers.json[${host}] seat-provider key must be non-empty`,
|
|
@@ -79,13 +74,7 @@ export function loadHostProvidersTable(home: string): HostProvidersTable {
|
|
|
79
74
|
const raw = readFileSync(path, "utf8");
|
|
80
75
|
return parseHostProvidersTable(JSON.parse(raw) as unknown);
|
|
81
76
|
} catch (error) {
|
|
82
|
-
if (
|
|
83
|
-
error instanceof Error &&
|
|
84
|
-
"code" in error &&
|
|
85
|
-
(error as NodeJS.ErrnoException).code === "ENOENT"
|
|
86
|
-
) {
|
|
87
|
-
return {};
|
|
88
|
-
}
|
|
77
|
+
if (isEnoent(error)) return {};
|
|
89
78
|
throw error;
|
|
90
79
|
}
|
|
91
80
|
}
|
|
@@ -115,24 +104,18 @@ export function listHermesProvidersForModel(
|
|
|
115
104
|
try {
|
|
116
105
|
text = readFileSync(path, "utf8");
|
|
117
106
|
} catch (error) {
|
|
118
|
-
if (
|
|
119
|
-
error instanceof Error &&
|
|
120
|
-
"code" in error &&
|
|
121
|
-
(error as NodeJS.ErrnoException).code === "ENOENT"
|
|
122
|
-
) {
|
|
123
|
-
return [];
|
|
124
|
-
}
|
|
107
|
+
if (isEnoent(error)) return [];
|
|
125
108
|
throw error;
|
|
126
109
|
}
|
|
127
110
|
const raw: unknown = JSON.parse(text);
|
|
128
|
-
if (
|
|
111
|
+
if (!isRecord(raw)) {
|
|
129
112
|
throw new Error(
|
|
130
113
|
`hermes provider_models_cache.json must be an object: ${path}`,
|
|
131
114
|
);
|
|
132
115
|
}
|
|
133
116
|
const found: string[] = [];
|
|
134
|
-
for (const [provider, entry] of Object.entries(raw
|
|
135
|
-
if (
|
|
117
|
+
for (const [provider, entry] of Object.entries(raw)) {
|
|
118
|
+
if (!isRecord(entry)) {
|
|
136
119
|
continue;
|
|
137
120
|
}
|
|
138
121
|
const models = (entry as { models?: unknown }).models;
|
|
@@ -11,6 +11,8 @@ import { createPiDoctorAuditor } from "../doctor-auditor.ts";
|
|
|
11
11
|
|
|
12
12
|
import type { DurablePrincipalAuthority, HostContext, RoleTurnRequest } from "../host-contracts.ts";
|
|
13
13
|
import { officerConclusionReask, gateOfficerForSubject } from "../gatekeeper-role.ts";
|
|
14
|
+
import { receivedDiscriminator } from "../submission-errors.ts";
|
|
15
|
+
import { REVIEW_QUEUE_STATUSES } from "../review-submission.ts";
|
|
14
16
|
import { runJudgeGates } from "../judge-role.ts";
|
|
15
17
|
import { WORKER_DONE_STATUSES } from "../worker-submission-contracts.ts";
|
|
16
18
|
import { SECRETARIAT_GATE_OFFICER_ENTRY_TYPE } from "../secretariat-contracts.ts";
|
|
@@ -101,6 +103,8 @@ import {
|
|
|
101
103
|
latestPayloadEscalated,
|
|
102
104
|
type CountersignRunEnv,
|
|
103
105
|
} from "./countersign-run.ts";
|
|
106
|
+
import { isRecord, errorText } from "../unknown-value.ts";
|
|
107
|
+
|
|
104
108
|
export type InstructionSeatRunEnv = PostAdmissionEnv & Pick<
|
|
105
109
|
CountersignRunEnv,
|
|
106
110
|
"reviewReask" | "gateReviewInstruction" | "parentRunPath"
|
|
@@ -114,7 +118,6 @@ type SeatRunResult = {
|
|
|
114
118
|
|
|
115
119
|
const AUDITED_ROLES = new Set<PackagedRole>(["judge", "fixer", "coder", "secretariat", "countersign", "doctor"]);
|
|
116
120
|
const SECRETARIAT_STATUS_REASK = "secretariatStatus 不是 converged、escalate 之一。请重新交卷,secretariatStatus 写明其一。";
|
|
117
|
-
const COUNTERSIGN_STATUS_REASK = "status 不是 converged、continue、escalate 三态之一。请重新交卷,status 写明其一。";
|
|
118
121
|
const WORKER_ROUTING_STATUSES: ReadonlySet<string> = new Set([
|
|
119
122
|
"planned", "completed", "refused", "partially_completed", "unfinished",
|
|
120
123
|
]);
|
|
@@ -125,11 +128,10 @@ const DOCTOR_STATUS_REASK =
|
|
|
125
128
|
"status 不是 completed、refused 之一。请重新交卷,status 写明其一。";
|
|
126
129
|
const POST_SUBMISSION_ROUTING: Partial<Record<PackagedRole, {
|
|
127
130
|
readonly statuses: ReadonlySet<string>;
|
|
128
|
-
readonly reask
|
|
131
|
+
readonly reask?: string;
|
|
129
132
|
}>> = {
|
|
130
133
|
judge: {
|
|
131
|
-
statuses:
|
|
132
|
-
reask: "status 不是 converged、continue、escalate 三态之一。请重新交卷,status 写明其一。",
|
|
134
|
+
statuses: REVIEW_QUEUE_STATUSES,
|
|
133
135
|
},
|
|
134
136
|
coder: {
|
|
135
137
|
statuses: WORKER_ROUTING_STATUSES,
|
|
@@ -159,12 +161,10 @@ function unreadablePostSubmissionStatus(
|
|
|
159
161
|
const route = POST_SUBMISSION_ROUTING[admitted.role];
|
|
160
162
|
if (route === undefined) return undefined;
|
|
161
163
|
const payload = terminal.roleOutcome.payloads?.at(-1);
|
|
162
|
-
const status = payload
|
|
163
|
-
? (payload as Record<string, unknown>).status
|
|
164
|
-
: undefined;
|
|
164
|
+
const status = receivedDiscriminator(payload, "status");
|
|
165
165
|
return typeof status === "string" && route.statuses.has(status)
|
|
166
166
|
? undefined
|
|
167
|
-
: route.reask;
|
|
167
|
+
: route.reask ?? officerConclusionReask(status);
|
|
168
168
|
}
|
|
169
169
|
|
|
170
170
|
async function reaskUnreadablePostSubmissionStatus(
|
|
@@ -659,7 +659,7 @@ export async function runPublicInstructionSeat(
|
|
|
659
659
|
auditorSource = resolved.runDirectory;
|
|
660
660
|
auditorTicket = await readBoardTicketNumber(resolved.runDirectory);
|
|
661
661
|
} catch (error) {
|
|
662
|
-
presentStructuralRejection(new CliUsageError(
|
|
662
|
+
presentStructuralRejection(new CliUsageError(errorText(error)), io);
|
|
663
663
|
return { exitCode: 2 };
|
|
664
664
|
}
|
|
665
665
|
if (auditorSource === undefined) return { exitCode: 2 };
|
|
@@ -906,7 +906,6 @@ export async function runPublicInstructionSeatResume(
|
|
|
906
906
|
return resume();
|
|
907
907
|
}
|
|
908
908
|
|
|
909
|
-
const QUEUE_CONCLUSIONS = new Set(["converged", "continue", "escalate"]);
|
|
910
909
|
const GATE_CHILD_ROLES = new Set(["notary", "auditor", "inspector", "countersign"]);
|
|
911
910
|
|
|
912
911
|
/**
|
|
@@ -931,7 +930,7 @@ async function queueConclusionFromChild(
|
|
|
931
930
|
undefined,
|
|
932
931
|
);
|
|
933
932
|
const status = latestQueueStatus(terminal);
|
|
934
|
-
if (terminal !== undefined && status
|
|
933
|
+
if (terminal !== undefined && typeof status === "string" && REVIEW_QUEUE_STATUSES.has(status)) {
|
|
935
934
|
return { admitted: current, terminal, status };
|
|
936
935
|
}
|
|
937
936
|
const reasked = await runPublicInstructionSeatResume({
|
|
@@ -942,7 +941,7 @@ async function queueConclusionFromChild(
|
|
|
942
941
|
return { stop: reasked };
|
|
943
942
|
}
|
|
944
943
|
const reaskedStatus = latestQueueStatus(reasked.terminal);
|
|
945
|
-
if (reaskedStatus
|
|
944
|
+
if (typeof reaskedStatus === "string" && REVIEW_QUEUE_STATUSES.has(reaskedStatus)) {
|
|
946
945
|
return { admitted: reasked.admitted, terminal: reasked.terminal, status: reaskedStatus };
|
|
947
946
|
}
|
|
948
947
|
if (latestPayloadEscalated(reasked.terminal.roleOutcome)) return { stop: reasked };
|
|
@@ -997,15 +996,15 @@ async function auditSubmittedRole(
|
|
|
997
996
|
|| turn.terminal?.roleOutcome.kind !== "accepted") return turn;
|
|
998
997
|
const accepted = turn.terminal.roleOutcome.payloads?.at(-1);
|
|
999
998
|
if (accepted === undefined) throw new Error("accepted submission has no payload");
|
|
1000
|
-
const record =
|
|
999
|
+
const record = isRecord(accepted)
|
|
1001
1000
|
? accepted as Record<string, unknown> : undefined;
|
|
1002
1001
|
const status = admitted.role === "secretariat" ? record?.secretariatStatus : record?.status;
|
|
1003
1002
|
if (admitted.role === "secretariat" && status !== "converged" && status !== "escalate") {
|
|
1004
1003
|
return runPublicInstructionSeatResume({ runId: admitted.runId, message: SECRETARIAT_STATUS_REASK },
|
|
1005
1004
|
{ ...env, autoResumeLimit: 0 }, io);
|
|
1006
1005
|
}
|
|
1007
|
-
if (admitted.role === "countersign" && (typeof status !== "string" || !
|
|
1008
|
-
return runPublicInstructionSeatResume({ runId: admitted.runId, message:
|
|
1006
|
+
if (admitted.role === "countersign" && (typeof status !== "string" || !REVIEW_QUEUE_STATUSES.has(status))) {
|
|
1007
|
+
return runPublicInstructionSeatResume({ runId: admitted.runId, message: officerConclusionReask(status) },
|
|
1009
1008
|
{ ...env, autoResumeLimit: 0 }, io);
|
|
1010
1009
|
}
|
|
1011
1010
|
// Self-escalation is a valid open routing state for these seats only.
|
|
@@ -110,6 +110,8 @@ import {
|
|
|
110
110
|
} from "./option-definitions.ts";
|
|
111
111
|
import type { PublicThinkingLevel } from "./registry.ts";
|
|
112
112
|
|
|
113
|
+
import { errorText, isRecord } from "../unknown-value.ts";
|
|
114
|
+
|
|
113
115
|
export type FrozenAttachment = {
|
|
114
116
|
/** Original caller path retained only as provenance. */
|
|
115
117
|
readonly provenancePath: string;
|
|
@@ -1571,7 +1573,7 @@ export async function admitPublicRole(
|
|
|
1571
1573
|
try {
|
|
1572
1574
|
repository = parseCollectorRepository(parsed.repo);
|
|
1573
1575
|
} catch (error) {
|
|
1574
|
-
const detail =
|
|
1576
|
+
const detail = errorText(error);
|
|
1575
1577
|
throw new CliUsageError(detail, { cause: error });
|
|
1576
1578
|
}
|
|
1577
1579
|
} else {
|
|
@@ -1585,7 +1587,7 @@ export async function admitPublicRole(
|
|
|
1585
1587
|
manifestCanonicalJson = manifest.canonicalJson;
|
|
1586
1588
|
} catch (error) {
|
|
1587
1589
|
throw new CliUsageError(
|
|
1588
|
-
|
|
1590
|
+
errorText(error),
|
|
1589
1591
|
{ cause: error },
|
|
1590
1592
|
);
|
|
1591
1593
|
}
|
|
@@ -1640,7 +1642,7 @@ export async function admitPublicRole(
|
|
|
1640
1642
|
});
|
|
1641
1643
|
} catch (error) {
|
|
1642
1644
|
if (error instanceof CliUsageError) throw error;
|
|
1643
|
-
const detail =
|
|
1645
|
+
const detail = errorText(error);
|
|
1644
1646
|
throw new CliUsageError(detail, { cause: error });
|
|
1645
1647
|
}
|
|
1646
1648
|
if (parsed.runs === undefined) {
|
|
@@ -1658,7 +1660,7 @@ export async function admitPublicRole(
|
|
|
1658
1660
|
caseRunsPath = await realpath(caseRunsPath);
|
|
1659
1661
|
} catch (error) {
|
|
1660
1662
|
if (error instanceof CliUsageError) throw error;
|
|
1661
|
-
const detail =
|
|
1663
|
+
const detail = errorText(error);
|
|
1662
1664
|
throw new CliUsageError(
|
|
1663
1665
|
`doctor case could not be constructed from retained evidence: ${detail}`,
|
|
1664
1666
|
{ cause: error },
|
|
@@ -2203,8 +2205,8 @@ export async function loadAdmittedJudgeRequest(
|
|
|
2203
2205
|
const raw = JSON.parse(
|
|
2204
2206
|
await readFile(join(runDirectory, "admitted-request.json"), "utf8"),
|
|
2205
2207
|
) as unknown;
|
|
2206
|
-
if (
|
|
2207
|
-
const record = raw
|
|
2208
|
+
if (!isRecord(raw)) return undefined;
|
|
2209
|
+
const record = raw;
|
|
2208
2210
|
if (!packagedPublicInstructionSubject(record.role)) return undefined;
|
|
2209
2211
|
if (typeof record.instruction !== "string") return undefined;
|
|
2210
2212
|
if (typeof record.instructionEmpty !== "boolean") return undefined;
|
|
@@ -2246,7 +2248,7 @@ export type AdmitFixerInvocationOptions = {
|
|
|
2246
2248
|
|
|
2247
2249
|
function parsePositivePrOption(raw: string | undefined): number {
|
|
2248
2250
|
if (raw === undefined || raw.trim() === "") throw new CliUsageError("--pr requires a positive pull request number");
|
|
2249
|
-
try { return parseCollectorPrNumber(raw); } catch (error) { throw new CliUsageError(
|
|
2251
|
+
try { return parseCollectorPrNumber(raw); } catch (error) { throw new CliUsageError(errorText(error), { cause: error }); }
|
|
2250
2252
|
}
|
|
2251
2253
|
function parseRepoOption(raw: string | undefined): string {
|
|
2252
2254
|
if (raw === undefined || raw.trim() === "") throw new CliUsageError("--repo requires owner/repo");
|
|
@@ -2294,7 +2296,7 @@ export function resolveGitHubRemoteRepository(
|
|
|
2294
2296
|
try {
|
|
2295
2297
|
return parseCollectorRepository(ownerRepo);
|
|
2296
2298
|
} catch (error) {
|
|
2297
|
-
const detail =
|
|
2299
|
+
const detail = errorText(error);
|
|
2298
2300
|
throw new CliUsageError(detail, { cause: error });
|
|
2299
2301
|
}
|
|
2300
2302
|
}
|
|
@@ -2379,7 +2381,7 @@ export async function resolveDoctorCaseRunsPath(options: {
|
|
|
2379
2381
|
try {
|
|
2380
2382
|
real = await realpath(resolved);
|
|
2381
2383
|
} catch (error) {
|
|
2382
|
-
const detail =
|
|
2384
|
+
const detail = errorText(error);
|
|
2383
2385
|
throw new CliUsageError(
|
|
2384
2386
|
`doctor --runs is not a readable retained runs root: ${detail}`,
|
|
2385
2387
|
{ cause: error },
|
|
@@ -2401,7 +2403,6 @@ export async function resolveDoctorCaseRunsPath(options: {
|
|
|
2401
2403
|
return real;
|
|
2402
2404
|
}
|
|
2403
2405
|
|
|
2404
|
-
|
|
2405
2406
|
export type AdmitReviewerInvocationOptions = {
|
|
2406
2407
|
home: string;
|
|
2407
2408
|
principalAuthority: DurablePrincipalAuthority;
|
|
@@ -122,6 +122,8 @@ import {
|
|
|
122
122
|
writeHardenedArtifactFile,
|
|
123
123
|
} from "./auto-resume.ts";
|
|
124
124
|
|
|
125
|
+
import { isRecord, errorText } from "../unknown-value.ts";
|
|
126
|
+
|
|
125
127
|
function projectRelocatedTurnIdentity(
|
|
126
128
|
request: RoleTurnRequest,
|
|
127
129
|
result: { readonly terminal?: TerminalResult },
|
|
@@ -137,7 +139,7 @@ function projectRelocatedTurnIdentity(
|
|
|
137
139
|
mutableRequest.runDirectory = admitted.runDirectory;
|
|
138
140
|
mutableRequest.principal = admitted.principal;
|
|
139
141
|
const activation = mutableRequest.activation;
|
|
140
|
-
if (
|
|
142
|
+
if (isRecord(activation)) {
|
|
141
143
|
for (const field of ["taskPath", "packetPath", "prerequisitesPath", "inputPath", "requestManifestPath"] as const) {
|
|
142
144
|
const record = activation as Record<string, unknown>;
|
|
143
145
|
if (field in record) record[field] = rewrite(record[field]);
|
|
@@ -733,7 +735,7 @@ export async function dispatchPostAdmissionTurn<
|
|
|
733
735
|
continue;
|
|
734
736
|
}
|
|
735
737
|
const payload = row.accepted;
|
|
736
|
-
if (
|
|
738
|
+
if (!isRecord(payload)) continue;
|
|
737
739
|
ticketNumber = readDeclaredTicketNumber(
|
|
738
740
|
(payload as { ticketNumber?: unknown }).ticketNumber,
|
|
739
741
|
);
|
|
@@ -1802,7 +1804,7 @@ async function presentResumeFailurePointer(
|
|
|
1802
1804
|
cause.thrownCause = formatErrorCauseDetail(thrown.cause);
|
|
1803
1805
|
}
|
|
1804
1806
|
presentStructuralRejection({
|
|
1805
|
-
message:
|
|
1807
|
+
message: errorText(thrown),
|
|
1806
1808
|
cause,
|
|
1807
1809
|
}, io);
|
|
1808
1810
|
}
|
|
@@ -71,6 +71,8 @@ import {
|
|
|
71
71
|
type ReviewerLens,
|
|
72
72
|
} from "./invocation.ts";
|
|
73
73
|
|
|
74
|
+
import { isRecord, errorText, isEnoent } from "../unknown-value.ts";
|
|
75
|
+
|
|
74
76
|
/** Providers eligible for v1 typed-429 resume (Codex / xAI only).
|
|
75
77
|
* @deprecated v1 429-only gate removed by #416 (owner 2026-08-22: "根本不要有限制"). Kept for compatibility; do not use for new branching.
|
|
76
78
|
*/
|
|
@@ -241,8 +243,8 @@ type RoleRunStateDisk = {
|
|
|
241
243
|
function parseSameTicketSummonsMaterials(
|
|
242
244
|
raw: unknown,
|
|
243
245
|
): SameTicketSummonsMaterials | undefined {
|
|
244
|
-
if (
|
|
245
|
-
const record = raw
|
|
246
|
+
if (!isRecord(raw)) return undefined;
|
|
247
|
+
const record = raw;
|
|
246
248
|
const instruction =
|
|
247
249
|
typeof record.instruction === "string" ? record.instruction : undefined;
|
|
248
250
|
const instructionEmpty =
|
|
@@ -256,9 +258,7 @@ function parseSameTicketSummonsMaterials(
|
|
|
256
258
|
: undefined;
|
|
257
259
|
let sourceRun: NotarySourceRunLocator | undefined;
|
|
258
260
|
if (
|
|
259
|
-
record.sourceRun
|
|
260
|
-
typeof record.sourceRun === "object" &&
|
|
261
|
-
!Array.isArray(record.sourceRun)
|
|
261
|
+
isRecord(record.sourceRun)
|
|
262
262
|
) {
|
|
263
263
|
const sr = record.sourceRun as Record<string, unknown>;
|
|
264
264
|
if (
|
|
@@ -297,8 +297,8 @@ function parseSameTicketSummonsMaterials(
|
|
|
297
297
|
}
|
|
298
298
|
|
|
299
299
|
function parseCurrentCourtState(raw: unknown): CurrentCourtState | undefined {
|
|
300
|
-
if (
|
|
301
|
-
const record = raw
|
|
300
|
+
if (!isRecord(raw)) return undefined;
|
|
301
|
+
const record = raw;
|
|
302
302
|
if (typeof record.courtAttemptId !== "string" || record.courtAttemptId.length === 0) {
|
|
303
303
|
return undefined;
|
|
304
304
|
}
|
|
@@ -333,10 +333,10 @@ function parseRoleRunIdentity(raw: unknown, runDirectory: string): {
|
|
|
333
333
|
readonly runDirectory: string;
|
|
334
334
|
readonly state: RoleRunState;
|
|
335
335
|
} {
|
|
336
|
-
if (
|
|
336
|
+
if (!isRecord(raw)) {
|
|
337
337
|
throw new TypeError("Invalid run-state.json");
|
|
338
338
|
}
|
|
339
|
-
const record = raw
|
|
339
|
+
const record = raw;
|
|
340
340
|
if (typeof record.runId !== "string" || record.runId.trim() === "") {
|
|
341
341
|
throw new TypeError("Invalid run-state.json");
|
|
342
342
|
}
|
|
@@ -390,11 +390,8 @@ async function readRoleRunStateDisk(
|
|
|
390
390
|
};
|
|
391
391
|
let resumable: TypedHttp429Observation | undefined;
|
|
392
392
|
if (record.resumable !== undefined && record.resumable !== null) {
|
|
393
|
-
if (
|
|
394
|
-
|
|
395
|
-
!Array.isArray(record.resumable)
|
|
396
|
-
) {
|
|
397
|
-
const r = record.resumable as Record<string, unknown>;
|
|
393
|
+
if (isRecord(record.resumable)) {
|
|
394
|
+
const r = record.resumable;
|
|
398
395
|
if (
|
|
399
396
|
r.httpStatus === 429 &&
|
|
400
397
|
typeof r.provider === "string" &&
|
|
@@ -702,7 +699,6 @@ export type RunWriterLease = {
|
|
|
702
699
|
/** Kind of a writer-lease diagnostic sent on the existing sink. */
|
|
703
700
|
export type WriterLeaseDiagnosticKind = "stale-reclaimed";
|
|
704
701
|
|
|
705
|
-
|
|
706
702
|
/**
|
|
707
703
|
* True error identity for diagnostics — name/code/message as-is, never a
|
|
708
704
|
* guessed label (failure-honesty constitution).
|
|
@@ -741,7 +737,6 @@ function isProcessAlive(pid: number): boolean {
|
|
|
741
737
|
}
|
|
742
738
|
}
|
|
743
739
|
|
|
744
|
-
|
|
745
740
|
export type WriterLockAutopsy =
|
|
746
741
|
| { verdict: "absent" }
|
|
747
742
|
| { verdict: "unknown"; reason: "unparseable"; content: string }
|
|
@@ -1072,10 +1067,10 @@ export async function readRunParentPath(
|
|
|
1072
1067
|
if (errorCodeOf(error) === "ENOENT") return undefined;
|
|
1073
1068
|
throw error;
|
|
1074
1069
|
}
|
|
1075
|
-
if (
|
|
1070
|
+
if (!isRecord(raw)) {
|
|
1076
1071
|
return undefined;
|
|
1077
1072
|
}
|
|
1078
|
-
const record = raw
|
|
1073
|
+
const record = raw;
|
|
1079
1074
|
if (typeof record.sourceRunPath === "string" && record.sourceRunPath.trim() !== "") {
|
|
1080
1075
|
return record.sourceRunPath;
|
|
1081
1076
|
}
|
|
@@ -1280,7 +1275,7 @@ async function loadResumableRunRecord(
|
|
|
1280
1275
|
const raw: unknown = JSON.parse(
|
|
1281
1276
|
await readFile(run.admittedRequestPath, "utf8"),
|
|
1282
1277
|
);
|
|
1283
|
-
if (
|
|
1278
|
+
if (isRecord(raw)) {
|
|
1284
1279
|
const record = raw as Record<string, unknown>;
|
|
1285
1280
|
const storedRunDirectory =
|
|
1286
1281
|
typeof record.runDirectory === "string" && record.runDirectory.trim() !== ""
|
|
@@ -1353,9 +1348,7 @@ async function loadResumableRunRecord(
|
|
|
1353
1348
|
caseRunsPath = record.caseRunsPath;
|
|
1354
1349
|
}
|
|
1355
1350
|
if (
|
|
1356
|
-
record.caseIdentity
|
|
1357
|
-
typeof record.caseIdentity === "object" &&
|
|
1358
|
-
!Array.isArray(record.caseIdentity)
|
|
1351
|
+
isRecord(record.caseIdentity)
|
|
1359
1352
|
) {
|
|
1360
1353
|
const ci = record.caseIdentity as Record<string, unknown>;
|
|
1361
1354
|
if (
|
|
@@ -1373,9 +1366,7 @@ async function loadResumableRunRecord(
|
|
|
1373
1366
|
sourceRunPath = record.sourceRunPath;
|
|
1374
1367
|
}
|
|
1375
1368
|
if (
|
|
1376
|
-
record.sourceRun
|
|
1377
|
-
typeof record.sourceRun === "object" &&
|
|
1378
|
-
!Array.isArray(record.sourceRun)
|
|
1369
|
+
isRecord(record.sourceRun)
|
|
1379
1370
|
) {
|
|
1380
1371
|
const sr = record.sourceRun as Record<string, unknown>;
|
|
1381
1372
|
if (
|
|
@@ -1413,9 +1404,7 @@ async function loadResumableRunRecord(
|
|
|
1413
1404
|
mergerInputPath = record.mergerInputPath;
|
|
1414
1405
|
}
|
|
1415
1406
|
if (
|
|
1416
|
-
record.derived
|
|
1417
|
-
typeof record.derived === "object" &&
|
|
1418
|
-
!Array.isArray(record.derived)
|
|
1407
|
+
isRecord(record.derived)
|
|
1419
1408
|
) {
|
|
1420
1409
|
const d = record.derived as Record<string, unknown>;
|
|
1421
1410
|
if (
|
|
@@ -1452,9 +1441,7 @@ async function loadResumableRunRecord(
|
|
|
1452
1441
|
await readFile(join(run.runDirectory, "invocation.json"), "utf8"),
|
|
1453
1442
|
);
|
|
1454
1443
|
if (
|
|
1455
|
-
invocationRaw
|
|
1456
|
-
typeof invocationRaw === "object" &&
|
|
1457
|
-
!Array.isArray(invocationRaw)
|
|
1444
|
+
isRecord(invocationRaw)
|
|
1458
1445
|
) {
|
|
1459
1446
|
const rec = invocationRaw as Record<string, unknown>;
|
|
1460
1447
|
if (typeof rec.provider === "string" && typeof rec.model === "string") {
|
|
@@ -1478,13 +1465,7 @@ async function loadResumableRunRecord(
|
|
|
1478
1465
|
) {
|
|
1479
1466
|
throw error;
|
|
1480
1467
|
}
|
|
1481
|
-
if (
|
|
1482
|
-
!(
|
|
1483
|
-
error instanceof Error &&
|
|
1484
|
-
"code" in error &&
|
|
1485
|
-
(error as { code?: unknown }).code === "ENOENT"
|
|
1486
|
-
)
|
|
1487
|
-
) {
|
|
1468
|
+
if (!isEnoent(error)) {
|
|
1488
1469
|
throw new CliUsageError(
|
|
1489
1470
|
`role run invocation identity is unreadable: ${runId}`,
|
|
1490
1471
|
{ cause: error },
|
|
@@ -1583,7 +1564,6 @@ function seatLoadedResult<R extends AdmittedRoleInvocation>(
|
|
|
1583
1564
|
};
|
|
1584
1565
|
}
|
|
1585
1566
|
|
|
1586
|
-
|
|
1587
1567
|
export async function peekRoleRunRole(
|
|
1588
1568
|
home: string,
|
|
1589
1569
|
runId: string,
|
|
@@ -1594,7 +1574,6 @@ export async function peekRoleRunRole(
|
|
|
1594
1574
|
return run?.role;
|
|
1595
1575
|
}
|
|
1596
1576
|
|
|
1597
|
-
|
|
1598
1577
|
export type LoadedResumablePublicRole = {
|
|
1599
1578
|
readonly admitted: AdmittedRoleInvocation;
|
|
1600
1579
|
readonly run: RoleRunRecord;
|
|
@@ -1793,7 +1772,7 @@ function admitResumedRole(loaded: {
|
|
|
1793
1772
|
try {
|
|
1794
1773
|
parsedRepository = parseCollectorRepository(repositoryDisplay);
|
|
1795
1774
|
} catch (error) {
|
|
1796
|
-
const detail =
|
|
1775
|
+
const detail = errorText(error);
|
|
1797
1776
|
throw new CliUsageError(detail, { cause: error });
|
|
1798
1777
|
}
|
|
1799
1778
|
if (parsedRepository.canonical !== repository) {
|
|
@@ -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;
|
|
@@ -26,10 +26,11 @@ import type {
|
|
|
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";
|
|
30
|
+
|
|
29
31
|
/** Env published by the parent activation so nested summons never re-derive root. */
|
|
30
32
|
export const AK_ROLE_PACKAGE_ROOT_ENV = "AK_ROLE_PACKAGE_ROOT" as const;
|
|
31
33
|
|
|
32
|
-
|
|
33
34
|
export type PublicSummonRole =
|
|
34
35
|
| "inspector"
|
|
35
36
|
| "notary"
|
|
@@ -591,7 +592,7 @@ export async function summonParallelReviewerLenses(options: {
|
|
|
591
592
|
if (error instanceof AggregateError) {
|
|
592
593
|
return [error.message, ...error.errors.map(describeFailure)].join("\n");
|
|
593
594
|
}
|
|
594
|
-
return
|
|
595
|
+
return errorText(error);
|
|
595
596
|
};
|
|
596
597
|
const failedResult = (error: unknown): PublicSummonResult => ({
|
|
597
598
|
exitCode: 1,
|
|
@@ -839,7 +840,7 @@ export async function summonGateOfficer(options: {
|
|
|
839
840
|
const correlationId = parentRunId;
|
|
840
841
|
const { isSafePositiveTicketNumber, readBoardTicketNumber } = await import("./run-ticket-number.ts");
|
|
841
842
|
const parentTicket = await readBoardTicketNumber(options.sourceRunDirectory);
|
|
842
|
-
const submittedTicket =
|
|
843
|
+
const submittedTicket = isRecord(options.submission)
|
|
843
844
|
? (options.submission as { ticketNumber?: unknown }).ticketNumber
|
|
844
845
|
: undefined;
|
|
845
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)
|