Skip to content

aggregator(coverage): isRepoCensus accepts impossible census rows — negative counts, gate counts above the open total, '/' repos and silent duplicate overwrite — and they persist into the weekly snapshot baseline #3364

Closed

Description

@dezren39

Summary

isRepoCensus — the structural gate for the fleet-feed coverage census behind the #1220 coverage panel (merged in PR #3309) — accepts census rows that cannot describe a real repo: negative counts, gate counts larger than the repo's open-issue total, a repo of "/" or "a/", and duplicate rows for the same repo. Those rows flow straight into the report, are persisted into the weekly coverage snapshot (including the frozen weekly baseline), and render on /projects — so one bad feed read can show negative/impossible backlog numbers and poison the week-over-week baseline for a full week. Duplicate rows are resolved by silent last-wins overwrite in computeCoverage, with none of the drop-and-count diagnostics the aggregator's other feed gates (#2429 quota sanitization) surface.

Evidence (verified this run, main 1a68d6af; coverage.ts sha256 2c166cdf…b301, feed.ts sha256 d7416455…36a4, both matched on the laptop clone)

The gate, pm-stack/aggregator/src/coverage.ts:88-98, checks only typeof repo === "string" && repo.includes("/") and Number.isInteger on the three counts. Laptop probe (~/git/fleet/probe-2026-11-01-laneB-census/probe.ts, bun, importing the real coverage.ts/feed.ts; full output in run.log):

  • isRepoCensus({repo:"developing-today/code", openIssues:-5, gateNow:0, gateNext:0}) → true
  • isRepoCensus({…, openIssues:3, gateNow:10, gateNext:7}) → true (gate counts are label-filtered subsets of the same open-issue search in scripts/collect-fleet-feed.ts:684-696, so each must be ≤ openIssues)
  • isRepoCensus({…, openIssues:10, gateNow:-2, gateNext:0}) → true
  • isRepoCensus({repo:"/", …}) and {repo:"a/", …} → true
  • computeCoverage on two rows for developing-today/code (openIssues:100 then openIssues:7, gateNow:9, gateNext:9) → one row with the last values, no diagnostic; coverageFromFeed (src/feed.ts:275-282) keeps all 4 rows of a mixed feed (negative + impossible + duplicates)
  • A negative census row yields a report row with openIssues:-5 and a week-over-week delta of -55 against a baseline of 50 (diffCoverage)

Downstream, src/server.ts:81 (coverageSnapshot) persists whatever computeCoverage returns via CoverageSnapshotStore, and nextCoverageSnapshot freezes the week's first report into weekly, which becomes next week's baseline — so impossible values are not a transient render glitch; they are stored and compared against for a week. coverageSectionHtml (src/render.ts:4910-4925) renders the numbers verbatim.

Why it matters

The coverage panel's whole contract (per the coverage.ts header and PR #3309's Codex rounds) is that unavailable or malformed source data renders as unavailable, never as invented numbers. Every sibling feed gate enforces its section's invariants (e.g. isQuotaWindow/sanitizeQuotaView drop-and-count, isProjectPoolItem shape-strictness). The census gate enforces only types, so the one section whose values are snapshotted to disk and frozen as a weekly baseline is the one that can store impossible values. A collector bug, a hand-edited feed, or a future collector change that double-emits a repo silently rewrites the panel and the baseline instead of dropping the row.

Acceptance criteria

  • isRepoCensus refuses: negative counts; gateNow > openIssues or gateNext > openIssues; a repo that is not an owner/name pair (both sides non-empty, exactly the shape the collector emits for the four fleet repos).
  • Duplicate census rows for one repo are handled explicitly — refused/dropped at the gate (with the surviving row's provenance clear), or counted/surfaced like sanitizeQuotaView's drop counts — never silent last-wins.
  • Regression tests in test/coverage.test.ts pin each refusal and the duplicate behavior; existing coverage tests (absent census → null fields, pool-unavailable → null pool fields, weekly rotation) keep passing.
  • No change to the collector's emitted shape, the snapshot file format, or the panel layout.

Distinct from: #1220 (the feature, closed), #1218 (Project export auditability), #3332/#3309 (AA keep-last-good / the coverage panel PR itself). Dedup checked this run against open + closed issues for isRepoCensus / RepoCensus / coverage-census terms — no existing issue covers this gate.

Activity

  1. added
    kind/bugSomething isn't working (prefixed form of the classic bug label)
    queue/queuedHas a queued task in the Supabase agent queue
    source/creatorFiled by the new-issue-creator job
    task/triageQueue packet kind: verify, reproduce, and route this item
    priority/lowNice to have; do when convenient
    app/aggregatorPackage/app: aggregator (pm-stack in this repo)
    effort/sSmall: expected under 2 hours of work
    on Nov 1, 2026
  2. dezren39 commented on Nov 1, 2026

    @dezren39
    MemberAuthor

    🤖 Agent note · filed

    • Agent: new-issue-creator job (lane B, new-issue-creator-code-b)
    • Session / ID: new-issue-creator-code-b run 2026-11-01 00:50 CDT (2026-11-01T05:50Z)
    • Found via: filed this run
    • Task: Filed this issue: isRepoCensus accepts impossible coverage-census rows (negative counts, gate counts above the open total, / / a/ repos, silent duplicate last-wins), and the values persist into the weekly coverage snapshot baseline (probe-verified on the laptop against the real coverage.ts/feed.ts, sha-matched). Triage packet enqueued to repo-health-code-pilot.
    • Expectation: effort/s — triage confirms the gate gaps against current main, then routes the isRepoCensus invariant checks + duplicate handling and tests.
    • Links: laptop probe probe-2026-11-01-laneB-census (~/git/fleet/ on the laptop)
  3. dezren39 commented on Nov 1, 2026

    @dezren39
    MemberAuthor

    agent-note:v1 — state: picked-up (triage task 5083, OpenChamber scheduled lane)

  4. 24 remaining items

  5. added
    status/parkedDeliberately paused with a recorded resume condition
    and removed
    queue/claimedQueue worker lifecycle state
    on Nov 1, 2026
  6. dezren39 commented on Nov 1, 2026

    @dezren39
    MemberAuthor

    🤖 Agent note · parked

  7. added
    queue/claimedQueue worker lifecycle state
    and removed
    status/parkedDeliberately paused with a recorded resume condition
    queue/parkedQueue task is parked (waiting on CI, time, or an event)
    on Nov 2, 2026
  8. dezren39 commented on Nov 2, 2026

    @dezren39
    MemberAuthor

    🤖 Agent note · picked up (resume — ownership re-check)

  9. dezren39 commented on Nov 2, 2026

    @dezren39
    MemberAuthor

    🤖 Agent note · done (fixed, merged)

  10. added
    task/small-fixQueue packet kind: bounded fix with reproduction and targeted tests
    and removed
    task/triageQueue packet kind: verify, reproduce, and route this item
    queue/claimedQueue worker lifecycle state
    work/assignedQueue worker lifecycle state
    on Nov 2, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

app/aggregatorPackage/app: aggregator (pm-stack in this repo)app/pm-stackpm-stack (Pad/Grist) in developing-today/codeeffort/sSmall: expected under 2 hours of workkind/bugSomething isn't working (prefixed form of the classic bug label)priority/lowNice to have; do when convenientsource/creatorFiled by the new-issue-creator jobtask/small-fixQueue packet kind: bounded fix with reproduction and targeted tests

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions