8 Commits

Author SHA1 Message Date
b1121651dc v0.2.5: 1Hz tick keeps timer counting when no envelope event fires
Bug: timeSinceStart only updated when an envelope event fired
(combatStart, attack-roll, etc.). If the combat was idle — a
player thinking about their turn, between turns — the timer froze.

Fix: 1Hz self-rescheduling setTimeout in the constructor that
bumps timeSinceStart and triggers a throttled render while
_state.isActive is true. Stopped on unwireHooks (combat end).

TDD: Section O (5 assertions) added BEFORE the fix.
- O.1 initial timeSinceStart reflects _combatStartedAt
- O.2 advances without an envelope event
- O.3 tick interval is ~1s
- O.4 timer does not tick when combat is inactive
- O.5 timer resumes when combat becomes active again

Tests: 65/65 passing in ~2s. Playwright 31/31.
2026-06-22 19:21:30 -04:00
e9e550b190 v0.2.4: current-turn updates on combatTurn + session-open auto-open
Bug 1: current-turn indicator not updated on combatant switch.
Foundry's combatTurn hook fires BEFORE the new state is committed,
so game.combat.combatant is the OLD combatant at that moment. The
event-translation layer now resolves the new combatant from
combat.turns[newTurn] and passes combatantId + combatantName +
combatantTokenId through. The HUD stashes these on _state._latestTurn
and uses it as a tiebreaker when the encounter's combatantId is
stale (which battle-focus's encounter always is, since bf doesn't
update currentTurn on turn events).

Bug 2: HUD doesn't open on session-open with a pending/active combat.
At ready, check battle-focus.api.getActiveEncounter(); if it's
live (not endedAt), open the HUD and populate from the encounter.
This handles browser-refresh mid-combat and 'pending combat'
(tracker exists but Start Combat not yet clicked).

Bonus: encounter.combatantId key resolution. The encounter's
combatantId is the Foundry combatant document id, but the
combatants map may be keyed by tokenId, actorId, or combatantId.
The currentTurn resolver now tries all three.

Tests: 60/60 passing in <1s. Sections M (turn event) + N
(session-open) added.
2026-06-22 18:32:05 -04:00
bf9b8cd1cc v0.2.3: add isReady() + 3-place version rule
- New api.isReady() returns true after the ready hook fires (and
  core sections have registered). Tests now wait for isReady()
  before asserting on the section list.
- 3-place version rule (module.json + package.json + main.js
  MODULE_VERSION) — v0.2.2 was missing the source bump; corrected
  by going to v0.2.3 across all three places.
- Tests: 50/50 passing in <1s.
2026-06-22 17:08:24 -04:00
e6531ec569 v0.2.2: bump MODULE_VERSION in main.js to match module.json/package.json
Missed the 3-place version rule on the v0.2.2 bump. MODULE_VERSION
was still v0.2.0 in scripts/main.js, so Foundry's init log showed
the old version and the live system didn't have getFeed/clearFeed.
Caught during the e2e Playwright run when Foundry loaded v0.2.0
of the main.js but v0.2.2 of the module.json.
2026-06-22 17:06:35 -04:00
23c2deeac5 v0.2.2: add getFeed + clearFeed read accessors
- api.getFeed(sectionId) returns a shallow copy of the section's
  feed entries. Useful for tests + consumer introspection.
- api.clearFeed(sectionId) empties a section's feed.
- Smoke: 50/50 passing. Section C extended with new assertions.
- This unblocks the its-achievable v0.3.0 Playwright test, which
  needs getFeed to verify chatBubble → pushToHubFeed → chh feed.
2026-06-22 16:15:45 -04:00
f304db49cc v0.2.1: current-turn indicator + encounter-as-source-of-truth
- Combatants row whose tokenId matches encounter's current combatant
  gets data-chh-current-turn=true, an accent-color border + tint, an
  outlined portrait, and a '▶' marker before the name.
- Header section prepends '▶' before the turn name.
- buildRenderContext now resolves currentTurn from the encounter
  singleton (encounter.currentTurn / encounter.combatantId) instead
  of reading game.combat directly. battle-focus owns the encounter.
- Tests: 46/46 in <1s, new section L covers the indicator.
2026-06-22 16:05:14 -04:00
04008acc66 v0.2.0: port HUD from its-achievable as a section-based host
- Ported scripts/hud.js, scripts/event-translation.js,
  templates/hud.html, styles/hud.css from its-achievable v0.2.0.
- Renamed bf-hud-* CSS prefix to chh-* (function-over-branding).
- HUD now renders via addSection({ id, label, render }); no internal
  pinned-achievements feed. its-achievable (v0.3.0) registers its own
  pinned-achievements section.
- Built-in core sections: core-header, core-combatants, core-dice-streak.
- New hudPosition setting (per-user, top/bottom/left/right).
- Throttled render (1Hz).
- ApplicationV2 surface: open, close, isOpen, getState, getView,
  forceRender, wireHooks, unwireHooks.
- Tests: 42/42 passing in <1s covering PLAN sections A-K.
2026-06-22 12:37:12 -04:00
9c4e4c86fe v0.1.0: scaffold combat-hud-hub with public API + soft-dep wiring
- Public API: addSection, removeSection, pushFeedEntry, listSections,
  getHud, openHud, closeHud.
- Soft-dep on foundry-hooks-lib (envelope subscription) + battle-focus
  (encounter seam).
- Built-in core sections (round, current turn, per-PC damage, dice
  streak) register only when both deps are present at ready.
- Smoke tests: 22/22 in <1s covering sections A-G of tests/PLAN.md.
- HUD instance is a stub in v0.1.0; ApplicationV2 mounting in v0.2.0.
2026-06-22 12:04:43 -04:00