cueloop 0.5.0

A Rust CLI for managing AI agent loops with a structured JSON task queue
Documentation
//! Xcode project, Makefile, and release pipeline bundling contracts.
//!
//! Purpose:
//! - Xcode project, Makefile, and release pipeline bundling contracts.
//!
//! Responsibilities:
//! - Provide focused implementation or regression coverage for this file's owning feature.
//!
//! Scope:
//! - Limited to this file's owning feature boundary.
//!
//!
//! Usage:
//! - Used through the crate module tree or integration test harness.
//!
//! Invariants/Assumptions:
//! - Keep behavior aligned with CueLoop's canonical CLI, machine-contract, and queue semantics.

use super::support::{read_repo_file, swift_file_names};

#[test]
fn xcode_project_references_all_committed_swift_sources() {
    let project = read_repo_file("apps/CueLoopMac/CueLoopMac.xcodeproj/project.pbxproj");

    for relative_dir in [
        "apps/CueLoopMac/CueLoopCore",
        "apps/CueLoopMac/CueLoopCoreTests",
        "apps/CueLoopMac/CueLoopMac",
        "apps/CueLoopMac/CueLoopMacUITests",
    ] {
        for file_name in swift_file_names(relative_dir) {
            let file_ref_marker = format!("/* {file_name} */");
            let build_marker = format!("/* {file_name} in Sources */");
            assert!(
                project.contains(&file_ref_marker),
                "Xcode project is missing file reference for {relative_dir}/{file_name}"
            );
            assert!(
                project.contains(&build_marker),
                "Xcode project is missing Sources membership for {relative_dir}/{file_name}"
            );
        }
    }
}

#[test]
fn xcode_build_phase_uses_shared_cli_bundle_entrypoint() {
    let project = read_repo_file("apps/CueLoopMac/CueLoopMac.xcodeproj/project.pbxproj");
    assert!(
        project.contains("scripts/cueloop-cli-bundle.sh"),
        "Xcode project should call the shared CLI bundling script"
    );
    assert!(
        !project.contains("cargo ${BUILD_ARGS}") && !project.contains("target/debug/cueloop"),
        "Xcode project should not embed its own Cargo invocation policy or debug hardcoded CLI paths"
    );
    assert!(
        project.contains("cueloop-cli-bundle.sh") && !project.contains("target/release/cueloop"),
        "Release should always route through cueloop-cli-bundle.sh instead of copying a possibly stale target/release CLI"
    );
    assert!(
        project.contains("alwaysOutOfDate = 1;"),
        "The Xcode bundle phase should always rerun so CueLoopMac never ships a stale embedded CLI after Rust-only rebuilds"
    );
}

#[test]
fn shared_cli_bundle_script_supports_configuration_and_bundle_dir() {
    let script = read_repo_file("scripts/cueloop-cli-bundle.sh");
    assert!(
        script.contains("--configuration") && script.contains("--bundle-dir"),
        "shared CLI bundle script should accept configuration and bundle destination inputs"
    );
    assert!(
        script.contains("PRIMARY_BIN_NAME=\"cueloop\"")
            && !script.contains(&format!("{}{}", "LEGACY", "_BIN_NAME=")),
        "shared CLI bundle script should build only the primary cueloop binary"
    );
    assert!(
        script.contains("cueloop_activate_pinned_rust_toolchain"),
        "shared CLI bundle script should honor the pinned rustup toolchain"
    );
    assert!(
        script.contains("--target") && script.contains("--jobs"),
        "shared CLI bundle script should act as the canonical build entrypoint for both native and cross-target builds"
    );
    assert!(
        !script.contains("CUELOOP_BIN_PATH"),
        "shared CLI bundle script should not allow callers to bypass the canonical build contract with an arbitrary binary override"
    );
}

#[test]
fn release_pipeline_uses_github_draft_then_publish_flow() {
    let script = read_repo_file("scripts/lib/release_publish_pipeline.sh");
    assert!(
        script.contains("gh release create \"v$VERSION\"")
            && script.contains("--draft")
            && script.contains("gh release edit \"v$VERSION\" --draft=false"),
        "release publish pipeline should prepare a draft release before final publication"
    );
    assert!(
        script.find("gh release create \"v$VERSION\"")
            < script.find("cargo publish -p \"$CRATE_PACKAGE_NAME\" --locked"),
        "GitHub draft preparation should happen before crates.io publish"
    );
    assert!(
        script.find("cargo publish -p \"$CRATE_PACKAGE_NAME\" --locked")
            < script.find("gh release edit \"v$VERSION\" --draft=false"),
        "GitHub release publication should happen only after crates.io publish"
    );
}

#[test]
fn makefile_release_build_uses_shared_bundle_entrypoint() {
    let make_surface = format!(
        "{}\n{}",
        read_repo_file("Makefile"),
        read_repo_file("mk/rust.mk")
    );
    assert!(
        make_surface.contains("scripts/cueloop-cli-bundle.sh --configuration Release"),
        "Makefile release builds should route through the shared CLI bundling entrypoint"
    );
    assert!(
        !make_surface.contains("cargo build --workspace --release --locked"),
        "Makefile should not keep a separate direct cargo release-build path"
    );
    assert!(
        !make_surface.contains("publish-crate:"),
        "Makefile should not expose a direct crates.io publish bypass outside the release transaction"
    );
}

#[test]
fn makefile_does_not_expose_release_verify_as_dry_run() {
    let make_surface = format!(
        "{}\n{}",
        read_repo_file("Makefile"),
        read_repo_file("mk/rust.mk")
    );
    assert!(
        make_surface.contains("release-verify:"),
        "Makefile should keep release-verify as the canonical release verification target"
    );
    assert!(
        !make_surface.contains("release-dry-run"),
        "Makefile should not expose or advertise release-dry-run because release verification mutates local release metadata"
    );
    assert!(
        make_surface.contains("Mutating local preflight: prepares the exact release snapshot that make release will publish"),
        "Makefile help should describe release-verify as a mutating local preflight"
    );
}