- playground/voyage-playground.html: minimal skeleton (DOCTYPE, app-header, guide-panel, aria-live region, skip-to-main link). Steps 8-11 will extend with render-pipeline + creation gestures + sidebar + export. - playground/vendor/playground-design-system/: synced via 'node scripts/sync-design-system.mjs voyage' (27 files + MANIFEST.json with source_commit + sync_date + SHA-256 per file). - tests/playground/voyage-playground.test.mjs: 8 tests pinning HTML existence, DOCTYPE, no-external-URLs, no-marked, A11Y skip-to-main + aria-live, MANIFEST.json structure, vendored DS files present. - shared/PLAYGROUND-MAINTENANCE.md: consumer list updated 5 -> 6 (added voyage).
8.6 KiB
Playground Maintenance
Procedure for updating plugin playground HTML files (single-file decision-builders + report viewers shipped under plugins/<name>/playground/) when a plugin is extended or upgraded.
Six plugins currently consume the shared design system: ms-ai-architect, okr, llm-security, ultraplan-local, config-audit, voyage. The procedure is identical for all of them — substitute the plugin name where indicated.
Architecture in 30 seconds
marketplace-rot/
├── shared/
│ ├── playground-design-system/ ← Canonical source (where DS work happens)
│ │ ├── tokens.css, base.css, components*.css, fonts/
│ │ ├── CHANGELOG.md
│ │ └── README.md
│ └── playground-examples/ ← Reference scenarios + showcase landing
│
└── plugins/<name>/
└── playground/
├── <name>-playground.html ← Loads CSS from `vendor/...`
└── vendor/playground-design-system/ ← Vendored snapshot (synced from shared/)
└── MANIFEST.json ← SHA-256 per file + source_commit + sync_date
Standalone guarantee: plugin HTML loads vendor/..., never shared/.... After sync, vendor/ is self-sufficient — forkers who clip out plugins/<name>/ get everything.
Four update tracks
Pick the track(s) that match what you are changing. Multiple tracks can apply in one release.
Track A — Plugin HTML change (parser, renderer, surface, action)
When: you are adding/modifying parsers, renderers, surfaces, action handlers, or fixtures inside the plugin's playground HTML. No DS change.
- Edit
plugins/<name>/playground/<name>-playground.htmldirectly. - If fixture format changes, update
plugins/<name>/playground/test-fixtures/<archetype>.mdand re-run parser tests. - Run plugin's playground test suite:
cd plugins/<name> bash tests/run-e2e.sh --playground bash tests/test-playground-migrations.sh # if migrations exist - If demo state references fixtures, regenerate the inline JSON block:
node scripts/build-demo-state.mjs # idempotent — replaces existing block
No DS sync is needed for Track A.
Track B — Shared design-system change
When: you are adding new tokens, components, or modifying generic CSS that all consuming playgrounds should benefit from.
- Edit
shared/playground-design-system/<file>.cssat marketplace root. - Bump version in
shared/playground-design-system/CHANGELOG.md(Keep a Changelog format). - Sync vendored copy in each consuming plugin:
node scripts/sync-design-system.mjs <plugin-name> [--force]- Drift detection: the script refuses overwrite if
vendor/files have been modified locally (SHA-256 mismatch).--forceoverrides. MANIFEST.jsonis updated with newsource_commit+sync_dateper file.- Repeat for every consuming plugin (current consumers listed in repo-root
CLAUDE.md).
- Drift detection: the script refuses overwrite if
- Verify each plugin's playground tests still pass (Track A step 3).
- Each consuming plugin must adopt the new selectors in its HTML to actually use them — DS bumps are additive, never breaking.
Adoption is optional. Plugins not yet using a DS feature stay green without re-syncing. New DS hoists never break existing consumers as long as the bump is purely additive.
Track C — Visual verification (always before release)
When: any visual-affecting change has landed (Track A, B, or both).
- Regenerate screenshots:
cd plugins/<name>/tests/screenshot npm install # one-time, gitignored node_modules npx playwright install chromium # one-time, ~150MB node run.mjs- Output:
plugins/<name>/playground/screenshots/<version>/ - Bump
OUT_DIRintests/screenshot/run.mjswhen the plugin version changes (e.g. v1.10.0 → v1.11.0). - Decide whether to keep older screenshot folders as historical reference, or delete them — they live under git history regardless.
- Output:
- Manual visual QA in Chrome:
- Open the plugin playground HTML from
file://. - Compare against
shared/playground-examples/scenarios/<reference>.html(e.g.ros-lier-kommune.htmlis the showcase anchor for ms-ai-architect renderers). - Check: eyebrow labels visible, severity-coded borders rendering, app-header breadcrumb correct, AI Act pyramid not clipping text, light/dark theme toggle working.
- Open the plugin playground HTML from
Track D — Release (version bump + docs)
When: shipping a new version, regardless of which other tracks ran.
Mandatory files to update in the release commit (or immediately after):
plugins/<name>/.claude-plugin/plugin.json— bump"version".plugins/<name>/README.md— version badge, Version History entry, new detailed section under Playground describing the change.plugins/<name>/CLAUDE.md— Playground heading version, architecture notes, status of any deferred work.plugins/<name>/CHANGELOG.md— new[X.Y.Z]entry at the top (Keep a Changelog format) with Added/Changed/Notes subsections.- Marketplace-root
README.md— bump version reference in the plugin's block.
Conventional commit:
feat(<plugin-name>): release vX.Y.Z — <one-line summary>
Do not use [skip-docs] on release commits — release commits are exactly when docs ship. Intermediate session commits within a multi-session release may use [skip-docs] if docs are bundled with the final commit.
Push to Forgejo main is pre-authorized (see global ~/.claude/CLAUDE.md).
Three-doc rule (from marketplace-root CLAUDE.md)
Enhver feature-endring som pusher til Forgejo MÅ oppdatere alle tre doc-nivåer i SAMME commit eller umiddelbart etter:
- Plugin
README.md— detailed change documentation- Plugin
CLAUDE.md— architecture/overview- Marketplace-root
README.md— marketplace landing page
This rule applies to every release that consumers see. Internal refactors that do not change the user-visible contract may use [skip-docs], but the next release commit must catch up the docs.
Common pitfalls
- Editing
vendor/directly. Never. Editshared/and re-sync. Direct vendor edits trigger drift detection on next sync (which is the safety mechanism, but you have lost authorial intent). replace_allin Edit tool with a string that appears in multiple contexts. When migrating CSS class names, verify scope after eachreplace_all— e.g.<article class="card">may appear in both project-sub-card and catalog-card with different surrounding markup.- Sync without testing. Running
sync-design-system.mjsthen committing without running the plugin's test suite is how silent breakage ships. Always Track A step 3 after Track B step 3. - Forgetting to regenerate demo state. If you change fixture formats but skip
build-demo-state.mjs, the inline JSON block becomes stale and the "Last inn demo-data" button loads obsolete data. - Screenshot folder version mismatch. Bumping
plugin.jsonversion without updatingOUT_DIRintests/screenshot/run.mjsproduces screenshots in the wrong folder. Bump both. - Background orchestrators. The harness does not expose Agent tool to sub-agents launched in background. Default to foreground for any orchestration involving sub-agents.
When to consider hoisting
Inline CSS in a plugin's playground HTML is a candidate for hoisting to shared/playground-design-system/components-tier3-supplement.css when:
- The selector represents a generic visual pattern (not domain-specific semantics).
- At least two playgrounds would benefit (or one playground plus the showcase under
playground-examples/). - The pattern is structurally identical, not just visually similar (different ARIA semantics or DOM shapes are usually a sign to keep it plugin-local).
Components that should stay plugin-local include:
- Domain-specific verdict semantics (e.g. ms-ai-architect's
.verdict-pillfor go/block contrasts with DS.verdict-pill-lgfor severity bands). - Status modifiers that don't generalize (e.g.
.scenario-card[data-status="met/partial/missing"]vs DSdata-status="winner"). - Components with structurally different ARIA patterns (e.g. native
<details>vs JS-toggledaria-expanded). - Surface-specific layouts (
.onboarding-*,.home-*,.project-*,.modal*,.command-form*).
References
- Marketplace-root
CLAUDE.md— conventions and three-doc rule shared/playground-design-system/CHANGELOG.md— DS version historyshared/playground-design-system/README.md— DS API surface and token referenceshared/playground-examples/— reference scenarios serving as visual anchors- Each plugin's
CLAUDE.mdPlayground section — plugin-specific architecture and validation counts