Files
2026-05-27 11:07:12 +02:00

3.2 KiB

Scrying Pool — Agent Instructions

FoundryVTT v14 module for GM camera visibility control. Ships as raw ES modules (no bundler). Entry: module.jsmodule.json:esmodules.

Commands (run in order: lint → typecheck → test → build)

Intent Command
Lint npm run lint
Typecheck npm run typecheck
Test (unit) npm run test
Test (watch) npm run test:watch
Build CSS npm run build
Release npm run release
E2E test npm test in tests/e2e/

Watch is brokennpm run watch outputs to dist/styles/ (gitignored) instead of styles/. Use npm run build manually.

Version source of truth: package.json; scripts/package.mjs copies it to module.json at release.

Architecture

  • module.js — wiring diagram ONLY. Imports, constructs with DI, registers hooks. Zero business logic. Never add logic here.
  • src/contracts/ — data contracts/DTOs. Must not import from any other src/ module.
  • src/utils/ — utilities. Must not import from any other src/ module.
  • src/core/ — business logic. May import from contracts/ and utils/ only.
  • src/foundry/FoundryAdapter.js is the sole gateway to game.* APIs. Same import restriction as core/.
  • src/core/src/foundry/ — never cross-import. Enforced by ESLint import/no-restricted-paths.
  • Constructor side-effect-free — no hooks/socket registration in constructors; call init() from Hooks.once('ready') in module.js.

Testing

  • Vitest with happy-dom, globals: false — always import describe, it, expect, vi explicitly.
  • Path aliases (vitest only): @src, @contracts, @utils, @tests.
  • Mock factory — always use createFoundryAdapterMock() from tests/helpers/foundryAdapterMock.js. No ad-hoc stubs.
  • Hooks is stubbed globally via vi.stubGlobal('Hooks', ...) in each test's beforeEach.
  • E2E tests live in tests/e2e/ with separate package.json. Need live FoundryVTT at https://localhost:31000 (user: gamemaster). Not run in CI.
  • @ts-nocheck is used at top of many test files — this is normal for this repo.

FoundryVTT specifics

  • Globals injected at runtime: Hooks, game, ui, canvas, foundry, CONFIG, CONST — listed as ESLint readonly globals.
  • Type checking (tsc --noEmit) only covers module.js. Source files are NOT typechecked.
  • Type defs from @league-of-foundry-developers/foundry-vtt-types (9.x) + local src/types/foundry-globals.d.ts.
  • CSS scoped under .scrying-pool, token vars prefixed --sp-*, compiled from LESS via npm run build.

CI & releases

  • Gitea (not GitHub) at uberwald.me/gitea/. CI uses RouxAntoine/checkout@v3.5.4.
  • CI: npm cinpm audit --productionnpm run lintnpm run typechecknpm run testnpm run build.
  • Release: triggered on tag publish, substitutes module.json URLs, creates module.zip, uploads via curl + Gitea API token.

Design docs

Full project history in _bmad-output/ — PRDs, architecture specs, epics, deferred work tracking. For deep context start with _bmad-output/planning-artifacts/architecture.md and _bmad-output/planning-artifacts/epics.md.