@kici-dev/compiler 0.4.0 → 0.6.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 (83) hide show
  1. package/dist/cli.js +37 -7
  2. package/dist/commands/approve.d.ts +12 -0
  3. package/dist/commands/approve.js +5 -2
  4. package/dist/commands/compile.js +5 -15
  5. package/dist/commands/doctor.js +2 -2
  6. package/dist/commands/endpoints.js +4 -6
  7. package/dist/commands/held-run-client.d.ts +21 -1
  8. package/dist/commands/held-run-client.js +34 -15
  9. package/dist/commands/hook.js +22 -20
  10. package/dist/commands/index.d.ts +2 -0
  11. package/dist/commands/index.js +2 -1
  12. package/dist/commands/init.d.ts +9 -2
  13. package/dist/commands/init.js +43 -16
  14. package/dist/commands/login.js +1 -1
  15. package/dist/commands/orchestrators.js +3 -2
  16. package/dist/commands/preview.js +1 -8
  17. package/dist/commands/reject.d.ts +12 -0
  18. package/dist/commands/reject.js +5 -2
  19. package/dist/commands/report/collect.d.ts +82 -0
  20. package/dist/commands/report/collect.js +234 -0
  21. package/dist/commands/report/identity.d.ts +48 -0
  22. package/dist/commands/report/identity.js +49 -0
  23. package/dist/commands/report/index.d.ts +63 -0
  24. package/dist/commands/report/index.js +119 -0
  25. package/dist/commands/report/upload.d.ts +38 -0
  26. package/dist/commands/report/upload.js +64 -0
  27. package/dist/commands/run-hold-watch.js +2 -2
  28. package/dist/commands/run.js +6 -3
  29. package/dist/commands/runs/show.js +80 -1
  30. package/dist/commands/types.js +51 -9
  31. package/dist/errors/formatter.d.ts +2 -4
  32. package/dist/errors/formatter.js +1 -3
  33. package/dist/errors/index.d.ts +1 -1
  34. package/dist/errors/index.js +2 -2
  35. package/dist/execution/sdk-alias.js +4 -2
  36. package/dist/fixtures/compiler.js +2 -1
  37. package/dist/format.js +3 -3
  38. package/dist/generators/secrets-dts.d.ts +8 -3
  39. package/dist/generators/secrets-dts.js +3 -3
  40. package/dist/hooks/installer.js +2 -1
  41. package/dist/llm-context/llms-architecture.txt +59 -23
  42. package/dist/llm-context/llms-cli.txt +168 -34
  43. package/dist/llm-context/llms-features-execution.txt +2017 -0
  44. package/dist/llm-context/llms-features.txt +96 -1100
  45. package/dist/llm-context/llms-full.txt +3131 -1407
  46. package/dist/llm-context/llms-getting-started.txt +164 -31
  47. package/dist/llm-context/llms-patterns.txt +186 -7
  48. package/dist/llm-context/llms-providers.txt +15 -33
  49. package/dist/llm-context/llms-sdk-runtime.txt +62 -40
  50. package/dist/llm-context/llms-sdk.txt +284 -58
  51. package/dist/llm-context/llms.txt +23 -15
  52. package/dist/local-plane/paths.d.ts +15 -0
  53. package/dist/local-plane/paths.js +22 -1
  54. package/dist/local-plane/plane-manager.js +2 -2
  55. package/dist/local-plane/port-holder.js +1 -1
  56. package/dist/local-plane/postgres.d.ts +3 -16
  57. package/dist/local-plane/postgres.js +10 -15
  58. package/dist/lockfile/generator.d.ts +12 -0
  59. package/dist/lockfile/generator.js +182 -54
  60. package/dist/lockfile/index.d.ts +0 -2
  61. package/dist/lockfile/index.js +1 -2
  62. package/dist/postinstall.js +2 -1
  63. package/dist/remote/config.d.ts +2 -15
  64. package/dist/remote/config.js +2 -16
  65. package/dist/remote/dashboard-client.d.ts +39 -0
  66. package/dist/remote/dashboard-client.js +41 -0
  67. package/dist/remote/oauth.js +7 -5
  68. package/dist/remote/uploader.js +2 -2
  69. package/dist/templates/package-json.js +1 -1
  70. package/dist/test-runner/dry-run.d.ts +1 -2
  71. package/dist/test-runner/dry-run.js +5 -20
  72. package/dist/test-runner/git-detector.js +2 -1
  73. package/dist/test-runner/job-executor.js +2 -1
  74. package/dist/test-runner/payload-builder.js +11 -17
  75. package/dist/types.d.ts +64 -10
  76. package/dist/types.js +7 -1
  77. package/dist/validation/validator.js +63 -6
  78. package/package.json +16 -11
  79. package/sbom.spdx.json +957 -900
  80. package/dist/lockfile/purity-analyzer.d.ts +0 -25
  81. package/dist/lockfile/purity-analyzer.js +0 -204
  82. package/dist/lockfile/purity-diagnostics.d.ts +0 -31
  83. package/dist/lockfile/purity-diagnostics.js +0 -52
@@ -313,12 +313,16 @@ The `ProviderRegistry` maps routing keys to provider bundles. Each routing key (
313
313
  - `WebhookNormalizer` (required) -- normalizes incoming webhooks to a standard format
314
314
  - `LockFileFetcher` -- fetches lock files from the repository
315
315
  - `ChangedFilesFetcher` -- determines which files changed
316
+ - `FileContentsFetcher` -- reads arbitrary repository files at a ref, for the declarative content-requirements (`requires`) filter
316
317
  - `CloneTokenProvider` -- generates clone tokens for agents
317
318
  - `RepoUrlBuilder` -- builds clone URLs and raw file URLs
318
- - `ContributorResolver` -- resolves contributor permissions for trust-tier gating
319
319
  - `CheckStatusPoster` -- posts check statuses (approval/hold) to the git provider
320
320
 
321
- A GitHub App source populates all seven. A plain generic webhook source carries only the normalizer -- it has no repository API to fetch a lock file, resolve a contributor, or post a check against -- so the pipeline skips the stages whose interface is absent rather than failing the delivery.
321
+ A bundle also carries a `hasForkModel` flag, set for a provider whose head ref can live outside the base repository. It is what admits a pull-request event to the org fork switch. GitHub sets it; a generic source (whose trust boundary is its verification secret) and a local source (whose trust boundary is on-disk ownership) do not.
322
+
323
+ A GitHub App source populates all seven. The file-contents capability arrives as a per-delivery factory rather than a prebuilt instance: a GitHub client is scoped to one installation, and the installation id is known only once the delivery's credentials are resolved.
324
+
325
+ A plain generic webhook source carries only the normalizer, because it has no repository API to fetch a lock file or post a check against. The pipeline skips the stages whose interface is absent rather than failing the delivery.
322
326
 
323
327
  Provider registrations are managed via the `sources` database table, not via `SharedConfig`. When the orchestrator connects to the Platform relay, it reads source records from the DB and sends `source.register` messages. Changes to sources (add/remove) are detected via PostgreSQL LISTEN/NOTIFY on the `sources_change` channel and pushed to the Platform via `source.secrets` and `source.register`/`source.deregister`.
324
328
 
@@ -406,10 +410,11 @@ GitHub --> Platform Relay --> Orchestrator --> Agent
406
410
  12. **Orchestrator extracts registrations** on default-branch pushes: persists registerable workflows (event, schedule, lifecycle triggers) for cluster-wide event matching.
407
411
  13. **Orchestrator notifies the event router** on default-branch pushes: after the registrations are persisted, emits a `registration.updated` event via `eventRouter.emit()` (if event routing is active). Workflow event subscriptions are the persisted registrations themselves, matched at emit time through the registration index.
408
412
  14. **Orchestrator fetches changed files** via the provider's `ChangedFilesFetcher` for path-based trigger filtering (skipped when no workflow uses path filters).
409
- 15. **Orchestrator matches triggers** against lock file using `matchAllWorkflows()` from `@kici-dev/engine`.
410
- 16. **Orchestrator checks caches** for source tarballs and dependency tarballs.
411
- 17. **Orchestrator dispatches jobs** to agents via the job queue and WebSocket.
412
- 18. **Orchestrator persists a delivery row** keyed by `(org_id, delivery_id)` to its own `event_log`, including a pointer to the gzipped payload in object storage. The orchestrator's delivery log is surfaced in the dashboard's Settings → Event log tab. See [`webhook-delivery.md`](https://docs.kici.dev/architecture/webhooks/webhook-delivery/#delivery-log).
413
+ 15. **Orchestrator matches triggers** against the lock file using `matchWorkflowsForEvent()` from `@kici-dev/engine` -- an event-type-bucketed candidate scan that evaluates only the workflows subscribed to this event type. (The single-registration global / cross-source paths evaluate one lock entry at a time via `matchAllWorkflows()`.)
414
+ 16. **Orchestrator applies the content-requirements filter** to the matched candidates: for each trigger that declares `requires`, it reads the named source files at the event's ref through the provider's `FileContentsFetcher` (once per distinct `(repo, sha, path)` via an LRU cache) and evaluates the declarative requirement. Candidates that fail -- or that cannot be evaluated at all (unreadable or oversize content, a fetch error, no fetcher wired) -- are dropped before dispatch with the concrete reason logged. No workflow code runs at this stage. Skipped entirely when no matched trigger declares `requires`.
415
+ 17. **Orchestrator checks caches** for source tarballs and dependency tarballs.
416
+ 18. **Orchestrator dispatches jobs** to agents via the job queue and WebSocket.
417
+ 19. **Orchestrator persists a delivery row** keyed by `(org_id, delivery_id)` to its own `event_log`, including a pointer to the gzipped payload in object storage. The orchestrator's delivery log is surfaced in the dashboard's Settings → Event log tab. See [`webhook-delivery.md`](https://docs.kici.dev/architecture/webhooks/webhook-delivery/#delivery-log).
413
418
 
414
419
  ## Job execution flow
415
420
 
@@ -437,7 +442,18 @@ Orchestrator Agent Sandbox (child pro
437
442
 
438
443
  ### Agent pipeline
439
444
 
440
- The agent delegates job execution to an `ExecutionSandbox` (container, bare-metal, or firecracker). The sandbox runs customer code in an isolated child process -- never in the agent's V8 isolate. Four job types are handled: execution jobs (sandbox), build-only jobs (in-process, cache population), init-only jobs (in-process, dynamic field resolution), and DynamicJobFn evaluation jobs (in-process, runtime job generation). See [Job execution lifecycle](https://docs.kici.dev/architecture/execution/job-execution/) for details.
445
+ The agent delegates job execution to an `ExecutionSandbox` (container, bare-metal, or firecracker). The sandbox runs customer code in an isolated child process -- never in the agent's V8 isolate.
446
+
447
+ Six job types are handled. Only the first uses a sandbox; the other five run in-process, because they never execute customer workflow steps:
448
+
449
+ - **Execution jobs** -- the standard sandbox path.
450
+ - **Init-only jobs** -- dynamic field resolution.
451
+ - **Global-eval-round jobs** -- filters and generators for the candidate global workflows of one workflow repo.
452
+ - **DynamicJobFn evaluation jobs** -- runtime job generation.
453
+ - **Bring-up jobs** -- init-runner SSH bring-up. No clone, no sandbox.
454
+ - **Build-only jobs** -- cache population.
455
+
456
+ See [Job execution lifecycle](https://docs.kici.dev/architecture/execution/job-execution/) for details.
441
457
 
442
458
  1. **Report running** -- Send `job.status: running` immediately upon accepting the dispatch
443
459
  2. **Sandbox selection** -- Determine execution mode (container, bare-metal, firecracker) from job config and environment
@@ -510,7 +526,7 @@ Build Job Dispatch --> Build Agent (kici:role:builder + matching kici:os:/kici:a
510
526
  | |-- Pack .kici/ source (portable tar.gz, excludes node_modules)
511
527
  | |-- Pack .kici/node_modules (portable tar.gz)
512
528
  | |-- Upload source tarball to cache (source/{contentHash}.tar.gz)
513
- | |-- Upload deps tarball to cache (deps/{plat}-{arch}/{lockfileHash}.tar.gz)
529
+ | |-- Upload deps tarball to cache (deps/{plat}-{arch}/{depsHash}.tar.gz)
514
530
  | |-- Upload deps companion .hash file
515
531
  | |-- Report success (cache.upload.complete × 2)
516
532
  | |
@@ -525,7 +541,7 @@ Execution Job Dispatch --> Execution Agent
525
541
  | |
526
542
  | |-- Download source tarball (sourceTarUrl) -> extract to workDir/.kici/
527
543
  | |-- Download deps tarball (depsUrl) -> verify SHA-256 -> extract to .kici/node_modules/
528
- | |-- Register @kici-dev/shared/ts-loader-hook
544
+ | |-- Register @kici-dev/core/ts-loader-hook
529
545
  | |-- Verify workflow contentHash against lock file (drift guard)
530
546
  | |-- Dynamic-import workflow .ts
531
547
  | |-- Execute steps
@@ -584,7 +600,7 @@ Dep cache misses alone do **not** trigger a build job. Deps are platform-specifi
584
600
 
585
601
  ### Cross-source / no-contentHash workflows
586
602
 
587
- - **Lock files without `contentHash`** (schema v1) skip the source cache entirely; agents compile from source. Regenerate lock files with `kici compile` to enable caching. The current lock file schema version is 32.
603
+ - **Lock files without `contentHash`** (schema v1) skip the source cache entirely; agents compile from source. Regenerate lock files with `kici compile` to enable caching. The current lock file schema version is 39.
588
604
  - **Cross-source / global-workflow dispatch** (a workflow registered against source A fired by a webhook on source B) bypasses both caches. The registration's lock file entry still carries `contentHash`, but the cross-source path always clone-and-installs — the eval temp dir doesn't ship `@kici-dev/sdk`. The execution agent still verifies `contentHash` against the cloned source for drift detection.
589
605
 
590
606
  ### Build deduplication
@@ -624,7 +640,10 @@ Both source and dep caches use `S3CacheStorage` as the sole backend. The `CacheS
624
640
  Cache keys reflect that source tarballs and deps have different platform characteristics:
625
641
 
626
642
  - **Source:** `source/{contentHash}.tar.gz` — platform-agnostic. Raw TypeScript source is identical regardless of CPU architecture, so one entry is shared across all platforms. `contentHash` is the per-workflow hash from the lock file (`SHA-256(COMPILE_SCHEMA_VERSION + ":" + rawSource [+ "\0" + assetDigest])`, where `COMPILE_SCHEMA_VERSION = 5` and line endings are normalized to LF so the hash agrees across platforms).
627
- - **Deps:** `deps/{platform}-{arch}/{lockfileHash}.tar.gz` (e.g., `deps/linux-arm64/def456.tar.gz`) — platform-specific. Native dependencies in `node_modules` differ across architectures, so each platform/arch combination gets its own cache entry.
643
+ - **Deps:** `deps/{platform}-{arch}/{depsHash}.tar.gz`, with a
644
+ `deps/{platform}-{arch}/{lockfileHash}.hash` pointer holding that hash — the
645
+ tarball is addressed by its own content, so two builds sharing a lock file
646
+ cannot leave a tarball and an integrity hash that disagree. Platform-specific. Native dependencies in `node_modules` differ across architectures, so each platform/arch combination gets its own cache entry.
628
647
 
629
648
  The orchestrator derives the target platform/arch for dep cache lookups by probing `AgentRegistry.findAvailable()` with the workflow's first job's `runsOn` labels to find a representative matching agent, then using that agent's platform and arch. Falls back to `linux/x64` if no matching agents are registered.
630
649
 
@@ -829,7 +848,7 @@ Agent Orchestrator
829
848
 
830
849
  ### Registration extraction flow
831
850
 
832
- When code is pushed to the default branch, the orchestrator extracts event-triggered workflows from the lock file and stores them as registrations for cluster-wide event matching.
851
+ When code is pushed to the default branch, the orchestrator extracts registerable workflows from the lock file and stores them as registrations for cluster-wide event matching. Non-Git triggers (`kici_event`, `schedule`, `generic_webhook`, …) live there because they have no per-repo lock-file pipeline to fall back on; Git-provider triggers (`push`, `pr`, `tag`, …) are indexed too, so the cross-source dispatch path can resolve them by `(customer_id, repo_identifier)` when a generic webhook targets an externally-hosted repo. For same-source Git events the per-event lock-file pipeline remains the primary matcher — registration is an additive index.
833
852
 
834
853
  ```
835
854
  Git Push to Default Branch
@@ -842,8 +861,15 @@ GitHub Webhook -> Platform Relay -> Orchestrator Processor
842
861
  |-- extractRegisterableWorkflows(fullLockFile)
843
862
  | |-- For each workflow entry in lock file:
844
863
  | | Check if any trigger type is registerable
845
- | | (kici_event, workflow_complete, job_complete,
846
- | | generic_webhook, schedule, lifecycle)
864
+ | | (the RegisterableTriggerType enum — the non-Git
865
+ | | set kici_event, workflow_complete,
866
+ | | workflows_failed_batch, job_complete,
867
+ | | generic_webhook, schedule, lifecycle, webhook,
868
+ | | plus every Git-provider trigger: push, pr, tag,
869
+ | | comment, review, review_comment, release,
870
+ | | dispatch, create, delete, status, workflow_run,
871
+ | | fork, star, watch)
872
+ | | ... or the workflow has repo patterns (global workflow)
847
873
  | |-- Return array of registerable workflows
848
874
  |
849
875
  |-- globalWorkflowPolicy.isWorkflowRepoAllowed() (if policy configured)
@@ -1221,7 +1247,7 @@ The Platform tier exposes a `/ws/browser` WebSocket endpoint for dashboard clien
1221
1247
  - [Architecture overview](https://docs.kici.dev/architecture/overview/) -- three-tier model and component responsibilities
1222
1248
  - [Protocol messages](https://docs.kici.dev/architecture/protocol-messages/) -- WebSocket message schemas
1223
1249
  - [Event system internals](https://docs.kici.dev/architecture/webhooks/event-system/) -- event router, registration model, cron scheduler
1224
- - [Execution lifecycle](https://docs.kici.dev/architecture/execution/state-machine/) -- run, job, and step status vocabularies and terminal states
1250
+ - [Execution status vocabulary](https://docs.kici.dev/architecture/execution/state-machine/) -- run, job, and step status vocabularies and terminal states
1225
1251
  - [Webhook delivery](https://docs.kici.dev/architecture/webhooks/webhook-delivery/) -- detailed webhook processing pipeline
1226
1252
  - [Operator: dependency caching](https://docs.kici.dev/operator/dependency-caching/) -- configuration guide
1227
1253
  - [Operator: monitoring & tracing](https://docs.kici.dev/operator/observability/monitoring/) -- trace fields and Loki queries
@@ -1295,7 +1321,7 @@ The orchestrator is the execution brain. It decides what to run and dispatches w
1295
1321
  - **Job queue** -- PostgreSQL-backed FIFO queue for reliable dispatch.
1296
1322
  - **Webhook pipeline** -- Dedup, event mapping, lock file fetch, trigger matching, and job dispatch in a single pipeline.
1297
1323
  - **Multi-orchestrator clustering** -- Optional peer-to-peer coordination via direct WebSocket connections. Enables cross-architecture job routing (e.g., x64 coordinator reroutes arm64 jobs to a peer), high availability, and dedicated coordinator topologies. Uses Raft consensus for leader election (orphan recovery). See [Multi-Orchestrator Architecture](https://docs.kici.dev/architecture/clustering/multi-orchestrator/).
1298
- - **Auto-scaler** -- Optional pluggable module for ephemeral agent provisioning. Supports containers (Docker/Podman), bare-metal processes, and Firecracker microVMs as backends. Spawns agents on demand when no matching agent is connected, with label-based routing, two-level capacity limits (global + per-backend), warm pools, YAML configuration (`scalers.d/` directory support), and SIGHUP reload. Disabled by default -- orchestrator works without it.
1324
+ - **Auto-scaler** -- Optional pluggable module for ephemeral agent provisioning. Four backends are configurable: containers (Docker/Podman), bare-metal processes, Firecracker microVMs, and the event backend, which performs no local compute -- it emits reserved scale-up / scale-down events that a customer-authored provisioning workflow consumes to boot and tear down a cloud instance. Spawns agents on demand when no matching agent is connected, with label-based routing, two-level capacity limits (global + per-backend), warm pools, YAML configuration (`scalers.d/` directory support), and SIGHUP reload. Disabled by default -- orchestrator works without it.
1299
1325
  - **Independent database** -- Has its own PostgreSQL database separate from the Platform. Stores execution runs/jobs/steps, dispatch queue, webhook secrets, dedup cache, and scaler state. The orchestrator's `execution_runs` and `execution_jobs` are the authoritative source of truth. The Platform receives execution status updates via WebSocket messages (`execution.status`, `job.status.forward`).
1300
1326
 
1301
1327
  > Source: `packages/orchestrator/src/pipeline/processor.ts` (webhook pipeline), `packages/orchestrator/src/cluster/` (P2P coordination), `packages/orchestrator/src/scaler/` (auto-scaler module), `packages/orchestrator/src/server.ts` (Platform/hybrid entry point)
@@ -1305,6 +1331,7 @@ The orchestrator is the execution brain. It decides what to run and dispatches w
1305
1331
  The agent is the execution worker. It runs on customer infrastructure and has full access to customer code.
1306
1332
 
1307
1333
  - **Repository cloning** -- Clones the target repo with token-based auth (token in HTTP headers, not URLs, to prevent leakage).
1334
+ - **Git credential helper** -- Registers a credential helper for the job's git operations. Every network operation asks the orchestrator's broker for a credential, so a token is minted seconds before use rather than held for the life of the job. Write access is opt-in and time-boxed: `ctx.repo.withWrite(...)` adds a repository-scoped grant for the duration of its callback and revokes it afterwards, with a TTL backstop.
1308
1335
  - **Step execution** -- Runs steps in declaration order with full `StepContext` (zx shell, logger, environment, workflow/job metadata). Steps wrapped in a `parallel()` group run concurrently behind a `maxParallel` window, and each child reports as its own observable step with its own logs, status, timing, and retry.
1309
1336
  - **Execution sandboxes** -- Runs the workflow runner as a separate child process with a sanitized environment, in one of three sandboxes: bare metal (process fork, with optional bubblewrap namespace isolation), a container runtime (the whole job lifecycle runs inside a disposable container), or inside a Firecracker microVM. Agent-internal credentials never reach customer workflow code.
1310
1337
  - **Log streaming** -- Chunked log streaming back to the orchestrator with configurable size limits.
@@ -1320,11 +1347,14 @@ The agent is the execution worker. It runs on customer infrastructure and has fu
1320
1347
  Shared business logic used by all three tiers. Single source of truth for cross-tier concerns. Has no internal `@kici-dev/*` dependencies -- only a handful of third-party libraries.
1321
1348
 
1322
1349
  - Protocol message schemas (Zod-based, direction-specific unions including dashboard REST-over-WS, browser live streaming, the test-relay control plane, log pull, run events, peer-to-peer, cluster join, and source registration)
1323
- - Provider interfaces (WebhookNormalizer, LockFileFetcher, ChangedFilesFetcher, CloneTokenProvider, RepoUrlBuilder, ContributorResolver, CheckStatusPoster)
1350
+ - Provider interfaces (WebhookNormalizer, LockFileFetcher, ChangedFilesFetcher, FileContentsFetcher, CloneTokenProvider, RepoUrlBuilder, CheckStatusPoster), plus the deprecated `ContributorResolver` the pipeline no longer calls
1351
+ - Git credential vocabulary (forge names plus the credential reference, grant, request, and result shapes the SDK declares and the orchestrator's broker resolves) and the agent→orchestrator relay protocol its credential helper calls. See [Git credentials](https://docs.kici.dev/user/patterns/git-credentials/)
1324
1352
  - Trigger matching engine (branch, path, event evaluation)
1353
+ - Content-requirement matcher (the declarative `requires` filter -- pure data describing a query over the bytes of one source file at the event's ref, interpreted by the orchestrator via the `FileContentsFetcher` so no author code runs there) and the shared text-match vocabulary (`contains` / `notContains` / `matches` / `notMatches`) it shares with the commit-message trigger filter
1325
1354
  - Dispatch inputs (input descriptors, extraction from the trigger event, and coercion to typed values)
1326
1355
  - Matrix expansion and fanout (combination expansion with include/exclude, job-name suffix formatting, and materialization of one matrix or multi-host job into N dispatchable children)
1327
- - Execution status vocabulary (run/job/step status enums + terminal-state sets; lifecycle owned by the orchestrator's execution tracker)
1356
+ - Execution status vocabulary (run/job/step status enums + terminal-state sets; lifecycle owned by the orchestrator's execution tracker) and its presentation layer (the total precedence order that decides which status wins a roll-up, legacy-spelling resolution, and the per-status failure classification every consumer asks about)
1357
+ - Job-kind discriminator, alongside the status enums. It separates a `standard` job running steps from an invoke `gate` and from the `proxy` job that mirrors a summoned run
1328
1358
  - Check mode (the idempotent run modes `apply` / `check` / `check-fail-on-drift` and the per-step outcome vocabulary)
1329
1359
  - Webhook signature verification (HMAC-SHA256, timing-safe)
1330
1360
  - WebSocket close codes (unified across all tiers)
@@ -1335,12 +1365,18 @@ Shared business logic used by all three tiers. Single source of truth for cross-
1335
1365
  - Approval requirements (normalized approver clauses shared by the orchestrator gate, the resolver, the held-run store, and the agent step round-trip)
1336
1366
  - Build provenance (in-toto statement schema, DSSE envelope, attestation bundle, verification)
1337
1367
  - Artifact name contract (the shared filesystem/URL-safe name schema the orchestrator, agent, and SDK all validate against)
1338
- - Developer MCP tool schemas (argument schemas for the AI-agent tool surface)
1368
+ - Developer MCP tool schemas (argument schemas for the AI-agent tool surface) and the untrusted-content fence that wraps every repository- or contributor-supplied value an agent reads in a per-response random nonce, so log lines and error text cannot be read as instructions
1369
+ - Developer-operations contract (one row per workflow-developer operation declaring which entrypoints expose it -- the shared REST API behind the web UI and the `kici` CLI, the AI-agent tool surface, and a curated UI flag -- asserted against each real surface by congruence tests)
1339
1370
  - Label utilities (platform label derivation, runsOn normalization, `kici:*` set-only reserved namespace, role labels)
1340
1371
  - Host inventory (the canonical queryable host-roster schema shared by the orchestrator's roster store, the agent-facing inventory API, and the SDK's `ctx.kici.inventory`)
1341
1372
  - Audit policy and retention (per-action access-log sampling, warm-retention windows for cold-store eligibility, federated activity row schema)
1342
- - Scaler backend type enum (`container`, `bare-metal`, `firecracker`, `kubernetes`)
1373
+ - Scaler backend type enum (`container`, `bare-metal`, `firecracker`, `kubernetes`, `event`) and the reserved `kici.` event-name prefix that keeps a user step from forging a system event
1374
+ - Job resource vocabulary (the requests/limits shape the SDK accepts, the compiler validates and emits, the orchestrator uses for capacity math and kernel-side enforcement, and the dashboard displays)
1343
1375
  - Registration trigger type enum (registerable trigger discriminator)
1376
+ - Sandbox capability set (the Linux capability names a container sandbox may add or drop, shared by the SDK validator, the compiler, and the dispatch resolver)
1377
+ - Plan tier vocabulary (the hosted plan tiers and the purchasable subset, shared by the Platform and the browser dashboard)
1378
+ - Infrastructure alert vocabulary (the diagnostics alert types and severities the Platform mints and the dashboard and `kici` CLI render)
1379
+ - Metric catalog (the generated Prometheus metric inventory, its naming policy, and metric-kind compatibility checks)
1344
1380
  - Bundler config (shared bundler configuration consumed by `e2e/helpers/service-deploy.ts`; the agent runtime uses the `@kici-dev/core/ts-loader-hook` to transform TypeScript on import, with no runtime bundler step)
1345
1381
 
1346
1382
  > Source: `packages/engine/src/`
@@ -1361,7 +1397,7 @@ It also runs the **local dev plane** -- an on-demand, fully local execution stac
1361
1397
 
1362
1398
  ### `@kici-dev/core`
1363
1399
 
1364
- Light shared utilities with no server-side dependencies JSON-structured logging, error helpers, human-readable formatting (`formatBytes`/`formatDuration`/`formatUptime`), cryptographic helpers (`sha256`/`sha256File`/`deriveSharedSecret`), zx initialization (`initZx()`), and the TypeScript loader hook that transforms TypeScript on import. It is the dependency-light core that the SDK, compiler, and `kici` CLI consume directly so they stay free of heavier server-only dependencies. `@kici-dev/shared` re-exports it, so existing `@kici-dev/shared` import paths keep working.
1400
+ Light shared utilities with no server-side dependencies. It provides JSON-structured logging, error helpers, async-local-storage request context, and human-readable formatting (`formatBytes`/`formatDuration`/`formatUptime`). It also provides cryptographic helpers (`sha256`/`sha256File`/`deriveSharedSecret` plus symmetric encrypt/decrypt), retry-backoff computation, and the shared diagnostics-result contract. The rest of its surface ships as subpath entry points: the temp-directory allocator and its garbage collector, package-manager detection, CI-environment detection, and the idempotent-step runner (the check / confirm / apply primitive behind idempotent steps). Finally it supplies zx initialization (`initZx()`) and the TypeScript loader hook that transforms TypeScript on import. It is the dependency-light core that the SDK, compiler, and `kici` CLI consume directly so they stay free of heavier server-only dependencies. `@kici-dev/shared` re-exports it, so existing `@kici-dev/shared` import paths keep working.
1365
1401
 
1366
1402
  > Source: `packages/core/src/`
1367
1403
 
@@ -1449,7 +1485,7 @@ The orchestrator connects outbound to the Platform WebSocket endpoint. After aut
1449
1485
 
1450
1486
  When multiple orchestrators are deployed, they establish direct WebSocket connections to each other on the `/ws/peer` endpoint. Peers are discovered via the Platform matchmaker (Platform/hybrid modes) or static configuration (`KICI_CLUSTER_PEERS` env var, independent mode). Connections are authenticated with a mutual pre-shared key (PSK). Traffic includes agent inventory heartbeats, job rerouting, progress reporting, cancel propagation, and Raft leader election. These messages never transit the Platform tier.
1451
1487
 
1452
- > See [Multi-Orchestrator Architecture](https://docs.kici.dev/architecture/clustering/multi-orchestrator/) for clustering details and [Protocol Messages](https://docs.kici.dev/architecture/protocol/dashboard/#orchestrator-orchestrator-messages-peer-to-peer) for message schemas.
1488
+ > See [Multi-Orchestrator Architecture](https://docs.kici.dev/architecture/clustering/multi-orchestrator/) for clustering details and [Protocol Messages](https://docs.kici.dev/architecture/protocol/dashboard/#orchestrator---orchestrator-messages-peer-to-peer) for message schemas.
1453
1489
 
1454
1490
  ### Orchestrator ↔ Agent
1455
1491
 
@@ -1464,7 +1500,7 @@ KiCI uses application-level tenant isolation. The Platform dashboard API accepts
1464
1500
  ## See also
1465
1501
 
1466
1502
  - [Multi-Orchestrator Architecture](https://docs.kici.dev/architecture/clustering/multi-orchestrator/) -- P2P clustering, Raft consensus, job rerouting
1467
- - [Execution lifecycle](https://docs.kici.dev/architecture/execution/state-machine/) -- run, job, and step status vocabularies and the tracker that owns lifecycle state
1503
+ - [Execution status vocabulary](https://docs.kici.dev/architecture/execution/state-machine/) -- run, job, and step status vocabularies and the tracker that owns lifecycle state
1468
1504
  - [Protocol Messages](https://docs.kici.dev/architecture/protocol-messages/) -- WebSocket message schemas for all three layers
1469
1505
  - [Webhook Delivery](https://docs.kici.dev/architecture/webhooks/webhook-delivery/) -- end-to-end trace of a webhook through all three tiers
1470
1506
 
@@ -340,8 +340,11 @@ kici logout
340
340
  This:
341
341
 
342
342
  1. Revokes the PAT on the server (preventing further use)
343
- 2. Clears auth fields from the local config file
344
- 3. Preserves non-auth settings (active org, default clusters, Platform endpoint)
343
+ 2. Detaches the local dev plane if it is attached, so a logged-out user is not left with a hybrid plane holding an orphaned orchestrator key
344
+ 3. Clears the auth fields from the local config file — the PAT, its id and expiry, your email, and the active organization
345
+ 4. Preserves the connection settings (per-org default clusters, Platform endpoint, orchestrator endpoint, OIDC issuer, routing key)
346
+
347
+ Server revocation is best-effort: if the network call fails, the local config is still cleared.
345
348
 
346
349
  ## Organization management
347
350
 
@@ -502,11 +505,13 @@ Every `/api/v1/*` mutation that touches tenant-plane data is recorded in the ups
502
505
 
503
506
  The CLI stores authentication data in `~/.kici/config` with `0600` permissions (owner read/write only). The config file contains:
504
507
 
505
- - PAT token
506
- - PAT expiry date
508
+ - PAT token, its server-side id, and its expiry date
509
+ - The email address from your OIDC token
507
510
  - Active organization ID
508
511
  - Per-org default orchestrator clusters
509
- - Platform endpoint URL
512
+ - Platform endpoint URL, orchestrator endpoint URL, and the OIDC issuer the PAT was minted against
513
+ - Routing key for webhook source identification
514
+ - API key, when you logged in with `--token`
510
515
 
511
516
  ## Troubleshooting
512
517
 
@@ -540,11 +545,11 @@ Two ways forward:
540
545
 
541
546
  A port below 1024 fails the same way, with a permissions message rather than an "in use" one: those ports need elevated privileges. Pick a port above 1024. A value that is not a port number at all — non-numeric, negative, or above 65535 — is rejected before the login starts, naming the value you set.
542
547
 
543
- ### Device flow timeout
548
+ ### Device code expired
544
549
 
545
550
  This is the device flow's own expiry, not the browser flow's callback timeout above.
546
551
 
547
- The device flow has a 5-minute timeout. If it expires:
552
+ The device code is issued by the identity provider, which also sets how long it lives. The CLI prints the lifetime with the code (`Code expires in N minutes`) and polls until you approve or the code expires. On expiry it stops with `Device code expired`. If that happens:
548
553
 
549
554
  - Run `kici login --device` again to get a new code
550
555
  - Ensure you're using the correct URL displayed by the CLI
@@ -605,7 +610,7 @@ The full command reference is split by area:
605
610
  - [Authoring & local dev](https://docs.kici.dev/user/cli/authoring-and-local/) — `compile`, `preview`, `local`, `fixture`, `types`, `workflows`, `hook`, `docs`
606
611
  - [Runs & approvals](https://docs.kici.dev/user/cli/runs-and-approvals/) — `run`, `runs`, `reject`, `approve`
607
612
  - [Account & org](https://docs.kici.dev/user/cli/account-and-org/) — `login`, `logout`, `init`, `org`, `pat`, `secrets`, `admin`, `orchestrators`, `endpoints`
608
- - [Notifications & diagnostics](https://docs.kici.dev/user/cli/notifications-and-diagnostics/) — `notifications`, `verify-attestation`, `diagnostics`, `doctor`
613
+ - [Notifications & diagnostics](https://docs.kici.dev/user/cli/notifications-and-diagnostics/) — `notifications`, `verify-attestation`, `diagnostics`, `doctor`, `report`
609
614
 
610
615
  Each area page carries a `## Guide` section (worked examples and command-by-command narrative) and a `## Reference` section (the always-current generated signature list for that area's commands).
611
616
 
@@ -702,12 +707,13 @@ companion at [Operator troubleshooting](https://docs.kici.dev/operator/troublesh
702
707
 
703
708
  ## Fast triage
704
709
 
705
- | You see... | Jump to |
706
- | -------------------------------------------------------------- | ------------------------------------------------------- |
707
- | A run finishes with `No jobs dispatched` | [No jobs dispatched](https://docs.kici.dev/user/common-failures/#no-jobs-dispatched) |
708
- | A run fails complaining the lock file is stale or incompatible | [Lock-file drift](https://docs.kici.dev/user/common-failures/#lock-file-drift) |
709
- | You pushed but no run ever appears | [The webhook never arrives](https://docs.kici.dev/user/common-failures/#the-webhook-never-arrives) |
710
- | A run is stuck "queued" and no agent ever picks it up | [The agent won't connect](https://docs.kici.dev/user/common-failures/#the-agent-wont-connect) |
710
+ | You see... | Jump to |
711
+ | -------------------------------------------------------------- | ----------------------------------------------------------------------------------- |
712
+ | A run finishes with `No jobs dispatched` | [No jobs dispatched](https://docs.kici.dev/user/common-failures/#no-jobs-dispatched) |
713
+ | A run fails complaining the lock file is stale or incompatible | [Lock-file drift](https://docs.kici.dev/user/common-failures/#lock-file-drift) |
714
+ | You pushed but no run ever appears | [The webhook never arrives](https://docs.kici.dev/user/common-failures/#the-webhook-never-arrives) |
715
+ | A run is stuck "queued" and no agent ever picks it up | [The agent won't connect](https://docs.kici.dev/user/common-failures/#the-agent-wont-connect) |
716
+ | A `commitMessage`-gated workflow stops running for some events | [A `commitMessage` filter never evaluates](https://docs.kici.dev/user/common-failures/#a-commitmessage-filter-never-evaluates) |
711
717
 
712
718
  ## No jobs dispatched
713
719
 
@@ -847,6 +853,24 @@ the unpullable image) — hand this to your operator with the run's failure reas
847
853
  The full provisioning-failure playbook is in
848
854
  [Operator troubleshooting](https://docs.kici.dev/operator/troubleshooting/).
849
855
 
856
+ ## A `commitMessage` filter never evaluates
857
+
858
+ **Symptom.** A workflow gated on a `commitMessage` trigger filter stops running
859
+ for some events, even though the message looks like it should match.
860
+
861
+ **Cause.** The event carries no commit message. A branch-deletion push has no
862
+ head commit, and a self-hosted forge (Gogs, or a GitLab source) may publish none
863
+ at the configured path. The filter is **fail-visible**: when it cannot read a
864
+ message, the workflow does not run rather than running ungated.
865
+
866
+ **Diagnose.** The decision trace records the `commitMessage` check with the
867
+ verdict `indeterminate` and the reason `no commit message in payload`. That is
868
+ distinct from an `excluded` verdict, which the message itself caused.
869
+
870
+ **Fix.** For a self-hosted forge, set the source's `commitMessage` payload path so
871
+ the orchestrator can read the head commit's message. A branch-deletion push
872
+ genuinely carries no message and is expected not to match.
873
+
850
874
  ## When to escalate to your operator
851
875
 
852
876
  The failures above are ones you can resolve from your workflow repo and the
@@ -1140,12 +1164,14 @@ Each workflow entry includes:
1140
1164
  | `concurrency` | Workflow-level concurrency config: `hasGroup`, `cancelInProgress`, `max` (optional). See [concurrency groups](https://docs.kici.dev/user/concurrency/). |
1141
1165
  | `timeout` | Whole-run wall-clock timeout in milliseconds (optional). The orchestrator reads this at run creation to set the run deadline. |
1142
1166
  | `approval` | Normalized approval gate (optional): `clauses`, `reason`, `timeoutSeconds`, `when`. When present the whole run is held before any job is dispatched. Job and step entries carry the same normalized block for job- and step-level gates. See [approval gates](https://docs.kici.dev/user/approvals/). |
1167
+ | `hasFilter` | `true` when the workflow declares a workflow-level `filter` predicate (optional; omitted rather than `false`). The predicate itself is never serialized — the flag tells the orchestrator an agent must evaluate the workflow before any of its jobs is dispatched. See [global workflows](https://docs.kici.dev/user/global-workflows/#narrowing-with-a-filter). |
1143
1168
  | Hook flags | Boolean flags (`hasOnCancel`, `hasCleanup`, `hasOnSuccess`, `hasOnFailure`) indicating which lifecycle hooks are defined. Job entries additionally have `hasBeforeStep` and `hasAfterStep`. |
1144
1169
 
1145
1170
  Step entries carry their own capability flags, so the orchestrator can reason about a step without loading your TypeScript:
1146
1171
 
1147
1172
  | Flag | Meaning |
1148
1173
  | --------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- |
1174
+ | `hasOutputs` | The step declares an output schema, so the run has typed outputs to record for it. Present on every step entry. |
1149
1175
  | `hasCheck` | The step declares an idempotent `check` facet, so a run can be dispatched in check mode. See [idempotent steps and check mode](https://docs.kici.dev/user/idempotent-steps/). |
1150
1176
  | `hasWhenInSync` | The step declares a `whenInSync` facet that produces its outputs when `check` reports no drift. |
1151
1177
  | `hasRules` | The step has conditional rules (evaluated agent-side). |
@@ -1767,7 +1793,7 @@ export const pushMain = fixture('push-main', {
1767
1793
 
1768
1794
  Source: https://docs.kici.dev/user/workflow-patterns/
1769
1795
 
1770
- Practical patterns for building real-world KiCI workflows in TypeScript. The patterns are organised across five pages -- start with [Basic CI](https://docs.kici.dev/user/patterns/basic/) if you're new, or jump to [Integrations](https://docs.kici.dev/user/patterns/integrations/) if you're wiring up a non-GitHub forge or a generic webhook.
1796
+ Practical patterns for building real-world KiCI workflows in TypeScript. The patterns are organised across seven pages -- start with [Basic CI](https://docs.kici.dev/user/patterns/basic/) if you're new, or jump to [Integrations](https://docs.kici.dev/user/patterns/integrations/) if you're wiring up a non-GitHub forge or a generic webhook.
1771
1797
 
1772
1798
  | Page | Covers |
1773
1799
  | ---------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------- |
@@ -1775,6 +1801,8 @@ Practical patterns for building real-world KiCI workflows in TypeScript. The pat
1775
1801
  | [Conditionals & matrix](https://docs.kici.dev/user/patterns/conditionals-matrix/) | Conditional execution with rules, matrix builds (static + dynamic), and dynamic job generation. |
1776
1802
  | [Integrations](https://docs.kici.dev/user/patterns/integrations/) | Workflow chaining, generic webhooks, Stripe handlers, self-hosted git forges (Forgejo / Gitea / Gogs), plain GitHub repo webhooks (no GitHub App). |
1777
1803
  | [Scheduling & events](https://docs.kici.dev/user/patterns/scheduling-and-events/) | Nightly cron, workflow-complete-triggered deploys, custom event chaining. |
1804
+ | [Git credentials](https://docs.kici.dev/user/patterns/git-credentials/) | Declaring named git credentials from the secrets backend, and pushing from a job (including to the job's own repository). |
1805
+ | [Host restart](https://docs.kici.dev/user/patterns/host-restart/) | `restartHost()` and `waitForHostAlive()` -- reboot the host a workflow runs on and resume in a second job pinned to the same host. |
1778
1806
  | [Pattern reference](https://docs.kici.dev/user/patterns/reference/) | Step context, the examples repository, and GitHub check run output -- cross-cutting reference shared by every pattern above. |
1779
1807
 
1780
1808
  ## See also
@@ -2133,7 +2161,6 @@ Synopsis: `kici init [options]`
2133
2161
  | `--private-registry <url>` | | Scaffold a workflow registries: entry pointing at <url> |
2134
2162
  | `--private-registry-scope <scope>` | | Optional npm package scope (e.g. @my-org) for the private registry |
2135
2163
  | `--private-registry-secret <ref>` | `production:NPM_TOKEN` | Qualified secret reference (env:NAME) the private registry token comes from |
2136
- | `--use-verdaccio-local` | `false` | |
2137
2164
 
2138
2165
  ### `kici login`
2139
2166
 
@@ -2408,7 +2435,7 @@ Generate a fixture template for an event type. Useful for creating custom test p
2408
2435
  kici fixture <event> [options]
2409
2436
  ```
2410
2437
 
2411
- **Valid events:** `pr:open`, `pr:sync`, `pr:close`, `pr:reopen`, `push`, `tag`, `comment`, `review`, `review_comment`, `release`, `dispatch`, `create`, `delete`, `status`, `workflow_run`, `fork`, `star`, `watch`, `kici_event`, `workflow_complete`, `job_complete`, `generic_webhook`, `schedule`, `lifecycle` (many support `:action` suffixes, e.g. `comment:edited`, `release:published`, `lifecycle:workflow_complete`). `webhook:<source>` is a shorthand alias for `generic_webhook:<source>`.
2438
+ **Valid events:** `pr:open`, `pr:sync`, `pr:close`, `pr:reopen`, `push`, `tag`, `comment`, `review`, `review_comment`, `release`, `dispatch`, `create`, `delete`, `status`, `workflow_run`, `fork`, `star`, `watch`, `kici_event`, `workflow_complete`, `workflows_failed_batch`, `job_complete`, `generic_webhook`, `schedule`, `lifecycle` (many support `:action` suffixes, e.g. `comment:edited`, `release:published`, `lifecycle:workflow_complete`). `webhook:<source>` is a shorthand alias for `generic_webhook:<source>`.
2412
2439
 
2413
2440
  **Examples:**
2414
2441
 
@@ -2438,7 +2465,7 @@ Generate TypeScript declaration files from orchestrator environment metadata. Th
2438
2465
  kici types [options]
2439
2466
  ```
2440
2467
 
2441
- **Prerequisites:** Must be authenticated via `kici login`.
2468
+ **Prerequisites:** Authenticate via `kici login` to fetch the real key set. Without it, `kici types` writes an empty stub (see "Offline behavior" below).
2442
2469
 
2443
2470
  **Output:** `.kici/types/secrets.d.ts`
2444
2471
 
@@ -2460,7 +2487,9 @@ kici types --kici-dir packages/app/.kici
2460
2487
 
2461
2488
  After generating types, `ctx.secrets.get('MY_KEY')` and `ctx.secrets.expose('DB_HOST')` gain autocomplete and type checking in your IDE.
2462
2489
 
2463
- **Git workflow:** Commit the generated `.kici/types/secrets.d.ts` so team members get type checking without needing orchestrator access. Run `kici types` to refresh when environments change.
2490
+ **Git workflow:** `.kici/types/secrets.d.ts` is a local development aid, not source its content is a snapshot of one org's secret keys fetched from the Platform. `kici init` gitignores `.kici/types/`, so the file stays out of version control. Each team member runs `kici types` (or an authenticated `kici compile`) to generate their own copy. Do not commit it: a stale committed copy would type-check against secret keys that no longer exist.
2491
+
2492
+ **Offline behavior:** When the Platform cannot be reached — not logged in, no active org, or offline — `kici types` never fails. If a `secrets.d.ts` already exists, `kici types` keeps it untouched, so a transient outage does not wipe your real key set. If the file is absent (a fresh clone or unauthenticated CI), `kici types` writes a valid empty stub. Type checking then degrades to "no known keys" (any key name is accepted) rather than breaking with "module has no exported member". Run `kici types` again once authenticated to refresh it.
2464
2493
 
2465
2494
  **Auto-regeneration:** `kici compile` automatically runs `kici types` after successful compilation when authenticated. See the [kici compile](https://docs.kici.dev/user/cli/authoring-and-local/#kici-compile) section for details.
2466
2495
 
@@ -2545,7 +2574,7 @@ kici docs llm sdk | claude -- "Read this and help me author a deploy workflow"
2545
2574
  kici docs llm --out kici-llms-index.txt
2546
2575
  ```
2547
2576
 
2548
- Bundles are regenerated from `docs/` every time `@kici-dev/compiler` is built, so they always match your installed CLI version. The index lists each task bundle — `getting-started`, `sdk`, `sdk-runtime`, `cli`, `patterns`, `features`, `providers`, `architecture` — with its size and a one-line purpose; pass the bundle id as the topic. Every cross-reference link inside a bundle is an absolute `docs.kici.dev` URL. The same files are published online following the [llms.txt convention](https://llmstxt.org/).
2577
+ Bundles are regenerated from `docs/` every time `@kici-dev/compiler` is built, so they always match your installed CLI version. The index lists each task bundle — `getting-started`, `sdk`, `sdk-runtime`, `cli`, `patterns`, `features`, `features-execution`, `providers`, `architecture` — with its size and a one-line purpose; pass the bundle id as the topic. Every cross-reference link inside a bundle is an absolute `docs.kici.dev` URL. The same files are published online following the [llms.txt convention](https://llmstxt.org/).
2549
2578
 
2550
2579
  ## Reference
2551
2580
 
@@ -2943,9 +2972,9 @@ kici diagnostics --json
2943
2972
  Walk your KiCI setup end to end and print the exact next command for each
2944
2973
  problem found. Where `kici diagnostics` shows the org's infrastructure, `kici
2945
2974
  doctor` checks **your own setup**: it runs six checks in onboarding order —
2946
- login (stored, unexpired credentials), active organization, a live token probe
2947
- against the platform, a connected orchestrator for the org, a present, fresh,
2948
- and committed lock file, and whether every workflow's `runsOn` labels are
2975
+ login (stored, unexpired credentials), active organization, a present, fresh,
2976
+ and committed lock file, a live token probe against the platform, a connected
2977
+ orchestrator for the org, and whether every workflow's `runsOn` labels are
2949
2978
  satisfiable by a connected agent or scaler. Each check reports pass/warn/fail
2950
2979
  with the fix command (e.g. `kici login`, `kici org use <name>`,
2951
2980
  `kici compile`), so the first failing row tells you exactly what to run next.
@@ -2967,6 +2996,60 @@ kici doctor --json
2967
2996
  The command exits `0` when every check passes, `1` when any check warns, and
2968
2997
  `2` when any check fails, so it also works as a CI preflight.
2969
2998
 
2999
+ ### kici report
3000
+
3001
+ Gather a diagnostic bundle to share when you report a problem. `kici doctor`
3002
+ tells you what is wrong; `kici report` packages the context somebody else needs
3003
+ to see it. The bundle holds your CLI, Node and orchestrator versions, your
3004
+ redacted configuration, and your project's workflow and lock-file state. With
3005
+ `--run` it also holds the failing run's detail and logs.
3006
+
3007
+ ```bash
3008
+ kici report [options]
3009
+ ```
3010
+
3011
+ The command writes a ZIP and prints its path and `sha256`. It does not send
3012
+ anything. Open the file and read it before you share it.
3013
+
3014
+ ```bash
3015
+ # Bundle your setup
3016
+ kici report
3017
+
3018
+ # Scope it to the run that failed, and say what went wrong
3019
+ kici report --run 8f3c1d2e --message "matrix job hangs on macOS"
3020
+
3021
+ # Choose the output path and attach your own metadata
3022
+ kici report -o /tmp/bug.zip --metadata ticket=1234 --metadata severity=high
3023
+ ```
3024
+
3025
+ **Redaction.** KiCI removes known secret shapes — API keys, tokens, `Authorization`
3026
+ headers, private keys, passwords in connection URLs — from configuration and
3027
+ from log text. This is best effort. A secret in a format KiCI does not
3028
+ recognize can survive, so review the bundle before you share it. `--no-redact`
3029
+ turns redaction off and prints a warning; use it only on a bundle you keep.
3030
+
3031
+ **Sending it privately.** Add `--upload` to send the bundle to KiCI over a
3032
+ one-time upload link. The bundle goes straight to KiCI storage, and the command
3033
+ prints a reference id to quote:
3034
+
3035
+ ```bash
3036
+ kici report --run 8f3c1d2e --upload --message "matrix job hangs on macOS"
3037
+ ```
3038
+
3039
+ Uploads are private, are kept for 90 days, and are yours to withdraw:
3040
+
3041
+ ```bash
3042
+ # See what you have sent
3043
+ kici report list
3044
+
3045
+ # Delete an uploaded bundle
3046
+ kici report withdraw <ref>
3047
+ ```
3048
+
3049
+ Anyone in your organization can upload a report. By default you see and
3050
+ withdraw your own; a member with the `support:admin` permission can manage
3051
+ every report in the organization.
3052
+
2970
3053
  ## Reference
2971
3054
 
2972
3055
  <!-- BEGIN GENERATED: kici-notifications-and-diagnostics (do not edit; run the doc generator) -->
@@ -3174,6 +3257,49 @@ Synopsis: `kici notifications subscriptions remove <id> [options]`
3174
3257
  | ------------ | ------- | ---------------------------------------------- |
3175
3258
  | `--org <id>` | | Target organization (overrides the active org) |
3176
3259
 
3260
+ ### `kici report`
3261
+
3262
+ Gather a redacted diagnostic bundle to share when reporting an issue
3263
+
3264
+ Synopsis: `kici report [options]`
3265
+
3266
+ **Options**
3267
+
3268
+ | Option | Default | Description |
3269
+ | ------------------------ | ------- | ------------------------------------------------------------ |
3270
+ | `--run <id>` | | Scope the bundle to a failing run |
3271
+ | `-o, --output <path>` | | Where to write the bundle ZIP |
3272
+ | `--metadata <key=value>` | | Attach metadata (repeatable) |
3273
+ | `--no-redact` | | Do NOT redact secrets (prints a loud warning) |
3274
+ | `--upload` | | Upload the bundle privately to KiCI and print a reference id |
3275
+ | `--message <text>` | | Describe the problem (sent with --upload) |
3276
+ | `--email <address>` | | Contact address for follow-up (sent with --upload) |
3277
+ | `--kici-dir <path>` | `.kici` | Path to the .kici directory |
3278
+
3279
+ ### `kici report list`
3280
+
3281
+ List the issue reports you have uploaded
3282
+
3283
+ Synopsis: `kici report list [options]`
3284
+
3285
+ **Options**
3286
+
3287
+ | Option | Default | Description |
3288
+ | -------- | ------- | --------------- |
3289
+ | `--json` | `false` | Output raw JSON |
3290
+
3291
+ ### `kici report withdraw`
3292
+
3293
+ Withdraw an uploaded report and delete its bundle
3294
+
3295
+ Synopsis: `kici report withdraw <ref>`
3296
+
3297
+ **Arguments**
3298
+
3299
+ | Argument | Required | Variadic | Description |
3300
+ | -------- | -------- | -------- | -------------------------------------- |
3301
+ | `ref` | yes | no | Reference id of the report to withdraw |
3302
+
3177
3303
  ### `kici verify-attestation`
3178
3304
 
3179
3305
  Verify a KiCI provenance attestation bundle offline
@@ -3489,7 +3615,11 @@ kici runs list --json | jq '.runs[].runId'
3489
3615
  #### kici runs show
3490
3616
 
3491
3617
  Show a run's summary header plus its jobs-and-steps tree (name, status,
3492
- duration, exit code). If the run id is not on the Platform but exists in your
3618
+ duration, exit code). A run that never started a step also prints why: the
3619
+ run-level failure, and per job the reason it did not run — a job a
3620
+ [context](https://docs.kici.dev/user/contexts/#protection-rules) rejected names the context and the
3621
+ rule. Any approval hold on the run is listed too, with its context, hold type,
3622
+ status and reason. If the run id is not on the Platform but exists in your
3493
3623
  local run history (from `kici run <event> --local`), the local record is shown instead.
3494
3624
 
3495
3625
  ```bash
@@ -3670,10 +3800,12 @@ Synopsis: `kici approve <run-id> [options]`
3670
3800
 
3671
3801
  **Options**
3672
3802
 
3673
- | Option | Default | Description |
3674
- | ---------------- | ------- | ------------------------------------------- |
3675
- | `--job <name>` | | Approve the hold for a specific job |
3676
- | `--step <index>` | | Approve a step-scoped hold (requires --job) |
3803
+ | Option | Default | Description |
3804
+ | -------------------- | ------- | -------------------------------------------------------------------------------------------- |
3805
+ | `--job <name>` | | Approve the hold for a specific job |
3806
+ | `--step <index>` | | Approve a step-scoped hold (requires --job) |
3807
+ | `--hold-type <type>` | | Approve the hold of this type (reviewer, timer, concurrency, security) — a job can carry two |
3808
+ | `--hold <id>` | | Approve one hold by its id, as listed when nothing else separates them |
3677
3809
 
3678
3810
  ### `kici reject`
3679
3811
 
@@ -3689,11 +3821,13 @@ Synopsis: `kici reject <run-id> [options]`
3689
3821
 
3690
3822
  **Options**
3691
3823
 
3692
- | Option | Default | Description |
3693
- | ----------------- | ------- | ------------------------------------------ |
3694
- | `--job <name>` | | Reject the hold for a specific job |
3695
- | `--step <index>` | | Reject a step-scoped hold (requires --job) |
3696
- | `--reason <text>` | | Reason for the rejection |
3824
+ | Option | Default | Description |
3825
+ | -------------------- | ------- | ------------------------------------------------------------------------------------------- |
3826
+ | `--job <name>` | | Reject the hold for a specific job |
3827
+ | `--step <index>` | | Reject a step-scoped hold (requires --job) |
3828
+ | `--hold-type <type>` | | Reject the hold of this type (reviewer, timer, concurrency, security) — a job can carry two |
3829
+ | `--hold <id>` | | Reject one hold by its id, as listed when nothing else separates them |
3830
+ | `--reason <text>` | | Reason for the rejection |
3697
3831
 
3698
3832
  ### `kici run`
3699
3833
 
@@ -3891,7 +4025,7 @@ Synopsis: `kici runs rerun <run-id> [options]`
3891
4025
 
3892
4026
  ### `kici runs show`
3893
4027
 
3894
- Show a run summary with its jobs and steps
4028
+ Show a run summary with its jobs and steps, why a job did not run, and any approval hold
3895
4029
 
3896
4030
  Synopsis: `kici runs show <run-id> [options]`
3897
4031