use std::sync::OnceLock;
use crate::change_request::{canonical_change_request, ChangeRequest};
pub const CHANGE_PATH: &str = "requested-change.lino";
fn cached_change_request() -> &'static ChangeRequest {
static REQUEST: OnceLock<ChangeRequest> = OnceLock::new();
REQUEST.get_or_init(canonical_change_request)
}
pub const CHANGE_TASK: &str =
"I want to change Formal AI itself: please add a new capability to the system, and \
route my request through the same human-gated review loop that produces a \
requirement, a test, and a patch plan I can review as a pull request.";
const CHANGE_KEYWORDS: [&str; 6] = [
"change formal ai",
"modify formal ai",
"add a capability to formal ai",
"add a new capability to the system",
"change the ai system",
"change formal ai itself",
];
#[must_use]
pub fn is_change_request_task(prompt: &str) -> bool {
let lower = prompt.to_lowercase();
if CHANGE_KEYWORDS
.iter()
.any(|keyword| lower.contains(keyword))
{
return true;
}
let targets_the_system = lower.contains("formal ai")
|| lower.contains("the ai system")
|| lower.contains("the system itself");
let asks_to_change = (lower.contains("change")
|| lower.contains("modify")
|| lower.contains("add a"))
&& (lower.contains("capability") || lower.contains("feature") || lower.contains("support"));
targets_the_system && asks_to_change
}
#[must_use]
pub fn render_document() -> String {
format!("{}\n", cached_change_request().links_notation().trim_end())
}
#[must_use]
pub fn change_request() -> ChangeRequest {
cached_change_request().clone()
}
#[must_use]
pub fn final_answer(document: &str) -> String {
let request = cached_change_request();
format!(
"Turned your change request into a reviewable pull request: it derives the requirement \
\"{requirement}\", proposes the test `{test}`, and a {steps}-step patch plan against the \
grounded module {target}. Nothing is applied — the change merges only through the same \
human-gated loop: a green benchmark gate and your explicit approval. Neural inference is \
not used; the requirement, test, and patch plan are a deterministic function of your \
request and its grounded target.\n\n\
Generated document ({CHANGE_PATH}):\n\n{document}",
requirement = request.derived_requirement,
test = request.proposed_test,
steps = request.patch_plan.len(),
target = request.target_module,
document = document.trim_end(),
)
}