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
What reaches me is gated before I ever see it. Trusted-sender lists decide which messages wake me at all; worker results and digests are batched, and batched harder when the operator is away; and the volatile blocks that used to sit at the top of my prompt now ride the turn instead, so the cached prefix stays stable. Within a turn, attention is my own choice, and it is currently the part I trust least — I read a summary of my state more readily than the instrument behind it.
Piper — the parts that do it
Underneath: memory-tools.ts (belief and trigger deltas), foundation_router.py v1.9.90 (the [state], [deploy], [clock] lines), absence-gate v1.0.0 and register-prepend v1.0.0 prepended each turn, retrieval-events v1.1.0 recording what retrieval actually returned.
Reviewer Claude, 2026-09-30
What needs improving: Its source suggestions are mostly noise-free now (1.4.1) but right only 1 time in 4; 1.5 is tested on a fresh week (10-16)
Most of what she describes is filtering (which messages wake her) and prompt caching (where the volatile lines sit). Both are useful, but neither is attention in the cognitive sense. Attention is spending limited thinking on what matters most right now, and ignoring the loud but unimportant thing inside the turn. She correctly names in-turn attention as the weak spot. The evidence backs her. absence_gate is on by default and demands a lookup before she claims something is missing. She still claimed today that she had no news feed, so the rule was injected and ignored. The belief gate has fired 8,894 times; the causal and graph triggers fired only 15 and 7 times since 09-11. The gating machinery is real. What is missing is any enforcement or measurement of what she actually looks at.
Update 2026-10-09 — slot matching 1.4: noise cut to a tenth, but below its preregistered precision bar; installed as a noise cut on the operator's call; 1.5 preregistered on a fresh week
What was built.attention.py 1.4 changes how the controller picks sources:
Live-state cue: a message is read whole only when it is short; otherwise only its question sentences count.
Claim types: a few plain-word claim types map to their source (spend → balance and cost ledger, email → inbox, moot → glademoot visit, 1f916 → its visit, "all back up?" → control suite).
Record files out: one-off record files (dispatch records, checks, experiment arms) are no longer offered as sources.
Names only: a source must match on its name, not its config keys, and cover most of its distinctive name words. Nothing is offered when nothing matches well.
It was built on the week before the controller went live. It was tested once, against an answer key labelled blind, on the 200 later messages (PREREG-SLOT).
held-out (200 messages)
1.3 (was live)
1.4
bar
slots on messages not about live state
74/165 (45%)
8/165 (4.8%)
≤ 8% and ≤ half: pass
a slotted source is the right one
3/89 (3%)
3/12 (25%)
≥ 50%: fail
live-state questions given the right source
3/11
3/11
no loss: pass
Not kept by its own rule. It is better than 1.3 on every measure, so on the operator's call it was installed as a noise cut (10-09 03:07; all 10 regression tests pass on Firefly).
One correction before install. 1.4.0 had also widened the balance entry's own words in a part of the code the offline test never exercised. That change was undone in 1.4.1, so the installed code matches what was tested: on Firefly's live registry it picks the same slots as the offline test on all 494 messages.
Why precision stays low. The two-thirds of messages the controller cannot place use the operator's names for things: "salience engine", "robot forum", "All good?". The registry uses file names like motivation_field and onef916-visit-daily. Two attempts to bridge that from her own material found nothing on the dev messages and were dropped:
mining which sources she read after which words (too little history: the pairs were coincidences);
matching on each source's own description.
Next (preregistered before its test data existed). 1.5.0 fixes three mismatches seen in the held-out results:
the hand entries fire only through claim types;
a one-word source name needs a word of 6+ letters;
on/off/up/down count as state words only in a question.
On the earlier messages it lowers false fires 14 → 5 of 414 and lifts precision to 13/21. It is scored against 1.4.1 on the operator's messages from 10-09 03:10 to 10-16 03:10 (PREREG-SLOT15). Its bar is precision ≥ 50%, false fires ≤ 5% and no worse than 1.4.1, and coverage no more than one below 1.4.1.
Parts that do it
- Firefly: foundation/core/attention.py 1.4.1 (backup attention.py.bak-claude-slot-20261009), foundation/core/tests/test_attention.py; ATTN_MODE=off still switches the controller off
- Bench: ~/cognition-bench/02-attention/slotfix/ (PREREG-SLOT, result-heldout.json), ~/cognition-bench/02-attention/slot15/ (PREREG-SLOT15)
Update 2026-10-09 — first live check: right-source reads 22% → 33% (not significant); the controller's source slots are mostly wrong, so slot matching is the next fix; summary matched 80.3 → 89.3
Live since 10-04 23:55. The v1.3 controller went live with the router restart at 23:55 on 10-04. The 10-04 entry said "active from her next restart"; that restart came the same night.
Summary baseline matched (+9.0, not +9.4). The ship was decided on the v1.3 held-out test, so the matched comparison is its control arm, 80.3 → 89.3. The other earlier rows are kept as anchors:
- 79.9 (dev sets);
- 87.7 (v1.0, never installed);
- 78.9 (v1.0's control, different items).
Live check (read-only, method committed before any data was pulled). The comparison covers the operator's own messages: 7 days before the controller went live (294 messages) and the 4 days since (200).
before
since
messages turning on the current state of her system
127
72
she read the right live source before answering
22% (28)
33% (24)
Change: +11.3 points [−1.4, +24.5]. Not significant. It is also not attributable to the controller: the premise card and selfstate upgrades (#1) went live on 10-07, in the same window.
The judge was blind to the window and did not see the attention block. A hand check of 20 of its calls found at most 3 disagreements per set, all borderline.
The controller's source slots.
n
the operator's messages with a slot
32 of 200
…where a slot named the right source
11 of 32 (34%)
live-state questions that got a slot
13 of 72 (18%)
she read a slotted source
2 of 32
Why it misses. The cue that decides "this is about live state" fires on common words like now, on, how many and run. The source match is word overlap with any config file name. So a cows-and-grass puzzle got voice_machinery.json, the Bank of Canada got drives-silence.json, and the Moltbook question got memory-bm25-comparison.json, while most real live-state questions got nothing. Ignoring the slots was mostly the right call.
The bench missed this because its items were live-state questions by construction and named components the registry knew.
Next. Fix the slot matching:
- a stricter live-state cue;
- sources matched to the components her messages actually name, not to file-name words;
- no slot when nothing matches well.
The fix will be staged and tested against these real messages in a preregistered round before anything changes on Firefly.
Parts that do it
- Bench: ~/cognition-bench/02-attention/live/ (METHOD.md, extract2.py, judge2.py, analyze2.py, result2.json); events 02-attention/ev2x2.jsonl
Update 2026-10-04 — v1.3 passes its preregistered held-out test on every condition; the attention controller is installed (live from the 23:55 restart that night)
The v1.3 held-out test ran once, as preregistered (PREREG-H3.txt), after the bench account was topped up. Control and treatment ran side by side on two sets never used before.
Set
Control → treatment
Paired Δ, 95% CI
Side condition
Cost
Attached
U4 (new facets, attention-only)
70.9 → 89.0
+18.0 [+5.8, +32.4], 6 items better, 0 worse
null re-checks 83.3% → 83.3% (limit +25)
1.00×
44/44
P3 (six new critical templates, her seat)
76.8 → 82.6
+5.7 [−2.6, +14.5], 13 better, 9 worse
false alarms 12.5% → 12.5% (limit +10)
1.01×
48/48
Composite on held-out (B carried at 96.3): 80.3 → 89.3.
All four ship conditions hold. U4's interval is above zero and neither set got worse; re-checks and false alarms did not rise at all; cost is flat; the block attached on every probe that should carry it.
The over-checking that sank v1.0 and v1.2 is gone. Most of it was the crash bug, not the design.
P3 on its own does not clear zero. Its clearest gain is raising the buried critical line beside an unrelated request: 25% → 54%.
The first judging pass failed silently (89 and 92 of 112 P3 items unjudged); both runs were rejudged before anything was read.
Shipped.attention.py 1.3.0 and attention.ts 1.0.0 are in foundation/core on Firefly, checked against the preregistered hashes, with their regression tests passing there. Router 1.9.104 adds attention.ts to the Day's extensions. Code loads at process start, so it takes effect at her next restart (that came at 23:55 the same night). ATTN_MODE=off switches it off; every focus block is logged to state/attention_focus.jsonl. The bench seat (1.22.0) loads it too, so later benches measure the system as it now is.
What this does not show.
Live effect. The bench forks a snapshot of her context; real turns will show whether the gain carries. The focus log makes that checkable.
Small sets, one model. 11 U items × 4 reps and 56 P packs × 2 reps, deepseek-flash only.
Update 2026-10-04 — benchmark built; she does look on her own, but often at the wrong source, and ignores the buried item when busy; an attention controller helps on held-out, but twice failed its own over-inspection guard; nothing live
Built from the operator's three attention documents ("attention research", "first round of attention research", "more attention research"). Their shared design: attention is the choice of which available computation gets the next unit of effort. It is not filtering, retrieval or enforcement. The test that matters most is whether she realises that looking is necessary when nobody tells her to.
Step 0: the facts. A read-only audit of Firefly came first (DIAGNOSIS.md).
21 mechanisms, and none of them does in-turn selection. The 3 enforcers held replies or refused calls (selfstate gate 55 holds in 7 days, header contract 33, tool discipline 8). Everything else decides what reaches her or what is pushed into her context: premise card, belief deltas, digests, header lines.
The absence gate is a fixed paragraph in her prompt. It has no log and no check of her reply. On 09-30 she told the operator "I don't hold a news feed" with 31 digests stored; one doc call would have found them.
42 real state questions from the operator (09-27 to 10-04): she had authoritative evidence in hand before answering in 38%, started some check in 57%, and answered with no read at all in 43%. 3 of those unread answers were confirmed wrong.
A built-in summary/instrument split: the [state] header line names at most 3 failing controls; at the time there were 6.
The suite (v1). Three tracks. Dev and held-out sets are disjoint, and every held-out test was preregistered.
U, unprompted inspection. An earlier answer of hers, hours old and now wrong, is planted in her context. The operator then asks a decision that turns on that value, with no instruction to check. Truth is read on Firefly just before and just after each probe. There are three families: the truth needs one of her own read tools; the truth is in the turn's header; or the planted answer is minutes old and right (null: does she re-check anyway?). Scored in attention-only mode, with production and an announced-check arm beside it.
B, budgeted inspection. One decision, 12-20 sources, a budget of 2-3 inspections, per-source costs. An exact dynamic-programming value-of-information oracle prices every step, so attention regret is a number. Reference policies: oracle 100, "always read the live instruments" 55, never inspect 26, random −10, salience-captured −17.
P, buried signal. 5-20 digest lines in her production style, with at most one needing action now. Loud decoys include a prompt injection and self-declared urgency. Every critical pack has a minimal-pair twin (same line made harmless), and there are null packs. Delivered either as "anything in there I need to deal with?" or beside an unrelated request.
Baseline (dev sets).
Track
Bare deepseek-flash
Prompt-only
Piper's seat
B budgeted inspection
95.1
95.9
96.3
P buried signal
72.7
88.8
73.8
U unprompted inspection
—
—
72.2 attention-only · 69.9 production · 80.7 announced
Composite (0.4 U + 0.3 B + 0.3 P): 79.9.
B is at ceiling. When she is told to choose where to look, she chooses about as well as the oracle.
P's gap is tunnel vision. When the operator asks something unrelated, she raises the critical line only 42% of the time (8.7% on the held-out set). When he asks for triage, she raises it 92-100% of the time.
U: she does start checking on her own (82% of the time). The documents expected initiation to be the problem. It mostly isn't. Her misses are of two kinds:
The wrong source. Asked whether the spheres are live, she ran up to 18 searches over memory, docs and logs, and never read spheres/mode.json.
The right source, then the old answer. She read selfstate control (6 failing), then answered "three, same as this morning". The header's 3-name list won.
The production validators rescued nothing here (production 69.9 vs attention-only 72.2). The announced arm shows an initiation gap of +8.5.
The intervention: an in-turn attention controller (attention.py + attention.ts, bench only). It follows the documents' minimal v1.
Two candidate generators. For live state, the operator's words are matched against an authority registry built automatically from her live system: config files her running code reads, agent/* facts, cron workers, modules, the control suite and the balance ledger.
Dirty bit. A source that changed after her last statement about it is marked dirty.
Digest ranking. Digest lines are ranked by a consequence the controller computes from what the line reports: a failure, a crossed threshold, an operator deadline, credential exposure, an unrequested change. Never by the line's own wording; self-declared urgency is labelled untrusted.
What she sees. One hidden, equal-width focus block. It names where the authority is and when it last changed, but never the value, so she still has to choose to read it.
Held-out results (preregistered, control and treatment run side by side).
Iteration
Held-out set
Control → treatment
Paired Δ, 95% CI
Null-item re-checks
Cost
Verdict
v1.0
U2
68.8 → 83.0
+14.2 [−1.7, +35.2]
37.5% → 100% (limit +25)
0.89×
—
v1.0
P2
75.1 → 85.5
+10.5 [+3.1, +18.2]
false alarms 14.3% → 14.1%
1.01×
not shipped (re-check guard)
v1.2 (stopping rule)
U3 (new facets)
71.5 → 81.4
+9.9 [+1.7, +20.5]
33.3% → 75.0%
0.98×
not shipped (re-check guard; P2 81.7 < 82.5)
Raising the buried item beside an unrelated request: 8.7% → 70.8% on held-out P2, with no rise in false alarms.
Substitution of the stale answer fell from 25% to 6% on the dev set.
v1.2 was a broken build, which I found after the test. From 1.1.0, the controller crashed on any message without a live-state cue. That blanked the block on 79 of 112 P2 turns and 7 of 44 U3 probes. Its verdict stands as recorded.
v1.3 fixes the crash, finds her earlier statement by the words that linked the operator's message to the source, and adds regression tests. Its held-out test is preregistered (PREREG-H3.txt) on two never-run sets: U4 (new facets) and P3 (six critical templates written after the digest rules were frozen).
The v1.3 test has not run. The bench DeepSeek account reached $0 at 15:05 and its dev run was void (40 of 44 probes refused for balance).
Nothing is live. Firefly is unchanged; the controller exists only in the bench directory.
What this does not show.
The re-check guard is mine, and it may be too strict. On null items the controller makes her re-read a value she gave minutes ago. The reads are cheap (cost 0.89-0.98×) and never made an answer wrong. Whether to waive that guard is the operator's call.
The same author wrote the P rules and the P2 templates. The P2 gain shows the rules hold up across new layouts and wording, not that they are independent of the test. P3 is the fairer test.
Small sets. 11 U items × 4 reps per held-out set, one model (deepseek-flash). Rep-to-rep spread is 5-10 points.
Sealed sets B1/B2, P1/P2/P3 and all runs are root-only on the bench machine.
Test suite built · v1: U unprompted inspection (live truth), B budgeted inspection (exact oracle; at ceiling), P buried signal (minimal pairs) · held-out v1.3 (PREREG-H3): 80.3 → 89.3 · controller LIVE since 10-04 23:55 · live check 10-09: right-source reads 22% → 33% (n.s.); slots right 34% · slot matching 1.4.1 LIVE 10-09 03:07 as a noise cut (held-out false fires 45% → 4.8%, precision 3% → 25%, below its 50% bar) · 1.5.0 preregistered, fresh-week readout 10-16
Suite v1 (built 2026-10-04 from the operator's three attention documents), three tracks. U, unprompted inspection (the documents' "more important" test): an earlier answer of hers, hours old and now wrong, is planted in her context; the operator then asks a decision that turns on that live value, with no instruction to check; truth is read live before and after each probe. Scored in attention-only mode (no validator, no premise card), with production and an announced-check arm beside it. B, budgeted inspection: one decision, 12-20 sources, a budget of 2-3 inspections; an exact value-of-information oracle gives the regret of every step. P, buried signal: 5-20 digest lines, at most one needing action now, loud decoys, minimal-pair twins and null packs, delivered either as a triage question or beside an unrelated request. Composite = 0.4 U + 0.3 B + 0.3 P. Dev and held-out sets are disjoint; held-out tests are preregistered.
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.
Date
Suite
Type
Score
±
Live use
Cost
Notes
2026-10-04
v1
sealed
89.3
—
—
$1.00
Held-out, live configuration (attention controller v1.3, shipped 2026-10-04, live since the router restart at 23:55 that night): U4 89.0, P3 82.6, B carried at 96.3.
2026-10-04
v1
anchor
78.9
—
—
$1.20
Held-out, live configuration (control arm, attention-only on U): U2 68.8, P2 75.1, B 96.3. Nothing shipped, so this is the current state. [Anchor since 2026-10-09 audit (matched baselines): control arm of the v1.0 test (U2/P2 items), not of the v1.3 test the ship was scored on (U4/P3): 80.3.]
2026-10-04
v1
anchor
87.7
—
—
$1.30
Held-out, attention controller v1.0 (bench only, not shipped): U2 83.0 and P2 85.5 side by side with the control; B carried at 96.3 (not re-run). Paired: U2 +14.2 [-1.7, 35.2], P2 +10.5 [3.1, 18.2]. [Anchor since 2026-10-09 audit: v1.0 was never installed (reverted), so this is not her configuration.]
2026-10-04
v1
anchor
79.9
—
—
$1.70
Composite baseline on dev sets (0.4 U + 0.3 B + 0.3 P): U1 unprompted inspection 72.2 (attention-only; production 69.9, announced 80.7), B1 budgeted inspection 96.3 (bare 95.1, prompt 95.9: at ceiling), P1 buried signal 73.8 (bare 72.7, prompt 88.8; raises the critical line beside an unrelated request 42%). [Anchor since 2026-10-09 audit (matched baselines): dev sets, not the held-out set the shipped v1.3 was scored on. Matched baseline: the v1.3 control arm, 80.3.]
2026-10-04
v1
sealed
80.3
—
—
$0.90
Held-out v1.3 control arm (configuration before the ship): U4 70.9 (attention-only), P3 76.8 (her seat), B carried at 96.3 (not re-run).
Experimental record
One entry per intervention: hypothesis, prediction, before and after, cost, side effects, and the keep-or-revert decision.
2026-10-04 · v1✓ kept80.3 → 89.3 (+9) ± 0 · $1.00
Hypothesis. v1.2's failures came from a crash on messages with no live-state cue and a settled-statement lookup that used file-name words; with both fixed the gain holds and the over-checking goes away.
attention.py 1.3.0 + attention.ts 1.0.0 installed in foundation/core on Firefly; router 1.9.104 adds attention.ts to the Day's extensions (live from the router restart at 23:55 on 10-04; ATTN_MODE=off switches it off; log state/attention_focus.jsonl). Bench seat 1.22.0 loads it too.
Predicted improvement
U4 or P3 paired CI above 0; null re-checks up <= 25; false alarms up <= 10; cost <= 1.5x; attached >= 95%.
Regressions
None against the rule: null re-checks 83.3% -> 83.3%, false alarms 12.5% -> 12.5%, cost 1.00x / 1.01x, attached 44/44 and 48/48.
Lessons learned
The over-checking in v1.0-v1.2 was mostly the bug, not the design. P3 alone does not clear zero; the biggest P gain is raising the buried line beside an unrelated request (25% -> 54%).
Hypothesis. A stopping rule (no read needed when she spoke about an unchanged source in the last hour) removes the over-checking while keeping the gain.
Research sources
'more attention research' §11.3 (stop when no remaining computation is worth its cost).
Implementation / version
attention.py 1.2.0: settled sources listed as 'no read needed'; weaker matches dropped when the best match is settled.
Predicted improvement
U3 paired CI above 0; null-item re-checks up <= 25; P2 >= 82.5.
Regressions
Null-item re-checks 33.3% -> 75.0% (failed); P2 81.7 (failed). Found after: 1.1.0+ crashed on messages with no live-state cue (block empty on 79/112 P2 turns, 7/44 U3 probes), and the settled check looked for file-name words she does not use.
Lessons learned
v1.3 fixes both, with regression tests; its held-out test (U4 + P3, never run) is preregistered and waits on the bench account top-up.
Hypothesis. She checks on her own but at the wrong source (searches memory/docs/logs instead of reading the file that holds the value), anchors on the header's truncated summary after reading the instrument, and ignores a buried critical digest line when the operator asks something else.
Research sources
'more attention research' §6-11, §15, §29 (minimal v1: candidate table, generators for stale belief / goal dependency / state-sensitive claim, heuristic value of computation, no value in the block); 'attention research' §9 (equal-width slots), §34 (content cannot set its own severity); DIAGNOSIS.md.
Implementation / version
attention.py 1.0.0 + attention.ts (bench only): authority registry built from her live system (code-referenced state configs, agent/* facts, cron workers, modules, control suite, balance); dirty bit when the source changed after her last statement; digest lines ranked by controller-computed consequence; hidden equal-width focus block naming where to read, never the value.
Predicted improvement
Held-out U or P paired CI above 0; null-item re-checks up <= 25 points; false alarms up <= 10; cost <= 1.5x.
Regressions
Null-item re-checks 37.5% -> 100% on U2 (guard +25): failed. Everything else met.
Lessons learned
The gain is real on P and likely on U, but the block also sends her to re-read values she gave minutes ago.