CtrlK
BlogDocsLog inGet started
Tessl Logo

adobe/stardust

Redesign an existing website to make it better. Built on top of impeccable.

71

Quality

89%

Does it follow best practices?

Run evals on this skill

Adds up to 20 points to the overall score

View guide

SecuritybySnyk

Low

Low-risk findings worth noting

Overview
Quality
Evals
Security
Files

coverage-model.mdskills/rollout/reference/

rollout coverage model (operational reference)

The contract the two scripts maintain. Design rationale is in notes/rollout/PLAN.md; this doc is the runtime behaviour.

Files (all under stardust/rollout/)

FileWriterContract
rollout.jsoninventory + blocks + update-coverage + verifytarget + DA config + lastRun counts
coverage/pages.jsoninventory (rows) + update-coverage/verify (delivery)one row per migrated page
coverage/templates.jsoninventory + roll-up writerspages grouped by templateId + roll-ups
coverage/blocks.jsonblocks (rows) + update-coverage (delivery)one row per distinct block (dedup unit)
plan.jsonplandedup-driven delivery order + per-page convert/reuse
optimize/findings.jsonoptimize + findings + autofixmulti-source quality findings (detect→fix→verify)
optimize/scorecard.jsonoptimize + findings + autofixper-layer health + overall + history
site/{sitemap.xml,robots.txt,manifest.json}assemblesite-level artifacts
dashboard/{index.html,data.json}dashboardself-contained progress view + snapshot

rollout writes nothing outside this directory. stardust/migrated/, state.json, and the rest of the agnostic core are read-only inputs.

Page delivery status lifecycle

┌──── migrate emits page ────────────────────────┐
                                     ▼                                                 │
  content-pending ──► pending ──► converting ──► deployed ──► verified ──────────► stale
        ▲                ▲            │                                                │
        │                └─ inventory │                                                │
        │                   seeds new └──► failed ──(retry)──► converting …           │
        │                                                                              │
        └─ inventory seeds (archetypes-only mode, no migrated HTML yet)               │
                         stale/failed pages are re-picked by the next Phase B pass ◄──┘
  • content-pending — inventoried from state.json in archetypes-only mode; no migrated HTML exists yet. Block code is live (deployed via the archetype); the document push is deferred to the content track. Advances automatically to pending when migrate emits the page's HTML and inventory is re-run. Not a failure — these pages are tracked, not lost.
  • pending — inventoried with migrated HTML, not yet delivered. New pages start here (full mode) or transition here from content-pending.
  • convertingdeploy is mid-flight on this page.
  • deployed — pushed to the branch preview; not yet verified.
  • verified — renders live (200, blocks decorate, no about:error).
  • failed — a delivery error; error carries the reason. Non-fatal to the run.
  • stale — was deployed/verified, but migrate re-emitted the page (its sourceHash changed). Needs re-delivery.

Artifact type + fidelity tier (orthogonal to status)

Two further per-page fields make delivery quality auditable; both are independent of delivery.status:

  • delivery.typepage | fragment | index. Drives what "renders correctly" means: a fragment has no <h1>, an index is JSON with rows. verify.mjs infers it from the path when unset and reports the distribution; a one-size <h1> check false-fails fragments without it.
  • fidelityTierarchetype | sibling | thin (+ archetypeSource, gatesPassed[]), set by migrate from the render branch (migrate/reference/fidelity-tiers.md). Records how much QA the page carries: archetype is craft-gated once per template; sibling is a canon-fork that inherits that structure and re-checks only content + media + the delivery contract; thin is a bodyless/PDF page rendered gracefully.

The dashboard surfaces the tier distribution alongside status, so "92/92 deployed" cannot hide "1 craft-gated, 91 ungated clones". Many unique/thin pages where one template was expected signals a missing archetype — prototype it, then re-fork its siblings.

Idempotency rules (inventory)

On every inventory.mjs run:

  • A page's sourceHash is recomputed from its migrated HTML bytes (migrated pages) or from state.json[].currentStatePath content (content-pending pages).
  • If a page already exists in pages.json:
    • hash unchanged → its delivery is preserved verbatim.
    • hash changed and prior status ∈ {deployed,verified} → status becomes stale (delivered URL retained); otherwise the prior status is kept.
    • prior status was content-pending and migrated HTML now exists → status advances to pending and sourceHash is recomputed from the HTML bytes.
  • A page not in prior coverage → seeded content-pending (if sourced from state.json only) or pending (if migrated HTML is present).
  • Pages are keyed by slug (from the _meta.json sidecar, else derived from the delivered path, else from state.json[].slug). The assets/ bundle is never inventoried.

Block delivery status lifecycle

pending ──► converted ──► deployed ──► verified
     ▲            (the distinct block is converted ONCE, on its
     └─ blocks.mjs  conversion point in plan.json; siblings reuse it)
  • pending — inventoried as a distinct block, not yet converted.
  • converted — its EDS block (blocks/<edsBlockName>/) or fragment exists.
  • deployed / verified — live on the delivered site.

blocks.mjs is idempotent: a block already past pending keeps its status and edsBlockName; only still-pending blocks get a freshly derived name.

Dedup contract (plan.json)

plan.mjs guarantees each distinct module block is converted on exactly one page (the first in delivery order that uses it). Per page it emits:

  • convert[] — blocks introduced here → deploy creates them;
  • reuse[] — blocks already converted → deploy's Step-7 brief reuses them by edsBlockName, never recreating.

Chrome (header/nav/footer) is not per-page; it's listed once under plan.json.fragments and delivered as the authored /nav + /footer documents (published content, on the roster like any page).

Verify

verify.mjs flips delivered pages to verified or failed based on: reachable (HTTP 200 / file present), no about:error in the body, and every internal href="/…" resolving to a known delivered path. Offline --root <dir> mode maps each delivered path back to a file for testing against a local export.

Optimize gate (findings lifecycle)

open ──(no longer detected, in scope)──► fixed ──(regression)──► open
   │                                                                ▲
   ├──(human)──► accepted / wontfix  (never auto-reopened)          │
   └────────────────────── still detected ─────────────────────────┘

optimize.mjs is the delivery-quality gate. It writes optimize/findings.json (append-only runs[] + status-tracked findings[]) and optimize/scorecard.json (per-layer 0–100, null for unassessed judgment layers, + history[]). The gate exits non-zero while any open P1 is in scope; fixability routes the fix (platform-migration → rollout re-deploys; design-pass → upstream; out-of-scope → informational). See checks.md for the catalog.

Roll-ups

update-coverage.mjs, inventory.mjs, blocks.mjs, and verify.mjs all re-derive, from the per-unit rows:

  • each template's { verified, deployed, pending } in templates.json;
  • the site-wide lastRun.pages + lastRun.blocks counts in rollout.json.

So the counts never drift from the per-unit truth — they are always recomputed, never incremented.

skills

README.md

tile.json