lernie 0.1.70

lernie: the operator seat — the window and wire client for a yog server
//! **The covering panes whose subject is a FOCUS**: the aimed wall, one of its
//! rows, or the selected conversation.
//!
//! Split from [`super`] at the design-time budget, and split again from
//! [`union`] at it on the seam DESIGN itself draws (bl-4c48): a pane about a
//! focus is retired when that focus moves, and a pane about every channel has
//! no focus to move. The two halves change for different reasons — the first
//! when a row grows a fact, the second when a channel-wide op lands a surface.
//!
//! Every one of them is `..seated()`, because a pane covers the window at work
//! rather than replacing it — and each is answered rather than waiting, for
//! the reason `crate::snapshot::worlds` states: what a pane's world exists to
//! photograph is every sentence it can say, and an unanswered pane says only
//! that nobody has answered.

/// The covering panes whose subject is every channel this box holds.
pub(crate) mod board;
pub(crate) mod fleet;
/// The prices pane, channel-wide and in a file of its own.
pub(crate) mod prices;
/// The records pane, whose four reads make it the fixture that grows.
pub(crate) mod records;
pub(crate) mod union;

pub(crate) use board::{boarded, column, figure};
pub(crate) use fleet::{attempt, diff, fleeting};
pub(crate) use prices::priced;
pub(crate) use records::{deposit, drilled, mark, notch, own_row, recorded, step};
pub(crate) use union::{
    checked, clearing, commanded, doctored, finding, helped, hit, queued, trailed, trailing,
    waiting,
};

use crate::ui::{Login, Model, Tuning};

use super::{role, seated};

/// **The seated model with the tuning pane open and answered.** The pane's
/// own screen, and the one the `effort` and `priority` controls live on.
pub(crate) fn tuned() -> Model {
    Model {
        roles: Some(vec![role("worker"), role("compactor")]),
        tuning: Some(Tuning::Rows),
        ..seated()
    }
}

/// **The seated model with the aimed wall pinned** (bl-7782) — the one screen
/// the `unpin` control exists on, because the pin pair are assertions and each
/// row carries exactly the one that is not already true of it.
pub(crate) fn pinned() -> Model {
    let mut model = seated();
    for chunk in &mut model.roster {
        for row in &mut chunk.walls {
            row.pinned = Some(0);
        }
    }
    model
}

/// One provider row, open to a sign-in and taking both tuning knobs.
pub(crate) fn provider(name: &str) -> crate::reply::providers::ProviderRow {
    crate::reply::providers::ProviderRow {
        name: name.to_owned(),
        fact: "credential present".to_owned(),
        blocked: None,
        effort: true,
        priority: true,
    }
}

/// **The seated model with the login pane open and answered** (bl-e3c5): a row
/// that can be signed in to and is being followed mid-flow, a row the engine
/// has blocked, and a row asked what it offers — every sentence the pane can
/// say about a row, on one screen.
pub(crate) fn signing() -> Model {
    let blocked = crate::reply::providers::ProviderRow {
        fact: "no credential".to_owned(),
        blocked: Some("no login flow".to_owned()),
        effort: false,
        priority: false,
        ..provider("otherhouse")
    };
    Model {
        login: Some(Login {
            following: Some("housevendor".to_owned()),
            asking: Some("otherhouse".to_owned()),
        }),
        providers: Some(vec![provider("housevendor"), blocked]),
        offered: Some(vec!["house-model-1".to_owned()]),
        signin: Some(crate::reply::login::Signin {
            lines: vec![
                crate::reply::login::Line {
                    text: "open https://provider.invalid/auth".to_owned(),
                    err: true,
                },
                crate::reply::login::Line {
                    text: "waiting for the browser".to_owned(),
                    err: false,
                },
            ],
            outcome: None,
            fallback: None,
        }),
        ..seated()
    }
}

/// One machine, connected or not, offering one tool that takes a caller-named
/// directory and one that does not.
pub(crate) fn machine(client: &str, present: bool) -> crate::reply::clients::ClientRow {
    crate::reply::clients::ClientRow {
        client: client.to_owned(),
        present,
        // A machine that has dialled: the never-dialled row is its own fixture
        // where a pane asserts it, because the absence is the reading.
        last_seen: Some(1_700),
        tools: vec![
            crate::reply::clients::ToolRow {
                name: "Bash".to_owned(),
                description: "run a command".to_owned(),
                subject_cwd: false,
            },
            crate::reply::clients::ToolRow {
                name: "bash".to_owned(),
                description: "run a command in the conversation's cwd".to_owned(),
                subject_cwd: true,
            },
        ],
    }
}

/// **The seated model with the clients pane open and answered** (bl-e53c): a
/// machine connected right now with both consents on its set, one that is not
/// connected, and one that has advertised nothing — every sentence the pane
/// can say about a row, on one screen.
pub(crate) fn machines() -> Model {
    let bare = crate::reply::clients::ClientRow {
        tools: Vec::new(),
        ..machine("phone", false)
    };
    Model {
        listing: Some(crate::ui::Listing::Clients),
        machines: Some(vec![machine("laptop", true), machine("desk", false), bare]),
        ..seated()
    }
}

/// One lineage, with two paths on its tip.
pub(crate) fn lineage(name: &str) -> crate::reply::lineages::Lineage {
    crate::reply::lineages::Lineage {
        name: name.to_owned(),
        oid: "abcdef1234".to_owned(),
        short_oid: "abcdef1".to_owned(),
        committed: 1_700_000_000,
        files: vec!["providers.yaml".to_owned(), "workflow.yaml".to_owned()],
    }
}

/// **The seated model with the config pane open, pointed at a file and
/// answered** (bl-5c53): a lineage to index into, a typed setting the engine
/// has faulted, a bounded one it has not, and the bytes they were read out of
/// — every sentence the pane can say about a file, on one screen. And a
/// reviewer's proposal named and answered whole (bl-a1d6), so both verdicts
/// are on the glass.
pub(crate) fn configured() -> Model {
    Model {
        configuring: Some(crate::ui::Configuring {
            at: Some(crate::verbs::Where::Brazen {
                workspace: "home".to_owned(),
            }),
            proposal: Some(crate::ui::Proposing {
                id: PROPOSED.to_owned(),
                ..crate::ui::Proposing::default()
            }),
            ..crate::ui::Configuring::default()
        }),
        lineages: Some(vec![lineage("default")]),
        proposals: Some(crate::reply::proposals::Proposals {
            rows: vec![proposed(PROPOSED, true)],
            whole: Some(WHOLE.to_owned()),
        }),
        config: Some(crate::reply::config::Config {
            text: "roles:\n  worker:\n    provider: gone\n".to_owned(),
            settings: vec![
                crate::reply::config::Setting {
                    entry: "worker".to_owned(),
                    name: "provider".to_owned(),
                    value: "gone".to_owned(),
                    help: "the provider row this role dispatches through".to_owned(),
                    fault: Some("brazen's table has no provider row `gone`".to_owned()),
                    control: crate::reply::config::Control {
                        kind: "provider".to_owned(),
                        min: None,
                        max: None,
                    },
                },
                crate::reply::config::Setting {
                    entry: "watcher".to_owned(),
                    name: "debounce_ms".to_owned(),
                    value: "100".to_owned(),
                    help: "how long a changed workspace coalesces".to_owned(),
                    fault: None,
                    control: crate::reply::config::Control {
                        kind: "number".to_owned(),
                        min: Some(0),
                        max: Some(10_000),
                    },
                },
            ],
        }),
        ..seated()
    }
}

/// The staged proposal the config fixture names.
pub(crate) const PROPOSED: &str = "20260906T090000Z-r001";

/// **Its message and diff**, with the indentation and the long line a reflow
/// would be the first thing to break.
pub(crate) const WHOLE: &str = "teach the worker to stop retrying\n\n\
     --- a/roles.yaml\n\
     +++ b/roles.yaml\n\
     @@ -1,2 +1,2 @@\n\
     \x20 worker:\n\
     -    retries: 3\n\
     +    retries: 0  # a long trailing comment that no pane is allowed to wrap onto a second line\n";

/// One staged proposal row.
pub(crate) fn proposed(id: &str, fresh: bool) -> crate::reply::proposals::Proposal {
    crate::reply::proposals::Proposal {
        id: id.to_owned(),
        lineages: if fresh {
            vec!["default".to_owned()]
        } else {
            Vec::new()
        },
        parent: "9f2c1ab4".to_owned(),
        fresh,
        diffstat: "1 file changed, 1 insertion(+), 1 deletion(-)".to_owned(),
        subject: "teach the worker to stop retrying".to_owned(),
    }
}