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
|
@@ -2,7 +2,8 @@
|
|
|
2
2
|
# aw-spec-plan (orchestrator) — the spec-anchored Plan phase, BOTH LANES
|
|
3
3
|
#
|
|
4
4
|
# Authors the feature's LANE PLANS — the tech-agnostic HLDs that MEDIATE between the
|
|
5
|
-
# spec and the code:
|
|
5
|
+
# spec and the code — and the API contract between them:
|
|
6
|
+
# • specs/<Context>/<Feature>/api-plan.md when a BACKEND lane is declared — its endpoints
|
|
6
7
|
# • specs/<Context>/<Feature>/backend-plan.md when a BACKEND lane is declared
|
|
7
8
|
# • specs/<Context>/<Feature>/frontend-plan.md when a FRONTEND lane is declared
|
|
8
9
|
# `implement` GENERATES each lane's code from ITS PLAN ALONE (model-driven, not a
|
|
@@ -33,16 +34,28 @@
|
|
|
33
34
|
# backend-only change gets no frontend delta plan, even from a developer on `both`. A
|
|
34
35
|
# change with no such line touches every lane.
|
|
35
36
|
#
|
|
36
|
-
# THE
|
|
37
|
-
#
|
|
37
|
+
# THE API PLAN COMES FIRST. The backend lane authors api-plan.md — every endpoint the
|
|
38
|
+
# service publishes, the API contract between the lanes — before backend-plan.md, which then
|
|
39
|
+
# realises each endpoint as a use-case. A change does the same in its own directory:
|
|
40
|
+
# delta-api-plan.md first, then delta-backend-plan.md. After the backend half,
|
|
41
|
+
# contract-draft writes api-draft.json beside the plans from the API plan, by script, so a
|
|
42
|
+
# frontend can generate its client against endpoints the service has planned and not built
|
|
43
|
+
# yet. The frontend plan reads the API plan and nothing else of the service's.
|
|
44
|
+
#
|
|
45
|
+
# A FEATURE PLANNED BEFORE API PLANS EXISTED keeps its endpoints in its backend plan, and
|
|
46
|
+
# every reader falls back to that while it has no api-plan.md. Every re-derivation (`main`)
|
|
47
|
+
# offers to move them out while they are there, by script (api-split); finalize-delta moves
|
|
48
|
+
# them when it first merges a change's API into the feature. A change planned before then
|
|
49
|
+
# keeps its API in its delta backend plan, which is re-planned with the API in it.
|
|
50
|
+
#
|
|
51
|
+
# THE CONTRACT HAND-OFF BETWEEN THE TWO LANES. Each lane's developer writes only their own
|
|
52
|
+
# plans, so what the frontend needs from the service travels as a REQUEST LEDGER:
|
|
38
53
|
# frontend-plan.md §5 "Contract deltas needed" holds one RQ-n per operation it needs and the
|
|
39
|
-
# surface lacks — every binding, when there is no
|
|
40
|
-
#
|
|
41
|
-
#
|
|
42
|
-
#
|
|
43
|
-
#
|
|
44
|
-
# api-draft.json beside the plan from its API section, by script, so a frontend can
|
|
45
|
-
# generate its client against endpoints the service has planned and not built yet.
|
|
54
|
+
# surface lacks — every binding, when there is no API plan yet — and api-plan.md answers
|
|
55
|
+
# each in "Requests from the frontend lane", published under an operation id or declined
|
|
56
|
+
# with the reason. contract-requests reads both before each lane is authored: the API plan
|
|
57
|
+
# is told which requests are open, the frontend plan which were answered (to re-bind) or
|
|
58
|
+
# declined (to plan around).
|
|
46
59
|
#
|
|
47
60
|
# ONE COMMAND, TWO LANES, TWO RULE SETS. The lanes take their rules from different
|
|
48
61
|
# headings of tech-rule-bindings (`## /aw-spec-plan-backend` for the service,
|
|
@@ -85,9 +98,9 @@
|
|
|
85
98
|
# CONFIRMED first — the run stops on a decline, leaving them untouched.
|
|
86
99
|
# Next: /appweaver analyze-plan (spec↔plan gate) → implement.
|
|
87
100
|
# • CR-… → author THAT change's delta plans ONLY (delta-plan module). The masters are
|
|
88
|
-
# left UNTOUCHED, and finalize-delta does not merge
|
|
89
|
-
# change's spec and
|
|
90
|
-
# is what the main row above does. The change stays OPEN.
|
|
101
|
+
# left UNTOUCHED, and finalize-delta does not merge the lane plans either: it merges
|
|
102
|
+
# the change's spec, model and API halves, and a master plan is RE-DERIVED from those —
|
|
103
|
+
# which is what the main row above does. The change stays OPEN.
|
|
91
104
|
# Next: analyze-plan-delta → implement (which asks which change) → build →
|
|
92
105
|
# analyze-slice-delta → finalize-delta → analyze-slice → close-delta.
|
|
93
106
|
# • new → open a plan-only change first, then plan it: a refactor or architectural
|
|
@@ -116,8 +129,8 @@
|
|
|
116
129
|
# =============================================================================
|
|
117
130
|
|
|
118
131
|
name: aw-spec-plan
|
|
119
|
-
description: "Author the feature's lane plans from the spec and the bounded context's domain model — backend-plan.md when a backend lane is declared, frontend-plan.md when a frontend lane is
|
|
120
|
-
version: 5.
|
|
132
|
+
description: "Author the feature's lane plans from the spec and the bounded context's domain model — backend-plan.md when a backend lane is declared, with api-plan.md (the endpoints the service publishes, the API contract the frontend binds to) authored before it; frontend-plan.md when a frontend lane is; all of them when both are. Lanes come from .appweaver/stacks.json, so one command covers backend-only, frontend-only and full-stack projects; the former separate design-ui command is folded in. It ASKS what it is planning, the way implement asks what it is building: the master (`main`), one of the OPEN CHANGES, or a new plan-only change for a refactor with no spec delta — the argument doubles as the answer, and the menu appears only once a master exists, so a first run bootstraps with no prompt. `main` on a feature that already has masters RE-DERIVES them from the merged spec.md + domain-model.md — the operation finalize-delta's contract assumes when it merges a change's spec and model halves and no lane plan — and is confirmed before it rewrites anything. A change instead gets delta-backend-plan.md / delta-frontend-plan.md inside changes/<CR-id>/ while the masters stay untouched, written against the effective model (the master model, the change's own model delta, and the pending model deltas of LOWER waves, which are its predecessors) and against the feature's real source files from its OKF concept. Master authoring is template-driven: the kit's templates by default, or the code-derived as-built structure when onboard installed an override. Authoring only — a master gates at analyze-plan; a change ships through the CR chain."
|
|
133
|
+
version: 5.8.1
|
|
121
134
|
agent_agnostic: true
|
|
122
135
|
dialect: aw-spec.orchestrator/v1
|
|
123
136
|
|
|
@@ -161,10 +174,34 @@ vars:
|
|
|
161
174
|
fe_working: "false"
|
|
162
175
|
any_working: "false"
|
|
163
176
|
working_lane: ""
|
|
164
|
-
#
|
|
165
|
-
#
|
|
166
|
-
|
|
167
|
-
|
|
177
|
+
# THE SERVICE'S API AS READ CONTEXT for the frontend lane — the API plan, or the backend
|
|
178
|
+
# plan of a feature planned before API plans existed; and the same for the chosen change.
|
|
179
|
+
# Bound only when the backend lane is declared, so a plan left behind by a removed lane
|
|
180
|
+
# never reaches the payload.
|
|
181
|
+
api_read: ""
|
|
182
|
+
delta_api_read: ""
|
|
183
|
+
# THE API PLAN (api-plan.md) — the endpoints the backend lane publishes, authored before
|
|
184
|
+
# the backend plan on the main path. api_mode: skip | author (fill the template just
|
|
185
|
+
# scaffolded) | update (revise the API plan that is there, or was just split out).
|
|
186
|
+
api_plan: ""
|
|
187
|
+
api_plan_exists: "false"
|
|
188
|
+
api_go: "false" # the main path, on a worked backend lane
|
|
189
|
+
api_mode: "skip"
|
|
190
|
+
api_created: "false"
|
|
191
|
+
api_blocked: "false" # the backend plan still carries the API — the split is offered
|
|
192
|
+
api_split_answer: ""
|
|
193
|
+
api_split_done: "false"
|
|
194
|
+
api_split_endpoints: "0"
|
|
195
|
+
api_split_dropped: "none"
|
|
196
|
+
api_split_kept: "true"
|
|
197
|
+
api_split_ok: "true" # false when a yes to the split did not move the endpoints
|
|
198
|
+
api_in_backend: "false" # the backend plan keeps the API this run: the scaffold refused and no split moved it
|
|
199
|
+
# What the backend plan's authoring step is told about where the endpoints are — the API
|
|
200
|
+
# plan, or this document itself when no split moved them out of it.
|
|
201
|
+
be_api_rule: "THE ENDPOINTS ARE IN api-plan.md (in context), authored just before this document: the API contract the frontend lane binds to. Do NOT restate them here — the API section of this document is the one line pointing to api-plan.md, and where the template has an endpoint block or a requests table (a template generated before API plans existed), that line goes in their place. REALISE every endpoint instead: each names under **Maps to** the use-case that serves it, and that use-case is this document's, with request and response DTOs that match the endpoint's shapes. An endpoint with no use-case here is unrealised. The traceability spine cites an endpoint as `VERB /route`."
|
|
202
|
+
cr_delta_backend_plan: "" # cr-paths, on the delta path
|
|
203
|
+
cr_delta_api_plan: ""
|
|
204
|
+
cr_delta_api_exists: "false"
|
|
168
205
|
rederive_be_txt: ""
|
|
169
206
|
rederive_fe_txt: ""
|
|
170
207
|
active_change: ""
|
|
@@ -236,11 +273,25 @@ vars:
|
|
|
236
273
|
source_files: [] # the feature's real source files, from its OKF concept
|
|
237
274
|
source_count: "0"
|
|
238
275
|
# THE REQUEST LEDGER and the draft (contract-requests / contract-draft).
|
|
239
|
-
req_backend_text: "none" # the frontend's requests still open — what the backend plan
|
|
276
|
+
req_backend_text: "none" # the frontend's requests still open — what the API plan answers (the backend plan, for a feature with none yet)
|
|
240
277
|
req_frontend_text: "none" # answered requests to re-bind and declined ones to plan around
|
|
241
278
|
req_summary: ""
|
|
242
279
|
draft_path: ""
|
|
280
|
+
draft_plan: "" # the document it was drawn from: api-plan.md, or the backend plan
|
|
243
281
|
draft_ops: "0"
|
|
282
|
+
draft_unread: "0" # endpoint shapes the drafting script could not type
|
|
283
|
+
draft_unread_text: "none"
|
|
284
|
+
draft_clean: "true"
|
|
285
|
+
draft_dropped: "0" # operations the previous draft had and this one does not
|
|
286
|
+
draft_dropped_text: "none"
|
|
287
|
+
draft_kept: "true"
|
|
288
|
+
# The change's own API draft (delta path).
|
|
289
|
+
draft_change_go: "false"
|
|
290
|
+
change_draft_path: ""
|
|
291
|
+
change_draft_plan: ""
|
|
292
|
+
change_draft_unread: "0"
|
|
293
|
+
change_draft_unread_text: "none"
|
|
294
|
+
change_draft_clean: "true"
|
|
244
295
|
|
|
245
296
|
workflow:
|
|
246
297
|
|
|
@@ -312,6 +363,8 @@ workflow:
|
|
|
312
363
|
- { name: backend_plan_exists, from: "$.backend_plan_exists" }
|
|
313
364
|
- { name: frontend_plan, from: "$.frontend_plan" }
|
|
314
365
|
- { name: frontend_plan_exists, from: "$.frontend_plan_exists" }
|
|
366
|
+
- { name: api_plan, from: "$.api_plan" }
|
|
367
|
+
- { name: api_plan_exists, from: "$.api_plan_exists" }
|
|
315
368
|
|
|
316
369
|
# THIS FEATURE'S LANES. lane_resolve above read the REPO's declaration; one feature may
|
|
317
370
|
# own no part of a lane's surface — adopt records `lanes: [backend]` in
|
|
@@ -345,12 +398,6 @@ workflow:
|
|
|
345
398
|
action: set
|
|
346
399
|
vars: { any_working: "true" }
|
|
347
400
|
|
|
348
|
-
# The backend plan as READ context for the frontend lane, on a declared backend only.
|
|
349
|
-
- id: be_plan_read_set
|
|
350
|
-
condition: "{{be_declared}} == true"
|
|
351
|
-
action: set
|
|
352
|
-
vars: { be_plan_read: "{{backend_plan}}" }
|
|
353
|
-
|
|
354
401
|
# The BOUNDED CONTEXT's domain model — where the aggregate root, its entities and its
|
|
355
402
|
# invariants (BR-n) live. The spec cites them by id; this phase records where each is
|
|
356
403
|
# ENFORCED, so the model has to be in context or the instruction to "follow it exactly"
|
|
@@ -615,6 +662,28 @@ workflow:
|
|
|
615
662
|
# returns the existing path when the plan is there, and RENAMES a legacy design.md /
|
|
616
663
|
# design.ui.md into the plan name). It sits after the question on purpose: a template
|
|
617
664
|
# copied in before a `no` stays on disk, and the next run reads it as a master.
|
|
665
|
+
#
|
|
666
|
+
# THE API PLAN FIRST, on the main path of a worked backend lane. The scaffold refuses
|
|
667
|
+
# (`blocked`) while a backend plan still carries the API, since an empty API plan
|
|
668
|
+
# beside it would be read in its place — and a backend plan scaffolded from a template
|
|
669
|
+
# generated before API plans existed carries an empty requests table, so on a first
|
|
670
|
+
# run the backend plan must not be there yet. The delta path plans the change's API in
|
|
671
|
+
# the delta-plan module instead and leaves the master API plan alone.
|
|
672
|
+
- id: api_go_arm
|
|
673
|
+
condition: "{{plan_target}} == main"
|
|
674
|
+
action: set
|
|
675
|
+
vars: { api_go: "{{be_working}}" }
|
|
676
|
+
- id: api_scaffold
|
|
677
|
+
condition: "{{api_go}} == true"
|
|
678
|
+
action: execute_script
|
|
679
|
+
script: { ref: actions }
|
|
680
|
+
subcommand: plan-scaffold
|
|
681
|
+
args: ["--feature-dir", "{{feature_dir}}", "--lane", "api"]
|
|
682
|
+
outputs:
|
|
683
|
+
- { name: api_plan, from: "$.plan_doc" }
|
|
684
|
+
- { name: api_created, from: "$.created" }
|
|
685
|
+
- { name: api_blocked, from: "$.blocked" }
|
|
686
|
+
|
|
618
687
|
- id: be_scaffold
|
|
619
688
|
condition: "{{be_working}} == true"
|
|
620
689
|
action: execute_script
|
|
@@ -639,11 +708,100 @@ workflow:
|
|
|
639
708
|
- { name: fe_created, from: "$.created" }
|
|
640
709
|
- { name: fe_migrated, from: "$.migrated" }
|
|
641
710
|
|
|
642
|
-
#
|
|
643
|
-
|
|
644
|
-
|
|
711
|
+
# A FEATURE PLANNED BEFORE API PLANS EXISTED keeps its endpoints in its backend plan, and
|
|
712
|
+
# the API scaffold above refused to put an empty API plan beside them. Offered on every
|
|
713
|
+
# re-derivation while they are there: api-split moves every endpoint block and the
|
|
714
|
+
# requests table into a new api-plan.md by script, leaves a line in the backend plan where
|
|
715
|
+
# they were, and redraws api-draft.json. A no keeps the old layout for this run — every
|
|
716
|
+
# reader falls back to the backend plan — and finalize-delta moves them when it first
|
|
717
|
+
# merges a change's API. Yes is first, so an unattended run moves them: the move only
|
|
718
|
+
# relocates blocks, and what it drew is checked against the draft before it below. A yes
|
|
719
|
+
# the split does not complete keeps the old layout too, and is reported.
|
|
720
|
+
- id: ask_api_split
|
|
721
|
+
condition: "{{api_blocked}} == true"
|
|
722
|
+
action: ask
|
|
723
|
+
prompt: "This feature's endpoints are still in {{backend_plan}}. Move them into their own api-plan.md now? A script does it (api-split): every endpoint block and the requests table go over as they are, the backend plan keeps one line saying where they went, and api-draft.json is redrawn from the new file. The frontend lane's next analyze-plan re-gates once, because the surface it binds to is now a different file. Answer no to keep them where they are for this run."
|
|
724
|
+
options: ["yes", "no"]
|
|
725
|
+
answer_var: api_split_answer
|
|
726
|
+
- id: api_split
|
|
727
|
+
condition: "{{api_split_answer}} == yes"
|
|
728
|
+
action: execute_script
|
|
729
|
+
on_error: continue
|
|
730
|
+
script: { ref: actions }
|
|
731
|
+
subcommand: api-split
|
|
732
|
+
args: ["--feature-dir", "{{feature_dir}}"]
|
|
733
|
+
outputs:
|
|
734
|
+
- { name: api_split_done, from: "$.split" }
|
|
735
|
+
- { name: api_split_endpoints, from: "$.endpoints" }
|
|
736
|
+
- { name: api_split_dropped, from: "$.dropped_text" }
|
|
737
|
+
- id: api_split_lost
|
|
738
|
+
condition: "{{api_split_dropped}} != none"
|
|
739
|
+
action: set
|
|
740
|
+
vars: { api_split_kept: "false" }
|
|
741
|
+
- id: warn_api_split_lost
|
|
742
|
+
condition: "{{api_split_done}} == true"
|
|
743
|
+
action: verify_context
|
|
744
|
+
require_true: api_split_kept
|
|
745
|
+
on_false: continue
|
|
746
|
+
on_false_message: "API SPLIT — the {{api_split_endpoints}} endpoint(s) moved into {{api_plan}} draw fewer operations than api-draft.json had before: {{api_split_dropped}}. Compare {{api_plan}} with the backend plan's history, restore what is missing, then re-run plan or analyze-plan."
|
|
747
|
+
|
|
748
|
+
# A YES THE SPLIT DID NOT COMPLETE — the script failed, or answered without moving the
|
|
749
|
+
# endpoints. They are still in the backend plan and no api-plan.md was written, so the run
|
|
750
|
+
# goes on as a declined split does (the backend plan keeps the API, below) and says so.
|
|
751
|
+
# The engine binds no reason for a script that fails without answering, so the message
|
|
752
|
+
# names the command that shows it.
|
|
753
|
+
- id: api_split_ok_flag
|
|
754
|
+
condition: "{{api_split_answer}} == yes"
|
|
645
755
|
action: set
|
|
646
|
-
vars: {
|
|
756
|
+
vars: { api_split_ok: "{{api_split_done}}" }
|
|
757
|
+
- id: warn_api_split_failed
|
|
758
|
+
action: verify_context
|
|
759
|
+
require_true: api_split_ok
|
|
760
|
+
on_false: continue
|
|
761
|
+
on_false_message: "API SPLIT DID NOT COMPLETE — you answered yes, but api-split did not move this feature's endpoints out of {{backend_plan}}, and no api-plan.md was written. This run went on as if the move had been declined: the endpoints stay in the backend plan, and its re-derivation keeps them there. To see why and move them, run `.appweaver/scripts/bash/aw-spec-actions.sh api-split --feature-dir {{feature_dir}}` (PowerShell: `.appweaver/scripts/powershell/aw-spec-actions.ps1 api-split --feature-dir {{feature_dir}}`); once it reports split=true, re-run /appweaver plan main to revise the new api-plan.md."
|
|
762
|
+
|
|
763
|
+
# THE API PLAN'S AUTHORING MODE, as ordered assignments: `update` revises an API plan that
|
|
764
|
+
# was already there; `author` fills a template the scaffold just copied in; a refused
|
|
765
|
+
# scaffold leaves `skip` and the API in the backend plan (`api_in_backend`) for this run;
|
|
766
|
+
# a split that happened makes it `update` again, over the blocks it moved, and the API is
|
|
767
|
+
# no longer in the backend plan.
|
|
768
|
+
- id: api_mode_existing
|
|
769
|
+
condition: "{{api_go}} == true"
|
|
770
|
+
action: set
|
|
771
|
+
vars: { api_mode: "update" }
|
|
772
|
+
- id: api_mode_author
|
|
773
|
+
condition: "{{api_created}} == true"
|
|
774
|
+
action: set
|
|
775
|
+
vars: { api_mode: "author" }
|
|
776
|
+
- id: api_mode_blocked
|
|
777
|
+
condition: "{{api_blocked}} == true"
|
|
778
|
+
action: set
|
|
779
|
+
vars: { api_mode: "skip", api_in_backend: "true" }
|
|
780
|
+
- id: api_mode_split
|
|
781
|
+
condition: "{{api_split_done}} == true"
|
|
782
|
+
action: set
|
|
783
|
+
vars: { api_mode: "update", api_in_backend: "false" }
|
|
784
|
+
|
|
785
|
+
# WHAT THE FRONTEND LANE READS OF THE SERVICE: the API plan when there is one — on disk
|
|
786
|
+
# already, or authored in this run — and otherwise the backend plan (the scaffold may
|
|
787
|
+
# have renamed a legacy design.md, so its path is the one taken after the scaffold).
|
|
788
|
+
# Nothing on an undeclared backend lane.
|
|
789
|
+
- id: api_read_be
|
|
790
|
+
condition: "{{be_declared}} == true"
|
|
791
|
+
action: set
|
|
792
|
+
vars: { api_read: "{{backend_plan}}" }
|
|
793
|
+
- id: api_read_on_disk
|
|
794
|
+
condition: "{{api_plan_exists}} == true"
|
|
795
|
+
action: set
|
|
796
|
+
vars: { api_read: "{{api_plan}}" }
|
|
797
|
+
- id: api_read_authored
|
|
798
|
+
condition: "{{api_mode}} != skip"
|
|
799
|
+
action: set
|
|
800
|
+
vars: { api_read: "{{api_plan}}" }
|
|
801
|
+
- id: api_read_undeclared
|
|
802
|
+
condition: "{{be_declared}} == false"
|
|
803
|
+
action: set
|
|
804
|
+
vars: { api_read: "" }
|
|
647
805
|
|
|
648
806
|
# 5e. Resolve each lane's authoring MODE. Four ordered assignments per lane: the
|
|
649
807
|
# greenfield default for a new lane, the code-derived override replacing it, a
|
|
@@ -710,6 +868,16 @@ workflow:
|
|
|
710
868
|
- { name: req_backend_text, from: "$.backend_text" }
|
|
711
869
|
- { name: req_summary, from: "$.summary" }
|
|
712
870
|
|
|
871
|
+
# THE API STAYS IN THE BACKEND PLAN whenever no split moved it — declined, or a yes the
|
|
872
|
+
# split did not complete — so its re-derivation is told to keep the endpoint blocks and
|
|
873
|
+
# answer the requests itself, as it did before API plans existed. Told the endpoints were
|
|
874
|
+
# in api-plan.md, it would replace them with a pointer to a document that does not exist.
|
|
875
|
+
- id: be_api_rule_in_plan
|
|
876
|
+
condition: "{{api_in_backend}} == true"
|
|
877
|
+
action: set
|
|
878
|
+
vars:
|
|
879
|
+
be_api_rule: "THE ENDPOINTS STAY IN THIS DOCUMENT for this run — they have not been moved into api-plan.md. Keep the endpoint blocks of its API section in their form: the `VERB /route` heading, then **Operation id**, Request, Success and the Errors table, every shape `{ field: type }`. OPERATION IDS ARE STABLE: every endpoint keeps the operation id it already has, and a new one gets an id unique across the service. ANSWER THE FRONTEND LANE'S CONTRACT REQUESTS still open in the frontend plan's §5 'Contract deltas needed': {{req_backend_text}}. Answer each one in the 'Requests from the frontend lane' table of the API section (| Request | Outcome | Operation id | Why |): PUBLISH it as an endpoint, under the operation id it proposes unless that clashes with one already in use, or DECLINE it with the reason. Publish only what the spec supports — a request the spec gives no basis for is declined as a spec gap for /appweaver specify. Keep every row the table already has. `none` means no request is open."
|
|
880
|
+
|
|
713
881
|
# 6. Pre-execution hooks.
|
|
714
882
|
- id: resolve_pre_hooks
|
|
715
883
|
action: execute_script
|
|
@@ -722,6 +890,129 @@ workflow:
|
|
|
722
890
|
action: dispatch_hooks
|
|
723
891
|
hooks_from_variable: before_hooks
|
|
724
892
|
|
|
893
|
+
# ═══════════ THE API PLAN — the endpoints, before the backend plan ══════════
|
|
894
|
+
# The contract first: the endpoints a client needs, their shapes and their errors, and
|
|
895
|
+
# the answers to the frontend lane's requests. The backend plan is authored next and
|
|
896
|
+
# realises each endpoint as a use-case. One template in every project, greenfield or
|
|
897
|
+
# brownfield — the endpoint block form is what the contract scripts read — so there is
|
|
898
|
+
# no template split here, only author (a template just scaffolded) or update.
|
|
899
|
+
- id: ctx_api
|
|
900
|
+
condition: "{{api_mode}} == author"
|
|
901
|
+
action: build_context
|
|
902
|
+
context:
|
|
903
|
+
- { path: "{{api_plan}}" } # the copied template = the fixed endpoint block form
|
|
904
|
+
- { path: "{{spec_file}}" } # BEHAVIOUR: what a client must be able to do
|
|
905
|
+
- { path: "{{domain_model}}", optional: true } # the ubiquitous language; the BR-nnn an error answers to
|
|
906
|
+
- { path: .appweaver/DESIGN-FORMAT.md } # the HLD contract, and The API plan in it
|
|
907
|
+
- { path: .appweaver/memory/constitution.technical.md, optional: true } # technology base ONLY — the protocol it publishes
|
|
908
|
+
- id: gen_api
|
|
909
|
+
condition: "{{api_mode}} == author"
|
|
910
|
+
action: agent_author
|
|
911
|
+
tools: Read # the feature's EXISTING source arrives as {{source_files}} paths, not inlined
|
|
912
|
+
output_target: { type: file, path: "{{api_plan}}" }
|
|
913
|
+
task: |
|
|
914
|
+
Author the API PLAN (the target api-plan.md in context) for this feature by filling
|
|
915
|
+
out the template: every endpoint the service lane publishes for it, and its answers
|
|
916
|
+
to the frontend lane's requests. It is the API contract between the lanes — the
|
|
917
|
+
frontend plan binds to it, implement serves it, a script drafts it into
|
|
918
|
+
api-draft.json — and it is written BEFORE the backend plan, which then realises each
|
|
919
|
+
endpoint as a use-case. Guidance: {{USER_INPUT}}
|
|
920
|
+
Rules:
|
|
921
|
+
- THE SPEC IS THE BEHAVIOUR AUTHORITY. Publish the endpoints a client needs to do
|
|
922
|
+
what the spec's requirements and user stories say, and no more. Each block's
|
|
923
|
+
heading cites the spec ids it serves; an endpoint no spec id calls for is
|
|
924
|
+
over-reach.
|
|
925
|
+
- KEEP THE TEMPLATE'S FORM EXACTLY: one block per endpoint under "## Endpoints" — the
|
|
926
|
+
heading `### `VERB /route` — purpose · Serves …`, then **Operation id**, **Auth**,
|
|
927
|
+
**Request**, **Success**, the **Errors** table and **Maps to**. Scripts read exactly
|
|
928
|
+
this form; an endpoint written as a table row or in prose reaches neither
|
|
929
|
+
api-draft.json nor the frontend.
|
|
930
|
+
- EVERY SHAPE IS `{ field: type }` in conceptual types — path and query parameters,
|
|
931
|
+
request body, success body, each error body. A shape in prose reaches the frontend's
|
|
932
|
+
client untyped. **Maps to** names the use-case that serves the endpoint; the backend
|
|
933
|
+
plan, authored next, realises it under that name.
|
|
934
|
+
- NAME EVERY ENDPOINT. Its **Operation id** is its name in the service's published API
|
|
935
|
+
document (e.g. `CreatePatient`), unique across the service and never reused. The
|
|
936
|
+
frontend plan cites it and implement gives the endpoint exactly this id.
|
|
937
|
+
- THE ERROR CONTRACT: every failure the spec's requirements and the model's BR-nnn
|
|
938
|
+
imply gets a row — its status, when it is returned, its body shape.
|
|
939
|
+
- DATA CLASSIFICATION (DC-): a response shape carries no field the spec's DC- items
|
|
940
|
+
keep from the client; cite the DC- id in the block whose shape it governs.
|
|
941
|
+
- THE CODE THAT EXISTS IS THE WHAT-IS AUTHORITY. {{source_count}} source file(s)
|
|
942
|
+
already realise this feature: {{source_files}}. Where the code already serves an
|
|
943
|
+
endpoint, record its route, verb and operation id exactly as the code has them; one
|
|
944
|
+
it serves under no id keeps `—` and says so in its block — never an invented id,
|
|
945
|
+
which the built service would not carry and analyze-slice would report. With no
|
|
946
|
+
source files there is nothing to conform to.
|
|
947
|
+
- ANSWER THE FRONTEND LANE'S CONTRACT REQUESTS. Still open in the frontend plan's §5
|
|
948
|
+
"Contract deltas needed": {{req_backend_text}}. Answer each one in the "Requests
|
|
949
|
+
from the frontend lane" table (| Request | Outcome | Operation id | Why |): PUBLISH
|
|
950
|
+
it as an endpoint, under the operation id it proposes unless that clashes with one
|
|
951
|
+
this service already uses, or DECLINE it with the reason. Publish only what the spec
|
|
952
|
+
supports — a request the spec gives no basis for is declined as a spec gap for
|
|
953
|
+
/appweaver specify, never published on a guess. `none` means no request is open:
|
|
954
|
+
write `None` under that heading when the table would be empty.
|
|
955
|
+
- TECHNOLOGY-AGNOSTIC: protocol level only — no controller code, framework
|
|
956
|
+
attributes, serializer settings or language types. The stack binds at implement.
|
|
957
|
+
- Write `None` under "## Endpoints" when the feature publishes no endpoint.
|
|
958
|
+
- Set **Version** to the feature's version as the spec's header gives it, and write
|
|
959
|
+
the first Change History row.
|
|
960
|
+
|
|
961
|
+
# The API plan RE-DERIVED: revised against the spec as it stands now, before the backend
|
|
962
|
+
# plan is. The document in context is the current API plan — what is being revised, and
|
|
963
|
+
# its form — and the backend plan as it stands is read for the use-cases its endpoints
|
|
964
|
+
# map to.
|
|
965
|
+
- id: ctx_api_update
|
|
966
|
+
condition: "{{api_mode}} == update"
|
|
967
|
+
action: build_context
|
|
968
|
+
context:
|
|
969
|
+
- { path: "{{api_plan}}" } # the CURRENT API plan = what is being revised
|
|
970
|
+
- { path: "{{spec_file}}" } # BEHAVIOUR, carrying every change finalize-delta has merged
|
|
971
|
+
- { path: "{{domain_model}}", optional: true } # the ubiquitous language; the BR-nnn an error answers to
|
|
972
|
+
- { path: "{{backend_plan}}", optional: true } # READ ONLY — the use-cases the endpoints map to today
|
|
973
|
+
- { path: .appweaver/DESIGN-FORMAT.md }
|
|
974
|
+
- { path: .appweaver/memory/constitution.technical.md, optional: true } # technology base ONLY
|
|
975
|
+
- id: gen_api_update
|
|
976
|
+
condition: "{{api_mode}} == update"
|
|
977
|
+
action: agent_author
|
|
978
|
+
tools: Read # the feature's EXISTING source arrives as {{source_files}} paths, not inlined
|
|
979
|
+
output_target: { type: file, path: "{{api_plan}}" }
|
|
980
|
+
task: |
|
|
981
|
+
RE-DERIVE the API PLAN in context from the current spec. The document you are given
|
|
982
|
+
is the feature's API as it stands today; produce the API this feature's spec calls
|
|
983
|
+
for NOW. It is revised before the backend plan, which then realises each endpoint.
|
|
984
|
+
Do not edit the backend plan. Guidance: {{USER_INPUT}}
|
|
985
|
+
Rules:
|
|
986
|
+
- THIS IS A REVISION, NOT A RE-AUTHORING. Keep every endpoint block the spec still
|
|
987
|
+
supports, byte-for-byte where nothing requires a change: the frontend plan binds to
|
|
988
|
+
it, and the built service is checked against it.
|
|
989
|
+
- OPERATION IDS ARE STABLE. Every endpoint keeps the operation id it already has. A
|
|
990
|
+
new endpoint gets one unique across the service; an endpoint without one gets one
|
|
991
|
+
now, unless the code serves it under none, which keeps `—`.
|
|
992
|
+
- WHAT THE SPEC SAYS NOW WINS. An endpoint no spec id still calls for is deleted with
|
|
993
|
+
its block; a requirement or user story a client needs and no endpoint serves is a
|
|
994
|
+
gap — add the endpoint. The draft drawn after this run reports every operation the
|
|
995
|
+
previous api-draft.json had and this document no longer has.
|
|
996
|
+
- KEEP THE FORM: one block per endpoint under "## Endpoints" — the `### `VERB /route``
|
|
997
|
+
heading, then **Operation id**, **Auth**, **Request**, **Success**, the **Errors**
|
|
998
|
+
table and **Maps to** — every shape `{ field: type }`. A block left in another form
|
|
999
|
+
by an earlier hand reaches neither api-draft.json nor the frontend: bring it into
|
|
1000
|
+
this form.
|
|
1001
|
+
- ANSWER THE FRONTEND LANE'S CONTRACT REQUESTS. Still open in the frontend plan's §5
|
|
1002
|
+
"Contract deltas needed": {{req_backend_text}}. Answer each one in the "Requests
|
|
1003
|
+
from the frontend lane" table (| Request | Outcome | Operation id | Why |): PUBLISH
|
|
1004
|
+
it as an endpoint, under the operation id it proposes unless that clashes with one
|
|
1005
|
+
already in use, or DECLINE it with the reason. Publish only what the spec supports.
|
|
1006
|
+
Keep every row the table already has. `none` means no request is open.
|
|
1007
|
+
- THE CODE THAT EXISTS IS THE WHAT-IS AUTHORITY. {{source_count}} source file(s)
|
|
1008
|
+
realise this feature: {{source_files}}. Where the plan and the code disagree about
|
|
1009
|
+
a route, a verb or an operation id the code serves, the code is what is there —
|
|
1010
|
+
record it as served and let the spec decide whether it changes.
|
|
1011
|
+
- TECHNOLOGY-AGNOSTIC: protocol level only, conceptual types, no code.
|
|
1012
|
+
- ADD ONE Change History row for this re-derivation, describing what moved and why
|
|
1013
|
+
(the spec ids that drove it). Do NOT invent a version number — the version spine
|
|
1014
|
+
belongs to close-delta.
|
|
1015
|
+
|
|
725
1016
|
# ═══════════ BACKEND LANE — bootstrap, greenfield four-layer template ═══════
|
|
726
1017
|
# Author the whole HLD in one pass: all four layers as sections, tech-agnostic, traced
|
|
727
1018
|
# to the spec. build_context REPLACES the per-request envelope; sticky standards stay
|
|
@@ -733,6 +1024,7 @@ workflow:
|
|
|
733
1024
|
- { path: "{{backend_plan}}" } # the copied template = section structure
|
|
734
1025
|
- { path: "{{spec_file}}" } # BEHAVIOUR: FR/CN/DC/IC/US/SC + cited BR ids
|
|
735
1026
|
- { path: "{{domain_model}}", optional: true } # the CONTEXT's canonical model — entities, invariants, boundary
|
|
1027
|
+
- { path: "{{api_plan}}", optional: true } # the API plan authored just before — the endpoints §2 realises
|
|
736
1028
|
- { path: .appweaver/DESIGN-FORMAT.md } # the HLD contract
|
|
737
1029
|
- { path: .appweaver/memory/constitution.technical.md, optional: true } # technology base ONLY — no domain (domain enters via the spec + model)
|
|
738
1030
|
- id: gen_backend
|
|
@@ -764,32 +1056,18 @@ workflow:
|
|
|
764
1056
|
seams. The spec stays the only authority on BEHAVIOUR; the code is the authority
|
|
765
1057
|
on what the structure currently IS. With no source files this is a greenfield
|
|
766
1058
|
feature and there is nothing to conform to.
|
|
767
|
-
- Cover the four layers as sections: Domain (§1), Application (§2), API (§3
|
|
768
|
-
Infrastructure (§4). Keep the template's section
|
|
1059
|
+
- Cover the four layers as sections: Domain (§1), Application (§2), API (§3 — the
|
|
1060
|
+
one line pointing to api-plan.md), Infrastructure (§4). Keep the template's section
|
|
1061
|
+
order and headings.
|
|
1062
|
+
- {{be_api_rule}}
|
|
769
1063
|
- REALISE THE LIFTED CONSTRAINTS (each cites its spec id):
|
|
770
1064
|
• Constraints & NFRs (CN-) → structural ones (immutability, append-only audit,
|
|
771
1065
|
no-hard-delete) as §1 invariant enforcement/events; retention/performance/audit
|
|
772
1066
|
as §5 Cross-Cutting rows or §4 persistence.
|
|
773
|
-
• Data Classification (DC-) → §5 data-protection + the §2
|
|
774
|
-
|
|
1067
|
+
• Data Classification (DC-) → §5 data-protection + the §2 projections (what MUST
|
|
1068
|
+
NOT be exposed in responses, logs or traces).
|
|
775
1069
|
• Integration Contracts (IC-) → §4.2 External integrations (one port/adapter row
|
|
776
1070
|
per IC-), realising the obligation the spec named.
|
|
777
|
-
- PUBLISH THE SURFACE THE FRONTEND LANE BINDS TO. §3 states each endpoint's contract
|
|
778
|
-
as field shapes. That section is the ONLY part of this document the frontend plan
|
|
779
|
-
may read; keep it complete and self-contained, because a contract the UI needs and
|
|
780
|
-
this document never states becomes a client-side workaround.
|
|
781
|
-
- NAME EVERY ENDPOINT. Each §3 endpoint carries an **Operation id** — its name in the
|
|
782
|
-
service's published API document (e.g. `CreatePatient`), unique across the
|
|
783
|
-
service and never reused. The frontend plan cites it, and implement gives the
|
|
784
|
-
endpoint exactly this id, so the two lanes meet on it.
|
|
785
|
-
- ANSWER THE FRONTEND LANE'S CONTRACT REQUESTS. Still open in the frontend plan's §5
|
|
786
|
-
"Contract deltas needed": {{req_backend_text}}. Answer each one in §3's "Requests
|
|
787
|
-
from the frontend lane" table (| Request | Outcome | Operation id | Why |): PUBLISH
|
|
788
|
-
it as a §3 endpoint, under the operation id it proposes unless that clashes with
|
|
789
|
-
one this service already uses, or DECLINE it with the reason. Publish only what
|
|
790
|
-
the spec supports — a request the spec gives no basis for is declined as a spec gap
|
|
791
|
-
for /appweaver specify, never published on a guess. `none` means no request is
|
|
792
|
-
open: write `None` under that heading when the table would be empty.
|
|
793
1071
|
- CONSTITUTION-MANDATED CROSS-CUTTING (from the loaded technical constitution, NOT
|
|
794
1072
|
the spec): a NON-NEGOTIABLE technical principle you must apply that has NO
|
|
795
1073
|
per-feature spec id. APPLY it (it is non-negotiable), and because it is not
|
|
@@ -825,6 +1103,7 @@ workflow:
|
|
|
825
1103
|
- { path: "{{backend_plan}}" } # the scaffolded BROWNFIELD template = code-derived section structure
|
|
826
1104
|
- { path: "{{spec_file}}" } # BEHAVIOUR: FR/CN/DC/IC/US/SC + cited BR ids
|
|
827
1105
|
- { path: "{{domain_model}}", optional: true } # the CONTEXT's canonical model — entities, invariants, boundary
|
|
1106
|
+
- { path: "{{api_plan}}", optional: true } # the API plan authored just before — the endpoints §2 realises
|
|
828
1107
|
- { path: .appweaver/DESIGN-FORMAT.md } # the HLD contract (see its Brownfield variant note)
|
|
829
1108
|
- { path: knowledge/architecture/overview.md, optional: true } # the project's AS-BUILT architecture (onboard) — align to it
|
|
830
1109
|
- { path: knowledge/architecture/platform.md, optional: true } # the as-built technology base / cross-cutting reality
|
|
@@ -873,22 +1152,9 @@ workflow:
|
|
|
873
1152
|
(immutability, append-only audit, no-hard-delete) as §1.2 invariant enforcement /
|
|
874
1153
|
events; retention/performance/audit as §2 persistence or §3 Cross-Cutting rows.
|
|
875
1154
|
DC- → §3 data-protection + the projection surface (what MUST NOT be exposed in
|
|
876
|
-
|
|
877
|
-
-
|
|
878
|
-
|
|
879
|
-
part of this document the frontend plan may read.
|
|
880
|
-
- NAME EVERY ENDPOINT with its route, verb and operation id — its name in the
|
|
881
|
-
service's published API document, unique across the service. Where the code
|
|
882
|
-
already gives the endpoint one, record THAT id exactly as the code spells it; the
|
|
883
|
-
frontend plan cites it and implement finds the endpoint by it.
|
|
884
|
-
- ANSWER THE FRONTEND LANE'S CONTRACT REQUESTS. Still open in the frontend plan's
|
|
885
|
-
"Contract deltas needed" table: {{req_backend_text}}. Answer each one in a
|
|
886
|
-
"Requests from the frontend lane" table beside this feature's endpoints (| Request
|
|
887
|
-
| Outcome | Operation id | Why |): PUBLISH it as an endpoint, under the operation id
|
|
888
|
-
it proposes unless that clashes with one the service already uses, or DECLINE it
|
|
889
|
-
with the reason. Publish only what the spec supports — a request the spec gives no
|
|
890
|
-
basis for is declined as a spec gap for /appweaver specify. `none` means no request
|
|
891
|
-
is open: write `None` under that heading when the table would be empty.
|
|
1155
|
+
responses, logs or traces).
|
|
1156
|
+
- {{be_api_rule}} The §2 axis this project publishes its endpoints from ends with
|
|
1157
|
+
that line.
|
|
892
1158
|
- CONSTITUTION-MANDATED CROSS-CUTTING (from the loaded technical constitution, NOT
|
|
893
1159
|
the spec): a NON-NEGOTIABLE technical principle with no per-feature spec id —
|
|
894
1160
|
APPLY it, and LOG it as a §5 DA-n whose basis cites the mandating principle
|
|
@@ -927,6 +1193,7 @@ workflow:
|
|
|
927
1193
|
- { path: "{{backend_plan}}" } # the CURRENT master = what is being revised, and its section structure
|
|
928
1194
|
- { path: "{{spec_file}}" } # BEHAVIOUR, carrying every change finalize-delta has merged
|
|
929
1195
|
- { path: "{{domain_model}}", optional: true } # the CONTEXT's canonical model — entities, invariants, boundary
|
|
1196
|
+
- { path: "{{api_plan}}", optional: true } # the API plan revised just before — absent when no split moved the endpoints
|
|
930
1197
|
- { path: .appweaver/DESIGN-FORMAT.md } # the HLD contract
|
|
931
1198
|
- { path: .appweaver/memory/constitution.technical.md, optional: true } # technology base ONLY
|
|
932
1199
|
- id: gen_backend_update
|
|
@@ -958,17 +1225,7 @@ workflow:
|
|
|
958
1225
|
workarounds are DECISIONS THIS TEAM MADE, not derivations from the spec — keep
|
|
959
1226
|
every one, with its id and its basis, unless the thing it decided about is gone.
|
|
960
1227
|
Never renumber a surviving entry: its id is cited elsewhere.
|
|
961
|
-
-
|
|
962
|
-
the frontend plan and the built code both use it. A new endpoint gets one, unique
|
|
963
|
-
across the service; an endpoint without one gets one now.
|
|
964
|
-
- ANSWER THE FRONTEND LANE'S CONTRACT REQUESTS. Still open in the frontend plan's §5
|
|
965
|
-
"Contract deltas needed": {{req_backend_text}}. Answer each one in the "Requests
|
|
966
|
-
from the frontend lane" table of the API section (| Request | Outcome | Operation id
|
|
967
|
-
| Why |) — add the table if the document has none: PUBLISH it as an endpoint, under
|
|
968
|
-
the operation id it proposes unless that clashes with one already in use, or
|
|
969
|
-
DECLINE it with the reason. Publish only what the spec supports — a request the
|
|
970
|
-
spec gives no basis for is declined as a spec gap for /appweaver specify. Keep
|
|
971
|
-
every row the table already has. `none` means no request is open.
|
|
1228
|
+
- {{be_api_rule}}
|
|
972
1229
|
- THE CODE THAT EXISTS IS THE WHAT-IS AUTHORITY. {{source_count}} source file(s)
|
|
973
1230
|
realise this feature: {{source_files}}. READ them, and where the plan and the code
|
|
974
1231
|
disagree about STRUCTURE, the code is what is actually there — conform to it and
|
|
@@ -981,11 +1238,15 @@ workflow:
|
|
|
981
1238
|
(the spec ids and BR-nnn that drove it). Do NOT invent a version number — the
|
|
982
1239
|
version spine belongs to close-delta.
|
|
983
1240
|
|
|
984
|
-
# ══════════════ THE DRAFT — the
|
|
985
|
-
# api-draft.json beside the
|
|
986
|
-
#
|
|
987
|
-
#
|
|
988
|
-
#
|
|
1241
|
+
# ══════════════ THE DRAFT — the API plan as a document ═══════════════════════
|
|
1242
|
+
# api-draft.json beside the plans, drawn by script from the API plan as it now stands (the
|
|
1243
|
+
# backend plan's API section, for a feature planned before API plans existed): the API
|
|
1244
|
+
# contract between the lanes. The frontend lane generates its client from it, and
|
|
1245
|
+
# analyze-slice checks that the built service serves it. Rewritten only when it differs;
|
|
1246
|
+
# removed when the plan names no endpoint. Advisory — a plan the script cannot read
|
|
1247
|
+
# leaves the run going. Two things are reported: a shape it cannot type, because the
|
|
1248
|
+
# frontend's client gets that data untyped; and an operation the previous draft had and
|
|
1249
|
+
# this one does not, because the frontend may still bind to it.
|
|
989
1250
|
- id: contract_draft
|
|
990
1251
|
condition: "{{be_working}} == true"
|
|
991
1252
|
action: execute_script
|
|
@@ -994,8 +1255,33 @@ workflow:
|
|
|
994
1255
|
subcommand: contract-draft
|
|
995
1256
|
args: ["--feature-dir", "{{feature_dir}}"]
|
|
996
1257
|
outputs:
|
|
997
|
-
- { name: draft_path,
|
|
998
|
-
- { name:
|
|
1258
|
+
- { name: draft_path, from: "$.path" }
|
|
1259
|
+
- { name: draft_plan, from: "$.plan" }
|
|
1260
|
+
- { name: draft_ops, from: "$.operations" }
|
|
1261
|
+
- { name: draft_unread, from: "$.unread_count" }
|
|
1262
|
+
- { name: draft_unread_text, from: "$.unread_text" }
|
|
1263
|
+
- { name: draft_dropped, from: "$.dropped_count" }
|
|
1264
|
+
- { name: draft_dropped_text, from: "$.dropped_text" }
|
|
1265
|
+
- id: draft_unread_flag
|
|
1266
|
+
condition: "{{draft_unread}} != 0"
|
|
1267
|
+
action: set
|
|
1268
|
+
vars: { draft_clean: "false" }
|
|
1269
|
+
- id: warn_draft_unread
|
|
1270
|
+
condition: "{{be_working}} == true"
|
|
1271
|
+
action: verify_context
|
|
1272
|
+
require_true: draft_clean
|
|
1273
|
+
on_false: continue
|
|
1274
|
+
on_false_message: "API DRAFT — {{draft_unread}} endpoint shape(s) in {{draft_plan}} are not written as `{ field: type }`, so the frontend's client gets that data untyped: {{draft_unread_text}}. Write each request and response the way the template's endpoint block does, then re-run plan or analyze-plan."
|
|
1275
|
+
- id: draft_dropped_flag
|
|
1276
|
+
condition: "{{draft_dropped}} != 0"
|
|
1277
|
+
action: set
|
|
1278
|
+
vars: { draft_kept: "false" }
|
|
1279
|
+
- id: warn_draft_dropped
|
|
1280
|
+
condition: "{{be_working}} == true"
|
|
1281
|
+
action: verify_context
|
|
1282
|
+
require_true: draft_kept
|
|
1283
|
+
on_false: continue
|
|
1284
|
+
on_false_message: "API DRAFT — {{draft_dropped}} operation(s) the previous api-draft.json had are no longer in {{draft_plan}}: {{draft_dropped_text}}. The frontend lane may still bind to them. If this run removed them on purpose, the frontend plan has to stop binding to them; if not, restore their blocks in {{draft_plan}} and re-run plan or analyze-plan."
|
|
999
1285
|
|
|
1000
1286
|
# THE LEDGER AGAIN, for the frontend half: the backend plan may have just answered.
|
|
1001
1287
|
- id: contract_requests_frontend
|
|
@@ -1040,7 +1326,7 @@ workflow:
|
|
|
1040
1326
|
- { path: "{{domain_model}}", optional: true } # the ubiquitous language this lane's labels and messages use
|
|
1041
1327
|
- { path: .appweaver/DESIGN-FORMAT.md } # the design-doc contract + its frontend lane variant
|
|
1042
1328
|
- { path: .appweaver/memory/constitution.ui.md, optional: true } # the lane's ratified UX-* base — optional: a lane may be declared before it is ratified
|
|
1043
|
-
- { path: "{{
|
|
1329
|
+
- { path: "{{api_read}}", optional: true } # §5 ONLY — the service's API: api-plan.md, or the backend plan of a feature planned before it
|
|
1044
1330
|
- id: gen_frontend
|
|
1045
1331
|
condition: "{{fe_mode}} == bootstrap_gf"
|
|
1046
1332
|
action: agent_author
|
|
@@ -1084,22 +1370,23 @@ workflow:
|
|
|
1084
1370
|
gap: log it as a §8 DA-n and say it routes to `specify`; never invent the
|
|
1085
1371
|
requirement here.
|
|
1086
1372
|
- §5 IS THE LANE BOUNDARY. Bind against the service's PUBLISHED surface only —
|
|
1087
|
-
the spec's IC- ids, and where the
|
|
1088
|
-
|
|
1089
|
-
|
|
1373
|
+
the spec's IC- ids, and where the service's API is in context (api-plan.md, or the
|
|
1374
|
+
API section of a backend plan written before API plans existed), the endpoints it
|
|
1375
|
+
states. CITE those contracts; do NOT restate, re-derive or contradict them, and
|
|
1376
|
+
introduce NO server-side behaviour, persistence assumption or handler detail.
|
|
1090
1377
|
- WHAT THE SURFACE DOES NOT OFFER IS A CONTRACT REQUEST, never a workaround in the
|
|
1091
1378
|
client: one row in §5's "Contract deltas needed" table per operation, with a new
|
|
1092
1379
|
RQ-n (never renumber or reuse one), the operation id you propose, what it sends
|
|
1093
1380
|
and receives as field shapes, and the spec ids it serves. The binding row that
|
|
1094
1381
|
needs it cites that proposed id and names the RQ-n in its Serves cell. With NO
|
|
1095
|
-
|
|
1096
|
-
|
|
1382
|
+
API in context, EVERY binding is a request. The backend developer answers each in
|
|
1383
|
+
the API plan; this plan never edits that one.
|
|
1097
1384
|
- THE BACKEND'S ANSWERS SO FAR: {{req_frontend_text}}. Re-bind every binding row of
|
|
1098
1385
|
an answered request to the operation id the backend gave it, and plan around a
|
|
1099
1386
|
declined one — or log a §8 DA-n routing the need to /appweaver specify. `none`
|
|
1100
1387
|
means no answer is waiting on this plan.
|
|
1101
1388
|
- EVERY §5 ROW CITES ITS OPERATION ID, copied exactly from the endpoint's
|
|
1102
|
-
**Operation id** in the
|
|
1389
|
+
**Operation id** in the API in context, or the id its request proposes —
|
|
1103
1390
|
implement looks the endpoint up by it in the API document.
|
|
1104
1391
|
- CONSTITUTION-MANDATED CROSS-CUTTING (from the loaded UI constitution, NOT the
|
|
1105
1392
|
spec): a NON-NEGOTIABLE UX principle you must apply that has no per-feature spec
|
|
@@ -1142,7 +1429,7 @@ workflow:
|
|
|
1142
1429
|
- { path: .appweaver/DESIGN-FORMAT.md } # the design-doc contract + its frontend lane variant
|
|
1143
1430
|
- { path: .appweaver/memory/constitution.ui.md, optional: true } # the lane's UX-* base, reversed by onboard from this same UI
|
|
1144
1431
|
- { path: knowledge/architecture/frontend.md, optional: true } # the as-built UI architecture + the SHARED surface no slice owns
|
|
1145
|
-
- { path: "{{
|
|
1432
|
+
- { path: "{{api_read}}", optional: true } # §5 ONLY — the service's API: api-plan.md, or the backend plan of a feature planned before it
|
|
1146
1433
|
- id: gen_frontend_brownfield
|
|
1147
1434
|
condition: "{{fe_mode}} == bootstrap_bf"
|
|
1148
1435
|
action: agent_author
|
|
@@ -1182,19 +1469,20 @@ workflow:
|
|
|
1182
1469
|
or its logs, storage and URLs, IC- as binding rows, SC- as the performance
|
|
1183
1470
|
decision.
|
|
1184
1471
|
- THE LANE BOUNDARY: bind against the service's PUBLISHED surface only — the
|
|
1185
|
-
spec's IC- ids and, where the
|
|
1472
|
+
spec's IC- ids and, where the service's API is in context (api-plan.md, or the API
|
|
1473
|
+
section of a backend plan written before API plans existed), the endpoints it
|
|
1186
1474
|
states. Cite them; do not restate, re-derive or contradict them, and introduce no
|
|
1187
1475
|
server-side behaviour.
|
|
1188
1476
|
- WHAT THE SURFACE LACKS IS A CONTRACT REQUEST, never a client workaround: one row
|
|
1189
1477
|
in the "Contract deltas needed" table per operation, with a new RQ-n (never
|
|
1190
1478
|
renumbered or reused), the operation id you propose, what it sends and receives,
|
|
1191
1479
|
and the spec ids it serves; the binding row that needs it cites that id and names
|
|
1192
|
-
the RQ-n. With NO
|
|
1480
|
+
the RQ-n. With NO API in context, EVERY binding is a request.
|
|
1193
1481
|
- THE BACKEND'S ANSWERS SO FAR: {{req_frontend_text}}. Re-bind an answered
|
|
1194
1482
|
request's binding rows to the id the backend gave it; plan around a declined one,
|
|
1195
1483
|
or log a DA-n routing the need to /appweaver specify. `none` means nothing waits.
|
|
1196
|
-
- EVERY BINDING ROW CITES ITS OPERATION ID, copied exactly from the
|
|
1197
|
-
the id its request proposes — implement looks the endpoint up by it in the API
|
|
1484
|
+
- EVERY BINDING ROW CITES ITS OPERATION ID, copied exactly from the API in context,
|
|
1485
|
+
or the id its request proposes — implement looks the endpoint up by it in the API
|
|
1198
1486
|
document.
|
|
1199
1487
|
- CONSTITUTION-MANDATED CROSS-CUTTING with no per-feature spec id: apply it, and
|
|
1200
1488
|
log it as a DA-n citing the mandating principle ("per constitution.ui.md
|
|
@@ -1225,7 +1513,7 @@ workflow:
|
|
|
1225
1513
|
- { path: "{{domain_model}}", optional: true } # the ubiquitous language this lane's labels and messages use
|
|
1226
1514
|
- { path: .appweaver/DESIGN-FORMAT.md } # the design-doc contract + its frontend lane variant
|
|
1227
1515
|
- { path: .appweaver/memory/constitution.ui.md, optional: true } # the lane's ratified UX-* base
|
|
1228
|
-
- { path: "{{
|
|
1516
|
+
- { path: "{{api_read}}", optional: true } # §5 ONLY — the service's API: api-plan.md, or the backend plan of a feature planned before it
|
|
1229
1517
|
- id: gen_frontend_update
|
|
1230
1518
|
condition: "{{fe_mode}} == update"
|
|
1231
1519
|
action: agent_author
|
|
@@ -1251,20 +1539,21 @@ workflow:
|
|
|
1251
1539
|
source file(s) realise this feature: {{source_files}}. Read them and conform to
|
|
1252
1540
|
the component boundaries and naming actually there.
|
|
1253
1541
|
- THE LANE BOUNDARY IS UNCHANGED: bind against the service's PUBLISHED surface only
|
|
1254
|
-
— the spec's IC- ids and, where the
|
|
1255
|
-
|
|
1542
|
+
— the spec's IC- ids and, where the service's API is in context (api-plan.md, or
|
|
1543
|
+
the API section of a backend plan written before API plans existed), the
|
|
1544
|
+
endpoints it states.
|
|
1256
1545
|
- WHAT THE SURFACE LACKS IS A CONTRACT REQUEST, never a client workaround: one row
|
|
1257
1546
|
in §5's "Contract deltas needed" table per operation, with a new RQ-n, the
|
|
1258
1547
|
operation id you propose, what it sends and receives, and the spec ids it serves;
|
|
1259
1548
|
the binding row that needs it cites that id and names the RQ-n. KEEP every request
|
|
1260
|
-
already in the table with its id — the
|
|
1261
|
-
|
|
1549
|
+
already in the table with its id — the API plan's answers refer to it. With NO
|
|
1550
|
+
API in context, EVERY binding is a request.
|
|
1262
1551
|
- THE BACKEND'S ANSWERS SO FAR: {{req_frontend_text}}. Re-bind an answered
|
|
1263
1552
|
request's binding rows to the id the backend gave it; plan around a declined one,
|
|
1264
1553
|
or log a §8 DA-n routing the need to /appweaver specify. `none` means nothing waits.
|
|
1265
|
-
- EVERY BINDING ROW CITES ITS OPERATION ID, copied exactly from the
|
|
1554
|
+
- EVERY BINDING ROW CITES ITS OPERATION ID, copied exactly from the API in context or
|
|
1266
1555
|
the id its request proposes; a row that has none yet gets one now, and a row whose
|
|
1267
|
-
id the
|
|
1556
|
+
id the API no longer has is re-bound.
|
|
1268
1557
|
- TECHNOLOGY-AGNOSTIC: no framework, router, state library, component library or
|
|
1269
1558
|
styling approach — responsibilities, field shapes, events and states only.
|
|
1270
1559
|
- ADD ONE Change History row for this re-derivation, describing what MOVED and why.
|
|
@@ -1371,10 +1660,13 @@ workflow:
|
|
|
1371
1660
|
- { name: predecessor_ids, from: "$.predecessor_ids" }
|
|
1372
1661
|
- { name: sibling_count, from: "$.sibling_count" }
|
|
1373
1662
|
- { name: sibling_ids, from: "$.sibling_ids" }
|
|
1374
|
-
# THIS CHANGE'S
|
|
1375
|
-
#
|
|
1376
|
-
#
|
|
1663
|
+
# THIS CHANGE'S API, as READ context for its frontend delta plan — what the experience
|
|
1664
|
+
# binds to, which the backend developer may have authored in a run of their own: the
|
|
1665
|
+
# delta API plan, or the delta backend plan of a change planned before those.
|
|
1666
|
+
# Bound below only on a declared backend lane.
|
|
1377
1667
|
- { name: cr_delta_backend_plan, from: "$.delta_backend_plan" }
|
|
1668
|
+
- { name: cr_delta_api_plan, from: "$.delta_api_plan" }
|
|
1669
|
+
- { name: cr_delta_api_exists, from: "$.delta_api_plan_exists" }
|
|
1378
1670
|
# Predecessors AND siblings in one list: the delta plan is authored against both, and
|
|
1379
1671
|
# a build_context takes a single `context_from:` variable. Which entries are which is
|
|
1380
1672
|
# carried by predecessor_ids / sibling_ids, because the planner's licence over the two
|
|
@@ -1386,10 +1678,18 @@ workflow:
|
|
|
1386
1678
|
- { name: cr_touches_backend, from: "$.touches_backend" }
|
|
1387
1679
|
- { name: cr_touches_frontend, from: "$.touches_frontend" }
|
|
1388
1680
|
|
|
1389
|
-
- id:
|
|
1681
|
+
- id: delta_api_read_be
|
|
1390
1682
|
condition: "{{be_declared}} == true"
|
|
1391
1683
|
action: set
|
|
1392
|
-
vars: {
|
|
1684
|
+
vars: { delta_api_read: "{{cr_delta_backend_plan}}" }
|
|
1685
|
+
- id: delta_api_read_on_disk
|
|
1686
|
+
condition: "{{cr_delta_api_exists}} == true"
|
|
1687
|
+
action: set
|
|
1688
|
+
vars: { delta_api_read: "{{cr_delta_api_plan}}" }
|
|
1689
|
+
- id: delta_api_read_undeclared
|
|
1690
|
+
condition: "{{be_declared}} == false"
|
|
1691
|
+
action: set
|
|
1692
|
+
vars: { delta_api_read: "" }
|
|
1393
1693
|
|
|
1394
1694
|
# ONLY THE LANES THE CHANGE NAMES. be_existing / fe_existing already mean "a working lane
|
|
1395
1695
|
# with a master plan"; a lane the change's **Lanes** line leaves out is knocked down here,
|
|
@@ -1428,6 +1728,39 @@ workflow:
|
|
|
1428
1728
|
action: include
|
|
1429
1729
|
module: .appweaver/orchestrator/modules/delta-plan.orch.yaml
|
|
1430
1730
|
|
|
1731
|
+
# THE CHANGE'S API DRAFT — what its delta API plan adds, changes and removes in the
|
|
1732
|
+
# service's API (its delta backend plan's, for a change planned before delta API plans
|
|
1733
|
+
# existed), drawn by script into changes/<CR-id>/api-draft.json. While the change is
|
|
1734
|
+
# open the frontend lane binds to it over the feature's draft, analyze-slice-delta checks
|
|
1735
|
+
# the built service against it, and finalize-delta merges the change's API into the
|
|
1736
|
+
# feature's api-plan.md, whose redrawn draft then carries it.
|
|
1737
|
+
- id: draft_change_arm
|
|
1738
|
+
condition: "{{plan_target}} == delta"
|
|
1739
|
+
action: set
|
|
1740
|
+
vars: { draft_change_go: "{{be_existing}}" }
|
|
1741
|
+
- id: contract_draft_change
|
|
1742
|
+
condition: "{{draft_change_go}} == true"
|
|
1743
|
+
action: execute_script
|
|
1744
|
+
on_error: continue
|
|
1745
|
+
script: { ref: actions }
|
|
1746
|
+
subcommand: contract-draft
|
|
1747
|
+
args: ["--feature-dir", "{{feature_dir}}", "--cr", "{{cr_id}}"]
|
|
1748
|
+
outputs:
|
|
1749
|
+
- { name: change_draft_path, from: "$.path" }
|
|
1750
|
+
- { name: change_draft_plan, from: "$.plan" }
|
|
1751
|
+
- { name: change_draft_unread, from: "$.unread_count" }
|
|
1752
|
+
- { name: change_draft_unread_text, from: "$.unread_text" }
|
|
1753
|
+
- id: change_draft_unread_flag
|
|
1754
|
+
condition: "{{change_draft_unread}} != 0"
|
|
1755
|
+
action: set
|
|
1756
|
+
vars: { change_draft_clean: "false" }
|
|
1757
|
+
- id: warn_change_draft_unread
|
|
1758
|
+
condition: "{{draft_change_go}} == true"
|
|
1759
|
+
action: verify_context
|
|
1760
|
+
require_true: change_draft_clean
|
|
1761
|
+
on_false: continue
|
|
1762
|
+
on_false_message: "API DRAFT — {{change_draft_unread}} endpoint shape(s) in {{change_draft_plan}} are not written as `{ field: type }`, so the frontend's client gets that data untyped: {{change_draft_unread_text}}. Write each endpoint the change adds or changes as a whole block under its endpoints section, the way the API plan does, then re-run plan {{cr_id}} or analyze-plan-delta."
|
|
1763
|
+
|
|
1431
1764
|
# 6b. CROSS-SLICE EDGES, from the document that states them. `aw-xref record` reads the
|
|
1432
1765
|
# MASTER service plan — §1 References-by-id and the External integrations table — and
|
|
1433
1766
|
# writes a Cross-References row into every sibling aggregate this one uses. Its input
|
|
@@ -1468,10 +1801,11 @@ workflow:
|
|
|
1468
1801
|
# conformance gate) → implement. No change is opened either way.
|
|
1469
1802
|
# • DELTA → the chosen change stays OPEN with filled delta plans. Ship it via the CR
|
|
1470
1803
|
# chain: /appweaver analyze-plan-delta → implement → build → analyze-slice-delta
|
|
1471
|
-
# → finalize-delta (merges the delta into spec.md + domain-model.md
|
|
1472
|
-
# plans, which are derived from those
|
|
1473
|
-
# → close-delta (archives the change, bumps the
|
|
1474
|
-
# masters from the merged documents is `plan main`
|
|
1804
|
+
# → finalize-delta (merges the delta into spec.md + domain-model.md, and its delta
|
|
1805
|
+
# API plan into api-plan.md — not the lane plans, which are derived from those; the
|
|
1806
|
+
# change stays OPEN) → analyze-slice → close-delta (archives the change, bumps the
|
|
1807
|
+
# minor version). Re-deriving the masters from the merged documents is `plan main`
|
|
1808
|
+
# on a later run.
|
|
1475
1809
|
|
|
1476
1810
|
# 7. Post-execution hooks.
|
|
1477
1811
|
- id: resolve_post_hooks
|
|
@@ -1488,6 +1822,8 @@ workflow:
|
|
|
1488
1822
|
outputs:
|
|
1489
1823
|
feature_dir: "{{feature_dir}}"
|
|
1490
1824
|
bounded_context: "{{context}}"
|
|
1825
|
+
api_plan: "{{api_plan}}" # api-plan.md — the endpoints the service publishes, the API contract the frontend binds to
|
|
1826
|
+
api_mode: "{{api_mode}}" # author | update | skip (not the main path, not your lane, or no split moved the endpoints out of the backend plan)
|
|
1491
1827
|
backend_plan: "{{backend_plan}}" # empty when no backend lane is declared
|
|
1492
1828
|
frontend_plan: "{{frontend_plan}}" # empty when no frontend lane is declared
|
|
1493
1829
|
frontend_excluded: "{{fe_excluded}}" # true = a frontend lane is declared and this feature records no surface in it (feature-lanes)
|
|
@@ -1500,7 +1836,8 @@ outputs:
|
|
|
1500
1836
|
version: "{{version}}"
|
|
1501
1837
|
change_id: "{{active_change}}"
|
|
1502
1838
|
source_count: "{{source_count}}"
|
|
1503
|
-
api_draft: "{{draft_path}}" # api-draft.json, drafted by script from
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
1839
|
+
api_draft: "{{draft_path}}" # api-draft.json, drafted by script from {{draft_plan}} ({{draft_ops}} operation(s)) — the API contract the frontend binds to; commit it with the plans
|
|
1840
|
+
change_api_draft: "{{change_draft_path}}" # on the delta path: changes/<CR-id>/api-draft.json, the change's API changes — commit it with the change
|
|
1841
|
+
contract_requests: "{{req_summary}}" # the frontend plan's RQ-n requests and the API plan's answers
|
|
1842
|
+
note: "This run was pointed at `{{plan_target}}` (plan_mode {{plan_mode}}); backend lane {{be_mode}}, frontend lane {{fe_mode}}. Lanes come from .appweaver/stacks.json: backend declared = {{be_declared}}, frontend declared = {{fe_declared}}; your working lane is `{{working_lane}}` (.appweaver/lane.json — backend worked = {{be_working}}, frontend worked = {{fe_working}}). A working lane gets a plan; a declared lane you do not work on is read, never written, and an undeclared one gets nothing — neither is a failure. Contract requests: {{req_summary}} — the frontend plan raises them in §5 'Contract deltas needed' and the API plan answers them; commit the plans so the other lane's developer sees them. The API plan: api_mode {{api_mode}} — `author` or `update` means it was written before the backend plan, which realises its endpoints; `skip` means this run did not write it (not the main path, not your lane, or the endpoints are still in the backend plan). A lane whose mode is `update` had its MASTER re-derived from the current spec and model, with its DA-n and WA-n ledgers carried forward — that rewrite was confirmed before it ran. The domain model at {{domain_model}} was READ, never written — it is spec-tier, and this phase records where each invariant is ENFORCED rather than what it says."
|
|
1843
|
+
next: "MAIN (masters authored or re-derived): /appweaver analyze-plan (spec↔plan gate) → implement. DELTA (change {{active_change}} open, delta plans authored): /appweaver analyze-plan-delta → implement → build → analyze-slice-delta → finalize-delta → analyze-slice → close-delta — implement is the same command on both paths and ASKS which open change it is building, so pass the id (/appweaver implement {{active_change}}) to skip the prompt (finalize-delta merges the delta into spec.md and domain-model.md, and its delta API plan into api-plan.md — not the lane plans, which are derived from those — but leaves the change open; analyze-slice verifies the slice against the merged masters; close-delta archives the change and bumps the minor version). Once a change has merged, /appweaver plan main re-derives the masters from the documents it merged into."
|