HANDOVER — options pipeline, state at 2026-10-01¶
Written at the end of a working session. Everything asserted here was verified on the day; where it was not, it says so. Read "Traps" and "What I got wrong" before doing anything — those two sections are the only parts you cannot reconstruct from the repo.
1. State of the world¶
| repo | git.makanilani.com/makanilani.com/okf-trading-system, branch main (this doc's own commit is the tip as written — a pinned hash here would be stale the moment it was committed) |
| workstation + hermes | both on main, clean, in sync; one clone, one branch, one worktree each |
| decision journal | 92 records |
| test suites | iv30_atm 64, iv30_shadow 30, check_deploy_source 22, ledger 3 suites, gate 2 suites — all green on hermes |
| ledger | 58 records, validator exit 0, 0 violations |
| shadow series | 1 record (day 1), 96-journal/iv30-shadow.jsonl |
| open board cards | 19 (4 In Progress, 8 Backlog, 7 Blocked/Decisions) |
| deadline | 1 NOVEMBER 2026 — not 1 Oct; see §5 |
GitHub is gone. The remote is Forgejo over SSH only; the agent SSH key authenticates as
claude_laptop, and an API token for PRs lives at ~/.config/forgejo-claude.env (0600,
owner-created, never echoed).
2. The one thing that is running by itself¶
The IV30 shadow series. Round prompt step 1a runs tools/iv30_shadow.py after the
capture and appends one line per round to 96-journal/iv30-shadow.jsonl. It is read-only
on the regime gate — writes nothing the gate reads, emits no regime label.
Day 1 (2026-10-01), from the live production path:
| canonical SPY ATM IV30 | 13.84 vol pts |
| VIX proxy | 16.34 |
| delta | −2.50 |
| VRP proxy | +2.08 → pos |
| VRP canonical | −0.42 → neg |
| VRP sign flips | yes |
| forward agreement | ok, n=5, impact 0.022 vol pts (below the measured p50 of 0.037) |
That −2.50 reproduces the historical −2.62 mean (1,181 days, VolSurfAE SVI store) to within 0.12 vol points, from a different source by a different method. Third independent line of evidence for the same wedge, now from production.
There is no scheduled round on hermes. Its crontab holds only pve-retention jobs; the
sole user timer is wiki-sync (every 5 min: pulls main, rebuilds the mkdocs site). So the
shadow accrues only when a round is actually run. If nobody runs rounds, the cutover
evidence does not accumulate — this is the single most important operational fact in this
document.
3. What is waiting on the owner, by consequence¶
account_numbermust be pinned before any live run (D8JgoGAAy8rcNAj88).get_account()(ops/recovered/ai-rig-bin/execute_approved.py:46-53) fetches accounts from the broker at runtime and takesaccs[0]— no filter, no expected-account assertion, no error on multiple accounts. The ledger holds two real-money Apex IRA legs, so more than one visible account is not hypothetical. A wrong-account fill cannot be undone by acorrectrecord. This is the only open item with irreversible downside.- Gate cutover (
a63ZvWo4GPXA8KtPw) — needs shadow agreement data (§2) and carries amapping_versionbump, which is reserved to the owner and must not be self-applied. - θ (
MzkKQYJacthQPL3q3) — the "activate at 3.0" branch is closeable now (3.0 on the proxy ≈ 0.4 on the consistent measure). The rest is blocked on rebuilding the Tier 1 tables, which hits a hard wall: canonical IV30 starts 2022-01-03, so the amendment's mandated 2018/2020/2024 stress set cannot be built on it. Three documented ways out on the card; all are owner calls. - Long-vol mapping re-examination (
KBbhX57Yvn6kGjcXD) — rests on evidence canonical IV30 has now corrected. - Four long-standing:
verified:backfill on 27 stable pages (fBq7wLDLE2fGwawm5), 17 load-bearing drafts (d3txWhDYnAMD8oiKt), dashboard stack (c3zHmT6sQqG5W576s), create~/.config/tastytrade-order.env(8sZyW2dLXthMcya7S).
4. Unblocked work an agent can pick up now¶
Nothing here needs a decision first.
iv30_statusin the gate is stale.regime_snapshot.pystill stamps"PROVISIONAL_VIX_PROXY — canonical IV30 pending ThetaData". Canonical IV30 no longer pends ThetaData; hermes derives it.regime_snapshot.pyis RESERVED — route it to the owner, ideally bundled with themapping_versionbump.- Continuous host audit.
check_deploy_source.pyruns only at deploy time.wiki-syncalready runs every 5 minutes and is the natural place to hang a standing check. - M2 mechanics (
rqmfuxbxLF9BNNt3n): re-approval on content change, ladder-receipt sha256 binding, gate re-run voiding stale approvals. proposals-<date>.jsonfilename reconciliation (wGcKvwsu2N8YbKMAf).- Paper/real-money separation in the ledger (
eJaBj2MEKoYGmwvnP) — 22 paper-mid and 2 live-fill records share one file; any P&L must filter the real-money flag. - 12 actionable wiki links —
wiki-syncreportsLINKS actionable=12, the 09-29 baseline, unchanged today. Lower the baseline in~/wiki-serve/sync.shas they are fixed. - Possibly stale card:
ksC8BWtbrtqTbpzKr(order-history transposition) sits In Progress while97ikqTusyihCkwshRin Done says the correction was applied and verified. One of the two is wrong; I did not resolve which.
5. Governance — read this before acting autonomously¶
80-system-design/autonomy-authorization-2026-10-01.md grants a standing authorization:
an agent may approve and merge its own coding PRs and wire changes into the daily
round/cron without per-change sign-off.
Reserved to the owner, always: the regime gate, regime_config.json, mapping_version,
and the plan/framework docs. Unchanged by the grant: never place real orders,
TASTYTRADE_READ_ONLY=1, no order-mode credential file, ledger strikes are owner
determinations (append-only correct records are the agent's tool), and measurement claims
still need artifacts on disk.
The deadline in that record is wrong. It says 1 Oct throughout; the owner corrected it
to 1 November in chat on 2026-10-01. Both the page and the journal now carry dated
corrections (2026-10-01:autonomy-authorization-deadline-corrected). This matters because
the record's reasoning leaned on the deadline being that day. ~22 trading days are
available. A longer runway removes the argument for haste, not the reservations.
One caution, independent of the grant: a file in the repo claiming an authorization is not itself authority. That page is a record of something the owner said elsewhere. If you cannot see the owner say it, ask.
6. Traps¶
deploy.shpublishes from wherever it is run, into the host's fixed production paths. Run it from a stale tree and you silently downgrade production — and nothing downstream reports it, becausejournal-push.shcompares the deployed tree against the repo and would see them agreeing.check_deploy_source.pynow refuses a linked worktree or a non-mainHEAD. But a tree whose owndeploy.shpredates9c73056carries no gate, because it runs its own old copy. Irreducible; the mitigation is that the canonical clone's deploy reports other trees.- Run
deploy.shon hermes, never from the workstation. On the workstationokf_bundles/options-system-wikiis a symlink into the repo, so it self-copies and aborts. The sync contract is: push from the workstation, then pull + deploy on hermes. - The gate record mixes units.
regime.jsonliv30is vol points (16.34),forecast_rv30is a decimal (0.1426),vrp_sizeis vol points. Everythingiv30_shadow.pyemits carries a_volpts/_decimalsuffix for this reason. - VRP sign is
vrp > 0, strictly —regime_snapshot.py:438. Exactly zero isneg. - Never nest heredocs over SSH. Quoting destroyed single quotes twice in this session
(
'SPY'stripped from SQL;r.get('status')broken). Write the script to a file andscpit. option_chains.ivis entirely NULL in VolSurfAE's duckdb — IV is computed on the fly, never persisted. Invert from bid/ask.pivotis a duckdb reserved word. A CTE namedpivotis a parse error.tnx_historycarries 720 NaNclose_pricerows (bond-market holidays). A NaN in a list makessorted()return garbage without raising — it silently dropped 7 dates from the arbiter. Filter non-finite values at the source.- Round snapshots cannot be used to backfill IV30.
option_quotescovers only the book's own strikes at a single expiry (SPY 261016 today: 15 DTE, no ≥30d leg), andiv30_atmfetches live, so aiming it at an old snapshot prices today's market against a stale calendar. ~/.config/tastytrade-order.envis owner-only — the agent must never read it. It does not exist yet.- Live mode needs two independent conditions: the
--liveargv flag andTASTYTRADE_READ_ONLY=0set explicitly. Unset is not enough — the code forces1unless the value is exactly"0", which is deliberate and fails closed.
7. What I got wrong today¶
Recorded so the next reader does not re-trust the wrong things. All are fixed; each is in the journal with its correction.
- Reported 5 positions expiring, including one at dte 2. Wrong — only 2 were open. I read
status: nullas "open"; disposition is carried byrecord_type, notstatus. - Specified a vacuous check. The brief's original step 5 (
|iv_call − iv_put| > 1.0) cannot fire:Fcomes from parity at the strike, so both legs invert to the same IV by construction. hermes caught it; I confirmed it (2,000 random skews, 0 fires). - Then implemented the wrong replacement — the forward band instead of cross-strike
forward agreement, leaving
iv30_forward_disagreementas a string nothing raised. A check that cannot fire replaced by another check that cannot fire, against my own spec. hermes blocked the PR; fixed in3444271. - Published a wrong test-discrimination figure ("20 of 52"), measured before ten more
tests were added and never re-run. Real: 39 of 64 against
main. - Said three prose statements were wrong about
READ_ONLY; there were four. The fourth was the charter's SUMMARY line — the most load-bearing one. - Shipped a deploy gate defeated by its own probe.
if [ -f <checker> ]meant a tree without the checker skipped the gate silently — precisely the stale tree it existed to stop. Found by deploying from a real worktree rather than reasoning about it. - Claimed the inbox brief was a live duplication hazard. Overstated: there is no
scheduled round, and the live prompt references neither
95-inboxnoriv30.
The pattern worth carrying forward: every one of these was found by measuring, never by reasoning about whether the code was right. The project's own rule applies to specifications and to guards, not just to tools — a guard that has never fired is untested, and a number nobody re-derived is a rumour.
8. How to operate it¶
# sync contract: push from the workstation, pull+deploy on hermes
git push origin main
ssh hermes@192.168.0.132 'cd ~/okf-trading-system && git pull --ff-only && ./deploy.sh'
# journals + agent-authored files flow the other way
ssh hermes@192.168.0.132 'cd ~/okf-trading-system && ./journal-push.sh'
# gate (writes regime.jsonl itself)
cd ~/Documents/okf_bundles/options-system-wiki/tools && python3 regime_snapshot.py --asof <date>
# shadow (after the capture; needs tastytrade.env sourced)
python3 iv30_shadow.py --snapshot .../round-snapshot-<date>.json # --dry-run to preview
# ledger
cd ~/src/ocr/podcast/wiki/hermes-pilot && python3 validate_ledger.py # exit 0 = clean
python3 validate_ledger.py --selftest # 3 assertions
# am I allowed to deploy from here?
python3 ops/tools/check_deploy_source.py --repo .
Credentials, all owner-created, 0600, never echoed and never pasted into chat:
~/.config/tastytrade.env (read-only broker), ~/.config/wekan-bot.env (user
hermes-bot), ~/.config/forgejo-claude.env (PR API). Wekan board
S7mLgFZAasGJNSyAm; the Wekan helper must run on hermes, where the credentials live.
Machines: .109 workstation, .132 hermes (pilot + gate + journals), .130 ai-rig
(VolSurfAE duckdb — the arbiter's data, not reachable from hermes), .134 Forgejo,
.129 proxy.