docs(research): measure --slice line recall on an issue-derived Python corpus - #318
Draft
joyful-ii-V-I wants to merge 8 commits into
Draft
joyful-ii-V-I wants to merge 8 commits into
joyful-ii-V-I wants to merge 8 commits into
Conversation
…e-derived Python corpus The 2026-08-28 registration in docs/EVALS.md has been run twice, both times on cpp corpora mined from git history, scoring ADDED lines at the POST-fix tree. This registers the py-family, issue-derived, PRE-fix-tree reading of the same shape, and three things the original registration left open (which tree, what is gold for a pure insertion, what "surfaces" means when rows are unordered), plus the rank, reachability, cost and granularity-vs-presentation questions the ARISE paper (arXiv:2605.03117) actually raises. No number produced by the harness exists at this commit; that is the point of committing the protocol first. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…ix corpus Harness (bench/slice/): locbench_gold.py builds pre-image line-level gold from a LocBench-shaped dataset and local checkouts without invoking ripwire, so the gold cannot move when the binary does; run_slice_linerecall.py measures set recall, rank against a random-order control, the reachability cascade, cost in bytes and wall time, and a byte-budgeted file/symbol/line granularity comparison; inspect_slice_misses.py classifies every miss with Python's own tokenizer; probe_wholerepo_selector.py prices the one-file-tree deviation. 560 dataset rows, 182 carried, 173 scored, 498 (instance, variable) pairs. The run is deterministic: two end-to-end runs compared identical row for row. Three findings worth a reader's time. Seven in ten of the corpus's gold lines live in fixes that span functions, which an intra-procedural primitive cannot address at all — the ceiling, stated apart from the accuracy. Under a tokenizer-decided relevance oracle the per-variable line recall is 0.995 and the three residual misses are all a keyword-argument name colliding with a local. Unioned over a function's whole inventory the flow rows reach no line the flat rows do not, because a flow row at depth >= 1 is by construction a line in some other variable's own slice. docs/EVALS.md gets a cross-reference, not a number: this corpus scores pre-image lines at the base commit where the four cpp corpora score added lines at the post-commit tree, so the two are not comparable and are never averaged. docs/README.md indexes the new directory. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…mains --quality-delta named two clone pairs the new py-round harnesses created against the existing cpp one: my git() against its sh(), my text_of() against its line_text(). Both now live in bench/slice/_common.py, together with the strict NAME-token oracle the runner and the inspector both use, and run_slicerecall.py imports them rather than keeping its copies. The extraction is textual - the bodies are unchanged - and the proof is that the gold file and every measured row still compare identical after it. The two oversized new mains lose their per-row bodies to measure_instance() and carry_row(), which also makes every early exit a counted skip in one place. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…easurement loop measure_instance was 126 lines at complexity 49 with nine parameters. The two scoring blocks it ends with are independent of everything above them, so they become rank_scores() and budget_scores(), and the four accumulators that outlive a row travel as one sink. Textual extraction again: the measured rows and the summary compare identical to the run before it. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
Important Draft PR not reviewedDraft PRs are not automatically reviewed by default.
To automatically review draft PRs, update your CodeRabbit configuration: reviews:
auto_review:
drafts: trueComment |
Eight research lanes each added their own wording for the same `docs/README.md` table line, which is eight conflicts on one line the moment two of them land. This is the shared text, byte-identical everywhere, so the same addition on two branches merges clean. The entry count above the table is corrected with it: the table has held twenty rows for some time while the sentence still said sixteen. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…lti-function ceiling --slice is intra-procedural by declaration, and §R3 of slice-line-recall.md already measured that 70.8% of the LocBench corpus's gold lines (6,809/9,615) sit in fixes touching more than one function -- out of reach by construction. Before extending --slice across call boundaries, measure whether the call graph the tool already builds would actually recover them: for each gold line outside the seed function, --at names its true enclosing symbol and --path reports the directed hop count from the seed, deduped per distinct symbol and cached per row. This commit adds the protocol and the pre-registered decision bands (extend_2 = (hop1+hop2)/6809; >=50% builds it, <20% kills it) before any number exists -- §10.4/10.5/10.6 are headings only, same discipline the 2026-09-20 round's own pre-registration commit (3d994cd) used. A follow-up commit fills in the results once bench/slice/run_cross_fn_reach.py finishes. archive_tree() moves into _common.py (probe_wholerepo_selector.py's own git-archive materialization, now shared with the new script) rather than growing a second copy. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…hin 2 hops -- kill it bench/slice/run_cross_fn_reach.py against the 122 measurable multi-function rows (2,913 of the 6,809-gold-line ceiling; 80 rows lack a local checkout, 2 have no base_commit, 4 refused the full-path seed selector): extend_2 = (hop1+hop2)/6809 = 6.14%, well under the 20% kill band fixed in 2173712 before this ran. hop1=4.3%, hop2=1.9%, hop3plus=0.9%, unreachable=22.9%, no_enclosing_symbol=4.5%, hop0 (already reachable today)=8.4%. At the instance level, extending reach to depth 3 still leaves 95% of measured rows with at least one gold line out of reach. The one open thread: 83.8% of unreachable gold lines sit behind a symbol that has SOME graph edge, just not on a directed path from the seed -- consistent with sibling functions a patch touches together via a shared caller, which --path cannot see and --connect might. Recorded in §10.6 as future work this round does not answer; the 6.14% verdict is scoped to directed extension only. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…lds either way extend_2 = 6.14% was reported only against the full 6,809-line ceiling, of which 57.2% was never measured (no checkout/commit/seed refusal). Scoring the unmeasured share as non-extendable is the conservative choice, but a reader can reasonably ask for the figure over the 2,913-line measured subset alone: (hop1+hop2)/2913 = 418/2913 = 14.35%, verified independently from run_cross_fn_reach.py's own results.json rather than assumed. Both stay under the pre-registered 20% kill band, so the verdict does not depend on which denominator is used. Also: names --connect=SEED,TARGET (or an equivalent undirected/bidirectional reach) over the 83.8% of unreachable gold lines that have graph edges but no directed path from the seed as the specific follow-up measurement that would need to change before this verdict does, rather than leaving that as a vague caveat; and states the verdict's scope explicitly (LocBench Python multi-function fixes, edit_functions[0]-seeded, directed reach only) so it is not read as a general claim about slicing. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This runs ripwire's
--sliceprimitive against the question the paper it came from actually asks.--sliceis our bounded first rung of the statement-level def-use primitive in ARISE (arXiv:2605.03117), which measured such a primitive at +17 pp Function Recall@1 and argued the binding constraint was the graph's granularity floor rather than its ranking. Itsdocs/LINEAGE.mdrow is at L87.docs/EVALS.mdhas carried the registered contract and, since August, results on four C/C++ corpora; this round asks the harder question on Python, on issue-derived fix patches, with gold taken at the pre-fix tree — the setting an agent is actually in. Full write-up:docs/research/slice-line-recall.md.The protocol is committed before the numbers exist (results section deliberately empty in the first commit), and the three things the original registration left open — which tree, what counts as gold for a pure insertion, what "surfaces" means when the rows are unordered — are closed as dated amendments rather than decided afterwards. 560 dataset rows, 173 scored, 498 (instance, variable) pairs, deterministic, re-run identical. No
src/changes. (Base note: measured againstmainat755f9026, before 0.6.2; the diff still merges cleanly onto today'smain,15a20855, tag 0.6.2.)What it says, including the parts that do not flatter us.
--slice-flow=bothreaches no line the flat rows do not — a flow row at depth ≥1 is by construction a line in some other variable's own slice.This is a first pass with a lot further to push, and the write-up states plainly where we are weakest against the original: name-based occurrences instead of true def-use edges, source lines instead of AST statement nodes, no alias analysis, no lexical scope separation in Python, no inter-procedural tier at all. We would like correction on, first, whether the paper's own gain came from coverage or from precision — our construct loses almost nothing in coverage and pays heavily in precision, and the answer decides whether name-based def-use is worth extending or worth replacing — plus four more questions in the doc's closing section.
Our working premise across this line of investigations: algorithmic, deterministic checks applied while an AI writes are the practical way to keep code sound at the speed AI now writes it — no label, no vendor claim, a check that either fires or it doesn't.
🤖 Generated with Claude Code