From a69cef9b4ba1054898b642f96e4ab2801a1b4c40 Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 17 Jul 2026 13:56:38 +0000 Subject: [PATCH] D-MBX-A6 output overhaul: StrategyOutcome carrier retires the dead-store _reliability MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit StyleStrategy::plan() computed a style-conditioned reliability and discarded it (`let _reliability = …`) because PlanInput had nowhere to carry a cognitive outcome, and faking a KanbanMove/commit would be theatre. Add an honest carrier. - traits.rs: `StrategyOutcome { reliability: f32, intended_move: Option }` + additive `PlanInput.outcome: Option` (default None, threaded unchanged by every pass-through strategy). - style_strategy.rs: plan() now surfaces the reliability + an INTENDED move — Planning→CognitiveWork (a legal Rubicon edge), mailbox 0 / cycle 0 (the zero-fallback bootstrap owner, write-on-behalf, not as ourselves; the live owner rebinds on adoption), libet -550_000 (Σ-commit anchor), exec Elixir (the backend reliability_of actually ran). The plan itself stays a pure pass-through (out.plan.is_none() still asserted) — this is a SURFACE, not an emit/commit. - 6 in-crate PlanInput{} literals gain `outcome: None`; the other ~15 plan() impls return Ok(input) untouched. Gating: UNBLOCKED — no classid mint (pairs an existing f32 with the already-minted contract KanbanMove), not the OQ-11.7 five-phase cutover. Deferred: thread the outcome OUT of compose_and_execute, promote StrategyOutcome to contract::kanban on first cross-bridge read, and the owner-consume/advance edge. Tests: 216 lib + 4 probe green; clippy -D warnings exit 0; fmt clean. Board: EPIPHANIES E-STRATEGY-OUTCOME-CARRIER-1, STATUS_BOARD D-MBX-A6-P3b, D-MBX-COMPLETION-MAP, AGENT_LOG. Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_01Awg6TXocHcwTtc6eGsHcdD --- .claude/board/AGENT_LOG.md | 9 ++ .claude/board/D-MBX-COMPLETION-MAP.md | 3 + .claude/board/EPIPHANIES.md | 9 ++ .claude/board/STATUS_BOARD.md | 1 + crates/lance-graph-planner/src/compose.rs | 1 + .../src/strategy/gql_parse.rs | 2 + .../src/strategy/gremlin_parse.rs | 1 + .../src/strategy/sparql_parse.rs | 1 + .../src/strategy/style_strategy.rs | 91 ++++++++++++++++--- crates/lance-graph-planner/src/traits.rs | 26 ++++++ 10 files changed, 130 insertions(+), 14 deletions(-) diff --git a/.claude/board/AGENT_LOG.md b/.claude/board/AGENT_LOG.md index 2090b90fb..67b4b1488 100644 --- a/.claude/board/AGENT_LOG.md +++ b/.claude/board/AGENT_LOG.md @@ -1,3 +1,12 @@ +## 2026-07-17 — D-MBX-A6-P3b output-overhaul carrier (StrategyOutcome on PlanInput) — planner-internal, shipped + +- **Task:** retire the `StyleStrategy::plan()` dead-store `_reliability` onto an honest carrier (the D-MBX-A6 output overhaul), the next unblocked plateau after P5a (jc battery, #709/#710). +- **Design:** one background Opus design agent produced the apply-ready spec (carrier type + exact 6-site edit list + backward-compat proof for the other ~15 `plan()` impls + gating verdict UNBLOCKED). Implemented on the main thread. +- **Deliverable:** `StrategyOutcome{reliability: f32, intended_move: Option}` in `planner::traits`; additive `PlanInput.outcome: Option<…>` (default None); `StyleStrategy::plan()` surfaces reliability + a bootstrap intended move (`Planning→CognitiveWork`, mailbox 0 / cycle 0, `libet -550_000`, `exec Elixir`) without mutating the plan. 6 in-crate `PlanInput{}` literals updated; all other strategies pass-through untouched. +- **Tests:** `plan_is_pure_passthrough…` rewritten → `plan_surfaces_outcome_without_mutating_the_plan` (plan still None; outcome shape + legal-edge asserted). `cargo test -p lance-graph-planner` 216 lib + 4 probes green; `cargo clippy -p lance-graph-planner -- -D warnings` exit 0; fmt clean. +- **Gating:** UNBLOCKED (no classid mint; not the OQ-11.7 five-phase cutover). Deferred: compose thread-out, contract-promote of `StrategyOutcome`, owner-consume/advance. +- **Board:** EPIPHANIES `E-STRATEGY-OUTCOME-CARRIER-1` prepended; STATUS_BOARD `D-MBX-A6-P3b` row; D-MBX-COMPLETION-MAP tee-append. Branch `claude/review-claude-board-files-nhqgx1`; PR pending. + ## 2026-07-15 — cross-repo forensic audit (q2 session) — rung-2 two-144s split + third 0–9 ladder filed as deltas onto E-RUNG-CONTENT-LADDER-1 - **Fleet:** 5-agent read-only evidence sweep (before/after `1a11038` API shape, contract StyleFamily design, D-TSC-1 spec/governance coverage, five-tables divergence reconstruction, cross-repo consumer+CI survey) + main-thread verification greps. A second 4-agent sweep (per-hunk claim audit) was lost to a token wall — its two open checks (FieldModulation→plan-shape functional trace; full 38-file claim audit) remain UNRUN, not asserted. diff --git a/.claude/board/D-MBX-COMPLETION-MAP.md b/.claude/board/D-MBX-COMPLETION-MAP.md index 6947fae1c..1be0946a3 100644 --- a/.claude/board/D-MBX-COMPLETION-MAP.md +++ b/.claude/board/D-MBX-COMPLETION-MAP.md @@ -79,3 +79,6 @@ 3. **D-MBX-10** (version byte) — the foundation every cold/view consumer reads; pairs with OQ-11.5. 4. Then A2→A3 (hot-path expressivity + witness arc), surfacing OQ-1/OQ-2/OQ-11.2 for ratification as reached. 5. **D-MBX-9** stays BLOCKED on OQ-11.6 (surreal fork) — flag for user unblock; the `MailboxSoaView` borrow trait already lets it land with zero contract change once unblocked. + +## 2026-07-17 update — D-MBX-A6-P3b (output-overhaul carrier) SHIPPED +- **D-MBX-A6-P3b** — `StrategyOutcome { reliability, intended_move: Option }` carrier landed on `PlanInput.outcome` (planner-internal, additive). `StyleStrategy` retires the dead-store `_reliability` and SURFACES reliability + a **bootstrap** intended move (`Planning→CognitiveWork`, owner 0 / cycle 0, warden-BOOTSTRAP-OK) — no mutation, no commit, no advance. 216 lib + 4 probe tests green. **UNBLOCKED** (no mint, not the OQ-11.7 cutover). Next nodes still open: thread the outcome OUT of `compose_and_execute` (`compose_and_collect()` sibling), promote `StrategyOutcome` to `contract::kanban` on first cross-bridge read, and the owner-consume/advance edge (OQ-11.7). See EPIPHANIES `E-STRATEGY-OUTCOME-CARRIER-1`. diff --git a/.claude/board/EPIPHANIES.md b/.claude/board/EPIPHANIES.md index 9f14e3910..111855d1c 100644 --- a/.claude/board/EPIPHANIES.md +++ b/.claude/board/EPIPHANIES.md @@ -1,3 +1,12 @@ +## 2026-07-17 — E-STRATEGY-OUTCOME-CARRIER-1 — the planner's dead-store `_reliability` is retired onto an honest `PlanInput.outcome` carrier; StyleStrategy surfaces reliability + a *bootstrap* intended KanbanMove (D-MBX-A6 output overhaul, planner-internal slice) + +**Status:** SHIPPED (plateau D-MBX-A6-P3b; `crates/lance-graph-planner`, 216 lib + 4 probe tests green, clippy `-D warnings` exit 0). Partially closes the "emit edge" the 2026-05-30 de-theatred entry deferred — this is the SURFACE (carrier + intent), not the emit (owner-consume) and not the OQ-11.7 five-phase cutover. + +- **The finding:** `StyleStrategy::plan()` computed a style-conditioned reliability and threw it away (`let _reliability = …`) because the `plan()` return type `PlanInput { plan, context }` had nowhere to carry a cognitive outcome, and faking a `KanbanMove`/commit would be theatre (the exact dead-store the council flagged). The honest gap was a missing carrier, not a missing computation. +- **The fix:** additive `StrategyOutcome { reliability: f32, intended_move: Option }` on a new `PlanInput.outcome: Option<…>` (default `None`, threaded unchanged by every pass-through strategy — only 6 in-crate struct literals needed the field; the other ~15 `plan()` impls return `Ok(input)` untouched). `StyleStrategy` now writes its reliability + an **intended** move; the plan itself is still a pure pass-through (`out.plan.is_none()` still asserted — no mutation, no advance, no commit). +- **Bootstrap intent, not an emission:** the intended move is `Planning → CognitiveWork` (a legal Rubicon edge) with `mailbox = 0` / `witness_chain_position = 0` — the doctrinally-blessed zero-fallback bootstrap owner (v3-mailbox-warden **BOOTSTRAP-OK**, write-on-behalf, NOT as ourselves; the live `MailboxSoaOwner` rebinds them on adoption). `libet_offset_us = -550_000` (Σ-commit anchor), `exec = Elixir` (the backend `reliability_of` actually ran). Nothing consumes `intended_move` to mutate a live mailbox in this slice. +- **Gating: UNBLOCKED** — no new classid mint (pairs an existing `f32` with the already-minted contract `KanbanMove`), not the OQ-11.7 cutover. **Deferred next nodes:** thread the outcome OUT of `compose_and_execute` (a `compose_and_collect()` sibling), promote `StrategyOutcome` to `contract::kanban` when the kanban owner reads it across the `OrchestrationBridge`, and the owner-consume/advance edge (OQ-11.7). Cross-ref `E-RELIABILITY-NOT-VALIDITY`, `D-MBX-COMPLETION-MAP` A6-P3. + ## 2026-07-17 — E-JC-BATTERY-NO-NAN-CONTRACT-1 — the reliability battery's documented no-NaN contract was not enforced for non-finite input; two reviewers caught `Some(NaN)`/finite-garbage (follow-up to P5a) **Status:** SHIPPED (follow-up PR to #709; `crates/jc/src/reliability.rs`, +2 regression tests, 14 lib + 3 doctests green). Corrects a real gap in E-JC-IS-NOT-A-METRIC-BATTERY-1's shipped code, not that entry's framing (append-only — the merged entry stands). diff --git a/.claude/board/STATUS_BOARD.md b/.claude/board/STATUS_BOARD.md index 624ebefc4..10f68ed0c 100644 --- a/.claude/board/STATUS_BOARD.md +++ b/.claude/board/STATUS_BOARD.md @@ -818,6 +818,7 @@ Plan path: `.claude/plans/unified-soa-convergence-v1.md`. Handover `.claude/hand | D-MBX-A6-P1 | contract slice of D-MBX-A6: `kanban::{KanbanColumn, KanbanMove}` + `soa_view::{MailboxSoaView, MailboxSoaOwner}` + `StepDomain::Kanban` — the planner⟷ractor⟷surreal seam, zero-dep, no parallel DTO family | lance-graph-contract | 340 | HIGH | **Shipped** | #437 (merged 9161bd7); + `class_id` N1 hook ride-along | | D-MBX-A6-P2 | Rubicon lifecycle enforcement + exec-target tag: `KanbanColumn::{next_phases, can_transition_to, is_absorbing}` (the lifecycle DAG) + `MailboxSoaOwner::try_advance_phase` (checked, `RubiconTransitionError`) + `ExecTarget{Native,Jit,SurrealQl,Elixir}` on `KanbanMove` | lance-graph-contract | 120 | LOW | **In PR** | builds on P1; 489 lib tests (+4); downstream cargo-check clean; gates the ractor owner-impl + planner emit (P3) | | D-MBX-A6-P3a | StyleStrategy: thinking-style -> cluster -> mechanism -> recipe_kernels Tactic selection (planning substrate; carries tau JIT addr) | lance-graph-planner | 130 | LOW | **In PR** | #439; first cut of A6-P3 consumer wiring; planner now consumes contract recipes/styles; deferred: i4-32D decode, Outcome->Candidate, tau->JIT, membrane commit | +| D-MBX-A6-P3b | output overhaul: `StrategyOutcome{reliability, intended_move: Option}` carrier on `PlanInput.outcome`; StyleStrategy retires the dead-store `_reliability`, SURFACES reliability + a bootstrap intended move (Planning→CognitiveWork, owner 0, warden-BOOTSTRAP-OK) — plan still pure | lance-graph-planner | 130 | LOW | **In progress** | additive Option field (6 in-crate literals); UNBLOCKED (no mint, not OQ-11.7); deferred: compose thread-out + contract-promote + owner-consume; E-STRATEGY-OUTCOME-CARRIER-1 | | D-MBX-A6-P3-M1 | `Tactic::requires() -> ThoughtMask` + `ThoughtField`/`ThoughtMask` (checklist-as-data keystone): 34 tactics declare their ThoughtCtx field-reads; `covered_by` = reliability-coverage gate | lance-graph-contract | 120 | LOW | **In PR** | #439; the panel-recalibrated keystone (extraction not construction); makes P1/P7/P11 derived; teeth-test asserts masks varied not stub | | D-CLS-FM | `class_view`: FieldMask(u64 presence) + ClassView meta-DTO resolver trait + ClassProjection (the class flies ABOVE the SoA; labels resolved late from OGIT cache, zero in the bytes) — extends ObjectView, reuses class_id | lance-graph-contract | 270 | LOW | **Shipped** | #441 D-CLS contract foundation; OD-gates ratified; presence!=semantics (C2); N3 stable positions; 3 teeth-tests | | D-CLS-RES | `class_resolver`: `RegistryClassView` impls `ClassView` over the live OntologyRegistry — the ontology-side 'parser' (class_id -> shape, DOLCE resolved LATE via classify_odoo from the cache URI, memoized over the O(n) registry scan) | lance-graph-ontology | 200 | LOW | **Shipped** | #441 D-CLS; makes the contract trait live; field-set supplied (D-CLS audit deferred); 4 teeth-tests | diff --git a/crates/lance-graph-planner/src/compose.rs b/crates/lance-graph-planner/src/compose.rs index 23b1e3284..e4e344e35 100644 --- a/crates/lance-graph-planner/src/compose.rs +++ b/crates/lance-graph-planner/src/compose.rs @@ -14,6 +14,7 @@ pub fn compose_and_execute( let mut current = PlanInput { plan: None, context, + outcome: None, }; tracing::info!( diff --git a/crates/lance-graph-planner/src/strategy/gql_parse.rs b/crates/lance-graph-planner/src/strategy/gql_parse.rs index 3eb02a0ba..b09aeb1eb 100644 --- a/crates/lance-graph-planner/src/strategy/gql_parse.rs +++ b/crates/lance-graph-planner/src/strategy/gql_parse.rs @@ -222,6 +222,7 @@ mod tests { thinking_style: None, nars_hint: None, }, + outcome: None, }; let result = parser.plan(input, &mut arena).unwrap(); @@ -244,6 +245,7 @@ mod tests { thinking_style: None, nars_hint: None, }, + outcome: None, }; let result = parser.plan(input, &mut arena).unwrap(); diff --git a/crates/lance-graph-planner/src/strategy/gremlin_parse.rs b/crates/lance-graph-planner/src/strategy/gremlin_parse.rs index 6b7e20d43..8e3fd0d48 100644 --- a/crates/lance-graph-planner/src/strategy/gremlin_parse.rs +++ b/crates/lance-graph-planner/src/strategy/gremlin_parse.rs @@ -831,6 +831,7 @@ mod tests { thinking_style: None, nars_hint: None, }, + outcome: None, }; let result = gremlin.plan(input, &mut arena).unwrap(); diff --git a/crates/lance-graph-planner/src/strategy/sparql_parse.rs b/crates/lance-graph-planner/src/strategy/sparql_parse.rs index d0482e3da..68a37b1d6 100644 --- a/crates/lance-graph-planner/src/strategy/sparql_parse.rs +++ b/crates/lance-graph-planner/src/strategy/sparql_parse.rs @@ -914,6 +914,7 @@ mod tests { thinking_style: None, nars_hint: None, }, + outcome: None, }; let result = parser.plan(input, &mut arena).unwrap(); diff --git a/crates/lance-graph-planner/src/strategy/style_strategy.rs b/crates/lance-graph-planner/src/strategy/style_strategy.rs index 7afd66741..5e62400e2 100644 --- a/crates/lance-graph-planner/src/strategy/style_strategy.rs +++ b/crates/lance-graph-planner/src/strategy/style_strategy.rs @@ -29,12 +29,13 @@ //! Deferred: `Outcome`→`Candidate`/`KanbanMove` adapter, the JIT compile call, and the //! membrane commit path (see the D-MBX-COMPLETION-MAP / board). +use lance_graph_contract::kanban::{ExecTarget, KanbanColumn, KanbanMove}; use lance_graph_contract::recipe_kernels::{kernel, ThoughtCtx}; use lance_graph_contract::recipes::{Mechanism, Recipe, RECIPES}; use lance_graph_contract::thinking::{StyleCluster, ThinkingStyle}; use crate::ir::{Arena, LogicalOp}; -use crate::traits::{PlanCapability, PlanContext, PlanInput, PlanStrategy}; +use crate::traits::{PlanCapability, PlanContext, PlanInput, PlanStrategy, StrategyOutcome}; use crate::PlanError; /// Default thinking style when the `PlanContext` carries no explicit style. @@ -137,16 +138,22 @@ impl PlanStrategy for StyleStrategy { fn plan( &self, - input: PlanInput, + mut input: PlanInput, _arena: &mut Arena, ) -> Result { - // The style-conditioned reliability is the substrate output this strategy - // computes. It is NOT yet emitted as a KanbanMove — the planner cannot construct - // one until the D-MBX-A6 output overhaul; faking one here would be theatre (the - // exact dead-store the council flagged). So this slice computes the measurable - // honestly and leaves the plan untouched; the emit edge is the next, separate slice. - let _reliability = - Self::reliability_of(Self::resolve_style(&input.context), &input.context); + // Surface the style-conditioned reliability AND the lifecycle transition this + // planning-substrate strategy INTENDS — honestly, on the D-MBX-A6 carrier. This + // is NOT a commit and NOT a plan mutation: `input.plan` is left exactly as + // received, and the intended move is a *bootstrap intent* (owner 0, cycle 0, + // the zero-fallback ladder) that no one consumes to advance a live mailbox in + // this slice. It replaces the dead-store `let _reliability = …` the council + // flagged — the value now has an honest home instead of `_`. + let style = Self::resolve_style(&input.context); + let reliability = Self::reliability_of(style, &input.context); + input.outcome = Some(StrategyOutcome { + reliability, + intended_move: Some(Self::intended_move(style)), + }); Ok(input) } } @@ -177,6 +184,32 @@ impl StyleStrategy { } tc.confidence.clamp(0.0, 1.0) } + + /// The lifecycle transition a style-substrate strategy INTENDS, as a **bootstrap + /// intent** (not an emission). StyleStrategy runs in the Planning column (the + /// spawn/default state, [`KanbanColumn::default`]); having selected the style and + /// measured its reliability, the honest intent is the forward Rubicon crossing + /// `Planning → CognitiveWork` (a legal edge: + /// `KanbanColumn::Planning.can_transition_to(CognitiveWork)`), carrying the −550 ms + /// Σ-commit anchor (matches `soa_view` `advance_phase`, contract). + /// + /// Honestly-fillable fields: `from`/`to`/`libet_offset_us` (structural constants of + /// the crossing) and `exec` (the backend `reliability_of` actually ran = the + /// interpreted `recipe_kernels` layer = [`ExecTarget::Elixir`], per this module's + /// doc header). Bootstrap-sentinel fields: `mailbox = 0` (write-on-behalf of the + /// documented bootstrap owner, NOT as ourselves — the live owner rebinds it) and + /// `witness_chain_position = 0` (no live `current_cycle` exists at plan time; 0 is + /// the zero-fallback pre-cycle stamp the owner overwrites on adoption). + fn intended_move(_style: ThinkingStyle) -> KanbanMove { + KanbanMove { + mailbox: 0, + from: KanbanColumn::Planning, + to: KanbanColumn::CognitiveWork, + witness_chain_position: 0, + libet_offset_us: -550_000, + exec: ExecTarget::Elixir, + } + } } #[cfg(test)] @@ -286,10 +319,11 @@ mod tests { } #[test] - fn plan_is_pure_passthrough_until_emit_edge_lands() { - // Honest test: plan() computes reliability but does NOT yet mutate the plan - // (no KanbanMove emit until the D-MBX-A6 output overhaul). It must not error, - // and — explicitly — must leave the plan None as it received it (no theatre). + fn plan_surfaces_outcome_without_mutating_the_plan() { + // The plan itself stays a pure pass-through (no KanbanMove is *emitted*, no + // Rubicon advance) — but the reliability + intended move are now SURFACED on + // the D-MBX-A6 carrier instead of dead-stored (the `_reliability` the council + // flagged now has an honest home). let s = StyleStrategy; let mut arena = Arena::new(); let out = s @@ -298,9 +332,37 @@ mod tests { &mut arena, ) .expect("style strategy plan() must not error"); + // Plan untouched (no mutation, no theatre). assert!( out.plan.is_none(), - "plan() is a pure pass-through this slice — it computes reliability, emits nothing yet" + "plan() must not mutate the plan this slice" + ); + // Outcome surfaced honestly. + let o = out.outcome.expect("plan() must surface a StrategyOutcome"); + assert!((0.0..=1.0).contains(&o.reliability), "reliability in [0,1]"); + let mv = o + .intended_move + .expect("StyleStrategy intends a lifecycle move"); + // Bootstrap intent — not a live mailbox advance. + assert_eq!(mv.mailbox, 0, "write-on-behalf of the bootstrap owner (0)"); + assert_eq!( + mv.witness_chain_position, 0, + "no live cycle at plan time (zero-fallback)" + ); + assert_eq!(mv.from, KanbanColumn::Planning); + assert_eq!(mv.to, KanbanColumn::CognitiveWork); + assert!( + mv.from.can_transition_to(mv.to), + "intended edge must be a legal Rubicon transition" + ); + assert_eq!( + mv.libet_offset_us, -550_000, + "Σ-commit anchor on the crossing" + ); + assert_eq!( + mv.exec, + ExecTarget::Elixir, + "the backend reliability_of ran" ); } @@ -308,6 +370,7 @@ mod tests { PlanInput { plan: None, context, + outcome: None, } } } diff --git a/crates/lance-graph-planner/src/traits.rs b/crates/lance-graph-planner/src/traits.rs index c6235f20c..8e5af8593 100644 --- a/crates/lance-graph-planner/src/traits.rs +++ b/crates/lance-graph-planner/src/traits.rs @@ -3,6 +3,7 @@ #[allow(unused_imports)] // Node intended for strategy result wiring use crate::ir::{Arena, LogicalOp, LogicalPlan, Node}; use crate::PlanError; +use lance_graph_contract::kanban::KanbanMove; /// What kind of planning problem a strategy solves. #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] @@ -96,6 +97,27 @@ pub struct QueryFeatures { pub estimated_complexity: f64, } +/// The honest cognitive outcome a strategy SURFACES alongside the plan — the +/// D-MBX-A6 carrier. Additive: rides [`PlanInput`] (default `None`). A strategy +/// that computes a cognitive measurable writes it here instead of dead-storing it +/// (the `let _reliability = …` the council flagged, `style_strategy.rs`). +/// +/// This is a SURFACE, never a commit: `intended_move` is an *intent*, not an +/// advance of a live mailbox — the mailbox lifecycle is mutated only by the +/// owner's [`try_advance_phase`](lance_graph_contract::soa_view::MailboxSoaOwner::try_advance_phase), +/// a separate cognitive-shader-driver slice. Reliability is settledness +/// (NARS confidence family), NOT validity — see `E-RELIABILITY-NOT-VALIDITY`. +#[derive(Debug, Clone, Copy, PartialEq)] +pub struct StrategyOutcome { + /// Style-conditioned RELIABILITY of crystallising at this context, in `[0,1]`. + pub reliability: f32, + /// The lifecycle transition this strategy INTENDS (never emits). `None` when the + /// strategy has no lifecycle intent. A **bootstrap intent** (`mailbox 0`, + /// `cycle 0` — the zero-fallback ladder) is rebound to a live mailbox by the + /// D-MBX-A6 owner adapter; nothing consumes it to mutate a mailbox in this slice. + pub intended_move: Option, +} + /// Input/output for a strategy in the pipeline. #[derive(Debug)] pub struct PlanInput { @@ -103,6 +125,10 @@ pub struct PlanInput { pub plan: Option, /// Context (accumulated through pipeline). pub context: PlanContext, + /// Cognitive outcome accumulated through the pipeline (D-MBX-A6 carrier). + /// `None` until a strategy surfaces one; threaded unchanged by pass-through + /// strategies. Writing this NEVER mutates `plan`. + pub outcome: Option, } /// A composable planning strategy.