Skip to content

fix(docs,tests): three backlog ids were used twice, and nothing measured it - #514

Merged
cevheri merged 1 commit into
mainfrom
fix/backlog-duplicate-ids
Aug 27, 2026
Merged

fix(docs,tests): three backlog ids were used twice, and nothing measured it#514
cevheri merged 1 commit into
mainfrom
fix/backlog-duplicate-ids

Conversation

@cevheri

@cevheri cevheri commented Aug 27, 2026

Copy link
Copy Markdown
Member

What broke

#511 and #513 branched from the same commit (8a0797f2) and each appended three entries to the
"Drivers and connections" section of docs/BACKLOG.md. The bodies landed at different offsets, so
git merged them without reporting a conflict, and main carried D36, D37 and D38 twice:

Line Entry From
431 D36. The migration generator emits ADD CONSTRAINT for SQLite... #511
456 D37. Five HTTP providers read the SSL mode... #511
482 D38. getConnectionInfo masks a password in a connection string... #511
548 D36. A slow-query source nobody could read is still a row... #513
590 D37. The Overview panel still shows a fabricated zero... #513
622 D38. Two more surfaces read a capped list as a count... #513

The file's own header states the rule: "Every ID is unique across the whole file. Cross-references
use the bare ID (B47), so no two entries may share one."
A duplicate makes every such reference
ambiguous.

There is a second defect from the same merge. The one line both branches did edit, the section
index for Drivers and connections, conflicted, and the resolution dropped its id range and count
altogether — leaving - [Drivers and connections](#drivers-and-connections) with no basis at all.
A section index that states nothing cannot be wrong, which is why nothing caught it.

The fix

#511 reached main first, so its three entries keep D36-D38 and #513's are renumbered to
D39-D41. The single citation in src/lib/schema-diff/migration-generator.ts:388 names #511's
D36 and is left alone; nothing in the repository cited the renumbered three, and there are no
in-file prose cross-references to any of the six.

The index line is restored as the entries make it: D1–D41, U17, U22–U23 · 19.

The guard that was missing

tests/unit/backlog-structure.test.ts derives the index block from the entry bodies rather than
trusting it:

  • no id appears twice anywhere in the file;
  • the sections listed are the sections present, in both directions, and each anchor resolves to its
    heading slug;
  • every id a line names exists as an entry in that section;
  • each range's endpoints are the real extremes for that prefix;
  • the trailing · N is the real number of entries, and a line may omit it only for a section with a
    single entry.

Endpoints are checked as extremes rather than against one canonical rendering because the file
legitimately writes a prefix two ways — U17, U22–U23 in one section, X2–X14 in another.

The existing citation guard in tests/unit/agent-documentation.test.ts only ever asked whether a
cited id exists, which a duplicate satisfies.

Verification

Both defects were confirmed to fail the new test before the fix (no id is used twice, and
Drivers and connections states a range and a count). Each index assertion was then confirmed
non-vacuous by corrupting the line and watching the specific test go red:

Mutation Test that failed
· 19· 18 Drivers and connections counts its entries
D1–D41D1–D38 Drivers and connections names the real extremes
dropped U22–U23 Drivers and connections names the real extremes

The document was restored byte-for-byte after each mutation.

Local gates on the pushed tree: format clean · lint 0 errors · typecheck clean · knip clean ·
bun run test all 33 groups pass · bun run build exit 0.

No src/ behaviour changes.

…red it

#511 and #513 branched from the same commit and each appended three entries to the
"Drivers and connections" section. The bodies landed at different offsets, so git merged
them without reporting a conflict and main carried D36, D37 and D38 twice. The file's own
rule, stated in its header, is that every id is unique across the whole file because
cross-references use the bare id; a duplicate makes every such reference ambiguous.

#511 reached main first, so its three entries keep D36-D38 and #513's are renumbered to
D39-D41. The single citation in src/lib/schema-diff/migration-generator.ts names #511's
D36 and is unchanged; nothing cited the renumbered three.

The one line both branches did edit, the section index for Drivers and connections, did
conflict, and the resolution dropped its id range and its count altogether. A section
index that states nothing cannot be wrong, which is why nothing caught that either. It is
restored as the entries make it: D1-D41, U17, U22-U23, 19 entries.

tests/unit/backlog-structure.test.ts is the guard that was missing. It derives the index
block from the entry bodies rather than trusting it: no id appears twice, the sections
listed are the sections present and their anchors resolve, every id a line names exists,
each range's endpoints are the real extremes, and the trailing count is the real number of
entries. The endpoints are checked as extremes rather than as one canonical rendering
because the file legitimately writes a prefix two ways, U17, U22-U23 in one section and
X2-X14 in another.

Both defects were confirmed to fail the new test before the fix, and each of the four
index assertions was confirmed to fail against a deliberately corrupted line, so none of
them passes vacuously. The existing citation guard in tests/unit/agent-documentation.test.ts
only ever asked whether an id exists, which a duplicate satisfies.
@sonarqubecloud

Copy link
Copy Markdown

@cevheri
cevheri merged commit dccb730 into main Aug 27, 2026
22 checks passed
@cevheri
cevheri deleted the fix/backlog-duplicate-ids branch August 27, 2026 12:39
cevheri added a commit that referenced this pull request Aug 27, 2026
…ds a total (#517)

* fix(db,ui,docs): an unknown size is absent, not zero, and a share needs a total

Two providers stated both facts in one object. Trino paired
`databaseSize: TRINO_UNAVAILABLE_TEXT` with `databaseSizeBytes: 0`, and the search
seam paired `SEARCH_UNKNOWN_TEXT` with `sizeBytes ?? 0`, so one overview said
"unavailable" in the string and "zero bytes" in the number from a single input.
Both now omit the key, which is what the optional field is for, and a real zero
still reads as zero. Apache Cassandra had already written the argument down.

The search seam also held the last unconditional `activeConnections: 0`. It is
absent now, and `getHealth()` stops composing a key it has no source for. Not the
last zero of any kind: Trino, Druid, ClickHouse and Couchbase each degrade a
refused monitoring read to no rows and then map the absent row to zero, which is
the same encoding by a longer route and is filed rather than fixed here.

The Storage tab is where the fabrications were visible, and three of its figures
divided by a total it did not have. A share now requires `totalSize > 0`, which
excludes the absent size and the measured zero alike, so the remainder bar is empty
instead of full and the two Quick Stats percentages no longer sit under real
megabyte figures. The remainder's BYTES are gated on the contradiction rather than
on the share: a 0 total beside per-table reads that answered rendered a negative
byte count, while `0 - 0 - 0` is an honest zero and stays one. A refused overview
now carries the engine's own sentence, the way two sibling panels do.

Verified end to end in Chrome against the SQLite sample: unpatched, the breakdown
reads 504 + 288 + 4 = 796 KB with bars at -36.68% / -63.82% / -99.4975%; with the
overview's size forced to 0 while the table read answers, the remainder reads N/A,
all three bars are empty, and no percentage is drawn anywhere.

The shared `formatBytes` refused nothing. Measured live: -1, NaN and both
infinities all rendered "NaN undefined", and a petabyte rendered "1 undefined" - a
number wearing a missing unit, which scans as a figure rather than as garbage.
Non-magnitudes return "N/A", the string three other places in this codebase
already use for a size they do not have; the ladder gains PB and EB; and the index
is clamped, which makes indexing past the array unreachable rather than moving the
boundary up two rungs.

Also corrects three claims this repo made about itself. The Storage tab defines its
own local byte formatter and never imports the shared one, so the negative
remainder rendered "-1536 B" and not "NaN undefined" as mongodb.md, a mongodb.ts
comment and the backlog entry all said - a review lane reported exactly that last
round and was overruled by a measurement of the wrong function. The search docs'
claim that `TableStats` cannot say "unknown" is false for its four optional size
fields. And a new comment claiming the last zero anywhere was narrowed to the last
unconditional one.

* docs(backlog): three entries close, four open in their place

D46 and U24 close outright. D44 closes three of its fourteen type-ids - the ones
that contradicted themselves inside a single object - and its counts moved for a
second reason: DuckDB arrived as a seventeenth type-id in #516 and already writes
the key conditionally, so it is a fourth correct provider rather than a fifteenth
fabricating one. The title now reads 11 of 17, the remaining-work list names all
eleven files, and MongoDB is explicitly off that list because both its paths were
already right.

Four entries open, each measured rather than inferred:

D50 - the search seam zeroes two OPTIONAL `TableStats` size fields for a closed
index. Not fixed alongside the rest because omitting them takes the Data figure
away from every open index in the cluster, through `tables.every(...)`, which is a
visible panel change that wants its own decision rather than a drive-by.

D51 - Trino, Druid, ClickHouse and Couchbase each swallow an unavailable
monitoring surface into an empty result and then map the absent row to 0.
ClickHouse's does it to six fields at once, so one refused read publishes a
fully-zeroed overview that reads as measured. Filed as one entry because the fix
is one decision applied four times: the degrade step already knows the difference
and discards it before the mapper can act. Redis and PostgreSQL are named as NOT
measured rather than folded in on resemblance.

U25 - `formatBytes` exists three times, and the two component-local copies have no
guard: measured, they render "-1 B", "NaN B", "Infinity GB" and an exabyte in
gigabytes.

U26 - the admin fleet total re-parses formatted strings and has no `tb` branch, so
a 1 TB database contributes one byte, and this round's PB and EB rungs add two more
spellings that land in the same arm. The real defect is that `FleetHealthItem`
carries no numeric channel at all, which is also what makes an honest absence
inexpressible there.

The section index lines were recomputed from the surviving headings rather than
merged. Both new ids had to move: this branch took D47 and D48 before #516 merged
and published its own, and the bodies auto-merged without a conflict while only the
index line reported one - the same mechanism as #513, caught this time by the guard
#514 added.
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