@kici-dev/compiler 0.1.25 → 0.1.27
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/cli-banner.d.ts +6 -3
- package/dist/cli-banner.js +13 -5
- package/dist/cli.js +66 -43
- package/dist/commands/check-mode.d.ts +1 -1
- package/dist/commands/compile.js +3 -3
- package/dist/commands/index.d.ts +5 -1
- package/dist/commands/index.js +6 -3
- package/dist/commands/init.js +1 -1
- package/dist/commands/local-trust-root.d.ts +6 -0
- package/dist/commands/local-trust-root.js +52 -0
- package/dist/commands/local.d.ts +39 -0
- package/dist/commands/local.js +137 -0
- package/dist/commands/login.d.ts +2 -0
- package/dist/commands/login.js +40 -0
- package/dist/commands/logout.js +7 -0
- package/dist/commands/preview.js +1 -1
- package/dist/commands/run-banner.d.ts +31 -0
- package/dist/commands/run-banner.js +25 -0
- package/dist/commands/run-routed.d.ts +53 -0
- package/dist/commands/run-routed.js +176 -0
- package/dist/commands/run.d.ts +0 -17
- package/dist/commands/run.js +7 -50
- package/dist/commands/secrets-list.d.ts +2 -2
- package/dist/commands/secrets-list.js +4 -4
- package/dist/commands/types.d.ts +3 -3
- package/dist/commands/types.js +4 -4
- package/dist/execution/executor.js +7 -7
- package/dist/generators/secrets-dts.d.ts +9 -9
- package/dist/generators/secrets-dts.js +12 -12
- package/dist/llm-context/llms-architecture.txt +2 -2
- package/dist/llm-context/llms-cli.txt +674 -340
- package/dist/llm-context/llms-features.txt +334 -336
- package/dist/llm-context/llms-full.txt +1207 -892
- package/dist/llm-context/llms-getting-started.txt +7 -15
- package/dist/llm-context/llms-patterns.txt +5 -23
- package/dist/llm-context/llms-providers.txt +10 -1
- package/dist/llm-context/llms-sdk.txt +12 -12
- package/dist/llm-context/llms.txt +5 -5
- package/dist/local-executor/secret-loader.d.ts +1 -1
- package/dist/local-plane/orchestrator-process.d.ts +65 -0
- package/dist/local-plane/orchestrator-process.js +115 -0
- package/dist/local-plane/paths.d.ts +39 -0
- package/dist/local-plane/paths.js +54 -0
- package/dist/local-plane/plane-manager.d.ts +151 -0
- package/dist/local-plane/plane-manager.js +340 -0
- package/dist/local-plane/plane-seed.d.ts +76 -0
- package/dist/local-plane/plane-seed.js +59 -0
- package/dist/local-plane/plane-trigger.d.ts +62 -0
- package/dist/local-plane/plane-trigger.js +97 -0
- package/dist/local-plane/platform-attach.d.ts +53 -0
- package/dist/local-plane/platform-attach.js +111 -0
- package/dist/local-plane/postgres.d.ts +44 -0
- package/dist/local-plane/postgres.js +165 -0
- package/dist/local-plane/resolve-plane.d.ts +37 -0
- package/dist/local-plane/resolve-plane.js +76 -0
- package/dist/local-plane/run-follow.d.ts +41 -0
- package/dist/local-plane/run-follow.js +104 -0
- package/dist/local-plane/scaler-config.d.ts +54 -0
- package/dist/local-plane/scaler-config.js +114 -0
- package/dist/local-plane/secret-seed.d.ts +59 -0
- package/dist/local-plane/secret-seed.js +112 -0
- package/dist/local-plane/source-provider.d.ts +43 -0
- package/dist/local-plane/source-provider.js +165 -0
- package/dist/local-plane/trusted-routing.d.ts +32 -0
- package/dist/local-plane/trusted-routing.js +47 -0
- package/dist/lockfile/generator.js +7 -7
- package/dist/remote/dashboard-client.d.ts +7 -7
- package/dist/remote/dashboard-client.js +7 -7
- package/dist/remote/platform-client.d.ts +1 -1
- package/dist/remote/secret-loader.d.ts +18 -0
- package/dist/{local-executor → remote}/secret-loader.js +4 -4
- package/dist/remote/secret-upload.d.ts +1 -1
- package/dist/remote/secret-upload.js +2 -2
- package/dist/remote/uploader.d.ts +1 -1
- package/dist/remote/uploader.js +2 -2
- package/dist/templates/agents-md.d.ts +1 -1
- package/dist/templates/agents-md.js +2 -2
- package/dist/templates/package-json.js +1 -1
- package/dist/test-runner/job-executor.js +1 -1
- package/dist/test-runner/runs-on-display.d.ts +9 -0
- package/dist/{local-executor → test-runner}/runs-on-display.js +1 -1
- package/dist/test-runner/step-context.d.ts +1 -1
- package/dist/test-runner/step-context.js +2 -2
- package/dist/types.d.ts +6 -6
- package/package.json +7 -4
- package/sbom.spdx.json +9884 -1459
- package/dist/local-executor/dag-scheduler.js +0 -183
- package/dist/local-executor/index.js +0 -378
- package/dist/local-executor/job-runner.js +0 -411
- package/dist/local-executor/materializer.js +0 -132
- package/dist/local-executor/output-streamer.js +0 -168
- package/dist/local-executor/payload-generator.js +0 -138
- package/dist/local-executor/picker.js +0 -109
- package/dist/local-executor/to-event-payload.js +0 -21
- package/dist/local-executor/types.js +0 -2
- package/dist/local-executor/workflow-lock.js +0 -0
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Route a `kici run --local --trusted` run onto the plane's trusted label set
|
|
3
|
+
* by appending a routing label to every job's `runsOn` in the workdir lock the
|
|
4
|
+
* plane orchestrator reads.
|
|
5
|
+
*
|
|
6
|
+
* The orchestrator resolves each job's target agent from the lock's `runsOn`
|
|
7
|
+
* selectors (subset match + smallest-set-wins in the scaler label matcher).
|
|
8
|
+
* A default run leaves `runsOn` untouched, so a `runsOn: ['default']` job lands
|
|
9
|
+
* on the sandboxed `['default']` label set — byte-identical to a non-trusted
|
|
10
|
+
* run. `--trusted` appends the non-reserved `self-hosted` label, which only the
|
|
11
|
+
* trusted `['default','self-hosted']` label set carries, forcing every job onto
|
|
12
|
+
* the trusted profile.
|
|
13
|
+
*
|
|
14
|
+
* This is routing-by-label to a PRE-CONFIGURED trusted scaler label set — the
|
|
15
|
+
* `KICI_TRUSTED_ENV` value lives only in that label set's env (the plane's own
|
|
16
|
+
* config), never on a dispatch payload. The lock patch adds a label
|
|
17
|
+
* requirement, not the trusted flag itself.
|
|
18
|
+
*/
|
|
19
|
+
/** Handle to restore the lock to its pre-patch bytes. */
|
|
20
|
+
export interface RunsOnLabelInjection {
|
|
21
|
+
/** Rewrite the original bytes captured before the patch. */
|
|
22
|
+
restore: () => void;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Append an exact-match `runsOn` selector for `label` to every job in the lock
|
|
26
|
+
* at `lockPath`, unless the job already requires it. Returns a `restore()` that
|
|
27
|
+
* rewrites the original file bytes (call it in a `finally` — for an in-place run
|
|
28
|
+
* it un-dirties the developer's tree; for an isolated run the throwaway clone is
|
|
29
|
+
* removed anyway).
|
|
30
|
+
*/
|
|
31
|
+
export declare function injectRunsOnLabel(lockPath: string, label: string): RunsOnLabelInjection;
|
|
32
|
+
//# sourceMappingURL=trusted-routing.d.ts.map
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import "../rolldown-runtime-ClRpJifh.js";
|
|
2
|
+
import fs from "node:fs";
|
|
3
|
+
//#region src/local-plane/trusted-routing.ts
|
|
4
|
+
/**
|
|
5
|
+
* Route a `kici run --local --trusted` run onto the plane's trusted label set
|
|
6
|
+
* by appending a routing label to every job's `runsOn` in the workdir lock the
|
|
7
|
+
* plane orchestrator reads.
|
|
8
|
+
*
|
|
9
|
+
* The orchestrator resolves each job's target agent from the lock's `runsOn`
|
|
10
|
+
* selectors (subset match + smallest-set-wins in the scaler label matcher).
|
|
11
|
+
* A default run leaves `runsOn` untouched, so a `runsOn: ['default']` job lands
|
|
12
|
+
* on the sandboxed `['default']` label set — byte-identical to a non-trusted
|
|
13
|
+
* run. `--trusted` appends the non-reserved `self-hosted` label, which only the
|
|
14
|
+
* trusted `['default','self-hosted']` label set carries, forcing every job onto
|
|
15
|
+
* the trusted profile.
|
|
16
|
+
*
|
|
17
|
+
* This is routing-by-label to a PRE-CONFIGURED trusted scaler label set — the
|
|
18
|
+
* `KICI_TRUSTED_ENV` value lives only in that label set's env (the plane's own
|
|
19
|
+
* config), never on a dispatch payload. The lock patch adds a label
|
|
20
|
+
* requirement, not the trusted flag itself.
|
|
21
|
+
*/
|
|
22
|
+
/**
|
|
23
|
+
* Append an exact-match `runsOn` selector for `label` to every job in the lock
|
|
24
|
+
* at `lockPath`, unless the job already requires it. Returns a `restore()` that
|
|
25
|
+
* rewrites the original file bytes (call it in a `finally` — for an in-place run
|
|
26
|
+
* it un-dirties the developer's tree; for an isolated run the throwaway clone is
|
|
27
|
+
* removed anyway).
|
|
28
|
+
*/
|
|
29
|
+
function injectRunsOnLabel(lockPath, label) {
|
|
30
|
+
const original = fs.readFileSync(lockPath, "utf-8");
|
|
31
|
+
const lock = JSON.parse(original);
|
|
32
|
+
for (const workflow of lock.workflows ?? []) for (const job of workflow.jobs ?? []) {
|
|
33
|
+
const runsOn = job.runsOn ??= [];
|
|
34
|
+
if (!runsOn.some((m) => m.kind === "exact" && m.value === label)) runsOn.push({
|
|
35
|
+
kind: "exact",
|
|
36
|
+
value: label
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
fs.writeFileSync(lockPath, JSON.stringify(lock, null, 2) + "\n");
|
|
40
|
+
return { restore: () => {
|
|
41
|
+
fs.writeFileSync(lockPath, original);
|
|
42
|
+
} };
|
|
43
|
+
}
|
|
44
|
+
//#endregion
|
|
45
|
+
export { injectRunsOnLabel };
|
|
46
|
+
|
|
47
|
+
//# sourceMappingURL=trusted-routing.js.map
|
|
@@ -485,12 +485,12 @@ function validateRunsOn(runsOn, jobName) {
|
|
|
485
485
|
if (overlap.length > 0) throw new Error(`Job "${jobName}": labels and exclude overlap on [${overlap.join(", ")}]. A label cannot be both required and excluded.`);
|
|
486
486
|
}
|
|
487
487
|
/**
|
|
488
|
-
* Transform one
|
|
488
|
+
* Transform one context reference (static name or function) into a lock
|
|
489
489
|
* `{ value, dynamic }` entry. A function element is analyzed for purity: a pure
|
|
490
490
|
* function becomes an inline expression resolvable at two-phase eval; an impure
|
|
491
491
|
* one carries only the `dynamic` flag (the agent runs an init job to resolve it).
|
|
492
492
|
*/
|
|
493
|
-
function
|
|
493
|
+
function transformContextRef(ref, jobName) {
|
|
494
494
|
if (typeof ref === "function") {
|
|
495
495
|
const fnSource = ref.toString();
|
|
496
496
|
const purity = analyzePurity(fnSource);
|
|
@@ -501,7 +501,7 @@ function transformEnvironmentRef(ref, jobName) {
|
|
|
501
501
|
},
|
|
502
502
|
dynamic: true
|
|
503
503
|
};
|
|
504
|
-
console.warn(`[kici] Job "${jobName}":
|
|
504
|
+
console.warn(`[kici] Job "${jobName}": context function is not pure (${purity.reason}). An init job will be required, adding ~5-10s delay.`);
|
|
505
505
|
return {
|
|
506
506
|
value: "",
|
|
507
507
|
dynamic: true
|
|
@@ -522,9 +522,9 @@ function transformJob(job, configPath, index, gitRoot, uuidToName) {
|
|
|
522
522
|
if (job.maxParallel !== void 0 && job.maxParallel < 1) throw new Error(`job '${job.name}': maxParallel must be >= 1`);
|
|
523
523
|
if (!(job.matrix !== void 0 || job.runsOnAll !== void 0) && (job.maxParallel !== void 0 || job.failFast !== void 0)) console.warn(`[kici] job '${job.name}': maxParallel/failFast are ignored without matrix or runsOnAll (no fan-out to bound)`);
|
|
524
524
|
if (job.runsOn !== void 0) validateRunsOn(job.runsOn, job.name);
|
|
525
|
-
const
|
|
526
|
-
const
|
|
527
|
-
if (
|
|
525
|
+
const contextFields = {};
|
|
526
|
+
const contextRefs = job.contexts ?? (job.context !== void 0 ? [job.context] : void 0);
|
|
527
|
+
if (contextRefs !== void 0 && contextRefs.length > 0) contextFields.contexts = contextRefs.map((ref) => transformContextRef(ref, job.name));
|
|
528
528
|
const envFields = {};
|
|
529
529
|
if (job.env !== void 0) {
|
|
530
530
|
if (typeof job.env === "function") {
|
|
@@ -576,7 +576,7 @@ function transformJob(job, configPath, index, gitRoot, uuidToName) {
|
|
|
576
576
|
...job.checkout !== void 0 && { checkout: job.checkout },
|
|
577
577
|
...job.cache !== void 0 && { cache: normalizeCacheSpecs(job.cache) },
|
|
578
578
|
...job.container !== void 0 && { container: job.container },
|
|
579
|
-
...
|
|
579
|
+
...contextFields,
|
|
580
580
|
...envFields,
|
|
581
581
|
...concurrencyFields,
|
|
582
582
|
...job.onCancel !== void 0 && { hasOnCancel: true },
|
|
@@ -36,18 +36,18 @@ export interface RegistrationsListFilters {
|
|
|
36
36
|
repoIdentifier?: string;
|
|
37
37
|
}
|
|
38
38
|
/**
|
|
39
|
-
* A secret context (
|
|
39
|
+
* A secret context (context) as surfaced to the developer CLI's
|
|
40
40
|
* `secrets list` / `types` commands. The orchestrator returns the per-env
|
|
41
41
|
* secret key names (never values) when `includeSecrets` is requested.
|
|
42
42
|
*/
|
|
43
|
-
declare const
|
|
43
|
+
declare const contextContextSchema: z.ZodObject<{
|
|
44
44
|
name: z.ZodString;
|
|
45
45
|
enabled: z.ZodBoolean;
|
|
46
46
|
allowLocalExecution: z.ZodBoolean;
|
|
47
47
|
secretKeys: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
48
48
|
}, z.core.$strip>;
|
|
49
|
-
/** A secret context (
|
|
50
|
-
export type
|
|
49
|
+
/** A secret context (context) returned by {@link DashboardClient.listContexts}. */
|
|
50
|
+
export type ContextContext = z.infer<typeof contextContextSchema>;
|
|
51
51
|
export declare class DashboardClient {
|
|
52
52
|
private readonly endpoint;
|
|
53
53
|
private readonly token;
|
|
@@ -80,13 +80,13 @@ export declare class DashboardClient {
|
|
|
80
80
|
/** List the org's permanently registered workflows (GET /registrations). */
|
|
81
81
|
listRegistrations(filters?: RegistrationsListFilters): Promise<RegistrationsListResult>;
|
|
82
82
|
/**
|
|
83
|
-
* List the org's
|
|
83
|
+
* List the org's contexts as secret contexts (GET /contexts).
|
|
84
84
|
*
|
|
85
|
-
* Pass `includeSecrets` to have the orchestrator attach each
|
|
85
|
+
* Pass `includeSecrets` to have the orchestrator attach each context's
|
|
86
86
|
* reachable secret key names (never values). Used by `kici secrets list`
|
|
87
87
|
* and `kici types`.
|
|
88
88
|
*/
|
|
89
|
-
|
|
89
|
+
listContexts(includeSecrets?: boolean): Promise<ContextContext[]>;
|
|
90
90
|
}
|
|
91
91
|
export {};
|
|
92
92
|
//# sourceMappingURL=dashboard-client.d.ts.map
|
|
@@ -29,17 +29,17 @@ const registrationsListSchema = z.object({
|
|
|
29
29
|
registryUpdatedAt: z.string()
|
|
30
30
|
});
|
|
31
31
|
/**
|
|
32
|
-
* A secret context (
|
|
32
|
+
* A secret context (context) as surfaced to the developer CLI's
|
|
33
33
|
* `secrets list` / `types` commands. The orchestrator returns the per-env
|
|
34
34
|
* secret key names (never values) when `includeSecrets` is requested.
|
|
35
35
|
*/
|
|
36
|
-
const
|
|
36
|
+
const contextContextSchema = z.object({
|
|
37
37
|
name: z.string(),
|
|
38
38
|
enabled: z.boolean(),
|
|
39
39
|
allowLocalExecution: z.boolean(),
|
|
40
40
|
secretKeys: z.array(z.string()).default([])
|
|
41
41
|
});
|
|
42
|
-
const
|
|
42
|
+
const contextsListSchema = z.object({ contexts: z.array(contextContextSchema).default([]) });
|
|
43
43
|
const STATUS_ERROR_MAP = {
|
|
44
44
|
401: ["unauthorized", "Authentication failed. Run `kici login` to re-authenticate."],
|
|
45
45
|
403: ["forbidden", "Access denied."],
|
|
@@ -151,15 +151,15 @@ var DashboardClient = class DashboardClient {
|
|
|
151
151
|
return registrationsListSchema.parse(await this.getJson(`/registrations${suffix}`));
|
|
152
152
|
}
|
|
153
153
|
/**
|
|
154
|
-
* List the org's
|
|
154
|
+
* List the org's contexts as secret contexts (GET /contexts).
|
|
155
155
|
*
|
|
156
|
-
* Pass `includeSecrets` to have the orchestrator attach each
|
|
156
|
+
* Pass `includeSecrets` to have the orchestrator attach each context's
|
|
157
157
|
* reachable secret key names (never values). Used by `kici secrets list`
|
|
158
158
|
* and `kici types`.
|
|
159
159
|
*/
|
|
160
|
-
async
|
|
160
|
+
async listContexts(includeSecrets = false) {
|
|
161
161
|
const suffix = includeSecrets ? "?includeSecrets=true" : "";
|
|
162
|
-
return
|
|
162
|
+
return contextsListSchema.parse(await this.getJson(`/contexts${suffix}`)).contexts;
|
|
163
163
|
}
|
|
164
164
|
};
|
|
165
165
|
//#endregion
|
|
@@ -94,7 +94,7 @@ export interface PlatformTriggerResponse {
|
|
|
94
94
|
status: 'accepted' | 'rejected';
|
|
95
95
|
reason?: string;
|
|
96
96
|
jobIds?: string[];
|
|
97
|
-
/** User-visible warnings on acceptance (e.g. skipped non-test bound
|
|
97
|
+
/** User-visible warnings on acceptance (e.g. skipped non-test bound contexts). */
|
|
98
98
|
warnings?: string[];
|
|
99
99
|
}
|
|
100
100
|
export interface PlatformRunStatusResponse {
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { ParsedSecrets } from '../test-runner/secrets-file.js';
|
|
2
|
+
/**
|
|
3
|
+
* Load secrets from multiple sources with merge precedence.
|
|
4
|
+
*
|
|
5
|
+
* Merge order (lowest to highest priority):
|
|
6
|
+
* 1. .kici/.secrets (INI-style, backward compat)
|
|
7
|
+
* 2. .kici/.env.local (dotenv format)
|
|
8
|
+
* 3. .kici/secrets.yaml (YAML with context scopes, merged flat)
|
|
9
|
+
* 4. --env KEY=VALUE CLI flags
|
|
10
|
+
*
|
|
11
|
+
* Note: process.env is NOT merged here -- it's handled at step-context level.
|
|
12
|
+
*
|
|
13
|
+
* @param kiciDir - Path to the .kici directory
|
|
14
|
+
* @param envFlags - Optional --env KEY=VALUE flag values
|
|
15
|
+
* @returns Merged secrets with correct precedence
|
|
16
|
+
*/
|
|
17
|
+
export declare function loadLocalSecrets(kiciDir: string, envFlags?: string[]): Promise<ParsedSecrets>;
|
|
18
|
+
//# sourceMappingURL=secret-loader.d.ts.map
|
|
@@ -3,7 +3,7 @@ import { loadSecretsFile } from "../test-runner/secrets-file.js";
|
|
|
3
3
|
import path from "node:path";
|
|
4
4
|
import { readFile } from "node:fs/promises";
|
|
5
5
|
import { parse } from "yaml";
|
|
6
|
-
//#region src/
|
|
6
|
+
//#region src/remote/secret-loader.ts
|
|
7
7
|
/**
|
|
8
8
|
* Parse a dotenv-style file (.env.local) into flat key-value pairs.
|
|
9
9
|
* Lines starting with # are comments. Blank lines are ignored.
|
|
@@ -24,8 +24,8 @@ function parseDotenv(content) {
|
|
|
24
24
|
}
|
|
25
25
|
/**
|
|
26
26
|
* Parse a secrets.yaml file.
|
|
27
|
-
* Expected format: top-level keys are
|
|
28
|
-
* For local execution, all
|
|
27
|
+
* Expected format: top-level keys are context names, values are key-value maps.
|
|
28
|
+
* For local execution, all contexts are merged flat (no context resolution).
|
|
29
29
|
*/
|
|
30
30
|
function parseSecretsYaml(content) {
|
|
31
31
|
const parsed = parse(content);
|
|
@@ -66,7 +66,7 @@ async function readFileOrNull(filePath) {
|
|
|
66
66
|
* Merge order (lowest to highest priority):
|
|
67
67
|
* 1. .kici/.secrets (INI-style, backward compat)
|
|
68
68
|
* 2. .kici/.env.local (dotenv format)
|
|
69
|
-
* 3. .kici/secrets.yaml (YAML with
|
|
69
|
+
* 3. .kici/secrets.yaml (YAML with context scopes, merged flat)
|
|
70
70
|
* 4. --env KEY=VALUE CLI flags
|
|
71
71
|
*
|
|
72
72
|
* Note: process.env is NOT merged here -- it's handled at step-context level.
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
*/
|
|
7
7
|
export declare function parseContextFlags(flags: string[] | undefined): Record<string, Record<string, string>>;
|
|
8
8
|
/**
|
|
9
|
-
* Load the developer's local secrets (same sources as `kici run local`: the
|
|
9
|
+
* Load the developer's local secrets (same sources as `kici run --local`: the
|
|
10
10
|
* `.kici` secret files plus `--env` flat flags) and `--context` namespaced
|
|
11
11
|
* flags, and encrypt them to the orchestrator's per-upload X25519 public key.
|
|
12
12
|
* `--context` values override `.kici/.secrets` file contexts for the same key.
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import "../rolldown-runtime-ClRpJifh.js";
|
|
2
|
-
import { loadLocalSecrets } from "
|
|
2
|
+
import { loadLocalSecrets } from "./secret-loader.js";
|
|
3
3
|
import { encryptJson } from "@kici-dev/core";
|
|
4
4
|
//#region src/remote/secret-upload.ts
|
|
5
5
|
/**
|
|
@@ -25,7 +25,7 @@ function parseContextFlags(flags) {
|
|
|
25
25
|
return contexts;
|
|
26
26
|
}
|
|
27
27
|
/**
|
|
28
|
-
* Load the developer's local secrets (same sources as `kici run local`: the
|
|
28
|
+
* Load the developer's local secrets (same sources as `kici run --local`: the
|
|
29
29
|
* `.kici` secret files plus `--env` flat flags) and `--context` namespaced
|
|
30
30
|
* flags, and encrypt them to the orchestrator's per-upload X25519 public key.
|
|
31
31
|
* `--context` values override `.kici/.secrets` file contexts for the same key.
|
|
@@ -82,7 +82,7 @@ export interface OverlaySelection {
|
|
|
82
82
|
* When `fullWorkingTree` is set (the `kici run remote` path), the entire
|
|
83
83
|
* `.git` directory is additively included so the extracted overlay is a real
|
|
84
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
|
|
85
|
+
* exactly as they do under `kici run --local`. The `.git` files are added after
|
|
86
86
|
* `.kiciignore` filtering (git internals are never subject to working-tree
|
|
87
87
|
* ignore globs).
|
|
88
88
|
*
|
package/dist/remote/uploader.js
CHANGED
|
@@ -44,7 +44,7 @@ function isGitDirPath(relPath) {
|
|
|
44
44
|
* clone on the agent — we enumerate the directory explicitly. Including the
|
|
45
45
|
* whole `.git` directory (objects, refs, HEAD, index, config, packed-refs)
|
|
46
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`.
|
|
47
|
+
* shell out to git work exactly as they do under `kici run --local`.
|
|
48
48
|
*/
|
|
49
49
|
async function collectGitDirFiles(repoRoot) {
|
|
50
50
|
const gitRoot = path.join(repoRoot, ".git");
|
|
@@ -94,7 +94,7 @@ async function loadKiciIgnore(kiciIgnorePath) {
|
|
|
94
94
|
* When `fullWorkingTree` is set (the `kici run remote` path), the entire
|
|
95
95
|
* `.git` directory is additively included so the extracted overlay is a real
|
|
96
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
|
|
97
|
+
* exactly as they do under `kici run --local`. The `.git` files are added after
|
|
98
98
|
* `.kiciignore` filtering (git internals are never subject to working-tree
|
|
99
99
|
* ignore globs).
|
|
100
100
|
*
|
|
@@ -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: '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 preview pr:open --debug` | Preview which workflows match an event. |\n| `pnpm kici run local
|
|
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 preview pr:open --debug` | Preview which workflows match an event. |\n| `pnpm kici run push --local` | Execute a workflow locally (this machine as an ephemeral agent). |\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 preview <event>` to preview matching.\n6. Run `kici run <event> --local` to execute locally before pushing.\n";
|
|
8
8
|
//# sourceMappingURL=agents-md.d.ts.map
|
|
@@ -113,7 +113,7 @@ into a portable lock file, and executed by self-hosted agents.
|
|
|
113
113
|
| ------------------------------- | ------------------------------------------- |
|
|
114
114
|
| \`pnpm kici compile --check\` | Validate workflow source without writing. |
|
|
115
115
|
| \`pnpm kici preview pr:open --debug\` | Preview which workflows match an event. |
|
|
116
|
-
| \`pnpm kici run local
|
|
116
|
+
| \`pnpm kici run push --local\` | Execute a workflow locally (this machine as an ephemeral agent). |
|
|
117
117
|
| \`pnpm kici docs llm\` | Print the full LLM documentation bundle. |
|
|
118
118
|
| \`pnpm kici docs llm --index\` | Print the curated link index. |
|
|
119
119
|
|
|
@@ -127,7 +127,7 @@ If \`pnpm kici\` isn't in scripts, fall back to \`npx kici\`.
|
|
|
127
127
|
3. Edit a workflow under \`.kici/workflows/\`.
|
|
128
128
|
4. Run \`kici compile --check\` (zero exit means valid).
|
|
129
129
|
5. Run \`kici preview <event>\` to preview matching.
|
|
130
|
-
6. Run \`kici run
|
|
130
|
+
6. Run \`kici run <event> --local\` to execute locally before pushing.
|
|
131
131
|
`;
|
|
132
132
|
//#endregion
|
|
133
133
|
export { agentsMdTemplate };
|
|
@@ -2,7 +2,7 @@ import "../rolldown-runtime-ClRpJifh.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 "
|
|
5
|
+
import { localRunsOnString } from "./runs-on-display.js";
|
|
6
6
|
import { pathToFileURL } from "node:url";
|
|
7
7
|
import path from "node:path";
|
|
8
8
|
import pc from "picocolors";
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { RunsOn } from '@kici-dev/sdk';
|
|
2
|
+
/**
|
|
3
|
+
* Render a job's `runsOn` to the comma-joined label string the local/test
|
|
4
|
+
* runners surface as `ctx.job.runsOn`. A `runsOnAll` job has no `runsOn` —
|
|
5
|
+
* locally it runs once on this machine, so we surface the marker `'runsOnAll'`.
|
|
6
|
+
* RegExp selectors render via their `/source/flags` literal.
|
|
7
|
+
*/
|
|
8
|
+
export declare function localRunsOnString(runsOn: RunsOn | undefined): string;
|
|
9
|
+
//# sourceMappingURL=runs-on-display.d.ts.map
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import "../rolldown-runtime-ClRpJifh.js";
|
|
2
|
-
//#region src/
|
|
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;
|
|
@@ -11,5 +11,5 @@ import type { StepContext, WorkflowInfo, JobInfo, MatrixValues } from '@kici-dev
|
|
|
11
11
|
export declare function createStepContext(workflowInfo: WorkflowInfo, jobInfo: JobInfo, repoRoot: string, inputs?: Record<string, unknown>, matrix?: MatrixValues, testSecrets?: {
|
|
12
12
|
flat: Record<string, string>;
|
|
13
13
|
contexts: Record<string, Record<string, string>>;
|
|
14
|
-
},
|
|
14
|
+
}, context?: string, rawPayload?: Record<string, unknown>, provider?: string, dispatchInputs?: Readonly<Record<string, string | number | boolean | null>>, signal?: AbortSignal): StepContext;
|
|
15
15
|
//# sourceMappingURL=step-context.d.ts.map
|
|
@@ -42,7 +42,7 @@ function createTestLogger(jobName) {
|
|
|
42
42
|
* `ctx.$` would inherit `process.cwd()` — i.e. wherever the user invoked
|
|
43
43
|
* `kici` — which silently breaks any step that uses relative paths.
|
|
44
44
|
*/
|
|
45
|
-
function createStepContext(workflowInfo, jobInfo, repoRoot, inputs = {}, matrix, testSecrets,
|
|
45
|
+
function createStepContext(workflowInfo, jobInfo, repoRoot, inputs = {}, matrix, testSecrets, context, rawPayload, provider, dispatchInputs = {}, signal = new AbortController().signal) {
|
|
46
46
|
const flat = testSecrets?.flat ?? {};
|
|
47
47
|
const namespacedSecrets = testSecrets?.contexts ?? {};
|
|
48
48
|
const mergedFlat = { ...flat };
|
|
@@ -116,7 +116,7 @@ function createStepContext(workflowInfo, jobInfo, repoRoot, inputs = {}, matrix,
|
|
|
116
116
|
job: jobInfo,
|
|
117
117
|
matrix,
|
|
118
118
|
isTestRun: false,
|
|
119
|
-
|
|
119
|
+
context,
|
|
120
120
|
...rawPayload && { rawPayload },
|
|
121
121
|
...provider && { provider },
|
|
122
122
|
secrets: secretsHandle.secrets,
|
package/dist/types.d.ts
CHANGED
|
@@ -28,7 +28,7 @@ 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:
|
|
31
|
+
export declare const SCHEMA_VERSION: 30;
|
|
32
32
|
/**
|
|
33
33
|
* Source file reference with meaningful path.
|
|
34
34
|
* Format: file is relative path from git root, export uses hash syntax.
|
|
@@ -441,11 +441,11 @@ export interface LockJob {
|
|
|
441
441
|
env?: Record<string, string>;
|
|
442
442
|
};
|
|
443
443
|
/**
|
|
444
|
-
*
|
|
444
|
+
* Bound contexts in merge order. Each entry is a static name or inline
|
|
445
445
|
* expression (pure function); `dynamic` is set when it is a function resolved at
|
|
446
446
|
* two-phase eval. Later entries override earlier ones on name collisions.
|
|
447
447
|
*/
|
|
448
|
-
readonly
|
|
448
|
+
readonly contexts?: ReadonlyArray<{
|
|
449
449
|
value: string | LockInlineValue;
|
|
450
450
|
dynamic: boolean;
|
|
451
451
|
}>;
|
|
@@ -517,12 +517,12 @@ export type LockJobOrFactory = LockJob | LockDynamicJobFn;
|
|
|
517
517
|
/**
|
|
518
518
|
* Private npm registry declaration in the lock file.
|
|
519
519
|
* Carries URL/scope/secret-reference but NOT the resolved token — the orchestrator
|
|
520
|
-
* resolves the token at dispatch via the per-
|
|
520
|
+
* resolves the token at dispatch via the per-context secretResolver path.
|
|
521
521
|
*/
|
|
522
522
|
export interface LockRegistry {
|
|
523
523
|
readonly url: string;
|
|
524
524
|
readonly scope?: string;
|
|
525
|
-
/** Qualified secret reference: `<
|
|
525
|
+
/** Qualified secret reference: `<context>:<secret-name>`. */
|
|
526
526
|
readonly tokenSecret: string;
|
|
527
527
|
readonly alwaysAuth?: boolean;
|
|
528
528
|
}
|
|
@@ -554,7 +554,7 @@ export interface LockWorkflow {
|
|
|
554
554
|
*/
|
|
555
555
|
readonly registries?: readonly LockRegistry[];
|
|
556
556
|
/**
|
|
557
|
-
* Extra qualified secret refs (`<
|
|
557
|
+
* Extra qualified secret refs (`<context>:<secret-name>`) to project as env vars
|
|
558
558
|
* on the install subprocess for use with a customer-committed `.kici/.npmrc`.
|
|
559
559
|
*/
|
|
560
560
|
readonly installEnv?: readonly string[];
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kici-dev/compiler",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.27",
|
|
4
4
|
"description": "Compiler and CLI for KiCI workflows. Compiles `.kici/workflows/*.ts` to a `kici.lock.json` file consumed by the orchestrator and agents, and runs workflows locally or against a remote orchestrator.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ci",
|
|
@@ -49,6 +49,7 @@
|
|
|
49
49
|
"@inquirer/prompts": "^8.5.2",
|
|
50
50
|
"chokidar": "^5.0.0",
|
|
51
51
|
"commander": "^15.0.0",
|
|
52
|
+
"embedded-postgres": "18.4.0-beta.17",
|
|
52
53
|
"fast-glob": "^3.3.3",
|
|
53
54
|
"open": "^11.0.0",
|
|
54
55
|
"picocolors": "^1.1.1",
|
|
@@ -60,11 +61,13 @@
|
|
|
60
61
|
"yaml": "^2.9.0",
|
|
61
62
|
"zod": "^4.4.3",
|
|
62
63
|
"zx": "^8.8.5",
|
|
63
|
-
"@kici-dev/
|
|
64
|
-
"@kici-dev/
|
|
64
|
+
"@kici-dev/orchestrator": "0.1.27",
|
|
65
|
+
"@kici-dev/core": "0.1.27",
|
|
66
|
+
"@kici-dev/agent": "0.1.27",
|
|
67
|
+
"@kici-dev/engine": "0.1.27"
|
|
65
68
|
},
|
|
66
69
|
"peerDependencies": {
|
|
67
|
-
"@kici-dev/sdk": "0.1.
|
|
70
|
+
"@kici-dev/sdk": "0.1.27"
|
|
68
71
|
},
|
|
69
72
|
"devDependencies": {
|
|
70
73
|
"@types/proper-lockfile": "^4.1.4"
|