compw00ter — Build-Plan Tracker & Phased Roadmap
Date: 2026-07-04 Status: Design — approved, ready for implementation plan.
A host-facing project board built into the Hero Builder site: an interactive,
DB-backed tracker of the phased build plan that takes compw00ter from
"Hero Builder done" to "playable at the LAN party." Two deliverables in one:
the tracker page (plan.php) and the seeded phase content (the roadmap).
Why
The game is a large, multi-subsystem build (Node engine, w00t economy, incidents, player client, admin panel, bosses). We need a single place to see what's done, what's in flight, and what's next — and to manage it live as work moves. It lives on the site itself, alongside the other host tools (Heroes / Vocab / Workbench).
Decisions locked in brainstorming
- Page type: interactive DB-backed tracker (not static markdown, not kanban).
- Deadline: none fixed — phases are dependency-ordered, no countdown.
- Granularity: phases plus checkable tasks; phase progress = % tasks done.
- Database: the same
data/compw00ter.db, new tables (not a separate file). - Reordering: up/down buttons, not drag (matches progressive-enhancement style).
- Access: unauthenticated internal tool, same as the rest of the app.
Part A — The tracker
Data model
Two new tables in data/compw00ter.db, added idempotently to sql/schema.sql:
CREATE TABLE IF NOT EXISTS plan_phases (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
blurb TEXT NOT NULL DEFAULT '',
sort_order INTEGER NOT NULL DEFAULT 0,
created_at TEXT NOT NULL,
updated_at TEXT NOT NULL
);
CREATE TABLE IF NOT EXISTS plan_tasks (
id INTEGER PRIMARY KEY AUTOINCREMENT,
phase_id INTEGER NOT NULL REFERENCES plan_phases(id) ON DELETE CASCADE,
title TEXT NOT NULL,
note TEXT NOT NULL DEFAULT '',
status TEXT NOT NULL DEFAULT 'todo', -- todo | doing | done | blocked
sort_order INTEGER NOT NULL DEFAULT 0,
created_at TEXT NOT NULL,
updated_at TEXT NOT NULL
);
- The four statuses are a fixed enum defined in
includes/config.php(e.g.W00T_PLAN_STATUSES = ['todo', 'doing', 'done', 'blocked']), consistent with how the other enums live there. - Phase progress is computed, never stored —
done / totaltasks — so it can never drift from the underlying tasks. ON DELETE CASCADEcleans up tasks when a phase is deleted. (RequiresPRAGMA foreign_keys = ONper connection; set inDatabase.)
Files
Follows the existing Hero Builder shape exactly:
plan.php -- the board page (read + render)
plan_save.php -- POST action handler (CSRF-checked) for all writes
classes/PlanRepository.php -- all plan SQL, mirroring HeroRepository
includes/header.php -- add "Plan" to the nav
sql/schema.sql -- + plan_phases, plan_tasks (idempotent)
sql/seed.sql / seeder -- seed the initial phases + tasks on a fresh DB
PlanRepository exposes: allPhasesWithTasks(), addPhase(), addTask(),
updateTask(), setTaskStatus(), deleteTask(), deletePhase(),
movePhase(dir), moveTask(dir), and a phaseProgress() helper (or progress
computed inline from the loaded task list).
Page behaviour (plan.php)
- Renders each phase as a card: name, blurb, a progress bar (computed %),
and its tasks listed beneath, ordered by
sort_order. - Each task shows a status chip (todo / doing / done / blocked), its title, and an optional note.
- Uses the project palette from
assets/style.css; done tasks visually muted, blocked tasks flagged, doing tasks highlighted.
Interactions (all POST → plan_save.php, CSRF-checked)
Every write is POST with a CSRF token (csrf_field() / csrf_check() from
bootstrap.php), then redirects back to plan.php (PRG pattern), matching
hero_save.php.
| Action | action= |
Effect |
|---|---|---|
| Cycle task status | cycle_status |
todo → doing → done → blocked → todo |
| Add task | add_task |
new task in a phase |
| Edit task | edit_task |
change title / note |
| Delete task | delete_task |
remove one task |
| Add phase | add_phase |
new phase at end |
| Edit phase | edit_phase |
change name / blurb |
| Delete phase | delete_phase |
remove phase + its tasks (cascade) |
| Move phase | move_phase |
up / down (swap sort_order) |
| Move task | move_task |
up / down within its phase |
Progressive enhancement
Everything works JS-off as plain form submits with full-page round-trips
(status cycling is a one-button form per task; add-task is an inline form). A
later JS layer (in the spirit of assets/builder.js) may intercept these for
no-reload updates, but is not required for the page to be fully usable.
Access & security
- Same posture as the rest of the app: no auth (internal LAN-party host tool).
- SQL via prepared statements only; output escaped with
e(). - All state changes are POST + CSRF;
GET plan.phpis read-only.
Part B — The seeded roadmap
Dependency-ordered, no calendar. Seeded on a fresh DB. Phase 1 is seeded as done to reflect current reality. Fully editable afterwards — this is a starting skeleton, not a contract.
Phase 1 — Hero Builder & tooling (done)
- Hero/ability/trait CRUD — done
- Editable vocabularies (incident types, vice states, vices, meters) — done
- Design Workbench (
spec/) — done - Map grid editor (
map/) — done
Phase 2 — Content lock
Fill the data the engine will need before writing engine code.
- Complete the 10-hero roster, each with abilities + traits
- Seed the incident catalogue into the DB (from the incident-catalogue spec)
- Finalise meters and vices → vice-states
Phase 3 — Engine core (Node + WebSocket, port 6767)
- Boot the WS server on 6767
- Load the roster/content from
compw00ter.dbviabetter-sqlite3 - Client connect / identify / room model
- The round/tick loop — in-game hours as ~30s real rounds (game window + interlude)
Phase 4 — The w00t engine (attendance economy)
- The schedule/timetable (hourly activities, per-room requirements)
- Per-room quorum check during the game window
- w00t fills on attendance, drains on empty chairs
- Lose condition (w00t → 0 = collapse); score = party uptime
Phase 5 — Meters, traits & incidents
- Meter drain over time; refill at a source (move there)
- Traits fire at a meter extreme → reset meter, pull player off rig, spawn incident
- Incident HP model (clear by ability damage); tiers (blocker / puller / standard / supply)
- Abilities: fight / cleanse / provide; soft-counter, type-match ≈ 3×; escalation
Phase 6 — Player client
- The player's game screen: their meters, abilities, position, nearby incidents
- Movement between rooms / to sources
- Using abilities on incidents; targeting
Phase 7 — Live admin panel
- Privileged admin WS client showing live match state
- Timeline lane of director-scheduled incidents & bosses
- Trigger-now; inject an incident (type / location / severity)
- Drop a boss; fire a chosen player's trait manually
Phase 8 — Bosses & richer layers
- Named bosses: The Wife, The Martin
- The hero counter-web
- Team mini-games
Phase 9 — Playtest & tune
- Number tuning (meter/incident/w00t rates)
- Balance passes
- LAN dry-run
Testing
- Data layer: extend
tests/smoke.php(or a sibling) to exercisePlanRepository— create phase, add tasks, cycle status, compute progress, delete-cascades. - UI:
php -S 127.0.0.1:<port>, driveplan.php/plan_save.phpwith curl or Playwright (add task, cycle status, verify progress bar). - Always check the error log after PHP changes (
grep w00tthe shared log).
Out of scope (YAGNI)
- Auth / per-user boards — single shared board.
- Drag-and-drop reordering — up/down buttons only.
- Due dates, assignees, comments/history — status + note is enough.
- Any game-engine code — this is the tracker for it, not the engine.