diff --git a/server/src/agents/gates.rs b/server/src/agents/gates.rs index 7d93ff93..e3ddbd26 100644 --- a/server/src/agents/gates.rs +++ b/server/src/agents/gates.rs @@ -212,33 +212,6 @@ fn run_command_with_timeout( } } -/// Run the documentation coverage gate for the given worktree. -/// -/// Invokes `cargo run --quiet -p source-map-gen --bin source-map-check` in -/// `path`, comparing the current branch against its detected base branch -/// (`master` or `main`). Returns `(passed, combined_output)`. -pub(crate) fn run_doc_coverage_gate(path: &Path) -> Result<(bool, String), String> { - let base = detect_worktree_base_branch(path); - let base_str = base.as_str(); - run_command_with_timeout( - "cargo", - &[ - "run", - "--quiet", - "-p", - "source-map-gen", - "--bin", - "source-map-check", - "--", - "--worktree", - ".", - "--base", - base_str, - ], - path, - ) -} - /// Run `cargo clippy` and the project test suite (via `script/test` if present, /// otherwise `cargo nextest run` / `cargo test`) in the given directory. /// Returns `(gates_passed, combined_output)`. @@ -268,19 +241,6 @@ pub(crate) fn run_acceptance_gates(path: &Path) -> Result<(bool, String), String return Ok((false, test_out)); } - // Doc coverage gate (defence in depth): verify all public items in files - // changed since the base branch have doc comments. This gate catches - // projects that do not include source-map-check in their script/test, and - // provides an actionable "Doc coverage gate failed:" preamble so the agent - // knows exactly what to fix on retry. - let (doc_ok, doc_out) = run_doc_coverage_gate(path)?; - if !doc_ok { - return Ok(( - false, - format!("{test_out}Doc coverage gate failed:\n{doc_out}"), - )); - } - Ok((true, test_out)) } @@ -599,181 +559,6 @@ mod tests { ); } - // ── run_acceptance_gates doc-coverage tests ─────────────────────────────── - - /// Create a git worktree from the actual huskies workspace on a fresh - /// branch (``) rooted at `master`. Returns the path to the - /// worktree. Call `cleanup_worktree` when done. - #[cfg(unix)] - fn create_test_worktree(branch: &str) -> std::path::PathBuf { - let workspace = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR")) - .parent() - .unwrap() - .to_path_buf(); - let wt = std::env::temp_dir().join(branch.replace('/', "_")); - // Remove any stale worktree from a previous failed run. - let _ = Command::new("git") - .args(["worktree", "remove", "--force", wt.to_str().unwrap()]) - .current_dir(&workspace) - .output(); - let _ = Command::new("git") - .args(["branch", "-D", branch]) - .current_dir(&workspace) - .output(); - - let out = Command::new("git") - .args([ - "worktree", - "add", - wt.to_str().unwrap(), - "-b", - branch, - "master", - ]) - .current_dir(&workspace) - .output() - .expect("git worktree add"); - assert!( - out.status.success(), - "git worktree add failed: {}", - String::from_utf8_lossy(&out.stderr) - ); - wt - } - - /// Remove the test worktree and its branch from the workspace. - #[cfg(unix)] - fn cleanup_worktree(branch: &str, wt: &std::path::Path) { - let workspace = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR")) - .parent() - .unwrap() - .to_path_buf(); - let _ = Command::new("git") - .args(["worktree", "remove", "--force", wt.to_str().unwrap()]) - .current_dir(&workspace) - .output(); - let _ = Command::new("git") - .args(["branch", "-D", branch]) - .current_dir(&workspace) - .output(); - } - - /// Write a `.cargo/config.toml` inside `wt` that redirects the build - /// target directory to the shared workspace `target/` so `cargo run` - /// finds the already-compiled `source-map-check` binary without - /// recompiling. - #[cfg(unix)] - fn set_shared_target(wt: &std::path::Path) { - use std::fs; - let workspace = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR")) - .parent() - .unwrap() - .to_path_buf(); - let target_dir = workspace.join("target"); - let cargo_dir = wt.join(".cargo"); - fs::create_dir_all(&cargo_dir).unwrap(); - fs::write( - cargo_dir.join("config.toml"), - format!( - "[build]\ntarget-dir = \"{}\"\n", - target_dir.to_str().unwrap() - ), - ) - .unwrap(); - } - - /// Write and chmod a minimal `script/test` that exits 0 without running - /// the full test suite. The file is left uncommitted so `run_project_tests` - /// uses it but it does not appear in the doc-check diff. - #[cfg(unix)] - fn write_fast_script_test(wt: &std::path::Path) { - use std::fs; - use std::os::unix::fs::PermissionsExt; - let script = wt.join("script").join("test"); - fs::write(&script, "#!/usr/bin/env bash\nexit 0\n").unwrap(); - let mut perms = fs::metadata(&script).unwrap().permissions(); - perms.set_mode(0o755); - fs::set_permissions(&script, perms).unwrap(); - } - - /// Commit a single Rust file in the worktree. - #[cfg(unix)] - fn commit_file(wt: &std::path::Path, rel_path: &str, content: &str) { - use std::fs; - let full = wt.join(rel_path); - if let Some(parent) = full.parent() { - fs::create_dir_all(parent).unwrap(); - } - fs::write(&full, content).unwrap(); - Command::new("git") - .args(["add", rel_path]) - .current_dir(wt) - .output() - .unwrap(); - Command::new("git") - .args([ - "-c", - "user.email=test@test.com", - "-c", - "user.name=Test", - "commit", - "-m", - "test: add file for doc gate test", - ]) - .current_dir(wt) - .output() - .unwrap(); - } - - #[cfg(unix)] - #[test] - fn run_acceptance_gates_fails_on_undocumented_pub_fn() { - let branch = format!("test/doc-gate-fail-story-860-{}", std::process::id()); - let wt = create_test_worktree(&branch); - - set_shared_target(&wt); - write_fast_script_test(&wt); - commit_file( - &wt, - "server/src/_doc_gate_test_undoc.rs", - "pub fn undocumented_gate_test_fn() {}\n", - ); - - let result = run_acceptance_gates(&wt); - cleanup_worktree(&branch, &wt); - - let (passed, output) = result.unwrap(); - assert!(!passed, "acceptance gates should fail; output:\n{output}"); - assert!( - output.contains("Doc coverage gate failed:"), - "output should contain 'Doc coverage gate failed:'; got:\n{output}" - ); - } - - #[cfg(unix)] - #[test] - fn run_acceptance_gates_passes_with_documented_pub_fn() { - let branch = format!("test/doc-gate-pass-story-860-{}", std::process::id()); - let wt = create_test_worktree(&branch); - - set_shared_target(&wt); - write_fast_script_test(&wt); - commit_file( - &wt, - "server/src/_doc_gate_test_doc.rs", - "//! Test module for the doc-coverage happy-path gate test.\n/// A test function that is properly documented.\npub fn documented_gate_test_fn() {}\n", - ); - - let result = run_acceptance_gates(&wt); - cleanup_worktree(&branch, &wt); - - let (passed, output) = result.unwrap(); - assert!( - passed, - "acceptance gates should pass for documented pub fn; output:\n{output}" - ); - } - // ── worktree_has_committed_work tests ───────────────────────────────────── #[test]