Summary
skills/reactor.api.txt is the canonical index agents use to discover the Reactor API surface, but it only catalogs five sections:
- Factories (
Microsoft.UI.Reactor.Factories.*)
- Modifiers (extension methods on
Element)
- Hooks (
RenderContext / Component)
- Theme tokens
- Enums
This leaves big swaths of public API undiscoverable from the index file, including (non-exhaustive):
- Properties / init-only fields on public records — e.g.
WindowSpec.Opacity, WindowSpec.NoActivate, WindowSpec.IgnorePointerInput, plus all the existing fields like WindowSpec.Title, MinWidth, Backdrop, etc.
- Instance methods on public classes — e.g.
ReactorWindow.SetOpacity, SetPosition, SetSize, SetNoActivate, SetIgnorePointerInput, Update, Mount, Activate, Hide, Show, Close, CenterOnScreen, …
- Public types themselves (records, sealed classes, structs) that aren't reachable via a Factories/Hooks/Modifiers method — e.g.
DockManager, DockTabGroup, DockSplit, WindowSpec, BackdropChoice, WindowKey, Command, …
- Constructors and overloads of public types
- Events on public classes — e.g.
ReactorWindow.Closing, Activated, Closed, DpiChanged
Motivating example
While working on PR #415 (feat/window-layered-attrs), I added three new init-only properties to WindowSpec and three matching instance methods on ReactorWindow. After committing, ran mur --regen-api — both copies of reactor.api.txt came back unchanged, because none of the new surface fits the five sections the index catalogs.
That's not a bug in the regen tool — it's a gap in what the index covers. The end result is that an agent picking up this codebase cold has no way to discover (a) the new APIs we just added, or (b) most of the existing window/docking/command surface, from the index alone.
Why it matters for agents
The Reactor docs deliberately push agents toward reactor.api.txt as the source of truth ("Source of truth: Reactor.dll public surface" — header of the file). The hope is that agents have a single curated catalog to look at instead of grepping the codebase. Today that promise is half-kept: factory-style fluent code is well-covered; everything else requires the agent to fall back to grep / Glob / opening Element.cs / etc.
This makes agent-driven work less reliable in three concrete ways:
- Missed APIs. An agent that doesn't realize
ReactorWindow.SetPosition exists may reach for a Win32 P/Invoke or a less-good workaround.
- Wrong abstractions. An agent that doesn't see a record's properties may invent a new helper instead of using the existing init-only field.
- Stale references. Agents trained on older versions can't easily verify whether
Foo.Bar still exists.
Possible directions (not prescriptive)
A few options, in increasing order of effort:
-
Document the gap. Update the reactor.api.txt header to be explicit about what's covered and what isn't, and point to the right fallback (e.g. "for public records / methods on classes, see src/Reactor/**/*.cs directly"). Cheapest fix, doesn't actually solve the discovery problem but stops false promises.
-
Add a sixth section: "Public types". Have Reactor.SignaturesGen emit a per-type catalog of constructors / properties / methods / events for every public, non-static, non-Factories type in Reactor.dll. Same toolchain, larger file. Risk: file size grows non-trivially.
-
Generate a structured API surface file (e.g. reactor.api.json or per-namespace markdown) that an agent can pull selectively. Roslyn's public API tracking convention (PublicAPI.Shipped.txt / PublicAPI.Unshipped.txt) is one well-trodden pattern; it also gives us PR-time review of breaking changes for free.
-
Augment with a /discover skill that lets an agent ask "what's the API for ReactorWindow?" and resolve against a generated catalog on demand. Higher-overhead but matches how agents tend to work.
Option 2 is the smallest change that meaningfully closes the gap. Option 3 has more long-term value but is a bigger lift.
Acceptance criteria
- An agent reading the canonical API index (whatever form it takes) can discover:
- Public properties / init-only fields on every public type
- Public instance methods on every public type
- Public events on every public type
- Constructors / overloads
- The regen pipeline catches new surface added in a PR (the
WindowSpec.Opacity example would have produced a diff on mur --regen-api)
- The file format remains diffable and reviewable in a PR (i.e. not just a binary symbol dump)
Summary
skills/reactor.api.txtis the canonical index agents use to discover the Reactor API surface, but it only catalogs five sections:Microsoft.UI.Reactor.Factories.*)Element)RenderContext/Component)This leaves big swaths of public API undiscoverable from the index file, including (non-exhaustive):
WindowSpec.Opacity,WindowSpec.NoActivate,WindowSpec.IgnorePointerInput, plus all the existing fields likeWindowSpec.Title,MinWidth,Backdrop, etc.ReactorWindow.SetOpacity,SetPosition,SetSize,SetNoActivate,SetIgnorePointerInput,Update,Mount,Activate,Hide,Show,Close,CenterOnScreen, …DockManager,DockTabGroup,DockSplit,WindowSpec,BackdropChoice,WindowKey,Command, …ReactorWindow.Closing,Activated,Closed,DpiChangedMotivating example
While working on PR #415 (
feat/window-layered-attrs), I added three new init-only properties toWindowSpecand three matching instance methods onReactorWindow. After committing, ranmur --regen-api— both copies ofreactor.api.txtcame back unchanged, because none of the new surface fits the five sections the index catalogs.That's not a bug in the regen tool — it's a gap in what the index covers. The end result is that an agent picking up this codebase cold has no way to discover (a) the new APIs we just added, or (b) most of the existing window/docking/command surface, from the index alone.
Why it matters for agents
The Reactor docs deliberately push agents toward
reactor.api.txtas the source of truth ("Source of truth: Reactor.dll public surface" — header of the file). The hope is that agents have a single curated catalog to look at instead of grepping the codebase. Today that promise is half-kept: factory-style fluent code is well-covered; everything else requires the agent to fall back togrep/Glob/ openingElement.cs/ etc.This makes agent-driven work less reliable in three concrete ways:
ReactorWindow.SetPositionexists may reach for a Win32 P/Invoke or a less-good workaround.Foo.Barstill exists.Possible directions (not prescriptive)
A few options, in increasing order of effort:
Document the gap. Update the
reactor.api.txtheader to be explicit about what's covered and what isn't, and point to the right fallback (e.g. "for public records / methods on classes, seesrc/Reactor/**/*.csdirectly"). Cheapest fix, doesn't actually solve the discovery problem but stops false promises.Add a sixth section: "Public types". Have
Reactor.SignaturesGenemit a per-type catalog of constructors / properties / methods / events for every public, non-static, non-Factories type inReactor.dll. Same toolchain, larger file. Risk: file size grows non-trivially.Generate a structured API surface file (e.g.
reactor.api.jsonor per-namespace markdown) that an agent can pull selectively. Roslyn's public API tracking convention (PublicAPI.Shipped.txt/PublicAPI.Unshipped.txt) is one well-trodden pattern; it also gives us PR-time review of breaking changes for free.Augment with a
/discoverskill that lets an agent ask "what's the API forReactorWindow?" and resolve against a generated catalog on demand. Higher-overhead but matches how agents tend to work.Option 2 is the smallest change that meaningfully closes the gap. Option 3 has more long-term value but is a bigger lift.
Acceptance criteria
WindowSpec.Opacityexample would have produced a diff onmur --regen-api)