Skip to content

Production-Readiness Sweep — 2026-05-03 ​

Snapshot of pm-bot production-readiness status as of commit fe880bc (post-X2.4 WebUI configurator), refreshed by the X2.5 final-closure sweep on 2026-05-03.

Purpose: single artefact an operator (or future agent) can read to answer "is the binary ready for live operation, what are the open known limitations, and where do I look next." Companion to the per-section production-readiness-checklist.md (operator pre-flight) and tech-debt-backlog.md (per-row history). This document is the summary; the other two are the operator manual and the engineering log.

1. Verdict ​

READY for sustained 24/7 production on any of the 5 active strategies (bucket-arb, directional, maker, maker-rebate, merge-arb), single- or multi-wallet, single- or multi-strategy-via- process-restart. All correctness invariants are test-covered, the operator tooling is feature-complete, and the open backlog is empty (deferred-roadmap rows excepted — those are gated on empirical production signals rather than further implementation).

Tier upgrade (X2.5, this sweep). The two-tier "MVP-capable" vs "full operator-tooling" framing introduced by the 2026-05-03 user-decision sweep is collapsed: the upper tier shipped end-to-end across X1 (TD-27 dashboard rebuild) → X2 (FE-1 multi-wallet + FE-2 SQLite strategy config + FE-5 budget predicate + X2.4 WebUI configurator) → X3 (TD-2/TD-3/TD-4 strategy bug-fix bundle) → X4 (TD-5 stress-test re-port) → X5 (TD-7 paired maker-rebate emission) → X6 (cleanup batch — Headless MetricsTick / OrderClient struct migration / //! docs full coverage). The original lower-tier scope (single-strategy / single-wallet via .env, TUI primary, dashboard wallet-explorer + /local route as observability) is still fully supported as the legacy path — the new selector env vars (BOT_WALLET_LABEL, BOT_STRATEGY_LABEL) are semantic-Optional and unset ⇒ trading hot path bit-identical to pre-X2 behaviour.

TierScopeStatus
Sustained production-ready (collapsed from prior two tiers)Single- or multi-wallet, single- or multi-strategy-via-process-restart, TUI + Vue 3 SPA dashboard with cancel UI / risk widgets / configurator, encrypted wallets store + plaintext strategy-config store, FE-5 budget predicate, paired maker-rebate emission, alerts engine, journal retentionREADY 2026-05-03 (X2.5)

Open items list — empty. The implementation queue in tech-debt-backlog.md holds zero rows for the first time since the file was created. The active backlog reduces to the deferred-to-roadmap set (FE-3 multi-strategy per process, FE-4 declarative Condition rule engine, FE-5 reinvestment toggle) — each gated on empirical signals from a production cycle rather than further design or implementation work.

History trace (rows that stood open before X2.5 and shipped during the X1+X2+X3+X4+X5+X6 chain):

  • TD-2 / TD-3 / TD-4 — RESOLVED 2026-05-03 (X3 strategy bug-fix bundle, commit 02a6fb0).
  • TD-5 — RESOLVED 2026-05-03 (X4 stress-test re-port, commit f6e5fa9; +14 lib tests, 966 → 980).
  • TD-7 — RESOLVED 2026-05-03 (X5.1..X5.4 paired maker-rebate emission; ADR-011 + paired runbook + sprint summary; +33 lib tests, 980 → 1014).
  • TD-27 — RESOLVED 2026-05-03 (X1.0..X1.5b dashboard rebuild + X2.4 configurator surface; ADRs 012/013/014/015 §D8/D9; 12 → 28 pm-dashboard integration tests).
  • FE-1 / FE-2 / FE-5 — RESOLVED 2026-05-03 (X2.2..X2.3 multi-wallet store + SQLite strategy config + budget predicate; ADR-015; +57 lib tests, 1014 → 1071; +27 pm-cli integration tests).
  • Headless MetricsTick ingest / Phase 5.6.2 OrderClient struct migration / //! docs full coverage — RESOLVED 2026-05-03 (X6 cleanup batch, commit a611c35; supplemented by N5/N6 polish in e53b73b).

The deferred-to-roadmap rows remain unchanged from the user-decision sweep:

  • FE-3 multi-strategy per process — picks up after operators exercise FE-1/FE-2/FE-5 in production for one cycle. Architecture ADR will draw on the archived pm-orchestrator design (multi-strategy execution shape).
  • FE-4 declarative Condition rule engine — picks up after FE-2 + WebUI configurator are battle-tested. Pre-existing implementation in archived pm-orchestrator; salvage path is port + operator validation pass, no design work needed up-front.
  • FE-5 reinvestment toggle — backlog only; defer until empirical data from base FE-5 in production for at least one cycle.

The 2026-05-03 user-decision sweep removed never-requested items (TD-15 / TD-16 / TD-25 / TD-26 / testnet row / Telegram + SMTP backends — earlier cleanup commit 9fe2e5f) and bundled four Tier-3 polish rows under TD-27 (closed in X1). Nothing in the deferred-to-roadmap set blocks production.

2. Build / test status ​

Workspace at commit fe880bc (X2.4 — WebUI configurator):

CheckStatusNotes
cargo check --workspacegreen (cached)6 crates: pm-common, pm-cli, pm-sdk, pm-bot, pm-bot-events, pm-dashboard
cargo build --workspace --releasegreenrelease binary ~19 MB
cargo clippy -p pm-bot -p pm-sdk -p pm-bot-events --lib0 warningsTD-23 swept the prior 43-warning batch in N4 polish; preserved through X1+X2+X3+X4+X5+X6
cargo test -p pm-bot --lib1071 passed / 0 failed / 1 ignoredX2.5 baseline (899 → 1071: +14 X4 + +33 X5 + +57 X2.2 + +68 across X3/X6/N4..N7)
cargo test -p pm-cli --tests27 passed / 0 failedX2.3 introduced the suite covering all 7 pm-cli strategy subcommands + audit invariants
cargo test -p pm-dashboard --tests28 passed / 0 failedX2.4 grew the suite from 12 to 28 (FE-1 + FE-2 REST endpoints + FE-5 422 reject path coverage)
cargo test -p pm-sdk --lib18 passed / 0 failedunchanged across the X-chain
cargo test -p pm-bot --tests1066+ passed / 0 failed / 16 ignoredload tests + smoke harnesses (counts unchanged from N7 baseline)
cargo doc --workspace --no-depscleanTD-24 fixed rtds_probe.rs HTML-tag rustdoc warning in N5; the //! docs full-coverage row in X6 closed remaining gaps

The 1 ignored lib test is intentional (slow / network-bound); the 16 ignored integration tests are smoke harnesses gated behind operator flags (--smoke-rtds, --smoke-webhook).

Workspace test total: 1144 (1071 pm-bot lib + 27 pm-cli + 28 pm-dashboard + 18 pm-sdk lib), all green; 0 clippy warnings; trading hot path bit-identical to pre-X2 (every test added in X2.2..X2.4 is additive against the new multi-wallet / config-store / configurator surface; the env path itself touches no production code on the hot path — confirmed by the 1014 → 1071 baseline preservation).

3. Operator handbook (entry-point) ​

NeedDoc
Pre-flight checklistproduction-readiness-checklist.md
Strategy / RTDS smoke proceduresmoke-test-runbook.md
Dashboard smoke procedure (UI widgets, X1.5b)dashboard-smoke-runbook-2026-05-03.md
Multi-wallet smoke procedure (configurator surface, X2.5)multi-wallet-smoke-runbook-2026-05-03.md
Multi-wallet migration runbook (.env → SQLite, X2.5)multi-wallet-migration-runbook-2026-05-03.md
RTDS toxic-flow activationrtds-cutover-runbook.md
Local-Bot dashboard modelocal-dashboard-runbook.md
Paired maker-rebate activation (TD-7)paired-maker-rebate-runbook-2026-05-03.md
Alerts engine + custom rules / sinks (TD-12)alerts-2026-05-03.md
Journal retention / GC (TD-11)journal-retention-2026-05-03.md
DB / journal clean rewritedb-clean-rewrite-2026-05-03.md
Env var referenceenv-reference.md
Rate limits (CLOB, Gamma)rate-limits.md
Replay parity methodologyreplay-parity-methodology.md
Backlog triage / next itembacklog-triage-2026-05-03.md
Per-row TD historytech-debt-backlog.md
Worktree cleanup helperscripts/cleanup-worktrees.sh (TD-8 RESOLVED 2026-05-03)

ADR set:

ADRTopic
adr-006-archive-extraction.mdArchived crate set (12 → 6)
adr-007-pm-bot-modular-restructure.mdDomain / application / IO split
adr-008-config-split-per-strategy.mdPer-strategy config modules
adr-016-timezone-handling-policy.mdMidnight-to-midnight time policy
adr-010-order-client-trait-unified.mdOrder placement trait + dry-run adapter
adr-011-paired-maker-rebate-emission.mdTD-7 paired maker-rebate emission (Accepted 2026-05-03 X5.1; shipped X5.2..X5.4)
adr-012-pm-dashboard-redesign.mdTD-27 pm-dashboard redesign (backend + Vue 3 SPA split, finalized 2026-05-03 X1.0)
adr-013-dashboard-cancel-ui-invariants.mdDashboard cancel UI invariants (X1.5a — soft-delete + paranoid bulk gate)
adr-014-dashboard-risk-metrics.mdDashboard risk metrics lock-in (X1.5b — Sharpe / Sortino / max drawdown)
adr-015-multi-wallet-and-strategy-config.mdMulti-wallet (FE-1) + SQLite strategy config (FE-2) + budget predicate (FE-5) + WebUI configurator surface (X2.4); Accepted 2026-05-03 X2.1
merge-arb-strategy.mdmerge-arb v2 design + on-chain merge
phase-5-scanner-fsm-extraction.mdScanner / FSM extraction
pm-bot-dashboard-integration.mdADR-005 Local-Bot Mode
rtds-integration.mdRTDS integration + 12-question resolution
strategy-isolation-design.mdStrategy trait + Decision pipeline
webhook-signal-source.mdADR-003 webhook signal source

4. Deployment ​

Production binary path:

sh
cargo build --workspace --release
target/release/pm-bot --strategy <bucket-arb|directional|maker|maker-rebate|merge-arb> \
    --env env/.env.<preset>

Companion processes (optional):

sh
target/release/pm-dashboard           # web UI on :31337
target/release/pm-cli <subcommand>    # init / wrap / approve / redeem / cancel-all / sell-all

Docker ​

docker-compose.yml and docker-compose.prod.yml exist for the historical multi-service deployment, but the current 6-crate workspace does not require external services for trading. pm-bot runs as a single self-contained binary: SQLite for journal, no Valkey, no trading-api, no market-data daemon (those crates were archived 2026-05-02 — see ADR-006). Use Docker only if the operator wants the dashboard in a container.

5. Required env vars (fail-fast) ​

BotConfig::validate_required_env_or_panic enforces that every [REQUIRED] line in env/.env.example (112 lines) is set. Missing values abort startup with a single panic listing every missing key.

Strategy-conditional blocks are surfaced lazily after BOT_STRATEGY parses, so operators may need a second dry-run pass after picking a strategy:

BlockActivated by
BUCKET_ARB_*BOT_STRATEGY=bucket-arb
MAKER_REBATE_*BOT_STRATEGY=maker-rebate
DIRECTIONAL_*BOT_STRATEGY=directional
MAKER_*BOT_STRATEGY=maker
MERGE_ARB_*BOT_STRATEGY=merge-arb
WEBHOOK_*WEBHOOK_ENABLED=true
RTDS_*always required
BOT_LOCAL_API_*BOT_LOCAL_API_ENABLED=true (other 3 vars apply defaults rather than fail-fast — see ADR-005)

Public optional defaults (NOT in fail-fast list):

  • WEATHER_API_KEY — built-in public Weather Underground free-tier key
  • BUCKET_ARB_AUTOSELL, BOT_TOTAL_BUDGET, POLYGON_RPC_URL, WEBHOOK_IP_ALLOWLIST, MARKET_*_FILTER — semantic-Optional, None means feature off
  • BOT_LOCAL_API_* (Local-Bot Mode, ADR-005) — opt-in observability layer; BOT_LOCAL_API_ENABLED=false (default) ⇒ trading hot path bit-identical to pre-integration
  • BOT_WALLET_LABEL / BOT_STRATEGY_LABEL (multi-wallet selectors, ADR-015) — opt-in. Unset ⇒ legacy .env path bit-identical. When BOT_WALLET_LABEL is set, WALLETS_MASTER_PASSPHRASE MUST be set and non-empty (fail-fast at crates/pm-bot/src/main.rs:112-116). When BOTH selectors are set, INV-3 enforces that the strategy row's wallet_label equals BOT_WALLET_LABEL (fail-fast at crates/pm-bot/src/main.rs:210-228).
  • BOT_WALLETS_DB_PATH / BOT_CONFIG_DB_PATH (multi-wallet store paths, ADR-015) — semantic-Optional. Default ./wallets.db / ./config.db resolve relative to pm-bot's working directory. Recommended deployment override: /etc/pm-bot/wallets.db (mode 0600) and /etc/pm-bot/config.db (mode 0644).
  • MAKER_REBATE_PAIRED_ENABLED (TD-7 paired emission, ADR-011) — default false preserves Phase 1 single-side parity bit-for-bit. Activation runbook: paired-maker-rebate-runbook-2026-05-03.md.

6. Open known limitations ​

The implementation queue is empty as of X2.5 (2026-05-03). The active backlog reduces to the deferred-to-roadmap rows below — each gated on empirical signals from a production cycle, not on further design or implementation work.

Implementation queued — empty ​

The X1+X2+X3+X4+X5+X6 sprint chain shipped every previously-queued row. History trace lives in tech-debt-backlog.md "Resolved / obsolete (kept for traceability)" table — TD-2 / TD-3 / TD-4 / TD-5 / TD-7 / TD-27 / FE-1 / FE-2 / FE-5 / Headless MetricsTick / OrderClient struct migration / //! docs full coverage all carry RESOLVED rows with commit hashes.

Production-critical resolved within prior sweeps ​

  • TD-11 auto-prune retention — RESOLVED 2026-05-03. Auto-prune scheduler + pm-cli journal gc primitive shipped; see journal-retention-2026-05-03.md.
  • TD-12 alerts — RESOLVED 2026-05-03. Engine + LogSink baseline shipped; see alerts-2026-05-03.md.
  • TD-18 metrics_loop wiring — RESOLVED 2026-05-03; tokio::spawn next to local_api::serve confirmed live SSE 1Hz cadence.
  • TD-21 RTDS observability, TD-23 clippy sweep, TD-24 rustdoc HTML-tag — all RESOLVED in N3..N5 polish batch.
  • TD-7 paired maker-rebate emission — RESOLVED 2026-05-03 in X5.1..X5.4. ADR-011 + paired runbook (paired-maker-rebate-runbook-2026-05-03.md). Default MAKER_REBATE_PAIRED_ENABLED=false preserves single-side parity bit-for-bit.
  • TD-27 dashboard UI redesign — RESOLVED 2026-05-03 in X1.0..X1.5b + X2.4. ADRs 012 / 013 / 014 + ADR-015 §D8/D9. 28 pm-dashboard integration tests (was 12 pre-X2.4). Dashboard smoke runbook (dashboard-smoke-runbook-2026-05-03.md) for trading widgets and multi-wallet smoke runbook (multi-wallet-smoke-runbook-2026-05-03.md) for the configurator surface.
  • FE-1 / FE-2 / FE-5 — RESOLVED 2026-05-03 in X2.2..X2.3. ADR-015. Migration runbook (multi-wallet-migration-runbook-2026-05-03.md) documents the .env → wallets.db + config.db path. 27 pm-cli integration tests.

Deferred to roadmap with documented architecture ​

  • FE-3 multi-strategy per process — gated on operators exercising FE-1 + FE-2 + WebUI configurator in production for one cycle. Architecture: parent strategy manager + per-strategy child processes
    • wallet selection. Salvage path documented from archived pm-orchestrator.
  • FE-4 declarative Condition rule engine — gated on FE-2 SQLite config + WebUI configurator being battle-tested. Pre-existing implementation in archived pm-orchestrator (25+ leaf-condition enum); salvage path is port + operator validation pass, no design work needed up-front.
  • FE-5 reinvestment toggle — backlog only; base FE-5 budget-limit predicate shipped. Defer until empirical data from base FE-5 in production for at least one cycle.

Removed in cleanup (never user-scoped) ​

TD-15 (CSV / Parquet export), TD-16 (multi-wallet aggregation as separate feature — subsumed by FE-1, now RESOLVED), TD-25 (Telegram backend), TD-26 (SMTP backend), testnet validation row, Telegram / SMTP backends — all deleted in cleanup commit 9fe2e5f. Listed here for completeness only.

7. Operator escalation procedure ​

The alert engine (TD-12) provides structured tracing lines for critical events via LogSink. Escalation flow:

  1. Soft alert (P&L drift, fill-rate degradation): operator monitors pm-dashboard /local route (when BOT_LOCAL_API_ENABLED=true) or the TUI directly. The drawdown_threshold and posts_err_spike rules surface as warn! log lines when their thresholds trip.
  2. Hard alert (emergency stop, repeated rejection cluster): the emergency_stop rule emits an error! log line; the MetricsTick SSE stream emits is_emergency=true (Phase 7c schema). Operator polls or watches the /api/local/stream endpoint.
  3. On-chain alert (wallet drained, suspicious tx): out-of-band — block explorer / RPC monitoring.

The AlertSink trait is public; an operator who needs to fan alerts into an external system (e.g. log aggregator with paging) can implement it in a side crate / fork — see alerts-2026-05-03.md "Custom rules + sinks".

8. Rollback procedure ​

Trading is fully reversible via env restart — no schema migration, no on-chain state to roll back.

  1. Kill switch: pkill pm-bot (or systemd / supervisor stop).
  2. Cancel open orders: cargo run -p pm-cli -- cancel-all --private-key $KEY.
  3. Sell open positions (if needed): cargo run -p pm-cli -- sell-all --private-key $KEY (FOK at best bid).
  4. Redeem resolved positions: cargo run -p pm-cli -- redeem --all --private-key $KEY --rpc-url $RPC.
  5. Restart with safe defaults: re-launch with BUCKET_ARB_IMMEDIATE_FILL_ENABLED=false, RTDS_TOXIC_FLOW_ACTIVE_CANCEL_ENABLED=false, RTDS_TOXIC_FLOW_LOG_ONLY=true, WEBHOOK_ENABLED=false, BOT_BUDGET_PER_MARKET=5.

The journal SQLite (pm-bot.sqlite) is forward-compat across sessions — a restart creates a new bot_sessions row but does not disturb prior state. Hard reset: stop the binary + delete the SQLite file (operator-conscious — destroys session history).

9. Sign-off (X2.5 — final closure) ​

  • [x] Build green (cargo check --workspace).
  • [x] Tests baseline preserved and grown additively: 1071 pm-bot lib (1 ignored) + 27 pm-cli integration + 28 pm-dashboard integration + 18 pm-sdk lib = 1144 tests workspace-wide, all green. Trading hot path bit-identical (the 1014 → 1071 lib delta is purely additive against the new multi-wallet / config-store / configurator surface).
  • [x] Clippy clean (0 warnings on pm-bot, pm-sdk, pm-bot-events).
  • [x] Tier 1 sweep landed (TD-1 + TD-17 OBSOLETE marks; TD-6 + TD-8 RESOLVED; scripts/cleanup-worktrees.sh shipped + smoke-tested).
  • [x] Tier 2 documentation landed (FSD bucket-arbitrage immediate-fill block extended with TD-2 / TD-3 / TD-4 operator-facing limitations; production-readiness checklist refreshed with current numbers).
  • [x] Tier 5 sweep doc (this file) created.
  • [x] Cleanup pass (post-Tier-3): never-requested rows removed (TD-15 / TD-16 / TD-25 / TD-26); TD-12 marked fully RESOLVED.
  • [x] Post-user-decision sweep (2026-05-03) — 5 rounds of AskUserQuestion consolidating every open and deferred row. Outcome
    • sprint sequencing recorded; coding unblocked.
  • [x] TD-27 X1.0 — ADR-012 landed (585 LOC, Accepted). Scope finalized via 4 AskUserQuestion rounds.
  • [x] X1 dashboard rebuild — RESOLVED 2026-05-03. X1.1 frontend scaffold (9d8ddc9) → X1.2 backend REST (b76c1a2) → X1.3 Pinia + SSE (cabe6c9) → X1.4a darkPreset + PnL chart + WalletView (4db95fb) → X1.4b chunks + Compare + persist + events + retire (47bb95a) → X1.5a cancel UI hardening + ADR-013 (305cd75) → X1.5b risk widgets + ADR-014 (21a853d).
  • [x] X2 multi-wallet + SQLite config — RESOLVED 2026-05-03. X2.1 ADR-015 (94bbbf5) → X2.2 FE-1 encrypted multi-wallet store (0f2978f) → X2.3 FE-2 SQLite strategy config + FE-5 budget predicate (33b0402) → X2.4 WebUI configurator (fe880bc) → X2.5 final closure docs (this revision).
  • [x] X3 strategy bug-fix bundle — RESOLVED 2026-05-03. TD-2 + TD-3
    • TD-4 shipped as a single bundle (02a6fb0).
  • [x] X4 stress-test re-port — RESOLVED 2026-05-03. TD-5 14 ST-0* invariants re-authored against BucketArbStrategy::on_ws_book hook
    • MockRepository (f6e5fa9).
  • [x] X5 paired maker-rebate emission — RESOLVED 2026-05-03. TD-7 ADR-011 + pure evaluator + state machine + runbook (4185085 → 184257c → 32cc2a6 → af105b3).
  • [x] X6 cleanup batch — RESOLVED 2026-05-03. Headless MetricsTick ingest + Phase 5.6.2 OrderClient struct migration + //! docs full coverage (a611c35 + N4..N6 polish from e53b73b).
  • [x] X2.5 final closure docs (this revision): multi-wallet-migration-runbook-2026-05-03.md (537 LOC) + multi-wallet-smoke-runbook-2026-05-03.md (28-probe smoke) + tech-debt-backlog rows for FE-1/FE-2/FE-5/ TD-7/TD-27 closed in the resolved table + this verdict block upgraded to READY for sustained 24/7 production.
  • [x] Implementation queue empty. First time since the file was created. Active backlog reduces to deferred-to-roadmap rows (FE-3 / FE-4 / FE-5 reinvestment toggle), each gated on empirical production signals.

End of sweep — workspace is production-ready.