@kici-dev/compiler 0.1.23 → 0.1.25

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 (137) hide show
  1. package/dist/auth/headless-detect.js +1 -1
  2. package/dist/cli-banner.js +1 -1
  3. package/dist/cli.d.ts +18 -0
  4. package/dist/cli.js +71 -10
  5. package/dist/commands/approve.js +2 -2
  6. package/dist/commands/check-mode.js +1 -1
  7. package/dist/commands/compile.js +1 -1
  8. package/dist/commands/diagnostics.js +1 -1
  9. package/dist/commands/docs.js +1 -1
  10. package/dist/commands/drain-worker.js +1 -1
  11. package/dist/commands/endpoints.js +1 -1
  12. package/dist/commands/fixture.js +2 -2
  13. package/dist/commands/held-run-client.d.ts +1 -1
  14. package/dist/commands/held-run-client.js +1 -1
  15. package/dist/commands/hook.js +1 -1
  16. package/dist/commands/index.d.ts +5 -3
  17. package/dist/commands/index.js +5 -4
  18. package/dist/commands/init.js +3 -3
  19. package/dist/commands/login.js +1 -1
  20. package/dist/commands/logout.js +1 -1
  21. package/dist/commands/orchestrators.js +1 -1
  22. package/dist/commands/org.js +1 -1
  23. package/dist/commands/pat.d.ts +27 -0
  24. package/dist/commands/pat.js +76 -0
  25. package/dist/commands/preview.d.ts +88 -0
  26. package/dist/commands/{test.js → preview.js} +16 -15
  27. package/dist/commands/reject.js +2 -2
  28. package/dist/commands/run-hold-watch.d.ts +10 -1
  29. package/dist/commands/run-hold-watch.js +13 -12
  30. package/dist/commands/run.d.ts +20 -1
  31. package/dist/commands/run.js +62 -12
  32. package/dist/commands/runs/cancel.js +1 -1
  33. package/dist/commands/runs/list.js +1 -1
  34. package/dist/commands/runs/logs.js +1 -1
  35. package/dist/commands/runs/rerun.js +1 -1
  36. package/dist/commands/runs/show.js +1 -1
  37. package/dist/commands/secrets-list.js +1 -1
  38. package/dist/commands/types.js +1 -1
  39. package/dist/commands/verify-attestation.d.ts +4 -1
  40. package/dist/commands/verify-attestation.js +34 -12
  41. package/dist/commands/watch.js +1 -1
  42. package/dist/commands/workflows.js +1 -1
  43. package/dist/errors/capability-gap.js +1 -1
  44. package/dist/errors/formatter.js +1 -1
  45. package/dist/errors/index.js +1 -1
  46. package/dist/execution/executor.d.ts +5 -6
  47. package/dist/execution/executor.js +6 -7
  48. package/dist/execution/index.js +1 -1
  49. package/dist/execution/sdk-alias.d.ts +4 -14
  50. package/dist/execution/sdk-alias.js +6 -45
  51. package/dist/execution/ts-loader.js +1 -1
  52. package/dist/fixtures/compiler.js +1 -1
  53. package/dist/fixtures/defaults/index.js +1 -1
  54. package/dist/fixtures/describe-event.d.ts +0 -4
  55. package/dist/fixtures/describe-event.js +35 -5
  56. package/dist/fixtures/picker.js +1 -1
  57. package/dist/format.js +1 -1
  58. package/dist/generators/secrets-dts.js +3 -1
  59. package/dist/hooks/detector.js +1 -1
  60. package/dist/hooks/index.js +1 -1
  61. package/dist/hooks/installer.js +1 -1
  62. package/dist/hooks/templates.js +1 -1
  63. package/dist/index.d.ts +2 -2
  64. package/dist/index.js +3 -3
  65. package/dist/llm-context/llms-architecture.txt +4 -4
  66. package/dist/llm-context/llms-cli.txt +346 -33
  67. package/dist/llm-context/llms-features.txt +128 -21
  68. package/dist/llm-context/llms-full.txt +610 -71
  69. package/dist/llm-context/llms-getting-started.txt +7 -7
  70. package/dist/llm-context/llms-sdk.txt +125 -6
  71. package/dist/llm-context/llms.txt +7 -5
  72. package/dist/local-executor/dag-scheduler.js +1 -1
  73. package/dist/local-executor/index.js +3 -2
  74. package/dist/local-executor/job-runner.js +4 -4
  75. package/dist/local-executor/materializer.js +1 -1
  76. package/dist/local-executor/output-streamer.js +1 -1
  77. package/dist/local-executor/payload-generator.js +1 -1
  78. package/dist/local-executor/picker.js +1 -1
  79. package/dist/local-executor/runs-on-display.js +1 -1
  80. package/dist/local-executor/secret-loader.js +1 -1
  81. package/dist/local-executor/to-event-payload.js +1 -1
  82. package/dist/local-executor/types.js +1 -1
  83. package/dist/local-executor/workflow-lock.js +0 -0
  84. package/dist/lockfile/generator.d.ts +10 -2
  85. package/dist/lockfile/generator.js +107 -53
  86. package/dist/lockfile/hash-files.js +1 -1
  87. package/dist/lockfile/hasher.js +1 -1
  88. package/dist/lockfile/index.js +1 -1
  89. package/dist/lockfile/purity-analyzer.js +3 -3
  90. package/dist/postinstall.js +1 -1
  91. package/dist/provenance-trust-root.js +1 -1
  92. package/dist/remote/config.js +1 -1
  93. package/dist/remote/dashboard-client.js +1 -1
  94. package/dist/remote/encryption.js +1 -1
  95. package/dist/remote/history.d.ts +1 -1
  96. package/dist/remote/history.js +2 -2
  97. package/dist/remote/local-repo-identity.d.ts +32 -0
  98. package/dist/remote/local-repo-identity.js +74 -0
  99. package/dist/remote/oauth.js +1 -1
  100. package/dist/remote/oidc-discovery.js +1 -1
  101. package/dist/remote/output/json.js +1 -1
  102. package/dist/remote/output/junit.js +1 -1
  103. package/dist/remote/output/streaming.js +1 -1
  104. package/dist/remote/output/summary.js +1 -1
  105. package/dist/remote/platform-client.d.ts +2 -0
  106. package/dist/remote/platform-client.js +1 -1
  107. package/dist/remote/prod-defaults.d.ts +9 -1
  108. package/dist/remote/prod-defaults.js +11 -3
  109. package/dist/remote/render.js +1 -1
  110. package/dist/remote/secret-upload.js +1 -1
  111. package/dist/remote/uploader.js +4 -4
  112. package/dist/{chunk-BTugEXQM.js → rolldown-runtime-ClRpJifh.js} +0 -1
  113. package/dist/templates/agents-md.d.ts +1 -1
  114. package/dist/templates/agents-md.js +3 -3
  115. package/dist/templates/index.js +1 -1
  116. package/dist/templates/package-json.js +2 -2
  117. package/dist/templates/tsconfig-json.js +1 -1
  118. package/dist/templates/workflows/hello-world.js +1 -1
  119. package/dist/templates/workflows/pr-checks.js +1 -1
  120. package/dist/test-runner/dry-run.js +1 -1
  121. package/dist/test-runner/event-types.js +1 -1
  122. package/dist/test-runner/git-detector.js +1 -1
  123. package/dist/test-runner/index.js +1 -1
  124. package/dist/test-runner/job-executor.js +1 -1
  125. package/dist/test-runner/output-formatter.js +1 -1
  126. package/dist/test-runner/payload-builder.js +1 -1
  127. package/dist/test-runner/rule-evaluator.js +1 -1
  128. package/dist/test-runner/secrets-file.js +1 -1
  129. package/dist/test-runner/step-context.d.ts +1 -1
  130. package/dist/test-runner/step-context.js +3 -2
  131. package/dist/types.d.ts +33 -6
  132. package/dist/types.js +6 -2
  133. package/dist/validation/index.js +1 -1
  134. package/dist/validation/validator.js +1 -1
  135. package/package.json +4 -7
  136. package/sbom.spdx.json +35 -35
  137. package/dist/commands/held-run-resolve.js +0 -53
@@ -1,4 +1,4 @@
1
- import "../chunk-BTugEXQM.js";
1
+ import "../rolldown-runtime-ClRpJifh.js";
2
2
  import { discoverWorkflows, resolveKiciDir } from "../execution/executor.js";
3
3
  import "../execution/index.js";
4
4
  import { transformTriggers } from "../lockfile/generator.js";
@@ -9,30 +9,31 @@ import { loadSecretsFile } from "../test-runner/secrets-file.js";
9
9
  import path from "node:path";
10
10
  import pc from "picocolors";
11
11
  import { readFile } from "node:fs/promises";
12
+ import { flattenStepInputs } from "@kici-dev/sdk";
12
13
  import { logger, toErrorMessage } from "@kici-dev/core";
13
14
  import { matchAllWorkflows } from "@kici-dev/engine";
14
15
  import { normalizeRunsOnToMatchers } from "@kici-dev/engine/labels/compile";
15
- //#region src/commands/test.ts
16
+ //#region src/commands/preview.ts
16
17
  /**
17
- * Main test command entry point.
18
+ * Main preview command entry point.
18
19
  *
19
- * `kici test <event>` is now dry-run trigger preview only.
20
+ * `kici preview <event>` is a dry-run trigger preview only — it executes nothing.
20
21
  * If the argument looks like a fixture name (not a known event type), prints a migration message.
21
22
  */
22
- async function testCommand(event, options) {
23
+ async function previewCommand(event, options) {
23
24
  if (options.debug) {
24
25
  process.env.KICI_DEBUG = "true";
25
26
  logger.info(pc.gray("Debug mode enabled"));
26
27
  }
27
28
  try {
28
29
  if (!event) {
29
- logger.info(pc.bold("\nUsage: kici test <event>\n"));
30
+ logger.info(pc.bold("\nUsage: kici preview <event>\n"));
30
31
  logger.info(pc.gray("Preview which workflows and jobs would run for a given event.\n"));
31
32
  logger.info(pc.gray("Examples:"));
32
- logger.info(pc.gray(" kici test push"));
33
- logger.info(pc.gray(" kici test pr:open"));
34
- logger.info(pc.gray(" kici test schedule"));
35
- logger.info(pc.gray(" kici test lifecycle:workflow_complete\n"));
33
+ logger.info(pc.gray(" kici preview push"));
34
+ logger.info(pc.gray(" kici preview pr:open"));
35
+ logger.info(pc.gray(" kici preview schedule"));
36
+ logger.info(pc.gray(" kici preview lifecycle:workflow_complete\n"));
36
37
  logger.info(pc.gray("For remote fixture execution, use: kici run remote [fixture] [options]"));
37
38
  logger.info(pc.gray("For local workflow execution, use: kici run local <event> [options]\n"));
38
39
  return true;
@@ -41,7 +42,7 @@ async function testCommand(event, options) {
41
42
  logger.info(pc.yellow(`\nFixture-based testing has moved to \`kici run remote\`.\nRun \`kici run remote ${event}\` instead.\n`));
42
43
  return false;
43
44
  }
44
- return await testDryRun(event, options);
45
+ return await previewEvent(event, options);
45
46
  } catch (error) {
46
47
  const message = toErrorMessage(error);
47
48
  logger.error(pc.red(`\nError: ${message}\n`));
@@ -64,7 +65,7 @@ function isKnownEventArg(arg) {
64
65
  /**
65
66
  * Local-only dry-run mode: compile workflows, match triggers, display what would execute.
66
67
  */
67
- async function testDryRun(event, options) {
68
+ async function previewEvent(event, options) {
68
69
  try {
69
70
  const kiciDir = resolveKiciDir(options.kiciDir);
70
71
  logger.info(pc.gray(`KiCI directory: ${kiciDir}`));
@@ -144,7 +145,7 @@ function workflowsToLockFormat(workflows) {
144
145
  if ("group" in n) return `__group:${n.group}`;
145
146
  return n.name;
146
147
  }) ?? [],
147
- steps: j.steps.map((s) => {
148
+ steps: flattenStepInputs(j.steps).map((s) => {
148
149
  if (typeof s === "function") return {
149
150
  name: "",
150
151
  hasOutputs: false
@@ -213,6 +214,6 @@ async function loadTestSecrets(kiciDir, secretFlags, contextFlags) {
213
214
  return secrets;
214
215
  }
215
216
  //#endregion
216
- export { testCommand, testDryRun };
217
+ export { previewCommand, previewEvent };
217
218
 
218
- //# sourceMappingURL=test.js.map
219
+ //# sourceMappingURL=preview.js.map
@@ -1,8 +1,8 @@
1
- import "../chunk-BTugEXQM.js";
1
+ import "../rolldown-runtime-ClRpJifh.js";
2
2
  import { listHeldRunsForRun, postReject, resolveHeldRunContext } from "./held-run-client.js";
3
- import { resolveHeldRunId } from "./held-run-resolve.js";
4
3
  import pc from "picocolors";
5
4
  import { logger, toErrorMessage } from "@kici-dev/core";
5
+ import { resolveHeldRunId } from "@kici-dev/engine";
6
6
  //#region src/commands/reject.ts
7
7
  /**
8
8
  * kici reject command
@@ -10,10 +10,13 @@
10
10
  * path as `kici approve` / `kici reject`. In a non-TTY it prints guidance and
11
11
  * keeps polling (the run stays held until resolved out-of-band).
12
12
  */
13
- import type { HeldRunSummary } from './held-run-resolve.js';
13
+ import type { HeldRunSummary } from '@kici-dev/engine';
14
14
  import { type HeldRunContext } from './held-run-client.js';
15
15
  /** A yes/no prompt; injected so the poll branch is unit-testable. */
16
16
  export type ConfirmPrompt = (message: string) => Promise<boolean>;
17
+ /** Where hold/approve text is written. Injected so callers can route it to
18
+ * stderr in quiet/json mode (keeping stdout a pure JSON channel). */
19
+ export type HoldOutput = (line: string) => void;
17
20
  /** What to do with a newly-observed hold. Pure — no IO. */
18
21
  export type HoldAction = {
19
22
  kind: 'prompt';
@@ -48,6 +51,12 @@ export declare function handleNewHolds(args: {
48
51
  * audits it distinctly. Eligibility is still enforced server-side.
49
52
  */
50
53
  approveAll?: boolean;
54
+ /**
55
+ * Where hold/approve text goes. Defaults to `logger.info` (stdout). Quiet /
56
+ * `--json` callers pass a stderr sink so the machine-readable stdout payload
57
+ * stays pure.
58
+ */
59
+ output?: HoldOutput;
51
60
  /** Override for tests; defaults to the shared Platform held-run context. */
52
61
  resolveContext?: () => Promise<HeldRunContext | null>;
53
62
  /** Override for tests. */
@@ -1,4 +1,4 @@
1
- import "../chunk-BTugEXQM.js";
1
+ import "../rolldown-runtime-ClRpJifh.js";
2
2
  import { postApprove, postReject, resolveHeldRunContext } from "./held-run-client.js";
3
3
  import pc from "picocolors";
4
4
  import { logger } from "@kici-dev/core";
@@ -37,14 +37,14 @@ function classifyNewHolds(holds, seen, isTty) {
37
37
  seen: next
38
38
  };
39
39
  }
40
- /** Print a hold's identity + its drift payload (when present) to stdout. */
41
- function printHold(hold) {
40
+ /** Print a hold's identity + its drift payload (when present) via `out`. */
41
+ function printHold(hold, out) {
42
42
  const scope = hold.holdScope ?? "job";
43
43
  const where = scope === "step" && hold.stepIndex != null ? `step #${hold.stepIndex}${hold.jobId ? ` of job '${hold.jobId}'` : ""}` : hold.jobId ? `job '${hold.jobId}'` : scope;
44
- logger.info(pc.yellow(`\n[kici] Run held for approval (${where}).`));
44
+ out(pc.yellow(`\n[kici] Run held for approval (${where}).`));
45
45
  if (hold.payload?.summaryMarkdown) {
46
- logger.info(pc.dim("Computed drift — review before approving:"));
47
- for (const line of hold.payload.summaryMarkdown.split("\n")) logger.info(pc.dim(` ${line}`));
46
+ out(pc.dim("Computed drift — review before approving:"));
47
+ for (const line of hold.payload.summaryMarkdown.split("\n")) out(pc.dim(` ${line}`));
48
48
  }
49
49
  }
50
50
  /**
@@ -56,28 +56,29 @@ function printHold(hold) {
56
56
  async function handleNewHolds(args) {
57
57
  const { actions, seen } = classifyNewHolds(args.holds, args.seen, args.isTty);
58
58
  if (actions.length === 0) return seen;
59
+ const out = args.output ?? ((line) => logger.info(line));
59
60
  const resolveCtx = args.resolveContext ?? resolveHeldRunContext;
60
61
  const doApprove = args.approve ?? postApprove;
61
62
  const doReject = args.reject ?? postReject;
62
63
  let ctx = null;
63
- if (args.approveAll) logger.info(pc.yellow("[kici] --approve-all: auto-approving every gate for this run (eligibility enforced)."));
64
+ if (args.approveAll) out(pc.yellow("[kici] --approve-all: auto-approving every gate for this run (eligibility enforced)."));
64
65
  for (const action of actions) {
65
- printHold(action.hold);
66
+ printHold(action.hold, out);
66
67
  ctx = ctx ?? await resolveCtx();
67
68
  if (!ctx) {
68
- logger.info(pc.dim(`Run held; approve via \`kici approve ${action.hold.runId}\`.`));
69
+ out(pc.dim(`Run held; approve via \`kici approve ${action.hold.runId}\`.`));
69
70
  continue;
70
71
  }
71
72
  if (args.approveAll) {
72
- if (await doApprove(ctx, action.hold.id, true)) logger.info(pc.green("[kici] Auto-approved."));
73
+ if (await doApprove(ctx, action.hold.id, true)) out(pc.green("[kici] Auto-approved."));
73
74
  continue;
74
75
  }
75
76
  if (action.kind === "notify") {
76
- logger.info(pc.dim(`Run held; approve via the dashboard or \`kici approve ${action.hold.runId}\`.`));
77
+ out(pc.dim(`Run held; approve via the dashboard or \`kici approve ${action.hold.runId}\`.`));
77
78
  continue;
78
79
  }
79
80
  const approved = await args.confirm("Approve this gate?");
80
- if (approved ? await doApprove(ctx, action.hold.id) : await doReject(ctx, action.hold.id, "rejected via kici run")) logger.info(approved ? pc.green("[kici] Approved.") : pc.red("[kici] Rejected."));
81
+ if (approved ? await doApprove(ctx, action.hold.id) : await doReject(ctx, action.hold.id, "rejected via kici run")) out(approved ? pc.green("[kici] Approved.") : pc.red("[kici] Rejected."));
81
82
  }
82
83
  return seen;
83
84
  }
@@ -1,6 +1,15 @@
1
1
  import { type HostTargetSelector, type InputsDescriptorMap } from '@kici-dev/engine';
2
2
  import type { RunLocalOptions } from '../local-executor/types.js';
3
- import type { RemoteRunOptions } from './test.js';
3
+ import type { RemoteRunOptions } from './preview.js';
4
+ /**
5
+ * Print a usage block for `kici run local` when the event argument is missing.
6
+ *
7
+ * Mirrors the discoverable help `kici preview` prints for a missing event: a
8
+ * bold synopsis line, a one-line description, and a few concrete event
9
+ * examples. The caller exits non-zero after printing — a missing event is a
10
+ * usage error, unlike `kici preview` which treats no-event as help.
11
+ */
12
+ export declare function printRunLocalUsage(): void;
4
13
  /**
5
14
  * Compile `--target` selector strings into a {@link HostTargetSelector}. Each
6
15
  * string becomes one AND value (its own include set); repeated values
@@ -23,6 +32,16 @@ export declare function lookupDispatchInputsDescriptor(inlineLockFile: string |
23
32
  * authoritative and applies coercion + defaults exactly once.
24
33
  */
25
34
  export declare function buildDispatchInputs(pairs: string[], descriptor: InputsDescriptorMap | undefined): Record<string, string>;
35
+ /**
36
+ * Run `fn` with everything written to `process.stdout` redirected to
37
+ * `process.stderr`, then restore the original writer. Compiling a repo
38
+ * evaluates every user workflow / fixture module, and a `console.log` at a
39
+ * module's top level writes straight to stdout. On a machine-readable
40
+ * (`--json`) run that stdout MUST carry only the final JSON result, so the
41
+ * compile phases run inside this guard — workflow log output belongs on
42
+ * stderr regardless.
43
+ */
44
+ export declare function withStdoutOnStderr<T>(fn: () => Promise<T>): Promise<T>;
26
45
  /**
27
46
  * Run a workflow locally using the local executor.
28
47
  * Thin wrapper that delegates to executeLocal from local-executor.
@@ -1,8 +1,9 @@
1
- import "../chunk-BTugEXQM.js";
1
+ import "../rolldown-runtime-ClRpJifh.js";
2
2
  import { resolveKiciDir } from "../execution/executor.js";
3
3
  import "../execution/index.js";
4
4
  import { loadGlobalConfig } from "../remote/config.js";
5
5
  import { RunHistory } from "../remote/history.js";
6
+ import { buildLocalRepoIdentity } from "../remote/local-repo-identity.js";
6
7
  import { AccessDeniedError, AmbiguousClusterError, AuthenticationError, ConnectionError, NoClusterError, PlatformRunClient } from "../remote/platform-client.js";
7
8
  import { buildEncryptedSecrets } from "../remote/secret-upload.js";
8
9
  import { createOverlayTarball, getSizeWarning, uploadTarball } from "../remote/uploader.js";
@@ -23,8 +24,26 @@ import { coerceDispatchInputs, parseInputPairs } from "@kici-dev/engine";
23
24
  import { normalizeRunsOnToMatchers } from "@kici-dev/engine/labels/compile";
24
25
  import { confirm } from "@inquirer/prompts";
25
26
  //#region src/commands/run.ts
27
+ /**
28
+ * Print a usage block for `kici run local` when the event argument is missing.
29
+ *
30
+ * Mirrors the discoverable help `kici preview` prints for a missing event: a
31
+ * bold synopsis line, a one-line description, and a few concrete event
32
+ * examples. The caller exits non-zero after printing — a missing event is a
33
+ * usage error, unlike `kici preview` which treats no-event as help.
34
+ */
35
+ function printRunLocalUsage() {
36
+ logger.info(pc.bold("\nUsage: kici run local <event> [options]\n"));
37
+ logger.info(pc.gray("Execute workflows locally for a given event, without orchestrator infrastructure.\n"));
38
+ logger.info(pc.gray("Examples:"));
39
+ logger.info(pc.gray(" kici run local push"));
40
+ logger.info(pc.gray(" kici run local pr:open"));
41
+ logger.info(pc.gray(" kici run local schedule"));
42
+ logger.info(pc.gray(" kici run local lifecycle:workflow_complete\n"));
43
+ logger.info(pc.gray("Or pick a workflow interactively: kici run local --pick\n"));
44
+ }
26
45
  /** Terminal run statuses returned by the Platform run-status snapshot. */
27
- const TERMINAL_STATUSES = new Set([
46
+ const TERMINAL_STATUSES = /* @__PURE__ */ new Set([
28
47
  "success",
29
48
  "failed",
30
49
  "cancelled",
@@ -90,6 +109,24 @@ function buildDispatchInputs(pairs, descriptor) {
90
109
  /** Interval between status/log polls while a run is active. */
91
110
  const POLL_INTERVAL_MS = 750;
92
111
  /**
112
+ * Run `fn` with everything written to `process.stdout` redirected to
113
+ * `process.stderr`, then restore the original writer. Compiling a repo
114
+ * evaluates every user workflow / fixture module, and a `console.log` at a
115
+ * module's top level writes straight to stdout. On a machine-readable
116
+ * (`--json`) run that stdout MUST carry only the final JSON result, so the
117
+ * compile phases run inside this guard — workflow log output belongs on
118
+ * stderr regardless.
119
+ */
120
+ async function withStdoutOnStderr(fn) {
121
+ const realWrite = process.stdout.write.bind(process.stdout);
122
+ process.stdout.write = process.stderr.write.bind(process.stderr);
123
+ try {
124
+ return await fn();
125
+ } finally {
126
+ process.stdout.write = realWrite;
127
+ }
128
+ }
129
+ /**
93
130
  * Recompile `.kici/workflows` → `kici.lock.json` before a remote run, mirroring
94
131
  * `kici run local`. The orchestrator matches triggers and dispatches against the
95
132
  * inline lock, so a stale lock would route an edited or newly-added workflow
@@ -97,12 +134,14 @@ const POLL_INTERVAL_MS = 750;
97
134
  * abort before any upload or dispatch.
98
135
  */
99
136
  async function compileBeforeRemoteRun(options) {
100
- return compileCommand({
137
+ const pureStdout = Boolean(options.json || options.quiet);
138
+ const compile = () => compileCommand({
101
139
  kiciDir: options.kiciDir ?? ".kici",
102
140
  check: false,
103
141
  verbose: options.debug ?? false,
104
- quiet: Boolean(options.json || options.quiet)
142
+ quiet: pureStdout
105
143
  });
144
+ return pureStdout ? withStdoutOnStderr(compile) : compile();
106
145
  }
107
146
  /**
108
147
  * Run a workflow locally using the local executor.
@@ -148,7 +187,8 @@ async function runRemoteCommand(fixture, options) {
148
187
  console.log(history.formatTable(entries));
149
188
  return true;
150
189
  }
151
- const fixtures = await compileFixtures(path.join(kiciDir, "tests"));
190
+ const testsDir = path.join(kiciDir, "tests");
191
+ const fixtures = options.json ? await withStdoutOnStderr(() => compileFixtures(testsDir)) : await compileFixtures(testsDir);
152
192
  let selected;
153
193
  if (options.pick) {
154
194
  if (fixtures.length === 0) return listFixtures(fixtures);
@@ -355,11 +395,12 @@ async function runSingleFixture(fixture, ctx, options, config, history) {
355
395
  const uploaded = await initAndUpload(ctx, overlay, options);
356
396
  const event = buildEventFromFixture(opts);
357
397
  {
358
- const repoName = path.basename(overlay.repoRoot);
398
+ const identity = buildLocalRepoIdentity(overlay.repoRoot);
359
399
  const repo = event.payload.repository;
360
400
  event.payload.repository = {
361
401
  ...repo ?? {},
362
- full_name: `local/${repoName}`
402
+ full_name: identity.repoIdentifier,
403
+ provider: identity.provider
363
404
  };
364
405
  }
365
406
  if (!options.quiet) logger.info(pc.gray("Triggering test run..."));
@@ -397,7 +438,10 @@ async function runSingleFixture(fixture, ctx, options, config, history) {
397
438
  reason: triggerResult.reason
398
439
  };
399
440
  }
400
- if (!options.quiet) logger.info(pc.green(`Run started: ${triggerResult.runId}`));
441
+ if (!options.quiet) {
442
+ logger.info(pc.green(`Run started: ${triggerResult.runId}`));
443
+ for (const warning of triggerResult.warnings ?? []) logger.warn(pc.yellow(`⚠ ${warning}`));
444
+ }
401
445
  await history.addEntry({
402
446
  runId: triggerResult.runId,
403
447
  fixtureId: fixture.id,
@@ -476,7 +520,7 @@ async function pollRunToCompletion(ctx, runId, fixtureId, options) {
476
520
  lastStatus = await ctx.client.runStatus(ctx.orgId, runId, ctx.target);
477
521
  const terminal = lastStatus.done || TERMINAL_STATUSES.has(lastStatus.status);
478
522
  if (terminal && logs.done) return finishRun(fixtureId, runId, lastStatus, startTime, tailLines, options);
479
- if (!terminal && !options.quiet) await watchRunHolds(runId, seenHolds, () => heldCtx, (c) => heldCtx = c, options);
523
+ if (!terminal) await watchRunHolds(runId, seenHolds, () => heldCtx, (c) => heldCtx = c, options);
480
524
  await new Promise((resolve) => setTimeout(resolve, POLL_INTERVAL_MS));
481
525
  }
482
526
  return {
@@ -506,10 +550,12 @@ async function watchRunHolds(runId, seenHolds, getCtx, setCtx, options) {
506
550
  if (!ctx) return;
507
551
  const holds = await listHeldRunsForRun(ctx, runId);
508
552
  if (holds.length === 0) return;
553
+ const quiet = Boolean(options.quiet);
509
554
  await handleNewHolds({
510
555
  holds,
511
556
  seen: seenHolds,
512
- isTty: Boolean(process.stdin.isTTY && process.stdout.isTTY),
557
+ isTty: quiet ? false : Boolean(process.stdin.isTTY && process.stdout.isTTY),
558
+ output: quiet ? (line) => void process.stderr.write(line + "\n") : (line) => logger.info(line),
513
559
  approveAll: Boolean(options.approveAll),
514
560
  confirm: (message) => confirm({
515
561
  message,
@@ -589,7 +635,11 @@ async function runDirectWorkflow(workflowName, options) {
589
635
  try {
590
636
  const overlay = await prepareOverlay(options);
591
637
  const uploaded = await initAndUpload(ctx, overlay, options);
592
- const payload = { repository: { full_name: `local/${path.basename(overlay.repoRoot)}` } };
638
+ const identity = buildLocalRepoIdentity(overlay.repoRoot);
639
+ const payload = { repository: {
640
+ full_name: identity.repoIdentifier,
641
+ provider: identity.provider
642
+ } };
593
643
  const encrypted = await buildEncryptedSecrets(overlay.kiciDir, options.envFlags, options.context, uploaded.publicKey);
594
644
  const triggerResult = await ctx.client.trigger(ctx.orgId, ctx.target, {
595
645
  fixtureId,
@@ -644,6 +694,6 @@ function displayRemoteResults(results) {
644
694
  logger.info("");
645
695
  }
646
696
  //#endregion
647
- export { buildDispatchInputs, buildTargetSelector, lookupDispatchInputsDescriptor, runLocalCommand, runRemoteCommand };
697
+ export { buildDispatchInputs, buildTargetSelector, lookupDispatchInputsDescriptor, printRunLocalUsage, runLocalCommand, runRemoteCommand, withStdoutOnStderr };
648
698
 
649
699
  //# sourceMappingURL=run.js.map
@@ -1,4 +1,4 @@
1
- import "../../chunk-BTugEXQM.js";
1
+ import "../../rolldown-runtime-ClRpJifh.js";
2
2
  import { DashboardClient, DashboardClientError } from "../../remote/dashboard-client.js";
3
3
  import pc from "picocolors";
4
4
  import { logger, toErrorMessage } from "@kici-dev/core";
@@ -1,4 +1,4 @@
1
- import "../../chunk-BTugEXQM.js";
1
+ import "../../rolldown-runtime-ClRpJifh.js";
2
2
  import { DashboardClient, DashboardClientError } from "../../remote/dashboard-client.js";
3
3
  import { colorStatus, formatDuration as formatDuration$1, relativeTime, renderTable } from "../../remote/render.js";
4
4
  import pc from "picocolors";
@@ -1,4 +1,4 @@
1
- import "../../chunk-BTugEXQM.js";
1
+ import "../../rolldown-runtime-ClRpJifh.js";
2
2
  import { DashboardClient, DashboardClientError } from "../../remote/dashboard-client.js";
3
3
  import { colorStatus } from "../../remote/render.js";
4
4
  import pc from "picocolors";
@@ -1,4 +1,4 @@
1
- import "../../chunk-BTugEXQM.js";
1
+ import "../../rolldown-runtime-ClRpJifh.js";
2
2
  import { DashboardClient, DashboardClientError } from "../../remote/dashboard-client.js";
3
3
  import pc from "picocolors";
4
4
  import { logger, toErrorMessage } from "@kici-dev/core";
@@ -1,4 +1,4 @@
1
- import "../../chunk-BTugEXQM.js";
1
+ import "../../rolldown-runtime-ClRpJifh.js";
2
2
  import { DashboardClient, DashboardClientError } from "../../remote/dashboard-client.js";
3
3
  import { RunHistory } from "../../remote/history.js";
4
4
  import { colorStatus, formatDuration as formatDuration$1, relativeTime } from "../../remote/render.js";
@@ -1,4 +1,4 @@
1
- import "../chunk-BTugEXQM.js";
1
+ import "../rolldown-runtime-ClRpJifh.js";
2
2
  import { DashboardClient, DashboardClientError } from "../remote/dashboard-client.js";
3
3
  import pc from "picocolors";
4
4
  import { toErrorMessage } from "@kici-dev/core";
@@ -1,4 +1,4 @@
1
- import "../chunk-BTugEXQM.js";
1
+ import "../rolldown-runtime-ClRpJifh.js";
2
2
  import { loadGlobalConfig } from "../remote/config.js";
3
3
  import { DashboardClient, DashboardClientError } from "../remote/dashboard-client.js";
4
4
  import { generateSecretsDts } from "../generators/secrets-dts.js";
@@ -1,7 +1,10 @@
1
1
  export interface VerifyAttestationOptions {
2
2
  /** Path or `http(s)` URL to the attestation bundle JSON. Required. */
3
3
  bundle?: string;
4
- /** Trusted issuer URL (online discovery) or a self-contained `{ issuer, jwks }` file. Required. */
4
+ /**
5
+ * Trusted issuer URL (online discovery) or a self-contained `{ issuer, jwks }`
6
+ * file. Optional — defaults to the hosted KiCI Platform's provenance issuer.
7
+ */
5
8
  trustRoot?: string;
6
9
  /** Expected token audience (defaults to the KiCI provenance audience). */
7
10
  audience?: string;
@@ -1,5 +1,6 @@
1
- import "../chunk-BTugEXQM.js";
1
+ import "../rolldown-runtime-ClRpJifh.js";
2
2
  import { resolveTrustRoot } from "../provenance-trust-root.js";
3
+ import "../remote/prod-defaults.js";
3
4
  import pc from "picocolors";
4
5
  import { readFile } from "node:fs/promises";
5
6
  import { logger, sha256File, toErrorMessage } from "@kici-dev/core";
@@ -7,13 +8,18 @@ import { KICI_PROVENANCE_AUDIENCE } from "@kici-dev/engine/provenance/bundle";
7
8
  import { verifyKiciBundle } from "@kici-dev/engine/provenance/verify";
8
9
  //#region src/commands/verify-attestation.ts
9
10
  /**
10
- * `kici verify-attestation [artifact] --bundle <path|url> --trust-root <url|file>`
11
+ * `kici verify-attestation [artifact] --bundle <path|url> [--trust-root <url|file>]`
11
12
  *
12
13
  * Offline verification of a KiCI-signed provenance bundle: read the bundle,
13
- * resolve the trusted issuer + JWKS out-of-band (`--trust-root`), optionally
14
- * digest the artifact, and hand everything to the shared browser-safe
15
- * `verifyKiciBundle` core in `@kici-dev/engine`. The engine owns all crypto;
16
- * this command is the thin Node wrapper (fs / fetch / artifact digest / output).
14
+ * resolve the trusted issuer + JWKS out-of-band, optionally digest the artifact,
15
+ * and hand everything to the shared browser-safe `verifyKiciBundle` core in
16
+ * `@kici-dev/engine`. The engine owns all crypto; this command is the thin Node
17
+ * wrapper (fs / fetch / artifact digest / output).
18
+ *
19
+ * `--trust-root` is optional: when omitted it defaults to the hosted KiCI
20
+ * Platform's provenance issuer, so the common case (verifying a bundle attested
21
+ * on the hosted platform) needs no flag. Pass `--trust-root` to verify against a
22
+ * different environment (e.g. staging) or an offline `{ issuer, jwks }` file.
17
23
  *
18
24
  * Returns a boolean (verified) so `cli.ts` can map it to an exit code (0/1).
19
25
  */
@@ -23,12 +29,22 @@ async function verifyAttestationCommand(artifact, options = {}) {
23
29
  logger.error(pc.red("Error: --bundle <path|url> is required"));
24
30
  return false;
25
31
  }
26
- if (!options.trustRoot) {
27
- logger.error(pc.red("Error: --trust-root <url|file> is required"));
28
- return false;
29
- }
32
+ const trustRoot = options.trustRoot ?? "https://api.kici.dev";
33
+ const usingDefault = !options.trustRoot;
34
+ if (usingDefault) logger.info(pc.gray(`Using default trust root ${trustRoot} (pass --trust-root to override)`));
30
35
  const bundle = JSON.parse(await readBundle(options.bundle));
31
- const { issuer, jwks } = await resolveTrustRoot(options.trustRoot);
36
+ let resolved;
37
+ try {
38
+ resolved = await resolveTrustRoot(trustRoot);
39
+ } catch (error) {
40
+ const msg = toErrorMessage(error);
41
+ if (usingDefault && /\b503\b/.test(msg)) {
42
+ logger.error(pc.red(`Error: build provenance is not enabled on the hosted KiCI platform yet (${trustRoot} returned 503). Pass --trust-root to verify against another environment (e.g. staging) or an offline { issuer, jwks } file.`));
43
+ return false;
44
+ }
45
+ throw error;
46
+ }
47
+ const { issuer, jwks } = resolved;
32
48
  const expectedDigest = artifact ? {
33
49
  alg: "sha256",
34
50
  hex: await sha256File(artifact)
@@ -47,7 +63,13 @@ async function verifyAttestationCommand(artifact, options = {}) {
47
63
  if (result.verified) {
48
64
  logger.info(`${pc.green("PASS")} provenance verified (issuer ${issuer})`);
49
65
  const c = result.claims ?? {};
50
- logger.info(pc.gray(` repository=${c.repository} ref=${c.ref} sha=${c.sha} run=${c.kici_run_id} job=${c.kici_job_id}`));
66
+ logger.info(pc.gray(` origin org=${c.org_id ?? "unknown"}`));
67
+ if (c.source_origin === "run-remote") logger.info(pc.bold(pc.yellow(" SOURCE: kici run remote (local working-tree overlay — repository/ref/sha are caller-supplied, not a triggered VCS commit)")));
68
+ else logger.info(pc.gray(` source: ${c.source_origin ?? "triggered"}`));
69
+ const origin = result.attestationOrigin ?? "live";
70
+ if (origin === "deferred") logger.info(pc.bold(pc.yellow(" ATTESTATION: deferred — the build facts were sealed at build time; the identity token was minted later (after a transient Platform outage), bound to the frozen statement by hash.")));
71
+ else if (origin === "offline-backfill") logger.info(pc.bold(pc.yellow(" ATTESTATION: offline-backfill — the run was ingested while the Platform was down; its run/job rows were backfilled and the token minted later. The org id is the authoritative anchor; the temporal gap is disclosed.")));
72
+ logger.info(pc.gray(` repository=${c.repository} ref=${c.ref} sha=${c.sha} provider=${c.provider ?? "unknown"} run=${c.kici_run_id} job=${c.kici_job_id}`));
51
73
  } else logger.error(`${pc.red("FAIL")} provenance NOT verified: ${result.failures.join(", ")}`);
52
74
  return result.verified;
53
75
  } catch (error) {
@@ -1,4 +1,4 @@
1
- import "../chunk-BTugEXQM.js";
1
+ import "../rolldown-runtime-ClRpJifh.js";
2
2
  import { resolveKiciDir } from "../execution/executor.js";
3
3
  import "../execution/index.js";
4
4
  import { compileCommand } from "./compile.js";
@@ -1,4 +1,4 @@
1
- import "../chunk-BTugEXQM.js";
1
+ import "../rolldown-runtime-ClRpJifh.js";
2
2
  import { formatRelativeTime } from "../format.js";
3
3
  import { DashboardClient, DashboardClientError } from "../remote/dashboard-client.js";
4
4
  import pc from "picocolors";
@@ -1,4 +1,4 @@
1
- import "../chunk-BTugEXQM.js";
1
+ import "../rolldown-runtime-ClRpJifh.js";
2
2
  import pc from "picocolors";
3
3
  //#region src/errors/capability-gap.ts
4
4
  /**
@@ -1,4 +1,4 @@
1
- import "../chunk-BTugEXQM.js";
1
+ import "../rolldown-runtime-ClRpJifh.js";
2
2
  import pc from "picocolors";
3
3
  //#region src/errors/formatter.ts
4
4
  /**
@@ -1,4 +1,4 @@
1
- import "../chunk-BTugEXQM.js";
1
+ import "../rolldown-runtime-ClRpJifh.js";
2
2
  import { compilerError, formatError, isCompilerError } from "./formatter.js";
3
3
  import { CapabilityGapError, formatCapabilityGapError } from "./capability-gap.js";
4
4
  export { CapabilityGapError, compilerError, formatCapabilityGapError, formatError, isCompilerError };
@@ -19,12 +19,11 @@ export interface DiscoveryResult {
19
19
  * Execute a TypeScript config file and extract workflow definitions.
20
20
  *
21
21
  * Process:
22
- * 1. Read TypeScript source from disk
23
- * 2. Transform to ESM JavaScript via rolldown (in-memory)
24
- * 3. Write temp file for Node.js dynamic import (required by ESM spec)
25
- * 4. Dynamic import the compiled module
26
- * 5. Extract and return workflow definitions
27
- * 6. Clean up temp file
22
+ * 1. Resolve the path and verify the file exists and is readable
23
+ * 2. Register the oxc-transform TS loader hook and dynamic-import the module
24
+ * (TypeScript compiled on the fly by the hook no bundling, no temp files)
25
+ * 3. Extract workflow definitions from the module's default/named exports
26
+ * 4. Return the workflows with source tracking
28
27
  *
29
28
  * @param configPath - Path to workflow file (relative or absolute)
30
29
  * @returns Workflows exported from the config
@@ -1,4 +1,4 @@
1
- import "../chunk-BTugEXQM.js";
1
+ import "../rolldown-runtime-ClRpJifh.js";
2
2
  import { compilerError } from "../errors/formatter.js";
3
3
  import "../errors/index.js";
4
4
  import { ensureTsLoaderHook } from "./ts-loader.js";
@@ -47,12 +47,11 @@ async function loadModule(entryPoint, errorContext) {
47
47
  * Execute a TypeScript config file and extract workflow definitions.
48
48
  *
49
49
  * Process:
50
- * 1. Read TypeScript source from disk
51
- * 2. Transform to ESM JavaScript via rolldown (in-memory)
52
- * 3. Write temp file for Node.js dynamic import (required by ESM spec)
53
- * 4. Dynamic import the compiled module
54
- * 5. Extract and return workflow definitions
55
- * 6. Clean up temp file
50
+ * 1. Resolve the path and verify the file exists and is readable
51
+ * 2. Register the oxc-transform TS loader hook and dynamic-import the module
52
+ * (TypeScript compiled on the fly by the hook no bundling, no temp files)
53
+ * 3. Extract workflow definitions from the module's default/named exports
54
+ * 4. Return the workflows with source tracking
56
55
  *
57
56
  * @param configPath - Path to workflow file (relative or absolute)
58
57
  * @returns Workflows exported from the config
@@ -1,3 +1,3 @@
1
- import "../chunk-BTugEXQM.js";
1
+ import "../rolldown-runtime-ClRpJifh.js";
2
2
  import { discoverWorkflows, executeConfig, resolveKiciDir } from "./executor.js";
3
3
  export { discoverWorkflows, executeConfig, resolveKiciDir };
@@ -1,23 +1,13 @@
1
1
  /**
2
- * SDK aliasing for development mode
2
+ * SDK development-mode path resolution.
3
3
  *
4
- * Enables automatic aliasing of @kici-dev/sdk imports to a local development repository when:
4
+ * Resolves a local @kici-dev/sdk checkout for IDE tsconfig `paths` mappings when:
5
5
  * 1. sdkPath is configured in .kici/package.json
6
6
  * 2. Current project is NOT the kici development repo itself
7
7
  *
8
- * This allows developers to test SDK changes in real-time without publishing or manual linking.
8
+ * This gives developers editor autocomplete against local SDK source without
9
+ * publishing or manual linking.
9
10
  */
10
- /**
11
- * Get rolldown alias configuration for SDK development mode.
12
- *
13
- * Returns alias mapping if:
14
- * - sdkPath is configured in .kici/package.json
15
- * - Current project is NOT the kici repo itself
16
- * - SDK build exists at configured path
17
- *
18
- * @returns Alias config for rolldown (empty object if aliasing disabled)
19
- */
20
- export declare function getSdkAliasConfig(): Promise<Record<string, string>>;
21
11
  /**
22
12
  * Get TypeScript path mappings for IDE support.
23
13
  *