Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ jobs:

services:
doltgres:
image: dolthub/doltgresql:latest
image: dolthub/doltgresql:0.55.2
env:
DOLTGRES_USER: appuser
DOLTGRES_PASSWORD: password
Expand Down Expand Up @@ -289,4 +289,4 @@ jobs:
env:
INKEEP_AGENTS_MANAGE_DATABASE_URL: postgresql://appuser:password@localhost:5432/inkeep_agents
INKEEP_AGENTS_RUN_DATABASE_URL: postgresql://appuser:password@localhost:5433/inkeep_agents
SPICEDB_PRESHARED_KEY: dev-secret-key
SPICEDB_PRESHARED_KEY: dev-secret-key
2 changes: 1 addition & 1 deletion .github/workflows/cypress.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ jobs:

services:
doltgres:
image: dolthub/doltgresql:latest
image: dolthub/doltgresql:0.55.2
env:
DOLTGRES_USER: appuser
DOLTGRES_PASSWORD: password
Expand Down
44 changes: 44 additions & 0 deletions packages/agents-core/drizzle/manage/0010_oval_angel.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
-- Migration: Widen the UNIQUE constraint on sub_agent_skills to include tenant_id, project_id, agent_id
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟠 MAJOR: Deployment strategy for environments where original migration succeeded

Issue: This PR modifies an existing migration file (0010_oval_angel.sql) that exists on main. Per AGENTS.md, existing migration files should not be edited after application. While the original migration fails on Doltgres (which is why this fix is needed), it may have succeeded on PostgreSQL/PGlite environments.

Why: Environments where the original DROP CONSTRAINT + ADD CONSTRAINT migration already ran successfully will:

  1. Have the migration marked as applied in __drizzle_migrations
  2. Skip this new version entirely on future deployments
  3. Be in a correct end-state but with different migration history

This isn't necessarily a problem if the end-state is the same, but it creates a divergence in migration history between environments.

Fix: The current approach appears acceptable given:

  • The original migration fails on Doltgres (the production engine per PR description)
  • Environments where it succeeded have the correct constraint already
  • The backup-restore approach is idempotent in intent (achieving same end-state)

However, consider documenting:

  1. Deployment expectations in the PR description (which environment types this fixes vs. which already work)
  2. Whether any manual verification is needed for environments that ran the original migration

Refs:

-- Problem: The original UNIQUE("sub_agent_id","skill_id") was too narrow; it should be scoped per-agent.
-- Approach: backup→drop→recreate→restore to avoid Doltgres DROP CONSTRAINT bug and PGlite name collisions.
-- Step 1: Create backup table (no constraints, just data storage)
CREATE TABLE "sub_agent_skills_backup" (
"tenant_id" varchar(256),
"id" varchar(256),
"project_id" varchar(256),
"agent_id" varchar(256),
"sub_agent_id" varchar(256),
"skill_id" varchar(64),
"index" numeric,
"always_loaded" boolean,
"created_at" timestamp,
"updated_at" timestamp
);--> statement-breakpoint
-- Step 2: Copy all existing data to backup
INSERT INTO "sub_agent_skills_backup" SELECT * FROM "sub_agent_skills";--> statement-breakpoint
-- Step 3: Drop original table (frees all constraint/index names)
DROP TABLE "sub_agent_skills";--> statement-breakpoint
-- Step 4: Recreate table with correct wider UNIQUE constraint
CREATE TABLE "sub_agent_skills" (
"tenant_id" varchar(256) NOT NULL,
"id" varchar(256) NOT NULL,
"project_id" varchar(256) NOT NULL,
"agent_id" varchar(256) NOT NULL,
"sub_agent_id" varchar(256) NOT NULL,
"skill_id" varchar(64) NOT NULL,
"index" numeric DEFAULT 0 NOT NULL,
"always_loaded" boolean DEFAULT false NOT NULL,
"created_at" timestamp DEFAULT now() NOT NULL,
"updated_at" timestamp DEFAULT now() NOT NULL,
CONSTRAINT "sub_agent_skills_tenant_id_project_id_agent_id_id_pk" PRIMARY KEY("tenant_id","project_id","agent_id","id"),
CONSTRAINT "sub_agent_skills_sub_agent_skill_unique" UNIQUE("tenant_id","project_id","agent_id","sub_agent_id","skill_id")
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔴 CRITICAL: Schema/migration constraint mismatch

Issue: This migration creates a 5-column UNIQUE constraint, but the Drizzle schema definition at manage-schema.ts:293 still defines a 2-column constraint:

// Current schema (line 293):
unique('sub_agent_skills_sub_agent_skill_unique').on(table.subAgentId, table.skillId)

// Migration creates (line 34):
UNIQUE("tenant_id","project_id","agent_id","sub_agent_id","skill_id")

Why: This mismatch causes critical issues:

  1. Test/Production divergence: PGlite tests apply the Drizzle schema directly (2-column constraint), while Doltgres production uses migrations (5-column constraint)
  2. Future migration drift: Running pnpm db:generate will detect a discrepancy and generate a migration to revert back to 2 columns
  3. Missing Drizzle tracking: The journal (meta/_journal.json) is missing the 0010 entry, and no 0010_snapshot.json exists

Fix: Update the Drizzle schema to match the migration:

// manage-schema.ts line 293 should be:
unique('sub_agent_skills_sub_agent_skill_unique').on(
  table.tenantId, 
  table.projectId, 
  table.agentId, 
  table.subAgentId, 
  table.skillId
)

Then either:

  • Option A: Run pnpm db:generate to regenerate the migration with proper meta files (preferred if Drizzle can generate the backup→restore pattern, which it likely cannot)
  • Option B: Manually add the journal entry and create 0010_snapshot.json to match the post-migration state

Refs:

);--> statement-breakpoint
-- Step 5: Restore data from backup
INSERT INTO "sub_agent_skills" SELECT * FROM "sub_agent_skills_backup";--> statement-breakpoint
-- Step 6: Drop backup table
DROP TABLE "sub_agent_skills_backup";--> statement-breakpoint
-- Step 7: Re-add foreign keys
ALTER TABLE "sub_agent_skills" ADD CONSTRAINT "sub_agent_skills_sub_agent_fk" FOREIGN KEY ("tenant_id","project_id","agent_id","sub_agent_id") REFERENCES "public"."sub_agents"("tenant_id","project_id","agent_id","id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "sub_agent_skills" ADD CONSTRAINT "sub_agent_skills_skill_fk" FOREIGN KEY ("tenant_id","project_id","skill_id") REFERENCES "public"."skills"("tenant_id","project_id","id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
-- Step 8: Re-add index
CREATE INDEX "sub_agent_skills_skill_idx" ON "sub_agent_skills" USING btree ("skill_id");
Loading