You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Seam consolidation plan (converged 2026-08-06, red-teamed, maintainer decisions applied)
Maintainer decisions: one plan-epic (this issue); M2 order is seams then types (#69) then guard (#56); #76 lands standalone now; #78 is the first car (parse-reject makes the fallback consts dead before the Role car deletes them); #81 rides the builder car; #55 closed as landed in-crate; the downstream audit (item 1) starts immediately and gates the deletion bucket; item 8 (provider install deadline) is its own PR after the train and the audit.
Car order: #78 reject-blank-names -> item 2 builder-tail (+#81 clock exposure) -> item 5 BootEnv -> item 3 Role vocabulary (+#80 provider-subscription validation) -> item 4 load-path convergence -> item 6 cruft sweep -> item 7 SubscriptionPlan. Cars close #78, #81, #80 respectively; others are Part of this issue.
Ranked items (as analysed)
1. Single downstream-consumer audit (one grep pass, one keep/delete decision doc) [S] ~0 code; one decision doc
One pass over shepherd and the extension repos resolving every gated deletion the four lenses scattered: Ext = bounds and HostState.ext reads (decides RuntimeTypes::Ext + ExtState), impl SealedRuntimeTypes occurrences, engine_config quota/watch/status_poll accessors (docs already name a consuming service at engine_config.rs:486), actor.rs SupervisedStore/ActorSlot/ActorFault, build_provider_linker, IntoStaticStr on the four pub error enums (EngineConfigError/EnvVarError/DigestParseError/ParseError - Cargo.toml:28's rationale was downstream metric labels), test_utils Entry/ManifestSource From impls, ModuleId Ord/PartialOrd/AsRef, and AssembledRuntime pub-field changes (owned add_ons, PathBuf). Output is a single decision doc; expected outcomes per in-tree evidence: quota/watch KEEP, SupervisedStore KEEP, Ext axis KEEP (harness builder_with_ext/MockTypes at harness.rs:34-72,154,438 exists for downstream tests), the rest likely DELETE in a later coordinated bump. Runs in parallel with everything; only ranks first because items 2 and 8 consult it.
Depends on: none; can start immediately, in parallel with the t7/t8/docs cars
Issues: #50#51 (StorageError shape input), #54 (published test-utils surfaces); clears epic #83's deferred-decision residue
2. Builder-tail consolidation: one open_and_launch, delete bootstrap.rs + ComponentsStage + LaunchRuntime + runtime/limits.rs [M] -120 to -180
Collapse the three copy-pasted launch bodies (builder.rs:456, :515, :649) into one private fn open_and_launch(config, extensions, add_ons, source, clocks, components_builder) that each terminal stage calls; delete bootstrap.rs outright (zero workspace consumers; its one advertised capability is already the Prebuilt slots) and runtime/limits.rs (5 doc lines, zero code), retargeting the dispatch.rs:352 doc link; LaunchRuntime dies with bootstrap (single impl at builder.rs:143-148) - its body becomes an inherent async fn launch on AssembledRuntime. Dissolve ComponentsStage: ReadyBuilder gains add_ons defaulting to empty with optional with_add_ons, TypedBuilder::with_components returns ReadyBuilder directly (every non-preset caller passes .with_add_ons(&[]) - builder.rs:982, 1016, 1108, harness.rs:156). KEEP the generic chain slot and Runtime::ChainBuilder (harness injects Prebuilt(pool) at harness.rs:152 - that slot IS the test seam). The AssembledRuntime field flips (owned AddOns killing both add_on_refs blocks, Option) land here only if the item-1 audit clears the escape-hatch API; otherwise keep the refs and flip later. nexum-launch is unaffected (uses only RuntimeBuilder, nexum-launch/src/lib.rs:36-42).
Depends on: item 1 for the AssembledRuntime pub-field flips only (core merge proceeds regardless); first car of the train
Issues: none of #21/#22/#23/#47/#50/#51/#54/#67/#11 directly; pure post-#82 residue outside epic #83's supervisor scope
3. Role as the single role vocabulary + role-keyed telemetry helpers (pre-metric-rename) [M] -80 to -110
Promote lifecycle::Role supervisor-wide (supervisor/role.rs): fallback_name() absorbs MODULE_FALLBACK_NAME/PROVIDER_FALLBACK_NAME (prepass.rs:37-41); manifest_role()='provider' and claim_role()='adapter' stay as two recorded decisions - do NOT silently reword, ledger.rs claim messages and scenario.rs:517 assert these strings. RolePass becomes { role: Role, chains: Option<&ConfiguredChains> } with the adapter None explicitly commented pointing at #80, making #80's fix a 10-line slice (flip the Option + read manifest.subscriptions in load::provider). load_providers/load_modules fold into one closure-parameterised loop. Telemetry half: report_trap(role, name, &verdict, policy, last_error), report_restart_attempt, report_restart_outcome as macro_rules/fns matching on Role internally (compile-time field keys force the two-arm match, but written once) - lifecycle.rs:402-511 shrinks ~70 lines; dispatch_to's trap arm shares ONLY the poison-transition trio (warn+counter+gauge) via report_poison - the trap logs themselves differ in level and fields (dispatch.rs:291-301 error! vs lifecycle.rs:403-414 warn!) and stay separate. Normalise the {e:#}-vs-%e accident (lifecycle.rs:497-507) to one rendering. Zero behavior change.
Depends on: t7/t8 merged (lifecycle.rs churn); MUST merge before the shepherd_->nexum_runtime_ metric rename so the rename touches Role's const fns once (lifecycle.rs:190-209)
Issues: #80 (turns its fix into a 10-line slice), epic #83 residual (T6 Role const-table follow-through); adjacent #78 (fallback naming centralised)
4. Load-path convergence: shared boot/restart pipelines, Role-parameterised store build, one Seed [M] -90 to -130
The boot-vs-restart axis becomes the parameter, not the role. Extract: fresh_run_store(shared, name, seq, spec, role) used at all four store-build sites (load.rs:227-228, 379-383; lifecycle.rs:273-279, 345-351) - per the red-team's contradiction resolution, the services argument is replaced by a Role/StoreRole parameter so store::build itself owns module-gets-shared.services vs provider-gets-empty (load.rs:380-383's cycle comment becomes one match in one place; the linker-withholding half stays in build_provider_linker, acknowledged as unreachable by any layer move). instantiate_module(shared, linker, seed, run, store) shared by load::module and LoadedModule::revive; install_provider(...) shared by load::provider and LoadedProvider::revive; callers keep the dead-permanent-vs-defer policy VISIBLE at the two call sites (load.rs:159-162, 402-404 vs lifecycle.rs:372). Health::from_init(ok) replaces the twin conditionals (load.rs:293-297, 419-423). Merge ModuleSeed/ProviderSeed into Seed { artifact, spec, event_deadline } (load.rs:48-61) with Seed::instance taking (linker, sections, store, liveness) - the red-team's corrected 4-borrow signature, collapsing the twin 7-field ProviderInstance literals (load.rs:389-397, lifecycle.rs:354-362); seed-before-install ordering is borrow-clean (install borrows &seed.artifact.component, borrow ends at return). Drop the verified-dead boot-only refuel (load.rs:253-254; dispatch.rs:216 refuels per call) - micro behavior change, one PR-body line. NO deadline wrap here (that is item 8).
Depends on: item 3 (Role type used by store::build parameter); t7/t8 merged
Issues: epic #83 residual (completes #70's convergence where T3 deliberately left the duplicated skeletons load.rs:173-299 vs 303-425 visible)
5. boot_single: BootEnv bundle + shared wire_extensions behind a register_kinds flag [S] -30 to -50
boot_single and boot share one wire_extensions with a with_provider_kinds: bool parameter - the skip is load-bearing (provider_kinds errors on a serviceless kind, admission.rs:33-39), so it becomes a named argument instead of a copied divergence (mod.rs:132-141). The derived-at-call-site argument spread (builder.rs:187-199 vs mod.rs:81-88) collapses into a small BootEnv derived once from engine_cfg - mandatory, not optional: passing engine_cfg whole still leaves 8 parameters and does NOT clear the too_many_arguments allow (red-team correction to both lenses). builder.rs:181-215 shrinks to boot(engine, linker, env, components, extensions, clocks, source_override). Zero behavior change.
Depends on: sequenced after item 2 in the train (both edit builder.rs); no semantic dependency
Issues: #23 (smaller boot_single surface eases porting its e2e tests to the harness), epic #83 residual (T3 named-phases follow-through)
The audit-safe subset only: strip IntoStaticStr + serialize_all from the non-pub enums (LifecycleState, Role, FilterError) and fix the stale Cargo.toml:28 strum rationale; drop the inert allow attributes (mod.rs:202 cfg_attr - poisoned_count is pub so dead_code cannot fire; manifest/types.rs:70,165) and the unused DispatchOutcome Eq/PartialEq (consumed only via matches!); tighten Health/LifecycleState to pub(super)/private (referenced nowhere outside supervisor/); move the 17-item cfg(test) import ladder from supervisor/mod.rs:344-376 into tests/mod.rs and replace TestTypes/CoreTypes with preset::CoreRuntime + DefaultSupervisor = Supervisor (verified: BootScenario already defaults to CoreRuntime, scenario.rs:92 - the trait lens and cruft lens proposed this identically, one commit); delete the zero-call-site From impls in the test DSL EXCEPT Entry/ManifestSource (gated); rename the 'Sealed' docs to 'marker reserved for semver evolution' (lib.rs:20-24, runtime_types.rs:8, preset.rs:25) without deleting the traits. Follow-up commit: backoff_pause helper collapsing the five event_loop.rs retry blocks - with message + optional-field parameters, since the sites differ intentionally (module vs chain-only at 177-185, tail_block at 271-283); the shared contract is bump+sleep, not the log line. Everything downstream-visible stays out pending item 1.
Depends on: t7/t8 merged (the cfg(test) ladder and TestTypes live in supervisor/mod.rs and the test lattice); item 1 only to later harvest the gated bucket
Issues: #21 (test-lattice consolidation), #54 (test-utils surface hygiene, gated half deferred)
Give the supervisor one SubscriptionPlan projection { block_chains, chain_log_subs, extension_kinds, viable: {Nothing, DeadHoldSubs, Live} } computed with ONE health filter, fixing the extension-kind asymmetry (subscriptions.rs:23/40 filter dispatchable, :95-104 do not) and moving the builder.rs:288-304 bail policy onto the plan - safe because boot-dead is permanent (no Backoff exists at launch), but observable (an extension source that today opens and idles will no longer open): own test + PR-body line. Cursor half, in the red-team's amended form: TaggedChainLog carries a compact subscription id (index into a supervisor-owned Vec of cursor keys) - NOT a bare ModuleId->key lookup, which cannot disambiguate a module's multiple resume chain-log subscriptions (chainlog_cursor_key spans chain|address|sig, cursors.rs:134-149); ChainLogCursors re-keys to BTreeMap<ModuleId, BTreeMap<Arc, u64>> so T8's Arc identity reaches the mirror, and the lazy seed read (cursors.rs:70-72) folds into boot-time mirror pre-population. ChainLogResume folds into a slimmer ChainLogSub carrying its identity from birth.
Depends on: t8 merged (ModuleId Arc identity is load-bearing for the re-key); last car of the train
Issues: epic #83 residuals (subscriptions.rs/cursors.rs completion; the T8 Arc-to-mirror gap), #80 adjacent (plan is where its validation naturally lands); groundwork for #66's viable/health gauges
8. Provider install deadline (the one downstream-contract behavior change, own PR) [S code / M contract weight] +25 to +45 (wrap + contract doc + fixture test)
Wrap both kind.install call sites in with_dispatch_deadline (dispatch.rs:355-362), closing the hung-provider-init hole: a hung install in revive parks ALL dispatch (sweep runs at dispatch.rs:26-29/85). This is NOT a verbatim mirror of the module side - the module deadline bounds only call_init (load.rs:165; instantiate_async at :229 is outside it), whereas ProviderKind::install spans instantiation + guest init + extension wiring, so the wrap imposes a NEW cancel-safety contract on every downstream ProviderKind impl (both in-tree impls are test-only; production kinds live in shepherd): a timeout drops install mid-flight and may leave a half-registered actor in the extension service. Land with (a) the contract documented on ProviderKind::install, (b) a slow-host fixture test (modules/fixtures/slow-host exists), (c) a decision on a separate install-deadline knob vs reusing event_deadline. Providers gain event_deadline via item 4's Seed merge (limits_cfg.event_deadline() at load).
Depends on: item 4 (Seed carries event_deadline), item 1 (audit confirms downstream ProviderKind impls before the contract lands); strictly last, outside the train
Issues: #22 adjacent (the deadline test is exactly what the clock seam would speed up - note the insertion point upstream), epic #83/#70 residual (symmetry with the documented module rationale, load.rs:159-162)
Killed proposals
S1 Roster<S: Sweepable> collection type - single-consumer generic ceremony, net +10 LOC by its own estimate; the six health-filter counts are 4-line one-liners on module-only pub API (mod.rs:174-208, 302-316); re-propose only if Sync-lag gauge pair and progressing-vs-stuck chain health #66 supplies a second real consumer.
Role-generic Loaded / GAT extras on ProviderKind or Sweepable - the PR-89 T6 adjudication stands; all four lenses respected it and verification produced no new structural evidence to reopen it.
Chain-slot demotion + Runtime::ChainBuilder deletion (inside topology step 2) - the generic C slot IS the harness test seam (Prebuilt(pool) at harness.rs:152, test_utils/mod.rs:130); an enum special-case buys one type parameter at the cost of an asymmetric harness.
HostState::for_run move into host/ (topology step 6) - trades a 4-arg builder for a 7+-arg one and the linker-withholding half of the policy (store.rs:195-204) stays behind regardless; superseded by the Role-parameter form inside item 4.
RuntimeTypes::Ext axis + ExtState deletion - 'write-only in-tree' was misleading: the harness's builder_with_ext/MockTypes/ptr_eq seam (harness.rs:34-72, :154, :438) is a published downstream test surface; expected audit outcome KEEP, and deleting it would collapse RuntimeTypes to one axis with very large churn for -60..-100 LOC.
Sealed-marker trait deletion - breaks any downstream impl SealedRuntimeTypes for X {}; downgraded to the doc rename riding item 6, with actual deletion deferred to a coordinated downstream bump.
engine_config quota/watch/status_poll deletion (~200 LOC) - the accessor docs name a consuming service (engine_config.rs:486); expected audit outcome KEEP with a doc note; the real fix for the lib.rs charter tension is extension-owned config, out of scope.
actor.rs SupervisedStore/ActorSlot/ActorFault deletion (~55 LOC) - it is precisely the documented helper for the downstream install-impl ownership model (extension.rs:142-143 / :162-177); expected audit outcome KEEP.
Unified trap logging across dispatch and sweep - the arms differ in level AND fields (dispatch.rs:291-301 error! with chain/event/latency vs lifecycle.rs:403-414 warn!); only the poison-transition trio is shared, and that is absorbed into item 3.
Pub-surface strippings now (IntoStaticStr on the four pub error enums, ModuleId Ord/PartialOrd/AsRef, build_provider_linker re-export demotion, test_utils Entry/ManifestSource From impls) - downstream-visible API; parked in item 1's gated bucket rather than deleted in this pass.
Do not count the two flipped gated deletions (~255 LOC quota/watch + actor.rs) as expected savings anywhere - in-tree evidence says they are consumed.
Packaging (as analysed; superseded where the decisions header differs)
One jj stacked train of items 2->5->3->4->6->7 (sequential cars, each independently revertible and CI-green, mergiraf for conflicts), based on the merged tip AFTER the in-flight t7/t8/docs cars land - items 3, 4, 6, and 7 all edit lifecycle.rs/load.rs/supervisor test lattice that T7's test conversion and T8's ModuleId rename are still churning, and item 7 requires T8's Arc identity outright; basing earlier just buys rebase noise. Two things sit OUTSIDE the train: item 1 (the downstream audit) is a no-code decision doc that starts now, in parallel with the still-merging cars; item 8 (the install deadline) is deliberately its own independent PR after the train and after the audit, because it is the only change in the entire accepted set that alters a downstream contract (cancel-safety on ProviderKind::install) - it needs its own fixture test and PR-body declaration, exactly as the boot-refuel drop (inside item 4) and the extension-kind filter change (inside item 7) each need one declared line. Hard ordering constraint: item 3 must merge before the shepherd_->nexum_runtime_ metric rename lands, so the rename edits Role's const tables once (lifecycle.rs:190-209). Honest aggregate for the accepted set: roughly net -350 to -450 LOC, with the ~255 LOC of gated deletions explicitly excluded from that figure. A second wave (gated-bucket harvest per the audit doc, plus the #51-scoped StorageError/BootRefusal PR) follows as independent PRs, not cars of this train."
Seam consolidation plan (converged 2026-08-06, red-teamed, maintainer decisions applied)
Maintainer decisions: one plan-epic (this issue); M2 order is seams then types (#69) then guard (#56); #76 lands standalone now; #78 is the first car (parse-reject makes the fallback consts dead before the Role car deletes them); #81 rides the builder car; #55 closed as landed in-crate; the downstream audit (item 1) starts immediately and gates the deletion bucket; item 8 (provider install deadline) is its own PR after the train and the audit.
Car order: #78 reject-blank-names -> item 2 builder-tail (+#81 clock exposure) -> item 5 BootEnv -> item 3 Role vocabulary (+#80 provider-subscription validation) -> item 4 load-path convergence -> item 6 cruft sweep -> item 7 SubscriptionPlan. Cars close #78, #81, #80 respectively; others are Part of this issue.
Ranked items (as analysed)
1. Single downstream-consumer audit (one grep pass, one keep/delete decision doc) [S] ~0 code; one decision doc
One pass over shepherd and the extension repos resolving every gated deletion the four lenses scattered:
Ext =bounds and HostState.ext reads (decides RuntimeTypes::Ext + ExtState),impl SealedRuntimeTypesoccurrences, engine_config quota/watch/status_poll accessors (docs already name a consuming service at engine_config.rs:486), actor.rs SupervisedStore/ActorSlot/ActorFault, build_provider_linker, IntoStaticStr on the four pub error enums (EngineConfigError/EnvVarError/DigestParseError/ParseError - Cargo.toml:28's rationale was downstream metric labels), test_utils Entry/ManifestSource From impls, ModuleId Ord/PartialOrd/AsRef, and AssembledRuntime pub-field changes (owned add_ons, PathBuf). Output is a single decision doc; expected outcomes per in-tree evidence: quota/watch KEEP, SupervisedStore KEEP, Ext axis KEEP (harness builder_with_ext/MockTypes at harness.rs:34-72,154,438 exists for downstream tests), the rest likely DELETE in a later coordinated bump. Runs in parallel with everything; only ranks first because items 2 and 8 consult it.Depends on: none; can start immediately, in parallel with the t7/t8/docs cars
Issues: #50 #51 (StorageError shape input), #54 (published test-utils surfaces); clears epic #83's deferred-decision residue
2. Builder-tail consolidation: one open_and_launch, delete bootstrap.rs + ComponentsStage + LaunchRuntime + runtime/limits.rs [M] -120 to -180
Collapse the three copy-pasted launch bodies (builder.rs:456, :515, :649) into one private fn open_and_launch(config, extensions, add_ons, source, clocks, components_builder) that each terminal stage calls; delete bootstrap.rs outright (zero workspace consumers; its one advertised capability is already the Prebuilt slots) and runtime/limits.rs (5 doc lines, zero code), retargeting the dispatch.rs:352 doc link; LaunchRuntime dies with bootstrap (single impl at builder.rs:143-148) - its body becomes an inherent async fn launch on AssembledRuntime. Dissolve ComponentsStage: ReadyBuilder gains add_ons defaulting to empty with optional with_add_ons, TypedBuilder::with_components returns ReadyBuilder directly (every non-preset caller passes .with_add_ons(&[]) - builder.rs:982, 1016, 1108, harness.rs:156). KEEP the generic chain slot and Runtime::ChainBuilder (harness injects Prebuilt(pool) at harness.rs:152 - that slot IS the test seam). The AssembledRuntime field flips (owned AddOns killing both add_on_refs blocks, Option) land here only if the item-1 audit clears the escape-hatch API; otherwise keep the refs and flip later. nexum-launch is unaffected (uses only RuntimeBuilder, nexum-launch/src/lib.rs:36-42).
Depends on: item 1 for the AssembledRuntime pub-field flips only (core merge proceeds regardless); first car of the train
Issues: none of #21/#22/#23/#47/#50/#51/#54/#67/#11 directly; pure post-#82 residue outside epic #83's supervisor scope
3. Role as the single role vocabulary + role-keyed telemetry helpers (pre-metric-rename) [M] -80 to -110
Promote lifecycle::Role supervisor-wide (supervisor/role.rs): fallback_name() absorbs MODULE_FALLBACK_NAME/PROVIDER_FALLBACK_NAME (prepass.rs:37-41); manifest_role()='provider' and claim_role()='adapter' stay as two recorded decisions - do NOT silently reword, ledger.rs claim messages and scenario.rs:517 assert these strings. RolePass becomes { role: Role, chains: Option<&ConfiguredChains> } with the adapter None explicitly commented pointing at #80, making #80's fix a 10-line slice (flip the Option + read manifest.subscriptions in load::provider). load_providers/load_modules fold into one closure-parameterised loop. Telemetry half: report_trap(role, name, &verdict, policy, last_error), report_restart_attempt, report_restart_outcome as macro_rules/fns matching on Role internally (compile-time field keys force the two-arm match, but written once) - lifecycle.rs:402-511 shrinks ~70 lines; dispatch_to's trap arm shares ONLY the poison-transition trio (warn+counter+gauge) via report_poison - the trap logs themselves differ in level and fields (dispatch.rs:291-301 error! vs lifecycle.rs:403-414 warn!) and stay separate. Normalise the {e:#}-vs-%e accident (lifecycle.rs:497-507) to one rendering. Zero behavior change.
Depends on: t7/t8 merged (lifecycle.rs churn); MUST merge before the shepherd_->nexum_runtime_ metric rename so the rename touches Role's const fns once (lifecycle.rs:190-209)
Issues: #80 (turns its fix into a 10-line slice), epic #83 residual (T6 Role const-table follow-through); adjacent #78 (fallback naming centralised)
4. Load-path convergence: shared boot/restart pipelines, Role-parameterised store build, one Seed [M] -90 to -130
The boot-vs-restart axis becomes the parameter, not the role. Extract: fresh_run_store(shared, name, seq, spec, role) used at all four store-build sites (load.rs:227-228, 379-383; lifecycle.rs:273-279, 345-351) - per the red-team's contradiction resolution, the services argument is replaced by a Role/StoreRole parameter so store::build itself owns module-gets-shared.services vs provider-gets-empty (load.rs:380-383's cycle comment becomes one match in one place; the linker-withholding half stays in build_provider_linker, acknowledged as unreachable by any layer move). instantiate_module(shared, linker, seed, run, store) shared by load::module and LoadedModule::revive; install_provider(...) shared by load::provider and LoadedProvider::revive; callers keep the dead-permanent-vs-defer policy VISIBLE at the two call sites (load.rs:159-162, 402-404 vs lifecycle.rs:372). Health::from_init(ok) replaces the twin conditionals (load.rs:293-297, 419-423). Merge ModuleSeed/ProviderSeed into Seed { artifact, spec, event_deadline } (load.rs:48-61) with Seed::instance taking (linker, sections, store, liveness) - the red-team's corrected 4-borrow signature, collapsing the twin 7-field ProviderInstance literals (load.rs:389-397, lifecycle.rs:354-362); seed-before-install ordering is borrow-clean (install borrows &seed.artifact.component, borrow ends at return). Drop the verified-dead boot-only refuel (load.rs:253-254; dispatch.rs:216 refuels per call) - micro behavior change, one PR-body line. NO deadline wrap here (that is item 8).
Depends on: item 3 (Role type used by store::build parameter); t7/t8 merged
Issues: epic #83 residual (completes #70's convergence where T3 deliberately left the duplicated skeletons load.rs:173-299 vs 303-425 visible)
5. boot_single: BootEnv bundle + shared wire_extensions behind a register_kinds flag [S] -30 to -50
boot_single and boot share one wire_extensions with a with_provider_kinds: bool parameter - the skip is load-bearing (provider_kinds errors on a serviceless kind, admission.rs:33-39), so it becomes a named argument instead of a copied divergence (mod.rs:132-141). The derived-at-call-site argument spread (builder.rs:187-199 vs mod.rs:81-88) collapses into a small BootEnv derived once from engine_cfg - mandatory, not optional: passing engine_cfg whole still leaves 8 parameters and does NOT clear the too_many_arguments allow (red-team correction to both lenses). builder.rs:181-215 shrinks to boot(engine, linker, env, components, extensions, clocks, source_override). Zero behavior change.
Depends on: sequenced after item 2 in the train (both edit builder.rs); no semantic dependency
Issues: #23 (smaller boot_single surface eases porting its e2e tests to the harness), epic #83 residual (T3 named-phases follow-through)
6. Conservative cruft sweep (independently revertible commits) [M] ~-110
The audit-safe subset only: strip IntoStaticStr + serialize_all from the non-pub enums (LifecycleState, Role, FilterError) and fix the stale Cargo.toml:28 strum rationale; drop the inert allow attributes (mod.rs:202 cfg_attr - poisoned_count is pub so dead_code cannot fire; manifest/types.rs:70,165) and the unused DispatchOutcome Eq/PartialEq (consumed only via matches!); tighten Health/LifecycleState to pub(super)/private (referenced nowhere outside supervisor/); move the 17-item cfg(test) import ladder from supervisor/mod.rs:344-376 into tests/mod.rs and replace TestTypes/CoreTypes with preset::CoreRuntime + DefaultSupervisor = Supervisor (verified: BootScenario already defaults to CoreRuntime, scenario.rs:92 - the trait lens and cruft lens proposed this identically, one commit); delete the zero-call-site From impls in the test DSL EXCEPT Entry/ManifestSource (gated); rename the 'Sealed' docs to 'marker reserved for semver evolution' (lib.rs:20-24, runtime_types.rs:8, preset.rs:25) without deleting the traits. Follow-up commit: backoff_pause helper collapsing the five event_loop.rs retry blocks - with message + optional-field parameters, since the sites differ intentionally (module vs chain-only at 177-185, tail_block at 271-283); the shared contract is bump+sleep, not the log line. Everything downstream-visible stays out pending item 1.
Depends on: t7/t8 merged (the cfg(test) ladder and TestTypes live in supervisor/mod.rs and the test lattice); item 1 only to later harvest the gated bucket
Issues: #21 (test-lattice consolidation), #54 (test-utils surface hygiene, gated half deferred)
7. SubscriptionPlan projection + cursor subscription-identity closure [M] -30 to -60
Give the supervisor one SubscriptionPlan projection { block_chains, chain_log_subs, extension_kinds, viable: {Nothing, DeadHoldSubs, Live} } computed with ONE health filter, fixing the extension-kind asymmetry (subscriptions.rs:23/40 filter dispatchable, :95-104 do not) and moving the builder.rs:288-304 bail policy onto the plan - safe because boot-dead is permanent (no Backoff exists at launch), but observable (an extension source that today opens and idles will no longer open): own test + PR-body line. Cursor half, in the red-team's amended form: TaggedChainLog carries a compact subscription id (index into a supervisor-owned Vec of cursor keys) - NOT a bare ModuleId->key lookup, which cannot disambiguate a module's multiple resume chain-log subscriptions (chainlog_cursor_key spans chain|address|sig, cursors.rs:134-149); ChainLogCursors re-keys to BTreeMap<ModuleId, BTreeMap<Arc, u64>> so T8's Arc identity reaches the mirror, and the lazy seed read (cursors.rs:70-72) folds into boot-time mirror pre-population. ChainLogResume folds into a slimmer ChainLogSub carrying its identity from birth.
Depends on: t8 merged (ModuleId Arc identity is load-bearing for the re-key); last car of the train
Issues: epic #83 residuals (subscriptions.rs/cursors.rs completion; the T8 Arc-to-mirror gap), #80 adjacent (plan is where its validation naturally lands); groundwork for #66's viable/health gauges
8. Provider install deadline (the one downstream-contract behavior change, own PR) [S code / M contract weight] +25 to +45 (wrap + contract doc + fixture test)
Wrap both kind.install call sites in with_dispatch_deadline (dispatch.rs:355-362), closing the hung-provider-init hole: a hung install in revive parks ALL dispatch (sweep runs at dispatch.rs:26-29/85). This is NOT a verbatim mirror of the module side - the module deadline bounds only call_init (load.rs:165; instantiate_async at :229 is outside it), whereas ProviderKind::install spans instantiation + guest init + extension wiring, so the wrap imposes a NEW cancel-safety contract on every downstream ProviderKind impl (both in-tree impls are test-only; production kinds live in shepherd): a timeout drops install mid-flight and may leave a half-registered actor in the extension service. Land with (a) the contract documented on ProviderKind::install, (b) a slow-host fixture test (modules/fixtures/slow-host exists), (c) a decision on a separate install-deadline knob vs reusing event_deadline. Providers gain event_deadline via item 4's Seed merge (limits_cfg.event_deadline() at load).
Depends on: item 4 (Seed carries event_deadline), item 1 (audit confirms downstream ProviderKind impls before the contract lands); strictly last, outside the train
Issues: #22 adjacent (the deadline test is exactly what the clock seam would speed up - note the insertion point upstream), epic #83/#70 residual (symmetry with the documented module rationale, load.rs:159-162)
Killed proposals
impl SealedRuntimeTypes for X {}; downgraded to the doc rename riding item 6, with actual deletion deferred to a coordinated downstream bump.Packaging (as analysed; superseded where the decisions header differs)
One jj stacked train of items 2->5->3->4->6->7 (sequential cars, each independently revertible and CI-green, mergiraf for conflicts), based on the merged tip AFTER the in-flight t7/t8/docs cars land - items 3, 4, 6, and 7 all edit lifecycle.rs/load.rs/supervisor test lattice that T7's test conversion and T8's ModuleId rename are still churning, and item 7 requires T8's Arc identity outright; basing earlier just buys rebase noise. Two things sit OUTSIDE the train: item 1 (the downstream audit) is a no-code decision doc that starts now, in parallel with the still-merging cars; item 8 (the install deadline) is deliberately its own independent PR after the train and after the audit, because it is the only change in the entire accepted set that alters a downstream contract (cancel-safety on ProviderKind::install) - it needs its own fixture test and PR-body declaration, exactly as the boot-refuel drop (inside item 4) and the extension-kind filter change (inside item 7) each need one declared line. Hard ordering constraint: item 3 must merge before the shepherd_->nexum_runtime_ metric rename lands, so the rename edits Role's const tables once (lifecycle.rs:190-209). Honest aggregate for the accepted set: roughly net -350 to -450 LOC, with the ~255 LOC of gated deletions explicitly excluded from that figure. A second wave (gated-bucket harvest per the audit doc, plus the #51-scoped StorageError/BootRefusal PR) follows as independent PRs, not cars of this train."