Context
T2.10 of the #13349 map — the leaf the create-module spine currently dead-ends without: #14655 (PR #14678) produces a validated blueprint and #14656 (PR #14682) can record what exists, but nothing yet carries an ACCEPTED blueprint into a live component and keeps the registry truthful over its lifecycle.
The Problem
The shipped widget childapp (apps/agentos/childapps/widget/view/ViewportController.mjs) already enforces the load-bearing invariant: ONE create path — widgets enter the stage via the container add → insert seam, the same seam a Neural-Link create_component drives, so provenance projection works identically for in-app and external creations. The generalized create module must join that seam, not build a parallel one. Today the childapp's v1 grammar (parseEditRequest/validateRequest) and the generalized route/validator/registry are disconnected islands.
The Fix
A create-module accept unit (apps/agentos/view/create/util/ per the recorded module convention) that:
- Takes an accepted blueprint (the route's output — never re-validates creation; one validator, two call sites) and instantiates it through the stage container
add() path, deriving the component config from the registered schema (grid@1 first — the childapp's grid mapping generalized, never forked).
- On the stage
insert event, writes registerCreated({instanceId, blueprintSchema, title, blueprintSnapshot, paneRef}) — the registry becomes truthful at the same moment the provenance projection fires.
- Routes follow-up mutations through
validateMutation(currentSnapshot, mutation) (merge-then-validate; the registry snapshot is the current-blueprint argument), applies the accepted merged blueprint to the live instance, then markMutated.
- Wires dispose →
markDisposed (record kept; resolution stops seeing it).
Refusals stay data end-to-end: an accept-path failure (unknown schema at instantiation time, dead stage ref) returns the same bounded {accepted, reason, stage} vocabulary — never a throw into the render path.
Acceptance Criteria
Out of Scope
Pane chrome / chat surface (SSOT-gated views) · live NL wiring (the injected generate leaf) · T4 persistence · retiring the childapp's v1 parseEditRequest/validateRequest (follow-up leaf once this path is proven).
Blocked-by
PR #14678 (#14655 route + validator) and PR #14682 (#14656 registry) — this leaf imports both modules. First-claim: @neo-fable (warm files, same-session lane continuity); claimable by anyone if my queue shifts.
Related
Parent #13349 (T2.10) · #14655/#14656 (the two modules this joins) · #14644 (the safety contract, two-sided) · #14642 (module convention) · #13361 (the mutation mechanism whose product face this completes) · apps/agentos/childapps/widget/view/ViewportController.mjs (the ONE-create-path invariant this generalizes).
Origin Session ID: b9b95ac6-42f5-47a3-b58f-6071f79657e8
Retrieval Hint: "accept path blueprint instantiation stage insert seam registry lifecycle one create path"
Context
T2.10 of the #13349 map — the leaf the create-module spine currently dead-ends without: #14655 (PR #14678) produces a validated blueprint and #14656 (PR #14682) can record what exists, but nothing yet carries an ACCEPTED blueprint into a live component and keeps the registry truthful over its lifecycle.
The Problem
The shipped widget childapp (
apps/agentos/childapps/widget/view/ViewportController.mjs) already enforces the load-bearing invariant: ONE create path — widgets enter the stage via the containeradd → insertseam, the same seam a Neural-Linkcreate_componentdrives, so provenance projection works identically for in-app and external creations. The generalized create module must join that seam, not build a parallel one. Today the childapp's v1 grammar (parseEditRequest/validateRequest) and the generalized route/validator/registry are disconnected islands.The Fix
A create-module accept unit (
apps/agentos/view/create/util/per the recorded module convention) that:add()path, deriving the component config from the registered schema (grid@1first — the childapp's grid mapping generalized, never forked).insertevent, writesregisterCreated({instanceId, blueprintSchema, title, blueprintSnapshot, paneRef})— the registry becomes truthful at the same moment the provenance projection fires.validateMutation(currentSnapshot, mutation)(merge-then-validate; the registry snapshot is the current-blueprint argument), applies the accepted merged blueprint to the live instance, thenmarkMutated.markDisposed(record kept; resolution stops seeing it).Refusals stay data end-to-end: an accept-path failure (unknown schema at instantiation time, dead stage ref) returns the same bounded
{accepted, reason, stage}vocabulary — never a throw into the render path.Acceptance Criteria
add → insertseam (no parallel create path; the childapp's provenance invariant holds by construction).insert, mutated on accepted mutation, flipped on dispose — the registry is the ONE "what exists" source for the module.Out of Scope
Pane chrome / chat surface (SSOT-gated views) · live NL wiring (the injected
generateleaf) · T4 persistence · retiring the childapp's v1parseEditRequest/validateRequest(follow-up leaf once this path is proven).Blocked-by
PR #14678 (#14655 route + validator) and PR #14682 (#14656 registry) — this leaf imports both modules. First-claim: @neo-fable (warm files, same-session lane continuity); claimable by anyone if my queue shifts.
Related
Parent #13349 (T2.10) · #14655/#14656 (the two modules this joins) · #14644 (the safety contract, two-sided) · #14642 (module convention) · #13361 (the mutation mechanism whose product face this completes) ·
apps/agentos/childapps/widget/view/ViewportController.mjs(the ONE-create-path invariant this generalizes).Origin Session ID: b9b95ac6-42f5-47a3-b58f-6071f79657e8 Retrieval Hint: "accept path blueprint instantiation stage insert seam registry lifecycle one create path"