@kici-dev/engine 0.1.26 → 0.2.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 (157) hide show
  1. package/dist/approval/types.d.ts +11 -4
  2. package/dist/approval/types.js +11 -4
  3. package/dist/artifacts/name.d.ts +60 -0
  4. package/dist/artifacts/name.js +71 -0
  5. package/dist/audit/access-log-policy.d.ts +1 -1
  6. package/dist/audit/access-log-policy.js +20 -11
  7. package/dist/audit/activity.d.ts +12 -12
  8. package/dist/audit/retention-policy.js +40 -22
  9. package/dist/billing/plan-type.d.ts +53 -0
  10. package/dist/billing/plan-type.js +70 -0
  11. package/dist/bundler/rolldown-config.d.ts +3 -3
  12. package/dist/check-mode.d.ts +1 -1
  13. package/dist/context/concurrency-strategy.d.ts +34 -0
  14. package/dist/context/concurrency-strategy.js +35 -0
  15. package/dist/context/held-run-job-id.d.ts +45 -0
  16. package/dist/context/held-run-job-id.js +56 -0
  17. package/dist/context/held-run-status.d.ts +33 -0
  18. package/dist/context/held-run-status.js +37 -0
  19. package/dist/context/hold-expiry.d.ts +20 -0
  20. package/dist/context/hold-expiry.js +25 -0
  21. package/dist/context/hold-reason.d.ts +33 -0
  22. package/dist/context/hold-reason.js +23 -0
  23. package/dist/context/hold-type.d.ts +40 -0
  24. package/dist/context/hold-type.js +61 -0
  25. package/dist/{environment → context}/host-match.js +1 -1
  26. package/dist/context/index.d.ts +14 -0
  27. package/dist/context/index.js +12 -0
  28. package/dist/context/multi-context.d.ts +30 -0
  29. package/dist/context/multi-context.js +38 -0
  30. package/dist/context/scope-name.d.ts +29 -0
  31. package/dist/context/scope-name.js +49 -0
  32. package/dist/context/scope-resolver.d.ts +79 -0
  33. package/dist/{environment → context}/scope-resolver.js +47 -17
  34. package/dist/{environment → context}/scope-template.js +1 -1
  35. package/dist/{environment → context}/types.d.ts +25 -22
  36. package/dist/{environment → context}/types.js +3 -3
  37. package/dist/dev-ops/operations.d.ts +9 -1
  38. package/dist/dev-ops/operations.js +37 -20
  39. package/dist/diagnostics/infra-alert.d.ts +71 -0
  40. package/dist/diagnostics/infra-alert.js +60 -0
  41. package/dist/env/environment-allowlist.d.ts +26 -3
  42. package/dist/env/environment-allowlist.js +35 -1
  43. package/dist/fanout/materialize.d.ts +16 -0
  44. package/dist/fanout/materialize.js +34 -5
  45. package/dist/index.d.ts +16 -7
  46. package/dist/index.js +38 -23
  47. package/dist/inputs/descriptor.d.ts +9 -9
  48. package/dist/inventory.d.ts +4 -4
  49. package/dist/labels.d.ts +82 -2
  50. package/dist/labels.js +119 -1
  51. package/dist/matrix/expand.d.ts +49 -2
  52. package/dist/matrix/expand.js +102 -13
  53. package/dist/matrix/format.d.ts +6 -1
  54. package/dist/matrix/format.js +6 -1
  55. package/dist/mcp/held-run-resolve.d.ts +7 -10
  56. package/dist/mcp/held-run-resolve.js +33 -7
  57. package/dist/metrics/catalog-policy.js +4 -4
  58. package/dist/metrics/metric-catalog.generated.d.ts +954 -734
  59. package/dist/metrics/metric-catalog.generated.js +296 -32
  60. package/dist/metrics/metric-kind-compat.d.ts +26 -0
  61. package/dist/metrics/metric-kind-compat.js +33 -0
  62. package/dist/protocol/analytics-events.d.ts +6 -6
  63. package/dist/protocol/dashboard-api-errors.d.ts +13 -0
  64. package/dist/protocol/dashboard-api-errors.js +17 -0
  65. package/dist/protocol/dashboard-write-operations.d.ts +143 -86
  66. package/dist/protocol/dashboard-write-operations.js +143 -69
  67. package/dist/protocol/messages/access-log.d.ts +438 -388
  68. package/dist/protocol/messages/access-log.js +24 -14
  69. package/dist/protocol/messages/actor.d.ts +2 -2
  70. package/dist/protocol/messages/agent-dev-ops.d.ts +4 -2
  71. package/dist/protocol/messages/agent-dev-ops.js +2 -5
  72. package/dist/protocol/messages/agent-run-result.d.ts +74 -64
  73. package/dist/protocol/messages/agent-run-result.js +1 -1
  74. package/dist/protocol/messages/auth.d.ts +35 -23
  75. package/dist/protocol/messages/browser.d.ts +81 -5
  76. package/dist/protocol/messages/browser.js +53 -2
  77. package/dist/protocol/messages/capabilities.d.ts +106 -31
  78. package/dist/protocol/messages/capabilities.js +94 -10
  79. package/dist/protocol/messages/common.d.ts +45 -2
  80. package/dist/protocol/messages/common.js +64 -3
  81. package/dist/protocol/messages/dashboard-sealed-write.d.ts +52 -0
  82. package/dist/protocol/messages/dashboard-sealed-write.js +57 -0
  83. package/dist/protocol/messages/dashboard.d.ts +1232 -706
  84. package/dist/protocol/messages/dashboard.js +387 -220
  85. package/dist/protocol/messages/deployment-identity.d.ts +37 -10
  86. package/dist/protocol/messages/deployment-identity.js +30 -3
  87. package/dist/protocol/messages/event-log.d.ts +5 -5
  88. package/dist/protocol/messages/execution-status.d.ts +198 -62
  89. package/dist/protocol/messages/execution-status.js +114 -46
  90. package/dist/protocol/messages/heartbeat-health.d.ts +83 -0
  91. package/dist/protocol/messages/heartbeat-health.js +87 -0
  92. package/dist/protocol/messages/log-stream.d.ts +18 -0
  93. package/dist/protocol/messages/log-stream.js +19 -0
  94. package/dist/protocol/messages/oidc-mint.d.ts +7 -0
  95. package/dist/protocol/messages/oidc-mint.js +7 -0
  96. package/dist/protocol/messages/orchestrator-agent.d.ts +264 -67
  97. package/dist/protocol/messages/orchestrator-agent.js +170 -5
  98. package/dist/protocol/messages/pat-kind.d.ts +1 -1
  99. package/dist/protocol/messages/peer.d.ts +122 -58
  100. package/dist/protocol/messages/peer.js +37 -2
  101. package/dist/protocol/messages/platform-orchestrator.d.ts +603 -258
  102. package/dist/protocol/messages/platform-orchestrator.js +131 -21
  103. package/dist/protocol/messages/run-events.d.ts +5 -5
  104. package/dist/protocol/messages/scaler-event.d.ts +3 -3
  105. package/dist/protocol/messages/source-registration.d.ts +56 -13
  106. package/dist/protocol/messages/source-registration.js +49 -6
  107. package/dist/protocol/session-policy.d.ts +20 -0
  108. package/dist/protocol/session-policy.js +25 -0
  109. package/dist/protocol/source-origin.d.ts +1 -1
  110. package/dist/provenance/attestation-origin.d.ts +1 -1
  111. package/dist/provenance/schema.d.ts +11 -11
  112. package/dist/provenance/verify.js +2 -1
  113. package/dist/provider/changed-files-fetcher.d.ts +21 -2
  114. package/dist/provider/check-run-conclusion.d.ts +2 -2
  115. package/dist/provider/check-status-poster.d.ts +23 -0
  116. package/dist/provider/index.d.ts +2 -2
  117. package/dist/registration/registerable-trigger-type.d.ts +14 -13
  118. package/dist/registration/registerable-trigger-type.js +1 -0
  119. package/dist/sandbox/capabilities.d.ts +6 -0
  120. package/dist/sandbox/capabilities.js +57 -0
  121. package/dist/scaler/scaler-backend-type.d.ts +1 -1
  122. package/dist/status/presentation.d.ts +89 -0
  123. package/dist/status/presentation.js +163 -0
  124. package/dist/trigger/compiled-matchers.d.ts +13 -0
  125. package/dist/trigger/compiled-matchers.js +44 -0
  126. package/dist/trigger/event-buckets.d.ts +44 -0
  127. package/dist/trigger/event-buckets.js +93 -0
  128. package/dist/trigger/matcher.d.ts +7 -3
  129. package/dist/trigger/matcher.js +53 -15
  130. package/dist/trigger/schedule-key.d.ts +14 -0
  131. package/dist/trigger/schedule-key.js +21 -0
  132. package/dist/trigger/trigger-event-type.d.ts +1 -1
  133. package/dist/trigger/trigger-event-type.js +2 -0
  134. package/dist/trigger/types.d.ts +178 -47
  135. package/dist/trigger/types.js +82 -24
  136. package/dist/webhook/event-types.d.ts +56 -0
  137. package/dist/webhook/event-types.js +59 -0
  138. package/dist/ws/ws-like.d.ts +13 -0
  139. package/package.json +26 -10
  140. package/sbom.spdx.json +10 -10
  141. package/dist/environment/index.d.ts +0 -6
  142. package/dist/environment/index.js +0 -5
  143. package/dist/environment/multi-env.d.ts +0 -30
  144. package/dist/environment/multi-env.js +0 -38
  145. package/dist/environment/scope-resolver.d.ts +0 -46
  146. package/dist/package-manager.d.ts +0 -20
  147. package/dist/protocol/messages/observe.d.ts +0 -76
  148. package/dist/protocol/messages/saas-orchestrator.d.ts +0 -2179
  149. package/dist/protocol/messages/test-run.d.ts +0 -59
  150. package/dist/state-machine/index.d.ts +0 -2
  151. package/dist/state-machine/index.js +0 -3
  152. package/dist/state-machine/machine.d.ts +0 -34
  153. package/dist/state-machine/machine.js +0 -103
  154. package/dist/state-machine/types.d.ts +0 -34
  155. package/dist/state-machine/types.js +0 -15
  156. /package/dist/{environment → context}/host-match.d.ts +0 -0
  157. /package/dist/{environment → context}/scope-template.d.ts +0 -0
package/dist/labels.d.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import { z } from 'zod';
1
2
  /**
2
3
  * Structured auto-labels with category prefixes.
3
4
  *
@@ -30,6 +31,85 @@
30
31
  * Derive kici:os: and kici:arch: labels from platform and architecture strings.
31
32
  */
32
33
  export declare function deriveOsArchLabels(platform: string, arch: string): string[];
34
+ /**
35
+ * Plain OS/arch labels that gate a bare-metal scaler as a mandatory taint.
36
+ * A pool whose declared labels include one of these only accepts jobs that
37
+ * explicitly request that platform. Linux and x64/amd64 are the defaults and
38
+ * are absent on purpose — an unqualified `runsOn: 'bare-metal'` job must still
39
+ * land on a Linux-x64 scaler.
40
+ */
41
+ export declare const PLATFORM_TAINT_LABELS: Set<string>;
42
+ /**
43
+ * Intersect a pool's declared labels with {@link PLATFORM_TAINT_LABELS},
44
+ * returning the de-duplicated plain platform-taint labels (lowercased) in
45
+ * input order.
46
+ */
47
+ export declare function derivePlatformTaints(declaredLabels: string[]): string[];
48
+ /**
49
+ * Operating systems a scaler pool can declare via the structured `platform`
50
+ * field. `linux` is the default and carries no taint; `macos` / `windows` are
51
+ * non-default and taint the pool.
52
+ */
53
+ export declare const ScalerOs: z.ZodEnum<{
54
+ linux: "linux";
55
+ macos: "macos";
56
+ windows: "windows";
57
+ }>;
58
+ export type ScalerOs = z.infer<typeof ScalerOs>;
59
+ /**
60
+ * CPU architectures a scaler pool can declare via the structured `platform`
61
+ * field. `x64` is the default and carries no taint; `arm64` taints the pool.
62
+ */
63
+ export declare const ScalerArch: z.ZodEnum<{
64
+ arm64: "arm64";
65
+ x64: "x64";
66
+ }>;
67
+ export type ScalerArch = z.infer<typeof ScalerArch>;
68
+ /**
69
+ * Structured platform of a scaler pool: the single source of truth for both the
70
+ * auto-injected `kici:os:*` / `kici:arch:*` labels and the mandatory platform
71
+ * taint. Declaring it once removes the ambiguity of matching plain string
72
+ * labels against a denylist.
73
+ */
74
+ export declare const scalerPlatformSchema: z.ZodObject<{
75
+ os: z.ZodEnum<{
76
+ linux: "linux";
77
+ macos: "macos";
78
+ windows: "windows";
79
+ }>;
80
+ arch: z.ZodEnum<{
81
+ arm64: "arm64";
82
+ x64: "x64";
83
+ }>;
84
+ }, z.core.$strict>;
85
+ export type ScalerPlatform = z.infer<typeof scalerPlatformSchema>;
86
+ /**
87
+ * Derive the `kici:os:*` / `kici:arch:*` labels for a declared structured
88
+ * platform. Reuses {@link deriveOsArchLabels} so the label shape is identical to
89
+ * the host-reported form (e.g. `windows` yields both `kici:os:windows` and
90
+ * `kici:os:win32`).
91
+ */
92
+ export declare function platformToOsArchLabels(platform: ScalerPlatform): string[];
93
+ /**
94
+ * Derive the plain platform-taint labels for a declared structured platform.
95
+ * Returns the canonical tokens (`macos`, `windows`, `arm64`) that a job's
96
+ * `runsOn` must include to allocate on the pool. The linux/x64 default carries
97
+ * no taint. Unlike {@link derivePlatformTaints} (which intersects declared
98
+ * labels against a denylist), this derives from the structured field, so a pool
99
+ * labeled `windows-2022` still taints correctly.
100
+ */
101
+ export declare function platformToTaints(platform: ScalerPlatform): string[];
102
+ /** Map an `os.platform()` string to a `ScalerOs`, or null when unrecognised. */
103
+ export declare function nodePlatformToScalerOs(nodePlatform: string): ScalerOs | null;
104
+ /** Map an `os.arch()` string to a `ScalerArch`, or null when unrecognised. */
105
+ export declare function nodeArchToScalerArch(nodeArch: string): ScalerArch | null;
106
+ /**
107
+ * Build a structured platform from the host's `os.platform()` / `os.arch()`.
108
+ * Returns null when either component is not one of the supported enum values,
109
+ * so a caller can fall back to the legacy host-label derivation for exotic
110
+ * hosts.
111
+ */
112
+ export declare function hostToScalerPlatform(nodePlatform: string, nodeArch: string): ScalerPlatform | null;
33
113
  /** Prefix for the agent self-reported hostname label. */
34
114
  export declare const HOST_LABEL_PREFIX = "kici:host:";
35
115
  /**
@@ -74,7 +154,7 @@ export declare function normalizeRunsOn(runsOn: string | string[] | {
74
154
  * - builder: can run __build__ jobs (dependency cache compilation)
75
155
  * - init-runner: can run __init__ jobs (workspace initialization)
76
156
  */
77
- export declare const KNOWN_ROLES: readonly ["builder", "init-runner"];
157
+ export declare const KNOWN_ROLES: readonly ['builder', 'init-runner'];
78
158
  /** Agent role type derived from KNOWN_ROLES. */
79
159
  export type AgentRole = (typeof KNOWN_ROLES)[number];
80
160
  /** Reserved label prefix — labels starting with this are system-managed. */
@@ -140,7 +220,7 @@ export declare function scalerAgentLabels(labelSet: string[], backendType: strin
140
220
  * platform facts, not authorization grants, so the orchestrator's register-time
141
221
  * label-scope gate does not require an ephemeral token to be bound to them.
142
222
  */
143
- export declare const SELF_REPORTED_LABEL_PREFIXES: readonly ["kici:os:", "kici:arch:", "kici:host:"];
223
+ export declare const SELF_REPORTED_LABEL_PREFIXES: readonly ['kici:os:', 'kici:arch:', 'kici:host:'];
144
224
  /**
145
225
  * True if a label is a self-reported platform fact (os/arch/host) rather than a
146
226
  * scaler-assigned, authorization-bearing label. Used by the agent register-time
package/dist/labels.js CHANGED
@@ -1,4 +1,5 @@
1
1
  import "./rolldown-runtime-ClRpJifh.js";
2
+ import { z } from "zod";
2
3
  //#region src/labels.ts
3
4
  /**
4
5
  * Structured auto-labels with category prefixes.
@@ -56,6 +57,123 @@ function deriveOsArchLabels(platform, arch) {
56
57
  }
57
58
  return labels;
58
59
  }
60
+ /**
61
+ * Plain OS/arch labels that gate a bare-metal scaler as a mandatory taint.
62
+ * A pool whose declared labels include one of these only accepts jobs that
63
+ * explicitly request that platform. Linux and x64/amd64 are the defaults and
64
+ * are absent on purpose — an unqualified `runsOn: 'bare-metal'` job must still
65
+ * land on a Linux-x64 scaler.
66
+ */
67
+ const PLATFORM_TAINT_LABELS = /* @__PURE__ */ new Set([
68
+ "windows",
69
+ "win32",
70
+ "macos",
71
+ "darwin",
72
+ "arm64",
73
+ "aarch64",
74
+ "arm"
75
+ ]);
76
+ /**
77
+ * Intersect a pool's declared labels with {@link PLATFORM_TAINT_LABELS},
78
+ * returning the de-duplicated plain platform-taint labels (lowercased) in
79
+ * input order.
80
+ */
81
+ function derivePlatformTaints(declaredLabels) {
82
+ const seen = /* @__PURE__ */ new Set();
83
+ for (const raw of declaredLabels) {
84
+ const label = raw.toLowerCase();
85
+ if (PLATFORM_TAINT_LABELS.has(label)) seen.add(label);
86
+ }
87
+ return [...seen];
88
+ }
89
+ /**
90
+ * Operating systems a scaler pool can declare via the structured `platform`
91
+ * field. `linux` is the default and carries no taint; `macos` / `windows` are
92
+ * non-default and taint the pool.
93
+ */
94
+ const ScalerOs = z.enum([
95
+ "linux",
96
+ "macos",
97
+ "windows"
98
+ ]);
99
+ /**
100
+ * CPU architectures a scaler pool can declare via the structured `platform`
101
+ * field. `x64` is the default and carries no taint; `arm64` taints the pool.
102
+ */
103
+ const ScalerArch = z.enum(["x64", "arm64"]);
104
+ /**
105
+ * Structured platform of a scaler pool: the single source of truth for both the
106
+ * auto-injected `kici:os:*` / `kici:arch:*` labels and the mandatory platform
107
+ * taint. Declaring it once removes the ambiguity of matching plain string
108
+ * labels against a denylist.
109
+ */
110
+ const scalerPlatformSchema = z.object({
111
+ os: ScalerOs,
112
+ arch: ScalerArch
113
+ }).strict();
114
+ /** Map a structured `ScalerOs` back to the `os.platform()` string it represents. */
115
+ function scalerOsToNodePlatform(os) {
116
+ switch (os) {
117
+ case "linux": return "linux";
118
+ case "macos": return "darwin";
119
+ case "windows": return "win32";
120
+ }
121
+ }
122
+ /**
123
+ * Derive the `kici:os:*` / `kici:arch:*` labels for a declared structured
124
+ * platform. Reuses {@link deriveOsArchLabels} so the label shape is identical to
125
+ * the host-reported form (e.g. `windows` yields both `kici:os:windows` and
126
+ * `kici:os:win32`).
127
+ */
128
+ function platformToOsArchLabels(platform) {
129
+ return deriveOsArchLabels(scalerOsToNodePlatform(platform.os), platform.arch);
130
+ }
131
+ /**
132
+ * Derive the plain platform-taint labels for a declared structured platform.
133
+ * Returns the canonical tokens (`macos`, `windows`, `arm64`) that a job's
134
+ * `runsOn` must include to allocate on the pool. The linux/x64 default carries
135
+ * no taint. Unlike {@link derivePlatformTaints} (which intersects declared
136
+ * labels against a denylist), this derives from the structured field, so a pool
137
+ * labeled `windows-2022` still taints correctly.
138
+ */
139
+ function platformToTaints(platform) {
140
+ const taints = [];
141
+ if (platform.os === "macos") taints.push("macos");
142
+ else if (platform.os === "windows") taints.push("windows");
143
+ if (platform.arch === "arm64") taints.push("arm64");
144
+ return taints;
145
+ }
146
+ /** Map an `os.platform()` string to a `ScalerOs`, or null when unrecognised. */
147
+ function nodePlatformToScalerOs(nodePlatform) {
148
+ switch (nodePlatform) {
149
+ case "linux": return "linux";
150
+ case "darwin": return "macos";
151
+ case "win32": return "windows";
152
+ default: return null;
153
+ }
154
+ }
155
+ /** Map an `os.arch()` string to a `ScalerArch`, or null when unrecognised. */
156
+ function nodeArchToScalerArch(nodeArch) {
157
+ switch (nodeArch) {
158
+ case "x64": return "x64";
159
+ case "arm64": return "arm64";
160
+ default: return null;
161
+ }
162
+ }
163
+ /**
164
+ * Build a structured platform from the host's `os.platform()` / `os.arch()`.
165
+ * Returns null when either component is not one of the supported enum values,
166
+ * so a caller can fall back to the legacy host-label derivation for exotic
167
+ * hosts.
168
+ */
169
+ function hostToScalerPlatform(nodePlatform, nodeArch) {
170
+ const os = nodePlatformToScalerOs(nodePlatform);
171
+ const arch = nodeArchToScalerArch(nodeArch);
172
+ return os && arch ? {
173
+ os,
174
+ arch
175
+ } : null;
176
+ }
59
177
  /** Prefix for the agent self-reported hostname label. */
60
178
  const HOST_LABEL_PREFIX = "kici:host:";
61
179
  /**
@@ -234,6 +352,6 @@ function separateLabels(labels) {
234
352
  };
235
353
  }
236
354
  //#endregion
237
- export { CAPABILITY_LABEL_PREFIX, HOST_LABEL_PREFIX, INIT_LABEL, KNOWN_ROLES, PRIVILEGED_ROOT_LABEL, RESERVED_LABEL_PREFIX, ROLE_LABEL_PREFIX, SELF_REPORTED_LABEL_PREFIXES, SSH_TRANSPORT_CAPABILITY, agentTypeLabel, capabilityLabel, deriveOsArchLabels, hostLabel, isAutoLabel, isSelfReportedLabel, mergeAutoLabels, normalizeRunsOn, parseHostLabel, resolveRoleLabels, roleToLabel, scalerAgentLabels, scalerLabel, separateLabels, validateNoReservedLabels };
355
+ export { CAPABILITY_LABEL_PREFIX, HOST_LABEL_PREFIX, INIT_LABEL, KNOWN_ROLES, PLATFORM_TAINT_LABELS, PRIVILEGED_ROOT_LABEL, RESERVED_LABEL_PREFIX, ROLE_LABEL_PREFIX, SELF_REPORTED_LABEL_PREFIXES, SSH_TRANSPORT_CAPABILITY, ScalerArch, ScalerOs, agentTypeLabel, capabilityLabel, deriveOsArchLabels, derivePlatformTaints, hostLabel, hostToScalerPlatform, isAutoLabel, isSelfReportedLabel, mergeAutoLabels, nodeArchToScalerArch, nodePlatformToScalerOs, normalizeRunsOn, parseHostLabel, platformToOsArchLabels, platformToTaints, resolveRoleLabels, roleToLabel, scalerAgentLabels, scalerLabel, scalerPlatformSchema, separateLabels, validateNoReservedLabels };
238
356
 
239
357
  //# sourceMappingURL=labels.js.map
@@ -17,6 +17,31 @@ export interface MatrixValues {
17
17
  /** Multi-dimensional: named properties */
18
18
  [dimension: string]: string | undefined;
19
19
  }
20
+ /**
21
+ * Thrown when a matrix value does not match the documented contract — a
22
+ * `string[]` or a `Record<string, string[]>`. A static matrix is guaranteed by
23
+ * the lock-file schema, but a dynamic matrix returns arbitrary runtime data, so
24
+ * the contract has to be enforced here rather than by the type system.
25
+ */
26
+ export declare class MatrixShapeError extends Error {
27
+ readonly name = "MatrixShapeError";
28
+ constructor(message: string);
29
+ }
30
+ /** A validated matrix input: dimensions sorted, elements coerced to strings. */
31
+ export type NormalizedMatrix = {
32
+ kind: 'array';
33
+ values: string[];
34
+ } | {
35
+ kind: 'object';
36
+ dimensions: Array<[name: string, values: string[]]>;
37
+ };
38
+ /**
39
+ * Validate and normalize a matrix value. Accepts the two documented shapes,
40
+ * coercing numeric and boolean elements to strings (they already reach job
41
+ * names as strings), and rejects everything else with the contract in the
42
+ * message. Dimensions are sorted here so expansion stays deterministic.
43
+ */
44
+ export declare function normalizeMatrixInput(input: unknown): NormalizedMatrix;
20
45
  /**
21
46
  * Compute the cartesian product of the given value sets in row-major order.
22
47
  * An empty set list yields a single empty tuple; any empty set yields no tuples.
@@ -34,9 +59,31 @@ export declare function expandSingleDimension(matrix: StaticMatrixArray): Matrix
34
59
  */
35
60
  export declare function expandMultiDimension(matrix: StaticMatrixObject): MatrixValues[];
36
61
  /**
37
- * Unified expand function that dispatches to single or multi-dimensional expansion.
62
+ * Validated entry point: normalizes an untrusted matrix value, then dispatches
63
+ * to single- or multi-dimensional expansion. {@link expandSingleDimension} and
64
+ * {@link expandMultiDimension} remain available for a caller that already holds
65
+ * a typed value; this is the one to use for anything crossing a runtime
66
+ * boundary, such as the return value of a dynamic matrix function.
67
+ */
68
+ export declare function expandMatrix(input: unknown): MatrixValues[];
69
+ /**
70
+ * How many combinations a matrix would expand to, computed WITHOUT building
71
+ * them. Callers use this to refuse an oversized matrix before allocating it —
72
+ * the product is checked, never materialized.
73
+ */
74
+ export declare function matrixCombinationCount(input: unknown): number;
75
+ /**
76
+ * The first combination whose key collides with an earlier one, or `null` when
77
+ * every combination is distinct.
78
+ *
79
+ * `keyOf` decides what "the same combination" means. Callers that own a job name
80
+ * pass a renderer for the expanded name, because the collision that actually
81
+ * hurts is two children sharing a name — they are indistinguishable to an
82
+ * operator and ambiguous as a needs-edge target. Two structurally different
83
+ * combinations can still render the same name, so name-keying is strictly
84
+ * stronger than the structural default.
38
85
  */
39
- export declare function expandMatrix(matrix: StaticMatrixArray | StaticMatrixObject): MatrixValues[];
86
+ export declare function findDuplicateCombination(combos: readonly MatrixValues[], keyOf?: (combo: MatrixValues) => string): MatrixValues | null;
40
87
  /**
41
88
  * Apply include/exclude modifications to expanded matrix combinations.
42
89
  * Exclude first (remove matching), then include (add new).
@@ -1,10 +1,65 @@
1
1
  import "../rolldown-runtime-ClRpJifh.js";
2
2
  //#region src/matrix/expand.ts
3
3
  /**
4
+ * Thrown when a matrix value does not match the documented contract — a
5
+ * `string[]` or a `Record<string, string[]>`. A static matrix is guaranteed by
6
+ * the lock-file schema, but a dynamic matrix returns arbitrary runtime data, so
7
+ * the contract has to be enforced here rather than by the type system.
8
+ */
9
+ var MatrixShapeError = class MatrixShapeError extends Error {
10
+ name = "MatrixShapeError";
11
+ constructor(message) {
12
+ super(message);
13
+ Object.setPrototypeOf(this, MatrixShapeError.prototype);
14
+ }
15
+ };
16
+ /** Describe a rejected value for an error message, without dumping it wholesale. */
17
+ function describeValue(value) {
18
+ if (value === null) return "null";
19
+ if (value === void 0) return "undefined";
20
+ if (Array.isArray(value)) return "an array";
21
+ if (typeof value === "string") return `a string (${JSON.stringify(value)})`;
22
+ if (typeof value === "object") return "an object";
23
+ return `a ${typeof value}`;
24
+ }
25
+ /** Coerce one matrix element, rejecting anything that has no sensible string form. */
26
+ function coerceElement(value, where) {
27
+ if (typeof value === "string") return value;
28
+ if (typeof value === "number" || typeof value === "boolean") return String(value);
29
+ throw new MatrixShapeError(`matrix ${where} must contain strings, got ${describeValue(value)}`);
30
+ }
31
+ /**
32
+ * Validate and normalize a matrix value. Accepts the two documented shapes,
33
+ * coercing numeric and boolean elements to strings (they already reach job
34
+ * names as strings), and rejects everything else with the contract in the
35
+ * message. Dimensions are sorted here so expansion stays deterministic.
36
+ */
37
+ function normalizeMatrixInput(input) {
38
+ if (Array.isArray(input)) return {
39
+ kind: "array",
40
+ values: Array.from(input, (v, i) => coerceElement(v, `values[${i}]`))
41
+ };
42
+ if (input === null || typeof input !== "object") {
43
+ const suffix = typeof input === "string" ? " — a bare string is read as one dimension per character; split it into an array" : "";
44
+ throw new MatrixShapeError(`matrix must be a string array or an object of string arrays, got ${describeValue(input)}${suffix}`);
45
+ }
46
+ const dimensions = [];
47
+ for (const [name, values] of Object.entries(input)) {
48
+ if (!Array.isArray(values)) throw new MatrixShapeError(`matrix dimension "${name}" must be an array, got ${describeValue(values)}`);
49
+ dimensions.push([name, Array.from(values, (v, i) => coerceElement(v, `dimension "${name}"[${i}]`))]);
50
+ }
51
+ dimensions.sort((a, b) => a[0].localeCompare(b[0]));
52
+ return {
53
+ kind: "object",
54
+ dimensions
55
+ };
56
+ }
57
+ /**
4
58
  * Compute the cartesian product of the given value sets in row-major order.
5
59
  * An empty set list yields a single empty tuple; any empty set yields no tuples.
6
60
  */
7
61
  function cartesianProduct(sets) {
62
+ if (sets.some((set) => set.length === 0)) return [];
8
63
  return sets.reduce((acc, set) => acc.flatMap((tuple) => set.map((value) => [...tuple, value])), [[]]);
9
64
  }
10
65
  /**
@@ -24,20 +79,54 @@ function expandMultiDimension(matrix) {
24
79
  if (dimensions.length === 0) return [];
25
80
  dimensions.sort((a, b) => a[0].localeCompare(b[0]));
26
81
  const names = dimensions.map(([name]) => name);
27
- return cartesianProduct(dimensions.map(([, values]) => values)).map((combo) => {
28
- const result = {};
29
- names.forEach((name, idx) => {
30
- result[name] = combo[idx];
31
- });
32
- return result;
33
- });
82
+ return cartesianProduct(dimensions.map(([, values]) => values)).map((combo) => Object.fromEntries(names.map((name, idx) => [name, combo[idx]])));
83
+ }
84
+ /**
85
+ * Validated entry point: normalizes an untrusted matrix value, then dispatches
86
+ * to single- or multi-dimensional expansion. {@link expandSingleDimension} and
87
+ * {@link expandMultiDimension} remain available for a caller that already holds
88
+ * a typed value; this is the one to use for anything crossing a runtime
89
+ * boundary, such as the return value of a dynamic matrix function.
90
+ */
91
+ function expandMatrix(input) {
92
+ const normalized = normalizeMatrixInput(input);
93
+ if (normalized.kind === "array") return expandSingleDimension(normalized.values);
94
+ return expandMultiDimension(Object.fromEntries(normalized.dimensions));
34
95
  }
35
96
  /**
36
- * Unified expand function that dispatches to single or multi-dimensional expansion.
97
+ * How many combinations a matrix would expand to, computed WITHOUT building
98
+ * them. Callers use this to refuse an oversized matrix before allocating it —
99
+ * the product is checked, never materialized.
37
100
  */
38
- function expandMatrix(matrix) {
39
- if (Array.isArray(matrix)) return expandSingleDimension(matrix);
40
- return expandMultiDimension(matrix);
101
+ function matrixCombinationCount(input) {
102
+ const normalized = normalizeMatrixInput(input);
103
+ if (normalized.kind === "array") return normalized.values.length;
104
+ if (normalized.dimensions.length === 0) return 0;
105
+ return normalized.dimensions.reduce((acc, [, values]) => acc * values.length, 1);
106
+ }
107
+ /** Stable identity for a combination: its key/value pairs, key-sorted. */
108
+ function combinationKey(combo) {
109
+ return JSON.stringify(Object.entries(combo).filter(([, value]) => value !== void 0).sort((a, b) => a[0].localeCompare(b[0])));
110
+ }
111
+ /**
112
+ * The first combination whose key collides with an earlier one, or `null` when
113
+ * every combination is distinct.
114
+ *
115
+ * `keyOf` decides what "the same combination" means. Callers that own a job name
116
+ * pass a renderer for the expanded name, because the collision that actually
117
+ * hurts is two children sharing a name — they are indistinguishable to an
118
+ * operator and ambiguous as a needs-edge target. Two structurally different
119
+ * combinations can still render the same name, so name-keying is strictly
120
+ * stronger than the structural default.
121
+ */
122
+ function findDuplicateCombination(combos, keyOf = combinationKey) {
123
+ const seen = /* @__PURE__ */ new Set();
124
+ for (const combo of combos) {
125
+ const key = keyOf(combo);
126
+ if (seen.has(key)) return combo;
127
+ seen.add(key);
128
+ }
129
+ return null;
41
130
  }
42
131
  /**
43
132
  * Apply include/exclude modifications to expanded matrix combinations.
@@ -62,11 +151,11 @@ function applyIncludeExclude(expanded, include, exclude) {
62
151
  const comboKeys = Object.keys(combo);
63
152
  if (inclKeys.length !== comboKeys.length) return false;
64
153
  return inclKeys.every((key) => combo[key] === incl[key]);
65
- })) result.push(incl);
154
+ })) result.push(Object.fromEntries([...inclKeys].sort((a, b) => a.localeCompare(b)).map((key) => [key, incl[key]])));
66
155
  }
67
156
  return result;
68
157
  }
69
158
  //#endregion
70
- export { applyIncludeExclude, cartesianProduct, expandMatrix, expandMultiDimension, expandSingleDimension };
159
+ export { MatrixShapeError, applyIncludeExclude, cartesianProduct, expandMatrix, expandMultiDimension, expandSingleDimension, findDuplicateCombination, matrixCombinationCount, normalizeMatrixInput };
71
160
 
72
161
  //# sourceMappingURL=expand.js.map
@@ -5,6 +5,11 @@ import type { MatrixValues } from './expand.js';
5
5
  * Multi-dimensional: "linux, 18"
6
6
  */
7
7
  export declare function formatMatrixSuffix(matrixValues: MatrixValues): string;
8
- /** Expanded child job name: `${baseName} (${suffix})`. MUST match the local executor. */
8
+ /**
9
+ * Expanded child job name: `${baseName} (${suffix})`. The `(...)` wrapper is
10
+ * load-bearing, not decoration: `variantLabelOf` (fanout/materialize.ts) and
11
+ * `buildMatrixOutputsEnvelope` (the orchestrator's `byMatrix` key) both recover
12
+ * the suffix by slicing it back out of the name.
13
+ */
9
14
  export declare function formatExpandedJobName(baseName: string, matrixValues: MatrixValues): string;
10
15
  //# sourceMappingURL=format.d.ts.map
@@ -10,7 +10,12 @@ function formatMatrixSuffix(matrixValues) {
10
10
  if (defined.length === 1 && defined[0][0] === "value") return defined[0][1];
11
11
  return defined.map(([, v]) => v).join(", ");
12
12
  }
13
- /** Expanded child job name: `${baseName} (${suffix})`. MUST match the local executor. */
13
+ /**
14
+ * Expanded child job name: `${baseName} (${suffix})`. The `(...)` wrapper is
15
+ * load-bearing, not decoration: `variantLabelOf` (fanout/materialize.ts) and
16
+ * `buildMatrixOutputsEnvelope` (the orchestrator's `byMatrix` key) both recover
17
+ * the suffix by slicing it back out of the name.
18
+ */
14
19
  function formatExpandedJobName(baseName, matrixValues) {
15
20
  return `${baseName} (${formatMatrixSuffix(matrixValues)})`;
16
21
  }
@@ -1,13 +1,3 @@
1
- /**
2
- * Shared held-run resolution for the `kici approve` / `kici reject` commands and
3
- * the developer MCP `approve_run` / `reject_run` tools.
4
- *
5
- * Both surfaces first list the pending holds for a run, then resolve the one
6
- * the caller named via `job` / `step` (or the sole pending hold when there is
7
- * exactly one and no filter is given). The resolution is a pure function so it
8
- * can be unit-tested without HTTP, and it stays import-free so it is safe to
9
- * re-export from the browser-facing engine barrel.
10
- */
11
1
  /** Hold scope, mirroring the engine `HoldScope` enum. */
12
2
  export type HeldRunScope = 'workflow' | 'job' | 'step';
13
3
  /** A pending-hold row as returned by the held-runs list. */
@@ -18,6 +8,13 @@ export interface HeldRunSummary {
18
8
  holdScope?: HeldRunScope;
19
9
  stepIndex?: number | null;
20
10
  status: string;
11
+ /**
12
+ * Persisted `held_runs.hold_type`, when the orchestrator's list response
13
+ * carried one. Optional and un-normalized: callers pass it through
14
+ * `normalizePersistedHoldType` before branching. Absent from an older
15
+ * orchestrator's response.
16
+ */
17
+ holdType?: string;
21
18
  /** Computed drift payload for a `when: 'drift'` step hold; absent otherwise. */
22
19
  payload?: {
23
20
  summaryMarkdown: string;
@@ -1,6 +1,32 @@
1
1
  import "../rolldown-runtime-ClRpJifh.js";
2
+ import { HeldRunStatus } from "../context/held-run-status.js";
2
3
  //#region src/mcp/held-run-resolve.ts
3
4
  /**
5
+ * Shared held-run resolution for the `kici approve` / `kici reject` commands and
6
+ * the developer MCP `approve_run` / `reject_run` tools.
7
+ *
8
+ * Both surfaces first list the pending holds for a run, then resolve the one
9
+ * the caller named via `job` / `step` (or the sole pending hold when there is
10
+ * exactly one and no filter is given). The resolution is a pure function so it
11
+ * can be unit-tested without HTTP, and it imports nothing beyond the shared
12
+ * held-run vocabulary, so it is safe to re-export from the browser-facing
13
+ * engine barrel.
14
+ */
15
+ /**
16
+ * Name a hold the way the caller would type it: the literal `jobId` (so an
17
+ * `__install__…` sentinel or an opaque legacy id is reproduced verbatim), with
18
+ * the step index prefixed for a step-scoped hold.
19
+ */
20
+ function describeHold(hold) {
21
+ const job = hold.jobId || "(unnamed hold)";
22
+ if (hold.holdScope === "step" && hold.stepIndex != null) return `step ${hold.stepIndex} of ${job}`;
23
+ return job;
24
+ }
25
+ /** The distinct hold descriptions, in listing order, for an error message. */
26
+ function listCandidates(holds) {
27
+ return [...new Set(holds.map(describeHold))].join(", ");
28
+ }
29
+ /**
4
30
  * Resolve the held-run id matching the filter from a list of pending holds.
5
31
  *
6
32
  * - `step` requires `job` and matches a `step`-scoped hold whose step index
@@ -9,7 +35,7 @@ import "../rolldown-runtime-ClRpJifh.js";
9
35
  * - With no filter, the sole pending hold is used; ambiguity is an error.
10
36
  */
11
37
  function resolveHeldRunId(holds, filter) {
12
- const pending = holds.filter((h) => h.status === "pending");
38
+ const pending = holds.filter((h) => h.status === HeldRunStatus.enum.pending);
13
39
  if (pending.length === 0) return {
14
40
  ok: false,
15
41
  error: "No pending approval holds found for this run."
@@ -19,12 +45,12 @@ function resolveHeldRunId(holds, filter) {
19
45
  ok: false,
20
46
  error: "--step requires --job to identify the held step."
21
47
  };
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}'`);
48
+ return pickSingle(pending.filter((h) => h.holdScope === "step" && h.jobId === filter.job && String(h.stepIndex ?? "") === filter.step), `step ${filter.step} of job '${filter.job}'`, pending);
23
49
  }
24
- if (filter.job !== void 0) return pickSingle(pending.filter((h) => h.jobId === filter.job && h.holdScope !== "step"), `job '${filter.job}'`);
50
+ if (filter.job !== void 0) return pickSingle(pending.filter((h) => h.jobId === filter.job && h.holdScope !== "step"), `job '${filter.job}'`, pending);
25
51
  if (pending.length > 1) return {
26
52
  ok: false,
27
- error: "Multiple pending holds for this run. Use --job <name> (and --step <index>) to choose one."
53
+ error: `Multiple pending holds for this run. Use --job <name> (and --step <index>) to choose one. Candidates: ${listCandidates(pending)}.`
28
54
  };
29
55
  return {
30
56
  ok: true,
@@ -32,14 +58,14 @@ function resolveHeldRunId(holds, filter) {
32
58
  hold: pending[0]
33
59
  };
34
60
  }
35
- function pickSingle(matches, label) {
61
+ function pickSingle(matches, label, pending) {
36
62
  if (matches.length === 0) return {
37
63
  ok: false,
38
- error: `No pending hold found for ${label}.`
64
+ error: `No pending hold found for ${label}. Pending holds: ${listCandidates(pending)}.`
39
65
  };
40
66
  if (matches.length > 1) return {
41
67
  ok: false,
42
- error: `Multiple pending holds match ${label}; cannot disambiguate.`
68
+ error: `Multiple pending holds match ${label}; cannot disambiguate. Candidates: ${listCandidates(matches)}.`
43
69
  };
44
70
  return {
45
71
  ok: true,
@@ -259,10 +259,6 @@ const METRIC_LABEL_POLICY = {
259
259
  "v8js.gc.type": { maxUniqueValues: 6 },
260
260
  scaler: { values: AGENT_SCALER_VALUES }
261
261
  },
262
- "v8js.memory.heap.limit": {
263
- "v8js.heap.space.name": { maxUniqueValues: 20 },
264
- scaler: { values: AGENT_SCALER_VALUES }
265
- },
266
262
  "v8js.memory.heap.used": {
267
263
  "v8js.heap.space.name": { maxUniqueValues: 20 },
268
264
  scaler: { values: AGENT_SCALER_VALUES }
@@ -274,6 +270,10 @@ const METRIC_LABEL_POLICY = {
274
270
  "v8js.memory.heap.space.physical_size": {
275
271
  "v8js.heap.space.name": { maxUniqueValues: 20 },
276
272
  scaler: { values: AGENT_SCALER_VALUES }
273
+ },
274
+ "v8js.resource.active": {
275
+ "v8js.resource.type": { maxUniqueValues: 20 },
276
+ scaler: { values: AGENT_SCALER_VALUES }
277
277
  }
278
278
  };
279
279
  //#endregion