codesift-mcp 0.8.11 → 0.8.15

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 (32) hide show
  1. package/dist/cli/hooks.d.ts.map +1 -1
  2. package/dist/cli/hooks.js +31 -2
  3. package/dist/cli/hooks.js.map +1 -1
  4. package/dist/cli/setup.d.ts.map +1 -1
  5. package/dist/cli/setup.js +77 -9
  6. package/dist/cli/setup.js.map +1 -1
  7. package/dist/register-tools.d.ts.map +1 -1
  8. package/dist/register-tools.js +90 -3
  9. package/dist/register-tools.js.map +1 -1
  10. package/dist/search/static-embedding-provider.d.ts.map +1 -1
  11. package/dist/search/static-embedding-provider.js +9 -1
  12. package/dist/search/static-embedding-provider.js.map +1 -1
  13. package/dist/storage/group-registry.d.ts +51 -0
  14. package/dist/storage/group-registry.d.ts.map +1 -0
  15. package/dist/storage/group-registry.js +263 -0
  16. package/dist/storage/group-registry.js.map +1 -0
  17. package/dist/tools/cross-repo-contract-tools.d.ts +137 -0
  18. package/dist/tools/cross-repo-contract-tools.d.ts.map +1 -0
  19. package/dist/tools/cross-repo-contract-tools.js +593 -0
  20. package/dist/tools/cross-repo-contract-tools.js.map +1 -0
  21. package/dist/tools/cross-repo-outbound-lexer.d.ts +35 -0
  22. package/dist/tools/cross-repo-outbound-lexer.d.ts.map +1 -0
  23. package/dist/tools/cross-repo-outbound-lexer.js +594 -0
  24. package/dist/tools/cross-repo-outbound-lexer.js.map +1 -0
  25. package/dist/tools/index-tools.d.ts.map +1 -1
  26. package/dist/tools/index-tools.js +4 -1
  27. package/dist/tools/index-tools.js.map +1 -1
  28. package/dist/tools/wiki-tools.d.ts +7 -0
  29. package/dist/tools/wiki-tools.d.ts.map +1 -1
  30. package/dist/tools/wiki-tools.js +33 -1
  31. package/dist/tools/wiki-tools.js.map +1 -1
  32. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"static-embedding-provider.d.ts","sourceRoot":"","sources":["../../src/search/static-embedding-provider.ts"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAqCtE,eAAO,MAAM,0BAA0B,QAAS,CAAC;AACjD,eAAO,MAAM,mBAAmB,qBAA4B,CAAC;AA2E7D,qBAAa,uBAAwB,YAAW,iBAAiB;;IAC/D,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;gBAIX,KAAK,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM;IAO5C;;;;;OAKG;IACH,IAAI,UAAU,IAAI,MAAM,CAEvB;IAED;;;;OAIG;IACG,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,KAAK,GAAE,aAA0B,GAAG,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC;CAMrF;AAED,8DAA8D;AAC9D,wBAAgB,8BAA8B,IAAI,IAAI,CAKrD"}
1
+ {"version":3,"file":"static-embedding-provider.d.ts","sourceRoot":"","sources":["../../src/search/static-embedding-provider.ts"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAqCtE,eAAO,MAAM,0BAA0B,QAAS,CAAC;AACjD,eAAO,MAAM,mBAAmB,qBAA4B,CAAC;AA2E7D,qBAAa,uBAAwB,YAAW,iBAAiB;;IAC/D,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;gBAIX,KAAK,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM;IAO5C;;;;;OAKG;IACH,IAAI,UAAU,IAAI,MAAM,CASvB;IAED;;;;OAIG;IACG,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,KAAK,GAAE,aAA0B,GAAG,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC;CAMrF;AAED,8DAA8D;AAC9D,wBAAgB,8BAA8B,IAAI,IAAI,CAKrD"}
@@ -124,7 +124,15 @@ export class StaticEmbeddingProvider {
124
124
  * with a different width than the static table records.
125
125
  */
126
126
  get dimensions() {
127
- return this.#realDims ?? lookupStaticDimensions(this.model);
127
+ if (this.#realDims !== null)
128
+ return this.#realDims;
129
+ // embed() hasn't run yet (all-cache-hit indexing path): report the real
130
+ // column count from the module cache if the model is already loaded, so
131
+ // persisted EmbeddingMeta records the true width instead of the static
132
+ // fallback. Read-only — the authoritative #realDims is still set by embed()
133
+ // from actual output, never pinned early from a read.
134
+ const cached = staticModelCache.get(this.model);
135
+ return cached?.cols ?? lookupStaticDimensions(this.model);
128
136
  }
129
137
  /**
130
138
  * `mode` is accepted to satisfy the EmbeddingProvider contract but IGNORED:
@@ -1 +1 @@
1
- {"version":3,"file":"static-embedding-provider.js","sourceRoot":"","sources":["../../src/search/static-embedding-provider.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"static-embedding-provider.js","sourceRoot":"","sources":["../../src/search/static-embedding-provider.ts"],"names":[],"mappings":"AAAA,2CAA2C;AAC3C,EAAE;AACF,+EAA+E;AAC/E,iFAAiF;AACjF,6EAA6E;AAC7E,wEAAwE;AACxE,EAAE;AACF,8EAA8E;AAC9E,mFAAmF;AACnF,0EAA0E;AAE1E,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AAC9D,OAAO,EAAE,gBAAgB,EAAE,SAAS,EAAwB,MAAM,gCAAgC,CAAC;AACnG,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAE1C,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AAEzE,MAAM,gBAAgB,GAAG,mBAAmB,CAAC;AAC7C,MAAM,cAAc,GAAG,gBAAgB,CAAC;AAExC;;;;GAIG;AACH,MAAM,iBAAiB,GAAqC;IAC1D,2BAA2B,EAAE,GAAG;IAChC,0BAA0B,EAAE,GAAG;CAChC,CAAC;AACF,MAAM,mBAAmB,GAAG,GAAG,CAAC;AAEhC,SAAS,sBAAsB,CAAC,KAAa;IAC3C,OAAO,iBAAiB,CAAC,KAAK,CAAC,IAAI,mBAAmB,CAAC;AACzD,CAAC;AAWD,+EAA+E;AAC/E,+EAA+E;AAC/E,MAAM,gBAAgB,GAAG,IAAI,GAAG,EAA6B,CAAC;AAC9D,iFAAiF;AACjF,MAAM,kBAAkB,GAAG,IAAI,GAAG,EAAsC,CAAC;AACzE,oEAAoE;AACpE,0FAA0F;AAC1F,MAAM,CAAC,MAAM,0BAA0B,GAAG,MAAM,CAAC;AACjD,MAAM,CAAC,MAAM,mBAAmB,GAAG,IAAI,GAAG,EAAkB,CAAC;AAC7D,IAAI,gBAAgB,GAAG,KAAK,CAAC;AAE7B,SAAS,eAAe;IACtB,OAAO,IAAI,CAAC,UAAU,EAAE,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;AAC9C,CAAC;AAED,KAAK,UAAU,kBAAkB,CAAC,KAAa,EAAE,QAAgB;IAC/D,IAAI,CAAC;QACH,MAAM,CAAC,eAAe,EAAE,aAAa,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;YACzD,eAAe,CAAC,KAAK,EAAE,gBAAgB,EAAE,QAAQ,CAAC;YAClD,eAAe,CAAC,KAAK,EAAE,cAAc,EAAE,QAAQ,CAAC;SACjD,CAAC,CAAC;QAEH,MAAM,YAAY,GAAG,MAAM,QAAQ,CAAC,eAAe,CAAC,CAAC;QACrD,MAAM,MAAM,GAAG,gBAAgB,CAAC,YAAY,CAAC,CAAC;QAC9C,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;YACrB,MAAM,IAAI,KAAK,CAAC,yDAAyD,CAAC,CAAC;QAC7E,oEAAoE;QACpE,IAAI,KAAsB,CAAC;QAC3B,IAAI,CAAC;YACH,KAAK,GAAG,SAAS,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;QAC1C,CAAC;QAAC,MAAM,CAAC;YACP,KAAK,GAAG,MAAM,CAAC,CAAC,CAAE,CAAC;QACrB,CAAC;QACD,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC;QAEjC,MAAM,aAAa,GAAG,MAAM,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC,CAAC;QAC5D,IAAI,YAAqB,CAAC;QAC1B,IAAI,CAAC;YACH,YAAY,GAAG,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC;QAC3C,CAAC;QAAC,OAAO,GAAY,EAAE,CAAC;YACtB,MAAM,GAAG,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YAC7D,MAAM,IAAI,KAAK,CAAC,gDAAgD,GAAG,EAAE,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,CAAC;QACzF,CAAC;QACD,MAAM,KAAK,GAAG,UAAU,CAAC,YAAY,CAAC,CAAC;QAEvC,MAAM,MAAM,GAAsB,EAAE,MAAM,EAAE,KAAK,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;QAC5E,gBAAgB,CAAC,GAAG,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;QACpC,OAAO,MAAM,CAAC;IAChB,CAAC;IAAC,OAAO,GAAY,EAAE,CAAC;QACtB,qDAAqD;QACrD,mBAAmB,CAAC,GAAG,CAAC,KAAK,EAAE,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;QAC3C,iFAAiF;QACjF,kBAAkB,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACjC,IAAI,CAAC,gBAAgB,EAAE,CAAC;YACtB,gBAAgB,GAAG,IAAI,CAAC;YACxB,MAAM,GAAG,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YAC7D,OAAO,CAAC,KAAK,CAAC,qCAAqC,KAAK,iBAAiB,GAAG,GAAG,CAAC,CAAC;QACnF,CAAC;QACD,MAAM,GAAG,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QAC7D,MAAM,IAAI,KAAK,CAAC,0CAA0C,KAAK,KAAK,GAAG,EAAE,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,CAAC;IAC7F,CAAC;AACH,CAAC;AAED,KAAK,UAAU,eAAe,CAAC,KAAa,EAAE,QAAgB;IAC5D,MAAM,MAAM,GAAG,gBAAgB,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;IAC3C,IAAI,MAAM;QAAE,OAAO,MAAM,CAAC;IAE1B,2EAA2E;IAC3E,MAAM,QAAQ,GAAG,mBAAmB,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;IAChD,IAAI,QAAQ,KAAK,SAAS,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,QAAQ,GAAG,0BAA0B,EAAE,CAAC;QACjF,MAAM,IAAI,KAAK,CAAC,2BAA2B,KAAK,4BAA4B,CAAC,CAAC;IAChF,CAAC;IAED,gEAAgE;IAChE,+EAA+E;IAC/E,MAAM,QAAQ,GAAG,kBAAkB,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;IAC/C,IAAI,QAAQ;QAAE,OAAO,QAAQ,CAAC;IAE9B,MAAM,OAAO,GAAG,kBAAkB,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;IACpD,kBAAkB,CAAC,GAAG,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;IACvC,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,MAAM,OAAO,uBAAuB;IACzB,KAAK,CAAS;IACd,SAAS,CAAS;IAC3B,SAAS,GAAkB,IAAI,CAAC;IAEhC,YAAY,KAAa,EAAE,QAAiB;QAC1C,IAAI,CAAC,KAAK,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE;YACzB,MAAM,IAAI,KAAK,CAAC,8CAA8C,CAAC,CAAC;QAClE,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QACnB,IAAI,CAAC,SAAS,GAAG,QAAQ,IAAI,eAAe,EAAE,CAAC;IACjD,CAAC;IAED;;;;;OAKG;IACH,IAAI,UAAU;QACZ,IAAI,IAAI,CAAC,SAAS,KAAK,IAAI;YAAE,OAAO,IAAI,CAAC,SAAS,CAAC;QACnD,wEAAwE;QACxE,wEAAwE;QACxE,uEAAuE;QACvE,4EAA4E;QAC5E,sDAAsD;QACtD,MAAM,MAAM,GAAG,gBAAgB,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAChD,OAAO,MAAM,EAAE,IAAI,IAAI,sBAAsB,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC5D,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,KAAK,CAAC,KAAe,EAAE,QAAuB,UAAU;QAC5D,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,EAAE,CAAC;QAClC,MAAM,MAAM,GAAG,MAAM,eAAe,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC;QACjE,IAAI,CAAC,SAAS,GAAG,MAAM,CAAC,IAAI,CAAC;QAC7B,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC;IAC9G,CAAC;CACF;AAED,8DAA8D;AAC9D,MAAM,UAAU,8BAA8B;IAC5C,gBAAgB,CAAC,KAAK,EAAE,CAAC;IACzB,kBAAkB,CAAC,KAAK,EAAE,CAAC;IAC3B,mBAAmB,CAAC,KAAK,EAAE,CAAC;IAC5B,gBAAgB,GAAG,KAAK,CAAC;AAC3B,CAAC"}
@@ -0,0 +1,51 @@
1
+ import type { GroupRegistry, RepoGroup } from "../types.js";
2
+ /**
3
+ * Return the canonical path for the group registry file inside a data directory.
4
+ */
5
+ export declare function getGroupRegistryPath(dataDir: string): string;
6
+ /**
7
+ * Load the group registry from disk.
8
+ *
9
+ * - ENOENT → returns empty registry (first run)
10
+ * - Corrupt JSON or invalid structure → renames file to groups.json.corrupt-<ts>,
11
+ * logs a warning, and returns empty registry (data is never silently destroyed)
12
+ * - Other I/O error (EACCES, EMFILE, …) → throws so callers can propagate
13
+ */
14
+ export declare function loadGroupRegistry(registryPath: string): Promise<GroupRegistry>;
15
+ /**
16
+ * Save the group registry atomically.
17
+ * Writes to a temp file first, then renames to prevent partial reads.
18
+ */
19
+ export declare function saveGroupRegistry(registryPath: string, registry: GroupRegistry): Promise<void>;
20
+ /**
21
+ * Register or update a group. Duplicate repos are deduplicated.
22
+ * On overwrite: preserves created_at, updates updated_at.
23
+ *
24
+ * Mutations are serialized per registry path (CRITICAL-3 R-M-W race fix).
25
+ * Invalid/reserved names are rejected immediately (CRITICAL-2).
26
+ */
27
+ export declare function registerGroup(registryPath: string, input: {
28
+ name: string;
29
+ repos: string[];
30
+ description?: string;
31
+ }): Promise<void>;
32
+ /**
33
+ * Get a single group by name. Returns null if not found.
34
+ *
35
+ * Read-only: catches non-fatal load errors and returns null with a warning.
36
+ */
37
+ export declare function getGroup(registryPath: string, name: string): Promise<RepoGroup | null>;
38
+ /**
39
+ * List all registered groups.
40
+ *
41
+ * Read-only: catches non-fatal load errors and returns empty array with a warning.
42
+ */
43
+ export declare function listGroups(registryPath: string): Promise<RepoGroup[]>;
44
+ /**
45
+ * Remove a group by name.
46
+ * Returns true if it existed and was removed, false otherwise (idempotent).
47
+ *
48
+ * Mutations are serialized per registry path (CRITICAL-3 R-M-W race fix).
49
+ */
50
+ export declare function removeGroup(registryPath: string, name: string): Promise<boolean>;
51
+ //# sourceMappingURL=group-registry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"group-registry.d.ts","sourceRoot":"","sources":["../../src/storage/group-registry.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAG5D;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAE5D;AAyCD;;;;;;;GAOG;AACH,wBAAsB,iBAAiB,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC,CA6BpF;AAqBD;;;GAGG;AACH,wBAAsB,iBAAiB,CACrC,YAAY,EAAE,MAAM,EACpB,QAAQ,EAAE,aAAa,GACtB,OAAO,CAAC,IAAI,CAAC,CAGf;AAED;;;;;;GAMG;AACH,wBAAsB,aAAa,CACjC,YAAY,EAAE,MAAM,EACpB,KAAK,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,EAAE,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAA;CAAE,GAC7D,OAAO,CAAC,IAAI,CAAC,CAiDf;AAED;;;;GAIG;AACH,wBAAsB,QAAQ,CAC5B,YAAY,EAAE,MAAM,EACpB,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC,CAS3B;AAED;;;;GAIG;AACH,wBAAsB,UAAU,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC,CAW3E;AAED;;;;;GAKG;AACH,wBAAsB,WAAW,CAC/B,YAAY,EAAE,MAAM,EACpB,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,OAAO,CAAC,CAalB"}
@@ -0,0 +1,263 @@
1
+ import { readFile, rename } from "node:fs/promises";
2
+ import { join, resolve } from "node:path";
3
+ import { atomicWriteFile } from "./_shared.js";
4
+ /**
5
+ * Return the canonical path for the group registry file inside a data directory.
6
+ */
7
+ export function getGroupRegistryPath(dataDir) {
8
+ return join(dataDir, "groups.json");
9
+ }
10
+ // ---------------------------------------------------------------------------
11
+ // CRITICAL-3: per-path promise chain to serialize R-M-W mutations
12
+ // (mirrors writeLocks pattern from index-store.ts)
13
+ // ---------------------------------------------------------------------------
14
+ const writeLocks = new Map();
15
+ function chainMutation(registryPath, fn) {
16
+ // FIX-A: normalize path so "./x/groups.json" and "x/groups.json" share a lock
17
+ const lockKey = resolve(registryPath);
18
+ const prev = writeLocks.get(lockKey) ?? Promise.resolve();
19
+ const next = prev.then(fn);
20
+ // Swallow errors from the chain link so future callers aren't blocked
21
+ writeLocks.set(lockKey, next.catch(() => { }));
22
+ return next;
23
+ }
24
+ // ---------------------------------------------------------------------------
25
+ // CRITICAL-2: reserved name guard
26
+ // ---------------------------------------------------------------------------
27
+ const RESERVED_NAMES = /^(__proto__|constructor|prototype)$/;
28
+ function assertValidName(name) {
29
+ if (name.trim() === "") {
30
+ throw new Error(`Invalid group name: name must not be empty or whitespace-only.`);
31
+ }
32
+ if (RESERVED_NAMES.test(name)) {
33
+ throw new Error(`Invalid group name "${name}": reserved prototype/constructor names are not allowed.`);
34
+ }
35
+ }
36
+ // ---------------------------------------------------------------------------
37
+ // CRITICAL-1: split load semantics
38
+ // ENOENT → empty registry (legit first run)
39
+ // JSON/struct bad → quarantine (rename to .corrupt-<ts>), return empty
40
+ // other read error → THROW (prevents silent wipe on EACCES/EMFILE)
41
+ // ---------------------------------------------------------------------------
42
+ /**
43
+ * Load the group registry from disk.
44
+ *
45
+ * - ENOENT → returns empty registry (first run)
46
+ * - Corrupt JSON or invalid structure → renames file to groups.json.corrupt-<ts>,
47
+ * logs a warning, and returns empty registry (data is never silently destroyed)
48
+ * - Other I/O error (EACCES, EMFILE, …) → throws so callers can propagate
49
+ */
50
+ export async function loadGroupRegistry(registryPath) {
51
+ let raw;
52
+ try {
53
+ raw = await readFile(registryPath, "utf-8");
54
+ }
55
+ catch (err) {
56
+ const code = err.code;
57
+ if (code === "ENOENT") {
58
+ return emptyGroupRegistry();
59
+ }
60
+ // EACCES, EMFILE, etc. — throw so mutations don't overwrite with empty state
61
+ throw err;
62
+ }
63
+ // File exists — try to parse
64
+ let parsed;
65
+ try {
66
+ parsed = JSON.parse(raw);
67
+ }
68
+ catch {
69
+ await quarantineCorrupt(registryPath);
70
+ return emptyGroupRegistry();
71
+ }
72
+ if (isValidGroupRegistry(parsed)) {
73
+ return parsed;
74
+ }
75
+ // Structurally invalid (valid JSON but wrong shape)
76
+ await quarantineCorrupt(registryPath);
77
+ return emptyGroupRegistry();
78
+ }
79
+ /**
80
+ * Rename the corrupt file to a timestamped sibling so data is never lost.
81
+ * Best-effort — if renaming fails we swallow the error (we already know the
82
+ * data is unusable).
83
+ */
84
+ async function quarantineCorrupt(registryPath) {
85
+ const dest = `${registryPath}.corrupt-${Date.now()}`;
86
+ try {
87
+ await rename(registryPath, dest);
88
+ console.warn(`[codesift] group-registry: corrupt file quarantined as ${dest}`);
89
+ }
90
+ catch {
91
+ console.warn(`[codesift] group-registry: failed to quarantine corrupt file at ${registryPath}`);
92
+ }
93
+ }
94
+ /**
95
+ * Save the group registry atomically.
96
+ * Writes to a temp file first, then renames to prevent partial reads.
97
+ */
98
+ export async function saveGroupRegistry(registryPath, registry) {
99
+ const data = JSON.stringify(registry);
100
+ await atomicWriteFile(registryPath, data);
101
+ }
102
+ /**
103
+ * Register or update a group. Duplicate repos are deduplicated.
104
+ * On overwrite: preserves created_at, updates updated_at.
105
+ *
106
+ * Mutations are serialized per registry path (CRITICAL-3 R-M-W race fix).
107
+ * Invalid/reserved names are rejected immediately (CRITICAL-2).
108
+ */
109
+ export async function registerGroup(registryPath, input) {
110
+ assertValidName(input.name);
111
+ // FIX-B: runtime input validation
112
+ if (!Array.isArray(input.repos)) {
113
+ throw new Error(`Invalid repos: expected an array of strings, got ${typeof input.repos}.`);
114
+ }
115
+ for (const r of input.repos) {
116
+ if (typeof r !== "string" || r === "") {
117
+ throw new Error(`Invalid repos: every element must be a non-empty string (got ${JSON.stringify(r)}).`);
118
+ }
119
+ }
120
+ if (input.description !== undefined && typeof input.description !== "string") {
121
+ throw new Error(`Invalid description: expected a string, got ${typeof input.description}.`);
122
+ }
123
+ return chainMutation(registryPath, async () => {
124
+ const registry = await loadGroupRegistry(registryPath);
125
+ const now = Date.now();
126
+ const existing = Object.hasOwn(registry.groups, input.name)
127
+ ? registry.groups[input.name]
128
+ : undefined;
129
+ const deduped = [...new Set(input.repos)];
130
+ const group = existing
131
+ ? {
132
+ name: input.name,
133
+ repos: deduped,
134
+ ...(input.description !== undefined ? { description: input.description } : {}),
135
+ created_at: existing.created_at,
136
+ updated_at: now,
137
+ }
138
+ : {
139
+ name: input.name,
140
+ repos: deduped,
141
+ ...(input.description !== undefined ? { description: input.description } : {}),
142
+ created_at: now,
143
+ updated_at: now,
144
+ };
145
+ registry.groups[input.name] = group;
146
+ registry.updated_at = now;
147
+ await saveGroupRegistry(registryPath, registry);
148
+ });
149
+ }
150
+ /**
151
+ * Get a single group by name. Returns null if not found.
152
+ *
153
+ * Read-only: catches non-fatal load errors and returns null with a warning.
154
+ */
155
+ export async function getGroup(registryPath, name) {
156
+ let registry;
157
+ try {
158
+ registry = await loadGroupRegistry(registryPath);
159
+ }
160
+ catch {
161
+ console.warn(`[codesift] group-registry: could not read registry at ${registryPath}`);
162
+ return null;
163
+ }
164
+ return Object.hasOwn(registry.groups, name) ? registry.groups[name] : null;
165
+ }
166
+ /**
167
+ * List all registered groups.
168
+ *
169
+ * Read-only: catches non-fatal load errors and returns empty array with a warning.
170
+ */
171
+ export async function listGroups(registryPath) {
172
+ let registry;
173
+ try {
174
+ registry = await loadGroupRegistry(registryPath);
175
+ }
176
+ catch {
177
+ console.warn(`[codesift] group-registry: could not read registry at ${registryPath}`);
178
+ return [];
179
+ }
180
+ return Object.keys(registry.groups)
181
+ .filter((k) => Object.hasOwn(registry.groups, k))
182
+ .map((k) => registry.groups[k]);
183
+ }
184
+ /**
185
+ * Remove a group by name.
186
+ * Returns true if it existed and was removed, false otherwise (idempotent).
187
+ *
188
+ * Mutations are serialized per registry path (CRITICAL-3 R-M-W race fix).
189
+ */
190
+ export async function removeGroup(registryPath, name) {
191
+ return chainMutation(registryPath, async () => {
192
+ const registry = await loadGroupRegistry(registryPath);
193
+ if (!Object.hasOwn(registry.groups, name)) {
194
+ return false;
195
+ }
196
+ delete registry.groups[name];
197
+ registry.updated_at = Date.now();
198
+ await saveGroupRegistry(registryPath, registry);
199
+ return true;
200
+ });
201
+ }
202
+ // ---------------------------------------------------------------------------
203
+ // Internal helpers
204
+ // ---------------------------------------------------------------------------
205
+ function emptyGroupRegistry() {
206
+ return { groups: {}, updated_at: Date.now() };
207
+ }
208
+ /**
209
+ * Deep structural guard for a raw parsed GroupRegistry value.
210
+ * Mirrors the Array.isArray improvements from hash-snapshot.ts.
211
+ */
212
+ function isValidGroupRegistry(value) {
213
+ if (typeof value !== "object" || value === null || Array.isArray(value)) {
214
+ return false;
215
+ }
216
+ const obj = value;
217
+ if (typeof obj["updated_at"] !== "number")
218
+ return false;
219
+ const groups = obj["groups"];
220
+ if (typeof groups !== "object" || groups === null || Array.isArray(groups)) {
221
+ return false;
222
+ }
223
+ // FIX-C: validate each group entry, guarding against prototype pollution,
224
+ // key/name mismatch, and reserved keys crafted on disk
225
+ for (const key of Object.keys(groups)) {
226
+ if (!Object.hasOwn(groups, key))
227
+ continue;
228
+ // Reject reserved keys even if they somehow appear in the JSON
229
+ if (RESERVED_NAMES.test(key))
230
+ return false;
231
+ const entry = groups[key];
232
+ if (!isValidRepoGroup(entry))
233
+ return false;
234
+ // key must equal the group's own name field — mismatch = tampered file
235
+ if (entry["name"] !== key)
236
+ return false;
237
+ }
238
+ return true;
239
+ }
240
+ function isValidRepoGroup(value) {
241
+ if (typeof value !== "object" || value === null || Array.isArray(value)) {
242
+ return false;
243
+ }
244
+ const obj = value;
245
+ if (typeof obj["name"] !== "string")
246
+ return false;
247
+ if (typeof obj["created_at"] !== "number")
248
+ return false;
249
+ if (typeof obj["updated_at"] !== "number")
250
+ return false;
251
+ const repos = obj["repos"];
252
+ if (!Array.isArray(repos))
253
+ return false;
254
+ for (const r of repos) {
255
+ if (typeof r !== "string")
256
+ return false;
257
+ }
258
+ // description is optional — if present it must be a string
259
+ if (Object.hasOwn(obj, "description") && typeof obj["description"] !== "string")
260
+ return false;
261
+ return true;
262
+ }
263
+ //# sourceMappingURL=group-registry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"group-registry.js","sourceRoot":"","sources":["../../src/storage/group-registry.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,137 @@
1
+ /**
2
+ * Cross-repo contract adapters (Task 12) and outbound HTTP call extractor (Task 13).
3
+ *
4
+ * Normalises endpoint shapes from Hono, NestJS, and Next.js into the shared
5
+ * RepoEndpoint type so that the outbound extractor (T13) and matcher (T14)
6
+ * can work against a single canonical form.
7
+ *
8
+ * extractOutboundCalls: lexer-based consumer-side outbound HTTP call extractor.
9
+ * Supports fetch, axios.{get|post|put|patch|delete}, got.{get|post|put|patch|delete}.
10
+ * Uses a single-pass state-machine lexer (cross-repo-outbound-lexer.ts) so calls
11
+ * inside comments, string literals, template literals, and regex literals are never
12
+ * falsely reported.
13
+ */
14
+ import type { RepoEndpoint, ContractMatch } from "../types.js";
15
+ import type { ApiContractResult as HonoContractResult } from "./hono-api-contract.js";
16
+ import type { NestRouteInventoryResult } from "./nest-tools.js";
17
+ import type { ApiContractResult as NextjsContractResult } from "./nextjs-api-contract-tools.js";
18
+ /**
19
+ * Replace all path-parameter segments with the canonical `{param}` placeholder.
20
+ *
21
+ * Recognised styles:
22
+ * - Express / Hono `:name`
23
+ * - OpenAPI / NestJS `{name}`
24
+ * - Next.js `[name]`
25
+ * - Next.js catch-all `[...name]`
26
+ *
27
+ * Trailing slashes are stripped (except for a bare "/").
28
+ * Method strings are UPPERCASED by callers; this function only handles paths.
29
+ */
30
+ export declare function normalizePathParams(path: string): string;
31
+ /**
32
+ * Adapt an `extractApiContract` result (Hono) into `RepoEndpoint[]`.
33
+ *
34
+ * Only the `summary` format carries the per-route list; `openapi` format and
35
+ * missing/undefined summary both return [].
36
+ */
37
+ export declare function adaptHonoContract(repo: string, r: HonoContractResult): RepoEndpoint[];
38
+ /**
39
+ * Adapt a `nestRouteInventory` result into `RepoEndpoint[]`.
40
+ *
41
+ * `NestRouteEntry.file` is a required string field — the value is used as-is
42
+ * (may be "" for entries where the controller file couldn't be resolved).
43
+ */
44
+ export declare function adaptNestInventory(repo: string, r: NestRouteInventoryResult): RepoEndpoint[];
45
+ /**
46
+ * Adapt a Next.js `ApiContractResult` into `RepoEndpoint[]`.
47
+ *
48
+ * `HandlerShape.method` is a single `HttpMethod` string per entry (Next.js
49
+ * emits one handler per HTTP verb), so each handler maps to one RepoEndpoint.
50
+ */
51
+ export declare function adaptNextjsContract(repo: string, r: NextjsContractResult): RepoEndpoint[];
52
+ /** A single detected outbound HTTP call from consumer source. */
53
+ export interface OutboundCall {
54
+ /** The static URL prefix extracted from the call. Paths only — origin stripped. */
55
+ url_prefix: string;
56
+ /** HTTP method, uppercased. Defaults to "GET" when not detectable. */
57
+ method: string;
58
+ /** True when the URL contains a dynamic segment (template var, concat, path param). */
59
+ partial: boolean;
60
+ /** Source file path as provided to extractOutboundCalls. */
61
+ file: string;
62
+ /** 1-based line number of the call in the original (pre-strip) source. */
63
+ line: number;
64
+ }
65
+ /**
66
+ * Match producer `RepoEndpoint[]` against consumer outbound calls (annotated with repo).
67
+ *
68
+ * Matching rules:
69
+ * - Same HTTP method (case-insensitive, already uppercased by adapters)
70
+ * - Cross-repo only (producer.repo !== consumer.repo)
71
+ * - Non-partial consumer: concrete path INSTANTIATES the normalised template → "exact"
72
+ * - Partial consumer: url_prefix is a path-prefix of the template's literal head → "partial"
73
+ *
74
+ * One consumer can match multiple producers (all reported).
75
+ * Multiple consumers can match one producer (all reported).
76
+ * Deduplication: identical (producer_repo, consumer_file, line, path, method) → single entry.
77
+ */
78
+ export declare function matchContracts(producers: RepoEndpoint[], consumers: Array<OutboundCall & {
79
+ repo: string;
80
+ }>): ContractMatch[];
81
+ /**
82
+ * Extract all outbound HTTP calls from `source` (TypeScript/JavaScript).
83
+ * Supports fetch, axios.METHOD, and got.METHOD patterns.
84
+ *
85
+ * Uses a single-pass state-machine lexer so calls inside comments, string
86
+ * literals, template literals, and regex literals are never falsely reported
87
+ * (fixes C3/C6). Multi-line templates are handled naturally (C4). Wide-
88
+ * spaced string concatenation is detected via the lexer's nextCodeToken (C5).
89
+ * Query-string and fragment stripping is done in extractUrlPrefix (C1).
90
+ *
91
+ * @param source - Raw source code.
92
+ * @param file - File path to embed in results (returned as-is).
93
+ */
94
+ export declare function extractOutboundCalls(source: string, file: string): OutboundCall[];
95
+ /** Hard cap on repos processed per group (CQ6 — bounds cross-repo fan-out). */
96
+ export declare const MAX_GROUP_REPOS = 20;
97
+ /** Producer endpoints + consumer outbound calls resolved for one repo. */
98
+ export interface RepoContractData {
99
+ producers: RepoEndpoint[];
100
+ consumers: Array<OutboundCall & {
101
+ repo: string;
102
+ }>;
103
+ /** False when the repo is not indexed — caller emits a warning and skips it. */
104
+ indexed: boolean;
105
+ /** Non-fatal per-repo notes (e.g. a producer extractor threw) surfaced to the caller. */
106
+ warnings?: string[];
107
+ }
108
+ /** Resolves one repo's producer + consumer contract data. Injectable for tests. */
109
+ export type RepoResolver = (repo: string) => Promise<RepoContractData>;
110
+ export interface GroupContractResult {
111
+ matches: ContractMatch[];
112
+ warnings: string[];
113
+ repos_processed: number;
114
+ error?: string;
115
+ /** Set by findEndpointConsumers: raw consumer calls hitting the queried path,
116
+ * INCLUDING consumers of endpoints with no producer in the group (external
117
+ * services). Without this, a consumer of an un-indexed producer is invisible. */
118
+ consumers_of_path?: Array<OutboundCall & {
119
+ repo: string;
120
+ }>;
121
+ }
122
+ export declare function matchGroupContracts(groupName: string, opts?: {
123
+ registryPath?: string;
124
+ resolver?: RepoResolver;
125
+ }): Promise<GroupContractResult>;
126
+ /**
127
+ * Answer "who calls METHOD path" within a group. Returns producer↔consumer
128
+ * `matches` for the endpoint AND `consumers_of_path` — every raw consumer call
129
+ * hitting that path, INCLUDING calls to endpoints with no producer in the group
130
+ * (an external/un-indexed service). Method is uppercased; the path is normalised
131
+ * (`:id`/`{id}`/`[id]` → `{param}`) so any param style works.
132
+ */
133
+ export declare function findEndpointConsumers(groupName: string, method: string, path: string, opts?: {
134
+ registryPath?: string;
135
+ resolver?: RepoResolver;
136
+ }): Promise<GroupContractResult>;
137
+ //# sourceMappingURL=cross-repo-contract-tools.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cross-repo-contract-tools.d.ts","sourceRoot":"","sources":["../../src/tools/cross-repo-contract-tools.ts"],"names":[],"mappings":"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"}