mirror of
https://github.com/Gitlawb/openclaude.git
synced 2026-08-24 02:34:15 -05:00
* feat(buddy): hero pixel-art companions with signature Enter animations Rebuild the buddy system as heroes-only. The 18 legacy rolled species are removed; the hatch pool is now 7 hero forms — robinhood, kaio, strawhat, merlin, kage, ember, corsair — each hand-pickable via /buddy set. Every hero has 22x16 truecolor half-block pixel art (idle + action poses), a line-art fallback for low-color terminals, a narrow-mode face, and a signature effect that fires on every message submission: arrow with impact thunk, charging full-width energy wave, stretchy punch that extends and snaps back, twinkling sparkle stream, spinning shuriken, gradient fire cone, and cannonball with smoke trail. Engine: companion animation moves from a raw 500ms setInterval to the shared animation clock (useAnimationFrame; pauses when hidden, respects prefersReducedMotion), with a one-shot 50ms burst driver (useShotClock, arm-then-anchor to avoid stale-tick draw-phase skips) and a general ActionEffect system (pure draw/travel/impact functions, frame-tested). Effects travel right-to-left toward the prompt — matching where the sprite actually stands. Commands: /buddy set <form|random>, /buddy name <name>, muted-buddy feedback (silent no-op pets now explain themselves), and a hatch-message fix so the announced species always matches the displayed sprite (the message previously rolled with a different seed). BREAKING: existing rolled pets transform into a hero on upgrade (name and personality persist; speciesOverride pins are unaffected). Co-Authored-By: OpenClaude <openclaude@gitlawb.com> * fix(buddy): address CodeRabbit review on PR #1972 - useShotClock: consume an in-flight shot when playback becomes ineligible mid-flight (mute/reduced-motion/resize), so re-enabling can't resume a stale animation. - /buddy unmute: emit a greeting reaction — the sprite reads companionMuted non-reactively and its clock is paused while hidden, so a config-only unmute left it invisible until an unrelated re-render. - /buddy name: strip ANSI escapes and control/format characters before saving, and cap by display width (stringWidth) instead of UTF-16 length. - CompanionSprite: track bubble age in sync-render state instead of an effect-updated ref, so a fresh reaction can't render pre-faded. - companion_intro already keyed on name+species (prior commit); tests now pin exact faces for all seven heroes, separate idle/shoot pixel frame counts, and decode-guard the charCode species constants. - CompanionActionFX tests: deterministic companion fixture via complete-config module mock; raw (untrimmed) output compared against a rendered-null baseline so a spurious blank FX row fails. - companion.test: re-register the real config module in afterAll (mock.restore does not undo mock.module). - Types: SPECIES_COLORS and FORM_FLAVOR are full Records (compile error on a colorless/flavorless future hero); dead RARITY_COLORS removed. Co-Authored-By: OpenClaude <openclaude@gitlawb.com> * test(buddy): regression coverage for bubble age reset on reaction change Renders CompanionSprite against a fake shared clock: ages the first bubble past the fade threshold, swaps the reaction WITHOUT advancing the clock, and asserts the fresh bubble renders unfaded. Fading is detected structurally (border and text collapse to one color when fading) so the test is independent of the active theme's exact values. Requested by CodeRabbit on PR #1972. Co-Authored-By: OpenClaude <openclaude@gitlawb.com> --------- Co-authored-by: OpenClaude <openclaude@gitlawb.com>