Skip to content

docs: full-project audit + phased hardening fix plan - #25

Merged
ksdisch merged 1 commit into
mainfrom
claude/project-audit-plan-a47sjw
Jul 11, 2026
Merged

docs: full-project audit + phased hardening fix plan#25
ksdisch merged 1 commit into
mainfrom
claude/project-audit-plan-a47sjw

Conversation

@ksdisch

@ksdisch ksdisch commented Jul 9, 2026

Copy link
Copy Markdown
Owner

What & why

You asked for everything that needs fixing or improving, plus a plan to fix all of it. This PR adds docs/AUDIT-2026-07-09.md — a full-project audit with ~60 findings (each with file:line evidence and effort sizing) and a six-phase fix plan (~5–7 focused days), plus one BACKLOG Open item linking it.

How it was audited

Not just static reading — the highest-severity claims were reproduced live in this session:

  • ✅ typecheck · 156/156 tests · build all green
  • ✅ headless planet-1 clear via the ?test=1 bridge (win, unlock, schema-v2 telemetry, reload durability)
  • real two-client co-op round-trip over the live relay (room join → ice theme reaches the phone → genuine QuickMath solve → power-cast with solveMs → planet-complete → +3 stardust toast)
  • ⚠️ npm audit: 7 advisories (2 critical / 3 high), all fixable in-range
  • smoke:relay leaks an orphaned relay process and hangs piped callers (reproduced twice, root-caused)
  • ❌ the repo-pinned playwright MCP fails in cloud sessions (chrome channel absent — hit live)

Headline findings

  • P0 — relay crashes remotely: a 4-byte null frame kills the process (msg.type on null outside the try/catch); no ws 'error' listeners, so a routine cellular RST can also kill it.
  • P1 — the couch-playtest killers: neither client detects its own socket death (phone shows a false "Cast!" and mints stardust after a silent disconnect); no relay heartbeat, so a ghost phone permanently blocks the documented rejoin; scene handlers never unsubscribe → duplicate casts + corrupted M10 telemetry in co-op.
  • P1 — shipped features undermined: re-casting Freeze truncates the freeze window instead of extending it; every particle burst renders at (2×, 2×) — off-screen — so the whole M5 burst layer has been invisible (verified against Phaser 3.90 source; the bridge asserts metadata, not pixels, which is exactly why nothing caught it).
  • P1 — tooling: protocol-boundary-guard.sh emits "permissionDecision":"allow" and thereby auto-approves edits to the one file it exists to guard; ws@8.20.0 carries known DoS/memory-disclosure advisories.
  • P2 — docs actively mislead: README says "M2 — one power, one level" (M11 shipped); CLAUDE.md points at the deleted Level.ts; session-start.md says "M4 in flight… don't add automated tests yet" against 156 sanctioned tests; tsconfig never typechecks the test files.

Plus a "what's genuinely solid" section — the persistence layer, pure-logic layering, exhaustiveness engineering, and the allowlist relay design hold up well and the plan deliberately leaves them alone.

The plan (in the doc)

  1. Stop the bleeding — relay crash-proofing, npm audit fix, hook fix, smoke-relay orphan fix, MCP browser pin (~½ day)
  2. Make co-op survive real life — heartbeat, disconnect surfacing on both clients, handler-leak fixes, peer-disconnected protocol message, room-registry extraction + tests (1–2 days)
  3. Game-feel correctness — visible bursts, freeze token, post-win guard, win-card depth (~½–1 day)
  4. Docs tell the truth — README/CLAUDE.md/session-start/PROJECT_GUIDE banner (~½ day)
  5. Test & CI spine — typecheck the tests, hook fixes, engines field, minimal CI (decision) (~½–1 day)
  6. Phone hygiene — setState side-effect fix → StrictMode, 44px targets, puzzle-logic tests (~1 day)
  7. Deploy hardening — ride along with the actual public deploy (optional)

Each phase is independently shippable with a named verification gate. Six items need your decision (CI, Prettier, jump feel, solveMs semantics, PROJECT_GUIDE regen, Docker slim approach) — everything else can proceed without input. Coordination note: land or rebase around PR #23 (M12 generator spike) — phases 2/5 touch neighboring files.

🤖 Generated with Claude Code

https://claude.ai/code/session_01UEAWk5o1W73GYBS4ahvobK


Generated by Claude Code

Audit of main @ 5caa420 across game, phone, relay/protocol, deploy,
docs, and .claude tooling. All 156 tests / typecheck / build green and
a live two-client co-op round-trip passes — but the audit found:

- P0: two remotely triggerable relay process crashes (null frame,
  missing ws error listeners)
- P1: freeze re-cast truncates the freeze window; every particle burst
  renders off-screen (emitter-local coords passed twice); net-handler
  leaks that duplicate casts and corrupt M10 telemetry; both clients
  blind to their own socket death; no relay heartbeat (ghost phone
  blocks rejoin); protocol-guard hook auto-approves protocol edits;
  ws 8.20.0 known advisories; smoke:relay orphans its relay child and
  hangs piped callers; repo playwright MCP broken in cloud sessions
- P2/P3: post-win casts, win-card depth, README/CLAUDE.md/session-start
  drift (docs describe M2/M4 while M11 shipped), tests never
  typechecked, sub-44px touch targets, and ~30 more, each with
  file:line evidence

Fix plan: six independently shippable phases (relay crash-proofing →
co-op disconnect survival → game-feel fixes → docs truth pass → test/CI
spine → deploy hardening), with per-phase verification gates and the
six decisions that need the owner.

Adds one BACKLOG Open item linking the audit.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UEAWk5o1W73GYBS4ahvobK
@ksdisch
ksdisch marked this pull request as ready for review July 11, 2026 03:09
@ksdisch
ksdisch merged commit 4a6a925 into main Jul 11, 2026
@ksdisch
ksdisch deleted the claude/project-audit-plan-a47sjw branch July 29, 2026 01:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants