fix(prompt-hook): close the segment-vocab integrity gaps (#1141, #1142, #1144, #1145, #1146) (#1150)
Five hardening fixes to the #1136 MEDIUM (graph-derived) tier: - #1141: updateNode() now writes the segment vocabulary like insertNode() does — framework post-extract renames (NestJS route prefixing) left the new name permanently unsearchable (the old rows orphaned, the backfill gated on an EMPTY vocab, so even a full re-index re-created the drift). - #1142: new CodeGraph.healSegmentVocabIfEmpty() — the hook opens the graph without sync, so a database migrated from pre-vocab schema kept the MEDIUM tier dormant until some unrelated sync ran. The hook heals on first use (one SELECT when populated; lock-aware, defers to a running sync) and records noop-vocab-empty when it can't. - #1144: a name whose only nodes are file/import kind is skipped instead of falling back to surfacing an import statement as a matched symbol; import specifiers no longer enter the vocab at all (shared isSegmentableKind gate across insertNode/updateNode/rebuild page query) since they can never be surfaced and only inflate rarity statistics. - #1145: plural variant folding is keyed on English plural spelling — bare-s plurals no longer mint a bogus -es sibling (services→servic), unambiguous sibilant-es plurals no longer mint a bogus -s sibling (classes→classe), trailing -ss singulars no longer strip (class→clas); genuinely ambiguous endings (caches/databases) still emit both keys. - #1146: getSegmentCoOccurrence folds variants to their original word inside the SQL (CASE mapping + COUNT(DISTINCT word)) so a plural pair of ONE word can't tie with a genuine two-word match and crowd it past the pre-fold ORDER BY/LIMIT; the JS re-check stays as the honesty layer. Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5
parent
be55b93d02
commit
35611b92bb
@@ -1156,6 +1156,16 @@ program
|
||||
// scored, each hit re-verified to exist (see getSegmentMatches). The
|
||||
// payload names the symbols but does NOT run explore — the agent owns
|
||||
// the query where the hook's confidence is only "these are related".
|
||||
//
|
||||
// A database indexed before the vocab table existed starts with it
|
||||
// EMPTY, and only sync() backfills it — which this hook never runs
|
||||
// (#1142). Heal it here: on a populated vocab this is one SELECT;
|
||||
// the actual backfill is a one-time batched pass whose cost the MCP
|
||||
// server's own catch-up sync usually pays first (it runs at every
|
||||
// session start). A distinct noop outcome keeps a dormant vocab
|
||||
// from polluting the noop-unverified recall signal.
|
||||
const vocabReady = await cg.healSegmentVocabIfEmpty().catch(() => false);
|
||||
if (!vocabReady) { gate('noop-vocab-empty'); return; }
|
||||
const related = cg.getSegmentMatches(proseWords);
|
||||
if (related.length === 0) { gate('noop-unverified'); return; }
|
||||
const lines = related
|
||||
|
||||
Reference in New Issue
Block a user