a3s 0.10.3

a3s — A3S coding agent CLI; `a3s code` launches the interactive TUI
Documentation
fn exists_nonempty(path: &Path) -> bool {
    path.is_file()
        && std::fs::metadata(path)
            .map(|m| m.len() > 0)
            .unwrap_or(false)
}

pub(crate) fn audit_loop(spec: &LoopSpec) -> LoopAudit {
    let mut score = 0u8;
    let mut passed = Vec::new();
    let mut missing = Vec::new();
    let mut warnings = Vec::new();
    let mut add = |points: u8, ok: bool, pass: &str, miss: &str| {
        if ok {
            score = score.saturating_add(points);
            passed.push(pass.to_string());
        } else {
            missing.push(miss.to_string());
        }
    };
    add(
        10,
        !spec.goal.trim().is_empty(),
        "single clear goal",
        "add a single-sentence goal",
    );
    add(
        10,
        exists_nonempty(&spec.dir.join(STATE_FILE)),
        "durable STATE.md",
        "create STATE.md",
    );
    add(
        10,
        exists_nonempty(&spec.dir.join(RUN_LOG_FILE)),
        "append-only RUN_LOG.md",
        "create RUN_LOG.md",
    );
    add(
        10,
        exists_nonempty(&spec.dir.join(BUDGET_FILE)) && spec.budget_tokens_per_day > 0,
        "budget and kill-switch file",
        "create budget.toml with daily caps",
    );
    add(
        10,
        !spec.denylist.is_empty(),
        "denylist paths configured",
        "add denylist paths for secrets/infra",
    );
    add(
        15,
        !spec.maker_agent.is_empty()
            && !spec.checker_agent.is_empty()
            && spec.maker_agent != spec.checker_agent,
        "maker/checker split",
        "configure separate maker_agent and checker_agent",
    );
    let agent_loop = spec.level == "A2";
    let goal_loop = spec.level == "G1";
    add(
        10,
        spec.worktree || agent_loop || goal_loop,
        if agent_loop {
            "agent asset scope requested"
        } else if goal_loop {
            "goal scope is guarded by the active session"
        } else {
            "worktree isolation requested"
        },
        if agent_loop {
            "scope the loop to one agent definition"
        } else {
            "enable worktree isolation before L2"
        },
    );
    add(
        10,
        if agent_loop || goal_loop {
            !spec.os_runtime && !spec.connectors.iter().any(|c| c == "os-runtime")
        } else {
            spec.os_runtime && spec.connectors.iter().any(|c| c == "os-runtime")
        },
        if agent_loop {
            "local agent loop runtime"
        } else if goal_loop {
            "local goal loop runtime"
        } else {
            "OS Runtime connector enabled"
        },
        if agent_loop {
            "disable OS Runtime for local /agent loops"
        } else {
            "enable os_runtime/connectors=[\"os-runtime\"]"
        },
    );
    let skill_pair = if goal_loop {
        exists_nonempty(&spec.dir.join("skills").join("maker.md"))
            && exists_nonempty(&spec.dir.join("skills").join("verifier.md"))
    } else {
        exists_nonempty(&spec.dir.join("skills").join("triage.md"))
            && exists_nonempty(&spec.dir.join("skills").join("verifier.md"))
    };
    add(
        15,
        skill_pair,
        if goal_loop {
            "maker and verifier skills"
        } else {
            "triage and verifier skills"
        },
        if goal_loop {
            "add skills/maker.md and skills/verifier.md"
        } else {
            "add skills/triage.md and skills/verifier.md"
        },
    );
    if spec.level == "L3" && score < 90 {
        warnings.push("L3 requested but readiness is below unattended threshold".to_string());
    }
    if spec.level != "L1" && spec.level != "A2" && spec.level != "G1" && !spec.worktree {
        warnings.push("acting loops should use worktree isolation".to_string());
    }
    let level = if score >= 90 {
        "L3-ready"
    } else if score >= 75 {
        "L2-ready"
    } else if score >= 50 {
        "L1-ready"
    } else {
        "L0-draft"
    }
    .to_string();
    LoopAudit {
        score,
        level,
        passed,
        missing,
        warnings,
    }
}