@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.
- package/dist/auth/headless-detect.js +1 -1
- package/dist/cli-banner.js +1 -1
- package/dist/cli.js +56 -19
- package/dist/commands/approve.js +1 -1
- package/dist/commands/compile.js +19 -17
- package/dist/commands/diagnostics.d.ts +7 -0
- package/dist/commands/diagnostics.js +58 -0
- package/dist/commands/docs.js +1 -1
- package/dist/commands/drain-worker.js +1 -1
- package/dist/commands/endpoints.js +1 -1
- package/dist/commands/fixture.js +1 -1
- package/dist/commands/held-run-client.js +1 -1
- package/dist/commands/held-run-resolve.js +1 -1
- package/dist/commands/hook.js +1 -1
- package/dist/commands/index.d.ts +16 -4
- package/dist/commands/index.js +10 -4
- package/dist/commands/init.js +2 -2
- package/dist/commands/login.d.ts +0 -2
- package/dist/commands/login.js +1 -3
- package/dist/commands/logout.js +1 -1
- package/dist/commands/orchestrators.d.ts +25 -0
- package/dist/commands/orchestrators.js +115 -0
- package/dist/commands/org.js +1 -1
- package/dist/commands/reject.js +1 -1
- package/dist/commands/run.d.ts +2 -9
- package/dist/commands/run.js +256 -315
- package/dist/commands/runs/cancel.d.ts +6 -0
- package/dist/commands/runs/cancel.js +32 -0
- package/dist/commands/runs/list.d.ts +6 -0
- package/dist/commands/runs/list.js +49 -0
- package/dist/commands/runs/logs.d.ts +7 -0
- package/dist/commands/runs/logs.js +67 -0
- package/dist/commands/runs/rerun.d.ts +5 -0
- package/dist/commands/runs/rerun.js +21 -0
- package/dist/commands/runs/show.d.ts +5 -0
- package/dist/commands/runs/show.js +65 -0
- package/dist/commands/secrets-list.d.ts +7 -9
- package/dist/commands/secrets-list.js +40 -64
- package/dist/commands/test.d.ts +4 -0
- package/dist/commands/test.js +4 -6
- package/dist/commands/types.d.ts +3 -5
- package/dist/commands/types.js +13 -37
- package/dist/commands/verify-attestation.d.ts +12 -0
- package/dist/commands/verify-attestation.js +69 -0
- package/dist/commands/watch.js +1 -1
- package/dist/commands/workflows.js +14 -34
- package/dist/errors/capability-gap.js +1 -1
- package/dist/errors/formatter.js +1 -1
- package/dist/errors/index.js +1 -1
- package/dist/execution/executor.js +1 -1
- package/dist/execution/index.js +1 -1
- package/dist/execution/sdk-alias.js +1 -1
- package/dist/execution/ts-loader.js +1 -1
- package/dist/fixtures/compiler.js +1 -1
- package/dist/fixtures/defaults/index.js +1 -1
- package/dist/format.js +1 -1
- package/dist/generators/secrets-dts.js +2 -2
- package/dist/hooks/detector.js +1 -1
- package/dist/hooks/index.js +1 -1
- package/dist/hooks/installer.js +1 -1
- package/dist/hooks/templates.js +1 -1
- package/dist/index.js +1 -1
- package/dist/llm-context/llms-full.txt +1549 -1282
- package/dist/llm-context/llms.txt +6 -2
- package/dist/local-executor/dag-scheduler.js +1 -1
- package/dist/local-executor/index.js +1 -1
- package/dist/local-executor/job-runner.js +40 -18
- package/dist/local-executor/materializer.js +1 -1
- package/dist/local-executor/output-streamer.js +1 -1
- package/dist/local-executor/payload-generator.js +1 -1
- package/dist/local-executor/picker.js +1 -1
- package/dist/local-executor/runs-on-display.d.ts +9 -0
- package/dist/local-executor/runs-on-display.js +23 -0
- package/dist/local-executor/secret-loader.js +1 -1
- package/dist/local-executor/to-event-payload.js +1 -1
- package/dist/local-executor/types.js +1 -1
- package/dist/local-executor/workflow-lock.js +0 -0
- package/dist/lockfile/generator.d.ts +9 -5
- package/dist/lockfile/generator.js +58 -38
- package/dist/lockfile/hash-files.js +1 -1
- package/dist/lockfile/hasher.js +1 -1
- package/dist/lockfile/index.js +1 -1
- package/dist/lockfile/purity-analyzer.js +1 -1
- package/dist/postinstall.js +1 -1
- package/dist/provenance-trust-root.d.ts +14 -0
- package/dist/provenance-trust-root.js +49 -0
- package/dist/remote/config.d.ts +6 -2
- package/dist/remote/config.js +7 -4
- package/dist/remote/dashboard-client.d.ts +92 -0
- package/dist/remote/dashboard-client.js +168 -0
- package/dist/remote/encryption.js +3 -4
- package/dist/remote/history.js +1 -1
- package/dist/remote/oauth.js +1 -1
- package/dist/remote/oidc-discovery.js +1 -1
- package/dist/remote/output/json.js +1 -1
- package/dist/remote/output/junit.js +1 -1
- package/dist/remote/output/streaming.js +1 -1
- package/dist/remote/output/summary.js +1 -1
- package/dist/remote/platform-client.d.ts +142 -0
- package/dist/remote/platform-client.js +187 -0
- package/dist/remote/prod-defaults.js +1 -1
- package/dist/remote/render.d.ts +11 -0
- package/dist/remote/render.js +48 -0
- package/dist/remote/secret-upload.js +1 -1
- package/dist/remote/uploader.d.ts +9 -0
- package/dist/remote/uploader.js +51 -4
- package/dist/templates/agents-md.d.ts +1 -1
- package/dist/templates/agents-md.js +8 -3
- package/dist/templates/index.js +1 -1
- package/dist/templates/package-json.js +4 -5
- package/dist/templates/tsconfig-json.js +1 -1
- package/dist/templates/workflows/hello-world.js +2 -2
- package/dist/templates/workflows/hello-world.ts +1 -1
- package/dist/templates/workflows/pr-checks.js +3 -3
- package/dist/templates/workflows/pr-checks.ts +2 -2
- package/dist/test-runner/dry-run.js +1 -1
- package/dist/test-runner/event-types.js +1 -1
- package/dist/test-runner/git-detector.js +1 -1
- package/dist/test-runner/index.js +1 -1
- package/dist/test-runner/job-executor.js +3 -2
- package/dist/test-runner/output-formatter.js +1 -1
- package/dist/test-runner/payload-builder.js +1 -1
- package/dist/test-runner/rule-evaluator.js +1 -1
- package/dist/test-runner/secrets-file.js +1 -1
- package/dist/test-runner/step-context.js +10 -6
- package/dist/types.d.ts +29 -8
- package/dist/types.js +2 -1
- package/dist/validation/index.js +1 -1
- package/dist/validation/validator.js +1 -1
- package/dist/workflows/hello-world.ts +1 -1
- package/dist/workflows/pr-checks.ts +2 -2
- package/package.json +10 -9
- package/sbom.spdx.json +465 -410
- package/dist/commands/cancel.js +0 -124
- package/dist/commands/status.js +0 -212
- package/dist/remote/client.js +0 -203
- package/dist/remote/observer.js +0 -174
- /package/dist/{chunk-gOLHoazu.js → chunk-BTugEXQM.js} +0 -0
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { formatDuration } from '@kici-dev/core';
|
|
2
|
+
export { formatDuration };
|
|
3
|
+
/** Length of a string ignoring ANSI color codes (for column alignment). */
|
|
4
|
+
export declare function stripAnsi(s: string): string;
|
|
5
|
+
/** Human "Ns/Nm/Nh/Nd ago" from an ISO timestamp; '—' when absent/invalid. */
|
|
6
|
+
export declare function relativeTime(iso: string | undefined, now?: number): string;
|
|
7
|
+
/** Color a run/job/step status. picocolors disables itself for NO_COLOR / non-TTY. */
|
|
8
|
+
export declare function colorStatus(status: string): string;
|
|
9
|
+
/** Width-aligned ASCII table with a bold header row. */
|
|
10
|
+
export declare function renderTable(headers: string[], rows: string[][]): string;
|
|
11
|
+
//# sourceMappingURL=render.d.ts.map
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import "../chunk-BTugEXQM.js";
|
|
2
|
+
import pc from "picocolors";
|
|
3
|
+
import { formatDuration } from "@kici-dev/core";
|
|
4
|
+
//#region src/remote/render.ts
|
|
5
|
+
/** Shared terminal-render helpers for the diagnostics + runs commands. */
|
|
6
|
+
const ANSI_SGR = /\[[0-9;]*m/g;
|
|
7
|
+
/** Length of a string ignoring ANSI color codes (for column alignment). */
|
|
8
|
+
function stripAnsi(s) {
|
|
9
|
+
return s.replace(ANSI_SGR, "");
|
|
10
|
+
}
|
|
11
|
+
/** Human "Ns/Nm/Nh/Nd ago" from an ISO timestamp; '—' when absent/invalid. */
|
|
12
|
+
function relativeTime(iso, now = Date.now()) {
|
|
13
|
+
if (!iso) return "—";
|
|
14
|
+
const then = Date.parse(iso);
|
|
15
|
+
if (Number.isNaN(then)) return "—";
|
|
16
|
+
const sec = Math.max(0, Math.round((now - then) / 1e3));
|
|
17
|
+
if (sec < 60) return `${sec}s ago`;
|
|
18
|
+
const min = Math.round(sec / 60);
|
|
19
|
+
if (min < 60) return `${min}m ago`;
|
|
20
|
+
const hr = Math.round(min / 60);
|
|
21
|
+
if (hr < 24) return `${hr}h ago`;
|
|
22
|
+
return `${Math.round(hr / 24)}d ago`;
|
|
23
|
+
}
|
|
24
|
+
/** Color a run/job/step status. picocolors disables itself for NO_COLOR / non-TTY. */
|
|
25
|
+
function colorStatus(status) {
|
|
26
|
+
if (!pc.isColorSupported) return status;
|
|
27
|
+
switch (status) {
|
|
28
|
+
case "success": return pc.green(status);
|
|
29
|
+
case "failed":
|
|
30
|
+
case "error":
|
|
31
|
+
case "timed_out": return pc.red(status);
|
|
32
|
+
case "running": return pc.cyan(status);
|
|
33
|
+
case "cancelled": return pc.yellow(status);
|
|
34
|
+
default: return pc.gray(status);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
/** Width-aligned ASCII table with a bold header row. */
|
|
38
|
+
function renderTable(headers, rows) {
|
|
39
|
+
const widths = headers.map((h, i) => Math.max(stripAnsi(h).length, ...rows.map((r) => stripAnsi(r[i] ?? "").length)));
|
|
40
|
+
const pad = (cell, i) => cell + " ".repeat(Math.max(0, widths[i] - stripAnsi(cell).length));
|
|
41
|
+
const header = headers.map((h, i) => pc.bold(pad(h, i))).join(" ");
|
|
42
|
+
const body = rows.map((r) => r.map((c, i) => pad(c ?? "", i)).join(" ")).join("\n");
|
|
43
|
+
return body ? `${header}\n${body}` : header;
|
|
44
|
+
}
|
|
45
|
+
//#endregion
|
|
46
|
+
export { colorStatus, formatDuration, relativeTime, renderTable, stripAnsi };
|
|
47
|
+
|
|
48
|
+
//# sourceMappingURL=render.js.map
|
|
@@ -79,12 +79,20 @@ export interface OverlaySelection {
|
|
|
79
79
|
* files like `.kici/.env.local` — are excluded by `--exclude-standard` and
|
|
80
80
|
* never appear in the selection.
|
|
81
81
|
*
|
|
82
|
+
* When `fullWorkingTree` is set (the `kici run remote` path), the entire
|
|
83
|
+
* `.git` directory is additively included so the extracted overlay is a real
|
|
84
|
+
* git repository on the agent — workflow steps that shell out to git then work
|
|
85
|
+
* exactly as they do under `kici run local`. The `.git` files are added after
|
|
86
|
+
* `.kiciignore` filtering (git internals are never subject to working-tree
|
|
87
|
+
* ignore globs).
|
|
88
|
+
*
|
|
82
89
|
* @param repoRoot - Path to the git repository root
|
|
83
90
|
* @param options - Optional configuration
|
|
84
91
|
* @returns HEAD SHA, remote flag, and the existing/deleted file partition
|
|
85
92
|
*/
|
|
86
93
|
export declare function selectOverlayFiles(repoRoot: string, options?: {
|
|
87
94
|
kiciIgnorePath?: string;
|
|
95
|
+
fullWorkingTree?: boolean;
|
|
88
96
|
}): Promise<OverlaySelection>;
|
|
89
97
|
/**
|
|
90
98
|
* Create an overlay tarball from a git repo, including only changed files.
|
|
@@ -101,6 +109,7 @@ export declare function selectOverlayFiles(repoRoot: string, options?: {
|
|
|
101
109
|
*/
|
|
102
110
|
export declare function createOverlayTarball(repoRoot: string, options?: {
|
|
103
111
|
kiciIgnorePath?: string;
|
|
112
|
+
fullWorkingTree?: boolean;
|
|
104
113
|
}): Promise<{
|
|
105
114
|
tarballPath: string;
|
|
106
115
|
summary: UploadSummary;
|
package/dist/remote/uploader.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import "../chunk-
|
|
1
|
+
import "../chunk-BTugEXQM.js";
|
|
2
2
|
import { encryptTarball } from "./encryption.js";
|
|
3
3
|
import path from "node:path";
|
|
4
4
|
import fs from "node:fs/promises";
|
|
@@ -30,6 +30,41 @@ function gitLines(cmd, cwd) {
|
|
|
30
30
|
return [];
|
|
31
31
|
}
|
|
32
32
|
}
|
|
33
|
+
/** True for repo-relative paths inside the `.git` directory. */
|
|
34
|
+
function isGitDirPath(relPath) {
|
|
35
|
+
return relPath === ".git" || relPath.startsWith(".git/");
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Recursively enumerate every file under `<repoRoot>/.git`, returning paths
|
|
39
|
+
* relative to `repoRoot` (so they keep the `.git/...` prefix in the tarball
|
|
40
|
+
* and extract back in place).
|
|
41
|
+
*
|
|
42
|
+
* `git ls-files` never lists `.git` contents, so for `kici run remote` — which
|
|
43
|
+
* uploads the developer's working tree as a self-contained overlay with NO
|
|
44
|
+
* clone on the agent — we enumerate the directory explicitly. Including the
|
|
45
|
+
* whole `.git` directory (objects, refs, HEAD, index, config, packed-refs)
|
|
46
|
+
* makes the extracted overlay a real git repository, so workflow steps that
|
|
47
|
+
* shell out to git work exactly as they do under `kici run local`.
|
|
48
|
+
*/
|
|
49
|
+
async function collectGitDirFiles(repoRoot) {
|
|
50
|
+
const gitRoot = path.join(repoRoot, ".git");
|
|
51
|
+
const out = [];
|
|
52
|
+
async function walk(absDir) {
|
|
53
|
+
let entries;
|
|
54
|
+
try {
|
|
55
|
+
entries = await fs.readdir(absDir, { withFileTypes: true });
|
|
56
|
+
} catch {
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
await Promise.all(entries.map(async (entry) => {
|
|
60
|
+
const abs = path.join(absDir, entry.name);
|
|
61
|
+
if (entry.isDirectory()) await walk(abs);
|
|
62
|
+
else if (entry.isFile() || entry.isSymbolicLink()) out.push(path.relative(repoRoot, abs));
|
|
63
|
+
}));
|
|
64
|
+
}
|
|
65
|
+
await walk(gitRoot);
|
|
66
|
+
return out;
|
|
67
|
+
}
|
|
33
68
|
/**
|
|
34
69
|
* Load .kiciignore patterns from a file.
|
|
35
70
|
* Returns a picomatch matcher function or null if file doesn't exist.
|
|
@@ -56,6 +91,13 @@ async function loadKiciIgnore(kiciIgnorePath) {
|
|
|
56
91
|
* files like `.kici/.env.local` — are excluded by `--exclude-standard` and
|
|
57
92
|
* never appear in the selection.
|
|
58
93
|
*
|
|
94
|
+
* When `fullWorkingTree` is set (the `kici run remote` path), the entire
|
|
95
|
+
* `.git` directory is additively included so the extracted overlay is a real
|
|
96
|
+
* git repository on the agent — workflow steps that shell out to git then work
|
|
97
|
+
* exactly as they do under `kici run local`. The `.git` files are added after
|
|
98
|
+
* `.kiciignore` filtering (git internals are never subject to working-tree
|
|
99
|
+
* ignore globs).
|
|
100
|
+
*
|
|
59
101
|
* @param repoRoot - Path to the git repository root
|
|
60
102
|
* @param options - Optional configuration
|
|
61
103
|
* @returns HEAD SHA, remote flag, and the existing/deleted file partition
|
|
@@ -67,7 +109,7 @@ async function selectOverlayFiles(repoRoot, options) {
|
|
|
67
109
|
}).trim();
|
|
68
110
|
const hasRemote = gitLines("git remote", repoRoot).length > 0;
|
|
69
111
|
let allFiles;
|
|
70
|
-
if (hasRemote) {
|
|
112
|
+
if (hasRemote && !options?.fullWorkingTree) {
|
|
71
113
|
const unstaged = gitLines("git diff --name-only HEAD", repoRoot);
|
|
72
114
|
const staged = gitLines("git diff --name-only --cached HEAD", repoRoot);
|
|
73
115
|
const untracked = gitLines("git ls-files --others --exclude-standard", repoRoot);
|
|
@@ -83,6 +125,10 @@ async function selectOverlayFiles(repoRoot, options) {
|
|
|
83
125
|
}
|
|
84
126
|
const kiciIgnore = await loadKiciIgnore(options?.kiciIgnorePath ?? path.join(repoRoot, ".kiciignore"));
|
|
85
127
|
if (kiciIgnore) allFiles = allFiles.filter((f) => !kiciIgnore(f));
|
|
128
|
+
if (options?.fullWorkingTree) {
|
|
129
|
+
const gitFiles = await collectGitDirFiles(repoRoot);
|
|
130
|
+
allFiles = [...new Set([...allFiles, ...gitFiles])];
|
|
131
|
+
}
|
|
86
132
|
const existingFiles = [];
|
|
87
133
|
const deletedFiles = [];
|
|
88
134
|
await Promise.all(allFiles.map(async (file) => {
|
|
@@ -117,8 +163,9 @@ async function selectOverlayFiles(repoRoot, options) {
|
|
|
117
163
|
async function createOverlayTarball(repoRoot, options) {
|
|
118
164
|
const { sha, hasRemote, existingFiles, deletedFiles } = await selectOverlayFiles(repoRoot, options);
|
|
119
165
|
const untrackedSet = new Set(gitLines("git ls-files --others --exclude-standard", repoRoot));
|
|
120
|
-
const
|
|
121
|
-
const
|
|
166
|
+
const workingTreeFiles = existingFiles.filter((f) => !isGitDirPath(f));
|
|
167
|
+
const newFiles = workingTreeFiles.filter((f) => untrackedSet.has(f));
|
|
168
|
+
const modifiedFiles = workingTreeFiles.filter((f) => !untrackedSet.has(f));
|
|
122
169
|
const checksums = {};
|
|
123
170
|
await Promise.all(existingFiles.map(async (file) => {
|
|
124
171
|
checksums[file] = await sha256File(path.join(repoRoot, file));
|
|
@@ -4,5 +4,5 @@
|
|
|
4
4
|
* picked up by Claude Code, Cursor, Aider, and other coding agents that scan
|
|
5
5
|
* the working tree for an authoring context file.
|
|
6
6
|
*/
|
|
7
|
-
export declare const agentsMdTemplate = "# KiCI workflow authoring guide\n\nThis project uses KiCI \u2014 a TypeScript-native CI/CD workflow engine \u2014 instead\nof YAML-based CI. Workflows live in `.kici/workflows/*.ts`, are compiled\ninto a portable lock file, and executed by self-hosted agents.\n\n## Where the API surface lives\n\n- Public SDK types: `node_modules/@kici-dev/sdk/dist/index.d.ts` \u2014 read this\n for the canonical signatures of `workflow`, `job`, `step`, `pr`,\n `push`, `schedule`, `matrix`, `rule`, `dynamicJob`, etc.\n- Bundled offline reference for coding agents: `kici docs llm` prints the\n full markdown documentation bundle to stdout. `kici docs llm --index`\n prints just the curated link index (llms.txt format).\n- Online docs:\n - <https://kici.dev/docs/> \u2014 published docs site.\n - <https://kici.dev/llms.txt> \u2014 curated index for LLM consumers.\n - <https://kici.dev/llms-full.txt> \u2014 full markdown bundle.\n - Key pages: `user/sdk-reference`, `user/workflow-patterns`,\n `user/testing-guide`, `user/hooks`, `user/secrets`.\n\n## The five core patterns\n\n1. **Push trigger** \u2014 `on: push({ branches: 'main' })`. Pair with `paths`\n to scope to subtrees.\n\n ```ts\n import { workflow, job, step, push } from '@kici-dev/sdk';\n\n export default workflow('build', {\n on: push({ branches: 'main' }),\n jobs: [\n job('build', {\n runsOn: '
|
|
7
|
+
export declare const agentsMdTemplate = "# KiCI workflow authoring guide\n\nThis project uses KiCI \u2014 a TypeScript-native CI/CD workflow engine \u2014 instead\nof YAML-based CI. Workflows live in `.kici/workflows/*.ts`, are compiled\ninto a portable lock file, and executed by self-hosted agents.\n\n## Where the API surface lives\n\n- Public SDK types: `node_modules/@kici-dev/sdk/dist/index.d.ts` \u2014 read this\n for the canonical signatures of `workflow`, `job`, `step`, `pr`,\n `push`, `schedule`, `matrix`, `rule`, `dynamicJob`, etc.\n- Bundled offline reference for coding agents: `kici docs llm` prints the\n full markdown documentation bundle to stdout. `kici docs llm --index`\n prints just the curated link index (llms.txt format).\n- Online docs:\n - <https://kici.dev/docs/> \u2014 published docs site.\n - <https://kici.dev/llms.txt> \u2014 curated index for LLM consumers.\n - <https://kici.dev/llms-full.txt> \u2014 full markdown bundle.\n - Key pages: `user/sdk-reference`, `user/workflow-patterns`,\n `user/testing-guide`, `user/hooks`, `user/secrets`.\n\n## The five core patterns\n\n1. **Push trigger** \u2014 `on: push({ branches: 'main' })`. Pair with `paths`\n to scope to subtrees.\n\n ```ts\n import { workflow, job, step, push } from '@kici-dev/sdk';\n\n export default workflow('build', {\n on: push({ branches: 'main' }),\n jobs: [\n job('build', {\n runsOn: 'kici:os:linux',\n steps: [step('install', async ({ $ }) => { await $`pnpm install`; })],\n }),\n ],\n });\n ```\n\n `kici:os:linux` targets any agent reporting that OS \u2014 every agent\n self-reports `kici:os:` / `kici:arch:` / `kici:host:`. Use a custom label\n (e.g. `'gpu'`, `'prod-pool'`) to target a specific agent pool your scaler\n defines.\n\n2. **PR + matrix** \u2014 `pr({ target: 'main' })` plus a matrix over node\n versions. The matrix expands at dispatch time.\n\n ```ts\n import { workflow, job, step, pr, matrix } from '@kici-dev/sdk';\n\n export default workflow('test-matrix', {\n on: pr({ target: 'main' }),\n jobs: [\n job('test', {\n runsOn: 'kici:os:linux',\n strategy: { matrix: matrix({ node: ['20', '22', '24'] }) },\n steps: [\n step('test', async ({ $, matrix }) => {\n await $`node --version`;\n await $`pnpm install`;\n await $`pnpm test`;\n return { node: matrix.node };\n }),\n ],\n }),\n ],\n });\n ```\n\n3. **Lifecycle hooks** \u2014 `onFailure` / `onSuccess` / `onCancel` on a\n job or workflow run after the main steps in their own scope.\n\n4. **Secrets** \u2014 declared scopes resolve at dispatch:\n\n ```ts\n step('deploy', async ({ $, secrets }) => {\n await $`./scripts/deploy.sh`.env({ DEPLOY_TOKEN: secrets.production.DEPLOY_TOKEN });\n });\n ```\n\n Run `kici secrets list` to enumerate the contexts available for testing.\n\n5. **Dynamic jobs** \u2014 `dynamicJob` and `dynamicGroup` build the DAG at\n runtime from a step's outputs. Don't try to compute job names at top level;\n the lock file would be wrong.\n\n## Anti-patterns\n\n- **Do NOT write `.yml` / `.yaml` CI files** \u2014 KiCI replaces that entire\n layer. There is no compatibility shim.\n- **Do NOT `import` from any `@kici-dev/*` package's `/dist/...`\n subpath** \u2014 those are not part of the public API and break across versions.\n Import from the package root.\n- **Do NOT `await` outside step bodies.** The top-level workflow file is\n loaded by the compiler synchronously; async I/O at module scope means the\n lock file emits before it resolves and the workflow appears empty.\n- **Do NOT mutate shared variables between jobs.** Each job runs in its own\n agent process. Use `needs` + step outputs to thread values.\n- **Do NOT hand-edit `kici.lock.json`.** Regenerate it via `kici compile`.\n\n## Local commands a coding agent should run\n\n| Command | Purpose |\n| ------------------------------- | ------------------------------------------- |\n| `pnpm kici compile --check` | Validate workflow source without writing. |\n| `pnpm kici test pr:open --debug`| Preview which workflows match an event. |\n| `pnpm kici run local push` | Execute workflows locally with no orchestrator. |\n| `pnpm kici docs llm` | Print the full LLM documentation bundle. |\n| `pnpm kici docs llm --index` | Print the curated link index. |\n\nIf `pnpm kici` isn't in scripts, fall back to `npx kici`.\n\n## Loop\n\n1. Read the SDK types from `node_modules/@kici-dev/sdk/dist/index.d.ts`.\n2. Pipe `kici docs llm` into the agent's context if it doesn't already have\n the full bundle.\n3. Edit a workflow under `.kici/workflows/`.\n4. Run `kici compile --check` (zero exit means valid).\n5. Run `kici test <event>` to preview matching.\n6. Run `kici run local <event>` to execute locally before pushing.\n";
|
|
8
8
|
//# sourceMappingURL=agents-md.d.ts.map
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import "../chunk-
|
|
1
|
+
import "../chunk-BTugEXQM.js";
|
|
2
2
|
//#region src/templates/agents-md.ts
|
|
3
3
|
/**
|
|
4
4
|
* Template body for .kici/AGENTS.md, written by `kici init` (unless opted out
|
|
@@ -39,13 +39,18 @@ into a portable lock file, and executed by self-hosted agents.
|
|
|
39
39
|
on: push({ branches: 'main' }),
|
|
40
40
|
jobs: [
|
|
41
41
|
job('build', {
|
|
42
|
-
runsOn: '
|
|
42
|
+
runsOn: 'kici:os:linux',
|
|
43
43
|
steps: [step('install', async ({ $ }) => { await $\`pnpm install\`; })],
|
|
44
44
|
}),
|
|
45
45
|
],
|
|
46
46
|
});
|
|
47
47
|
\`\`\`
|
|
48
48
|
|
|
49
|
+
\`kici:os:linux\` targets any agent reporting that OS — every agent
|
|
50
|
+
self-reports \`kici:os:\` / \`kici:arch:\` / \`kici:host:\`. Use a custom label
|
|
51
|
+
(e.g. \`'gpu'\`, \`'prod-pool'\`) to target a specific agent pool your scaler
|
|
52
|
+
defines.
|
|
53
|
+
|
|
49
54
|
2. **PR + matrix** — \`pr({ target: 'main' })\` plus a matrix over node
|
|
50
55
|
versions. The matrix expands at dispatch time.
|
|
51
56
|
|
|
@@ -56,7 +61,7 @@ into a portable lock file, and executed by self-hosted agents.
|
|
|
56
61
|
on: pr({ target: 'main' }),
|
|
57
62
|
jobs: [
|
|
58
63
|
job('test', {
|
|
59
|
-
runsOn: '
|
|
64
|
+
runsOn: 'kici:os:linux',
|
|
60
65
|
strategy: { matrix: matrix({ node: ['20', '22', '24'] }) },
|
|
61
66
|
steps: [
|
|
62
67
|
step('test', async ({ $, matrix }) => {
|
package/dist/templates/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import "../chunk-
|
|
1
|
+
import "../chunk-BTugEXQM.js";
|
|
2
2
|
//#region src/templates/package-json.ts
|
|
3
|
-
const sdkVersion = "0.1.
|
|
3
|
+
const sdkVersion = "0.1.18";
|
|
4
4
|
/**
|
|
5
5
|
* Generate package.json content for .kici/ directory
|
|
6
6
|
*
|
|
@@ -10,7 +10,7 @@ const sdkVersion = "0.1.16";
|
|
|
10
10
|
* @returns JSON string with proper formatting (2-space indent, trailing newline)
|
|
11
11
|
*/
|
|
12
12
|
function generatePackageJson(devMode = false) {
|
|
13
|
-
|
|
13
|
+
return JSON.stringify({
|
|
14
14
|
name: "@kici-dev/workflows",
|
|
15
15
|
private: true,
|
|
16
16
|
type: "module",
|
|
@@ -19,8 +19,7 @@ function generatePackageJson(devMode = false) {
|
|
|
19
19
|
typecheck: "tsc --noEmit"
|
|
20
20
|
},
|
|
21
21
|
devDependencies: { "@kici-dev/sdk": devMode ? ">=0.0.1-0" : `^${sdkVersion}` }
|
|
22
|
-
};
|
|
23
|
-
return JSON.stringify(pkg, null, 2) + "\n";
|
|
22
|
+
}, null, 2) + "\n";
|
|
24
23
|
}
|
|
25
24
|
//#endregion
|
|
26
25
|
export { generatePackageJson };
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import "../../chunk-
|
|
1
|
+
import "../../chunk-BTugEXQM.js";
|
|
2
2
|
import { job, push, step, workflow } from "@kici-dev/sdk";
|
|
3
3
|
//#region src/templates/workflows/hello-world.ts
|
|
4
4
|
const helloWorldWorkflow = workflow("hello-world", {
|
|
5
5
|
on: push(),
|
|
6
6
|
jobs: [job("greet", {
|
|
7
|
-
runsOn: "
|
|
7
|
+
runsOn: "kici:os:linux",
|
|
8
8
|
steps: [step("say-hello", async ({ $ }) => {
|
|
9
9
|
await $`echo "Hello, World!"`;
|
|
10
10
|
})]
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import "../../chunk-
|
|
1
|
+
import "../../chunk-BTugEXQM.js";
|
|
2
2
|
import { isEventType, job, pr, rule, skip, step, workflow } from "@kici-dev/sdk";
|
|
3
3
|
//#region src/templates/workflows/pr-checks.ts
|
|
4
4
|
const prChecksWorkflow = workflow("pr-checks", {
|
|
@@ -13,14 +13,14 @@ const prChecksWorkflow = workflow("pr-checks", {
|
|
|
13
13
|
return ctx.changedFiles.some((file) => file.startsWith("src/"));
|
|
14
14
|
})],
|
|
15
15
|
jobs: [job("lint", {
|
|
16
|
-
runsOn: "
|
|
16
|
+
runsOn: "kici:os:linux",
|
|
17
17
|
steps: [step("checkout", async ({ $ }) => {
|
|
18
18
|
await $`echo "Checking out code..."`;
|
|
19
19
|
}), step("run-linter", async ({ $ }) => {
|
|
20
20
|
await $`echo "Running linter..."`;
|
|
21
21
|
})]
|
|
22
22
|
}), job("test", {
|
|
23
|
-
runsOn: "
|
|
23
|
+
runsOn: "kici:os:linux",
|
|
24
24
|
needs: ["lint"],
|
|
25
25
|
steps: [
|
|
26
26
|
step("checkout", async ({ $ }) => {
|
|
@@ -26,7 +26,7 @@ export const prChecksWorkflow = workflow('pr-checks', {
|
|
|
26
26
|
// Jobs: run in parallel unless connected via `needs`
|
|
27
27
|
jobs: [
|
|
28
28
|
job('lint', {
|
|
29
|
-
runsOn: '
|
|
29
|
+
runsOn: 'kici:os:linux',
|
|
30
30
|
steps: [
|
|
31
31
|
step('checkout', async ({ $ }) => {
|
|
32
32
|
await $`echo "Checking out code..."`;
|
|
@@ -39,7 +39,7 @@ export const prChecksWorkflow = workflow('pr-checks', {
|
|
|
39
39
|
}),
|
|
40
40
|
|
|
41
41
|
job('test', {
|
|
42
|
-
runsOn: '
|
|
42
|
+
runsOn: 'kici:os:linux',
|
|
43
43
|
needs: ['lint'], // Waits for lint to pass
|
|
44
44
|
steps: [
|
|
45
45
|
step('checkout', async ({ $ }) => {
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import "../chunk-
|
|
1
|
+
import "../chunk-BTugEXQM.js";
|
|
2
2
|
import { formatter } from "./output-formatter.js";
|
|
3
3
|
import { createStepContext } from "./step-context.js";
|
|
4
4
|
import { createRuleContext, evaluateRules as evaluateRulesWithFormatting } from "./rule-evaluator.js";
|
|
5
|
+
import { localRunsOnString } from "../local-executor/runs-on-display.js";
|
|
5
6
|
import { pathToFileURL } from "node:url";
|
|
6
7
|
import path from "node:path";
|
|
7
8
|
import pc from "picocolors";
|
|
@@ -94,7 +95,7 @@ async function executeJob(job, workflowName, event, repoRoot, testSecrets, sdkSe
|
|
|
94
95
|
setStepRefMap(refMap);
|
|
95
96
|
const ctx = createStepContext({ name: workflowName }, {
|
|
96
97
|
name: job.name,
|
|
97
|
-
runsOn:
|
|
98
|
+
runsOn: localRunsOnString(job.runsOn)
|
|
98
99
|
}, repoRoot, void 0, void 0, testSecrets, void 0, event.payload, event.provider);
|
|
99
100
|
let stepCounter = 0;
|
|
100
101
|
for (const stepOrFn of job.steps) {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import "../chunk-
|
|
1
|
+
import "../chunk-BTugEXQM.js";
|
|
2
2
|
import { formatter } from "./output-formatter.js";
|
|
3
3
|
import { join } from "node:path";
|
|
4
4
|
import { chmodSync, mkdtempSync, rmSync, writeFileSync } from "node:fs";
|
|
@@ -128,14 +128,18 @@ function createStepContext(workflowInfo, jobInfo, repoRoot, inputs = {}, matrix,
|
|
|
128
128
|
return resolveJobOutputs(ref);
|
|
129
129
|
},
|
|
130
130
|
setSecretOutput: () => {},
|
|
131
|
-
kici: {
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
131
|
+
kici: {
|
|
132
|
+
infrastructure: { list: () => Promise.resolve({
|
|
133
|
+
scalers: [],
|
|
134
|
+
agents: []
|
|
135
|
+
}) },
|
|
136
|
+
oidc: { token: () => Promise.reject(/* @__PURE__ */ new Error("ctx.kici.oidc.token() is not available in the local test runner")) }
|
|
137
|
+
},
|
|
135
138
|
cache: {
|
|
136
139
|
restore: async () => ({ hit: false }),
|
|
137
140
|
save: async () => {}
|
|
138
|
-
}
|
|
141
|
+
},
|
|
142
|
+
attestProvenance: () => Promise.reject(/* @__PURE__ */ new Error("ctx.attestProvenance() is not available in the local test runner"))
|
|
139
143
|
};
|
|
140
144
|
}
|
|
141
145
|
//#endregion
|
package/dist/types.d.ts
CHANGED
|
@@ -10,8 +10,9 @@
|
|
|
10
10
|
* v8 adds runsOn polymorphic type (string | string[] | selector) and excludeLabels.
|
|
11
11
|
* v11 adds LockInlineValue type for pure function inline evaluation.
|
|
12
12
|
* v15 adds per-job init config(s).
|
|
13
|
+
* v17 widens per-job init to typed presets ('mise' / { mise }) and 'auto' detection.
|
|
13
14
|
*/
|
|
14
|
-
import type { ResourceRequest, ApproverClause } from '@kici-dev/engine';
|
|
15
|
+
import type { ResourceRequest, ApproverClause, RunsOnAllPredicate, OnUnreachableMode, LabelMatcher } from '@kici-dev/engine';
|
|
15
16
|
/**
|
|
16
17
|
* Normalized approval config carried in the lock file. Mirrors the engine
|
|
17
18
|
* `LockApproval` type. Produced by the compiler from an SDK `requireApproval`.
|
|
@@ -22,7 +23,7 @@ export interface LockApproval {
|
|
|
22
23
|
readonly timeoutSeconds?: number;
|
|
23
24
|
}
|
|
24
25
|
/** Schema version - re-exported from engine as single source of truth */
|
|
25
|
-
export declare const SCHEMA_VERSION:
|
|
26
|
+
export declare const SCHEMA_VERSION: 20;
|
|
26
27
|
/**
|
|
27
28
|
* Source file reference with meaningful path.
|
|
28
29
|
* Format: file is relative path from git root, export uses hash syntax.
|
|
@@ -370,8 +371,17 @@ export interface LockNeedsGroupEntry {
|
|
|
370
371
|
export interface LockJob {
|
|
371
372
|
readonly _type: 'static';
|
|
372
373
|
readonly name: string;
|
|
373
|
-
|
|
374
|
-
readonly
|
|
374
|
+
/** Single-agent targeting matchers. Absent when the job uses runsOnAll instead. */
|
|
375
|
+
readonly runsOn?: readonly LabelMatcher[];
|
|
376
|
+
readonly excludeLabels?: readonly LabelMatcher[];
|
|
377
|
+
/** Host fan-out predicate (mutually exclusive with runsOn). */
|
|
378
|
+
readonly runsOnAll?: RunsOnAllPredicate;
|
|
379
|
+
/** Failure policy for unreachable durable hosts in a runsOnAll fan-out. */
|
|
380
|
+
readonly onUnreachable?: OnUnreachableMode;
|
|
381
|
+
/** Fan-out concurrency width (sliding window; 1 = serial). Applies to matrix and runsOnAll. */
|
|
382
|
+
readonly maxParallel?: number;
|
|
383
|
+
/** Halt the fan-out on first child failure, skipping the held remainder. Default false. */
|
|
384
|
+
readonly failFast?: boolean;
|
|
375
385
|
readonly needs: readonly (string | LockNeedsEntry | LockNeedsGroupEntry)[];
|
|
376
386
|
/** Group names this job depends on (populated from dynamicGroup refs). */
|
|
377
387
|
readonly dependsOnGroups?: readonly string[];
|
|
@@ -425,11 +435,13 @@ export interface LockJob {
|
|
|
425
435
|
*/
|
|
426
436
|
readonly resources?: ResourceRequest;
|
|
427
437
|
/**
|
|
428
|
-
* Per-job init config(s) run after clone, before steps.
|
|
429
|
-
*
|
|
430
|
-
*
|
|
438
|
+
* Per-job init config(s) run after clone, before steps. A generic config,
|
|
439
|
+
* a typed preset (`'mise'` / `{ mise }`), an ordered array, `'auto'`
|
|
440
|
+
* (detect from committed files), or `false` (opt-out). Threaded verbatim from
|
|
441
|
+
* the SDK `Job.init` -- the agent reads it from the loaded module, the lock
|
|
442
|
+
* copy is for orchestrator/dashboard visibility.
|
|
431
443
|
*/
|
|
432
|
-
readonly init?: import('@kici-dev/sdk').
|
|
444
|
+
readonly init?: import('@kici-dev/sdk').InitConfig;
|
|
433
445
|
/** Normalized approval gate; when set the job is held before dispatch. */
|
|
434
446
|
readonly approval?: LockApproval;
|
|
435
447
|
}
|
|
@@ -445,6 +457,15 @@ export interface LockDynamicJobFn {
|
|
|
445
457
|
};
|
|
446
458
|
/** Group name for cross-domain needs (set when dynamicJob('name', fn) is used). */
|
|
447
459
|
readonly group?: string;
|
|
460
|
+
/**
|
|
461
|
+
* Declared upstream needs for a result-aware generator. When present the
|
|
462
|
+
* generator's eval job is deferred until these upstreams complete, then run
|
|
463
|
+
* with their frozen outputs available as ctx.needs. Same normalized shape as
|
|
464
|
+
* a static job's `needs`.
|
|
465
|
+
*/
|
|
466
|
+
readonly needs?: readonly (string | LockNeedsEntry | LockNeedsGroupEntry)[];
|
|
467
|
+
/** True when this dynamic entry was authored as dynamicJob(group, { needs, generate }). */
|
|
468
|
+
readonly resultAware?: boolean;
|
|
448
469
|
}
|
|
449
470
|
/** Job or dynamic job generator */
|
|
450
471
|
export type LockJobOrFactory = LockJob | LockDynamicJobFn;
|
package/dist/types.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import "./chunk-
|
|
1
|
+
import "./chunk-BTugEXQM.js";
|
|
2
2
|
import { SCHEMA_VERSION as SCHEMA_VERSION$1 } from "@kici-dev/engine";
|
|
3
3
|
//#region src/types.ts
|
|
4
4
|
/**
|
|
@@ -13,6 +13,7 @@ import { SCHEMA_VERSION as SCHEMA_VERSION$1 } from "@kici-dev/engine";
|
|
|
13
13
|
* v8 adds runsOn polymorphic type (string | string[] | selector) and excludeLabels.
|
|
14
14
|
* v11 adds LockInlineValue type for pure function inline evaluation.
|
|
15
15
|
* v15 adds per-job init config(s).
|
|
16
|
+
* v17 widens per-job init to typed presets ('mise' / { mise }) and 'auto' detection.
|
|
16
17
|
*/
|
|
17
18
|
/** Schema version - re-exported from engine as single source of truth */
|
|
18
19
|
const SCHEMA_VERSION = SCHEMA_VERSION$1;
|
package/dist/validation/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import "../chunk-
|
|
1
|
+
import "../chunk-BTugEXQM.js";
|
|
2
2
|
import { compilerError } from "../errors/formatter.js";
|
|
3
3
|
import "../errors/index.js";
|
|
4
4
|
import { getDynamicJobGroup, isDynamicGroupRef, isDynamicJobFn, isStaticArray, isStaticObject, validateDag } from "@kici-dev/sdk";
|
|
@@ -26,7 +26,7 @@ export const prChecksWorkflow = workflow('pr-checks', {
|
|
|
26
26
|
// Jobs: run in parallel unless connected via `needs`
|
|
27
27
|
jobs: [
|
|
28
28
|
job('lint', {
|
|
29
|
-
runsOn: '
|
|
29
|
+
runsOn: 'kici:os:linux',
|
|
30
30
|
steps: [
|
|
31
31
|
step('checkout', async ({ $ }) => {
|
|
32
32
|
await $`echo "Checking out code..."`;
|
|
@@ -39,7 +39,7 @@ export const prChecksWorkflow = workflow('pr-checks', {
|
|
|
39
39
|
}),
|
|
40
40
|
|
|
41
41
|
job('test', {
|
|
42
|
-
runsOn: '
|
|
42
|
+
runsOn: 'kici:os:linux',
|
|
43
43
|
needs: ['lint'], // Waits for lint to pass
|
|
44
44
|
steps: [
|
|
45
45
|
step('checkout', async ({ $ }) => {
|