v0.4.0: scope to Foundry v14 only, drop v13 dual-subscription
User directive: 'update the plan. v14 only'. Implementation: **scope change (Foundry v14 only):** - registered-hooks.js: renderChatInput entry drops the v13 renderChatLog name. Single subscription to the v14 name. - anti-corruption.js: combatRound arg-normalization no longer detects the v13 round-num position. v14's updateOptions.round is the only path. Removed the v13 comments from the other arg shapes (combatEnd, combatTurn). - module.json: compatibility.minimum is now 14 (was 13). verified stays 14. - package.json: version 0.3.0 -> 0.4.0 (semver-breaking: dropping v13 support is a breaking change for v13 consumers). - package.json description: 'Foundry VTT v14-only module' prefix. **test plan:** - tests/PLAN.md: v14-only scope documented at the top of the file and in Section E. Status line bumps 554 to 546 assertions (v13-only assertions dropped). Test files table re-scoped to v0.4.0. - tests/verify-hooks-lib.mjs: dropped the v13-only assertions (E.2 'renderChatLog in installed', E.3's 'both v13 and v14 produce' check, E.4's v13 round shape). Kept the v14-only assertions + added an inverse assertion: 'renderChatLog is NOT in installed raw hooks' to lock the v14-only scope. - tests/verify-hooks-lib.mjs: stub table at line ~520 drops renderChatLog (dead in production now). **doc updates:** - README.md: new 'v0.4.0 — Foundry v14 only' section explaining the change + migration note for v13 consumers. - docs/HOOK_CONTRACT.md: v0.3.0 header. §9 marks the v13 column as historical. §10 example uses the v14 shape only. **artifact:** - foundry-hooks-lib-0.4.0.zip built (82KB, 46 entries, inner version 0.4.0, inner compatibility.minimum 14). **verified:** - npm test: 546/546 assertions passed - npm run test:foundry: 30/30 assertions passed - npm run test:perf: 6/6 assertions passed (median 0.0003ms/fire) - battle-focus E2E (consumer): 125/125 still green - its-achievable smoke (consumer): 75/75 still green **consumer follow-up (separate commits in their own repos):** - battle-focus/module.json: relationships.requires[0].version bumped to ^0.4.0 - its-achievable/module.json: relationships.requires[0].minimum bumped to 0.4.0
This commit is contained in:
27
README.md
27
README.md
@@ -11,6 +11,33 @@ Consumers today: `battle-focus` (encounter + journal + summary) and
|
||||
(dnd5e rolls, PF2e, etc.) lives in separate adapter repos that declare
|
||||
Foundry + system version ranges they support.
|
||||
|
||||
## v0.4.0 — Foundry v14 only
|
||||
|
||||
v0.3.0 renamed the module id (hax-hooks-lib → foundry-hooks-lib) and
|
||||
shipped the Playwright test against a live Foundry v14. v0.4.0 narrows
|
||||
the scope to **Foundry v14 only** — the v0.2.0-era anti-corruption
|
||||
layer that absorbed both v13 and v14 hook renames is reduced to
|
||||
v14-only normalization. Specifically:
|
||||
|
||||
- The `renderChatInput` registered-hooks entry no longer subscribes
|
||||
to the v13 `renderChatLog` name.
|
||||
- The `combatRound` arg-normalization no longer detects the v13
|
||||
round-num position; v14's `updateOptions.round` is the only path.
|
||||
- `compatibility.minimum` in `module.json` is now `14` (was `13`).
|
||||
- The smoke test dropped 8 v13-only assertions (E.2's
|
||||
`renderChatLog is in installed`, E.3's "both produce" check, E.4's
|
||||
v13 round-shape). 546/546 remaining assertions pass.
|
||||
|
||||
`tests/PLAN.md` documents the v14-only scope at the top of the file
|
||||
and in Section E.
|
||||
|
||||
**Migration note for v13 consumers:** upgrade to Foundry v14. The
|
||||
contract still documents the v13 → v14 hook name mapping in §9 for
|
||||
historical reference, but the library no longer subscribes to v13
|
||||
names.
|
||||
|
||||
---
|
||||
|
||||
## v0.3.0 — module id renamed (hax-hooks-lib → foundry-hooks-lib)
|
||||
|
||||
v0.2.0 is a complete rewrite. v0.1.0 shipped as a curated-event catalog
|
||||
|
||||
@@ -1,8 +1,13 @@
|
||||
# HOOK_CONTRACT.md — `hooks-lib` v0.2.0
|
||||
# HOOK_CONTRACT.md — `hooks-lib` v0.3.0
|
||||
|
||||
**Status:** Proposed spec. Subject to revision until v0.2.0 ships.
|
||||
**Status:** Implemented spec for v0.3.0.
|
||||
**Audience:** hooks-lib authors + consumer authors + system adapter authors.
|
||||
**Stability:** v0.2.0 ships as the contract; breaking changes require a major bump.
|
||||
**Stability:** v0.3.0 ships as the contract; breaking changes require a major bump.
|
||||
|
||||
**Scope:** Foundry v14 only. v0.2.0's anti-corruption layer absorbed
|
||||
v13/v14 hook renames; v0.3.0 narrows to v14. See §9 for the v14
|
||||
mapping (the v13 column is kept for historical context — those
|
||||
renames are no longer subscribed to).
|
||||
|
||||
---
|
||||
|
||||
@@ -374,20 +379,26 @@ return matters. The dispatch mode is part of the hook's entry in §6.
|
||||
## 9. Anti-corruption: hook rename mapping
|
||||
|
||||
Foundry renames hooks between versions. The library absorbs the
|
||||
churn so consumers don't have to. Example mappings (v0.2.0):
|
||||
churn so consumers don't have to. **v0.3.0 is Foundry v14 only.**
|
||||
|
||||
| Foundry v14 hook | Foundry v13 hook | Library `envelope.hook` |
|
||||
|------------------|------------------|-------------------------|
|
||||
| `renderChatInput` | `renderChatLog` | `renderChatInput` |
|
||||
| `updateCombat` (active→inactive) | `combatEnd` (sometimes) | `combatInactive` |
|
||||
| `dnd5e.rollAttackV2` | `dnd5e.rollAttack` (v1) | `dnd5e.rollAttackV2` (only v2 supported in v0.2.0) |
|
||||
v0.2.0 supported both v13 and v14 by subscribing to both names and
|
||||
normalizing the envelope. The current v0.3.0 only subscribes to
|
||||
v14 names; the v13 column below is historical (those entries are
|
||||
no longer in the registered hook set, and firing them produces no
|
||||
envelope).
|
||||
|
||||
The library internally subscribes to BOTH the v13 and v14 hook
|
||||
names where applicable, normalizing the envelope `hook` field to the
|
||||
modern name. Consumers see one stable name regardless of Foundry
|
||||
version.
|
||||
| Foundry v14 hook | Foundry v13 hook (historical) | Library `envelope.hook` |
|
||||
|------------------|--------------------------------|-------------------------|
|
||||
| `renderChatInput` | `renderChatLog` | `renderChatInput` |
|
||||
| `updateCombat` (active→inactive) | `combatEnd` (sometimes) | `combatEnd` |
|
||||
| `dnd5e.rollAttackV2` | `dnd5e.rollAttack` (v1) | `dnd5e.rollAttackV2` (only v2 supported) |
|
||||
|
||||
For each mapped pair, the library's tests assert the normalization.
|
||||
For v14, the library subscribes to the v14 name and emits it
|
||||
verbatim. The envelope.hook name IS the v14 name. Consumers see
|
||||
one stable name.
|
||||
|
||||
If a future v14 micro-release renames a hook again, add the mapping
|
||||
back here and re-introduce the dual-subscription pattern.
|
||||
|
||||
---
|
||||
|
||||
@@ -397,14 +408,13 @@ Foundry's hook arities shift between versions. The library passes
|
||||
args verbatim, but for hooks where arity is unstable, the library
|
||||
normalizes by padding/truncating to a documented shape.
|
||||
|
||||
Example (illustrative — exact normalization is implementation-defined):
|
||||
Example (Foundry v14; v0.3.0 is v14 only):
|
||||
|
||||
```js
|
||||
// Foundry v13: combatRound(combat, updateData, roundNum)
|
||||
// Foundry v14: combatRound(combat, updateData, updateOptions)
|
||||
|
||||
// Library normalizes to:
|
||||
envelope.args = [combat, updateData, roundNum ?? updateOptions?.round ?? 1, updateOptions]
|
||||
envelope.args = [combat, updateData, updateOptions?.round ?? 1, updateOptions]
|
||||
```
|
||||
|
||||
This normalization is **the only** consumer-facing change vs raw
|
||||
@@ -412,7 +422,7 @@ Foundry. Consumers can rely on `args[N]` being the documented field
|
||||
even if Foundry shifts it.
|
||||
|
||||
The exact normalized shapes are listed in `docs/HOOK_ARG_SHAPES.md`
|
||||
(separate file because it's long). v0.2.0 documents the shape for
|
||||
(separate file because it's long). v0.3.0 documents the shape for
|
||||
every hook in §6.
|
||||
|
||||
---
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1,8 +1,8 @@
|
||||
{
|
||||
"id": "foundry-hooks-lib",
|
||||
"title": "Foundry Hooks Lib",
|
||||
"description": "Foundry VTT module: generic Foundry hook facade. Subscribes to every relevant Foundry hook (combat, document CRUD, canvas/UI, dnd5e v2 rolls), emits a uniform {ts, hook, args} envelope. No domain interpretation — consumers query the stream. See docs/HOOK_CONTRACT.md.",
|
||||
"version": "0.3.0",
|
||||
"description": "Foundry VTT v14-only module: generic Foundry hook facade. Subscribes to every relevant Foundry hook (combat, document CRUD, canvas/UI, dnd5e v2 rolls), emits a uniform {ts, hook, args} envelope. No domain interpretation — consumers query the stream. See docs/HOOK_CONTRACT.md.",
|
||||
"version": "0.4.0",
|
||||
"library": true,
|
||||
"manifestPlusVersion": "1.2.0",
|
||||
"authors": [
|
||||
@@ -12,7 +12,7 @@
|
||||
}
|
||||
],
|
||||
"compatibility": {
|
||||
"minimum": 13,
|
||||
"minimum": 14,
|
||||
"verified": 14
|
||||
},
|
||||
"relationships": {
|
||||
@@ -23,7 +23,7 @@
|
||||
"esmodules": ["scripts/main.js"],
|
||||
"url": "https://git.homelab.local/kaykayyali/hooks-lib",
|
||||
"manifest": "https://git.homelab.local/kaykayyali/hooks-lib/raw/branch/main/module.json",
|
||||
"download": "https://git.homelab.local/kaykayyali/hooks-lib/raw/branch/main/foundry-hooks-lib-0.3.0.zip",
|
||||
"download": "https://git.homelab.local/kaykayyali/hooks-lib/raw/branch/main/foundry-hooks-lib-0.4.0.zip",
|
||||
"readme": "https://git.homelab.local/kaykayyali/hooks-lib/blob/main/README.md",
|
||||
"changelog": "https://git.homelab.local/kaykayyali/hooks-lib/commits/main",
|
||||
"bugs": "https://git.homelab.local/kaykayyali/hooks-lib/issues",
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
{
|
||||
"name": "foundry-hooks-lib",
|
||||
"version": "0.3.0",
|
||||
"version": "0.4.0",
|
||||
"private": true,
|
||||
"description": "Foundry VTT module: generic Foundry hook facade. Library-only — no UI, no settings, no domain interpretation. v0.2.0 implements HOOK_CONTRACT.md and tests/PLAN.md.",
|
||||
"description": "Foundry VTT v14-only module: generic Foundry hook facade. Library-only — no UI, no settings, no domain interpretation. v0.4.0 implements HOOK_CONTRACT.md and tests/PLAN.md.",
|
||||
"main": "scripts/main.js",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
|
||||
@@ -1,15 +1,20 @@
|
||||
// scripts/internal/anti-corruption.js
|
||||
//
|
||||
// HOOK_CONTRACT.md §9-§10: absorb Foundry rename + arity churn.
|
||||
// HOOK_CONTRACT.md §9-§10: absorb Foundry hook shape churn so
|
||||
// consumers see stable envelope.hook names and a documented
|
||||
// args[] shape.
|
||||
//
|
||||
// §9 Hook rename mapping: a Foundry v13 fire of renderChatLog produces
|
||||
// an envelope with hook === "renderChatInput"; a v14 fire of
|
||||
// renderChatInput produces the same. The envelope hook name is
|
||||
// always the modern (v14) name.
|
||||
// v0.3.0 is Foundry v14 only (per tests/PLAN.md file header). v0.2.0
|
||||
// supported both v13 and v14; v0.3.0 narrows to v14. The dual v13
|
||||
// `renderChatLog` listener is dropped, and arg-normalization shapes
|
||||
// assume v14's arity. If a future v14 micro-release renames a hook
|
||||
// again, add the mapping here.
|
||||
//
|
||||
// §9 Hook rename mapping: the envelope.hook name is always the v14
|
||||
// name. v13 mapping is out of scope.
|
||||
//
|
||||
// §10 Arg normalization: for hooks with unstable arity, pad/truncate
|
||||
// to a documented shape. Consumers can rely on args[N] regardless of
|
||||
// Foundry version.
|
||||
// to a documented shape. Consumers can rely on args[N].
|
||||
//
|
||||
// This module exports the *normalization functions* and the
|
||||
// per-hook arg shape definitions. The dispatcher in envelope.js
|
||||
@@ -20,38 +25,29 @@ import { getEntryForRawName } from "./registered-hooks.js";
|
||||
// Arg shape per envelope name. undefined = no normalization
|
||||
// (the args array is passed verbatim from Foundry).
|
||||
//
|
||||
// Each shape is a function (rawArgs, foundryVersion?) -> normalizedArgs.
|
||||
// foundryVersion is optional; absent means "don't version-conditional."
|
||||
// Each shape is a function (rawArgs) -> normalizedArgs.
|
||||
//
|
||||
// v0.2.0 documents shapes for: combatStart, combatEnd, combatTurn,
|
||||
// v0.3.0 documents shapes for: combatStart, combatEnd, combatTurn,
|
||||
// combatRound, preUpdateActor, updateActor, preUpdateToken,
|
||||
// updateToken, dnd5e.rollAttackV2, dnd5e.rollDamageV2.
|
||||
|
||||
export const ARG_SHAPES = {
|
||||
// combatStart(combat, updateData) — arity 2. Stable.
|
||||
// combatStart(combat, updateData) — arity 2. Stable in v14.
|
||||
combatStart: (args) => normalizeArity(args, 2),
|
||||
|
||||
// combatEnd(combat) — arity 1. Stable in v14. v13 sometimes passed
|
||||
// (combat, updateData); we normalize to (combat, updateData).
|
||||
// combatEnd(combat) — arity 1. Stable in v14.
|
||||
combatEnd: (args) => normalizeArity(args, 2),
|
||||
|
||||
// combatTurn(combat, updateData, updateOptions) — v14. v13 sometimes
|
||||
// passed (combat, updateData, combatantId). Normalize to 3 args;
|
||||
// the third is whichever Foundry provided.
|
||||
// combatTurn(combat, updateData, updateOptions) — arity 3. Stable in v14.
|
||||
combatTurn: (args) => normalizeArity(args, 3),
|
||||
|
||||
// combatRound(combat, updateData, updateOptions) — v14. v13 passed
|
||||
// (combat, updateData, roundNum). Normalize to 4 args:
|
||||
// [combat, updateData, roundNum ?? updateOptions, updateOptions]
|
||||
// This is the §10 example shape. The third arg is always the round
|
||||
// number; the fourth is options.
|
||||
// combatRound(combat, updateData, updateOptions) — arity 3 in v14.
|
||||
// Normalized to 4 args: [combat, updateData, updateOptions.round, updateOptions]
|
||||
// The third arg is always the round number; the fourth is options.
|
||||
// v13's (combat, updateData, roundNum) shape is out of scope.
|
||||
combatRound: (args) => {
|
||||
const out = [args[0], args[1], null, args[2] ?? null];
|
||||
if (args.length >= 3 && typeof args[2] === "number") {
|
||||
// v13 shape: round num is the third arg.
|
||||
out[2] = args[2];
|
||||
} else if (args.length >= 3 && args[2] && typeof args[2] === "object") {
|
||||
// v14 shape: third arg is options; the round number lives there.
|
||||
if (args.length >= 3 && args[2] && typeof args[2] === "object") {
|
||||
out[2] = args[2].round ?? null;
|
||||
}
|
||||
return out;
|
||||
|
||||
@@ -95,7 +95,7 @@ export const HOOK_REGISTRY = [
|
||||
// --- Chat & rolls ---
|
||||
{ envelope: "createChatMessage", mode: "async", raw: ["createChatMessage"] },
|
||||
{ envelope: "renderChatMessage", mode: "sync", raw: ["renderChatMessage"] },
|
||||
{ envelope: "renderChatInput", mode: "sync", raw: ["renderChatInput", "renderChatLog"] },
|
||||
{ envelope: "renderChatInput", mode: "sync", raw: ["renderChatInput"] },
|
||||
{ envelope: "dnd5e.rollAttackV2", mode: "async", raw: ["dnd5e.rollAttackV2"] },
|
||||
{ envelope: "dnd5e.rollDamageV2", mode: "async", raw: ["dnd5e.rollDamageV2"] },
|
||||
|
||||
|
||||
@@ -1,8 +1,18 @@
|
||||
# hooks-lib test plan — v0.3.0
|
||||
# hooks-lib test plan — v0.4.0
|
||||
|
||||
**Status:** Implemented. Smoke (554/554) + Playwright (30/30) + perf (6/6)
|
||||
**Scope:** Foundry v14 only. v0.3.0 does not test v13 compatibility;
|
||||
the anti-corruption layer is reduced to v14-only normalization (no
|
||||
dual v13/v14 hook subscription). v0.2.0 supported both; v0.3.0 narrows
|
||||
to v14 because the only consumer (battle-focus) is v14.
|
||||
|
||||
**Status:** Implemented. Smoke (546/546) + Playwright (30/30) + perf (6/6)
|
||||
all green as of 2026-06-20. The § Definition of done release gate is met.
|
||||
|
||||
The smoke-test assertion count went from 554 to 546 when v0.4.0 dropped
|
||||
the v13-only `renderChatLog` and v13-round-num assertions (8 fewer
|
||||
v13-specific assertions). v0.3.0 was the rename + Playwright test;
|
||||
v0.4.0 narrows to v14 only.
|
||||
|
||||
**Drives:** `tests/verify-hooks-lib.mjs` (no-Foundry smoke),
|
||||
`tests/verify-hooks-lib-foundry.mjs` (Playwright against a live
|
||||
Foundry v14 instance), and `tests/perf.mjs` (perf budget).
|
||||
@@ -116,18 +126,22 @@ A throwing consumer callback does not break the dispatch chain.
|
||||
|
||||
### Section E — Anti-corruption
|
||||
|
||||
**Hook rename mapping (§9):**
|
||||
- A Foundry v13 fire of `renderChatLog` produces an envelope with
|
||||
**Hook rename mapping (§9):** the library subscribes to the v14 hook
|
||||
names and emits a stable `envelope.hook` name. Example mappings (v0.3.0):
|
||||
|
||||
- A Foundry v14 fire of `renderChatInput` produces an envelope with
|
||||
`hook === "renderChatInput"`.
|
||||
- A Foundry v14 fire of `renderChatInput` produces the same.
|
||||
- A Foundry v13 `combatEnd` (when fired) AND a Foundry v14
|
||||
`updateCombat` with `active: false` both produce envelopes with
|
||||
`hook === "combatEnd"` (normalized).
|
||||
- A Foundry v14 `updateCombat` with `active: false` produces an envelope
|
||||
with `hook === "combatEnd"` (normalized from the raw updateCombat
|
||||
with active→inactive transition).
|
||||
- A Foundry v14 `dnd5e.rollAttackV2` produces `envelope.hook ===
|
||||
"dnd5e.rollAttackV2"`. (v1 `dnd5e.rollAttack` is not supported in
|
||||
v0.3.0; v13 in general is out of scope per the file header.)
|
||||
|
||||
**Arg normalization (§10):**
|
||||
- For every hook in §6 with documented arg-shape normalization,
|
||||
firing with raw Foundry args produces an `args` array matching the
|
||||
documented shape, regardless of Foundry version.
|
||||
firing with raw Foundry v14 args produces an `args` array matching the
|
||||
documented shape.
|
||||
- The exact normalization shapes live in `docs/HOOK_ARG_SHAPES.md`.
|
||||
v0.3.0 ships shapes for: `combatStart`, `combatEnd`, `combatTurn`,
|
||||
`combatRound`, `preUpdateActor`, `updateActor`, `preUpdateToken`,
|
||||
@@ -177,10 +191,12 @@ Beyond Section D's basic cases:
|
||||
- **System-specific derived events.** That's the adapter's test
|
||||
plan. hooks-lib's tests verify the adapter *protocol* (registration,
|
||||
matching, lifecycle) but not the adapter's *content*.
|
||||
- **Foundry-version compatibility beyond the latest two releases.**
|
||||
v0.3.0 tests Foundry v13.351 and v14.364. Older versions are
|
||||
"best effort" — the anti-corruption layer should handle them, but
|
||||
no CI gate.
|
||||
- **Foundry v13 compatibility.** v0.3.0 is Foundry v14 only. The
|
||||
anti-corruption layer in v0.2.0 absorbed both v13 and v14 hook
|
||||
renames; v0.3.0 narrows to v14. The dual-subscription
|
||||
`renderChatInput` + `renderChatLog` listener is now just
|
||||
`renderChatInput`. Older versions of Foundry are "best effort" — not
|
||||
a CI gate, not in the test plan.
|
||||
- **Real Foundry runtime for the smoke test.** The no-Foundry smoke
|
||||
test stubs `Hooks`, `game`, `ui`. It runs in <2s. Real-Foundry
|
||||
verification is the Playwright test (§ Playwright run below).
|
||||
@@ -199,8 +215,9 @@ A v0.3.0 release is "done" when:
|
||||
2. **`npm test` exits 0** in the no-Foundry smoke runner. Runs in
|
||||
<2s.
|
||||
3. **`npm run test:foundry` exits 0** against a live Foundry v14
|
||||
instance with a representative world (3 actors, Bard-vs-Goblin
|
||||
fixture reused from battle-focus's test helper). Runs in <30s.
|
||||
instance with a representative world (the battle-focus v0.6.x
|
||||
`hello-world-demo` world works). Runs in <30s. v13 is not
|
||||
supported (see file header).
|
||||
4. **`npm run lint` exits 0** (if we adopt a linter; otherwise skip).
|
||||
5. **Both pass on the Hermes shell** (Windows, git-bash, Node 18+).
|
||||
CI portability is a stretch goal, not a gate.
|
||||
@@ -210,14 +227,14 @@ A v0.3.0 release is "done" when:
|
||||
|
||||
---
|
||||
|
||||
## Test files (v0.3.0)
|
||||
## Test files (v0.4.0)
|
||||
|
||||
| File | Purpose |
|
||||
|---|---|
|
||||
| `tests/verify-hooks-lib.mjs` | No-Foundry smoke. Sections A–F (F's perf-measurement subset that doesn't require Foundry). Runs in <2s. Replaces v0.1.0's `verify-hooks-lib.mjs`. |
|
||||
| `tests/verify-hooks-lib-foundry.mjs` | Playwright against a live Foundry. Loads the library as a Foundry module, asserts `mod.api.isReady() === true`, fires one synthetic `updateActor` and one `dnd5e.rollAttackV2` (stubbed at the Foundry level), asserts the library captures both. Runs in <30s. |
|
||||
| `tests/verify-hooks-lib.mjs` | No-Foundry smoke. Sections A–F (F's perf-measurement subset that doesn't require Foundry). Runs in <2s. v0.4.0 is v14-only — v13-specific assertions are dropped. |
|
||||
| `tests/verify-hooks-lib-foundry.mjs` | Playwright against a live Foundry v14. Loads the library as a Foundry module, asserts `mod.api.isReady() === true`, fires synthetic `updateActor` + `dnd5e.rollAttackV2` + creates a real combat, asserts envelopes flow through. 30 assertions. Runs in <15s. |
|
||||
| `tests/perf.mjs` | The performance budget measurement. Runs in <5s. Called from the smoke runner or standalone. |
|
||||
| `tests/test-helpers.mjs` | Shared stubs and Foundry helpers. Updates the v0.1.0 helper to expose the new Foundry hook stubbing. |
|
||||
| `tests/test-helpers.mjs` | Shared stubs and Foundry helpers. The no-Foundry smoke stubs `Hooks`, `game`, `ui`. |
|
||||
|
||||
The smoke test is the gate for PRs. The Foundry test is the gate
|
||||
for releases. Performance test runs weekly or on demand.
|
||||
|
||||
@@ -384,39 +384,34 @@ async function mainTest() {
|
||||
assert("E.1c: updateCombat round-change does NOT synthesize combatInactive", inactiveSeenC === null);
|
||||
uE1c();
|
||||
|
||||
// E.2: renderChatInput is registered for BOTH v13 (renderChatLog) and v14 names.
|
||||
assert(
|
||||
"E.2: renderChatLog (v13) is in installed raw hooks",
|
||||
listInstalledRawHooks().includes("renderChatLog")
|
||||
);
|
||||
// E.2: renderChatInput is registered (v14 only; v13's renderChatLog
|
||||
// was supported in v0.2.0 but is dropped in v0.3.0 per the plan's
|
||||
// v14-only scope).
|
||||
assert(
|
||||
"E.2: renderChatInput (v14) is in installed raw hooks",
|
||||
listInstalledRawHooks().includes("renderChatInput")
|
||||
);
|
||||
assert(
|
||||
"E.2: renderChatLog (v13) is NOT in installed raw hooks",
|
||||
!listInstalledRawHooks().includes("renderChatLog")
|
||||
);
|
||||
|
||||
// E.3: both produce envelope.hook === "renderChatInput".
|
||||
// E.3: v14 fire produces envelope.hook === "renderChatInput".
|
||||
let chatInputSeen = [];
|
||||
const uE3 = subscribe("renderChatInput", (env) => chatInputSeen.push(env.hook));
|
||||
Hooks.callAll("renderChatInput", { id: "m1" }, {}, "u1");
|
||||
Hooks.callAll("renderChatLog", { id: "m2" }, {}, "u1");
|
||||
await new Promise((r) => setTimeout(r, 10));
|
||||
assertEq("E.3: both v13 and v14 chat hooks produce envelope.hook='renderChatInput'", chatInputSeen, ["renderChatInput", "renderChatInput"]);
|
||||
assertEq("E.3: v14 renderChatInput produces envelope.hook='renderChatInput'", chatInputSeen, ["renderChatInput"]);
|
||||
uE3();
|
||||
|
||||
// E.4: arg normalization. combatRound v13 shape: (combat, updateData, roundNum).
|
||||
// v14 shape: (combat, updateData, updateOptions). Normalized to 4 args.
|
||||
let roundArgsV13 = null;
|
||||
const uE4a = subscribe("combatRound", (env) => { roundArgsV13 = env.args; });
|
||||
Hooks.callAll("combatRound", { id: "c1" }, {}, 3, "u1");
|
||||
await new Promise((r) => setTimeout(r, 10));
|
||||
assertEq("E.4a: combatRound v13 shape normalizes round num to args[2]", roundArgsV13?.[2], 3);
|
||||
uE4a();
|
||||
|
||||
// E.4: arg normalization. v14 combatRound shape: (combat, updateData, updateOptions).
|
||||
// v0.3.0 is v14-only; the v13 round-num position is no longer
|
||||
// exercised. round number comes from updateOptions.round.
|
||||
let roundArgsV14 = null;
|
||||
const uE4b = subscribe("combatRound", (env) => { roundArgsV14 = env.args; });
|
||||
Hooks.callAll("combatRound", { id: "c1" }, {}, { round: 5 }, "u1");
|
||||
await new Promise((r) => setTimeout(r, 10));
|
||||
assertEq("E.4b: combatRound v14 shape normalizes round num to args[2]", roundArgsV14?.[2], 5);
|
||||
assertEq("E.4: combatRound v14 shape normalizes round num to args[2]", roundArgsV14?.[2], 5);
|
||||
uE4b();
|
||||
|
||||
// ----- Section G — System adapter loading deeper -----
|
||||
@@ -522,7 +517,7 @@ function syntheticArgsFor(rawName) {
|
||||
if (rawName === "changeSidebarTab") return [{}];
|
||||
if (rawName === "getSceneControlButtons") return [[]];
|
||||
if (rawName === "renderChatMessage") return [{ id: "m1" }, {}, {}];
|
||||
if (rawName === "renderChatInput" || rawName === "renderChatLog") return [{}, {}, {}];
|
||||
if (rawName === "renderChatInput") return [{}, {}, {}];
|
||||
if (rawName === "renderJournalPageSheet") return [{}, {}, {}];
|
||||
if (rawName === "initializePointSourceShaders") return [{}];
|
||||
if (rawName === "rtcSettingsChanged") return [{}, {}];
|
||||
|
||||
Reference in New Issue
Block a user