Skip to content

refactor: hoist scenario-template registry out of materializer orchestrator#334

Merged
jwulf merged 3 commits into
mainfrom
refactor/template-registry-333
May 21, 2026
Merged

refactor: hoist scenario-template registry out of materializer orchestrator#334
jwulf merged 3 commits into
mainfrom
refactor/template-registry-333

Conversation

@jwulf
Copy link
Copy Markdown
Member

@jwulf jwulf commented May 21, 2026

Closes #333. Follow-up to #332.

Problem

materializer/src/index.ts open-coded one emitTemplateSuites() block per scenario template (EdgeLifecycle, EntityLifecycle, UpdatedFieldVisibleOnReadBack, StateTransitionVisibleAfterAction) and buildCoverage() received a duplicate hardcoded templateOutputDirs map. Adding a template was three edits across two files — every site had to agree on name + output dir or coverage would silently skip a template the orchestrator emitted (or vice versa).

This was the coupling smell flagged during #332 review: the materializer claims to be config-agnostic, but its orchestrator hardcoded the template list.

Change

  • New materializer/src/templateRegistry.ts declares TEMPLATE_REGISTRY: readonly TemplateBinding[] — one entry per template, { name, outputDir }. Single source of truth.
  • materializer/src/index.ts now loops over the registry for wipe-and-emit and passes it straight into buildCoverage().
  • materializer/src/coverage.ts accepts templates: readonly TemplateBinding[] instead of templateOutputDirs: Record<string, string> — same semantics, one fewer place where the map can drift.
  • All four current templates share the same emitTemplateSuites renderer, so no emitter field is needed on TemplateBinding. Step 2 of refactor(materializer): decouple template emission + coverage from hardcoded template registry #333 (deriving the registry from the ABox) is deferred until a future template needs a different renderer.

Tests

  • New guard tests/codegen/template-registry.test.ts asserts symmetric equality between the active config's scenario-templates.json ABox and TEMPLATE_REGISTRY, plus that registry outputDirs are distinct. Catches the next class of drift the refactor opens up: ABox row without a registry entry (or vice versa) fails red.
  • Existing tests/codegen/coverage.test.ts (added in feat: suppress feature specs covered by scenario-template ontology #332) updated to the new signature.

Behaviour preservation

testsuite:generate against the pinned spec still reports:

Generated test suites for 117 endpoints (+70 variant suites, +26 lifecycle suites, -73 suppressed by scenario-template coverage)

All 633 tests pass; pipeline output for camunda-oca is unchanged.

Pre-push gate

  • ✅ Biome lint (0 diagnostics)
  • tsc --noEmit × 6 workspace tsconfigs
  • testsuite:generate + generate:request-validation (regen)
  • npm test (633 passed, 4 skipped)

…trator

Closes #333.

Before: `materializer/src/index.ts` open-coded one
`emitTemplateSuites()` block per template (EdgeLifecycle,
EntityLifecycle, UpdatedFieldVisibleOnReadBack,
StateTransitionVisibleAfterAction) and `buildCoverage()` received a
duplicate hardcoded `templateOutputDirs` map. Adding a template was
three edits across two files — every site had to agree on name +
output dir or coverage would silently skip a template the
orchestrator emitted (or vice versa).

After: a single `materializer/src/templateRegistry.ts` declares
`TEMPLATE_REGISTRY: readonly TemplateBinding[]`. The orchestrator
loops over it for both wipe-and-emit and the `buildCoverage()` call.
`buildCoverage` now takes `templates: readonly TemplateBinding[]`
directly instead of a name→dir Record. Adding a template is now one
entry in one file (plus the planner-side TBox + ABox edits).

A new L3-style guard in `tests/codegen/template-registry.test.ts`
asserts symmetric equality between the active config's
scenario-templates ABox and `TEMPLATE_REGISTRY` so an ABox row
without a registry entry (or vice versa) fails red — the next class
of drift this refactor opens up. The existing coverage tests
(`tests/codegen/coverage.test.ts`, added in #332) are updated to the
new signature.

Behaviour-preserving: pipeline output is unchanged
(testsuite:generate still reports `+26 lifecycle suites, -73
suppressed by scenario-template coverage` against the same pinned
spec). All 633 tests pass.
Copilot AI review requested due to automatic review settings May 21, 2026 04:50
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Refactors the materializer orchestrator to remove hardcoded scenario-template wiring by introducing a single template registry used for both template suite emission and coverage-based suppression.

Changes:

  • Added TEMPLATE_REGISTRY (template name + outputDir) as a single source of truth for scenario-template wiring.
  • Updated the orchestrator to iterate the registry for wipe-and-emit, and passed it directly to buildCoverage().
  • Updated coverage extraction API and tests to use the new registry-based templates input.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
tests/codegen/template-registry.test.ts Adds a guard test to enforce symmetry between the active config’s scenario-templates ABox and TEMPLATE_REGISTRY.
tests/codegen/coverage.test.ts Updates buildCoverage unit tests to pass templates instead of templateOutputDirs.
materializer/src/templateRegistry.ts Introduces the centralized registry of scenario templates (name + outputDir).
materializer/src/index.ts Replaces per-template emission and hardcoded coverage wiring with a loop over TEMPLATE_REGISTRY.
materializer/src/coverage.ts Changes buildCoverage to accept templates: readonly TemplateBinding[] and derives the name→outputDir lookup internally.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread tests/codegen/template-registry.test.ts
Comment thread materializer/src/templateRegistry.ts Outdated
@jwulf jwulf self-assigned this May 21, 2026
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 5 out of 5 changed files in this pull request and generated 3 comments.

Comment thread materializer/src/templateRegistry.ts Outdated
Comment thread materializer/src/coverage.ts Outdated
Comment thread tests/codegen/coverage.test.ts Outdated
- templateRegistry.ts: TBox is name-agnostic; only ABox + registry edits are mandatory when adding a new template (TBox/emitter changes only when shape changes).

- coverage.ts: clarify that suppression extends when included in the templates option (TEMPLATE_REGISTRY in production).

- coverage.test.ts: rename test to reference the templates option, since buildCoverage has no knowledge of TEMPLATE_REGISTRY.
@jwulf jwulf merged commit c312b41 into main May 21, 2026
2 checks passed
@jwulf jwulf deleted the refactor/template-registry-333 branch May 21, 2026 05:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

refactor(materializer): decouple template emission + coverage from hardcoded template registry

2 participants