garak/analyze/report_digest.py parses garak JSONL report files and generates structured report data for HTML/digest output, serving as the main entry point for report generation.[1] At module import time, report_digest.py calls _config.load_config() if the config is not already loaded, ensuring config is always available even when the module is used standalone.[1] Also at import time, report_digest.py loads MISP tag descriptions from data/tags.misp.tsv — a tab-separated file with columns key, title, and descr — used to annotate taxonomy-grouped probe report sections.[1] report_digest.py loads CAS intent names from data/cas/trait_typology.json at import time, normalizing empty name values to None; these names drive the technique×intent matrix display in reports.[1] The constant TECHNIQUE_TAG_PREFIX = "demon:" defines the probe tag namespace used to identify technique tags for the technique×intent matrix in HTML reports.[1]
report_digest.py uses an in-memory SQLite database (:memory:) to store and query per-probe evaluation results during report generation.[1] The results table stores probe_module, probe_group, probe_class, detector, score, instances, passes, and bootstrap confidence interval fields (confidence, confidence_lower, confidence_upper).[1] _init_populate_result_db() strips the probes. prefix from probe paths and the detector. prefix from detector paths before inserting rows into the results database.[1] When a taxonomy is provided to _init_populate_result_db(), probe grouping is determined by matching probe tags against the taxonomy prefix; probes with no matching tag are placed in the "other" group. Without a taxonomy, probes are grouped by their module name.[1] If a report references a probe not found in the plugin cache, _init_populate_result_db() raises ReportIncompatibleError with a message indicating the report was likely generated with a different garak version.[1]
_parse_report() falls back to a deep copy of the live garak._plugins.PluginCache.instance() tagged with garak.__version__ when no plugin_cache entry is found in the JSONL report, meaning such reports are interpreted using the currently-installed garak plugin metadata.[1] _extract_to_probespec() resolves the probe selection used in a run: it reads transient.active_probes first, falls back to plugins.probe_spec for older reports, and defaults to "probes.*" if neither is present — providing backward compatibility with pre-transient.active_probes report formats.[1] _report_header_content() resolves the target type and name using plugins.target_type/plugins.target_name, falling back to the deprecated plugins.model_type/plugins.model_name keys introduced before the v0.13.1 rename.[1] _resolve_plugin_info() raises ValueError if the requested plugin classpath is missing from the plugin cache, or if any of the required_fields are absent or None in the cached metadata.[1]
_get_probe_group_summaries() returns probes within a group sorted by minimum score ascending, then by probe class name, so the most-failed probes appear first.[1] _get_group_info() computes a DEFCON rating for each probe group using garak.analyze.score_to_defcon() with ABSOLUTE_DEFCON_BOUNDS, and includes the group's aggregation function name in the returned dict.[1] When no taxonomy is set, _get_group_info() dynamically imports garak.probes.<module> to extract its docstring as the group description, and builds a link to https://reference.garak.ai/en/latest/garak.probes.<probe_group>.html.[1]
Sources