feat(thressgame-coverage): Wave 8 (WS protocol v2 + suspended execution + request-choice)
- T43: WS protocol v2 schema; protocolVersion field; RequestChoice/SubmitChoice/ProtocolVersionMismatch messages; v1 backward-compat - T44: server-side request-choice broadcast on push; submit-choice validation (kind/forPlayer/value-type); ordered LIFO matching - T45: PendingChoices stack on GAME_ENTITY; pushPendingChoice/popPendingChoice/peekPendingChoice helpers; serializePendingChoice (Map<->Array roundtrip); MAX_CHOICE_DEPTH=8 enforced - T46: submitChoiceAndResume(engine, choiceId, value); descriptor-by-id lookup; bindings restored; remaining primitives executed via runPrimitives from primitiveIndex+1 - T47: request-choice primitive; SuspendedExecution exception mechanism; dispatcher catches and stops sibling iteration; deterministic choiceId via session counter - T48: AutoChoiceResolver test transport (answersByKind / answersById); drainPendingChoices LIFO walk - T49: server-side choice timeout enforcement; auto-resolve to first-option-per-kind; disconnect handler (forfeit / pause) - T50: ChoiceTimeoutPolicy on GAME_ENTITY (timeout-with-default | no-timeout); CreateGameRequest extended; default 60s Tests: 2533 -> 2658 (+125). bun run check exit 0.
This commit is contained in:
parent
778ebc4129
commit
d4931a50ee
37 changed files with 6841 additions and 295 deletions
|
|
@ -671,3 +671,46 @@ Added BlockList wrapping BlockCard with dnd-kit for sorting. Added tests verifyi
|
|||
2. Depth-4 invalid (conditional -> on-move -> conditional -> add-to-attribute) triggering `descriptor.primitives.depth.exceeded`
|
||||
3. Mixed old/new kinds at depth 3 (on-captured -> conditional -> add-aura) valid
|
||||
- `bun test packages/chess/src/modifiers/custom/validate.test.ts` passes with 16 test cases.
|
||||
|
||||
---
|
||||
|
||||
## Path-based selection refactor + nested-editing + add-child button — 2026-04-21
|
||||
|
||||
### Problem
|
||||
Nested BlockCards couldn't be selected/edited. BlockList recursion hardcoded `selectedIndex={null}` + `onSelect={() => {}}` (no-ops) because selection state was flat `number | null`. Also no visible affordance existed to add primitives inside an expanded trigger (user had to know "click parent → palette banner appears → click palette item").
|
||||
|
||||
### Solution
|
||||
- Replaced `selectedIndex: number | null` with `SelectionPath = readonly number[]` throughout VisualBuilderPane / BlockList / BlockCard.
|
||||
- `[]` = no selection; `[0]` = top-level 0; `[0, 2]` = child 2 of top-level 0 (via `params.primitives`). Arbitrary depth supported.
|
||||
- Replaced `expandedIndices: Set<number>` with `expandedPaths: Set<string>` keyed by `path.join('.')` (avoids deep-set-equality ceremony).
|
||||
- 5 new pure path walkers in VisualBuilderPane.tsx: `getNodeAtPath`, `updateAtPath`, `removeAtPath`, `appendChildAtPath`, `reorderAtPath` + `pathStartsWith` helper.
|
||||
- Deleted redundant `handleNestedReorder` / `handleNestedRemove` — consolidated into path-based versions.
|
||||
- New BlockCard prop `onAddChildClick?: () => void` renders a dashed-violet "+ Add primitive inside" button at the bottom of the nested container. BlockList wires it to `() => onSelect(thisPath)` for container primitives only (checks `primitive?.childPrimitives !== undefined`).
|
||||
- Nested-container now renders even when children-list is empty — so empty triggers STILL show the add button.
|
||||
- Nested DnD id collision guard: `nodeIds` include `basePath.join('.')` so nested SortableContexts don't share IDs.
|
||||
- `handleSelect` auto-expands container primitives so the add-child button appears immediately.
|
||||
|
||||
### Conditional `then`/`else` — documented as out of scope
|
||||
Path walker only traverses `params.primitives`. `conditional`'s separate `then`/`else` arrays are NOT selectable/editable in visual mode — same status as before this refactor. Comment in VisualBuilderPane.tsx:85-94.
|
||||
|
||||
### Edge cases handled
|
||||
- Remove subtree containing selection → `pathStartsWith` clears selection
|
||||
- Remove cleans expandedPaths via key-prefix match
|
||||
- Reorder adjusts selection index if it pointed into the reordered list
|
||||
- "Add at top level instead" button → `setSelectedPath([])`
|
||||
|
||||
### Verification
|
||||
- 27/27 visual-builder tests pass (up from 22, +5 new tests covering nested selection + add-child button)
|
||||
- `bun run check` → 166 files / 1957 tests pass
|
||||
- 0 lsp_diagnostics errors in modified files
|
||||
- No `as any`, no `@ts-ignore` introduced
|
||||
|
||||
### Files touched
|
||||
- packages/chess/src/ui/visual-builder/VisualBuilderPane.tsx (+245 / -126 lines)
|
||||
- packages/chess/src/ui/visual-builder/BlockList.tsx (+86 / -49)
|
||||
- packages/chess/src/ui/visual-builder/BlockCard.tsx (+25 / -4)
|
||||
- packages/chess/src/ui/visual-builder/{BlockCard,BlockList,VisualBuilderPane}.test.tsx (updated for new prop shapes + new tests)
|
||||
|
||||
### Pre-existing noise confirmed NOT caused by this work
|
||||
- `ParamField.snapshot.test.tsx` has 15 obsolete snapshots (T14 legacy) — untouched ParamField.tsx per user request
|
||||
- `CustomModifierEditor.mode-roundtrip.test.tsx` fails under `bun test` direct but passes under `bun run check` (vitest environment) — pre-existing localStorage mocking limitation documented at learnings.md:658
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue