Cut the backlog over from per-repo SQLite + backlog.jsonl files to a global Postgres database. The motivation was the web UI bug from a few days back (openDb caching a single _db globally) plus the wider friction of every project carrying its own .assist/backlog.db: switching repos in the web UI cross-read each other’s data, and there was no good way to look at “everything I’m working on” across projects. Postgres is overkill for the storage volume, but the connection is shared across every assist invocation in any repo, and getCurrentOrigin tags rows with the originating remote so per-repo queries still work.

The bulk of the change is a refactor — every loader/saver that used to read JSONL or hit better-sqlite3 now goes through a BacklogDb interface backed by a pg pool. Some _test files lost ~30% of their lines because the tests no longer need to set up a fresh on-disk SQLite per run; they go through createTestDb and reuse the schema. migrateLocalBacklog runs once per project on first invocation: backs up the existing .assist/backlog.db and backlog.jsonl, parses the JSONL, remaps item IDs so they don’t collide with already-migrated rows from other repos, and imports. After verifying the migration the jsonl file is gone from the tree.

One catch found right after rollout — backlog commands were hanging after printing their output. The pg pool’s idle connections and timers keep the Node event loop alive, so the process never exits cleanly. Fixed by switching the CLI to parseAsync().finally(closeBacklogDb) so the pool drains on exit. Stuff that’s harder to fix once it bites: anything that holds the event loop open.