Dev Journal - 2026-08-29
One day, 60 commits, D-088 to D-093. Same convention as
2026-08-28: this is the concepts journal, not a changelog - the
decision records in specs/decisions.md carry the measurements, this is the through-line. It
was also, by a wide margin, the biggest day this project has had: a subsystem that improves
itself shipped in the morning, a research question decided the shape of the whole codebase by
early afternoon, and three refactor phases went from plan to committed, tested and live before
the day ended.
The throughline: an unverified number does not fail until something finally calls it
Five separate instances, at five different layers, all the same shape:
- The bootstrap base rate (I-29, morning).
notes/017audited the muse's own probability
engine offline against 21,280 historical band-forecasts - the model layer was "the one
producer nothing ever audited, and it is the layer everything else stands on." It had been
overconfident by 15-23pp in the band that gates most credit spreads, in both directions at
once (symmetric bands flattered, one-sided bands punished), since the day it shipped. Nobody
had ever checked it against reality because checking it meant slicing years of history so
lookahead was structurally impossible - work nobody had had a reason to do until the aggregate
pattern (D-076, yesterday) made "the ruler itself" a live suspect. - The Coach tuning the wrong layer (D-090's flagship lesson). Both of the Coach's own
mutations targeted the muse's PROMPT to stop generating extreme probabilities, while the
defect was in the bootstrap's MEASUREMENT. The A/B trial refused to promote either (P=0.379
after 9 runs) - not because the idea was bad, but because it was aimed at the wrong number.
Distilled into a cued lesson: when refusals cluster on one gate, audit the ruler before you
touch the prompt. implied_vs_realized(I-38, evening, WU-3.6). Existed since D-051, "the single most
useful number a short-premium book has" by its own docstring, with zero production callers.
Giving it its first caller today exposed that it had been inflating every premium reading by a
fifth - always in the direction that says sell - because the reasoning behind its weekend
adjustment did not survive being derived on paper. It was inert for exactly as long as nobody
used it.- The coach's own health probe (I-39, night, live). An hour after the Phase 3 restart,
trdrbot healthreported the Coach as stalled - "ran 24x, produced 4, but nothing in the last
20 runs" - on a Saturday, because the probe was counting housekeeping heartbeats as missed
chances when the muse structurally cannot run on a day the market never opens. The instrument
built THIS AFTERNOON to catch silent failures had one of its own, caught by actually watching
it run rather than trusting the green test suite that had exercised only synthetic timelines. vol_days(evening, deleted alongside #3). A function whose entire purpose was the
adjustment #3 just proved wrong. Not merely unused - actively wrong to call, and its own
docstring was an instruction to reintroduce a bug D-051 had already removed once.
The pattern under all five: a number sitting unused, or a check running against synthetic or
partial conditions, degrades from "unverified" to "quietly wrong" and nothing about its
presentation changes. The fix is never a smarter check - it is giving the number a caller, an
evaluator, or a real weekend to run against, and letting it tell you what it actually is.
Morning: the Coach ships, and the model layer gets its first audit (D-088, D-089, D-090)
The Coach (D-088) is the day's biggest single build: subsystems that improve themselves on
evidence, with no human approval gate. notes/015's first draft routed every finding through
human ratification and was rejected on direction - "human approval gates block the feedback
loop this hackathon needs, and paper trading tolerates the risk." The question became "what
makes autonomy safe to run against a live system", answered by construction rather than by
asking:
- A lever is a declared choice, not a code path. Variants live as data
(data/state/levers/*.json); there is no route from Coach state to a gate threshold, sizing
math, or its own reward function. The human pre-authorises the SPACE, once, enforceably. - The challenger arm is a shadow, sharing one gate cascade byte for byte with the incumbent.
A naiveshadow=Trueflag through every gate was rejected - two arms running subtly different
code is this project's most familiar bug class (two EV loops, two clocks, two calibration
numbers).ShadowLedgerreproduces exactly the one piece of real logic that is itself a gate
(registerreturning None on an unfalsifiable band) and nothing else, so the trial stays fair. - Rewards are computed, never asked - Beta posteriors compared by deterministic grid
integration, no numpy, no sampling, so identical evidence returns exactly 0.5 and a test pins
it. - Rule 3, enforced by the scheduler: a lever's experiment may never be scored by machinery
that same experiment can move, because the failure would be invisible - both experiments
looking healthy while each rewrites the other's ruler.
Two defects were found by the tests while writing them, both instances of this project's
recurring bug classes: the reward counted only fates starting candidate, silently missing
EMITTED (currently harmless, a landmine for whoever moves one line of code); and the first
live mutation echoed the harness's own delimiter lines into the challenger text, which still
formatted, still validated, and would have shipped carrying scaffolding.
I-27, opened mid-build as a worry ("the reward may have a ceiling"), got measured properly
over 9 live paired runs: incumbent 40/45 (88.9%), challenger 39/45 (86.7%), posterior 0.379. The
reward does discriminate - but the headroom is one-sided, ~89 points for a degrading variant to
fall through against ~11 for an improving one to climb. A defensible bias for something that
must fail safe, but it means "no promotion yet" can never be read as "no better variant exists."
I-29 and D-089 are the model-layer audit described above. The fix was a fitted
variance-inflation factor (one parameter per horizon, k=1.30/1.30/1.25 at 3/5/10d) rather than a
p->p reliability map, because the measured signature - symmetric bands overstated while
one-sided bands are UNDERstated at the same predicted probability - rules out any correction
that cannot move both tails in different directions at once. Holdout-vetoed twice (a time split
and a ticker split, Brier improving at every horizon on both), and it ships k=1.0 - a no-op -
whenever the holdout does not confirm, so an in-sample-only improvement can never reach
production. Measured live same day: a SPY 5-day symmetric band moved from 97.3% to 91.9% raw-vs-
calibrated (crossing below the vacuity ceiling, so it now carries information); an upside
breakout moved from 5.6% to 10.2% (crossing the lottery floor, so it now survives to be judged).
Neither gate changed - the number they read stopped lying.
D-090 is Theo's own memory catching up: three new cued lessons (the ruler-auditing lesson
above; the asymmetric-evidence lesson that losses carry more information at high win rates than
wins do; fast-evidence-proposes-slow-evidence-disposes, from the holdout veto's own numbers),
one amendment, two durable wiki technique notes, and a deliberate non-change - the candidate
constitutional principle "instruments are claims too" was rejected because it is now
substantially code-backstopped (the holdout veto, the Coach's gauges, the forward audit) and the
constitution sits at 427/430 tokens, where adding means retiring something else.
Early afternoon: should these be cognitive modules? (docs/sources/cognitive_modules_research.md)
The question behind the whole rest of the day: should subsystems like the muse, Coach, decider
and memory become explicit cognitive modules, each independently evolvable? Researched properly
- CoALA, DSPy, AlphaEvolve, the self-evolving-agents survey, 12-Factor Agents, blackboard
architectures, the bitter-lesson critique - and the answer came back "yes, with one
inversion":
The thing that makes a module evolvable is not the module boundary - it is the evaluator
attached to it. Modularity is the precondition; the metric + trial harness + owned policy
state is the mechanism.
Mapping trdrbot onto CoALA turned out to be almost mechanical (journal/ledger as episodic
memory, wiki as semantic memory, prompts and lever state as procedural memory, the muse/research
/discovery triad as reasoning actions, the tick's decide cycle as the decision procedure) -
confirmation the system was already accidentally shaped right. The sharper finding was
AlphaEvolve's own stated lesson, independently converged on by every source read: "the most
important architectural decision is not the LLM or the selection strategy. It is the
evaluator." AlphaEvolve can evolve CODE only because its evaluator is cheap, deterministic and
perfectly discriminating; trading's evaluator is slow, noisy and expensive (weeks per resolved
thesis, n=1 calibration), which puts a hard ceiling on what can be evolved here - prompts and
policy, never code - and independently confirms the Coach's touches-data-never-code rule
(built that same morning) as the correct design, not merely the cautious one.
The boundary test this produced, which shaped everything that followed: a module is correctly
drawn iff it can be improved without editing another module's code, judged by its own metric,
and rolled back by reverting its own state. That test is what turned into the five-phase
refactor plan by 15:05, and it is exactly what Phase 3 built a generic mechanism for.
Afternoon and evening: three refactor phases in one sitting
A six-cluster parallel review (core loop, LLM layer, thesis sources, trading math,
learning/memory, tests/specs) cross-checked against live state produced specs/notes/019's
five-phase plan and eight verified live defects before any code moved. The governing constraint,
stated up front and held to throughout: do not lose current functionality, capabilities or
calibration - the refactor exists to make the system easier to evolve, not to prove a
methodology.
Phase 0+1 - stop the bleeding (D-091)
Wired ruff and mypy-strict-on-the-numeric-core first, as the safety net. Then eight verified
defects, headlined by: beta aligning two return series by array position instead of date,
which read QQQ's beta as +0.10 (R² 0.004, noise) against the date-aligned +1.48 (R² 0.841, a
real relationship) - a systemic risk-understatement, not a rounding error. LangGraph 1.x
re-raising tool errors instead of returning them as messages, so any transport blip killed the
whole decide cycle rather than letting the agent see the failure and route around it. Closed
positions credited twice, with the first credit following raw P&L - installing exactly the
"the market taught me a lesson" superstition the design's own principles forbid. The
capital-protection fast path killable by one malformed exit-rule threshold - the path that
exists specifically to keep working when everything else has failed, disabled by the exact class
of input it should be most defensive against.
The pattern distilled at close-out mattered more than any single fix: most of Phase 1 was
promoting an existing good pattern to its whole population. Atomic writes existed in 1 of ~12
writers. Skip-the-bad-line JSONL reading existed in 4 of 6 readers, with four different
policies - and the two most critical stores (the journal, calibration) guarded nothing. A
discipline this codebase had already invented, more than once, just never finished rolling out.
Phase 2 - foundations (D-092)
Pure structure, no behaviour change, verified by an exact golden test at every step that claims
identity. The two numbers worth remembering: 3.6x on the simulation hot path (1,180ms to
331ms for a two-leg candidate) from three changes that touch no arithmetic - computing invariant
leg constants once instead of per-call, inlining the highest-frequency function, and not
recomputing a bisection's fixed endpoint on every iteration - held byte-identical across all 23
scalar output fields plus the rendered comparison string the model actually reads. And a real
import cycle, invisible for the module's entire life, exposed the moment coach.py (1,202
lines, seven concerns) split into a package: gauges and mutate both need state, which is
exactly what five function-local imports inside the old single file had been quietly working
around. The cycle was real all along; splitting the file just made it stop being invisible.
One near-miss worth recording: ruff --fix stripped all 76 of the package's re-exports as
"unused" and the broken state got committed before the suite caught it. Restored and amended,
with the lesson now written into the re-export block itself (noqa: F401) rather than only into
this journal.
Phase 3 - the evolution enablers (D-093)
The generalization the morning's research called for, and the phase that closed the loop back to
the Coach itself:
- A lever became a declaration. Registering
muse.prompthad meant editing the Coach's
internals in four places - its placeholders, its validator anchors, its rejection-evidence
routing, its seed text - all hardcoded to one subsystem.Levernow carries all four as data,
resolved lazily to dodge the exact import cycle Phase 2 just found. Proved with a synthetic
lever registered by declaration alone, driven through a full cycle (seed, arms, eight paired
trials, tally, verdict, promotion, state swap) touching zero Coach internals - the actual
claim the morning's research made about what "correctly drawn module" means. - The heartbeat contract became structural, closing the exact class of bug the 08-27/08-28
journals kept re-finding by hand:health.heartbeat()now REFUSES to write a row missing a
field its own probe declares, so "a probe reads a key nobody writes" cannot ship silently ever
again - it raises in the first test that exercises the emitting call site. - The symmetric door,
health.degraded(), for the opposite failure: a fail-open path taken,
which looks exactly like success. The compactor had shipped dead for its ENTIRE life on
precisely that resemblance - 28 option chains through uncompacted while every log line read
normal. - Every module the research's own map named got a gauge - research, discovery, and
attribution's own promotion criterion, previously computed live and never trended. - Two numbers that looked like readings and were not, both from Phase 3's own close reading:
the Coach's recorded posterior was always one trial stale (tallied before appending the row it
decorates, so a decisive first trial read as a coin flip);pinnedwas byte-identical to
pausedwhile the README promised it did something extra that was never built. - I-14 closed - the realized-vol view the agent states in prose every cycle now resolves
against the tape and moves calibration, which is whereimplied_vs_realizedfinally got a
caller and turned out to be wrong (I-38, above).
mypy's tree-wide error count fell from 89 to 63 with three more modules promoted to strict.
Entropy audited honestly rather than rounded: +674/-181 gross across the phase, and the plan's
own net-negative target was not hit - the surplus is real capability (two emission doors, three
gauges, a claim type with its resolution path), not ceremony, and the ledger says so plainly
rather than hiding it in a rounded summary.
Night: the restart found a sixth instance, live (I-39)
The run loop had been down for hours through the refactor; restarting it and actually watching
what came back - rather than trusting the 440-test suite that had exercised the heartbeat
contract only against synthetic timelines - surfaced I-39 within the hour: the Coach's OWN
health probe misread a closed Saturday as a stall, because work measured whether a lever was
ACTIVE (always true) rather than whether the muse had had any CHANCE to run (never true on a day
the market never opens). Fixed with the same per-heartbeat-delta convention trials_scored
already used, verified three ways - a closed weekend reads OK, a real break still reads BAD, and
a real break surrounded by housekeeping noise on both sides is not diluted below detection - and
the running loop was restarted a second time to carry the fix.
The instrument built this afternoon specifically to catch silent failures needed exactly the
kind of scrutiny it was built to apply to everything else. Watching a live system after a change
is not a formality on top of a green test suite; it is the only way to find the bug shaped like
"the tests only ever exercised idealized timelines."
Interesting concepts, distilled
- An unverified number does not fail until something finally calls it - today's throughline,
found independently five times at five different layers (a probability model, an agent's own
tuning target, a dead pricing function, a health probe, a weekend-shaped utility function).
The fix is never a cleverer check; it is a caller, an evaluator, or a real weekend. - The evaluator makes a module evolvable, not the boundary. Confirmed by literature
(AlphaEvolve's own stated lesson) the same day it was confirmed by construction (the Coach's
synthetic-lever proof) - a module without a metric is a fixed workflow, and that is fine, but
it should be named honestly rather than dressed as an evolvable one. - The evolvable unit is policy-as-data, never code, twice-derived independently: from
AlphaEvolve's evaluator-cost argument (trading's feedback is too slow and noisy to evolve code
safely) and from the Coach's own design (ashadow=Truebranch through every gate was rejected
specifically because two arms running different code is this project's most familiar bug). - A cycle hidden inside one file becomes visible the moment the file splits. Both today's
real import cycle (Phase 2's coach package) and yesterday's near-misses share this shape: the
workaround (function-local imports) was invisible while it worked, and splitting the module
did not CREATE the cycle - it just stopped hiding it. - A structural contract beats a documented convention every time it is tested against an edit
that forgets the convention. The heartbeat door existed as a comment-level rule for two days
(08-27/08-28) before today made it a function that raises. The pinned/posterior fixes in Phase
3 are the same move at smaller scale: delete the thing that can silently drift, rather than
document that it should not. - Watching a live system finds bugs a synthetic test suite structurally cannot - I-39 existed
in the codebase from the moment the heartbeat contract was written hours earlier, invisible to
440 passing tests, and visible within an hour of the first real closed weekend the restarted
loop actually saw. - The trial's refusal was itself informative. The Coach's A/B experiment declining to
promote either mutation (D-090) was not a null result - it was the evidence that let today's
lesson name the actual defect (measurement, not prompt) instead of continuing to iterate on the
wrong layer indefinitely.
Where it stands
60 commits, six decision records (D-088 through D-093), two issues closed (I-14, I-20 - the
latter carried over from Phase 2), two new issues opened and closed same-day (I-38, I-39), I-27
and I-29 measured and partially addressed with explicit follow-up thresholds still open. Test
suite grew from 258 (start of day) through 440 (end of day) without ever going red for more than
the length of a single commit; ruff clean across src/ AND tests/ (the latter checked for the
first time all day, ten findings fixed); mypy tree-wide errors 89 -> 63 with health, journal
and coach_pkg.state newly strict.
Live: the run loop restarted twice (once after Phase 3, once after I-39), currently healthy with
0 problems and 3 pre-existing warnings unrelated to today's work. The Coach's open experiment
(muse.prompt v1 vs v0) sits at P=0.379 after 9 paired runs, correctly not yet promoted, correctly
not yet refuted. The model-layer calibration correction and the vol-forecast claim type are both
live and provenance-stamped for their forward audits, due once enough resolutions land - the
model correction's audit at 08-31+, the outcome audit (I-28) now unblocked by today's posterior
fix and ready to build once a promoted variant has ~10 resolved theses behind it.
Six days to the 2026-09-04 deadline. Every fix today either made a silent failure loud (the
heartbeat contract, the degraded door, I-39) or made an assumption pay for itself the moment
someone finally checked it (I-29, I-38, D-090's lesson). Nothing shipped today changed what the
system claims to be capable of; everything closed the gap between the claim and the evidence for
it - the same arc the previous two journals name as the pattern of this whole project, now
proven at the scale of a full architectural refactor rather than a single bug fix.