fix(explore): guarantee an agent-named symbol renders, wherever it sits (CG-38)
`codegraph_explore` never returned `queueMessage` (L1087) or `flushQueuedMessages` (L1102) from a 1,414-line file, on a symbol bag or a prose question, even with that file at rank #1 holding 67% of the envelope — the agent got a same-stem `QueuedMessage` interface at L70 and had to Read the file for the functions it had named. Pre-existing at every build including pre-epic (controlled bisect, index held fixed). Two independent causes: 1. `buildFlowFromNamedSymbols` returns the Flow prose AND the set of node ids the agent named — and the latter is the whole guarantee, since it injects a named def into its file's cluster ranges at importance 9. Its bail-outs returned EMPTY, zeroing the identity whenever there was nothing to PRINT. Two sibling closures that never call each other produce no chain, no synth hop and no boundary, so both defs lost importance 9 and the file rendered from its head. `identityOnly()` now separates the two, gated on shape-precise tokens so a prose word that exact-matches a callable cannot promote itself. 2. The ceiling trim filled in SOURCE order, so an over-ceiling render always dropped the END of a large file first. The shrink HAD kept both symbols (1022-1121); the trim cut back to 839. `windowToCeiling` now takes the spine call site plus every importance>=9 member as focus lines, tries the full ceiling first, and splits the held-back reserve evenly with carry-forward — greedy-in-source-order reproduced the bug one level down. The shrink's loose size estimate is left alone deliberately, and the comment now says why: making it exact was built and measured WORSE (it stops at the last member that fits whole and the released bytes carry forward to lower-ranked files, costing payroll-go's `s.store.Upsert`). `bound()` clamps to the ceiling anyway, so the slack costs no bytes; it just must not pick the survivors, which is what the trim now handles. The measurement gap this closes: every existing probe is aggregate — envelope share, per-file spend, source totals, file counts — and all are green on a response that returns 25K from the right file and omits the named function. `probe-named-symbol.mjs` checks the definition LINE against the response's rendered lines, per symbol. Suite envelope byte-identical to main on all six repos; probe-allocation 4/4, no starvation flags; 180 files / 2,997 tests green. Fixture: 7/7 fail on main, 7/7 pass here, deterministic over 4 runs per arm.
This commit is contained in:
@@ -52,13 +52,13 @@ change at all**.
|
||||
Deterministic across the 6-repo suite: no repo truncates, none loses a file,
|
||||
okhttp gains one, every repo lands at or under the 25,000 hard ceiling.
|
||||
|
||||
## Open
|
||||
## Follow-up — CG-38 (closed)
|
||||
|
||||
**CG-38** — agent-named symbols in the tail of a large file never render. On the
|
||||
**Agent-named symbols in the tail of a large file never rendered.** On the
|
||||
motivating repo, `queueMessage` (line 1087) and `flushQueuedMessages` (1102) in a
|
||||
1,414-line file are absent from the response on both prose and symbol-bag
|
||||
queries, even when that file wins rank #1 with 67% of the envelope. The response
|
||||
returns the `QueuedMessage` *interface* at line 70 — a fuzzy near-match on the
|
||||
1,414-line file were absent from the response on both prose and symbol-bag
|
||||
queries, even when that file won rank #1 with 67% of the envelope. The response
|
||||
returned the `QueuedMessage` *interface* at line 70 — a fuzzy near-match on the
|
||||
query token — instead of the function.
|
||||
|
||||
**Pre-existing, not caused by this epic.** A controlled bisect (index held fixed,
|
||||
@@ -67,15 +67,20 @@ lines here and CG-36 rendering 463; the symbols render at neither. The epic
|
||||
strictly improves the case. An earlier claim that the epic regressed it was
|
||||
wrong — it compared runs across two different indexes.
|
||||
|
||||
Sharpest lead: an earlier index of the same repo with the `.d.ts` **not** flagged
|
||||
generated rendered 581 lines including both symbols on the pre-epic engine, where
|
||||
the current flagged index renders 12. A penalty on one file should not shrink an
|
||||
unrelated top-ranked file's render; `rankPenalty` scales `fileGraphScore`, which
|
||||
moves the relevance gate and reshuffles the admitted set.
|
||||
Two independent causes, both longstanding: `buildFlowFromNamedSymbols` discarded
|
||||
the named-symbol IDENTITY along with the narrative whenever the named symbols did
|
||||
not form a call chain, so the importance-9 injection never ran; and the ceiling
|
||||
trim cut in SOURCE order, so a named def at the end of a large file was always the
|
||||
first thing dropped. Full account, plus the ranker-penalty lead (real, and
|
||||
orthogonal — the defs are absent at both `generated` flag states on the old build
|
||||
and present at both on the new one): `explore-tail-render-cg38.md`.
|
||||
|
||||
This epic's probes measure envelope share, starvation, source totals and file
|
||||
counts. **None measures "did the agent-named symbol render"** — which is why this
|
||||
survived the whole epic. CG-38 requires the fixture that closes that gap.
|
||||
counts. **None measured "did the agent-named symbol render"** — which is why this
|
||||
survived the whole epic. `scripts/agent-eval/probe-named-symbol.mjs`,
|
||||
`__tests__/fixtures/tail-render-ts` and
|
||||
`__tests__/explore-named-symbol-render.test.ts` close that gap: per-symbol and
|
||||
binary, checking the definition LINE against the response's rendered lines.
|
||||
|
||||
CG-36's own measurement is worth carrying forward, because the issue named the wrong
|
||||
fix point: both real cases (`query.py`, `RealInterceptorChain.kt`) lost on
|
||||
|
||||
Reference in New Issue
Block a user