Sync Shadcn
Handle $ARGUMENTS.
Goal: compare the tracked upstream shadcn docs baseline with the current
../shadcn/apps/v4 target, inventory every added/modified/deleted upstream
change, map each change to Plate's docs app, classify the merge decision, write
a reviewable plan under docs/sync/shadcn, directly merge any qualifying tiny
overlap fixes, then stop for user review of the remaining slices. A later
explicit user acceptance starts implementation mode for a named plan and slice.
If $ARGUMENTS starts with a command name, dispatch to that command before the
default planning/implementation flow. If $ARGUMENTS names a feature, product
surface, or slice, run a scoped planning lane for that scope. The default
full-range planning lane applies only when no command or scope is mentioned.
This skill exists because Plate's docs app is a forked product surface, not a
generic shadcn mirror. Upstream owns the Fumadocs/shadcn docs architecture.
Plate owns Plate docs content, editor demos, registry content, API MDX, CN docs,
MCP, Plate Plus hooks, GA, and a small set of intentional forks.
Autogoal Dependency
This skill depends on
$autogoal. Load
autogoal before mutable sync state, upstream pull/fetch, run artifact writes,
status JSON edits, or implementation delegation.
sync-shadcn is a derived autogoal workflow and a two-phase lane:
- Planning mode is the default. It writes the range plan, updates
lastPlannedCommit, directly applies qualifying micro-overlap merges,
asks the user to review the remaining plan, and stops.
- Implementation mode starts only after the user explicitly accepts a plan and
slice in a later instruction, except for the micro-overlap direct merge
exception below.
- Default flow mode: one-shot execution for planning mode and one-shot
execution for accepted implementation mode. They are separate activations.
- Use collaborative planning only when the user is explicitly deciding policy
before a range plan is written.
- Primary template:
docs/plans/templates/sync-shadcn.md.
- Default packs: none. Add
docs if docs/content pages are edited during an
accepted implementation, browser if visible docs UI is edited, and
agent-native if .agents/**, .claude/**, .codex/**, skills, commands,
prompts, or user-action tooling are edited.
- Required evidence types:
command, source-audit, artifact, and N/A
rows. Add browser evidence when a planning scope or accepted
implementation touches visible docs UI.
- Visual sync scopes must capture comparable screenshots of the upstream
shadcn page and the Plate page before making or closing a visual parity call.
Save only screenshots and notes, not broad upstream patch files.
autogoal owns goal lifecycle, blocked/completion semantics, active-goal
conflict handling, plan instantiation, output-budget discipline, and
check-complete.mjs.
sync-shadcn owns shadcn range policy, commit accounting, upstream inventory
classification, Plate fork/exclusion decisions, status JSON semantics, and
merge-slice handoff.
Micro-Overlap Direct Merge Exception
The default review boundary is still real. Do not use it as an excuse to miss
obvious tiny upstream fixes on components Plate already mirrors.
During planning, directly merge a change when all of these are true:
- The upstream row maps to a retained Plate component, primitive, hook, or
utility with a clear local owner path, not to upstream product content.
- The parent surface is already
synced, an accepted partial sync, or an
obvious overlapping primitive such as Button, Badge, Input, Command,
Tooltip, PageHeader, or the copied docs-shell components.
- The diff is tiny: one local file, one behavior/class/token/prop/import fix,
no new files, no deleted files, no new dependency, no route, no data model,
no generated output, and no package or lockfile edit.
- The local Plate file still has the old value or an equivalent local variant
that should receive the same fix.
- The change does not touch settled exclusions: v0, create, charts, colors,
Rhea/theme/customizer/style-registry product surfaces, upstream docs prose,
external registry directory content, or generated
public/r/** output.
- No product judgment is needed. If the change changes layout, UX, copy,
route shape, docs concepts, registry semantics, or multi-file architecture,
it is not a micro-merge.
Examples of direct merges:
- Replace one stale utility class on Plate's copied
Button because upstream
fixed the same class on every style variant.
- Apply one bugfix conditional to a copied
Command or CopyButton primitive
when Plate has the same bug and no Plate product requirement changes.
- Remove one dead prop/import from a synced component when upstream removed it
and Plate has no local dependency on it.
Examples that still require review:
- Package bumps, lockfile changes, registry schema/route changes, docs concept
additions, new components, deleted components, multi-file UI chunks, visual
layout rewrites, sidebar/search behavior changes, generated registry output,
and anything touching a deferred or rejected product surface.
When a micro-overlap merge is found:
- Record it in the run plan under
## Micro Auto-Merges with upstream path,
Plate path, focused diff summary, why it qualifies, and verification.
- Patch the Plate owner file directly in the same activation.
- Run the smallest meaningful verification: focused eslint/typecheck/source
audit; add browser proof when the changed component is browser-visible and a
stable route exists.
- Add a
partialSyncs entry if the full baseline does not advance. Keep
lastSyncedCommit unchanged unless the whole range is complete.
- Continue to stop for review on every non-micro slice.
Commands
Supported commands:
status: summarize current shadcn sync state, partial syncs, deferred
decisions, and recommended next step without writing sync artifacts.
dashboard: regenerate the structured feature-delta dashboard under
docs/sync/shadcn for visual review of synced, deferred, rejected, forked,
and pending shadcn sync decisions.
apply: apply a copied dashboard review payload to
docs/sync/shadcn/deltas.json, answer question-only rows without mutation,
implement rows targeting synced, then regenerate the dashboard when rows
changed.
review: re-audit the current tracked shadcn range against ../shadcn and
the current Plate checkout before trusting an existing plan.
Feature-scoped planning:
- Any non-command $ARGUMENTS value is a user-named scope. Treat the full
argument string as the scope label instead of hardcoding allowed feature names.
- Scope labels can describe UI surfaces, routes, product areas, registry
groups, content families, or implementation slices.
- If the scope is too vague to map to upstream and Plate files, ask one focused
question before writing artifacts.
Command parsing:
- The first $ARGUMENTS token is the command when it matches a supported command.
- The full $ARGUMENTS string is the scope when the first token is not a
supported command.
- If no command or scope is present, use the default full-range
planning/implementation flow.
- Reserved commands are
status, dashboard, apply, and review; do not
treat them as scope labels.
- Scopes are planning lanes, not broad implementation permission. A scoped
plan still stops for user review before non-micro
apps/www work.
Scoped Planning
Use sync-shadcn <scope> when the user wants to sync only one named surface
before reviewing broader docs sync work.
Purpose:
- compare the tracked upstream range, but inventory and classify only changes
that affect the named scope
- write a reviewable scope-specific plan under
docs/sync/shadcn
- avoid the default full-range lane unless the user invokes
sync-shadcn
without a command or scope
Scope discovery:
- Translate the user-named scope into likely upstream files under
../shadcn/apps/v4 and likely Plate files under apps/www.
- Search names, route paths, component names, config keys, registry names, and
docs paths that match the scope.
- Include all matching hunks that directly affect the scope.
- Exclude adjacent changes that only share a file but belong to another surface;
classify those as out-of-scope.
Scoped planning rules:
- Save artifacts in a scope-named run directory or plan name, for example
docs/sync/shadcn/runs/<date>-<base>-to-<target>-<scope-slug>/.
- Use upstream diffs/logs for the same baseline and target as the default lane,
but filter inventory rows to scope-matching files and patch hunks.
- Also record an out-of-scope count for upstream rows in the range so it is
clear the scoped plan cannot advance
lastSyncedCommit alone.
- If the scope is visual or route-owned, capture upstream and Plate screenshots
for the matching route(s) at the same viewport before finalizing the plan.
Use
docs/sync/shadcn/runs/<range>/screenshots/ for committed evidence, and
include screenshot paths plus the visible deltas in the plan.
- Do not update
lastSyncedCommit from a scoped plan. Scoped sync can add a
partialSyncs entry after accepted implementation, but the baseline advances
only when the full range is accounted for.
- The plan's recommended slices must stay inside the named scope. If a file also
contains unrelated changes, classify the scope hunk as
smart-merge and the
unrelated hunks as out-of-scope for this lane.
- Final planning output must say that the default full sync lane remains
pending for the out-of-scope rows.
status
Use sync-shadcn status when the user wants a quick checkpoint before choosing
the next sync step.
Purpose:
- show the current baseline, latest planned target, current upstream target, and
whether the tracked plan looks fresh enough for decision-making
- list accepted partial syncs already landed
- list deferred decisions so the user can choose what to do next
- list reviewable Plate-vs-shadcn differences that are still intentionally
undecided or deferred, especially visual parity gaps from scoped sync plans
- recommend the next command or decision
Status mode may:
- read
docs/sync/shadcn/status.json
- read
lastPlan, the linked inventory.md, and the latest run directory when
present
- resolve
../shadcn refs and fetch origin main --tags when the user asks for
current upstream freshness; if fetch fails, report freshness as unverified
- count upstream commits and file-status rows for
lastPlannedCommit..origin/main
- summarize
partialSyncs[*].slices, partialSyncs[*].deferred,
and plan Questions
- when the user supplies words after
status, treat the remaining argument as
a status scope filter, for example status our /editors vs shadcn /blocks;
prefer the matching partialSyncs[*].plan, lastPlan, or run directory
before falling back to global status
- summarize remaining reviewable differences from the matched plan's
Recommended Merge Slices, Visual Evidence, Implementation Result, and
partialSyncs[*].deferred
Status mode must not:
- patch
apps/www
- write
docs/sync/shadcn/runs/**
- write review artifacts
- change
lastSyncedCommit, lastPlannedCommit, lastPlan, or
partialSyncs
- delegate implementation to
task
- treat listed deferred items as accepted decisions
- list settled exclusions or preserved Plate forks as if they still need
action; those belong in
review evidence or the plan, not routine status
output
Status must distinguish three things:
Landed: accepted partial sync slices already applied.
Reviewable differences: Plate still differs from upstream and the
difference is not settled policy. These are the items the user can re-decide.
Include the upstream behavior, current Plate behavior, likely owner files,
and the smallest next command or decision.
Settled differences: explicit exclusions and preserved Plate forks. Do not
list these by default unless the user asks to re-open them.
Deferred item sources, in order:
docs/sync/shadcn/status.json partialSyncs[*].deferred
- the selected plan's
Questions section
- recommended merge slices marked
defer, needs-question, or not yet
implemented
- visual evidence rows where the plan says a Plate-vs-upstream difference
still needs work
- implementation-result notes that explicitly leave a follow-up slice open
- status update notes that say
lastSyncedCommit cannot advance
For visual scoped status, do not stop at "fresh" when visible deltas remain.
Report them as reviewable differences even when the scoped implementation was
verified. Example:
Reviewable differences:
- BlockViewer toolbar: upstream `/blocks` has compact device controls,
refresh, separated command pill, and v0 action; Plate `/editors` still keeps
its current toolbar density and excludes v0. Decision: sync toolbar spacing
only, keep Plate install/source behavior and no v0; or leave as Plate fork.
Collapse upstream product/theme/style noise into its owning deferred decision.
For example, Rhea/style/theme/generated style registry rows are part of the
upstream create/theming product surface; do not list them as separate status
items unless the user explicitly asks to review that product surface.
Status checks:
node -e '
const fs = require("fs");
const status = JSON.parse(fs.readFileSync("docs/sync/shadcn/status.json", "utf8"));
console.log(JSON.stringify({
lastSyncedCommit: status.lastSyncedCommit,
lastPlannedCommit: status.lastPlannedCommit,
lastPlan: status.lastPlan,
partialSyncs: status.partialSyncs ?? []
}, null, 2));
'
git -C ../shadcn fetch origin main --tags
TARGET=$(git -C ../shadcn rev-parse origin/main)
PLANNED=$(node -e 'console.log(JSON.parse(require("fs").readFileSync("docs/sync/shadcn/status.json", "utf8")).lastPlannedCommit || "")')
git -C ../shadcn log --oneline --decorate "$PLANNED..$TARGET" -- apps/v4
git -C ../shadcn diff --name-status --find-renames "$PLANNED..$TARGET" -- apps/v4
Status output shape:
Status: <fresh | upstream-ahead | no-plan | blocked-ref | unverified>
Baseline: <lastSynced-short>
Planned: <lastPlanned-short>
Current upstream: <target-short>
Plan: <path or none>
Partial syncs:
- <date/range>: <landed slices>
Reviewable differences:
- <surface>: upstream <behavior>; Plate <behavior>; decision needed <adopt |
smart-merge | keep fork>; files <paths>
Deferred decisions:
- <item>
Next: <run review | rerun planning | decide deferred item | implement accepted slice | advance baseline>
Keep status concise, but do not hide reviewable differences behind a generic
"deferred" label. If the user wants full evidence, tell them to run
sync-shadcn review.
apply
Use sync-shadcn apply when the user pastes a dashboard review payload.
Purpose:
- apply rows listed directly under
$sync-shadcn apply or under an optional
Rows heading
- answer rows listed under
Questions in chat without mutating
deltas.json
- keep the copied dashboard prompt short by storing the mutation contract in
this command
Apply mode may:
- read and update
docs/sync/shadcn/deltas.json
- patch
apps/www, content/docs, and related source files when a listed row
targets synced or fork
- delegate a coherent implementation slice to
task when a synced or fork
row needs more than a tiny local edit
- remove screenshot refs for rows applied to
synced or rejected
- delete unreferenced local screenshot files under
docs/sync/shadcn/runs/**
- run
pnpm sync-shadcn dashboard after any JSON mutation
Apply mode must not:
- write
docs/sync/shadcn/runs/** except deleting unreferenced screenshots
- change
lastSyncedCommit, lastPlannedCommit, lastPlan, or
partialSyncs
- infer decisions for rows not listed in the pasted payload
- mutate
deltas.json for question-only rows
- mark a row
synced or fork before implementation is present and verified
- ask for review when the row has clear files, suggestion, and acceptance
criteria; ask one focused question only when the target behavior is unclear
Payload shape:
$sync-shadcn apply
- command-menu/command-footer-shortcuts (Command Menu / Footer shortcuts and copy payloads): defer -> pending note: Add copy only for components and editor kits.
Questions:
- registry/registry-review (Registry / Full registry review): Which registry rows should include copy shortcuts?
Apply rules:
- A direct bullet row under
$sync-shadcn apply, or under an optional Rows
heading, is the only mutation unit.
- Set each listed item state to the requested target state.
- Target states
pending, defer, and rejected are metadata decisions.
- Target state
synced is implementation mode: inspect the row files and
suggestion, implement the requested change, run focused verification, then
update deltas.json to synced.
- Target state
fork is also implementation mode when the row's note,
suggestion, or files imply work in Plate. Inspect the row files and
suggestion, implement or verify the intentional Plate-owned fork, run focused
verification, then update deltas.json to fork.
- A
fork update may be metadata-only only when the Plate fork already exists,
the row note does not ask for code/content work, and the source evidence is
checked before updating deltas.json.
- Use notes to update
decision, suggestion, or summary text when
appropriate.
- If a note is only a question, keep it under
Questions, answer it in chat,
and do not mutate JSON.
- When applying
synced or rejected, remove that row's screenshots object
and delete unreferenced local screenshot files.
- Keep screenshots for
fork rows.
- If any row is applied, run
pnpm sync-shadcn dashboard.
dashboard
Use sync-shadcn dashboard when the user wants a visual decision board for
the shadcn sync delta instead of prose status output.
Purpose:
- render feature-owned sync deltas grouped by product surface, such as header,
home, editors, releases, command menu, registry, create, preview routes, and
sidebar
- show review states that can be re-decided later:
pending, defer,
fork, rejected, and synced
- keep settled exclusions visible in the dashboard without polluting routine
status output
- make user review possible through a local static HTML artifact
- include browser-only state controls, note textareas, and a copy button that
builds a concise
$sync-shadcn apply payload
- include quick row actions in two rows:
Ask, Defer, then Sync,
Reject, Fork; pending is a state/filter, not a row action
- keep note textareas locked until the user chooses an explicit row intent:
Ask, a quick apply action, or a changed state value
- render review actions as selected controls;
Sync copies an
$sync-shadcn apply row targeting synced, which means implementation mode
for that row
- render
Fork as an implementation-capable action too: copied payloads
targeting fork mean "make or verify the Plate-owned fork", not "metadata
only"
- use
suggestion as the durable item field for Plate-owned recommendation
text, rendered as Suggestion in the dashboard with an explicit Apply
action that copies that suggestion into Note
- treat
Ask as question-only: it keeps the current row state, writes the row
under Questions, and must not mutate deltas.json
- treat question-only notes as questions to answer in chat, not as decisions to
apply to
deltas.json; only rows under Rows in a $sync-shadcn apply
payload should mutate structured state
- open on the actionable filter by default:
pending and defer; keep synced, rejected, and fork available
behind explicit filters
- split state filters into an Action row and a Done row so active review work
is visually separate from settled policy/history
- render Suggestion and shadcn screenshot columns for non-
synced review rows when
row screenshot paths exist, with click-to-zoom and close behavior in the
static HTML page
- remove screenshot refs for
synced and rejected rows during dashboard
generation, and delete unreferenced local screenshot files; keep screenshot
evidence for fork rows because forked differences stay useful
- render one card per delta item instead of a wide table, with Suggestion vs shadcn
text in two responsive columns and empty screenshot areas hidden
- do not use an item-level
next field in deltas.json; status and workflow
guidance should come from item state, decision, suggestion, and group summary
Dashboard mode may:
- read
docs/sync/shadcn/status.json
- read and update
docs/sync/shadcn/deltas.json
- write
docs/sync/shadcn/dashboard.json
- write
docs/sync/shadcn/dashboard.html
Dashboard mode must not:
- patch
apps/www
- write
docs/sync/shadcn/runs/**
- change
lastSyncedCommit, lastPlannedCommit, lastPlan, or
partialSyncs
- delegate implementation to
task
- treat a dashboard item as user acceptance to implement
State meanings:
synced: the slice was accepted, implemented, and verified.
defer: the item is acknowledged but intentionally postponed.
pending: the item has no final decision yet, including rows waiting on a
user decision.
fork: Plate intentionally keeps a different implementation, and that
implementation is present or has been verified before the row is marked fork.
rejected: upstream behavior is explicitly excluded.
Dashboard source:
docs/sync/shadcn/deltas.json is the editable structured decision source.
docs/sync/shadcn/dashboard.json and
docs/sync/shadcn/dashboard.html are generated views.
- When adding a landed implementation slice, update
status.json first, then
add or update the matching deltas.json feature row, then regenerate the
dashboard.
- When rejecting, deferring, or forking a feature, record the upstream behavior,
suggestion, owner files, and state rationale in
deltas.json.
- For non-
synced visual rows, add screenshot paths under
screenshots.suggestion and screenshots.shadcn when available. Leave
source-only rows blank.
- The HTML review controls are intentionally not persistent. The user can mark
many rows, copy the generated prompt, and send it back; Codex applies the
JSON edits and regenerates the dashboard.
Dashboard command:
pnpm sync-shadcn dashboard
This regenerates dashboard.html and opens it in the local browser. Use
--no-open or SYNC_SHADCN_NO_OPEN=1 when running in a non-GUI check.
Dashboard output shape:
Dashboard: docs/sync/shadcn/dashboard.html
Data: docs/sync/shadcn/dashboard.json
Opened: file:///.../docs/sync/shadcn/dashboard.html
| Feature | State | Items |
| --- | --- | ---: |
| Registry | defer | 2 |
review
Use sync-shadcn review when the user asks whether the latest sync plan is
still fresh, whether a previously written plan can still be implemented, or
whether current apps/www drift changed the merge posture.
Purpose:
- prove whether
docs/sync/shadcn/status.json, the latest plan artifacts, the
current ../shadcn/apps/v4 target, and the current Plate docs checkout still
describe the same sync problem
- find new upstream commits since
lastPlannedCommit
- find stale inventory artifacts for the
lastSyncedCommit..target range
- re-run local Plate owner/source evidence for actionable rows before
implementation
Inputs:
- optional plan path or run directory; default to
lastPlan from
docs/sync/shadcn/status.json
- optional target ref; default to
origin/main in ../shadcn
- baseline from
lastSyncedCommit
- planned target from
lastPlannedCommit
Review mode may:
- fetch
../shadcn and resolve exact refs
- read
docs/sync/shadcn/status.json, the selected plan, inventory.md, and
upstream-name-status.tsv
- recompute upstream name-status/numstat/log data into a temporary review file
under the same run directory or under
docs/sync/shadcn/reviews/
- compare recomputed inventories with the stored run artifacts
- re-run scoped
rg/file-existence checks for Plate owner paths, explicit
exclusions, preserved forks, partial sync entries, and recommended slices
- write a dated
review.md artifact with the verdict and evidence
Review mode must not:
- patch
apps/www
- change
lastSyncedCommit, lastPlannedCommit, lastPlan, or
partialSyncs
- delegate implementation to
task
- create a new implementation plan or advance the baseline
- treat a fresh review as user acceptance to implement
Review checks:
git -C ../shadcn fetch origin main --tags
node -e '
const fs = require("fs");
const status = JSON.parse(fs.readFileSync("docs/sync/shadcn/status.json", "utf8"));
console.log(JSON.stringify({
lastSyncedCommit: status.lastSyncedCommit,
lastPlannedCommit: status.lastPlannedCommit,
lastPlan: status.lastPlan,
partialSyncs: status.partialSyncs?.length ?? 0
}, null, 2));
'
BASE=$(node -e 'console.log(JSON.parse(require("fs").readFileSync("docs/sync/shadcn/status.json", "utf8")).lastSyncedCommit || "")')
PLANNED=$(node -e 'console.log(JSON.parse(require("fs").readFileSync("docs/sync/shadcn/status.json", "utf8")).lastPlannedCommit || "")')
TARGET=$(git -C ../shadcn rev-parse origin/main)
git -C ../shadcn merge-base --is-ancestor "$BASE" "$TARGET"
git -C ../shadcn log --oneline --decorate "$PLANNED..$TARGET" -- apps/v4
git -C ../shadcn diff --name-status --find-renames "$BASE..$TARGET" -- apps/v4
Staleness verdicts:
fresh: current upstream target equals lastPlannedCommit, recomputed
upstream inventory matches the selected run artifact, required Plate owner
paths/source evidence still exist, and no partial-sync/status contradiction is
found.
stale-upstream: origin/main has newer apps/v4 commits than
lastPlannedCommit or the recomputed upstream inventory differs from the
selected run artifact.
stale-local: Plate owner paths or local search evidence used by the plan no
longer match the current checkout.
stale-status: status.json contradicts the selected plan, for example the
selected plan target differs from lastPlannedCommit without an explicit
override, or partialSyncs claim work that the local checkout no longer
shows.
blocked-ref: the baseline, planned target, selected target, or ancestry
cannot be proven.
The review artifact must include:
- selected plan/run directory
- base, planned target, and current target SHAs
- upstream commit count and file-status count for
PLANNED..TARGET
- inventory comparison result for
BASE..TARGET
- local Plate owner/source evidence summary
- explicit exclusions and preserved forks checked
- status semantics checked
- verdict and the next action
Review output shape:
Review: <fresh | stale-upstream | stale-local | stale-status | blocked-ref>
Range: <base-short>..<target-short>
Plan: <path>
Report: <path>
| Check | Result | Evidence |
| --- | --- | --- |
| upstream target | ... | ... |
| inventory | ... | ... |
| Plate owners | ... | ... |
| status semantics | ... | ... |
Next: <use the existing plan | rerun planning | fix local drift | resolve refs>
Before substantive work:
node .agents/skills/autogoal/scripts/create-goal-scratchpad.mjs \
--template sync-shadcn \
--title "sync shadcn <short range or target>"
Fill the generated plan immediately. It must name the objective, flow mode,
completion threshold, verification surface, constraints, boundaries, output
budget strategy, blocked condition, and planned run directory. Do not replace it
with a smaller ad hoc plan.
Completion requires the named sync evidence plus:
node .agents/skills/autogoal/scripts/check-complete.mjs <docs/plans/path>
Never mark the active goal complete just because a range plan was written if
the goal also required implementation, baseline advancement, or user acceptance.
User Review Boundary
This mirrors the important part of slate-plan: plan first, stop, then execute
only after explicit acceptance.
Planning mode may:
- fetch/pull
../shadcn
- create the active goal plan
- write
docs/sync/shadcn/runs/<range>/ artifacts
- update
lastPlannedCommit and lastPlan
- directly apply qualifying micro-overlap merges and record them as partial
syncs
- ask one review/decision question
Planning mode must not:
- patch
apps/www except for qualifying micro-overlap direct merges
- delegate to
task
- advance
lastSyncedCommit
- treat "recommended first slice" as accepted
- combine plan creation and non-micro implementation in the same activation
The final planning response must say:
Review the plan. I directly merged these micro-overlap fixes: <list or none>.
To implement the remaining slices, invoke `sync-shadcn` again with the accepted
plan path and slice.
Implementation mode requires a later user message that names or clearly accepts
the plan/slice. Then create or continue an implementation-shaped goal for that
accepted slice and proceed through task.
Hard Rules
- Use evidence, not vibes. Read upstream commits, file status, focused diffs,
local Plate files, prior decisions, screenshots for visual surfaces, and
relevant solution notes.
- Track exact commits. Never say "latest shadcn" without recording the target
SHA.
- Treat
docs/sync/shadcn/status.json as the durable baseline. Do not advance
lastSyncedCommit until every upstream change in the planned range is
accounted for as adopted, smart-merged, intentionally forked, or explicitly
excluded.
- Planning is the default output. Do not patch
apps/www unless the row
qualifies as a micro-overlap direct merge or the user accepts a merge slice in
a later instruction after reviewing a written plan.
- Do not edit generated registry output, templates output, or generated skill
mirrors by hand.
- Do not run
build:registry; local registry generation is CI-owned in this
repo.
- Do not delegate to
task in the same activation that creates or materially
updates a sync plan. Direct micro-overlap merges stay in-thread and tiny; all
bigger work waits for review.
- Keep the active
sync-shadcn goal plan current after every meaningful
decision, artifact write, classification pass, status JSON edit, accepted
implementation slice, verification run, or blocker.
- Prefer deleting old Plate fork residue over preserving compatibility layers
when upstream already owns the better model.
- Prefer upstream docs infrastructure unless Plate has a real product or
registry reason to diverge.
- Keep output comprehensive. If a diff is too large for the chat, save complete
TSV inventories under
docs/sync/shadcn/runs/<range>/ and summarize the
artifact paths in the response.
- Do not persist
.patch files in the repo. Inspect focused diffs on demand
with capped git diff commands, summarize the relevant hunks in
inventory.md or plan.md, and leave broad upstream patches out of
committed sync artifacts.
Start Gates
These gates must be resolved in the active sync-shadcn goal plan before broad
exploration:
autogoal loaded and active goal checked or created.
docs/sync/shadcn/status.json read.
docs/sync/shadcn/decisions.md read.
- Prior migration plans and solution notes checked when relevant.
- Output budget strategy recorded before running upstream diff/log commands.
../shadcn clone state known and fetched/pulled intentionally.
- Base and target refs resolved to exact SHAs.
- Base ancestry proven, or the ref problem recorded before stopping.
- Planning-only versus implementation mode decided.
- User-review boundary recorded: planning mode stops, implementation mode
requires later explicit acceptance.
Completion Gates
These gates belong in docs/plans/templates/sync-shadcn.md and must be closed
in the instantiated goal plan:
- Upstream range artifacts exist and are non-empty, or a target-only bootstrap
exception is recorded.
inventory.md accounts for every row in upstream-name-status.tsv.
- Decision counts cover every upstream row.
- Source-backed Plate mapping exists for every actionable adoption, fork,
exclusion, or question group.
docs/sync/shadcn/status.json parses and its lastPlannedCommit /
lastSyncedCommit semantics match the work actually completed.
- Planning-only runs prove no
apps/www implementation patch was made, or
record and verify every qualifying micro-overlap direct merge.
- Accepted implementation runs include focused verification for the touched
Plate surface.
- Browser proof exists when browser-visible docs UI changed, or when a
planning scope is visual and needs Plate-vs-shadcn parity evidence.
- Visual sync scopes include screenshots of both upstream shadcn and Plate
pages at matching viewport(s), plus written deltas such as background,
spacing, disabled/gray controls, nav/header items, and first-viewport
framing.
lastSyncedCommit advances only after full-row accounting, verification, and
user acceptance.
- Planning-mode final handoff lists any direct micro-overlap merges, asks the
user to review the remaining plan, and invokes
sync-shadcn again with the
accepted plan path and slice for bigger work.
check-complete.mjs passes for the active goal plan.
Durable Policy
Read these before making decisions:
docs/sync/shadcn/status.json
docs/sync/shadcn/decisions.md
docs/plans/2026-05-23-shadcn-docs-restart-comparison.md
docs/plans/2026-05-24-shadcn-base-migration-progress.md
.agents/rules/shadcn-parity.mdc
docs/solutions/best-practices/2026-05-23-shadcn-docs-restart-comparison.md
docs/solutions/developer-experience/2026-05-27-shadcn-docs-sidebar-parity-needs-source-and-dom-metrics.md
docs/solutions/developer-experience/2026-05-24-plate-init-routes-should-return-shadcn-registry-base-items.md
docs/solutions/developer-experience/2026-05-24-shadcn-v4-registry-schema-needs-source-only-validation.md
docs/solutions/developer-experience/2026-05-24-shadcn-registry-install-commands-should-use-configured-namespaces.md
docs/solutions/developer-experience/2026-05-24-fumadocs-page-tree-search-needs-locale-safe-metadata.md
Default durable decisions:
- Discard upstream v0 surfaces.
- Discard upstream
/create, /charts, /colors, and public directory-style
product pages unless the user explicitly asks for a Plate version.
- Discard Plate theme/customizer/project/lift-mode residue.
- Keep Plate docs content under
content/docs/**.
- Keep committed Fumadocs metadata as the docs navigation authority.
- Keep Plate API MDX vocabulary and generated API docs support.
- Keep Plate registry content and docs-registry generation, aligned to shadcn v4
schema/resolver semantics.
- Keep Plate editor demos,
/view/[name], and registry preview/source display.
- Keep lazy code-view source loading through
/api/registry-source/[name] for
bandwidth, but do not treat it as a public registry API.
- Keep CN docs, MCP docs/dialog, Plate Plus/Pro hooks, GA, Plate home page, and
the Slate-to-HTML special page.
- Keep Plate's sidebar accordion/filter UX only as an intentional fork rebuilt
on Fumadocs/upstream sidebar primitives.
1. Establish Upstream Clone And Refs
Do this only after the autogoal start gates are satisfied and the active
sync-shadcn plan records the output budget strategy.
Use ../shadcn as the upstream clone. Create it only if missing:
test -d ../shadcn/.git || gh repo clone shadcn-ui/ui ../shadcn
git -C ../shadcn fetch origin main --tags
test -d ../shadcn/apps/v4
Read the tracked baseline:
node -e '
const fs = require("fs");
const status = JSON.parse(fs.readFileSync("docs/sync/shadcn/status.json", "utf8"));
console.log(JSON.stringify(status, null, 2));
'
Resolve refs:
BASE=$(node -e 'console.log(JSON.parse(require("fs").readFileSync("docs/sync/shadcn/status.json", "utf8")).lastSyncedCommit || "")')
TARGET=$(git -C ../shadcn rev-parse origin/main)
git -C ../shadcn log -1 --format='%H%n%ci%n%s' "$TARGET"
If $ARGUMENTS names a base or target ref, prove it exists and use it:
git -C ../shadcn rev-parse <base-or-target-ref>
If BASE is empty, run a bootstrap audit:
- compare the whole
../shadcn/apps/v4 source against Plate
- write a plan
- ask the user before setting
lastSyncedCommit
- do not silently set the baseline
If BASE is present, prove ancestry when possible:
git -C ../shadcn merge-base --is-ancestor "$BASE" "$TARGET"
git -C ../shadcn log --oneline --decorate "$BASE..$TARGET" -- apps/v4
If BASE is not an ancestor of TARGET, stop and explain the ref problem
before planning. Do not produce a misleading change list.
2. Create A Run Artifact Directory
Use a range-keyed directory so the full evidence survives beyond chat context:
RUN_DIR="docs/sync/shadcn/runs/$(date +%Y-%m-%d)-${BASE:0:7}-to-${TARGET:0:7}"
mkdir -p "$RUN_DIR"
Save complete inventories:
git -C ../shadcn diff --name-status --find-renames "$BASE..$TARGET" -- apps/v4 \
> "$RUN_DIR/upstream-name-status.tsv"
git -C ../shadcn diff --numstat "$BASE..$TARGET" -- apps/v4 \
> "$RUN_DIR/upstream-numstat.tsv"
git -C ../shadcn log --oneline --decorate "$BASE..$TARGET" -- apps/v4 \
> "$RUN_DIR/upstream-commits.txt"
For bootstrap audits without a base ref, use target-only in the directory
name and save a full current upstream file list instead:
git -C ../shadcn ls-files apps/v4 > "$RUN_DIR/upstream-files.txt"
Do not stream huge diffs into chat and do not write .patch files. Inspect
focused diffs on demand with capped commands, then summarize only the relevant
hunks in inventory.md or plan.md:
git -C ../shadcn diff --stat "$BASE..$TARGET" -- apps/v4/app apps/v4/components apps/v4/lib
git -C ../shadcn diff "$BASE..$TARGET" -- apps/v4/app/(app)/(root)/page.tsx | sed -n '1,220p'
If the focused diff is still too large, narrow by path/function/search term and
record the command plus summary instead of saving the diff body.
3. Classify Upstream Changes
Every upstream changed file must be assigned to one subsystem:
docs-engine: Fumadocs source, page tree, MDX compilation, raw markdown
routing: Next routes, rewrites, metadata, layout groups
shell-nav-sidebar: header, footer, sidebar, mobile nav, command/search UI
mdx-code: MDX components, code blocks, copy-page, source viewer, RSS/OG
registry-contract: shadcn schema, resolver semantics, namespace behavior,
init/base item, local-file install
registry-build: registry scripts, generated source indexes, validation
preview-view: block/component preview routes and iframe/source display
product-page: create, charts, colors, blocks gallery, directory, examples
pages that are shadcn product surfaces
theme-style: global CSS, theme providers, tokens, active theme, customizer
deps-config: package, lock, tsconfig, eslint, Next config
tests: upstream app tests and fixtures
assets: public assets, manifest, images, fonts
other: only with an explanation
For each file, record:
- upstream status: added, modified, deleted, renamed
- upstream path
- subsystem
- nearest Plate owner path, or
none
- local search evidence
- default decision
- confidence
Useful local mapping heuristics:
| Upstream path |
Plate path to inspect |
apps/v4/app/** |
apps/www/src/app/** |
apps/v4/components/** |
apps/www/src/components/** |
apps/v4/lib/** |
apps/www/src/lib/** |
apps/v4/hooks/** |
apps/www/src/hooks/** |
apps/v4/content/docs/** |
content/docs/** |
apps/v4/registry/** |
apps/www/src/registry/** |
apps/v4/scripts/** |
`apps/www/script |
…(truncated)
1---2name: sync-shadcn3description: Autogoal-backed planning, status, review, dashboard, apply, and tracking for upstream shadcn docs syncs into Plate docs. Use when the user asks for `sync-shadcn`, `sync-shadcn status`, `sync-shadcn review`, `sync-shadcn dashboard`, `sync-shadcn apply`, a scoped `sync-shadcn <feature>` lane, to sync shadcn docs, audit newer shadcn docs changes, compare `../shadcn/apps/v4` with `apps/www`, update the shadcn sync baseline, or decide what to adopt, fork, defer, or exclude from upstream shadcn.4---56# Sync Shadcn78Handle $ARGUMENTS.910Goal: compare the tracked upstream shadcn docs baseline with the current11`../shadcn/apps/v4` target, inventory every added/modified/deleted upstream12change, map each change to Plate's docs app, classify the merge decision, write13a reviewable plan under `docs/sync/shadcn`, directly merge any qualifying tiny14overlap fixes, then stop for user review of the remaining slices. A later15explicit user acceptance starts implementation mode for a named plan and slice.1617If $ARGUMENTS starts with a command name, dispatch to that command before the18default planning/implementation flow. If $ARGUMENTS names a feature, product19surface, or slice, run a scoped planning lane for that scope. The default20full-range planning lane applies only when no command or scope is mentioned.2122This skill exists because Plate's docs app is a forked product surface, not a23generic shadcn mirror. Upstream owns the Fumadocs/shadcn docs architecture.24Plate owns Plate docs content, editor demos, registry content, API MDX, CN docs,25MCP, Plate Plus hooks, GA, and a small set of intentional forks.2627## Autogoal Dependency2829This skill depends on30[$autogoal](/Users/zbeyens/git/plate/.agents/skills/autogoal/SKILL.md). Load31`autogoal` before mutable sync state, upstream pull/fetch, run artifact writes,32status JSON edits, or implementation delegation.3334`sync-shadcn` is a derived `autogoal` workflow and a two-phase lane:3536- Planning mode is the default. It writes the range plan, updates37 `lastPlannedCommit`, directly applies qualifying micro-overlap merges,38 asks the user to review the remaining plan, and stops.39- Implementation mode starts only after the user explicitly accepts a plan and40 slice in a later instruction, except for the micro-overlap direct merge41 exception below.42- Default flow mode: one-shot execution for planning mode and one-shot43 execution for accepted implementation mode. They are separate activations.44- Use collaborative planning only when the user is explicitly deciding policy45 before a range plan is written.46- Primary template:47 `docs/plans/templates/sync-shadcn.md`.48- Default packs: none. Add `docs` if docs/content pages are edited during an49 accepted implementation, `browser` if visible docs UI is edited, and50 `agent-native` if `.agents/**`, `.claude/**`, `.codex/**`, skills, commands,51 prompts, or user-action tooling are edited.52- Required evidence types: `command`, `source-audit`, `artifact`, and `N/A`53 rows. Add `browser` evidence when a planning scope or accepted54 implementation touches visible docs UI.55- Visual sync scopes must capture comparable screenshots of the upstream56 shadcn page and the Plate page before making or closing a visual parity call.57 Save only screenshots and notes, not broad upstream patch files.58- `autogoal` owns goal lifecycle, blocked/completion semantics, active-goal59 conflict handling, plan instantiation, output-budget discipline, and60 `check-complete.mjs`.61- `sync-shadcn` owns shadcn range policy, commit accounting, upstream inventory62 classification, Plate fork/exclusion decisions, status JSON semantics, and63 merge-slice handoff.6465## Micro-Overlap Direct Merge Exception6667The default review boundary is still real. Do not use it as an excuse to miss68obvious tiny upstream fixes on components Plate already mirrors.6970During planning, directly merge a change when all of these are true:7172- The upstream row maps to a retained Plate component, primitive, hook, or73 utility with a clear local owner path, not to upstream product content.74- The parent surface is already `synced`, an accepted partial sync, or an75 obvious overlapping primitive such as `Button`, `Badge`, `Input`, `Command`,76 `Tooltip`, `PageHeader`, or the copied docs-shell components.77- The diff is tiny: one local file, one behavior/class/token/prop/import fix,78 no new files, no deleted files, no new dependency, no route, no data model,79 no generated output, and no package or lockfile edit.80- The local Plate file still has the old value or an equivalent local variant81 that should receive the same fix.82- The change does not touch settled exclusions: v0, create, charts, colors,83 Rhea/theme/customizer/style-registry product surfaces, upstream docs prose,84 external registry directory content, or generated `public/r/**` output.85- No product judgment is needed. If the change changes layout, UX, copy,86 route shape, docs concepts, registry semantics, or multi-file architecture,87 it is not a micro-merge.8889Examples of direct merges:9091- Replace one stale utility class on Plate's copied `Button` because upstream92 fixed the same class on every style variant.93- Apply one bugfix conditional to a copied `Command` or `CopyButton` primitive94 when Plate has the same bug and no Plate product requirement changes.95- Remove one dead prop/import from a synced component when upstream removed it96 and Plate has no local dependency on it.9798Examples that still require review:99100- Package bumps, lockfile changes, registry schema/route changes, docs concept101 additions, new components, deleted components, multi-file UI chunks, visual102 layout rewrites, sidebar/search behavior changes, generated registry output,103 and anything touching a deferred or rejected product surface.104105When a micro-overlap merge is found:1061071. Record it in the run plan under `## Micro Auto-Merges` with upstream path,108 Plate path, focused diff summary, why it qualifies, and verification.1092. Patch the Plate owner file directly in the same activation.1103. Run the smallest meaningful verification: focused eslint/typecheck/source111 audit; add browser proof when the changed component is browser-visible and a112 stable route exists.1134. Add a `partialSyncs` entry if the full baseline does not advance. Keep114 `lastSyncedCommit` unchanged unless the whole range is complete.1155. Continue to stop for review on every non-micro slice.116117## Commands118119Supported commands:120121- `status`: summarize current shadcn sync state, partial syncs, deferred122 decisions, and recommended next step without writing sync artifacts.123- `dashboard`: regenerate the structured feature-delta dashboard under124 `docs/sync/shadcn` for visual review of synced, deferred, rejected, forked,125 and pending shadcn sync decisions.126- `apply`: apply a copied dashboard review payload to127 `docs/sync/shadcn/deltas.json`, answer question-only rows without mutation,128 implement rows targeting `synced`, then regenerate the dashboard when rows129 changed.130- `review`: re-audit the current tracked shadcn range against `../shadcn` and131 the current Plate checkout before trusting an existing plan.132133Feature-scoped planning:134135- Any non-command $ARGUMENTS value is a user-named scope. Treat the full136 argument string as the scope label instead of hardcoding allowed feature names.137- Scope labels can describe UI surfaces, routes, product areas, registry138 groups, content families, or implementation slices.139- If the scope is too vague to map to upstream and Plate files, ask one focused140 question before writing artifacts.141142Command parsing:143144- The first $ARGUMENTS token is the command when it matches a supported command.145- The full $ARGUMENTS string is the scope when the first token is not a146 supported command.147- If no command or scope is present, use the default full-range148 planning/implementation flow.149- Reserved commands are `status`, `dashboard`, `apply`, and `review`; do not150 treat them as scope labels.151- Scopes are planning lanes, not broad implementation permission. A scoped152 plan still stops for user review before non-micro `apps/www` work.153154### Scoped Planning155156Use `sync-shadcn <scope>` when the user wants to sync only one named surface157before reviewing broader docs sync work.158159Purpose:160161- compare the tracked upstream range, but inventory and classify only changes162 that affect the named scope163- write a reviewable scope-specific plan under `docs/sync/shadcn`164- avoid the default full-range lane unless the user invokes `sync-shadcn`165 without a command or scope166167Scope discovery:168169- Translate the user-named scope into likely upstream files under170 `../shadcn/apps/v4` and likely Plate files under `apps/www`.171- Search names, route paths, component names, config keys, registry names, and172 docs paths that match the scope.173- Include all matching hunks that directly affect the scope.174- Exclude adjacent changes that only share a file but belong to another surface;175 classify those as out-of-scope.176177Scoped planning rules:178179- Save artifacts in a scope-named run directory or plan name, for example180 `docs/sync/shadcn/runs/<date>-<base>-to-<target>-<scope-slug>/`.181- Use upstream diffs/logs for the same baseline and target as the default lane,182 but filter inventory rows to scope-matching files and patch hunks.183- Also record an out-of-scope count for upstream rows in the range so it is184 clear the scoped plan cannot advance `lastSyncedCommit` alone.185- If the scope is visual or route-owned, capture upstream and Plate screenshots186 for the matching route(s) at the same viewport before finalizing the plan.187 Use `docs/sync/shadcn/runs/<range>/screenshots/` for committed evidence, and188 include screenshot paths plus the visible deltas in the plan.189- Do not update `lastSyncedCommit` from a scoped plan. Scoped sync can add a190 `partialSyncs` entry after accepted implementation, but the baseline advances191 only when the full range is accounted for.192- The plan's recommended slices must stay inside the named scope. If a file also193 contains unrelated changes, classify the scope hunk as `smart-merge` and the194 unrelated hunks as out-of-scope for this lane.195- Final planning output must say that the default full sync lane remains196 pending for the out-of-scope rows.197198### `status`199200Use `sync-shadcn status` when the user wants a quick checkpoint before choosing201the next sync step.202203Purpose:204205- show the current baseline, latest planned target, current upstream target, and206 whether the tracked plan looks fresh enough for decision-making207- list accepted partial syncs already landed208- list deferred decisions so the user can choose what to do next209- list reviewable Plate-vs-shadcn differences that are still intentionally210 undecided or deferred, especially visual parity gaps from scoped sync plans211- recommend the next command or decision212213Status mode may:214215- read `docs/sync/shadcn/status.json`216- read `lastPlan`, the linked `inventory.md`, and the latest run directory when217 present218- resolve `../shadcn` refs and fetch `origin main --tags` when the user asks for219 current upstream freshness; if fetch fails, report freshness as unverified220- count upstream commits and file-status rows for221 `lastPlannedCommit..origin/main`222- summarize `partialSyncs[*].slices`, `partialSyncs[*].deferred`,223 and plan `Questions`224- when the user supplies words after `status`, treat the remaining argument as225 a status scope filter, for example `status our /editors vs shadcn /blocks`;226 prefer the matching `partialSyncs[*].plan`, `lastPlan`, or run directory227 before falling back to global status228- summarize remaining reviewable differences from the matched plan's229 `Recommended Merge Slices`, `Visual Evidence`, `Implementation Result`, and230 `partialSyncs[*].deferred`231232Status mode must not:233234- patch `apps/www`235- write `docs/sync/shadcn/runs/**`236- write review artifacts237- change `lastSyncedCommit`, `lastPlannedCommit`, `lastPlan`, or238 `partialSyncs`239- delegate implementation to `task`240- treat listed deferred items as accepted decisions241- list settled exclusions or preserved Plate forks as if they still need242 action; those belong in `review` evidence or the plan, not routine status243 output244245Status must distinguish three things:246247- `Landed`: accepted partial sync slices already applied.248- `Reviewable differences`: Plate still differs from upstream and the249 difference is not settled policy. These are the items the user can re-decide.250 Include the upstream behavior, current Plate behavior, likely owner files,251 and the smallest next command or decision.252- `Settled differences`: explicit exclusions and preserved Plate forks. Do not253 list these by default unless the user asks to re-open them.254255Deferred item sources, in order:2562571. `docs/sync/shadcn/status.json` `partialSyncs[*].deferred`2582. the selected plan's `Questions` section2593. recommended merge slices marked `defer`, `needs-question`, or not yet260 implemented2614. visual evidence rows where the plan says a Plate-vs-upstream difference262 still needs work2635. implementation-result notes that explicitly leave a follow-up slice open2646. status update notes that say `lastSyncedCommit` cannot advance265266For visual scoped status, do not stop at "fresh" when visible deltas remain.267Report them as reviewable differences even when the scoped implementation was268verified. Example:269270```md271Reviewable differences:272- BlockViewer toolbar: upstream `/blocks` has compact device controls,273 refresh, separated command pill, and v0 action; Plate `/editors` still keeps274 its current toolbar density and excludes v0. Decision: sync toolbar spacing275 only, keep Plate install/source behavior and no v0; or leave as Plate fork.276```277278Collapse upstream product/theme/style noise into its owning deferred decision.279For example, Rhea/style/theme/generated style registry rows are part of the280upstream create/theming product surface; do not list them as separate status281items unless the user explicitly asks to review that product surface.282283Status checks:284285```bash286node -e '287const fs = require("fs");288const status = JSON.parse(fs.readFileSync("docs/sync/shadcn/status.json", "utf8"));289console.log(JSON.stringify({290 lastSyncedCommit: status.lastSyncedCommit,291 lastPlannedCommit: status.lastPlannedCommit,292 lastPlan: status.lastPlan,293 partialSyncs: status.partialSyncs ?? []294}, null, 2));295'296297git -C ../shadcn fetch origin main --tags298TARGET=$(git -C ../shadcn rev-parse origin/main)299PLANNED=$(node -e 'console.log(JSON.parse(require("fs").readFileSync("docs/sync/shadcn/status.json", "utf8")).lastPlannedCommit || "")')300git -C ../shadcn log --oneline --decorate "$PLANNED..$TARGET" -- apps/v4301git -C ../shadcn diff --name-status --find-renames "$PLANNED..$TARGET" -- apps/v4302```303304Status output shape:305306```md307Status: <fresh | upstream-ahead | no-plan | blocked-ref | unverified>308Baseline: <lastSynced-short>309Planned: <lastPlanned-short>310Current upstream: <target-short>311Plan: <path or none>312313Partial syncs:314- <date/range>: <landed slices>315316Reviewable differences:317- <surface>: upstream <behavior>; Plate <behavior>; decision needed <adopt |318 smart-merge | keep fork>; files <paths>319320Deferred decisions:321- <item>322323Next: <run review | rerun planning | decide deferred item | implement accepted slice | advance baseline>324```325326Keep status concise, but do not hide reviewable differences behind a generic327"deferred" label. If the user wants full evidence, tell them to run328`sync-shadcn review`.329330### `apply`331332Use `sync-shadcn apply` when the user pastes a dashboard review payload.333334Purpose:335336- apply rows listed directly under `$sync-shadcn apply` or under an optional337 `Rows` heading338- answer rows listed under `Questions` in chat without mutating339 `deltas.json`340- keep the copied dashboard prompt short by storing the mutation contract in341 this command342343Apply mode may:344345- read and update `docs/sync/shadcn/deltas.json`346- patch `apps/www`, `content/docs`, and related source files when a listed row347 targets `synced` or `fork`348- delegate a coherent implementation slice to `task` when a `synced` or `fork`349 row needs more than a tiny local edit350- remove screenshot refs for rows applied to `synced` or `rejected`351- delete unreferenced local screenshot files under `docs/sync/shadcn/runs/**`352- run `pnpm sync-shadcn dashboard` after any JSON mutation353354Apply mode must not:355356- write `docs/sync/shadcn/runs/**` except deleting unreferenced screenshots357- change `lastSyncedCommit`, `lastPlannedCommit`, `lastPlan`, or358 `partialSyncs`359- infer decisions for rows not listed in the pasted payload360- mutate `deltas.json` for question-only rows361- mark a row `synced` or `fork` before implementation is present and verified362- ask for review when the row has clear files, suggestion, and acceptance363 criteria; ask one focused question only when the target behavior is unclear364365Payload shape:366367```md368$sync-shadcn apply369370- command-menu/command-footer-shortcuts (Command Menu / Footer shortcuts and copy payloads): defer -> pending note: Add copy only for components and editor kits.371372Questions:373- registry/registry-review (Registry / Full registry review): Which registry rows should include copy shortcuts?374```375376Apply rules:377378- A direct bullet row under `$sync-shadcn apply`, or under an optional `Rows`379 heading, is the only mutation unit.380- Set each listed item state to the requested target state.381- Target states `pending`, `defer`, and `rejected` are metadata decisions.382- Target state `synced` is implementation mode: inspect the row files and383 suggestion, implement the requested change, run focused verification, then384 update `deltas.json` to `synced`.385- Target state `fork` is also implementation mode when the row's note,386 suggestion, or files imply work in Plate. Inspect the row files and387 suggestion, implement or verify the intentional Plate-owned fork, run focused388 verification, then update `deltas.json` to `fork`.389- A `fork` update may be metadata-only only when the Plate fork already exists,390 the row note does not ask for code/content work, and the source evidence is391 checked before updating `deltas.json`.392- Use notes to update `decision`, `suggestion`, or summary text when393 appropriate.394- If a note is only a question, keep it under `Questions`, answer it in chat,395 and do not mutate JSON.396- When applying `synced` or `rejected`, remove that row's `screenshots` object397 and delete unreferenced local screenshot files.398- Keep screenshots for `fork` rows.399- If any row is applied, run `pnpm sync-shadcn dashboard`.400401### `dashboard`402403Use `sync-shadcn dashboard` when the user wants a visual decision board for404the shadcn sync delta instead of prose status output.405406Purpose:407408- render feature-owned sync deltas grouped by product surface, such as header,409 home, editors, releases, command menu, registry, create, preview routes, and410 sidebar411- show review states that can be re-decided later: `pending`, `defer`,412 `fork`, `rejected`, and `synced`413- keep settled exclusions visible in the dashboard without polluting routine414 `status` output415- make user review possible through a local static HTML artifact416- include browser-only state controls, note textareas, and a copy button that417 builds a concise `$sync-shadcn apply` payload418- include quick row actions in two rows: `Ask`, `Defer`, then `Sync`,419 `Reject`, `Fork`; `pending` is a state/filter, not a row action420- keep note textareas locked until the user chooses an explicit row intent:421 `Ask`, a quick apply action, or a changed state value422- render review actions as selected controls; `Sync` copies an423 `$sync-shadcn apply` row targeting `synced`, which means implementation mode424 for that row425- render `Fork` as an implementation-capable action too: copied payloads426 targeting `fork` mean "make or verify the Plate-owned fork", not "metadata427 only"428- use `suggestion` as the durable item field for Plate-owned recommendation429 text, rendered as `Suggestion` in the dashboard with an explicit `Apply`430 action that copies that suggestion into `Note`431- treat `Ask` as question-only: it keeps the current row state, writes the row432 under `Questions`, and must not mutate `deltas.json`433- treat question-only notes as questions to answer in chat, not as decisions to434 apply to `deltas.json`; only rows under `Rows` in a `$sync-shadcn apply`435 payload should mutate structured state436- open on the actionable filter by default:437 `pending` and `defer`; keep `synced`, `rejected`, and `fork` available438 behind explicit filters439- split state filters into an Action row and a Done row so active review work440 is visually separate from settled policy/history441- render Suggestion and shadcn screenshot columns for non-`synced` review rows when442 row screenshot paths exist, with click-to-zoom and close behavior in the443 static HTML page444- remove screenshot refs for `synced` and `rejected` rows during dashboard445 generation, and delete unreferenced local screenshot files; keep screenshot446 evidence for `fork` rows because forked differences stay useful447- render one card per delta item instead of a wide table, with Suggestion vs shadcn448 text in two responsive columns and empty screenshot areas hidden449- do not use an item-level `next` field in `deltas.json`; status and workflow450 guidance should come from item state, decision, suggestion, and group summary451452Dashboard mode may:453454- read `docs/sync/shadcn/status.json`455- read and update `docs/sync/shadcn/deltas.json`456- write `docs/sync/shadcn/dashboard.json`457- write `docs/sync/shadcn/dashboard.html`458459Dashboard mode must not:460461- patch `apps/www`462- write `docs/sync/shadcn/runs/**`463- change `lastSyncedCommit`, `lastPlannedCommit`, `lastPlan`, or464 `partialSyncs`465- delegate implementation to `task`466- treat a dashboard item as user acceptance to implement467468State meanings:469470- `synced`: the slice was accepted, implemented, and verified.471- `defer`: the item is acknowledged but intentionally postponed.472- `pending`: the item has no final decision yet, including rows waiting on a473 user decision.474- `fork`: Plate intentionally keeps a different implementation, and that475 implementation is present or has been verified before the row is marked fork.476- `rejected`: upstream behavior is explicitly excluded.477478Dashboard source:479480- `docs/sync/shadcn/deltas.json` is the editable structured decision source.481- `docs/sync/shadcn/dashboard.json` and482 `docs/sync/shadcn/dashboard.html` are generated views.483- When adding a landed implementation slice, update `status.json` first, then484 add or update the matching `deltas.json` feature row, then regenerate the485 dashboard.486- When rejecting, deferring, or forking a feature, record the upstream behavior,487 suggestion, owner files, and state rationale in `deltas.json`.488- For non-`synced` visual rows, add screenshot paths under489 `screenshots.suggestion` and `screenshots.shadcn` when available. Leave490 source-only rows blank.491- The HTML review controls are intentionally not persistent. The user can mark492 many rows, copy the generated prompt, and send it back; Codex applies the493 JSON edits and regenerates the dashboard.494495Dashboard command:496497```bash498pnpm sync-shadcn dashboard499```500501This regenerates `dashboard.html` and opens it in the local browser. Use502`--no-open` or `SYNC_SHADCN_NO_OPEN=1` when running in a non-GUI check.503504Dashboard output shape:505506```md507Dashboard: docs/sync/shadcn/dashboard.html508Data: docs/sync/shadcn/dashboard.json509Opened: file:///.../docs/sync/shadcn/dashboard.html510511| Feature | State | Items |512| --- | --- | ---: |513| Registry | defer | 2 |514```515516### `review`517518Use `sync-shadcn review` when the user asks whether the latest sync plan is519still fresh, whether a previously written plan can still be implemented, or520whether current `apps/www` drift changed the merge posture.521522Purpose:523524- prove whether `docs/sync/shadcn/status.json`, the latest plan artifacts, the525 current `../shadcn/apps/v4` target, and the current Plate docs checkout still526 describe the same sync problem527- find new upstream commits since `lastPlannedCommit`528- find stale inventory artifacts for the `lastSyncedCommit..target` range529- re-run local Plate owner/source evidence for actionable rows before530 implementation531532Inputs:533534- optional plan path or run directory; default to `lastPlan` from535 `docs/sync/shadcn/status.json`536- optional target ref; default to `origin/main` in `../shadcn`537- baseline from `lastSyncedCommit`538- planned target from `lastPlannedCommit`539540Review mode may:541542- fetch `../shadcn` and resolve exact refs543- read `docs/sync/shadcn/status.json`, the selected plan, `inventory.md`, and544 `upstream-name-status.tsv`545- recompute upstream name-status/numstat/log data into a temporary review file546 under the same run directory or under `docs/sync/shadcn/reviews/`547- compare recomputed inventories with the stored run artifacts548- re-run scoped `rg`/file-existence checks for Plate owner paths, explicit549 exclusions, preserved forks, partial sync entries, and recommended slices550- write a dated `review.md` artifact with the verdict and evidence551552Review mode must not:553554- patch `apps/www`555- change `lastSyncedCommit`, `lastPlannedCommit`, `lastPlan`, or556 `partialSyncs`557- delegate implementation to `task`558- create a new implementation plan or advance the baseline559- treat a fresh review as user acceptance to implement560561Review checks:562563```bash564git -C ../shadcn fetch origin main --tags565566node -e '567const fs = require("fs");568const status = JSON.parse(fs.readFileSync("docs/sync/shadcn/status.json", "utf8"));569console.log(JSON.stringify({570 lastSyncedCommit: status.lastSyncedCommit,571 lastPlannedCommit: status.lastPlannedCommit,572 lastPlan: status.lastPlan,573 partialSyncs: status.partialSyncs?.length ?? 0574}, null, 2));575'576577BASE=$(node -e 'console.log(JSON.parse(require("fs").readFileSync("docs/sync/shadcn/status.json", "utf8")).lastSyncedCommit || "")')578PLANNED=$(node -e 'console.log(JSON.parse(require("fs").readFileSync("docs/sync/shadcn/status.json", "utf8")).lastPlannedCommit || "")')579TARGET=$(git -C ../shadcn rev-parse origin/main)580581git -C ../shadcn merge-base --is-ancestor "$BASE" "$TARGET"582git -C ../shadcn log --oneline --decorate "$PLANNED..$TARGET" -- apps/v4583git -C ../shadcn diff --name-status --find-renames "$BASE..$TARGET" -- apps/v4584```585586Staleness verdicts:587588- `fresh`: current upstream target equals `lastPlannedCommit`, recomputed589 upstream inventory matches the selected run artifact, required Plate owner590 paths/source evidence still exist, and no partial-sync/status contradiction is591 found.592- `stale-upstream`: `origin/main` has newer `apps/v4` commits than593 `lastPlannedCommit` or the recomputed upstream inventory differs from the594 selected run artifact.595- `stale-local`: Plate owner paths or local search evidence used by the plan no596 longer match the current checkout.597- `stale-status`: `status.json` contradicts the selected plan, for example the598 selected plan target differs from `lastPlannedCommit` without an explicit599 override, or `partialSyncs` claim work that the local checkout no longer600 shows.601- `blocked-ref`: the baseline, planned target, selected target, or ancestry602 cannot be proven.603604The review artifact must include:605606- selected plan/run directory607- base, planned target, and current target SHAs608- upstream commit count and file-status count for `PLANNED..TARGET`609- inventory comparison result for `BASE..TARGET`610- local Plate owner/source evidence summary611- explicit exclusions and preserved forks checked612- status semantics checked613- verdict and the next action614615Review output shape:616617```md618Review: <fresh | stale-upstream | stale-local | stale-status | blocked-ref>619Range: <base-short>..<target-short>620Plan: <path>621Report: <path>622623| Check | Result | Evidence |624| --- | --- | --- |625| upstream target | ... | ... |626| inventory | ... | ... |627| Plate owners | ... | ... |628| status semantics | ... | ... |629630Next: <use the existing plan | rerun planning | fix local drift | resolve refs>631```632633Before substantive work:634635```bash636node .agents/skills/autogoal/scripts/create-goal-scratchpad.mjs \637 --template sync-shadcn \638 --title "sync shadcn <short range or target>"639```640641Fill the generated plan immediately. It must name the objective, flow mode,642completion threshold, verification surface, constraints, boundaries, output643budget strategy, blocked condition, and planned run directory. Do not replace it644with a smaller ad hoc plan.645646Completion requires the named sync evidence plus:647648```bash649node .agents/skills/autogoal/scripts/check-complete.mjs <docs/plans/path>650```651652Never mark the active goal complete just because a range plan was written if653the goal also required implementation, baseline advancement, or user acceptance.654655## User Review Boundary656657This mirrors the important part of `slate-plan`: plan first, stop, then execute658only after explicit acceptance.659660Planning mode may:661662- fetch/pull `../shadcn`663- create the active goal plan664- write `docs/sync/shadcn/runs/<range>/` artifacts665- update `lastPlannedCommit` and `lastPlan`666- directly apply qualifying micro-overlap merges and record them as partial667 syncs668- ask one review/decision question669670Planning mode must not:671672- patch `apps/www` except for qualifying micro-overlap direct merges673- delegate to `task`674- advance `lastSyncedCommit`675- treat "recommended first slice" as accepted676- combine plan creation and non-micro implementation in the same activation677678The final planning response must say:679680```md681Review the plan. I directly merged these micro-overlap fixes: <list or none>.682To implement the remaining slices, invoke `sync-shadcn` again with the accepted683plan path and slice.684```685686Implementation mode requires a later user message that names or clearly accepts687the plan/slice. Then create or continue an implementation-shaped goal for that688accepted slice and proceed through `task`.689690## Hard Rules691692- Use evidence, not vibes. Read upstream commits, file status, focused diffs,693 local Plate files, prior decisions, screenshots for visual surfaces, and694 relevant solution notes.695- Track exact commits. Never say "latest shadcn" without recording the target696 SHA.697- Treat `docs/sync/shadcn/status.json` as the durable baseline. Do not advance698 `lastSyncedCommit` until every upstream change in the planned range is699 accounted for as adopted, smart-merged, intentionally forked, or explicitly700 excluded.701- Planning is the default output. Do not patch `apps/www` unless the row702 qualifies as a micro-overlap direct merge or the user accepts a merge slice in703 a later instruction after reviewing a written plan.704- Do not edit generated registry output, templates output, or generated skill705 mirrors by hand.706- Do not run `build:registry`; local registry generation is CI-owned in this707 repo.708- Do not delegate to `task` in the same activation that creates or materially709 updates a sync plan. Direct micro-overlap merges stay in-thread and tiny; all710 bigger work waits for review.711- Keep the active `sync-shadcn` goal plan current after every meaningful712 decision, artifact write, classification pass, status JSON edit, accepted713 implementation slice, verification run, or blocker.714- Prefer deleting old Plate fork residue over preserving compatibility layers715 when upstream already owns the better model.716- Prefer upstream docs infrastructure unless Plate has a real product or717 registry reason to diverge.718- Keep output comprehensive. If a diff is too large for the chat, save complete719 TSV inventories under `docs/sync/shadcn/runs/<range>/` and summarize the720 artifact paths in the response.721- Do not persist `.patch` files in the repo. Inspect focused diffs on demand722 with capped `git diff` commands, summarize the relevant hunks in723 `inventory.md` or `plan.md`, and leave broad upstream patches out of724 committed sync artifacts.725726## Start Gates727728These gates must be resolved in the active `sync-shadcn` goal plan before broad729exploration:730731- `autogoal` loaded and active goal checked or created.732- `docs/sync/shadcn/status.json` read.733- `docs/sync/shadcn/decisions.md` read.734- Prior migration plans and solution notes checked when relevant.735- Output budget strategy recorded before running upstream diff/log commands.736- `../shadcn` clone state known and fetched/pulled intentionally.737- Base and target refs resolved to exact SHAs.738- Base ancestry proven, or the ref problem recorded before stopping.739- Planning-only versus implementation mode decided.740- User-review boundary recorded: planning mode stops, implementation mode741 requires later explicit acceptance.742743## Completion Gates744745These gates belong in `docs/plans/templates/sync-shadcn.md` and must be closed746in the instantiated goal plan:747748- Upstream range artifacts exist and are non-empty, or a target-only bootstrap749 exception is recorded.750- `inventory.md` accounts for every row in `upstream-name-status.tsv`.751- Decision counts cover every upstream row.752- Source-backed Plate mapping exists for every actionable adoption, fork,753 exclusion, or question group.754- `docs/sync/shadcn/status.json` parses and its `lastPlannedCommit` /755 `lastSyncedCommit` semantics match the work actually completed.756- Planning-only runs prove no `apps/www` implementation patch was made, or757 record and verify every qualifying micro-overlap direct merge.758- Accepted implementation runs include focused verification for the touched759 Plate surface.760- Browser proof exists when browser-visible docs UI changed, or when a761 planning scope is visual and needs Plate-vs-shadcn parity evidence.762- Visual sync scopes include screenshots of both upstream shadcn and Plate763 pages at matching viewport(s), plus written deltas such as background,764 spacing, disabled/gray controls, nav/header items, and first-viewport765 framing.766- `lastSyncedCommit` advances only after full-row accounting, verification, and767 user acceptance.768- Planning-mode final handoff lists any direct micro-overlap merges, asks the769 user to review the remaining plan, and invokes `sync-shadcn` again with the770 accepted plan path and slice for bigger work.771- `check-complete.mjs` passes for the active goal plan.772773## Durable Policy774775Read these before making decisions:776777- `docs/sync/shadcn/status.json`778- `docs/sync/shadcn/decisions.md`779- `docs/plans/2026-05-23-shadcn-docs-restart-comparison.md`780- `docs/plans/2026-05-24-shadcn-base-migration-progress.md`781- `.agents/rules/shadcn-parity.mdc`782- `docs/solutions/best-practices/2026-05-23-shadcn-docs-restart-comparison.md`783- `docs/solutions/developer-experience/2026-05-27-shadcn-docs-sidebar-parity-needs-source-and-dom-metrics.md`784- `docs/solutions/developer-experience/2026-05-24-plate-init-routes-should-return-shadcn-registry-base-items.md`785- `docs/solutions/developer-experience/2026-05-24-shadcn-v4-registry-schema-needs-source-only-validation.md`786- `docs/solutions/developer-experience/2026-05-24-shadcn-registry-install-commands-should-use-configured-namespaces.md`787- `docs/solutions/developer-experience/2026-05-24-fumadocs-page-tree-search-needs-locale-safe-metadata.md`788789Default durable decisions:790791- Discard upstream v0 surfaces.792- Discard upstream `/create`, `/charts`, `/colors`, and public directory-style793 product pages unless the user explicitly asks for a Plate version.794- Discard Plate theme/customizer/project/lift-mode residue.795- Keep Plate docs content under `content/docs/**`.796- Keep committed Fumadocs metadata as the docs navigation authority.797- Keep Plate API MDX vocabulary and generated API docs support.798- Keep Plate registry content and docs-registry generation, aligned to shadcn v4799 schema/resolver semantics.800- Keep Plate editor demos, `/view/[name]`, and registry preview/source display.801- Keep lazy code-view source loading through `/api/registry-source/[name]` for802 bandwidth, but do not treat it as a public registry API.803- Keep CN docs, MCP docs/dialog, Plate Plus/Pro hooks, GA, Plate home page, and804 the Slate-to-HTML special page.805- Keep Plate's sidebar accordion/filter UX only as an intentional fork rebuilt806 on Fumadocs/upstream sidebar primitives.807808## 1. Establish Upstream Clone And Refs809810Do this only after the `autogoal` start gates are satisfied and the active811`sync-shadcn` plan records the output budget strategy.812813Use `../shadcn` as the upstream clone. Create it only if missing:814815```bash816test -d ../shadcn/.git || gh repo clone shadcn-ui/ui ../shadcn817git -C ../shadcn fetch origin main --tags818test -d ../shadcn/apps/v4819```820821Read the tracked baseline:822823```bash824node -e '825const fs = require("fs");826const status = JSON.parse(fs.readFileSync("docs/sync/shadcn/status.json", "utf8"));827console.log(JSON.stringify(status, null, 2));828'829```830831Resolve refs:832833```bash834BASE=$(node -e 'console.log(JSON.parse(require("fs").readFileSync("docs/sync/shadcn/status.json", "utf8")).lastSyncedCommit || "")')835TARGET=$(git -C ../shadcn rev-parse origin/main)836git -C ../shadcn log -1 --format='%H%n%ci%n%s' "$TARGET"837```838839If $ARGUMENTS names a base or target ref, prove it exists and use it:840841```bash842git -C ../shadcn rev-parse <base-or-target-ref>843```844845If `BASE` is empty, run a bootstrap audit:846847- compare the whole `../shadcn/apps/v4` source against Plate848- write a plan849- ask the user before setting `lastSyncedCommit`850- do not silently set the baseline851852If `BASE` is present, prove ancestry when possible:853854```bash855git -C ../shadcn merge-base --is-ancestor "$BASE" "$TARGET"856git -C ../shadcn log --oneline --decorate "$BASE..$TARGET" -- apps/v4857```858859If `BASE` is not an ancestor of `TARGET`, stop and explain the ref problem860before planning. Do not produce a misleading change list.861862## 2. Create A Run Artifact Directory863864Use a range-keyed directory so the full evidence survives beyond chat context:865866```bash867RUN_DIR="docs/sync/shadcn/runs/$(date +%Y-%m-%d)-${BASE:0:7}-to-${TARGET:0:7}"868mkdir -p "$RUN_DIR"869```870871Save complete inventories:872873```bash874git -C ../shadcn diff --name-status --find-renames "$BASE..$TARGET" -- apps/v4 \875 > "$RUN_DIR/upstream-name-status.tsv"876877git -C ../shadcn diff --numstat "$BASE..$TARGET" -- apps/v4 \878 > "$RUN_DIR/upstream-numstat.tsv"879880git -C ../shadcn log --oneline --decorate "$BASE..$TARGET" -- apps/v4 \881 > "$RUN_DIR/upstream-commits.txt"882```883884For bootstrap audits without a base ref, use `target-only` in the directory885name and save a full current upstream file list instead:886887```bash888git -C ../shadcn ls-files apps/v4 > "$RUN_DIR/upstream-files.txt"889```890891Do not stream huge diffs into chat and do not write `.patch` files. Inspect892focused diffs on demand with capped commands, then summarize only the relevant893hunks in `inventory.md` or `plan.md`:894895```bash896git -C ../shadcn diff --stat "$BASE..$TARGET" -- apps/v4/app apps/v4/components apps/v4/lib897git -C ../shadcn diff "$BASE..$TARGET" -- apps/v4/app/(app)/(root)/page.tsx | sed -n '1,220p'898```899900If the focused diff is still too large, narrow by path/function/search term and901record the command plus summary instead of saving the diff body.902903## 3. Classify Upstream Changes904905Every upstream changed file must be assigned to one subsystem:906907- `docs-engine`: Fumadocs source, page tree, MDX compilation, raw markdown908- `routing`: Next routes, rewrites, metadata, layout groups909- `shell-nav-sidebar`: header, footer, sidebar, mobile nav, command/search UI910- `mdx-code`: MDX components, code blocks, copy-page, source viewer, RSS/OG911- `registry-contract`: shadcn schema, resolver semantics, namespace behavior,912 init/base item, local-file install913- `registry-build`: registry scripts, generated source indexes, validation914- `preview-view`: block/component preview routes and iframe/source display915- `product-page`: create, charts, colors, blocks gallery, directory, examples916 pages that are shadcn product surfaces917- `theme-style`: global CSS, theme providers, tokens, active theme, customizer918- `deps-config`: package, lock, tsconfig, eslint, Next config919- `tests`: upstream app tests and fixtures920- `assets`: public assets, manifest, images, fonts921- `other`: only with an explanation922923For each file, record:924925- upstream status: added, modified, deleted, renamed926- upstream path927- subsystem928- nearest Plate owner path, or `none`929- local search evidence930- default decision931- confidence932933Useful local mapping heuristics:934935| Upstream path | Plate path to inspect |936| --- | --- |937| `apps/v4/app/**` | `apps/www/src/app/**` |938| `apps/v4/components/**` | `apps/www/src/components/**` |939| `apps/v4/lib/**` | `apps/www/src/lib/**` |940| `apps/v4/hooks/**` | `apps/www/src/hooks/**` |941| `apps/v4/content/docs/**` | `content/docs/**` |942| `apps/v4/registry/**` | `apps/www/src/registry/**` |943| `apps/v4/scripts/**` | `apps/www/script944945…(truncated)