@kici-dev/compiler 0.6.1 → 0.8.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 (57) hide show
  1. package/dist/cli.js +2 -2
  2. package/dist/commands/compile.js +5 -1
  3. package/dist/commands/doctor.js +8 -2
  4. package/dist/commands/init.d.ts +9 -0
  5. package/dist/commands/init.js +77 -12
  6. package/dist/commands/local.d.ts +9 -2
  7. package/dist/commands/local.js +14 -4
  8. package/dist/commands/preview.js +1 -1
  9. package/dist/commands/report/identity.d.ts +11 -0
  10. package/dist/commands/report/identity.js +7 -2
  11. package/dist/commands/run-routed.js +4 -0
  12. package/dist/commands/run.js +5 -2
  13. package/dist/commands/runs/logs.js +3 -2
  14. package/dist/commands/types.d.ts +6 -1
  15. package/dist/commands/types.js +2 -1
  16. package/dist/execution/executor.js +7 -1
  17. package/dist/llm-context/llms-architecture.txt +73 -87
  18. package/dist/llm-context/llms-cli-remote.txt +53 -8
  19. package/dist/llm-context/llms-cli.txt +71 -36
  20. package/dist/llm-context/llms-features-execution.txt +52 -6
  21. package/dist/llm-context/llms-features.txt +137 -6
  22. package/dist/llm-context/llms-full.txt +558 -180
  23. package/dist/llm-context/llms-getting-started.txt +5 -5
  24. package/dist/llm-context/llms-patterns.txt +81 -5
  25. package/dist/llm-context/llms-providers.txt +6 -2
  26. package/dist/llm-context/llms-sdk-runtime.txt +33 -18
  27. package/dist/llm-context/llms-sdk.txt +47 -7
  28. package/dist/llm-context/llms.txt +8 -8
  29. package/dist/local-plane/orchestrator-process.d.ts +0 -8
  30. package/dist/local-plane/orchestrator-process.js +6 -14
  31. package/dist/local-plane/paths.d.ts +1 -0
  32. package/dist/local-plane/paths.js +1 -0
  33. package/dist/local-plane/plane-log.d.ts +27 -0
  34. package/dist/local-plane/plane-log.js +39 -0
  35. package/dist/local-plane/plane-manager.js +2 -2
  36. package/dist/local-plane/plane-trigger.d.ts +28 -0
  37. package/dist/local-plane/plane-trigger.js +57 -2
  38. package/dist/local-plane/postgres.js +9 -6
  39. package/dist/local-plane/run-follow.js +2 -1
  40. package/dist/lockfile/generator.js +25 -9
  41. package/dist/lockfile/hasher.d.ts +5 -13
  42. package/dist/lockfile/hasher.js +1 -15
  43. package/dist/lockfile/workspace-siblings.d.ts +46 -0
  44. package/dist/lockfile/workspace-siblings.js +197 -0
  45. package/dist/remote/output/streaming.d.ts +12 -0
  46. package/dist/remote/output/streaming.js +20 -1
  47. package/dist/remote/platform-client.d.ts +2 -0
  48. package/dist/templates/package-json.d.ts +9 -7
  49. package/dist/templates/package-json.js +11 -9
  50. package/dist/test-runner/job-executor.js +1 -1
  51. package/dist/test-runner/rule-evaluator.js +1 -1
  52. package/dist/types.d.ts +6 -1
  53. package/package.json +7 -9
  54. package/sbom.spdx.json +123 -123
  55. package/dist/postinstall.d.ts +0 -9
  56. package/dist/postinstall.js +0 -62
  57. package/hack/postinstall.mjs +0 -105
@@ -46,7 +46,7 @@ The lock file is the seam. Everything left of it is decided once at compile time
46
46
 
47
47
  `kici compile` loads your `.kici/workflows/*.ts`, validates dependencies (no cycles, no missing `needs`), assigns compile-time step IDs (unnamed steps become `step-1`, `step-2`, …), and writes `kici.lock.json`.
48
48
 
49
- The compiler runs your module's **top-level code** to build the workflow object — but that execution's side effects and in-memory state do not travel. Only the resulting workflow structure lands in the lock. Anything your top-level code computes that isn't part of the returned workflow object simply doesn't exist past this point.
49
+ The compiler runs your module's **top-level code** to build the workflow object — but that execution's side effects and in-memory state do not travel. Only the resulting workflow structure lands in the lock. Anything your top-level code computes that isn't part of the returned workflow object doesn't exist past this point.
50
50
 
51
51
  See [compile the workflow](https://docs.kici.dev/user/getting-started/#compile-the-workflow) for the command in context.
52
52
 
@@ -202,7 +202,7 @@ kici runs logs <run-id>
202
202
  When you cannot resolve it yourself, gather a diagnostic bundle:
203
203
 
204
204
  ```bash
205
- kici report --run <run-id> --message "what you expected, and what happened"
205
+ kici report --run <run-id>
206
206
  ```
207
207
 
208
208
  The command writes a ZIP and prints its path and `sha256`. It sends nothing.
@@ -309,7 +309,7 @@ npx kici init
309
309
  This will:
310
310
 
311
311
  1. Create `.kici/` directory with `workflows/`, `tests/`, `types/`, `package.json`, and `tsconfig.json`. The `types/` folder holds a local development aid — TypeScript declarations that `kici types` (and an authenticated `kici compile`) generate from your orchestrator's secret contexts. Its content is a snapshot of one org's secret keys, so it is not committed.
312
- 2. Create a `.kiciignore` file with sensible defaults
312
+ 2. Create two `.kiciignore` files with sensible defaults: one at the repo root, which selects the working-tree files a remote run uploads, and one inside `.kici/`, which declares the paths the per-workflow content hash skips
313
313
  3. Let you choose from starter workflow templates (hello-world, pr-checks)
314
314
  4. Install dependencies using the package manager detected for your repo (npm, pnpm, or yarn)
315
315
  5. Update `.gitignore` to exclude `.kici/node_modules/`, and write `.kici/.gitignore` to keep the generated `types/` declarations untracked (`kici.lock.json` stays tracked — the orchestrator fetches it from your repo)
@@ -588,7 +588,7 @@ Point to a local SDK checkout for IDE autocompletion:
588
588
  {
589
589
  "name": "my-project-kici",
590
590
  "devDependencies": {
591
- "@kici-dev/sdk": ">=0.0.1-0"
591
+ "@kici-dev/sdk": "latest"
592
592
  },
593
593
  "kici": {
594
594
  "sdkPath": "../../packages/sdk"
@@ -600,7 +600,7 @@ The `sdkPath` field tells the compiler where to resolve TypeScript path mappings
600
600
 
601
601
  ### KICI_DEV environment variable
602
602
 
603
- Set `KICI_DEV=true` to use a prerelease-compatible version range (`>=0.0.1-0`) in generated files, which resolves prerelease builds from a local Verdaccio registry:
603
+ Set `KICI_DEV=true` to pin the SDK to the `latest` dist-tag in generated files, which resolves prerelease builds from a local Verdaccio registry:
604
604
 
605
605
  ```bash
606
606
  KICI_DEV=true npx kici init
@@ -725,6 +725,74 @@ For a **minted app token**, prefer re-deriving over transporting — those expir
725
725
  after an hour, so one minted in an earlier job is often already dead by the time
726
726
  a later job reads it. Have the later job name the same secret, or mint its own.
727
727
 
728
+ ## What a job may ask for
729
+
730
+ A credential is authorized against the workflow you wrote, not against the code
731
+ running in the job. Three things must all hold before the orchestrator resolves
732
+ one:
733
+
734
+ 1. **The job declared it.** The orchestrator records the job's `gitCredentials`
735
+ map when it dispatches the job, and compares every request against that
736
+ record. A request naming a credential the job did not declare is refused.
737
+ This is why you pass `credential: 'forge'` — a name — rather than building a
738
+ credential reference in step code.
739
+ 2. **The named context admits the run.** A `prod:` reference runs the `prod`
740
+ context's own protection rules first: its branch restrictions, its
741
+ `minimumTrust`, its approval requirement. A credential named from a branch
742
+ the context does not allow is refused, and the git operation fails. The rule
743
+ that refused it is named in your orchestrator's log, not in the run — the
744
+ orchestrator returns a fixed error to the job rather than describing its own
745
+ configuration to code it does not trust.
746
+ 3. **The contributor is trusted.** A run from an untrusted ref — a fork pull
747
+ request — gets no declared credential at all. It still clones with the
748
+ source credential, so the build runs; only the declared credentials are
749
+ withheld. The reduced-privilege note on the run says so.
750
+
751
+ The context in a reference does **not** have to appear in the job's `contexts:`
752
+ list. The reference names its own context, and that context's rules are what
753
+ authorize it.
754
+
755
+ ## Generated jobs
756
+
757
+ A job produced by a `dynamicJob` generator has no entry in the lock file, so it
758
+ cannot declare credentials of its own. The **generator** declares them, and every
759
+ job it produces inherits that map:
760
+
761
+ ```typescript
762
+ dynamicJob('shards', {
763
+ gitCredentials: {
764
+ forge: { kind: 'token', tokenSecret: 'ci:FORGE_PAT' },
765
+ },
766
+ generate: async ({ ctx }) =>
767
+ ctx.event.payload.targets.map((target) =>
768
+ job(`publish-${target}`, {
769
+ runsOn: 'linux',
770
+ run: async ({ $, repo }) => {
771
+ await repo.withWrite(
772
+ { permissions: { contents: 'write' }, credential: 'forge' },
773
+ async () => {
774
+ await $`git push origin HEAD`;
775
+ },
776
+ );
777
+ },
778
+ }),
779
+ ),
780
+ });
781
+ ```
782
+
783
+ Three points follow from where the declaration lives:
784
+
785
+ - **All generated jobs share one map.** The generator is granted one ceiling, and
786
+ every job it produces gets exactly that ceiling. Use a second generator when
787
+ two sets of jobs need different credentials.
788
+ - **A `gitCredentials` map on a generated job is ignored.** The generator's
789
+ declaration is committed source that KiCI reads from the lock file. A generated
790
+ job's own declaration would come from the code that produced it, which is what
791
+ the authorization check above exists to be independent of.
792
+ - **The options form is required.** `dynamicJob('shards', async () => …)` — the
793
+ bare function form — has nowhere to put the declaration. Pass
794
+ `{ generate, gitCredentials }` instead; `needs` stays optional.
795
+
728
796
  ## How it works, and why long jobs still push
729
797
 
730
798
  An app token expires an hour after it is issued, and cannot be renewed. Rather
@@ -741,6 +809,10 @@ does at the start, and no credential is ever written into `.git/config`, into
741
809
  unaffected.
742
810
  - **The reserved `needs:` context is not resolvable yet** on a deployed
743
811
  orchestrator; naming it produces a clear error rather than a wrong credential.
812
+ - **A credential reference built in step code is refused.** The SDK takes a
813
+ credential _name_; there is no way to pass a reference. Code that constructs
814
+ one and sends it directly is rejected by the agent and, if it reaches the
815
+ orchestrator, by the declaration check above.
744
816
  - **A write window is bounded by the repository and the callback, not the step.**
745
817
  Steps running concurrently in the same job can push to the same repository
746
818
  while it is open. They cannot reach a different one.
@@ -1075,8 +1147,10 @@ KiCI has no native provider for Gogs, Forgejo, or Gitea, but these forges send H
1075
1147
  ```bash
1076
1148
  # Forgejo / Gitea send event name in X-Gitea-Event and signature in X-Gitea-Signature.
1077
1149
  # Gogs uses X-Gogs-Event and X-Gogs-Signature (same HMAC-SHA256 hex-digest format).
1150
+ # --org must be your Platform organization id: a generic source's routing key
1151
+ # embeds it, and the Platform refuses to register a key naming another org.
1078
1152
  kici-admin source add generic \
1079
- --org my-org \
1153
+ --org <platform-org-id> \
1080
1154
  --name forgejo-main \
1081
1155
  --verification hmac_sha256 \
1082
1156
  --secret @/path/to/webhook-secret.txt \
@@ -1084,7 +1158,7 @@ kici-admin source add generic \
1084
1158
  --rate-limit 120
1085
1159
  ```
1086
1160
 
1087
- Note the returned source ID, then register a webhook in the forge pointing at `https://<platform>/webhooks/<orgId>/generic/<sourceId>` (or the orchestrator's direct URL). Set content type to `application/json` and paste the same secret.
1161
+ Note the returned source ID, then register a webhook in the forge pointing at `https://<platform>/webhook/<orgId>/generic/<sourceId>` (or the orchestrator's direct URL, which takes the source **name** in place of the id). Set content type to `application/json` and paste the same secret.
1088
1162
 
1089
1163
  **Workflow:**
1090
1164
 
@@ -1151,14 +1225,16 @@ HTTPS with a forge PAT works the same way — store the token as a secret, `awai
1151
1225
 
1152
1226
  ## Plain GitHub repo webhooks (no GitHub App)
1153
1227
 
1154
- The Gogs/Forgejo/Gitea pattern above also applies when you want to trigger workflows from a GitHub repository **without installing the KiCI GitHub App** for example because you lack org-admin rights, you're on a restricted GitHub Enterprise tenant, or you simply don't want an App installation. Model the repo-level webhook as a generic source, accepting the same `genericWebhook()`-only ergonomics.
1228
+ The Gogs/Forgejo/Gitea pattern above also applies when you want to trigger workflows from a GitHub repository **without installing the KiCI GitHub App**. You may lack org-admin rights, sit on a restricted GitHub Enterprise tenant, or not want an App installation. Model the repo-level webhook as a generic source, accepting the same `genericWebhook()`-only ergonomics.
1155
1229
 
1156
1230
  **Operator setup:**
1157
1231
 
1158
1232
  ```bash
1159
1233
  # GitHub sends event name in X-GitHub-Event and HMAC-SHA256 signature in X-Hub-Signature-256.
1234
+ # --org must be your Platform organization id: a generic source's routing key
1235
+ # embeds it, and the Platform refuses to register a key naming another org.
1160
1236
  kici-admin source add generic \
1161
- --org my-org \
1237
+ --org <platform-org-id> \
1162
1238
  --name gh-repo-foo \
1163
1239
  --verification hmac_sha256 \
1164
1240
  --secret @/path/to/webhook-secret.txt \
@@ -1175,7 +1251,7 @@ curl -X PATCH https://<orchestrator>/api/v1/admin/generic-sources/<sourceId> \
1175
1251
 
1176
1252
  Then in the GitHub repo, go to **Settings → Webhooks → Add webhook**, set:
1177
1253
 
1178
- - **Payload URL:** `https://<platform>/webhooks/<orgId>/generic/<sourceId>` (or the orchestrator's direct URL)
1254
+ - **Payload URL:** `https://<platform>/webhook/<orgId>/generic/<sourceId>` (or the orchestrator's direct URL, which takes the source **name** in place of the id)
1179
1255
  - **Content type:** `application/json`
1180
1256
  - **Secret:** the same secret
1181
1257
  - **Events:** pick what you care about (e.g., `push`, `pull_request`)
@@ -627,10 +627,14 @@ kici-admin secret set <orgId> "__source__/<sourceId>" pat --value "<your-forgejo
627
627
  Finally, configure the forge to deliver webhooks to:
628
628
 
629
629
  ```
630
- https://<platform-host>/webhook/<orgId>/generic/<source-name>
630
+ https://<platform-host>/webhook/<orgId>/generic/<sourceId>
631
631
  ```
632
632
 
633
- with the same secret you passed to `--secret`.
633
+ with the same secret you passed to `--secret`. `<orgId>` is your Platform
634
+ organization id — the same value you passed to `--org`, which the source's
635
+ routing key embeds — and `<sourceId>` is the id `source add` printed. The
636
+ orchestrator's own ingest URL has the same shape but takes the source **name**
637
+ in place of the id.
634
638
 
635
639
  ## SSH deploy key
636
640
 
@@ -617,7 +617,7 @@ The SDK exposes three idempotency helpers — a generic function `idempotent()`,
617
617
  2. **Apply** the change only when drift is detected.
618
618
  3. **Surface** the resource (or its identifier) on both branches, so downstream steps don't need to know whether work happened or was skipped.
619
619
 
620
- `idempotent()` and `idempotentStep()` wrap the same underlying runner and always apply on drift. Pick `idempotentStep()` when the operation is the whole job of a step; use `idempotent()` from anywhere — inside a multi-action step, a hook, or a bare async function. Pick `checkStep()` when the step should respect the run-level check mode — `kici run --check` previews the drift without applying it.
620
+ `idempotent()` and `idempotentStep()` wrap the same underlying runner and always apply on drift. Pick `idempotentStep()` when the operation is the whole job of a step; use `idempotent()` from anywhere — inside a multi-action step, a hook, or a bare async function. Pick `checkStep()` when the step should respect the run-level check mode — `kici run remote --check` previews the drift without applying it.
621
621
 
622
622
  ## `idempotent(options)`
623
623
 
@@ -712,30 +712,30 @@ export const setup = job('setup', {
712
712
 
713
713
  ## `checkStep(name, options)`
714
714
 
715
- The check-mode-aware sibling of `idempotentStep()`. It takes a closely related option shape, but behaves differently when a run is started in check mode (`kici run --check`):
715
+ The check-mode-aware sibling of `idempotentStep()`. It takes a closely related option shape, but behaves differently when a run is started in check mode (`kici run remote --check`):
716
716
 
717
- | Factory | Behavior under `kici run --check` |
717
+ | Factory | Behavior under `kici run remote --check` |
718
718
  | ---------------- | ----------------------------------------- |
719
719
  | `idempotentStep` | always applies on drift |
720
720
  | `checkStep` | reports drift, applies only in apply mode |
721
721
 
722
- Use `checkStep()` for deploy-style steps where you want a dry-run preview of pending changes before committing them, and `idempotentStep()` for steps that must always converge (for example inside a hook). A `checkStep()` desugars to the first-class step check facet (`check` / `summarize` / `run(ctx, drift)` / `whenInSync`), so it participates in run-level check mode automatically: `kici run --check` reports the drift and skips `apply`, `kici run --check --fail-on-drift` exits non-zero when drift is detected, and apply mode applies the change.
722
+ Use `checkStep()` for deploy-style steps where you want a dry-run preview of pending changes before committing them, and `idempotentStep()` for steps that must always converge (for example inside a hook). A `checkStep()` desugars to the first-class step check facet (`check` / `summarize` / `run(ctx, drift)` / `whenInSync`), so it participates in run-level check mode automatically: `kici run remote --check` reports the drift and skips `apply`, `kici run remote --check --fail-on-drift` exits non-zero when drift is detected, and apply mode applies the change.
723
723
 
724
724
  ### Parameters
725
725
 
726
- | Name | Type | Required | Description |
727
- | ----------------- | ------------------------------------------- | -------- | --------------------------------------------------------------------------------------------------- |
728
- | `name` | `string` | Yes | Step name. Appears in the run timeline and in log lines. |
729
- | `check` | `(ctx) => Promise<TDrift \| null>` | Yes | Read-only inspection. Return `null` when the system is already in the desired state. |
730
- | `apply` | `(ctx, drift: TDrift) => Promise<TApplied>` | Yes | Brings the system to the desired state. Runs only in apply mode (skipped under `kici run --check`). |
731
- | `summarize` | `(drift: TDrift) => string` | Yes | Human-readable summary of what `apply()` would do; shown in check-mode drift output. |
732
- | `whenInSync` | `(ctx) => Promise<TInSync>` | No | Runs when `check()` returned `null` (already in sync). |
733
- | `outputs` | `OutputSchema` | No | Zod schema validating the step's outputs at runtime. |
734
- | `continueOnError` | `boolean` | No | When true, the job proceeds even if this step fails. |
735
- | `timeout` | `number` | No | Step-level timeout in milliseconds. |
736
- | `retry` | `number \| RetryConfig` | No | Retry policy for the step; `retry: N` is shorthand for `{ maxAttempts: N }`. |
737
- | `cache` | `CacheInput` | No | Declarative cache restored before the step and saved after it succeeds. |
738
- | `rules` | `Rule[]` | No | Step-level conditional rules, evaluated agent-side. |
726
+ | Name | Type | Required | Description |
727
+ | ----------------- | ------------------------------------------- | -------- | ---------------------------------------------------------------------------------------------------------- |
728
+ | `name` | `string` | Yes | Step name. Appears in the run timeline and in log lines. |
729
+ | `check` | `(ctx) => Promise<TDrift \| null>` | Yes | Read-only inspection. Return `null` when the system is already in the desired state. |
730
+ | `apply` | `(ctx, drift: TDrift) => Promise<TApplied>` | Yes | Brings the system to the desired state. Runs only in apply mode (skipped under `kici run remote --check`). |
731
+ | `summarize` | `(drift: TDrift) => string` | Yes | Human-readable summary of what `apply()` would do; shown in check-mode drift output. |
732
+ | `whenInSync` | `(ctx) => Promise<TInSync>` | No | Runs when `check()` returned `null` (already in sync). |
733
+ | `outputs` | `OutputSchema` | No | Zod schema validating the step's outputs at runtime. |
734
+ | `continueOnError` | `boolean` | No | When true, the job proceeds even if this step fails. |
735
+ | `timeout` | `number` | No | Step-level timeout in milliseconds. |
736
+ | `retry` | `number \| RetryConfig` | No | Retry policy for the step; `retry: N` is shorthand for `{ maxAttempts: N }`. |
737
+ | `cache` | `CacheInput` | No | Declarative cache restored before the step and saved after it succeeds. |
738
+ | `rules` | `Rule[]` | No | Step-level conditional rules, evaluated agent-side. |
739
739
 
740
740
  Everything from `outputs` down is a plain [`step()` option](https://docs.kici.dev/user/sdk/core/) forwarded to the underlying step. The three step options `checkStep` does **not** accept are `onCancel`, `cleanup`, and `approval`.
741
741
 
@@ -769,7 +769,7 @@ export const deploy = job('deploy', {
769
769
  });
770
770
  ```
771
771
 
772
- Run `kici run --check` against this workflow to see the drift summary without touching DNS; run it without `--check` to apply.
772
+ Run `kici run remote --check` against this workflow to see the drift summary without touching DNS; run it without `--check` to apply.
773
773
 
774
774
  ## Worked example: create-if-missing returning a resource id
775
775
 
@@ -1332,6 +1332,17 @@ interface StepContext<TInputs = Record<string, unknown>> {
1332
1332
  provider?: string;
1333
1333
  /** Whether this execution was triggered by `kici run remote` (developer-initiated remote run) */
1334
1334
  isTestRun: boolean;
1335
+ /** The job's own checked-out repository (present for every job that checks out); `withWrite` opens a write window for it — see [Git credentials](https://docs.kici.dev/user/patterns/git-credentials/) */
1336
+ repo?: {
1337
+ identifier: string;
1338
+ path: string;
1339
+ ref?: string;
1340
+ sha?: string;
1341
+ withWrite(
1342
+ opts: { permissions?: Record<string, string>; credential?: string },
1343
+ fn: () => Promise<void>,
1344
+ ): Promise<void>;
1345
+ };
1335
1346
  /** Registering repo of a global workflow (undefined for non-global workflows) */
1336
1347
  workflowRepo?: RepoInfo;
1337
1348
  /** Repo where the triggering event occurred (undefined for non-global workflows) */
@@ -1532,6 +1543,8 @@ const deploy = job('deploy', {
1532
1543
 
1533
1544
  Request a short-lived OIDC ID token for the current job, bound to an `audience`. The token is a signed JWT whose identity claims (`repository`, `ref`, `sha`, `kici_run_id`, `kici_job_id`) are derived by your orchestrator from the run context — a step cannot spoof them. Use it to authenticate the build to an external service that trusts the orchestrator's OIDC issuer (for example, when generating build provenance).
1534
1545
 
1546
+ The token also carries the event context a cloud trust policy needs to tell a fork pull request from a trusted push — `is_fork`, `head_repository`, `trust_tier`, `event_name`, and a pull-request-specific `sub`. See [ID-token claims and cloud trust policies](https://docs.kici.dev/user/provenance/#id-token-claims-and-cloud-trust-policies) for the full claim table and a worked AWS policy.
1547
+
1535
1548
  ```typescript
1536
1549
  const publish = job('publish', {
1537
1550
  steps: [
@@ -1571,6 +1584,8 @@ interface HostInventoryEntry {
1571
1584
 
1572
1585
  Two dimensions describe a host. **Labels** are flat strings used for grouping and targeting (the same labels `runsOn` / `runsOnAll` match). **Properties** are typed host-vars (`string | number | boolean`) — the place for facts like `region`, `cores`, or `gpu`. A host reports its own properties via the agent's `KICI_PROPERTIES` config, and an operator can pre-declare them with `kici-admin host declare --prop key=value`; the two are shallow-merged (agent-reported keys win).
1573
1586
 
1587
+ `labels` and `hostname` come back lowercase — KiCI folds both, so a pool declaring `Docker` reports `docker`. Compare against a lowercase value: `h.labels.includes('gpu')`, not `h.labels.includes('GPU')`. A label selector passed to `query()` folds too, so `{ include: [['GPU']] }` matches. `agentId` and `properties` keep their case.
1588
+
1574
1589
  ```typescript
1575
1590
  // All hosts:
1576
1591
  const all = await ctx.kici.inventory.query();
@@ -142,6 +142,7 @@ runsOn: { labels: ['kici:os:linux'], exclude: ['kici:host:box-01'] }
142
142
 
143
143
  - **Required labels:** The agent must have every label in the `labels` array (or the string/array form).
144
144
  - **Excluded labels:** The agent must NOT have any label in the `exclude` array. This includes auto-derived labels like `kici:arch:arm64`, `kici:os:linux`, etc.
145
+ - **Case:** Label matching is **case-insensitive** at every step. `runsOn: 'gpu'` matches an agent that reports `GPU`, and a pool declaring `["Docker"]` serves a `runsOn: ["docker"]` job (see [auto-scaler matching rules](https://docs.kici.dev/operator/orchestrator/auto-scaler/operations/#matching-rules)). KiCI stores and displays every label in lowercase, so the dashboard, `kici-admin agent list`, and `ctx.kici.inventory[…].labels` report the folded form. Compare against a lowercase value when you read a label back in workflow code: `h.labels.includes('gpu')`, not `h.labels.includes('GPU')`.
145
146
  - **Compile-time validation:** The compiler will error if any label appears in both `labels` and `exclude` (overlap detection).
146
147
  - **Operator-declared mandatory labels:** Operators may mark a scaler with `mandatoryLabels` (Kubernetes-taint-style opt-in). When a scaler declares a mandatory label, a job is only allowed to land on it if `runsOn.labels` includes that label. A workflow targeting such a scaler must explicitly list the mandatory label in `runsOn`. See the [auto-scaler mandatory labels](https://docs.kici.dev/operator/orchestrator/auto-scaler/common-config/#mandatory--exclude-labels) for details.
147
148
 
@@ -194,6 +195,12 @@ Every selector element — in `runsOn`, in `runsOnAll`, on both the include and
194
195
  - **String with glob metacharacters (`*`, `?`, `[]`, `{}`) → glob.** `'kici:host:web-*'` matches every host label starting with `kici:host:web-`. `'kici:host:box-0[1-3]'` matches `box-01`, `box-02`, `box-03`.
195
196
  - **`RegExp` literal → regular expression.** `/kici:host:box-0[1-3]/` matches any label the expression matches.
196
197
 
198
+ All three forms match case-insensitively. `'GPU'`, `'kici:host:Web-*'` and `/kici:host:BOX-0[1-3]/` each match a label of any case, and a `RegExp` you write with the `i` flag behaves the same. The `g` and `y` flags are dropped — a selector asks one question per label, so a sticky match would resume part-way through the next one.
199
+
200
+ `kici:host:` carries the machine's hostname folded to lowercase. A host that calls itself `Build-Box-01` advertises `kici:host:build-box-01`, and both `runsOn: 'kici:host:build-box-01'` and `runsOn: 'kici:host:Build-Box-01'` match it.
201
+
202
+ Case folding covers labels and hostnames only. An **agent ID** stays an opaque identifier and compares exactly, which is what keeps a per-host secret binding on `prod-01` away from an agent named `PROD-01` — see [per-host secret scoping](https://docs.kici.dev/operator/security/secrets/#per-host-secret-scoping).
203
+
197
204
  Both the required (include) side and the excluded side accept all three forms:
198
205
 
199
206
  ```typescript
@@ -852,11 +859,19 @@ Tag a dynamic job generator with a group name so other jobs can reference it via
852
859
  ```typescript
853
860
  function dynamicJob(
854
861
  groupName: string,
855
- fnOrConfig: DynamicJobFn | { needs: DynamicJobNeed[]; generate: DynamicJobFn },
862
+ fnOrConfig:
863
+ | DynamicJobFn
864
+ | {
865
+ needs?: DynamicJobNeed[];
866
+ generate: DynamicJobFn;
867
+ gitCredentials?: GitCredentialMap;
868
+ },
856
869
  ): TaggedDynamicJobFn;
857
870
  ```
858
871
 
859
- The second argument is either a plain generator (event-only, evaluated at webhook time) or a result-aware `{ needs, generate }` config, which defers the generator until its declared upstreams complete and exposes their frozen outputs as `ctx.needs`. See [Rules, matrix, dynamic jobs](https://docs.kici.dev/user/sdk/rules-matrix-dynamic/#dynamicjob--result-aware-generation) for the result-aware form.
872
+ The second argument is either a plain generator (event-only, evaluated at webhook time) or an options config. An options config that declares `needs` is result-aware: it defers the generator until those upstreams complete and exposes their frozen outputs as `ctx.needs`. See [Rules, matrix, dynamic jobs](https://docs.kici.dev/user/sdk/rules-matrix-dynamic/#dynamicjob--result-aware-generation) for the result-aware form.
873
+
874
+ `needs` is optional. An options config without it is evaluated at webhook time, like the plain generator form. Use that form to declare `gitCredentials` on an event-only generator: every job the generator produces inherits the map, which is the only way a generated job gets named credentials. See [Git credentials](https://docs.kici.dev/user/patterns/git-credentials/#generated-jobs).
860
875
 
861
876
  The generator runs twice: once in the init phase (to register expected job names) and once inside the executing agent (to produce the actual jobs). Mismatches between the two evaluations are detected as determinism drift -- see [dynamic-jobs](https://docs.kici.dev/architecture/execution/dynamic-jobs/).
862
877
 
@@ -1035,6 +1050,11 @@ The throw is a `ChangedFilesUnavailableError` (exported from `@kici-dev/sdk`, ca
1035
1050
 
1036
1051
  ### evaluateRules(rules, context, label, onRuleResult?)
1037
1052
 
1053
+ The agent calls this on your behalf. A workflow does not call it. It lives on
1054
+ `@kici-dev/sdk/internal`, outside semver, and stays exported from the root barrel as
1055
+ `@deprecated` until v1.0.0 — see [deprecations](https://docs.kici.dev/user/deprecations/). It is described here
1056
+ because its return shape is what a rule's outcome looks like in the run log.
1057
+
1038
1058
  Evaluate an array of rules sequentially with fail-fast behavior. Stops on the first failure.
1039
1059
 
1040
1060
  ```typescript
@@ -1102,7 +1122,7 @@ Every variant carries the shared `EventBase` fields — `type`, `action`, `targe
1102
1122
 
1103
1123
  Matrix configurations expand a single job into multiple instances, one per parameter combination. Maximum 256 combinations.
1104
1124
 
1105
- Combinations must be **unique**. Two combinations that would produce the same instance name — most simply, the same value listed twice — fail the job instead of quietly running it twice.
1125
+ Combinations must be **unique**. Two combinations that would produce the same instance name — in the simplest case, the same value listed twice — fail the job instead of quietly running it twice.
1106
1126
 
1107
1127
  Expansion happens at **dispatch time**: the orchestrator materializes the matrix into N execution jobs — one per combination, each dispatched to its own agent — before any job runs. Each instance receives its combination as `ctx.matrix`. This is identical whether the workflow runs via `kici run <event> --local` or remotely through a webhook trigger, and the dashboard groups the N instances under one parent node.
1108
1128
 
@@ -1285,8 +1305,13 @@ isDynamicFunction(matrix); // true if async function
1285
1305
 
1286
1306
  ### Matrix expansion utilities
1287
1307
 
1308
+ The agent expands a matrix for you. A workflow does not call these. They live on
1309
+ `@kici-dev/sdk/internal`, outside semver, and stay exported from the root barrel as
1310
+ `@deprecated` until v1.0.0 — see [deprecations](https://docs.kici.dev/user/deprecations/). They are described
1311
+ here because they define the combinations a matrix job actually produces.
1312
+
1288
1313
  ```typescript
1289
- import { expandMatrix, applyIncludeExclude } from '@kici-dev/sdk';
1314
+ import { expandMatrix, applyIncludeExclude } from '@kici-dev/sdk/internal';
1290
1315
  ```
1291
1316
 
1292
1317
  `expandMatrix(matrix)` takes a string array or an object of string arrays and returns all combinations as `MatrixValues[]`. For a single-dimension array, each value becomes `{ value: '...' }`. For multi-dimensional objects, it produces the Cartesian product. Anything else throws a `MatrixShapeError` naming the expected shape; numbers and booleans inside the values are accepted and converted to strings.
@@ -1344,7 +1369,8 @@ export default workflow('ci', {
1344
1369
  `dynamicJob(group, fnOrConfig)` tags a generator with a group name (so static jobs can depend on it via `needs: [dynamicGroup('group')]`). It is polymorphic:
1345
1370
 
1346
1371
  - **Function form** — event-only, dispatched at webhook time: `dynamicJob('shards', async ({ ctx }) => [...])`.
1347
- - **Options-object form** — result-aware, deferred until its declared `needs` complete, then run with the upstreams' frozen outputs as `ctx.needs`: `dynamicJob('reports', { needs, generate })`.
1372
+ - **Options-object form** — `dynamicJob('reports', { needs, generate })`. With `needs`, it is result-aware: deferred until those upstreams complete, then run with their frozen outputs as `ctx.needs`.
1373
+ - `needs` is optional. Without it the generator is dispatched at webhook time, like the function form. That form is how a generator declares `gitCredentials`, which every job it produces inherits — see [Git credentials](https://docs.kici.dev/user/patterns/git-credentials/#generated-jobs).
1348
1374
 
1349
1375
  ```typescript
1350
1376
  import { workflow, job, step, dynamicJob, dynamicGroup, z } from '@kici-dev/sdk';
@@ -1517,7 +1543,7 @@ those files contain**. It is a declarative filter on the `pr()`, `push()`, and
1517
1543
  at the event's commit. The orchestrator evaluates it as pure data before
1518
1544
  dispatching — it reads only the referenced files, never clones the whole
1519
1545
  repository, and never runs any of your workflow code. A workflow whose `requires`
1520
- does not pass is simply not dispatched.
1546
+ does not pass is not dispatched.
1521
1547
 
1522
1548
  Each entry is a `ContentRequirement`:
1523
1549
 
@@ -1782,7 +1808,7 @@ dispatch({ types: ['deploy', 'rollback'] }); // Specific event types
1782
1808
  #### Typed dispatch inputs
1783
1809
 
1784
1810
  A `dispatch()` trigger can declare a typed `inputs` schema. Operators supply
1785
- values with `kici run --input key=value`; KiCI validates, coerces, defaults, and
1811
+ values with `kici run remote --input key=value`; KiCI validates, coerces, defaults, and
1786
1812
  exposes them to steps and rules as `ctx.dispatchInputs`. The values are validated
1787
1813
  on the orchestrator from the compiled lock file — a missing required input or a
1788
1814
  bad value is rejected before any agent runs, without cloning the repository.
@@ -2497,6 +2523,20 @@ import { workflow, job, step, pr, push, rule, defineEvent } from '@kici-dev/sdk'
2497
2523
 
2498
2524
  For the complete list of every named export (factory functions, triggers, rules, validation, hook factories, types), see the per-topic pages above.
2499
2525
 
2526
+ ## `@kici-dev/sdk/internal` is not a supported surface
2527
+
2528
+ The package also publishes an `@kici-dev/sdk/internal` subpath. It carries the runtime
2529
+ contract between the SDK and the KiCI agent. Those are the functions that install the maps
2530
+ a `.result` proxy reads, build the step context your workflow body receives, evaluate its
2531
+ rules, and expand its matrix. The agent drives all of it on your behalf.
2532
+
2533
+ It is **not covered by semver** and may change shape in any release. Do not import it from
2534
+ a workflow. Everything a workflow author needs is on the root entry point above.
2535
+
2536
+ Those same symbols are also still exported from the root barrel, marked `@deprecated`, so
2537
+ an older SDK in a repository keeps working. They are removed from the root at v1.0.0 — see
2538
+ [deprecations](https://docs.kici.dev/user/deprecations/).
2539
+
2500
2540
  ## See also
2501
2541
 
2502
2542
  - [Getting started](https://docs.kici.dev/user/getting-started/) -- install the SDK, write your first workflow, test locally
@@ -11,15 +11,15 @@ Found a mismatch between what these docs advertise and what KiCI does? Read http
11
11
  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:
12
12
 
13
13
  - [getting-started](https://docs.kici.dev/llms-getting-started.txt) (65 KB) — Adopt KiCI: why it exists, how workflows execute, migrating from GitHub Actions, installing the SDK, and writing/compiling/testing your first workflow
14
- - [patterns](https://docs.kici.dev/llms-patterns.txt) (57 KB) — Copy-paste workflow recipes: triggers, conditionals, matrix, scheduling, integrations
15
- - [sdk](https://docs.kici.dev/llms-sdk.txt) (127 KB) — Core authoring API: workflow/job/step factories, triggers, rules, matrix, dynamic jobs, cross-job outputs
16
- - [sdk-runtime](https://docs.kici.dev/llms-sdk-runtime.txt) (114 KB) — Runtime and advanced authoring: step runtime context, event payloads, host fan-out, idempotent steps, caching, artifacts, waiting
17
- - [cli](https://docs.kici.dev/llms-cli.txt) (90 KB) — Running the CLI locally: compile, test, run local, hooks, lock-file drift, common failures
18
- - [cli-remote](https://docs.kici.dev/llms-cli-remote.txt) (106 KB) — Auth, org and orchestrator selection, runs, approvals, notifications, diagnostics, and the MCP server a coding agent connects to
19
- - [features](https://docs.kici.dev/llms-features.txt) (90 KB) — Deployment contexts, scoped secrets, private registries, approvals, provenance, dashboard and account access
20
- - [features-execution](https://docs.kici.dev/llms-features-execution.txt) (121 KB) — Concurrency, dynamic values, events, container jobs, environment variables, global workflows, idempotent steps
14
+ - [patterns](https://docs.kici.dev/llms-patterns.txt) (61 KB) — Copy-paste workflow recipes: triggers, conditionals, matrix, scheduling, integrations
15
+ - [sdk](https://docs.kici.dev/llms-sdk.txt) (131 KB) — Core authoring API: workflow/job/step factories, triggers, rules, matrix, dynamic jobs, cross-job outputs
16
+ - [sdk-runtime](https://docs.kici.dev/llms-sdk-runtime.txt) (115 KB) — Runtime and advanced authoring: step runtime context, event payloads, host fan-out, idempotent steps, caching, artifacts, waiting
17
+ - [cli](https://docs.kici.dev/llms-cli.txt) (97 KB) — Running the CLI locally: compile, test, run local, hooks, lock-file drift, common failures
18
+ - [cli-remote](https://docs.kici.dev/llms-cli-remote.txt) (111 KB) — Auth, org and orchestrator selection, runs, approvals, notifications, diagnostics, and the MCP server a coding agent connects to
19
+ - [features](https://docs.kici.dev/llms-features.txt) (97 KB) — Deployment contexts, scoped secrets, private registries, approvals, provenance, dashboard and account access
20
+ - [features-execution](https://docs.kici.dev/llms-features-execution.txt) (124 KB) — Concurrency, dynamic values, events, container jobs, environment variables, global workflows, idempotent steps
21
21
  - [providers](https://docs.kici.dev/llms-providers.txt) (35 KB) — Connecting sources: GitHub App, universal-git (Forgejo/Gitea/GitLab), local file://
22
- - [architecture](https://docs.kici.dev/llms-architecture.txt) (99 KB) — How the runtime works: three-tier relay model, data flows, configuration
22
+ - [architecture](https://docs.kici.dev/llms-architecture.txt) (100 KB) — How the runtime works: three-tier relay model, data flows, configuration
23
23
 
24
24
  ## Getting started
25
25
 
@@ -1,11 +1,3 @@
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
1
  /**
10
2
  * Resolve the built `@kici-dev/orchestrator/standalone` entry the local plane
11
3
  * launches in independent (offline) mode.
@@ -1,22 +1,11 @@
1
1
  import "../rolldown-runtime-ClRpJifh.js";
2
2
  import { planePaths, planePorts } from "./paths.js";
3
+ import { rotatePlaneLogIfOversized } from "./plane-log.js";
3
4
  import { createRequire } from "node:module";
4
5
  import fs from "node:fs";
5
6
  import { spawn } from "node:child_process";
6
- import os from "node:os";
7
7
  //#region src/local-plane/orchestrator-process.ts
8
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
9
  * Resolve the built `@kici-dev/orchestrator/standalone` entry the local plane
21
10
  * launches in independent (offline) mode.
22
11
  */
@@ -60,6 +49,7 @@ function spawnOrchestratorProcess(databaseUrl, opts) {
60
49
  const { logFile, root, cacheDir } = planePaths();
61
50
  fs.mkdirSync(root, { recursive: true });
62
51
  fs.mkdirSync(cacheDir, { recursive: true });
52
+ rotatePlaneLogIfOversized(logFile);
63
53
  const out = fs.openSync(logFile, "a");
64
54
  const baseEnv = {};
65
55
  for (const [key, value] of Object.entries(process.env)) if (!key.startsWith("KICI_")) baseEnv[key] = value;
@@ -68,7 +58,9 @@ function spawnOrchestratorProcess(databaseUrl, opts) {
68
58
  KICI_PORT: String(port),
69
59
  KICI_DATABASE_URL: databaseUrl,
70
60
  KICI_AGENT_AUTH: "none",
61
+ KICI_HOST: "127.0.0.1",
71
62
  KICI_AUTO_MIGRATE: "true",
63
+ KICI_CLUSTER_SINGLE_NODE: "true",
72
64
  KICI_DATA_DIR: root,
73
65
  KICI_BOOTSTRAP_ADMIN_TOKEN: opts.adminToken,
74
66
  KICI_SECRET_KEY: opts.secretKey,
@@ -76,7 +68,7 @@ function spawnOrchestratorProcess(databaseUrl, opts) {
76
68
  KICI_WEBHOOK_PUBLIC_URL: `http://127.0.0.1:${port}`,
77
69
  KICI_STORAGE_TYPE: "filesystem",
78
70
  KICI_STORAGE_FS_PATH: cacheDir,
79
- KICI_STORAGE_FS_BASE_URL: `http://${resolveAgentReachableHost()}:${port}`
71
+ KICI_STORAGE_FS_BASE_URL: `http://127.0.0.1:${port}`
80
72
  };
81
73
  let entry;
82
74
  let modeEnv;
@@ -124,6 +116,6 @@ async function awaitOrchestratorReady(port, attempts = 120, intervalMs = 500) {
124
116
  throw new Error("local orchestrator did not become ready");
125
117
  }
126
118
  //#endregion
127
- export { awaitOrchestratorReady, orchestratorReady, resolveAgentReachableHost, resolveServerEntry, resolveStandaloneEntry, spawnOrchestratorProcess };
119
+ export { awaitOrchestratorReady, orchestratorReady, resolveServerEntry, resolveStandaloneEntry, spawnOrchestratorProcess };
128
120
 
129
121
  //# sourceMappingURL=orchestrator-process.js.map
@@ -33,6 +33,7 @@ export declare function planePaths(): {
33
33
  pidfile: string;
34
34
  stampFile: string;
35
35
  logFile: string;
36
+ pgLogFile: string;
36
37
  socketDir: string;
37
38
  adminTokenFile: string;
38
39
  platformTokenFile: string;
@@ -48,6 +48,7 @@ function planePaths() {
48
48
  pidfile: path.join(root, "plane.pid"),
49
49
  stampFile: path.join(root, "stamp.json"),
50
50
  logFile: path.join(root, "orchestrator.log"),
51
+ pgLogFile: path.join(root, "orchestrator.log.pg"),
51
52
  socketDir: path.join(root, "sock"),
52
53
  adminTokenFile: path.join(root, "admin-token"),
53
54
  platformTokenFile: path.join(root, "platform-token"),
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Size at which a local dev plane log is rotated on the next plane start.
3
+ *
4
+ * The plane's orchestrator writes one JSON line per request and per
5
+ * scheduled-job tick, and nothing truncates the file between boots, so an
6
+ * unrotated log grows without bound. 50 MB is roughly 200k lines — more history
7
+ * than a local debugging session reads.
8
+ */
9
+ export declare const PLANE_LOG_MAX_BYTES: number;
10
+ /** The cap expressed in whole megabytes, for the messages that name it. */
11
+ export declare const PLANE_LOG_MAX_MB: number;
12
+ /**
13
+ * Rotate `file` to `<file>.1` once it reaches `PLANE_LOG_MAX_BYTES`, keeping two
14
+ * generations: any previous `.1` is discarded.
15
+ *
16
+ * Call this only where nothing holds the file open. A rename under a live
17
+ * writer leaves that writer appending to the renamed inode, so the live log
18
+ * would stay empty for the rest of the process's life.
19
+ *
20
+ * Every failure is swallowed on purpose. Both callers are on a plane-boot path:
21
+ * `startPlanePostgres` reads a throw as "embedded Postgres is unavailable" and
22
+ * silently falls back to a Podman container, and `spawnOrchestratorProcess`
23
+ * would fail the boot outright. A log that cannot be rotated must not cost the
24
+ * user their plane.
25
+ */
26
+ export declare function rotatePlaneLogIfOversized(file: string): void;
27
+ //# sourceMappingURL=plane-log.d.ts.map
@@ -0,0 +1,39 @@
1
+ import "../rolldown-runtime-ClRpJifh.js";
2
+ import fs from "node:fs";
3
+ //#region src/local-plane/plane-log.ts
4
+ /**
5
+ * Size at which a local dev plane log is rotated on the next plane start.
6
+ *
7
+ * The plane's orchestrator writes one JSON line per request and per
8
+ * scheduled-job tick, and nothing truncates the file between boots, so an
9
+ * unrotated log grows without bound. 50 MB is roughly 200k lines — more history
10
+ * than a local debugging session reads.
11
+ */
12
+ const PLANE_LOG_MAX_BYTES = 52428800;
13
+ /** The cap expressed in whole megabytes, for the messages that name it. */
14
+ const PLANE_LOG_MAX_MB = PLANE_LOG_MAX_BYTES / 1048576;
15
+ /**
16
+ * Rotate `file` to `<file>.1` once it reaches `PLANE_LOG_MAX_BYTES`, keeping two
17
+ * generations: any previous `.1` is discarded.
18
+ *
19
+ * Call this only where nothing holds the file open. A rename under a live
20
+ * writer leaves that writer appending to the renamed inode, so the live log
21
+ * would stay empty for the rest of the process's life.
22
+ *
23
+ * Every failure is swallowed on purpose. Both callers are on a plane-boot path:
24
+ * `startPlanePostgres` reads a throw as "embedded Postgres is unavailable" and
25
+ * silently falls back to a Podman container, and `spawnOrchestratorProcess`
26
+ * would fail the boot outright. A log that cannot be rotated must not cost the
27
+ * user their plane.
28
+ */
29
+ function rotatePlaneLogIfOversized(file) {
30
+ try {
31
+ if (fs.statSync(file).size < 52428800) return;
32
+ fs.rmSync(`${file}.1`, { force: true });
33
+ fs.renameSync(file, `${file}.1`);
34
+ } catch {}
35
+ }
36
+ //#endregion
37
+ export { PLANE_LOG_MAX_BYTES, PLANE_LOG_MAX_MB, rotatePlaneLogIfOversized };
38
+
39
+ //# sourceMappingURL=plane-log.js.map
@@ -19,8 +19,8 @@ import { generateKeyPairSync, randomBytes } from "node:crypto";
19
19
  */
20
20
  function currentBuildIdentity() {
21
21
  return {
22
- version: "0.6.1",
23
- buildCommit: "d32193b6b"
22
+ version: "0.8.0",
23
+ buildCommit: "57712173f"
24
24
  };
25
25
  }
26
26
  /**