@crewhaus/ir 0.2.4 → 0.3.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/dist/index.d.ts CHANGED
@@ -19,17 +19,24 @@ export type IrPermissions = {
19
19
  * MCP server configs carried through to codegen (Section 9). Lower-time
20
20
  * normalisation: optional spec fields become required IR fields with
21
21
  * empty defaults, so target codegen doesn't need `?? []` guards.
22
+ *
23
+ * 0.3.0 (breaking, pre-1.0): stdio `env` and sse `headers` VALUES are
24
+ * `IrSecretRef`, not plain strings — `$UPPER_SNAKE` spec values lower to
25
+ * `{ kind: "env" }` references exactly like every other credential field,
26
+ * so secrets never land in compiled artifacts. Target codegen embeds the
27
+ * unresolved config verbatim and the emitted bundle resolves it at process
28
+ * start via `resolveMcpServerConfig` from `@crewhaus/mcp-host`.
22
29
  */
23
30
  export type IrMcpStdioConfig = {
24
31
  readonly transport: "stdio";
25
32
  readonly command: string;
26
33
  readonly args: readonly string[];
27
- readonly env?: Readonly<Record<string, string>>;
34
+ readonly env?: Readonly<Record<string, IrSecretRef>>;
28
35
  };
29
36
  export type IrMcpSseConfig = {
30
37
  readonly transport: "sse";
31
38
  readonly url: string;
32
- readonly headers?: Readonly<Record<string, string>>;
39
+ readonly headers?: Readonly<Record<string, IrSecretRef>>;
33
40
  };
34
41
  export type IrMcpServerConfig = IrMcpStdioConfig | IrMcpSseConfig;
35
42
  export type IrMcpServers = Readonly<Record<string, IrMcpServerConfig>>;
@@ -259,20 +266,180 @@ export type IrFeedback = {
259
266
  readonly exitPrompt?: boolean;
260
267
  readonly channelReactions?: boolean;
261
268
  };
269
+ /**
270
+ * v0.3.0 §3.1/§9 — the wiki (semantic tier) config, lowered from
271
+ * `spec.memory.wiki`. Presence (with `enabled` not `false`) registers the
272
+ * thredz-vocabulary `wiki_*` tools over `@crewhaus/wiki-store`. Every field
273
+ * is carried only when the spec declared it (absent-when-omitted).
274
+ */
275
+ export type IrMemoryWiki = {
276
+ readonly enabled?: boolean;
277
+ /** Wiki hits fused into auto-recall (1–50). */
278
+ readonly recallK?: number;
279
+ /** `@crewhaus/embedder` factory grammar — enables hybrid recall on both
280
+ * the wiki and the fact store. */
281
+ readonly embedder?: string;
282
+ /** Fuse wiki recall into the session-start memory bundle. */
283
+ readonly autoRecall?: boolean;
284
+ /** Learning-mode write governance: `wiki_write` rejects bodies without a
285
+ * `## Sources` heading. */
286
+ readonly requireSources?: boolean;
287
+ };
288
+ /**
289
+ * v0.3.0 Goal 5 (§6/§9) — scheduled memory consolidation, lowered from
290
+ * `spec.memory.dream`. `every` is parsed to `everyMs` at lower time
291
+ * (>= 5m enforced there); `mode` is RESOLVED at lower time (default
292
+ * `"full"`) so emitters and the interpreter read one deterministic shape.
293
+ * `budgetUsd`/`instructions` are carried only when declared — the model
294
+ * phase runs only when `mode` is `"full"` AND `budgetUsd > 0`.
295
+ */
296
+ export type IrMemoryDream = {
297
+ /** Consolidation cadence in milliseconds (`spec.memory.dream.every`). */
298
+ readonly everyMs: number;
299
+ /** `deterministic` (no model, ever) | `full` (bounded model synthesis). */
300
+ readonly mode: "deterministic" | "full";
301
+ /** Item-27 spend cap for the model phase (USD). Absent or 0 =
302
+ * deterministic only. */
303
+ readonly budgetUsd?: number;
304
+ /** Playbook override; default = the builtin `dream` skill body. */
305
+ readonly instructions?: string;
306
+ };
262
307
  /**
263
308
  * Feature #53 — cross-session memory config, lowered from `spec.memory`.
264
309
  * Presence of the block wires Remember/Recall into the target; the auto-*
265
310
  * switches gate auto-capture (summarize durable outcomes at teardown) and
266
311
  * auto-recall (inject top-K memories into the system prompt at session start).
267
- * Carried on the interactive shapes that run a chat loop (IrV0/cli,
268
- * IrChannelV0, IrManagedV0, IrResearchV0). Absent when the spec omits `memory`.
312
+ * Carried on the agent-loop shapes (IrV0/cli, IrChannelV0, IrManagedV0,
313
+ * IrResearchV0, IrCrewV0). Absent when the spec omits `memory`.
314
+ *
315
+ * v0.3.0 (§9) extensions, all absent-when-omitted: `backend` (`file` |
316
+ * reserved `thredz`), `ttlMs` (explicit fact forgetting — `spec.memory.ttl`
317
+ * parsed to milliseconds at lower time, >= 1h enforced there), `wiki`
318
+ * (see {@link IrMemoryWiki}), and `dream` (see {@link IrMemoryDream}).
269
319
  */
270
320
  export type IrMemory = {
271
321
  readonly enabled?: boolean;
322
+ readonly backend?: "file" | "thredz";
323
+ readonly ttlMs?: number;
272
324
  readonly autoCapture?: boolean;
273
325
  readonly autoCaptureThreshold?: number;
274
326
  readonly autoRecall?: boolean;
275
327
  readonly recallK?: number;
328
+ readonly wiki?: IrMemoryWiki;
329
+ readonly dream?: IrMemoryDream;
330
+ };
331
+ /** v0.3.0 §2.7 — the RESOLVED continuity scope. `auto` is a compiler
332
+ * concern: `lower()` resolves it per shape (cli/research/crew/managed →
333
+ * `spec`, channel → `session`), so the IR never carries `auto`. */
334
+ export type IrContinuityScope = "spec" | "session";
335
+ /**
336
+ * v0.3.0 Goal 1 (§2.1/§9) — continuity config, lowered from the top-level
337
+ * `continuity:` block. THE release's one sanctioned default-on: on the five
338
+ * emit-wired agent-loop shapes (IrV0/cli, IrChannelV0, IrManagedV0,
339
+ * IrResearchV0, IrCrewV0) an ABSENT spec key lowers to the default-on config
340
+ * below, and only `continuity: false` (or `enabled: false`) removes this
341
+ * field — presence means enabled. Also carried, when the spec declares it,
342
+ * on IrWorkflowV0/IrBatchV0/IrVoiceV0/IrBrowserV0, whose emitters print the
343
+ * 0.2.3-convention ignored-note comment instead of wiring it.
344
+ *
345
+ * All fields except `focusMaxChars` are RESOLVED at lower time (defaults
346
+ * filled in: plan/ledger/handoff true, proof "ladder", scope per §2.7), so
347
+ * emitters and the interpreter read one deterministic shape.
348
+ */
349
+ export type IrContinuity = {
350
+ /** Plan/goal persistence + the Plan and Goal tool families; `false`
351
+ * keeps only FocusRead/FocusWrite + MemoryClear. */
352
+ readonly plan: boolean;
353
+ /** §2.4 proof-of-action: `ladder` (default) | `require` | `off`. */
354
+ readonly proof: "ladder" | "require" | "off";
355
+ /** §2.3 verbatim requirements ledger (context_evicted externalization). */
356
+ readonly ledger: boolean;
357
+ /** §2.8 deterministic teardown handoff.md. */
358
+ readonly handoff: boolean;
359
+ /** Resolved store scope (§2.7/§14.5). */
360
+ readonly scope: IrContinuityScope;
361
+ /** Hard cap on the mutable tail block. Absent → runtime default (4096). */
362
+ readonly focusMaxChars?: number;
363
+ };
364
+ /**
365
+ * v0.3.0 Goal 3 (§4.1/§9) — the Thredz config, lowered from the top-level
366
+ * `thredz:` block (boolean/string shorthand or the object form — the spec
367
+ * shorthands are RESOLVED at lower time so this carries one deterministic
368
+ * shape). Presence means Thredz is on.
369
+ *
370
+ * The compiler additionally SYNTHESIZES an `mcp_servers.thredz` stdio entry
371
+ * (`npx -y thredz-mcp@0.2.0` with `THREDZ_API_KEY` as an `IrSecretRef` env
372
+ * value, riding the §4.2 secret machinery end-to-end) on the emit-wired
373
+ * shape (cli). A user-declared `mcp_servers.thredz` wins over synthesis
374
+ * (explicit beats implicit — `crewhaus lint` warns); this config block is
375
+ * carried either way so the wiring layer (memory-service) still routes the
376
+ * wiki backend and goal mirror through that server.
377
+ */
378
+ export type IrThredzVisibility = "private" | "shared";
379
+ export type IrThredz = {
380
+ /** The Thredz API key — credential-lowered (`$THREDZ_API_KEY` →
381
+ * `{ kind: "env" }`; fail-fast on a malformed `$…` ref). */
382
+ readonly apiKey: IrSecretRef;
383
+ /** Self-hosted / local API base (`THREDZ_API_BASE`). Absent → the hosted
384
+ * default inside thredz-mcp. */
385
+ readonly baseUrl?: string;
386
+ /** RESOLVED default `private` — becomes `THREDZ_DEFAULT_VISIBILITY`, so
387
+ * agent memory is never public by accident (Thredz's own API defaults
388
+ * new articles to globally-shared). */
389
+ readonly visibility: IrThredzVisibility;
390
+ /** RESOLVED — mirror continuity goal writes to Thredz `goal_write`/
391
+ * `goal_update` (spec-scoped only, §14.5 decision 5). Defaulted at lower
392
+ * time to "on when continuity goals are on". */
393
+ readonly goals: boolean;
394
+ /** Register this addressable agent handle at boot (idempotent
395
+ * `agent_register`). Absent → no registration (the default). */
396
+ readonly agentName?: string;
397
+ };
398
+ /** v0.3.0 Goal 2 (§3.3, PR 17) — the first-class competency exam: dataset +
399
+ * graders paths, spec-relative. Whether the files EXIST is a runtime
400
+ * concern (the `run_exam` tool fails with a clear error); the compiler
401
+ * validates shape only. */
402
+ export type IrLearningExam = {
403
+ /** Spec-relative path to the exam dataset (jsonl). */
404
+ readonly dataset: string;
405
+ /** Spec-relative path to the graders config (yaml). */
406
+ readonly graders: string;
407
+ };
408
+ /** v0.3.0 Goal 2 (§3.3, PR 17) — unattended-study toggles, RESOLVED at lower
409
+ * time (both default true) so downstream reads one deterministic shape. */
410
+ export type IrLearningStudy = {
411
+ /** Prepend the study-rotation preamble (gaps first, ~3:1 study:reflect,
412
+ * bounded per tick) to channel heartbeat instructions. */
413
+ readonly onHeartbeat: boolean;
414
+ /** Seed the dream model phase's findings with the top open knowledge gaps
415
+ * + the next unmastered curriculum rung. */
416
+ readonly onDream: boolean;
417
+ };
418
+ /**
419
+ * v0.3.0 Goal 2 (§3.3, PR 17) — continual-learning config, lowered from the
420
+ * top-level `learning:` block. Presence means learning is ON (the compiler
421
+ * dropped `enabled: false` at lower time). Learning REQUIRES a wiki —
422
+ * `lower()` rejects the block without `memory.wiki` (local) or `thredz:`
423
+ * (hosted) — and deterministically stamps `memory.wiki.requireSources: true`
424
+ * (Sources-required write governance, what was prompt-only in the expert
425
+ * demo).
426
+ *
427
+ * `domain`/`curriculum`/`sources` are substituted into the builtin
428
+ * `learning-loop` skill body at wire time; `exam` drives the programmatic
429
+ * `run_exam` tool; `study` carries the resolved unattended-study toggles.
430
+ * Carried on the five memory shapes (IrV0/cli, IrChannelV0, IrManagedV0,
431
+ * IrResearchV0, IrCrewV0).
432
+ */
433
+ export type IrLearning = {
434
+ /** One sentence naming the field of expertise. */
435
+ readonly domain: string;
436
+ /** Spec-relative path to the agent-editable curriculum ladder. Absent →
437
+ * the skill keeps the ladder in the wiki. */
438
+ readonly curriculum?: string;
439
+ /** Source-allowlist hints. NOT optimizable — allowlist = security (§7.5). */
440
+ readonly sources?: readonly string[];
441
+ readonly exam?: IrLearningExam;
442
+ readonly study: IrLearningStudy;
276
443
  };
277
444
  /** Ops item 37 — a mitigation-ladder rung the runtime SLO monitor walks on a
278
445
  * sustained breach, in declared order. See {@link IrSlo}. */
@@ -388,6 +555,15 @@ export type IrV0 = {
388
555
  readonly feedback?: IrFeedback;
389
556
  /** #53 cross-session memory config. Optional; absent when the spec omits `memory`. */
390
557
  readonly memory?: IrMemory;
558
+ /** v0.3.0 Goal 1 — continuity config. DEFAULT-ON: present unless the spec
559
+ * opted out with `continuity: false`. */
560
+ readonly continuity?: IrContinuity;
561
+ /** v0.3.0 Goal 3 — Thredz config. Present when the spec declares `thredz:`;
562
+ * the compiler also synthesizes `mcp_servers.thredz` on this shape. */
563
+ readonly thredz?: IrThredz;
564
+ /** v0.3.0 Goal 2 — continual-learning config (§3.3, PR 17). Present
565
+ * when the spec declares an enabled `learning:` block. */
566
+ readonly learning?: IrLearning;
391
567
  /** Ops item 37 — SLO targets + mitigation ladder. Optional; absent when the
392
568
  * spec omits the `observability` block. */
393
569
  readonly observability?: IrObservability;
@@ -428,6 +604,9 @@ export type IrWorkflowV0 = {
428
604
  readonly compaction: IrCompaction;
429
605
  /** Section 55 (Track A) — named failure taxonomy. Optional. */
430
606
  readonly failureTaxonomy?: IrFailureTaxonomy;
607
+ /** v0.3.0 — carried when the spec declares `continuity:` (NOT default-on
608
+ * here); target-workflow prints the ignored-note comment. */
609
+ readonly continuity?: IrContinuity;
431
610
  };
432
611
  /**
433
612
  * A secret value referenced by a channel config (Section 12). Lower-time
@@ -650,6 +829,16 @@ export type IrChannelV0 = {
650
829
  readonly feedback?: IrFeedback;
651
830
  /** #53 cross-session memory config. Optional; absent when the spec omits `memory`. */
652
831
  readonly memory?: IrMemory;
832
+ /** v0.3.0 Goal 1 — continuity config. DEFAULT-ON: present unless the spec
833
+ * opted out with `continuity: false`. `scope` resolves to `session` here
834
+ * (per-conversation stores riding the session router's sessionId, §14.5). */
835
+ readonly continuity?: IrContinuity;
836
+ /** v0.3.0 Goal 3 — Thredz config, CARRIED but not emit-wired on this shape
837
+ * in this release (the emitter prints the ignored-note comment). */
838
+ readonly thredz?: IrThredz;
839
+ /** v0.3.0 Goal 2 — continual-learning config (§3.3, PR 17). Present
840
+ * when the spec declares an enabled `learning:` block. */
841
+ readonly learning?: IrLearning;
653
842
  /** Ops item 37 — SLO targets + mitigation ladder. Optional; absent when the
654
843
  * spec omits the `observability` block. */
655
844
  readonly observability?: IrObservability;
@@ -697,6 +886,16 @@ export type IrManagedV0 = {
697
886
  readonly budget?: IrBudget;
698
887
  /** #53 cross-session memory config. Optional; absent when the spec omits `memory`. */
699
888
  readonly memory?: IrMemory;
889
+ /** v0.3.0 Goal 1 — continuity config. DEFAULT-ON: present unless the spec
890
+ * opted out with `continuity: false`. `scope` resolves to `spec` here;
891
+ * every store is tenant-fenced at boot (deps carry the tenant, §2.7). */
892
+ readonly continuity?: IrContinuity;
893
+ /** v0.3.0 Goal 3 — Thredz config, CARRIED but not emit-wired on this shape
894
+ * in this release (the emitter prints the ignored-note comment). */
895
+ readonly thredz?: IrThredz;
896
+ /** v0.3.0 Goal 2 — continual-learning config (§3.3, PR 17). Present
897
+ * when the spec declares an enabled `learning:` block. */
898
+ readonly learning?: IrLearning;
700
899
  /** Ops item 37 — SLO targets + mitigation ladder. Optional; absent when the
701
900
  * spec omits the `observability` block. The managed daemon's `pause-intake`
702
901
  * rung reuses its `budget_exceeded` 429 path. */
@@ -849,6 +1048,19 @@ export type IrCrewV0 = {
849
1048
  readonly compaction: IrCompaction;
850
1049
  /** Section 55 (Track A) — named failure taxonomy. Optional. */
851
1050
  readonly failureTaxonomy?: IrFailureTaxonomy;
1051
+ /** #53/v0.3.0 — cross-session memory config (crew joins the carrying
1052
+ * shapes in 0.3.0; roles share the spec-scoped store). Optional. */
1053
+ readonly memory?: IrMemory;
1054
+ /** v0.3.0 Goal 1 — continuity config. DEFAULT-ON: present unless the spec
1055
+ * opted out with `continuity: false`. Roles share the `spec`-scoped plan
1056
+ * store — the plan IS the coordination surface (§2.7). */
1057
+ readonly continuity?: IrContinuity;
1058
+ /** v0.3.0 Goal 3 — Thredz config, CARRIED but not emit-wired on this shape
1059
+ * in this release (the emitter prints the ignored-note comment). */
1060
+ readonly thredz?: IrThredz;
1061
+ /** v0.3.0 Goal 2 — continual-learning config (§3.3, PR 17). Present
1062
+ * when the spec declares an enabled `learning:` block. */
1063
+ readonly learning?: IrLearning;
852
1064
  /** §47 cross-cutting blockchain subsystem (slice 0). All optional. */
853
1065
  readonly chains?: readonly IrChainBinding[];
854
1066
  readonly wallets?: readonly IrWalletBinding[];
@@ -896,6 +1108,15 @@ export type IrResearchV0 = {
896
1108
  readonly failureTaxonomy?: IrFailureTaxonomy;
897
1109
  /** #53 cross-session memory config. Optional; absent when the spec omits `memory`. */
898
1110
  readonly memory?: IrMemory;
1111
+ /** v0.3.0 Goal 1 — continuity config. DEFAULT-ON: present unless the spec
1112
+ * opted out with `continuity: false`. `scope` resolves to `spec` here. */
1113
+ readonly continuity?: IrContinuity;
1114
+ /** v0.3.0 Goal 3 — Thredz config, CARRIED but not emit-wired on this shape
1115
+ * in this release (the emitter prints the ignored-note comment). */
1116
+ readonly thredz?: IrThredz;
1117
+ /** v0.3.0 Goal 2 — continual-learning config (§3.3, PR 17). Present
1118
+ * when the spec declares an enabled `learning:` block. */
1119
+ readonly learning?: IrLearning;
899
1120
  /** §47 cross-cutting blockchain subsystem (slice 0). All optional. */
900
1121
  readonly chains?: readonly IrChainBinding[];
901
1122
  readonly wallets?: readonly IrWalletBinding[];
@@ -940,6 +1161,9 @@ export type IrBatchV0 = {
940
1161
  readonly compaction: IrCompaction;
941
1162
  /** Section 55 (Track A) — named failure taxonomy. Optional. */
942
1163
  readonly failureTaxonomy?: IrFailureTaxonomy;
1164
+ /** v0.3.0 — carried when the spec declares `continuity:` (NOT default-on
1165
+ * here); target-batch-worker prints the ignored-note comment. */
1166
+ readonly continuity?: IrContinuity;
943
1167
  /** §47 cross-cutting blockchain subsystem (slice 0). All optional. */
944
1168
  readonly chains?: readonly IrChainBinding[];
945
1169
  readonly wallets?: readonly IrWalletBinding[];
@@ -984,6 +1208,9 @@ export type IrVoiceV0 = {
984
1208
  readonly compaction: IrCompaction;
985
1209
  /** Section 55 (Track A) — named failure taxonomy. Optional. */
986
1210
  readonly failureTaxonomy?: IrFailureTaxonomy;
1211
+ /** v0.3.0 — carried when the spec declares `continuity:` (NOT default-on
1212
+ * here); target-voice prints the ignored-note comment. */
1213
+ readonly continuity?: IrContinuity;
987
1214
  };
988
1215
  /**
989
1216
  * Section 25 — BROW (computer-use / browser driver) IR. The compiled
@@ -1020,6 +1247,9 @@ export type IrBrowserV0 = {
1020
1247
  readonly compaction: IrCompaction;
1021
1248
  /** Section 55 (Track A) — named failure taxonomy. Optional. */
1022
1249
  readonly failureTaxonomy?: IrFailureTaxonomy;
1250
+ /** v0.3.0 — carried when the spec declares `continuity:` (NOT default-on
1251
+ * here); target-browser-driver prints the ignored-note comment. */
1252
+ readonly continuity?: IrContinuity;
1023
1253
  };
1024
1254
  /** Discriminated union over every supported target IR. */
1025
1255
  /**
package/dist/readme.js CHANGED
@@ -6,13 +6,25 @@ import { OPAQUE_TOKEN_RE, maskCredentialTokens } from "./redact";
6
6
  * (kept, with a notice).
7
7
  */
8
8
  export const GENERATED_README_MARKER = "<!-- crewhaus:generated-readme -->";
9
+ /**
10
+ * Literal refs under these keys are COMPILER-SYNTHESIZED configuration
11
+ * knobs (v0.3.0 `thredz:` lowering — visibility enforcement + self-hosted
12
+ * base URL), not user-supplied secrets: counting them would print the
13
+ * "supplied as literals in the spec" warning on every one-knob
14
+ * `thredz: true` spec whose author supplied nothing literal at all. Scoped
15
+ * to exactly these names so every user-declared literal keeps warning.
16
+ */
17
+ const SYNTHESIZED_LITERAL_KEYS = new Set([
18
+ "THREDZ_DEFAULT_VISIBILITY",
19
+ "THREDZ_API_BASE",
20
+ ]);
9
21
  export function collectSecretRefs(ir) {
10
22
  const envNames = new Set();
11
23
  let literalCount = 0;
12
- const visit = (node) => {
24
+ const visit = (node, parentKey) => {
13
25
  if (Array.isArray(node)) {
14
26
  for (const item of node)
15
- visit(item);
27
+ visit(item, parentKey);
16
28
  return;
17
29
  }
18
30
  if (node === null || typeof node !== "object")
@@ -25,10 +37,12 @@ export function collectSecretRefs(ir) {
25
37
  envNames.add(record["name"]);
26
38
  }
27
39
  else if (record["kind"] === "literal" && typeof record["value"] === "string") {
28
- literalCount += 1;
40
+ if (parentKey === undefined || !SYNTHESIZED_LITERAL_KEYS.has(parentKey)) {
41
+ literalCount += 1;
42
+ }
29
43
  }
30
- for (const value of Object.values(record))
31
- visit(value);
44
+ for (const [key, value] of Object.entries(record))
45
+ visit(value, key);
32
46
  };
33
47
  visit(ir);
34
48
  return { envNames: [...envNames].sort(), literalCount };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@crewhaus/ir",
3
- "version": "0.2.4",
3
+ "version": "0.3.1",
4
4
  "type": "module",
5
5
  "description": "Canonical typed intermediate representation",
6
6
  "main": "dist/index.js",