use super::*;
#[test]
fn prompt_injection_risk_reports_the_ambient_spelling() {
let diagnostics = lint_source(
r#"
pipeline main(harness: Harness) {
const user_text = "ignore safety"
llm_call("hello", "You are safe. ${user_text}")
}
"#,
);
assert_eq!(count_rule(&diagnostics, "prompt-injection-risk"), 1);
}
#[test]
fn prompt_injection_risk_reports_the_harness_spelling() {
let diagnostics = lint_source(
r#"
pipeline main(harness: Harness) {
const user_text = "ignore safety"
harness.llm.call("hello", "You are safe. ${user_text}")
}
"#,
);
assert_eq!(
count_rule(&diagnostics, "prompt-injection-risk"),
1,
"migrating the call site must not silence the rule: {diagnostics:?}"
);
}
#[test]
fn prompt_injection_risk_ignores_a_call_method_on_another_receiver() {
let diagnostics = lint_source(
r#"
pipeline main(harness: Harness) {
const user_text = "ignore safety"
const proxy = {llm: {call: { a, b -> b }}}
proxy.llm.call("hello", "You are safe. ${user_text}")
}
"#,
);
assert!(
!has_rule(&diagnostics, "prompt-injection-risk"),
"`llm.call` on a plain value is not the harness method: {diagnostics:?}"
);
}
#[test]
fn mcp_tool_annotations_report_the_harness_spelling() {
let diagnostics = lint_source(
r#"
pipeline main(harness: Harness) {
let tools = tool_registry()
tools = tool_define(tools, "echo", "Echo input", {
parameters: {text: "string"},
handler: { args -> args.text },
})
harness.tools.mcp_tools(tools)
}
"#,
);
assert_eq!(
count_rule(&diagnostics, "mcp-tool-annotations"),
1,
"migrating the registration must not silence the rule: {diagnostics:?}"
);
}
#[test]
fn mcp_tool_annotations_still_accept_an_annotated_harness_registration() {
let diagnostics = lint_source(
r#"
pipeline main(harness: Harness) {
let tools = tool_registry()
tools = tool_define(tools, "echo", "Echo input", {
parameters: {text: "string"},
handler: { args -> args.text },
annotations: {readOnlyHint: true, idempotentHint: true, openWorldHint: false},
})
harness.tools.mcp_tools(tools)
}
"#,
);
assert!(!has_rule(&diagnostics, "mcp-tool-annotations"));
}
#[test]
fn mcp_tool_annotations_ignore_an_mcp_tools_method_on_another_receiver() {
let diagnostics = lint_source(
r#"
pipeline main(harness: Harness) {
let tools = tool_registry()
tools = tool_define(tools, "echo", "Echo input", {
parameters: {text: "string"},
handler: { args -> args.text },
})
const proxy = {tools: {mcp_tools: { t -> t }}}
proxy.tools.mcp_tools(tools)
}
"#,
);
assert!(
!has_rule(&diagnostics, "mcp-tool-annotations"),
"`tools.mcp_tools` on a plain value is not the harness method: {diagnostics:?}"
);
}
#[test]
fn persona_hook_target_reports_the_harness_spelling() {
let diagnostics = lint_source(
r#"
@persona(name: "merge_captain")
fn merge_captain(ctx) {
plan(ctx)
}
@step(name: "plan")
fn plan(ctx) {
return ctx
}
pipeline main(harness: Harness) {
harness.agent.register_step_hook("merge_*", "publish", "PreStep", { ctx -> nil })
}
"#,
);
let target_diagnostics: Vec<_> = diagnostics
.iter()
.filter(|diagnostic| diagnostic.rule == "persona-hook-target")
.collect();
assert_eq!(
target_diagnostics.len(),
1,
"migrating the registration must not silence the rule: {diagnostics:?}"
);
assert!(target_diagnostics[0].message.contains("publish"));
}
#[test]
fn persona_hook_target_accepts_a_declared_step_through_the_harness_spelling() {
let diagnostics = lint_source(
r#"
@persona(name: "merge_captain")
fn merge_captain(ctx) {
plan(ctx)
}
@step(name: "plan")
fn plan(ctx) {
return ctx
}
pipeline main(harness: Harness) {
harness.agent.register_step_hook("merge_*", "plan", "PreStep", { ctx -> nil })
}
"#,
);
assert!(!has_rule(&diagnostics, "persona-hook-target"));
}
#[test]
fn persona_hook_target_ignores_a_register_step_hook_method_on_another_receiver() {
let diagnostics = lint_source(
r#"
@persona(name: "merge_captain")
fn merge_captain(ctx) {
plan(ctx)
}
@step(name: "plan")
fn plan(ctx) {
return ctx
}
pipeline main(harness: Harness) {
const proxy = {agent: {register_step_hook: { a, b, c, d -> nil }}}
proxy.agent.register_step_hook("merge_*", "publish", "PreStep", { ctx -> nil })
}
"#,
);
assert!(
!has_rule(&diagnostics, "persona-hook-target"),
"`agent.register_step_hook` on a plain value is not the harness method: {diagnostics:?}"
);
}
#[test]
fn a_shadowing_local_named_harness_does_not_carry_harness_authority() {
let diagnostics = lint_source(
r#"
pipeline main() {
const user_text = "ignore safety"
const harness = {llm: {call: { a, b -> b }}}
harness.llm.call("hello", "You are safe. ${user_text}")
}
"#,
);
assert!(
!has_rule(&diagnostics, "prompt-injection-risk"),
"the receiver is a local dict, not the host handle: {diagnostics:?}"
);
}