@xemahq/dsl 0.8.1 → 0.8.3

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 (80) hide show
  1. package/dist/payload-codec/index.d.ts.map +1 -1
  2. package/dist/payload-codec/index.js.map +1 -1
  3. package/dist/payload-codec/lib/codec.d.ts.map +1 -1
  4. package/dist/payload-codec/lib/codec.js +2 -1
  5. package/dist/payload-codec/lib/codec.js.map +1 -1
  6. package/dist/payload-codec/lib/payload.d.ts.map +1 -1
  7. package/dist/schema/action.schema.json +205 -39
  8. package/dist/schema/workflow.schema.json +335 -88
  9. package/dist/workflow/index.d.ts.map +1 -1
  10. package/dist/workflow/index.js.map +1 -1
  11. package/dist/workflow/lib/compiler/compile.js +1 -1
  12. package/dist/workflow/lib/compiler/compile.js.map +1 -1
  13. package/package.json +2 -18
  14. package/schema/action.schema.json +205 -39
  15. package/schema/workflow.schema.json +335 -88
  16. package/dist/payload-codec/temporal/index.d.ts +0 -5
  17. package/dist/payload-codec/temporal/index.d.ts.map +0 -1
  18. package/dist/payload-codec/temporal/index.js +0 -7
  19. package/dist/payload-codec/temporal/index.js.map +0 -1
  20. package/src/deliverable-spec/index.ts +0 -19
  21. package/src/deliverable-spec/lib/schema.ts +0 -270
  22. package/src/deliverable-spec/lib/types.ts +0 -26
  23. package/src/payload-codec/index.ts +0 -44
  24. package/src/payload-codec/lib/blob-store.ts +0 -176
  25. package/src/payload-codec/lib/codec-context.ts +0 -38
  26. package/src/payload-codec/lib/codec.ts +0 -605
  27. package/src/payload-codec/lib/enums.ts +0 -58
  28. package/src/payload-codec/lib/errors.ts +0 -54
  29. package/src/payload-codec/lib/http-blob-store.ts +0 -267
  30. package/src/payload-codec/lib/lru-cache.ts +0 -81
  31. package/src/payload-codec/lib/payload.ts +0 -26
  32. package/src/payload-codec/temporal/index.ts +0 -36
  33. package/src/workflow/index.ts +0 -108
  34. package/src/workflow/lib/action-input-validator.ts +0 -160
  35. package/src/workflow/lib/compiler/action-shape.ts +0 -71
  36. package/src/workflow/lib/compiler/canonical-json.ts +0 -66
  37. package/src/workflow/lib/compiler/compile.ts +0 -1742
  38. package/src/workflow/lib/compiler/concurrency.ts +0 -223
  39. package/src/workflow/lib/compiler/dag.ts +0 -108
  40. package/src/workflow/lib/compiler/gate-defaults.ts +0 -153
  41. package/src/workflow/lib/compiler/index.ts +0 -11
  42. package/src/workflow/lib/compiler/inputs.ts +0 -254
  43. package/src/workflow/lib/compiler/installation-resource-validator.ts +0 -114
  44. package/src/workflow/lib/compiler/manifest-source.ts +0 -71
  45. package/src/workflow/lib/compiler/matrix.ts +0 -135
  46. package/src/workflow/lib/compiler/mount-plan.ts +0 -190
  47. package/src/workflow/lib/compiler/payload-reach-in.ts +0 -497
  48. package/src/workflow/lib/compiler/permissions.ts +0 -64
  49. package/src/workflow/lib/compiler/retry-timeout.ts +0 -105
  50. package/src/workflow/lib/compiler/review-step.ts +0 -548
  51. package/src/workflow/lib/compiler/types.ts +0 -172
  52. package/src/workflow/lib/compiler/variable-requirements.ts +0 -208
  53. package/src/workflow/lib/deliverable-spec-introspection-error.ts +0 -63
  54. package/src/workflow/lib/deliverable-spec-keys.ts +0 -147
  55. package/src/workflow/lib/deliverable-spec-source-scan.ts +0 -280
  56. package/src/workflow/lib/dispatch-inputs/index.ts +0 -160
  57. package/src/workflow/lib/dispatch-inputs/to-json-schema.ts +0 -60
  58. package/src/workflow/lib/duration.ts +0 -43
  59. package/src/workflow/lib/errors.ts +0 -37
  60. package/src/workflow/lib/expression/ast.ts +0 -108
  61. package/src/workflow/lib/expression/context.ts +0 -148
  62. package/src/workflow/lib/expression/evaluator.ts +0 -492
  63. package/src/workflow/lib/expression/index.ts +0 -28
  64. package/src/workflow/lib/expression/interpolation.ts +0 -84
  65. package/src/workflow/lib/expression/parser.ts +0 -264
  66. package/src/workflow/lib/expression/template.ts +0 -117
  67. package/src/workflow/lib/expression/tokenizer.ts +0 -200
  68. package/src/workflow/lib/expression/tokens.ts +0 -30
  69. package/src/workflow/lib/expression/walk-artifact-refs.ts +0 -232
  70. package/src/workflow/lib/installation-resource-kind.ts +0 -107
  71. package/src/workflow/lib/schemas-loader.ts +0 -64
  72. package/src/workflow/lib/serializer.ts +0 -30
  73. package/src/workflow/lib/types.ts +0 -417
  74. package/src/workflow/lib/validate.ts +0 -199
  75. package/src/workspace-manifest/index.ts +0 -27
  76. package/src/workspace-manifest/lib/compile.ts +0 -619
  77. package/src/workspace-manifest/lib/interpolate.ts +0 -166
  78. package/src/workspace-manifest/lib/resolve-extends.ts +0 -260
  79. package/src/workspace-manifest/lib/schema.ts +0 -692
  80. package/src/workspace-manifest/lib/types.ts +0 -446
@@ -1,223 +0,0 @@
1
- import {
2
- WorkflowErrorCode,
3
- WorkflowTriggerKind,
4
- type ConcurrencyGroup,
5
- type TriggerPayload,
6
- } from '@xemahq/kernel-contracts/workflow';
7
- import { WorkflowDslError } from '../errors';
8
- import type { WorkflowConcurrencyDeclaration } from '../types';
9
- import {
10
- EMPTY_CONTEXT_SEEDS,
11
- XemaActorKind,
12
- compileExpression,
13
- evaluateExpression,
14
- parseTemplate,
15
- TemplateSegmentKind,
16
- type ExpressionContext,
17
- type ExpressionNode,
18
- type TemplateSegment,
19
- } from '../expression';
20
-
21
- /**
22
- * Deterministically expand the authored concurrency `group` template into a
23
- * concrete lease key. Two passes:
24
- *
25
- * 1. **Compile time** (`compileConcurrencyGroupTemplate`): tokenize and
26
- * pre-compile every embedded expression. Authoring errors fire here so
27
- * they block snapshot creation, not dispatch.
28
- * 2. **Dispatch time** (`expandCompiledConcurrencyTemplate`): evaluate each
29
- * pre-compiled expression against the trigger / inputs / vars context
30
- * and stitch the literal + evaluated segments back together.
31
- *
32
- * Concurrency `group` is the one DSL field that opts in to partial
33
- * interpolation (`product-development:${{ inputs.projectId }}`). Every
34
- * other authored expression site enforces the "fully wrapped or pure
35
- * literal" policy through `extractInterpolations` — see `compile.ts`.
36
- */
37
-
38
- interface CompiledTemplateExpressionSegment {
39
- readonly kind: TemplateSegmentKind.Expression;
40
- readonly source: string;
41
- readonly node: ExpressionNode;
42
- }
43
-
44
- interface CompiledTemplateLiteralSegment {
45
- readonly kind: TemplateSegmentKind.Literal;
46
- readonly value: string;
47
- }
48
-
49
- type CompiledTemplateSegment =
50
- | CompiledTemplateExpressionSegment
51
- | CompiledTemplateLiteralSegment;
52
-
53
- /**
54
- * Tokenize and pre-compile every interpolation in the authored template.
55
- * Pure function: same input always yields the same compiled segments.
56
- */
57
- function compileConcurrencyGroupTemplate(
58
- authored: string,
59
- ): readonly CompiledTemplateSegment[] {
60
- const segments = parseTemplate(authored, ['concurrency', 'group']);
61
- return segments.map((segment) => compileSegment(segment));
62
- }
63
-
64
- function compileSegment(segment: TemplateSegment): CompiledTemplateSegment {
65
- if (segment.kind === TemplateSegmentKind.Literal) {
66
- return { kind: TemplateSegmentKind.Literal, value: segment.value };
67
- }
68
- return {
69
- kind: TemplateSegmentKind.Expression,
70
- source: segment.source,
71
- node: compileExpression(segment.source),
72
- };
73
- }
74
-
75
- function expandCompiledConcurrencyTemplate(
76
- authored: string,
77
- segments: readonly CompiledTemplateSegment[],
78
- ctx: ExpressionContext,
79
- ): string {
80
- const out: string[] = [];
81
- for (const segment of segments) {
82
- if (segment.kind === TemplateSegmentKind.Literal) {
83
- out.push(segment.value);
84
- continue;
85
- }
86
- const value = evaluateExpression(segment.node, ctx);
87
- out.push(stringifyConcurrencyValue(authored, segment.source, value));
88
- }
89
- return out.join('');
90
- }
91
-
92
- function stringifyConcurrencyValue(
93
- authored: string,
94
- expressionSource: string,
95
- value: unknown,
96
- ): string {
97
- if (value === null || value === undefined) {
98
- throw new WorkflowDslError(
99
- WorkflowErrorCode.DSL_SEMANTIC_INVALID,
100
- `Concurrency group expression '${expressionSource}' resolved to ${value === null ? 'null' : 'undefined'} — refuse to build an ambiguous lease key.`,
101
- { authored, expression: expressionSource },
102
- );
103
- }
104
- if (
105
- typeof value !== 'string' &&
106
- typeof value !== 'number' &&
107
- typeof value !== 'boolean'
108
- ) {
109
- throw new WorkflowDslError(
110
- WorkflowErrorCode.DSL_SEMANTIC_INVALID,
111
- `Concurrency group expression '${expressionSource}' must resolve to string/number/boolean; got ${typeof value}.`,
112
- { authored, expression: expressionSource, resultKind: typeof value },
113
- );
114
- }
115
- return String(value);
116
- }
117
-
118
- function buildConcurrencyContext(
119
- trigger: TriggerPayload,
120
- inputs: Readonly<Record<string, unknown>>,
121
- vars: Readonly<Record<string, unknown>>,
122
- ): ExpressionContext {
123
- // Concurrency runs before any job: no `needs`, no matrix, no `job`.
124
- // `xema.*` is seeded with the run-level identity available at this
125
- // point (org/project/correlation/actor) so authors may key concurrency
126
- // groups off `xema.org.id` or `xema.project.id` without reaching into
127
- // trigger metadata.
128
- return {
129
- needs: EMPTY_CONTEXT_SEEDS.needs,
130
- matrix: EMPTY_CONTEXT_SEEDS.matrix,
131
- inputs,
132
- vars,
133
- secrets: EMPTY_CONTEXT_SEEDS.secrets,
134
- trigger,
135
- job: EMPTY_CONTEXT_SEEDS.job,
136
- payloadCache: EMPTY_CONTEXT_SEEDS.payloadCache,
137
- xema: {
138
- org: { id: trigger.orgId },
139
- project: { id: trigger.projectId },
140
- run: {
141
- id: '',
142
- attempt: 0,
143
- startedAtIso: trigger.triggeredAt,
144
- correlationId: trigger.correlationId,
145
- actor: {
146
- subject: trigger.actorSubject,
147
- kind: actorKindFromTrigger(trigger),
148
- },
149
- },
150
- workflow: { key: '', revisionNumber: 0 },
151
- job: { key: '', attempt: 0 },
152
- },
153
- };
154
- }
155
-
156
- function actorKindFromTrigger(trigger: TriggerPayload): XemaActorKind {
157
- if (trigger.actorSubject) return XemaActorKind.User;
158
- switch (trigger.kind) {
159
- case WorkflowTriggerKind.WEBHOOK:
160
- return XemaActorKind.Webhook;
161
- case WorkflowTriggerKind.SCHEDULE:
162
- return XemaActorKind.Schedule;
163
- default:
164
- return XemaActorKind.System;
165
- }
166
- }
167
-
168
- /**
169
- * Compile + expand the authored concurrency declaration into the runtime
170
- * `ConcurrencyGroup`. Returns `null` when the workflow declares no
171
- * concurrency at all.
172
- *
173
- * Compile-time errors (malformed template, malformed expression body) and
174
- * dispatch-time errors (expression evaluates to null/undefined or a
175
- * non-stringifiable type, expanded key is empty) all surface as typed
176
- * `WorkflowDslError`s — never silently degraded to a default group.
177
- */
178
- export function compileConcurrency(
179
- declaration: WorkflowConcurrencyDeclaration | undefined,
180
- trigger: TriggerPayload,
181
- inputs: Readonly<Record<string, unknown>>,
182
- vars: Readonly<Record<string, unknown>>,
183
- ): ConcurrencyGroup | null {
184
- if (!declaration) return null;
185
-
186
- const compiledSegments = compileConcurrencyGroupTemplate(declaration.group);
187
- const ctx = buildConcurrencyContext(trigger, inputs, vars);
188
- const leaseKey = expandCompiledConcurrencyTemplate(
189
- declaration.group,
190
- compiledSegments,
191
- ctx,
192
- );
193
-
194
- if (leaseKey.length === 0) {
195
- throw new WorkflowDslError(
196
- WorkflowErrorCode.DSL_SEMANTIC_INVALID,
197
- `Concurrency group expression '${declaration.group}' expanded to an empty string.`,
198
- { authored: declaration.group },
199
- );
200
- }
201
-
202
- return {
203
- leaseKey,
204
- mode: declaration.mode,
205
- };
206
- }
207
-
208
- /**
209
- * Compile-time-only validation hook: parse and pre-compile the concurrency
210
- * template so authoring errors block snapshot creation. Used by
211
- * `validateAllAuthoredExpressions` in the main compiler pass; the result is
212
- * discarded because the dispatch path recompiles from the same source
213
- * (determinism is preserved by the canonical workflow document hash).
214
- */
215
- export function validateConcurrencyGroupTemplate(
216
- declaration: WorkflowConcurrencyDeclaration | undefined,
217
- ): void {
218
- if (!declaration) return;
219
- // Parse + compile every embedded expression; throw on any syntax error.
220
- // The returned segments are intentionally discarded — the dispatch path
221
- // recompiles from the same source string (deterministic).
222
- compileConcurrencyGroupTemplate(declaration.group);
223
- }
@@ -1,108 +0,0 @@
1
- import { WorkflowErrorCode } from '@xemahq/kernel-contracts/workflow';
2
- import { WorkflowDslError } from '../errors';
3
-
4
- /**
5
- * Topological sort for the job DAG. Returns jobs in a stable order where
6
- * every job appears after all its `needs` predecessors.
7
- *
8
- * Cycle detection: Kahn's algorithm. If any node remains after the queue
9
- * drains, there's a cycle. Stable order: within each ready set, jobs are
10
- * visited in input order (so authoring order drives UI layout).
11
- *
12
- * Missing-need detection: if any `needs` entry references a jobKey that
13
- * isn't in the graph, fail fast (can't be silently dropped — would hide
14
- * a copy-paste bug).
15
- */
16
- export function topologicalSort<T>(
17
- nodes: readonly { key: string; payload: T; needs: readonly string[] }[],
18
- ): readonly { key: string; payload: T; needs: readonly string[] }[] {
19
- const byKey = new Map<string, { key: string; payload: T; needs: readonly string[] }>();
20
- const inputOrder = new Map<string, number>();
21
- nodes.forEach((node, i) => {
22
- if (byKey.has(node.key)) {
23
- throw new WorkflowDslError(
24
- WorkflowErrorCode.DSL_SEMANTIC_INVALID,
25
- `Duplicate job key: ${node.key}`,
26
- { key: node.key },
27
- );
28
- }
29
- byKey.set(node.key, node);
30
- inputOrder.set(node.key, i);
31
- });
32
-
33
- // Validate needs references before building indegree — unknown refs are
34
- // a structural error, not a cycle error.
35
- for (const node of nodes) {
36
- for (const needKey of node.needs) {
37
- if (!byKey.has(needKey)) {
38
- throw new WorkflowDslError(
39
- WorkflowErrorCode.DSL_SEMANTIC_INVALID,
40
- `Job '${node.key}' declares needs: [${needKey}] but no such job exists.`,
41
- { jobKey: node.key, missingNeed: needKey },
42
- );
43
- }
44
- if (needKey === node.key) {
45
- throw new WorkflowDslError(
46
- WorkflowErrorCode.DSL_CYCLE_DETECTED,
47
- `Job '${node.key}' cannot depend on itself.`,
48
- { jobKey: node.key },
49
- );
50
- }
51
- }
52
- }
53
-
54
- const indegree = new Map<string, number>();
55
- const dependents = new Map<string, string[]>();
56
- for (const node of nodes) {
57
- indegree.set(node.key, node.needs.length);
58
- dependents.set(node.key, []);
59
- }
60
- for (const node of nodes) {
61
- for (const needKey of node.needs) {
62
- dependents.get(needKey)!.push(node.key);
63
- }
64
- }
65
-
66
- const ready: string[] = [];
67
- for (const [key, d] of indegree) {
68
- if (d === 0) ready.push(key);
69
- }
70
- stableSortByInputOrder(ready, inputOrder);
71
-
72
- const sorted: { key: string; payload: T; needs: readonly string[] }[] = [];
73
- while (ready.length > 0) {
74
- const key = ready.shift()!;
75
- sorted.push(byKey.get(key)!);
76
- const children = dependents.get(key)!;
77
- const newlyReady: string[] = [];
78
- for (const child of children) {
79
- const next = indegree.get(child)! - 1;
80
- indegree.set(child, next);
81
- if (next === 0) newlyReady.push(child);
82
- }
83
- stableSortByInputOrder(newlyReady, inputOrder);
84
- ready.push(...newlyReady);
85
- stableSortByInputOrder(ready, inputOrder);
86
- }
87
-
88
- if (sorted.length !== nodes.length) {
89
- const stuck = [...indegree.entries()]
90
- .filter(([, d]) => d > 0)
91
- .map(([k]) => k);
92
- throw new WorkflowDslError(
93
- WorkflowErrorCode.DSL_CYCLE_DETECTED,
94
- `Workflow DAG contains a cycle. Jobs in cycle or downstream of one: ${stuck.join(', ')}`,
95
- { stuck },
96
- );
97
- }
98
-
99
- return sorted;
100
- }
101
-
102
- function stableSortByInputOrder(keys: string[], inputOrder: Map<string, number>): void {
103
- keys.sort((a, b) => {
104
- const ai = inputOrder.get(a)!;
105
- const bi = inputOrder.get(b)!;
106
- return ai - bi;
107
- });
108
- }
@@ -1,153 +0,0 @@
1
- // ═══════════════════════════════════════════════════════════════════════════
2
- // ── Workflow-level decision-gate defaults (`defaults.gate`) ──
3
- //
4
- // Gate-heavy workflows (e.g. the software-dev product-development pipeline)
5
- // repeat the same decision-gate configuration on every gate job:
6
- // timeoutSeconds, onTimeout, autonomyMode, recipients, policy. `defaults.gate`
7
- // lets the author declare that configuration ONCE at the workflow level; the
8
- // compiler folds it into each gate job's `with:` before any other compile
9
- // pass runs, so downstream validation, expression compilation, and the
10
- // CompiledRun snapshot all observe the merged document — expressions inside
11
- // defaults compile per-job exactly as if written inline.
12
- //
13
- // Merge contract (deterministic, no silent deep-merging):
14
- // • Applies ONLY to jobs whose `uses:` resolves to the `xema/decision-gate`
15
- // action id — matched on the resolved ref's id, regardless of version.
16
- // • Fills ABSENT `with:` keys only. Explicit per-gate values always win.
17
- // • Fill is per top-level key: a gate that declares its own `policy` or
18
- // `recipients` keeps that value verbatim — there is no partial merge
19
- // inside a key's object/array value.
20
- // • Fail-fast validation: every `defaults.gate` key must be declared in
21
- // the resolved gate manifest's `inputs.properties` (guards drift between
22
- // the DSL schema's closed key set and the pinned gate action version).
23
- // ═══════════════════════════════════════════════════════════════════════════
24
-
25
- import { WorkflowErrorCode } from '@xemahq/kernel-contracts/workflow';
26
- import { WorkflowDslError } from '../errors';
27
- import { compileExpression, extractInterpolations } from '../expression';
28
- import type { WorkflowDocument, WorkflowGateDefaults } from '../types';
29
- import type { ResolvedRef } from './types';
30
-
31
- /**
32
- * Canonical action id of the decision-gate primitive. `defaults.gate`
33
- * targets jobs by this id — never by the raw `uses:` string — so any
34
- * pinned version (`xema/decision-gate@1.2.0`, `@2.x`, …) participates.
35
- */
36
- export const DECISION_GATE_ACTION_ID = 'xema/decision-gate';
37
-
38
- /**
39
- * Fold `defaults.gate` into every decision-gate job's `with:` block and
40
- * return the (possibly rewritten) document. Pure: never mutates the input.
41
- *
42
- * Runs BEFORE all other compile passes so the merged `with:` flows through
43
- * expression validation, needs-shape validation, review rewriting, the
44
- * action input-schema pin, and the snapshot hash exactly like authored
45
- * values.
46
- *
47
- * Jobs whose `uses:` is missing from `resolvedRefs` are skipped here — the
48
- * per-job compile loop already fails them with `DSL_UNKNOWN_ACTION`, and
49
- * pre-empting that error would reorder author-facing diagnostics.
50
- */
51
- export function applyGateDefaults(
52
- workflow: WorkflowDocument,
53
- resolvedRefs: Readonly<Record<string, ResolvedRef>>,
54
- ): WorkflowDocument {
55
- const gate = workflow.defaults?.gate;
56
- if (gate === undefined) return workflow;
57
- const gateEntries = Object.entries(gate).filter(
58
- ([, value]) => value !== undefined,
59
- );
60
- if (gateEntries.length === 0) return workflow;
61
-
62
- // Validate every `${{ … }}` expression inside the defaults block up
63
- // front — even when no gate job consumes it. A malformed expression in
64
- // `defaults.gate` is an authoring error regardless of merge fan-out;
65
- // deferring it until a gate job appears would be a silent latency.
66
- for (const ext of extractInterpolations(
67
- gate as Readonly<Record<string, unknown>>,
68
- ['defaults', 'gate'],
69
- )) {
70
- compileExpression(ext.source);
71
- }
72
-
73
- let anyChanged = false;
74
- const rewrittenJobs: Record<string, WorkflowDocument['jobs'][string]> = {};
75
- for (const [jobKey, job] of Object.entries(workflow.jobs)) {
76
- const resolved = resolvedRefs[job.uses];
77
- if (
78
- resolved === undefined ||
79
- resolved.isReusableWorkflow ||
80
- resolved.id !== DECISION_GATE_ACTION_ID
81
- ) {
82
- rewrittenJobs[jobKey] = job;
83
- continue;
84
- }
85
-
86
- assertGateDefaultKeysDeclared(jobKey, gate, resolved);
87
-
88
- const authored = job.with ?? {};
89
- let jobChanged = false;
90
- const merged: Record<string, unknown> = { ...authored };
91
- for (const [key, value] of gateEntries) {
92
- if (Object.hasOwn(authored, key)) continue;
93
- merged[key] = value;
94
- jobChanged = true;
95
- }
96
- if (!jobChanged) {
97
- rewrittenJobs[jobKey] = job;
98
- continue;
99
- }
100
- anyChanged = true;
101
- rewrittenJobs[jobKey] = { ...job, with: merged };
102
- }
103
-
104
- if (!anyChanged) return workflow;
105
- return { ...workflow, jobs: rewrittenJobs };
106
- }
107
-
108
- /**
109
- * Fail-fast subset check: every `defaults.gate` key must be a declared
110
- * input of the resolved gate action version. The JSON schema already
111
- * closes the key set to the canonical decision-gate input names; this
112
- * check guards manifest drift (e.g. a future gate version renaming or
113
- * dropping an input while a workflow still defaults it).
114
- *
115
- * Skipped only when the manifest declares no introspectable
116
- * `inputs.properties` map — nothing to prove against; the worker's
117
- * pinned input-schema validation still rejects unknown keys at dispatch.
118
- */
119
- function assertGateDefaultKeysDeclared(
120
- jobKey: string,
121
- gate: WorkflowGateDefaults,
122
- resolved: ResolvedRef,
123
- ): void {
124
- const inputs = resolved.actionManifest?.spec.inputs;
125
- const properties =
126
- inputs && typeof inputs === 'object'
127
- ? (inputs as { properties?: unknown }).properties
128
- : undefined;
129
- if (
130
- properties === null ||
131
- properties === undefined ||
132
- typeof properties !== 'object' ||
133
- Array.isArray(properties)
134
- ) {
135
- return;
136
- }
137
- const declared = properties as Readonly<Record<string, unknown>>;
138
- for (const [key, value] of Object.entries(gate)) {
139
- if (value === undefined) continue;
140
- if (Object.hasOwn(declared, key)) continue;
141
- throw new WorkflowDslError(
142
- WorkflowErrorCode.DSL_SEMANTIC_INVALID,
143
- `defaults.gate.${key} is not a declared input of ${resolved.id}@${resolved.version} (consumed by job '${jobKey}'). Declared inputs: [${Object.keys(declared).sort((a, b) => a.localeCompare(b)).join(', ')}].`,
144
- {
145
- jobKey,
146
- key,
147
- actionId: resolved.id,
148
- actionVersion: resolved.version,
149
- declaredInputs: Object.keys(declared),
150
- },
151
- );
152
- }
153
- }
@@ -1,11 +0,0 @@
1
- export { compileWorkflow } from './compile';
2
- export { DECISION_GATE_ACTION_ID, applyGateDefaults } from './gate-defaults';
3
- export { canonicalJsonSha256, canonicalJsonStringify } from './canonical-json';
4
- export { compileManifestSource } from './manifest-source';
5
- export { getWorkspaceManifestContract, isAgentShapedAction } from './action-shape';
6
- export type {
7
- CompileInput,
8
- ResolvedAgentMeta,
9
- ResolvedDeliverableSpec,
10
- ResolvedRef,
11
- } from './types';