@kici-dev/orchestrator 0.4.0 → 0.5.0

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 (67) hide show
  1. package/dist/__test-helpers__/mock-db.d.ts +4 -0
  2. package/dist/agent/agent-version.d.ts +34 -0
  3. package/dist/agent/dispatcher.d.ts +70 -0
  4. package/dist/app.d.ts +23 -1
  5. package/dist/cache/global-eval-round-cache.d.ts +88 -0
  6. package/dist/cache/index.d.ts +3 -0
  7. package/dist/cache/pending-global-evals.d.ts +42 -0
  8. package/dist/cache/pending-inits.d.ts +10 -0
  9. package/dist/cli/commands/cluster-settings.d.ts +41 -3
  10. package/dist/cli/commands/runs.d.ts +1 -0
  11. package/dist/cli.js +1205 -620
  12. package/dist/cluster/cluster-settings-reader.d.ts +53 -1
  13. package/dist/config.d.ts +27 -0
  14. package/dist/content-requirements-cache.d.ts +55 -0
  15. package/dist/db/migrations/109_cluster_settings_cache_knobs.d.ts +4 -0
  16. package/dist/db/migrations/110_cluster_settings_global_eval_knobs.d.ts +4 -0
  17. package/dist/db/migrations/111_cluster_settings_global_eval_wait.d.ts +4 -0
  18. package/dist/db/migrations/112_execution_runs_workflow_repo.d.ts +4 -0
  19. package/dist/db/migrations/113_execution_runs_workflow_repo_index.d.ts +30 -0
  20. package/dist/db/migrations/114_ingest_queue_claim.d.ts +4 -0
  21. package/dist/db/migrations/115_global_workflows_cluster_switch.d.ts +9 -0
  22. package/dist/db/types.d.ts +60 -2
  23. package/dist/metrics/agent-metrics-aggregator.d.ts +2 -2
  24. package/dist/metrics/prometheus.d.ts +59 -0
  25. package/dist/orchestrator-core.d.ts +12 -1
  26. package/dist/pipeline/content-filter.d.ts +71 -0
  27. package/dist/pipeline/dispatch-matched-workflow.d.ts +247 -8
  28. package/dist/pipeline/global-eval-round.d.ts +293 -0
  29. package/dist/pipeline/job-contexts.d.ts +16 -17
  30. package/dist/pipeline/process-webhook.d.ts +7 -0
  31. package/dist/pipeline/processor.d.ts +56 -2
  32. package/dist/pipeline/route-or-dispatch-jobs.d.ts +6 -0
  33. package/dist/pipeline/test-pipeline.d.ts +12 -0
  34. package/dist/pipeline/webhook-payload-store.d.ts +20 -0
  35. package/dist/provenance/backfill-run.d.ts +10 -1
  36. package/dist/provider-registry.d.ts +38 -3
  37. package/dist/providers/github/check-status-poster.d.ts +22 -3
  38. package/dist/providers/github/commit-message.d.ts +20 -0
  39. package/dist/providers/github/file-contents.d.ts +40 -0
  40. package/dist/providers/github/index.d.ts +2 -0
  41. package/dist/providers/universal-git/config.d.ts +2 -0
  42. package/dist/providers/universal-git/normalizer.d.ts +10 -0
  43. package/dist/queue/cleanup.d.ts +7 -1
  44. package/dist/queue/job-queue.d.ts +69 -6
  45. package/dist/queue/terminalize-unroutable.d.ts +13 -0
  46. package/dist/registration/registration-run-match.d.ts +47 -0
  47. package/dist/reporting/check-run-reporter.d.ts +52 -1
  48. package/dist/reporting/execution-tracker.d.ts +117 -7
  49. package/dist/reporting/log-chunk-sink.d.ts +8 -5
  50. package/dist/routes/admin-org-settings.d.ts +5 -0
  51. package/dist/routes/admin.d.ts +6 -0
  52. package/dist/scaler/manager.d.ts +10 -8
  53. package/dist/security/global-workflow-policy.d.ts +52 -12
  54. package/dist/server.js +27553 -23779
  55. package/dist/standalone.js +5840 -2207
  56. package/dist/webhook/ingest-accept.d.ts +70 -0
  57. package/dist/webhook/ingest-overflow-buffer.d.ts +35 -4
  58. package/dist/webhook/ingest-overflow-replayer.d.ts +50 -6
  59. package/dist/ws/agent-handler.d.ts +3 -0
  60. package/dist/ws/dashboard-global-workflows-handler.d.ts +30 -9
  61. package/dist/ws/execution-status-frame.d.ts +32 -0
  62. package/dist/ws/platform-client.d.ts +14 -0
  63. package/dist/ws/test-relay-handlers.d.ts +35 -10
  64. package/installer-image-digests.json +3 -3
  65. package/package.json +4 -4
  66. package/sbom.spdx.json +57 -52
  67. package/dist/pipeline/inline-eval.d.ts +0 -44
package/dist/cli.js CHANGED
@@ -6,7 +6,7 @@ import path, { dirname, join, resolve } from "node:path";
6
6
  import * as fs$1 from "node:fs";
7
7
  import fs, { chmodSync, closeSync, constants, createReadStream, createWriteStream, existsSync, mkdirSync, mkdtempSync, openSync, promises, readFileSync, realpathSync, rmSync, statSync, unwatchFile, watchFile, writeFileSync } from "node:fs";
8
8
  import { Command, Option } from "commander";
9
- import { AgentPlatform, BaseColdStore, ChunkLru, addLogsToArchive, chunkObjectKey, clearDispatchQueueDirect, computeChunkId, computeMigrationsHash, createContextTemplateDirect, createDb, createDbRole, createLogger, createPool, createReadOnlyDbUser, createS3Client, decodeChunk, decrypt, deleteContextDirect, deriveKey, diagnoseExitCode, dropAndCreateDatabase, emitKiciEventDirect, encodeKeySegment, encrypt, ensureDatabase, formatBytes, formatUptime, isSchemaCurrent, kiciMkdtemp, listCheckRunTrackingDirect, listContextsDirect, listExecutionRunsDirect, listQueueDirect, listRegistrationsDirect, maskDatabaseUrl, parseDatabaseUrl, parseManifest, prunePeerCredentialsDirect, purgeContextsDirect, purgeScopedSecretsDirect, purgeSecretBackendsDirect, purgeStaleExecutionDirect, purgeStaleSourcesDirect, registerWorkflowManualDirect, resetRaftStateDirect, seedContextBindingDirect, seedContextDirect, setContextPolicyDirect, setContextSecretDirect, sha256, showContextDirect, showExecutionRunDirect, showQueueEntryDirect, showRegistrationDirect, splitAgentPlatform, storeMigrationContentHash, tablePrefix, toErrorMessage } from "@kici-dev/shared";
9
+ import { AgentPlatform, BaseColdStore, ChunkLru, addLogsToArchive, chunkObjectKey, clearDispatchQueueDirect, computeChunkId, computeMigrationsHash, createContextTemplateDirect, createDb, createDbRole, createLogger, createPool, createReadOnlyDbUser, createS3Client, decodeChunk, decrypt, deleteContextDirect, deriveKey, diagnoseExitCode, dropAndCreateDatabase, emitKiciEventDirect, encodeKeySegment, encrypt, ensureDatabase, formatBytes, formatUptime, isSchemaCurrent, kiciMkdtemp, listCheckRunTrackingDirect, listContextsDirect, listExecutionRunsDirect, listQueueDirect, listRegistrationsDirect, maskDatabaseUrl, parseDatabaseUrl, parseManifest, prunePeerCredentialsDirect, purgeContextsDirect, purgeScopedSecretsDirect, purgeSecretBackendsDirect, purgeStaleExecutionDirect, purgeStaleSourcesDirect, registerWorkflowManualDirect, resetRaftStateDirect, seedContextBindingDirect, seedContextDirect, serializeError, setContextPolicyDirect, setContextSecretDirect, sha256, showContextDirect, showExecutionRunDirect, showQueueEntryDirect, showRegistrationDirect, splitAgentPlatform, storeMigrationContentHash, tablePrefix, toErrorMessage } from "@kici-dev/shared";
10
10
  import { AccessLogSource, DEFAULT_APPROVAL_EXPIRY_HOURS, ExecutionJobStatus, KICI_AGENT_ENV_PREFIX, KNOWN_ROLES, OrchestratorMode, PLATFORM_CONNECTED_MODES, PRIVILEGED_ROOT_LABEL, ScalerBackendType, ScalerEventType, TERMINAL_JOB_STATES, TERMINAL_RUN_STATES, WS_MAX_PAYLOAD_BYTES, accessLogWarmSqlCase, agentLabelOf, assertValidSecretKey, attestationVerifyStatusSchema, flattenActor, getAccessLogColdDays, getSecretAuditLogColdDays, matcherSatisfiedBy, minAccessLogWarmDays, minSecretAuditLogWarmDays, parseHostPropertyAssignments, scalerAgentLabels, scalerPlatformSchema, secretAuditLogWarmSqlCase, shouldRecordAccess, shouldRecordSecretResolve } from "@kici-dev/engine";
11
11
  import crypto$1, { createDecipheriv, createHash, createHmac, createPublicKey, generateKeyPairSync, hkdfSync, randomBytes, randomUUID } from "node:crypto";
12
12
  import { createInterface } from "node:readline";
@@ -36,6 +36,7 @@ import { confirm, input, password, select } from "@inquirer/prompts";
36
36
  import JSZip from "jszip";
37
37
  import { pipeline } from "node:stream/promises";
38
38
  import { isCiEnvironment } from "@kici-dev/shared/ci-env";
39
+ import { setTimeout as setTimeout$1 } from "node:timers/promises";
39
40
  import { $ } from "zx";
40
41
  import "pg";
41
42
  import { DASHBOARD_WRITE_OPERATIONS, DASHBOARD_WRITE_OPERATIONS_BY_NAME, DashboardWriteCategory, DashboardWritePolicyState, DashboardWriteSensitivity } from "@kici-dev/engine/protocol/dashboard-write-operations";
@@ -2512,8 +2513,8 @@ server:
2512
2513
  //#endregion
2513
2514
  //#region src/db/migrations/001_initial.ts
2514
2515
  var _001_initial_exports = /* @__PURE__ */ __exportAll({
2515
- down: () => down$107,
2516
- up: () => up$107
2516
+ down: () => down$114,
2517
+ up: () => up$114
2517
2518
  });
2518
2519
  /**
2519
2520
  * Squashed initial migration -- creates the complete Orchestrator database schema.
@@ -3205,7 +3206,7 @@ const DDL_STATEMENTS = [
3205
3206
  `ALTER TABLE ONLY public.held_runs
3206
3207
  ADD CONSTRAINT held_runs_environment_id_fkey FOREIGN KEY (environment_id) REFERENCES public.environments(id);`
3207
3208
  ];
3208
- async function up$107(db) {
3209
+ async function up$114(db) {
3209
3210
  for (const stmt of DDL_STATEMENTS) await sql.raw(stmt).execute(db);
3210
3211
  await sql`
3211
3212
  INSERT INTO cluster_meta (key, value)
@@ -3227,7 +3228,7 @@ async function up$107(db) {
3227
3228
  * Rollback drops everything created above. Uses CASCADE on table drops to cut
3228
3229
  * through the FK graph without relying on exact topological order.
3229
3230
  */
3230
- async function down$107(db) {
3231
+ async function down$114(db) {
3231
3232
  for (const [trig, tbl] of [["source_secrets_change_trigger", "scoped_secrets"], ["sources_change_trigger", "sources"]]) await sql.raw(`DROP TRIGGER IF EXISTS ${trig} ON public.${tbl}`).execute(db);
3232
3233
  for (const table of [
3233
3234
  "workflow_registrations",
@@ -3274,8 +3275,8 @@ async function down$107(db) {
3274
3275
  //#endregion
3275
3276
  //#region src/db/migrations/002_config_versions_key_version.ts
3276
3277
  var _002_config_versions_key_version_exports = /* @__PURE__ */ __exportAll({
3277
- down: () => down$106,
3278
- up: () => up$106
3278
+ down: () => down$113,
3279
+ up: () => up$113
3279
3280
  });
3280
3281
  /**
3281
3282
  * Add key_version column to config_versions so that sensitive-field encryption
@@ -3289,13 +3290,13 @@ var _002_config_versions_key_version_exports = /* @__PURE__ */ __exportAll({
3289
3290
  * No index is needed: rotation does a full-table scan; reads are by
3290
3291
  * `version` primary key and never filter on `key_version`.
3291
3292
  */
3292
- async function up$106(db) {
3293
+ async function up$113(db) {
3293
3294
  await sql`
3294
3295
  ALTER TABLE public.config_versions
3295
3296
  ADD COLUMN key_version integer NOT NULL DEFAULT 1
3296
3297
  `.execute(db);
3297
3298
  }
3298
- async function down$106(db) {
3299
+ async function down$113(db) {
3299
3300
  await sql`
3300
3301
  ALTER TABLE public.config_versions
3301
3302
  DROP COLUMN key_version
@@ -3304,8 +3305,8 @@ async function down$106(db) {
3304
3305
  //#endregion
3305
3306
  //#region src/db/migrations/003_access_log.ts
3306
3307
  var _003_access_log_exports = /* @__PURE__ */ __exportAll({
3307
- down: () => down$105,
3308
- up: () => up$105
3308
+ down: () => down$112,
3309
+ up: () => up$112
3309
3310
  });
3310
3311
  /**
3311
3312
  * Access log: one row per read or orchestrator-admin mutation attributable
@@ -3329,7 +3330,7 @@ var _003_access_log_exports = /* @__PURE__ */ __exportAll({
3329
3330
  * Retention is TTL-based via expires_at; packages/orchestrator/src/queue/
3330
3331
  * cleanup.ts picks up the prune pass.
3331
3332
  */
3332
- async function up$105(db) {
3333
+ async function up$112(db) {
3333
3334
  await sql`
3334
3335
  CREATE TABLE public.access_log (
3335
3336
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
@@ -3367,28 +3368,28 @@ async function up$105(db) {
3367
3368
  ON public.access_log (actor_type, actor_id, created_at DESC)
3368
3369
  `.execute(db);
3369
3370
  }
3370
- async function down$105(db) {
3371
+ async function down$112(db) {
3371
3372
  await sql`DROP TABLE IF EXISTS public.access_log`.execute(db);
3372
3373
  }
3373
3374
  //#endregion
3374
3375
  //#region src/db/migrations/004_rename_bundle_to_source.ts
3375
3376
  var _004_rename_bundle_to_source_exports = /* @__PURE__ */ __exportAll({
3376
- down: () => down$104,
3377
- up: () => up$104
3377
+ down: () => down$111,
3378
+ up: () => up$111
3378
3379
  });
3379
- async function up$104(db) {
3380
+ async function up$111(db) {
3380
3381
  await db.schema.alterTable("dispatch_queue").renameColumn("bundle_url", "source_tar_url").execute();
3381
3382
  await db.schema.alterTable("dispatch_queue").renameColumn("bundle_hash", "source_tar_hash").execute();
3382
3383
  }
3383
- async function down$104(db) {
3384
+ async function down$111(db) {
3384
3385
  await db.schema.alterTable("dispatch_queue").renameColumn("source_tar_url", "bundle_url").execute();
3385
3386
  await db.schema.alterTable("dispatch_queue").renameColumn("source_tar_hash", "bundle_hash").execute();
3386
3387
  }
3387
3388
  //#endregion
3388
3389
  //#region src/db/migrations/005_cold_store_chunk_counter.ts
3389
3390
  var _005_cold_store_chunk_counter_exports = /* @__PURE__ */ __exportAll({
3390
- down: () => down$103,
3391
- up: () => up$103
3391
+ down: () => down$110,
3392
+ up: () => up$110
3392
3393
  });
3393
3394
  /**
3394
3395
  * Cold-store chunk counter table.
@@ -3405,7 +3406,7 @@ var _005_cold_store_chunk_counter_exports = /* @__PURE__ */ __exportAll({
3405
3406
  *
3406
3407
  * sections 5 and 8.
3407
3408
  */
3408
- async function up$103(db) {
3409
+ async function up$110(db) {
3409
3410
  await sql`
3410
3411
  CREATE TABLE public.cold_store_chunk_counts (
3411
3412
  db TEXT NOT NULL,
@@ -3423,14 +3424,14 @@ async function up$103(db) {
3423
3424
  ON public.cold_store_chunk_counts (db, table_name)
3424
3425
  `.execute(db);
3425
3426
  }
3426
- async function down$103(db) {
3427
+ async function down$110(db) {
3427
3428
  await sql`DROP TABLE IF EXISTS public.cold_store_chunk_counts`.execute(db);
3428
3429
  }
3429
3430
  //#endregion
3430
3431
  //#region src/db/migrations/006_runs_jobs_steps_archived_at.ts
3431
3432
  var _006_runs_jobs_steps_archived_at_exports = /* @__PURE__ */ __exportAll({
3432
- down: () => down$102,
3433
- up: () => up$102
3433
+ down: () => down$109,
3434
+ up: () => up$109
3434
3435
  });
3435
3436
  /**
3436
3437
  * `execution_runs` / `execution_jobs` / `execution_steps` cold-store
@@ -3466,7 +3467,7 @@ var _006_runs_jobs_steps_archived_at_exports = /* @__PURE__ */ __exportAll({
3466
3467
  * - `idx_execution_jobs_routing_key_created (routing_key, created_at)`
3467
3468
  * - `idx_execution_steps_routing_key_created (routing_key, created_at)`
3468
3469
  */
3469
- async function up$102(db) {
3470
+ async function up$109(db) {
3470
3471
  await sql`
3471
3472
  ALTER TABLE public.execution_runs
3472
3473
  ADD COLUMN archived_at TIMESTAMPTZ NULL,
@@ -3511,7 +3512,7 @@ async function up$102(db) {
3511
3512
  ON public.execution_steps (routing_key, created_at)
3512
3513
  `.execute(db);
3513
3514
  }
3514
- async function down$102(db) {
3515
+ async function down$109(db) {
3515
3516
  await sql`DROP INDEX IF EXISTS public.idx_execution_steps_routing_key_created`.execute(db);
3516
3517
  await sql`
3517
3518
  ALTER TABLE public.execution_steps
@@ -3536,8 +3537,8 @@ async function down$102(db) {
3536
3537
  //#endregion
3537
3538
  //#region src/db/migrations/007_audit_logs_archived_at.ts
3538
3539
  var _007_audit_logs_archived_at_exports = /* @__PURE__ */ __exportAll({
3539
- down: () => down$101,
3540
- up: () => up$101
3540
+ down: () => down$108,
3541
+ up: () => up$108
3541
3542
  });
3542
3543
  /**
3543
3544
  * `secret_audit_log` and `access_log` cold-store schema additions, plus
@@ -3577,7 +3578,7 @@ var _007_audit_logs_archived_at_exports = /* @__PURE__ */ __exportAll({
3577
3578
  * `down()` would not have meaningful retention bounds. Acceptable for
3578
3579
  * staging.
3579
3580
  */
3580
- async function up$101(db) {
3581
+ async function up$108(db) {
3581
3582
  await sql`
3582
3583
  ALTER TABLE public.secret_audit_log
3583
3584
  ADD COLUMN archived_at TIMESTAMPTZ NULL,
@@ -3598,7 +3599,7 @@ async function up$101(db) {
3598
3599
  DROP COLUMN IF EXISTS expires_at
3599
3600
  `.execute(db);
3600
3601
  }
3601
- async function down$101(db) {
3602
+ async function down$108(db) {
3602
3603
  await sql`
3603
3604
  ALTER TABLE public.access_log
3604
3605
  ADD COLUMN expires_at TIMESTAMPTZ NOT NULL DEFAULT (now() + INTERVAL '90 days')
@@ -3626,8 +3627,8 @@ async function down$101(db) {
3626
3627
  //#endregion
3627
3628
  //#region src/db/migrations/008_event_log_archived_at.ts
3628
3629
  var _008_event_log_archived_at_exports = /* @__PURE__ */ __exportAll({
3629
- down: () => down$100,
3630
- up: () => up$100
3630
+ down: () => down$107,
3631
+ up: () => up$107
3631
3632
  });
3632
3633
  /**
3633
3634
  * `event_log` cold-store schema additions plus removal of the
@@ -3665,7 +3666,7 @@ var _008_event_log_archived_at_exports = /* @__PURE__ */ __exportAll({
3665
3666
  * — best effort; rows inserted between `up()` and a hypothetical
3666
3667
  * `down()` would not have meaningful retention bounds.
3667
3668
  */
3668
- async function up$100(db) {
3669
+ async function up$107(db) {
3669
3670
  await sql`
3670
3671
  ALTER TABLE public.event_log
3671
3672
  ADD COLUMN archived_at TIMESTAMPTZ NULL,
@@ -3681,7 +3682,7 @@ async function up$100(db) {
3681
3682
  DROP COLUMN IF EXISTS expires_at
3682
3683
  `.execute(db);
3683
3684
  }
3684
- async function down$100(db) {
3685
+ async function down$107(db) {
3685
3686
  await sql`
3686
3687
  ALTER TABLE public.event_log
3687
3688
  ADD COLUMN expires_at TIMESTAMPTZ NOT NULL DEFAULT (now() + INTERVAL '30 days')
@@ -3700,8 +3701,8 @@ async function down$100(db) {
3700
3701
  //#endregion
3701
3702
  //#region src/db/migrations/009_access_log_trigram.ts
3702
3703
  var _009_access_log_trigram_exports = /* @__PURE__ */ __exportAll({
3703
- down: () => down$99,
3704
- up: () => up$99
3704
+ down: () => down$106,
3705
+ up: () => up$106
3705
3706
  });
3706
3707
  /**
3707
3708
  * Trigram (pg_trgm) index on access_log.error_message for the federated
@@ -3714,7 +3715,7 @@ var _009_access_log_trigram_exports = /* @__PURE__ */ __exportAll({
3714
3715
  * EXISTS` are both safe to re-run. No CONCURRENTLY because Kysely runs
3715
3716
  * migrations inside a transaction; the lock is brief on a sampled table.
3716
3717
  */
3717
- async function up$99(db) {
3718
+ async function up$106(db) {
3718
3719
  await sql`CREATE EXTENSION IF NOT EXISTS pg_trgm`.execute(db);
3719
3720
  await sql`
3720
3721
  CREATE INDEX IF NOT EXISTS access_log_error_message_trgm_idx
@@ -3723,14 +3724,14 @@ async function up$99(db) {
3723
3724
  WHERE error_message IS NOT NULL
3724
3725
  `.execute(db);
3725
3726
  }
3726
- async function down$99(db) {
3727
+ async function down$106(db) {
3727
3728
  await sql`DROP INDEX IF EXISTS public.access_log_error_message_trgm_idx`.execute(db);
3728
3729
  }
3729
3730
  //#endregion
3730
3731
  //#region src/db/migrations/010_cold_store_chunks.ts
3731
3732
  var _010_cold_store_chunks_exports = /* @__PURE__ */ __exportAll({
3732
- down: () => down$98,
3733
- up: () => up$98
3733
+ down: () => down$105,
3734
+ up: () => up$105
3734
3735
  });
3735
3736
  /**
3736
3737
  * Cold-store chunk index — Phase 2 (cold-store purge).
@@ -3762,7 +3763,7 @@ var _010_cold_store_chunks_exports = /* @__PURE__ */ __exportAll({
3762
3763
  * forever. Adapters that don't opt into per-bucket archival via
3763
3764
  * `coldTtlDays` don't insert here either.
3764
3765
  */
3765
- async function up$98(db) {
3766
+ async function up$105(db) {
3766
3767
  await sql`
3767
3768
  CREATE TABLE public.cold_store_chunks (
3768
3769
  db TEXT NOT NULL,
@@ -3789,14 +3790,14 @@ async function up$98(db) {
3789
3790
  ON public.cold_store_chunks (db, table_name, tenant_id, archived_at DESC)
3790
3791
  `.execute(db);
3791
3792
  }
3792
- async function down$98(db) {
3793
+ async function down$105(db) {
3793
3794
  await sql`DROP TABLE IF EXISTS public.cold_store_chunks`.execute(db);
3794
3795
  }
3795
3796
  //#endregion
3796
3797
  //#region src/db/migrations/011_drop_source_secrets_notify.ts
3797
3798
  var _011_drop_source_secrets_notify_exports = /* @__PURE__ */ __exportAll({
3798
- down: () => down$97,
3799
- up: () => up$97
3799
+ down: () => down$104,
3800
+ up: () => up$104
3800
3801
  });
3801
3802
  /**
3802
3803
  * Drop the `source_secrets_change_trigger` and the
@@ -3815,11 +3816,11 @@ var _011_drop_source_secrets_notify_exports = /* @__PURE__ */ __exportAll({
3815
3816
  * in `001_initial.ts`. They wake up no consumer until the `WebhookSecretManager`
3816
3817
  * is restored, so this migration is safe to roll back.
3817
3818
  */
3818
- async function up$97(db) {
3819
+ async function up$104(db) {
3819
3820
  await sql`DROP TRIGGER IF EXISTS source_secrets_change_trigger ON public.scoped_secrets`.execute(db);
3820
3821
  await sql`DROP FUNCTION IF EXISTS public.notify_source_secrets_change() CASCADE`.execute(db);
3821
3822
  }
3822
- async function down$97(db) {
3823
+ async function down$104(db) {
3823
3824
  await sql`
3824
3825
  CREATE OR REPLACE FUNCTION public.notify_source_secrets_change() RETURNS trigger
3825
3826
  LANGUAGE plpgsql
@@ -3858,8 +3859,8 @@ async function down$97(db) {
3858
3859
  //#endregion
3859
3860
  //#region src/db/migrations/012_peer_credentials_active_uniq.ts
3860
3861
  var _012_peer_credentials_active_uniq_exports = /* @__PURE__ */ __exportAll({
3861
- down: () => down$96,
3862
- up: () => up$96
3862
+ down: () => down$103,
3863
+ up: () => up$103
3863
3864
  });
3864
3865
  /**
3865
3866
  * Add a partial unique index on `peer_credentials (instance_id) WHERE
@@ -3885,7 +3886,7 @@ var _012_peer_credentials_active_uniq_exports = /* @__PURE__ */ __exportAll({
3885
3886
  * `down()` only drops the index; it does NOT undo the dedupe (there's no
3886
3887
  * safe way to recreate revoked rows, and the dedupe is monotonic).
3887
3888
  */
3888
- async function up$96(db) {
3889
+ async function up$103(db) {
3889
3890
  await sql`
3890
3891
  UPDATE public.peer_credentials
3891
3892
  SET revoked_at = NOW()
@@ -3903,14 +3904,14 @@ async function up$96(db) {
3903
3904
  WHERE revoked_at IS NULL
3904
3905
  `.execute(db);
3905
3906
  }
3906
- async function down$96(db) {
3907
+ async function down$103(db) {
3907
3908
  await sql`DROP INDEX IF EXISTS public.peer_credentials_active_uniq`.execute(db);
3908
3909
  }
3909
3910
  //#endregion
3910
3911
  //#region src/db/migrations/013_execution_log_bytes.ts
3911
3912
  var _013_execution_log_bytes_exports = /* @__PURE__ */ __exportAll({
3912
- down: () => down$95,
3913
- up: () => up$95
3913
+ down: () => down$102,
3914
+ up: () => up$102
3914
3915
  });
3915
3916
  /**
3916
3917
  * Add `log_bytes BIGINT NOT NULL DEFAULT 0` columns to `execution_runs` and
@@ -3929,7 +3930,7 @@ var _013_execution_log_bytes_exports = /* @__PURE__ */ __exportAll({
3929
3930
  *
3930
3931
  * Idempotent (`ADD COLUMN IF NOT EXISTS`).
3931
3932
  */
3932
- async function up$95(db) {
3933
+ async function up$102(db) {
3933
3934
  await sql`
3934
3935
  ALTER TABLE public.execution_runs
3935
3936
  ADD COLUMN IF NOT EXISTS log_bytes BIGINT NOT NULL DEFAULT 0
@@ -3939,15 +3940,15 @@ async function up$95(db) {
3939
3940
  ADD COLUMN IF NOT EXISTS log_bytes BIGINT NOT NULL DEFAULT 0
3940
3941
  `.execute(db);
3941
3942
  }
3942
- async function down$95(db) {
3943
+ async function down$102(db) {
3943
3944
  await sql`ALTER TABLE public.execution_runs DROP COLUMN IF EXISTS log_bytes`.execute(db);
3944
3945
  await sql`ALTER TABLE public.execution_jobs DROP COLUMN IF EXISTS log_bytes`.execute(db);
3945
3946
  }
3946
3947
  //#endregion
3947
3948
  //#region src/db/migrations/014_kici_events_lease_retry.ts
3948
3949
  var _014_kici_events_lease_retry_exports = /* @__PURE__ */ __exportAll({
3949
- down: () => down$94,
3950
- up: () => up$94
3950
+ down: () => down$101,
3951
+ up: () => up$101
3951
3952
  });
3952
3953
  /**
3953
3954
  * Add lease + retry + DLQ columns to `kici_events` so the EventRouter can
@@ -3981,7 +3982,7 @@ var _014_kici_events_lease_retry_exports = /* @__PURE__ */ __exportAll({
3981
3982
  *
3982
3983
  * Idempotent (`ADD COLUMN IF NOT EXISTS` + `CREATE INDEX IF NOT EXISTS`).
3983
3984
  */
3984
- async function up$94(db) {
3985
+ async function up$101(db) {
3985
3986
  await sql`
3986
3987
  ALTER TABLE public.kici_events
3987
3988
  ADD COLUMN IF NOT EXISTS claimed_at TIMESTAMPTZ,
@@ -4012,7 +4013,7 @@ async function up$94(db) {
4012
4013
  WHERE dlq_at IS NOT NULL
4013
4014
  `.execute(db);
4014
4015
  }
4015
- async function down$94(db) {
4016
+ async function down$101(db) {
4016
4017
  await sql`DROP INDEX IF EXISTS public.idx_kici_events_dlq`.execute(db);
4017
4018
  await sql`DROP INDEX IF EXISTS public.idx_kici_events_lease_expired`.execute(db);
4018
4019
  await sql`DROP INDEX IF EXISTS public.idx_kici_events_retry_due`.execute(db);
@@ -4030,8 +4031,8 @@ async function down$94(db) {
4030
4031
  //#endregion
4031
4032
  //#region src/db/migrations/015_org_settings_customer_scoped.ts
4032
4033
  var _015_org_settings_customer_scoped_exports = /* @__PURE__ */ __exportAll({
4033
- down: () => down$93,
4034
- up: () => up$93
4034
+ down: () => down$100,
4035
+ up: () => up$100
4035
4036
  });
4036
4037
  /**
4037
4038
  * Org-scope `org_settings` and qualify each glob entry by source.
@@ -4059,7 +4060,7 @@ var _015_org_settings_customer_scoped_exports = /* @__PURE__ */ __exportAll({
4059
4060
  * Idempotent: a re-run on an already-migrated DB sees `customer_id` exists
4060
4061
  * and the list columns are already jsonb, so it is a no-op.
4061
4062
  */
4062
- async function up$93(db) {
4063
+ async function up$100(db) {
4063
4064
  if ((await sql`
4064
4065
  SELECT EXISTS (
4065
4066
  SELECT 1 FROM information_schema.columns
@@ -4184,7 +4185,7 @@ async function up$93(db) {
4184
4185
  await sql`DROP TABLE _org_settings_merged`.execute(db);
4185
4186
  await sql`DROP TABLE _org_settings_stage`.execute(db);
4186
4187
  }
4187
- async function down$93(db) {
4188
+ async function down$100(db) {
4188
4189
  if (!(await sql`
4189
4190
  SELECT EXISTS (
4190
4191
  SELECT 1 FROM information_schema.columns
@@ -4209,8 +4210,8 @@ async function down$93(db) {
4209
4210
  //#endregion
4210
4211
  //#region src/db/migrations/016_org_settings_allow_http_npm.ts
4211
4212
  var _016_org_settings_allow_http_npm_exports = /* @__PURE__ */ __exportAll({
4212
- down: () => down$92,
4213
- up: () => up$92
4213
+ down: () => down$99,
4214
+ up: () => up$99
4214
4215
  });
4215
4216
  /**
4216
4217
  * Add `org_settings.allow_http_npm_registries boolean NOT NULL DEFAULT false`.
@@ -4223,7 +4224,7 @@ var _016_org_settings_allow_http_npm_exports = /* @__PURE__ */ __exportAll({
4223
4224
  *
4224
4225
  * Idempotent: a re-run on a DB that already has the column is a no-op.
4225
4226
  */
4226
- async function up$92(db) {
4227
+ async function up$99(db) {
4227
4228
  if ((await sql`
4228
4229
  SELECT EXISTS (
4229
4230
  SELECT 1 FROM information_schema.columns
@@ -4237,7 +4238,7 @@ async function up$92(db) {
4237
4238
  ADD COLUMN allow_http_npm_registries boolean NOT NULL DEFAULT false
4238
4239
  `.execute(db);
4239
4240
  }
4240
- async function down$92(db) {
4241
+ async function down$99(db) {
4241
4242
  await sql`
4242
4243
  ALTER TABLE public.org_settings DROP COLUMN IF EXISTS allow_http_npm_registries
4243
4244
  `.execute(db);
@@ -4245,8 +4246,8 @@ async function down$92(db) {
4245
4246
  //#endregion
4246
4247
  //#region src/db/migrations/017_org_id_widen.ts
4247
4248
  var _017_org_id_widen_exports = /* @__PURE__ */ __exportAll({
4248
- down: () => down$91,
4249
- up: () => up$91
4249
+ down: () => down$98,
4250
+ up: () => up$98
4250
4251
  });
4251
4252
  /**
4252
4253
  * Widen every orchestrator-side `org_id varchar(12)` column to
@@ -4286,17 +4287,17 @@ const ORG_ID_TABLES$1 = [
4286
4287
  "held_runs",
4287
4288
  "scoped_secrets"
4288
4289
  ];
4289
- async function up$91(db) {
4290
+ async function up$98(db) {
4290
4291
  for (const table of ORG_ID_TABLES$1) await sql.raw(`ALTER TABLE public.${table} ALTER COLUMN org_id TYPE varchar(16)`).execute(db);
4291
4292
  }
4292
- async function down$91(db) {
4293
+ async function down$98(db) {
4293
4294
  for (const table of ORG_ID_TABLES$1) await sql.raw(`ALTER TABLE public.${table} ALTER COLUMN org_id TYPE varchar(12)`).execute(db);
4294
4295
  }
4295
4296
  //#endregion
4296
4297
  //#region src/db/migrations/018_org_id_prefix_backfill.ts
4297
4298
  var _018_org_id_prefix_backfill_exports = /* @__PURE__ */ __exportAll({
4298
- down: () => down$90,
4299
- up: () => up$90
4299
+ down: () => down$97,
4300
+ up: () => up$97
4300
4301
  });
4301
4302
  /**
4302
4303
  * Prefix every orchestrator-side tenant string with `org_` to align
@@ -4341,19 +4342,19 @@ const CUSTOMER_ID_TABLES = [
4341
4342
  "workflow_registrations",
4342
4343
  "org_settings"
4343
4344
  ];
4344
- async function up$90(db) {
4345
+ async function up$97(db) {
4345
4346
  for (const table of ORG_ID_TABLES) await sql.raw(`UPDATE public.${table} SET org_id = 'org_' || org_id WHERE org_id <> 'kici-admin' AND org_id NOT LIKE 'org\\_%' ESCAPE '\\'`).execute(db);
4346
4347
  for (const table of CUSTOMER_ID_TABLES) await sql.raw(`UPDATE public.${table} SET customer_id = 'org_' || customer_id WHERE customer_id <> 'kici-admin' AND customer_id NOT LIKE 'org\\_%' ESCAPE '\\'`).execute(db);
4347
4348
  }
4348
- async function down$90(db) {
4349
+ async function down$97(db) {
4349
4350
  for (const table of CUSTOMER_ID_TABLES) await sql.raw(`UPDATE public.${table} SET customer_id = substring(customer_id from 5) WHERE customer_id LIKE 'org\\_%' ESCAPE '\\'`).execute(db);
4350
4351
  for (const table of ORG_ID_TABLES) await sql.raw(`UPDATE public.${table} SET org_id = substring(org_id from 5) WHERE org_id LIKE 'org\\_%' ESCAPE '\\'`).execute(db);
4351
4352
  }
4352
4353
  //#endregion
4353
4354
  //#region src/db/migrations/019_generic_sources_change_notify.ts
4354
4355
  var _019_generic_sources_change_notify_exports = /* @__PURE__ */ __exportAll({
4355
- down: () => down$89,
4356
- up: () => up$89
4356
+ down: () => down$96,
4357
+ up: () => up$96
4357
4358
  });
4358
4359
  /**
4359
4360
  * Add a Postgres trigger on `generic_webhook_sources` that emits
@@ -4376,7 +4377,7 @@ var _019_generic_sources_change_notify_exports = /* @__PURE__ */ __exportAll({
4376
4377
  * (`notify_sources_change()` + `sources_change_trigger`, defined in
4377
4378
  * `001_initial.ts`).
4378
4379
  */
4379
- async function up$89(db) {
4380
+ async function up$96(db) {
4380
4381
  await sql`
4381
4382
  CREATE FUNCTION public.notify_generic_sources_change() RETURNS trigger
4382
4383
  LANGUAGE plpgsql
@@ -4397,15 +4398,15 @@ async function up$89(db) {
4397
4398
  FOR EACH ROW EXECUTE FUNCTION public.notify_generic_sources_change()
4398
4399
  `.execute(db);
4399
4400
  }
4400
- async function down$89(db) {
4401
+ async function down$96(db) {
4401
4402
  await sql`DROP TRIGGER IF EXISTS generic_sources_change_trigger ON public.generic_webhook_sources`.execute(db);
4402
4403
  await sql`DROP FUNCTION IF EXISTS public.notify_generic_sources_change()`.execute(db);
4403
4404
  }
4404
4405
  //#endregion
4405
4406
  //#region src/db/migrations/020_org_settings_dashboard_write_policy.ts
4406
4407
  var _020_org_settings_dashboard_write_policy_exports = /* @__PURE__ */ __exportAll({
4407
- down: () => down$88,
4408
- up: () => up$88
4408
+ down: () => down$95,
4409
+ up: () => up$95
4409
4410
  });
4410
4411
  /**
4411
4412
  * Add `org_settings.dashboard_write_policy jsonb NOT NULL DEFAULT '{}'`.
@@ -4420,7 +4421,7 @@ var _020_org_settings_dashboard_write_policy_exports = /* @__PURE__ */ __exportA
4420
4421
  *
4421
4422
  * Idempotent: a re-run on a DB that already has the column is a no-op.
4422
4423
  */
4423
- async function up$88(db) {
4424
+ async function up$95(db) {
4424
4425
  if ((await sql`
4425
4426
  SELECT EXISTS (
4426
4427
  SELECT 1 FROM information_schema.columns
@@ -4434,7 +4435,7 @@ async function up$88(db) {
4434
4435
  ADD COLUMN dashboard_write_policy jsonb NOT NULL DEFAULT '{}'::jsonb
4435
4436
  `.execute(db);
4436
4437
  }
4437
- async function down$88(db) {
4438
+ async function down$95(db) {
4438
4439
  await sql`
4439
4440
  ALTER TABLE public.org_settings DROP COLUMN IF EXISTS dashboard_write_policy
4440
4441
  `.execute(db);
@@ -4442,8 +4443,8 @@ async function down$88(db) {
4442
4443
  //#endregion
4443
4444
  //#region src/db/migrations/021_check_run_tracking.ts
4444
4445
  var _021_check_run_tracking_exports = /* @__PURE__ */ __exportAll({
4445
- down: () => down$87,
4446
- up: () => up$87
4446
+ down: () => down$94,
4447
+ up: () => up$94
4447
4448
  });
4448
4449
  /**
4449
4450
  * Add `check_run_tracking` table for HA-safe check-run state persistence.
@@ -4467,7 +4468,7 @@ var _021_check_run_tracking_exports = /* @__PURE__ */ __exportAll({
4467
4468
  *
4468
4469
  * Idempotent: a re-run on a DB that already has the table is a no-op.
4469
4470
  */
4470
- async function up$87(db) {
4471
+ async function up$94(db) {
4471
4472
  if ((await sql`
4472
4473
  SELECT EXISTS (
4473
4474
  SELECT 1 FROM information_schema.tables
@@ -4498,14 +4499,14 @@ async function up$87(db) {
4498
4499
  WHERE run_id IS NOT NULL
4499
4500
  `.execute(db);
4500
4501
  }
4501
- async function down$87(db) {
4502
+ async function down$94(db) {
4502
4503
  await sql`DROP TABLE IF EXISTS public.check_run_tracking`.execute(db);
4503
4504
  }
4504
4505
  //#endregion
4505
4506
  //#region src/db/migrations/022_scaler_manager_state.ts
4506
4507
  var _022_scaler_manager_state_exports = /* @__PURE__ */ __exportAll({
4507
- down: () => down$86,
4508
- up: () => up$86
4508
+ down: () => down$93,
4509
+ up: () => up$93
4509
4510
  });
4510
4511
  /**
4511
4512
  * Add three tables persisting `ScalerManager` per-coord state:
@@ -4532,7 +4533,7 @@ var _022_scaler_manager_state_exports = /* @__PURE__ */ __exportAll({
4532
4533
  * Idempotent: a re-run on a DB that already has any of these tables
4533
4534
  * leaves the existing one alone.
4534
4535
  */
4535
- async function up$86(db) {
4536
+ async function up$93(db) {
4536
4537
  const tableExists = async (name) => {
4537
4538
  return (await sql`
4538
4539
  SELECT EXISTS (
@@ -4582,7 +4583,7 @@ async function up$86(db) {
4582
4583
  `.execute(db);
4583
4584
  }
4584
4585
  }
4585
- async function down$86(db) {
4586
+ async function down$93(db) {
4586
4587
  await sql`DROP TABLE IF EXISTS public.scaler_reservations`.execute(db);
4587
4588
  await sql`DROP TABLE IF EXISTS public.scaler_agent_jobs`.execute(db);
4588
4589
  await sql`DROP TABLE IF EXISTS public.scaler_spawning_agents`.execute(db);
@@ -4590,8 +4591,8 @@ async function down$86(db) {
4590
4591
  //#endregion
4591
4592
  //#region src/db/migrations/023_dispatch_queue_recovery_deadline.ts
4592
4593
  var _023_dispatch_queue_recovery_deadline_exports = /* @__PURE__ */ __exportAll({
4593
- down: () => down$85,
4594
- up: () => up$85
4594
+ down: () => down$92,
4595
+ up: () => up$92
4595
4596
  });
4596
4597
  /**
4597
4598
  * Add `dispatch_queue.recovery_deadline TIMESTAMPTZ` and
@@ -4615,7 +4616,7 @@ var _023_dispatch_queue_recovery_deadline_exports = /* @__PURE__ */ __exportAll(
4615
4616
  * Idempotent: re-running on a DB that already has either column is a
4616
4617
  * no-op.
4617
4618
  */
4618
- async function up$85(db) {
4619
+ async function up$92(db) {
4619
4620
  const colExists = async (name) => {
4620
4621
  return (await sql`
4621
4622
  SELECT EXISTS (
@@ -4640,7 +4641,7 @@ async function up$85(db) {
4640
4641
  WHERE recovery_deadline IS NOT NULL
4641
4642
  `.execute(db);
4642
4643
  }
4643
- async function down$85(db) {
4644
+ async function down$92(db) {
4644
4645
  await sql`DROP INDEX IF EXISTS public.idx_dispatch_queue_recovery_deadline`.execute(db);
4645
4646
  await sql`
4646
4647
  ALTER TABLE public.dispatch_queue DROP COLUMN IF EXISTS recovery_agent_id
@@ -4652,8 +4653,8 @@ async function down$85(db) {
4652
4653
  //#endregion
4653
4654
  //#region src/db/migrations/024_dispatch_queue_provisioning_error.ts
4654
4655
  var _024_dispatch_queue_provisioning_error_exports = /* @__PURE__ */ __exportAll({
4655
- down: () => down$84,
4656
- up: () => up$84
4656
+ down: () => down$91,
4657
+ up: () => up$91
4657
4658
  });
4658
4659
  /**
4659
4660
  * Add `dispatch_queue.last_provisioning_error TEXT` recording the most
@@ -4669,7 +4670,7 @@ var _024_dispatch_queue_provisioning_error_exports = /* @__PURE__ */ __exportAll
4669
4670
  *
4670
4671
  * Idempotent: re-running on a DB that already has the column is a no-op.
4671
4672
  */
4672
- async function up$84(db) {
4673
+ async function up$91(db) {
4673
4674
  const colExists = async (name) => {
4674
4675
  return (await sql`
4675
4676
  SELECT EXISTS (
@@ -4685,7 +4686,7 @@ async function up$84(db) {
4685
4686
  ADD COLUMN last_provisioning_error TEXT
4686
4687
  `.execute(db);
4687
4688
  }
4688
- async function down$84(db) {
4689
+ async function down$91(db) {
4689
4690
  await sql`
4690
4691
  ALTER TABLE public.dispatch_queue DROP COLUMN IF EXISTS last_provisioning_error
4691
4692
  `.execute(db);
@@ -4693,8 +4694,8 @@ async function down$84(db) {
4693
4694
  //#endregion
4694
4695
  //#region src/db/migrations/025_init_failure.ts
4695
4696
  var _025_init_failure_exports = /* @__PURE__ */ __exportAll({
4696
- down: () => down$83,
4697
- up: () => up$83
4697
+ down: () => down$90,
4698
+ up: () => up$90
4698
4699
  });
4699
4700
  /**
4700
4701
  * Add `init_failure jsonb` columns to `execution_runs` and `execution_jobs`.
@@ -4708,7 +4709,7 @@ var _025_init_failure_exports = /* @__PURE__ */ __exportAll({
4708
4709
  * Idempotent: re-running on a DB that already has either column is a no-op
4709
4710
  * for that column.
4710
4711
  */
4711
- async function up$83(db) {
4712
+ async function up$90(db) {
4712
4713
  const colExists = async (table, name) => {
4713
4714
  return (await sql`
4714
4715
  SELECT EXISTS (
@@ -4728,7 +4729,7 @@ async function up$83(db) {
4728
4729
  ADD COLUMN init_failure JSONB DEFAULT NULL
4729
4730
  `.execute(db);
4730
4731
  }
4731
- async function down$83(db) {
4732
+ async function down$90(db) {
4732
4733
  await sql`
4733
4734
  ALTER TABLE public.execution_jobs DROP COLUMN IF EXISTS init_failure
4734
4735
  `.execute(db);
@@ -4739,8 +4740,8 @@ async function down$83(db) {
4739
4740
  //#endregion
4740
4741
  //#region src/db/migrations/026_event_log_lockfile_corrupt.ts
4741
4742
  var _026_event_log_lockfile_corrupt_exports = /* @__PURE__ */ __exportAll({
4742
- down: () => down$82,
4743
- up: () => up$82
4743
+ down: () => down$89,
4744
+ up: () => up$89
4744
4745
  });
4745
4746
  /**
4746
4747
  * Extend the event_log.status CHECK constraint with 'lockfile_corrupt' so the
@@ -4749,7 +4750,7 @@ var _026_event_log_lockfile_corrupt_exports = /* @__PURE__ */ __exportAll({
4749
4750
  *
4750
4751
  * Idempotent: the DROP ... IF EXISTS / re-ADD pair re-runs cleanly.
4751
4752
  */
4752
- async function up$82(db) {
4753
+ async function up$89(db) {
4753
4754
  await sql`ALTER TABLE event_log DROP CONSTRAINT IF EXISTS event_log_status_check`.execute(db);
4754
4755
  await sql`
4755
4756
  ALTER TABLE event_log ADD CONSTRAINT event_log_status_check
@@ -4759,7 +4760,7 @@ async function up$82(db) {
4759
4760
  ])))
4760
4761
  `.execute(db);
4761
4762
  }
4762
- async function down$82(db) {
4763
+ async function down$89(db) {
4763
4764
  await sql`ALTER TABLE event_log DROP CONSTRAINT IF EXISTS event_log_status_check`.execute(db);
4764
4765
  await sql`
4765
4766
  ALTER TABLE event_log ADD CONSTRAINT event_log_status_check
@@ -4772,8 +4773,8 @@ async function down$82(db) {
4772
4773
  //#endregion
4773
4774
  //#region src/db/migrations/027_workflow_timeout.ts
4774
4775
  var _027_workflow_timeout_exports = /* @__PURE__ */ __exportAll({
4775
- down: () => down$81,
4776
- up: () => up$81
4776
+ down: () => down$88,
4777
+ up: () => up$88
4777
4778
  });
4778
4779
  /**
4779
4780
  * Add `workflow_timeout_ms integer` to `execution_runs`.
@@ -4791,13 +4792,13 @@ var _027_workflow_timeout_exports = /* @__PURE__ */ __exportAll({
4791
4792
  *
4792
4793
  * Idempotent: re-running on a DB that already has the column is a no-op.
4793
4794
  */
4794
- async function up$81(db) {
4795
+ async function up$88(db) {
4795
4796
  await sql`
4796
4797
  ALTER TABLE public.execution_runs
4797
4798
  ADD COLUMN IF NOT EXISTS workflow_timeout_ms INTEGER DEFAULT NULL
4798
4799
  `.execute(db);
4799
4800
  }
4800
- async function down$81(db) {
4801
+ async function down$88(db) {
4801
4802
  await sql`
4802
4803
  ALTER TABLE public.execution_runs DROP COLUMN IF EXISTS workflow_timeout_ms
4803
4804
  `.execute(db);
@@ -4805,8 +4806,8 @@ async function down$81(db) {
4805
4806
  //#endregion
4806
4807
  //#region src/db/migrations/028_org_settings_user_cache.ts
4807
4808
  var _028_org_settings_user_cache_exports = /* @__PURE__ */ __exportAll({
4808
- down: () => down$80,
4809
- up: () => up$80
4809
+ down: () => down$87,
4810
+ up: () => up$87
4810
4811
  });
4811
4812
  /**
4812
4813
  * Add `org_settings.user_cache_quota_bytes bigint` and
@@ -4825,7 +4826,7 @@ var _028_org_settings_user_cache_exports = /* @__PURE__ */ __exportAll({
4825
4826
  *
4826
4827
  * Idempotent: a re-run on a DB that already has either column skips it.
4827
4828
  */
4828
- async function columnExists$6(db, column) {
4829
+ async function columnExists$11(db, column) {
4829
4830
  return (await sql`
4830
4831
  SELECT EXISTS (
4831
4832
  SELECT 1 FROM information_schema.columns
@@ -4835,17 +4836,17 @@ async function columnExists$6(db, column) {
4835
4836
  ) AS exists
4836
4837
  `.execute(db)).rows[0]?.exists ?? false;
4837
4838
  }
4838
- async function up$80(db) {
4839
- if (!await columnExists$6(db, "user_cache_quota_bytes")) await sql`
4839
+ async function up$87(db) {
4840
+ if (!await columnExists$11(db, "user_cache_quota_bytes")) await sql`
4840
4841
  ALTER TABLE public.org_settings
4841
4842
  ADD COLUMN user_cache_quota_bytes bigint
4842
4843
  `.execute(db);
4843
- if (!await columnExists$6(db, "user_cache_ttl_ms")) await sql`
4844
+ if (!await columnExists$11(db, "user_cache_ttl_ms")) await sql`
4844
4845
  ALTER TABLE public.org_settings
4845
4846
  ADD COLUMN user_cache_ttl_ms bigint
4846
4847
  `.execute(db);
4847
4848
  }
4848
- async function down$80(db) {
4849
+ async function down$87(db) {
4849
4850
  await sql`
4850
4851
  ALTER TABLE public.org_settings DROP COLUMN IF EXISTS user_cache_quota_bytes
4851
4852
  `.execute(db);
@@ -4856,8 +4857,8 @@ async function down$80(db) {
4856
4857
  //#endregion
4857
4858
  //#region src/db/migrations/029_dispatch_queue_attempts.ts
4858
4859
  var _029_dispatch_queue_attempts_exports = /* @__PURE__ */ __exportAll({
4859
- down: () => down$79,
4860
- up: () => up$79
4860
+ down: () => down$86,
4861
+ up: () => up$86
4861
4862
  });
4862
4863
  /**
4863
4864
  * Add `dispatch_queue.dispatch_attempts INT NOT NULL DEFAULT 0`.
@@ -4871,7 +4872,7 @@ var _029_dispatch_queue_attempts_exports = /* @__PURE__ */ __exportAll({
4871
4872
  *
4872
4873
  * Idempotent: re-running on a DB that already has the column is a no-op.
4873
4874
  */
4874
- async function up$79(db) {
4875
+ async function up$86(db) {
4875
4876
  if (!((await sql`
4876
4877
  SELECT EXISTS (
4877
4878
  SELECT 1 FROM information_schema.columns
@@ -4884,7 +4885,7 @@ async function up$79(db) {
4884
4885
  ADD COLUMN dispatch_attempts INT NOT NULL DEFAULT 0
4885
4886
  `.execute(db);
4886
4887
  }
4887
- async function down$79(db) {
4888
+ async function down$86(db) {
4888
4889
  await sql`
4889
4890
  ALTER TABLE public.dispatch_queue DROP COLUMN IF EXISTS dispatch_attempts
4890
4891
  `.execute(db);
@@ -4892,8 +4893,8 @@ async function down$79(db) {
4892
4893
  //#endregion
4893
4894
  //#region src/db/migrations/030_held_runs_env_set_null.ts
4894
4895
  var _030_held_runs_env_set_null_exports = /* @__PURE__ */ __exportAll({
4895
- down: () => down$78,
4896
- up: () => up$78
4896
+ down: () => down$85,
4897
+ up: () => up$85
4897
4898
  });
4898
4899
  /**
4899
4900
  * held_runs.environment_id becomes nullable with ON DELETE SET NULL so
@@ -4904,14 +4905,14 @@ var _030_held_runs_env_set_null_exports = /* @__PURE__ */ __exportAll({
4904
4905
  * Idempotent: dropping the NOT NULL and the constraint are both no-ops on a
4905
4906
  * re-run, and the constraint is re-created with the SET NULL action.
4906
4907
  */
4907
- async function up$78(db) {
4908
+ async function up$85(db) {
4908
4909
  await sql`ALTER TABLE public.held_runs ALTER COLUMN environment_id DROP NOT NULL`.execute(db);
4909
4910
  await sql`ALTER TABLE public.held_runs DROP CONSTRAINT IF EXISTS held_runs_environment_id_fkey`.execute(db);
4910
4911
  await sql`ALTER TABLE public.held_runs
4911
4912
  ADD CONSTRAINT held_runs_environment_id_fkey
4912
4913
  FOREIGN KEY (environment_id) REFERENCES public.environments(id) ON DELETE SET NULL`.execute(db);
4913
4914
  }
4914
- async function down$78(db) {
4915
+ async function down$85(db) {
4915
4916
  await sql`ALTER TABLE public.held_runs DROP CONSTRAINT IF EXISTS held_runs_environment_id_fkey`.execute(db);
4916
4917
  await sql`ALTER TABLE public.held_runs
4917
4918
  ADD CONSTRAINT held_runs_environment_id_fkey
@@ -4921,8 +4922,8 @@ async function down$78(db) {
4921
4922
  //#endregion
4922
4923
  //#region src/db/migrations/031_dispatch_queue_ack_deadline.ts
4923
4924
  var _031_dispatch_queue_ack_deadline_exports = /* @__PURE__ */ __exportAll({
4924
- down: () => down$77,
4925
- up: () => up$77
4925
+ down: () => down$84,
4926
+ up: () => up$84
4926
4927
  });
4927
4928
  /**
4928
4929
  * Add `dispatch_queue.ack_deadline TIMESTAMPTZ` and
@@ -4939,7 +4940,7 @@ var _031_dispatch_queue_ack_deadline_exports = /* @__PURE__ */ __exportAll({
4939
4940
  *
4940
4941
  * Idempotent: re-running on a DB that already has either column is a no-op.
4941
4942
  */
4942
- async function up$77(db) {
4943
+ async function up$84(db) {
4943
4944
  const colExists = async (name) => {
4944
4945
  return (await sql`
4945
4946
  SELECT EXISTS (
@@ -4964,7 +4965,7 @@ async function up$77(db) {
4964
4965
  WHERE ack_deadline IS NOT NULL
4965
4966
  `.execute(db);
4966
4967
  }
4967
- async function down$77(db) {
4968
+ async function down$84(db) {
4968
4969
  await sql`DROP INDEX IF EXISTS public.idx_dispatch_queue_ack_deadline`.execute(db);
4969
4970
  await sql`ALTER TABLE public.dispatch_queue DROP COLUMN IF EXISTS ack_agent_id`.execute(db);
4970
4971
  await sql`ALTER TABLE public.dispatch_queue DROP COLUMN IF EXISTS ack_deadline`.execute(db);
@@ -4972,8 +4973,8 @@ async function down$77(db) {
4972
4973
  //#endregion
4973
4974
  //#region src/db/migrations/032_org_settings_dispatch_ack_timeout.ts
4974
4975
  var _032_org_settings_dispatch_ack_timeout_exports = /* @__PURE__ */ __exportAll({
4975
- down: () => down$76,
4976
- up: () => up$76
4976
+ down: () => down$83,
4977
+ up: () => up$83
4977
4978
  });
4978
4979
  /**
4979
4980
  * Add `org_settings.dispatch_ack_timeout_ms BIGINT` (nullable).
@@ -4985,7 +4986,7 @@ var _032_org_settings_dispatch_ack_timeout_exports = /* @__PURE__ */ __exportAll
4985
4986
  *
4986
4987
  * Idempotent: a re-run on a DB that already has the column is a no-op.
4987
4988
  */
4988
- async function up$76(db) {
4989
+ async function up$83(db) {
4989
4990
  if ((await sql`
4990
4991
  SELECT EXISTS (
4991
4992
  SELECT 1 FROM information_schema.columns
@@ -4999,7 +5000,7 @@ async function up$76(db) {
4999
5000
  ADD COLUMN dispatch_ack_timeout_ms BIGINT
5000
5001
  `.execute(db);
5001
5002
  }
5002
- async function down$76(db) {
5003
+ async function down$83(db) {
5003
5004
  await sql`
5004
5005
  ALTER TABLE public.org_settings DROP COLUMN IF EXISTS dispatch_ack_timeout_ms
5005
5006
  `.execute(db);
@@ -5007,8 +5008,8 @@ async function down$76(db) {
5007
5008
  //#endregion
5008
5009
  //#region src/db/migrations/033_org_settings_approval.ts
5009
5010
  var _033_org_settings_approval_exports = /* @__PURE__ */ __exportAll({
5010
- down: () => down$75,
5011
- up: () => up$75
5011
+ down: () => down$82,
5012
+ up: () => up$82
5012
5013
  });
5013
5014
  /**
5014
5015
  * Add the two approval-policy columns to `org_settings`:
@@ -5025,7 +5026,7 @@ var _033_org_settings_approval_exports = /* @__PURE__ */ __exportAll({
5025
5026
  * and the orchestrator admin route. Idempotent: a re-run on a DB that already
5026
5027
  * has the columns is a no-op (each column is guarded independently).
5027
5028
  */
5028
- async function up$75(db) {
5029
+ async function up$82(db) {
5029
5030
  const colExists = async (column) => {
5030
5031
  return (await sql`
5031
5032
  SELECT EXISTS (
@@ -5045,7 +5046,7 @@ async function up$75(db) {
5045
5046
  ADD COLUMN allow_self_approval BOOLEAN NOT NULL DEFAULT true
5046
5047
  `.execute(db);
5047
5048
  }
5048
- async function down$75(db) {
5049
+ async function down$82(db) {
5049
5050
  await sql`
5050
5051
  ALTER TABLE public.org_settings DROP COLUMN IF EXISTS approval_expiry_seconds
5051
5052
  `.execute(db);
@@ -5056,8 +5057,8 @@ async function down$75(db) {
5056
5057
  //#endregion
5057
5058
  //#region src/db/migrations/034_held_runs_generalize.ts
5058
5059
  var _034_held_runs_generalize_exports = /* @__PURE__ */ __exportAll({
5059
- down: () => down$74,
5060
- up: () => up$74
5060
+ down: () => down$81,
5061
+ up: () => up$81
5061
5062
  });
5062
5063
  /**
5063
5064
  * Generalize `held_runs` from an environment-only hold into the unified
@@ -5079,7 +5080,7 @@ var _034_held_runs_generalize_exports = /* @__PURE__ */ __exportAll({
5079
5080
  * New `held_run_approvals` table: one row per approver decision, FK to
5080
5081
  * `held_runs.id` (uuid) with ON DELETE CASCADE.
5081
5082
  */
5082
- async function up$74(db) {
5083
+ async function up$81(db) {
5083
5084
  const colExists = async (column) => {
5084
5085
  return (await sql`
5085
5086
  SELECT EXISTS (
@@ -5112,7 +5113,7 @@ async function up$74(db) {
5112
5113
  ON public.held_run_approvals USING btree (held_run_id)
5113
5114
  `.execute(db);
5114
5115
  }
5115
- async function down$74(db) {
5116
+ async function down$81(db) {
5116
5117
  await sql`DROP TABLE IF EXISTS public.held_run_approvals`.execute(db);
5117
5118
  await sql`ALTER TABLE public.held_runs DROP COLUMN IF EXISTS approval_requirement`.execute(db);
5118
5119
  await sql`ALTER TABLE public.held_runs DROP COLUMN IF EXISTS trigger_source`.execute(db);
@@ -5122,8 +5123,8 @@ async function down$74(db) {
5122
5123
  //#endregion
5123
5124
  //#region src/db/migrations/035_pending_workflow_contexts.ts
5124
5125
  var _035_pending_workflow_contexts_exports = /* @__PURE__ */ __exportAll({
5125
- down: () => down$73,
5126
- up: () => up$73
5126
+ down: () => down$80,
5127
+ up: () => up$80
5127
5128
  });
5128
5129
  /**
5129
5130
  * Pending workflow dispatch context — backs resume of a workflow whose install
@@ -5132,7 +5133,7 @@ var _035_pending_workflow_contexts_exports = /* @__PURE__ */ __exportAll({
5132
5133
  * wait-timer expiry, concurrency slot free). The row is deleted once the resume
5133
5134
  * dispatch has been kicked off.
5134
5135
  */
5135
- async function up$73(db) {
5136
+ async function up$80(db) {
5136
5137
  await sql`
5137
5138
  CREATE TABLE IF NOT EXISTS public.pending_workflow_contexts (
5138
5139
  run_id text PRIMARY KEY,
@@ -5142,15 +5143,15 @@ async function up$73(db) {
5142
5143
  )
5143
5144
  `.execute(db);
5144
5145
  }
5145
- async function down$73(db) {
5146
+ async function down$80(db) {
5146
5147
  await sql`DROP TABLE IF EXISTS public.pending_workflow_contexts`.execute(db);
5147
5148
  }
5148
5149
  //#endregion
5149
5150
  //#region src/db/migrations/036_attestations.ts
5150
5151
  var _036_attestations_exports = /* @__PURE__ */ __exportAll({
5151
- down: () => down$72,
5152
- up: () => up$72
5153
- });
5152
+ down: () => down$79,
5153
+ up: () => up$79
5154
+ });
5154
5155
  /**
5155
5156
  * Add the `attestations` table for build-provenance bundles.
5156
5157
  *
@@ -5162,7 +5163,7 @@ var _036_attestations_exports = /* @__PURE__ */ __exportAll({
5162
5163
  *
5163
5164
  * Idempotent: a re-run on a DB that already has the table is a no-op.
5164
5165
  */
5165
- async function up$72(db) {
5166
+ async function up$79(db) {
5166
5167
  if ((await sql`
5167
5168
  SELECT EXISTS (
5168
5169
  SELECT 1 FROM information_schema.tables
@@ -5188,14 +5189,14 @@ async function up$72(db) {
5188
5189
  ON public.attestations (run_id, job_id)
5189
5190
  `.execute(db);
5190
5191
  }
5191
- async function down$72(db) {
5192
+ async function down$79(db) {
5192
5193
  await sql`DROP TABLE IF EXISTS public.attestations`.execute(db);
5193
5194
  }
5194
5195
  //#endregion
5195
5196
  //#region src/db/migrations/037_generic_sources_provider_type_local.ts
5196
5197
  var _037_generic_sources_provider_type_local_exports = /* @__PURE__ */ __exportAll({
5197
- down: () => down$71,
5198
- up: () => up$71
5198
+ down: () => down$78,
5199
+ up: () => up$78
5199
5200
  });
5200
5201
  /**
5201
5202
  * Replace the `generic_webhook_sources.provider_type` CHECK constraint so it
@@ -5212,7 +5213,7 @@ var _037_generic_sources_provider_type_local_exports = /* @__PURE__ */ __exportA
5212
5213
  * Idempotent: the constraint is dropped IF EXISTS and recreated; the data
5213
5214
  * backfill is a plain UPDATE that is a no-op once no `'internal'` rows remain.
5214
5215
  */
5215
- async function up$71(db) {
5216
+ async function up$78(db) {
5216
5217
  await sql`
5217
5218
  ALTER TABLE public.generic_webhook_sources
5218
5219
  DROP CONSTRAINT IF EXISTS generic_webhook_sources_provider_type_check
@@ -5228,7 +5229,7 @@ async function up$71(db) {
5228
5229
  CHECK (provider_type = ANY (ARRAY['generic'::text, 'local'::text]))
5229
5230
  `.execute(db);
5230
5231
  }
5231
- async function down$71(db) {
5232
+ async function down$78(db) {
5232
5233
  await sql`
5233
5234
  ALTER TABLE public.generic_webhook_sources
5234
5235
  DROP CONSTRAINT IF EXISTS generic_webhook_sources_provider_type_check
@@ -5247,8 +5248,8 @@ async function down$71(db) {
5247
5248
  //#endregion
5248
5249
  //#region src/db/migrations/038_remote_sources.ts
5249
5250
  var _038_remote_sources_exports = /* @__PURE__ */ __exportAll({
5250
- down: () => down$70,
5251
- up: () => up$70
5251
+ down: () => down$77,
5252
+ up: () => up$77
5252
5253
  });
5253
5254
  /**
5254
5255
  * `remote_sources` anchors a Platform-relayed `kici run remote` to its real
@@ -5260,7 +5261,7 @@ var _038_remote_sources_exports = /* @__PURE__ */ __exportAll({
5260
5261
  *
5261
5262
  * Idempotent: a re-run on a DB that already has the table is a no-op.
5262
5263
  */
5263
- async function up$70(db) {
5264
+ async function up$77(db) {
5264
5265
  if ((await sql`
5265
5266
  SELECT EXISTS (
5266
5267
  SELECT 1 FROM information_schema.tables
@@ -5279,14 +5280,14 @@ async function up$70(db) {
5279
5280
  )
5280
5281
  `.execute(db);
5281
5282
  }
5282
- async function down$70(db) {
5283
+ async function down$77(db) {
5283
5284
  await sql`DROP TABLE IF EXISTS public.remote_sources`.execute(db);
5284
5285
  }
5285
5286
  //#endregion
5286
5287
  //#region src/db/migrations/039_host_roster.ts
5287
5288
  var _039_host_roster_exports = /* @__PURE__ */ __exportAll({
5288
- down: () => down$69,
5289
- up: () => up$69
5289
+ down: () => down$76,
5290
+ up: () => up$76
5290
5291
  });
5291
5292
  /**
5292
5293
  * `host_roster` is KiCI's declared inventory: one durable row per agent the
@@ -5303,7 +5304,7 @@ var _039_host_roster_exports = /* @__PURE__ */ __exportAll({
5303
5304
  *
5304
5305
  * Idempotent: a re-run on a DB that already has the table is a no-op.
5305
5306
  */
5306
- async function up$69(db) {
5307
+ async function up$76(db) {
5307
5308
  if ((await sql`
5308
5309
  SELECT EXISTS (
5309
5310
  SELECT 1 FROM information_schema.tables
@@ -5333,14 +5334,14 @@ async function up$69(db) {
5333
5334
  await sql`CREATE INDEX idx_host_roster_reap
5334
5335
  ON public.host_roster (lifecycle_class, last_seen)`.execute(db);
5335
5336
  }
5336
- async function down$69(db) {
5337
+ async function down$76(db) {
5337
5338
  await sql`DROP TABLE IF EXISTS public.host_roster`.execute(db);
5338
5339
  }
5339
5340
  //#endregion
5340
5341
  //#region src/db/migrations/040_runsonall_pin.ts
5341
5342
  var _040_runsonall_pin_exports = /* @__PURE__ */ __exportAll({
5342
- down: () => down$68,
5343
- up: () => up$68
5343
+ down: () => down$75,
5344
+ up: () => up$75
5344
5345
  });
5345
5346
  /**
5346
5347
  * Add the `runsOnAll` host fan-out columns:
@@ -5357,7 +5358,7 @@ var _040_runsonall_pin_exports = /* @__PURE__ */ __exportAll({
5357
5358
  *
5358
5359
  * Idempotent: re-running on a DB that already has any column is a no-op.
5359
5360
  */
5360
- async function colExists$12(db, table, name) {
5361
+ async function colExists$13(db, table, name) {
5361
5362
  return (await sql`
5362
5363
  SELECT EXISTS (
5363
5364
  SELECT 1 FROM information_schema.columns
@@ -5367,18 +5368,18 @@ async function colExists$12(db, table, name) {
5367
5368
  ) AS exists
5368
5369
  `.execute(db)).rows[0]?.exists ?? false;
5369
5370
  }
5370
- async function up$68(db) {
5371
- if (!await colExists$12(db, "dispatch_queue", "pinned_agent_id")) await sql`ALTER TABLE public.dispatch_queue ADD COLUMN pinned_agent_id TEXT`.execute(db);
5372
- if (!await colExists$12(db, "execution_jobs", "base_job_name")) await sql`ALTER TABLE public.execution_jobs ADD COLUMN base_job_name TEXT`.execute(db);
5373
- if (!await colExists$12(db, "execution_jobs", "variant_kind")) await sql`ALTER TABLE public.execution_jobs ADD COLUMN variant_kind TEXT`.execute(db);
5374
- if (!await colExists$12(db, "execution_jobs", "variant_label")) await sql`ALTER TABLE public.execution_jobs ADD COLUMN variant_label TEXT`.execute(db);
5371
+ async function up$75(db) {
5372
+ if (!await colExists$13(db, "dispatch_queue", "pinned_agent_id")) await sql`ALTER TABLE public.dispatch_queue ADD COLUMN pinned_agent_id TEXT`.execute(db);
5373
+ if (!await colExists$13(db, "execution_jobs", "base_job_name")) await sql`ALTER TABLE public.execution_jobs ADD COLUMN base_job_name TEXT`.execute(db);
5374
+ if (!await colExists$13(db, "execution_jobs", "variant_kind")) await sql`ALTER TABLE public.execution_jobs ADD COLUMN variant_kind TEXT`.execute(db);
5375
+ if (!await colExists$13(db, "execution_jobs", "variant_label")) await sql`ALTER TABLE public.execution_jobs ADD COLUMN variant_label TEXT`.execute(db);
5375
5376
  await sql`
5376
5377
  CREATE INDEX IF NOT EXISTS idx_dispatch_queue_pinned_agent
5377
5378
  ON public.dispatch_queue (pinned_agent_id)
5378
5379
  WHERE pinned_agent_id IS NOT NULL
5379
5380
  `.execute(db);
5380
5381
  }
5381
- async function down$68(db) {
5382
+ async function down$75(db) {
5382
5383
  await sql`DROP INDEX IF EXISTS public.idx_dispatch_queue_pinned_agent`.execute(db);
5383
5384
  await sql`ALTER TABLE public.dispatch_queue DROP COLUMN IF EXISTS pinned_agent_id`.execute(db);
5384
5385
  await sql`ALTER TABLE public.execution_jobs DROP COLUMN IF EXISTS variant_label`.execute(db);
@@ -5388,8 +5389,8 @@ async function down$68(db) {
5388
5389
  //#endregion
5389
5390
  //#region src/db/migrations/041_wave_gated.ts
5390
5391
  var _041_wave_gated_exports = /* @__PURE__ */ __exportAll({
5391
- down: () => down$67,
5392
- up: () => up$67
5392
+ down: () => down$74,
5393
+ up: () => up$74
5393
5394
  });
5394
5395
  /**
5395
5396
  * Add the rolling fan-out wave-gate columns:
@@ -5409,7 +5410,7 @@ var _041_wave_gated_exports = /* @__PURE__ */ __exportAll({
5409
5410
  *
5410
5411
  * Idempotent: re-running on a DB that already has the columns is a no-op.
5411
5412
  */
5412
- async function colExists$11(db, table, name) {
5413
+ async function colExists$12(db, table, name) {
5413
5414
  return (await sql`
5414
5415
  SELECT EXISTS (
5415
5416
  SELECT 1 FROM information_schema.columns
@@ -5419,16 +5420,16 @@ async function colExists$11(db, table, name) {
5419
5420
  ) AS exists
5420
5421
  `.execute(db)).rows[0]?.exists ?? false;
5421
5422
  }
5422
- async function up$67(db) {
5423
- if (!await colExists$11(db, "execution_jobs", "wave_gated")) await sql`ALTER TABLE public.execution_jobs ADD COLUMN wave_gated boolean NOT NULL DEFAULT false`.execute(db);
5424
- if (!await colExists$11(db, "execution_jobs", "wave_max_parallel")) await sql`ALTER TABLE public.execution_jobs ADD COLUMN wave_max_parallel integer`.execute(db);
5425
- if (!await colExists$11(db, "execution_jobs", "wave_fail_fast")) await sql`ALTER TABLE public.execution_jobs ADD COLUMN wave_fail_fast boolean`.execute(db);
5423
+ async function up$74(db) {
5424
+ if (!await colExists$12(db, "execution_jobs", "wave_gated")) await sql`ALTER TABLE public.execution_jobs ADD COLUMN wave_gated boolean NOT NULL DEFAULT false`.execute(db);
5425
+ if (!await colExists$12(db, "execution_jobs", "wave_max_parallel")) await sql`ALTER TABLE public.execution_jobs ADD COLUMN wave_max_parallel integer`.execute(db);
5426
+ if (!await colExists$12(db, "execution_jobs", "wave_fail_fast")) await sql`ALTER TABLE public.execution_jobs ADD COLUMN wave_fail_fast boolean`.execute(db);
5426
5427
  await sql`
5427
5428
  CREATE INDEX IF NOT EXISTS idx_execution_jobs_wave
5428
5429
  ON public.execution_jobs (run_id, base_job_name, wave_gated)
5429
5430
  `.execute(db);
5430
5431
  }
5431
- async function down$67(db) {
5432
+ async function down$74(db) {
5432
5433
  await sql`DROP INDEX IF EXISTS public.idx_execution_jobs_wave`.execute(db);
5433
5434
  await sql`ALTER TABLE public.execution_jobs DROP COLUMN IF EXISTS wave_fail_fast`.execute(db);
5434
5435
  await sql`ALTER TABLE public.execution_jobs DROP COLUMN IF EXISTS wave_max_parallel`.execute(db);
@@ -5437,8 +5438,8 @@ async function down$67(db) {
5437
5438
  //#endregion
5438
5439
  //#region src/db/migrations/042_dispatch_queue_patterns.ts
5439
5440
  var _042_dispatch_queue_patterns_exports = /* @__PURE__ */ __exportAll({
5440
- down: () => down$66,
5441
- up: () => up$66
5441
+ down: () => down$73,
5442
+ up: () => up$73
5442
5443
  });
5443
5444
  /**
5444
5445
  * Add pattern columns to dispatch_queue. Exact labels stay in runs_on_labels /
@@ -5454,7 +5455,7 @@ var _042_dispatch_queue_patterns_exports = /* @__PURE__ */ __exportAll({
5454
5455
  *
5455
5456
  * Idempotent: re-running on a DB that already has the columns is a no-op.
5456
5457
  */
5457
- async function colExists$10(db, table, name) {
5458
+ async function colExists$11(db, table, name) {
5458
5459
  return (await sql`
5459
5460
  SELECT EXISTS (
5460
5461
  SELECT 1 FROM information_schema.columns
@@ -5464,19 +5465,19 @@ async function colExists$10(db, table, name) {
5464
5465
  ) AS exists
5465
5466
  `.execute(db)).rows[0]?.exists ?? false;
5466
5467
  }
5467
- async function up$66(db) {
5468
- if (!await colExists$10(db, "dispatch_queue", "runs_on_patterns")) await sql`ALTER TABLE public.dispatch_queue ADD COLUMN runs_on_patterns jsonb NOT NULL DEFAULT '[]'::jsonb`.execute(db);
5469
- if (!await colExists$10(db, "dispatch_queue", "exclude_patterns")) await sql`ALTER TABLE public.dispatch_queue ADD COLUMN exclude_patterns jsonb NOT NULL DEFAULT '[]'::jsonb`.execute(db);
5468
+ async function up$73(db) {
5469
+ if (!await colExists$11(db, "dispatch_queue", "runs_on_patterns")) await sql`ALTER TABLE public.dispatch_queue ADD COLUMN runs_on_patterns jsonb NOT NULL DEFAULT '[]'::jsonb`.execute(db);
5470
+ if (!await colExists$11(db, "dispatch_queue", "exclude_patterns")) await sql`ALTER TABLE public.dispatch_queue ADD COLUMN exclude_patterns jsonb NOT NULL DEFAULT '[]'::jsonb`.execute(db);
5470
5471
  }
5471
- async function down$66(db) {
5472
+ async function down$73(db) {
5472
5473
  await sql`ALTER TABLE public.dispatch_queue DROP COLUMN IF EXISTS exclude_patterns`.execute(db);
5473
5474
  await sql`ALTER TABLE public.dispatch_queue DROP COLUMN IF EXISTS runs_on_patterns`.execute(db);
5474
5475
  }
5475
5476
  //#endregion
5476
5477
  //#region src/db/migrations/043_rerouted_to_peer.ts
5477
5478
  var _043_rerouted_to_peer_exports = /* @__PURE__ */ __exportAll({
5478
- down: () => down$65,
5479
- up: () => up$65
5479
+ down: () => down$72,
5480
+ up: () => up$72
5480
5481
  });
5481
5482
  /**
5482
5483
  * Add a nullable `rerouted_to_peer text` marker to execution_jobs. Non-null
@@ -5487,7 +5488,7 @@ var _043_rerouted_to_peer_exports = /* @__PURE__ */ __exportAll({
5487
5488
  *
5488
5489
  * Idempotent: re-running on a DB that already has the column is a no-op.
5489
5490
  */
5490
- async function colExists$9(db, table, name) {
5491
+ async function colExists$10(db, table, name) {
5491
5492
  return (await sql`
5492
5493
  SELECT EXISTS (
5493
5494
  SELECT 1 FROM information_schema.columns
@@ -5497,17 +5498,17 @@ async function colExists$9(db, table, name) {
5497
5498
  ) AS exists
5498
5499
  `.execute(db)).rows[0]?.exists ?? false;
5499
5500
  }
5500
- async function up$65(db) {
5501
- if (!await colExists$9(db, "execution_jobs", "rerouted_to_peer")) await sql`ALTER TABLE public.execution_jobs ADD COLUMN rerouted_to_peer text`.execute(db);
5501
+ async function up$72(db) {
5502
+ if (!await colExists$10(db, "execution_jobs", "rerouted_to_peer")) await sql`ALTER TABLE public.execution_jobs ADD COLUMN rerouted_to_peer text`.execute(db);
5502
5503
  }
5503
- async function down$65(db) {
5504
+ async function down$72(db) {
5504
5505
  await sql`ALTER TABLE public.execution_jobs DROP COLUMN IF EXISTS rerouted_to_peer`.execute(db);
5505
5506
  }
5506
5507
  //#endregion
5507
5508
  //#region src/db/migrations/044_check_mode.ts
5508
5509
  var _044_check_mode_exports = /* @__PURE__ */ __exportAll({
5509
- down: () => down$64,
5510
- up: () => up$64
5510
+ down: () => down$71,
5511
+ up: () => up$71
5511
5512
  });
5512
5513
  /**
5513
5514
  * Add idempotent check-mode columns:
@@ -5524,7 +5525,7 @@ var _044_check_mode_exports = /* @__PURE__ */ __exportAll({
5524
5525
  * All nullable. Idempotent: re-running on a DB that already has the columns is
5525
5526
  * a no-op.
5526
5527
  */
5527
- async function colExists$8(db, table, name) {
5528
+ async function colExists$9(db, table, name) {
5528
5529
  return (await sql`
5529
5530
  SELECT EXISTS (
5530
5531
  SELECT 1 FROM information_schema.columns
@@ -5534,13 +5535,13 @@ async function colExists$8(db, table, name) {
5534
5535
  ) AS exists
5535
5536
  `.execute(db)).rows[0]?.exists ?? false;
5536
5537
  }
5537
- async function up$64(db) {
5538
- if (!await colExists$8(db, "execution_runs", "check_mode")) await sql`ALTER TABLE public.execution_runs ADD COLUMN check_mode text`.execute(db);
5539
- if (!await colExists$8(db, "execution_steps", "check_outcome")) await sql`ALTER TABLE public.execution_steps ADD COLUMN check_outcome text`.execute(db);
5540
- if (!await colExists$8(db, "execution_steps", "drift_summary")) await sql`ALTER TABLE public.execution_steps ADD COLUMN drift_summary text`.execute(db);
5541
- if (!await colExists$8(db, "execution_steps", "drift")) await sql`ALTER TABLE public.execution_steps ADD COLUMN drift jsonb`.execute(db);
5538
+ async function up$71(db) {
5539
+ if (!await colExists$9(db, "execution_runs", "check_mode")) await sql`ALTER TABLE public.execution_runs ADD COLUMN check_mode text`.execute(db);
5540
+ if (!await colExists$9(db, "execution_steps", "check_outcome")) await sql`ALTER TABLE public.execution_steps ADD COLUMN check_outcome text`.execute(db);
5541
+ if (!await colExists$9(db, "execution_steps", "drift_summary")) await sql`ALTER TABLE public.execution_steps ADD COLUMN drift_summary text`.execute(db);
5542
+ if (!await colExists$9(db, "execution_steps", "drift")) await sql`ALTER TABLE public.execution_steps ADD COLUMN drift jsonb`.execute(db);
5542
5543
  }
5543
- async function down$64(db) {
5544
+ async function down$71(db) {
5544
5545
  await sql`ALTER TABLE public.execution_steps DROP COLUMN IF EXISTS drift`.execute(db);
5545
5546
  await sql`ALTER TABLE public.execution_steps DROP COLUMN IF EXISTS drift_summary`.execute(db);
5546
5547
  await sql`ALTER TABLE public.execution_steps DROP COLUMN IF EXISTS check_outcome`.execute(db);
@@ -5549,8 +5550,8 @@ async function down$64(db) {
5549
5550
  //#endregion
5550
5551
  //#region src/db/migrations/045_host_properties.ts
5551
5552
  var _045_host_properties_exports = /* @__PURE__ */ __exportAll({
5552
- down: () => down$63,
5553
- up: () => up$63
5553
+ down: () => down$70,
5554
+ up: () => up$70
5554
5555
  });
5555
5556
  /**
5556
5557
  * Add the typed host-vars dimension to the host roster:
@@ -5564,18 +5565,18 @@ var _045_host_properties_exports = /* @__PURE__ */ __exportAll({
5564
5565
  * Idempotent (`ADD COLUMN IF NOT EXISTS`): re-running on a DB that already has
5565
5566
  * the column is a no-op. Staging data is preserved (additive column).
5566
5567
  */
5567
- async function up$63(db) {
5568
+ async function up$70(db) {
5568
5569
  await sql`ALTER TABLE public.host_roster
5569
5570
  ADD COLUMN IF NOT EXISTS host_properties jsonb NOT NULL DEFAULT '{}'::jsonb`.execute(db);
5570
5571
  }
5571
- async function down$63(db) {
5572
+ async function down$70(db) {
5572
5573
  await sql`ALTER TABLE public.host_roster DROP COLUMN IF EXISTS host_properties`.execute(db);
5573
5574
  }
5574
5575
  //#endregion
5575
5576
  //#region src/db/migrations/046_join_token_consumed_by_instance.ts
5576
5577
  var _046_join_token_consumed_by_instance_exports = /* @__PURE__ */ __exportAll({
5577
- down: () => down$62,
5578
- up: () => up$62
5578
+ down: () => down$69,
5579
+ up: () => up$69
5579
5580
  });
5580
5581
  /**
5581
5582
  * Record the joining peer's instanceId at first consumption of a join token:
@@ -5590,18 +5591,18 @@ var _046_join_token_consumed_by_instance_exports = /* @__PURE__ */ __exportAll({
5590
5591
  * Idempotent (`ADD COLUMN IF NOT EXISTS`): re-running on a DB that already has
5591
5592
  * the column is a no-op. Staging data is preserved (additive nullable column).
5592
5593
  */
5593
- async function up$62(db) {
5594
+ async function up$69(db) {
5594
5595
  await sql`ALTER TABLE public.join_tokens
5595
5596
  ADD COLUMN IF NOT EXISTS consumed_by_instance text`.execute(db);
5596
5597
  }
5597
- async function down$62(db) {
5598
+ async function down$69(db) {
5598
5599
  await sql`ALTER TABLE public.join_tokens DROP COLUMN IF EXISTS consumed_by_instance`.execute(db);
5599
5600
  }
5600
5601
  //#endregion
5601
5602
  //#region src/db/migrations/047_needs_run_on.ts
5602
5603
  var _047_needs_run_on_exports = /* @__PURE__ */ __exportAll({
5603
- down: () => down$61,
5604
- up: () => up$61
5604
+ down: () => down$68,
5605
+ up: () => up$68
5605
5606
  });
5606
5607
  /**
5607
5608
  * Migrate `execution_job_needs` from the binary `if_failed` policy to a
@@ -5626,7 +5627,7 @@ const ALL_TERMINAL_JSON = JSON.stringify([
5626
5627
  "drift_dropped"
5627
5628
  ]);
5628
5629
  const SUCCESS_ONLY_JSON = JSON.stringify(["success"]);
5629
- async function colExists$7(db, table, name) {
5630
+ async function colExists$8(db, table, name) {
5630
5631
  return (await sql`
5631
5632
  SELECT EXISTS (
5632
5633
  SELECT 1 FROM information_schema.columns
@@ -5637,12 +5638,12 @@ async function colExists$7(db, table, name) {
5637
5638
  `.execute(db)).rows[0]?.exists ?? false;
5638
5639
  }
5639
5640
  const SUCCESS_ONLY_DEFAULT = `'${SUCCESS_ONLY_JSON}'`;
5640
- async function up$61(db) {
5641
- if (!await colExists$7(db, "execution_job_needs", "run_on")) await sql`
5641
+ async function up$68(db) {
5642
+ if (!await colExists$8(db, "execution_job_needs", "run_on")) await sql`
5642
5643
  ALTER TABLE public.execution_job_needs
5643
5644
  ADD COLUMN run_on text NOT NULL DEFAULT ${sql.raw(SUCCESS_ONLY_DEFAULT)}
5644
5645
  `.execute(db);
5645
- if (await colExists$7(db, "execution_job_needs", "if_failed")) {
5646
+ if (await colExists$8(db, "execution_job_needs", "if_failed")) {
5646
5647
  await sql`
5647
5648
  UPDATE public.execution_job_needs
5648
5649
  SET run_on = ${ALL_TERMINAL_JSON}
@@ -5656,12 +5657,12 @@ async function up$61(db) {
5656
5657
  await sql`ALTER TABLE public.execution_job_needs DROP COLUMN if_failed`.execute(db);
5657
5658
  }
5658
5659
  }
5659
- async function down$61(db) {
5660
- if (!await colExists$7(db, "execution_job_needs", "if_failed")) await sql`
5660
+ async function down$68(db) {
5661
+ if (!await colExists$8(db, "execution_job_needs", "if_failed")) await sql`
5661
5662
  ALTER TABLE public.execution_job_needs
5662
5663
  ADD COLUMN if_failed text NOT NULL DEFAULT 'skip'
5663
5664
  `.execute(db);
5664
- if (await colExists$7(db, "execution_job_needs", "run_on")) {
5665
+ if (await colExists$8(db, "execution_job_needs", "run_on")) {
5665
5666
  await sql`
5666
5667
  UPDATE public.execution_job_needs
5667
5668
  SET if_failed = CASE WHEN run_on = ${SUCCESS_ONLY_JSON} THEN 'skip' ELSE 'run' END
@@ -5672,8 +5673,8 @@ async function down$61(db) {
5672
5673
  //#endregion
5673
5674
  //#region src/db/migrations/048_host_reboot_pending.ts
5674
5675
  var _048_host_reboot_pending_exports = /* @__PURE__ */ __exportAll({
5675
- down: () => down$60,
5676
- up: () => up$60
5676
+ down: () => down$67,
5677
+ up: () => up$67
5677
5678
  });
5678
5679
  /**
5679
5680
  * Add `host_roster.reboot_pending_until timestamptz NULL` — the persisted
@@ -5690,18 +5691,18 @@ var _048_host_reboot_pending_exports = /* @__PURE__ */ __exportAll({
5690
5691
  * Idempotent (`ADD COLUMN IF NOT EXISTS`); additive, so staging data is
5691
5692
  * preserved.
5692
5693
  */
5693
- async function up$60(db) {
5694
+ async function up$67(db) {
5694
5695
  await sql`ALTER TABLE public.host_roster
5695
5696
  ADD COLUMN IF NOT EXISTS reboot_pending_until timestamptz`.execute(db);
5696
5697
  }
5697
- async function down$60(db) {
5698
+ async function down$67(db) {
5698
5699
  await sql`ALTER TABLE public.host_roster DROP COLUMN IF EXISTS reboot_pending_until`.execute(db);
5699
5700
  }
5700
5701
  //#endregion
5701
5702
  //#region src/db/migrations/049_held_runs_payload.ts
5702
5703
  var _049_held_runs_payload_exports = /* @__PURE__ */ __exportAll({
5703
- down: () => down$59,
5704
- up: () => up$59
5704
+ down: () => down$66,
5705
+ up: () => up$66
5705
5706
  });
5706
5707
  /**
5707
5708
  * Add `held_runs.payload jsonb NULL` — the drift payload captured when a
@@ -5713,18 +5714,18 @@ var _049_held_runs_payload_exports = /* @__PURE__ */ __exportAll({
5713
5714
  * Idempotent (`ADD COLUMN IF NOT EXISTS`); additive, so staging data is
5714
5715
  * preserved.
5715
5716
  */
5716
- async function up$59(db) {
5717
+ async function up$66(db) {
5717
5718
  await sql`ALTER TABLE public.held_runs
5718
5719
  ADD COLUMN IF NOT EXISTS payload jsonb`.execute(db);
5719
5720
  }
5720
- async function down$59(db) {
5721
+ async function down$66(db) {
5721
5722
  await sql`ALTER TABLE public.held_runs DROP COLUMN IF EXISTS payload`.execute(db);
5722
5723
  }
5723
5724
  //#endregion
5724
5725
  //#region src/db/migrations/050_sources_slug.ts
5725
5726
  var _050_sources_slug_exports = /* @__PURE__ */ __exportAll({
5726
- down: () => down$58,
5727
- up: () => up$58
5727
+ down: () => down$65,
5728
+ up: () => up$65
5728
5729
  });
5729
5730
  /**
5730
5731
  * Add `sources.slug TEXT NULL` — the GitHub App slug (the URL-safe identifier
@@ -5739,18 +5740,18 @@ var _050_sources_slug_exports = /* @__PURE__ */ __exportAll({
5739
5740
  * Idempotent (`ADD COLUMN IF NOT EXISTS`); additive, so staging data is
5740
5741
  * preserved.
5741
5742
  */
5742
- async function up$58(db) {
5743
+ async function up$65(db) {
5743
5744
  await sql`ALTER TABLE public.sources
5744
5745
  ADD COLUMN IF NOT EXISTS slug text`.execute(db);
5745
5746
  }
5746
- async function down$58(db) {
5747
+ async function down$65(db) {
5747
5748
  await sql`ALTER TABLE public.sources DROP COLUMN IF EXISTS slug`.execute(db);
5748
5749
  }
5749
5750
  //#endregion
5750
5751
  //#region src/db/migrations/051_binding_host_pattern.ts
5751
5752
  var _051_binding_host_pattern_exports = /* @__PURE__ */ __exportAll({
5752
- down: () => down$57,
5753
- up: () => up$57
5753
+ down: () => down$64,
5754
+ up: () => up$64
5754
5755
  });
5755
5756
  /**
5756
5757
  * Add a per-host dimension to environment secret bindings:
@@ -5766,7 +5767,7 @@ var _051_binding_host_pattern_exports = /* @__PURE__ */ __exportAll({
5766
5767
  * Idempotent: re-running on a DB that already has the column / index is a no-op.
5767
5768
  * Additive — staging data is preserved.
5768
5769
  */
5769
- async function up$57(db) {
5770
+ async function up$64(db) {
5770
5771
  await sql`ALTER TABLE public.environment_bindings
5771
5772
  ADD COLUMN IF NOT EXISTS host_pattern text NOT NULL DEFAULT '**'`.execute(db);
5772
5773
  await sql`ALTER TABLE public.environment_bindings
@@ -5774,7 +5775,7 @@ async function up$57(db) {
5774
5775
  await sql`CREATE UNIQUE INDEX IF NOT EXISTS environment_bindings_env_scope_host_uniq
5775
5776
  ON public.environment_bindings (environment_id, scope_pattern, host_pattern)`.execute(db);
5776
5777
  }
5777
- async function down$57(db) {
5778
+ async function down$64(db) {
5778
5779
  await sql`DROP INDEX IF EXISTS public.environment_bindings_env_scope_host_uniq`.execute(db);
5779
5780
  await sql`ALTER TABLE public.environment_bindings
5780
5781
  DROP COLUMN IF EXISTS host_pattern`.execute(db);
@@ -5784,8 +5785,8 @@ async function down$57(db) {
5784
5785
  //#endregion
5785
5786
  //#region src/db/migrations/052_host_reach_metadata.ts
5786
5787
  var _052_host_reach_metadata_exports = /* @__PURE__ */ __exportAll({
5787
- down: () => down$56,
5788
- up: () => up$56
5788
+ down: () => down$63,
5789
+ up: () => up$63
5789
5790
  });
5790
5791
  /**
5791
5792
  * Add pre-agent reach metadata to the host roster so a declared host (no agent
@@ -5802,14 +5803,14 @@ var _052_host_reach_metadata_exports = /* @__PURE__ */ __exportAll({
5802
5803
  * behaves exactly as before. Idempotent (`ADD COLUMN IF NOT EXISTS`); additive,
5803
5804
  * so staging data is preserved.
5804
5805
  */
5805
- async function up$56(db) {
5806
+ async function up$63(db) {
5806
5807
  await sql`ALTER TABLE public.host_roster
5807
5808
  ADD COLUMN IF NOT EXISTS address text,
5808
5809
  ADD COLUMN IF NOT EXISTS ssh_user text,
5809
5810
  ADD COLUMN IF NOT EXISTS ssh_port integer,
5810
5811
  ADD COLUMN IF NOT EXISTS ssh_key_secret text`.execute(db);
5811
5812
  }
5812
- async function down$56(db) {
5813
+ async function down$63(db) {
5813
5814
  await sql`ALTER TABLE public.host_roster
5814
5815
  DROP COLUMN IF EXISTS address,
5815
5816
  DROP COLUMN IF EXISTS ssh_user,
@@ -5819,8 +5820,8 @@ async function down$56(db) {
5819
5820
  //#endregion
5820
5821
  //#region src/db/migrations/053_agent_token_single_use.ts
5821
5822
  var _053_agent_token_single_use_exports = /* @__PURE__ */ __exportAll({
5822
- down: () => down$55,
5823
- up: () => up$55
5823
+ down: () => down$62,
5824
+ up: () => up$62
5824
5825
  });
5825
5826
  /**
5826
5827
  * Add a single-use marker to agent tokens for the bootstrap (init-runner)
@@ -5835,19 +5836,19 @@ var _053_agent_token_single_use_exports = /* @__PURE__ */ __exportAll({
5835
5836
  * Idempotent (`ADD COLUMN IF NOT EXISTS`); additive, so staging data is
5836
5837
  * preserved.
5837
5838
  */
5838
- async function up$55(db) {
5839
+ async function up$62(db) {
5839
5840
  await sql`ALTER TABLE public.agent_tokens
5840
5841
  ADD COLUMN IF NOT EXISTS consumed_at timestamptz`.execute(db);
5841
5842
  }
5842
- async function down$55(db) {
5843
+ async function down$62(db) {
5843
5844
  await sql`ALTER TABLE public.agent_tokens
5844
5845
  DROP COLUMN IF EXISTS consumed_at`.execute(db);
5845
5846
  }
5846
5847
  //#endregion
5847
5848
  //#region src/db/migrations/054_local_working_tree.ts
5848
5849
  var _054_local_working_tree_exports = /* @__PURE__ */ __exportAll({
5849
- down: () => down$54,
5850
- up: () => up$54
5850
+ down: () => down$61,
5851
+ up: () => up$61
5851
5852
  });
5852
5853
  /**
5853
5854
  * Mark runs that executed an uploaded local working tree (`kici run remote`):
@@ -5860,19 +5861,19 @@ var _054_local_working_tree_exports = /* @__PURE__ */ __exportAll({
5860
5861
  * Idempotent (`ADD COLUMN IF NOT EXISTS`); additive with a default, so staging
5861
5862
  * data is preserved.
5862
5863
  */
5863
- async function up$54(db) {
5864
+ async function up$61(db) {
5864
5865
  await sql`ALTER TABLE public.execution_runs
5865
5866
  ADD COLUMN IF NOT EXISTS local_working_tree boolean NOT NULL DEFAULT false`.execute(db);
5866
5867
  }
5867
- async function down$54(db) {
5868
+ async function down$61(db) {
5868
5869
  await sql`ALTER TABLE public.execution_runs
5869
5870
  DROP COLUMN IF EXISTS local_working_tree`.execute(db);
5870
5871
  }
5871
5872
  //#endregion
5872
5873
  //#region src/db/migrations/055_agent_token_mandatory_labels.ts
5873
5874
  var _055_agent_token_mandatory_labels_exports = /* @__PURE__ */ __exportAll({
5874
- down: () => down$53,
5875
- up: () => up$53
5875
+ down: () => down$60,
5876
+ up: () => up$60
5876
5877
  });
5877
5878
  /**
5878
5879
  * Add a token-bound mandatory-label taint to agent tokens:
@@ -5888,19 +5889,19 @@ var _055_agent_token_mandatory_labels_exports = /* @__PURE__ */ __exportAll({
5888
5889
  * Idempotent (`ADD COLUMN IF NOT EXISTS`); additive, so staging data is
5889
5890
  * preserved.
5890
5891
  */
5891
- async function up$53(db) {
5892
+ async function up$60(db) {
5892
5893
  await sql`ALTER TABLE public.agent_tokens
5893
5894
  ADD COLUMN IF NOT EXISTS mandatory_labels text`.execute(db);
5894
5895
  }
5895
- async function down$53(db) {
5896
+ async function down$60(db) {
5896
5897
  await sql`ALTER TABLE public.agent_tokens
5897
5898
  DROP COLUMN IF EXISTS mandatory_labels`.execute(db);
5898
5899
  }
5899
5900
  //#endregion
5900
5901
  //#region src/db/migrations/056_execution_jobs_environments.ts
5901
5902
  var _056_execution_jobs_environments_exports = /* @__PURE__ */ __exportAll({
5902
- down: () => down$52,
5903
- up: () => up$52
5903
+ down: () => down$59,
5904
+ up: () => up$59
5904
5905
  });
5905
5906
  /**
5906
5907
  * Add a per-job bound deployment-environment list to `execution_jobs`:
@@ -5915,19 +5916,19 @@ var _056_execution_jobs_environments_exports = /* @__PURE__ */ __exportAll({
5915
5916
  * Idempotent (`ADD COLUMN IF NOT EXISTS`); additive, so staging data is
5916
5917
  * preserved.
5917
5918
  */
5918
- async function up$52(db) {
5919
+ async function up$59(db) {
5919
5920
  await sql`ALTER TABLE public.execution_jobs
5920
5921
  ADD COLUMN IF NOT EXISTS environments text`.execute(db);
5921
5922
  }
5922
- async function down$52(db) {
5923
+ async function down$59(db) {
5923
5924
  await sql`ALTER TABLE public.execution_jobs
5924
5925
  DROP COLUMN IF EXISTS environments`.execute(db);
5925
5926
  }
5926
5927
  //#endregion
5927
5928
  //#region src/db/migrations/057_step_concurrency.ts
5928
5929
  var _057_step_concurrency_exports = /* @__PURE__ */ __exportAll({
5929
- down: () => down$51,
5930
- up: () => up$51
5930
+ down: () => down$58,
5931
+ up: () => up$58
5931
5932
  });
5932
5933
  /**
5933
5934
  * Add parallel step-group concurrency columns to `execution_steps`:
@@ -5940,7 +5941,7 @@ var _057_step_concurrency_exports = /* @__PURE__ */ __exportAll({
5940
5941
  * Both nullable, no backfill. Idempotent: re-running on a DB that already has the
5941
5942
  * columns is a no-op.
5942
5943
  */
5943
- async function colExists$6(db, table, name) {
5944
+ async function colExists$7(db, table, name) {
5944
5945
  return (await sql`
5945
5946
  SELECT EXISTS (
5946
5947
  SELECT 1 FROM information_schema.columns
@@ -5950,19 +5951,19 @@ async function colExists$6(db, table, name) {
5950
5951
  ) AS exists
5951
5952
  `.execute(db)).rows[0]?.exists ?? false;
5952
5953
  }
5953
- async function up$51(db) {
5954
- if (!await colExists$6(db, "execution_steps", "concurrency_kind")) await sql`ALTER TABLE public.execution_steps ADD COLUMN concurrency_kind text`.execute(db);
5955
- if (!await colExists$6(db, "execution_steps", "group_id")) await sql`ALTER TABLE public.execution_steps ADD COLUMN group_id text`.execute(db);
5954
+ async function up$58(db) {
5955
+ if (!await colExists$7(db, "execution_steps", "concurrency_kind")) await sql`ALTER TABLE public.execution_steps ADD COLUMN concurrency_kind text`.execute(db);
5956
+ if (!await colExists$7(db, "execution_steps", "group_id")) await sql`ALTER TABLE public.execution_steps ADD COLUMN group_id text`.execute(db);
5956
5957
  }
5957
- async function down$51(db) {
5958
+ async function down$58(db) {
5958
5959
  await sql`ALTER TABLE public.execution_steps DROP COLUMN IF EXISTS group_id`.execute(db);
5959
5960
  await sql`ALTER TABLE public.execution_steps DROP COLUMN IF EXISTS concurrency_kind`.execute(db);
5960
5961
  }
5961
5962
  //#endregion
5962
5963
  //#region src/db/migrations/058_access_log_agent_label.ts
5963
5964
  var _058_access_log_agent_label_exports = /* @__PURE__ */ __exportAll({
5964
- down: () => down$50,
5965
- up: () => up$50
5965
+ down: () => down$57,
5966
+ up: () => up$57
5966
5967
  });
5967
5968
  /**
5968
5969
  * Add `access_log.agent_label text` — the human-set name of the agent that
@@ -5972,7 +5973,7 @@ var _058_access_log_agent_label_exports = /* @__PURE__ */ __exportAll({
5972
5973
  * the access log by agent. NULL for ordinary human / API-key / system actors.
5973
5974
  * Nullable, no backfill. Idempotent.
5974
5975
  */
5975
- async function colExists$5(db, table, name) {
5976
+ async function colExists$6(db, table, name) {
5976
5977
  return (await sql`
5977
5978
  SELECT EXISTS (
5978
5979
  SELECT 1 FROM information_schema.columns
@@ -5982,17 +5983,17 @@ async function colExists$5(db, table, name) {
5982
5983
  ) AS exists
5983
5984
  `.execute(db)).rows[0]?.exists ?? false;
5984
5985
  }
5985
- async function up$50(db) {
5986
- if (!await colExists$5(db, "access_log", "agent_label")) await sql`ALTER TABLE public.access_log ADD COLUMN agent_label text`.execute(db);
5986
+ async function up$57(db) {
5987
+ if (!await colExists$6(db, "access_log", "agent_label")) await sql`ALTER TABLE public.access_log ADD COLUMN agent_label text`.execute(db);
5987
5988
  }
5988
- async function down$50(db) {
5989
+ async function down$57(db) {
5989
5990
  await sql`ALTER TABLE public.access_log DROP COLUMN IF EXISTS agent_label`.execute(db);
5990
5991
  }
5991
5992
  //#endregion
5992
5993
  //#region src/db/migrations/059_attestation_verdict.ts
5993
5994
  var _059_attestation_verdict_exports = /* @__PURE__ */ __exportAll({
5994
- down: () => down$49,
5995
- up: () => up$49
5995
+ down: () => down$56,
5996
+ up: () => up$56
5996
5997
  });
5997
5998
  /**
5998
5999
  * Add server-side verification verdict columns to `attestations`, plus the
@@ -6009,7 +6010,7 @@ var _059_attestation_verdict_exports = /* @__PURE__ */ __exportAll({
6009
6010
  *
6010
6011
  * Idempotent: guarded on the `verify_status` column's existence.
6011
6012
  */
6012
- async function colExists$4(db, table, name) {
6013
+ async function colExists$5(db, table, name) {
6013
6014
  return (await sql`
6014
6015
  SELECT EXISTS (
6015
6016
  SELECT 1 FROM information_schema.columns
@@ -6019,8 +6020,8 @@ async function colExists$4(db, table, name) {
6019
6020
  ) AS exists
6020
6021
  `.execute(db)).rows[0]?.exists ?? false;
6021
6022
  }
6022
- async function up$49(db) {
6023
- if (await colExists$4(db, "attestations", "verify_status")) return;
6023
+ async function up$56(db) {
6024
+ if (await colExists$5(db, "attestations", "verify_status")) return;
6024
6025
  await sql`
6025
6026
  ALTER TABLE public.attestations
6026
6027
  ADD COLUMN verify_status TEXT NOT NULL DEFAULT 'pending',
@@ -6032,7 +6033,7 @@ async function up$49(db) {
6032
6033
  await sql`CREATE INDEX idx_attestations_verify_status ON public.attestations (verify_status)`.execute(db);
6033
6034
  await sql`CREATE INDEX idx_attestations_created_at ON public.attestations (created_at)`.execute(db);
6034
6035
  }
6035
- async function down$49(db) {
6036
+ async function down$56(db) {
6036
6037
  await sql`DROP INDEX IF EXISTS idx_attestations_created_at`.execute(db);
6037
6038
  await sql`DROP INDEX IF EXISTS idx_attestations_verify_status`.execute(db);
6038
6039
  await sql`DROP INDEX IF EXISTS idx_attestations_subject_name`.execute(db);
@@ -6047,8 +6048,8 @@ async function down$49(db) {
6047
6048
  //#endregion
6048
6049
  //#region src/db/migrations/060_run_trigger_actor.ts
6049
6050
  var _060_run_trigger_actor_exports = /* @__PURE__ */ __exportAll({
6050
- down: () => down$48,
6051
- up: () => up$48
6051
+ down: () => down$55,
6052
+ up: () => up$55
6052
6053
  });
6053
6054
  /**
6054
6055
  * Add the triggering-actor columns to `execution_runs`:
@@ -6066,7 +6067,7 @@ var _060_run_trigger_actor_exports = /* @__PURE__ */ __exportAll({
6066
6067
  * @x" and audit, beyond actor notifications. All nullable, no backfill,
6067
6068
  * idempotent.
6068
6069
  */
6069
- async function colExists$3(db, table, name) {
6070
+ async function colExists$4(db, table, name) {
6070
6071
  return (await sql`
6071
6072
  SELECT EXISTS (
6072
6073
  SELECT 1 FROM information_schema.columns
@@ -6076,12 +6077,12 @@ async function colExists$3(db, table, name) {
6076
6077
  ) AS exists
6077
6078
  `.execute(db)).rows[0]?.exists ?? false;
6078
6079
  }
6079
- async function up$48(db) {
6080
- if (!await colExists$3(db, "execution_runs", "trigger_actor_provider")) await sql`ALTER TABLE public.execution_runs ADD COLUMN trigger_actor_provider text`.execute(db);
6081
- if (!await colExists$3(db, "execution_runs", "trigger_actor_username")) await sql`ALTER TABLE public.execution_runs ADD COLUMN trigger_actor_username text`.execute(db);
6082
- if (!await colExists$3(db, "execution_runs", "trigger_actor_user_id")) await sql`ALTER TABLE public.execution_runs ADD COLUMN trigger_actor_user_id text`.execute(db);
6080
+ async function up$55(db) {
6081
+ if (!await colExists$4(db, "execution_runs", "trigger_actor_provider")) await sql`ALTER TABLE public.execution_runs ADD COLUMN trigger_actor_provider text`.execute(db);
6082
+ if (!await colExists$4(db, "execution_runs", "trigger_actor_username")) await sql`ALTER TABLE public.execution_runs ADD COLUMN trigger_actor_username text`.execute(db);
6083
+ if (!await colExists$4(db, "execution_runs", "trigger_actor_user_id")) await sql`ALTER TABLE public.execution_runs ADD COLUMN trigger_actor_user_id text`.execute(db);
6083
6084
  }
6084
- async function down$48(db) {
6085
+ async function down$55(db) {
6085
6086
  await sql`ALTER TABLE public.execution_runs DROP COLUMN IF EXISTS trigger_actor_provider`.execute(db);
6086
6087
  await sql`ALTER TABLE public.execution_runs DROP COLUMN IF EXISTS trigger_actor_username`.execute(db);
6087
6088
  await sql`ALTER TABLE public.execution_runs DROP COLUMN IF EXISTS trigger_actor_user_id`.execute(db);
@@ -6089,8 +6090,8 @@ async function down$48(db) {
6089
6090
  //#endregion
6090
6091
  //#region src/db/migrations/061_execution_runs_environment_id.ts
6091
6092
  var _061_execution_runs_environment_id_exports = /* @__PURE__ */ __exportAll({
6092
- down: () => down$47,
6093
- up: () => up$47
6093
+ down: () => down$54,
6094
+ up: () => up$54
6094
6095
  });
6095
6096
  /**
6096
6097
  * Add `environment_id` to `execution_runs` so environment run-history can be
@@ -6116,7 +6117,7 @@ var _061_execution_runs_environment_id_exports = /* @__PURE__ */ __exportAll({
6116
6117
  * backfill use `IF NOT EXISTS` / `WHERE environment_id IS NULL` so re-running is
6117
6118
  * a no-op.
6118
6119
  */
6119
- async function colExists$2(db, table, name) {
6120
+ async function colExists$3(db, table, name) {
6120
6121
  return (await sql`
6121
6122
  SELECT EXISTS (
6122
6123
  SELECT 1 FROM information_schema.columns
@@ -6126,8 +6127,8 @@ async function colExists$2(db, table, name) {
6126
6127
  ) AS exists
6127
6128
  `.execute(db)).rows[0]?.exists ?? false;
6128
6129
  }
6129
- async function up$47(db) {
6130
- if (!await colExists$2(db, "execution_runs", "environment_id")) await sql`
6130
+ async function up$54(db) {
6131
+ if (!await colExists$3(db, "execution_runs", "environment_id")) await sql`
6131
6132
  ALTER TABLE public.execution_runs
6132
6133
  ADD COLUMN environment_id uuid
6133
6134
  REFERENCES public.environments(id) ON DELETE SET NULL
@@ -6148,15 +6149,15 @@ async function up$47(db) {
6148
6149
  WHERE e2.type = 'fixed' AND e2.name = er.environment) = 1
6149
6150
  `.execute(db);
6150
6151
  }
6151
- async function down$47(db) {
6152
+ async function down$54(db) {
6152
6153
  await sql`DROP INDEX IF EXISTS idx_execution_runs_environment_id`.execute(db);
6153
6154
  await sql`ALTER TABLE public.execution_runs DROP COLUMN IF EXISTS environment_id`.execute(db);
6154
6155
  }
6155
6156
  //#endregion
6156
6157
  //#region src/db/migrations/062_execution_runs_agent_label.ts
6157
6158
  var _062_execution_runs_agent_label_exports = /* @__PURE__ */ __exportAll({
6158
- down: () => down$46,
6159
- up: () => up$46
6159
+ down: () => down$53,
6160
+ up: () => up$53
6160
6161
  });
6161
6162
  /**
6162
6163
  * Add the agent-provenance columns to `execution_runs`:
@@ -6171,7 +6172,7 @@ var _062_execution_runs_agent_label_exports = /* @__PURE__ */ __exportAll({
6171
6172
  * permissions). NULL for ordinary human / webhook / system-driven runs.
6172
6173
  * Nullable, no backfill, idempotent.
6173
6174
  */
6174
- async function colExists$1(db, table, name) {
6175
+ async function colExists$2(db, table, name) {
6175
6176
  return (await sql`
6176
6177
  SELECT EXISTS (
6177
6178
  SELECT 1 FROM information_schema.columns
@@ -6181,19 +6182,19 @@ async function colExists$1(db, table, name) {
6181
6182
  ) AS exists
6182
6183
  `.execute(db)).rows[0]?.exists ?? false;
6183
6184
  }
6184
- async function up$46(db) {
6185
- if (!await colExists$1(db, "execution_runs", "triggered_by_agent_label")) await sql`ALTER TABLE public.execution_runs ADD COLUMN triggered_by_agent_label text`.execute(db);
6186
- if (!await colExists$1(db, "execution_runs", "cancelled_by_agent_label")) await sql`ALTER TABLE public.execution_runs ADD COLUMN cancelled_by_agent_label text`.execute(db);
6185
+ async function up$53(db) {
6186
+ if (!await colExists$2(db, "execution_runs", "triggered_by_agent_label")) await sql`ALTER TABLE public.execution_runs ADD COLUMN triggered_by_agent_label text`.execute(db);
6187
+ if (!await colExists$2(db, "execution_runs", "cancelled_by_agent_label")) await sql`ALTER TABLE public.execution_runs ADD COLUMN cancelled_by_agent_label text`.execute(db);
6187
6188
  }
6188
- async function down$46(db) {
6189
+ async function down$53(db) {
6189
6190
  await sql`ALTER TABLE public.execution_runs DROP COLUMN IF EXISTS triggered_by_agent_label`.execute(db);
6190
6191
  await sql`ALTER TABLE public.execution_runs DROP COLUMN IF EXISTS cancelled_by_agent_label`.execute(db);
6191
6192
  }
6192
6193
  //#endregion
6193
6194
  //#region src/db/migrations/063_access_log_agent_label_index.ts
6194
6195
  var _063_access_log_agent_label_index_exports = /* @__PURE__ */ __exportAll({
6195
- down: () => down$45,
6196
- up: () => up$45
6196
+ down: () => down$52,
6197
+ up: () => up$52
6197
6198
  });
6198
6199
  /**
6199
6200
  * Index `access_log.agent_label` (column added by migration 058) so the
@@ -6201,17 +6202,17 @@ var _063_access_log_agent_label_index_exports = /* @__PURE__ */ __exportAll({
6201
6202
  * the dashboard "agent name" filter) does an indexed exact-match lookup
6202
6203
  * instead of a scan. Idempotent.
6203
6204
  */
6204
- async function up$45(db) {
6205
+ async function up$52(db) {
6205
6206
  await sql`CREATE INDEX IF NOT EXISTS access_log_agent_label_idx ON public.access_log (agent_label)`.execute(db);
6206
6207
  }
6207
- async function down$45(db) {
6208
+ async function down$52(db) {
6208
6209
  await sql`DROP INDEX IF EXISTS access_log_agent_label_idx`.execute(db);
6209
6210
  }
6210
6211
  //#endregion
6211
6212
  //#region src/db/migrations/064_execution_jobs_skipped_environments.ts
6212
6213
  var _064_execution_jobs_skipped_environments_exports = /* @__PURE__ */ __exportAll({
6213
- down: () => down$44,
6214
- up: () => up$44
6214
+ down: () => down$51,
6215
+ up: () => up$51
6215
6216
  });
6216
6217
  /**
6217
6218
  * Add the test-run skipped-environment columns to `execution_jobs`:
@@ -6226,13 +6227,13 @@ var _064_execution_jobs_skipped_environments_exports = /* @__PURE__ */ __exportA
6226
6227
  * Idempotent (`ADD COLUMN IF NOT EXISTS`); additive, so staging data is
6227
6228
  * preserved.
6228
6229
  */
6229
- async function up$44(db) {
6230
+ async function up$51(db) {
6230
6231
  await sql`ALTER TABLE public.execution_jobs
6231
6232
  ADD COLUMN IF NOT EXISTS skipped_environments text`.execute(db);
6232
6233
  await sql`ALTER TABLE public.execution_jobs
6233
6234
  ADD COLUMN IF NOT EXISTS env_warning text`.execute(db);
6234
6235
  }
6235
- async function down$44(db) {
6236
+ async function down$51(db) {
6236
6237
  await sql`ALTER TABLE public.execution_jobs
6237
6238
  DROP COLUMN IF EXISTS skipped_environments`.execute(db);
6238
6239
  await sql`ALTER TABLE public.execution_jobs
@@ -6241,8 +6242,8 @@ async function down$44(db) {
6241
6242
  //#endregion
6242
6243
  //#region src/db/migrations/065_pending_attestations.ts
6243
6244
  var _065_pending_attestations_exports = /* @__PURE__ */ __exportAll({
6244
- down: () => down$43,
6245
- up: () => up$43
6245
+ down: () => down$50,
6246
+ up: () => up$50
6246
6247
  });
6247
6248
  /**
6248
6249
  * Add the `pending_attestations` deferred-attestation outbox and an idempotency
@@ -6262,7 +6263,7 @@ var _065_pending_attestations_exports = /* @__PURE__ */ __exportAll({
6262
6263
  *
6263
6264
  * Idempotent: guarded on table existence.
6264
6265
  */
6265
- async function up$43(db) {
6266
+ async function up$50(db) {
6266
6267
  if ((await sql`
6267
6268
  SELECT EXISTS (
6268
6269
  SELECT 1 FROM information_schema.tables
@@ -6301,15 +6302,15 @@ async function up$43(db) {
6301
6302
  ON public.attestations (run_id, job_id, subject_digest)
6302
6303
  `.execute(db);
6303
6304
  }
6304
- async function down$43(db) {
6305
+ async function down$50(db) {
6305
6306
  await sql`DROP INDEX IF EXISTS uq_attestations_run_job_subject`.execute(db);
6306
6307
  await sql`DROP TABLE IF EXISTS public.pending_attestations`.execute(db);
6307
6308
  }
6308
6309
  //#endregion
6309
6310
  //#region src/db/migrations/066_pending_attestations_rejected.ts
6310
6311
  var _066_pending_attestations_rejected_exports = /* @__PURE__ */ __exportAll({
6311
- down: () => down$42,
6312
- up: () => up$42
6312
+ down: () => down$49,
6313
+ up: () => up$49
6313
6314
  });
6314
6315
  /**
6315
6316
  * Add `rejected_at` to `pending_attestations`: the terminal-rejection marker for
@@ -6320,21 +6321,21 @@ var _066_pending_attestations_rejected_exports = /* @__PURE__ */ __exportAll({
6320
6321
  *
6321
6322
  * Idempotent: guarded on column existence.
6322
6323
  */
6323
- async function up$42(db) {
6324
- if (await columnExists$5(db, "pending_attestations", "rejected_at")) return;
6324
+ async function up$49(db) {
6325
+ if (await columnExists$10(db, "pending_attestations", "rejected_at")) return;
6325
6326
  await sql`
6326
6327
  ALTER TABLE public.pending_attestations
6327
6328
  ADD COLUMN rejected_at TIMESTAMPTZ
6328
6329
  `.execute(db);
6329
6330
  }
6330
- async function down$42(db) {
6331
- if (!await columnExists$5(db, "pending_attestations", "rejected_at")) return;
6331
+ async function down$49(db) {
6332
+ if (!await columnExists$10(db, "pending_attestations", "rejected_at")) return;
6332
6333
  await sql`
6333
6334
  ALTER TABLE public.pending_attestations
6334
6335
  DROP COLUMN rejected_at
6335
6336
  `.execute(db);
6336
6337
  }
6337
- async function columnExists$5(db, table, column) {
6338
+ async function columnExists$10(db, table, column) {
6338
6339
  return (await sql`
6339
6340
  SELECT EXISTS (
6340
6341
  SELECT 1 FROM information_schema.columns
@@ -6345,8 +6346,8 @@ async function columnExists$5(db, table, column) {
6345
6346
  //#endregion
6346
6347
  //#region src/db/migrations/067_environments_to_contexts.ts
6347
6348
  var _067_environments_to_contexts_exports = /* @__PURE__ */ __exportAll({
6348
- down: () => down$41,
6349
- up: () => up$41
6349
+ down: () => down$48,
6350
+ up: () => up$48
6350
6351
  });
6351
6352
  /**
6352
6353
  * Rename the named-policy object from "environment" to "context" across the
@@ -6380,7 +6381,7 @@ var _067_environments_to_contexts_exports = /* @__PURE__ */ __exportAll({
6380
6381
  * columns automatically (Postgres references them by identity, not name), so
6381
6382
  * only the one hand-named index above needs an explicit rename.
6382
6383
  */
6383
- async function up$41(db) {
6384
+ async function up$48(db) {
6384
6385
  await sql`ALTER TABLE public.environments RENAME TO contexts`.execute(db);
6385
6386
  await sql`ALTER TABLE public.environment_bindings RENAME TO context_bindings`.execute(db);
6386
6387
  await sql`ALTER TABLE public.environment_variables RENAME TO context_variables`.execute(db);
@@ -6399,7 +6400,7 @@ async function up$41(db) {
6399
6400
  await sql`ALTER TABLE public.held_runs ALTER COLUMN queue_type SET DEFAULT 'context'`.execute(db);
6400
6401
  await sql`ALTER TABLE public.held_runs ALTER COLUMN trigger_source SET DEFAULT 'context'`.execute(db);
6401
6402
  }
6402
- async function down$41(db) {
6403
+ async function down$48(db) {
6403
6404
  await sql`ALTER TABLE public.held_runs ALTER COLUMN trigger_source SET DEFAULT 'environment'`.execute(db);
6404
6405
  await sql`ALTER TABLE public.held_runs ALTER COLUMN queue_type SET DEFAULT 'environment'`.execute(db);
6405
6406
  await sql`UPDATE public.held_runs SET trigger_source = 'environment' WHERE trigger_source = 'context'`.execute(db);
@@ -6421,8 +6422,8 @@ async function down$41(db) {
6421
6422
  //#endregion
6422
6423
  //#region src/db/migrations/068_request_idempotency.ts
6423
6424
  var _068_request_idempotency_exports = /* @__PURE__ */ __exportAll({
6424
- down: () => down$40,
6425
- up: () => up$40
6425
+ down: () => down$47,
6426
+ up: () => up$47
6426
6427
  });
6427
6428
  /**
6428
6429
  * Add the `request_idempotency` claim table: a `request_id`-keyed record that
@@ -6437,12 +6438,12 @@ var _068_request_idempotency_exports = /* @__PURE__ */ __exportAll({
6437
6438
  *
6438
6439
  * Idempotent: guarded on table existence.
6439
6440
  */
6440
- async function up$40(db) {
6441
+ async function up$47(db) {
6441
6442
  if (await tableExists$3(db, "request_idempotency")) return;
6442
6443
  await db.schema.createTable("request_idempotency").addColumn("request_id", "text", (c) => c.primaryKey()).addColumn("new_run_id", "text", (c) => c.notNull()).addColumn("created_at", "timestamptz", (c) => c.notNull().defaultTo(sql`now()`)).execute();
6443
6444
  await db.schema.createIndex("idx_request_idempotency_created_at").on("request_idempotency").column("created_at").execute();
6444
6445
  }
6445
- async function down$40(db) {
6446
+ async function down$47(db) {
6446
6447
  await db.schema.dropTable("request_idempotency").ifExists().execute();
6447
6448
  }
6448
6449
  async function tableExists$3(db, table) {
@@ -6456,8 +6457,8 @@ async function tableExists$3(db, table) {
6456
6457
  //#endregion
6457
6458
  //#region src/db/migrations/069_reroute_tunables.ts
6458
6459
  var _069_reroute_tunables_exports = /* @__PURE__ */ __exportAll({
6459
- down: () => down$39,
6460
- up: () => up$39
6460
+ down: () => down$46,
6461
+ up: () => up$46
6461
6462
  });
6462
6463
  /**
6463
6464
  * Add the three reroute-tunable columns to `org_settings` (all nullable):
@@ -6476,12 +6477,12 @@ var _069_reroute_tunables_exports = /* @__PURE__ */ __exportAll({
6476
6477
  * Idempotent: each column add is guarded on column existence, so a re-run on a
6477
6478
  * DB that already has a column is a no-op for that column.
6478
6479
  */
6479
- async function up$39(db) {
6480
+ async function up$46(db) {
6480
6481
  await addColumnIfMissing(db, "reroute_spawn_window_ms", "BIGINT");
6481
6482
  await addColumnIfMissing(db, "reroute_ack_timeout_ms", "BIGINT");
6482
6483
  await addColumnIfMissing(db, "reroute_max_hops", "INTEGER");
6483
6484
  }
6484
- async function down$39(db) {
6485
+ async function down$46(db) {
6485
6486
  await sql`ALTER TABLE public.org_settings DROP COLUMN IF EXISTS reroute_spawn_window_ms`.execute(db);
6486
6487
  await sql`ALTER TABLE public.org_settings DROP COLUMN IF EXISTS reroute_ack_timeout_ms`.execute(db);
6487
6488
  await sql`ALTER TABLE public.org_settings DROP COLUMN IF EXISTS reroute_max_hops`.execute(db);
@@ -6500,8 +6501,8 @@ async function addColumnIfMissing(db, column, type) {
6500
6501
  //#endregion
6501
6502
  //#region src/db/migrations/070_execution_runs_failure_class.ts
6502
6503
  var _070_execution_runs_failure_class_exports = /* @__PURE__ */ __exportAll({
6503
- down: () => down$38,
6504
- up: () => up$38
6504
+ down: () => down$45,
6505
+ up: () => up$45
6505
6506
  });
6506
6507
  /**
6507
6508
  * Add `execution_runs.failure_class` — the reason a terminal run failed
@@ -6512,7 +6513,7 @@ var _070_execution_runs_failure_class_exports = /* @__PURE__ */ __exportAll({
6512
6513
  * like `status`. NULL for success / not-yet-terminal runs. Nullable, no backfill,
6513
6514
  * idempotent.
6514
6515
  */
6515
- async function colExists(db, table, name) {
6516
+ async function colExists$1(db, table, name) {
6516
6517
  return (await sql`
6517
6518
  SELECT EXISTS (
6518
6519
  SELECT 1 FROM information_schema.columns
@@ -6522,17 +6523,17 @@ async function colExists(db, table, name) {
6522
6523
  ) AS exists
6523
6524
  `.execute(db)).rows[0]?.exists ?? false;
6524
6525
  }
6525
- async function up$38(db) {
6526
- if (!await colExists(db, "execution_runs", "failure_class")) await sql`ALTER TABLE public.execution_runs ADD COLUMN failure_class text`.execute(db);
6526
+ async function up$45(db) {
6527
+ if (!await colExists$1(db, "execution_runs", "failure_class")) await sql`ALTER TABLE public.execution_runs ADD COLUMN failure_class text`.execute(db);
6527
6528
  }
6528
- async function down$38(db) {
6529
+ async function down$45(db) {
6529
6530
  await sql`ALTER TABLE public.execution_runs DROP COLUMN IF EXISTS failure_class`.execute(db);
6530
6531
  }
6531
6532
  //#endregion
6532
6533
  //#region src/db/migrations/071_batch_accumulation.ts
6533
6534
  var _071_batch_accumulation_exports = /* @__PURE__ */ __exportAll({
6534
- down: () => down$37,
6535
- up: () => up$37
6535
+ down: () => down$44,
6536
+ up: () => up$44
6536
6537
  });
6537
6538
  /**
6538
6539
  * Add the batch-accumulation tables that back the `workflows_failed_batch`
@@ -6556,7 +6557,7 @@ var _071_batch_accumulation_exports = /* @__PURE__ */ __exportAll({
6556
6557
  *
6557
6558
  * Idempotent: guarded on table existence.
6558
6559
  */
6559
- async function up$37(db) {
6560
+ async function up$44(db) {
6560
6561
  if ((await sql`
6561
6562
  SELECT EXISTS (
6562
6563
  SELECT 1 FROM information_schema.tables
@@ -6601,15 +6602,15 @@ async function up$37(db) {
6601
6602
  ON public.batch_accumulation_items (window_id)
6602
6603
  `.execute(db);
6603
6604
  }
6604
- async function down$37(db) {
6605
+ async function down$44(db) {
6605
6606
  await sql`DROP TABLE IF EXISTS public.batch_accumulation_items`.execute(db);
6606
6607
  await sql`DROP TABLE IF EXISTS public.batch_accumulation_windows`.execute(db);
6607
6608
  }
6608
6609
  //#endregion
6609
6610
  //#region src/db/migrations/072_dispatch_queue_run_id_index.ts
6610
6611
  var _072_dispatch_queue_run_id_index_exports = /* @__PURE__ */ __exportAll({
6611
- down: () => down$36,
6612
- up: () => up$36
6612
+ down: () => down$43,
6613
+ up: () => up$43
6613
6614
  });
6614
6615
  /**
6615
6616
  * Add `idx_dispatch_queue_run_id` on `dispatch_queue (run_id)`.
@@ -6622,20 +6623,20 @@ var _072_dispatch_queue_run_id_index_exports = /* @__PURE__ */ __exportAll({
6622
6623
  *
6623
6624
  * Idempotent: `IF NOT EXISTS` makes a re-run a no-op.
6624
6625
  */
6625
- async function up$36(db) {
6626
+ async function up$43(db) {
6626
6627
  await sql`
6627
6628
  CREATE INDEX IF NOT EXISTS idx_dispatch_queue_run_id
6628
6629
  ON public.dispatch_queue (run_id)
6629
6630
  `.execute(db);
6630
6631
  }
6631
- async function down$36(db) {
6632
+ async function down$43(db) {
6632
6633
  await sql`DROP INDEX IF EXISTS public.idx_dispatch_queue_run_id`.execute(db);
6633
6634
  }
6634
6635
  //#endregion
6635
6636
  //#region src/db/migrations/073_org_settings_ingest_concurrency.ts
6636
6637
  var _073_org_settings_ingest_concurrency_exports = /* @__PURE__ */ __exportAll({
6637
- down: () => down$35,
6638
- up: () => up$35
6638
+ down: () => down$42,
6639
+ up: () => up$42
6639
6640
  });
6640
6641
  /**
6641
6642
  * Add `org_settings.ingest_max_concurrency BIGINT` (nullable).
@@ -6646,7 +6647,7 @@ var _073_org_settings_ingest_concurrency_exports = /* @__PURE__ */ __exportAll({
6646
6647
  *
6647
6648
  * Idempotent: a re-run on a DB that already has the column is a no-op.
6648
6649
  */
6649
- async function up$35(db) {
6650
+ async function up$42(db) {
6650
6651
  if ((await sql`
6651
6652
  SELECT EXISTS (
6652
6653
  SELECT 1 FROM information_schema.columns
@@ -6660,7 +6661,7 @@ async function up$35(db) {
6660
6661
  ADD COLUMN ingest_max_concurrency BIGINT
6661
6662
  `.execute(db);
6662
6663
  }
6663
- async function down$35(db) {
6664
+ async function down$42(db) {
6664
6665
  await sql`
6665
6666
  ALTER TABLE public.org_settings DROP COLUMN IF EXISTS ingest_max_concurrency
6666
6667
  `.execute(db);
@@ -6668,8 +6669,8 @@ async function down$35(db) {
6668
6669
  //#endregion
6669
6670
  //#region src/db/migrations/074_normalize_zero_concurrency_limit.ts
6670
6671
  var _074_normalize_zero_concurrency_limit_exports = /* @__PURE__ */ __exportAll({
6671
- down: () => down$34,
6672
- up: () => up$34
6672
+ down: () => down$41,
6673
+ up: () => up$41
6673
6674
  });
6674
6675
  /**
6675
6676
  * Normalize degenerate context concurrency limits. A `concurrency_limit` of 0
@@ -6680,15 +6681,15 @@ var _074_normalize_zero_concurrency_limit_exports = /* @__PURE__ */ __exportAll(
6680
6681
  * Idempotent; down() is a no-op (a normalized 0 cannot — and should not — be
6681
6682
  * restored).
6682
6683
  */
6683
- async function up$34(db) {
6684
+ async function up$41(db) {
6684
6685
  await sql`UPDATE public.contexts SET concurrency_limit = NULL WHERE concurrency_limit <= 0`.execute(db);
6685
6686
  }
6686
- async function down$34(_db) {}
6687
+ async function down$41(_db) {}
6687
6688
  //#endregion
6688
6689
  //#region src/db/migrations/075_ingest_overflow_buffer.ts
6689
6690
  var _075_ingest_overflow_buffer_exports = /* @__PURE__ */ __exportAll({
6690
- down: () => down$33,
6691
- up: () => up$33
6691
+ down: () => down$40,
6692
+ up: () => up$40
6692
6693
  });
6693
6694
  /**
6694
6695
  * Durable overflow buffer for shed webhook-ingest deliveries.
@@ -6702,7 +6703,7 @@ var _075_ingest_overflow_buffer_exports = /* @__PURE__ */ __exportAll({
6702
6703
  *
6703
6704
  * Idempotent: a re-run on a DB that already has the table is a no-op.
6704
6705
  */
6705
- async function up$33(db) {
6706
+ async function up$40(db) {
6706
6707
  if ((await sql`
6707
6708
  SELECT EXISTS (
6708
6709
  SELECT 1 FROM information_schema.tables
@@ -6735,14 +6736,14 @@ async function up$33(db) {
6735
6736
  ON public.ingest_overflow_buffer (delivery_id)
6736
6737
  `.execute(db);
6737
6738
  }
6738
- async function down$33(db) {
6739
+ async function down$40(db) {
6739
6740
  await sql`DROP TABLE IF EXISTS public.ingest_overflow_buffer`.execute(db);
6740
6741
  }
6741
6742
  //#endregion
6742
6743
  //#region src/db/migrations/076_artifacts.ts
6743
6744
  var _076_artifacts_exports = /* @__PURE__ */ __exportAll({
6744
- down: () => down$32,
6745
- up: () => up$32
6745
+ down: () => down$39,
6746
+ up: () => up$39
6746
6747
  });
6747
6748
  /**
6748
6749
  * Add the `artifacts` table for user-facing build artifacts and the per-org
@@ -6759,7 +6760,7 @@ var _076_artifacts_exports = /* @__PURE__ */ __exportAll({
6759
6760
  *
6760
6761
  * Idempotent: a re-run on a DB that already has the table / columns is a no-op.
6761
6762
  */
6762
- async function up$32(db) {
6763
+ async function up$39(db) {
6763
6764
  if (!(await sql`
6764
6765
  SELECT EXISTS (
6765
6766
  SELECT 1 FROM information_schema.tables
@@ -6795,7 +6796,7 @@ async function up$32(db) {
6795
6796
  ADD COLUMN IF NOT EXISTS artifact_ttl_ms BIGINT
6796
6797
  `.execute(db);
6797
6798
  }
6798
- async function down$32(db) {
6799
+ async function down$39(db) {
6799
6800
  await sql`DROP TABLE IF EXISTS public.artifacts`.execute(db);
6800
6801
  await sql`
6801
6802
  ALTER TABLE public.org_settings
@@ -6806,8 +6807,8 @@ async function down$32(db) {
6806
6807
  //#endregion
6807
6808
  //#region src/db/migrations/077_backup_runs.ts
6808
6809
  var _077_backup_runs_exports = /* @__PURE__ */ __exportAll({
6809
- down: () => down$31,
6810
- up: () => up$31
6810
+ down: () => down$38,
6811
+ up: () => up$38
6811
6812
  });
6812
6813
  /**
6813
6814
  * Add the `backup_runs` table: one row per successful `kici-admin db backup`,
@@ -6818,12 +6819,12 @@ var _077_backup_runs_exports = /* @__PURE__ */ __exportAll({
6818
6819
  *
6819
6820
  * Idempotent: guarded on table existence.
6820
6821
  */
6821
- async function up$31(db) {
6822
+ async function up$38(db) {
6822
6823
  if (await tableExists$2(db, "backup_runs")) return;
6823
6824
  await db.schema.createTable("backup_runs").addColumn("id", "bigserial", (c) => c.primaryKey()).addColumn("created_at", "timestamptz", (c) => c.notNull().defaultTo(sql`now()`)).addColumn("dump_path", "text", (c) => c.notNull()).addColumn("byte_size", "bigint", (c) => c.notNull()).addColumn("secret_key_version", "integer").addColumn("pg_server_version", "text", (c) => c.notNull()).addColumn("migrations_hash", "text", (c) => c.notNull()).addColumn("hostname", "text", (c) => c.notNull()).execute();
6824
6825
  await db.schema.createIndex("idx_backup_runs_created_at").on("backup_runs").column("created_at").execute();
6825
6826
  }
6826
- async function down$31(db) {
6827
+ async function down$38(db) {
6827
6828
  await db.schema.dropTable("backup_runs").ifExists().execute();
6828
6829
  }
6829
6830
  async function tableExists$2(db, table) {
@@ -6837,8 +6838,8 @@ async function tableExists$2(db, table) {
6837
6838
  //#endregion
6838
6839
  //#region src/db/migrations/078_org_settings_backup_staleness.ts
6839
6840
  var _078_org_settings_backup_staleness_exports = /* @__PURE__ */ __exportAll({
6840
- down: () => down$30,
6841
- up: () => up$30
6841
+ down: () => down$37,
6842
+ up: () => up$37
6842
6843
  });
6843
6844
  /**
6844
6845
  * Add the nullable `org_settings.backup_staleness_warn_hours INTEGER` column:
@@ -6848,7 +6849,7 @@ var _078_org_settings_backup_staleness_exports = /* @__PURE__ */ __exportAll({
6848
6849
  *
6849
6850
  * Idempotent: guarded on column existence.
6850
6851
  */
6851
- async function up$30(db) {
6852
+ async function up$37(db) {
6852
6853
  if ((await sql`
6853
6854
  SELECT EXISTS (
6854
6855
  SELECT 1 FROM information_schema.columns
@@ -6862,7 +6863,7 @@ async function up$30(db) {
6862
6863
  ADD COLUMN backup_staleness_warn_hours INTEGER
6863
6864
  `.execute(db);
6864
6865
  }
6865
- async function down$30(db) {
6866
+ async function down$37(db) {
6866
6867
  await sql`
6867
6868
  ALTER TABLE public.org_settings DROP COLUMN IF EXISTS backup_staleness_warn_hours
6868
6869
  `.execute(db);
@@ -6870,8 +6871,8 @@ async function down$30(db) {
6870
6871
  //#endregion
6871
6872
  //#region src/db/migrations/079_org_settings_scaler_spawn_timeout.ts
6872
6873
  var _079_org_settings_scaler_spawn_timeout_exports = /* @__PURE__ */ __exportAll({
6873
- down: () => down$29,
6874
- up: () => up$29
6874
+ down: () => down$36,
6875
+ up: () => up$36
6875
6876
  });
6876
6877
  /**
6877
6878
  * Add `org_settings.scaler_spawn_timeout_ms BIGINT` (nullable).
@@ -6883,7 +6884,7 @@ var _079_org_settings_scaler_spawn_timeout_exports = /* @__PURE__ */ __exportAll
6883
6884
  *
6884
6885
  * Idempotent: a re-run on a DB that already has the column is a no-op.
6885
6886
  */
6886
- async function up$29(db) {
6887
+ async function up$36(db) {
6887
6888
  if ((await sql`
6888
6889
  SELECT EXISTS (
6889
6890
  SELECT 1 FROM information_schema.columns
@@ -6897,7 +6898,7 @@ async function up$29(db) {
6897
6898
  ADD COLUMN scaler_spawn_timeout_ms BIGINT
6898
6899
  `.execute(db);
6899
6900
  }
6900
- async function down$29(db) {
6901
+ async function down$36(db) {
6901
6902
  await sql`
6902
6903
  ALTER TABLE public.org_settings DROP COLUMN IF EXISTS scaler_spawn_timeout_ms
6903
6904
  `.execute(db);
@@ -6905,8 +6906,8 @@ async function down$29(db) {
6905
6906
  //#endregion
6906
6907
  //#region src/db/migrations/080_cluster_settings.ts
6907
6908
  var _080_cluster_settings_exports = /* @__PURE__ */ __exportAll({
6908
- down: () => down$28,
6909
- up: () => up$28
6909
+ down: () => down$35,
6910
+ up: () => up$35
6910
6911
  });
6911
6912
  /**
6912
6913
  * Create `cluster_settings`: a single-row (id='default') table of fleet-wide
@@ -6921,7 +6922,7 @@ var _080_cluster_settings_exports = /* @__PURE__ */ __exportAll({
6921
6922
  *
6922
6923
  * Idempotent: a re-run on a DB that already has the table is a no-op.
6923
6924
  */
6924
- async function up$28(db) {
6925
+ async function up$35(db) {
6925
6926
  if ((await sql`
6926
6927
  SELECT EXISTS (
6927
6928
  SELECT 1 FROM information_schema.tables
@@ -6945,14 +6946,14 @@ async function up$28(db) {
6945
6946
  )
6946
6947
  `.execute(db);
6947
6948
  }
6948
- async function down$28(db) {
6949
+ async function down$35(db) {
6949
6950
  await sql`DROP TABLE IF EXISTS public.cluster_settings`.execute(db);
6950
6951
  }
6951
6952
  //#endregion
6952
6953
  //#region src/db/migrations/081_org_settings_queue_timeout.ts
6953
6954
  var _081_org_settings_queue_timeout_exports = /* @__PURE__ */ __exportAll({
6954
- down: () => down$27,
6955
- up: () => up$27
6955
+ down: () => down$34,
6956
+ up: () => up$34
6956
6957
  });
6957
6958
  /**
6958
6959
  * Add `org_settings.queue_timeout_ms BIGINT` (nullable).
@@ -6969,7 +6970,7 @@ var _081_org_settings_queue_timeout_exports = /* @__PURE__ */ __exportAll({
6969
6970
  *
6970
6971
  * Idempotent: a re-run on a DB that already has the column is a no-op.
6971
6972
  */
6972
- async function up$27(db) {
6973
+ async function up$34(db) {
6973
6974
  if ((await sql`
6974
6975
  SELECT EXISTS (
6975
6976
  SELECT 1 FROM information_schema.columns
@@ -6983,7 +6984,7 @@ async function up$27(db) {
6983
6984
  ADD COLUMN queue_timeout_ms BIGINT
6984
6985
  `.execute(db);
6985
6986
  }
6986
- async function down$27(db) {
6987
+ async function down$34(db) {
6987
6988
  await sql`
6988
6989
  ALTER TABLE public.org_settings DROP COLUMN IF EXISTS queue_timeout_ms
6989
6990
  `.execute(db);
@@ -6991,8 +6992,8 @@ async function down$27(db) {
6991
6992
  //#endregion
6992
6993
  //#region src/db/migrations/082_host_s3_reachable.ts
6993
6994
  var _082_host_s3_reachable_exports = /* @__PURE__ */ __exportAll({
6994
- down: () => down$26,
6995
- up: () => up$26
6995
+ down: () => down$33,
6996
+ up: () => up$33
6996
6997
  });
6997
6998
  /**
6998
6999
  * Add `host_roster.s3_reachable BOOLEAN` (nullable).
@@ -7006,7 +7007,7 @@ var _082_host_s3_reachable_exports = /* @__PURE__ */ __exportAll({
7006
7007
  *
7007
7008
  * Idempotent: a re-run on a DB that already has the column is a no-op.
7008
7009
  */
7009
- async function up$26(db) {
7010
+ async function up$33(db) {
7010
7011
  if ((await sql`
7011
7012
  SELECT EXISTS (
7012
7013
  SELECT 1 FROM information_schema.columns
@@ -7020,7 +7021,7 @@ async function up$26(db) {
7020
7021
  ADD COLUMN s3_reachable BOOLEAN
7021
7022
  `.execute(db);
7022
7023
  }
7023
- async function down$26(db) {
7024
+ async function down$33(db) {
7024
7025
  await sql`
7025
7026
  ALTER TABLE public.host_roster DROP COLUMN IF EXISTS s3_reachable
7026
7027
  `.execute(db);
@@ -7028,8 +7029,8 @@ async function down$26(db) {
7028
7029
  //#endregion
7029
7030
  //#region src/db/migrations/083_org_settings_artifact_caps.ts
7030
7031
  var _083_org_settings_artifact_caps_exports = /* @__PURE__ */ __exportAll({
7031
- down: () => down$25,
7032
- up: () => up$25
7032
+ down: () => down$32,
7033
+ up: () => up$32
7033
7034
  });
7034
7035
  /**
7035
7036
  * Add `org_settings.artifact_max_bytes` + `artifact_max_per_run` (both nullable
@@ -7045,7 +7046,7 @@ var _083_org_settings_artifact_caps_exports = /* @__PURE__ */ __exportAll({
7045
7046
  * Idempotent: guarded on column existence; a re-run on a DB that already has a
7046
7047
  * column is a no-op.
7047
7048
  */
7048
- async function up$25(db) {
7049
+ async function up$32(db) {
7049
7050
  for (const col of ["artifact_max_bytes", "artifact_max_per_run"]) {
7050
7051
  if ((await sql`
7051
7052
  SELECT EXISTS (
@@ -7058,15 +7059,15 @@ async function up$25(db) {
7058
7059
  await sql`ALTER TABLE public.org_settings ADD COLUMN ${sql.ref(col)} BIGINT`.execute(db);
7059
7060
  }
7060
7061
  }
7061
- async function down$25(db) {
7062
+ async function down$32(db) {
7062
7063
  await sql`ALTER TABLE public.org_settings DROP COLUMN IF EXISTS artifact_max_bytes`.execute(db);
7063
7064
  await sql`ALTER TABLE public.org_settings DROP COLUMN IF EXISTS artifact_max_per_run`.execute(db);
7064
7065
  }
7065
7066
  //#endregion
7066
7067
  //#region src/db/migrations/084_orchestrator_signing_keys.ts
7067
7068
  var _084_orchestrator_signing_keys_exports = /* @__PURE__ */ __exportAll({
7068
- down: () => down$24,
7069
- up: () => up$24
7069
+ down: () => down$31,
7070
+ up: () => up$31
7070
7071
  });
7071
7072
  /**
7072
7073
  * Add the `orchestrator_signing_keys` table: the cluster-scoped, long-lived
@@ -7084,12 +7085,12 @@ var _084_orchestrator_signing_keys_exports = /* @__PURE__ */ __exportAll({
7084
7085
  *
7085
7086
  * Idempotent: guarded on table existence.
7086
7087
  */
7087
- async function up$24(db) {
7088
+ async function up$31(db) {
7088
7089
  if (await tableExists$1(db, "orchestrator_signing_keys")) return;
7089
7090
  await db.schema.createTable("orchestrator_signing_keys").addColumn("kid", "text", (c) => c.primaryKey()).addColumn("public_jwk", "jsonb", (c) => c.notNull()).addColumn("encrypted_private_jwk", "text").addColumn("key_version", "integer", (c) => c.notNull().defaultTo(1)).addColumn("alg", "text", (c) => c.notNull()).addColumn("signer_kind", "text", (c) => c.notNull()).addColumn("key_ref", "text").addColumn("status", "text", (c) => c.notNull().defaultTo("active")).addColumn("revocation_reason", "text").addColumn("created_at", "timestamptz", (c) => c.notNull().defaultTo(sql`now()`)).addColumn("activated_at", "timestamptz").addColumn("retired_at", "timestamptz").addColumn("revoked_at", "timestamptz").execute();
7090
7091
  await db.schema.createIndex("idx_orch_signing_keys_status").on("orchestrator_signing_keys").column("status").execute();
7091
7092
  }
7092
- async function down$24(db) {
7093
+ async function down$31(db) {
7093
7094
  await db.schema.dropTable("orchestrator_signing_keys").ifExists().execute();
7094
7095
  }
7095
7096
  async function tableExists$1(db, table) {
@@ -7103,8 +7104,8 @@ async function tableExists$1(db, table) {
7103
7104
  //#endregion
7104
7105
  //#region src/db/migrations/085_cluster_settings_reroute_flap_grace_ms.ts
7105
7106
  var _085_cluster_settings_reroute_flap_grace_ms_exports = /* @__PURE__ */ __exportAll({
7106
- down: () => down$23,
7107
- up: () => up$23
7107
+ down: () => down$30,
7108
+ up: () => up$30
7108
7109
  });
7109
7110
  /**
7110
7111
  * Add `cluster_settings.reroute_flap_grace_ms` (nullable BIGINT).
@@ -7114,7 +7115,7 @@ var _085_cluster_settings_reroute_flap_grace_ms_exports = /* @__PURE__ */ __expo
7114
7115
  * Idempotent: guarded on column existence; a re-run on a DB that already has
7115
7116
  * the column is a no-op.
7116
7117
  */
7117
- async function up$23(db) {
7118
+ async function up$30(db) {
7118
7119
  if ((await sql`
7119
7120
  SELECT EXISTS (
7120
7121
  SELECT 1 FROM information_schema.columns
@@ -7125,14 +7126,14 @@ async function up$23(db) {
7125
7126
  `.execute(db)).rows[0]?.exists) return;
7126
7127
  await sql`ALTER TABLE public.cluster_settings ADD COLUMN reroute_flap_grace_ms BIGINT`.execute(db);
7127
7128
  }
7128
- async function down$23(db) {
7129
+ async function down$30(db) {
7129
7130
  await sql`ALTER TABLE public.cluster_settings DROP COLUMN IF EXISTS reroute_flap_grace_ms`.execute(db);
7130
7131
  }
7131
7132
  //#endregion
7132
7133
  //#region src/db/migrations/086_cluster_settings_max_fanout_hosts.ts
7133
7134
  var _086_cluster_settings_max_fanout_hosts_exports = /* @__PURE__ */ __exportAll({
7134
- down: () => down$22,
7135
- up: () => up$22
7135
+ down: () => down$29,
7136
+ up: () => up$29
7136
7137
  });
7137
7138
  /**
7138
7139
  * Add `cluster_settings.max_fanout_hosts` (nullable INTEGER).
@@ -7142,7 +7143,7 @@ var _086_cluster_settings_max_fanout_hosts_exports = /* @__PURE__ */ __exportAll
7142
7143
  * Idempotent: guarded on column existence; a re-run on a DB that already has
7143
7144
  * the column is a no-op.
7144
7145
  */
7145
- async function up$22(db) {
7146
+ async function up$29(db) {
7146
7147
  if ((await sql`
7147
7148
  SELECT EXISTS (
7148
7149
  SELECT 1 FROM information_schema.columns
@@ -7153,14 +7154,14 @@ async function up$22(db) {
7153
7154
  `.execute(db)).rows[0]?.exists) return;
7154
7155
  await sql`ALTER TABLE public.cluster_settings ADD COLUMN max_fanout_hosts INTEGER`.execute(db);
7155
7156
  }
7156
- async function down$22(db) {
7157
+ async function down$29(db) {
7157
7158
  await sql`ALTER TABLE public.cluster_settings DROP COLUMN IF EXISTS max_fanout_hosts`.execute(db);
7158
7159
  }
7159
7160
  //#endregion
7160
7161
  //#region src/db/migrations/087_cluster_settings_event_router_rate_limit.ts
7161
7162
  var _087_cluster_settings_event_router_rate_limit_exports = /* @__PURE__ */ __exportAll({
7162
- down: () => down$21,
7163
- up: () => up$21
7163
+ down: () => down$28,
7164
+ up: () => up$28
7164
7165
  });
7165
7166
  /**
7166
7167
  * Add `cluster_settings.event_router_rate_limit_per_workflow_per_minute` (nullable INTEGER).
@@ -7170,7 +7171,7 @@ var _087_cluster_settings_event_router_rate_limit_exports = /* @__PURE__ */ __ex
7170
7171
  * Idempotent: guarded on column existence; a re-run on a DB that already has
7171
7172
  * the column is a no-op.
7172
7173
  */
7173
- async function up$21(db) {
7174
+ async function up$28(db) {
7174
7175
  if ((await sql`
7175
7176
  SELECT EXISTS (
7176
7177
  SELECT 1 FROM information_schema.columns
@@ -7181,14 +7182,14 @@ async function up$21(db) {
7181
7182
  `.execute(db)).rows[0]?.exists) return;
7182
7183
  await sql`ALTER TABLE public.cluster_settings ADD COLUMN event_router_rate_limit_per_workflow_per_minute INTEGER`.execute(db);
7183
7184
  }
7184
- async function down$21(db) {
7185
+ async function down$28(db) {
7185
7186
  await sql`ALTER TABLE public.cluster_settings DROP COLUMN IF EXISTS event_router_rate_limit_per_workflow_per_minute`.execute(db);
7186
7187
  }
7187
7188
  //#endregion
7188
7189
  //#region src/db/migrations/088_cluster_settings_cache_max_tarball_bytes.ts
7189
7190
  var _088_cluster_settings_cache_max_tarball_bytes_exports = /* @__PURE__ */ __exportAll({
7190
- down: () => down$20,
7191
- up: () => up$20
7191
+ down: () => down$27,
7192
+ up: () => up$27
7192
7193
  });
7193
7194
  /**
7194
7195
  * Add `cluster_settings.cache_max_tarball_bytes` (nullable BIGINT).
@@ -7198,7 +7199,7 @@ var _088_cluster_settings_cache_max_tarball_bytes_exports = /* @__PURE__ */ __ex
7198
7199
  * Idempotent: guarded on column existence; a re-run on a DB that already has
7199
7200
  * the column is a no-op.
7200
7201
  */
7201
- async function up$20(db) {
7202
+ async function up$27(db) {
7202
7203
  if ((await sql`
7203
7204
  SELECT EXISTS (
7204
7205
  SELECT 1 FROM information_schema.columns
@@ -7209,14 +7210,14 @@ async function up$20(db) {
7209
7210
  `.execute(db)).rows[0]?.exists) return;
7210
7211
  await sql`ALTER TABLE public.cluster_settings ADD COLUMN cache_max_tarball_bytes BIGINT`.execute(db);
7211
7212
  }
7212
- async function down$20(db) {
7213
+ async function down$27(db) {
7213
7214
  await sql`ALTER TABLE public.cluster_settings DROP COLUMN IF EXISTS cache_max_tarball_bytes`.execute(db);
7214
7215
  }
7215
7216
  //#endregion
7216
7217
  //#region src/db/migrations/089_cluster_settings_cache_ttl_days.ts
7217
7218
  var _089_cluster_settings_cache_ttl_days_exports = /* @__PURE__ */ __exportAll({
7218
- down: () => down$19,
7219
- up: () => up$19
7219
+ down: () => down$26,
7220
+ up: () => up$26
7220
7221
  });
7221
7222
  /**
7222
7223
  * Add `cluster_settings.cache_ttl_days` (nullable INTEGER).
@@ -7226,7 +7227,7 @@ var _089_cluster_settings_cache_ttl_days_exports = /* @__PURE__ */ __exportAll({
7226
7227
  * Idempotent: guarded on column existence; a re-run on a DB that already has
7227
7228
  * the column is a no-op.
7228
7229
  */
7229
- async function up$19(db) {
7230
+ async function up$26(db) {
7230
7231
  if ((await sql`
7231
7232
  SELECT EXISTS (
7232
7233
  SELECT 1 FROM information_schema.columns
@@ -7237,14 +7238,14 @@ async function up$19(db) {
7237
7238
  `.execute(db)).rows[0]?.exists) return;
7238
7239
  await sql`ALTER TABLE public.cluster_settings ADD COLUMN cache_ttl_days INTEGER`.execute(db);
7239
7240
  }
7240
- async function down$19(db) {
7241
+ async function down$26(db) {
7241
7242
  await sql`ALTER TABLE public.cluster_settings DROP COLUMN IF EXISTS cache_ttl_days`.execute(db);
7242
7243
  }
7243
7244
  //#endregion
7244
7245
  //#region src/db/migrations/090_cluster_settings_concurrency_wait_timeout_ms.ts
7245
7246
  var _090_cluster_settings_concurrency_wait_timeout_ms_exports = /* @__PURE__ */ __exportAll({
7246
- down: () => down$18,
7247
- up: () => up$18
7247
+ down: () => down$25,
7248
+ up: () => up$25
7248
7249
  });
7249
7250
  /**
7250
7251
  * Add `cluster_settings.concurrency_wait_timeout_ms` (nullable BIGINT).
@@ -7254,7 +7255,7 @@ var _090_cluster_settings_concurrency_wait_timeout_ms_exports = /* @__PURE__ */
7254
7255
  * Idempotent: guarded on column existence; a re-run on a DB that already has
7255
7256
  * the column is a no-op.
7256
7257
  */
7257
- async function up$18(db) {
7258
+ async function up$25(db) {
7258
7259
  if ((await sql`
7259
7260
  SELECT EXISTS (
7260
7261
  SELECT 1 FROM information_schema.columns
@@ -7265,14 +7266,14 @@ async function up$18(db) {
7265
7266
  `.execute(db)).rows[0]?.exists) return;
7266
7267
  await sql`ALTER TABLE public.cluster_settings ADD COLUMN concurrency_wait_timeout_ms BIGINT`.execute(db);
7267
7268
  }
7268
- async function down$18(db) {
7269
+ async function down$25(db) {
7269
7270
  await sql`ALTER TABLE public.cluster_settings DROP COLUMN IF EXISTS concurrency_wait_timeout_ms`.execute(db);
7270
7271
  }
7271
7272
  //#endregion
7272
7273
  //#region src/db/migrations/091_cluster_settings_agent_token_ttl_ms.ts
7273
7274
  var _091_cluster_settings_agent_token_ttl_ms_exports = /* @__PURE__ */ __exportAll({
7274
- down: () => down$17,
7275
- up: () => up$17
7275
+ down: () => down$24,
7276
+ up: () => up$24
7276
7277
  });
7277
7278
  /**
7278
7279
  * Add `cluster_settings.agent_token_ttl_ms` (nullable BIGINT).
@@ -7282,7 +7283,7 @@ var _091_cluster_settings_agent_token_ttl_ms_exports = /* @__PURE__ */ __exportA
7282
7283
  * Idempotent: guarded on column existence; a re-run on a DB that already has
7283
7284
  * the column is a no-op.
7284
7285
  */
7285
- async function up$17(db) {
7286
+ async function up$24(db) {
7286
7287
  if ((await sql`
7287
7288
  SELECT EXISTS (
7288
7289
  SELECT 1 FROM information_schema.columns
@@ -7293,14 +7294,14 @@ async function up$17(db) {
7293
7294
  `.execute(db)).rows[0]?.exists) return;
7294
7295
  await sql`ALTER TABLE public.cluster_settings ADD COLUMN agent_token_ttl_ms BIGINT`.execute(db);
7295
7296
  }
7296
- async function down$17(db) {
7297
+ async function down$24(db) {
7297
7298
  await sql`ALTER TABLE public.cluster_settings DROP COLUMN IF EXISTS agent_token_ttl_ms`.execute(db);
7298
7299
  }
7299
7300
  //#endregion
7300
7301
  //#region src/db/migrations/092_cluster_settings_version.ts
7301
7302
  var _092_cluster_settings_version_exports = /* @__PURE__ */ __exportAll({
7302
- down: () => down$16,
7303
- up: () => up$16
7303
+ down: () => down$23,
7304
+ up: () => up$23
7304
7305
  });
7305
7306
  /**
7306
7307
  * Add `cluster_settings.version` (monotonic BIGINT, bumped on each settings
@@ -7314,7 +7315,7 @@ var _092_cluster_settings_version_exports = /* @__PURE__ */ __exportAll({
7314
7315
  * Idempotent: guarded on column existence; a re-run on a DB that already has
7315
7316
  * the column is a no-op.
7316
7317
  */
7317
- async function up$16(db) {
7318
+ async function up$23(db) {
7318
7319
  if ((await sql`
7319
7320
  SELECT EXISTS (
7320
7321
  SELECT 1 FROM information_schema.columns
@@ -7325,14 +7326,14 @@ async function up$16(db) {
7325
7326
  `.execute(db)).rows[0]?.exists) return;
7326
7327
  await sql`ALTER TABLE public.cluster_settings ADD COLUMN version BIGINT NOT NULL DEFAULT 0`.execute(db);
7327
7328
  }
7328
- async function down$16(db) {
7329
+ async function down$23(db) {
7329
7330
  await sql`ALTER TABLE public.cluster_settings DROP COLUMN IF EXISTS version`.execute(db);
7330
7331
  }
7331
7332
  //#endregion
7332
7333
  //#region src/db/migrations/093_org_settings_sandbox_allowlist.ts
7333
7334
  var _093_org_settings_sandbox_allowlist_exports = /* @__PURE__ */ __exportAll({
7334
- down: () => down$15,
7335
- up: () => up$15
7335
+ down: () => down$22,
7336
+ up: () => up$22
7336
7337
  });
7337
7338
  /**
7338
7339
  * Add the per-org container-sandbox escape-hatch allow-list to `org_settings`:
@@ -7350,7 +7351,7 @@ var _093_org_settings_sandbox_allowlist_exports = /* @__PURE__ */ __exportAll({
7350
7351
  *
7351
7352
  * Idempotent: a re-run on a DB that already has a column skips that column.
7352
7353
  */
7353
- async function columnExists$4(db, column) {
7354
+ async function columnExists$9(db, column) {
7354
7355
  return (await sql`
7355
7356
  SELECT EXISTS (
7356
7357
  SELECT 1 FROM information_schema.columns
@@ -7360,17 +7361,17 @@ async function columnExists$4(db, column) {
7360
7361
  ) AS exists
7361
7362
  `.execute(db)).rows[0]?.exists ?? false;
7362
7363
  }
7363
- async function up$15(db) {
7364
- if (!await columnExists$4(db, "sandbox_allowed_capabilities")) await sql`
7364
+ async function up$22(db) {
7365
+ if (!await columnExists$9(db, "sandbox_allowed_capabilities")) await sql`
7365
7366
  ALTER TABLE public.org_settings
7366
7367
  ADD COLUMN sandbox_allowed_capabilities TEXT[]
7367
7368
  `.execute(db);
7368
- if (!await columnExists$4(db, "sandbox_allow_host_network")) await sql`
7369
+ if (!await columnExists$9(db, "sandbox_allow_host_network")) await sql`
7369
7370
  ALTER TABLE public.org_settings
7370
7371
  ADD COLUMN sandbox_allow_host_network BOOLEAN
7371
7372
  `.execute(db);
7372
7373
  }
7373
- async function down$15(db) {
7374
+ async function down$22(db) {
7374
7375
  await sql`
7375
7376
  ALTER TABLE public.org_settings DROP COLUMN IF EXISTS sandbox_allowed_capabilities
7376
7377
  `.execute(db);
@@ -7381,8 +7382,8 @@ async function down$15(db) {
7381
7382
  //#endregion
7382
7383
  //#region src/db/migrations/094_dashboard_encryption_keys.ts
7383
7384
  var _094_dashboard_encryption_keys_exports = /* @__PURE__ */ __exportAll({
7384
- down: () => down$14,
7385
- up: () => up$14
7385
+ down: () => down$21,
7386
+ up: () => up$21
7386
7387
  });
7387
7388
  /**
7388
7389
  * Add the `dashboard_encryption_keys` table: the cluster-scoped, long-lived
@@ -7401,12 +7402,12 @@ var _094_dashboard_encryption_keys_exports = /* @__PURE__ */ __exportAll({
7401
7402
  *
7402
7403
  * Idempotent: guarded on table existence.
7403
7404
  */
7404
- async function up$14(db) {
7405
+ async function up$21(db) {
7405
7406
  if (await tableExists(db, "dashboard_encryption_keys")) return;
7406
7407
  await db.schema.createTable("dashboard_encryption_keys").addColumn("kid", "text", (c) => c.primaryKey()).addColumn("public_jwk", "jsonb", (c) => c.notNull()).addColumn("encrypted_private_key", "text", (c) => c.notNull()).addColumn("status", "text", (c) => c.notNull().defaultTo("active")).addColumn("revocation_reason", "text").addColumn("created_at", "timestamptz", (c) => c.notNull().defaultTo(sql`now()`)).addColumn("activated_at", "timestamptz").addColumn("revoked_at", "timestamptz").execute();
7407
7408
  await db.schema.createIndex("idx_dashboard_encryption_keys_status").on("dashboard_encryption_keys").column("status").execute();
7408
7409
  }
7409
- async function down$14(db) {
7410
+ async function down$21(db) {
7410
7411
  await db.schema.dropTable("dashboard_encryption_keys").ifExists().execute();
7411
7412
  }
7412
7413
  async function tableExists(db, table) {
@@ -7420,8 +7421,8 @@ async function tableExists(db, table) {
7420
7421
  //#endregion
7421
7422
  //#region src/db/migrations/095_dashboard_write_policy_tristate.ts
7422
7423
  var _095_dashboard_write_policy_tristate_exports = /* @__PURE__ */ __exportAll({
7423
- down: () => down$13,
7424
- up: () => up$13
7424
+ down: () => down$20,
7425
+ up: () => up$20
7425
7426
  });
7426
7427
  /**
7427
7428
  * Migrate stored `org_settings.dashboard_write_policy` JSONB from the legacy
@@ -7439,7 +7440,7 @@ var _095_dashboard_write_policy_tristate_exports = /* @__PURE__ */ __exportAll({
7439
7440
  * Pure SQL rewrite: for each row, rebuild the object keeping only non-`true`
7440
7441
  * entries and mapping `false` → `'disabled'`, leaving existing string values.
7441
7442
  */
7442
- async function up$13(db) {
7443
+ async function up$20(db) {
7443
7444
  await sql`
7444
7445
  UPDATE org_settings
7445
7446
  SET dashboard_write_policy = COALESCE(
@@ -7466,12 +7467,12 @@ async function up$13(db) {
7466
7467
  )
7467
7468
  `.execute(db);
7468
7469
  }
7469
- async function down$13() {}
7470
+ async function down$20() {}
7470
7471
  //#endregion
7471
7472
  //#region src/db/migrations/096_multi_schedule_cron_last_fired.ts
7472
7473
  var _096_multi_schedule_cron_last_fired_exports = /* @__PURE__ */ __exportAll({
7473
- down: () => down$12,
7474
- up: () => up$12
7474
+ down: () => down$19,
7475
+ up: () => up$19
7475
7476
  });
7476
7477
  /**
7477
7478
  * Track cron last-fired per (registration, schedule) instead of per
@@ -7486,7 +7487,7 @@ var _096_multi_schedule_cron_last_fired_exports = /* @__PURE__ */ __exportAll({
7486
7487
  *
7487
7488
  * Idempotent: re-running on an already-migrated DB skips each step.
7488
7489
  */
7489
- async function columnExists$3(db, column) {
7490
+ async function columnExists$8(db, column) {
7490
7491
  return (await sql`
7491
7492
  SELECT EXISTS (
7492
7493
  SELECT 1 FROM information_schema.columns
@@ -7506,8 +7507,8 @@ async function primaryKeyColumns(db) {
7506
7507
  ORDER BY a.attnum
7507
7508
  `.execute(db)).rows.map((row) => row.attname);
7508
7509
  }
7509
- async function up$12(db) {
7510
- if (!await columnExists$3(db, "schedule_key")) await sql`ALTER TABLE public.cron_last_fired ADD COLUMN schedule_key text`.execute(db);
7510
+ async function up$19(db) {
7511
+ if (!await columnExists$8(db, "schedule_key")) await sql`ALTER TABLE public.cron_last_fired ADD COLUMN schedule_key text`.execute(db);
7511
7512
  await sql`
7512
7513
  UPDATE public.cron_last_fired clf
7513
7514
  SET schedule_key = k.key
@@ -7533,7 +7534,7 @@ async function up$12(db) {
7533
7534
  `.execute(db);
7534
7535
  }
7535
7536
  }
7536
- async function down$12(db) {
7537
+ async function down$19(db) {
7537
7538
  await sql`
7538
7539
  DELETE FROM public.cron_last_fired a
7539
7540
  USING public.cron_last_fired b
@@ -7545,13 +7546,13 @@ async function down$12(db) {
7545
7546
  ALTER TABLE public.cron_last_fired
7546
7547
  ADD CONSTRAINT cron_last_fired_pkey PRIMARY KEY (registration_id)
7547
7548
  `.execute(db);
7548
- if (await columnExists$3(db, "schedule_key")) await sql`ALTER TABLE public.cron_last_fired DROP COLUMN schedule_key`.execute(db);
7549
+ if (await columnExists$8(db, "schedule_key")) await sql`ALTER TABLE public.cron_last_fired DROP COLUMN schedule_key`.execute(db);
7549
7550
  }
7550
7551
  //#endregion
7551
7552
  //#region src/db/migrations/097_execution_runs_pr_number.ts
7552
7553
  var _097_execution_runs_pr_number_exports = /* @__PURE__ */ __exportAll({
7553
- down: () => down$11,
7554
- up: () => up$11
7554
+ down: () => down$18,
7555
+ up: () => up$18
7555
7556
  });
7556
7557
  /**
7557
7558
  * Add `pr_number INTEGER NULL` to `execution_runs`.
@@ -7564,7 +7565,7 @@ var _097_execution_runs_pr_number_exports = /* @__PURE__ */ __exportAll({
7564
7565
  *
7565
7566
  * Idempotent: a re-run on a DB that already has the column is a no-op.
7566
7567
  */
7567
- async function columnExists$2(db, column) {
7568
+ async function columnExists$7(db, column) {
7568
7569
  return (await sql`
7569
7570
  SELECT EXISTS (
7570
7571
  SELECT 1 FROM information_schema.columns
@@ -7574,13 +7575,13 @@ async function columnExists$2(db, column) {
7574
7575
  ) AS exists
7575
7576
  `.execute(db)).rows[0]?.exists ?? false;
7576
7577
  }
7577
- async function up$11(db) {
7578
- if (!await columnExists$2(db, "pr_number")) await sql`
7578
+ async function up$18(db) {
7579
+ if (!await columnExists$7(db, "pr_number")) await sql`
7579
7580
  ALTER TABLE public.execution_runs
7580
7581
  ADD COLUMN pr_number INTEGER
7581
7582
  `.execute(db);
7582
7583
  }
7583
- async function down$11(db) {
7584
+ async function down$18(db) {
7584
7585
  await sql`
7585
7586
  ALTER TABLE public.execution_runs DROP COLUMN IF EXISTS pr_number
7586
7587
  `.execute(db);
@@ -7588,8 +7589,8 @@ async function down$11(db) {
7588
7589
  //#endregion
7589
7590
  //#region src/db/migrations/098_execution_runs_customer_id.ts
7590
7591
  var _098_execution_runs_customer_id_exports = /* @__PURE__ */ __exportAll({
7591
- down: () => down$10,
7592
- up: () => up$10
7592
+ down: () => down$17,
7593
+ up: () => up$17
7593
7594
  });
7594
7595
  /**
7595
7596
  * Denormalize the owning org onto `execution_runs` so the concurrency-gate
@@ -7607,7 +7608,7 @@ var _098_execution_runs_customer_id_exports = /* @__PURE__ */ __exportAll({
7607
7608
  *
7608
7609
  * Idempotent: re-running skips the column when it already exists.
7609
7610
  */
7610
- async function columnExists$1(db, column) {
7611
+ async function columnExists$6(db, column) {
7611
7612
  return (await sql`
7612
7613
  SELECT EXISTS (
7613
7614
  SELECT 1 FROM information_schema.columns
@@ -7617,8 +7618,8 @@ async function columnExists$1(db, column) {
7617
7618
  ) AS exists
7618
7619
  `.execute(db)).rows[0]?.exists ?? false;
7619
7620
  }
7620
- async function up$10(db) {
7621
- if (!await columnExists$1(db, "customer_id")) {
7621
+ async function up$17(db) {
7622
+ if (!await columnExists$6(db, "customer_id")) {
7622
7623
  await sql`
7623
7624
  ALTER TABLE public.execution_runs
7624
7625
  ADD COLUMN customer_id TEXT NOT NULL DEFAULT '__default__'
@@ -7641,7 +7642,7 @@ async function up$10(db) {
7641
7642
  ON public.execution_runs (customer_id, context)
7642
7643
  `.execute(db);
7643
7644
  }
7644
- async function down$10(db) {
7645
+ async function down$17(db) {
7645
7646
  await sql`DROP INDEX IF EXISTS execution_runs_customer_id_context_idx`.execute(db);
7646
7647
  await sql`
7647
7648
  ALTER TABLE public.execution_runs DROP COLUMN IF EXISTS customer_id
@@ -7650,8 +7651,8 @@ async function down$10(db) {
7650
7651
  //#endregion
7651
7652
  //#region src/db/migrations/099_cluster_settings_dashboard_verified_issuer.ts
7652
7653
  var _099_cluster_settings_dashboard_verified_issuer_exports = /* @__PURE__ */ __exportAll({
7653
- down: () => down$9,
7654
- up: () => up$9
7654
+ down: () => down$16,
7655
+ up: () => up$16
7655
7656
  });
7656
7657
  /**
7657
7658
  * Add `cluster_settings.dashboard_verified_issuer` (nullable text).
@@ -7670,7 +7671,7 @@ var _099_cluster_settings_dashboard_verified_issuer_exports = /* @__PURE__ */ __
7670
7671
  * Idempotent: guarded on column existence; a re-run on a DB that already has the
7671
7672
  * column is a no-op.
7672
7673
  */
7673
- async function up$9(db) {
7674
+ async function up$16(db) {
7674
7675
  if ((await sql`
7675
7676
  SELECT EXISTS (
7676
7677
  SELECT 1 FROM information_schema.columns
@@ -7681,14 +7682,14 @@ async function up$9(db) {
7681
7682
  `.execute(db)).rows[0]?.exists) return;
7682
7683
  await sql`ALTER TABLE public.cluster_settings ADD COLUMN dashboard_verified_issuer TEXT`.execute(db);
7683
7684
  }
7684
- async function down$9(db) {
7685
+ async function down$16(db) {
7685
7686
  await sql`ALTER TABLE public.cluster_settings DROP COLUMN IF EXISTS dashboard_verified_issuer`.execute(db);
7686
7687
  }
7687
7688
  //#endregion
7688
7689
  //#region src/db/migrations/100_held_runs_hold_type_vocabulary.ts
7689
7690
  var _100_held_runs_hold_type_vocabulary_exports = /* @__PURE__ */ __exportAll({
7690
- down: () => down$8,
7691
- up: () => up$8
7691
+ down: () => down$15,
7692
+ up: () => up$15
7692
7693
  });
7693
7694
  /**
7694
7695
  * Realign `held_runs.hold_type` onto the engine's `HoldType` vocabulary.
@@ -7707,7 +7708,7 @@ var _100_held_runs_hold_type_vocabulary_exports = /* @__PURE__ */ __exportAll({
7707
7708
  *
7708
7709
  * Idempotent: a second run matches no rows.
7709
7710
  */
7710
- async function up$8(db) {
7711
+ async function up$15(db) {
7711
7712
  await sql`UPDATE public.held_runs SET hold_type = 'reviewer' WHERE hold_type = 'approval'`.execute(db);
7712
7713
  await sql`UPDATE public.held_runs SET hold_type = 'timer' WHERE hold_type = 'wait_timer'`.execute(db);
7713
7714
  }
@@ -7721,15 +7722,15 @@ async function up$8(db) {
7721
7722
  * `wait_timer` alone, so leaving those rows spelled `timer` would strand them
7722
7723
  * in the expire-and-fail path.
7723
7724
  */
7724
- async function down$8(db) {
7725
+ async function down$15(db) {
7725
7726
  await sql`UPDATE public.held_runs SET hold_type = 'approval' WHERE hold_type = 'reviewer'`.execute(db);
7726
7727
  await sql`UPDATE public.held_runs SET hold_type = 'wait_timer' WHERE hold_type = 'timer'`.execute(db);
7727
7728
  }
7728
7729
  //#endregion
7729
7730
  //#region src/db/migrations/101_contexts_hold_expiry_drop_default.ts
7730
7731
  var _101_contexts_hold_expiry_drop_default_exports = /* @__PURE__ */ __exportAll({
7731
- down: () => down$7,
7732
- up: () => up$7
7732
+ down: () => down$14,
7733
+ up: () => up$14
7733
7734
  });
7734
7735
  /**
7735
7736
  * Give the context hold expiry a single default, and retire the stored zeroes.
@@ -7750,7 +7751,7 @@ var _101_contexts_hold_expiry_drop_default_exports = /* @__PURE__ */ __exportAll
7750
7751
  * Idempotent: dropping an absent default is a no-op and the UPDATE matches no
7751
7752
  * rows on a second run.
7752
7753
  */
7753
- async function up$7(db) {
7754
+ async function up$14(db) {
7754
7755
  await sql`ALTER TABLE public.contexts ALTER COLUMN hold_expiry_seconds DROP DEFAULT`.execute(db);
7755
7756
  await sql`UPDATE public.contexts SET hold_expiry_seconds = NULL WHERE hold_expiry_seconds = 0`.execute(db);
7756
7757
  }
@@ -7762,14 +7763,14 @@ async function up$7(db) {
7762
7763
  * back to `0` would resume cancelling every hold on its context — so a
7763
7764
  * rollback keeps them on the fallback rather than re-breaking them.
7764
7765
  */
7765
- async function down$7(db) {
7766
+ async function down$14(db) {
7766
7767
  await sql`ALTER TABLE public.contexts ALTER COLUMN hold_expiry_seconds SET DEFAULT 86400`.execute(db);
7767
7768
  }
7768
7769
  //#endregion
7769
7770
  //#region src/db/migrations/102_dispatch_queue_agent_id.ts
7770
7771
  var _102_dispatch_queue_agent_id_exports = /* @__PURE__ */ __exportAll({
7771
- down: () => down$6,
7772
- up: () => up$6
7772
+ down: () => down$13,
7773
+ up: () => up$13
7773
7774
  });
7774
7775
  /**
7775
7776
  * Add `dispatch_queue.agent_id` (nullable text).
@@ -7787,7 +7788,7 @@ var _102_dispatch_queue_agent_id_exports = /* @__PURE__ */ __exportAll({
7787
7788
  * Idempotent: guarded on column existence; a re-run on a DB that already has the
7788
7789
  * column is a no-op.
7789
7790
  */
7790
- async function up$6(db) {
7791
+ async function up$13(db) {
7791
7792
  if ((await sql`
7792
7793
  SELECT EXISTS (
7793
7794
  SELECT 1 FROM information_schema.columns
@@ -7798,14 +7799,14 @@ async function up$6(db) {
7798
7799
  `.execute(db)).rows[0]?.exists) return;
7799
7800
  await sql`ALTER TABLE public.dispatch_queue ADD COLUMN agent_id TEXT`.execute(db);
7800
7801
  }
7801
- async function down$6(db) {
7802
+ async function down$13(db) {
7802
7803
  await sql`ALTER TABLE public.dispatch_queue DROP COLUMN IF EXISTS agent_id`.execute(db);
7803
7804
  }
7804
7805
  //#endregion
7805
7806
  //#region src/db/migrations/103_cluster_settings_ownership_db_check_timeout_ms.ts
7806
7807
  var _103_cluster_settings_ownership_db_check_timeout_ms_exports = /* @__PURE__ */ __exportAll({
7807
- down: () => down$5,
7808
- up: () => up$5
7808
+ down: () => down$12,
7809
+ up: () => up$12
7809
7810
  });
7810
7811
  /**
7811
7812
  * Add `cluster_settings.ownership_db_check_timeout_ms` (nullable bigint).
@@ -7823,7 +7824,7 @@ var _103_cluster_settings_ownership_db_check_timeout_ms_exports = /* @__PURE__ *
7823
7824
  * Idempotent: guarded on column existence; a re-run on a DB that already has the
7824
7825
  * column is a no-op.
7825
7826
  */
7826
- async function up$5(db) {
7827
+ async function up$12(db) {
7827
7828
  if ((await sql`
7828
7829
  SELECT EXISTS (
7829
7830
  SELECT 1 FROM information_schema.columns
@@ -7834,14 +7835,14 @@ async function up$5(db) {
7834
7835
  `.execute(db)).rows[0]?.exists) return;
7835
7836
  await sql`ALTER TABLE public.cluster_settings ADD COLUMN ownership_db_check_timeout_ms BIGINT`.execute(db);
7836
7837
  }
7837
- async function down$5(db) {
7838
+ async function down$12(db) {
7838
7839
  await sql`ALTER TABLE public.cluster_settings DROP COLUMN IF EXISTS ownership_db_check_timeout_ms`.execute(db);
7839
7840
  }
7840
7841
  //#endregion
7841
7842
  //#region src/db/migrations/104_check_run_terminal_sent.ts
7842
7843
  var _104_check_run_terminal_sent_exports = /* @__PURE__ */ __exportAll({
7843
- down: () => down$4,
7844
- up: () => up$4
7844
+ down: () => down$11,
7845
+ up: () => up$11
7845
7846
  });
7846
7847
  /**
7847
7848
  * Add `check_run_tracking.terminal_sent_at` (nullable timestamptz).
@@ -7853,157 +7854,475 @@ var _104_check_run_terminal_sent_exports = /* @__PURE__ */ __exportAll({
7853
7854
  * unattributable: nothing on our side recorded whether the terminal update had
7854
7855
  * been sent at all.
7855
7856
  *
7856
- * Stamped only after the provider accepts a `completed` update. Nullable and
7857
- * best-effort like every write on this table — a tracking write must never
7858
- * break check-run reporting — so NULL means "we have no record of sending it",
7859
- * not "it was never sent".
7857
+ * Stamped only after the provider accepts a `completed` update. Nullable and
7858
+ * best-effort like every write on this table — a tracking write must never
7859
+ * break check-run reporting — so NULL means "we have no record of sending it",
7860
+ * not "it was never sent".
7861
+ *
7862
+ * Idempotent: guarded on column existence; a re-run on a DB that already has
7863
+ * the column is a no-op.
7864
+ */
7865
+ async function up$11(db) {
7866
+ if ((await sql`
7867
+ SELECT EXISTS (
7868
+ SELECT 1 FROM information_schema.columns
7869
+ WHERE table_schema = 'public'
7870
+ AND table_name = 'check_run_tracking'
7871
+ AND column_name = 'terminal_sent_at'
7872
+ ) AS exists
7873
+ `.execute(db)).rows[0]?.exists) return;
7874
+ await sql`ALTER TABLE public.check_run_tracking ADD COLUMN terminal_sent_at TIMESTAMPTZ`.execute(db);
7875
+ }
7876
+ async function down$11(db) {
7877
+ await sql`ALTER TABLE public.check_run_tracking DROP COLUMN IF EXISTS terminal_sent_at`.execute(db);
7878
+ }
7879
+ //#endregion
7880
+ //#region src/db/migrations/105_org_trust_policy.ts
7881
+ var _105_org_trust_policy_exports = /* @__PURE__ */ __exportAll({
7882
+ down: () => down$10,
7883
+ up: () => up$10
7884
+ });
7885
+ /**
7886
+ * Create `org_trust_policy` — the orchestrator's cache of the Platform-owned org
7887
+ * trust policy pushed on `trust_policy.update`.
7888
+ *
7889
+ * A dedicated table rather than `org_settings` columns, because this is
7890
+ * Platform-owned policy the orchestrator consumes, not operator-owned config the
7891
+ * operator tunes. `source` records which of the two wrote the row so the admin
7892
+ * surface can present a Platform-managed policy as read-only.
7893
+ *
7894
+ * Persisting rather than caching in memory is deliberate: a security policy that
7895
+ * silently reverts to a default across a restart is worse than one that is never
7896
+ * applied.
7897
+ *
7898
+ * Idempotent: guarded by IF NOT EXISTS, so a re-run is a no-op.
7899
+ */
7900
+ async function up$10(db) {
7901
+ await sql`
7902
+ CREATE TABLE IF NOT EXISTS public.org_trust_policy (
7903
+ customer_id TEXT PRIMARY KEY,
7904
+ fork_policy TEXT NOT NULL,
7905
+ unknown_contributor_policy TEXT NOT NULL,
7906
+ workflow_change_policy TEXT NOT NULL,
7907
+ approval_expiry_hours INTEGER NOT NULL,
7908
+ source TEXT NOT NULL,
7909
+ updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
7910
+ )
7911
+ `.execute(db);
7912
+ }
7913
+ async function down$10(db) {
7914
+ await sql`DROP TABLE IF EXISTS public.org_trust_policy`.execute(db);
7915
+ }
7916
+ //#endregion
7917
+ //#region src/db/migrations/106_cluster_settings_check_run_tracking_ttl_days.ts
7918
+ var _106_cluster_settings_check_run_tracking_ttl_days_exports = /* @__PURE__ */ __exportAll({
7919
+ down: () => down$9,
7920
+ up: () => up$9
7921
+ });
7922
+ /**
7923
+ * Add `cluster_settings.check_run_tracking_ttl_days` (nullable integer).
7924
+ *
7925
+ * Retention window for `check_run_tracking` rows. The hourly cleanup sweep
7926
+ * deletes rows untouched for longer than this; 0 disables the sweep.
7927
+ *
7928
+ * Cluster-global (the sweep runs once per fleet on the cleanup tick, with no
7929
+ * tenant in scope at the read site), so it lives on `cluster_settings` rather
7930
+ * than `org_settings`. NULL means the orchestrator's own configured default
7931
+ * applies.
7932
+ *
7933
+ * Idempotent: guarded on column existence; a re-run on a database that already
7934
+ * has the column is a no-op.
7935
+ */
7936
+ async function up$9(db) {
7937
+ if ((await sql`
7938
+ SELECT EXISTS (
7939
+ SELECT 1 FROM information_schema.columns
7940
+ WHERE table_schema = 'public'
7941
+ AND table_name = 'cluster_settings'
7942
+ AND column_name = 'check_run_tracking_ttl_days'
7943
+ ) AS exists
7944
+ `.execute(db)).rows[0]?.exists) return;
7945
+ await sql`ALTER TABLE public.cluster_settings ADD COLUMN check_run_tracking_ttl_days INTEGER`.execute(db);
7946
+ }
7947
+ async function down$9(db) {
7948
+ await sql`ALTER TABLE public.cluster_settings DROP COLUMN IF EXISTS check_run_tracking_ttl_days`.execute(db);
7949
+ }
7950
+ //#endregion
7951
+ //#region src/db/migrations/107_check_run_tracking_updated_at_index.ts
7952
+ var _107_check_run_tracking_updated_at_index_exports = /* @__PURE__ */ __exportAll({
7953
+ down: () => down$8,
7954
+ up: () => up$8
7955
+ });
7956
+ /**
7957
+ * Add `idx_check_run_tracking_updated_at` on `check_run_tracking (updated_at)`.
7958
+ *
7959
+ * `CheckRunTrackingStore.pruneStale` — the hourly retention sweep — filters
7960
+ * `WHERE updated_at < now() - <window>`. The table already carries two indexes
7961
+ * — the primary key on `(provider, owner, repo, sha, check_name)` and the
7962
+ * partial `idx_check_run_tracking_run_id` — but `updated_at` leads neither, so
7963
+ * that predicate can use neither and without this index every sweep
7964
+ * sequentially scans the whole table. The scan
7965
+ * is worst exactly where it hurts: a deployment that accumulated rows before
7966
+ * retention existed has the largest table and gets the scan hourly, on every
7967
+ * coordinator, since the cleanup tick is not leader-gated.
7968
+ *
7969
+ * Mirrors `idx_dispatch_queue_run_id` (migration 072) and
7970
+ * `idx_request_idempotency_created_at` (migration 068), both of which exist to
7971
+ * index a TTL sweep's prune predicate.
7972
+ *
7973
+ * Idempotent: `IF NOT EXISTS` makes a re-run a no-op.
7974
+ */
7975
+ async function up$8(db) {
7976
+ await sql`
7977
+ CREATE INDEX IF NOT EXISTS idx_check_run_tracking_updated_at
7978
+ ON public.check_run_tracking (updated_at)
7979
+ `.execute(db);
7980
+ }
7981
+ async function down$8(db) {
7982
+ await sql`DROP INDEX IF EXISTS public.idx_check_run_tracking_updated_at`.execute(db);
7983
+ }
7984
+ //#endregion
7985
+ //#region src/db/migrations/108_unroutable_fast_fail.ts
7986
+ var _108_unroutable_fast_fail_exports = /* @__PURE__ */ __exportAll({
7987
+ down: () => down$7,
7988
+ up: () => up$7
7989
+ });
7990
+ /**
7991
+ * Fast-fail support for jobs nothing in the fleet can run.
7992
+ *
7993
+ * Three additive, nullable columns:
7994
+ *
7995
+ * - `cluster_settings.unroutable_grace_ms` — how long a job may stay
7996
+ * continuously unroutable before it is terminalized. NULL means the
7997
+ * orchestrator's configured default applies; 0 disables fast-fail and leaves
7998
+ * the `queue_timeout_ms` backstop as the only path.
7999
+ * - `dispatch_queue.unroutable_since` — when the job first read unroutable.
8000
+ * Persisted rather than in-memory so a restart mid-grace resumes the same
8001
+ * clock instead of resetting it; an orchestrator that bounces every 90s must
8002
+ * not be able to keep a genuinely dead job alive forever. Cleared the moment
8003
+ * the job reads routable again.
8004
+ * - `execution_jobs.routing_reason` — the operator-facing reason, visible while
8005
+ * the job is still queued. Cleared on recovery.
8006
+ *
8007
+ * Idempotent: each column is guarded on existence, so a re-run is a no-op.
8008
+ */
8009
+ async function columnExists$5(db, table, column) {
8010
+ return (await sql`
8011
+ SELECT EXISTS (
8012
+ SELECT 1 FROM information_schema.columns
8013
+ WHERE table_schema = 'public'
8014
+ AND table_name = ${table}
8015
+ AND column_name = ${column}
8016
+ ) AS exists
8017
+ `.execute(db)).rows[0]?.exists === true;
8018
+ }
8019
+ async function up$7(db) {
8020
+ if (!await columnExists$5(db, "cluster_settings", "unroutable_grace_ms")) await sql`ALTER TABLE public.cluster_settings ADD COLUMN unroutable_grace_ms INTEGER`.execute(db);
8021
+ if (!await columnExists$5(db, "dispatch_queue", "unroutable_since")) await sql`ALTER TABLE public.dispatch_queue ADD COLUMN unroutable_since TIMESTAMPTZ`.execute(db);
8022
+ if (!await columnExists$5(db, "execution_jobs", "routing_reason")) await sql`ALTER TABLE public.execution_jobs ADD COLUMN routing_reason TEXT`.execute(db);
8023
+ }
8024
+ async function down$7(db) {
8025
+ await sql`ALTER TABLE public.execution_jobs DROP COLUMN IF EXISTS routing_reason`.execute(db);
8026
+ await sql`ALTER TABLE public.dispatch_queue DROP COLUMN IF EXISTS unroutable_since`.execute(db);
8027
+ await sql`ALTER TABLE public.cluster_settings DROP COLUMN IF EXISTS unroutable_grace_ms`.execute(db);
8028
+ }
8029
+ //#endregion
8030
+ //#region src/db/migrations/109_cluster_settings_cache_knobs.ts
8031
+ var _109_cluster_settings_cache_knobs_exports = /* @__PURE__ */ __exportAll({
8032
+ down: () => down$6,
8033
+ up: () => up$6
8034
+ });
8035
+ /**
8036
+ * Cluster-global cache tunables for the lock-file cache and the Tier-1
8037
+ * content-requirements cache.
8038
+ *
8039
+ * Six additive, nullable columns. NULL means the orchestrator's configured
8040
+ * default applies (the `KICI_LOCKFILE_CACHE_*` / `KICI_CONTENT_CACHE_*` env
8041
+ * vars stay as the cluster-wide defaults). Sizes and TTLs are structural to the
8042
+ * underlying LRU, so a change takes effect at the next orchestrator restart.
8043
+ *
8044
+ * BIGINT rather than INTEGER: a byte ceiling defaults to 64 MiB and the TTLs are
8045
+ * in milliseconds, so both leave INTEGER range as soon as an operator raises
8046
+ * them.
8047
+ *
8048
+ * Idempotent: each column is guarded on existence, so a re-run is a no-op.
8049
+ */
8050
+ async function columnExists$4(db, table, column) {
8051
+ return (await sql`
8052
+ SELECT EXISTS (
8053
+ SELECT 1 FROM information_schema.columns
8054
+ WHERE table_schema = 'public'
8055
+ AND table_name = ${table}
8056
+ AND column_name = ${column}
8057
+ ) AS exists
8058
+ `.execute(db)).rows[0]?.exists === true;
8059
+ }
8060
+ const COLUMNS$2 = [
8061
+ "lockfile_cache_max",
8062
+ "lockfile_cache_max_bytes",
8063
+ "lockfile_cache_ttl_ms",
8064
+ "content_cache_max",
8065
+ "content_cache_max_bytes",
8066
+ "content_cache_ttl_ms"
8067
+ ];
8068
+ async function up$6(db) {
8069
+ for (const column of COLUMNS$2) if (!await columnExists$4(db, "cluster_settings", column)) await sql`ALTER TABLE public.cluster_settings ADD COLUMN ${sql.ref(column)} BIGINT`.execute(db);
8070
+ }
8071
+ async function down$6(db) {
8072
+ for (const column of COLUMNS$2) await sql`ALTER TABLE public.cluster_settings DROP COLUMN IF EXISTS ${sql.ref(column)}`.execute(db);
8073
+ }
8074
+ //#endregion
8075
+ //#region src/db/migrations/110_cluster_settings_global_eval_knobs.ts
8076
+ var _110_cluster_settings_global_eval_knobs_exports = /* @__PURE__ */ __exportAll({
8077
+ down: () => down$5,
8078
+ up: () => up$5
8079
+ });
8080
+ /**
8081
+ * Cluster-global tunables for the Tier-2 global eval round — the pre-run job
8082
+ * that evaluates each candidate global workflow's `filter` and generators on one
8083
+ * shared checkout of the source and workflow repos.
8084
+ *
8085
+ * Three additive, nullable columns. NULL means the orchestrator's configured
8086
+ * default applies (the `KICI_GLOBAL_EVAL_*` env vars stay as the cluster-wide
8087
+ * defaults). The two budgets are read per round and shipped to the agent in the
8088
+ * round's job config, so a change lands on the next push; `global_eval_cache_max`
8089
+ * sizes an LRU built once at boot and therefore applies at the next restart.
8090
+ *
8091
+ * BIGINT rather than INTEGER: the budgets are in milliseconds, so an operator
8092
+ * raising one leaves INTEGER range with a single generous value.
8093
+ *
8094
+ * Idempotent: each column is guarded on existence, so a re-run is a no-op.
8095
+ */
8096
+ async function columnExists$3(db, table, column) {
8097
+ return (await sql`
8098
+ SELECT EXISTS (
8099
+ SELECT 1 FROM information_schema.columns
8100
+ WHERE table_schema = 'public'
8101
+ AND table_name = ${table}
8102
+ AND column_name = ${column}
8103
+ ) AS exists
8104
+ `.execute(db)).rows[0]?.exists === true;
8105
+ }
8106
+ const COLUMNS$1 = [
8107
+ "global_eval_round_timeout_ms",
8108
+ "global_eval_candidate_timeout_ms",
8109
+ "global_eval_cache_max"
8110
+ ];
8111
+ async function up$5(db) {
8112
+ for (const column of COLUMNS$1) if (!await columnExists$3(db, "cluster_settings", column)) await sql`ALTER TABLE public.cluster_settings ADD COLUMN ${sql.ref(column)} BIGINT`.execute(db);
8113
+ }
8114
+ async function down$5(db) {
8115
+ for (const column of COLUMNS$1) await sql`ALTER TABLE public.cluster_settings DROP COLUMN IF EXISTS ${sql.ref(column)}`.execute(db);
8116
+ }
8117
+ //#endregion
8118
+ //#region src/db/migrations/111_cluster_settings_global_eval_wait.ts
8119
+ var _111_cluster_settings_global_eval_wait_exports = /* @__PURE__ */ __exportAll({
8120
+ down: () => down$4,
8121
+ up: () => up$4
8122
+ });
8123
+ /**
8124
+ * Cluster-global ceiling on how long webhook processing waits for a Tier-2
8125
+ * global eval round to settle.
8126
+ *
8127
+ * One additive, nullable column. NULL means the orchestrator's configured
8128
+ * default applies (`KICI_GLOBAL_EVAL_WAIT_TIMEOUT_MS` stays the cluster-wide
8129
+ * default). It is read fresh per round and applies orchestrator-side — unlike
8130
+ * the two agent budgets, which are shipped inside the round's job config — so a
8131
+ * change lands on the next push.
7860
8132
  *
7861
- * Idempotent: guarded on column existence; a re-run on a DB that already has
7862
- * the column is a no-op.
8133
+ * BIGINT rather than INTEGER: the value is in milliseconds, so an operator
8134
+ * raising it leaves INTEGER range with a single generous value.
8135
+ *
8136
+ * Idempotent: the column is guarded on existence, so a re-run is a no-op.
7863
8137
  */
7864
- async function up$4(db) {
7865
- if ((await sql`
8138
+ async function columnExists$2(db, table, column) {
8139
+ return (await sql`
7866
8140
  SELECT EXISTS (
7867
8141
  SELECT 1 FROM information_schema.columns
7868
8142
  WHERE table_schema = 'public'
7869
- AND table_name = 'check_run_tracking'
7870
- AND column_name = 'terminal_sent_at'
8143
+ AND table_name = ${table}
8144
+ AND column_name = ${column}
7871
8145
  ) AS exists
7872
- `.execute(db)).rows[0]?.exists) return;
7873
- await sql`ALTER TABLE public.check_run_tracking ADD COLUMN terminal_sent_at TIMESTAMPTZ`.execute(db);
8146
+ `.execute(db)).rows[0]?.exists === true;
8147
+ }
8148
+ const COLUMNS = ["global_eval_wait_timeout_ms"];
8149
+ async function up$4(db) {
8150
+ for (const column of COLUMNS) if (!await columnExists$2(db, "cluster_settings", column)) await sql`ALTER TABLE public.cluster_settings ADD COLUMN ${sql.ref(column)} BIGINT`.execute(db);
7874
8151
  }
7875
8152
  async function down$4(db) {
7876
- await sql`ALTER TABLE public.check_run_tracking DROP COLUMN IF EXISTS terminal_sent_at`.execute(db);
8153
+ for (const column of COLUMNS) await sql`ALTER TABLE public.cluster_settings DROP COLUMN IF EXISTS ${sql.ref(column)}`.execute(db);
7877
8154
  }
7878
8155
  //#endregion
7879
- //#region src/db/migrations/105_org_trust_policy.ts
7880
- var _105_org_trust_policy_exports = /* @__PURE__ */ __exportAll({
8156
+ //#region src/db/migrations/112_execution_runs_workflow_repo.ts
8157
+ var _112_execution_runs_workflow_repo_exports = /* @__PURE__ */ __exportAll({
7881
8158
  down: () => down$3,
7882
8159
  up: () => up$3
7883
8160
  });
7884
8161
  /**
7885
- * Create `org_trust_policy` the orchestrator's cache of the Platform-owned org
7886
- * trust policy pushed on `trust_policy.update`.
8162
+ * Record which repository DEFINED the workflow a run executed.
7887
8163
  *
7888
- * A dedicated table rather than `org_settings` columns, because this is
7889
- * Platform-owned policy the orchestrator consumes, not operator-owned config the
7890
- * operator tunes. `source` records which of the two wrote the row so the admin
7891
- * surface can present a Platform-managed policy as read-only.
8164
+ * `execution_runs.repo_identifier` is the repository the run acted on. For an
8165
+ * organization-wide workflow dispatched against another repository those are
8166
+ * two different repositories: `repo_identifier` holds the source repository
8167
+ * that emitted the event, while the workflow itself was authored elsewhere and
8168
+ * travels only per job in `jobConfig.workflowRepoIdentifier` — which lives in
8169
+ * `dispatch_queue.job_config` and is pruned once the run's queue rows age out.
7892
8170
  *
7893
- * Persisting rather than caching in memory is deliberate: a security policy that
7894
- * silently reverts to a default across a restart is worse than one that is never
7895
- * applied.
8171
+ * So the run row alone could not answer "which repository defines this
8172
+ * workflow", and the rerun path read `repo_identifier` as the answer: it
8173
+ * re-fetched the source repository's lock file and either failed with a
8174
+ * misleading force-push message or, on a same-named workflow, silently ran the
8175
+ * source repository's workflow instead.
7896
8176
  *
7897
- * Idempotent: guarded by IF NOT EXISTS, so a re-run is a no-op.
8177
+ * Nullable and unbackfilled by design: a null means "the run acted on the
8178
+ * repository that defines its workflow", which is true of every per-repository
8179
+ * run and of every row written before this column existed.
8180
+ *
8181
+ * Idempotent: guarded on the column's existence, so re-running is a no-op.
7898
8182
  */
8183
+ async function colExists(db, table, name) {
8184
+ return (await sql`
8185
+ SELECT EXISTS (
8186
+ SELECT 1 FROM information_schema.columns
8187
+ WHERE table_schema = 'public'
8188
+ AND table_name = ${table}
8189
+ AND column_name = ${name}
8190
+ ) AS exists
8191
+ `.execute(db)).rows[0]?.exists ?? false;
8192
+ }
7899
8193
  async function up$3(db) {
7900
- await sql`
7901
- CREATE TABLE IF NOT EXISTS public.org_trust_policy (
7902
- customer_id TEXT PRIMARY KEY,
7903
- fork_policy TEXT NOT NULL,
7904
- unknown_contributor_policy TEXT NOT NULL,
7905
- workflow_change_policy TEXT NOT NULL,
7906
- approval_expiry_hours INTEGER NOT NULL,
7907
- source TEXT NOT NULL,
7908
- updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
7909
- )
7910
- `.execute(db);
8194
+ if (!await colExists(db, "execution_runs", "workflow_repo_identifier")) await sql`
8195
+ ALTER TABLE public.execution_runs
8196
+ ADD COLUMN workflow_repo_identifier text
8197
+ `.execute(db);
7911
8198
  }
7912
8199
  async function down$3(db) {
7913
- await sql`DROP TABLE IF EXISTS public.org_trust_policy`.execute(db);
8200
+ await sql`
8201
+ ALTER TABLE public.execution_runs DROP COLUMN IF EXISTS workflow_repo_identifier
8202
+ `.execute(db);
7914
8203
  }
7915
8204
  //#endregion
7916
- //#region src/db/migrations/106_cluster_settings_check_run_tracking_ttl_days.ts
7917
- var _106_cluster_settings_check_run_tracking_ttl_days_exports = /* @__PURE__ */ __exportAll({
8205
+ //#region src/db/migrations/113_execution_runs_workflow_repo_index.ts
8206
+ var _113_execution_runs_workflow_repo_index_exports = /* @__PURE__ */ __exportAll({
7918
8207
  down: () => down$2,
7919
8208
  up: () => up$2
7920
8209
  });
7921
8210
  /**
7922
- * Add `cluster_settings.check_run_tracking_ttl_days` (nullable integer).
7923
- *
7924
- * Retention window for `check_run_tracking` rows. The hourly cleanup sweep
7925
- * deletes rows untouched for longer than this; 0 disables the sweep.
7926
- *
7927
- * Cluster-global (the sweep runs once per fleet on the cleanup tick, with no
7928
- * tenant in scope at the read site), so it lives on `cluster_settings` rather
7929
- * than `org_settings`. NULL means the orchestrator's own configured default
7930
- * applies.
8211
+ * Add the partial index `idx_execution_runs_workflow_repo` on
8212
+ * `execution_runs (workflow_repo_identifier) WHERE workflow_repo_identifier IS NOT NULL`.
8213
+ *
8214
+ * Matching a workflow registration to its runs keys on the repository that
8215
+ * DEFINES the workflow — `workflow_repo_identifier ?? repo_identifier` — which
8216
+ * the orchestrator expresses as
8217
+ * `workflow_repo_identifier IN (…) OR (workflow_repo_identifier IS NULL AND repo_identifier IN (…))`
8218
+ * (`registration/registration-run-match.ts`). The second arm rides
8219
+ * `idx_execution_runs_repo` from migration 001; the first arm had no index at
8220
+ * all, because migration 112 added the column without one. A planner cannot
8221
+ * use an index for only half a disjunction, so the whole predicate degraded to
8222
+ * a sequential scan over a table that grows with every run — on
8223
+ * `dashboard.registrations.list`, which runs its grouped MAX on every list
8224
+ * request.
8225
+ *
8226
+ * With both arms indexed the planner can BitmapOr them.
8227
+ *
8228
+ * Partial by design, and the partiality is what makes it cheap: the column is
8229
+ * non-null only for a cross-repository organization-wide run, a small minority
8230
+ * of rows, so the index stays a fraction of the table's size and skips every
8231
+ * per-repository run. It also matches the predicate exactly — the first arm
8232
+ * can never match a NULL row, since `NULL IN (…)` is never true.
7931
8233
  *
7932
- * Idempotent: guarded on column existence; a re-run on a database that already
7933
- * has the column is a no-op.
8234
+ * Idempotent: `IF NOT EXISTS` makes a re-run a no-op.
7934
8235
  */
7935
8236
  async function up$2(db) {
7936
- if ((await sql`
7937
- SELECT EXISTS (
7938
- SELECT 1 FROM information_schema.columns
7939
- WHERE table_schema = 'public'
7940
- AND table_name = 'cluster_settings'
7941
- AND column_name = 'check_run_tracking_ttl_days'
7942
- ) AS exists
7943
- `.execute(db)).rows[0]?.exists) return;
7944
- await sql`ALTER TABLE public.cluster_settings ADD COLUMN check_run_tracking_ttl_days INTEGER`.execute(db);
8237
+ await sql`
8238
+ CREATE INDEX IF NOT EXISTS idx_execution_runs_workflow_repo
8239
+ ON public.execution_runs (workflow_repo_identifier)
8240
+ WHERE workflow_repo_identifier IS NOT NULL
8241
+ `.execute(db);
7945
8242
  }
7946
8243
  async function down$2(db) {
7947
- await sql`ALTER TABLE public.cluster_settings DROP COLUMN IF EXISTS check_run_tracking_ttl_days`.execute(db);
8244
+ await sql`DROP INDEX IF EXISTS public.idx_execution_runs_workflow_repo`.execute(db);
7948
8245
  }
7949
8246
  //#endregion
7950
- //#region src/db/migrations/107_check_run_tracking_updated_at_index.ts
7951
- var _107_check_run_tracking_updated_at_index_exports = /* @__PURE__ */ __exportAll({
8247
+ //#region src/db/migrations/114_ingest_queue_claim.ts
8248
+ var _114_ingest_queue_claim_exports = /* @__PURE__ */ __exportAll({
7952
8249
  down: () => down$1,
7953
8250
  up: () => up$1
7954
8251
  });
7955
8252
  /**
7956
- * Add `idx_check_run_tracking_updated_at` on `check_run_tracking (updated_at)`.
8253
+ * Claim bookkeeping for the durable ingest queue.
7957
8254
  *
7958
- * `CheckRunTrackingStore.pruneStale` the hourly retention sweep — filters
7959
- * `WHERE updated_at < now() - <window>`. The table already carries two indexes
7960
- * — the primary key on `(provider, owner, repo, sha, check_name)` and the
7961
- * partial `idx_check_run_tracking_run_id` — but `updated_at` leads neither, so
7962
- * that predicate can use neither and without this index every sweep
7963
- * sequentially scans the whole table. The scan
7964
- * is worst exactly where it hurts: a deployment that accumulated rows before
7965
- * retention existed has the largest table and gets the scan hourly, on every
7966
- * coordinator, since the cleanup tick is not leader-gated.
8255
+ * Two additive, nullable columns:
7967
8256
  *
7968
- * Mirrors `idx_dispatch_queue_run_id` (migration 072) and
7969
- * `idx_request_idempotency_created_at` (migration 068), both of which exist to
7970
- * index a TTL sweep's prune predicate.
8257
+ * - `ingest_overflow_buffer.claimed_at` when a row moved `buffered` →
8258
+ * `replaying`. A worker that dies mid-pipeline leaves its row in `replaying`
8259
+ * with nothing to move it back, so the drain pass reclaims a row whose claim
8260
+ * is older than the timeout below. The claim clock has to be its own column:
8261
+ * `captured_at` orders the FIFO drain, so an old row picked up first would
8262
+ * read as instantly stale and be reclaimed out from under a live worker.
8263
+ * - `cluster_settings.ingest_overflow_claim_timeout_ms` — how long a claim may
8264
+ * stand before the drain pass reclaims it. NULL means the orchestrator's
8265
+ * configured default applies. It must exceed the longest a single delivery's
8266
+ * pipeline can legitimately run (a build phase alone is capped at
8267
+ * `cacheBuildTimeoutMs`), or a reclaim would re-run work still in flight.
7971
8268
  *
7972
- * Idempotent: `IF NOT EXISTS` makes a re-run a no-op.
8269
+ * Idempotent: each column is guarded on existence, so a re-run is a no-op.
7973
8270
  */
8271
+ async function columnExists$1(db, table, column) {
8272
+ return (await sql`
8273
+ SELECT EXISTS (
8274
+ SELECT 1 FROM information_schema.columns
8275
+ WHERE table_schema = 'public'
8276
+ AND table_name = ${table}
8277
+ AND column_name = ${column}
8278
+ ) AS exists
8279
+ `.execute(db)).rows[0]?.exists === true;
8280
+ }
7974
8281
  async function up$1(db) {
7975
- await sql`
7976
- CREATE INDEX IF NOT EXISTS idx_check_run_tracking_updated_at
7977
- ON public.check_run_tracking (updated_at)
7978
- `.execute(db);
8282
+ if (!await columnExists$1(db, "ingest_overflow_buffer", "claimed_at")) await sql`ALTER TABLE public.ingest_overflow_buffer ADD COLUMN claimed_at TIMESTAMPTZ`.execute(db);
8283
+ if (!await columnExists$1(db, "cluster_settings", "ingest_overflow_claim_timeout_ms")) await sql`
8284
+ ALTER TABLE public.cluster_settings ADD COLUMN ingest_overflow_claim_timeout_ms INTEGER
8285
+ `.execute(db);
7979
8286
  }
7980
8287
  async function down$1(db) {
7981
- await sql`DROP INDEX IF EXISTS public.idx_check_run_tracking_updated_at`.execute(db);
8288
+ await sql`
8289
+ ALTER TABLE public.cluster_settings DROP COLUMN IF EXISTS ingest_overflow_claim_timeout_ms
8290
+ `.execute(db);
8291
+ await sql`
8292
+ ALTER TABLE public.ingest_overflow_buffer DROP COLUMN IF EXISTS claimed_at
8293
+ `.execute(db);
7982
8294
  }
7983
8295
  //#endregion
7984
- //#region src/db/migrations/108_unroutable_fast_fail.ts
7985
- var _108_unroutable_fast_fail_exports = /* @__PURE__ */ __exportAll({
8296
+ //#region src/db/migrations/115_global_workflows_cluster_switch.ts
8297
+ var _115_global_workflows_cluster_switch_exports = /* @__PURE__ */ __exportAll({
7986
8298
  down: () => down,
7987
8299
  up: () => up
7988
8300
  });
7989
8301
  /**
7990
- * Fast-fail support for jobs nothing in the fleet can run.
8302
+ * Move the global-workflows master switch from `org_settings` to
8303
+ * `cluster_settings`.
7991
8304
  *
7992
- * Three additive, nullable columns:
8305
+ * The switch decides whether any repo may register or dispatch a global
8306
+ * workflow — a workflow defined in one repo that runs against events emitted by
8307
+ * other repos in the org, optionally with elevated access to source-repo
8308
+ * secrets. That is an operator-held decision, so it belongs on the fleet-wide
8309
+ * row an operator reaches through `kici-admin cluster-settings`, not on a
8310
+ * per-org row an org admin can flip from the dashboard.
7993
8311
  *
7994
- * - `cluster_settings.unroutable_grace_ms` how long a job may stay
7995
- * continuously unroutable before it is terminalized. NULL means the
7996
- * orchestrator's configured default applies; 0 disables fast-fail and leaves
7997
- * the `queue_timeout_ms` backstop as the only path.
7998
- * - `dispatch_queue.unroutable_since` — when the job first read unroutable.
7999
- * Persisted rather than in-memory so a restart mid-grace resumes the same
8000
- * clock instead of resetting it; an orchestrator that bounces every 90s must
8001
- * not be able to keep a genuinely dead job alive forever. Cleared the moment
8002
- * the job reads routable again.
8003
- * - `execution_jobs.routing_reason` — the operator-facing reason, visible while
8004
- * the job is still queued. Cleared on recovery.
8312
+ * Deliberately NOT back-filled. Copying `EXISTS(SELECT 1 FROM org_settings
8313
+ * WHERE global_workflows_enabled)` into the new column would silently carry a
8314
+ * per-org opt-in forward into a fleet-wide one — enabling globals for orgs
8315
+ * whose operator never chose it. The new column starts NULL, which resolves to
8316
+ * the orchestrator's configured default (`KICI_GLOBAL_WORKFLOWS_ENABLED`,
8317
+ * default false), so global workflows are off until an operator opts in:
8005
8318
  *
8006
- * Idempotent: each column is guarded on existence, so a re-run is a no-op.
8319
+ * kici-admin cluster-settings set --global-workflows-enabled true
8320
+ *
8321
+ * BOOLEAN and nullable, matching the `NULL ⇒ configured default` contract every
8322
+ * other `cluster_settings` knob follows.
8323
+ *
8324
+ * Idempotent: the add is guarded on existence and the drop uses IF EXISTS, so a
8325
+ * re-run is a no-op.
8007
8326
  */
8008
8327
  async function columnExists(db, table, column) {
8009
8328
  return (await sql`
@@ -8016,14 +8335,20 @@ async function columnExists(db, table, column) {
8016
8335
  `.execute(db)).rows[0]?.exists === true;
8017
8336
  }
8018
8337
  async function up(db) {
8019
- if (!await columnExists(db, "cluster_settings", "unroutable_grace_ms")) await sql`ALTER TABLE public.cluster_settings ADD COLUMN unroutable_grace_ms INTEGER`.execute(db);
8020
- if (!await columnExists(db, "dispatch_queue", "unroutable_since")) await sql`ALTER TABLE public.dispatch_queue ADD COLUMN unroutable_since TIMESTAMPTZ`.execute(db);
8021
- if (!await columnExists(db, "execution_jobs", "routing_reason")) await sql`ALTER TABLE public.execution_jobs ADD COLUMN routing_reason TEXT`.execute(db);
8338
+ if (!await columnExists(db, "cluster_settings", "global_workflows_enabled")) await sql`ALTER TABLE public.cluster_settings ADD COLUMN global_workflows_enabled BOOLEAN`.execute(db);
8339
+ await sql`ALTER TABLE public.org_settings DROP COLUMN IF EXISTS global_workflows_enabled`.execute(db);
8022
8340
  }
8341
+ /**
8342
+ * Restores the org column with its original NOT NULL DEFAULT false. A rollback
8343
+ * cannot recover the per-org values the up-migration dropped — they are gone —
8344
+ * so every org comes back at the opt-in default.
8345
+ */
8023
8346
  async function down(db) {
8024
- await sql`ALTER TABLE public.execution_jobs DROP COLUMN IF EXISTS routing_reason`.execute(db);
8025
- await sql`ALTER TABLE public.dispatch_queue DROP COLUMN IF EXISTS unroutable_since`.execute(db);
8026
- await sql`ALTER TABLE public.cluster_settings DROP COLUMN IF EXISTS unroutable_grace_ms`.execute(db);
8347
+ if (!await columnExists(db, "org_settings", "global_workflows_enabled")) await sql`
8348
+ ALTER TABLE public.org_settings
8349
+ ADD COLUMN global_workflows_enabled BOOLEAN NOT NULL DEFAULT false
8350
+ `.execute(db);
8351
+ await sql`ALTER TABLE public.cluster_settings DROP COLUMN IF EXISTS global_workflows_enabled`.execute(db);
8027
8352
  }
8028
8353
  //#endregion
8029
8354
  //#region src/db/migration-provider.ts
@@ -8137,7 +8462,14 @@ function createMigrationProvider() {
8137
8462
  "105_org_trust_policy": _105_org_trust_policy_exports,
8138
8463
  "106_cluster_settings_check_run_tracking_ttl_days": _106_cluster_settings_check_run_tracking_ttl_days_exports,
8139
8464
  "107_check_run_tracking_updated_at_index": _107_check_run_tracking_updated_at_index_exports,
8140
- "108_unroutable_fast_fail": _108_unroutable_fast_fail_exports
8465
+ "108_unroutable_fast_fail": _108_unroutable_fast_fail_exports,
8466
+ "109_cluster_settings_cache_knobs": _109_cluster_settings_cache_knobs_exports,
8467
+ "110_cluster_settings_global_eval_knobs": _110_cluster_settings_global_eval_knobs_exports,
8468
+ "111_cluster_settings_global_eval_wait": _111_cluster_settings_global_eval_wait_exports,
8469
+ "112_execution_runs_workflow_repo": _112_execution_runs_workflow_repo_exports,
8470
+ "113_execution_runs_workflow_repo_index": _113_execution_runs_workflow_repo_index_exports,
8471
+ "114_ingest_queue_claim": _114_ingest_queue_claim_exports,
8472
+ "115_global_workflows_cluster_switch": _115_global_workflows_cluster_switch_exports
8141
8473
  };
8142
8474
  } };
8143
8475
  }
@@ -9054,7 +9386,13 @@ const UniversalGitPayloadPathsSchema = z.object({
9054
9386
  /** Path to the `modified` files array on a push event. */
9055
9387
  commitsModified: z.string().min(1),
9056
9388
  /** Path to the `removed` files array on a push event. */
9057
- commitsRemoved: z.string().min(1)
9389
+ commitsRemoved: z.string().min(1),
9390
+ /**
9391
+ * Path to the head commit's message on a push event. Optional so a stored
9392
+ * config written before this field stays valid; when unset, a `commitMessage`
9393
+ * trigger filter is INDETERMINATE and the workflow does not run.
9394
+ */
9395
+ commitMessage: z.string().min(1).optional()
9058
9396
  });
9059
9397
  /**
9060
9398
  * Header-to-event-name mapping. Most forges send an `X-Event-Type`-style
@@ -9153,7 +9491,8 @@ const UNIVERSAL_GIT_PRESETS = {
9153
9491
  defaultBranch: "$.repository.default_branch",
9154
9492
  commitsAdded: "$.commits[*].added[*]",
9155
9493
  commitsModified: "$.commits[*].modified[*]",
9156
- commitsRemoved: "$.commits[*].removed[*]"
9494
+ commitsRemoved: "$.commits[*].removed[*]",
9495
+ commitMessage: "$.head_commit.message"
9157
9496
  },
9158
9497
  eventMapping: {
9159
9498
  push: ["push"],
@@ -9169,7 +9508,8 @@ const UNIVERSAL_GIT_PRESETS = {
9169
9508
  defaultBranch: "$.repository.default_branch",
9170
9509
  commitsAdded: "$.commits[*].added[*]",
9171
9510
  commitsModified: "$.commits[*].modified[*]",
9172
- commitsRemoved: "$.commits[*].removed[*]"
9511
+ commitsRemoved: "$.commits[*].removed[*]",
9512
+ commitMessage: "$.head_commit.message"
9173
9513
  },
9174
9514
  eventMapping: {
9175
9515
  push: ["push"],
@@ -9185,7 +9525,8 @@ const UNIVERSAL_GIT_PRESETS = {
9185
9525
  defaultBranch: "$.repository.default_branch",
9186
9526
  commitsAdded: "$.commits[*].added[*]",
9187
9527
  commitsModified: "$.commits[*].modified[*]",
9188
- commitsRemoved: "$.commits[*].removed[*]"
9528
+ commitsRemoved: "$.commits[*].removed[*]",
9529
+ commitMessage: "$.commits[-1:].message"
9189
9530
  },
9190
9531
  eventMapping: {
9191
9532
  push: ["push"],
@@ -9201,7 +9542,8 @@ const UNIVERSAL_GIT_PRESETS = {
9201
9542
  defaultBranch: "$.project.default_branch",
9202
9543
  commitsAdded: "$.commits[*].added[*]",
9203
9544
  commitsModified: "$.commits[*].modified[*]",
9204
- commitsRemoved: "$.commits[*].removed[*]"
9545
+ commitsRemoved: "$.commits[*].removed[*]",
9546
+ commitMessage: "$.commits[-1:].message"
9205
9547
  },
9206
9548
  eventMapping: {
9207
9549
  push: ["Push Hook", "push"],
@@ -9217,7 +9559,8 @@ const UNIVERSAL_GIT_PRESETS = {
9217
9559
  defaultBranch: "$.repository.default_branch",
9218
9560
  commitsAdded: "$.commits[*].added[*]",
9219
9561
  commitsModified: "$.commits[*].modified[*]",
9220
- commitsRemoved: "$.commits[*].removed[*]"
9562
+ commitsRemoved: "$.commits[*].removed[*]",
9563
+ commitMessage: "$.head_commit.message"
9221
9564
  },
9222
9565
  eventMapping: {
9223
9566
  push: ["push"],
@@ -11364,6 +11707,23 @@ function registerRunsCommands(program, getClient) {
11364
11707
  process.exit(1);
11365
11708
  }
11366
11709
  });
11710
+ runs.command("logs <runId>").description("Print a page of a step log (dogfooded via /api/v1/admin/runs/:runId/jobs/:jobId/steps/:i/logs)").requiredOption("--job <jobId>", "Job id (the dispatch_queue row id for an eval round)").option("--step <n>", "Step index (default 0)", "0").option("--limit <n>", "Max lines to return (default 500, server caps at 2000)", "500").option("--cursor <c>", "Line-offset cursor from a previous page").option("--json", "Emit raw JSON instead of plain lines").action(async (runId, opts) => {
11711
+ try {
11712
+ const params = new URLSearchParams({ limit: String(opts.limit) });
11713
+ if (opts.cursor) params.set("cursor", String(opts.cursor));
11714
+ const path = `/api/v1/admin/runs/${encodeURIComponent(runId)}/jobs/${encodeURIComponent(String(opts.job))}/steps/${encodeURIComponent(String(opts.step))}/logs?${params.toString()}`;
11715
+ const response = await getClient().get(path);
11716
+ if (opts.json) {
11717
+ console.log(JSON.stringify(response, null, 2));
11718
+ return;
11719
+ }
11720
+ for (const line of response.lines) console.log(line.value);
11721
+ if (response.nextCursor) console.error(`(more: re-run with --cursor ${response.nextCursor})`);
11722
+ } catch (err) {
11723
+ console.error(`Error: ${toErrorMessage(err)}`);
11724
+ process.exit(1);
11725
+ }
11726
+ });
11367
11727
  runs.command("ephemeral-key <runId>").description("Show whether the run-ephemeral key has been scrubbed yet").option("--json", "Emit raw JSON instead of plain text").action(async (runId, opts) => {
11368
11728
  try {
11369
11729
  const response = await getClient().getRunEphemeralKey(runId);
@@ -11533,6 +11893,13 @@ const baseSchema = z.object({
11533
11893
  lockfileCacheMax: z.coerce.number().default(500),
11534
11894
  lockfileCacheTtlMs: z.coerce.number().default(36e5),
11535
11895
  lockfileCacheMaxBytes: z.coerce.number().default(64 * 1024 * 1024),
11896
+ contentCacheMax: z.coerce.number().default(500),
11897
+ contentCacheTtlMs: z.coerce.number().default(36e5),
11898
+ contentCacheMaxBytes: z.coerce.number().default(64 * 1024 * 1024),
11899
+ globalEvalRoundTimeoutMs: z.coerce.number().default(12e4),
11900
+ globalEvalCandidateTimeoutMs: z.coerce.number().default(2e4),
11901
+ globalEvalCacheMax: z.coerce.number().default(500),
11902
+ globalEvalWaitTimeoutMs: z.coerce.number().default(24e4),
11536
11903
  queueMaxDepth: z.coerce.number().default(1e3),
11537
11904
  queueTimeoutMs: z.coerce.number().default(36e5),
11538
11905
  /**
@@ -11542,6 +11909,15 @@ const baseSchema = z.object({
11542
11909
  */
11543
11910
  unroutableGraceMs: z.coerce.number().default(12e4),
11544
11911
  /**
11912
+ * Fleet-wide default for the global-workflows master switch. Cluster default;
11913
+ * the live value is the `global_workflows_enabled` cluster setting, and NULL
11914
+ * there means this value applies.
11915
+ *
11916
+ * Defaults to false: a global workflow runs against events from repos other
11917
+ * than the one that defines it, so it is opt-in by the operator.
11918
+ */
11919
+ globalWorkflowsEnabled: z.union([z.boolean(), z.string()]).default(false).transform((v) => typeof v === "boolean" ? v : v === "true"),
11920
+ /**
11545
11921
  * Operator-facing backpressure warning threshold for the dispatch queue.
11546
11922
  * When pending-queue depth stays at or above this value for at least two
11547
11923
  * consecutive refresher ticks (~10s), the orchestrator emits a
@@ -11569,6 +11945,7 @@ const baseSchema = z.object({
11569
11945
  ingestOverflowReplayIntervalMs: z.coerce.number().int().min(1).default(2e3),
11570
11946
  ingestOverflowReplayBatch: z.coerce.number().int().min(1).default(50),
11571
11947
  ingestOverflowMaxAttempts: z.coerce.number().int().min(1).default(10),
11948
+ ingestOverflowClaimTimeoutMs: z.coerce.number().int().min(6e4).default(9e5),
11572
11949
  rerouteSpawnWindowMs: z.coerce.number().int().min(1e3).default(9e4),
11573
11950
  rerouteAckTimeoutMs: z.coerce.number().int().min(1e3).default(15e3),
11574
11951
  rerouteMaxHops: z.coerce.number().int().min(1).default(3),
@@ -11895,9 +12272,17 @@ const envDef = defineEnv({
11895
12272
  lockfileCacheMax: "KICI_LOCKFILE_CACHE_MAX",
11896
12273
  lockfileCacheTtlMs: "KICI_LOCKFILE_CACHE_TTL_MS",
11897
12274
  lockfileCacheMaxBytes: "KICI_LOCKFILE_CACHE_MAX_BYTES",
12275
+ contentCacheMax: "KICI_CONTENT_CACHE_MAX",
12276
+ contentCacheTtlMs: "KICI_CONTENT_CACHE_TTL_MS",
12277
+ contentCacheMaxBytes: "KICI_CONTENT_CACHE_MAX_BYTES",
12278
+ globalEvalRoundTimeoutMs: "KICI_GLOBAL_EVAL_ROUND_TIMEOUT_MS",
12279
+ globalEvalCandidateTimeoutMs: "KICI_GLOBAL_EVAL_CANDIDATE_TIMEOUT_MS",
12280
+ globalEvalCacheMax: "KICI_GLOBAL_EVAL_CACHE_MAX",
12281
+ globalEvalWaitTimeoutMs: "KICI_GLOBAL_EVAL_WAIT_TIMEOUT_MS",
11898
12282
  queueMaxDepth: "KICI_QUEUE_MAX_DEPTH",
11899
12283
  queueTimeoutMs: "KICI_QUEUE_TIMEOUT_MS",
11900
12284
  unroutableGraceMs: "KICI_UNROUTABLE_GRACE_MS",
12285
+ globalWorkflowsEnabled: "KICI_GLOBAL_WORKFLOWS_ENABLED",
11901
12286
  queueBackpressureThreshold: "KICI_QUEUE_BACKPRESSURE_THRESHOLD",
11902
12287
  workerConcurrency: "KICI_WORKER_CONCURRENCY",
11903
12288
  concurrencyWaitTimeoutMs: "KICI_CONCURRENCY_WAIT_TIMEOUT_MS",
@@ -11917,6 +12302,7 @@ const envDef = defineEnv({
11917
12302
  ingestOverflowReplayIntervalMs: "KICI_INGEST_OVERFLOW_REPLAY_INTERVAL_MS",
11918
12303
  ingestOverflowReplayBatch: "KICI_INGEST_OVERFLOW_REPLAY_BATCH",
11919
12304
  ingestOverflowMaxAttempts: "KICI_INGEST_OVERFLOW_MAX_ATTEMPTS",
12305
+ ingestOverflowClaimTimeoutMs: "KICI_INGEST_OVERFLOW_CLAIM_TIMEOUT_MS",
11920
12306
  rerouteSpawnWindowMs: "KICI_REROUTE_SPAWN_WINDOW_MS",
11921
12307
  rerouteAckTimeoutMs: "KICI_REROUTE_ACK_TIMEOUT_MS",
11922
12308
  rerouteMaxHops: "KICI_REROUTE_MAX_HOPS",
@@ -13513,6 +13899,27 @@ var DashboardEncryptionKeyRepo = class {
13513
13899
  //#endregion
13514
13900
  //#region src/cluster/cluster-settings-reader.ts
13515
13901
  const logger$9 = createLogger({ prefix: "orch:cluster-settings" });
13902
+ /**
13903
+ * Ceiling for the three LRU entry-count knobs — `lockfile_cache_max`,
13904
+ * `content_cache_max`, and `global_eval_cache_max`.
13905
+ *
13906
+ * This is a boot-safety bound, not a policy preference. The underlying LRU
13907
+ * allocates its index arrays eagerly from `max` — several typed arrays plus the
13908
+ * TTL and size arrays the caches ask for — so the cost is paid at construction
13909
+ * with zero entries cached. Measured on the shipped version: an empty cache at
13910
+ * `max` 5,000,000 costs ~191 MB, and at 5,000,000,000 the constructor throws
13911
+ * `RangeError: Invalid array length`.
13912
+ *
13913
+ * That throw is what makes an unbounded knob dangerous rather than merely
13914
+ * wasteful. All three caches are built inside `bootstrapOrchestrator`, so a bad
13915
+ * stored value crashes the orchestrator before its admin API is listening —
13916
+ * and the admin API is the only way `kici-admin cluster-settings` can reach the
13917
+ * stored value. The knob would brick the very tool needed to un-brick it.
13918
+ *
13919
+ * 100,000 is 200x the shipped default of 500 and costs ~4 MB per empty cache,
13920
+ * so it is far above any plausible operator setting while keeping boot bounded.
13921
+ */
13922
+ const CACHE_MAX_ENTRIES_CEILING = 1e5;
13516
13923
  const DEFAULT_CACHE_TTL_MS = 1e4;
13517
13924
  /**
13518
13925
  * Reads the single cluster_settings row (id='default') once per short TTL
@@ -13619,6 +14026,29 @@ var ClusterSettingsReader = class {
13619
14026
  };
13620
14027
  }
13621
14028
  /**
14029
+ * Resolve a fleet-wide boolean knob without collapsing a read failure into a
14030
+ * default.
14031
+ *
14032
+ * There is deliberately no `getBoolean(column, fallback)` companion. The
14033
+ * security gate that consumes this must tell the reader's outcomes apart
14034
+ * itself: a stored `false` and a NULL both deny today, but they deny for
14035
+ * different reasons, and `{ ok: false }` must deny regardless of what the
14036
+ * configured default happens to be. A convenience wrapper that folded the
14037
+ * failure into the default would be safe only for as long as that default
14038
+ * stayed `false`. A caller that only needs a display value (the dashboard
14039
+ * status badge) folds `{ ok: false }` into the default explicitly at its own
14040
+ * site, where getting it wrong misreports a badge rather than opening a gate.
14041
+ */
14042
+ async tryGetBoolean(column) {
14043
+ const { row, readable } = await this.loadSnapshot();
14044
+ if (!readable) return { ok: false };
14045
+ const value = row?.[column];
14046
+ return {
14047
+ ok: true,
14048
+ value: typeof value === "boolean" ? value : null
14049
+ };
14050
+ }
14051
+ /**
13622
14052
  * The cluster_settings row version last seen in the cache (0 if never loaded).
13623
14053
  *
13624
14054
  * Synchronous — never awaits a DB read — so the heartbeat timer can read it
@@ -18189,6 +18619,31 @@ function registerLogsCommand(parent) {
18189
18619
  //#endregion
18190
18620
  //#region src/agent-packaging/node-binary.ts
18191
18621
  /**
18622
+ * Fetch a Node dist URL, retrying transient failures. The runtime download is a
18623
+ * bootstrap-critical step on a box that may have flaky egress (a fresh customer
18624
+ * host, a CDN blip); a single bare `fetch` turns any transient connect/DNS/5xx
18625
+ * hiccup into an opaque `fetch failed` that aborts the whole packaging run. We
18626
+ * retry connection-level throws and 5xx responses with exponential backoff, and
18627
+ * fold the underlying `cause` (e.g. `connect ETIMEDOUT …`, `UND_ERR_…`) into the
18628
+ * final error so a genuine failure is diagnosable instead of a bare message.
18629
+ */
18630
+ async function fetchNodeDist(url, attempts = 4) {
18631
+ let lastErr;
18632
+ for (let attempt = 1; attempt <= attempts; attempt++) {
18633
+ try {
18634
+ const resp = await fetch(url);
18635
+ if (resp.ok) return resp;
18636
+ if (resp.status < 500 || attempt === attempts) throw new Error(`Failed to fetch ${url}: HTTP ${resp.status}`);
18637
+ lastErr = /* @__PURE__ */ new Error(`HTTP ${resp.status}`);
18638
+ } catch (err) {
18639
+ lastErr = err;
18640
+ if (attempt === attempts) throw new Error(`Failed to fetch ${url} after ${attempts} attempts: ${JSON.stringify(serializeError(err))}`);
18641
+ }
18642
+ await setTimeout$1(Math.min(500 * 2 ** (attempt - 1), 4e3));
18643
+ }
18644
+ throw new Error(`Failed to fetch ${url}: ${JSON.stringify(serializeError(lastErr))}`);
18645
+ }
18646
+ /**
18192
18647
  * Download + SHASUMS256-verify the Node runtime for a glibc-Linux platform and
18193
18648
  * vendor `node` + `npm` into the payload.
18194
18649
  *
@@ -18208,13 +18663,10 @@ async function downloadNodeBinary(opts) {
18208
18663
  const base = (opts.nodeMirror ?? "https://nodejs.org/dist").replace(/\/$/, "");
18209
18664
  const filename = `node-v${opts.version}-${nodeOs}-${nodeArch}.tar.gz`;
18210
18665
  const dir = `v${opts.version}`;
18211
- const shaResp = await fetch(`${base}/${dir}/SHASUMS256.txt`);
18212
- if (!shaResp.ok) throw new Error(`Failed to fetch SHASUMS256.txt: ${shaResp.status}`);
18213
- const shaLine = (await shaResp.text()).split("\n").find((l) => l.endsWith(filename));
18666
+ const shaLine = (await (await fetchNodeDist(`${base}/${dir}/SHASUMS256.txt`)).text()).split("\n").find((l) => l.endsWith(filename));
18214
18667
  if (!shaLine) throw new Error(`No SHA-256 entry for ${filename} in SHASUMS256.txt`);
18215
18668
  const expected = shaLine.trim().split(/\s+/)[0];
18216
- const archiveResp = await fetch(`${base}/${dir}/${filename}`);
18217
- if (!archiveResp.ok) throw new Error(`Failed to download ${filename}: ${archiveResp.status}`);
18669
+ const archiveResp = await fetchNodeDist(`${base}/${dir}/${filename}`);
18218
18670
  const buf = Buffer.from(await archiveResp.arrayBuffer());
18219
18671
  const actual = createHash("sha256").update(buf).digest("hex");
18220
18672
  if (actual !== expected) throw new Error(`SHA-256 mismatch for ${filename}:\n expected ${expected}\n actual ${actual}`);
@@ -18446,7 +18898,7 @@ async function refreshAgentPackages(storage, version, opts, deps) {
18446
18898
  const ALL_PLATFORMS = AgentPlatform.options;
18447
18899
  /** The orchestrator's own version (single-version invariant) = the packaged agent version. */
18448
18900
  function resolveKiciVersion() {
18449
- return "0.4.0";
18901
+ return "0.5.0";
18450
18902
  }
18451
18903
  /** Parse the --platform value: default set | single | CSV | `all`. */
18452
18904
  function parsePlatforms(raw) {
@@ -20080,7 +20532,7 @@ function formatSettings$1(s, format) {
20080
20532
  if (format === "json") return JSON.stringify(s, null, 2);
20081
20533
  const lines = [];
20082
20534
  lines.push(`Customer/org id: ${s.customerId}`);
20083
- lines.push(`Enabled: ${s.enabled}`);
20535
+ lines.push(`Enabled (cluster-wide): ${s.enabled}`);
20084
20536
  lines.push(`Allowed authors: ${s.allowedRepos === null ? "(any repo)" : formatList(s.allowedRepos)}`);
20085
20537
  lines.push(`Denied source repos: ${s.deniedRepos === null ? "(none)" : formatList(s.deniedRepos)}`);
20086
20538
  lines.push(`Elevated authors: ${s.elevatedRepos === null ? "(none)" : formatList(s.elevatedRepos)}`);
@@ -20138,24 +20590,6 @@ function registerOrgSettingsCommands(program, getClient) {
20138
20590
  process.exit(1);
20139
20591
  }
20140
20592
  });
20141
- gw.command("set-enabled <value>").description("Toggle the master enable switch (true|false)").option("--customer-id <id>", "Customer / org id (alias: --org)").option("--org <id>", "Alias for --customer-id").option("--format <format>", "Output format: json|table", "table").action(async (value, opts) => {
20142
- const enabled = value === "true" ? true : value === "false" ? false : void 0;
20143
- if (enabled === void 0) {
20144
- console.error("Error: value must be \"true\" or \"false\"");
20145
- process.exit(1);
20146
- }
20147
- const customerId = resolveCustomerId(opts);
20148
- try {
20149
- const settings = await patchSettings$1(getClient(), {
20150
- customerId,
20151
- enabled
20152
- });
20153
- console.log(formatSettings$1(settings, opts.format));
20154
- } catch (err) {
20155
- console.error(`Error: ${toErrorMessage(err)}`);
20156
- process.exit(1);
20157
- }
20158
- });
20159
20593
  registerListMutators(gw, getClient, "allow", "allowedRepos");
20160
20594
  registerListMutators(gw, getClient, "deny", "deniedRepos");
20161
20595
  registerListMutators(gw, getClient, "elevate", "elevatedRepos");
@@ -20831,7 +21265,7 @@ function resolveCustomerId(opts) {
20831
21265
  function label(prefix) {
20832
21266
  if (prefix === "allow") return "workflow-author allow-list";
20833
21267
  if (prefix === "deny") return "source-repo deny-list";
20834
- return "elevated-access list";
21268
+ return "elevated-access list (DEPRECATED: not enforced, removed at v1.0.0)";
20835
21269
  }
20836
21270
  /** Legacy boolean sugar for --op / --enabled: true→permissive, false→disabled. */
20837
21271
  function parseStateToken(token) {
@@ -21089,6 +21523,75 @@ const KNOBS$1 = [
21089
21523
  flag: "unroutable-grace-ms",
21090
21524
  min: 0,
21091
21525
  label: "Unroutable fast-fail grace (ms)"
21526
+ },
21527
+ {
21528
+ field: "ingestOverflowClaimTimeoutMs",
21529
+ flag: "ingest-overflow-claim-timeout-ms",
21530
+ min: 6e4,
21531
+ label: "Ingest queue claim timeout (ms)"
21532
+ },
21533
+ {
21534
+ field: "lockfileCacheMax",
21535
+ flag: "lockfile-cache-max",
21536
+ min: 1,
21537
+ max: CACHE_MAX_ENTRIES_CEILING,
21538
+ label: "Lock-file cache max entries"
21539
+ },
21540
+ {
21541
+ field: "lockfileCacheMaxBytes",
21542
+ flag: "lockfile-cache-max-bytes",
21543
+ min: 1024,
21544
+ label: "Lock-file cache max bytes"
21545
+ },
21546
+ {
21547
+ field: "lockfileCacheTtlMs",
21548
+ flag: "lockfile-cache-ttl-ms",
21549
+ min: 1e3,
21550
+ label: "Lock-file cache TTL (ms)"
21551
+ },
21552
+ {
21553
+ field: "contentCacheMax",
21554
+ flag: "content-cache-max",
21555
+ min: 1,
21556
+ max: CACHE_MAX_ENTRIES_CEILING,
21557
+ label: "Content cache max entries"
21558
+ },
21559
+ {
21560
+ field: "contentCacheMaxBytes",
21561
+ flag: "content-cache-max-bytes",
21562
+ min: 1024,
21563
+ label: "Content cache max bytes"
21564
+ },
21565
+ {
21566
+ field: "contentCacheTtlMs",
21567
+ flag: "content-cache-ttl-ms",
21568
+ min: 1e3,
21569
+ label: "Content cache TTL (ms)"
21570
+ },
21571
+ {
21572
+ field: "globalEvalRoundTimeoutMs",
21573
+ flag: "global-eval-round-timeout-ms",
21574
+ min: 1e3,
21575
+ label: "Global eval round timeout (ms)"
21576
+ },
21577
+ {
21578
+ field: "globalEvalCandidateTimeoutMs",
21579
+ flag: "global-eval-candidate-timeout-ms",
21580
+ min: 1e3,
21581
+ label: "Global eval candidate timeout (ms)"
21582
+ },
21583
+ {
21584
+ field: "globalEvalCacheMax",
21585
+ flag: "global-eval-cache-max",
21586
+ min: 1,
21587
+ max: CACHE_MAX_ENTRIES_CEILING,
21588
+ label: "Global eval round-result cache max entries"
21589
+ },
21590
+ {
21591
+ field: "globalEvalWaitTimeoutMs",
21592
+ flag: "global-eval-wait-timeout-ms",
21593
+ min: 1e3,
21594
+ label: "Global eval wait timeout (ms)"
21092
21595
  }
21093
21596
  ];
21094
21597
  /** The cluster-global text knobs. */
@@ -21099,6 +21602,11 @@ const STRING_KNOBS = [{
21099
21602
  expects: "an absolute http(s) URL",
21100
21603
  validate: (v) => /^https?:\/\/[^\s]+$/.test(v)
21101
21604
  }];
21605
+ const BOOLEAN_KNOBS = [{
21606
+ field: "globalWorkflowsEnabled",
21607
+ flag: "global-workflows-enabled",
21608
+ label: "Global workflows enabled"
21609
+ }];
21102
21610
  /** Map a Commander long-flag (`--foo-bar`) to its camelCase option key. */
21103
21611
  function optionKey(flag) {
21104
21612
  return flag.replace(/-([a-z])/g, (_m, c) => c.toUpperCase());
@@ -21106,9 +21614,17 @@ function optionKey(flag) {
21106
21614
  function formatSettings(s, format) {
21107
21615
  if (format === "json") return JSON.stringify(s, null, 2);
21108
21616
  const lines = [];
21109
- const labels = [...KNOBS$1, ...STRING_KNOBS].map((k) => k.label);
21617
+ const labels = [
21618
+ ...KNOBS$1,
21619
+ ...STRING_KNOBS,
21620
+ ...BOOLEAN_KNOBS
21621
+ ].map((k) => k.label);
21110
21622
  const width = Math.max(...labels.map((l) => l.length)) + 2;
21111
- for (const knob of [...KNOBS$1, ...STRING_KNOBS]) {
21623
+ for (const knob of [
21624
+ ...KNOBS$1,
21625
+ ...STRING_KNOBS,
21626
+ ...BOOLEAN_KNOBS
21627
+ ]) {
21112
21628
  const value = s[knob.field];
21113
21629
  const shown = value === null || value === void 0 ? "(cluster default)" : String(value);
21114
21630
  lines.push(`${(knob.label + ":").padEnd(width)} ${shown}`);
@@ -21121,11 +21637,17 @@ async function fetchSettings(client) {
21121
21637
  async function patchSettings(client, body) {
21122
21638
  return (await client.patch("/api/v1/admin/cluster-settings", body)).settings;
21123
21639
  }
21124
- /** Parse an integer CLI flag with a minimum, exiting with an error on failure. */
21125
- function parseKnobValue(flag, value, min) {
21640
+ /**
21641
+ * Parse an integer CLI flag against its knob's bounds, exiting on failure.
21642
+ *
21643
+ * `max` is optional because most knobs have no meaningful ceiling; the ones
21644
+ * that do carry a hard boot-safety bound (see {@link KnobSpec.max}).
21645
+ */
21646
+ function parseKnobValue(flag, value, min, max) {
21126
21647
  const n = Number(value);
21127
- if (!Number.isInteger(n) || n < min) {
21128
- console.error(`Error: --${flag} must be an integer >= ${min}`);
21648
+ const bounds = max === void 0 ? `>= ${min}` : `between ${min} and ${max}`;
21649
+ if (!Number.isInteger(n) || n < min || max !== void 0 && n > max) {
21650
+ console.error(`Error: --${flag} must be an integer ${bounds}`);
21129
21651
  process.exit(1);
21130
21652
  }
21131
21653
  return n;
@@ -21139,26 +21661,80 @@ function parseStringKnobValue(knob, value) {
21139
21661
  }
21140
21662
  return trimmed;
21141
21663
  }
21664
+ /**
21665
+ * Parse a boolean CLI flag, exiting on failure.
21666
+ *
21667
+ * Accepts only the exact strings `true` and `false`. A permissive parser (any
21668
+ * non-empty string is true) would read `--global-workflows-enabled no` as an
21669
+ * enable, which for this knob turns a typo into a security posture change.
21670
+ */
21671
+ function parseBooleanKnobValue(knob, value) {
21672
+ const trimmed = value.trim();
21673
+ if (trimmed !== "true" && trimmed !== "false") {
21674
+ console.error(`Error: --${knob.flag} must be true or false`);
21675
+ process.exit(1);
21676
+ }
21677
+ return trimmed === "true";
21678
+ }
21142
21679
  /** Assemble the PATCH body from provided `set` flags (exits if none given). */
21143
21680
  function buildClusterPatch(opts) {
21144
21681
  const patch = {};
21145
21682
  for (const knob of KNOBS$1) {
21146
21683
  const raw = opts[optionKey(knob.flag)];
21147
- if (raw !== void 0) patch[knob.field] = parseKnobValue(knob.flag, raw, knob.min);
21684
+ if (raw !== void 0) patch[knob.field] = parseKnobValue(knob.flag, raw, knob.min, knob.max);
21148
21685
  }
21149
21686
  for (const knob of STRING_KNOBS) {
21150
21687
  const raw = opts[optionKey(knob.flag)];
21151
21688
  if (raw !== void 0) patch[knob.field] = parseStringKnobValue(knob, raw);
21152
21689
  }
21690
+ for (const knob of BOOLEAN_KNOBS) {
21691
+ const raw = opts[optionKey(knob.flag)];
21692
+ if (raw !== void 0) patch[knob.field] = parseBooleanKnobValue(knob, raw);
21693
+ }
21153
21694
  if (Object.keys(patch).length === 0) {
21154
21695
  console.error(`Error: pass at least one knob flag (e.g. --${KNOBS$1[0].flag} <value>)`);
21155
21696
  process.exit(1);
21156
21697
  }
21157
21698
  return patch;
21158
21699
  }
21700
+ /**
21701
+ * Warn when only one of the two ordered global-eval timeouts is being set.
21702
+ *
21703
+ * The orchestrator's wait ceiling must exceed the agent's round budget — the
21704
+ * agent's budget starts only once the round job is RUNNING, so a lower ceiling
21705
+ * fires on every round that merely waited for a free agent, failing every round
21706
+ * silently. The server rejects the pair outright when BOTH effective values are
21707
+ * stored, but it cannot compare against a column left NULL: NULL means "the
21708
+ * orchestrator's configured default applies", and the route does not know that
21709
+ * number. Setting one alone is exactly that blind spot, so warn here.
21710
+ *
21711
+ * Returns the lines rather than printing them so the check is unit-testable.
21712
+ */
21713
+ function unpairedEvalTimeoutWarnings(patch) {
21714
+ const setting = (v) => typeof v === "number";
21715
+ const round = patch.globalEvalRoundTimeoutMs;
21716
+ const warnings = [];
21717
+ const wait = patch.globalEvalWaitTimeoutMs;
21718
+ if (setting(wait) !== setting(round)) {
21719
+ const which = setting(wait) ? "wait timeout" : "round timeout";
21720
+ const other = setting(wait) ? "--global-eval-round-timeout-ms" : "--global-eval-wait-timeout-ms";
21721
+ warnings.push(`Warning: setting the global eval ${which} alone. The wait timeout must stay greater than the round timeout, or every round fails. Check ${other} with \`kici-admin cluster-settings show\`.`);
21722
+ }
21723
+ const candidate = patch.globalEvalCandidateTimeoutMs;
21724
+ if (setting(candidate) !== setting(round)) {
21725
+ const which = setting(candidate) ? "candidate timeout" : "round timeout";
21726
+ const other = setting(candidate) ? "--global-eval-round-timeout-ms" : "--global-eval-candidate-timeout-ms";
21727
+ warnings.push(`Warning: setting the global eval ${which} alone. The candidate timeout must stay less than the round timeout, or one workflow can suppress every other in its round. Check ${other} with \`kici-admin cluster-settings show\`.`);
21728
+ }
21729
+ return warnings;
21730
+ }
21159
21731
  /** Build the reset PATCH body: all knobs → null, or just the flagged ones. */
21160
21732
  function buildClusterReset(opts) {
21161
- const all = [...KNOBS$1, ...STRING_KNOBS];
21733
+ const all = [
21734
+ ...KNOBS$1,
21735
+ ...STRING_KNOBS,
21736
+ ...BOOLEAN_KNOBS
21737
+ ];
21162
21738
  const flagged = all.filter((k) => opts[optionKey(k.flag)]);
21163
21739
  const target = flagged.length > 0 ? flagged : all;
21164
21740
  const patch = {};
@@ -21208,10 +21784,15 @@ function registerClusterSettingsCommands(program, getClient) {
21208
21784
  }
21209
21785
  });
21210
21786
  const setCmd = cs.command("set").description("Set one or more cluster-global tunables. At least one knob flag required.").option("--format <format>", "Output format: json|table", "table");
21211
- for (const knob of KNOBS$1) setCmd.option(`--${knob.flag} <value>`, `${knob.label} (integer >= ${knob.min})`);
21787
+ for (const knob of KNOBS$1) {
21788
+ const bounds = knob.max === void 0 ? `integer >= ${knob.min}` : `integer ${knob.min}-${knob.max}`;
21789
+ setCmd.option(`--${knob.flag} <value>`, `${knob.label} (${bounds})`);
21790
+ }
21212
21791
  for (const knob of STRING_KNOBS) setCmd.option(`--${knob.flag} <value>`, `${knob.label} (${knob.expects})`);
21792
+ for (const knob of BOOLEAN_KNOBS) setCmd.option(`--${knob.flag} <value>`, `${knob.label} (true|false)`);
21213
21793
  setCmd.action(async (opts) => {
21214
21794
  const patch = buildClusterPatch(opts);
21795
+ for (const line of unpairedEvalTimeoutWarnings(patch)) console.warn(line);
21215
21796
  try {
21216
21797
  const updated = await patchSettings(getClient(), patch);
21217
21798
  console.log(formatSettings(updated, opts.format ?? "table"));
@@ -21226,7 +21807,11 @@ function registerClusterSettingsCommands(program, getClient) {
21226
21807
  }
21227
21808
  });
21228
21809
  const resetCmd = cs.command("reset").description("Clear cluster-global overrides (all, or the named knobs) back to cluster defaults").option("--format <format>", "Output format: json|table", "table");
21229
- for (const knob of [...KNOBS$1, ...STRING_KNOBS]) resetCmd.option(`--${knob.flag}`, `Clear only ${knob.label}`);
21810
+ for (const knob of [
21811
+ ...KNOBS$1,
21812
+ ...STRING_KNOBS,
21813
+ ...BOOLEAN_KNOBS
21814
+ ]) resetCmd.option(`--${knob.flag}`, `Clear only ${knob.label}`);
21230
21815
  resetCmd.action(async (opts) => {
21231
21816
  const patch = buildClusterReset(opts);
21232
21817
  try {