Files
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

13 KiB
Raw Permalink Blame History

Eval: multi-template migrate

Validates Path A (approved page), Path A′ (template-applied sibling), Path B (unique render), canon application, module reuse, broken-link reporting, idempotent skip, canon-driven re-render, and bespoke-slot promotion suggestion.

Setup

A project where prepare-migration has run and three archetypes are approved:

  • stardust/state.json lists 25 pages:
    • home — approved (canon-author, V01 Polish)
    • news/post-housing-summit — approved (article archetype)
    • news — approved (listing archetype)
    • 18 article-typed pages — directed
    • 2 program-typed pages — directed
    • 1 form-typed page (donate) — directed
    • 1 unique-typed page (404) — directed
  • stardust/current/ populated with full inventory and typed slots per page.
  • Project-root PRODUCT.md, DESIGN.md, DESIGN.json exist with populated extensions.canon, extensions.modules[], extensions.colorReservations[], extensions.metadata.
  • stardust/canon/ populated (header.html, footer.html, canon.css, modules/hotline-211.html, modules/donate-band.html, modules/story-card.html, modules/stat-trio.html).
  • stardust/direction.md has an active direction (Mode A brand-faithful, with brand_faithful_inversions[] declared for #FFFFFF, #000000, hex format, 0px corners, ALL CAPS).
  • stardust/prototypes/ has the three approved files.
  • No stardust/migrated/ yet.
  • Impeccable installed.

User prompt (run 1)

$stardust migrate

Expected behavior (run 1)

The stardust:migrate skill is invoked. It:

  1. Runs the master setup; verifies state, DESIGN, canon, direction.
  2. Prints the plan with branch partition:
    • Path A: 3 pages
    • Path A′: 21 pages (18 article, 2 program, 1 form)
    • Path B: 1 page (404)
  3. For Path A pages: reads each <slug>-proposed.html, refreshes :root from DESIGN.md (with canon.pinned precedence), injects canon.css, applies content-preservation, validates with brand-faithful inversions lifted, writes.
  4. For Path A′ pages: per reference/template-and-module-rendering.md § Path A′, forks the matching archetype's structure, injects this page's typed slots from current/pages/<slug>.json § slots, adapts content that doesn't fit (logged as template-adapted), applies canon, validates, writes.
  5. For Path B (404): per § Path B, composes a one-off using DESIGN.md/json + canon + modules. Logs unique-render decision.
  6. Each migrated page has:
    • :root block from canon.pinned first, DESIGN.md fallback otherwise.
    • Canon CSS injected after :root in the first <style>.
    • Canon header and footer applied verbatim with data-canon flag on containers.
    • Required data-* vocabulary present (data-template="<type>" on body/main, data-section per section, data-module per module instance, data-slot per slot container, locally scoped).
    • Provenance block as first child of <head> with all required shas.
    • JSON-LD per page-type (Article on news posts, ItemList on news, extends-Organization on about, none on 404).
    • Internal links rewritten to migrated-tree paths; missing-slug targets flagged data-broken-link="true".
    • Resolved <head> metadata composed per reference/metadata-and-jsonld.md five categories.
  7. Each page's directory contains index.html AND _meta.json sidecar with full migrationDecisions[] trace, slotsFilled, modules, canonShas, deviations.
  8. Copies referenced media to migrated/assets/media/; verifies fonts and favicon variants present.
  9. Writes migrated/robots.txt and migrated/sitemap.xml with page-type-derived priorities.
  10. Updates state.json: 25 pages move to migrated.
  11. Prints summary including:
    • Render branch counts (3 A / 21 A′ / 1 B).
    • Pages with non-trivial decisions (with one-line "why").
    • Broken internal links count + target slugs.
    • Bespoke slots crossing promotion threshold (if any).
    • One-line note acknowledging brand-faithful inversion lifts.

User prompt (run 2 — immediately after run 1, no other changes)

$stardust migrate

Expected behavior (run 2 — idempotent re-run)

  1. Zero file writes. Every page is sha-compared. All match → all 25 skipped.
  2. Summary: 0 migrated, 25 unchanged (idempotent skip), 0 failed.
  3. state.json is NOT updated for unchanged pages.

User prompt (run 3 — after editing DESIGN.md to bump section padding)

$stardust migrate

Expected behavior (run 3 — DESIGN-driven re-render)

  1. designMd sha changed → all 25 pages re-render.
  2. Per reference/migration-procedure.md § :root block sourcing: canon.pinned retains precedence for pinned paths; non-pinned paths inherit the new DESIGN.md value.
  3. Summary reflects the cause: Re-rendered: DESIGN.md sha changed (1a2b3c4 → 4d5e6f7).

User prompt (run 4 — after editing canon.css)

$stardust migrate

Expected behavior (run 4 — canon-driven re-render)

  1. canon CSS sha changed → all 25 pages re-render (canon affects every page).
  2. No stale-flagging is triggered. Stale-flagging fires only when an underlying skill (prototype --prep approval, extract --prep module-catalog update, direct --re-direct) commits a content-aware change. A manual edit to canon.css doesn't run any of those skills — migrate detects the change purely through sha-mismatch in the idempotent-skip check.
  3. Summary surfaces canon-driven cause: Re-rendered: canon.css sha changed (1k2l3m → 9m8n7o).

The user manually deletes stardust/current/pages/programs__shelter.json and the corresponding state.json entry. Then runs $stardust migrate.

Expected behavior (run 5)

  1. Pages that linked to /programs/shelter (e.g., the home program-grid module instance, the programs listing) get their links flagged data-broken-link="true" and the href rewritten to the migrated-tree path the slug WOULD have served at (/programs/shelter/).
  2. Run summary surfaces:
    Broken internal links: 1
      /programs/shelter   referenced by 3 pages; not in inventory
    
  3. Migration succeeds for all 24 remaining pages.

User prompt (run 6 — bespoke slot promotion)

The home, get-help, and donate pages each carry a hotline-211 module instance with a <span data-slot="state" data-bespoke>Utah</span> element. The state slot is not in the module catalog. After $stardust migrate:

Expected behavior (run 6)

  1. All three instances render with data-bespoke on the state slot.
  2. _meta.json sidecar for each page records a module-bespoke-slot decision.
  3. Run summary surfaces the promotion suggestion:
    Bespoke slots crossing promotion threshold: 1
      hotline-211: "state"  (3 instances) —
      consider `$stardust prepare-migration --refine-module`
    
  4. Promoting via the suggested command updates the module catalog (slot state becomes canonical with appropriate type/required/default), and the next migrate run drops the data-bespoke flag from those instances (sha mismatch triggers re-render).

User prompt (run 7 — color-reservation violation)

The static-typed archetype that legal/privacy would fork from contains a .footnote-callout element with inline style="color: #DC323D" (centennial-red, reserved to the trh-100-lockup module). When legal/privacy renders via Path A' and inherits that section, the rendered output carries the violating color outside the reserved context. The page fails validation per DESIGN.json.extensions.colorReservations[].

Expected behavior (run 7)

  1. The page is not written; its directory in migrated/ is left in its prior state (or absent on first run).
  2. state.json.lastRun.failures[] records:
    {
      "slug": "legal__privacy",
      "kind": "color-reservation",
      "color": "#DC323D",
      "reservedFor": ["module:trh-100-lockup"],
      "found": "inline style on .footnote-callout"
    }
    
  3. Run summary surfaces the failure with a remediation hint (re-iterate prototype to remove the reserved color, or promote the violating element to a trh-100-lockup module instance).

User prompt (run 8 — Path A′ template adaptation)

An article page (news/post-2026-04-08-volunteer-recap) contains a video embed in its body — the news/post-housing-summit archetype has no video slot. After $stardust migrate:

Expected behavior (run 8)

  1. Path A′ renders the article using the archetype's structure, injects all standard article slots (headline, byline, body, related), and places the video embed in an overflow region after data-slot="article-body".
  2. The page's _meta.json sidecar records:
    {
      "kind": "template-adapted",
      "template": "article",
      "adaptations": [
        { "what": "video embed", "where": "after article-body slot", "via": "overflow region" }
      ],
      "reason": "Content carries a video module not present in canonical article template"
    }
    
  3. Run summary surfaces the adaptation with a one-line "why".

User prompt (run 9 — canonical strategy: deployUrl unset)

state.json.site.deployUrl is null. Run $stardust migrate.

Expected behavior (run 9)

  1. Each migrated page's <link rel="canonical"> preserves the canonical from current/pages/<slug>.json § metadata.canonical verbatim (typically pointing back to the live origin). For presales/staging contexts where the migrated tree isn't deployed, this attributes search-engine signals back to the live site correctly.
  2. Run summary makes no special mention of canonical strategy (the default-preserve behavior is silent).

User prompt (run 10 — canonical strategy: deployUrl set)

User edits state.json.site.deployUrl to "https://migrated.example.com". Run $stardust migrate.

Expected behavior (run 10)

  1. All 25 pages re-render (state.json change invalidates the canonical-derived metadata; migrate recomputes per page).
  2. Each migrated page's canonical is rewritten to https://migrated.example.com/<slug-path>/. Home is https://migrated.example.com/.
  3. Run summary surfaces the deployUrl-driven re-render cause.

User prompt (run 11 — brand-faithful inversion negative case)

The user edits direction.md to remove #FFFFFF from the brand_faithful_inversions[] list while leaving canon.css unchanged (canon.css still uses #FFFFFF as the page ground). Run $stardust migrate.

Expected behavior (run 11)

  1. With #FFFFFF no longer declared as inverted, the impeccable "no pure black/white" hard rule applies to every migrated page (canon CSS rules using #FFFFFF are now in violation).
  2. Migrate refuses every affected page and records each failure in state.json.lastRun.failures[] with kind: "hard-rule-violation", the rule name, and the offending token/value.
  3. Run summary surfaces the failures with a remediation hint (re-add the inversion to direction.md, or re-iterate the canon-author prototype to move off pure white).

What this eval covers

Behavior Run Branch
Path A render verbatim from approved prototype 1 A
Path A′ render via template fork + slot injection 1 A′
Path B unique render with canon + modules 1 B
Canon application (chrome verbatim + canon.css) 1 all
Module rendering via canonical files 1 all
_meta.json sidecar with migrationDecisions 1 all
JSON-LD per page-type 1 all
Internal-link rewriting (always migrated-tree) 1, 5 all
Brand-faithful inversion lifts 1 all
Idempotent zero-write re-run 2 all
DESIGN-driven re-render (sha change cascade) 3 all
Canon-driven re-render (sha change cascade) 4 all
Broken-link reporting on missing slugs 5 all
Bespoke slot promotion threshold (3 instances) 6 A′
Color-reservation enforcement 7 all
Template adaptation (extra content → overflow region) 8 A′
Canonical strategy (deployUrl unset → preserve) 9 all
Canonical strategy (deployUrl set → rewrite) 10 all
Brand-faithful inversion negative (rule restored) 11 all