Skip to content

Runs subcharts: registers the canonical handler - #40

Merged
johnnyt merged 2 commits into
mainfrom
se-4dt.4-subchart-handler-uptake
Aug 31, 2026
Merged

Runs subcharts: registers the canonical handler#40
johnnyt merged 2 commits into
mainfrom
se-4dt.4-subchart-handler-uptake

Conversation

@johnnyt

@johnnyt johnnyt commented Aug 31, 2026

Copy link
Copy Markdown
Member

Provenance

Pin

The statifier_blocks git pin moves 957ea91 -> 487cebf (sb main, the
commit documenting the shipped subchart handler). It is the fourth INTERIM
pin this dep has carried; the FINAL re-pin to a Hex requirement happens at
the operator's publish, per the se-p22 pattern. mix.lock and the pin test's
expectation move with it. No other dep line is touched.

What landed

  1. The handler is registered. StatifierExamples.Charts.Subchart uses
    the package's StatifierBlocks.Runtime.Subchart and supplies this host's
    two callbacks: resolve_chart/2, a document-id lookup over
    Charts.fixtures/0, and palette/0.
  2. The registration is a union, so the use moved.
    Statifier.Invoke.SyncHandler.Adapter writes invoke_types/0 and
    invoke_handlers/0 as plain definitions over its own handler list, so a
    module that uses it cannot also state a union including something that
    list does not hold. The use now lives in
    StatifierExamples.Charts.SyncAdapter and Charts joins the sync half
    with the subchart handler. The engine still writes the adapter; se-4dt.2's
    uptake is intact.
  3. The new fixture. priv/fixtures/signup_onboarding.json
    (bdoc_su_onboarding_demo): a parent whose one core.subchart names the
    wizard's document id and routes done / abandon / error.
  4. The pin (R-d). A created run's metadata gains a subcharts key -
    %{document id => content hash} - beside the existing fixture key. A
    core.subchart names its child by document id, which is stable across
    every revision of that child, so without this the record says nothing
    about which revision ran. This is the host-provenance concern
    StatifierBlocks.Core.Subchart's moduledoc names in as many words.
  5. The demo script gains beats 11 and 12, with the feed rows read off a
    real run rather than composed.

The retired warning (before / after)

Before, on main at da66f44, compiling signup_invitations through
Charts.Durable.compile/2:

%StatifierBlocks.Compiler.Finding{
  stage: :chart, block_id: "blk_si_invitee_signup",
  reason: {:no_registered_invoke_handler, "statifier_blocks:subchart"},
  message: "no handler registered for invoke type \"statifier_blocks:subchart\"",
  code: :no_registered_invoke_handler, severity: :warning, fault: :author}

After, on this branch, the same call: warnings: []. Both fixtures that name
a child chart (signup_invitations, signup_onboarding) compile with no
unregistered-handler finding at all, which
InvokeRegistryTest asserts over the pair. The test that used to refute
the registration is rewritten to the new truth rather than deleted, with the
old reading quoted in its comment.

Two limits, both reported rather than worked around

  • Single level only. Statifier.Session starts a child session with
    invoked_by:, a seeded datamodel and the parent's observer options, and
    not with the parent's :invoke_handlers - filed upstream as
    st-pvpz. So a child chart's own <invoke>s reach a session with no
    handler for them, myapp:* calls included. The wizard child therefore
    starts and sits at its first step; it cannot finish inside the parent, and
    a nested subchart would not run at all. The fixture is written to that
    limit, says so in its own description, and a test walks the shipped set to
    prove no document used as a child names a subchart of its own. This is the
    engine's to fix, not this app's to route around (CLAUDE.md's reference-embedder
    rule).
  • Durable runs refuse, by name. {:start_child, _, _} is executed by
    Statifier.Session and by nothing else; the durable driver performs an
    <invoke> through this app's dispatch: fun, which routes sync handlers.
    So Charts.dispatch/3 refuses the type as
    {:error, {:durable_subchart_unsupported, type}} rather than letting it
    fall through to :unknown_invoke_type, which would be untrue in the way
    that matters to a reader of the feed - the type is registered, and a
    session answers it. Durable subcharts are ruling R-e's follow-up. The
    widened refusal shape surfaced in Durable.reason/1 exactly where that
    function's own comment predicted it would.

LOC delta

Area + - net
lib/ 377 43 +334
test/ 419 48 +371
docs/, priv/, mix.* 173 9 +164
total 969 100 +869

Net-positive, unlike E1-E3: this child adds a capability rather than moving
plumbing upstream. The lib/ half is 178 lines of new handler module, 43 of
adapter relocation, and the rest moduledoc on two seams that did not exist.

Gate

Full mix quality green on this HEAD: format, compile (warnings as errors),
credo, dependencies, dialyzer, 225 of 225 tests, 75.6% coverage (floor 70).
Doctor, Sobelow and Gettext are the manifest's declared
not-applicable skips. Every new test was sabotaged by hand and shown red;
the mutations are noted above each one.

Registers `statifier_blocks:subchart` with a resolver over this app's
own fixture list, which retires the standing Findings-1 warning on
`signup_invitations`: both fixtures that name a child chart now compile
with no unregistered-handler finding at all.

The registration is a union rather than one list. The sync adapter's
`use` moves to `StatifierExamples.Charts.SyncAdapter` because the macro
writes `invoke_types/0` and `invoke_handlers/0` over its own handlers,
and the subchart handler is not a sync call; `Charts` joins the two.
`StatifierExamples.Charts.Subchart` supplies the package's two host
callbacks - a document-id lookup over the fixtures, and the palette.

`signup_onboarding` is the new fixture: a parent that embeds the wizard
as a `core.subchart` and routes on the outcome. One level deep, because
a child session is started without the parent's invoke handlers
(st-pvpz), which the tests assert over the shipped set.

A created run records the child chart each subchart resolved to, keyed
by document id, beside the fixture key - the host-provenance pin
`StatifierBlocks.Core.Subchart` names, since a document id is stable
across every revision of the child.

A durable run refuses a subchart by name: starting a child chart has no
executor in the durable driver, and durable subcharts are a follow-up.
The demo script gains the two beats, read off a real run.

Moves the statifier_blocks pin to the commit carrying the handler.

Refs: se-4dt.4
The registry comment beside `Statifier.Supervisor` still said the
adapter is generated into `StatifierExamples.Charts` and that the module
is this app's one `Statifier.Invoke.Handler`. Since se-4dt.4 the
generated adapter lives in `StatifierExamples.Charts.SyncAdapter`, and
`StatifierExamples.Charts` joins it with
`StatifierExamples.Charts.Subchart`. Prose only.

Refs: se-4dt.4
@johnnyt
johnnyt merged commit 07bceda into main Aug 31, 2026
1 check passed
@johnnyt
johnnyt deleted the se-4dt.4-subchart-handler-uptake branch August 31, 2026 18:39
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