---
id: IR-10
title: "plexus-macros: drop IR-3's static-child suppression (now redundant after IR-4)"
status: Complete
type: implementation
blocked_by: [IR-4, IR-21]
unlocks: []
severity: Low
target_repo: plexus-macros
---

## Problem

IR-3 introduced a transitional workaround in `plexus-macros`: when the macro synthesizes `plugin_children()` (the CHILD-8 inferred-hub path), static-child `MethodSchema` entries are suppressed to avoid tripping plexus-core's `validate_no_collisions` check. Without the suppression, a method named `body` with `role: StaticChild` in `methods` and a `ChildSummary` named `body` in `children` would panic plexus-core at `PluginSchema` validation — the names collide.

IR-4 fixed the underlying cause: `validate_no_collisions` was relaxed to recognize that static-child-method ↔ derived-child-summary pairs with the same name are the same thing by construction, not a collision. The panic is gone.

The suppression in `plexus-macros` is therefore redundant. It hides role-tagged entries from the `methods` list that downstream consumers (synapse, hub-codegen, any IR reader) expect to be present. Removing the suppression makes the macro's output consistent with the IR epic's promise: every `#[plexus_macros::child]` method appears in `methods` with its role tag, regardless of whether `plugin_children()` is hand-written, synthesized, or derived.

## Context

Location: the suppression lives in `plexus-macros/src/codegen/mod.rs`, in the codepath that assembles the `MethodSchema` list — roughly a helper named `schema_child_methods` or equivalent (IR-3's commit `b6285a8` for the exact location). The branch is gated on whether `synthesize_plugin_children()` is active.

After this ticket: the macro emits static-child `MethodSchema` entries unconditionally. Dynamic-child entries were already emitted unconditionally; they remain unchanged. `plugin_children()` synthesis and hand-written overrides both continue to work unchanged (IR-4's `validate_no_collisions` relaxation means the collision is not a panic for any of these configurations).

## Required behavior

| Input | Generated `methods` list |
|---|---|
| Activation with only `#[method]` methods | Unchanged — all methods with `role: Rpc`. |
| Activation with `#[child]` static methods, no `plugin_children()` override | Each static method appears in `methods` with `role: StaticChild`. (Unchanged from today.) |
| Activation with `#[child]` static methods, synthesized `plugin_children()` (CHILD-8 inferred hub) | Each static method appears in `methods` with `role: StaticChild`. **Changed** — suppression removed. |
| Activation with `#[child]` static methods and hand-written `plugin_children()` | Each static method appears in `methods` with `role: StaticChild`. `plugin_children()` still drives `children` (unchanged). |
| Activation with `#[child]` dynamic method + `list`/`search` args | Method appears with `role: DynamicChild { list_method, search_method }`. (Unchanged from today.) |

No other behavior changes.

## Risks

| Risk | Mitigation |
|---|---|
| Some test (substrate or plexus-macros) was implicitly relying on the suppression and fails once static entries appear in `methods`. | Identified as acceptance criterion 3. If any test breaks, fix the test — the pre-IR-4 behavior was a workaround; role-tagged entries in `methods` are the correct post-IR state. |
| Existing trybuild `.stderr` fixtures need reblessing because post-IR-4 deprecation warnings on `PluginSchema.children` leak into compile output. | Out of scope for this ticket — tracked separately. This ticket does not bless stderr; if this ticket's changes alter stderr, call it out in the PR and defer the bless to the separate hygiene ticket. |
| Some consumer in the substrate workspace was reading `methods.len()` and expecting static children to be excluded. | Verified by acceptance criterion 2: substrate `cargo test` passes. If the exclusion is load-bearing for any consumer, that's a bug — the consumer should use `methods.iter().filter(|m| m.role == Rpc).count()` instead. |

## What must NOT change

- Dynamic-child `MethodSchema` emission is unchanged.
- Hand-written `fn plugin_children()` override continues to drive `PluginSchema.children`.
- Synthesized `plugin_children()` (CHILD-8 inferred hub) continues to drive `PluginSchema.children`.
- `ChildRouter::get_child` / `list_children` / `search_children` behavior is unchanged.
- All 16 substrate activations compile without source edits.
- Solar's golden snapshot (from IR-4, `plexus-core/tests/golden/solar.json`) either remains byte-identical OR the snapshot is reblessed in this ticket with a clear one-line diff (only the `methods` array gains the static-child entries; `children` is unchanged).

## Acceptance criteria

1. `cargo build -p plexus-macros` and `cargo test -p plexus-macros` succeed.
2. `cargo build -p plexus-substrate` and `cargo test -p plexus-substrate` succeed with no source edits to substrate activations.
3. A unit test or fixture in plexus-macros verifies that an activation with `#[child]` static methods and no `plugin_children()` override produces a `MethodSchema` list that includes each static child method with `role: StaticChild`. A second fixture verifies the same for an activation with synthesized `plugin_children()` (CHILD-8 inferred hub).
4. Solar's golden snapshot in `plexus-core/tests/golden/solar.json` is either byte-identical (if Solar's specific pattern doesn't hit the suppression branch) or reblessed with a documented minimal diff limited to the `methods` array.
5. The diff of this PR against `main` shows the removal of the suppression branch — a `grep` for the guard name (or equivalent conditional) returns zero matches in plexus-macros after the change.

## Completion

PR against plexus-macros. CI green in plexus-macros. Regression green in plexus-substrate. If the golden snapshot was reblessed, include the diff in the PR description and verify the change is limited to `methods` array additions. Status flipped from `Ready` to `Complete` in the same commit as the code.
