On the LIVE entry path, the exposure/spend/position caps are alarms, not brakesfast_reserve does a bare INSERT and evaluates no caps, and the post-check that runs after it only increments a Telegram counter. Nothing cancels, unwinds, or blocks the order. The regression test that asserts otherwise had not compiled in months, so it never ran and nothing said so. Discovered 2026-07-09 while repairing the db-test suite. Pre-existing bug; low current exposure; fix proposed and awaiting Andras (babylon #1172).

Caps do NOT stop a live order

total_exposure_cap_usd, daily_spend_cap_usd, max_open_positions, max_copies_per_event are enforced synchronously only in reserve() — the DRY path, where no money moves. On the live path they run in a spawned post-check that only records a digest counter. Exactly backwards: the money path has no brake, the no-money path has the brake.

The Bug

  • The live entry path calls fast_reserve (execute.rs:125) — a bare INSERT that evaluates no caps.
  • evaluate_caps_post (execute.rs:133) runs AFTER the reserve, inside a tokio::spawn, concurrently with place_buy.
  • On a cap breach it only calls agg.record(Category::CapSkip, &spec.wallet_id, None) — a Telegram digest counter. Nothing cancels, unwinds, or blocks. Signing and submission proceed regardless.
  • So on live, all four caps are ALARMS, not BRAKES.
  • They are enforced synchronously — but only in reserve(), the DRY path, where no money moves.

Root cause: fast_reserve replaced reserve() on the live path for latency (see pmv2-entry-config-cache-design-2026-07-09). The cap evaluation went with it into a spawned post-check, and the spawn made it advisory. The DRY path kept the synchronous reserve() with real caps — so the guardrail ended up on the wrong path.

Why It Hid — a test that cannot compile is not protecting you

crates/position_manager/tests/mode_control_ledger.rs::live_cap_event_breach asserts ExecOutcome::Skipped("cap:event"). It is precisely the regression test for this bug. It never ran:

  • That test file had not compiled since PositionManager::new gained an agg parameter.
  • consumer_ack.rs and ops_commands.rs were dead the same way (the latter referenced Command::Enable / Command::Disable, removed by a contracts re-pin).
  • cargo test --features db-tests failed with 7 compile errors on main.

The durable lesson

A test that cannot compile is not protecting you, and nothing tells you. Unit tests were green (213 passing) the whole time; only the db-tests — the ones that touch the money path — were dead. CI does not run them (they need Docker / testcontainers), so green CI meant nothing here. A dead regression test is worse than no test: it reads as coverage.

For Agents

Same failure class as pmv2-sqlx-runtime-type-decode-bug-db-tests-2026-07-02: the money path is only exercised by the feature=db-tests testcontainers suite, which offline/unit tests and CI do not run. When a db-test file won’t compile, treat it as an outage of that guardrail, not a nuisance. Wire --features db-tests (or per---test) into CI.

Current Exposure

Low. Caps sit at 20,000 versus wallets holding $100–235. It is a missing guardrail, not an active loss — the caps are nowhere near binding at current bankroll. This is why the fix is queued rather than hot-patched.

The Fix (proposed, awaiting Andras — babylon #1172)

Fold the cap conditions into the new guarded reserve INSERT — the CTE that already gates the INSERT on the DB’s own mode / breaker_tripped state at zero extra round-trips (from the config-cache work). The caps become additional gate conditions on that same INSERT, so a breach rejects the reserve synchronously before any signing.

Do NOT revert the live path to reserve()

Reverting to reserve() pays BEGIN + SELECT FOR UPDATE + serial SUM queries across a Zurich→Dublin cross-region hop (~183ms per round-trip) — exactly the latency the config-cache work just removed. The right move is to add the cap gates to the round-trip we already pay (the INSERT), not to bring back the multi-query transaction. See Key architectural idea — move the authority check to a round-trip you already pay.