Skip to content

Intake race: enforce one-active-run-per-issue with a DB constraint, not check-then-insert #9

@JeremySNR

Description

@JeremySNR

Severity: High — known limitation (AGENTS.md), filing so it's tracked and fixable

Problem

intake_and_plan checks for an active run in one session (orchestrator.py:175-180) and creates the run in a different session later (~orchestrator.py:190-257). foundry_runs.linear_issue_id deliberately has no unique constraint (db/models.py:88-90). Two simultaneous webhook deliveries for the same issue both pass the check and both create runs — two approvals, two dispatched agents, two PRs are possible.

The GitHub-events dedup set is in-memory and per-process (api/app.py:160), so it doesn't protect multi-worker deployments or restarts.

Suggested fix

  • Postgres: partial unique index UNIQUE (linear_issue_id) WHERE status IN (<active statuses>) via an Alembic migration; SQLite dev gets it via a filtered Index in create_all.
  • Flip intake to insert-first and catch IntegrityError, returning/attaching to the existing active run.
  • Add a test simulating duplicate intake (two sessions) asserting exactly one run survives.

This is also a prerequisite for ROADMAP #7 ("Unique constraint: one active run per issue, enforced in the DB") — it can be pulled forward cheaply.

Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions