Found by a blind dogfood run against v0.1.90-21-gf56aa72.
Symptom
In the canonical #206 scenario — a scaffold whose civitai-host.js was deleted — the ready-ack advisory lists the reasons it could not resolve the entry graph, and none of them is the actual reason.
$ civitai app create dogstatic --template static -y
$ grep -n script index.html
19: <script src="./civitai-host.js"></script>
20: <script src="./app.js"></script>
$ rm civitai-host.js
$ civitai app validate
⚠ 1 warning(s):
- the manifest declares a "page" surface but nothing in this project's source posts
BLOCK_READY — […] 🔴 What this run did NOT check: it could not resolve the files your
index.html loads (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), so it
checked only whether SOME file in the project mentions BLOCK_READY […]
index.html is at the project root, and it holds a perfectly ordinary reference. The real cause is that the reference points at a file that does not exist — which is neither of the two alternatives offered, and matches none of the three examples.
A user in a 5-file no-build app is sent hunting for a bundler alias that cannot exist.
The behaviour is correct; the message is not
To be clear, this is not a request to change the tiering. AGENTS.md item 20 deliberately treats a reference to a missing file as a gap rather than a decided absence, and explicitly records this exact case as a known trade-off: "deleting the emitter from a current scaffold (dangling <script src>) drops to the presence tier." That reasoning stands.
The defect is that the checker knows why it gapped and does not say so. It resolved ./civitai-host.js, found nothing there, and that is precisely the information the author needs. One sentence — "index.html references ./civitai-host.js, but that file does not exist" — turns the most confusing output in the command into the most useful, on the population the check was written for (#206-era apps).
Second problem: the message is 1938 characters on one unwrapped line
Measured on an 80-column terminal: a single unwrapped block, ~318 words. It contains the mechanism, two remedies, an SDK caveat, a "what this did NOT check" disclosure, a false-negative caveat and an advisory-only caveat. All of it is individually justified — item 18 and item 20 explain why each clause exists — but as one wall it is unreadable at the moment a beginner meets it.
Worth considering: lead with the specific finding (the dangling reference), then the remedy, and let the epistemics follow. The disclosure requirement from item 20 — that the weak tier must state what it did not check — is satisfied wherever the sentence sits, not only when it is inline.
Suggested fix
- When the entry graph gaps because a resolved reference has no file at the target, name the referencing file and the missing target in the advisory. That case is already distinguishable inside
ResolveEntryGraph (it is what sets the gap); it just is not surfaced.
- Keep the tier and the disclosure exactly as item 20 specifies — this changes what the message says, not what the check concludes.
- Consider wrapping / restructuring the advisory so the actionable sentence comes first.
Test coverage this needs
- A rendered
static (and page-vite) scaffold with civitai-host.js deleted must produce an advisory naming both index.html and ./civitai-host.js. Assert the specific strings, not that "a warning appeared".
- The orphan case (emitter present, unreferenced) must keep its current, already-correct message — control.
- A correctly wired scaffold must stay silent — control.
- The weak tier must still carry its "did NOT check that the file is loaded" disclosure (
TestReadyAckAdvisoriesStateTheirOwnStrength already pins this direction; make sure the change does not weaken it).
Found by a blind dogfood run against
v0.1.90-21-gf56aa72.Symptom
In the canonical #206 scenario — a scaffold whose
civitai-host.jswas deleted — the ready-ack advisory lists the reasons it could not resolve the entry graph, and none of them is the actual reason.index.htmlis at the project root, and it holds a perfectly ordinary reference. The real cause is that the reference points at a file that does not exist — which is neither of the two alternatives offered, and matches none of the three examples.A user in a 5-file no-build app is sent hunting for a bundler alias that cannot exist.
The behaviour is correct; the message is not
To be clear, this is not a request to change the tiering.
AGENTS.mditem 20 deliberately treats a reference to a missing file as a gap rather than a decided absence, and explicitly records this exact case as a known trade-off: "deleting the emitter from a current scaffold (dangling<script src>) drops to the presence tier." That reasoning stands.The defect is that the checker knows why it gapped and does not say so. It resolved
./civitai-host.js, found nothing there, and that is precisely the information the author needs. One sentence — "index.htmlreferences./civitai-host.js, but that file does not exist" — turns the most confusing output in the command into the most useful, on the population the check was written for (#206-era apps).Second problem: the message is 1938 characters on one unwrapped line
Measured on an 80-column terminal: a single unwrapped block, ~318 words. It contains the mechanism, two remedies, an SDK caveat, a "what this did NOT check" disclosure, a false-negative caveat and an advisory-only caveat. All of it is individually justified — item 18 and item 20 explain why each clause exists — but as one wall it is unreadable at the moment a beginner meets it.
Worth considering: lead with the specific finding (the dangling reference), then the remedy, and let the epistemics follow. The disclosure requirement from item 20 — that the weak tier must state what it did not check — is satisfied wherever the sentence sits, not only when it is inline.
Suggested fix
ResolveEntryGraph(it is what sets the gap); it just is not surfaced.Test coverage this needs
static(andpage-vite) scaffold withcivitai-host.jsdeleted must produce an advisory naming bothindex.htmland./civitai-host.js. Assert the specific strings, not that "a warning appeared".TestReadyAckAdvisoriesStateTheirOwnStrengthalready pins this direction; make sure the change does not weaken it).