- Markup is the image-generation fallback only when markup can carry the
dimension honestly. A photographic or painterly direction authored as
markup fakes exactly what is being judged, contradicting the organizing
rule; that path now reports the missing capability instead.
- The recap carries the prototype path only when the run left one behind.
An overlay run undoes its edits and leaves nothing, so the unconditional
wording handed the next skill a dangling reference. Fixed in SKILL.md and
in the matching write-back sentence this PR added.
Claude-Session: https://claude.ai/code/session_01KzLbr589npfw9AJezV3mwv
The implementation-ready unified plan this branch executes, kept as the
decision record for why the routing predicate was consolidated and why
ownership stops at the skill boundary.
Claude-Session: https://claude.ai/code/session_01KzLbr589npfw9AJezV3mwv
Code review found five defects the earlier passes missed.
The Phase 2 approach step offered ce-prototype for a Rule 7 decision and then
independently offered the visual probe, because its second sentence had lost
the not-Rule-7 conjunct — two incompatible routes for one decision.
The web-default guard matched "default", "substrate" and "web" anywhere in the
body, so "Default substrate is the product stack, not the web, whatever the
product is written in" satisfied every assertion while reversing the rule.
Bound the checks to the sentence that states the rule and reject a negated or
product-stack-first form. Verified: the reversing string now fails the guard.
preview.md still carried "a question that has to be used to be decided" — a
live paraphrase of the retired predicate that the exact-string guard cannot
see. The substrate paragraph authorized a non-browser medium and then closed
with an unconditional "do not introduce another display mechanism", negating
the branch it had just permitted. And CONCEPTS.md promised the artifact
survives the run where the overlay path says nothing survives.
Claude-Session: https://claude.ai/code/session_01KzLbr589npfw9AJezV3mwv
slice(start, -1) does not throw or return empty — it returns everything up to
the last character. So a missing "## " heading silently widened the spine to
the whole document and turned the placement assertion into a presence check
the neighbouring assertion already covered. Proven on a synthetic SKILL.md
with the rule buried under a heading: the test passed green.
Guard the heading index explicitly, and take the frontmatter boundary from the
shipped parseFrontmatter helper rather than re-deriving it with two coupled
magic offsets that also broke under a CRLF checkout. Pin the derivation clause
to the spine as well, matching R1, and correct one failure message that said
"spine" while its assertion scanned the whole body.
Both tightened pins were re-verified to fail against the pre-change bytes.
Claude-Session: https://claude.ai/code/session_01KzLbr589npfw9AJezV3mwv
The glossary and the four user-facing surfaces still defined the skill by
driving: CONCEPTS.md called a visual probe "not something you click through
to feel an interaction", and the skill page keyed its TL;DR on a decision that
"has to be used, not inspected". Both describe the boundary this change
retired.
Reconcile all five with what shipped — experience by driving or by seeing at
real finish, one organizing rule governing modality/fidelity/medium, the
sketch-insufficiency routing test, throwaway as unmaintained rather than
discarded, and the web default substrate.
Section structure and heading numbering are unchanged.
Claude-Session: https://claude.ai/code/session_01KzLbr589npfw9AJezV3mwv
Nothing guarded the invariant this change establishes, which is why the
drive-versus-look-at predicate spread to nine statements across three skills
before anyone noticed it disagreed with the fidelity test beside it.
Pin the organizing rule and the web-default floor in ce-prototype's spine,
and the sketch half plus the unravel-cost precondition in Interaction Rule 7.
Add a negative assertion that no skill file reintroduces any of the four
retired wordings.
The negative assertion matches exact phrases rather than a semantic pattern
on purpose: ce-prototype's spine deliberately keeps a contrast pair reading
"settled by driving it, so a screen that only looks like the product does not
answer it", which describes the dimension under test rather than a route. A
looser pattern fires on it.
Every new assertion was verified to fail against the pre-change bytes at
a27aa2af; the negative assertion finds five offender files there and none on
this tree.
Claude-Session: https://claude.ai/code/session_01KzLbr589npfw9AJezV3mwv
Both post-plan handoff menus gated the ce-prototype option on a question that
"requires use, not inspection", so a plan whose only open question was a
visual treatment choice had that option filtered out — at the entry point
people most often reach the skill from.
Ownership stops at the skill boundary: a skill cannot reference another
skill's files and a ce-plan run never loads ce-brainstorm's spine, so the
menu states the test itself rather than citing Rule 7 across skills.
plan-handoff.md cites the menu, which it can resolve.
Claude-Session: https://claude.ai/code/session_01KzLbr589npfw9AJezV3mwv
The skill stated when ce-prototype applies at seven places using two
incompatible tests. visual-probes.md routed on fidelity in its Trigger and on
drive-versus-look-at four lines later in its gate, while claiming the second
restated the first — so a question settled by seeing at real finish had two
conflicting routes and a false pointer between them.
Rule 7 now states the test once and every other site cites it: the gate, Rule
4's exception, the approach-comparison route, both visual-probes sites, and
both handoff-menu statements. The test is unravel cost AND sketch
insufficiency, with finish and motion named as dimensions a rough sketch
strips by definition. Unravel cost stays a precondition so a cheap-to-reverse
decision does not escalate however visual it is, and the routine-UI exclusion
gains its visual analogue.
The gate keeps its non-firing branch — deleting that clause wholesale would
have made it fire on decisions routed straight to prototype, the wasted round
this change exists to remove.
Claude-Session: https://claude.ai/code/session_01KzLbr589npfw9AJezV3mwv
The description excluded "look at a sketch" outright, so the skill would not
activate on a question whose dimension is visual — exactly the case the
widened boundary now covers. Activation and execution fail independently: a
correct body is useless if the skill never runs.
Key the trigger on whether a cheap sketch can settle the question rather than
on whether the user drives the artifact, and keep the adjacent negatives that
send rough probes, scoping work, polish, and real implementation elsewhere.
Claude-Session: https://claude.ai/code/session_01KzLbr589npfw9AJezV3mwv
The skill separated size from finish correctly but drew its own boundary on
the wrong axis: it was worded around interaction throughout, so a question
settled by seeing at real finish had nowhere to go. The cheap visual-probe
tier refuses those as too polished; this skill refused them as look-at.
Elevate "do not fake the dimension being tested" into the spine and derive
modality, fidelity, and medium from it, absorbing the four competing
statements rather than qualifying them. Add the web-default floor: web is
the substrate whatever the product is written in, yielding only when the
user names a technology or the dimension cannot be rendered in a browser
without faking it.
Throwaway now means unmaintained and unshipped rather than discarded — the
prototype stays as a reference for the implementation that follows, on a
best-effort basis, with the overlay path exempt because those edits are
undone. A recap with no Product Contract to write back to is a complete
outcome, not a degraded one.
Claude-Session: https://claude.ai/code/session_01KzLbr589npfw9AJezV3mwv