fix(validate): the ready-ack advisory names the reason it fell back, and wraps - #269
Open
ZacxDev wants to merge 2 commits into
Open
fix(validate): the ready-ack advisory names the reason it fell back, and wraps#269ZacxDev wants to merge 2 commits into
ZacxDev wants to merge 2 commits into
Conversation
…and wraps The presence-tier advisory GUESSED at why the entry graph had not resolved — "there is no index.html at the project root, or it holds a reference this CLI cannot follow — a bundler alias, a generated file, an off-project URL" — while `EntryGraph.Gaps` already held the real, per-reference reason and readyack.go discarded it. In the canonical #206 shape (a `static` scaffold whose `civitai-host.js` has been deleted) none of the guesses is true: index.html plainly references a file that is not there. A five-file no-build app sent its author hunting for a bundler alias that cannot exist in it. Issue #258. The gaps are now surfaced GENERALLY rather than special-casing the dangling reference, so all six gap kinds reach the author at once — capped at 3 with the overflow counted out loud, because a silently truncated list reads as "that was all of them". The tiering is unchanged: AGENTS.md item 20's judgement that a missing target is a GAP rather than a decided absence stands. The message was the defect. Second half: `app validate` printed the ~2 kB advisory as ONE 1938-character line. Layout now happens at the printer (internal/cmd/validate_print.go), which fixes every finding rather than the one that provoked it. Wrapping inside the message would have corrupted `--json` — the inverse of item 23: the field comes from the producer, the layout does not. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…p report A mutation found the hole: restoring the shipped speculation to `readyAckAdvicePresenceOnlyHead` while KEEPING the real reasons — the most likely way #258 regresses — reddened 0 subtests, because the absence assertion was scoped to the gap report. `TestPresenceAdviceNoLongerSpeculates` now reads the emitted message at a fixture where every quoted phrase is provably impossible, with a positive control so "says none of the wrong things" cannot be satisfied by a message that says nothing. Records the measurement, the tiering-unchanged boundary and the mutation matrix in AGENTS.md items 18 and 20. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
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.
Closes #258.
The defect
In the canonical #206 shape — a
staticscaffold whosecivitai-host.jshasbeen deleted — the presence-tier ready-ack advisory listed reasons it might have
fallen back, and none of them was the actual reason:
Not one is true of a five-file no-build app. The real reason is that
<script src="./civitai-host.js">points at a file that is not there — andEntryGraph.Gapshad already recorded exactly that, per reference, beforereadyAckChecksreturned the constantreadyAckAdvicePresenceOnlyanddiscarded the slice.
The tiering is unchanged and correct. AGENTS.md item 20 deliberately treats
a reference to a missing file as a gap rather than a decided absence, and
records this case as a known trade. The message was the defect.
The fix
Surface
Gapsgenerally, not the dangling reference specially — so all sixgap kinds (dangling reference, bare specifier, off-project URL, unreadable file,
file budget, depth truncation) reach the author from one change:
; and 2 more this message does not list). A silently truncated list reads as "that was all ofthem" — the same class of lie as the guess it replaced.
"this resolver's model of the project is incomplete", a fact about us.
What sets a gap is untouched — only how it reads.
…PresenceOnlyHeadand…PresenceOnlyTail,before the shared remedy rather than after it: the remedy is the longest
fragment, so appending put the one project-specific sentence two thirds of the
way down a wall of generic advice.
Second half: the 1938-character line
The advisory is ~2 kB and
app validateprinted it as one line. Layout nowhappens at the printer (
internal/cmd/validate_print.go), wrapping everyfinding to 79 columns with a hanging indent — one place fixes every long
message, including ones added later.
Wrapping inside
Finding.Messagewould corrupt--json. This is the inverse ofAGENTS.md item 23: the field comes from the producer, the layout does not.
wrapRunesis reused as-is fromexitcodes_doc.go(same package — no export,no edit to that file).
Mutation matrix
--- FAILleaf lines counted from output (never an exit code); every mutationchecksum-gated, so an edit that silently failed to apply aborts instead of
reading as a survivor.
--jsonguard)🔴 One mutant survived the first round and is why an assertion moved.
Restoring the guess to
…PresenceOnlyHeadwhile keeping the real reasons —the most likely regression — reddened 0 subtests, because the absence check
was scoped to the gap report.
TestPresenceAdviceNoLongerSpeculatesnow readsthe whole emitted message at a fixture where every quoted phrase is provably
impossible, with a positive control that the real cause is present so "says none
of the wrong things" is not satisfied by a message that says nothing.
TestReadyAckAdvisoriesStateTheirOwnStrengthstill passes and still can failin both directions (K: 2, L: 1 above). It reads the FIXED bases, so it
structurally cannot see text appended at runtime —
TestGapReportCannotSatisfyAnotherTiersStrengthAssertioncovers that, and killsthe "report leaks
orphan" mutant the strength test cannot.Coverage
staticandpage-vitewith the emitter deleted: the report names thereferencing file (
index.html/src/main.jsx), the specifier and themissing target — asserted on the gap section, not the whole message, since
the shared remedy names
index.htmlin every tier and a whole-messageContainswould be vacuous.no root
index.html, plus an off-project URL.readyAckAdviceUnwired; all shipped templatesstay silent; the strong tiers never acquire the gap apparatus.
--jsonis asserted on the decodedmap[string]any(aContainsoverraw stdout cannot tell a real newline from the
\nescape).make ci--- FAIL: 0 ·build failed: 0 · 18 packagesok·gofmt -s -l .clean over 299
.gofiles (count quoted as the positive control).🤖 Generated with Claude Code