prismalens 0.0.1
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/LICENSE +201 -0
- package/NOTICE +5 -0
- package/README.md +312 -0
- package/dist/bin/prismalens.d.ts +3 -0
- package/dist/bin/prismalens.d.ts.map +1 -0
- package/dist/bin/prismalens.js +32 -0
- package/dist/bin/prismalens.js.map +1 -0
- package/dist/src/cli/doctor.d.ts +3 -0
- package/dist/src/cli/doctor.d.ts.map +1 -0
- package/dist/src/cli/doctor.js +156 -0
- package/dist/src/cli/doctor.js.map +1 -0
- package/dist/src/cli/init.d.ts +3 -0
- package/dist/src/cli/init.d.ts.map +1 -0
- package/dist/src/cli/init.js +85 -0
- package/dist/src/cli/init.js.map +1 -0
- package/dist/src/cli/investigate.d.ts +101 -0
- package/dist/src/cli/investigate.d.ts.map +1 -0
- package/dist/src/cli/investigate.js +452 -0
- package/dist/src/cli/investigate.js.map +1 -0
- package/dist/src/cli/serve.d.ts +3 -0
- package/dist/src/cli/serve.d.ts.map +1 -0
- package/dist/src/cli/serve.js +26 -0
- package/dist/src/cli/serve.js.map +1 -0
- package/dist/src/config/loader.d.ts +22 -0
- package/dist/src/config/loader.d.ts.map +1 -0
- package/dist/src/config/loader.js +155 -0
- package/dist/src/config/loader.js.map +1 -0
- package/dist/src/config/schema.d.ts +336 -0
- package/dist/src/config/schema.d.ts.map +1 -0
- package/dist/src/config/schema.js +160 -0
- package/dist/src/config/schema.js.map +1 -0
- package/dist/src/core/detect-repo.d.ts +4 -0
- package/dist/src/core/detect-repo.d.ts.map +1 -0
- package/dist/src/core/detect-repo.js +28 -0
- package/dist/src/core/detect-repo.js.map +1 -0
- package/dist/src/core/file-session-store.d.ts +10 -0
- package/dist/src/core/file-session-store.d.ts.map +1 -0
- package/dist/src/core/file-session-store.js +34 -0
- package/dist/src/core/file-session-store.js.map +1 -0
- package/dist/src/core/parse-stdin.d.ts +2 -0
- package/dist/src/core/parse-stdin.d.ts.map +1 -0
- package/dist/src/core/parse-stdin.js +30 -0
- package/dist/src/core/parse-stdin.js.map +1 -0
- package/dist/src/core/run-investigation.d.ts +42 -0
- package/dist/src/core/run-investigation.d.ts.map +1 -0
- package/dist/src/core/run-investigation.js +144 -0
- package/dist/src/core/run-investigation.js.map +1 -0
- package/dist/src/core/session.d.ts +42 -0
- package/dist/src/core/session.d.ts.map +1 -0
- package/dist/src/core/session.js +168 -0
- package/dist/src/core/session.js.map +1 -0
- package/dist/src/jsonrpc/server.d.ts +15 -0
- package/dist/src/jsonrpc/server.d.ts.map +1 -0
- package/dist/src/jsonrpc/server.js +244 -0
- package/dist/src/jsonrpc/server.js.map +1 -0
- package/dist/src/jsonrpc/types.d.ts +12 -0
- package/dist/src/jsonrpc/types.d.ts.map +1 -0
- package/dist/src/jsonrpc/types.js +4 -0
- package/dist/src/jsonrpc/types.js.map +1 -0
- package/dist/src/version.d.ts +8 -0
- package/dist/src/version.d.ts.map +1 -0
- package/dist/src/version.js +27 -0
- package/dist/src/version.js.map +1 -0
- package/package.json +61 -0
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
// Copyright 2026 Sumit Patel
|
|
3
|
+
/**
|
|
4
|
+
* Config loader (ADR-0010/0014).
|
|
5
|
+
*
|
|
6
|
+
* Resolution order (later overrides earlier — deep-merge; arrays replace):
|
|
7
|
+
* 1. Built-in defaults (Zod `.default()`)
|
|
8
|
+
* 2. User layer: ~/.config/prismalens/config.yaml (the XDG config dir; BYO-key
|
|
9
|
+
* creds live in env per ADR-0006, never here)
|
|
10
|
+
* 3. Project layer: the explicit `--config` path, else the nearest
|
|
11
|
+
* `prismalens.config.yaml` found by walking UP from cwd to the root
|
|
12
|
+
* 4. Project-local: `prismalens.config.local.yaml` beside the project config — a
|
|
13
|
+
* gitignored per-checkout override
|
|
14
|
+
* 5. CLI flag overrides
|
|
15
|
+
*
|
|
16
|
+
* `${VAR}` patterns in string values are interpolated from the environment (throws
|
|
17
|
+
* on an unset var), then the merged object is validated by the schema.
|
|
18
|
+
*
|
|
19
|
+
* Deferred ADR-0014 layers (pulled in with their consumers, not speculatively):
|
|
20
|
+
* - a curated env-overlay layer — today `${VAR}` interpolation already covers env
|
|
21
|
+
* access from within the config;
|
|
22
|
+
* - the reserved managed layer — there is no managed config source in the
|
|
23
|
+
* local-first OSS build (it belongs to the cloud tier);
|
|
24
|
+
* - the permission allow/deny list UNION (deny-wins) — coupled to the tool-seam
|
|
25
|
+
* that enforces it (its own slice), so it lands there, not in the merge.
|
|
26
|
+
*/
|
|
27
|
+
import { existsSync } from "node:fs";
|
|
28
|
+
import { readFile } from "node:fs/promises";
|
|
29
|
+
import { dirname, join, parse as parsePath, resolve } from "node:path";
|
|
30
|
+
import envPaths from "env-paths";
|
|
31
|
+
import { parse as parseYaml } from "yaml";
|
|
32
|
+
import { PlConfigSchema } from "./schema.js";
|
|
33
|
+
const PROJECT_CONFIG_FILENAME = "prismalens.config.yaml";
|
|
34
|
+
const PROJECT_LOCAL_CONFIG_FILENAME = "prismalens.config.local.yaml";
|
|
35
|
+
const USER_CONFIG_FILENAME = "config.yaml";
|
|
36
|
+
/** Find the nearest project config by walking up from `cwd` to the filesystem root. */
|
|
37
|
+
export function findConfigFile(cwd = process.cwd()) {
|
|
38
|
+
let dir = resolve(cwd);
|
|
39
|
+
const { root } = parsePath(dir);
|
|
40
|
+
for (;;) {
|
|
41
|
+
const candidate = join(dir, PROJECT_CONFIG_FILENAME);
|
|
42
|
+
if (existsSync(candidate))
|
|
43
|
+
return candidate;
|
|
44
|
+
if (dir === root)
|
|
45
|
+
return undefined;
|
|
46
|
+
dir = dirname(dir);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
/** The user-global config in the XDG config dir (~/.config/prismalens/config.yaml). */
|
|
50
|
+
function userConfigFile() {
|
|
51
|
+
const candidate = join(envPaths("prismalens", { suffix: "" }).config, USER_CONFIG_FILENAME);
|
|
52
|
+
return existsSync(candidate) ? candidate : undefined;
|
|
53
|
+
}
|
|
54
|
+
/** The gitignored project-local override beside the project config (else in cwd). */
|
|
55
|
+
function projectLocalConfigFile(projectFile, cwd) {
|
|
56
|
+
const dir = projectFile ? dirname(projectFile) : resolve(cwd);
|
|
57
|
+
const candidate = join(dir, PROJECT_LOCAL_CONFIG_FILENAME);
|
|
58
|
+
return existsSync(candidate) ? candidate : undefined;
|
|
59
|
+
}
|
|
60
|
+
async function readYamlFile(filePath) {
|
|
61
|
+
try {
|
|
62
|
+
const content = await readFile(filePath, "utf-8");
|
|
63
|
+
return parseYaml(content) ?? {};
|
|
64
|
+
}
|
|
65
|
+
catch (err) {
|
|
66
|
+
if (err.code === "ENOENT")
|
|
67
|
+
return {};
|
|
68
|
+
throw err;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
const ENV_VAR_PATTERN = /\$\{([^}]+)\}/g;
|
|
72
|
+
/** Replace `${VAR}` in every string value (recursively). Throws on an unset var. */
|
|
73
|
+
function interpolateDeep(value) {
|
|
74
|
+
if (typeof value === "string") {
|
|
75
|
+
return value.replace(ENV_VAR_PATTERN, (_, name) => {
|
|
76
|
+
const v = process.env[name];
|
|
77
|
+
if (v === undefined) {
|
|
78
|
+
throw new Error(`Config references unset environment variable "${name}" (as \${${name}})`);
|
|
79
|
+
}
|
|
80
|
+
return v;
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
if (Array.isArray(value))
|
|
84
|
+
return value.map(interpolateDeep);
|
|
85
|
+
if (value !== null && typeof value === "object") {
|
|
86
|
+
const out = {};
|
|
87
|
+
for (const [k, v] of Object.entries(value))
|
|
88
|
+
out[k] = interpolateDeep(v);
|
|
89
|
+
return out;
|
|
90
|
+
}
|
|
91
|
+
return value;
|
|
92
|
+
}
|
|
93
|
+
function isObject(v) {
|
|
94
|
+
return v !== null && typeof v === "object" && !Array.isArray(v);
|
|
95
|
+
}
|
|
96
|
+
/** Deep-merge `source` over `target`. Arrays replace; objects merge recursively. */
|
|
97
|
+
function deepMerge(target, source) {
|
|
98
|
+
const out = { ...target };
|
|
99
|
+
for (const [k, sv] of Object.entries(source)) {
|
|
100
|
+
const tv = out[k];
|
|
101
|
+
out[k] = isObject(sv) && isObject(tv) ? deepMerge(tv, sv) : sv;
|
|
102
|
+
}
|
|
103
|
+
return out;
|
|
104
|
+
}
|
|
105
|
+
function applyCliOverrides(config, o) {
|
|
106
|
+
const patch = {};
|
|
107
|
+
const agent = {};
|
|
108
|
+
if (o.agent !== undefined)
|
|
109
|
+
agent.default = o.agent;
|
|
110
|
+
if (o.model !== undefined)
|
|
111
|
+
agent.model = o.model;
|
|
112
|
+
if (Object.keys(agent).length > 0)
|
|
113
|
+
patch.agent = agent;
|
|
114
|
+
const telemetry = {};
|
|
115
|
+
if (o.prometheusUrl !== undefined)
|
|
116
|
+
telemetry.prometheusUrl = o.prometheusUrl;
|
|
117
|
+
if (o.alertmanagerUrl !== undefined)
|
|
118
|
+
telemetry.alertmanagerUrl = o.alertmanagerUrl;
|
|
119
|
+
if (o.apiUrl !== undefined)
|
|
120
|
+
telemetry.apiUrl = o.apiUrl;
|
|
121
|
+
if (Object.keys(telemetry).length > 0)
|
|
122
|
+
patch.telemetry = telemetry;
|
|
123
|
+
return deepMerge(config, patch);
|
|
124
|
+
}
|
|
125
|
+
/** Load, merge, interpolate, and validate the config. Result is frozen. */
|
|
126
|
+
export async function loadConfig(options = {}) {
|
|
127
|
+
const cwd = options.cwd ?? process.cwd();
|
|
128
|
+
const userFile = userConfigFile();
|
|
129
|
+
const projectFile = options.configPath
|
|
130
|
+
? resolve(options.configPath)
|
|
131
|
+
: findConfigFile(cwd);
|
|
132
|
+
const projectLocalFile = projectLocalConfigFile(projectFile, cwd);
|
|
133
|
+
let merged = {};
|
|
134
|
+
if (userFile)
|
|
135
|
+
merged = deepMerge(merged, await readYamlFile(userFile));
|
|
136
|
+
if (projectFile)
|
|
137
|
+
merged = deepMerge(merged, await readYamlFile(projectFile));
|
|
138
|
+
if (projectLocalFile && projectLocalFile !== projectFile) {
|
|
139
|
+
merged = deepMerge(merged, await readYamlFile(projectLocalFile));
|
|
140
|
+
}
|
|
141
|
+
if (options.cliOverrides) {
|
|
142
|
+
merged = applyCliOverrides(merged, options.cliOverrides);
|
|
143
|
+
}
|
|
144
|
+
const interpolated = interpolateDeep(merged);
|
|
145
|
+
let config;
|
|
146
|
+
try {
|
|
147
|
+
config = PlConfigSchema.parse(interpolated);
|
|
148
|
+
}
|
|
149
|
+
catch (err) {
|
|
150
|
+
const detail = err instanceof Error ? err.message : String(err);
|
|
151
|
+
throw new Error(`Invalid PrismaLens configuration: ${detail}`);
|
|
152
|
+
}
|
|
153
|
+
return Object.freeze(config);
|
|
154
|
+
}
|
|
155
|
+
//# sourceMappingURL=loader.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"loader.js","sourceRoot":"","sources":["../../../src/config/loader.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,336 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
/**
|
|
3
|
+
* The single posture dial (ADR-0017) — prismalens does not build a permission
|
|
4
|
+
* policy engine; it exposes this one dial and translates it to each harness's
|
|
5
|
+
* native config. Defaults to the safest posture, `read-only`.
|
|
6
|
+
*/
|
|
7
|
+
export declare const PermissionConfigSchema: z.ZodObject<{
|
|
8
|
+
mode: z.ZodDefault<z.ZodEnum<["read-only", "supervised", "auto", "dangerous"]>>;
|
|
9
|
+
}, "strip", z.ZodTypeAny, {
|
|
10
|
+
mode: "read-only" | "supervised" | "auto" | "dangerous";
|
|
11
|
+
}, {
|
|
12
|
+
mode?: "read-only" | "supervised" | "auto" | "dangerous" | undefined;
|
|
13
|
+
}>;
|
|
14
|
+
/**
|
|
15
|
+
* Arbitrary harness-native passthrough (ADR-0017) — e.g. Agent SDK query options
|
|
16
|
+
* for `claude-code`, or `args` (extra CLI args) for `deepagents`. Kept untyped
|
|
17
|
+
* here (per-harness runners narrow it); prismalens does not validate the shape,
|
|
18
|
+
* it defers to the harness.
|
|
19
|
+
*/
|
|
20
|
+
export declare const HarnessNativeConfigSchema: z.ZodObject<{
|
|
21
|
+
native: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
22
|
+
}, "strip", z.ZodTypeAny, {
|
|
23
|
+
native?: Record<string, unknown> | undefined;
|
|
24
|
+
}, {
|
|
25
|
+
native?: Record<string, unknown> | undefined;
|
|
26
|
+
}>;
|
|
27
|
+
/**
|
|
28
|
+
* Best-effort resource caps for the sandboxed harness run (ADR-0020: "resource
|
|
29
|
+
* limits are part of the contract"). All optional with NO defaults — an unset knob
|
|
30
|
+
* means "no cap", never a value that would lie about being enforced. What actually
|
|
31
|
+
* takes effect is provider-dependent (the `process` floor enforces only
|
|
32
|
+
* `wall_clock_ms`; `srt` adds memory/cpu when `systemd-run` is present).
|
|
33
|
+
*/
|
|
34
|
+
export declare const AgentLimitsConfigSchema: z.ZodObject<{
|
|
35
|
+
/** Wall-clock deadline (ms) — enforced by every sandbox provider. */
|
|
36
|
+
wall_clock_ms: z.ZodOptional<z.ZodNumber>;
|
|
37
|
+
/** Memory ceiling (MB) — best-effort (srt+systemd-run only). */
|
|
38
|
+
memory_mb: z.ZodOptional<z.ZodNumber>;
|
|
39
|
+
/** CPU quota (whole/fractional cores) — best-effort (srt+systemd-run only). */
|
|
40
|
+
cpu_cores: z.ZodOptional<z.ZodNumber>;
|
|
41
|
+
}, "strip", z.ZodTypeAny, {
|
|
42
|
+
wall_clock_ms?: number | undefined;
|
|
43
|
+
memory_mb?: number | undefined;
|
|
44
|
+
cpu_cores?: number | undefined;
|
|
45
|
+
}, {
|
|
46
|
+
wall_clock_ms?: number | undefined;
|
|
47
|
+
memory_mb?: number | undefined;
|
|
48
|
+
cpu_cores?: number | undefined;
|
|
49
|
+
}>;
|
|
50
|
+
/** Tier-2 harness backend the supervisor rents (ADR-0008). */
|
|
51
|
+
export declare const AgentConfigSchema: z.ZodObject<{
|
|
52
|
+
default: z.ZodDefault<z.ZodEnum<["deepagents", "claude-code", "codex"]>>;
|
|
53
|
+
/**
|
|
54
|
+
* BARE model id (e.g. "gpt-oss:120b") — the chosen harness applies its own
|
|
55
|
+
* provider prefix (ADR-0017: deepagents prepends "openai:"; Claude Code takes it
|
|
56
|
+
* bare). Also reused as the Tier-1 reduce model id. Omit to let the harness pick
|
|
57
|
+
* its own default.
|
|
58
|
+
*/
|
|
59
|
+
model: z.ZodOptional<z.ZodString>;
|
|
60
|
+
/** The posture dial (ADR-0017). Defaults to `read-only`. */
|
|
61
|
+
permissions: z.ZodEffects<z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>, {
|
|
62
|
+
mode: "read-only" | "supervised" | "auto" | "dangerous";
|
|
63
|
+
}, Record<string, unknown> | undefined>;
|
|
64
|
+
/**
|
|
65
|
+
* The isolation boundary the harness runs in (ADR-0020): `process` (the always-on
|
|
66
|
+
* cooperative floor), `srt` (enforced OS boundary), or `auto` (srt WHEN its egress
|
|
67
|
+
* bridge is healthy — the self-check, B.1.1 — else the floor; the degrade is honest,
|
|
68
|
+
* never silent). Defaults to `auto`: honest precisely BECAUSE of the self-check, which
|
|
69
|
+
* is what makes it safe to prefer the enforced boundary by default.
|
|
70
|
+
*/
|
|
71
|
+
sandbox: z.ZodDefault<z.ZodEnum<["auto", "process", "srt", "e2b"]>>;
|
|
72
|
+
/**
|
|
73
|
+
* Best-effort resource caps for the sandboxed harness (ADR-0020). Optional; an
|
|
74
|
+
* omitted section means "no caps" (the object defaults to `{}` after parse).
|
|
75
|
+
*/
|
|
76
|
+
limits: z.ZodEffects<z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>, {
|
|
77
|
+
wall_clock_ms?: number | undefined;
|
|
78
|
+
memory_mb?: number | undefined;
|
|
79
|
+
cpu_cores?: number | undefined;
|
|
80
|
+
}, Record<string, unknown> | undefined>;
|
|
81
|
+
/**
|
|
82
|
+
* Per-alert fan-out cap (ADR-0016 decision 2): the max branches the supervisor
|
|
83
|
+
* runs when a context carries multiple alerts. Optional — omitted ⇒ the engine
|
|
84
|
+
* default (3). A single-alert run always uses one branch regardless.
|
|
85
|
+
*/
|
|
86
|
+
max_branches: z.ZodOptional<z.ZodNumber>;
|
|
87
|
+
}, "strip", z.ZodTypeAny, {
|
|
88
|
+
default: "deepagents" | "claude-code" | "codex";
|
|
89
|
+
permissions: {
|
|
90
|
+
mode: "read-only" | "supervised" | "auto" | "dangerous";
|
|
91
|
+
};
|
|
92
|
+
sandbox: "auto" | "process" | "srt" | "e2b";
|
|
93
|
+
limits: {
|
|
94
|
+
wall_clock_ms?: number | undefined;
|
|
95
|
+
memory_mb?: number | undefined;
|
|
96
|
+
cpu_cores?: number | undefined;
|
|
97
|
+
};
|
|
98
|
+
model?: string | undefined;
|
|
99
|
+
max_branches?: number | undefined;
|
|
100
|
+
}, {
|
|
101
|
+
default?: "deepagents" | "claude-code" | "codex" | undefined;
|
|
102
|
+
model?: string | undefined;
|
|
103
|
+
permissions?: Record<string, unknown> | undefined;
|
|
104
|
+
sandbox?: "auto" | "process" | "srt" | "e2b" | undefined;
|
|
105
|
+
limits?: Record<string, unknown> | undefined;
|
|
106
|
+
max_branches?: number | undefined;
|
|
107
|
+
}>;
|
|
108
|
+
export declare const WorkspaceConfigSchema: z.ZodObject<{
|
|
109
|
+
base_dir: z.ZodDefault<z.ZodString>;
|
|
110
|
+
}, "strip", z.ZodTypeAny, {
|
|
111
|
+
base_dir: string;
|
|
112
|
+
}, {
|
|
113
|
+
base_dir?: string | undefined;
|
|
114
|
+
}>;
|
|
115
|
+
/**
|
|
116
|
+
* Read-only telemetry + app endpoints the harness may query. Mirrors the engine's
|
|
117
|
+
* TelemetryEndpoints (camelCase) so a loaded config can be handed straight to
|
|
118
|
+
* `InvestigateOptions.telemetry`. All optional here — resolved/overridden per run.
|
|
119
|
+
*/
|
|
120
|
+
export declare const TelemetryConfigSchema: z.ZodObject<{
|
|
121
|
+
prometheusUrl: z.ZodOptional<z.ZodString>;
|
|
122
|
+
alertmanagerUrl: z.ZodOptional<z.ZodString>;
|
|
123
|
+
apiUrl: z.ZodOptional<z.ZodString>;
|
|
124
|
+
}, "strip", z.ZodTypeAny, {
|
|
125
|
+
prometheusUrl?: string | undefined;
|
|
126
|
+
alertmanagerUrl?: string | undefined;
|
|
127
|
+
apiUrl?: string | undefined;
|
|
128
|
+
}, {
|
|
129
|
+
prometheusUrl?: string | undefined;
|
|
130
|
+
alertmanagerUrl?: string | undefined;
|
|
131
|
+
apiUrl?: string | undefined;
|
|
132
|
+
}>;
|
|
133
|
+
/**
|
|
134
|
+
* A service in the catalog (ADR-0015). The CLI maps the matched entry into the
|
|
135
|
+
* investigation context's `service` field so a single-alert run carries the affected
|
|
136
|
+
* service's repo/tier/deps, not just the bare alert.
|
|
137
|
+
*/
|
|
138
|
+
export declare const ServiceConfigSchema: z.ZodObject<{
|
|
139
|
+
tier: z.ZodOptional<z.ZodString>;
|
|
140
|
+
/** owner/name slug or a local path the harness reads. */
|
|
141
|
+
repo: z.ZodOptional<z.ZodString>;
|
|
142
|
+
/** Direct dependency service names (blast-radius seed). */
|
|
143
|
+
depends_on: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
|
|
144
|
+
}, "strip", z.ZodTypeAny, {
|
|
145
|
+
depends_on: string[];
|
|
146
|
+
tier?: string | undefined;
|
|
147
|
+
repo?: string | undefined;
|
|
148
|
+
}, {
|
|
149
|
+
tier?: string | undefined;
|
|
150
|
+
repo?: string | undefined;
|
|
151
|
+
depends_on?: string[] | undefined;
|
|
152
|
+
}>;
|
|
153
|
+
/** A read-only log-query system the harness may curl (Loki/Elasticsearch/…). */
|
|
154
|
+
export declare const LogSourceConfigSchema: z.ZodObject<{
|
|
155
|
+
kind: z.ZodOptional<z.ZodString>;
|
|
156
|
+
url: z.ZodOptional<z.ZodString>;
|
|
157
|
+
}, "strip", z.ZodTypeAny, {
|
|
158
|
+
kind?: string | undefined;
|
|
159
|
+
url?: string | undefined;
|
|
160
|
+
}, {
|
|
161
|
+
kind?: string | undefined;
|
|
162
|
+
url?: string | undefined;
|
|
163
|
+
}>;
|
|
164
|
+
/** Free-form `{ source: { key: value } }` connection hints for alert ingestion. */
|
|
165
|
+
export declare const AlertSourceConfigSchema: z.ZodRecord<z.ZodString, z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
166
|
+
export declare const RepoConfigSchema: z.ZodObject<{
|
|
167
|
+
repo: z.ZodString;
|
|
168
|
+
local_path: z.ZodDefault<z.ZodNullable<z.ZodString>>;
|
|
169
|
+
alert_sources: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodRecord<z.ZodString, z.ZodString>>>;
|
|
170
|
+
}, "strip", z.ZodTypeAny, {
|
|
171
|
+
repo: string;
|
|
172
|
+
local_path: string | null;
|
|
173
|
+
alert_sources?: Record<string, Record<string, string>> | undefined;
|
|
174
|
+
}, {
|
|
175
|
+
repo: string;
|
|
176
|
+
local_path?: string | null | undefined;
|
|
177
|
+
alert_sources?: Record<string, Record<string, string>> | undefined;
|
|
178
|
+
}>;
|
|
179
|
+
export declare const PlConfigSchema: z.ZodObject<{
|
|
180
|
+
$schema: z.ZodOptional<z.ZodString>;
|
|
181
|
+
/** Convenience single-repo default (owner/name); `repos` is the multi-repo map. */
|
|
182
|
+
repo: z.ZodOptional<z.ZodString>;
|
|
183
|
+
repos: z.ZodEffects<z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
184
|
+
repo: z.ZodString;
|
|
185
|
+
local_path: z.ZodDefault<z.ZodNullable<z.ZodString>>;
|
|
186
|
+
alert_sources: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodRecord<z.ZodString, z.ZodString>>>;
|
|
187
|
+
}, "strip", z.ZodTypeAny, {
|
|
188
|
+
repo: string;
|
|
189
|
+
local_path: string | null;
|
|
190
|
+
alert_sources?: Record<string, Record<string, string>> | undefined;
|
|
191
|
+
}, {
|
|
192
|
+
repo: string;
|
|
193
|
+
local_path?: string | null | undefined;
|
|
194
|
+
alert_sources?: Record<string, Record<string, string>> | undefined;
|
|
195
|
+
}>>>, Record<string, {
|
|
196
|
+
repo: string;
|
|
197
|
+
local_path: string | null;
|
|
198
|
+
alert_sources?: Record<string, Record<string, string>> | undefined;
|
|
199
|
+
}>, Record<string, {
|
|
200
|
+
repo: string;
|
|
201
|
+
local_path?: string | null | undefined;
|
|
202
|
+
alert_sources?: Record<string, Record<string, string>> | undefined;
|
|
203
|
+
}> | undefined>;
|
|
204
|
+
/** Service catalog (ADR-0015) — keyed by service name; maps into the context. */
|
|
205
|
+
services: z.ZodEffects<z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
206
|
+
tier: z.ZodOptional<z.ZodString>;
|
|
207
|
+
/** owner/name slug or a local path the harness reads. */
|
|
208
|
+
repo: z.ZodOptional<z.ZodString>;
|
|
209
|
+
/** Direct dependency service names (blast-radius seed). */
|
|
210
|
+
depends_on: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
|
|
211
|
+
}, "strip", z.ZodTypeAny, {
|
|
212
|
+
depends_on: string[];
|
|
213
|
+
tier?: string | undefined;
|
|
214
|
+
repo?: string | undefined;
|
|
215
|
+
}, {
|
|
216
|
+
tier?: string | undefined;
|
|
217
|
+
repo?: string | undefined;
|
|
218
|
+
depends_on?: string[] | undefined;
|
|
219
|
+
}>>>, Record<string, {
|
|
220
|
+
depends_on: string[];
|
|
221
|
+
tier?: string | undefined;
|
|
222
|
+
repo?: string | undefined;
|
|
223
|
+
}>, Record<string, {
|
|
224
|
+
tier?: string | undefined;
|
|
225
|
+
repo?: string | undefined;
|
|
226
|
+
depends_on?: string[] | undefined;
|
|
227
|
+
}> | undefined>;
|
|
228
|
+
/** Read-only log-query system the harness may query. */
|
|
229
|
+
logs: z.ZodEffects<z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>, {
|
|
230
|
+
kind?: string | undefined;
|
|
231
|
+
url?: string | undefined;
|
|
232
|
+
}, Record<string, unknown> | undefined>;
|
|
233
|
+
agent: z.ZodEffects<z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>, {
|
|
234
|
+
default: "deepagents" | "claude-code" | "codex";
|
|
235
|
+
permissions: {
|
|
236
|
+
mode: "read-only" | "supervised" | "auto" | "dangerous";
|
|
237
|
+
};
|
|
238
|
+
sandbox: "auto" | "process" | "srt" | "e2b";
|
|
239
|
+
limits: {
|
|
240
|
+
wall_clock_ms?: number | undefined;
|
|
241
|
+
memory_mb?: number | undefined;
|
|
242
|
+
cpu_cores?: number | undefined;
|
|
243
|
+
};
|
|
244
|
+
model?: string | undefined;
|
|
245
|
+
max_branches?: number | undefined;
|
|
246
|
+
}, Record<string, unknown> | undefined>;
|
|
247
|
+
workspace: z.ZodEffects<z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>, {
|
|
248
|
+
base_dir: string;
|
|
249
|
+
}, Record<string, unknown> | undefined>;
|
|
250
|
+
telemetry: z.ZodEffects<z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>, {
|
|
251
|
+
prometheusUrl?: string | undefined;
|
|
252
|
+
alertmanagerUrl?: string | undefined;
|
|
253
|
+
apiUrl?: string | undefined;
|
|
254
|
+
}, Record<string, unknown> | undefined>;
|
|
255
|
+
alert_sources: z.ZodEffects<z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodRecord<z.ZodString, z.ZodString>>>, Record<string, Record<string, string>>, Record<string, Record<string, string>> | undefined>;
|
|
256
|
+
/** Per-harness native passthrough (ADR-0017), keyed by harness id. */
|
|
257
|
+
harnesses: z.ZodEffects<z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
258
|
+
native: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
259
|
+
}, "strip", z.ZodTypeAny, {
|
|
260
|
+
native?: Record<string, unknown> | undefined;
|
|
261
|
+
}, {
|
|
262
|
+
native?: Record<string, unknown> | undefined;
|
|
263
|
+
}>>>, Record<string, {
|
|
264
|
+
native?: Record<string, unknown> | undefined;
|
|
265
|
+
}>, Record<string, {
|
|
266
|
+
native?: Record<string, unknown> | undefined;
|
|
267
|
+
}> | undefined>;
|
|
268
|
+
}, "strip", z.ZodTypeAny, {
|
|
269
|
+
alert_sources: Record<string, Record<string, string>>;
|
|
270
|
+
repos: Record<string, {
|
|
271
|
+
repo: string;
|
|
272
|
+
local_path: string | null;
|
|
273
|
+
alert_sources?: Record<string, Record<string, string>> | undefined;
|
|
274
|
+
}>;
|
|
275
|
+
services: Record<string, {
|
|
276
|
+
depends_on: string[];
|
|
277
|
+
tier?: string | undefined;
|
|
278
|
+
repo?: string | undefined;
|
|
279
|
+
}>;
|
|
280
|
+
logs: {
|
|
281
|
+
kind?: string | undefined;
|
|
282
|
+
url?: string | undefined;
|
|
283
|
+
};
|
|
284
|
+
agent: {
|
|
285
|
+
default: "deepagents" | "claude-code" | "codex";
|
|
286
|
+
permissions: {
|
|
287
|
+
mode: "read-only" | "supervised" | "auto" | "dangerous";
|
|
288
|
+
};
|
|
289
|
+
sandbox: "auto" | "process" | "srt" | "e2b";
|
|
290
|
+
limits: {
|
|
291
|
+
wall_clock_ms?: number | undefined;
|
|
292
|
+
memory_mb?: number | undefined;
|
|
293
|
+
cpu_cores?: number | undefined;
|
|
294
|
+
};
|
|
295
|
+
model?: string | undefined;
|
|
296
|
+
max_branches?: number | undefined;
|
|
297
|
+
};
|
|
298
|
+
workspace: {
|
|
299
|
+
base_dir: string;
|
|
300
|
+
};
|
|
301
|
+
telemetry: {
|
|
302
|
+
prometheusUrl?: string | undefined;
|
|
303
|
+
alertmanagerUrl?: string | undefined;
|
|
304
|
+
apiUrl?: string | undefined;
|
|
305
|
+
};
|
|
306
|
+
harnesses: Record<string, {
|
|
307
|
+
native?: Record<string, unknown> | undefined;
|
|
308
|
+
}>;
|
|
309
|
+
repo?: string | undefined;
|
|
310
|
+
$schema?: string | undefined;
|
|
311
|
+
}, {
|
|
312
|
+
repo?: string | undefined;
|
|
313
|
+
alert_sources?: Record<string, Record<string, string>> | undefined;
|
|
314
|
+
$schema?: string | undefined;
|
|
315
|
+
repos?: Record<string, {
|
|
316
|
+
repo: string;
|
|
317
|
+
local_path?: string | null | undefined;
|
|
318
|
+
alert_sources?: Record<string, Record<string, string>> | undefined;
|
|
319
|
+
}> | undefined;
|
|
320
|
+
services?: Record<string, {
|
|
321
|
+
tier?: string | undefined;
|
|
322
|
+
repo?: string | undefined;
|
|
323
|
+
depends_on?: string[] | undefined;
|
|
324
|
+
}> | undefined;
|
|
325
|
+
logs?: Record<string, unknown> | undefined;
|
|
326
|
+
agent?: Record<string, unknown> | undefined;
|
|
327
|
+
workspace?: Record<string, unknown> | undefined;
|
|
328
|
+
telemetry?: Record<string, unknown> | undefined;
|
|
329
|
+
harnesses?: Record<string, {
|
|
330
|
+
native?: Record<string, unknown> | undefined;
|
|
331
|
+
}> | undefined;
|
|
332
|
+
}>;
|
|
333
|
+
export type PlConfigInput = z.input<typeof PlConfigSchema>;
|
|
334
|
+
/** The validated, defaults-applied config consumed by the CLI commands. */
|
|
335
|
+
export type PlConfig = z.output<typeof PlConfigSchema>;
|
|
336
|
+
//# sourceMappingURL=schema.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../../src/config/schema.ts"],"names":[],"mappings":"AAsBA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB;;;;GAIG;AACH,eAAO,MAAM,sBAAsB;;;;;;EAEjC,CAAC;AAEH;;;;;GAKG;AACH,eAAO,MAAM,yBAAyB;;;;;;EAEpC,CAAC;AAEH;;;;;;GAMG;AACH,eAAO,MAAM,uBAAuB;IACnC,qEAAqE;;IAErE,gEAAgE;;IAEhE,+EAA+E;;;;;;;;;;EAE9E,CAAC;AAEH,8DAA8D;AAC9D,eAAO,MAAM,iBAAiB;;IAE7B;;;;;OAKG;;IAEH,4DAA4D;;;;IAE5D;;;;;;OAMG;;IAEH;;;OAGG;;;;;;IAEH;;;;OAIG;;;;;;;;;;;;;;;;;;;;;;EAEF,CAAC;AAEH,eAAO,MAAM,qBAAqB;;;;;;EAEhC,CAAC;AAEH;;;;GAIG;AACH,eAAO,MAAM,qBAAqB;;;;;;;;;;;;EAIhC,CAAC;AAEH;;;;GAIG;AACH,eAAO,MAAM,mBAAmB;;IAE/B,yDAAyD;;IAEzD,2DAA2D;;;;;;;;;;EAE1D,CAAC;AAEH,gFAAgF;AAChF,eAAO,MAAM,qBAAqB;;;;;;;;;EAGhC,CAAC;AAEH,mFAAmF;AACnF,eAAO,MAAM,uBAAuB,iEAGnC,CAAC;AAEF,eAAO,MAAM,gBAAgB;;;;;;;;;;;;EAI3B,CAAC;AAcH,eAAO,MAAM,cAAc;;IAE1B,mFAAmF;;;;;;;;;;;;;;;;;;;;;;;IAMnF,iFAAiF;;;QA5CjF,yDAAyD;;QAEzD,2DAA2D;;;;;;;;;;;;;;;;;;;IA+C3D,wDAAwD;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAQxD,sEAAsE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAKrE,CAAC;AAEH,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,cAAc,CAAC,CAAC;AAC3D,2EAA2E;AAC3E,MAAM,MAAM,QAAQ,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,cAAc,CAAC,CAAC"}
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
// Copyright 2026 Sumit Patel
|
|
3
|
+
/**
|
|
4
|
+
* prismalens.config.yaml schema (ADR-0010 engine-as-CLI), adapted from the retired
|
|
5
|
+
* pl orchestrator's config to the two-tier engine (ADR-0008).
|
|
6
|
+
*
|
|
7
|
+
* What changed vs. the old pl config:
|
|
8
|
+
* - `agent.default` enum is the harness BACKEND the supervisor rents
|
|
9
|
+
* ("deepagents" | "claude-code" | "codex"), not the old "deepagents-cli" et al.
|
|
10
|
+
* - `agent.model` is now OPTIONAL — each harness has its own default (deepagents:
|
|
11
|
+
* "openai:gpt-oss:120b"; Claude Code: the CLI/subscription default).
|
|
12
|
+
* - ADDED `telemetry` — the engine's TelemetryEndpoints (read-only surfaces the
|
|
13
|
+
* rented harness queries).
|
|
14
|
+
* - DROPPED the gatherer/analyst/verifier role taxonomy: `harness.roles` +
|
|
15
|
+
* `harness.tool_access`, the `sub_agents` role section, `investigation`, and
|
|
16
|
+
* `convergence.confidence_threshold` (ADR-0002: no numeric confidence). In the
|
|
17
|
+
* two-tier engine decompose is N=1 (one alert → one rented branch → reduce), so
|
|
18
|
+
* the role machinery is gone.
|
|
19
|
+
*/
|
|
20
|
+
import { HARNESS_IDS, PERMISSION_MODES } from "@prismalens/config/harness";
|
|
21
|
+
import { SANDBOX_MODES } from "@prismalens/engine";
|
|
22
|
+
import { z } from "zod";
|
|
23
|
+
/**
|
|
24
|
+
* The single posture dial (ADR-0017) — prismalens does not build a permission
|
|
25
|
+
* policy engine; it exposes this one dial and translates it to each harness's
|
|
26
|
+
* native config. Defaults to the safest posture, `read-only`.
|
|
27
|
+
*/
|
|
28
|
+
export const PermissionConfigSchema = z.object({
|
|
29
|
+
mode: z.enum(PERMISSION_MODES).default("read-only"),
|
|
30
|
+
});
|
|
31
|
+
/**
|
|
32
|
+
* Arbitrary harness-native passthrough (ADR-0017) — e.g. Agent SDK query options
|
|
33
|
+
* for `claude-code`, or `args` (extra CLI args) for `deepagents`. Kept untyped
|
|
34
|
+
* here (per-harness runners narrow it); prismalens does not validate the shape,
|
|
35
|
+
* it defers to the harness.
|
|
36
|
+
*/
|
|
37
|
+
export const HarnessNativeConfigSchema = z.object({
|
|
38
|
+
native: z.record(z.string(), z.unknown()).optional(),
|
|
39
|
+
});
|
|
40
|
+
/**
|
|
41
|
+
* Best-effort resource caps for the sandboxed harness run (ADR-0020: "resource
|
|
42
|
+
* limits are part of the contract"). All optional with NO defaults — an unset knob
|
|
43
|
+
* means "no cap", never a value that would lie about being enforced. What actually
|
|
44
|
+
* takes effect is provider-dependent (the `process` floor enforces only
|
|
45
|
+
* `wall_clock_ms`; `srt` adds memory/cpu when `systemd-run` is present).
|
|
46
|
+
*/
|
|
47
|
+
export const AgentLimitsConfigSchema = z.object({
|
|
48
|
+
/** Wall-clock deadline (ms) — enforced by every sandbox provider. */
|
|
49
|
+
wall_clock_ms: z.number().int().positive().optional(),
|
|
50
|
+
/** Memory ceiling (MB) — best-effort (srt+systemd-run only). */
|
|
51
|
+
memory_mb: z.number().int().positive().optional(),
|
|
52
|
+
/** CPU quota (whole/fractional cores) — best-effort (srt+systemd-run only). */
|
|
53
|
+
cpu_cores: z.number().positive().optional(),
|
|
54
|
+
});
|
|
55
|
+
/** Tier-2 harness backend the supervisor rents (ADR-0008). */
|
|
56
|
+
export const AgentConfigSchema = z.object({
|
|
57
|
+
default: z.enum(HARNESS_IDS).default("deepagents"),
|
|
58
|
+
/**
|
|
59
|
+
* BARE model id (e.g. "gpt-oss:120b") — the chosen harness applies its own
|
|
60
|
+
* provider prefix (ADR-0017: deepagents prepends "openai:"; Claude Code takes it
|
|
61
|
+
* bare). Also reused as the Tier-1 reduce model id. Omit to let the harness pick
|
|
62
|
+
* its own default.
|
|
63
|
+
*/
|
|
64
|
+
model: z.string().optional(),
|
|
65
|
+
/** The posture dial (ADR-0017). Defaults to `read-only`. */
|
|
66
|
+
permissions: optionalWithDefaults(PermissionConfigSchema),
|
|
67
|
+
/**
|
|
68
|
+
* The isolation boundary the harness runs in (ADR-0020): `process` (the always-on
|
|
69
|
+
* cooperative floor), `srt` (enforced OS boundary), or `auto` (srt WHEN its egress
|
|
70
|
+
* bridge is healthy — the self-check, B.1.1 — else the floor; the degrade is honest,
|
|
71
|
+
* never silent). Defaults to `auto`: honest precisely BECAUSE of the self-check, which
|
|
72
|
+
* is what makes it safe to prefer the enforced boundary by default.
|
|
73
|
+
*/
|
|
74
|
+
sandbox: z.enum(SANDBOX_MODES).default("auto"),
|
|
75
|
+
/**
|
|
76
|
+
* Best-effort resource caps for the sandboxed harness (ADR-0020). Optional; an
|
|
77
|
+
* omitted section means "no caps" (the object defaults to `{}` after parse).
|
|
78
|
+
*/
|
|
79
|
+
limits: optionalWithDefaults(AgentLimitsConfigSchema),
|
|
80
|
+
/**
|
|
81
|
+
* Per-alert fan-out cap (ADR-0016 decision 2): the max branches the supervisor
|
|
82
|
+
* runs when a context carries multiple alerts. Optional — omitted ⇒ the engine
|
|
83
|
+
* default (3). A single-alert run always uses one branch regardless.
|
|
84
|
+
*/
|
|
85
|
+
max_branches: z.number().int().positive().optional(),
|
|
86
|
+
});
|
|
87
|
+
export const WorkspaceConfigSchema = z.object({
|
|
88
|
+
base_dir: z.string().default("~/.prismalens"),
|
|
89
|
+
});
|
|
90
|
+
/**
|
|
91
|
+
* Read-only telemetry + app endpoints the harness may query. Mirrors the engine's
|
|
92
|
+
* TelemetryEndpoints (camelCase) so a loaded config can be handed straight to
|
|
93
|
+
* `InvestigateOptions.telemetry`. All optional here — resolved/overridden per run.
|
|
94
|
+
*/
|
|
95
|
+
export const TelemetryConfigSchema = z.object({
|
|
96
|
+
prometheusUrl: z.string().optional(),
|
|
97
|
+
alertmanagerUrl: z.string().optional(),
|
|
98
|
+
apiUrl: z.string().optional(),
|
|
99
|
+
});
|
|
100
|
+
/**
|
|
101
|
+
* A service in the catalog (ADR-0015). The CLI maps the matched entry into the
|
|
102
|
+
* investigation context's `service` field so a single-alert run carries the affected
|
|
103
|
+
* service's repo/tier/deps, not just the bare alert.
|
|
104
|
+
*/
|
|
105
|
+
export const ServiceConfigSchema = z.object({
|
|
106
|
+
tier: z.string().optional(),
|
|
107
|
+
/** owner/name slug or a local path the harness reads. */
|
|
108
|
+
repo: z.string().optional(),
|
|
109
|
+
/** Direct dependency service names (blast-radius seed). */
|
|
110
|
+
depends_on: z.array(z.string()).default([]),
|
|
111
|
+
});
|
|
112
|
+
/** A read-only log-query system the harness may curl (Loki/Elasticsearch/…). */
|
|
113
|
+
export const LogSourceConfigSchema = z.object({
|
|
114
|
+
kind: z.string().optional(),
|
|
115
|
+
url: z.string().optional(),
|
|
116
|
+
});
|
|
117
|
+
/** Free-form `{ source: { key: value } }` connection hints for alert ingestion. */
|
|
118
|
+
export const AlertSourceConfigSchema = z.record(z.string(), z.record(z.string(), z.string()));
|
|
119
|
+
export const RepoConfigSchema = z.object({
|
|
120
|
+
repo: z.string(),
|
|
121
|
+
local_path: z.string().nullable().default(null),
|
|
122
|
+
alert_sources: AlertSourceConfigSchema.optional(),
|
|
123
|
+
});
|
|
124
|
+
/**
|
|
125
|
+
* Make a sub-section optional in YAML but always present (with defaults) after
|
|
126
|
+
* parse. The transform's return is annotated `z.output<T>` so the resolved
|
|
127
|
+
* `PlConfig` keeps each sub-object's precise field types (e.g. `agent.default` is
|
|
128
|
+
* the harness-id union, not `any`) instead of collapsing to `any`.
|
|
129
|
+
*/
|
|
130
|
+
function optionalWithDefaults(schema) {
|
|
131
|
+
return z
|
|
132
|
+
.optional(z.record(z.string(), z.unknown()))
|
|
133
|
+
.transform((val) => schema.parse(val ?? {}));
|
|
134
|
+
}
|
|
135
|
+
export const PlConfigSchema = z.object({
|
|
136
|
+
$schema: z.string().optional(),
|
|
137
|
+
/** Convenience single-repo default (owner/name); `repos` is the multi-repo map. */
|
|
138
|
+
repo: z.string().optional(),
|
|
139
|
+
repos: z
|
|
140
|
+
.record(z.string(), RepoConfigSchema)
|
|
141
|
+
.optional()
|
|
142
|
+
.transform((val) => val ?? {}),
|
|
143
|
+
/** Service catalog (ADR-0015) — keyed by service name; maps into the context. */
|
|
144
|
+
services: z
|
|
145
|
+
.record(z.string(), ServiceConfigSchema)
|
|
146
|
+
.optional()
|
|
147
|
+
.transform((val) => val ?? {}),
|
|
148
|
+
/** Read-only log-query system the harness may query. */
|
|
149
|
+
logs: optionalWithDefaults(LogSourceConfigSchema),
|
|
150
|
+
agent: optionalWithDefaults(AgentConfigSchema),
|
|
151
|
+
workspace: optionalWithDefaults(WorkspaceConfigSchema),
|
|
152
|
+
telemetry: optionalWithDefaults(TelemetryConfigSchema),
|
|
153
|
+
alert_sources: AlertSourceConfigSchema.optional().transform((val) => val ?? {}),
|
|
154
|
+
/** Per-harness native passthrough (ADR-0017), keyed by harness id. */
|
|
155
|
+
harnesses: z
|
|
156
|
+
.record(z.string(), HarnessNativeConfigSchema)
|
|
157
|
+
.optional()
|
|
158
|
+
.transform((val) => val ?? {}),
|
|
159
|
+
});
|
|
160
|
+
//# sourceMappingURL=schema.js.map
|