minerva 0.2.0

Causal ordering for distributed systems
//! The block-shape counters: deterministic counts in the measurements-module
//! discipline (dot counts, byte lengths off the shipped `to_bytes`,
//! structural sizes; never wall clock). These are the numbers PRD 0019's
//! later stages cite, the way arcs 1 through 9 cited the S110/S181 tables.

extern crate alloc;

use crate::metis::DotStore;

use super::page::Page;
use super::{PARAGRAPH, TABLE, gossip_fields, gossip_order, gossip_para};

/// Delivers a one-block writer's three pair deltas to two fresh receivers in
/// opposite orders, summing the classified anomaly windows each receiver
/// passes through: the coherence count (order-first opens ghost then
/// kind-pending; content-first is silent, the orphan never renders).
fn anomaly_windows(writer: &Page) -> (usize, usize) {
    let mut order_first = Page::new(4);
    let mut windows_order_first = 0usize;
    gossip_order(writer, &mut order_first);
    windows_order_first += order_first.anomalous_blocks();
    gossip_fields(writer, &mut order_first);
    windows_order_first += order_first.anomalous_blocks();
    gossip_para(writer, &mut order_first);
    windows_order_first += order_first.anomalous_blocks();

    let mut content_first = Page::new(5);
    let mut windows_content_first = 0usize;
    gossip_para(writer, &mut content_first);
    windows_content_first += content_first.anomalous_blocks();
    gossip_fields(writer, &mut content_first);
    windows_content_first += content_first.anomalous_blocks();
    gossip_order(writer, &mut content_first);
    windows_content_first += content_first.anomalous_blocks();

    (windows_order_first, windows_content_first)
}

/// A delta's measurable shape: its store dot count and its context frame's
/// byte length off the shipped have-set codec. The store half of a content
/// delta has NO wire form in-tree (`DotMap`/`DotFun` are payload-shaped, the
/// caller's to encode), so the context frame is the whole measurable wire
/// cost of a block edit today: a structural finding, recorded beside the
/// numbers.
fn delta_shape<S: DotStore>(delta: &crate::metis::Dotted<S>) -> (usize, usize) {
    (
        delta.store().dots().count(),
        delta.context().to_bytes().len(),
    )
}

#[test]
fn blocks_report() {
    let mut page = Page::new(1);

    // --- One block create: the cross-pair write shape. ---
    let order_before = page.order_context().clone();
    let fields_before = page.fields_context().clone();
    let para_block = page.create_block(PARAGRAPH, "intro", None);
    let (create_order_dots, _) = delta_shape(&page.order.owed_to(&order_before));
    let (create_fields_dots, _) = delta_shape(&page.fields.owed_to(&fields_before));
    assert_eq!(create_order_dots, 1, "one order weave per create");
    assert_eq!(
        create_fields_dots, 2,
        "kind and title registers: one create is three writes across two pairs"
    );

    // --- Per-edit delta shapes: one store dot each, context frame measured
    // (see `delta_shape` on why the frame is the whole measurable cost). ---
    let fields_before = page.fields_context().clone();
    page.set_title(para_block, "intro v2");
    let (field_edit_dots, field_edit_context_bytes) =
        delta_shape(&page.fields.owed_to(&fields_before));
    assert_eq!(field_edit_dots, 1);

    let para_before = page.para_context().clone();
    let char_a = page.type_into(para_block, 'a', None);
    let (char_edit_dots, char_edit_context_bytes) = delta_shape(&page.para.owed_to(&para_before));
    assert_eq!(char_edit_dots, 1);

    let table_block = page.create_block(TABLE, "data", Some(para_block));
    let table_before = page.table_context().clone();
    page.set_cell(table_block, 1, "x1");
    let (cell_edit_dots, cell_edit_context_bytes) = delta_shape(&page.table.owed_to(&table_before));
    assert_eq!(cell_edit_dots, 1);

    // --- Key-space duplication: one identity, three key spaces for a
    // paragraph block (order skeleton, fields map, paragraph map); a block
    // that has ever been both kinds appears in four. ---
    assert!(page.block_order().contains(&para_block));
    assert!(page.fields_present(para_block));
    assert!(page.para_present(para_block));
    let key_spaces_per_paragraph_block = 3usize;

    // --- The conjunction render's deterministic cost: three cross-pair
    // lookups per single-kind block (fields get, kind read, content get). ---
    page.set_cell(table_block, 2, "x2");
    let _ = page.type_into(para_block, 'b', Some(char_a));
    let (rendered, lookups) = page.render_counted();
    assert_eq!(rendered.len(), 2);
    assert_eq!(
        lookups,
        3 * rendered.len(),
        "three cross-pair lookups per rendered single-kind block"
    );
    assert_eq!(page.anomalous_blocks(), 0, "the local page never tears");

    // --- The tree viewport, answered at probe scale: each block's sequence
    // is its own store, so a per-container render walks that container's
    // skeleton only. Container-local windows are free by construction in
    // this recipe (the flat document needed S183's windowed walk for this;
    // PRD 0019 open question 3). ---
    let second_para = page.create_block(PARAGRAPH, "outro", Some(table_block));
    let mut after = None;
    for ch in "world".chars() {
        after = Some(page.type_into(second_para, ch, after));
    }
    let first_walk = page.para_skeleton_len(para_block);
    let second_walk = page.para_skeleton_len(second_para);
    let total_para_dots = page.para.state().store().dots().count();
    assert_eq!(first_walk, 2);
    assert_eq!(second_walk, 5);
    assert_eq!(
        first_walk + second_walk,
        total_para_dots,
        "a per-container render walks its own skeleton, never the document's"
    );

    // --- Anomaly windows per delivery interleaving, the coherence count:
    // order-first opens two classified windows (ghost, then kind-pending);
    // content-first opens none (the orphan is silent). No interleaving
    // fabricates a rendered state the conjunction cannot classify. ---
    let mut writer = Page::new(3);
    let block = writer.create_block(PARAGRAPH, "w", None);
    let _ = writer.type_into(block, 'w', None);
    let (windows_order_first, windows_content_first) = anomaly_windows(&writer);
    assert_eq!(windows_order_first, 2, "ghost, kind-pending, then whole");
    assert_eq!(windows_content_first, 0, "content-first windows are silent");

    #[cfg(feature = "std")]
    {
        std::println!("\n=== BLOCK-DOCUMENT PROBE (PRD 0019 stage A) ===");
        std::println!("one block create:      1 order dot + 2 field dots, two pairs");
        std::println!(
            "field edit delta:      {field_edit_dots} store dot, {field_edit_context_bytes}-byte context frame"
        );
        std::println!(
            "char edit delta:       {char_edit_dots} store dot, {char_edit_context_bytes}-byte context frame"
        );
        std::println!(
            "cell edit delta:       {cell_edit_dots} store dot, {cell_edit_context_bytes}-byte context frame"
        );
        std::println!("content-pair wire:     context frame only (no in-tree store codec)");
        std::println!(
            "conjunction render:    {lookups} lookups for {} blocks",
            rendered.len()
        );
        std::println!(
            "key spaces per block:  {key_spaces_per_paragraph_block} (order, fields, own-kind map)"
        );
        std::println!(
            "tree viewport:         {first_walk} of {total_para_dots} para dots walked for one container"
        );
        std::println!(
            "anomaly windows:       order-first {windows_order_first}, content-first {windows_content_first}"
        );
        std::println!("===============================================\n");
    }

    // Under no_std every number above is already asserted; touch the
    // byte-length readings that only the std table prints.
    let _ = (
        field_edit_context_bytes,
        char_edit_context_bytes,
        cell_edit_context_bytes,
        key_spaces_per_paragraph_block,
    );
}