aw-spec-cli 0.1.33 → 0.1.35
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 +76 -81
- package/assets/.appweaver/DESIGN-FORMAT.md +57 -25
- package/assets/.appweaver/STACK-PROFILES.md +95 -60
- package/assets/.appweaver/orchestrator/LAUNCHER.md +1 -1
- package/assets/.appweaver/orchestrator/modules/delta-plan.orch.yaml +173 -32
- package/assets/.appweaver/orchestrator/modules/domain-select.orch.yaml +29 -1
- package/assets/.appweaver/orchestrator/modules/foundation-pack.orch.yaml +7 -4
- package/assets/.appweaver/orchestrator/modules/foundation-spec.orch.yaml +49 -60
- package/assets/.appweaver/orchestrator/modules/tech-select.orch.yaml +58 -0
- package/assets/.appweaver/orchestrator/orchestrator.py +26 -8
- package/assets/.appweaver/orchestrator/rev-templates/delta-design-template.skeleton.md +20 -20
- package/assets/.appweaver/orchestrator/rev-templates/design-template.skeleton.md +22 -48
- package/assets/.appweaver/orchestrator/rev-templates/ui-delta-design-template.skeleton.md +9 -7
- package/assets/.appweaver/orchestrator/rev-templates/ui-design-template.skeleton.md +5 -5
- package/assets/.appweaver/orchestrator/workflows/aw-spec-adopt.orch.yaml +239 -40
- package/assets/.appweaver/orchestrator/workflows/aw-spec-analyze-plan-delta.orch.yaml +254 -43
- package/assets/.appweaver/orchestrator/workflows/aw-spec-analyze-plan.orch.yaml +248 -68
- package/assets/.appweaver/orchestrator/workflows/aw-spec-analyze-slice-delta.orch.yaml +251 -20
- package/assets/.appweaver/orchestrator/workflows/aw-spec-analyze-slice.orch.yaml +316 -10
- package/assets/.appweaver/orchestrator/workflows/aw-spec-build.orch.yaml +6 -47
- package/assets/.appweaver/orchestrator/workflows/aw-spec-close-delta.orch.yaml +62 -16
- package/assets/.appweaver/orchestrator/workflows/aw-spec-finalize-delta.orch.yaml +132 -9
- package/assets/.appweaver/orchestrator/workflows/aw-spec-fix-test-coverage.orch.yaml +965 -0
- package/assets/.appweaver/orchestrator/workflows/aw-spec-implement.orch.yaml +222 -169
- package/assets/.appweaver/orchestrator/workflows/aw-spec-onboard.orch.yaml +21 -22
- package/assets/.appweaver/orchestrator/workflows/aw-spec-plan.orch.yaml +453 -120
- package/assets/.appweaver/orchestrator/workflows/aw-spec-select-lane.orch.yaml +2 -2
- package/assets/.appweaver/orchestrator/workflows/aw-spec-select-stack.orch.yaml +83 -6
- package/assets/.appweaver/orchestrator/workflows/aw-spec-specify.orch.yaml +45 -2
- package/assets/.appweaver/scripts/bash/aw-spec-actions.sh +324 -74
- package/assets/.appweaver/scripts/powershell/aw-spec-actions.ps1 +275 -44
- package/assets/.appweaver/scripts/python/aw-foundation.py +16 -13
- package/assets/.appweaver/scripts/python/aw-gaps.py +11 -3
- package/assets/.appweaver/scripts/python/aw-model-guard.py +295 -0
- package/assets/.appweaver/scripts/python/aw-plan-coverage.py +412 -3
- package/assets/.appweaver/scripts/python/aw-plangate.py +23 -16
- package/assets/.appweaver/scripts/python/aw-stack.py +1794 -265
- package/assets/.appweaver/stack-profiles/dotnet-webapi.json +0 -2
- package/assets/.appweaver/stack-profiles/java-spring.json +0 -2
- package/assets/.appweaver/templates/api-plan-template.md +107 -0
- package/assets/.appweaver/templates/delta-api-plan-template.md +87 -0
- package/assets/.appweaver/templates/delta-design-template.md +25 -23
- package/assets/.appweaver/templates/delta-spec-template.md +3 -3
- package/assets/.appweaver/templates/design-template.md +20 -42
- package/assets/.appweaver/templates/domain-model-template.md +3 -0
- package/assets/.appweaver/templates/ui-delta-design-template.md +11 -8
- package/assets/.appweaver/templates/ui-design-template.md +4 -4
- package/assets/foundations/foundation.spec.template.txt +25 -18
- package/assets/guardrails/README.md +61 -25
- package/assets/guardrails/methodology/ux/accessibility-standards.md +38 -0
- package/assets/guardrails/methodology/ux/content-design.md +34 -0
- package/assets/guardrails/methodology/ux/interaction-states.md +45 -0
- package/assets/guardrails/methodology/ux/journey-mapping.md +41 -0
- package/assets/guardrails/project-specific/domain/domain-requirements.md +25 -38
- package/assets/guardrails/project-specific/domain-rule-bindings.md +33 -69
- package/assets/guardrails/project-specific/frontend/ui-requirements.md +2 -2
- package/assets/guardrails/project-specific/service/technical-requirements.md +2 -2
- package/assets/guardrails/project-specific/tech-rule-bindings.md +16 -13
- package/assets/guardrails/sample-healthcare/domain/domain-requirements.md +58 -0
- package/assets/guardrails/sample-healthcare/domain-rule-bindings.md +138 -0
- package/assets/guardrails/sample-healthcare/frontend/ui-requirements.md +43 -0
- package/assets/guardrails/sample-healthcare/service/technical-requirements.md +40 -0
- package/assets/guardrails/sample-healthcare/tech-rule-bindings.md +303 -0
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +216 -7
- package/dist/commands/init.js.map +1 -1
- package/dist/utils/config.js +1 -1
- package/dist/utils/config.js.map +1 -1
- package/dist/utils/foundation.d.ts +36 -0
- package/dist/utils/foundation.d.ts.map +1 -0
- package/dist/utils/foundation.js +109 -0
- package/dist/utils/foundation.js.map +1 -0
- package/dist/utils/paths.js +1 -1
- package/dist/utils/paths.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -37,7 +37,6 @@ git clone https://dev.azure.com/bytestrone-labs/AppWeaver/_git/appweaver
|
|
|
37
37
|
cd platform/Appweaver.Spec.Cli
|
|
38
38
|
npm install
|
|
39
39
|
npm run build
|
|
40
|
-
# Then run via node
|
|
41
40
|
dist/index.js init
|
|
42
41
|
```
|
|
43
42
|
|
|
@@ -53,18 +52,12 @@ aw-spec init
|
|
|
53
52
|
|
|
54
53
|
# Or specify a target directory
|
|
55
54
|
aw-spec init my-project
|
|
56
|
-
|
|
57
|
-
# Non-interactive (uses Claude skills by default)
|
|
58
|
-
aw-spec init -y
|
|
59
|
-
|
|
60
|
-
# Choose agent explicitly
|
|
61
|
-
aw-spec init --agent antigravity
|
|
62
|
-
aw-spec init --agent kilocode
|
|
63
|
-
|
|
64
|
-
# Preview what would be copied (no changes)
|
|
65
|
-
aw-spec init --dry-run
|
|
66
55
|
```
|
|
67
56
|
|
|
57
|
+
The interactive wizard prompts you to choose:
|
|
58
|
+
- **Project Scaffolding**: Unpacks clean enterprise starter code (Java Spring Boot Hexagonal, .NET WebApi Vertical Slice, or Modular Monolith) without agent folders.
|
|
59
|
+
- **Spec Workflow Setup**: Installs `.aw-spec/` pipelines and AI agent skills (Claude Code, Antigravity, Cursor, KiloCode).
|
|
60
|
+
|
|
68
61
|
After initialization:
|
|
69
62
|
|
|
70
63
|
```bash
|
|
@@ -81,39 +74,20 @@ aw-spec specify "Your feature description"
|
|
|
81
74
|
|
|
82
75
|
### `aw-spec init [directory]`
|
|
83
76
|
|
|
84
|
-
Initialize
|
|
77
|
+
Initialize an AppWeaver project: Project Scaffolding or Spec Workflow Setup.
|
|
85
78
|
|
|
86
79
|
| Option | Description |
|
|
87
80
|
|--------|-------------|
|
|
88
|
-
| `directory` | Target directory (default: current directory) |
|
|
89
|
-
| `-
|
|
90
|
-
| `-
|
|
91
|
-
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
│ ├── feature.json # Feature tracking
|
|
99
|
-
│ ├── workflows/ # Workflow definitions
|
|
100
|
-
│ ├── templates/ # Spec/plan/task templates
|
|
101
|
-
│ └── scripts/ # Bash/PowerShell helpers
|
|
102
|
-
├── docs/ # Documentation scaffold
|
|
103
|
-
│ ├── architecture/
|
|
104
|
-
│ ├── domain/
|
|
105
|
-
│ ├── governance/
|
|
106
|
-
│ ├── security/
|
|
107
|
-
│ ├── domainspecs/
|
|
108
|
-
│ ├── glossary/
|
|
109
|
-
│ ├── VerticalSlice/ # Vertical slice packaging
|
|
110
|
-
│ └── ...
|
|
111
|
-
└── .claude/skills/ # Or .agents/skills/, .kilocode/
|
|
112
|
-
├── aw-spec-specify/
|
|
113
|
-
├── aw-spec-plan/
|
|
114
|
-
├── aw-spec-implement/
|
|
115
|
-
└── ... (13 skills total)
|
|
116
|
-
```
|
|
81
|
+
| `[directory]` | Target directory (default: current directory `.`) |
|
|
82
|
+
| `-i, --intent <intent>` | Action intent: `scaffolding` (Project Scaffolding) or `spec` (Spec Workflow Setup) |
|
|
83
|
+
| `-b, --backend <stack>` | Backend stack: `java-spring`, `dotnet-webapi`, or `none` |
|
|
84
|
+
| `-f, --frontend <stack>` | Frontend stack: `nextjs`, `react-vite`, or `none` |
|
|
85
|
+
| `--foundation <type>` | Foundation type: `hexagonal`, `vertical-slice`, `modular-monolith` |
|
|
86
|
+
| `--app-name <name>` | Application name for scaffolding |
|
|
87
|
+
| `--package <package>` | Root package or namespace |
|
|
88
|
+
| `-a, --agent <agent>` | Agent skills (for spec workflow): `claude`, `antigravity`, `kilocode`, `cursor`, etc. |
|
|
89
|
+
| `-y, --yes` | Skip prompts and use defaults |
|
|
90
|
+
| `--dry-run` | Show what would be created without making changes |
|
|
117
91
|
|
|
118
92
|
### `aw-spec doctor`
|
|
119
93
|
|
|
@@ -152,62 +126,83 @@ Choose based on your AI assistant. Skills provide guided workflows for spec-driv
|
|
|
152
126
|
|
|
153
127
|
## Project Structure (After Init)
|
|
154
128
|
|
|
129
|
+
The resulting structure depends on the chosen intent:
|
|
130
|
+
|
|
131
|
+
### Option A: Project Scaffolding (Clean Application Code)
|
|
132
|
+
|
|
133
|
+
When choosing **Project Scaffolding**, the foundation unpacks directly into your project root. No `.aw-spec/` or AI agent folders are added, keeping the codebase completely clean and standard.
|
|
134
|
+
|
|
135
|
+
**Example: Java Spring Boot — Hexagonal Architecture (`hexagonal`):**
|
|
155
136
|
```
|
|
156
137
|
my-project/
|
|
157
|
-
├──
|
|
158
|
-
│ ├──
|
|
159
|
-
│ ├──
|
|
160
|
-
│ ├──
|
|
161
|
-
│ ├──
|
|
138
|
+
├── src/
|
|
139
|
+
│ ├── main/
|
|
140
|
+
│ │ ├── java/com/mycompany/order/
|
|
141
|
+
│ │ │ ├── domain/ # Enterprise domain models & business rules
|
|
142
|
+
│ │ │ ├── application/ # Use cases, inbound/outbound ports
|
|
143
|
+
│ │ │ └── infrastructure/ # Adapters: Web REST controllers, DB repositories
|
|
144
|
+
│ │ └── resources/
|
|
145
|
+
│ │ └── application.yml
|
|
146
|
+
│ └── test/
|
|
147
|
+
├── pom.xml
|
|
148
|
+
├── mvnw / mvnw.cmd
|
|
149
|
+
└── README.md
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
**Example: .NET WebApi — Vertical Slice Architecture (`vertical-slice`):**
|
|
153
|
+
```
|
|
154
|
+
my-project/
|
|
155
|
+
├── src/
|
|
156
|
+
│ └── OrderService/
|
|
157
|
+
│ ├── Features/ # Self-contained vertical slices (Commands, Queries, Endpoints)
|
|
158
|
+
│ │ └── Orders/
|
|
159
|
+
│ │ ├── CreateOrder/
|
|
160
|
+
│ │ └── GetOrderById/
|
|
161
|
+
│ ├── Common/ # Cross-cutting concerns & behaviors
|
|
162
|
+
│ ├── Program.cs
|
|
163
|
+
│ └── OrderService.csproj
|
|
164
|
+
├── OrderService.sln
|
|
165
|
+
└── README.md
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
---
|
|
169
|
+
|
|
170
|
+
### Option B: Spec Workflow Setup (AI Agent Skills & Orchestration)
|
|
171
|
+
|
|
172
|
+
When choosing **Spec Workflow Setup**, the CLI installs the spec-driven development orchestration files and selected AI agent skills:
|
|
173
|
+
|
|
174
|
+
```
|
|
175
|
+
my-project/
|
|
176
|
+
├── .aw-spec/ # Core spec configuration
|
|
177
|
+
│ ├── extensions.yml # Extension registry
|
|
178
|
+
│ ├── feature.json # Feature tracking
|
|
179
|
+
│ ├── init-options.json # Stored setup configuration
|
|
180
|
+
│ ├── integration.json # Integration settings
|
|
162
181
|
│ ├── workflows/
|
|
163
|
-
│ │ └── workflow-registry.json
|
|
182
|
+
│ │ └── workflow-registry.json # Workflow pipeline definitions
|
|
164
183
|
│ ├── extensions/
|
|
165
184
|
│ │ └── agent-context/
|
|
166
|
-
│
|
|
167
|
-
│ │ └── commands/
|
|
168
|
-
│ ├── templates/
|
|
185
|
+
│ ├── templates/ # Spec, plan, and task templates
|
|
169
186
|
│ │ ├── spec-template.md
|
|
170
187
|
│ │ ├── plan-template.md
|
|
171
188
|
│ │ └── tasks-template.md
|
|
172
|
-
│ ├── scripts/
|
|
173
|
-
│ │ └── bash/
|
|
174
|
-
│ │ └── common.sh
|
|
175
|
-
│ ├── integrations/
|
|
189
|
+
│ ├── scripts/ # Automation & validation scripts
|
|
176
190
|
│ └── memory/
|
|
177
|
-
├── docs/
|
|
191
|
+
├── docs/ # Architecture & governance reference docs
|
|
178
192
|
│ ├── architecture/
|
|
179
193
|
│ ├── domain/
|
|
180
194
|
│ ├── governance/
|
|
181
195
|
│ ├── security/
|
|
182
|
-
│
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
│ │ ├── PACKAGING.md
|
|
189
|
-
│ │ ├── pack-foundation.sh
|
|
190
|
-
│ │ └── unpack-foundation.sh
|
|
191
|
-
│ ├── command.txt
|
|
192
|
-
│ ├── components/
|
|
193
|
-
│ ├── pharma-constitution.my-ref.md
|
|
194
|
-
│ ├── requirement-spec.txt
|
|
195
|
-
│ ├── technology-constitution.md
|
|
196
|
-
│ └── README.md
|
|
197
|
-
└── .claude/skills/ # Or .agents/skills/, .kilocode/
|
|
198
|
-
├── aw-spec-addcomponent/
|
|
199
|
-
├── aw-spec-agent-context-update/
|
|
200
|
-
├── aw-spec-analyze/
|
|
196
|
+
│ └── ...
|
|
197
|
+
└── .agents/skills/ # Or .claude/skills/, .kilocode/
|
|
198
|
+
├── aw-spec-specify/
|
|
199
|
+
├── aw-spec-plan/
|
|
200
|
+
├── aw-spec-implement/
|
|
201
|
+
├── aw-spec-tasks/
|
|
201
202
|
├── aw-spec-checklist/
|
|
202
203
|
├── aw-spec-clarify/
|
|
203
|
-
├── aw-spec-constitution/
|
|
204
204
|
├── aw-spec-foundation/
|
|
205
|
-
|
|
206
|
-
├── aw-spec-plan/
|
|
207
|
-
├── aw-spec-select-domain/
|
|
208
|
-
├── aw-spec-specify/
|
|
209
|
-
├── aw-spec-tasks/
|
|
210
|
-
└── aw-spec-taskstoissues/
|
|
205
|
+
└── ... (13 skills total)
|
|
211
206
|
```
|
|
212
207
|
|
|
213
208
|
---
|
|
@@ -16,6 +16,7 @@ specs/<Context>/
|
|
|
16
16
|
domain-model.md # STRUCTURE — aggregates, entities, invariants (BR-nnn) — shared
|
|
17
17
|
<Aggregate>/
|
|
18
18
|
spec.md # BEHAVIOUR (tech-agnostic) — WHAT / WHY
|
|
19
|
+
api-plan.md # the API CONTRACT — the endpoints the service publishes
|
|
19
20
|
backend-plan.md # structure & decisions (tech-agnostic HLD) — the MEDIATOR
|
|
20
21
|
changes/ # open + archived change records (delta-spec + delta plans)
|
|
21
22
|
```
|
|
@@ -38,8 +39,10 @@ FR/US/SC/CN/DC/IC
|
|
|
38
39
|
|
|
39
40
|
- **One design per feature.** The four clean-architecture layers (Domain,
|
|
40
41
|
Application, API, Infrastructure) are **sections** of this one document, each at
|
|
41
|
-
design level
|
|
42
|
-
|
|
42
|
+
design level — except the endpoints themselves, which are in `api-plan.md` (see
|
|
43
|
+
*The API plan* below); §3 points there. A feature is a capability scope the
|
|
44
|
+
developer chooses — it may act on several aggregates, and several features may act
|
|
45
|
+
on one; its operations are user
|
|
43
46
|
stories inside it. *(This is
|
|
44
47
|
the **greenfield** layout, authored from `design-template.md`. See the Brownfield
|
|
45
48
|
variant below for reverse-engineered / existing-codebase designs.)*
|
|
@@ -67,6 +70,37 @@ FR/US/SC/CN/DC/IC
|
|
|
67
70
|
applied in the `implement` phase. `backend-plan.md` stays feature-specific and
|
|
68
71
|
technology-agnostic.
|
|
69
72
|
|
|
73
|
+
## The API plan (`api-plan.md`)
|
|
74
|
+
|
|
75
|
+
The endpoints a feature's service publishes — route, verb, operation id, request and
|
|
76
|
+
response shapes, the error contract — and its answers to the frontend lane's requests are
|
|
77
|
+
**one document of their own**, `api-plan.md`, beside the backend plan. It is the API
|
|
78
|
+
contract between the lanes: the frontend plan binds to its operation ids, `implement`
|
|
79
|
+
serves it, and `contract-draft` writes `api-draft.json` from it by script. The backend plan
|
|
80
|
+
realises each endpoint as a use-case and names it under the endpoint's **Maps to**.
|
|
81
|
+
|
|
82
|
+
- **A master, like `spec.md`.** A change plans its API in
|
|
83
|
+
`changes/<CR-id>/delta-api-plan.md` — a Contract deltas table (one row per endpoint
|
|
84
|
+
`added`, `changed` or `removed`), each added or changed endpoint written whole, and the
|
|
85
|
+
requests the change answers — and `finalize-delta` merges it into `api-plan.md` by script
|
|
86
|
+
(`contract-merge`), by whole endpoint block keyed by operation id. The backend plan is
|
|
87
|
+
derived and never merged; the API plan is merged, so what a change adds or changes is in
|
|
88
|
+
the document every redraw reads from the moment the change is merged.
|
|
89
|
+
- **One form in every project.** Each endpoint is a block under `## Endpoints`: the heading
|
|
90
|
+
`### `VERB /route`` and its fields, every shape `{ field: type }`. The contract scripts
|
|
91
|
+
read exactly that form, so it is the kit's template (`api-plan-template.md`,
|
|
92
|
+
`delta-api-plan-template.md`) in greenfield and brownfield repos alike; an override
|
|
93
|
+
generated by `onboard` shapes the backend plan, never the API plan.
|
|
94
|
+
- **Operation ids are stable.** An endpoint keeps its id for life; a new one takes an id
|
|
95
|
+
unique across the service. An endpoint the code already serves keeps the id the code
|
|
96
|
+
publishes, and one it serves under no id writes `—`, never an invented id.
|
|
97
|
+
- **Authored first.** `plan` writes the API plan before the backend plan on both paths —
|
|
98
|
+
the master, and a change's delta — so the contract is fixed before what realises it.
|
|
99
|
+
- **Features planned before it** keep their endpoints in the backend plan's API section,
|
|
100
|
+
which every reader falls back to while no `api-plan.md` exists. A re-derivation
|
|
101
|
+
(`plan main`) offers to move them once, by script (`api-split`), and `finalize-delta`
|
|
102
|
+
moves them when it first merges a change's API into the feature.
|
|
103
|
+
|
|
70
104
|
## Brownfield variant (existing codebases)
|
|
71
105
|
|
|
72
106
|
A design reverse-engineered from — or added forward to — an **existing** codebase is
|
|
@@ -82,18 +116,14 @@ same traceability spine and the two deferral ledgers — with **one difference t
|
|
|
82
116
|
are **derived from the code's own organisation** (its folders / projects / modules)
|
|
83
117
|
rather than the fixed Domain/Application/API/Infrastructure four. A component the
|
|
84
118
|
code has that fits no textbook layer (a UI tier, a worker, a host project) gets its
|
|
85
|
-
own section; a layer the code lacks does not appear.
|
|
119
|
+
own section; a layer the code lacks does not appear. Two neutral anchors are kept
|
|
86
120
|
because every system has them and the tooling keys on them: **§1 is the domain/data
|
|
87
|
-
model** (the cross-reference tool reads it for `<Other>Id` reference edges), one
|
|
121
|
+
model** (the cross-reference tool reads it for `<Other>Id` reference edges), and one
|
|
88
122
|
**§2 subsection is the External Integrations table** (matched by heading keyword, so
|
|
89
|
-
`aw-xref` extracts contract edges from either layout)
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
draft is written from the headings, and the request ledger between the two lanes reads
|
|
94
|
-
the operation ids and the table. An endpoint the code already serves keeps the id it
|
|
95
|
-
publishes; where it publishes none the plan writes `—` and records a §5 assumption,
|
|
96
|
-
never an invented id. The `debt` ledger records
|
|
123
|
+
`aw-xref` extracts contract edges from either layout). The published endpoints are not
|
|
124
|
+
in the plan at all: they are in the feature's `api-plan.md`, whose form is the same in
|
|
125
|
+
every project (see *The API plan* above), and the §2 axis that publishes them ends with
|
|
126
|
+
a line pointing there. The `debt` ledger records
|
|
97
127
|
only debt the **code itself** evidences (stubs, dead code, torn seams) — being
|
|
98
128
|
organised unlike a reference architecture is **not** debt, it is the as-built shape;
|
|
99
129
|
migrating toward a target is a separate modernization decision.
|
|
@@ -129,7 +159,7 @@ states it can be in, and the framework binds in the FRONTEND LANE of `implement`
|
|
|
129
159
|
|
|
130
160
|
**§5 Contract Binding is the lane boundary.** The UI design reads the whole spec — the
|
|
131
161
|
experience is stated there — but only the service's **published surface**: the spec's `IC-`
|
|
132
|
-
ids and the
|
|
162
|
+
ids and the endpoints `api-plan.md` states. No table, handler or persistence choice
|
|
133
163
|
crosses that line, and an operation the experience needs that the surface does not offer is
|
|
134
164
|
a contract delta raised back to the service lane, never a client workaround. ⌛ `design`
|
|
135
165
|
will emit that surface as a `design-contract.md` projection; the rule does not change when
|
|
@@ -138,11 +168,11 @@ it does, only what §5 reads.
|
|
|
138
168
|
**Contract deltas are a request ledger between the two plans.** frontend-plan.md §5 "Contract
|
|
139
169
|
deltas needed" is a table, one `RQ-n` per operation the experience needs and the surface does
|
|
140
170
|
not offer, with the operation id and field shapes it proposes; a request keeps its id for
|
|
141
|
-
life.
|
|
171
|
+
life. api-plan.md answers each in its "Requests from the frontend lane" table —
|
|
142
172
|
`published` under an operation id, or `declined` with the reason — so each lane's developer
|
|
143
|
-
writes only their own
|
|
173
|
+
writes only their own plans. `contract-requests` reads both: an open request is a backend-lane
|
|
144
174
|
gap at `analyze-plan`, a declined one or an answered one not yet re-bound is a frontend-lane
|
|
145
|
-
gap. With no
|
|
175
|
+
gap. With no API plan at all, every binding is a request.
|
|
146
176
|
|
|
147
177
|
**`UX-` lives here and only here.** The service design excludes the spec's Experience
|
|
148
178
|
Standards by contract — it realises no experience standard, and a traceability row for one
|
|
@@ -198,16 +228,18 @@ backend-plan.md:
|
|
|
198
228
|
|
|
199
229
|
- `CreateOrder` = US-1; `UpdateOrder` = US-2.
|
|
200
230
|
- Adding `UpdateOrder` is an additive CR: a **delta-spec** (`+US-2`), the change's own
|
|
201
|
-
**model delta** where the domain moves,
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
`
|
|
206
|
-
`backend-plan.md
|
|
207
|
-
|
|
231
|
+
**model delta** where the domain moves, a **delta API plan** (the `UpdateOrder` endpoint,
|
|
232
|
+
`added` — see `delta-api-plan-template.md`) and **delta lane plans** (`ADDED` the new
|
|
233
|
+
use-case, `MODIFIED` the shared Order/root and repository sections — see
|
|
234
|
+
`delta-design-template.md`). All of them live inside `changes/<CR-id>/`, and the
|
|
235
|
+
MASTERS are not touched while the change is open: `plan` writes `delta-api-plan.md`,
|
|
236
|
+
`delta-backend-plan.md` and `delta-frontend-plan.md` beside the delta-spec, never
|
|
237
|
+
`api-plan.md` or `backend-plan.md`. `implement` generates only what the delta marks
|
|
238
|
+
ADDED or MODIFIED; regression re-tests the shared-file dependents.
|
|
208
239
|
- **Nothing in the plan phase bumps a version or archives a change.** `finalize-delta`
|
|
209
|
-
MERGES the delta into `spec.md
|
|
210
|
-
plans — they are derived from those
|
|
240
|
+
MERGES the delta into `spec.md`, the context's `domain-model.md` and `api-plan.md` (not
|
|
241
|
+
the lane plans — they are derived from those three and are re-derived by
|
|
242
|
+
`/appweaver plan main`),
|
|
211
243
|
and `close-delta` is the sole stage that archives `changes/<CR-id>/` and moves the
|
|
212
244
|
version (`v1.0 → v1.1`). The two are deliberately separate so a red `analyze-slice`
|
|
213
245
|
between them is still "fix and re-run" rather than a change that already shipped.
|
|
@@ -56,9 +56,10 @@ no heading to key on. Where the two lanes are folded into one command, as `plan`
|
|
|
56
56
|
| `run_from` | *(optional)* **where the commands run**: `repo` (the default, and the shape of every lane written before this key existed) at the repository root, or `root` inside the lane root folder. `select-stack` decides it from where the stack's build file sits — see §3.1 |
|
|
57
57
|
| `build` / `test` / `run` | project-supplied command strings the engine shells out to. These are the matched **profile's** defaults and may not fit a legacy layout — reviewing them is what `select-stack` is for. `{{root}}` in a command resolves to this lane's `root`, as seen from where the command runs (§4.2) |
|
|
58
58
|
| `migrate` | *(optional)* the lane's schema-migration command, recorded only when the profile declares one. Absent, `run-migrate` falls back to `dotnet ef` and otherwise reports that nothing ran (§4.2) |
|
|
59
|
-
| `
|
|
60
|
-
| `
|
|
61
|
-
| `
|
|
59
|
+
| `contract_write` | *(optional, backend)* a command that writes the service's as-built API document to `{{contract}}` with no server started, which `analyze-slice` runs to check the API the code serves against the plan (§4.5). `foundation` sets it from a pack's `<pack>.lane.json` or a spec's header, or asks for it on the spec route |
|
|
60
|
+
| `contract_run` | *(optional, backend)* or: the command that starts the service on its own so its document can be fetched (§4.5). `foundation` sets it from a pack's `<pack>.lane.json` or a spec's header |
|
|
61
|
+
| `contract` | *(optional, backend)* with `contract_run`: the URL the running service serves its API document at (§4.5) |
|
|
62
|
+
| `client` | *(optional, frontend)* the command that generates the frontend's API client from the API document; `{{contract}}` in it is the document's path. No shipped profile has one: `implement` asks the developer the first time and records the answer here (§4.5) |
|
|
62
63
|
|
|
63
64
|
### Three properties matter more than the schema
|
|
64
65
|
|
|
@@ -218,11 +219,11 @@ behaviour from before the file existed.
|
|
|
218
219
|
|
|
219
220
|
| Phase | With a working lane narrower than the declared lanes |
|
|
220
221
|
|---|---|
|
|
221
|
-
| `plan` | scaffolds, authors, re-derives and delta-plans only the working lane; the menu and the re-derive question look only at its master. The
|
|
222
|
-
| `analyze-plan` | gates, repairs and receipts only the working lane's
|
|
223
|
-
| `implement` | offers, receipt-checks and generates only the working lane; a refused receipt skips that lane with the reason. The backend half
|
|
224
|
-
| `build` | compiles only the working lane (`build-compile --kind`); `lane-verify --working-only` does not require the other lane's root on disk
|
|
225
|
-
| `analyze-slice` | tests only the working lane (`test-run --kind`); the fix loops' file list is narrowed with `concept-paths --under`; the composition pass
|
|
222
|
+
| `plan` | scaffolds, authors, re-derives and delta-plans only the working lane; the menu and the re-derive question look only at its master. The frontend plan binds to the API plan (`api-plan.md`), the backend lane's published surface, and never reads the backend plan. The backend half writes the API plan first — answering the frontend's open contract requests there — and `api-draft.json` from it; the frontend half re-binds answered requests and raises new ones (§4.5) |
|
|
223
|
+
| `analyze-plan` | gates, repairs and receipts only the working lane's documents (`.aw-plan-gate.<lane>.json`, that lane's verdict; the backend's covers `api-plan.md` too); check 3 reads the API plan, the frontend plan and the request ledger, and a finding only the other lane can close is reported for its developer (`plan-gaps --lanes` → `other`). The frontend receipt also hashes `api-plan.md`, so a contract change re-gates the frontend |
|
|
224
|
+
| `implement` | offers, receipt-checks and generates only the working lane; a refused receipt skips that lane with the reason. The backend half serves every endpoint of `api-plan.md` as written; the frontend half binds to the features' drafts, combined, and never starts the service (§4.5) |
|
|
225
|
+
| `build` | compiles only the working lane (`build-compile --kind`); `lane-verify --working-only` does not require the other lane's root on disk |
|
|
226
|
+
| `analyze-slice` | tests only the working lane (`test-run --kind`); the fix loops' file list is narrowed with `concept-paths --under`; the composition pass and the API check — the built service against the API plan (§4.5) — run when the backend is worked |
|
|
226
227
|
| `specify`, `finalize-delta`, `close-delta` | **ignore it** — the spec is written whole, and a change merges and closes with whatever its lanes delivered |
|
|
227
228
|
|
|
228
229
|
**A change records the lanes it touches**, separately from anyone's working lane: the
|
|
@@ -292,9 +293,11 @@ workflow.**
|
|
|
292
293
|
"host_patterns": [], // optional — where the runnable project sits, for
|
|
293
294
|
// `{{host}}` in a command — see §4.2
|
|
294
295
|
"migrate": "", // optional — schema migration, if the stack has one
|
|
295
|
-
"
|
|
296
|
-
//
|
|
297
|
-
"
|
|
296
|
+
"contract_write": "", // optional, backend — write the as-built API
|
|
297
|
+
// document to {{contract}} — see §4.5
|
|
298
|
+
"contract_run": "", // optional, backend — or start the service to
|
|
299
|
+
// fetch it …
|
|
300
|
+
"contract": "", // … from this URL
|
|
298
301
|
"client": "", // optional, frontend — generate the API client
|
|
299
302
|
// from `{{contract}}` — see §4.5
|
|
300
303
|
"prototype_run": "npm run dev --prefix prototype", // frontend only — fills the prototype block
|
|
@@ -514,53 +517,78 @@ A layout the table gets wrong is fixed by writing `test_root` on the lane in `st
|
|
|
514
517
|
| `go-chi` | `backend/` | *(inside the lane root folder)* | `internal/` | — |
|
|
515
518
|
| every frontend | `frontend/` | *(inside the lane root folder)* | `web/` | — |
|
|
516
519
|
|
|
517
|
-
### 4.5 `contract_run`, `contract` and `client` — the API
|
|
518
|
-
|
|
519
|
-
The
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
`
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
520
|
+
### 4.5 `contract_write`, `contract_run`, `contract` and `client` — the API between the lanes
|
|
521
|
+
|
|
522
|
+
**The contract between the lanes is the API plan.** Each feature's `api-plan.md`, beside its
|
|
523
|
+
backend plan, states the endpoints the service publishes — route, verb, operation id, field
|
|
524
|
+
shapes, errors — in one form in every project, so the scripts read it the same way on every stack.
|
|
525
|
+
The frontend lane binds to those endpoints, drafted from the API plan by script, and the built
|
|
526
|
+
service is checked against that document rather than read from. So the frontend works the same on
|
|
527
|
+
every stack and in a brownfield repo, can be built before the backend is, and never needs the
|
|
528
|
+
service's code built, started or its runtime installed. The API plan is a master: a change plans
|
|
529
|
+
its API in `changes/<CR-id>/delta-api-plan.md`, and `finalize-delta` merges it in by script. A
|
|
530
|
+
feature planned before API plans existed keeps its endpoints in its backend plan's API section,
|
|
531
|
+
which every step below reads instead until `api-split` moves them out. Every step warns rather
|
|
532
|
+
than stops, except the backend gates' check and the merge:
|
|
533
|
+
|
|
534
|
+
1. **Draft** (`contract-draft`) — run by the backend lane's `plan` and `analyze-plan`, and by
|
|
535
|
+
`adopt`: `api-plan.md` drafted by script into `specs/<ctx>/<feature>/api-draft.json`.
|
|
536
|
+
Committed with the plan. A shape not written as `{ field: type }` is reported, since the
|
|
537
|
+
frontend's client gets it untyped, and so is an operation the previous draft had and this one
|
|
538
|
+
does not.
|
|
539
|
+
2. **Draft a change** (`contract-draft --cr`) — run by `plan` and `analyze-plan-delta` on a
|
|
540
|
+
change: the endpoints its `delta-api-plan.md` adds or changes, written as full blocks, and the
|
|
541
|
+
ones it removes, into `changes/<CR-id>/api-draft.json`.
|
|
542
|
+
3. **Merge** (`contract-merge`) — run by `finalize-delta`: the change's delta API plan merged
|
|
543
|
+
into `api-plan.md` by whole endpoint block, keyed by operation id, with the requests it
|
|
544
|
+
answers; `api-draft.json` is redrawn from the result. A run that does not answer stops
|
|
545
|
+
`finalize-delta` with the command that finishes it, and `close-delta` will not archive a
|
|
546
|
+
change whose API delta `api-plan.md` has not recorded (`contract-merge --check`).
|
|
547
|
+
4. **Combine** (`contract-combine`) — run by the frontend half of `implement`: every feature's
|
|
548
|
+
draft with each open change's applied over it, written to
|
|
549
|
+
`.appweaver/contracts/openapi.combined.json` (not committed). An operation an open change
|
|
550
|
+
removes stays, marked `deprecated` with the change that removes it, so a frontend still bound
|
|
551
|
+
to it is told rather than broken. Where an open change serves another operation on its
|
|
552
|
+
route, that one takes the route, and the removed one moves to the document's `x-aw-removed`
|
|
553
|
+
list with its route and change, so a binding to it is still reported as removed.
|
|
554
|
+
5. **Client** (`contract-client --doc`) — run the frontend lane's `client` command, with
|
|
540
555
|
`{{contract}}` standing for the combined document as seen from where the command runs.
|
|
541
|
-
|
|
542
|
-
`operationId` in the combined document; the ids
|
|
556
|
+
6. **Check** (`contract-check`) — every operation id the frontend plan cites must be an
|
|
557
|
+
`operationId` in the combined document; the ids an open change removes, and those the
|
|
558
|
+
service does not serve yet, are named apart.
|
|
559
|
+
7. **Verify** (`contract-export` + `contract-verify`) — run by the backend gates: after its fix
|
|
560
|
+
loops `analyze-slice` writes the service's AS-BUILT document to
|
|
561
|
+
`<service lane root folder>/contracts/openapi.json` and compares it with the feature's draft
|
|
562
|
+
(plus a change merged and not yet closed); `analyze-slice-delta` does it for the change's own
|
|
563
|
+
draft. A planned endpoint not served, or served under another route, verb or operation id,
|
|
564
|
+
fails the gate; a field or status code that differs warns. A feature whose plan names no
|
|
565
|
+
endpoint, or a change that drafts no API change, is not checked and the lane's export is
|
|
566
|
+
not run (`contract-verify --check` asks first). Committed, the as-built document
|
|
567
|
+
also adds the operations no plan describes to the frontend's combined document, marked
|
|
568
|
+
`x-aw-unplanned` — the endpoints of a brownfield feature nobody has adopted yet.
|
|
543
569
|
|
|
544
570
|
Between the plans, what the frontend needs and the backend does not publish travels as a
|
|
545
571
|
**request ledger**: `frontend-plan.md` §5 "Contract deltas needed" holds one `RQ-n` per
|
|
546
|
-
request, and `
|
|
572
|
+
request, and `api-plan.md` "Requests from the frontend lane" answers each —
|
|
547
573
|
published under an operation id, or declined. `contract-requests` reads both (§6).
|
|
548
574
|
|
|
549
|
-
|
|
550
|
-
|
|
575
|
+
**How the as-built document is written is the lane's setting**, because only the project knows
|
|
576
|
+
it, and a lane that sets none is simply not checked:
|
|
551
577
|
|
|
552
|
-
| Key |
|
|
578
|
+
| Key | What it is | Set on the lane by |
|
|
553
579
|
|---|---|---|
|
|
554
|
-
| `
|
|
555
|
-
| `contract` |
|
|
556
|
-
| `client` |
|
|
580
|
+
| `contract_write` | a command that writes the service's OpenAPI JSON to `{{contract}}` with no server started — the stack's own generator, or a script that loads the application and dumps its document (a FastAPI app's `app.openapi()`, for instance). Preferred: nothing of the service runs. It writes to a scratch path, and only a document that reads as OpenAPI replaces the committed one | `foundation`: from the pack's `<pack>.lane.json`; on the spec route from the spec's `# contract-write:` header line, or the operator's answer when the header gives no way |
|
|
581
|
+
| `contract_run` + `contract` | start the service on its own, fetch its document from the URL, stop it and everything it started. For a stack that can only serve its document; a service already answering at the URL is used, and said to maybe be older than the code. Starting a service runs its startup code — the shipped .NET packs migrate a local SQLite file | `foundation`: from the pack's `<pack>.lane.json` (the shipped packs set these), or the spec's `# contract-run:` / `# contract:` header lines |
|
|
582
|
+
| `client` | the frontend's client generator | `foundation` on the spec route, from the `# client:` header line or the operator's answer; else `implement`, which asks the first time and records the answer |
|
|
557
583
|
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
584
|
+
No stack profile sets a way to write the document: starting a service runs whatever its
|
|
585
|
+
configuration points at, so the kit never does it unless the project says so. Each key is still
|
|
586
|
+
read from the lane first and from its profile second, so a project's own profile may carry one.
|
|
587
|
+
`foundations/foundation.spec.template.txt` shows the header lines; `<App>` in them is the app name
|
|
588
|
+
given at `foundation`.
|
|
561
589
|
|
|
562
590
|
`--environment Development` matters for the .NET packs: outside Development they redirect
|
|
563
|
-
to HTTPS, and
|
|
591
|
+
to HTTPS, and `contract-export` fetches over http. Their API projects also read
|
|
564
592
|
`ConnectionStrings:SqliteConnection` when started without the AppHost, and the packs'
|
|
565
593
|
configuration carries none, so their commands pass one. A pack's `<pack>.lane.json` sits
|
|
566
594
|
beside its `.pack.txt`, names the pack's sentinel the way its files do, and is renamed with
|
|
@@ -584,10 +612,10 @@ grep -rl "lane-declare" .appweaver/orchestrator/workflows/ # must print exactl
|
|
|
584
612
|
# aw-spec-select-stack.orch.yaml — a person picks
|
|
585
613
|
```
|
|
586
614
|
|
|
587
|
-
**`lane-set` changes
|
|
588
|
-
`contract_run`, `contract` and `client` (§4.5). Its callers are
|
|
589
|
-
what a pack knows about
|
|
590
|
-
command a developer types. They cannot use `lane-declare`, which rebuilds the whole lane
|
|
615
|
+
**`lane-set` changes four keys on a lane that is already there, and nothing else** —
|
|
616
|
+
`contract_write`, `contract_run`, `contract` and `client` (§4.5). Its callers are
|
|
617
|
+
`foundation`, recording what a pack or a spec knows about writing its service's API
|
|
618
|
+
document, and `implement`, recording the client command a developer types. They cannot use `lane-declare`, which rebuilds the whole lane
|
|
591
619
|
and would reset every command on it to the profile's default.
|
|
592
620
|
|
|
593
621
|
`onboard` used to be a second caller. Before `select-stack` was the first command of the
|
|
@@ -689,15 +717,19 @@ implementation and the twins cannot drift.
|
|
|
689
717
|
|---|---|
|
|
690
718
|
| `stack-list [--kind k] [--preselect text] [--include-none] [--suggest]` | enumerate the installed profiles; returns `select_options[]`, and `preselect` when the text names one of *this kind's* ids. `--suggest` also runs detection, so the menu **leads with** the stack this repo's files point at and `root_options[]` leads with the directory the evidence sits in |
|
|
691
719
|
| `stack-detect [--kind k] [--exclude-root p]…` | match the repo's OWN files against the installed profiles — the brownfield candidate list, since an existing repo already answered the question. Writes nothing. `--exclude-root` keeps a service profile from relocating onto a subtree another lane owns |
|
|
720
|
+
| `stack-rules --kind k [--declared]` | for each profile of the kind, how many of the files the active project's `tech-rule-bindings.md` names under `guardrails/technology/{{<kind>_stack}}/` exist with that profile put in, resolved with `resolve-tech`'s placeholder table: `complete`, `partial`, `none`, or `not-mapped` when the map names no stack folder for the lane. `note` is the line `select-stack` puts in the menu; `--declared` adds the declared lane's verdict, `ok`, and the `warning` `select-stack` raises when it is partial or none. Read-only (§7) |
|
|
692
721
|
| `lane-declare --profile <id\|label\|none\|detected> [--kind k] [--id lane] [--source-path\|--root p] [--stack label] [--origin declared\|reverse-engineered] [--build/--test/--run/--migrate c] [--run-from repo\|root] [--no-prototype] [--require-existing-root]` | upsert a WHOLE lane — its one caller is `select-stack` (§5). `detected` declares a stack the kit ships no profile for (needs `--stack` and a lane root folder), which is how a legacy WebForms, JSP or ERB lane gets recorded at all |
|
|
693
|
-
| `lane-set (--id lane\|--kind k) [--set KEY=VALUE]… [--unset KEY]…` | change only `contract_run`, `contract` or `client` on a lane already declared, leaving the rest of it alone. An empty VALUE changes nothing; `--unset` puts the key back on the profile's value. Called by `foundation` (a pack's lane settings) and `implement` (the client command a developer supplies) — re-declaring would reset every other command |
|
|
694
|
-
| `contract-export [--timeout s]` |
|
|
695
|
-
| `contract-draft --feature-dir p` | draft `api-draft.json` beside the feature's plans from `
|
|
696
|
-
| `contract-
|
|
697
|
-
| `
|
|
698
|
-
| `contract-
|
|
699
|
-
| `contract-
|
|
700
|
-
| `contract-
|
|
722
|
+
| `lane-set (--id lane\|--kind k) [--set KEY=VALUE]… [--unset KEY]…` | change only `contract_write`, `contract_run`, `contract` or `client` on a lane already declared, leaving the rest of it alone. An empty VALUE changes nothing; `--unset` puts the key back on the profile's value. Called by `foundation` (a pack's lane settings) and `implement` (the client command a developer supplies) — re-declaring would reset every other command |
|
|
723
|
+
| `contract-export [--timeout s]` | write the service lane's as-built API document to `<service root>/contracts/openapi.json`: run its `contract_write` command (to a scratch path, kept only when it reads as OpenAPI), or start the service with `contract_run`, fetch `contract` and stop it and everything it started. Returns the `way` used and, on a failure, its `cause`; a lane with neither writes nothing (`cause: no-way`) (§4.5) |
|
|
724
|
+
| `contract-draft --feature-dir p [--cr id]` | draft `api-draft.json` beside the feature's plans from `api-plan.md` (for a feature planned before it, the backend plan's API section), by script: each `### \`VERB /route\`` endpoint with its operation id, request and response field shapes (conceptual types → JSON schema, a use case's DTO standing in for a named shape) and error statuses with their body shapes. `unread` lists the shapes it could not type, and `dropped` the operations the draft it replaced had. Rewritten only when it differs; removed when the plan names no endpoint. With `--cr`, the change's draft in its change folder, from its `delta-api-plan.md` (§4.5) |
|
|
725
|
+
| `contract-merge --feature-dir p --cr id` | merge the change's `delta-api-plan.md` into the feature's `api-plan.md` — whole endpoint blocks keyed by operation id (verb and route for a block with none, which is written with the id its row or the block it replaces gives that route): changed ones replaced, added ones after the last, removed ones deleted, a Contract deltas row with no block written from the row and reported (never over a block the change wrote on the same route) — plus the requests it answers and a `(pending)` Change History row; redraws `api-draft.json` and reports what it dropped. A feature with no `api-plan.md` has its backend plan's API moved into one first. A second run changes nothing. `finalize-delta`'s call (§4.5). With `--check` it writes nothing and reports `needed` — the change carries an API delta `api-plan.md` has no Change History row for — which `close-delta` asks before it archives |
|
|
726
|
+
| `api-split --feature-dir p [--check] [--cr id]` | move a feature's endpoint blocks and requests table out of its backend plan into a new `api-plan.md`, leaving one line where they were, and redraw `api-draft.json`. `--check` only reports whether the backend plan still carries the API (`needed`); `--cr` checks a change's delta backend plan the same way. `plan main` offers it |
|
|
727
|
+
| `contract-combine` | write `.appweaver/contracts/openapi.combined.json`: every feature's draft with each open change's applied — added, replaced, or marked `deprecated` with `x-aw-removed-by`, or, where an open change serves another operation on its route, listed in the document's `x-aw-removed` — plus, from a committed as-built document, the operations no plan describes (`x-aw-unplanned`), and `x-aw-unserved` on planned ones it does not serve. `ok:false` with a reason when there is nothing (§4.5) |
|
|
728
|
+
| `contract-requests --feature-dir p` | the request ledger: the frontend plan's `RQ-n` rows against the API plan's answers — `open`, `published` (and whether the frontend still has to re-bind), `declined` — with one line per lane's to-do for a prompt to quote |
|
|
729
|
+
| `contract-client [--doc d]` | `run-phase --phase client` for the frontend lane — its `client` command, `{{contract}}` expanded to `--doc` (`implement` passes the combined document), else to the as-built one |
|
|
730
|
+
| `contract-check --plan p [--doc d]` | the operation ids a frontend plan cites (its §5 `Operation id` column, or a delta plan's `Contract Binding` rows; never the request table) against the combined document's `operationId`s — by script, no model. Also names the cited ids an open change removes, the service does not serve yet, and the service serves with no plan describing them |
|
|
731
|
+
| `contract-impact --delta-backend p --frontend-plan p [--delta-frontend p]` | the operations a change's API delta marks `changed` or `removed` in its "Contract deltas for the frontend lane" table — the `delta-api-plan.md` beside the delta backend plan when there is one — that the frontend master plan binds to, and which of them the change's frontend delta plan does not name (`unaddressed[]`) — `analyze-plan-delta`'s warning. By script, no model |
|
|
732
|
+
| `contract-verify --feature-dir p [--cr id] [--doc d] [--check]` | the as-built document against the operations the feature's draft names, with any change merged into its spec and not yet closed applied — or, with `--cr`, against that change's draft alone. `missing`, `moved`, `renamed` and `still_served` are findings (`ok:false`) — a removed operation is still served when its id is, or its route is answered while the plan keeps no other operation on it; differing fields and status codes, and served operations no plan describes, are the `warning`. `checked:false` with a `note` when there is nothing to check against. `--check` reads no as-built document and reports `needed` — the plan names something to check — which the gates ask before they write the document. By script, no model |
|
|
701
733
|
| `lane-resolve [--kind k] [--id lane] [--feature-dir p]` | read; exit 0 always. `exists` reports the file, `declared` reports the lanes — the shipped-but-unfilled seed is `exists:true, declared:false`. Returns the matched lane **and** both kinds flattened — `backend_source_path`, `frontend_root_exists`, `backend_build` … — so a workflow binds one variable instead of calling twice — and the working-lane fields of §2a |
|
|
702
734
|
| `lane-verify [--require backend\|frontend]… [--allow-missing-root] [--working-only] [--command phase]` | **the gate**: is the declaration usable for the phase about to run. Never writes, and **always exits 0** — the calling workflow's `verify_context` owns the stop, so the reason arrives as text. `--working-only` checks on disk only the working lanes' root folders and the required kinds (§2a). Whatever the flags, `kinds_on_disk[]` lists the kinds whose lane root folder exists and `missing_roots` the issue each declared lane without one raises when `--allow-missing-root` is not passed |
|
|
703
735
|
| `lane-select [--lane backend\|frontend\|both] [--default] [--preselect text]` | read or write `.appweaver/lane.json` (§2a). No argument reads it and returns the `select_options[]` the declared stacks offer; `--lane` writes one of them; `--default` writes the default — `select-stack`'s call |
|
|
@@ -745,7 +777,10 @@ they are content the kit cannot invent:
|
|
|
745
777
|
- **Technical rules** — a corpus at `guardrails/technology/<id>/`, mapped from the project's
|
|
746
778
|
`tech-rule-bindings.md` (§7a). Until one exists the stack runs with the universal
|
|
747
779
|
`ai-rules.md` and the technical constitution, which is the greenfield-safe default, not an
|
|
748
|
-
error.
|
|
780
|
+
error. It is said, not left to be discovered: `select-stack`'s menu names the stacks the
|
|
781
|
+
active map has rule files for, a lane declared on a stack with none or only some of them
|
|
782
|
+
raises a warning (`stack-rules`), and each later phase reports the missing folder once
|
|
783
|
+
rather than file by file.
|
|
749
784
|
- **A foundation pack or spec** — `foundations/<ecosystem>/<Name>/`, only if you want
|
|
750
785
|
`/appweaver foundation` to offer one for this stack (give it `# kind:` / `# profiles:`
|
|
751
786
|
header lines). Without one, `foundation` still offers `[manual spec]` for the lane, and
|
|
@@ -81,7 +81,7 @@ If the user names a strategy your row does not support — or you have no row an
|
|
|
81
81
|
- If `pending.note` is present, your previous response was rejected — follow the note and rewrite `response_path`.
|
|
82
82
|
|
|
83
83
|
4. **Report**:
|
|
84
|
-
Report the final JSON (`status`, `outputs`, and any `reason`) to the user. On `stopped`, relay the gate message verbatim — it tells the user what to fix or run first.
|
|
84
|
+
Report the final JSON (`status`, `outputs`, and any `reason`) to the user. On `stopped`, relay the gate message verbatim — it tells the user what to fix or run first. Relay every entry of `warnings` too, verbatim and one per line, on `ok` and on `stopped` alike: each is a check that failed and let the run continue — a lane skipped, a rule file not loaded, a document not exported — and the run log that also shows it is not printed under `--json`.
|
|
85
85
|
|
|
86
86
|
## Adding an agent
|
|
87
87
|
|