.agents/skills/sync-shadcn/SKILL.md
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.
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:
lastPlannedCommit, directly applies qualifying micro-overlap merges,
asks the user to review the remaining plan, and stops.docs/plans/templates/sync-shadcn.md.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.command, source-audit, artifact, and N/A
rows. Add browser evidence when a planning scope or accepted
implementation touches visible docs UI.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.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:
synced, an accepted partial sync, or an
obvious overlapping primitive such as Button, Badge, Input, Command,
Tooltip, PageHeader, or the copied docs-shell components.public/r/** output.Examples of direct merges:
Button because upstream
fixed the same class on every style variant.Command or CopyButton primitive
when Plate has the same bug and no Plate product requirement changes.Examples that still require review:
When a micro-overlap merge is found:
## Micro Auto-Merges with upstream path,
Plate path, focused diff summary, why it qualifies, and verification.partialSyncs entry if the full baseline does not advance. Keep
lastSyncedCommit unchanged unless the whole range is complete.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:
Command parsing:
status, dashboard, apply, and review; do not
treat them as scope labels.apps/www work.Use sync-shadcn <scope> when the user wants to sync only one named surface
before reviewing broader docs sync work.
Purpose:
docs/sync/shadcnsync-shadcn
without a command or scopeScope discovery:
../shadcn/apps/v4 and likely Plate files under apps/www.Scoped planning rules:
docs/sync/shadcn/runs/<date>-<base>-to-<target>-<scope-slug>/.lastSyncedCommit alone.docs/sync/shadcn/runs/<range>/screenshots/ for committed evidence, and
include screenshot paths plus the visible deltas in the plan.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.smart-merge and the
unrelated hunks as out-of-scope for this lane.statusUse sync-shadcn status when the user wants a quick checkpoint before choosing
the next sync step.
Purpose:
Status mode may:
docs/sync/shadcn/status.jsonlastPlan, the linked inventory.md, and the latest run directory when
present../shadcn refs and fetch origin main --tags when the user asks for
current upstream freshness; if fetch fails, report freshness as unverifiedlastPlannedCommit..origin/mainpartialSyncs[*].slices, partialSyncs[*].deferred,
and plan Questionsstatus, 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 statusRecommended Merge Slices, Visual Evidence, Implementation Result, and
partialSyncs[*].deferredStatus mode must not:
apps/wwwdocs/sync/shadcn/runs/**lastSyncedCommit, lastPlannedCommit, lastPlan, or
partialSyncstaskreview evidence or the plan, not routine status
outputStatus 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[*].deferredQuestions sectiondefer, needs-question, or not yet
implementedlastSyncedCommit cannot advanceFor 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.
applyUse sync-shadcn apply when the user pastes a dashboard review payload.
Purpose:
$sync-shadcn apply or under an optional
Rows headingQuestions in chat without mutating
deltas.jsonApply mode may:
docs/sync/shadcn/deltas.jsonapps/www, content/docs, and related source files when a listed row
targets synced or forktask when a synced or fork
row needs more than a tiny local editsynced or rejecteddocs/sync/shadcn/runs/**pnpm sync-shadcn dashboard after any JSON mutationApply mode must not:
docs/sync/shadcn/runs/** except deleting unreferenced screenshotslastSyncedCommit, lastPlannedCommit, lastPlan, or
partialSyncsdeltas.json for question-only rowssynced or fork before implementation is present and verifiedPayload 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:
$sync-shadcn apply, or under an optional Rows
heading, is the only mutation unit.pending, defer, and rejected are metadata decisions.synced is implementation mode: inspect the row files and
suggestion, implement the requested change, run focused verification, then
update deltas.json to synced.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.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.decision, suggestion, or summary text when
appropriate.Questions, answer it in chat,
and do not mutate JSON.synced or rejected, remove that row's screenshots object
and delete unreferenced local screenshot files.fork rows.pnpm sync-shadcn dashboard.dashboardUse sync-shadcn dashboard when the user wants a visual decision board for
the shadcn sync delta instead of prose status output.
Purpose:
pending, defer,
fork, rejected, and syncedstatus output$sync-shadcn apply payloadAsk, Defer, then Sync,
Reject, Fork; pending is a state/filter, not a row actionAsk, a quick apply action, or a changed state valueSync copies an
$sync-shadcn apply row targeting synced, which means implementation mode
for that rowFork as an implementation-capable action too: copied payloads
targeting fork mean "make or verify the Plate-owned fork", not "metadata
only"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 NoteAsk as question-only: it keeps the current row state, writes the row
under Questions, and must not mutate deltas.jsondeltas.json; only rows under Rows in a $sync-shadcn apply
payload should mutate structured statepending and defer; keep synced, rejected, and fork available
behind explicit filterssynced review rows when
row screenshot paths exist, with click-to-zoom and close behavior in the
static HTML pagesynced and rejected rows during dashboard
generation, and delete unreferenced local screenshot files; keep screenshot
evidence for fork rows because forked differences stay usefulnext field in deltas.json; status and workflow
guidance should come from item state, decision, suggestion, and group summaryDashboard mode may:
docs/sync/shadcn/status.jsondocs/sync/shadcn/deltas.jsondocs/sync/shadcn/dashboard.jsondocs/sync/shadcn/dashboard.htmlDashboard mode must not:
apps/wwwdocs/sync/shadcn/runs/**lastSyncedCommit, lastPlannedCommit, lastPlan, or
partialSyncstaskState 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.status.json first, then
add or update the matching deltas.json feature row, then regenerate the
dashboard.deltas.json.synced visual rows, add screenshot paths under
screenshots.suggestion and screenshots.shadcn when available. Leave
source-only rows blank.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 |
reviewUse 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:
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 problemlastPlannedCommitlastSyncedCommit..target rangeInputs:
lastPlan from
docs/sync/shadcn/status.jsonorigin/main in ../shadcnlastSyncedCommitlastPlannedCommitReview mode may:
../shadcn and resolve exact refsdocs/sync/shadcn/status.json, the selected plan, inventory.md, and
upstream-name-status.tsvdocs/sync/shadcn/reviews/rg/file-existence checks for Plate owner paths, explicit
exclusions, preserved forks, partial sync entries, and recommended slicesreview.md artifact with the verdict and evidenceReview mode must not:
apps/wwwlastSyncedCommit, lastPlannedCommit, lastPlan, or
partialSyncstaskReview 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:
PLANNED..TARGETBASE..TARGETReview 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.
This mirrors the important part of slate-plan: plan first, stop, then execute
only after explicit acceptance.
Planning mode may:
../shadcndocs/sync/shadcn/runs/<range>/ artifactslastPlannedCommit and lastPlanPlanning mode must not:
apps/www except for qualifying micro-overlap direct mergestasklastSyncedCommitThe 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.
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.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.build:registry; local registry generation is CI-owned in this
repo.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.sync-shadcn goal plan current after every meaningful
decision, artifact write, classification pass, status JSON edit, accepted
implementation slice, verification run, or blocker.docs/sync/shadcn/runs/<range>/ and summarize the
artifact paths in the response..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.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.../shadcn clone state known and fetched/pulled intentionally.These gates belong in docs/plans/templates/sync-shadcn.md and must be closed
in the instantiated goal plan:
inventory.md accounts for every row in upstream-name-status.tsv.docs/sync/shadcn/status.json parses and its lastPlannedCommit /
lastSyncedCommit semantics match the work actually completed.apps/www implementation patch was made, or
record and verify every qualifying micro-overlap direct merge.lastSyncedCommit advances only after full-row accounting, verification, and
user acceptance.sync-shadcn again with the
accepted plan path and slice for bigger work.check-complete.mjs passes for the active goal plan.Read these before making decisions:
docs/sync/shadcn/status.jsondocs/sync/shadcn/decisions.mddocs/plans/2026-05-23-shadcn-docs-restart-comparison.mddocs/plans/2026-05-24-shadcn-base-migration-progress.md.agents/rules/shadcn-parity.mdcdocs/solutions/best-practices/2026-05-23-shadcn-docs-restart-comparison.mddocs/solutions/developer-experience/2026-05-27-shadcn-docs-sidebar-parity-needs-source-and-dom-metrics.mddocs/solutions/developer-experience/2026-05-24-plate-init-routes-should-return-shadcn-registry-base-items.mddocs/solutions/developer-experience/2026-05-24-shadcn-v4-registry-schema-needs-source-only-validation.mddocs/solutions/developer-experience/2026-05-24-shadcn-registry-install-commands-should-use-configured-namespaces.mddocs/solutions/developer-experience/2026-05-24-fumadocs-page-tree-search-needs-locale-safe-metadata.mdDefault durable decisions:
/create, /charts, /colors, and public directory-style
product pages unless the user explicitly asks for a Plate version.content/docs/**./view/[name], and registry preview/source display./api/registry-source/[name] for
bandwidth, but do not treat it as a public registry API.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:
../shadcn/apps/v4 source against PlatelastSyncedCommitIf 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.
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.
Every upstream changed file must be assigned to one subsystem:
docs-engine: Fumadocs source, page tree, MDX compilation, raw markdownrouting: Next routes, rewrites, metadata, layout groupsshell-nav-sidebar: header, footer, sidebar, mobile nav, command/search UImdx-code: MDX components, code blocks, copy-page, source viewer, RSS/OGregistry-contract: shadcn schema, resolver semantics, namespace behavior,
init/base item, local-file installregistry-build: registry scripts, generated source indexes, validationpreview-view: block/component preview routes and iframe/source displayproduct-page: create, charts, colors, blocks gallery, directory, examples
pages that are shadcn product surfacestheme-style: global CSS, theme providers, tokens, active theme, customizerdeps-config: package, lock, tsconfig, eslint, Next configtests: upstream app tests and fixturesassets: public assets, manifest, images, fontsother: only with an explanationFor each file, record:
noneUseful 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/scripts/** |
apps/v4/styles/** | apps/www/src/app/globals.css, apps/www/src/styles/** |
apps/v4/package.json | apps/www/package.json |
apps/v4/next.config.mjs | apps/www/next.config.ts |
Search Plate by component/function names from upstream diffs:
rg -n "<ComponentOrFunctionName>|<route-segment>|<registry-key>" apps/www content/docs docs/sync/shadcn
Also search deleted/discarded vocabulary when upstream or Plate removes a surface:
rg -n "v0|OpenInV0|create|charts|colors|themes|customizer|useProject|liftMode|docsConfig|Contentlayer|/api/registry/\\[name\\]" apps/www content/docs docs
Classify each row with one decision:
adopt-upstream: upstream owns the better generic docs infrastructure and
Plate has no durable reason to diverge.smart-merge: apply the upstream architecture or fix, but retain a named
Plate product requirement.plate-fork: keep Plate's implementation intentionally; upstream change is
useful as context but not directly adopted.exclude-upstream: do not bring this upstream product surface to Plate.delete-plate-residue: upstream direction confirms local fork code should be
removed.no-op: upstream changed content or product surface irrelevant to Plate.needs-question: user decision required before planning implementation.Write a Markdown plan:
PLAN="docs/sync/shadcn/runs/$(date +%Y-%m-%d)-${BASE:0:7}-to-${TARGET:0:7}/plan.md"
The plan must include these sections:
# Sync Shadcn <base-short>..<target-short>
## Range
- Upstream repo: `shadcn-ui/ui`
- Upstream app: `../shadcn/apps/v4`
- Base: `<sha> <date> <subject>`
- Target: `<sha> <date> <subject>`
- Plate app: `apps/www`
- Status source: `docs/sync/shadcn/status.json`
## Summary
Short factual summary of the changed subsystems and the recommended merge
posture.
## Complete Upstream Inventory
| Status | Upstream file | Subsystem | Plate owner | Decision | Evidence |
| --- | --- | --- | --- | --- | --- |
| M | `apps/v4/...` | `shell-nav-sidebar` | `apps/www/src/...` | `smart-merge` | focused diff summary + rg evidence |
This table must include every row from `upstream-name-status.tsv`.
## Added Files
All upstream added files with decision.
## Modified Files
All upstream modified files with decision.
## Deleted Files
All upstream deleted files with decision.
## Recommended Merge Slices
| Order | Slice | Class | Files | Why | Verification |
| --- | --- | --- | --- | --- | --- |
## Micro Auto-Merges
List qualifying tiny overlapping-component fixes applied during this activation,
or `None`.
| Upstream file | Plate file | Change | Why direct | Verification |
| --- | --- | --- | --- | --- |
## Explicit Exclusions
List upstream changes not to import, especially v0/create/charts/colors/theme
surfaces, with the local Plate policy evidence.
## Plate Forks To Preserve
List intentional forks, including sidebar accordion/filter UX,
`/api/registry-source/[name]`, API MDX, CN docs, MCP, Plus hooks, GA, Plate home,
editor demos, workspace aliases, and package integration tests when touched.
## Visual Evidence
For visual scopes or browser-visible slices, include upstream and Plate
screenshot paths, viewport, route, and the visible deltas that still need work.
Do not rely on source diffs alone for visual parity.
## Smart Merge Details
For every `smart-merge` row, state what comes from upstream and what remains
Plate-owned.
## Questions
Only include real user decisions. Do not ask about settled policy.
## Status Update Rule
State whether this plan can advance `lastSyncedCommit` after implementation. If
not, identify the remaining groups.
If the inventory is very large, the plan still needs every row. Put the full row
table in inventory.md in the same run directory and link it from plan.md.
Default stop point:
Range: <base-short>..<target-short>
Plan: <path>
| Decision | Count | Notes |
| --- | ---: | --- |
| adopt-upstream | ... | ... |
| smart-merge | ... | ... |
| plate-fork | ... | ... |
| exclude-upstream | ... | ... |
| delete-plate-residue | ... | ... |
| needs-question | ... | ... |
Micro auto-merges:
- <list, or none>
Recommended first slice: <slice>
Question: Review the plan. Should any decision change before implementation?
To implement it, invoke `sync-shadcn` again with the accepted plan path and
slice.
Ask one pointed question when there are needs-question rows. Do not ask about
settled exclusions.
Then stop. Do not delegate implementation to task from the same planning
activation, even if the recommended slice looks obvious.
taskOnly after a later user message accepts a plan/slice, load $task with this prompt:
Implement this shadcn docs sync slice.
Upstream: shadcn-ui/ui `../shadcn/apps/v4`
Range: <base-sha>..<target-sha>
Plan: <docs/sync/shadcn/runs/.../plan.md>
Slice: <one-sentence selected slice>
Class: <adopt-upstream | smart-merge | plate-fork cleanup | delete-plate-residue>
Evidence:
- Upstream commits: <short commit list or artifact path>
- Upstream files: <file rows from the plan>
- Upstream diff evidence: <focused command summaries, file rows, or hunk notes>
- Plate evidence: <local files and solution notes>
- Explicit exclusions: <v0/create/charts/colors/themes/etc. if relevant>
Implementation:
- <specific files or surfaces to inspect first>
- <what should come from upstream>
- <what must stay Plate-owned>
- <what must be deleted instead of carried forward>
Acceptance:
- <focused typecheck/test/source audit>
- `pnpm install` only if package, lock, or agent generated output needs it
- `pnpm lint:fix`
- browser proof only if the slice changes browser-visible docs UI
- for visual slices, screenshot both upstream shadcn and Plate pages at the
same viewport before calling the slice done
- do not run `build:registry`
- update `docs/sync/shadcn/status.json` only if the whole target range is fully
accounted for; otherwise record a partial sync note and keep
`lastSyncedCommit` unchanged
Do not preserve obsolete Plate fork residue if the upstream change removes the
need for it. Hard cut the residue.
Then follow task until the implementation is verified or a real blocker is
proven. This is implementation mode, not the planning run that wrote the plan.
docs/sync/shadcn/status.json has three meanings:
lastSyncedCommit: every upstream change through this commit has been
adopted, smart-merged, intentionally forked, or explicitly excluded.lastPlannedCommit: latest target commit with a written sync plan.partialSyncs: accepted slices that landed before the whole range was fully
accounted for.Plan generation may update lastPlannedCommit and lastPlan.
Only update lastSyncedCommit when:
When advancing the baseline, include:
{
"lastSyncedCommit": "<target-sha>",
"lastSyncedAt": "YYYY-MM-DD",
"lastSyncPlan": "docs/sync/shadcn/runs/.../plan.md",
"lastVerification": ["<commands or proof>"]
}
Do not delete older run artifacts. They are the audit trail.
For planning-only runs, end with:
Range: <base-short>..<target-short>
Plan: <path>
| Decision | Count | Notes |
| --- | ---: | --- |
| adopt-upstream | ... | ... |
| smart-merge | ... | ... |
| plate-fork | ... | ... |
| exclude-upstream | ... | ... |
| delete-plate-residue | ... | ... |
| needs-question | ... | ... |
Micro auto-merges:
- <list, or none>
Recommended first slice: <slice>
Question: Review the plan. Should any decision change before implementation?
To implement it, invoke `sync-shadcn` again with the accepted plan path and
slice.
For implementation runs, use task's final handoff format and include whether
docs/sync/shadcn/status.json was advanced or left unchanged.