@colbymchenry/codegraph 0.7.10 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +48 -48
- package/dist/bin/codegraph.js +25 -0
- package/dist/bin/codegraph.js.map +1 -1
- package/dist/context/index.d.ts.map +1 -1
- package/dist/context/index.js +4 -2
- package/dist/context/index.js.map +1 -1
- package/dist/extraction/index.d.ts.map +1 -1
- package/dist/extraction/index.js +63 -37
- package/dist/extraction/index.js.map +1 -1
- package/dist/installer/config-writer.d.ts.map +1 -1
- package/dist/installer/config-writer.js +3 -1
- package/dist/installer/config-writer.js.map +1 -1
- package/dist/installer/index.d.ts +12 -0
- package/dist/installer/index.d.ts.map +1 -1
- package/dist/installer/index.js +72 -4
- package/dist/installer/index.js.map +1 -1
- package/dist/installer/instructions-template.d.ts +2 -2
- package/dist/installer/instructions-template.d.ts.map +1 -1
- package/dist/installer/instructions-template.js +3 -2
- package/dist/installer/instructions-template.js.map +1 -1
- package/dist/installer/targets/claude.d.ts +10 -6
- package/dist/installer/targets/claude.d.ts.map +1 -1
- package/dist/installer/targets/claude.js +72 -10
- package/dist/installer/targets/claude.js.map +1 -1
- package/dist/mcp/index.d.ts +8 -0
- package/dist/mcp/index.d.ts.map +1 -1
- package/dist/mcp/index.js +116 -18
- package/dist/mcp/index.js.map +1 -1
- package/dist/mcp/server-instructions.d.ts +1 -1
- package/dist/mcp/server-instructions.d.ts.map +1 -1
- package/dist/mcp/server-instructions.js +14 -2
- package/dist/mcp/server-instructions.js.map +1 -1
- package/dist/mcp/tools.d.ts +59 -2
- package/dist/mcp/tools.d.ts.map +1 -1
- package/dist/mcp/tools.js +384 -70
- package/dist/mcp/tools.js.map +1 -1
- package/dist/mcp/transport.d.ts +17 -0
- package/dist/mcp/transport.d.ts.map +1 -1
- package/dist/mcp/transport.js +63 -0
- package/dist/mcp/transport.js.map +1 -1
- package/dist/resolution/frameworks/index.d.ts +1 -0
- package/dist/resolution/frameworks/index.d.ts.map +1 -1
- package/dist/resolution/frameworks/index.js +5 -1
- package/dist/resolution/frameworks/index.js.map +1 -1
- package/dist/resolution/frameworks/nestjs.d.ts +26 -0
- package/dist/resolution/frameworks/nestjs.d.ts.map +1 -0
- package/dist/resolution/frameworks/nestjs.js +374 -0
- package/dist/resolution/frameworks/nestjs.js.map +1 -0
- package/dist/search/query-utils.d.ts.map +1 -1
- package/dist/search/query-utils.js +29 -26
- package/dist/search/query-utils.js.map +1 -1
- package/dist/sync/git-hooks.d.ts +45 -0
- package/dist/sync/git-hooks.d.ts.map +1 -0
- package/dist/sync/git-hooks.js +223 -0
- package/dist/sync/git-hooks.js.map +1 -0
- package/dist/sync/index.d.ts +4 -0
- package/dist/sync/index.d.ts.map +1 -1
- package/dist/sync/index.js +12 -1
- package/dist/sync/index.js.map +1 -1
- package/dist/sync/watch-policy.d.ts +48 -0
- package/dist/sync/watch-policy.d.ts.map +1 -0
- package/dist/sync/watch-policy.js +124 -0
- package/dist/sync/watch-policy.js.map +1 -0
- package/dist/sync/watcher.d.ts.map +1 -1
- package/dist/sync/watcher.js +10 -0
- package/dist/sync/watcher.js.map +1 -1
- package/package.json +3 -3
- package/scripts/agent-eval/audit.sh +68 -0
- package/scripts/agent-eval/itrun.sh +107 -0
- package/scripts/agent-eval/parse-run.mjs +45 -0
- package/scripts/agent-eval/parse-session.mjs +93 -0
- package/scripts/agent-eval/run-agent.sh +34 -0
- package/scripts/agent-eval/run-all.sh +67 -0
- package/scripts/extract-release-notes.mjs +130 -0
- package/scripts/release.sh +5 -7
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Git Sync Hooks
|
|
4
|
+
*
|
|
5
|
+
* When the live file watcher is disabled (e.g. on WSL2 `/mnt/*` drives,
|
|
6
|
+
* see watch-policy.ts), the CodeGraph index would otherwise go stale until
|
|
7
|
+
* the user runs `codegraph sync` by hand. As an opt-in alternative, we can
|
|
8
|
+
* install git hooks that refresh the index after the operations that change
|
|
9
|
+
* files on disk: commit, merge (covers `git pull`), and checkout.
|
|
10
|
+
*
|
|
11
|
+
* The hooks run `codegraph sync` in the background so they never block git,
|
|
12
|
+
* and are guarded by `command -v codegraph` so they no-op cleanly when the
|
|
13
|
+
* CLI isn't on PATH. Our snippet is delimited by marker comments so install
|
|
14
|
+
* is idempotent and removal preserves any user-authored hook content.
|
|
15
|
+
*/
|
|
16
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
17
|
+
if (k2 === undefined) k2 = k;
|
|
18
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
19
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
20
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
21
|
+
}
|
|
22
|
+
Object.defineProperty(o, k2, desc);
|
|
23
|
+
}) : (function(o, m, k, k2) {
|
|
24
|
+
if (k2 === undefined) k2 = k;
|
|
25
|
+
o[k2] = m[k];
|
|
26
|
+
}));
|
|
27
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
28
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
29
|
+
}) : function(o, v) {
|
|
30
|
+
o["default"] = v;
|
|
31
|
+
});
|
|
32
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
33
|
+
var ownKeys = function(o) {
|
|
34
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
35
|
+
var ar = [];
|
|
36
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
37
|
+
return ar;
|
|
38
|
+
};
|
|
39
|
+
return ownKeys(o);
|
|
40
|
+
};
|
|
41
|
+
return function (mod) {
|
|
42
|
+
if (mod && mod.__esModule) return mod;
|
|
43
|
+
var result = {};
|
|
44
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
45
|
+
__setModuleDefault(result, mod);
|
|
46
|
+
return result;
|
|
47
|
+
};
|
|
48
|
+
})();
|
|
49
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
50
|
+
exports.DEFAULT_SYNC_HOOKS = void 0;
|
|
51
|
+
exports.isGitRepo = isGitRepo;
|
|
52
|
+
exports.installGitSyncHook = installGitSyncHook;
|
|
53
|
+
exports.removeGitSyncHook = removeGitSyncHook;
|
|
54
|
+
exports.isSyncHookInstalled = isSyncHookInstalled;
|
|
55
|
+
const fs = __importStar(require("fs"));
|
|
56
|
+
const path = __importStar(require("path"));
|
|
57
|
+
const child_process_1 = require("child_process");
|
|
58
|
+
const MARKER_BEGIN = '# >>> codegraph sync hook >>>';
|
|
59
|
+
const MARKER_END = '# <<< codegraph sync hook <<<';
|
|
60
|
+
/** Hooks installed by default: commit, merge (git pull), and checkout. */
|
|
61
|
+
exports.DEFAULT_SYNC_HOOKS = ['post-commit', 'post-merge', 'post-checkout'];
|
|
62
|
+
/**
|
|
63
|
+
* Whether `projectRoot` is inside a git working tree. Returns false if git
|
|
64
|
+
* isn't installed or the path isn't a repo.
|
|
65
|
+
*/
|
|
66
|
+
function isGitRepo(projectRoot) {
|
|
67
|
+
try {
|
|
68
|
+
const out = (0, child_process_1.execFileSync)('git', ['rev-parse', '--is-inside-work-tree'], {
|
|
69
|
+
cwd: projectRoot,
|
|
70
|
+
encoding: 'utf8',
|
|
71
|
+
stdio: ['ignore', 'pipe', 'ignore'],
|
|
72
|
+
}).trim();
|
|
73
|
+
return out === 'true';
|
|
74
|
+
}
|
|
75
|
+
catch {
|
|
76
|
+
return false;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Resolve the git hooks directory for a project, honoring `core.hooksPath`
|
|
81
|
+
* and git worktrees. Returns an absolute path, or null when not a repo.
|
|
82
|
+
*/
|
|
83
|
+
function gitHooksDir(projectRoot) {
|
|
84
|
+
try {
|
|
85
|
+
const out = (0, child_process_1.execFileSync)('git', ['rev-parse', '--git-path', 'hooks'], {
|
|
86
|
+
cwd: projectRoot,
|
|
87
|
+
encoding: 'utf8',
|
|
88
|
+
stdio: ['ignore', 'pipe', 'ignore'],
|
|
89
|
+
}).trim();
|
|
90
|
+
if (!out)
|
|
91
|
+
return null;
|
|
92
|
+
return path.isAbsolute(out) ? out : path.resolve(projectRoot, out);
|
|
93
|
+
}
|
|
94
|
+
catch {
|
|
95
|
+
return null;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
/** The shell snippet (between markers) injected into each hook. */
|
|
99
|
+
function markerBlock() {
|
|
100
|
+
return [
|
|
101
|
+
MARKER_BEGIN,
|
|
102
|
+
'# Keeps the CodeGraph index fresh while the live file watcher is off',
|
|
103
|
+
'# (e.g. WSL2 /mnt drives). Runs in the background so it never blocks git.',
|
|
104
|
+
'# Managed by codegraph; remove with `codegraph uninit` or delete this block.',
|
|
105
|
+
'if command -v codegraph >/dev/null 2>&1; then',
|
|
106
|
+
' ( codegraph sync >/dev/null 2>&1 & ) >/dev/null 2>&1',
|
|
107
|
+
'fi',
|
|
108
|
+
MARKER_END,
|
|
109
|
+
].join('\n');
|
|
110
|
+
}
|
|
111
|
+
/** Remove our marker block (and the marker lines) from hook content. */
|
|
112
|
+
function stripMarkerBlock(content) {
|
|
113
|
+
const lines = content.split('\n');
|
|
114
|
+
const kept = [];
|
|
115
|
+
let inBlock = false;
|
|
116
|
+
for (const line of lines) {
|
|
117
|
+
const trimmed = line.trim();
|
|
118
|
+
if (trimmed === MARKER_BEGIN) {
|
|
119
|
+
inBlock = true;
|
|
120
|
+
continue;
|
|
121
|
+
}
|
|
122
|
+
if (trimmed === MARKER_END) {
|
|
123
|
+
inBlock = false;
|
|
124
|
+
continue;
|
|
125
|
+
}
|
|
126
|
+
if (!inBlock)
|
|
127
|
+
kept.push(line);
|
|
128
|
+
}
|
|
129
|
+
return kept.join('\n');
|
|
130
|
+
}
|
|
131
|
+
/** Whether a hook body is just a shebang / blank lines (i.e. only ever ours). */
|
|
132
|
+
function isEffectivelyEmpty(content) {
|
|
133
|
+
return content
|
|
134
|
+
.split('\n')
|
|
135
|
+
.map((l) => l.trim())
|
|
136
|
+
.every((l) => l.length === 0 || l.startsWith('#!'));
|
|
137
|
+
}
|
|
138
|
+
function chmodExecutable(file) {
|
|
139
|
+
try {
|
|
140
|
+
fs.chmodSync(file, 0o755);
|
|
141
|
+
}
|
|
142
|
+
catch {
|
|
143
|
+
/* chmod is a no-op / unsupported on some platforms (e.g. Windows) */
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Install (or update) the CodeGraph sync hooks in a git repository.
|
|
148
|
+
* Idempotent: re-running replaces our marker block rather than duplicating
|
|
149
|
+
* it, and any user-authored hook content is preserved.
|
|
150
|
+
*/
|
|
151
|
+
function installGitSyncHook(projectRoot, hooks = exports.DEFAULT_SYNC_HOOKS) {
|
|
152
|
+
const hooksDir = gitHooksDir(projectRoot);
|
|
153
|
+
if (!hooksDir) {
|
|
154
|
+
return { installed: [], hooksDir: null, skipped: 'not a git repository' };
|
|
155
|
+
}
|
|
156
|
+
try {
|
|
157
|
+
fs.mkdirSync(hooksDir, { recursive: true });
|
|
158
|
+
}
|
|
159
|
+
catch {
|
|
160
|
+
return { installed: [], hooksDir, skipped: 'could not access the git hooks directory' };
|
|
161
|
+
}
|
|
162
|
+
const block = markerBlock();
|
|
163
|
+
const installed = [];
|
|
164
|
+
for (const hook of hooks) {
|
|
165
|
+
const file = path.join(hooksDir, hook);
|
|
166
|
+
let content;
|
|
167
|
+
if (fs.existsSync(file)) {
|
|
168
|
+
// Strip any prior block, then re-append the current one.
|
|
169
|
+
const base = stripMarkerBlock(fs.readFileSync(file, 'utf8')).replace(/\s*$/, '');
|
|
170
|
+
content = base.length > 0
|
|
171
|
+
? `${base}\n\n${block}\n`
|
|
172
|
+
: `#!/bin/sh\n${block}\n`;
|
|
173
|
+
}
|
|
174
|
+
else {
|
|
175
|
+
content = `#!/bin/sh\n${block}\n`;
|
|
176
|
+
}
|
|
177
|
+
fs.writeFileSync(file, content);
|
|
178
|
+
chmodExecutable(file);
|
|
179
|
+
installed.push(hook);
|
|
180
|
+
}
|
|
181
|
+
return { installed, hooksDir };
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* Remove the CodeGraph sync hooks. Strips only our marker block; deletes the
|
|
185
|
+
* hook file entirely when nothing but a shebang remains, otherwise rewrites
|
|
186
|
+
* the user's content untouched.
|
|
187
|
+
*/
|
|
188
|
+
function removeGitSyncHook(projectRoot, hooks = exports.DEFAULT_SYNC_HOOKS) {
|
|
189
|
+
const hooksDir = gitHooksDir(projectRoot);
|
|
190
|
+
if (!hooksDir) {
|
|
191
|
+
return { installed: [], hooksDir: null, skipped: 'not a git repository' };
|
|
192
|
+
}
|
|
193
|
+
const removed = [];
|
|
194
|
+
for (const hook of hooks) {
|
|
195
|
+
const file = path.join(hooksDir, hook);
|
|
196
|
+
if (!fs.existsSync(file))
|
|
197
|
+
continue;
|
|
198
|
+
const original = fs.readFileSync(file, 'utf8');
|
|
199
|
+
if (!original.includes(MARKER_BEGIN))
|
|
200
|
+
continue;
|
|
201
|
+
const stripped = stripMarkerBlock(original);
|
|
202
|
+
if (isEffectivelyEmpty(stripped)) {
|
|
203
|
+
fs.unlinkSync(file);
|
|
204
|
+
}
|
|
205
|
+
else {
|
|
206
|
+
fs.writeFileSync(file, `${stripped.replace(/\s*$/, '')}\n`);
|
|
207
|
+
chmodExecutable(file);
|
|
208
|
+
}
|
|
209
|
+
removed.push(hook);
|
|
210
|
+
}
|
|
211
|
+
return { installed: removed, hooksDir };
|
|
212
|
+
}
|
|
213
|
+
/** Whether any CodeGraph sync hook is currently installed. */
|
|
214
|
+
function isSyncHookInstalled(projectRoot, hooks = exports.DEFAULT_SYNC_HOOKS) {
|
|
215
|
+
const hooksDir = gitHooksDir(projectRoot);
|
|
216
|
+
if (!hooksDir)
|
|
217
|
+
return false;
|
|
218
|
+
return hooks.some((hook) => {
|
|
219
|
+
const file = path.join(hooksDir, hook);
|
|
220
|
+
return fs.existsSync(file) && fs.readFileSync(file, 'utf8').includes(MARKER_BEGIN);
|
|
221
|
+
});
|
|
222
|
+
}
|
|
223
|
+
//# sourceMappingURL=git-hooks.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"git-hooks.js","sourceRoot":"","sources":["../../src/sync/git-hooks.ts"],"names":[],"mappings":"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"}
|
package/dist/sync/index.d.ts
CHANGED
|
@@ -6,8 +6,12 @@
|
|
|
6
6
|
*
|
|
7
7
|
* Components:
|
|
8
8
|
* - FileWatcher: Debounced fs.watch that auto-triggers sync on file changes
|
|
9
|
+
* - Watch policy: decides when the watcher must be disabled (e.g. WSL2 /mnt)
|
|
10
|
+
* - Git sync hooks: opt-in commit/merge/checkout hooks when watching is off
|
|
9
11
|
* - Content hashing for change detection (in extraction module)
|
|
10
12
|
* - Incremental reindexing (in extraction module)
|
|
11
13
|
*/
|
|
12
14
|
export { FileWatcher, WatchOptions } from './watcher';
|
|
15
|
+
export { watchDisabledReason, detectWsl } from './watch-policy';
|
|
16
|
+
export { installGitSyncHook, removeGitSyncHook, isSyncHookInstalled, isGitRepo, DEFAULT_SYNC_HOOKS, type GitHookName, type GitHookResult, } from './git-hooks';
|
|
13
17
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/sync/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/sync/index.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/sync/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AACtD,OAAO,EAAE,mBAAmB,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAChE,OAAO,EACL,kBAAkB,EAClB,iBAAiB,EACjB,mBAAmB,EACnB,SAAS,EACT,kBAAkB,EAClB,KAAK,WAAW,EAChB,KAAK,aAAa,GACnB,MAAM,aAAa,CAAC"}
|
package/dist/sync/index.js
CHANGED
|
@@ -7,11 +7,22 @@
|
|
|
7
7
|
*
|
|
8
8
|
* Components:
|
|
9
9
|
* - FileWatcher: Debounced fs.watch that auto-triggers sync on file changes
|
|
10
|
+
* - Watch policy: decides when the watcher must be disabled (e.g. WSL2 /mnt)
|
|
11
|
+
* - Git sync hooks: opt-in commit/merge/checkout hooks when watching is off
|
|
10
12
|
* - Content hashing for change detection (in extraction module)
|
|
11
13
|
* - Incremental reindexing (in extraction module)
|
|
12
14
|
*/
|
|
13
15
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
14
|
-
exports.FileWatcher = void 0;
|
|
16
|
+
exports.DEFAULT_SYNC_HOOKS = exports.isGitRepo = exports.isSyncHookInstalled = exports.removeGitSyncHook = exports.installGitSyncHook = exports.detectWsl = exports.watchDisabledReason = exports.FileWatcher = void 0;
|
|
15
17
|
var watcher_1 = require("./watcher");
|
|
16
18
|
Object.defineProperty(exports, "FileWatcher", { enumerable: true, get: function () { return watcher_1.FileWatcher; } });
|
|
19
|
+
var watch_policy_1 = require("./watch-policy");
|
|
20
|
+
Object.defineProperty(exports, "watchDisabledReason", { enumerable: true, get: function () { return watch_policy_1.watchDisabledReason; } });
|
|
21
|
+
Object.defineProperty(exports, "detectWsl", { enumerable: true, get: function () { return watch_policy_1.detectWsl; } });
|
|
22
|
+
var git_hooks_1 = require("./git-hooks");
|
|
23
|
+
Object.defineProperty(exports, "installGitSyncHook", { enumerable: true, get: function () { return git_hooks_1.installGitSyncHook; } });
|
|
24
|
+
Object.defineProperty(exports, "removeGitSyncHook", { enumerable: true, get: function () { return git_hooks_1.removeGitSyncHook; } });
|
|
25
|
+
Object.defineProperty(exports, "isSyncHookInstalled", { enumerable: true, get: function () { return git_hooks_1.isSyncHookInstalled; } });
|
|
26
|
+
Object.defineProperty(exports, "isGitRepo", { enumerable: true, get: function () { return git_hooks_1.isGitRepo; } });
|
|
27
|
+
Object.defineProperty(exports, "DEFAULT_SYNC_HOOKS", { enumerable: true, get: function () { return git_hooks_1.DEFAULT_SYNC_HOOKS; } });
|
|
17
28
|
//# sourceMappingURL=index.js.map
|
package/dist/sync/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/sync/index.ts"],"names":[],"mappings":";AAAA
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/sync/index.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;GAYG;;;AAEH,qCAAsD;AAA7C,sGAAA,WAAW,OAAA;AACpB,+CAAgE;AAAvD,mHAAA,mBAAmB,OAAA;AAAE,yGAAA,SAAS,OAAA;AACvC,yCAQqB;AAPnB,+GAAA,kBAAkB,OAAA;AAClB,8GAAA,iBAAiB,OAAA;AACjB,gHAAA,mBAAmB,OAAA;AACnB,sGAAA,SAAS,OAAA;AACT,+GAAA,kBAAkB,OAAA"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Watch Policy
|
|
3
|
+
*
|
|
4
|
+
* Decides whether the live file watcher should run for a given project.
|
|
5
|
+
*
|
|
6
|
+
* Native recursive `fs.watch` is pathologically slow on WSL2 `/mnt/*`
|
|
7
|
+
* drives (NTFS exposed over the 9p/drvfs bridge): setting up the recursive
|
|
8
|
+
* watch walks the directory tree, and every readdir/stat crosses the
|
|
9
|
+
* Windows boundary. Inside an MCP server this stalls the event loop during
|
|
10
|
+
* startup long enough to blow past host handshake timeouts (opencode's 30s),
|
|
11
|
+
* so the tools never appear. See issue #199.
|
|
12
|
+
*
|
|
13
|
+
* This module centralizes the on/off decision so the watcher, the MCP
|
|
14
|
+
* server (for diagnostics), and the installer all agree.
|
|
15
|
+
*/
|
|
16
|
+
/**
|
|
17
|
+
* Detect whether the current process is running under WSL (Windows
|
|
18
|
+
* Subsystem for Linux). Result is cached after the first call.
|
|
19
|
+
*
|
|
20
|
+
* Checks the WSL-specific env vars first (no I/O), then falls back to
|
|
21
|
+
* `/proc/version`, which contains "microsoft" on WSL kernels.
|
|
22
|
+
*/
|
|
23
|
+
export declare function detectWsl(): boolean;
|
|
24
|
+
/**
|
|
25
|
+
* Inputs that can be overridden in tests so the decision is deterministic
|
|
26
|
+
* without touching real env vars or `/proc/version`.
|
|
27
|
+
*/
|
|
28
|
+
export interface WatchProbe {
|
|
29
|
+
/** Defaults to `process.env`. */
|
|
30
|
+
env?: NodeJS.ProcessEnv;
|
|
31
|
+
/** Defaults to `detectWsl()`. */
|
|
32
|
+
isWsl?: boolean;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Decide whether the file watcher should be disabled for a project, and why.
|
|
36
|
+
*
|
|
37
|
+
* Returns a short human-readable reason when watching should be skipped, or
|
|
38
|
+
* `null` when it should run normally.
|
|
39
|
+
*
|
|
40
|
+
* Precedence (first match wins):
|
|
41
|
+
* 1. `CODEGRAPH_NO_WATCH=1` → off (explicit opt-out always wins)
|
|
42
|
+
* 2. `CODEGRAPH_FORCE_WATCH=1` → on (overrides auto-detection)
|
|
43
|
+
* 3. WSL2 + `/mnt/*` drive → off (recursive fs.watch is too slow; #199)
|
|
44
|
+
*/
|
|
45
|
+
export declare function watchDisabledReason(projectRoot: string, probe?: WatchProbe): string | null;
|
|
46
|
+
/** Test-only: reset the cached WSL detection. */
|
|
47
|
+
export declare function __resetWslCacheForTests(): void;
|
|
48
|
+
//# sourceMappingURL=watch-policy.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"watch-policy.d.ts","sourceRoot":"","sources":["../../src/sync/watch-policy.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAQH;;;;;;GAMG;AACH,wBAAgB,SAAS,IAAI,OAAO,CAmBnC;AAWD;;;GAGG;AACH,MAAM,WAAW,UAAU;IACzB,iCAAiC;IACjC,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IACxB,iCAAiC;IACjC,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,mBAAmB,CAAC,WAAW,EAAE,MAAM,EAAE,KAAK,GAAE,UAAe,GAAG,MAAM,GAAG,IAAI,CAgB9F;AAED,iDAAiD;AACjD,wBAAgB,uBAAuB,IAAI,IAAI,CAG9C"}
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Watch Policy
|
|
4
|
+
*
|
|
5
|
+
* Decides whether the live file watcher should run for a given project.
|
|
6
|
+
*
|
|
7
|
+
* Native recursive `fs.watch` is pathologically slow on WSL2 `/mnt/*`
|
|
8
|
+
* drives (NTFS exposed over the 9p/drvfs bridge): setting up the recursive
|
|
9
|
+
* watch walks the directory tree, and every readdir/stat crosses the
|
|
10
|
+
* Windows boundary. Inside an MCP server this stalls the event loop during
|
|
11
|
+
* startup long enough to blow past host handshake timeouts (opencode's 30s),
|
|
12
|
+
* so the tools never appear. See issue #199.
|
|
13
|
+
*
|
|
14
|
+
* This module centralizes the on/off decision so the watcher, the MCP
|
|
15
|
+
* server (for diagnostics), and the installer all agree.
|
|
16
|
+
*/
|
|
17
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
18
|
+
if (k2 === undefined) k2 = k;
|
|
19
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
20
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
21
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
22
|
+
}
|
|
23
|
+
Object.defineProperty(o, k2, desc);
|
|
24
|
+
}) : (function(o, m, k, k2) {
|
|
25
|
+
if (k2 === undefined) k2 = k;
|
|
26
|
+
o[k2] = m[k];
|
|
27
|
+
}));
|
|
28
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
29
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
30
|
+
}) : function(o, v) {
|
|
31
|
+
o["default"] = v;
|
|
32
|
+
});
|
|
33
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
34
|
+
var ownKeys = function(o) {
|
|
35
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
36
|
+
var ar = [];
|
|
37
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
38
|
+
return ar;
|
|
39
|
+
};
|
|
40
|
+
return ownKeys(o);
|
|
41
|
+
};
|
|
42
|
+
return function (mod) {
|
|
43
|
+
if (mod && mod.__esModule) return mod;
|
|
44
|
+
var result = {};
|
|
45
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
46
|
+
__setModuleDefault(result, mod);
|
|
47
|
+
return result;
|
|
48
|
+
};
|
|
49
|
+
})();
|
|
50
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
51
|
+
exports.detectWsl = detectWsl;
|
|
52
|
+
exports.watchDisabledReason = watchDisabledReason;
|
|
53
|
+
exports.__resetWslCacheForTests = __resetWslCacheForTests;
|
|
54
|
+
const fs = __importStar(require("fs"));
|
|
55
|
+
const utils_1 = require("../utils");
|
|
56
|
+
let wslChecked = false;
|
|
57
|
+
let wslValue = false;
|
|
58
|
+
/**
|
|
59
|
+
* Detect whether the current process is running under WSL (Windows
|
|
60
|
+
* Subsystem for Linux). Result is cached after the first call.
|
|
61
|
+
*
|
|
62
|
+
* Checks the WSL-specific env vars first (no I/O), then falls back to
|
|
63
|
+
* `/proc/version`, which contains "microsoft" on WSL kernels.
|
|
64
|
+
*/
|
|
65
|
+
function detectWsl() {
|
|
66
|
+
if (wslChecked)
|
|
67
|
+
return wslValue;
|
|
68
|
+
wslChecked = true;
|
|
69
|
+
if (process.platform !== 'linux') {
|
|
70
|
+
wslValue = false;
|
|
71
|
+
return wslValue;
|
|
72
|
+
}
|
|
73
|
+
if (process.env.WSL_DISTRO_NAME || process.env.WSL_INTEROP) {
|
|
74
|
+
wslValue = true;
|
|
75
|
+
return wslValue;
|
|
76
|
+
}
|
|
77
|
+
try {
|
|
78
|
+
const version = fs.readFileSync('/proc/version', 'utf8').toLowerCase();
|
|
79
|
+
wslValue = version.includes('microsoft') || version.includes('wsl');
|
|
80
|
+
}
|
|
81
|
+
catch {
|
|
82
|
+
wslValue = false;
|
|
83
|
+
}
|
|
84
|
+
return wslValue;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* True for WSL Windows-drive mounts like `/mnt/c` or `/mnt/d/project`.
|
|
88
|
+
* Deliberately matches only single-letter drive mounts, so genuinely fast
|
|
89
|
+
* Linux mounts such as `/mnt/wsl/...` are not flagged.
|
|
90
|
+
*/
|
|
91
|
+
function isWindowsDriveMount(projectRoot) {
|
|
92
|
+
return /^\/mnt\/[a-z](\/|$)/i.test((0, utils_1.normalizePath)(projectRoot));
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Decide whether the file watcher should be disabled for a project, and why.
|
|
96
|
+
*
|
|
97
|
+
* Returns a short human-readable reason when watching should be skipped, or
|
|
98
|
+
* `null` when it should run normally.
|
|
99
|
+
*
|
|
100
|
+
* Precedence (first match wins):
|
|
101
|
+
* 1. `CODEGRAPH_NO_WATCH=1` → off (explicit opt-out always wins)
|
|
102
|
+
* 2. `CODEGRAPH_FORCE_WATCH=1` → on (overrides auto-detection)
|
|
103
|
+
* 3. WSL2 + `/mnt/*` drive → off (recursive fs.watch is too slow; #199)
|
|
104
|
+
*/
|
|
105
|
+
function watchDisabledReason(projectRoot, probe = {}) {
|
|
106
|
+
const env = probe.env ?? process.env;
|
|
107
|
+
if (env.CODEGRAPH_NO_WATCH === '1') {
|
|
108
|
+
return 'CODEGRAPH_NO_WATCH=1 is set';
|
|
109
|
+
}
|
|
110
|
+
if (env.CODEGRAPH_FORCE_WATCH === '1') {
|
|
111
|
+
return null;
|
|
112
|
+
}
|
|
113
|
+
const isWsl = probe.isWsl ?? detectWsl();
|
|
114
|
+
if (isWsl && isWindowsDriveMount(projectRoot)) {
|
|
115
|
+
return 'project is on a WSL2 /mnt/ drive, where recursive fs.watch is too slow to be reliable';
|
|
116
|
+
}
|
|
117
|
+
return null;
|
|
118
|
+
}
|
|
119
|
+
/** Test-only: reset the cached WSL detection. */
|
|
120
|
+
function __resetWslCacheForTests() {
|
|
121
|
+
wslChecked = false;
|
|
122
|
+
wslValue = false;
|
|
123
|
+
}
|
|
124
|
+
//# sourceMappingURL=watch-policy.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"watch-policy.js","sourceRoot":"","sources":["../../src/sync/watch-policy.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;GAcG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAeH,8BAmBC;AAiCD,kDAgBC;AAGD,0DAGC;AAvFD,uCAAyB;AACzB,oCAAyC;AAEzC,IAAI,UAAU,GAAG,KAAK,CAAC;AACvB,IAAI,QAAQ,GAAG,KAAK,CAAC;AAErB;;;;;;GAMG;AACH,SAAgB,SAAS;IACvB,IAAI,UAAU;QAAE,OAAO,QAAQ,CAAC;IAChC,UAAU,GAAG,IAAI,CAAC;IAElB,IAAI,OAAO,CAAC,QAAQ,KAAK,OAAO,EAAE,CAAC;QACjC,QAAQ,GAAG,KAAK,CAAC;QACjB,OAAO,QAAQ,CAAC;IAClB,CAAC;IACD,IAAI,OAAO,CAAC,GAAG,CAAC,eAAe,IAAI,OAAO,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC;QAC3D,QAAQ,GAAG,IAAI,CAAC;QAChB,OAAO,QAAQ,CAAC;IAClB,CAAC;IACD,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,eAAe,EAAE,MAAM,CAAC,CAAC,WAAW,EAAE,CAAC;QACvE,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAC,IAAI,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;IACtE,CAAC;IAAC,MAAM,CAAC;QACP,QAAQ,GAAG,KAAK,CAAC;IACnB,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED;;;;GAIG;AACH,SAAS,mBAAmB,CAAC,WAAmB;IAC9C,OAAO,sBAAsB,CAAC,IAAI,CAAC,IAAA,qBAAa,EAAC,WAAW,CAAC,CAAC,CAAC;AACjE,CAAC;AAaD;;;;;;;;;;GAUG;AACH,SAAgB,mBAAmB,CAAC,WAAmB,EAAE,QAAoB,EAAE;IAC7E,MAAM,GAAG,GAAG,KAAK,CAAC,GAAG,IAAI,OAAO,CAAC,GAAG,CAAC;IAErC,IAAI,GAAG,CAAC,kBAAkB,KAAK,GAAG,EAAE,CAAC;QACnC,OAAO,6BAA6B,CAAC;IACvC,CAAC;IACD,IAAI,GAAG,CAAC,qBAAqB,KAAK,GAAG,EAAE,CAAC;QACtC,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,IAAI,SAAS,EAAE,CAAC;IACzC,IAAI,KAAK,IAAI,mBAAmB,CAAC,WAAW,CAAC,EAAE,CAAC;QAC9C,OAAO,uFAAuF,CAAC;IACjG,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC;AAED,iDAAiD;AACjD,SAAgB,uBAAuB;IACrC,UAAU,GAAG,KAAK,CAAC;IACnB,QAAQ,GAAG,KAAK,CAAC;AACnB,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"watcher.d.ts","sourceRoot":"","sources":["../../src/sync/watcher.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,OAAO,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"watcher.d.ts","sourceRoot":"","sources":["../../src/sync/watcher.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,OAAO,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAM3C;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpB;;OAEG;IACH,cAAc,CAAC,EAAE,CAAC,MAAM,EAAE;QAAE,YAAY,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC;IAEhF;;OAEG;IACH,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;CACtC;AAED;;;;;;;;;GASG;AACH,qBAAa,WAAW;IACtB,OAAO,CAAC,OAAO,CAA6B;IAC5C,OAAO,CAAC,aAAa,CAA8C;IACnE,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,OAAO,CAAS;IAExB,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;IACrC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAkB;IACzC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA8D;IACrF,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAC,CAAiC;IACjE,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAC,CAA8B;gBAGzD,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,eAAe,EACvB,MAAM,EAAE,MAAM,OAAO,CAAC;QAAE,YAAY,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE,CAAC,EACnE,OAAO,GAAE,YAAiB;IAU5B;;;OAGG;IACH,KAAK,IAAI,OAAO;IA2DhB;;OAEG;IACH,IAAI,IAAI,IAAI;IAiBZ;;OAEG;IACH,QAAQ,IAAI,OAAO;IAInB;;OAEG;IACH,OAAO,CAAC,YAAY;IAUpB;;OAEG;YACW,KAAK;CAuBpB"}
|
package/dist/sync/watcher.js
CHANGED
|
@@ -47,6 +47,7 @@ const fs = __importStar(require("fs"));
|
|
|
47
47
|
const extraction_1 = require("../extraction");
|
|
48
48
|
const errors_1 = require("../errors");
|
|
49
49
|
const utils_1 = require("../utils");
|
|
50
|
+
const watch_policy_1 = require("./watch-policy");
|
|
50
51
|
/**
|
|
51
52
|
* FileWatcher monitors a project directory for changes and triggers
|
|
52
53
|
* debounced sync operations via a provided callback.
|
|
@@ -85,6 +86,15 @@ class FileWatcher {
|
|
|
85
86
|
if (this.watcher)
|
|
86
87
|
return true; // Already watching
|
|
87
88
|
this.stopped = false;
|
|
89
|
+
// Some environments make recursive fs.watch unusable — most notably WSL2
|
|
90
|
+
// /mnt/ drives, where setup blocks long enough to break MCP startup
|
|
91
|
+
// handshakes (issue #199). Skip watching there; callers fall back to
|
|
92
|
+
// manual `codegraph sync` or the git sync hooks.
|
|
93
|
+
const disabledReason = (0, watch_policy_1.watchDisabledReason)(this.projectRoot);
|
|
94
|
+
if (disabledReason) {
|
|
95
|
+
(0, errors_1.logDebug)('File watcher disabled', { reason: disabledReason, projectRoot: this.projectRoot });
|
|
96
|
+
return false;
|
|
97
|
+
}
|
|
88
98
|
try {
|
|
89
99
|
this.watcher = fs.watch(this.projectRoot, { recursive: true }, (_eventType, filename) => {
|
|
90
100
|
if (!filename || this.stopped)
|
package/dist/sync/watcher.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"watcher.js","sourceRoot":"","sources":["../../src/sync/watcher.ts"],"names":[],"mappings":";AAAA;;;;;;;;GAQG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAEH,uCAAyB;AAEzB,8CAAkD;AAClD,sCAA8C;AAC9C,oCAAyC;
|
|
1
|
+
{"version":3,"file":"watcher.js","sourceRoot":"","sources":["../../src/sync/watcher.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@colbymchenry/codegraph",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.8.0",
|
|
4
4
|
"description": "Supercharge Claude Code with semantic code intelligence. 94% fewer tool calls • 77% faster exploration • 100% local.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -51,9 +51,9 @@
|
|
|
51
51
|
"vitest": "^2.1.9"
|
|
52
52
|
},
|
|
53
53
|
"optionalDependencies": {
|
|
54
|
-
"better-sqlite3": "^
|
|
54
|
+
"better-sqlite3": "^12.4.1"
|
|
55
55
|
},
|
|
56
56
|
"engines": {
|
|
57
|
-
"node": ">=
|
|
57
|
+
"node": ">=20.0.0 <25.0.0"
|
|
58
58
|
}
|
|
59
59
|
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# One-shot CodeGraph quality audit:
|
|
3
|
+
# set version -> ensure corpus repo -> wipe+reindex with that version ->
|
|
4
|
+
# run with/without A/B -> restore the local dev link.
|
|
5
|
+
#
|
|
6
|
+
# Usage: audit.sh <version> <repo-name> <repo-url> "<question>" [headless|all]
|
|
7
|
+
# <version> "local" (build + npm link this repo) | "latest" | a version (e.g. 0.7.10)
|
|
8
|
+
# <repo-name> dir name under the corpus dir
|
|
9
|
+
# <repo-url> git URL (cloned --depth 1 when the repo dir is missing)
|
|
10
|
+
# [mode] headless (default) | all (also the interactive tmux arms)
|
|
11
|
+
# Env: CORPUS corpus dir (default: /tmp/codegraph-corpus)
|
|
12
|
+
set -uo pipefail
|
|
13
|
+
|
|
14
|
+
VERSION="${1:?usage: audit.sh <version> <repo-name> <repo-url> \"<question>\" [mode]}"
|
|
15
|
+
NAME="${2:?repo-name required}"
|
|
16
|
+
URL="${3:?repo-url required}"
|
|
17
|
+
Q="${4:?question required}"
|
|
18
|
+
MODE="${5:-headless}"
|
|
19
|
+
|
|
20
|
+
HARNESS="$(cd "$(dirname "$0")" && pwd)"
|
|
21
|
+
REPO_ROOT="$(cd "$HARNESS/../.." && pwd)" # codegraph repo root
|
|
22
|
+
CORPUS="${CORPUS:-/tmp/codegraph-corpus}"
|
|
23
|
+
REPO="$CORPUS/$NAME"
|
|
24
|
+
PKG="@colbymchenry/codegraph"
|
|
25
|
+
|
|
26
|
+
echo "==================== CodeGraph audit ===================="
|
|
27
|
+
echo "version=$VERSION repo=$NAME mode=$MODE corpus=$CORPUS"
|
|
28
|
+
echo
|
|
29
|
+
|
|
30
|
+
# 1. Set the codegraph version under test (mutates the global install).
|
|
31
|
+
if [ "$VERSION" = local ]; then
|
|
32
|
+
echo "→ [1/4] building + linking local dev build (local-install.sh)"
|
|
33
|
+
( cd "$REPO_ROOT" && ./scripts/local-install.sh ) || { echo "local-install.sh failed"; exit 1; }
|
|
34
|
+
else
|
|
35
|
+
echo "→ [1/4] installing $PKG@$VERSION globally"
|
|
36
|
+
npm install -g "$PKG@$VERSION" || { echo "npm install -g $PKG@$VERSION failed"; exit 1; }
|
|
37
|
+
fi
|
|
38
|
+
ACTUAL="$(codegraph --version 2>/dev/null || echo '?')"
|
|
39
|
+
echo " codegraph on PATH: $(command -v codegraph) -> $ACTUAL"
|
|
40
|
+
|
|
41
|
+
# 2. Ensure the corpus repo exists (clone shallow if missing, reuse if present).
|
|
42
|
+
mkdir -p "$CORPUS"
|
|
43
|
+
if [ -d "$REPO/.git" ]; then
|
|
44
|
+
echo "→ [2/4] reusing existing checkout: $REPO"
|
|
45
|
+
else
|
|
46
|
+
echo "→ [2/4] cloning $URL"
|
|
47
|
+
git clone --depth 1 "$URL" "$REPO" || { echo "git clone failed"; exit 1; }
|
|
48
|
+
fi
|
|
49
|
+
|
|
50
|
+
# 3. Wipe + re-index with THIS version (the index must be built by the same
|
|
51
|
+
# binary that serves it — different versions extract differently).
|
|
52
|
+
echo "→ [3/4] wiping .codegraph and re-indexing with $ACTUAL"
|
|
53
|
+
rm -rf "$REPO/.codegraph"
|
|
54
|
+
( cd "$REPO" && codegraph init -i ) || { echo "indexing failed"; exit 1; }
|
|
55
|
+
|
|
56
|
+
# 4. Run the with/without A/B.
|
|
57
|
+
echo "→ [4/4] running A/B harness (mode=$MODE)"
|
|
58
|
+
bash "$HARNESS/run-all.sh" "$REPO" "$Q" "$MODE"
|
|
59
|
+
|
|
60
|
+
# Restore the dev link (the normal working state in this repo).
|
|
61
|
+
echo
|
|
62
|
+
echo "→ restoring local dev link (local-install.sh)"
|
|
63
|
+
if ( cd "$REPO_ROOT" && ./scripts/local-install.sh >/dev/null 2>&1 ); then
|
|
64
|
+
echo " global codegraph restored to dev build"
|
|
65
|
+
else
|
|
66
|
+
echo " WARN: restore failed — run ./scripts/local-install.sh manually"
|
|
67
|
+
fi
|
|
68
|
+
echo "==================== audit complete ===================="
|