@kici-dev/compiler 0.1.16 → 0.1.18

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 (138) hide show
  1. package/dist/auth/headless-detect.js +1 -1
  2. package/dist/cli-banner.js +1 -1
  3. package/dist/cli.js +56 -19
  4. package/dist/commands/approve.js +1 -1
  5. package/dist/commands/compile.js +19 -17
  6. package/dist/commands/diagnostics.d.ts +7 -0
  7. package/dist/commands/diagnostics.js +58 -0
  8. package/dist/commands/docs.js +1 -1
  9. package/dist/commands/drain-worker.js +1 -1
  10. package/dist/commands/endpoints.js +1 -1
  11. package/dist/commands/fixture.js +1 -1
  12. package/dist/commands/held-run-client.js +1 -1
  13. package/dist/commands/held-run-resolve.js +1 -1
  14. package/dist/commands/hook.js +1 -1
  15. package/dist/commands/index.d.ts +16 -4
  16. package/dist/commands/index.js +10 -4
  17. package/dist/commands/init.js +2 -2
  18. package/dist/commands/login.d.ts +0 -2
  19. package/dist/commands/login.js +1 -3
  20. package/dist/commands/logout.js +1 -1
  21. package/dist/commands/orchestrators.d.ts +25 -0
  22. package/dist/commands/orchestrators.js +115 -0
  23. package/dist/commands/org.js +1 -1
  24. package/dist/commands/reject.js +1 -1
  25. package/dist/commands/run.d.ts +2 -9
  26. package/dist/commands/run.js +256 -315
  27. package/dist/commands/runs/cancel.d.ts +6 -0
  28. package/dist/commands/runs/cancel.js +32 -0
  29. package/dist/commands/runs/list.d.ts +6 -0
  30. package/dist/commands/runs/list.js +49 -0
  31. package/dist/commands/runs/logs.d.ts +7 -0
  32. package/dist/commands/runs/logs.js +67 -0
  33. package/dist/commands/runs/rerun.d.ts +5 -0
  34. package/dist/commands/runs/rerun.js +21 -0
  35. package/dist/commands/runs/show.d.ts +5 -0
  36. package/dist/commands/runs/show.js +65 -0
  37. package/dist/commands/secrets-list.d.ts +7 -9
  38. package/dist/commands/secrets-list.js +40 -64
  39. package/dist/commands/test.d.ts +4 -0
  40. package/dist/commands/test.js +4 -6
  41. package/dist/commands/types.d.ts +3 -5
  42. package/dist/commands/types.js +13 -37
  43. package/dist/commands/verify-attestation.d.ts +12 -0
  44. package/dist/commands/verify-attestation.js +69 -0
  45. package/dist/commands/watch.js +1 -1
  46. package/dist/commands/workflows.js +14 -34
  47. package/dist/errors/capability-gap.js +1 -1
  48. package/dist/errors/formatter.js +1 -1
  49. package/dist/errors/index.js +1 -1
  50. package/dist/execution/executor.js +1 -1
  51. package/dist/execution/index.js +1 -1
  52. package/dist/execution/sdk-alias.js +1 -1
  53. package/dist/execution/ts-loader.js +1 -1
  54. package/dist/fixtures/compiler.js +1 -1
  55. package/dist/fixtures/defaults/index.js +1 -1
  56. package/dist/format.js +1 -1
  57. package/dist/generators/secrets-dts.js +2 -2
  58. package/dist/hooks/detector.js +1 -1
  59. package/dist/hooks/index.js +1 -1
  60. package/dist/hooks/installer.js +1 -1
  61. package/dist/hooks/templates.js +1 -1
  62. package/dist/index.js +1 -1
  63. package/dist/llm-context/llms-full.txt +1549 -1282
  64. package/dist/llm-context/llms.txt +6 -2
  65. package/dist/local-executor/dag-scheduler.js +1 -1
  66. package/dist/local-executor/index.js +1 -1
  67. package/dist/local-executor/job-runner.js +40 -18
  68. package/dist/local-executor/materializer.js +1 -1
  69. package/dist/local-executor/output-streamer.js +1 -1
  70. package/dist/local-executor/payload-generator.js +1 -1
  71. package/dist/local-executor/picker.js +1 -1
  72. package/dist/local-executor/runs-on-display.d.ts +9 -0
  73. package/dist/local-executor/runs-on-display.js +23 -0
  74. package/dist/local-executor/secret-loader.js +1 -1
  75. package/dist/local-executor/to-event-payload.js +1 -1
  76. package/dist/local-executor/types.js +1 -1
  77. package/dist/local-executor/workflow-lock.js +0 -0
  78. package/dist/lockfile/generator.d.ts +9 -5
  79. package/dist/lockfile/generator.js +58 -38
  80. package/dist/lockfile/hash-files.js +1 -1
  81. package/dist/lockfile/hasher.js +1 -1
  82. package/dist/lockfile/index.js +1 -1
  83. package/dist/lockfile/purity-analyzer.js +1 -1
  84. package/dist/postinstall.js +1 -1
  85. package/dist/provenance-trust-root.d.ts +14 -0
  86. package/dist/provenance-trust-root.js +49 -0
  87. package/dist/remote/config.d.ts +6 -2
  88. package/dist/remote/config.js +7 -4
  89. package/dist/remote/dashboard-client.d.ts +92 -0
  90. package/dist/remote/dashboard-client.js +168 -0
  91. package/dist/remote/encryption.js +3 -4
  92. package/dist/remote/history.js +1 -1
  93. package/dist/remote/oauth.js +1 -1
  94. package/dist/remote/oidc-discovery.js +1 -1
  95. package/dist/remote/output/json.js +1 -1
  96. package/dist/remote/output/junit.js +1 -1
  97. package/dist/remote/output/streaming.js +1 -1
  98. package/dist/remote/output/summary.js +1 -1
  99. package/dist/remote/platform-client.d.ts +142 -0
  100. package/dist/remote/platform-client.js +187 -0
  101. package/dist/remote/prod-defaults.js +1 -1
  102. package/dist/remote/render.d.ts +11 -0
  103. package/dist/remote/render.js +48 -0
  104. package/dist/remote/secret-upload.js +1 -1
  105. package/dist/remote/uploader.d.ts +9 -0
  106. package/dist/remote/uploader.js +51 -4
  107. package/dist/templates/agents-md.d.ts +1 -1
  108. package/dist/templates/agents-md.js +8 -3
  109. package/dist/templates/index.js +1 -1
  110. package/dist/templates/package-json.js +4 -5
  111. package/dist/templates/tsconfig-json.js +1 -1
  112. package/dist/templates/workflows/hello-world.js +2 -2
  113. package/dist/templates/workflows/hello-world.ts +1 -1
  114. package/dist/templates/workflows/pr-checks.js +3 -3
  115. package/dist/templates/workflows/pr-checks.ts +2 -2
  116. package/dist/test-runner/dry-run.js +1 -1
  117. package/dist/test-runner/event-types.js +1 -1
  118. package/dist/test-runner/git-detector.js +1 -1
  119. package/dist/test-runner/index.js +1 -1
  120. package/dist/test-runner/job-executor.js +3 -2
  121. package/dist/test-runner/output-formatter.js +1 -1
  122. package/dist/test-runner/payload-builder.js +1 -1
  123. package/dist/test-runner/rule-evaluator.js +1 -1
  124. package/dist/test-runner/secrets-file.js +1 -1
  125. package/dist/test-runner/step-context.js +10 -6
  126. package/dist/types.d.ts +29 -8
  127. package/dist/types.js +2 -1
  128. package/dist/validation/index.js +1 -1
  129. package/dist/validation/validator.js +1 -1
  130. package/dist/workflows/hello-world.ts +1 -1
  131. package/dist/workflows/pr-checks.ts +2 -2
  132. package/package.json +10 -9
  133. package/sbom.spdx.json +465 -410
  134. package/dist/commands/cancel.js +0 -124
  135. package/dist/commands/status.js +0 -212
  136. package/dist/remote/client.js +0 -203
  137. package/dist/remote/observer.js +0 -174
  138. /package/dist/{chunk-gOLHoazu.js → chunk-BTugEXQM.js} +0 -0
@@ -1,4 +1,4 @@
1
- import "../chunk-gOLHoazu.js";
1
+ import "../chunk-BTugEXQM.js";
2
2
  //#region src/auth/headless-detect.ts
3
3
  /**
4
4
  * Detect if the current environment is headless (no browser available).
@@ -1,4 +1,4 @@
1
- import "./chunk-gOLHoazu.js";
1
+ import "./chunk-BTugEXQM.js";
2
2
  //#region src/cli-banner.ts
3
3
  /**
4
4
  * Whether the version banner should be suppressed for the command about to run.
package/dist/cli.js CHANGED
@@ -1,12 +1,12 @@
1
1
  #!/usr/bin/env node
2
- import "./chunk-gOLHoazu.js";
2
+ import "./chunk-BTugEXQM.js";
3
3
  import { shouldSuppressBanner } from "./cli-banner.js";
4
4
  import { fileURLToPath } from "node:url";
5
5
  import { resolve } from "node:path";
6
6
  import { Argument, Command, Option } from "commander";
7
7
  import pc from "picocolors";
8
8
  //#region src/cli.ts
9
- const version = "0.1.16";
9
+ const version = "0.1.18";
10
10
  /**
11
11
  * Build the kici Commander program with every command registered. Exported so
12
12
  * the surface registry can walk the real command tree without parsing argv (no
@@ -76,7 +76,7 @@ function buildProgram() {
76
76
  });
77
77
  process.exit(success ? 0 : 1);
78
78
  });
79
- runCommand.command("remote").argument("[fixture]", "Fixture name or glob pattern (omit to list available)").description("Execute fixtures remotely via orchestrator").option("--workflow <name>", "Run a specific workflow directly (bypass triggers)").option("--all", "Run all available fixtures", false).option("--parallel", "Run matching fixtures concurrently", false).option("--no-wait", "Fire and forget (print runIds, don't stream)").option("--quiet", "Suppress output except final result", false).option("--json", "Output structured JSON result", false).option("--junit <path>", "Output JUnit XML result").option("--history", "Show recent run history", false).option("--routing-key <key>", "Override routing key for this run").option("--debug", "Verbose internals", false).option("--kici-dir <path>", "Path to .kici directory", ".kici").option("--context <ctx.key=value>", "Inject a namespaced context secret, uploaded encrypted to the orchestrator (repeatable)", (val, prev) => [...prev, val], []).option("--env <KEY=VALUE>", "Provide a per-run secret (repeatable); uploaded encrypted to the orchestrator", (val, prev) => [...prev, val], []).action(async (fixture, options) => {
79
+ runCommand.command("remote").argument("[fixture]", "Fixture name or glob pattern (omit to list available)").description("Execute fixtures remotely via orchestrator").option("--workflow <name>", "Run a specific workflow directly (bypass triggers)").option("--all", "Run all available fixtures", false).option("--parallel", "Run matching fixtures concurrently", false).option("--no-wait", "Fire and forget (print runIds, don't stream)").option("--quiet", "Suppress output except final result", false).option("--json", "Output structured JSON result", false).option("--junit <path>", "Output JUnit XML result").option("--history", "Show recent run history", false).option("--routing-key <key>", "Override routing key for this run").option("--org <id>", "Target organization (overrides the active org)").option("--orchestrator <name>", "Target orchestrator cluster (overrides the per-org default)").option("--debug", "Verbose internals", false).option("--kici-dir <path>", "Path to .kici directory", ".kici").option("--context <ctx.key=value>", "Inject a namespaced context secret, uploaded encrypted to the orchestrator (repeatable)", (val, prev) => [...prev, val], []).option("--env <KEY=VALUE>", "Provide a per-run secret (repeatable); uploaded encrypted to the orchestrator", (val, prev) => [...prev, val], []).action(async (fixture, options) => {
80
80
  const { runRemoteCommand } = await import("./commands/index.js");
81
81
  const success = await runRemoteCommand(fixture, {
82
82
  ...options,
@@ -102,7 +102,7 @@ function buildProgram() {
102
102
  const success = await hookInstallCommand({ git: options.git });
103
103
  process.exit(success ? 0 : 1);
104
104
  });
105
- program.command("login").description("Authenticate with KiCI via browser OAuth (default) or API key (--token)").option("--token <key>", "API key for direct authentication (legacy)").option("--device", "Force device authorization flow (for headless/SSH environments)").option("--endpoint <url>", "Orchestrator URL for direct connection").option("--platform-endpoint <url>", "Platform relay URL").option("--routing-key <key>", "Routing key for webhook source identification").addHelpText("after", `
105
+ program.command("login").description("Authenticate with KiCI via browser OAuth (default) or API key (--token)").option("--token <key>", "API key for direct authentication (legacy)").option("--device", "Force device authorization flow (for headless/SSH environments)").option("--platform-endpoint <url>", "Platform relay URL").option("--routing-key <key>", "Routing key for webhook source identification").addHelpText("after", `
106
106
  Environment variables:
107
107
  KICI_BROWSER_CMD Custom browser command (use {url} placeholder, or 'none' to suppress)
108
108
  KICI_CALLBACK_PORT Fixed port for OAuth PKCE callback server (default: random)
@@ -114,7 +114,6 @@ Environment variables:
114
114
  const success = await loginCommand({
115
115
  token: options.token,
116
116
  device: options.device,
117
- endpoint: options.endpoint,
118
117
  platformEndpoint: options.platformEndpoint,
119
118
  routingKey: options.routingKey
120
119
  });
@@ -141,23 +140,50 @@ Environment variables:
141
140
  const success = await orgCurrentCommand();
142
141
  process.exit(success ? 0 : 1);
143
142
  });
144
- program.command("secrets").description("Manage secrets").command("list").description("List test-available secret contexts").option("--endpoint <url>", "Orchestrator URL override").action(async (options) => {
143
+ const orchestratorsCommand = program.command("orchestrators").description("Inspect the org's orchestrator clusters and pick a default for run remote");
144
+ orchestratorsCommand.command("list").description("List the connected orchestrator clusters for the active org").option("--org <id>", "Target organization (overrides the active org)").action(async (options) => {
145
+ const { orchestratorsListCommand } = await import("./commands/index.js");
146
+ const success = await orchestratorsListCommand({ org: options.org });
147
+ process.exit(success ? 0 : 1);
148
+ });
149
+ orchestratorsCommand.command("use").argument("<name>", "Orchestrator cluster name").description("Set the per-org default orchestrator cluster for run remote").option("--org <id>", "Target organization (overrides the active org)").action(async (name, options) => {
150
+ const { orchestratorsUseCommand } = await import("./commands/index.js");
151
+ const success = await orchestratorsUseCommand(name, { org: options.org });
152
+ process.exit(success ? 0 : 1);
153
+ });
154
+ program.command("secrets").description("Manage secrets").command("list").description("List test-available secret contexts").action(async () => {
145
155
  const { secretsListCommand } = await import("./commands/index.js");
146
- const success = await secretsListCommand({ endpoint: options.endpoint });
156
+ const success = await secretsListCommand();
147
157
  process.exit(success ? 0 : 1);
148
158
  });
149
- program.command("status").argument("<run-id>", "Run ID to inspect").description("Show status and details of a test run").option("--logs", "Stream full log replay", false).option("--job <name>", "Filter logs to specific job").option("--json", "Output raw JSON", false).action(async (runId, options) => {
150
- const { statusCommand } = await import("./commands/index.js");
151
- const success = await statusCommand(runId, {
152
- logs: options.logs,
159
+ const runsCommand = program.command("runs").description("Inspect and manage execution runs");
160
+ runsCommand.command("list").description("List execution runs (mirrors the dashboard Runs page)").option("--status <s>", "Filter by status").option("--workflow <w>", "Filter by workflow name").option("--branch <b>", "Filter by branch/ref").option("--repo <r>", "Filter by repository").option("--trigger <t>", "Filter by trigger type").option("--source <routingKey>", "Filter by source routing key").option("--since <ts>", "Only runs since (ISO-8601 or epoch ms)").option("--page <n>", "Page number", (v) => parseInt(v, 10)).option("--json", "Output raw JSON", false).action(async (options) => {
161
+ const { runsListCommand } = await import("./commands/index.js");
162
+ const success = await runsListCommand(options);
163
+ process.exit(success ? 0 : 1);
164
+ });
165
+ runsCommand.command("show").argument("<run-id>", "Run ID to inspect").description("Show a run summary with its jobs and steps").option("--json", "Output raw JSON", false).action(async (runId, options) => {
166
+ const { runsShowCommand } = await import("./commands/index.js");
167
+ const success = await runsShowCommand(runId, { json: options.json });
168
+ process.exit(success ? 0 : 1);
169
+ });
170
+ runsCommand.command("logs").argument("<run-id>", "Run ID").description("Print step logs for a run").option("--job <name>", "Only logs for this job").option("-f, --follow", "Tail logs for a live run", false).option("--json", "Output raw JSON", false).action(async (runId, options) => {
171
+ const { runsLogsCommand } = await import("./commands/index.js");
172
+ const success = await runsLogsCommand(runId, {
153
173
  job: options.job,
174
+ follow: options.follow,
154
175
  json: options.json
155
176
  });
156
177
  process.exit(success ? 0 : 1);
157
178
  });
158
- program.command("cancel").argument("[run-id]", "Run ID to cancel").description("Cancel a running workflow or all runs on a branch").option("--force", "Force cancel (kill immediately, skip hooks)", false).option("--branch <name>", "Cancel all in-progress runs on this branch").action(async (runId, options) => {
159
- const { cancelCommand } = await import("./commands/index.js");
160
- const success = await cancelCommand(runId, {
179
+ runsCommand.command("rerun").argument("<run-id>", "Run ID to rerun").description("Re-trigger a run").option("--json", "Output raw JSON", false).action(async (runId, options) => {
180
+ const { runsRerunCommand } = await import("./commands/index.js");
181
+ const success = await runsRerunCommand(runId, { json: options.json });
182
+ process.exit(success ? 0 : 1);
183
+ });
184
+ runsCommand.command("cancel").argument("[run-id]", "Run ID to cancel").description("Cancel a run, or all in-progress runs on a branch").option("--force", "Force cancel (kill immediately, skip hooks)", false).option("--branch <name>", "Cancel all in-progress runs on this branch").action(async (runId, options) => {
185
+ const { runsCancelCommand } = await import("./commands/index.js");
186
+ const success = await runsCancelCommand(runId, {
161
187
  force: options.force,
162
188
  branch: options.branch
163
189
  });
@@ -180,12 +206,9 @@ Environment variables:
180
206
  });
181
207
  process.exit(success ? 0 : 1);
182
208
  });
183
- program.command("types").description("Generate TypeScript declarations for secret contexts").option("--kici-dir <path>", "Path to .kici directory", ".kici").option("--endpoint <url>", "Orchestrator URL override").action(async (options) => {
209
+ program.command("types").description("Generate TypeScript declarations for secret contexts").option("--kici-dir <path>", "Path to .kici directory", ".kici").action(async (options) => {
184
210
  const { typesCommand } = await import("./commands/index.js");
185
- const success = await typesCommand({
186
- kiciDir: options.kiciDir,
187
- endpoint: options.endpoint
188
- });
211
+ const success = await typesCommand({ kiciDir: options.kiciDir });
189
212
  process.exit(success ? 0 : 1);
190
213
  });
191
214
  program.command("endpoints").description("List all webhook entrypoints for the current project").option("--kici-dir <path>", "Path to .kici directory", ".kici").action(async (options) => {
@@ -193,6 +216,15 @@ Environment variables:
193
216
  const success = await endpointsCommand({ kiciDir: options.kiciDir });
194
217
  process.exit(success ? 0 : 1);
195
218
  });
219
+ program.command("diagnostics").description("Show orchestrators, scalers, and agents (mirrors the dashboard Diagnostics page)").option("--json", "Output raw JSON", false).option("--verbose", "Show extended per-agent fields", false).option("--orchestrator <id>", "Scope the tree to one connection id").action(async (options) => {
220
+ const { diagnosticsCommand } = await import("./commands/index.js");
221
+ const success = await diagnosticsCommand({
222
+ json: options.json,
223
+ verbose: options.verbose,
224
+ orchestrator: options.orchestrator
225
+ });
226
+ process.exit(success ? 0 : 1);
227
+ });
196
228
  program.command("workflows").description("Manage workflow registrations").command("list").description("List permanently registered workflows").option("--json", "Output as JSON", false).option("--stale <duration>", "Filter stale registrations (e.g., 30d, 7d)").option("--trigger-type <type>", "Filter by trigger type").option("--repo <repo>", "Filter by repository").action(async (options) => {
197
229
  const { workflowsListCommand } = await import("./commands/index.js");
198
230
  const success = await workflowsListCommand({
@@ -220,6 +252,11 @@ Environment variables:
220
252
  const success = await drainWorkerCommand({ url: options.url });
221
253
  process.exit(success ? 0 : 1);
222
254
  });
255
+ program.command("verify-attestation").argument("[artifact]", "Artifact path to digest-check against the attestation subject (optional)").description("Verify a KiCI provenance attestation bundle offline").option("--bundle <path>", "Path or URL to the attestation bundle JSON").option("--trust-root <url-or-file>", "Trusted issuer URL, or a self-contained { issuer, jwks } file").option("--audience <aud>", "Expected token audience").option("--json", "Output structured JSON result", false).action(async (artifact, options) => {
256
+ const { verifyAttestationCommand } = await import("./commands/index.js");
257
+ const success = await verifyAttestationCommand(artifact, options);
258
+ process.exit(success ? 0 : 1);
259
+ });
223
260
  return program;
224
261
  }
225
262
  /** Build the program and parse argv — the bin-shim entry point. */
@@ -1,4 +1,4 @@
1
- import "../chunk-gOLHoazu.js";
1
+ import "../chunk-BTugEXQM.js";
2
2
  import { listHeldRunsForRun, postApprove, resolveHeldRunContext } from "./held-run-client.js";
3
3
  import { resolveHeldRunId } from "./held-run-resolve.js";
4
4
  import pc from "picocolors";
@@ -1,4 +1,4 @@
1
- import "../chunk-gOLHoazu.js";
1
+ import "../chunk-BTugEXQM.js";
2
2
  import { formatError, isCompilerError } from "../errors/formatter.js";
3
3
  import "../errors/index.js";
4
4
  import { discoverWorkflows, resolveKiciDir } from "../execution/executor.js";
@@ -12,6 +12,7 @@ import pc from "picocolors";
12
12
  import { existsSync } from "node:fs";
13
13
  import fs from "node:fs/promises";
14
14
  import { logger, toErrorMessage } from "@kici-dev/core";
15
+ import { PackageManager, detectPackageManagerSync } from "@kici-dev/core/package-manager";
15
16
  import { execSync } from "node:child_process";
16
17
  //#region src/commands/compile.ts
17
18
  /**
@@ -26,22 +27,21 @@ async function readExistingLockfileHash(lockPath) {
26
27
  }
27
28
  }
28
29
  /**
29
- * Reinstall dependencies in .kici/ using npm.
30
+ * Reinstall dependencies in .kici/ using the project's package manager.
31
+ *
32
+ * Detects the manager from `.kici/` (pnpm-lock.yaml / yarn.lock /
33
+ * package-lock.json) so a standalone-pnpm or -yarn `.kici` is reinstalled with
34
+ * the right tool — running `npm ci` against a pnpm lock fails, and against a
35
+ * stale npm lock left beside a pnpm lock it fails even harder.
30
36
  */
31
37
  async function reinstallDeps(kiciDir) {
32
- if (existsSync(path.join(kiciDir, "package-lock.json"))) {
33
- logger.info("Running " + pc.cyan("npm ci") + ` in ${kiciDir}`);
34
- execSync("npm ci", {
35
- cwd: kiciDir,
36
- stdio: "inherit"
37
- });
38
- } else {
39
- logger.info("Running " + pc.cyan("npm install") + ` in ${kiciDir}`);
40
- execSync("npm install", {
41
- cwd: kiciDir,
42
- stdio: "inherit"
43
- });
44
- }
38
+ const pm = detectPackageManagerSync(kiciDir);
39
+ const command = pm === PackageManager.Pnpm ? "pnpm install" : pm === PackageManager.Yarn ? "yarn install" : existsSync(path.join(kiciDir, "package-lock.json")) ? "npm ci" : "npm install";
40
+ logger.info("Running " + pc.cyan(command) + ` in ${kiciDir}`);
41
+ execSync(command, {
42
+ cwd: kiciDir,
43
+ stdio: "inherit"
44
+ });
45
45
  }
46
46
  /**
47
47
  * Execute the compile command.
@@ -80,12 +80,14 @@ async function compileCommand(options) {
80
80
  try {
81
81
  const { loadGlobalConfig } = await import("../remote/config.js");
82
82
  const config = await loadGlobalConfig();
83
- if (config.token && config.endpoint) {
83
+ const hasToken = Boolean(config.pat ?? config.token);
84
+ const hasEndpoint = Boolean(config.platformEndpoint ?? config.endpoint);
85
+ if (hasToken && hasEndpoint && config.activeOrgId) {
84
86
  const { typesCommand } = await import("./types.js");
85
87
  await typesCommand({ kiciDir });
86
88
  }
87
89
  } catch {
88
- logger.warn(pc.yellow("Could not refresh types (orchestrator unreachable). Compilation succeeded."));
90
+ logger.warn(pc.yellow("Could not refresh types (Platform unreachable). Compilation succeeded."));
89
91
  }
90
92
  } else logger.info(pc.green("✓") + ` Workflows are valid` + pc.dim(` (${workflowsWithSource.length} workflow${workflowsWithSource.length !== 1 ? "s" : ""})`));
91
93
  return true;
@@ -0,0 +1,7 @@
1
+ export interface DiagnosticsOptions {
2
+ json?: boolean;
3
+ verbose?: boolean;
4
+ orchestrator?: string;
5
+ }
6
+ export declare function diagnosticsCommand(options?: DiagnosticsOptions): Promise<boolean>;
7
+ //# sourceMappingURL=diagnostics.d.ts.map
@@ -0,0 +1,58 @@
1
+ import "../chunk-BTugEXQM.js";
2
+ import { DashboardClient, DashboardClientError } from "../remote/dashboard-client.js";
3
+ import { relativeTime } from "../remote/render.js";
4
+ import pc from "picocolors";
5
+ import { logger, toErrorMessage } from "@kici-dev/core";
6
+ //#region src/commands/diagnostics.ts
7
+ /** kici diagnostics — mirrors the dashboard Diagnostics page (infra tree). */
8
+ async function diagnosticsCommand(options = {}) {
9
+ try {
10
+ const client = await DashboardClient.load();
11
+ const [summary, infra] = await Promise.all([client.getDiagnosticsSummary(), client.getInfrastructure()]);
12
+ let orchestrators = infra.orchestrators;
13
+ if (options.orchestrator) orchestrators = orchestrators.filter((o) => o.connectionId === options.orchestrator);
14
+ if (options.json) {
15
+ console.log(JSON.stringify({
16
+ summary,
17
+ orchestrators,
18
+ alerts: infra.alerts
19
+ }, null, 2));
20
+ return true;
21
+ }
22
+ printSummary(summary);
23
+ printAlerts(infra.alerts);
24
+ if (orchestrators.length === 0) {
25
+ console.log(pc.gray("\nNo orchestrators connected."));
26
+ return true;
27
+ }
28
+ for (const o of orchestrators) printOrchestrator(o, options.verbose ?? false);
29
+ return true;
30
+ } catch (err) {
31
+ logger.error(pc.red(err instanceof DashboardClientError ? err.message : toErrorMessage(err)));
32
+ return false;
33
+ }
34
+ }
35
+ function printSummary(s) {
36
+ const m = s.executionMetrics;
37
+ console.log(pc.bold("\nDiagnostics") + pc.gray(` runs(24h)=${m.totalRuns} success=${m.successRate}% avg=${m.avgDurationSeconds}s queued=${m.queuedJobs} running=${m.runningJobs}` + (s.orphanedConnections > 0 ? ` orphaned=${s.orphanedConnections}` : "")));
38
+ }
39
+ function printAlerts(alerts) {
40
+ for (const a of alerts) {
41
+ const color = a.severity === "critical" ? pc.red : pc.yellow;
42
+ console.log(color(` ! [${a.type}] ${a.message}`));
43
+ }
44
+ }
45
+ function printOrchestrator(o, verbose) {
46
+ const hb = o.lastHeartbeat ? relativeTime(new Date(o.lastHeartbeat).toISOString()) : "—";
47
+ const head = pc.bold(o.clusterName ?? o.connectionId) + pc.gray(` [${o.connectionId}] keys=${o.routingKeys.join(",") || "—"} ${o.connected ? pc.green("connected") : pc.red("disconnected")} raft=${o.raftRole ?? "—"} hb=${hb}`);
48
+ console.log(`\n${head}`);
49
+ for (const sc of o.scalers) console.log(pc.gray(" └─ ") + `${sc.name} (${sc.type}) ${sc.activeAgents}/${sc.maxAgents} ` + pc.gray(`labels=${sc.labelSets.map((set) => set.join("+")).join(" | ") || "—"}`));
50
+ for (const ag of o.agents) {
51
+ const extra = verbose ? ` host=${ag.hostname ?? "—"} node=${ag.nodeVersion ?? "—"} mem=${ag.memoryUsedMb ?? "—"}MB` : "";
52
+ console.log(pc.gray(" • ") + `${ag.agentId} ` + pc.cyan(`[${ag.labels.join(",")}]`) + pc.gray(` ${ag.platform}/${ag.arch} jobs=${ag.activeJobs}/${ag.maxConcurrency} hb=${relativeTime(new Date(ag.lastHeartbeatAt).toISOString())}${extra}`));
53
+ }
54
+ }
55
+ //#endregion
56
+ export { diagnosticsCommand };
57
+
58
+ //# sourceMappingURL=diagnostics.js.map
@@ -1,4 +1,4 @@
1
- import "../chunk-gOLHoazu.js";
1
+ import "../chunk-BTugEXQM.js";
2
2
  import { fileURLToPath } from "node:url";
3
3
  import path from "node:path";
4
4
  import pc from "picocolors";
@@ -1,4 +1,4 @@
1
- import "../chunk-gOLHoazu.js";
1
+ import "../chunk-BTugEXQM.js";
2
2
  import pc from "picocolors";
3
3
  import { logger, toErrorMessage } from "@kici-dev/core";
4
4
  //#region src/commands/drain-worker.ts
@@ -1,4 +1,4 @@
1
- import "../chunk-gOLHoazu.js";
1
+ import "../chunk-BTugEXQM.js";
2
2
  import { resolveKiciDir } from "../execution/executor.js";
3
3
  import "../execution/index.js";
4
4
  import { loadGlobalConfig } from "../remote/config.js";
@@ -1,4 +1,4 @@
1
- import "../chunk-gOLHoazu.js";
1
+ import "../chunk-BTugEXQM.js";
2
2
  import { parseEventArg } from "../test-runner/event-types.js";
3
3
  import { detectRepoFromGit } from "../test-runner/git-detector.js";
4
4
  import { getDefaultFixture } from "../fixtures/defaults/index.js";
@@ -1,4 +1,4 @@
1
- import "../chunk-gOLHoazu.js";
1
+ import "../chunk-BTugEXQM.js";
2
2
  import { loadGlobalConfig } from "../remote/config.js";
3
3
  import pc from "picocolors";
4
4
  import { logger } from "@kici-dev/core";
@@ -1,4 +1,4 @@
1
- import "../chunk-gOLHoazu.js";
1
+ import "../chunk-BTugEXQM.js";
2
2
  //#region src/commands/held-run-resolve.ts
3
3
  /**
4
4
  * Resolve the held-run id matching the filter from a list of pending holds.
@@ -1,4 +1,4 @@
1
- import "../chunk-gOLHoazu.js";
1
+ import "../chunk-BTugEXQM.js";
2
2
  import { detectHookTools, findGitDir } from "../hooks/detector.js";
3
3
  import { installHook } from "../hooks/installer.js";
4
4
  import "../hooks/index.js";
@@ -14,16 +14,26 @@ export { loginCommand } from './login.js';
14
14
  export type { LoginOptions } from './login.js';
15
15
  export { secretsListCommand } from './secrets-list.js';
16
16
  export type { SecretsListOptions } from './secrets-list.js';
17
- export { statusCommand } from './status.js';
18
- export type { StatusOptions } from './status.js';
17
+ export { runsListCommand } from './runs/list.js';
18
+ export type { RunsListOptions } from './runs/list.js';
19
+ export { runsShowCommand } from './runs/show.js';
20
+ export type { RunsShowOptions } from './runs/show.js';
21
+ export { runsLogsCommand } from './runs/logs.js';
22
+ export type { RunsLogsOptions } from './runs/logs.js';
23
+ export { runsRerunCommand } from './runs/rerun.js';
24
+ export type { RunsRerunOptions } from './runs/rerun.js';
25
+ export { runsCancelCommand } from './runs/cancel.js';
26
+ export type { RunsCancelOptions } from './runs/cancel.js';
19
27
  export { typesCommand } from './types.js';
20
28
  export type { TypesOptions } from './types.js';
21
29
  export { endpointsCommand } from './endpoints.js';
22
30
  export type { EndpointsOptions } from './endpoints.js';
31
+ export { diagnosticsCommand } from './diagnostics.js';
32
+ export type { DiagnosticsOptions } from './diagnostics.js';
23
33
  export { orgListCommand, orgUseCommand, orgCurrentCommand } from './org.js';
34
+ export { orchestratorsListCommand, orchestratorsUseCommand } from './orchestrators.js';
35
+ export type { OrchestratorsOptions } from './orchestrators.js';
24
36
  export { logoutCommand } from './logout.js';
25
- export { cancelCommand } from './cancel.js';
26
- export type { CancelOptions } from './cancel.js';
27
37
  export { approveCommand } from './approve.js';
28
38
  export type { ApproveOptions } from './approve.js';
29
39
  export { rejectCommand } from './reject.js';
@@ -34,4 +44,6 @@ export { drainWorkerCommand } from './drain-worker.js';
34
44
  export type { DrainWorkerOptions } from './drain-worker.js';
35
45
  export { docsCommand, docsLlmCommand } from './docs.js';
36
46
  export type { DocsOptions, DocsLlmOptions } from './docs.js';
47
+ export { verifyAttestationCommand } from './verify-attestation.js';
48
+ export type { VerifyAttestationOptions } from './verify-attestation.js';
37
49
  //# sourceMappingURL=index.d.ts.map
@@ -1,7 +1,7 @@
1
- import "../chunk-gOLHoazu.js";
1
+ import "../chunk-BTugEXQM.js";
2
2
  import { compileCommand } from "./compile.js";
3
3
  import { approveCommand } from "./approve.js";
4
- import { cancelCommand } from "./cancel.js";
4
+ import { diagnosticsCommand } from "./diagnostics.js";
5
5
  import { docsCommand, docsLlmCommand } from "./docs.js";
6
6
  import { drainWorkerCommand } from "./drain-worker.js";
7
7
  import { endpointsCommand } from "./endpoints.js";
@@ -13,10 +13,16 @@ import { runLocalCommand, runRemoteCommand } from "./run.js";
13
13
  import { initCommand } from "./init.js";
14
14
  import { loginCommand } from "./login.js";
15
15
  import { secretsListCommand } from "./secrets-list.js";
16
- import { statusCommand } from "./status.js";
16
+ import { runsListCommand } from "./runs/list.js";
17
+ import { runsShowCommand } from "./runs/show.js";
18
+ import { runsLogsCommand } from "./runs/logs.js";
19
+ import { runsRerunCommand } from "./runs/rerun.js";
20
+ import { runsCancelCommand } from "./runs/cancel.js";
17
21
  import { typesCommand } from "./types.js";
18
22
  import { orgCurrentCommand, orgListCommand, orgUseCommand } from "./org.js";
23
+ import { orchestratorsListCommand, orchestratorsUseCommand } from "./orchestrators.js";
19
24
  import { logoutCommand } from "./logout.js";
20
25
  import { rejectCommand } from "./reject.js";
21
26
  import { workflowsListCommand } from "./workflows.js";
22
- export { approveCommand, cancelCommand, compileCommand, docsCommand, docsLlmCommand, drainWorkerCommand, endpointsCommand, fixtureCommand, hookInstallCommand, initCommand, loginCommand, logoutCommand, orgCurrentCommand, orgListCommand, orgUseCommand, rejectCommand, runLocalCommand, runRemoteCommand, secretsListCommand, statusCommand, testCommand, testDryRun, typesCommand, watchCommand, workflowsListCommand };
27
+ import { verifyAttestationCommand } from "./verify-attestation.js";
28
+ export { approveCommand, compileCommand, diagnosticsCommand, docsCommand, docsLlmCommand, drainWorkerCommand, endpointsCommand, fixtureCommand, hookInstallCommand, initCommand, loginCommand, logoutCommand, orchestratorsListCommand, orchestratorsUseCommand, orgCurrentCommand, orgListCommand, orgUseCommand, rejectCommand, runLocalCommand, runRemoteCommand, runsCancelCommand, runsListCommand, runsLogsCommand, runsRerunCommand, runsShowCommand, secretsListCommand, testCommand, testDryRun, typesCommand, verifyAttestationCommand, watchCommand, workflowsListCommand };
@@ -1,4 +1,4 @@
1
- import "../chunk-gOLHoazu.js";
1
+ import "../chunk-BTugEXQM.js";
2
2
  import { agentsMdTemplate } from "../templates/agents-md.js";
3
3
  import { tsconfigTemplate } from "../templates/tsconfig-json.js";
4
4
  import { generatePackageJson } from "../templates/package-json.js";
@@ -292,7 +292,7 @@ export default workflow('private-registry-example', {
292
292
  ],
293
293
  jobs: [
294
294
  job('build', {
295
- runsOn: 'linux',
295
+ runsOn: 'kici:os:linux',
296
296
  steps: [step('install', async () => { /* deps install with auth */ })],
297
297
  }),
298
298
  ],
@@ -1,8 +1,6 @@
1
1
  export interface LoginOptions {
2
2
  /** API key for non-interactive authentication */
3
3
  token?: string;
4
- /** Orchestrator URL for direct connection */
5
- endpoint?: string;
6
4
  /** Platform relay URL */
7
5
  platformEndpoint?: string;
8
6
  /** Routing key for webhook source identification */
@@ -1,4 +1,4 @@
1
- import "../chunk-gOLHoazu.js";
1
+ import "../chunk-BTugEXQM.js";
2
2
  import { getConfigPath, mergeGlobalConfig } from "../remote/config.js";
3
3
  import { deviceFlow, exchangeTokenForPat, pkceFlow } from "../remote/oauth.js";
4
4
  import "../remote/prod-defaults.js";
@@ -75,7 +75,6 @@ async function oauthLogin(options) {
75
75
  patId: patResult.id,
76
76
  patExpiresAt: patResult.expiresAt
77
77
  };
78
- if (options.endpoint) configUpdate.endpoint = options.endpoint;
79
78
  if (options.platformEndpoint) configUpdate.platformEndpoint = options.platformEndpoint;
80
79
  if (options.routingKey) configUpdate.routingKey = options.routingKey;
81
80
  await mergeGlobalConfig(configUpdate);
@@ -117,7 +116,6 @@ async function legacyTokenLogin(options) {
117
116
  return false;
118
117
  }
119
118
  const update = { token };
120
- if (options.endpoint) update.endpoint = options.endpoint;
121
119
  if (options.platformEndpoint) update.platformEndpoint = options.platformEndpoint;
122
120
  if (options.routingKey) update.routingKey = options.routingKey;
123
121
  await mergeGlobalConfig(update);
@@ -1,4 +1,4 @@
1
- import "../chunk-gOLHoazu.js";
1
+ import "../chunk-BTugEXQM.js";
2
2
  import { getConfigPath, loadGlobalConfig, saveGlobalConfig } from "../remote/config.js";
3
3
  import pc from "picocolors";
4
4
  //#region src/commands/logout.ts
@@ -0,0 +1,25 @@
1
+ /**
2
+ * kici orchestrators commands
3
+ *
4
+ * Inspect the org's connected orchestrator clusters and pick a per-org default
5
+ * for `kici run remote`. `list` reads the Platform orchestrators index;
6
+ * `use <name>` records `config.defaultClusters[orgId]` so a developer with a
7
+ * preferred cluster types no `--orchestrator` flag.
8
+ */
9
+ /** Options shared by the orchestrators subcommands. */
10
+ export interface OrchestratorsOptions {
11
+ /** Target organization id (overrides config.activeOrgId). */
12
+ org?: string;
13
+ }
14
+ /**
15
+ * List the org's connected orchestrator clusters, marking the per-org default.
16
+ */
17
+ export declare function orchestratorsListCommand(options: OrchestratorsOptions): Promise<boolean>;
18
+ /**
19
+ * Set the per-org default orchestrator cluster.
20
+ *
21
+ * Validates the cluster name against the org's connected clusters before
22
+ * writing it to `config.defaultClusters[orgId]`.
23
+ */
24
+ export declare function orchestratorsUseCommand(clusterName: string, options: OrchestratorsOptions): Promise<boolean>;
25
+ //# sourceMappingURL=orchestrators.d.ts.map
@@ -0,0 +1,115 @@
1
+ import "../chunk-BTugEXQM.js";
2
+ import { loadGlobalConfig, mergeGlobalConfig } from "../remote/config.js";
3
+ import pc from "picocolors";
4
+ //#region src/commands/orchestrators.ts
5
+ /**
6
+ * kici orchestrators commands
7
+ *
8
+ * Inspect the org's connected orchestrator clusters and pick a per-org default
9
+ * for `kici run remote`. `list` reads the Platform orchestrators index;
10
+ * `use <name>` records `config.defaultClusters[orgId]` so a developer with a
11
+ * preferred cluster types no `--orchestrator` flag.
12
+ */
13
+ /**
14
+ * Resolve the authenticated config + the target org id, printing an actionable
15
+ * error and returning null when either is missing.
16
+ */
17
+ async function resolveOrgContext(options) {
18
+ const config = await loadGlobalConfig();
19
+ if (!config.pat) {
20
+ console.error(pc.red("Not logged in. Run `kici login` first."));
21
+ return null;
22
+ }
23
+ if (!config.platformEndpoint) {
24
+ console.error(pc.red("No Platform endpoint configured. Run `kici login` to set up your Platform."));
25
+ return null;
26
+ }
27
+ const orgId = options.org ?? config.activeOrgId;
28
+ if (!orgId) {
29
+ console.error(pc.red("No target organization. Select one with `kici org use <org>` or pass `--org <id>`."));
30
+ return null;
31
+ }
32
+ return {
33
+ config,
34
+ orgId
35
+ };
36
+ }
37
+ /**
38
+ * Fetch the org's connected orchestrator clusters from the Platform index.
39
+ * Returns null on an auth/HTTP failure (after printing an error).
40
+ */
41
+ async function fetchOrchestrators(config, orgId) {
42
+ const url = `${config.platformEndpoint}/api/v1/orgs/${orgId}/orchestrators`;
43
+ const response = await fetch(url, { headers: {
44
+ Authorization: `Bearer ${config.pat}`,
45
+ "Content-Type": "application/json"
46
+ } });
47
+ if (!response.ok) {
48
+ if (response.status === 401) {
49
+ console.error(pc.red("Authentication failed. Your token may be expired. Run `kici login` to re-authenticate."));
50
+ return null;
51
+ }
52
+ console.error(pc.red(`Failed to list orchestrators: HTTP ${response.status}`));
53
+ return null;
54
+ }
55
+ return (await response.json()).orchestrators ?? [];
56
+ }
57
+ /**
58
+ * List the org's connected orchestrator clusters, marking the per-org default.
59
+ */
60
+ async function orchestratorsListCommand(options) {
61
+ const ctx = await resolveOrgContext(options);
62
+ if (!ctx) return false;
63
+ const orchestrators = await fetchOrchestrators(ctx.config, ctx.orgId);
64
+ if (orchestrators === null) return false;
65
+ if (orchestrators.length === 0) {
66
+ console.log(pc.gray("No orchestrators are connected for this organization."));
67
+ return true;
68
+ }
69
+ const defaultCluster = ctx.config.defaultClusters?.[ctx.orgId];
70
+ console.log(pc.bold("\nOrchestrators:\n"));
71
+ const names = orchestrators.map((o) => o.clusterName ?? "(unnamed)");
72
+ const nameWidth = Math.max(12, ...names.map((n) => n.length)) + 2;
73
+ for (const orch of orchestrators) {
74
+ const name = orch.clusterName ?? "(unnamed)";
75
+ const isDefault = orch.clusterName !== null && orch.clusterName === defaultCluster;
76
+ const marker = isDefault ? pc.green("* ") : " ";
77
+ const display = isDefault ? pc.bold(name) : name;
78
+ const version = orch.orchVersion ? pc.gray(`v${orch.orchVersion}`) : pc.gray("(unknown)");
79
+ console.log(` ${marker}${display.padEnd(nameWidth)} ${version}`);
80
+ }
81
+ console.log("");
82
+ console.log(pc.gray("Set a default with `kici orchestrators use <name>`."));
83
+ return true;
84
+ }
85
+ /**
86
+ * Set the per-org default orchestrator cluster.
87
+ *
88
+ * Validates the cluster name against the org's connected clusters before
89
+ * writing it to `config.defaultClusters[orgId]`.
90
+ */
91
+ async function orchestratorsUseCommand(clusterName, options) {
92
+ const ctx = await resolveOrgContext(options);
93
+ if (!ctx) return false;
94
+ const orchestrators = await fetchOrchestrators(ctx.config, ctx.orgId);
95
+ if (orchestrators === null) return false;
96
+ if (!orchestrators.find((o) => o.clusterName === clusterName)) {
97
+ console.error(pc.red(`Orchestrator cluster not found: ${clusterName}`));
98
+ const named = orchestrators.map((o) => o.clusterName).filter((n) => !!n);
99
+ if (named.length > 0) {
100
+ console.error(pc.gray("Connected clusters:"));
101
+ for (const n of named) console.error(pc.gray(` - ${n}`));
102
+ }
103
+ return false;
104
+ }
105
+ await mergeGlobalConfig({ defaultClusters: {
106
+ ...ctx.config.defaultClusters ?? {},
107
+ [ctx.orgId]: clusterName
108
+ } });
109
+ console.log(pc.green(`Default orchestrator for ${ctx.orgId} set to: ${clusterName}`));
110
+ return true;
111
+ }
112
+ //#endregion
113
+ export { orchestratorsListCommand, orchestratorsUseCommand };
114
+
115
+ //# sourceMappingURL=orchestrators.js.map
@@ -1,4 +1,4 @@
1
- import "../chunk-gOLHoazu.js";
1
+ import "../chunk-BTugEXQM.js";
2
2
  import { loadGlobalConfig, mergeGlobalConfig } from "../remote/config.js";
3
3
  import pc from "picocolors";
4
4
  //#region src/commands/org.ts