@getbourdon/conformance 0.2.2 → 0.3.0

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 (34) hide show
  1. package/README.md +26 -4
  2. package/dist/index.cjs +30 -2
  3. package/dist/index.cjs.map +1 -1
  4. package/dist/index.d.cts +20 -1
  5. package/dist/index.d.ts +28 -11
  6. package/dist/index.js +51 -29
  7. package/dist/index.js.map +1 -1
  8. package/fixtures/README.md +11 -3
  9. package/fixtures/l5_manifests/invalid/entity-impossible-calendar-date.json +14 -0
  10. package/fixtures/l5_manifests/invalid/reasons.json +52 -0
  11. package/fixtures/l5_manifests/invalid/session-impossible-calendar-date.json +13 -0
  12. package/fixtures/l5_manifests/invalid/session-impossible-feb-30.json +13 -0
  13. package/fixtures/l5_manifests/valid/session-empty-date.json +16 -0
  14. package/fixtures/l5_schema.json +137 -38
  15. package/fixtures/manifest.json +97 -7
  16. package/fixtures/mcp_snapshots/_normalizer.json +1 -0
  17. package/fixtures/mcp_snapshots/commit_to_federation.res.json +1 -0
  18. package/fixtures/mcp_snapshots/explain_memory_change.req.json +7 -0
  19. package/fixtures/mcp_snapshots/explain_memory_change.res.json +15 -0
  20. package/fixtures/mcp_snapshots/list_memory_versions.req.json +6 -0
  21. package/fixtures/mcp_snapshots/list_memory_versions.res.json +13 -0
  22. package/fixtures/mcp_snapshots/prepare_recognition_context_drifting.req.json +8 -0
  23. package/fixtures/mcp_snapshots/prepare_recognition_context_drifting.res.json +26 -0
  24. package/fixtures/mcp_snapshots/resource_agent_memory.req.json +6 -0
  25. package/fixtures/mcp_snapshots/resource_agent_memory.res.json +80 -0
  26. package/fixtures/mcp_snapshots/resource_agents.req.json +4 -0
  27. package/fixtures/mcp_snapshots/resource_agents.res.json +4 -0
  28. package/fixtures/mcp_snapshots/resource_entity.req.json +6 -0
  29. package/fixtures/mcp_snapshots/resource_entity.res.json +19 -0
  30. package/fixtures/mcp_snapshots/rollback_agent_memory.req.json +7 -0
  31. package/fixtures/mcp_snapshots/rollback_agent_memory.res.json +7 -0
  32. package/fixtures/mcp_snapshots/seed_library.json +67 -3
  33. package/fixtures.pin.json +5 -0
  34. package/package.json +6 -4
package/README.md CHANGED
@@ -6,8 +6,13 @@ Python (`pip install bourdon`) is the **oracle**. The `@getbourdon/*` TypeScript
6
6
  reproduces the oracle's output on these exact fixtures — byte-for-byte where the contract is bytes (redaction,
7
7
  recognition strings, MCP wire), value-for-value where it's structured (F1, schema validity, tool I/O).
8
8
 
9
- The fixtures are generated by the Python repo's `tools/gen_conformance.py` (the single writer) and consumed by
10
- both the Python test suite and the TS `vitest` suite. This package ships them with typed loaders.
9
+ ## Who mints fixtures
10
+
11
+ **The Python repository mints fixtures; this package is a runner and consumer, never a producer.** Every
12
+ fixture is generated by the Python repo's `tools/gen_conformance.py` (the single writer, which imports the
13
+ live oracle and emits its actual output). This package vendors a reviewed snapshot of that output under
14
+ `fixtures/` and ships it with typed loaders. No fixture is ever authored or edited here — a change always
15
+ starts oracle-side and arrives through the re-pin ritual below.
11
16
 
12
17
  ```ts
13
18
  import { loadRedactionBattery, assembleSecret } from "@getbourdon/conformance";
@@ -19,8 +24,25 @@ for (const secret of battery.secrets) {
19
24
  }
20
25
  ```
21
26
 
22
- **Resolution (Phase 0–1):** `BOURDON_CONFORMANCE_DIR`, else the sibling Python checkout
23
- `../bourdon/conformance`. Once published, the fixtures ship inside this package.
27
+ ## The pin
28
+
29
+ `fixtures.pin.json` records which contract the vendored snapshot is (`conformance_version`) and the sha256
30
+ `fixtures/manifest.json` must hash to. The test suite asserts both and prints them, and separately verifies
31
+ every fixture file against the sha256 its manifest stamps — so a stale, partial, or hand-edited fixture tree
32
+ cannot pass quietly. A mutation test corrupts a temp copy and asserts the hash gate goes red, proving the
33
+ gate itself is live.
34
+
35
+ ## Re-pin ritual (per contract bump)
36
+
37
+ 1. Oracle side: regenerate (`python tools/gen_conformance.py`), review the diff, land it there first.
38
+ 2. Here: `BOURDON_CONFORMANCE_DIR=<oracle>/conformance pnpm --filter @getbourdon/conformance sync-fixtures`
39
+ 3. Update `fixtures.pin.json` with the new `conformance_version` and the sha256 of the new
40
+ `fixtures/manifest.json`.
41
+ 4. Run the workspace test suite; fix whatever the new contract flushes out **in the mirror packages**, never
42
+ by editing a fixture.
43
+
44
+ **Resolution order:** `BOURDON_CONFORMANCE_DIR`, else the vendored `fixtures/` snapshot, else the sibling
45
+ Python checkout `../bourdon/conformance`.
24
46
 
25
47
  License: Apache-2.0 (the wire-contract surface is permissive so third parties can build conformant
26
48
  implementations). The Bourdon engine is BUSL-1.1.
package/dist/index.cjs CHANGED
@@ -23,9 +23,13 @@ __export(index_exports, {
23
23
  assembleSecret: () => assembleSecret,
24
24
  conformanceDir: () => conformanceDir,
25
25
  loadManifest: () => loadManifest,
26
- loadRedactionBattery: () => loadRedactionBattery
26
+ loadPin: () => loadPin,
27
+ loadRedactionBattery: () => loadRedactionBattery,
28
+ sha256File: () => sha256File,
29
+ verifyFixtureHashes: () => verifyFixtureHashes
27
30
  });
28
31
  module.exports = __toCommonJS(index_exports);
32
+ var import_node_crypto = require("crypto");
29
33
  var import_node_fs = require("fs");
30
34
  var import_node_path = require("path");
31
35
  var import_node_url = require("url");
@@ -49,6 +53,27 @@ function loadJson(name) {
49
53
  function loadManifest() {
50
54
  return loadJson("manifest.json");
51
55
  }
56
+ function loadPin() {
57
+ return JSON.parse(
58
+ (0, import_node_fs.readFileSync)((0, import_node_path.resolve)(moduleDir(), "..", "fixtures.pin.json"), "utf8")
59
+ );
60
+ }
61
+ function sha256File(path) {
62
+ return (0, import_node_crypto.createHash)("sha256").update((0, import_node_fs.readFileSync)(path)).digest("hex");
63
+ }
64
+ function verifyFixtureHashes(dir = conformanceDir()) {
65
+ const manifest = JSON.parse(
66
+ (0, import_node_fs.readFileSync)((0, import_node_path.resolve)(dir, "manifest.json"), "utf8")
67
+ );
68
+ const mismatches = [];
69
+ for (const fixture of manifest.fixtures) {
70
+ const actual = sha256File((0, import_node_path.resolve)(dir, fixture.path));
71
+ if (actual !== fixture.sha256) {
72
+ mismatches.push({ path: fixture.path, expected: fixture.sha256, actual });
73
+ }
74
+ }
75
+ return mismatches;
76
+ }
52
77
  function loadRedactionBattery() {
53
78
  return loadJson("redaction_battery.json");
54
79
  }
@@ -60,6 +85,9 @@ function assembleSecret(secret) {
60
85
  assembleSecret,
61
86
  conformanceDir,
62
87
  loadManifest,
63
- loadRedactionBattery
88
+ loadPin,
89
+ loadRedactionBattery,
90
+ sha256File,
91
+ verifyFixtureHashes
64
92
  });
65
93
  //# sourceMappingURL=index.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts"],"sourcesContent":["import { existsSync, readFileSync } from \"node:fs\";\nimport { dirname, resolve } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\n\n/**\n * Typed loaders for the language-neutral parity fixtures produced by the Python\n * oracle (`~/repos/bourdon/tools/gen_conformance.py`). Python is the source of\n * truth; the @getbourdon/* TypeScript mirror asserts against these exact bytes.\n *\n * Resolution order:\n * 1. `BOURDON_CONFORMANCE_DIR` env var — the oracle checkout (parity tests +\n * oracle dev use this; highest priority so a build always asserts against\n * the live oracle).\n * 2. the fixtures BUNDLED in this package (`<pkg>/fixtures`, shipped in the\n * tarball) — what an installed `@getbourdon/conformance` consumer gets.\n * 3. the sibling Python checkout `../../bourdon/conformance` — dev fallback.\n *\n * The bundled copy is a vendored snapshot refreshed from the oracle by\n * `pnpm --filter @getbourdon/conformance sync-fixtures` (and in the release\n * workflow before publish), so the published package is self-contained.\n */\n\n// `import.meta.url` in ESM; esbuild empties it in the CJS bundle, where the\n// native `__dirname` global is the real directory — fall back to it.\ndeclare const __dirname: string | undefined;\nfunction moduleDir(): string {\n if (typeof import.meta !== \"undefined\" && import.meta.url) {\n return dirname(fileURLToPath(import.meta.url));\n }\n return typeof __dirname !== \"undefined\" ? __dirname : process.cwd();\n}\n\nexport interface RedactionSecretCase {\n /** Joined at load (`assembleSecret`) so no contiguous secret literal lands in git. */\n fragments: string[];\n expect_redacted: string;\n expect_contains_secret: boolean;\n}\n\nexport interface RedactionBenignCase {\n text: string;\n expect_redacted: string;\n expect_contains_secret: boolean;\n}\n\nexport interface RedactionBattery {\n redacted_sentinel: string;\n benign_limit: number;\n secrets: RedactionSecretCase[];\n benign: RedactionBenignCase[];\n}\n\nexport interface ConformanceFixtureMeta {\n path: string;\n sha256: string;\n producer: string;\n}\n\nexport interface ConformanceManifest {\n conformance_version: string;\n produced_against: { bourdon_version: string };\n fixtures: ConformanceFixtureMeta[];\n}\n\nexport function conformanceDir(): string {\n const override = process.env.BOURDON_CONFORMANCE_DIR;\n if (override) return override;\n // Bundled snapshot: <pkg>/fixtures, one level up from src/ or dist/.\n const bundled = resolve(moduleDir(), \"..\", \"fixtures\");\n if (existsSync(resolve(bundled, \"manifest.json\"))) return bundled;\n // Dev fallback: the sibling Python oracle checkout.\n return resolve(process.cwd(), \"..\", \"..\", \"bourdon\", \"conformance\");\n}\n\nfunction loadJson<T>(name: string): T {\n return JSON.parse(readFileSync(resolve(conformanceDir(), name), \"utf8\")) as T;\n}\n\nexport function loadManifest(): ConformanceManifest {\n return loadJson<ConformanceManifest>(\"manifest.json\");\n}\n\nexport function loadRedactionBattery(): RedactionBattery {\n return loadJson<RedactionBattery>(\"redaction_battery.json\");\n}\n\n/** Reconstruct a secret case's runtime string from its fragments. */\nexport function assembleSecret(secret: RedactionSecretCase): string {\n return secret.fragments.join(\"\");\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,qBAAyC;AACzC,uBAAiC;AACjC,sBAA8B;AAF9B;AAyBA,SAAS,YAAoB;AAC3B,MAAI,OAAO,gBAAgB,eAAe,YAAY,KAAK;AACzD,eAAO,8BAAQ,+BAAc,YAAY,GAAG,CAAC;AAAA,EAC/C;AACA,SAAO,OAAO,cAAc,cAAc,YAAY,QAAQ,IAAI;AACpE;AAkCO,SAAS,iBAAyB;AACvC,QAAM,WAAW,QAAQ,IAAI;AAC7B,MAAI,SAAU,QAAO;AAErB,QAAM,cAAU,0BAAQ,UAAU,GAAG,MAAM,UAAU;AACrD,UAAI,+BAAW,0BAAQ,SAAS,eAAe,CAAC,EAAG,QAAO;AAE1D,aAAO,0BAAQ,QAAQ,IAAI,GAAG,MAAM,MAAM,WAAW,aAAa;AACpE;AAEA,SAAS,SAAY,MAAiB;AACpC,SAAO,KAAK,UAAM,iCAAa,0BAAQ,eAAe,GAAG,IAAI,GAAG,MAAM,CAAC;AACzE;AAEO,SAAS,eAAoC;AAClD,SAAO,SAA8B,eAAe;AACtD;AAEO,SAAS,uBAAyC;AACvD,SAAO,SAA2B,wBAAwB;AAC5D;AAGO,SAAS,eAAe,QAAqC;AAClE,SAAO,OAAO,UAAU,KAAK,EAAE;AACjC;","names":[]}
1
+ {"version":3,"sources":["../src/index.ts"],"sourcesContent":["import { createHash } from \"node:crypto\";\nimport { existsSync, readFileSync } from \"node:fs\";\nimport { dirname, resolve } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\n\n/**\n * Typed loaders for the language-neutral parity fixtures produced by the Python\n * oracle (`~/repos/bourdon/tools/gen_conformance.py`). Python is the source of\n * truth; the @getbourdon/* TypeScript mirror asserts against these exact bytes.\n *\n * Resolution order:\n * 1. `BOURDON_CONFORMANCE_DIR` env var — the oracle checkout (parity tests +\n * oracle dev use this; highest priority so a build always asserts against\n * the live oracle).\n * 2. the fixtures BUNDLED in this package (`<pkg>/fixtures`, shipped in the\n * tarball) — what an installed `@getbourdon/conformance` consumer gets.\n * 3. the sibling Python checkout `../../bourdon/conformance` — dev fallback.\n *\n * The bundled copy is a vendored snapshot refreshed from the oracle by\n * `pnpm --filter @getbourdon/conformance sync-fixtures` (and in the release\n * workflow before publish), so the published package is self-contained.\n */\n\n// `import.meta.url` in ESM; esbuild empties it in the CJS bundle, where the\n// native `__dirname` global is the real directory — fall back to it.\ndeclare const __dirname: string | undefined;\nfunction moduleDir(): string {\n if (typeof import.meta !== \"undefined\" && import.meta.url) {\n return dirname(fileURLToPath(import.meta.url));\n }\n return typeof __dirname !== \"undefined\" ? __dirname : process.cwd();\n}\n\nexport interface RedactionSecretCase {\n /** Joined at load (`assembleSecret`) so no contiguous secret literal lands in git. */\n fragments: string[];\n expect_redacted: string;\n expect_contains_secret: boolean;\n}\n\nexport interface RedactionBenignCase {\n text: string;\n expect_redacted: string;\n expect_contains_secret: boolean;\n}\n\nexport interface RedactionBattery {\n redacted_sentinel: string;\n benign_limit: number;\n secrets: RedactionSecretCase[];\n benign: RedactionBenignCase[];\n}\n\nexport interface ConformanceFixtureMeta {\n path: string;\n sha256: string;\n producer: string;\n}\n\nexport interface ConformanceManifest {\n conformance_version: string;\n produced_against: { bourdon_version: string };\n fixtures: ConformanceFixtureMeta[];\n}\n\nexport function conformanceDir(): string {\n const override = process.env.BOURDON_CONFORMANCE_DIR;\n if (override) return override;\n // Bundled snapshot: <pkg>/fixtures, one level up from src/ or dist/.\n const bundled = resolve(moduleDir(), \"..\", \"fixtures\");\n if (existsSync(resolve(bundled, \"manifest.json\"))) return bundled;\n // Dev fallback: the sibling Python oracle checkout.\n return resolve(process.cwd(), \"..\", \"..\", \"bourdon\", \"conformance\");\n}\n\nfunction loadJson<T>(name: string): T {\n return JSON.parse(readFileSync(resolve(conformanceDir(), name), \"utf8\")) as T;\n}\n\nexport function loadManifest(): ConformanceManifest {\n return loadJson<ConformanceManifest>(\"manifest.json\");\n}\n\nexport interface FixturePin {\n conformance_version: string;\n manifest_sha256: string;\n}\n\n/** The recorded fixture pin committed beside this package: which contract\n * version the vendored snapshot is, and the sha256 the manifest must hash to. */\nexport function loadPin(): FixturePin {\n return JSON.parse(\n readFileSync(resolve(moduleDir(), \"..\", \"fixtures.pin.json\"), \"utf8\"),\n ) as FixturePin;\n}\n\n/** sha256 hex of one file's raw bytes. */\nexport function sha256File(path: string): string {\n return createHash(\"sha256\").update(readFileSync(path)).digest(\"hex\");\n}\n\nexport interface FixtureMismatch {\n path: string;\n expected: string;\n actual: string;\n}\n\n/** Verify every fixture in `dir` against the sha256 its manifest stamps.\n * Returns the mismatches — an empty array is the only passing result. The\n * same routine backs the parity gate AND its mutation test, so the check\n * that guards releases is itself provably able to fail. */\nexport function verifyFixtureHashes(dir: string = conformanceDir()): FixtureMismatch[] {\n const manifest = JSON.parse(\n readFileSync(resolve(dir, \"manifest.json\"), \"utf8\"),\n ) as ConformanceManifest;\n const mismatches: FixtureMismatch[] = [];\n for (const fixture of manifest.fixtures) {\n const actual = sha256File(resolve(dir, fixture.path));\n if (actual !== fixture.sha256) {\n mismatches.push({ path: fixture.path, expected: fixture.sha256, actual });\n }\n }\n return mismatches;\n}\n\nexport function loadRedactionBattery(): RedactionBattery {\n return loadJson<RedactionBattery>(\"redaction_battery.json\");\n}\n\n/** Reconstruct a secret case's runtime string from its fragments. */\nexport function assembleSecret(secret: RedactionSecretCase): string {\n return secret.fragments.join(\"\");\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,yBAA2B;AAC3B,qBAAyC;AACzC,uBAAiC;AACjC,sBAA8B;AAH9B;AA0BA,SAAS,YAAoB;AAC3B,MAAI,OAAO,gBAAgB,eAAe,YAAY,KAAK;AACzD,eAAO,8BAAQ,+BAAc,YAAY,GAAG,CAAC;AAAA,EAC/C;AACA,SAAO,OAAO,cAAc,cAAc,YAAY,QAAQ,IAAI;AACpE;AAkCO,SAAS,iBAAyB;AACvC,QAAM,WAAW,QAAQ,IAAI;AAC7B,MAAI,SAAU,QAAO;AAErB,QAAM,cAAU,0BAAQ,UAAU,GAAG,MAAM,UAAU;AACrD,UAAI,+BAAW,0BAAQ,SAAS,eAAe,CAAC,EAAG,QAAO;AAE1D,aAAO,0BAAQ,QAAQ,IAAI,GAAG,MAAM,MAAM,WAAW,aAAa;AACpE;AAEA,SAAS,SAAY,MAAiB;AACpC,SAAO,KAAK,UAAM,iCAAa,0BAAQ,eAAe,GAAG,IAAI,GAAG,MAAM,CAAC;AACzE;AAEO,SAAS,eAAoC;AAClD,SAAO,SAA8B,eAAe;AACtD;AASO,SAAS,UAAsB;AACpC,SAAO,KAAK;AAAA,QACV,iCAAa,0BAAQ,UAAU,GAAG,MAAM,mBAAmB,GAAG,MAAM;AAAA,EACtE;AACF;AAGO,SAAS,WAAW,MAAsB;AAC/C,aAAO,+BAAW,QAAQ,EAAE,WAAO,6BAAa,IAAI,CAAC,EAAE,OAAO,KAAK;AACrE;AAYO,SAAS,oBAAoB,MAAc,eAAe,GAAsB;AACrF,QAAM,WAAW,KAAK;AAAA,QACpB,iCAAa,0BAAQ,KAAK,eAAe,GAAG,MAAM;AAAA,EACpD;AACA,QAAM,aAAgC,CAAC;AACvC,aAAW,WAAW,SAAS,UAAU;AACvC,UAAM,SAAS,eAAW,0BAAQ,KAAK,QAAQ,IAAI,CAAC;AACpD,QAAI,WAAW,QAAQ,QAAQ;AAC7B,iBAAW,KAAK,EAAE,MAAM,QAAQ,MAAM,UAAU,QAAQ,QAAQ,OAAO,CAAC;AAAA,IAC1E;AAAA,EACF;AACA,SAAO;AACT;AAEO,SAAS,uBAAyC;AACvD,SAAO,SAA2B,wBAAwB;AAC5D;AAGO,SAAS,eAAe,QAAqC;AAClE,SAAO,OAAO,UAAU,KAAK,EAAE;AACjC;","names":[]}
package/dist/index.d.cts CHANGED
@@ -29,8 +29,27 @@ interface ConformanceManifest {
29
29
  }
30
30
  declare function conformanceDir(): string;
31
31
  declare function loadManifest(): ConformanceManifest;
32
+ interface FixturePin {
33
+ conformance_version: string;
34
+ manifest_sha256: string;
35
+ }
36
+ /** The recorded fixture pin committed beside this package: which contract
37
+ * version the vendored snapshot is, and the sha256 the manifest must hash to. */
38
+ declare function loadPin(): FixturePin;
39
+ /** sha256 hex of one file's raw bytes. */
40
+ declare function sha256File(path: string): string;
41
+ interface FixtureMismatch {
42
+ path: string;
43
+ expected: string;
44
+ actual: string;
45
+ }
46
+ /** Verify every fixture in `dir` against the sha256 its manifest stamps.
47
+ * Returns the mismatches — an empty array is the only passing result. The
48
+ * same routine backs the parity gate AND its mutation test, so the check
49
+ * that guards releases is itself provably able to fail. */
50
+ declare function verifyFixtureHashes(dir?: string): FixtureMismatch[];
32
51
  declare function loadRedactionBattery(): RedactionBattery;
33
52
  /** Reconstruct a secret case's runtime string from its fragments. */
34
53
  declare function assembleSecret(secret: RedactionSecretCase): string;
35
54
 
36
- export { type ConformanceFixtureMeta, type ConformanceManifest, type RedactionBattery, type RedactionBenignCase, type RedactionSecretCase, assembleSecret, conformanceDir, loadManifest, loadRedactionBattery };
55
+ export { type ConformanceFixtureMeta, type ConformanceManifest, type FixtureMismatch, type FixturePin, type RedactionBattery, type RedactionBenignCase, type RedactionSecretCase, assembleSecret, conformanceDir, loadManifest, loadPin, loadRedactionBattery, sha256File, verifyFixtureHashes };
package/dist/index.d.ts CHANGED
@@ -1,36 +1,53 @@
1
- interface RedactionSecretCase {
1
+ export interface RedactionSecretCase {
2
2
  /** Joined at load (`assembleSecret`) so no contiguous secret literal lands in git. */
3
3
  fragments: string[];
4
4
  expect_redacted: string;
5
5
  expect_contains_secret: boolean;
6
6
  }
7
- interface RedactionBenignCase {
7
+ export interface RedactionBenignCase {
8
8
  text: string;
9
9
  expect_redacted: string;
10
10
  expect_contains_secret: boolean;
11
11
  }
12
- interface RedactionBattery {
12
+ export interface RedactionBattery {
13
13
  redacted_sentinel: string;
14
14
  benign_limit: number;
15
15
  secrets: RedactionSecretCase[];
16
16
  benign: RedactionBenignCase[];
17
17
  }
18
- interface ConformanceFixtureMeta {
18
+ export interface ConformanceFixtureMeta {
19
19
  path: string;
20
20
  sha256: string;
21
21
  producer: string;
22
22
  }
23
- interface ConformanceManifest {
23
+ export interface ConformanceManifest {
24
24
  conformance_version: string;
25
25
  produced_against: {
26
26
  bourdon_version: string;
27
27
  };
28
28
  fixtures: ConformanceFixtureMeta[];
29
29
  }
30
- declare function conformanceDir(): string;
31
- declare function loadManifest(): ConformanceManifest;
32
- declare function loadRedactionBattery(): RedactionBattery;
30
+ export declare function conformanceDir(): string;
31
+ export declare function loadManifest(): ConformanceManifest;
32
+ export interface FixturePin {
33
+ conformance_version: string;
34
+ manifest_sha256: string;
35
+ }
36
+ /** The recorded fixture pin committed beside this package: which contract
37
+ * version the vendored snapshot is, and the sha256 the manifest must hash to. */
38
+ export declare function loadPin(): FixturePin;
39
+ /** sha256 hex of one file's raw bytes. */
40
+ export declare function sha256File(path: string): string;
41
+ export interface FixtureMismatch {
42
+ path: string;
43
+ expected: string;
44
+ actual: string;
45
+ }
46
+ /** Verify every fixture in `dir` against the sha256 its manifest stamps.
47
+ * Returns the mismatches — an empty array is the only passing result. The
48
+ * same routine backs the parity gate AND its mutation test, so the check
49
+ * that guards releases is itself provably able to fail. */
50
+ export declare function verifyFixtureHashes(dir?: string): FixtureMismatch[];
51
+ export declare function loadRedactionBattery(): RedactionBattery;
33
52
  /** Reconstruct a secret case's runtime string from its fragments. */
34
- declare function assembleSecret(secret: RedactionSecretCase): string;
35
-
36
- export { type ConformanceFixtureMeta, type ConformanceManifest, type RedactionBattery, type RedactionBenignCase, type RedactionSecretCase, assembleSecret, conformanceDir, loadManifest, loadRedactionBattery };
53
+ export declare function assembleSecret(secret: RedactionSecretCase): string;
package/dist/index.js CHANGED
@@ -1,36 +1,58 @@
1
- // src/index.ts
2
- import { existsSync, readFileSync } from "fs";
3
- import { dirname, resolve } from "path";
4
- import { fileURLToPath } from "url";
1
+ import { createHash } from "node:crypto";
2
+ import { existsSync, readFileSync } from "node:fs";
3
+ import { dirname, resolve } from "node:path";
4
+ import { fileURLToPath } from "node:url";
5
5
  function moduleDir() {
6
- if (typeof import.meta !== "undefined" && import.meta.url) {
7
- return dirname(fileURLToPath(import.meta.url));
8
- }
9
- return typeof __dirname !== "undefined" ? __dirname : process.cwd();
10
- }
11
- function conformanceDir() {
12
- const override = process.env.BOURDON_CONFORMANCE_DIR;
13
- if (override) return override;
14
- const bundled = resolve(moduleDir(), "..", "fixtures");
15
- if (existsSync(resolve(bundled, "manifest.json"))) return bundled;
16
- return resolve(process.cwd(), "..", "..", "bourdon", "conformance");
6
+ if (typeof import.meta !== "undefined" && import.meta.url) {
7
+ return dirname(fileURLToPath(import.meta.url));
8
+ }
9
+ return typeof __dirname !== "undefined" ? __dirname : process.cwd();
10
+ }
11
+ export function conformanceDir() {
12
+ const override = process.env.BOURDON_CONFORMANCE_DIR;
13
+ if (override)
14
+ return override;
15
+ // Bundled snapshot: <pkg>/fixtures, one level up from src/ or dist/.
16
+ const bundled = resolve(moduleDir(), "..", "fixtures");
17
+ if (existsSync(resolve(bundled, "manifest.json")))
18
+ return bundled;
19
+ // Dev fallback: the sibling Python oracle checkout.
20
+ return resolve(process.cwd(), "..", "..", "bourdon", "conformance");
17
21
  }
18
22
  function loadJson(name) {
19
- return JSON.parse(readFileSync(resolve(conformanceDir(), name), "utf8"));
23
+ return JSON.parse(readFileSync(resolve(conformanceDir(), name), "utf8"));
24
+ }
25
+ export function loadManifest() {
26
+ return loadJson("manifest.json");
27
+ }
28
+ /** The recorded fixture pin committed beside this package: which contract
29
+ * version the vendored snapshot is, and the sha256 the manifest must hash to. */
30
+ export function loadPin() {
31
+ return JSON.parse(readFileSync(resolve(moduleDir(), "..", "fixtures.pin.json"), "utf8"));
32
+ }
33
+ /** sha256 hex of one file's raw bytes. */
34
+ export function sha256File(path) {
35
+ return createHash("sha256").update(readFileSync(path)).digest("hex");
20
36
  }
21
- function loadManifest() {
22
- return loadJson("manifest.json");
37
+ /** Verify every fixture in `dir` against the sha256 its manifest stamps.
38
+ * Returns the mismatches — an empty array is the only passing result. The
39
+ * same routine backs the parity gate AND its mutation test, so the check
40
+ * that guards releases is itself provably able to fail. */
41
+ export function verifyFixtureHashes(dir = conformanceDir()) {
42
+ const manifest = JSON.parse(readFileSync(resolve(dir, "manifest.json"), "utf8"));
43
+ const mismatches = [];
44
+ for (const fixture of manifest.fixtures) {
45
+ const actual = sha256File(resolve(dir, fixture.path));
46
+ if (actual !== fixture.sha256) {
47
+ mismatches.push({ path: fixture.path, expected: fixture.sha256, actual });
48
+ }
49
+ }
50
+ return mismatches;
23
51
  }
24
- function loadRedactionBattery() {
25
- return loadJson("redaction_battery.json");
52
+ export function loadRedactionBattery() {
53
+ return loadJson("redaction_battery.json");
26
54
  }
27
- function assembleSecret(secret) {
28
- return secret.fragments.join("");
55
+ /** Reconstruct a secret case's runtime string from its fragments. */
56
+ export function assembleSecret(secret) {
57
+ return secret.fragments.join("");
29
58
  }
30
- export {
31
- assembleSecret,
32
- conformanceDir,
33
- loadManifest,
34
- loadRedactionBattery
35
- };
36
- //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts"],"sourcesContent":["import { existsSync, readFileSync } from \"node:fs\";\nimport { dirname, resolve } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\n\n/**\n * Typed loaders for the language-neutral parity fixtures produced by the Python\n * oracle (`~/repos/bourdon/tools/gen_conformance.py`). Python is the source of\n * truth; the @getbourdon/* TypeScript mirror asserts against these exact bytes.\n *\n * Resolution order:\n * 1. `BOURDON_CONFORMANCE_DIR` env var — the oracle checkout (parity tests +\n * oracle dev use this; highest priority so a build always asserts against\n * the live oracle).\n * 2. the fixtures BUNDLED in this package (`<pkg>/fixtures`, shipped in the\n * tarball) — what an installed `@getbourdon/conformance` consumer gets.\n * 3. the sibling Python checkout `../../bourdon/conformance` — dev fallback.\n *\n * The bundled copy is a vendored snapshot refreshed from the oracle by\n * `pnpm --filter @getbourdon/conformance sync-fixtures` (and in the release\n * workflow before publish), so the published package is self-contained.\n */\n\n// `import.meta.url` in ESM; esbuild empties it in the CJS bundle, where the\n// native `__dirname` global is the real directory — fall back to it.\ndeclare const __dirname: string | undefined;\nfunction moduleDir(): string {\n if (typeof import.meta !== \"undefined\" && import.meta.url) {\n return dirname(fileURLToPath(import.meta.url));\n }\n return typeof __dirname !== \"undefined\" ? __dirname : process.cwd();\n}\n\nexport interface RedactionSecretCase {\n /** Joined at load (`assembleSecret`) so no contiguous secret literal lands in git. */\n fragments: string[];\n expect_redacted: string;\n expect_contains_secret: boolean;\n}\n\nexport interface RedactionBenignCase {\n text: string;\n expect_redacted: string;\n expect_contains_secret: boolean;\n}\n\nexport interface RedactionBattery {\n redacted_sentinel: string;\n benign_limit: number;\n secrets: RedactionSecretCase[];\n benign: RedactionBenignCase[];\n}\n\nexport interface ConformanceFixtureMeta {\n path: string;\n sha256: string;\n producer: string;\n}\n\nexport interface ConformanceManifest {\n conformance_version: string;\n produced_against: { bourdon_version: string };\n fixtures: ConformanceFixtureMeta[];\n}\n\nexport function conformanceDir(): string {\n const override = process.env.BOURDON_CONFORMANCE_DIR;\n if (override) return override;\n // Bundled snapshot: <pkg>/fixtures, one level up from src/ or dist/.\n const bundled = resolve(moduleDir(), \"..\", \"fixtures\");\n if (existsSync(resolve(bundled, \"manifest.json\"))) return bundled;\n // Dev fallback: the sibling Python oracle checkout.\n return resolve(process.cwd(), \"..\", \"..\", \"bourdon\", \"conformance\");\n}\n\nfunction loadJson<T>(name: string): T {\n return JSON.parse(readFileSync(resolve(conformanceDir(), name), \"utf8\")) as T;\n}\n\nexport function loadManifest(): ConformanceManifest {\n return loadJson<ConformanceManifest>(\"manifest.json\");\n}\n\nexport function loadRedactionBattery(): RedactionBattery {\n return loadJson<RedactionBattery>(\"redaction_battery.json\");\n}\n\n/** Reconstruct a secret case's runtime string from its fragments. */\nexport function assembleSecret(secret: RedactionSecretCase): string {\n return secret.fragments.join(\"\");\n}\n"],"mappings":";AAAA,SAAS,YAAY,oBAAoB;AACzC,SAAS,SAAS,eAAe;AACjC,SAAS,qBAAqB;AAuB9B,SAAS,YAAoB;AAC3B,MAAI,OAAO,gBAAgB,eAAe,YAAY,KAAK;AACzD,WAAO,QAAQ,cAAc,YAAY,GAAG,CAAC;AAAA,EAC/C;AACA,SAAO,OAAO,cAAc,cAAc,YAAY,QAAQ,IAAI;AACpE;AAkCO,SAAS,iBAAyB;AACvC,QAAM,WAAW,QAAQ,IAAI;AAC7B,MAAI,SAAU,QAAO;AAErB,QAAM,UAAU,QAAQ,UAAU,GAAG,MAAM,UAAU;AACrD,MAAI,WAAW,QAAQ,SAAS,eAAe,CAAC,EAAG,QAAO;AAE1D,SAAO,QAAQ,QAAQ,IAAI,GAAG,MAAM,MAAM,WAAW,aAAa;AACpE;AAEA,SAAS,SAAY,MAAiB;AACpC,SAAO,KAAK,MAAM,aAAa,QAAQ,eAAe,GAAG,IAAI,GAAG,MAAM,CAAC;AACzE;AAEO,SAAS,eAAoC;AAClD,SAAO,SAA8B,eAAe;AACtD;AAEO,SAAS,uBAAyC;AACvD,SAAO,SAA2B,wBAAwB;AAC5D;AAGO,SAAS,eAAe,QAAqC;AAClE,SAAO,OAAO,UAAU,KAAK,EAAE;AACjC;","names":[]}
1
+ {"version":3,"sources":["../src/index.ts"],"sourcesContent":["import { createHash } from \"node:crypto\";\nimport { existsSync, readFileSync } from \"node:fs\";\nimport { dirname, resolve } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\n\n/**\n * Typed loaders for the language-neutral parity fixtures produced by the Python\n * oracle (`~/repos/bourdon/tools/gen_conformance.py`). Python is the source of\n * truth; the @getbourdon/* TypeScript mirror asserts against these exact bytes.\n *\n * Resolution order:\n * 1. `BOURDON_CONFORMANCE_DIR` env var — the oracle checkout (parity tests +\n * oracle dev use this; highest priority so a build always asserts against\n * the live oracle).\n * 2. the fixtures BUNDLED in this package (`<pkg>/fixtures`, shipped in the\n * tarball) — what an installed `@getbourdon/conformance` consumer gets.\n * 3. the sibling Python checkout `../../bourdon/conformance` — dev fallback.\n *\n * The bundled copy is a vendored snapshot refreshed from the oracle by\n * `pnpm --filter @getbourdon/conformance sync-fixtures` (and in the release\n * workflow before publish), so the published package is self-contained.\n */\n\n// `import.meta.url` in ESM; esbuild empties it in the CJS bundle, where the\n// native `__dirname` global is the real directory — fall back to it.\ndeclare const __dirname: string | undefined;\nfunction moduleDir(): string {\n if (typeof import.meta !== \"undefined\" && import.meta.url) {\n return dirname(fileURLToPath(import.meta.url));\n }\n return typeof __dirname !== \"undefined\" ? __dirname : process.cwd();\n}\n\nexport interface RedactionSecretCase {\n /** Joined at load (`assembleSecret`) so no contiguous secret literal lands in git. */\n fragments: string[];\n expect_redacted: string;\n expect_contains_secret: boolean;\n}\n\nexport interface RedactionBenignCase {\n text: string;\n expect_redacted: string;\n expect_contains_secret: boolean;\n}\n\nexport interface RedactionBattery {\n redacted_sentinel: string;\n benign_limit: number;\n secrets: RedactionSecretCase[];\n benign: RedactionBenignCase[];\n}\n\nexport interface ConformanceFixtureMeta {\n path: string;\n sha256: string;\n producer: string;\n}\n\nexport interface ConformanceManifest {\n conformance_version: string;\n produced_against: { bourdon_version: string };\n fixtures: ConformanceFixtureMeta[];\n}\n\nexport function conformanceDir(): string {\n const override = process.env.BOURDON_CONFORMANCE_DIR;\n if (override) return override;\n // Bundled snapshot: <pkg>/fixtures, one level up from src/ or dist/.\n const bundled = resolve(moduleDir(), \"..\", \"fixtures\");\n if (existsSync(resolve(bundled, \"manifest.json\"))) return bundled;\n // Dev fallback: the sibling Python oracle checkout.\n return resolve(process.cwd(), \"..\", \"..\", \"bourdon\", \"conformance\");\n}\n\nfunction loadJson<T>(name: string): T {\n return JSON.parse(readFileSync(resolve(conformanceDir(), name), \"utf8\")) as T;\n}\n\nexport function loadManifest(): ConformanceManifest {\n return loadJson<ConformanceManifest>(\"manifest.json\");\n}\n\nexport interface FixturePin {\n conformance_version: string;\n manifest_sha256: string;\n}\n\n/** The recorded fixture pin committed beside this package: which contract\n * version the vendored snapshot is, and the sha256 the manifest must hash to. */\nexport function loadPin(): FixturePin {\n return JSON.parse(\n readFileSync(resolve(moduleDir(), \"..\", \"fixtures.pin.json\"), \"utf8\"),\n ) as FixturePin;\n}\n\n/** sha256 hex of one file's raw bytes. */\nexport function sha256File(path: string): string {\n return createHash(\"sha256\").update(readFileSync(path)).digest(\"hex\");\n}\n\nexport interface FixtureMismatch {\n path: string;\n expected: string;\n actual: string;\n}\n\n/** Verify every fixture in `dir` against the sha256 its manifest stamps.\n * Returns the mismatches — an empty array is the only passing result. The\n * same routine backs the parity gate AND its mutation test, so the check\n * that guards releases is itself provably able to fail. */\nexport function verifyFixtureHashes(dir: string = conformanceDir()): FixtureMismatch[] {\n const manifest = JSON.parse(\n readFileSync(resolve(dir, \"manifest.json\"), \"utf8\"),\n ) as ConformanceManifest;\n const mismatches: FixtureMismatch[] = [];\n for (const fixture of manifest.fixtures) {\n const actual = sha256File(resolve(dir, fixture.path));\n if (actual !== fixture.sha256) {\n mismatches.push({ path: fixture.path, expected: fixture.sha256, actual });\n }\n }\n return mismatches;\n}\n\nexport function loadRedactionBattery(): RedactionBattery {\n return loadJson<RedactionBattery>(\"redaction_battery.json\");\n}\n\n/** Reconstruct a secret case's runtime string from its fragments. */\nexport function assembleSecret(secret: RedactionSecretCase): string {\n return secret.fragments.join(\"\");\n}\n"],"mappings":";AAAA,SAAS,kBAAkB;AAC3B,SAAS,YAAY,oBAAoB;AACzC,SAAS,SAAS,eAAe;AACjC,SAAS,qBAAqB;AAuB9B,SAAS,YAAoB;AAC3B,MAAI,OAAO,gBAAgB,eAAe,YAAY,KAAK;AACzD,WAAO,QAAQ,cAAc,YAAY,GAAG,CAAC;AAAA,EAC/C;AACA,SAAO,OAAO,cAAc,cAAc,YAAY,QAAQ,IAAI;AACpE;AAkCO,SAAS,iBAAyB;AACvC,QAAM,WAAW,QAAQ,IAAI;AAC7B,MAAI,SAAU,QAAO;AAErB,QAAM,UAAU,QAAQ,UAAU,GAAG,MAAM,UAAU;AACrD,MAAI,WAAW,QAAQ,SAAS,eAAe,CAAC,EAAG,QAAO;AAE1D,SAAO,QAAQ,QAAQ,IAAI,GAAG,MAAM,MAAM,WAAW,aAAa;AACpE;AAEA,SAAS,SAAY,MAAiB;AACpC,SAAO,KAAK,MAAM,aAAa,QAAQ,eAAe,GAAG,IAAI,GAAG,MAAM,CAAC;AACzE;AAEO,SAAS,eAAoC;AAClD,SAAO,SAA8B,eAAe;AACtD;AASO,SAAS,UAAsB;AACpC,SAAO,KAAK;AAAA,IACV,aAAa,QAAQ,UAAU,GAAG,MAAM,mBAAmB,GAAG,MAAM;AAAA,EACtE;AACF;AAGO,SAAS,WAAW,MAAsB;AAC/C,SAAO,WAAW,QAAQ,EAAE,OAAO,aAAa,IAAI,CAAC,EAAE,OAAO,KAAK;AACrE;AAYO,SAAS,oBAAoB,MAAc,eAAe,GAAsB;AACrF,QAAM,WAAW,KAAK;AAAA,IACpB,aAAa,QAAQ,KAAK,eAAe,GAAG,MAAM;AAAA,EACpD;AACA,QAAM,aAAgC,CAAC;AACvC,aAAW,WAAW,SAAS,UAAU;AACvC,UAAM,SAAS,WAAW,QAAQ,KAAK,QAAQ,IAAI,CAAC;AACpD,QAAI,WAAW,QAAQ,QAAQ;AAC7B,iBAAW,KAAK,EAAE,MAAM,QAAQ,MAAM,UAAU,QAAQ,QAAQ,OAAO,CAAC;AAAA,IAC1E;AAAA,EACF;AACA,SAAO;AACT;AAEO,SAAS,uBAAyC;AACvD,SAAO,SAA2B,wBAAwB;AAC5D;AAGO,SAAS,eAAe,QAAqC;AAClE,SAAO,OAAO,UAAU,KAAK,EAAE;AACjC;","names":[]}
@@ -19,7 +19,7 @@ uncommitted diff (`git diff --exit-code -- conformance/`).
19
19
  python tools/gen_conformance.py # rewrites conformance/ + manifest.json
20
20
  ```
21
21
 
22
- After changing a pattern in `bourdon.core.redaction` (or any oracle), regenerate, review the
22
+ After changing a pattern in `core.redaction` (or any oracle), regenerate, review the
23
23
  diff, and bump `conformance_version` in `tools/gen_conformance.py` (patch = added cases,
24
24
  minor = new family, major = a changed expected-output = a reviewed behavior change).
25
25
 
@@ -44,8 +44,16 @@ dict. `on_disk/` holds Python-written artifacts the TS side must parse identical
44
44
  never a contiguous literal), and an append-only audit log produced by the real `record()` with frozen
45
45
  timestamps. Both pytest (`tests/test_federation_conformance.py`) and the TS vitest suite assert these.
46
46
 
47
- The `mcp_snapshots/` family pins the **JSON-in-TextContent wire contract** for all 12 L6
48
- MCP tools. Each `*.res.json` is the live tool's payload (as `RemoteL6Client` recovers it:
47
+ The `mcp_snapshots/` family pins the **JSON-in-TextContent wire contract** for **every**
48
+ tool `create_l6_server` registers (15 as of conformance 1.11.0) **plus** the three
49
+ `agent-library://` resource response contracts (`resource_agents`, `resource_agent_memory`,
50
+ `resource_entity` — snapshotted first, over the pure seed view). The generator refuses to
51
+ emit when a registered tool or resource lacks a snapshot case, so the surface stays
52
+ complete by construction. The three version-history tools (`list_memory_versions`,
53
+ `explain_memory_change`, `rollback_agent_memory`) are driven over a deterministic
54
+ version-history seed described in `mcp_snapshots/seed_library.json` (fixed prior-state
55
+ bytes + a fixed-ts provenance entry); `rollback_agent_memory` runs last because it
56
+ restores that seeded prior state. Each `*.res.json` is the live tool's payload (as `RemoteL6Client` recovers it:
49
57
  `json.loads` of the single `TextContent.text` = `json.dumps(payload)`) run through one codified
50
58
  NORMALIZER — sort object keys, round floats to 4dp, drop null/empty-list fields (to_dict
51
59
  omission), freeze `last_updated`/`generated_at`/`generated_from`/`path`, drop latency fields,
@@ -0,0 +1,14 @@
1
+ {
2
+ "spec_version": "0.1",
3
+ "agent": {
4
+ "id": "alpha-agent",
5
+ "type": "note-capture"
6
+ },
7
+ "last_updated": "2026-06-29T12:00:00+00:00",
8
+ "known_entities": [
9
+ {
10
+ "name": "X",
11
+ "valid_from": "2026-13-05"
12
+ }
13
+ ]
14
+ }
@@ -70,6 +70,58 @@
70
70
  "message": "'name' is a required property"
71
71
  }
72
72
  ]
73
+ },
74
+ "session-impossible-calendar-date.json": {
75
+ "valid": false,
76
+ "expected": {
77
+ "keyword": "pattern",
78
+ "instancePath": "/recent_sessions/0/date"
79
+ },
80
+ "errors": [
81
+ {
82
+ "keyword": "anyOf",
83
+ "instancePath": "/recent_sessions/0/date",
84
+ "message": "'2026-99-99' is not valid under any of the given schemas"
85
+ },
86
+ {
87
+ "keyword": "pattern",
88
+ "instancePath": "/recent_sessions/0/date",
89
+ "message": "'2026-99-99' does not match '^(\\\\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12]\\\\d|3[01]))?$'"
90
+ }
91
+ ]
92
+ },
93
+ "session-impossible-feb-30.json": {
94
+ "valid": false,
95
+ "expected": {
96
+ "keyword": "anyOf",
97
+ "instancePath": "/recent_sessions/0/date"
98
+ },
99
+ "errors": [
100
+ {
101
+ "keyword": "anyOf",
102
+ "instancePath": "/recent_sessions/0/date",
103
+ "message": "'2026-02-30' is not valid under any of the given schemas"
104
+ }
105
+ ]
106
+ },
107
+ "entity-impossible-calendar-date.json": {
108
+ "valid": false,
109
+ "expected": {
110
+ "keyword": "format",
111
+ "instancePath": "/known_entities/0/valid_from"
112
+ },
113
+ "errors": [
114
+ {
115
+ "keyword": "format",
116
+ "instancePath": "/known_entities/0/valid_from",
117
+ "message": "'2026-13-05' is not a 'date'"
118
+ },
119
+ {
120
+ "keyword": "pattern",
121
+ "instancePath": "/known_entities/0/valid_from",
122
+ "message": "'2026-13-05' does not match '^\\\\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12]\\\\d|3[01])$'"
123
+ }
124
+ ]
73
125
  }
74
126
  }
75
127
  }
@@ -0,0 +1,13 @@
1
+ {
2
+ "spec_version": "0.1",
3
+ "agent": {
4
+ "id": "alpha-agent",
5
+ "type": "note-capture"
6
+ },
7
+ "last_updated": "2026-06-29T12:00:00+00:00",
8
+ "recent_sessions": [
9
+ {
10
+ "date": "2026-99-99"
11
+ }
12
+ ]
13
+ }
@@ -0,0 +1,13 @@
1
+ {
2
+ "spec_version": "0.1",
3
+ "agent": {
4
+ "id": "alpha-agent",
5
+ "type": "note-capture"
6
+ },
7
+ "last_updated": "2026-06-29T12:00:00+00:00",
8
+ "recent_sessions": [
9
+ {
10
+ "date": "2026-02-30"
11
+ }
12
+ ]
13
+ }
@@ -0,0 +1,16 @@
1
+ {
2
+ "spec_version": "0.1",
3
+ "agent": {
4
+ "id": "alpha-agent",
5
+ "type": "note-capture"
6
+ },
7
+ "last_updated": "2026-06-29T12:00:00+00:00",
8
+ "recent_sessions": [
9
+ {
10
+ "date": "",
11
+ "key_actions": [
12
+ "undated native-store session"
13
+ ]
14
+ }
15
+ ]
16
+ }