pointbreak 0.5.0

Durable terminal code review for changes humans and coding agents collaborate on together
Documentation
mod support;

use serde_json::Value;
use support::git_repo::GitRepo;
use support::shore_env;

fn parse_json(bytes: &[u8]) -> Value {
    serde_json::from_slice(bytes).expect("valid json on stdout")
}

fn captured_repo() -> GitRepo {
    let repo = GitRepo::new();
    repo.write("src/lib.rs", "pub fn value() -> u32 { 1 }\n");
    repo.commit_all("base");
    repo.write("src/lib.rs", "pub fn value() -> u32 { 2 }\n");
    repo
}

#[test]
fn store_link_emits_camelcase_json_with_family_and_clone_refs() {
    let repo = captured_repo();
    let repo_arg = repo.path().to_str().unwrap().to_owned();
    let home = tempfile::tempdir().unwrap();
    let home_str = home.path().to_str().unwrap();

    assert!(
        shore_env(
            ["capture", "--repo", &repo_arg],
            &[("SHORE_HOME", home_str)]
        )
        .status
        .success()
    );

    let link = shore_env(
        ["store", "link", "acme", "--repo", &repo_arg],
        &[("SHORE_HOME", home_str)],
    );
    assert!(
        link.status.success(),
        "link: {}",
        String::from_utf8_lossy(&link.stderr)
    );
    let json = parse_json(&link.stdout);
    assert_eq!(json["familyRef"], "acme");
    assert!(!json["cloneRef"].as_str().unwrap().is_empty());
    assert_eq!(json["createdFamily"], true);
}

#[test]
fn store_link_text_digest_mentions_the_family() {
    let repo = captured_repo();
    let repo_arg = repo.path().to_str().unwrap().to_owned();
    let home = tempfile::tempdir().unwrap();
    let home_str = home.path().to_str().unwrap();
    assert!(
        shore_env(
            ["capture", "--repo", &repo_arg],
            &[("SHORE_HOME", home_str)]
        )
        .status
        .success()
    );

    let link = shore_env(
        [
            "store", "link", "acme", "--repo", &repo_arg, "--format", "text",
        ],
        &[("SHORE_HOME", home_str)],
    );
    assert!(link.status.success());
    let stdout = String::from_utf8(link.stdout).unwrap();
    assert!(stdout.contains("acme"), "{stdout}");
    assert!(
        !stdout.contains("\"schema\""),
        "text lane is not JSON: {stdout}"
    );
}

#[test]
fn store_link_default_fold_discloses_removed_unsigned_events() {
    let repo = captured_repo();
    let repo_arg = repo.path().to_str().unwrap().to_owned();
    let home = tempfile::tempdir().unwrap();
    let home_str = home.path().to_str().unwrap();

    assert!(
        shore_env(
            ["capture", "--repo", &repo_arg],
            &[("SHORE_HOME", home_str)]
        )
        .status
        .success()
    );
    let status = shore_env(
        ["store", "status", "--repo", &repo_arg],
        &[("SHORE_HOME", home_str)],
    );
    let object_ref = parse_json(&status.stdout)["inventory"]["revisionObjects"][0]["objectId"]
        .as_str()
        .unwrap()
        .to_owned();
    assert!(
        shore_env(
            [
                "store",
                "remove",
                "--snapshot",
                &object_ref,
                "--repo",
                &repo_arg
            ],
            &[("SHORE_HOME", home_str), ("SHORE_SIGNING", "off")],
        )
        .status
        .success()
    );

    let link = shore_env(
        ["store", "link", "acme", "--repo", &repo_arg],
        &[("SHORE_HOME", home_str)],
    );
    assert!(link.status.success());
    let json = parse_json(&link.stdout);
    let diagnostics = json["diagnostics"].as_array().cloned().unwrap_or_default();
    assert!(
        diagnostics.iter().any(|d| d["message"]
            .as_str()
            .unwrap_or_default()
            .contains("unsigned removal event")),
        "expected the possession-lost disclosure: {json}"
    );
}

#[test]
fn store_link_dry_run_previews_without_writing() {
    let repo = captured_repo();
    let repo_arg = repo.path().to_str().unwrap().to_owned();
    let home = tempfile::tempdir().unwrap();
    let home_str = home.path().to_str().unwrap();
    assert!(
        shore_env(
            ["capture", "--repo", &repo_arg],
            &[("SHORE_HOME", home_str)]
        )
        .status
        .success()
    );

    let dry = shore_env(
        ["store", "link", "acme", "--dry-run", "--repo", &repo_arg],
        &[("SHORE_HOME", home_str)],
    );
    assert!(
        dry.status.success(),
        "dry-run exits 0 on a clean path: {}",
        String::from_utf8_lossy(&dry.stderr)
    );
    let json = parse_json(&dry.stdout);
    assert_eq!(json["schema"], "shore.store-link-preview");
    assert_eq!(json["familyRef"], "acme");
    assert_eq!(json["wouldCreateFamily"], true);
    assert_eq!(json["exportFidelity"], "full");
    assert!(json["foldedEventsToCreate"].as_u64().unwrap() >= 1);
    // No binding was flipped, and a subsequent status still reports the local store.
    assert!(!repo.path().join(".shore/store.local.json").exists());
    let status = shore_env(
        ["store", "status", "--repo", &repo_arg],
        &[("SHORE_HOME", home_str)],
    );
    assert_eq!(parse_json(&status.stdout)["mode"], "local");
}

#[test]
fn store_link_dry_run_blocks_on_ephemeral_without_override() {
    let repo = captured_repo();
    let repo_arg = repo.path().to_str().unwrap().to_owned();
    let home = tempfile::tempdir().unwrap();
    let home_str = home.path().to_str().unwrap();
    assert!(
        shore_env(
            ["capture", "--repo", &repo_arg],
            &[("SHORE_HOME", home_str)]
        )
        .status
        .success()
    );
    assert!(
        shore_env(
            ["store", "mode", "ephemeral", "--repo", &repo_arg],
            &[("SHORE_HOME", home_str)]
        )
        .status
        .success()
    );

    let dry = shore_env(
        ["store", "link", "acme", "--dry-run", "--repo", &repo_arg],
        &[("SHORE_HOME", home_str)],
    );
    assert!(
        !dry.status.success(),
        "an ephemeral worktree blocks the dry-run"
    );
    let stderr = String::from_utf8_lossy(&dry.stderr);
    assert!(stderr.contains("ephemeral"), "names the gate: {stderr}");
    assert!(!repo.path().join(".shore/store.local.json").exists());
}

#[test]
fn store_unlink_round_trips() {
    let repo = captured_repo();
    let repo_arg = repo.path().to_str().unwrap().to_owned();
    let home = tempfile::tempdir().unwrap();
    let home_str = home.path().to_str().unwrap();
    assert!(
        shore_env(
            ["capture", "--repo", &repo_arg],
            &[("SHORE_HOME", home_str)]
        )
        .status
        .success()
    );
    assert!(
        shore_env(
            ["store", "link", "acme", "--repo", &repo_arg],
            &[("SHORE_HOME", home_str)]
        )
        .status
        .success()
    );

    let unlink = shore_env(
        ["store", "unlink", "--repo", &repo_arg],
        &[("SHORE_HOME", home_str)],
    );
    assert!(
        unlink.status.success(),
        "{}",
        String::from_utf8_lossy(&unlink.stderr)
    );

    let status = shore_env(
        ["store", "status", "--repo", &repo_arg],
        &[("SHORE_HOME", home_str)],
    );
    let json = parse_json(&status.stdout);
    assert_eq!(json["mode"], "local");
    assert!(json.get("repositoryFamilyRef").is_none());
}

#[test]
fn store_link_without_a_slug_surfaces_the_workflow_suggestion_error() {
    let repo = captured_repo();
    let repo_arg = repo.path().to_str().unwrap().to_owned();
    let home = tempfile::tempdir().unwrap();
    let home_str = home.path().to_str().unwrap();
    assert!(
        shore_env(
            ["capture", "--repo", &repo_arg],
            &[("SHORE_HOME", home_str)]
        )
        .status
        .success()
    );

    let link = shore_env(
        ["store", "link", "--repo", &repo_arg],
        &[("SHORE_HOME", home_str)],
    );
    assert!(
        !link.status.success(),
        "an omitted slug must not silently pick one"
    );
    let stderr = String::from_utf8_lossy(&link.stderr);
    assert!(stderr.contains("slug"), "names the missing input: {stderr}");
}