AUR-467: the review looks at code as code and prose as prose
Documento histórico do board. Pode descrever componentes removidos; para uso atual, consulte o guia do produto.
The defect, as measured
Run against the real gateway on 2026-08-14 over a real commit that changed
26 files, 15 of them .mjs:
AGENTS.md:115: [error] 'o que NAO fazer' contem instrucoes redundantes (quality/dead-code)
AGENTS.md:134: [info] a secao de invariantes e longa (quality/long-function)
AGENTS.md:142: [warning] as regras de invariante sao complexas (quality/high-complexity)
AGENTS.md:58,156: [info] termos poderiam ser mais descritivos (quality/poor-naming)
AGENTS.md:78,164: [warning] falta tratamento de erro (quality/missing-error-handling)
Seven findings, all seven on AGENTS.md (markdown), every one a code-quality
rule id applied to prose. None of the fifteen .mjs files got a comment.
The fix
internal/prompt now classifies each diff file via internal/analyzer's own
GetLanguageCategory (reused, not reimplemented) and excludes
documentation-classified files from the pool that competes for the code
token budget and receives the code rule catalog (filetype.go). The
exclusion is never silent: coverage.go renders a "Review Coverage" section
into the assembled prompt, and mirrors the same counts in
PromptParts.Meta (code_files_total, code_files_complete, code_files_partial,
code_files_omitted, prose_files_excluded), naming every documentation
file excluded and every code file a tight budget could not fit.
Unrecognized extensions (.txt, .vue, an extensionless file) classify as
code, not prose — DetectLanguage returns "unknown", and
GetLanguageCategory("unknown") is "other", never "documentation".
Treating unknown as prose would silently stop reviewing unmapped source,
which AC-002 forbids.
Known gap, declared and not fixed (internal/analyzer is read_paths,
not owned by this card): internal/analyzer.buildExtensionMap has no
entry for .markdown (the long form of the extension) — only .md and
.mdx map to "markdown", and .rst to "restructuredtext". A
.markdown file, and extensionless README/LICENSE/CHANGELOG files,
therefore classify as "unknown" → code, and still receive the code rule
catalog. This is the same fail-closed default as .txt, applied to files
that are usually pure prose in practice — a real gap, not a made-up one.
Fixing it requires editing internal/analyzer's extension map, out of this
card's paths.
This card does not build a prose rule catalog (Non-goals): documentation still has no rule_id catalog of its own, and that absence is what the coverage section now states.
The measured third cause
tests/unit/AUR-467.go::MeasuredCauseOfMJSOmission reconstructs (not
replays — the original diff was never captured) why the .mjs files got
zero comments, against the exported budgeting primitives directly:
- Ordering.
determineFilePriority(budgeting.go) gives a documentation file the samePriorityHightier as code, so ties break onSortKey, the file path."AGENTS.md"(leading byte0x41) sorts before any lowercase path, so its hunk is offered toTrimToFitfirst. - Starvation.
TrimToFitbreaks at the first segment that no longer fits rather than skipping it and trying the next, smaller one. OnceAGENTS.md's hunk fills the budget, every later segment — the fifteen.mjsfiles — is dropped entirely, not truncated.
Both mechanisms are diagnosed, not independently patched: excluding prose
before TrimToFit runs removes cause 1 for this shape of diff and frees the
whole budget for code, which is what the same test's post-fix half proves.
Cause 2 (break vs. continue) is still live for an all-code diff whose
first-sorted file is oversized — flipping it would change which code files
get reviewed today and fights budgeting_test.go; left as a follow-up.
Post-ff64e18 adversarial review: two blockers fixed
Blocker 1 — the coverage declaration was not itself budgeted. The
first cut appended renderCoverageDeclaration's text to userContent
after TrimToFit had already closed the token budget, and
Meta["estimated_tokens"] summed baseTokens plus the trimmed segments
only, never the declaration. Measured: an 8-omitted-file diff at
MaxTokens=1500 assembled to ~1546 estimated tokens (3% over) while Meta
reported 1419 — an undercount that grows with the number of omitted files,
so the worst overshoot lands exactly when the budget is already tightest.
Fixed by maxCoverageDeclarationTokens (coverage.go): it renders the
declaration's WORST CASE for this diff's file set (every code file
classified "omitted", the state that puts every path on its own bullet
line — the maximum bullet count the renderer can ever emit, since a
"complete" file contributes none) and reserves that many tokens out of
the content budget before TrimToFit runs. Meta["estimated_tokens"] is
now computed directly from the final System+User text BuildPrompt
returns, not a partial sum.
Blocker 2 — a file was "covered" if any one of its hunks survived.
coveredFiles (removed) checked file presence, not hunk completeness: a
2-hunk file whose second hunk TrimToFit dropped still read as
code_files_omitted=0, and nothing was ever declared about it — silence
on partial coverage, which this card's own Outcome forbids. Coverage is
now tracked per hunk (coveredHunkCounts) and every code file is
classified into exactly one of three states — complete (every hunk
present), partial (some hunks present, some cut), omitted (zero hunks
present). partial files are named in the declaration with their hunk
fraction (path (k/n hunks)) and counted separately in
Meta["code_files_partial"]; Meta["code_files_reviewed"] no longer
exists, replaced by the three explicit counters
(code_files_complete/code_files_partial/code_files_omitted).
What this card does not surface
PromptParts is this package's only public output; cmd/aurumcode and
internal/review are read_paths, not paths. The coverage declaration
lands in the assembled prompt content and in Meta, not on the CLI's own
stdout — printing it there needs a follow-up card that owns
cmd/aurumcode.
Selectors, each its own program
tests/unit/AUR-467.go::TestAUR467— AC-001/002/003 onBuildPromptdirectly, plus the ordering/starvation reconstruction.tests/integration/AUR-467.go::IntegrationAUR467— mixed prose types (.md,.rst), Meta arithmetic across three budgets, a no-prose control, and the AUR-461 rule catalog still present inSystem.tests/e2e/AUR-467.sh— no-regression control: the real binary againsttests/fixtures/repos/git-demo/repo.git(an all-code diff) still reports its fixture finding and closes--fail-on. AC-001/003 are not observable through a canned LLM fixture, since the defect is entirely in what gets sent to the model.tests/acceptance/AUR-467.sh::AC-001— a generated program calls the realBuildPromptagainst a diff shaped like the measured commit and greps its output; no git, no python3.AC-001-MUT-001reverts the prose exclusion;AC-003-MUT-002suppresses the coverage line. Both must go red.