@kici-dev/orchestrator 0.1.26 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (310) hide show
  1. package/dist/__test-helpers__/mock-db.d.ts +2 -0
  2. package/dist/agent/dispatcher.d.ts +52 -2
  3. package/dist/agent/host-roster-reaper.d.ts +1 -2
  4. package/dist/agent/host-roster.d.ts +34 -0
  5. package/dist/agent/ownership-refusal.d.ts +12 -0
  6. package/dist/agent/ownership-tracker.d.ts +64 -16
  7. package/dist/agent/token-store.d.ts +13 -0
  8. package/dist/agent-packaging/availability.d.ts +27 -0
  9. package/dist/agent-packaging/build-package.d.ts +16 -0
  10. package/dist/agent-packaging/download.d.ts +30 -0
  11. package/dist/agent-packaging/index.d.ts +9 -0
  12. package/dist/agent-packaging/install-closure.d.ts +30 -0
  13. package/dist/agent-packaging/node-binary.d.ts +26 -0
  14. package/dist/agent-packaging/refresh.d.ts +50 -0
  15. package/dist/agent-packaging/store.d.ts +15 -0
  16. package/dist/agent-packaging/upload.d.ts +24 -0
  17. package/dist/app-on-error.d.ts +29 -0
  18. package/dist/app.d.ts +69 -8
  19. package/dist/approvals/apply-decision.d.ts +1 -1
  20. package/dist/approvals/step-approval-bridge.d.ts +1 -1
  21. package/dist/artifacts/artifact-store.d.ts +233 -0
  22. package/dist/artifacts/failure-messages.d.ts +46 -0
  23. package/dist/audit/access-log.d.ts +18 -1
  24. package/dist/cache/dep-cache.d.ts +15 -0
  25. package/dist/cache/pending-inits.d.ts +4 -4
  26. package/dist/cache/user-cache.d.ts +37 -0
  27. package/dist/cancel/cancel-run.d.ts +10 -3
  28. package/dist/cancel/dashboard-cancel-handler.d.ts +19 -0
  29. package/dist/cli/api-client.d.ts +51 -5
  30. package/dist/cli/commands/agent-package.d.ts +34 -0
  31. package/dist/cli/commands/check-run.d.ts +26 -0
  32. package/dist/cli/commands/cluster-settings.d.ts +55 -0
  33. package/dist/cli/commands/context.d.ts +25 -0
  34. package/dist/cli/commands/dashboard-encryption-key.d.ts +3 -0
  35. package/dist/cli/commands/db-backup.d.ts +71 -0
  36. package/dist/cli/commands/debug-bundle.d.ts +1 -1
  37. package/dist/cli/commands/orchestrator-service/drain.d.ts +31 -0
  38. package/dist/cli/commands/orchestrator-service/index.d.ts +7 -4
  39. package/dist/cli/commands/orchestrator-service/install-env.d.ts +58 -0
  40. package/dist/cli/commands/secret.d.ts +45 -1
  41. package/dist/cli/commands/shared/admin-cli-access-log.d.ts +46 -0
  42. package/dist/cli/commands/shared/versioned-upgrade.d.ts +65 -2
  43. package/dist/cli/commands/signing-key.d.ts +3 -0
  44. package/dist/cli/commands/source.d.ts +12 -0
  45. package/dist/cli/commands/token.d.ts +9 -0
  46. package/dist/cli/commands/trust-policy.d.ts +48 -0
  47. package/dist/cli/commands/variable.d.ts +6 -6
  48. package/dist/cli/join.d.ts +1 -1
  49. package/dist/cli/service/index.d.ts +2 -2
  50. package/dist/cli/service/instance/manifest.d.ts +17 -0
  51. package/dist/cli/service/instance/resolve.d.ts +11 -0
  52. package/dist/cli/service/windows.d.ts +6 -0
  53. package/dist/cli/wizard/orchestrator-wizard.d.ts +39 -11
  54. package/dist/cli.js +10263 -3667
  55. package/dist/cluster/cluster-settings-reader.d.ts +78 -0
  56. package/dist/cluster/coordinator.d.ts +81 -9
  57. package/dist/cluster/join-client.d.ts +1 -1
  58. package/dist/cluster/leader-gated-scheduler.d.ts +50 -0
  59. package/dist/cluster/orphan-recovery.d.ts +14 -0
  60. package/dist/cluster/peer-client.d.ts +12 -2
  61. package/dist/cluster/peer-handler.d.ts +15 -4
  62. package/dist/cluster/peer-registry.d.ts +12 -0
  63. package/dist/cluster/verified-issuer-poller.d.ts +11 -0
  64. package/dist/cluster/verified-issuer.d.ts +63 -0
  65. package/dist/cold-store/tables/access-log.d.ts +1 -1
  66. package/dist/cold-store/tables/event-log.d.ts +1 -1
  67. package/dist/cold-store/tables/execution-jobs.d.ts +1 -1
  68. package/dist/cold-store/tables/execution-runs.d.ts +1 -1
  69. package/dist/cold-store/tables/execution-steps.d.ts +1 -1
  70. package/dist/cold-store/tables/secret-audit-log.d.ts +1 -1
  71. package/dist/config/loader.d.ts +1 -1
  72. package/dist/config/resolver.d.ts +2 -1
  73. package/dist/config/schema.d.ts +8 -6
  74. package/dist/config/types.d.ts +3 -2
  75. package/dist/config.d.ts +372 -46
  76. package/dist/contexts/binding-store.d.ts +36 -0
  77. package/dist/contexts/context-store.d.ts +100 -0
  78. package/dist/contexts/glob-specificity.d.ts +30 -0
  79. package/dist/{environments → contexts}/held-runs.d.ts +64 -32
  80. package/dist/{environments → contexts}/index.d.ts +1 -1
  81. package/dist/contexts/protection/aggregate.d.ts +43 -0
  82. package/dist/contexts/protection/branch-gate.d.ts +5 -0
  83. package/dist/contexts/protection/concurrency-gate.d.ts +4 -0
  84. package/dist/{environments → contexts}/protection/pipeline.d.ts +3 -3
  85. package/dist/contexts/protection/reviewer-gate.d.ts +4 -0
  86. package/dist/{environments → contexts}/protection/satisfiability.d.ts +22 -22
  87. package/dist/contexts/protection/trust-gate.d.ts +4 -0
  88. package/dist/contexts/protection/wait-timer-gate.d.ts +4 -0
  89. package/dist/contexts/variable-store.d.ts +39 -0
  90. package/dist/cron/cron-scheduler.d.ts +24 -4
  91. package/dist/cron/cron-store.d.ts +21 -7
  92. package/dist/dashboard/attestation-filters.d.ts +94 -74
  93. package/dist/dashboard/handler.d.ts +63 -3
  94. package/dist/db/migration-test-harness.d.ts +41 -0
  95. package/dist/db/migrations/067_environments_to_contexts.d.ts +36 -0
  96. package/dist/db/migrations/068_request_idempotency.d.ts +17 -0
  97. package/dist/db/migrations/069_reroute_tunables.d.ts +21 -0
  98. package/dist/db/migrations/070_execution_runs_failure_class.d.ts +4 -0
  99. package/dist/db/migrations/071_batch_accumulation.d.ts +26 -0
  100. package/dist/db/migrations/072_dispatch_queue_run_id_index.d.ts +15 -0
  101. package/dist/db/migrations/073_org_settings_ingest_concurrency.d.ts +13 -0
  102. package/dist/db/migrations/074_normalize_zero_concurrency_limit.d.ts +13 -0
  103. package/dist/db/migrations/075_ingest_overflow_buffer.d.ts +16 -0
  104. package/dist/db/migrations/076_artifacts.d.ts +19 -0
  105. package/dist/db/migrations/077_backup_runs.d.ts +13 -0
  106. package/dist/db/migrations/078_org_settings_backup_staleness.d.ts +12 -0
  107. package/dist/db/migrations/079_org_settings_scaler_spawn_timeout.d.ts +14 -0
  108. package/dist/db/migrations/080_cluster_settings.d.ts +17 -0
  109. package/dist/db/migrations/081_org_settings_queue_timeout.d.ts +19 -0
  110. package/dist/db/migrations/082_host_s3_reachable.d.ts +16 -0
  111. package/dist/db/migrations/083_org_settings_artifact_caps.d.ts +18 -0
  112. package/dist/db/migrations/084_orchestrator_signing_keys.d.ts +20 -0
  113. package/dist/db/migrations/085_cluster_settings_reroute_flap_grace_ms.d.ts +12 -0
  114. package/dist/db/migrations/086_cluster_settings_max_fanout_hosts.d.ts +12 -0
  115. package/dist/db/migrations/087_cluster_settings_event_router_rate_limit.d.ts +12 -0
  116. package/dist/db/migrations/088_cluster_settings_cache_max_tarball_bytes.d.ts +12 -0
  117. package/dist/db/migrations/089_cluster_settings_cache_ttl_days.d.ts +12 -0
  118. package/dist/db/migrations/090_cluster_settings_concurrency_wait_timeout_ms.d.ts +12 -0
  119. package/dist/db/migrations/091_cluster_settings_agent_token_ttl_ms.d.ts +12 -0
  120. package/dist/db/migrations/092_cluster_settings_version.d.ts +16 -0
  121. package/dist/db/migrations/093_org_settings_sandbox_allowlist.d.ts +4 -0
  122. package/dist/db/migrations/094_dashboard_encryption_keys.d.ts +21 -0
  123. package/dist/db/migrations/095_dashboard_write_policy_tristate.d.ts +20 -0
  124. package/dist/db/migrations/096_multi_schedule_cron_last_fired.d.ts +4 -0
  125. package/dist/db/migrations/097_execution_runs_pr_number.d.ts +4 -0
  126. package/dist/db/migrations/098_execution_runs_customer_id.d.ts +4 -0
  127. package/dist/db/migrations/099_cluster_settings_dashboard_verified_issuer.d.ts +21 -0
  128. package/dist/db/migrations/100_held_runs_hold_type_vocabulary.d.ts +31 -0
  129. package/dist/db/migrations/101_contexts_hold_expiry_drop_default.d.ts +31 -0
  130. package/dist/db/migrations/102_dispatch_queue_agent_id.d.ts +20 -0
  131. package/dist/db/migrations/103_cluster_settings_ownership_db_check_timeout_ms.d.ts +20 -0
  132. package/dist/db/migrations/104_check_run_terminal_sent.d.ts +22 -0
  133. package/dist/db/migrations/105_org_trust_policy.d.ts +19 -0
  134. package/dist/db/migrations/106_cluster_settings_check_run_tracking_ttl_days.d.ts +18 -0
  135. package/dist/db/migrations/107_check_run_tracking_updated_at_index.d.ts +23 -0
  136. package/dist/db/repos/dashboard-encryption-keys-repo.d.ts +48 -0
  137. package/dist/db/repos/signing-keys-repo.d.ts +34 -0
  138. package/dist/db/types.d.ts +499 -66
  139. package/dist/deployment/deployment-identity.d.ts +87 -2
  140. package/dist/diagnostics/checks/backup.d.ts +18 -0
  141. package/dist/diagnostics/checks/index.d.ts +2 -1
  142. package/dist/diagnostics/fleet-collector.d.ts +1 -1
  143. package/dist/drain/drain-controller.d.ts +52 -0
  144. package/dist/events/batch-accumulator.d.ts +63 -0
  145. package/dist/events/circuit-breaker.d.ts +9 -3
  146. package/dist/events/event-emitter.d.ts +31 -0
  147. package/dist/events/event-retry-scanner.d.ts +12 -2
  148. package/dist/events/event-router.d.ts +29 -0
  149. package/dist/firecracker/host-network.d.ts +2 -0
  150. package/dist/firecracker/net-interfaces.d.ts +14 -0
  151. package/dist/github-app-name-refresher/github-app-name-refresher.d.ts +19 -9
  152. package/dist/index.d.ts +2 -0
  153. package/dist/index.js +625 -22
  154. package/dist/lockfile-cache.d.ts +4 -0
  155. package/dist/lockfile-validate.d.ts +16 -9
  156. package/dist/metrics/prometheus.d.ts +114 -15
  157. package/dist/oidc/aws-kms-signer.d.ts +37 -0
  158. package/dist/oidc/command-signer.d.ts +23 -0
  159. package/dist/oidc/db-signer.d.ts +48 -0
  160. package/dist/oidc/id-token-claims.d.ts +76 -0
  161. package/dist/oidc/jwt.d.ts +18 -0
  162. package/dist/oidc/local-dev-signer.d.ts +31 -0
  163. package/dist/oidc/local-mint.d.ts +77 -0
  164. package/dist/oidc/oidc-mint-registration.d.ts +65 -0
  165. package/dist/oidc/orchestrator-mint.d.ts +97 -0
  166. package/dist/oidc/orchestrator-signer-factory.d.ts +33 -0
  167. package/dist/oidc/reconcile-signing-key.d.ts +21 -0
  168. package/dist/oidc/signer.d.ts +25 -0
  169. package/dist/oidc/signing-key-status.d.ts +23 -0
  170. package/dist/orchestrator-core.d.ts +42 -2
  171. package/dist/pipeline/decorating-secret-resolver.d.ts +5 -4
  172. package/dist/pipeline/dispatch-matched-workflow.d.ts +44 -3
  173. package/dist/pipeline/inline-eval.d.ts +2 -2
  174. package/dist/pipeline/install-secrets-resolver.d.ts +25 -14
  175. package/dist/pipeline/{job-environments.d.ts → job-contexts.d.ts} +23 -23
  176. package/dist/pipeline/manual-schedule.d.ts +28 -14
  177. package/dist/pipeline/pending-workflow-context.d.ts +1 -1
  178. package/dist/pipeline/process-webhook.d.ts +57 -2
  179. package/dist/pipeline/processor.d.ts +49 -13
  180. package/dist/pipeline/request-idempotency.d.ts +28 -0
  181. package/dist/pipeline/rerun.d.ts +20 -13
  182. package/dist/pipeline/resolve-sandbox-grant.d.ts +28 -0
  183. package/dist/pipeline/resume-workflow.d.ts +1 -1
  184. package/dist/pipeline/route-or-dispatch-jobs.d.ts +71 -0
  185. package/dist/pipeline/sandbox-allowlist-reader.d.ts +33 -0
  186. package/dist/pipeline/test-pipeline.d.ts +2 -2
  187. package/dist/policy/dashboard-write-policy.d.ts +9 -4
  188. package/dist/provenance/backfill-run.d.ts +1 -0
  189. package/dist/provenance/trust-root.d.ts +20 -0
  190. package/dist/provider-registry.d.ts +8 -0
  191. package/dist/providers/generic/normalizer.d.ts +1 -1
  192. package/dist/providers/github/auth.d.ts +1 -1
  193. package/dist/providers/github/changed-files.d.ts +14 -6
  194. package/dist/providers/github/check-status-poster.d.ts +19 -3
  195. package/dist/providers/github/contributor-resolver.d.ts +1 -1
  196. package/dist/providers/github/lock-file.d.ts +1 -1
  197. package/dist/providers/github/normalizer.d.ts +1 -1
  198. package/dist/providers/github/repo-url.d.ts +1 -1
  199. package/dist/providers/local/index.d.ts +1 -0
  200. package/dist/providers/local/local-source-config.d.ts +1 -0
  201. package/dist/providers/local/lock-file-fetcher.d.ts +1 -1
  202. package/dist/providers/local/normalizer.d.ts +1 -1
  203. package/dist/providers/local/repo-url-builder.d.ts +1 -1
  204. package/dist/providers/universal-git/changed-files.d.ts +8 -7
  205. package/dist/providers/universal-git/clone-token.d.ts +1 -1
  206. package/dist/providers/universal-git/config.d.ts +4 -4
  207. package/dist/providers/universal-git/index.d.ts +5 -1
  208. package/dist/providers/universal-git/lock-file.d.ts +6 -1
  209. package/dist/providers/universal-git/normalizer.d.ts +1 -1
  210. package/dist/providers/universal-git/repo-url.d.ts +1 -1
  211. package/dist/queue/cleanup.d.ts +69 -8
  212. package/dist/queue/job-queue.d.ts +94 -14
  213. package/dist/queue/scheduled-job.d.ts +2 -2
  214. package/dist/registration/registration-index.d.ts +1 -1
  215. package/dist/reporting/agent-failure-category.d.ts +4 -1
  216. package/dist/reporting/check-run-reporter.d.ts +34 -14
  217. package/dist/reporting/check-run-tracking-store.d.ts +70 -8
  218. package/dist/reporting/execution-tracker.d.ts +173 -17
  219. package/dist/reporting/fs-log-storage.d.ts +31 -2
  220. package/dist/reporting/job-check-run-completion.d.ts +50 -0
  221. package/dist/reporting/log-chunk-sink.d.ts +47 -0
  222. package/dist/reporting/log-retention.d.ts +16 -0
  223. package/dist/reporting/log-storage.d.ts +64 -4
  224. package/dist/reporting/log-writer.d.ts +22 -7
  225. package/dist/reporting/peer-log-normalize.d.ts +14 -0
  226. package/dist/reporting/run-aggregator.d.ts +36 -36
  227. package/dist/reporting/s3-log-storage.d.ts +102 -8
  228. package/dist/routes/admin-auth.d.ts +90 -0
  229. package/dist/routes/admin-cluster-settings.d.ts +31 -0
  230. package/dist/routes/admin-contexts.d.ts +47 -0
  231. package/dist/routes/admin-events.d.ts +3 -0
  232. package/dist/routes/admin-orchestrator-drain.d.ts +35 -0
  233. package/dist/routes/admin-registrations.d.ts +2 -2
  234. package/dist/routes/admin-runs.d.ts +9 -0
  235. package/dist/routes/admin-sources.d.ts +7 -0
  236. package/dist/routes/admin-trust-policy.d.ts +49 -0
  237. package/dist/routes/admin.d.ts +15 -1
  238. package/dist/routes/github-webhook.d.ts +9 -3
  239. package/dist/routes/provenance-oidc.d.ts +38 -0
  240. package/dist/routes/verify-attestation.d.ts +21 -0
  241. package/dist/scaler/bare-metal-backend.d.ts +9 -2
  242. package/dist/scaler/config.d.ts +25 -4
  243. package/dist/scaler/container-backend.d.ts +9 -1
  244. package/dist/scaler/firecracker-backend.d.ts +29 -2
  245. package/dist/scaler/index.d.ts +1 -1
  246. package/dist/scaler/manager.d.ts +166 -8
  247. package/dist/scaler/pending-scale-sweeper.d.ts +35 -0
  248. package/dist/scaler/types.d.ts +75 -6
  249. package/dist/secrets/backend-registry.d.ts +32 -1
  250. package/dist/secrets/context-secret-resolver.d.ts +30 -0
  251. package/dist/secrets/dashboard-encryption-key.d.ts +48 -0
  252. package/dist/secrets/ephemeral-keys.d.ts +16 -0
  253. package/dist/secrets/index.d.ts +1 -1
  254. package/dist/secrets/pg-secret-store.d.ts +13 -3
  255. package/dist/secrets/rbac.d.ts +5 -1
  256. package/dist/secrets/routing-key-scope.d.ts +6 -0
  257. package/dist/secrets/scope-routing.d.ts +126 -0
  258. package/dist/secrets/secret-resolver.d.ts +19 -32
  259. package/dist/secrets/token-manager.d.ts +5 -1
  260. package/dist/security/comment-handler.d.ts +1 -1
  261. package/dist/security/contributor-cache.d.ts +9 -1
  262. package/dist/security/trust-policy-gate.d.ts +117 -0
  263. package/dist/security/trust-policy-store.d.ts +78 -0
  264. package/dist/server.js +44012 -32721
  265. package/dist/sources/source-manager.d.ts +24 -0
  266. package/dist/stale-detector/stale-run-detector.d.ts +8 -1
  267. package/dist/standalone.js +44106 -33690
  268. package/dist/storage/blob-routes.d.ts +16 -0
  269. package/dist/storage/filesystem.d.ts +17 -0
  270. package/dist/storage/key-discriminator.d.ts +20 -0
  271. package/dist/storage/s3.d.ts +2 -0
  272. package/dist/storage/types.d.ts +16 -0
  273. package/dist/webhook/dedup.d.ts +9 -1
  274. package/dist/webhook/event-log.d.ts +13 -2
  275. package/dist/webhook/generic-sources-listener.d.ts +4 -0
  276. package/dist/webhook/ingest-admission.d.ts +140 -0
  277. package/dist/webhook/ingest-overflow-buffer.d.ts +27 -0
  278. package/dist/webhook/ingest-overflow-replayer.d.ts +49 -0
  279. package/dist/webhook/ingest-overflow-types.d.ts +73 -0
  280. package/dist/webhook/loop-lag-source.d.ts +40 -0
  281. package/dist/webhook/observed-relay-guard.d.ts +40 -0
  282. package/dist/webhook/org-ingest-cap-reader.d.ts +24 -0
  283. package/dist/webhook/register-source-bundle.d.ts +3 -0
  284. package/dist/webhook/relay-reinject.d.ts +43 -0
  285. package/dist/worker/in-memory-job-queue.d.ts +8 -3
  286. package/dist/worker-core.d.ts +10 -0
  287. package/dist/ws/agent-api-registry.d.ts +20 -0
  288. package/dist/ws/agent-handler.d.ts +63 -7
  289. package/dist/ws/bringup-api.d.ts +99 -0
  290. package/dist/ws/{dashboard-env-handler.d.ts → dashboard-context-handler.d.ts} +43 -25
  291. package/dist/ws/dashboard-run-state-handler.d.ts +31 -0
  292. package/dist/ws/failure-messages.d.ts +29 -0
  293. package/dist/ws/oidc-token-relay.d.ts +15 -0
  294. package/dist/ws/ownership-gate.d.ts +22 -0
  295. package/dist/ws/platform-client.d.ts +96 -1
  296. package/dist/ws/replay-chunker.d.ts +37 -0
  297. package/installer-image-digests.json +3 -3
  298. package/package.json +22 -21
  299. package/sbom.spdx.json +1245 -1793
  300. package/dist/cli/commands/environment.d.ts +0 -25
  301. package/dist/environments/binding-store.d.ts +0 -36
  302. package/dist/environments/environment-store.d.ts +0 -87
  303. package/dist/environments/protection/aggregate.d.ts +0 -43
  304. package/dist/environments/protection/branch-gate.d.ts +0 -5
  305. package/dist/environments/protection/concurrency-gate.d.ts +0 -7
  306. package/dist/environments/protection/reviewer-gate.d.ts +0 -7
  307. package/dist/environments/protection/trust-gate.d.ts +0 -7
  308. package/dist/environments/protection/wait-timer-gate.d.ts +0 -7
  309. package/dist/environments/variable-store.d.ts +0 -39
  310. package/dist/routes/admin-environments.d.ts +0 -47
@@ -13,7 +13,10 @@ export interface FailureSignals {
13
13
  hasInitFailure: boolean;
14
14
  /** The init-failure category (`InitFailureCategory`), if any. */
15
15
  initFailureCategory: string | null;
16
- /** Any job ended in `timed_out_stale` (or a workflow/job timeout fired). */
16
+ /**
17
+ * Any job ended in an infra-class verdict that means it never really ran —
18
+ * `timed_out_stale` or `unroutable` — or a workflow/job timeout fired.
19
+ */
17
20
  timedOut: boolean;
18
21
  /** Any step recorded a non-zero exit code. */
19
22
  anyStepNonZeroExit: boolean;
@@ -30,7 +30,7 @@ import type { ProviderRegistry } from '../provider-registry.js';
30
30
  import type { StepLogBuffer } from './step-log-buffer.js';
31
31
  import { type SourceLocationData } from './check-run-summary.js';
32
32
  import type { CheckRunTrackingStore } from './check-run-tracking-store.js';
33
- import { ExecutionJobStatus } from '@kici-dev/engine';
33
+ import { type TerminalJobStatus } from '@kici-dev/engine';
34
34
  /**
35
35
  * Dependencies for the CheckRunReporter.
36
36
  */
@@ -122,7 +122,7 @@ interface SetBuildCompleteOptions {
122
122
  repo: string;
123
123
  sha: string;
124
124
  workflowName: string;
125
- status: Extract<ExecutionJobStatus, 'success' | 'failed' | 'cancelled' | 'timed_out_stale'>;
125
+ status: TerminalJobStatus;
126
126
  installationId?: number;
127
127
  /** Routing key for per-app credential lookup (e.g., "github:12345"). */
128
128
  routingKey?: string;
@@ -142,7 +142,7 @@ interface UpdateJobStatusOptions {
142
142
  sha: string;
143
143
  workflowName: string;
144
144
  jobName: string;
145
- state: Extract<ExecutionJobStatus, 'success' | 'failed' | 'cancelled' | 'timed_out_stale'>;
145
+ state: TerminalJobStatus;
146
146
  installationId?: number;
147
147
  /** Routing key for per-app credential lookup (e.g., "github:12345"). */
148
148
  routingKey?: string;
@@ -167,7 +167,7 @@ interface UpdateWorkflowStatusOptions {
167
167
  repo: string;
168
168
  sha: string;
169
169
  workflowName: string;
170
- overallStatus: Extract<ExecutionJobStatus, 'success' | 'failed' | 'cancelled' | 'timed_out_stale'>;
170
+ overallStatus: TerminalJobStatus;
171
171
  installationId?: number;
172
172
  /** Routing key for per-app credential lookup (e.g., "github:12345"). */
173
173
  routingKey?: string;
@@ -238,6 +238,19 @@ export declare class CheckRunReporter {
238
238
  private readonly progressTimers;
239
239
  /** L1 cache: first in-progress sent flag (synced to `check_run_tracking.in_progress_sent_at`). */
240
240
  private readonly inProgressSent;
241
+ /**
242
+ * Keys whose job check run has already been completed.
243
+ *
244
+ * Makes the check run's status monotonic: once a `completed` update is
245
+ * issued, no later step-progress update may push it back to `in_progress`.
246
+ * Cancelling the pending debounce timer at completion time is not sufficient
247
+ * on its own — a step status that arrives after the completion schedules a
248
+ * FRESH timer, which then fires and leaves the check run showing
249
+ * `status: in_progress` with a terminal `conclusion` already attached. That
250
+ * is the permanently-unresolved state check-run completion exists to prevent,
251
+ * so the guard is on the write itself rather than on the timer.
252
+ */
253
+ private readonly terminalSent;
241
254
  /**
242
255
  * L1 cache: runId → set of check-run composite keys. Synced to the
243
256
  * indexed `check_run_tracking.run_id` column so a replacement coord can
@@ -334,21 +347,28 @@ export declare class CheckRunReporter {
334
347
  */
335
348
  setBuildComplete(opts: SetBuildCompleteOptions): void;
336
349
  /**
337
- * Clean up step-progress entries, debounce timers, and DB rows for a
338
- * completed run. Called when the execution tracker prunes the run.
350
+ * Clean up step-progress entries and debounce timers for a completed run.
351
+ * Called when the execution tracker prunes the run.
339
352
  *
340
- * In-memory cleanup is synchronous; the DB cleanup is fire-and-forget
341
- * because the caller (run-pruning hook) is on the response-shaping path
342
- * and shouldn't block on a network round-trip. Failure logs but does
343
- * not propagate.
353
+ * In-memory only. Database rows are owned by the retention sweep in
354
+ * `queue/cleanup.ts`, which deletes on inactivity age rather than on run
355
+ * completion. Deleting here would strand a late terminal update: a check-run
356
+ * status PATCH that arrives after the prune resolves its check-run ID by
357
+ * loading through to this row, and a deleted row makes that lookup fail.
344
358
  */
345
359
  cleanupRun(runId: string): void;
346
360
  /**
347
- * Hydrate the L1 caches from the DB after a leader switch (or any
348
- * boot-time recovery). Called once on coord become-leader so the
349
- * runIdToKeys reverse map is populated for any future cleanupRun calls
350
- * without requiring a DB round-trip per cleanup. If no store is wired,
361
+ * Mark the reporter as DB-backed after a leader switch (or any boot-time
362
+ * recovery). Called once on coord become-leader. If no store is wired,
351
363
  * this is a no-op.
364
+ *
365
+ * Nothing is hydrated up front — the table can be large across many shas —
366
+ * so check-run IDs load through on demand inside `resolveCheckRunId`. The
367
+ * `runIdToKeys` reverse map is rebuilt only from this coord's own writes,
368
+ * so a run whose keys all predate the switch leaves `cleanupRun` nothing to
369
+ * evict. That is harmless: the L1 caches it clears are equally empty on a
370
+ * fresh coord, and the DB rows belong to the retention sweep rather than to
371
+ * run prune.
352
372
  */
353
373
  recoverState(): Promise<void>;
354
374
  /** Track a check run key associated with a runId for later cleanup. */
@@ -29,7 +29,16 @@ export interface CheckRunTrackingState {
29
29
  stepProgress: StepProgressEntry[];
30
30
  /** Timestamp the first running-step transition was sent to GitHub. */
31
31
  inProgressSentAt?: Date;
32
- /** KiCI run this check-run belongs to. Used by `cleanupRun`. */
32
+ /**
33
+ * Timestamp the terminal (`completed`) update was accepted by the provider.
34
+ * Undefined means we have no record of sending it — not proof it failed.
35
+ */
36
+ terminalSentAt?: Date;
37
+ /**
38
+ * KiCI run this check-run belongs to. Written at create time so the row
39
+ * records its owning run; it is an attribution/lookup key, not a retention
40
+ * key — the sweep prunes on `updated_at` age alone.
41
+ */
33
42
  runId?: string;
34
43
  /** Last persisted update time; powers debounce-after-failover recovery. */
35
44
  updatedAt?: Date;
@@ -64,8 +73,13 @@ export declare class CheckRunTrackingStore {
64
73
  * Performed as an upsert so a re-issued setPending after a coord
65
74
  * failover replaces the prior ID rather than silently leaving a row
66
75
  * mismatched with the GitHub-side state.
76
+ *
77
+ * `runId` is written alongside so the row records which run owns it from
78
+ * the moment it is created. A row created without it carries a NULL
79
+ * `run_id`, which makes `listKeysByRunId` under-report and leaves the
80
+ * column useless to an operator asking which run posted a given check.
67
81
  */
68
- setCheckRunId(key: CheckRunTrackingKey, checkRunId: number): Promise<void>;
82
+ setCheckRunId(key: CheckRunTrackingKey, checkRunId: number, runId?: string): Promise<void>;
69
83
  /**
70
84
  * Lookup the check-run ID for a key. Returns undefined if no row exists
71
85
  * yet OR the row exists but the GitHub create has not finished
@@ -93,6 +107,14 @@ export declare class CheckRunTrackingStore {
93
107
  * cluster-wide.
94
108
  */
95
109
  markInProgressSent(key: CheckRunTrackingKey, runId?: string): Promise<void>;
110
+ /**
111
+ * Stamp that the terminal (`completed`) provider update was sent.
112
+ *
113
+ * Mirrors `markInProgressSent`. Best-effort like every write on this table —
114
+ * the caller swallows failures, because a tracking write must never break
115
+ * check-run reporting — so a null column is "no record", not "never sent".
116
+ */
117
+ markTerminalSent(key: CheckRunTrackingKey, runId?: string): Promise<void>;
96
118
  /**
97
119
  * Get the full state snapshot for a key. Used by the L1 cache to
98
120
  * hydrate on miss and by tests to verify the on-disk layout. Returns
@@ -104,17 +126,56 @@ export declare class CheckRunTrackingStore {
104
126
  */
105
127
  deleteRow(key: CheckRunTrackingKey): Promise<boolean>;
106
128
  /**
107
- * List every key currently tracked for a runId. Used by `cleanupRun`
108
- * to reproduce the runId keys reverse index that the in-memory map
109
- * provided. Index `idx_check_run_tracking_run_id` keeps this O(matches).
129
+ * List every key currently tracked for a runId the runId → keys reverse
130
+ * index that `CheckRunReporter` otherwise holds only in memory, so a
131
+ * replacement coord that never saw the run can still recover it. Index
132
+ * `idx_check_run_tracking_run_id` keeps this O(matches).
133
+ *
134
+ * No caller in tree: run-prune stopped consulting the store once row
135
+ * lifetime moved to {@link pruneStale}. Kept as the read half of the
136
+ * `run_id` column, beside {@link deleteByRunId}.
110
137
  */
111
138
  listKeysByRunId(runId: string): Promise<CheckRunTrackingKey[]>;
112
139
  /**
113
- * Delete every row for a runId. Mirrors the bulk-cleanup semantics of
114
- * `cleanupRun` so a single call from execution-tracker prune releases
115
- * all rows for the run.
140
+ * Delete every row for a runId.
141
+ *
142
+ * Not on the run-prune path: `cleanupRun` evicts only its in-memory state,
143
+ * because a row deleted at prune time strands a late terminal PATCH that
144
+ * still has to resolve its check-run ID. Routine reclamation is
145
+ * {@link pruneStale}. This remains as the targeted escape hatch for
146
+ * discarding one run's rows deliberately.
116
147
  */
117
148
  deleteByRunId(runId: string): Promise<number>;
149
+ /**
150
+ * Delete every row untouched for longer than `retentionDays`, and return
151
+ * how many were removed. `retentionDays <= 0` disables the sweep, matching
152
+ * the `JobQueue.pruneTerminalDispatchRows` convention.
153
+ *
154
+ * `updated_at` is the staleness signal because the table carries no status
155
+ * column, and the rows that most need reaping are precisely the ones with no
156
+ * `run_id` to join on — so the predicate is age alone, deliberately
157
+ * unfiltered by `run_id`. Every upsert bumps `updated_at`, so a run that is
158
+ * still emitting check-run traffic keeps its rows fresh; a workflow-level
159
+ * row, written once at create, ages from creation.
160
+ *
161
+ * Inactivity age rather than run completion is what keeps a reader safe: a
162
+ * row a diagnostic is polling for cannot disappear underneath it, because
163
+ * the window is days and the row is only removed once nothing has touched
164
+ * it for that long.
165
+ *
166
+ * The bound this trades for that safety: age is measured on check-run
167
+ * writes, not on run liveness, so a run that stays live while emitting no
168
+ * check-run traffic for longer than the window — a run parked on a manual
169
+ * approval gate, whose hold statuses go through `CheckStatusPoster` and
170
+ * never touch this table — has its rows swept while it is still running.
171
+ * The reporter's L1 cache still holds the ID, so its terminal update lands
172
+ * anyway on a coord that stayed up; it takes a restart or failover across
173
+ * that window to leave the update with no row to load through and no
174
+ * check-run ID to resolve.
175
+ *
176
+ * Called from the hourly cleanup tick.
177
+ */
178
+ pruneStale(retentionDays: number): Promise<number>;
118
179
  private selectRow;
119
180
  private upsertRow;
120
181
  }
@@ -127,6 +188,7 @@ export declare function rowToState(row: {
127
188
  build_creation_state: string | null;
128
189
  step_progress_json: unknown;
129
190
  in_progress_sent_at: Date | null;
191
+ terminal_sent_at: Date | null;
130
192
  run_id: string | null;
131
193
  updated_at: Date;
132
194
  }): CheckRunTrackingState;
@@ -13,7 +13,7 @@
13
13
  */
14
14
  import { type Kysely } from 'kysely';
15
15
  import type { Database } from '../db/types.js';
16
- import { ExecutionRunStatus, type InitFailure, ScalerEventType } from '@kici-dev/engine';
16
+ import { ExecutionRunStatus, type InitFailure, RunFailureClass, ScalerEventType, OrchLogPhase } from '@kici-dev/engine';
17
17
  import type { ObserverRegistry } from '../ws/observer-registry.js';
18
18
  import type { LogStorage } from './log-storage.js';
19
19
  import type { JobQueue } from '../queue/job-queue.js';
@@ -50,6 +50,12 @@ export interface ExecutionContext {
50
50
  triggerActorUsername?: string | null;
51
51
  /** Immutable provider user id of the triggering actor (preferred for resolution). */
52
52
  triggerActorUserId?: string | null;
53
+ /**
54
+ * Why a terminal run failed (`RunFailureClass`). Set on terminal-failed /
55
+ * cancelled runs; forwarded to the Platform on `execution.status` so managed
56
+ * subscriptions can match on it. Null/undefined for success or non-terminal.
57
+ */
58
+ failureClass?: RunFailureClass | null;
53
59
  /** Workflow-level concurrency config from the lock file. */
54
60
  concurrency?: {
55
61
  cancelInProgress?: boolean;
@@ -68,6 +74,8 @@ interface WorkflowCompleteCallbackData {
68
74
  }>;
69
75
  routingKey?: string;
70
76
  repo: string;
77
+ /** Why the run failed (`RunFailureClass`); carried onto the `__workflow_complete` event. */
78
+ failureClass?: string;
71
79
  }
72
80
  /** Data passed to the onJobComplete callback. */
73
81
  interface JobCompleteCallbackData {
@@ -78,6 +86,11 @@ interface JobCompleteCallbackData {
78
86
  routingKey?: string;
79
87
  repo: string;
80
88
  workflowName: string;
89
+ /**
90
+ * Job payload carried by the status update (step results, error, duration).
91
+ * Feeds the enriched check-run summary and the failure description.
92
+ */
93
+ data?: Record<string, unknown>;
81
94
  }
82
95
  export interface ExecutionTrackerDeps {
83
96
  db: Kysely<Database>;
@@ -125,8 +138,8 @@ export interface ExecutionTrackerDeps {
125
138
  * jobs that never started. Persisted in execution_jobs.init_failure.
126
139
  */
127
140
  initFailure?: InitFailure,
128
- /** Ordered bound deployment-environment names for this job (multi-env jobs). */
129
- environments?: string[]) => void;
141
+ /** Ordered bound deployment-context names for this job (multi-env jobs). */
142
+ contexts?: string[]) => void;
130
143
  /**
131
144
  * Optional callback to emit run.event messages to Platform.
132
145
  * Fires at orchestrator lifecycle points (dispatch, agent assignment, job start/complete).
@@ -145,12 +158,37 @@ export interface ExecutionTrackerDeps {
145
158
  metadata?: Record<string, unknown>;
146
159
  durationMs?: number | null;
147
160
  }) => void;
161
+ /**
162
+ * Optional live forward of orchestration/provisioning log lines to Platform,
163
+ * fired in addition to persisting them to `logStorage`. Platform fans these
164
+ * out to run-detail browser subscribers as `orch-log.lines`. Best-effort:
165
+ * a push failure must never break dispatch.
166
+ *
167
+ * SECURITY: like `onRunEventEmit`, this payload MUST NOT carry an `orgId`.
168
+ * The Platform attributes the tenant from `authState.orgId`.
169
+ */
170
+ onOrchLog?: (chunk: {
171
+ runId: string;
172
+ jobId: string;
173
+ phase: OrchLogPhase;
174
+ lines: string[];
175
+ ts: number;
176
+ }) => void;
148
177
  /** Optional log storage for writing per-job orchestration logs (JSONL). */
149
178
  logStorage?: LogStorage;
150
179
  /** Org ID for this orchestrator instance (used in run.event emission). */
151
180
  orgId?: string;
152
181
  /** Optional job queue for cascading run failures to dispatch_queue entries. */
153
182
  jobQueue?: JobQueue;
183
+ /**
184
+ * Resolves a routing key to its owning org (customer_id), used to populate
185
+ * `execution_runs.customer_id` at insert time so the concurrency-gate running
186
+ * count is scoped per tenant. Injected (bound to `(rk) => resolveOrgId(db, rk)`
187
+ * at construction) to keep the tracker free of a pipeline import cycle. When
188
+ * absent — or when a run has no routing key — the row falls back to the
189
+ * `'__default__'` column default (the no-source fallback org).
190
+ */
191
+ resolveOrgId?: (routingKey: string) => Promise<string>;
154
192
  }
155
193
  export declare class ExecutionTracker {
156
194
  private readonly db;
@@ -163,9 +201,11 @@ export declare class ExecutionTracker {
163
201
  private readonly onExecutionStatusChange?;
164
202
  private readonly onJobStatusChange?;
165
203
  private readonly onRunEventEmit?;
204
+ private readonly onOrchLog?;
166
205
  private readonly logStorage?;
167
206
  private readonly orgId?;
168
207
  private readonly jobQueue?;
208
+ private readonly resolveOrgIdFn?;
169
209
  private readonly runs;
170
210
  /**
171
211
  * Per-run async-mutex chain. `onJobStatus` and `addJobsToRun` mutate the same
@@ -200,6 +240,12 @@ export declare class ExecutionTracker {
200
240
  /** Callback fired when a job's needs are satisfied and it's ready for dispatch. */
201
241
  onJobReadyCallback?: (runId: string, jobName: string) => Promise<void>;
202
242
  constructor(deps: ExecutionTrackerDeps);
243
+ /**
244
+ * Resolve the owning org for an `execution_runs` row from its routing key.
245
+ * Falls back to the `'__default__'` org (the column default) when the run has
246
+ * no routing key or no resolver is injected (single-tenant / test contexts).
247
+ */
248
+ private resolveCustomerId;
203
249
  /**
204
250
  * Register a callback fired when a job's needs become satisfied.
205
251
  * The processor sets this to dispatch newly-ready jobs to agents.
@@ -222,8 +268,8 @@ export declare class ExecutionTracker {
222
268
  waveGated?: boolean;
223
269
  waveMaxParallel?: number;
224
270
  waveFailFast?: boolean;
225
- environments?: string[];
226
- skippedEnvironments?: string[];
271
+ contexts?: string[];
272
+ skippedContexts?: string[];
227
273
  envWarning?: string;
228
274
  }>, routingKey?: string,
229
275
  /** Secret context names dispatched with jobs (for context-disable job lookup). */
@@ -254,7 +300,9 @@ export declare class ExecutionTracker {
254
300
  /** Immutable provider user id of the triggering actor. */
255
301
  triggerActorUserId?: string | null,
256
302
  /** Agent provenance label when triggered through an agent credential. */
257
- triggeredByAgentLabel?: string | null): Promise<void>;
303
+ triggeredByAgentLabel?: string | null,
304
+ /** Pull-request number for PR-triggered runs; null/omitted for non-PR runs. */
305
+ prNumber?: number | null): Promise<void>;
258
306
  /**
259
307
  * Upsert one execution_jobs row per dispatched job (idempotent on
260
308
  * (run_id, job_id) to tolerate a race with an early `onJobStatus`). The
@@ -311,8 +359,8 @@ export declare class ExecutionTracker {
311
359
  baseJobName?: string;
312
360
  variantKind?: string;
313
361
  variantLabel?: string;
314
- environments?: string[];
315
- skippedEnvironments?: string[];
362
+ contexts?: string[];
363
+ skippedContexts?: string[];
316
364
  envWarning?: string;
317
365
  }>, dispatchedContexts?: string[],
318
366
  /** Synthetic job ID to replace (e.g. needs-pending-deploy-{uuid}). */
@@ -438,12 +486,17 @@ export declare class ExecutionTracker {
438
486
  */
439
487
  onBuildFailedBeforeTracking(runId: string, workflowName: string, provider: string, repoIdentifier: string, ref: string, sha: string, deliveryId: string | null, providerContext: Record<string, unknown>, routingKey: string, triggerEvent?: string, commitMessage?: string, failureReason?: string, initFailure?: InitFailure): Promise<void>;
440
488
  /**
441
- * Insert a `failed` execution_runs row directly for an init failure that
442
- * occurred BEFORE onExecutionStarted ran (so no in-memory state exists
443
- * and no jobs were dispatched). Also writes the structured init_failure
444
- * signal and fires onExecutionStatusChange so Platform's projection picks
445
- * it up via the normal forward path. Idempotent: if a row already exists
446
- * for this runId, the insert is a no-op (ON CONFLICT DO NOTHING).
489
+ * Write a `failed` execution_runs row directly for an init failure, and drop
490
+ * any in-memory run so the recorded failure is the run's final word. Also
491
+ * writes the structured init_failure signal and fires onExecutionStatusChange
492
+ * so Platform's projection picks it up via the normal forward path.
493
+ *
494
+ * An existing row for this runId is overwritten while it is still live
495
+ * dispatch may already have registered the run before init failed — and left
496
+ * alone once it is terminal, so a run that genuinely finished is never
497
+ * rewritten as failed. When the guard leaves the row alone, the failure
498
+ * metric and the Platform forward are suppressed with it: this orchestrator
499
+ * did not record the init failure, so it must not report one.
447
500
  *
448
501
  * Closes the silent pre-run-failure gap — without this helper, secret /
449
502
  * install-secret / all-jobs-rejected early-exits in dispatch-matched-workflow
@@ -469,7 +522,11 @@ export declare class ExecutionTracker {
469
522
  * `execution_runs` row in the `held` state — alive and resumable — so the
470
523
  * dashboard run list surfaces the paused workflow. No jobs are tracked: the
471
524
  * workflow-scoped held_runs row + pending workflow context (written by the
472
- * caller) keep the run from being counted complete. Idempotent on runId.
525
+ * caller) keep the run from being counted complete, and any in-memory run is
526
+ * dropped so jobs registered before the gate cannot roll it up.
527
+ *
528
+ * An existing row for this runId is flipped to `held` while it is still live
529
+ * and left alone once it is terminal — a finished run is never re-held.
473
530
  */
474
531
  recordRunHeld(args: {
475
532
  runId: string;
@@ -481,10 +538,17 @@ export declare class ExecutionTracker {
481
538
  deliveryId: string | null;
482
539
  providerContext: Record<string, unknown>;
483
540
  routingKey: string;
484
- environmentName?: string;
541
+ contextName?: string;
485
542
  reason: string;
486
543
  triggerEvent?: string;
487
544
  commitMessage?: string;
545
+ /**
546
+ * Pull-request number for PR-triggered holds; null/omitted for non-PR runs.
547
+ * Stamped so PR-scoped `/kici approve|reject` (which joins `execution_runs`
548
+ * on `pr_number`) can attribute the held run to its PR — a NULL leaves a
549
+ * security hold fail-closed unreachable by the comment path.
550
+ */
551
+ prNumber?: number | null;
488
552
  }): Promise<void>;
489
553
  /**
490
554
  * Flip a `held` run back to `pending` so the resumed dispatch can proceed
@@ -524,6 +588,54 @@ export declare class ExecutionTracker {
524
588
  * Check if all tracked jobs in a run have reached terminal state.
525
589
  */
526
590
  isRunComplete(runId: string): boolean;
591
+ /**
592
+ * Take a token holding a run open while some of its jobs are still to be
593
+ * registered. Returns true when a token was taken, false for an unknown or
594
+ * already-completed run (nothing to hold).
595
+ *
596
+ * Three registration windows need this. A run whose source-pack `__build__`
597
+ * job is dispatched first is registered with that job ALONE, and its real
598
+ * jobs are only dispatched once the build finishes. A deferred init job and a
599
+ * deferred dynamic entry each register their jobs from a fire-and-forget task
600
+ * that outlives the dispatch call. In every case, without a token the already
601
+ * -registered jobs reaching a terminal state satisfies {@link isRunComplete},
602
+ * so the run is finalized early: a terminal run status is written, the
603
+ * provider check is posted, and the status is forwarded to the Platform — all
604
+ * before a single real job has run.
605
+ *
606
+ * The hold is a counter on the in-memory run, read only by
607
+ * {@link isRunComplete} — deliberately NOT a synthetic entry in the run's job
608
+ * map. The job map is what every outward projection enumerates (the Platform
609
+ * `state.replay` snapshot and its `execution_jobs` mirror, the reported job
610
+ * count, the workflow-complete job results, the active-run summary), so a
611
+ * marker parked there would surface as a phantom pending job on the dashboard
612
+ * and an off-by-one job count for the length of the window. A counter holds
613
+ * the completion check open without being visible to any of them, and it
614
+ * writes no `execution_jobs` row, so it never surfaces as a phantom job.
615
+ * A token whose holder never settles keeps the run `running` until the stale
616
+ * detector reaps it — the same backstop that covers a job that never
617
+ * reports.
618
+ *
619
+ * Each token must be paired with exactly one {@link releasePendingJobsHold}.
620
+ */
621
+ holdRunForPendingJobs(runId: string): boolean;
622
+ /**
623
+ * Drop one token taken by {@link holdRunForPendingJobs}, and finalize the run
624
+ * if dropping the LAST one left every remaining job terminal.
625
+ *
626
+ * The re-evaluation matters for the same reason it does in `addJobsToRun`:
627
+ * once the last token is gone nothing else drives a completion check (no
628
+ * further `job.status` messages are coming for already-finished jobs), so a
629
+ * run whose jobs all finished while a token was held would otherwise hang in
630
+ * `running` forever. Only the last release may finalize — while any other
631
+ * token is outstanding more jobs are still on their way.
632
+ *
633
+ * Idempotent — a no-op when no token is outstanding. The count clamps at
634
+ * zero so a stray extra release cannot drive it negative, which would
635
+ * permanently un-hold the run and stop a genuinely outstanding token from
636
+ * holding it open.
637
+ */
638
+ releasePendingJobsHold(runId: string): Promise<void>;
527
639
  /**
528
640
  * Get the current overall status of a run.
529
641
  */
@@ -533,6 +645,16 @@ export declare class ExecutionTracker {
533
645
  * Used by LogWriter to construct log paths.
534
646
  */
535
647
  getJobName(runId: string, jobId: string): string | undefined;
648
+ /**
649
+ * Find the runId of the in-memory run that owns a given dispatched jobId.
650
+ *
651
+ * The agent's `event.emit` message is job-scoped (it carries only the
652
+ * emitting jobId), but run context is keyed by runId. This maps job → run so
653
+ * `getExecutionContext(runId)` resolves for an agent-emitted custom event.
654
+ * In-memory only (matches `getExecutionContext`'s semantics); emit happens
655
+ * mid-execution, so the owning run is always live in `this.runs`.
656
+ */
657
+ getRunIdForJob(jobId: string): string | undefined;
536
658
  /**
537
659
  * Get execution context for a run from in-memory state.
538
660
  * Used by commit status reporting to access provider/repo/sha info.
@@ -584,6 +706,7 @@ export declare class ExecutionTracker {
584
706
  triggeredBy?: string | null;
585
707
  triggeredByAgentLabel?: string | null;
586
708
  failureReason?: string;
709
+ failureClass?: RunFailureClass;
587
710
  jobCount: number;
588
711
  startedAt: number;
589
712
  completedAt?: number;
@@ -659,13 +782,35 @@ export declare class ExecutionTracker {
659
782
  * stale detector when memRun is still tracked locally — writes the
660
783
  * execution_runs terminal row, fires Platform-forwarding +
661
784
  * workflow-complete callbacks, and schedules in-memory pruning.
785
+ *
786
+ * The terminal write is clobber-guarded. If the guard rejects it (the run
787
+ * already finished through the normal path), only the pruning happens: the
788
+ * recomputed status is not this orchestrator's record of the run, so neither
789
+ * the callbacks nor the completion metrics may claim it.
662
790
  */
663
791
  private completeRunFromMemoryState;
792
+ /**
793
+ * Drop a finished run's in-memory state after a grace period, so a late
794
+ * status/heartbeat arriving just after completion still finds its run.
795
+ *
796
+ * This is the single owner of run-lifetime state teardown, so every
797
+ * run-lifetime map is cleared here — including `testRunIds`: a run finished by
798
+ * the stale detector rather than the normal completion path would otherwise
799
+ * leave its observer-broadcast marker behind for the process's lifetime.
800
+ * (`runLockTails` is deliberately not touched: it is keyed by runId but scoped
801
+ * to a lock's holders, and `withRunLock` drops its own entry on release.)
802
+ */
803
+ private scheduleRunPrune;
664
804
  /**
665
805
  * Path B helper: complete a run using DB rows only (crash recovery /
666
806
  * pruned runs). Loads jobs + run row from execution_jobs/execution_runs,
667
807
  * checks the all-terminal predicate + run-state guard, then writes the
668
808
  * terminal row and fires Platform-forwarding callbacks.
809
+ *
810
+ * The run-state read and the terminal write are separate statements, so the
811
+ * write carries its own clobber guard. If that guard rejects it — a
812
+ * concurrent normal completion landed in between — the callbacks and the
813
+ * completion metrics are suppressed with it.
669
814
  */
670
815
  private completeRunFromDbFallback;
671
816
  /**
@@ -704,10 +849,21 @@ export declare class ExecutionTracker {
704
849
  *
705
850
  * Per locked decision:
706
851
  * - success ONLY if ALL jobs pass (skipped jobs count as success)
707
- * - failed if ANY job failed or timed_out_stale
852
+ * - failed if ANY job ended in a failure status (see `STATUS_FAILURE_CLASS`)
708
853
  * - cancelled if ANY job cancelled (and none failed)
709
854
  */
710
855
  private computeRunStatus;
856
+ /**
857
+ * Derive the failure class from a terminal run's job statuses. Null for
858
+ * success (and any non-terminal status). `timed_out_stale` / `drift_dropped`
859
+ * / `unroutable` jobs — a job that never dispatched, whose `runsOn` matched no
860
+ * agent, whose agent went silent, or that was dropped by a topology reroute —
861
+ * are infra-class and collapse to `timed_out`; any other `failed` run is a
862
+ * `step_failure` (a job actually ran and failed). `never_started` (init
863
+ * failure) and `dead_orchestrator` (Platform-detected) are stamped by their
864
+ * own paths, not here.
865
+ */
866
+ private computeFailureClass;
711
867
  }
712
868
  export {};
713
869
  //# sourceMappingURL=execution-tracker.d.ts.map
@@ -1,8 +1,9 @@
1
1
  /**
2
2
  * Filesystem-backed log storage.
3
3
  *
4
- * Stores execution logs as files on disk. No TTL -- logs persist indefinitely.
5
- * Supports append-only writes (JSONL accumulation) and cursor-based pagination.
4
+ * Stores execution logs as files on disk. Lifecycle is operator-managed (the
5
+ * cleanup retention sweep runs on the S3 backend only). Supports append-only
6
+ * writes (JSONL accumulation) and cursor-based pagination.
6
7
  *
7
8
  * File layout:
8
9
  * {basePath}/executions/{runId}/job-{name}/step-{index}.log
@@ -14,6 +15,27 @@ interface FilesystemLogStorageOptions {
14
15
  export declare class FilesystemLogStorage implements LogStorage {
15
16
  private readonly basePath;
16
17
  constructor(options: FilesystemLogStorageOptions);
18
+ /**
19
+ * Resolve a logical log path to an absolute filesystem path, refusing
20
+ * anything that would address a file outside the storage root.
21
+ *
22
+ * Two checks, deliberately both. `assertSafeLogPath` is the effective gate on
23
+ * POSIX: once a path is relative and carries no `..` segment, `resolve()`
24
+ * cannot produce anything outside the root, so the comparison below is
25
+ * unreachable there. It is kept as a second, independent statement of the
26
+ * same invariant — it is what catches a resolver with extra escape hatches
27
+ * (win32 resolves a drive-relative `C:foo` against that drive's own cwd, not
28
+ * against the root), and it means relaxing the logical check cannot silently
29
+ * reopen an escape.
30
+ *
31
+ * Both checks are lexical — neither resolves symlinks. A symlink planted
32
+ * inside the log root still redirects a logically-clean path outside it;
33
+ * containing that would need a `realpath` on every call, and the log root is
34
+ * the orchestrator user's own directory.
35
+ *
36
+ * Every verb on this class funnels through here, so a new caller is
37
+ * contained on arrival.
38
+ */
17
39
  private fullPath;
18
40
  /**
19
41
  * Ensure the directory for a given file path exists.
@@ -33,9 +55,16 @@ export declare class FilesystemLogStorage implements LogStorage {
33
55
  */
34
56
  private listRecursive;
35
57
  append(path: string, data: string): Promise<void>;
58
+ appendStreaming(path: string, data: string): Promise<void>;
59
+ finalize(_path: string): Promise<void>;
36
60
  read(path: string, options?: LogReadOptions): Promise<LogReadResult>;
37
61
  exists(path: string): Promise<boolean>;
38
62
  list(prefix: string): Promise<string[]>;
63
+ listWithMetadata(prefix: string): Promise<Array<{
64
+ path: string;
65
+ lastModified: Date;
66
+ }>>;
67
+ deleteMany(paths: string[]): Promise<number>;
39
68
  }
40
69
  export {};
41
70
  //# sourceMappingURL=fs-log-storage.d.ts.map