Skip to content

prompt-hook opens CodeGraph without sync, so the MEDIUM (segment-vocab) gate tier stays permanently empty on any repo indexed before v1.2.0 #1142

Description

@inth3shadows

Summary

The prompt-hook's MEDIUM gate tier (#1136) depends on name_segment_vocab, which — per this repo's
own migration comment — starts empty on any database migrated from schema <7 and is only backfilled
by sync(). The prompt-hook itself never calls sync(), so on any repo indexed before upgrading to
a version carrying #1136, the MEDIUM tier returns zero matches indefinitely, until some unrelated
trigger (a manual codegraph sync, a git-hook sync, an MCP daemon sync) happens to run first.

Root cause

// src/bin/codegraph.ts:1117 (prompt-hook action)
const cg = await CodeGraph.open(plan.exploreRoot);
// ... later:
const related = cg.getSegmentMatches(proseWords);   // line 1153
// src/index.ts:295, 318-320 (CodeGraph.open)
static async open(projectRoot: string, options: OpenOptions = {}): Promise<CodeGraph> {
  // ...
  if (options.sync) {
    await instance.sync();
  }
  return instance;
}

The hook calls CodeGraph.open(plan.exploreRoot) with no options object, so options.sync is
undefined and sync() never runs on this path.

// src/db/migrations.ts:109-110 (v7 migration comment)
// ... The table starts EMPTY on migrated databases; `sync`
// detects that over a populated graph and backfills batched+yielding

The only backfill (rebuildNameSegmentVocab(), src/index.ts:1017) has exactly one call site
(src/index.ts:634, gated on vocabWasEmpty, src/index.ts:560), inside sync() — not in open()
— and getSegmentMatches() (src/index.ts:927 onward) has no lazy-backfill logic of its own; it
purely queries the table and re-verifies hits against nodes. Confirmed the empty-result path:

// src/bin/codegraph.ts:1153-1154
const related = cg.getSegmentMatches(proseWords);
if (related.length === 0) { gate('noop-unverified'); return; }

Impact

Every repo indexed before upgrading to a version with #1136 gets zero MEDIUM-tier value from the
prompt-hook — silently, with no error, logged only as noop-unverified in the gate telemetry — until
something else happens to trigger a sync first. I'd expect this to be common immediately after an
upgrade for users without a git-hook auto-sync configured (no postinstall/preinstall script exists,
and the installer's "auto-sync" machinery is about post-init file-watching, not upgrade-triggered
sync of already-indexed projects — checked both), though I don't have telemetry to confirm how often
that setup applies in practice.

Verification / scope

Environment

Found on main (tip e699ee9, v1.2.0).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions