gitnexus 1.6.10-rc.8 → 1.6.10-rc.9
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
CHANGED
|
@@ -535,17 +535,26 @@ After scope resolution, analyze prunes inert block-local value symbols (a functi
|
|
|
535
535
|
|
|
536
536
|
Programmatic callers can pass `keepLocalValueSymbols: true` in `PipelineOptions` instead of setting the env var.
|
|
537
537
|
|
|
538
|
-
### Hook augmentation
|
|
538
|
+
### Hook augmentation and skip diagnostics
|
|
539
539
|
|
|
540
|
-
The Claude Code / Antigravity hooks
|
|
540
|
+
The Claude Code / Antigravity hooks keep their **stderr** silent on normal skip
|
|
541
541
|
paths so strict hook runners (e.g. Codex `PreToolUse`) never see unexpected
|
|
542
|
-
output.
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
542
|
+
diagnostic output.
|
|
543
|
+
|
|
544
|
+
When a GitNexus process holds the repo DB write lock (the common case — the MCP
|
|
545
|
+
server is running, or the DB-lock probe timed out and failed closed), the local
|
|
546
|
+
CLI `augment` can't run (LadybugDB is single-writer). Rather than drop the
|
|
547
|
+
augmentation, the hook hands the agent a short, conditional MCP-query hint on
|
|
548
|
+
stdout (the sanctioned `additionalContext` channel) — _"if the GitNexus MCP tools
|
|
549
|
+
are live in this session, call `query` …"_ — so an agent that has the tools can
|
|
550
|
+
still fetch graph-ranked context. The hint is throttled to at most once per repo
|
|
551
|
+
per window (`GITNEXUS_MCP_HINT_THROTTLE_MS`, default 10 min; `0` disables), so an
|
|
552
|
+
owner-locked session isn't nudged on every search. A stale-index reminder, or an
|
|
553
|
+
already-current index, stays silent.
|
|
554
|
+
|
|
555
|
+
To see why a hook skipped the CLI augment, set `GITNEXUS_DEBUG=1` and re-run the
|
|
556
|
+
action — the hook writes the reason (e.g. `[GitNexus] augment skipped: MCP server
|
|
557
|
+
owns DB`) and the stale-index hint to its stderr:
|
|
549
558
|
|
|
550
559
|
```bash
|
|
551
560
|
GITNEXUS_DEBUG=1 <your command> # surfaces hook skip/diagnostic reasons on stderr
|
|
@@ -391,6 +391,49 @@ function buildAfterToolContext(input) {
|
|
|
391
391
|
return parts.length > 0 ? parts.join('\n\n') : null;
|
|
392
392
|
}
|
|
393
393
|
|
|
394
|
+
/**
|
|
395
|
+
* Fallback augmentation for the #2396 path: when a GitNexus process holds the
|
|
396
|
+
* lbug DB write lock the CLI `augment` can't run, so point the agent at the MCP
|
|
397
|
+
* `query` tool instead. Phrased conditionally ("if the MCP tools are live") so it
|
|
398
|
+
* stays truthful on every owner path — a confirmed MCP owner, a `serve` owner, or
|
|
399
|
+
* a fail-closed probe where no server is actually confirmed. `pattern` is embedded
|
|
400
|
+
* verbatim; the caller (writeAdditionalContext) JSON-escapes it structurally.
|
|
401
|
+
*/
|
|
402
|
+
function buildMcpQueryHint(pattern) {
|
|
403
|
+
return (
|
|
404
|
+
`[GitNexus] Local augment is unavailable (the graph DB is held by another ` +
|
|
405
|
+
`GitNexus process). If the GitNexus MCP tools are live in this session, call ` +
|
|
406
|
+
`the GitNexus \`query\` MCP tool (e.g. mcp__gitnexus__query) with ` +
|
|
407
|
+
`search_query "${pattern}".`
|
|
408
|
+
);
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
/**
|
|
412
|
+
* #2396 throttle: emit the MCP-query hint at most once per repo per window, so an
|
|
413
|
+
* owner-locked session isn't nudged on every search. Window (ms) via
|
|
414
|
+
* GITNEXUS_MCP_HINT_THROTTLE_MS (default 10min; 0/invalid disables). Best-effort —
|
|
415
|
+
* any fs error falls back to emitting.
|
|
416
|
+
* ponytail: per-repo mtime marker, shared across concurrent sessions on the same
|
|
417
|
+
* repo; add per-session dedup only if that sharing becomes a problem.
|
|
418
|
+
*/
|
|
419
|
+
function shouldEmitMcpHint(gitNexusDir) {
|
|
420
|
+
const raw = process.env.GITNEXUS_MCP_HINT_THROTTLE_MS;
|
|
421
|
+
const windowMs = raw === undefined || raw === '' ? 600000 : Number(raw);
|
|
422
|
+
if (!Number.isFinite(windowMs) || windowMs <= 0) return true;
|
|
423
|
+
const marker = path.join(gitNexusDir, '.mcp-hint-shown');
|
|
424
|
+
try {
|
|
425
|
+
if (Date.now() - fs.statSync(marker).mtimeMs < windowMs) return false;
|
|
426
|
+
} catch {
|
|
427
|
+
/* marker missing/unreadable → emit */
|
|
428
|
+
}
|
|
429
|
+
try {
|
|
430
|
+
fs.writeFileSync(marker, '');
|
|
431
|
+
} catch {
|
|
432
|
+
/* best-effort; still emit */
|
|
433
|
+
}
|
|
434
|
+
return true;
|
|
435
|
+
}
|
|
436
|
+
|
|
394
437
|
function runAugment(gitNexusDir, cwd, pattern) {
|
|
395
438
|
// Acquire the per-repo slot BEFORE the DB-owner probe (#2163): the probe
|
|
396
439
|
// itself spawns lsof/ps, so it must be bounded by the same ≤3-per-repo cap
|
|
@@ -410,12 +453,16 @@ function runAugment(gitNexusDir, cwd, pattern) {
|
|
|
410
453
|
}
|
|
411
454
|
try {
|
|
412
455
|
if (hasGitNexusServerOwner(gitNexusDir)) {
|
|
413
|
-
//
|
|
414
|
-
//
|
|
456
|
+
// #2396: the MCP server holds the DB write lock, so a competing CLI
|
|
457
|
+
// `augment` would only contend on it (LadybugDB is single-writer). The
|
|
458
|
+
// session has the GitNexus MCP tools live — route the augmentation to the
|
|
459
|
+
// agent via additionalContext instead of dropping it. Mirror the skip
|
|
460
|
+
// reason to stderr only under GITNEXUS_DEBUG (strict-runner contract,
|
|
461
|
+
// #1913); the hint itself rides the sanctioned additionalContext channel.
|
|
415
462
|
if (isDebugEnabled()) {
|
|
416
463
|
process.stderr.write('[GitNexus] augment skipped: MCP server owns DB\n');
|
|
417
464
|
}
|
|
418
|
-
return '';
|
|
465
|
+
return shouldEmitMcpHint(gitNexusDir) ? buildMcpQueryHint(pattern) : '';
|
|
419
466
|
}
|
|
420
467
|
const cliPath = resolveCliPath();
|
|
421
468
|
const child = runGitNexusCli(cliPath, ['augment', '--', pattern], cwd, 7000);
|
|
@@ -349,6 +349,49 @@ function runGitNexusCli(cliPath, args, cwd, timeout) {
|
|
|
349
349
|
});
|
|
350
350
|
}
|
|
351
351
|
|
|
352
|
+
/**
|
|
353
|
+
* Fallback augmentation for the #2396 path: when a GitNexus process holds the
|
|
354
|
+
* lbug DB write lock the CLI `augment` can't run, so point the agent at the MCP
|
|
355
|
+
* `query` tool instead. Phrased conditionally ("if the MCP tools are live") so it
|
|
356
|
+
* stays truthful on every owner path — a confirmed MCP owner, a `serve` owner, or
|
|
357
|
+
* a fail-closed probe where no server is actually confirmed. `pattern` is embedded
|
|
358
|
+
* verbatim; the caller (sendHookResponse) JSON-escapes it structurally.
|
|
359
|
+
*/
|
|
360
|
+
function buildMcpQueryHint(pattern) {
|
|
361
|
+
return (
|
|
362
|
+
`[GitNexus] Local augment is unavailable (the graph DB is held by another ` +
|
|
363
|
+
`GitNexus process). If the GitNexus MCP tools are live in this session, call ` +
|
|
364
|
+
`the GitNexus \`query\` MCP tool (e.g. mcp__gitnexus__query) with ` +
|
|
365
|
+
`search_query "${pattern}".`
|
|
366
|
+
);
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
/**
|
|
370
|
+
* #2396 throttle: emit the MCP-query hint at most once per repo per window, so an
|
|
371
|
+
* owner-locked session isn't nudged on every search. Window (ms) via
|
|
372
|
+
* GITNEXUS_MCP_HINT_THROTTLE_MS (default 10min; 0/invalid disables). Best-effort —
|
|
373
|
+
* any fs error falls back to emitting.
|
|
374
|
+
* ponytail: per-repo mtime marker, shared across concurrent sessions on the same
|
|
375
|
+
* repo; add per-session dedup only if that sharing becomes a problem.
|
|
376
|
+
*/
|
|
377
|
+
function shouldEmitMcpHint(gitNexusDir) {
|
|
378
|
+
const raw = process.env.GITNEXUS_MCP_HINT_THROTTLE_MS;
|
|
379
|
+
const windowMs = raw === undefined || raw === '' ? 600000 : Number(raw);
|
|
380
|
+
if (!Number.isFinite(windowMs) || windowMs <= 0) return true;
|
|
381
|
+
const marker = path.join(gitNexusDir, '.mcp-hint-shown');
|
|
382
|
+
try {
|
|
383
|
+
if (Date.now() - fs.statSync(marker).mtimeMs < windowMs) return false;
|
|
384
|
+
} catch {
|
|
385
|
+
/* marker missing/unreadable → emit */
|
|
386
|
+
}
|
|
387
|
+
try {
|
|
388
|
+
fs.writeFileSync(marker, '');
|
|
389
|
+
} catch {
|
|
390
|
+
/* best-effort; still emit */
|
|
391
|
+
}
|
|
392
|
+
return true;
|
|
393
|
+
}
|
|
394
|
+
|
|
352
395
|
/**
|
|
353
396
|
* PreToolUse handler — augment searches with graph context.
|
|
354
397
|
*/
|
|
@@ -385,18 +428,25 @@ function handlePreToolUse(input) {
|
|
|
385
428
|
let result = '';
|
|
386
429
|
try {
|
|
387
430
|
if (hasGitNexusServerOwner(gitNexusDir)) {
|
|
388
|
-
//
|
|
389
|
-
//
|
|
390
|
-
//
|
|
431
|
+
// #2396: the MCP server holds the DB write lock, so a competing CLI
|
|
432
|
+
// `augment` would only contend on it (LadybugDB is single-writer). But the
|
|
433
|
+
// session that triggered this hook has the GitNexus MCP tools live — route
|
|
434
|
+
// the augmentation to the agent via additionalContext instead of silently
|
|
435
|
+
// doing nothing. Mirror the skip reason to stderr only under GITNEXUS_DEBUG
|
|
436
|
+
// (strict-runner contract, #1913); the hint itself rides the sanctioned
|
|
437
|
+
// additionalContext stdout channel the successful augment already uses.
|
|
391
438
|
if (isDebugEnabled()) {
|
|
392
439
|
process.stderr.write('[GitNexus] augment skipped: MCP server owns DB\n');
|
|
393
440
|
}
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
441
|
+
if (shouldEmitMcpHint(gitNexusDir)) {
|
|
442
|
+
result = buildMcpQueryHint(pattern);
|
|
443
|
+
}
|
|
444
|
+
} else {
|
|
445
|
+
const cliPath = resolveCliPath();
|
|
446
|
+
const child = runGitNexusCli(cliPath, ['augment', '--', pattern], cwd, 7000);
|
|
447
|
+
if (!child.error && child.status === 0) {
|
|
448
|
+
result = extractAugmentContext(child.stderr || '');
|
|
449
|
+
}
|
|
400
450
|
}
|
|
401
451
|
} catch {
|
|
402
452
|
/* graceful failure */
|
package/package.json
CHANGED