AgentSkillsCN

rule-authoring

创建或更新Inspequte分析规则与Harness测试用例。适用于新增规则、修改规则元数据,或为src/rules/*.rs中的规则编写JVM Harness测试时使用。

SKILL.md
--- frontmatter
name: rule-authoring
description: Create or update inspequte analysis rules and harness-based tests. Use when adding new rules, modifying rule metadata, or writing JVM harness tests for rules in src/rules/*.rs.

Rule authoring (inspequte)

Workflow

  1. Define rule metadata: unique id, clear name, and short description.
  2. Write rule messages for end users so they are intuitive and actionable: explain what is wrong and what to change to fix it.
  3. Add #[derive(Default)] to the rule struct (required for automatic registration).
  4. Add crate::register_rule!(RuleName); after the struct declaration to enable automatic discovery.
  5. Implement Rule::run using AnalysisContext and helpers from crate::rules (ex: result_message, method_location_with_line, class_location). Always guard rule scans with if !context.is_analysis_target_class(class) { continue; } so classpath-only classes are skipped.
  6. Add harness tests in the same rule file (#[cfg(test)]): compile Java sources with JvmTestHarness, analyze, then assert on rule_id and message text.
  7. Declare the new rule module in src/rules/mod.rs (ex: pub(crate) mod my_new_rule;).
  8. Update SARIF snapshot tests if rule list changes (see tests/snapshots/ and INSPEQUTE_UPDATE_SNAPSHOTS=1 cargo test sarif_callgraph_snapshot).
  9. Keep output deterministic (results are sorted by rule_id/message; avoid non-deterministic ordering in rule code).

Note: Rules are automatically discovered and registered at compile time using the inventory crate. No manual registration in src/engine.rs is needed.

See references/rule-checklist.md for a compact checklist.

Harness testing

  • Use JvmTestHarness::new(); it requires JAVA_HOME (Java 21).
  • Prefer local stub sources over downloading jars.
  • Filter SARIF results by rule_id for assertions.
  • Cover both happy-path and edge cases: include cases that should report, cases that should not report (false positives), and cases that should not miss reports (false negatives).
  • Use generic names in Java harness code (ex: ClassA, methodOne, varOne) and avoid names from user examples; keep real JDK/library API names where required.

Complete rule example with automatic registration

rust
/// Rule that detects [describe what your rule checks].
#[derive(Default)]
pub(crate) struct MyNewRule;

crate::register_rule!(MyNewRule);

impl Rule for MyNewRule {
    fn metadata(&self) -> RuleMetadata {
        RuleMetadata {
            id: "MY_NEW_RULE",
            name: "My new rule",
            description: "Brief description of what this rule checks",
        }
    }

    fn run(&self, context: &AnalysisContext) -> Result<Vec<SarifResult>> {
        // Implementation here
        Ok(vec![])
    }
}

Harness test template

rust
let harness = JvmTestHarness::new().expect("JAVA_HOME must be set for harness tests");
let sources = vec![SourceFile {
    path: "com/example/Sample.java".to_string(),
    contents: r#"
package com.example;
public class Sample {
    public void run() {
        // code under test
    }
}
"#.to_string(),
}];
let output = harness
    .compile_and_analyze(Language::Java, &sources, &[])
    .expect("run harness analysis");
let messages: Vec<String> = output
    .results
    .iter()
    .filter(|result| result.rule_id.as_deref() == Some("RULE_ID"))
    .filter_map(|result| result.message.text.clone())
    .collect();
assert!(messages.iter().any(|msg| msg.contains("expected")));

Guardrails

  • Keep tests in the rule file to avoid a massive shared test module.
  • Use ASCII-only edits unless the file already uses Unicode.
  • Add doc comments to any new structs.
  • Verify changes with cargo build, cargo test, and cargo audit --format sarif.
  • If cargo audit is unavailable, install it first via cargo install cargo-audit --locked.