@kici-dev/agent 0.1.15 → 0.1.17

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 (30) hide show
  1. package/dist/diagnostics/mini-bundle.d.ts +9 -0
  2. package/dist/execution/dep-installer.d.ts +7 -3
  3. package/dist/execution/dep-packer.d.ts +6 -1
  4. package/dist/execution/env-init/presets/directives.d.ts +20 -0
  5. package/dist/execution/env-init/presets/expand.d.ts +16 -0
  6. package/dist/execution/env-init/presets/mise/cache-key.d.ts +7 -0
  7. package/dist/execution/env-init/presets/mise/expander.d.ts +16 -0
  8. package/dist/execution/env-init/presets/mise/templates.d.ts +16 -0
  9. package/dist/execution/env-init/presets/mise/windows-install.d.ts +18 -0
  10. package/dist/execution/env-init/presets/registry.d.ts +31 -0
  11. package/dist/execution/init-runner.d.ts +7 -0
  12. package/dist/execution/job-runner.d.ts +18 -1
  13. package/dist/execution/sandbox/env-delta.d.ts +2 -0
  14. package/dist/execution/sandbox/index.d.ts +1 -1
  15. package/dist/execution/sandbox/ipc-protocol.d.ts +101 -3
  16. package/dist/execution/sandbox/step-loop.d.ts +24 -1
  17. package/dist/execution/sandbox/types.d.ts +18 -1
  18. package/dist/execution/sandbox/workflow-runner.d.ts +12 -7
  19. package/dist/execution/validate-kici-deps.d.ts +5 -0
  20. package/dist/execution/workspace-siblings.d.ts +33 -0
  21. package/dist/index.js +223 -6
  22. package/dist/provenance/attest.d.ts +30 -0
  23. package/dist/provenance/sign.d.ts +21 -0
  24. package/dist/provenance/statement-builder.d.ts +38 -0
  25. package/dist/server.js +698 -146
  26. package/dist/version.d.ts +2 -0
  27. package/dist/workflow-runner.js +877 -45
  28. package/dist/ws/orchestrator-client.d.ts +53 -4
  29. package/package.json +8 -5
  30. package/sbom.spdx.json +1957 -152
@@ -0,0 +1,9 @@
1
+ export interface AgentMiniBundleOptions {
2
+ agentId: string;
3
+ logDir?: string;
4
+ logWindowHours: number;
5
+ config: Record<string, unknown>;
6
+ metricsText?: string;
7
+ }
8
+ export declare function buildAgentMiniBundle(opts: AgentMiniBundleOptions): Promise<Buffer>;
9
+ //# sourceMappingURL=mini-bundle.d.ts.map
@@ -4,12 +4,14 @@
4
4
  * When the dep cache is unavailable or a download fails, the agent installs
5
5
  * `.kici/` dependencies directly with the repository's package manager.
6
6
  *
7
- * The package manager is detected from the cloned repo (npm / pnpm); the
7
+ * The package manager is detected from the cloned repo (npm / pnpm / yarn); the
8
8
  * presence of `.kici/package.json` signals that deps should be installed. npm
9
9
  * is the default and ships with every Node.js install; pnpm is used when the
10
10
  * repo is a pnpm workspace so a `.kici/` member can resolve in-repo
11
- * `workspace:` siblings. yarn is detected but not yet supported and is
12
- * rejected with an actionable error.
11
+ * `workspace:` siblings. yarn classic (v1) is supported for registry
12
+ * dependencies and version-range workspace siblings (which it links but does
13
+ * not build, so the agent builds the in-repo closure after install). yarn
14
+ * berry (v2+) is not yet supported.
13
15
  *
14
16
  * Security: the install runs with an isolated per-invocation cache/store
15
17
  * directory to prevent cache poisoning across build jobs — a malicious
@@ -49,4 +51,6 @@ export interface InstallDepsOptions {
49
51
  * @param opts - Optional registry / installEnv / repoRoot configuration.
50
52
  */
51
53
  export declare function installDeps(kiciDir: string, opts?: InstallDepsOptions): Promise<void>;
54
+ /** Pure: argv for `yarn install` with an isolated cache folder. */
55
+ export declare function buildYarnInstallArgs(cacheDir: string, hasPrivateRegistry: boolean): string[];
52
56
  //# sourceMappingURL=dep-installer.d.ts.map
@@ -6,13 +6,18 @@
6
6
  * **repo-root-relative** (cwd = the clone root) so restore is a single layout
7
7
  * regardless of package manager:
8
8
  *
9
- * - npm / yarn: just `.kici/node_modules`.
9
+ * - npm: just `.kici/node_modules`.
10
10
  * - pnpm: `.kici/node_modules` plus the repo-root `node_modules/.pnpm` virtual
11
11
  * store and the in-repo `workspace:` sibling package directories `.kici`
12
12
  * depends on (with their built output). pnpm lays `.kici/node_modules` out as
13
13
  * symlinks into the root store and into sibling dirs that live outside
14
14
  * `.kici/`, so packing `.kici/node_modules` alone would capture dangling
15
15
  * links — the store and siblings must travel together.
16
+ * - yarn classic: the resolved node_modules root (standalone `.kici` →
17
+ * `.kici/node_modules`; hoisted workspace member → the repo-root
18
+ * `node_modules`) plus the in-repo version-range sibling package directories
19
+ * `.kici` depends on (with their built output), whose symlinks would dangle
20
+ * otherwise.
16
21
  *
17
22
  * Uses tar.gz (Node.js built-in zlib, no external binary) in portable mode to
18
23
  * strip user/group info for cross-machine consistency; symlinks are preserved
@@ -0,0 +1,20 @@
1
+ import type { GenericInitConfig, Job, MiseInitConfig } from '@kici-dev/sdk';
2
+ /** A normalized init step, ready for agent-side expansion. */
3
+ export type InitDirective = {
4
+ kind: 'generic';
5
+ config: GenericInitConfig;
6
+ } | {
7
+ kind: 'preset';
8
+ name: 'mise';
9
+ config: MiseInitConfig;
10
+ } | {
11
+ kind: 'auto';
12
+ };
13
+ /**
14
+ * Normalize `Job.init` to an ordered list of directives, without touching the
15
+ * filesystem. `false`/`undefined` -> []; `'auto'` -> one auto directive;
16
+ * presets/generic configs -> their directive; arrays map element-wise.
17
+ * `'auto'` is a scalar only — finding it inside an array throws.
18
+ */
19
+ export declare function normalizeInitItems(job: Job | undefined): InitDirective[];
20
+ //# sourceMappingURL=directives.d.ts.map
@@ -0,0 +1,16 @@
1
+ import type { GenericInitConfig } from '@kici-dev/sdk';
2
+ import type { InitDirective } from './directives.js';
3
+ /** Options for agent-side directive expansion. */
4
+ export interface ExpandOptions {
5
+ cloneRoot: string;
6
+ /** Host platform; defaults to process.platform. */
7
+ platform?: NodeJS.Platform;
8
+ /** Optional info logger (e.g. to emit a pseudo-step line). */
9
+ log?: (message: string) => void;
10
+ }
11
+ /**
12
+ * Expand normalized directives into concrete generic init configs, reading the
13
+ * clone root for preset cache keys and `'auto'` marker detection.
14
+ */
15
+ export declare function expandInitDirectives(directives: InitDirective[], opts: ExpandOptions): Promise<GenericInitConfig[]>;
16
+ //# sourceMappingURL=expand.d.ts.map
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Derive the default mise cache key from the committed mise config under
3
+ * `cloneRoot`. Concatenates whichever of {@link MISE_CONFIG_FILES} exist (in
4
+ * fixed order) and hashes them. Returns `mise-noconfig` when none exist.
5
+ */
6
+ export declare function miseCacheKey(cloneRoot: string): Promise<string>;
7
+ //# sourceMappingURL=cache-key.d.ts.map
@@ -0,0 +1,16 @@
1
+ import type { GenericInitConfig, MiseInitConfig } from '@kici-dev/sdk';
2
+ import { type MiseWindowsArch } from './windows-install.js';
3
+ /** Arguments to expand the mise preset into a concrete generic init config. */
4
+ export interface MiseExpandArgs {
5
+ cloneRoot: string;
6
+ config: MiseInitConfig;
7
+ /** Host platform (defaults to process.platform). Injected for tests. */
8
+ platform?: NodeJS.Platform;
9
+ /** Windows asset resolver (defaults to the real GitHub lookup). Injected for tests. */
10
+ resolveWindowsAsset?: (arch: MiseWindowsArch) => Promise<string>;
11
+ }
12
+ /** The mise preset expander: turns MiseInitConfig into an OS-correct GenericInitConfig. */
13
+ export declare const miseExpander: {
14
+ expand(args: MiseExpandArgs): Promise<GenericInitConfig>;
15
+ };
16
+ //# sourceMappingURL=expander.d.ts.map
@@ -0,0 +1,16 @@
1
+ /** OS-specific pieces of a mise init expansion. */
2
+ export interface MiseTemplate {
3
+ /** The `run` command. */
4
+ run: string;
5
+ /** Shell to run it with. */
6
+ shell: string;
7
+ /** Cache `paths` for mise's data dir on this OS. */
8
+ cachePaths: string[];
9
+ }
10
+ /**
11
+ * Pick the mise template for a host platform (Node `process.platform` value).
12
+ * The Windows `run` carries an `<ASSET_URL>` placeholder the expander replaces
13
+ * with the resolved GitHub-release zip URL.
14
+ */
15
+ export declare function selectMiseTemplate(platform: NodeJS.Platform): MiseTemplate;
16
+ //# sourceMappingURL=templates.d.ts.map
@@ -0,0 +1,18 @@
1
+ /** mise Windows architecture slug used in release asset names. */
2
+ export type MiseWindowsArch = 'x64' | 'arm64';
3
+ interface GithubRelease {
4
+ assets: {
5
+ name: string;
6
+ browser_download_url: string;
7
+ }[];
8
+ }
9
+ /** Map a Windows `PROCESSOR_ARCHITECTURE` value to mise's asset arch slug. */
10
+ export declare function miseWindowsArch(processorArch: string | undefined): MiseWindowsArch;
11
+ /**
12
+ * Resolve the download URL of the latest mise standalone Windows zip for `arch`.
13
+ * `fetchJson` is injected (defaults to a real fetch) so the resolution is
14
+ * unit-testable without network.
15
+ */
16
+ export declare function resolveLatestMiseWindowsAsset(arch: MiseWindowsArch, fetchJson?: (url: string) => Promise<GithubRelease>): Promise<string>;
17
+ export {};
18
+ //# sourceMappingURL=windows-install.d.ts.map
@@ -0,0 +1,31 @@
1
+ import type { GenericInitConfig } from '@kici-dev/sdk';
2
+ /**
3
+ * A preset expander: clone root + typed config -> a concrete generic init config.
4
+ * Expanders may accept additional optional fields (e.g. an injected `platform`
5
+ * for tests); the agent path passes only `cloneRoot` + `config`.
6
+ */
7
+ export interface PresetExpander<C> {
8
+ expand(args: {
9
+ cloneRoot: string;
10
+ config: C;
11
+ platform?: NodeJS.Platform;
12
+ }): Promise<GenericInitConfig>;
13
+ }
14
+ /**
15
+ * The set of typed presets. Nix is added here (one row) once its provider lands.
16
+ */
17
+ export declare const PRESET_REGISTRY: {
18
+ mise: {
19
+ expand(args: import("./mise/expander.js").MiseExpandArgs): Promise<GenericInitConfig>;
20
+ };
21
+ };
22
+ export type PresetName = keyof typeof PRESET_REGISTRY;
23
+ /**
24
+ * Ordered auto-detect table: `init: 'auto'` tries each row against the clone
25
+ * root and accumulates matches in this order. (nix row added with its provider.)
26
+ */
27
+ export declare const AUTO_DETECT_TABLE: {
28
+ markers: string[];
29
+ preset: PresetName;
30
+ }[];
31
+ //# sourceMappingURL=registry.d.ts.map
@@ -1,4 +1,5 @@
1
1
  import type { Workflow } from '@kici-dev/sdk';
2
+ import { type MatrixValues } from '@kici-dev/engine';
2
3
  /**
3
4
  * Result of evaluating dynamic fields on a job.
4
5
  * Only fields that were flagged as dynamic and successfully resolved are set.
@@ -7,6 +8,11 @@ export interface InitResult {
7
8
  environmentName?: string;
8
9
  env?: Record<string, string>;
9
10
  concurrencyGroup?: string;
11
+ /**
12
+ * Resolved matrix combinations when the job's matrix is a dynamic function.
13
+ * The orchestrator re-materializes these into N execution jobs at dispatch.
14
+ */
15
+ matrixValues?: MatrixValues[];
10
16
  }
11
17
  /**
12
18
  * Evaluate dynamic fields (environment, env, concurrencyGroup) on a job.
@@ -29,5 +35,6 @@ export declare function evaluateDynamicFields(workflow: Workflow, jobName: strin
29
35
  dynamicEnvironment: boolean;
30
36
  dynamicEnv: boolean;
31
37
  dynamicConcurrencyGroup: boolean;
38
+ dynamicMatrix?: boolean;
32
39
  }, timeoutMs?: number): Promise<InitResult>;
33
40
  //# sourceMappingURL=init-runner.d.ts.map
@@ -1,6 +1,6 @@
1
1
  import type { AgentToOrchestratorMessage, JobDispatch } from '@kici-dev/engine';
2
2
  import type { AppConfig } from '../config.js';
3
- import type { CacheRequestIpc, CacheResponseIpc } from './sandbox/index.js';
3
+ import type { CacheRequestIpc, CacheResponseIpc, ProvenanceRequestIpc, ProvenanceResponseIpc, StepApprovalRequestIpc, StepApprovalResolvedIpc } from './sandbox/index.js';
4
4
  /**
5
5
  * Dependencies injected into JobRunner.
6
6
  */
@@ -91,6 +91,21 @@ export interface JobRunnerDeps {
91
91
  * Optional for backward compatibility (callers that don't support the cache).
92
92
  */
93
93
  requestUserCache?: (jobId: string, request: CacheRequestIpc) => Promise<CacheResponseIpc>;
94
+ /**
95
+ * Relay a provenance bundle upload operation to the orchestrator and await the
96
+ * response. Translates the sandbox `provenance.request` IPC into the matching
97
+ * `provenance.upload.request` / `.complete` WS message. Optional for backward
98
+ * compatibility (callers that don't support provenance).
99
+ */
100
+ relayProvenance?: (jobId: string, request: ProvenanceRequestIpc) => Promise<ProvenanceResponseIpc>;
101
+ /**
102
+ * Relay a step-level approval request to the orchestrator and await the
103
+ * resolution. Translates the sandbox `approval.request` IPC into a
104
+ * `step.approval-request` WS message and returns the orchestrator's
105
+ * `step.approval-resolved` mapped onto the IPC response shape. Optional for
106
+ * backward compatibility (callers that don't support approvals).
107
+ */
108
+ sendStepApproval?: (runId: string, jobId: string, request: StepApprovalRequestIpc) => Promise<StepApprovalResolvedIpc>;
94
109
  }
95
110
  interface ActiveJob {
96
111
  abortController: AbortController;
@@ -125,6 +140,8 @@ export declare class JobRunner {
125
140
  private readonly _sendConcurrencyReport;
126
141
  private readonly _sendApiRequest?;
127
142
  private readonly _requestUserCache?;
143
+ private readonly _relayProvenance?;
144
+ private readonly _sendStepApproval?;
128
145
  /** Tracks running jobs for concurrency and cancellation */
129
146
  readonly activeJobs: Map<string, ActiveJob>;
130
147
  /** Active sandbox for the current job (used for abort). */
@@ -31,6 +31,8 @@ export interface ApplyEnvDeltaOptions {
31
31
  target?: NodeJS.ProcessEnv;
32
32
  /** Invoked once per rejected key (e.g. to emit a masked log warning). */
33
33
  onReject?: (key: string) => void;
34
+ /** PATH list separator. Defaults to the platform separator (';' on Windows, ':' elsewhere). */
35
+ pathSeparator?: string;
34
36
  }
35
37
  /**
36
38
  * Apply an environment delta to `target` (defaults to process.env), honoring the
@@ -5,7 +5,7 @@
5
5
  * import { BareMetalSandbox, ContainerSandbox, buildSanitizedEnv } from './sandbox/index.js';
6
6
  */
7
7
  export type { ExecutionSandbox, SandboxSetupOptions, JobExecutionOptions, JobExecutionResult, SandboxStepResult, } from './types.js';
8
- export type { RunnerToAgentMessage, AgentToRunnerMessage, EventEmitRequest, EventEmitResponse, CacheRequestIpc, CacheResponseIpc, JobExecutionRequest, } from './ipc-protocol.js';
8
+ export type { RunnerToAgentMessage, AgentToRunnerMessage, EventEmitRequest, EventEmitResponse, CacheRequestIpc, CacheResponseIpc, ProvenanceRequestIpc, ProvenanceResponseIpc, StepApprovalRequestIpc, StepApprovalResolvedIpc, JobExecutionRequest, } from './ipc-protocol.js';
9
9
  export { buildSanitizedEnv } from './env-sanitizer.js';
10
10
  export { ALLOWED_SYSTEM_VARS, KICI_AGENT_ENV_PREFIX, AGENT_REQUIRED_KICI_VARS, } from '@kici-dev/engine';
11
11
  export { BareMetalSandbox } from './bare-metal-sandbox.js';
@@ -159,7 +159,54 @@ export interface CacheRequestIpc {
159
159
  /** Tarball size in bytes (drives quota accounting). `completeSave` only. */
160
160
  sizeBytes?: number;
161
161
  }
162
- export type RunnerToAgentMessage = ReadyMessage | StepStartMessage | StepCompleteMessage | LogLineMessage | StepSecretMountMessage | JobCompleteMessage | EventEmitRequest | ConcurrencyReportMessage | AgentApiRequestIpc | CacheRequestIpc;
162
+ /**
163
+ * Request a step-level approval hold (runner -> agent). The sandbox runner
164
+ * blocks the step loop before a `requireApproval` step; the agent relays this
165
+ * as a `step.approval-request` WS message and pipes the orchestrator's
166
+ * resolution back as a {@link StepApprovalResolvedIpc}. Mirrors the
167
+ * {@link CacheRequestIpc} relay pattern.
168
+ */
169
+ export interface StepApprovalRequestIpc {
170
+ type: 'approval.request';
171
+ /** UUID for correlating the response. */
172
+ requestId: string;
173
+ /** Step index within the job. */
174
+ stepIndex: number;
175
+ /** Step name (for the hold reason / logs). */
176
+ stepName: string;
177
+ /** AND-list of approver clauses (empty = any approval-capable member). */
178
+ clauses: Array<{
179
+ team: string;
180
+ } | {
181
+ user: string;
182
+ }>;
183
+ /** Human label for the gate. */
184
+ reason: string;
185
+ /** Per-gate timeout override (seconds) from the SDK `requireApproval.timeout`. */
186
+ timeoutSeconds?: number;
187
+ }
188
+ /** Which provenance upload operation to relay. */
189
+ export type ProvenanceRequestOp = 'requestUploadUrl' | 'complete';
190
+ /**
191
+ * Request a provenance bundle upload operation (runner -> agent). The agent
192
+ * relays it over the WS as a `provenance.upload.request` / `.complete` and pipes
193
+ * the response back as a {@link ProvenanceResponseIpc}. Mirrors the
194
+ * {@link CacheRequestIpc} relay pattern.
195
+ */
196
+ export interface ProvenanceRequestIpc {
197
+ type: 'provenance.request';
198
+ /** UUID for correlating the response. */
199
+ requestId: string;
200
+ /** Which provenance operation to perform. */
201
+ op: ProvenanceRequestOp;
202
+ /** Primary subject digest (lowercase hex) — the storage-key discriminator. */
203
+ subjectDigest: string;
204
+ /** Caller-supplied artifact name. `complete` only. */
205
+ subjectName?: string;
206
+ /** Bundle media type. `complete` only. */
207
+ mediaType?: string;
208
+ }
209
+ export type RunnerToAgentMessage = ReadyMessage | StepStartMessage | StepCompleteMessage | LogLineMessage | StepSecretMountMessage | JobCompleteMessage | EventEmitRequest | ConcurrencyReportMessage | AgentApiRequestIpc | CacheRequestIpc | ProvenanceRequestIpc | StepApprovalRequestIpc;
163
210
  /** Instruct the workflow runner to execute a job. */
164
211
  interface ExecuteMessage {
165
212
  type: 'execute';
@@ -233,7 +280,38 @@ export interface CacheResponseIpc {
233
280
  /** Error description (present when the relay or orchestrator failed). */
234
281
  error?: string;
235
282
  }
236
- export type AgentToRunnerMessage = ExecuteMessage | AbortMessage | EventEmitResponse | ConcurrencyAckMessage | AgentApiResponseIpc | CacheResponseIpc;
283
+ /**
284
+ * Resolution of a step-level approval hold (agent -> runner). Relayed from the
285
+ * orchestrator's `step.approval-resolved` WS message. On `approved` the runner
286
+ * runs the step; on `rejected`/`expired` it fails the job. `error` is set when
287
+ * the relay itself failed (treated as a fail-closed reject by the runner).
288
+ */
289
+ export interface StepApprovalResolvedIpc {
290
+ type: 'approval.resolved';
291
+ /** Matches the original request's requestId. */
292
+ requestId: string;
293
+ /** Outcome of the hold. */
294
+ outcome?: 'approved' | 'rejected' | 'expired';
295
+ /** Optional human reason (e.g. the reject reason). */
296
+ reason?: string;
297
+ /** Error description (present when the relay or orchestrator failed). */
298
+ error?: string;
299
+ }
300
+ /**
301
+ * Response to a {@link ProvenanceRequestIpc} (agent -> runner). `requestUploadUrl`
302
+ * resolves with `uploadUrl`; `complete` resolves with an empty (no-field)
303
+ * response. `error` is set when the relay or orchestrator failed.
304
+ */
305
+ export interface ProvenanceResponseIpc {
306
+ type: 'provenance.response';
307
+ /** Matches the original request's requestId. */
308
+ requestId: string;
309
+ /** Presigned PUT URL for the bundle. `requestUploadUrl` only. */
310
+ uploadUrl?: string;
311
+ /** Error description (present when the relay or orchestrator failed). */
312
+ error?: string;
313
+ }
314
+ export type AgentToRunnerMessage = ExecuteMessage | AbortMessage | EventEmitResponse | ConcurrencyAckMessage | AgentApiResponseIpc | CacheResponseIpc | ProvenanceResponseIpc | StepApprovalResolvedIpc;
237
315
  /**
238
316
  * All data the workflow runner needs to execute a job inside the sandbox.
239
317
  *
@@ -241,6 +319,17 @@ export type AgentToRunnerMessage = ExecuteMessage | AbortMessage | EventEmitResp
241
319
  * The runner uses this to clone, install deps, compile, and execute steps.
242
320
  */
243
321
  export interface JobExecutionRequest {
322
+ /**
323
+ * Run UUID. Threaded into the step context so the OIDC token relay can name
324
+ * the job/run a request is bound to. Correlation only — the orchestrator
325
+ * re-derives ownership and the runId from its own dispatch state.
326
+ */
327
+ runId: string;
328
+ /**
329
+ * Job UUID. Sent with `ctx.kici.oidc.token()` requests so the orchestrator
330
+ * can verify the agent owns this job before relaying a mint request.
331
+ */
332
+ jobId: string;
244
333
  /** Working directory inside the sandbox (e.g. /workspace). */
245
334
  workDir: string;
246
335
  /** Repository URL for git clone. */
@@ -277,10 +366,19 @@ export interface JobExecutionRequest {
277
366
  depsHash?: string;
278
367
  /** Workflow name to execute. */
279
368
  workflowName: string;
280
- /** Job name within the workflow. */
369
+ /**
370
+ * Job name used to locate the job in the compiled workflow and to populate
371
+ * `ctx.job.name`. For a matrix child this is the BASE job name (the job is
372
+ * defined once in source); the combination is exposed only via `ctx.matrix`.
373
+ */
281
374
  jobName: string;
282
375
  /** Runs-on label for the job. */
283
376
  runsOn: string;
377
+ /**
378
+ * Matrix combination values for this child (e.g. `{ variant: 'a' }`), exposed
379
+ * to steps as `ctx.matrix`. Absent for non-matrix jobs.
380
+ */
381
+ matrixValues?: Record<string, unknown>;
284
382
  /** Secrets to merge into step environment (highest precedence). */
285
383
  secrets?: Record<string, string>;
286
384
  /** Namespaced secrets by context name for ctx.secrets['context-name'].KEY access. */
@@ -19,7 +19,7 @@ export interface JobHooks {
19
19
  cleanup?: HookInput;
20
20
  }
21
21
  /** Options for the step execution loop. */
22
- interface StepLoopOptions {
22
+ export interface StepLoopOptions {
23
23
  steps: Step[];
24
24
  /** Factory that creates a StepContext for a given step index and name. */
25
25
  createStepContext: (stepIndex: number, stepName: string) => StepContext;
@@ -83,6 +83,29 @@ interface StepLoopOptions {
83
83
  * them for the next step. Never throws -- errors are logged by the wired impl.
84
84
  */
85
85
  afterStepApplyEnvFiles?: () => Promise<void>;
86
+ /**
87
+ * Block a `requireApproval` step pending an orchestrator-side approval hold.
88
+ * The runner sends the normalized requirement and awaits the resolution; the
89
+ * agent keeps job heartbeats flowing during the wait so the agent isn't
90
+ * reaped. Absent ⇒ approvals are not gated (CT / unit harnesses) and steps
91
+ * run unconditionally.
92
+ */
93
+ awaitStepApproval?: (req: {
94
+ stepIndex: number;
95
+ stepName: string;
96
+ clauses: Array<{
97
+ team: string;
98
+ } | {
99
+ user: string;
100
+ }>;
101
+ reason: string;
102
+ timeoutSeconds?: number;
103
+ }) => Promise<StepApprovalResolution>;
104
+ }
105
+ /** Outcome of an awaited step-level approval hold. */
106
+ export interface StepApprovalResolution {
107
+ outcome: 'approved' | 'rejected' | 'expired';
108
+ reason?: string;
86
109
  }
87
110
  /** Result of the step execution loop. */
88
111
  interface StepLoopResult {
@@ -1,5 +1,5 @@
1
1
  import type { JobDispatch } from '@kici-dev/engine';
2
- import type { EventEmitRequest, EventEmitResponse, ConcurrencyReportMessage, ConcurrencyAckMessage, CacheRequestIpc, CacheResponseIpc } from './ipc-protocol.js';
2
+ import type { EventEmitRequest, EventEmitResponse, ConcurrencyReportMessage, ConcurrencyAckMessage, CacheRequestIpc, CacheResponseIpc, ProvenanceRequestIpc, ProvenanceResponseIpc, StepApprovalRequestIpc, StepApprovalResolvedIpc } from './ipc-protocol.js';
3
3
  /**
4
4
  * Common interface for all execution sandbox backends.
5
5
  *
@@ -89,6 +89,23 @@ export interface JobExecutionOptions {
89
89
  * working — the runner falls back to a "not configured" cache response.
90
90
  */
91
91
  onCacheRequest?: (request: CacheRequestIpc) => Promise<CacheResponseIpc>;
92
+ /**
93
+ * Callback for relaying a provenance bundle upload request from the sandbox to
94
+ * the orchestrator. The sandbox runner sends `provenance.request` IPC; the
95
+ * agent wraps it in the matching `provenance.upload.*` WS message and forwards
96
+ * to the orchestrator. Optional so harnesses that don't thread provenance keep
97
+ * working — the runner falls back to a "not configured" error response.
98
+ */
99
+ onProvenanceRequest?: (request: ProvenanceRequestIpc) => Promise<ProvenanceResponseIpc>;
100
+ /**
101
+ * Callback for relaying a step-level approval request from the sandbox to the
102
+ * orchestrator. The sandbox runner sends `approval.request` IPC; the agent
103
+ * wraps it in a `step.approval-request` WS message and forwards to the
104
+ * orchestrator, awaiting the `step.approval-resolved` response which it pipes
105
+ * back as `approval.resolved`. Optional so harnesses that don't thread
106
+ * approvals keep working — the runner falls back to a fail-closed reject.
107
+ */
108
+ onApprovalRequest?: (request: StepApprovalRequestIpc) => Promise<StepApprovalResolvedIpc>;
92
109
  /**
93
110
  * Callback fired once per `ctx.secrets.mountFile` / `exposeFile` call the
94
111
  * workflow runner performs. Carries only key names + the resulting path /
@@ -13,13 +13,18 @@
13
13
  * This file is compiled alongside the agent by rolldown (existing build), but
14
14
  * runs as a SEPARATE process spawned by the sandbox backend.
15
15
  */
16
- import type { Job, GenericInitConfig } from '@kici-dev/sdk';
17
- /** Raw provider webhook body for ctx.rawPayload nested in the envelope. */
18
- export declare function rawPayloadFromEvent(event: Record<string, unknown> | undefined): Record<string, unknown> | undefined;
16
+ import type { StepContext } from '@kici-dev/sdk';
17
+ import type { OutputsMap, StepRefMap, TrackedStepSecrets } from '@kici-dev/sdk';
18
+ import type { RunnerToAgentMessage, JobExecutionRequest } from './ipc-protocol.js';
19
+ import { LogMasker } from './log-masker.js';
19
20
  /**
20
- * Normalize `Job.init` (config | config[] | false | undefined) to an ordered
21
- * array of init specs. `false` is an explicit opt-out and `undefined` (no
22
- * config) both resolve to an empty list — the init phase is then a no-op.
21
+ * Create a StepContext natively inside the workflow runner.
22
+ *
23
+ * The context is reconstructed from the environment and IPC request fields --
24
+ * NOT serialized across the process boundary. This means zx $ runs natively
25
+ * inside this process with full shell access.
23
26
  */
24
- export declare function resolveInitSpecs(job: Job | undefined): GenericInitConfig[];
27
+ export declare function createSandboxStepContext(workDir: string, stepIndex: number, stepName: string, request: JobExecutionRequest, maskedSendFn: (msg: RunnerToAgentMessage) => void, outputsMap: OutputsMap, refMap: StepRefMap, operatorSecretKeys: Set<string>, secretOutputs: Map<string, string>, jobOutputsMap: OutputsMap, secrets: TrackedStepSecrets, masker: LogMasker): StepContext;
28
+ /** Raw provider webhook body for ctx.rawPayload — nested in the envelope. */
29
+ export declare function rawPayloadFromEvent(event: Record<string, unknown> | undefined): Record<string, unknown> | undefined;
25
30
  //# sourceMappingURL=workflow-runner.d.ts.map
@@ -14,6 +14,11 @@
14
14
  * clones the whole repo, so an in-repo sibling is present), and resolves
15
15
  * `file:`/`link:`/`portal:` against a path — allowed when that path stays
16
16
  * inside the cloned repo, rejected when it escapes the clone.
17
+ * - yarn classic (v1) has no `workspace:` protocol and no `portal:` — it links
18
+ * in-repo siblings by version range, not by a local specifier — so both are
19
+ * rejected with guidance; `file:`/`link:` are allowed when the path stays
20
+ * inside the clone, rejected when it escapes. (yarn berry is not yet
21
+ * supported.)
17
22
  *
18
23
  * This module performs that classification so unresolvable specifiers fail
19
24
  * fast with guidance rather than a cryptic install error.
@@ -0,0 +1,33 @@
1
+ /**
2
+ * In-repo workspace-sibling discovery for the agent's dependency handling.
3
+ *
4
+ * A pnpm or yarn-classic workspace lays out a `.kici/` member's `workspace:`
5
+ * (pnpm) or version-range (yarn) siblings as symlinks pointing at package
6
+ * directories that live inside the clone but outside `.kici/` and outside the
7
+ * `node_modules` store. The dep-cache packer must travel those sibling dirs with
8
+ * the closure (their symlinks would dangle otherwise), and the yarn install path
9
+ * must build them (the install links a sibling but does not build it).
10
+ *
11
+ * `collectInRepoSiblings` walks a starting `node_modules` (and transitively each
12
+ * discovered sibling's `node_modules`), returning each in-repo sibling directory
13
+ * once, repo-root-relative, in breadth-first discovery order. The starting
14
+ * `node_modules` is a parameter so it serves pnpm + yarn-standalone (seeded at
15
+ * `.kici/node_modules`) and yarn-workspace-member (seeded at the hoisted root
16
+ * `node_modules`).
17
+ */
18
+ /**
19
+ * The directory yarn lays `.kici`'s dependencies into. A standalone `.kici`
20
+ * (own lockfile, no parent workspace) gets `.kici/node_modules`; a workspace
21
+ * member hoists everything to the repo-root `node_modules`, leaving no
22
+ * `.kici/node_modules`.
23
+ */
24
+ export declare function resolveYarnNodeModulesRoot(repoRoot: string, kiciDir: string): string;
25
+ /**
26
+ * Walk `seedNodeModules` (and transitively each in-repo sibling's
27
+ * `node_modules`) collecting the repo-root-relative directories of workspace
28
+ * siblings — package dirs that live inside the clone but outside `.kici/` and
29
+ * outside the repo-root `node_modules/` store. Returns each dir once, in
30
+ * discovery (BFS) order.
31
+ */
32
+ export declare function collectInRepoSiblings(workDir: string, kiciDir: string, seedNodeModules?: string): Promise<string[]>;
33
+ //# sourceMappingURL=workspace-siblings.d.ts.map