@kici-dev/compiler 0.1.27 → 0.3.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 (153) hide show
  1. package/dist/auth/headless-detect.d.ts +14 -5
  2. package/dist/auth/headless-detect.js +50 -9
  3. package/dist/cli.js +120 -11
  4. package/dist/commands/compile.js +28 -4
  5. package/dist/commands/diagnostics.js +14 -2
  6. package/dist/commands/doctor.d.ts +64 -0
  7. package/dist/commands/doctor.js +413 -0
  8. package/dist/commands/endpoints.js +6 -0
  9. package/dist/commands/fixture.js +13 -0
  10. package/dist/commands/hook.js +3 -2
  11. package/dist/commands/index.d.ts +8 -0
  12. package/dist/commands/index.js +5 -1
  13. package/dist/commands/init-host-os.d.ts +34 -0
  14. package/dist/commands/init-host-os.js +44 -0
  15. package/dist/commands/init.d.ts +4 -0
  16. package/dist/commands/init.js +159 -36
  17. package/dist/commands/local.d.ts +28 -2
  18. package/dist/commands/local.js +74 -5
  19. package/dist/commands/login.js +1 -1
  20. package/dist/commands/notifications.d.ts +61 -0
  21. package/dist/commands/notifications.js +274 -0
  22. package/dist/commands/preview.js +8 -1
  23. package/dist/commands/run-routed.js +10 -1
  24. package/dist/commands/run.js +41 -12
  25. package/dist/commands/runs/artifacts/download.d.ts +24 -0
  26. package/dist/commands/runs/artifacts/download.js +154 -0
  27. package/dist/commands/runs/artifacts/list.d.ts +5 -0
  28. package/dist/commands/runs/artifacts/list.js +47 -0
  29. package/dist/commands/runs/cancel.js +2 -2
  30. package/dist/commands/runs/list.js +8 -2
  31. package/dist/commands/verify-attestation.d.ts +3 -1
  32. package/dist/commands/verify-attestation.js +18 -7
  33. package/dist/errors/formatter.d.ts +14 -1
  34. package/dist/errors/formatter.js +13 -3
  35. package/dist/errors/index.d.ts +2 -1
  36. package/dist/errors/index.js +3 -2
  37. package/dist/errors/source-location.d.ts +20 -0
  38. package/dist/errors/source-location.js +45 -0
  39. package/dist/execution/executor.js +25 -5
  40. package/dist/fixtures/defaults/index.js +2 -1
  41. package/dist/llm-context/llms-architecture.txt +51 -22
  42. package/dist/llm-context/llms-cli.txt +2461 -1582
  43. package/dist/llm-context/llms-features.txt +178 -106
  44. package/dist/llm-context/llms-full.txt +6127 -4426
  45. package/dist/llm-context/llms-getting-started.txt +306 -42
  46. package/dist/llm-context/llms-patterns.txt +13 -7
  47. package/dist/llm-context/llms-sdk-runtime.txt +2013 -0
  48. package/dist/llm-context/llms-sdk.txt +591 -2152
  49. package/dist/llm-context/llms.txt +30 -16
  50. package/dist/local-plane/orchestrator-process.d.ts +12 -7
  51. package/dist/local-plane/orchestrator-process.js +28 -14
  52. package/dist/local-plane/os-mismatch-hint.d.ts +16 -0
  53. package/dist/local-plane/os-mismatch-hint.js +34 -0
  54. package/dist/local-plane/plane-liveness.d.ts +68 -0
  55. package/dist/local-plane/plane-liveness.js +145 -0
  56. package/dist/local-plane/plane-manager.d.ts +60 -18
  57. package/dist/local-plane/plane-manager.js +210 -70
  58. package/dist/local-plane/plane-trigger.d.ts +13 -4
  59. package/dist/local-plane/plane-trigger.js +27 -14
  60. package/dist/local-plane/platform-attach.js +1 -5
  61. package/dist/local-plane/port-holder.d.ts +78 -0
  62. package/dist/local-plane/port-holder.js +227 -0
  63. package/dist/local-plane/postgres.d.ts +15 -3
  64. package/dist/local-plane/postgres.js +34 -12
  65. package/dist/local-plane/run-follow.d.ts +20 -0
  66. package/dist/local-plane/run-follow.js +51 -4
  67. package/dist/local-plane/scaler-config.d.ts +28 -14
  68. package/dist/local-plane/scaler-config.js +59 -41
  69. package/dist/local-plane/source-provider.js +4 -10
  70. package/dist/lockfile/generator.d.ts +14 -1
  71. package/dist/lockfile/generator.js +99 -33
  72. package/dist/lockfile/index.d.ts +3 -1
  73. package/dist/lockfile/index.js +3 -2
  74. package/dist/lockfile/purity-diagnostics.d.ts +31 -0
  75. package/dist/lockfile/purity-diagnostics.js +52 -0
  76. package/dist/postinstall.js +2 -1
  77. package/dist/remote/artifact-extract.d.ts +8 -0
  78. package/dist/remote/artifact-extract.js +58 -0
  79. package/dist/remote/config.d.ts +21 -3
  80. package/dist/remote/config.js +24 -5
  81. package/dist/remote/dashboard-client.d.ts +39 -2
  82. package/dist/remote/dashboard-client.js +47 -4
  83. package/dist/remote/fs-case.d.ts +21 -0
  84. package/dist/remote/fs-case.js +45 -0
  85. package/dist/remote/history.d.ts +9 -3
  86. package/dist/remote/history.js +79 -10
  87. package/dist/remote/local-repo-identity.d.ts +1 -1
  88. package/dist/remote/local-repo-identity.js +2 -1
  89. package/dist/remote/notifications-client.d.ts +149 -0
  90. package/dist/remote/notifications-client.js +103 -0
  91. package/dist/remote/oauth.d.ts +13 -0
  92. package/dist/remote/oauth.js +31 -5
  93. package/dist/remote/output/summary.js +76 -14
  94. package/dist/remote/render.js +30 -9
  95. package/dist/remote/uploader.js +5 -4
  96. package/dist/templates/agents-md.d.ts +1 -1
  97. package/dist/templates/agents-md.js +6 -6
  98. package/dist/templates/index.d.ts +1 -1
  99. package/dist/templates/index.js +2 -2
  100. package/dist/templates/package-json.d.ts +15 -0
  101. package/dist/templates/package-json.js +26 -5
  102. package/dist/test-runner/dry-run.d.ts +2 -1
  103. package/dist/test-runner/dry-run.js +18 -1
  104. package/dist/test-runner/event-types.d.ts +2 -0
  105. package/dist/test-runner/event-types.js +3 -0
  106. package/dist/test-runner/job-executor.d.ts +1 -0
  107. package/dist/test-runner/job-executor.js +81 -43
  108. package/dist/test-runner/output-formatter.d.ts +5 -2
  109. package/dist/test-runner/output-formatter.js +6 -4
  110. package/dist/test-runner/payload-builder.d.ts +7 -1
  111. package/dist/test-runner/payload-builder.js +11 -2
  112. package/dist/test-runner/rule-evaluator.d.ts +7 -3
  113. package/dist/test-runner/rule-evaluator.js +13 -12
  114. package/dist/test-runner/step-context.d.ts +23 -5
  115. package/dist/test-runner/step-context.js +28 -118
  116. package/dist/types.d.ts +21 -2
  117. package/dist/types.js +4 -2
  118. package/dist/validation/index.d.ts +2 -0
  119. package/dist/validation/index.js +2 -1
  120. package/dist/validation/typecheck.d.ts +28 -0
  121. package/dist/validation/typecheck.js +110 -0
  122. package/dist/validation/validator.d.ts +9 -4
  123. package/dist/validation/validator.js +38 -44
  124. package/package.json +12 -15
  125. package/sbom.spdx.json +1322 -1964
  126. package/dist/assets/api-TJJVHrjC.json +0 -118
  127. package/dist/assets/descriptor-BTtjzN9L.json +0 -1382
  128. package/dist/assets/package-BpQF9kR8.json +0 -74
  129. package/dist/assets/package-Ceo2h27X.json +0 -89
  130. package/dist/assets/source_context-D0atuL28.json +0 -20
  131. package/dist/assets/type-BFqO8SCZ.json +0 -202
  132. package/dist/commands/cancel.d.ts +0 -22
  133. package/dist/commands/detect-package-manager.d.ts +0 -42
  134. package/dist/commands/held-run-resolve.d.ts +0 -50
  135. package/dist/commands/status.d.ts +0 -34
  136. package/dist/commands/test.d.ts +0 -88
  137. package/dist/errors/codes.d.ts +0 -25
  138. package/dist/local-executor/dag-scheduler.d.ts +0 -44
  139. package/dist/local-executor/index.d.ts +0 -23
  140. package/dist/local-executor/job-runner.d.ts +0 -47
  141. package/dist/local-executor/materializer.d.ts +0 -44
  142. package/dist/local-executor/output-streamer.d.ts +0 -31
  143. package/dist/local-executor/payload-generator.d.ts +0 -16
  144. package/dist/local-executor/picker.d.ts +0 -33
  145. package/dist/local-executor/runs-on-display.d.ts +0 -9
  146. package/dist/local-executor/secret-loader.d.ts +0 -18
  147. package/dist/local-executor/to-event-payload.d.ts +0 -16
  148. package/dist/local-executor/types.d.ts +0 -93
  149. package/dist/local-executor/workflow-lock.d.ts +0 -82
  150. package/dist/package-F7UXSDHW.json +0 -74
  151. package/dist/remote/client.d.ts +0 -210
  152. package/dist/remote/observer.d.ts +0 -81
  153. package/dist/test-runner/summary.d.ts +0 -7
@@ -1,19 +1,22 @@
1
1
  import "../rolldown-runtime-ClRpJifh.js";
2
2
  import { agentsMdTemplate } from "../templates/agents-md.js";
3
3
  import { tsconfigTemplate } from "../templates/tsconfig-json.js";
4
- import { generatePackageJson } from "../templates/package-json.js";
4
+ import { generatePackageJson, sdkDependencyRange } from "../templates/package-json.js";
5
5
  import { workflowPaths } from "../templates/index.js";
6
6
  import { detectHookTools, findGitDir } from "../hooks/detector.js";
7
7
  import { installHook } from "../hooks/installer.js";
8
8
  import "../hooks/index.js";
9
9
  import { getTypeScriptPaths } from "../execution/sdk-alias.js";
10
+ import { rewriteRunsOnForHost, shouldOfferFirstRun } from "./init-host-os.js";
10
11
  import path from "node:path";
11
12
  import pc from "picocolors";
12
13
  import { access, mkdir, readFile, rm, writeFile } from "node:fs/promises";
14
+ import { $ } from "zx";
13
15
  import { initZx, logger, toErrorMessage } from "@kici-dev/core";
14
- import { detectPackageManager, installBuildPolicyArgs, installCommand, parsePackageManager } from "@kici-dev/core/package-manager";
16
+ import { detectPackageManager, detectWorkspaceRoot, installBuildPolicyArgs, installCommand, parsePackageManager } from "@kici-dev/core/package-manager";
15
17
  import { checkbox, confirm, select } from "@inquirer/prompts";
16
- import { $ } from "zx";
18
+ import { isCiEnvironment } from "@kici-dev/core/ci-env";
19
+ import os from "node:os";
17
20
  //#region src/commands/init.ts
18
21
  /**
19
22
  * kici init command
@@ -59,6 +62,7 @@ async function initCommand(options = {}) {
59
62
  content = content.replaceAll("targeting('main')", `targeting('${defaultBranch}')`);
60
63
  content = content.replaceAll("targeting the main branch", `targeting the ${defaultBranch} branch`);
61
64
  }
65
+ content = rewriteRunsOnForHost(content, os.platform(), os.arch());
62
66
  await writeFile(path.join(kiciDir, "workflows", `${workflow}.ts`), content, "utf-8");
63
67
  }
64
68
  logger.info(pc.gray("Creating .kici/tests/"));
@@ -73,34 +77,12 @@ async function initCommand(options = {}) {
73
77
  await writeFile(kiciIgnorePath, kiciIgnoreTemplate, "utf-8");
74
78
  }
75
79
  const devMode = options.useVerdaccioLocal || await detectDevelopmentMode();
76
- logger.info(pc.gray("Writing .kici/package.json"));
77
- const pkgContent = generatePackageJson(devMode);
78
- await writeFile(path.join(kiciDir, "package.json"), pkgContent, "utf-8");
80
+ const mode = await resolveScaffoldMode(options);
79
81
  const useVerdaccio = devMode;
80
- if (useVerdaccio) {
81
- logger.info(pc.yellow("Pointing @kici-dev to local Verdaccio registry."));
82
- const npmrc = "@kici-dev:registry=http://verdaccio.local:4873\n";
83
- await writeFile(path.join(kiciDir, ".npmrc"), npmrc, "utf-8");
84
- const rootNpmrc = path.resolve(".npmrc");
85
- if (!await checkExists(rootNpmrc)) {
86
- logger.info(pc.gray("Writing .npmrc (Verdaccio scope)"));
87
- await writeFile(rootNpmrc, npmrc, "utf-8");
88
- }
89
- }
90
- if (!options.mjs) {
91
- logger.info(pc.gray("Writing .kici/tsconfig.json"));
92
- const tsconfigContent = await generateTsConfig();
93
- await writeFile(path.join(kiciDir, "tsconfig.json"), tsconfigContent, "utf-8");
94
- await mkdir(path.join(kiciDir, "types"), { recursive: true });
95
- logger.info(pc.gray("Created .kici/types/ for generated type declarations"));
96
- if (!options.skipInstall) {
97
- const pm = await resolvePackageManager(options.packageManager);
98
- const [bin, action] = installCommand(pm);
99
- const buildPolicyArgs = installBuildPolicyArgs(pm);
100
- logger.info(pc.gray(`Running ${bin} ${action}...`));
101
- await $`cd ${kiciDir} && ${bin} ${action} ${buildPolicyArgs}`;
102
- }
103
- }
82
+ if (mode.kind === "integrate") {
83
+ logger.info(pc.cyan(`Integrating .kici/ into the ${mode.workspaceKind} workspace at ${mode.workspaceRoot}`));
84
+ await wireIntegrateDeps(kiciDir, mode.workspaceRoot, devMode, options);
85
+ } else await wireStandaloneDeps(kiciDir, devMode, options);
104
86
  if (options.privateRegistry) await writePrivateRegistryScaffold(kiciDir, {
105
87
  url: options.privateRegistry,
106
88
  scope: options.privateRegistryScope,
@@ -109,13 +91,17 @@ async function initCommand(options = {}) {
109
91
  if (await shouldWriteAgentsMd(options)) await writeAgentsMd(kiciDir);
110
92
  logger.info(pc.gray("Updating .gitignore"));
111
93
  await updateGitignore(useVerdaccio);
112
- if (process.stdout.isTTY && process.env.CI !== "true") {
94
+ if (process.stdout.isTTY && !isCiEnvironment()) {
113
95
  if (await findGitDir()) await offerHookInstallation(useVerdaccio);
114
96
  }
115
97
  logger.info(pc.green("\n✓ kici initialized successfully!\n"));
116
98
  logger.info(pc.gray("Next steps:"));
117
99
  logger.info(pc.gray(" 1. Edit workflows in .kici/workflows/"));
118
- if (options.mjs || options.skipInstall) {
100
+ if (mode.kind === "integrate") {
101
+ logger.info(pc.gray(" 2. Import your workspace packages from .kici/workflows/ (e.g. @your-scope/utils)"));
102
+ logger.info(pc.gray(" 3. Compile: kici compile"));
103
+ logger.info(pc.gray(" 4. Commit .kici/ to your repository\n"));
104
+ } else if (options.mjs || options.skipInstall) {
119
105
  logger.info(pc.gray(" 2. Run your package manager install in .kici/ to generate a lockfile"));
120
106
  logger.info(pc.gray(" 3. Preview matching: kici preview push"));
121
107
  logger.info(pc.gray(" 4. Commit .kici/ to your repository\n"));
@@ -123,6 +109,23 @@ async function initCommand(options = {}) {
123
109
  logger.info(pc.gray(" 2. Preview matching: kici preview push"));
124
110
  logger.info(pc.gray(" 3. Commit .kici/ to your repository\n"));
125
111
  }
112
+ if (shouldOfferFirstRun({
113
+ isTTY: Boolean(process.stdout.isTTY),
114
+ ci: isCiEnvironment(),
115
+ mjs: Boolean(options.mjs),
116
+ skipInstall: Boolean(options.skipInstall)
117
+ })) {
118
+ if (await confirm({
119
+ message: "Run it now? (kici run push --local)",
120
+ default: false
121
+ })) {
122
+ const { runRoutedCommand } = await import("./run-routed.js");
123
+ await runRoutedCommand({
124
+ event: "push",
125
+ local: true
126
+ });
127
+ }
128
+ }
126
129
  return true;
127
130
  } catch (error) {
128
131
  const message = toErrorMessage(error);
@@ -153,7 +156,7 @@ async function checkExists(targetPath) {
153
156
  * @returns Array of workflow names to include
154
157
  */
155
158
  async function selectWorkflows() {
156
- if (!process.stdout.isTTY || process.env.CI === "true") return ["hello-world", "pr-checks"];
159
+ if (!process.stdout.isTTY || isCiEnvironment()) return ["hello-world", "pr-checks"];
157
160
  const selected = await checkbox({
158
161
  message: "Which workflows would you like to include?",
159
162
  choices: [{
@@ -217,13 +220,133 @@ async function detectDevelopmentMode() {
217
220
  *
218
221
  * @param override - The raw `--package-manager` flag value, if provided.
219
222
  */
220
- async function resolvePackageManager(override) {
223
+ async function resolvePackageManager(override, dir = process.cwd()) {
221
224
  if (override) {
222
225
  const parsed = parsePackageManager(override);
223
226
  if (!parsed) throw new Error(`Invalid --package-manager value '${override}'. Expected one of: npm, pnpm, yarn.`);
224
227
  return parsed;
225
228
  }
226
- return detectPackageManager(process.cwd());
229
+ return detectPackageManager(dir);
230
+ }
231
+ /** The @kici-dev scope → local Verdaccio registry line written in dev mode. */
232
+ const VERDACCIO_NPMRC = "@kici-dev:registry=http://verdaccio.local:4873\n";
233
+ /** Write .kici/tsconfig.json + the empty types/ dir (TypeScript mode only). */
234
+ async function writeTsConfigAndTypesDir(kiciDir) {
235
+ logger.info(pc.gray("Writing .kici/tsconfig.json"));
236
+ await writeFile(path.join(kiciDir, "tsconfig.json"), await generateTsConfig(), "utf-8");
237
+ await mkdir(path.join(kiciDir, "types"), { recursive: true });
238
+ logger.info(pc.gray("Created .kici/types/ for generated type declarations"));
239
+ }
240
+ /** Run the given package manager's install in `dir`, with pnpm's build-gate flag. */
241
+ async function runInstall(pm, dir) {
242
+ const [bin, action] = installCommand(pm);
243
+ const buildPolicyArgs = installBuildPolicyArgs(pm);
244
+ logger.info(pc.gray(`Running ${bin} ${action}...`));
245
+ await $`cd ${dir} && ${bin} ${action} ${buildPolicyArgs}`;
246
+ }
247
+ /**
248
+ * Standalone dep wiring: write .kici/package.json (+ .kici/.npmrc and root
249
+ * .npmrc in dev mode), then tsconfig + isolated install in TypeScript mode.
250
+ */
251
+ async function wireStandaloneDeps(kiciDir, devMode, options) {
252
+ logger.info(pc.gray("Writing .kici/package.json"));
253
+ await writeFile(path.join(kiciDir, "package.json"), generatePackageJson(devMode), "utf-8");
254
+ if (devMode) {
255
+ logger.info(pc.yellow("Pointing @kici-dev to local Verdaccio registry."));
256
+ await writeFile(path.join(kiciDir, ".npmrc"), VERDACCIO_NPMRC, "utf-8");
257
+ const rootNpmrc = path.resolve(".npmrc");
258
+ if (!await checkExists(rootNpmrc)) {
259
+ logger.info(pc.gray("Writing .npmrc (Verdaccio scope)"));
260
+ await writeFile(rootNpmrc, VERDACCIO_NPMRC, "utf-8");
261
+ }
262
+ }
263
+ if (!options.mjs) {
264
+ await writeTsConfigAndTypesDir(kiciDir);
265
+ if (!options.skipInstall) await runInstall(await resolvePackageManager(options.packageManager), kiciDir);
266
+ }
267
+ }
268
+ /**
269
+ * Integrate dep wiring: NO .kici/package.json (its absence is the
270
+ * externally-managed signal the compiler honors). Add @kici-dev/sdk to the
271
+ * workspace-root manifest, write a root .npmrc in dev mode, write .kici/tsconfig
272
+ * in TypeScript mode, and run a root install.
273
+ */
274
+ async function wireIntegrateDeps(kiciDir, workspaceRoot, devMode, options) {
275
+ await addSdkToRootManifest(workspaceRoot, devMode);
276
+ if (devMode) {
277
+ const rootNpmrc = path.join(workspaceRoot, ".npmrc");
278
+ if (!await checkExists(rootNpmrc)) {
279
+ logger.info(pc.gray("Writing workspace-root .npmrc (Verdaccio scope)"));
280
+ await writeFile(rootNpmrc, VERDACCIO_NPMRC, "utf-8");
281
+ }
282
+ }
283
+ if (!options.mjs) await writeTsConfigAndTypesDir(kiciDir);
284
+ if (!options.skipInstall) await runInstall(await resolvePackageManager(options.packageManager, workspaceRoot), workspaceRoot);
285
+ }
286
+ /**
287
+ * Add @kici-dev/sdk to the workspace-root package.json devDependencies.
288
+ * Never clobbers an existing @kici-dev/sdk declaration (dev or prod dep).
289
+ */
290
+ async function addSdkToRootManifest(workspaceRoot, devMode) {
291
+ const manifestPath = path.join(workspaceRoot, "package.json");
292
+ let raw;
293
+ try {
294
+ raw = await readFile(manifestPath, "utf-8");
295
+ } catch {
296
+ throw new Error(`Cannot integrate: no package.json at workspace root ${workspaceRoot}`);
297
+ }
298
+ const pkg = JSON.parse(raw);
299
+ const existing = pkg.devDependencies?.["@kici-dev/sdk"] ?? pkg.dependencies?.["@kici-dev/sdk"];
300
+ if (existing) {
301
+ logger.info(pc.gray(`@kici-dev/sdk already declared in ${manifestPath} (${existing}) — leaving as-is`));
302
+ return;
303
+ }
304
+ const range = sdkDependencyRange(devMode);
305
+ pkg.devDependencies = {
306
+ ...pkg.devDependencies ?? {},
307
+ "@kici-dev/sdk": range
308
+ };
309
+ await writeFile(manifestPath, JSON.stringify(pkg, null, 2) + "\n", "utf-8");
310
+ logger.info(pc.gray(`Added @kici-dev/sdk (${range}) to ${manifestPath}`));
311
+ }
312
+ /**
313
+ * Decide standalone vs integrate. Flags win; otherwise, when a workspace is
314
+ * detected, prompt in interactive mode and default to standalone in CI/non-TTY.
315
+ * With no workspace and no --workspace, always standalone (unchanged behavior).
316
+ */
317
+ async function resolveScaffoldMode(options) {
318
+ if (options.workspace && options.standalone) throw new Error("Cannot combine --workspace and --standalone.");
319
+ if (options.standalone) return { kind: "standalone" };
320
+ const ws = await detectWorkspaceRoot(process.cwd());
321
+ if (options.workspace) {
322
+ if (!ws) throw new Error("Cannot integrate: no pnpm/npm/yarn workspace found at or above the current directory. Run from a workspace root, or omit --workspace for a standalone .kici/.");
323
+ return {
324
+ kind: "integrate",
325
+ workspaceRoot: ws.root,
326
+ workspaceKind: ws.kind
327
+ };
328
+ }
329
+ if (!ws) return { kind: "standalone" };
330
+ if (!process.stdout.isTTY || isCiEnvironment()) return { kind: "standalone" };
331
+ return await promptScaffoldMode(ws.kind) === "integrate" ? {
332
+ kind: "integrate",
333
+ workspaceRoot: ws.root,
334
+ workspaceKind: ws.kind
335
+ } : { kind: "standalone" };
336
+ }
337
+ /** Interactive standalone-vs-integrate select. Defaults to standalone. */
338
+ async function promptScaffoldMode(kind) {
339
+ return await select({
340
+ message: `A ${kind} workspace was detected. How should the workflows be set up?`,
341
+ choices: [{
342
+ name: "Standalone — self-contained .kici/ with its own package.json",
343
+ value: "standalone"
344
+ }, {
345
+ name: "Integrate — join the workspace; workflows can import your other packages",
346
+ value: "integrate"
347
+ }],
348
+ default: "standalone"
349
+ });
227
350
  }
228
351
  /**
229
352
  * Generate tsconfig.json content with optional TypeScript path mappings.
@@ -355,7 +478,7 @@ coverage/
355
478
  */
356
479
  async function shouldWriteAgentsMd(options) {
357
480
  if (options.noAgentsMd) return false;
358
- if (!process.stdout.isTTY || process.env.CI === "true") return true;
481
+ if (!process.stdout.isTTY || isCiEnvironment()) return true;
359
482
  return await confirm({
360
483
  message: "Add LLM authoring context (.kici/AGENTS.md)?",
361
484
  default: true
@@ -7,6 +7,8 @@
7
7
  * `status` reports it plus the control commands, `down` stops it, and `logs`
8
8
  * prints the orchestrator log path.
9
9
  */
10
+ import type { PlaneStatus, PlaneMode } from '../local-plane/plane-manager.js';
11
+ import type { PlaneState } from '../local-plane/plane-liveness.js';
10
12
  /**
11
13
  * Boot (or reuse) the local dev plane, honoring the durable attachment record.
12
14
  *
@@ -22,9 +24,33 @@ export declare function localUpCommand(flags?: {
22
24
  offline?: boolean;
23
25
  connected?: boolean;
24
26
  }): Promise<boolean>;
27
+ /**
28
+ * The machine-readable projection of a plane status.
29
+ *
30
+ * An explicit allow-list, NOT `JSON.stringify(status)`. `PlaneStatus` carries
31
+ * `adminToken` — the bootstrap admin token the CLI presents to the plane's
32
+ * admin API — so serializing the whole object would publish it on stdout, and
33
+ * from there into any consumer's logs. `attachment` is omitted for the same
34
+ * reason in miniature: no consumer needs it, and a field that is never emitted
35
+ * cannot leak a field added to it later.
36
+ */
37
+ export interface LocalStatusJson {
38
+ state: PlaneState;
39
+ running: boolean;
40
+ pid: number | null;
41
+ port: number | null;
42
+ url: string | null;
43
+ pgKind: 'embedded' | 'podman' | null;
44
+ stampVersion: number | null;
45
+ mode: PlaneMode | null;
46
+ }
47
+ /** Project a PlaneStatus onto the published JSON shape, absent fields as null. */
48
+ export declare function toLocalStatusJson(status: PlaneStatus): LocalStatusJson;
25
49
  /** Show the local dev plane status and its control commands. */
26
- export declare function localStatusCommand(): Promise<boolean>;
27
- /** Stop the local dev plane. */
50
+ export declare function localStatusCommand(options?: {
51
+ json?: boolean;
52
+ }): Promise<boolean>;
53
+ /** Stop the local dev plane, reporting success only once the port is released. */
28
54
  export declare function localDownCommand(): Promise<boolean>;
29
55
  /** Print the local dev plane orchestrator log path. */
30
56
  export declare function localLogsCommand(): Promise<boolean>;
@@ -54,14 +54,78 @@ async function localUpCommand(flags = {}) {
54
54
  printControlHints();
55
55
  return true;
56
56
  }
57
+ /**
58
+ * Render the branch for a plane port held by a process that is not a KiCI plane
59
+ * orchestrator. Kept apart from the not-serving branch because `kici local down`
60
+ * deliberately refuses to signal such a holder, so pointing at it here would
61
+ * send the operator to a command that cannot act.
62
+ */
63
+ function printForeignHolder(status) {
64
+ console.log(pc.yellow("⚠") + ` Port ${pc.bold(String(status.port))} is held by a process that is not a KiCI plane orchestrator.`);
65
+ console.log(pc.dim(` pid: ${status.pid ?? "unknown"}`));
66
+ console.log("The local dev plane cannot start while that process holds the port.");
67
+ console.log(`Stop it yourself, or point the plane elsewhere with ${pc.cyan("KICI_LOCAL_ORCH_PORT")}.`);
68
+ }
69
+ /**
70
+ * Render the branch for a plane port held by a KiCI plane orchestrator that is
71
+ * not serving this config dir: our own stamped orchestrator failing its
72
+ * readiness probe, or a plane no stamp here accounts for. Split out of
73
+ * `localStatusCommand` so each branch stays readable.
74
+ *
75
+ * The two get different headlines because only one of them has been probed:
76
+ * readiness is checked for a plane we stamped, so `unready` is a measurement,
77
+ * while a plane we did not stamp is only known to be holding the port.
78
+ */
79
+ function printNotServing(status) {
80
+ if (status.state === "foreign-kici") {
81
+ console.log(pc.yellow("⚠") + ` Port ${pc.bold(String(status.port))} is held by a KiCI plane orchestrator this config dir did not start.`);
82
+ console.log(pc.dim(` pid: ${status.pid ?? "unknown"}`));
83
+ console.log(pc.dim(" owner: another KiCI plane — no stamp in this config dir"));
84
+ console.log(`Stop it with ${pc.cyan("kici local down")}.`);
85
+ return;
86
+ }
87
+ console.log(pc.yellow("⚠") + ` Local dev plane is running but NOT ready at ${pc.bold(status.url ?? "")}`);
88
+ console.log(pc.dim(` port: ${status.port}`));
89
+ console.log(pc.dim(` pid: ${status.pid ?? "unknown"}`));
90
+ if (status.checks && Object.keys(status.checks).length > 0) {
91
+ const rendered = Object.entries(status.checks).map(([name, ok]) => `${name}=${ok}`).join(" ");
92
+ console.log(pc.dim(` checks: ${rendered}`));
93
+ }
94
+ console.log(`Stop it with ${pc.cyan("kici local down")}.`);
95
+ }
96
+ /** Project a PlaneStatus onto the published JSON shape, absent fields as null. */
97
+ function toLocalStatusJson(status) {
98
+ return {
99
+ state: status.state,
100
+ running: status.running,
101
+ pid: status.pid ?? null,
102
+ port: status.port ?? null,
103
+ url: status.url ?? null,
104
+ pgKind: status.pgKind ?? null,
105
+ stampVersion: status.stampVersion ?? null,
106
+ mode: status.mode ?? null
107
+ };
108
+ }
57
109
  /** Show the local dev plane status and its control commands. */
58
- async function localStatusCommand() {
110
+ async function localStatusCommand(options) {
59
111
  const status = await planeStatus();
60
- if (!status.running) {
112
+ if (options?.json) {
113
+ console.log(JSON.stringify(toLocalStatusJson(status)));
114
+ return true;
115
+ }
116
+ if (status.state === "stopped") {
61
117
  console.log(pc.yellow("Local dev plane is not running."));
62
118
  console.log(`Start it with ${pc.cyan("kici local up")}.`);
63
119
  return true;
64
120
  }
121
+ if (status.state === "foreign-unknown") {
122
+ printForeignHolder(status);
123
+ return true;
124
+ }
125
+ if (status.state !== "ready") {
126
+ printNotServing(status);
127
+ return true;
128
+ }
65
129
  console.log(pc.green("✓") + ` Local dev plane running at ${pc.bold(status.url ?? "")}`);
66
130
  console.log(pc.dim(` port: ${status.port}`));
67
131
  console.log(pc.dim(` pid: ${status.pid ?? "unknown"}`));
@@ -71,10 +135,15 @@ async function localStatusCommand() {
71
135
  printControlHints();
72
136
  return true;
73
137
  }
74
- /** Stop the local dev plane. */
138
+ /** Stop the local dev plane, reporting success only once the port is released. */
75
139
  async function localDownCommand() {
76
140
  console.log(pc.dim("Stopping the local dev plane…"));
77
- await planeDown();
141
+ const result = await planeDown();
142
+ if (!result.stopped) {
143
+ console.error(pc.red(`✗ Local dev plane NOT stopped: ${result.reason ?? "port still held"}`));
144
+ if (result.holderPid !== void 0) console.error(pc.dim(` holder pid: ${result.holderPid} port: ${result.port}`));
145
+ return false;
146
+ }
78
147
  console.log(pc.green("✓") + " Local dev plane stopped.");
79
148
  return true;
80
149
  }
@@ -132,6 +201,6 @@ async function localDetachCommand() {
132
201
  }
133
202
  }
134
203
  //#endregion
135
- export { localAttachCommand, localDetachCommand, localDownCommand, localLogsCommand, localStatusCommand, localUpCommand };
204
+ export { localAttachCommand, localDetachCommand, localDownCommand, localLogsCommand, localStatusCommand, localUpCommand, toLocalStatusJson };
136
205
 
137
206
  //# sourceMappingURL=local.js.map
@@ -53,7 +53,7 @@ async function oauthLogin(options) {
53
53
  const clientId = process.env.KICI_OIDC_CLIENT_ID || "kici-cli";
54
54
  console.log(pc.cyan("\n Step 1/4: Detecting environment..."));
55
55
  const browserCmdSet = !!process.env.KICI_BROWSER_CMD;
56
- const useDeviceFlow = options.device || !browserCmdSet && isHeadless();
56
+ const useDeviceFlow = options.device || !browserCmdSet && await isHeadless();
57
57
  const flowName = useDeviceFlow ? "device authorization" : "PKCE (browser)";
58
58
  console.log(pc.gray(` Using ${flowName} flow`));
59
59
  console.log(pc.cyan(`\n Step 2/4: Authenticating with IdP (${flowName})...`));
@@ -0,0 +1,61 @@
1
+ /**
2
+ * kici notifications commands
3
+ *
4
+ * Customer self-service management of an org's notification configuration —
5
+ * channels, subscriptions, and the Layer 1 Slack-identity roster — under the
6
+ * logged-in user's PAT against the hosted Platform's org-scoped HTTP API. This
7
+ * is a tenant-plane developer operation, so it lives in the public `kici` CLI
8
+ * (like `kici org` / `kici verify-attestation`), never the DB-direct
9
+ * `kici-platform-admin`.
10
+ */
11
+ /** Options common to every notifications subcommand. */
12
+ export interface NotificationsCommonOptions {
13
+ /** Target organization id (overrides the saved active org). */
14
+ org?: string;
15
+ }
16
+ /** Options for the `list` leaves. */
17
+ export interface NotificationsListOptions extends NotificationsCommonOptions {
18
+ json?: boolean;
19
+ }
20
+ /** Options for `channels add`. */
21
+ export interface ChannelsAddOptions extends NotificationsCommonOptions {
22
+ type?: string;
23
+ name?: string;
24
+ connection?: string;
25
+ slackChannel?: string;
26
+ fromName?: string;
27
+ replyTo?: string;
28
+ }
29
+ /** Options for `subscriptions add`. */
30
+ export interface SubscriptionsAddOptions extends NotificationsCommonOptions {
31
+ channel?: string;
32
+ level?: string;
33
+ scope?: string;
34
+ scopeId?: string;
35
+ onStatus?: string;
36
+ repoGlob?: string;
37
+ workflowGlob?: string;
38
+ jobGlob?: string;
39
+ mentions?: string;
40
+ recipientOverride?: string;
41
+ onFailureClass?: string;
42
+ accumulateFor?: string;
43
+ }
44
+ /** Options for `roster add`. */
45
+ export interface RosterAddOptions extends NotificationsCommonOptions {
46
+ connection?: string;
47
+ subjectKind?: string;
48
+ subject?: string;
49
+ inputForm?: string;
50
+ value?: string;
51
+ }
52
+ export declare function notificationsChannelsListCommand(opts: NotificationsListOptions): Promise<boolean>;
53
+ export declare function notificationsChannelsAddCommand(opts: ChannelsAddOptions): Promise<boolean>;
54
+ export declare function notificationsChannelsRemoveCommand(id: string, opts: NotificationsCommonOptions): Promise<boolean>;
55
+ export declare function notificationsSubscriptionsListCommand(opts: NotificationsListOptions): Promise<boolean>;
56
+ export declare function notificationsSubscriptionsAddCommand(opts: SubscriptionsAddOptions): Promise<boolean>;
57
+ export declare function notificationsSubscriptionsRemoveCommand(id: string, opts: NotificationsCommonOptions): Promise<boolean>;
58
+ export declare function notificationsRosterListCommand(opts: NotificationsListOptions): Promise<boolean>;
59
+ export declare function notificationsRosterAddCommand(opts: RosterAddOptions): Promise<boolean>;
60
+ export declare function notificationsRosterRemoveCommand(id: string, opts: NotificationsCommonOptions): Promise<boolean>;
61
+ //# sourceMappingURL=notifications.d.ts.map