use crate::rules::{Confirmed, Context, Evidence, Examine, Finding, Rule, Stance, Trend};
use crate::shell::Parsed;
pub const RULE: Rule = Rule {
id: crate::implementation_review::RULE_ID,
default_stance: Stance::Advise,
max_stance: Stance::Deny,
evidence: Evidence {
per_1000: 0.0,
measured: "2026-09-29",
trend: Trend::Rare,
},
examine: Examine::Legacy(examine),
confirm: Some(confirm),
};
const REMEDY: &str = "worktree-task F4b: `amont-agent tree-sha --block`, then launch the \
implementation-review agent with the plan, the diff and the active rules; \
a stale or rework review gets ONE delta with the round-1 findings, and a \
rework that survives it goes to the person on a marked question \
(`[implementation-review <repo>@<sha>]`, options exactly Overrule / Fix / Hold).";
fn examine(parsed: &Parsed) -> Option<Finding> {
if let Some(cmd) = crate::push_target::find(parsed) {
if cmd.is_dry_run() || cmd.has_short('n') {
return None;
}
if cmd
.operands()
.iter()
.skip(2)
.any(|w| to_default_branch(&w.text))
{
return None;
}
return Some(Finding {
reason:
"This push carries a plan whose implementation no independent reviewer has read."
.to_string(),
remedy: REMEDY.to_string(),
span: cmd.at..cmd.end,
});
}
None
}
fn to_default_branch(refspec: &str) -> bool {
let dst = refspec.rsplit(':').next().unwrap_or(refspec);
let dst = dst.strip_prefix('+').unwrap_or(dst);
let dst = dst.strip_prefix("refs/heads/").unwrap_or(dst);
matches!(dst, "main" | "master")
}
fn confirm(ctx: &Context, _finding: &Finding) -> Confirmed {
let stance = crate::stance::resolve(&RULE);
match crate::push_target::find(ctx.parsed) {
Some(cmd) => crate::implementation_review::confirm_push(ctx, cmd, stance),
None => Confirmed::No("the push could not be read a second time"),
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::shell::lex;
fn fires(command: &str) -> bool {
examine(&lex(command)).is_some()
}
#[test]
fn a_push_is_examined() {
assert!(fires("git push -u origin feat/x"));
assert!(fires("cd ../wt && git push origin HEAD:feat/x"));
assert!(fires("git -C ../wt push origin feat/x"));
}
#[test]
fn a_dry_run_the_default_branch_and_other_commands_are_not() {
assert!(!fires("git push --dry-run origin feat/x"));
assert!(!fires("git push -n origin feat/x"));
assert!(!fires("git pull"));
assert!(!fires("echo git push"));
assert!(!fires("git push origin main"));
assert!(!fires("git push origin HEAD:refs/heads/master"));
}
}