-- change_requests: one row links project/workspace/(requirement|issue)/source+target -- branch with a review verdict + CI state + the external (Gitea) PR id. This is -- the server-side merge gate: an agent opens a reviewable PR; a human approves -- via the web before merge_pull_request can succeed. -- -- number is a per-project sequence (max(number)+1 within project_id), mirroring -- requirements/issues. Columns are appended in physical order; sqlc SELECT/RETURNING -- column order must match this order (sqlc 列序约定,见 migrations/0012 comment)。 CREATE TABLE change_requests ( id UUID PRIMARY KEY, project_id UUID NOT NULL REFERENCES projects(id) ON DELETE CASCADE, workspace_id UUID NOT NULL REFERENCES workspaces(id) ON DELETE CASCADE, requirement_id UUID REFERENCES requirements(id) ON DELETE SET NULL, issue_id UUID REFERENCES issues(id) ON DELETE SET NULL, number INT NOT NULL, title TEXT NOT NULL, description TEXT NOT NULL DEFAULT '', source_branch TEXT NOT NULL, target_branch TEXT NOT NULL, state TEXT NOT NULL DEFAULT 'open' CHECK (state IN ('open','merged','closed')), review_verdict TEXT NOT NULL DEFAULT 'pending' CHECK (review_verdict IN ('pending','approved','changes_requested','rejected')), ci_state TEXT NOT NULL DEFAULT 'unknown' CHECK (ci_state IN ('unknown','pending','success','failure')), provider TEXT NOT NULL DEFAULT 'gitea', external_id BIGINT, external_url TEXT NOT NULL DEFAULT '', merge_commit_sha TEXT NOT NULL DEFAULT '', reviewed_by UUID REFERENCES users(id) ON DELETE SET NULL, reviewed_at TIMESTAMPTZ, created_by UUID NOT NULL REFERENCES users(id) ON DELETE RESTRICT, merged_at TIMESTAMPTZ, created_at TIMESTAMPTZ NOT NULL DEFAULT now(), updated_at TIMESTAMPTZ NOT NULL DEFAULT now(), UNIQUE (project_id, number) ); CREATE INDEX idx_change_requests_workspace ON change_requests(workspace_id); CREATE INDEX idx_change_requests_open ON change_requests(workspace_id) WHERE state = 'open';