@kici-dev/compiler 0.6.1 → 0.7.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 (41) hide show
  1. package/dist/cli.js +1 -1
  2. package/dist/commands/compile.js +5 -1
  3. package/dist/commands/doctor.js +8 -2
  4. package/dist/commands/init.d.ts +9 -0
  5. package/dist/commands/init.js +77 -12
  6. package/dist/commands/preview.js +1 -1
  7. package/dist/commands/report/identity.d.ts +11 -0
  8. package/dist/commands/report/identity.js +7 -2
  9. package/dist/commands/run-routed.js +1 -0
  10. package/dist/commands/types.d.ts +6 -1
  11. package/dist/commands/types.js +2 -1
  12. package/dist/execution/executor.js +7 -1
  13. package/dist/llm-context/llms-architecture.txt +72 -86
  14. package/dist/llm-context/llms-cli-remote.txt +40 -7
  15. package/dist/llm-context/llms-cli.txt +67 -34
  16. package/dist/llm-context/llms-features-execution.txt +52 -6
  17. package/dist/llm-context/llms-features.txt +137 -6
  18. package/dist/llm-context/llms-full.txt +527 -174
  19. package/dist/llm-context/llms-getting-started.txt +3 -3
  20. package/dist/llm-context/llms-patterns.txt +81 -5
  21. package/dist/llm-context/llms-providers.txt +6 -2
  22. package/dist/llm-context/llms-sdk-runtime.txt +22 -18
  23. package/dist/llm-context/llms-sdk.txt +47 -7
  24. package/dist/llm-context/llms.txt +8 -8
  25. package/dist/local-plane/orchestrator-process.d.ts +0 -8
  26. package/dist/local-plane/orchestrator-process.js +3 -14
  27. package/dist/local-plane/plane-manager.js +2 -2
  28. package/dist/lockfile/generator.js +25 -9
  29. package/dist/lockfile/hasher.d.ts +5 -13
  30. package/dist/lockfile/hasher.js +1 -15
  31. package/dist/lockfile/workspace-siblings.d.ts +46 -0
  32. package/dist/lockfile/workspace-siblings.js +197 -0
  33. package/dist/templates/package-json.js +1 -1
  34. package/dist/test-runner/job-executor.js +1 -1
  35. package/dist/test-runner/rule-evaluator.js +1 -1
  36. package/dist/types.d.ts +6 -1
  37. package/package.json +7 -9
  38. package/sbom.spdx.json +123 -123
  39. package/dist/postinstall.d.ts +0 -9
  40. package/dist/postinstall.js +0 -62
  41. package/hack/postinstall.mjs +0 -105
@@ -1,22 +1,8 @@
1
1
  import "../rolldown-runtime-ClRpJifh.js";
2
+ import { COMPILE_SCHEMA_VERSION } from "@kici-dev/core/kici-source-digest";
2
3
  import { normalizeLineEndings, sha256 } from "@kici-dev/core";
3
4
  //#region src/lockfile/hasher.ts
4
5
  /**
5
- * Compile schema version -- bump when compilation approach changes
6
- * (bundler change, bundling config, output format, etc.).
7
- * This is NOT the lock file schema version.
8
- *
9
- * Bumped 3 → 4: the agent artifact switched from a Rolldown-bundled
10
- * `.compiled.mjs` to a raw `.kici/` source tarball that the agent extracts
11
- * and imports via the shared oxc-transform ESM loader hook.
12
- *
13
- * Bumped 4 → 5: the hash input is now line-ending-normalized (CRLF → LF) so a
14
- * lockfile produced on Linux (LF) matches the agent's hash on Windows, where
15
- * Git's `core.autocrlf=true` system default rewrites checked-out text files to
16
- * CRLF. Old lockfiles must be regenerated via `kici compile`.
17
- */
18
- const COMPILE_SCHEMA_VERSION = 5;
19
- /**
20
6
  * Compute content hash for a compiled workflow bundle, optionally including asset file contents.
21
7
  * Hash = SHA-256(schemaVersion + ":" + bundleSource + "\0" + assetDigest) when assetDigest is provided,
22
8
  * otherwise SHA-256(schemaVersion + ":" + bundleSource) for backward compatibility.
@@ -0,0 +1,46 @@
1
+ /**
2
+ * Static resolution of the in-repo `workspace:` sibling closure `.kici` depends
3
+ * on, and a digest over its source.
4
+ *
5
+ * The deps tarball carries those sibling package directories **with their built
6
+ * output** (`packKiciDeps`), while the pointer that names it is keyed on
7
+ * `lockfileHash` — a hash of the package-manager lock file. Editing a sibling's
8
+ * source moves no package-manager lock file, so a repo whose `.kici` depends on
9
+ * an in-repo `workspace:` package restored that sibling's STALE build over the
10
+ * fresh clone on every warm-cache run. `siblingsDigest` closes that: it enters
11
+ * the dep pointer key, so a sibling edit is a pointer miss and the deps are
12
+ * rebuilt.
13
+ *
14
+ * Resolution is **static** — manifests and `git ls-files`, never an installed
15
+ * `node_modules`. The agent's own `collectInRepoSiblings` walks an installed
16
+ * tree, which cannot be used here: `kici compile` would then emit a different
17
+ * lock file before and after an install, and a lock file whose contents depend
18
+ * on whether you have installed is not hermetic.
19
+ */
20
+ /**
21
+ * The workspace globs declared at the repo root — `pnpm-workspace.yaml`'s
22
+ * `packages:` first, then `package.json#workspaces` (npm / yarn / bun). Empty
23
+ * when the repo declares no workspace, in which case a `workspace:` specifier
24
+ * resolves to nothing and is skipped rather than guessed at.
25
+ */
26
+ export declare function readWorkspaceGlobs(gitRoot: string): string[];
27
+ /**
28
+ * Every in-repo sibling directory `.kici` depends on, transitively, as sorted
29
+ * repo-relative POSIX paths.
30
+ *
31
+ * `.kici` itself is excluded: its own source is already covered by
32
+ * `contentHash`, and including it here would make a `.kici` edit invalidate the
33
+ * dep cache for no reason.
34
+ */
35
+ export declare function collectInRepoSiblings(gitRoot: string, kiciDir?: string): string[];
36
+ /**
37
+ * SHA-256 over the git-tracked source of every resolved sibling directory, or
38
+ * null when `.kici` depends on none.
39
+ *
40
+ * `git ls-files` is install-independent and is already the compiler's world (it
41
+ * resolves `gitRoot` to generate the lock at all). Content is read as text and
42
+ * `\0`-delimited against its path, exactly as the `.kici/` tree digest is, so a
43
+ * rename cannot be disguised as a content edit.
44
+ */
45
+ export declare function computeSiblingsDigest(gitRoot: string, kiciDir?: string): string | null;
46
+ //# sourceMappingURL=workspace-siblings.d.ts.map
@@ -0,0 +1,197 @@
1
+ import "../rolldown-runtime-ClRpJifh.js";
2
+ import path from "node:path";
3
+ import { existsSync, readFileSync } from "node:fs";
4
+ import { sha256 } from "@kici-dev/core";
5
+ import { execFileSync } from "node:child_process";
6
+ import { parse } from "yaml";
7
+ //#region src/lockfile/workspace-siblings.ts
8
+ /**
9
+ * Static resolution of the in-repo `workspace:` sibling closure `.kici` depends
10
+ * on, and a digest over its source.
11
+ *
12
+ * The deps tarball carries those sibling package directories **with their built
13
+ * output** (`packKiciDeps`), while the pointer that names it is keyed on
14
+ * `lockfileHash` — a hash of the package-manager lock file. Editing a sibling's
15
+ * source moves no package-manager lock file, so a repo whose `.kici` depends on
16
+ * an in-repo `workspace:` package restored that sibling's STALE build over the
17
+ * fresh clone on every warm-cache run. `siblingsDigest` closes that: it enters
18
+ * the dep pointer key, so a sibling edit is a pointer miss and the deps are
19
+ * rebuilt.
20
+ *
21
+ * Resolution is **static** — manifests and `git ls-files`, never an installed
22
+ * `node_modules`. The agent's own `collectInRepoSiblings` walks an installed
23
+ * tree, which cannot be used here: `kici compile` would then emit a different
24
+ * lock file before and after an install, and a lock file whose contents depend
25
+ * on whether you have installed is not hermetic.
26
+ */
27
+ /** Dependency protocols that name a directory inside this repository. */
28
+ const IN_REPO_PROTOCOLS = [
29
+ "workspace:",
30
+ "file:",
31
+ "link:",
32
+ "portal:"
33
+ ];
34
+ function readManifest(dir) {
35
+ const file = path.join(dir, "package.json");
36
+ if (!existsSync(file)) return null;
37
+ try {
38
+ return JSON.parse(readFileSync(file, "utf-8"));
39
+ } catch {
40
+ return null;
41
+ }
42
+ }
43
+ /** Every dependency specifier in a manifest, across all four dependency maps. */
44
+ function allSpecifiers(m) {
45
+ return Object.entries({
46
+ ...m.dependencies,
47
+ ...m.devDependencies,
48
+ ...m.optionalDependencies,
49
+ ...m.peerDependencies
50
+ });
51
+ }
52
+ /**
53
+ * The workspace globs declared at the repo root — `pnpm-workspace.yaml`'s
54
+ * `packages:` first, then `package.json#workspaces` (npm / yarn / bun). Empty
55
+ * when the repo declares no workspace, in which case a `workspace:` specifier
56
+ * resolves to nothing and is skipped rather than guessed at.
57
+ */
58
+ function readWorkspaceGlobs(gitRoot) {
59
+ const pnpmFile = path.join(gitRoot, "pnpm-workspace.yaml");
60
+ if (existsSync(pnpmFile)) try {
61
+ const doc = parse(readFileSync(pnpmFile, "utf-8"));
62
+ if (Array.isArray(doc?.packages)) return doc.packages.filter((p) => typeof p === "string");
63
+ } catch {}
64
+ const ws = readManifest(gitRoot)?.workspaces;
65
+ if (Array.isArray(ws)) return ws;
66
+ if (ws && Array.isArray(ws.packages)) return ws.packages;
67
+ return [];
68
+ }
69
+ /**
70
+ * Directories the workspace globs match, each carrying a manifest. Resolved with
71
+ * `git ls-files` so the set is exactly what is tracked — the same authority the
72
+ * digest itself uses, and one that needs no install.
73
+ */
74
+ function workspacePackageDirs(gitRoot, globs) {
75
+ const byName = /* @__PURE__ */ new Map();
76
+ if (globs.length === 0) return byName;
77
+ let manifests;
78
+ try {
79
+ manifests = execFileSync("git", [
80
+ "ls-files",
81
+ "--",
82
+ "*package.json",
83
+ "package.json"
84
+ ], {
85
+ cwd: gitRoot,
86
+ encoding: "utf-8",
87
+ maxBuffer: 33554432
88
+ }).split("\n").filter(Boolean);
89
+ } catch {
90
+ return byName;
91
+ }
92
+ for (const rel of manifests) {
93
+ const dir = path.dirname(rel);
94
+ if (dir.split("/").includes("node_modules")) continue;
95
+ const m = readManifest(path.join(gitRoot, dir));
96
+ if (m?.name) byName.set(m.name, dir);
97
+ }
98
+ return byName;
99
+ }
100
+ /**
101
+ * Resolve one specifier to a repo-relative directory, or null when it does not
102
+ * name one. `file:` / `link:` / `portal:` carry the path; `workspace:` carries a
103
+ * version range, so the package NAME is resolved through the workspace globs.
104
+ */
105
+ function resolveSpecifier(pkgName, spec, fromDir, gitRoot, workspacePkgs) {
106
+ if (spec.startsWith("workspace:")) return workspacePkgs.get(pkgName) ?? null;
107
+ for (const proto of [
108
+ "file:",
109
+ "link:",
110
+ "portal:"
111
+ ]) {
112
+ if (!spec.startsWith(proto)) continue;
113
+ const target = spec.slice(proto.length);
114
+ const abs = path.resolve(gitRoot, fromDir, target);
115
+ const rel = path.relative(gitRoot, abs).replaceAll("\\", "/");
116
+ if (rel.startsWith("..") || path.isAbsolute(rel)) return null;
117
+ return rel;
118
+ }
119
+ return null;
120
+ }
121
+ /**
122
+ * Every in-repo sibling directory `.kici` depends on, transitively, as sorted
123
+ * repo-relative POSIX paths.
124
+ *
125
+ * `.kici` itself is excluded: its own source is already covered by
126
+ * `contentHash`, and including it here would make a `.kici` edit invalidate the
127
+ * dep cache for no reason.
128
+ */
129
+ function collectInRepoSiblings(gitRoot, kiciDir = ".kici") {
130
+ const kiciManifest = readManifest(path.join(gitRoot, kiciDir));
131
+ if (!kiciManifest) return [];
132
+ const workspacePkgs = workspacePackageDirs(gitRoot, readWorkspaceGlobs(gitRoot));
133
+ const found = /* @__PURE__ */ new Set();
134
+ const queue = [{
135
+ dir: kiciDir,
136
+ manifest: kiciManifest
137
+ }];
138
+ const visited = /* @__PURE__ */ new Set([kiciDir]);
139
+ while (queue.length > 0) {
140
+ const { dir, manifest } = queue.shift();
141
+ for (const [name, spec] of allSpecifiers(manifest)) {
142
+ if (!IN_REPO_PROTOCOLS.some((p) => spec.startsWith(p))) continue;
143
+ const target = resolveSpecifier(name, spec, dir, gitRoot, workspacePkgs);
144
+ if (target === null || visited.has(target)) continue;
145
+ visited.add(target);
146
+ found.add(target);
147
+ const m = readManifest(path.join(gitRoot, target));
148
+ if (m) queue.push({
149
+ dir: target,
150
+ manifest: m
151
+ });
152
+ }
153
+ }
154
+ return [...found].sort();
155
+ }
156
+ /**
157
+ * SHA-256 over the git-tracked source of every resolved sibling directory, or
158
+ * null when `.kici` depends on none.
159
+ *
160
+ * `git ls-files` is install-independent and is already the compiler's world (it
161
+ * resolves `gitRoot` to generate the lock at all). Content is read as text and
162
+ * `\0`-delimited against its path, exactly as the `.kici/` tree digest is, so a
163
+ * rename cannot be disguised as a content edit.
164
+ */
165
+ function computeSiblingsDigest(gitRoot, kiciDir = ".kici") {
166
+ const siblings = collectInRepoSiblings(gitRoot, kiciDir);
167
+ if (siblings.length === 0) return null;
168
+ const parts = [];
169
+ for (const dir of siblings) {
170
+ let files;
171
+ try {
172
+ files = execFileSync("git", [
173
+ "ls-files",
174
+ "--",
175
+ dir
176
+ ], {
177
+ cwd: gitRoot,
178
+ encoding: "utf-8",
179
+ maxBuffer: 67108864
180
+ }).split("\n").filter(Boolean).sort();
181
+ } catch {
182
+ continue;
183
+ }
184
+ for (const rel of files) {
185
+ let content = "";
186
+ try {
187
+ content = readFileSync(path.join(gitRoot, rel), "utf-8");
188
+ } catch {}
189
+ parts.push(`${rel}\0${content.replaceAll("\r\n", "\n")}\0`);
190
+ }
191
+ }
192
+ return parts.length > 0 ? sha256(parts.join("")) : null;
193
+ }
194
+ //#endregion
195
+ export { collectInRepoSiblings, computeSiblingsDigest, readWorkspaceGlobs };
196
+
197
+ //# sourceMappingURL=workspace-siblings.js.map
@@ -1,6 +1,6 @@
1
1
  import "../rolldown-runtime-ClRpJifh.js";
2
2
  //#region src/templates/package-json.ts
3
- const sdkVersion = "0.6.1";
3
+ const sdkVersion = "0.7.0";
4
4
  /**
5
5
  * The npm version range the scaffold pins `@kici-dev/sdk` to.
6
6
  *
@@ -6,8 +6,8 @@ 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";
9
- import { setJobOutputsMap, setStepOutputsMap, setStepRefMap } from "@kici-dev/sdk";
10
9
  import { logger } from "@kici-dev/core";
10
+ import { setJobOutputsMap, setStepOutputsMap, setStepRefMap } from "@kici-dev/sdk/internal";
11
11
  //#region src/test-runner/job-executor.ts
12
12
  /**
13
13
  * Resolve SDK output setter functions from the workflow's module instance.
@@ -1,7 +1,7 @@
1
1
  import "../rolldown-runtime-ClRpJifh.js";
2
2
  import { formatter } from "./output-formatter.js";
3
- import { createRuleContext as createRuleContext$1, evaluateRules } from "@kici-dev/sdk";
4
3
  import { initZx } from "@kici-dev/core";
4
+ import { createRuleContext as createRuleContext$1, evaluateRules } from "@kici-dev/sdk/internal";
5
5
  //#region src/test-runner/rule-evaluator.ts
6
6
  initZx();
7
7
  /**
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: 39;
31
+ export declare const SCHEMA_VERSION: 41;
32
32
  /** Lock compatibility-window floor - re-exported from engine as single source of truth */
33
33
  export declare const BREAKING_FLOOR: 30;
34
34
  /**
@@ -570,6 +570,11 @@ export interface LockDynamicJobFn {
570
570
  readonly needs?: readonly (string | LockNeedsEntry | LockNeedsGroupEntry)[];
571
571
  /** True when this dynamic entry was authored as dynamicJob(group, { needs, generate }). */
572
572
  readonly resultAware?: boolean;
573
+ /**
574
+ * Named git credentials the generator declares, inherited by every job it
575
+ * generates. Mirrors the engine `LockDynamicJobFn.gitCredentials`.
576
+ */
577
+ readonly gitCredentials?: Readonly<Record<string, Readonly<Record<string, string>>>>;
573
578
  }
574
579
  /** Job or dynamic job generator */
575
580
  export type LockJobOrFactory = LockJob | LockDynamicJobFn;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kici-dev/compiler",
3
- "version": "0.6.1",
3
+ "version": "0.7.0",
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",
@@ -33,7 +33,6 @@
33
33
  "files": [
34
34
  "dist",
35
35
  "!dist/**/*.map",
36
- "hack/postinstall.mjs",
37
36
  "sbom.spdx.json"
38
37
  ],
39
38
  "main": "dist/index.js",
@@ -62,24 +61,23 @@
62
61
  "yaml": "^2.9.0",
63
62
  "zod": "^4.4.3",
64
63
  "zx": "^8.8.5",
65
- "@kici-dev/agent": "0.6.1",
66
- "@kici-dev/core": "0.6.1",
67
- "@kici-dev/engine": "0.6.1",
68
- "@kici-dev/orchestrator": "0.6.1"
64
+ "@kici-dev/agent": "0.7.0",
65
+ "@kici-dev/orchestrator": "0.7.0",
66
+ "@kici-dev/core": "0.7.0",
67
+ "@kici-dev/engine": "0.7.0"
69
68
  },
70
69
  "devDependencies": {
71
70
  "@types/archiver": "^8.0.0",
72
71
  "jszip": "^3.10.1"
73
72
  },
74
73
  "peerDependencies": {
75
- "@kici-dev/sdk": "0.6.1"
74
+ "@kici-dev/sdk": "0.7.0"
76
75
  },
77
76
  "scripts": {
78
77
  "build": "node ../../scripts/build-ts.mjs && tsgo --emitDeclarationOnly",
79
78
  "postbuild": "zx hack/postbuild.mjs",
80
79
  "typecheck": "tsgo --noEmit",
81
80
  "test": "vitest run",
82
- "test:watch": "vitest",
83
- "postinstall": "node hack/postinstall.mjs"
81
+ "test:watch": "vitest"
84
82
  }
85
83
  }