Zum Inhalt

Reduce the Preset Library to the 7 Curated (Implementation Plan)

For agentic workers: REQUIRED SUB-SKILL: superpowers:subagent-driven-development. Steps use checkbox (- [ ]) syntax.

Goal: Make the 7 curated factory presets the ONLY built-ins everywhere — web library, native bundle, thumbnails, docs — retiring the ~22 hand-built classics. Johannes' decision (2026-06-21): "überall auf 7 runter", accepting that builtin:<classic> embed/share links break.

Architecture: The web SSOT src/presets/builtIn.ts composes BUILT_IN_PRESETS from HAND_BUILT (25 classics) + CURATED_PRESETS (7, self-contained in curated.ts). Reduce BUILT_IN_PRESETS to just the curated 7, repoint DEFAULT_PRESET (currently Dreamy → Aurora), regenerate the native preset JSONs from the SSOT (the engine drift-guard test decodes whatever JSONs are committed — no count assert), prune classic thumbnails, and fix the two tests + README that reference classic ids.

Tech Stack: TypeScript/Solid (web), scripts/export-native-presets.ts (native sync), Vitest + Playwright (web tests), Swift swift test (engine drift guard).

The 7 curated ids (keep): aurora, dancing-ink, mandala, mystic, neon-waves, solar-veil, terminal-haze.


Conventions

  • Repo root: the physarum checkout (all paths repo-relative). Work on main. Conventional Commits, no emoji, no --no-verify. Do NOT push.
  • Web gates: npm test (vitest), npx tsc --noEmit, npm run build. Engine gate: cd apple/PhysarumEngine && swift test.

Task 1: Reduce the web SSOT to the 7 + repoint the default + fix tests

Files: - Modify: src/presets/builtIn.ts (remove the HAND_BUILT array, lines ~101–1160; simplify the BUILT_IN_PRESETS export) - Modify: tests/e2e/player.spec.ts (classic ids → curated) - Modify: tests/player/resolvePreset.test.ts (classic id → curated, for clarity)

  • [ ] Step 1: Pre-check for hidden classic-id dependencies

Run: grep -rnE "BUILT_IN_PRESETS\.length|presets\.length === |\.length\).toBe\(29|toHaveLength\(29" src tests and grep -rnE "'(dreamy|nebula|lava|matrix|circuits|coral|embers|waves|fireworks|supernova|nebula)'" src tests | grep -v builtIn.ts | grep -v curated.ts Expected: only tests/e2e/player.spec.ts and tests/player/resolvePreset.test.ts reference classic ids; NO test asserts a count of 29. If a count assert exists, update it to 7 in this task.

  • [ ] Step 2: Remove HAND_BUILT and simplify the export

In src/presets/builtIn.ts, delete the entire const HAND_BUILT = ( … ) as const).map(withThumb); block (≈ lines 101–1160). Keep the helper functions hex, sp, symMatrix, withThumb and the CURATED_PRESETS import. Replace the export block:

const CURATED_IDS = new Set(CURATED_PRESETS.map((p) => p.id));
export const BUILT_IN_PRESETS: readonly Preset[] = [
  ...HAND_BUILT.filter((p) => !CURATED_IDS.has(p.id)),
  ...CURATED_PRESETS.map(withThumb),
];

// biome-ignore lint/style/noNonNullAssertion: literal index 0 is safe on a non-empty const array
export const DEFAULT_PRESET = BUILT_IN_PRESETS[0]!; // Dreamy

with:

// The library is exactly the 7 curated factory presets (curated.ts). The hand-built
// classics were retired 2026-06-21 (Johannes' call) — git history holds them.
export const BUILT_IN_PRESETS: readonly Preset[] = CURATED_PRESETS.map(withThumb);

// biome-ignore lint/style/noNonNullAssertion: literal index 0 is safe on a non-empty const array
export const DEFAULT_PRESET = BUILT_IN_PRESETS[0]!; // Aurora

If, after removing HAND_BUILT, biome reports sp/symMatrix as unused non-exported symbols, remove them too; if they remain exported, leave them (exports are not flagged). Run npx biome check src/presets/builtIn.ts to confirm.

  • [ ] Step 3: Fix the tests that load a classic preset

In tests/e2e/player.spec.ts: replace builtin:dreamy → builtin:aurora and the playlist builtin:dreamy,builtin:aurora → builtin:aurora,builtin:mandala; update any toContain('dreamy') → toContain('aurora'). In tests/player/resolvePreset.test.ts: change the parseSource('builtin:dreamy') example → parseSource('builtin:aurora') and its expected value: 'dreamy' → value: 'aurora'.

  • [ ] Step 4: Verify web — types, unit, build

Run: npx tsc --noEmit && npm test && npm run build Expected: tsc clean; vitest all green (the count is now 7); build succeeds.

  • [ ] Step 5: Commit
git add src/presets/builtIn.ts tests/e2e/player.spec.ts tests/player/resolvePreset.test.ts
git commit -m "feat(presets): retire the hand-built classics — library is the 7 curated"

Task 2: Regenerate the native preset JSONs to the 7

Files: - Delete + regenerate: apple/PhysarumApp/Resources/Presets/*.json (29 → 7)

The export script writes per-preset but does NOT prune; clear the dir first so retired classics don't linger.

  • [ ] Step 1: Clear the stale native preset JSONs, then re-export from the (now 7-preset) SSOT

Run:

rm -f apple/PhysarumApp/Resources/Presets/*.json
npx tsx scripts/export-native-presets.ts
ls apple/PhysarumApp/Resources/Presets/*.json | wc -l
Expected: 7 JSON files (aurora, dancing-ink, mandala, mystic, neon-waves, solar-veil, terminal-haze). (If the script also writes a manifest/index, confirm it lists 7.)

  • [ ] Step 2: Confirm factory.json untouched + engine drift guard green

apple/PhysarumApp/Resources/Factory/factory.json must be unchanged (already the 7 slots): git diff --stat apple/PhysarumApp/Resources/Factory/factory.json → empty. Run: cd apple/PhysarumEngine && swift test Expected: all green — testAllCommittedPresetsDecode now decodes the 7 committed JSONs.

  • [ ] Step 3: Commit
git add apple/PhysarumApp/Resources/Presets
git commit -m "chore(presets): regenerate native preset JSONs to the 7 curated"

Task 3: Prune classic thumbnails to the 7

Files: - Prune: assets/presets/*.png, public/preset-thumbs/*.png

  • [ ] Step 1: Keep only the 7 curated thumbnails

Run (for both dirs, keep only the 7 curated ids):

for dir in assets/presets public/preset-thumbs; do
  for f in "$dir"/*.png; do
    base=$(basename "$f" .png)
    case "$base" in aurora|dancing-ink|mandala|mystic|neon-waves|solar-veil|terminal-haze) ;; *) git rm -q "$f" 2>/dev/null || rm -f "$f";; esac
  done
done
ls assets/presets/ public/preset-thumbs/ 2>/dev/null
Expected: each dir holds exactly the 7 curated PNGs. The README gallery references assets/presets/<curated>.png — those 7 remain, so the gallery still renders.

  • [ ] Step 2: Verify the README gallery images all still exist

Run: for p in aurora mandala mystic terminal-haze neon-waves solar-veil dancing-ink; do test -f assets/presets/$p.png && echo "ok $p" || echo "MISSING $p"; done Expected: all 7 ok.

  • [ ] Step 3: Commit
git add -A assets/presets public/preset-thumbs
git commit -m "chore(presets): prune classic thumbnails to the 7 curated"

Task 4: README + CHANGELOG

Files: - Modify: README.md, CHANGELOG.md

  • [ ] Step 1: README — fix the classic references

In README.md: - Features list: the **29 curated built-in presets** spanning … bullet (with classic names Matrix, Circuits, Neural Lattice, Murmuration, Comet Trail, Supernova, Ink Study, Ink Veins) → rewrite to the 7: **7 curated factory presets** — Aurora, Mandala, Mystic, Terminal Haze, Neon Waves, Solar Veil, and Dancing Ink: a hand-tuned starting set spanning luminous rings, kaleidoscopic symmetry, and ink-on-paper. - Preset gallery intro line "The full library has 29 built-ins." → "These 7 are the full built-in set." - Embed playlist example playlist="builtin:dreamy,builtin:aurora,builtin:nebula" → playlist="builtin:aurora,builtin:mandala,builtin:mystic". - Scan for any other builtin:<classic> or classic preset name; update or remove.

  • [ ] Step 2: CHANGELOG — note the reduction under [Unreleased]

Add under ## [Unreleased] → ### Changed:

- **The built-in library is now the 7 curated factory presets.** The earlier hand-built
  classics were retired so the web and native apps share one starter set. Existing
  `builtin:<classic>` embed/share links no longer resolve (git history keeps the definitions).

  • [ ] Step 3: Commit
git add README.md CHANGELOG.md
git commit -m "docs: reflect the 7-preset library in README + changelog"

Task 5: Final verification

  • [ ] Step 1: Full web gates

Run: npx tsc --noEmit && npm test && npm run build Expected: tsc clean, vitest green, build succeeds.

  • [ ] Step 2: Engine + native sanity

Run: cd apple/PhysarumEngine && swift test (green) and cd apple/PhysarumApp && xcodegen generate && xcodebuild -scheme Physarum -destination 'platform=macOS' build (BUILD SUCCEEDED — the app reads factory.json=7 + the regenerated Resources/Presets).

  • [ ] Step 3: Embed smoke — the 7 resolve

Run: grep -oE "id: '[a-z-]+'" src/presets/curated.ts | sed "s/id: //;s/'//g" | sort | tr '\n' ' ' Expected: aurora dancing-ink mandala mystic neon-waves solar-veil terminal-haze — and confirm BUILT_IN_PRESETS length is 7 (e.g. a quick grep -c in the built output or a vitest assertion already covers it).

  • [ ] Step 4: Done — no commit (verification only). Report any gate failure with its output tail.

Done criteria

  • [ ] BUILT_IN_PRESETS = the 7 curated; DEFAULT_PRESET = Aurora; classics gone from builtIn.ts.
  • [ ] Native Resources/Presets/ = 7 JSONs; factory.json untouched; engine swift test green.
  • [ ] Thumbnails pruned to 7; README gallery still renders.
  • [ ] README + CHANGELOG updated; the 2 classic-id tests fixed.
  • [ ] vitest + tsc + web build + swift test + macOS build all green.