From eeab8ef5bb2b60b6e4351b001c1888f350866d2a Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 31 Aug 2026 14:44:16 +0000 Subject: [PATCH] Survive the console this will actually be run from MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The report prints an arrow between the old and new word counts, and it prints the memories themselves, which are model-written prose. A Windows console defaults to cp1252 and cannot encode either, so the run dies on UnicodeEncodeError partway through — after some memories have been rewritten and committed, which is the worst place to stop. STATUS already carries the same warning for tools/dbmeter.py. stdout is reconfigured to UTF-8 with errors="replace" instead, so the report degrades a character at a time rather than failing. The usage notes were also written for a POSIX shell, and this project is developed in PowerShell, where `VAR=x command` is not a thing. Both docs now give the PowerShell form first, via Read-Host so the Neon URL and the secret stay out of the history file, and name the venv's Python. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01Tqgupw5CZGjSZrUTNUd4fW --- backend/tools/rewrite_memories.py | 21 ++++++++++++++++++--- plan/STATUS.md | 8 ++++++-- 2 files changed, 24 insertions(+), 5 deletions(-) diff --git a/backend/tools/rewrite_memories.py b/backend/tools/rewrite_memories.py index 98fad05..76d41d5 100644 --- a/backend/tools/rewrite_memories.py +++ b/backend/tools/rewrite_memories.py @@ -68,10 +68,18 @@ ask to have rewritten. `--email` restricts the run to the accounts you name and `--adventure` to single adventures; a dry run costs nothing and lists both, with the owner of each. Guests have no email and can only be reached by id. -Two environment variables reach that database from a checkout: +Two environment variables reach that database from a checkout. In PowerShell, +which is where this project is developed, they are set first and then persist +for the rest of the session: - AIDND_DATABASE_URL= \ - AIDND_SECRET_KEY= \ + $env:AIDND_DATABASE_URL = Read-Host 'Neon URL' + $env:AIDND_SECRET_KEY = Read-Host 'Secret key' + .venv\Scripts\python.exe -m tools.rewrite_memories --email you@example.com + +`Read-Host` keeps both values out of the PowerShell history file. On a POSIX +shell the same thing is one line: + + AIDND_DATABASE_URL=... AIDND_SECRET_KEY=... \ python -m tools.rewrite_memories --email you@example.com `AIDND_SECRET_KEY` is not optional there. Stored API keys are encrypted with it, @@ -308,5 +316,12 @@ if __name__ == "__main__": parser.add_argument("--api-key", help="override the owner's API key.") args = parser.parse_args() + # A Windows console defaults to cp1252, which cannot encode the arrow this + # prints, let alone whatever is in a story's prose. Ask for UTF-8 and + # replace what the terminal still cannot render, so a run never dies + # halfway through on an encoding error. + if hasattr(sys.stdout, "reconfigure"): + sys.stdout.reconfigure(encoding="utf-8", errors="replace") + sys.path.insert(0, str(Path(__file__).resolve().parent.parent)) raise SystemExit(asyncio.run(main(args))) diff --git a/plan/STATUS.md b/plan/STATUS.md index 1374dd1..0a5bb1f 100644 --- a/plan/STATUS.md +++ b/plan/STATUS.md @@ -145,10 +145,14 @@ people's stories and each adventure is summarized with its owner's key, so `--em a shell on Render — the image copies `backend/app` alone, so `tools/` is not on the box: ``` -AIDND_DATABASE_URL= AIDND_SECRET_KEY= \ - python -m tools.rewrite_memories --email you@example.com +$env:AIDND_DATABASE_URL = Read-Host 'Neon URL' # direct endpoint, not -pooler +$env:AIDND_SECRET_KEY = Read-Host 'Secret key' # the web service's value +.venv/Scripts/python.exe -m tools.rewrite_memories --email you@example.com ``` +`Read-Host` keeps both out of the PowerShell history file. Use the venv's Python: the +system one on this machine is 3.10 and has none of the dependencies. + `AIDND_SECRET_KEY` is not optional there: stored API keys are encrypted with it, and with the wrong one `decrypt_secret` returns "" and every adventure is reported as having no key — a run that looks fine and does nothing. Hand-written memories, and memories whose actions have been deleted, are left