Compare commits

...

2 Commits

Author SHA1 Message Date
Alexander Whitestone
c2aed12464 docs: refresh the-playground genome analysis (#671)
Some checks failed
Agent PR Gate / gate (pull_request) Failing after 24s
Self-Healing Smoke / self-healing-smoke (pull_request) Failing after 11s
Smoke Test / smoke (pull_request) Failing after 17s
Agent PR Gate / report (pull_request) Has been cancelled
2026-04-17 03:09:43 -04:00
Alexander Whitestone
d9221d5cd6 wip: refresh the-playground genome regression test 2026-04-17 03:09:43 -04:00
2 changed files with 313 additions and 383 deletions

View File

@@ -1,35 +1,54 @@
from pathlib import Path
GENOME = Path("the-playground-GENOME.md")
def _content() -> str:
return Path("the-playground-GENOME.md").read_text()
assert GENOME.exists(), "the-playground-GENOME.md must exist"
return GENOME.read_text(encoding="utf-8")
def test_the_playground_genome_exists() -> None:
assert Path("the-playground-GENOME.md").exists()
assert GENOME.exists()
def test_the_playground_genome_has_required_sections() -> None:
content = _content()
assert "# GENOME.md — the-playground" in content
assert "## Project Overview" in content
assert "## Architecture" in content
assert "```mermaid" in content
assert "## Entry Points" in content
assert "## Data Flow" in content
assert "## Key Abstractions" in content
assert "## API Surface" in content
assert "## Test Coverage Gaps" in content
assert "## Security Considerations" in content
assert "## Dependencies" in content
assert "## Deployment" in content
assert "## Technical Debt" in content
required = [
"# GENOME.md — the-playground",
"## Project Overview",
"## Architecture",
"```mermaid",
"## Entry Points",
"## Data Flow",
"## Key Abstractions",
"## API Surface",
"## Test Coverage Gaps",
"## Security Considerations",
"## Dependencies",
"## Deployment",
"## Technical Debt",
"## Bottom Line",
]
for heading in required:
assert heading in content
def test_the_playground_genome_captures_repo_specific_findings() -> None:
def test_the_playground_genome_reflects_current_repo_shape() -> None:
content = _content()
assert "IndexedDB" in content
assert "AudioContext" in content
assert "smoke-test.html" in content
assert "no tests ran" in content
assert "innerHTML" in content
required_snippets = [
"14 JavaScript source files",
"src/export/wav-encoder.js",
"src/export/download.js",
"src/utils/perf-monitor.js",
"src/modes/constellation.js",
"tests/test_perf_budgets.py",
"pytest -q` → `7 passed",
"the-playground #247",
"the-playground #248",
"JSZip from CDN",
"PerfMonitor ships but is never loaded or started on `main`",
]
for snippet in required_snippets:
assert snippet in content

View File

@@ -1,34 +1,42 @@
# GENOME.md — the-playground
Generated: 2026-04-15 00:19:15 EDT
Generated: 2026-04-17 10:00 UTC
Repo: Timmy_Foundation/the-playground
Issue: timmy-home #671
Analyzed commit: `142d77736de3b303ea5320dbd5dcfda99e59f325`
Host issue: timmy-home #671
## Project Overview
The Sovereign Playground is a browser-only creative sandbox: a dark, local-first art toy with an entrance ritual, a canvas in the center, a sound panel on the left, a gallery on the right, and a footer action bar for save/download/clear/fullscreen.
`the-playground` is a browser-first creative sandbox with a strong visual identity and a deliberately simple deployment model: open `index.html` or serve static files. It is not yet the full platform promised by the README. The current repo is a compact prototype shell with real interaction loops for sound, drawing, constellation play, gallery persistence, and export.
The current codebase is much smaller than the README vision. The README describes a platform with Sound Studio, Visual Forge, Gallery, Games Floor, Video Forge, and a long roadmap of immersive experiences. The code on `main` today implements a solid prototype shell with:
- a cinematic entrance screen
- two actual canvas modes: `free-draw` and `ambient`
- a basic Web Audio engine for notes/chords/scales
- a basic Canvas 2D visual engine
- an IndexedDB-backed gallery
- a manual browser smoke harness
Quick measured facts from the fresh main clone I analyzed:
- 10 JavaScript source files
Current measured facts from the fresh `main` archive I analyzed:
- 14 JavaScript source files
- 1 CSS design system file
- 2 HTML entry pages (`index.html`, `smoke-test.html`)
- 1 Python test module in the target repo (`tests/test_perf_budgets.py`)
- 0 package manifests
- 0 build steps
- `python3 -m pytest -q` -> `no tests ran in 0.02s`
- browser smoke harness shows 18 passing checks, but the summary is broken and still says `0 passed, 0 failed`
- `pytest -q` `7 passed in 0.03s`
- no backend or network API in the shipped app shell
This repo is best understood as a browser-native prototype platform shell with one strong design language and three real cores:
1. orchestration in `src/playground.js`
What exists on `main` today:
- cinematic entrance screen
- three actual canvas/runtime modes:
- `free-draw`
- `ambient`
- `constellation`
- a Web Audio engine for notes/chords/scales
- a Canvas 2D visual engine
- an IndexedDB-backed gallery
- export helpers for WAV, single-item download, ZIP packaging, and standalone HTML export
- perf budget artifacts and a dormant runtime performance monitor
- a browser smoke harness plus one pytest module for perf budget/pipeline presence
This repo is best understood as four layers:
1. page shell + script-order runtime contract
2. browser engines (`PlaygroundAudio`, `PlaygroundVisual`, `PlaygroundGallery`)
3. thin shared globals (`PlaygroundUtils`, `PlaygroundState`, `PlaygroundEvents`, `ModeManager`)
3. experience/orchestration (`src/playground.js`, `ModeManager`, `constellation`)
4. export/perf sidecars that are only partially integrated into the live app
## Architecture
@@ -38,258 +46,237 @@ graph TD
HTML --> U[src/utils/utils.js]
HTML --> S[src/utils/state.js]
HTML --> E[src/utils/events.js]
HTML --> A[src/engine/audio-engine.js]
HTML --> V[src/engine/visual-engine.js]
HTML --> AE[src/engine/audio-engine.js]
HTML --> VE[src/engine/visual-engine.js]
HTML --> G[src/gallery/gallery.js]
HTML --> WAV[src/export/wav-encoder.js]
HTML --> EXP[src/export/download.js]
HTML --> SP[src/panels/sound/sound-panel.js]
HTML --> GP[src/panels/gallery/gallery-panel.js]
HTML --> M[src/modes/mode-manager.js]
HTML --> P[src/playground.js]
HTML --> MM[src/modes/mode-manager.js]
HTML --> CONST[src/modes/constellation.js]
HTML --> APP[src/playground.js]
P --> A
P --> V
P --> G
P --> SP
P --> GP
P --> M
P --> S
P --> E
P --> U
APP --> AE
APP --> VE
APP --> G
APP --> SP
APP --> GP
APP --> MM
APP --> U
APP --> S
APP --> E
GP --> EXP
EXP --> WAV
G --> IDB[(IndexedDB playground-gallery)]
AE --> AC[AudioContext]
VE --> CANVAS[Canvas 2D]
User[User interactions] --> P
P --> Canvas[Canvas 2D]
P --> Audio[AudioContext]
P --> DB[IndexedDB playground-gallery]
DB --> GP
SP --> A
M --> Canvas
Smoke[smoke-test.html] --> U
Smoke --> S
Smoke --> E
Smoke --> A
Smoke --> V
Smoke --> G
SMOKE[smoke-test.html] --> U
SMOKE --> S
SMOKE --> E
SMOKE --> AE
SMOKE --> VE
SMOKE --> G
PERF[src/utils/perf-monitor.js]
PERFTEST[tests/test_perf_budgets.py] --> PERF
PERFTEST --> PERFCFG[lighthouse-budget.json + .lighthouserc.json + .gitea/workflows/perf-check.yml]
HTML -. not loaded on main .-> PERF
```
## Entry Points
### `index.html`
The real application shell.
- loads `src/styles/design-system.css`
- renders the entrance curtain, header, panels, canvas, action bar, and toast container
- loads 10 classic `<script>` files in a strict dependency order
- has no framework, bundler, or module loader
The real product entry point.
Script order is the runtime contract:
Responsibilities:
- defines the entrance curtain
- defines header, left sound panel, center canvas, right gallery panel, and footer action bar
- loads global scripts in strict dependency order
- exposes no module loader or bundler boundary
Current runtime script order:
1. `src/utils/utils.js`
2. `src/utils/state.js`
3. `src/utils/events.js`
4. `src/engine/audio-engine.js`
5. `src/engine/visual-engine.js`
6. `src/gallery/gallery.js`
7. `src/panels/sound/sound-panel.js`
8. `src/panels/gallery/gallery-panel.js`
9. `src/modes/mode-manager.js`
10. `src/playground.js`
7. `src/export/wav-encoder.js`
8. `src/export/download.js`
9. `src/panels/sound/sound-panel.js`
10. `src/panels/gallery/gallery-panel.js`
11. `src/modes/mode-manager.js`
12. `src/modes/constellation.js`
13. `src/playground.js`
Because everything is loaded as globals, this order matters. `src/playground.js` assumes the prior globals already exist.
Important truth: `src/utils/perf-monitor.js` exists in the repo but is not loaded by `index.html` on current `main`.
### `src/playground.js`
The orchestration nucleus.
Responsibilities:
- entrance particle animation
- enter transition
- engine construction and initialization
- canvas sizing
- gallery boot
- sound panel boot
- ambient particle loop
- mode registration
- save/download/clear/fullscreen button wiring
- panel toggle wiring
- keyboard shortcut wiring
If you want to know what the product actually does today, this is the file.
What it does today:
- entrance particle system and enter transition
- engine construction and initialization
- default ambient animation loop
- mode registration and selector rendering
- canvas resizing
- gallery initialization and rerender after saves
- save/download/clear/fullscreen button wiring
- footer prompt handling and keyboard shortcuts
This file is the clearest statement of what the app actually is right now.
### `smoke-test.html`
The only real automated harness shipped in the target repo.
- dynamically loads a subset of source files
- performs 18 browser assertions around utils/state/events/audio/visual/gallery
- writes green/red lines into the DOM
- currently has a broken summary counter
Browser smoke harness.
- loads a subset of runtime files directly
- runs assertions in the browser DOM
- provides manual high-signal sanity checks around utils/state/events/audio/visual/gallery
### Engine modules
- `src/engine/audio-engine.js`
- Web Audio wrapper for notes, chords, scales, note playback, and chord playback
- `src/engine/visual-engine.js`
- Canvas wrapper for resize, clear, line/circle drawing, seeded palette generation, and placeholder noise
- `src/gallery/gallery.js`
- IndexedDB persistence layer
### `tests/test_perf_budgets.py`
The only pytest module in the target repo.
### Panel / mode modules
- `src/panels/sound/sound-panel.js`
- renders sound controls and quick-play chord UI
- `src/panels/gallery/gallery-panel.js`
- renders gallery thumbnails and empty state
- `src/modes/mode-manager.js`
- registry/switcher for canvas modes
What it verifies:
- existence of `src/utils/perf-monitor.js`
- existence of `lighthouse-budget.json`
- existence of `.lighthouserc.json`
- existence of `.gitea/workflows/perf-check.yml`
- very shallow content checks for the perf monitor and perf workflow artifacts
## Data Flow
### App boot flow
### Boot flow
1. Browser opens `index.html`.
2. CSS design system establishes the entire visual identity.
3. Utility/state/event globals load.
4. Audio, visual, gallery, panel, and mode globals load.
5. `src/playground.js` runs immediately in an IIFE.
6. The entrance screen appears with animated gold particles.
7. User clicks `Enter` or presses any key.
8. `enterPlayground()`:
- fades the entrance out
- creates and initializes `PlaygroundAudio`
- reveals the playground
- calls `initPlayground()`
- plays a welcome chord
2. CSS establishes the gold-on-dark design system.
3. utility/state/events globals load.
4. engine/gallery/export/panel/mode globals load.
5. `src/playground.js` runs in an IIFE.
6. entrance screen shows animated particles.
7. user clicks `Enter` or presses a key.
8. `enterPlayground()` fades out entrance, initializes audio, reveals the app shell, and starts the playground.
### Main interaction flow
1. `initPlayground()` creates `PlaygroundVisual(canvas)`.
2. Canvas is resized to the container.
3. `PlaygroundGallery` opens IndexedDB and initializes the gallery panel.
4. `SoundPanel.init(audioEngine)` renders the left control surface.
5. `ModeManager.register()` adds two modes:
- `free-draw`
- `ambient`
6. `ModeManager.renderSelector()` creates mode buttons.
7. `ModeManager.switch('ambient')` makes the experience feel alive on load.
### Core interaction flow
1. `PlaygroundVisual` binds the canvas.
2. `PlaygroundGallery` opens IndexedDB.
3. `SoundPanel.init(audioEngine)` renders the left-side sound UI.
4. `GalleryPanel.init(galleryEngine)` renders the right-side gallery UI.
5. `ModeManager` registers available modes and renders selector buttons.
6. ambient mode starts by default; draw and constellation can be selected.
### Draw mode flow
1. User switches to `Draw`.
2. `free-draw.init()` binds mouse and touch listeners.
3. Pointer movement draws lines on the canvas via `visualEngine.drawLine()`.
4. X-position is mapped to frequency with `PlaygroundUtils.map()`.
5. `audioEngine.play()` emits short sine notes while drawing.
6. The first interaction hides the “Click anywhere to begin” prompt.
### Draw/save/export flow
1. user draws or interacts in a mode.
2. save path converts canvas to a blob/data URL.
3. `PlaygroundGallery.save()` writes a gallery item into IndexedDB.
4. `gallery:item-saved` fires on the event bus.
5. `GalleryPanel` rerenders.
6. download path exports the canvas PNG and a JSON metadata sidecar.
7. gallery panel can also invoke `PlaygroundExport.downloadItem()` for persisted items.
### Save/export flow
1. User clicks `Save`.
2. Canvas is converted to PNG via `canvas.toBlob()`.
3. `FileReader` converts the blob to a data URL.
4. `galleryEngine.save()` writes an object into IndexedDB with:
- `id`
- `created`
- `modified`
- `type`
- `name`
- `data`
- `mimeType`
- `thumbnail`
- `metadata.mode`
5. `gallery:item-saved` fires on the event bus.
6. `GalleryPanel` rerenders.
### Constellation mode flow
1. `ModeManager.switch('constellation')` activates `src/modes/constellation.js`.
2. stars are created and drawn on the canvas.
3. drag events move stars.
4. close-distance interactions trigger pentatonic notes and an ambient drone.
5. teardown removes listeners and fades out drone oscillators.
### Gallery render flow
1. `GalleryPanel.render()` calls `gallery.getAll()`.
2. Results are sorted newest-first by ISO timestamp.
3. Gallery HTML is rebuilt via `innerHTML`.
4. Clicking a thumb currently only shows a toast with the item id prefix.
- there is no real open/view/edit flow yet
### Download flow
1. User clicks `Download`.
2. Canvas blob is created.
3. `PlaygroundUtils.downloadBlob()` synthesizes an `<a download>` link.
4. Browser downloads a PNG snapshot.
### Metrics synthesis flow (current state)
1. perf budget artifacts exist in the repo.
2. `tests/test_perf_budgets.py` proves those files exist.
3. `PerfMonitor` can emit paint/layout/long-task/memory signals.
4. but the live app never loads or starts it, so there is no real runtime metric emission on `main`.
## Key Abstractions
### `PlaygroundUtils`
A tiny global helpers object.
Important methods:
- `uuid()` -> `crypto.randomUUID()`
Small browser helper surface:
- `uuid()`
- `clamp()`
- `lerp()`
- `map()`
- `toast()`
- `downloadBlob()`
It is intentionally small, but it is depended on by multiple subsystems.
### `PlaygroundState`
A global mutable state container with sections for:
- `canvas`
- `audio`
- `gallery`
- `ui`
- `recording`
Global mutable state bucket for:
- canvas
- audio
- gallery
- UI
- recording
It behaves more like a convenience registry than a true source-of-truth store. Real durable gallery data lives in IndexedDB, not here.
It is a convenience registry, not a durable data store.
### `PlaygroundEvents`
A minimal event bus:
Minimal event bus:
- `on(event, fn)`
- `emit(event, data)`
- `off(event, fn)`
This is the main loose-coupling seam across modules.
### `PlaygroundAudio`
A lightweight music engine over `AudioContext`.
Capabilities:
- note-name to frequency conversion
- chord construction
- scale construction
- one-shot oscillator playback
Web Audio wrapper for:
- note → frequency mapping
- chord generation
- scale generation
- oscillator playback
- chord playback
- analyser wiring for future visualization/reactivity
### `PlaygroundVisual`
A minimal canvas wrapper.
Capabilities:
- resize canvas and bind context into `PlaygroundState`
- clear canvas
- draw lines and circles
- deterministic palette generation from a seed
- placeholder pseudo-noise function (`perlin2d`, not real Perlin)
Canvas wrapper for:
- resize
- clear
- drawLine
- drawCircle
- seeded palette generation
- placeholder pseudo-noise helper
### `PlaygroundGallery`
A thin IndexedDB repository.
Contract:
IndexedDB repository:
- DB name: `playground-gallery`
- store: `items`
- object store: `items`
- indexes: `type`, `collection`, `created`
- CRUD methods:
- `init()`
- `save(item)`
- `getById(id)`
- `getAll()`
- `deleteItem(id)`
- methods: `init`, `save`, `getById`, `getAll`, `deleteItem`
### `ModeManager`
A registry + switcher for canvas modes.
It holds:
- `modes`
- `current`
Registry/switcher for canvas experiences:
- `register()`
- `switch()`
- `renderSelector()`
- `current`
- `modes`
This is the intended extension point for future experiences.
### `PlaygroundExport`
Download/export sidecar for:
- single item download
- metadata sidecars
- batch ZIP export
- standalone HTML gallery export
### `SoundPanel` and `GalleryPanel`
These are rendering adapters that convert state/engine methods into DOM UI.
They keep the app readable by not putting every DOM template inside `src/playground.js`.
### `PlaygroundWavEncoder`
AudioBuffer → WAV blob encoder used by export paths.
### `PerfMonitor`
Dormant runtime performance monitor for:
- FCP/LCP
- CLS
- long tasks
- memory polling
Useful code, but currently disconnected from the product entrypoint.
## API Surface
This repo has no network API. Its API surface is an in-browser global surface.
This repo has no network API. The public surface is browser globals plus IndexedDB object contracts.
### Browser globals exposed by load order
### Browser globals exposed on `main`
- `PlaygroundUtils`
- `PlaygroundState`
- `PlaygroundEvents`
- `PlaygroundAudio`
- `PlaygroundVisual`
- `PlaygroundGallery`
- `PlaygroundWavEncoder`
- `PlaygroundExport`
- `SoundPanel`
- `GalleryPanel`
- `ModeManager`
@@ -303,8 +290,8 @@ Observed event names:
- `canvas:mode-changed`
- `playground:ready`
### IndexedDB object contract
Saved gallery items can contain:
### Gallery item contract
Persisted items can include:
- `id`
- `created`
- `modified`
@@ -314,9 +301,10 @@ Saved gallery items can contain:
- `mimeType`
- `thumbnail`
- `metadata`
- sometimes audio/video-specific fields consumed by export helpers
### UI control contract
Important DOM ids and commands:
### UI command surface
Important DOM ids:
- `btn-save`
- `btn-download`
- `btn-clear`
@@ -326,127 +314,78 @@ Important DOM ids and commands:
- `gallery-content`
- `playground-canvas`
Keyboard shortcuts implemented today:
- `Ctrl+S` -> Save
- `Ctrl+D` -> Download
- `F11` -> Fullscreen
- `Escape` -> exit fullscreen
Keyboard shortcuts implemented on `main`:
- `Ctrl+S` Save
- `Ctrl+D` Download
- `F11` Fullscreen
- `Escape` exit fullscreen
## Test Coverage Gaps
### Current state
What I verified on a fresh clone of `main`:
- `find src -name '*.js' -print0 | xargs -0 -n1 node --check` -> passes
- `python3 -m pytest -q` -> `no tests ran in 0.02s`
- `smoke-test.html` runs 18 browser assertions successfully
- but `smoke-test.html` reports `0 passed, 0 failed` in the summary even while showing 18 green checks
What I verified on a fresh `main` archive:
- `pytest -q``7 passed in 0.03s`
- there is exactly one pytest module: `tests/test_perf_budgets.py`
- no JS unit-test harness
- no package manifest
- browser smoke harness still exists, but it is not the same thing as CI-grade coverage
This means the repo has a manual browser smoke harness, but no real automated CI-grade test suite.
### What is covered today
- presence/shape of perf budget artifacts
- presence of the perf monitor file
- presence of the perf check workflow
- smoke-test manual coverage around utils/state/events/audio/visual/gallery (browser harness, not pytest)
### What is covered by `smoke-test.html`
- UUID/clamp/lerp helpers
- default state and snapshot
- event bus firing
- AudioContext construction and music theory helpers
- canvas visual primitives and deterministic palette generation
- IndexedDB save/getAll/getById/delete flow
### What is not covered and should be
### Critical uncovered paths
1. `src/playground.js` orchestration
- entrance flow
- mode registration
- action bar wiring
- initialization sequence
- action-bar wiring
- keyboard shortcuts
- panel toggles
2. `src/export/download.js`
- single-item export
- ZIP export
- standalone HTML export
3. `src/export/wav-encoder.js`
- WAV blob correctness
4. `src/modes/constellation.js`
- drag lifecycle
- teardown correctness
- audio interaction contract
5. gallery interaction behavior
- open/view flow
- item count updates
- HTML escaping and render safety
2. `ModeManager`
- teardown/init switching order
- active button state
- event emission correctness
3. `SoundPanel`
- BPM slider updates state
- quality button activation
- chord button actually invokes audio engine
- volume slider is rendered but currently unwired
4. `GalleryPanel`
- empty/non-empty rendering
- item-count text updates
- click behavior
- escaping/sanitization of item fields before `innerHTML`
5. cross-module browser integration
- draw mode pointer lifecycle
- touch behavior
- fullscreen and download wiring
- prompt fade-out on first interaction
### Generated missing tests for critical paths
#### A. Mode switching contract test
A Node+VM or browser test should verify teardown/init ordering and active button state.
```python
# pseudo-test idea
# load utils/state/events/mode-manager
# register two fake modes with counters
# switch twice
# assert first teardown ran before second init
# assert PlaygroundState.canvas.mode updated
```
#### B. Smoke summary correctness test
The current smoke harness is lying about pass/fail totals.
```python
# browser-level assertion
# after smoke-test.html finishes,
# count the green result rows and compare them to the h2 summary
```
#### C. GalleryPanel XSS regression test
`GalleryPanel.render()` builds markup with `innerHTML` from gallery item data.
That should be locked down with a test before the panel grows more capable.
```python
# save item with name containing HTML-like content
# render gallery
# assert rendered text is escaped / inert
# assert no unexpected nodes/scripts are created
```
### Filed from this analysis
- the-playground #247 — PerfMonitor ships but is never loaded or started on `main`
- the-playground #248 — batch export loads JSZip from CDN, violating zero-dependency/local-first posture
## Security Considerations
### Strengths
- zero network/API attack surface in the app itself
- no dependency tree or third-party script loaders
- local-first persistence using IndexedDB instead of remote storage
- deterministic, transparent runtime based on classic script tags
- reduced-motion CSS support already present
### Strong points
- no backend/API attack surface in the shipped app
- local-first IndexedDB persistence
- static hosting posture is simple and inspectable
- no npm dependency tree on current `main`
### Risks and caveats
1. `innerHTML` is used in multiple modules.
- `ModeManager.renderSelector()` builds buttons with `innerHTML`
- `SoundPanel.render()` builds control markup with `innerHTML`
- `GalleryPanel.render()` builds gallery thumbnails with `innerHTML`
- The first two are fed by trusted in-repo data.
- `GalleryPanel.render()` is the risky one because it interpolates gallery item data (`item.name`, `item.thumbnail`) coming back from IndexedDB.
2. Browser capability assumptions are strong.
- `crypto.randomUUID()`
- `AudioContext`
- `indexedDB`
- `canvas.toBlob()`
### Risks
1. `innerHTML` remains a major sink surface
- gallery rendering is the riskiest because it interpolates persisted item data
- related issues already exist in the target repo
2. dynamic third-party script load in export path
- `PlaygroundExport._loadJSZip()` injects a CDN script tag for JSZip
- this breaks the repo's own zero-dependency/local-first claim
3. dormant perf monitoring path
- monitoring code exists but is not in the runtime path
- repo can give a false sense of observability
4. browser capability assumptions remain strong
- IndexedDB
- AudioContext
- Fullscreen API
- FileReader
- all are required for the best path
3. No storage limits or cleanup policy.
- IndexedDB can grow without quotas or cleanup UX inside the app
- saved images are stored as data URLs, which can become heavy over time
4. No CSP/integrity story because the repo assumes direct static hosting or file-open execution.
- Blob/FileReader
- `crypto.randomUUID()`
## Dependencies
@@ -461,79 +400,51 @@ That should be locked down with a test before the panel grows more capable.
- standard DOM APIs
### Project/tooling dependencies
- none declared
- no `package.json`
- no `requirements.txt`
- no build tooling
- no CI workflow files on `main`
- no bundler
- no build step
- one pytest-based perf artifact check
- one browser smoke harness
### Verification tools used during analysis
- `node --check` for JS syntax verification
- browser execution of `smoke-test.html`
- `pytest` baseline probe, which confirmed there is no Python test suite in this target repo
### External runtime dependency discovered
- JSZip from CDN in `src/export/download.js` for batch ZIP export
## Deployment
The deployment model is intentionally trivial.
Current deployment model is still very simple:
- open `index.html` directly in a browser
- or serve the repo as static files from any web server
How to run it today:
- open `index.html` in a browser
- or serve the repo as static files from any plain web server
There is no backend, no API contract, no environment variables, and no deployment automation in the target repo.
Practical verification flow:
1. `find src -name '*.js' -print0 | xargs -0 -n1 node --check`
2. open `smoke-test.html`
3. open `index.html`
4. click `Enter`
5. verify:
- entrance transition
- ambient mode active by default
- sound panel playable
- save creates a gallery item in IndexedDB
- download exports a PNG
Verification flow I used:
1. inspect `index.html` script contract
2. run `pytest -q` in the target repo
3. inspect critical mode/export/perf files directly
4. compare live repo state to the existing genome artifact
## Technical Debt
### Highest-priority debt
1. README vision vs code reality gap
- the README describes a much larger platform than the current implementation
- mainline code today is a polished shell plus two real modes
2. No real automated test suite
- `python3 -m pytest -q` returns `no tests ran`
- the only harness is `smoke-test.html`
- the smoke harness summary is already broken
3. `GalleryPanel.render()` trusts item data too much
- direct `innerHTML` interpolation of stored item fields is a future XSS footgun
4. Global load-order coupling
- every major module assumes previous globals are already loaded
- there is no module isolation or dependency enforcement beyond script order
5. Volume slider is fake right now
- `vol-slider` exists in `SoundPanel.render()`
- there is no listener wiring it to `audioEngine.masterGain`
1. README vision still exceeds code reality
2. orchestration/export/mode behavior lacks serious automated coverage
3. `PerfMonitor` exists but is not wired into runtime (`#247`)
4. ZIP export relies on CDN-loaded JSZip (`#248`)
5. gallery/open interaction depth is still shallow compared to the product promise
### Meaningful product debt
- gallery items do not really open; click only toasts an id prefix
- no import/restore/export package flows
- no video forge
- no games floor
- no persistence integration between `PlaygroundState.gallery` and IndexedDB
- `mode-label` in the footer exists but is never updated
- `canvas-overlay` exists but is unused
- `perlin2d()` is explicitly a placeholder, not real Perlin noise
- skip-link CSS exists, but no skip link appears in `index.html`
- no real frontend app/test packaging discipline
- no integrated runtime metrics surface despite perf budget artifacts
- export system is richer than the rest of the UI exposes
- batch export and standalone gallery export exist in code but are not a clearly surfaced first-class workflow in the main shell
- the prototype is still held together by global load order rather than explicit module boundaries
## Bottom Line
The Playground is a clean sovereign-web prototype: one HTML shell, one design system, a handful of browser engines, and a strong aesthetic identity. It already proves the interaction model.
`the-playground` is no longer just a two-mode shell. Current `main` has grown into a more substantial browser prototype with export infrastructure, a third experience mode, a perf-budget lane, and one real pytest module.
What it does not yet have is the verification, hardening, and feature depth implied by its own vision. The core challenge now is not invention. It is contraction into truth:
- make the shipped surface match the promise
- turn `smoke-test.html` into real automated coverage
- harden `innerHTML` paths
- finish the panel/mode/gallery interactions that are still only half-born
But the repo still has a truth gap between what exists in source and what is actually exercised end-to-end:
- export is richer than the visible UI story
- performance monitoring exists but is not running
- dependency posture says local-first while ZIP export reaches for a CDN
- automated coverage is still far thinner than the surface area of the product
That is the real architectural story now: the codebase is starting to branch into platform-level capabilities, but verification and integration are lagging behind the feature shards already present in source.