Commit Graph

18 Commits

Author SHA1 Message Date
David Bosschaert ecd1e2b2c4 fix(stardust): fix opening prototyped pages from SLICC browser plugin (#152)
* fix(stardust): fix opening prototyped pages from browser plugin

Use `open <vfs-path>`, not `playwright-cli open`, for prototype
previews.

VFS-backed prototype files must be opened with the `open` shell
command so the preview service worker resolves the path.
`playwright-cli open` bypasses the worker and yields FILE NOT
FOUND. Update prototype and uplift SKILL.md to spell this out.

* chore: remove multiple files detail
2026-05-26 08:36:54 +01:00
Paolo Mottadelli 07aa1f4211 fix(stardust): close 3 Tessl orphaned-reference warnings (#151)
Closes three low-risk Tessl skill-review orphan warnings.

- distill/SKILL.md: added a `## References` section listing the two
  reference files (samples-brief-format.md, trait-matrix-schema.md).
  distill was the only skill without a References section.
- prototype/SKILL.md References: added the four cinematic motion docs
  (motion-registers.md, motion-stack.md, motion-attributes.md,
  motion-runtime.md) alongside motion-validation.md.
- prototype/SKILL.md References: switched 7 cross-skill paths from
  `skills/stardust/reference/X.md` (absolute-style, unresolvable by
  Tessl) to `../stardust/reference/X.md` (the convention already
  used by stardust/SKILL.md and uplift/SKILL.md).

No behavior changes — additive + path-correctness fixes.

🤖 Generated with [Claude Code](https://claude.com/claude-code)
2026-05-24 22:54:38 -07:00
Paolo Mottadelli 07fa21891a feat(stardust): 0.7.1 → 0.10.0 — distill, cinematic motion, uplift orchestrator (#149)
Stacks three minor versions on the `redesign-adobecom` branch.

## 0.8.0 — Original `redesign-adobecom` changes
- NEW skill: `distill` — analyze HTML mockups + website URLs and produce a structured style guide; anchors `direct` under Mode B.
- Motion validation gate (Phase 2.8 on `prototype`) — clipped-container reveal timing, animation-range vs reading position, anim-enter trigger reachability, reduced-motion override completeness, no-JS fallback, multi-viewport scroll-driven checks.
- Surface forks formalized as parent-direction tuning under reimagined mode.
- Journal rule + recursive validate-and-fix loop promoted to master skill.
- HTTP/2 / Akamai bypass: route-fulfiller pattern in playwright-recipe.

## 0.9.0 — Cinematic motion feature
- `prototype --cinematic` (and `--cinematic=<register>`) — layers a brand-faithful motion register on the static prototype. Output is `<slug>-cinematic.html` alongside the static `<slug>-proposed.html`.
- Five motion registers as a closed catalog (`arrival`, `kinetic-display`, `live-systems`, `editorial`, `kinetic-grid`).
- Lenis bundled at `skills/prototype/assets/motion/` (MIT, ~17 KB). No GSAP / Framer / Theatre.js.
- Motion `data-*` vocabulary: `[data-anim]`, `[data-tile-anim]`, `[data-countup]`, `[data-flip]`, `[data-fill]`, `[data-split]`, `[data-parallax]`.
- Canonical inline runtime at `prototype/reference/motion-runtime.md`.
- Six cinematic-mode validation gates (Pass 6): Lenis bootstrap, reduced-motion fallback, scroll-jack check, three-position screenshot pass, register-match audit, motion C-cliff detector.
- `direct` writes `extensions.motion.register` from PRODUCT.md Brand Personality. For multi-variant runs the register lives in per-variant `DESIGN-<id>.json`.

## 0.10.0 — `/stardust:uplift <URL>` one-shot presales orchestrator
- NEW skill: `uplift` — produces three differentiated variants (A faithful + improvements, B "what if we amplified `<captured trait>`?", C "what if motion was part of the identity?" — fully cinematic) without further user coordination.
- Closed catalog of 8 "what if…" captured-trait amplification candidates with disqualification clauses.
- Load-bearing artifacts: `uplift-improvements.md` (5 specific weaknesses) and `uplift-questions.md` (catalog walk + picks + disqualifications).
- Delegates to extract → direct → prototype with no new flags on the underlying skills.

## Plugin metadata
- `tile.json` bumped 0.8.0 → 0.10.0; registers `uplift` + `prepare-migration` (the latter a pre-existing gap closed).
- `.claude-plugin/plugin.json` bumped 0.9.0 → 0.10.0.

## Backward compatibility
All existing sub-commands unchanged. Motion is opt-in via `--cinematic`. `uplift` is a new entry point with no parallel render path — it delegates to existing skills. Existing project trees gain new artifacts only when the new flags / skills are engaged.

🤖 Generated with [Claude Code](https://claude.com/claude-code)
2026-05-24 22:25:46 -07:00
Paolo Mottadelli 1ab6833f1e fix(stardust): make migrate output genuinely zip-and-deploy portable (#133)
* fix(stardust): make migrate output genuinely zip-and-deploy portable

The 0.7.0 contract claimed "self-contained, zip-and-deploy" but
emitted root-absolute paths (/assets/..., /beers/) plus
directory-only nav links. Those work on a webserver at the host
root only — they 404 on file:// and at any subpath. This PR
delivers what the claim promised:

- Output path is URL-literal: /beers/ -> beers/index.html,
  /about-us/history.html -> about-us/history.html. No more
  synthesizing /about/index.html from a slug.
- Page map (state.json.migrate.pageMap[]) built once per run;
  per-page rendering and internal-link rewriting both consume it.
- Reference shape is depth-aware relative: prefix is ./ for
  depth-0 pages, ../ * depth otherwise. Works on file://, at
  host root, and at any subpath without rewriting.
- Phase 3 broadens the self-containment check into a full
  portability audit: refuses absolute internal refs, refuses
  directory-only nav, runs the new pageMap + file:// fixtures.
- New fixtures: file-protocol-audit.mjs (Playwright file://
  round-trip) and pagemap-audit.mjs (static pageMap consistency).
- asset-bundling.md and migrate-output-format.md aligned to the
  new depth-aware-relative shape; state.json contract gains
  pageMap[].

Plugin bumped 0.7.0 -> 0.7.1.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* review: fix four flagged correctness issues

- Directory-only-nav regex now catches `./beers/` (the cited example).
  Old pattern required a-z as first char; `./beers/` starts with `.`
  and would have slipped through. New pattern accepts ./, ../, /, or a
  bare segment, and excludes scheme-bearing URLs (no false positive
  on https://google.com/).
- Add a second grep for absolute url() references inside inline style
  attrs and <style> blocks (and CSS files); the original href/src grep
  missed these.
- SKILL.md Outputs row no longer claims the sidecar lives at
  <source-url-path>/_meta.json (nonsense for .html-leaf pages).
  Replaced with a row that points at the canonical sidecar rule.
- migration-procedure.md § Page map now explicitly says same-origin
  absolute URLs are stripped to their path portion before pageMap
  lookup (per content-preservation.md § Internal link rewriting),
  closing the loophole that would let <a href="https://origin/foo/">
  pass through verbatim.

Regex patterns verified against a test fixture before commit.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* review: update migrate-self-contained-bundle eval to 0.7.1 contract

The eval was pinned to 0.7.0's root-relative /assets/<subpath>
shape. This PR's contract change to depth-aware relative paths
would have made the eval fail against correct 0.7.1 output.

- detection_src_href criterion now asserts <prefix>assets/<subpath>
  (not /assets/<subpath>).
- Renamed prefix_resolution_root_relative -> prefix_normalises_authoring;
  description flipped from "reference is left as-is" to "authoring
  is normalised to the depth-aware emit form".
- Added 4 new criteria: depth_aware_paths (6pts),
  pagemap_constructed (6pts), internal_links_via_pagemap (5pts),
  portability_audit_passes (13pts).
- Setup uses real source URLs that exercise the URL-literal rule:
  /, /beers/, /about/history.html (preserve .html leaf),
  /docs/api/ (depth-2 nested).
- Prototype HTML now carries internal nav in three authoring styles
  (root-absolute, same-origin absolute, directory-only) plus a
  broken-link case, exercising the page map rewrite.
- Run 1 expected behavior rewritten to expect depth-aware emission
  ('./assets/...'), pageMap built before render, broken-link
  flagging, and the 6-step portability audit passing.
- Run 4 (cross-page dedup) updated so the second page emits its
  shared asset with its own '../' prefix while the underlying file
  on disk is a single copy.
- Weights re-balanced to sum to 100; portability_audit_passes gets
  the largest weight (13pts) since it backs the contract claim.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-14 03:29:23 -07:00
Paolo Mottadelli 27dd06341c feat(stardust): migrate produces self-contained zip-and-deploy bundle (#132)
* feat(stardust): migrate produces self-contained zip-and-deploy bundle

Bundles every referenced asset into stardust/migrated/assets/ and
rewrites HTML/CSS references to root-relative /assets/<subpath> so
the migrated tree is fully self-contained. Adds asset-bundling
reference (six detection shapes, nine edge cases), output-format
contract with state.json.migrate block (selfContained: true),
--clean and --pin-timestamp flags, and an eval covering the six
acceptance criteria.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* review: fix count, --clean correctness, document asset-missing rename

- Bump totalAssetsBundled 6 → 7 in eval task.md (matched bundledAssets[] length).
- --clean now implies --force so the bundledAssets Set is the complete
  union across every page; idempotent-skipped pages' assets are no
  longer at risk of being deleted as stale. Updated SKILL.md flag
  description, asset-bundling.md § Stale asset cleanup, the
  Idempotent-skip interaction note, and the eval's run-3 expected
  behaviour + criterion.
- Document the contentDeviations / migrationDecisions kind rename
  from "media-missing" to "asset-missing" in
  migrate-output-format.md § Backwards compatibility — consumers
  should accept either string until they migrate.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* chore(stardust): bump plugin version 0.6.0 → 0.7.0

Self-contained zip-and-deploy bundle is a minor-version addition:
new --clean and --pin-timestamp flags, new state.json migrate
block (forward-compat), new asset-bundling reference contract,
provenance kind rename (media-missing → asset-missing).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* chore(stardust): bump palette library version v0.6.0 → v0.7.0

Keep the palette library version aligned with the plugin version.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-13 12:32:30 -07:00
Paolo Mottadelli bfe537dbdd feat(stardust): ia-fidelity axis + 10 non-slop disciplines + approval fold-back (#131)
Coordinated three-part change: Part I adds a strategic ia-fidelity
axis pinned at direct time (verbatim → A1/A2/A3 surface forks vs
reimagined → A+B+C role-differentiated). Part II adds 10 disciplines
at three phase boundaries (brief-time 1-5, craft-time 6-8, quality
gates 9 + convergence detector 10) with the four wasatch dry-run
friction carve-outs folded in. Part III lands Phase 5 approval
fold-back (site-wide / page-local / don't-fold) with verbatim no-op
gating. Also sweeps remaining Phase 5.5 → 2.7 references across the
plugin docs.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-13 09:44:12 -07:00
Paolo Mottadelli 5d47099881 feat(stardust)!: sweep — drop doctor, fossils, opt-out flags, live integration
* feat(stardust)!: sweep — drop doctor.md, F-NNN fossils, opt-out flags, live integration

Four related cleanups bundled. Each independently small; together
they shrink the docs by ~600 lines and remove three doc-rot
patterns at once.

1. Delete doctor.md (493-line spec for an unimplemented script).
   The Festool-incident concerns it was scoped to are now handled
   by concrete write-time contracts (validateProvenance, content-
   sourcing hierarchy, anti-toolbox audit). No external references.

2. Drop F-NNN feedback fossils + version-changelog paragraphs.
   STARDUST-FEEDBACK.md doesn't exist in the plugin; the F-001 /
   F-002 / F-009 / F-015 / F-016 / F-018 citations were opaque
   tribal vocabulary. Kept the rules they cited; dropped the
   IDs. divergence-toolkit.md changelog paragraphs (v0.1 → v0.2,
   v0.4 → v0.5, v0.5 → v0.5.1) collapsed.

3. Slim flag surfaces. Every --no-* / --skip-* / --allow-* /
   --refresh-stale flag dropped from prototype and migrate; the
   underlying quality gates are now mandatory. Manual chat
   overrides ("ship as-is", "accept the P1 findings") remain
   available and are recorded in _provenance verbatim.

   prototype flags: 10 → 5 (<slug>, --all, --prep, --canon-from,
   --publish-sample).
   migrate flags: 8 → 5 (<slug>, --all, --force, --require-approved,
   --strict-canon).

4. Drop the impeccable:live integration. Live was documented as
   the "default" iteration path but wasn't used — chat-driven
   command invocation is the actual default. Phase 4 collapses
   from 6 steps to 3 (open file → mark prototyped → report).
   Iteration paths drop from 3 to 2 (chat-driven, direct
   invocation). Live remains usable as an external tool the user
   invokes directly against the proposed file; stardust no
   longer pretends to drive its poll loop.

BREAKING CHANGE: prototype no longer accepts --no-iterate,
--no-critique, --skip-adapt-audit, --adapt-variant, --no-hamburger,
--refresh-stale, or --no-impeccable. migrate no longer accepts
--refresh-stale, --allow-placeholder, or --skip-adapt-audit.
The mobile-adapt audit, content-sourcing scan, placeholder gate,
and critique + audit pass are now mandatory; manual chat overrides
replace the flag-based bypasses.

The live driver loop (Phase 4 steps 4-6: config.json setup, event
streaming, carbonize cleanup, iteratedVia: impeccable:live
provenance) is gone. The proposed file's iteratedVia provenance
now records the named impeccable commands run against the file,
not a live sessionId.

stardust bumped to 0.6.0.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* chore(stardust): sync tile.json version to plugin.json (0.6.0)

The tile manifest's version was stuck at 0.1.0 while the plugin
moved to 0.6.0. Keep them in sync so tessl-side catalog metadata
matches the marketplace.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-13 02:31:08 -07:00
Paolo Mottadelli 33dd9037f3 stardust: mobile-nav collapse + drop before/after viewer (#127)
* stardust: mobile-nav collapse pattern + drop before/after viewer

Two related changes to stardust:prototype landing together.

Mobile-nav collapse (additive):
- New stock CSS-only hamburger pattern auto-applied by Phase 5.5
  when the Mobile-adapt audit refuses at 360px (overflow,
  sub-11px nav font, or sub-10px nav gap).
- New audit conditions documented in skills/prototype/SKILL.md
  § Mobile-adapt audit; checked at runtime via the Playwright
  snippet at skills/prototype/fixtures/mobile-nav-audit.mjs.
- Stock pattern doc at skills/prototype/reference/mobile-nav-collapse.md
  carries the copy-pasteable HTML+CSS+JS, the ARIA checklist,
  the post-injection source-order check, --no-hamburger opt-out,
  and the alternative-pattern vocabulary.
- New data-nav-collapse="hamburger" attribute (v2.2 additive) on
  <header> when the pattern is applied.
- Positive + negative fixtures verify the audit end-to-end.

Drop the per-page before/after viewer:
- Phase 3 (Compose the viewer) removed; the proposed file is
  opened directly in the browser.
- Approval is now chat-only: "approve <slug>" or "approve".
- skills/prototype/reference/before-after-shell.md renamed to
  proposed-file-shell.md and stripped to the proposed-file
  contract only (viewer half, iframe resolution chain, action
  buttons, and stash mechanic all dropped).
- state-machine.md prototypePath repointed at -proposed.html;
  doctor.md D-104 pairs -proposed.html with -shape.md;
  artifact-map.md drops the <slug>.html row; publish-sample.md
  simplifies variant discovery (no more "is not the viewer"
  disambiguation); evals/prototype-before-after rewritten to
  expect a single proposed file.

BREAKING CHANGE: stardust:prototype no longer composes the
before/after viewer at stardust/prototypes/<slug>.html.
Anyone scripting on top of that file existing on disk should
switch to stardust/prototypes/<slug>-proposed.html (the
prototypePath in state.json now points there directly). The
approval gesture moves from the viewer's Approve button to a
chat-only "approve <slug>" / "approve".

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* stardust: bump version to 0.5.0

Minor bump for the breaking change in 370a208 (drop before/after
viewer; chat-only approval). Pre-1.0 semver: minor bump signals
a breaking change without claiming API stability.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-13 00:06:20 -07:00
Paolo Mottadelli 2da4f830ad stardust: fix dependencies schema to use name@marketplace string (#126)
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-12 12:21:32 -07:00
Paolo Mottadelli 90be5b7bf2 stardust: fix cross-marketplace dep reference to impeccable
The `marketplace` field in plugin dependencies and the
`allowCrossMarketplaceDependenciesOn` allowlist must use the
marketplace's `name` (`impeccable`), not its GitHub repo path
(`pbakaus/impeccable`). The mismatch caused Claude Code to flag
the stardust plugin manifest as invalid on install.

Bumped to 0.4.1.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-12 21:11:48 +02:00
Paolo Mottadelli 69068cee1c stardust: bump version to 0.4.0
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-12 20:53:32 +02:00
Paolo Mottadelli 48ec3970ef stardust: close open clusters + declare cross-marketplace impeccable dep (#120)
* feat(stardust): close open clusters — publish-sample URL, mobile-adapt phase, critique+audit, add-variant

Four items from the 2026-05-05 review session covering UPS F7+F9,
NVIDIA F8, and dogfood-feedback 2026-05-03-a / JFK F14. All four
shipped together because they overlap in the same SKILL files.

- publish-sample showcase URL fix (UPS F9): the printed URL pattern
  pointed at a route that doesn't exist (samples/<slug>/), so every
  published sample carried a broken link in the PR body and final
  report. Updated to the actual single-page-viewer route
  (samples/brand.html?slug=<slug>#<variantId>) and synced the upstream
  default to paolomoz/stardust-site.

- Mobile-adapt as a pipeline phase (dogfood-feedback 2026-05-03-a +
  JFK F14): new prototype Phase 5.5 runs $impeccable adapt against
  the approved variant on every approval; mobile-adapt audit at
  prototype, migrate, and publish-sample refuses files with no
  <meta viewport>, zero @media (max-width: ...) rules, or no
  mobile-targeted breakpoint at <= 640px. --skip-adapt-audit escape
  hatch threads through all three. Closes the failure mode where
  the lovesac.com showcase shipped variant B to mobile visitors with
  bracket motif crowding, overflowing trust band, and no hamburger.

- Phase 2.5 critique + audit (NVIDIA F8): renamed from "Validate via
  critique" to "Validate via critique + audit"; runs both impeccable
  validators in parallel and gates prototyped status on P0/P1 from
  either. Added brand-faithful inversion auto-dismiss against
  DESIGN.json#extensions.divergence.brand_faithful_inversions[] so
  Mode A renders don't drown the report in known false positives
  (Arial fallback flagged as overused-font, eyebrow uppercase as
  all-caps body, etc.). publish-sample's submitter checklist updated
  to cover both validators.

- direct --add-variant <name> (UPS F7): incremental variant addition
  against the existing direction without re-running Phase 1 reasoning
  or stale-flagging existing prototypes. Procedure documented; per-
  field inheritance rules table specifies what's pinned (palette,
  typography, IA-priorities), what extends (componentStyle, divergence
  inversions), and what's variant-local (narrative, voice DOs, the
  amplified-trait anchor). Fixes the workflow where variant A ships,
  user later asks for B and C, and --re-direct is too heavy.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* chore(stardust): declare cross-marketplace dependency on impeccable

Whitelist pbakaus/impeccable in marketplace.json and declare it as a
dependency in stardust's plugin.json so stardust can formally depend on
the impeccable plugin hosted in a different marketplace.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-11 20:44:58 -07:00
Robert Munteanu eb78c8a148 fix(stardust): fix tile.json to pass tessl-lint (#116)
- Add missing version/summary fields and convert skill paths from strings
to objects to match the required tile.json schema.
- tessl-lint rejects colons in skill names; only lowercase letters,
numbers, and hyphens are allowed.
- Skill keys must match the name field in each SKILL.md; drop the
stardust- prefix since the SKILL.md files declare short names.

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-08 17:33:48 +02:00
Paolo Mottadelli 5bb2150e37 feat(stardust): close open clusters — publish-sample URL, mobile-adapt phase, critique+audit, add-variant (#113)
Four items from the 2026-05-05 review session covering UPS F7+F9,
NVIDIA F8, and dogfood-feedback 2026-05-03-a / JFK F14. All four
shipped together because they overlap in the same SKILL files.

- publish-sample showcase URL fix (UPS F9): the printed URL pattern
  pointed at a route that doesn't exist (samples/<slug>/), so every
  published sample carried a broken link in the PR body and final
  report. Updated to the actual single-page-viewer route
  (samples/brand.html?slug=<slug>#<variantId>) and synced the upstream
  default to paolomoz/stardust-site.

- Mobile-adapt as a pipeline phase (dogfood-feedback 2026-05-03-a +
  JFK F14): new prototype Phase 5.5 runs $impeccable adapt against
  the approved variant on every approval; mobile-adapt audit at
  prototype, migrate, and publish-sample refuses files with no
  <meta viewport>, zero @media (max-width: ...) rules, or no
  mobile-targeted breakpoint at <= 640px. --skip-adapt-audit escape
  hatch threads through all three. Closes the failure mode where
  the lovesac.com showcase shipped variant B to mobile visitors with
  bracket motif crowding, overflowing trust band, and no hamburger.

- Phase 2.5 critique + audit (NVIDIA F8): renamed from "Validate via
  critique" to "Validate via critique + audit"; runs both impeccable
  validators in parallel and gates prototyped status on P0/P1 from
  either. Added brand-faithful inversion auto-dismiss against
  DESIGN.json#extensions.divergence.brand_faithful_inversions[] so
  Mode A renders don't drown the report in known false positives
  (Arial fallback flagged as overused-font, eyebrow uppercase as
  all-caps body, etc.). publish-sample's submitter checklist updated
  to cover both validators.

- direct --add-variant <name> (UPS F7): incremental variant addition
  against the existing direction without re-running Phase 1 reasoning
  or stale-flagging existing prototypes. Procedure documented; per-
  field inheritance rules table specifies what's pinned (palette,
  typography, IA-priorities), what extends (componentStyle, divergence
  inversions), and what's variant-local (narrative, voice DOs, the
  amplified-trait anchor). Fixes the workflow where variant A ships,
  user later asks for B and C, and --re-direct is too heavy.

Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-05 09:00:14 +02:00
Paolo Mottadelli ed46712dde stardust: extract integrity & capture-fidelity hardening from 2026-04-29 → 2026-05-04 dogfood (#112)
* feat(stardust): provenance integrity — synthesis guard, cascade validation, full body capture

Closes a class of silent corruption where extract --prep silently
synthesized page records and the cascade ran four phases on
fabricated data before being caught by a meta-question
(2026-04-30 lovesac.com).

- extract refuses to mark a page extracted without renderedBy:"playwright"
  + fetchedAt + waitMs>0 + waitMode + httpStatus; new ProvenanceMissing
  error class; sub-agent prompts must forbid synthesis by name and return
  a per-page evidence table.
- validateProvenance(page) specced in state-machine.md; called at setup
  of direct --prep, prototype, migrate; cascade guard runs between
  prepare-migration Phase 1 and Phase 2 with explicit abort message.
- innerText captured in full — no truncation. Reference scripts must
  not slice (the v0.2 .slice(0, 4000) silently dropped most body content
  on long-form pages and broke module detection downstream).
- Schema additions for sections[].body, lists, qa, quotes so migrate can
  render real body copy under each heading instead of falling back to
  placeholder-with-signature throughout.
- Mandatory per-page evidence table in extract Phase 6 with live: yes/no
  column; Provenance: N/N live line in prep summary so the contract is
  visible at a glance.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* feat(stardust): extract reliability — Akamai headed fallback + consent pre-flight

Two unrelated context-setup gaps surfaced in 2026-05-03/04 dogfood
that silently produced bad captures.

- Bot-management fallback (UPS, ups.com/gb): Akamai rejects bundled-
  chromium-default headless on its TLS/H2 fingerprint with
  ERR_HTTP2_PROTOCOL_ERROR, before any JS runs. Recipe now specifies
  headless: false, channel: 'chrome' as the retry path; playwright-
  recipe.md gains a Bot-management fallback section, extract setup
  switches modes on the protocol error without retrying headless,
  and the in-page fetch pattern is documented for sub-resource
  fetches that need to inherit the JA3 fingerprint.

- Consent banner pre-flight (NVIDIA, nvidia.com): every page's
  screenshot was overlaid by the OneTrust banner and the voice
  table was dominated by 'Manage Settings' / 'Reject All' /
  'Accept All' once-per-page. Recipe now specifies an API-first
  dismissal (OneTrust / Cookiebot / Didomi / Osano) with selector
  fallbacks, --no-consent-dismiss opt-out, and consent.method
  recorded in _crawl-log.json. Side-effect caveat documented: the
  dismissal can activate other gated scripts (analytics, geo-IP,
  A/B) and the result may differ from a no-dismiss capture.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* feat(stardust): extract capture fidelity — fonts, icon font, CSS-bg pseudo, hero image, logo rect-filter

Five capture-fidelity gaps surfaced across the 2026-04-29 → 2026-05-04
dogfood window. Each silently produced a thinner or wrong brand surface
that downstream prototypes then rendered against.

- Logo locator step 2 (UPS): rect filter (height ≥ 32, width ≥ 40,
  top ≤ 200) + aspect filter [0.5, 3.0] + rank by proximity to 1.5
  ideal. Stops promotional icons that share the brand-name substring
  from being picked as the masthead logo.
- CSS-background hero (UPS): pseudo-element walk on ::before / ::after
  generated content, which document.querySelectorAll('*') doesn't
  reach. Performance-bounded by the prior visible-size filter.
- voice.heroImage elevation (UPS): single canonical hero per home,
  resolved by viewport-top + visible-area + aspect-ratio filters
  with explicit DOM > CSS-bg > pseudo tie-breakers. Ends downstream
  re-derivation from a 16-image list.
- Font file capture via network-intercept (JFK): every woff2/ttf/otf
  saved to assets/fonts/, recorded in _brand-extraction.json#type.files[]
  with @font-face metadata + licensing flag. Closes the gap where
  Mode A prototypes silently fall back to system-ui on private-cut
  brands.
- Icon-font detection (JFK): query [class^="icon-"] + ::before
  font-family + codepoint, build iconClass → codepoint table, save
  the font file. Closes the emoji-fallback render path on
  Chakra/Material/government sites.
- Module-detection signal priority (sliccy): explicit ranking —
  headings → CTAs → cssBackgrounds → forms → componentsByLandmark
  → innerText substring. Substring search drops to corroboration
  only; was the source of the 2026-04-29 under-detection.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-05 08:10:29 +02:00
Paolo Mottadelli 9cfed1145a feat(stardust): replace v1 with v0.3.0 (redesign on top of impeccable) (#111)
v1 (four-stage greenfield: brand → briefings → wireframes → prototype) is
preserved at tag stardust--v0.1.0. v0.3.0 is a complete refactor with a
new surface (extract → direct → prototype → migrate) and a hard runtime
dependency on impeccable.

- plugins/stardust: replace contents with v0.3.0 source from paolomoz/stardust-2
  (skills, evals, README, tile.json, plugin.json)
- plugins/stardust/.claude-plugin/plugin.json: bump to 0.3.0; add repository
  and v2-relevant keywords
- plugins/stardust/skills/*/SKILL.md: add license: Apache-2.0 to frontmatter
- .claude-plugin/marketplace.json: update stardust entry with new
  description, version, category, keywords, author, homepage, repository,
  license (mirrors adobe-for-creativity entry shape)
- plugins/stardust/README.md: status bumped to v0.3.0; v1 link repointed
  to the stardust--v0.1.0 tag

Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-30 17:24:22 +02:00
Paolo Mottadelli 91589bfb0d docs(stardust): refresh README with identity visuals and voice
Adds cover, pipeline, and logo SVGs under docs/ and rewrites the README
to lead with the identity (brief + seed = star) while keeping all
instructional sections. Adds a short "how it wants to be spoken about"
section so docs and tooling on top of stardust can match register.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-24 21:56:12 +02:00
Paolo Mottadelli a183041f6e feat(stardust): publish design-phase skills plugin (#92)
* feat(aem-design): scaffold plugin skeleton

- plugin.json (Apache-2.0, Adobe author, v0.1.0)
- tile.json listing the 5 design skills
- empty skills/ and evals/ (populated by subsequent commits)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* feat(aem-design): import hardened skills from stardust-plugin

5 design skills (aem-design navigator, brand, briefings, wireframes, prototype)
plus _shared/ (preflight, skill-contract, soft-deps, fallback-brainstorm,
fallback-critique).

All skills use /aem-design:* slash commands, aem-design:provenance markers,
no absolute paths, and no EDS dev-server references.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* test(aem-design): import eval packs

5 packs (aem-design-navigator, brand-extract-from-url, briefings-from-prompt,
wireframes-render, prototype-iterate). Each has task.md (setup, prompt,
expected behavior) and criteria.json (weighted rubric summing to 100).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* docs(aem-design): plugin README

Install, skill table, soft-dep notes (superpowers, impeccable),
AGENTS.md snippet for activation reinforcement, and out-of-scope
clarification (EDS build phase is separate).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* feat(marketplace): register aem-design

Insert alongside the other AEM entries, immediately before
aem-edge-delivery-services to group the design-phase plugin
with its downstream EDS implementation companion.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* docs(readme): add aem-design section and install command

Adds the Designing-with-aem-design subsection with the 5 skills
(navigator + brand, briefings, wireframes, prototype) under the
AEM section, placed before Developing with Edge Delivery Services
to reflect pipeline order. Adds /plugin install aem-design to the
top install block.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* docs(aem-design): add "When to use" / "Do NOT use" blocks per Tessl rubric

Each SKILL.md now names the triggers that should invoke it and defers to
sibling skills for out-of-scope requests, so agents with weaker description
matching hand off cleanly instead of overreaching.

* fix(aem-design/brand): enforce _provenance contract and extract real logo to aem-design/assets/

Follow-ups #1, #3, #4 from docs/superpowers/aem-design-followups.md.

- brand-profile.json now requires `_provenance` as the first top-level key
  with generated_by, source, extraction_method, synthesized_inputs
  (enumerating LLM-filled fields) and screenshots. Legacy `extraction`
  block removed. Aligns with _shared/skill-contract.md.

- brand skill now extracts the real logo on a deterministic fallback path:
  inline <svg> in header/nav → <img> with logo class/src → apple-touch-icon
  / og:image → favicon → synthesized placeholder (last resort). Output
  always lands at aem-design/assets/logo.<ext> — never icons/ — so the
  design phase stays EDS-agnostic. brand-profile.json's logo object now
  records path/format/source. brand-board.html references the asset file
  via <img>, not inline SVG.

- brand-extract-from-url eval: provenance_stamped criterion tightened to
  assert the new contract shape; new real_logo_asset criterion (10 pts)
  asserts the file exists under assets/ with logo.source set; weights
  rebalanced to sum to 100.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* fix(aem-design): honor soft-deps delegation across skills (briefings, brand, wireframes)

Explicit decision tree at each soft-dep boundary: detect the peer slash command,
delegate when present, otherwise announce the fallback once per session and run
the inline pattern. Silent inline interviews are now a bug.

- briefings/SKILL.md Phase 2 Step 1: rewrite discovery to branch on /brainstorm
  registration. Either delegate with visible hand-off or announce fallback once.
- brand/SKILL.md conversational path: same pattern for brand discovery.
- wireframes/SKILL.md Phase 1 Step 4: same pattern for multi-page IA planning
  via /write-plan.
- evals/briefings-from-prompt: rename fallback_announced_once -> soft_deps_honored
  with tightened description covering both delegation and announcement paths.

Follow-up #5 from PR #92 smoke test.

* feat(aem-design): briefings default to structured shape with [TBD] placeholders

Previously the skill asked the user to pick a fidelity level (prompt-only /
structured / full) before drafting. This created an unnecessary gate — the user
had to front-load a planning decision before they had any output to react to.

Now every briefing emits the same structured shape (Intent + Audience + Key
Messages + CTAs + Tone), with `[TBD]` written verbatim in sections the user
hasn't committed to. Downstream skills synthesize on-brand content for `[TBD]`
fields and stamp provenance. Fidelity becomes a consequence of how much the
user fills in, not a tier they select upfront.

- briefings/SKILL.md Phase 1: drop the fidelity question, default to structured,
  document [TBD] semantics. Phase 2: draft in structured shape always.
- briefing-format.md: replace three-tier fidelity table with structured+full
  shape table. Remove `fidelity` frontmatter field. Update Rules to require
  all five structured sections (with [TBD] valid as section body).
- evals/briefings-from-prompt: add `no_fidelity_gate` criterion (10), retune
  weights to keep total=100. Tighten briefing_sections and provenance_stamped
  descriptions. Rewrite task.md expected behavior.

Follow-up #6 from PR #92 smoke test.

* feat(aem-design): prototype skill offers 1-4 variants to choose from

Early variant choice is cheaper than late iteration — committing silently to
one design direction means that changing direction after the user has asked
for type-scale tweaks throws away the tweaks. The soft-gate philosophy already
embraces "synthesize and stamp"; variants are the logical extension.

- prototype/SKILL.md Phase 0: ask "How many variants? (1-4, default 1)".
  N=1 preserves current behavior. N>=2 renders {page}-a.html, {page}-b.html, ...
  each exploring a load-bearing axis: type-voice, density, color-energy,
  imagery-role. Each variant's provenance block carries a `variant_direction`
  line.
- Phase 3 (Serve): for multi-variant, present a comparison table
  (direction / key visual move / risk) and ask the user which to take forward.
- Phase 4 (Iterate): iterate only on the chosen file. Unchosen variants stay
  on disk as design-history reference.
- Artifacts table documents both {page}.html and {page}-{letter}.html shapes.
- evals/prototype-iterate: add Scenario B (3 variants + choose B + iterate).
  New criteria: variant_count_asked (5), variant_directions_distinct (8),
  iteration_targets_chosen_variant (8). Retune existing weights to keep total=100.
  task.md extended with Scenario B expected behavior.

Follow-up #7 from PR #92 smoke test (minimum ambition per plan).

* feat(aem-design/brand): add divergence toolkit and make reference-required the default

Push back against LLM-driven visual convergence across brand generations
by establishing three within-session mechanisms:

1. New _shared/divergence-toolkit.md (v0.1, self-audited) houses:
   - Default-moves budget (max 3 per profile) listing recurring LLM defaults
     across typography, motifs, voice rules, structure, and palette roles
   - Seed lists (decade x craft tradition x cultural register) used as hard
     constraints when no reference is provided; deterministic-random from
     MD5(brand-name + date) for audit reproducibility
   - Named font decks (editorial-archival, retro-italian, zine-maximalist,
     swiss-modernist, etc.) replacing ad-hoc font picks
   - Role-naming rule forbidding generic palette role slots
   - Reference-use discipline for listicle inputs (extract all trends, tag
     in/off-toolbox, require off-toolbox per variant)

2. brand/SKILL.md Phase 1: reference-required by default. Conversational
   input drops to option 4 (explicit escape hatch) with a verbatim warning
   citing the toolkit. When accepted, rolls a seed and stamps
   _divergence.divergence_warning=true.

3. brand/SKILL.md Phase 2: .impeccable.md authorship stamping. Every file
   opens with frontmatter declaring authored_by (designer|synthesized) and
   strength. Adds a "last chance" interview prompt before synthesis so
   downstream skills don't enforce LLM defaults as designer taste.

Schema additions in brand-profile-schema.md:
- New optional _divergence block as the second top-level key (captures
  seed, chassis, font_deck, anti_toolbox_count/hits, justifications,
  off_toolbox_moves, references_used with listicle tagging, warning flag)
- Role-naming enforcement on new writes; old profiles remain valid reads
- Optional sibling "use" field on color entries for technical qualifiers
  so role stays brand-native

Backward-compatible: missing _divergence block is valid; existing profiles
with generic role names are still read. No downstream skill is required
to hard-fail on these additions.

Addresses convergence observed when the same LLM regenerates brand boards
for unrelated categories (e.g., horror publisher vs. Italian pantry brand
sharing stencil typography, hazard stripes, rotated stamps, and identical
palette role taxonomies). See tmp/e2e-3 divergence report for analysis.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* feat(aem-design/brand): divergence toolkit v0.2 (I1+I2+I3+I5+I7)

Bundle five within-file edits to _shared/divergence-toolkit.md after a 4-run
test (e2e-4/5/6/7) surfaced specific gaps in v0.1. Changes:

I1 - Expanded § 1 Default-Moves List:
  - Added Triplet-cadence copy to Voice-rule moves (detected in all 4 test
    runs: "Same press. Same shop. Same eight years." / "Dated, classified,
    cross-linked." / "Saturday. Bar Beach. We dance.")
  - Added Collage-maximalism kit to Motif moves (the assistant's own
    archetype, reached for in fresh sessions without context)
  - Added Generic-2026-SaaS silhouette and Stat-callout bar to Structural
    moves (Linear/Notion/Stripe aesthetic; observed in Orrery run)
  - New Palette-family subsection covering the "archival editorial" palette
    that recurred in 3 of 4 test runs (cream ground + warm-family saturated
    accent + muted earth-tone secondary), cream-as-default page ground,
    brutalist-pomodoro, and dark-mode-editorial

I2 - Replaced the 3-free-hit budget with per-hit justification:
  - Every hit from § 1 now requires a brand-specific justification that
    would not transfer unchanged to an arbitrary other brand
  - Retired the budget because the 4-run test (Yadda Dey, 4 hits) showed
    the LLM comfortably fills it with defaults and rationalises excess

I3 - Moved sensible universal voice rules out of § 1 into new § 7:
  - Banned marketing adjectives list (artisanal/crafted/premium/curated/
    beloved/cozy/warm/inviting/thoughtfully/delightfully/lovingly/
    uncompromising/bespoke)
  - No exclamation points except italic quoted outbursts
  - Em-dashes welcome / semicolons earned
  These are opt-in house standards, copied into voice.rules[] when the
  brand or seed implies them, and do NOT count against the budget

I5 - Added new § 2.5 Dimension Weighting:
  - decade drives type deck + cultural references + display register
  - craft drives texture + motif idiom + print artifacts
  - register drives voice stance + structural metaphor + IA
  - Within-run variants use dimension dominance (A decade-lead, B craft-
    lead, C register-lead) to produce meaningful variant divergence
  - Added "Ground color by seed" table: cream belongs only to specific
    seeds (1920s-1960s x letterpress/riso/field-guide/travel-brochure);
    1990s x legal-contract belongs on pale gray; 1970s x enamel-sign
    belongs on saturated ground. Cream as default is now a § 1 hit.

I7 - Appended self-audit rationalisation check to Enforcement:
  - Hit audit: "would a reviewer agree this is a hit?" (A 'travel decal'
    that is a rotated circular stamp IS a rotated circular stamp)
  - Off-toolbox audit: is it a genuine invention or a dressed-up default?
  - Triplet-copy audit: max one triplet per page
  - Adjustments recorded in _divergence.audit_adjustments[]

Status banner updated to v0.2 - self-audited - run-tested with a v0.1 -> v0.2
changelog. Backward compatibility: _divergence.toolkit_version carries the
version so downstream skills can tell which list was in effect.

Addresses gaps surfaced in:
- /Users/paolo/excat/tmp/e2e-3/aem-design-divergence-test-assessment.md
- /Users/paolo/excat/tmp/e2e-3/aem-design-toolkit-v0.2-improvements.md

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* feat(aem-design/brand): tighten role-naming + remove cream default (I4+I8)

Close two palette-vocabulary loopholes observed in the 4-run test. Both
edits are small and compound with the divergence toolkit v0.2 shipped in
the previous commit.

I4 - brand-profile-schema.md Role Naming: token-level match

The v0.1 rule forbade specific values as the sole role name (Primary,
Secondary, Alarm, Warning, Shadow, Hardware, Accent, Background). That
string-equality check missed compound smuggling like "Accent Gold" /
"Primary Red" / "Brand Blue" — the generic taxonomy sneaks in alongside a
color name and passes validation.

v0.2 upgrades to token-level whole-word case-insensitive match. Any role
value containing a token from the forbidden list is rejected, including
compounds. New tokens added to the list: Neutral, Brand, House.

- Forbidden on new writes: Primary, Secondary, Tertiary, Alarm, Warning,
  Danger, Shadow, Hardware, Ink, Accent, Background, Neutral, Brand, House
  (anywhere in the role value, not just as the whole value)
- Technical intent continues to live in the sibling 'use' field, which is
  allowed to contain the forbidden tokens
- The color's 'name' field is also unrestricted - a color called "Shadow
  of Pomodoro" is fine; the 'role' field is the one that must be brand-
  native

Existing profiles with generic role names remain valid reads. The rule
applies only to new writes.

I8 - brand-board-template.md: remove cream default substrate

The v0.1 template said: "Light background (#faf9f6 or similar warm
neutral) for the page body". That instruction drove cream backgrounds in
3 of 4 test runs regardless of whether the brand's seed called for cream.
Shita-gawa's seed was 1990s x Letterpress x Legal contract (pale gray
substrate per toolkit v0.2 section 2.5) and still landed on cream because
the template told it to.

v0.2 replaces the instruction with a brand-derived-ground rule that points
at the divergence toolkit's Palette-family moves (section 1) and Ground
color by seed table (section 2.5). Example seeds that want cream are
named inline; example seeds that should NOT default to cream are also
named. The dark-sections rule is softened: inversion happens only when
the brand's palette supports an ink-or-deeper-than-ground surface, not as
a blanket template default.

Addresses gaps identified in:
- /Users/paolo/excat/tmp/e2e-3/aem-design-divergence-test-assessment.md
- /Users/paolo/excat/tmp/e2e-3/aem-design-toolkit-v0.2-improvements.md (I4, I8)

Canonical test after both commits: a Shita-gawa re-run should either
produce a non-cream ground, or stamp _divergence.anti_toolbox_hits[] with
a "Cream/paper as default page ground" entry carrying a brand-specific
justification.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* feat(aem-design/brand): chassis library (I6)

Split brand-board-template.md into a data contract and a chassis library,
ship 4 chassis specs, and update brand/SKILL.md Phase 3 to pick a chassis
per run. This is the single-largest remaining convergence axis: v0.2
boards diverged in palette/type/motif but shared one skeleton. Chassis
addresses that.

New files (brand/reference/chassis/):

classic-archive.md - v0.1 default preserved as one option; numbered
  sections, sticky top nav, masthead with metadata stamp, horizontal
  grid. Appropriate for archival/institutional/editorial brands.
  Reference: Pentagram annual report, MacGuffin.

dashboard.md - fixed left sidebar, cards-as-widgets, meters / gauges /
  status chips. Appropriate for operational/tool brands and seeds with
  railway-timetable, broadcast-captioning, sports-scorecard,
  repair-manual, hospital-discharge registers. Reference: Linear admin,
  Bloomberg Terminal overview.

magazine.md - masthead with Vol/Issue/date, column text, pull quotes,
  drop caps, magazine department heads (FEATURE / ESSAY / LETTER).
  Appropriate for tabloid, memoir, auction-catalogue, travel-brochure
  registers. Reference: Apartamento, The Gentlewoman.

pinboard.md - no sticky nav, cluster-based spatial arrangement,
  handwritten labels, scrapbook overlap. Appropriate for zine register
  and collective/community/youth brands. Reference: La Palatine, Cy
  Twombly workbook. Carries explicit caveat that picking pinboard
  does NOT excuse hitting the Collage-maximalism kit from
  divergence-toolkit.md section 1 Motif moves.

Each chassis spec covers: intent, navigation, section order, hero shape,
eyebrow conventions, spacing rhythm, typography register, motif placement,
what it is NOT, and example references. Structural, not taste-prose.

Modified files:

brand/reference/brand-board-template.md - rewritten as a data contract
  (what must be rendered) plus a chassis picker section. Adds explicit
  chassis-selection rules with seed-informed preference table. Previous
  "Required Sections" block now a plain bullet data-contract list.

brand/SKILL.md Phase 3 - rewritten to pick a chassis before rendering:
  1) designer override, 2) byte[3] hash from seed.hash_input mod chassis
  count, 3) seed-preference override, 4) fallback to classic-archive.
  Records _divergence.chassis and _divergence.chassis_pick_reason.

brand/reference/brand-profile-schema.md - adds chassis_pick_reason field
  to the _divergence block. chassis field description expanded to name
  the four available chassis.

After this commit, chassis selection is auditable: _divergence.chassis
and _divergence.chassis_pick_reason tell a reviewer exactly which
chassis landed and why. The expected outcome on a 4-run test (same
brands as e2e-4/5/6/7) is at least 3 different chassis across the 4
boards — structural divergence, not just surface divergence.

Addresses Improvement I6 in:
- /Users/paolo/excat/tmp/e2e-3/aem-design-toolkit-v0.2-improvements.md

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* refactor(aem-design): chassis artifact-agnostic + prototype integration (v0.3)

v0.2 shipped chassis as brand-board-only. The chassis files mixed
presentation-pattern concerns (nav, hero pattern, spacing, type register)
with brand-board-specific concerns (section list naming Palette/
Typography/Voice/etc). Prototypes still rendered on a single implicit
chassis — the exact convergence problem v0.2 was supposed to address.

v0.3 refactors chassis into a shared library both brand and prototype
read, and adds a prototype chassis picker.

Structural changes:

1. Move chassis files from brand/reference/chassis/ to _shared/chassis/.
   The library is artifact-agnostic; both brand and prototype skills now
   reference it.

2. Refactor each of the four chassis files
   (classic-archive/dashboard/magazine/pinboard):
   - Remove "Section order" subsection (brand-board-specific)
   - Rename "Hero shape" to "Hero pattern" (shape, not content)
   - Rename "Motif placement" to "Demo / visual presentation style"
     (applies to any demos, not just motifs)
   - Add explicit "this chassis describes a presentation pattern only"
     clarification at the top
   - Bump version 0.1 → 0.2, add scope: artifact-agnostic

3. brand-board-template.md:
   - Add "Section order per chassis (board-specific application)" block
     that maps the data contract to each chassis (this is where the
     brand-board-specific section order lives now)
   - Update chassis links from brand/reference/chassis/ to
     ../../_shared/chassis/
   - Renumber the Template Generation steps to accommodate the added
     section-order-reading step

4. prototype/reference/design-guide.md:
   - Add introductory paragraph about the shared chassis library
   - Add new "Chassis selection" section: designer override via
     _divergence.prototype_chassis → inherit from brand's
     _divergence.chassis → fallback classic-archive
   - Add "Prototype section order per chassis" table with per-chassis
     landing-page section ordering (e.g. dashboard landing: hero cluster
     → feature grid → status strip → reservation card → FAQ tray)
   - Add cross-chassis rules: one primary CTA, briefing drives content
     selection, motifs/components applied within sections per chassis
     demo style, variants stay within the chosen chassis

5. prototype/SKILL.md Phase 2:
   - Add Step A "Pick the chassis" before the render step
   - Chassis recorded in the prototype's provenance block with
     chassis_pick_reason
   - Step B renamed, includes "Apply the chassis's presentation pattern"

6. brand-profile-schema.md:
   - chassis field description updated to note prototypes inherit by
     default and to point at the new _shared/chassis/ location
   - New optional prototype_chassis field for per-artifact override

7. brand/SKILL.md Phase 3:
   - Path references updated from reference/chassis/ to
     ../_shared/chassis/
   - Clarified split: chassis spec is artifact-agnostic; section order
     lives in brand-board-template.md

Result: a brand on magazine chassis produces a brand board AND a
prototype both in magazine presentation pattern by default. Designer
can override prototype_chassis when a given brand wants one chassis for
internal documentation and another for public landing.

Addresses the "chassis was brand-board-only" gap raised in review.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* feat(aem-design/brand): swap pinboard for broadcast-grid chassis (v0.4)

Replace the pinboard chassis with broadcast-grid after review of v0.3's
4 chassis and 7 speculative mocks (see tmp/e2e-3/chassis-mocks/).

Rationale:

- Pinboard paired structurally with the Collage-maximalism kit listed in
  _shared/divergence-toolkit.md section 1. The chassis itself wasn't the
  problem (spatial cluster arrangement is a legitimate pattern), but in
  practice picking pinboard produced boards that then hit the anti-
  toolbox with rubber stamps, handwritten annotations, rotated date-
  blocks, and ripped edges. The chassis's very availability nudged the
  LLM toward its own "collage-maximalism" archetype — exactly the
  convergence the divergence work is trying to address.

- Broadcast-grid fills a structural gap that pinboard didn't. v0.3's
  4 chassis left no good home for brands whose seed register is
  railway-timetable, broadcast-captioning, sports-scorecard, liturgical-
  program, or pharmacy-insert — registers where the native form is a
  scoreboard / terminal / timetable. Dashboard was the fallback, but
  dashboard is cards-on-a-canvas; broadcast-grid is flat dense panes
  with a ticker. Different metaphor, different density.

Changes:

New: _shared/chassis/broadcast-grid.md (90 lines)
  - Intent: terminal / EPG / news-broadcast presentation
  - Navigation: top bar (channel + LIVE + tabs + clock) + ticker band
  - Hero pattern: multi-pane grid with 1.5fr hero pane + feed panes
  - Eyebrow conventions: pane title + source label, split by hairline
  - Spacing rhythm: 1px inter-pane rules, no radii, tight 14-16px pad
  - Typography: monospace-dominant, tabular numerals, condensed sans
    for pane titles; dark surface by default, light variant valid
  - Demo style: each demo rendered as a live-feed pane (table/list +
    source label), not as individual cards on a canvas
  - Explicit NOT list vs dashboard / classic-archive / magazine
  - Accessibility note on high-density contrast requirements

Removed: _shared/chassis/pinboard.md

Updated chassis selection and section orders:

brand/reference/brand-board-template.md:
  - Chassis list now alphabetical: broadcast-grid, classic-archive,
    dashboard, magazine
  - Hash-based default mapping updated: 0 -> broadcast-grid, 1 ->
    classic-archive, 2 -> dashboard, 3 -> magazine
  - Seed-informed preference table rewritten:
    - railway-timetable / broadcast-captioning / sports-scorecard /
      liturgical-program / pharmacy-insert -> broadcast-grid OR
      dashboard
    - zine register moved to magazine (was pinboard in v0.3)
    - legal-contract / repair-manual / museum-didactic / hospital-
      discharge still -> classic-archive OR dashboard (pharmacy-insert
      moved out)
  - Board section order per chassis: added broadcast-grid row (panes
    in a flat grid with a ticker above), removed pinboard row
  - Added note explaining why pinboard was retired — signal to propose
    a new chassis if zine brands need a non-magazine pattern, not to
    reintroduce pinboard

prototype/reference/design-guide.md:
  - Chassis list updated alphabetically with broadcast-grid
  - Prototype section order per chassis: added broadcast-grid (top bar
    + ticker + hero pane + feed panes + wide event pane + status strip
    + compact footer), removed pinboard
  - Cross-chassis rules: CTA-placement guidance for broadcast-grid
    hero pane; motif placement note includes live-feed panes

brand/SKILL.md Phase 3:
  - Hash mapping reference updated to new alphabetical order

brand/reference/brand-profile-schema.md:
  - chassis value domain updated: 'broadcast-grid' | 'classic-archive'
    | 'dashboard' | 'magazine'. Note added about v0.3 having pinboard
    and v0.4 routing zine to magazine

Chassis NOT-lists in the three preserved chassis updated:
  - Replaced "Not a pinboard" line with "Not a broadcast-grid" where
    useful (classic-archive, dashboard, magazine)

After v0.4: 4 chassis, zero anti-toolbox entanglement at the chassis
level, coverage of data-register brands that previously had no good
structural home.

Reference mocks for all four chassis in this repo at
tmp/e2e-3/chassis-mocks/{1-classic-archive,2-dashboard,3-magazine,
5-broadcast-grid}.html.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* revert(aem-design/brand): remove chassis system entirely (v0.5)

Chassis added in v0.3 and refined in v0.4 (chassis-library shared between
brand and prototype, 4 chassis with seed-preference routing) turned out to
be a distraction. In the e2e-8/9/10 test runs the chassis did pick
deterministically and the boards did render in their chosen chassis's
pattern, but the divergence payoff was marginal relative to the surface
area of the system — and the cream-ground convergence (the actual tell)
happened regardless of which chassis rendered.

Removed:

- _shared/chassis/broadcast-grid.md · classic-archive.md · dashboard.md ·
  magazine.md (entire chassis library)

Reverted to pre-chassis state:

- brand/reference/brand-board-template.md — back to a single canonical
  data contract with section order, design guidelines, and template
  generation steps. The cream-rebrand ban (vellum, kami, bone, ivory,
  eggshell) is preserved in the Design guidelines section.

- brand/SKILL.md Phase 3 — back to a single render step (read profile →
  generate HTML → write file → tell designer), no chassis pick, no
  pick-reason logging. Keeps the explicit "do not default to cream" line
  that points at toolkit §2.5.

- prototype/SKILL.md Phase 2 — removed Step A (chassis pick + provenance
  block stamping). Phase 2 is now a single render step.

- prototype/reference/design-guide.md — removed "Chassis selection" and
  "Prototype section order per chassis" sections. Replaced the
  "Cross-chassis rules" block with a "Landing-page section rules" block
  that holds the same invariants (one primary CTA, briefing drives
  content, motifs applied within sections, variants share copy + tokens).

- brand/reference/brand-profile-schema.md — removed chassis,
  chassis_pick_reason, and prototype_chassis fields from the _divergence
  block. Also removed the chassis bullet from the Divergence Tracking
  notes.

What remains from v0.3/v0.4:

- _shared/chassis/ directory deleted, but the structural reasoning (data
  contract vs presentation) has been absorbed into brand-board-template.md
  as a straightforward single-template spec.

- Font decks (toolkit §3) remain — they were always artifact-agnostic and
  drive real divergence.

- Seed system (§2 decade × craft × register) remains. The 'zine register
  route-to-magazine' routing is moot now that chassis routing is gone.

What this does not fix:

- Cream ground dominance observed in e2e-8 (justified by seed Embossed
  leather × Liturgical program), e2e-9 (cream rebranded as "kami" to slip
  the explicit ban), e2e-10 (cream justified by §2.5 carveout). The
  toolkit §2.5 Ground-color-by-seed table is the loophole — addressed in
  the next commit.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* feat(aem-design/brand): 4th seed dimension + cream rebrand ban (v0.5)

Second v0.5 change. Addresses the cream-ground convergence observed
across all three e2e-8/9/10 test runs:

- e2e-8 (Beumer & Becker, seed Embossed leather × Liturgical program) →
  cream justified by §2.5 carveout as "liturgical programs print on
  cream stock"
- e2e-9 (Shita-gawa, explicit cream ban in anti-toolbox) → cream
  rebranded as "kami" (Japanese paper) to slip the ban
- e2e-10 (Yadda Dey, seed 1960s × folded-paper × travel brochure,
  cream on §2.5 "belongs here" row) → cream permitted

All three grounds landed at #EDE.../#F0E.../#F5E... — clear cream family.

Two changes:

1. Expanded § 1 cream-family entry with rebrand ban and deterministic
   hex test:

   - Named rebrands called out: vellum, kami, parchment, washi, bone,
     oatmeal, eggshell, ivory, biscuit, tan, wheat, fawn, sand, linen,
     canvas, manila, calfskin, morocco-cream. Renaming cream does not
     change what it is.
   - Deterministic HSL-range test: a ground is cream-family when
     L is 80-97 AND (H is 20°-60° OR S < 15%) AND S < 40%. The LLM
     can perform this check on its own emitted hex before finalising.
   - Justification bar narrowed: cream is only acceptable when the
     brand's primary business is literally printing / publishing /
     paper-goods / binding / stationery. Adjacent registers
     (liturgical program, field guide, museum didactic, auction
     catalogue, travel brochure) are NOT sufficient on their own —
     they must combine with the brand being in that category.

2. Retired § 2.5 "Ground color by seed" table and replaced it with a
   new 4th seed dimension:

   - Ground family · deterministic-random from byte[3] of the seed
     hash mod 6: cream · stark-white · pale-gray · saturated · dark ·
     monochrome-tint
   - Stamped in _divergence.seed.ground with seed.picked_by and
     seed.overrides[] for mixed designer/auto picks
   - Cream now lands on ~1/6 of no-reference runs by construction,
     not by template default and not by LLM rationalisation
   - Designer override available for genuine print/paper brands

   The retired table was a carveout the LLM used to rationalise cream
   on most brands. Removing the opportunity for post-hoc rationalisation
   — by picking the ground BEFORE the LLM reasons about the brand —
   closes that specific loophole.

Schema updates:

- brand-profile-schema.md _divergence.seed now includes:
  - ground field (one of six enum values)
  - picked_by expanded to include 'mixed'
  - overrides array for mixed picks

- Status banner bumped to v0.5 with a v0.4→v0.5 changelog entry

Expected outcome on re-run of e2e-8/9/10 with same brand names/date:

- Each brand gets a specific hashed ground family. Cream shows up only
  when byte[3] mod 6 lands on 0.
- For brands that do not hash to cream, cream-family rebrands are
  actively prevented by the § 1 rebrand list + hex check.
- Shita-gawa's "kami" rebrand would now fail both the named-rebrand
  check AND the deterministic hex test.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* fix(aem-design/brand): cream test uses raw channel warm-bias (v0.5.1)

v0.5 rule used 'S < 15' as a proxy for "warm or neutral" in the
cream-family hex test. That false-positively flagged pure neutral grays
as cream because grays satisfy S = 0. Observed in the Coolors-scraped
anchor library: the "Silver Lining" palette (#595959 #7F7F7F #A5A5A5
#CCCCCC #F2F2F2) got classified as cream despite being pure grayscale.

v0.5.1 replaces the saturation-as-proxy with raw-channel warm bias:
  R − B ≥ 5 in the raw 0-255 channels.

This still catches every legitimate cream rebrand from the v0.5 list
(vellum, kami, oatmeal, bone, eggshell, ivory, parchment, washi, biscuit,
tan, wheat, fawn, sand, linen, canvas, manila, calfskin) because those
ARE warm at low saturation — their R channel runs higher than their B
channel by design. It correctly excludes:
- #F5F5F5 (pure gray, R−B=0)
- #CCCCCC (pure gray, R−B=0)
- #D4E2E8 (cool gray, R<B)
- #E8ECEE (cool near-white, R<B)

Examples now include R−B deltas for each cream-family example so a
reviewer can verify the rule by eye.

Status banner bumped v0.5 → v0.5.1 with a short changelog entry.

Addresses issue observed when scraping Coolors trending and
classifying the 127 extracted palettes — see tmp/e2e-3/tools/
scrape-coolors.py which uses the same rule.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* feat(aem-design/brand): palette picker + library integration (v0.6)

Add an offline palette-selection phase to the brand skill. Replaces the
weakest link in the pipeline — LLM-invented color palettes — with a
pick-from-library flow whose colors come from real Coolors trending
palettes. Every hex carries a source URL back to coolors.co.

New files (127 palette JSONs + 4 structural files):

_shared/palettes/
  library.json                  consolidated index of all 127 entries
  cream/ (5)                    warm near-white grounds
  stark-white/ (6)              true-white, near-achromatic
  pale-gray/ (5)                cool near-neutral
  saturated/ (78)               bold, colored-light or colored-dominant
  dark/ (20)                    ink or deep-jewel grounds
  monochrome-tint/ (13)         tinted near-neutral with loud accent

  Each palette file: source URL, scraped_at, name, 5 hexes, classified
  anchor candidate, classification (ground_family + hue_bias +
  saturation_level + energy + cream-flag list). Scraped from
  coolors.co/palettes/trending on 2026-04-24 via tools/scrape-coolors.py
  in the session repo.

_shared/palette-picker.md       classifier vocabulary + filter scoring
  - §1 keyword dictionaries for 5 descriptor dimensions (energy,
    contrast, saturation_level, hue_bias, ground_family)
  - §2 filter scoring rules (exact/loose hue match, ±diff saturation +
    energy, ground-family 100-point match)
  - §3 HSL + raw-channel warm-bias helpers (for library regeneration)
  - §4 UI contract pointing at the template
  - §5 designer corrections section

brand/reference/pick-ui-template.md
  - full HTML template with {{placeholders}}
  - dark-background layout, numbered cards 1-5, gold border on
    recommended pick, cream-flag indicator per swatch, Coolors source
    links, designer instruction footer

Modified:

brand/SKILL.md
  - NEW Phase 2 Palette Selection (119 lines)
    Step A  derive description from designer brief OR synthesize from
            voice/pillars/seed
    Step B  classify via palette-picker.md §1 keyword vocabulary
    Step C  filter and score palettes/ per §2 rules
    Step D  render pick UI at aem-design/_palette-pick.html
    Step E  wait for designer pick (integer 1-5, palette name, or refine)
    Step F  record in in-memory profile + _divergence.palette_source
  - Renumbered downstream phases: Design Personality 2→3, Render Brand
    Board 3→4, Approval Gate 4→5
  - Updated "No .impeccable.md" cross-reference to point at Phase 3

brand/reference/brand-profile-schema.md
  - Added _divergence.palette_source object: method enum, library_version,
    description_used, classification block, candidates_shown array,
    recommended_index, picked_index, picked_palette_name,
    picked_palette_source
  - New "palette_source sub-block" doc section under Divergence Tracking
  - Backwards-compatible: older profiles without palette_source still
    read valid

Zero external dependencies. Entire flow runs offline from bundled data.

Expected outcome on a no-reference run:
- brand skill reaches Phase 2
- if designer provides a palette brief, runs classifier; else synthesizes
  one from voice + seed
- writes aem-design/_palette-pick.html with 5 candidate cards
- designer picks a number
- brand profile's colors.primary[] gets the Coolors hexes with
  brand-native role names from the designer (or derived if absent)
- _divergence.palette_source records the full chain for audit

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* feat(aem-design/prototype): Phase 0b imagery mode · generated or placeholder

Extend Phase 0 (previously "Variant Count") into "Setup" with a second
question: whether the prototypes should use branded placeholder
rectangles (default) or real generated images. When generated, the
skill collects the model name and credential source.

Changes:

prototype/SKILL.md Phase 0 renamed "Variant Count" → "Setup":
  - Step 0a (variant count) — existing content preserved
  - Step 0b (imagery mode) — NEW

Step 0b asks the designer:
  "For images in the prototype, do you want: (a) branded placeholder
   rectangles — fast, offline, free, or (b) real generated images?"

If (b), two follow-ups:
  1. Which model? Options presented with provider + env-var name:
     - gemini → Gemini 3 Pro Image Preview · GOOGLE_API_KEY
     - flux   → fal.ai FLUX Schnell        · FAL_KEY
     - imagen → Vertex Imagen 3            · GOOGLE_APPLICATION_CREDENTIALS
     - dalle  → OpenAI DALL-E 3            · OPENAI_API_KEY
  2. Where's the credential?
     - "env" → read from the named env var directly
     - A .env file path → read the var from that file (key stays in memory)
     - A raw token → used only for the session, not written to disk

Imagery mode recorded in each prototype's provenance block:
  <!-- aem-design:provenance
    imagery_mode: placeholder | generated
    imagery_provider: gemini | flux | imagen | dalle | null
    imagery_credential_source: "env" | "<file-path>" | "<session-only>"
    imagery_generated_at: <ISO timestamp> (only when mode=generated)
    images: [ { section, path, prompt_hash } ]
  -->

Never logs the actual key value anywhere. Re-ask-once logic: on subsequent
invocations in the same project, the skill reads the previous prototype's
provenance block and re-uses the recorded mode; only re-asks if missing.

Phase 2 consequences:
  - mode=placeholder → existing branded-rectangle path per design-guide.md
  - mode=generated   → invoke ai-image-generator skill (from eds-site-builder,
    sumi, or testing plugin — whichever is registered) with the briefing's
    # Imagery direction + brand photography rules + target aspect ratio.
    Images at aem-design/prototypes/images/{page}-{section}.png
  - Cache by prompt_hash — iteration doesn't re-generate unchanged prompts
  - Fallback when generation fails: retry once simplified, then fall back
    to placeholder for that slot only, stamp imagery_fallback: true, never
    abort the whole page over one failed image

design-guide.md Imagery section rewritten with three named paths:
  (a) briefing source hint — highest priority
  (b) branded placeholder (default)
  (c) generated image via ai-image-generator soft-dep

Alt-text requirement preserved across all three paths; "image" or "photo"
as the whole alt is explicitly disallowed.

Zero new dependencies. The generation path uses ai-image-generator which
is already available in the user's environment via three installed plugins.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* feat(aem-design/prototype): default variant count 1 → 2, require confirm

Phase 0a used to default to 1 variant when the designer skipped. v0.7
changes the default to 2 (a pair to compare) and asks for explicit
confirmation:

  "I'll produce 2 variants of each prototype so you can compare — confirm,
   or give a different number (1-4)?"

Valid responses:
  - "ok" / "confirm" / "yes" / Enter / "2" → 2 variants (default)
  - 1 → single variant
  - 3 or 4 → that many variants
  - other → re-ask once

Rationale: the multi-variant comparison workflow (Phase 3 table, Phase 4
iteration on the chosen variant) is the more-useful default for design
decisions. A single variant skips the compare step; a pair captures the
most value for least effort.

Pipeline automation also defaults to 2 now — no explicit variant count
in the prompt means the skill renders 2 and presents them.

No downstream changes: Phase 2 rendering logic already handled both
single-variant and multi-variant modes.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* refactor(stardust): rename aem-design plugin to stardust

Move from plugins/aem/design/ to plugins/stardust/ (top-level, sibling of
plugins/aem/, plugins/app-builder/, plugins/creative-cloud/). Rename
plugin identifier to "stardust". Rename content-folder convention
aem-design/ to stardust/ inside user projects. Broaden scope language
from AEM-EDS-specific to platform-agnostic static-HTML design.

No backward compatibility — clean break.

Filesystem moves (git mv, rename history preserved):
- plugins/aem/design/                       → plugins/stardust/
- plugins/stardust/skills/aem-design/       → plugins/stardust/skills/stardust/
- plugins/stardust/evals/aem-design-navigator/ → plugins/stardust/evals/stardust-navigator/

Manifest updates:
- .claude-plugin/marketplace.json — entry name aem-design → stardust,
  source path updated, description broadened to "static-HTML design
  projects" from "AEM Edge Delivery Services sites"
- plugins/stardust/.claude-plugin/plugin.json — name + description +
  keywords (removed aem, eds; added palette, wireframes)
- plugins/stardust/tile.json — adobe/aem-design → adobe/stardust, summary
  broadened, skill map key aem-design → stardust
- plugins/stardust/README.md — full rewrite with broadened scope,
  added "What makes stardust different" section covering the v0.2-v0.7
  palette library + divergence toolkit + seed system

Navigator skill (skills/stardust/SKILL.md):
- Frontmatter name aem-design → stardust
- Full prose rewrite via word-boundary sed

Source updates (single pass of \baem-design\b → stardust across all .md
and .json files in the plugin):
- ~60 invocation-path refs (/aem-design:* → /stardust:*)
- ~100 content-folder refs (aem-design/ → stardust/)
- ~20 prose mentions
- 1 eval-folder name ref

Scope-broadening edits (beyond the sed):
- prototype/SKILL.md description: "no EDS or dev-server dependency" →
  "no build system or dev-server dependency"
- prototype/SKILL.md: "EDS-free" → "platform-free", "EDS-independent"
  → "platform-independent"
- brand/SKILL.md icons/ note: reframed as "platform-agnostic" with EDS
  as one example
- wireframes-guide.md: "not an EDS block type" → "not a downstream
  block/component type"; "concrete EDS site" → "concrete site"

AEM/EDS still mentioned in scope-correct contexts as ONE EXAMPLE of a
downstream target (alongside "another SSG", "a different CMS", "a
framework component library") — those are kept. Eval criterion IDs
like "no_eds_references" kept stable so eval history still runs.

BREAKING: existing user projects with aem-design/ artifact folders are
not found by /stardust. Users must `mv aem-design stardust` in each
project. Installed plugin cache at
~/.claude/plugins/cache/adobe-skills/aem-design/0.1.0/ becomes stale;
re-install from the marketplace as stardust to replace.

Validation: all 5 skills valid under new paths. Zero remaining
aem-design references. Commit log preserves rename history via
git-mv + git similarity-detection.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* feat(stardust): open HTML artifacts in browser after every write

Every HTML artifact the stardust skills produce now opens in the
designer's default browser immediately after it's written. No more
"tell the designer to open the file" wording — the skill invokes the
platform-appropriate open command via Bash.

Rule added to _shared/skill-contract.md:

  ## Opening HTML artifacts
  - macOS:   open "<absolute-path>"
  - Linux:   xdg-open "<absolute-path>" &
  - Windows: start "" "<absolute-path>"
  - Skill detects platform from environment, picks matching command.
  - Unknown platform → try open, fall back to xdg-open.
  - Open after EVERY write (including iteration re-writes).
  - Multi-variant mode: open all variants simultaneously for tab-
    compare.
  - Pipeline-automation mode (no designer present): skip the open.
  - Bash-unavailable environments: fall back to telling the designer
    the path.

Skill updates:

- brand/SKILL.md:
  - Phase 2 Step D (palette pick UI): `open stardust/_palette-pick.html`
    immediately after write. Designer message updated from "open the
    file" to "the UI is already open."
  - Phase 4 (brand board): `open stardust/brand-board.html` immediately
    after write. SLICC browser-panel path still works.

- wireframes/SKILL.md Phase 3 (Serve):
  - Open each emitted wireframe in the browser immediately.
  - Multi-page run: open each for tab-compare.
  - Old code-block with `open` + `xdg-open` side-by-side replaced with
    clear "skill does the open, not the designer" rule.

- prototype/SKILL.md Phase 3 (Serve):
  - Open each emitted prototype in the browser immediately after Phase 2
    render.
  - Multi-variant mode: open all variants simultaneously so the designer
    can flip between browser tabs for the comparison-table evaluation.
  - `python3 -m http.server` path preserved for cases that need a real
    HTTP origin (fetch/service-workers), but file:// via `open` is the
    primary path (covers ~95% of prototype needs).

- prototype/SKILL.md Phase 4 (Iterate):
  - Every iteration re-opens the file so the designer sees the change
    immediately. Browsers with live-reload pick up the change on
    re-open.

Rationale: the designer-opens-manually pattern added friction at every
gate. Phase 2 palette pick, Phase 4 brand board, wireframe review, and
prototype variant comparison all required the same mental gear-shift
of copy-path-then-open-browser. The open is one Bash call; putting it
in the skill removes a persistent small annoyance.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-24 17:09:44 +02:00