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,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,13 @@
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
28
  import { S3Client, GetObjectCommand, PutObjectCommand, HeadObjectCommand, DeleteObjectCommand, } from '@aws-sdk/client-s3';
29
+ import { renderObjectPath } from './layout.js';
29
30
  export class R2Backend {
30
31
  kind = 'r2';
31
32
  client;
@@ -33,7 +34,7 @@ export class R2Backend {
33
34
  prefix;
34
35
  constructor(opts) {
35
36
  this.bucket = opts.bucket;
36
- this.prefix = (opts.prefix ?? 'v1').replace(/^\/+|\/+$/g, '');
37
+ this.prefix = (opts.prefix ?? 'v2').replace(/^\/+|\/+$/g, '');
37
38
  this.client = new S3Client({
38
39
  endpoint: opts.endpoint,
39
40
  region: opts.region ?? 'auto',
@@ -46,8 +47,7 @@ export class R2Backend {
46
47
  });
47
48
  }
48
49
  objectKey(key) {
49
- const sub = key.substring(0, 2);
50
- return `${this.prefix}/${sub}/${key}.json`;
50
+ return `${this.prefix}/${renderObjectPath(key)}`;
51
51
  }
52
52
  async get(key) {
53
53
  try {
@@ -57,12 +57,10 @@ export class R2Backend {
57
57
  }));
58
58
  if (!out.Body)
59
59
  return null;
60
- // SDK v3 returns a stream; collect to string.
61
60
  const stream = out.Body;
62
61
  return await streamToString(stream);
63
62
  }
64
63
  catch (err) {
65
- // 404 → miss. Other errors swallowed (cache is best-effort).
66
64
  const name = err?.name;
67
65
  if (name === 'NoSuchKey' || name === 'NotFound')
68
66
  return null;
@@ -1 +1 @@
1
- {"version":3,"file":"r2.js","sourceRoot":"","sources":["../../../src/cache/backends/r2.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"r2.js","sourceRoot":"","sources":["../../../src/cache/backends/r2.ts"],"names":[],"mappings":"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"}
@@ -2,35 +2,65 @@
2
2
  * Classification Cache
3
3
  *
4
4
  * Caches LLM classification results by composite key
5
- * (content hash + classifier name + per-phase model fingerprint).
6
- * Optimized for batch classifier workloads with shorter TTL than FileCache.
5
+ * (schemaVer + content hash + classifier name + per-phase model fingerprint
6
+ * + optional coordinate hash-prefix).
7
7
  *
8
- * Key differences from FileCache:
9
- * - Composite key: SHA-256(content + '\0' + classifierName + '\0' + modelFingerprint)
10
- * - Shorter default TTL (24h vs 7d)
11
- * - Cache directory: .cognium/cache/
12
- * - Hit/miss tracking for observability
8
+ * Storage is delegated to a `CacheBackend` (cognium-ai#158). Default
9
+ * = `LocalFSBackend`. Selecting `LLM_CACHE_BACKEND=r2` swaps to Cloudflare
10
+ * R2 transparently so two runners on different machines share the same
11
+ * cache.
13
12
  *
14
- * Storage is delegated to a `CacheBackend` (cognium-ai#158 Acceptance #4).
15
- * Default = `LocalFSBackend` (preserves ≤2.26.0 on-disk shape). Selecting
16
- * `LLM_CACHE_BACKEND=r2` swaps to Cloudflare R2 transparently so two
17
- * runners on different machines share the same cache.
13
+ * # Round 2 (2.28.0) key shape
18
14
  *
19
- * Model dimension (cognium-ai#151 P0 spike):
20
- * When `modelFingerprint` is supplied (typically via
21
- * `getPhaseModelFingerprint()` from `../llm/config.ts`) it becomes part
22
- * of the cache key. This prevents a `gemma3:12b` discovery result from
23
- * being silently reused when the operator switches to `gpt-4o-mini` for
24
- * discovery. The fingerprint is the same identity the persistent cache
25
- * (#158) uses, so call-site cache and S3 cache stay in lockstep.
15
+ * sha256(
16
+ * 'cic:v2' // SCHEMA_VER bump on breaking key changes
17
+ * + '\0' + namespace // 'tree' | 'verify' | 'discovery'
18
+ * + '\0' + classifier
19
+ * + '\0' + content
20
+ * + '\0' + modelFingerprint // per-phase, see ../llm/config.ts
21
+ * + '\0' + coordinateHashPrefix // empty for non-tree, or _unowned
22
+ * )
23
+ *
24
+ * Why `namespace` is in the hash:
25
+ * So a tree-cache entry can never collide with a verify-cache entry
26
+ * even if a future caller happens to choose the same classifier name.
27
+ *
28
+ * Why `coordinate` is in the hash (when present):
29
+ * So `commons-lang3@3.12.0` and `commons-lang3@3.13.0` produce
30
+ * different SHAs for the same byte-identical file (we WANT them
31
+ * distinct because the surrounding rules / version-conditioned
32
+ * profile could differ). The coordinate is also reflected in the
33
+ * backend path layout — see `./backends/layout.ts` — so the cache
34
+ * is browseable in R2 dashboard by package.
26
35
  *
27
- * Backward compat: when omitted the key falls through to the prior
28
- * 2-component shape, so existing callers (and on-disk entries from
29
- * ≤2.21.0) keep working — the first run after wire-through is a cache
30
- * miss only for the call sites that opt into the fingerprint.
36
+ * Model dimension (cognium-ai#151 P0 spike):
37
+ * `modelFingerprint` is the per-phase identity from
38
+ * `getDiscoveryModelFingerprint()` / `getVerifyModelFingerprint()` /
39
+ * `getComponentModelFingerprint()` in `../llm/config.ts`. Each cache
40
+ * instance uses the fingerprint scoped to its phase so swapping the
41
+ * discovery model doesn't invalidate verify results and vice versa
42
+ * (#158 D2).
43
+ */
44
+ import type { CacheBackend, CacheNamespace } from './backend.js';
45
+ import type { PackageCoordinate } from './coordinate.js';
46
+ /**
47
+ * Wire-format version. Bump on every breaking change to the key composition
48
+ * OR the on-disk envelope shape. Operators rolling back to an older
49
+ * circle-ir-ai will see misses against newer SCHEMA_VER entries and
50
+ * re-populate cleanly.
31
51
  */
32
- import type { CacheBackend } from './backend.js';
52
+ export declare const SCHEMA_VER = "cic:v2";
33
53
  export interface ClassificationCacheOptions {
54
+ /**
55
+ * Logical cache namespace. Determines backend path layout AND whether
56
+ * the cache participates in the coordinate-aware tree layout.
57
+ *
58
+ * Defaults to `'classifier'` for generic LLM classification callers
59
+ * (batch-classifier, trust passes) that don't care about the namespace
60
+ * dimension. The three SAST caches (`tree-cache.ts`, `verify-cache.ts`,
61
+ * `discovery-cache.ts`) always pass their own namespace explicitly.
62
+ */
63
+ namespace?: CacheNamespace;
34
64
  /** Cache directory (default: .cognium/cache/ in project root). For
35
65
  * non-fs backends this is interpreted as a sub-prefix only. */
36
66
  cacheDir?: string;
@@ -39,20 +69,28 @@ export interface ClassificationCacheOptions {
39
69
  /** Enable/disable cache (default: true) */
40
70
  enabled?: boolean;
41
71
  /**
42
- * Per-phase model identity for cache namespacing (cognium-ai#151).
43
- * Typically the output of `getPhaseModelFingerprint(config)` from
44
- * `../llm/config.ts`. Two scans with different discovery / verification
45
- * models will produce different cache keys and not poison each other.
46
- * Defaults to empty string (legacy 2-component key shape).
72
+ * Per-phase model identity for cache namespacing (cognium-ai#151 / #158 D2).
73
+ * Tree-cache passes the discovery+verify joint fingerprint; verify-cache
74
+ * passes the verify-only fingerprint; discovery-cache passes the
75
+ * discovery-only fingerprint. See `../llm/config.ts`.
47
76
  */
48
77
  modelFingerprint?: string;
49
78
  /**
50
79
  * Override the backend instance (tests). When omitted we build one
51
- * via `makeBackend(cacheDir)` based on `LLM_CACHE_BACKEND` env.
80
+ * via `makeBackend(cacheDir, namespace)` based on `LLM_CACHE_BACKEND` env.
52
81
  */
53
82
  backend?: CacheBackend;
54
83
  }
84
+ /**
85
+ * Per-get/set call extras. `coordinate` is honored only for the
86
+ * `tree` namespace; passing it elsewhere is a no-op so callers don't
87
+ * have to branch.
88
+ */
89
+ export interface CacheCallOptions {
90
+ coordinate?: PackageCoordinate;
91
+ }
55
92
  export declare class ClassificationCache<T = unknown> {
93
+ private namespace;
56
94
  private cacheDir;
57
95
  private maxAge;
58
96
  private enabled;
@@ -66,19 +104,23 @@ export declare class ClassificationCache<T = unknown> {
66
104
  getModelFingerprint(): string;
67
105
  /** Backend kind identifier (`local-fs` | `memory` | `r2`). Observability. */
68
106
  getBackendKind(): string;
69
- private computeKey;
107
+ /** Logical namespace (`tree` | `verify` | `discovery`). Observability. */
108
+ getNamespace(): CacheNamespace;
109
+ private computeDigest;
110
+ private toCacheKey;
70
111
  private isValid;
71
- get(content: string, classifier: string): Promise<T | null>;
72
- set(content: string, classifier: string, result: T): Promise<void>;
73
- has(content: string, classifier: string): Promise<boolean>;
112
+ get(content: string, classifier: string, opts?: CacheCallOptions): Promise<T | null>;
113
+ set(content: string, classifier: string, result: T, opts?: CacheCallOptions): Promise<void>;
114
+ has(content: string, classifier: string, opts?: CacheCallOptions): Promise<boolean>;
74
115
  clear(): Promise<void>;
75
116
  stats(): Promise<{
117
+ namespace: CacheNamespace;
76
118
  memoryEntries: number;
77
119
  diskEntries: number;
78
120
  hitRate: number;
79
121
  backend: string;
80
122
  }>;
81
123
  }
82
- export declare function getClassificationCache(options?: ClassificationCacheOptions): ClassificationCache;
124
+ export declare function getClassificationCache<T = unknown>(options?: ClassificationCacheOptions): ClassificationCache<T>;
83
125
  export declare function resetClassificationCache(): void;
84
126
  //# sourceMappingURL=classification-cache.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"classification-cache.d.ts","sourceRoot":"","sources":["../../src/cache/classification-cache.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAIH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAGjD,MAAM,WAAW,0BAA0B;IACzC;oEACgE;IAChE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,kDAAkD;IAClD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,2CAA2C;IAC3C,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB;;;;;;OAMG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B;;;OAGG;IACH,OAAO,CAAC,EAAE,YAAY,CAAC;CACxB;AAUD,qBAAa,mBAAmB,CAAC,CAAC,GAAG,OAAO;IAC1C,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,OAAO,CAAU;IACzB,OAAO,CAAC,gBAAgB,CAAS;IACjC,OAAO,CAAC,OAAO,CAAe;IAC9B,OAAO,CAAC,WAAW,CAAyC;IAC5D,OAAO,CAAC,IAAI,CAAK;IACjB,OAAO,CAAC,MAAM,CAAK;gBAEP,OAAO,GAAE,0BAA+B;IAQpD,mEAAmE;IACnE,mBAAmB,IAAI,MAAM;IAI7B,6EAA6E;IAC7E,cAAc,IAAI,MAAM;IAIxB,OAAO,CAAC,UAAU;IAWlB,OAAO,CAAC,OAAO;IAIT,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC;IAoC3D,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAclE,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAI1D,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAStB,KAAK,IAAI,OAAO,CAAC;QAAE,aAAa,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;CAazG;AASD,wBAAgB,sBAAsB,CAAC,OAAO,CAAC,EAAE,0BAA0B,GAAG,mBAAmB,CAMhG;AAED,wBAAgB,wBAAwB,IAAI,IAAI,CAE/C"}
1
+ {"version":3,"file":"classification-cache.d.ts","sourceRoot":"","sources":["../../src/cache/classification-cache.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0CG;AAIH,OAAO,KAAK,EAAE,YAAY,EAAY,cAAc,EAAE,MAAM,cAAc,CAAC;AAE3E,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAGzD;;;;;GAKG;AACH,eAAO,MAAM,UAAU,WAAW,CAAC;AAEnC,MAAM,WAAW,0BAA0B;IACzC;;;;;;;;OAQG;IACH,SAAS,CAAC,EAAE,cAAc,CAAC;IAC3B;oEACgE;IAChE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,kDAAkD;IAClD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,2CAA2C;IAC3C,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB;;;;;OAKG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B;;;OAGG;IACH,OAAO,CAAC,EAAE,YAAY,CAAC;CACxB;AAWD;;;;GAIG;AACH,MAAM,WAAW,gBAAgB;IAC/B,UAAU,CAAC,EAAE,iBAAiB,CAAC;CAChC;AAED,qBAAa,mBAAmB,CAAC,CAAC,GAAG,OAAO;IAC1C,OAAO,CAAC,SAAS,CAAiB;IAClC,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,OAAO,CAAU;IACzB,OAAO,CAAC,gBAAgB,CAAS;IACjC,OAAO,CAAC,OAAO,CAAe;IAC9B,OAAO,CAAC,WAAW,CAAyC;IAC5D,OAAO,CAAC,IAAI,CAAK;IACjB,OAAO,CAAC,MAAM,CAAK;gBAEP,OAAO,GAAE,0BAA+B;IASpD,mEAAmE;IACnE,mBAAmB,IAAI,MAAM;IAI7B,6EAA6E;IAC7E,cAAc,IAAI,MAAM;IAIxB,0EAA0E;IAC1E,YAAY,IAAI,cAAc;IAI9B,OAAO,CAAC,aAAa;IAqBrB,OAAO,CAAC,UAAU;IAWlB,OAAO,CAAC,OAAO;IAKT,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC;IAqCpF,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,EAAE,IAAI,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC;IAoB3F,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAAC,OAAO,CAAC;IAInF,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAStB,KAAK,IAAI,OAAO,CAAC;QACrB,SAAS,EAAE,cAAc,CAAC;QAC1B,aAAa,EAAE,MAAM,CAAC;QACtB,WAAW,EAAE,MAAM,CAAC;QACpB,OAAO,EAAE,MAAM,CAAC;QAChB,OAAO,EAAE,MAAM,CAAC;KACjB,CAAC;CAcH;AASD,wBAAgB,sBAAsB,CAAC,CAAC,GAAG,OAAO,EAAE,OAAO,GAAE,0BAA+B,GAAG,mBAAmB,CAAC,CAAC,CAAC,CAUpH;AAED,wBAAgB,wBAAwB,IAAI,IAAI,CAE/C"}
@@ -2,38 +2,59 @@
2
2
  * Classification Cache
3
3
  *
4
4
  * Caches LLM classification results by composite key
5
- * (content hash + classifier name + per-phase model fingerprint).
6
- * Optimized for batch classifier workloads with shorter TTL than FileCache.
5
+ * (schemaVer + content hash + classifier name + per-phase model fingerprint
6
+ * + optional coordinate hash-prefix).
7
7
  *
8
- * Key differences from FileCache:
9
- * - Composite key: SHA-256(content + '\0' + classifierName + '\0' + modelFingerprint)
10
- * - Shorter default TTL (24h vs 7d)
11
- * - Cache directory: .cognium/cache/
12
- * - Hit/miss tracking for observability
8
+ * Storage is delegated to a `CacheBackend` (cognium-ai#158). Default
9
+ * = `LocalFSBackend`. Selecting `LLM_CACHE_BACKEND=r2` swaps to Cloudflare
10
+ * R2 transparently so two runners on different machines share the same
11
+ * cache.
13
12
  *
14
- * Storage is delegated to a `CacheBackend` (cognium-ai#158 Acceptance #4).
15
- * Default = `LocalFSBackend` (preserves ≤2.26.0 on-disk shape). Selecting
16
- * `LLM_CACHE_BACKEND=r2` swaps to Cloudflare R2 transparently so two
17
- * runners on different machines share the same cache.
13
+ * # Round 2 (2.28.0) key shape
18
14
  *
19
- * Model dimension (cognium-ai#151 P0 spike):
20
- * When `modelFingerprint` is supplied (typically via
21
- * `getPhaseModelFingerprint()` from `../llm/config.ts`) it becomes part
22
- * of the cache key. This prevents a `gemma3:12b` discovery result from
23
- * being silently reused when the operator switches to `gpt-4o-mini` for
24
- * discovery. The fingerprint is the same identity the persistent cache
25
- * (#158) uses, so call-site cache and S3 cache stay in lockstep.
15
+ * sha256(
16
+ * 'cic:v2' // SCHEMA_VER bump on breaking key changes
17
+ * + '\0' + namespace // 'tree' | 'verify' | 'discovery'
18
+ * + '\0' + classifier
19
+ * + '\0' + content
20
+ * + '\0' + modelFingerprint // per-phase, see ../llm/config.ts
21
+ * + '\0' + coordinateHashPrefix // empty for non-tree, or _unowned
22
+ * )
23
+ *
24
+ * Why `namespace` is in the hash:
25
+ * So a tree-cache entry can never collide with a verify-cache entry
26
+ * even if a future caller happens to choose the same classifier name.
27
+ *
28
+ * Why `coordinate` is in the hash (when present):
29
+ * So `commons-lang3@3.12.0` and `commons-lang3@3.13.0` produce
30
+ * different SHAs for the same byte-identical file (we WANT them
31
+ * distinct because the surrounding rules / version-conditioned
32
+ * profile could differ). The coordinate is also reflected in the
33
+ * backend path layout — see `./backends/layout.ts` — so the cache
34
+ * is browseable in R2 dashboard by package.
26
35
  *
27
- * Backward compat: when omitted the key falls through to the prior
28
- * 2-component shape, so existing callers (and on-disk entries from
29
- * ≤2.21.0) keep working — the first run after wire-through is a cache
30
- * miss only for the call sites that opt into the fingerprint.
36
+ * Model dimension (cognium-ai#151 P0 spike):
37
+ * `modelFingerprint` is the per-phase identity from
38
+ * `getDiscoveryModelFingerprint()` / `getVerifyModelFingerprint()` /
39
+ * `getComponentModelFingerprint()` in `../llm/config.ts`. Each cache
40
+ * instance uses the fingerprint scoped to its phase so swapping the
41
+ * discovery model doesn't invalidate verify results and vice versa
42
+ * (#158 D2).
31
43
  */
32
44
  import * as path from 'path';
33
45
  import * as crypto from 'crypto';
34
46
  import { makeBackend } from './backends/index.js';
47
+ import { coordinateSegments } from './coordinate.js';
48
+ /**
49
+ * Wire-format version. Bump on every breaking change to the key composition
50
+ * OR the on-disk envelope shape. Operators rolling back to an older
51
+ * circle-ir-ai will see misses against newer SCHEMA_VER entries and
52
+ * re-populate cleanly.
53
+ */
54
+ export const SCHEMA_VER = 'cic:v2';
35
55
  const DEFAULT_MAX_AGE = 24 * 60 * 60 * 1000; // 24 hours
36
56
  export class ClassificationCache {
57
+ namespace;
37
58
  cacheDir;
38
59
  maxAge;
39
60
  enabled;
@@ -43,11 +64,12 @@ export class ClassificationCache {
43
64
  hits = 0;
44
65
  misses = 0;
45
66
  constructor(options = {}) {
67
+ this.namespace = options.namespace ?? 'classifier';
46
68
  this.cacheDir = options.cacheDir || path.join(process.cwd(), '.cognium', 'cache');
47
69
  this.maxAge = options.maxAge ?? DEFAULT_MAX_AGE;
48
70
  this.enabled = options.enabled ?? true;
49
71
  this.modelFingerprint = options.modelFingerprint ?? '';
50
- this.backend = options.backend ?? makeBackend(this.cacheDir);
72
+ this.backend = options.backend ?? makeBackend(this.cacheDir, this.namespace);
51
73
  }
52
74
  /** Per-phase model identity used in cache key (cognium-ai#151). */
53
75
  getModelFingerprint() {
@@ -57,43 +79,62 @@ export class ClassificationCache {
57
79
  getBackendKind() {
58
80
  return this.backend.kind;
59
81
  }
60
- computeKey(content, classifier) {
61
- // 3-component key when fingerprint present (cognium-ai#151). When
62
- // empty falls through to the prior 2-component shape via the trailing
63
- // `'\0' + ''` collapse — bit-identical to ≤2.21.0 only when no
64
- // fingerprint is supplied at all, which is the back-compat path.
65
- const parts = this.modelFingerprint
66
- ? content + '\0' + classifier + '\0' + this.modelFingerprint
67
- : content + '\0' + classifier;
82
+ /** Logical namespace (`tree` | `verify` | `discovery`). Observability. */
83
+ getNamespace() {
84
+ return this.namespace;
85
+ }
86
+ computeDigest(content, classifier, coordinate) {
87
+ // Coordinate hash-prefix only applies to the `tree` namespace.
88
+ // Including it in the digest (not just the path) is what guarantees
89
+ // a fileSHA collision across packages still produces distinct keys.
90
+ const coordPart = (this.namespace === 'tree' && coordinate)
91
+ ? coordinateSegments(coordinate).hashPrefix
92
+ : '';
93
+ const parts = SCHEMA_VER
94
+ + '\0' + this.namespace
95
+ + '\0' + classifier
96
+ + '\0' + content
97
+ + '\0' + this.modelFingerprint
98
+ + '\0' + coordPart;
68
99
  return crypto.createHash('sha256').update(parts).digest('hex');
69
100
  }
101
+ toCacheKey(digest, coordinate) {
102
+ const key = { namespace: this.namespace, digest };
103
+ if (this.namespace === 'tree' && coordinate) {
104
+ key.coordinate = coordinate;
105
+ }
106
+ return key;
107
+ }
70
108
  isValid(entry) {
109
+ if (entry.schemaVer !== SCHEMA_VER)
110
+ return false;
71
111
  return (Date.now() - entry.timestamp) <= this.maxAge;
72
112
  }
73
- async get(content, classifier) {
113
+ async get(content, classifier, opts) {
74
114
  if (!this.enabled)
75
115
  return null;
76
- const key = this.computeKey(content, classifier);
116
+ const digest = this.computeDigest(content, classifier, opts?.coordinate);
117
+ const cacheKey = this.toCacheKey(digest, opts?.coordinate);
77
118
  // Memory cache (process-local hot path)
78
- const memEntry = this.memoryCache.get(key);
119
+ const memEntry = this.memoryCache.get(digest);
79
120
  if (memEntry && this.isValid(memEntry)) {
80
121
  this.hits++;
81
122
  return memEntry.result;
82
123
  }
83
124
  // Backend (disk / R2 / etc.)
84
125
  try {
85
- const raw = await this.backend.get(key);
126
+ const raw = await this.backend.get(cacheKey);
86
127
  if (raw !== null) {
87
128
  const entry = JSON.parse(raw);
88
129
  if (this.isValid(entry)) {
89
- this.memoryCache.set(key, entry);
130
+ this.memoryCache.set(digest, entry);
90
131
  this.hits++;
91
132
  return entry.result;
92
133
  }
93
- // Stale best-effort drop. We don't await the deletion to
94
- // keep the read path fast.
134
+ // Stale OR schemaVer-mismatch drop. We don't await the deletion
135
+ // to keep the read path fast.
95
136
  if (this.backend.delete) {
96
- void this.backend.delete(key);
137
+ void this.backend.delete(cacheKey);
97
138
  }
98
139
  }
99
140
  }
@@ -103,21 +144,27 @@ export class ClassificationCache {
103
144
  this.misses++;
104
145
  return null;
105
146
  }
106
- async set(content, classifier, result) {
147
+ async set(content, classifier, result, opts) {
107
148
  if (!this.enabled)
108
149
  return;
109
- const key = this.computeKey(content, classifier);
110
- const entry = { key, timestamp: Date.now(), result };
111
- this.memoryCache.set(key, entry);
150
+ const digest = this.computeDigest(content, classifier, opts?.coordinate);
151
+ const cacheKey = this.toCacheKey(digest, opts?.coordinate);
152
+ const entry = {
153
+ schemaVer: SCHEMA_VER,
154
+ key: digest,
155
+ timestamp: Date.now(),
156
+ result,
157
+ };
158
+ this.memoryCache.set(digest, entry);
112
159
  try {
113
- await this.backend.set(key, JSON.stringify(entry));
160
+ await this.backend.set(cacheKey, JSON.stringify(entry));
114
161
  }
115
162
  catch {
116
163
  // Cache write is best-effort; never fail the caller.
117
164
  }
118
165
  }
119
- async has(content, classifier) {
120
- return (await this.get(content, classifier)) !== null;
166
+ async has(content, classifier, opts) {
167
+ return (await this.get(content, classifier, opts)) !== null;
121
168
  }
122
169
  async clear() {
123
170
  this.memoryCache.clear();
@@ -140,6 +187,7 @@ export class ClassificationCache {
140
187
  }
141
188
  const total = this.hits + this.misses;
142
189
  return {
190
+ namespace: this.namespace,
143
191
  memoryEntries: this.memoryCache.size,
144
192
  diskEntries,
145
193
  hitRate: total > 0 ? this.hits / total : 0,
@@ -147,20 +195,24 @@ export class ClassificationCache {
147
195
  };
148
196
  }
149
197
  }
150
- // Singleton — keyed on cacheDir + modelFingerprint so two scans with
151
- // different per-phase models in the same process get distinct caches
152
- // (cognium-ai#151). Without the fingerprint dimension, switching
153
- // `LLM_DISCOVERY_MODEL` between scans would silently reuse the first
154
- // scan's classifier results.
155
- let classificationCache = null;
156
- export function getClassificationCache(options) {
157
- const wantFingerprint = options?.modelFingerprint ?? '';
158
- if (!classificationCache || classificationCache.getModelFingerprint() !== wantFingerprint) {
159
- classificationCache = new ClassificationCache(options);
198
+ /**
199
+ * Singleton table keyed on (namespace, modelFingerprint) so two scans
200
+ * with different per-phase models in the same process get distinct
201
+ * caches (cognium-ai#151).
202
+ */
203
+ const singletons = new Map();
204
+ export function getClassificationCache(options = {}) {
205
+ const fp = options.modelFingerprint ?? '';
206
+ const namespace = options.namespace ?? 'classifier';
207
+ const slot = `${namespace}\0${fp}`;
208
+ let existing = singletons.get(slot);
209
+ if (!existing) {
210
+ existing = new ClassificationCache(options);
211
+ singletons.set(slot, existing);
160
212
  }
161
- return classificationCache;
213
+ return existing;
162
214
  }
163
215
  export function resetClassificationCache() {
164
- classificationCache = null;
216
+ singletons.clear();
165
217
  }
166
218
  //# sourceMappingURL=classification-cache.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"classification-cache.js","sourceRoot":"","sources":["../../src/cache/classification-cache.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAEH,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAC7B,OAAO,KAAK,MAAM,MAAM,QAAQ,CAAC;AAEjC,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AA+BlD,MAAM,eAAe,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC,WAAW;AAExD,MAAM,OAAO,mBAAmB;IACtB,QAAQ,CAAS;IACjB,MAAM,CAAS;IACf,OAAO,CAAU;IACjB,gBAAgB,CAAS;IACzB,OAAO,CAAe;IACtB,WAAW,GAA+B,IAAI,GAAG,EAAE,CAAC;IACpD,IAAI,GAAG,CAAC,CAAC;IACT,MAAM,GAAG,CAAC,CAAC;IAEnB,YAAY,UAAsC,EAAE;QAClD,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAC,QAAQ,IAAI,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,UAAU,EAAE,OAAO,CAAC,CAAC;QAClF,IAAI,CAAC,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,eAAe,CAAC;QAChD,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC,OAAO,IAAI,IAAI,CAAC;QACvC,IAAI,CAAC,gBAAgB,GAAG,OAAO,CAAC,gBAAgB,IAAI,EAAE,CAAC;QACvD,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC,OAAO,IAAI,WAAW,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IAC/D,CAAC;IAED,mEAAmE;IACnE,mBAAmB;QACjB,OAAO,IAAI,CAAC,gBAAgB,CAAC;IAC/B,CAAC;IAED,6EAA6E;IAC7E,cAAc;QACZ,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC;IAC3B,CAAC;IAEO,UAAU,CAAC,OAAe,EAAE,UAAkB;QACpD,kEAAkE;QAClE,sEAAsE;QACtE,+DAA+D;QAC/D,iEAAiE;QACjE,MAAM,KAAK,GAAG,IAAI,CAAC,gBAAgB;YACjC,CAAC,CAAC,OAAO,GAAG,IAAI,GAAG,UAAU,GAAG,IAAI,GAAG,IAAI,CAAC,gBAAgB;YAC5D,CAAC,CAAC,OAAO,GAAG,IAAI,GAAG,UAAU,CAAC;QAChC,OAAO,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IACjE,CAAC;IAEO,OAAO,CAAC,KAAoB;QAClC,OAAO,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC,SAAS,CAAC,IAAI,IAAI,CAAC,MAAM,CAAC;IACvD,CAAC;IAED,KAAK,CAAC,GAAG,CAAC,OAAe,EAAE,UAAkB;QAC3C,IAAI,CAAC,IAAI,CAAC,OAAO;YAAE,OAAO,IAAI,CAAC;QAE/B,MAAM,GAAG,GAAG,IAAI,CAAC,UAAU,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC;QAEjD,wCAAwC;QACxC,MAAM,QAAQ,GAAG,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAC3C,IAAI,QAAQ,IAAI,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC;YACvC,IAAI,CAAC,IAAI,EAAE,CAAC;YACZ,OAAO,QAAQ,CAAC,MAAM,CAAC;QACzB,CAAC;QAED,6BAA6B;QAC7B,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YACxC,IAAI,GAAG,KAAK,IAAI,EAAE,CAAC;gBACjB,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAkB,CAAC;gBAC/C,IAAI,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;oBACxB,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;oBACjC,IAAI,CAAC,IAAI,EAAE,CAAC;oBACZ,OAAO,KAAK,CAAC,MAAM,CAAC;gBACtB,CAAC;gBACD,2DAA2D;gBAC3D,2BAA2B;gBAC3B,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC;oBACxB,KAAK,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;gBAChC,CAAC;YACH,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACP,qCAAqC;QACvC,CAAC;QAED,IAAI,CAAC,MAAM,EAAE,CAAC;QACd,OAAO,IAAI,CAAC;IACd,CAAC;IAED,KAAK,CAAC,GAAG,CAAC,OAAe,EAAE,UAAkB,EAAE,MAAS;QACtD,IAAI,CAAC,IAAI,CAAC,OAAO;YAAE,OAAO;QAE1B,MAAM,GAAG,GAAG,IAAI,CAAC,UAAU,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC;QACjD,MAAM,KAAK,GAAkB,EAAE,GAAG,EAAE,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,MAAM,EAAE,CAAC;QAEpE,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;QACjC,IAAI,CAAC;YACH,MAAM,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC;QACrD,CAAC;QAAC,MAAM,CAAC;YACP,qDAAqD;QACvD,CAAC;IACH,CAAC;IAED,KAAK,CAAC,GAAG,CAAC,OAAe,EAAE,UAAkB;QAC3C,OAAO,CAAC,MAAM,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC,KAAK,IAAI,CAAC;IACxD,CAAC;IAED,KAAK,CAAC,KAAK;QACT,IAAI,CAAC,WAAW,CAAC,KAAK,EAAE,CAAC;QACzB,IAAI,CAAC,IAAI,GAAG,CAAC,CAAC;QACd,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC;QAChB,IAAI,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;YACvB,IAAI,CAAC;gBAAC,MAAM,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;YAAC,CAAC;YAAC,MAAM,CAAC,CAAC,YAAY,CAAC,CAAC;QAC5D,CAAC;IACH,CAAC;IAED,KAAK,CAAC,KAAK;QACT,IAAI,WAAW,GAAG,CAAC,CAAC;QACpB,IAAI,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;YACvB,IAAI,CAAC;gBAAC,WAAW,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;YAAC,CAAC;YAAC,MAAM,CAAC,CAAC,YAAY,CAAC,CAAC;QAC1E,CAAC;QACD,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC;QACtC,OAAO;YACL,aAAa,EAAE,IAAI,CAAC,WAAW,CAAC,IAAI;YACpC,WAAW;YACX,OAAO,EAAE,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;YAC1C,OAAO,EAAE,IAAI,CAAC,OAAO,CAAC,IAAI;SAC3B,CAAC;IACJ,CAAC;CACF;AAED,qEAAqE;AACrE,qEAAqE;AACrE,iEAAiE;AACjE,qEAAqE;AACrE,6BAA6B;AAC7B,IAAI,mBAAmB,GAA+B,IAAI,CAAC;AAE3D,MAAM,UAAU,sBAAsB,CAAC,OAAoC;IACzE,MAAM,eAAe,GAAG,OAAO,EAAE,gBAAgB,IAAI,EAAE,CAAC;IACxD,IAAI,CAAC,mBAAmB,IAAI,mBAAmB,CAAC,mBAAmB,EAAE,KAAK,eAAe,EAAE,CAAC;QAC1F,mBAAmB,GAAG,IAAI,mBAAmB,CAAC,OAAO,CAAC,CAAC;IACzD,CAAC;IACD,OAAO,mBAAmB,CAAC;AAC7B,CAAC;AAED,MAAM,UAAU,wBAAwB;IACtC,mBAAmB,GAAG,IAAI,CAAC;AAC7B,CAAC"}
1
+ {"version":3,"file":"classification-cache.js","sourceRoot":"","sources":["../../src/cache/classification-cache.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,59 @@
1
+ /**
2
+ * Package coordinate detection for cache path layout.
3
+ *
4
+ * The tree-cache backend (R2 / local-fs) uses the coordinate to build a
5
+ * package-aware key layout:
6
+ *
7
+ * tree/<ecosystem>/<name>@<version>/<4hex>/<sha>.json (published coords)
8
+ * tree/_local/<name>@<version>/<4hex>/<sha>.json (repo-root manifest)
9
+ * tree/_unowned/<4hex>/<sha>.json (no coordinate)
10
+ *
11
+ * Coordinate is resolved ONCE per scan from the repo root. We deliberately
12
+ * keep the extractor minimal (only manifest files we can parse with zero
13
+ * deps) so it can be folded into hot paths without measurable overhead.
14
+ *
15
+ * What's intentionally *not* in scope here:
16
+ * - per-file coordinate from `node_modules/<pkg>/...` paths (deferred until
17
+ * we actually scan transitive deps)
18
+ * - lockfile-derived coordinates
19
+ * - Maven `<artifactId>` resolution from a multi-module reactor
20
+ *
21
+ * For the first-party github sweep use case, every file in a repo shares
22
+ * the same coordinate (or falls through to `_unowned`), which is exactly
23
+ * what we want for cross-runner cache sharing.
24
+ */
25
+ export type Ecosystem = 'npm' | 'maven' | 'pypi' | 'cargo' | 'go' | '_local' | '_unowned';
26
+ export interface PackageCoordinate {
27
+ ecosystem: Ecosystem;
28
+ /** Package name in its ecosystem's canonical form (lower-case, normalized). */
29
+ name: string;
30
+ /** Resolved version string, or `'HEAD'` for `_local`. */
31
+ version: string;
32
+ }
33
+ /**
34
+ * The sentinel coordinate emitted when the repo has no detectable manifest.
35
+ *
36
+ * Tree-cache content still gets cached, just under `_unowned/<4hex>/<sha>`.
37
+ * Re-using the singleton means the path layout is constant for un-coord'd
38
+ * scans and avoids per-file object allocation.
39
+ */
40
+ export declare const UNOWNED: PackageCoordinate;
41
+ /**
42
+ * Render the coordinate as a stable path prefix and a stable hash prefix.
43
+ *
44
+ * `pathSegment` is what the backend uses to build the R2 / local-fs key.
45
+ * `hashPrefix` is what cache-key composers fold into the content hash so
46
+ * the SHA itself encodes the coordinate (no collision across packages).
47
+ */
48
+ export declare function coordinateSegments(c: PackageCoordinate): {
49
+ pathSegment: string;
50
+ hashPrefix: string;
51
+ };
52
+ /**
53
+ * Detect a package coordinate from the repo root manifest files.
54
+ *
55
+ * Synchronous because it runs once per scan at scanner entry and the
56
+ * disk reads are tiny (`package.json` / `pom.xml`).
57
+ */
58
+ export declare function detectCoordinate(repoRoot: string): PackageCoordinate;
59
+ //# sourceMappingURL=coordinate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"coordinate.d.ts","sourceRoot":"","sources":["../../src/cache/coordinate.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAKH,MAAM,MAAM,SAAS,GAAG,KAAK,GAAG,OAAO,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,GAAG,QAAQ,GAAG,UAAU,CAAC;AAE1F,MAAM,WAAW,iBAAiB;IAChC,SAAS,EAAE,SAAS,CAAC;IACrB,+EAA+E;IAC/E,IAAI,EAAE,MAAM,CAAC;IACb,yDAAyD;IACzD,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;;;;;GAMG;AACH,eAAO,MAAM,OAAO,EAAE,iBAIpB,CAAC;AAEH;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,CAAC,EAAE,iBAAiB,GAAG;IAAE,WAAW,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,CASpG;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,iBAAiB,CAwFpE"}