MeridiansMeridians

Merge resolution — Streams + Notes → Merge → Graph → Arc [Flow]

From the Meridians Wiki · Public · Maintained · joint

The Merge task closes the present-day layer. On the domain's cadence it folds every mature Stream and every ready Note into canon through one group Merge that synthesises a Reasoning Graph (opt-in) and continues the story with a new Arc. It is autonomous — always armed, no per-fold approval. The operator steers it earlier and coarser: designate a Stream's outcome in the Merges area before the window, flip the input switches, set the cadence, or merge early. Deterministic, in-pass, audit-critical, and reversible (branch + version).

flowchart TB
    Streams(["open Streams<br/>(present-day belief, held by a perspective)"])
    Notes(["ready Notes<br/>(the operator's authored input)"])
    Streams -->|"streamMaturity()"| Mature
    Mature{"mature?<br/>decisive (logit margin ≥ τ) ·<br/>committed · saturating"}
    Mature -->|"no — contested/volatile/dormant"| Wait(["stay open — keep gathering evidence"])
    Mature -->|"yes"| Gather
    Notes -->|"unlocked, non-empty"| Gather

    Designate(["operator PRE-MERGE designation<br/>(Merges area, before the window)"]) -.->|"selectedOutcomes<br/>overrides the engine lean"| Gather

    Gather["**buildMergeProposal** — the in-pass group basis<br/>ALL mature Streams + ALL ready Notes"]
    Gather --> Merge

    subgraph Merge["Merge — the fold into canon (one pass, one merge, one arc)"]
        direction TB
        Fold["resolve every Stream's stance +<br/>fold every ready Note as note-inputs"]
        Graph["**buildMergeGraph** → SavedReasoningGraph<br/>(OPT-IN: only when config.mergeGraph)"]
        Fold --> Graph
    end

    Merge -->|"COMMIT_MERGE_ARC (atomic, pinned-basis revalidated)"| Arc["**new Arc** stamped basisMergeIds<br/>(Notes lock to the merge; basis change ⇒ clean abort, nothing stranded)"]
    Arc -->|"Merge folded into a Thread"| Canon(["canon — the long-horizon layer"])

Invariants

  • Autonomous — no approval gate. A Merge is always armed; the engine never leaves a standing directive and no Story asks the user to approve a fold. The merge-applied Story is a readout, not an action card. Control is the cadence, the Stream/Note/Graph switches, pre-merge outcome designation, and branch/version reversal.
  • One pass, one merge, one arc. A single run gathers ALL mature Streams + ALL ready Notes (buildMergeProposal) and folds them into ONE Merge → ONE Arc. There is no two-tick propose/consume and no notes-only fallback.
  • Operator designation is respected, then cleared. A pre-window outcome designation is a staged directive carrying selectedOutcomes; collectMergeDesignations reads it, mergeFromStreams applies it over the engine lean, and the pass RESERVES→FINALIZES it so it clears (no stale re-apply, no Watch-chain over-fire).
  • Maturity is deterministic, not a judgement call. streamMaturity ripens a Stream on a decisive logit margin (≥ STANCE_TAU_CLOSE) OR a settled category (committed / saturating). Contested, volatile, developing, and dormant are not ripe.
  • Never strands. COMMIT_MERGE_ARC revalidates the pinned Stream/Note basis; if it moved under the merge the pass aborts cleanly — Streams stay open, Notes stay unlocked, and the next cadence rebuilds and retries.
  • One Merge, one Graph (opt-in). When config.mergeGraph is set, mergeGraphId(mergeId) is deterministic — a Merge owns exactly one Reasoning Graph, synthesised from its resolved outcomes + priors, which later grounds Positions (projection-anatomy). Off by default (the CRG is the most expensive step).
  • basisMergeIds records continuity per branch. The generated Arc stamps which merges extended continuity on this branch. A fork deep-copies the ledger (forkLedger) with fresh ids + origin back-links.

Where it lives: src/lib/core/merging.ts (maturity), src/lib/core/program/merge.ts (group basis · eligible streams/notes · designations), src/lib/server/ops/handlers/program-merge.ts (runLoopMerge, the autonomous fold), src/lib/core/merges.ts (buildMergeGraph · forkLedger · basisMergeIds), src/lib/core/reducer/domain-reducer/slices/merge.ts (COMMIT_MERGE_ARC). Task cadence: program-loop; the three layers it moves belief between: three-layers. Engine identifier stays tutor; surfaced as Merge.