Outcome
By the end of this lesson, you will be able to route any recommendation to its verification bucket, explain why the bucket is derived from the prescribed lever rather than the category, and treat abstaining as a first-class outcome rather than a gap.
| Tier | Engineer |
| JTBD | ”Know what would count as proof that this specific finding was acted on.” |
| Personas | Platform Engineer · FinOps Lead |
| Prerequisites | M2.13.L3 |
| Time | 9 minutes |
| Bloom verb | Route (Apply), Explain (Understand), Treat (Evaluate) |
1. Concept
The design’s load-bearing observation:
What “changed” means depends on the lever, not the category.
Take one resource type and two recommendations on it.
A SCHEDULE recommendation Adopted correctly, the resource is running by day and stopped by night. The 6-hourly discovery scan samples that at four arbitrary points, so `status` becomes a COIN FLIP. Nothing stable moves. What DOES move: the billing-derived uptime fraction.
An IDLE -> STOP recommendation Adopted correctly, the resource is continuously stopped. `status` is exactly the right thing to read.
Same resource. Same status column. Two prescriptions.Two completely different proofs.A single “did the rule stop firing?” probe cannot serve both. So verification dispatches on what the prescribed action changes.
The seven buckets
# BUCKET PROVES ADOPTION BY LAG─────────────────────────────────────────────────────────────B1 EXISTENCE row absent from the live ≤6h listing AND present under deleted_within_days (delete; orphan unattached/unused)
B2 POWER STATE canonical power state is ≤6h stopped/deallocated/paused, CONTINUOUSLY, over ≥N samples (stop, pause)
B3 SHAPE instance_type / size_gb / ≤6h unit_count / a metadata key moved off baseline, ideally onto the frozen target (resize; orphan prune_images)
B4 DUTY CYCLE uptime fraction dropped 24-48h materially vs the t0 baseline, + ≥7d or a state entry carrying a window ScheduleID (schedule)
B5 SETTING a specific metadata / tags key ≤6h flipped to the compliant value (configure)
B6 RATE reservation/SP coverage flips, 24-48h, purchase_type moves, or the month effective $/unit-hour steps boundary down (commitment, hybrid, spot, migration)
B7 NOT OBSERVABLE nothing in our data moves. n/a ALWAYS abstains. (advisory, most compliance / governance / security prose)Six of the seven are observable probes. B7 is abstention by construction.
Each bucket knows when to abstain
B1 snapshot suspect-empty or truncatedB2 Schedulable=false (status is a hardcoded literal for those types), or a status outside the canonical mapB3 the target key has no read-side mapping (L3)B4 inside the billing lag, or the org's metrics/CUR coverage is emptyB5 the provider returned no tags that cycle. Stale tags are preserved, so they would read as "not configured"B6 inside the lag, and ALWAYS for per-resource commitment claimsThat B6 line is worth pausing on: a commitment is an account-level financial instrument, so attributing its adoption to one resource is not something the data can honestly support. It abstains by rule rather than by circumstance.
How a recommendation gets its bucket
Not from a hand-maintained list. The lever is resolved from two authoritative sources:
1. the rule's own LeverAware declaration, or2. its auto-remediation StepKind
If neither exists, resolution returns not-ok, and therecommendation abstains.It deliberately does not fall back to a broad category default. There is such a fallback for display purposes, so the drawer has copy to render, and verifying against a guessed lever would produce confident wrong verdicts. The fact belongs to the rule author who knows the gate, not to a category-wide assumption nobody re-checks.
The coverage number, stated plainly
~387 rule ids in the rule packages~129 have an authoritative lever (~18 via LeverAware, 114 via the allowlist)~258 do not
So verification covers roughly a THIRD of the catalogueand abstains on the rest.This is phasing, not a defect. Closing the gap is a per-rule Lever() declaration, guarded by a test that requires registered rules to declare a known lever, parallelisable across rules and independently reviewable. A registry-walking test prints the coverage number so it stays visible and monotone rather than being discovered later.
Knowing this number is what stops you misreading a dashboard. A large abstained column is the expected state today, not a broken pipeline.
Abstaining is the honest answer
B7 exists because some recommendations ask a human to write a policy document, hold a review, or make a procurement decision. Nothing in the estate moves when they succeed.
MANUFACTURING A VERDICT THERE = fabricated audit data = exactly the problem this program exists to fixThe named abstention reasons are specific rather than a single “unknown”: no_baseline, not_observable, posture_no_cost_outcome and others. A specific abstention tells you whether it is permanent or whether a later change upgrades it.
2. Demo
Routing five recommendations on one estate:
1. RC-002 Orphaned EBS Volume -> B1 EXISTENCE Proof: the volume is gone from the live listing and present under deleted_within_days. Verdict at +2 days: verified_adopted
2. RC-093 EC2 Heatmap Schedule -> B4 DUTY CYCLE Proof: uptime fraction 100% -> 41% against the frozen t0 baseline, sustained over a 7-day window. Verdict at +9 days: verified_adopted NOTE: at +2 days this was still `pending`. Inside the billing lag there is nothing to read, and reading `status` here would have been a coin flip.
3. RC-003 EC2 Rightsizing -> B3 SHAPE Proof: instance_type moved off the frozen baseline. Verdict at +1 day: verified_diverged (moved to t3.large, not the m5.xlarge we asked for)
4. RC-014 EC2 Reserved Instance -> B6 RATE Verdict: ABSTAINED, always. A commitment is an account-level instrument. Attributing its adoption to one resource is not something the data can honestly support, so this abstains by rule.
5. RC-1615 Guardrail missing PII -> B7 NOT OBSERVABLE The fix is a policy configuration whose compliant state this rule does not declare an observable for. Verdict: abstained, reason not_observable. Permanent until the rule declares one.
THE DASHBOARD THIS PRODUCES verified_* 2 abstained 2 pending 1
A reader who does not know the coverage number reads this as "verification is half broken". A reader who does reads it correctly: two real verdicts, one waiting on billing lag, and two honest refusals.3. Hands-on (6 min)
1. Pick five recommendations across different categories. Route each to a bucket WITHOUT looking at its verdict: rec ____________ bucket ____ rec ____________ bucket ____ rec ____________ bucket ____ rec ____________ bucket ____ rec ____________ bucket ____
2. Now check the actual verdicts. Any surprises? ______________________________________________
3. Find a schedule-category rec applied more than 9 days ago. Does it have a verdict, or is it pending? ______ If pending after 9 days, check whether the org has CUR/metrics coverage at all.
4. Count your abstained recommendations as a share of closed ones: ______% Is that near a third, or much higher? ________ Much higher usually means your estate leans on rules in the ~258 that have no declared lever yet.
5. Name one rule in your estate you would want a Lever() declaration on first, and why: ______________________________________________4. Knowledge check
Q1
Why can a schedule recommendation not be verified by reading the resource’s status?
A. Status is not recorded for scheduled resources
B. Schedules are applied by the executor rather than by the customer, so there is no customer action for the verification pass to look for when it comes to run later
C. An adopted schedule leaves the resource running by day and stopped by night, and the 6-hourly discovery scan samples that at four arbitrary points, so status becomes a coin flip
D. Status only updates on manual actions
Show answer
Correct: C. What actually moves is the billing-derived uptime fraction, which is what bucket B4 reads. This is the observation the whole dispatch design rests on: an idle-to-stop recommendation on the same resource type expects continuously stopped, so status is exactly right there. Same column, two prescriptions, two different proofs.
Q2
A rule has neither a LeverAware declaration nor an auto-remediation StepKind. Verification:
A. Falls back to the category’s default lever
B. Defers to the next evaluation cycle
C. Uses the “did the rule stop firing” probe
D. Abstains
Show answer
Correct: D. There is a category-default fallback for display, so the drawer has copy to render, but verifying against a guessed lever would produce confident wrong verdicts. The lever is a fact the rule author knows, not a category-wide assumption. This is why coverage sits at roughly a third of the catalogue: about 129 of ~387 rule ids have an authoritative lever. Closing that is a per-rule declaration, and a registry-walking test prints the number so it stays visible.
Q3
A commitment recommendation (RC-014, an EC2 Reserved Instance) is routed to bucket B6, RATE. Its verdict is:
A. verified_adopted once reservation coverage flips
B. pending until the month boundary
C. abstained, always, for per-resource commitment claims
D. verified_unchanged unless purchase_type moves
Show answer
Correct: C. A commitment is an account-level financial instrument, so attributing its adoption to a single resource is not something the data can honestly support. B6 abstains inside the lag and always for per-resource commitment claims. The distinction matters: this one is not a timing problem that resolves next month, it is a permanent honesty constraint on what the data can attribute.
5. Apply
Before asking why a recommendation has no verdict, route it to a bucket yourself and check that bucket’s abstention conditions. Most missing verdicts are B4 inside the billing lag, B3 on an unmapped target key, or a rule with no declared lever.
When reporting verification coverage upward, lead with the coverage number. A large abstained column is the expected state today, and a reader who does not know that will read your dashboard as broken.
Related lessons
- L3: Frozen baselines and declared observables
- L5: Rule versions, retirement and supersede (next)
- L2: Status is a claim, evidence is a fact
- T2.M2.3.L7: The Recommendation Safety Gate
Glossary terms touched
Verification bucket · Duty cycle · LeverAware · not_observable