# SwingTrader — Fresh-Eyes Review To-Dos (2026-08-01)

Full triage completed 2026-08-01 with the user, "do it / don't care / ignore"
per item. Every "do it" item is now built and tested. See memory for the two
items that turned into bigger context (`project_account_value_and_trust`,
`project_broker_execution_exploration`).

## Resolved / decided — no further action

- [x] ~~Single point of failure on a USB drive~~ — **done**: moved to
      `/media/raid/rshare/SwingTrader`. Old USB copy archived at
      `/media/usb/claude/SwingTrader.moved-2026-08-01`.
- [x] ~~No version control~~ — **ignored**, user's call. Revisit if that ever
      feels insufficient.
- [x] ~~Commission/fee structure~~ — **don't care**. Not modeled in position
      sizing. Revisit if it starts to feel material.
- [x] ~~Confirm account value~~ — **$2,500 is an arbitrary trial number**;
      user could scale to $250,000 if the system proves reliable. Number
      stays as-is, but treat reliability work as higher-stakes than $2,500
      implies. See memory `project_account_value_and_trust`.
- [x] ~~Brokerage execution manual~~ — user is **open to exploring secure
      automated execution**, further than originally proposed. Not
      greenlit — needs its own dedicated conversation before any building.
      See memory `project_broker_execution_exploration`.

## Build queue — all built and tested, 2026-08-01

- [x] **Actions Required panel surfaces retrospective lessons.** Overdue
      exits, unenriched positions, and high-severity sector concentration now
      appear as `OVERDUE EXIT` / `NO STOP` / `SECTOR RISK` rows in the
      dashboard's top panel, not just buried in Retrospective further down.
- [x] **No-stop-loss alert.** `check_positions.py` fires a `NO STOP` alert
      (urgent priority) same-hour when an open position has no
      `stop_loss_cad` past `screen_criteria.json`'s
      `unenriched_position_grace_days` (5).
- [x] **Scan health + compliance check.** `verify_scan.py`, appended to the
      end of `run_daily_scan.sh`. Verifies today's `daily_snapshots/` file
      exists, is valid JSON, has all required fields, cleared
      `funnel_breadth`'s minimums, and applied any active lessons. ntfy
      alerts same-day on any failure.
- [x] **Watchlist live price tracking.** `fetch_prices.py` now also tracks
      `positions.json`'s watchlist and the latest scan's `signals.watchlist`,
      deduped against open positions.
- [x] **fetch_prices.py silent failure escalation.** Alerts via ntfy after 6
      consecutive failed quote fetches (~30 min) for the same ticker; clears
      on recovery.
- [x] **Sector-concentration enforcement in code.** `positions.json` entries
      now carry a `sector` field (enriched in Step 1b like `company`);
      `generate_retrospective.py` groups open positions by sector and always
      flags 2+, severity keyed off `active_mode`.
- [x] **Alert volume batching/threshold.** `check_positions.sh`'s truncation
      raised from 180 to ~1000 chars with an explicit "+more" marker instead
      of silent truncation; escalates to `urgent` priority when a stop-hit or
      no-stop alert is in the batch. Topic now read from `ntfy_alert.py`
      (single source) instead of a second hardcoded copy.
- [x] **learnings.md / CLAUDE.md consolidation.** `learnings.md` deleted;
      everything still relevant (file structure, daily workflow, operational
      gotchas — server.py hot-reload, CORS, cron timezone, `review_flags`
      schema) folded into `CLAUDE.md`. The stale duplicate "Key Rules" table
      (conflicted with the current aggressive-mode numbers) was dropped
      rather than merged.

New shared modules from this pass: `ntfy_alert.py` (single ntfy.sh sender,
used by `verify_scan.py`, `fetch_prices.py`, `generate_retrospective.py`) and
`verify_scan.py` itself. `screen_criteria.json` gained
`unenriched_position_grace_days` as the single source for that threshold,
read by both `check_positions.py` and `generate_retrospective.py`.
