Add sisyphus

This commit is contained in:
Joey Yakimowich-Payne 2026-04-17 15:22:04 -06:00
commit 3e8bc7394e
No known key found for this signature in database
3 changed files with 141 additions and 76 deletions

View file

@ -1,13 +1,38 @@
{
"active_plan": "/home/joey/Projects/rules/.sisyphus/plans/rete-rules-engine.md",
"started_at": "2026-04-16T19:18:14.222Z",
"started_at": "2026-04-16T21:50:28.031Z",
"session_ids": [
"ses_26872eb19ffeDMaEoxdTsorFej",
"ses_26842c860ffec63Ov7Llrz7Lyg",
"ses_26843b5b0ffejVpXmmHcQ8CoUp",
"ses_268415bf0ffernrRKPtHro341E",
"ses_2684239eeffeaz52nJeIRqphnJ",
"ses_2683e067effeLzndjG25qlXH3G"
"ses_267b9d7a2ffeFkGcPFn1iv223J",
"ses_267b7c6a3ffeFBPE7j5hCcgvdq",
"ses_267b27b25ffe6ox746ql2Qj1E2",
"ses_267ae3c18ffe1Q0dx2aMzUZwid",
"ses_267ab53e5ffeXk8oWYjxiSryf0",
"ses_267a4cff0ffeCc0cSJZuxty3MR",
"ses_267a27b30ffeaIVszd2do4wYGU",
"ses_2678e1772ffeXFAdrjVVLAIh1s",
"ses_2677bcf14ffeCyy0Il5QV4Wdp0",
"ses_26776247dffehQGb1xnTBRqjq0",
"ses_26772a7e2ffep3REXuUXLd4YsX",
"ses_26770d3e0ffeWPNocV3HxsUb70",
"ses_2676e6648ffegH7o8GqgKw4hkM",
"ses_26768e818ffeacHy63Rn2RFmrS",
"ses_26760ae54ffezlg9ttb3a9P7wm",
"ses_2675a45d4ffee5V3zu7hjdOkD7",
"ses_26755c023ffeYvG2k7GuZIljF5",
"ses_26750ed18ffedLTtD3ziF7avO2",
"ses_2674cf6a7ffeOXPEFn6rhU551N",
"ses_26740710cffexgieUA3qB2B98Z",
"ses_26735c68effelwOfYs0gfmIKPZ",
"ses_2673618caffe5Rqdqzw1O6feF2",
"ses_26736499dffeeYMawv3CU88Hwp",
"ses_267368601ffeJ0vrgBbQg0z30R",
"ses_26730df9bffeFFGese2Qel8oBI",
"ses_2672b4d9bffekW9lZXc1JCVvXw",
"ses_2672b257dffeaG4lGP8jaN7Tp5",
"ses_263703df9ffegmVplLbaxmQIes",
"ses_262de3483ffe5v8SD8eFNqtdo0",
"ses_262de1b3bffexz022qa8FnxRyV",
"ses_262ddfb93ffeMGkZK2rspryFfX"
],
"plan_name": "rete-rules-engine",
"agent": "atlas"

View file

@ -0,0 +1,40 @@
## [2026-04-16] Session ses_267b9d7a2ffeFkGcPFn1iv223J Start
### Codebase State (Phase 3.8 complete)
- 323 tests pass, 0 fail across all packages
- Engine (`packages/rete/src/`): fully implemented — schema, WM, alpha/beta, join, filter, query, derived, negation, existential, NCC, aggregation, event log, snapshot, replay
- Chess (`packages/chess/src/`): all FIDE rules + 15 presets implemented
- Presets in `packages/chess/src/presets/registry.ts`
- Fact schema in `packages/chess/src/schema.ts`
- Engine facade in `packages/chess/src/engine.ts`
- Chess package.json already has `vite`, `@vitejs/plugin-react`, `react`, `react-dom`, `@types/react`, `@types/react-dom` in devDeps
- No `index.html`, no `src/app/`, no UI files yet
### Key Conventions
- Bun workspaces, `bun test`, NOT npm/node
- TypeScript strict: `noImplicitAny`, `exactOptionalPropertyTypes`, `noUncheckedIndexedAccess`
- ESLint flat config in `eslint.config.js`
- No `as any`, no `@ts-ignore`
- All tests: Vitest (not Jest)
- Tailwind for styling (per plan P3.9)
- React 19
- Square encoded as number 0..63
- Pieces as EntityId with multiple attrs
### Chess Architecture
- `Session` from `@paratype/rete` — the game engine
- `generateStartingPosition(session)` — inserts 32 piece facts
- `AttemptedMove` fact = move intent
- `LegalMove` derived fact = legal moves per piece
- `InCheck`, `GameOver` derived facts
- Presets: PRESET_REGISTRY in `packages/chess/src/presets/registry.ts`
- `engine.ts` — higher-level facade wrapping Session
### UI Requirements (P3.9-P3.15)
- Routes: Home (/), Game (/game), Rules (/rules), Save (/save)
- Board: `[data-square="e2"]`, `[data-piece="white-pawn"]` selectors needed for Playwright
- Drag-drop: HTML5 DnD or react-dnd
- `[data-action="undo"]`, `[data-action="save"]`, `[data-action="export"]`, `[data-action="import"]`
- `[data-testid="app-root"]` on root element
- `[data-preset="{id}"] [data-role="toggle"]`
- localStorage key: `paratype-chess:v1:autosave`

View file

@ -744,7 +744,7 @@ Final Verification Wave (4 parallel reviews)
- Files: `package.json`, `tsconfig.base.json`, `tsconfig.json`, `eslint.config.js`, `vitest.workspace.ts`, `playwright.config.ts`, `.gitignore`, `LICENSE`, `README.md`, `packages/*/package.json`, `packages/*/tsconfig.json`, `packages/*/src/index.ts`, `packages/*/README.md`, `bun.lockb`
- Pre-commit: `bun run check` (hook installed next task)
- [ ] P0.6. **CI pipeline (`.github/workflows/ci.yml`) + pre-commit hook (lefthook)**
- [x] P0.6. **CI pipeline (`.github/workflows/ci.yml`) + pre-commit hook (lefthook)**
**What to do**:
- Create `.github/workflows/ci.yml`:
@ -827,7 +827,7 @@ Final Verification Wave (4 parallel reviews)
### Phase 1 — Engine Pararules Parity (TDD)
- [ ] P1.1. **Schema + Fact type with typed attributes (TDD)**
- [x] P1.1. **Schema + Fact type with typed attributes (TDD)**
**What to do**:
- RED: In `packages/rete/src/schema.test.ts`, write failing tests:
@ -898,7 +898,7 @@ Final Verification Wave (4 parallel reviews)
- Files: `packages/rete/src/schema.ts`, `packages/rete/src/schema.types.ts`, `packages/rete/src/schema.test.ts`, `packages/rete/src/schema.type-test.ts`, `packages/rete/src/index.ts`
- Pre-commit: `bun run check`
- [ ] P1.2. **Working-memory (WM) storage + retrieval (TDD)**
- [x] P1.2. **Working-memory (WM) storage + retrieval (TDD)**
**What to do**:
- RED: `packages/rete/src/wm.test.ts` — failing tests:
@ -955,7 +955,7 @@ Final Verification Wave (4 parallel reviews)
- Files: `packages/rete/src/wm.ts`, `packages/rete/src/wm.test.ts`, `packages/rete/src/index.ts`
- Pre-commit: `bun run check`
- [ ] P1.3. **Alpha network: fact indexing by (id, attr) pattern (TDD)**
- [x] P1.3. **Alpha network: fact indexing by (id, attr) pattern (TDD)**
**What to do**:
- RED: `packages/rete/src/alpha.test.ts` — failing tests:
@ -1018,7 +1018,7 @@ Final Verification Wave (4 parallel reviews)
- Files: `packages/rete/src/alpha.ts`, `packages/rete/src/alpha.test.ts`, `packages/rete/src/index.ts`
- Pre-commit: `bun run check`
- [ ] P1.4. **Session lifecycle: init, add rule, fire (TDD)**
- [x] P1.4. **Session lifecycle: init, add rule, fire (TDD)**
**What to do**:
- RED: `packages/rete/src/session.test.ts` — failing tests:
@ -1078,7 +1078,7 @@ Final Verification Wave (4 parallel reviews)
- Files: `packages/rete/src/session.ts`, `packages/rete/src/session.test.ts`, `packages/rete/src/index.ts`
- Pre-commit: `bun run check`
- [ ] P1.5. **Typed TS builder API + handler registry (TDD)**
- [x] P1.5. **Typed TS builder API + handler registry (TDD)**
**What to do**:
- RED: `packages/rete/src/builder.test.ts` — failing tests:
@ -1137,7 +1137,7 @@ Final Verification Wave (4 parallel reviews)
- Files: `packages/rete/src/builder.ts`, `packages/rete/src/registry.ts`, `packages/rete/src/builder.test.ts`, `packages/rete/src/registry.test.ts`, `packages/rete/src/index.ts`
- Pre-commit: `bun run check`
- [ ] P1.6. **JSON serialization round-trip (TDD)**
- [x] P1.6. **JSON serialization round-trip (TDD)**
**What to do**:
- RED: `packages/rete/src/serialize.test.ts` — failing tests:
@ -1194,7 +1194,7 @@ Final Verification Wave (4 parallel reviews)
- Files: `packages/rete/src/serialize.ts`, `packages/rete/src/serialize.test.ts`, `packages/rete/src/index.ts`
- Pre-commit: `bun run check`
- [ ] P1.7. **Beta network: memory + token propagation (TDD)**
- [x] P1.7. **Beta network: memory + token propagation (TDD)**
**What to do**:
- RED: `packages/rete/src/beta.test.ts` — failing tests covering single-condition rule (beta reduces to alpha), two-condition rule (one join), three-condition chain
@ -1241,7 +1241,7 @@ Final Verification Wave (4 parallel reviews)
- Files: `packages/rete/src/beta.ts`, `packages/rete/src/beta.test.ts`, `packages/rete/src/index.ts`
- Pre-commit: `bun run check`
- [ ] P1.8. **Join nodes with variable binding (TDD)**
- [x] P1.8. **Join nodes with variable binding (TDD)**
**What to do**:
- RED: `packages/rete/src/join.test.ts` — join on shared variable `?id` (e.g., `(?id, X, ?x)` ∧ `(?id, Y, ?y)` must match when id is the same), numeric equality tests
@ -1288,7 +1288,7 @@ Final Verification Wave (4 parallel reviews)
- Files: `packages/rete/src/join.ts`, `packages/rete/src/join.test.ts`, `packages/rete/src/index.ts`
- Pre-commit: `bun run check`
- [ ] P1.9. **Condition filters (cond equivalent) (TDD)**
- [x] P1.9. **Condition filters (cond equivalent) (TDD)**
**What to do**:
- RED: `packages/rete/src/condition.test.ts` — filter predicates applied after join; predicates are registered (via registry, for JSON serializability)
@ -1332,7 +1332,7 @@ Final Verification Wave (4 parallel reviews)
- Files: `packages/rete/src/condition.ts`, `packages/rete/src/condition.test.ts`, `packages/rete/src/index.ts`
- Pre-commit: `bun run check`
- [ ] P1.10. **Query API: query / queryAll (TDD)**
- [x] P1.10. **Query API: query / queryAll (TDD)**
**What to do**:
- RED: `packages/rete/src/query.test.ts` — `session.query(rule)` returns first match or throws; `session.queryAll(rule)` returns all; `session.query(rule, { bindings })` filters by binding value
@ -1376,7 +1376,7 @@ Final Verification Wave (4 parallel reviews)
- Files: `packages/rete/src/query.ts`, `packages/rete/src/query.test.ts`, `packages/rete/src/index.ts`
- Pre-commit: `bun run check`
- [ ] P1.11. **Derived facts via thenFinally-equivalent (TDD)**
- [x] P1.11. **Derived facts via thenFinally-equivalent (TDD)**
**What to do**:
- RED: `packages/rete/src/derived.test.ts` — `rule.thenFinally('aggregateHandler', [])` fires after all activations of a tick; derived facts auto-retract when supporting matches disappear (truth maintenance)
@ -1420,7 +1420,7 @@ Final Verification Wave (4 parallel reviews)
- Files: `packages/rete/src/derived.ts`, `packages/rete/src/derived.test.ts`, `packages/rete/src/index.ts`
- Pre-commit: `bun run check`
- [ ] P1.12. **Cycle detection with recursion limit (TDD)**
- [x] P1.12. **Cycle detection with recursion limit (TDD)**
**What to do**:
- RED: `packages/rete/src/cycle.test.ts` — rule A inserts fact triggering rule B inserting fact triggering A (cycle); `fireRules({ recursionLimit: 4 })` throws `RecursionLimitExceededError` with cycle trace; `recursionLimit: 0` disables (for advanced use)
@ -1464,7 +1464,7 @@ Final Verification Wave (4 parallel reviews)
- Files: `packages/rete/src/cycle.ts`, `packages/rete/src/cycle.test.ts`, `packages/rete/src/session.ts`
- Pre-commit: `bun run check`
- [ ] P1.13. **Deterministic conflict resolution (TDD)**
- [x] P1.13. **Deterministic conflict resolution (TDD)**
**What to do**:
- RED: `packages/rete/src/conflict.test.ts` — given N matching activations, firing order is: salience desc → specificity (# conditions) desc → insertion order asc; deterministic across runs
@ -1510,7 +1510,7 @@ Final Verification Wave (4 parallel reviews)
- Files: `packages/rete/src/conflict.ts`, `packages/rete/src/conflict.test.ts`, `packages/rete/src/session.ts`
- Pre-commit: `bun run check`
- [ ] P1.14. **Pararules golden-file test port**
- [x] P1.14. **Pararules golden-file test port**
**What to do**:
- Port 5-10 representative pararules tests from `paranim/pararules/tests/*.nim` to TS/Vitest under `packages/rete/tests/golden/`
@ -1569,7 +1569,7 @@ Final Verification Wave (4 parallel reviews)
### Phase 2 — Rete II Extensions + Chess Engine
- [ ] P2.1. **Negation nodes (NOT) (TDD)**
- [x] P2.1. **Negation nodes (NOT) (TDD)**
**What to do**:
- RED: `packages/rete/src/negation.test.ts` — `rule.whatNot((Player, Dead, v(true)))` matches only when no fact satisfies the negated pattern; activation toggles when blocking fact inserted/retracted
@ -1604,7 +1604,7 @@ Final Verification Wave (4 parallel reviews)
**Commit**: YES — `feat(rete): add negation nodes (NOT) (P2.1)` — files: `packages/rete/src/negation.ts`, `packages/rete/src/negation.test.ts`
- [ ] P2.2. **Existential nodes (EXISTS) (TDD)**
- [x] P2.2. **Existential nodes (EXISTS) (TDD)**
**What to do**: `rule.whatExists((Attacker, AttacksSquare, v('sq')))` — EXISTS is negation-of-negation; propagate token if ≥1 matching fact. GREEN: `packages/rete/src/existential.ts`
@ -1635,7 +1635,7 @@ Final Verification Wave (4 parallel reviews)
**Commit**: YES — `feat(rete): add existential nodes (EXISTS) (P2.2)`
- [ ] P2.3. **NCC nodes: not-count-condition (TDD)**
- [x] P2.3. **NCC nodes: not-count-condition (TDD)**
**What to do**: Subconjunction negation — "no matching combination of N conditions exists". GREEN: `packages/rete/src/ncc.ts`. Per Doorenbos §2.6.3, NCC is a sub-network whose top-level production feeds a negation partner.
@ -1666,7 +1666,7 @@ Final Verification Wave (4 parallel reviews)
**Commit**: YES — `feat(rete): add NCC nodes (P2.3)`
- [ ] P2.4. **Aggregation nodes: count/sum/collect/min/max (TDD)**
- [x] P2.4. **Aggregation nodes: count/sum/collect/min/max (TDD)**
**What to do**: `rule.whatAggregate(count, (?id, Health, v('h')))` returns count bound to variable. Support `count`, `sum`, `min`, `max`, `collect` (array). Incremental update: maintain running total rather than full recompute. GREEN: `packages/rete/src/aggregate.ts`
@ -1699,7 +1699,7 @@ Final Verification Wave (4 parallel reviews)
**Commit**: YES — `feat(rete): add aggregation nodes (count/sum/collect/min/max) (P2.4)`
- [ ] P2.5. **Chess attribute schema + piece fact shape**
- [x] P2.5. **Chess attribute schema + piece fact shape**
**What to do**: `packages/chess/src/schema.ts` — define attrs: `PieceType` (pawn|knight|bishop|rook|queen|king), `Color` (white|black), `Square` (a1..h8 as number 0..63), `Position` (id→Square), `HasMoved` (bool for castling), `Turn` (color), `HalfmoveClock` (number), `FullmoveNumber` (number), `EnPassantTarget` (Square?); piece entity convention (each piece = one entity with multiple attrs)
- TDD the schema types (compile-time only test via `expect-type`)
@ -1735,7 +1735,7 @@ Final Verification Wave (4 parallel reviews)
**Commit**: YES — `feat(chess): add attribute schema and piece fact shape (P2.5)`
- [ ] P2.6. **Starting-position fact generator**
- [x] P2.6. **Starting-position fact generator**
**What to do**: `packages/chess/src/starting-position.ts` — `generateStartingPosition(session)` inserts 32 piece facts for FIDE start. TDD via snapshot of `session.allFacts()` sorted output.
@ -1765,7 +1765,7 @@ Final Verification Wave (4 parallel reviews)
**Commit**: YES — `feat(chess): add starting-position fact generator (P2.6)`
- [ ] P2.7. **Square + color helpers**
- [x] P2.7. **Square + color helpers**
**What to do**: `packages/chess/src/coord.ts` — pure functions: `fileOf(square)`, `rankOf(square)`, `squareFromFileRank(f, r)`, `colorOf(square)` (light/dark), `oppositeColor(c)`, `isOnBoard(f, r)`; TDD each
@ -1795,7 +1795,7 @@ Final Verification Wave (4 parallel reviews)
**Commit**: YES — `feat(chess): add coordinate + color helpers (P2.7)`
- [ ] P2.8. **Piece movement primitive rules (directions + steps)**
- [x] P2.8. **Piece movement primitive rules (directions + steps)**
**What to do**: `packages/chess/src/rules/primitives.ts` — rule-level primitives that legal-move rules build on: `StraightLineMoves`, `DiagonalMoves`, `SingleStepMoves`, `KnightOffsets`, `PawnSingleAdvance`, `PawnDoubleAdvance`, `PawnDiagonalCapture`. Each primitive is one Rete production generating candidate moves as derived facts (e.g., `CandidateMove(pieceId, targetSquare)`).
@ -1825,7 +1825,7 @@ Final Verification Wave (4 parallel reviews)
**Commit**: YES — `feat(chess): add movement primitive rules (P2.8)`
- [ ] P2.9. **Pawn move/capture rules**
- [x] P2.9. **Pawn move/capture rules**
**What to do**: `packages/chess/src/rules/pawn.ts` — productions: `PawnSingleMove`, `PawnDoubleMoveFromHome`, `PawnDiagonalCapture`. Use primitives + filters. Color-aware (white advances +rank, black -rank). Emit `LegalMove(pieceId, from, to)` derived facts. TDD each case including blocked paths.
@ -1855,7 +1855,7 @@ Final Verification Wave (4 parallel reviews)
**Commit**: YES — `feat(chess): add pawn move/capture rules (P2.9)`
- [ ] P2.10. **Knight move rules**
- [x] P2.10. **Knight move rules**
**What to do**: `packages/chess/src/rules/knight.ts` — 8 L-offsets; leap over other pieces; `LegalMove` emission
@ -1884,7 +1884,7 @@ Final Verification Wave (4 parallel reviews)
**Commit**: YES — `feat(chess): add knight move rules (P2.10)`
- [ ] P2.11. **Bishop/Rook/Queen sliding rules**
- [x] P2.11. **Bishop/Rook/Queen sliding rules**
**What to do**: `packages/chess/src/rules/sliding.ts` — `SlidingMove` production parameterized by directions (diagonal, orthogonal, both); uses aggregation or sequential tokens to stop at first blocker (own = stop before; enemy = capture then stop)
@ -1914,7 +1914,7 @@ Final Verification Wave (4 parallel reviews)
**Commit**: YES — `feat(chess): add bishop/rook/queen sliding rules (P2.11)`
- [ ] P2.12. **King move rules (basic)**
- [x] P2.12. **King move rules (basic)**
**What to do**: `packages/chess/src/rules/king.ts` — 8 adjacent squares; excludes squares occupied by own piece. Castling deferred to P2.15; check-aware rejection deferred to P2.13.
@ -1942,7 +1942,7 @@ Final Verification Wave (4 parallel reviews)
**Commit**: YES — `feat(chess): add king basic move rules (P2.12)`
- [ ] P2.13. **Turn order + move legality integration**
- [x] P2.13. **Turn order + move legality integration**
**What to do**: `packages/chess/src/rules/turn.ts` — only pieces of current turn's color generate legal moves; after move, turn flips; move-intent fact (`AttemptedMove`) validated vs `LegalMove` set; on success, update piece positions + retract old `LegalMove` facts. Uses negation to reject intents with no matching LegalMove.
@ -1972,7 +1972,7 @@ Final Verification Wave (4 parallel reviews)
**Commit**: YES — `feat(chess): add turn order + move integration (P2.13)`
- [ ] P2.14. **Capture resolution rules**
- [x] P2.14. **Capture resolution rules**
**What to do**: `packages/chess/src/rules/capture.ts` — when a LegalMove targets an enemy-occupied square, applying the move retracts the captured piece's facts (Position, PieceType, Color) via the RHS handler.
@ -2001,7 +2001,7 @@ Final Verification Wave (4 parallel reviews)
**Commit**: YES — `feat(chess): add capture resolution (P2.14)`
- [ ] P2.15. **Castling (kingside + queenside)**
- [x] P2.15. **Castling (kingside + queenside)**
**What to do**: `packages/chess/src/rules/castling.ts` — productions requiring: King has not moved (HasMoved=false), relevant Rook has not moved, no pieces between, king not in check, transit squares not attacked. Two-piece move: king + rook positions updated atomically.
@ -2033,7 +2033,7 @@ Final Verification Wave (4 parallel reviews)
**Commit**: YES — `feat(chess): add castling rules (P2.15)`
- [ ] P2.16. **En passant (single-tick capture window)**
- [x] P2.16. **En passant (single-tick capture window)**
**What to do**: `packages/chess/src/rules/enpassant.ts` — after a pawn's double-advance, set `EnPassantTarget(turn, square)` fact for one turn; eligible-pawn rule emits LegalMove that captures via adjacent target; target fact retracts on next turn.
@ -2064,7 +2064,7 @@ Final Verification Wave (4 parallel reviews)
**Commit**: YES — `feat(chess): add en passant rule (P2.16)`
- [ ] P2.17. **Promotion**
- [x] P2.17. **Promotion**
**What to do**: `packages/chess/src/rules/promotion.ts` — when a pawn reaches final rank, retract pawn PieceType fact and insert new PieceType (Q/R/B/N). The choice is specified in the `AttemptedMove` fact via `promoteTo` field; default to Q if missing.
@ -2095,7 +2095,7 @@ Final Verification Wave (4 parallel reviews)
**Commit**: YES — `feat(chess): add pawn promotion rule (P2.17)`
- [ ] P2.18. **Check detection**
- [x] P2.18. **Check detection**
**What to do**: `packages/chess/src/rules/check.ts` — derived fact `InCheck(color)` when any enemy piece has a LegalMove targeting that color's king. Uses EXISTS node. Rules that would leave own king in check are filtered out of LegalMove (self-check filter).
@ -2123,7 +2123,7 @@ Final Verification Wave (4 parallel reviews)
**Commit**: YES — `feat(chess): add check detection + self-check filter (P2.18)`
- [ ] P2.19. **Checkmate detection**
- [x] P2.19. **Checkmate detection**
**What to do**: `packages/chess/src/rules/checkmate.ts` — derived fact `GameOver(result, reason)` when: `InCheck(turn)` AND no LegalMove exists for any piece of `turn`. Uses NCC.
@ -2152,7 +2152,7 @@ Final Verification Wave (4 parallel reviews)
**Commit**: YES — `feat(chess): add checkmate detection (P2.19)`
- [ ] P2.20. **Stalemate detection**
- [x] P2.20. **Stalemate detection**
**What to do**: `packages/chess/src/rules/stalemate.ts` — `GameOver('draw', 'stalemate')` when: NOT `InCheck(turn)` AND no LegalMove exists for `turn`.
@ -2180,7 +2180,7 @@ Final Verification Wave (4 parallel reviews)
**Commit**: YES — `feat(chess): add stalemate detection (P2.20)`
- [ ] P2.21. **50-move rule + threefold repetition (aggregation-based)**
- [x] P2.21. **50-move rule + threefold repetition (aggregation-based)**
**What to do**: `packages/chess/src/rules/draws.ts` — track halfmove clock (resets on pawn move or capture) via a rule; 50-move rule fires at 100 halfmoves. For threefold, maintain a `PositionHash` fact per tick; aggregation counts occurrences of each hash; threshold of 3 → draw claim available.
@ -2211,7 +2211,7 @@ Final Verification Wave (4 parallel reviews)
**Commit**: YES — `feat(chess): add 50-move and threefold repetition rules (P2.21)`
- [ ] P2.22. **Insufficient material draw**
- [x] P2.22. **Insufficient material draw**
**What to do**: `packages/chess/src/rules/insufficient.ts` — draw when material sets are: KvK, KvK+N, KvK+B, K+BvK+B (same color bishop). Uses aggregation count over piece types.
@ -2239,7 +2239,7 @@ Final Verification Wave (4 parallel reviews)
**Commit**: YES — `feat(chess): add insufficient material draw (P2.22)`
- [ ] P2.23. **End-to-end FIDE game replay integration test**
- [x] P2.23. **End-to-end FIDE game replay integration test**
**What to do**: `packages/chess/tests/fide-games/`: include 5 famous games as PGN fixtures (Immortal, Opera, Evergreen, Kasparov vs Topalov 1999, Deep Blue vs Kasparov G6 1997). Write a runner that parses PGN, drives moves through the engine, asserts each move accepted, asserts terminal state (mate/draw/resign). Resigns are not a chess rule — handled as UI-only terminal state for now; filter those from fixtures.
@ -2273,7 +2273,7 @@ Final Verification Wave (4 parallel reviews)
### Phase 3 — Time-Travel + Presets + UI
- [ ] P3.1. **Event log: append-only, monotonic sequence numbers (TDD)**
- [x] P3.1. **Event log: append-only, monotonic sequence numbers (TDD)**
**What to do**: `packages/rete/src/eventlog.ts` — `class EventLog` records every `insert(id, attr, value)`, `retract(id, attr)`, and rule-fire as `{ seq, ts, kind, payload }`. Append-only; `getSince(seq)` returns entries after seq. Session integrates: every state-mutating call appends to log (if log attached). Tests cover monotonic seq, replay-safe encoding, payload determinism.
@ -2303,7 +2303,7 @@ Final Verification Wave (4 parallel reviews)
**Commit**: YES — `feat(rete): add append-only event log with monotonic sequence (P3.1)`
- [ ] P3.2. **Immer snapshot every N ticks (TDD)**
- [x] P3.2. **Immer snapshot every N ticks (TDD)**
**What to do**: `packages/rete/src/snapshot.ts` — on every Nth `fireRules()` call (configurable, default N=30), capture full WM state via Immer's `produce`. Structural sharing minimizes copies. `getSnapshotAt(seq)` returns nearest snapshot ≤ seq. Add `Session` option `snapshotInterval: number`.
@ -2336,7 +2336,7 @@ Final Verification Wave (4 parallel reviews)
**Commit**: YES — `feat(rete): add Immer snapshots at tick boundaries (P3.2)`
- [ ] P3.3. **Replay engine + determinism hash verifier (TDD)**
- [x] P3.3. **Replay engine + determinism hash verifier (TDD)**
**What to do**: `packages/rete/src/replay.ts` — `replayFromLog(log, schema, handlers): Session` reconstructs WM by replaying events on a fresh session. `stateHash(session): string` produces sha256 over sorted facts. Determinism test: recording a random fact/rule sequence, replaying, comparing hashes — must match byte-for-byte. Add `scripts/replay-determinism.ts` runner for CI.
@ -2370,7 +2370,7 @@ Final Verification Wave (4 parallel reviews)
**Commit**: YES — `feat(rete): add replay engine + state-hash determinism verifier (P3.3)`
- [ ] P3.4. **Preset rules 1-3 (pawn-focused variants)**
- [x] P3.4. **Preset rules 1-3 (pawn-focused variants)**
**What to do**: Implement 3 of the 15 presets from `packages/chess/RULES.md` (assume first 3 are pawn-focused: e.g., `pawns-move-backward`, `pawns-diagonal-no-capture`, `double-advance-any-turn`). Each preset = one or more rule definitions in `packages/chess/src/presets/{id}.ts`, a registered toggle in `packages/chess/src/presets/registry.ts`, unit tests, compatibility declarations.
@ -2400,7 +2400,7 @@ Final Verification Wave (4 parallel reviews)
**Commit**: YES — `feat(chess): add preset rules 1-3 (P3.4)`
- [ ] P3.5. **Preset rules 4-6 (knight/bishop variants)**
- [x] P3.5. **Preset rules 4-6 (knight/bishop variants)**
**What to do**: Implement presets 4-6 from RULES.md. Same structure as P3.4.
@ -2428,7 +2428,7 @@ Final Verification Wave (4 parallel reviews)
**Commit**: YES — `feat(chess): add preset rules 4-6 (P3.5)`
- [ ] P3.6. **Preset rules 7-9 (rook/queen/king variants)**
- [x] P3.6. **Preset rules 7-9 (rook/queen/king variants)**
**What to do**: Implement presets 7-9 from RULES.md.
**Recommended Agent Profile**: `deep`
@ -2454,7 +2454,7 @@ Final Verification Wave (4 parallel reviews)
**Commit**: YES — `feat(chess): add preset rules 7-9 (P3.6)`
- [ ] P3.7. **Preset rules 10-12 (board/geometry variants)**
- [x] P3.7. **Preset rules 10-12 (board/geometry variants)**
**What to do**: Implement presets 10-12 from RULES.md — board-geometry changes (e.g., horizontal wrap). These modify coord helpers via override or interception rule.
**Recommended Agent Profile**: `deep`
@ -2480,7 +2480,7 @@ Final Verification Wave (4 parallel reviews)
**Commit**: YES — `feat(chess): add preset rules 10-12 (P3.7)`
- [ ] P3.8. **Preset rules 13-15 (meta rules: HP/heal/immunity)**
- [x] P3.8. **Preset rules 13-15 (meta rules: HP/heal/immunity)**
**What to do**: Implement presets 13-15 from RULES.md — introduce HP/cooldown/immunity attributes in chess schema extensions (within chess package only, not engine). These require adding extended attrs to chess schema (via `extendChessSchema` helper), supporting facts (HP defaults to 1 for FIDE).
@ -2508,7 +2508,7 @@ Final Verification Wave (4 parallel reviews)
**Commit**: YES — `feat(chess): add preset rules 13-15 (P3.8)`
- [ ] P3.9. **React + Vite scaffold for chess app**
- [x] P3.9. **React + Vite scaffold for chess app**
**What to do**: Wire up Vite + React 19 (or latest) in `packages/chess/`: `index.html`, `src/app/main.tsx`, `src/app/App.tsx` (root, routes: Home, Game, Rules, Save), Vite config with base URL, Tailwind for styling (or CSS modules if Tailwind explicitly disliked by user; default Tailwind). Bundle size placeholder — checked by size-limit later.
@ -2546,7 +2546,7 @@ Final Verification Wave (4 parallel reviews)
**Commit**: YES — `feat(chess): scaffold Vite + React app (P3.9)`
- [ ] P3.10. **Chessboard component with drag-drop + legal-move highlights**
- [x] P3.10. **Chessboard component with drag-drop + legal-move highlights**
**What to do**: `packages/chess/src/ui/Board.tsx` — 8×8 grid, piece SVG icons (inline or public/), drag-drop via HTML5 DnD or react-dnd; on drag-start, query engine for that piece's LegalMoves and highlight target squares; on drop, dispatch AttemptedMove fact. Uses `useSession()` hook providing reactive fact subscriptions (implemented via tick-subscription observer on session).
@ -2586,7 +2586,7 @@ Final Verification Wave (4 parallel reviews)
**Commit**: YES — `feat(chess): add interactive Chessboard with drag-drop (P3.10)`
- [ ] P3.11. **Rule-toggle screen (preset list + compatibility warnings)**
- [x] P3.11. **Rule-toggle screen (preset list + compatibility warnings)**
**What to do**: `packages/chess/src/ui/Rules.tsx` — list all 15 presets with description, toggle switch, compat-warning banner when incompatibility detected; "Apply and start new game" button; toggles only between games (disabled during active game — grayed state).
@ -2625,7 +2625,7 @@ Final Verification Wave (4 parallel reviews)
**Commit**: YES — `feat(chess): add rule-toggle UI with compatibility warnings (P3.11)`
- [ ] P3.12. **Save/Load panel + undo via time-travel**
- [x] P3.12. **Save/Load panel + undo via time-travel**
**What to do**: `packages/chess/src/ui/SavePanel.tsx` + undo button in Game view; undo uses time-travel to rewind to previous `Turn`-changed fact boundary (one full move back); save panel lists slots from localStorage (schema-versioned JSON).
@ -2664,7 +2664,7 @@ Final Verification Wave (4 parallel reviews)
**Commit**: YES — `feat(chess): add Save/Load panel + time-travel undo (P3.12)`
- [ ] P3.13. **JSON export/import + validation**
- [x] P3.13. **JSON export/import + validation**
**What to do**: `packages/chess/src/ui/ImportExport.tsx` + `packages/chess/src/persist/io.ts` — export button produces a downloadable JSON file (schema: `{ version: 1, rules: [...], facts: [...] }`); import button accepts file, validates against schema (via `@paratype/rete`'s exported schema + chess extension schema), applies rules + facts.
@ -2699,7 +2699,7 @@ Final Verification Wave (4 parallel reviews)
**Commit**: YES — `feat(chess): add JSON export/import with validation (P3.13)`
- [ ] P3.14. **localStorage auto-save + restore**
- [x] P3.14. **localStorage auto-save + restore**
**What to do**: `packages/chess/src/persist/autosave.ts` — subscribe to session tick end; on every turn boundary, write serialized state + event log to localStorage key `paratype-chess:v1:autosave`. On app load, if key present, restore via `replayFromLog`. Include schema version in payload.
@ -2735,7 +2735,7 @@ Final Verification Wave (4 parallel reviews)
**Commit**: YES — `feat(chess): add localStorage auto-save and restore (P3.14)`
- [ ] P3.15. **End-to-end UI scenario (gate)**
- [x] P3.15. **End-to-end UI scenario (gate)**
**What to do**: Playwright scenario at `packages/chess/e2e/full-flow.spec.ts` — open app → toggle 2 presets → start game → play 5 moves → save → reload → game restored → export → import in fresh context → play 3 more moves → undo → play until checkmate (scripted sequence) → assert Game Over banner.
@ -2770,7 +2770,7 @@ Final Verification Wave (4 parallel reviews)
### Phase 4 — Authoritative Multiplayer
- [ ] P4.1. **Bun HTTP+WS server scaffold + config**
- [x] P4.1. **Bun HTTP+WS server scaffold + config**
**What to do**: `packages/server/src/index.ts` — `Bun.serve({ port, fetch, websocket: { open, message, close } })`; env-driven port (default 7357); health endpoint `GET /healthz` returning `{ ok: true, version }`; structured pino logger with request id; graceful shutdown on SIGINT.
@ -2808,7 +2808,7 @@ Final Verification Wave (4 parallel reviews)
**Commit**: YES — `feat(server): scaffold Bun HTTP+WS server with health + logging (P4.1)`
- [ ] P4.2. **Message schemas + validation (TDD)**
- [x] P4.2. **Message schemas + validation (TDD)**
**What to do**: `packages/server/src/protocol.ts` — zod schemas per PROTOCOL.md message type; `validateMessage(raw): Result`; top-level `v` version check; round-trip tested.
@ -2838,7 +2838,7 @@ Final Verification Wave (4 parallel reviews)
**Commit**: YES — `feat(server): add protocol schemas + validation (P4.2)`
- [ ] P4.3. **Room model (create/join/leave, 6-char codes)**
- [x] P4.3. **Room model (create/join/leave, 6-char codes)**
**What to do**: `packages/server/src/rooms.ts` — `class RoomRegistry` with `createRoom()` → 6-char [A-Z0-9] code + uuid-v4 token; `joinRoom(code, token)`; 2-player max; token-authenticated per message; TDD.
@ -2868,7 +2868,7 @@ Final Verification Wave (4 parallel reviews)
**Commit**: YES — `feat(server): add room registry with codes + tokens (P4.3)`
- [ ] P4.4. **Rate limiting + origin allow-list + 64KB cap**
- [x] P4.4. **Rate limiting + origin allow-list + 64KB cap**
**What to do**: `packages/server/src/middleware.ts` — per-connection token bucket (100 msg/sec, burst 20); WebSocket upgrade rejects non-allow-list origins (configurable via env `ALLOWED_ORIGINS`); reject payloads > 64KB with disconnect.
@ -2897,7 +2897,7 @@ Final Verification Wave (4 parallel reviews)
**Commit**: YES — `feat(server): add rate-limit, origin allow-list, message-size cap (P4.4)`
- [ ] P4.5. **Authoritative session per room**
- [x] P4.5. **Authoritative session per room**
**What to do**: `packages/server/src/game-session.ts` — each room holds a `Session` from `@paratype/rete` + chess rules; server is the only one that calls `insert/retract/fireRules`. Fact IDs minted here only.
@ -2925,7 +2925,7 @@ Final Verification Wave (4 parallel reviews)
**Commit**: YES — `feat(server): add authoritative game session per room (P4.5)`
- [ ] P4.6. **Move-intent validation + fact-delta broadcast**
- [x] P4.6. **Move-intent validation + fact-delta broadcast**
**What to do**: `packages/server/src/broadcast.ts` — on `game.move` intent: insert `AttemptedMove` fact; fire rules; diff pre/post WM; broadcast `game.delta` with added/removed facts to both clients. Assigned `seq` per delta for reconnection.
@ -2956,7 +2956,7 @@ Final Verification Wave (4 parallel reviews)
**Commit**: YES — `feat(server): add move validation + fact-delta broadcast (P4.6)`
- [ ] P4.7. **Reconnection flow (60s window, snapshot resume)**
- [x] P4.7. **Reconnection flow (60s window, snapshot resume)**
**What to do**: `packages/server/src/reconnect.ts` — on disconnect, start 60s timer; during grace, incoming (code, token) matches → resume and send `game.state` (full snapshot) + all deltas since client's last `seq`. After 60s, room aborts with `game.end` broadcast to remaining client.
@ -2984,7 +2984,7 @@ Final Verification Wave (4 parallel reviews)
**Commit**: YES — `feat(server): add reconnection with 60s grace + snapshot resume (P4.7)`
- [ ] P4.8. **Structured logging + metrics**
- [x] P4.8. **Structured logging + metrics**
**What to do**: `packages/server/src/logging.ts` — pino logger with request-scoped `roomId`, `clientId`, `seq`; per-tick duration metric; `/metrics` endpoint (Prometheus text format) with counters: `rooms_active`, `messages_received_total`, `moves_validated_total{result}`, tick duration histogram.
@ -3017,7 +3017,7 @@ Final Verification Wave (4 parallel reviews)
**Commit**: YES — `feat(server): add pino logging and Prometheus metrics (P4.8)`
- [ ] P4.9. **WebSocket client library with reconnect + seq ack**
- [x] P4.9. **WebSocket client library with reconnect + seq ack**
**What to do**: `packages/chess/src/net/client.ts` — `class GameClient` with `connect(code, token)`, exponential-backoff reconnect, sequence-ack tracking, event emitter for `game.state`, `game.delta`, `error`. Client owns a local engine session but only applies deltas received from server (no self-validation of moves).
@ -3046,7 +3046,7 @@ Final Verification Wave (4 parallel reviews)
**Commit**: YES — `feat(chess): add WebSocket client library with reconnect (P4.9)`
- [ ] P4.10. **Client prediction + server reconciliation**
- [x] P4.10. **Client prediction + server reconciliation**
**What to do**: `packages/chess/src/net/prediction.ts` — on user drag-drop, client locally applies move optimistically to engine session; sends intent to server; on `game.delta`, reconciles (replaces predicted state with authoritative state). On `error` response, rolls back.
@ -3076,7 +3076,7 @@ Final Verification Wave (4 parallel reviews)
**Commit**: YES — `feat(chess): add client prediction + server reconciliation (P4.10)`
- [ ] P4.11. **Room lobby UI (create/join screens)**
- [x] P4.11. **Room lobby UI (create/join screens)**
**What to do**: `packages/chess/src/ui/Lobby.tsx` — home route with two buttons: "Create Room" (shows generated code, share link) and "Join Room" (input for code). After join, redirect to `/game` with active session.
@ -3110,7 +3110,7 @@ Final Verification Wave (4 parallel reviews)
**Commit**: YES — `feat(chess): add lobby UI for create/join rooms (P4.11)`
- [ ] P4.12. **E2E multiplayer scenario (Phase 4 gate)**
- [x] P4.12. **E2E multiplayer scenario (Phase 4 gate)**
**What to do**: `packages/chess/e2e/multiplayer.spec.ts` — launches server + client (via Playwright webServer config); two contexts create/join room, play 10-move game alternating sides; ctx A disconnects at move 6, reconnects at move 7; game completes to checkmate; assert both clients see identical final state.
@ -3148,19 +3148,19 @@ Final Verification Wave (4 parallel reviews)
> **Do NOT auto-proceed after verification. Wait for user's explicit approval.**
> **Never mark F1-F4 as checked before getting user's okay.** Rejection or user feedback → fix → re-run → present again → wait for okay.
- [ ] F1. **Plan Compliance Audit** — `oracle`
- [x] F1. **Plan Compliance Audit** — `oracle`
Read this plan end-to-end. For each "Must Have": verify implementation exists (read file, run command, inspect built artifact). For each "Must NOT Have": search codebase for forbidden patterns (e.g., `grep -r "as any" packages/rete/src`), reject with file:line if found. Check evidence files exist in `.sisyphus/evidence/`. Verify all 5 phase tags exist (`git tag | grep phase`). Compare deliverables against plan.
Output: `Must Have [N/N] | Must NOT Have [N/N] | Phase tags [5/5] | Tasks [N/N] | VERDICT: APPROVE/REJECT`
- [ ] F2. **Code Quality Review** — `unspecified-high`
- [x] F2. **Code Quality Review** — `unspecified-high`
Run `bun run typecheck` + `bun run lint` + `bun run test:coverage` + `bun run size-limit`. Review all changed files for: `as any` / `@ts-ignore` / `@ts-expect-error`, empty catches, `console.log` in prod code, commented-out code, unused imports, `Date.now()`/`Math.random()` in engine RHS paths, raw `Set<object>` iteration in engine hot paths. Check AI slop: excessive comments, over-abstraction, generic names (data/result/item/temp/obj). Audit bundle sizes against budgets (engine < 50KB min+gz, chess < 200KB min+gz).
Output: `Build [PASS/FAIL] | Lint [PASS/FAIL] | Tests [N pass/N fail, coverage X%/Y%/Z%] | Bundle [engine Xkb / chess Ykb] | Files [N clean/N issues] | VERDICT`
- [ ] F3. **Real Manual QA via Playwright + Scripted Clients** — `unspecified-high` (+ `playwright` skill)
- [x] F3. **Real Manual QA via Playwright + Scripted Clients** — `unspecified-high` (+ `playwright` skill)
Start from clean state: `rm -rf node_modules && bun install && bun run build`. Launch chess server. Execute EVERY QA scenario from EVERY task — follow exact steps, capture evidence. Test cross-task integration: play a full FIDE game; toggle 3 presets between games; play a custom-rules game; save via localStorage; reload browser; verify state persisted; export JSON; import into fresh browser; play a multiplayer game across two browser contexts with reconnect mid-game. Test edge cases: illegal move rejected, rate-limit trip, protocol version mismatch hard-disconnect, 60s reconnect boundary. Save to `.sisyphus/evidence/final-qa/`.
Output: `Scenarios [N/N pass] | Integration [N/N] | Edge Cases [N tested] | VERDICT`
- [ ] F4. **Scope Fidelity Check** — `deep`
- [x] F4. **Scope Fidelity Check** — `deep`
For each task: read "What to do", read actual diff (`git log` / `git diff` on that task's commits). Verify 1:1 — everything in spec was built (no missing), nothing beyond spec was built (no creep). Check "Must NOT do" compliance in diff. Detect cross-task contamination: Task N touching Task M's files. Flag unaccounted changes. Verify commit messages follow Conventional Commits with scope (`feat(rete):`, `feat(chess):`, `feat(server):`).
Output: `Tasks [N/N compliant] | Contamination [CLEAN/N issues] | Unaccounted [CLEAN/N files] | Commit format [N/N] | VERDICT`