Skip to content

Four recorded residuals from the tabwriter ledger (#552 successor) #575

Description

@ZacxDev

STATUS, 2026-09-14 — R2, R3 and R4 were ACCEPTED IN WRITING; this issue now rests on R6 alone.
The decision and its reasoning are in a comment below. The 09-13 note follows unchanged.

STATUS, 2026-09-13 — read this before the list below. Two of these are
CLOSED and two more residuals were found while closing them. The per-residual
headings below were written when all four were open and are annotated in place
rather than rewritten, so the original framing stays readable.

residual state
R1 gatePreSanitised resolves a name CLOSED#578 (3457c5dc): the state was deleted rather than made relational
R2 laundering past four hops CLOSED — accepted in writing 2026-09-14 by @ZacxDev (comment below): bound measured 4/5, live corpus max 2 hops, GREW/SHRANK/MISLABELLED unaffected
R3 a renderer with no server text has no honest row CLOSED — accepted 2026-09-14 (comment below). 🔴 Its "points at gatePreSanitised" clause is STALE: #578 deleted that state
R4 the same hazard one line outside a cell CLOSED — accepted 2026-09-14 (comment below); was already partly narrowed by #578
R5 one-letter bareIdentArgs keys (comment below) CLOSED#582 (095f4acf): re-keyed enclosingFunction::argument
R6 a (function, name) key cannot express two callers with two origins (comment below) 🟡 open — surfaced by R5's audit

R5 and R6 are recorded as comments on this issue, not in this body.

Successor to #552, whose closing condition was met by #573 (6f0a8d8). These four were recorded in the code as open — each is stated in internal/cmd/tabwriter_ledger_test.go's residual list or const block rather than implied — and none is covered by #552's condition. Filed together because they share one root: a structural scan over tabwriter cells cannot see any of them.

Closing condition

Each residual below is either fixed, or re-stated with a decision recorded by a named reader. R1 is the only one that is plainly a defect; R2–R4 are trade-offs that may legitimately be accepted in writing.

Checked by: for a fix, the merged PR plus a mutation showing the relevant guard reddens; for an accepted trade-off, a comment on this issue from a maintainer naming which residual and why, after which this issue closes.


✅ R1 — gatePreSanitised resolves a NAME, never a relationship — CLOSED by #578

Closed 2026-09-13 by #578 (3457c5dc). Not by making the resolution relational,
which is what the text below proposes: matching an upstream's output to the
renderer's own cell narrows the hole to a field name and still leaves one. The state
was deleted instead, and its single user (printGenerateQuote) now gates at the
cell, where safeTermSingle is an idempotent no-op and the scan can see it. Watched:
the row that used to pass now fails three ways — unknown gate, MISLABELLED, and
GREW — where all three were green before.

The original framing follows unchanged.

internal/cmd/tabwriter_ledger_test.go. The gate arm checks that upstream names a function that exists and calls safeTermSingle somewhere. It never checks the named function feeds this renderer's cells.

Measured: a renderer writing a raw server string into a cell, ledgered as {…, gatePreSanitised, "printTagList", …}printTagList being an unrelated renderer that merely happens to sanitise — passes the test and the entire internal/cmd package.

So the ledger's set is closed at two states, but one of them is a hole any row can be moved into. Pre-existing — the same row is green before that file existed — and three sentences claiming otherwise were retracted in 34f0257.

Closing it means resolving upstream against the renderer's own cell expressions. That is hard precisely for the struct-field case the state exists to cover, which is why it is filed rather than fixed.

Today exactly one row uses it (describeVersion) and that use is independently true. That bounds the damage; it is not a defence.

🟡 R2 — laundering past four hops

sanitizerReach stops at depth 4. A bare safeTerm passed through five successive local assignments reaches a cell uncounted. Measured at both points: 4 hops → reported, 5 hops → sanitizers=[], missed.

The renderer is still seen, so GREW/SHRANK/MISLABELLED still apply — only the BARE-SAFETERM half is lost. No value in the package is currently passed through more than two hops.

🟡 R3 — a renderer with no server text has no honest row

An all-CLI-owned renderer (integers and literals only) is still registered as a renderer, so GREW demands a row — but gateSingle fails MISLABELLED with "the gate was deleted — which is the #552 defect happening", which is untrue of it, and gatePreSanitised would be a lie.

The honest options are a no-op safeTermSingle on an integer, or restoring a third state. None exists today, so the choice is deferred, not made — and the GREW message currently points the next author at gatePreSanitised, i.e. straight into R1.

🟡 R4 — the same hazard one line outside a cell — NARROWED, still open

#578 closed the money-path instances: confirmGenerate's Checkpoint: and
LoRA: label lines, and printImageDisclosure's Image: line, all of which sat
above Generate? [y/N]: and could forge a fake Cost: line before an irreversible
spend. The ~60 other single-line read-path sites below are untouched.

printModelDetail's header, printCollectionDetail, printAppDetail print label: value with plain Fprintf; a \n still lands at column zero. ~60 such single-line read-path sites remain.

printSubmissionDetail and printListingStatus were in this class and are fixed (#573) — a rejection reason of "\x1b[1A\x1b[2KOVERWRITTEN" previously put a raw ESC on stdout.

Telling a single-line label from legitimately multi-line free text is a per-field judgement, not a structural one. The README says this to users rather than promising the wider claim.


Not included

Soft wrap — collapsing \n makes lines longer, so a long value can still reach column zero via the terminal's own wrap with no control character involved. It is the one item #552 was being held open for; it is a different root cause (no column budget) and belongs in its own issue if anyone takes it up. U+2028/U+2029 likewise: a documented internal/saferune residual with no known terminal that breaks on them.

Provenance

R1 came from a delta re-audit of #573; R2–R4 from the blind correctness round and the requirements round. The original forgery class is @xsvm's (#544, #545, #554).

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions