@kici-dev/orchestrator 0.2.0 → 0.3.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.
package/dist/server.js CHANGED
@@ -162,7 +162,7 @@ async function cancelRunWithReason(deps, runId, reason, options = {}) {
162
162
  const force = options.force ?? false;
163
163
  const runRow = await db.selectFrom("execution_runs").select(["status"]).where("run_id", "=", runId).executeTakeFirst();
164
164
  if (runRow && TERMINAL_RUN_STATES.has(runRow.status)) {
165
- logger$129.info("Cancel ignored: run already terminal", {
165
+ logger$131.info("Cancel ignored: run already terminal", {
166
166
  runId,
167
167
  status: runRow.status
168
168
  });
@@ -190,7 +190,7 @@ async function cancelRunWithReason(deps, runId, reason, options = {}) {
190
190
  }));
191
191
  agentsNotified++;
192
192
  } catch (err) {
193
- logger$129.warn("Failed to send job.cancel to agent; treating job as orphaned", {
193
+ logger$131.warn("Failed to send job.cancel to agent; treating job as orphaned", {
194
194
  runId,
195
195
  jobId,
196
196
  agentId,
@@ -201,7 +201,8 @@ async function cancelRunWithReason(deps, runId, reason, options = {}) {
201
201
  const pendingResult = await db.updateTable("execution_jobs").set({
202
202
  status: ExecutionJobStatus.enum.cancelled,
203
203
  completed_at: /* @__PURE__ */ new Date(),
204
- error_message: reason
204
+ error_message: reason,
205
+ routing_reason: null
205
206
  }).where("run_id", "=", runId).where("status", "in", [ExecutionJobStatus.enum.pending, ExecutionJobStatus.enum.queued]).execute();
206
207
  const pendingCancelled = Number(pendingResult[0]?.numUpdatedRows ?? 0);
207
208
  await jobQueue.cancelByRunId(runId);
@@ -220,7 +221,7 @@ async function cancelRunWithReason(deps, runId, reason, options = {}) {
220
221
  orphansCancelled = Number(orphanResult[0]?.numUpdatedRows ?? 0);
221
222
  await executionTracker.completeRunIfAllJobsTerminal(runId);
222
223
  }
223
- logger$129.info("Cancelled run", {
224
+ logger$131.info("Cancelled run", {
224
225
  runId,
225
226
  agentsNotified,
226
227
  pendingCancelled,
@@ -233,9 +234,9 @@ async function cancelRunWithReason(deps, runId, reason, options = {}) {
233
234
  alreadyTerminal: false
234
235
  };
235
236
  }
236
- var logger$129;
237
+ var logger$131;
237
238
  var init_cancel_run = __esmMin((() => {
238
- logger$129 = createLogger({ prefix: "cancel-run" });
239
+ logger$131 = createLogger({ prefix: "cancel-run" });
239
240
  }));
240
241
  //#endregion
241
242
  //#region src/cancel/dashboard-cancel-handler.ts
@@ -491,7 +492,7 @@ function readDeploymentIdentity(env = process.env, execPath = process.execPath,
491
492
  * `test.relay.uploads.init` relay handler — the developer never reaches the
492
493
  * orchestrator's HTTP API directly.
493
494
  */
494
- const logger$128 = createLogger({ prefix: "uploads" });
495
+ const logger$130 = createLogger({ prefix: "uploads" });
495
496
  /**
496
497
  * Sanitize a routing key for use in S3 storage paths.
497
498
  * Replaces characters that are problematic in S3 keys.
@@ -533,7 +534,7 @@ async function initTestUpload(deps, params) {
533
534
  expires_at: expiresAt,
534
535
  created_by: params.createdBy ?? null
535
536
  }).execute();
536
- logger$128.info("Upload initialized", {
537
+ logger$130.info("Upload initialized", {
537
538
  uploadId,
538
539
  routingKey,
539
540
  sha: sha ?? "unknown",
@@ -1092,6 +1093,7 @@ var prometheus_exports = /* @__PURE__ */ __exportAll({
1092
1093
  trustMatchRefusedNoIdTotal: () => trustMatchRefusedNoIdTotal,
1093
1094
  trustPolicyDecisionsTotal: () => trustPolicyDecisionsTotal,
1094
1095
  universalGitRegistrationErrorsTotal: () => universalGitRegistrationErrorsTotal,
1096
+ unroutableFastFailedTotal: () => unroutableFastFailedTotal,
1095
1097
  webhooksProcessedTotal: () => webhooksProcessedTotal,
1096
1098
  webhooksReceivedTotal: () => webhooksReceivedTotal,
1097
1099
  wsNackReceivedTotal: () => wsNackReceivedTotal,
@@ -1276,7 +1278,7 @@ function registerOrchestratorMetrics() {
1276
1278
  _observableGaugesRegistered = true;
1277
1279
  for (const register of _observableGauges) register();
1278
1280
  }
1279
- var _meter$1, _observableGauges, _agentsActiveValue, _configVersionValue, _drainingValue, _declaredHostsUnreachableValue, _staleRunsCurrentValue, _pendingAttestationsValue, _pendingAttestationOldestAgeSeconds, _rejectedAttestationsValue, _dbCollationDrift, _scalerUsageRows, _scalerSpawnRefusalsValue, scalerRedispatchTotal, _queueDepthBreakdown, _everSeenQueueLabels, EMPTY_INGEST_STATE, _ingest, _ingestLimits, ingestShedTotal, stateReplayBreakerTripsTotal, ingestAdmittedTotal, _overflowBuffered, ingestOverflowCapturedTotal, ingestOverflowReplayedTotal, ingestOverflowDroppedTotal, webhooksReceivedTotal, webhooksProcessedTotal, trustPolicyDecisionsTotal, triggerMatchDurationSeconds, dedupHitsTotal, pgPoolClientErrorsTotal, sourceCacheHitsTotal, sourceCacheMissesTotal, depCacheHitsTotal, depCacheMissesTotal, buildDurationSeconds, executionsTotal, executionDurationSeconds, stepsTotal, githubCheckRunTotal, logChunksReceivedTotal, logBytesStoredTotal, scalerConfigReloadsTotal, ScalerSpawnFailureBound, scalerSpawnFailuresTotal, configReloadTotal, staleRunsDetectedTotal, staleDetectionDurationSeconds, crossSourceFanoutSize, crossSourceErrorsTotal, universalGitRegistrationErrorsTotal, trustMatchRefusedNoIdTotal, eventDispatchSuccessTotal, eventRetryTotal, eventDlqTotal, eventLeaseExpirationsTotal, eventAttemptsHistogram, _eventDlqDepthValue, InstallSecretsDecisionReason, InstallSecretsChannel, installSecretsDecisionsTotal, installSecretsRegistryUsedTotal, installSecretsContributorStrippedTotal, installSecretsTokenResolutionDurationSeconds, dispatchQueueRowsPrunedTotal, stepLogsPrunedTotal, checkRunTrackingRowsPrunedTotal, wsUnsupportedMessageSentTotal, wsNackReceivedTotal, wsPlatformCapabilityGapTotal, _observableGaugesRegistered;
1281
+ var _meter$1, _observableGauges, _agentsActiveValue, _configVersionValue, _drainingValue, _declaredHostsUnreachableValue, _staleRunsCurrentValue, _pendingAttestationsValue, _pendingAttestationOldestAgeSeconds, _rejectedAttestationsValue, _dbCollationDrift, _scalerUsageRows, _scalerSpawnRefusalsValue, scalerRedispatchTotal, _queueDepthBreakdown, _everSeenQueueLabels, EMPTY_INGEST_STATE, _ingest, _ingestLimits, ingestShedTotal, stateReplayBreakerTripsTotal, ingestAdmittedTotal, _overflowBuffered, ingestOverflowCapturedTotal, ingestOverflowReplayedTotal, ingestOverflowDroppedTotal, webhooksReceivedTotal, webhooksProcessedTotal, trustPolicyDecisionsTotal, triggerMatchDurationSeconds, dedupHitsTotal, pgPoolClientErrorsTotal, sourceCacheHitsTotal, sourceCacheMissesTotal, depCacheHitsTotal, depCacheMissesTotal, buildDurationSeconds, executionsTotal, executionDurationSeconds, stepsTotal, githubCheckRunTotal, logChunksReceivedTotal, logBytesStoredTotal, scalerConfigReloadsTotal, ScalerSpawnFailureBound, scalerSpawnFailuresTotal, configReloadTotal, staleRunsDetectedTotal, staleDetectionDurationSeconds, crossSourceFanoutSize, crossSourceErrorsTotal, universalGitRegistrationErrorsTotal, trustMatchRefusedNoIdTotal, eventDispatchSuccessTotal, eventRetryTotal, eventDlqTotal, eventLeaseExpirationsTotal, eventAttemptsHistogram, _eventDlqDepthValue, InstallSecretsDecisionReason, InstallSecretsChannel, installSecretsDecisionsTotal, installSecretsRegistryUsedTotal, installSecretsContributorStrippedTotal, installSecretsTokenResolutionDurationSeconds, dispatchQueueRowsPrunedTotal, unroutableFastFailedTotal, stepLogsPrunedTotal, checkRunTrackingRowsPrunedTotal, wsUnsupportedMessageSentTotal, wsNackReceivedTotal, wsPlatformCapabilityGapTotal, _observableGaugesRegistered;
1280
1282
  var init_prometheus = __esmMin((() => {
1281
1283
  _observableGauges = [];
1282
1284
  _agentsActiveValue = 0;
@@ -1533,6 +1535,7 @@ var init_prometheus = __esmMin((() => {
1533
1535
  ] }
1534
1536
  });
1535
1537
  dispatchQueueRowsPrunedTotal = lazyCounter$1("kici_orch_dispatch_queue_rows_pruned_total", { description: "Terminal dispatch_queue rows deleted by the retention sweep" });
1538
+ unroutableFastFailedTotal = lazyCounter$1("kici_orch_unroutable_fast_failed_total", { description: "Jobs terminalized as unroutable by the fast-fail probe (not the queue timeout)" });
1536
1539
  stepLogsPrunedTotal = lazyCounter$1("kici_orch_step_logs_pruned_total", { description: "Step-log objects deleted by the retention sweep" });
1537
1540
  checkRunTrackingRowsPrunedTotal = lazyCounter$1("kici_orch_check_run_tracking_rows_pruned_total", { description: "check_run_tracking rows deleted by the retention sweep" });
1538
1541
  wsUnsupportedMessageSentTotal = lazyCounter$1("kici_orch_ws_unsupported_message_sent_total", { description: "NACKs sent to the Platform for an unrecognized inbound message type (version skew)" });
@@ -1565,7 +1568,7 @@ var trust_resolver_exports = /* @__PURE__ */ __exportAll({
1565
1568
  function findIdentityLink(identityLinks, provider, providerUsername, providerUserId) {
1566
1569
  if (providerUserId === void 0 || providerUserId.length === 0) {
1567
1570
  trustMatchRefusedNoIdTotal.add(1, { reason: "event_missing" });
1568
- logger$127.warn("Trust match refused: webhook event has no provider numeric id", {
1571
+ logger$129.warn("Trust match refused: webhook event has no provider numeric id", {
1569
1572
  provider,
1570
1573
  providerUsername
1571
1574
  });
@@ -1577,7 +1580,7 @@ function findIdentityLink(identityLinks, provider, providerUsername, providerUse
1577
1580
  if (byUsername) {
1578
1581
  const reason = byUsername.providerUserId === null || byUsername.providerUserId === void 0 ? "link_missing" : "id_mismatch";
1579
1582
  trustMatchRefusedNoIdTotal.add(1, { reason });
1580
- logger$127.warn("Trust match refused: numeric id missing on link or did not match event", {
1583
+ logger$129.warn("Trust match refused: numeric id missing on link or did not match event", {
1581
1584
  provider,
1582
1585
  providerUsername,
1583
1586
  providerUserId,
@@ -1605,10 +1608,10 @@ function isReadOrHigher(permission) {
1605
1608
  function isCiTrustWriteOrHigher(level) {
1606
1609
  return level === "write" || level === "admin";
1607
1610
  }
1608
- var logger$127, TrustResolver$1;
1611
+ var logger$129, TrustResolver$1;
1609
1612
  var init_trust_resolver = __esmMin((() => {
1610
1613
  init_prometheus();
1611
- logger$127 = createLogger({ prefix: "trust-resolver" });
1614
+ logger$129 = createLogger({ prefix: "trust-resolver" });
1612
1615
  TrustResolver$1 = class {
1613
1616
  contributorCache;
1614
1617
  constructor(contributorCache) {
@@ -1739,14 +1742,14 @@ async function handleApprovalComment(params) {
1739
1742
  const { commentBody, commenterUsername, commenterUserId, provider, repoIdentifier, prNumber, orgId, identityLinks, orgMemberPermissions, heldRunStore } = params;
1740
1743
  const command = parseKiciCommand(commentBody);
1741
1744
  if (!command) return { handled: false };
1742
- logger$126.info("Processing /kici command", {
1745
+ logger$128.info("Processing /kici command", {
1743
1746
  action: command.action,
1744
1747
  commenter: commenterUsername,
1745
1748
  runId: command.runId
1746
1749
  });
1747
1750
  const identityLink = findIdentityLink(identityLinks, provider, commenterUsername, commenterUserId);
1748
1751
  if (!identityLink) {
1749
- logger$126.info("No identity link for commenter", {
1752
+ logger$128.info("No identity link for commenter", {
1750
1753
  commenter: commenterUsername,
1751
1754
  provider
1752
1755
  });
@@ -1757,7 +1760,7 @@ async function handleApprovalComment(params) {
1757
1760
  }
1758
1761
  const ciTrustLevel = orgMemberPermissions.get(identityLink.userId) ?? "none";
1759
1762
  if (ciTrustLevel !== "write" && ciTrustLevel !== "admin") {
1760
- logger$126.info("Insufficient ci_trust level", {
1763
+ logger$128.info("Insufficient ci_trust level", {
1761
1764
  commenter: commenterUsername,
1762
1765
  userId: identityLink.userId,
1763
1766
  ciTrustLevel
@@ -1769,7 +1772,7 @@ async function handleApprovalComment(params) {
1769
1772
  }
1770
1773
  const pendingHolds = await heldRunStore.listPendingSecurityHoldsForPr(orgId, repoIdentifier, prNumber);
1771
1774
  if (pendingHolds.length === 0) {
1772
- logger$126.info("No pending security holds found for PR", {
1775
+ logger$128.info("No pending security holds found for PR", {
1773
1776
  orgId,
1774
1777
  repoIdentifier,
1775
1778
  prNumber
@@ -1778,7 +1781,7 @@ async function handleApprovalComment(params) {
1778
1781
  }
1779
1782
  const targetHolds = command.runId ? pendingHolds.filter((h) => h.run_id === command.runId) : pendingHolds;
1780
1783
  if (targetHolds.length === 0) {
1781
- logger$126.info("No matching security holds found", {
1784
+ logger$128.info("No matching security holds found", {
1782
1785
  orgId,
1783
1786
  runId: command.runId
1784
1787
  });
@@ -1789,14 +1792,14 @@ async function handleApprovalComment(params) {
1789
1792
  for (const hold of targetHolds) try {
1790
1793
  if (approved) {
1791
1794
  await heldRunStore.approveByQueueType(orgId, hold.id, identityLink.userId, "security");
1792
- logger$126.info("Security hold approved", {
1795
+ logger$128.info("Security hold approved", {
1793
1796
  heldRunId: hold.id,
1794
1797
  runId: hold.run_id,
1795
1798
  approvedBy: identityLink.userId
1796
1799
  });
1797
1800
  } else {
1798
1801
  await heldRunStore.reject(orgId, hold.id, `Rejected by ${commenterUsername} via /kici reject`);
1799
- logger$126.info("Security hold rejected", {
1802
+ logger$128.info("Security hold rejected", {
1800
1803
  heldRunId: hold.id,
1801
1804
  runId: hold.run_id,
1802
1805
  rejectedBy: commenterUsername
@@ -1804,7 +1807,7 @@ async function handleApprovalComment(params) {
1804
1807
  }
1805
1808
  processedCount++;
1806
1809
  } catch (err) {
1807
- logger$126.error("Failed to process security hold", {
1810
+ logger$128.error("Failed to process security hold", {
1808
1811
  heldRunId: hold.id,
1809
1812
  action: command.action,
1810
1813
  error: toErrorMessage(err)
@@ -1814,15 +1817,15 @@ async function handleApprovalComment(params) {
1814
1817
  const title = approved ? "Approved" : "Rejected";
1815
1818
  const summary = approved ? `Approved by ${commenterUsername} via /kici approve` : `Rejected by ${commenterUsername} via /kici reject`;
1816
1819
  params.checkStatusPoster.postCheckStatus(params.repoIdentifier, params.commitSha, approved ? "success" : "failure", title, summary, params.credentials).catch((err) => {
1817
- logger$126.warn("Failed to update check status after approval", { error: toErrorMessage(err) });
1820
+ logger$128.warn("Failed to update check status after approval", { error: toErrorMessage(err) });
1818
1821
  });
1819
1822
  }
1820
1823
  return { handled: true };
1821
1824
  }
1822
- var logger$126;
1825
+ var logger$128;
1823
1826
  var init_comment_handler = __esmMin((() => {
1824
1827
  init_trust_resolver();
1825
- logger$126 = createLogger({ prefix: "comment-handler" });
1828
+ logger$128 = createLogger({ prefix: "comment-handler" });
1826
1829
  }));
1827
1830
  //#endregion
1828
1831
  //#region src/registration/extractor.ts
@@ -1916,9 +1919,9 @@ function payloadFromObject$1(payload) {
1916
1919
  function payloadFromRawBody(body) {
1917
1920
  return { raw: Buffer.from(body, "utf-8") };
1918
1921
  }
1919
- var logger$125, EventLogWriter;
1922
+ var logger$127, EventLogWriter;
1920
1923
  var init_event_log$1 = __esmMin((() => {
1921
- logger$125 = createLogger({ prefix: "event-log" });
1924
+ logger$127 = createLogger({ prefix: "event-log" });
1922
1925
  EventLogWriter = class EventLogWriter {
1923
1926
  db;
1924
1927
  logStorage;
@@ -1955,7 +1958,7 @@ var init_event_log$1 = __esmMin((() => {
1955
1958
  if (sizeBytes > maxBytes) {
1956
1959
  payloadOmitted = true;
1957
1960
  payloadOmittedReason = PayloadOmittedReason.enum.size_exceeded;
1958
- logger$125.warn("Webhook payload exceeds soft cap; recording metadata only", {
1961
+ logger$127.warn("Webhook payload exceeds soft cap; recording metadata only", {
1959
1962
  deliveryId: info.deliveryId,
1960
1963
  sizeBytes,
1961
1964
  maxBytes
@@ -1969,7 +1972,7 @@ var init_event_log$1 = __esmMin((() => {
1969
1972
  } catch (err) {
1970
1973
  payloadOmitted = true;
1971
1974
  payloadOmittedReason = PayloadOmittedReason.enum.storage_failed;
1972
- logger$125.error("Failed to upload event-log payload to object storage", {
1975
+ logger$127.error("Failed to upload event-log payload to object storage", {
1973
1976
  deliveryId: info.deliveryId,
1974
1977
  orgId: outcome.orgId,
1975
1978
  error: toErrorMessage(err)
@@ -2006,7 +2009,7 @@ var init_event_log$1 = __esmMin((() => {
2006
2009
  ref: row.ref
2007
2010
  })).execute();
2008
2011
  } catch (err) {
2009
- logger$125.error("Failed to record event_log row", {
2012
+ logger$127.error("Failed to record event_log row", {
2010
2013
  deliveryId: info.deliveryId,
2011
2014
  orgId: outcome.orgId,
2012
2015
  error: toErrorMessage(err)
@@ -2764,6 +2767,7 @@ var init_schema = __esmMin((() => {
2764
2767
  rosterTtlMs: z.coerce.number().default(18e5),
2765
2768
  queueMaxDepth: z.coerce.number().default(1e3),
2766
2769
  queueTimeoutMs: z.coerce.number().default(36e5),
2770
+ unroutableGraceMs: z.coerce.number().default(12e4),
2767
2771
  /**
2768
2772
  * Operator-facing backpressure warning threshold. See `configSchema` in
2769
2773
  * `packages/orchestrator/src/config.ts` for the user-facing prose.
@@ -3243,6 +3247,7 @@ function flattenToAppConfig(merged) {
3243
3247
  const queue = merged.queue;
3244
3248
  flat.queueMaxDepth = queue?.maxDepth ?? 1e3;
3245
3249
  flat.queueTimeoutMs = queue?.timeoutMs ?? 36e5;
3250
+ flat.unroutableGraceMs = queue?.unroutableGraceMs ?? 12e4;
3246
3251
  flat.queueBackpressureThreshold = queue?.backpressureThreshold ?? 100;
3247
3252
  const lfCache = merged.lockfileCache;
3248
3253
  flat.lockfileCacheMax = lfCache?.max ?? 500;
@@ -3334,9 +3339,9 @@ function satisfiesMandatoryLabels(agent, requiredLabels) {
3334
3339
  for (const label of agent.mandatoryLabels) if (!requiredSet.has(label)) return false;
3335
3340
  return true;
3336
3341
  }
3337
- var logger$124, AgentRegistry;
3342
+ var logger$126, AgentRegistry;
3338
3343
  var init_registry = __esmMin((() => {
3339
- logger$124 = createLogger({ prefix: "agent-registry" });
3344
+ logger$126 = createLogger({ prefix: "agent-registry" });
3340
3345
  AgentRegistry = class {
3341
3346
  /** Primary: agentId -> AgentEntry */
3342
3347
  agents = /* @__PURE__ */ new Map();
@@ -3459,7 +3464,7 @@ var init_registry = __esmMin((() => {
3459
3464
  arch,
3460
3465
  instanceId,
3461
3466
  properties: metadata?.properties
3462
- }).catch((err) => logger$124.warn("host_roster upsert failed (best-effort)", {
3467
+ }).catch((err) => logger$126.warn("host_roster upsert failed (best-effort)", {
3463
3468
  agentId,
3464
3469
  error: toErrorMessage(err)
3465
3470
  }));
@@ -3854,9 +3859,9 @@ var init_leader_gated_scheduler = __esmMin((() => {
3854
3859
  * Driven by the leader-only host-roster reaper's tick (one timer, one leader),
3855
3860
  * so this class owns no timer of its own — just a testable `scan()`.
3856
3861
  */
3857
- var logger$123, RebootDeadlineSweep;
3862
+ var logger$125, RebootDeadlineSweep;
3858
3863
  var init_reboot_deadline_sweep = __esmMin((() => {
3859
- logger$123 = createLogger({ prefix: "reboot-deadline-sweep" });
3864
+ logger$125 = createLogger({ prefix: "reboot-deadline-sweep" });
3860
3865
  RebootDeadlineSweep = class {
3861
3866
  rosterStore;
3862
3867
  constructor(deps) {
@@ -3868,21 +3873,21 @@ var init_reboot_deadline_sweep = __esmMin((() => {
3868
3873
  const expired = await this.rosterStore.listExpiredRebootPending(Date.now());
3869
3874
  for (const agentId of expired) {
3870
3875
  await this.rosterStore.clearRebootPending(agentId);
3871
- logger$123.warn("Host did not return after reboot within deadline; cleared reboot-pending", { agentId });
3876
+ logger$125.warn("Host did not return after reboot within deadline; cleared reboot-pending", { agentId });
3872
3877
  }
3873
3878
  } catch (err) {
3874
- logger$123.error("Reboot deadline sweep error", { error: toErrorMessage(err) });
3879
+ logger$125.error("Reboot deadline sweep error", { error: toErrorMessage(err) });
3875
3880
  }
3876
3881
  }
3877
3882
  };
3878
3883
  }));
3879
3884
  //#endregion
3880
3885
  //#region src/agent/host-roster-reaper.ts
3881
- var logger$122, HostRosterReaper;
3886
+ var logger$124, HostRosterReaper;
3882
3887
  var init_host_roster_reaper = __esmMin((() => {
3883
3888
  init_leader_gated_scheduler();
3884
3889
  init_reboot_deadline_sweep();
3885
- logger$122 = createLogger({ prefix: "host-roster-reaper" });
3890
+ logger$124 = createLogger({ prefix: "host-roster-reaper" });
3886
3891
  HostRosterReaper = class {
3887
3892
  store;
3888
3893
  ttlMs;
@@ -3901,7 +3906,7 @@ var init_host_roster_reaper = __esmMin((() => {
3901
3906
  this.scheduler = new LeaderGatedScheduler({
3902
3907
  name: "host roster reaper",
3903
3908
  intervalMs: this.scanIntervalMs,
3904
- logger: logger$122,
3909
+ logger: logger$124,
3905
3910
  tick: () => this.tick()
3906
3911
  });
3907
3912
  }
@@ -3918,10 +3923,10 @@ var init_host_roster_reaper = __esmMin((() => {
3918
3923
  async tick() {
3919
3924
  if (!this.scheduler.isLeader) return;
3920
3925
  const deleted = await this.store.reapEphemeralPastTtl(this.ttlMs);
3921
- if (deleted > 0) logger$122.info("Reaped expired ephemeral hosts", { deleted });
3926
+ if (deleted > 0) logger$124.info("Reaped expired ephemeral hosts", { deleted });
3922
3927
  const unreachable = await this.store.countStaticUnreachable(this.graceMs);
3923
3928
  this.setUnreachableGauge(unreachable);
3924
- if (unreachable > 0) logger$122.warn("Declared hosts unreachable", { count: unreachable });
3929
+ if (unreachable > 0) logger$124.warn("Declared hosts unreachable", { count: unreachable });
3925
3930
  await this.rebootSweep.scan();
3926
3931
  }
3927
3932
  };
@@ -3929,6 +3934,22 @@ var init_host_roster_reaper = __esmMin((() => {
3929
3934
  //#endregion
3930
3935
  //#region src/queue/job-queue.ts
3931
3936
  /**
3937
+ * Shared row -> {@link ExpiredJobInfo} mapping, so the expiry sweep and the
3938
+ * unroutable probe can never read a job's selectors differently.
3939
+ */
3940
+ function rowToExpiredJobInfo(r) {
3941
+ return {
3942
+ id: r.id,
3943
+ runId: r.run_id,
3944
+ jobName: r.job_name,
3945
+ lastProvisioningError: r.last_provisioning_error ?? null,
3946
+ runsOnLabels: parseSelectorColumnForExpiry(r.runs_on_labels, "runs_on_labels"),
3947
+ runsOnPatterns: parseSelectorColumnForExpiry(r.runs_on_patterns, "runs_on_patterns"),
3948
+ excludeLabels: parseSelectorColumnForExpiry(r.exclude_labels, "exclude_labels"),
3949
+ excludePatterns: parseSelectorColumnForExpiry(r.exclude_patterns, "exclude_patterns")
3950
+ };
3951
+ }
3952
+ /**
3932
3953
  * Parse a `dispatch_queue` jsonb pattern column into a `LabelMatcher[]`. Handles
3933
3954
  * both the auto-parsed array form (from the pg driver) and the JSON string form
3934
3955
  * (from tests / a non-parsing driver). A missing value yields `[]`.
@@ -3959,9 +3980,9 @@ function parseSelectorColumnForExpiry(v, column) {
3959
3980
  if (typeof v === "string") try {
3960
3981
  const parsed = JSON.parse(v);
3961
3982
  if (Array.isArray(parsed)) return parsed;
3962
- logger$121.warn("dispatch_queue selector column is not a JSON array", { column });
3983
+ logger$123.warn("dispatch_queue selector column is not a JSON array", { column });
3963
3984
  } catch {
3964
- logger$121.warn("dispatch_queue selector column holds malformed JSON", { column });
3985
+ logger$123.warn("dispatch_queue selector column holds malformed JSON", { column });
3965
3986
  }
3966
3987
  return [];
3967
3988
  }
@@ -3976,9 +3997,9 @@ function jobPatternsSatisfiedBy(job, labels) {
3976
3997
  if (job.excludePatterns.some((p) => matcherSatisfiedBy(p, labels))) return false;
3977
3998
  return true;
3978
3999
  }
3979
- var logger$121, JobQueue;
4000
+ var logger$123, JobQueue;
3980
4001
  var init_job_queue = __esmMin((() => {
3981
- logger$121 = createLogger({ prefix: "job-queue" });
4002
+ logger$123 = createLogger({ prefix: "job-queue" });
3982
4003
  JobQueue = class {
3983
4004
  db;
3984
4005
  /** Cluster-wide fallback for queue_max_depth when cluster_settings is null. */
@@ -4287,16 +4308,7 @@ var init_job_queue = __esmMin((() => {
4287
4308
  ]).where("status", "=", "pending").where("expires_at", "is not", null).where("expires_at", "<", now).execute();
4288
4309
  if (rows.length === 0) return [];
4289
4310
  await this.db.updateTable("dispatch_queue").set({ status: "expired" }).where("id", "in", rows.map((r) => r.id)).execute();
4290
- return rows.map((r) => ({
4291
- id: r.id,
4292
- runId: r.run_id,
4293
- jobName: r.job_name,
4294
- lastProvisioningError: r.last_provisioning_error ?? null,
4295
- runsOnLabels: parseSelectorColumnForExpiry(r.runs_on_labels, "runs_on_labels"),
4296
- runsOnPatterns: parseSelectorColumnForExpiry(r.runs_on_patterns, "runs_on_patterns"),
4297
- excludeLabels: parseSelectorColumnForExpiry(r.exclude_labels, "exclude_labels"),
4298
- excludePatterns: parseSelectorColumnForExpiry(r.exclude_patterns, "exclude_patterns")
4299
- }));
4311
+ return rows.map((r) => rowToExpiredJobInfo(r));
4300
4312
  }
4301
4313
  /**
4302
4314
  * Bulk-fail every still-non-terminal dispatch_queue entry for a run.
@@ -4571,7 +4583,8 @@ var init_job_queue = __esmMin((() => {
4571
4583
  dispatch_attempts: sql`dispatch_attempts + 1`,
4572
4584
  ack_deadline: null,
4573
4585
  ack_agent_id: null,
4574
- agent_id: null
4586
+ agent_id: null,
4587
+ unroutable_since: null
4575
4588
  }).where("id", "=", jobId).where("status", "=", "dispatched").returning("dispatch_attempts").executeTakeFirst();
4576
4589
  this.depthCache = null;
4577
4590
  this.breakdownCache = null;
@@ -4694,6 +4707,59 @@ var init_job_queue = __esmMin((() => {
4694
4707
  return (await this.pendingOldestFirstQuery().limit(limit).execute()).map((row) => this.rowToQueuedJob(row));
4695
4708
  }
4696
4709
  /**
4710
+ * Pending, non-expired jobs with the facts the unroutable probe needs:
4711
+ * routing selectors, any recorded provisioning error, and the grace clock.
4712
+ *
4713
+ * Read-only — no claim, no `FOR UPDATE`; the probe never dispatches. Reuses
4714
+ * the shared pending query so it inherits the same FIFO ordering and
4715
+ * not-yet-expired filter the rest of the queue uses.
4716
+ */
4717
+ async listUnroutableCandidates(limit) {
4718
+ return (await this.pendingOldestFirstQuery().limit(limit).execute()).map((row) => ({
4719
+ ...rowToExpiredJobInfo(row),
4720
+ unroutableSince: row.unroutable_since ? new Date(row.unroutable_since) : null
4721
+ }));
4722
+ }
4723
+ /**
4724
+ * Stamp the grace clock the first time a job reads unroutable.
4725
+ *
4726
+ * The `unroutable_since IS NULL` guard is load-bearing, not defensive: the
4727
+ * cleanup/probe ticks are NOT leader-gated, so without it two coordinators
4728
+ * would each re-stamp `now` on every tick, pushing the deadline outward
4729
+ * forever and preventing the grace from ever elapsing.
4730
+ */
4731
+ async markUnroutableSince(id, at) {
4732
+ await this.db.updateTable("dispatch_queue").set({ unroutable_since: at }).where("id", "=", id).where("unroutable_since", "is", null).execute();
4733
+ }
4734
+ /** Clear the grace clock after the job reads routable again. */
4735
+ async clearUnroutableState(id) {
4736
+ await this.db.updateTable("dispatch_queue").set({ unroutable_since: null }).where("id", "=", id).execute();
4737
+ }
4738
+ /**
4739
+ * Claim a still-pending row for fast-fail, moving it out of the queue.
4740
+ *
4741
+ * Mirrors {@link markExpired}: the queue row has to leave `Pending` in the
4742
+ * same breath the job is terminalized, and for the same two reasons.
4743
+ * A row left pending is still dispatchable, so an agent connecting later
4744
+ * would pick up a job whose `execution_jobs` row already reads terminal; and
4745
+ * the probe re-lists it on every tick, re-running the whole terminalize path
4746
+ * (and re-counting the fast-fail metric) until the queue timeout finally
4747
+ * expires it.
4748
+ *
4749
+ * The `status = Pending` guard is also the concurrency arbiter — probe ticks
4750
+ * are NOT leader-gated, so exactly one coordinator's UPDATE hits a row and
4751
+ * the losers get `false` and move on.
4752
+ *
4753
+ * @returns true when this call claimed the row, false when it was already
4754
+ * dispatched, cancelled, expired, or claimed by another coordinator.
4755
+ */
4756
+ async claimUnroutable(id) {
4757
+ const result = await this.db.updateTable("dispatch_queue").set({ status: "expired" }).where("id", "=", id).where("status", "=", "pending").executeTakeFirst();
4758
+ this.depthCache = null;
4759
+ this.breakdownCache = null;
4760
+ return Number(result.numUpdatedRows ?? 0) > 0;
4761
+ }
4762
+ /**
4697
4763
  * Convert a DB row to a QueuedJob object.
4698
4764
  * Handles both auto-parsed JSONB arrays (from pg driver) and JSON strings (from tests).
4699
4765
  */
@@ -4732,6 +4798,82 @@ var init_job_queue = __esmMin((() => {
4732
4798
  };
4733
4799
  }));
4734
4800
  //#endregion
4801
+ //#region src/reporting/log-retention.ts
4802
+ /**
4803
+ * Delete step-log objects older than `ttlDays` in one bulk pass.
4804
+ *
4805
+ * Step-log objects are write-once (appended during the run, untouched after
4806
+ * finalize), so last-modified time is the correct expiry basis — a recent or
4807
+ * still-running run's objects were all written within the window and survive.
4808
+ * `ttlDays <= 0` disables the sweep (returns 0). Expired objects are collected
4809
+ * then bulk-deleted via `deleteMany` (S3 DeleteObjects), so a large sweep is a
4810
+ * handful of API calls, not one-per-object. A delete failure is logged and the
4811
+ * cleanup tick is not aborted.
4812
+ *
4813
+ * @returns Number of objects deleted.
4814
+ */
4815
+ async function pruneExpiredLogs(storage, ttlDays, now = /* @__PURE__ */ new Date()) {
4816
+ if (ttlDays <= 0) return 0;
4817
+ const cutoff = now.getTime() - ttlDays * 864e5;
4818
+ const expired = (await storage.listWithMetadata(LOG_ROOT_PREFIX)).filter((o) => o.lastModified.getTime() < cutoff).map((o) => o.path);
4819
+ if (expired.length === 0) return 0;
4820
+ try {
4821
+ return await storage.deleteMany(expired);
4822
+ } catch (err) {
4823
+ logger$122.error("Failed to bulk-delete expired log objects", {
4824
+ count: expired.length,
4825
+ error: toErrorMessage(err)
4826
+ });
4827
+ return 0;
4828
+ }
4829
+ }
4830
+ var logger$122, LOG_ROOT_PREFIX;
4831
+ var init_log_retention = __esmMin((() => {
4832
+ logger$122 = createLogger({ prefix: "log-retention" });
4833
+ LOG_ROOT_PREFIX = "executions/";
4834
+ }));
4835
+ //#endregion
4836
+ //#region src/pipeline/request-idempotency.ts
4837
+ /**
4838
+ * Atomically claim a run-minting request by its Platform `requestId`. Returns
4839
+ * the run id to use. `claimed: false` means a sibling coordinator already owns
4840
+ * this requestId (a relay failover re-sent the same request): the caller MUST
4841
+ * return `{ newRunId }` WITHOUT creating or dispatching a run, so one user
4842
+ * click yields exactly one run.
4843
+ *
4844
+ * Shared by `run.rerun.request` and `run.manual_schedule.request` — both mint a
4845
+ * fresh run and both ride the Platform's timeout-driven failover path. HA
4846
+ * coordinator siblings share one orchestrator DB, so the `INSERT … ON CONFLICT
4847
+ * (request_id) DO NOTHING` is the single point of arbitration: exactly one hop
4848
+ * inserts and wins; the loser reads back the winner's `new_run_id`.
4849
+ */
4850
+ async function claimRequestId(db, requestId) {
4851
+ const candidate = randomUUID();
4852
+ if (await db.insertInto("request_idempotency").values({
4853
+ request_id: requestId,
4854
+ new_run_id: candidate
4855
+ }).onConflict((oc) => oc.column("request_id").doNothing()).returning("new_run_id").executeTakeFirst()) return {
4856
+ newRunId: candidate,
4857
+ claimed: true
4858
+ };
4859
+ return {
4860
+ newRunId: (await db.selectFrom("request_idempotency").select("new_run_id").where("request_id", "=", requestId).executeTakeFirstOrThrow()).new_run_id,
4861
+ claimed: false
4862
+ };
4863
+ }
4864
+ /**
4865
+ * Prune `request_idempotency` rows older than 1h. The request budget is ~10s,
4866
+ * so a claimed requestId is never re-sent after an hour; keeping the table
4867
+ * bounded avoids unbounded growth on a long-lived coordinator.
4868
+ *
4869
+ * @returns the number of rows deleted.
4870
+ */
4871
+ async function pruneRequestIdempotency(db) {
4872
+ const result = await db.deleteFrom("request_idempotency").where("created_at", "<", sql`now() - interval '1 hour'`).executeTakeFirst();
4873
+ return Number(result.numDeletedRows ?? 0n);
4874
+ }
4875
+ var init_request_idempotency = __esmMin((() => {}));
4876
+ //#endregion
4735
4877
  //#region src/providers/github/auth.ts
4736
4878
  /**
4737
4879
  * GitHub clone token provider and authentication utilities.
@@ -5020,12 +5162,12 @@ function buildJobFailureDescription(data) {
5020
5162
  if (data.error) return `Job error: ${data.error}`;
5021
5163
  return "Job failed";
5022
5164
  }
5023
- var logger$120, PROGRESS_DEBOUNCE_MS, CheckRunReporter;
5165
+ var logger$121, PROGRESS_DEBOUNCE_MS, CheckRunReporter;
5024
5166
  var init_check_run_reporter = __esmMin((() => {
5025
5167
  init_auth();
5026
5168
  init_prometheus();
5027
5169
  init_check_run_summary();
5028
- logger$120 = createLogger({ prefix: "check-run-reporter" });
5170
+ logger$121 = createLogger({ prefix: "check-run-reporter" });
5029
5171
  PROGRESS_DEBOUNCE_MS = 5e3;
5030
5172
  CheckRunReporter = class {
5031
5173
  deps;
@@ -5116,7 +5258,7 @@ var init_check_run_reporter = __esmMin((() => {
5116
5258
  */
5117
5259
  setPending(opts) {
5118
5260
  this.doSetPending(opts).catch((err) => {
5119
- logger$120.error("Failed to set pending check run", {
5261
+ logger$121.error("Failed to set pending check run", {
5120
5262
  error: toErrorMessage(err),
5121
5263
  provider: opts.provider,
5122
5264
  owner: opts.owner,
@@ -5141,7 +5283,7 @@ var init_check_run_reporter = __esmMin((() => {
5141
5283
  */
5142
5284
  updateJobStatus(opts) {
5143
5285
  this.doUpdateJobStatus(opts).catch((err) => {
5144
- logger$120.error("Failed to update job check run", {
5286
+ logger$121.error("Failed to update job check run", {
5145
5287
  error: toErrorMessage(err),
5146
5288
  provider: opts.provider,
5147
5289
  owner: opts.owner,
@@ -5160,7 +5302,7 @@ var init_check_run_reporter = __esmMin((() => {
5160
5302
  */
5161
5303
  updateWorkflowStatus(opts) {
5162
5304
  this.doUpdateWorkflowStatus(opts).catch((err) => {
5163
- logger$120.error("Failed to update workflow check run", {
5305
+ logger$121.error("Failed to update workflow check run", {
5164
5306
  error: toErrorMessage(err),
5165
5307
  provider: opts.provider,
5166
5308
  owner: opts.owner,
@@ -5185,7 +5327,7 @@ var init_check_run_reporter = __esmMin((() => {
5185
5327
  */
5186
5328
  cleanupStaleCheckRuns(opts) {
5187
5329
  this.doCleanupStaleCheckRuns(opts).catch((err) => {
5188
- logger$120.error("Failed to clean up stale check runs", {
5330
+ logger$121.error("Failed to clean up stale check runs", {
5189
5331
  error: toErrorMessage(err),
5190
5332
  provider: opts.provider,
5191
5333
  owner: opts.owner,
@@ -5204,7 +5346,7 @@ var init_check_run_reporter = __esmMin((() => {
5204
5346
  */
5205
5347
  updateStepProgress(opts) {
5206
5348
  this.doUpdateStepProgress(opts).catch((err) => {
5207
- logger$120.error("Failed to update step progress", {
5349
+ logger$121.error("Failed to update step progress", {
5208
5350
  error: toErrorMessage(err),
5209
5351
  provider: opts.provider,
5210
5352
  workflowName: opts.workflowName,
@@ -5227,7 +5369,7 @@ var init_check_run_reporter = __esmMin((() => {
5227
5369
  this.persistBuildCreationPending(key, opts.runId);
5228
5370
  this.trackRunKey(opts.runId, key);
5229
5371
  const creation = this.doSetBuildPending(opts).catch((err) => {
5230
- logger$120.error("Failed to set build pending check run", {
5372
+ logger$121.error("Failed to set build pending check run", {
5231
5373
  error: toErrorMessage(err),
5232
5374
  provider: opts.provider,
5233
5375
  owner: opts.owner,
@@ -5246,7 +5388,7 @@ var init_check_run_reporter = __esmMin((() => {
5246
5388
  */
5247
5389
  setBuildComplete(opts) {
5248
5390
  this.doSetBuildComplete(opts).catch((err) => {
5249
- logger$120.error("Failed to set build complete check run", {
5391
+ logger$121.error("Failed to set build complete check run", {
5250
5392
  error: toErrorMessage(err),
5251
5393
  provider: opts.provider,
5252
5394
  owner: opts.owner,
@@ -5298,7 +5440,7 @@ var init_check_run_reporter = __esmMin((() => {
5298
5440
  */
5299
5441
  async recoverState() {
5300
5442
  if (!this.deps.trackingStore) return;
5301
- logger$120.info("CheckRunReporter recovered (DB-backed state lookups enabled)");
5443
+ logger$121.info("CheckRunReporter recovered (DB-backed state lookups enabled)");
5302
5444
  }
5303
5445
  /** Track a check run key associated with a runId for later cleanup. */
5304
5446
  trackRunKey(runId, key) {
@@ -5340,7 +5482,7 @@ var init_check_run_reporter = __esmMin((() => {
5340
5482
  await this.deps.trackingStore.setCheckRunId(this.parseKey(key), checkRunId, runId);
5341
5483
  if (runId) await this.deps.trackingStore.markBuildCreationComplete(this.parseKey(key));
5342
5484
  } catch (err) {
5343
- logger$120.warn("Failed to persist check_run_tracking row; cache-only fallback", {
5485
+ logger$121.warn("Failed to persist check_run_tracking row; cache-only fallback", {
5344
5486
  key,
5345
5487
  error: toErrorMessage(err)
5346
5488
  });
@@ -5360,7 +5502,7 @@ var init_check_run_reporter = __esmMin((() => {
5360
5502
  if (fromDb !== void 0) this.checkRunIds.set(key, fromDb);
5361
5503
  return fromDb;
5362
5504
  } catch (err) {
5363
- logger$120.warn("Failed to read check_run_tracking row; treating as miss", {
5505
+ logger$121.warn("Failed to read check_run_tracking row; treating as miss", {
5364
5506
  key,
5365
5507
  error: toErrorMessage(err)
5366
5508
  });
@@ -5376,7 +5518,7 @@ var init_check_run_reporter = __esmMin((() => {
5376
5518
  try {
5377
5519
  await this.deps.trackingStore.setStepProgress(this.parseKey(key), steps, runId);
5378
5520
  } catch (err) {
5379
- logger$120.warn("Failed to persist step-progress; cache-only fallback", {
5521
+ logger$121.warn("Failed to persist step-progress; cache-only fallback", {
5380
5522
  key,
5381
5523
  error: toErrorMessage(err)
5382
5524
  });
@@ -5391,7 +5533,7 @@ var init_check_run_reporter = __esmMin((() => {
5391
5533
  try {
5392
5534
  await this.deps.trackingStore.markInProgressSent(this.parseKey(key), runId);
5393
5535
  } catch (err) {
5394
- logger$120.warn("Failed to persist in-progress-sent marker; cache-only fallback", {
5536
+ logger$121.warn("Failed to persist in-progress-sent marker; cache-only fallback", {
5395
5537
  key,
5396
5538
  error: toErrorMessage(err)
5397
5539
  });
@@ -5405,7 +5547,7 @@ var init_check_run_reporter = __esmMin((() => {
5405
5547
  try {
5406
5548
  await this.deps.trackingStore.markBuildCreationPending(this.parseKey(key), runId);
5407
5549
  } catch (err) {
5408
- logger$120.warn("Failed to persist build-creation-pending marker", {
5550
+ logger$121.warn("Failed to persist build-creation-pending marker", {
5409
5551
  key,
5410
5552
  error: toErrorMessage(err)
5411
5553
  });
@@ -5471,12 +5613,12 @@ var init_check_run_reporter = __esmMin((() => {
5471
5613
  }
5472
5614
  async doSetPending(opts) {
5473
5615
  if (opts.provider !== "github") {
5474
- logger$120.warn("Check runs not supported for provider, skipping", { provider: opts.provider });
5616
+ logger$121.warn("Check runs not supported for provider, skipping", { provider: opts.provider });
5475
5617
  return;
5476
5618
  }
5477
5619
  const githubConfig = this.resolveGithubConfig(opts.routingKey);
5478
5620
  if (!githubConfig || !opts.installationId) {
5479
- logger$120.debug("GitHub config or installationId missing, skipping check run", {
5621
+ logger$121.debug("GitHub config or installationId missing, skipping check run", {
5480
5622
  hasConfig: !!githubConfig,
5481
5623
  hasInstallationId: !!opts.installationId
5482
5624
  });
@@ -5526,19 +5668,19 @@ var init_check_run_reporter = __esmMin((() => {
5526
5668
  }
5527
5669
  async doUpdateJobStatus(opts) {
5528
5670
  if (opts.provider !== "github") {
5529
- logger$120.warn("Check runs not supported for provider, skipping", { provider: opts.provider });
5671
+ logger$121.warn("Check runs not supported for provider, skipping", { provider: opts.provider });
5530
5672
  return;
5531
5673
  }
5532
5674
  const githubConfig = this.resolveGithubConfig(opts.routingKey);
5533
5675
  if (!githubConfig || !opts.installationId) {
5534
- logger$120.debug("GitHub config or installationId missing, skipping check run update");
5676
+ logger$121.debug("GitHub config or installationId missing, skipping check run update");
5535
5677
  return;
5536
5678
  }
5537
5679
  const checkName = `kici/${opts.workflowName}/job/${opts.jobName}`;
5538
5680
  const key = this.checkRunKey(opts.owner, opts.repo, opts.sha, checkName);
5539
5681
  const checkRunId = await this.resolveCheckRunId(key);
5540
5682
  if (!checkRunId) {
5541
- logger$120.warn("Check run ID not found for job update, skipping", { key });
5683
+ logger$121.warn("Check run ID not found for job update, skipping", { key });
5542
5684
  return;
5543
5685
  }
5544
5686
  const pendingTimer = this.progressTimers.get(key);
@@ -5611,18 +5753,18 @@ var init_check_run_reporter = __esmMin((() => {
5611
5753
  }
5612
5754
  async doUpdateWorkflowStatus(opts) {
5613
5755
  if (opts.provider !== "github") {
5614
- logger$120.warn("Check runs not supported for provider, skipping", { provider: opts.provider });
5756
+ logger$121.warn("Check runs not supported for provider, skipping", { provider: opts.provider });
5615
5757
  return;
5616
5758
  }
5617
5759
  const githubConfig = this.resolveGithubConfig(opts.routingKey);
5618
5760
  if (!githubConfig || !opts.installationId) {
5619
- logger$120.debug("GitHub config or installationId missing, skipping check run update");
5761
+ logger$121.debug("GitHub config or installationId missing, skipping check run update");
5620
5762
  return;
5621
5763
  }
5622
5764
  const key = this.checkRunKey(opts.owner, opts.repo, opts.sha, `kici/${opts.workflowName}`);
5623
5765
  const checkRunId = await this.resolveCheckRunId(key);
5624
5766
  if (!checkRunId) {
5625
- logger$120.warn("Check run ID not found for workflow update, skipping", { key });
5767
+ logger$121.warn("Check run ID not found for workflow update, skipping", { key });
5626
5768
  return;
5627
5769
  }
5628
5770
  const octokit = createInstallationOctokit(githubConfig, opts.installationId);
@@ -5645,12 +5787,12 @@ var init_check_run_reporter = __esmMin((() => {
5645
5787
  }
5646
5788
  async doCleanupStaleCheckRuns(opts) {
5647
5789
  if (opts.provider !== "github") {
5648
- logger$120.debug("Stale check run cleanup not supported for provider, skipping", { provider: opts.provider });
5790
+ logger$121.debug("Stale check run cleanup not supported for provider, skipping", { provider: opts.provider });
5649
5791
  return;
5650
5792
  }
5651
5793
  const githubConfig = this.resolveGithubConfig(opts.routingKey);
5652
5794
  if (!githubConfig) {
5653
- logger$120.debug("GitHub config not available for stale cleanup, skipping", { routingKey: opts.routingKey });
5795
+ logger$121.debug("GitHub config not available for stale cleanup, skipping", { routingKey: opts.routingKey });
5654
5796
  return;
5655
5797
  }
5656
5798
  const appOctokit = new Octokit({
@@ -5668,7 +5810,7 @@ var init_check_run_reporter = __esmMin((() => {
5668
5810
  });
5669
5811
  installationId = data.id;
5670
5812
  } catch (err) {
5671
- logger$120.warn("Could not find installation for repo, skipping stale cleanup", {
5813
+ logger$121.warn("Could not find installation for repo, skipping stale cleanup", {
5672
5814
  owner: opts.owner,
5673
5815
  repo: opts.repo,
5674
5816
  error: toErrorMessage(err)
@@ -5703,14 +5845,14 @@ var init_check_run_reporter = __esmMin((() => {
5703
5845
  });
5704
5846
  cleanedCount++;
5705
5847
  } catch (updateErr) {
5706
- logger$120.warn("Failed to update stale check run", {
5848
+ logger$121.warn("Failed to update stale check run", {
5707
5849
  checkRunId: checkRun.id,
5708
5850
  checkName: checkRun.name,
5709
5851
  error: toErrorMessage(updateErr)
5710
5852
  });
5711
5853
  }
5712
5854
  if (cleanedCount > 0) {
5713
- logger$120.info("Cleaned up stale check runs", {
5855
+ logger$121.info("Cleaned up stale check runs", {
5714
5856
  owner: opts.owner,
5715
5857
  repo: opts.repo,
5716
5858
  sha: opts.sha,
@@ -5720,7 +5862,7 @@ var init_check_run_reporter = __esmMin((() => {
5720
5862
  githubCheckRunTotal.add(cleanedCount, { operation: "stale_cleanup" });
5721
5863
  }
5722
5864
  } catch (err) {
5723
- logger$120.error("Failed to list check runs for stale cleanup", {
5865
+ logger$121.error("Failed to list check runs for stale cleanup", {
5724
5866
  owner: opts.owner,
5725
5867
  repo: opts.repo,
5726
5868
  sha: opts.sha,
@@ -5786,7 +5928,7 @@ var init_check_run_reporter = __esmMin((() => {
5786
5928
  const timer = setTimeout(() => {
5787
5929
  this.progressTimers.delete(key);
5788
5930
  this.flushProgress(key, opts).catch((err) => {
5789
- logger$120.error("Failed to flush step progress", {
5931
+ logger$121.error("Failed to flush step progress", {
5790
5932
  error: toErrorMessage(err),
5791
5933
  key
5792
5934
  });
@@ -5826,12 +5968,12 @@ var init_check_run_reporter = __esmMin((() => {
5826
5968
  }
5827
5969
  async doSetBuildPending(opts) {
5828
5970
  if (opts.provider !== "github") {
5829
- logger$120.warn("Check runs not supported for provider, skipping", { provider: opts.provider });
5971
+ logger$121.warn("Check runs not supported for provider, skipping", { provider: opts.provider });
5830
5972
  return;
5831
5973
  }
5832
5974
  const githubConfig = this.resolveGithubConfig(opts.routingKey);
5833
5975
  if (!githubConfig || !opts.installationId) {
5834
- logger$120.debug("GitHub config or installationId missing, skipping build check run", {
5976
+ logger$121.debug("GitHub config or installationId missing, skipping build check run", {
5835
5977
  hasConfig: !!githubConfig,
5836
5978
  hasInstallationId: !!opts.installationId
5837
5979
  });
@@ -5860,12 +6002,12 @@ var init_check_run_reporter = __esmMin((() => {
5860
6002
  }
5861
6003
  async doSetBuildComplete(opts) {
5862
6004
  if (opts.provider !== "github") {
5863
- logger$120.warn("Check runs not supported for provider, skipping", { provider: opts.provider });
6005
+ logger$121.warn("Check runs not supported for provider, skipping", { provider: opts.provider });
5864
6006
  return;
5865
6007
  }
5866
6008
  const githubConfig = this.resolveGithubConfig(opts.routingKey);
5867
6009
  if (!githubConfig || !opts.installationId) {
5868
- logger$120.debug("GitHub config or installationId missing, skipping build check run update");
6010
+ logger$121.debug("GitHub config or installationId missing, skipping build check run update");
5869
6011
  return;
5870
6012
  }
5871
6013
  const buildCheckName = `kici/${opts.workflowName}/setup`;
@@ -5874,7 +6016,7 @@ var init_check_run_reporter = __esmMin((() => {
5874
6016
  if (pending) await pending;
5875
6017
  const checkRunId = await this.resolveCheckRunId(key);
5876
6018
  if (!checkRunId) {
5877
- logger$120.warn("Check run ID not found for build update, skipping", { key });
6019
+ logger$121.warn("Check run ID not found for build update, skipping", { key });
5878
6020
  return;
5879
6021
  }
5880
6022
  const octokit = createInstallationOctokit(githubConfig, opts.installationId);
@@ -5930,7 +6072,7 @@ var init_check_run_reporter = __esmMin((() => {
5930
6072
  };
5931
6073
  default: {
5932
6074
  const unexpected = status;
5933
- logger$120.warn("Unexpected terminal job status mapping a build conclusion", { status: unexpected });
6075
+ logger$121.warn("Unexpected terminal job status mapping a build conclusion", { status: unexpected });
5934
6076
  return {
5935
6077
  conclusion: CheckRunConclusion.enum.failure,
5936
6078
  description: customDescription ?? "Build finished with an unrecognised status"
@@ -5973,7 +6115,7 @@ var init_check_run_reporter = __esmMin((() => {
5973
6115
  };
5974
6116
  default: {
5975
6117
  const unexpected = state;
5976
- logger$120.warn("Unexpected terminal job status mapping a job conclusion", { status: unexpected });
6118
+ logger$121.warn("Unexpected terminal job status mapping a job conclusion", { status: unexpected });
5977
6119
  return {
5978
6120
  conclusion: CheckRunConclusion.enum.failure,
5979
6121
  description: customDescription ?? "Job finished with an unrecognised status"
@@ -6016,7 +6158,7 @@ var init_check_run_reporter = __esmMin((() => {
6016
6158
  };
6017
6159
  default: {
6018
6160
  const unexpected = status;
6019
- logger$120.warn("Unexpected terminal job status mapping a workflow conclusion", { status: unexpected });
6161
+ logger$121.warn("Unexpected terminal job status mapping a workflow conclusion", { status: unexpected });
6020
6162
  return {
6021
6163
  conclusion: CheckRunConclusion.enum.failure,
6022
6164
  description: customDescription ?? "Workflow finished with an unrecognised status"
@@ -6046,12 +6188,12 @@ var init_check_run_reporter = __esmMin((() => {
6046
6188
  if (error.status === 403) {
6047
6189
  const rateRemaining = error.response?.headers?.["x-ratelimit-remaining"];
6048
6190
  const rateReset = error.response?.headers?.["x-ratelimit-reset"];
6049
- logger$120.error("GitHub API 403 creating check run", {
6191
+ logger$121.error("GitHub API 403 creating check run", {
6050
6192
  name: params.name,
6051
6193
  rateRemaining,
6052
6194
  rateReset
6053
6195
  });
6054
- } else logger$120.error("GitHub API error creating check run", {
6196
+ } else logger$121.error("GitHub API error creating check run", {
6055
6197
  name: params.name,
6056
6198
  status: error.status,
6057
6199
  error: toErrorMessage(err)
@@ -6088,12 +6230,12 @@ var init_check_run_reporter = __esmMin((() => {
6088
6230
  if (error.status === 403) {
6089
6231
  const rateRemaining = error.response?.headers?.["x-ratelimit-remaining"];
6090
6232
  const rateReset = error.response?.headers?.["x-ratelimit-reset"];
6091
- logger$120.error("GitHub API 403 updating check run", {
6233
+ logger$121.error("GitHub API 403 updating check run", {
6092
6234
  checkRunId: params.check_run_id,
6093
6235
  rateRemaining,
6094
6236
  rateReset
6095
6237
  });
6096
- } else logger$120.error("GitHub API error updating check run", {
6238
+ } else logger$121.error("GitHub API error updating check run", {
6097
6239
  checkRunId: params.check_run_id,
6098
6240
  status: error.status,
6099
6241
  error: toErrorMessage(err)
@@ -6102,7 +6244,7 @@ var init_check_run_reporter = __esmMin((() => {
6102
6244
  if (patchAccepted && params.status === "completed" && trackingKey && this.deps.trackingStore) try {
6103
6245
  await this.deps.trackingStore.markTerminalSent(this.parseKey(trackingKey), trackingRunId);
6104
6246
  } catch (err) {
6105
- logger$120.warn("Failed to stamp terminal_sent_at; continuing", {
6247
+ logger$121.warn("Failed to stamp terminal_sent_at; continuing", {
6106
6248
  key: trackingKey,
6107
6249
  error: toErrorMessage(err)
6108
6250
  });
@@ -6145,7 +6287,7 @@ function reportJobCheckRunCompletion(deps, input) {
6145
6287
  try {
6146
6288
  postJobCheckRunCompletion(deps, input);
6147
6289
  } catch (err) {
6148
- logger$119.error("Failed to report job check-run completion", {
6290
+ logger$120.error("Failed to report job check-run completion", {
6149
6291
  error: toErrorMessage(err),
6150
6292
  runId: input.runId,
6151
6293
  jobId: input.jobId,
@@ -6157,7 +6299,7 @@ function postJobCheckRunCompletion(deps, input) {
6157
6299
  if (!isTerminalJobStatus(input.status)) return;
6158
6300
  const execContext = deps.getExecutionContext(input.runId);
6159
6301
  if (!execContext) {
6160
- logger$119.debug("No execution context for job check-run completion, skipping", {
6302
+ logger$120.debug("No execution context for job check-run completion, skipping", {
6161
6303
  runId: input.runId,
6162
6304
  jobId: input.jobId
6163
6305
  });
@@ -6182,105 +6324,107 @@ function postJobCheckRunCompletion(deps, input) {
6182
6324
  runId: input.runId
6183
6325
  });
6184
6326
  }
6185
- var logger$119;
6327
+ var logger$120;
6186
6328
  var init_job_check_run_completion = __esmMin((() => {
6187
6329
  init_check_run_reporter();
6188
- logger$119 = createLogger({ prefix: "check-run-completion" });
6330
+ logger$120 = createLogger({ prefix: "check-run-completion" });
6189
6331
  }));
6190
6332
  //#endregion
6191
- //#region src/reporting/log-retention.ts
6333
+ //#region src/queue/terminalize-unroutable.ts
6192
6334
  /**
6193
- * Delete step-log objects older than `ttlDays` in one bulk pass.
6194
- *
6195
- * Step-log objects are write-once (appended during the run, untouched after
6196
- * finalize), so last-modified time is the correct expiry basis — a recent or
6197
- * still-running run's objects were all written within the window and survive.
6198
- * `ttlDays <= 0` disables the sweep (returns 0). Expired objects are collected
6199
- * then bulk-deleted via `deleteMany` (S3 DeleteObjects), so a large sweep is a
6200
- * handful of API calls, not one-per-object. A delete failure is logged and the
6201
- * cleanup tick is not aborted.
6202
- *
6203
- * @returns Number of objects deleted.
6335
+ * The operator-facing reason a job is `unroutable`, naming the exact selectors
6336
+ * that went unmatched. Regex matchers are rendered as their source so the
6337
+ * message stays readable rather than printing `[object Object]`.
6204
6338
  */
6205
- async function pruneExpiredLogs(storage, ttlDays, now = /* @__PURE__ */ new Date()) {
6206
- if (ttlDays <= 0) return 0;
6207
- const cutoff = now.getTime() - ttlDays * 864e5;
6208
- const expired = (await storage.listWithMetadata(LOG_ROOT_PREFIX)).filter((o) => o.lastModified.getTime() < cutoff).map((o) => o.path);
6209
- if (expired.length === 0) return 0;
6210
- try {
6211
- return await storage.deleteMany(expired);
6212
- } catch (err) {
6213
- logger$118.error("Failed to bulk-delete expired log objects", {
6214
- count: expired.length,
6215
- error: toErrorMessage(err)
6216
- });
6217
- return 0;
6218
- }
6339
+ function renderMatcher(m) {
6340
+ return m.kind === "exact" ? m.value : `/${m.source}/${m.flags}`;
6341
+ }
6342
+ function unroutableMessage(job) {
6343
+ const required = [...job.runsOnLabels, ...job.runsOnPatterns.map(renderMatcher)];
6344
+ const excluded = [...job.excludeLabels, ...job.excludePatterns.map(renderMatcher)];
6345
+ const parts = [required.length > 0 ? `runsOn [${required.join(", ")}]` : "this job (it declares no runsOn, so any agent would do)"];
6346
+ if (excluded.length > 0) parts.push(`excluding [${excluded.join(", ")}]`);
6347
+ return `No connected agent or scaler backend currently matches ${parts.join(" ")} the job was never dispatched`;
6219
6348
  }
6220
- var logger$118, LOG_ROOT_PREFIX;
6221
- var init_log_retention = __esmMin((() => {
6222
- logger$118 = createLogger({ prefix: "log-retention" });
6223
- LOG_ROOT_PREFIX = "executions/";
6224
- }));
6225
- //#endregion
6226
- //#region src/pipeline/request-idempotency.ts
6227
6349
  /**
6228
- * Atomically claim a run-minting request by its Platform `requestId`. Returns
6229
- * the run id to use. `claimed: false` means a sibling coordinator already owns
6230
- * this requestId (a relay failover re-sent the same request): the caller MUST
6231
- * return `{ newRunId }` WITHOUT creating or dispatching a run, so one user
6232
- * click yields exactly one run.
6350
+ * Split the two reasons a queued job never ran: nothing in the fleet matched
6351
+ * its `runsOn` (`unroutable` a label/fleet problem an operator has to fix)
6352
+ * versus something matched but never produced a usable agent
6353
+ * (`timed_out_stale` a capacity or provisioning problem).
6233
6354
  *
6234
- * Shared by `run.rerun.request` and `run.manual_schedule.request` both mint a
6235
- * fresh run and both ride the Platform's timeout-driven failover path. HA
6236
- * coordinator siblings share one orchestrator DB, so the `INSERT ON CONFLICT
6237
- * (request_id) DO NOTHING` is the single point of arbitration: exactly one hop
6238
- * inserts and wins; the loser reads back the winner's `new_run_id`.
6355
+ * Shared by the unroutable probe (which asks on a short tick, gated by a grace
6356
+ * window) and the queue-expiry sweep (which asks once at expiry, as the
6357
+ * backstop). One verdict, two moments in time a second copy of this logic is
6358
+ * exactly the drift this module exists to prevent.
6239
6359
  */
6240
- async function claimRequestId(db, requestId) {
6241
- const candidate = randomUUID();
6242
- if (await db.insertInto("request_idempotency").values({
6243
- request_id: requestId,
6244
- new_run_id: candidate
6245
- }).onConflict((oc) => oc.column("request_id").doNothing()).returning("new_run_id").executeTakeFirst()) return {
6246
- newRunId: candidate,
6247
- claimed: true
6248
- };
6360
+ function classifyUnroutable(job, canRouteLabels) {
6361
+ const unroutable = job.lastProvisioningError === null && canRouteLabels !== void 0 && !canRouteLabels(job.runsOnLabels, job.runsOnPatterns, job.excludeLabels, job.excludePatterns);
6249
6362
  return {
6250
- newRunId: (await db.selectFrom("request_idempotency").select("new_run_id").where("request_id", "=", requestId).executeTakeFirstOrThrow()).new_run_id,
6251
- claimed: false
6363
+ unroutable,
6364
+ status: unroutable ? ExecutionJobStatus.enum.unroutable : ExecutionJobStatus.enum.timed_out_stale,
6365
+ errorMessage: unroutable ? unroutableMessage(job) : job.lastProvisioningError ?? GENERIC_MESSAGE
6252
6366
  };
6253
6367
  }
6254
6368
  /**
6255
- * Prune `request_idempotency` rows older than 1h. The request budget is ~10s,
6256
- * so a claimed requestId is never re-sent after an hour; keeping the table
6257
- * bounded avoids unbounded growth on a long-lived coordinator.
6369
+ * Settle one never-dispatched job: write the terminal status locally, surface
6370
+ * the reason at run level, forward to Platform, and resolve its check run.
6258
6371
  *
6259
- * @returns the number of rows deleted.
6372
+ * @returns the run id when this call actually terminalized the job (so the
6373
+ * caller can complete the run), or null when another coordinator got there
6374
+ * first or the job was no longer pending.
6260
6375
  */
6261
- async function pruneRequestIdempotency(db) {
6262
- const result = await db.deleteFrom("request_idempotency").where("created_at", "<", sql`now() - interval '1 hour'`).executeTakeFirst();
6263
- return Number(result.numDeletedRows ?? 0n);
6376
+ async function terminalizeUnroutableJob(deps, job) {
6377
+ const { status, errorMessage, unroutable } = classifyUnroutable(job, deps.canRouteLabels);
6378
+ try {
6379
+ const ejResult = await deps.db.updateTable("execution_jobs").set({
6380
+ status,
6381
+ completed_at: /* @__PURE__ */ new Date(),
6382
+ error_message: errorMessage
6383
+ }).where("run_id", "=", sql`${job.runId}::uuid`).where("job_name", "=", job.jobName).where("status", "in", [ExecutionJobStatus.enum.pending, ExecutionJobStatus.enum.queued]).executeTakeFirst();
6384
+ if (!ejResult.numUpdatedRows || ejResult.numUpdatedRows === 0n) return null;
6385
+ const runReason = unroutable ? errorMessage : job.lastProvisioningError;
6386
+ if (runReason) await deps.db.updateTable("execution_runs").set({ failure_reason: runReason }).where("run_id", "=", sql`${job.runId}::uuid`).where("failure_reason", "is", null).execute();
6387
+ const ejRow = await deps.db.selectFrom("execution_jobs").select(["job_id"]).where("run_id", "=", sql`${job.runId}::uuid`).where("job_name", "=", job.jobName).executeTakeFirst();
6388
+ if (ejRow) {
6389
+ deps.executionTracker.updateInMemoryJob(job.runId, ejRow.job_id, status);
6390
+ deps.executionTracker.forwardJobTerminalStatus(job.runId, ejRow.job_id, job.jobName, status, errorMessage);
6391
+ deps.executionTracker.emitInfraEvent(job.runId, "orchestrator.job.queue_expired", {
6392
+ jobId: ejRow.job_id,
6393
+ metadata: {
6394
+ jobName: job.jobName,
6395
+ reason: errorMessage
6396
+ }
6397
+ });
6398
+ if (deps.checkRunReporter) reportJobCheckRunCompletion({
6399
+ checkRunReporter: deps.checkRunReporter,
6400
+ getExecutionContext: (runId) => deps.executionTracker.getExecutionContext(runId)
6401
+ }, {
6402
+ runId: job.runId,
6403
+ jobId: ejRow.job_id,
6404
+ jobName: job.jobName,
6405
+ status,
6406
+ description: errorMessage
6407
+ });
6408
+ }
6409
+ return job.runId;
6410
+ } catch (err) {
6411
+ logger$119.error("Failed to forward never-dispatched job status", {
6412
+ runId: job.runId,
6413
+ jobName: job.jobName,
6414
+ error: toErrorMessage(err)
6415
+ });
6416
+ return null;
6417
+ }
6264
6418
  }
6265
- var init_request_idempotency = __esmMin((() => {}));
6419
+ var logger$119, GENERIC_MESSAGE;
6420
+ var init_terminalize_unroutable = __esmMin((() => {
6421
+ init_job_check_run_completion();
6422
+ logger$119 = createLogger({ prefix: "terminalize-unroutable" });
6423
+ GENERIC_MESSAGE = "Queue timeout expired (job was never dispatched to an agent)";
6424
+ }));
6266
6425
  //#endregion
6267
6426
  //#region src/queue/cleanup.ts
6268
6427
  /**
6269
- * The operator-facing reason an expired job is `unroutable`, naming the exact
6270
- * selectors that went unmatched. Regex matchers are rendered as their source so
6271
- * the message stays readable rather than printing `[object Object]`.
6272
- */
6273
- function renderMatcher(m) {
6274
- return m.kind === "exact" ? m.value : `/${m.source}/${m.flags}`;
6275
- }
6276
- function unroutableMessage(job) {
6277
- const required = [...job.runsOnLabels, ...job.runsOnPatterns.map(renderMatcher)];
6278
- const excluded = [...job.excludeLabels, ...job.excludePatterns.map(renderMatcher)];
6279
- const parts = [required.length > 0 ? `runsOn [${required.join(", ")}]` : "this job (it declares no runsOn, so any agent would do)"];
6280
- if (excluded.length > 0) parts.push(`excluding [${excluded.join(", ")}]`);
6281
- return `No connected agent or scaler backend currently matches ${parts.join(" ")} — the job was never dispatched`;
6282
- }
6283
- /**
6284
6428
  * Run a single cleanup pass: remove expired dedup_cache entries and
6285
6429
  * mark expired dispatch_queue entries.
6286
6430
  *
@@ -6304,31 +6448,31 @@ async function runCleanup(dedup, queue, extras) {
6304
6448
  if (extras) {
6305
6449
  try {
6306
6450
  const pruned = await pruneRequestIdempotency(extras.db);
6307
- if (pruned > 0) logger$117.info("Pruned stale request idempotency claims", { pruned });
6451
+ if (pruned > 0) logger$118.info("Pruned stale request idempotency claims", { pruned });
6308
6452
  } catch (err) {
6309
- logger$117.error("Failed to prune request idempotency claims", { error: toErrorMessage(err) });
6453
+ logger$118.error("Failed to prune request idempotency claims", { error: toErrorMessage(err) });
6310
6454
  }
6311
6455
  const ttlDays = extras.dispatchQueueTtlDays ?? 30;
6312
6456
  try {
6313
6457
  dispatchRowsPruned = await queue.pruneTerminalDispatchRows(ttlDays);
6314
6458
  if (dispatchRowsPruned > 0) {
6315
6459
  dispatchQueueRowsPrunedTotal.add(dispatchRowsPruned);
6316
- logger$117.info("Pruned terminal dispatch_queue rows", {
6460
+ logger$118.info("Pruned terminal dispatch_queue rows", {
6317
6461
  dispatchRowsPruned,
6318
6462
  ttlDays
6319
6463
  });
6320
6464
  }
6321
6465
  } catch (err) {
6322
- logger$117.error("Failed to prune terminal dispatch_queue rows", { error: toErrorMessage(err) });
6466
+ logger$118.error("Failed to prune terminal dispatch_queue rows", { error: toErrorMessage(err) });
6323
6467
  }
6324
6468
  if (extras.logStorage && extras.logStorageIsS3) try {
6325
6469
  logObjectsPruned = await pruneExpiredLogs(extras.logStorage, extras.stepLogTtlDays ?? 90);
6326
6470
  if (logObjectsPruned > 0) {
6327
6471
  stepLogsPrunedTotal.add(logObjectsPruned);
6328
- logger$117.info("Pruned expired step-log objects", { logObjectsPruned });
6472
+ logger$118.info("Pruned expired step-log objects", { logObjectsPruned });
6329
6473
  }
6330
6474
  } catch (err) {
6331
- logger$117.error("Failed to prune expired step-log objects", { error: toErrorMessage(err) });
6475
+ logger$118.error("Failed to prune expired step-log objects", { error: toErrorMessage(err) });
6332
6476
  }
6333
6477
  if (extras.checkRunTrackingStore) {
6334
6478
  const checkRunTtlDefault = extras.checkRunTrackingTtlDays ?? 7;
@@ -6337,81 +6481,44 @@ async function runCleanup(dedup, queue, extras) {
6337
6481
  checkRunRowsPruned = await extras.checkRunTrackingStore.pruneStale(ttlDays);
6338
6482
  if (checkRunRowsPruned > 0) {
6339
6483
  checkRunTrackingRowsPrunedTotal.add(checkRunRowsPruned);
6340
- logger$117.info("Pruned stale check-run-tracking rows", {
6484
+ logger$118.info("Pruned stale check-run-tracking rows", {
6341
6485
  checkRunRowsPruned,
6342
6486
  ttlDays
6343
6487
  });
6344
6488
  }
6345
6489
  } catch (err) {
6346
- logger$117.error("Failed to prune stale check-run-tracking rows", { error: toErrorMessage(err) });
6490
+ logger$118.error("Failed to prune stale check-run-tracking rows", { error: toErrorMessage(err) });
6347
6491
  }
6348
6492
  }
6349
6493
  }
6350
6494
  if (extras && expiredJobs.length > 0) {
6351
6495
  const affectedRunIds = /* @__PURE__ */ new Set();
6352
- const genericMessage = "Queue timeout expired (job was never dispatched to an agent)";
6353
6496
  for (const job of expiredJobs) {
6354
- const unroutable = job.lastProvisioningError === null && extras.canRouteLabels !== void 0 && !extras.canRouteLabels(job.runsOnLabels, job.runsOnPatterns, job.excludeLabels, job.excludePatterns);
6355
- const status = unroutable ? ExecutionJobStatus.enum.unroutable : ExecutionJobStatus.enum.timed_out_stale;
6356
- const errorMessage = unroutable ? unroutableMessage(job) : job.lastProvisioningError ?? genericMessage;
6357
- try {
6358
- const ejResult = await extras.db.updateTable("execution_jobs").set({
6359
- status,
6360
- completed_at: /* @__PURE__ */ new Date(),
6361
- error_message: errorMessage
6362
- }).where("run_id", "=", sql`${job.runId}::uuid`).where("job_name", "=", job.jobName).where("status", "in", [ExecutionJobStatus.enum.pending, ExecutionJobStatus.enum.queued]).executeTakeFirst();
6363
- if (ejResult.numUpdatedRows && ejResult.numUpdatedRows > 0n) {
6364
- const runReason = unroutable ? errorMessage : job.lastProvisioningError;
6365
- if (runReason) await extras.db.updateTable("execution_runs").set({ failure_reason: runReason }).where("run_id", "=", sql`${job.runId}::uuid`).where("failure_reason", "is", null).execute();
6366
- const ejRow = await extras.db.selectFrom("execution_jobs").select(["job_id"]).where("run_id", "=", sql`${job.runId}::uuid`).where("job_name", "=", job.jobName).executeTakeFirst();
6367
- if (ejRow) {
6368
- extras.executionTracker.updateInMemoryJob(job.runId, ejRow.job_id, status);
6369
- extras.executionTracker.forwardJobTerminalStatus(job.runId, ejRow.job_id, job.jobName, status, errorMessage);
6370
- extras.executionTracker.emitInfraEvent(job.runId, "orchestrator.job.queue_expired", {
6371
- jobId: ejRow.job_id,
6372
- metadata: {
6373
- jobName: job.jobName,
6374
- reason: errorMessage
6375
- }
6376
- });
6377
- if (extras.checkRunReporter) reportJobCheckRunCompletion({
6378
- checkRunReporter: extras.checkRunReporter,
6379
- getExecutionContext: (runId) => extras.executionTracker.getExecutionContext(runId)
6380
- }, {
6381
- runId: job.runId,
6382
- jobId: ejRow.job_id,
6383
- jobName: job.jobName,
6384
- status,
6385
- description: errorMessage
6386
- });
6387
- }
6388
- affectedRunIds.add(job.runId);
6389
- }
6390
- } catch (err) {
6391
- logger$117.error("Failed to forward expired job status", {
6392
- runId: job.runId,
6393
- jobName: job.jobName,
6394
- error: toErrorMessage(err)
6395
- });
6396
- }
6497
+ const runId = await terminalizeUnroutableJob({
6498
+ db: extras.db,
6499
+ executionTracker: extras.executionTracker,
6500
+ checkRunReporter: extras.checkRunReporter,
6501
+ canRouteLabels: extras.canRouteLabels
6502
+ }, job);
6503
+ if (runId) affectedRunIds.add(runId);
6397
6504
  }
6398
6505
  for (const runId of affectedRunIds) try {
6399
6506
  await extras.executionTracker.completeRunIfAllJobsTerminal(runId);
6400
6507
  } catch (err) {
6401
- logger$117.error("Error checking run completion after queue expiry", {
6508
+ logger$118.error("Error checking run completion after queue expiry", {
6402
6509
  runId,
6403
6510
  error: toErrorMessage(err)
6404
6511
  });
6405
6512
  }
6406
6513
  }
6407
- if (dedupDeleted > 0 || queueExpired > 0 || dispatchRowsPruned > 0 || logObjectsPruned > 0 || checkRunRowsPruned > 0) logger$117.info("Cleanup completed", {
6514
+ if (dedupDeleted > 0 || queueExpired > 0 || dispatchRowsPruned > 0 || logObjectsPruned > 0 || checkRunRowsPruned > 0) logger$118.info("Cleanup completed", {
6408
6515
  dedupDeleted,
6409
6516
  queueExpired,
6410
6517
  dispatchRowsPruned,
6411
6518
  logObjectsPruned,
6412
6519
  checkRunRowsPruned
6413
6520
  });
6414
- else logger$117.debug("Cleanup completed, nothing to clean");
6521
+ else logger$118.debug("Cleanup completed, nothing to clean");
6415
6522
  return {
6416
6523
  dedupDeleted,
6417
6524
  queueExpired,
@@ -6432,13 +6539,100 @@ function createCleanupHandler(dedup, queue, extras) {
6432
6539
  await runCleanup(dedup, queue, extras);
6433
6540
  };
6434
6541
  }
6435
- var logger$117;
6542
+ var logger$118;
6436
6543
  var init_cleanup$1 = __esmMin((() => {
6437
- init_job_check_run_completion();
6438
6544
  init_log_retention();
6439
6545
  init_request_idempotency();
6440
6546
  init_prometheus();
6441
- logger$117 = createLogger({ prefix: "cleanup" });
6547
+ init_terminalize_unroutable();
6548
+ logger$118 = createLogger({ prefix: "cleanup" });
6549
+ }));
6550
+ //#endregion
6551
+ //#region src/queue/unroutable-probe.ts
6552
+ /**
6553
+ * Probe cadence, derived from the grace rather than configured separately.
6554
+ *
6555
+ * The tick is an implementation detail of the grace window — it only has to be
6556
+ * fine-grained enough that the grace elapses on time — not independent policy,
6557
+ * so it deliberately does not earn its own cluster knob.
6558
+ */
6559
+ function probeTickIntervalMs(graceMs) {
6560
+ return Math.min(TICK_CEILING_MS, Math.max(TICK_FLOOR_MS, Math.floor(graceMs / 4)));
6561
+ }
6562
+ /**
6563
+ * Write the routing reason onto a job that is still waiting to be routed.
6564
+ *
6565
+ * The status guard matters: the reason is a statement about a job that has not
6566
+ * been picked up, so it must never annotate one that already started or
6567
+ * finished between the probe's read and this write.
6568
+ */
6569
+ function makeRoutingReasonWriter(db) {
6570
+ return async (runId, jobName, reason) => {
6571
+ await db.updateTable("execution_jobs").set({ routing_reason: reason }).where("run_id", "=", sql`${runId}::uuid`).where("job_name", "=", jobName).where("status", "in", [ExecutionJobStatus.enum.pending, ExecutionJobStatus.enum.queued]).execute();
6572
+ };
6573
+ }
6574
+ /**
6575
+ * Build the per-tick handler for the unroutable probe.
6576
+ *
6577
+ * The probe consults the SAME routability predicate the queue-expiry sweep uses
6578
+ * — one verdict, two moments in time — but asks on a short tick instead of once
6579
+ * an hour. On the first unroutable verdict it records the reason (so the cause
6580
+ * is visible while the job still waits) and starts a grace clock; only once the
6581
+ * job has been CONTINUOUSLY unroutable for the whole grace does it terminalize.
6582
+ * A job that reads routable again has both cleared, so a scaler reload or an
6583
+ * agent reconnect can never cost it its place in the queue.
6584
+ */
6585
+ function createUnroutableProbeHandler(deps) {
6586
+ return async () => {
6587
+ const graceMs = await deps.getGraceMs();
6588
+ if (graceMs <= 0) return;
6589
+ const candidates = await deps.queue.listUnroutableCandidates(deps.batchLimit ?? DEFAULT_BATCH_LIMIT$1);
6590
+ const now = Date.now();
6591
+ for (const job of candidates) {
6592
+ const verdict = classifyUnroutable(job, deps.canRouteLabels);
6593
+ if (!verdict.unroutable) {
6594
+ if (job.unroutableSince !== null) {
6595
+ await deps.queue.clearUnroutableState(job.id);
6596
+ await deps.setRoutingReason(job.runId, job.jobName, null);
6597
+ logger$117.info("Job became routable again; cleared unroutable state", {
6598
+ runId: job.runId,
6599
+ jobName: job.jobName
6600
+ });
6601
+ }
6602
+ continue;
6603
+ }
6604
+ if (job.unroutableSince === null) {
6605
+ await deps.queue.markUnroutableSince(job.id, new Date(now));
6606
+ await deps.setRoutingReason(job.runId, job.jobName, verdict.errorMessage);
6607
+ logger$117.warn("Job is unroutable; starting grace window", {
6608
+ runId: job.runId,
6609
+ jobName: job.jobName,
6610
+ graceMs,
6611
+ reason: verdict.errorMessage
6612
+ });
6613
+ continue;
6614
+ }
6615
+ if (now - job.unroutableSince.getTime() >= graceMs) {
6616
+ if (!await deps.queue.claimUnroutable(job.id)) continue;
6617
+ await deps.terminalize(job);
6618
+ deps.onFastFailed?.();
6619
+ logger$117.warn("Job stayed unroutable for the whole grace window; failed it", {
6620
+ runId: job.runId,
6621
+ jobName: job.jobName,
6622
+ graceMs
6623
+ });
6624
+ }
6625
+ }
6626
+ };
6627
+ }
6628
+ var logger$117, TICK_FLOOR_MS, TICK_CEILING_MS, DEFAULT_BATCH_LIMIT$1, DEFAULT_UNROUTABLE_GRACE_MS;
6629
+ var init_unroutable_probe = __esmMin((() => {
6630
+ init_terminalize_unroutable();
6631
+ logger$117 = createLogger({ prefix: "unroutable-probe" });
6632
+ TICK_FLOOR_MS = 5e3;
6633
+ TICK_CEILING_MS = 3e4;
6634
+ DEFAULT_BATCH_LIMIT$1 = 200;
6635
+ DEFAULT_UNROUTABLE_GRACE_MS = 12e4;
6442
6636
  }));
6443
6637
  //#endregion
6444
6638
  //#region src/metrics/scheduled-jobs.ts
@@ -6670,7 +6864,8 @@ var init_scheduled_job = __esmMin((() => {
6670
6864
  "orphan-secret-cleanup",
6671
6865
  "token-cleanup",
6672
6866
  "cold-store-archive",
6673
- "cold-store-purge"
6867
+ "cold-store-purge",
6868
+ "unroutable-probe"
6674
6869
  ]);
6675
6870
  ACCESS_LOG_ACTION_TICK_FAILURE = "scheduled_job.tick";
6676
6871
  ACCESS_LOG_ACTION_TRIGGER = "scheduled_job.trigger";
@@ -6692,6 +6887,12 @@ function bootstrapOrchestratorScheduledJobs(deps, registrations) {
6692
6887
  intervalMs: registrations.cleanup.intervalMs,
6693
6888
  handler: registrations.cleanup.handler
6694
6889
  }));
6890
+ if (registrations.unroutableProbe) handles.push(registerOrchestratorScheduledJob({
6891
+ ...common,
6892
+ name: "unroutable-probe",
6893
+ intervalMs: registrations.unroutableProbe.intervalMs,
6894
+ handler: registrations.unroutableProbe.handler
6895
+ }));
6695
6896
  if (registrations.orphanSecretCleanup) handles.push(registerOrchestratorScheduledJob({
6696
6897
  ...common,
6697
6898
  name: "orphan-secret-cleanup",
@@ -20910,10 +21111,10 @@ var init_admin_sources = __esmMin((() => {
20910
21111
  //#endregion
20911
21112
  //#region src/db/migrations/001_initial.ts
20912
21113
  var _001_initial_exports = /* @__PURE__ */ __exportAll({
20913
- down: () => down$106,
20914
- up: () => up$106
21114
+ down: () => down$107,
21115
+ up: () => up$107
20915
21116
  });
20916
- async function up$106(db) {
21117
+ async function up$107(db) {
20917
21118
  for (const stmt of DDL_STATEMENTS) await sql.raw(stmt).execute(db);
20918
21119
  await sql`
20919
21120
  INSERT INTO cluster_meta (key, value)
@@ -20935,7 +21136,7 @@ async function up$106(db) {
20935
21136
  * Rollback drops everything created above. Uses CASCADE on table drops to cut
20936
21137
  * through the FK graph without relying on exact topological order.
20937
21138
  */
20938
- async function down$106(db) {
21139
+ async function down$107(db) {
20939
21140
  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);
20940
21141
  for (const table of [
20941
21142
  "workflow_registrations",
@@ -21655,8 +21856,8 @@ var init__001_initial = __esmMin((() => {
21655
21856
  //#endregion
21656
21857
  //#region src/db/migrations/002_config_versions_key_version.ts
21657
21858
  var _002_config_versions_key_version_exports = /* @__PURE__ */ __exportAll({
21658
- down: () => down$105,
21659
- up: () => up$105
21859
+ down: () => down$106,
21860
+ up: () => up$106
21660
21861
  });
21661
21862
  /**
21662
21863
  * Add key_version column to config_versions so that sensitive-field encryption
@@ -21670,13 +21871,13 @@ var _002_config_versions_key_version_exports = /* @__PURE__ */ __exportAll({
21670
21871
  * No index is needed: rotation does a full-table scan; reads are by
21671
21872
  * `version` primary key and never filter on `key_version`.
21672
21873
  */
21673
- async function up$105(db) {
21874
+ async function up$106(db) {
21674
21875
  await sql`
21675
21876
  ALTER TABLE public.config_versions
21676
21877
  ADD COLUMN key_version integer NOT NULL DEFAULT 1
21677
21878
  `.execute(db);
21678
21879
  }
21679
- async function down$105(db) {
21880
+ async function down$106(db) {
21680
21881
  await sql`
21681
21882
  ALTER TABLE public.config_versions
21682
21883
  DROP COLUMN key_version
@@ -21686,8 +21887,8 @@ var init__002_config_versions_key_version = __esmMin((() => {}));
21686
21887
  //#endregion
21687
21888
  //#region src/db/migrations/003_access_log.ts
21688
21889
  var _003_access_log_exports = /* @__PURE__ */ __exportAll({
21689
- down: () => down$104,
21690
- up: () => up$104
21890
+ down: () => down$105,
21891
+ up: () => up$105
21691
21892
  });
21692
21893
  /**
21693
21894
  * Access log: one row per read or orchestrator-admin mutation attributable
@@ -21711,7 +21912,7 @@ var _003_access_log_exports = /* @__PURE__ */ __exportAll({
21711
21912
  * Retention is TTL-based via expires_at; packages/orchestrator/src/queue/
21712
21913
  * cleanup.ts picks up the prune pass.
21713
21914
  */
21714
- async function up$104(db) {
21915
+ async function up$105(db) {
21715
21916
  await sql`
21716
21917
  CREATE TABLE public.access_log (
21717
21918
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
@@ -21749,21 +21950,21 @@ async function up$104(db) {
21749
21950
  ON public.access_log (actor_type, actor_id, created_at DESC)
21750
21951
  `.execute(db);
21751
21952
  }
21752
- async function down$104(db) {
21953
+ async function down$105(db) {
21753
21954
  await sql`DROP TABLE IF EXISTS public.access_log`.execute(db);
21754
21955
  }
21755
21956
  var init__003_access_log = __esmMin((() => {}));
21756
21957
  //#endregion
21757
21958
  //#region src/db/migrations/004_rename_bundle_to_source.ts
21758
21959
  var _004_rename_bundle_to_source_exports = /* @__PURE__ */ __exportAll({
21759
- down: () => down$103,
21760
- up: () => up$103
21960
+ down: () => down$104,
21961
+ up: () => up$104
21761
21962
  });
21762
- async function up$103(db) {
21963
+ async function up$104(db) {
21763
21964
  await db.schema.alterTable("dispatch_queue").renameColumn("bundle_url", "source_tar_url").execute();
21764
21965
  await db.schema.alterTable("dispatch_queue").renameColumn("bundle_hash", "source_tar_hash").execute();
21765
21966
  }
21766
- async function down$103(db) {
21967
+ async function down$104(db) {
21767
21968
  await db.schema.alterTable("dispatch_queue").renameColumn("source_tar_url", "bundle_url").execute();
21768
21969
  await db.schema.alterTable("dispatch_queue").renameColumn("source_tar_hash", "bundle_hash").execute();
21769
21970
  }
@@ -21771,8 +21972,8 @@ var init__004_rename_bundle_to_source = __esmMin((() => {}));
21771
21972
  //#endregion
21772
21973
  //#region src/db/migrations/005_cold_store_chunk_counter.ts
21773
21974
  var _005_cold_store_chunk_counter_exports = /* @__PURE__ */ __exportAll({
21774
- down: () => down$102,
21775
- up: () => up$102
21975
+ down: () => down$103,
21976
+ up: () => up$103
21776
21977
  });
21777
21978
  /**
21778
21979
  * Cold-store chunk counter table.
@@ -21789,7 +21990,7 @@ var _005_cold_store_chunk_counter_exports = /* @__PURE__ */ __exportAll({
21789
21990
  *
21790
21991
  * sections 5 and 8.
21791
21992
  */
21792
- async function up$102(db) {
21993
+ async function up$103(db) {
21793
21994
  await sql`
21794
21995
  CREATE TABLE public.cold_store_chunk_counts (
21795
21996
  db TEXT NOT NULL,
@@ -21807,15 +22008,15 @@ async function up$102(db) {
21807
22008
  ON public.cold_store_chunk_counts (db, table_name)
21808
22009
  `.execute(db);
21809
22010
  }
21810
- async function down$102(db) {
22011
+ async function down$103(db) {
21811
22012
  await sql`DROP TABLE IF EXISTS public.cold_store_chunk_counts`.execute(db);
21812
22013
  }
21813
22014
  var init__005_cold_store_chunk_counter = __esmMin((() => {}));
21814
22015
  //#endregion
21815
22016
  //#region src/db/migrations/006_runs_jobs_steps_archived_at.ts
21816
22017
  var _006_runs_jobs_steps_archived_at_exports = /* @__PURE__ */ __exportAll({
21817
- down: () => down$101,
21818
- up: () => up$101
22018
+ down: () => down$102,
22019
+ up: () => up$102
21819
22020
  });
21820
22021
  /**
21821
22022
  * `execution_runs` / `execution_jobs` / `execution_steps` cold-store
@@ -21851,7 +22052,7 @@ var _006_runs_jobs_steps_archived_at_exports = /* @__PURE__ */ __exportAll({
21851
22052
  * - `idx_execution_jobs_routing_key_created (routing_key, created_at)`
21852
22053
  * - `idx_execution_steps_routing_key_created (routing_key, created_at)`
21853
22054
  */
21854
- async function up$101(db) {
22055
+ async function up$102(db) {
21855
22056
  await sql`
21856
22057
  ALTER TABLE public.execution_runs
21857
22058
  ADD COLUMN archived_at TIMESTAMPTZ NULL,
@@ -21896,7 +22097,7 @@ async function up$101(db) {
21896
22097
  ON public.execution_steps (routing_key, created_at)
21897
22098
  `.execute(db);
21898
22099
  }
21899
- async function down$101(db) {
22100
+ async function down$102(db) {
21900
22101
  await sql`DROP INDEX IF EXISTS public.idx_execution_steps_routing_key_created`.execute(db);
21901
22102
  await sql`
21902
22103
  ALTER TABLE public.execution_steps
@@ -21922,8 +22123,8 @@ var init__006_runs_jobs_steps_archived_at = __esmMin((() => {}));
21922
22123
  //#endregion
21923
22124
  //#region src/db/migrations/007_audit_logs_archived_at.ts
21924
22125
  var _007_audit_logs_archived_at_exports = /* @__PURE__ */ __exportAll({
21925
- down: () => down$100,
21926
- up: () => up$100
22126
+ down: () => down$101,
22127
+ up: () => up$101
21927
22128
  });
21928
22129
  /**
21929
22130
  * `secret_audit_log` and `access_log` cold-store schema additions, plus
@@ -21963,7 +22164,7 @@ var _007_audit_logs_archived_at_exports = /* @__PURE__ */ __exportAll({
21963
22164
  * `down()` would not have meaningful retention bounds. Acceptable for
21964
22165
  * staging.
21965
22166
  */
21966
- async function up$100(db) {
22167
+ async function up$101(db) {
21967
22168
  await sql`
21968
22169
  ALTER TABLE public.secret_audit_log
21969
22170
  ADD COLUMN archived_at TIMESTAMPTZ NULL,
@@ -21984,7 +22185,7 @@ async function up$100(db) {
21984
22185
  DROP COLUMN IF EXISTS expires_at
21985
22186
  `.execute(db);
21986
22187
  }
21987
- async function down$100(db) {
22188
+ async function down$101(db) {
21988
22189
  await sql`
21989
22190
  ALTER TABLE public.access_log
21990
22191
  ADD COLUMN expires_at TIMESTAMPTZ NOT NULL DEFAULT (now() + INTERVAL '90 days')
@@ -22013,8 +22214,8 @@ var init__007_audit_logs_archived_at = __esmMin((() => {}));
22013
22214
  //#endregion
22014
22215
  //#region src/db/migrations/008_event_log_archived_at.ts
22015
22216
  var _008_event_log_archived_at_exports = /* @__PURE__ */ __exportAll({
22016
- down: () => down$99,
22017
- up: () => up$99
22217
+ down: () => down$100,
22218
+ up: () => up$100
22018
22219
  });
22019
22220
  /**
22020
22221
  * `event_log` cold-store schema additions plus removal of the
@@ -22052,7 +22253,7 @@ var _008_event_log_archived_at_exports = /* @__PURE__ */ __exportAll({
22052
22253
  * — best effort; rows inserted between `up()` and a hypothetical
22053
22254
  * `down()` would not have meaningful retention bounds.
22054
22255
  */
22055
- async function up$99(db) {
22256
+ async function up$100(db) {
22056
22257
  await sql`
22057
22258
  ALTER TABLE public.event_log
22058
22259
  ADD COLUMN archived_at TIMESTAMPTZ NULL,
@@ -22068,7 +22269,7 @@ async function up$99(db) {
22068
22269
  DROP COLUMN IF EXISTS expires_at
22069
22270
  `.execute(db);
22070
22271
  }
22071
- async function down$99(db) {
22272
+ async function down$100(db) {
22072
22273
  await sql`
22073
22274
  ALTER TABLE public.event_log
22074
22275
  ADD COLUMN expires_at TIMESTAMPTZ NOT NULL DEFAULT (now() + INTERVAL '30 days')
@@ -22088,8 +22289,8 @@ var init__008_event_log_archived_at = __esmMin((() => {}));
22088
22289
  //#endregion
22089
22290
  //#region src/db/migrations/009_access_log_trigram.ts
22090
22291
  var _009_access_log_trigram_exports = /* @__PURE__ */ __exportAll({
22091
- down: () => down$98,
22092
- up: () => up$98
22292
+ down: () => down$99,
22293
+ up: () => up$99
22093
22294
  });
22094
22295
  /**
22095
22296
  * Trigram (pg_trgm) index on access_log.error_message for the federated
@@ -22102,7 +22303,7 @@ var _009_access_log_trigram_exports = /* @__PURE__ */ __exportAll({
22102
22303
  * EXISTS` are both safe to re-run. No CONCURRENTLY because Kysely runs
22103
22304
  * migrations inside a transaction; the lock is brief on a sampled table.
22104
22305
  */
22105
- async function up$98(db) {
22306
+ async function up$99(db) {
22106
22307
  await sql`CREATE EXTENSION IF NOT EXISTS pg_trgm`.execute(db);
22107
22308
  await sql`
22108
22309
  CREATE INDEX IF NOT EXISTS access_log_error_message_trgm_idx
@@ -22111,15 +22312,15 @@ async function up$98(db) {
22111
22312
  WHERE error_message IS NOT NULL
22112
22313
  `.execute(db);
22113
22314
  }
22114
- async function down$98(db) {
22315
+ async function down$99(db) {
22115
22316
  await sql`DROP INDEX IF EXISTS public.access_log_error_message_trgm_idx`.execute(db);
22116
22317
  }
22117
22318
  var init__009_access_log_trigram = __esmMin((() => {}));
22118
22319
  //#endregion
22119
22320
  //#region src/db/migrations/010_cold_store_chunks.ts
22120
22321
  var _010_cold_store_chunks_exports = /* @__PURE__ */ __exportAll({
22121
- down: () => down$97,
22122
- up: () => up$97
22322
+ down: () => down$98,
22323
+ up: () => up$98
22123
22324
  });
22124
22325
  /**
22125
22326
  * Cold-store chunk index — Phase 2 (cold-store purge).
@@ -22151,7 +22352,7 @@ var _010_cold_store_chunks_exports = /* @__PURE__ */ __exportAll({
22151
22352
  * forever. Adapters that don't opt into per-bucket archival via
22152
22353
  * `coldTtlDays` don't insert here either.
22153
22354
  */
22154
- async function up$97(db) {
22355
+ async function up$98(db) {
22155
22356
  await sql`
22156
22357
  CREATE TABLE public.cold_store_chunks (
22157
22358
  db TEXT NOT NULL,
@@ -22178,15 +22379,15 @@ async function up$97(db) {
22178
22379
  ON public.cold_store_chunks (db, table_name, tenant_id, archived_at DESC)
22179
22380
  `.execute(db);
22180
22381
  }
22181
- async function down$97(db) {
22382
+ async function down$98(db) {
22182
22383
  await sql`DROP TABLE IF EXISTS public.cold_store_chunks`.execute(db);
22183
22384
  }
22184
22385
  var init__010_cold_store_chunks = __esmMin((() => {}));
22185
22386
  //#endregion
22186
22387
  //#region src/db/migrations/011_drop_source_secrets_notify.ts
22187
22388
  var _011_drop_source_secrets_notify_exports = /* @__PURE__ */ __exportAll({
22188
- down: () => down$96,
22189
- up: () => up$96
22389
+ down: () => down$97,
22390
+ up: () => up$97
22190
22391
  });
22191
22392
  /**
22192
22393
  * Drop the `source_secrets_change_trigger` and the
@@ -22205,11 +22406,11 @@ var _011_drop_source_secrets_notify_exports = /* @__PURE__ */ __exportAll({
22205
22406
  * in `001_initial.ts`. They wake up no consumer until the `WebhookSecretManager`
22206
22407
  * is restored, so this migration is safe to roll back.
22207
22408
  */
22208
- async function up$96(db) {
22409
+ async function up$97(db) {
22209
22410
  await sql`DROP TRIGGER IF EXISTS source_secrets_change_trigger ON public.scoped_secrets`.execute(db);
22210
22411
  await sql`DROP FUNCTION IF EXISTS public.notify_source_secrets_change() CASCADE`.execute(db);
22211
22412
  }
22212
- async function down$96(db) {
22413
+ async function down$97(db) {
22213
22414
  await sql`
22214
22415
  CREATE OR REPLACE FUNCTION public.notify_source_secrets_change() RETURNS trigger
22215
22416
  LANGUAGE plpgsql
@@ -22249,8 +22450,8 @@ var init__011_drop_source_secrets_notify = __esmMin((() => {}));
22249
22450
  //#endregion
22250
22451
  //#region src/db/migrations/012_peer_credentials_active_uniq.ts
22251
22452
  var _012_peer_credentials_active_uniq_exports = /* @__PURE__ */ __exportAll({
22252
- down: () => down$95,
22253
- up: () => up$95
22453
+ down: () => down$96,
22454
+ up: () => up$96
22254
22455
  });
22255
22456
  /**
22256
22457
  * Add a partial unique index on `peer_credentials (instance_id) WHERE
@@ -22276,7 +22477,7 @@ var _012_peer_credentials_active_uniq_exports = /* @__PURE__ */ __exportAll({
22276
22477
  * `down()` only drops the index; it does NOT undo the dedupe (there's no
22277
22478
  * safe way to recreate revoked rows, and the dedupe is monotonic).
22278
22479
  */
22279
- async function up$95(db) {
22480
+ async function up$96(db) {
22280
22481
  await sql`
22281
22482
  UPDATE public.peer_credentials
22282
22483
  SET revoked_at = NOW()
@@ -22294,15 +22495,15 @@ async function up$95(db) {
22294
22495
  WHERE revoked_at IS NULL
22295
22496
  `.execute(db);
22296
22497
  }
22297
- async function down$95(db) {
22498
+ async function down$96(db) {
22298
22499
  await sql`DROP INDEX IF EXISTS public.peer_credentials_active_uniq`.execute(db);
22299
22500
  }
22300
22501
  var init__012_peer_credentials_active_uniq = __esmMin((() => {}));
22301
22502
  //#endregion
22302
22503
  //#region src/db/migrations/013_execution_log_bytes.ts
22303
22504
  var _013_execution_log_bytes_exports = /* @__PURE__ */ __exportAll({
22304
- down: () => down$94,
22305
- up: () => up$94
22505
+ down: () => down$95,
22506
+ up: () => up$95
22306
22507
  });
22307
22508
  /**
22308
22509
  * Add `log_bytes BIGINT NOT NULL DEFAULT 0` columns to `execution_runs` and
@@ -22321,7 +22522,7 @@ var _013_execution_log_bytes_exports = /* @__PURE__ */ __exportAll({
22321
22522
  *
22322
22523
  * Idempotent (`ADD COLUMN IF NOT EXISTS`).
22323
22524
  */
22324
- async function up$94(db) {
22525
+ async function up$95(db) {
22325
22526
  await sql`
22326
22527
  ALTER TABLE public.execution_runs
22327
22528
  ADD COLUMN IF NOT EXISTS log_bytes BIGINT NOT NULL DEFAULT 0
@@ -22331,7 +22532,7 @@ async function up$94(db) {
22331
22532
  ADD COLUMN IF NOT EXISTS log_bytes BIGINT NOT NULL DEFAULT 0
22332
22533
  `.execute(db);
22333
22534
  }
22334
- async function down$94(db) {
22535
+ async function down$95(db) {
22335
22536
  await sql`ALTER TABLE public.execution_runs DROP COLUMN IF EXISTS log_bytes`.execute(db);
22336
22537
  await sql`ALTER TABLE public.execution_jobs DROP COLUMN IF EXISTS log_bytes`.execute(db);
22337
22538
  }
@@ -22339,8 +22540,8 @@ var init__013_execution_log_bytes = __esmMin((() => {}));
22339
22540
  //#endregion
22340
22541
  //#region src/db/migrations/014_kici_events_lease_retry.ts
22341
22542
  var _014_kici_events_lease_retry_exports = /* @__PURE__ */ __exportAll({
22342
- down: () => down$93,
22343
- up: () => up$93
22543
+ down: () => down$94,
22544
+ up: () => up$94
22344
22545
  });
22345
22546
  /**
22346
22547
  * Add lease + retry + DLQ columns to `kici_events` so the EventRouter can
@@ -22374,7 +22575,7 @@ var _014_kici_events_lease_retry_exports = /* @__PURE__ */ __exportAll({
22374
22575
  *
22375
22576
  * Idempotent (`ADD COLUMN IF NOT EXISTS` + `CREATE INDEX IF NOT EXISTS`).
22376
22577
  */
22377
- async function up$93(db) {
22578
+ async function up$94(db) {
22378
22579
  await sql`
22379
22580
  ALTER TABLE public.kici_events
22380
22581
  ADD COLUMN IF NOT EXISTS claimed_at TIMESTAMPTZ,
@@ -22405,7 +22606,7 @@ async function up$93(db) {
22405
22606
  WHERE dlq_at IS NOT NULL
22406
22607
  `.execute(db);
22407
22608
  }
22408
- async function down$93(db) {
22609
+ async function down$94(db) {
22409
22610
  await sql`DROP INDEX IF EXISTS public.idx_kici_events_dlq`.execute(db);
22410
22611
  await sql`DROP INDEX IF EXISTS public.idx_kici_events_lease_expired`.execute(db);
22411
22612
  await sql`DROP INDEX IF EXISTS public.idx_kici_events_retry_due`.execute(db);
@@ -22424,8 +22625,8 @@ var init__014_kici_events_lease_retry = __esmMin((() => {}));
22424
22625
  //#endregion
22425
22626
  //#region src/db/migrations/015_org_settings_customer_scoped.ts
22426
22627
  var _015_org_settings_customer_scoped_exports = /* @__PURE__ */ __exportAll({
22427
- down: () => down$92,
22428
- up: () => up$92
22628
+ down: () => down$93,
22629
+ up: () => up$93
22429
22630
  });
22430
22631
  /**
22431
22632
  * Org-scope `org_settings` and qualify each glob entry by source.
@@ -22453,7 +22654,7 @@ var _015_org_settings_customer_scoped_exports = /* @__PURE__ */ __exportAll({
22453
22654
  * Idempotent: a re-run on an already-migrated DB sees `customer_id` exists
22454
22655
  * and the list columns are already jsonb, so it is a no-op.
22455
22656
  */
22456
- async function up$92(db) {
22657
+ async function up$93(db) {
22457
22658
  if ((await sql`
22458
22659
  SELECT EXISTS (
22459
22660
  SELECT 1 FROM information_schema.columns
@@ -22578,7 +22779,7 @@ async function up$92(db) {
22578
22779
  await sql`DROP TABLE _org_settings_merged`.execute(db);
22579
22780
  await sql`DROP TABLE _org_settings_stage`.execute(db);
22580
22781
  }
22581
- async function down$92(db) {
22782
+ async function down$93(db) {
22582
22783
  if (!(await sql`
22583
22784
  SELECT EXISTS (
22584
22785
  SELECT 1 FROM information_schema.columns
@@ -22604,8 +22805,8 @@ var init__015_org_settings_customer_scoped = __esmMin((() => {}));
22604
22805
  //#endregion
22605
22806
  //#region src/db/migrations/016_org_settings_allow_http_npm.ts
22606
22807
  var _016_org_settings_allow_http_npm_exports = /* @__PURE__ */ __exportAll({
22607
- down: () => down$91,
22608
- up: () => up$91
22808
+ down: () => down$92,
22809
+ up: () => up$92
22609
22810
  });
22610
22811
  /**
22611
22812
  * Add `org_settings.allow_http_npm_registries boolean NOT NULL DEFAULT false`.
@@ -22618,7 +22819,7 @@ var _016_org_settings_allow_http_npm_exports = /* @__PURE__ */ __exportAll({
22618
22819
  *
22619
22820
  * Idempotent: a re-run on a DB that already has the column is a no-op.
22620
22821
  */
22621
- async function up$91(db) {
22822
+ async function up$92(db) {
22622
22823
  if ((await sql`
22623
22824
  SELECT EXISTS (
22624
22825
  SELECT 1 FROM information_schema.columns
@@ -22632,7 +22833,7 @@ async function up$91(db) {
22632
22833
  ADD COLUMN allow_http_npm_registries boolean NOT NULL DEFAULT false
22633
22834
  `.execute(db);
22634
22835
  }
22635
- async function down$91(db) {
22836
+ async function down$92(db) {
22636
22837
  await sql`
22637
22838
  ALTER TABLE public.org_settings DROP COLUMN IF EXISTS allow_http_npm_registries
22638
22839
  `.execute(db);
@@ -22641,13 +22842,13 @@ var init__016_org_settings_allow_http_npm = __esmMin((() => {}));
22641
22842
  //#endregion
22642
22843
  //#region src/db/migrations/017_org_id_widen.ts
22643
22844
  var _017_org_id_widen_exports = /* @__PURE__ */ __exportAll({
22644
- down: () => down$90,
22645
- up: () => up$90
22845
+ down: () => down$91,
22846
+ up: () => up$91
22646
22847
  });
22647
- async function up$90(db) {
22848
+ async function up$91(db) {
22648
22849
  for (const table of ORG_ID_TABLES$1) await sql.raw(`ALTER TABLE public.${table} ALTER COLUMN org_id TYPE varchar(16)`).execute(db);
22649
22850
  }
22650
- async function down$90(db) {
22851
+ async function down$91(db) {
22651
22852
  for (const table of ORG_ID_TABLES$1) await sql.raw(`ALTER TABLE public.${table} ALTER COLUMN org_id TYPE varchar(12)`).execute(db);
22652
22853
  }
22653
22854
  var ORG_ID_TABLES$1;
@@ -22666,14 +22867,14 @@ var init__017_org_id_widen = __esmMin((() => {
22666
22867
  //#endregion
22667
22868
  //#region src/db/migrations/018_org_id_prefix_backfill.ts
22668
22869
  var _018_org_id_prefix_backfill_exports = /* @__PURE__ */ __exportAll({
22669
- down: () => down$89,
22670
- up: () => up$89
22870
+ down: () => down$90,
22871
+ up: () => up$90
22671
22872
  });
22672
- async function up$89(db) {
22873
+ async function up$90(db) {
22673
22874
  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);
22674
22875
  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);
22675
22876
  }
22676
- async function down$89(db) {
22877
+ async function down$90(db) {
22677
22878
  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);
22678
22879
  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);
22679
22880
  }
@@ -22699,8 +22900,8 @@ var init__018_org_id_prefix_backfill = __esmMin((() => {
22699
22900
  //#endregion
22700
22901
  //#region src/db/migrations/019_generic_sources_change_notify.ts
22701
22902
  var _019_generic_sources_change_notify_exports = /* @__PURE__ */ __exportAll({
22702
- down: () => down$88,
22703
- up: () => up$88
22903
+ down: () => down$89,
22904
+ up: () => up$89
22704
22905
  });
22705
22906
  /**
22706
22907
  * Add a Postgres trigger on `generic_webhook_sources` that emits
@@ -22723,7 +22924,7 @@ var _019_generic_sources_change_notify_exports = /* @__PURE__ */ __exportAll({
22723
22924
  * (`notify_sources_change()` + `sources_change_trigger`, defined in
22724
22925
  * `001_initial.ts`).
22725
22926
  */
22726
- async function up$88(db) {
22927
+ async function up$89(db) {
22727
22928
  await sql`
22728
22929
  CREATE FUNCTION public.notify_generic_sources_change() RETURNS trigger
22729
22930
  LANGUAGE plpgsql
@@ -22744,7 +22945,7 @@ async function up$88(db) {
22744
22945
  FOR EACH ROW EXECUTE FUNCTION public.notify_generic_sources_change()
22745
22946
  `.execute(db);
22746
22947
  }
22747
- async function down$88(db) {
22948
+ async function down$89(db) {
22748
22949
  await sql`DROP TRIGGER IF EXISTS generic_sources_change_trigger ON public.generic_webhook_sources`.execute(db);
22749
22950
  await sql`DROP FUNCTION IF EXISTS public.notify_generic_sources_change()`.execute(db);
22750
22951
  }
@@ -22752,8 +22953,8 @@ var init__019_generic_sources_change_notify = __esmMin((() => {}));
22752
22953
  //#endregion
22753
22954
  //#region src/db/migrations/020_org_settings_dashboard_write_policy.ts
22754
22955
  var _020_org_settings_dashboard_write_policy_exports = /* @__PURE__ */ __exportAll({
22755
- down: () => down$87,
22756
- up: () => up$87
22956
+ down: () => down$88,
22957
+ up: () => up$88
22757
22958
  });
22758
22959
  /**
22759
22960
  * Add `org_settings.dashboard_write_policy jsonb NOT NULL DEFAULT '{}'`.
@@ -22768,7 +22969,7 @@ var _020_org_settings_dashboard_write_policy_exports = /* @__PURE__ */ __exportA
22768
22969
  *
22769
22970
  * Idempotent: a re-run on a DB that already has the column is a no-op.
22770
22971
  */
22771
- async function up$87(db) {
22972
+ async function up$88(db) {
22772
22973
  if ((await sql`
22773
22974
  SELECT EXISTS (
22774
22975
  SELECT 1 FROM information_schema.columns
@@ -22782,7 +22983,7 @@ async function up$87(db) {
22782
22983
  ADD COLUMN dashboard_write_policy jsonb NOT NULL DEFAULT '{}'::jsonb
22783
22984
  `.execute(db);
22784
22985
  }
22785
- async function down$87(db) {
22986
+ async function down$88(db) {
22786
22987
  await sql`
22787
22988
  ALTER TABLE public.org_settings DROP COLUMN IF EXISTS dashboard_write_policy
22788
22989
  `.execute(db);
@@ -22791,8 +22992,8 @@ var init__020_org_settings_dashboard_write_policy = __esmMin((() => {}));
22791
22992
  //#endregion
22792
22993
  //#region src/db/migrations/021_check_run_tracking.ts
22793
22994
  var _021_check_run_tracking_exports = /* @__PURE__ */ __exportAll({
22794
- down: () => down$86,
22795
- up: () => up$86
22995
+ down: () => down$87,
22996
+ up: () => up$87
22796
22997
  });
22797
22998
  /**
22798
22999
  * Add `check_run_tracking` table for HA-safe check-run state persistence.
@@ -22816,7 +23017,7 @@ var _021_check_run_tracking_exports = /* @__PURE__ */ __exportAll({
22816
23017
  *
22817
23018
  * Idempotent: a re-run on a DB that already has the table is a no-op.
22818
23019
  */
22819
- async function up$86(db) {
23020
+ async function up$87(db) {
22820
23021
  if ((await sql`
22821
23022
  SELECT EXISTS (
22822
23023
  SELECT 1 FROM information_schema.tables
@@ -22847,15 +23048,15 @@ async function up$86(db) {
22847
23048
  WHERE run_id IS NOT NULL
22848
23049
  `.execute(db);
22849
23050
  }
22850
- async function down$86(db) {
23051
+ async function down$87(db) {
22851
23052
  await sql`DROP TABLE IF EXISTS public.check_run_tracking`.execute(db);
22852
23053
  }
22853
23054
  var init__021_check_run_tracking = __esmMin((() => {}));
22854
23055
  //#endregion
22855
23056
  //#region src/db/migrations/022_scaler_manager_state.ts
22856
23057
  var _022_scaler_manager_state_exports = /* @__PURE__ */ __exportAll({
22857
- down: () => down$85,
22858
- up: () => up$85
23058
+ down: () => down$86,
23059
+ up: () => up$86
22859
23060
  });
22860
23061
  /**
22861
23062
  * Add three tables persisting `ScalerManager` per-coord state:
@@ -22882,7 +23083,7 @@ var _022_scaler_manager_state_exports = /* @__PURE__ */ __exportAll({
22882
23083
  * Idempotent: a re-run on a DB that already has any of these tables
22883
23084
  * leaves the existing one alone.
22884
23085
  */
22885
- async function up$85(db) {
23086
+ async function up$86(db) {
22886
23087
  const tableExists = async (name) => {
22887
23088
  return (await sql`
22888
23089
  SELECT EXISTS (
@@ -22932,7 +23133,7 @@ async function up$85(db) {
22932
23133
  `.execute(db);
22933
23134
  }
22934
23135
  }
22935
- async function down$85(db) {
23136
+ async function down$86(db) {
22936
23137
  await sql`DROP TABLE IF EXISTS public.scaler_reservations`.execute(db);
22937
23138
  await sql`DROP TABLE IF EXISTS public.scaler_agent_jobs`.execute(db);
22938
23139
  await sql`DROP TABLE IF EXISTS public.scaler_spawning_agents`.execute(db);
@@ -22941,8 +23142,8 @@ var init__022_scaler_manager_state = __esmMin((() => {}));
22941
23142
  //#endregion
22942
23143
  //#region src/db/migrations/023_dispatch_queue_recovery_deadline.ts
22943
23144
  var _023_dispatch_queue_recovery_deadline_exports = /* @__PURE__ */ __exportAll({
22944
- down: () => down$84,
22945
- up: () => up$84
23145
+ down: () => down$85,
23146
+ up: () => up$85
22946
23147
  });
22947
23148
  /**
22948
23149
  * Add `dispatch_queue.recovery_deadline TIMESTAMPTZ` and
@@ -22966,7 +23167,7 @@ var _023_dispatch_queue_recovery_deadline_exports = /* @__PURE__ */ __exportAll(
22966
23167
  * Idempotent: re-running on a DB that already has either column is a
22967
23168
  * no-op.
22968
23169
  */
22969
- async function up$84(db) {
23170
+ async function up$85(db) {
22970
23171
  const colExists = async (name) => {
22971
23172
  return (await sql`
22972
23173
  SELECT EXISTS (
@@ -22991,7 +23192,7 @@ async function up$84(db) {
22991
23192
  WHERE recovery_deadline IS NOT NULL
22992
23193
  `.execute(db);
22993
23194
  }
22994
- async function down$84(db) {
23195
+ async function down$85(db) {
22995
23196
  await sql`DROP INDEX IF EXISTS public.idx_dispatch_queue_recovery_deadline`.execute(db);
22996
23197
  await sql`
22997
23198
  ALTER TABLE public.dispatch_queue DROP COLUMN IF EXISTS recovery_agent_id
@@ -23004,8 +23205,8 @@ var init__023_dispatch_queue_recovery_deadline = __esmMin((() => {}));
23004
23205
  //#endregion
23005
23206
  //#region src/db/migrations/024_dispatch_queue_provisioning_error.ts
23006
23207
  var _024_dispatch_queue_provisioning_error_exports = /* @__PURE__ */ __exportAll({
23007
- down: () => down$83,
23008
- up: () => up$83
23208
+ down: () => down$84,
23209
+ up: () => up$84
23009
23210
  });
23010
23211
  /**
23011
23212
  * Add `dispatch_queue.last_provisioning_error TEXT` recording the most
@@ -23021,7 +23222,7 @@ var _024_dispatch_queue_provisioning_error_exports = /* @__PURE__ */ __exportAll
23021
23222
  *
23022
23223
  * Idempotent: re-running on a DB that already has the column is a no-op.
23023
23224
  */
23024
- async function up$83(db) {
23225
+ async function up$84(db) {
23025
23226
  const colExists = async (name) => {
23026
23227
  return (await sql`
23027
23228
  SELECT EXISTS (
@@ -23037,7 +23238,7 @@ async function up$83(db) {
23037
23238
  ADD COLUMN last_provisioning_error TEXT
23038
23239
  `.execute(db);
23039
23240
  }
23040
- async function down$83(db) {
23241
+ async function down$84(db) {
23041
23242
  await sql`
23042
23243
  ALTER TABLE public.dispatch_queue DROP COLUMN IF EXISTS last_provisioning_error
23043
23244
  `.execute(db);
@@ -23046,8 +23247,8 @@ var init__024_dispatch_queue_provisioning_error = __esmMin((() => {}));
23046
23247
  //#endregion
23047
23248
  //#region src/db/migrations/025_init_failure.ts
23048
23249
  var _025_init_failure_exports = /* @__PURE__ */ __exportAll({
23049
- down: () => down$82,
23050
- up: () => up$82
23250
+ down: () => down$83,
23251
+ up: () => up$83
23051
23252
  });
23052
23253
  /**
23053
23254
  * Add `init_failure jsonb` columns to `execution_runs` and `execution_jobs`.
@@ -23061,7 +23262,7 @@ var _025_init_failure_exports = /* @__PURE__ */ __exportAll({
23061
23262
  * Idempotent: re-running on a DB that already has either column is a no-op
23062
23263
  * for that column.
23063
23264
  */
23064
- async function up$82(db) {
23265
+ async function up$83(db) {
23065
23266
  const colExists = async (table, name) => {
23066
23267
  return (await sql`
23067
23268
  SELECT EXISTS (
@@ -23081,7 +23282,7 @@ async function up$82(db) {
23081
23282
  ADD COLUMN init_failure JSONB DEFAULT NULL
23082
23283
  `.execute(db);
23083
23284
  }
23084
- async function down$82(db) {
23285
+ async function down$83(db) {
23085
23286
  await sql`
23086
23287
  ALTER TABLE public.execution_jobs DROP COLUMN IF EXISTS init_failure
23087
23288
  `.execute(db);
@@ -23093,8 +23294,8 @@ var init__025_init_failure = __esmMin((() => {}));
23093
23294
  //#endregion
23094
23295
  //#region src/db/migrations/026_event_log_lockfile_corrupt.ts
23095
23296
  var _026_event_log_lockfile_corrupt_exports = /* @__PURE__ */ __exportAll({
23096
- down: () => down$81,
23097
- up: () => up$81
23297
+ down: () => down$82,
23298
+ up: () => up$82
23098
23299
  });
23099
23300
  /**
23100
23301
  * Extend the event_log.status CHECK constraint with 'lockfile_corrupt' so the
@@ -23103,7 +23304,7 @@ var _026_event_log_lockfile_corrupt_exports = /* @__PURE__ */ __exportAll({
23103
23304
  *
23104
23305
  * Idempotent: the DROP ... IF EXISTS / re-ADD pair re-runs cleanly.
23105
23306
  */
23106
- async function up$81(db) {
23307
+ async function up$82(db) {
23107
23308
  await sql`ALTER TABLE event_log DROP CONSTRAINT IF EXISTS event_log_status_check`.execute(db);
23108
23309
  await sql`
23109
23310
  ALTER TABLE event_log ADD CONSTRAINT event_log_status_check
@@ -23113,7 +23314,7 @@ async function up$81(db) {
23113
23314
  ])))
23114
23315
  `.execute(db);
23115
23316
  }
23116
- async function down$81(db) {
23317
+ async function down$82(db) {
23117
23318
  await sql`ALTER TABLE event_log DROP CONSTRAINT IF EXISTS event_log_status_check`.execute(db);
23118
23319
  await sql`
23119
23320
  ALTER TABLE event_log ADD CONSTRAINT event_log_status_check
@@ -23127,8 +23328,8 @@ var init__026_event_log_lockfile_corrupt = __esmMin((() => {}));
23127
23328
  //#endregion
23128
23329
  //#region src/db/migrations/027_workflow_timeout.ts
23129
23330
  var _027_workflow_timeout_exports = /* @__PURE__ */ __exportAll({
23130
- down: () => down$80,
23131
- up: () => up$80
23331
+ down: () => down$81,
23332
+ up: () => up$81
23132
23333
  });
23133
23334
  /**
23134
23335
  * Add `workflow_timeout_ms integer` to `execution_runs`.
@@ -23146,13 +23347,13 @@ var _027_workflow_timeout_exports = /* @__PURE__ */ __exportAll({
23146
23347
  *
23147
23348
  * Idempotent: re-running on a DB that already has the column is a no-op.
23148
23349
  */
23149
- async function up$80(db) {
23350
+ async function up$81(db) {
23150
23351
  await sql`
23151
23352
  ALTER TABLE public.execution_runs
23152
23353
  ADD COLUMN IF NOT EXISTS workflow_timeout_ms INTEGER DEFAULT NULL
23153
23354
  `.execute(db);
23154
23355
  }
23155
- async function down$80(db) {
23356
+ async function down$81(db) {
23156
23357
  await sql`
23157
23358
  ALTER TABLE public.execution_runs DROP COLUMN IF EXISTS workflow_timeout_ms
23158
23359
  `.execute(db);
@@ -23161,8 +23362,8 @@ var init__027_workflow_timeout = __esmMin((() => {}));
23161
23362
  //#endregion
23162
23363
  //#region src/db/migrations/028_org_settings_user_cache.ts
23163
23364
  var _028_org_settings_user_cache_exports = /* @__PURE__ */ __exportAll({
23164
- down: () => down$79,
23165
- up: () => up$79
23365
+ down: () => down$80,
23366
+ up: () => up$80
23166
23367
  });
23167
23368
  /**
23168
23369
  * Add `org_settings.user_cache_quota_bytes bigint` and
@@ -23181,7 +23382,7 @@ var _028_org_settings_user_cache_exports = /* @__PURE__ */ __exportAll({
23181
23382
  *
23182
23383
  * Idempotent: a re-run on a DB that already has either column skips it.
23183
23384
  */
23184
- async function columnExists$5(db, column) {
23385
+ async function columnExists$6(db, column) {
23185
23386
  return (await sql`
23186
23387
  SELECT EXISTS (
23187
23388
  SELECT 1 FROM information_schema.columns
@@ -23191,17 +23392,17 @@ async function columnExists$5(db, column) {
23191
23392
  ) AS exists
23192
23393
  `.execute(db)).rows[0]?.exists ?? false;
23193
23394
  }
23194
- async function up$79(db) {
23195
- if (!await columnExists$5(db, "user_cache_quota_bytes")) await sql`
23395
+ async function up$80(db) {
23396
+ if (!await columnExists$6(db, "user_cache_quota_bytes")) await sql`
23196
23397
  ALTER TABLE public.org_settings
23197
23398
  ADD COLUMN user_cache_quota_bytes bigint
23198
23399
  `.execute(db);
23199
- if (!await columnExists$5(db, "user_cache_ttl_ms")) await sql`
23400
+ if (!await columnExists$6(db, "user_cache_ttl_ms")) await sql`
23200
23401
  ALTER TABLE public.org_settings
23201
23402
  ADD COLUMN user_cache_ttl_ms bigint
23202
23403
  `.execute(db);
23203
23404
  }
23204
- async function down$79(db) {
23405
+ async function down$80(db) {
23205
23406
  await sql`
23206
23407
  ALTER TABLE public.org_settings DROP COLUMN IF EXISTS user_cache_quota_bytes
23207
23408
  `.execute(db);
@@ -23213,8 +23414,8 @@ var init__028_org_settings_user_cache = __esmMin((() => {}));
23213
23414
  //#endregion
23214
23415
  //#region src/db/migrations/029_dispatch_queue_attempts.ts
23215
23416
  var _029_dispatch_queue_attempts_exports = /* @__PURE__ */ __exportAll({
23216
- down: () => down$78,
23217
- up: () => up$78
23417
+ down: () => down$79,
23418
+ up: () => up$79
23218
23419
  });
23219
23420
  /**
23220
23421
  * Add `dispatch_queue.dispatch_attempts INT NOT NULL DEFAULT 0`.
@@ -23228,7 +23429,7 @@ var _029_dispatch_queue_attempts_exports = /* @__PURE__ */ __exportAll({
23228
23429
  *
23229
23430
  * Idempotent: re-running on a DB that already has the column is a no-op.
23230
23431
  */
23231
- async function up$78(db) {
23432
+ async function up$79(db) {
23232
23433
  if (!((await sql`
23233
23434
  SELECT EXISTS (
23234
23435
  SELECT 1 FROM information_schema.columns
@@ -23241,7 +23442,7 @@ async function up$78(db) {
23241
23442
  ADD COLUMN dispatch_attempts INT NOT NULL DEFAULT 0
23242
23443
  `.execute(db);
23243
23444
  }
23244
- async function down$78(db) {
23445
+ async function down$79(db) {
23245
23446
  await sql`
23246
23447
  ALTER TABLE public.dispatch_queue DROP COLUMN IF EXISTS dispatch_attempts
23247
23448
  `.execute(db);
@@ -23250,8 +23451,8 @@ var init__029_dispatch_queue_attempts = __esmMin((() => {}));
23250
23451
  //#endregion
23251
23452
  //#region src/db/migrations/030_held_runs_env_set_null.ts
23252
23453
  var _030_held_runs_env_set_null_exports = /* @__PURE__ */ __exportAll({
23253
- down: () => down$77,
23254
- up: () => up$77
23454
+ down: () => down$78,
23455
+ up: () => up$78
23255
23456
  });
23256
23457
  /**
23257
23458
  * held_runs.environment_id becomes nullable with ON DELETE SET NULL so
@@ -23262,14 +23463,14 @@ var _030_held_runs_env_set_null_exports = /* @__PURE__ */ __exportAll({
23262
23463
  * Idempotent: dropping the NOT NULL and the constraint are both no-ops on a
23263
23464
  * re-run, and the constraint is re-created with the SET NULL action.
23264
23465
  */
23265
- async function up$77(db) {
23466
+ async function up$78(db) {
23266
23467
  await sql`ALTER TABLE public.held_runs ALTER COLUMN environment_id DROP NOT NULL`.execute(db);
23267
23468
  await sql`ALTER TABLE public.held_runs DROP CONSTRAINT IF EXISTS held_runs_environment_id_fkey`.execute(db);
23268
23469
  await sql`ALTER TABLE public.held_runs
23269
23470
  ADD CONSTRAINT held_runs_environment_id_fkey
23270
23471
  FOREIGN KEY (environment_id) REFERENCES public.environments(id) ON DELETE SET NULL`.execute(db);
23271
23472
  }
23272
- async function down$77(db) {
23473
+ async function down$78(db) {
23273
23474
  await sql`ALTER TABLE public.held_runs DROP CONSTRAINT IF EXISTS held_runs_environment_id_fkey`.execute(db);
23274
23475
  await sql`ALTER TABLE public.held_runs
23275
23476
  ADD CONSTRAINT held_runs_environment_id_fkey
@@ -23280,8 +23481,8 @@ var init__030_held_runs_env_set_null = __esmMin((() => {}));
23280
23481
  //#endregion
23281
23482
  //#region src/db/migrations/031_dispatch_queue_ack_deadline.ts
23282
23483
  var _031_dispatch_queue_ack_deadline_exports = /* @__PURE__ */ __exportAll({
23283
- down: () => down$76,
23284
- up: () => up$76
23484
+ down: () => down$77,
23485
+ up: () => up$77
23285
23486
  });
23286
23487
  /**
23287
23488
  * Add `dispatch_queue.ack_deadline TIMESTAMPTZ` and
@@ -23298,7 +23499,7 @@ var _031_dispatch_queue_ack_deadline_exports = /* @__PURE__ */ __exportAll({
23298
23499
  *
23299
23500
  * Idempotent: re-running on a DB that already has either column is a no-op.
23300
23501
  */
23301
- async function up$76(db) {
23502
+ async function up$77(db) {
23302
23503
  const colExists = async (name) => {
23303
23504
  return (await sql`
23304
23505
  SELECT EXISTS (
@@ -23323,7 +23524,7 @@ async function up$76(db) {
23323
23524
  WHERE ack_deadline IS NOT NULL
23324
23525
  `.execute(db);
23325
23526
  }
23326
- async function down$76(db) {
23527
+ async function down$77(db) {
23327
23528
  await sql`DROP INDEX IF EXISTS public.idx_dispatch_queue_ack_deadline`.execute(db);
23328
23529
  await sql`ALTER TABLE public.dispatch_queue DROP COLUMN IF EXISTS ack_agent_id`.execute(db);
23329
23530
  await sql`ALTER TABLE public.dispatch_queue DROP COLUMN IF EXISTS ack_deadline`.execute(db);
@@ -23332,8 +23533,8 @@ var init__031_dispatch_queue_ack_deadline = __esmMin((() => {}));
23332
23533
  //#endregion
23333
23534
  //#region src/db/migrations/032_org_settings_dispatch_ack_timeout.ts
23334
23535
  var _032_org_settings_dispatch_ack_timeout_exports = /* @__PURE__ */ __exportAll({
23335
- down: () => down$75,
23336
- up: () => up$75
23536
+ down: () => down$76,
23537
+ up: () => up$76
23337
23538
  });
23338
23539
  /**
23339
23540
  * Add `org_settings.dispatch_ack_timeout_ms BIGINT` (nullable).
@@ -23345,7 +23546,7 @@ var _032_org_settings_dispatch_ack_timeout_exports = /* @__PURE__ */ __exportAll
23345
23546
  *
23346
23547
  * Idempotent: a re-run on a DB that already has the column is a no-op.
23347
23548
  */
23348
- async function up$75(db) {
23549
+ async function up$76(db) {
23349
23550
  if ((await sql`
23350
23551
  SELECT EXISTS (
23351
23552
  SELECT 1 FROM information_schema.columns
@@ -23359,7 +23560,7 @@ async function up$75(db) {
23359
23560
  ADD COLUMN dispatch_ack_timeout_ms BIGINT
23360
23561
  `.execute(db);
23361
23562
  }
23362
- async function down$75(db) {
23563
+ async function down$76(db) {
23363
23564
  await sql`
23364
23565
  ALTER TABLE public.org_settings DROP COLUMN IF EXISTS dispatch_ack_timeout_ms
23365
23566
  `.execute(db);
@@ -23368,8 +23569,8 @@ var init__032_org_settings_dispatch_ack_timeout = __esmMin((() => {}));
23368
23569
  //#endregion
23369
23570
  //#region src/db/migrations/033_org_settings_approval.ts
23370
23571
  var _033_org_settings_approval_exports = /* @__PURE__ */ __exportAll({
23371
- down: () => down$74,
23372
- up: () => up$74
23572
+ down: () => down$75,
23573
+ up: () => up$75
23373
23574
  });
23374
23575
  /**
23375
23576
  * Add the two approval-policy columns to `org_settings`:
@@ -23386,7 +23587,7 @@ var _033_org_settings_approval_exports = /* @__PURE__ */ __exportAll({
23386
23587
  * and the orchestrator admin route. Idempotent: a re-run on a DB that already
23387
23588
  * has the columns is a no-op (each column is guarded independently).
23388
23589
  */
23389
- async function up$74(db) {
23590
+ async function up$75(db) {
23390
23591
  const colExists = async (column) => {
23391
23592
  return (await sql`
23392
23593
  SELECT EXISTS (
@@ -23406,7 +23607,7 @@ async function up$74(db) {
23406
23607
  ADD COLUMN allow_self_approval BOOLEAN NOT NULL DEFAULT true
23407
23608
  `.execute(db);
23408
23609
  }
23409
- async function down$74(db) {
23610
+ async function down$75(db) {
23410
23611
  await sql`
23411
23612
  ALTER TABLE public.org_settings DROP COLUMN IF EXISTS approval_expiry_seconds
23412
23613
  `.execute(db);
@@ -23418,8 +23619,8 @@ var init__033_org_settings_approval = __esmMin((() => {}));
23418
23619
  //#endregion
23419
23620
  //#region src/db/migrations/034_held_runs_generalize.ts
23420
23621
  var _034_held_runs_generalize_exports = /* @__PURE__ */ __exportAll({
23421
- down: () => down$73,
23422
- up: () => up$73
23622
+ down: () => down$74,
23623
+ up: () => up$74
23423
23624
  });
23424
23625
  /**
23425
23626
  * Generalize `held_runs` from an environment-only hold into the unified
@@ -23441,7 +23642,7 @@ var _034_held_runs_generalize_exports = /* @__PURE__ */ __exportAll({
23441
23642
  * New `held_run_approvals` table: one row per approver decision, FK to
23442
23643
  * `held_runs.id` (uuid) with ON DELETE CASCADE.
23443
23644
  */
23444
- async function up$73(db) {
23645
+ async function up$74(db) {
23445
23646
  const colExists = async (column) => {
23446
23647
  return (await sql`
23447
23648
  SELECT EXISTS (
@@ -23474,7 +23675,7 @@ async function up$73(db) {
23474
23675
  ON public.held_run_approvals USING btree (held_run_id)
23475
23676
  `.execute(db);
23476
23677
  }
23477
- async function down$73(db) {
23678
+ async function down$74(db) {
23478
23679
  await sql`DROP TABLE IF EXISTS public.held_run_approvals`.execute(db);
23479
23680
  await sql`ALTER TABLE public.held_runs DROP COLUMN IF EXISTS approval_requirement`.execute(db);
23480
23681
  await sql`ALTER TABLE public.held_runs DROP COLUMN IF EXISTS trigger_source`.execute(db);
@@ -23485,8 +23686,8 @@ var init__034_held_runs_generalize = __esmMin((() => {}));
23485
23686
  //#endregion
23486
23687
  //#region src/db/migrations/035_pending_workflow_contexts.ts
23487
23688
  var _035_pending_workflow_contexts_exports = /* @__PURE__ */ __exportAll({
23488
- down: () => down$72,
23489
- up: () => up$72
23689
+ down: () => down$73,
23690
+ up: () => up$73
23490
23691
  });
23491
23692
  /**
23492
23693
  * Pending workflow dispatch context — backs resume of a workflow whose install
@@ -23495,7 +23696,7 @@ var _035_pending_workflow_contexts_exports = /* @__PURE__ */ __exportAll({
23495
23696
  * wait-timer expiry, concurrency slot free). The row is deleted once the resume
23496
23697
  * dispatch has been kicked off.
23497
23698
  */
23498
- async function up$72(db) {
23699
+ async function up$73(db) {
23499
23700
  await sql`
23500
23701
  CREATE TABLE IF NOT EXISTS public.pending_workflow_contexts (
23501
23702
  run_id text PRIMARY KEY,
@@ -23505,15 +23706,15 @@ async function up$72(db) {
23505
23706
  )
23506
23707
  `.execute(db);
23507
23708
  }
23508
- async function down$72(db) {
23709
+ async function down$73(db) {
23509
23710
  await sql`DROP TABLE IF EXISTS public.pending_workflow_contexts`.execute(db);
23510
23711
  }
23511
23712
  var init__035_pending_workflow_contexts = __esmMin((() => {}));
23512
23713
  //#endregion
23513
23714
  //#region src/db/migrations/036_attestations.ts
23514
23715
  var _036_attestations_exports = /* @__PURE__ */ __exportAll({
23515
- down: () => down$71,
23516
- up: () => up$71
23716
+ down: () => down$72,
23717
+ up: () => up$72
23517
23718
  });
23518
23719
  /**
23519
23720
  * Add the `attestations` table for build-provenance bundles.
@@ -23526,7 +23727,7 @@ var _036_attestations_exports = /* @__PURE__ */ __exportAll({
23526
23727
  *
23527
23728
  * Idempotent: a re-run on a DB that already has the table is a no-op.
23528
23729
  */
23529
- async function up$71(db) {
23730
+ async function up$72(db) {
23530
23731
  if ((await sql`
23531
23732
  SELECT EXISTS (
23532
23733
  SELECT 1 FROM information_schema.tables
@@ -23552,15 +23753,15 @@ async function up$71(db) {
23552
23753
  ON public.attestations (run_id, job_id)
23553
23754
  `.execute(db);
23554
23755
  }
23555
- async function down$71(db) {
23756
+ async function down$72(db) {
23556
23757
  await sql`DROP TABLE IF EXISTS public.attestations`.execute(db);
23557
23758
  }
23558
23759
  var init__036_attestations = __esmMin((() => {}));
23559
23760
  //#endregion
23560
23761
  //#region src/db/migrations/037_generic_sources_provider_type_local.ts
23561
23762
  var _037_generic_sources_provider_type_local_exports = /* @__PURE__ */ __exportAll({
23562
- down: () => down$70,
23563
- up: () => up$70
23763
+ down: () => down$71,
23764
+ up: () => up$71
23564
23765
  });
23565
23766
  /**
23566
23767
  * Replace the `generic_webhook_sources.provider_type` CHECK constraint so it
@@ -23577,7 +23778,7 @@ var _037_generic_sources_provider_type_local_exports = /* @__PURE__ */ __exportA
23577
23778
  * Idempotent: the constraint is dropped IF EXISTS and recreated; the data
23578
23779
  * backfill is a plain UPDATE that is a no-op once no `'internal'` rows remain.
23579
23780
  */
23580
- async function up$70(db) {
23781
+ async function up$71(db) {
23581
23782
  await sql`
23582
23783
  ALTER TABLE public.generic_webhook_sources
23583
23784
  DROP CONSTRAINT IF EXISTS generic_webhook_sources_provider_type_check
@@ -23593,7 +23794,7 @@ async function up$70(db) {
23593
23794
  CHECK (provider_type = ANY (ARRAY['generic'::text, 'local'::text]))
23594
23795
  `.execute(db);
23595
23796
  }
23596
- async function down$70(db) {
23797
+ async function down$71(db) {
23597
23798
  await sql`
23598
23799
  ALTER TABLE public.generic_webhook_sources
23599
23800
  DROP CONSTRAINT IF EXISTS generic_webhook_sources_provider_type_check
@@ -23613,8 +23814,8 @@ var init__037_generic_sources_provider_type_local = __esmMin((() => {}));
23613
23814
  //#endregion
23614
23815
  //#region src/db/migrations/038_remote_sources.ts
23615
23816
  var _038_remote_sources_exports = /* @__PURE__ */ __exportAll({
23616
- down: () => down$69,
23617
- up: () => up$69
23817
+ down: () => down$70,
23818
+ up: () => up$70
23618
23819
  });
23619
23820
  /**
23620
23821
  * `remote_sources` anchors a Platform-relayed `kici run remote` to its real
@@ -23626,7 +23827,7 @@ var _038_remote_sources_exports = /* @__PURE__ */ __exportAll({
23626
23827
  *
23627
23828
  * Idempotent: a re-run on a DB that already has the table is a no-op.
23628
23829
  */
23629
- async function up$69(db) {
23830
+ async function up$70(db) {
23630
23831
  if ((await sql`
23631
23832
  SELECT EXISTS (
23632
23833
  SELECT 1 FROM information_schema.tables
@@ -23645,15 +23846,15 @@ async function up$69(db) {
23645
23846
  )
23646
23847
  `.execute(db);
23647
23848
  }
23648
- async function down$69(db) {
23849
+ async function down$70(db) {
23649
23850
  await sql`DROP TABLE IF EXISTS public.remote_sources`.execute(db);
23650
23851
  }
23651
23852
  var init__038_remote_sources = __esmMin((() => {}));
23652
23853
  //#endregion
23653
23854
  //#region src/db/migrations/039_host_roster.ts
23654
23855
  var _039_host_roster_exports = /* @__PURE__ */ __exportAll({
23655
- down: () => down$68,
23656
- up: () => up$68
23856
+ down: () => down$69,
23857
+ up: () => up$69
23657
23858
  });
23658
23859
  /**
23659
23860
  * `host_roster` is KiCI's declared inventory: one durable row per agent the
@@ -23670,7 +23871,7 @@ var _039_host_roster_exports = /* @__PURE__ */ __exportAll({
23670
23871
  *
23671
23872
  * Idempotent: a re-run on a DB that already has the table is a no-op.
23672
23873
  */
23673
- async function up$68(db) {
23874
+ async function up$69(db) {
23674
23875
  if ((await sql`
23675
23876
  SELECT EXISTS (
23676
23877
  SELECT 1 FROM information_schema.tables
@@ -23700,15 +23901,15 @@ async function up$68(db) {
23700
23901
  await sql`CREATE INDEX idx_host_roster_reap
23701
23902
  ON public.host_roster (lifecycle_class, last_seen)`.execute(db);
23702
23903
  }
23703
- async function down$68(db) {
23904
+ async function down$69(db) {
23704
23905
  await sql`DROP TABLE IF EXISTS public.host_roster`.execute(db);
23705
23906
  }
23706
23907
  var init__039_host_roster = __esmMin((() => {}));
23707
23908
  //#endregion
23708
23909
  //#region src/db/migrations/040_runsonall_pin.ts
23709
23910
  var _040_runsonall_pin_exports = /* @__PURE__ */ __exportAll({
23710
- down: () => down$67,
23711
- up: () => up$67
23911
+ down: () => down$68,
23912
+ up: () => up$68
23712
23913
  });
23713
23914
  /**
23714
23915
  * Add the `runsOnAll` host fan-out columns:
@@ -23735,7 +23936,7 @@ async function colExists$12(db, table, name) {
23735
23936
  ) AS exists
23736
23937
  `.execute(db)).rows[0]?.exists ?? false;
23737
23938
  }
23738
- async function up$67(db) {
23939
+ async function up$68(db) {
23739
23940
  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);
23740
23941
  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);
23741
23942
  if (!await colExists$12(db, "execution_jobs", "variant_kind")) await sql`ALTER TABLE public.execution_jobs ADD COLUMN variant_kind TEXT`.execute(db);
@@ -23746,7 +23947,7 @@ async function up$67(db) {
23746
23947
  WHERE pinned_agent_id IS NOT NULL
23747
23948
  `.execute(db);
23748
23949
  }
23749
- async function down$67(db) {
23950
+ async function down$68(db) {
23750
23951
  await sql`DROP INDEX IF EXISTS public.idx_dispatch_queue_pinned_agent`.execute(db);
23751
23952
  await sql`ALTER TABLE public.dispatch_queue DROP COLUMN IF EXISTS pinned_agent_id`.execute(db);
23752
23953
  await sql`ALTER TABLE public.execution_jobs DROP COLUMN IF EXISTS variant_label`.execute(db);
@@ -23757,8 +23958,8 @@ var init__040_runsonall_pin = __esmMin((() => {}));
23757
23958
  //#endregion
23758
23959
  //#region src/db/migrations/041_wave_gated.ts
23759
23960
  var _041_wave_gated_exports = /* @__PURE__ */ __exportAll({
23760
- down: () => down$66,
23761
- up: () => up$66
23961
+ down: () => down$67,
23962
+ up: () => up$67
23762
23963
  });
23763
23964
  /**
23764
23965
  * Add the rolling fan-out wave-gate columns:
@@ -23788,7 +23989,7 @@ async function colExists$11(db, table, name) {
23788
23989
  ) AS exists
23789
23990
  `.execute(db)).rows[0]?.exists ?? false;
23790
23991
  }
23791
- async function up$66(db) {
23992
+ async function up$67(db) {
23792
23993
  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);
23793
23994
  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);
23794
23995
  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);
@@ -23797,7 +23998,7 @@ async function up$66(db) {
23797
23998
  ON public.execution_jobs (run_id, base_job_name, wave_gated)
23798
23999
  `.execute(db);
23799
24000
  }
23800
- async function down$66(db) {
24001
+ async function down$67(db) {
23801
24002
  await sql`DROP INDEX IF EXISTS public.idx_execution_jobs_wave`.execute(db);
23802
24003
  await sql`ALTER TABLE public.execution_jobs DROP COLUMN IF EXISTS wave_fail_fast`.execute(db);
23803
24004
  await sql`ALTER TABLE public.execution_jobs DROP COLUMN IF EXISTS wave_max_parallel`.execute(db);
@@ -23807,8 +24008,8 @@ var init__041_wave_gated = __esmMin((() => {}));
23807
24008
  //#endregion
23808
24009
  //#region src/db/migrations/042_dispatch_queue_patterns.ts
23809
24010
  var _042_dispatch_queue_patterns_exports = /* @__PURE__ */ __exportAll({
23810
- down: () => down$65,
23811
- up: () => up$65
24011
+ down: () => down$66,
24012
+ up: () => up$66
23812
24013
  });
23813
24014
  /**
23814
24015
  * Add pattern columns to dispatch_queue. Exact labels stay in runs_on_labels /
@@ -23834,11 +24035,11 @@ async function colExists$10(db, table, name) {
23834
24035
  ) AS exists
23835
24036
  `.execute(db)).rows[0]?.exists ?? false;
23836
24037
  }
23837
- async function up$65(db) {
24038
+ async function up$66(db) {
23838
24039
  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);
23839
24040
  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);
23840
24041
  }
23841
- async function down$65(db) {
24042
+ async function down$66(db) {
23842
24043
  await sql`ALTER TABLE public.dispatch_queue DROP COLUMN IF EXISTS exclude_patterns`.execute(db);
23843
24044
  await sql`ALTER TABLE public.dispatch_queue DROP COLUMN IF EXISTS runs_on_patterns`.execute(db);
23844
24045
  }
@@ -23846,8 +24047,8 @@ var init__042_dispatch_queue_patterns = __esmMin((() => {}));
23846
24047
  //#endregion
23847
24048
  //#region src/db/migrations/043_rerouted_to_peer.ts
23848
24049
  var _043_rerouted_to_peer_exports = /* @__PURE__ */ __exportAll({
23849
- down: () => down$64,
23850
- up: () => up$64
24050
+ down: () => down$65,
24051
+ up: () => up$65
23851
24052
  });
23852
24053
  /**
23853
24054
  * Add a nullable `rerouted_to_peer text` marker to execution_jobs. Non-null
@@ -23868,18 +24069,18 @@ async function colExists$9(db, table, name) {
23868
24069
  ) AS exists
23869
24070
  `.execute(db)).rows[0]?.exists ?? false;
23870
24071
  }
23871
- async function up$64(db) {
24072
+ async function up$65(db) {
23872
24073
  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);
23873
24074
  }
23874
- async function down$64(db) {
24075
+ async function down$65(db) {
23875
24076
  await sql`ALTER TABLE public.execution_jobs DROP COLUMN IF EXISTS rerouted_to_peer`.execute(db);
23876
24077
  }
23877
24078
  var init__043_rerouted_to_peer = __esmMin((() => {}));
23878
24079
  //#endregion
23879
24080
  //#region src/db/migrations/044_check_mode.ts
23880
24081
  var _044_check_mode_exports = /* @__PURE__ */ __exportAll({
23881
- down: () => down$63,
23882
- up: () => up$63
24082
+ down: () => down$64,
24083
+ up: () => up$64
23883
24084
  });
23884
24085
  /**
23885
24086
  * Add idempotent check-mode columns:
@@ -23906,13 +24107,13 @@ async function colExists$8(db, table, name) {
23906
24107
  ) AS exists
23907
24108
  `.execute(db)).rows[0]?.exists ?? false;
23908
24109
  }
23909
- async function up$63(db) {
24110
+ async function up$64(db) {
23910
24111
  if (!await colExists$8(db, "execution_runs", "check_mode")) await sql`ALTER TABLE public.execution_runs ADD COLUMN check_mode text`.execute(db);
23911
24112
  if (!await colExists$8(db, "execution_steps", "check_outcome")) await sql`ALTER TABLE public.execution_steps ADD COLUMN check_outcome text`.execute(db);
23912
24113
  if (!await colExists$8(db, "execution_steps", "drift_summary")) await sql`ALTER TABLE public.execution_steps ADD COLUMN drift_summary text`.execute(db);
23913
24114
  if (!await colExists$8(db, "execution_steps", "drift")) await sql`ALTER TABLE public.execution_steps ADD COLUMN drift jsonb`.execute(db);
23914
24115
  }
23915
- async function down$63(db) {
24116
+ async function down$64(db) {
23916
24117
  await sql`ALTER TABLE public.execution_steps DROP COLUMN IF EXISTS drift`.execute(db);
23917
24118
  await sql`ALTER TABLE public.execution_steps DROP COLUMN IF EXISTS drift_summary`.execute(db);
23918
24119
  await sql`ALTER TABLE public.execution_steps DROP COLUMN IF EXISTS check_outcome`.execute(db);
@@ -23922,8 +24123,8 @@ var init__044_check_mode = __esmMin((() => {}));
23922
24123
  //#endregion
23923
24124
  //#region src/db/migrations/045_host_properties.ts
23924
24125
  var _045_host_properties_exports = /* @__PURE__ */ __exportAll({
23925
- down: () => down$62,
23926
- up: () => up$62
24126
+ down: () => down$63,
24127
+ up: () => up$63
23927
24128
  });
23928
24129
  /**
23929
24130
  * Add the typed host-vars dimension to the host roster:
@@ -23937,19 +24138,19 @@ var _045_host_properties_exports = /* @__PURE__ */ __exportAll({
23937
24138
  * Idempotent (`ADD COLUMN IF NOT EXISTS`): re-running on a DB that already has
23938
24139
  * the column is a no-op. Staging data is preserved (additive column).
23939
24140
  */
23940
- async function up$62(db) {
24141
+ async function up$63(db) {
23941
24142
  await sql`ALTER TABLE public.host_roster
23942
24143
  ADD COLUMN IF NOT EXISTS host_properties jsonb NOT NULL DEFAULT '{}'::jsonb`.execute(db);
23943
24144
  }
23944
- async function down$62(db) {
24145
+ async function down$63(db) {
23945
24146
  await sql`ALTER TABLE public.host_roster DROP COLUMN IF EXISTS host_properties`.execute(db);
23946
24147
  }
23947
24148
  var init__045_host_properties = __esmMin((() => {}));
23948
24149
  //#endregion
23949
24150
  //#region src/db/migrations/046_join_token_consumed_by_instance.ts
23950
24151
  var _046_join_token_consumed_by_instance_exports = /* @__PURE__ */ __exportAll({
23951
- down: () => down$61,
23952
- up: () => up$61
24152
+ down: () => down$62,
24153
+ up: () => up$62
23953
24154
  });
23954
24155
  /**
23955
24156
  * Record the joining peer's instanceId at first consumption of a join token:
@@ -23964,19 +24165,19 @@ var _046_join_token_consumed_by_instance_exports = /* @__PURE__ */ __exportAll({
23964
24165
  * Idempotent (`ADD COLUMN IF NOT EXISTS`): re-running on a DB that already has
23965
24166
  * the column is a no-op. Staging data is preserved (additive nullable column).
23966
24167
  */
23967
- async function up$61(db) {
24168
+ async function up$62(db) {
23968
24169
  await sql`ALTER TABLE public.join_tokens
23969
24170
  ADD COLUMN IF NOT EXISTS consumed_by_instance text`.execute(db);
23970
24171
  }
23971
- async function down$61(db) {
24172
+ async function down$62(db) {
23972
24173
  await sql`ALTER TABLE public.join_tokens DROP COLUMN IF EXISTS consumed_by_instance`.execute(db);
23973
24174
  }
23974
24175
  var init__046_join_token_consumed_by_instance = __esmMin((() => {}));
23975
24176
  //#endregion
23976
24177
  //#region src/db/migrations/047_needs_run_on.ts
23977
24178
  var _047_needs_run_on_exports = /* @__PURE__ */ __exportAll({
23978
- down: () => down$60,
23979
- up: () => up$60
24179
+ down: () => down$61,
24180
+ up: () => up$61
23980
24181
  });
23981
24182
  async function colExists$7(db, table, name) {
23982
24183
  return (await sql`
@@ -23988,7 +24189,7 @@ async function colExists$7(db, table, name) {
23988
24189
  ) AS exists
23989
24190
  `.execute(db)).rows[0]?.exists ?? false;
23990
24191
  }
23991
- async function up$60(db) {
24192
+ async function up$61(db) {
23992
24193
  if (!await colExists$7(db, "execution_job_needs", "run_on")) await sql`
23993
24194
  ALTER TABLE public.execution_job_needs
23994
24195
  ADD COLUMN run_on text NOT NULL DEFAULT ${sql.raw(SUCCESS_ONLY_DEFAULT)}
@@ -24007,7 +24208,7 @@ async function up$60(db) {
24007
24208
  await sql`ALTER TABLE public.execution_job_needs DROP COLUMN if_failed`.execute(db);
24008
24209
  }
24009
24210
  }
24010
- async function down$60(db) {
24211
+ async function down$61(db) {
24011
24212
  if (!await colExists$7(db, "execution_job_needs", "if_failed")) await sql`
24012
24213
  ALTER TABLE public.execution_job_needs
24013
24214
  ADD COLUMN if_failed text NOT NULL DEFAULT 'skip'
@@ -24036,8 +24237,8 @@ var init__047_needs_run_on = __esmMin((() => {
24036
24237
  //#endregion
24037
24238
  //#region src/db/migrations/048_host_reboot_pending.ts
24038
24239
  var _048_host_reboot_pending_exports = /* @__PURE__ */ __exportAll({
24039
- down: () => down$59,
24040
- up: () => up$59
24240
+ down: () => down$60,
24241
+ up: () => up$60
24041
24242
  });
24042
24243
  /**
24043
24244
  * Add `host_roster.reboot_pending_until timestamptz NULL` — the persisted
@@ -24054,19 +24255,19 @@ var _048_host_reboot_pending_exports = /* @__PURE__ */ __exportAll({
24054
24255
  * Idempotent (`ADD COLUMN IF NOT EXISTS`); additive, so staging data is
24055
24256
  * preserved.
24056
24257
  */
24057
- async function up$59(db) {
24258
+ async function up$60(db) {
24058
24259
  await sql`ALTER TABLE public.host_roster
24059
24260
  ADD COLUMN IF NOT EXISTS reboot_pending_until timestamptz`.execute(db);
24060
24261
  }
24061
- async function down$59(db) {
24262
+ async function down$60(db) {
24062
24263
  await sql`ALTER TABLE public.host_roster DROP COLUMN IF EXISTS reboot_pending_until`.execute(db);
24063
24264
  }
24064
24265
  var init__048_host_reboot_pending = __esmMin((() => {}));
24065
24266
  //#endregion
24066
24267
  //#region src/db/migrations/049_held_runs_payload.ts
24067
24268
  var _049_held_runs_payload_exports = /* @__PURE__ */ __exportAll({
24068
- down: () => down$58,
24069
- up: () => up$58
24269
+ down: () => down$59,
24270
+ up: () => up$59
24070
24271
  });
24071
24272
  /**
24072
24273
  * Add `held_runs.payload jsonb NULL` — the drift payload captured when a
@@ -24078,19 +24279,19 @@ var _049_held_runs_payload_exports = /* @__PURE__ */ __exportAll({
24078
24279
  * Idempotent (`ADD COLUMN IF NOT EXISTS`); additive, so staging data is
24079
24280
  * preserved.
24080
24281
  */
24081
- async function up$58(db) {
24282
+ async function up$59(db) {
24082
24283
  await sql`ALTER TABLE public.held_runs
24083
24284
  ADD COLUMN IF NOT EXISTS payload jsonb`.execute(db);
24084
24285
  }
24085
- async function down$58(db) {
24286
+ async function down$59(db) {
24086
24287
  await sql`ALTER TABLE public.held_runs DROP COLUMN IF EXISTS payload`.execute(db);
24087
24288
  }
24088
24289
  var init__049_held_runs_payload = __esmMin((() => {}));
24089
24290
  //#endregion
24090
24291
  //#region src/db/migrations/050_sources_slug.ts
24091
24292
  var _050_sources_slug_exports = /* @__PURE__ */ __exportAll({
24092
- down: () => down$57,
24093
- up: () => up$57
24293
+ down: () => down$58,
24294
+ up: () => up$58
24094
24295
  });
24095
24296
  /**
24096
24297
  * Add `sources.slug TEXT NULL` — the GitHub App slug (the URL-safe identifier
@@ -24105,19 +24306,19 @@ var _050_sources_slug_exports = /* @__PURE__ */ __exportAll({
24105
24306
  * Idempotent (`ADD COLUMN IF NOT EXISTS`); additive, so staging data is
24106
24307
  * preserved.
24107
24308
  */
24108
- async function up$57(db) {
24309
+ async function up$58(db) {
24109
24310
  await sql`ALTER TABLE public.sources
24110
24311
  ADD COLUMN IF NOT EXISTS slug text`.execute(db);
24111
24312
  }
24112
- async function down$57(db) {
24313
+ async function down$58(db) {
24113
24314
  await sql`ALTER TABLE public.sources DROP COLUMN IF EXISTS slug`.execute(db);
24114
24315
  }
24115
24316
  var init__050_sources_slug = __esmMin((() => {}));
24116
24317
  //#endregion
24117
24318
  //#region src/db/migrations/051_binding_host_pattern.ts
24118
24319
  var _051_binding_host_pattern_exports = /* @__PURE__ */ __exportAll({
24119
- down: () => down$56,
24120
- up: () => up$56
24320
+ down: () => down$57,
24321
+ up: () => up$57
24121
24322
  });
24122
24323
  /**
24123
24324
  * Add a per-host dimension to environment secret bindings:
@@ -24133,7 +24334,7 @@ var _051_binding_host_pattern_exports = /* @__PURE__ */ __exportAll({
24133
24334
  * Idempotent: re-running on a DB that already has the column / index is a no-op.
24134
24335
  * Additive — staging data is preserved.
24135
24336
  */
24136
- async function up$56(db) {
24337
+ async function up$57(db) {
24137
24338
  await sql`ALTER TABLE public.environment_bindings
24138
24339
  ADD COLUMN IF NOT EXISTS host_pattern text NOT NULL DEFAULT '**'`.execute(db);
24139
24340
  await sql`ALTER TABLE public.environment_bindings
@@ -24141,7 +24342,7 @@ async function up$56(db) {
24141
24342
  await sql`CREATE UNIQUE INDEX IF NOT EXISTS environment_bindings_env_scope_host_uniq
24142
24343
  ON public.environment_bindings (environment_id, scope_pattern, host_pattern)`.execute(db);
24143
24344
  }
24144
- async function down$56(db) {
24345
+ async function down$57(db) {
24145
24346
  await sql`DROP INDEX IF EXISTS public.environment_bindings_env_scope_host_uniq`.execute(db);
24146
24347
  await sql`ALTER TABLE public.environment_bindings
24147
24348
  DROP COLUMN IF EXISTS host_pattern`.execute(db);
@@ -24152,8 +24353,8 @@ var init__051_binding_host_pattern = __esmMin((() => {}));
24152
24353
  //#endregion
24153
24354
  //#region src/db/migrations/052_host_reach_metadata.ts
24154
24355
  var _052_host_reach_metadata_exports = /* @__PURE__ */ __exportAll({
24155
- down: () => down$55,
24156
- up: () => up$55
24356
+ down: () => down$56,
24357
+ up: () => up$56
24157
24358
  });
24158
24359
  /**
24159
24360
  * Add pre-agent reach metadata to the host roster so a declared host (no agent
@@ -24170,14 +24371,14 @@ var _052_host_reach_metadata_exports = /* @__PURE__ */ __exportAll({
24170
24371
  * behaves exactly as before. Idempotent (`ADD COLUMN IF NOT EXISTS`); additive,
24171
24372
  * so staging data is preserved.
24172
24373
  */
24173
- async function up$55(db) {
24374
+ async function up$56(db) {
24174
24375
  await sql`ALTER TABLE public.host_roster
24175
24376
  ADD COLUMN IF NOT EXISTS address text,
24176
24377
  ADD COLUMN IF NOT EXISTS ssh_user text,
24177
24378
  ADD COLUMN IF NOT EXISTS ssh_port integer,
24178
24379
  ADD COLUMN IF NOT EXISTS ssh_key_secret text`.execute(db);
24179
24380
  }
24180
- async function down$55(db) {
24381
+ async function down$56(db) {
24181
24382
  await sql`ALTER TABLE public.host_roster
24182
24383
  DROP COLUMN IF EXISTS address,
24183
24384
  DROP COLUMN IF EXISTS ssh_user,
@@ -24188,8 +24389,8 @@ var init__052_host_reach_metadata = __esmMin((() => {}));
24188
24389
  //#endregion
24189
24390
  //#region src/db/migrations/053_agent_token_single_use.ts
24190
24391
  var _053_agent_token_single_use_exports = /* @__PURE__ */ __exportAll({
24191
- down: () => down$54,
24192
- up: () => up$54
24392
+ down: () => down$55,
24393
+ up: () => up$55
24193
24394
  });
24194
24395
  /**
24195
24396
  * Add a single-use marker to agent tokens for the bootstrap (init-runner)
@@ -24204,11 +24405,11 @@ var _053_agent_token_single_use_exports = /* @__PURE__ */ __exportAll({
24204
24405
  * Idempotent (`ADD COLUMN IF NOT EXISTS`); additive, so staging data is
24205
24406
  * preserved.
24206
24407
  */
24207
- async function up$54(db) {
24408
+ async function up$55(db) {
24208
24409
  await sql`ALTER TABLE public.agent_tokens
24209
24410
  ADD COLUMN IF NOT EXISTS consumed_at timestamptz`.execute(db);
24210
24411
  }
24211
- async function down$54(db) {
24412
+ async function down$55(db) {
24212
24413
  await sql`ALTER TABLE public.agent_tokens
24213
24414
  DROP COLUMN IF EXISTS consumed_at`.execute(db);
24214
24415
  }
@@ -24216,8 +24417,8 @@ var init__053_agent_token_single_use = __esmMin((() => {}));
24216
24417
  //#endregion
24217
24418
  //#region src/db/migrations/054_local_working_tree.ts
24218
24419
  var _054_local_working_tree_exports = /* @__PURE__ */ __exportAll({
24219
- down: () => down$53,
24220
- up: () => up$53
24420
+ down: () => down$54,
24421
+ up: () => up$54
24221
24422
  });
24222
24423
  /**
24223
24424
  * Mark runs that executed an uploaded local working tree (`kici run remote`):
@@ -24230,11 +24431,11 @@ var _054_local_working_tree_exports = /* @__PURE__ */ __exportAll({
24230
24431
  * Idempotent (`ADD COLUMN IF NOT EXISTS`); additive with a default, so staging
24231
24432
  * data is preserved.
24232
24433
  */
24233
- async function up$53(db) {
24434
+ async function up$54(db) {
24234
24435
  await sql`ALTER TABLE public.execution_runs
24235
24436
  ADD COLUMN IF NOT EXISTS local_working_tree boolean NOT NULL DEFAULT false`.execute(db);
24236
24437
  }
24237
- async function down$53(db) {
24438
+ async function down$54(db) {
24238
24439
  await sql`ALTER TABLE public.execution_runs
24239
24440
  DROP COLUMN IF EXISTS local_working_tree`.execute(db);
24240
24441
  }
@@ -24242,8 +24443,8 @@ var init__054_local_working_tree = __esmMin((() => {}));
24242
24443
  //#endregion
24243
24444
  //#region src/db/migrations/055_agent_token_mandatory_labels.ts
24244
24445
  var _055_agent_token_mandatory_labels_exports = /* @__PURE__ */ __exportAll({
24245
- down: () => down$52,
24246
- up: () => up$52
24446
+ down: () => down$53,
24447
+ up: () => up$53
24247
24448
  });
24248
24449
  /**
24249
24450
  * Add a token-bound mandatory-label taint to agent tokens:
@@ -24259,11 +24460,11 @@ var _055_agent_token_mandatory_labels_exports = /* @__PURE__ */ __exportAll({
24259
24460
  * Idempotent (`ADD COLUMN IF NOT EXISTS`); additive, so staging data is
24260
24461
  * preserved.
24261
24462
  */
24262
- async function up$52(db) {
24463
+ async function up$53(db) {
24263
24464
  await sql`ALTER TABLE public.agent_tokens
24264
24465
  ADD COLUMN IF NOT EXISTS mandatory_labels text`.execute(db);
24265
24466
  }
24266
- async function down$52(db) {
24467
+ async function down$53(db) {
24267
24468
  await sql`ALTER TABLE public.agent_tokens
24268
24469
  DROP COLUMN IF EXISTS mandatory_labels`.execute(db);
24269
24470
  }
@@ -24271,8 +24472,8 @@ var init__055_agent_token_mandatory_labels = __esmMin((() => {}));
24271
24472
  //#endregion
24272
24473
  //#region src/db/migrations/056_execution_jobs_environments.ts
24273
24474
  var _056_execution_jobs_environments_exports = /* @__PURE__ */ __exportAll({
24274
- down: () => down$51,
24275
- up: () => up$51
24475
+ down: () => down$52,
24476
+ up: () => up$52
24276
24477
  });
24277
24478
  /**
24278
24479
  * Add a per-job bound deployment-environment list to `execution_jobs`:
@@ -24287,11 +24488,11 @@ var _056_execution_jobs_environments_exports = /* @__PURE__ */ __exportAll({
24287
24488
  * Idempotent (`ADD COLUMN IF NOT EXISTS`); additive, so staging data is
24288
24489
  * preserved.
24289
24490
  */
24290
- async function up$51(db) {
24491
+ async function up$52(db) {
24291
24492
  await sql`ALTER TABLE public.execution_jobs
24292
24493
  ADD COLUMN IF NOT EXISTS environments text`.execute(db);
24293
24494
  }
24294
- async function down$51(db) {
24495
+ async function down$52(db) {
24295
24496
  await sql`ALTER TABLE public.execution_jobs
24296
24497
  DROP COLUMN IF EXISTS environments`.execute(db);
24297
24498
  }
@@ -24299,8 +24500,8 @@ var init__056_execution_jobs_environments = __esmMin((() => {}));
24299
24500
  //#endregion
24300
24501
  //#region src/db/migrations/057_step_concurrency.ts
24301
24502
  var _057_step_concurrency_exports = /* @__PURE__ */ __exportAll({
24302
- down: () => down$50,
24303
- up: () => up$50
24503
+ down: () => down$51,
24504
+ up: () => up$51
24304
24505
  });
24305
24506
  /**
24306
24507
  * Add parallel step-group concurrency columns to `execution_steps`:
@@ -24323,11 +24524,11 @@ async function colExists$6(db, table, name) {
24323
24524
  ) AS exists
24324
24525
  `.execute(db)).rows[0]?.exists ?? false;
24325
24526
  }
24326
- async function up$50(db) {
24527
+ async function up$51(db) {
24327
24528
  if (!await colExists$6(db, "execution_steps", "concurrency_kind")) await sql`ALTER TABLE public.execution_steps ADD COLUMN concurrency_kind text`.execute(db);
24328
24529
  if (!await colExists$6(db, "execution_steps", "group_id")) await sql`ALTER TABLE public.execution_steps ADD COLUMN group_id text`.execute(db);
24329
24530
  }
24330
- async function down$50(db) {
24531
+ async function down$51(db) {
24331
24532
  await sql`ALTER TABLE public.execution_steps DROP COLUMN IF EXISTS group_id`.execute(db);
24332
24533
  await sql`ALTER TABLE public.execution_steps DROP COLUMN IF EXISTS concurrency_kind`.execute(db);
24333
24534
  }
@@ -24335,8 +24536,8 @@ var init__057_step_concurrency = __esmMin((() => {}));
24335
24536
  //#endregion
24336
24537
  //#region src/db/migrations/058_access_log_agent_label.ts
24337
24538
  var _058_access_log_agent_label_exports = /* @__PURE__ */ __exportAll({
24338
- down: () => down$49,
24339
- up: () => up$49
24539
+ down: () => down$50,
24540
+ up: () => up$50
24340
24541
  });
24341
24542
  /**
24342
24543
  * Add `access_log.agent_label text` — the human-set name of the agent that
@@ -24356,18 +24557,18 @@ async function colExists$5(db, table, name) {
24356
24557
  ) AS exists
24357
24558
  `.execute(db)).rows[0]?.exists ?? false;
24358
24559
  }
24359
- async function up$49(db) {
24560
+ async function up$50(db) {
24360
24561
  if (!await colExists$5(db, "access_log", "agent_label")) await sql`ALTER TABLE public.access_log ADD COLUMN agent_label text`.execute(db);
24361
24562
  }
24362
- async function down$49(db) {
24563
+ async function down$50(db) {
24363
24564
  await sql`ALTER TABLE public.access_log DROP COLUMN IF EXISTS agent_label`.execute(db);
24364
24565
  }
24365
24566
  var init__058_access_log_agent_label = __esmMin((() => {}));
24366
24567
  //#endregion
24367
24568
  //#region src/db/migrations/059_attestation_verdict.ts
24368
24569
  var _059_attestation_verdict_exports = /* @__PURE__ */ __exportAll({
24369
- down: () => down$48,
24370
- up: () => up$48
24570
+ down: () => down$49,
24571
+ up: () => up$49
24371
24572
  });
24372
24573
  /**
24373
24574
  * Add server-side verification verdict columns to `attestations`, plus the
@@ -24394,7 +24595,7 @@ async function colExists$4(db, table, name) {
24394
24595
  ) AS exists
24395
24596
  `.execute(db)).rows[0]?.exists ?? false;
24396
24597
  }
24397
- async function up$48(db) {
24598
+ async function up$49(db) {
24398
24599
  if (await colExists$4(db, "attestations", "verify_status")) return;
24399
24600
  await sql`
24400
24601
  ALTER TABLE public.attestations
@@ -24407,7 +24608,7 @@ async function up$48(db) {
24407
24608
  await sql`CREATE INDEX idx_attestations_verify_status ON public.attestations (verify_status)`.execute(db);
24408
24609
  await sql`CREATE INDEX idx_attestations_created_at ON public.attestations (created_at)`.execute(db);
24409
24610
  }
24410
- async function down$48(db) {
24611
+ async function down$49(db) {
24411
24612
  await sql`DROP INDEX IF EXISTS idx_attestations_created_at`.execute(db);
24412
24613
  await sql`DROP INDEX IF EXISTS idx_attestations_verify_status`.execute(db);
24413
24614
  await sql`DROP INDEX IF EXISTS idx_attestations_subject_name`.execute(db);
@@ -24423,8 +24624,8 @@ var init__059_attestation_verdict = __esmMin((() => {}));
24423
24624
  //#endregion
24424
24625
  //#region src/db/migrations/060_run_trigger_actor.ts
24425
24626
  var _060_run_trigger_actor_exports = /* @__PURE__ */ __exportAll({
24426
- down: () => down$47,
24427
- up: () => up$47
24627
+ down: () => down$48,
24628
+ up: () => up$48
24428
24629
  });
24429
24630
  /**
24430
24631
  * Add the triggering-actor columns to `execution_runs`:
@@ -24452,12 +24653,12 @@ async function colExists$3(db, table, name) {
24452
24653
  ) AS exists
24453
24654
  `.execute(db)).rows[0]?.exists ?? false;
24454
24655
  }
24455
- async function up$47(db) {
24656
+ async function up$48(db) {
24456
24657
  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);
24457
24658
  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);
24458
24659
  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);
24459
24660
  }
24460
- async function down$47(db) {
24661
+ async function down$48(db) {
24461
24662
  await sql`ALTER TABLE public.execution_runs DROP COLUMN IF EXISTS trigger_actor_provider`.execute(db);
24462
24663
  await sql`ALTER TABLE public.execution_runs DROP COLUMN IF EXISTS trigger_actor_username`.execute(db);
24463
24664
  await sql`ALTER TABLE public.execution_runs DROP COLUMN IF EXISTS trigger_actor_user_id`.execute(db);
@@ -24466,8 +24667,8 @@ var init__060_run_trigger_actor = __esmMin((() => {}));
24466
24667
  //#endregion
24467
24668
  //#region src/db/migrations/061_execution_runs_environment_id.ts
24468
24669
  var _061_execution_runs_environment_id_exports = /* @__PURE__ */ __exportAll({
24469
- down: () => down$46,
24470
- up: () => up$46
24670
+ down: () => down$47,
24671
+ up: () => up$47
24471
24672
  });
24472
24673
  /**
24473
24674
  * Add `environment_id` to `execution_runs` so environment run-history can be
@@ -24503,7 +24704,7 @@ async function colExists$2(db, table, name) {
24503
24704
  ) AS exists
24504
24705
  `.execute(db)).rows[0]?.exists ?? false;
24505
24706
  }
24506
- async function up$46(db) {
24707
+ async function up$47(db) {
24507
24708
  if (!await colExists$2(db, "execution_runs", "environment_id")) await sql`
24508
24709
  ALTER TABLE public.execution_runs
24509
24710
  ADD COLUMN environment_id uuid
@@ -24525,7 +24726,7 @@ async function up$46(db) {
24525
24726
  WHERE e2.type = 'fixed' AND e2.name = er.environment) = 1
24526
24727
  `.execute(db);
24527
24728
  }
24528
- async function down$46(db) {
24729
+ async function down$47(db) {
24529
24730
  await sql`DROP INDEX IF EXISTS idx_execution_runs_environment_id`.execute(db);
24530
24731
  await sql`ALTER TABLE public.execution_runs DROP COLUMN IF EXISTS environment_id`.execute(db);
24531
24732
  }
@@ -24533,8 +24734,8 @@ var init__061_execution_runs_environment_id = __esmMin((() => {}));
24533
24734
  //#endregion
24534
24735
  //#region src/db/migrations/062_execution_runs_agent_label.ts
24535
24736
  var _062_execution_runs_agent_label_exports = /* @__PURE__ */ __exportAll({
24536
- down: () => down$45,
24537
- up: () => up$45
24737
+ down: () => down$46,
24738
+ up: () => up$46
24538
24739
  });
24539
24740
  /**
24540
24741
  * Add the agent-provenance columns to `execution_runs`:
@@ -24559,11 +24760,11 @@ async function colExists$1(db, table, name) {
24559
24760
  ) AS exists
24560
24761
  `.execute(db)).rows[0]?.exists ?? false;
24561
24762
  }
24562
- async function up$45(db) {
24763
+ async function up$46(db) {
24563
24764
  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);
24564
24765
  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);
24565
24766
  }
24566
- async function down$45(db) {
24767
+ async function down$46(db) {
24567
24768
  await sql`ALTER TABLE public.execution_runs DROP COLUMN IF EXISTS triggered_by_agent_label`.execute(db);
24568
24769
  await sql`ALTER TABLE public.execution_runs DROP COLUMN IF EXISTS cancelled_by_agent_label`.execute(db);
24569
24770
  }
@@ -24571,8 +24772,8 @@ var init__062_execution_runs_agent_label = __esmMin((() => {}));
24571
24772
  //#endregion
24572
24773
  //#region src/db/migrations/063_access_log_agent_label_index.ts
24573
24774
  var _063_access_log_agent_label_index_exports = /* @__PURE__ */ __exportAll({
24574
- down: () => down$44,
24575
- up: () => up$44
24775
+ down: () => down$45,
24776
+ up: () => up$45
24576
24777
  });
24577
24778
  /**
24578
24779
  * Index `access_log.agent_label` (column added by migration 058) so the
@@ -24580,18 +24781,18 @@ var _063_access_log_agent_label_index_exports = /* @__PURE__ */ __exportAll({
24580
24781
  * the dashboard "agent name" filter) does an indexed exact-match lookup
24581
24782
  * instead of a scan. Idempotent.
24582
24783
  */
24583
- async function up$44(db) {
24784
+ async function up$45(db) {
24584
24785
  await sql`CREATE INDEX IF NOT EXISTS access_log_agent_label_idx ON public.access_log (agent_label)`.execute(db);
24585
24786
  }
24586
- async function down$44(db) {
24787
+ async function down$45(db) {
24587
24788
  await sql`DROP INDEX IF EXISTS access_log_agent_label_idx`.execute(db);
24588
24789
  }
24589
24790
  var init__063_access_log_agent_label_index = __esmMin((() => {}));
24590
24791
  //#endregion
24591
24792
  //#region src/db/migrations/064_execution_jobs_skipped_environments.ts
24592
24793
  var _064_execution_jobs_skipped_environments_exports = /* @__PURE__ */ __exportAll({
24593
- down: () => down$43,
24594
- up: () => up$43
24794
+ down: () => down$44,
24795
+ up: () => up$44
24595
24796
  });
24596
24797
  /**
24597
24798
  * Add the test-run skipped-environment columns to `execution_jobs`:
@@ -24606,13 +24807,13 @@ var _064_execution_jobs_skipped_environments_exports = /* @__PURE__ */ __exportA
24606
24807
  * Idempotent (`ADD COLUMN IF NOT EXISTS`); additive, so staging data is
24607
24808
  * preserved.
24608
24809
  */
24609
- async function up$43(db) {
24810
+ async function up$44(db) {
24610
24811
  await sql`ALTER TABLE public.execution_jobs
24611
24812
  ADD COLUMN IF NOT EXISTS skipped_environments text`.execute(db);
24612
24813
  await sql`ALTER TABLE public.execution_jobs
24613
24814
  ADD COLUMN IF NOT EXISTS env_warning text`.execute(db);
24614
24815
  }
24615
- async function down$43(db) {
24816
+ async function down$44(db) {
24616
24817
  await sql`ALTER TABLE public.execution_jobs
24617
24818
  DROP COLUMN IF EXISTS skipped_environments`.execute(db);
24618
24819
  await sql`ALTER TABLE public.execution_jobs
@@ -24622,8 +24823,8 @@ var init__064_execution_jobs_skipped_environments = __esmMin((() => {}));
24622
24823
  //#endregion
24623
24824
  //#region src/db/migrations/065_pending_attestations.ts
24624
24825
  var _065_pending_attestations_exports = /* @__PURE__ */ __exportAll({
24625
- down: () => down$42,
24626
- up: () => up$42
24826
+ down: () => down$43,
24827
+ up: () => up$43
24627
24828
  });
24628
24829
  /**
24629
24830
  * Add the `pending_attestations` deferred-attestation outbox and an idempotency
@@ -24643,7 +24844,7 @@ var _065_pending_attestations_exports = /* @__PURE__ */ __exportAll({
24643
24844
  *
24644
24845
  * Idempotent: guarded on table existence.
24645
24846
  */
24646
- async function up$42(db) {
24847
+ async function up$43(db) {
24647
24848
  if ((await sql`
24648
24849
  SELECT EXISTS (
24649
24850
  SELECT 1 FROM information_schema.tables
@@ -24682,7 +24883,7 @@ async function up$42(db) {
24682
24883
  ON public.attestations (run_id, job_id, subject_digest)
24683
24884
  `.execute(db);
24684
24885
  }
24685
- async function down$42(db) {
24886
+ async function down$43(db) {
24686
24887
  await sql`DROP INDEX IF EXISTS uq_attestations_run_job_subject`.execute(db);
24687
24888
  await sql`DROP TABLE IF EXISTS public.pending_attestations`.execute(db);
24688
24889
  }
@@ -24690,8 +24891,8 @@ var init__065_pending_attestations = __esmMin((() => {}));
24690
24891
  //#endregion
24691
24892
  //#region src/db/migrations/066_pending_attestations_rejected.ts
24692
24893
  var _066_pending_attestations_rejected_exports = /* @__PURE__ */ __exportAll({
24693
- down: () => down$41,
24694
- up: () => up$41
24894
+ down: () => down$42,
24895
+ up: () => up$42
24695
24896
  });
24696
24897
  /**
24697
24898
  * Add `rejected_at` to `pending_attestations`: the terminal-rejection marker for
@@ -24702,21 +24903,21 @@ var _066_pending_attestations_rejected_exports = /* @__PURE__ */ __exportAll({
24702
24903
  *
24703
24904
  * Idempotent: guarded on column existence.
24704
24905
  */
24705
- async function up$41(db) {
24706
- if (await columnExists$4(db, "pending_attestations", "rejected_at")) return;
24906
+ async function up$42(db) {
24907
+ if (await columnExists$5(db, "pending_attestations", "rejected_at")) return;
24707
24908
  await sql`
24708
24909
  ALTER TABLE public.pending_attestations
24709
24910
  ADD COLUMN rejected_at TIMESTAMPTZ
24710
24911
  `.execute(db);
24711
24912
  }
24712
- async function down$41(db) {
24713
- if (!await columnExists$4(db, "pending_attestations", "rejected_at")) return;
24913
+ async function down$42(db) {
24914
+ if (!await columnExists$5(db, "pending_attestations", "rejected_at")) return;
24714
24915
  await sql`
24715
24916
  ALTER TABLE public.pending_attestations
24716
24917
  DROP COLUMN rejected_at
24717
24918
  `.execute(db);
24718
24919
  }
24719
- async function columnExists$4(db, table, column) {
24920
+ async function columnExists$5(db, table, column) {
24720
24921
  return (await sql`
24721
24922
  SELECT EXISTS (
24722
24923
  SELECT 1 FROM information_schema.columns
@@ -24728,8 +24929,8 @@ var init__066_pending_attestations_rejected = __esmMin((() => {}));
24728
24929
  //#endregion
24729
24930
  //#region src/db/migrations/067_environments_to_contexts.ts
24730
24931
  var _067_environments_to_contexts_exports = /* @__PURE__ */ __exportAll({
24731
- down: () => down$40,
24732
- up: () => up$40
24932
+ down: () => down$41,
24933
+ up: () => up$41
24733
24934
  });
24734
24935
  /**
24735
24936
  * Rename the named-policy object from "environment" to "context" across the
@@ -24763,7 +24964,7 @@ var _067_environments_to_contexts_exports = /* @__PURE__ */ __exportAll({
24763
24964
  * columns automatically (Postgres references them by identity, not name), so
24764
24965
  * only the one hand-named index above needs an explicit rename.
24765
24966
  */
24766
- async function up$40(db) {
24967
+ async function up$41(db) {
24767
24968
  await sql`ALTER TABLE public.environments RENAME TO contexts`.execute(db);
24768
24969
  await sql`ALTER TABLE public.environment_bindings RENAME TO context_bindings`.execute(db);
24769
24970
  await sql`ALTER TABLE public.environment_variables RENAME TO context_variables`.execute(db);
@@ -24782,7 +24983,7 @@ async function up$40(db) {
24782
24983
  await sql`ALTER TABLE public.held_runs ALTER COLUMN queue_type SET DEFAULT 'context'`.execute(db);
24783
24984
  await sql`ALTER TABLE public.held_runs ALTER COLUMN trigger_source SET DEFAULT 'context'`.execute(db);
24784
24985
  }
24785
- async function down$40(db) {
24986
+ async function down$41(db) {
24786
24987
  await sql`ALTER TABLE public.held_runs ALTER COLUMN trigger_source SET DEFAULT 'environment'`.execute(db);
24787
24988
  await sql`ALTER TABLE public.held_runs ALTER COLUMN queue_type SET DEFAULT 'environment'`.execute(db);
24788
24989
  await sql`UPDATE public.held_runs SET trigger_source = 'environment' WHERE trigger_source = 'context'`.execute(db);
@@ -24805,8 +25006,8 @@ var init__067_environments_to_contexts = __esmMin((() => {}));
24805
25006
  //#endregion
24806
25007
  //#region src/db/migrations/068_request_idempotency.ts
24807
25008
  var _068_request_idempotency_exports = /* @__PURE__ */ __exportAll({
24808
- down: () => down$39,
24809
- up: () => up$39
25009
+ down: () => down$40,
25010
+ up: () => up$40
24810
25011
  });
24811
25012
  /**
24812
25013
  * Add the `request_idempotency` claim table: a `request_id`-keyed record that
@@ -24821,12 +25022,12 @@ var _068_request_idempotency_exports = /* @__PURE__ */ __exportAll({
24821
25022
  *
24822
25023
  * Idempotent: guarded on table existence.
24823
25024
  */
24824
- async function up$39(db) {
25025
+ async function up$40(db) {
24825
25026
  if (await tableExists$3(db, "request_idempotency")) return;
24826
25027
  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();
24827
25028
  await db.schema.createIndex("idx_request_idempotency_created_at").on("request_idempotency").column("created_at").execute();
24828
25029
  }
24829
- async function down$39(db) {
25030
+ async function down$40(db) {
24830
25031
  await db.schema.dropTable("request_idempotency").ifExists().execute();
24831
25032
  }
24832
25033
  async function tableExists$3(db, table) {
@@ -24841,8 +25042,8 @@ var init__068_request_idempotency = __esmMin((() => {}));
24841
25042
  //#endregion
24842
25043
  //#region src/db/migrations/069_reroute_tunables.ts
24843
25044
  var _069_reroute_tunables_exports = /* @__PURE__ */ __exportAll({
24844
- down: () => down$38,
24845
- up: () => up$38
25045
+ down: () => down$39,
25046
+ up: () => up$39
24846
25047
  });
24847
25048
  /**
24848
25049
  * Add the three reroute-tunable columns to `org_settings` (all nullable):
@@ -24861,12 +25062,12 @@ var _069_reroute_tunables_exports = /* @__PURE__ */ __exportAll({
24861
25062
  * Idempotent: each column add is guarded on column existence, so a re-run on a
24862
25063
  * DB that already has a column is a no-op for that column.
24863
25064
  */
24864
- async function up$38(db) {
25065
+ async function up$39(db) {
24865
25066
  await addColumnIfMissing(db, "reroute_spawn_window_ms", "BIGINT");
24866
25067
  await addColumnIfMissing(db, "reroute_ack_timeout_ms", "BIGINT");
24867
25068
  await addColumnIfMissing(db, "reroute_max_hops", "INTEGER");
24868
25069
  }
24869
- async function down$38(db) {
25070
+ async function down$39(db) {
24870
25071
  await sql`ALTER TABLE public.org_settings DROP COLUMN IF EXISTS reroute_spawn_window_ms`.execute(db);
24871
25072
  await sql`ALTER TABLE public.org_settings DROP COLUMN IF EXISTS reroute_ack_timeout_ms`.execute(db);
24872
25073
  await sql`ALTER TABLE public.org_settings DROP COLUMN IF EXISTS reroute_max_hops`.execute(db);
@@ -24886,8 +25087,8 @@ var init__069_reroute_tunables = __esmMin((() => {}));
24886
25087
  //#endregion
24887
25088
  //#region src/db/migrations/070_execution_runs_failure_class.ts
24888
25089
  var _070_execution_runs_failure_class_exports = /* @__PURE__ */ __exportAll({
24889
- down: () => down$37,
24890
- up: () => up$37
25090
+ down: () => down$38,
25091
+ up: () => up$38
24891
25092
  });
24892
25093
  /**
24893
25094
  * Add `execution_runs.failure_class` — the reason a terminal run failed
@@ -24908,18 +25109,18 @@ async function colExists(db, table, name) {
24908
25109
  ) AS exists
24909
25110
  `.execute(db)).rows[0]?.exists ?? false;
24910
25111
  }
24911
- async function up$37(db) {
25112
+ async function up$38(db) {
24912
25113
  if (!await colExists(db, "execution_runs", "failure_class")) await sql`ALTER TABLE public.execution_runs ADD COLUMN failure_class text`.execute(db);
24913
25114
  }
24914
- async function down$37(db) {
25115
+ async function down$38(db) {
24915
25116
  await sql`ALTER TABLE public.execution_runs DROP COLUMN IF EXISTS failure_class`.execute(db);
24916
25117
  }
24917
25118
  var init__070_execution_runs_failure_class = __esmMin((() => {}));
24918
25119
  //#endregion
24919
25120
  //#region src/db/migrations/071_batch_accumulation.ts
24920
25121
  var _071_batch_accumulation_exports = /* @__PURE__ */ __exportAll({
24921
- down: () => down$36,
24922
- up: () => up$36
25122
+ down: () => down$37,
25123
+ up: () => up$37
24923
25124
  });
24924
25125
  /**
24925
25126
  * Add the batch-accumulation tables that back the `workflows_failed_batch`
@@ -24943,7 +25144,7 @@ var _071_batch_accumulation_exports = /* @__PURE__ */ __exportAll({
24943
25144
  *
24944
25145
  * Idempotent: guarded on table existence.
24945
25146
  */
24946
- async function up$36(db) {
25147
+ async function up$37(db) {
24947
25148
  if ((await sql`
24948
25149
  SELECT EXISTS (
24949
25150
  SELECT 1 FROM information_schema.tables
@@ -24988,7 +25189,7 @@ async function up$36(db) {
24988
25189
  ON public.batch_accumulation_items (window_id)
24989
25190
  `.execute(db);
24990
25191
  }
24991
- async function down$36(db) {
25192
+ async function down$37(db) {
24992
25193
  await sql`DROP TABLE IF EXISTS public.batch_accumulation_items`.execute(db);
24993
25194
  await sql`DROP TABLE IF EXISTS public.batch_accumulation_windows`.execute(db);
24994
25195
  }
@@ -24996,8 +25197,8 @@ var init__071_batch_accumulation = __esmMin((() => {}));
24996
25197
  //#endregion
24997
25198
  //#region src/db/migrations/072_dispatch_queue_run_id_index.ts
24998
25199
  var _072_dispatch_queue_run_id_index_exports = /* @__PURE__ */ __exportAll({
24999
- down: () => down$35,
25000
- up: () => up$35
25200
+ down: () => down$36,
25201
+ up: () => up$36
25001
25202
  });
25002
25203
  /**
25003
25204
  * Add `idx_dispatch_queue_run_id` on `dispatch_queue (run_id)`.
@@ -25010,21 +25211,21 @@ var _072_dispatch_queue_run_id_index_exports = /* @__PURE__ */ __exportAll({
25010
25211
  *
25011
25212
  * Idempotent: `IF NOT EXISTS` makes a re-run a no-op.
25012
25213
  */
25013
- async function up$35(db) {
25214
+ async function up$36(db) {
25014
25215
  await sql`
25015
25216
  CREATE INDEX IF NOT EXISTS idx_dispatch_queue_run_id
25016
25217
  ON public.dispatch_queue (run_id)
25017
25218
  `.execute(db);
25018
25219
  }
25019
- async function down$35(db) {
25220
+ async function down$36(db) {
25020
25221
  await sql`DROP INDEX IF EXISTS public.idx_dispatch_queue_run_id`.execute(db);
25021
25222
  }
25022
25223
  var init__072_dispatch_queue_run_id_index = __esmMin((() => {}));
25023
25224
  //#endregion
25024
25225
  //#region src/db/migrations/073_org_settings_ingest_concurrency.ts
25025
25226
  var _073_org_settings_ingest_concurrency_exports = /* @__PURE__ */ __exportAll({
25026
- down: () => down$34,
25027
- up: () => up$34
25227
+ down: () => down$35,
25228
+ up: () => up$35
25028
25229
  });
25029
25230
  /**
25030
25231
  * Add `org_settings.ingest_max_concurrency BIGINT` (nullable).
@@ -25035,7 +25236,7 @@ var _073_org_settings_ingest_concurrency_exports = /* @__PURE__ */ __exportAll({
25035
25236
  *
25036
25237
  * Idempotent: a re-run on a DB that already has the column is a no-op.
25037
25238
  */
25038
- async function up$34(db) {
25239
+ async function up$35(db) {
25039
25240
  if ((await sql`
25040
25241
  SELECT EXISTS (
25041
25242
  SELECT 1 FROM information_schema.columns
@@ -25049,7 +25250,7 @@ async function up$34(db) {
25049
25250
  ADD COLUMN ingest_max_concurrency BIGINT
25050
25251
  `.execute(db);
25051
25252
  }
25052
- async function down$34(db) {
25253
+ async function down$35(db) {
25053
25254
  await sql`
25054
25255
  ALTER TABLE public.org_settings DROP COLUMN IF EXISTS ingest_max_concurrency
25055
25256
  `.execute(db);
@@ -25058,8 +25259,8 @@ var init__073_org_settings_ingest_concurrency = __esmMin((() => {}));
25058
25259
  //#endregion
25059
25260
  //#region src/db/migrations/074_normalize_zero_concurrency_limit.ts
25060
25261
  var _074_normalize_zero_concurrency_limit_exports = /* @__PURE__ */ __exportAll({
25061
- down: () => down$33,
25062
- up: () => up$33
25262
+ down: () => down$34,
25263
+ up: () => up$34
25063
25264
  });
25064
25265
  /**
25065
25266
  * Normalize degenerate context concurrency limits. A `concurrency_limit` of 0
@@ -25070,16 +25271,16 @@ var _074_normalize_zero_concurrency_limit_exports = /* @__PURE__ */ __exportAll(
25070
25271
  * Idempotent; down() is a no-op (a normalized 0 cannot — and should not — be
25071
25272
  * restored).
25072
25273
  */
25073
- async function up$33(db) {
25274
+ async function up$34(db) {
25074
25275
  await sql`UPDATE public.contexts SET concurrency_limit = NULL WHERE concurrency_limit <= 0`.execute(db);
25075
25276
  }
25076
- async function down$33(_db) {}
25277
+ async function down$34(_db) {}
25077
25278
  var init__074_normalize_zero_concurrency_limit = __esmMin((() => {}));
25078
25279
  //#endregion
25079
25280
  //#region src/db/migrations/075_ingest_overflow_buffer.ts
25080
25281
  var _075_ingest_overflow_buffer_exports = /* @__PURE__ */ __exportAll({
25081
- down: () => down$32,
25082
- up: () => up$32
25282
+ down: () => down$33,
25283
+ up: () => up$33
25083
25284
  });
25084
25285
  /**
25085
25286
  * Durable overflow buffer for shed webhook-ingest deliveries.
@@ -25093,7 +25294,7 @@ var _075_ingest_overflow_buffer_exports = /* @__PURE__ */ __exportAll({
25093
25294
  *
25094
25295
  * Idempotent: a re-run on a DB that already has the table is a no-op.
25095
25296
  */
25096
- async function up$32(db) {
25297
+ async function up$33(db) {
25097
25298
  if ((await sql`
25098
25299
  SELECT EXISTS (
25099
25300
  SELECT 1 FROM information_schema.tables
@@ -25126,15 +25327,15 @@ async function up$32(db) {
25126
25327
  ON public.ingest_overflow_buffer (delivery_id)
25127
25328
  `.execute(db);
25128
25329
  }
25129
- async function down$32(db) {
25330
+ async function down$33(db) {
25130
25331
  await sql`DROP TABLE IF EXISTS public.ingest_overflow_buffer`.execute(db);
25131
25332
  }
25132
25333
  var init__075_ingest_overflow_buffer = __esmMin((() => {}));
25133
25334
  //#endregion
25134
25335
  //#region src/db/migrations/076_artifacts.ts
25135
25336
  var _076_artifacts_exports = /* @__PURE__ */ __exportAll({
25136
- down: () => down$31,
25137
- up: () => up$31
25337
+ down: () => down$32,
25338
+ up: () => up$32
25138
25339
  });
25139
25340
  /**
25140
25341
  * Add the `artifacts` table for user-facing build artifacts and the per-org
@@ -25151,7 +25352,7 @@ var _076_artifacts_exports = /* @__PURE__ */ __exportAll({
25151
25352
  *
25152
25353
  * Idempotent: a re-run on a DB that already has the table / columns is a no-op.
25153
25354
  */
25154
- async function up$31(db) {
25355
+ async function up$32(db) {
25155
25356
  if (!(await sql`
25156
25357
  SELECT EXISTS (
25157
25358
  SELECT 1 FROM information_schema.tables
@@ -25187,7 +25388,7 @@ async function up$31(db) {
25187
25388
  ADD COLUMN IF NOT EXISTS artifact_ttl_ms BIGINT
25188
25389
  `.execute(db);
25189
25390
  }
25190
- async function down$31(db) {
25391
+ async function down$32(db) {
25191
25392
  await sql`DROP TABLE IF EXISTS public.artifacts`.execute(db);
25192
25393
  await sql`
25193
25394
  ALTER TABLE public.org_settings
@@ -25199,8 +25400,8 @@ var init__076_artifacts = __esmMin((() => {}));
25199
25400
  //#endregion
25200
25401
  //#region src/db/migrations/077_backup_runs.ts
25201
25402
  var _077_backup_runs_exports = /* @__PURE__ */ __exportAll({
25202
- down: () => down$30,
25203
- up: () => up$30
25403
+ down: () => down$31,
25404
+ up: () => up$31
25204
25405
  });
25205
25406
  /**
25206
25407
  * Add the `backup_runs` table: one row per successful `kici-admin db backup`,
@@ -25211,12 +25412,12 @@ var _077_backup_runs_exports = /* @__PURE__ */ __exportAll({
25211
25412
  *
25212
25413
  * Idempotent: guarded on table existence.
25213
25414
  */
25214
- async function up$30(db) {
25415
+ async function up$31(db) {
25215
25416
  if (await tableExists$2(db, "backup_runs")) return;
25216
25417
  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();
25217
25418
  await db.schema.createIndex("idx_backup_runs_created_at").on("backup_runs").column("created_at").execute();
25218
25419
  }
25219
- async function down$30(db) {
25420
+ async function down$31(db) {
25220
25421
  await db.schema.dropTable("backup_runs").ifExists().execute();
25221
25422
  }
25222
25423
  async function tableExists$2(db, table) {
@@ -25231,8 +25432,8 @@ var init__077_backup_runs = __esmMin((() => {}));
25231
25432
  //#endregion
25232
25433
  //#region src/db/migrations/078_org_settings_backup_staleness.ts
25233
25434
  var _078_org_settings_backup_staleness_exports = /* @__PURE__ */ __exportAll({
25234
- down: () => down$29,
25235
- up: () => up$29
25435
+ down: () => down$30,
25436
+ up: () => up$30
25236
25437
  });
25237
25438
  /**
25238
25439
  * Add the nullable `org_settings.backup_staleness_warn_hours INTEGER` column:
@@ -25242,7 +25443,7 @@ var _078_org_settings_backup_staleness_exports = /* @__PURE__ */ __exportAll({
25242
25443
  *
25243
25444
  * Idempotent: guarded on column existence.
25244
25445
  */
25245
- async function up$29(db) {
25446
+ async function up$30(db) {
25246
25447
  if ((await sql`
25247
25448
  SELECT EXISTS (
25248
25449
  SELECT 1 FROM information_schema.columns
@@ -25256,7 +25457,7 @@ async function up$29(db) {
25256
25457
  ADD COLUMN backup_staleness_warn_hours INTEGER
25257
25458
  `.execute(db);
25258
25459
  }
25259
- async function down$29(db) {
25460
+ async function down$30(db) {
25260
25461
  await sql`
25261
25462
  ALTER TABLE public.org_settings DROP COLUMN IF EXISTS backup_staleness_warn_hours
25262
25463
  `.execute(db);
@@ -25265,8 +25466,8 @@ var init__078_org_settings_backup_staleness = __esmMin((() => {}));
25265
25466
  //#endregion
25266
25467
  //#region src/db/migrations/079_org_settings_scaler_spawn_timeout.ts
25267
25468
  var _079_org_settings_scaler_spawn_timeout_exports = /* @__PURE__ */ __exportAll({
25268
- down: () => down$28,
25269
- up: () => up$28
25469
+ down: () => down$29,
25470
+ up: () => up$29
25270
25471
  });
25271
25472
  /**
25272
25473
  * Add `org_settings.scaler_spawn_timeout_ms BIGINT` (nullable).
@@ -25278,7 +25479,7 @@ var _079_org_settings_scaler_spawn_timeout_exports = /* @__PURE__ */ __exportAll
25278
25479
  *
25279
25480
  * Idempotent: a re-run on a DB that already has the column is a no-op.
25280
25481
  */
25281
- async function up$28(db) {
25482
+ async function up$29(db) {
25282
25483
  if ((await sql`
25283
25484
  SELECT EXISTS (
25284
25485
  SELECT 1 FROM information_schema.columns
@@ -25292,7 +25493,7 @@ async function up$28(db) {
25292
25493
  ADD COLUMN scaler_spawn_timeout_ms BIGINT
25293
25494
  `.execute(db);
25294
25495
  }
25295
- async function down$28(db) {
25496
+ async function down$29(db) {
25296
25497
  await sql`
25297
25498
  ALTER TABLE public.org_settings DROP COLUMN IF EXISTS scaler_spawn_timeout_ms
25298
25499
  `.execute(db);
@@ -25301,8 +25502,8 @@ var init__079_org_settings_scaler_spawn_timeout = __esmMin((() => {}));
25301
25502
  //#endregion
25302
25503
  //#region src/db/migrations/080_cluster_settings.ts
25303
25504
  var _080_cluster_settings_exports = /* @__PURE__ */ __exportAll({
25304
- down: () => down$27,
25305
- up: () => up$27
25505
+ down: () => down$28,
25506
+ up: () => up$28
25306
25507
  });
25307
25508
  /**
25308
25509
  * Create `cluster_settings`: a single-row (id='default') table of fleet-wide
@@ -25317,7 +25518,7 @@ var _080_cluster_settings_exports = /* @__PURE__ */ __exportAll({
25317
25518
  *
25318
25519
  * Idempotent: a re-run on a DB that already has the table is a no-op.
25319
25520
  */
25320
- async function up$27(db) {
25521
+ async function up$28(db) {
25321
25522
  if ((await sql`
25322
25523
  SELECT EXISTS (
25323
25524
  SELECT 1 FROM information_schema.tables
@@ -25341,15 +25542,15 @@ async function up$27(db) {
25341
25542
  )
25342
25543
  `.execute(db);
25343
25544
  }
25344
- async function down$27(db) {
25545
+ async function down$28(db) {
25345
25546
  await sql`DROP TABLE IF EXISTS public.cluster_settings`.execute(db);
25346
25547
  }
25347
25548
  var init__080_cluster_settings = __esmMin((() => {}));
25348
25549
  //#endregion
25349
25550
  //#region src/db/migrations/081_org_settings_queue_timeout.ts
25350
25551
  var _081_org_settings_queue_timeout_exports = /* @__PURE__ */ __exportAll({
25351
- down: () => down$26,
25352
- up: () => up$26
25552
+ down: () => down$27,
25553
+ up: () => up$27
25353
25554
  });
25354
25555
  /**
25355
25556
  * Add `org_settings.queue_timeout_ms BIGINT` (nullable).
@@ -25366,7 +25567,7 @@ var _081_org_settings_queue_timeout_exports = /* @__PURE__ */ __exportAll({
25366
25567
  *
25367
25568
  * Idempotent: a re-run on a DB that already has the column is a no-op.
25368
25569
  */
25369
- async function up$26(db) {
25570
+ async function up$27(db) {
25370
25571
  if ((await sql`
25371
25572
  SELECT EXISTS (
25372
25573
  SELECT 1 FROM information_schema.columns
@@ -25380,7 +25581,7 @@ async function up$26(db) {
25380
25581
  ADD COLUMN queue_timeout_ms BIGINT
25381
25582
  `.execute(db);
25382
25583
  }
25383
- async function down$26(db) {
25584
+ async function down$27(db) {
25384
25585
  await sql`
25385
25586
  ALTER TABLE public.org_settings DROP COLUMN IF EXISTS queue_timeout_ms
25386
25587
  `.execute(db);
@@ -25389,8 +25590,8 @@ var init__081_org_settings_queue_timeout = __esmMin((() => {}));
25389
25590
  //#endregion
25390
25591
  //#region src/db/migrations/082_host_s3_reachable.ts
25391
25592
  var _082_host_s3_reachable_exports = /* @__PURE__ */ __exportAll({
25392
- down: () => down$25,
25393
- up: () => up$25
25593
+ down: () => down$26,
25594
+ up: () => up$26
25394
25595
  });
25395
25596
  /**
25396
25597
  * Add `host_roster.s3_reachable BOOLEAN` (nullable).
@@ -25404,7 +25605,7 @@ var _082_host_s3_reachable_exports = /* @__PURE__ */ __exportAll({
25404
25605
  *
25405
25606
  * Idempotent: a re-run on a DB that already has the column is a no-op.
25406
25607
  */
25407
- async function up$25(db) {
25608
+ async function up$26(db) {
25408
25609
  if ((await sql`
25409
25610
  SELECT EXISTS (
25410
25611
  SELECT 1 FROM information_schema.columns
@@ -25418,7 +25619,7 @@ async function up$25(db) {
25418
25619
  ADD COLUMN s3_reachable BOOLEAN
25419
25620
  `.execute(db);
25420
25621
  }
25421
- async function down$25(db) {
25622
+ async function down$26(db) {
25422
25623
  await sql`
25423
25624
  ALTER TABLE public.host_roster DROP COLUMN IF EXISTS s3_reachable
25424
25625
  `.execute(db);
@@ -25427,8 +25628,8 @@ var init__082_host_s3_reachable = __esmMin((() => {}));
25427
25628
  //#endregion
25428
25629
  //#region src/db/migrations/083_org_settings_artifact_caps.ts
25429
25630
  var _083_org_settings_artifact_caps_exports = /* @__PURE__ */ __exportAll({
25430
- down: () => down$24,
25431
- up: () => up$24
25631
+ down: () => down$25,
25632
+ up: () => up$25
25432
25633
  });
25433
25634
  /**
25434
25635
  * Add `org_settings.artifact_max_bytes` + `artifact_max_per_run` (both nullable
@@ -25444,7 +25645,7 @@ var _083_org_settings_artifact_caps_exports = /* @__PURE__ */ __exportAll({
25444
25645
  * Idempotent: guarded on column existence; a re-run on a DB that already has a
25445
25646
  * column is a no-op.
25446
25647
  */
25447
- async function up$24(db) {
25648
+ async function up$25(db) {
25448
25649
  for (const col of ["artifact_max_bytes", "artifact_max_per_run"]) {
25449
25650
  if ((await sql`
25450
25651
  SELECT EXISTS (
@@ -25457,7 +25658,7 @@ async function up$24(db) {
25457
25658
  await sql`ALTER TABLE public.org_settings ADD COLUMN ${sql.ref(col)} BIGINT`.execute(db);
25458
25659
  }
25459
25660
  }
25460
- async function down$24(db) {
25661
+ async function down$25(db) {
25461
25662
  await sql`ALTER TABLE public.org_settings DROP COLUMN IF EXISTS artifact_max_bytes`.execute(db);
25462
25663
  await sql`ALTER TABLE public.org_settings DROP COLUMN IF EXISTS artifact_max_per_run`.execute(db);
25463
25664
  }
@@ -25465,8 +25666,8 @@ var init__083_org_settings_artifact_caps = __esmMin((() => {}));
25465
25666
  //#endregion
25466
25667
  //#region src/db/migrations/084_orchestrator_signing_keys.ts
25467
25668
  var _084_orchestrator_signing_keys_exports = /* @__PURE__ */ __exportAll({
25468
- down: () => down$23,
25469
- up: () => up$23
25669
+ down: () => down$24,
25670
+ up: () => up$24
25470
25671
  });
25471
25672
  /**
25472
25673
  * Add the `orchestrator_signing_keys` table: the cluster-scoped, long-lived
@@ -25484,12 +25685,12 @@ var _084_orchestrator_signing_keys_exports = /* @__PURE__ */ __exportAll({
25484
25685
  *
25485
25686
  * Idempotent: guarded on table existence.
25486
25687
  */
25487
- async function up$23(db) {
25688
+ async function up$24(db) {
25488
25689
  if (await tableExists$1(db, "orchestrator_signing_keys")) return;
25489
25690
  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();
25490
25691
  await db.schema.createIndex("idx_orch_signing_keys_status").on("orchestrator_signing_keys").column("status").execute();
25491
25692
  }
25492
- async function down$23(db) {
25693
+ async function down$24(db) {
25493
25694
  await db.schema.dropTable("orchestrator_signing_keys").ifExists().execute();
25494
25695
  }
25495
25696
  async function tableExists$1(db, table) {
@@ -25504,8 +25705,8 @@ var init__084_orchestrator_signing_keys = __esmMin((() => {}));
25504
25705
  //#endregion
25505
25706
  //#region src/db/migrations/085_cluster_settings_reroute_flap_grace_ms.ts
25506
25707
  var _085_cluster_settings_reroute_flap_grace_ms_exports = /* @__PURE__ */ __exportAll({
25507
- down: () => down$22,
25508
- up: () => up$22
25708
+ down: () => down$23,
25709
+ up: () => up$23
25509
25710
  });
25510
25711
  /**
25511
25712
  * Add `cluster_settings.reroute_flap_grace_ms` (nullable BIGINT).
@@ -25515,7 +25716,7 @@ var _085_cluster_settings_reroute_flap_grace_ms_exports = /* @__PURE__ */ __expo
25515
25716
  * Idempotent: guarded on column existence; a re-run on a DB that already has
25516
25717
  * the column is a no-op.
25517
25718
  */
25518
- async function up$22(db) {
25719
+ async function up$23(db) {
25519
25720
  if ((await sql`
25520
25721
  SELECT EXISTS (
25521
25722
  SELECT 1 FROM information_schema.columns
@@ -25526,15 +25727,15 @@ async function up$22(db) {
25526
25727
  `.execute(db)).rows[0]?.exists) return;
25527
25728
  await sql`ALTER TABLE public.cluster_settings ADD COLUMN reroute_flap_grace_ms BIGINT`.execute(db);
25528
25729
  }
25529
- async function down$22(db) {
25730
+ async function down$23(db) {
25530
25731
  await sql`ALTER TABLE public.cluster_settings DROP COLUMN IF EXISTS reroute_flap_grace_ms`.execute(db);
25531
25732
  }
25532
25733
  var init__085_cluster_settings_reroute_flap_grace_ms = __esmMin((() => {}));
25533
25734
  //#endregion
25534
25735
  //#region src/db/migrations/086_cluster_settings_max_fanout_hosts.ts
25535
25736
  var _086_cluster_settings_max_fanout_hosts_exports = /* @__PURE__ */ __exportAll({
25536
- down: () => down$21,
25537
- up: () => up$21
25737
+ down: () => down$22,
25738
+ up: () => up$22
25538
25739
  });
25539
25740
  /**
25540
25741
  * Add `cluster_settings.max_fanout_hosts` (nullable INTEGER).
@@ -25544,7 +25745,7 @@ var _086_cluster_settings_max_fanout_hosts_exports = /* @__PURE__ */ __exportAll
25544
25745
  * Idempotent: guarded on column existence; a re-run on a DB that already has
25545
25746
  * the column is a no-op.
25546
25747
  */
25547
- async function up$21(db) {
25748
+ async function up$22(db) {
25548
25749
  if ((await sql`
25549
25750
  SELECT EXISTS (
25550
25751
  SELECT 1 FROM information_schema.columns
@@ -25555,15 +25756,15 @@ async function up$21(db) {
25555
25756
  `.execute(db)).rows[0]?.exists) return;
25556
25757
  await sql`ALTER TABLE public.cluster_settings ADD COLUMN max_fanout_hosts INTEGER`.execute(db);
25557
25758
  }
25558
- async function down$21(db) {
25759
+ async function down$22(db) {
25559
25760
  await sql`ALTER TABLE public.cluster_settings DROP COLUMN IF EXISTS max_fanout_hosts`.execute(db);
25560
25761
  }
25561
25762
  var init__086_cluster_settings_max_fanout_hosts = __esmMin((() => {}));
25562
25763
  //#endregion
25563
25764
  //#region src/db/migrations/087_cluster_settings_event_router_rate_limit.ts
25564
25765
  var _087_cluster_settings_event_router_rate_limit_exports = /* @__PURE__ */ __exportAll({
25565
- down: () => down$20,
25566
- up: () => up$20
25766
+ down: () => down$21,
25767
+ up: () => up$21
25567
25768
  });
25568
25769
  /**
25569
25770
  * Add `cluster_settings.event_router_rate_limit_per_workflow_per_minute` (nullable INTEGER).
@@ -25573,7 +25774,7 @@ var _087_cluster_settings_event_router_rate_limit_exports = /* @__PURE__ */ __ex
25573
25774
  * Idempotent: guarded on column existence; a re-run on a DB that already has
25574
25775
  * the column is a no-op.
25575
25776
  */
25576
- async function up$20(db) {
25777
+ async function up$21(db) {
25577
25778
  if ((await sql`
25578
25779
  SELECT EXISTS (
25579
25780
  SELECT 1 FROM information_schema.columns
@@ -25584,15 +25785,15 @@ async function up$20(db) {
25584
25785
  `.execute(db)).rows[0]?.exists) return;
25585
25786
  await sql`ALTER TABLE public.cluster_settings ADD COLUMN event_router_rate_limit_per_workflow_per_minute INTEGER`.execute(db);
25586
25787
  }
25587
- async function down$20(db) {
25788
+ async function down$21(db) {
25588
25789
  await sql`ALTER TABLE public.cluster_settings DROP COLUMN IF EXISTS event_router_rate_limit_per_workflow_per_minute`.execute(db);
25589
25790
  }
25590
25791
  var init__087_cluster_settings_event_router_rate_limit = __esmMin((() => {}));
25591
25792
  //#endregion
25592
25793
  //#region src/db/migrations/088_cluster_settings_cache_max_tarball_bytes.ts
25593
25794
  var _088_cluster_settings_cache_max_tarball_bytes_exports = /* @__PURE__ */ __exportAll({
25594
- down: () => down$19,
25595
- up: () => up$19
25795
+ down: () => down$20,
25796
+ up: () => up$20
25596
25797
  });
25597
25798
  /**
25598
25799
  * Add `cluster_settings.cache_max_tarball_bytes` (nullable BIGINT).
@@ -25602,7 +25803,7 @@ var _088_cluster_settings_cache_max_tarball_bytes_exports = /* @__PURE__ */ __ex
25602
25803
  * Idempotent: guarded on column existence; a re-run on a DB that already has
25603
25804
  * the column is a no-op.
25604
25805
  */
25605
- async function up$19(db) {
25806
+ async function up$20(db) {
25606
25807
  if ((await sql`
25607
25808
  SELECT EXISTS (
25608
25809
  SELECT 1 FROM information_schema.columns
@@ -25613,15 +25814,15 @@ async function up$19(db) {
25613
25814
  `.execute(db)).rows[0]?.exists) return;
25614
25815
  await sql`ALTER TABLE public.cluster_settings ADD COLUMN cache_max_tarball_bytes BIGINT`.execute(db);
25615
25816
  }
25616
- async function down$19(db) {
25817
+ async function down$20(db) {
25617
25818
  await sql`ALTER TABLE public.cluster_settings DROP COLUMN IF EXISTS cache_max_tarball_bytes`.execute(db);
25618
25819
  }
25619
25820
  var init__088_cluster_settings_cache_max_tarball_bytes = __esmMin((() => {}));
25620
25821
  //#endregion
25621
25822
  //#region src/db/migrations/089_cluster_settings_cache_ttl_days.ts
25622
25823
  var _089_cluster_settings_cache_ttl_days_exports = /* @__PURE__ */ __exportAll({
25623
- down: () => down$18,
25624
- up: () => up$18
25824
+ down: () => down$19,
25825
+ up: () => up$19
25625
25826
  });
25626
25827
  /**
25627
25828
  * Add `cluster_settings.cache_ttl_days` (nullable INTEGER).
@@ -25631,7 +25832,7 @@ var _089_cluster_settings_cache_ttl_days_exports = /* @__PURE__ */ __exportAll({
25631
25832
  * Idempotent: guarded on column existence; a re-run on a DB that already has
25632
25833
  * the column is a no-op.
25633
25834
  */
25634
- async function up$18(db) {
25835
+ async function up$19(db) {
25635
25836
  if ((await sql`
25636
25837
  SELECT EXISTS (
25637
25838
  SELECT 1 FROM information_schema.columns
@@ -25642,15 +25843,15 @@ async function up$18(db) {
25642
25843
  `.execute(db)).rows[0]?.exists) return;
25643
25844
  await sql`ALTER TABLE public.cluster_settings ADD COLUMN cache_ttl_days INTEGER`.execute(db);
25644
25845
  }
25645
- async function down$18(db) {
25846
+ async function down$19(db) {
25646
25847
  await sql`ALTER TABLE public.cluster_settings DROP COLUMN IF EXISTS cache_ttl_days`.execute(db);
25647
25848
  }
25648
25849
  var init__089_cluster_settings_cache_ttl_days = __esmMin((() => {}));
25649
25850
  //#endregion
25650
25851
  //#region src/db/migrations/090_cluster_settings_concurrency_wait_timeout_ms.ts
25651
25852
  var _090_cluster_settings_concurrency_wait_timeout_ms_exports = /* @__PURE__ */ __exportAll({
25652
- down: () => down$17,
25653
- up: () => up$17
25853
+ down: () => down$18,
25854
+ up: () => up$18
25654
25855
  });
25655
25856
  /**
25656
25857
  * Add `cluster_settings.concurrency_wait_timeout_ms` (nullable BIGINT).
@@ -25660,7 +25861,7 @@ var _090_cluster_settings_concurrency_wait_timeout_ms_exports = /* @__PURE__ */
25660
25861
  * Idempotent: guarded on column existence; a re-run on a DB that already has
25661
25862
  * the column is a no-op.
25662
25863
  */
25663
- async function up$17(db) {
25864
+ async function up$18(db) {
25664
25865
  if ((await sql`
25665
25866
  SELECT EXISTS (
25666
25867
  SELECT 1 FROM information_schema.columns
@@ -25671,15 +25872,15 @@ async function up$17(db) {
25671
25872
  `.execute(db)).rows[0]?.exists) return;
25672
25873
  await sql`ALTER TABLE public.cluster_settings ADD COLUMN concurrency_wait_timeout_ms BIGINT`.execute(db);
25673
25874
  }
25674
- async function down$17(db) {
25875
+ async function down$18(db) {
25675
25876
  await sql`ALTER TABLE public.cluster_settings DROP COLUMN IF EXISTS concurrency_wait_timeout_ms`.execute(db);
25676
25877
  }
25677
25878
  var init__090_cluster_settings_concurrency_wait_timeout_ms = __esmMin((() => {}));
25678
25879
  //#endregion
25679
25880
  //#region src/db/migrations/091_cluster_settings_agent_token_ttl_ms.ts
25680
25881
  var _091_cluster_settings_agent_token_ttl_ms_exports = /* @__PURE__ */ __exportAll({
25681
- down: () => down$16,
25682
- up: () => up$16
25882
+ down: () => down$17,
25883
+ up: () => up$17
25683
25884
  });
25684
25885
  /**
25685
25886
  * Add `cluster_settings.agent_token_ttl_ms` (nullable BIGINT).
@@ -25689,7 +25890,7 @@ var _091_cluster_settings_agent_token_ttl_ms_exports = /* @__PURE__ */ __exportA
25689
25890
  * Idempotent: guarded on column existence; a re-run on a DB that already has
25690
25891
  * the column is a no-op.
25691
25892
  */
25692
- async function up$16(db) {
25893
+ async function up$17(db) {
25693
25894
  if ((await sql`
25694
25895
  SELECT EXISTS (
25695
25896
  SELECT 1 FROM information_schema.columns
@@ -25700,15 +25901,15 @@ async function up$16(db) {
25700
25901
  `.execute(db)).rows[0]?.exists) return;
25701
25902
  await sql`ALTER TABLE public.cluster_settings ADD COLUMN agent_token_ttl_ms BIGINT`.execute(db);
25702
25903
  }
25703
- async function down$16(db) {
25904
+ async function down$17(db) {
25704
25905
  await sql`ALTER TABLE public.cluster_settings DROP COLUMN IF EXISTS agent_token_ttl_ms`.execute(db);
25705
25906
  }
25706
25907
  var init__091_cluster_settings_agent_token_ttl_ms = __esmMin((() => {}));
25707
25908
  //#endregion
25708
25909
  //#region src/db/migrations/092_cluster_settings_version.ts
25709
25910
  var _092_cluster_settings_version_exports = /* @__PURE__ */ __exportAll({
25710
- down: () => down$15,
25711
- up: () => up$15
25911
+ down: () => down$16,
25912
+ up: () => up$16
25712
25913
  });
25713
25914
  /**
25714
25915
  * Add `cluster_settings.version` (monotonic BIGINT, bumped on each settings
@@ -25722,7 +25923,7 @@ var _092_cluster_settings_version_exports = /* @__PURE__ */ __exportAll({
25722
25923
  * Idempotent: guarded on column existence; a re-run on a DB that already has
25723
25924
  * the column is a no-op.
25724
25925
  */
25725
- async function up$15(db) {
25926
+ async function up$16(db) {
25726
25927
  if ((await sql`
25727
25928
  SELECT EXISTS (
25728
25929
  SELECT 1 FROM information_schema.columns
@@ -25733,15 +25934,15 @@ async function up$15(db) {
25733
25934
  `.execute(db)).rows[0]?.exists) return;
25734
25935
  await sql`ALTER TABLE public.cluster_settings ADD COLUMN version BIGINT NOT NULL DEFAULT 0`.execute(db);
25735
25936
  }
25736
- async function down$15(db) {
25937
+ async function down$16(db) {
25737
25938
  await sql`ALTER TABLE public.cluster_settings DROP COLUMN IF EXISTS version`.execute(db);
25738
25939
  }
25739
25940
  var init__092_cluster_settings_version = __esmMin((() => {}));
25740
25941
  //#endregion
25741
25942
  //#region src/db/migrations/093_org_settings_sandbox_allowlist.ts
25742
25943
  var _093_org_settings_sandbox_allowlist_exports = /* @__PURE__ */ __exportAll({
25743
- down: () => down$14,
25744
- up: () => up$14
25944
+ down: () => down$15,
25945
+ up: () => up$15
25745
25946
  });
25746
25947
  /**
25747
25948
  * Add the per-org container-sandbox escape-hatch allow-list to `org_settings`:
@@ -25759,7 +25960,7 @@ var _093_org_settings_sandbox_allowlist_exports = /* @__PURE__ */ __exportAll({
25759
25960
  *
25760
25961
  * Idempotent: a re-run on a DB that already has a column skips that column.
25761
25962
  */
25762
- async function columnExists$3(db, column) {
25963
+ async function columnExists$4(db, column) {
25763
25964
  return (await sql`
25764
25965
  SELECT EXISTS (
25765
25966
  SELECT 1 FROM information_schema.columns
@@ -25769,17 +25970,17 @@ async function columnExists$3(db, column) {
25769
25970
  ) AS exists
25770
25971
  `.execute(db)).rows[0]?.exists ?? false;
25771
25972
  }
25772
- async function up$14(db) {
25773
- if (!await columnExists$3(db, "sandbox_allowed_capabilities")) await sql`
25973
+ async function up$15(db) {
25974
+ if (!await columnExists$4(db, "sandbox_allowed_capabilities")) await sql`
25774
25975
  ALTER TABLE public.org_settings
25775
25976
  ADD COLUMN sandbox_allowed_capabilities TEXT[]
25776
25977
  `.execute(db);
25777
- if (!await columnExists$3(db, "sandbox_allow_host_network")) await sql`
25978
+ if (!await columnExists$4(db, "sandbox_allow_host_network")) await sql`
25778
25979
  ALTER TABLE public.org_settings
25779
25980
  ADD COLUMN sandbox_allow_host_network BOOLEAN
25780
25981
  `.execute(db);
25781
25982
  }
25782
- async function down$14(db) {
25983
+ async function down$15(db) {
25783
25984
  await sql`
25784
25985
  ALTER TABLE public.org_settings DROP COLUMN IF EXISTS sandbox_allowed_capabilities
25785
25986
  `.execute(db);
@@ -25791,8 +25992,8 @@ var init__093_org_settings_sandbox_allowlist = __esmMin((() => {}));
25791
25992
  //#endregion
25792
25993
  //#region src/db/migrations/094_dashboard_encryption_keys.ts
25793
25994
  var _094_dashboard_encryption_keys_exports = /* @__PURE__ */ __exportAll({
25794
- down: () => down$13,
25795
- up: () => up$13
25995
+ down: () => down$14,
25996
+ up: () => up$14
25796
25997
  });
25797
25998
  /**
25798
25999
  * Add the `dashboard_encryption_keys` table: the cluster-scoped, long-lived
@@ -25811,12 +26012,12 @@ var _094_dashboard_encryption_keys_exports = /* @__PURE__ */ __exportAll({
25811
26012
  *
25812
26013
  * Idempotent: guarded on table existence.
25813
26014
  */
25814
- async function up$13(db) {
26015
+ async function up$14(db) {
25815
26016
  if (await tableExists(db, "dashboard_encryption_keys")) return;
25816
26017
  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();
25817
26018
  await db.schema.createIndex("idx_dashboard_encryption_keys_status").on("dashboard_encryption_keys").column("status").execute();
25818
26019
  }
25819
- async function down$13(db) {
26020
+ async function down$14(db) {
25820
26021
  await db.schema.dropTable("dashboard_encryption_keys").ifExists().execute();
25821
26022
  }
25822
26023
  async function tableExists(db, table) {
@@ -25831,8 +26032,8 @@ var init__094_dashboard_encryption_keys = __esmMin((() => {}));
25831
26032
  //#endregion
25832
26033
  //#region src/db/migrations/095_dashboard_write_policy_tristate.ts
25833
26034
  var _095_dashboard_write_policy_tristate_exports = /* @__PURE__ */ __exportAll({
25834
- down: () => down$12,
25835
- up: () => up$12
26035
+ down: () => down$13,
26036
+ up: () => up$13
25836
26037
  });
25837
26038
  /**
25838
26039
  * Migrate stored `org_settings.dashboard_write_policy` JSONB from the legacy
@@ -25850,7 +26051,7 @@ var _095_dashboard_write_policy_tristate_exports = /* @__PURE__ */ __exportAll({
25850
26051
  * Pure SQL rewrite: for each row, rebuild the object keeping only non-`true`
25851
26052
  * entries and mapping `false` → `'disabled'`, leaving existing string values.
25852
26053
  */
25853
- async function up$12(db) {
26054
+ async function up$13(db) {
25854
26055
  await sql`
25855
26056
  UPDATE org_settings
25856
26057
  SET dashboard_write_policy = COALESCE(
@@ -25877,13 +26078,13 @@ async function up$12(db) {
25877
26078
  )
25878
26079
  `.execute(db);
25879
26080
  }
25880
- async function down$12() {}
26081
+ async function down$13() {}
25881
26082
  var init__095_dashboard_write_policy_tristate = __esmMin((() => {}));
25882
26083
  //#endregion
25883
26084
  //#region src/db/migrations/096_multi_schedule_cron_last_fired.ts
25884
26085
  var _096_multi_schedule_cron_last_fired_exports = /* @__PURE__ */ __exportAll({
25885
- down: () => down$11,
25886
- up: () => up$11
26086
+ down: () => down$12,
26087
+ up: () => up$12
25887
26088
  });
25888
26089
  /**
25889
26090
  * Track cron last-fired per (registration, schedule) instead of per
@@ -25898,7 +26099,7 @@ var _096_multi_schedule_cron_last_fired_exports = /* @__PURE__ */ __exportAll({
25898
26099
  *
25899
26100
  * Idempotent: re-running on an already-migrated DB skips each step.
25900
26101
  */
25901
- async function columnExists$2(db, column) {
26102
+ async function columnExists$3(db, column) {
25902
26103
  return (await sql`
25903
26104
  SELECT EXISTS (
25904
26105
  SELECT 1 FROM information_schema.columns
@@ -25918,8 +26119,8 @@ async function primaryKeyColumns(db) {
25918
26119
  ORDER BY a.attnum
25919
26120
  `.execute(db)).rows.map((row) => row.attname);
25920
26121
  }
25921
- async function up$11(db) {
25922
- if (!await columnExists$2(db, "schedule_key")) await sql`ALTER TABLE public.cron_last_fired ADD COLUMN schedule_key text`.execute(db);
26122
+ async function up$12(db) {
26123
+ if (!await columnExists$3(db, "schedule_key")) await sql`ALTER TABLE public.cron_last_fired ADD COLUMN schedule_key text`.execute(db);
25923
26124
  await sql`
25924
26125
  UPDATE public.cron_last_fired clf
25925
26126
  SET schedule_key = k.key
@@ -25945,7 +26146,7 @@ async function up$11(db) {
25945
26146
  `.execute(db);
25946
26147
  }
25947
26148
  }
25948
- async function down$11(db) {
26149
+ async function down$12(db) {
25949
26150
  await sql`
25950
26151
  DELETE FROM public.cron_last_fired a
25951
26152
  USING public.cron_last_fired b
@@ -25957,14 +26158,14 @@ async function down$11(db) {
25957
26158
  ALTER TABLE public.cron_last_fired
25958
26159
  ADD CONSTRAINT cron_last_fired_pkey PRIMARY KEY (registration_id)
25959
26160
  `.execute(db);
25960
- if (await columnExists$2(db, "schedule_key")) await sql`ALTER TABLE public.cron_last_fired DROP COLUMN schedule_key`.execute(db);
26161
+ if (await columnExists$3(db, "schedule_key")) await sql`ALTER TABLE public.cron_last_fired DROP COLUMN schedule_key`.execute(db);
25961
26162
  }
25962
26163
  var init__096_multi_schedule_cron_last_fired = __esmMin((() => {}));
25963
26164
  //#endregion
25964
26165
  //#region src/db/migrations/097_execution_runs_pr_number.ts
25965
26166
  var _097_execution_runs_pr_number_exports = /* @__PURE__ */ __exportAll({
25966
- down: () => down$10,
25967
- up: () => up$10
26167
+ down: () => down$11,
26168
+ up: () => up$11
25968
26169
  });
25969
26170
  /**
25970
26171
  * Add `pr_number INTEGER NULL` to `execution_runs`.
@@ -25977,7 +26178,7 @@ var _097_execution_runs_pr_number_exports = /* @__PURE__ */ __exportAll({
25977
26178
  *
25978
26179
  * Idempotent: a re-run on a DB that already has the column is a no-op.
25979
26180
  */
25980
- async function columnExists$1(db, column) {
26181
+ async function columnExists$2(db, column) {
25981
26182
  return (await sql`
25982
26183
  SELECT EXISTS (
25983
26184
  SELECT 1 FROM information_schema.columns
@@ -25987,13 +26188,13 @@ async function columnExists$1(db, column) {
25987
26188
  ) AS exists
25988
26189
  `.execute(db)).rows[0]?.exists ?? false;
25989
26190
  }
25990
- async function up$10(db) {
25991
- if (!await columnExists$1(db, "pr_number")) await sql`
26191
+ async function up$11(db) {
26192
+ if (!await columnExists$2(db, "pr_number")) await sql`
25992
26193
  ALTER TABLE public.execution_runs
25993
26194
  ADD COLUMN pr_number INTEGER
25994
26195
  `.execute(db);
25995
26196
  }
25996
- async function down$10(db) {
26197
+ async function down$11(db) {
25997
26198
  await sql`
25998
26199
  ALTER TABLE public.execution_runs DROP COLUMN IF EXISTS pr_number
25999
26200
  `.execute(db);
@@ -26002,8 +26203,8 @@ var init__097_execution_runs_pr_number = __esmMin((() => {}));
26002
26203
  //#endregion
26003
26204
  //#region src/db/migrations/098_execution_runs_customer_id.ts
26004
26205
  var _098_execution_runs_customer_id_exports = /* @__PURE__ */ __exportAll({
26005
- down: () => down$9,
26006
- up: () => up$9
26206
+ down: () => down$10,
26207
+ up: () => up$10
26007
26208
  });
26008
26209
  /**
26009
26210
  * Denormalize the owning org onto `execution_runs` so the concurrency-gate
@@ -26021,7 +26222,7 @@ var _098_execution_runs_customer_id_exports = /* @__PURE__ */ __exportAll({
26021
26222
  *
26022
26223
  * Idempotent: re-running skips the column when it already exists.
26023
26224
  */
26024
- async function columnExists(db, column) {
26225
+ async function columnExists$1(db, column) {
26025
26226
  return (await sql`
26026
26227
  SELECT EXISTS (
26027
26228
  SELECT 1 FROM information_schema.columns
@@ -26031,8 +26232,8 @@ async function columnExists(db, column) {
26031
26232
  ) AS exists
26032
26233
  `.execute(db)).rows[0]?.exists ?? false;
26033
26234
  }
26034
- async function up$9(db) {
26035
- if (!await columnExists(db, "customer_id")) {
26235
+ async function up$10(db) {
26236
+ if (!await columnExists$1(db, "customer_id")) {
26036
26237
  await sql`
26037
26238
  ALTER TABLE public.execution_runs
26038
26239
  ADD COLUMN customer_id TEXT NOT NULL DEFAULT '__default__'
@@ -26055,7 +26256,7 @@ async function up$9(db) {
26055
26256
  ON public.execution_runs (customer_id, context)
26056
26257
  `.execute(db);
26057
26258
  }
26058
- async function down$9(db) {
26259
+ async function down$10(db) {
26059
26260
  await sql`DROP INDEX IF EXISTS execution_runs_customer_id_context_idx`.execute(db);
26060
26261
  await sql`
26061
26262
  ALTER TABLE public.execution_runs DROP COLUMN IF EXISTS customer_id
@@ -26065,8 +26266,8 @@ var init__098_execution_runs_customer_id = __esmMin((() => {}));
26065
26266
  //#endregion
26066
26267
  //#region src/db/migrations/099_cluster_settings_dashboard_verified_issuer.ts
26067
26268
  var _099_cluster_settings_dashboard_verified_issuer_exports = /* @__PURE__ */ __exportAll({
26068
- down: () => down$8,
26069
- up: () => up$8
26269
+ down: () => down$9,
26270
+ up: () => up$9
26070
26271
  });
26071
26272
  /**
26072
26273
  * Add `cluster_settings.dashboard_verified_issuer` (nullable text).
@@ -26085,7 +26286,7 @@ var _099_cluster_settings_dashboard_verified_issuer_exports = /* @__PURE__ */ __
26085
26286
  * Idempotent: guarded on column existence; a re-run on a DB that already has the
26086
26287
  * column is a no-op.
26087
26288
  */
26088
- async function up$8(db) {
26289
+ async function up$9(db) {
26089
26290
  if ((await sql`
26090
26291
  SELECT EXISTS (
26091
26292
  SELECT 1 FROM information_schema.columns
@@ -26096,15 +26297,15 @@ async function up$8(db) {
26096
26297
  `.execute(db)).rows[0]?.exists) return;
26097
26298
  await sql`ALTER TABLE public.cluster_settings ADD COLUMN dashboard_verified_issuer TEXT`.execute(db);
26098
26299
  }
26099
- async function down$8(db) {
26300
+ async function down$9(db) {
26100
26301
  await sql`ALTER TABLE public.cluster_settings DROP COLUMN IF EXISTS dashboard_verified_issuer`.execute(db);
26101
26302
  }
26102
26303
  var init__099_cluster_settings_dashboard_verified_issuer = __esmMin((() => {}));
26103
26304
  //#endregion
26104
26305
  //#region src/db/migrations/100_held_runs_hold_type_vocabulary.ts
26105
26306
  var _100_held_runs_hold_type_vocabulary_exports = /* @__PURE__ */ __exportAll({
26106
- down: () => down$7,
26107
- up: () => up$7
26307
+ down: () => down$8,
26308
+ up: () => up$8
26108
26309
  });
26109
26310
  /**
26110
26311
  * Realign `held_runs.hold_type` onto the engine's `HoldType` vocabulary.
@@ -26123,7 +26324,7 @@ var _100_held_runs_hold_type_vocabulary_exports = /* @__PURE__ */ __exportAll({
26123
26324
  *
26124
26325
  * Idempotent: a second run matches no rows.
26125
26326
  */
26126
- async function up$7(db) {
26327
+ async function up$8(db) {
26127
26328
  await sql`UPDATE public.held_runs SET hold_type = 'reviewer' WHERE hold_type = 'approval'`.execute(db);
26128
26329
  await sql`UPDATE public.held_runs SET hold_type = 'timer' WHERE hold_type = 'wait_timer'`.execute(db);
26129
26330
  }
@@ -26137,7 +26338,7 @@ async function up$7(db) {
26137
26338
  * `wait_timer` alone, so leaving those rows spelled `timer` would strand them
26138
26339
  * in the expire-and-fail path.
26139
26340
  */
26140
- async function down$7(db) {
26341
+ async function down$8(db) {
26141
26342
  await sql`UPDATE public.held_runs SET hold_type = 'approval' WHERE hold_type = 'reviewer'`.execute(db);
26142
26343
  await sql`UPDATE public.held_runs SET hold_type = 'wait_timer' WHERE hold_type = 'timer'`.execute(db);
26143
26344
  }
@@ -26145,8 +26346,8 @@ var init__100_held_runs_hold_type_vocabulary = __esmMin((() => {}));
26145
26346
  //#endregion
26146
26347
  //#region src/db/migrations/101_contexts_hold_expiry_drop_default.ts
26147
26348
  var _101_contexts_hold_expiry_drop_default_exports = /* @__PURE__ */ __exportAll({
26148
- down: () => down$6,
26149
- up: () => up$6
26349
+ down: () => down$7,
26350
+ up: () => up$7
26150
26351
  });
26151
26352
  /**
26152
26353
  * Give the context hold expiry a single default, and retire the stored zeroes.
@@ -26167,7 +26368,7 @@ var _101_contexts_hold_expiry_drop_default_exports = /* @__PURE__ */ __exportAll
26167
26368
  * Idempotent: dropping an absent default is a no-op and the UPDATE matches no
26168
26369
  * rows on a second run.
26169
26370
  */
26170
- async function up$6(db) {
26371
+ async function up$7(db) {
26171
26372
  await sql`ALTER TABLE public.contexts ALTER COLUMN hold_expiry_seconds DROP DEFAULT`.execute(db);
26172
26373
  await sql`UPDATE public.contexts SET hold_expiry_seconds = NULL WHERE hold_expiry_seconds = 0`.execute(db);
26173
26374
  }
@@ -26179,15 +26380,15 @@ async function up$6(db) {
26179
26380
  * back to `0` would resume cancelling every hold on its context — so a
26180
26381
  * rollback keeps them on the fallback rather than re-breaking them.
26181
26382
  */
26182
- async function down$6(db) {
26383
+ async function down$7(db) {
26183
26384
  await sql`ALTER TABLE public.contexts ALTER COLUMN hold_expiry_seconds SET DEFAULT 86400`.execute(db);
26184
26385
  }
26185
26386
  var init__101_contexts_hold_expiry_drop_default = __esmMin((() => {}));
26186
26387
  //#endregion
26187
26388
  //#region src/db/migrations/102_dispatch_queue_agent_id.ts
26188
26389
  var _102_dispatch_queue_agent_id_exports = /* @__PURE__ */ __exportAll({
26189
- down: () => down$5,
26190
- up: () => up$5
26390
+ down: () => down$6,
26391
+ up: () => up$6
26191
26392
  });
26192
26393
  /**
26193
26394
  * Add `dispatch_queue.agent_id` (nullable text).
@@ -26205,7 +26406,7 @@ var _102_dispatch_queue_agent_id_exports = /* @__PURE__ */ __exportAll({
26205
26406
  * Idempotent: guarded on column existence; a re-run on a DB that already has the
26206
26407
  * column is a no-op.
26207
26408
  */
26208
- async function up$5(db) {
26409
+ async function up$6(db) {
26209
26410
  if ((await sql`
26210
26411
  SELECT EXISTS (
26211
26412
  SELECT 1 FROM information_schema.columns
@@ -26216,15 +26417,15 @@ async function up$5(db) {
26216
26417
  `.execute(db)).rows[0]?.exists) return;
26217
26418
  await sql`ALTER TABLE public.dispatch_queue ADD COLUMN agent_id TEXT`.execute(db);
26218
26419
  }
26219
- async function down$5(db) {
26420
+ async function down$6(db) {
26220
26421
  await sql`ALTER TABLE public.dispatch_queue DROP COLUMN IF EXISTS agent_id`.execute(db);
26221
26422
  }
26222
26423
  var init__102_dispatch_queue_agent_id = __esmMin((() => {}));
26223
26424
  //#endregion
26224
26425
  //#region src/db/migrations/103_cluster_settings_ownership_db_check_timeout_ms.ts
26225
26426
  var _103_cluster_settings_ownership_db_check_timeout_ms_exports = /* @__PURE__ */ __exportAll({
26226
- down: () => down$4,
26227
- up: () => up$4
26427
+ down: () => down$5,
26428
+ up: () => up$5
26228
26429
  });
26229
26430
  /**
26230
26431
  * Add `cluster_settings.ownership_db_check_timeout_ms` (nullable bigint).
@@ -26242,7 +26443,7 @@ var _103_cluster_settings_ownership_db_check_timeout_ms_exports = /* @__PURE__ *
26242
26443
  * Idempotent: guarded on column existence; a re-run on a DB that already has the
26243
26444
  * column is a no-op.
26244
26445
  */
26245
- async function up$4(db) {
26446
+ async function up$5(db) {
26246
26447
  if ((await sql`
26247
26448
  SELECT EXISTS (
26248
26449
  SELECT 1 FROM information_schema.columns
@@ -26253,15 +26454,15 @@ async function up$4(db) {
26253
26454
  `.execute(db)).rows[0]?.exists) return;
26254
26455
  await sql`ALTER TABLE public.cluster_settings ADD COLUMN ownership_db_check_timeout_ms BIGINT`.execute(db);
26255
26456
  }
26256
- async function down$4(db) {
26457
+ async function down$5(db) {
26257
26458
  await sql`ALTER TABLE public.cluster_settings DROP COLUMN IF EXISTS ownership_db_check_timeout_ms`.execute(db);
26258
26459
  }
26259
26460
  var init__103_cluster_settings_ownership_db_check_timeout_ms = __esmMin((() => {}));
26260
26461
  //#endregion
26261
26462
  //#region src/db/migrations/104_check_run_terminal_sent.ts
26262
26463
  var _104_check_run_terminal_sent_exports = /* @__PURE__ */ __exportAll({
26263
- down: () => down$3,
26264
- up: () => up$3
26464
+ down: () => down$4,
26465
+ up: () => up$4
26265
26466
  });
26266
26467
  /**
26267
26468
  * Add `check_run_tracking.terminal_sent_at` (nullable timestamptz).
@@ -26281,7 +26482,7 @@ var _104_check_run_terminal_sent_exports = /* @__PURE__ */ __exportAll({
26281
26482
  * Idempotent: guarded on column existence; a re-run on a DB that already has
26282
26483
  * the column is a no-op.
26283
26484
  */
26284
- async function up$3(db) {
26485
+ async function up$4(db) {
26285
26486
  if ((await sql`
26286
26487
  SELECT EXISTS (
26287
26488
  SELECT 1 FROM information_schema.columns
@@ -26292,15 +26493,15 @@ async function up$3(db) {
26292
26493
  `.execute(db)).rows[0]?.exists) return;
26293
26494
  await sql`ALTER TABLE public.check_run_tracking ADD COLUMN terminal_sent_at TIMESTAMPTZ`.execute(db);
26294
26495
  }
26295
- async function down$3(db) {
26496
+ async function down$4(db) {
26296
26497
  await sql`ALTER TABLE public.check_run_tracking DROP COLUMN IF EXISTS terminal_sent_at`.execute(db);
26297
26498
  }
26298
26499
  var init__104_check_run_terminal_sent = __esmMin((() => {}));
26299
26500
  //#endregion
26300
26501
  //#region src/db/migrations/105_org_trust_policy.ts
26301
26502
  var _105_org_trust_policy_exports = /* @__PURE__ */ __exportAll({
26302
- down: () => down$2,
26303
- up: () => up$2
26503
+ down: () => down$3,
26504
+ up: () => up$3
26304
26505
  });
26305
26506
  /**
26306
26507
  * Create `org_trust_policy` — the orchestrator's cache of the Platform-owned org
@@ -26317,7 +26518,7 @@ var _105_org_trust_policy_exports = /* @__PURE__ */ __exportAll({
26317
26518
  *
26318
26519
  * Idempotent: guarded by IF NOT EXISTS, so a re-run is a no-op.
26319
26520
  */
26320
- async function up$2(db) {
26521
+ async function up$3(db) {
26321
26522
  await sql`
26322
26523
  CREATE TABLE IF NOT EXISTS public.org_trust_policy (
26323
26524
  customer_id TEXT PRIMARY KEY,
@@ -26330,15 +26531,15 @@ async function up$2(db) {
26330
26531
  )
26331
26532
  `.execute(db);
26332
26533
  }
26333
- async function down$2(db) {
26534
+ async function down$3(db) {
26334
26535
  await sql`DROP TABLE IF EXISTS public.org_trust_policy`.execute(db);
26335
26536
  }
26336
26537
  var init__105_org_trust_policy = __esmMin((() => {}));
26337
26538
  //#endregion
26338
26539
  //#region src/db/migrations/106_cluster_settings_check_run_tracking_ttl_days.ts
26339
26540
  var _106_cluster_settings_check_run_tracking_ttl_days_exports = /* @__PURE__ */ __exportAll({
26340
- down: () => down$1,
26341
- up: () => up$1
26541
+ down: () => down$2,
26542
+ up: () => up$2
26342
26543
  });
26343
26544
  /**
26344
26545
  * Add `cluster_settings.check_run_tracking_ttl_days` (nullable integer).
@@ -26354,7 +26555,7 @@ var _106_cluster_settings_check_run_tracking_ttl_days_exports = /* @__PURE__ */
26354
26555
  * Idempotent: guarded on column existence; a re-run on a database that already
26355
26556
  * has the column is a no-op.
26356
26557
  */
26357
- async function up$1(db) {
26558
+ async function up$2(db) {
26358
26559
  if ((await sql`
26359
26560
  SELECT EXISTS (
26360
26561
  SELECT 1 FROM information_schema.columns
@@ -26365,15 +26566,15 @@ async function up$1(db) {
26365
26566
  `.execute(db)).rows[0]?.exists) return;
26366
26567
  await sql`ALTER TABLE public.cluster_settings ADD COLUMN check_run_tracking_ttl_days INTEGER`.execute(db);
26367
26568
  }
26368
- async function down$1(db) {
26569
+ async function down$2(db) {
26369
26570
  await sql`ALTER TABLE public.cluster_settings DROP COLUMN IF EXISTS check_run_tracking_ttl_days`.execute(db);
26370
26571
  }
26371
26572
  var init__106_cluster_settings_check_run_tracking_ttl_days = __esmMin((() => {}));
26372
26573
  //#endregion
26373
26574
  //#region src/db/migrations/107_check_run_tracking_updated_at_index.ts
26374
26575
  var _107_check_run_tracking_updated_at_index_exports = /* @__PURE__ */ __exportAll({
26375
- down: () => down,
26376
- up: () => up
26576
+ down: () => down$1,
26577
+ up: () => up$1
26377
26578
  });
26378
26579
  /**
26379
26580
  * Add `idx_check_run_tracking_updated_at` on `check_run_tracking (updated_at)`.
@@ -26394,17 +26595,63 @@ var _107_check_run_tracking_updated_at_index_exports = /* @__PURE__ */ __exportA
26394
26595
  *
26395
26596
  * Idempotent: `IF NOT EXISTS` makes a re-run a no-op.
26396
26597
  */
26397
- async function up(db) {
26598
+ async function up$1(db) {
26398
26599
  await sql`
26399
26600
  CREATE INDEX IF NOT EXISTS idx_check_run_tracking_updated_at
26400
26601
  ON public.check_run_tracking (updated_at)
26401
26602
  `.execute(db);
26402
26603
  }
26403
- async function down(db) {
26604
+ async function down$1(db) {
26404
26605
  await sql`DROP INDEX IF EXISTS public.idx_check_run_tracking_updated_at`.execute(db);
26405
26606
  }
26406
26607
  var init__107_check_run_tracking_updated_at_index = __esmMin((() => {}));
26407
26608
  //#endregion
26609
+ //#region src/db/migrations/108_unroutable_fast_fail.ts
26610
+ var _108_unroutable_fast_fail_exports = /* @__PURE__ */ __exportAll({
26611
+ down: () => down,
26612
+ up: () => up
26613
+ });
26614
+ /**
26615
+ * Fast-fail support for jobs nothing in the fleet can run.
26616
+ *
26617
+ * Three additive, nullable columns:
26618
+ *
26619
+ * - `cluster_settings.unroutable_grace_ms` — how long a job may stay
26620
+ * continuously unroutable before it is terminalized. NULL means the
26621
+ * orchestrator's configured default applies; 0 disables fast-fail and leaves
26622
+ * the `queue_timeout_ms` backstop as the only path.
26623
+ * - `dispatch_queue.unroutable_since` — when the job first read unroutable.
26624
+ * Persisted rather than in-memory so a restart mid-grace resumes the same
26625
+ * clock instead of resetting it; an orchestrator that bounces every 90s must
26626
+ * not be able to keep a genuinely dead job alive forever. Cleared the moment
26627
+ * the job reads routable again.
26628
+ * - `execution_jobs.routing_reason` — the operator-facing reason, visible while
26629
+ * the job is still queued. Cleared on recovery.
26630
+ *
26631
+ * Idempotent: each column is guarded on existence, so a re-run is a no-op.
26632
+ */
26633
+ async function columnExists(db, table, column) {
26634
+ return (await sql`
26635
+ SELECT EXISTS (
26636
+ SELECT 1 FROM information_schema.columns
26637
+ WHERE table_schema = 'public'
26638
+ AND table_name = ${table}
26639
+ AND column_name = ${column}
26640
+ ) AS exists
26641
+ `.execute(db)).rows[0]?.exists === true;
26642
+ }
26643
+ async function up(db) {
26644
+ if (!await columnExists(db, "cluster_settings", "unroutable_grace_ms")) await sql`ALTER TABLE public.cluster_settings ADD COLUMN unroutable_grace_ms INTEGER`.execute(db);
26645
+ if (!await columnExists(db, "dispatch_queue", "unroutable_since")) await sql`ALTER TABLE public.dispatch_queue ADD COLUMN unroutable_since TIMESTAMPTZ`.execute(db);
26646
+ if (!await columnExists(db, "execution_jobs", "routing_reason")) await sql`ALTER TABLE public.execution_jobs ADD COLUMN routing_reason TEXT`.execute(db);
26647
+ }
26648
+ async function down(db) {
26649
+ await sql`ALTER TABLE public.execution_jobs DROP COLUMN IF EXISTS routing_reason`.execute(db);
26650
+ await sql`ALTER TABLE public.dispatch_queue DROP COLUMN IF EXISTS unroutable_since`.execute(db);
26651
+ await sql`ALTER TABLE public.cluster_settings DROP COLUMN IF EXISTS unroutable_grace_ms`.execute(db);
26652
+ }
26653
+ var init__108_unroutable_fast_fail = __esmMin((() => {}));
26654
+ //#endregion
26408
26655
  //#region src/db/migration-provider.ts
26409
26656
  function createMigrationProvider() {
26410
26657
  return { async getMigrations() {
@@ -26515,7 +26762,8 @@ function createMigrationProvider() {
26515
26762
  "104_check_run_terminal_sent": _104_check_run_terminal_sent_exports,
26516
26763
  "105_org_trust_policy": _105_org_trust_policy_exports,
26517
26764
  "106_cluster_settings_check_run_tracking_ttl_days": _106_cluster_settings_check_run_tracking_ttl_days_exports,
26518
- "107_check_run_tracking_updated_at_index": _107_check_run_tracking_updated_at_index_exports
26765
+ "107_check_run_tracking_updated_at_index": _107_check_run_tracking_updated_at_index_exports,
26766
+ "108_unroutable_fast_fail": _108_unroutable_fast_fail_exports
26519
26767
  };
26520
26768
  } };
26521
26769
  }
@@ -26627,6 +26875,7 @@ var init_migration_provider = __esmMin((() => {
26627
26875
  init__105_org_trust_policy();
26628
26876
  init__106_cluster_settings_check_run_tracking_ttl_days();
26629
26877
  init__107_check_run_tracking_updated_at_index();
26878
+ init__108_unroutable_fast_fail();
26630
26879
  }));
26631
26880
  //#endregion
26632
26881
  //#region src/db/migrator.ts
@@ -27828,7 +28077,8 @@ var init_admin_cluster_settings = __esmMin((() => {
27828
28077
  checkRunTrackingTtlDays: "check_run_tracking_ttl_days",
27829
28078
  concurrencyWaitTimeoutMs: "concurrency_wait_timeout_ms",
27830
28079
  agentTokenTtlMs: "agent_token_ttl_ms",
27831
- ownershipDbCheckTimeoutMs: "ownership_db_check_timeout_ms"
28080
+ ownershipDbCheckTimeoutMs: "ownership_db_check_timeout_ms",
28081
+ unroutableGraceMs: "unroutable_grace_ms"
27832
28082
  };
27833
28083
  STRING_COLUMNS = { dashboardVerifiedIssuer: "dashboard_verified_issuer" };
27834
28084
  updateSchema$1 = z.object({
@@ -27850,6 +28100,8 @@ var init_admin_cluster_settings = __esmMin((() => {
27850
28100
  concurrencyWaitTimeoutMs: z.number().int().min(1e3).nullable().optional(),
27851
28101
  agentTokenTtlMs: z.number().int().min(1e3).nullable().optional(),
27852
28102
  ownershipDbCheckTimeoutMs: z.number().int().min(100).nullable().optional(),
28103
+ /** 0 disables unroutable fast-fail, so the floor is 0, not 1000. */
28104
+ unroutableGraceMs: z.number().int().min(0).nullable().optional(),
27853
28105
  /**
27854
28106
  * Verified-tier origin for browser-sealed dashboard writes. Must be an
27855
28107
  * absolute http(s) origin (the dashboard fetches `<issuer>/.well-known/jwks.json`
@@ -32078,6 +32330,23 @@ function mapRunDetailStep(step) {
32078
32330
  ...step.group_id != null && { groupId: step.group_id }
32079
32331
  };
32080
32332
  }
32333
+ /**
32334
+ * The routing reason as a reader should see it.
32335
+ *
32336
+ * `routing_reason` is only meaningful while the job is still waiting to be
32337
+ * routed, and more than twenty call sites move a job out of `pending`/`queued`
32338
+ * — dispatch, cancel, the run-level failure cascades, the stale detector.
32339
+ * Requiring every one of them to also null the column would be fragile in the
32340
+ * one direction that matters: the site somebody forgets renders a finished job
32341
+ * as "waiting for an agent".
32342
+ *
32343
+ * So the guard lives here, at the read boundary both projections share, where
32344
+ * it cannot be forgotten by a writer that does not know this column exists.
32345
+ * The stale bytes may linger in the row; they are never shown.
32346
+ */
32347
+ function visibleRoutingReason(status, routingReason) {
32348
+ return status === ExecutionJobStatus.enum.pending || status === ExecutionJobStatus.enum.queued ? routingReason ?? null : null;
32349
+ }
32081
32350
  /** Map queried job + step rows into the dashboard run-detail job DTO shape. */
32082
32351
  function buildRunDetailJobs(jobs, lookups) {
32083
32352
  const { stepsByJob, secretKeysByJob, needsByJob } = lookups;
@@ -32098,6 +32367,7 @@ function buildRunDetailJobs(jobs, lookups) {
32098
32367
  agentId: job.agent_id ?? null,
32099
32368
  orchestratorId: null,
32100
32369
  errorMessage: job.error_message ?? null,
32370
+ routingReason: visibleRoutingReason(job.status, job.routing_reason ?? null),
32101
32371
  runsOnLabels: job.runs_on_labels ?? null,
32102
32372
  contexts: job.contexts ? typeof job.contexts === "string" ? JSON.parse(job.contexts) : job.contexts : null,
32103
32373
  skippedContexts: job.skipped_contexts ? typeof job.skipped_contexts === "string" ? JSON.parse(job.skipped_contexts) : job.skipped_contexts : null,
@@ -32671,6 +32941,7 @@ function createAdminRunRoutes(deps) {
32671
32941
  "completed_at",
32672
32942
  "duration_ms",
32673
32943
  "error_message",
32944
+ "routing_reason",
32674
32945
  "runs_on_labels",
32675
32946
  "created_at"
32676
32947
  ]).where("run_id", "=", runId).orderBy("created_at", "asc").execute();
@@ -32724,6 +32995,7 @@ function createAdminRunRoutes(deps) {
32724
32995
  completedAt: job.completed_at?.toISOString() ?? null,
32725
32996
  durationMs: job.duration_ms,
32726
32997
  errorMessage: job.error_message,
32998
+ routingReason: visibleRoutingReason(job.status, job.routing_reason),
32727
32999
  runsOnLabels: safeJsonParse$1(job.runs_on_labels),
32728
33000
  createdAt: job.created_at.toISOString(),
32729
33001
  needs: needsByJob.get(job.job_name) ?? null
@@ -34124,14 +34396,14 @@ var init_admin_config = __esmMin((() => {
34124
34396
  function createHealthRoutes$1(deps = {}) {
34125
34397
  return createHealthRoutes({
34126
34398
  livenessInfo: () => ({
34127
- version: "0.2.0",
34128
- buildDate: "2026-08-08T03:42:24.121Z",
34129
- buildCommit: "15d5e4447",
34130
- sdkVersion: "0.2.0",
34399
+ version: "0.3.0",
34400
+ buildDate: "2026-08-09T00:52:55.102Z",
34401
+ buildCommit: "2e7dec998",
34402
+ sdkVersion: "0.3.0",
34131
34403
  sdkBundleHash: "fcd0a836aa1cb92debd93e0254450614d123b3748511aa4148d956fd72a7c29f",
34132
- sharedVersion: "0.2.0",
34404
+ sharedVersion: "0.3.0",
34133
34405
  sharedBundleHash: "f16fa528a8a9ef1bed8df369f0e88efafca8a9954a749005299fdbcdb93fa188",
34134
- engineVersion: "0.2.0",
34406
+ engineVersion: "0.3.0",
34135
34407
  engineBundleHash: "c579e54f7d0b0d5b16587a0528a3e66d32f63e2434bb471a93a01366296efd58"
34136
34408
  }),
34137
34409
  readinessCheck: deps.db ? async () => {
@@ -34167,7 +34439,7 @@ function createCapabilitiesRoutes() {
34167
34439
  const app = new Hono();
34168
34440
  app.get("/api/v1/capabilities", (c) => {
34169
34441
  const manifest = {
34170
- orchestratorVersion: "0.2.0",
34442
+ orchestratorVersion: "0.3.0",
34171
34443
  protocolVersion: PROTOCOL_VERSION,
34172
34444
  minProtocolVersion: MIN_PROTOCOL_VERSION
34173
34445
  };
@@ -36786,7 +37058,7 @@ var init_app = __esmMin((() => {
36786
37058
  init_log_chunk_sink();
36787
37059
  init_agent_metrics_aggregator();
36788
37060
  logger$57 = createLogger({ prefix: "app" });
36789
- ORCHESTRATOR_VERSION$2 = "0.2.0";
37061
+ ORCHESTRATOR_VERSION$2 = "0.3.0";
36790
37062
  SourceLocationStore = class {
36791
37063
  cache = /* @__PURE__ */ new Map();
36792
37064
  key(workflowName, jobName) {
@@ -43700,7 +43972,8 @@ var init_execution_tracker = __esmMin((() => {
43700
43972
  await this.db.updateTable("execution_jobs").set({
43701
43973
  status: ExecutionJobStatus.enum.failed,
43702
43974
  completed_at: now,
43703
- error_message: failureReason
43975
+ error_message: failureReason,
43976
+ routing_reason: null
43704
43977
  }).where("run_id", "=", runId).where("status", "in", [ExecutionJobStatus.enum.pending, ExecutionJobStatus.enum.queued]).execute();
43705
43978
  await this.jobQueue?.failByRunId(runId);
43706
43979
  const run = this.runs.get(runId);
@@ -43952,7 +44225,8 @@ var init_execution_tracker = __esmMin((() => {
43952
44225
  await this.db.updateTable("execution_jobs").set({
43953
44226
  status: ExecutionJobStatus.enum.failed,
43954
44227
  completed_at: now,
43955
- error_message: reason
44228
+ error_message: reason,
44229
+ routing_reason: null
43956
44230
  }).where("run_id", "=", runId).where("status", "in", [ExecutionJobStatus.enum.pending, ExecutionJobStatus.enum.queued]).execute();
43957
44231
  await this.jobQueue?.failByRunId(runId);
43958
44232
  executionsTotal.add(1, { status: ExecutionRunStatus.enum.failed });
@@ -45976,7 +46250,7 @@ var logger$44, SOFTWARE_VERSION$1, PeerClient$1;
45976
46250
  var init_peer_client = __esmMin((() => {
45977
46251
  init_peer_crypto();
45978
46252
  logger$44 = createLogger({ prefix: "peer-client" });
45979
- SOFTWARE_VERSION$1 = "0.2.0";
46253
+ SOFTWARE_VERSION$1 = "0.3.0";
45980
46254
  PeerClient$1 = class {
45981
46255
  ws = null;
45982
46256
  _state = "disconnected";
@@ -47939,7 +48213,7 @@ var init_peer_handler = __esmMin((() => {
47939
48213
  init_peer_crypto();
47940
48214
  init_join_token();
47941
48215
  logger$42 = createLogger({ prefix: "peer-handler" });
47942
- SOFTWARE_VERSION = "0.2.0";
48216
+ SOFTWARE_VERSION = "0.3.0";
47943
48217
  RATE_LIMIT_MAX = 5;
47944
48218
  RATE_LIMIT_WINDOW_MS = 6e4;
47945
48219
  }));
@@ -55968,6 +56242,7 @@ async function bootstrapOrchestrator$1(config, hooks, options) {
55968
56242
  logger$24.warn("cold-store singleton init skipped", { error: toErrorMessage(err) });
55969
56243
  }
55970
56244
  accessLogWriter.setColdStore(coldStoreSingleton);
56245
+ const canRouteLabels = (labels, patterns, excludeLabels, excludePatterns) => agentRegistry.hasMatchingAgent(labels, patterns, excludeLabels, excludePatterns) || (scalerManager?.hasBackendForLabels(labels, excludeLabels) ?? false);
55971
56246
  const scheduledJobHandles = bootstrapOrchestratorScheduledJobs({
55972
56247
  db,
55973
56248
  instanceId: config.instanceId
@@ -55985,7 +56260,26 @@ async function bootstrapOrchestrator$1(config, hooks, options) {
55985
56260
  clusterSettings,
55986
56261
  logStorage,
55987
56262
  logStorageIsS3: config.storage?.type === "s3",
55988
- canRouteLabels: (labels, patterns, excludeLabels, excludePatterns) => agentRegistry.hasMatchingAgent(labels, patterns, excludeLabels, excludePatterns) || (scalerManager?.hasBackendForLabels(labels, excludeLabels) ?? false)
56263
+ canRouteLabels
56264
+ })
56265
+ },
56266
+ unroutableProbe: {
56267
+ intervalMs: probeTickIntervalMs(config.unroutableGraceMs > 0 ? config.unroutableGraceMs : DEFAULT_UNROUTABLE_GRACE_MS),
56268
+ handler: createUnroutableProbeHandler({
56269
+ queue,
56270
+ getGraceMs: () => clusterSettings.getNumber("unroutable_grace_ms", config.unroutableGraceMs),
56271
+ canRouteLabels,
56272
+ setRoutingReason: makeRoutingReasonWriter(db),
56273
+ terminalize: async (job) => {
56274
+ await terminalizeUnroutableJob({
56275
+ db,
56276
+ executionTracker,
56277
+ checkRunReporter,
56278
+ canRouteLabels
56279
+ }, job);
56280
+ await executionTracker.completeRunIfAllJobsTerminal(job.runId);
56281
+ },
56282
+ onFastFailed: () => unroutableFastFailedTotal.add(1)
55989
56283
  })
55990
56284
  },
55991
56285
  orphanSecretCleanup: {
@@ -56973,6 +57267,9 @@ var init_orchestrator_core = __esmMin((() => {
56973
57267
  init_host_roster_reaper();
56974
57268
  init_job_queue();
56975
57269
  init_cleanup$1();
57270
+ init_terminalize_unroutable();
57271
+ init_unroutable_probe();
57272
+ init_prometheus();
56976
57273
  init_bootstrap();
56977
57274
  init_orchestrator_cold_store();
56978
57275
  init_depth_refresher();
@@ -56985,7 +57282,6 @@ var init_orchestrator_core = __esmMin((() => {
56985
57282
  init_dedup();
56986
57283
  init_observer_registry();
56987
57284
  init_agent_heartbeat();
56988
- init_prometheus();
56989
57285
  init_ingest_admission();
56990
57286
  init_loop_lag_source();
56991
57287
  init_org_ingest_cap_reader();
@@ -64584,6 +64880,12 @@ var init_config = __esmMin((() => {
64584
64880
  queueMaxDepth: z.coerce.number().default(1e3),
64585
64881
  queueTimeoutMs: z.coerce.number().default(36e5),
64586
64882
  /**
64883
+ * Grace a job may stay continuously unroutable (nothing in the fleet matches
64884
+ * its selectors) before it is terminalized. Cluster default; the live value
64885
+ * is the `unroutable_grace_ms` cluster setting. 0 = fast-fail disabled.
64886
+ */
64887
+ unroutableGraceMs: z.coerce.number().default(12e4),
64888
+ /**
64587
64889
  * Operator-facing backpressure warning threshold for the dispatch queue.
64588
64890
  * When pending-queue depth stays at or above this value for at least two
64589
64891
  * consecutive refresher ticks (~10s), the orchestrator emits a
@@ -64861,6 +65163,7 @@ var init_config = __esmMin((() => {
64861
65163
  lockfileCacheMaxBytes: "KICI_LOCKFILE_CACHE_MAX_BYTES",
64862
65164
  queueMaxDepth: "KICI_QUEUE_MAX_DEPTH",
64863
65165
  queueTimeoutMs: "KICI_QUEUE_TIMEOUT_MS",
65166
+ unroutableGraceMs: "KICI_UNROUTABLE_GRACE_MS",
64864
65167
  queueBackpressureThreshold: "KICI_QUEUE_BACKPRESSURE_THRESHOLD",
64865
65168
  workerConcurrency: "KICI_WORKER_CONCURRENCY",
64866
65169
  concurrencyWaitTimeoutMs: "KICI_CONCURRENCY_WAIT_TIMEOUT_MS",
@@ -67237,6 +67540,7 @@ var init_handler = __esmMin((() => {
67237
67540
  "completed_at",
67238
67541
  "duration_ms",
67239
67542
  "error_message",
67543
+ "routing_reason",
67240
67544
  "runs_on_labels",
67241
67545
  "contexts",
67242
67546
  "skipped_contexts",
@@ -69248,6 +69552,7 @@ var init_handler = __esmMin((() => {
69248
69552
  completed_at: coerceToDate(r.completed_at),
69249
69553
  duration_ms: typeof r.duration_ms === "number" ? r.duration_ms : null,
69250
69554
  error_message: typeof r.error_message === "string" ? r.error_message : null,
69555
+ routing_reason: typeof r.routing_reason === "string" ? r.routing_reason : null,
69251
69556
  runs_on_labels: typeof r.runs_on_labels === "string" ? r.runs_on_labels : null,
69252
69557
  contexts: typeof r.contexts === "string" ? r.contexts : null,
69253
69558
  skipped_contexts: typeof r.skipped_contexts === "string" ? r.skipped_contexts : null,
@@ -75285,13 +75590,13 @@ var init_worker_core = __esmMin((() => {
75285
75590
  init_peer_outbox();
75286
75591
  init_worker_outbox_relay();
75287
75592
  init_app_on_error();
75288
- ORCHESTRATOR_VERSION$1 = "0.2.0";
75289
- WORKER_BUILD_COMMIT = "15d5e4447";
75290
- WORKER_SDK_VERSION = "0.2.0";
75593
+ ORCHESTRATOR_VERSION$1 = "0.3.0";
75594
+ WORKER_BUILD_COMMIT = "2e7dec998";
75595
+ WORKER_SDK_VERSION = "0.3.0";
75291
75596
  WORKER_SDK_BUNDLE_HASH = "fcd0a836aa1cb92debd93e0254450614d123b3748511aa4148d956fd72a7c29f";
75292
- WORKER_SHARED_VERSION = "0.2.0";
75597
+ WORKER_SHARED_VERSION = "0.3.0";
75293
75598
  WORKER_SHARED_BUNDLE_HASH = "f16fa528a8a9ef1bed8df369f0e88efafca8a9954a749005299fdbcdb93fa188";
75294
- WORKER_ENGINE_VERSION = "0.2.0";
75599
+ WORKER_ENGINE_VERSION = "0.3.0";
75295
75600
  WORKER_ENGINE_BUNDLE_HASH = "c579e54f7d0b0d5b16587a0528a3e66d32f63e2434bb471a93a01366296efd58";
75296
75601
  logger$2 = createLogger({ prefix: "worker" });
75297
75602
  DRAIN_TIMEOUT_MS = 3e5;
@@ -75316,13 +75621,13 @@ var init_worker_core = __esmMin((() => {
75316
75621
  init_verify_inbound();
75317
75622
  init_ingest_overflow_types();
75318
75623
  init_scope_routing();
75319
- const ORCHESTRATOR_VERSION = "0.2.0";
75320
- const BUILD_COMMIT = "15d5e4447";
75321
- const SDK_VERSION = "0.2.0";
75624
+ const ORCHESTRATOR_VERSION = "0.3.0";
75625
+ const BUILD_COMMIT = "2e7dec998";
75626
+ const SDK_VERSION = "0.3.0";
75322
75627
  const SDK_BUNDLE_HASH = "fcd0a836aa1cb92debd93e0254450614d123b3748511aa4148d956fd72a7c29f";
75323
- const SHARED_VERSION = "0.2.0";
75628
+ const SHARED_VERSION = "0.3.0";
75324
75629
  const SHARED_BUNDLE_HASH = "f16fa528a8a9ef1bed8df369f0e88efafca8a9954a749005299fdbcdb93fa188";
75325
- const ENGINE_VERSION = "0.2.0";
75630
+ const ENGINE_VERSION = "0.3.0";
75326
75631
  const ENGINE_BUNDLE_HASH = "c579e54f7d0b0d5b16587a0528a3e66d32f63e2434bb471a93a01366296efd58";
75327
75632
  const otelSdk = initTelemetry({
75328
75633
  serviceName: "kici-orchestrator",