ADR-0022: Detection-tuning as the third skill — graded outcomes, corpus-as-input, manifest dispatch¶
- Status: Accepted (architecture as built 2026-05-25; skill set aside — see Consequences)
- Date: 2026-05-25
- Deciders: Ken Rollins
- Related: ADR-0020, ADR-0023
Recorded after the fact (2026-06-13) to file the decision that built the third skill. The architecture below is as-built; the build narrative and honest outcome are in
journey/39, the original proposal infutures/detection-tuning-skill.
Context¶
STIG (ADR-0006) and CVE remediation were the first two skills on the Ralph harness. Both are the same problem shape: a binary evaluator (rule passes or fails an OpenSCAP/OVAL rescan), a system-state target, fix-and-rescan. CVE was internally judged "underwhelming" precisely because its loop duplicated STIG's — it proved the harness handled a sibling, not a structurally different problem.
The "skills are pluggable" claim needed a test against a problem shape that was genuinely different along three axes:
- Outcome type — statistical (precision/recall/F1 in [0,1]), not boolean.
- Target — the artifact under change is a spec (a detection rule), not a running system; there is no mission app to protect.
- Cross-run intelligence — the transferable knowledge is authoring
patterns ("use
Image|endswithnotImage|contains"), not remediation patterns tied to a host.
Detection engineering (tuning Sigma rules against labeled threat-telemetry corpora) is the candidate that exercises all three. If the same five-interface harness handles it, the architecture is not STIG-shaped.
Decision¶
Build one generic skills/detection-tuning/ skill on the existing
harness, with the following architecture:
- Corpus as a per-run input, not per-corpus skills.
forge run detection-tuning --corpus <name>. The tip pool is corpus-independent (Sigma authoring patterns transfer across corpora), so per-corpus skills (detection-tuning-bots,…-optc) are rejected — they would fragment the pool and kill the cross-corpus-transfer value. - Graded evaluator. The skill declares
signal_type=graded(continuous F1, not binary). PASS bar:precision ≥ 0.95 AND recall ≥ 0.80, withF1 ≥ 0.85as the fallback framing. Failure taxonomy:RULE_TOO_NOISY,RULE_TOO_NARROW,RULE_PARSE_FAILURE,CORPUS_GAP(escalate),NEEDS_BASELINE(escalate). - Manifest-driven dispatch. The skill declares its runtime builder in
skill.yaml'sruntime:block;ralph.pycarries zero references to "detection-tuning". This is the first skill wired entirely this way — making the "drop a skill dir and the harness picks it up" claim empirically defensible. worker_contextfor a graded domain (ADR-0020/DEF-28). Returns{sigma_schema_excerpt, sample_events_for_technique, prior_rule_version}— the authoritative spec of a valid rule plus a representative sample of what it must catch. First application of the Protocol outside STIG's XCCDF descriptions.- Sub-runtimes:
DetectionWorkQueue(loads rules per--corpus),DetectionExecutor(writes the candidate rule),DetectionEvaluator(Sigma → SPL viasigmac→ corpus → P/R/F1 + failure class),DetectionCheckpoint(git stash-shaped — rules are text), andDetectionSkillRuntimebundling them. - Develop against EVTX-ATTACK-SAMPLES (lowest friction, Sigma-native); hold DARPA OpTC as the higher-credibility corpus for later.
Zero harness changes — pure skill-side work, by design.
Alternatives considered¶
-
A binary evaluator (STIG-shaped) for detection too. Rejected: it would duplicate the CVE mistake and prove nothing new. The whole point was to exercise
signal_type=graded, which had never run before this skill. -
Per-corpus skills. Rejected: the cross-run intelligence is corpus-independent Sigma authoring patterns; per-corpus skills fragment the tip pool and undermine the transfer-across-corpora claim that is the skill's architectural value.
-
Don't build a third skill. Rejected: with only STIG + a STIG-shaped CVE sibling, "skills are pluggable" remained asserted, not demonstrated. A structurally different third skill was the cheapest way to test it.
-
Target a native SIEM language (Splunk SPL / Elastic ESQL) instead of Sigma. Set aside: Sigma is portable and
sigmac-translatable to most targets, which keeps the skill audience-agnostic. A native-format variant remains open if a specific audience warrants it.
Consequences¶
Positive¶
- The harness is not STIG-shaped. Graded outcomes, spec-as-target, and corpus-as-input all ran on the unchanged five-interface harness.
worker_contextgeneralizes beyond STIG — a real second-domain data point for ADR-0020.- Manifest dispatch works —
ralph.pyinstantiated a skill it has no knowledge of, fromskill.yamlalone. - Cross-corpus tip transfer was observed — authoring patterns measurably carried across corpora, the bigger version of the memory-stack value prop.
- The architecture transfers directly to the fourth skill
(ADR-0023), which reused this
manifest + sub-runtime +
worker_contextshape.
Negative / accepted trade-offs¶
- The skill itself produced 0/5 PASS on the public corpora (both runs).
Two causes, both downstream of framing, not the harness: the PASS bar
(
P ≥ 0.95 AND R ≥ 0.80, generic-ML thresholds) was misaligned with how detection engineers actually tune, and the corpora label at the file level (EVTX-ATTACK-SAMPLES, SDS), capping achievable F1 around 0.7–0.75 regardless of rule quality. Seejourney/39. - The skill is set aside as a standalone result while retained as architectural validation. A skill that proves the architecture is not automatically a skill that produces a clean result — both properties matter, and this one had the first without the second.
- A graded evaluator needs careful, domain-true thresholds; lifting generic-ML numbers is a trap this skill walked into and documented.
References¶
futures/detection-tuning-skill— the original proposaljourney/39— the build + honest 0/5 outcome- ADR-0020 — the
worker_contextProtocol this skill exercises in a graded domain - ADR-0023 — the fourth skill, which reuses this architecture