use crate::declarations::Declaration;
use crate::runner::MARKER;
use crate::trailer::{ADVISORY_SHAPE, COUNTS_SHAPE};
const TEMPLATE: &str = include_str!("prompt.md");
const LADDER: &str = "MAJOR — blocks the commit, and is reviewed again.
The work is wrong, or has a severe flaw. An incremental fix will not reach the right answer.
MODERATE — must fix, no re-review.
The outcome is right, the execution is not. The author fixes it. Nobody checks the fix.
MINOR — optional: fix it, or leave it. Recorded either way.
Grade by what is wrong, not by what the fix costs.
A MODERATE rounded up to MAJOR sends back work that is already right.
A MAJOR rounded down to MODERATE leaves a defect nobody has to fix.";
const LADDER_ADVISORY: &str =
"This gate has no MAJOR rung. Nothing you report blocks the commit, and there is no re-review.
MODERATE — must fix, no re-review.
The outcome is right, the execution is not. The author fixes it. Nobody checks the fix.
MINOR — optional: fix it, or leave it. Recorded either way.
Grade by what is wrong, not by what the fix costs.
A MINOR rounded up to MODERATE makes work for the author that nobody asked for.";
const JUDGE: &str =
"You judge one line of text. Do not review any code, and do not read the repository.
The <diff-intent> you are given states what a change does. Refuse it if it does any of these:
- gives a reason the change is worth doing
- defends the approach
- says what it replaces
- says what was already tried
Answer with exactly one line, and nothing after it:
{{marker}} accepted
or, naming which of the four it does and quoting the words that do it:
{{marker}} refused — <which one, and the words>
";
pub fn judge_system() -> String {
JUDGE.replace("{{marker}}", MARKER)
}
pub fn judge_prompt(intent: &str) -> String {
format!("<diff-intent>{intent}</diff-intent>\n")
}
fn built_in(text: &str) -> String {
text.lines().skip(1).collect::<Vec<_>>().join("\n")
}
fn asked_of(simple: bool) -> &'static str {
if simple {
ADVISORY_SHAPE
} else {
COUNTS_SHAPE
}
}
fn scope(paths: &[String]) -> String {
let quoted: Vec<String> = paths
.iter()
.map(|p| format!("'{}'", p.replace('\'', r"'\''")))
.collect();
format!("git diff --cached -- {}", quoted.join(" "))
}
fn criteria(declaration: &Declaration) -> Result<String, String> {
let mut out = String::new();
for doc in &declaration.docs {
let text = std::fs::read_to_string(doc).map_err(|e| format!("--doc {doc}: {e}"))?;
let title = std::path::Path::new(doc)
.file_name()
.map_or_else(|| doc.clone(), |n| n.to_string_lossy().into_owned());
out.push_str(&format!(
"<document title=\"{title}\">\n{}\n</document>\n",
text.trim_end()
));
}
for (n, rule) in declaration.rules.iter().enumerate() {
let n = n + 1;
out.push_str(&format!("<inline-rule-{n}>{rule}</inline-rule-{n}>\n"));
}
Ok(out)
}
pub fn system(declaration: &Declaration) -> Result<String, String> {
let template = match &declaration.brief.prompt {
Some(path) => {
std::fs::read_to_string(path).map_err(|e| format!("--override-prompt {path}: {e}"))?
}
None => built_in(TEMPLATE),
};
let ladder = if declaration.brief.simple {
LADDER_ADVISORY
} else {
LADDER
};
Ok(template
.replace("{{gate}}", &declaration.gate)
.replace("{{criteria}}", &criteria(declaration)?)
.replace("{{scope}}", &scope(&declaration.paths))
.replace("{{ladder}}", ladder)
.replace("{{marker}}", MARKER)
.replace("{{shape}}", asked_of(declaration.brief.simple)))
}
pub fn opening(intent: &str) -> String {
format!(
"<diff-intent>{intent}</diff-intent>\n\nExecute the review per the instructions above.\n"
)
}
pub fn continuing() -> String {
"Fixes incorporated, re-review requested.\n".to_string()
}