@kici-dev/engine 0.14.2 → 0.16.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 (58) hide show
  1. package/dist/approval/expiry-duration.d.ts +11 -0
  2. package/dist/approval/expiry-duration.js +29 -0
  3. package/dist/audit/access-log-policy.js +2 -0
  4. package/dist/audit/retention-policy.d.ts +1 -1
  5. package/dist/audit/retention-policy.js +5 -1
  6. package/dist/auth/permissions.d.ts +69 -0
  7. package/dist/auth/permissions.js +51 -0
  8. package/dist/context/hold-type.d.ts +0 -19
  9. package/dist/context/hold-type.js +1 -37
  10. package/dist/context/index.d.ts +1 -1
  11. package/dist/context/index.js +2 -2
  12. package/dist/index.d.ts +7 -2
  13. package/dist/index.js +20 -15
  14. package/dist/labels.d.ts +2 -17
  15. package/dist/labels.js +3 -33
  16. package/dist/mcp/held-run-resolve.d.ts +2 -5
  17. package/dist/mcp/held-run-resolve.js +3 -4
  18. package/dist/metrics/metric-catalog.generated.d.ts +0 -5
  19. package/dist/metrics/metric-catalog.generated.js +0 -6
  20. package/dist/protocol/messages/access-log.d.ts +10 -0
  21. package/dist/protocol/messages/access-log.js +2 -0
  22. package/dist/protocol/messages/auth.d.ts +7 -8
  23. package/dist/protocol/messages/auth.js +12 -17
  24. package/dist/protocol/messages/browser.js +1 -1
  25. package/dist/protocol/messages/capabilities.d.ts +21 -100
  26. package/dist/protocol/messages/capabilities.js +22 -124
  27. package/dist/protocol/messages/dashboard.d.ts +64 -22
  28. package/dist/protocol/messages/dashboard.js +43 -40
  29. package/dist/protocol/messages/execution-status.d.ts +3 -3
  30. package/dist/protocol/messages/execution-status.js +7 -12
  31. package/dist/protocol/messages/join.d.ts +73 -2
  32. package/dist/protocol/messages/join.js +101 -12
  33. package/dist/protocol/messages/orchestrator-agent.d.ts +35 -40
  34. package/dist/protocol/messages/orchestrator-agent.js +63 -96
  35. package/dist/protocol/messages/peer.d.ts +278 -26
  36. package/dist/protocol/messages/peer.js +120 -65
  37. package/dist/protocol/messages/platform-orchestrator.d.ts +36 -141
  38. package/dist/protocol/messages/platform-orchestrator.js +24 -86
  39. package/dist/protocol/messages/source-registration.d.ts +0 -13
  40. package/dist/protocol/messages/source-registration.js +9 -10
  41. package/dist/protocol/version.d.ts +9 -15
  42. package/dist/protocol/version.js +9 -15
  43. package/dist/provenance/id-token-claim-names.d.ts +3 -5
  44. package/dist/provenance/id-token-claim-names.js +3 -5
  45. package/dist/status/presentation.d.ts +2 -14
  46. package/dist/status/presentation.js +3 -23
  47. package/dist/trigger/types.d.ts +125 -34
  48. package/dist/trigger/types.js +9 -24
  49. package/dist/util/date.d.ts +7 -0
  50. package/dist/util/date.js +14 -0
  51. package/dist/util/parse-duration.d.ts +6 -0
  52. package/dist/util/parse-duration.js +21 -0
  53. package/dist/util/sleep.d.ts +3 -0
  54. package/dist/util/sleep.js +10 -0
  55. package/dist/webhook/webhook-url-format.d.ts +2 -2
  56. package/dist/webhook/webhook-url-format.js +2 -2
  57. package/package.json +1 -1
  58. package/sbom.spdx.json +5 -5
@@ -1,10 +1,10 @@
1
1
  import "../../rolldown-runtime-ClRpJifh.js";
2
2
  import { provenanceContextSchema } from "../../provenance/id-token-event-claims.js";
3
+ import { agentCapabilitiesSchema, orchAgentCapabilitiesSchema } from "./capabilities.js";
4
+ import { LogStream } from "./log-stream.js";
3
5
  import { ExecutionJobStatus, ExecutionStepStatus, StepConcurrencyKind } from "./execution-status.js";
4
6
  import { dsseEnvelopeSchema } from "../../provenance/dsse.js";
5
7
  import { approvalTimeoutSecondsSchema, approverClauseSchema } from "../../approval/types.js";
6
- import { agentCapabilitiesSchema, orchAgentCapabilitiesSchema } from "./capabilities.js";
7
- import { LogStream } from "./log-stream.js";
8
8
  import { z } from "zod";
9
9
  //#region src/protocol/messages/orchestrator-agent.ts
10
10
  /**
@@ -88,8 +88,6 @@ const jobDispatchSchema = z.object({
88
88
  /** Pass-through job configuration. Shape is `LockJob | LockDynamicJobFn` from the lock file. */
89
89
  jobConfig: z.record(z.string(), z.unknown()).describe("Job configuration from the lock file (LockJob | LockDynamicJobFn)"),
90
90
  timestamp: z.number(),
91
- /** Short-lived GitHub installation token for private repo clone auth. */
92
- token: z.string().optional(),
93
91
  /** Orchestrator-provided secrets to merge into step environment. */
94
92
  secrets: z.record(z.string(), z.string()).optional(),
95
93
  /** Namespaced secrets by context name: { 'context-name': { KEY: 'value' } } */
@@ -98,8 +96,8 @@ const jobDispatchSchema = z.object({
98
96
  maxLogSizeBytes: z.coerce.number().optional(),
99
97
  /**
100
98
  * Orchestrator-resolved concurrency-slot wait timeout (ms), from the
101
- * fleet-wide `cluster_settings.concurrency_wait_timeout_ms`. Agent falls
102
- * back to its own env/config default (1h) when absent (older orchestrators).
99
+ * fleet-wide `cluster_settings.concurrency_wait_timeout_ms`. The agent falls
100
+ * back to its own env/config default (1h) when absent.
103
101
  */
104
102
  concurrencyWaitTimeoutMs: z.coerce.number().optional(),
105
103
  /** URL or file:// path to a pre-packed `.kici/` source tarball. If present, agent extracts it into workDir instead of cloning the repo. */
@@ -129,9 +127,10 @@ const jobDispatchSchema = z.object({
129
127
  * HEAD branch where the claim is the BASE branch, and `workflowRef` here is
130
128
  * the `<name>@<sha>` claim rather than a global workflow's clone ref.
131
129
  *
132
- * Additive and optional: an older orchestrator omits it and the agent falls
133
- * back to its local guess. That fallback statement fails the capture
134
- * cross-check, so the defer is dropped rather than stored unchecked.
130
+ * Absent when the orchestrator has no provenance issuer configured, or when
131
+ * a worker dispatches a rerouted job. The agent then falls back to its local
132
+ * guess. That fallback statement fails the capture cross-check, so the
133
+ * defer is dropped rather than stored unchecked.
135
134
  */
136
135
  provenanceContext: provenanceContextSchema.optional(),
137
136
  /** Plain outputs from upstream jobs (keyed by job name, then by step name). Populated for downstream jobs with `needs` dependencies. */
@@ -142,20 +141,14 @@ const jobDispatchSchema = z.object({
142
141
  * Per-invoke-gate results for any upstream gate this job `needs`, keyed by
143
142
  * gate job name. One {@link invokeResultSchema} entry per run the gate
144
143
  * triggered, carrying the invoked run's non-secret declared outputs. Powers
145
- * a standard downstream job's `ctx.needs['<gate>'].result`. Additive and
146
- * optional — older orchestrators omit it and the agent resolves the gate
147
- * need through the fan-out group shape instead.
144
+ * a standard downstream job's `ctx.needs['<gate>'].result`. Absent when the
145
+ * job needs no invoke gate, or when a worker dispatches a rerouted job; the
146
+ * agent then resolves the gate need through the fan-out group shape.
148
147
  */
149
148
  upstreamInvokeResults: z.record(z.string(), z.array(invokeResultSchema)).optional(),
150
149
  /**
151
- * Structured clone auth for the source repo. Preferred over `token` (which
152
- * remains as a backward-compat field for same-provider GitHub App flows
153
- * during the transition to universal-git / cross-provider global workflows).
154
- *
155
- * When both `token` and `sourceAuth` are set, a Zod refinement enforces
156
- * that they agree (`sourceAuth.kind === 'basic'` and
157
- * `sourceAuth.secret === token`) — otherwise the dispatch is rejected to
158
- * prevent silent credential mismatches.
150
+ * Structured clone auth for the source repo. Absent when the job's provider
151
+ * mints no clone credential (a public or local repository).
159
152
  */
160
153
  sourceAuth: gitAuthSchema.optional(),
161
154
  /**
@@ -187,9 +180,8 @@ const jobDispatchSchema = z.object({
187
180
  * resolved by the orchestrator (the lock carries secret NAMES; the agent
188
181
  * never resolves them itself).
189
182
  *
190
- * Optional for backward compatibility with older orchestrators, which do
191
- * not send it — an agent that receives no auth pulls anonymously, exactly
192
- * as it did before.
183
+ * Absent when the job's image needs no registry credential — the agent
184
+ * then pulls anonymously.
193
185
  */
194
186
  containerRegistryAuth: z.object({
195
187
  username: z.string().min(1),
@@ -214,19 +206,6 @@ const jobDispatchSchema = z.object({
214
206
  * as `isolated` by the agent (fail-closed).
215
207
  */
216
208
  cacheRefScope: CacheRefScope.optional()
217
- }).superRefine((val, ctx) => {
218
- if (val.token && val.sourceAuth) {
219
- if (val.sourceAuth.kind !== "basic") ctx.addIssue({
220
- code: z.ZodIssueCode.custom,
221
- path: ["sourceAuth", "kind"],
222
- message: "token is set; sourceAuth.kind must be \"basic\" to agree"
223
- });
224
- else if (val.sourceAuth.secret !== val.token) ctx.addIssue({
225
- code: z.ZodIssueCode.custom,
226
- path: ["sourceAuth", "secret"],
227
- message: "token and sourceAuth.secret must match when both are set"
228
- });
229
- }
230
209
  });
231
210
  /** Cancel a running or queued job. */
232
211
  const jobCancelSchema = z.object({
@@ -268,17 +247,10 @@ const registerAckSchema = z.object({
268
247
  * reaper's back, re-creating the spawn/reap churn that reaping only surplus
269
248
  * agents exists to prevent.
270
249
  *
271
- * Absent on orchestrators that predate warm pools. An agent that does not
272
- * understand this field arms the short KICI_SCALER_IDLE_TIMEOUT timer exactly
273
- * as before — so warm pools do not work against it, which is today's
274
- * behaviour rather than a regression.
250
+ * Absent for a job-bound spawn and for a static agent.
275
251
  */
276
252
  warmPool: z.boolean().optional(),
277
- /**
278
- * Optional agent-facing capabilities this orchestrator supports (absent on
279
- * pre-capability orchestrators). The agent reads it to decide whether to
280
- * await optional acks like `artifacts.upload.complete.ack`.
281
- */
253
+ /** Agent-facing capabilities this orchestrator advertises; none are defined at protocol 4. */
282
254
  capabilities: orchAgentCapabilitiesSchema.optional()
283
255
  });
284
256
  /** Agent registration with capabilities and capacity. */
@@ -291,7 +263,7 @@ const agentRegisterSchema = z.object({
291
263
  platform: z.string().optional(),
292
264
  /** Agent architecture (os.arch(), e.g. 'x64', 'arm64') */
293
265
  arch: z.string().optional(),
294
- /** Agent version (e.g. "0.0.1"). Optional for backward compatibility with older agents. */
266
+ /** Agent version (e.g. "0.0.1"). Absent when the agent cannot read its own package version. */
295
267
  version: z.string().optional(),
296
268
  /** Maximum concurrent jobs this agent can handle. Defaults to 1 if not specified. */
297
269
  maxConcurrency: z.number().int().positive().optional(),
@@ -326,11 +298,7 @@ const agentRegisterSchema = z.object({
326
298
  z.number(),
327
299
  z.boolean()
328
300
  ])).optional(),
329
- /**
330
- * Optional agent behaviours this agent build implements (absent on
331
- * pre-capability agents, which the orchestrator treats as supporting none).
332
- * The orchestrator reads it to route work that depends on one of them.
333
- */
301
+ /** Optional agent behaviours this agent advertises; none are defined at protocol 4. */
334
302
  capabilities: agentCapabilitiesSchema.optional()
335
303
  });
336
304
  /** Periodic agent status update. */
@@ -377,8 +345,8 @@ const jobStatusSchema = z.object({
377
345
  * `LockJob` interface in `trigger/types.ts`, and a hand-written Zod copy would
378
346
  * drift and start rejecting legitimate generated jobs.
379
347
  *
380
- * Every field beyond the verdict itself is `.optional()` so an older peer
381
- * tolerates the message unchanged.
348
+ * Every field beyond the verdict itself is `.optional()`: an undecided or
349
+ * job-less verdict omits them.
382
350
  */
383
351
  const globalEvalCandidateResultSchema = z.object({
384
352
  /** The candidate workflow's name, as it appears in the lock file. */
@@ -451,11 +419,8 @@ const agentLogChunkSchema = z.object({
451
419
  stepIndex: z.number(),
452
420
  lines: z.array(z.string()),
453
421
  timestamp: z.number(),
454
- /**
455
- * Which stream these lines came from. Optional for backward compatibility
456
- * with agents that do not send it; absent is read as `stdout`.
457
- */
458
- stream: LogStream.optional()
422
+ /** Which stream these lines came from. */
423
+ stream: LogStream
459
424
  });
460
425
  /** Step-level execution state report (agent -> orchestrator). */
461
426
  const agentStepStatusSchema = z.object({
@@ -553,37 +518,37 @@ const configAckSchema = z.object({
553
518
  messageId: z.string(),
554
519
  agentId: z.string()
555
520
  });
556
- /** Agent -> Orchestrator: request a pre-signed upload URL for cache storage. */
557
- const cacheUploadRequestSchema = z.object({
521
+ /**
522
+ * Agent -> Orchestrator: request a pre-signed upload URL for cache storage.
523
+ *
524
+ * Each tarball is stored under its own content hash, so the orchestrator needs
525
+ * that hash to sign the upload URL: `sourceTarDigest` for a source upload,
526
+ * `depsHash` for a deps upload. The agent has already packed and hashed the
527
+ * tarball by the time it asks.
528
+ */
529
+ const cacheUploadRequestSchema = z.discriminatedUnion("cacheType", [z.object({
558
530
  type: z.literal("cache.upload.request"),
559
531
  messageId: z.string(),
560
532
  jobId: z.string(),
561
- cacheType: z.enum(["source", "deps"]),
533
+ cacheType: z.literal("source"),
562
534
  contentHash: z.string().optional(),
535
+ platform: z.string(),
536
+ arch: z.string(),
537
+ /** SHA-256 of the source tarball about to be uploaded. */
538
+ sourceTarDigest: z.string()
539
+ }), z.object({
540
+ type: z.literal("cache.upload.request"),
541
+ messageId: z.string(),
542
+ jobId: z.string(),
543
+ cacheType: z.literal("deps"),
563
544
  lockfileHash: z.string().optional(),
564
545
  platform: z.string(),
565
546
  arch: z.string(),
566
- /**
567
- * SHA-256 of the dependency tarball about to be uploaded. Deps uploads only.
568
- *
569
- * The dep tarball is stored under its own content hash, so the orchestrator
570
- * needs it to sign the upload URL — the agent has already built the tarball
571
- * and hashed it by the time it asks. Optional so an older agent that omits it
572
- * still gets a usable (lockfile-keyed) URL during a mixed-version rollout.
573
- */
574
- depsHash: z.string().optional(),
575
- /**
576
- * SHA-256 of the source tarball about to be uploaded. Source uploads only.
577
- *
578
- * The source tarball is stored under its own content hash, so the
579
- * orchestrator needs it to sign the upload URL — the agent has already packed
580
- * and hashed it by the time it asks. Optional so an older agent that omits it
581
- * still gets a usable URL during a mixed-version rollout.
582
- */
583
- sourceTarDigest: z.string().optional(),
547
+ /** SHA-256 of the dependency tarball about to be uploaded. */
548
+ depsHash: z.string(),
584
549
  /** In-repo `workspace:` sibling closure digest; part of the dep pointer key. */
585
550
  siblingsDigest: z.string().optional()
586
- });
551
+ })]);
587
552
  /** Orchestrator -> Agent: return the pre-signed upload URL. */
588
553
  const cacheUploadResponseSchema = z.object({
589
554
  type: z.literal("cache.upload.response"),
@@ -591,22 +556,29 @@ const cacheUploadResponseSchema = z.object({
591
556
  uploadUrl: z.string()
592
557
  });
593
558
  /** Agent -> Orchestrator: confirm upload complete (for metadata update). */
594
- const cacheUploadCompleteSchema = z.object({
559
+ const cacheUploadCompleteSchema = z.discriminatedUnion("cacheType", [z.object({
595
560
  type: z.literal("cache.upload.complete"),
596
561
  messageId: z.string(),
597
562
  jobId: z.string(),
598
- cacheType: z.enum(["source", "deps"]),
563
+ cacheType: z.literal("source"),
599
564
  contentHash: z.string().optional(),
565
+ platform: z.string(),
566
+ arch: z.string(),
567
+ /** SHA-256 of the source tarball's own bytes. */
568
+ sourceTarDigest: z.string()
569
+ }), z.object({
570
+ type: z.literal("cache.upload.complete"),
571
+ messageId: z.string(),
572
+ jobId: z.string(),
573
+ cacheType: z.literal("deps"),
600
574
  lockfileHash: z.string().optional(),
601
575
  platform: z.string(),
602
576
  arch: z.string(),
603
- /** SHA-256 hash of the dependency tarball for integrity verification. Only present for deps uploads. */
604
- depsHash: z.string().optional(),
605
- /** SHA-256 of the source tarball's own bytes. Only present for source uploads. */
606
- sourceTarDigest: z.string().optional(),
577
+ /** SHA-256 hash of the dependency tarball for integrity verification. */
578
+ depsHash: z.string(),
607
579
  /** In-repo `workspace:` sibling closure digest; part of the dep pointer key. */
608
580
  siblingsDigest: z.string().optional()
609
- });
581
+ })]);
610
582
  /** Agent -> Orchestrator: request a user-cache restore (presigned download). */
611
583
  const cacheUserRestoreRequestSchema = z.object({
612
584
  type: z.literal("cache.user.restore.request"),
@@ -765,8 +737,7 @@ const artifactsUploadResponseSchema = z.object({
765
737
  * uploads are not configured on the orchestrator, the job's run could not be
766
738
  * resolved, the job is not owned by this agent, or the orchestrator hit an
767
739
  * internal error. A safe, fixed,
768
- * human-readable string; never a raw exception. Older agents ignore the field
769
- * and fall back to a generic rejection message.
740
+ * human-readable string; never a raw exception.
770
741
  */
771
742
  error: z.string().optional()
772
743
  });
@@ -793,9 +764,7 @@ const artifactsUploadCompleteSchema = z.object({
793
764
  const ArtifactCompleteAckOutcome = z.enum(["committed", "failed"]);
794
765
  /**
795
766
  * Orchestrator -> Agent: the outcome of committing an
796
- * `artifacts.upload.complete`. Sent by orchestrators that advertise the
797
- * `artifactCompleteAck` capability on `register.ack`; the agent awaits it and
798
- * fails the workflow step on `failed`/timeout, so a lost commit surfaces as a
767
+ * `artifacts.upload.complete`. The agent awaits it and fails the workflow step on `failed`/timeout, so a lost commit surfaces as a
799
768
  * failed step instead of a green run with a missing artifact. `requestId`
800
769
  * echoes the complete message's `messageId`.
801
770
  */
@@ -841,8 +810,7 @@ const artifactsDownloadResponseSchema = z.object({
841
810
  * the job's run could not be resolved, the job is not owned by this agent, or
842
811
  * the orchestrator hit an internal error — rather than a genuinely missing
843
812
  * artifact. A safe, fixed,
844
- * human-readable string; never a raw exception. Older agents ignore the field
845
- * and render the plain not-found message.
813
+ * human-readable string; never a raw exception.
846
814
  */
847
815
  error: z.string().optional()
848
816
  });
@@ -876,8 +844,7 @@ const eventEmitResponseSchema = z.object({
876
844
  * A provisioned agent normally sends this itself to self-bootstrap — the claim
877
845
  * code is the authorization, so it may send it before it authenticates or
878
846
  * registers. A provisioning workflow can also send it to obtain the token
879
- * directly. Additive/negotiated by presence — older peers that never emit it
880
- * are unaffected, so it needs no `PROTOCOL_VERSION` bump of its own.
847
+ * directly.
881
848
  */
882
849
  const scalerClaimCredentialsSchema = z.object({
883
850
  type: z.literal("scaler.claim-credentials"),