No description
Wave 2 of thressgame-100 epic complete. Coverage 27/51 \u2192 37/51 = 72 % (on plan target).
ENGINE WORK (W2.0\u2013W2.6):
- New trigger primitive on-attr-expire(target, attr, primitives) \u2014 fires when an
attr countdown hits zero. Introduces 'expiringValue' binding to inner primitives.
- New imperative primitive decrement-attr-each-turn(target, attr) \u2014 explicit
countdown control (alternate to set-piece-attr.lifetime: turns).
- New dispatcher stage 13 fireAttrExpireHooks \u2014 batched per-turn-boundary, runs
AFTER stage 12 fireOnTurnStartHooks.
- Lifetime registry extension (lifetime-registry.ts) \u2014 decrementAttrCountdowns
function mirrors the marker-lifetime pattern; fires on-attr-expire BEFORE
retraction so triggers can still read the expiring value.
- Schema additions (schema.ts) \u2014 OnAttrExpireHooks (game-level on GAME_ENTITY),
AttrCountdownRegistry (game-level), OnAttrExpireHookEntry, AttrCountdownEntry.
- Validator (validate.ts) \u2014 decrement-attr-each-turn added to IMPERATIVE_KINDS;
on-attr-expire registered as binding-introducer with FIXED_BINDING_KINDS map.
- IMPERATIVE_KINDS list and trigger-scope walker updated.
10 NEW RECIPES (W2.7\u2013W2.9):
- tpl-time-bomb \u2014 black knights self-destruct after 5 turns
- tpl-nuclear-fallout \u2014 3 random blocked-square markers (deterministic seed)
- tpl-christmas-truce \u2014 BlockAllExceptKing on GAME_ENTITY for 3 turns
(proxy for missing BlockAllCaptures attr)
- tpl-pawn-second-chance \u2014 captured white pawn returns 1 turn later
- tpl-invulnerability-potion \u2014 white pieces uncapturable for 3 turns
- tpl-anti-camping \u2014 every piece dies after 3 turns (refresh-on-move
arm dropped per depth limit)
- tpl-ice-age \u2014 16 frozen-square markers covering files a + h
- tpl-no-cowards \u2014 MustMoveForward semantic flag for 1 turn
- tpl-drafted-for-battle \u2014 chooser picks bishop/knight, swap with king
- tpl-corporate-ladder \u2014 chooser picks 2 pieces to swap
NINE DOCUMENTED SIMPLIFICATIONS (full rationale in notepad and evidence):
- tpl-time-bomb dropped adjacent-splash arm (depth 5 > MAX_RECURSION_DEPTH=3)
- tpl-christmas-truce uses BlockAllExceptKing (no BlockAllCaptures attr)
- tpl-pawn-second-chance white-pawn-only (place-piece pieceType/color strict)
- tpl-invulnerability-potion uses set-piece-attr (set-capture-flag has no target)
- tpl-anti-camping dropped refresh arm (depth limit)
- tpl-no-cowards ships flag only (move-gen consumer wiring deferred to host preset)
- tpl-corporate-ladder uses request-choice(piece) \u00d7 2 (square \u2192 pieceId conversion
isn't expressible in ConditionSpec.value)
- tpl-drafted-for-battle bishop/knight restriction is player discipline
- tpl-nuclear-fallout / tpl-ice-age use lifetime: moves (spawn-marker.lifetime
schema doesn't accept turns)
TEST SURFACE:
- on-attr-expire.test.ts: 12 unit tests
- decrement-attr-each-turn.test.ts: 10 unit tests
- attr-expire-integration.test.ts: 7 integration tests
(incl. N=100 determinism)
- countdowns-perf.test.ts: 1 perf test
(p50=13.6ms p99=24.6ms; budget <150ms)
- wave2-recipes-real.test.ts: 15 runtime tests (NEW)
- recipes.test.ts: 5 \u00d7 46 = 378 expect calls
- wave2-countdowns.spec.ts (Playwright e2e): 13 tests
(10 load + 3 runtime: ice-age,
nuclear-fallout, drafted-for-battle)
bun run check: 3055 tests pass (was 3010, +45). 0 regressions.
e2e: 13/13 green via .sisyphus/scripts/run-pw.sh against docker compose dev stack.
BACKWARD-INCOMPAT TESTS UPDATED (per locked decision J):
- registry-count.test.ts: 50 \u2192 52 (decrement + on-attr-expire)
- ParamField.snapshot.test.tsx: SAMPLE_PARAMS exhaustiveness for two new kinds
- apply.test.ts: stage-list comment updated for new stage 13
Plan: .sisyphus/plans/thressgame-100.md
Notepads: .sisyphus/notepads/thressgame-100/
Evidence: .sisyphus/evidence/thressgame-100-wave2.txt (gitignored, 1037 lines)
|
||
|---|---|---|
| .github/workflows | ||
| .sisyphus | ||
| docs | ||
| packages | ||
| scripts | ||
| .dockerignore | ||
| .gitignore | ||
| docker-compose.dev.yml | ||
| docker-compose.yml | ||
| Dockerfile.dev | ||
| eslint.config.js | ||
| lefthook.yml | ||
| LICENSE | ||
| package.json | ||
| playwright.config.ts | ||
| README.md | ||
| tsconfig.base.json | ||
| tsconfig.json | ||
| vitest.workspace.ts | ||
@paratype
A Doorenbos-style Rete II rules engine for TypeScript games, with an authoritative WebSocket chess demo.
Packages
packages/rete— Rete II engine corepackages/chess— Browser chess demo (React + Vite)packages/server— Authoritative Bun WebSocket server
Docs
- SPEC.md — Engine specification
- PHASES.md — Development phases & perf budgets
- RULES.md — Chess rule presets
- PROTOCOL.md — WebSocket message protocol
Getting Started
bun install && bun run check