@kici-dev/compiler 0.1.26 → 0.2.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 (199) hide show
  1. package/dist/auth/headless-detect.d.ts +14 -5
  2. package/dist/auth/headless-detect.js +50 -9
  3. package/dist/cli-banner.d.ts +6 -3
  4. package/dist/cli-banner.js +13 -5
  5. package/dist/cli.js +180 -48
  6. package/dist/commands/check-mode.d.ts +1 -1
  7. package/dist/commands/compile.js +31 -7
  8. package/dist/commands/diagnostics.js +14 -2
  9. package/dist/commands/doctor.d.ts +64 -0
  10. package/dist/commands/doctor.js +413 -0
  11. package/dist/commands/endpoints.js +6 -0
  12. package/dist/commands/fixture.js +13 -0
  13. package/dist/commands/hook.js +3 -2
  14. package/dist/commands/index.d.ts +13 -1
  15. package/dist/commands/index.js +10 -3
  16. package/dist/commands/init-host-os.d.ts +34 -0
  17. package/dist/commands/init-host-os.js +44 -0
  18. package/dist/commands/init.d.ts +4 -0
  19. package/dist/commands/init.js +160 -37
  20. package/dist/commands/local-trust-root.d.ts +6 -0
  21. package/dist/commands/local-trust-root.js +52 -0
  22. package/dist/commands/local.d.ts +65 -0
  23. package/dist/commands/local.js +206 -0
  24. package/dist/commands/login.d.ts +2 -0
  25. package/dist/commands/login.js +41 -1
  26. package/dist/commands/logout.js +7 -0
  27. package/dist/commands/notifications.d.ts +61 -0
  28. package/dist/commands/notifications.js +274 -0
  29. package/dist/commands/preview.js +9 -2
  30. package/dist/commands/run-banner.d.ts +31 -0
  31. package/dist/commands/run-banner.js +25 -0
  32. package/dist/commands/run-routed.d.ts +53 -0
  33. package/dist/commands/run-routed.js +185 -0
  34. package/dist/commands/run.d.ts +0 -17
  35. package/dist/commands/run.js +44 -58
  36. package/dist/commands/runs/artifacts/download.d.ts +24 -0
  37. package/dist/commands/runs/artifacts/download.js +154 -0
  38. package/dist/commands/runs/artifacts/list.d.ts +5 -0
  39. package/dist/commands/runs/artifacts/list.js +47 -0
  40. package/dist/commands/runs/cancel.js +2 -2
  41. package/dist/commands/runs/list.js +8 -2
  42. package/dist/commands/secrets-list.d.ts +2 -2
  43. package/dist/commands/secrets-list.js +4 -4
  44. package/dist/commands/types.d.ts +3 -3
  45. package/dist/commands/types.js +4 -4
  46. package/dist/commands/verify-attestation.d.ts +3 -1
  47. package/dist/commands/verify-attestation.js +18 -7
  48. package/dist/errors/formatter.d.ts +14 -1
  49. package/dist/errors/formatter.js +13 -3
  50. package/dist/errors/index.d.ts +2 -1
  51. package/dist/errors/index.js +3 -2
  52. package/dist/errors/source-location.d.ts +20 -0
  53. package/dist/errors/source-location.js +45 -0
  54. package/dist/execution/executor.js +32 -12
  55. package/dist/fixtures/defaults/index.js +2 -1
  56. package/dist/generators/secrets-dts.d.ts +9 -9
  57. package/dist/generators/secrets-dts.js +12 -12
  58. package/dist/llm-context/llms-architecture.txt +50 -21
  59. package/dist/llm-context/llms-cli.txt +2667 -1454
  60. package/dist/llm-context/llms-features.txt +484 -414
  61. package/dist/llm-context/llms-full.txt +6703 -4687
  62. package/dist/llm-context/llms-getting-started.txt +311 -55
  63. package/dist/llm-context/llms-patterns.txt +17 -29
  64. package/dist/llm-context/llms-providers.txt +10 -1
  65. package/dist/llm-context/llms-sdk-runtime.txt +2013 -0
  66. package/dist/llm-context/llms-sdk.txt +596 -2157
  67. package/dist/llm-context/llms.txt +31 -17
  68. package/dist/local-plane/orchestrator-process.d.ts +70 -0
  69. package/dist/local-plane/orchestrator-process.js +129 -0
  70. package/dist/local-plane/os-mismatch-hint.d.ts +16 -0
  71. package/dist/local-plane/os-mismatch-hint.js +34 -0
  72. package/dist/local-plane/paths.d.ts +39 -0
  73. package/dist/local-plane/paths.js +54 -0
  74. package/dist/local-plane/plane-liveness.d.ts +68 -0
  75. package/dist/local-plane/plane-liveness.js +145 -0
  76. package/dist/local-plane/plane-manager.d.ts +193 -0
  77. package/dist/local-plane/plane-manager.js +480 -0
  78. package/dist/local-plane/plane-seed.d.ts +76 -0
  79. package/dist/local-plane/plane-seed.js +59 -0
  80. package/dist/local-plane/plane-trigger.d.ts +71 -0
  81. package/dist/local-plane/plane-trigger.js +110 -0
  82. package/dist/local-plane/platform-attach.d.ts +53 -0
  83. package/dist/local-plane/platform-attach.js +107 -0
  84. package/dist/local-plane/port-holder.d.ts +78 -0
  85. package/dist/local-plane/port-holder.js +227 -0
  86. package/dist/local-plane/postgres.d.ts +56 -0
  87. package/dist/local-plane/postgres.js +187 -0
  88. package/dist/local-plane/resolve-plane.d.ts +37 -0
  89. package/dist/local-plane/resolve-plane.js +76 -0
  90. package/dist/local-plane/run-follow.d.ts +61 -0
  91. package/dist/local-plane/run-follow.js +151 -0
  92. package/dist/local-plane/scaler-config.d.ts +68 -0
  93. package/dist/local-plane/scaler-config.js +132 -0
  94. package/dist/local-plane/secret-seed.d.ts +59 -0
  95. package/dist/local-plane/secret-seed.js +112 -0
  96. package/dist/local-plane/source-provider.d.ts +43 -0
  97. package/dist/local-plane/source-provider.js +159 -0
  98. package/dist/local-plane/trusted-routing.d.ts +32 -0
  99. package/dist/local-plane/trusted-routing.js +47 -0
  100. package/dist/lockfile/generator.d.ts +14 -1
  101. package/dist/lockfile/generator.js +103 -37
  102. package/dist/lockfile/index.d.ts +3 -1
  103. package/dist/lockfile/index.js +3 -2
  104. package/dist/lockfile/purity-diagnostics.d.ts +31 -0
  105. package/dist/lockfile/purity-diagnostics.js +52 -0
  106. package/dist/postinstall.js +2 -1
  107. package/dist/remote/artifact-extract.d.ts +8 -0
  108. package/dist/remote/artifact-extract.js +58 -0
  109. package/dist/remote/config.d.ts +21 -3
  110. package/dist/remote/config.js +24 -5
  111. package/dist/remote/dashboard-client.d.ts +46 -9
  112. package/dist/remote/dashboard-client.js +54 -11
  113. package/dist/remote/fs-case.d.ts +21 -0
  114. package/dist/remote/fs-case.js +45 -0
  115. package/dist/remote/history.d.ts +9 -3
  116. package/dist/remote/history.js +79 -10
  117. package/dist/remote/local-repo-identity.d.ts +1 -1
  118. package/dist/remote/local-repo-identity.js +2 -1
  119. package/dist/remote/notifications-client.d.ts +149 -0
  120. package/dist/remote/notifications-client.js +103 -0
  121. package/dist/remote/oauth.d.ts +13 -0
  122. package/dist/remote/oauth.js +31 -5
  123. package/dist/remote/output/summary.js +76 -14
  124. package/dist/remote/platform-client.d.ts +1 -1
  125. package/dist/remote/render.js +30 -9
  126. package/dist/{local-executor → remote}/secret-loader.d.ts +1 -1
  127. package/dist/{local-executor → remote}/secret-loader.js +4 -4
  128. package/dist/remote/secret-upload.d.ts +1 -1
  129. package/dist/remote/secret-upload.js +2 -2
  130. package/dist/remote/uploader.d.ts +1 -1
  131. package/dist/remote/uploader.js +7 -6
  132. package/dist/templates/agents-md.d.ts +1 -1
  133. package/dist/templates/agents-md.js +8 -8
  134. package/dist/templates/index.d.ts +1 -1
  135. package/dist/templates/index.js +2 -2
  136. package/dist/templates/package-json.d.ts +15 -0
  137. package/dist/templates/package-json.js +26 -5
  138. package/dist/test-runner/dry-run.d.ts +2 -1
  139. package/dist/test-runner/dry-run.js +18 -1
  140. package/dist/test-runner/event-types.d.ts +2 -0
  141. package/dist/test-runner/event-types.js +3 -0
  142. package/dist/test-runner/job-executor.d.ts +1 -0
  143. package/dist/test-runner/job-executor.js +82 -44
  144. package/dist/test-runner/output-formatter.d.ts +5 -2
  145. package/dist/test-runner/output-formatter.js +6 -4
  146. package/dist/test-runner/payload-builder.d.ts +7 -1
  147. package/dist/test-runner/payload-builder.js +11 -2
  148. package/dist/test-runner/rule-evaluator.d.ts +7 -3
  149. package/dist/test-runner/rule-evaluator.js +13 -12
  150. package/dist/{local-executor → test-runner}/runs-on-display.js +1 -1
  151. package/dist/test-runner/step-context.d.ts +23 -5
  152. package/dist/test-runner/step-context.js +29 -119
  153. package/dist/types.d.ts +26 -7
  154. package/dist/types.js +4 -2
  155. package/dist/validation/index.d.ts +2 -0
  156. package/dist/validation/index.js +2 -1
  157. package/dist/validation/typecheck.d.ts +28 -0
  158. package/dist/validation/typecheck.js +110 -0
  159. package/dist/validation/validator.d.ts +9 -4
  160. package/dist/validation/validator.js +38 -44
  161. package/package.json +13 -13
  162. package/sbom.spdx.json +9311 -1528
  163. package/dist/assets/api-TJJVHrjC.json +0 -118
  164. package/dist/assets/descriptor-BTtjzN9L.json +0 -1382
  165. package/dist/assets/package-BpQF9kR8.json +0 -74
  166. package/dist/assets/package-Ceo2h27X.json +0 -89
  167. package/dist/assets/source_context-D0atuL28.json +0 -20
  168. package/dist/assets/type-BFqO8SCZ.json +0 -202
  169. package/dist/commands/cancel.d.ts +0 -22
  170. package/dist/commands/detect-package-manager.d.ts +0 -42
  171. package/dist/commands/held-run-resolve.d.ts +0 -50
  172. package/dist/commands/status.d.ts +0 -34
  173. package/dist/commands/test.d.ts +0 -88
  174. package/dist/errors/codes.d.ts +0 -25
  175. package/dist/local-executor/dag-scheduler.d.ts +0 -44
  176. package/dist/local-executor/dag-scheduler.js +0 -183
  177. package/dist/local-executor/index.d.ts +0 -23
  178. package/dist/local-executor/index.js +0 -378
  179. package/dist/local-executor/job-runner.d.ts +0 -47
  180. package/dist/local-executor/job-runner.js +0 -411
  181. package/dist/local-executor/materializer.d.ts +0 -44
  182. package/dist/local-executor/materializer.js +0 -132
  183. package/dist/local-executor/output-streamer.d.ts +0 -31
  184. package/dist/local-executor/output-streamer.js +0 -168
  185. package/dist/local-executor/payload-generator.d.ts +0 -16
  186. package/dist/local-executor/payload-generator.js +0 -138
  187. package/dist/local-executor/picker.d.ts +0 -33
  188. package/dist/local-executor/picker.js +0 -109
  189. package/dist/local-executor/to-event-payload.d.ts +0 -16
  190. package/dist/local-executor/to-event-payload.js +0 -21
  191. package/dist/local-executor/types.d.ts +0 -93
  192. package/dist/local-executor/types.js +0 -2
  193. package/dist/local-executor/workflow-lock.d.ts +0 -82
  194. package/dist/local-executor/workflow-lock.js +0 -0
  195. package/dist/package-F7UXSDHW.json +0 -74
  196. package/dist/remote/client.d.ts +0 -210
  197. package/dist/remote/observer.d.ts +0 -81
  198. package/dist/test-runner/summary.d.ts +0 -7
  199. /package/dist/{local-executor → test-runner}/runs-on-display.d.ts +0 -0
@@ -147,7 +147,8 @@ async function buildEventPayload(eventArg, options) {
147
147
  payload: mergedPayload,
148
148
  targetBranch,
149
149
  sourceBranch,
150
- changedFiles: options.files ?? []
150
+ changedFiles: options.files ?? [],
151
+ changedFilesStatus: options.changedFilesStatus ?? "fetched"
151
152
  };
152
153
  }
153
154
  /**
@@ -157,6 +158,7 @@ function isInternalEventType(eventType) {
157
158
  return [
158
159
  "kici_event",
159
160
  "workflow_complete",
161
+ "workflows_failed_batch",
160
162
  "job_complete",
161
163
  "generic_webhook",
162
164
  "schedule",
@@ -182,6 +184,12 @@ async function buildInternalEventPayload(eventType, options) {
182
184
  status: eventType.status
183
185
  };
184
186
  break;
187
+ case "workflows_failed_batch":
188
+ payload = {
189
+ total: 0,
190
+ runs: []
191
+ };
192
+ break;
185
193
  case "job_complete":
186
194
  payload = {
187
195
  workflowName: eventType.workflowName,
@@ -207,7 +215,8 @@ async function buildInternalEventPayload(eventType, options) {
207
215
  action: void 0,
208
216
  payload,
209
217
  targetBranch: "main",
210
- changedFiles: options.files ?? []
218
+ changedFiles: options.files ?? [],
219
+ changedFilesStatus: options.changedFilesStatus ?? "fetched"
211
220
  };
212
221
  }
213
222
  //#endregion
@@ -1,9 +1,13 @@
1
- import type { Rule, RuleContext, EventPayload } from '@kici-dev/sdk';
1
+ import type { Rule, RuleContext, CreateRuleContextInput } from '@kici-dev/sdk';
2
2
  import type { RuleEvaluationResult } from '@kici-dev/sdk';
3
3
  /**
4
- * Create RuleContext for rule evaluation.
4
+ * Create a RuleContext for `kici test` rule evaluation. Delegates to the shared
5
+ * SDK factory (single source of truth), defaulting `env` to the process
6
+ * environment — the test-runner exposes the developer's real env to rules — and
7
+ * `changedFilesStatus` to `'fetched'` so an author-supplied (or empty) test
8
+ * changeset is a genuine diff and `ctx.changedFiles` never throws.
5
9
  */
6
- export declare function createRuleContext(event: EventPayload, changedFiles?: string[], dispatchInputs?: Readonly<Record<string, string | number | boolean | null>>): RuleContext;
10
+ export declare function createRuleContext(input: CreateRuleContextInput): RuleContext;
7
11
  /**
8
12
  * Evaluate rules with formatting output.
9
13
  * Wraps the SDK's evaluateRules() with a callback that logs each rule result.
@@ -1,21 +1,22 @@
1
1
  import "../rolldown-runtime-ClRpJifh.js";
2
2
  import { formatter } from "./output-formatter.js";
3
- import { evaluateRules } from "@kici-dev/sdk";
3
+ import { createRuleContext as createRuleContext$1, evaluateRules } from "@kici-dev/sdk";
4
4
  import { initZx } from "@kici-dev/core";
5
- import { $ } from "zx";
6
5
  //#region src/test-runner/rule-evaluator.ts
7
6
  initZx();
8
7
  /**
9
- * Create RuleContext for rule evaluation.
8
+ * Create a RuleContext for `kici test` rule evaluation. Delegates to the shared
9
+ * SDK factory (single source of truth), defaulting `env` to the process
10
+ * environment — the test-runner exposes the developer's real env to rules — and
11
+ * `changedFilesStatus` to `'fetched'` so an author-supplied (or empty) test
12
+ * changeset is a genuine diff and `ctx.changedFiles` never throws.
10
13
  */
11
- function createRuleContext(event, changedFiles = [], dispatchInputs = {}) {
12
- return {
13
- event,
14
- changedFiles,
15
- env: { ...process.env },
16
- dispatchInputs,
17
- $
18
- };
14
+ function createRuleContext(input) {
15
+ return createRuleContext$1({
16
+ ...input,
17
+ env: input.env ?? { ...process.env },
18
+ changedFilesStatus: input.changedFilesStatus ?? "fetched"
19
+ });
19
20
  }
20
21
  /**
21
22
  * Evaluate rules with formatting output.
@@ -23,7 +24,7 @@ function createRuleContext(event, changedFiles = [], dispatchInputs = {}) {
23
24
  */
24
25
  async function evaluateRulesWithFormatting(rules, context, jobName) {
25
26
  return evaluateRules(rules, context, jobName, (result) => {
26
- formatter.logRuleResult(jobName, result.label, result.passed);
27
+ formatter.logRuleResult(jobName, result);
27
28
  });
28
29
  }
29
30
  //#endregion
@@ -1,5 +1,5 @@
1
1
  import "../rolldown-runtime-ClRpJifh.js";
2
- //#region src/local-executor/runs-on-display.ts
2
+ //#region src/test-runner/runs-on-display.ts
3
3
  /** Render one selector element (string label or RegExp) for the local display string. */
4
4
  function runsOnElementString(el) {
5
5
  return el instanceof RegExp ? el.toString() : el;
@@ -1,15 +1,33 @@
1
1
  import type { StepContext, WorkflowInfo, JobInfo, MatrixValues } from '@kici-dev/sdk';
2
+ /** Handle returned by {@link createStepContext}. */
3
+ export interface LocalStepContext {
4
+ /** The built step context, threaded into every step of the job. */
5
+ ctx: StepContext;
6
+ /**
7
+ * Drain the job's temp scope (and secrets state). Call once at job end —
8
+ * success, failure, or throw — to reclaim every `ctx.mktemp`/`ctx.mktempFile`
9
+ * allocation the job made. Delegates to the shared builder's `dispose`.
10
+ */
11
+ dispose: () => Promise<void>;
12
+ }
2
13
  /**
3
14
  * Create a step context for local test execution.
4
15
  *
5
- * `repoRoot` pins `ctx.$` to the workflow's repository root so steps running
6
- * via local-dispatch behave the same as on the agent path (see
16
+ * `repoRoot` pins `ctx.$` to the workflow's repository root so steps running via
17
+ * local-dispatch behave the same as on the agent path (see
7
18
  * `packages/agent/src/execution/sandbox/workflow-runner.ts`). Without this,
8
- * `ctx.$` would inherit `process.cwd()` — i.e. wherever the user invoked
9
- * `kici` — which silently breaks any step that uses relative paths.
19
+ * `ctx.$` would inherit `process.cwd()` — i.e. wherever the user invoked `kici`
20
+ * — which silently breaks any step that uses relative paths.
21
+ *
22
+ * This is a thin adapter over the shared `@kici-dev/sdk/testing` builder — the
23
+ * single source of truth for constructing a test step context — supplying the
24
+ * local runner's formatter-backed logger. The shared builder owns the
25
+ * job-scoped temp allocator backing `ctx.mktemp`/`ctx.mktempFile`; the returned
26
+ * `dispose` surfaces its drain so the caller (`executeJob`) can reclaim the
27
+ * job's temp dirs at job end rather than only via the exit backstop.
10
28
  */
11
29
  export declare function createStepContext(workflowInfo: WorkflowInfo, jobInfo: JobInfo, repoRoot: string, inputs?: Record<string, unknown>, matrix?: MatrixValues, testSecrets?: {
12
30
  flat: Record<string, string>;
13
31
  contexts: Record<string, Record<string, string>>;
14
- }, environment?: string, rawPayload?: Record<string, unknown>, provider?: string, dispatchInputs?: Readonly<Record<string, string | number | boolean | null>>, signal?: AbortSignal): StepContext;
32
+ }, context?: string, rawPayload?: Record<string, unknown>, provider?: string, dispatchInputs?: Readonly<Record<string, string | number | boolean | null>>, signal?: AbortSignal): LocalStepContext;
15
33
  //# sourceMappingURL=step-context.d.ts.map
@@ -1,15 +1,9 @@
1
1
  import "../rolldown-runtime-ClRpJifh.js";
2
2
  import { formatter } from "./output-formatter.js";
3
- import { join } from "node:path";
4
- import { chmodSync, mkdtempSync, rmSync, writeFileSync } from "node:fs";
5
- import { createStepSecrets, resolveJobOutputs, resolveStepOutputs } from "@kici-dev/sdk";
6
- import { initZx } from "@kici-dev/core";
7
- import { tmpdir } from "node:os";
8
- import { $ } from "zx";
3
+ import { createTestStepContext } from "@kici-dev/sdk/testing";
9
4
  //#region src/test-runner/step-context.ts
10
- initZx();
11
5
  /**
12
- * Create a logger that prefixes output with job name.
6
+ * Create a logger that prefixes output with the job name.
13
7
  */
14
8
  function createTestLogger(jobName) {
15
9
  return {
@@ -36,121 +30,37 @@ function createTestLogger(jobName) {
36
30
  /**
37
31
  * Create a step context for local test execution.
38
32
  *
39
- * `repoRoot` pins `ctx.$` to the workflow's repository root so steps running
40
- * via local-dispatch behave the same as on the agent path (see
33
+ * `repoRoot` pins `ctx.$` to the workflow's repository root so steps running via
34
+ * local-dispatch behave the same as on the agent path (see
41
35
  * `packages/agent/src/execution/sandbox/workflow-runner.ts`). Without this,
42
- * `ctx.$` would inherit `process.cwd()` — i.e. wherever the user invoked
43
- * `kici` — which silently breaks any step that uses relative paths.
36
+ * `ctx.$` would inherit `process.cwd()` — i.e. wherever the user invoked `kici`
37
+ * — which silently breaks any step that uses relative paths.
38
+ *
39
+ * This is a thin adapter over the shared `@kici-dev/sdk/testing` builder — the
40
+ * single source of truth for constructing a test step context — supplying the
41
+ * local runner's formatter-backed logger. The shared builder owns the
42
+ * job-scoped temp allocator backing `ctx.mktemp`/`ctx.mktempFile`; the returned
43
+ * `dispose` surfaces its drain so the caller (`executeJob`) can reclaim the
44
+ * job's temp dirs at job end rather than only via the exit backstop.
44
45
  */
45
- function createStepContext(workflowInfo, jobInfo, repoRoot, inputs = {}, matrix, testSecrets, environment, rawPayload, provider, dispatchInputs = {}, signal = new AbortController().signal) {
46
- const flat = testSecrets?.flat ?? {};
47
- const namespacedSecrets = testSecrets?.contexts ?? {};
48
- const mergedFlat = { ...flat };
49
- for (const contextSecrets of Object.values(namespacedSecrets)) Object.assign(mergedFlat, contextSecrets);
50
- const env = { ...process.env };
51
- const scoped$ = $({ cwd: repoRoot });
52
- let tmpdirPath = null;
53
- const exposedEnvVars = /* @__PURE__ */ new Set();
54
- let mountCounter = 0;
55
- let exitHandlerRegistered = false;
56
- const onProcessExit = () => {
57
- for (const envVar of exposedEnvVars) {
58
- delete env[envVar];
59
- delete process.env[envVar];
60
- }
61
- exposedEnvVars.clear();
62
- if (tmpdirPath !== null) {
63
- try {
64
- rmSync(tmpdirPath, {
65
- recursive: true,
66
- force: true
67
- });
68
- } catch {}
69
- tmpdirPath = null;
70
- }
71
- };
72
- const secretsHandle = createStepSecrets(mergedFlat, env, void 0, {
73
- host: {
74
- async writeMountedFile(args) {
75
- if (tmpdirPath === null) tmpdirPath = mkdtempSync(join(tmpdir(), "kici-secret-files-"));
76
- if (!exitHandlerRegistered) {
77
- process.once("exit", onProcessExit);
78
- exitHandlerRegistered = true;
79
- }
80
- mountCounter += 1;
81
- const filename = args.name ?? `secret-${mountCounter}`;
82
- const filePath = join(tmpdirPath, filename);
83
- writeFileSync(filePath, args.content);
84
- chmodSync(filePath, args.mode);
85
- return filePath;
86
- },
87
- trackExposedEnv(envVar) {
88
- exposedEnvVars.add(envVar);
89
- }
90
- },
91
- cleanup: async () => {
92
- if (exitHandlerRegistered) {
93
- process.off("exit", onProcessExit);
94
- exitHandlerRegistered = false;
95
- }
96
- onProcessExit();
97
- }
98
- });
99
- return {
100
- $: scoped$,
101
- log: createTestLogger(jobInfo.name),
102
- signal,
103
- env,
104
- setEnv: (key, value) => {
105
- env[key] = value;
106
- process.env[key] = value;
107
- },
108
- addPath: (dir) => {
109
- const updated = `${dir}:${env.PATH ?? process.env.PATH ?? ""}`;
110
- env.PATH = updated;
111
- process.env.PATH = updated;
112
- },
113
- inputs,
114
- dispatchInputs,
46
+ function createStepContext(workflowInfo, jobInfo, repoRoot, inputs = {}, matrix, testSecrets, context, rawPayload, provider, dispatchInputs = {}, signal = new AbortController().signal) {
47
+ const { ctx, dispose } = createTestStepContext({
115
48
  workflow: workflowInfo,
116
49
  job: jobInfo,
117
- matrix,
118
- isTestRun: false,
119
- environment,
120
- ...rawPayload && { rawPayload },
121
- ...provider && { provider },
122
- secrets: secretsHandle.secrets,
123
- emit: async () => {
124
- return { deliveryId: "local-test-noop" };
125
- },
126
- outputsOf: (ref) => {
127
- return resolveStepOutputs(ref);
128
- },
129
- jobOutputs: (ref) => {
130
- return resolveJobOutputs(ref);
131
- },
132
- setSecretOutput: () => {},
133
- kici: {
134
- infrastructure: { list: () => Promise.resolve({
135
- scalers: [],
136
- agents: []
137
- }) },
138
- inventory: {
139
- query: () => Promise.resolve([]),
140
- get: () => Promise.resolve(null)
141
- },
142
- oidc: { token: () => Promise.reject(/* @__PURE__ */ new Error("ctx.kici.oidc.token() is not available in the local test runner")) },
143
- host: { requestReboot: () => Promise.reject(/* @__PURE__ */ new Error("ctx.kici.host.requestReboot() is not available in the local test runner")) },
144
- bootstrap: {
145
- ensureInitRunner: () => Promise.reject(/* @__PURE__ */ new Error("ctx.kici.bootstrap.ensureInitRunner() is not available in the local test runner")),
146
- preBootSend: () => Promise.reject(/* @__PURE__ */ new Error("ctx.kici.bootstrap.preBootSend() is not available in the local test runner"))
147
- }
148
- },
149
- cache: {
150
- restore: async () => ({ hit: false }),
151
- save: async () => {}
152
- },
153
- attestProvenance: () => Promise.reject(/* @__PURE__ */ new Error("ctx.attestProvenance() is not available in the local test runner"))
50
+ repoRoot,
51
+ inputs,
52
+ dispatchInputs,
53
+ signal,
54
+ log: createTestLogger(jobInfo.name),
55
+ secrets: testSecrets,
56
+ ...matrix !== void 0 && { matrix },
57
+ ...context !== void 0 && { context },
58
+ ...rawPayload !== void 0 && { rawPayload },
59
+ ...provider !== void 0 && { provider }
60
+ });
61
+ return {
62
+ ctx,
63
+ dispose
154
64
  };
155
65
  }
156
66
  //#endregion
package/dist/types.d.ts CHANGED
@@ -28,7 +28,9 @@ export interface LockApproval {
28
28
  readonly when: 'always' | 'drift';
29
29
  }
30
30
  /** Schema version - re-exported from engine as single source of truth */
31
- export declare const SCHEMA_VERSION: 29;
31
+ export declare const SCHEMA_VERSION: 32;
32
+ /** Lock compatibility-window floor - re-exported from engine as single source of truth */
33
+ export declare const BREAKING_FLOOR: 30;
32
34
  /**
33
35
  * Source file reference with meaningful path.
34
36
  * Format: file is relative path from git root, export uses hash syntax.
@@ -229,6 +231,17 @@ export interface LockWorkflowCompleteTrigger {
229
231
  readonly status?: readonly string[];
230
232
  readonly source?: string;
231
233
  }
234
+ /**
235
+ * Workflows-failed-batch trigger in lock file.
236
+ * Accumulates failed workflow completions over a window and fires the
237
+ * subscribing workflow once per window with the batched run list.
238
+ */
239
+ export interface LockWorkflowsFailedBatchTrigger {
240
+ readonly _type: 'workflows_failed_batch';
241
+ readonly accumulateFor: number;
242
+ readonly name?: string;
243
+ readonly source?: string;
244
+ }
232
245
  /**
233
246
  * Job completion trigger in lock file.
234
247
  * Matches when a specific job within a workflow finishes execution.
@@ -289,7 +302,7 @@ export interface LockLifecycleTrigger {
289
302
  readonly description?: string;
290
303
  }
291
304
  /** Union of all trigger types */
292
- export type LockTrigger = LockPrTrigger | LockPushTrigger | LockTagTrigger | LockCommentTrigger | LockReviewTrigger | LockReviewCommentTrigger | LockReleaseTrigger | LockDispatchTrigger | LockCreateTrigger | LockDeleteTrigger | LockStatusTrigger | LockWorkflowRunTrigger | LockForkTrigger | LockStarTrigger | LockWatchTrigger | LockWebhookTrigger | LockKiciEventTrigger | LockWorkflowCompleteTrigger | LockJobCompleteTrigger | LockGenericWebhookTrigger | LockScheduleTrigger | LockLifecycleTrigger;
305
+ export type LockTrigger = LockPrTrigger | LockPushTrigger | LockTagTrigger | LockCommentTrigger | LockReviewTrigger | LockReviewCommentTrigger | LockReleaseTrigger | LockDispatchTrigger | LockCreateTrigger | LockDeleteTrigger | LockStatusTrigger | LockWorkflowRunTrigger | LockForkTrigger | LockStarTrigger | LockWatchTrigger | LockWebhookTrigger | LockKiciEventTrigger | LockWorkflowCompleteTrigger | LockWorkflowsFailedBatchTrigger | LockJobCompleteTrigger | LockGenericWebhookTrigger | LockScheduleTrigger | LockLifecycleTrigger;
293
306
  /**
294
307
  * Matrix configuration in lock file.
295
308
  * Static matrices are expanded at orchestrator, dynamic at agent runtime.
@@ -441,11 +454,11 @@ export interface LockJob {
441
454
  env?: Record<string, string>;
442
455
  };
443
456
  /**
444
- * Deployment environments in merge order. Each entry is a static name or inline
457
+ * Bound contexts in merge order. Each entry is a static name or inline
445
458
  * expression (pure function); `dynamic` is set when it is a function resolved at
446
459
  * two-phase eval. Later entries override earlier ones on name collisions.
447
460
  */
448
- readonly environments?: ReadonlyArray<{
461
+ readonly contexts?: ReadonlyArray<{
449
462
  value: string | LockInlineValue;
450
463
  dynamic: boolean;
451
464
  }>;
@@ -517,12 +530,12 @@ export type LockJobOrFactory = LockJob | LockDynamicJobFn;
517
530
  /**
518
531
  * Private npm registry declaration in the lock file.
519
532
  * Carries URL/scope/secret-reference but NOT the resolved token — the orchestrator
520
- * resolves the token at dispatch via the per-environment secretResolver path.
533
+ * resolves the token at dispatch via the per-context secretResolver path.
521
534
  */
522
535
  export interface LockRegistry {
523
536
  readonly url: string;
524
537
  readonly scope?: string;
525
- /** Qualified secret reference: `<environment>:<secret-name>`. */
538
+ /** Qualified secret reference: `<context>:<secret-name>`. */
526
539
  readonly tokenSecret: string;
527
540
  readonly alwaysAuth?: boolean;
528
541
  }
@@ -554,7 +567,7 @@ export interface LockWorkflow {
554
567
  */
555
568
  readonly registries?: readonly LockRegistry[];
556
569
  /**
557
- * Extra qualified secret refs (`<environment>:<secret-name>`) to project as env vars
570
+ * Extra qualified secret refs (`<context>:<secret-name>`) to project as env vars
558
571
  * on the install subprocess for use with a customer-committed `.kici/.npmrc`.
559
572
  */
560
573
  readonly installEnv?: readonly string[];
@@ -592,6 +605,12 @@ export interface LockWorkflow {
592
605
  */
593
606
  export interface LockFile {
594
607
  readonly schemaVersion: typeof SCHEMA_VERSION;
608
+ /**
609
+ * Newest breaking schema version at emit time (`BREAKING_FLOOR`). Readers
610
+ * whose own SCHEMA_VERSION is below this must reject the lock. Mirrors the
611
+ * engine `LockFile.minReaderVersion` field.
612
+ */
613
+ readonly minReaderVersion?: number;
595
614
  readonly source: LockSource;
596
615
  /** SHA-256 hash of the serialized lock file content (excluding this field). Changes only when workflows, triggers, jobs, or bundle hashes change. */
597
616
  readonly contentHash: string;
package/dist/types.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import "./rolldown-runtime-ClRpJifh.js";
2
- import { SCHEMA_VERSION as SCHEMA_VERSION$1 } from "@kici-dev/engine";
2
+ import { BREAKING_FLOOR as BREAKING_FLOOR$1, SCHEMA_VERSION as SCHEMA_VERSION$1 } from "@kici-dev/engine";
3
3
  //#region src/types.ts
4
4
  /**
5
5
  * Lock file schema version 11.
@@ -17,6 +17,8 @@ import { SCHEMA_VERSION as SCHEMA_VERSION$1 } from "@kici-dev/engine";
17
17
  */
18
18
  /** Schema version - re-exported from engine as single source of truth */
19
19
  const SCHEMA_VERSION = SCHEMA_VERSION$1;
20
+ /** Lock compatibility-window floor - re-exported from engine as single source of truth */
21
+ const BREAKING_FLOOR = BREAKING_FLOOR$1;
20
22
  /** Type guard distinguishing a parallel group from an ordinary lock step. */
21
23
  function isLockParallelStep(entry) {
22
24
  return entry.kind === "parallel";
@@ -34,6 +36,6 @@ function isLockDynamicJobFn(job) {
34
36
  return job._type === "dynamic";
35
37
  }
36
38
  //#endregion
37
- export { SCHEMA_VERSION, isLockDynamicJobFn, isLockInlineValue, isLockParallelStep, isLockStaticJob };
39
+ export { BREAKING_FLOOR, SCHEMA_VERSION, isLockDynamicJobFn, isLockInlineValue, isLockParallelStep, isLockStaticJob };
38
40
 
39
41
  //# sourceMappingURL=types.js.map
@@ -1,3 +1,5 @@
1
1
  export { validateConfig } from './validator.js';
2
2
  export type { ValidationResult } from './validator.js';
3
+ export { runTypecheck, parseTscOutput } from './typecheck.js';
4
+ export type { TypecheckResult } from './typecheck.js';
3
5
  //# sourceMappingURL=index.d.ts.map
@@ -1,3 +1,4 @@
1
1
  import "../rolldown-runtime-ClRpJifh.js";
2
2
  import { validateConfig } from "./validator.js";
3
- export { validateConfig };
3
+ import { parseTscOutput, runTypecheck } from "./typecheck.js";
4
+ export { parseTscOutput, runTypecheck, validateConfig };
@@ -0,0 +1,28 @@
1
+ import { type CompilerError } from '../errors/index.js';
2
+ /**
3
+ * Result of the opt-in `tsc --noEmit` type-check pass.
4
+ *
5
+ * `ran: false` means the pass was skipped (no `tsconfig.json` — a
6
+ * JavaScript-only / `--mjs` workspace has no types to check). `ran: true` with
7
+ * an empty `errors` array means the sources type-check cleanly.
8
+ */
9
+ export interface TypecheckResult {
10
+ ran: boolean;
11
+ errors: CompilerError[];
12
+ }
13
+ /**
14
+ * Turn `tsc --noEmit --pretty false` output into located `E120` compiler errors.
15
+ * Handles both located diagnostics (`file(line,col): error TS…`) and global
16
+ * ones (`error TS…`, e.g. a bad tsconfig). Non-diagnostic noise lines are
17
+ * ignored. Paths are left as tsc emits them (kiciDir-relative), readable in the
18
+ * GNU error format.
19
+ */
20
+ export declare function parseTscOutput(stdout: string): CompilerError[];
21
+ /**
22
+ * Run an opt-in `tsc --noEmit` type-check over the workflow sources in
23
+ * `kiciDir`. Skips (returns `ran: false`) when there is no `tsconfig.json`.
24
+ * Prefers the workspace-local `tsc` binary, falling back to `npx typescript`;
25
+ * returns a single `E121` when the compiler cannot be resolved.
26
+ */
27
+ export declare function runTypecheck(kiciDir: string): Promise<TypecheckResult>;
28
+ //# sourceMappingURL=typecheck.d.ts.map
@@ -0,0 +1,110 @@
1
+ import "../rolldown-runtime-ClRpJifh.js";
2
+ import { compilerError } from "../errors/formatter.js";
3
+ import "../errors/index.js";
4
+ import path from "node:path";
5
+ import { existsSync } from "node:fs";
6
+ import { $ } from "zx";
7
+ import { initZx } from "@kici-dev/core";
8
+ //#region src/validation/typecheck.ts
9
+ initZx();
10
+ /** `path(line,col): error TSxxxx: message` — a located tsc diagnostic. */
11
+ const TSC_LOCATED_RE = /^(.+?)\((\d+),(\d+)\): error (TS\d+): (.+)$/;
12
+ /** `error TSxxxx: message` — a global tsc diagnostic (config errors, etc.). */
13
+ const TSC_GLOBAL_RE = /^error (TS\d+): (.+)$/;
14
+ /**
15
+ * Turn `tsc --noEmit --pretty false` output into located `E120` compiler errors.
16
+ * Handles both located diagnostics (`file(line,col): error TS…`) and global
17
+ * ones (`error TS…`, e.g. a bad tsconfig). Non-diagnostic noise lines are
18
+ * ignored. Paths are left as tsc emits them (kiciDir-relative), readable in the
19
+ * GNU error format.
20
+ */
21
+ function parseTscOutput(stdout) {
22
+ const errors = [];
23
+ for (const raw of stdout.split("\n")) {
24
+ const line = raw.trim();
25
+ const located = TSC_LOCATED_RE.exec(line);
26
+ if (located) {
27
+ const [, file, lineStr, colStr, tsCode, message] = located;
28
+ const location = {
29
+ file,
30
+ line: parseInt(lineStr, 10),
31
+ column: parseInt(colStr, 10)
32
+ };
33
+ errors.push(compilerError("E120", `${tsCode}: ${message}`, {
34
+ location,
35
+ suggestion: "Fix the type error in your workflow source."
36
+ }));
37
+ continue;
38
+ }
39
+ const global = TSC_GLOBAL_RE.exec(line);
40
+ if (global) {
41
+ const [, tsCode, message] = global;
42
+ errors.push(compilerError("E120", `${tsCode}: ${message}`, { suggestion: "Fix the type error in your workflow source." }));
43
+ }
44
+ }
45
+ return errors;
46
+ }
47
+ /** The E121 "compiler could not be resolved" error. */
48
+ function typecheckUnavailable() {
49
+ return compilerError("E121", "Type-check unavailable: could not resolve the TypeScript compiler", { suggestion: "Add \"typescript\" to your .kici/package.json devDependencies (kici init scaffolds it), then reinstall." });
50
+ }
51
+ /**
52
+ * Run an opt-in `tsc --noEmit` type-check over the workflow sources in
53
+ * `kiciDir`. Skips (returns `ran: false`) when there is no `tsconfig.json`.
54
+ * Prefers the workspace-local `tsc` binary, falling back to `npx typescript`;
55
+ * returns a single `E121` when the compiler cannot be resolved.
56
+ */
57
+ async function runTypecheck(kiciDir) {
58
+ const tsconfigPath = path.join(kiciDir, "tsconfig.json");
59
+ if (!existsSync(tsconfigPath)) return {
60
+ ran: false,
61
+ errors: []
62
+ };
63
+ const localBin = path.join(kiciDir, "node_modules", ".bin", "tsc");
64
+ const usedLocal = existsSync(localBin);
65
+ const invocation = usedLocal ? [localBin] : [
66
+ "npx",
67
+ "--yes",
68
+ "-p",
69
+ "typescript",
70
+ "tsc"
71
+ ];
72
+ const tscArgs = [
73
+ "--noEmit",
74
+ "--pretty",
75
+ "false",
76
+ "-p",
77
+ tsconfigPath
78
+ ];
79
+ let out;
80
+ try {
81
+ out = await $({
82
+ cwd: kiciDir,
83
+ nothrow: true
84
+ })`${invocation} ${tscArgs}`;
85
+ } catch {
86
+ return {
87
+ ran: true,
88
+ errors: [typecheckUnavailable()]
89
+ };
90
+ }
91
+ const errors = parseTscOutput(out.stdout);
92
+ if (out.exitCode !== 0 && errors.length === 0) {
93
+ if (!usedLocal) return {
94
+ ran: true,
95
+ errors: [typecheckUnavailable()]
96
+ };
97
+ return {
98
+ ran: true,
99
+ errors: [compilerError("E120", `type-check failed: ${(out.stderr || out.stdout).trim()}`, { suggestion: "Fix the type error in your workflow source." })]
100
+ };
101
+ }
102
+ return {
103
+ ran: true,
104
+ errors
105
+ };
106
+ }
107
+ //#endregion
108
+ export { parseTscOutput, runTypecheck };
109
+
110
+ //# sourceMappingURL=typecheck.js.map
@@ -1,5 +1,5 @@
1
- import type { Workflow } from '@kici-dev/sdk';
2
1
  import { type CompilerError } from '../errors/index.js';
2
+ import type { WorkflowWithSource } from '../types.js';
3
3
  /**
4
4
  * Validation result - either success or list of errors.
5
5
  */
@@ -18,9 +18,14 @@ export type ValidationResult = {
18
18
  * 3. Job dependencies are valid (exist, no cycles, no self-refs)
19
19
  * 4. Static matrix expansions stay under 256 job limit
20
20
  *
21
- * @param workflows - Array of workflows from config
22
- * @param configPath - Path for error location reporting
21
+ * Each error carries the most precise `file:line:column` the data allows: a
22
+ * job-scoped error anchors to the offending job's first step location (real
23
+ * file + real line), falling back to the workflow's source file at line 1 when
24
+ * no step exists; a workflow-scoped error uses the workflow source file (line 1,
25
+ * since `workflow()` captures no call-site).
26
+ *
27
+ * @param workflows - Source-carrying workflows from discovery
23
28
  * @returns Validation result with errors if any
24
29
  */
25
- export declare function validateConfig(workflows: Workflow[], configPath: string): ValidationResult;
30
+ export declare function validateConfig(workflows: WorkflowWithSource[]): ValidationResult;
26
31
  //# sourceMappingURL=validator.d.ts.map