fix(ci): cap test SQLAlchemy below 2.1 — pg-migrations broke on the new default driver - #3015
Conversation
…ew default driver SQLAlchemy 2.1.0 (released 2026-09-24) resolves a bare postgresql:// URL to the psycopg (v3) driver. tests/requirements-test.txt carried an uncapped sqlalchemy>=2.0.0, so every run since resolved 2.1.0 and the pg-migrations job's alembic upgrade died with ModuleNotFoundError: No module named 'psycopg'. The backend image pins 2.0.36 + psycopg2-binary, so production was never affected; CI was running a stack prod never does. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
/review ReportBranch: Execution coverage
Fix mutation: I reproduced the
Critical findingsNone. Informational findings[I1] Test gap: pull_request:
paths:
- 'src/backend/migrations/**'
- 'src/backend/db/**'
- 'src/backend/alembic.ini'
- '.github/workflows/pg-migrations.yml'
[I2] The production path still relies on SQLAlchemy's default driver for a bare
Clean categories
Summary
|
vybe
left a comment
There was a problem hiding this comment.
merge-train: validated (lane A, one-line test-env cap; green incl. regression diff; #3020's green pg-migrations run carries this cap). Merged alone ahead of the train because every migration-bearing PR's pg-migrations/schema-parity is red on SQLAlchemy 2.1 until it lands.
…nity-enterprise#705) Create-time kind: agent (default) | deployment, on POST /api/agents and MCP create_agent. An explicit source_mode always wins. An agent gets a working branch + auto_sync_enabled + freeze-on-sync- failure, but only when the Abilityai#2107 push probe says its token can push to that repo. A deployment, an ephemeral ghost, a tokenless create, a refused or unverifiable probe all stay pull-only, with the reason on the create response's git_mode (never on the /ws broadcast). A template someone else owns therefore never receives an agent's branches (the ent#162 class); Cornelius, built from a shared public upstream, is pinned pull-only. Fork-to-own gets the trio. Existing agents are not flipped. Operator runbook for migrating a live agent: docs/migrations/AGENT_WORKING_BRANCH_DEFAULT_2026-09.md. Stacked on Abilityai#3016, Abilityai#3017, Abilityai#3018 (+Abilityai#3015): merges only after them. Related to Abilityai/trinity-enterprise#705 Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…rise#703) (#3021) * feat(git-sync): the container pulls origin on its own (trinity-enterprise#703) Invariant G3: human and fleet work reaches the agent within a bound. Nothing inside the container ever pulled; the 2026-09-24 audit found agents up to 31 commits behind. - agent server: a pull loop beside the push loop, gated per cycle on the owner's pull_sync_enabled (read live, GIT_SYNC_PULL fallback), interval GIT_SYNC_PULL_INTERVAL_SECONDS (defaults to the push one). Under _REPO_LOCK, never while an execution runs (checked again right before the tree is touched). Fast-forward, or rebase aborted on conflict. Uncommitted edits are stashed explicitly and a pull that collides with them is undone - not --autostash, which strands them in the stash while reporting success. - pull_sync_enabled + last_pull_at/_status/behind_after_pull on both migration tracks; backfill on only where auto-sync is on; new github agents get it at creation (source mode included), GIT_SYNC_PULL env derived from the DB flag alone at recreate. - GET/PUT /api/agents/{name}/git/pull-sync; sync-health persists the pull outcome (bounded); Settings -> Git sync gains the toggle. Stacked on #3020 (+#3015-#3018): merges after it. Related to Abilityai/trinity-enterprise#703 Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix(schema): keep the FK strip working on agent_git_config for PostgreSQL (trinity-enterprise#703) The inline comment on `pull_sync_enabled` sat between the comma and the FOREIGN KEY clause. `_PG_TABLE_SUBS` strips that clause only when it directly follows the comma, so the clause survived without its REFERENCES and PostgreSQL rejected the table ("syntax error at or near ')'"), failing 18 requires_postgres tests in schema-parity. The comment moves above the column. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix(git-sync): pull cycle never strands local work, counts queued turns, brings main to working branches (trinity-enterprise#703) PR #3021 review: - _with_stash wraps every post-stash step: a git child that times out (run_registered raises TimeoutExpired) goes back to the pre-pull HEAD and re-applies the stash; when that is impossible the error says the edits are kept in `git stash`. - reset --hard's return code is checked. A failed undo stops with an error naming it instead of leaving UU files behind silently. - Both cycles refuse to run over unmerged paths. The push cycle checks before `git add -A`, which would stage conflict markers and push them to origin as a successful sync. - The execution gate counts register_pending entries (#2433), so a turn queued on the chat lock or the headless pool is busy, not idle. - The pull reaps stale lock litter first, as the push cycle does; a pull-only agent has no push cycle to do it. - sync-state gains last_pull_error streak fields: consecutive pull failures / skips and last_successful_pull_at. Ruling on the intent question: a trinity/* working branch only ever pulled itself, so human pushes to main never arrived (G3). The cycle now also merges origin/main (via _get_pull_branch) into the working branch — a merge, not a rebase, since the branch is already pushed; a conflict is aborted and recorded. Nine real-repo tests, all red before. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * feat(git-sync): persist pull health; renumber to 0080_pull_sync; docs + UI copy (trinity-enterprise#703) - Alembic 0076_pull_sync -> 0080_pull_sync <- 0079_telegram_group_context (one head, 81 revisions); SQLite entry re-appended after dev's. - The same migration pair adds agent_sync_state.last_pull_error, last_successful_pull_at, consecutive_pull_failures and consecutive_pull_skips, persisted by the sync-health poller (bounded, coerced; a success clears the error). ent#706/#707 read these, so they land here rather than as a second migration on the same table. - agent-runtime.md says three loops; the flow and requirement describe the main merge, the queued-turn gate, the unmerged-path refusal, what behind_after_pull measures, and that auto-sync agents already rebase in the push cycle. - Settings copy no longer hard-codes 15 minutes (GIT_SYNC_PULL_INTERVAL_SECONDS) and no longer claims the push cycle never touches the tree while the agent works. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(git-sync): pull records merge conflicts as conflicts; rebases keep merges (trinity-enterprise#703) PR #3021 re-review: - A conflict merging main was recorded as "Auto-merging <file>": git prints it on stdout with an empty stderr. Unmerged paths are read before the abort; the error is "diverged: merge conflict with main (<files>)", and a failed merge --abort is named. - `git rebase` flattened the merge the pull made into copies of main's commits; both cycles now rebase with --rebase-merges. - A failed strict ahead/behind count fails the pull instead of reading as up to date. - A timed-out step is reset to the pre-pull HEAD even with nothing stashed; a reset blocked by the killed child's index.lock says so. - "Never runs while the agent is working" is check-then-act: the copy and docs now say "never starts" and document the admission window. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(git-sync): pull-sync write is person-only; classify the agent's read #2996's route census (merged to dev) requires every new route to be classified. The agent's pull loop reads GET .../git/pull-sync with its own key each cycle (AGENT_CALLABLE); the PUT is a setting write, so it takes Depends(require_person) like the other #2996 settings. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(git-sync): the push and pull cycles share the repo lock without starving each other (#3021 review) The two background loops started together on one interval and took _REPO_LOCK non-blocking, so the loser skipped silently every tick and the effective pull bound could quietly double. Background cycles now wait up to GIT_SYNC_LOCK_WAIT_SECONDS (default 120 s) for the lock, and the pull loop's first tick is half an interval after the push loop's. Operator endpoints keep their immediate 409. The pull's reset --hard undo re-checks that no execution started meanwhile; if one did, the tree is left as it is (conflict markers block the next push and pull) instead of discarding the turn's writes. merge --abort runs only when MERGE_HEAD exists, so a merge that refused to start no longer records "There is no merge to abort". Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * merge-train: narrow the "never discards local work" claims to what _safe_to_reset guarantees (#3021) — mechanical, per the merge-train note on the PR The undo paths no longer reset over a registered execution, but writes outside the process registry (Files API, docker exec, web terminal) made during the integrate window are not protected, as the author's e6cb8b5 note concedes. Wording only: two git.py docstrings, the auto_sync.py comment, requirements/github.md and the GitSyncSettingsPanel.vue copy. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Co-authored-by: Andrii Pasternak <44377756+AndriiPasternak31@users.noreply.github.com> Co-authored-by: trinity-ability <309458136+trinity-ability@users.noreply.github.com>
Summary
postgresql://URL to the psycopg v3 driver instead of psycopg2.tests/requirements-test.txthad an uncappedsqlalchemy>=2.0.0, so CI started resolving 2.1.0.pg-migrationsfails atalembic upgrade headwithModuleNotFoundError: No module named 'psycopg'(seen on feat(skills): skill sets — assign a named slice of the library as a unit (ent#530) #3005, feat(workspace): suggestions — what you can do with this agent, and what is waiting (abilityai/trinity-enterprise#465) #3000, feat(workspace): the autonomy dial — what a companion may do unprompted (ent#641) #2984; dev's last green run used 2.0.54).sqlalchemy==2.0.36+psycopg2-binary, so production is unaffected. This caps the test env to<2.1so it matches the image again.Verification
Test Plan
pg-migrationsgreen on this PR (it triggers ontests/requirements-test.txt)schema-paritygreen🤖 Generated with Claude Code