Skip to content

feat(ui): yield button + /yield slash command#165

Merged
slabgorb merged 3 commits intofeat/dual-track-momentum-phase-2from
feat/dual-track-momentum-phase-3
Apr 25, 2026
Merged

feat(ui): yield button + /yield slash command#165
slabgorb merged 3 commits intofeat/dual-track-momentum-phase-2from
feat/dual-track-momentum-phase-3

Conversation

@slabgorb
Copy link
Copy Markdown
Owner

Summary

Phase 3 of the dual-track momentum implementation — UI side. Adds the player-facing yield action: a button in the active confrontation overlay and a /yield slash command. The server-side YIELD message dispatch lands in sidequest-server PR #56.

Note on stacking: This PR is stacked on PR #164 (Phase 2). After #164 merges, the base of this PR can be retargeted to develop.

Spec: orchestrator docs/superpowers/specs/2026-04-25-dual-track-momentum-design.md.
Plan: orchestrator docs/superpowers/plans/2026-04-25-dual-track-momentum.md Task 26.

Commits

  • feat(ui): yield button + /yield command (4ee781c) — adds YieldButton.tsx, registers /yield in useSlashCommands, threads onYield callback from App.tsxGameBoardConfrontationWidgetConfrontationOverlay. MessageType.YIELD mirrored to src/types/protocol.ts.
  • fix(ui): forward slash-command messages to server send pipeline (cdef71b) — fixes a bug found in code review: handleSend was appending slash-command-produced messages to local messages state but never calling send(), so /yield (and any future server-bound slash command) silently dropped. Adds the for (const msg of slashResult.messages) { send(msg); } loop and a wiring test that asserts the call path is intact.

Plan deviations (acknowledged)

  • Plan referenced src/lib/socket.ts, src/screens/EncounterPanel.tsx, and src/lib/slash.ts — none of those files exist. Used the actual codebase locations: useGameSocket, ConfrontationOverlay, useSlashCommands.
  • disabled={false} is hardcoded on the YieldButton inside ConfrontationOverlay. The overlay's encounter model is legacy single-metric shape (Phase 1/2 cleanup gap, not Phase 3 scope) and doesn't expose enough state to compute the right disabled value here. The button is only rendered while the overlay is mounted (which only happens during an active encounter), so the practical impact is small — but it's a real limitation worth noting for a future overlay refactor.

Test plan

  • npx vitest run src/__tests__/YieldButton.test.tsx — 2 component tests
  • npx vitest run src/hooks/__tests__/useSlashCommands.test.ts/yield produces YIELD message
  • npx vitest run src/__tests__/slash-command-send-wiring.test.ts — slash messages reach send()
  • npx vitest run — full suite, no new regressions
  • Live smoke (deferred — covered by Task 31 regression test on the server side)

🤖 Generated with Claude Code

slabgorb and others added 3 commits April 25, 2026 16:18
…nds (#164)

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Add YieldButton component, wire it into the confrontation overlay, add
/yield slash command that sends a YIELD wire message, and thread the
onYield callback from App.tsx through GameBoard → ConfrontationWidget →
ConfrontationOverlay. MessageType.YIELD added to protocol.ts to mirror
the server-side type added in Task 23.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
handleSend was appending slash-command-produced messages (e.g. /yield →
YIELD) to local state but never calling send(), so the server's
_handle_yield never fired. Add send(msg) for-loop inside the
slashResult.messages.length > 0 block; intentionally omit setCanType /
setThinking — slash commands do not start a narration turn.

Add wiring test (slash-command-send-wiring.test.ts) asserting the
for-loop and send(msg) are present inside the slashResult.handled branch
and that setCanType/setThinking are absent from that branch.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@slabgorb slabgorb force-pushed the feat/dual-track-momentum-phase-3 branch from cdef71b to 8a18d94 Compare April 25, 2026 20:18
@slabgorb slabgorb merged commit 7765523 into feat/dual-track-momentum-phase-2 Apr 25, 2026
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.

1 participant