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_BUILTand 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
- [ ] 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
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 frombuiltIn.ts. - [ ] Native
Resources/Presets/= 7 JSONs;factory.jsonuntouched; engineswift testgreen. - [ ] 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.