Skip to content

feat(testgen): the ranker that orders test-writing work now has a caller - #161

Merged
stranske merged 1 commit into
mainfrom
claude/testgen-lane-ranks-by-escaped-defects
Aug 30, 2026
Merged

feat(testgen): the ranker that orders test-writing work now has a caller#161
stranske merged 1 commit into
mainfrom
claude/testgen-lane-ranks-by-escaped-defects

Conversation

@stranske

Copy link
Copy Markdown
Owner

The ranker had no caller

escaped_defect_priority merged in #153 and nothing invoked it. This repository's dominant defect class is built-and-forgotten features, so that is the documented failure mode rather than an oversight — and it means this PR is wiring, not building. The ranker existed, the lane existed, the edge between them did not.

Dedup finding, before writing anything: grepped for rank/priority/churn/escaped; searched the improvement log for testgen (44 hits) and escaped (4); checked open PRs. Both halves present, edge absent. Recorded on improvement-log item 2, where testgen_lane's build is recorded.

What it does

testgen_lane --rank-sources N picks the lane's --source values by measured priority — escaped defects, then churn, then uncovered mass — and puts each file's reason in the prompt:

Why these files, in this order:
1. `src/hot.py` — escaped-defect weight 1.0, churn 2, uncovered 0, hollow rate 0.0 (fix commit touched this file)
2. `src/cold.py` — escaped-defect weight 0.0, churn 1, uncovered 0, hollow rate 0.0 (no per-file evidence recorded)

followed by an explicit statement that the order is a priority, not a mandate, with an instruction to say so and take the next file rather than write a smoke test to clear one that cannot be tested meaningfully.

The substance is rank_status, and it is about the latch

Both git-backed tiers go through _git, which returns "" on a non-zero exit. A directory that is not a git repository therefore produces exactly the empty ranking a pristine one does — so a caller choosing test-writing work would read "no file needs tests" off a failed subprocess. That is this workspace's most repeated defect in its test-writing costume: one value meaning both measured zero and could not measure, where only the first is good news.

rev-parse --git-dir is asked before ranking rather than inferred from an empty result, and ok / no_signal / unavailable stay three findings. The no_signal reason states what was not read, so a drained result and an unread one never render alike.

Every fallback fails toward motion. Switch off, ranker unimportable, repo unreadable, nothing scored — all fall back to sources named on the command line and say which, in a note that is always printed (a lane that quietly fell back would be indistinguishable from one that ranked). Only with nothing to fall back on does the CLI exit 2, and then the note names what was missing.

Two defects in my own draft, both found by testing rather than by reading it

coverage run --source=src/mod.py measures nothing and exits 0. Verified empirically, and already documented at testgen_gate.py:44-47 as one of two directions this goes wrong. So ranked file paths become importable names, dropping the leading component only when it is a source root — detected by a missing __init__.py, because src is a root here and a package elsewhere. A wrong guess is not silent: testgen_gate.unmeasured_sources already fails the gate on a source no measured file belongs to.

The rationale was unfalsifiable. The prompt read escaped/churn/uncovered with a default of 0 while as_dict emits tier1_escaped_defects and friends. Every key missed, so every file's stated reason was "escaped 0, churn 0, uncovered 0" — a correct ordering under a reason no input could ever contradict. Absent keys now render ?. A rendered ? is a visible defect; a rendered 0 is a lie that reads as good news.

Why no new ledger row

The heartbeat is filed under testgen-lane. The ranker is a rail the lane consults — no model call, no dispatch, no work a caller could be offered instead of the lane — so it is one capability with two code paths that can prove it ran. A second lifecycle record for an implementation detail is how this project loses track of features.

Verification

python3 src/verify.py from the checkout: 529 passed, 0 failed, 0/26 max skipped, 88/88 selftests, 5/5 gates. Floor 515 → 529 measured on this merge result, rationale appended to the note rather than replacing it.

+14 pytest tests — eleven on the fallbacks, three on the ranking, because the fallbacks are where an empty answer gets mistaken for good news. Three deliberate breaks, each reverted:

break result
git probe removed 2 fail
.get(key, 0) rationale restored 1 fail
source-root rule hardcoded 1 fail

One note for the reviewer: the admission gate goes red on the owner's machine right now, and it is not this change. The shared machine-local ledger acquired findability-exemption declarations for 12 capabilities absent from KNOWN_DECLARATIONS while I worked. Confirmed pre-existing by running the same test on clean origin/main in a scratch worktree, and confirmed absent under fresh ORCH_STATE_DIR + ORCH_LOCAL_RUNTIME (10 passed, 3 skipped) — which is what CI runs. A concurrent session's rows.

🤖 Generated with Claude Code

`escaped_defect_priority` merged in #153 and nothing invoked it. In this repository that is
the documented failure mode rather than an oversight, so this is wiring, not building: the
ranker existed, the lane existed, the edge between them did not.

`testgen_lane --rank-sources N` chooses the lane's `--source` values by measured priority —
escaped defects, then churn, then uncovered mass — and puts the reason for each file in the
prompt. The order is stated as a priority, not a mandate, with an instruction to say so and
take the next file rather than write a smoke test to clear one that cannot be tested.

The substance is `rank_status`, and it is about the latch rather than the ranking. Both
git-backed tiers go through a helper that returns "" on a non-zero exit, so a directory that
is not a git repository produces exactly the empty ranking a pristine one does — a caller
picking work would read "no file needs tests" off a failed subprocess. The probe is asked
before ranking rather than inferred from an empty result, and ok / no_signal / unavailable
stay three findings, not one.

Every fallback fails toward motion. Switch off, ranker unimportable, repo unreadable, nothing
scored: all fall back to hand-named sources and say which in a note that is always printed.
Only with nothing to fall back on does the CLI exit 2, and then the note names what was
missing.

Two defects in my own draft, both found by testing rather than by reading it:

- `coverage run --source=src/mod.py` measures nothing and exits 0 — verified, and already
  documented at testgen_gate.py:44-47. Ranked file paths become importable names, dropping
  the leading component only when it is a source root, detected by a missing `__init__.py`
  because `src` is a root here and a package elsewhere.
- The rationale was unfalsifiable: it read `escaped`/`churn`/`uncovered` with a default of 0
  while `as_dict` emits `tier1_escaped_defects` and friends, so every file's stated reason
  was "escaped 0, churn 0, uncovered 0" under a correct ordering. Absent keys now render `?`.
  A rendered `?` is a visible defect; a rendered 0 is a lie that reads as good news.

The heartbeat is filed under `testgen-lane` rather than as a new capability row. The ranker
is a rail the lane consults — no model call, no dispatch, no work a caller could be offered
instead of the lane — and a second lifecycle record for an implementation detail is how this
project loses track of features.

+14 pytest tests, eleven of them on the fallbacks. Floor 515 -> 529 measured on this merge
result, rationale appended to the note. Three deliberate breaks, each reverted: removing the
git probe (2 fail), restoring the `.get(key, 0)` rationale (1 fail), hardcoding the
source-root rule (1 fail).

verify.py from the checkout: 529 passed, 0 failed, 0/26 max skipped, 88/88 selftests, 5 gates.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Aug 30, 2026

Copy link
Copy Markdown

Warning

Review limit reached

Next included review available in 6 minutes.

View limit details

Limit details: You’ve used all 2 included reviews currently available. Your 55 included PR review attempts over the past 7 days set your current allowance at 2 reviews per hour.

Your organization has reached its usage spending cap. Adjust your spending cap in the billing tab.

Learn how review limits work.

Review configuration:

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 272b37f3-9b7d-47e5-bed9-3e1a1cbcd003

📥 Commits

Reviewing files that changed from the base of the PR and between 4ffd8b3 and e7a389f.

📒 Files selected for processing (4)
  • .verify-floor.json
  • src/escaped_defect_priority.py
  • src/testgen_lane.py
  • tests/test_testgen_lane_ranking.py

Comment @coderabbitai help to get the list of available commands.

@agents-workflows-bot

Copy link
Copy Markdown
Contributor

Workflow source needed

PR #161 needs either a linked GitHub issue or one valid non-issue Workflow Source before PR metadata automation can manage it safely.

Please do one of:

  • Add <!-- meta:issue:123 --> or a normal Closes #123 / Related to #123 line.
  • Check one Workflow Source option in the PR body.
  • Add a hidden marker such as <!-- workflow-source:local_request -->, <!-- workflow-source:manual_remote -->, <!-- workflow-source:review_followup -->, <!-- workflow-source:sync_campaign -->, or <!-- workflow-source:dependabot -->.
  • Add a workflow source label such as workflow:source-direct-pr, workflow:source-local-request, workflow:source-review-followup, workflow:source-sync, or workflow:no-automation.

Once a valid source is present, this warning will not be reposted.

@stranske-keepalive

Copy link
Copy Markdown

Automated Status Summary

Head SHA: d325972
Latest Runs: ⏳ pending — Gate
Required: core tests (3.12): ⏳ pending, core tests (3.13): ⏳ pending, docker smoke: ⏳ pending, gate: ⏳ pending

Workflow / Job Result Logs
(no jobs reported) ⏳ pending

Coverage Overview

  • Coverage history entries: 1

Coverage Trend

Metric Value
Current 34.14%
Baseline ⚠️ not configured (absent)
Delta n/a — nothing to compare against
Minimum 70.00%
Status ❌ Below minimum

No baseline was read (absent), so the delta above is not a measurement. Status reflects only the --minimum floor. Write config/coverage-baseline.json with a line or coverage percentage to enable the comparison; that file is deliberately not synced from Workflows, so each repo owns its own.

Top Coverage Hotspots (lowest coverage)

File Coverage Missing
src/capability_effectiveness.py 0.0% 154
src/capability_firing_monitor.py 0.0% 192
src/capability_matcher_proposals.py 0.0% 111
src/capability_opportunity.py 0.0% 143
src/capability_propensity.py 0.0% 2216
src/capability_task_proposals.py 0.0% 195
src/ccusage_reconcile.py 0.0% 286
src/codemod_lane.py 0.0% 351
src/evidence_acquisition.py 0.0% 103
src/exploration_collection.py 0.0% 331
src/feature_scan.py 0.0% 118
src/frontend_verify.py 0.0% 255
src/improvement_log.py 0.0% 248
src/issue_readiness.py 0.0% 507
src/keepalive_evidence.py 0.0% 378

Low Coverage Files (<50.0%)

File Coverage Missing
src/capability_effectiveness.py 0.0% 154
src/capability_firing_monitor.py 0.0% 192
src/capability_matcher_proposals.py 0.0% 111
src/capability_opportunity.py 0.0% 143
src/capability_propensity.py 0.0% 2216
src/capability_task_proposals.py 0.0% 195
src/ccusage_reconcile.py 0.0% 286
src/codemod_lane.py 0.0% 351
src/evidence_acquisition.py 0.0% 103
src/exploration_collection.py 0.0% 331
src/feature_scan.py 0.0% 118
src/frontend_verify.py 0.0% 255
src/improvement_log.py 0.0% 248
src/issue_readiness.py 0.0% 507
src/keepalive_evidence.py 0.0% 378

Updated automatically; will refresh on subsequent CI/Docker completions.


Keepalive checklist

Scope

No scope information available

Tasks

  • No tasks defined

Acceptance criteria

  • No acceptance criteria defined

@github-actions

Copy link
Copy Markdown
Contributor

Workflow state fingerprint for Agents Gate Followups. Do not edit.

@stranske
stranske merged commit 540965a into main Aug 30, 2026
38 checks passed
@stranske
stranske deleted the claude/testgen-lane-ranks-by-escaped-defects branch August 30, 2026 02:31
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.

1 participant