Panel run 29 — 2026-09-28
Records for the daily research panel's run of Monday 2026-09-28. One row
opened (queue/open/lab-1-collection-error-fail-closes-trading-gate.md); this
note carries everything that was judged worth recording but not worth a
queue slot, plus the run's dated escalations.
Run record: considered=7 · survived-review=1 · opened=1.
Standing context, because it governs most of what follows: GitHub has refused
every Actions job repo-wide since 2026-09-19 (the account's free allowance is
spent; it resets 2026-10-01). Re-verified this morning — the two lab-commit
runs at 06:00Z and 06:21Z today died in 3 seconds with zero steps, the billing
signature per ops/DAILY_AUDIT.md §4c. Nothing has traded since 2026-09-18;
five trading days are permanently lost (09-21 … 09-25) with 09-28 in progress.
1. THE ONE THING WITH A DEADLINE — Friday 2026-10-02, zero margin
This is the headline of the run. It is recorded nowhere else in the repository — not in a memo, not in the ledger, not in a queue file.
research/2026-08-01_b4_skew_activation_pin.md:83-85 is hash-frozen and reads:
If s′ − s exceeds 10 trading days (a dead-cron stretch), the observation is dropped rather than becoming one giant-horizon week.
The last option-skew capture is 2026-09-18, carrying 888 valid rows — comfortably over the pin's ≥400 floor, so it is a signal date. Counting NYSE trading days forward from it:
| next qualifying signal date | trading days from 09-18 | the 09-18 observation |
|---|---|---|
| 2026-10-01 (Thu) | 9 | survives |
| 2026-10-02 (Fri) | 10 | survives — "exceeds 10" is false, by exactly zero margin |
| 2026-10-05 (Mon) | 11 | destroyed, permanently |
| 2026-10-09 (Fri) | 15 | destroyed, permanently |
So: a qualifying skew capture (≥400 valid rows) must land on or before Friday 2026-10-02, or the 2026-09-18 observation is dropped from the B4 panel for good. ISO week 2026-W39 (09-21 → 09-27) is already lost outright — it has no qualifying date and never will.
The allowance resets 10-01, so the automated path just makes it. If anything
slips — the reset lands late in the day, the first run fails, the dispatcher
misfires — the remedy is to run thales snapshot-skew by hand from the Mac
on 10-01 or 10-02. This is un-backfillable either way, on the one live forward
experiment this shop has.
2. Escalations with dates — none of these is buildable work
- #185 and #186 are the only lever on whether this outage recurs, and
auto-merge cannot land them. The outage memo records that the owner has
decided to stay on the free tier, so the remedy is "fit inside the
allowance"; those two PRs are exactly that fix (~250 Actions minutes a
month). But
auto-merge-records.ymlis itself an Actions workflow, refused until the reset. A human merge is the only path, and if they land after October's allowance is already burning at September's pace, the outage repeats late in the month. One caveat on sizing, worth stating because nobody has: both PRs were measured against this repository's minutes, while the allowance is account-wide across repositories. Nobody currently knows the account-level number, and nothing in the tree computes it (grepfor billing/minutes/ allowance finds onlyops/DAILY_AUDIT.md:380, a post-hoc diagnosis recipe). - #177 and #176 republish known-wrong numbers publicly on 10-01. Both are
still unmerged and both defects are still live on
main:src/thales/execution/fleet_digest.py:169is still"gate_days": len(equity_hist)(the VRP forward clock, inflated by 11 days because it counts from activation rather than the pinned reset, and counts marks rather than returns), andforward_gate.pystill sums ledger rows the ledger's own annotation marks basis-contaminated (~2× overstated twin). The first post-outage fleet digest runs 2026-10-01 andexport-publiccommits to the public site in the same workflow. - The December go-live gate — a correction to the standing record. The
gate could never have PASSED on 2026-12-01: NYSE days 2026-06-11 →
2026-12-01 inclusive = 120, so
n_livemaxes at ~119 againstmin_live_trading_days: 126.not_beforeis a floor, not a target, andconfig/settings.yaml:353already says so ("clean clock 2026-06-11 + 126 td lands ~Dec 10"). More materially: the daily audit of 2026-09-24 concluded that "each further lost day moves that date one further." That is wrong. All three trading workflows runthales portfolio backfill-equity --days 14on every run (paper-trading.yml:276,-meanrev.yml:165,-vrp.yml:111), andAlpacaBroker.get_equity_historymapsdays <= 30to Alpaca period"1M"and does not truncate back todays(alpaca_broker.py:558-584, verified). All eight lost sessions fall inside one month of 2026-10-01, so the first post-outage run should heal the clock in full and restore the 126th return to ~2026-12-10. Lost days are not cumulative. The new exposure this creates: the"1M"window means the earliest lost mark (09-21) stops being recoverable around 2026-10-21 — and the outage memo says allowance exhaustion "will recur, most likely late in a month", i.e. the next outage would land in the window where the first one is still un-healed. Worth confirming the backfill actually fired on 10-01 rather than assuming it. - Triage's kill-counter (a) fires 8 of 8 today, and fires into nothing:
git log -- research/queue/approved/returns exactly one commit ever (the README), so the owner-approval directory has never held an item, and the pre-committed remedy (AUTO-APPROVE) was itself dismissed 2026-08-31 as unbuildable. Eight weeks, thirteen proposals, zero approvals. See §3. - Five older PRs carry new head commits no panel has reviewed. #168, #171,
#174, #176 and #177 all gained new heads on 2026-09-26 (07:27–07:36Z), each
a response to a prior panel review; three touch
src/thales/execution/. Checked cheaply because the file is keystone-pinned on a live sleeve: #177'sconfig/vrp.yamlchange is comment-only, no keystone value moves. Flagged for the next change-review lens; reviewing five PRs' new heads was not this run's scope. - The panel itself was dark on Friday 2026-09-26 — no beacon commit, no PR, no session artifact. The scheduler's control plane exposes only the most recent run, so from here the cause is not establishable; recorded rather than guessed.
3. RDR-1 — the third decline, and the last one
research/queue/dismissed/rdr-1-no-reader-for-dismissed-reopen-conditions.md
records the finding that queue/dismissed/ holds 30 files, every one carrying
a reopen condition, and nothing reads them on their date. Run 28 declined to
reopen it and pre-registered: "the next panel to find a fourth instance
should open the row without further deliberation."
The fourth instance exists, and both of run 28's conditions are satisfied.
- The "dies permanently" clause is unsatisfied.
grep -n "dismissed"overops/QUEUE_TRIAGE.md,ops/prompts/triage.md,ops/RESEARCH_PANEL.mdandops/prompts/panel.mdreturns only write-side and structural hits. No routine is instructed to evaluate reopen conditions. - CQA-2 is the fourth fired-unevaluated dismissal (after LCK-1, ERN-1,
BCN-1). Its leg (a) —
research/queue/dismissed/cqa-2-latest-file-only-qa.md:45, "a capture stream loses a day and no instrument reds … reopen immediately and rank it P0" — has both conjuncts measurably true during this outage, andgrep -rn "CQA-2"returns only fold cross-references. Nothing evaluated it.
It is nonetheless recorded here rather than opened as a row, for three reasons, and this is the third time the panel has declined:
- The row is not buildable, and building it would do harm. The ask is
prose in
ops/QUEUE_TRIAGE.mdandops/prompts/triage.md. The prompt mirrors carry a standing rule that any prompt edit lands in the mirror and is pushed to the live control plane in the same sitting — and the implementer's rails forbid touching the control plane. An implementer building this row would land the mirror and leave the live trigger prompt stale: precisely the invisible prompt-rot the rule exists to prevent, and which has already happened twice in this repo. - A note reaches the owner by the same channel a row does. A dated file
in
research/is a PR, and PRs surface in the fleet digest's research-pipeline section — the same visibility, at zero slot cost and zero eviction. Run 28's own annotation reached the owner exactly this way. open/is at its 12-file cap, and the one row this run opened (LAB-1) already spends the eviction.
New material that changes the owner ask itself. dismissed → open is
not a sanctioned transition for any routine. Triage owns open→dismissed;
the implementer owns approved→built|dismissed; nobody is granted
dismissed→open. Yet all 30 dismissed files carry reopen conditions, and
CQA-2's own text says "Reopening costs one git mv" — a move no routine may
make. So the two-sentence fix as previously drafted is incomplete: it
commissions a sweep whose only remedy nobody is permitted to execute. The
corrected ask is two things, not one:
(a) Add to
ops/QUEUE_TRIAGE.md§1 andops/prompts/triage.md's sweep step: "Also sweepresearch/queue/dismissed/for reopen conditions dated within the next 14 days or whose triggering event has already occurred; report each one." (b) Name who may act on a fired condition — either grant triage thedismissed→openmove, or state that reopening is the owner's move alone. Without (b), (a) produces a report nobody can act on.
Terminal clause, and it binds this panel, not the next one. If the owner
does not make that edit before the next triage run, the panel stops raising
RDR-1 entirely and it is recorded as an owner decision. A panel that
annotates the same unactioned item a fourth time is manufacturing output —
NORTHSTAR.md §2's degenerate strategy in slow motion — and a chain of panels
each minting an obligation for its successor is a ratchet, not discipline. The
ratchet is cut here, on the record.
One argument deliberately not used. ops/RESEARCH_PANEL.md:21-22 says
reopen conditions become "standing tripwires future panels EVALUATE (did Y
become true?)", and the panel prompt orders that section be followed exactly —
so it is arguable that a routine is already instructed, and RDR-1's "dies
permanently" clause is already satisfied. RDR-1's author quoted that exact line
and ruled it non-operative preamble. Re-reading it now, in the direction that
retires the file, is the after-the-fact reinterpretation this shop treats as a
cardinal sin. Recorded as contested, not used to close. It has one
consequence worth carrying: if that line binds, the defect class is
non-compliance with an instruction the panel already has, not a missing
instruction — and no queue row has ever fixed non-compliance.
On CQA-2 itself: it should NOT be reopened. Its proposed fix is a
missing-today check inside capture_qa, and capture_qa did not run at all
during the outage — the remedy is counterfactually inert against the event
that tripped its own trigger. It counts as a fired-unevaluated instance (which
is what RDR-1's leg (b) measures) without being a valid reopening. Those are
two different questions and were being run together.
4. Hypothesis lab — two findings folded here rather than opened as rows
The lab's trading-safety exposure is the row (LAB-1). Three further findings were raised against its honesty guarantees; one survives, as a fold instruction.
- FOLD INSTRUCTION —
lab confirmprints the vault verdict before it charges the ledger.src/thales/lab/cli.py:505-528echoes the p-values, the bar andCONFIRMED / NOT CONFIRMED; theconfirmrow is appended at:529, the last statement in the function. A Ctrl-C, a full disk or an append error after the answer is on screen leaveskun-incremented, the id absent fromledger.confirmations, and the rule re-openable at α/2 with the holdout answer already known. This is not an accusation of cheating — it is that the operator would not know the vault had been opened.src/thales/lab/study.py:480-487states the correct principle in its own docstring ("Charge the ledger FIRST, then write the artifacts … the trials are still counted (the safe direction)");confirmis the one path that does not follow it. When anyone next openssrc/thales/lab/cli.py, move the append above the firsttyper.echoof any result. Three lines, with the module's own precedent as the spec. - Provenance, worth one sentence: both committed study runs are stamped
+lab-dirty. The lab's ledger recordscode_versionas18a510b+lab-dirtyand547950a+lab-dirty— i.e. the two closures CLAUDE.md now cites as pre-registered NULLs (cross_index_v1,comprehensive_v1) were produced by code that was not committed at the time of the run. Recorded, not escalated; the verdicts were NULL in both cases, so nothing rests on them. - Struck at review: the claim that the lab's vault date and never-shrink
floor are currently unguarded because their pinning test runs only in
fleet-digest.yml. True, but it is a strict subset of "no CI has run in nine days", which is already the headline incident — and the runtime backstop is not vacuous in the real repo, sinceresults/lab/ledger.jsonlholds four records all sealed under2023-01-01forcheck_vaultto refuse against. - Also struck: that trial charging is blind to the lab's own code version
(
settings_keyhashes settings but not source;code_versionis written five times and compared never). The gaming channel is genuine but exotic, and the naive fix — foldingcode_versionintosettings_key— charges a trial for every unrelated commit, which is worse. Recorded as known, not as work.
5. Capture continuity — considered and not filed, deliberately
All six time-gated capture streams are delivered by one workflow on one
billing-gated account, and the incident memo's remedy section is framed
entirely as cost-fitting inside the allowance, never as capture
continuity. It is a real structural observation and it is not a
relitigation of queue/dismissed/cron-delay-capture.md (that dismissal
rejects capturing runner-latency telemetry as a data stream; this is a
delivery-path question, a different object).
It is not filed as a row because there is no experiment in it: the remedy set
is "pay GitHub", "move the capture crons to the Mac launchd dispatcher that
already exists", or "accept the risk" — owner decisions with no falsifiable
design and no kill criterion, and ops/RESEARCH_PANEL.md §4 says a suggestion
without a kill criterion does not ship. A budget detector is not buildable by
any routine either: the binding number is account-wide and reachable only with
owner-side billing credentials no routine container holds.
And no dismissal file was written for it, which is this run's one original
procedural point. A dismissed/ file's entire promised function is to become a
standing tripwire a future panel evaluates — and this run has just measured
that four such tripwires have fired unread. Minting a fifth record whose
mechanism is demonstrably not working, on a topic the owner may act on this
week, adds surface and buys nothing. Its one concrete consequence already has a
louder carrier: §1's Friday deadline is capture-continuity risk, dated,
quantified, and attached to the only live experiment.
6. Clean negatives — recorded so nobody re-derives them
- B4-NOTCH leg (b) has NOT fired. Cumulative accrued-week loss measured at 6.7% today (15 accrued ISO weeks, 1 with no qualifying day), rising to ~11.8% once W39 is counted — marginally above, not "materially exceeding", the ~11% its reopen condition names, and by an outage rather than a calendar notch.
- B5's termination clause has NOT fired. An 8-session outage is not the lane being retired; the clause cites a two-consecutive-DEGRADED-verdict rule. Recorded now so nobody reaches for it after seeing Δ.
- B5's lost days are already pre-registered as backfillable — the pin says
so explicitly and names
portfolio backfill-equityas allowed. One residual: if the marks are not backfilled, returns are computed by consecutive-mark differencing with no date-gap awareness, so 09-18 → 10-01 becomes a single 9-session compounded return — and 2026-10-01 is a turn day under the pinned phase. The single most contaminated return in the record would be classified as a turn day. The backfill removes this entirely, which is one more reason to confirm it fired rather than assume it. - RCX-1 leg (a) has NOT fired — the largest line in any committed
.jsonlis 740 B against its 4096 B tripwire. - NORTHSTAR §6's G1 row is correct and the stale "to build" line has not returned; §7's contrary line is the dated 2026-08-02 appendix, superseded by §7b. No live defect.
- The live trigger prompt matches
ops/prompts/panel.mdverbatim. Read from the scheduler's control plane and compared against the mirror's fenced body; prompt-rev2026-08-21-panel-r2on both. No disagreement to report. - Frontier: zero from both halves, correctly. No deferred direction
activated (B1 at 34 of 60 with median 7.0 expiries against its <5 vacuity
bar — trending away from vacuity; B2/B3/A5 unbuilt and owner-gated). Six
scout idea-spaces deliberated, four dead on prior art — including the one
genuinely attractive candidate, IBKR's public
shortstockfee file, killed because the 2026-07-25/26 probes found the anonymous FTP dead and iBorrowDesk bot-blocking, which puts it in the banned fragile-scrape class. - Scout cadence: 6.00 of 8 weeks. Revert-to-watch-only fires 2026-10-12 — the same date as ERN-1's dated default. Two clocks, one date, two weeks out.
7. Slipped clocks — the outage moved these
| clock | was | now, assuming 2026-10-01 resumption |
|---|---|---|
options_iv_term 60-td vacuity read (B1) | ~2026-10-26 | ~2026-11-05 |
| shortability 60-td read (BTB-1 is pinned to land before it) | ~2026-10-19 | ~2026-10-29 |
GAP-1's ledger deadline (lost capture-days must reach ACKNOWLEDGED_GAPS + CAPTURES.md before capture_gaps()'s trailing 20-td window rolls past them) | ~2026-10-23 | ~2026-10-28 |
| momentum go-live 126th return | ~2026-12-10 | ~2026-12-10 if the backfill fires, ~2026-12-22 if not |
| VRP forward gate 126th return | ~2027-01-26 | ~2027-01-26 if the backfill fires, ~2027-02-05 if not |
GAP-1 remains the cheapest dated item in the tree (~0.2 pd, implementer-
buildable) and it sits in dismissed/, where no implementer can reach it —
which is §3's problem wearing its most expensive hat. Note it needs three new
ACKNOWLEDGED_GAPS keys created (options_skew, options_chains,
options_iv_term have none), not merely lines appended.
Appended 2026-10-01 from the scheduled check-in on this PR
This PR was stranded for three days (see the mechanism in panel run 30's
append: auto-merge fires on pull_request events, #188's was consumed and
refused during the outage, and an allowance reset does not replay it;
rerun-failed-jobs returns 403 to a routine). It is merging now with a
correction it must not merge without, because §2's December-gate paragraph
makes a prediction that is partly falsified.
The backfill healed 6 of 8 lost marks, not 8 — and the same two are missing on all three sleeves
§2 said the first post-outage run "should heal the clock in full". Measured on
main at 3d4f432, after all three sleeves ran on 2026-10-01:
| sleeve | outage-window trading days | missing after backfill |
|---|---|---|
momentum (data/processed/) | 10 | 2026-09-21, 2026-09-28 |
meanrev (data/state/meanrev/) | 10 | 2026-09-21, 2026-09-28 |
vrp (data/state/vrp/) | 10 | 2026-09-21, 2026-09-28 |
So the mechanism I described does work — 09-22, 09-23, 09-24, 09-25, 09-29 and 09-30 all came back from broker truth — but two sessions did not, the two Mondays inside the outage, identically on all three sleeves. Identical across three independent Alpaca accounts means this is systematic, not a per-sleeve fluke.
Momentum now stands at 76 marks since the pinned clean clock 2026-06-11 →
n_live 75, against 78 NYSE trading days in that range. 126 returns needs
127 marks.
I am deliberately not naming a cause. Both obvious candidates — Alpaca's
period="1M" portfolio history omitting those points, or
select_backfill_entries rejecting them — are untestable from this container
(no broker credentials: NOT-RUN), and this run's sibling panel (run 31)
spent its headline on a record whose named cause was false. The measurement is
solid; the explanation is open. Note also that it is not a general Monday
defect: 13 of the 15 Mondays in the clean-clock window carry marks.
The dated consequence, which is the reason this is worth your attention.
AlpacaBroker.get_equity_history maps days <= 30 to period "1M", so
2026-09-21 leaves the recoverable window around 2026-10-21 — and PR #191
independently forecasts the next allowance exhaustion at ~2026-10-20. The
chance to recover that mark closes at almost exactly the moment the next
blackout is forecast to begin. If those two marks are wanted, the window is
roughly the next three weeks, and it is narrower than it looks.
Also worth correcting in the frozen archive's direction: RESEARCH_QUEUE.md
records equity_history.jsonl as "BACKFILLABLE — 0 — healed by
backfill-equity". That is now false for two sessions on three sleeves. The
archive is frozen and must not be edited; this note is the correction of
record.
The other three check-in items
- The skew deadline is still live and still unmet.
data/options_skew.jsonlonmainstill ends at 2026-09-18 (888 valid rows). The last four Skew Snapshot runs all failed — 09-29 19:11Z, 09-29 22:53Z, 09-30 19:11Z, 09-30 22:53Z — and the most recent died in 3 seconds with zero steps, i.e. the billing refusal, not a new defect. Today's 19:00Z attempt had not fired when this was written (15:20Z). Two automated attempts remain (10-01, 10-02). Panel run 32's correction stands and matters for any hand-run rescue: the rescue is worth two observations, not one, and a post-close rescue would fail clause (c) of the B4 pin's still-uncountersigned 2026-09-02 append — so the countersign ruling has to precede the rescue, not follow it. - Trading resumed on all three sleeves (state commits
3d4f432,a4597f0,18f72a0), so momentum's October alpha selection was not missed. - #185 and #186 both merged 2026-10-01 07:31Z and 07:32Z, by hand as predicted. §2's note that they needed a human merge is discharged. Its other claim — that nobody had the account-level number — was closed the same day by PR #191, which measures the trims at ~8% of the account and forecasts recurrence ~2026-10-20. That is a far larger loss than the skew deadline this run headlined (#191 and run 31 size it at roughly fifteen times), and my run put its emphasis on the smaller of the two.