Files
Kaysser Kayyali 7f0d1bbff1 v0.2.0 — generic Foundry hook facade (rip-and-replace of v0.1.0)
v0.1.0 shipped as a curated-event catalog (18 hand-written handlers
+ system adapters + an encounter.js stub). Wrong shape. v0.2.0 is a
RIP-AND-REPLACE per HOOK_CONTRACT.md (docs/HOOK_CONTRACT.md):
generic Foundry hook facade with NO domain interpretation.

## What's new

scripts/internal/ — new modular structure:
- registered-hooks.js: the §6 hook set (~60 raw Foundry hooks,
  envelope name, sync/async mode)
- envelope.js: buildEnvelope + sync/async dispatch (§8)
- subscribers.js: subscribe/subscribeMany/subscribeAll/unsubscribeAll
  primitives (§3) + error containment (§3.5)
- adapter-registry.js: registerSystemAdapter + semver-range matching
  (§5) + ready-time evaluation
- semver.js: inline semver matcher (no external dep)
- anti-corruption.js: hook rename normalization (§9) + arg shape
  fixes (§10) + combatInactive synthesis from updateCombat
- lifecycle.js: init/ready/unregisterModule hooks (§4)

scripts/main.js — Foundry entry point. Registers the public API on
mod.api; init installs Foundry hooks; ready evaluates adapters;
unregisterModule cleans up.

## Tests

- tests/verify-hooks-lib.mjs — 554 assertions in 0.34s (under the
  2s budget). Sections A-G of tests/PLAN.md:
  - A: envelope shape (every registered hook produces exactly
    {ts, hook, args})
  - B: subscriber API (single, batch, all, atomic, error path)
  - C: error containment (throwing consumer doesn't break chain)
  - D: lifecycle (install/uninstall, adapter eval, world change)
  - E: anti-corruption (renderChatLog→renderChatInput,
    combatInactive synthesis, combatRound arg normalization)
  - F: semver matcher
  - G: adapter loading (validation, dedup, factory failure)
- tests/perf.mjs — 6 assertions. Median 0.0003ms/fire
  (333x under the 0.1ms budget). Heap delta 2.8MB across 10k fires.
- tests/test-helpers.mjs — Foundry stub (Hooks, game, ui).

## Archive

scripts/_archive/v0.1.0/ — v0.1.0 catalog moved here for git
history. The 18 handlers, system adapters, and encounter.js stub
all live there but are not part of the v0.2.0 module.

tests/_archive_v0.1.0_*.mjs — v0.1.0 test files renamed with
prefix to avoid colliding with v0.2.0 files.

## Manifest

- module.json: bumped to 0.2.0; download URL points at the new zip.
- package.json: bumped to 0.2.0; added test:perf script.
- README.md: rewritten for v0.2.0.

Push: Gitea only.
2026-06-20 03:01:22 -04:00
..