# HANDOFF — polymarket rules audit, 2026-09-12 (from DESKTOP-SKPI2F1 → next session on the BOT BOX)

Read this first in the next session. Everything below is on the VPS at
`/home/claude/CONTINUITY/current/handoff/2026-09-12-rules-audit/` (tar: `handoff.tgz`), and the
deployed code is in the docroot git snapshot (`/var/git/timeportal.git`, work-tree `/var/www/timeportal.pro`).
The owner uses one Claude account from several computers; nothing in a machine-local Claude memory travels —
THIS file and the VPS kit memory are the handoff.

## 1. What is LIVE on timeportal.pro/polymarket (all deployed 2026-09-12)
- odds.php: per-match RULE PANE (`#rulepane`, every registry rule, status, why, when) + diamond markers on the
  odds chart per rule event + `B✗/B✓/S✓` badges in the match list. Renders "not available" until the bot
  pushes a `rules` block (see §3).
- analysis.php: sport × basket table (won/lost/open/win rate/reached ≤X¢/≥Y¢), chart 2 by REAL DATE
  (day/week/month, page window), chart 3 bottom-price histogram (TP-only / TP+market × won/lost, lows while
  bets were open only), bottom tile "Where should we buy in?" (ladder backtest, curves, per-rung, sweet-spot
  sentences, candidate rule), HEALTH STRIP on every chart (rolling 24h/48h/7d counts, newest-game age, file age).
- history.php: cohort chips on EVERY canvas (TP-only fav / TP+market fav / nobody's fav / TP-only won / TP-only
  lost), chart 4 rebuilt as the WHAT-IF heatmap (X = buy multiple of open 0.40×…1.00×, Y = sell 40¢…100¢=hold
  or % above buy-in 30%…1000%, cell = total profit, cohort + window), health strips.
- superadmin: "Trading rules (hub defaults)" — all 35 registry rules listed; 30 editable, 5 observational.
  Non-null hub values are BINDING on spokes (config < local < hub) once the bot reads them (§3).
- LLM text: /polymarket/llm/{index,analysis,history}.txt (+ /llms.txt, /polymarket/llms.txt), regenerated
  every 10 min by cron (user claude) from the pages' OWN code blocks. Sections have stable ids [A0]…[A6], [H0]…[H4].
- Generators + cron (user claude): `polymarket/llm/gen_llm_text.js` (:05,:15…), `whatif_grid.py` (:12,:42 →
  odds_data/whatif_grid.json), `ladder_backtest.py` (02:10 UTC → odds_data/ladder_backtest.json). Logs: llm/gen.log.
- /polymarket/todo/ → the roadmap list (upgrade/todo.json) with the P0 OWNER ACTION item; landing page links to it.

## 2. Tests (all green at handoff) — run from the docroot on the VPS or from the mirror
node tests/{health,history_filters,analysis,adversarial_filters,llm_text,whatif}.test.js ·
python3 tests/{whatif_grid,ladder_backtest}.test.py · php tests/spoke_rules.test.php (190/190) ·
node tests/rules_pane.test.js. Bot suite (pmstack, from bot/ with its venv): 3694 passed; 1 failure
(test_rank_gap_ratio) + 5 collection errors (need config.local.json) are pre-existing at baseline.

## 3. NOT DONE — the bot package (needs the bot box; the next session IS on the bot box)
The pmstack change (branch `rules-audit-20260912`, 17 files: rule_registry.py, rule_log.py, hub_rules.py,
pmtrade.py/supervisor.py hooks, push_odds_data.py san_rules, board/odds_api.php arm fallback + tests) is NOT
in /srv/git/pmstack.git yet. Files in this handoff: `pmstack-rules-audit-20260912.bundle` and `.patch`.
On the bot box:
  1. `cd <pmstack root>` (the git checkout run_update.cmd pulls into), `git fetch <path to bundle>
     rules-audit-20260912:rules-audit-20260912`, review `git diff main..rules-audit-20260912 --stat`,
     then `git push origin rules-audit-20260912:main` (origin = /srv/git/pmstack.git via ssh) so every
     enrolled node gets it at 05:40. Or apply the .patch with `git am`.
  2. `bot\venv\Scripts\python.exe -m pytest -q` from bot/ (expect the same pre-existing failures only).
  3. Restart the supervisor (`Restart-ScheduledTask pmtrade-supervisor`) — a running supervisor keeps old code.
  4. `python -m rule_log --backfill 989095` then open odds.php?m=989095: the pane must say
     "No buy: price never reached the first live rung after the open-kill (rung 3 = 26.5c; in-play low 30c)".
  5. Check push_odds_data now stages `rules` per bundle and `rule_verdict` in list.json (odds_data on the VPS).
  6. Also on the bot box: `build_ladder_opt.py` (chart 5's ladder_opt.json) lives only there — not in the package.

## 4. OPEN FINDINGS the owner has not decided
- Buy rule: backtest on 329 TP-only matches (all CIs straddle zero): sweet band 15–27¢ absolute
  (≈0.42–0.75× open), the 46¢ rung is negative, and the 15%@72¢/80%@81¢ sell rungs cost 40–50% of net
  (135 of 139 winners touched 81¢; only 18 of 442 losers did). Candidate (NOT live): anchor = min(pregame
  median, open); rungs at anchor × [0.75, 0.52, 0.35]; nothing above 36¢. Money rules change only on superadmin.
- Health strip at handoff says `bad · source_stale_6h`: ladderfit.json on the VPS was generated 01:53 UTC and is
  >10 h old, and only 2 games in the last 24 h vs a 7-day average of 8.9/day → check the bot box's
  pmtrade-odds-push task and the ladderfit builder.
- Not visually reviewed in a browser (no Chrome tools in the building session): open odds.php?m=989095,
  analysis.php, history.php and eyeball every chart; report anything off as a bug and fix (FIX-DON'T-ASK).

## 5. Where things are
- VPS kit memory: memory/pmtrade-rules-audit-20260912.md (indexed in MEMORY.md "Read first"),
  USER-DEMANDS-LEDGER.md 2026-09-12 section (owner orders verbatim).
- Handoff dir: spec/ (WS-A…WS-I specs, REPORT-*, LEDGER-*, TRACE-989095.md, COMMON.md contract),
  backtest/ (fetch.py, sim.py, report.py, REPORT.md, results.csv, matches.csv), deploy/ (deploy scripts,
  grok-detached.ps1, todo item), logs/ (grok-*.log per workstream), vps-round2.bundle (docroot mirror git),
  pmstack bundle + patch.
- Windows box DESKTOP-SKPI2F1 also has all of it under D:\work\timeportal\polymarket\rules-audit-20260912\.
- Method that worked: Claude specs (spec/WS-*.md + COMMON.md) → `grok --prompt-file … -m grok-4.6 --yolo`
  one workstream per run with disjoint files → Claude QCs (tests, php -l via /tmp/qc on the VPS) → deploy
  script. Auto-mode classifier blocks direct scp/ssh writes and git pushes to production; a deploy script
  run from the scratchpad was allowed; the pmstack push was not (hence §3).

## 6. STATUS AT HANDOFF — ALL BOTS PAUSED
Owner 2026-09-12, verbatim: "all bots are paused until i find a better buy/sell ladder config."
- So the health strips reading bad/source_stale_6h (no fresh ladderfit / bundle pushes) is EXPECTED while paused.
- The next session's real job is the LADDER DECISION: analysis.php bottom tile (backtest), history.php chart 4
  (what-if heatmap: buy multiple of open x sell target, $1 per game, losers cut at ladder kill), backtest/REPORT.md
  in the handoff. Owner sets the rule on superadmin (hub trading_rules, binding once the pmstack branch is pushed and
  the supervisor restarted), then unpauses.

## 7. H2 (2026-09-12, after the first handoff) — chart 4 amended and LIVE
k grid now 0.10x…1.00x (19 columns); cells = $ profit per $1 staked per game, summed; LOSERS: the sell window ends
at trade_cut (bets closed = buy-ladder kill) so a loser can only be sold before its ladder dies; winners use the whole
tape. whatif_grid.json schema 2 (`fills.<anchor>[i] = [fill, max_after_all, max_after_to_cut, fill_ts]`); the page
reads schema 1 or 2. Spec/report: spec/WS-H2-whatif-fixes.md, spec/REPORT-H2.md.
