1use crate::config::Config;
2
3pub fn pre_commit() -> anyhow::Result<()> {
4 println!("=== dstack quality gate ===\n");
5 let questions = [
6 ("Negative tests?", "Did I test what happens when things go WRONG? (wrong password → 403, invalid input → error, missing field → handled)"),
7 ("Live verification?", "Did I verify against the LIVE system? (not just compilation — actual curl, DB query, or Chrome DevTools)"),
8 ("Companion doc updated?", "Did I update the .implementation.md with DETAILS? (bugs found, DB state, commit hashes — not one-liner 'DONE')"),
9 ("Tests prove the change?", "Would these tests FAIL without my code change? (decorative tests that pass regardless are worthless)"),
10 ("Truly done?", "Am I moving forward because it's TRULY done, or because I want to show progress?"),
11 ];
12 for (i, (short, detail)) in questions.iter().enumerate() {
13 println!(" {}. {} — {}", i + 1, short, detail);
14 }
15 println!("\nAnswer honestly before committing. These exist because skipping them cost us a client meeting.");
16 Ok(())
17}
18
19pub fn stale(cfg: &Config) -> anyhow::Result<()> {
20 eprintln!("Scanning for stale files across tracked repos...\n");
21 let mut found = 0;
22 for repo in &cfg.repos.tracked {
23 let path = format!("{}/{}", cfg.repos.root, repo);
24 if !std::path::Path::new(&path).exists() {
25 continue;
26 }
27 let output = std::process::Command::new("find")
29 .args([&path, "-name", "*.implementation.md", "-mtime", "+14", "-type", "f"])
30 .output()?;
31 for line in String::from_utf8_lossy(&output.stdout).lines() {
32 if !line.is_empty() {
33 println!("STALE (>14d): {}", line);
34 found += 1;
35 }
36 }
37 }
38 if found == 0 {
39 println!("No stale companion docs found.");
40 } else {
41 println!("\n{} stale file(s). Update or remove them.", found);
42 }
43 Ok(())
44}