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
@@ -129,12 +129,32 @@ export function extractProseCandidates(prompt: string): string[] {
|
||||
/**
|
||||
* Lookup variants for a prose word: the word itself plus light plural folding
|
||||
* ("services" → service, "dependencies" → dependencie/dependency is NOT
|
||||
* attempted — only trailing s/es strip), so common plurals still hit their
|
||||
* attempted — only a trailing s/es strip), so common plurals still hit their
|
||||
* singular segment. Returned variants map back to the same original word.
|
||||
*
|
||||
* The strips are keyed on English plural spelling (#1145), in three classes:
|
||||
* - UNAMBIGUOUS `-es` (after x/sh/ss/zz: boxes, hashes, classes, quizzes) —
|
||||
* strip 2 only. Stripping 1 minted a bogus sibling ("classes" → classe).
|
||||
* - AMBIGUOUS endings (`-ches`/`-ses`/`-zes`/`-oes`): spelling alone can't
|
||||
* split patches(+es) from caches(+s), lenses from databases, heroes from
|
||||
* shoes — emit BOTH candidate keys and let the vocab lookup decide; a miss
|
||||
* is an ignored key, a wrong exclusive guess would LOSE the real match.
|
||||
* - Everything else ending in `-s` — a bare `-s` plural (services, machines,
|
||||
* cookies): strip 1 only. Stripping 2 minted "services" → servic.
|
||||
* A trailing `-ss` is a singular (class, process), not a plural: no strip —
|
||||
* that used to mint "class" → clas.
|
||||
*/
|
||||
export function segmentLookupVariants(word: string): string[] {
|
||||
const variants = [word];
|
||||
if (word.endsWith('es') && word.length >= MIN_PROSE_CHARS + 2) variants.push(word.slice(0, -2));
|
||||
if (word.endsWith('s') && word.length >= MIN_PROSE_CHARS + 1) variants.push(word.slice(0, -1));
|
||||
const canStrip2 = word.length >= MIN_PROSE_CHARS + 2;
|
||||
const canStrip1 = word.length >= MIN_PROSE_CHARS + 1;
|
||||
if (/(?:x|sh|ss|zz)es$/.test(word)) {
|
||||
if (canStrip2) variants.push(word.slice(0, -2));
|
||||
} else if (/(?:ch|s|z|o)es$/.test(word)) {
|
||||
if (canStrip2) variants.push(word.slice(0, -2));
|
||||
if (canStrip1) variants.push(word.slice(0, -1));
|
||||
} else if (word.endsWith('s') && !word.endsWith('ss')) {
|
||||
if (canStrip1) variants.push(word.slice(0, -1));
|
||||
}
|
||||
return variants;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user