Skip to content

fix(testenv): -update-skips deleted the audit trail it exists to protect - #699

Merged
rainmanjam merged 1 commit into
mainfrom
fix/update-skips-keeps-its-own-audit-trail
Sep 4, 2026
Merged

fix(testenv): -update-skips deleted the audit trail it exists to protect#699
rainmanjam merged 1 commit into
mainfrom
fix/update-skips-keeps-its-own-audit-trail

Conversation

@rainmanjam

Copy link
Copy Markdown
Owner

Closes #697.

The skip ratchet's own failure message tells an author what to do:

If the new site is environmental, say so in the message and regenerate with
-update-skips AND raise the number here by hand, which is the reviewable act.

Following that instruction deleted 142 of the file's 166 lines — every
justification for every previous raise, on the one file whose entire purpose is
to make raises reviewable. I hit this raising the budget for #696, worked around
it by hand there, and filed it rather than leaving the workaround buried.

Cause

writeSkipCensus unmarshalled into skipCensus, built a fresh one from the
two fields that struct declares, and marshalled that. Every other key was
dropped by construction. There are seven of them:

raisedBy, loweredBy, raisedBy2, raisedBy3, loweredBy2, raisedBy4, raisedBy5

The numbering is what happens when a hand edit has nowhere obvious to append.

The fix does not know the history schema

Deliberately. "Preserve every key I do not own" stays correct when the eighth
history key appears — and a fix that carried raisedBy by name would have
dropped the other six and passed a test written about raisedBy. That is
why the test asserts the general property.

nextCensusFile rewrites total and byPackage, leaves everything else as it
found it, and leaves an existing note alone too — that is prose somebody may
have edited.

Order is preserved, read back off the token stream because encoding/json
does not keep it. This file is read in diffs; reordering it on every
regeneration buries the two lines that actually changed under a whole-file
rewrite, which is a large part of how the original bug stayed invisible.

Verification

Regeneration against the real file is now byte-identical, where it
previously produced +1/−142.

Four mutations, each turning a test red: dropping unknown keys (the old
behaviour), setting a new key without ordering it, overwriting an edited note,
and failing to record key order.

https://claude.ai/code/session_01A8N3W5ct9SZtHK9sCDD9cL

Closes #697.

The ratchet's own failure message tells an author to regenerate with
-update-skips. Following that instruction deleted 142 of the census file's 166
lines -- every justification for every previous raise, on the one file whose
entire purpose is to make raises reviewable. Hit while raising the budget for
#696, worked around by hand there, filed rather than buried.

THE CAUSE. writeSkipCensus unmarshalled into skipCensus, built a FRESH one from
the two fields that struct declares, and marshalled that. Every other key in the
file was dropped by construction. There are seven of them -- raisedBy,
loweredBy, raisedBy2, raisedBy3, loweredBy2, raisedBy4, raisedBy5 -- the
numbering being what happens when a hand edit has nowhere obvious to append.

THE FIX DOES NOT KNOW THE HISTORY SCHEMA, deliberately. "Preserve every key I do
not own" stays correct when the eighth history key appears; a fix that carried
`raisedBy` by name would have dropped the other six, and would have passed a
test written about raisedBy. So nextCensusFile rewrites `total` and `byPackage`,
leaves everything else exactly as it found it, and leaves an existing `note`
alone too -- that is prose somebody may have edited.

ORDER IS PRESERVED, read back off the token stream because encoding/json does
not keep it. This file is read in diffs: reordering it on every regeneration
buries the two lines that actually changed under a rewrite of the whole file,
which is a large part of how the original bug stayed invisible.

Verified against the real file: regeneration is now BYTE-IDENTICAL where it
previously produced +1/-142.

Four mutations, each turning a test red: dropping unknown keys (the old
behaviour), setting a new key without ordering it, overwriting an edited note,
and failing to record key order. The test asserts the general property rather
than raisedBy specifically, for the reason above.

Claude-Session: https://claude.ai/code/session_01A8N3W5ct9SZtHK9sCDD9cL
Copilot AI lite review requested due to automatic review settings September 4, 2026 15:32

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

nextCensusFile’s pretty-print path likely introduces extra leading spaces for object/array values, risking non-byte-identical regeneration and noisy diffs in testdata/skips.json.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

This PR fixes the -update-skips regeneration path so it preserves the skip census file’s hand-maintained audit/history keys (and top-level key order) instead of rewriting testdata/skips.json from only the struct-owned fields and dropping everything else.

Changes:

  • Introduces nextCensusFile to rewrite only total and byPackage while carrying through all other keys in their original order.
  • Updates writeSkipCensus to use nextCensusFile so regeneration no longer deletes the audit trail.
  • Adds regression tests covering preservation of unknown keys, preservation of existing note, and key order, plus the “absent census” bootstrap case.
File summaries
File Description
internal/testenv/skips_test.go Adds ordered-preserving census rewrite helper, updates regeneration path to preserve unknown keys, and adds regression tests for key preservation/order.
Review details
  • Files reviewed: 1/1 changed files
  • Comments generated: 2
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment on lines +293 to +297
var pretty bytes.Buffer
if err := json.Indent(&pretty, fields[k], " ", " "); err != nil {
return nil, err
}
fmt.Fprintf(&buf, " %s: %s", kb, pretty.String())
Comment on lines +209 to +212
// censusKeysOwnedByTheWriter are the only two the regenerator computes. Every
// other key in the file belongs to whoever hand-edited it, and is carried
// through untouched -- see nextCensusFile.
var censusKeysOwnedByTheWriter = map[string]bool{"total": true, "byPackage": true}
@sonarqubecloud

sonarqubecloud Bot commented Sep 4, 2026

Copy link
Copy Markdown

@rainmanjam
rainmanjam merged commit e8aa0a5 into main Sep 4, 2026
36 checks passed
@rainmanjam
rainmanjam deleted the fix/update-skips-keeps-its-own-audit-trail branch September 4, 2026 16:34
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.

-update-skips deletes the raisedBy audit trail it exists to protect

2 participants