ktg-plugin-marketplace/shared/PLAYGROUND-MAINTENANCE.md
Kjell Tore Guttormsen 2f4330265c feat(voyage): scaffold playground/ with DS vendor sync — v4.2 Step 5
- 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).
2026-05-09 12:55:02 +02:00

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.

  1. Edit plugins/<name>/playground/<name>-playground.html directly.
  2. If fixture format changes, update plugins/<name>/playground/test-fixtures/<archetype>.md and re-run parser tests.
  3. Run plugin's playground test suite:
    cd plugins/<name>
    bash tests/run-e2e.sh --playground
    bash tests/test-playground-migrations.sh   # if migrations exist
    
  4. 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.

  1. Edit shared/playground-design-system/<file>.css at marketplace root.
  2. Bump version in shared/playground-design-system/CHANGELOG.md (Keep a Changelog format).
  3. 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). --force overrides.
    • MANIFEST.json is updated with new source_commit + sync_date per file.
    • Repeat for every consuming plugin (current consumers listed in repo-root CLAUDE.md).
  4. Verify each plugin's playground tests still pass (Track A step 3).
  5. 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).

  1. 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_DIR in tests/screenshot/run.mjs when 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.
  2. 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.html is 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.

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):

  1. plugins/<name>/.claude-plugin/plugin.json — bump "version".
  2. plugins/<name>/README.md — version badge, Version History entry, new detailed section under Playground describing the change.
  3. plugins/<name>/CLAUDE.md — Playground heading version, architecture notes, status of any deferred work.
  4. plugins/<name>/CHANGELOG.md — new [X.Y.Z] entry at the top (Keep a Changelog format) with Added/Changed/Notes subsections.
  5. 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:

  1. Plugin README.md — detailed change documentation
  2. Plugin CLAUDE.md — architecture/overview
  3. 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. Edit shared/ and re-sync. Direct vendor edits trigger drift detection on next sync (which is the safety mechanism, but you have lost authorial intent).
  • replace_all in Edit tool with a string that appears in multiple contexts. When migrating CSS class names, verify scope after each replace_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.mjs then 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.json version without updating OUT_DIR in tests/screenshot/run.mjs produces 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-pill for go/block contrasts with DS .verdict-pill-lg for severity bands).
  • Status modifiers that don't generalize (e.g. .scenario-card[data-status="met/partial/missing"] vs DS data-status="winner").
  • Components with structurally different ARIA patterns (e.g. native <details> vs JS-toggled aria-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 history
  • shared/playground-design-system/README.md — DS API surface and token reference
  • shared/playground-examples/ — reference scenarios serving as visual anchors
  • Each plugin's CLAUDE.md Playground section — plugin-specific architecture and validation counts