@akagilnc/pi-workflow-roles 0.1.5368 → 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 +719 -776
- 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 +721 -780
- 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 +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 +4 -3
- package/dist/public-cli/invocation.js +9 -8
- package/dist/public-cli/main.js +1531 -1567
- 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/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 +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/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 +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 +5 -3
- 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 +0 -1
- 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 +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
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
*/
|
|
8
8
|
import { Type } from "typebox";
|
|
9
9
|
|
|
10
|
+
import { isRecord } from "../unknown-value.ts";
|
|
10
11
|
import { openToolObject } from "../open-tool-schema.ts";
|
|
11
12
|
import { withTerminatingOutputDeclarations } from "./terminating-infrastructure.ts";
|
|
12
13
|
|
|
@@ -33,19 +34,18 @@ export type NavigatorAdvice = { readonly prose: string };
|
|
|
33
34
|
export function projectLawfulNavigatorOutput(value: unknown): NavigatorAdvice | undefined {
|
|
34
35
|
if (value === undefined || value === null) return undefined;
|
|
35
36
|
if (typeof value === "string") return { prose: value };
|
|
36
|
-
if (
|
|
37
|
-
|
|
38
|
-
if (
|
|
39
|
-
|
|
40
|
-
return { prose: typeof record.prose === "string" ? record.prose : String(record.prose) };
|
|
37
|
+
if (isRecord(value)) {
|
|
38
|
+
if (typeof value.prose === "string") return { prose: value.prose };
|
|
39
|
+
if (value.prose !== undefined && value.prose !== null) {
|
|
40
|
+
return { prose: typeof value.prose === "string" ? value.prose : String(value.prose) };
|
|
41
41
|
}
|
|
42
42
|
// Free-form object submission: present the whole body as prose when it has content.
|
|
43
|
-
const keys = Object.keys(
|
|
43
|
+
const keys = Object.keys(value);
|
|
44
44
|
if (keys.length === 0) return { prose: "" };
|
|
45
45
|
try {
|
|
46
|
-
return { prose: JSON.stringify(
|
|
46
|
+
return { prose: JSON.stringify(value) };
|
|
47
47
|
} catch {
|
|
48
|
-
return { prose: String(
|
|
48
|
+
return { prose: String(value) };
|
|
49
49
|
}
|
|
50
50
|
}
|
|
51
51
|
return { prose: String(value) };
|
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
*/
|
|
14
14
|
import { Type, type TSchema } from "typebox";
|
|
15
15
|
import type { CorrectableSubmissionError } from "../submission-correctable-error.ts";
|
|
16
|
+
import { isRecord } from "../unknown-value.ts";
|
|
16
17
|
|
|
17
18
|
export const INFRASTRUCTURE_FAILURE_DECLARATION_KEY =
|
|
18
19
|
"infrastructureFailure" as const;
|
|
@@ -94,26 +95,11 @@ type TerminatingInfrastructureHostActions<C> = {
|
|
|
94
95
|
function isInfrastructureFailureDeclaration(
|
|
95
96
|
parameters: unknown,
|
|
96
97
|
): boolean {
|
|
97
|
-
if (
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
return false;
|
|
103
|
-
}
|
|
104
|
-
const record = parameters as Record<string, unknown>;
|
|
105
|
-
if (!Object.hasOwn(record, INFRASTRUCTURE_FAILURE_DECLARATION_KEY)) return false;
|
|
106
|
-
const declaration = record[INFRASTRUCTURE_FAILURE_DECLARATION_KEY];
|
|
107
|
-
if (
|
|
108
|
-
declaration === null ||
|
|
109
|
-
typeof declaration !== "object" ||
|
|
110
|
-
Array.isArray(declaration)
|
|
111
|
-
) {
|
|
112
|
-
return false;
|
|
113
|
-
}
|
|
114
|
-
const diagnostic = (declaration as Record<string, unknown>)[
|
|
115
|
-
INFRASTRUCTURE_FAILURE_DIAGNOSTIC_KEY
|
|
116
|
-
];
|
|
98
|
+
if (!isRecord(parameters)) return false;
|
|
99
|
+
if (!Object.hasOwn(parameters, INFRASTRUCTURE_FAILURE_DECLARATION_KEY)) return false;
|
|
100
|
+
const declaration = parameters[INFRASTRUCTURE_FAILURE_DECLARATION_KEY];
|
|
101
|
+
if (!isRecord(declaration)) return false;
|
|
102
|
+
const diagnostic = declaration[INFRASTRUCTURE_FAILURE_DIAGNOSTIC_KEY];
|
|
117
103
|
return typeof diagnostic === "string" && diagnostic.trim().length > 0;
|
|
118
104
|
}
|
|
119
105
|
|
|
@@ -36,6 +36,8 @@ import {
|
|
|
36
36
|
type WorkerOutput,
|
|
37
37
|
} from "./worker-output.ts";
|
|
38
38
|
|
|
39
|
+
import { isRecord } from "../unknown-value.ts";
|
|
40
|
+
|
|
39
41
|
export {
|
|
40
42
|
CODER_OUTPUT_TOOL_NAME,
|
|
41
43
|
COLLECTOR_OUTPUT_TOOL,
|
|
@@ -114,7 +116,6 @@ export class AcceptedDetailsContractError extends CorrectableSubmissionError {
|
|
|
114
116
|
}
|
|
115
117
|
}
|
|
116
118
|
|
|
117
|
-
|
|
118
119
|
/**
|
|
119
120
|
* #836: status allowlist rejection deleted. Original object is the receipt.
|
|
120
121
|
* Callers that need a typed view may still cast; code must not bounce on status.
|
|
@@ -123,7 +124,7 @@ export function validateAcceptedDetails(
|
|
|
123
124
|
_toolName: TerminatingToolName,
|
|
124
125
|
details: unknown,
|
|
125
126
|
): AcceptedDetails {
|
|
126
|
-
if (
|
|
127
|
+
if (isRecord(details)) {
|
|
127
128
|
return details as AcceptedDetails;
|
|
128
129
|
}
|
|
129
130
|
// Non-object payload still records as empty object rather than rejecting.
|
|
@@ -178,18 +179,13 @@ export function deepEqual(a: unknown, b: unknown): boolean {
|
|
|
178
179
|
if (!Array.isArray(b) || a.length !== b.length) return false;
|
|
179
180
|
return a.every((item, index) => deepEqual(item, b[index]));
|
|
180
181
|
}
|
|
181
|
-
if (
|
|
182
|
-
if (
|
|
183
|
-
const aKeys = Object.keys(a
|
|
184
|
-
const bKeys = Object.keys(b
|
|
182
|
+
if (isRecord(a)) {
|
|
183
|
+
if (!isRecord(b)) return false;
|
|
184
|
+
const aKeys = Object.keys(a).sort();
|
|
185
|
+
const bKeys = Object.keys(b).sort();
|
|
185
186
|
if (aKeys.length !== bKeys.length) return false;
|
|
186
187
|
if (!aKeys.every((key, index) => key === bKeys[index])) return false;
|
|
187
|
-
return aKeys.every((key) =>
|
|
188
|
-
deepEqual(
|
|
189
|
-
(a as Record<string, unknown>)[key],
|
|
190
|
-
(b as Record<string, unknown>)[key],
|
|
191
|
-
)
|
|
192
|
-
);
|
|
188
|
+
return aKeys.every((key) => deepEqual(a[key], b[key]));
|
|
193
189
|
}
|
|
194
190
|
return false;
|
|
195
191
|
}
|
package/src/pi/adapter.ts
CHANGED
|
@@ -20,7 +20,6 @@ import { createRoleRuntimeExtension, type RoleRuntimeDependencies } from "../rol
|
|
|
20
20
|
import { renderAgentStartMaterials } from "../agent-start-materials.ts";
|
|
21
21
|
import { readUserDialogueStdin } from "../user-dialogue-stdin.ts";
|
|
22
22
|
|
|
23
|
-
|
|
24
23
|
export type PiRoleHostAdapter = RoleEnvelopeHost;
|
|
25
24
|
|
|
26
25
|
const piContexts = new WeakMap<HostContext, ExtensionContext>();
|
package/src/pi/role-turn-host.ts
CHANGED
|
@@ -26,7 +26,6 @@ import { applyEngineChildEnv, ENGINE_MODEL_FLAG_NAME, normalizeEngineName } from
|
|
|
26
26
|
import { projectActivationFlags } from "../role-activation-flags.ts";
|
|
27
27
|
import { encodeUserDialogueStdin } from "../user-dialogue-stdin.ts";
|
|
28
28
|
|
|
29
|
-
|
|
30
29
|
/** Package-relative Internal role entrypoint (ADR 0052; same path as public-cli registry). */
|
|
31
30
|
const INTERNAL_ROLE_ENTRYPOINT_RELATIVE = "extensions/role-runtime.ts";
|
|
32
31
|
|
|
@@ -41,6 +41,8 @@ import type {
|
|
|
41
41
|
} from "./invocation.ts";
|
|
42
42
|
import { presentControlledFailure, presentStructuralRejection } from "./settlement.ts";
|
|
43
43
|
|
|
44
|
+
import { errorText } from "../unknown-value.ts";
|
|
45
|
+
|
|
44
46
|
export type AnalystRunEnv = {
|
|
45
47
|
readonly home: string;
|
|
46
48
|
};
|
|
@@ -97,7 +99,7 @@ export async function buildAnalystIssueModeInputFromPublicArgv(
|
|
|
97
99
|
|
|
98
100
|
/**
|
|
99
101
|
* Attachment JSON → library AnalystSweepModeInput via the sole schema (#337).
|
|
100
|
-
* No parallel hand shape; rejects missing
|
|
102
|
+
* No parallel hand shape; rejects missing or wrong-type fields only.
|
|
101
103
|
*/
|
|
102
104
|
export function parseAnalystSweepModeInputFromJsonValue(
|
|
103
105
|
value: unknown,
|
|
@@ -141,7 +143,7 @@ export async function buildAnalystSweepModeInputFromAttachmentPaths(
|
|
|
141
143
|
try {
|
|
142
144
|
text = exactUtf8(bytes, "analyst sweep attachment");
|
|
143
145
|
} catch (error) {
|
|
144
|
-
const detail =
|
|
146
|
+
const detail = errorText(error);
|
|
145
147
|
throw new CliUsageError(detail, { cause: error });
|
|
146
148
|
}
|
|
147
149
|
|
|
@@ -42,6 +42,8 @@ import {
|
|
|
42
42
|
import type { CliIo } from "./cli-io.ts";
|
|
43
43
|
import { serializeThrownValue } from "../serialize-thrown-value.ts";
|
|
44
44
|
|
|
45
|
+
import { errorText, isEnoent } from "../unknown-value.ts";
|
|
46
|
+
|
|
45
47
|
const dummyIo: CliIo = { stdout: () => {}, stderr: () => {} };
|
|
46
48
|
|
|
47
49
|
/**
|
|
@@ -132,7 +134,7 @@ export class TurnDispatchedFailure extends Error {
|
|
|
132
134
|
constructor(cause: unknown) {
|
|
133
135
|
super(
|
|
134
136
|
`settlement failed after the host turn genuinely started: ${
|
|
135
|
-
|
|
137
|
+
errorText(cause)
|
|
136
138
|
}`,
|
|
137
139
|
{ cause },
|
|
138
140
|
);
|
|
@@ -164,7 +166,7 @@ export async function ensureRealArtifactsDirectory(runDirectory: string): Promis
|
|
|
164
166
|
throw new Error("run artifact retention: artifacts path is not a real directory");
|
|
165
167
|
}
|
|
166
168
|
} catch (error) {
|
|
167
|
-
if (!
|
|
169
|
+
if (!isEnoent(error)) throw error;
|
|
168
170
|
await mkdir(artifactsDir, { recursive: true });
|
|
169
171
|
const created = await lstat(artifactsDir);
|
|
170
172
|
if (created.isSymbolicLink() || !created.isDirectory()) {
|
|
@@ -174,15 +176,6 @@ export async function ensureRealArtifactsDirectory(runDirectory: string): Promis
|
|
|
174
176
|
return artifactsDir;
|
|
175
177
|
}
|
|
176
178
|
|
|
177
|
-
/** ENOENT identity shared with settlement.ts's hardened audit-artifact path. */
|
|
178
|
-
function isMissingPathError(error: unknown): boolean {
|
|
179
|
-
return (
|
|
180
|
-
error instanceof Error &&
|
|
181
|
-
"code" in error &&
|
|
182
|
-
(error as { code?: unknown }).code === "ENOENT"
|
|
183
|
-
);
|
|
184
|
-
}
|
|
185
|
-
|
|
186
179
|
/** Cycle- and bigint-safe JSON replacer so serialization itself cannot drop data. */
|
|
187
180
|
function jsonSafeReplacer(): (key: string, value: unknown) => unknown {
|
|
188
181
|
const seen = new WeakSet<object>();
|
package/src/public-cli/cli.ts
CHANGED
|
@@ -105,6 +105,8 @@ import {
|
|
|
105
105
|
} from "./settlement.ts";
|
|
106
106
|
import type { TerminalResult } from "./terminal.ts";
|
|
107
107
|
|
|
108
|
+
import { errorText } from "../unknown-value.ts";
|
|
109
|
+
|
|
108
110
|
export {
|
|
109
111
|
buildExplicitInternalActivationArgs,
|
|
110
112
|
resolveInternalRoleEntrypoint,
|
|
@@ -237,8 +239,6 @@ export type CliEnv = {
|
|
|
237
239
|
signal?: AbortSignal;
|
|
238
240
|
};
|
|
239
241
|
|
|
240
|
-
|
|
241
|
-
|
|
242
242
|
type RoleEnvironmentOptions = {
|
|
243
243
|
role: PublicCallableRole;
|
|
244
244
|
home: string;
|
|
@@ -542,7 +542,7 @@ function requireLegalEngineModel(model: string): string {
|
|
|
542
542
|
return assertLegalEngineModel(model);
|
|
543
543
|
} catch (error) {
|
|
544
544
|
throw new CliUsageError(
|
|
545
|
-
|
|
545
|
+
errorText(error),
|
|
546
546
|
{ cause: error },
|
|
547
547
|
);
|
|
548
548
|
}
|
|
@@ -553,7 +553,7 @@ function requireLegalEngineName(name: string): string {
|
|
|
553
553
|
return assertLegalEngineName(name);
|
|
554
554
|
} catch (error) {
|
|
555
555
|
throw new CliUsageError(
|
|
556
|
-
|
|
556
|
+
errorText(error),
|
|
557
557
|
{ cause: error },
|
|
558
558
|
);
|
|
559
559
|
}
|
|
@@ -585,7 +585,7 @@ function loadAndValidateConfig(
|
|
|
585
585
|
validatePublicCliConfigAxes(config, packageRoot);
|
|
586
586
|
} catch (error) {
|
|
587
587
|
throw new CliUsageError(
|
|
588
|
-
|
|
588
|
+
errorText(error),
|
|
589
589
|
{ cause: error },
|
|
590
590
|
);
|
|
591
591
|
}
|
|
@@ -917,7 +917,7 @@ async function runConfigCommand(
|
|
|
917
917
|
try {
|
|
918
918
|
config = setPersistentSeatHost(config, seat, unset ? undefined : args[2]!);
|
|
919
919
|
} catch (error) {
|
|
920
|
-
throw new CliUsageError(
|
|
920
|
+
throw new CliUsageError(errorText(error), { cause: error });
|
|
921
921
|
}
|
|
922
922
|
await savePublicCliConfig(config, home);
|
|
923
923
|
io.stdout(renderConfig(config, home));
|
|
@@ -941,7 +941,7 @@ async function runConfigCommand(
|
|
|
941
941
|
config = setPersistentSeatEngine(config, seat, name, engineModel);
|
|
942
942
|
} catch (error) {
|
|
943
943
|
throw new CliUsageError(
|
|
944
|
-
|
|
944
|
+
errorText(error),
|
|
945
945
|
{ cause: error },
|
|
946
946
|
);
|
|
947
947
|
}
|
|
@@ -963,7 +963,7 @@ async function runConfigCommand(
|
|
|
963
963
|
config = setPersistentSeatEngine(config, seat, undefined);
|
|
964
964
|
} catch (error) {
|
|
965
965
|
throw new CliUsageError(
|
|
966
|
-
|
|
966
|
+
errorText(error),
|
|
967
967
|
{ cause: error },
|
|
968
968
|
);
|
|
969
969
|
}
|
|
@@ -987,7 +987,7 @@ async function runConfigCommand(
|
|
|
987
987
|
config = setPersistentSeatEngineModel(config, seat, model);
|
|
988
988
|
} catch (error) {
|
|
989
989
|
throw new CliUsageError(
|
|
990
|
-
|
|
990
|
+
errorText(error),
|
|
991
991
|
{ cause: error },
|
|
992
992
|
);
|
|
993
993
|
}
|
|
@@ -1009,7 +1009,7 @@ async function runConfigCommand(
|
|
|
1009
1009
|
config = setPersistentSeatEngineModel(config, seat, undefined);
|
|
1010
1010
|
} catch (error) {
|
|
1011
1011
|
throw new CliUsageError(
|
|
1012
|
-
|
|
1012
|
+
errorText(error),
|
|
1013
1013
|
{ cause: error },
|
|
1014
1014
|
);
|
|
1015
1015
|
}
|
package/src/public-cli/config.ts
CHANGED
|
@@ -27,6 +27,7 @@ import {
|
|
|
27
27
|
type PublicConfigurableSeat,
|
|
28
28
|
type PublicThinkingLevel,
|
|
29
29
|
} from "./registry.ts";
|
|
30
|
+
import { isEnoent, isRecord } from "../unknown-value.ts";
|
|
30
31
|
|
|
31
32
|
/** Province officers that may carry a persistent model override (#453). Registry order. */
|
|
32
33
|
type ProvinceConfigRole = Extract<
|
|
@@ -134,13 +135,7 @@ export async function loadPublicCliConfig(
|
|
|
134
135
|
const raw = await readFile(path, "utf8");
|
|
135
136
|
return parsePublicCliConfig(JSON.parse(raw));
|
|
136
137
|
} catch (error) {
|
|
137
|
-
if (
|
|
138
|
-
error instanceof Error &&
|
|
139
|
-
"code" in error &&
|
|
140
|
-
(error as NodeJS.ErrnoException).code === "ENOENT"
|
|
141
|
-
) {
|
|
142
|
-
return { seats: {} };
|
|
143
|
-
}
|
|
138
|
+
if (isEnoent(error)) return { seats: {} };
|
|
144
139
|
throw error;
|
|
145
140
|
}
|
|
146
141
|
}
|
|
@@ -481,7 +476,7 @@ function serializePublicCliConfig(config: PublicCliConfig): {
|
|
|
481
476
|
}
|
|
482
477
|
|
|
483
478
|
function parsePublicCliConfig(value: unknown): PublicCliConfig {
|
|
484
|
-
if (
|
|
479
|
+
if (!isRecord(value)) {
|
|
485
480
|
throw new Error("public CLI config must be an object");
|
|
486
481
|
}
|
|
487
482
|
const record = value as {
|
|
@@ -500,11 +495,7 @@ function parsePublicCliConfig(value: unknown): PublicCliConfig {
|
|
|
500
495
|
// disk-shaped seats map and a memory-shaped bucket both survive.
|
|
501
496
|
const unknownSeats: Record<string, unknown> = {};
|
|
502
497
|
if (record.unknownSeats !== undefined) {
|
|
503
|
-
if (
|
|
504
|
-
record.unknownSeats === null ||
|
|
505
|
-
typeof record.unknownSeats !== "object" ||
|
|
506
|
-
Array.isArray(record.unknownSeats)
|
|
507
|
-
) {
|
|
498
|
+
if (!isRecord(record.unknownSeats)) {
|
|
508
499
|
throw new Error("public CLI config.unknownSeats must be an object");
|
|
509
500
|
}
|
|
510
501
|
Object.assign(unknownSeats, record.unknownSeats as Record<string, unknown>);
|
|
@@ -517,11 +508,7 @@ function parsePublicCliConfig(value: unknown): PublicCliConfig {
|
|
|
517
508
|
if (record.seats === undefined) {
|
|
518
509
|
return withOpaque({});
|
|
519
510
|
}
|
|
520
|
-
if (
|
|
521
|
-
record.seats === null ||
|
|
522
|
-
typeof record.seats !== "object" ||
|
|
523
|
-
Array.isArray(record.seats)
|
|
524
|
-
) {
|
|
511
|
+
if (!isRecord(record.seats)) {
|
|
525
512
|
throw new Error("public CLI config.seats must be an object");
|
|
526
513
|
}
|
|
527
514
|
const seats: PublicCliConfig["seats"] = {};
|
|
@@ -542,7 +529,7 @@ function parsePublicCliConfig(value: unknown): PublicCliConfig {
|
|
|
542
529
|
}
|
|
543
530
|
|
|
544
531
|
function parseSeatModelConfig(value: unknown, seat: string): PersistentSeatConfig {
|
|
545
|
-
if (
|
|
532
|
+
if (!isRecord(value)) {
|
|
546
533
|
throw new Error(`config seat ${seat} must be an object`);
|
|
547
534
|
}
|
|
548
535
|
const raw = value as Record<string, unknown>;
|
|
@@ -825,7 +812,7 @@ export function listRolesForDisplay(
|
|
|
825
812
|
export function credentialProvidersFromAuthData(
|
|
826
813
|
data: unknown,
|
|
827
814
|
): CredentialProviders {
|
|
828
|
-
if (
|
|
815
|
+
if (!isRecord(data)) {
|
|
829
816
|
return { "openai-codex": false, xai: false };
|
|
830
817
|
}
|
|
831
818
|
const record = data as Record<string, unknown>;
|
|
@@ -850,13 +837,7 @@ export async function loadCredentialProviders(
|
|
|
850
837
|
const raw = await readFile(join(agentDir, "auth.json"), "utf8");
|
|
851
838
|
return credentialProvidersFromAuthData(JSON.parse(raw));
|
|
852
839
|
} catch (error) {
|
|
853
|
-
if (
|
|
854
|
-
error instanceof Error &&
|
|
855
|
-
"code" in error &&
|
|
856
|
-
(error as NodeJS.ErrnoException).code === "ENOENT"
|
|
857
|
-
) {
|
|
858
|
-
return { "openai-codex": false, xai: false };
|
|
859
|
-
}
|
|
840
|
+
if (isEnoent(error)) return { "openai-codex": false, xai: false };
|
|
860
841
|
throw error;
|
|
861
842
|
}
|
|
862
843
|
}
|
|
@@ -9,6 +9,8 @@ import type { PostAdmissionEnv } from "./post-admission.ts";
|
|
|
9
9
|
import type { CliIo } from "./cli-io.ts";
|
|
10
10
|
import type { TerminalRoleOutcome } from "./terminal.ts";
|
|
11
11
|
|
|
12
|
+
import { isRecord } from "../unknown-value.ts";
|
|
13
|
+
|
|
12
14
|
export type CountersignRunEnv = PostAdmissionEnv & {
|
|
13
15
|
principalAuthority: DurablePrincipalAuthority;
|
|
14
16
|
createRunId?: () => string;
|
|
@@ -51,10 +53,6 @@ export type CourtDiaristInvocationResult = {
|
|
|
51
53
|
readonly failedWithoutEscalate?: { readonly diagnostic: string };
|
|
52
54
|
};
|
|
53
55
|
|
|
54
|
-
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
55
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
56
|
-
}
|
|
57
|
-
|
|
58
56
|
function isEscalatePayload(payload: unknown): boolean {
|
|
59
57
|
if (!isRecord(payload)) return false;
|
|
60
58
|
return (
|
|
@@ -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;
|
|
@@ -101,6 +101,8 @@ import {
|
|
|
101
101
|
latestPayloadEscalated,
|
|
102
102
|
type CountersignRunEnv,
|
|
103
103
|
} from "./countersign-run.ts";
|
|
104
|
+
import { isRecord, errorText } from "../unknown-value.ts";
|
|
105
|
+
|
|
104
106
|
export type InstructionSeatRunEnv = PostAdmissionEnv & Pick<
|
|
105
107
|
CountersignRunEnv,
|
|
106
108
|
"reviewReask" | "gateReviewInstruction" | "parentRunPath"
|
|
@@ -159,7 +161,7 @@ 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 =
|
|
164
|
+
const status = isRecord(payload)
|
|
163
165
|
? (payload as Record<string, unknown>).status
|
|
164
166
|
: undefined;
|
|
165
167
|
return typeof status === "string" && route.statuses.has(status)
|
|
@@ -659,7 +661,7 @@ export async function runPublicInstructionSeat(
|
|
|
659
661
|
auditorSource = resolved.runDirectory;
|
|
660
662
|
auditorTicket = await readBoardTicketNumber(resolved.runDirectory);
|
|
661
663
|
} catch (error) {
|
|
662
|
-
presentStructuralRejection(new CliUsageError(
|
|
664
|
+
presentStructuralRejection(new CliUsageError(errorText(error)), io);
|
|
663
665
|
return { exitCode: 2 };
|
|
664
666
|
}
|
|
665
667
|
if (auditorSource === undefined) return { exitCode: 2 };
|
|
@@ -997,7 +999,7 @@ async function auditSubmittedRole(
|
|
|
997
999
|
|| turn.terminal?.roleOutcome.kind !== "accepted") return turn;
|
|
998
1000
|
const accepted = turn.terminal.roleOutcome.payloads?.at(-1);
|
|
999
1001
|
if (accepted === undefined) throw new Error("accepted submission has no payload");
|
|
1000
|
-
const record =
|
|
1002
|
+
const record = isRecord(accepted)
|
|
1001
1003
|
? accepted as Record<string, unknown> : undefined;
|
|
1002
1004
|
const status = admitted.role === "secretariat" ? record?.secretariatStatus : record?.status;
|
|
1003
1005
|
if (admitted.role === "secretariat" && status !== "converged" && status !== "escalate") {
|
|
@@ -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
|
}
|