specfold_core/audit/
plugins.rs1use super::types::{Item, Kind};
4use crate::corpus::Corpus;
5use crate::graph::Graph;
6use crate::plugins::{self, payload, process};
7use serde::Deserialize;
8use serde_json::json;
9
10#[derive(Deserialize)]
11struct PluginItem {
12 subject: String,
13 #[serde(default)]
14 path: String,
15 #[serde(default)]
16 line: usize,
17 detail: String,
18 next: Option<String>,
19}
20
21#[derive(Deserialize)]
22struct Response {
23 #[serde(default)]
24 items: Vec<PluginItem>,
25}
26
27pub fn run(c: &Corpus, g: &Graph, out: &mut Vec<Item>) {
28 for p in plugins::load(&c.cfg) {
29 let Ok(d) = &p.description else { continue };
30 if d.provides.audits.is_empty() {
31 continue;
32 }
33 let params =
34 json!({"audits": d.provides.audits, "docs": payload::docs(c, None), "edges": payload::edges(c, g)});
35 match process::call::<Response>(&c.cfg, &p.def, "audit.run", params) {
36 Ok(r) => out.extend(r.items.into_iter().map(|x| Item {
37 kind: Kind::Plugin,
38 subject: x.subject,
39 path: x.path,
40 line: x.line,
41 detail: format!("[{}] {}", p.def.name, x.detail),
42 next: x.next,
43 })),
44 Err(e) => out.push(Item {
45 kind: Kind::Plugin,
46 subject: p.def.name.clone(),
47 path: "spec.toml".into(),
48 line: 0,
49 detail: e.to_string(),
50 next: None,
51 }),
52 }
53 }
54}