@proofhound/db 0.1.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (112) hide show
  1. package/LICENSE +190 -0
  2. package/dist/clean-test-residue.d.ts +2 -0
  3. package/dist/clean-test-residue.d.ts.map +1 -0
  4. package/dist/clean-test-residue.js +59 -0
  5. package/dist/clean-test-residue.js.map +1 -0
  6. package/dist/client.d.ts +5 -0
  7. package/dist/client.d.ts.map +1 -0
  8. package/dist/client.js +87 -0
  9. package/dist/client.js.map +1 -0
  10. package/dist/ensure-e2e-database.d.ts +2 -0
  11. package/dist/ensure-e2e-database.d.ts.map +1 -0
  12. package/dist/ensure-e2e-database.js +87 -0
  13. package/dist/ensure-e2e-database.js.map +1 -0
  14. package/dist/fixtures/dev/connectors.d.ts +72 -0
  15. package/dist/fixtures/dev/connectors.d.ts.map +1 -0
  16. package/dist/fixtures/dev/connectors.js +90 -0
  17. package/dist/fixtures/dev/connectors.js.map +1 -0
  18. package/dist/fixtures/dev/experiments.d.ts +48 -0
  19. package/dist/fixtures/dev/experiments.d.ts.map +1 -0
  20. package/dist/fixtures/dev/experiments.js +1168 -0
  21. package/dist/fixtures/dev/experiments.js.map +1 -0
  22. package/dist/fixtures/dev/models.d.ts +20 -0
  23. package/dist/fixtures/dev/models.d.ts.map +1 -0
  24. package/dist/fixtures/dev/models.js +60 -0
  25. package/dist/fixtures/dev/models.js.map +1 -0
  26. package/dist/fixtures/dev/optimizations.d.ts +62 -0
  27. package/dist/fixtures/dev/optimizations.d.ts.map +1 -0
  28. package/dist/fixtures/dev/optimizations.js +124 -0
  29. package/dist/fixtures/dev/optimizations.js.map +1 -0
  30. package/dist/fixtures/dev/prompts.d.ts +31 -0
  31. package/dist/fixtures/dev/prompts.d.ts.map +1 -0
  32. package/dist/fixtures/dev/prompts.js +115 -0
  33. package/dist/fixtures/dev/prompts.js.map +1 -0
  34. package/dist/fixtures/dev/tokens.d.ts +10 -0
  35. package/dist/fixtures/dev/tokens.d.ts.map +1 -0
  36. package/dist/fixtures/dev/tokens.js +28 -0
  37. package/dist/fixtures/dev/tokens.js.map +1 -0
  38. package/dist/index.d.ts +3 -0
  39. package/dist/index.d.ts.map +1 -0
  40. package/dist/index.js +44 -0
  41. package/dist/index.js.map +1 -0
  42. package/dist/migrate.d.ts +2 -0
  43. package/dist/migrate.d.ts.map +1 -0
  44. package/dist/migrate.js +34 -0
  45. package/dist/migrate.js.map +1 -0
  46. package/dist/migrations/0000_woozy_thunderbolt.sql +688 -0
  47. package/dist/migrations/0001_webhook_token_scope.sql +28 -0
  48. package/dist/migrations/0002_tokens_table_unify_scope.sql +50 -0
  49. package/dist/migrations/0003_models_auto_concurrency.sql +4 -0
  50. package/dist/migrations/0004_webhook_token_attribution.sql +4 -0
  51. package/dist/migrations/0005_same_thor_girl.sql +34 -0
  52. package/dist/reset.d.ts +2 -0
  53. package/dist/reset.d.ts.map +1 -0
  54. package/dist/reset.js +78 -0
  55. package/dist/reset.js.map +1 -0
  56. package/dist/schema/index.d.ts +5 -0
  57. package/dist/schema/index.d.ts.map +1 -0
  58. package/dist/schema/index.js +23 -0
  59. package/dist/schema/index.js.map +1 -0
  60. package/dist/schema/ph_assets/index.d.ts +2012 -0
  61. package/dist/schema/ph_assets/index.d.ts.map +1 -0
  62. package/dist/schema/ph_assets/index.js +272 -0
  63. package/dist/schema/ph_assets/index.js.map +1 -0
  64. package/dist/schema/ph_core/index.d.ts +424 -0
  65. package/dist/schema/ph_core/index.d.ts.map +1 -0
  66. package/dist/schema/ph_core/index.js +69 -0
  67. package/dist/schema/ph_core/index.js.map +1 -0
  68. package/dist/schema/ph_releases/_schema.d.ts +2 -0
  69. package/dist/schema/ph_releases/_schema.d.ts.map +1 -0
  70. package/dist/schema/ph_releases/_schema.js +8 -0
  71. package/dist/schema/ph_releases/_schema.js.map +1 -0
  72. package/dist/schema/ph_releases/annotation-tasks.d.ts +263 -0
  73. package/dist/schema/ph_releases/annotation-tasks.d.ts.map +1 -0
  74. package/dist/schema/ph_releases/annotation-tasks.js +38 -0
  75. package/dist/schema/ph_releases/annotation-tasks.js.map +1 -0
  76. package/dist/schema/ph_releases/canary-releases.d.ts +672 -0
  77. package/dist/schema/ph_releases/canary-releases.d.ts.map +1 -0
  78. package/dist/schema/ph_releases/canary-releases.js +91 -0
  79. package/dist/schema/ph_releases/canary-releases.js.map +1 -0
  80. package/dist/schema/ph_releases/index.d.ts +6 -0
  81. package/dist/schema/ph_releases/index.d.ts.map +1 -0
  82. package/dist/schema/ph_releases/index.js +24 -0
  83. package/dist/schema/ph_releases/index.js.map +1 -0
  84. package/dist/schema/ph_releases/production-release-events.d.ts +527 -0
  85. package/dist/schema/ph_releases/production-release-events.d.ts.map +1 -0
  86. package/dist/schema/ph_releases/production-release-events.js +86 -0
  87. package/dist/schema/ph_releases/production-release-events.js.map +1 -0
  88. package/dist/schema/ph_releases/release-lines.d.ts +1442 -0
  89. package/dist/schema/ph_releases/release-lines.d.ts.map +1 -0
  90. package/dist/schema/ph_releases/release-lines.js +203 -0
  91. package/dist/schema/ph_releases/release-lines.js.map +1 -0
  92. package/dist/schema/ph_runs/_schema.d.ts +2 -0
  93. package/dist/schema/ph_runs/_schema.d.ts.map +1 -0
  94. package/dist/schema/ph_runs/_schema.js +6 -0
  95. package/dist/schema/ph_runs/_schema.js.map +1 -0
  96. package/dist/schema/ph_runs/experiments.d.ts +984 -0
  97. package/dist/schema/ph_runs/experiments.d.ts.map +1 -0
  98. package/dist/schema/ph_runs/experiments.js +134 -0
  99. package/dist/schema/ph_runs/experiments.js.map +1 -0
  100. package/dist/schema/ph_runs/index.d.ts +1027 -0
  101. package/dist/schema/ph_runs/index.d.ts.map +1 -0
  102. package/dist/schema/ph_runs/index.js +135 -0
  103. package/dist/schema/ph_runs/index.js.map +1 -0
  104. package/dist/seed-dev.d.ts +2 -0
  105. package/dist/seed-dev.d.ts.map +1 -0
  106. package/dist/seed-dev.js +605 -0
  107. package/dist/seed-dev.js.map +1 -0
  108. package/dist/seed.d.ts +2 -0
  109. package/dist/seed.d.ts.map +1 -0
  110. package/dist/seed.js +13 -0
  111. package/dist/seed.js.map +1 -0
  112. package/package.json +60 -0
@@ -0,0 +1,688 @@
1
+ CREATE EXTENSION IF NOT EXISTS "pgcrypto";
2
+ --> statement-breakpoint
3
+ CREATE SCHEMA "ph_core";
4
+ --> statement-breakpoint
5
+ CREATE SCHEMA "ph_assets";
6
+ --> statement-breakpoint
7
+ CREATE SCHEMA "ph_runs";
8
+ --> statement-breakpoint
9
+ CREATE SCHEMA "ph_releases";
10
+ --> statement-breakpoint
11
+ CREATE TABLE "ph_core"."api_tokens" (
12
+ "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
13
+ "scope" text NOT NULL,
14
+ "project_id" uuid,
15
+ "name" text NOT NULL,
16
+ "token_hash" text NOT NULL,
17
+ "token_encrypted" text,
18
+ "prefix" text NOT NULL,
19
+ "ip_whitelist" jsonb,
20
+ "last_used_at" timestamp with time zone,
21
+ "expires_at" timestamp with time zone,
22
+ "created_by" uuid NOT NULL,
23
+ "created_at" timestamp with time zone DEFAULT now() NOT NULL,
24
+ "revoked_at" timestamp with time zone,
25
+ CONSTRAINT "api_tokens_token_hash_unique" UNIQUE("token_hash"),
26
+ CONSTRAINT "api_tokens_scope_check" CHECK ("ph_core"."api_tokens"."scope" IN ('project_api', 'global_mcp')),
27
+ CONSTRAINT "api_tokens_scope_fields_check" CHECK ((
28
+ ("ph_core"."api_tokens"."scope" = 'project_api' AND "ph_core"."api_tokens"."project_id" IS NOT NULL) OR
29
+ ("ph_core"."api_tokens"."scope" = 'global_mcp' AND "ph_core"."api_tokens"."project_id" IS NULL)
30
+ ))
31
+ );
32
+ --> statement-breakpoint
33
+ CREATE TABLE "ph_core"."projects" (
34
+ "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
35
+ "name" text NOT NULL,
36
+ "description" text,
37
+ "type" text DEFAULT 'classification' NOT NULL,
38
+ "status" text DEFAULT 'active' NOT NULL,
39
+ "created_by" uuid NOT NULL,
40
+ "created_at" timestamp with time zone DEFAULT now() NOT NULL,
41
+ "updated_at" timestamp with time zone DEFAULT now() NOT NULL,
42
+ "archived_at" timestamp with time zone,
43
+ "deleted_at" timestamp with time zone,
44
+ CONSTRAINT "projects_type_check" CHECK ("ph_core"."projects"."type" IN ('classification', 'generative', 'agent')),
45
+ CONSTRAINT "projects_status_check" CHECK ("ph_core"."projects"."status" IN ('active', 'archived'))
46
+ );
47
+ --> statement-breakpoint
48
+ INSERT INTO "ph_core"."projects" (
49
+ "id",
50
+ "name",
51
+ "description",
52
+ "type",
53
+ "status",
54
+ "created_by"
55
+ )
56
+ VALUES (
57
+ '00000000-0000-4000-8000-000000000001',
58
+ 'Local Project',
59
+ 'Self-hosted single-project data boundary',
60
+ 'classification',
61
+ 'active',
62
+ '00000000-0000-4000-8000-000000000001'
63
+ )
64
+ ON CONFLICT ("id") DO NOTHING;
65
+ --> statement-breakpoint
66
+ CREATE TABLE "ph_assets"."connectors" (
67
+ "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
68
+ "project_id" uuid NOT NULL,
69
+ "name" text NOT NULL,
70
+ "description" text,
71
+ "direction" text NOT NULL,
72
+ "type" text NOT NULL,
73
+ "config" jsonb NOT NULL,
74
+ "config_encrypted" jsonb,
75
+ "webhook_path" text,
76
+ "webhook_token_id" uuid,
77
+ "ip_whitelist" jsonb,
78
+ "health_status" text DEFAULT 'unknown' NOT NULL,
79
+ "last_probed_at" timestamp with time zone,
80
+ "last_probe_error" text,
81
+ "created_by" uuid NOT NULL,
82
+ "created_at" timestamp with time zone DEFAULT now() NOT NULL,
83
+ "updated_at" timestamp with time zone DEFAULT now() NOT NULL,
84
+ "deleted_at" timestamp with time zone,
85
+ CONSTRAINT "connectors_direction_check" CHECK ("ph_assets"."connectors"."direction" IN ('input', 'output')),
86
+ CONSTRAINT "connectors_type_check" CHECK ("ph_assets"."connectors"."type" IN ('redis', 'kafka', 'webhook')),
87
+ CONSTRAINT "connectors_health_status_check" CHECK ("ph_assets"."connectors"."health_status" IN ('healthy', 'degraded', 'unhealthy', 'unknown')),
88
+ CONSTRAINT "connectors_type_webhook_check" CHECK ((
89
+ ("ph_assets"."connectors"."type" = 'webhook' AND "ph_assets"."connectors"."direction" = 'input' AND "ph_assets"."connectors"."webhook_path" IS NOT NULL) OR
90
+ ("ph_assets"."connectors"."type" = 'webhook' AND "ph_assets"."connectors"."direction" = 'output' AND "ph_assets"."connectors"."webhook_path" IS NULL) OR
91
+ ("ph_assets"."connectors"."type" <> 'webhook' AND "ph_assets"."connectors"."webhook_path" IS NULL)
92
+ ))
93
+ );
94
+ --> statement-breakpoint
95
+ CREATE TABLE "ph_assets"."dataset_samples" (
96
+ "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
97
+ "dataset_id" uuid NOT NULL,
98
+ "data" jsonb NOT NULL,
99
+ "external_id" text,
100
+ "created_at" timestamp with time zone DEFAULT now() NOT NULL,
101
+ "updated_at" timestamp with time zone DEFAULT now() NOT NULL
102
+ );
103
+ --> statement-breakpoint
104
+ CREATE TABLE "ph_assets"."datasets" (
105
+ "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
106
+ "project_id" uuid NOT NULL,
107
+ "name" text NOT NULL,
108
+ "description" text,
109
+ "sample_count" integer DEFAULT 0 NOT NULL,
110
+ "field_schema" jsonb DEFAULT '[]'::jsonb NOT NULL,
111
+ "has_images" boolean DEFAULT false NOT NULL,
112
+ "storage_prefix" text,
113
+ "created_by" uuid NOT NULL,
114
+ "created_at" timestamp with time zone DEFAULT now() NOT NULL,
115
+ "updated_at" timestamp with time zone DEFAULT now() NOT NULL,
116
+ "deleted_at" timestamp with time zone
117
+ );
118
+ --> statement-breakpoint
119
+ CREATE TABLE "ph_assets"."model_context_windows" (
120
+ "provider_model_id" text PRIMARY KEY NOT NULL,
121
+ "context_window_tokens" integer NOT NULL,
122
+ "updated_by" uuid,
123
+ "updated_at" timestamp with time zone DEFAULT now() NOT NULL,
124
+ CONSTRAINT "model_context_windows_context_window_positive_check" CHECK ("ph_assets"."model_context_windows"."context_window_tokens" > 0)
125
+ );
126
+ --> statement-breakpoint
127
+ CREATE TABLE "ph_assets"."models" (
128
+ "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
129
+ "project_id" uuid NOT NULL,
130
+ "name" text NOT NULL,
131
+ "provider_type" text NOT NULL,
132
+ "provider_model_id" text NOT NULL,
133
+ "endpoint" text NOT NULL,
134
+ "api_key_encrypted" text NOT NULL,
135
+ "context_window_tokens" integer,
136
+ "rpm_limit" integer DEFAULT 60 NOT NULL,
137
+ "tpm_limit" integer DEFAULT 100000 NOT NULL,
138
+ "concurrency_limit" integer DEFAULT 20 NOT NULL,
139
+ "input_token_price_per_million" numeric(12, 6) DEFAULT '0' NOT NULL,
140
+ "output_token_price_per_million" numeric(12, 6) DEFAULT '0' NOT NULL,
141
+ "capabilities" jsonb DEFAULT '{}'::jsonb NOT NULL,
142
+ "extra_body" jsonb DEFAULT '{}'::jsonb NOT NULL,
143
+ "is_active" boolean DEFAULT true NOT NULL,
144
+ "last_probed_at" timestamp with time zone,
145
+ "last_probe_error" text,
146
+ "created_by" uuid NOT NULL,
147
+ "created_at" timestamp with time zone DEFAULT now() NOT NULL,
148
+ "updated_at" timestamp with time zone DEFAULT now() NOT NULL,
149
+ "deleted_at" timestamp with time zone,
150
+ CONSTRAINT "models_context_window_tokens_positive_check" CHECK ("ph_assets"."models"."context_window_tokens" IS NULL OR "ph_assets"."models"."context_window_tokens" > 0),
151
+ CONSTRAINT "models_rpm_limit_valid_check" CHECK ("ph_assets"."models"."rpm_limit" = -1 OR "ph_assets"."models"."rpm_limit" > 0),
152
+ CONSTRAINT "models_tpm_limit_valid_check" CHECK ("ph_assets"."models"."tpm_limit" = -1 OR "ph_assets"."models"."tpm_limit" > 0),
153
+ CONSTRAINT "models_concurrency_limit_valid_check" CHECK ("ph_assets"."models"."concurrency_limit" >= 1 AND "ph_assets"."models"."concurrency_limit" <= 999),
154
+ CONSTRAINT "models_input_token_price_nonnegative_check" CHECK ("ph_assets"."models"."input_token_price_per_million" >= 0),
155
+ CONSTRAINT "models_output_token_price_nonnegative_check" CHECK ("ph_assets"."models"."output_token_price_per_million" >= 0),
156
+ CONSTRAINT "models_extra_body_object_check" CHECK (jsonb_typeof("ph_assets"."models"."extra_body") = 'object')
157
+ );
158
+ --> statement-breakpoint
159
+ CREATE TABLE "ph_assets"."prompt_version_labels" (
160
+ "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
161
+ "prompt_id" uuid NOT NULL,
162
+ "version_id" uuid NOT NULL,
163
+ "label" text NOT NULL,
164
+ "label_type" text DEFAULT 'custom' NOT NULL,
165
+ "created_by" uuid NOT NULL,
166
+ "created_at" timestamp with time zone DEFAULT now() NOT NULL,
167
+ "updated_at" timestamp with time zone DEFAULT now() NOT NULL,
168
+ CONSTRAINT "prompt_version_labels_type_check" CHECK ("ph_assets"."prompt_version_labels"."label_type" IN ('system', 'custom')),
169
+ CONSTRAINT "prompt_version_labels_label_check" CHECK ("ph_assets"."prompt_version_labels"."label" ~ '^[A-Za-z0-9一-鿿][A-Za-z0-9一-鿿_.:-]{0,63}$')
170
+ );
171
+ --> statement-breakpoint
172
+ CREATE TABLE "ph_assets"."prompt_versions" (
173
+ "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
174
+ "prompt_id" uuid NOT NULL,
175
+ "version_number" integer NOT NULL,
176
+ "body" text,
177
+ "variables" jsonb DEFAULT '[]'::jsonb NOT NULL,
178
+ "output_schema" jsonb,
179
+ "judgment_rules" jsonb,
180
+ "prompt_language" text DEFAULT 'zh-CN' NOT NULL,
181
+ "parent_version_id" uuid,
182
+ "generated_by_optimization_id" uuid,
183
+ "change_reason" text,
184
+ "is_frozen" boolean DEFAULT false NOT NULL,
185
+ "created_by" uuid NOT NULL,
186
+ "created_at" timestamp with time zone DEFAULT now() NOT NULL,
187
+ "frozen_at" timestamp with time zone,
188
+ CONSTRAINT "prompt_versions_prompt_version_unique" UNIQUE("prompt_id","version_number"),
189
+ CONSTRAINT "prompt_versions_prompt_language_check" CHECK ("ph_assets"."prompt_versions"."prompt_language" IN ('zh-CN', 'en-US'))
190
+ );
191
+ --> statement-breakpoint
192
+ CREATE TABLE "ph_assets"."prompts" (
193
+ "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
194
+ "project_id" uuid NOT NULL,
195
+ "name" text NOT NULL,
196
+ "current_online_version_id" uuid,
197
+ "default_dataset_id" uuid,
198
+ "created_by" uuid NOT NULL,
199
+ "created_at" timestamp with time zone DEFAULT now() NOT NULL,
200
+ "updated_at" timestamp with time zone DEFAULT now() NOT NULL,
201
+ "deleted_at" timestamp with time zone
202
+ );
203
+ --> statement-breakpoint
204
+ CREATE TABLE "ph_runs"."annotations" (
205
+ "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
206
+ "run_result_id" uuid NOT NULL,
207
+ "run_result_created_at" timestamp with time zone NOT NULL,
208
+ "task_id" uuid,
209
+ "is_correct" boolean,
210
+ "fields" jsonb DEFAULT '{}'::jsonb NOT NULL,
211
+ "notes" text,
212
+ "locked_by" uuid,
213
+ "locked_at" timestamp with time zone,
214
+ "lock_heartbeat_at" timestamp with time zone,
215
+ "submitted_at" timestamp with time zone,
216
+ "submitted_by" uuid,
217
+ "created_at" timestamp with time zone DEFAULT now() NOT NULL,
218
+ "updated_at" timestamp with time zone DEFAULT now() NOT NULL
219
+ );
220
+ --> statement-breakpoint
221
+ CREATE TABLE "ph_runs"."experiments" (
222
+ "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
223
+ "project_id" uuid NOT NULL,
224
+ "name" text NOT NULL,
225
+ "prompt_version_id" uuid NOT NULL,
226
+ "dataset_id" uuid NOT NULL,
227
+ "model_id" uuid NOT NULL,
228
+ "optimization_id" uuid,
229
+ "round_index" integer,
230
+ "status" text DEFAULT 'running' NOT NULL,
231
+ "run_config" jsonb DEFAULT '{}'::jsonb NOT NULL,
232
+ "dbos_workflow_id" text,
233
+ "control_state" text,
234
+ "total_samples" integer DEFAULT 0 NOT NULL,
235
+ "processed_samples" integer DEFAULT 0 NOT NULL,
236
+ "failed_samples" integer DEFAULT 0 NOT NULL,
237
+ "metrics" jsonb,
238
+ "failure_kind" text,
239
+ "failure_reason" text,
240
+ "started_at" timestamp with time zone,
241
+ "finished_at" timestamp with time zone,
242
+ "created_by" uuid NOT NULL,
243
+ "created_at" timestamp with time zone DEFAULT now() NOT NULL,
244
+ "updated_at" timestamp with time zone DEFAULT now() NOT NULL,
245
+ "deleted_at" timestamp with time zone,
246
+ CONSTRAINT "experiments_status_check" CHECK ("ph_runs"."experiments"."status" IN ('running', 'success', 'failed', 'stopped', 'cancelled')),
247
+ CONSTRAINT "experiments_control_state_check" CHECK ("ph_runs"."experiments"."control_state" IN ('stop', 'resume', 'cancel') OR "ph_runs"."experiments"."control_state" IS NULL),
248
+ CONSTRAINT "experiments_failure_kind_check" CHECK ("ph_runs"."experiments"."failure_kind" IN ('rate_limit', 'parse', 'timeout', 'internal') OR "ph_runs"."experiments"."failure_kind" IS NULL),
249
+ CONSTRAINT "experiments_optimization_round_paired" CHECK (("ph_runs"."experiments"."optimization_id" IS NULL) = ("ph_runs"."experiments"."round_index" IS NULL))
250
+ );
251
+ --> statement-breakpoint
252
+ CREATE TABLE "ph_runs"."optimization_round_steps" (
253
+ "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
254
+ "optimization_id" uuid NOT NULL,
255
+ "round_index" integer NOT NULL,
256
+ "step" text NOT NULL,
257
+ "status" text NOT NULL,
258
+ "error_class" text,
259
+ "error_message" text,
260
+ "run_result_id" uuid,
261
+ "experiment_id" uuid,
262
+ "started_at" timestamp with time zone,
263
+ "finished_at" timestamp with time zone,
264
+ "attempt" integer DEFAULT 0 NOT NULL,
265
+ "dbos_workflow_id" text,
266
+ "created_at" timestamp with time zone DEFAULT now() NOT NULL,
267
+ "updated_at" timestamp with time zone DEFAULT now() NOT NULL,
268
+ CONSTRAINT "optimization_round_steps_step_check" CHECK ("ph_runs"."optimization_round_steps"."step" IN ('error_analysis', 'generate_prompt', 'experiment')),
269
+ CONSTRAINT "optimization_round_steps_status_check" CHECK ("ph_runs"."optimization_round_steps"."status" IN ('pending', 'running', 'success', 'failed', 'skipped'))
270
+ );
271
+ --> statement-breakpoint
272
+ CREATE TABLE "ph_runs"."optimizations" (
273
+ "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
274
+ "project_id" uuid NOT NULL,
275
+ "name" text NOT NULL,
276
+ "description" text,
277
+ "optimization_hint" text,
278
+ "strategy" text DEFAULT 'error_pattern_analysis' NOT NULL,
279
+ "strategy_config" jsonb DEFAULT '{}'::jsonb NOT NULL,
280
+ "starting_mode" text NOT NULL,
281
+ "source_experiment_id" uuid,
282
+ "prompt_id" uuid,
283
+ "base_version_id" uuid,
284
+ "dataset_id" uuid NOT NULL,
285
+ "experiment_model_id" uuid NOT NULL,
286
+ "analysis_model_id" uuid NOT NULL,
287
+ "prompt_language" text DEFAULT 'zh-CN' NOT NULL,
288
+ "status" text DEFAULT 'running' NOT NULL,
289
+ "dbos_workflow_id" text,
290
+ "control_state" text,
291
+ "goals" jsonb NOT NULL,
292
+ "field_whitelist" jsonb,
293
+ "run_config" jsonb DEFAULT '{}'::jsonb NOT NULL,
294
+ "max_rounds" integer DEFAULT 10 NOT NULL,
295
+ "current_round" integer DEFAULT 0 NOT NULL,
296
+ "best_version_id" uuid,
297
+ "best_metrics" jsonb,
298
+ "summary" jsonb,
299
+ "analysis_failure_reason" text,
300
+ "started_at" timestamp with time zone,
301
+ "finished_at" timestamp with time zone,
302
+ "created_by" uuid NOT NULL,
303
+ "created_at" timestamp with time zone DEFAULT now() NOT NULL,
304
+ "updated_at" timestamp with time zone DEFAULT now() NOT NULL,
305
+ "deleted_at" timestamp with time zone,
306
+ CONSTRAINT "optimizations_status_check" CHECK ("ph_runs"."optimizations"."status" IN ('running', 'success', 'failed', 'stopped', 'cancelled')),
307
+ CONSTRAINT "optimizations_starting_mode_check" CHECK ("ph_runs"."optimizations"."starting_mode" IN ('from_experiment', 'from_prompt_version', 'from_dataset_only')),
308
+ CONSTRAINT "optimizations_control_state_check" CHECK ("ph_runs"."optimizations"."control_state" IN ('stop', 'resume', 'cancel') OR "ph_runs"."optimizations"."control_state" IS NULL),
309
+ CONSTRAINT "optimizations_prompt_language_check" CHECK ("ph_runs"."optimizations"."prompt_language" IN ('zh-CN', 'en-US'))
310
+ );
311
+ --> statement-breakpoint
312
+ CREATE TABLE "ph_runs"."run_results" (
313
+ "id" uuid DEFAULT gen_random_uuid() NOT NULL,
314
+ "project_id" uuid NOT NULL,
315
+ "source" text NOT NULL,
316
+ "source_id" uuid NOT NULL,
317
+ "release_variant_id" uuid,
318
+ "prompt_version_id" uuid NOT NULL,
319
+ "model_id" uuid NOT NULL,
320
+ "sample_id" uuid,
321
+ "external_id" text,
322
+ "round_index" integer,
323
+ "rendered_prompt" jsonb NOT NULL,
324
+ "input_variables" jsonb,
325
+ "raw_response" text,
326
+ "parsed_output" jsonb,
327
+ "decision_output" text,
328
+ "expected_output" text,
329
+ "is_correct" boolean,
330
+ "judgment_status" text,
331
+ "status" text NOT NULL,
332
+ "error_class" text,
333
+ "error_message" text,
334
+ "latency_ms" integer,
335
+ "input_tokens" integer,
336
+ "output_tokens" integer,
337
+ "cost_estimate" numeric(12, 6),
338
+ "attempt" integer DEFAULT 1 NOT NULL,
339
+ "dbos_workflow_id" text,
340
+ "bullmq_job_id" text,
341
+ "created_at" timestamp with time zone DEFAULT now() NOT NULL,
342
+ CONSTRAINT "run_results_pkey" PRIMARY KEY("id","created_at"),
343
+ CONSTRAINT "run_results_source_check" CHECK ("ph_runs"."run_results"."source" IN ('experiment', 'optimization_analysis', 'optimization_generate', 'release', 'canary', 'online')),
344
+ CONSTRAINT "run_results_judgment_status_check" CHECK ("ph_runs"."run_results"."judgment_status" IN ('correct', 'incorrect', 'parse_error', 'judge_error') OR "ph_runs"."run_results"."judgment_status" IS NULL),
345
+ CONSTRAINT "run_results_status_check" CHECK ("ph_runs"."run_results"."status" IN ('success', 'error', 'timeout', 'rate_limited'))
346
+ );
347
+ --> statement-breakpoint
348
+ CREATE TABLE "ph_releases"."release_line_events" (
349
+ "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
350
+ "project_id" uuid NOT NULL,
351
+ "release_line_id" uuid NOT NULL,
352
+ "lane_type" text NOT NULL,
353
+ "operation" text NOT NULL,
354
+ "status" text NOT NULL,
355
+ "terminal_reason" text,
356
+ "source_event_id" uuid,
357
+ "supersedes_event_id" uuid,
358
+ "rollback_target_event_id" uuid,
359
+ "legacy_source" text,
360
+ "legacy_source_id" uuid,
361
+ "release_variant_id" uuid,
362
+ "prompt_id" uuid,
363
+ "prompt_name" text NOT NULL,
364
+ "prompt_version_id" uuid,
365
+ "prompt_version_number" integer,
366
+ "prompt_snapshot" jsonb DEFAULT '{}'::jsonb NOT NULL,
367
+ "prompt_version_snapshot" jsonb DEFAULT '{}'::jsonb NOT NULL,
368
+ "model_id" uuid,
369
+ "model_snapshot" jsonb DEFAULT '{}'::jsonb NOT NULL,
370
+ "input_connector_id" uuid,
371
+ "input_connector_snapshot" jsonb DEFAULT '{}'::jsonb NOT NULL,
372
+ "output_connector_ids" uuid[] DEFAULT ARRAY[]::uuid[] NOT NULL,
373
+ "output_connector_snapshots" jsonb DEFAULT '[]'::jsonb NOT NULL,
374
+ "traffic_mode" text,
375
+ "traffic_ratio" numeric(5, 4),
376
+ "run_config" jsonb DEFAULT '{}'::jsonb NOT NULL,
377
+ "variable_mapping" jsonb DEFAULT '{}'::jsonb NOT NULL,
378
+ "output_mapping" jsonb DEFAULT '[]'::jsonb NOT NULL,
379
+ "filter_rules" jsonb,
380
+ "record_mode" text DEFAULT 'all' NOT NULL,
381
+ "external_id_field" text,
382
+ "retention_days" integer,
383
+ "source_experiment_id" uuid,
384
+ "submit_reason" text DEFAULT '' NOT NULL,
385
+ "metrics" jsonb,
386
+ "total_received" integer DEFAULT 0 NOT NULL,
387
+ "total_processed" integer DEFAULT 0 NOT NULL,
388
+ "total_filtered" integer DEFAULT 0 NOT NULL,
389
+ "total_correct" integer DEFAULT 0 NOT NULL,
390
+ "total_errors" integer DEFAULT 0 NOT NULL,
391
+ "control_state" text,
392
+ "control_state_payload" jsonb,
393
+ "started_at" timestamp with time zone,
394
+ "finished_at" timestamp with time zone,
395
+ "created_by" uuid NOT NULL,
396
+ "created_at" timestamp with time zone DEFAULT now() NOT NULL,
397
+ "updated_at" timestamp with time zone DEFAULT now() NOT NULL,
398
+ CONSTRAINT "release_line_events_lane_type_check" CHECK ("ph_releases"."release_line_events"."lane_type" IN ('production', 'canary')),
399
+ CONSTRAINT "release_line_events_operation_check" CHECK ("ph_releases"."release_line_events"."operation" IN (
400
+ 'create_production',
401
+ 'create_production_from_experiment',
402
+ 'create_canary',
403
+ 'traffic_updated',
404
+ 'mode_updated',
405
+ 'config_changed',
406
+ 'stop_lane',
407
+ 'resume_lane',
408
+ 'cancel_canary',
409
+ 'promote_canary',
410
+ 'rollback',
411
+ 'force_stop',
412
+ 'archive_line'
413
+ )),
414
+ CONSTRAINT "release_line_events_status_check" CHECK ("ph_releases"."release_line_events"."status" IN ('running', 'stopped', 'completed', 'failed', 'cancelled', 'archived')),
415
+ CONSTRAINT "release_line_events_terminal_reason_check" CHECK ("ph_releases"."release_line_events"."terminal_reason" IN ('replaced', 'rolled_back', 'force_stopped', 'promoted', 'cancelled', 'archived', 'error') OR "ph_releases"."release_line_events"."terminal_reason" IS NULL),
416
+ CONSTRAINT "release_line_events_traffic_mode_check" CHECK ("ph_releases"."release_line_events"."traffic_mode" IN ('split', 'dual_run') OR "ph_releases"."release_line_events"."traffic_mode" IS NULL),
417
+ CONSTRAINT "release_line_events_traffic_ratio_check" CHECK ("ph_releases"."release_line_events"."traffic_ratio" IS NULL OR ("ph_releases"."release_line_events"."traffic_ratio" >= 0 AND "ph_releases"."release_line_events"."traffic_ratio" <= 1)),
418
+ CONSTRAINT "release_line_events_record_mode_check" CHECK ("ph_releases"."release_line_events"."record_mode" IN ('all', 'correct_only')),
419
+ CONSTRAINT "release_line_events_rollback_target_required" CHECK ("ph_releases"."release_line_events"."operation" <> 'rollback' OR "ph_releases"."release_line_events"."rollback_target_event_id" IS NOT NULL),
420
+ CONSTRAINT "release_line_events_promote_source_required" CHECK ("ph_releases"."release_line_events"."operation" <> 'promote_canary' OR "ph_releases"."release_line_events"."source_event_id" IS NOT NULL),
421
+ CONSTRAINT "release_line_events_legacy_source_check" CHECK ("ph_releases"."release_line_events"."legacy_source" IN ('production_release_event', 'canary_release') OR "ph_releases"."release_line_events"."legacy_source" IS NULL)
422
+ );
423
+ --> statement-breakpoint
424
+ CREATE TABLE "ph_releases"."release_lines" (
425
+ "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
426
+ "project_id" uuid NOT NULL,
427
+ "name" text NOT NULL,
428
+ "description" text,
429
+ "prompt_id" uuid,
430
+ "prompt_name" text NOT NULL,
431
+ "prompt_snapshot" jsonb DEFAULT '{}'::jsonb NOT NULL,
432
+ "input_connector_id" uuid,
433
+ "input_connector_name" text,
434
+ "input_connector_type" text,
435
+ "input_connector_snapshot" jsonb DEFAULT '{}'::jsonb NOT NULL,
436
+ "status" text DEFAULT 'canary' NOT NULL,
437
+ "current_production_event_id" uuid,
438
+ "active_canary_event_id" uuid,
439
+ "created_by" uuid NOT NULL,
440
+ "created_at" timestamp with time zone DEFAULT now() NOT NULL,
441
+ "updated_at" timestamp with time zone DEFAULT now() NOT NULL,
442
+ "archived_at" timestamp with time zone,
443
+ CONSTRAINT "release_lines_status_check" CHECK ("ph_releases"."release_lines"."status" IN ('canary', 'production', 'production_with_canary', 'stopped', 'archived'))
444
+ );
445
+ --> statement-breakpoint
446
+ CREATE TABLE "ph_releases"."release_variants" (
447
+ "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
448
+ "project_id" uuid NOT NULL,
449
+ "release_line_id" uuid NOT NULL,
450
+ "variant_number" integer NOT NULL,
451
+ "prompt_id" uuid,
452
+ "prompt_name" text NOT NULL,
453
+ "prompt_version_id" uuid NOT NULL,
454
+ "prompt_version_number" integer,
455
+ "prompt_snapshot" jsonb DEFAULT '{}'::jsonb NOT NULL,
456
+ "prompt_version_snapshot" jsonb DEFAULT '{}'::jsonb NOT NULL,
457
+ "model_id" uuid NOT NULL,
458
+ "model_snapshot" jsonb DEFAULT '{}'::jsonb NOT NULL,
459
+ "created_by" uuid NOT NULL,
460
+ "created_at" timestamp with time zone DEFAULT now() NOT NULL,
461
+ "updated_at" timestamp with time zone DEFAULT now() NOT NULL,
462
+ CONSTRAINT "release_variants_number_positive_check" CHECK ("ph_releases"."release_variants"."variant_number" > 0)
463
+ );
464
+ --> statement-breakpoint
465
+ CREATE TABLE "ph_releases"."canary_releases" (
466
+ "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
467
+ "project_id" uuid NOT NULL,
468
+ "name" text,
469
+ "description" text,
470
+ "prompt_version_id" uuid NOT NULL,
471
+ "model_id" uuid NOT NULL,
472
+ "input_connector_id" uuid NOT NULL,
473
+ "output_connector_ids" uuid[] DEFAULT ARRAY[]::uuid[] NOT NULL,
474
+ "status" text DEFAULT 'pending' NOT NULL,
475
+ "control_state" text,
476
+ "control_state_payload" jsonb,
477
+ "traffic_ratio" numeric(5, 4) NOT NULL,
478
+ "traffic_mode" text DEFAULT 'split' NOT NULL,
479
+ "run_mode" text NOT NULL,
480
+ "stop_conditions" jsonb,
481
+ "record_mode" text DEFAULT 'all' NOT NULL,
482
+ "filter_rules" jsonb,
483
+ "variable_mapping" jsonb NOT NULL,
484
+ "output_mapping" jsonb DEFAULT '[]'::jsonb NOT NULL,
485
+ "external_id_field" text NOT NULL,
486
+ "annotation_schema" jsonb,
487
+ "storage_categories" text[] DEFAULT ARRAY[]::text[] NOT NULL,
488
+ "target_dataset_id" uuid,
489
+ "run_config" jsonb DEFAULT '{}'::jsonb NOT NULL,
490
+ "total_received" integer DEFAULT 0 NOT NULL,
491
+ "total_processed" integer DEFAULT 0 NOT NULL,
492
+ "total_filtered" integer DEFAULT 0 NOT NULL,
493
+ "total_correct" integer DEFAULT 0 NOT NULL,
494
+ "total_errors" integer DEFAULT 0 NOT NULL,
495
+ "metrics" jsonb,
496
+ "started_at" timestamp with time zone,
497
+ "finished_at" timestamp with time zone,
498
+ "created_by" uuid NOT NULL,
499
+ "created_at" timestamp with time zone DEFAULT now() NOT NULL,
500
+ "updated_at" timestamp with time zone DEFAULT now() NOT NULL,
501
+ "deleted_at" timestamp with time zone,
502
+ CONSTRAINT "canary_releases_status_check" CHECK ("ph_releases"."canary_releases"."status" IN ('pending', 'running', 'stopped', 'completed', 'failed', 'cancelled')),
503
+ CONSTRAINT "canary_releases_control_state_check" CHECK ("ph_releases"."canary_releases"."control_state" IN ('stop', 'resume', 'cancel', 'extend') OR "ph_releases"."canary_releases"."control_state" IS NULL),
504
+ CONSTRAINT "canary_releases_run_mode_check" CHECK ("ph_releases"."canary_releases"."run_mode" IN ('fixed_duration', 'manual')),
505
+ CONSTRAINT "canary_releases_traffic_mode_check" CHECK ("ph_releases"."canary_releases"."traffic_mode" IN ('split', 'dual_run')),
506
+ CONSTRAINT "canary_releases_record_mode_check" CHECK ("ph_releases"."canary_releases"."record_mode" IN ('all', 'correct_only')),
507
+ CONSTRAINT "canary_releases_traffic_ratio_check" CHECK ("ph_releases"."canary_releases"."traffic_ratio" >= 0 AND "ph_releases"."canary_releases"."traffic_ratio" <= 1)
508
+ );
509
+ --> statement-breakpoint
510
+ CREATE TABLE "ph_releases"."production_release_events" (
511
+ "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
512
+ "project_id" uuid NOT NULL,
513
+ "prompt_id" uuid NOT NULL,
514
+ "event_type" text NOT NULL,
515
+ "prompt_version_id" uuid NOT NULL,
516
+ "model_id" uuid NOT NULL,
517
+ "input_connector_id" uuid,
518
+ "output_connector_ids" uuid[] DEFAULT ARRAY[]::uuid[] NOT NULL,
519
+ "run_config" jsonb NOT NULL,
520
+ "variable_mapping" jsonb DEFAULT '{}'::jsonb NOT NULL,
521
+ "filter_rules" jsonb,
522
+ "record_mode" text DEFAULT 'all' NOT NULL,
523
+ "external_id_field" text,
524
+ "retention_days" integer,
525
+ "status" text DEFAULT 'running' NOT NULL,
526
+ "created_by" uuid NOT NULL,
527
+ "submit_reason" text NOT NULL,
528
+ "source_experiment_id" uuid,
529
+ "source_canary_id" uuid,
530
+ "source_metrics_snapshot" jsonb,
531
+ "prompt_snapshot" jsonb DEFAULT '{}'::jsonb NOT NULL,
532
+ "prompt_version_snapshot" jsonb DEFAULT '{}'::jsonb NOT NULL,
533
+ "rollback_target_event_id" uuid,
534
+ "control_state" text,
535
+ "started_at" timestamp with time zone,
536
+ "finished_at" timestamp with time zone,
537
+ "stop_reason" text,
538
+ "created_at" timestamp with time zone DEFAULT now() NOT NULL,
539
+ "updated_at" timestamp with time zone DEFAULT now() NOT NULL,
540
+ CONSTRAINT "production_release_events_event_type_check" CHECK ("ph_releases"."production_release_events"."event_type" IN ('from_prompt', 'from_experiment', 'from_canary', 'config_change', 'rollback', 'force_stop')),
541
+ CONSTRAINT "production_release_events_record_mode_check" CHECK ("ph_releases"."production_release_events"."record_mode" IN ('all', 'correct_only')),
542
+ CONSTRAINT "production_release_events_status_check" CHECK ("ph_releases"."production_release_events"."status" IN ('running', 'success', 'failed', 'stopped')),
543
+ CONSTRAINT "production_release_events_control_state_check" CHECK ("ph_releases"."production_release_events"."control_state" IN ('stop', 'resume', 'cancel') OR "ph_releases"."production_release_events"."control_state" IS NULL),
544
+ CONSTRAINT "production_release_events_stop_reason_check" CHECK ("ph_releases"."production_release_events"."stop_reason" IN ('replaced', 'rolled_back', 'force_stopped', 'error') OR "ph_releases"."production_release_events"."stop_reason" IS NULL),
545
+ CONSTRAINT "production_release_events_source_experiment_required" CHECK ("ph_releases"."production_release_events"."event_type" <> 'from_experiment' OR "ph_releases"."production_release_events"."source_experiment_id" IS NOT NULL),
546
+ CONSTRAINT "production_release_events_source_canary_required" CHECK ("ph_releases"."production_release_events"."event_type" <> 'from_canary' OR "ph_releases"."production_release_events"."source_canary_id" IS NOT NULL),
547
+ CONSTRAINT "production_release_events_rollback_target_required" CHECK ("ph_releases"."production_release_events"."event_type" <> 'rollback' OR "ph_releases"."production_release_events"."rollback_target_event_id" IS NOT NULL)
548
+ );
549
+ --> statement-breakpoint
550
+ CREATE TABLE "ph_releases"."annotation_tasks" (
551
+ "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
552
+ "scope" text NOT NULL,
553
+ "canary_id" uuid,
554
+ "production_release_event_id" uuid,
555
+ "release_line_event_id" uuid,
556
+ "release_variant_id" uuid,
557
+ "name" text NOT NULL,
558
+ "annotation_schema" jsonb NOT NULL,
559
+ "sampling_config" jsonb,
560
+ "total_sampled" integer DEFAULT 0 NOT NULL,
561
+ "total_annotated" integer DEFAULT 0 NOT NULL,
562
+ "status" text DEFAULT 'active' NOT NULL,
563
+ "created_by" uuid NOT NULL,
564
+ "created_at" timestamp with time zone DEFAULT now() NOT NULL,
565
+ "updated_at" timestamp with time zone DEFAULT now() NOT NULL,
566
+ CONSTRAINT "annotation_tasks_scope_check" CHECK ("ph_releases"."annotation_tasks"."scope" IN ('canary', 'online')),
567
+ CONSTRAINT "annotation_tasks_status_check" CHECK ("ph_releases"."annotation_tasks"."status" IN ('active', 'completed', 'archived')),
568
+ CONSTRAINT "annotation_tasks_scope_target_consistent" CHECK (("ph_releases"."annotation_tasks"."scope" = 'canary' AND "ph_releases"."annotation_tasks"."production_release_event_id" IS NULL AND ("ph_releases"."annotation_tasks"."release_variant_id" IS NOT NULL OR "ph_releases"."annotation_tasks"."release_line_event_id" IS NOT NULL OR "ph_releases"."annotation_tasks"."canary_id" IS NOT NULL))
569
+ OR ("ph_releases"."annotation_tasks"."scope" = 'online' AND "ph_releases"."annotation_tasks"."canary_id" IS NULL AND ("ph_releases"."annotation_tasks"."release_variant_id" IS NOT NULL OR "ph_releases"."annotation_tasks"."release_line_event_id" IS NOT NULL OR "ph_releases"."annotation_tasks"."production_release_event_id" IS NOT NULL)))
570
+ );
571
+ --> statement-breakpoint
572
+ ALTER TABLE "ph_core"."api_tokens" ADD CONSTRAINT "api_tokens_project_id_projects_id_fk" FOREIGN KEY ("project_id") REFERENCES "ph_core"."projects"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
573
+ ALTER TABLE "ph_assets"."connectors" ADD CONSTRAINT "connectors_project_id_projects_id_fk" FOREIGN KEY ("project_id") REFERENCES "ph_core"."projects"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
574
+ ALTER TABLE "ph_assets"."connectors" ADD CONSTRAINT "connectors_webhook_token_id_api_tokens_id_fk" FOREIGN KEY ("webhook_token_id") REFERENCES "ph_core"."api_tokens"("id") ON DELETE set null ON UPDATE no action;--> statement-breakpoint
575
+ ALTER TABLE "ph_assets"."dataset_samples" ADD CONSTRAINT "dataset_samples_dataset_id_datasets_id_fk" FOREIGN KEY ("dataset_id") REFERENCES "ph_assets"."datasets"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
576
+ ALTER TABLE "ph_assets"."datasets" ADD CONSTRAINT "datasets_project_id_projects_id_fk" FOREIGN KEY ("project_id") REFERENCES "ph_core"."projects"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
577
+ ALTER TABLE "ph_assets"."models" ADD CONSTRAINT "models_project_id_projects_id_fk" FOREIGN KEY ("project_id") REFERENCES "ph_core"."projects"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
578
+ ALTER TABLE "ph_assets"."prompt_version_labels" ADD CONSTRAINT "prompt_version_labels_prompt_id_prompts_id_fk" FOREIGN KEY ("prompt_id") REFERENCES "ph_assets"."prompts"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
579
+ ALTER TABLE "ph_assets"."prompt_version_labels" ADD CONSTRAINT "prompt_version_labels_version_id_prompt_versions_id_fk" FOREIGN KEY ("version_id") REFERENCES "ph_assets"."prompt_versions"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
580
+ ALTER TABLE "ph_assets"."prompt_versions" ADD CONSTRAINT "prompt_versions_prompt_id_prompts_id_fk" FOREIGN KEY ("prompt_id") REFERENCES "ph_assets"."prompts"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
581
+ ALTER TABLE "ph_assets"."prompts" ADD CONSTRAINT "prompts_project_id_projects_id_fk" FOREIGN KEY ("project_id") REFERENCES "ph_core"."projects"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
582
+ ALTER TABLE "ph_assets"."prompts" ADD CONSTRAINT "prompts_default_dataset_id_datasets_id_fk" FOREIGN KEY ("default_dataset_id") REFERENCES "ph_assets"."datasets"("id") ON DELETE restrict ON UPDATE no action;--> statement-breakpoint
583
+ ALTER TABLE "ph_runs"."annotations" ADD CONSTRAINT "annotations_task_id_annotation_tasks_id_fk" FOREIGN KEY ("task_id") REFERENCES "ph_releases"."annotation_tasks"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
584
+ ALTER TABLE "ph_runs"."experiments" ADD CONSTRAINT "experiments_project_id_projects_id_fk" FOREIGN KEY ("project_id") REFERENCES "ph_core"."projects"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
585
+ ALTER TABLE "ph_runs"."experiments" ADD CONSTRAINT "experiments_dataset_id_datasets_id_fk" FOREIGN KEY ("dataset_id") REFERENCES "ph_assets"."datasets"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
586
+ ALTER TABLE "ph_runs"."experiments" ADD CONSTRAINT "experiments_model_id_models_id_fk" FOREIGN KEY ("model_id") REFERENCES "ph_assets"."models"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
587
+ ALTER TABLE "ph_runs"."experiments" ADD CONSTRAINT "experiments_optimization_id_optimizations_id_fk" FOREIGN KEY ("optimization_id") REFERENCES "ph_runs"."optimizations"("id") ON DELETE set null ON UPDATE no action;--> statement-breakpoint
588
+ ALTER TABLE "ph_runs"."optimization_round_steps" ADD CONSTRAINT "optimization_round_steps_optimization_id_optimizations_id_fk" FOREIGN KEY ("optimization_id") REFERENCES "ph_runs"."optimizations"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
589
+ ALTER TABLE "ph_runs"."optimizations" ADD CONSTRAINT "optimizations_project_id_projects_id_fk" FOREIGN KEY ("project_id") REFERENCES "ph_core"."projects"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
590
+ ALTER TABLE "ph_runs"."optimizations" ADD CONSTRAINT "optimizations_source_experiment_id_experiments_id_fk" FOREIGN KEY ("source_experiment_id") REFERENCES "ph_runs"."experiments"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
591
+ ALTER TABLE "ph_runs"."optimizations" ADD CONSTRAINT "optimizations_dataset_id_datasets_id_fk" FOREIGN KEY ("dataset_id") REFERENCES "ph_assets"."datasets"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
592
+ ALTER TABLE "ph_runs"."optimizations" ADD CONSTRAINT "optimizations_experiment_model_id_models_id_fk" FOREIGN KEY ("experiment_model_id") REFERENCES "ph_assets"."models"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
593
+ ALTER TABLE "ph_runs"."optimizations" ADD CONSTRAINT "optimizations_analysis_model_id_models_id_fk" FOREIGN KEY ("analysis_model_id") REFERENCES "ph_assets"."models"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
594
+ ALTER TABLE "ph_runs"."run_results" ADD CONSTRAINT "run_results_project_id_projects_id_fk" FOREIGN KEY ("project_id") REFERENCES "ph_core"."projects"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
595
+ ALTER TABLE "ph_runs"."run_results" ADD CONSTRAINT "run_results_release_variant_id_release_variants_id_fk" FOREIGN KEY ("release_variant_id") REFERENCES "ph_releases"."release_variants"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
596
+ ALTER TABLE "ph_releases"."release_line_events" ADD CONSTRAINT "release_line_events_project_id_projects_id_fk" FOREIGN KEY ("project_id") REFERENCES "ph_core"."projects"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
597
+ ALTER TABLE "ph_releases"."release_line_events" ADD CONSTRAINT "release_line_events_release_line_id_release_lines_id_fk" FOREIGN KEY ("release_line_id") REFERENCES "ph_releases"."release_lines"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
598
+ ALTER TABLE "ph_releases"."release_line_events" ADD CONSTRAINT "release_line_events_release_variant_id_release_variants_id_fk" FOREIGN KEY ("release_variant_id") REFERENCES "ph_releases"."release_variants"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
599
+ ALTER TABLE "ph_releases"."release_line_events" ADD CONSTRAINT "release_line_events_model_id_models_id_fk" FOREIGN KEY ("model_id") REFERENCES "ph_assets"."models"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
600
+ ALTER TABLE "ph_releases"."release_line_events" ADD CONSTRAINT "release_line_events_input_connector_id_connectors_id_fk" FOREIGN KEY ("input_connector_id") REFERENCES "ph_assets"."connectors"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
601
+ ALTER TABLE "ph_releases"."release_line_events" ADD CONSTRAINT "release_line_events_source_experiment_id_experiments_id_fk" FOREIGN KEY ("source_experiment_id") REFERENCES "ph_runs"."experiments"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
602
+ ALTER TABLE "ph_releases"."release_lines" ADD CONSTRAINT "release_lines_project_id_projects_id_fk" FOREIGN KEY ("project_id") REFERENCES "ph_core"."projects"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
603
+ ALTER TABLE "ph_releases"."release_lines" ADD CONSTRAINT "release_lines_input_connector_id_connectors_id_fk" FOREIGN KEY ("input_connector_id") REFERENCES "ph_assets"."connectors"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
604
+ ALTER TABLE "ph_releases"."release_variants" ADD CONSTRAINT "release_variants_project_id_projects_id_fk" FOREIGN KEY ("project_id") REFERENCES "ph_core"."projects"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
605
+ ALTER TABLE "ph_releases"."release_variants" ADD CONSTRAINT "release_variants_release_line_id_release_lines_id_fk" FOREIGN KEY ("release_line_id") REFERENCES "ph_releases"."release_lines"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
606
+ ALTER TABLE "ph_releases"."release_variants" ADD CONSTRAINT "release_variants_model_id_models_id_fk" FOREIGN KEY ("model_id") REFERENCES "ph_assets"."models"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
607
+ ALTER TABLE "ph_releases"."canary_releases" ADD CONSTRAINT "canary_releases_project_id_projects_id_fk" FOREIGN KEY ("project_id") REFERENCES "ph_core"."projects"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
608
+ ALTER TABLE "ph_releases"."canary_releases" ADD CONSTRAINT "canary_releases_model_id_models_id_fk" FOREIGN KEY ("model_id") REFERENCES "ph_assets"."models"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
609
+ ALTER TABLE "ph_releases"."canary_releases" ADD CONSTRAINT "canary_releases_input_connector_id_connectors_id_fk" FOREIGN KEY ("input_connector_id") REFERENCES "ph_assets"."connectors"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
610
+ ALTER TABLE "ph_releases"."canary_releases" ADD CONSTRAINT "canary_releases_target_dataset_id_datasets_id_fk" FOREIGN KEY ("target_dataset_id") REFERENCES "ph_assets"."datasets"("id") ON DELETE set null ON UPDATE no action;--> statement-breakpoint
611
+ ALTER TABLE "ph_releases"."production_release_events" ADD CONSTRAINT "production_release_events_project_id_projects_id_fk" FOREIGN KEY ("project_id") REFERENCES "ph_core"."projects"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
612
+ ALTER TABLE "ph_releases"."production_release_events" ADD CONSTRAINT "production_release_events_model_id_models_id_fk" FOREIGN KEY ("model_id") REFERENCES "ph_assets"."models"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
613
+ ALTER TABLE "ph_releases"."production_release_events" ADD CONSTRAINT "production_release_events_input_connector_id_connectors_id_fk" FOREIGN KEY ("input_connector_id") REFERENCES "ph_assets"."connectors"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
614
+ ALTER TABLE "ph_releases"."production_release_events" ADD CONSTRAINT "production_release_events_source_experiment_id_experiments_id_fk" FOREIGN KEY ("source_experiment_id") REFERENCES "ph_runs"."experiments"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
615
+ ALTER TABLE "ph_releases"."production_release_events" ADD CONSTRAINT "production_release_events_source_canary_id_canary_releases_id_fk" FOREIGN KEY ("source_canary_id") REFERENCES "ph_releases"."canary_releases"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
616
+ ALTER TABLE "ph_releases"."production_release_events" ADD CONSTRAINT "production_release_events_rollback_target_event_id_production_release_events_id_fk" FOREIGN KEY ("rollback_target_event_id") REFERENCES "ph_releases"."production_release_events"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
617
+ ALTER TABLE "ph_releases"."annotation_tasks" ADD CONSTRAINT "annotation_tasks_canary_id_canary_releases_id_fk" FOREIGN KEY ("canary_id") REFERENCES "ph_releases"."canary_releases"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
618
+ ALTER TABLE "ph_releases"."annotation_tasks" ADD CONSTRAINT "annotation_tasks_production_release_event_id_production_release_events_id_fk" FOREIGN KEY ("production_release_event_id") REFERENCES "ph_releases"."production_release_events"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
619
+ ALTER TABLE "ph_releases"."annotation_tasks" ADD CONSTRAINT "annotation_tasks_release_line_event_id_release_line_events_id_fk" FOREIGN KEY ("release_line_event_id") REFERENCES "ph_releases"."release_line_events"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
620
+ ALTER TABLE "ph_releases"."annotation_tasks" ADD CONSTRAINT "annotation_tasks_release_variant_id_release_variants_id_fk" FOREIGN KEY ("release_variant_id") REFERENCES "ph_releases"."release_variants"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
621
+ CREATE INDEX "idx_api_tokens_project" ON "ph_core"."api_tokens" USING btree ("project_id") WHERE "ph_core"."api_tokens"."revoked_at" IS NULL;--> statement-breakpoint
622
+ CREATE INDEX "idx_api_tokens_active" ON "ph_core"."api_tokens" USING btree ("scope") WHERE "ph_core"."api_tokens"."revoked_at" IS NULL;--> statement-breakpoint
623
+ CREATE UNIQUE INDEX "uniq_active_global_mcp_token" ON "ph_core"."api_tokens" USING btree ("scope") WHERE "ph_core"."api_tokens"."scope" = 'global_mcp' AND "ph_core"."api_tokens"."revoked_at" IS NULL;--> statement-breakpoint
624
+ CREATE INDEX "idx_projects_active" ON "ph_core"."projects" USING btree ("status") WHERE "ph_core"."projects"."deleted_at" IS NULL;--> statement-breakpoint
625
+ CREATE UNIQUE INDEX "idx_connectors_project_name_active" ON "ph_assets"."connectors" USING btree ("project_id","name") WHERE "ph_assets"."connectors"."deleted_at" IS NULL;--> statement-breakpoint
626
+ CREATE UNIQUE INDEX "idx_connectors_webhook_path_active" ON "ph_assets"."connectors" USING btree ("project_id","webhook_path") WHERE "ph_assets"."connectors"."webhook_path" IS NOT NULL AND "ph_assets"."connectors"."deleted_at" IS NULL;--> statement-breakpoint
627
+ CREATE INDEX "idx_connectors_project" ON "ph_assets"."connectors" USING btree ("project_id") WHERE "ph_assets"."connectors"."deleted_at" IS NULL;--> statement-breakpoint
628
+ CREATE INDEX "idx_dataset_samples_dataset" ON "ph_assets"."dataset_samples" USING btree ("dataset_id");--> statement-breakpoint
629
+ CREATE INDEX "idx_dataset_samples_ext" ON "ph_assets"."dataset_samples" USING btree ("dataset_id","external_id") WHERE "ph_assets"."dataset_samples"."external_id" IS NOT NULL;--> statement-breakpoint
630
+ CREATE UNIQUE INDEX "idx_datasets_project_name_active" ON "ph_assets"."datasets" USING btree ("project_id","name") WHERE "ph_assets"."datasets"."deleted_at" IS NULL;--> statement-breakpoint
631
+ CREATE INDEX "idx_datasets_project" ON "ph_assets"."datasets" USING btree ("project_id") WHERE "ph_assets"."datasets"."deleted_at" IS NULL;--> statement-breakpoint
632
+ CREATE UNIQUE INDEX "idx_models_project_name_active" ON "ph_assets"."models" USING btree ("project_id","name") WHERE "ph_assets"."models"."deleted_at" IS NULL;--> statement-breakpoint
633
+ CREATE INDEX "idx_models_project" ON "ph_assets"."models" USING btree ("project_id") WHERE "ph_assets"."models"."deleted_at" IS NULL;--> statement-breakpoint
634
+ CREATE UNIQUE INDEX "uniq_prompt_version_labels_prompt_label" ON "ph_assets"."prompt_version_labels" USING btree ("prompt_id","label");--> statement-breakpoint
635
+ CREATE INDEX "idx_prompt_version_labels_version" ON "ph_assets"."prompt_version_labels" USING btree ("version_id");--> statement-breakpoint
636
+ CREATE INDEX "idx_prompt_versions_prompt" ON "ph_assets"."prompt_versions" USING btree ("prompt_id","version_number");--> statement-breakpoint
637
+ CREATE UNIQUE INDEX "idx_prompts_project_name_active" ON "ph_assets"."prompts" USING btree ("project_id","name") WHERE "ph_assets"."prompts"."deleted_at" IS NULL;--> statement-breakpoint
638
+ CREATE INDEX "idx_prompts_project" ON "ph_assets"."prompts" USING btree ("project_id") WHERE "ph_assets"."prompts"."deleted_at" IS NULL;--> statement-breakpoint
639
+ CREATE INDEX "idx_prompts_default_dataset" ON "ph_assets"."prompts" USING btree ("default_dataset_id") WHERE "ph_assets"."prompts"."default_dataset_id" IS NOT NULL AND "ph_assets"."prompts"."deleted_at" IS NULL;--> statement-breakpoint
640
+ CREATE UNIQUE INDEX "uniq_annotations_run_result_task" ON "ph_runs"."annotations" USING btree ("run_result_id","task_id");--> statement-breakpoint
641
+ CREATE INDEX "idx_annotations_run_result" ON "ph_runs"."annotations" USING btree ("run_result_id");--> statement-breakpoint
642
+ CREATE INDEX "idx_annotations_task" ON "ph_runs"."annotations" USING btree ("task_id") WHERE "ph_runs"."annotations"."task_id" IS NOT NULL;--> statement-breakpoint
643
+ CREATE INDEX "idx_annotations_lock_stale" ON "ph_runs"."annotations" USING btree ("task_id","lock_heartbeat_at") WHERE "ph_runs"."annotations"."locked_by" IS NOT NULL;--> statement-breakpoint
644
+ CREATE UNIQUE INDEX "idx_experiments_project_name_active" ON "ph_runs"."experiments" USING btree ("project_id","name") WHERE "ph_runs"."experiments"."deleted_at" IS NULL;--> statement-breakpoint
645
+ CREATE INDEX "idx_experiments_project_created" ON "ph_runs"."experiments" USING btree ("project_id","created_at") WHERE "ph_runs"."experiments"."deleted_at" IS NULL;--> statement-breakpoint
646
+ CREATE INDEX "idx_experiments_dbos" ON "ph_runs"."experiments" USING btree ("dbos_workflow_id") WHERE "ph_runs"."experiments"."dbos_workflow_id" IS NOT NULL;--> statement-breakpoint
647
+ CREATE INDEX "idx_experiments_status" ON "ph_runs"."experiments" USING btree ("project_id","status") WHERE "ph_runs"."experiments"."deleted_at" IS NULL;--> statement-breakpoint
648
+ CREATE UNIQUE INDEX "experiments_optimization_round_uq" ON "ph_runs"."experiments" USING btree ("optimization_id","round_index") WHERE "ph_runs"."experiments"."optimization_id" IS NOT NULL;--> statement-breakpoint
649
+ CREATE UNIQUE INDEX "optimization_round_steps_uq" ON "ph_runs"."optimization_round_steps" USING btree ("optimization_id","round_index","step");--> statement-breakpoint
650
+ CREATE INDEX "idx_optimization_round_steps_by_iter" ON "ph_runs"."optimization_round_steps" USING btree ("optimization_id","round_index");--> statement-breakpoint
651
+ CREATE UNIQUE INDEX "idx_optimization_project_name_active" ON "ph_runs"."optimizations" USING btree ("project_id","name") WHERE "ph_runs"."optimizations"."deleted_at" IS NULL;--> statement-breakpoint
652
+ CREATE INDEX "idx_optimization_project_created" ON "ph_runs"."optimizations" USING btree ("project_id","created_at") WHERE "ph_runs"."optimizations"."deleted_at" IS NULL;--> statement-breakpoint
653
+ CREATE INDEX "idx_optimization_dbos" ON "ph_runs"."optimizations" USING btree ("dbos_workflow_id") WHERE "ph_runs"."optimizations"."dbos_workflow_id" IS NOT NULL;--> statement-breakpoint
654
+ CREATE INDEX "idx_optimization_running" ON "ph_runs"."optimizations" USING btree ("project_id") WHERE "ph_runs"."optimizations"."status" = 'running';--> statement-breakpoint
655
+ CREATE INDEX "idx_run_results_project_source_time" ON "ph_runs"."run_results" USING btree ("project_id","source","source_id","created_at");--> statement-breakpoint
656
+ CREATE INDEX "idx_run_results_release_variant_time" ON "ph_runs"."run_results" USING btree ("project_id","release_variant_id","created_at") WHERE "ph_runs"."run_results"."release_variant_id" IS NOT NULL;--> statement-breakpoint
657
+ CREATE INDEX "idx_run_results_external_id" ON "ph_runs"."run_results" USING btree ("external_id") WHERE "ph_runs"."run_results"."external_id" IS NOT NULL;--> statement-breakpoint
658
+ CREATE INDEX "idx_run_results_dbos" ON "ph_runs"."run_results" USING btree ("dbos_workflow_id") WHERE "ph_runs"."run_results"."dbos_workflow_id" IS NOT NULL;--> statement-breakpoint
659
+ CREATE INDEX "idx_run_results_bullmq_job" ON "ph_runs"."run_results" USING btree ("bullmq_job_id") WHERE "ph_runs"."run_results"."bullmq_job_id" IS NOT NULL;--> statement-breakpoint
660
+ CREATE INDEX "idx_run_results_prompt_version" ON "ph_runs"."run_results" USING btree ("prompt_version_id","created_at");--> statement-breakpoint
661
+ CREATE INDEX "idx_run_results_id_lookup" ON "ph_runs"."run_results" USING btree ("id");--> statement-breakpoint
662
+ CREATE UNIQUE INDEX "uniq_release_line_event_legacy_source" ON "ph_releases"."release_line_events" USING btree ("project_id","legacy_source","legacy_source_id") WHERE "ph_releases"."release_line_events"."legacy_source" IS NOT NULL AND "ph_releases"."release_line_events"."legacy_source_id" IS NOT NULL;--> statement-breakpoint
663
+ CREATE UNIQUE INDEX "uniq_running_production_event_per_line" ON "ph_releases"."release_line_events" USING btree ("release_line_id") WHERE "ph_releases"."release_line_events"."lane_type" = 'production' AND "ph_releases"."release_line_events"."status" = 'running';--> statement-breakpoint
664
+ CREATE UNIQUE INDEX "uniq_active_canary_event_per_line" ON "ph_releases"."release_line_events" USING btree ("release_line_id") WHERE "ph_releases"."release_line_events"."lane_type" = 'canary' AND "ph_releases"."release_line_events"."status" IN ('running', 'stopped');--> statement-breakpoint
665
+ CREATE UNIQUE INDEX "uniq_running_production_event_per_prompt" ON "ph_releases"."release_line_events" USING btree ("prompt_id") WHERE "ph_releases"."release_line_events"."lane_type" = 'production' AND "ph_releases"."release_line_events"."status" = 'running' AND "ph_releases"."release_line_events"."prompt_id" IS NOT NULL;--> statement-breakpoint
666
+ CREATE INDEX "idx_release_line_events_line_created" ON "ph_releases"."release_line_events" USING btree ("release_line_id","created_at");--> statement-breakpoint
667
+ CREATE INDEX "idx_release_line_events_project_lane_status" ON "ph_releases"."release_line_events" USING btree ("project_id","lane_type","status","created_at");--> statement-breakpoint
668
+ CREATE INDEX "idx_release_line_events_project_prompt" ON "ph_releases"."release_line_events" USING btree ("project_id","prompt_id","created_at");--> statement-breakpoint
669
+ CREATE INDEX "idx_release_line_events_variant" ON "ph_releases"."release_line_events" USING btree ("release_variant_id");--> statement-breakpoint
670
+ CREATE UNIQUE INDEX "uniq_active_release_line_per_input_connector" ON "ph_releases"."release_lines" USING btree ("input_connector_id") WHERE "ph_releases"."release_lines"."status" <> 'archived' AND "ph_releases"."release_lines"."input_connector_id" IS NOT NULL;--> statement-breakpoint
671
+ CREATE UNIQUE INDEX "uniq_release_lines_project_name" ON "ph_releases"."release_lines" USING btree ("project_id","name");--> statement-breakpoint
672
+ CREATE INDEX "idx_release_lines_project_status" ON "ph_releases"."release_lines" USING btree ("project_id","status","updated_at");--> statement-breakpoint
673
+ CREATE INDEX "idx_release_lines_project_prompt" ON "ph_releases"."release_lines" USING btree ("project_id","prompt_id");--> statement-breakpoint
674
+ CREATE INDEX "idx_release_lines_project_input" ON "ph_releases"."release_lines" USING btree ("project_id","input_connector_id");--> statement-breakpoint
675
+ CREATE UNIQUE INDEX "uniq_release_variants_line_number" ON "ph_releases"."release_variants" USING btree ("release_line_id","variant_number");--> statement-breakpoint
676
+ CREATE UNIQUE INDEX "uniq_release_variants_line_prompt_model" ON "ph_releases"."release_variants" USING btree ("release_line_id","prompt_version_id","model_id");--> statement-breakpoint
677
+ CREATE INDEX "idx_release_variants_project_line" ON "ph_releases"."release_variants" USING btree ("project_id","release_line_id");--> statement-breakpoint
678
+ CREATE INDEX "idx_release_variants_project_prompt_model" ON "ph_releases"."release_variants" USING btree ("project_id","prompt_version_id","model_id");--> statement-breakpoint
679
+ CREATE UNIQUE INDEX "uniq_running_canary_per_input_connector" ON "ph_releases"."canary_releases" USING btree ("input_connector_id") WHERE "ph_releases"."canary_releases"."status" = 'running' AND "ph_releases"."canary_releases"."deleted_at" IS NULL;--> statement-breakpoint
680
+ CREATE INDEX "idx_canary_project_created" ON "ph_releases"."canary_releases" USING btree ("project_id","created_at") WHERE "ph_releases"."canary_releases"."deleted_at" IS NULL;--> statement-breakpoint
681
+ CREATE INDEX "idx_canary_status" ON "ph_releases"."canary_releases" USING btree ("project_id","status") WHERE "ph_releases"."canary_releases"."deleted_at" IS NULL;--> statement-breakpoint
682
+ CREATE INDEX "idx_canary_prompt_version" ON "ph_releases"."canary_releases" USING btree ("prompt_version_id");--> statement-breakpoint
683
+ CREATE UNIQUE INDEX "uniq_running_release_per_prompt" ON "ph_releases"."production_release_events" USING btree ("prompt_id") WHERE "ph_releases"."production_release_events"."status" = 'running';--> statement-breakpoint
684
+ CREATE UNIQUE INDEX "uniq_running_release_per_input_connector" ON "ph_releases"."production_release_events" USING btree ("input_connector_id") WHERE "ph_releases"."production_release_events"."status" = 'running' AND "ph_releases"."production_release_events"."input_connector_id" IS NOT NULL;--> statement-breakpoint
685
+ CREATE INDEX "idx_release_events_status_created" ON "ph_releases"."production_release_events" USING btree ("project_id","status","created_at");--> statement-breakpoint
686
+ CREATE INDEX "idx_release_events_prompt_created" ON "ph_releases"."production_release_events" USING btree ("project_id","prompt_id","created_at");--> statement-breakpoint
687
+ CREATE INDEX "idx_annotation_tasks_release_line_event" ON "ph_releases"."annotation_tasks" USING btree ("release_line_event_id");--> statement-breakpoint
688
+ CREATE INDEX "idx_annotation_tasks_release_variant" ON "ph_releases"."annotation_tasks" USING btree ("release_variant_id");