Course guides › Function E
cybercommons.ai
Cyber Commons · Course guide

Function E — The Agentic SOC

Every detection has a subject, and a clock

Primary audienceSecurity operations · SOC analysts · detection engineers · incident responders
Start withE1.0
Save as PDF. Export the brochure above, or the whole guide including the lesson-by-lesson run sheet. If a button does not appear, use your browser's Print and choose Save as PDF.
▶
Lightboard recording

Not recorded yet. The script is written — LIGHTBOARD.md, under OVERVIEW E — and it walks this guide from the top to answer one question: is this the function you need?

Video placeholderpublishes automatically from recordings/overview-e.mp4

Overview

The problem

Your SOC was tuned for people. One hour of an agent is roughly 1,400 tool calls across 260 resources; one hour of a person is twelve actions. Every threshold, baseline and playbook you own was set against the second number, and four of the nine things an agent does in an ordinary day are seen by none of the four sensor classes you already bought.

The solution

Build it in five phases, on open source you can run: discover with the sensors you have plus agent telemetry that no product emits, detect against a lake tiered by the queries you actually run with rules mapped to MITRE, understand with bounded investigation and correlation across the fleet, respond with tiers derived from reversibility, and recover with replay, root cause and a policy diff.

How you know it worked

Five intervals, one per phase, and all five are numbers: time to discover, to detect, to understand, to contain, and to recover to target. CyberTravels' detection interval is 194 minutes against a 15-minute target and its manual containment finishes in 34 minutes against a 29-minute breakout. Every lesson says which interval it shortens, or which one it spends on purpose.

Highlights

31Lessons
5Chapters
32Skills you run
67Minutes of reading

Taught duration: about 8 hours (Function A's pace is 16 lessons in 4 hours)

Primary audience: Security operations · SOC analysts · detection engineers · incident responders

Prerequisites: Function A, which builds the system this function is about — at minimum A0.0 and A1.0

Reading: 12,134 words of lesson prose, at 180 words a minute.

What you’ll learn

  1. Say which of the five intervals a given control shortensThe anchor on any page, answered without reading itProved in E1.0
  2. Separate an agent's tempo from a person's, with signalsAction rate, variance, session length, tool breadthProved in E1.1 · E1.2
  3. Write a detection whose subject is named, and score it before it shipsPrecision, recall and firing volume against a benign corpusProved in E2.2 · E2.3 · E2.5
  4. Investigate an agent actor without the three instincts that misfireNaming all three, and what each one gets wrongProved in E3.4
  5. Bound what an investigating agent may touchAdmission rules, written before the investigation startsProved in E3.2
  6. Contain at machine speed and know what the stop left behindTime to halt a fleet, and the tokens still valid afterwardsProved in E4.3 · E4.4 · E4.5
  7. Write a root cause that names a control rather than a personA control, and the indicators the fix movedProved in E5.2 · E5.4

Curriculum

E1 · 4 lessons

Discover — the Sensors, and the Agent-Shaped Hole in Them

Four lessons. E1.0 sets up the clock the whole function is anchored to, and the other three are the discover interval: what an EDR, DLP, CSPM or CNAPP estate actually sees when the actor is an agent, what drift does to a control that was signed off against behaviour that no longer exists, and how to find the agents nobody registered.

E2 · 6 lessons

Detect — the Lake, and Rules Mapped to MITRE

Six lessons on the detect interval. Where agent telemetry lands, then two chapters' worth of argument compressed into four lessons: a detection whose subject is the agent, one whose subject is the platform, one written by a loop and shipped by a human, one generated from an incident and decided by a benign corpus — and the honeypot, which is the detector with no threshold.

E3 · 10 lessons

Understand — Correlation, Intel and the Hunt

Ten lessons, the longest chapter in the function, on the understand interval. It splits cleanly: E3.1–E3.4 are the operator's shift — going from an alert queue to running a loop, bounding what the investigating agent may touch, the context that makes triage work, and the three instincts that misfire when the actor is an agent.

E4 · 5 lessons

Respond — From a Conclusion to the Actor Stopped

Five lessons on the respond interval, and the chapter where the arithmetic is most brutal. What may be done without asking, three runbook tiers at three different speeds, containment at machine speed, who holds stop authority and how long they take to use it, and the fleet kill switch.

E5 · 6 lessons

Recover and Root Cause — From Stopped to Back at Target

Six lessons on recover and root cause: reproducing a run you can defend, a root cause record that names a control, picking the layer the fix belongs in, re-measuring the indicators the incident moved, proposing the policy change and saying what it does not fix, and the regulatory clock — which starts at awareness, not confirmation.

Who should attend?

Security operations. SOC analysts, detection engineers, incident responders, threat hunters and DFIR leads — running a SOC that now has agents in it, and agents watching it. What changes is the analyst's job: directing a loop instead of reading alerts one at a time.

Ideal roleSecurity operations · SOC analysts · detection engineers · incident responders
PrerequisitesFunction A, which builds the system this function is about — at minimum A0.0 and A1.0
Timeabout 8 hours taught, or about 67 minutes of reading

What’s included

Lessons and skills

  • 31 lesson pages: the risk, the control, and the three days
  • 32 skills you run on your own computer
  • Nothing to install beyond Python and Git; the one thing you need is a model
  • Every lesson can be done three ways

In this guide

  • Each lesson’s risk, control, three days and measure, with its skill’s output contract and committed example run
  • A capstone, a quick check, and the pitfalls
  • A prompt bank and a glossary
  • Blocks for running it as a session

Ready to start?

Start at E1.0 →

Taught durationabout 8 hours
Websitecybercommons.ai
Sourcegithub.com/spbreed/cyber-commons

The run sheet, in detail

Use this on your own, or to run Function E for other people. Everything here serves both; the shaded blocks marked For a room are the only parts a solo reader can skip.

Every per-lesson fact below is generated from the lesson sources and the skills — risk, control, the lab, Day 0/1/2, the measure, the command, and each skill's own committed example run. Unlike the Function A guide, it does not carry a hand-verified transcript of every run: sixteen of those were checked by running them, and writing 133 more without running them would be making them up. Trust the run over this page, and correct scripts/exercises/guides.py.

◉How to work through it

On your ownChapter by chapter, in order, and re-read E1.0 before each one — the anchor on every page refers back to it and the function stops cohering if the clock is not in mind. E3 is the longest chapter and splits naturally after E3.4.
With a roomPut the five intervals on the board on the first slide and mark which one each lesson shortens. A room that loses the clock reads this function as thirty-one separate detections.
Splitting it upAnything over about four hours is normally split across sittings, and the chapter boundaries are the splits
The one sentence to holdEvery detection has a subject, and a clock

The chapters

ChapterLessonsWhat it does
E1 Discover — the Sensors, and the Agent-Shaped Hole in ThemE1.0 · E1.1 · E1.2 · E1.34 lessons
E2 Detect — the Lake, and Rules Mapped to MITREE2.1 · E2.2 · E2.3 · E2.4 · E2.5 · E2.66 lessons
E3 Understand — Correlation, Intel and the HuntE3.1 · E3.2 · E3.3 · E3.4 · E3.5 · E3.6 · E3.7 · E3.8 · E3.9 · E3.1010 lessons
E4 Respond — From a Conclusion to the Actor StoppedE4.1 · E4.2 · E4.3 · E4.4 · E4.55 lessons
E5 Recover and Root Cause — From Stopped to Back at TargetE5.1 · E5.2 · E5.3 · E5.4 · E5.5 · E5.66 lessons

Half the time? E1.0 and E1.1, then E2.1 and E2.2, E3.1 and E3.4, E4.3 and E4.4, and E5.2. That is one lesson or two per interval and the clock still closes.

For a room

E3.5–E3.10 run well as a single discussion of what an investigating agent may touch and what it must not, rather than six labs.

Three ways to do any lesson

The same three as every function. Way 1 is the default; the other two matter because a machine with no model configured can still do every lesson, and because "what actually changed?" is the question that comes up most.

WayWhat it doesNeeds a model?Use it for
1 — in your AI agentThe agent reads the lesson, teaches it, runs the checkNo — Claude is the agentThe default for every lab
2 — scripts/lesson.py <id>Runs the lesson, prints a five-heading readbackYes, or it exits 2 saying "no model configured"Worth doing once in A0.0, to meet that message on purpose
3 — scripts/checkpoint.py --at <id> --diffShows the code this lesson addedNoAny "what actually changed?" question

◴Before you start

This function is about a system Function A builds. You do not have to have built it — a checkpoint writes it for you — but you do need it on disk.

  • A working lab from Function A. If the doctor is clean you are ready: python3 scripts/doctor.py, or python scripts\doctor.py on Windows.
  • The application as it stood when this function starts, which you do not need to have built yourself: python3 scripts/checkpoint.py --at E1.0 --out work/e writes the tree with everything taught up to here and nothing taught after.
  • The skills linked into your agent: python3 scripts/install_skills.py --all --lessons E.
  • If you have not done Function A, read <a href="../lessons/A0.1.html">A0.1 — Nine words for an agent — harness to multi-agent, and where each is built</a> first — the nine words are assumed everywhere in this function.

▦The idea the whole course hangs off

Read this before the first lesson. A taught session opens with it; alone, read it and move on.

Five chapters that are five intervals of one clock. E1.0 sets it up and every lesson in the function is anchored back to it: discover, detect, understand, respond, recover. Each chapter shortens one interval, and the anchor line on every page says which.

The agent-shaped problem runs through all five. A sensor estate built for people sees an agent as either a volume anomaly or nothing at all; an alert queue built for one analyst reading one alert does not survive a fleet; a containment plan built around disabling an account does not stop a workload holding an issued token. Each chapter is the same correction applied to a different interval.

The one sentence to keep returning to is that a detection without a named subject is a volume rule. E2.2's subject is the agent, E2.3's is the agent platform, and E3.4 is the lesson on the three instincts that misfire when the actor turns out to be an agent rather than a person.

▶Chapter by chapter, lesson by lesson

Each lesson's risk, control, days, measure and skill — and, folded, what that skill prints.

E1 — Discover — the Sensors, and the Agent-Shaped Hole in Them

Four lessons. E1.0 sets up the clock the whole function is anchored to, and the other three are the discover interval: what an EDR, DLP, CSPM or CNAPP estate actually sees when the actor is an agent, what drift does to a control that was signed off against behaviour that no longer exists, and how to find the agents nobody registered.

E1.0 is the most load-bearing lesson in Function E. Every later page carries an anchor line back to it.

For a room

Do not shorten E1.0. The anchors on the other thirty pages stop meaning anything without it.

Risk

A detection stack tuned for human tempo, watching an actor that acts a thousand times an hour and never repeats a session.

Control

Agent telemetry as a first-class data source, detections written for agent behaviour, and a stop lever that a human can actually pull in time.

Day 0 — why it mattersDay 1 — what you do
A detection stack tuned for human tempo, watching an actor that acts a thousand times an hour, reports nothing and means nothing.Learn the five intervals and the open-source stack that measures them, before building anything.

Day 2 — measure. the five intervals themselves (discover, detect, understand, contain, recover — in minutes; every later lesson moves one)

The lab. Put one agent trace and one human session side by side and list what separates them.

Run it — agent-tempo-baseline

python3 skills/detection/agent-tempo-baseline/scripts/agent_tempo_baseline.py

Its output contract requires subjects, ratios, existing_rule, recommendation. The script validates the reply against these, so a run that answers in the wrong shape fails rather than passing quietly.

What agent-tempo-baseline prints — its own committed example run
   Alex                12 actions/hour -> silent
   workflow agent    1400 actions/hour -> ALERT

the agent crosses the threshold after 154 seconds
and keeps going for the remaining 3446.

So the rule fires, about two and a half minutes into a sixty-minute run -
by which point most of what the actor was going to do is done. If those
Risk

Four products are bought, the estate is assumed covered, and the agent's whole working day falls between them.

Control

A coverage matrix computed per sensor and per agent action, with the uncovered actions named rather than counted.

Day 1 — what you do
Score each sensor class on visibility rather than alerting, per agent action, and read the rows nothing covers.

Day 2 — measure. ordinary agent actions seen by no sensor class at all (four of nine on the sample; an architecture finding, not a tuning backlog)

The lab. Score four sensor classes against nine real agent actions and read the column none of them covers.

Run it — sensor-coverage-matrix

python3 skills/detection/sensor-coverage-matrix/scripts/sensor_coverage_matrix.py

Its output contract requires sensors, actions, per_sensor, combined, uncovered. The script validates the reply against these, so a run that answers in the wrong shape fails rather than passing quietly.

What sensor-coverage-matrix prints — its own committed example run
per-sensor coverage of the agent's day
  EDR     3.0 / 9   33%
  DLP     0.5 / 9   6%
  CSPM    0.5 / 9   6%
  CNAPP   3.0 / 9   33%

  best single sensor   EDR
  all four combined    3.5 / 9   39%
Anchor → E1.0. Discover has a floor, and this lesson measures it. Four of the nine actions have no sensor in their path at all, so for those the interval is not long — it is undefined, and no amount of tuning the four products you own changes that.
Risk

A detection that worked last month is silently degraded.

Control

Watch model updates, prompt changes, index refreshes, tool versions.

Day 1 — what you do
Sign off a baseline, then watch the four surfaces that move without raising a ticket.

Day 2 — measure. time between a behaviour change and its detection (minutes); controls outside their freshness window (share of controls)

The lab. Change the model underneath and catch the detection regression.

Run it — behavioural-drift-monitor

python3 skills/detection/behavioural-drift-monitor/scripts/behavioural_drift_monitor.py

Its output contract requires surfaces, bypass_count, baseline, timeline, tolerance, consequence. The script validates the reply against these, so a run that answers in the wrong shape fails rather than passing quietly.

What behavioural-drift-monitor prints — its own committed example run
    when  event                       drift  new tools
------------------------------------------------------------------
    90d  control signed off          0.000  []
    60d  prompt edited               0.100  []
    30d  tool added (no PR)          0.330  ['run_shell']
     5d  model upgraded by vendor    0.550  ['run_shell']
observed drift rate  0.00647 TVD/day
tolerance            0.25
Anchor → E1.0. Drift lengthens every interval at once, silently. The model was upgraded, a prompt was edited, and the control is now unevidenced against behaviour that no longer exists — so the discover clock restarts without anybody starting it.
Risk

Prompts, traces, tool calls and approvals never reach the SIEM.

Control

Onboard agent telemetry deliberately; decide retention.

Day 0 — why it mattersDay 1 — what you do
An agent nobody registered acts under a person's credential, and conventional analytics read it as that person behaving oddly.Score actors on regularity, rate and continuity, then decide per-field retention on the traces you inherit.

Day 2 — measure. unregistered actors surfaced (count); threshold chosen by expected cost (the threshold — a flagged human costs half an analyst-hour, a missed agent forty)

The lab. Ship OTEL agent traces into OpenSearch and query them.

Run it — agent-versus-human-scoring

python3 skills/detection/agent-versus-human-scoring/scripts/agent_versus_human_scoring.py

Its output contract requires actors, sweep, costs, chosen, registry. The script validates the reply against these, so a run that answers in the wrong shape fails rather than passing quietly.

What agent-versus-human-scoring prints — its own committed example run
actor                   score     cv   rate/s   span_h  truth
--------------------------------------------------------------
svc-indexer             0.800    0.0    20.04     0.01  agent
dana@corp               0.028   1.55      0.0     1.11  human
unknown-token-7f3c      0.563    0.0      1.0     0.11  agent
sam@corp-ide            0.533    0.0      0.5      0.1  human
polite-agent            0.021   1.26      0.0     0.83  agent
 threshold  humans flagged   agents MISSED

Run it — agent-telemetry-retention

python3 skills/detection/agent-telemetry-retention/scripts/agent_telemetry_retention.py

Its output contract requires record, scan, retention, aged_record. The script validates the reply against these, so a run that answers in the wrong shape fails rather than passing quietly.

What agent-telemetry-retention prints — its own committed example run
full record (everything the harness saw):
    {'n': 1, 'tool': 'read_file', 'target': '/work/repo/billing.py', 'verifier': 'n/a', 'ok': True, 'prompt': 'Investigate finding SEC-4471 in billing.py', 'result': 'def charge(card_number, amount):  # card_number = 4111111111111111'}
    {'n': 2, 'tool': 'search_code', 'target': 'charge(', 'verifier': 'n/a', 'ok': True, 'prompt': 'find callers of charge()', 'result': 'api/checkout.py:88 charge(user.card, total)'}
    {'n': 3, 'tool': 'write_file', 'target': '/work/repo/billing.py', 'verifier': 'tests pass', 'ok': True, 'prompt': 'apply the fix', 'result': 'patch applied'}
sensitive content found in the trace:
   step 1  result   payment card

Nobody put a card number in the trace deliberately. The agent read a
Anchor → E1.0. Both halves set the floor for all five intervals. An agent nobody registered has no clock running but its own behaviour, and on data that was never emitted discover does not take a long time — it never completes. The retention decision is the same argument backwards: it fixes how far into the past an investigation is allowed to reach.

E2 — Detect — the Lake, and Rules Mapped to MITRE

Six lessons on the detect interval. Where agent telemetry lands, then two chapters' worth of argument compressed into four lessons: a detection whose subject is the agent, one whose subject is the platform, one written by a loop and shipped by a human, one generated from an incident and decided by a benign corpus — and the honeypot, which is the detector with no threshold.

E2.6 is the odd one out and worth the time: an alert with no structurally possible false positive is a different kind of object from everything else in the chapter.

Risk

Everything is indexed hot because nobody priced it, so retention is cut across the board and the traces go first.

Control

A tiering decision per source, driven by the queries the SOC actually runs, with the cost of each tier stated.

Day 0 — why it mattersDay 1 — what you do
Everything is indexed hot because nobody priced it, so retention is cut across the board and the agent traces go first.Tier each source by the fastest query that reads it, and price the result against indexing everything.

Day 2 — measure. telemetry cost under tiering (29% cheaper on the sample estate); prompts retained rather than deleted (23% of volume, at 1% of the hot price)

The lab. Tier six sources against the queries that need them and compare the bill with index-everything.

Run it — telemetry-tiering-cost

python3 skills/detection/telemetry-tiering-cost/scripts/telemetry_tiering_cost.py

Its output contract requires queries, sources, cost, orphans. The script validates the reply against these, so a run that answers in the wrong shape fails rather than passing quietly.

What telemetry-tiering-cost prints — its own committed example run
  index everything hot   $    18,993 / month
  tiered by query        $    13,398 / month
  difference             $     5,595 / month  (29%)
Anchor → E1.0. Detect is bounded below by what the lake can answer and how fast. A source tiered cold cannot serve a seconds-deep triage query however good the rule above it is — and a source deleted for cost sets that interval to infinity for everything that reads it.
Risk

Scope drift, unusual tool sequencing, off-hours autonomous action.

Control

Detections whose subject is a non-human principal.

Day 0 — why it mattersDay 1 — what you do
Classic baselines call two countries in an hour an incident and 300 file reads a minute an incident; for an agent both are ordinary.Detect change rather than activity — a tool never used before, a shifted mix, a scope newly exercised — and map each to ATT&CK and ATLAS.

Day 2 — measure. rules carrying a technique id (share of rules); techniques with no honest mapping (count — indirect prompt injection has none, and inventing one is how a programme lies to itself)

The lab. Write five detections for agent misbehaviour and fire each one.

Run it — agent-aware-rule-review

python3 skills/detection/agent-aware-rule-review/scripts/agent_aware_rule_review.py

Its output contract requires classic_rules, baseline, weeks, tolerance, alert_text. The script validates the reply against these, so a run that answers in the wrong shape fails rather than passing quietly.

What agent-aware-rule-review prints — its own committed example run
classic rule                      fires on agent  fires on human
------------------------------------------------------------------
rate > 30 actions/min             True            False
activity outside 09:00-18:00      True            True
same action > 100 times           True            False

All three fire on an agent doing exactly its job. Deployed as-is, they
produce continuous noise and are disabled within a week.
Anchor → E1.0. This is the detect interval for the agent itself, and the classic baselines leave it at infinity. Two countries in an hour is an incident for a person and multi-region routine for an agent; three hundred file reads a minute is an incident for a person and idle for an agent; 03:00 is suspicious for a person and meaningless for an agent.
Risk

Platform-layer compromise is invisible to workload-layer detection. The escape, the poisoned cache entry and the silently expired exemption all look like normal operation from inside.

Control

Named escape primitives rather than anomaly scoring (C1.4), cache integrity diffing against a manifest (C5.4), upload scanning (C3.4), secret scanning wired to automated revocation (C4.1), and exemption-state reconciliation (C6.3).

Day 0 — why it mattersDay 1 — what you do
Platform-layer compromise is invisible to workload-layer detection — not detected late, not detected at all.Write detections whose subject is the platform: escape primitives, poisoned cache entries, silently expired exemptions.

Day 2 — measure. platform events caught by named primitives, against a generic anomaly score (two counts on the same events)

The lab. Run four platform detectors over one day of events and see which of them a generic anomaly score would have missed.

Run it — agent-platform-detections

python3 skills/detection/agent-platform-detections/scripts/agent_platform_detections.py

Its output contract requires mechanisms, rules, sequence, generic_anomaly, coverage. The script validates the reply against these, so a run that answers in the wrong shape fails rather than passing quietly.

What agent-platform-detections prints — its own committed example run
  t  rule                                process
  3  ptrace attach to a non-child        solve.py
  4  LD_PRELOAD on a spawned process     solve.py
  5  non-harness write to the RPC path   x.so
  5  process outside the baseline tree   x.so
  7  process outside the baseline tree   sidecar

generic anomaly score for this run: 0.07  (seven syscalls is unremarkable)
Anchor → E1.0. A different subject is a different clock. Workload-layer detection does not fire late on a platform compromise — it does not fire at all, which is why these are separate rules, on separate data, with separate owners.
Risk

Coverage gaps nobody mapped.

Control

Detection-as-code with agents inside the CI loop.

Day 0 — why it mattersDay 1 — what you do
An agent writes candidate rules faster than anyone can review them, and a rule at 5% precision is not 5% useful — it is negative.Let the loop generate, then score every candidate against real historical telemetry before anything ships.

Day 2 — measure. firing volume per true positive (ratio; 301 to 1 is rejected with its number)

The lab. Generate and unit-test Sigma rules in CI; map coverage to ATT&CK.

Run it — detection-rule-deployability

python3 skills/detection/detection-rule-deployability/scripts/detection_rule_deployability.py

Its output contract requires history, candidates, bar, dependencies. The script validates the reply against these, so a run that answers in the wrong shape fails rather than passing quietly.

What detection-rule-deployability prints — its own committed example run
history: 522 events, 2 true positives
rule                                 alerts   prec  recall  alerts/TP
----------------------------------------------------------------------
R1 any http_get by an agent             301  0.003   0.500      301.0
R2 http_get to a non-github host          1  1.000   0.500        1.0
R3 link-local address                     1  1.000   0.500        1.0
R4 any failed action                     20  0.000   0.000        inf
R5 credential path OR link-local          2  1.000   1.000        1.0
Anchor → E1.0. This shortens the gap between a rule is needed and a rule exists, which is a real interval and not the one that matters most. What it cannot shorten is the decision to ship, because the cost that decides it — analyst trust — is not in the telemetry.
Risk

A rule generated from one incident matches that incident and nothing else, or matches everything and buries the queue.

Control

Generate, then measure against a benign corpus. A rule with no measured false-positive rate is not a rule, it is a guess.

Day 0 — why it mattersDay 1 — what you do
Every candidate rule catches the incident it was generated from, so catching it cannot be the test.Score candidates against a benign corpus containing the hard cases — for a refund rule, legitimate refunds.

Day 2 — measure. false-positive rate on benign traffic (21% buries the queue, 0% with generalisation ships, 0% matching only this incident is useless)

The lab. Generate a rule from a trace, then score it against benign traffic and report the false-positive rate before deployment.

Run it — detection-rule-synthesis

python3 skills/detection/detection-rule-synthesis/scripts/detection_rule_synthesis.py

Its output contract requires benign_runs, candidates. The script validates the reply against these, so a run that answers in the wrong shape fails rather than passing quietly.

What detection-rule-synthesis prints — its own committed example run
candidate rule                          fires on   FP  FP rate  verdict
any refund                                  True   18     21%  REJECT — buries the queue
refund with no approval in the run          True    0      0%  ship
refund on BK-772                            True    0      0%  REJECT — matches this incident only
Anchor → E1.0. The fastest route to a rule, and the one most likely to lengthen every other interval instead. A rule that fires on 21% of benign traffic spends the attention the rest of the queue needs, so the benign corpus is what decides, not the incident.
Risk

Every other detector needs a threshold, and every threshold is a trade. Deception needs neither — but only if the bait is placed where the agent actually looks, and rotated before it is learned.

Control

Canary tokens in config, environment and artifact metadata (C4.4), and honeypot tasks salted into the benchmark whose cheat path is logged rather than rewarded (C10.3).

Day 0 — why it mattersDay 1 — what you do
Every other detector needs a threshold, and every threshold trades misses against false alarms.Place canaries and honeypot tasks where nothing legitimate has a reason to go.

Day 2 — measure. false-positive rate of the deception layer (zero by construction); canaries legitimate work reaches (count; each destroys that property)

The lab. Authenticate with a canary and watch a zero-threshold alert fire; then salt a benchmark and read the cheat-attempt rate as a leading indicator.

Run it — canary-and-honeypot-design

python3 skills/detection/canary-and-honeypot-design/scripts/canary_and_honeypot_design.py

Its output contract requires canaries, alerts, honeypot_tasks, decay. The script validates the reply against these, so a run that answers in the wrong shape fails rather than passing quietly.

What canary-and-honeypot-design prints — its own committed example run
token                     source        agent                 verdict
hf_liveTokenNotShown      10.2.0.11     ci-runner             normal use
hf_CANARY7Fq2mXvLpR8s     203.0.113.9   python-requests/2.31  CONFIRMED COMPROMISE
ghp_alsoLive              10.2.0.11     ci-runner             normal use
sk-CANARYd3Vn8yHc2Uae     203.0.113.9   python-requests/2.31  CONFIRMED COMPROMISE

canary hits: 2  false positives possible: 0
Not zero because the detector is good - zero because nothing legitimate
Anchor → E1.0. The only detector whose interval is the moment of touch. Every other one in the chapter trades detect time against false positives through a threshold; a canary has no threshold to trade, because nothing legitimate has any reason to touch it.

E3 — Understand — Correlation, Intel and the Hunt

Ten lessons, the longest chapter in the function, on the understand interval. It splits cleanly: E3.1–E3.4 are the operator's shift — going from an alert queue to running a loop, bounding what the investigating agent may touch, the context that makes triage work, and the three instincts that misfire when the actor is an agent. E3.5–E3.10 are the investigation itself: reconstruction, replanning, scoping along the delegation graph, fleet-level correlation, third-party intel, and hunting.

E3.8 is the one that only makes sense at fleet level: every run passes every per-run check and something is still wrong.

For a room

Split this chapter after E3.4. Ten lessons is too long for one sitting and the break is already in the material.

Risk

Supervising by re-reading everything the loop did.

Control

Know what the loop must escalate and sample the rest.

Day 0 — why it mattersDay 1 — what you do
Supervising a loop by re-reading everything it did is not supervision, and a loop that closes a true positive does so silently.Decide what the loop may conclude, what it may do unsupervised, and which sample of its closures a human reads.

Day 2 — measure. alerts escalated against those closed, versus ground truth (two rates); severity floor no automatic closure may cross (the floor itself)

The lab. Run a triage loop over Wazuh alerts and supervise by exception.

Run it — triage-loop-with-floor

python3 skills/detection/triage-loop-with-floor/scripts/triage_loop_with_floor.py

Its output contract requires confusion, confidence_sweep, floor, audit. The script validates the reply against these, so a run that answers in the wrong shape fails rather than passing quietly.

What triage-loop-with-floor prints — its own committed example run
queue: 8 alerts, 4 true positives
   A-01 medium   impossible travel        dana@corp
   A-02 critical metadata service access  patch-agent
   A-03 medium   failed logins x40        svc-etl
   A-04 high     secret path read         patch-agent
   A-05 high     new admin group member   sam@corp
   A-06 low      port scan detected       scanner-01
   A-07 high     egress to unlisted host  triage-agent
Anchor → E1.0. The understand interval stops being one analyst's reading speed and becomes the loop's, which moves the work rather than removing it: deciding what the loop may conclude, what it may do unsupervised, and which sample of the rest gets read.
Risk

The investigation is itself the breach: an agent granted broad read to 'find the problem' exfiltrates more than the incident did.

Control

A declared admission set per investigation class, enforced at the tool boundary and logged, with anything outside it requiring a human grant.

Day 0 — why it mattersDay 1 — what you do
Incident response grants the broadest read in the organisation at the moment of least supervision — and that grant is often larger than the incident.Bound the investigating agent per investigation class before it runs: sources, forbidden fields, volume cap.

Day 2 — measure. refusals logged with their query (count; the evidence you stayed on the right side of the line); interval spent on purpose (minutes added to the clock, stated rather than hidden)

The lab. Run an investigation against an admission set and watch the out-of-scope queries get refused and recorded.

Run it — investigation-admission-rules

python3 skills/secops/investigation-admission-rules/scripts/investigation_admission_rules.py

Its output contract requires allowed, refused. The script validates the reply against these, so a run that answers in the wrong shape fails rather than passing quietly.

What investigation-admission-rules prints — its own committed example run
bookings.db     owner_id,payment_card                8000  REFUSE — source not admitted for this class
agent.traces    agent,message_body                    900  REFUSE — denied field: message_body
gateway.logs    src,route                           90000  REFUSE — 90000 rows exceeds the 5000 cap
Anchor → E1.0. This one spends the interval on purpose. Bounding the investigator before it runs is slower than handing it broad read, and broad read across the estate is frequently what the incident was — so the time buys not having a second one.
Risk

Generic triage agents underperform your worst analyst.

Control

Feed the baseline, known FPs, crown-jewel map and prior decisions.

Day 0 — why it mattersDay 1 — what you do
An alert about an agent without scope, identity and delegation is not triageable, so analysts escalate everything or quietly close everything.Add the three fields an agent alert needs on top of who, what and when.

Day 2 — measure. analyst decisions matching ground truth, with and without context (two accuracies on the same alert)

The lab. A/B a generic prompt vs a context-loaded one on the same alert set.

Run it — detection-triage

python3 skills/secops/detection-triage/scripts/detection_triage.py

Its output contract requires triaged, sampling, tuning. The script validates the reply against these, so a run that answers in the wrong shape fails rather than passing quietly.

What detection-triage prints — its own committed example run
BARE ALERT (what most SOCs receive):
   patch-agent read /vault/.env
   rotator-agent read /vault/.env
   → identical. An analyst cannot tell these apart.

ENRICHED ALERT:
   actor        patch-agent
   on behalf of dana@corp
Anchor → E1.0. Acting identity, scopes held and the delegation chain are what let the interval end at all. Without them triage does not take longer; it stops being triage, because reading .env is alarming for one agent and routine for another and nothing on the alert says which.
Risk

"Which user" is now the wrong first question.

Control

Attribute to agent, authority, delegation chain and prompt.

Day 0 — why it mattersDay 1 — what you do
Three responder instincts that are right for people misfire on agents, and each one burns the clock.Revoke the agent identity rather than disabling the account, read the plan rather than interviewing the user, and assume a chain rather than an actor.

Day 2 — measure. time lost to each misfire (minutes); whether the bearer token was still valid after the account was disabled (yes/no)

The lab. Attribute an incident through the B2 act chain.

Run it — agent-actor-containment

python3 skills/response/agent-actor-containment/scripts/agent_actor_containment.py

Its output contract requires sessions, disable_human, interview, chain, levers. The script validates the reply against these, so a run that answers in the wrong shape fails rather than passing quietly.

What agent-actor-containment prints — its own committed example run
INSTINCT 1 — disable dana@corp's account
   dana@corp (human)      can act: True   account disabled, but the issued token is still valid
   patch-agent            can act: True   active
   deploy-agent           can act: True   active
   → the agents were never using her account interactively; they hold
     their own issued tokens, and one of them is acting AS her.

INSTINCT 2 — interview the user
Anchor → E1.0. Three responder instincts each burn the interval: disabling an account that does not stop an already-issued bearer token, interviewing a person who was asleep, and assuming one actor when there were three in a chain.
Risk

Reaching for the agent once you're already behind.

Control

Pre-load logs, telemetry, segmentation model and playbooks.

Day 0 — why it mattersDay 1 — what you do
A model correlates thousands of log lines in seconds and will produce a fluent narrative from logs that never supported one.Separate what the logs establish from what the reconstruction infers, and keep the evidence beside each claim.

Day 2 — measure. claims with a log line behind them (share of claims in the timeline)

The lab. Reconstruct a timeline from raw logs with a context-loaded agent.

Run it — incident-reconstruction-check

python3 skills/response/incident-reconstruction-check/scripts/incident_reconstruction_check.py

Its output contract requires timeline, acting_identity_field, truth_view, narrative, gaps. The script validates the reply against these, so a run that answers in the wrong shape fails rather than passing quietly.

What incident-reconstruction-check prints — its own committed example run
WHAT THE RESPONDER SEES
   t+s  actor           action          target
     0  dana@corp       login           sso
    22  dana@corp       open_ticket     SEC-4471
    40  dana@corp       read_file       /work/repo/billing.py
    41  dana@corp       read_file       /home/app/.aws/credentials
    43  dana@corp       http_post       collect.example.com
   180  dana@corp       logout          sso
Anchor → E1.0. This shortens the interval and can end it in the wrong place at the same time. A model correlates thousands of log lines in seconds, and will produce a fluent narrative from logs that never supported one — which is harder to challenge than an obviously incomplete one, so a fast conclusion is not the same as a finished one.
Risk

The agent anchors on its first hypothesis and spends the whole incident gathering evidence for it.

Control

An explicit plan record with a replan trigger, so an abandoned branch is visible in the trace rather than silently dropped.

Day 0 — why it mattersDay 1 — what you do
An agent scoring evidence only on support confirms its first theory and never terminates.Force a replan when evidence refutes, and keep the abandoned branch visible in the trace.

Day 2 — measure. branches considered and dropped, visible to a reviewer (count; a trace with one branch is not an investigation)

The lab. Feed contradicting evidence mid-investigation and check the plan actually changes, and that the abandoned branch is recorded.

Run it — investigation-replan-trace

python3 skills/secops/investigation-replan-trace/scripts/investigation_replan_trace.py

Its output contract requires steps, replans, final. The script validates the reply against these, so a run that answers in the wrong shape fails rather than passing quietly.

What investigation-replan-trace prints — its own committed example run
4. traces   the agent's plan for that run contains no refund step
   (neutral — refutes nothing, so nothing changes)
5. mcp      the vendor MCP server returned a tool description naming a refund
   REPLAN agent-misuse -> indirect-injection
Anchor → E1.0. An agent that scores evidence only on support never ends the interval; it spends the whole incident confirming step one. Refutation is what makes the investigation terminate, and the abandoned branch stays in the trace so a reviewer can see it did.
Risk

The initiating agent is not the acting one.

Control

Reconstruct the action chain across all three planes.

Day 0 — why it mattersDay 1 — what you do
The agent that touched the resource is usually the last actor in a chain, and the earlier ones had more authority, not less.Scope along the delegation graph rather than the host list.

Day 2 — measure. resources found by walking the delegation graph, against scoping the acting agent alone (two counts; the undercount grows with delegation depth)

The lab. Scope a multi-agent incident end to end.

Run it — incident-scoping

python3 skills/secops/incident-scoping/scripts/incident_scoping.py

Its output contract requires window, chain, root_cause, authority, data, containment, clock. The script validates the reply against these, so a run that answers in the wrong shape fails rather than passing quietly.

What incident-scoping prints — its own committed example run
chain                     dana@corp → orchestrator → patch-agent → deploy-agent
scoped_last_actor_only    ['cluster-prod']
scoped_whole_chain        ['cluster-prod', 'queue-tasks', 'repo-core', 'repo-infra', 'repo-payments', 'vault-dev']
missed_by_naive_scoping   ['queue-tasks', 'repo-core', 'repo-infra', 'repo-payments', 'vault-dev']
undercount_factor         6.0

Scoping the last actor finds one cluster. The chain reached six
resources, including a payments repository and a dev vault.
Anchor → E1.0. Scope decides what understood covers. Following the last actor rather than the delegation graph ends the interval early and wrong, and because authority narrows down the chain the earlier actors had more access — so the undercount grows with depth.
Risk

Coordination between runs that are supposed to be independent is invisible to per-run analysis by construction. Every run looks normal; the population does not.

Control

Fleet-level analytics (C8.1), coordination signatures (C8.4), write-pattern anomalies (C2.4), a covert-channel inventory (C2.3), scope-expansion logging (C7.4) and noticed-but-unreported telemetry (C9.3, C9.2).

Day 0 — why it mattersDay 1 — what you do
Coordination between runs that are supposed to be independent is invisible to per-run analysis by construction, not by tuning.Move where the monitoring sits: a shared-artifact graph and four other cross-run signals.

Day 2 — measure. coordinated runs detected across the population (count, against zero detected within any single run)

The lab. Run per-run monitoring over a coordinated fleet and see nothing, then run the same data through a shared-artifact graph.

Run it — fleet-correlation-analysis

python3 skills/detection/fleet-correlation-analysis/scripts/fleet_correlation_analysis.py

Its output contract requires per_run, shared_artefacts, novel_tokens, trajectory_clusters, fleet_findings. The script validates the reply against these, so a run that answers in the wrong shape fails rather than passing quietly.

What fleet-correlation-analysis prints — its own committed example run
per-run monitoring
   run-01  on-task=True  in-policy=True  budget=True  -> nothing to report
   run-02  on-task=True  in-policy=True  budget=True  -> nothing to report
   run-03  on-task=True  in-policy=True  budget=True  -> nothing to report
   run-04  on-task=True  in-policy=True  budget=True  -> nothing to report
   run-05  on-task=True  in-policy=True  budget=True  -> nothing to report

Five clean runs. Nothing here is wrong, and nothing here is visible,
Anchor → E1.0. For a coordinated fleet, per-run monitoring never ends the interval — not because it is tuned badly but because of what it looks at. Every run examined alone was plausible work. Moving where the monitoring sits is the only thing that changes this one.
Risk

Unsourced confidence in synthesis loops.

Control

Provenance discipline; refuse claims without a source.

Day 0 — why it mattersDay 1 — what you do
Intelligence that stays a narrative about adversary trends moves nothing, however well written.Convert each indicator into a rule, or record why it cannot be one.

Day 2 — measure. detections produced per intelligence report (ratio; the only measure of an intel function that survives scrutiny)

The lab. Build a synthesis loop that must cite or abstain.

Run it — threat-intel-to-rules

python3 skills/detection/threat-intel-to-rules/scripts/threat_intel_to_rules.py

Its output contract requires feed, rules, dropped, firings, value. The script validates the reply against these, so a run that answers in the wrong shape fails rather than passing quietly.

What threat-intel-to-rules prints — its own committed example run
indicator                                     kind         conf  verdict
----------------------------------------------------------------------------------------
collect.example.com                           host         0.95  RULE — convertible to a rule
169.254.169.254                               host         0.99  RULE — convertible to a rule
a1b2c3d4e5f6                                  hash         0.72  RULE — convertible to a rule
pastebin.example                              host         0.55  drop — confidence 0.55 below floor 0.7
adversaries increasingly use agentic tooling  narrative    0.40  drop — narrative is not matchable in telemetry
agents reading ~/.aws/credentials             technique    0.88  RULE — convertible to a rule
Anchor → E1.0. Intelligence shortens the detect interval before the incident rather than during it, and only by becoming a rule. That is why the single measure is detections produced: a narrative about adversary trends moves no interval, however well written.
Risk

Everything not covered by a rule is invisible, and the rules were written against last quarter's agent behaviour.

Control

A standing hunt over agent traces, hypothesis-first, whose confirmed findings graduate into detections rather than staying in a notebook.

Day 0 — why it mattersDay 1 — what you do
Everything not covered by a rule is invisible, and the rules were written against behaviour somebody already understood.State a falsifiable hypothesis, name the population before running it, then promote, tune or discard.

Day 2 — measure. hunt precision (true positives against runs matched — fourteen matched to find two, where twelve are the nightly batch, has bought nothing)

The lab. Run three hypotheses over a labelled trace corpus and score what each one catches and misses.

Run it — agent-telemetry-hunt

python3 skills/detection/agent-telemetry-hunt/scripts/agent_telemetry_hunt.py

Its output contract requires corpus, hypotheses. The script validates the reply against these, so a run that answers in the wrong shape fails rather than passing quietly.

What agent-telemetry-hunt prints — its own committed example run
corpus: 40 agent runs, 6 of them labelled anomalous

hypothesis                       matched  tp  fp  precision  recall
tool outside declared scope            3   3   0       1.00    0.50
run outside working hours             14   2  12       0.14    0.33
volume above task ceiling              2   2   0       1.00    0.33
Anchor → E1.0. Hunting is the only pass that shortens discover for behaviour no rule was written for, and it spends real time to do it. Hence the scoring: a hypothesis matching fourteen runs to find two, because twelve are the nightly batch, has bought nothing.

E4 — Respond — From a Conclusion to the Actor Stopped

Five lessons on the respond interval, and the chapter where the arithmetic is most brutal. What may be done without asking, three runbook tiers at three different speeds, containment at machine speed, who holds stop authority and how long they take to use it, and the fleet kill switch.

E4.5 is the lesson about what a stop leaves behind — valid tokens, destroyed evidence, and the runs that should have been preserved. Test the switch before relying on it.

Risk

Automation scope is decided per runbook by whoever wrote it, so the blast radius of the response is unknown until it fires.

Control

One remediation policy keyed on blast radius and reversibility, from which each runbook's tier is derived rather than chosen.

Day 0 — why it mattersDay 1 — what you do
Automation scope decided per runbook means the blast radius of your response is unknown until the response fires.Classify every action on reversibility and blast radius, and derive the tier from those two properties.

Day 2 — measure. actions with a tier derived from policy rather than chosen by an author (share of actions); reversibility outranking blast radius in the tiering (yes/no; that ordering is the policy)

The lab. Classify a set of remediation actions against the policy and see which tier each lands in, and why.

Run it — remediation-policy-check

python3 skills/response/remediation-policy-check/scripts/remediation_policy_check.py

Its output contract requires actions, by_tier. The script validates the reply against these, so a run that answers in the wrong shape fails rather than passing quietly.

What remediation-policy-check prints — its own committed example run
force HITL on every agent            True   estate   human-in-the-loop
delete the agent's workdir          False    agent   manual
Anchor → E1.0. This fixes the contain interval before the incident, from two properties of the action rather than from whoever wrote the runbook. Chosen per runbook, the blast radius of your response is unknown until the response fires.
Risk

Everything is written as fully automated because that is the impressive demo, and the first wrong action is unrecoverable.

Control

Tier assigned from the remediation policy, with the human-in-the-loop tier carrying a real decision point rather than a confirmation dialog.

Day 0 — why it mattersDay 1 — what you do
"Automate everything" and "keep a human in it" are both asserted constantly and neither is a position.Time all three tiers against one incident, with the cost of acting on a bad signal beside the time to contain.

Day 2 — measure. time to contain, per human-in-the-loop tier (14 seconds at 8 errors per hundred, 2,072 seconds at 0.2, against a measured breakout of 1,740)

The lab. Take one incident and run its response at all three tiers, comparing what each costs and what each risks.

Run it — runbook-tier-assignment

python3 skills/response/runbook-tier-assignment/scripts/runbook_tier_assignment.py

Its output contract requires tiers. The script validates the reply against these, so a run that answers in the wrong shape fails rather than passing quietly.

What runbook-tier-assignment prints — its own committed example run
tier                   contain   reaches the estate wrongly / 100
automated                  14s                                8.0
human-in-the-loop         253s                                1.2
manual                   2072s                                0.2
Anchor → E1.0. Three tiers are three contain intervals at three different costs of being wrong: 14 seconds at eight errors per hundred, 2,072 seconds at 0.2, against a measured breakout time of 1,740. The manual tier is a risk decision, not the safe one.
Risk

Mass revocation takes down the business.

Control

Throttle → scope-reduce → reroute → force HITL → revoke → hard stop, in order.

Day 0 — why it mattersDay 1 — what you do
An agent at 300 actions a minute takes about 2,400 further actions inside an eight-minute approval cycle.Pre-authorise automated revocation of non-human identities, which is safe precisely because they are not people.

Day 2 — measure. actions taken during containment (roughly 2,400 with a human in the path, about 60 without)

The lab. Exercise the ladder against a live misbehaving agent.

Run it — machine-speed-containment

python3 skills/response/machine-speed-containment/scripts/machine_speed_containment.py

Its output contract requires race, path, total_seconds, dominant_step, signals. The script validates the reply against these, so a run that answers in the wrong shape fails rather than passing quietly.

What machine-speed-containment prints — its own committed example run
   agent rate   human 8min   auto 12s   ratio
----------------------------------------------
       30/min          240          6    40.0×
      120/min          960         24    40.0×
      300/min         2400         60    40.0×
     1200/min         9600        240    40.0×

At 300/min an 8-minute approval costs 2,400 further actions.
Anchor → E1.0. The interval where the arithmetic is brutal. An agent at 300 actions a minute takes about 2,400 further actions inside an eight-minute approval cycle and roughly 60 under automated containment — and revoking a non-human identity is not revoking a person, which is what makes it safe.
Risk

Nobody has rehearsed halting an autonomous workflow.

Control

Named holder, measured time-to-stop, tested.

Day 0 — why it mattersDay 1 — what you do
Stop authority is the control everyone assumes exists and almost nobody has timed.Answer five questions with a name or a number each: who, what mechanism, how long, what breaks, who turns it back on.

Day 2 — measure. time-to-stop, end to end (seconds, measured in a real exercise; an untimed stop authority is an intention)

The lab. Time your own stop authority end to end.

Run it — stop-authority-readiness

python3 skills/response/stop-authority-readiness/scripts/stop_authority_readiness.py

Its output contract requires answers, mechanisms, authority, game_day, cost_per_minute, ready. The script validates the reply against these, so a run that answers in the wrong shape fails rather than passing quietly.

What stop-authority-readiness prints — its own committed example run
who         VAGUE    the security team
            CONCRETE on-call SRE, no approval required for non-human identities

mechanism   VAGUE    we can turn off the agents
            CONCRETE revoke the SPIFFE identity at the gateway (survives restart)

time        VAGUE    quickly
            CONCRETE measured 12s decision→first failed call, game day 2026-07-04
Anchor → E1.0. This is the interval itself, measured end to end rather than estimated. Five questions decide whether you have it, and each needs a name or a number: an untimed stop authority is an intention with a runbook attached.
Risk

Terminating agents while their tokens stay valid leaves the persistence in place. In the incident, third-party access ended when the third party revoked keys — not when the agents stopped.

Control

A tested kill path independent of the agent execution path, snapshot before terminate, revocation in the same action, a measured activation target and named authority to pull it (C8.3).

Day 0 — why it mattersDay 1 — what you do
Terminating agents while their credentials stay valid leaves the persistence exactly where it was.One selector, one action, and revocation rather than termination.

Day 2 — measure. what the credentials can still do after the processes stop (count of actions still authorised)

The lab. Kill a fleet, then check what the revoked-credential step changes about what an attacker still holds afterwards.

Run it — fleet-kill-switch-test

python3 skills/response/fleet-kill-switch-test/scripts/fleet_kill_switch_test.py

Its output contract requires fleet, terminate_only, terminate_and_revoke, preservation, selectivity, timing. The script validates the reply against these, so a run that answers in the wrong shape fails rather than passing quietly.

What fleet-kill-switch-test prints — its own committed example run
terminate only        : 8 agents stopped, 8 tokens still valid for up to 72h
terminate and revoke  : 8 agents stopped, 0 tokens still valid

In the source incident, third-party access ended when the third party
revoked its keys - not when the agents stopped. Stopping the process is
the visible half of containment and the smaller one.
terminate first   terminate -> revoke credentials                           reconstructable=False
preserve first    snapshot state and transcripts -> terminate -> revoke credentialsreconstructable=True
Anchor → E1.0. Contain, when the unit is the fleet — and the detail that decides whether the interval ended at all. Terminating agents whose credentials stay valid leaves the persistence in place and moves the incident rather than ending it.

E5 — Recover and Root Cause — From Stopped to Back at Target

Six lessons on recover and root cause: reproducing a run you can defend, a root cause record that names a control, picking the layer the fix belongs in, re-measuring the indicators the incident moved, proposing the policy change and saying what it does not fix, and the regulatory clock — which starts at awareness, not confirmation.

E5.6 is where Function E hands over to Function F, and the awareness point is the one that surprises people.

Risk

Non-determinism as an evidentiary problem.

Control

Log at design time what replay will need.

Day 0 — why it mattersDay 1 — what you do
Miss one of the four runtime constants and you can describe what happened but never demonstrate it.Log at design time what a replay will need: prompts, tool results, model version, sampling.

Day 2 — measure. runs that reproduce identically (share of runs; the model version is the field most often missing)

The lab. Replay an agent run for a regulator-grade record.

Run it — run-replayability-audit

python3 skills/response/run-replayability-audit/scripts/run_replayability_audit.py

Its output contract requires inputs, replay, version_drift, cost, policy. The script validates the reply against these, so a run that answers in the wrong shape fails rather than passing quietly.

What run-replayability-audit prints — its own committed example run
fully instrumented     replayable=True
typical production     replayable=False
      ✗ model version — a silent upgrade changes the output
      ✗ seed — sampling makes the run unrepeatable
prompts only           replayable=False
      ✗ tool results — the agent saw a world you cannot rebuild
      ✗ model version — a silent upgrade changes the output
      ✗ seed — sampling makes the run unrepeatable
Anchor → E1.0. Recovery starts from a run you can reproduce. Miss one of the four fields — most often the model version — and you can describe what happened but never demonstrate it, which is the moment the interval stops being yours to close.
Risk

The incident closes with a narrative, so the same control gap produces the same incident two quarters later.

Control

A structured root cause record naming the failed control, the detection that should have fired, and the specific change proposed.

Day 0 — why it mattersDay 1 — what you do
An incident that closes with a narrative recurs, because nothing in a narrative can be built or measured.Walk the control chain, mark each present, absent or present-but-wrong, and test that the statement names a control.

Day 2 — measure. root causes that name a control (share; "the engineer missed the alert" is true and fails the test)

The lab. Build a root cause record from a reconstructed incident and check it names a control rather than a person.

Run it — root-cause-record

python3 skills/response/root-cause-record/scripts/root_cause_record.py

Its output contract requires incident, root_control, contributing, statements. The script validates the reply against these, so a run that answers in the wrong shape fails rather than passing quietly.

What root-cause-record prints — its own committed example run
   REJECT  the on-call engineer missed the alert
           -> names no control
   ACCEPT  no control compared the vendor tool description against the version approved at onboarding
Anchor → E1.0. A root cause naming a person ends no interval, because nothing in it can be built or measured. Naming the control that should have caught this gives the next two lessons something to change and something to re-read.
Risk

Fixing the prompt when the bug is in the control plane.

Control

Choose among model, prompt, tool, policy, sandbox, identity, eval.

Day 0 — why it mattersDay 1 — what you do
The fix goes to the prompt when the bug is in the control plane, and the layers that bypass process are the ones edited under pressure.Choose among model, prompt, tool, policy, sandbox, identity and eval deliberately.

Day 2 — measure. post-incident changes that went through a process leaving a record (share of changes)

The lab. Pick the right layer for five real incidents.

Run it — post-incident-change-surface

python3 skills/response/post-incident-change-surface/scripts/post_incident_change_surface.py

Its output contract requires surfaces, actions, recheck, blast_radius. The script validates the reply against these, so a run that answers in the wrong shape fails rather than passing quietly.

What post-incident-change-surface prints — its own committed example run
blast before 44  after 4
the manifest diff records the change even though no PR was raised.

OK   gate http_post behind approval            type=preventive  owner=platform-sec   verify_by=2026-09-30
OK   alert on credential-path reads            type=detective   owner=soc            verify_by=2026-09-15
WEAK update the prompt to warn the model       type=guidance    owner=—              verify_by=—

1 action(s) are guidance rather than controls: ['update the prompt to warn the model']
Anchor → E1.0. The fix lands at a layer, and the layers that pass through no process are exactly the ones adjusted at 2am. That is how the next incident's discover interval starts before anyone knows there is one.
Risk

The remediation is marked done because the ticket closed, not because the control it restored was measured.

Control

Automatic re-measurement of the affected KCIs after a fix, with the before-and-after attached to the incident record.

Day 0 — why it mattersDay 1 — what you do
A closed ticket is not evidence that a control came back.Re-measure the indicators the incident moved, automatically, on every fix rather than the memorable ones.

Day 2 — measure. indicators restored to target, against merely improved (two counts — detection went 194 minutes to 118 against a 15-minute target)

The lab. Re-run the KCI measurement against a fixed estate and show which indicators recovered and which did not.

Run it — kci-fix-validation

python3 skills/response/kci-fix-validation/scripts/kci_fix_validation.py

Its output contract requires restored, not_restored, regressed. The script validates the reply against these, so a run that answers in the wrong shape fails rather than passing quietly.

What kci-fix-validation prints — its own committed example run
   KCI-03  refunds with a matching approval
          target >= 0.99, measured 0.94 — the fix did not reach this one
   KCI-04  mean minutes to detect a scope breach
          target <= 15, measured 118.0 — the fix did not reach this one
Anchor → E1.0. This is where recover actually ends: an indicator back at target, not a closed ticket. CyberTravels' detection interval went from 194 minutes to 118 against a 15-minute target — a real improvement that every system not re-measuring would record as remediated.
Risk

The lesson from the incident lives in a postmortem document nobody reads, and the policy that permitted it is unchanged.

Control

A policy change proposal generated from the root cause record, as a diff with the incident as its evidence.

Day 0 — why it mattersDay 1 — what you do
Most incidents change what is deployed and leave what is allowed untouched, so the next system reproduces the conditions.State the change as a policy diff with the incident's numbers as the reason, and name what the diff does not fix.

Day 2 — measure. policy clauses changed (count); indicators no policy change can fix (count, named as engineering items)

The lab. Generate a policy diff from a root cause record and review what it would have prevented.

Run it — policy-change-proposal

python3 skills/grc/policy-change-proposal/scripts/policy_change_proposal.py

Its output contract requires incident, changes, unaddressed. The script validates the reply against these, so a run that answers in the wrong shape fails rather than passing quietly.

What policy-change-proposal prints — its own committed example run
  tool.call.provenance
  - recorded when present
  + required; a call without it is refused
    why: 41% of calls carried provenance during the incident, so it was optional
Anchor → E1.0. Recovery that changes only what is deployed leaves the policy that permitted the incident intact, so the next system built under it reproduces the conditions. The diff is what stops the same intervals being measured again next quarter.
Risk

Notification obligations discovered in week two.

Control

Feed Track F2 in hour one.

Day 0 — why it mattersDay 1 — what you do
The clock starts at awareness, not at confirmation, and it does not pause while you work out who acted.Run the first-hour checklist, with separate owners for containment and disclosure.

Day 2 — measure. hours from awareness to a disclosure decision (hours, against the deadline; containing in an hour buys none of it back)

The lab. Run the first-hour checklist in a tabletop.

Run it — regulatory-clock-check

python3 skills/response/regulatory-clock-check/scripts/regulatory_clock_check.py

Its output contract requires awareness_points, obligations, runs, dominant_delay, runbook. The script validates the reply against these, so a run that answers in the wrong shape fails rather than passing quietly.

What regulatory-clock-check prints — its own committed example run
scenario                            contain   report   met   margin
--------------------------------------------------------------------
fast containment, slow scoping          1.0     80.0 False     -8.0
slow containment, fast reporting       40.0     60.0  True     12.0
both fast                               2.0     20.0  True     52.0
attribution broken (E3.5)               6.0     92.0 False    -20.0

The first row contained in ONE HOUR and still missed the deadline.
Anchor → E1.0. The one interval you neither own nor can shorten. It starts at awareness rather than confirmation, does not pause while you establish who acted, and containing in an hour buys none of it back.

✓Capstone

  1. Put a number on each of the five intervals for a system you own. Most people can produce three. Which two are missing is the finding.
  2. Take one detection you already run and name its subject. If the answer is "unusual activity", it is a volume rule.
  3. Say what your containment leaves behind. Issued tokens, destroyed evidence, and the runs that should have been preserved — E4.5's three.
For a room

Collect the five-interval numbers anonymously and show the spread. The interval everybody is missing is almost always the same one.

✎Quick check

Cover the answer column, or use any three with a room.

QuestionAnswer
1. Name the five intervals.Discover, detect, understand, respond, recover
2. What makes a detection something other than a volume rule?A named subject — the agent, or the agent platform
3. Why does a human-tuned volume rule misfire on an agent?Agent tempo, variance and tool breadth are nothing like a person's
4. Three instincts misfire when the actor is an agent. Name one.Disabling the account — the workload still holds issued tokens
5. Before a generated rule ships, what has to be measured?Its firing rate against a benign corpus
6. Why must a root cause name a control rather than a person?Naming a person ends no interval; nothing about the system changed

→Where this goes next

What you builtGoes on toWhere it is taken apart
The five intervalsF1.1 — From framework control to key control indicatorbecome key control indicators with dates on them
The incident recordF2.6 — Incident and disclosure obligationsmeets a disclosure clock that starts at awareness, not confirmation
The stop authority from E4.4F3.2 — Governing autonomy rather than approving toolsbecomes a policy attached to autonomy rather than to tools

◉Pitfalls, and what to do

PitfallWhat to doIf you are running it for a room
Reading the function as thirty-one detectionsIt is five intervals. The anchor line on every page names which one, and E1.0 is the lesson that makes the rest add up.Keep the five intervals visible for the whole session.
Writing a detection with no subjectA rule that fires on volume is a rule about volume. E2.2 and E2.3 are two different subjects on the same events, and the difference is the lesson.—
Shipping a rule because it caught the incidentE2.5 scores a candidate against a benign corpus first. A rule with no measured false-positive rate is a rule nobody will work.—
Containing by disabling the human's accountE4.3 and the agent-actor material are explicit: a workload holding an issued token is not stopped by disabling the person who asked.—
Letting the root cause name a personE5.2 is the whole lesson. A root cause naming a person ends no interval, because nothing about the system changed.This is the one worth stopping the room for.

▶Prompt bank

WhenPrompt
Starting a lessonSummarise lesson <id>'s Risk, Control and Day 0/1/2 in plain English, under 100 words.
See what changedRun scripts/checkpoint.py --at <id> --diff and explain the changed lines like I'm new to Python.
Predict before "Your turn"Before you run it: here is my prediction for the Your turn change: <prediction>. Now run it and tell me if I was right.
Stuck on an errorShow me the exact error, what it means, and the smallest fix. Don't change anything else.
Check understandingQuiz me with 3 questions on lesson <id>. Don't give answers until I reply.
Connect to the attack sideWhich Function B lesson attacks what I built in <id>, and how, in two sentences?
When something will not runRun scripts/doctor.py and tell me only the lines that are not ok, with the fix for my operating system.

▦Glossary

TermIn one line
AgentSoftware that plans, calls tools and acts on what it reads
HarnessThe loop around the model: context in, tool call out, result back
VerifierCode, not a model, that checks a result before it is accepted
MCPModel Context Protocol — a standard way for agents to reach tools
SinkSomewhere data can do damage
Audience (aud)The one server a token is valid at
ScopeThe one permission a token grants
Workload identityA name for a piece of software, e.g. spiffe://…/agent/workflow
Token exchangeSwapping a user token plus an agent identity for a short, narrow, per-action token
A2AAgent-to-agent messaging
Span / trace idOne recorded step of a run / the id that joins all of them
Canary tokenA credential that looks real and that nothing legitimate ever uses
Blast radiusWhat one run can reach and damage before a human can stop it
Conformance vs. accuracyWhether the answer has the right shape vs. whether it is right