LearnNewsExamplesServices
Frontmatter
id17406
titleComment density is unmeasured, and a share alone can be diluted
stateOpen
labels
enhancementaiarchitecture
assigneesneo-opus-vega
createdAtAug 19, 2026, 11:47 PM
updatedAtAug 20, 2026, 12:31 PM
githubUrlhttps://github.com/neomjs/neo/issues/17406
authorneo-opus-vega
commentsCount0
parentIssue17400
subIssues[]
subIssuesCompleted0
subIssuesTotal0
contentTrust
projected
quarantined0
signals[]
blockedBy[]
blocking[]

Comment density is unmeasured, and a share alone can be diluted

Open Backlog/active-chunk-17 enhancementaiarchitecture
neo-opus-vega
neo-opus-vega commented on Aug 19, 2026, 11:47 PM

Context

Split from #17400, which keeps the wiring. This leaf is the measurement itself: two axes over a commit's added lines, plus the bars they are judged against.

Nothing in the repo measured comment density in shipped source — check-ticket-archaeology governs decay-prone refs, check-substrate-size governs turn-loaded bytes — so the only gate was the author's own judgement. Measured over 21 days of agent-authored ai/ + src/ commits, prose share of added lines by family: opus5 39.8%, fable 30.5%, kimi 28.6%, gpt 10.7%, against an operator bar of ~30%.

The Problem

A share alone has an author-controlled denominator. a17ade4264 measures 21% — under the bar — while carrying a 36-line contiguous prose run on one function, and the operator change-requested it for bloat. ~200 lines of fixture in the same commit produced that dilution, so adding tests buys room for narrative: gameable in the direction of good behaviour, which nobody audits.

The cost is paid twice. A maintainer pays on every visit, and the text is ingested into Chroma — verified: a query for a phrase existing only inside comments returns TextEmbeddingService.mjs (2313) and TenantRepoSyncService.mjs (543). A long derivation dilutes the invariant it wraps and then competes with it for retrieval, at full weight, forever. Unlike a ticket, a docblock never closes.

The Architectural Reality

  • buildScripts/util/check-ticket-archaeology.mjs:44extractComment(line, state), string-aware with block state carried across lines. Reused rather than re-regexed.
  • buildScripts/util/stagedDiff.mjs:57getStagedAddedLines(file, gitRoot), the added-line-number reader.
  • buildScripts/util/check-substrate-size.mjs — budget-shaped guard precedent, scoped to turn-loaded substrate.
  • package.json lint-staged — where a pre-commit entry would live; .husky/pre-push runs its checks serially and is the likelier home.

The Fix

  1. Two axes over added lines, warned independently: prose share, and longest contiguous prose run — the axis with no denominator to dilute.
  2. Tag lines are contract, not prose. @param / @returns / @summary are excluded and break a run, so a densely-typed signature does not read as bloat.
  3. Bars as inputs. The run default sits inside the measured p90–p99 band (p90 32, p99 64 across ai/services/**), so a warning means unusual.
  4. Warn, never block, and print both raw numbers rather than a verdict.

Contract Ledger Matrix

Target Surface Source of Authority Proposed Behavior Fallback Docs Evidence
measureProseDensity the file's lines + the added-line set per-file share and longest run; only added lines count non-comment lines break a run pre-commit docs pre-existing prose is not this commit's
summarizeDensity per-file measurements commit-level share (summed) and run (max); warns on either empty set never warns pre-commit docs 21% share / 36 run must warn
bars measured p90–p99 band + the ~30% observation operator-tunable inputs partial bounds normalize onto defaults pre-commit docs a changed bound changes the outcome

Decision Record impact

none — adds a measurement, changes no authority.

⛔ IMPLEMENTATION PRESCRIPTION SUPERSEDED 2026-08-20 — read before building

PR #17407 was closed unmerged under a Drop+Supersede from @neo-gpt-emmy (review). The problem and the consumer are unchanged; the inference substrate is refuted. Do not restart from that diff's approach.

Why the line-oriented substrate cannot govern this

  • Raw-prefix comment inference. Matching /^\s*(\/\*|\*\/|\*|\/\/)/ against a raw line classifies a continued multiplication as a comment:
      const area = width
        * height;
    A checker that manufactures both false warnings and false silence on valid JavaScript has no authority over repository prose.
  • Unit mismatch, third instance on this lane. The shipped code measured a whole pushed range (remoteSha..localSha) as one diff while both bars were calibrated per commit. Earlier instances: a whole-FILE run distribution applied to per-commit added lines, and a chunk count divided into a file-count rate. A threshold inherits the unit of the distribution that produced it. The successor names its unit once, explicitly, and calibrates in that unit.
  • Lexical concession detection is a dead end, and this is measured. Two independent candidate vocabularies for the operator's "I know duplicating code is bad, but…" specimen scored 0 true across 13 hits over 2564 in-scope files: the lexical form fired only on this repository's own epistemic idiom ("the case we know"), the structural <norm>…but form only on contrastive "not X but Y" technical prose. Do not re-attempt it; beat the measurement first if you disagree.

Required substrate for the successor

  • Parser-owned comment ranges. buildScripts/util/check-aiconfig-test-mutation.mjs:160-200 is the sanctioned Acorn precedent in this repository. Comment classification comes from the parser, never from line prefixes.
  • One named measurement unit, calibrated in that unit, applied in that unit.
  • not-measured is a distinct state from clean. A file that could not be parsed, a range that could not be resolved, and a range with no findings must be three different outputs. The refuted implementation collapsed the first two into the third — twice in one file, the second time after the first was fixed.

Salvage — retained, do not rebuild

The pre-push payload capture and its advisory || true (with the set -e reasoning that makes non-blocking a stated property rather than an assumption); the pendingRanges tuple / branch-deletion / new-remote-branch shapes; the warning output format carrying raw numbers rather than a verdict; injectable bounds with the fixture proving a changed bound changes the outcome; the scan roots including buildScripts/ so the checker is subject to its own rule; and the temp-git-repo fixture, which is how a git-reading arm stays honest under a depth-1 CI checkout.

Acceptance Criteria

  • Red-proof, run axis: the TOOL, run over a17ade4264, reports 19% share and a 45-line block — under the share bar, over the run bar. Asserted by measuring the commit, not by feeding the numbers in: an earlier version of this AC said 36 while the tool computed 9 on the same commit, because the run broke on tag lines.
  • Silent arm: the tool reports 24% share and an 11-line block on 087114e8ab and warns on neither axis, so a guard that warns on everything fails here.
  • Share axis warns high and is silent at the median, and it catches what the run axis misses: 027125dcf7 cuts the run 45 → 5 while 27 of its 32 added lines are comment.
  • Tag lines are excluded from prose and do NOT break the run. The axes measure different objects: a typed signature is contract rather than narration, and a 45-line docblock is 45 lines to a reader whether or not @param sits in the middle. Breaking the run on tags is what made the axis unable to fire at all.
  • A comment marker inside a string literal is not prose.
  • An unchanged line breaks a run; pre-existing prose is not counted as this commit's.
  • Each bar is the p90 of the seats whose behaviour did not change — two independent flat controls agreeing (block run 34 and 35; share 31.9% and 28.5%) — and a changed bound changes the outcome. A trailing median would drift along with what it measures.
  • Both raw numbers are printed, never only a verdict.
  • Scope includes specs and buildScripts/ — a checker exempt from its own rule is not a rule.

Out of Scope

  • Wiring it into a hook. #17400 keeps it. Adding the lint-staged entry reproduced Task killed on unrelated checks, and a single-file commit reproduced the same kill, so the cause is host memory pressure rather than the entry. .husky/pre-push needs a commit-range mode, which is the follow-up rather than a rushed addition.
  • Blocking on density, and any rule a marker can silence.
  • Artifact-body density (issue / PR / review prose) — #16217 owns that surface.
  • Ticket-ref hygiene in comments — check-ticket-archaeology owns it.

Avoided Traps

  • A ratio as the only axis. Caught by a peer's counterexample rather than by reasoning, which is why the run axis is an AC.
  • A control that is merely smaller. A 30-line run six below the 36 that must warn would pin the bar into (30, 36] by construction, and 30 sits between median and p90 — ordinary. The silent arm is at the median instead.
  • Mirroring the archaeology check's escape hatch along with its shape. Free-text escapes defeat prose guards specifically, because prose is what the escape is made of.
  • Counting markers instead of text. extractComment('/**') returns *; counting it inflated every docblock by one, so prose requires a word character.
  • Attributing the hook kills to this change. One trial each way is not a cause, and a single-file commit reproduced the kill.

Related

  • #17400 — parent; keeps the hook wiring.
  • #16217 — the artifact-surface sibling; same operator observation, different reader.
  • #17396 — checkers whose granularity is finer than the structure they judge.
  • D#17326 — the confession anti-pattern: prose that owes work. A length warn surfaces confessions as a side effect.
  • D#17346 — substrate-weight governance; the layer this would report into.

Origin Session ID: 8cbd588b-be06-4a56-9997-1058f2a3a07b

Retrieval Hint: query_raw_memories("comment density two axes share run author-controlled denominator prose bar p90 band warn only")