agent-contracts 0.5.2 → 0.6.1

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.
package/README.md CHANGED
@@ -119,7 +119,7 @@ version: 1
119
119
  system:
120
120
  id: my-project
121
121
  name: My Agent Workflow
122
- default_phase_order: [design, implement]
122
+ default_workflow_order: [design, implement]
123
123
 
124
124
  agents:
125
125
  architect:
@@ -136,7 +136,7 @@ tasks:
136
136
  description: "Delegate feature implementation"
137
137
  target_agent: implementer
138
138
  allowed_from_agents: [architect]
139
- phase: implement
139
+ workflow: implement
140
140
  input_artifacts: [spec-md]
141
141
  invocation_handoff: task-delegation
142
142
  result_handoff: implementation-result
@@ -187,7 +187,7 @@ A **Task** defines a delegatable unit of work:
187
187
 
188
188
  * target agent
189
189
  * allowed callers
190
- * phase
190
+ * workflow
191
191
  * input artifacts
192
192
  * invocation/result handoffs
193
193
  * task-specific execution expectations
@@ -262,7 +262,7 @@ extends: "./base/"
262
262
  system:
263
263
  id: my-project
264
264
  name: My Agent Workflow
265
- default_phase_order:
265
+ default_workflow_order:
266
266
  - analyze
267
267
  - specify
268
268
  - plan
@@ -301,7 +301,7 @@ extends: "./base/"
301
301
  system:
302
302
  id: my-project
303
303
  name: My Agent Workflow
304
- default_phase_order: [analyze, specify, plan, implement, audit, release, reflect]
304
+ default_workflow_order: [analyze, specify, plan, implement, audit, release, reflect]
305
305
 
306
306
  agents: { $ref: "./agents.yaml" }
307
307
  tasks: { $ref: "./tasks.yaml" }
@@ -384,7 +384,7 @@ version: 1
384
384
  system:
385
385
  id: my-project
386
386
  name: My Agent Workflow
387
- default_phase_order: [analyze, implement]
387
+ default_workflow_order: [analyze, implement]
388
388
  $refs:
389
389
  - "./agents-core.yaml" # agents + artifacts definitions
390
390
  - "./agents-constraints.yaml" # constraints for the same agents
@@ -446,7 +446,7 @@ tasks:
446
446
  target_agent: implementer
447
447
  allowed_from_agents:
448
448
  - main-architect
449
- phase: implement
449
+ workflow: implement
450
450
  input_artifacts:
451
451
  - spec-md
452
452
  - plan-md
@@ -457,15 +457,21 @@ tasks:
457
457
  execution_steps:
458
458
  - id: read-specs
459
459
  action: "Read spec-md and design-docs"
460
+ description: "Read all relevant specification and design documents"
460
461
  - id: implement
461
462
  action: "Implement changes in codebase"
462
463
  - id: run-db-lint
463
464
  action: "Run db-lint"
465
+ description: "Run database schema linter to check migrations"
464
466
  uses_tool: db-lint
467
+ x-timeout: 120
465
468
  completion_criteria:
466
469
  - "canonical artifacts updated"
467
470
  ````
468
471
 
472
+ `x-` prefixed custom properties work at any nesting level — including inside
473
+ `execution_steps`, `rules`, `workflow.steps`, and other nested objects.
474
+
469
475
  ---
470
476
 
471
477
  ## Example: Artifact definition
@@ -605,7 +611,9 @@ Checks:
605
611
  * types
606
612
  * enums
607
613
  * handoff payload shape
608
- * invalid custom properties without `x-` prefix
614
+ * invalid custom properties without `x-` prefix (checked at all nesting levels)
615
+
616
+ Custom properties with `x-` prefix are allowed on any object in the DSL — top-level entities (agents, tasks, artifacts, …), nested objects (rules, execution steps, workflow steps, …), and the root DSL itself.
609
617
 
610
618
  ### Reference integrity
611
619
 
package/dist/cli.js CHANGED
@@ -6293,7 +6293,7 @@ var init_index_es = __esm({
6293
6293
  return { drive: t4.toLowerCase() + ":" };
6294
6294
  }, k2 = function() {
6295
6295
  return { drive: null };
6296
- }, z14 = function() {
6296
+ }, z15 = function() {
6297
6297
  return { drive: null };
6298
6298
  }, B2 = function(t4) {
6299
6299
  return { protocol: null, origin: null, absolute: false, drive: null, ...t4 };
@@ -6334,7 +6334,7 @@ var init_index_es = __esm({
6334
6334
  var t4, n4, r4, e4, o4;
6335
6335
  return t4 = K2, (n4 = rt()) !== c2 && (r4 = et()) !== c2 && (e4 = ut()) !== c2 && (o4 = it()) !== c2 ? (n4 = s2(n4, r4, e4, o4), t4 = n4) : (K2 = t4, t4 = c2), t4 === c2 && (t4 = K2, (n4 = rt()) !== c2 && (r4 = et()) !== c2 && (e4 = (function() {
6336
6336
  var t5;
6337
- return (t5 = x3) !== c2 && (t5 = z14()), t5;
6337
+ return (t5 = x3) !== c2 && (t5 = z15()), t5;
6338
6338
  })()) !== c2 ? (n4 = f2(n4, r4, e4), t4 = n4) : (K2 = t4, t4 = c2)), t4;
6339
6339
  })()) === c2 && (n3 = (function() {
6340
6340
  var n4, r4, e4, o4;
@@ -8023,7 +8023,7 @@ __export(index_es_exports2, {
8023
8023
  resolveExternalRef: () => ye,
8024
8024
  resolveExternalRefWithLocation: () => ge,
8025
8025
  resolveInlineRef: () => B,
8026
- resolveInlineRefWithLocation: () => z13,
8026
+ resolveInlineRefWithLocation: () => z14,
8027
8027
  safeParse: () => de,
8028
8028
  safeStringify: () => ve,
8029
8029
  startsWith: () => be,
@@ -8067,9 +8067,9 @@ function* L(e3, t3, r3) {
8067
8067
  for (const [n3, o3] of t3.entries()) O(e3.value, o3, r3), e3.value = e3.value[o3], A(e3.value) && (j(e3.value), yield [n3, e3.value]);
8068
8068
  }
8069
8069
  function B(e3, t3) {
8070
- return z13(e3, t3).value;
8070
+ return z14(e3, t3).value;
8071
8071
  }
8072
- function z13(e3, t3) {
8072
+ function z14(e3, t3) {
8073
8073
  return (function e4(t4, r3, n3, o3) {
8074
8074
  if (null !== V(r3)) throw new ReferenceError("Cannot resolve external references");
8075
8075
  const i3 = K(r3);
@@ -16899,7 +16899,7 @@ var require_immer_cjs_production_min = __commonJS({
16899
16899
  var t4 = n4[H2];
16900
16900
  return (t4 ? s2(t4) : n4)[r4];
16901
16901
  }
16902
- function z14(n4, r4) {
16902
+ function z15(n4, r4) {
16903
16903
  if (r4 in n4) for (var t4 = Object.getPrototypeOf(n4); t4; ) {
16904
16904
  var e4 = Object.getOwnPropertyDescriptor(t4, r4);
16905
16905
  if (e4) return e4;
@@ -17292,7 +17292,7 @@ var require_immer_cjs_production_min = __commonJS({
17292
17292
  if (r4 === H2) return n4;
17293
17293
  var e4 = s2(n4);
17294
17294
  if (!u2(e4, r4)) return (function(n5, r5, t4) {
17295
- var e5, i5 = z14(r5, t4);
17295
+ var e5, i5 = z15(r5, t4);
17296
17296
  return i5 ? "value" in i5 ? i5.value : null === (e5 = i5.get) || void 0 === e5 ? void 0 : e5.call(n5.k) : void 0;
17297
17297
  })(n4, e4, r4);
17298
17298
  var i4 = e4[r4];
@@ -17302,7 +17302,7 @@ var require_immer_cjs_production_min = __commonJS({
17302
17302
  }, ownKeys: function(n4) {
17303
17303
  return Reflect.ownKeys(s2(n4));
17304
17304
  }, set: function(n4, r4, t4) {
17305
- var e4 = z14(s2(n4), r4);
17305
+ var e4 = z15(s2(n4), r4);
17306
17306
  if (null == e4 ? void 0 : e4.set) return e4.set.call(n4.k, t4), true;
17307
17307
  if (!n4.g) {
17308
17308
  var i4 = A2(s2(n4), r4), o4 = null == i4 ? void 0 : i4[H2];
@@ -35641,11 +35641,11 @@ var require_brace_expansion = __commonJS({
35641
35641
  if (pad) {
35642
35642
  var need = width - c2.length;
35643
35643
  if (need > 0) {
35644
- var z14 = new Array(need + 1).join("0");
35644
+ var z15 = new Array(need + 1).join("0");
35645
35645
  if (i3 < 0)
35646
- c2 = "-" + z14 + c2.slice(1);
35646
+ c2 = "-" + z15 + c2.slice(1);
35647
35647
  else
35648
- c2 = z14 + c2;
35648
+ c2 = z15 + c2;
35649
35649
  }
35650
35650
  }
35651
35651
  }
@@ -55621,7 +55621,7 @@ var require_dist10 = __commonJS({
55621
55621
  var getSiblings = (parent) => (node) => getChildren(parent).filter(not(eq(node)));
55622
55622
  var concatAll = (
55623
55623
  /*::<T>*/
55624
- (xs) => (ys) => ys.reduce((zs, z14) => zs.concat(z14), xs)
55624
+ (xs) => (ys) => ys.reduce((zs, z15) => zs.concat(z15), xs)
55625
55625
  );
55626
55626
  function getLastSegment(instancePath) {
55627
55627
  const index4 = instancePath.lastIndexOf("/");
@@ -59004,6 +59004,9 @@ var resolveCommand = new Command("resolve").description("Resolve DSL (load + mer
59004
59004
  // src/cli/commands/validate.ts
59005
59005
  import { Command as Command2 } from "commander";
59006
59006
 
59007
+ // src/validator/schema-validator.ts
59008
+ import { z as z13 } from "zod";
59009
+
59007
59010
  // src/schema/agent.ts
59008
59011
  import { z as z2 } from "zod";
59009
59012
  var RuleSchema = z2.object({
@@ -59014,7 +59017,7 @@ var RuleSchema = z2.object({
59014
59017
  detection_method: z2.string().optional(),
59015
59018
  escalation: z2.string().optional(),
59016
59019
  ref: z2.string().optional()
59017
- }).strict();
59020
+ }).passthrough();
59018
59021
  var EscalationCriterionSchema = z2.object({
59019
59022
  condition: z2.string(),
59020
59023
  action: z2.enum([
@@ -59022,12 +59025,12 @@ var EscalationCriterionSchema = z2.object({
59022
59025
  "report_to_architect",
59023
59026
  "wait_for_approval"
59024
59027
  ])
59025
- }).strict();
59028
+ }).passthrough();
59026
59029
  var PrerequisiteSchema = z2.object({
59027
59030
  action: z2.enum(["read", "execute"]),
59028
59031
  target: z2.string(),
59029
59032
  required: z2.boolean()
59030
- }).strict();
59033
+ }).passthrough();
59031
59034
  var AgentSchema = z2.object({
59032
59035
  role_name: z2.string(),
59033
59036
  purpose: z2.string(),
@@ -59069,14 +59072,15 @@ import { z as z4 } from "zod";
59069
59072
  var HandoffTypeSchema = z4.object({
59070
59073
  version: z4.number(),
59071
59074
  description: z4.string().optional(),
59072
- payload: z4.record(z4.string(), z4.any())
59075
+ payload: z4.record(z4.string(), z4.any()),
59076
+ example: z4.record(z4.string(), z4.any()).optional()
59073
59077
  }).passthrough();
59074
59078
 
59075
59079
  // src/schema/policy.ts
59076
59080
  import { z as z5 } from "zod";
59077
59081
  var PolicyWhenSchema = z5.object({
59078
59082
  artifact_type: z5.string().optional(),
59079
- phase: z5.string().optional()
59083
+ workflow: z5.string().optional()
59080
59084
  }).passthrough();
59081
59085
  var PolicySchema = z5.object({
59082
59086
  when: PolicyWhenSchema,
@@ -59091,7 +59095,7 @@ var ExtendsSchema = z6.string().optional();
59091
59095
  var SystemSchema = z6.object({
59092
59096
  id: z6.string(),
59093
59097
  name: z6.string(),
59094
- default_phase_order: z6.array(z6.string())
59098
+ default_workflow_order: z6.array(z6.string())
59095
59099
  }).passthrough();
59096
59100
 
59097
59101
  // src/schema/task.ts
@@ -59099,6 +59103,7 @@ import { z as z7 } from "zod";
59099
59103
  var ExecutionStepSchema = z7.object({
59100
59104
  id: z7.string(),
59101
59105
  action: z7.string(),
59106
+ description: z7.string().optional(),
59102
59107
  required: z7.boolean().optional(),
59103
59108
  abort_on_failure: z7.boolean().optional(),
59104
59109
  uses_tool: z7.string().optional(),
@@ -59106,12 +59111,12 @@ var ExecutionStepSchema = z7.object({
59106
59111
  depends_on: z7.array(z7.string()).optional(),
59107
59112
  skip_condition: z7.string().optional(),
59108
59113
  wait_for_approval: z7.boolean().optional()
59109
- }).strict();
59114
+ }).passthrough();
59110
59115
  var TaskSchema = z7.object({
59111
59116
  description: z7.string(),
59112
59117
  target_agent: z7.string(),
59113
59118
  allowed_from_agents: z7.array(z7.string()),
59114
- phase: z7.string(),
59119
+ workflow: z7.string(),
59115
59120
  input_artifacts: z7.array(z7.string()),
59116
59121
  invocation_handoff: z7.string(),
59117
59122
  result_handoff: z7.string(),
@@ -59151,19 +59156,22 @@ var ValidationSchema = z9.object({
59151
59156
  import { z as z10 } from "zod";
59152
59157
  var WorkflowHandoffStepSchema = z10.object({
59153
59158
  type: z10.literal("handoff"),
59159
+ description: z10.string().optional(),
59154
59160
  handoff_kind: z10.string(),
59155
59161
  task: z10.string().optional(),
59156
59162
  from_agent: z10.string().optional()
59157
- }).strict();
59163
+ }).passthrough();
59158
59164
  var WorkflowValidationStepSchema = z10.object({
59159
59165
  type: z10.literal("validation"),
59166
+ description: z10.string().optional(),
59160
59167
  validation: z10.string()
59161
- }).strict();
59168
+ }).passthrough();
59162
59169
  var WorkflowDecisionStepSchema = z10.object({
59163
59170
  type: z10.literal("decision"),
59171
+ description: z10.string().optional(),
59164
59172
  on: z10.string(),
59165
59173
  branches: z10.record(z10.string(), z10.array(z10.string()))
59166
- }).strict();
59174
+ }).passthrough();
59167
59175
  var WorkflowStepSchema = z10.discriminatedUnion("type", [
59168
59176
  WorkflowHandoffStepSchema,
59169
59177
  WorkflowValidationStepSchema,
@@ -59171,6 +59179,7 @@ var WorkflowStepSchema = z10.discriminatedUnion("type", [
59171
59179
  ]);
59172
59180
  var WorkflowSchema = z10.object({
59173
59181
  entry_conditions: z10.array(z10.string()).default([]),
59182
+ trigger: z10.string().optional(),
59174
59183
  steps: z10.array(WorkflowStepSchema)
59175
59184
  }).passthrough();
59176
59185
 
@@ -59209,113 +59218,65 @@ var RemoveOperatorSchema = z12.object({
59209
59218
  });
59210
59219
 
59211
59220
  // src/validator/schema-validator.ts
59212
- function hasNonExtensionCustomProps(obj, knownKeys, path) {
59213
- const diagnostics = [];
59214
- for (const key of Object.keys(obj)) {
59215
- if (knownKeys.has(key)) continue;
59216
- if (key.startsWith("x-")) continue;
59217
- diagnostics.push({
59218
- path: `${path}.${key}`,
59219
- message: `Unknown property "${key}". Custom properties must use "x-" prefix.`,
59220
- code: "unknown-property"
59221
- });
59222
- }
59223
- return diagnostics;
59221
+ function unwrap(schema) {
59222
+ if (schema instanceof z13.ZodOptional) return unwrap(schema.unwrap());
59223
+ if (schema instanceof z13.ZodDefault) return unwrap(schema.removeDefault());
59224
+ if (schema instanceof z13.ZodNullable) return unwrap(schema.unwrap());
59225
+ return schema;
59224
59226
  }
59225
- var SYSTEM_KEYS = /* @__PURE__ */ new Set(["id", "name", "default_phase_order"]);
59226
- var AGENT_KEYS = /* @__PURE__ */ new Set([
59227
- "role_name",
59228
- "purpose",
59229
- "can_read_artifacts",
59230
- "can_write_artifacts",
59231
- "can_execute_tools",
59232
- "can_perform_validations",
59233
- "can_invoke_agents",
59234
- "can_return_handoffs",
59235
- "dispatch_only",
59236
- "mode",
59237
- "responsibilities",
59238
- "constraints",
59239
- "rules",
59240
- "anti_patterns",
59241
- "escalation_criteria",
59242
- "prerequisites"
59243
- ]);
59244
- var TASK_KEYS = /* @__PURE__ */ new Set([
59245
- "description",
59246
- "target_agent",
59247
- "allowed_from_agents",
59248
- "phase",
59249
- "input_artifacts",
59250
- "invocation_handoff",
59251
- "result_handoff",
59252
- "default_priority",
59253
- "responsibilities",
59254
- "constraints",
59255
- "execution_steps",
59256
- "completion_criteria",
59257
- "rules",
59258
- "anti_patterns",
59259
- "escalation_criteria"
59260
- ]);
59261
- var ARTIFACT_KEYS = /* @__PURE__ */ new Set([
59262
- "type",
59263
- "description",
59264
- "owner",
59265
- "producers",
59266
- "editors",
59267
- "consumers",
59268
- "states",
59269
- "required_validations",
59270
- "visibility"
59271
- ]);
59272
- var TOOL_KEYS = /* @__PURE__ */ new Set([
59273
- "kind",
59274
- "description",
59275
- "input_artifacts",
59276
- "output_artifacts",
59277
- "invokable_by",
59278
- "side_effects"
59279
- ]);
59280
- var VALIDATION_KEYS = /* @__PURE__ */ new Set([
59281
- "target_artifact",
59282
- "kind",
59283
- "executor_type",
59284
- "executor",
59285
- "blocking",
59286
- "produces_evidence"
59287
- ]);
59288
- var HANDOFF_TYPE_KEYS = /* @__PURE__ */ new Set(["version", "description", "payload"]);
59289
- var WORKFLOW_KEYS = /* @__PURE__ */ new Set(["entry_conditions", "steps"]);
59290
- var POLICY_KEYS = /* @__PURE__ */ new Set(["when", "requires_validations", "requires"]);
59291
- function checkCustomProps(data) {
59292
- const diagnostics = [];
59293
- if (data["system"] && typeof data["system"] === "object") {
59294
- diagnostics.push(
59295
- ...hasNonExtensionCustomProps(data["system"], SYSTEM_KEYS, "system")
59296
- );
59227
+ function checkCustomPropsRecursive(data, schema, path) {
59228
+ const inner = unwrap(schema);
59229
+ if (inner instanceof z13.ZodObject) {
59230
+ if (typeof data !== "object" || data === null || Array.isArray(data)) return [];
59231
+ const obj = data;
59232
+ const shape = inner.shape;
59233
+ const knownKeys = new Set(Object.keys(shape));
59234
+ const diagnostics = [];
59235
+ for (const key of Object.keys(obj)) {
59236
+ if (knownKeys.has(key)) continue;
59237
+ if (key.startsWith("x-")) continue;
59238
+ diagnostics.push({
59239
+ path: path ? `${path}.${key}` : key,
59240
+ message: `Unknown property "${key}". Custom properties must use "x-" prefix.`,
59241
+ code: "unknown-property"
59242
+ });
59243
+ }
59244
+ for (const [field, fieldSchema] of Object.entries(shape)) {
59245
+ if (obj[field] === void 0) continue;
59246
+ diagnostics.push(...checkCustomPropsRecursive(obj[field], fieldSchema, path ? `${path}.${field}` : field));
59247
+ }
59248
+ return diagnostics;
59297
59249
  }
59298
- const sections = [
59299
- { key: "agents", knownKeys: AGENT_KEYS },
59300
- { key: "tasks", knownKeys: TASK_KEYS },
59301
- { key: "artifacts", knownKeys: ARTIFACT_KEYS },
59302
- { key: "tools", knownKeys: TOOL_KEYS },
59303
- { key: "validations", knownKeys: VALIDATION_KEYS },
59304
- { key: "handoff_types", knownKeys: HANDOFF_TYPE_KEYS },
59305
- { key: "workflow", knownKeys: WORKFLOW_KEYS },
59306
- { key: "policies", knownKeys: POLICY_KEYS }
59307
- ];
59308
- for (const { key, knownKeys } of sections) {
59309
- const map = data[key];
59310
- if (typeof map !== "object" || map === null || Array.isArray(map)) continue;
59311
- for (const [entryKey, item] of Object.entries(map)) {
59312
- if (typeof item !== "object" || item === null) continue;
59313
- diagnostics.push(
59314
- ...hasNonExtensionCustomProps(item, knownKeys, `${key}.${entryKey}`)
59315
- );
59250
+ if (inner instanceof z13.ZodRecord) {
59251
+ if (typeof data !== "object" || data === null || Array.isArray(data)) return [];
59252
+ const valueSchema = inner._def.valueType;
59253
+ const diagnostics = [];
59254
+ for (const [key, value] of Object.entries(data)) {
59255
+ diagnostics.push(...checkCustomPropsRecursive(value, valueSchema, path ? `${path}.${key}` : key));
59316
59256
  }
59257
+ return diagnostics;
59317
59258
  }
59318
- return diagnostics;
59259
+ if (inner instanceof z13.ZodArray) {
59260
+ if (!Array.isArray(data)) return [];
59261
+ const diagnostics = [];
59262
+ for (let i3 = 0; i3 < data.length; i3++) {
59263
+ diagnostics.push(...checkCustomPropsRecursive(data[i3], inner.element, `${path}[${i3}]`));
59264
+ }
59265
+ return diagnostics;
59266
+ }
59267
+ if (inner instanceof z13.ZodDiscriminatedUnion) {
59268
+ if (typeof data !== "object" || data === null) return [];
59269
+ const obj = data;
59270
+ const disc = inner._def.discriminator;
59271
+ const discValue = obj[disc];
59272
+ const match = inner.options.find((opt) => {
59273
+ const shape = opt.shape;
59274
+ return shape[disc] instanceof z13.ZodLiteral && shape[disc].value === discValue;
59275
+ });
59276
+ if (match) return checkCustomPropsRecursive(data, match, path);
59277
+ return [];
59278
+ }
59279
+ return [];
59319
59280
  }
59320
59281
  function validateSchema(data) {
59321
59282
  const result = DslSchema.safeParse(data);
@@ -59327,7 +59288,7 @@ function validateSchema(data) {
59327
59288
  }));
59328
59289
  return { success: false, diagnostics };
59329
59290
  }
59330
- const customPropDiagnostics = checkCustomProps(data);
59291
+ const customPropDiagnostics = checkCustomPropsRecursive(data, DslSchema, "");
59331
59292
  if (customPropDiagnostics.length > 0) {
59332
59293
  return { success: false, diagnostics: customPropDiagnostics };
59333
59294
  }
@@ -59343,7 +59304,7 @@ function checkReferences(dsl) {
59343
59304
  const validationIds = new Set(Object.keys(dsl.validations));
59344
59305
  const handoffKinds = new Set(Object.keys(dsl.handoff_types));
59345
59306
  const taskIds = new Set(Object.keys(dsl.tasks));
59346
- const phases = new Set(dsl.system.default_phase_order);
59307
+ const workflowIds = new Set(dsl.system.default_workflow_order);
59347
59308
  function checkExists(value, validSet, entityType, path) {
59348
59309
  if (!validSet.has(value)) {
59349
59310
  diagnostics.push({
@@ -59429,26 +59390,26 @@ function checkReferences(dsl) {
59429
59390
  for (const ref of task.allowed_from_agents) {
59430
59391
  checkExists(ref, agentIds, "agents", `tasks.${id}.allowed_from_agents`);
59431
59392
  }
59432
- checkExists(task.phase, phases, "system.default_phase_order", `tasks.${id}.phase`);
59393
+ checkExists(task.workflow, workflowIds, "system.default_workflow_order", `tasks.${id}.workflow`);
59433
59394
  checkExists(task.invocation_handoff, handoffKinds, "handoff_types", `tasks.${id}.invocation_handoff`);
59434
59395
  checkExists(task.result_handoff, handoffKinds, "handoff_types", `tasks.${id}.result_handoff`);
59435
59396
  for (const ref of task.input_artifacts) {
59436
59397
  checkExists(ref, artifactIds, "artifacts", `tasks.${id}.input_artifacts`);
59437
59398
  }
59438
59399
  }
59439
- for (const [phase, wf] of Object.entries(dsl.workflow)) {
59440
- checkExists(phase, phases, "system.default_phase_order", `workflow.${phase}`);
59400
+ for (const [wfId, wf] of Object.entries(dsl.workflow)) {
59401
+ checkExists(wfId, workflowIds, "system.default_workflow_order", `workflow.${wfId}`);
59441
59402
  for (let j2 = 0; j2 < wf.steps.length; j2++) {
59442
59403
  const step = wf.steps[j2];
59443
59404
  if (step.type === "handoff") {
59444
59405
  if (step.task) {
59445
- checkExists(step.task, taskIds, "tasks", `workflow.${phase}.steps[${j2}].task`);
59406
+ checkExists(step.task, taskIds, "tasks", `workflow.${wfId}.steps[${j2}].task`);
59446
59407
  }
59447
59408
  if (step.from_agent) {
59448
- checkExists(step.from_agent, agentIds, "agents", `workflow.${phase}.steps[${j2}].from_agent`);
59409
+ checkExists(step.from_agent, agentIds, "agents", `workflow.${wfId}.steps[${j2}].from_agent`);
59449
59410
  }
59450
59411
  } else if (step.type === "validation") {
59451
- checkExists(step.validation, validationIds, "validations", `workflow.${phase}.steps[${j2}].validation`);
59412
+ checkExists(step.validation, validationIds, "validations", `workflow.${wfId}.steps[${j2}].validation`);
59452
59413
  }
59453
59414
  }
59454
59415
  }
@@ -59702,85 +59663,6 @@ var toolExecutionRule = {
59702
59663
  }
59703
59664
  };
59704
59665
 
59705
- // src/linter/rules/release-audit.ts
59706
- var releaseAuditRule = {
59707
- id: "release-audit",
59708
- description: "Workflow graph completeness: release/audit phases should have proper handoff structures",
59709
- run(dsl) {
59710
- const diagnostics = [];
59711
- const phases = dsl.system.default_phase_order;
59712
- const hasAuditPhase = phases.some(
59713
- (p2) => p2 === "audit" || p2 === "release" || p2 === "review"
59714
- );
59715
- if (!hasAuditPhase) {
59716
- return diagnostics;
59717
- }
59718
- const handoffKinds = new Set(Object.keys(dsl.handoff_types));
59719
- const hasReleaseReadiness = handoffKinds.has("release-readiness");
59720
- const hasReleaseResult = handoffKinds.has("release-result");
59721
- if (!hasReleaseReadiness) {
59722
- diagnostics.push({
59723
- ruleId: "release-audit",
59724
- severity: "warning",
59725
- path: "handoff_types",
59726
- message: 'Missing "release-readiness" handoff type for audit/release workflow'
59727
- });
59728
- }
59729
- if (!hasReleaseResult) {
59730
- diagnostics.push({
59731
- ruleId: "release-audit",
59732
- severity: "warning",
59733
- path: "handoff_types",
59734
- message: 'Missing "release-result" handoff type for audit/release workflow'
59735
- });
59736
- }
59737
- if (phases.some((p2) => p2 === "audit")) {
59738
- const hasAuditReport = handoffKinds.has("audit-report");
59739
- const hasAuditReconciliation = handoffKinds.has("audit-reconciliation");
59740
- if (!hasAuditReport) {
59741
- diagnostics.push({
59742
- ruleId: "release-audit",
59743
- severity: "warning",
59744
- path: "handoff_types",
59745
- message: 'Missing "audit-report" handoff type for audit workflow'
59746
- });
59747
- }
59748
- if (!hasAuditReconciliation) {
59749
- diagnostics.push({
59750
- ruleId: "release-audit",
59751
- severity: "warning",
59752
- path: "handoff_types",
59753
- message: 'Missing "audit-reconciliation" handoff type for audit workflow'
59754
- });
59755
- }
59756
- }
59757
- const workflowPhases = new Set(Object.keys(dsl.workflow));
59758
- for (const phase of phases) {
59759
- if ((phase === "audit" || phase === "release") && !workflowPhases.has(phase)) {
59760
- diagnostics.push({
59761
- ruleId: "release-audit",
59762
- severity: "warning",
59763
- path: "workflow",
59764
- message: `Phase "${phase}" is in default_phase_order but has no workflow definition`
59765
- });
59766
- }
59767
- }
59768
- for (const [phase, wf] of Object.entries(dsl.workflow)) {
59769
- if (phase !== "audit" && phase !== "release") continue;
59770
- const hasDecision = wf.steps.some((s2) => s2.type === "decision");
59771
- if (!hasDecision) {
59772
- diagnostics.push({
59773
- ruleId: "release-audit",
59774
- severity: "info",
59775
- path: `workflow.${phase}`,
59776
- message: `Audit/release workflow phase "${phase}" has no decision step for remediation routing`
59777
- });
59778
- }
59779
- }
59780
- return diagnostics;
59781
- }
59782
- };
59783
-
59784
59666
  // src/linter/rules/task-agent-binding.ts
59785
59667
  var taskAgentBindingRule = {
59786
59668
  id: "task-agent-binding",
@@ -59884,21 +59766,21 @@ var taskAgentBindingRule = {
59884
59766
  // src/linter/rules/merge-integrity.ts
59885
59767
  var mergeIntegrityRule = {
59886
59768
  id: "merge-integrity",
59887
- description: "Post-merge integrity: check that resolved DSL phase order has no duplicates",
59769
+ description: "Post-merge integrity: check that resolved DSL workflow order has no duplicates",
59888
59770
  run(dsl) {
59889
59771
  const diagnostics = [];
59890
- const phases = dsl.system.default_phase_order;
59891
- const phaseSeen = /* @__PURE__ */ new Set();
59892
- for (let i3 = 0; i3 < phases.length; i3++) {
59893
- if (phaseSeen.has(phases[i3])) {
59772
+ const workflows = dsl.system.default_workflow_order;
59773
+ const seen = /* @__PURE__ */ new Set();
59774
+ for (let i3 = 0; i3 < workflows.length; i3++) {
59775
+ if (seen.has(workflows[i3])) {
59894
59776
  diagnostics.push({
59895
59777
  ruleId: "merge-integrity",
59896
59778
  severity: "error",
59897
- path: `system.default_phase_order[${i3}]`,
59898
- message: `Duplicate phase "${phases[i3]}" in default_phase_order`
59779
+ path: `system.default_workflow_order[${i3}]`,
59780
+ message: `Duplicate workflow "${workflows[i3]}" in default_workflow_order`
59899
59781
  });
59900
59782
  }
59901
- phaseSeen.add(phases[i3]);
59783
+ seen.add(workflows[i3]);
59902
59784
  }
59903
59785
  return diagnostics;
59904
59786
  }
@@ -59908,7 +59790,6 @@ var mergeIntegrityRule = {
59908
59790
  var builtinRules = [
59909
59791
  validationCoverageRule,
59910
59792
  toolExecutionRule,
59911
- releaseAuditRule,
59912
59793
  taskAgentBindingRule,
59913
59794
  mergeIntegrityRule
59914
59795
  ];
@@ -60573,9 +60454,9 @@ function buildHandoffTypeContext(dsl, handoffTypeId) {
60573
60454
  ).map(([id, t3]) => ({ ...t3, id }));
60574
60455
  return { handoff_type, relatedTasks, dsl };
60575
60456
  }
60576
- function buildWorkflowContext(dsl, phaseId) {
60577
- const wfDef = dsl.workflow[phaseId];
60578
- const workflow = { ...wfDef, id: phaseId };
60457
+ function buildWorkflowContext(dsl, workflowId) {
60458
+ const wfDef = dsl.workflow[workflowId];
60459
+ const workflow = { ...wfDef, id: workflowId };
60579
60460
  return { workflow, dsl };
60580
60461
  }
60581
60462
  function buildPolicyContext(dsl, policyId) {
@@ -60639,7 +60520,7 @@ function buildDelegatableTasks(dsl, agentId) {
60639
60520
  id: taskId,
60640
60521
  description: t3.description,
60641
60522
  target_agent: t3.target_agent,
60642
- phase: t3.phase,
60523
+ workflow: t3.workflow,
60643
60524
  input_artifacts: t3.input_artifacts,
60644
60525
  invocation_handoff: t3.invocation_handoff,
60645
60526
  invocation_payload_keys: invocationHandoff ? extractPayloadFieldNames(invocationHandoff.payload) : [],
@@ -60691,6 +60572,11 @@ function buildPerAgentContext(dsl, agent) {
60691
60572
 
60692
60573
  // src/renderer/renderer.ts
60693
60574
  Handlebars.registerHelper("eq", (a3, b3) => a3 === b3);
60575
+ Handlebars.registerHelper("notEmpty", (obj) => {
60576
+ if (!obj || typeof obj !== "object") return false;
60577
+ return Object.keys(obj).length > 0;
60578
+ });
60579
+ Handlebars.registerHelper("inc", (val) => val + 1);
60694
60580
  Handlebars.registerHelper(
60695
60581
  "lookupPayloadFields",
60696
60582
  (payload) => {