Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion .github/copilot-instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,15 @@ workflow are in [AGENTS.md](../AGENTS.md); architecture decisions are in [docs/a
- 3D follows [docs/3D-Visualization-Standard.md](../docs/3D-Visualization-Standard.md). three.js is imported only from a `React.lazy` renderer and never reaches the entry bundle; `manualChunks` has no rule for it.
- Motion respects `useReducedMotion` (`src/shared/hooks`).

### Playground
- There is exactly one Playground, at `/playground` (`src/features/playground/`). No module gets a playground of its own ([ADR 0004](../docs/adr/0004-playground-traces-share-the-snapshot.md)).
- A trace's steps and a story's beats hold the same snapshot and are drawn by the same 2D and 3D views. A lens chooses which regions are drawn; it never brings its own renderer.
- A trace is never presented as a story: no authored captions, and no garbage-collection sweep, because a run cannot observe one.
- JavaScript first; other languages emit the same snapshot.

### Code
- Icon props are typed `LucideIcon`: R3F's global JSX types make a bare `React.ElementType` reject `className`.
- Light mode only. Tailwind v4 can't see class names built at runtime (`bg-${color}-50`): write classes out literally or map them through a fixed object.
- Light mode only, except the Playground, which is dark ([ADR 0004](../docs/adr/0004-playground-traces-share-the-snapshot.md)). Tailwind v4 can't see class names built at runtime (`bg-${color}-50`): write classes out literally or map them through a fixed object.
- Browser support: use Baseline widely available web features directly; a newer feature needs a fallback. The `modern-web-guidance` skill (vendored, read its files, never run its npx CLI) has the patterns.
- Tests sit next to the code as `*.test.ts(x)`.

Expand Down
8 changes: 7 additions & 1 deletion AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,15 @@ After editing anything in `.agents/`, run `npm run agents:sync` and commit the g
- 3D follows [docs/3D-Visualization-Standard.md](docs/3D-Visualization-Standard.md). three.js is imported only from a `React.lazy` renderer and never reaches the entry bundle; `manualChunks` has no rule for it.
- Motion respects `useReducedMotion` (`src/shared/hooks`).

### Playground
- There is exactly one Playground, at `/playground` (`src/features/playground/`). No module gets a playground of its own ([ADR 0004](docs/adr/0004-playground-traces-share-the-snapshot.md)).
- A trace's steps and a story's beats hold the same snapshot and are drawn by the same 2D and 3D views. A lens chooses which regions are drawn; it never brings its own renderer.
- A trace is never presented as a story: no authored captions, and no garbage-collection sweep, because a run cannot observe one.
- JavaScript first; other languages emit the same snapshot.

### Code
- Icon props are typed `LucideIcon`: R3F's global JSX types make a bare `React.ElementType` reject `className`.
- Light mode only. Tailwind v4 can't see class names built at runtime (`bg-${color}-50`): write classes out literally or map them through a fixed object.
- Light mode only, except the Playground, which is dark ([ADR 0004](docs/adr/0004-playground-traces-share-the-snapshot.md)). Tailwind v4 can't see class names built at runtime (`bg-${color}-50`): write classes out literally or map them through a fixed object.
- Browser support: use Baseline widely available web features directly; a newer feature needs a fallback. The `modern-web-guidance` skill (vendored, read its files, never run its npx CLI) has the patterns.
- Tests sit next to the code as `*.test.ts(x)`.

Expand Down
86 changes: 77 additions & 9 deletions CONTEXT.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,20 +8,48 @@ A site that teaches programming by showing, step by step, what code and tools do
A visualization of one concept, told as a sequence of beats and drawn literally (frames, objects, commits, refs), never as an everyday metaphor.
_Avoid_: Animation, demo, walkthrough

**Snapshot**:
The full state at one moment: every entity present, with its values and references. A snapshot is what a view draws.
_Avoid_: State, frame, diff

**Beat**:
One moment of a story: a full snapshot of every entity present, with a title, a caption and a shot.
_Avoid_: Slide, frame, stage
One authored moment of a story: a snapshot with a title, a caption and a shot.
_Avoid_: Slide, frame, stage, step (a step is recorded, not authored)

**Beat model**:
The pure data behind a story: its beats in order, or for a scenario its paths, each beat holding one snapshot.
_Avoid_: Step model (the old name), script, storyboard

**Region**:
A fixed area of the scene that holds one kind of entity, such as the stack or the heap, or one cast member's copy of the system.
_Avoid_: Zone, panel, layer

**Entity**:
One thing drawn in a snapshot, such as a frame, an object or a commit, with an identity that stays the same from one snapshot to the next.
_Avoid_: Node, item, element

**Cell**:
An entity's fixed position within its region, the same in every view.
_Avoid_: Coordinate, grid position

**Step model**:
The pure data behind a story, one snapshot per beat, that every view renders.
_Avoid_: Script, storyboard
**Slot**:
A named place in an entity that holds either a value or a reference.
_Avoid_: Field, property, variable

**Reference**:
A link from a slot to another entity.
_Avoid_: Pointer, edge, arrow

**Focus**:
The entities and slots a beat or step spotlights. An author chooses a beat's focus; a step's focus is whatever that step changed.
_Avoid_: Highlight, selection

**View**:
One rendering of a step model: 2D (the default) or 3D. Switching views keeps the beat.
One way of drawing a snapshot: 2D (the default) or 3D. Switching views keeps the beat or step.
_Avoid_: Mode, renderer (for the user-facing concept)

**Shot**:
The part of the scene a beat is framed on: an overview, one region, or a bridge between regions.
A part of the scene that the author named and framed a beat on. An overview, one region and a bridge between regions are the common kinds. Steps have no shot.
_Avoid_: Camera angle, zoom level

**Scenario**:
Expand All @@ -40,10 +68,50 @@ _Avoid_: Branch (overloaded with Git), fork, decision
The linear run of beats that follows one option of a choice point.
_Avoid_: Branch, route, track

**Timeline**:
The clock times at which a scenario's cast acts, in order.
_Avoid_: Schedule; never the steps of a trace

**Transcript**:
The running log of a scenario: at each beat, who acted, when, the command they ran, and what it printed.
_Avoid_: Console, log, terminal
The running log of a scenario: at each beat, who acted, when, the command they ran or the action they took, and what it printed.
_Avoid_: Log, terminal, console (the Console belongs to the Playground)

**Hold view**:
The learner's choice to keep their own camera across beats instead of each beat's shot.
_Avoid_: Free camera, lock camera

## Playground

**Playground**:
The one place where a learner runs their own code and watches what it does to state. There is exactly one; no module has a playground of its own.
_Avoid_: Sandbox, editor, IDE, code lab

**Trace**:
The record of one run of the learner's code in the Playground: a sequence of steps. A trace is recorded, never authored or approved, so it is not a story.
_Avoid_: Story, timeline, recording, execution

**Step**:
One moment of a trace: the snapshot recorded when one statement ran, with the line that ran.
_Avoid_: Beat, snapshot (the snapshot is the state a step holds)

**Console**:
What the learner's code printed during a run, in order. It has no cast and no clock times, so it is not a transcript.
_Avoid_: Transcript, output, log

**Lens**:
The learner's choice of which part of a snapshot the Playground draws, such as the stack and heap or the stack and queues. A lens is independent of the view: any lens can be drawn in 2D or 3D.
_Avoid_: View, mode, visualization

**Example**:
Prebuilt code the learner can load into the Playground to run and watch, with a suggested lens and no goal.
_Avoid_: Snippet, template, scenario, demo

**Exercise**:
A task in the Playground with a goal, checks that pass or fail on the learner's code, and hints.
_Avoid_: Problem, challenge, kata, test

## Modules

**Marble diagram tool**:
The RxJS module's interactive diagram: the learner writes a stream as marbles, picks an operator and sees the stream it produces. It does not run the learner's code, so it is not a playground.
_Avoid_: RxJS playground, marble playground
51 changes: 51 additions & 0 deletions docs/RESEARCH/Playground Audit 2026-10.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
# Playground audit, October 2026

Findings from running `/playground` in a browser and reading `src/features/playground/` on 2026-10-11 (commit `51a0ecc`). This records what is true today. It is not a plan.

## State of the 3D work

- Three visualizations use the step model with a 2D view and a lazy 3D view: JavaScript "Stack ↔ Heap" (#168), Git "What is a branch, really?" (#170) and the Git "Ship a feature" scenario (#173). Shared viewer controls landed in #172.
- `docs/3D-Visualization-Standard.md` and ADR 0001 still say "Prototype" and gate rollout on the owner's sign-off, although Git has shipped two 3D views.
- The three 3D renderers (566, 834 and 1,047 lines) each redefine `PALETTE`, `damp`, `labelStyle`, `SHOTS`, `SCENE_BOUNDS` and `Scene`. The two Git renderers also duplicate `Label`, `CommitBlock`, `commitPos`, `parentArc` and the card constants.
- The canvas and 3D accessibility guides in the `modern-web-guidance` skill (#182) arrived after the 3D views and have not been applied to them.
- The standard's own follow-up is still open: replace the hand-authored Stack ↔ Heap story with traces from the playground's `JsInstrumenter`.

## What happened when I ran the playground

| Test | Result |
|---|---|
| Default JS snippet, Event Loop lens | 8 steps. Microtask and task queues are empty on every step. The `setTimeout` and `.then` callbacks are never stepped into. With an empty stack the header reads "Processing Task Queue". |
| Default JS snippet, console | The `setTimeout(…, 1000)` log never appears. |
| "Closures & Scope" example, Heap & Stack lens | 12 steps and no heap objects. At global scope the lens shows "No heap or stack data in current step". `increment()` is never entered and `count` never appears. |
| "Promise Chain" example (TypeScript) | Fails with `Unexpected token ':'`. No timeline. |
| Console output | Strings render as `"Hello, World!"`; the TypeScript error renders as `'`. |
| 1024px-wide viewport | The toolbar clips and the Run button is off screen. |

Not tested: Python (needs the Pyodide download), the Data Structures lens, the Streams lens, touch input, reduced motion.

## Causes in the code

- **Empty heap and queues.** The tracker runtime in `services/instrumentCode.ts` writes `heapObjects: []`, `microtaskQueue: []` and `macrotaskQueue: []` on every step. `instrumentation/PythonInstrumenter.ts` does the same. `HeapStackLens` and `EventLoopLens` read those fields, so they have nothing to draw.
- **No object identity.** `safeClone` deep-copies each value (depth 3, 20 keys) on every step. Two variables that point at one object become two unrelated copies, so a reference cannot be drawn.
- **Functions inside expressions are not traced.** `instrumentNode` only descends through statements. Arrow callbacks, object methods and function expressions get no `enterFunction`/`step` calls.
- **One flat variable list.** `collectScopeVars` captures the variables visible at the current statement. Frames below the top of the stack carry no variables.
- **Results are reported too early.** `SandboxFrame.tsx` posts the result 50 ms after the synchronous code ends, so later timers never reach the console or the timeline.
- **TypeScript is not transpiled.** `handleRun` in `PlaygroundApp.tsx` passes TypeScript source straight to acorn and the sandbox. A comment in `hooks/useSandbox.ts` says the code "should be transpiled before passing to execute".
- **Different vocabularies.** The story step model (`StoryStep`: frames with slots, `refId`, heap objects with stable cells and states, a camera shot) is richer than the playground's `StateSnapshot`. The two also both export a type named `StackFrame` with different shapes.
- **Different themes.** The playground is dark (`data-theme="playground"`); the stories and the 3D palette are light, and AGENTS.md says "Light mode only".
- **Different renderers.** Playground lenses use React Flow or plain DOM; stories use SVG and react-three-fiber.

## Other playgrounds in the repository

Reported by an explorer agent from reading the code; nothing here was run in a browser.

- **`src/components/playground/` (old).** A LeetCode-style shell (problem, tests, submit, score, debug stepper) that never runs the user's code: Run, Test and Submit are `setTimeout` mocks (`Playground.tsx:65-97`) and Submit always returns "accepted" with score 100. Its only real execution path (`utils/instrument.ts`, `new Function` on the main thread, no sandbox or timeout) is unreachable.
- Mounted by `features/bigo/BigOPage.tsx` and `features/datastructures/DataStructuresPage.tsx`, linked from `Sidebar.tsx`, `moduleNavigation.ts` and both modules' Introduction sections, and advertised in the README.
- Worth carrying over: the problem/test/hint schema (`types/playground.ts`), `data/problems.ts` (1,266 lines, imported by nothing), the `ProblemDisplay` and `TestRunner` UI, and the achievement logic in `utils/scoring.ts`.
- Dead: `PerformanceAnalyzer` and `hooks/usePlayground.ts` (never imported, fabricated numbers).
- `utils/instrument.ts` is also used by the JavaScript `CallStack.tsx` and `MemoryHeap.tsx`, so it cannot be deleted with the rest.
- **`src/components/rxjs/playground/`.** Mounted only in the RxJS Visualization Tool section. `MarblePlayground` works but simulates operators by pattern matching (`map`, `filter`, `take` only) rather than running RxJS. `CodePlayground` prints canned output.

## A limit to keep in mind

JavaScript cannot observe real garbage collection. A tracer can compute which objects became unreachable from the roots, which is what the Stack ↔ Heap story's tests already do, but it cannot show an actual sweep.
Loading
Loading