@kici-dev/compiler 0.1.15 → 0.1.16

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 (51) hide show
  1. package/dist/cli.d.ts +9 -1
  2. package/dist/cli.js +213 -182
  3. package/dist/commands/approve.d.ts +23 -0
  4. package/dist/commands/approve.js +46 -0
  5. package/dist/commands/compile.js +1 -1
  6. package/dist/commands/docs.js +2 -2
  7. package/dist/commands/endpoints.js +1 -1
  8. package/dist/commands/held-run-client.d.ts +26 -0
  9. package/dist/commands/held-run-client.js +98 -0
  10. package/dist/commands/held-run-resolve.d.ts +45 -0
  11. package/dist/commands/held-run-resolve.js +53 -0
  12. package/dist/commands/hook.js +1 -1
  13. package/dist/commands/index.d.ts +4 -0
  14. package/dist/commands/index.js +3 -1
  15. package/dist/commands/init.js +1 -1
  16. package/dist/commands/reject.d.ts +25 -0
  17. package/dist/commands/reject.js +49 -0
  18. package/dist/commands/run.js +1 -1
  19. package/dist/commands/status.js +1 -1
  20. package/dist/commands/test.js +1 -1
  21. package/dist/commands/types.js +1 -1
  22. package/dist/commands/watch.js +1 -1
  23. package/dist/execution/executor.js +2 -2
  24. package/dist/execution/sdk-alias.js +1 -1
  25. package/dist/fixtures/compiler.js +2 -2
  26. package/dist/fixtures/defaults/index.js +2 -2
  27. package/dist/hooks/detector.js +1 -1
  28. package/dist/hooks/installer.js +1 -1
  29. package/dist/index.d.ts +1 -1
  30. package/dist/llm-context/llms-full.txt +137 -3
  31. package/dist/llm-context/llms.txt +2 -1
  32. package/dist/local-executor/index.js +1 -1
  33. package/dist/local-executor/job-runner.js +1 -1
  34. package/dist/local-executor/materializer.js +1 -1
  35. package/dist/local-executor/secret-loader.js +1 -1
  36. package/dist/local-executor/workflow-lock.js +0 -0
  37. package/dist/lockfile/generator.js +17 -5
  38. package/dist/lockfile/hash-files.js +1 -1
  39. package/dist/postinstall.js +1 -1
  40. package/dist/remote/config.js +1 -1
  41. package/dist/remote/history.js +1 -1
  42. package/dist/remote/uploader.js +1 -1
  43. package/dist/templates/index.js +1 -1
  44. package/dist/templates/package-json.js +1 -1
  45. package/dist/test-runner/git-detector.js +1 -1
  46. package/dist/test-runner/job-executor.js +2 -2
  47. package/dist/test-runner/secrets-file.js +1 -1
  48. package/dist/test-runner/step-context.js +1 -1
  49. package/dist/types.d.ts +17 -2
  50. package/package.json +4 -4
  51. package/sbom.spdx.json +34 -34
@@ -0,0 +1,98 @@
1
+ import "../chunk-gOLHoazu.js";
2
+ import { loadGlobalConfig } from "../remote/config.js";
3
+ import pc from "picocolors";
4
+ import { logger } from "@kici-dev/core";
5
+ //#region src/commands/held-run-client.ts
6
+ /**
7
+ * Shared HTTP plumbing for the `kici approve` / `kici reject` held-run
8
+ * commands. Resolves auth + endpoint from the global config (PAT preferred,
9
+ * API key fallback; Platform endpoint preferred, orchestrator fallback) and
10
+ * exposes thin list / approve / reject helpers against the Platform dashboard
11
+ * API.
12
+ */
13
+ /**
14
+ * Resolve the auth context, printing a clear error and returning null when the
15
+ * CLI is not authenticated / no active org is set.
16
+ */
17
+ async function resolveHeldRunContext() {
18
+ const config = await loadGlobalConfig();
19
+ const token = config.pat ?? config.token;
20
+ if (!token) {
21
+ logger.error(pc.red("Not authenticated. Run `kici login` to get started."));
22
+ return null;
23
+ }
24
+ const endpoint = config.platformEndpoint ?? config.endpoint;
25
+ if (!endpoint) {
26
+ logger.error(pc.red("No endpoint configured. Run `kici login` to configure."));
27
+ return null;
28
+ }
29
+ if (!config.activeOrgId) {
30
+ logger.error(pc.red("No active organization. Run `kici org use <name>` to set one."));
31
+ return null;
32
+ }
33
+ return {
34
+ endpoint,
35
+ token,
36
+ orgId: config.activeOrgId
37
+ };
38
+ }
39
+ function authHeaders(token) {
40
+ return {
41
+ "Content-Type": "application/json",
42
+ Authorization: `Bearer ${token}`
43
+ };
44
+ }
45
+ /** List the held runs for a single run id. */
46
+ async function listHeldRunsForRun(ctx, runId) {
47
+ const url = `${ctx.endpoint}/api/v1/orgs/${ctx.orgId}/held-runs?runId=${encodeURIComponent(runId)}`;
48
+ const response = await fetch(url, {
49
+ method: "GET",
50
+ headers: authHeaders(ctx.token)
51
+ });
52
+ if (!response.ok) throw new Error(await describeError(response));
53
+ return (await response.json()).heldRuns ?? [];
54
+ }
55
+ /** POST an approve decision for a held run. Returns true on success. */
56
+ async function postApprove(ctx, heldRunId) {
57
+ const url = `${ctx.endpoint}/api/v1/orgs/${ctx.orgId}/held-runs/${heldRunId}/approve`;
58
+ const response = await fetch(url, {
59
+ method: "POST",
60
+ headers: authHeaders(ctx.token)
61
+ });
62
+ if (!response.ok) {
63
+ logger.error(pc.red(await describeError(response)));
64
+ return false;
65
+ }
66
+ return true;
67
+ }
68
+ /** POST a reject decision (with reason) for a held run. Returns true on success. */
69
+ async function postReject(ctx, heldRunId, reason) {
70
+ const url = `${ctx.endpoint}/api/v1/orgs/${ctx.orgId}/held-runs/${heldRunId}/reject`;
71
+ const response = await fetch(url, {
72
+ method: "POST",
73
+ headers: authHeaders(ctx.token),
74
+ body: JSON.stringify({ reason })
75
+ });
76
+ if (!response.ok) {
77
+ logger.error(pc.red(await describeError(response)));
78
+ return false;
79
+ }
80
+ return true;
81
+ }
82
+ /** Build a user-facing error string from a failed response. */
83
+ async function describeError(response) {
84
+ let detail;
85
+ try {
86
+ detail = (await response.json()).error;
87
+ } catch {}
88
+ switch (response.status) {
89
+ case 401: return "Authentication failed. Run `kici login` to re-authenticate.";
90
+ case 403: return `Access denied${detail ? `: ${detail}` : ""}.`;
91
+ case 404: return `Held run not found${detail ? `: ${detail}` : ""}.`;
92
+ default: return detail ?? `Request failed with status ${response.status}.`;
93
+ }
94
+ }
95
+ //#endregion
96
+ export { listHeldRunsForRun, postApprove, postReject, resolveHeldRunContext };
97
+
98
+ //# sourceMappingURL=held-run-client.js.map
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Shared held-run resolution for the `kici approve` / `kici reject` commands.
3
+ *
4
+ * Both commands first list the pending holds for a run, then resolve the one
5
+ * the user named via `--job` / `--step` (or the sole pending hold when there is
6
+ * exactly one and no filter is given). The resolution is a pure function so it
7
+ * can be unit-tested without HTTP.
8
+ */
9
+ /** Hold scope, mirroring the engine `HoldScope` enum. */
10
+ export type HeldRunScope = 'workflow' | 'job' | 'step';
11
+ /** A pending-hold row as returned by `GET /orgs/:orgId/held-runs`. */
12
+ export interface HeldRunSummary {
13
+ id: string;
14
+ runId: string;
15
+ jobId?: string;
16
+ holdScope?: HeldRunScope;
17
+ stepIndex?: number | null;
18
+ status: string;
19
+ }
20
+ /** Filters supplied on the command line. */
21
+ export interface HeldRunFilter {
22
+ /** Match a hold by its job name. */
23
+ job?: string;
24
+ /** Match a step-scoped hold by its step index (compared as a string). */
25
+ step?: string;
26
+ }
27
+ /** Resolution result: either a held-run id or a user-facing error message. */
28
+ export type ResolveResult = {
29
+ ok: true;
30
+ heldRunId: string;
31
+ hold: HeldRunSummary;
32
+ } | {
33
+ ok: false;
34
+ error: string;
35
+ };
36
+ /**
37
+ * Resolve the held-run id matching the filter from a list of pending holds.
38
+ *
39
+ * - `--step` requires `--job` and matches a `step`-scoped hold whose step index
40
+ * equals the given value.
41
+ * - `--job` alone matches a `job`/`workflow`-scoped hold for that job.
42
+ * - With no filter, the sole pending hold is used; ambiguity is an error.
43
+ */
44
+ export declare function resolveHeldRunId(holds: readonly HeldRunSummary[], filter: HeldRunFilter): ResolveResult;
45
+ //# sourceMappingURL=held-run-resolve.d.ts.map
@@ -0,0 +1,53 @@
1
+ import "../chunk-gOLHoazu.js";
2
+ //#region src/commands/held-run-resolve.ts
3
+ /**
4
+ * Resolve the held-run id matching the filter from a list of pending holds.
5
+ *
6
+ * - `--step` requires `--job` and matches a `step`-scoped hold whose step index
7
+ * equals the given value.
8
+ * - `--job` alone matches a `job`/`workflow`-scoped hold for that job.
9
+ * - With no filter, the sole pending hold is used; ambiguity is an error.
10
+ */
11
+ function resolveHeldRunId(holds, filter) {
12
+ const pending = holds.filter((h) => h.status === "pending");
13
+ if (pending.length === 0) return {
14
+ ok: false,
15
+ error: "No pending approval holds found for this run."
16
+ };
17
+ if (filter.step !== void 0) {
18
+ if (!filter.job) return {
19
+ ok: false,
20
+ error: "--step requires --job to identify the held step."
21
+ };
22
+ return pickSingle(pending.filter((h) => h.holdScope === "step" && h.jobId === filter.job && String(h.stepIndex ?? "") === filter.step), `step ${filter.step} of job '${filter.job}'`);
23
+ }
24
+ if (filter.job !== void 0) return pickSingle(pending.filter((h) => h.jobId === filter.job && h.holdScope !== "step"), `job '${filter.job}'`);
25
+ if (pending.length > 1) return {
26
+ ok: false,
27
+ error: "Multiple pending holds for this run. Use --job <name> (and --step <index>) to choose one."
28
+ };
29
+ return {
30
+ ok: true,
31
+ heldRunId: pending[0].id,
32
+ hold: pending[0]
33
+ };
34
+ }
35
+ function pickSingle(matches, label) {
36
+ if (matches.length === 0) return {
37
+ ok: false,
38
+ error: `No pending hold found for ${label}.`
39
+ };
40
+ if (matches.length > 1) return {
41
+ ok: false,
42
+ error: `Multiple pending holds match ${label}; cannot disambiguate.`
43
+ };
44
+ return {
45
+ ok: true,
46
+ heldRunId: matches[0].id,
47
+ hold: matches[0]
48
+ };
49
+ }
50
+ //#endregion
51
+ export { resolveHeldRunId };
52
+
53
+ //# sourceMappingURL=held-run-resolve.js.map
@@ -2,9 +2,9 @@ import "../chunk-gOLHoazu.js";
2
2
  import { detectHookTools, findGitDir } from "../hooks/detector.js";
3
3
  import { installHook } from "../hooks/installer.js";
4
4
  import "../hooks/index.js";
5
+ import path from "node:path";
5
6
  import pc from "picocolors";
6
7
  import { readFile } from "node:fs/promises";
7
- import path from "node:path";
8
8
  import { logger, toErrorMessage } from "@kici-dev/core";
9
9
  import { select } from "@inquirer/prompts";
10
10
  //#region src/commands/hook.ts
@@ -24,6 +24,10 @@ export { orgListCommand, orgUseCommand, orgCurrentCommand } from './org.js';
24
24
  export { logoutCommand } from './logout.js';
25
25
  export { cancelCommand } from './cancel.js';
26
26
  export type { CancelOptions } from './cancel.js';
27
+ export { approveCommand } from './approve.js';
28
+ export type { ApproveOptions } from './approve.js';
29
+ export { rejectCommand } from './reject.js';
30
+ export type { RejectOptions } from './reject.js';
27
31
  export { workflowsListCommand } from './workflows.js';
28
32
  export type { WorkflowsListOptions } from './workflows.js';
29
33
  export { drainWorkerCommand } from './drain-worker.js';
@@ -1,5 +1,6 @@
1
1
  import "../chunk-gOLHoazu.js";
2
2
  import { compileCommand } from "./compile.js";
3
+ import { approveCommand } from "./approve.js";
3
4
  import { cancelCommand } from "./cancel.js";
4
5
  import { docsCommand, docsLlmCommand } from "./docs.js";
5
6
  import { drainWorkerCommand } from "./drain-worker.js";
@@ -16,5 +17,6 @@ import { statusCommand } from "./status.js";
16
17
  import { typesCommand } from "./types.js";
17
18
  import { orgCurrentCommand, orgListCommand, orgUseCommand } from "./org.js";
18
19
  import { logoutCommand } from "./logout.js";
20
+ import { rejectCommand } from "./reject.js";
19
21
  import { workflowsListCommand } from "./workflows.js";
20
- export { cancelCommand, compileCommand, docsCommand, docsLlmCommand, drainWorkerCommand, endpointsCommand, fixtureCommand, hookInstallCommand, initCommand, loginCommand, logoutCommand, orgCurrentCommand, orgListCommand, orgUseCommand, runLocalCommand, runRemoteCommand, secretsListCommand, statusCommand, testCommand, testDryRun, typesCommand, watchCommand, workflowsListCommand };
22
+ export { approveCommand, cancelCommand, compileCommand, docsCommand, docsLlmCommand, drainWorkerCommand, endpointsCommand, fixtureCommand, hookInstallCommand, initCommand, loginCommand, logoutCommand, orgCurrentCommand, orgListCommand, orgUseCommand, rejectCommand, runLocalCommand, runRemoteCommand, secretsListCommand, statusCommand, testCommand, testDryRun, typesCommand, watchCommand, workflowsListCommand };
@@ -7,9 +7,9 @@ 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 path from "node:path";
10
11
  import pc from "picocolors";
11
12
  import { access, mkdir, readFile, rm, writeFile } from "node:fs/promises";
12
- import path from "node:path";
13
13
  import { initZx, logger, toErrorMessage } from "@kici-dev/core";
14
14
  import { detectPackageManager, installBuildPolicyArgs, installCommand, parsePackageManager } from "@kici-dev/core/package-manager";
15
15
  import { checkbox, confirm, select } from "@inquirer/prompts";
@@ -0,0 +1,25 @@
1
+ /**
2
+ * kici reject command
3
+ *
4
+ * Rejects a held approval gate for a run (requires `--reason`). Resolves the
5
+ * held element by `--job` / `--step` (or the sole pending hold), then records
6
+ * the rejection via the Platform dashboard API (PAT auth).
7
+ */
8
+ /** Options for the reject command. */
9
+ export interface RejectOptions {
10
+ /** Match a hold by its job name. */
11
+ job?: string;
12
+ /** Match a step-scoped hold by its step index. */
13
+ step?: string;
14
+ /** Required rejection reason. */
15
+ reason?: string;
16
+ }
17
+ /**
18
+ * Reject a held approval gate.
19
+ *
20
+ * @param runId - The run whose hold to reject.
21
+ * @param options - Job/step filters plus the required reason.
22
+ * @returns true on success, false on error.
23
+ */
24
+ export declare function rejectCommand(runId: string, options?: RejectOptions): Promise<boolean>;
25
+ //# sourceMappingURL=reject.d.ts.map
@@ -0,0 +1,49 @@
1
+ import "../chunk-gOLHoazu.js";
2
+ import { listHeldRunsForRun, postReject, resolveHeldRunContext } from "./held-run-client.js";
3
+ import { resolveHeldRunId } from "./held-run-resolve.js";
4
+ import pc from "picocolors";
5
+ import { logger, toErrorMessage } from "@kici-dev/core";
6
+ //#region src/commands/reject.ts
7
+ /**
8
+ * kici reject command
9
+ *
10
+ * Rejects a held approval gate for a run (requires `--reason`). Resolves the
11
+ * held element by `--job` / `--step` (or the sole pending hold), then records
12
+ * the rejection via the Platform dashboard API (PAT auth).
13
+ */
14
+ /**
15
+ * Reject a held approval gate.
16
+ *
17
+ * @param runId - The run whose hold to reject.
18
+ * @param options - Job/step filters plus the required reason.
19
+ * @returns true on success, false on error.
20
+ */
21
+ async function rejectCommand(runId, options = {}) {
22
+ try {
23
+ if (!options.reason) {
24
+ logger.error(pc.red("A rejection reason is required. Pass --reason <text>."));
25
+ return false;
26
+ }
27
+ const ctx = await resolveHeldRunContext();
28
+ if (!ctx) return false;
29
+ const resolution = resolveHeldRunId(await listHeldRunsForRun(ctx, runId), {
30
+ job: options.job,
31
+ step: options.step
32
+ });
33
+ if (!resolution.ok) {
34
+ logger.error(pc.red(resolution.error));
35
+ return false;
36
+ }
37
+ logger.info(`Rejecting held run ${pc.cyan(resolution.heldRunId)} for run ${pc.cyan(runId)}...`);
38
+ if (!await postReject(ctx, resolution.heldRunId, options.reason)) return false;
39
+ logger.info(pc.yellow("Rejection recorded. The held element will fail."));
40
+ return true;
41
+ } catch (error) {
42
+ logger.error(pc.red(`Error: ${toErrorMessage(error)}`));
43
+ return false;
44
+ }
45
+ }
46
+ //#endregion
47
+ export { rejectCommand };
48
+
49
+ //# sourceMappingURL=reject.js.map
@@ -12,9 +12,9 @@ import { formatJunitResult } from "../remote/output/junit.js";
12
12
  import { StreamingFormatter } from "../remote/output/streaming.js";
13
13
  import { formatErrorHighlight, formatMultiFixtureSummary, formatSummary } from "../remote/output/summary.js";
14
14
  import { compileFixtures, filterFixtures } from "../fixtures/compiler.js";
15
+ import path from "node:path";
15
16
  import pc from "picocolors";
16
17
  import { readFile, writeFile } from "node:fs/promises";
17
- import path from "node:path";
18
18
  import { formatBytes, logger, toErrorMessage } from "@kici-dev/core";
19
19
  //#region src/commands/run.ts
20
20
  /**
@@ -15,7 +15,7 @@ import { formatDuration, logger, toErrorMessage } from "@kici-dev/core";
15
15
  * Looks up local history first, then fetches from the orchestrator for
16
16
  * up-to-date status and logs.
17
17
  */
18
- const CLI_VERSION = "0.1.15";
18
+ const CLI_VERSION = "0.1.16";
19
19
  /**
20
20
  * Show status and details of a test run.
21
21
  *
@@ -6,9 +6,9 @@ import { displayDryRun } from "../test-runner/dry-run.js";
6
6
  import { parseEventArg } from "../test-runner/event-types.js";
7
7
  import { buildEventPayload } from "../test-runner/payload-builder.js";
8
8
  import { loadSecretsFile } from "../test-runner/secrets-file.js";
9
+ import path from "node:path";
9
10
  import pc from "picocolors";
10
11
  import { readFile } from "node:fs/promises";
11
- import path from "node:path";
12
12
  import { logger, toErrorMessage } from "@kici-dev/core";
13
13
  import { matchAllWorkflows, normalizeRunsOn } from "@kici-dev/engine";
14
14
  //#region src/commands/test.ts
@@ -1,9 +1,9 @@
1
1
  import "../chunk-gOLHoazu.js";
2
2
  import { loadGlobalConfig } from "../remote/config.js";
3
3
  import { generateSecretsDts } from "../generators/secrets-dts.js";
4
+ import path from "node:path";
4
5
  import pc from "picocolors";
5
6
  import fs from "node:fs/promises";
6
- import path from "node:path";
7
7
  import { toErrorMessage } from "@kici-dev/core";
8
8
  //#region src/commands/types.ts
9
9
  /**
@@ -2,8 +2,8 @@ import "../chunk-gOLHoazu.js";
2
2
  import { resolveKiciDir } from "../execution/executor.js";
3
3
  import "../execution/index.js";
4
4
  import { compileCommand } from "./compile.js";
5
- import pc from "picocolors";
6
5
  import path from "node:path";
6
+ import pc from "picocolors";
7
7
  import { logger, toErrorMessage } from "@kici-dev/core";
8
8
  import chokidar from "chokidar";
9
9
  //#region src/commands/watch.ts
@@ -2,10 +2,10 @@ import "../chunk-gOLHoazu.js";
2
2
  import { compilerError } from "../errors/formatter.js";
3
3
  import "../errors/index.js";
4
4
  import { ensureTsLoaderHook } from "./ts-loader.js";
5
+ import { pathToFileURL } from "node:url";
6
+ import path from "node:path";
5
7
  import { existsSync } from "node:fs";
6
8
  import fs from "node:fs/promises";
7
- import path from "node:path";
8
- import { pathToFileURL } from "node:url";
9
9
  //#region src/execution/executor.ts
10
10
  /**
11
11
  * Load a TypeScript workflow/config module by direct dynamic import.
@@ -1,7 +1,7 @@
1
1
  import "../chunk-gOLHoazu.js";
2
+ import path from "node:path";
2
3
  import { existsSync } from "node:fs";
3
4
  import { readFile } from "node:fs/promises";
4
- import path from "node:path";
5
5
  import { logger } from "@kici-dev/core";
6
6
  //#region src/execution/sdk-alias.ts
7
7
  /**
@@ -1,8 +1,8 @@
1
1
  import "../chunk-gOLHoazu.js";
2
2
  import { ensureTsLoaderHook } from "../execution/ts-loader.js";
3
- import fs from "node:fs/promises";
4
- import path from "node:path";
5
3
  import { fileURLToPath, pathToFileURL } from "node:url";
4
+ import path from "node:path";
5
+ import fs from "node:fs/promises";
6
6
  import picomatch from "picomatch";
7
7
  //#region src/fixtures/compiler.ts
8
8
  /**
@@ -1,7 +1,7 @@
1
1
  import "../../chunk-gOLHoazu.js";
2
- import { readFileSync } from "node:fs";
3
- import { dirname, join } from "node:path";
4
2
  import { fileURLToPath } from "node:url";
3
+ import { dirname, join } from "node:path";
4
+ import { readFileSync } from "node:fs";
5
5
  //#region src/fixtures/defaults/index.ts
6
6
  /**
7
7
  * Built-in fixture registry for common GitHub webhook events.
@@ -1,6 +1,6 @@
1
1
  import "../chunk-gOLHoazu.js";
2
- import { readFile, stat } from "node:fs/promises";
3
2
  import path from "node:path";
3
+ import { readFile, stat } from "node:fs/promises";
4
4
  //#region src/hooks/detector.ts
5
5
  const TOOL_CONFIGS = [
6
6
  {
@@ -1,8 +1,8 @@
1
1
  import "../chunk-gOLHoazu.js";
2
2
  import { findGitDir } from "./detector.js";
3
3
  import { getHookTemplate, hasKiciHook } from "./templates.js";
4
- import { chmod, mkdir, readFile, stat, writeFile } from "node:fs/promises";
5
4
  import path from "node:path";
5
+ import { chmod, mkdir, readFile, stat, writeFile } from "node:fs/promises";
6
6
  import { exec } from "node:child_process";
7
7
  import { promisify } from "node:util";
8
8
  //#region src/hooks/installer.ts
package/dist/index.d.ts CHANGED
@@ -4,7 +4,7 @@ export { validateConfig } from './validation/index.js';
4
4
  export type { ValidationResult } from './validation/index.js';
5
5
  export { generateLockFile, serializeLockFile } from './lockfile/index.js';
6
6
  export { SCHEMA_VERSION, isLockStaticJob } from './types.js';
7
- export type { LockFile, LockWorkflow, LockJob, LockDynamicJobFn, LockJobOrFactory, LockTrigger, LockPrTrigger, LockPushTrigger, LockMatrix, LockRule, LockStep, LockSource, LockBranchPattern, } from './types.js';
7
+ export type { LockFile, LockWorkflow, LockJob, LockDynamicJobFn, LockJobOrFactory, LockTrigger, LockPrTrigger, LockPushTrigger, LockMatrix, LockRule, LockStep, LockApproval, LockSource, LockBranchPattern, } from './types.js';
8
8
  export { formatError, compilerError, isCompilerError } from './errors/index.js';
9
9
  export type { SourceLocation, CompilerError } from './errors/index.js';
10
10
  export { CapabilityGapError, formatCapabilityGapError } from './errors/index.js';
@@ -86,7 +86,7 @@ Cross-repo workflows that let a single workflow repo define jobs which run on ev
86
86
 
87
87
  ---
88
88
 
89
- ## Getting started with KiCI
89
+ ## Getting started with workflows
90
90
 
91
91
  Source: https://docs.kici.dev/user/getting-started/
92
92
 
@@ -5377,6 +5377,72 @@ kici cancel abc123 --force
5377
5377
  kici cancel --branch feature/wip
5378
5378
  ```
5379
5379
 
5380
+ ### kici approve
5381
+
5382
+ Approve a held [approval gate](approvals.md) so the run resumes. Identify the held element by run ID, optionally narrowed to a job and step.
5383
+
5384
+ ```bash
5385
+ kici approve <run-id> [options]
5386
+ ```
5387
+
5388
+ **Arguments:**
5389
+
5390
+ | Argument | Required | Description |
5391
+ | -------- | -------- | ---------------------------------- |
5392
+ | `run-id` | yes | Run ID holding the gate to approve |
5393
+
5394
+ **Options:**
5395
+
5396
+ | Option | Default | Description |
5397
+ | ----------------- | ------- | --------------------------------------------------- |
5398
+ | `--job <name>` | none | Approve a held job (omit for a workflow-level hold) |
5399
+ | `--step <name>` | none | Approve a held step (used with `--job`) |
5400
+ | `--reason <text>` | none | Optional note recorded with the approval |
5401
+
5402
+ **Examples:**
5403
+
5404
+ ```bash
5405
+ # Approve a workflow-level hold
5406
+ kici approve abc123
5407
+
5408
+ # Approve a held job
5409
+ kici approve abc123 --job deploy-production
5410
+
5411
+ # Approve a held step
5412
+ kici approve abc123 --job migrate-and-deploy --step apply-migration
5413
+ ```
5414
+
5415
+ You must be eligible for at least one unsatisfied clause (a member of a named team, or a named user) and hold the `environments:write` or `ci_trust:write` permission. The command reports whether the element was released, how many clauses remain, or that it was rejected.
5416
+
5417
+ ### kici reject
5418
+
5419
+ Reject a held [approval gate](approvals.md). A rejection fails the held element and the run. A reason is required.
5420
+
5421
+ ```bash
5422
+ kici reject <run-id> --reason <text> [options]
5423
+ ```
5424
+
5425
+ **Arguments:**
5426
+
5427
+ | Argument | Required | Description |
5428
+ | -------- | -------- | --------------------------------- |
5429
+ | `run-id` | yes | Run ID holding the gate to reject |
5430
+
5431
+ **Options:**
5432
+
5433
+ | Option | Default | Description |
5434
+ | ----------------- | ------- | -------------------------------------------------- |
5435
+ | `--reason <text>` | none | Required. Reason recorded with the rejection |
5436
+ | `--job <name>` | none | Reject a held job (omit for a workflow-level hold) |
5437
+ | `--step <name>` | none | Reject a held step (used with `--job`) |
5438
+
5439
+ **Examples:**
5440
+
5441
+ ```bash
5442
+ # Reject a held job with a reason
5443
+ kici reject abc123 --job deploy-production --reason "Wrong release branch"
5444
+ ```
5445
+
5380
5446
  ### kici secrets list
5381
5447
 
5382
5448
  List secret contexts available for test runs. Shows context names and key names (not values).
@@ -6605,6 +6671,58 @@ Practical patterns for building real-world KiCI workflows in TypeScript. The pat
6605
6671
 
6606
6672
  # Workflow features
6607
6673
 
6674
+ ## Account and sign-in
6675
+
6676
+ Source: https://docs.kici.dev/user/account-and-login/
6677
+
6678
+ Your KiCI account is a single identity. It stays the same no matter how you
6679
+ sign in — whether you signed up with GitHub or with an email and password.
6680
+ Changing your sign-in method does not create a new account or move your data;
6681
+ your organizations, roles, and API keys stay attached to the same identity.
6682
+
6683
+ ## Where sign-in methods are managed
6684
+
6685
+ Sign-in methods and passwords are managed in your **account console**, provided
6686
+ by the identity provider that handles single sign-on for KiCI. The dashboard's
6687
+ **Linked accounts** page does not control how you sign in — see
6688
+ [Linked accounts vs sign-in methods](#linked-accounts-vs-sign-in-methods) below.
6689
+
6690
+ You can open the account console from the dashboard: go to your personal
6691
+ settings, open **Linked accounts**, and use the **Account console** link.
6692
+
6693
+ ## Adding a password to a GitHub-created account
6694
+
6695
+ If you registered by signing in with GitHub and now want to sign in with an
6696
+ email and password as well:
6697
+
6698
+ 1. Open your account console.
6699
+ 2. Add a password (and, if prompted, confirm your email).
6700
+
6701
+ After this, you can sign in either with GitHub or with your email and password —
6702
+ it is the same account.
6703
+
6704
+ ## Removing GitHub as a sign-in method
6705
+
6706
+ To stop using GitHub to sign in:
6707
+
6708
+ 1. First add a password (see above). The identity provider will not let you
6709
+ remove your only sign-in method, so you must have another one first.
6710
+ 2. In your account console, remove the GitHub sign-in method.
6711
+
6712
+ Your account, organizations, and data are unaffected — you simply sign in a
6713
+ different way afterward.
6714
+
6715
+ ## Linked accounts vs sign-in methods
6716
+
6717
+ The dashboard's **Linked accounts** page controls **run-attribution metadata**
6718
+ only — for example, showing your GitHub username on the runs you trigger and
6719
+ determining your contributor trust level. Unlinking a provider there removes
6720
+ that display link; it does **not** remove the provider as a way to sign in.
6721
+
6722
+ To actually change how you sign in, use your account console as described above.
6723
+
6724
+ ---
6725
+
6608
6726
  ## Concurrency groups
6609
6727
 
6610
6728
  Source: https://docs.kici.dev/user/concurrency/
@@ -7266,6 +7384,16 @@ Create custom roles to restrict what team members can do, or use the built-in **
7266
7384
 
7267
7385
  <!-- /help:settings-roles -->
7268
7386
 
7387
+ <!-- help:settings-teams#settings -->
7388
+
7389
+ Teams are named groups of organization members. A role granted to a team is inherited by every member, so you can manage permissions for a whole group in one place.
7390
+
7391
+ Team names can also be referenced in workflow approval gates (`requireApproval: [{ team: 'leads' }]`) — any member of the named team can satisfy that gate.
7392
+
7393
+ Managing teams (create / rename / delete, membership, role grants) requires the **Teams** permission at `admin`; `read` shows a view-only list.
7394
+
7395
+ <!-- /help:settings-teams -->
7396
+
7269
7397
  <!-- help:settings-api-keys#settings -->
7270
7398
 
7271
7399
  API keys allow programmatic access to the KiCI API for automation, scripts, and CI integrations.
@@ -7679,7 +7807,9 @@ Use a token's clone button to open the creation modal prefilled with that token'
7679
7807
 
7680
7808
  <!-- help:personal-linked-accounts#account -->
7681
7809
 
7682
- Linked accounts connect your external provider identities (like GitHub) to your KiCI account. Linking enables features like showing your provider username in run metadata and associating your commits with your KiCI identity.
7810
+ Linked accounts connect your external provider identities (like GitHub) to your KiCI account. Linking shows your provider username in run metadata and sets your contributor trust level.
7811
+
7812
+ **Unlinking here removes the display link only** — it does not remove a sign-in method. To change how you sign in (add a password, remove GitHub login), use the **Account console** link, or see [Account and sign-in](./account-and-login.md).
7683
7813
 
7684
7814
  <!-- /help:personal-linked-accounts -->
7685
7815
 
@@ -7787,6 +7917,8 @@ The standalone account page (`/account`) provides access to personal settings ou
7787
7917
  - **Personal access tokens** -- create and revoke PATs for programmatic API access
7788
7918
  - **Linked accounts** -- connect external provider identities (e.g. GitHub) to your KiCI account
7789
7919
 
7920
+ Linked accounts control run-attribution metadata only — unlinking a provider here does not remove it as a way to sign in. To change how you sign in, see [Account and sign-in](./account-and-login.md).
7921
+
7790
7922
  This page is also accessible within an org context via the user menu in the sidebar (`/orgs/:customerId/account`).
7791
7923
 
7792
7924
  ## Admin section
@@ -8227,7 +8359,9 @@ Require manual approval before a job can proceed:
8227
8359
  Required reviewers: alice, bob
8228
8360
  ```
8229
8361
 
8230
- When reviewers are required, the job enters a "held" state. Reviewers can approve or reject via the dashboard or API. Held runs expire after a configurable timeout (default: 1 hour).
8362
+ When reviewers are required, the job enters a "held" state. Reviewers can approve or reject via the dashboard, the [`kici approve`](cli-reference.md#kici-approve) command, or the API. Held runs expire after a configurable timeout.
8363
+
8364
+ This operator-set rule is the **mandatory** form of an approval gate. Workflow authors can also declare gates in code with `requireApproval` at step, job, or workflow level — see [Approval gates](approvals.md). Both forms use the same held-element mechanism and the same queue.
8231
8365
 
8232
8366
  ### Wait timer
8233
8367