aw-spec-cli 0.1.32 → 0.1.34
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 +56 -17
- 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 -16
- package/assets/.appweaver/orchestrator/rev-templates/design-template.skeleton.md +30 -6
- 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 +341 -36
- 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 +28 -12
- package/assets/.appweaver/orchestrator/workflows/aw-spec-plan.orch.yaml +453 -116
- package/assets/.appweaver/orchestrator/workflows/aw-spec-select-lane.orch.yaml +7 -4
- 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
|
@@ -16,7 +16,10 @@
|
|
|
16
16
|
# still READ the other lane where they need it: a frontend plan binds to the backend
|
|
17
17
|
# plan's published surface, which the backend developer owns. specify, finalize-delta and
|
|
18
18
|
# close-delta do NOT follow it: the spec is written whole, from its rules and standards,
|
|
19
|
-
# and a change merges and closes with whatever its lanes have delivered.
|
|
19
|
+
# and a change merges and closes with whatever its lanes have delivered. Brownfield adopt
|
|
20
|
+
# does not follow it either: it reverses a feature once, every half its code has, because
|
|
21
|
+
# it cannot run a second time for the other lane, so the other lane's developer finds
|
|
22
|
+
# their plan already written.
|
|
20
23
|
#
|
|
21
24
|
# THE OPTIONS COME FROM stacks.json. Both lanes declared → backend, frontend and both.
|
|
22
25
|
# One lane declared → that lane only, picked without a question (there is nothing to
|
|
@@ -32,8 +35,8 @@
|
|
|
32
35
|
# =============================================================================
|
|
33
36
|
|
|
34
37
|
name: aw-spec-select-lane
|
|
35
|
-
description: Choose the lane this developer works on — backend, frontend or both — and store it in .appweaver/lane.json, which is not committed, so each developer keeps their own. The options come from the stacks declared in .appweaver/stacks.json, all three when both lanes are declared and only the declared one otherwise. plan, analyze-plan, implement, build and analyze-slice then write only that lane while still reading the other; specify, finalize-delta
|
|
36
|
-
version: 1.0.
|
|
38
|
+
description: Choose the lane this developer works on — backend, frontend or both — and store it in .appweaver/lane.json, which is not committed, so each developer keeps their own. The options come from the stacks declared in .appweaver/stacks.json, all three when both lanes are declared and only the declared one otherwise. plan, analyze-plan, implement, build and analyze-slice then write only that lane while still reading the other; specify, finalize-delta, close-delta and brownfield adopt do not follow it. select-stack writes the default (every declared lane); run this to narrow it.
|
|
39
|
+
version: 1.0.2
|
|
37
40
|
agent_agnostic: true
|
|
38
41
|
dialect: aw-spec.orchestrator/v1
|
|
39
42
|
|
|
@@ -100,5 +103,5 @@ outputs:
|
|
|
100
103
|
working_lane: "{{working_lane}}"
|
|
101
104
|
working_kinds: "{{working_kinds}}"
|
|
102
105
|
lane_file: "{{lane_file}}"
|
|
103
|
-
note: "Working lane `{{working_lane}}` stored in {{lane_file}}. The file is not committed — it is this developer's choice, and another developer on the same repository keeps their own. From now on plan, analyze-plan, implement, build and analyze-slice write only the working lane: they plan it, gate it with its own receipt, generate it, compile it and test it. They still READ the other lane where they need it — a frontend plan binds to the operation ids the
|
|
106
|
+
note: "Working lane `{{working_lane}}` stored in {{lane_file}}. The file is not committed — it is this developer's choice, and another developer on the same repository keeps their own. From now on plan, analyze-plan, implement, build and analyze-slice write only the working lane: they plan it, gate it with its own receipt, generate it, compile it and test it. They still READ the other lane where they need it — a frontend plan binds to the operation ids the feature's API plan (api-plan.md) publishes, and never reads the backend plan. specify writes the whole spec whatever lane is chosen, and finalize-delta and close-delta merge and close a change with whatever its lanes have delivered. Brownfield adopt reverses a feature once, every half its code has, whatever lane is chosen, so the other lane's developer finds their plan already written. Re-running /appweaver select-stack resets the working lane to every declared lane."
|
|
104
107
|
next: "Run the lane's flow on the active feature: /appweaver plan → analyze-plan → implement → build → analyze-slice. Switch lanes any time with /appweaver select-lane backend | frontend | both."
|
|
@@ -52,8 +52,15 @@
|
|
|
52
52
|
# for the projects it matters most to. `lane-verify` runs the on-disk check, in the
|
|
53
53
|
# phases that actually read the subtree — implement, build, run, onboard.
|
|
54
54
|
#
|
|
55
|
-
#
|
|
56
|
-
#
|
|
55
|
+
# WHICH STACKS HAVE A RULE SET is said where the stack is chosen. Each menu's prompt
|
|
56
|
+
# carries one line from `stack-rules` — the stacks the active project's technical map has
|
|
57
|
+
# rule files for, complete or partial, and the ones it has none for — and a lane declared
|
|
58
|
+
# on a stack whose rule set is missing or incomplete raises a warning. Every stack stays
|
|
59
|
+
# selectable: one without a rule set runs on ai-rules.md and the technical constitution
|
|
60
|
+
# (STACK-PROFILES.md §7), and the point is that the operator knows it before choosing.
|
|
61
|
+
#
|
|
62
|
+
# ZERO LLM: scripts, two gates, two warnings, two selects and two questions. No
|
|
63
|
+
# generation; the rule report reads the map and the disk and loads nothing.
|
|
57
64
|
#
|
|
58
65
|
# Run (interactive via launcher):
|
|
59
66
|
# /appweaver select-stack # ask everything
|
|
@@ -66,7 +73,7 @@
|
|
|
66
73
|
|
|
67
74
|
name: aw-spec-select-stack
|
|
68
75
|
description: Declare the project's lanes — each lane's STACK and its LANE ROOT FOLDER — and persist them to .appweaver/stacks.json, the single channel every later workflow resolves and gates on. The first command of both the greenfield and the brownfield sequence, and the sole writer of the lane model. It also writes this developer's working lane, .appweaver/lane.json, to its default — both lanes when both are declared, otherwise the one that is — which /appweaver select-lane narrows to one lane.
|
|
69
|
-
version: 2.
|
|
76
|
+
version: 2.5.0
|
|
70
77
|
agent_agnostic: true
|
|
71
78
|
dialect: aw-spec.orchestrator/v1
|
|
72
79
|
|
|
@@ -85,6 +92,17 @@ scripts:
|
|
|
85
92
|
sh: .appweaver/scripts/bash/aw-spec-actions.sh
|
|
86
93
|
ps1: .appweaver/scripts/powershell/aw-spec-actions.ps1
|
|
87
94
|
|
|
95
|
+
vars:
|
|
96
|
+
api_rules_note: "" # the menu's rule-set line for a backend stack (stack-rules)
|
|
97
|
+
api_rules_ok: "false" # the declared service lane's stack has a complete rule set, or the
|
|
98
|
+
# map names none for the lane — only stack-rules' own `ok` raises it
|
|
99
|
+
api_rules_warning: ""
|
|
100
|
+
api_rule_set: "" # complete | partial | none | not-mapped; empty with no service lane
|
|
101
|
+
ui_rules_note: ""
|
|
102
|
+
ui_rules_ok: "false"
|
|
103
|
+
ui_rules_warning: ""
|
|
104
|
+
ui_rule_set: ""
|
|
105
|
+
|
|
88
106
|
workflow:
|
|
89
107
|
|
|
90
108
|
# ═══════════════ SERVICE LANE ═══════════════════════════════════════════════
|
|
@@ -118,11 +136,22 @@ workflow:
|
|
|
118
136
|
stacks there), then re-run.
|
|
119
137
|
on_empty: stop
|
|
120
138
|
|
|
139
|
+
# 2b. Which backend stacks the active project's technical map has rule files for, as
|
|
140
|
+
# one line for the prompt. The option labels stay as stack-list wrote them, because
|
|
141
|
+
# lane-declare matches a label back to its profile.
|
|
142
|
+
- id: api_rules
|
|
143
|
+
action: execute_script
|
|
144
|
+
script: { ref: actions }
|
|
145
|
+
subcommand: stack-rules
|
|
146
|
+
args: ["--kind", "backend"]
|
|
147
|
+
outputs:
|
|
148
|
+
- { name: api_rules_note, from: "$.note" }
|
|
149
|
+
|
|
121
150
|
# 3. Choose the service stack. A matching id in USER_INPUT auto-selects, and so
|
|
122
151
|
# does a detected stack; a project with exactly one candidate auto-confirms.
|
|
123
152
|
- id: select_api_stack
|
|
124
153
|
action: user_select
|
|
125
|
-
prompt: "Select the API (backend) stack — it owns the service lane. This repo's own files point at: {{api_detected}}. A detected stack leads the list. (none) declares a project with no service lane at all, and stops the technical constitution half and the service rule files being authored
|
|
154
|
+
prompt: "Select the API (backend) stack — it owns the service lane. This repo's own files point at: {{api_detected}}. A detected stack leads the list. (none) declares a project with no service lane at all, and stops the technical constitution half and the service rule files being authored. {{api_rules_note}}"
|
|
126
155
|
options_from_variable: api_options
|
|
127
156
|
preselect_from: api_preselect
|
|
128
157
|
single_option_confirm: true
|
|
@@ -180,6 +209,25 @@ workflow:
|
|
|
180
209
|
- { name: api_test_path, from: "$.test_path" }
|
|
181
210
|
- { name: api_root_exists, from: "$.root_exists" }
|
|
182
211
|
|
|
212
|
+
# 6b. A service lane on a stack whose rule set is missing or incomplete is a supported
|
|
213
|
+
# setup, said here once with what it means and how to change it. The run continues.
|
|
214
|
+
- id: api_rules_check
|
|
215
|
+
condition: "{{api_declared}}"
|
|
216
|
+
action: execute_script
|
|
217
|
+
script: { ref: actions }
|
|
218
|
+
subcommand: stack-rules
|
|
219
|
+
args: ["--kind", "backend", "--declared"]
|
|
220
|
+
outputs:
|
|
221
|
+
- { name: api_rules_ok, from: "$.ok" }
|
|
222
|
+
- { name: api_rules_warning, from: "$.warning" }
|
|
223
|
+
- { name: api_rule_set, from: "$.verdict" }
|
|
224
|
+
- id: warn_api_rules
|
|
225
|
+
condition: "{{api_declared}}"
|
|
226
|
+
action: verify_context
|
|
227
|
+
require_true: api_rules_ok
|
|
228
|
+
on_false: continue
|
|
229
|
+
on_false_message: "{{api_rules_warning}}"
|
|
230
|
+
|
|
183
231
|
# ═══════════════ UI LANE ════════════════════════════════════════════════════
|
|
184
232
|
|
|
185
233
|
# 7. Candidates for the UI lane, same shape. The service lane is already declared
|
|
@@ -198,10 +246,20 @@ workflow:
|
|
|
198
246
|
- { name: ui_detected, from: "$.detected_summary" }
|
|
199
247
|
- { name: ui_none_sentinel, from: "$.none_sentinel" }
|
|
200
248
|
|
|
249
|
+
# 7b. The UI stacks' rule sets, measured with the service lane just declared: a
|
|
250
|
+
# frontend rule set can name a file per backend stack (its API integration).
|
|
251
|
+
- id: ui_rules
|
|
252
|
+
action: execute_script
|
|
253
|
+
script: { ref: actions }
|
|
254
|
+
subcommand: stack-rules
|
|
255
|
+
args: ["--kind", "frontend"]
|
|
256
|
+
outputs:
|
|
257
|
+
- { name: ui_rules_note, from: "$.note" }
|
|
258
|
+
|
|
201
259
|
# 8. Choose the UI stack.
|
|
202
260
|
- id: select_ui_stack
|
|
203
261
|
action: user_select
|
|
204
|
-
prompt: "Select the UI (frontend) stack — it owns the web lane, and its root must not overlap the service lane's. This repo's own files point at: {{ui_detected}}. A detected stack leads the list. (none) declares a backend-only project, and stops the UI constitution half and the frontend rule files being authored
|
|
262
|
+
prompt: "Select the UI (frontend) stack — it owns the web lane, and its root must not overlap the service lane's. This repo's own files point at: {{ui_detected}}. A detected stack leads the list. (none) declares a backend-only project, and stops the UI constitution half and the frontend rule files being authored. {{ui_rules_note}}"
|
|
205
263
|
options_from_variable: ui_options
|
|
206
264
|
preselect_from: ui_preselect
|
|
207
265
|
single_option_confirm: true
|
|
@@ -246,6 +304,23 @@ workflow:
|
|
|
246
304
|
- { name: ui_test_path, from: "$.test_path" }
|
|
247
305
|
- { name: ui_root_exists, from: "$.root_exists" }
|
|
248
306
|
|
|
307
|
+
- id: ui_rules_check
|
|
308
|
+
condition: "{{ui_declared}}"
|
|
309
|
+
action: execute_script
|
|
310
|
+
script: { ref: actions }
|
|
311
|
+
subcommand: stack-rules
|
|
312
|
+
args: ["--kind", "frontend", "--declared"]
|
|
313
|
+
outputs:
|
|
314
|
+
- { name: ui_rules_ok, from: "$.ok" }
|
|
315
|
+
- { name: ui_rules_warning, from: "$.warning" }
|
|
316
|
+
- { name: ui_rule_set, from: "$.verdict" }
|
|
317
|
+
- id: warn_ui_rules
|
|
318
|
+
condition: "{{ui_declared}}"
|
|
319
|
+
action: verify_context
|
|
320
|
+
require_true: ui_rules_ok
|
|
321
|
+
on_false: continue
|
|
322
|
+
on_false_message: "{{ui_rules_warning}}"
|
|
323
|
+
|
|
249
324
|
# ═══════════════ CHECK + REPORT ═════════════════════════════════════════════
|
|
250
325
|
|
|
251
326
|
# 10. Is what was just written sound? --allow-missing-root because a lane root folder
|
|
@@ -333,5 +408,7 @@ outputs:
|
|
|
333
408
|
ui_detected: "{{ui_detected}}"
|
|
334
409
|
prototype: "{{prototype}}"
|
|
335
410
|
working_lane: "{{working_lane}}" # this developer's working lane, written to .appweaver/lane.json (not committed)
|
|
336
|
-
|
|
411
|
+
api_rule_set: "{{api_rule_set}}" # complete | partial | none | not-mapped — the service stack's rule set in the active project's map
|
|
412
|
+
ui_rule_set: "{{ui_rule_set}}" # the same for the UI stack
|
|
413
|
+
note: "Lanes persisted to .appweaver/stacks.json. Each lane carries a STACK and a LANE ROOT FOLDER, and both are load-bearing. The LANE ROOT FOLDER is ownership: implement's service lane writes its code only under the service lane's and its frontend lane only under the UI lane's, build/test/run act on it, and onboard reverse-engineers out of it. Each lane also owns a TEST PATH, taken from its stack profile — tests/ beside a .NET src/, the lane root folder itself for a stack that keeps its tests inside — and implement writes the lane's tests there. Overlapping paths of either kind are refused here rather than discovered later as two generators writing one file. The build/test/run commands are project-supplied strings the engine shells out to, which is how it stays stdlib-only and stack-ignorant. api_detected / ui_detected report what this repo's own files pointed at, whether or not it was chosen, as '<stack> at <path>' — or 'nothing detected' on a greenfield repo with nothing to detect. A lane root folder that does not exist yet is NORMAL here and reported rather than refused: greenfield declares src/ before implement creates it. The on-disk check runs in the phases that read the subtree — implement, build, run and onboard all call lane-verify and STOP with the fix named. Declining a lane with (none) is a real declaration and removes any lane of that kind a previous run left behind; it is also what stops that lane's constitution half and rule files being authored. `prototype` is not a lane — it has a root and a run command so an operator can open it, and nothing else. Re-run this workflow any time to re-stack a lane, move a lane root folder, or drop a lane with (none); it is the only workflow that may write this file. It also wrote .appweaver/lane.json — this developer's WORKING lane, set to {{working_lane}} — which is not committed: each developer keeps their own. A developer who works on one lane runs /appweaver select-lane, and from then on plan, analyze-plan, implement, build and analyze-slice write only that lane while still reading the other one. api_rule_set / ui_rule_set say how much of each chosen stack's technical rule set the active project's map finds on disk — complete, partial, none, or not-mapped where the map names no stack folder for that lane. A stack with none runs on ai-rules.md and the technical constitution; a warning above says what to write to change that."
|
|
337
414
|
next: "GREENFIELD: /appweaver foundation → constitution → specify. The project rules live in guardrails/project-specific/, which .appweaver/domain.json names by default — fill in its rule files and its two maps; /appweaver select-domain switches to another project folder under guardrails/ when you keep more than one. On a project with no specs yet, constitution creates the default bounded context MainContext and its feature CoreFeature and makes both active; to use your own names, run /appweaver select-bounded-context <Name> and then /appweaver select-feature <Name> before specify. Once any bounded context exists, select-feature refuses to run until one is selected. foundation scaffolds every lane declared here in one run, backend then frontend — from a verified pack, from a spec the agent builds the project from, or skipped for a lane whose code already exists — and a spec build follows the technical rules the active project maps under `## /aw-spec-foundation-backend` and `## /aw-spec-foundation-frontend`. BROWNFIELD: /appweaver inventory — it scans the lane root folders declared here and proposes the bounded contexts and features as specs/proposed-inventory.md; edit that map, run /appweaver inventory apply, then /appweaver onboard <Context> once per bounded context, which reverse-engineers the governance out of the same lane root folders and activates it: onboard creates guardrails/brf-<domain>/ from the code and names it in .appweaver/domain.json. Run this workflow FIRST in either sequence: foundation scaffolds into the lane root folders declared here, constitution reads the declaration to decide which halves to author, and inventory and onboard read it to decide what to scan."
|
|
@@ -81,7 +81,7 @@
|
|
|
81
81
|
|
|
82
82
|
name: aw-spec-specify
|
|
83
83
|
description: Author the ACTIVE feature's specification AND its bounded context's domain model, together. The aggregate root, its entities, events and invariants (BR-n) live in specs/<Context>/domain-model.md — the one canonical definition every spec in the context cites by id and never restates. First call writes the master spec (US-1) plus the master model; a later call opens its OWN change (many may be open at once) and writes that change's delta-spec and delta-domain-model, leaving both masters untouched for finalize-delta to merge. Opening a change asks which lanes it touches — both by default — and records the answer on the delta-spec's **Lanes** line; the spec is written whole either way. Each change carries a WAVE — deltas sharing one are independent and developable in parallel, a higher wave is implemented after the lower ones land — and its model delta sits beside the master so every other open delta can see it while being authored. Spec phase only — plan/design is separate.
|
|
84
|
-
version: 3.
|
|
84
|
+
version: 3.7.1
|
|
85
85
|
agent_agnostic: true
|
|
86
86
|
dialect: aw-spec.orchestrator/v1
|
|
87
87
|
|
|
@@ -131,6 +131,10 @@ vars:
|
|
|
131
131
|
change_lanes_csv: "" # DELTA path only — what the **Lanes** line now records
|
|
132
132
|
open_count: "0" # how many changes are open on this feature after this call
|
|
133
133
|
domain_model: "" # the CONTEXT's canonical model — bound by context-paths
|
|
134
|
+
model_guard_ok: "false" # model-guard-check's verdict on the bootstrap rewrite. DEFAULTS
|
|
135
|
+
# TO REFUSE: only the check's own `ok` lets the run past the gate
|
|
136
|
+
model_guard_losses: "" # what the rejected rewrite lost, one clause per item
|
|
137
|
+
model_guard_rejected: "" # where the rejected rewrite was kept
|
|
134
138
|
pending_model_files: [] # every OTHER open delta's model change, for build_context
|
|
135
139
|
pending_count: "0"
|
|
136
140
|
next_wave: "1"
|
|
@@ -443,6 +447,19 @@ workflow:
|
|
|
443
447
|
- .appweaver/memory/constitution.domain.md
|
|
444
448
|
- { path: .appweaver/memory/constitution.ui.md, optional: true }
|
|
445
449
|
|
|
450
|
+
# THE REWRITE IS CHECKED. The engine writes the agent's reply over the WHOLE model, and
|
|
451
|
+
# from a context's second feature on that file holds the aggregates, the BR-/XBR- rules
|
|
452
|
+
# and the ledger rows other features rely on. The snapshot copies it aside; the check
|
|
453
|
+
# after the step compares the two (python/aw-model-guard.py) and, on a loss, puts the
|
|
454
|
+
# model back and keeps the rewrite as domain-model.rejected.md. Template placeholders are
|
|
455
|
+
# not recorded, so a context's first feature is held to nothing but its Context version.
|
|
456
|
+
- id: boot_model_snapshot
|
|
457
|
+
condition: "{{is_bootstrap}} == true"
|
|
458
|
+
action: execute_script
|
|
459
|
+
script: { ref: actions }
|
|
460
|
+
subcommand: model-guard-snapshot
|
|
461
|
+
args: ["--model", "{{domain_model}}"]
|
|
462
|
+
|
|
446
463
|
- id: boot_model_generate
|
|
447
464
|
condition: "{{is_bootstrap}} == true"
|
|
448
465
|
action: agent_author
|
|
@@ -465,6 +482,12 @@ workflow:
|
|
|
465
482
|
yet gets a new section. EXTEND the ubiquitous language. Do NOT rewrite, renumber
|
|
466
483
|
or "tidy" what is already there — other specs cite those ids, and a renumbered BR
|
|
467
484
|
breaks every citation silently.
|
|
485
|
+
- A SCRIPT COMPARES YOUR FILE WITH THE MODEL AS IT WAS, and puts the old one back if
|
|
486
|
+
any of these is gone: an `## Aggregate:` section under its name; a BR-n or XBR-n,
|
|
487
|
+
in the same section, with the same rule text, defined once; a name on an
|
|
488
|
+
aggregate's `Serving specs` line; a Ubiquitous Language term; a context the
|
|
489
|
+
Context Map names; a Change History row; the Context version. Add to any of them
|
|
490
|
+
freely; never remove, rename, renumber, move or reword one.
|
|
468
491
|
- DDD IS THE RATIFIED MODELLING STANDARD (NON-NEGOTIABLE → the modelling-methodology
|
|
469
492
|
standard in the sticky standards, wired per-project via tech-rule-bindings
|
|
470
493
|
"## /aw-spec-specify", plus the domain's own DDD overlay): a consistent ubiquitous
|
|
@@ -481,6 +504,26 @@ workflow:
|
|
|
481
504
|
- Do NOT write the Context version or the Change History version column — scripts
|
|
482
505
|
stamp those. Fill the initial row's date and aggregate only.
|
|
483
506
|
|
|
507
|
+
- id: boot_model_check
|
|
508
|
+
condition: "{{is_bootstrap}} == true"
|
|
509
|
+
action: execute_script
|
|
510
|
+
script: { ref: actions }
|
|
511
|
+
subcommand: model-guard-check
|
|
512
|
+
args: ["--model", "{{domain_model}}"]
|
|
513
|
+
outputs:
|
|
514
|
+
- { name: model_guard_ok, from: "$.ok" }
|
|
515
|
+
- { name: model_guard_losses, from: "$.losses_text" }
|
|
516
|
+
- { name: model_guard_rejected, from: "$.rejected" }
|
|
517
|
+
|
|
518
|
+
# On a stop the model is already restored, and the unfinished-first-draft marker is still
|
|
519
|
+
# up, so the re-run asks to re-author the draft.
|
|
520
|
+
- id: boot_model_guard
|
|
521
|
+
condition: "{{is_bootstrap}} == true"
|
|
522
|
+
action: verify_context
|
|
523
|
+
require_true: model_guard_ok
|
|
524
|
+
on_false: stop
|
|
525
|
+
on_false_message: "The domain model lost content other features rely on, so {{domain_model}} was put back as it was before this run. Lost: {{model_guard_losses}}. The rejected rewrite is kept at {{model_guard_rejected}} for inspection. Run /appweaver specify again and choose \"Re-author the first draft\"."
|
|
526
|
+
|
|
484
527
|
# ═════════════════════════ DELTA — spec.md exists ═════════════════════════
|
|
485
528
|
# A later requirement = a new user story on the SAME aggregate. Delegate to the
|
|
486
529
|
# delta-spec module: it opens the change (cr-setup) and authors BOTH of the change's
|
|
@@ -797,4 +840,4 @@ outputs:
|
|
|
797
840
|
# Both paths spell out their WHOLE remaining chain. The bootstrap path named only
|
|
798
841
|
# `plan` and stopped there, which left a first greenfield run with no successor at
|
|
799
842
|
# the exact point the delta path was fully documented.
|
|
800
|
-
next: "/appweaver plan — BOOTSTRAP authors backend-plan.md from the spec + the domain model (plus frontend-plan.md where a UI lane is declared); a DELTA (this run opened change {{cr_id}}, wave {{wave}}) authors the delta plans for it. BOOTSTRAP then flows: plan → analyze-plan → implement → build → analyze-slice → run → deploy (analyze-plan is the spec↔plan gate and it repairs and stops only while NO change is open). A change instead flows: analyze-plan-delta → implement → build → analyze-slice-delta → finalize-delta → analyze-slice → close-delta (finalize-delta merges the delta into spec.md + domain-model.md — not the lane plans, which are derived from those
|
|
843
|
+
next: "/appweaver plan — BOOTSTRAP authors api-plan.md and backend-plan.md from the spec + the domain model (plus frontend-plan.md where a UI lane is declared); a DELTA (this run opened change {{cr_id}}, wave {{wave}}) authors the delta plans for it. BOOTSTRAP then flows: plan → analyze-plan → implement → build → analyze-slice → run → deploy (analyze-plan is the spec↔plan gate and it repairs and stops only while NO change is open). A change instead flows: analyze-plan-delta → implement → build → analyze-slice-delta → finalize-delta → analyze-slice → close-delta (finalize-delta merges the delta into spec.md + domain-model.md, and the change's delta API plan into api-plan.md — not the lane plans, which are derived from those three — but leaves the change open; analyze-slice verifies the slice against the merged master; close-delta archives the change and bumps the version). ⚠️ With more than one change open, plan, analyze-plan-delta and implement ASK which one they are for (pass the id as the argument to skip the prompt) and activate the answer; finalize-delta and close-delta still act on whichever change is active — so finish or close the others deliberately."
|