RESTATED 2026-08-31 — the original shape was wrong and @tobiu killed it correctly. This was filed as "expose the freshness inspector as a standalone npm run check-themes". That premise does not survive one question. The command, its spec, its package script and its Contract Ledger are all withdrawn; what remains is the documentation gap, which is the only part that was ever real. Original framing preserved below the fold for the record.
Context
Neo's development mode serves JS from source (native ES modules, always current) and CSS from a built dist/ (only as fresh as the last theme build). A stale build therefore renders current JS against an older stylesheet — confidently wrong, and the first suspect is always product code.
That has cost real diagnosis time three times: twice on 2026-07-21 (recorded in #15666's Context) and again in #17890, where eight candidate causes were eliminated in source before the build was suspected.
The Problem — it is a documentation gap, not a tooling gap
There is a workflow that makes the stale state impossible, and it was never written down:
npm run build-themes on a fresh checkout, and after any pull or branch switch that brings someone else's SCSS — the compiled CSS is gitignored, so it never travels.
npm run watch-themes before editing SCSS, left running — it recompiles what you touch, so the build cannot fall behind your sources.
Measured, both directions:
| tree state |
npm run watch-themes |
| stale |
throws — names every stale/missing output and prints DEVELOPMENT_THEME_BUILD_COMMAND, non-zero exit (assertThemeWatcherReady) |
| fresh |
starts watching |
So on the case that matters, watch-themes already is the freshness check, with the same information and the same remedy. All three incidents were people who did not know the workflow — including the agent diagnosing the third.
Why the original prescription was withdrawn
It proposed a standalone read-only query on the premise that "there is no way to ask the inspector a question without starting a server, a watcher, or a test suite." Literally true; practically irrelevant. Nobody needs to ask the question, because the workflow prevents the state. A diagnostic for a state that should not exist is worse than none — it implies the state is expected, and it competes with the habit that actually prevents it.
#15585 (watchThemes: handle add/rename/delete events) is CLOSED/COMPLETED, so the watcher now handles rename as well as change; the July limitation that would have argued for a separate query no longer holds either.
The Fix
Document the workflow in learn/guides/uibuildingblocks/StylingAndTheming.md §3, where the build-vs-source mental model forms. No new command, no new script, no new detection logic.
Acceptance Criteria
Out of Scope
- Any new command. That was the error this restatement corrects.
- Changing how themes are built, or making a server rebuild automatically.
- Wiring theme materialization into the unit suite — it renders nothing and has no
globalSetup.
Avoided Traps
- Building a detector for a state a workflow prevents. The tooling was complete; the habit was undocumented. Asking "what workflow makes this not happen?" before "what detects it?" would have produced this ticket directly.
- Sweeping only GitHub for prior art. A dup sweep over issues found
#15666 and correctly avoided a duplicate ticket — but the operator's workflow rationale lived in Memory Core, never in a ticket. A GitHub sweep answers does a ticket exist; an MC sweep answers what did we decide, and why. The second one was skipped.
Related
#15666 — dev-server warning (CLOSED/COMPLETED).
#15585 — watcher add/rename/delete coverage (CLOSED/COMPLETED).
#15449 — materialize fresh development themes before source-mode e2e.
#17890 — the third occurrence and the worked example.
Origin Session ID: 56bc214a-5b55-41a2-848a-cdfa372abbcd
Retrieval Hint: "build-themes once then watch-themes before editing scss; stale dist renders old CSS against new JS"
Context
Neo's development mode serves JS from source (native ES modules, always current) and CSS from a built
dist/(only as fresh as the last theme build). A stale build therefore renders current JS against an older stylesheet — confidently wrong, and the first suspect is always product code.That has cost real diagnosis time three times: twice on 2026-07-21 (recorded in
#15666's Context) and again in#17890, where eight candidate causes were eliminated in source before the build was suspected.The Problem — it is a documentation gap, not a tooling gap
There is a workflow that makes the stale state impossible, and it was never written down:
npm run build-themeson a fresh checkout, and after any pull or branch switch that brings someone else's SCSS — the compiled CSS is gitignored, so it never travels.npm run watch-themesbefore editing SCSS, left running — it recompiles what you touch, so the build cannot fall behind your sources.Measured, both directions:
npm run watch-themesDEVELOPMENT_THEME_BUILD_COMMAND, non-zero exit (assertThemeWatcherReady)So on the case that matters,
watch-themesalready is the freshness check, with the same information and the same remedy. All three incidents were people who did not know the workflow — including the agent diagnosing the third.Why the original prescription was withdrawn
It proposed a standalone read-only query on the premise that "there is no way to ask the inspector a question without starting a server, a watcher, or a test suite." Literally true; practically irrelevant. Nobody needs to ask the question, because the workflow prevents the state. A diagnostic for a state that should not exist is worse than none — it implies the state is expected, and it competes with the habit that actually prevents it.
#15585(watchThemes: handle add/rename/delete events) is CLOSED/COMPLETED, so the watcher now handlesrenameas well aschange; the July limitation that would have argued for a separate query no longer holds either.The Fix
Document the workflow in
learn/guides/uibuildingblocks/StylingAndTheming.md§3, where the build-vs-source mental model forms. No new command, no new script, no new detection logic.Acceptance Criteria
build-themeson a fresh checkout and after incoming SCSS,watch-themesbefore editing.server-startfreshness warning is a dev-server feature no other static host provides.dist/.Out of Scope
globalSetup.Avoided Traps
#15666and correctly avoided a duplicate ticket — but the operator's workflow rationale lived in Memory Core, never in a ticket. A GitHub sweep answers does a ticket exist; an MC sweep answers what did we decide, and why. The second one was skipped.Related
#15666— dev-server warning (CLOSED/COMPLETED).#15585— watcher add/rename/delete coverage (CLOSED/COMPLETED).#15449— materialize fresh development themes before source-mode e2e.#17890— the third occurrence and the worked example.Origin Session ID: 56bc214a-5b55-41a2-848a-cdfa372abbcd
Retrieval Hint: "build-themes once then watch-themes before editing scss; stale dist renders old CSS against new JS"