circle-ir-ai 2.27.0 → 2.28.2

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 (71) hide show
  1. package/CHANGELOG.md +172 -0
  2. package/dist/agents/mastra/workflow.d.ts +15 -0
  3. package/dist/agents/mastra/workflow.d.ts.map +1 -1
  4. package/dist/agents/mastra/workflow.js +33 -12
  5. package/dist/agents/mastra/workflow.js.map +1 -1
  6. package/dist/cache/backend.d.ts +62 -10
  7. package/dist/cache/backend.d.ts.map +1 -1
  8. package/dist/cache/backend.js +20 -4
  9. package/dist/cache/backend.js.map +1 -1
  10. package/dist/cache/backends/index.d.ts +30 -18
  11. package/dist/cache/backends/index.d.ts.map +1 -1
  12. package/dist/cache/backends/index.js +37 -29
  13. package/dist/cache/backends/index.js.map +1 -1
  14. package/dist/cache/backends/layout.d.ts +31 -0
  15. package/dist/cache/backends/layout.d.ts.map +1 -0
  16. package/dist/cache/backends/layout.js +46 -0
  17. package/dist/cache/backends/layout.js.map +1 -0
  18. package/dist/cache/backends/local-fs.d.ts +14 -11
  19. package/dist/cache/backends/local-fs.d.ts.map +1 -1
  20. package/dist/cache/backends/local-fs.js +30 -18
  21. package/dist/cache/backends/local-fs.js.map +1 -1
  22. package/dist/cache/backends/memory.d.ts +11 -6
  23. package/dist/cache/backends/memory.d.ts.map +1 -1
  24. package/dist/cache/backends/memory.js +13 -5
  25. package/dist/cache/backends/memory.js.map +1 -1
  26. package/dist/cache/backends/r2.d.ts +17 -17
  27. package/dist/cache/backends/r2.d.ts.map +1 -1
  28. package/dist/cache/backends/r2.js +14 -16
  29. package/dist/cache/backends/r2.js.map +1 -1
  30. package/dist/cache/classification-cache.d.ts +76 -34
  31. package/dist/cache/classification-cache.d.ts.map +1 -1
  32. package/dist/cache/classification-cache.js +110 -58
  33. package/dist/cache/classification-cache.js.map +1 -1
  34. package/dist/cache/coordinate.d.ts +59 -0
  35. package/dist/cache/coordinate.d.ts.map +1 -0
  36. package/dist/cache/coordinate.js +240 -0
  37. package/dist/cache/coordinate.js.map +1 -0
  38. package/dist/cache/discovery-cache.d.ts +112 -36
  39. package/dist/cache/discovery-cache.d.ts.map +1 -1
  40. package/dist/cache/discovery-cache.js +163 -42
  41. package/dist/cache/discovery-cache.js.map +1 -1
  42. package/dist/cache/tree-cache.d.ts +48 -53
  43. package/dist/cache/tree-cache.d.ts.map +1 -1
  44. package/dist/cache/tree-cache.js +87 -72
  45. package/dist/cache/tree-cache.js.map +1 -1
  46. package/dist/cache/verify-cache.d.ts +26 -21
  47. package/dist/cache/verify-cache.d.ts.map +1 -1
  48. package/dist/cache/verify-cache.js +37 -29
  49. package/dist/cache/verify-cache.js.map +1 -1
  50. package/dist/llm/ax-client.d.ts +3 -16
  51. package/dist/llm/ax-client.d.ts.map +1 -1
  52. package/dist/llm/ax-client.js +49 -2
  53. package/dist/llm/ax-client.js.map +1 -1
  54. package/dist/llm/batch-classifier.d.ts.map +1 -1
  55. package/dist/llm/batch-classifier.js +1 -0
  56. package/dist/llm/batch-classifier.js.map +1 -1
  57. package/dist/llm/config.d.ts +34 -8
  58. package/dist/llm/config.d.ts.map +1 -1
  59. package/dist/llm/config.js +52 -12
  60. package/dist/llm/config.js.map +1 -1
  61. package/dist/llm/discovery.d.ts.map +1 -1
  62. package/dist/llm/discovery.js +50 -4
  63. package/dist/llm/discovery.js.map +1 -1
  64. package/dist/llm/verification.d.ts.map +1 -1
  65. package/dist/llm/verification.js +45 -1
  66. package/dist/llm/verification.js.map +1 -1
  67. package/dist/security-scan/scanner.d.ts +15 -0
  68. package/dist/security-scan/scanner.d.ts.map +1 -1
  69. package/dist/security-scan/scanner.js +34 -0
  70. package/dist/security-scan/scanner.js.map +1 -1
  71. package/package.json +2 -2
@@ -1,32 +1,44 @@
1
1
  /**
2
- * Cache backend factory (cognium-ai#158 Acceptance #4).
2
+ * Cache backend factory (cognium-ai#158).
3
3
  *
4
- * Selects a `CacheBackend` per cache-dir based on `LLM_CACHE_BACKEND`:
5
- * `local` (default) — `LocalFSBackend(cacheDir)`
4
+ * Selects a `CacheBackend` per namespace based on `LLM_CACHE_BACKEND`:
5
+ * `local` (default) — `LocalFSBackend(<cacheDir>/<namespace>)`
6
6
  * `memory` — `MemoryBackend()`
7
- * `r2` — `R2Backend({R2_ENDPOINT, R2_BUCKET, …})`
7
+ * `r2` — `R2Backend({prefix: <R2_PREFIX>/<namespace>, …})`
8
8
  *
9
- * For R2, the `cacheDir` is mapped to a stable sub-prefix so the three
10
- * caches (tree / verify / discovery) live under separate keyspaces in
11
- * a single bucket:
12
- * tree → `<R2_PREFIX>/tree/`
13
- * verify → `<R2_PREFIX>/verify/`
14
- * discovery → `<R2_PREFIX>/discovery/`
15
- * <other> → `<R2_PREFIX>/misc/`
9
+ * Each `ClassificationCache` (tree / verify / discovery) constructs ONE
10
+ * backend, scoped to its own namespace via the `namespace` arg. Inside
11
+ * the backend, the structured `CacheKey` is rendered to a path via
12
+ * `renderObjectPath()`:
16
13
  *
17
- * (Phase 2 #158 layout — `<lang>/_tree/<pkg>@<ver>/…` — lands as a
18
- * separate refactor on top of this.)
14
+ * tree+coord → `<eco>/<name>@<ver>/<4hex>/<sha>.json`
15
+ * tree+nocoord `_unowned/<2hex>/<sha>.json`
16
+ * verify → `<2hex>/<sha>.json`
17
+ * discovery → `<2hex>/<sha>.json`
18
+ *
19
+ * `R2_PREFIX` default bumped `v1` → `v2` for the Round 2 layout. Operators
20
+ * who want the old keys back can pin `R2_PREFIX=v1` (the 2.27.0 layout is
21
+ * read-only at that prefix; new writes use `v2`).
19
22
  */
20
- import type { CacheBackend } from '../backend.js';
23
+ import type { CacheBackend, CacheNamespace } from '../backend.js';
21
24
  import { LocalFSBackend } from './local-fs.js';
22
25
  import { MemoryBackend } from './memory.js';
23
26
  import { R2Backend } from './r2.js';
24
27
  export { LocalFSBackend, MemoryBackend, R2Backend };
25
28
  export declare function getBackendKind(): 'local' | 'memory' | 'r2';
26
29
  /**
27
- * Build the backend for a given cacheDir. `cacheDir` is the local-fs
28
- * path the caller would have used pre-abstraction; for non-fs backends
29
- * we use only its basename as a sub-prefix.
30
+ * Build the backend for a given (cacheDir, namespace).
31
+ *
32
+ * `cacheDir` is the local-fs root the caller would have used pre-layout-
33
+ * reshape. For local-fs, the backend writes to `<cacheDir>` directly (the
34
+ * caller is expected to already pass the namespace-scoped subdir; this
35
+ * preserves the 2.27.0 ≤ on-disk shape for operators who care).
36
+ *
37
+ * For R2, the backend prefix is `<R2_PREFIX>/<namespace>` so all three
38
+ * namespaces share one bucket but live in separate keyspaces.
39
+ *
40
+ * `namespace` is required so R2 can build the namespace prefix correctly
41
+ * even when the caller's `cacheDir` basename is something custom.
30
42
  */
31
- export declare function makeBackend(cacheDir: string): CacheBackend;
43
+ export declare function makeBackend(cacheDir: string, namespace: CacheNamespace): CacheBackend;
32
44
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/cache/backends/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAGH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAClD,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAC/C,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAEpC,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,SAAS,EAAE,CAAC;AAEpD,wBAAgB,cAAc,IAAI,OAAO,GAAG,QAAQ,GAAG,IAAI,CAK1D;AAED;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,YAAY,CAkC1D"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/cache/backends/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAGH,OAAO,KAAK,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAClE,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAC/C,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAEpC,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,SAAS,EAAE,CAAC;AAEpD,wBAAgB,cAAc,IAAI,OAAO,GAAG,QAAQ,GAAG,IAAI,CAK1D;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,cAAc,GAAG,YAAY,CAoCrF"}
@@ -1,21 +1,24 @@
1
1
  /**
2
- * Cache backend factory (cognium-ai#158 Acceptance #4).
2
+ * Cache backend factory (cognium-ai#158).
3
3
  *
4
- * Selects a `CacheBackend` per cache-dir based on `LLM_CACHE_BACKEND`:
5
- * `local` (default) — `LocalFSBackend(cacheDir)`
4
+ * Selects a `CacheBackend` per namespace based on `LLM_CACHE_BACKEND`:
5
+ * `local` (default) — `LocalFSBackend(<cacheDir>/<namespace>)`
6
6
  * `memory` — `MemoryBackend()`
7
- * `r2` — `R2Backend({R2_ENDPOINT, R2_BUCKET, …})`
7
+ * `r2` — `R2Backend({prefix: <R2_PREFIX>/<namespace>, …})`
8
8
  *
9
- * For R2, the `cacheDir` is mapped to a stable sub-prefix so the three
10
- * caches (tree / verify / discovery) live under separate keyspaces in
11
- * a single bucket:
12
- * tree → `<R2_PREFIX>/tree/`
13
- * verify → `<R2_PREFIX>/verify/`
14
- * discovery → `<R2_PREFIX>/discovery/`
15
- * <other> → `<R2_PREFIX>/misc/`
9
+ * Each `ClassificationCache` (tree / verify / discovery) constructs ONE
10
+ * backend, scoped to its own namespace via the `namespace` arg. Inside
11
+ * the backend, the structured `CacheKey` is rendered to a path via
12
+ * `renderObjectPath()`:
16
13
  *
17
- * (Phase 2 #158 layout — `<lang>/_tree/<pkg>@<ver>/…` — lands as a
18
- * separate refactor on top of this.)
14
+ * tree+coord → `<eco>/<name>@<ver>/<4hex>/<sha>.json`
15
+ * tree+nocoord `_unowned/<2hex>/<sha>.json`
16
+ * verify → `<2hex>/<sha>.json`
17
+ * discovery → `<2hex>/<sha>.json`
18
+ *
19
+ * `R2_PREFIX` default bumped `v1` → `v2` for the Round 2 layout. Operators
20
+ * who want the old keys back can pin `R2_PREFIX=v1` (the 2.27.0 layout is
21
+ * read-only at that prefix; new writes use `v2`).
19
22
  */
20
23
  import * as path from 'path';
21
24
  import { LocalFSBackend } from './local-fs.js';
@@ -31,11 +34,20 @@ export function getBackendKind() {
31
34
  return 'local';
32
35
  }
33
36
  /**
34
- * Build the backend for a given cacheDir. `cacheDir` is the local-fs
35
- * path the caller would have used pre-abstraction; for non-fs backends
36
- * we use only its basename as a sub-prefix.
37
+ * Build the backend for a given (cacheDir, namespace).
38
+ *
39
+ * `cacheDir` is the local-fs root the caller would have used pre-layout-
40
+ * reshape. For local-fs, the backend writes to `<cacheDir>` directly (the
41
+ * caller is expected to already pass the namespace-scoped subdir; this
42
+ * preserves the 2.27.0 ≤ on-disk shape for operators who care).
43
+ *
44
+ * For R2, the backend prefix is `<R2_PREFIX>/<namespace>` so all three
45
+ * namespaces share one bucket but live in separate keyspaces.
46
+ *
47
+ * `namespace` is required so R2 can build the namespace prefix correctly
48
+ * even when the caller's `cacheDir` basename is something custom.
37
49
  */
38
- export function makeBackend(cacheDir) {
50
+ export function makeBackend(cacheDir, namespace) {
39
51
  const kind = getBackendKind();
40
52
  if (kind === 'memory')
41
53
  return new MemoryBackend();
@@ -45,32 +57,28 @@ export function makeBackend(cacheDir) {
45
57
  const accessKeyId = process.env.R2_ACCESS_KEY_ID;
46
58
  const secretAccessKey = process.env.R2_SECRET_ACCESS_KEY;
47
59
  if (!endpoint || !bucket || !accessKeyId || !secretAccessKey) {
48
- // Misconfigured; degrade to local instead of crashing. The
49
- // operator will see no cross-runner sharing but the scan
50
- // still works.
60
+ // Misconfigured; degrade to local instead of crashing.
51
61
  // eslint-disable-next-line no-console
52
62
  console.warn('[cache] LLM_CACHE_BACKEND=r2 but R2_ENDPOINT / R2_BUCKET / ' +
53
63
  'R2_ACCESS_KEY_ID / R2_SECRET_ACCESS_KEY not all set — ' +
54
64
  'falling back to local filesystem cache.');
55
65
  return new LocalFSBackend({ cacheDir });
56
66
  }
57
- const userPrefix = (process.env.R2_PREFIX ?? 'v1').replace(/^\/+|\/+$/g, '');
58
- const sub = cacheDirToSubPrefix(cacheDir);
67
+ const userPrefix = (process.env.R2_PREFIX ?? 'v2').replace(/^\/+|\/+$/g, '');
59
68
  return new R2Backend({
60
69
  endpoint,
61
70
  bucket,
62
71
  accessKeyId,
63
72
  secretAccessKey,
64
73
  region: process.env.R2_REGION ?? 'auto',
65
- prefix: `${userPrefix}/${sub}`,
74
+ prefix: `${userPrefix}/${namespace}`,
66
75
  });
67
76
  }
68
- return new LocalFSBackend({ cacheDir });
69
- }
70
- function cacheDirToSubPrefix(cacheDir) {
77
+ // Local-fs: scope to <cacheDir>/<namespace> unless cacheDir already
78
+ // ends in that namespace (back-compat with callers passing the
79
+ // pre-existing per-namespace dir).
71
80
  const base = path.basename(cacheDir).toLowerCase();
72
- if (base === 'tree' || base === 'verify' || base === 'discovery')
73
- return base;
74
- return 'misc';
81
+ const scoped = base === namespace ? cacheDir : path.join(cacheDir, namespace);
82
+ return new LocalFSBackend({ cacheDir: scoped });
75
83
  }
76
84
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/cache/backends/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAE7B,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAC/C,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAEpC,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,SAAS,EAAE,CAAC;AAEpD,MAAM,UAAU,cAAc;IAC5B,MAAM,GAAG,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,iBAAiB,IAAI,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC,IAAI,EAAE,CAAC;IACvE,IAAI,GAAG,KAAK,IAAI;QAAE,OAAO,IAAI,CAAC;IAC9B,IAAI,GAAG,KAAK,QAAQ;QAAE,OAAO,QAAQ,CAAC;IACtC,OAAO,OAAO,CAAC;AACjB,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,WAAW,CAAC,QAAgB;IAC1C,MAAM,IAAI,GAAG,cAAc,EAAE,CAAC;IAC9B,IAAI,IAAI,KAAK,QAAQ;QAAE,OAAO,IAAI,aAAa,EAAE,CAAC;IAElD,IAAI,IAAI,KAAK,IAAI,EAAE,CAAC;QAClB,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC;QACzC,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC;QACrC,MAAM,WAAW,GAAG,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC;QACjD,MAAM,eAAe,GAAG,OAAO,CAAC,GAAG,CAAC,oBAAoB,CAAC;QACzD,IAAI,CAAC,QAAQ,IAAI,CAAC,MAAM,IAAI,CAAC,WAAW,IAAI,CAAC,eAAe,EAAE,CAAC;YAC7D,2DAA2D;YAC3D,yDAAyD;YACzD,eAAe;YACf,sCAAsC;YACtC,OAAO,CAAC,IAAI,CACV,6DAA6D;gBAC7D,wDAAwD;gBACxD,yCAAyC,CAC1C,CAAC;YACF,OAAO,IAAI,cAAc,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC;QAC1C,CAAC;QACD,MAAM,UAAU,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,SAAS,IAAI,IAAI,CAAC,CAAC,OAAO,CAAC,YAAY,EAAE,EAAE,CAAC,CAAC;QAC7E,MAAM,GAAG,GAAG,mBAAmB,CAAC,QAAQ,CAAC,CAAC;QAC1C,OAAO,IAAI,SAAS,CAAC;YACnB,QAAQ;YACR,MAAM;YACN,WAAW;YACX,eAAe;YACf,MAAM,EAAE,OAAO,CAAC,GAAG,CAAC,SAAS,IAAI,MAAM;YACvC,MAAM,EAAE,GAAG,UAAU,IAAI,GAAG,EAAE;SAC/B,CAAC,CAAC;IACL,CAAC;IAED,OAAO,IAAI,cAAc,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC;AAC1C,CAAC;AAED,SAAS,mBAAmB,CAAC,QAAgB;IAC3C,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,WAAW,EAAE,CAAC;IACnD,IAAI,IAAI,KAAK,MAAM,IAAI,IAAI,KAAK,QAAQ,IAAI,IAAI,KAAK,WAAW;QAAE,OAAO,IAAI,CAAC;IAC9E,OAAO,MAAM,CAAC;AAChB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/cache/backends/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAE7B,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAC/C,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAEpC,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,SAAS,EAAE,CAAC;AAEpD,MAAM,UAAU,cAAc;IAC5B,MAAM,GAAG,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,iBAAiB,IAAI,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC,IAAI,EAAE,CAAC;IACvE,IAAI,GAAG,KAAK,IAAI;QAAE,OAAO,IAAI,CAAC;IAC9B,IAAI,GAAG,KAAK,QAAQ;QAAE,OAAO,QAAQ,CAAC;IACtC,OAAO,OAAO,CAAC;AACjB,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,WAAW,CAAC,QAAgB,EAAE,SAAyB;IACrE,MAAM,IAAI,GAAG,cAAc,EAAE,CAAC;IAC9B,IAAI,IAAI,KAAK,QAAQ;QAAE,OAAO,IAAI,aAAa,EAAE,CAAC;IAElD,IAAI,IAAI,KAAK,IAAI,EAAE,CAAC;QAClB,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC;QACzC,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC;QACrC,MAAM,WAAW,GAAG,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC;QACjD,MAAM,eAAe,GAAG,OAAO,CAAC,GAAG,CAAC,oBAAoB,CAAC;QACzD,IAAI,CAAC,QAAQ,IAAI,CAAC,MAAM,IAAI,CAAC,WAAW,IAAI,CAAC,eAAe,EAAE,CAAC;YAC7D,uDAAuD;YACvD,sCAAsC;YACtC,OAAO,CAAC,IAAI,CACV,6DAA6D;gBAC7D,wDAAwD;gBACxD,yCAAyC,CAC1C,CAAC;YACF,OAAO,IAAI,cAAc,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC;QAC1C,CAAC;QACD,MAAM,UAAU,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,SAAS,IAAI,IAAI,CAAC,CAAC,OAAO,CAAC,YAAY,EAAE,EAAE,CAAC,CAAC;QAC7E,OAAO,IAAI,SAAS,CAAC;YACnB,QAAQ;YACR,MAAM;YACN,WAAW;YACX,eAAe;YACf,MAAM,EAAE,OAAO,CAAC,GAAG,CAAC,SAAS,IAAI,MAAM;YACvC,MAAM,EAAE,GAAG,UAAU,IAAI,SAAS,EAAE;SACrC,CAAC,CAAC;IACL,CAAC;IAED,oEAAoE;IACpE,+DAA+D;IAC/D,mCAAmC;IACnC,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,WAAW,EAAE,CAAC;IACnD,MAAM,MAAM,GAAG,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;IAC9E,OAAO,IAAI,cAAc,CAAC,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC,CAAC;AAClD,CAAC"}
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Shared key-to-path renderer used by every backend so R2 / local-fs /
3
+ * memory all agree on the on-disk layout for a given `CacheKey`.
4
+ *
5
+ * Renders the *namespace-relative* suffix. The factory roots each
6
+ * backend at a `<prefix>/<namespace>/` path, so the resulting full key
7
+ * is:
8
+ *
9
+ * tree → `<root>/tree/<eco>/<name>@<ver>/<4hex>/<sha>.json` (coord)
10
+ * → `<root>/tree/_unowned/<4hex>/<sha>.json` (fallback)
11
+ * verify → `<root>/verify/<4hex>/<sha>.json`
12
+ * discovery → `<root>/discovery/<4hex>/<sha>.json`
13
+ *
14
+ * All four namespaces use a 4-hex (65 536) shard prefix. Rationale:
15
+ *
16
+ * - Uniform shard depth keeps the renderer / backend code symmetric;
17
+ * no namespace-specific branching past the coordinate decision.
18
+ * - 4-hex sizes each shard to a few hundred entries even at the worst
19
+ * case we've observed (coord'd `tree` for large packages like the
20
+ * aws-sdk-java multi-module reactor or `_unowned` shared across an
21
+ * entire CI fleet's anonymous scans).
22
+ * - The depth cost is negligible: R2 has no directory concept, and
23
+ * the local-fs backend just creates one extra cheap directory per
24
+ * shard the first time it's touched.
25
+ *
26
+ * Always returns forward-slash-separated segments; the local-fs
27
+ * backend translates to `path.sep` at the filesystem boundary.
28
+ */
29
+ import type { CacheKey } from '../backend.js';
30
+ export declare function renderObjectPath(key: CacheKey): string;
31
+ //# sourceMappingURL=layout.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"layout.d.ts","sourceRoot":"","sources":["../../../src/cache/backends/layout.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAM9C,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,QAAQ,GAAG,MAAM,CActD"}
@@ -0,0 +1,46 @@
1
+ /**
2
+ * Shared key-to-path renderer used by every backend so R2 / local-fs /
3
+ * memory all agree on the on-disk layout for a given `CacheKey`.
4
+ *
5
+ * Renders the *namespace-relative* suffix. The factory roots each
6
+ * backend at a `<prefix>/<namespace>/` path, so the resulting full key
7
+ * is:
8
+ *
9
+ * tree → `<root>/tree/<eco>/<name>@<ver>/<4hex>/<sha>.json` (coord)
10
+ * → `<root>/tree/_unowned/<4hex>/<sha>.json` (fallback)
11
+ * verify → `<root>/verify/<4hex>/<sha>.json`
12
+ * discovery → `<root>/discovery/<4hex>/<sha>.json`
13
+ *
14
+ * All four namespaces use a 4-hex (65 536) shard prefix. Rationale:
15
+ *
16
+ * - Uniform shard depth keeps the renderer / backend code symmetric;
17
+ * no namespace-specific branching past the coordinate decision.
18
+ * - 4-hex sizes each shard to a few hundred entries even at the worst
19
+ * case we've observed (coord'd `tree` for large packages like the
20
+ * aws-sdk-java multi-module reactor or `_unowned` shared across an
21
+ * entire CI fleet's anonymous scans).
22
+ * - The depth cost is negligible: R2 has no directory concept, and
23
+ * the local-fs backend just creates one extra cheap directory per
24
+ * shard the first time it's touched.
25
+ *
26
+ * Always returns forward-slash-separated segments; the local-fs
27
+ * backend translates to `path.sep` at the filesystem boundary.
28
+ */
29
+ import { coordinateSegments } from '../coordinate.js';
30
+ /** Uniform shard depth across all namespaces. See file header for rationale. */
31
+ const SHARD_HEX_LEN = 4;
32
+ export function renderObjectPath(key) {
33
+ const sha = key.digest;
34
+ const shard = sha.substring(0, SHARD_HEX_LEN);
35
+ if (key.namespace === 'tree') {
36
+ const coord = key.coordinate;
37
+ if (coord && coord.ecosystem !== '_unowned') {
38
+ const { pathSegment } = coordinateSegments(coord);
39
+ return `${pathSegment}/${shard}/${sha}.json`;
40
+ }
41
+ return `_unowned/${shard}/${sha}.json`;
42
+ }
43
+ // verify / discovery / classifier — flat with same 4-hex shard.
44
+ return `${shard}/${sha}.json`;
45
+ }
46
+ //# sourceMappingURL=layout.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"layout.js","sourceRoot":"","sources":["../../../src/cache/backends/layout.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAGH,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAEtD,gFAAgF;AAChF,MAAM,aAAa,GAAG,CAAC,CAAC;AAExB,MAAM,UAAU,gBAAgB,CAAC,GAAa;IAC5C,MAAM,GAAG,GAAG,GAAG,CAAC,MAAM,CAAC;IACvB,MAAM,KAAK,GAAG,GAAG,CAAC,SAAS,CAAC,CAAC,EAAE,aAAa,CAAC,CAAC;IAC9C,IAAI,GAAG,CAAC,SAAS,KAAK,MAAM,EAAE,CAAC;QAC7B,MAAM,KAAK,GAAG,GAAG,CAAC,UAAU,CAAC;QAC7B,IAAI,KAAK,IAAI,KAAK,CAAC,SAAS,KAAK,UAAU,EAAE,CAAC;YAC5C,MAAM,EAAE,WAAW,EAAE,GAAG,kBAAkB,CAAC,KAAK,CAAC,CAAC;YAClD,OAAO,GAAG,WAAW,IAAI,KAAK,IAAI,GAAG,OAAO,CAAC;QAC/C,CAAC;QACD,OAAO,YAAY,KAAK,IAAI,GAAG,OAAO,CAAC;IACzC,CAAC;IAED,gEAAgE;IAChE,OAAO,GAAG,KAAK,IAAI,GAAG,OAAO,CAAC;AAChC,CAAC"}
@@ -1,18 +1,21 @@
1
1
  /**
2
- * Local filesystem cache backend (cognium-ai#158 Acceptance #4).
2
+ * Local filesystem cache backend (cognium-ai#158).
3
3
  *
4
- * Preserves 2.26.0 on-disk shape:
5
- * <cacheDir>/<key[0:2]>/<key>.json
4
+ * Round 2 (2.28.0) layout (translated to platform path-sep):
5
+ *
6
+ * <cacheDir>/tree/<eco>/<name>@<ver>/<4hex>/<sha>.json (coord)
7
+ * <cacheDir>/tree/_unowned/<2hex>/<sha>.json (fallback)
8
+ * <cacheDir>/verify/<2hex>/<sha>.json
9
+ * <cacheDir>/discovery/<2hex>/<sha>.json
6
10
  *
7
11
  * Atomic write via tmp + rename so concurrent `cognium-ai scan`
8
- * processes don't corrupt each other's entries (same pattern as
9
- * the previous inline implementation in `classification-cache.ts`).
12
+ * processes don't corrupt each other's entries.
10
13
  *
11
14
  * Read/write errors are swallowed and surfaced as cache misses.
12
15
  */
13
- import type { CacheBackend } from '../backend.js';
16
+ import type { CacheBackend, CacheKey } from '../backend.js';
14
17
  export interface LocalFSBackendOptions {
15
- /** Root directory under which `<key[0:2]>/<key>.json` lives. */
18
+ /** Root directory under which the `<namespace>/.../<sha>.json` tree lives. */
16
19
  cacheDir: string;
17
20
  }
18
21
  export declare class LocalFSBackend implements CacheBackend {
@@ -21,10 +24,10 @@ export declare class LocalFSBackend implements CacheBackend {
21
24
  constructor(opts: LocalFSBackendOptions);
22
25
  private ensureCacheDir;
23
26
  private cachePath;
24
- get(key: string): Promise<string | null>;
25
- set(key: string, value: string): Promise<void>;
26
- has(key: string): Promise<boolean>;
27
- delete(key: string): Promise<void>;
27
+ get(key: CacheKey): Promise<string | null>;
28
+ set(key: CacheKey, value: string): Promise<void>;
29
+ has(key: CacheKey): Promise<boolean>;
30
+ delete(key: CacheKey): Promise<void>;
28
31
  count(): Promise<number>;
29
32
  clear(): Promise<void>;
30
33
  }
@@ -1 +1 @@
1
- {"version":3,"file":"local-fs.d.ts","sourceRoot":"","sources":["../../../src/cache/backends/local-fs.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAIH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAElD,MAAM,WAAW,qBAAqB;IACpC,gEAAgE;IAChE,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,qBAAa,cAAe,YAAW,YAAY;IACjD,QAAQ,CAAC,IAAI,cAAc;IAC3B,OAAO,CAAC,QAAQ,CAAS;gBAEb,IAAI,EAAE,qBAAqB;IAKvC,OAAO,CAAC,cAAc;IAMtB,OAAO,CAAC,SAAS;IAKX,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAUxC,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAe9C,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAIlC,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IASlC,KAAK,IAAI,OAAO,CAAC,MAAM,CAAC;IAgBxB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAQ7B"}
1
+ {"version":3,"file":"local-fs.d.ts","sourceRoot":"","sources":["../../../src/cache/backends/local-fs.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAIH,OAAO,KAAK,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAG5D,MAAM,WAAW,qBAAqB;IACpC,8EAA8E;IAC9E,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,qBAAa,cAAe,YAAW,YAAY;IACjD,QAAQ,CAAC,IAAI,cAAc;IAC3B,OAAO,CAAC,QAAQ,CAAS;gBAEb,IAAI,EAAE,qBAAqB;IAKvC,OAAO,CAAC,cAAc;IAMtB,OAAO,CAAC,SAAS;IAMX,GAAG,CAAC,GAAG,EAAE,QAAQ,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAU1C,GAAG,CAAC,GAAG,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAehD,GAAG,CAAC,GAAG,EAAE,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAC;IAIpC,MAAM,CAAC,GAAG,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;IASpC,KAAK,IAAI,OAAO,CAAC,MAAM,CAAC;IAsBxB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAQ7B"}
@@ -1,17 +1,21 @@
1
1
  /**
2
- * Local filesystem cache backend (cognium-ai#158 Acceptance #4).
2
+ * Local filesystem cache backend (cognium-ai#158).
3
3
  *
4
- * Preserves 2.26.0 on-disk shape:
5
- * <cacheDir>/<key[0:2]>/<key>.json
4
+ * Round 2 (2.28.0) layout (translated to platform path-sep):
5
+ *
6
+ * <cacheDir>/tree/<eco>/<name>@<ver>/<4hex>/<sha>.json (coord)
7
+ * <cacheDir>/tree/_unowned/<2hex>/<sha>.json (fallback)
8
+ * <cacheDir>/verify/<2hex>/<sha>.json
9
+ * <cacheDir>/discovery/<2hex>/<sha>.json
6
10
  *
7
11
  * Atomic write via tmp + rename so concurrent `cognium-ai scan`
8
- * processes don't corrupt each other's entries (same pattern as
9
- * the previous inline implementation in `classification-cache.ts`).
12
+ * processes don't corrupt each other's entries.
10
13
  *
11
14
  * Read/write errors are swallowed and surfaced as cache misses.
12
15
  */
13
16
  import * as fs from 'fs';
14
17
  import * as path from 'path';
18
+ import { renderObjectPath } from './layout.js';
15
19
  export class LocalFSBackend {
16
20
  kind = 'local-fs';
17
21
  cacheDir;
@@ -25,8 +29,9 @@ export class LocalFSBackend {
25
29
  }
26
30
  }
27
31
  cachePath(key) {
28
- const subdir = key.substring(0, 2);
29
- return path.join(this.cacheDir, subdir, `${key}.json`);
32
+ // layout returns forward-slash segments; translate for windows etc.
33
+ const rel = renderObjectPath(key).split('/').join(path.sep);
34
+ return path.join(this.cacheDir, rel);
30
35
  }
31
36
  async get(key) {
32
37
  const p = this.cachePath(key);
@@ -71,21 +76,28 @@ export class LocalFSBackend {
71
76
  }
72
77
  }
73
78
  async count() {
79
+ // Walk every namespace dir and count regular files. Best-effort —
80
+ // used by stats() so we don't sweat the cost.
74
81
  let n = 0;
75
82
  if (!fs.existsSync(this.cacheDir))
76
83
  return 0;
77
- try {
78
- for (const sub of fs.readdirSync(this.cacheDir)) {
79
- const subPath = path.join(this.cacheDir, sub);
80
- try {
81
- if (fs.statSync(subPath).isDirectory()) {
82
- n += fs.readdirSync(subPath).length;
83
- }
84
- }
85
- catch { /* skip */ }
84
+ const walk = (dir) => {
85
+ let entries;
86
+ try {
87
+ entries = fs.readdirSync(dir, { withFileTypes: true });
86
88
  }
87
- }
88
- catch { /* ignore */ }
89
+ catch {
90
+ return;
91
+ }
92
+ for (const ent of entries) {
93
+ const p = path.join(dir, ent.name);
94
+ if (ent.isDirectory())
95
+ walk(p);
96
+ else if (ent.isFile() && ent.name.endsWith('.json'))
97
+ n++;
98
+ }
99
+ };
100
+ walk(this.cacheDir);
89
101
  return n;
90
102
  }
91
103
  async clear() {
@@ -1 +1 @@
1
- {"version":3,"file":"local-fs.js","sourceRoot":"","sources":["../../../src/cache/backends/local-fs.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AACzB,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAQ7B,MAAM,OAAO,cAAc;IAChB,IAAI,GAAG,UAAU,CAAC;IACnB,QAAQ,CAAS;IAEzB,YAAY,IAA2B;QACrC,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC;QAC9B,IAAI,CAAC,cAAc,EAAE,CAAC;IACxB,CAAC;IAEO,cAAc;QACpB,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC;YAClC,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,QAAQ,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACnD,CAAC;IACH,CAAC;IAEO,SAAS,CAAC,GAAW;QAC3B,MAAM,MAAM,GAAG,GAAG,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QACnC,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,GAAG,OAAO,CAAC,CAAC;IACzD,CAAC;IAED,KAAK,CAAC,GAAG,CAAC,GAAW;QACnB,MAAM,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;QAC9B,IAAI,CAAC;YACH,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC;gBAAE,OAAO,IAAI,CAAC;YACnC,OAAO,EAAE,CAAC,YAAY,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;QACrC,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;IAED,KAAK,CAAC,GAAG,CAAC,GAAW,EAAE,KAAa;QAClC,MAAM,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;QAC9B,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;QAC/B,MAAM,GAAG,GAAG,GAAG,CAAC,QAAQ,OAAO,CAAC,GAAG,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC;QAChF,IAAI,CAAC;YACH,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;gBAC3B,EAAE,CAAC,SAAS,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;YAC5C,CAAC;YACD,EAAE,CAAC,aAAa,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;YAC7B,EAAE,CAAC,UAAU,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;QACxB,CAAC;QAAC,MAAM,CAAC;YACP,IAAI,CAAC;gBAAC,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC;YAAC,CAAC;YAAC,MAAM,CAAC,CAAC,YAAY,CAAC,CAAC;QACpD,CAAC;IACH,CAAC;IAED,KAAK,CAAC,GAAG,CAAC,GAAW;QACnB,OAAO,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC;IAC5C,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,GAAW;QACtB,MAAM,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;QAC9B,IAAI,CAAC;YACH,IAAI,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC;gBAAE,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;QACzC,CAAC;QAAC,MAAM,CAAC;YACP,YAAY;QACd,CAAC;IACH,CAAC;IAED,KAAK,CAAC,KAAK;QACT,IAAI,CAAC,GAAG,CAAC,CAAC;QACV,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,QAAQ,CAAC;YAAE,OAAO,CAAC,CAAC;QAC5C,IAAI,CAAC;YACH,KAAK,MAAM,GAAG,IAAI,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC;gBAChD,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;gBAC9C,IAAI,CAAC;oBACH,IAAI,EAAE,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,WAAW,EAAE,EAAE,CAAC;wBACvC,CAAC,IAAI,EAAE,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC;oBACtC,CAAC;gBACH,CAAC;gBAAC,MAAM,CAAC,CAAC,UAAU,CAAC,CAAC;YACxB,CAAC;QACH,CAAC;QAAC,MAAM,CAAC,CAAC,YAAY,CAAC,CAAC;QACxB,OAAO,CAAC,CAAC;IACX,CAAC;IAED,KAAK,CAAC,KAAK;QACT,IAAI,CAAC;YACH,IAAI,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC;gBACjC,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,QAAQ,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;YAC7D,CAAC;YACD,IAAI,CAAC,cAAc,EAAE,CAAC;QACxB,CAAC;QAAC,MAAM,CAAC,CAAC,YAAY,CAAC,CAAC;IAC1B,CAAC;CACF"}
1
+ {"version":3,"file":"local-fs.js","sourceRoot":"","sources":["../../../src/cache/backends/local-fs.ts"],"names":[],"mappings":"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"}
@@ -1,18 +1,23 @@
1
1
  /**
2
- * In-memory cache backend (cognium-ai#158 Acceptance #4).
2
+ * In-memory cache backend (cognium-ai#158).
3
3
  *
4
4
  * Map-backed; used by unit tests to avoid filesystem coupling.
5
5
  * Not intended for production — no eviction, no persistence,
6
6
  * grows unbounded.
7
+ *
8
+ * The internal Map is keyed by the same path string the persistent
9
+ * backends would render, so memory-backed test fixtures behave
10
+ * identically to local-fs / R2 wrt layout invariants.
7
11
  */
8
- import type { CacheBackend } from '../backend.js';
12
+ import type { CacheBackend, CacheKey } from '../backend.js';
9
13
  export declare class MemoryBackend implements CacheBackend {
10
14
  readonly kind = "memory";
11
15
  private store;
12
- get(key: string): Promise<string | null>;
13
- set(key: string, value: string): Promise<void>;
14
- has(key: string): Promise<boolean>;
15
- delete(key: string): Promise<void>;
16
+ private k;
17
+ get(key: CacheKey): Promise<string | null>;
18
+ set(key: CacheKey, value: string): Promise<void>;
19
+ has(key: CacheKey): Promise<boolean>;
20
+ delete(key: CacheKey): Promise<void>;
16
21
  count(): Promise<number>;
17
22
  clear(): Promise<void>;
18
23
  }
@@ -1 +1 @@
1
- {"version":3,"file":"memory.d.ts","sourceRoot":"","sources":["../../../src/cache/backends/memory.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAElD,qBAAa,aAAc,YAAW,YAAY;IAChD,QAAQ,CAAC,IAAI,YAAY;IACzB,OAAO,CAAC,KAAK,CAAkC;IAEzC,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAIxC,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAI9C,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAIlC,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIlC,KAAK,IAAI,OAAO,CAAC,MAAM,CAAC;IAIxB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAG7B"}
1
+ {"version":3,"file":"memory.d.ts","sourceRoot":"","sources":["../../../src/cache/backends/memory.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAG5D,qBAAa,aAAc,YAAW,YAAY;IAChD,QAAQ,CAAC,IAAI,YAAY;IACzB,OAAO,CAAC,KAAK,CAAkC;IAE/C,OAAO,CAAC,CAAC;IAIH,GAAG,CAAC,GAAG,EAAE,QAAQ,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAI1C,GAAG,CAAC,GAAG,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIhD,GAAG,CAAC,GAAG,EAAE,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAC;IAIpC,MAAM,CAAC,GAAG,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;IAIpC,KAAK,IAAI,OAAO,CAAC,MAAM,CAAC;IAIxB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAG7B"}
@@ -1,24 +1,32 @@
1
1
  /**
2
- * In-memory cache backend (cognium-ai#158 Acceptance #4).
2
+ * In-memory cache backend (cognium-ai#158).
3
3
  *
4
4
  * Map-backed; used by unit tests to avoid filesystem coupling.
5
5
  * Not intended for production — no eviction, no persistence,
6
6
  * grows unbounded.
7
+ *
8
+ * The internal Map is keyed by the same path string the persistent
9
+ * backends would render, so memory-backed test fixtures behave
10
+ * identically to local-fs / R2 wrt layout invariants.
7
11
  */
12
+ import { renderObjectPath } from './layout.js';
8
13
  export class MemoryBackend {
9
14
  kind = 'memory';
10
15
  store = new Map();
16
+ k(key) {
17
+ return renderObjectPath(key);
18
+ }
11
19
  async get(key) {
12
- return this.store.get(key) ?? null;
20
+ return this.store.get(this.k(key)) ?? null;
13
21
  }
14
22
  async set(key, value) {
15
- this.store.set(key, value);
23
+ this.store.set(this.k(key), value);
16
24
  }
17
25
  async has(key) {
18
- return this.store.has(key);
26
+ return this.store.has(this.k(key));
19
27
  }
20
28
  async delete(key) {
21
- this.store.delete(key);
29
+ this.store.delete(this.k(key));
22
30
  }
23
31
  async count() {
24
32
  return this.store.size;
@@ -1 +1 @@
1
- {"version":3,"file":"memory.js","sourceRoot":"","sources":["../../../src/cache/backends/memory.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH,MAAM,OAAO,aAAa;IACf,IAAI,GAAG,QAAQ,CAAC;IACjB,KAAK,GAAwB,IAAI,GAAG,EAAE,CAAC;IAE/C,KAAK,CAAC,GAAG,CAAC,GAAW;QACnB,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC;IACrC,CAAC;IAED,KAAK,CAAC,GAAG,CAAC,GAAW,EAAE,KAAa;QAClC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;IAC7B,CAAC;IAED,KAAK,CAAC,GAAG,CAAC,GAAW;QACnB,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAC7B,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,GAAW;QACtB,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IACzB,CAAC;IAED,KAAK,CAAC,KAAK;QACT,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC;IACzB,CAAC;IAED,KAAK,CAAC,KAAK;QACT,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;IACrB,CAAC;CACF"}
1
+ {"version":3,"file":"memory.js","sourceRoot":"","sources":["../../../src/cache/backends/memory.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAGH,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAE/C,MAAM,OAAO,aAAa;IACf,IAAI,GAAG,QAAQ,CAAC;IACjB,KAAK,GAAwB,IAAI,GAAG,EAAE,CAAC;IAEvC,CAAC,CAAC,GAAa;QACrB,OAAO,gBAAgB,CAAC,GAAG,CAAC,CAAC;IAC/B,CAAC;IAED,KAAK,CAAC,GAAG,CAAC,GAAa;QACrB,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,IAAI,CAAC;IAC7C,CAAC;IAED,KAAK,CAAC,GAAG,CAAC,GAAa,EAAE,KAAa;QACpC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,KAAK,CAAC,CAAC;IACrC,CAAC;IAED,KAAK,CAAC,GAAG,CAAC,GAAa;QACrB,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;IACrC,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,GAAa;QACxB,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;IACjC,CAAC;IAED,KAAK,CAAC,KAAK;QACT,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC;IACzB,CAAC;IAED,KAAK,CAAC,KAAK;QACT,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;IACrB,CAAC;CACF"}
@@ -1,15 +1,17 @@
1
1
  /**
2
2
  * Cloudflare R2 (S3-compatible) cache backend (cognium-ai#158).
3
3
  *
4
- * Phase 1 scope: drop-in object-store mirror of the local-fs key shape.
5
- * The R2 object key is `<prefix>/<key[0:2]>/<key>.json` — same sharding
6
- * as `LocalFSBackend` so the existing 3-component `ClassificationCache`
7
- * keys (content + classifier + modelFingerprint hash) just work.
4
+ * Round 2 (2.28.0) layout:
8
5
  *
9
- * Phase 2 (#158 layout reshape — separate follow-up): swap the opaque
10
- * 64-hex key for the structured `<lang>/_tree/<pkg>@<ver>/<fileSHA>.json`
11
- * style and reuse the `pkg-coord` + `model-registry` normalization
12
- * helpers. Phase 1 only proves wire-up + cross-runner sharing.
6
+ * <prefix>/tree/<eco>/<name>@<ver>/<4hex>/<sha>.json (coord present)
7
+ * <prefix>/tree/_unowned/<2hex>/<sha>.json (no coord)
8
+ * <prefix>/verify/<2hex>/<sha>.json (flat)
9
+ * <prefix>/discovery/<2hex>/<sha>.json (flat)
10
+ *
11
+ * The coordinate is only consulted for tree-namespace keys; verify and
12
+ * discovery stay flat because their content already encodes the model
13
+ * fingerprint + per-batch fingerprint, so a coordinate prefix would
14
+ * just bloat the path.
13
15
  *
14
16
  * Configuration (env vars):
15
17
  * LLM_CACHE_BACKEND=r2
@@ -18,14 +20,12 @@
18
20
  * R2_ACCESS_KEY_ID=<S3-compat access key>
19
21
  * R2_SECRET_ACCESS_KEY=<S3-compat secret>
20
22
  * R2_REGION=auto (default; R2 ignores region)
21
- * R2_PREFIX=v1 (default; namespaces the bucket)
23
+ * R2_PREFIX=v2 (default; namespaces the bucket)
22
24
  *
23
25
  * Failure mode: R2 errors are swallowed and surfaced as misses so a
24
26
  * network blip during scan degrades to local behavior, not a crash.
25
- * This matches `LocalFSBackend` and the cache-as-optimization contract
26
- * spelled out in `backend.ts`.
27
27
  */
28
- import type { CacheBackend } from '../backend.js';
28
+ import type { CacheBackend, CacheKey } from '../backend.js';
29
29
  export interface R2BackendOptions {
30
30
  endpoint: string;
31
31
  bucket: string;
@@ -33,7 +33,7 @@ export interface R2BackendOptions {
33
33
  secretAccessKey: string;
34
34
  /** R2 ignores region; default `auto`. */
35
35
  region?: string;
36
- /** Object-key prefix (default `v1`). Used to roll layout versions. */
36
+ /** Object-key prefix (default `v2`). Used to roll layout versions. */
37
37
  prefix?: string;
38
38
  }
39
39
  export declare class R2Backend implements CacheBackend {
@@ -43,9 +43,9 @@ export declare class R2Backend implements CacheBackend {
43
43
  private prefix;
44
44
  constructor(opts: R2BackendOptions);
45
45
  private objectKey;
46
- get(key: string): Promise<string | null>;
47
- set(key: string, value: string): Promise<void>;
48
- has(key: string): Promise<boolean>;
49
- delete(key: string): Promise<void>;
46
+ get(key: CacheKey): Promise<string | null>;
47
+ set(key: CacheKey, value: string): Promise<void>;
48
+ has(key: CacheKey): Promise<boolean>;
49
+ delete(key: CacheKey): Promise<void>;
50
50
  }
51
51
  //# sourceMappingURL=r2.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"r2.d.ts","sourceRoot":"","sources":["../../../src/cache/backends/r2.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AASH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAElD,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,eAAe,EAAE,MAAM,CAAC;IACxB,yCAAyC;IACzC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,sEAAsE;IACtE,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,qBAAa,SAAU,YAAW,YAAY;IAC5C,QAAQ,CAAC,IAAI,QAAQ;IACrB,OAAO,CAAC,MAAM,CAAW;IACzB,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,MAAM,CAAS;gBAEX,IAAI,EAAE,gBAAgB;IAelC,OAAO,CAAC,SAAS;IAKX,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAkBxC,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAa9C,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAYlC,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAUzC"}
1
+ {"version":3,"file":"r2.d.ts","sourceRoot":"","sources":["../../../src/cache/backends/r2.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AASH,OAAO,KAAK,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAG5D,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,eAAe,EAAE,MAAM,CAAC;IACxB,yCAAyC;IACzC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,sEAAsE;IACtE,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,qBAAa,SAAU,YAAW,YAAY;IAC5C,QAAQ,CAAC,IAAI,QAAQ;IACrB,OAAO,CAAC,MAAM,CAAW;IACzB,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,MAAM,CAAS;gBAEX,IAAI,EAAE,gBAAgB;IAelC,OAAO,CAAC,SAAS;IAIX,GAAG,CAAC,GAAG,EAAE,QAAQ,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAgB1C,GAAG,CAAC,GAAG,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAahD,GAAG,CAAC,GAAG,EAAE,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAC;IAYpC,MAAM,CAAC,GAAG,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;CAU3C"}