docs(readme): make Troubleshooting a lookup table again — 35,250 → 19,182 bytes - #625
Merged
Merged
Conversation
…0,229 bytes Sixty rows whose cause cells had grown to essay length (individual cells at 2,952, 2,299 and 1,636 bytes; a 470-byte mean) against a section that opens with "Look up the message you got". Every cell is now one or two sentences — what happened, and the one thing to do next — plus the anchor the row already carried. No fact is deleted. Detail that the owning section did not already state was moved there, merged into the existing prose rather than appended: - the version guard's four cases and the `liveUrl` definition of "live" -> "Is your repo behind what you shipped?" - what the dirty-work-tree guard counts (the packager exemptions, a repo with no commits yet, `git mv` as two changes) -> "What the packager left out" - the three conditions under which a below-floor refusal is reported as progress -> "After you submit", replacing its pointer back at this row - the download-path sanitisation list and its two non-shared exceptions -> "Download model files" - the fixed 79-column wrap, "no words are dropped", and why prompts are NOT wrapped -> "What a table cell can contain" - the #513 numeric-username decode and what the error snippet is made of -> "Scripting with --json", beside the #525 repair it already documented Everything else displaced was already stated at length under the anchor the row points at (verified per row), or was maintainer-facing history and is deleted. Column one is untouched: all 68 symptom strings are byte-identical, which is what readme_troubleshooting_test.go pins. Rows 19 and 20 keep their cells verbatim -- TestAttributionProseCheckAcceptsCorrectProseAndRejectsMisattribution pins ~8 exact substrings of row 20 (one with a trailing space) and parses both cells for the commands they attribute the message to. Measured floors, before -> after: symptoms 68 -> 68 (>= 15), in-document links 212 -> 216 (>= 40), `##` 27 -> 27 (>= 15), `###` 47 -> 47, Troubleshooting's own `###` 5 -> 5 (the TOC exemption requires >= 1). Whole file 314,712 -> 306,073. The 13,000-byte target this was scoped to is below the section's structural floor: 7,081 bytes are the symptom column, the link column, the table scaffolding and the prose around it, so 13,000 leaves 99 bytes per cause cell -- one clause, not two sentences -- and rows 19 and 20 alone are 969 of it.
Round-0 audit follow-up on #625. Four fixes and one deletion. D1 — 14 cause cells were near-verbatim restatements of the error the binary already printed, in a column that (unlike column 1) is pinned against nothing and can drift silently. Each is trimmed to what the message does NOT say — the exit code, a cross-command caveat — plus the anchor. No ROW is removed: `TestREADMETroubleshootingCoversTheRefusalsAuthorsActuallyHit` puts 7 rows on an incident floor and 4 of these 14 (`cannot derive a slug from`, `refusing to overwrite. Scaffold somewhere else`, `no such directory …`, `refusing to submit without --yes`) are among them. Column 2 loses 1,103 bytes across the 14; column 1 of all 60 rows is byte-identical to origin/main. Every retained exit code was MEASURED against the built binary, not derived: rows 15/16/17 exit 2, 18 exits 1, 27/29/31/32 exit 2, 36 exits 1, 56 exits 2 (via a local stub for the model-version read), 59 exits 1 (via a local stub for the clone-info query). Row 58's code is not claimed — `upgrade` has no API-base override, so it could not be measured here. Two cells also gained a correction the measurement surfaced: - `is not valid UTF-8` claimed `--slug` was part of the remedy; measured, the refusal is about the DISPLAY name and fires with `--slug` given. - `is ambiguous — it matches` described a different message (the exact same-name collision, `matches N files that share this name`); the quoted fragment is the SUBSTRING match. F1 — the `from a dirty git work tree` row sent readers to `#exit-code-1` (whose bullet says the guard "degrades rather than enforcing" — the opposite of the no-commits case) and to the top of a 533-line section. It now names the sub-head holding the detail, the house pattern rows 11 and 40 already use. `####`/`#####` anchors are deliberately NOT linked: `readmeHeadingRe` only sees `##`/`###`, so a direct `#what-…` link fails `TestREADMEAnchorLinksResolve` — measured, not assumed. F2 — the two bullets #625 moved under `#### What the packager left out` are properties of the GUARD, not of the exclusion list, and now sit under their own `##### What the dirty-work-tree guard counts as a change`. The heading pays for itself out of the same block, so the cross-section give-back does not grow (6,382 -> 6,377). F5 — the gate warning lived only in the PR body and a doc retired when the arc closes. It is now a comment on `TestAttributionProseCheckAcceptsCorrectProseAndRejectsMisattribution`, with the measured pair: rewording row 20's cell produces 7 `--- FAIL` lines under `-run 'Attribution|Troubleshooting|README|Readme|readme'` and a plain `ok` under `-run 'README|Readme|readme'`. Rows 19 and 20 stay byte-identical; no `##`/`###` heading moved, was renamed, added or removed (74 before, 74 after, diffed). Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SFpMJ3mBc2XygE2EdSigSA
…d stop the intro overclaiming Round 1 on this PR returned no high-severity findings; these are its two 🟡. F2 is a real regression this PR introduced. Compressing the `unexpected response from` row dropped "please open an issue with the snippet" -- the only next step a user has when they hit an undecodable 200 that is NOT one of the two known causes. The replacement read as "this cannot happen to you", and the section footer names only --help and exit codes. Restored, and the row now links Scripting with --json, where the two known decodes are actually documented, instead of Exit code 1, which says nothing about an undecodable body. F1 is self-inflicted: the intro sentence this PR added claimed the third column "links the section that explains it in full", which the compression made false for five rows -- a checkable claim the table breaks. Rows 25 and 26 pointed at Listing media requirements, which contains nothing about revisions (measured: 0 hits for revision|not live in 2319-2392); they now point at After you submit, where the explanation actually lives. Rows 18 and 59 have no better target -- their remedy is in the emitted message -- so the sentence now says what is true of them rather than promising what only most rows deliver.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Phase 3 of the README reduction arc (plan:
claudedocs/readme-reduction-plan.md, #623). The Troubleshooting section becomes a lookup table again: column 1 is the string you got, column 2 is what the message did not tell you, column 3 is where the detail lives.## TroubleshootingREADME.md##/###headingsMean cause cell 469 → 204 bytes. Largest non-frozen cell 2,832 → 611. Per bucket (table rows + header + divider): Credentials 5,965→3,912 · Scaffolding 1,120→636 · Validating and submitting 15,857→8,261 · Generating 3,339→2,351 · Everything else 8,011→3,381.
All 60 rows are still present and column 1 of every one is byte-identical to
origin/main— verified with a positive control (mutating row 1's column 1 is detected).Round-1: the cells that restated the binary
14 cause cells were near-verbatim paraphrases of the error string the CLI had just printed on the line above. Column 2 is pinned against nothing — unlike column 1, which
TestREADMETroubleshootingSymptomsExistInTheSourceholds to the source — so that mirror can drift silently while adding nothing a reader does not already have on screen. Each is trimmed to what the message does not say (the exit code, a cross-command caveat) plus the anchor.Rows trimmed:
cannot derive a slug from·is not valid UTF-8·… and the limit is …·refusing to overwrite. Scaffold somewhere else·there is no open revision to submit·this listing is not live·pass a URL or --clear, not both·the source-repository URL is blank·no such directory …·is not a directory …·refusing to submit without --yes·is ambiguous — it matches·checksum mismatch for·git is required for `civitai app pull`. Column 2 loses 1,103 bytes across the 14.No ROW was removed.
TestREADMETroubleshootingCoversTheRefusalsAuthorsActuallyHitputs 7 rows on an incident floor, and 4 of these 14 are on it:cannot derive a slug from,refusing to overwrite. Scaffold somewhere else,no such directory — pass the path to an App project root,refusing to submit without --yes. That list was re-derived from the test, not carried over.Every retained exit code was measured against the built binary, not derived from the classifier. Rows 15/16/17 exit
2; 18 exits1; 27/29/31/32 exit2; 36 exits1; 56 exits2(local stub for the model-version read); 59 exits1(local stub for the clone-info query). Row 58's exit code is deliberately not claimed —civitai upgradehas no API-base override, so it could not be measured here, and a derived code is not a measured one.Two cells gained a correction the measurement surfaced:
is not valid UTF-8said "Pass--slug, and a--namethat is valid UTF-8". Measured: the refusal is about the display name, which goes intoblock.manifest.jsonverbatim, and it fires with--slugsupplied.--slugis not part of the remedy.is ambiguous — it matchesdescribed a different message — the exact same-name collision, which printsmatches N files that share this name. The fragment the row quotes is the substring match (download.go:647).Source strings were read with
find … -print0 | xargs -0 grepover 136 non-test.gofiles underinternal/,cmd/andpkg/— the repo'sgrepis ugrep and is.gitignore-blind — with a positive control (a string that must exist: 1 hit) and a negative control (a string that must not: 0 hits).Round-1: three other audit findings
The relocated detail was unreachable from the row that sent you there. The
from a dirty git work treerow linked#exit-code-1— whose bullet says the guard "degrades rather than enforcing", the opposite of what agit init-with-no-commits author just saw — and the top of a 533-line section, 275 lines above the two bullets that are the answer. The row now names the sub-head, the house pattern rows 11 and 40 already use.The relocation target was itself a misfile.
#### What the packager left outdocuments theSkipped N path(s)line. The paragraph about the dirty-work-tree guard sharing that exclusion list belongs there; the two bullets after it are properties of the guard, and now sit under their own##### What the dirty-work-tree guard counts as a change. The heading is paid for out of the same block, so the cross-section give-back does not grow: 6,382 → 6,377.The gate warning now ships somewhere durable. It lived only in this PR body and in
claudedocs/readme-reduction-plan.md(#623, retired when the arc closes). It is now a comment onTestAttributionProseCheckAcceptsCorrectProseAndRejectsMisattribution, next to the frozen spans it protects, carrying the measured pair below.Disclosed deletions
Deleted as maintainer history: a reporter credit, a dated measurement, "#422 retired the … refusal", and a preamble paragraph about which tests guard the table.
Two clauses were deleted without being disclosed, and are disclosed now — both from the
the server rejected this store-listing change (400)cell (2,832 → 611):(a revision that exists but was never reordered proves nothing either)— the symmetric twin of the icon parenthetical. The icon half (a listing being re-branded already has an *old* icon, which proves nothing) was carried across into After you submit; this one was not, and is absent from the whole after-README under whitespace-normalised search.#430archaeology clause. The carried-over sentence ends at "…which is also when a livereorderstarted reaching the revision routes at all." The original continued: "before it, a reorder of a live listing could only ever produce this row, because it was addressed to the parent listing while the ids it carried belonged to the open revision."Both are deliberate: restoring them adds bytes to After you submit, one of the five sections this PR already grew, and the audit's own constraint is that the give-back must not grow. Disclosing is the option the audit offered, and it is the one taken.
Two things the plan got wrong, corrected by measurement
1. "The middle column is pinned by nothing" is FALSE. Rows 19 and 20 are pinned. Row 20's cause cell carries exact
strings.Replacespans thatt.Fatalwhen absent — including"because validation reports the row above first. ", with a trailing space. Both cells are additionally prose-parsed for positive/negative command attribution. Both are byte-identical toorigin/main; they are 969 of the remaining bytes.2. The 13,000-byte target was below the floor. Re-measured on the final tree: 6,948 bytes of the section are not cause cells at all — the pinned symptom column, the link column, 60 row delimiters, five bucket headers, the preamble and footer — and the 60 cause cells are 12,234. With rows 19–20 frozen at 969 of those, a 13,000 target leaves ~104 bytes for each of the other 58 cells. Round-1's trim gets the section to 19,182, which is the floor for cells that still say something the binary did not. #623 should be updated to match.
Gates
Negative controls run, not assumed.
internal/cmd/produced1 issues: unused: 1. Removed; tree clean,0 issues.again.never print it→do not emit it): 7--- FAILlines under-run 'Attribution|Troubleshooting|README|Readme|readme', all inTestAttributionProseCheckAcceptsCorrectProseAndRejectsMisattribution, and a plainokunder-run 'README|Readme|readme'. Mutant B — mutate a trimmed row's column 1 (cannot derive a slug from→slugg): reddensTestREADMETroubleshootingSymptomsExistInTheSourceand…CoversTheRefusalsAuthorsActuallyHit, proving the filter reaches the rows round-1 touched. README restored from a checkpoint after each;md5sumidentical.origin/main→a6ebe54it reproduces the audit's own numbers exactly (give-back 6,382 across 5 sections, Troubleshooting 35,250 → 20,229).diffover the extracted##/###list (74 before, 74 after, identical) with a positive control appending a fake heading, which the diff detects.Merged tree
Branched on exit code, never a marker grep.
origin/mainhas moved to7c5a39c(#619) since this branch was cut, so this was re-run, not carried over.merge-tree --write-treeorigin/main(7c5a39c)docs/rank-31-closeddocs/readme-reduction-planzach/585-follow-upThe #602 conflict pre-dates round-1:
a6ebe54× #602 was already rc 1, whileorigin/main× #602 is rc 0. #602 edits thethe server can receiveandWhat this CLI sentrows, which this PR rewrote; round-1 touched neither, so it neither introduces nor widens it. It still needs resolving before either merges, and #602 should be rebased.A real merge was built and tested, not reasoned about.
origin/main(7c5a39c) + this branch in a throwaway worktree:go test ./...21/21 ok,gofmt -s -l .clean,golangci-lint run0 issues, wide filter 97 PASS / 0 FAIL. Worktree removed and its branch deleted.Reported, not done: bucket placement
Validating and submittingis still the largest bucket and about half of it is misfiled — 12 rows are live-listing management or the ready-ack advisory rather than validation or submission;the server can receivesits under Credentials but is a submit-size refusal;rate limited/Civitai returned HTTPare transport, not credentials. A defensible re-sort needs 5###headings moved, which the brief rules out of scope. Left for phase 4, where the reorder lives.