Commit6ecda8funknown_key
feat: schema additions for ai-loop and cross-repo impact (migrations 0101-0102)
feat: schema additions for ai-loop and cross-repo impact (migrations 0101-0102) - pull_requests: add ai_loop_attempts (int) + ai_loop_status (text) columns to track autonomous issue→PR→merge loop state per PR - cross_repo_impact_cache: new table storing jsonb impact reports with 15-min TTL keyed on pr_id, for the cross-repo dependency impact detector https://claude.ai/code/session_01DzJMTFASjMHt2f5ze4cNLR
3 files changed+41−06ecda8f35aaad39b4de87811c7f57fa50d367066
3 changed files+41−0
Addeddrizzle/0101_ai_loop.sql+5−0View fileUnifiedSplit
@@ -0,0 +1,5 @@
1-- Migration 0101: Add ai_loop columns to pull_requests table
2-- Tracks the autonomous issue-to-merged-PR loop state per PR.
3
4ALTER TABLE pull_requests ADD COLUMN IF NOT EXISTS ai_loop_attempts int NOT NULL DEFAULT 0;
5ALTER TABLE pull_requests ADD COLUMN IF NOT EXISTS ai_loop_status text; -- null | 'running' | 'merged' | 'failed'
Addeddrizzle/0102_cross_repo_impact.sql+9−0View fileUnifiedSplit
@@ -0,0 +1,9 @@
1-- Cross-repo impact cache (15min TTL, cleared on new PR push)
2CREATE TABLE IF NOT EXISTS cross_repo_impact_cache (
3 id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
4 pr_id uuid NOT NULL REFERENCES pull_requests(id) ON DELETE CASCADE,
5 report jsonb NOT NULL,
6 analyzed_at timestamp DEFAULT now(),
7 cached_until timestamp NOT NULL
8);
9CREATE INDEX IF NOT EXISTS idx_cross_repo_impact_pr ON cross_repo_impact_cache(pr_id);
Modifiedsrc/db/schema.ts+27−0View fileUnifiedSplit
@@ -756,6 +756,12 @@ export const pullRequests = pgTable(
756756 createdAt: timestamp("created_at").defaultNow().notNull(),
757757 updatedAt: timestamp("updated_at").defaultNow().notNull(),
758758 closedAt: timestamp("closed_at"),
759 // AI loop columns (migration 0101). Track the autonomous issue→PR→merge loop.
760 // aiLoopAttempts: how many fix-and-retry cycles have run so far (0 = not started).
761 // aiLoopStatus: null = not started, 'running' = loop active, 'merged' = success,
762 // 'failed' = exhausted attempts or unrecoverable error.
763 aiLoopAttempts: integer("ai_loop_attempts").notNull().default(0),
764 aiLoopStatus: text("ai_loop_status"), // null | 'running' | 'merged' | 'failed'
759765 },
760766 (table) => [
761767 index("prs_repo_state").on(table.repositoryId, table.state),
@@ -4573,3 +4579,24 @@ export const repoOnboardingData = pgTable("repo_onboarding_data", {
45734579
45744580export type RepoOnboardingData = typeof repoOnboardingData.$inferSelect;
45754581export type NewRepoOnboardingData = typeof repoOnboardingData.$inferInsert;
4582
4583// ---------------------------------------------------------------------------
4584// Migration 0102 — Cross-repo impact cache (15-min TTL, keyed on PR id)
4585// ---------------------------------------------------------------------------
4586export const crossRepoImpactCache = pgTable(
4587 "cross_repo_impact_cache",
4588 {
4589 id: uuid("id").primaryKey().defaultRandom(),
4590 prId: uuid("pr_id")
4591 .notNull()
4592 .references(() => pullRequests.id, { onDelete: "cascade" }),
4593 report: jsonb("report").notNull(),
4594 analyzedAt: timestamp("analyzed_at").defaultNow(),
4595 cachedUntil: timestamp("cached_until").notNull(),
4596 },
4597 (table) => [
4598 index("idx_cross_repo_impact_pr").on(table.prId),
4599 ]
4600);
4601
4602export type CrossRepoImpactCache = typeof crossRepoImpactCache.$inferSelect;
45764603