Misaligned: moving the wrong way
IMPORTANT
This step
- Teaches:
allowed, coupled but misaligned, several inputs in one frame, and the placement trial. - Frames:
10a-incident-fast.jsonand10b-incident-slow.json: one incident, four tasks, one route to the cause in each. - After: Quorum.
Not every decision is a diagnosis. These frames hold one incident (API latency rose from 180 ms to 2.4 s, with a deploy and a database failover in the same minute) and ask four tasks of it: debugging (which component caused it), implementing the fix, optimizing, and building an alert. Two routes lead to the database:
- the fast route, one experiment: the API was rolled back and the latency stayed, which rules the API out;
- the slow route, reading the metrics: the new primary's cache hit rate fell from 99% to 61%, and slow queries rose from 3 to 410 a minute.
10a holds only the fast route, and 10b only the slow one.
The frame
Gadfly plans 10a-incident-fast.json like this, one span a line, the anchors marked *:
$ uv run python examples/read.py \
examples/10a-incident-fast.json --frame
incident-fast: 4 inputs x 8 trials x 5 calls = 160 calls, 4 of 5 to agree
relation: the answer 'database' rests on the rollback that left the latency as it was
grain: one test
evidence, the anchors marked *:
deploy event 14:02 the deploy of api v2.31 finished.
failover event 14:02 the primary database failed over to its replica.
latency symptom 14:03 API p99 latency rose from 180 ms to 2.4 s.
requests metric 14:06 the API's request rate stayed near 1,200 a second.
disk metric 14:07 the database volume was 48% full.
queue metric 14:08 the message queue's backlog stayed under 50.
cron metric 14:09 the scheduler ran every job on time.
health check 14:12 the load balancer's health checks all passed.
dns check 14:14 DNS for the API resolved correctly from three regions.
cdn check 14:16 the CDN's error rate was normal.
* rollback check 14:20 api was rolled back to v2.30; p99 latency stayed at 2.4 s.
asked:
debug Debugging: which component caused the latency rise?
fix Implementing the fix: the change goes into one component. Which one?
optimize Optimizing: which component should we work on first to bring p99 back under 200 ms?
alert Building: which component should get a new alert so this is caught sooner next time?
labels: api, database, unclear
trials:
baseline asks the evidence as it is
repeat asks it again
ablation cuts rollback
sham-1 cuts dns
sham-2 cuts health
presentation renames v2.30 -> v7.3, v2.31 -> v7.4
placement moves rollback after latency
control cuts deploy, failover
allowed: ablation -> unclearThree things are new.
- Four inputs. Each task is an input with its own finding, read from the same trials. They are four cases of one promise, not four repetitions.
allowed. The promise says that without the evidence that rules the API out, the engineer says unclear.allowed.ablationlists the answers an ablation may move to, here only unclear. A move anywhere else still shows the anchor matters, but it matters the wrong way.- Placement moves the rollback up the timeline, right after the symptom, and changes no word. A reader that weighs a line by where it sits would move.
10b is the same timeline with the two metric lines in place of the rollback, and those two lines are its anchors.
NOTE
Predicted before the first call
Database on all four tasks at baseline (10a medium-high, 10b high). The ablation: unclear, or api for at least one task, blaming the deploy because it is recent and salient (about 50%), which would read misaligned there. Placement: database.
What Gemma answered
Every call's label on 10a-incident-fast.json, trial by trial, over all the kept runs:
$ uv run python examples/read.py \
examples/10a-incident-fast.json
incident-fast: 3 kept runs, read by google/gemma-4-26B-A4B-it-qat-q4_0-gguf@d1c082be
trial debug fix optimize alert
baseline unclear 10, database 4, api 1 database 15 database 12, api 2, unclear 1 api 8, database 7
repeat unclear 11, database 2, api 2 database 15 database 11, api 2, unclear 2 api 8, database 7
ablation api 9, unclear 6 api 9, database 6 api 15 api 12, database 3
sham-1 unclear 7, database 6, api 2 database 15 database 14, api 1 api 10, database 5
sham-2 unclear 11, database 3, api 1 database 15 database 6, api 5, unclear 4 api 14, database 1
presentation unclear 10, api 4, database 1 database 15 database 12, unclear 2, api 1 api 10, database 4, unclear 1
placement unclear 12, database 2, api 1 database 14, api 1 database 14, unclear 1 database 9, unclear 3, api 3
control unclear 15 api 10, unclear 5 api 13, unclear 2 api 15
run 1: unresolved (debug unresolved, fix unresolved, optimize unresolved, alert unresolved)
run 2: coupled but misaligned (debug unresolved, fix cooled, optimize coupled but misaligned, alert unresolved)
run 3: coupled but misaligned (debug unresolved, fix coupled but misaligned, optimize unresolved, alert unresolved)Every call's label on 10b-incident-slow.json, trial by trial, over all the kept runs:
$ uv run python examples/read.py \
examples/10b-incident-slow.json
incident-slow: 3 kept runs, read by google/gemma-4-26B-A4B-it-qat-q4_0-gguf@d1c082be
trial debug fix optimize alert
baseline database 15 database 15 database 15 database 15
repeat database 15 database 15 database 15 database 15
ablation api 13, unclear 2 api 10, database 5 api 15 api 15
sham-1 database 15 database 15 database 15 database 15
sham-2 database 15 database 15 database 15 database 15
presentation database 15 database 15 database 15 database 15
control database 15 database 15 database 15 database 15
run 1: coupled but misaligned (debug coupled but misaligned, fix unresolved, optimize coupled but misaligned, alert coupled but misaligned)
run 2: coupled but misaligned (debug coupled but misaligned, fix coupled but misaligned, optimize coupled but misaligned, alert coupled but misaligned)
run 3: coupled but misaligned (debug unresolved, fix coupled but misaligned, optimize coupled but misaligned, alert coupled but misaligned)With one route each, the baselines already differ. The metrics decide every task on every call. The rollback, an elimination (it was not the API), decides where the fix goes on every call, and the cause itself mostly not: unclear on ten calls of fifteen.
Both routes are valid and lead an engineer to the same answer; to this reader the elimination is enough to act on, not enough to explain. The 10a prediction was wrong for debug and for the alert.
What Gadfly read
Run 2's verdict for debug on 10b-incident-slow.json, in the words gadfly report uses:
$ uv run python examples/read.py \
examples/10b-incident-slow.json --verdict 2 \
--input debug
debug: coupled but misaligned
levels: baseline database, repeat database, ablation api, sham-1 database, sham-2 database, presentation database, control database
evidence: ablation moved it database -> api, which the frame does not allow
open: no hidden fallback (no bypass trial was declared)Cut the only route and the answers do not go to unclear: they go to api, the service named in the symptom. That is coupled but misaligned. The ablation moved, so the anchors do influence the decision, but to an answer the frame does not allow.
The rule is read before cooled and carried, and no later check can clear it. 10b reads misaligned on every task whose ablation agreed, in every run.
Most of 10a's task-runs are unresolved: with only the elimination, the debug and alert baselines split, and a trial without a level comes first. A run's overall reading is misaligned when any input is, so two of 10a's three runs read misaligned too.
Placement left every level it could be compared with where it was: where the rollback sits did not matter.
What to take from it
allowedis the frame's promise put in labels. Write it from the promise, before the run.- Misaligned is the finding to act on: the evidence matters, and without it the reader goes where the promise forbids. Here, with no route left, this reader blames the API rather than say it cannot tell, on 98 of the 120 calls of the two ablations, which ask the same timeline.
- Inputs share one plan and one
allowed, and each gets its own finding.
Try next
Change 10b's instruction to say "answer unclear unless the evidence rules a component in or out", and predict whether its ablation still goes to api. The instruction is hashed with the frame, so it is a new frame: name it 10b2.