supercode-harness 0.4.21

The optional native Supercode agent and tool harness
Documentation
//! UNI-15 acceptance: the Hermes read-only rescue tier against a REAL
//! `state.db` (SCHEMA_VERSION = 22, minted by hermes-agent 0.19.0 through
//! live ACP turns on 2026-08-31, then sanitized), extended with lineage rows
//! shaped by hermes's OWN v22 SQL (`hermes_state.py`: `model_config`
//! `$._branched_from`/`$._delegate_from` markers, `end_reason` heuristics).

use std::path::{Path, PathBuf};

use supercode_harness::{
    DiscoveryQuery, HarnessCatalog, HarnessHomes, HarnessId, Role, Session, SessionSource,
};

fn store() -> PathBuf {
    Path::new(env!("CARGO_MANIFEST_DIR")).join("tests/fixtures/hermes_home/state.db")
}

#[test]
fn bounded_sdk_reads_keep_native_worker_end_without_a_delivery_binding() {
    let path =
        std::env::temp_dir().join(format!("hermes-worker-end-sdk-{}.db", std::process::id()));
    std::fs::copy(store(), &path).unwrap();
    let db = rusqlite::Connection::open(&path).unwrap();
    db.execute_batch(
        "INSERT INTO sessions (id, source, started_at, ended_at, end_reason) VALUES
        ('worker-end-sdk', 'kanban', 100, 200.75, 'cli_close'),
        ('worker-live-sdk', 'kanban', 201, NULL, NULL);",
    )
    .unwrap();
    drop(db);
    let before = sha256(&path);
    let mut service = supercode_harness::harness_service::HarnessSessionService::new();
    for id in ["worker-end-sdk", "worker-live-sdk"] {
        for options in [
            serde_json::json!({"message_tail": 1}),
            serde_json::json!({"message_offset": 0, "message_limit": 1}),
        ] {
            let result = service.handle(serde_json::json!({
                "jsonrpc": "2.0", "id": 1, "method": "harness.v1.sessions.load",
                "params": {"locator": {"harness": "hermes", "session_id": id,
                    "storage": {"kind": "file", "path": path}}, "options": options}
            }));
            assert!(result.get("error").is_none(), "{result}");
            let session = &result["result"]["session"];
            if id == "worker-end-sdk" {
                assert_eq!(session["ended_at"], "1970-01-01T00:03:20.750Z");
                assert_eq!(session["end_reason"], "cli_close");
            } else {
                assert!(session["ended_at"].is_null());
                assert!(session["end_reason"].is_null());
            }
        }
    }
    assert_eq!(sha256(&path), before);
    std::fs::remove_file(path).unwrap();
}

fn sha256(path: &Path) -> String {
    use std::io::Read;
    let mut file = std::fs::File::open(path).unwrap();
    let mut bytes = Vec::new();
    file.read_to_end(&mut bytes).unwrap();
    format!("{:x}", md5_like(&bytes))
}

// Tiny deterministic digest (fnv) — enough to prove byte identity in-test
// without adding a hash dependency.
fn md5_like(bytes: &[u8]) -> u128 {
    let mut hash: u128 = 0xcbf2_9ce4_8422_2325;
    for byte in bytes {
        hash ^= *byte as u128;
        hash = hash.wrapping_mul(0x0000_0100_0000_01b3);
    }
    hash
}

#[test]
fn real_session_loads_with_tool_pairing_and_hermes_provenance() {
    // The tool-call session minted live: user -> assistant(tool_calls) ->
    // tool(result) -> assistant.
    let session = Session::from_hermes_sqlite(&store(), None).unwrap();
    assert_eq!(session.meta.source, SessionSource::Hermes);
    assert_eq!(session.meta.model.as_deref(), Some("gpt-5-nano"));
    assert!(
        !session.raw_is_verbatim,
        "synthesized raw must never claim verbatim"
    );

    let assistant_with_calls = session
        .messages
        .iter()
        .find(|message| message.tool_calls.is_some())
        .expect("the live tool-call turn must map to canonical tool calls");
    let calls = assistant_with_calls.tool_calls.as_ref().unwrap();
    assert_eq!(calls[0].function.name, "terminal");
    assert!(calls[0].function.arguments.contains("HERMES_TOOL_PROOF"));

    let tool_result = session
        .messages
        .iter()
        .find(|message| message.role == Role::Tool)
        .expect("the tool row must map to a canonical tool result");
    assert!(tool_result
        .content
        .as_deref()
        .unwrap_or("")
        .contains("HERMES_TOOL_PROOF"));
}

#[test]
fn lineage_classification_covers_all_verified_kinds() {
    let kinds = [
        ("child-branch-marker", "branch"),
        ("child-delegate", "delegate"),
        ("child-legacy-branch", "branch"),
        ("child-compaction", "compaction"),
        ("child-unknown", "unknown"),
    ];
    for (id, expected) in kinds {
        let session = Session::from_hermes_sqlite(&store(), Some(id)).unwrap();
        assert_eq!(
            session
                .meta
                .lineage
                .get("hermes_lineage_kind")
                .map(String::as_str),
            Some(expected),
            "session {id}"
        );
        assert!(session
            .meta
            .lineage
            .contains_key("hermes_parent_session_id"));
    }
}

#[test]
fn inactive_rows_are_rescued_in_raw_but_never_replayed() {
    let session = Session::from_hermes_sqlite(&store(), Some("child-branch-marker")).unwrap();
    let replayed: Vec<&str> = session
        .messages
        .iter()
        .filter_map(|message| message.content.as_deref())
        .collect();
    assert!(replayed.iter().any(|text| text.contains("active answer")));
    assert!(
        !replayed
            .iter()
            .any(|text| text.contains("inactive rewound answer")),
        "hermes's own replay rule is active=1 only: {replayed:?}"
    );
    // Rescue: the inactive row survives in the synthesized raw capture.
    assert!(session
        .raw
        .iter()
        .any(|line| line.contains("inactive rewound answer")));
}

#[test]
fn discovery_lists_sessions_and_the_load_path_routes_sqlite_correctly() {
    let query = DiscoveryQuery {
        harnesses: vec![HarnessId::new(HarnessId::HERMES)],
        homes: HarnessHomes {
            hermes: store(),
            ..HarnessHomes::default()
        },
        ..DiscoveryQuery::default()
    };
    // Default view: lineage children (branch/delegate/compaction) roll up
    // into their parents, exactly like Codex child rollouts — 2 real minted
    // sessions + 2 lineage parents stay visible, plus the three ORCH-3
    // channel/cron-origin rows (no lineage).
    let found = HarnessCatalog::new().discover(&query).unwrap();
    assert_eq!(found.len(), 7, "{found:#?}");
    assert!(found
        .iter()
        .all(|descriptor| descriptor.locator.harness.as_str() == HarnessId::HERMES));

    // Child-inclusive view exposes all 12 with their native lineage links.
    let mut with_children = query.clone();
    with_children.include_child_sessions = true;
    let all = HarnessCatalog::new().discover(&with_children).unwrap();
    assert_eq!(all.len(), 12, "{all:#?}");
    assert!(all
        .iter()
        .any(|descriptor| descriptor.parent_session_id.as_deref() == Some("parent-branched")));

    // A hermes state.db must never be misrouted to the OpenCode SQLite
    // loader by the generic load path.
    let session = Session::load(&store()).unwrap();
    assert_eq!(session.meta.source, SessionSource::Hermes);
}

#[test]
fn loading_and_discovery_never_write_the_store() {
    let before = sha256(&store());
    let _ = Session::from_hermes_sqlite(&store(), None).unwrap();
    let _ = Session::load(&store()).unwrap();
    let query = DiscoveryQuery {
        harnesses: vec![HarnessId::new(HarnessId::HERMES)],
        homes: HarnessHomes {
            hermes: store(),
            ..HarnessHomes::default()
        },
        ..DiscoveryQuery::default()
    };
    let _ = HarnessCatalog::new().discover(&query).unwrap();
    assert_eq!(before, sha256(&store()), "state.db bytes must be untouched");
    // And no journal/wal side files appear next to the fixture.
    assert!(!store().with_extension("db-wal").exists());
    for suffix in ["state.db-wal", "state.db-shm", "state.db-journal"] {
        assert!(
            !store().parent().unwrap().join(suffix).exists(),
            "{suffix} must not be created by read-only access"
        );
    }
}

// ORCH-3: shared nouns derived from Hermes rows (channel DM, cron fire, profiled group with handoff).
#[test]
fn orchestration_nouns_derive_from_hermes_rows() {
    use supercode_harness::{Trigger, WorkspaceKind};
    let dm = Session::from_hermes_sqlite(&store(), Some("tg-dm-1")).unwrap();
    assert_eq!(dm.meta.trigger, Some(Trigger::Channel));
    let s = dm.meta.surface.as_ref().expect("surface");
    assert_eq!(s.platform.as_deref(), Some("telegram"));
    assert_eq!(s.kind.as_deref(), Some("dm"));
    assert_eq!(s.chat_id.as_deref(), Some("123456"));
    assert_eq!(s.participant_id.as_deref(), Some("u1"));
    assert!(dm.meta.profile.is_none());
    assert_eq!(
        dm.meta.workspace(),
        (WorkspaceKind::Channel, Some("telegram:123456".into()))
    );

    let fire = Session::from_hermes_sqlite(&store(), Some("cron_job42_20260902_120000")).unwrap();
    assert_eq!(fire.meta.trigger, Some(Trigger::Cron));
    assert_eq!(
        fire.meta.recurrence.as_ref().map(|r| r.job_id.as_str()),
        Some("job42")
    );
    assert_eq!(fire.meta.workspace().0, WorkspaceKind::Repo);

    let coder = Session::from_hermes_sqlite(&store(), Some("tg-coder-1")).unwrap();
    assert_eq!(coder.meta.profile.as_deref(), Some("coder"));
    assert_eq!(coder.meta.trigger, Some(Trigger::Channel));
    let s = coder.meta.surface.as_ref().expect("surface");
    assert_eq!(s.thread_id.as_deref(), Some("55"));
    // D2 precedence: a cwd AND a chat → repo workspace, chat kept on the surface key.
    assert_eq!(coder.meta.workspace().0, WorkspaceKind::Repo);
    let x = coder.meta.cross_surface.as_ref().expect("handoff");
    assert_eq!(x.state, "pending");
    assert_eq!(x.platform.as_deref(), Some("discord"));

    // A plain ACP session stays human-triggered with no surface.
    let acp = Session::from_hermes_sqlite(&store(), Some("cef97234-e8e8-428a-99ab-e8fff4e7e613"))
        .unwrap();
    assert_eq!(acp.meta.trigger, Some(Trigger::Human));
    assert!(acp.meta.surface.is_none());
    // A delegate child is parent-triggered.
    let child = Session::from_hermes_sqlite(&store(), Some("child-delegate")).unwrap();
    assert_eq!(child.meta.trigger, Some(Trigger::Parent));
}