Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Match Visualization Plan

This chapter documents the planned visualization contract for a future match operator so the Mermaid and isometric views stay semantically aligned.

Problem Statement

The documentation renderer currently understands a narrow diagram DSL:

  • fn source() -> target
  • if expression -> target

That is enough for linear pipelines and threshold gates, but it does not yet express a true multi-arm match branch as one semantic node with ordered arms, fallthrough, and stable reflow behavior.

Canonical Sample

The operator contract should be driven by small, realistic examples instead of abstract syntax fragments. The baseline sample is a disposition router:

#![allow(unused)]
fn main() {
match result.disposition {
    Disposition::Unrecoverable => halt_pipeline,
    Disposition::Recoverable => repair_and_retry,
    Disposition::Advisory => record_note,
}
}

Equivalent workflow intent:

  • a single branching point reads result.disposition
  • each arm is declaration-ordered and labeled
  • terminal or review-heavy arms remain visually distinct

Mermaid Plan

Projection Rules

  • Compile one explicit match node, not three unrelated if nodes.
  • Preserve arm order from source.
  • Label every outgoing edge with the arm key.
  • Render a default edge when the source includes _ or else.
  • Keep the branch target node ids stable so diffs are readable across regenerations.

Sample 2D Layout

fn verify_result() -> match_result_disposition
match result.disposition => Disposition::Unrecoverable -> halt_pipeline
match result.disposition => Disposition::Recoverable -> repair_and_retry
match result.disposition => Disposition::Advisory -> record_note
fn repair_and_retry() -> requeue_validation
flowchart TD
    verify_result["verify_result"]
    match_result_disposition["match_result_disposition"]
    repair_and_retry["repair_and_retry"]
    requeue_validation["requeue_validation"]
    halt_pipeline["halt_pipeline"]
    record_note["record_note"]
    verify_result --> match_result_disposition
    repair_and_retry --> requeue_validation
    match_result_disposition -->|"Disposition::Unrecoverable"|halt_pipeline
    match_result_disposition -->|"Disposition::Recoverable"|repair_and_retry
    match_result_disposition -->|"Disposition::Advisory"|record_note

Mermaid Acceptance Criteria

  • arm labels must be the declared pattern names
  • the match node must render once even when there are many arms
  • adding a new arm should only add one new edge and one target node in the diff
  • Mermaid output should stay readable when an arm routes back into the main workflow

Isometric Plan

Placement Model

The isometric renderer should treat match as a structured fan-out node:

  • the match node sits on the main workflow spine
  • each arm receives a stable lane on the z axis by declaration order
  • the branch targets inherit the parent stage depth on x
  • terminal or review-heavy arms may get a small y lift to improve readability

Kasuari Constraint Sketch

  • x(match) == x(previous) + stage_gap
  • x(target_arm_n) >= x(match) + branch_gap
  • z(target_arm_n) == z(match) + arm_index * lane_gap
  • z(target_arm_default) should stay at the outermost lane so explicit arms keep their positions
  • x(rejoin) should be constrained after the widest branch target, not after the first branch target

Animated Reflow Goals

When the source changes:

  • inserting a new arm should push later lanes sideways instead of replacing the full scene
  • renaming an arm should preserve its lane if its identity key is unchanged
  • moving an arm in source order should animate the lane swap so the operator can see what changed
  • deleting an arm should collapse only the affected lane group

Sample Isometric Intent

fn verify_result() -> match_result_disposition
match result.disposition => Disposition::Unrecoverable -> halt_pipeline
match result.disposition => Disposition::Recoverable -> repair_and_retry
match result.disposition => Disposition::Advisory -> record_note
fn repair_and_retry() -> requeue_validation
flowchart TD
    verify_result["verify_result"]
    match_result_disposition["match_result_disposition"]
    repair_and_retry["repair_and_retry"]
    requeue_validation["requeue_validation"]
    halt_pipeline["halt_pipeline"]
    record_note["record_note"]
    verify_result --> match_result_disposition
    repair_and_retry --> requeue_validation
    match_result_disposition -->|"Disposition::Unrecoverable"|halt_pipeline
    match_result_disposition -->|"Disposition::Recoverable"|repair_and_retry
    match_result_disposition -->|"Disposition::Advisory"|record_note

Implementation Status

Completed

  • Single match node: Parser compiles one match node per expression, not scattered if nodes.
  • Arm order preservation: IndexMap in Rust and ordered Map in JS preserve declaration order.
  • Labeled edges: Every outgoing edge carries the arm key as its label.
  • Default arm detection: _, else, otherwise, default arms are flagged with is_default: true.
  • Stable identity keys: Node.identity_key enables identity-stable reflow across label changes.
  • Arm index tracking: Node.arm_index and Edge.arm_index carry declaration order.
  • Semantic role inference: Both Rust and JS infer roles from label keywords (ingest/validate/classify/review/reconcile/commit/decision/step).
  • Mermaid default annotation: Default arms rendered with (default) suffix.
  • Match-specific lane assignment in JS layout solver: Arms receive stable Z lanes from arm_index.
  • Default arm outer-lane placement: _/else arms render at the outermost lane.
  • Basic rejoin constraint: Simple rejoin points are placed after the widest branch and centered on the match node lane.

In Progress

  • Richer rejoin semantics: The live solver handles simple joins, but branch-local work and explicit rejoin syntax still need a stronger graph model.

Planned

  • Animated reflow: Inserting/deleting/moving arms should animate lane changes instead of snapping.
  • Explicit rejoin syntax: e.g. fn repair_and_retry() -> requeue_validation already implies rejoin; the parser should expose that intent directly.

The current live editor and mdBook preprocessor both accept the repeated-arm syntax above. The next implementation target is richer identity and placement semantics, not a second incompatible syntax.

Disposition Routing

Use this as the primary worked example in docs and tests:

#![allow(unused)]
fn main() {
match result.disposition {
    Disposition::Unrecoverable => halt_pipeline,
    Disposition::Recoverable => repair_and_retry,
    Disposition::Advisory => record_note,
}
}

Confidence Band Routing

This is the threshold analogue that should remain visually consistent with match:

#![allow(unused)]
fn main() {
match confidence_band {
    ConfidenceBand::High => commit_result,
    ConfidenceBand::Medium => queue_manual_review,
    ConfidenceBand::Low => escalate_to_operator,
}
}

Keyword Match Selector

This sample ties the visualization plan back to the rule-engine roadmap:

#![allow(unused)]
fn main() {
match selector.pick(tx.description) {
    RulePick::Exact(rule) => run_rule(rule),
    RulePick::Semantic(rule) => run_rule(rule),
    RulePick::Fallback => queue_unclassified_review,
}
}

Documentation Plan

  • add at least one match sample to every branch-heavy chapter instead of relying on generic prose
  • keep Mermaid and isometric screenshots or generated views side-by-side for the same sample
  • use stable example names derived from the full expression: match_result_disposition, match_confidence_band, match_selector_pick — the parser generates the node ID as match_ + sanitize_id(expr), so pipeline steps must target the full sanitized form
  • keep one example focused on routing to a terminal state and one focused on rejoining the main workflow

Test Plan

  • parser tests should confirm declaration order is preserved
  • Mermaid snapshot tests should assert a single switch node with labeled arms
  • isometric scene tests should assert stable lane ordering and animated reflow metadata
  • docs validation should include at least one match example chapter so regressions surface in just docgen-check