feat(db): add goose 00037 task_run_manifests

Persist typed RunManifest bytes and SHA per run, and allow a finalizing status so U8 can freeze a unique terminal without sharing env databases.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
weichen
2026-09-15 02:05:33 +00:00
co-authored by Cursor
parent 2234af476a
commit eb75f855a5
3 changed files with 67 additions and 2 deletions
@@ -0,0 +1,54 @@
-- +goose Up
-- U8: typed RunManifest persistence and optional finalizing status.
ALTER TABLE task_runs DROP CONSTRAINT IF EXISTS chk_task_run_status;
ALTER TABLE task_runs ADD CONSTRAINT chk_task_run_status CHECK (
status IN (
'pending',
'running',
'finalizing',
'completed',
'failed',
'cancelled',
'finalizing_failed',
'quality_failed',
'interrupted',
'pending_author_confirmation',
'blocked_pending_governance'
)
);
CREATE TABLE IF NOT EXISTS task_run_manifests (
run_id TEXT PRIMARY KEY REFERENCES task_runs(run_id) ON DELETE CASCADE,
canonical_bytes BYTEA NOT NULL,
sha256 CHAR(64) NOT NULL,
workspace_id TEXT NOT NULL DEFAULT '',
storage_identity TEXT NOT NULL DEFAULT '',
members JSONB NOT NULL DEFAULT '[]'::jsonb,
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
CONSTRAINT uq_task_run_manifests_run UNIQUE (run_id)
);
CREATE INDEX IF NOT EXISTS idx_task_run_manifests_sha ON task_run_manifests (sha256);
-- +goose Down
DROP INDEX IF EXISTS idx_task_run_manifests_sha;
DROP TABLE IF EXISTS task_run_manifests;
ALTER TABLE task_runs DROP CONSTRAINT IF EXISTS chk_task_run_status;
ALTER TABLE task_runs ADD CONSTRAINT chk_task_run_status CHECK (
status IN (
'pending',
'running',
'completed',
'failed',
'cancelled',
'finalizing_failed',
'quality_failed',
'interrupted',
'pending_author_confirmation',
'blocked_pending_governance'
)
);
+3 -2
View File
@@ -100,6 +100,7 @@ func TestGooseM2_00034to00036_DownThenUp(t *testing.T) {
"00034_2026-09-14-workspace-lease-fencing.sql",
"00035_2026-09-14-durable-event-delivery.sql",
"00036_2026-09-14-final-artifact-vault.sql",
"00037_2026-09-15-task-run-manifests.sql",
}
joined := strings.Join(files, "\n")
for _, name := range want {
@@ -135,7 +136,7 @@ func TestGooseM2_00034to00036_DownThenUp(t *testing.T) {
t.Fatalf("up: %v", err)
}
ver, err := CurrentVersion(ctx, pool)
if err != nil || ver < 36 {
if err != nil || ver < 37 {
t.Fatalf("version after up: %d %v", ver, err)
}
@@ -148,7 +149,7 @@ func TestGooseM2_00034to00036_DownThenUp(t *testing.T) {
if err := goose.DownToContext(ctx, sqlDB, migDir, 33); err != nil {
t.Fatalf("down to 33: %v", err)
}
for _, table := range []string{"event_envelopes", "event_deliveries", "event_dead_letters", "final_artifacts"} {
for _, table := range []string{"event_envelopes", "event_deliveries", "event_dead_letters", "final_artifacts", "task_run_manifests"} {
var n int
if err := pool.QueryRow(ctx, `SELECT COUNT(*) FROM information_schema.tables WHERE table_name=$1`, table).Scan(&n); err != nil {
t.Fatal(err)
+10
View File
@@ -49,3 +49,13 @@ func SkipIfNoTestDatabaseURL(t *testing.T) string {
}
return dsn
}
// RefuseSharedEnvDSN fails if the DSN targets a shared env database.
func RefuseSharedEnvDSN(t *testing.T, dsn string) {
t.Helper()
if strings.Contains(dsn, "5433") || strings.Contains(dsn, "agent_system_dev") ||
(strings.Contains(dsn, "5434") && strings.Contains(dsn, "agent_system_test")) ||
strings.Contains(dsn, "5435") {
t.Fatal("TEST_DATABASE_URL points at a shared env port; refuse agent_system_dev/test/main")
}
}