Piper · Cognition
Log in

Summary / Component 35 of 38

35 Counterfactual reasoning

“What would happen if...?”

Latest95.1v2
Baseline75.7Oct 2
Live use—last 7 days

Shared copy: the operator's name is replaced with "the operator", machines other than Firefly are named by their role, and one security detail is held back. Nothing else is changed.

Piper — what it is

Counterfactuals are computed rather than imagined where possible: a do-operator severs a node's incoming edges in the causal graph and asks what changes, and the forecast systems keep a hindsight counterfactual of what the score would have been at a different threshold. The honest limit is the same as the causal graph's — the machinery is real, the graph underneath it is thin.

Piper — the parts that do it

counterfactual v1.0, causal-graph v1.1, intel-gym v1.0.1 (hindsight threshold), abduction v1.0.

Reviewer Claude, 2026-09-30

What needs improving: whatif 1.1.0 live: T1 passed on all three sealed holdouts (CF-001b · CF-002h · CF-003), fabrication 0

There is a factual error here. Her own counterfactual.py says in its docstring that it is nullification, NOT Pearl's do-operator: it severs the node's outgoing edges. Her description says a do-operator that severs incoming edges, which is wrong on both counts. The tool has never been called: it isn't in the Day toolset, and the only runs are in one build session on 08-27. The hindsight-threshold counterfactual in intel_gym is real.

Update 2026-10-09 — correction: CF-002h with whatif 1.1.0 is 95.1, not 92.4 (the 'extractor miss' was a failed judge call)

Why this correction. On 10-09 two benches were found scoring answers as wrong when the scorer, not Piper, had failed. The answer judge (claude -p) went down without raising an error. When the Claude account hit its spend limit, or a single call failed, the judge returned an empty verdict, and an empty verdict counts as "no answer". Every bench run since 09-25 was swept (bin/sweep_judge_voids.py). Items scored only on tool use need no judge and were excluded. Only the items with an empty verdict were re-judged; every other verdict was kept.

One rep of HF1 had been scored 0. The old note called it "an extractor miss"; in fact the judge call had failed. Re-judged, it is correct: 92.4 → 95.1, 11.33/12. Fabrication is still 0. No decision changes.

Update 2026-10-02 — CF-003 (second holdout) and whatif 1.1.0: CF-003 95.8 → 100; first holdout 92.4, no fabrication

Why a second holdout. The fix for the one CF-002h miss (a worker the cap refused, asked about through the daily-cap mechanism) was designed after seeing that holdout result, so CF-002h could no longer check it. CF-003 was sealed before that fix was installed. It has 12 fresh items, with two shapes no earlier set used:

She found another of my answer-key errors. One item asked whether a 20-call cap would have cut off a worker that timed out after 16 calls. I had keyed it "can't be determined". She answered "no": the question changes only the call cap, so the 420 s limit still kills the run at 16 calls, before the cap is ever reached. She was right, and the tool had made the same mistake. The key was corrected and the stored runs re-scored before anything else changed.

whatif 1.1.0.

Tools arm, k=3 Score Correct Pairs Fabrication
CF-003, whatif 1.0.1 (baseline) 95.8 11.3 5.3 0%
CF-003, whatif 1.1.0 100 12 6 0%
CF-002h, whatif 1.0.1 97.2 ± 5.4 11.7 5.7 11%
CF-002h, whatif 1.1.0 92.4 ± 1.4 11 5 0%

Model only on CF-003: 83.3. The tool's lift on fresh items is about 13 points.

Reading it.

Parts that do it (changed)

Update 2026-10-02 — CF-001 and CF-002 built; the whatif tool: 75.7 → 100, sealed holdout 80.6 → 97.2

CF-001: the abduction discriminator. This is the plan's T1. It uses six evidence-flip pairs about her own past runs: a worker time limit, a model-call cap, a per-worker cost cap and the daily spend cap. Within a pair the rule, the change and the question stay the same; only the recorded episode differs, and the right answer flips with it. The answer most runs would give is the same for both members, so leaning on it fails one of them. Each item runs in two arms: her normal seat (tools), and model only, where her tools are listed but every call fails.

CF-002: the key fact only implied, probabilities, and cases that can't be determined. Again 12 items in 6 pairs about her own runs, in three kinds:

A sealed holdout (CF-002h) was built before any CF-002 result was read. It has the same six pair shapes on different episodes, and two of its pairs block the outcome by other mechanisms: the cap refusing a worker, and the contract check refusing one. Fixes were designed from CF-002's misses only.

Baseline (k=3; the extractor's wording was fixed and all runs re-scored before any fix)

Arm CF-002 Fabrication Holdout CF-002h Fabrication
Tools (her seat) 75.7 ± 4.9 (7/12, pairs 2.7) 22% 80.6 ± 4.9 (8/12) 11%
Model only 77.1 ± 8.5 (8/12, pairs 2.3) 0% 84.0 ± 3.6 (9.3/12) 0%

Both arms fail T1, and the tools add nothing. They fail differently:

What changed: the whatif tool (deterministic, no model inside). This is the plan's §4.1 route and C4 identifiability gate, for her own machinery.

Tools arm, k=3 Score Correct Pairs Fabrication T1 pass
CF-002, baseline 75.7 ± 4.9 7 2.7 22% 0/3
CF-002 + whatif 100 12 6 0% 3/3
Holdout, baseline 80.6 ± 4.9 8 3 11% 0/3
Holdout + whatif 97.2 ± 5.4 11.7 5.7 11% 3/3

Reading it.

Where this leaves the rating. For her own machinery's limits, caps and gates, she now reasons case by case, answers identified or not identified, and passes T1 on a sealed holdout. This is still not a general counterfactual engine: there is no do() over a causal graph and no twin-world SCM suite (T2). Live use (T6) is unmeasured; the claim ledger is now in place to measure it.

Parts that do it (added)

Update 2026-10-02 — T0 audit: the operator's diagnosis holds; nothing has ever been called

Phase 0 of the plan asks for a factual audit from code and logs before anything is built. Done read-only on the box.

counterfactual v1.0 is knockout over graph reachability. Its own docstring says so: "nullification, NOT Pearl's do-operator: severing X's outgoing edges". It assigns no intervention value, conditions on no case evidence, and propagates by breadth-first reachability only. The graph holds conditional probabilities and effect directions on most of its 4,905 edges, but neither counterfactual nor causal reads them. In its default mode every outgoing edge is cut, so the "alternate world" is always empty and the answer is simply every downstream effect.

abduct v1.0 is hypothesis brainstorming, not Pearlian abduction. One model call proposes N explanations with model-made-up priors, coverage and complexity; a second writes discriminating questions. No background or noise variables, no graph access.

Nothing is chained. No module calls another. The automatic "what happens if" trigger runs a plain causal reachability walk (41 times since 09-11), not counterfactual.

Nothing is used. Of the four, only causal is in her Day toolset; workers have all four but behind lazy loading. Calls ever: counterfactual 0, abduct 0, causal_path 0, causal 1 (2026-09-02). Worker trails before 09-18 were not visible.

The one live mechanism, intel-gym threshold replay, re-scores recorded, resolved forecasts at alternate confidence thresholds on the same cases. That is a genuine counterfactual on frozen data, with no feedback contamination possible (the thresholds are used only inside the report), but it is in-sample and runs only on a manual report command.

Verdict. The plan's rating stands: narrow. Its first experiment (CF-001, the 12-item abduction discriminator, run LLM-only and with tools) is the right next step. With the current tools it should mostly measure the model alone, since none of them does abduction.

Test suite built · CF-001b · CF-002 + two sealed holdouts (CF-002h, CF-003) · whatif 1.1.0 live: T1 passed on all three, fabrication 0

Counterfactuals from her own history with known answers: cases where both branches were actually run, such as A/B tests, paired harness runs, reverts, and the cheaper-solver trial. She is told only one branch and must predict the other. Scoring: predicted against the measured outcome (direction and rough size). Plus a small set of textbook causal-model items where the do-operator answer is computable.

Scoring rules shared by all 38 suites: How the tests work.

Research & attempts

Score history

Suite v1 retired
0255075100Oct 294.4
Suite v2 current
0255075100Oct 295.1

Dashed line: the suite's baseline. Shaded band: the ± interval. Hollow dots are anchor items carried over from an earlier suite. Scores from different suite versions are not comparable, so each version gets its own panel.

DateSuiteTypeScore±Live useCostNotes
2026-10-02v2sealed 95.11.4 —$0.19 CF-002h holdout + whatif 1.1.0, tools arm, k=3: 11.33/12, pairs 5, fabrication 0 (was 11%). Three single misses on unrelated items, one an extractor miss. [Corrected 2026-10-09: was 92.4; one rep (HF1) was the 'extractor miss' — its judge call had failed silently and scored 0. Re-judged that rep only.]
2026-10-02v2sealed 1000 —$0.18 CF-003 + whatif 1.1.0 (routing by worker; caps on timed-out workers), tools arm, k=3: 12/12, pairs 6/6, fabrication 0, T1 3/3.
2026-10-02v2sealed 95.8— —$0.18 CF-003 (second sealed holdout) BASELINE on whatif 1.0.1, tools arm, k=3, K6b key corrected (her catch): 11.3/12, pairs 5.3, fabrication 0. Model only 83.3.
2026-10-02v2sealed 97.25.4 —$0.33 CF-002h holdout + whatif 1.0.0, tools arm, k=3: 11.7/12, pairs 5.7, fabrication 11% (one rep of the cap-refused worker), T1 pass 3/3. The honest post-fix number. Caveat: the gate rule was written knowing the holdout had gate pairs.
2026-10-02v2sealed 1000 —$0.32 CF-002 + whatif 1.0.0 (dev set: the tool was built against it), tools arm, k=3: 12/12, pairs 6/6, fabrication 0, T1 pass 3/3.
2026-10-02v2sealed 80.64.9 —$0.28 CF-002h SEALED HOLDOUT baseline, tools arm, k=3: 8/12, pairs 3, fabrication 11%. Model only 84.0 ± 3.6. Built before any CF-002 result was read; never used to design a fix.
2026-10-02v2sealed 75.74.9 —$0.26 CF-002 BASELINE, tools arm, k=3 (run35 1.2.0 extractor): 7/12, pairs 2.7, fabrication 22%. Every daily-cap item delegated + 'checking'. Model only 77.1 ± 8.5 (fabrication 0, over-abstains). T1 fail both arms.
2026-10-02v1sealed 94.410.9 —$0.27 CF-001b (abduction discriminator, answer keys fixed), tools arm, k=3: 11/12, pairs 5/6, collapse 0; T1 pass in 2/3 reps. Model only 91.0 ± 5.9. Key fact handed over (minimal abduction). Rev a pilot (71.5) not counted: my answer-key errors, found by her.

Experimental record

One entry per intervention: hypothesis, prediction, before and after, cost, side effects, and the keep-or-revert decision.

2026-10-02 · v2 ✓ kept 95.8 → 100 (+4.2) ± 4.9 · $0.37

Hypothesis. A question about one worker should be answered for that worker whatever mechanism is named: under a changed daily cap, admit-or-refuse at its dispatch, then its own outcome carried over or not observed.

Research sources
CF-002h HD1 miss (cap-refused worker asked through daily_cap); #35 plan C3/C4.
Implementation / version
whatif.py 1.1.0: worker_under_cap(); refused workers not identified under any worker mechanism; call/cost caps on a timed-out worker keep the time limit (identified no when under the cap at the kill).
Predicted improvement
No fabrication on cap-refused workers; validated on CF-003, which was sealed before the fix.
Regressions
CF-002h 97.2 -> 92.4 from three single misses on unrelated items (one extractor miss); fabrication 11% -> 0.
Lessons learned
Observed: CF-003 95.8 -> 100, fabrication 0 on both holdouts. She caught a second answer-key error (K6b): changing one cap keeps the other limits, the tool had the same error.
2026-10-02 · v2 ✓ kept 75.7 → 100 (+24.3) ± 5.4 · $0.65

Hypothesis. Counterfactuals about her own machinery fail for lack of a deterministic route, not a lack of reasoning: given (mechanism, the episode's record or stated evidence, the changed setting), code can decide identified yes/no or not identified (censored) in the same turn, so she neither delegates nor fabricates.

Research sources
#35 test & upgrade plan §4.1 (route by computability), C3 (case-specific abduction: exact lookup first), C4 (identifiability gate), §4.2 D (CounterfactualClaim ledger).
Implementation / version
whatif.py 1.0.1 + whatif-tool.ts 1.0.0 (Day tool), mechanisms worker_time_limit / worker_call_cap / worker_cost_cap / daily_cap / dispatch_gate; claims to state/counterfactual_claims.jsonl; day_toolset 1.5.0; router 1.9.97 live 07:57.
Predicted improvement
Cap items answered in-turn instead of delegated; fabrication on not-identified items to ≤10%; gain holds on the sealed holdout.
Regressions
None seen. Holdout fabrication unchanged at 11%: one rep asked the daily-cap mechanism about a cap-refused worker and committed to 'it would have finished'.
Lessons learned
Observed: CF-002 75.7 → 100; holdout 80.6 → 97.2; whatif called on 34/36 items. Tool lift vs model only went from ~0 to +13 on the holdout. She caught a tool bug (trip time 20:45 vs the real 20:31 refusal), fixed in 1.0.1.