agent-contracts 0.6.1 → 0.7.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 +168 -2
- package/dist/cli.js +534 -11
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +23 -0
- package/dist/index.js +477 -3
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -204,6 +204,15 @@ An **Artifact** defines the objects that move through the workflow:
|
|
|
204
204
|
* required validations
|
|
205
205
|
* visibility
|
|
206
206
|
|
|
207
|
+
### Workflow
|
|
208
|
+
|
|
209
|
+
A **Workflow** defines a phase-level execution sequence:
|
|
210
|
+
|
|
211
|
+
* description
|
|
212
|
+
* entry conditions
|
|
213
|
+
* trigger
|
|
214
|
+
* ordered steps (handoff, validation, decision)
|
|
215
|
+
|
|
207
216
|
### Handoff
|
|
208
217
|
|
|
209
218
|
A **Handoff** is a runtime delegation instance.
|
|
@@ -244,6 +253,7 @@ Design regressions become testable.
|
|
|
244
253
|
* **Structured handoff definitions**
|
|
245
254
|
* **Artifact ownership and lifecycle modeling**
|
|
246
255
|
* **Config-driven prompt rendering**
|
|
256
|
+
* **Variable substitution** via `${vars.xxx}` in DSL values
|
|
247
257
|
* **Inheritance with merge operators via `extends`**
|
|
248
258
|
* **Flexible file splitting** via `$ref` (replacement) and `$refs` (import + deep-merge)
|
|
249
259
|
* **JSON Schema for editor support and external tooling**
|
|
@@ -457,12 +467,13 @@ tasks:
|
|
|
457
467
|
execution_steps:
|
|
458
468
|
- id: read-specs
|
|
459
469
|
action: "Read spec-md and design-docs"
|
|
460
|
-
|
|
470
|
+
reads_artifact: spec-md
|
|
461
471
|
- id: implement
|
|
462
472
|
action: "Implement changes in codebase"
|
|
473
|
+
produces_artifact: codebase
|
|
474
|
+
depends_on: [read-specs]
|
|
463
475
|
- id: run-db-lint
|
|
464
476
|
action: "Run db-lint"
|
|
465
|
-
description: "Run database schema linter to check migrations"
|
|
466
477
|
uses_tool: db-lint
|
|
467
478
|
x-timeout: 120
|
|
468
479
|
completion_criteria:
|
|
@@ -492,6 +503,33 @@ artifacts:
|
|
|
492
503
|
|
|
493
504
|
---
|
|
494
505
|
|
|
506
|
+
## Example: Workflow definition
|
|
507
|
+
|
|
508
|
+
````yaml
|
|
509
|
+
workflow:
|
|
510
|
+
specify:
|
|
511
|
+
description: "Externalize requirements — create spec.md from user stories"
|
|
512
|
+
entry_conditions:
|
|
513
|
+
- User story or feature request received
|
|
514
|
+
trigger: "User invokes /speckit.specify or asks to create a feature spec."
|
|
515
|
+
steps:
|
|
516
|
+
- type: handoff
|
|
517
|
+
handoff_kind: delegation
|
|
518
|
+
task: specify-feature
|
|
519
|
+
from_agent: main-architect
|
|
520
|
+
- type: validation
|
|
521
|
+
validation_id: spec-semantic-review
|
|
522
|
+
- type: decision
|
|
523
|
+
agent: main-architect
|
|
524
|
+
options:
|
|
525
|
+
- label: approve
|
|
526
|
+
next_workflow: plan
|
|
527
|
+
- label: revise
|
|
528
|
+
retry_from_step: 0
|
|
529
|
+
````
|
|
530
|
+
|
|
531
|
+
---
|
|
532
|
+
|
|
495
533
|
## Inheritance and merge operators
|
|
496
534
|
|
|
497
535
|
`agent-contracts` supports shared base definitions with project-level overrides through `extends`.
|
|
@@ -533,6 +571,67 @@ Supported merge operators:
|
|
|
533
571
|
|
|
534
572
|
---
|
|
535
573
|
|
|
574
|
+
## Variable substitution
|
|
575
|
+
|
|
576
|
+
When using `extends` to share a base DSL across projects, base definitions often contain values that differ per project (project name, language, repository URL, etc.).
|
|
577
|
+
|
|
578
|
+
`vars` in `agent-contracts.config.yaml` lets you define project-specific values that are substituted into DSL string values using `${vars.xxx}` syntax.
|
|
579
|
+
|
|
580
|
+
### Defining vars
|
|
581
|
+
|
|
582
|
+
Add a `vars` section to your config file. Values must be flat string key-value pairs.
|
|
583
|
+
|
|
584
|
+
````yaml
|
|
585
|
+
# agent-contracts.config.yaml
|
|
586
|
+
vars:
|
|
587
|
+
project_name: "my-service"
|
|
588
|
+
language: "TypeScript"
|
|
589
|
+
repo_url: "https://github.com/org/my-service"
|
|
590
|
+
````
|
|
591
|
+
|
|
592
|
+
### Using placeholders in DSL
|
|
593
|
+
|
|
594
|
+
Use `${vars.<key>}` in any string value within the DSL YAML (base or project).
|
|
595
|
+
|
|
596
|
+
````yaml
|
|
597
|
+
# base/agent-contracts.yaml
|
|
598
|
+
agents:
|
|
599
|
+
implementer:
|
|
600
|
+
purpose: "Implements features for ${vars.project_name}"
|
|
601
|
+
constraints:
|
|
602
|
+
- "Use ${vars.language} for all implementations"
|
|
603
|
+
- "Repository: ${vars.repo_url}"
|
|
604
|
+
````
|
|
605
|
+
|
|
606
|
+
### Processing order
|
|
607
|
+
|
|
608
|
+
Variable substitution happens **after** DSL resolution (`extends` merge) and **before** schema validation:
|
|
609
|
+
|
|
610
|
+
1. Load config (including `vars`)
|
|
611
|
+
2. Resolve DSL (load + merge `extends`)
|
|
612
|
+
3. Substitute `${vars.xxx}` in all string values
|
|
613
|
+
4. Validate schema
|
|
614
|
+
5. Render / lint / check
|
|
615
|
+
|
|
616
|
+
This ensures that merged strings from both base and project are substituted, and the resulting values pass schema validation.
|
|
617
|
+
|
|
618
|
+
### Error handling
|
|
619
|
+
|
|
620
|
+
If a placeholder references an undefined variable, the command exits with an error:
|
|
621
|
+
|
|
622
|
+
````
|
|
623
|
+
VarsSubstitutionError: Undefined variable "repo_url" in value "Repository: ${vars.repo_url}"
|
|
624
|
+
Defined vars: project_name, language
|
|
625
|
+
````
|
|
626
|
+
|
|
627
|
+
### Notes
|
|
628
|
+
|
|
629
|
+
- Only string values are substituted; object keys are not affected.
|
|
630
|
+
- `vars` is optional. If omitted, no substitution occurs.
|
|
631
|
+
- Patterns that do not match `${vars.<key>}` (e.g. `${env.HOME}`, `$vars.xxx`, `{{vars.xxx}}`) are left unchanged.
|
|
632
|
+
|
|
633
|
+
---
|
|
634
|
+
|
|
536
635
|
## CLI
|
|
537
636
|
|
|
538
637
|
### Installation
|
|
@@ -576,6 +675,11 @@ Rendering is configured via `agent-contracts.config.yaml`.
|
|
|
576
675
|
````yaml
|
|
577
676
|
dsl: ./agent-contracts.yaml
|
|
578
677
|
|
|
678
|
+
vars:
|
|
679
|
+
project_name: "my-service"
|
|
680
|
+
language: "TypeScript"
|
|
681
|
+
repo_url: "https://github.com/org/my-service"
|
|
682
|
+
|
|
579
683
|
renders:
|
|
580
684
|
- template: ./templates/agent-prompt.md.hbs
|
|
581
685
|
context: agent
|
|
@@ -597,6 +701,68 @@ This lets you generate static outputs for:
|
|
|
597
701
|
|
|
598
702
|
all from the same resolved DSL.
|
|
599
703
|
|
|
704
|
+
### Available context types
|
|
705
|
+
|
|
706
|
+
Each `context` type provides a different rendering scope:
|
|
707
|
+
|
|
708
|
+
| Context | Scope | Output | Key variables |
|
|
709
|
+
|---------|-------|--------|---------------|
|
|
710
|
+
| `system` | Single file | `output` as-is | `system`, `dsl` |
|
|
711
|
+
| `agent` | Per agent | `{agent.id}` in output path | `agent`, `receivableTasks`, `delegatableTasks`, `relatedArtifacts`, `relatedTools`, `relatedHandoffTypes`, `mergedBehavior`, `dsl` |
|
|
712
|
+
| `task` | Per task | `{task.id}` in output path | `task`, `targetAgent`, `dsl` |
|
|
713
|
+
| `artifact` | Per artifact | `{artifact.id}` in output path | `artifact`, `relatedTools`, `relatedValidations`, `producerAgents`, `consumerAgents`, `editorAgents`, `createdInWorkflows`, `dsl` |
|
|
714
|
+
| `tool` | Per tool | `{tool.id}` in output path | `tool`, `invokableAgents`, `inputArtifactDetails`, `outputArtifactDetails`, `dsl` |
|
|
715
|
+
| `validation` | Per validation | `{validation.id}` in output path | `validation`, `dsl` |
|
|
716
|
+
| `handoff_type` | Per handoff type | `{handoff_type.id}` in output path | `handoff_type`, `relatedTasks`, `dsl` |
|
|
717
|
+
| `workflow` | Per workflow phase | `{workflow.id}` in output path | `workflow`, `relatedAgents`, `relatedTasks`, `relatedTools`, `relatedArtifacts`, `relatedValidations`, `dsl` |
|
|
718
|
+
| `policy` | Per policy | `{policy.id}` in output path | `policy`, `dsl` |
|
|
719
|
+
|
|
720
|
+
#### Enriched context details
|
|
721
|
+
|
|
722
|
+
**`workflow` context** collects all entities involved in a phase:
|
|
723
|
+
|
|
724
|
+
* `relatedTasks` — tasks where `task.workflow` matches this phase
|
|
725
|
+
* `relatedAgents` — agents from task `target_agent`, `allowed_from_agents`, step `from_agent`, and validation executors
|
|
726
|
+
* `relatedTools` — tools from `can_execute_tools` of all related agents, plus `uses_tool` in execution steps
|
|
727
|
+
* `relatedArtifacts` — artifacts from `can_read_artifacts`, `can_write_artifacts`, `input_artifacts`, plus `produces_artifact` and `reads_artifact` in execution steps
|
|
728
|
+
* `relatedValidations` — validations referenced in workflow steps
|
|
729
|
+
|
|
730
|
+
**`artifact` context** provides ownership and cross-reference data:
|
|
731
|
+
|
|
732
|
+
* `relatedTools` — tools with this artifact in `input_artifacts` or `output_artifacts`
|
|
733
|
+
* `relatedValidations` — validations targeting this artifact
|
|
734
|
+
* `producerAgents` / `consumerAgents` / `editorAgents` — resolved agent records
|
|
735
|
+
* `createdInWorkflows` — workflow phases where this artifact is written
|
|
736
|
+
|
|
737
|
+
**`tool` context** resolves agent and artifact references:
|
|
738
|
+
|
|
739
|
+
* `invokableAgents` — agents listed in `invokable_by`
|
|
740
|
+
* `inputArtifactDetails` / `outputArtifactDetails` — resolved artifact records
|
|
741
|
+
|
|
742
|
+
### Handlebars helpers
|
|
743
|
+
|
|
744
|
+
Templates can use these built-in helpers:
|
|
745
|
+
|
|
746
|
+
| Helper | Usage | Description |
|
|
747
|
+
|--------|-------|-------------|
|
|
748
|
+
| `eq` | `{{#if (eq a b)}}` | Strict equality |
|
|
749
|
+
| `notEmpty` | `{{#if (notEmpty obj)}}` | True when object has at least one key |
|
|
750
|
+
| `inc` | `{{inc @index}}` | Increment number by 1 (for 1-based indexing) |
|
|
751
|
+
| `yamlBlock` | `{{{yamlBlock obj}}}` | Render value as YAML-formatted text |
|
|
752
|
+
| `lookupPayloadFields` | `{{#each (lookupPayloadFields payload)}}` | Extract payload field info (name, type, required, enum) |
|
|
753
|
+
| `join` | `{{join arr ", "}}` | Join array elements with separator |
|
|
754
|
+
| `contains` | `{{#if (contains arr "x")}}` | True when array includes value |
|
|
755
|
+
| `groupBy` | `{{#with (groupBy arr "key")}}` | Group array elements by field value |
|
|
756
|
+
| `filterByField` | `{{#each (filterByField arr "field" "val")}}` | Filter array by field match |
|
|
757
|
+
| `keys` | `{{#each (keys obj)}}` | Object keys as array |
|
|
758
|
+
| `values` | `{{#each (values obj)}}` | Object values as array |
|
|
759
|
+
| `size` | `{{size obj}}` | Array length or object key count |
|
|
760
|
+
| `not` | `{{#if (not x)}}` | Boolean negation |
|
|
761
|
+
| `or` | `{{#if (or a b)}}` | Boolean OR (variadic) |
|
|
762
|
+
| `and` | `{{#if (and a b)}}` | Boolean AND (variadic) |
|
|
763
|
+
| `gt` / `gte` / `lt` | `{{#if (gt a b)}}` | Numeric comparisons |
|
|
764
|
+
| `sequenceDiagram` | `{{{sequenceDiagram}}}` | Generate Mermaid sequence diagram from workflow context (requires `workflow` context) |
|
|
765
|
+
|
|
600
766
|
---
|
|
601
767
|
|
|
602
768
|
## Validation model
|