diff --git a/dashboard/storage/data/backtest.db b/dashboard/storage/data/backtest.db index 722763a..649c519 100644 Binary files a/dashboard/storage/data/backtest.db and b/dashboard/storage/data/backtest.db differ diff --git a/docs/superpowers/plans/2026-07-15-agent-strategy-persistence.md b/docs/superpowers/plans/2026-07-15-agent-strategy-persistence.md index ca08b82..6a3d7bf 100644 --- a/docs/superpowers/plans/2026-07-15-agent-strategy-persistence.md +++ b/docs/superpowers/plans/2026-07-15-agent-strategy-persistence.md @@ -2216,10 +2216,12 @@ Expected: no output (conftest isolates `DATABASE_PATH`; if the file shows as mod `capsys` proves the factory emitted something; it does not prove prod will show it. Prove that against the real server, since the whole fail-visible mitigation rests on it: ```bash -timeout 10 ~/atl-venv/bin/python -m uvicorn dashboard.backend.app:app --port 8123 2>&1 | grep "backend:" +PYTHONUNBUFFERED=1 timeout 10 ~/atl-venv/bin/python -m uvicorn dashboard.backend.app:app --port 8123 2>&1 | grep "backend:" ``` -Expected: four ` backend: sqlite (ephemeral on Render)` lines in the output (SQLite locally, since `CONTENT_DATABASE_URL` is unset). If nothing matches, someone converted a `print()` back into `logger.info()` and the mitigation is dead — that is a blocking regression, not a nit. (This is a manual check, not a test: a pytest that reconfigures global logging to simulate uvicorn would corrupt the rest of the session.) +Expected: four ` backend: sqlite (ephemeral on Render)` lines (SQLite locally, since `CONTENT_DATABASE_URL` is unset). If nothing matches, someone converted a `print()` back into `logger.info()` and the mitigation is dead — a blocking regression, not a nit. + +**`PYTHONUNBUFFERED=1` is load-bearing here — do not drop it.** The factory `print()`s run at import time; piped to `grep`, Python's stdout is *block*-buffered (a TTY would be line-buffered), so those four short lines sit in the buffer and `timeout`'s SIGTERM discards them before they flush — **zero matches on perfectly healthy code**, a false alarm indistinguishable from the regression above. (uvicorn's own "Application startup complete" still shows, because that is its logger writing to stderr — which is what makes the false alarm so convincing.) The env var forces an unbuffered flush, and it is *also* how prod shows these lines at all: `render.yaml` sets `PYTHONUNBUFFERED: true`, so this check reproduces the prod condition instead of a misleading local one. (This is a manual check, not a test: a pytest that reconfigures global logging to simulate uvicorn would corrupt the rest of the session.) - [ ] **Step 6: Confirm CI is green *with the live tier actually running* — this is the gate** diff --git a/render.yaml b/render.yaml index 4f1c4b9..471eddd 100644 --- a/render.yaml +++ b/render.yaml @@ -29,6 +29,12 @@ services: # CLAUDE.md "Prod deploy reality"). - key: CONTENT_DATABASE_URL sync: false + # Durable Postgres for user accounts + sessions (users, auth_sessions). + # Content is separate: CONTENT_DATABASE_URL. Documentation only, same as + # above -- set in the Render dashboard, not synced from this yaml. A fully + # durable deploy sets BOTH, pointed at the same Neon DB. + - key: USERS_DATABASE_URL + sync: false - key: DISCORD_BOT_API_SECRET sync: false - key: DISCORD_CLIENT_ID