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.
Files changed (64) hide show
  1. package/LICENSE +201 -0
  2. package/NOTICE +5 -0
  3. package/README.md +312 -0
  4. package/dist/bin/prismalens.d.ts +3 -0
  5. package/dist/bin/prismalens.d.ts.map +1 -0
  6. package/dist/bin/prismalens.js +32 -0
  7. package/dist/bin/prismalens.js.map +1 -0
  8. package/dist/src/cli/doctor.d.ts +3 -0
  9. package/dist/src/cli/doctor.d.ts.map +1 -0
  10. package/dist/src/cli/doctor.js +156 -0
  11. package/dist/src/cli/doctor.js.map +1 -0
  12. package/dist/src/cli/init.d.ts +3 -0
  13. package/dist/src/cli/init.d.ts.map +1 -0
  14. package/dist/src/cli/init.js +85 -0
  15. package/dist/src/cli/init.js.map +1 -0
  16. package/dist/src/cli/investigate.d.ts +101 -0
  17. package/dist/src/cli/investigate.d.ts.map +1 -0
  18. package/dist/src/cli/investigate.js +452 -0
  19. package/dist/src/cli/investigate.js.map +1 -0
  20. package/dist/src/cli/serve.d.ts +3 -0
  21. package/dist/src/cli/serve.d.ts.map +1 -0
  22. package/dist/src/cli/serve.js +26 -0
  23. package/dist/src/cli/serve.js.map +1 -0
  24. package/dist/src/config/loader.d.ts +22 -0
  25. package/dist/src/config/loader.d.ts.map +1 -0
  26. package/dist/src/config/loader.js +155 -0
  27. package/dist/src/config/loader.js.map +1 -0
  28. package/dist/src/config/schema.d.ts +336 -0
  29. package/dist/src/config/schema.d.ts.map +1 -0
  30. package/dist/src/config/schema.js +160 -0
  31. package/dist/src/config/schema.js.map +1 -0
  32. package/dist/src/core/detect-repo.d.ts +4 -0
  33. package/dist/src/core/detect-repo.d.ts.map +1 -0
  34. package/dist/src/core/detect-repo.js +28 -0
  35. package/dist/src/core/detect-repo.js.map +1 -0
  36. package/dist/src/core/file-session-store.d.ts +10 -0
  37. package/dist/src/core/file-session-store.d.ts.map +1 -0
  38. package/dist/src/core/file-session-store.js +34 -0
  39. package/dist/src/core/file-session-store.js.map +1 -0
  40. package/dist/src/core/parse-stdin.d.ts +2 -0
  41. package/dist/src/core/parse-stdin.d.ts.map +1 -0
  42. package/dist/src/core/parse-stdin.js +30 -0
  43. package/dist/src/core/parse-stdin.js.map +1 -0
  44. package/dist/src/core/run-investigation.d.ts +42 -0
  45. package/dist/src/core/run-investigation.d.ts.map +1 -0
  46. package/dist/src/core/run-investigation.js +144 -0
  47. package/dist/src/core/run-investigation.js.map +1 -0
  48. package/dist/src/core/session.d.ts +42 -0
  49. package/dist/src/core/session.d.ts.map +1 -0
  50. package/dist/src/core/session.js +168 -0
  51. package/dist/src/core/session.js.map +1 -0
  52. package/dist/src/jsonrpc/server.d.ts +15 -0
  53. package/dist/src/jsonrpc/server.d.ts.map +1 -0
  54. package/dist/src/jsonrpc/server.js +244 -0
  55. package/dist/src/jsonrpc/server.js.map +1 -0
  56. package/dist/src/jsonrpc/types.d.ts +12 -0
  57. package/dist/src/jsonrpc/types.d.ts.map +1 -0
  58. package/dist/src/jsonrpc/types.js +4 -0
  59. package/dist/src/jsonrpc/types.js.map +1 -0
  60. package/dist/src/version.d.ts +8 -0
  61. package/dist/src/version.d.ts.map +1 -0
  62. package/dist/src/version.js +27 -0
  63. package/dist/src/version.js.map +1 -0
  64. 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