@nanonets/graft 0.7.1 → 0.8.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (101) hide show
  1. package/README.md +170 -70
  2. package/dist/ask/ask.d.ts +14 -0
  3. package/dist/ask/ask.d.ts.map +1 -1
  4. package/dist/ask/ask.js +24 -5
  5. package/dist/ask/ask.js.map +1 -1
  6. package/dist/claude/format.d.ts +1 -1
  7. package/dist/claude/format.d.ts.map +1 -1
  8. package/dist/claude/format.js +6 -3
  9. package/dist/claude/format.js.map +1 -1
  10. package/dist/claude/hooks.d.ts +15 -0
  11. package/dist/claude/hooks.d.ts.map +1 -1
  12. package/dist/claude/hooks.js +55 -4
  13. package/dist/claude/hooks.js.map +1 -1
  14. package/dist/claude/init.d.ts +17 -0
  15. package/dist/claude/init.d.ts.map +1 -1
  16. package/dist/claude/init.js +45 -19
  17. package/dist/claude/init.js.map +1 -1
  18. package/dist/claude/settings-merge.d.ts.map +1 -1
  19. package/dist/claude/settings-merge.js +9 -1
  20. package/dist/claude/settings-merge.js.map +1 -1
  21. package/dist/claude/skill-template.d.ts.map +1 -1
  22. package/dist/claude/skill-template.js +31 -8
  23. package/dist/claude/skill-template.js.map +1 -1
  24. package/dist/claude/state.d.ts +2 -20
  25. package/dist/claude/state.d.ts.map +1 -1
  26. package/dist/claude/state.js +9 -72
  27. package/dist/claude/state.js.map +1 -1
  28. package/dist/cli-picker.d.ts +60 -0
  29. package/dist/cli-picker.d.ts.map +1 -0
  30. package/dist/cli-picker.js +268 -0
  31. package/dist/cli-picker.js.map +1 -0
  32. package/dist/cli.js +104 -13
  33. package/dist/cli.js.map +1 -1
  34. package/dist/context/check.d.ts +21 -0
  35. package/dist/context/check.d.ts.map +1 -1
  36. package/dist/context/check.js +32 -1
  37. package/dist/context/check.js.map +1 -1
  38. package/dist/engine.d.ts +2 -0
  39. package/dist/engine.d.ts.map +1 -1
  40. package/dist/engine.js +1 -0
  41. package/dist/engine.js.map +1 -1
  42. package/dist/graph/build.d.ts +13 -2
  43. package/dist/graph/build.d.ts.map +1 -1
  44. package/dist/graph/build.js +93 -19
  45. package/dist/graph/build.js.map +1 -1
  46. package/dist/graph/extract-cache.d.ts +96 -0
  47. package/dist/graph/extract-cache.d.ts.map +1 -0
  48. package/dist/graph/extract-cache.js +199 -0
  49. package/dist/graph/extract-cache.js.map +1 -0
  50. package/dist/graph/fingerprint.d.ts +70 -0
  51. package/dist/graph/fingerprint.d.ts.map +1 -0
  52. package/dist/graph/fingerprint.js +147 -0
  53. package/dist/graph/fingerprint.js.map +1 -0
  54. package/dist/graph/load.d.ts +11 -0
  55. package/dist/graph/load.d.ts.map +1 -1
  56. package/dist/graph/load.js +14 -0
  57. package/dist/graph/load.js.map +1 -1
  58. package/dist/graph/refresh.d.ts +49 -0
  59. package/dist/graph/refresh.d.ts.map +1 -0
  60. package/dist/graph/refresh.js +202 -0
  61. package/dist/graph/refresh.js.map +1 -0
  62. package/dist/graph/source-files.d.ts +18 -0
  63. package/dist/graph/source-files.d.ts.map +1 -0
  64. package/dist/graph/source-files.js +36 -0
  65. package/dist/graph/source-files.js.map +1 -0
  66. package/dist/graph/traverse-cli.d.ts.map +1 -1
  67. package/dist/graph/traverse-cli.js +16 -6
  68. package/dist/graph/traverse-cli.js.map +1 -1
  69. package/dist/hosts/codex-hooks.d.ts +8 -0
  70. package/dist/hosts/codex-hooks.d.ts.map +1 -1
  71. package/dist/hosts/codex-hooks.js +27 -4
  72. package/dist/hosts/codex-hooks.js.map +1 -1
  73. package/dist/hosts/init.d.ts +2 -0
  74. package/dist/hosts/init.d.ts.map +1 -1
  75. package/dist/hosts/init.js +5 -2
  76. package/dist/hosts/init.js.map +1 -1
  77. package/dist/hosts/mcp-config.d.ts +18 -0
  78. package/dist/hosts/mcp-config.d.ts.map +1 -1
  79. package/dist/hosts/mcp-config.js +31 -7
  80. package/dist/hosts/mcp-config.js.map +1 -1
  81. package/dist/hosts/plan.d.ts +32 -0
  82. package/dist/hosts/plan.d.ts.map +1 -0
  83. package/dist/hosts/plan.js +67 -0
  84. package/dist/hosts/plan.js.map +1 -0
  85. package/dist/hosts/registry.d.ts.map +1 -1
  86. package/dist/hosts/registry.js +9 -0
  87. package/dist/hosts/registry.js.map +1 -1
  88. package/dist/mcp/server.d.ts.map +1 -1
  89. package/dist/mcp/server.js +5 -2
  90. package/dist/mcp/server.js.map +1 -1
  91. package/dist/mcp/tools.d.ts +2 -2
  92. package/dist/mcp/tools.d.ts.map +1 -1
  93. package/dist/mcp/tools.js +108 -88
  94. package/dist/mcp/tools.js.map +1 -1
  95. package/dist/search/grep-cli.js +1 -1
  96. package/dist/search/grep-cli.js.map +1 -1
  97. package/dist/util/state.d.ts +45 -0
  98. package/dist/util/state.d.ts.map +1 -0
  99. package/dist/util/state.js +121 -0
  100. package/dist/util/state.js.map +1 -0
  101. package/package.json +1 -1
@@ -0,0 +1,147 @@
1
+ /**
2
+ * The cheap "has the working tree moved?" probe that gates the pre-query rebuild.
3
+ *
4
+ * Every graft retrieval call runs this, so it has to be ~free on the common
5
+ * unchanged path: a walk + one `stat` per source file, no reads, no parsing.
6
+ * Measured at ~3ms for 280 files. Only files whose `(size, mtimeMs)` disagree
7
+ * with the last build's record get read and hashed, which is what keeps a `touch`
8
+ * or a `git checkout` of identical bytes from triggering a pointless rebuild.
9
+ *
10
+ * Note graft has no notion of git here (it never shells out to git, never reads
11
+ * `.git`): drift is measured against the bytes in the working tree, so an
12
+ * uncommitted, staged, or committed edit all look the same — which is the point.
13
+ *
14
+ * `<outDir>/.cache/fingerprint.json` is a projection of the extraction cache
15
+ * (`extract-cache.ts`) minus the parse results, written by the same build. Keeping
16
+ * it separate means the probe reads ~10KB instead of the multi-MB parse cache. The
17
+ * two can only ever disagree by one sidecar going missing, and both directions
18
+ * degrade safely: no fingerprint → "unknown, rebuild"; no parse cache → the
19
+ * rebuild is just cold.
20
+ */
21
+ import { readFileSync } from "node:fs";
22
+ import { join } from "node:path";
23
+ import { CACHE_DIR } from "../context/node-file.js";
24
+ import { contentHash } from "../util/id.js";
25
+ import { readJson, writeJsonAtomic } from "../util/state.js";
26
+ import { extractorStamp, pruneSidecars } from "./extract-cache.js";
27
+ import { listSourceStats } from "./source-files.js";
28
+ const FINGERPRINT_PREFIX = "fingerprint";
29
+ const FINGERPRINT_VERSION = 1;
30
+ /** The identity this graft's prints are filed under. Unlike the extract memo, a
31
+ * missing extractor identity is *not* disqualifying here: freshness is a claim about
32
+ * source bytes, and a build with no memo is merely cold, never wrong. So stamp what
33
+ * we can and fall back to a shared bucket. */
34
+ function stamp() {
35
+ return extractorStamp() ?? "nostamp";
36
+ }
37
+ /** `<outDir>/.cache/fingerprint.<stamp>.json` — keyed by extractor identity for the
38
+ * same reason the memo is (see {@link extractCachePath}): two grafts on one repo,
39
+ * typically an `npx` MCP server and a locally installed hook binary, must not keep
40
+ * invalidating each other's prints and forcing a cold rebuild on every call. */
41
+ export function fingerprintPath(outDir) {
42
+ return join(outDir, CACHE_DIR, `${FINGERPRINT_PREFIX}.${stamp()}.json`);
43
+ }
44
+ export function readFingerprint(outDir) {
45
+ const f = readJson(fingerprintPath(outDir));
46
+ if (!f || f.version !== FINGERPRINT_VERSION || typeof f.files !== "object" || !f.files)
47
+ return null;
48
+ if (f.extractor !== stamp())
49
+ return null; // different extractor — re-extract, don't trust these prints
50
+ return f;
51
+ }
52
+ /** Project the extraction cache's entries into the probe sidecar. Best-effort:
53
+ * the graph is already on disk when this runs, so a failed write costs the next
54
+ * probe its fast path and nothing more. */
55
+ export function writeFingerprint(outDir, entries) {
56
+ const files = {};
57
+ for (const [rel, e] of Object.entries(entries))
58
+ files[rel] = [e.size, e.mtimeMs, e.hash];
59
+ try {
60
+ writeJsonAtomic(fingerprintPath(outDir), { version: FINGERPRINT_VERSION, extractor: stamp(), files }, true);
61
+ pruneSidecars(join(outDir, CACHE_DIR), FINGERPRINT_PREFIX);
62
+ return true;
63
+ }
64
+ catch {
65
+ return false;
66
+ }
67
+ }
68
+ /** `GRAFT_REFRESH=hash` — never trust a stat, confirm every file by its bytes. */
69
+ export function alwaysHash() {
70
+ return process.env.GRAFT_REFRESH === "hash";
71
+ }
72
+ /**
73
+ * May a recorded `(size, mtimeMs, hash)` be trusted for the file `f` as it is on
74
+ * disk now, without reading it?
75
+ *
76
+ * **The probe's rule only.** `buildGraph` deliberately does not use this: it reads
77
+ * and hashes every file, every time. A stat may decide whether a query bothers
78
+ * rebuilding; it may not decide what the rebuild itself looks at — otherwise
79
+ * `graft check` (which always re-hashes) can report drift that the `graft build` it
80
+ * recommends then refuses to repair. `GRAFT_REFRESH=hash` is the escape hatch for
81
+ * the probe's blind spot: a same-length edit inside one mtime tick.
82
+ *
83
+ * An empty `hash` means the last build never got the bytes — always re-read.
84
+ * A *parse* failure keeps its real hash, so it stays on the fast path: re-reading
85
+ * bytes that failed to parse yesterday just fails to parse again.
86
+ */
87
+ export function statUnchanged(rec, f) {
88
+ if (alwaysHash())
89
+ return false;
90
+ if (!rec.hash)
91
+ return false;
92
+ return rec.size === f.size && rec.mtimeMs === f.mtimeMs;
93
+ }
94
+ export function isClean(d) {
95
+ return d.changed.length === 0 && d.added.length === 0 && d.removed.length === 0;
96
+ }
97
+ export function driftCount(d) {
98
+ return d.changed.length + d.added.length + d.removed.length;
99
+ }
100
+ /**
101
+ * Diff the working tree against the last build's fingerprint. Returns null when
102
+ * there is no fingerprint to compare against (never built, or built by a version
103
+ * that didn't write one) — callers should treat that as "unknown", not "clean".
104
+ *
105
+ * `GRAFT_REFRESH=hash` skips the stat fast path and hashes every file, for the
106
+ * rare tooling that rewrites content while preserving size and mtime.
107
+ */
108
+ export function probeDrift(root, outDir) {
109
+ const fp = readFingerprint(outDir);
110
+ if (!fp)
111
+ return null;
112
+ const drift = { changed: [], added: [], removed: [] };
113
+ const seen = new Set();
114
+ for (const f of listSourceStats(root, outDir)) {
115
+ seen.add(f.rel);
116
+ const print = fp.files[f.rel];
117
+ if (!print) {
118
+ drift.added.push(f.rel);
119
+ continue;
120
+ }
121
+ const [size, mtimeMs, hash] = print;
122
+ if (statUnchanged({ size, mtimeMs, hash }, f))
123
+ continue;
124
+ // Suspect: confirm by bytes, so a touch (or a checkout that restores the
125
+ // same content) doesn't cost a rebuild. An entry with an empty hash lands
126
+ // here every time by design — that's a file the last build couldn't read, and
127
+ // the only way to learn it's readable again is to try.
128
+ let now;
129
+ try {
130
+ now = contentHash(readFileSync(f.abs, "utf8"));
131
+ }
132
+ catch {
133
+ continue; // unreadable right now — leave it to the next probe
134
+ }
135
+ if (now !== hash)
136
+ drift.changed.push(f.rel);
137
+ }
138
+ for (const rel of Object.keys(fp.files)) {
139
+ if (!seen.has(rel))
140
+ drift.removed.push(rel);
141
+ }
142
+ drift.changed.sort();
143
+ drift.added.sort();
144
+ drift.removed.sort();
145
+ return drift;
146
+ }
147
+ //# sourceMappingURL=fingerprint.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fingerprint.js","sourceRoot":"","sources":["../../src/graph/fingerprint.ts"],"names":[],"mappings":"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"}
@@ -15,4 +15,15 @@ export declare function loadGraphCached(outDir: string): GraphV1 | null;
15
15
  /** Cached `readAskIndex(outDir)` — same semantics, keyed on the sidecar file.
16
16
  * Returns a shared cached reference; callers must not mutate the returned index. */
17
17
  export declare function loadAskIndexCached(outDir: string): AskIndex | null;
18
+ /**
19
+ * Drop the cached graph + sidecar for `outDir`, forcing the next load to re-read.
20
+ *
21
+ * The `(mtimeMs, size)` key above is a good invalidator for a build that happened
22
+ * in *another* process, but not for one this process just performed: the
23
+ * pre-query auto-refresh (`refresh.ts`) rewrites the graph and then immediately
24
+ * queries it, and on a filesystem with coarse mtime resolution a same-tick rewrite
25
+ * of the same size would be served from the stale entry. Callers that rebuild must
26
+ * therefore invalidate explicitly rather than trust the clock.
27
+ */
28
+ export declare function invalidateGraphCaches(outDir: string): void;
18
29
  //# sourceMappingURL=load.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"load.d.ts","sourceRoot":"","sources":["../../src/graph/load.ts"],"names":[],"mappings":"AA2BA,OAAO,EAA8B,KAAK,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AACjF,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAW1C;6EAC6E;AAC7E,eAAO,MAAM,YAAY;;;CAA4B,CAAC;AAEtD,+EAA+E;AAC/E,wBAAgB,kBAAkB,IAAI,IAAI,CAGzC;AAmCD;;oFAEoF;AACpF,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,GAAG,IAAI,CAK9D;AAED;oFACoF;AACpF,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,GAAG,QAAQ,GAAG,IAAI,CAKlE"}
1
+ {"version":3,"file":"load.d.ts","sourceRoot":"","sources":["../../src/graph/load.ts"],"names":[],"mappings":"AA2BA,OAAO,EAA8B,KAAK,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AACjF,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAW1C;6EAC6E;AAC7E,eAAO,MAAM,YAAY;;;CAA4B,CAAC;AAEtD,+EAA+E;AAC/E,wBAAgB,kBAAkB,IAAI,IAAI,CAGzC;AAmCD;;oFAEoF;AACpF,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,GAAG,IAAI,CAK9D;AAED;oFACoF;AACpF,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,GAAG,QAAQ,GAAG,IAAI,CAKlE;AAED;;;;;;;;;GASG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAG1D"}
@@ -80,4 +80,18 @@ export function loadAskIndexCached(outDir) {
80
80
  __parseCount.askIndex++;
81
81
  });
82
82
  }
83
+ /**
84
+ * Drop the cached graph + sidecar for `outDir`, forcing the next load to re-read.
85
+ *
86
+ * The `(mtimeMs, size)` key above is a good invalidator for a build that happened
87
+ * in *another* process, but not for one this process just performed: the
88
+ * pre-query auto-refresh (`refresh.ts`) rewrites the graph and then immediately
89
+ * queries it, and on a filesystem with coarse mtime resolution a same-tick rewrite
90
+ * of the same size would be served from the stale entry. Callers that rebuild must
91
+ * therefore invalidate explicitly rather than trust the clock.
92
+ */
93
+ export function invalidateGraphCaches(outDir) {
94
+ graphCache.delete(wiringPath(outDir));
95
+ askIndexCache.delete(askIndexPath(outDir));
96
+ }
83
97
  //# sourceMappingURL=load.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"load.js","sourceRoot":"","sources":["../../src/graph/load.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AACnC,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AACnD,OAAO,EAAE,YAAY,EAAE,YAAY,EAAiB,MAAM,sBAAsB,CAAC;AASjF,MAAM,UAAU,GAAG,IAAI,GAAG,EAA+B,CAAC;AAC1D,MAAM,aAAa,GAAG,IAAI,GAAG,EAAgC,CAAC;AAE9D;6EAC6E;AAC7E,MAAM,CAAC,MAAM,YAAY,GAAG,EAAE,KAAK,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,CAAC;AAEtD,+EAA+E;AAC/E,MAAM,UAAU,kBAAkB;IAChC,YAAY,CAAC,KAAK,GAAG,CAAC,CAAC;IACvB,YAAY,CAAC,QAAQ,GAAG,CAAC,CAAC;AAC5B,CAAC;AAED,SAAS,MAAM,CAAC,IAAY;IAC1B,IAAI,CAAC;QACH,MAAM,CAAC,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC;QACzB,OAAO,EAAE,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IAC9C,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,SAAS,UAAU,CACjB,KAAiC,EACjC,IAAY,EACZ,KAAqB,EACrB,OAAmB;IAEnB,MAAM,EAAE,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC;IACxB,IAAI,CAAC,EAAE,EAAE,CAAC;QACR,sEAAsE;QACtE,sEAAsE;QACtE,+CAA+C;QAC/C,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QACnB,OAAO,IAAI,CAAC;IACd,CAAC;IACD,MAAM,MAAM,GAAG,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAC/B,IAAI,MAAM,IAAI,MAAM,CAAC,OAAO,KAAK,EAAE,CAAC,OAAO,IAAI,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC,IAAI,EAAE,CAAC;QACvE,OAAO,MAAM,CAAC,KAAK,CAAC;IACtB,CAAC;IACD,OAAO,EAAE,CAAC;IACV,MAAM,KAAK,GAAG,KAAK,EAAE,CAAC;IACtB,KAAK,CAAC,GAAG,CAAC,IAAI,EAAE,EAAE,OAAO,EAAE,EAAE,CAAC,OAAO,EAAE,IAAI,EAAE,EAAE,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;IAC/D,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;oFAEoF;AACpF,MAAM,UAAU,eAAe,CAAC,MAAc;IAC5C,MAAM,IAAI,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC;IAChC,OAAO,UAAU,CAAC,UAAU,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE;QAC9D,YAAY,CAAC,KAAK,EAAE,CAAC;IACvB,CAAC,CAAC,CAAC;AACL,CAAC;AAED;oFACoF;AACpF,MAAM,UAAU,kBAAkB,CAAC,MAAc;IAC/C,MAAM,IAAI,GAAG,YAAY,CAAC,MAAM,CAAC,CAAC;IAClC,OAAO,UAAU,CAAC,aAAa,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC,YAAY,CAAC,MAAM,CAAC,EAAE,GAAG,EAAE;QACtE,YAAY,CAAC,QAAQ,EAAE,CAAC;IAC1B,CAAC,CAAC,CAAC;AACL,CAAC"}
1
+ {"version":3,"file":"load.js","sourceRoot":"","sources":["../../src/graph/load.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,49 @@
1
+ import { type Drift } from "./fingerprint.js";
2
+ export interface RefreshResult {
3
+ /** True when the graph on disk was rebuilt by this call. */
4
+ refreshed: boolean;
5
+ /** What the probe found, when it ran and found something. */
6
+ drift?: Drift;
7
+ /** One-line explanation for the agent/user, when there's something worth saying. */
8
+ note?: string;
9
+ }
10
+ export interface RefreshOptions {
11
+ contextDir?: string;
12
+ /** Skip everything (the `--no-refresh` flag). */
13
+ disabled?: boolean;
14
+ }
15
+ /**
16
+ * Release the lock if this process is asked to die while holding it. Returns the
17
+ * un-hook.
18
+ *
19
+ * Not hypothetical: the Claude Code prompt hook runs `graft ask` with a timeout, and
20
+ * `execFileSync` enforces it with SIGTERM. Node's default disposition for SIGTERM is
21
+ * to exit without unwinding, so the `finally` below never runs and the lock outlives
22
+ * the process — after which the background sync is blocked and every query waits and
23
+ * then answers stale until the lock ages out. Ctrl-C on a CLI query is the same story
24
+ * with SIGINT.
25
+ *
26
+ * Adding a listener replaces that default disposition, so re-raise it explicitly
27
+ * afterwards: remove ourselves, then `process.kill(process.pid, sig)`, so the exit
28
+ * status still says "terminated by signal" for whoever is waiting on us.
29
+ */
30
+ export declare function releaseOnSignal(cache: string): () => void;
31
+ /**
32
+ * Rebuild `root`'s structural graph if the working tree has moved since the last
33
+ * build. Cheap and side-effect-free when nothing changed, which is the usual case.
34
+ *
35
+ * `root` is the repository root (the same value the query itself is given), not
36
+ * the context dir.
37
+ */
38
+ export declare function ensureFreshGraph(root: string, opts?: RefreshOptions): Promise<RefreshResult>;
39
+ /**
40
+ * Workspace variant: refresh each child repo's own graph (a workspace parent holds
41
+ * an index, never nodes). Children are independent, but they're refreshed in
42
+ * sequence — a fan-out of concurrent tree-sitter builds would spike CPU on the
43
+ * very path that's supposed to feel free.
44
+ */
45
+ export declare function ensureFreshChildren(root: string, children: string[], opts?: RefreshOptions): Promise<RefreshResult>;
46
+ /** The one-line note a CLI/MCP surface prints when a refresh actually happened.
47
+ * Null when there's nothing to say (the overwhelmingly common case). */
48
+ export declare function refreshNote(r: RefreshResult): string | null;
49
+ //# sourceMappingURL=refresh.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"refresh.d.ts","sourceRoot":"","sources":["../../src/graph/refresh.ts"],"names":[],"mappings":"AAkCA,OAAO,EAAmC,KAAK,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAU/E,MAAM,WAAW,aAAa;IAC5B,4DAA4D;IAC5D,SAAS,EAAE,OAAO,CAAC;IACnB,6DAA6D;IAC7D,KAAK,CAAC,EAAE,KAAK,CAAC;IACd,oFAAoF;IACpF,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,cAAc;IAC7B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,iDAAiD;IACjD,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAcD;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,IAAI,CAWzD;AAYD;;;;;;GAMG;AACH,wBAAsB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,GAAE,cAAmB,GAAG,OAAO,CAAC,aAAa,CAAC,CAwDtG;AAED;;;;;GAKG;AACH,wBAAsB,mBAAmB,CACvC,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,EAAE,EAClB,IAAI,GAAE,cAAmB,GACxB,OAAO,CAAC,aAAa,CAAC,CAsBxB;AAED;wEACwE;AACxE,wBAAgB,WAAW,CAAC,CAAC,EAAE,aAAa,GAAG,MAAM,GAAG,IAAI,CAK3D"}
@@ -0,0 +1,202 @@
1
+ /**
2
+ * `ensureFreshGraph` — the pre-query gate that keeps retrieval honest.
3
+ *
4
+ * Freshness used to be someone else's job: the Claude Code `Stop` hook spawned a
5
+ * background `graft build` *after* the turn ended, so every query an agent made
6
+ * between its first edit and the end of the turn answered from a graph that no
7
+ * longer matched the file it had just changed. Worse, an edit made outside the
8
+ * agent (your editor, a branch switch, a stash) set no `dirty` flag at all, so
9
+ * nothing ever triggered a resync.
10
+ *
11
+ * So freshness moves into the query path: every retrieval call probes the working
12
+ * tree (`fingerprint.ts`, ~3ms) and, when something moved, rebuilds the structural
13
+ * graph before answering. Properties worth keeping:
14
+ *
15
+ * - **$0 and offline.** Tier-1 only — never a summarizer, never `--deep`. Same
16
+ * money guard `claude/sync-run.ts` carries: auto-anything must not spend money.
17
+ * - **Never fatal.** A failed refresh degrades to answering from the graph on
18
+ * disk. A query that works today must not start failing because a rebuild did.
19
+ * - **Never a stampede.** It takes the same `graft/.cache/.sync.lock` the
20
+ * background sync uses, so concurrent MCP calls and the Stop hook can't pile up
21
+ * rebuilds on top of each other.
22
+ * - **Writes only what a query reads** (`graphOnly`): the graph, the `ask` sidecar,
23
+ * the freshness record. Not the markdown cards, not `INDEX.md`, not `.gitignore`.
24
+ * Those belong to an explicit `graft build` — which the `Stop` hook already runs
25
+ * at the end of a turn — so retrieval stays cheap and a read stays a read. It
26
+ * also leaves `stats.json` alone, so that same `Stop` hook still sees `dirty` and
27
+ * still rebuilds the passive surface.
28
+ */
29
+ import { existsSync } from "node:fs";
30
+ import { join, resolve } from "node:path";
31
+ import { contextDirFor } from "../context/node-file.js";
32
+ import { acquireLockIn, releaseLockIn } from "../util/state.js";
33
+ import { CACHE_DIR } from "../context/node-file.js";
34
+ import { buildGraph } from "./build.js";
35
+ import { driftCount, isClean, probeDrift } from "./fingerprint.js";
36
+ import { invalidateGraphCaches } from "./load.js";
37
+ import { wiringPath } from "./write.js";
38
+ /** How long to wait for another process's in-flight rebuild before giving up and
39
+ * answering from the current graph. Long enough to ride out a small repo's build,
40
+ * short enough that a tool call never feels hung. */
41
+ const LOCK_WAIT_MS = 2000;
42
+ const LOCK_POLL_MS = 50;
43
+ const CLEAN = { refreshed: false };
44
+ /** Env kill switch, for CI or anyone who wants queries to never write. */
45
+ function envDisabled() {
46
+ const v = process.env.GRAFT_NO_REFRESH;
47
+ return v !== undefined && v !== "" && v !== "0" && v !== "false";
48
+ }
49
+ function sleep(ms) {
50
+ return new Promise((r) => setTimeout(r, ms));
51
+ }
52
+ /**
53
+ * Release the lock if this process is asked to die while holding it. Returns the
54
+ * un-hook.
55
+ *
56
+ * Not hypothetical: the Claude Code prompt hook runs `graft ask` with a timeout, and
57
+ * `execFileSync` enforces it with SIGTERM. Node's default disposition for SIGTERM is
58
+ * to exit without unwinding, so the `finally` below never runs and the lock outlives
59
+ * the process — after which the background sync is blocked and every query waits and
60
+ * then answers stale until the lock ages out. Ctrl-C on a CLI query is the same story
61
+ * with SIGINT.
62
+ *
63
+ * Adding a listener replaces that default disposition, so re-raise it explicitly
64
+ * afterwards: remove ourselves, then `process.kill(process.pid, sig)`, so the exit
65
+ * status still says "terminated by signal" for whoever is waiting on us.
66
+ */
67
+ export function releaseOnSignal(cache) {
68
+ const signals = ["SIGTERM", "SIGINT"];
69
+ const onSignal = (sig) => {
70
+ releaseLockIn(cache);
71
+ for (const s of signals)
72
+ process.removeListener(s, onSignal);
73
+ process.kill(process.pid, sig);
74
+ };
75
+ for (const s of signals)
76
+ process.once(s, onSignal);
77
+ return () => {
78
+ for (const s of signals)
79
+ process.removeListener(s, onSignal);
80
+ };
81
+ }
82
+ /** Wait out someone else's rebuild, then take the lock. False when we couldn't. */
83
+ async function waitForLock(cache) {
84
+ const deadline = Date.now() + LOCK_WAIT_MS;
85
+ for (;;) {
86
+ if (acquireLockIn(cache))
87
+ return true;
88
+ if (Date.now() >= deadline)
89
+ return false;
90
+ await sleep(LOCK_POLL_MS);
91
+ }
92
+ }
93
+ /**
94
+ * Rebuild `root`'s structural graph if the working tree has moved since the last
95
+ * build. Cheap and side-effect-free when nothing changed, which is the usual case.
96
+ *
97
+ * `root` is the repository root (the same value the query itself is given), not
98
+ * the context dir.
99
+ */
100
+ export async function ensureFreshGraph(root, opts = {}) {
101
+ if (opts.disabled || envDisabled())
102
+ return CLEAN;
103
+ try {
104
+ const dir = resolve(root);
105
+ const outDir = contextDirFor(dir, opts.contextDir);
106
+ // Nothing built yet: the caller's own "no graph — run graft build" message is
107
+ // the right answer. Auto-building a whole repo under a query is a surprise,
108
+ // and it's the one case where the user hasn't opted into graft at all yet.
109
+ if (!existsSync(wiringPath(outDir)))
110
+ return CLEAN;
111
+ // null = no fingerprint at all: a graph built before this mechanism existed,
112
+ // or by a different extractor build. Rebuild once — that lays the fingerprint
113
+ // down, so it costs exactly one build, not one per query.
114
+ const drift = probeDrift(dir, outDir);
115
+ if (drift && isClean(drift))
116
+ return CLEAN;
117
+ // On the default layout this is `<root>/graft/.cache/.sync.lock`, the very file
118
+ // the Claude Code hooks lock — so this refresh and the background sync can
119
+ // never rebuild at the same time.
120
+ const lockCache = join(outDir, CACHE_DIR);
121
+ if (!(await waitForLock(lockCache))) {
122
+ return {
123
+ refreshed: false,
124
+ drift: drift ?? undefined,
125
+ note: "a graph rebuild is already in flight — answering from the current graph",
126
+ };
127
+ }
128
+ const unhook = releaseOnSignal(lockCache);
129
+ try {
130
+ // We may have queued behind another process's rebuild for up to LOCK_WAIT_MS,
131
+ // and that rebuild very likely fixed the same drift we saw. Re-probe rather
132
+ // than rebuild on the strength of a stale observation: without this, four
133
+ // parallel MCP tool calls on one edited file produce four full rebuilds, three
134
+ // of them pure waste, and the last tool call pays for all of it. A null drift
135
+ // means "no fingerprint" and still has to build.
136
+ const now = drift ? probeDrift(dir, outDir) : null;
137
+ if (now && isClean(now)) {
138
+ invalidateGraphCaches(outDir);
139
+ return CLEAN;
140
+ }
141
+ // Tier-1 only: no summarizer, so no LLM call and no network, ever. And
142
+ // `graphOnly`: write the graph, the ask sidecar and the fingerprint, nothing
143
+ // else. The markdown projections under `graft/` stay the `Stop` hook's job —
144
+ // a query has no business rewriting the repo's `.gitignore` or churning every
145
+ // card's mtime, and skipping them is most of what keeps this cheap.
146
+ await buildGraph(dir, { contextDir: opts.contextDir, graphOnly: true });
147
+ invalidateGraphCaches(outDir);
148
+ return { refreshed: true, drift: drift ?? undefined };
149
+ }
150
+ finally {
151
+ unhook();
152
+ releaseLockIn(lockCache);
153
+ }
154
+ }
155
+ catch (err) {
156
+ // Answering from a slightly stale graph beats failing the query.
157
+ return { refreshed: false, note: `graph refresh skipped: ${err instanceof Error ? err.message : String(err)}` };
158
+ }
159
+ }
160
+ /**
161
+ * Workspace variant: refresh each child repo's own graph (a workspace parent holds
162
+ * an index, never nodes). Children are independent, but they're refreshed in
163
+ * sequence — a fan-out of concurrent tree-sitter builds would spike CPU on the
164
+ * very path that's supposed to feel free.
165
+ */
166
+ export async function ensureFreshChildren(root, children, opts = {}) {
167
+ if (opts.disabled || envDisabled())
168
+ return CLEAN;
169
+ const refreshedIn = [];
170
+ let files = 0;
171
+ for (const child of children) {
172
+ // Deliberately NOT `opts`: `contextDirFor` returns an override verbatim and
173
+ // ignores the root it's handed, so forwarding the parent's `--dir` would point
174
+ // every child at the *parent's* context dir — which holds a workspace index and
175
+ // no wiring.json, so every child would silently be skipped. (And if it did hold
176
+ // one, each child would build into that single shared dir in turn, the last
177
+ // clobbering the rest.) A child's graph always lives in its own `<child>/graft`,
178
+ // which is exactly how `loadWorkspaceGraphs` reads them back.
179
+ const r = await ensureFreshGraph(resolve(root, child), { disabled: opts.disabled });
180
+ if (!r.refreshed)
181
+ continue;
182
+ refreshedIn.push(child);
183
+ files += r.drift ? driftCount(r.drift) : 0;
184
+ }
185
+ if (!refreshedIn.length)
186
+ return CLEAN;
187
+ return {
188
+ refreshed: true,
189
+ note: `refreshed ${refreshedIn.join(", ")} (${files || "?"} file${files === 1 ? "" : "s"} changed) before answering`,
190
+ };
191
+ }
192
+ /** The one-line note a CLI/MCP surface prints when a refresh actually happened.
193
+ * Null when there's nothing to say (the overwhelmingly common case). */
194
+ export function refreshNote(r) {
195
+ if (r.note)
196
+ return `[graft] ${r.note}`;
197
+ if (!r.refreshed)
198
+ return null;
199
+ const n = r.drift ? driftCount(r.drift) : 0;
200
+ return `[graft] refreshed the graph (${n || "?"} file${n === 1 ? "" : "s"} changed) before answering`;
201
+ }
202
+ //# sourceMappingURL=refresh.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"refresh.js","sourceRoot":"","sources":["../../src/graph/refresh.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ /** The source files a graph build parses: supported languages, minus the output dir. */
2
+ export declare function listSourceFiles(root: string, outDir: string): string[];
3
+ export interface SourceStat {
4
+ /** Absolute path. */
5
+ abs: string;
6
+ /** `relative(root, abs)` — exactly the form `buildGraph` uses for node ids and
7
+ * `checkGraph` diffs against, so cache keys and ids can never disagree. */
8
+ rel: string;
9
+ size: number;
10
+ mtimeMs: number;
11
+ }
12
+ /**
13
+ * {@link listSourceFiles} plus each file's `(size, mtimeMs)` — the currency of
14
+ * both the freshness probe and the extraction cache. Files that vanish between
15
+ * the walk and the stat are dropped (same fail-soft posture as `walkDir`).
16
+ */
17
+ export declare function listSourceStats(root: string, outDir: string): SourceStat[];
18
+ //# sourceMappingURL=source-files.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"source-files.d.ts","sourceRoot":"","sources":["../../src/graph/source-files.ts"],"names":[],"mappings":"AAaA,wFAAwF;AACxF,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAEtE;AAED,MAAM,WAAW,UAAU;IACzB,qBAAqB;IACrB,GAAG,EAAE,MAAM,CAAC;IACZ;+EAC2E;IAC3E,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,UAAU,EAAE,CAY1E"}
@@ -0,0 +1,36 @@
1
+ /**
2
+ * The file set a graph build parses, and its stat metadata.
3
+ *
4
+ * Split out of `build.ts` so the freshness probe (`fingerprint.ts`) can enumerate
5
+ * exactly the same files without importing the builder (which would be an import
6
+ * cycle: build → fingerprint → build). `build.ts` re-exports
7
+ * {@link listSourceFiles} so its existing importers are unaffected.
8
+ */
9
+ import { statSync } from "node:fs";
10
+ import { relative } from "node:path";
11
+ import { walkDir } from "../ingest/fs.js";
12
+ import { languageOf } from "./extract.js";
13
+ /** The source files a graph build parses: supported languages, minus the output dir. */
14
+ export function listSourceFiles(root, outDir) {
15
+ return walkDir(root).filter((f) => !f.startsWith(outDir) && languageOf(f) !== null);
16
+ }
17
+ /**
18
+ * {@link listSourceFiles} plus each file's `(size, mtimeMs)` — the currency of
19
+ * both the freshness probe and the extraction cache. Files that vanish between
20
+ * the walk and the stat are dropped (same fail-soft posture as `walkDir`).
21
+ */
22
+ export function listSourceStats(root, outDir) {
23
+ const out = [];
24
+ for (const abs of listSourceFiles(root, outDir)) {
25
+ let s;
26
+ try {
27
+ s = statSync(abs);
28
+ }
29
+ catch {
30
+ continue;
31
+ }
32
+ out.push({ abs, rel: relative(root, abs), size: s.size, mtimeMs: s.mtimeMs });
33
+ }
34
+ return out;
35
+ }
36
+ //# sourceMappingURL=source-files.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"source-files.js","sourceRoot":"","sources":["../../src/graph/source-files.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AACnC,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AACrC,OAAO,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAC1C,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAE1C,wFAAwF;AACxF,MAAM,UAAU,eAAe,CAAC,IAAY,EAAE,MAAc;IAC1D,OAAO,OAAO,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,MAAM,CAAC,IAAI,UAAU,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC;AACtF,CAAC;AAYD;;;;GAIG;AACH,MAAM,UAAU,eAAe,CAAC,IAAY,EAAE,MAAc;IAC1D,MAAM,GAAG,GAAiB,EAAE,CAAC;IAC7B,KAAK,MAAM,GAAG,IAAI,eAAe,CAAC,IAAI,EAAE,MAAM,CAAC,EAAE,CAAC;QAChD,IAAI,CAAoC,CAAC;QACzC,IAAI,CAAC;YACH,CAAC,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC;QACpB,CAAC;QAAC,MAAM,CAAC;YACP,SAAS;QACX,CAAC;QACD,GAAG,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,QAAQ,CAAC,IAAI,EAAE,GAAG,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC;IAChF,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"traverse-cli.d.ts","sourceRoot":"","sources":["../../src/graph/traverse-cli.ts"],"names":[],"mappings":"AAeA,OAAO,EAA6B,KAAK,OAAO,EAAE,MAAM,uBAAuB,CAAC;AAEhF,OAAO,EAA2B,KAAK,SAAS,EAAE,KAAK,OAAO,EAAE,MAAM,eAAe,CAAC;AACtF,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AAElD,MAAM,WAAW,iBAAiB;IAChC,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,uEAAuE;IACvE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,gFAAgF;IAChF,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,oFAAoF;IACpF,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAKD;;kFAEkF;AAClF,wBAAgB,QAAQ,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAE1C;AAED;sEACsE;AACtE,wBAAgB,OAAO,CAAC,SAAS,EAAE,SAAS,EAAE,GAAG,EAAE,OAAO,EAAE,SAAS,EAAE,OAAO,GAAG,MAAM,CAKtF;AAED;;;sCAGsC;AACtC,wBAAgB,cAAc,CAC5B,KAAK,EAAE,OAAO,EACd,OAAO,EAAE;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,OAAO,EAAE,CAAA;CAAE,EAAE,GAC7C,OAAO,GAAG,SAAS,CAOrB;AAED,oEAAoE;AACpE,wBAAgB,YAAY,CAAC,SAAS,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAIvE;AAiDD;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,iBAAiB,GAAG,IAAI,CAuD3F"}
1
+ {"version":3,"file":"traverse-cli.d.ts","sourceRoot":"","sources":["../../src/graph/traverse-cli.ts"],"names":[],"mappings":"AAeA,OAAO,EAA6B,KAAK,OAAO,EAAE,MAAM,uBAAuB,CAAC;AAEhF,OAAO,EAA2B,KAAK,SAAS,EAAE,KAAK,OAAO,EAAE,MAAM,eAAe,CAAC;AACtF,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AAElD,MAAM,WAAW,iBAAiB;IAChC,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,uEAAuE;IACvE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,gFAAgF;IAChF,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,oFAAoF;IACpF,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAKD;;kFAEkF;AAClF,wBAAgB,QAAQ,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAE1C;AAED;sEACsE;AACtE,wBAAgB,OAAO,CAAC,SAAS,EAAE,SAAS,EAAE,GAAG,EAAE,OAAO,EAAE,SAAS,EAAE,OAAO,GAAG,MAAM,CAKtF;AAED;;;sCAGsC;AACtC,wBAAgB,cAAc,CAC5B,KAAK,EAAE,OAAO,EACd,OAAO,EAAE;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,OAAO,EAAE,CAAA;CAAE,EAAE,GAC7C,OAAO,GAAG,SAAS,CAOrB;AAED,oEAAoE;AACpE,wBAAgB,YAAY,CAAC,SAAS,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAIvE;AAiDD;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,iBAAiB,GAAG,IAAI,CAgE3F"}
@@ -50,7 +50,7 @@ export function callersSavings(graph, results) {
50
50
  export function looseNoteFor(direction, name) {
51
51
  const label = direction === "out" ? "callees" : "callers";
52
52
  const dir = direction === "out" ? "outgoing" : "incoming";
53
- return ` no indexed ${label} — the graph has no ${dir} call/reference edges for this symbol; try grep -rn "${name}"`;
53
+ return ` no indexed ${label} — the graph has no ${dir} call/reference edges for this symbol as written. Check the name (try the bare symbol, or "Type.method"), or find its uses with graft grep "${name}". Fall back to raw grep -rn only for unindexed files`;
54
54
  }
55
55
  function symbolJson(n) {
56
56
  return { id: n.id, name: n.name, kind: n.kind, path: n.path, span: n.span };
@@ -96,12 +96,22 @@ export function runCallersCommand(query, dir, opts) {
96
96
  const direction = resolveDirection(opts.direction);
97
97
  let depth = DEFAULT_DEPTH;
98
98
  if (opts.depth !== undefined) {
99
- const d = Number(opts.depth);
100
- if (!Number.isFinite(d) || d < 1) {
101
- console.error(`✗ --depth must be a positive number, got "${opts.depth}"`);
102
- process.exit(1);
99
+ // `all` (aka full/max) = the whole transitive closure: walk until no new
100
+ // node is reached. The BFS's visited-set makes this cycle-safe, and it
101
+ // terminates when the frontier empties. This is the "show me every
102
+ // connected source" mode — the right first move before a multi-file
103
+ // refactor, where stopping at direct edges misses sibling/downstream files.
104
+ if (/^(all|full|max)$/i.test(opts.depth)) {
105
+ depth = Number.POSITIVE_INFINITY;
106
+ }
107
+ else {
108
+ const d = Number(opts.depth);
109
+ if (!Number.isFinite(d) || d < 1) {
110
+ console.error(`✗ --depth must be a positive number or "all", got "${opts.depth}"`);
111
+ process.exit(1);
112
+ }
113
+ depth = Math.floor(d);
103
114
  }
104
- depth = Math.floor(d);
105
115
  }
106
116
  const showDepth = depth > 1;
107
117
  const results = matches.map((symbol) => ({ symbol, hits: edgeWalk(graph, symbol, direction, depth) }));
@@ -1 +1 @@
1
- {"version":3,"file":"traverse-cli.js","sourceRoot":"","sources":["../../src/graph/traverse-cli.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"traverse-cli.js","sourceRoot":"","sources":["../../src/graph/traverse-cli.ts"],"names":[],"mappings":"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"}
@@ -1,7 +1,15 @@
1
+ import type { PlannedWrite } from './plan.js';
1
2
  export interface HookWrite {
2
3
  id: string;
3
4
  path: string;
4
5
  action: 'created' | 'updated' | 'unchanged' | 'skipped-unparseable';
5
6
  }
7
+ /**
8
+ * The files installing the Codex hook would touch — pure, no writes. Both live
9
+ * under `~/.codex`, so both are scoped 'global': the PostToolUse entry fires on
10
+ * every edit in every repo opened with Codex, not just this one. Empty when the
11
+ * CLI isn't installed, mirroring `installCodexHooks`' early return.
12
+ */
13
+ export declare function hookTargets(home: string): PlannedWrite[];
6
14
  export declare function installCodexHooks(home: string): HookWrite[];
7
15
  //# sourceMappingURL=codex-hooks.d.ts.map