yog 0.0.1

yog: a balls-oriented session manager for lernie loops (egui frontend)
Documentation
//! The §11 Altitude-2 inspector content — the per-agent tabbed pane's
//! **display**, dispatched by [`InspectorTab`].
//!
//! This is the one tested seam between the selected tab and the landed render
//! functions ([`transcript`](crate::transcript), [`steps_view`](crate::steps_view),
//! [`inboxview`](crate::inboxview), and the config-branch governing view). The
//! shell (coverage-excluded) builds a [`TabData`] for the focused agent — the
//! six view-models built fresh each frame and **moved** in — carries the RAM
//! ephemera beside them (the Raw toggle, the step selection/tab, the jsonview
//! collapse set — §5.3), and forwards the digit-key/click events; the dispatch
//! decision itself lives here so every arm is headless shape-walk tested.
//!
//! The Config tab shows only the agent's **governing config** ("policy frozen
//! at `<short-oid>`", §9.3); the three write surfaces (brazen / lernie-global /
//! config-branch editors) are the roster's Config panel (§11 "Config mode …
//! swaps the center"), interaction glue in the shell.

use std::collections::HashSet;

use crate::config_edit::branch::GoverningConfig;
use crate::files_view::{self, FilesView, Preview};
use crate::inboxview::{self, Deposit};
use crate::keymap::InspectorTab;
use crate::steps_view::{self, StepDetail, StepTab, StepsView};
use crate::transcript::{self, Transcript};

/// The pre-built view-models + RAM ephemera the inspector renders for one
/// focused agent (§11). Owned: the shell builds each disk-read VM fresh per
/// frame and moves it in, beside the viewport ephemera (§5.3) — nothing borrows
/// the shell's state, so the render holds the whole tab in hand. Absent data
/// (no steps, no governing config) is a value, never a special case.
#[derive(Clone)]
pub struct TabData {
    pub transcript: Transcript,
    /// The Transcript tab's Raw toggle (§11 "every tab has a Raw toggle").
    pub raw: bool,
    pub steps: StepsView,
    /// The selected step's list index (§5.3 ephemera), if any.
    pub step_sel: Option<usize>,
    /// The selected step's drill-in, built by the shell for `step_sel`.
    pub step_detail: Option<StepDetail>,
    pub step_tab: StepTab,
    pub inbox: Vec<Deposit>,
    /// The agent worktree's bounded listing (§11 Files tab).
    pub files: FilesView,
    /// The Files tab's selected-file preview, built by the shell from
    /// `files_sel`; `None` when nothing is selected.
    pub file_preview: Option<Preview>,
    /// The focused agent's governing config, when derivable (a defective or
    /// unfetched workspace yields `None`, shown as a note).
    pub governing: Option<GoverningConfig>,
}

/// Render the selected inspector tab's content. `collapsed` is the caller-owned
/// jsonview collapse set (§5.3), threaded into the Steps drill-in trees;
/// `file_sel` is the caller-owned Files selected-entry index, set on a row click.
pub fn render(
    ui: &mut egui::Ui,
    tab: InspectorTab,
    data: &TabData,
    collapsed: &mut HashSet<String>,
    file_sel: &mut Option<usize>,
) {
    match tab {
        InspectorTab::Transcript => transcript::render(ui, &data.transcript, data.raw),
        InspectorTab::Steps => steps_view::render(
            ui,
            &data.steps,
            data.step_sel,
            data.step_detail.as_ref(),
            data.step_tab,
            collapsed,
        ),
        InspectorTab::Inbox => inboxview::render(ui, &data.inbox),
        InspectorTab::Files => {
            files_view::render(ui, &data.files, data.file_preview.as_ref(), file_sel);
        }
        InspectorTab::Config => render_config(ui, data.governing.as_ref()),
    }
}

/// The Config tab (§11): the focused agent's governing config — "policy frozen
/// at `<short-oid>`", the config commit its branch forks off — plus that
/// commit's file listing. The three config *editors* are the roster Config
/// panel (§9), reached by the shell's link.
fn render_config(ui: &mut egui::Ui, governing: Option<&GoverningConfig>) {
    let Some(gov) = governing else {
        ui.weak("no governing config for this agent");
        return;
    };
    ui.strong(gov.frozen_label());
    if let Some(name) = &gov.branch_name_if_tip_of_one {
        ui.weak(format!("tip of config/{name}"));
    }
    egui::ScrollArea::vertical().show(ui, |ui| {
        for file in &gov.files {
            ui.monospace(file);
        }
    });
}

#[cfg(test)]
mod tests;