Context
Source: Cloudflare/Astro, "How we triaged Astro's issue backlog with agents" (2026-08) + the withastro/triagebot-action reference implementation. Astro took a 5+ year backlog from 200+ open issues to ~30 — not by issue bankruptcy or auto-closing.
Their stated core philosophy is the part RAD should steal:
"When an agent fails to identify a correct solution, we interpret that failure as an indicator of an underlying architectural or documentation issue."
They enumerate three deficits an agent failure implicates, and fix the codebase rather than the prompt:
- Opaque abstractions — "If an agent cannot interpret the boundaries between components, human developers likely struggle with the code structure as well"
- Missing documentation — critical code lacking explanatory comments
- Insufficient testing — no coverage pinning the intended behavior
Their worked example: on an HMR bug the bot repeatedly modified the same if condition, fixing the target bug but regressing others because nothing covered the neighbouring behavior. They did not tune the prompt — they added a descriptive comment explaining the exact logic governing that statement, and the bot stopped attempting incorrect modifications in that area.
"Every time we chase down one of these failures and add the missing comment, test, or clearer boundary, the bot gets noticeably better at that part of the codebase, and so does the next human who works on it."
This directly contradicts a premise currently written into #63. #63 frames the mining question as:
do waves fail because the code is hard (fix nothing) or because the plan was ambiguous (fix planning prompts)?
Astro's evidence says blocked_code is not a "fix nothing" bucket. Recurrent agent failure localized to a region of code is a legibility signal about that region, and the highest-leverage patch is in the code — a comment, a test, a clearer boundary — which pays off twice, for the next agent and the next human.
RAD's feedback loop today has two proposal routes and neither can express this:
There is no route that points at product code.
Proposal
Add a third route to the /rad-insights suggestion stage: signal→code-legibility proposal, keyed by file rather than by outcome.
Localization key: intersect the failing wave's per-task status (from #63's tasks[{title,status}]) with that task's plan File: field. A file accumulating blocked_code, retry-heavy-but-eventually-successful waves, or repeat fail-tests across multiple features is the unit of recurrence — not the outcome type.
Rendered proposal names the file, the observed evidence (which features, which waves, how many attempts), and classifies the suggested remedy into Astro's three deficits:
| Observed signal |
Implicated deficit |
Proposal shape |
Repeat blocked_code on the same file across features |
opaque abstraction |
described boundary/decomposition note |
| Retry-heavy waves that eventually succeed on the same file |
missing documentation |
described comment explaining the governing constraint |
| Fix lands but a later wave regresses the same file |
insufficient testing |
described characterization test naming the uncovered behavior |
Suggestion-only prose, same rule as every other insights route.
Hard constraints
- Suggestion-only. Insights never edits product code, tests, or comments — identical rule to the conventions/lints/prompt-surface routes.
- Read-side only: new folds live in the
harness/events.js insights block; the events writer and gate fold gain no authority.
- The frozen 7-outcome vocabulary is untouched. This route consumes recorded granularity, it does not route on it.
- Recurrence uses the existing threshold mechanism (named constant /
RAD_*_THRESHOLD env), not new matching machinery.
- File attribution degrades explicitly: plans whose tasks carry no
File: field render an "unattributable" note, never a silent omission or a guess.
Files in scope
harness/events.js (new pure fold: per-file failure attribution), harness/test/events.test.js
.claude/commands/shared/rad-insights.md (new "Code-legibility proposals" section + the deficit mapping table)
docs/ (document the rationale — specifically that blocked_code is a legibility signal, not a dead end)
Suggested wave structure
- Wave 1 — Attribution fold: derive per-file failure counts from enriched
wave-attempt events joined to plan task File: paths. Validate: plan with no File: fields → explicit unattributable bucket; a task touching multiple files attributes to each without double-counting the wave; historical logs without tasks[] fold to zero and say so.
- Wave 2 — Proposal rendering: deficit mapping table + insights section. Validate: below-threshold files render nothing; a file crossing threshold on two distinct signals renders both deficits, not a merged guess; zero-event fresh clone renders the existing zeros path.
Acceptance criteria
Related
Context
Source: Cloudflare/Astro, "How we triaged Astro's issue backlog with agents" (2026-08) + the
withastro/triagebot-actionreference implementation. Astro took a 5+ year backlog from 200+ open issues to ~30 — not by issue bankruptcy or auto-closing.Their stated core philosophy is the part RAD should steal:
They enumerate three deficits an agent failure implicates, and fix the codebase rather than the prompt:
Their worked example: on an HMR bug the bot repeatedly modified the same
ifcondition, fixing the target bug but regressing others because nothing covered the neighbouring behavior. They did not tune the prompt — they added a descriptive comment explaining the exact logic governing that statement, and the bot stopped attempting incorrect modifications in that area.This directly contradicts a premise currently written into #63. #63 frames the mining question as:
Astro's evidence says
blocked_codeis not a "fix nothing" bucket. Recurrent agent failure localized to a region of code is a legibility signal about that region, and the highest-leverage patch is in the code — a comment, a test, a clearer boundary — which pays off twice, for the next agent and the next human.RAD's feedback loop today has two proposal routes and neither can express this:
There is no route that points at product code.
Proposal
Add a third route to the
/rad-insightssuggestion stage: signal→code-legibility proposal, keyed by file rather than by outcome.Localization key: intersect the failing wave's per-task status (from #63's
tasks[{title,status}]) with that task's planFile:field. A file accumulatingblocked_code, retry-heavy-but-eventually-successful waves, or repeatfail-testsacross multiple features is the unit of recurrence — not the outcome type.Rendered proposal names the file, the observed evidence (which features, which waves, how many attempts), and classifies the suggested remedy into Astro's three deficits:
blocked_codeon the same file across featuresSuggestion-only prose, same rule as every other insights route.
Hard constraints
harness/events.jsinsights block; the events writer and gate fold gain no authority.RAD_*_THRESHOLDenv), not new matching machinery.File:field render an "unattributable" note, never a silent omission or a guess.Files in scope
harness/events.js(new pure fold: per-file failure attribution),harness/test/events.test.js.claude/commands/shared/rad-insights.md(new "Code-legibility proposals" section + the deficit mapping table)docs/(document the rationale — specifically thatblocked_codeis a legibility signal, not a dead end)Suggested wave structure
wave-attemptevents joined to plan taskFile:paths. Validate: plan with noFile:fields → explicit unattributable bucket; a task touching multiple files attributes to each without double-counting the wave; historical logs withouttasks[]fold to zero and say so.Acceptance criteria
/rad-insightsrenders per-file code-legibility proposals when a file crosses the recurrence threshold across more than one featuredocs/records the corrected premise: recurrentblocked_codeimplicates the code's legibilityRelated
blocked_codeis not "fix nothing". Mine traces, not counts: persist per-task WAVE_RESULT statuses, failed-wave transcripts, and contract-level usage #63 remains the hard data dependency (per-task statuses + failed-wave transcripts).--draft-plans) can turn a threshold-crossing file into a Gate-1-blocked plan.