Files
test01/docs/superpowers/plans/2026-03-17-conway-life-demo.md

6.5 KiB

Conway Life Demo Implementation Plan

For agentic workers: REQUIRED: Use superpowers:subagent-driven-development (if subagents available) or superpowers:executing-plans to implement this plan. Steps use checkbox (- [ ]) syntax for tracking.

Goal: Build a direct-open Conway's Game of Life demo page with a modern visualization style, preset patterns, canvas-based simulation, and a clean teaching-plus-exploration flow.

Architecture: Keep the page build-free and local-file friendly: semantic markup in index.html, visual styling in styles.css, and a single browser script in app.js. Put Conway engine logic and state helpers in testable pure functions exported from app.js, while the DOM/controller layer wires those functions to the canvas UI.

Tech Stack: HTML5, CSS3, vanilla JavaScript, Canvas API, Node.js built-in test runner (node --test)


Note: this workspace is not a git repository, so commit steps are intentionally omitted.

File Structure

  • Create: index.html - page structure, content sections, script/style includes
  • Create: styles.css - theme variables, layout, cards, control panel, responsive styling, animation polish
  • Create: app.js - Conway engine, preset definitions, state helpers, canvas rendering, UI events
  • Create: tests/life-demo.test.js - Node tests for pure simulation and state logic

Chunk 1: Build and test the Conway engine

Task 1: Create the failing engine tests

Files:

  • Create: tests/life-demo.test.js

  • Test: tests/life-demo.test.js

  • Step 1: Write the failing test

const test = require('node:test');
const assert = require('node:assert/strict');
const {
  createEmptyGrid,
  stepGrid,
  stampPattern,
  PATTERNS,
} = require('../app.js');

test('blinker rotates after one generation', () => {
  const grid = createEmptyGrid(5, 5);
  grid[2][1] = 1;
  grid[2][2] = 1;
  grid[2][3] = 1;

  const next = stepGrid(grid);

  assert.deepEqual(next[1], [0, 0, 1, 0, 0]);
});
  • Step 2: Run test to verify it fails

Run: node --test tests/life-demo.test.js Expected: FAIL because app.js or the exported functions do not exist yet.

  • Step 3: Write minimal implementation
function createEmptyGrid(rows, cols) {
  return Array.from({ length: rows }, () => Array(cols).fill(0));
}

Implement the smallest export set needed to pass:

  • createEmptyGrid(rows, cols)

  • countLiveNeighbors(grid, row, col)

  • stepGrid(grid)

  • stampPattern(grid, pattern, offsetRow, offsetCol)

  • PATTERNS for glider, pulsar, and gosperGliderGun

  • Step 4: Run test to verify it passes

Run: node --test tests/life-demo.test.js Expected: PASS for the engine tests.

Chunk 2: Add state helpers and page shell

Task 2: Add failing tests for state helpers

Files:

  • Modify: tests/life-demo.test.js

  • Modify: app.js

  • Create: index.html

  • Create: styles.css

  • Step 1: Write the failing test

Add tests for:

test('createInitialState seeds the default preset and starts paused', () => {
  const state = createInitialState({
    rows: 20,
    cols: 20,
    defaultPattern: 'pulsar',
  });

  assert.equal(state.running, false);
  assert.equal(state.selectedPattern, 'pulsar');
  assert.equal(state.generation, 0);
  assert.ok(state.liveCount > 0);
});
  • Step 2: Run test to verify it fails

Run: node --test tests/life-demo.test.js Expected: FAIL because createInitialState is not implemented yet.

  • Step 3: Write minimal implementation

Implement pure helpers:

  • cloneGrid(grid)
  • countLiveCells(grid)
  • createInitialState({ rows, cols, defaultPattern })
  • randomizeGrid(grid, probability)
  • toggleCell(grid, row, col, forcedValue)

At the same time, scaffold:

  • index.html with Hero, Lab, Rules, and Presets sections

  • styles.css with the modern visualization theme variables and responsive grid

  • Step 4: Run test to verify it passes

Run: node --test tests/life-demo.test.js Expected: PASS for the new state-helper tests.

Chunk 3: Wire controls, canvas rendering, and preset switching

Task 3: Add failing tests for UI-facing state transitions

Files:

  • Modify: tests/life-demo.test.js

  • Modify: app.js

  • Modify: index.html

  • Modify: styles.css

  • Step 1: Write the failing test

Add tests for:

test('applyPreset replaces the grid, pauses playback, and resets generation', () => {
  const state = {
    ...createInitialState({ rows: 25, cols: 25, defaultPattern: 'glider' }),
    running: true,
    generation: 12,
  };

  const next = applyPreset(state, 'gosperGliderGun');

  assert.equal(next.running, false);
  assert.equal(next.generation, 0);
  assert.equal(next.selectedPattern, 'gosperGliderGun');
  assert.ok(next.liveCount > state.liveCount);
});
  • Step 2: Run test to verify it fails

Run: node --test tests/life-demo.test.js Expected: FAIL because applyPreset is not implemented yet.

  • Step 3: Write minimal implementation

Implement:

  • applyPreset(state, patternName)
  • advanceState(state)
  • setSpeed(state, speed)
  • getSpeedLabel(speed)

Then wire browser behavior:

  • draw the grid on a canvas

  • support play/pause, step, clear, randomize, reset preset, and speed controls

  • support click and drag painting on the canvas

  • update status text, generation count, live-count, and active preset styling

  • Step 4: Run test to verify it passes

Run: node --test tests/life-demo.test.js Expected: PASS for the state-transition tests.

Chunk 4: Polish visual details and run end-to-end verification

Task 4: Finish presentation details and verify manually

Files:

  • Modify: index.html

  • Modify: styles.css

  • Modify: app.js

  • Test: tests/life-demo.test.js

  • Step 1: Refine the visuals

Complete:

  • luminous background gradients and grid accents

  • polished cards and control panel surfaces

  • hover/focus states

  • responsive stacking for smaller screens

  • subtle canvas/section entrance motion

  • Step 2: Run automated tests

Run: node --test tests/life-demo.test.js Expected: PASS with zero failures.

  • Step 3: Run manual verification

Open: index.html

Verify:

  • page opens directly without a dev server

  • pulsar loads by default and the simulation starts paused

  • controls behave correctly

  • each preset loads and pauses correctly

  • editing by click/drag works

  • desktop and narrow layouts both remain usable

  • Step 4: Record any gaps

If a browser-only issue appears, fix it and rerun:

  • node --test tests/life-demo.test.js
  • manual browser verification of index.html