Skip to content

lsp: count definition rebinds separately from confirmations - #613

Merged
zzet merged 4 commits into
zzet:mainfrom
pbednarcik:feat/lsp-rebound-ledger
Aug 19, 2026
Merged

lsp: count definition rebinds separately from confirmations#613
zzet merged 4 commits into
zzet:mainfrom
pbednarcik:feat/lsp-rebound-ledger

Conversation

@pbednarcik

Copy link
Copy Markdown
Contributor

Problem

The definition fallback has two outcomes and one counter. When the server's answer agrees with the heuristic target, the edge is confirmed; when it lands on a different same-name declaration, the edge is rewritten — target replaced, rebound_from tagged — and then counted into edges_confirmed all the same. A pass that "confirmed" an edge by replacing its target didn't confirm anything: it corrected the graph. The result surface, index_health, and the logs can't tell the two apart — while the same logs carry a refuted field that nothing currently increments.

This is №5 from the #605 discussion — the measuring-instrument piece. The dispatch-predicate work that follows will concentrate LSP attention exactly where the AST's answer is least trustworthy, so corrections have to be visible before it lands or its accuracy effect is unmeasurable.

Change

  • EnrichResult.EdgesRebound / EnrichmentStatus.EdgesRebound (edges_rebound): the rebind arm of the definition fallback increments this instead of EdgesConfirmed, so edges_confirmed only ever means "the heuristic target was right".
  • Surfaced beside the existing counters: the manager and indexer enrichment logs (next to refuted), the LSP degraded / deadline-cut logs, and index_health's landed sum + lsp_resolved_edges_by_language.
  • The zero-yield abandon guard counts a rebind-only pass as yield — a pass that only corrected edges did answer.
  • EdgesRefuted stays as-is; wiring RefuteEdge / refute_unconfirmed is a separate conversation.

What it shows on a real graph

My workspace's settled store carries 4 rebound edges today, all textbook same-name corrections — e.g. in this repo's own eval tree, the call in eval/run_eval.py::process_instance originally bound to eval/prompts.py::render_instance_prompt was rebound to eval/agents/gortex_agent.py::GortexAgent.render_instance_prompt. Rare for now; the predicate work aims the fallback at precisely the sites where these live, and this counter is how we'll see what it changes.

Tests

Two pins drive the real passes through the package's instrumented fake server: a definition answer landing on a different same-name declaration counts as edges_rebound and must not inflate edges_confirmed; an agreeing answer still counts as confirmed. Full suite matches my Windows baseline.

The definition fallback's rebind arm rewrites an edge's target and tags
rebound_from, then counted the correction into edges_confirmed. Split it
into EnrichResult/EnrichmentStatus EdgesRebound and surface it beside the
existing counters (enrichment logs, index_health sums, zero-yield guard).
On a degraded pass the serial fallback loop can be the only source of
progress - every other usefulYield site is unreachable - so the
productivity checkpoint read a pass that settles thousands of edges
there as zero-yield and cancelled it.
@zzet
zzet merged commit ca7ad3e into zzet:main Aug 19, 2026
11 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants