@kici-dev/compiler 0.4.0 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. package/dist/cli.js +1 -1
  2. package/dist/commands/compile.js +1 -13
  3. package/dist/commands/preview.js +1 -8
  4. package/dist/commands/types.js +1 -2
  5. package/dist/errors/formatter.d.ts +2 -4
  6. package/dist/errors/formatter.js +1 -3
  7. package/dist/errors/index.d.ts +1 -1
  8. package/dist/errors/index.js +2 -2
  9. package/dist/generators/secrets-dts.d.ts +0 -1
  10. package/dist/generators/secrets-dts.js +1 -2
  11. package/dist/llm-context/llms-architecture.txt +27 -13
  12. package/dist/llm-context/llms-cli.txt +26 -6
  13. package/dist/llm-context/llms-features.txt +272 -91
  14. package/dist/llm-context/llms-full.txt +649 -235
  15. package/dist/llm-context/llms-getting-started.txt +20 -20
  16. package/dist/llm-context/llms-patterns.txt +10 -6
  17. package/dist/llm-context/llms-providers.txt +4 -6
  18. package/dist/llm-context/llms-sdk-runtime.txt +37 -36
  19. package/dist/llm-context/llms-sdk.txt +253 -57
  20. package/dist/llm-context/llms.txt +6 -6
  21. package/dist/local-plane/plane-manager.js +2 -2
  22. package/dist/lockfile/generator.js +137 -42
  23. package/dist/lockfile/index.d.ts +0 -2
  24. package/dist/lockfile/index.js +1 -2
  25. package/dist/templates/package-json.js +1 -1
  26. package/dist/test-runner/dry-run.d.ts +1 -2
  27. package/dist/test-runner/dry-run.js +1 -18
  28. package/dist/types.d.ts +32 -8
  29. package/dist/types.js +7 -1
  30. package/dist/validation/validator.js +40 -0
  31. package/package.json +6 -6
  32. package/sbom.spdx.json +126 -121
  33. package/dist/lockfile/purity-analyzer.d.ts +0 -25
  34. package/dist/lockfile/purity-analyzer.js +0 -204
  35. package/dist/lockfile/purity-diagnostics.d.ts +0 -31
  36. package/dist/lockfile/purity-diagnostics.js +0 -52
@@ -34,19 +34,19 @@ Your workflow is plain TypeScript, but different parts of it run at three distin
34
34
 
35
35
  ## The three phases
36
36
 
37
- | Phase | Where it runs | What runs | When |
38
- | ---------------- | ---------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------- |
39
- | **Compile** | Your dev machine or CI (`kici compile`) | Load your workflow modules, validate the DAG, assign step IDs, analyze dynamic-value purity, emit `kici.lock.json` | Before anything is pushed |
40
- | **Orchestrator** | Your orchestrator (no repo clone) | Match triggers against the lock, evaluate **pure** inline dynamic values in a sandboxed JavaScript VM, dispatch jobs | On each incoming event |
41
- | **Agent** | An ephemeral agent (fresh clone per job) | Load the workflow module, evaluate job and step rules, run step bodies and hooks, run impure dynamic-value init jobs and `dynamicJob` generators (both forms) | After dispatch |
37
+ | Phase | Where it runs | What runs | When |
38
+ | ---------------- | ---------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------- |
39
+ | **Compile** | Your dev machine or CI (`kici compile`) | Load your workflow modules, validate the DAG, assign step IDs, emit `kici.lock.json` | Before anything is pushed |
40
+ | **Orchestrator** | Your orchestrator (no repo clone) | Match triggers against the lock and dispatch jobs; it never evaluates workflow code | On each incoming event |
41
+ | **Agent** | An ephemeral agent (fresh clone per job) | Load the workflow module, evaluate job and step rules, run step bodies and hooks, run dynamic-value init steps and `dynamicJob` generators (both forms) | After dispatch |
42
42
 
43
43
  The lock file is the seam. Everything left of it is decided once at compile time and frozen into JSON; everything right of it reads that JSON. See [the lock file and workflow drift](https://docs.kici.dev/user/lock-file-and-drift/) and [the three-tier architecture](https://docs.kici.dev/architecture/overview/) for the wider picture.
44
44
 
45
45
  ## Compile time
46
46
 
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`, …), runs purity analysis over every dynamic-value function, and writes `kici.lock.json`.
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 (plus the serialized source of pure dynamic-value functions) 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 simply 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
 
@@ -57,7 +57,7 @@ The lock is portable JSON. It carries:
57
57
  - Workflow and trigger metadata.
58
58
  - The job and step DAG, with compile-time step IDs.
59
59
  - Static values, verbatim.
60
- - The **source text** of pure dynamic-value functions, as inline expressions.
60
+ - Markers noting which fields are dynamic, so the orchestrator knows to resolve them on the agent's init step.
61
61
 
62
62
  It does **not** carry:
63
63
 
@@ -70,11 +70,13 @@ The consequence is blunt: if a value isn't in the lock, the orchestrator can't s
70
70
 
71
71
  ## Orchestrator time
72
72
 
73
- On each event the orchestrator matches triggers using only the lock — it never clones your repository. Pure dynamic `context`, `env`, and `concurrencyGroup` functions are evaluated here, as inline expressions in a sandboxed JavaScript VM (~0ms overhead), instead of dispatching a separate job to resolve them.
73
+ On each event the orchestrator matches triggers using only the lock — it never clones your repository and never evaluates workflow code. Dynamic `context`, `env`, and `concurrencyGroup` functions are not run here: the orchestrator dispatches a short init step to an agent to resolve them (see below).
74
74
 
75
- A runtime error in an inline expression fails the job immediately there is no automatic fallback to the clone-and-evaluate path. The orchestrator does **not** run `dynamicJob` generator bodies itself: for the event-only (function) form it dispatches a dedicated dynamic-evaluation job to an agent at event time; the generator function then runs agent-side (see below).
75
+ Trigger matching can query the **contents** of individual source files, not just their paths: a `pr()`, `push()`, or `tag()` trigger with a [`requires`](https://docs.kici.dev/user/sdk/triggers/#content-requirements-requires) filter is matched by reading the named files at the event's commit and evaluating the filter as declarative data still with no repository clone and no workflow code executed. A `requires` regex is checked for catastrophic (ReDoS) shapes at `kici compile` time and rejected there, so only safe patterns reach the orchestrator.
76
76
 
77
- See [dynamic values](https://docs.kici.dev/user/dynamic-values/) for the exact rules that make a function pure or impure.
77
+ The orchestrator also does **not** run `dynamicJob` generator bodies itself: for the event-only (function) form it dispatches a dedicated dynamic-evaluation job to an agent at event time; the generator function then runs agent-side (see below).
78
+
79
+ See [dynamic values](https://docs.kici.dev/user/dynamic-values/) for how dynamic `context`, `env`, and `concurrencyGroup` functions resolve.
78
80
 
79
81
  ## Agent time
80
82
 
@@ -82,7 +84,7 @@ After dispatch, each job runs in its own ephemeral agent sandbox: a shallow clon
82
84
 
83
85
  1. **Job-level rules** are evaluated. By this point the agent has already spawned and the source has already been restored, so a job that its rules skip has **still** paid for that spawn and clone; only its steps are avoided.
84
86
  2. **Step-level rules**, then each step's `run()` body and its hooks.
85
- 3. **Impure** dynamic values are resolved here too, via an init job that clones and evaluates the function (~5–10s) before the real job runs.
87
+ 3. **Dynamic values** (`context`, `env`, `concurrencyGroup` functions) are resolved here, via a short `__init__` job that runs the function before the real job runs; this shows in the run timeline as an `Init:` entry.
86
88
  4. **`dynamicJob` generators run here — both forms.** The event-only (function) form runs in a dedicated evaluation job dispatched at event time; the result-aware (options) form is deferred until its declared `needs` complete, then run with the upstream outputs frozen as `ctx.needs`.
87
89
 
88
90
  See [job execution](https://docs.kici.dev/architecture/execution/job-execution/) and [hooks and rules](https://docs.kici.dev/user/hooks/) for the details.
@@ -92,8 +94,7 @@ See [job execution](https://docs.kici.dev/architecture/execution/job-execution/)
92
94
  | Construct | Runs on | When |
93
95
  | ---------------------------- | ---------------- | ------------------------------- |
94
96
  | Static value | Compile → lock | Never re-evaluated |
95
- | Pure dynamic value | Orchestrator VM | Per event |
96
- | Impure dynamic value | Agent init job | Per event |
97
+ | Dynamic value | Agent init step | Per event |
97
98
  | Job-level rules | Agent | After clone |
98
99
  | Step-level rules | Agent | Per step |
99
100
  | `dynamicJob` (function form) | Agent (eval job) | Dispatched at event time |
@@ -132,12 +133,11 @@ Outputs are typed across the job boundary too: reading `jobRef.result.…` or `c
132
133
 
133
134
  ## Common footguns
134
135
 
135
- | Symptom | Why | Fix |
136
- | ------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------- |
137
- | A top-level `let seen = 0` (or a cache filled in job A) is empty in job B | Each job loads the workflow module fresh in its own agent process after its own clone — there is no shared memory between jobs | Pass data through step/job **outputs** (`OutputProxy` / `needs`), not module variables |
138
- | `context: (event) => event.ref + SUFFIX`, where `SUFFIX` is a module constant, silently falls back to the slower init-job path | Purity analysis only allows the function's own params, locals, and a fixed safe-globals set — a free identifier makes it impure | Inline the constant, or accept the init-job path knowingly. See [pure functions](https://docs.kici.dev/user/dynamic-values/#pure-functions-inline-evaluation) |
139
- | Fan-out job identities shift between re-evaluations | `ctx.event` / `ctx.needs` are frozen and replayed, but `Date.now()` / `Math.random()` are not | Derive job identity only from the frozen event/needs snapshot |
140
- | A rule-skipped job still spawned an agent and cloned | Job-level rules evaluate agent-side, after dispatch and clone — not on the orchestrator | This is by design: rules can read true runtime context (`$`, `changedFiles`, `env`). See [step-level rules](https://docs.kici.dev/user/hooks/#step-level-rules) |
136
+ | Symptom | Why | Fix |
137
+ | ------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------- |
138
+ | A top-level `let seen = 0` (or a cache filled in job A) is empty in job B | Each job loads the workflow module fresh in its own agent process after its own clone — there is no shared memory between jobs | Pass data through step/job **outputs** (`OutputProxy` / `needs`), not module variables |
139
+ | Fan-out job identities shift between re-evaluations | `ctx.event` / `ctx.needs` are frozen and replayed, but `Date.now()` / `Math.random()` are not | Derive job identity only from the frozen event/needs snapshot |
140
+ | A rule-skipped job still spawned an agent and cloned | Job-level rules evaluate agent-side, after dispatch and clone not on the orchestrator | This is by design: rules can read true runtime context (`$`, `changedFiles`, `env`). See [step-level rules](https://docs.kici.dev/user/hooks/#step-level-rules) |
141
141
 
142
142
  ## See also
143
143
 
@@ -304,12 +304,16 @@ export default workflow('ci', {
304
304
 
305
305
  Rule check functions receive a `RuleContext` with:
306
306
 
307
- | Property | Type | Description |
308
- | -------------- | ----------------------------------- | ----------------------------------- |
309
- | `event` | `EventPayload` | The triggering event data |
310
- | `changedFiles` | `string[]` | Files changed in this event |
311
- | `env` | `Record<string, string\|undefined>` | Environment variables |
312
- | `$` | zx shell | Shell executor for running commands |
307
+ | Property | Type | Description |
308
+ | -------------- | ----------------------------------- | ---------------------------------------------------------------------------------------------- |
309
+ | `event` | `EventPayload` | The triggering event data |
310
+ | `changedFiles` | `string[]` | Files changed in this event |
311
+ | `sourceRepo` | `RepoInfo \| undefined` | The repo whose event triggered the run, when the evaluation has a checkout |
312
+ | `workflowRepo` | `RepoInfo \| undefined` | The repo that registered the workflow. The same repo as `sourceRepo` outside a global workflow |
313
+ | `env` | `Record<string, string\|undefined>` | Environment variables |
314
+ | `$` | zx shell | Shell executor for running commands |
315
+
316
+ `RepoInfo` carries `path` — an absolute path to that repo's checkout — plus optional `ref` and `sha`. In a [global workflow](https://docs.kici.dev/user/global-workflows/) the two are different repos, which is what lets one rule read the source repo's tree while the workflow lives elsewhere. Read _through_ `path`: its contents are stable, but the path itself differs between the evaluation and the later run.
313
317
 
314
318
  ### Marker rules
315
319
 
@@ -312,9 +312,8 @@ when you want a list entry pinned to this specific App rather than
312
312
  applying to any source in the org:
313
313
 
314
314
  ```bash
315
- # Enable global workflows for the org
316
- kici-admin org-settings global-workflows set-enabled true \
317
- --customer-id <orgId>
315
+ # Enable global workflows cluster-wide (the master switch is fleet-wide, held by the operator)
316
+ kici-admin cluster-settings set --global-workflows-enabled true
318
317
 
319
318
  # Allow the listed repo as an author for any source in the org
320
319
  kici-admin org-settings global-workflows allow-add 'my-org/ci-workflows/*' \
@@ -749,9 +748,8 @@ org-scoped (one row per `customer_id`); each list entry can optionally
749
748
  pin to a specific source via `--source <routingKey>`:
750
749
 
751
750
  ```bash
752
- # Enable global workflows for the org
753
- kici-admin org-settings global-workflows set-enabled true \
754
- --customer-id <orgId>
751
+ # Enable global workflows cluster-wide (the master switch is fleet-wide, held by the operator)
752
+ kici-admin cluster-settings set --global-workflows-enabled true
755
753
 
756
754
  # Allow authors from any source in the org
757
755
  kici-admin org-settings global-workflows allow-add \
@@ -1130,7 +1130,7 @@ When `--target` narrows a `runsOnAll` job to zero hosts, the run **fails** by de
1130
1130
  (a mistyped selector should be loud, not silently no-op). Pass `--target-allow-empty`
1131
1131
  to **skip** the zeroed job instead — it records a `skipped` status, and downstream jobs
1132
1132
  gated with `when: 'on-skip'` (or `when: 'always'`) still run, exactly as for an
1133
- `onUnreachable: 'skip'` zero-host fan-out. See the [CLI reference](https://docs.kici.dev/user/cli-reference/#host-narrowing-with---target)
1133
+ `onUnreachable: 'skip'` zero-host fan-out. See the [CLI reference](https://docs.kici.dev/user/cli/runs-and-approvals/#host-narrowing-with---target)
1134
1134
  for the full flag behavior and the [`needs` gating model](https://docs.kici.dev/user/sdk/core/#job-dependencies-needs)
1135
1135
  for how a skipped upstream propagates.
1136
1136
 
@@ -1174,41 +1174,42 @@ All types are exported from `@kici-dev/sdk` as type-only imports.
1174
1174
 
1175
1175
  ### Trigger types
1176
1176
 
1177
- | Type | Description |
1178
- | ------------------------------- | --------------------------------------------------------------------- |
1179
- | `Trigger` | Trigger definition (trigger config + source location) |
1180
- | `TriggerConfig` | Union of all 23 trigger config types |
1181
- | `PrTriggerConfig` | PR trigger configuration (from `pr()`) |
1182
- | `PushTriggerConfig` | Push trigger configuration (from `push()`) |
1183
- | `TagTriggerConfig` | Tag trigger configuration (from `tag()`) |
1184
- | `CommentTriggerConfig` | Comment trigger configuration (from `comment()`) |
1185
- | `ReviewTriggerConfig` | Review trigger configuration (from `review()`) |
1186
- | `ReviewCommentTriggerConfig` | Review comment trigger configuration (from `reviewComment()`) |
1187
- | `ReleaseTriggerConfig` | Release trigger configuration (from `release()`) |
1188
- | `DispatchTriggerConfig` | Repository dispatch trigger configuration (from `dispatch()`) |
1189
- | `CreateTriggerConfig` | Ref creation trigger configuration (from `create()`) |
1190
- | `DeleteTriggerConfig` | Ref deletion trigger configuration (from `delete()`) |
1191
- | `StatusTriggerConfig` | Commit status trigger configuration (from `status()`) |
1192
- | `WorkflowRunTriggerConfig` | Workflow run trigger configuration (from `workflowRun()`) |
1193
- | `ForkTriggerConfig` | Fork trigger configuration (from `fork()`) |
1194
- | `StarTriggerConfig` | Star trigger configuration (from `star()`) |
1195
- | `WatchTriggerConfig` | Watch trigger configuration (from `watch()`) |
1196
- | `WebhookTriggerConfig` | Catch-all webhook trigger configuration (from `webhook()`) |
1197
- | `KiciEventTriggerConfig` | Custom event trigger configuration (from `kiciEvent()`) |
1198
- | `WorkflowCompleteTriggerConfig` | Workflow completion trigger configuration (from `workflowComplete()`) |
1199
- | `JobCompleteTriggerConfig` | Job completion trigger configuration (from `jobComplete()`) |
1200
- | `GenericWebhookTriggerConfig` | Generic webhook trigger configuration (from `genericWebhook()`) |
1201
- | `ScheduleTriggerConfig` | Schedule trigger configuration (from `schedule()`) |
1202
- | `LifecycleTriggerConfig` | Lifecycle trigger configuration (from `lifecycle()`) |
1203
- | `PrConfigInput` | Config object for `pr()` factory |
1204
- | `PushConfigInput` | Config object for `push()` factory |
1205
- | `BranchPattern` | `{ type: 'glob', pattern } \| { type: 'regex', pattern, flags? }` |
1206
- | `PrEvent` | PR event string literal union (17 event types) |
1207
- | `GenericWebhookConfigInput` | Config object for `genericWebhook()` factory |
1208
- | `GenericWebhookAuth` | Union of generic webhook auth types (HMAC or API key) |
1209
- | `GenericWebhookHmacAuth` | HMAC-SHA256 auth configuration for generic webhooks |
1210
- | `GenericWebhookApiKeyAuth` | API key auth configuration for generic webhooks |
1211
- | `GenericWebhookAuthMethod` | Auth method string literal (`'hmac-sha256' \| 'api-key'`) |
1177
+ | Type | Description |
1178
+ | ----------------------------------- | ------------------------------------------------------------------------------ |
1179
+ | `Trigger` | Trigger definition (trigger config + source location) |
1180
+ | `TriggerConfig` | Union of all 23 trigger config types |
1181
+ | `PrTriggerConfig` | PR trigger configuration (from `pr()`) |
1182
+ | `PushTriggerConfig` | Push trigger configuration (from `push()`) |
1183
+ | `TagTriggerConfig` | Tag trigger configuration (from `tag()`) |
1184
+ | `CommentTriggerConfig` | Comment trigger configuration (from `comment()`) |
1185
+ | `ReviewTriggerConfig` | Review trigger configuration (from `review()`) |
1186
+ | `ReviewCommentTriggerConfig` | Review comment trigger configuration (from `reviewComment()`) |
1187
+ | `ReleaseTriggerConfig` | Release trigger configuration (from `release()`) |
1188
+ | `DispatchTriggerConfig` | Repository dispatch trigger configuration (from `dispatch()`) |
1189
+ | `CreateTriggerConfig` | Ref creation trigger configuration (from `create()`) |
1190
+ | `DeleteTriggerConfig` | Ref deletion trigger configuration (from `delete()`) |
1191
+ | `StatusTriggerConfig` | Commit status trigger configuration (from `status()`) |
1192
+ | `WorkflowRunTriggerConfig` | Workflow run trigger configuration (from `workflowRun()`) |
1193
+ | `ForkTriggerConfig` | Fork trigger configuration (from `fork()`) |
1194
+ | `StarTriggerConfig` | Star trigger configuration (from `star()`) |
1195
+ | `WatchTriggerConfig` | Watch trigger configuration (from `watch()`) |
1196
+ | `WebhookTriggerConfig` | Catch-all webhook trigger configuration (from `webhook()`) |
1197
+ | `KiciEventTriggerConfig` | Custom event trigger configuration (from `kiciEvent()`) |
1198
+ | `WorkflowCompleteTriggerConfig` | Workflow completion trigger configuration (from `workflowComplete()`) |
1199
+ | `WorkflowsFailedBatchTriggerConfig` | Batched workflow-failure trigger configuration (from `workflowsFailedBatch()`) |
1200
+ | `JobCompleteTriggerConfig` | Job completion trigger configuration (from `jobComplete()`) |
1201
+ | `GenericWebhookTriggerConfig` | Generic webhook trigger configuration (from `genericWebhook()`) |
1202
+ | `ScheduleTriggerConfig` | Schedule trigger configuration (from `schedule()`) |
1203
+ | `LifecycleTriggerConfig` | Lifecycle trigger configuration (from `lifecycle()`) |
1204
+ | `PrConfigInput` | Config object for `pr()` factory |
1205
+ | `PushConfigInput` | Config object for `push()` factory |
1206
+ | `BranchPattern` | `{ type: 'glob', pattern } \| { type: 'regex', pattern, flags? }` |
1207
+ | `PrEvent` | PR event string literal union (17 event types) |
1208
+ | `GenericWebhookConfigInput` | Config object for `genericWebhook()` factory |
1209
+ | `GenericWebhookAuth` | Union of generic webhook auth types (HMAC or API key) |
1210
+ | `GenericWebhookHmacAuth` | HMAC-SHA256 auth configuration for generic webhooks |
1211
+ | `GenericWebhookApiKeyAuth` | API key auth configuration for generic webhooks |
1212
+ | `GenericWebhookAuthMethod` | Auth method string literal (`'hmac-sha256' \| 'api-key'`) |
1212
1213
 
1213
1214
  ### Rule types
1214
1215