@kici-dev/compiler 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 (199) hide show
  1. package/dist/auth/headless-detect.d.ts +14 -5
  2. package/dist/auth/headless-detect.js +50 -9
  3. package/dist/cli-banner.d.ts +6 -3
  4. package/dist/cli-banner.js +13 -5
  5. package/dist/cli.js +180 -48
  6. package/dist/commands/check-mode.d.ts +1 -1
  7. package/dist/commands/compile.js +31 -7
  8. package/dist/commands/diagnostics.js +14 -2
  9. package/dist/commands/doctor.d.ts +64 -0
  10. package/dist/commands/doctor.js +413 -0
  11. package/dist/commands/endpoints.js +6 -0
  12. package/dist/commands/fixture.js +13 -0
  13. package/dist/commands/hook.js +3 -2
  14. package/dist/commands/index.d.ts +13 -1
  15. package/dist/commands/index.js +10 -3
  16. package/dist/commands/init-host-os.d.ts +34 -0
  17. package/dist/commands/init-host-os.js +44 -0
  18. package/dist/commands/init.d.ts +4 -0
  19. package/dist/commands/init.js +160 -37
  20. package/dist/commands/local-trust-root.d.ts +6 -0
  21. package/dist/commands/local-trust-root.js +52 -0
  22. package/dist/commands/local.d.ts +65 -0
  23. package/dist/commands/local.js +206 -0
  24. package/dist/commands/login.d.ts +2 -0
  25. package/dist/commands/login.js +41 -1
  26. package/dist/commands/logout.js +7 -0
  27. package/dist/commands/notifications.d.ts +61 -0
  28. package/dist/commands/notifications.js +274 -0
  29. package/dist/commands/preview.js +9 -2
  30. package/dist/commands/run-banner.d.ts +31 -0
  31. package/dist/commands/run-banner.js +25 -0
  32. package/dist/commands/run-routed.d.ts +53 -0
  33. package/dist/commands/run-routed.js +185 -0
  34. package/dist/commands/run.d.ts +0 -17
  35. package/dist/commands/run.js +44 -58
  36. package/dist/commands/runs/artifacts/download.d.ts +24 -0
  37. package/dist/commands/runs/artifacts/download.js +154 -0
  38. package/dist/commands/runs/artifacts/list.d.ts +5 -0
  39. package/dist/commands/runs/artifacts/list.js +47 -0
  40. package/dist/commands/runs/cancel.js +2 -2
  41. package/dist/commands/runs/list.js +8 -2
  42. package/dist/commands/secrets-list.d.ts +2 -2
  43. package/dist/commands/secrets-list.js +4 -4
  44. package/dist/commands/types.d.ts +3 -3
  45. package/dist/commands/types.js +4 -4
  46. package/dist/commands/verify-attestation.d.ts +3 -1
  47. package/dist/commands/verify-attestation.js +18 -7
  48. package/dist/errors/formatter.d.ts +14 -1
  49. package/dist/errors/formatter.js +13 -3
  50. package/dist/errors/index.d.ts +2 -1
  51. package/dist/errors/index.js +3 -2
  52. package/dist/errors/source-location.d.ts +20 -0
  53. package/dist/errors/source-location.js +45 -0
  54. package/dist/execution/executor.js +32 -12
  55. package/dist/fixtures/defaults/index.js +2 -1
  56. package/dist/generators/secrets-dts.d.ts +9 -9
  57. package/dist/generators/secrets-dts.js +12 -12
  58. package/dist/llm-context/llms-architecture.txt +50 -21
  59. package/dist/llm-context/llms-cli.txt +2667 -1454
  60. package/dist/llm-context/llms-features.txt +484 -414
  61. package/dist/llm-context/llms-full.txt +6703 -4687
  62. package/dist/llm-context/llms-getting-started.txt +311 -55
  63. package/dist/llm-context/llms-patterns.txt +17 -29
  64. package/dist/llm-context/llms-providers.txt +10 -1
  65. package/dist/llm-context/llms-sdk-runtime.txt +2013 -0
  66. package/dist/llm-context/llms-sdk.txt +596 -2157
  67. package/dist/llm-context/llms.txt +31 -17
  68. package/dist/local-plane/orchestrator-process.d.ts +70 -0
  69. package/dist/local-plane/orchestrator-process.js +129 -0
  70. package/dist/local-plane/os-mismatch-hint.d.ts +16 -0
  71. package/dist/local-plane/os-mismatch-hint.js +34 -0
  72. package/dist/local-plane/paths.d.ts +39 -0
  73. package/dist/local-plane/paths.js +54 -0
  74. package/dist/local-plane/plane-liveness.d.ts +68 -0
  75. package/dist/local-plane/plane-liveness.js +145 -0
  76. package/dist/local-plane/plane-manager.d.ts +193 -0
  77. package/dist/local-plane/plane-manager.js +480 -0
  78. package/dist/local-plane/plane-seed.d.ts +76 -0
  79. package/dist/local-plane/plane-seed.js +59 -0
  80. package/dist/local-plane/plane-trigger.d.ts +71 -0
  81. package/dist/local-plane/plane-trigger.js +110 -0
  82. package/dist/local-plane/platform-attach.d.ts +53 -0
  83. package/dist/local-plane/platform-attach.js +107 -0
  84. package/dist/local-plane/port-holder.d.ts +78 -0
  85. package/dist/local-plane/port-holder.js +227 -0
  86. package/dist/local-plane/postgres.d.ts +56 -0
  87. package/dist/local-plane/postgres.js +187 -0
  88. package/dist/local-plane/resolve-plane.d.ts +37 -0
  89. package/dist/local-plane/resolve-plane.js +76 -0
  90. package/dist/local-plane/run-follow.d.ts +61 -0
  91. package/dist/local-plane/run-follow.js +151 -0
  92. package/dist/local-plane/scaler-config.d.ts +68 -0
  93. package/dist/local-plane/scaler-config.js +132 -0
  94. package/dist/local-plane/secret-seed.d.ts +59 -0
  95. package/dist/local-plane/secret-seed.js +112 -0
  96. package/dist/local-plane/source-provider.d.ts +43 -0
  97. package/dist/local-plane/source-provider.js +159 -0
  98. package/dist/local-plane/trusted-routing.d.ts +32 -0
  99. package/dist/local-plane/trusted-routing.js +47 -0
  100. package/dist/lockfile/generator.d.ts +14 -1
  101. package/dist/lockfile/generator.js +103 -37
  102. package/dist/lockfile/index.d.ts +3 -1
  103. package/dist/lockfile/index.js +3 -2
  104. package/dist/lockfile/purity-diagnostics.d.ts +31 -0
  105. package/dist/lockfile/purity-diagnostics.js +52 -0
  106. package/dist/postinstall.js +2 -1
  107. package/dist/remote/artifact-extract.d.ts +8 -0
  108. package/dist/remote/artifact-extract.js +58 -0
  109. package/dist/remote/config.d.ts +21 -3
  110. package/dist/remote/config.js +24 -5
  111. package/dist/remote/dashboard-client.d.ts +46 -9
  112. package/dist/remote/dashboard-client.js +54 -11
  113. package/dist/remote/fs-case.d.ts +21 -0
  114. package/dist/remote/fs-case.js +45 -0
  115. package/dist/remote/history.d.ts +9 -3
  116. package/dist/remote/history.js +79 -10
  117. package/dist/remote/local-repo-identity.d.ts +1 -1
  118. package/dist/remote/local-repo-identity.js +2 -1
  119. package/dist/remote/notifications-client.d.ts +149 -0
  120. package/dist/remote/notifications-client.js +103 -0
  121. package/dist/remote/oauth.d.ts +13 -0
  122. package/dist/remote/oauth.js +31 -5
  123. package/dist/remote/output/summary.js +76 -14
  124. package/dist/remote/platform-client.d.ts +1 -1
  125. package/dist/remote/render.js +30 -9
  126. package/dist/{local-executor → remote}/secret-loader.d.ts +1 -1
  127. package/dist/{local-executor → remote}/secret-loader.js +4 -4
  128. package/dist/remote/secret-upload.d.ts +1 -1
  129. package/dist/remote/secret-upload.js +2 -2
  130. package/dist/remote/uploader.d.ts +1 -1
  131. package/dist/remote/uploader.js +7 -6
  132. package/dist/templates/agents-md.d.ts +1 -1
  133. package/dist/templates/agents-md.js +8 -8
  134. package/dist/templates/index.d.ts +1 -1
  135. package/dist/templates/index.js +2 -2
  136. package/dist/templates/package-json.d.ts +15 -0
  137. package/dist/templates/package-json.js +26 -5
  138. package/dist/test-runner/dry-run.d.ts +2 -1
  139. package/dist/test-runner/dry-run.js +18 -1
  140. package/dist/test-runner/event-types.d.ts +2 -0
  141. package/dist/test-runner/event-types.js +3 -0
  142. package/dist/test-runner/job-executor.d.ts +1 -0
  143. package/dist/test-runner/job-executor.js +82 -44
  144. package/dist/test-runner/output-formatter.d.ts +5 -2
  145. package/dist/test-runner/output-formatter.js +6 -4
  146. package/dist/test-runner/payload-builder.d.ts +7 -1
  147. package/dist/test-runner/payload-builder.js +11 -2
  148. package/dist/test-runner/rule-evaluator.d.ts +7 -3
  149. package/dist/test-runner/rule-evaluator.js +13 -12
  150. package/dist/{local-executor → test-runner}/runs-on-display.js +1 -1
  151. package/dist/test-runner/step-context.d.ts +23 -5
  152. package/dist/test-runner/step-context.js +29 -119
  153. package/dist/types.d.ts +26 -7
  154. package/dist/types.js +4 -2
  155. package/dist/validation/index.d.ts +2 -0
  156. package/dist/validation/index.js +2 -1
  157. package/dist/validation/typecheck.d.ts +28 -0
  158. package/dist/validation/typecheck.js +110 -0
  159. package/dist/validation/validator.d.ts +9 -4
  160. package/dist/validation/validator.js +38 -44
  161. package/package.json +13 -13
  162. package/sbom.spdx.json +9311 -1528
  163. package/dist/assets/api-TJJVHrjC.json +0 -118
  164. package/dist/assets/descriptor-BTtjzN9L.json +0 -1382
  165. package/dist/assets/package-BpQF9kR8.json +0 -74
  166. package/dist/assets/package-Ceo2h27X.json +0 -89
  167. package/dist/assets/source_context-D0atuL28.json +0 -20
  168. package/dist/assets/type-BFqO8SCZ.json +0 -202
  169. package/dist/commands/cancel.d.ts +0 -22
  170. package/dist/commands/detect-package-manager.d.ts +0 -42
  171. package/dist/commands/held-run-resolve.d.ts +0 -50
  172. package/dist/commands/status.d.ts +0 -34
  173. package/dist/commands/test.d.ts +0 -88
  174. package/dist/errors/codes.d.ts +0 -25
  175. package/dist/local-executor/dag-scheduler.d.ts +0 -44
  176. package/dist/local-executor/dag-scheduler.js +0 -183
  177. package/dist/local-executor/index.d.ts +0 -23
  178. package/dist/local-executor/index.js +0 -378
  179. package/dist/local-executor/job-runner.d.ts +0 -47
  180. package/dist/local-executor/job-runner.js +0 -411
  181. package/dist/local-executor/materializer.d.ts +0 -44
  182. package/dist/local-executor/materializer.js +0 -132
  183. package/dist/local-executor/output-streamer.d.ts +0 -31
  184. package/dist/local-executor/output-streamer.js +0 -168
  185. package/dist/local-executor/payload-generator.d.ts +0 -16
  186. package/dist/local-executor/payload-generator.js +0 -138
  187. package/dist/local-executor/picker.d.ts +0 -33
  188. package/dist/local-executor/picker.js +0 -109
  189. package/dist/local-executor/to-event-payload.d.ts +0 -16
  190. package/dist/local-executor/to-event-payload.js +0 -21
  191. package/dist/local-executor/types.d.ts +0 -93
  192. package/dist/local-executor/types.js +0 -2
  193. package/dist/local-executor/workflow-lock.d.ts +0 -82
  194. package/dist/local-executor/workflow-lock.js +0 -0
  195. package/dist/package-F7UXSDHW.json +0 -74
  196. package/dist/remote/client.d.ts +0 -210
  197. package/dist/remote/observer.d.ts +0 -81
  198. package/dist/test-runner/summary.d.ts +0 -7
  199. /package/dist/{local-executor → test-runner}/runs-on-display.d.ts +0 -0
@@ -8,19 +8,23 @@ The full markdown bundle of every page indexed here is available at https://docs
8
8
 
9
9
  Each bundle below is a self-contained markdown file for one authoring task. Fetch only the one your task needs instead of the full bundle:
10
10
 
11
- - [getting-started](https://docs.kici.dev/llms-getting-started.txt) (25 KB) — Install the SDK, write your first workflow, compile and test locally
11
+ - [getting-started](https://docs.kici.dev/llms-getting-started.txt) (51 KB) — Adopt KiCI: why it exists, how workflows execute, migrating from GitHub Actions, installing the SDK, and writing/compiling/testing your first workflow
12
12
  - [patterns](https://docs.kici.dev/llms-patterns.txt) (49 KB) — Copy-paste workflow recipes: triggers, conditionals, matrix, scheduling, integrations
13
- - [sdk](https://docs.kici.dev/llms-sdk.txt) (190 KB) — Authoring API: workflow/job/step factories, triggers, rules, matrix, runtime, caching
14
- - [cli](https://docs.kici.dev/llms-cli.txt) (136 KB) — Running the CLI: compile, test, run local/remote, auth, hooks, lock-file drift
15
- - [features](https://docs.kici.dev/llms-features.txt) (126 KB) — Workflow features: concurrency, environments, secrets, approvals, provenance, events
16
- - [providers](https://docs.kici.dev/llms-providers.txt) (36 KB) — Connecting sources: GitHub App, universal-git (Forgejo/Gitea/GitLab), local file://
17
- - [architecture](https://docs.kici.dev/llms-architecture.txt) (87 KB) — How the runtime works: three-tier relay model, data flows, configuration
13
+ - [sdk](https://docs.kici.dev/llms-sdk.txt) (110 KB) — Core authoring API: workflow/job/step factories, triggers, rules, matrix, dynamic jobs, cross-job outputs
14
+ - [sdk-runtime](https://docs.kici.dev/llms-sdk-runtime.txt) (112 KB) — Runtime and advanced authoring: step runtime context, event payloads, host fan-out, idempotent steps, caching, artifacts, waiting
15
+ - [cli](https://docs.kici.dev/llms-cli.txt) (185 KB) — Running the CLI: compile, test, run local/remote, auth, hooks, lock-file drift
16
+ - [features](https://docs.kici.dev/llms-features.txt) (135 KB) — Workflow features: concurrency, contexts, secrets, approvals, provenance, events
17
+ - [providers](https://docs.kici.dev/llms-providers.txt) (37 KB) — Connecting sources: GitHub App, universal-git (Forgejo/Gitea/GitLab), local file://
18
+ - [architecture](https://docs.kici.dev/llms-architecture.txt) (92 KB) — How the runtime works: three-tier relay model, data flows, configuration
18
19
 
19
20
  ## Getting started
20
21
 
21
- - [User guide](https://docs.kici.dev/user/): Writing and testing CI/CD workflows in TypeScript
22
+ - [User guide](https://docs.kici.dev/user/): Writing and testing CI/CD workflows in TypeScript, running on infrastructure you control
23
+ - [How your workflow code executes](https://docs.kici.dev/user/execution-model/): When and where your workflow TypeScript runs — compile time, orchestrator time, and agent time
22
24
  - [Getting started with workflows](https://docs.kici.dev/user/getting-started/): Install the SDK, write your first workflow, compile and test locally
25
+ - [Migrating from GitHub Actions](https://docs.kici.dev/user/migrating-from-github-actions/): Map GitHub Actions concepts to KiCI, translate a real workflow side-by-side, and see what has no equivalent yet
23
26
  - [5-minute quickstart](https://docs.kici.dev/user/quickstart/): Stand up a KiCI orchestrator + agent and run your first workflow
27
+ - [Why KiCI](https://docs.kici.dev/user/why-kici/): The case for running CI on infrastructure you control, with typed TypeScript workflows you test locally
24
28
 
25
29
  ## Workflow patterns
26
30
 
@@ -31,40 +35,50 @@ Each bundle below is a self-contained markdown file for one authoring task. Fetc
31
35
  - [Pattern reference](https://docs.kici.dev/user/patterns/reference/): Step context, examples repository, GitHub check run output — cross-cutting reference for all patterns
32
36
  - [Scheduling & event patterns](https://docs.kici.dev/user/patterns/scheduling-and-events/): Nightly cron, workflow-complete-triggered deploys, custom event chaining
33
37
 
34
- ## SDK reference
38
+ ## SDK reference: core
35
39
 
36
- - [Caching](https://docs.kici.dev/user/sdk/caching/): Cache files and directories across runs with declarative job/step cache or the imperative ctx.cache API
37
40
  - [SDK reference: core](https://docs.kici.dev/user/sdk/core/): Factory functions (workflow, job, step) and authoring patterns: needs, output chaining, dynamic groups
38
- - [Event payload reference](https://docs.kici.dev/user/sdk/event-payloads/): Generated schema of the normalized event envelope passed to rules and dynamic functions.
39
- - [SDK reference: idempotent](https://docs.kici.dev/user/sdk/idempotent/): Idempotent helpers for declarative check / apply patterns inside workflow steps
40
41
  - [SDK reference: parallel](https://docs.kici.dev/user/sdk/parallel/): Run independent steps concurrently within a single job, each as its own observable step
41
42
  - [SDK reference: rules, matrix, dynamic jobs](https://docs.kici.dev/user/sdk/rules-matrix-dynamic/): rule(), skip(), matrix builds (static + dynamic), and dynamicJob / dynamicGroup
43
+ - [SDK reference: triggers](https://docs.kici.dev/user/sdk/triggers/): GitHub event triggers, kiciEvent, workflowComplete, workflowsFailedBatch, jobComplete, genericWebhook, schedule, lifecycle
44
+ - [SDK reference: validation & events](https://docs.kici.dev/user/sdk/validation-events/): validateDag(), event definitions, and event emission
45
+ - [SDK reference](https://docs.kici.dev/user/sdk-reference/): Complete API reference for @kici-dev/sdk -- workflows, jobs, steps, triggers, rules, matrix, validation, runtime
46
+
47
+ ## SDK reference: runtime and advanced
48
+
49
+ - [Artifacts](https://docs.kici.dev/user/sdk/artifacts/): Share named, durable build outputs between jobs of a run and download them from the run page with ctx.artifacts
50
+ - [Caching](https://docs.kici.dev/user/sdk/caching/): Cache files and directories across runs with declarative job/step cache or the imperative ctx.cache API
51
+ - [Event payload reference](https://docs.kici.dev/user/sdk/event-payloads/): Generated schema of the normalized event envelope passed to rules and dynamic functions.
52
+ - [SDK reference: idempotent](https://docs.kici.dev/user/sdk/idempotent/): Idempotent helpers for declarative check / apply patterns inside workflow steps
42
53
  - [SDK reference: runsOnAll host fan-out](https://docs.kici.dev/user/sdk/runs-on-all/): Fan one job out to every matching connected host, one pinned execution per host
43
54
  - [SDK reference: runtime](https://docs.kici.dev/user/sdk/runtime/): Types index, StepContext, secrets, fixtures
44
- - [SDK reference: triggers](https://docs.kici.dev/user/sdk/triggers/): GitHub event triggers, kiciEvent, workflowComplete, jobComplete, genericWebhook, schedule, lifecycle
45
- - [SDK reference: validation & events](https://docs.kici.dev/user/sdk/validation-events/): validateDag(), event definitions, and event emission
55
+ - [SDK reference: temp directories](https://docs.kici.dev/user/sdk/temp-directories/): Allocate job-scoped scratch dirs and files with ctx.mktemp() / ctx.mktempFile()
46
56
  - [SDK reference: waitFor](https://docs.kici.dev/user/sdk/wait-for/): Polling helpers for steps that pause until an external condition becomes true
47
- - [SDK reference](https://docs.kici.dev/user/sdk-reference/): Complete API reference for @kici-dev/sdk -- workflows, jobs, steps, triggers, rules, matrix, validation, runtime
48
57
 
49
58
  ## CLI and authoring
50
59
 
51
60
  - [Drive KiCI from your coding agent](https://docs.kici.dev/user/ai-agents/): Point a coding agent at KiCI's MCP server and let it trigger, read, and re-run your CI under your own identity.
52
61
  - [CLI authentication](https://docs.kici.dev/user/cli-auth/): Authenticate the KiCI CLI with browser OAuth, device flow, or API key paste
53
- - [CLI reference](https://docs.kici.dev/user/cli-reference/): All CLI commands: compile, run (local/remote), orchestrators, preview, login, logout, org, diagnostics, runs (list/show/logs/rerun/cancel), secrets, types, fixture, init, hook, endpoints, workflows, docs, admin
62
+ - [CLI reference](https://docs.kici.dev/user/cli-reference/): All CLI commands: compile, preview, local, fixture, types, workflows, hook, docs, run, runs, approve, reject, login, logout, init, org, pat, secrets, admin, orchestrators, endpoints, notifications, verify-attestation, diagnostics, doctor
63
+ - [Common failures](https://docs.kici.dev/user/common-failures/): Symptom-to-fix reference for the failures workflow authors hit most — no jobs dispatched, lock-file drift, missing webhooks, and agents that won't connect
54
64
  - [Lifecycle hooks](https://docs.kici.dev/user/hooks/): SDK hook API for cancel, cleanup, success, failure, and step-level callbacks
55
65
  - [Lock file and workflow drift](https://docs.kici.dev/user/lock-file-and-drift/): Keep the lock file in sync with your workflow source and avoid drift
56
66
  - [Testing guide](https://docs.kici.dev/user/testing-guide/): Running remote test fixtures with kici run remote
57
67
  - [Workflow patterns](https://docs.kici.dev/user/workflow-patterns/): Common patterns: monorepo builds, conditional jobs, dynamic matrices, generic webhooks, scheduling
68
+ - [kici: account & org](https://docs.kici.dev/user/cli/account-and-org/): Login, org selection, personal access tokens, secrets, and admin
69
+ - [kici: authoring & local dev](https://docs.kici.dev/user/cli/authoring-and-local/): Compile, preview, local execution, fixtures, types, workflows, hooks, and docs
70
+ - [kici: notifications & diagnostics](https://docs.kici.dev/user/cli/notifications-and-diagnostics/): Notification channels, attestation verification, and diagnostics
71
+ - [kici: runs & approvals](https://docs.kici.dev/user/cli/runs-and-approvals/): Run push and inspection plus approval / rejection of held runs
58
72
 
59
73
  ## Workflow features
60
74
 
61
75
  - [Account and sign-in](https://docs.kici.dev/user/account-and-login/): How your KiCI account relates to sign-in methods, and how to change the way you sign in.
62
76
  - [Approval gates](https://docs.kici.dev/user/approvals/): Pause a workflow for human sign-off at step, job, or workflow granularity with approval
63
77
  - [Concurrency groups](https://docs.kici.dev/user/concurrency/): Control parallel execution with auto-cancel and queue modes
78
+ - [Contexts](https://docs.kici.dev/user/contexts/): Configure deployment contexts with variables, secrets, and protection rules
64
79
  - [Dashboard](https://docs.kici.dev/user/dashboard/): Web UI for monitoring workflow runs, managing sources, secrets, and organization settings.
65
80
  - [Dynamic values](https://docs.kici.dev/user/dynamic-values/)
66
- - [Environment variables](https://docs.kici.dev/user/env-vars/): KICI_* environment variable reference for the CLI
67
- - [Environments](https://docs.kici.dev/user/environments/): Configure deployment environments with variables, secrets, and protection rules
81
+ - [Environment variables](https://docs.kici.dev/user/env-vars/): Environment variable reference for the CLI
68
82
  - [Event system](https://docs.kici.dev/user/events/): How KiCI's event model works -- event types, the registration model, event matching, and circuit breaker protection
69
83
  - [Global workflows](https://docs.kici.dev/user/global-workflows/): Cross-repo workflows that run on events from any repo in the same org
70
84
  - [Idempotent steps and check mode](https://docs.kici.dev/user/idempotent-steps/): Declare desired state with a step check facet, then run in apply or --check preview mode
@@ -0,0 +1,70 @@
1
+ /**
2
+ * Resolve a host address the plane's co-located bare-metal agent can reach for
3
+ * cache-blob fetches. The orchestrator refuses to hand a scaler a loopback
4
+ * storage URL (it assumes remote agents), so the plane advertises its first
5
+ * non-internal IPv4 (still this machine — the agent is co-located). Falls back
6
+ * to the hostname when no external interface is present.
7
+ */
8
+ export declare function resolveAgentReachableHost(): string;
9
+ /**
10
+ * Resolve the built `@kici-dev/orchestrator/standalone` entry the local plane
11
+ * launches in independent (offline) mode.
12
+ */
13
+ export declare function resolveStandaloneEntry(): string;
14
+ /**
15
+ * Resolve the built `@kici-dev/orchestrator/server` entry the local plane
16
+ * launches in hybrid (Platform-attached) mode.
17
+ */
18
+ export declare function resolveServerEntry(): string;
19
+ /** Single `/ready` probe against the local orchestrator. */
20
+ export declare function orchestratorReady(port: number): Promise<boolean>;
21
+ /** Options threading the plane's admin token + bare-metal scaler into the boot. */
22
+ export interface SpawnOrchestratorOptions {
23
+ /** Bootstrap admin token the CLI presents to the plane's admin API. */
24
+ adminToken: string;
25
+ /**
26
+ * Local master secret key (64 hex chars). Enables the orchestrator's secrets
27
+ * subsystem, which is what gates the admin API routes the CLI drives.
28
+ */
29
+ secretKey: string;
30
+ /** Path to the bare-metal scaler YAML (KICI_SCALER_CONFIG_PATH). */
31
+ scalerConfigFile: string;
32
+ /**
33
+ * Path to the dev-signed identity's EC P-256 private JWK (mode 0600), freshly
34
+ * generated by the plane. Enables the orchestrator's local OIDC mint +
35
+ * dev-signed provenance (issuer `kici-local`) in independent mode. Present in
36
+ * the independent boot; omitted (with `attach`) in the hybrid boot, which
37
+ * mints via the Platform relay instead.
38
+ */
39
+ devIdentityKeyFile?: string;
40
+ /**
41
+ * When present, boot the orchestrator in HYBRID mode attached to the Platform
42
+ * relay instead of independent mode. OIDC + attestation then mint via the
43
+ * Platform (the local dev signer is never consulted — the orchestrator's
44
+ * `selectOidcMintRegistration` prefers the relay whenever a Platform
45
+ * connection exists).
46
+ */
47
+ attach?: {
48
+ /** Orchestrator KICI_PLATFORM_URL — a ws(s)://…/ws relay URL. */
49
+ platformWsUrl: string;
50
+ /** Org-scoped orchestrator key (kici_ok_…) presented on WS auth. */
51
+ platformToken: string;
52
+ };
53
+ }
54
+ /**
55
+ * Spawn the orchestrator entry against the local Postgres, detached, with
56
+ * stdout/stderr redirected to the plane log, and return immediately. Boots with
57
+ * a bootstrap admin token (so the CLI can drive the admin API) and a bare-metal
58
+ * scaler (so a dispatched job auto-spawns an ephemeral agent).
59
+ *
60
+ * Returning before the process is ready is deliberate: it lets the caller record
61
+ * the pid on disk BEFORE the readiness wait, so a wait that fails or a CLI that
62
+ * dies mid-boot cannot leave a running orchestrator that nothing can identify.
63
+ */
64
+ export declare function spawnOrchestratorProcess(databaseUrl: string, opts: SpawnOrchestratorOptions): {
65
+ pid: number;
66
+ port: number;
67
+ };
68
+ /** Poll `/ready` until the orchestrator serves, or throw once the attempts run out. */
69
+ export declare function awaitOrchestratorReady(port: number, attempts?: number, intervalMs?: number): Promise<void>;
70
+ //# sourceMappingURL=orchestrator-process.d.ts.map
@@ -0,0 +1,129 @@
1
+ import "../rolldown-runtime-ClRpJifh.js";
2
+ import { planePaths, planePorts } from "./paths.js";
3
+ import { createRequire } from "node:module";
4
+ import fs from "node:fs";
5
+ import { spawn } from "node:child_process";
6
+ import os from "node:os";
7
+ //#region src/local-plane/orchestrator-process.ts
8
+ /**
9
+ * Resolve a host address the plane's co-located bare-metal agent can reach for
10
+ * cache-blob fetches. The orchestrator refuses to hand a scaler a loopback
11
+ * storage URL (it assumes remote agents), so the plane advertises its first
12
+ * non-internal IPv4 (still this machine — the agent is co-located). Falls back
13
+ * to the hostname when no external interface is present.
14
+ */
15
+ function resolveAgentReachableHost() {
16
+ for (const addrs of Object.values(os.networkInterfaces())) for (const a of addrs ?? []) if (a.family === "IPv4" && !a.internal) return a.address;
17
+ return os.hostname();
18
+ }
19
+ /**
20
+ * Resolve the built `@kici-dev/orchestrator/standalone` entry the local plane
21
+ * launches in independent (offline) mode.
22
+ */
23
+ function resolveStandaloneEntry() {
24
+ return createRequire(import.meta.url).resolve("@kici-dev/orchestrator/standalone");
25
+ }
26
+ /**
27
+ * Resolve the built `@kici-dev/orchestrator/server` entry the local plane
28
+ * launches in hybrid (Platform-attached) mode.
29
+ */
30
+ function resolveServerEntry() {
31
+ return createRequire(import.meta.url).resolve("@kici-dev/orchestrator/server");
32
+ }
33
+ /**
34
+ * Cap on one readiness probe. Generous enough for a server still warming up,
35
+ * bounded so a socket that accepts and then goes silent cannot stall the poll
36
+ * for the HTTP client's own multi-minute default — which would make
37
+ * `awaitOrchestratorReady`'s attempt budget meaningless.
38
+ */
39
+ const READY_PROBE_TIMEOUT_MS = 5e3;
40
+ /** Single `/ready` probe against the local orchestrator. */
41
+ async function orchestratorReady(port) {
42
+ try {
43
+ return (await fetch(`http://127.0.0.1:${port}/ready`, { signal: AbortSignal.timeout(READY_PROBE_TIMEOUT_MS) })).status === 200;
44
+ } catch {
45
+ return false;
46
+ }
47
+ }
48
+ /**
49
+ * Spawn the orchestrator entry against the local Postgres, detached, with
50
+ * stdout/stderr redirected to the plane log, and return immediately. Boots with
51
+ * a bootstrap admin token (so the CLI can drive the admin API) and a bare-metal
52
+ * scaler (so a dispatched job auto-spawns an ephemeral agent).
53
+ *
54
+ * Returning before the process is ready is deliberate: it lets the caller record
55
+ * the pid on disk BEFORE the readiness wait, so a wait that fails or a CLI that
56
+ * dies mid-boot cannot leave a running orchestrator that nothing can identify.
57
+ */
58
+ function spawnOrchestratorProcess(databaseUrl, opts) {
59
+ const { orchestrator: port } = planePorts();
60
+ const { logFile, root, cacheDir } = planePaths();
61
+ fs.mkdirSync(root, { recursive: true });
62
+ fs.mkdirSync(cacheDir, { recursive: true });
63
+ const out = fs.openSync(logFile, "a");
64
+ const baseEnv = {};
65
+ for (const [key, value] of Object.entries(process.env)) if (!key.startsWith("KICI_")) baseEnv[key] = value;
66
+ const commonEnv = {
67
+ ...baseEnv,
68
+ KICI_PORT: String(port),
69
+ KICI_DATABASE_URL: databaseUrl,
70
+ KICI_AGENT_AUTH: "none",
71
+ KICI_AUTO_MIGRATE: "true",
72
+ KICI_DATA_DIR: root,
73
+ KICI_BOOTSTRAP_ADMIN_TOKEN: opts.adminToken,
74
+ KICI_SECRET_KEY: opts.secretKey,
75
+ KICI_SCALER_CONFIG_PATH: opts.scalerConfigFile,
76
+ KICI_WEBHOOK_PUBLIC_URL: `http://127.0.0.1:${port}`,
77
+ KICI_STORAGE_TYPE: "filesystem",
78
+ KICI_STORAGE_FS_PATH: cacheDir,
79
+ KICI_STORAGE_FS_BASE_URL: `http://${resolveAgentReachableHost()}:${port}`
80
+ };
81
+ let entry;
82
+ let modeEnv;
83
+ if (opts.attach) {
84
+ entry = resolveServerEntry();
85
+ modeEnv = {
86
+ KICI_MODE: "hybrid",
87
+ KICI_PLATFORM_URL: opts.attach.platformWsUrl,
88
+ KICI_PLATFORM_TOKEN: opts.attach.platformToken
89
+ };
90
+ } else {
91
+ entry = resolveStandaloneEntry();
92
+ modeEnv = {
93
+ KICI_MODE: "independent",
94
+ KICI_INDEPENDENT_SECRETS: "true",
95
+ KICI_INDEPENDENT_IDENTITY: "true",
96
+ KICI_DEV_IDENTITY_KEY_FILE: opts.devIdentityKeyFile,
97
+ KICI_PROVENANCE_ISSUER: "kici-local"
98
+ };
99
+ }
100
+ const child = spawn(process.execPath, [entry], {
101
+ detached: true,
102
+ stdio: [
103
+ "ignore",
104
+ out,
105
+ out
106
+ ],
107
+ env: {
108
+ ...commonEnv,
109
+ ...modeEnv
110
+ }
111
+ });
112
+ child.unref();
113
+ return {
114
+ pid: child.pid,
115
+ port
116
+ };
117
+ }
118
+ /** Poll `/ready` until the orchestrator serves, or throw once the attempts run out. */
119
+ async function awaitOrchestratorReady(port, attempts = 120, intervalMs = 500) {
120
+ for (let i = 0; i < attempts; i++) {
121
+ if (await orchestratorReady(port)) return;
122
+ await new Promise((r) => setTimeout(r, intervalMs));
123
+ }
124
+ throw new Error("local orchestrator did not become ready");
125
+ }
126
+ //#endregion
127
+ export { awaitOrchestratorReady, orchestratorReady, resolveAgentReachableHost, resolveServerEntry, resolveStandaloneEntry, spawnOrchestratorProcess };
128
+
129
+ //# sourceMappingURL=orchestrator-process.js.map
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Detect when a routed local run cannot match the host OS.
3
+ *
4
+ * The local dev plane satisfies the host's own `kici:os:*` label (the scaler
5
+ * injects the host's derived OS labels into its bare-metal label sets). A job
6
+ * that requests a DIFFERENT OS than the host — e.g. a workflow authored on Linux
7
+ * run on a Mac — matches no local backend and dispatches nothing. This surfaces
8
+ * that as an honest hint instead of a silent "nothing happened".
9
+ */
10
+ /**
11
+ * One hint per job whose `runsOn` requires a `kici:os:*` label the host does not
12
+ * provide. Empty when every job either omits an OS selector or requests the
13
+ * host's own OS.
14
+ */
15
+ export declare function detectOsMismatchHints(lock: unknown, platform: string, arch: string): string[];
16
+ //# sourceMappingURL=os-mismatch-hint.d.ts.map
@@ -0,0 +1,34 @@
1
+ import "../rolldown-runtime-ClRpJifh.js";
2
+ import { deriveOsArchLabels } from "@kici-dev/engine";
3
+ //#region src/local-plane/os-mismatch-hint.ts
4
+ /**
5
+ * Detect when a routed local run cannot match the host OS.
6
+ *
7
+ * The local dev plane satisfies the host's own `kici:os:*` label (the scaler
8
+ * injects the host's derived OS labels into its bare-metal label sets). A job
9
+ * that requests a DIFFERENT OS than the host — e.g. a workflow authored on Linux
10
+ * run on a Mac — matches no local backend and dispatches nothing. This surfaces
11
+ * that as an honest hint instead of a silent "nothing happened".
12
+ */
13
+ const OS_LABEL_PREFIX = "kici:os:";
14
+ /**
15
+ * One hint per job whose `runsOn` requires a `kici:os:*` label the host does not
16
+ * provide. Empty when every job either omits an OS selector or requests the
17
+ * host's own OS.
18
+ */
19
+ function detectOsMismatchHints(lock, platform, arch) {
20
+ const hostOsLabels = new Set(deriveOsArchLabels(platform, arch).filter((l) => l.startsWith(OS_LABEL_PREFIX)));
21
+ const hostPrimary = [...hostOsLabels][0] ?? `${OS_LABEL_PREFIX}${platform}`;
22
+ const hints = [];
23
+ for (const workflow of lock.workflows ?? []) for (const job of workflow.jobs ?? []) {
24
+ const requestedOs = (job.runsOn ?? []).filter((m) => m.kind === "exact" && m.value?.startsWith(OS_LABEL_PREFIX)).map((m) => m.value);
25
+ if (requestedOs.length === 0) continue;
26
+ if (requestedOs.some((l) => hostOsLabels.has(l))) continue;
27
+ hints.push(`Job '${job.name ?? "job"}' wants ${requestedOs.join(", ")} but this host is ${platform} — nothing will dispatch locally. Retry with ${hostPrimary} or edit the job's runsOn in .kici/workflows/.`);
28
+ }
29
+ return hints;
30
+ }
31
+ //#endregion
32
+ export { detectOsMismatchHints };
33
+
34
+ //# sourceMappingURL=os-mismatch-hint.js.map
@@ -0,0 +1,39 @@
1
+ /**
2
+ * On-disk layout version of the local dev plane. Bumped when the state-dir
3
+ * structure changes incompatibly, so a stamped plane from an older layout is
4
+ * recreated rather than reused.
5
+ */
6
+ export declare const PLANE_STAMP_VERSION = 3;
7
+ /**
8
+ * Root directory of the local dev plane's state, following the same
9
+ * `KICI_CONFIG_DIR` → `~/.kici` convention the rest of the CLI uses.
10
+ */
11
+ export declare function planeRoot(): string;
12
+ /**
13
+ * Absolute paths for every artefact the plane persists under its state root.
14
+ */
15
+ export declare function planePaths(): {
16
+ root: string;
17
+ pgData: string;
18
+ pidfile: string;
19
+ stampFile: string;
20
+ logFile: string;
21
+ socketDir: string;
22
+ adminTokenFile: string;
23
+ platformTokenFile: string;
24
+ attachmentFile: string;
25
+ secretKeyFile: string;
26
+ scalerConfigFile: string;
27
+ agentWrapperFile: string;
28
+ devIdentityDir: string;
29
+ cacheDir: string;
30
+ };
31
+ /**
32
+ * Fixed localhost ports for the plane's orchestrator (HTTP+WS) and Postgres.
33
+ * Overridable via `KICI_LOCAL_ORCH_PORT` / `KICI_LOCAL_PG_PORT`.
34
+ */
35
+ export declare function planePorts(): {
36
+ orchestrator: number;
37
+ postgres: number;
38
+ };
39
+ //# sourceMappingURL=paths.d.ts.map
@@ -0,0 +1,54 @@
1
+ import "../rolldown-runtime-ClRpJifh.js";
2
+ import path from "node:path";
3
+ import os from "node:os";
4
+ //#region src/local-plane/paths.ts
5
+ /**
6
+ * On-disk layout version of the local dev plane. Bumped when the state-dir
7
+ * structure changes incompatibly, so a stamped plane from an older layout is
8
+ * recreated rather than reused.
9
+ */
10
+ const PLANE_STAMP_VERSION = 3;
11
+ /**
12
+ * Root directory of the local dev plane's state, following the same
13
+ * `KICI_CONFIG_DIR` → `~/.kici` convention the rest of the CLI uses.
14
+ */
15
+ function planeRoot() {
16
+ const base = process.env.KICI_CONFIG_DIR ?? path.join(os.homedir(), ".kici");
17
+ return path.join(base, "local");
18
+ }
19
+ /**
20
+ * Absolute paths for every artefact the plane persists under its state root.
21
+ */
22
+ function planePaths() {
23
+ const root = planeRoot();
24
+ return {
25
+ root,
26
+ pgData: path.join(root, "pgdata"),
27
+ pidfile: path.join(root, "plane.pid"),
28
+ stampFile: path.join(root, "stamp.json"),
29
+ logFile: path.join(root, "orchestrator.log"),
30
+ socketDir: path.join(root, "sock"),
31
+ adminTokenFile: path.join(root, "admin-token"),
32
+ platformTokenFile: path.join(root, "platform-token"),
33
+ attachmentFile: path.join(root, "attachment.json"),
34
+ secretKeyFile: path.join(root, "secret-key"),
35
+ scalerConfigFile: path.join(root, "scaler.yaml"),
36
+ agentWrapperFile: path.join(root, "agent-wrapper.sh"),
37
+ devIdentityDir: path.join(root, "dev-identity"),
38
+ cacheDir: path.join(root, "cache")
39
+ };
40
+ }
41
+ /**
42
+ * Fixed localhost ports for the plane's orchestrator (HTTP+WS) and Postgres.
43
+ * Overridable via `KICI_LOCAL_ORCH_PORT` / `KICI_LOCAL_PG_PORT`.
44
+ */
45
+ function planePorts() {
46
+ return {
47
+ orchestrator: Number(process.env.KICI_LOCAL_ORCH_PORT ?? 4319),
48
+ postgres: Number(process.env.KICI_LOCAL_PG_PORT ?? 45432)
49
+ };
50
+ }
51
+ //#endregion
52
+ export { PLANE_STAMP_VERSION, planePaths, planePorts, planeRoot };
53
+
54
+ //# sourceMappingURL=paths.js.map
@@ -0,0 +1,68 @@
1
+ /** The stamp fields classification needs. Structural, to avoid an import cycle with plane-manager. */
2
+ export interface StampIdentity {
3
+ orchestratorPid: number;
4
+ port: number;
5
+ }
6
+ /** The `/health` fields that identify a KiCI orchestrator. */
7
+ export interface KiciHealth {
8
+ uptime: number;
9
+ version?: string;
10
+ buildCommit?: string;
11
+ }
12
+ export type PlaneState = 'stopped' | 'ready' | 'unready' | 'foreign-kici' | 'foreign-unknown';
13
+ export type PlaneClassification = {
14
+ kind: 'free';
15
+ } | {
16
+ kind: 'ours-ready';
17
+ pid: number;
18
+ } | {
19
+ kind: 'ours-unready';
20
+ pid: number;
21
+ checks: Record<string, boolean>;
22
+ } | {
23
+ kind: 'foreign-kici';
24
+ pid: number | null;
25
+ health: KiciHealth;
26
+ } | {
27
+ kind: 'foreign-unknown';
28
+ pid: number | null;
29
+ };
30
+ export interface PlaneProbes {
31
+ isPortFree(port: number): Promise<boolean>;
32
+ findPortHolderPid(port: number): Promise<number | null>;
33
+ /** The parsed `/health` body, or null when it did not answer in time. */
34
+ fetchHealth(port: number): Promise<unknown>;
35
+ fetchReady(port: number): Promise<{
36
+ ok: boolean;
37
+ checks: Record<string, boolean>;
38
+ }>;
39
+ isPidAlive(pid: number): boolean;
40
+ }
41
+ export interface ReclaimResult {
42
+ freed: boolean;
43
+ killedPid?: number;
44
+ error?: string;
45
+ }
46
+ /**
47
+ * Whether a `/health` body came from a KiCI orchestrator. The build-fingerprint
48
+ * fields are the discriminator: an `ok` status alone is far too common to
49
+ * justify signalling the process that produced it.
50
+ */
51
+ export declare function isKiciOrchestratorHealth(body: unknown): body is KiciHealth;
52
+ /** The state label a classification reports to the operator. */
53
+ export declare function planeStateOf(c: PlaneClassification): PlaneState;
54
+ /** The holder pid a classification carries, when it has one. */
55
+ export declare function classificationPid(c: PlaneClassification): number | null;
56
+ /**
57
+ * Decide what, if anything, is holding the plane port and whether it is ours.
58
+ *
59
+ * `stamp` is the on-disk record of the plane this config dir booted; a null
60
+ * stamp means nothing here booted the holder, so any live holder is foreign.
61
+ */
62
+ export declare function classifyPlane(port: number, stamp: StampIdentity | null, probes?: Partial<PlaneProbes>): Promise<PlaneClassification>;
63
+ /**
64
+ * Free the plane port, if it is ours or another KiCI plane orchestrator. A
65
+ * holder that does not identify as one is reported and left strictly alone.
66
+ */
67
+ export declare function reclaimPlanePort(port: number, c: PlaneClassification): Promise<ReclaimResult>;
68
+ //# sourceMappingURL=plane-liveness.d.ts.map
@@ -0,0 +1,145 @@
1
+ import "../rolldown-runtime-ClRpJifh.js";
2
+ import { findPortHolderPid, isPortFree, terminatePid, waitForPortFree } from "./port-holder.js";
3
+ //#region src/local-plane/plane-liveness.ts
4
+ /**
5
+ * One answer to "is a local dev plane running", shared by up, down, and status.
6
+ *
7
+ * Ownership is decided by pid identity — the process actually holding the port
8
+ * versus the pid the stamp names — not by whether a stamp file exists. That is
9
+ * what keeps the three commands consistent: a plane nobody stamped is foreign to
10
+ * all of them, rather than invisible to two and adoptable by the third.
11
+ *
12
+ * Every external effect arrives through `PlaneProbes`, so the policy here is
13
+ * exercised without a subprocess or a socket.
14
+ */
15
+ /**
16
+ * Cap on each loopback probe. The holder these probes exist to diagnose is
17
+ * frequently wedged, and a socket that accepts a connection but never answers
18
+ * would otherwise hang the CLI for the HTTP client's own multi-minute default —
19
+ * turning `kici local status` into the hang it is meant to explain. A holder
20
+ * that cannot answer loopback within this window is treated as not answering.
21
+ */
22
+ const PROBE_TIMEOUT_MS = 2e3;
23
+ const defaultProbes = {
24
+ isPortFree,
25
+ findPortHolderPid,
26
+ async fetchHealth(port) {
27
+ try {
28
+ const r = await fetch(`http://127.0.0.1:${port}/health`, { signal: AbortSignal.timeout(PROBE_TIMEOUT_MS) });
29
+ if (!r.ok) return null;
30
+ return await r.json();
31
+ } catch {
32
+ return null;
33
+ }
34
+ },
35
+ async fetchReady(port) {
36
+ try {
37
+ const r = await fetch(`http://127.0.0.1:${port}/ready`, { signal: AbortSignal.timeout(PROBE_TIMEOUT_MS) });
38
+ const body = await r.json().catch(() => ({}));
39
+ return {
40
+ ok: r.status === 200,
41
+ checks: body.checks ?? {}
42
+ };
43
+ } catch {
44
+ return {
45
+ ok: false,
46
+ checks: {}
47
+ };
48
+ }
49
+ },
50
+ isPidAlive(pid) {
51
+ try {
52
+ process.kill(pid, 0);
53
+ return true;
54
+ } catch {
55
+ return false;
56
+ }
57
+ }
58
+ };
59
+ /**
60
+ * Whether a `/health` body came from a KiCI orchestrator. The build-fingerprint
61
+ * fields are the discriminator: an `ok` status alone is far too common to
62
+ * justify signalling the process that produced it.
63
+ */
64
+ function isKiciOrchestratorHealth(body) {
65
+ if (typeof body !== "object" || body === null) return false;
66
+ const b = body;
67
+ return b.status === "ok" && typeof b.uptime === "number" && "sdkBundleHash" in b && "engineBundleHash" in b;
68
+ }
69
+ /** The state label a classification reports to the operator. */
70
+ function planeStateOf(c) {
71
+ switch (c.kind) {
72
+ case "free": return "stopped";
73
+ case "ours-ready": return "ready";
74
+ case "ours-unready": return "unready";
75
+ case "foreign-kici": return "foreign-kici";
76
+ case "foreign-unknown": return "foreign-unknown";
77
+ }
78
+ }
79
+ /** The holder pid a classification carries, when it has one. */
80
+ function classificationPid(c) {
81
+ return "pid" in c ? c.pid : null;
82
+ }
83
+ /**
84
+ * Decide what, if anything, is holding the plane port and whether it is ours.
85
+ *
86
+ * `stamp` is the on-disk record of the plane this config dir booted; a null
87
+ * stamp means nothing here booted the holder, so any live holder is foreign.
88
+ */
89
+ async function classifyPlane(port, stamp, probes = {}) {
90
+ const p = {
91
+ ...defaultProbes,
92
+ ...probes
93
+ };
94
+ if (await p.isPortFree(port)) return { kind: "free" };
95
+ const holderPid = await p.findPortHolderPid(port);
96
+ if ((holderPid !== null ? stamp !== null && holderPid === stamp.orchestratorPid : stamp !== null && p.isPidAlive(stamp.orchestratorPid)) && stamp !== null) {
97
+ const ready = await p.fetchReady(port);
98
+ return ready.ok ? {
99
+ kind: "ours-ready",
100
+ pid: stamp.orchestratorPid
101
+ } : {
102
+ kind: "ours-unready",
103
+ pid: stamp.orchestratorPid,
104
+ checks: ready.checks
105
+ };
106
+ }
107
+ const health = await p.fetchHealth(port);
108
+ return isKiciOrchestratorHealth(health) ? {
109
+ kind: "foreign-kici",
110
+ pid: holderPid,
111
+ health
112
+ } : {
113
+ kind: "foreign-unknown",
114
+ pid: holderPid
115
+ };
116
+ }
117
+ /**
118
+ * Free the plane port, if it is ours or another KiCI plane orchestrator. A
119
+ * holder that does not identify as one is reported and left strictly alone.
120
+ */
121
+ async function reclaimPlanePort(port, c) {
122
+ if (c.kind === "free") return { freed: true };
123
+ if (c.kind === "foreign-unknown") return {
124
+ freed: false,
125
+ error: `port ${port} is held by a process that is not a KiCI plane orchestrator${c.pid === null ? "" : ` (pid ${c.pid})`} — refusing to stop it`
126
+ };
127
+ const pid = classificationPid(c);
128
+ if (pid === null) return {
129
+ freed: false,
130
+ error: `port ${port} is held by a KiCI plane orchestrator whose pid could not be determined`
131
+ };
132
+ await terminatePid(pid);
133
+ return await waitForPortFree(port) ? {
134
+ freed: true,
135
+ killedPid: pid
136
+ } : {
137
+ freed: false,
138
+ killedPid: pid,
139
+ error: `port ${port} is still held after stopping pid ${pid}`
140
+ };
141
+ }
142
+ //#endregion
143
+ export { classificationPid, classifyPlane, isKiciOrchestratorHealth, planeStateOf, reclaimPlanePort };
144
+
145
+ //# sourceMappingURL=plane-liveness.js.map