Skip to content

docs(spec): add spec 048 — lazy, trimmable control registration#466

Merged
codemonkeychris merged 1 commit into
mainfrom
spec-048-control-registration-and-trimming
May 30, 2026
Merged

docs(spec): add spec 048 — lazy, trimmable control registration#466
codemonkeychris merged 1 commit into
mainfrom
spec-048-control-registration-and-trimming

Conversation

@codemonkeychris
Copy link
Copy Markdown
Collaborator

Summary

Adds spec 048, the design follow-on to spec 047. 047 made external control authoring possible (the V1 handler protocol + the Reactor.External.TestControl proof). 048 settles how registration should happen so it is automatic, lazy, and — the load-bearing requirement — does not defeat AOT trimming.

Design only — no implementation in this PR.

What it captures

The doc preserves the discussion and the resolution we converged on:

  • The core tension (§3) — pure-data elements + automatic registration + trimmability can't all hold, because the trimmer follows static references and can't see a runtime registry lookup.
  • Rejected approaches (§4) — per-host RegisterHandler, element self-description/cctor, [ModuleInitializer], and reflection discovery, each tied to the requirement it violates. (Notably: [ModuleInitializer] is a trimmer root that actively prevents trimming.)
  • Resolution (§5–7)factory-as-registration-link: the factory the app already calls carries the static element→handler reference and registers it lazily/once, so a handler + WinUI control is kept iff its factory is reachable. Two expressions:
    • Pattern A — static-cctor factory holder (hand-authored 3P controls).
    • Pattern B — generic Reg<TElement, TControl, THandler> whose per-closed-generic-type statics register once (the ~50-control built-in catalog, no Factories split).
  • Contract & migration (§8–11) — the ControlRegistry contract (idempotent, lock-free, roots nothing), dispatch precedence, the hot-path cost model (one predicted branch, zero alloc, zero lock), the built-in migration that dismantles RegisterV1BuiltInHandlers, the "no type-level aggregation on Factories" invariant, and the CI trim verification test.
  • Open questions & phasing (§12–13) — incl. the §13 Q17 duplicate-policy amendment, closing element ctors, and optionally source-generating the Reg<> touches.

Note for reviewers

The one item that needs a real ratification call is §12.1 — the duplicate-registration policy amends 047 §13 Q17 (global table → idempotent first-wins; explicit per-host API keeps the strict throw). That's a spec decision, not just an implementation detail.

🤖 Generated with Claude Code

Follow-on to spec 047. Settles how V1 control registration should happen so
it is automatic, lazy, and — the load-bearing requirement — does not defeat
AOT trimming. Captures the discussion and resolution:

- The pick-two-of-three tension (pure-data elements + automatic registration +
  trimmability can't coexist), grounded in the trimmer following static refs.
- Rejected approaches (per-host RegisterHandler, element self-description/cctor,
  [ModuleInitializer], reflection discovery) each tied to the requirement they
  violate.
- Resolution: factory-as-registration-link, with Pattern A (static-cctor factory
  holder for 3P controls) and Pattern B (generic Reg<E,C,H> scale pattern for the
  built-in catalog).
- ControlRegistry contract, dispatch precedence, hot-path cost model, built-in
  migration (dismantle RegisterV1BuiltInHandlers, keep Factories aggregation-free),
  trim verification test, open questions, and phasing.

Design only — no implementation.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@codemonkeychris codemonkeychris merged commit 54273c6 into main May 30, 2026
15 checks passed
@codemonkeychris codemonkeychris deleted the spec-048-control-registration-and-trimming branch May 30, 2026 07:49
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.

1 participant