aw-spec-cli 0.1.16 → 0.1.17
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/assets/.appweaver/DESIGN-FORMAT.md +18 -18
- package/assets/.appweaver/ORCH-DIALECT.md +1 -3
- package/assets/.appweaver/RULE-PARTITION.md +29 -13
- package/assets/.appweaver/STACK-PROFILES.md +10 -9
- package/assets/.appweaver/orchestrator/.state/smoke.state.json +32 -0
- package/assets/.appweaver/orchestrator/AGENT-PROFILE.md +4 -1
- package/assets/.appweaver/orchestrator/modules/delta-plan.orch.yaml +251 -0
- package/assets/.appweaver/orchestrator/modules/delta-spec.orch.yaml +104 -35
- package/assets/.appweaver/orchestrator/orchestrator.py +5 -4
- package/assets/.appweaver/orchestrator/rev-templates/delta-design-template.skeleton.md +94 -36
- package/assets/.appweaver/orchestrator/rev-templates/design-template.skeleton.md +1 -1
- package/assets/.appweaver/orchestrator/rev-templates/domain-model-template.skeleton.md +115 -0
- package/assets/.appweaver/orchestrator/rev-templates/domain-rule-bindings.skeleton.md +2 -9
- package/assets/.appweaver/orchestrator/rev-templates/tech-rule-bindings.skeleton.md +16 -40
- package/assets/.appweaver/orchestrator/rev-templates/ui-delta-design-template.skeleton.md +38 -17
- package/assets/.appweaver/orchestrator/rev-templates/ui-design-template.skeleton.md +8 -8
- package/assets/.appweaver/orchestrator/workflows/aw-spec-adopt.orch.yaml +10 -11
- package/assets/.appweaver/orchestrator/workflows/aw-spec-analyze-plan-delta.orch.yaml +673 -0
- package/assets/.appweaver/orchestrator/workflows/aw-spec-analyze-plan.orch.yaml +535 -0
- package/assets/.appweaver/orchestrator/workflows/aw-spec-analyze-slice-delta.orch.yaml +643 -0
- package/assets/.appweaver/orchestrator/workflows/aw-spec-analyze-slice.orch.yaml +84 -701
- package/assets/.appweaver/orchestrator/workflows/aw-spec-build.orch.yaml +4 -4
- package/assets/.appweaver/orchestrator/workflows/aw-spec-characterize.orch.yaml +7 -7
- package/assets/.appweaver/orchestrator/workflows/aw-spec-close-delta.orch.yaml +16 -14
- package/assets/.appweaver/orchestrator/workflows/aw-spec-constitution.orch.yaml +2 -2
- package/assets/.appweaver/orchestrator/workflows/aw-spec-finalize-delta.orch.yaml +243 -144
- package/assets/.appweaver/orchestrator/workflows/aw-spec-implement.orch.yaml +877 -578
- package/assets/.appweaver/orchestrator/workflows/aw-spec-inventory.orch.yaml +4 -4
- package/assets/.appweaver/orchestrator/workflows/aw-spec-onboard.orch.yaml +32 -91
- package/assets/.appweaver/orchestrator/workflows/aw-spec-parity.orch.yaml +2 -2
- package/assets/.appweaver/orchestrator/workflows/aw-spec-plan.orch.yaml +836 -514
- package/assets/.appweaver/orchestrator/workflows/aw-spec-run.orch.yaml +2 -2
- package/assets/.appweaver/orchestrator/workflows/aw-spec-select-bounded-context.orch.yaml +132 -0
- package/assets/.appweaver/orchestrator/workflows/aw-spec-select-feature.orch.yaml +38 -5
- package/assets/.appweaver/orchestrator/workflows/aw-spec-select-stack.orch.yaml +3 -3
- package/assets/.appweaver/orchestrator/workflows/aw-spec-specify.orch.yaml +271 -979
- package/assets/.appweaver/scripts/bash/aw-spec-actions.sh +1085 -3385
- package/assets/.appweaver/scripts/bash/aw-xref.sh +1 -2
- package/assets/.appweaver/scripts/bash/common.sh +47 -0
- package/assets/.appweaver/scripts/powershell/aw-spec-actions.ps1 +914 -3220
- package/assets/.appweaver/scripts/powershell/aw-xref.ps1 +1 -2
- package/assets/.appweaver/scripts/python/aw-payload-parity.py +19 -3
- package/assets/.appweaver/scripts/python/aw-stack.py +6 -2
- package/assets/.appweaver/scripts/python/aw-xref.py +86 -350
- package/assets/.appweaver/templates/constitution-ui-template.md +1 -1
- package/assets/.appweaver/templates/delta-design-template.md +120 -30
- package/assets/.appweaver/templates/delta-domain-model-template.md +81 -0
- package/assets/.appweaver/templates/delta-spec-template.md +43 -17
- package/assets/.appweaver/templates/design-template.md +68 -98
- package/assets/.appweaver/templates/domain-model-template.md +130 -0
- package/assets/.appweaver/templates/okf-concept-template.md +2 -2
- package/assets/.appweaver/templates/source-map-template.md +3 -3
- package/assets/.appweaver/templates/spec-template.md +100 -122
- package/assets/.appweaver/templates/ui-delta-design-template.md +159 -0
- package/assets/.appweaver/templates/ui-design-template.md +46 -75
- package/assets/guardrails/projects/dotnet-default-project/domain-rule-bindings.md +7 -18
- package/assets/guardrails/projects/dotnet-default-project/tech-rule-bindings.md +34 -39
- package/assets/guardrails/requirement-spec.txt +2 -2
- package/assets/guardrails/technology/dotnet-webapi/testing.md +1 -1
- package/package.json +1 -1
- package/assets/.appweaver/orchestrator/modules/delta-design.orch.yaml +0 -105
- package/assets/.appweaver/orchestrator/modules/spec-state-gate.orch.yaml +0 -87
- package/assets/.appweaver/orchestrator/workflows/aw-spec-analyze-delta-design.orch.yaml +0 -251
- package/assets/.appweaver/orchestrator/workflows/aw-spec-analyze-design.orch.yaml +0 -813
- package/assets/.appweaver/orchestrator/workflows/aw-spec-implement-delta.orch.yaml +0 -253
- package/assets/.appweaver/orchestrator/workflows/aw-spec-implement-ui.orch.yaml +0 -663
- package/assets/.appweaver/orchestrator/workflows/aw-spec-plan-ui.orch.yaml +0 -600
- package/assets/.appweaver/orchestrator/workflows/aw-spec-story-plan.orch.yaml +0 -1147
- package/assets/.appweaver/orchestrator/workflows/aw-spec-sync-stories.orch.yaml +0 -1121
- package/assets/.appweaver/templates/story-template.md +0 -178
|
@@ -0,0 +1,673 @@
|
|
|
1
|
+
# =============================================================================
|
|
2
|
+
# aw-spec-analyze-plan-delta (orchestrator) — the delta-spec↔delta-plan GATE, BOTH LANES
|
|
3
|
+
#
|
|
4
|
+
# The CR analog of analyze-plan, scoped to ONE open change. The delta spec is the ANCHOR:
|
|
5
|
+
# confirm this change's delta plans STRICTLY realise it, and that everything they claim to
|
|
6
|
+
# MODIFY really exists in the masters. This stage VALIDATES the delta only — it does NOT
|
|
7
|
+
# touch spec.md / the master plans / domain-model.md, and it does NOT close the change
|
|
8
|
+
# (finalize-delta merges the delta later; close-delta closes it at the very end).
|
|
9
|
+
#
|
|
10
|
+
# IT ASKS WHICH CHANGE, exactly as `plan` does. Many changes may be open on one feature, so
|
|
11
|
+
# this gate LISTS them and asks rather than inferring one. A bare CR id in the command's
|
|
12
|
+
# argument selects without a prompt, one open change auto-confirms, and the chosen change
|
|
13
|
+
# is ACTIVATED so the stages after this one act on the same delta.
|
|
14
|
+
#
|
|
15
|
+
# THE FIVE CHECKS:
|
|
16
|
+
# 1. delta-spec.md → delta-backend-plan.md — every ADDED/MODIFIED spec item realised
|
|
17
|
+
# 2. delta-spec.md → delta-frontend-plan.md — every experience item realised
|
|
18
|
+
# 3. delta plan ↔ delta plan — CONTRACT BINDING across the change: what the frontend
|
|
19
|
+
# delta binds to must appear in the service delta's "Contract deltas for the frontend
|
|
20
|
+
# lane" table or in the master's published surface. A call neither publishes passes
|
|
21
|
+
# both one-sided checks and fails at integration.
|
|
22
|
+
# 4. THE EFFECTIVE MODEL — domain-model.md + this change's model delta + the model
|
|
23
|
+
# deltas of every LOWER-WAVE change (its predecessors). Every structural item the
|
|
24
|
+
# model delta adds has a realisation row; nothing structural is invented in a plan.
|
|
25
|
+
# 5. MASTER INTEGRITY — every MODIFIED element names something the master plan really
|
|
26
|
+
# defines, and every MODIFIED spec id something spec.md really defines. You cannot
|
|
27
|
+
# modify what does not exist; that is an ADD.
|
|
28
|
+
# Plus the OVERLAY BACKSTOP (the domain gate checklist over the constraints this change
|
|
29
|
+
# touches), and the WAVE DISCIPLINE check below.
|
|
30
|
+
#
|
|
31
|
+
# PREDECESSORS, NOT SIBLINGS. A wave is a dependency level. A LOWER-wave change is
|
|
32
|
+
# committed to landing first, so this delta may be planned on top of it — and both halves
|
|
33
|
+
# of each predecessor are in context, its model delta AND its delta-spec, because a plan
|
|
34
|
+
# that realises a predecessor's behaviour without its spec cannot be told apart from one
|
|
35
|
+
# that invented it. A SAME-wave change is ordered against this one by nothing at all: it
|
|
36
|
+
# is visible so it can be designed around, and building on it silently is the defect this
|
|
37
|
+
# check exists to catch.
|
|
38
|
+
#
|
|
39
|
+
# OVERLAP IS COMPUTED, NOT ASKED. cr-overlap reads the `## Aggregate:` headings of every
|
|
40
|
+
# pending model delta and reports which other open changes touch the same aggregates.
|
|
41
|
+
# That is a fact about two files, so a regex answers it exactly and the result is handed
|
|
42
|
+
# to the model as a finding rather than as a question.
|
|
43
|
+
#
|
|
44
|
+
# specify → plan → ⟨review⟩ → analyze-plan-delta ← you are here
|
|
45
|
+
# → implement → build → analyze-slice-delta → finalize-delta → analyze-slice
|
|
46
|
+
# → close-delta
|
|
47
|
+
#
|
|
48
|
+
# RENAMED FROM `analyze-delta-design`, following design → plan, and it absorbs the
|
|
49
|
+
# frontend half that never existed as its own command.
|
|
50
|
+
#
|
|
51
|
+
# Launch: /appweaver analyze-plan-delta [CR-id]
|
|
52
|
+
# Prereq: /appweaver specify (delta-spec + model delta) + /appweaver plan (delta plans).
|
|
53
|
+
# =============================================================================
|
|
54
|
+
|
|
55
|
+
name: aw-spec-analyze-plan-delta
|
|
56
|
+
description: The delta-spec↔delta-plan conformance gate for ONE open change — confirm its delta-backend-plan.md and delta-frontend-plan.md realise delta-spec.md, bind to each other's contract deltas, realise this change's domain model delta, and only MODIFY elements the masters really define. Checked against the EFFECTIVE model (domain-model.md plus this change's model delta plus every lower-wave predecessor's, whose delta-specs are in context too) and told, deterministically, which other open changes touch the same aggregates. Asks which open change it is gating when more than one is open; a CR id as the argument selects without a prompt. Does not modify the masters or close the change.
|
|
57
|
+
version: 2.0.0
|
|
58
|
+
agent_agnostic: true
|
|
59
|
+
dialect: aw-spec.orchestrator/v1
|
|
60
|
+
|
|
61
|
+
inputs:
|
|
62
|
+
user_input:
|
|
63
|
+
description: "The open change to gate — a bare CR id selects it without a prompt. Omitted, the run lists the open changes and asks."
|
|
64
|
+
required: false
|
|
65
|
+
bind: USER_INPUT
|
|
66
|
+
|
|
67
|
+
scripts:
|
|
68
|
+
actions:
|
|
69
|
+
sh: .appweaver/scripts/bash/aw-spec-actions.sh
|
|
70
|
+
ps1: .appweaver/scripts/powershell/aw-spec-actions.ps1
|
|
71
|
+
|
|
72
|
+
standards:
|
|
73
|
+
- { path: .appweaver/ai-rules.md } # kit-resident: the universal operating rules, every flow
|
|
74
|
+
|
|
75
|
+
vars:
|
|
76
|
+
analyze_ok: "false"
|
|
77
|
+
lanes_declared: "false"
|
|
78
|
+
be_declared: "false"
|
|
79
|
+
fe_declared: "false"
|
|
80
|
+
has_changes: "false"
|
|
81
|
+
cr_choice: ""
|
|
82
|
+
cr_id: ""
|
|
83
|
+
wave: "1"
|
|
84
|
+
predecessor_docs: [] # each lower-wave change's model delta AND its delta-spec
|
|
85
|
+
predecessor_count: "0"
|
|
86
|
+
sibling_count: "0"
|
|
87
|
+
overlap_report: ""
|
|
88
|
+
# PER-LANE PRESENCE. A lane is gated when it is declared AND has a master plan (only
|
|
89
|
+
# then is there a base for a delta) AND this change has a delta plan for it. The engine
|
|
90
|
+
# has no compound conditions, so each AND is one ordered assignment.
|
|
91
|
+
be_gated: "false" # declared AND a master plan exists
|
|
92
|
+
fe_gated: "false"
|
|
93
|
+
be_present: "false" # gated AND this change's delta plan exists ⇒ check it
|
|
94
|
+
fe_present: "false"
|
|
95
|
+
be_missing: "false" # gated AND it does NOT ⇒ `plan` has not run for this change
|
|
96
|
+
fe_missing: "false"
|
|
97
|
+
deltas_ok: "true"
|
|
98
|
+
any_lane: "false"
|
|
99
|
+
both_lanes: "false" # both delta plans present ⇒ the contract check applies
|
|
100
|
+
be_repair: "false"
|
|
101
|
+
fe_repair: "false"
|
|
102
|
+
backend_repair: "false"
|
|
103
|
+
frontend_repair: "false"
|
|
104
|
+
delta_backend_plan: ""
|
|
105
|
+
delta_frontend_plan: ""
|
|
106
|
+
# The plan paths AS CONTEXT — bound only for a lane this run actually gates. feature-paths
|
|
107
|
+
# and cr-paths resolve every path whatever the declaration says, so putting them straight
|
|
108
|
+
# into the envelope would show the gate documents belonging to a lane nobody declared.
|
|
109
|
+
# An unbound var renders empty and the engine drops it.
|
|
110
|
+
be_master_ctx: ""
|
|
111
|
+
fe_master_ctx: ""
|
|
112
|
+
be_delta_ctx: ""
|
|
113
|
+
fe_delta_ctx: ""
|
|
114
|
+
domain_model: ""
|
|
115
|
+
|
|
116
|
+
workflow:
|
|
117
|
+
|
|
118
|
+
# 0. WHICH LANES EXIST — the same declaration `plan` wrote against.
|
|
119
|
+
- id: lane_resolve
|
|
120
|
+
action: execute_script
|
|
121
|
+
on_error: continue # never crash raw on an undeclared lane — the gate below explains it
|
|
122
|
+
script: { ref: actions }
|
|
123
|
+
subcommand: lane-resolve
|
|
124
|
+
outputs:
|
|
125
|
+
- { name: lanes_declared, from: "$.declared" }
|
|
126
|
+
- { name: be_declared, from: "$.backend_declared" }
|
|
127
|
+
- { name: fe_declared, from: "$.frontend_declared" }
|
|
128
|
+
|
|
129
|
+
- id: require_lane
|
|
130
|
+
action: verify_context
|
|
131
|
+
require_true: lanes_declared
|
|
132
|
+
on_false: stop
|
|
133
|
+
on_false_message: "No lane is declared in .appweaver/stacks.json, so there is no delta plan to gate. Run /appweaver select-stack, then /appweaver plan, then re-run analyze-plan-delta."
|
|
134
|
+
|
|
135
|
+
# 1. Resolve the current feature, its spec and its MASTER plans — the base every
|
|
136
|
+
# MODIFIED element in a delta has to name.
|
|
137
|
+
- id: feature_paths
|
|
138
|
+
action: execute_script
|
|
139
|
+
on_error: continue # never crash raw on 'no feature set' — the gate below explains it
|
|
140
|
+
script: { ref: actions }
|
|
141
|
+
subcommand: feature-paths
|
|
142
|
+
outputs:
|
|
143
|
+
- { name: feature, from: "$.feature" }
|
|
144
|
+
- { name: feature_dir, from: "$.feature_dir" }
|
|
145
|
+
- { name: spec_file, from: "$.spec_file" }
|
|
146
|
+
- { name: spec_exists, from: "$.spec_exists" }
|
|
147
|
+
- { name: backend_plan, from: "$.backend_plan" }
|
|
148
|
+
- { name: frontend_plan, from: "$.frontend_plan" }
|
|
149
|
+
- { name: backend_plan_exists, from: "$.backend_plan_exists" }
|
|
150
|
+
- { name: frontend_plan_exists, from: "$.frontend_plan_exists" }
|
|
151
|
+
|
|
152
|
+
- id: require_feature
|
|
153
|
+
action: verify_context
|
|
154
|
+
require_non_empty: feature_dir
|
|
155
|
+
on_empty: stop
|
|
156
|
+
on_empty_message: "No active feature. Run /appweaver select-feature first (pick or create the aggregate, e.g. Order), then re-run analyze-plan-delta."
|
|
157
|
+
|
|
158
|
+
- id: verify_spec
|
|
159
|
+
action: verify_context
|
|
160
|
+
require_true: spec_exists
|
|
161
|
+
on_false: stop
|
|
162
|
+
on_false_message: "No spec.md for the current feature. Run /appweaver specify (and /appweaver plan) first."
|
|
163
|
+
|
|
164
|
+
# 2. WHICH CHANGES ARE OPEN. The evidence is changes/<cr-id>/ on disk; a closed change
|
|
165
|
+
# has moved to changes/archive/. `matched_label` resolves a CR id passed as the
|
|
166
|
+
# command's argument to the whole option string, so the pick below can auto-select it
|
|
167
|
+
# — the engine matches a preselection against the option text exactly.
|
|
168
|
+
- id: cr_list
|
|
169
|
+
action: execute_script
|
|
170
|
+
script: { ref: actions }
|
|
171
|
+
subcommand: cr-list
|
|
172
|
+
args: ["--feature-dir", "{{feature_dir}}", "--preselect", "{{USER_INPUT}}"]
|
|
173
|
+
outputs:
|
|
174
|
+
- { name: change_options, from: "$.select_options" }
|
|
175
|
+
- { name: matched_label, from: "$.matched_label" }
|
|
176
|
+
- { name: has_changes, from: "$.has_changes" }
|
|
177
|
+
- { name: change_count, from: "$.count" }
|
|
178
|
+
|
|
179
|
+
- id: require_change
|
|
180
|
+
action: verify_context
|
|
181
|
+
require_true: has_changes
|
|
182
|
+
on_false: stop
|
|
183
|
+
on_false_message: "No open change on this feature — there is no delta to gate. Run /appweaver specify <change> (which opens the change and writes its delta-spec + model delta), then /appweaver plan to author its delta plans, then re-run analyze-plan-delta. To re-anchor the MASTERS instead, run /appweaver analyze-plan."
|
|
184
|
+
|
|
185
|
+
# 2b. Ask which one. A CR id in the argument auto-selects via matched_label; a feature
|
|
186
|
+
# with exactly one open change auto-confirms.
|
|
187
|
+
- id: pick_change
|
|
188
|
+
action: user_select
|
|
189
|
+
prompt: "Which open change is this gate for? Deltas sharing a wave are independent; a higher wave is planned on top of the lower ones."
|
|
190
|
+
options_from_variable: change_options
|
|
191
|
+
preselect_from: matched_label
|
|
192
|
+
single_option_confirm: true
|
|
193
|
+
outputs:
|
|
194
|
+
- { name: cr_choice, from: selection }
|
|
195
|
+
|
|
196
|
+
# 2c. Make the chosen change the ACTIVE one. finalize-delta and close-delta still resolve
|
|
197
|
+
# the change through active_version.json.active_change (implement asks again, and
|
|
198
|
+
# re-activates whatever it is answered), so without this a delta gated here could be
|
|
199
|
+
# merged as a different one.
|
|
200
|
+
- id: activate
|
|
201
|
+
action: execute_script
|
|
202
|
+
script: { ref: actions }
|
|
203
|
+
subcommand: cr-activate
|
|
204
|
+
args: ["--cr-id", "{{cr_choice}}", "--feature-dir", "{{feature_dir}}"]
|
|
205
|
+
outputs:
|
|
206
|
+
- { name: active_change, from: "$.active_change" }
|
|
207
|
+
|
|
208
|
+
# 3. The change's documents, its wave, and everything that comes BEFORE it —
|
|
209
|
+
# predecessor_docs carries each lower-wave change's model delta AND its delta-spec,
|
|
210
|
+
# which is what a build_context `context_from:` inlines below.
|
|
211
|
+
- id: cr_paths
|
|
212
|
+
action: execute_script
|
|
213
|
+
script: { ref: actions }
|
|
214
|
+
subcommand: cr-paths
|
|
215
|
+
args: ["--cr-id", "{{cr_choice}}", "--feature-dir", "{{feature_dir}}"]
|
|
216
|
+
outputs:
|
|
217
|
+
- { name: cr_id, from: "$.cr_id" } # normalised: the label's first token
|
|
218
|
+
- { name: cr_dir, from: "$.cr_dir" }
|
|
219
|
+
- { name: delta_spec, from: "$.delta_spec" }
|
|
220
|
+
- { name: delta_spec_exists, from: "$.delta_spec_exists" }
|
|
221
|
+
- { name: delta_model, from: "$.delta_model" }
|
|
222
|
+
- { name: delta_backend_plan, from: "$.delta_backend_plan" }
|
|
223
|
+
- { name: delta_frontend_plan, from: "$.delta_frontend_plan" }
|
|
224
|
+
- { name: delta_backend_plan_exists, from: "$.delta_backend_plan_exists" }
|
|
225
|
+
- { name: delta_frontend_plan_exists, from: "$.delta_frontend_plan_exists" }
|
|
226
|
+
- { name: wave, from: "$.wave" }
|
|
227
|
+
- { name: predecessor_docs, from: "$.predecessor_docs" }
|
|
228
|
+
- { name: predecessor_count, from: "$.predecessor_count" }
|
|
229
|
+
- { name: sibling_count, from: "$.sibling_count" }
|
|
230
|
+
- { name: domain_model, from: "$.domain_model" }
|
|
231
|
+
|
|
232
|
+
# 3b. WHICH OTHER OPEN CHANGES TOUCH THE SAME AGGREGATES. Deterministic: the
|
|
233
|
+
# `## Aggregate:` headings of the pending model deltas are the merge unit
|
|
234
|
+
# domain-model.md is organised by, so this is a regex over two files rather than a
|
|
235
|
+
# judgement. The result reaches the check below as a FINDING, not a question.
|
|
236
|
+
- id: cr_overlap
|
|
237
|
+
action: execute_script
|
|
238
|
+
on_error: continue
|
|
239
|
+
script: { ref: actions }
|
|
240
|
+
subcommand: cr-overlap
|
|
241
|
+
args: ["--cr-id", "{{cr_id}}", "--feature-dir", "{{feature_dir}}"]
|
|
242
|
+
outputs:
|
|
243
|
+
- { name: overlap_report, from: "$.overlap_report" }
|
|
244
|
+
- { name: overlap_count, from: "$.overlap_count" }
|
|
245
|
+
- { name: sibling_overlaps, from: "$.sibling_overlaps" }
|
|
246
|
+
- { name: predecessor_overlaps, from: "$.predecessor_overlaps" }
|
|
247
|
+
|
|
248
|
+
# 4. WHICH LANES ARE GATED. Declared AND a master plan exists (only then is there a base
|
|
249
|
+
# for a delta) — then split on whether this change has that lane's delta plan.
|
|
250
|
+
# A lane whose MASTER was bootstrapped in the same `plan` run has no delta plan by
|
|
251
|
+
# design: it was authored from the whole spec and there is nothing for a delta to
|
|
252
|
+
# add. Keying on the master's presence is what keeps that case out of the gate.
|
|
253
|
+
- id: be_flag_gated
|
|
254
|
+
condition: "{{backend_plan_exists}} == true"
|
|
255
|
+
action: set
|
|
256
|
+
vars: { be_gated: "{{be_declared}}" }
|
|
257
|
+
- id: fe_flag_gated
|
|
258
|
+
condition: "{{frontend_plan_exists}} == true"
|
|
259
|
+
action: set
|
|
260
|
+
vars: { fe_gated: "{{fe_declared}}" }
|
|
261
|
+
- id: be_flag_present
|
|
262
|
+
condition: "{{delta_backend_plan_exists}} == true"
|
|
263
|
+
action: set
|
|
264
|
+
vars: { be_present: "{{be_gated}}" }
|
|
265
|
+
- id: be_flag_missing
|
|
266
|
+
condition: "{{delta_backend_plan_exists}} == false"
|
|
267
|
+
action: set
|
|
268
|
+
vars: { be_missing: "{{be_gated}}" }
|
|
269
|
+
- id: fe_flag_present
|
|
270
|
+
condition: "{{delta_frontend_plan_exists}} == true"
|
|
271
|
+
action: set
|
|
272
|
+
vars: { fe_present: "{{fe_gated}}" }
|
|
273
|
+
- id: fe_flag_missing
|
|
274
|
+
condition: "{{delta_frontend_plan_exists}} == false"
|
|
275
|
+
action: set
|
|
276
|
+
vars: { fe_missing: "{{fe_gated}}" }
|
|
277
|
+
|
|
278
|
+
# A lane with a master but no delta plan for this change is not a gap this gate repairs
|
|
279
|
+
# — it is work `plan` has not done for this change. Two independent raises.
|
|
280
|
+
- id: deltas_not_ok_backend
|
|
281
|
+
condition: "{{be_missing}} == true"
|
|
282
|
+
action: set
|
|
283
|
+
vars: { deltas_ok: "false" }
|
|
284
|
+
- id: deltas_not_ok_frontend
|
|
285
|
+
condition: "{{fe_missing}} == true"
|
|
286
|
+
action: set
|
|
287
|
+
vars: { deltas_ok: "false" }
|
|
288
|
+
|
|
289
|
+
- id: require_deltas
|
|
290
|
+
action: verify_context
|
|
291
|
+
require_true: deltas_ok
|
|
292
|
+
on_false: stop
|
|
293
|
+
on_false_message: "Change {{cr_id}} has no delta plan for a lane that has a master plan (backend missing={{be_missing}} · frontend missing={{fe_missing}}). Run /appweaver plan {{cr_id}} — it authors that change's delta plan for every lane whose master exists, against the delta spec, the effective model and the feature's real source files. This gate validates a delta plan; it does not write one."
|
|
294
|
+
|
|
295
|
+
- id: any_backend
|
|
296
|
+
condition: "{{be_present}} == true"
|
|
297
|
+
action: set
|
|
298
|
+
vars: { any_lane: "true" }
|
|
299
|
+
- id: any_frontend
|
|
300
|
+
condition: "{{fe_present}} == true"
|
|
301
|
+
action: set
|
|
302
|
+
vars: { any_lane: "true" }
|
|
303
|
+
|
|
304
|
+
- id: require_any_lane
|
|
305
|
+
action: verify_context
|
|
306
|
+
require_true: any_lane
|
|
307
|
+
on_false: stop
|
|
308
|
+
on_false_message: "Change {{cr_id}} has no delta plan to gate on any declared lane. Run /appweaver plan {{cr_id}} first."
|
|
309
|
+
|
|
310
|
+
# Check 3 needs BOTH delta plans. One more ordered assignment.
|
|
311
|
+
- id: flag_both_lanes
|
|
312
|
+
condition: "{{be_present}} == true"
|
|
313
|
+
action: set
|
|
314
|
+
vars: { both_lanes: "{{fe_present}}" }
|
|
315
|
+
|
|
316
|
+
# Bind the CONTEXT paths per lane: the master (the base a MODIFIED element must name) for
|
|
317
|
+
# a gated lane, the delta plan for a present one. A lane that is neither leaves both
|
|
318
|
+
# empty, so its documents never reach the payload.
|
|
319
|
+
- id: be_master_ctx_path
|
|
320
|
+
condition: "{{be_gated}} == true"
|
|
321
|
+
action: set
|
|
322
|
+
vars: { be_master_ctx: "{{backend_plan}}" }
|
|
323
|
+
- id: fe_master_ctx_path
|
|
324
|
+
condition: "{{fe_gated}} == true"
|
|
325
|
+
action: set
|
|
326
|
+
vars: { fe_master_ctx: "{{frontend_plan}}" }
|
|
327
|
+
- id: be_delta_ctx_path
|
|
328
|
+
condition: "{{be_present}} == true"
|
|
329
|
+
action: set
|
|
330
|
+
vars: { be_delta_ctx: "{{delta_backend_plan}}" }
|
|
331
|
+
- id: fe_delta_ctx_path
|
|
332
|
+
condition: "{{fe_present}} == true"
|
|
333
|
+
action: set
|
|
334
|
+
vars: { fe_delta_ctx: "{{delta_frontend_plan}}" }
|
|
335
|
+
|
|
336
|
+
# 4b. Load the domain GATE overlays (the domain-rule-bindings `/aw-spec-gate` checklist)
|
|
337
|
+
# as the conformance checklist — VALIDATION input only, NEVER authoring. analyze sees
|
|
338
|
+
# them (include_standards: true); the repair steps do NOT (the delta conforms to the
|
|
339
|
+
# delta SPEC, not to the overlays). Empty/no-op for a non-domain project.
|
|
340
|
+
- id: resolve_gate_overlays
|
|
341
|
+
action: execute_script
|
|
342
|
+
script: { ref: actions }
|
|
343
|
+
subcommand: resolve-domain
|
|
344
|
+
args: ["--command", "aw-spec-gate"]
|
|
345
|
+
outputs:
|
|
346
|
+
- { name: gate_overlays, from: "$.candidates" }
|
|
347
|
+
- id: load_gate_overlays
|
|
348
|
+
action: load_standards
|
|
349
|
+
files_from_variable: gate_overlays
|
|
350
|
+
optional: true
|
|
351
|
+
|
|
352
|
+
# 5. Pre-execution hooks.
|
|
353
|
+
- id: resolve_pre_hooks
|
|
354
|
+
action: execute_script
|
|
355
|
+
script: { ref: actions }
|
|
356
|
+
subcommand: resolve-hooks
|
|
357
|
+
args: ["--phase", "before_analyze_cr"]
|
|
358
|
+
outputs:
|
|
359
|
+
- { name: before_hooks, from: "$.hooks" }
|
|
360
|
+
- id: dispatch_pre_hooks
|
|
361
|
+
action: dispatch_hooks
|
|
362
|
+
hooks_from_variable: before_hooks
|
|
363
|
+
|
|
364
|
+
# 6. THE GATE'S CONTEXT — the delta, the masters it changes, and the EFFECTIVE MODEL.
|
|
365
|
+
# context_from inlines each PREDECESSOR's two halves (its model delta and its
|
|
366
|
+
# delta-spec); a wave-1 delta has none, which is the common case. A lane that is not
|
|
367
|
+
# gated left its *_ctx vars empty and drops out, so the same envelope serves all three
|
|
368
|
+
# project shapes, and it stays the envelope for the repair steps: a repair rewrites one
|
|
369
|
+
# delta plan against exactly what the check read.
|
|
370
|
+
- id: ctx_gate
|
|
371
|
+
action: build_context
|
|
372
|
+
context_from: predecessor_docs # LOWER waves only — committed to landing first
|
|
373
|
+
context:
|
|
374
|
+
- { path: "{{delta_spec}}" } # THE ANCHOR for this change
|
|
375
|
+
- { path: "{{delta_model}}", optional: true } # its model half — unfilled on a plan-only change
|
|
376
|
+
- { path: "{{be_delta_ctx}}", optional: true }
|
|
377
|
+
- { path: "{{fe_delta_ctx}}", optional: true }
|
|
378
|
+
- { path: "{{spec_file}}" } # the master spec (READ ONLY)
|
|
379
|
+
- { path: "{{be_master_ctx}}", optional: true } # the master plans (READ ONLY) — the base
|
|
380
|
+
- { path: "{{fe_master_ctx}}", optional: true } # every MODIFIED element must name
|
|
381
|
+
- { path: "{{domain_model}}", optional: true } # the canonical model (READ ONLY)
|
|
382
|
+
|
|
383
|
+
# 7. Conformance + REPAIR loop (the delta spec is the anchor): check → REPORT gaps +
|
|
384
|
+
# ASK → Repair on approval → re-check; "Report and Skip" writes the report + stops.
|
|
385
|
+
# Bounded (3×). The repair is PER LANE, so a frontend drift never rewrites a
|
|
386
|
+
# conformant service delta.
|
|
387
|
+
- id: analyze_loop
|
|
388
|
+
action: loop
|
|
389
|
+
while: "{{analyze_ok}} != true"
|
|
390
|
+
max_iterations: 3
|
|
391
|
+
steps:
|
|
392
|
+
- id: analyze
|
|
393
|
+
action: agent_query
|
|
394
|
+
include_standards: true # the gate overlays (checklist) are in the standards
|
|
395
|
+
schema: { ok: true, backend_repair: false, frontend_repair: false, gaps: [ { severity: "high", check: "<spec-backend|spec-frontend|contract|model|master|wave|overlay>", lane: "<backend|frontend>", spec_ref: "<delta FR/BR/CN/DC/IC/UX/US or overlay or —>", where: "<delta-plan section>", gap: "<how it drifts>" } ] }
|
|
396
|
+
mock: { ok: true, backend_repair: false, frontend_repair: false, gaps: [] }
|
|
397
|
+
task: |
|
|
398
|
+
delta-spec.md is the ANCHOR for change {{cr_id}} (wave {{wave}}). Gate this
|
|
399
|
+
change's DELTA PLANS against it, against the masters they change, and against the
|
|
400
|
+
effective domain model, and list EVERY drift as a gap. Run the checks that apply
|
|
401
|
+
— service delta present: {{be_present}}, experience delta present: {{fe_present}},
|
|
402
|
+
both present: {{both_lanes}}. A check for an absent lane is SKIPPED, not failed.
|
|
403
|
+
|
|
404
|
+
CHECK 1 — delta-spec.md → delta-backend-plan.md (when it is in context):
|
|
405
|
+
(a) every ADDED / MODIFIED delta-spec item — FR / BR / CN- / DC- / IC- / user
|
|
406
|
+
story — has a home in the delta plan (an ADDED or MODIFIED element that serves
|
|
407
|
+
it). A delta-spec item with no delta-plan element is a HIGH gap. EXCEPT the
|
|
408
|
+
Experience Standards (UX-), which the service lane excludes by contract;
|
|
409
|
+
(b) the delta plan introduces NOTHING beyond the delta spec — any element with no
|
|
410
|
+
delta-spec basis is a drift unless logged as a delta DA-n;
|
|
411
|
+
(c) shared elements have ONE owning definition (no duplicated element), the
|
|
412
|
+
layers stay coherent and it stays technology-agnostic;
|
|
413
|
+
(d) PLAN-ONLY CHANGE — if the delta-spec is an unfilled stub, the spec is
|
|
414
|
+
deliberately unchanged and this change moves only HOW existing ids are realised.
|
|
415
|
+
Then every changed element must still trace to an EXISTING spec id in the master
|
|
416
|
+
spec (in context). An element tracing to nothing at all is still a HIGH gap.
|
|
417
|
+
|
|
418
|
+
CHECK 2 — delta-spec.md → delta-frontend-plan.md (when it is in context):
|
|
419
|
+
(a) every UX- item in the delta-spec has a home HERE — the service lane excludes
|
|
420
|
+
them, so a UX- in neither delta is a DROPPED requirement, a HIGH gap;
|
|
421
|
+
(b) every new or altered interaction carries its FULL state set (loading, empty,
|
|
422
|
+
error, permission-denied, in-flight). A missing state is a HIGH gap, not a later
|
|
423
|
+
refinement;
|
|
424
|
+
(c) every user story and interaction-state FR- in the delta-spec has a screen and
|
|
425
|
+
a flow; the lifted CN-/DC-/IC-/SC- obligations are realised citing their ids;
|
|
426
|
+
(d) it stays technology-agnostic — no framework, router, state library, component
|
|
427
|
+
library or styling approach.
|
|
428
|
+
|
|
429
|
+
CHECK 3 — CONTRACT BINDING across the change (ONLY when {{both_lanes}} is true;
|
|
430
|
+
skip entirely otherwise):
|
|
431
|
+
(a) EVERY call, endpoint or payload the experience delta binds to is EITHER in
|
|
432
|
+
the service delta's "Contract deltas for the frontend lane" table OR already in
|
|
433
|
+
the MASTER backend plan's published surface. One that is in neither is a HIGH
|
|
434
|
+
`contract` gap — lane `backend` when the delta-spec requires the capability, lane
|
|
435
|
+
`frontend` when the experience invented it;
|
|
436
|
+
(b) FIELD SHAPES agree in both directions — a field the experience reads that the
|
|
437
|
+
service never returns, and a required field the service demands that the
|
|
438
|
+
experience never sends, are both HIGH gaps;
|
|
439
|
+
(c) anything the experience delta raised under "Contract deltas needed" is
|
|
440
|
+
UNRESOLVED by definition: report it so it is closed here rather than at
|
|
441
|
+
integration;
|
|
442
|
+
(d) a contract the service delta REMOVES or narrows that the master frontend plan
|
|
443
|
+
still uses is a HIGH gap — the experience delta has to carry the matching change.
|
|
444
|
+
|
|
445
|
+
CHECK 4 — THE EFFECTIVE MODEL. It is domain-model.md PLUS this change's model
|
|
446
|
+
delta PLUS the model deltas of every LOWER-WAVE change in context (its
|
|
447
|
+
predecessors, whose delta-specs are in context too). {{predecessor_count}}
|
|
448
|
+
predecessor document(s) were inlined.
|
|
449
|
+
(a) EVERY item this change's model delta ADDS / MODIFIES / REMOVES has a
|
|
450
|
+
realisation row in the service delta's "Model changes this plan realises",
|
|
451
|
+
saying where it lands and WHERE the invariant is ENFORCED. An item in the model
|
|
452
|
+
delta with no row is a structural change nothing implements — a HIGH gap;
|
|
453
|
+
(b) NO aggregate, entity, event or invariant appears in a delta plan that the
|
|
454
|
+
effective model does not define. A plan may not invent domain structure: the fix
|
|
455
|
+
is /appweaver specify (which authors the model delta), never the plan;
|
|
456
|
+
(c) a plan that RESTATES what an invariant says instead of citing its BR-nnn is a
|
|
457
|
+
gap — the model is the only place that text lives;
|
|
458
|
+
(d) DEPENDENCIES ON A PREDECESSOR. Where a delta plan relies on something a
|
|
459
|
+
lower-wave change introduces — in its model delta or in its delta-spec — that
|
|
460
|
+
change MUST be named under "## Depends on". An undeclared dependency is a HIGH
|
|
461
|
+
`wave` gap: the declaration is what orders the finalizes and what stops a
|
|
462
|
+
recall from silently invalidating this plan;
|
|
463
|
+
(e) both deltas use the model's UBIQUITOUS LANGUAGE exactly — same terms, no
|
|
464
|
+
synonyms.
|
|
465
|
+
|
|
466
|
+
CHECK 5 — MASTER INTEGRITY (the masters are in context, READ ONLY):
|
|
467
|
+
(a) every MODIFIED element names a REAL element the master plan defines — you
|
|
468
|
+
cannot MODIFY what the master does not define (that would be an ADD). A dangling
|
|
469
|
+
MODIFIED reference is a HIGH `master` gap;
|
|
470
|
+
(b) every MODIFIED / REMOVED spec id names one the master spec really defines;
|
|
471
|
+
(c) nothing in a delta plan edits the master: the delta plans are the whole plan
|
|
472
|
+
for this change, and no stage merges them back — a master plan is re-derived from
|
|
473
|
+
the spec and the model that finalize-delta merges.
|
|
474
|
+
|
|
475
|
+
CHECK 6 — WAVE DISCIPLINE. This change is wave {{wave}}. Other open changes
|
|
476
|
+
touching the same aggregates, computed from the pending model deltas:
|
|
477
|
+
{{overlap_report}}
|
|
478
|
+
({{sibling_overlaps}} same-wave, {{predecessor_overlaps}} lower-wave;
|
|
479
|
+
{{sibling_count}} same-or-higher-wave change(s) are open in total.)
|
|
480
|
+
(a) a SAME-WAVE overlap is ordered against this change by nothing. If either
|
|
481
|
+
delta plan assumes it — builds on its structure, or expects its contract — that
|
|
482
|
+
is a HIGH `wave` gap: either raise this change's wave and declare the dependency,
|
|
483
|
+
or plan around it (expand-then-contract). Merely NAMING it under "Other open
|
|
484
|
+
deltas" is correct and is not a gap;
|
|
485
|
+
(b) a same-wave overlap that the plans do not mention at all is a MEDIUM `wave`
|
|
486
|
+
gap — it has to be visible to whoever implements this change;
|
|
487
|
+
(c) a LOWER-wave overlap may be built on, but only with the "## Depends on"
|
|
488
|
+
declaration check 4(d) requires.
|
|
489
|
+
|
|
490
|
+
CHECK 7 — OVERLAY BACKSTOP. The domain gate checklist is loaded in the standards.
|
|
491
|
+
For each constraint it states (retention, immutability, append-only audit,
|
|
492
|
+
data-exposure, interop obligation, etc.) that THIS CHANGE touches, confirm the
|
|
493
|
+
delta realises it via a delta CN-/DC-/IC-. If the change touches such a
|
|
494
|
+
constraint and it is in NEITHER the delta spec NOR a delta plan, it is a HIGH gap
|
|
495
|
+
— set spec_ref to the overlay name and PREFIX the gap text with "LIFT-FAILURE:"
|
|
496
|
+
(re-run /appweaver specify to lift it into the delta spec; do NOT fabricate it in
|
|
497
|
+
a delta plan).
|
|
498
|
+
|
|
499
|
+
Tag every gap with its `check` and the `lane` whose document must change to close
|
|
500
|
+
it. Set backend_repair true if any gap needs the service delta rewritten, and
|
|
501
|
+
frontend_repair likewise. (If a delta plan is still the empty template, treat the
|
|
502
|
+
WHOLE delta spec as gaps against it.) Set ok=true ONLY when every applicable
|
|
503
|
+
check passes and no touched checklist constraint is unaccounted for.
|
|
504
|
+
outputs:
|
|
505
|
+
- { name: analyze_ok, from: "$.ok" }
|
|
506
|
+
- { name: analyze_gaps, from: "$.gaps" }
|
|
507
|
+
- { name: backend_repair, from: "$.backend_repair" }
|
|
508
|
+
- { name: frontend_repair, from: "$.frontend_repair" }
|
|
509
|
+
- id: conform_break
|
|
510
|
+
action: break
|
|
511
|
+
condition: "{{analyze_ok}} == true"
|
|
512
|
+
- id: ask_repair
|
|
513
|
+
action: ask
|
|
514
|
+
prompt: |
|
|
515
|
+
analyze-plan-delta found delta-spec↔delta-plan gaps on {{cr_id}} (the delta spec
|
|
516
|
+
is the anchor; the masters and the domain model are read-only here):
|
|
517
|
+
{{analyze_gaps}}
|
|
518
|
+
Repair the drifting delta plan(s) now, or report the gaps and stop?
|
|
519
|
+
options: ["Repair", "Report and Skip"]
|
|
520
|
+
answer_var: repair_choice
|
|
521
|
+
- id: write_report
|
|
522
|
+
condition: "{{repair_choice}} == Report and Skip"
|
|
523
|
+
action: agent_author
|
|
524
|
+
include_standards: false
|
|
525
|
+
output_target: { type: file, path: "{{cr_dir}}/delta-plan-analyze-report.md" }
|
|
526
|
+
task: |
|
|
527
|
+
Write a Delta Plan Analyze Report to the output from these delta-spec↔delta-plan
|
|
528
|
+
conformance gaps (the delta spec is the ANCHOR; the user chose to skip repair):
|
|
529
|
+
{{analyze_gaps}}
|
|
530
|
+
Markdown format:
|
|
531
|
+
- "# Delta Plan Analyze Report — {{cr_id}}" plus today's date.
|
|
532
|
+
- A verdict line: "verdict: GAPS ✗ · <n> gap(s)".
|
|
533
|
+
- "## Gaps" as a table: | # | check | lane | severity | delta-spec ref | delta-plan location | gap |.
|
|
534
|
+
- "## How to resolve": the delta spec is the anchor — update the named delta plan
|
|
535
|
+
to realise it for each gap (out of band). A `model` gap whose fix is a missing
|
|
536
|
+
entity or invariant routes to /appweaver specify, which authors the model
|
|
537
|
+
delta; a `wave` gap is closed by declaring "## Depends on" (and raising the
|
|
538
|
+
wave) or by planning around the sibling; a "LIFT-FAILURE:" gap means the
|
|
539
|
+
constraint was never lifted into the delta spec. Then re-run
|
|
540
|
+
/appweaver analyze-plan-delta {{cr_id}} to clear the report.
|
|
541
|
+
Return the complete report markdown only.
|
|
542
|
+
- id: skip_break
|
|
543
|
+
action: break
|
|
544
|
+
condition: "{{repair_choice}} == Report and Skip"
|
|
545
|
+
|
|
546
|
+
# WHICH DOCUMENT GETS REWRITTEN — drift reported in that lane AND that lane present.
|
|
547
|
+
# Cleared first, so a lane repaired on the previous iteration and clean on this one
|
|
548
|
+
# is not rewritten again.
|
|
549
|
+
- id: be_repair_clear
|
|
550
|
+
action: set
|
|
551
|
+
vars: { be_repair: "false" }
|
|
552
|
+
- id: be_repair_flag
|
|
553
|
+
condition: "{{backend_repair}} == true"
|
|
554
|
+
action: set
|
|
555
|
+
vars: { be_repair: "{{be_present}}" }
|
|
556
|
+
- id: fe_repair_clear
|
|
557
|
+
action: set
|
|
558
|
+
vars: { fe_repair: "false" }
|
|
559
|
+
- id: fe_repair_flag
|
|
560
|
+
condition: "{{frontend_repair}} == true"
|
|
561
|
+
action: set
|
|
562
|
+
vars: { fe_repair: "{{fe_present}}" }
|
|
563
|
+
|
|
564
|
+
- id: repair_backend
|
|
565
|
+
condition: "{{be_repair}} == true"
|
|
566
|
+
action: agent_author
|
|
567
|
+
include_standards: false # rewrite-in-place: the delta spec anchors — NOT the overlays
|
|
568
|
+
output_target: { type: file, path: "{{delta_backend_plan}}" }
|
|
569
|
+
task: |
|
|
570
|
+
delta-spec.md is the ANCHOR — update the SERVICE delta plan for {{cr_id}} (in
|
|
571
|
+
context) to REALISE it, closing the gaps whose lane is `backend` (the delta spec
|
|
572
|
+
WINS every time):
|
|
573
|
+
{{analyze_gaps}}
|
|
574
|
+
- Add a delta-plan element for each uncovered ADDED/MODIFIED delta-spec
|
|
575
|
+
FR/BR/CN/DC/IC/US, in the correct section, serving that spec id. On a PLAN-ONLY
|
|
576
|
+
change (an unfilled delta-spec) trace every changed element to an EXISTING
|
|
577
|
+
master spec id instead — you are changing the realisation, never inventing a
|
|
578
|
+
requirement.
|
|
579
|
+
- Ensure every MODIFIED element names a REAL element from the master plan (in
|
|
580
|
+
context); if the master does not define it, make it an ADDED element instead.
|
|
581
|
+
- Fill "## Model changes this plan realises" with a row per item this change's
|
|
582
|
+
MODEL DELTA adds, modifies or removes — where it lands, and where each
|
|
583
|
+
invariant is ENFORCED. Cite BR-nnn by id; never restate what one says. DO NOT
|
|
584
|
+
EDIT domain-model.md or the model delta: they are spec-tier. A gap that can
|
|
585
|
+
only be closed by ADDING to the model stays open with a DA-n saying it routes
|
|
586
|
+
to /appweaver specify.
|
|
587
|
+
- CONTRACT gaps whose lane is `backend`: publish the missing surface in
|
|
588
|
+
"## Contract deltas for the frontend lane" as field shapes. That table is the
|
|
589
|
+
only part of this document the experience delta may bind to.
|
|
590
|
+
- WAVE gaps: name a lower-wave change you build on under "## Depends on", and
|
|
591
|
+
name a same-wave overlap under "Other open deltas" — you may NOT assume a
|
|
592
|
+
same-wave change's structure or contract, because nothing orders it against
|
|
593
|
+
this one.
|
|
594
|
+
- REMOVE, or move to a delta DA-n note, any element with no delta-spec basis —
|
|
595
|
+
never keep a plan that exceeds the delta spec.
|
|
596
|
+
- A "LIFT-FAILURE:" gap you CANNOT close — the constraint is not in the delta
|
|
597
|
+
spec, and you must NOT invent a domain rule it omits. Leave it open and add a
|
|
598
|
+
note "lift-failure: <constraint> — re-run /appweaver specify to lift it into
|
|
599
|
+
the delta spec".
|
|
600
|
+
- Keep the technology-agnostic form (signatures + pre/post/invariant, field
|
|
601
|
+
shapes — NO code). Preserve every already-conformant section VERBATIM. Do NOT
|
|
602
|
+
change the delta spec, the masters or the domain model. Do NOT edit the Wave /
|
|
603
|
+
Base version / Delta spec / Model delta headers — scripts stamp those.
|
|
604
|
+
Return the COMPLETE updated delta plan content only.
|
|
605
|
+
|
|
606
|
+
- id: repair_frontend
|
|
607
|
+
condition: "{{fe_repair}} == true"
|
|
608
|
+
action: agent_author
|
|
609
|
+
include_standards: false # rewrite-in-place: the delta spec anchors — NOT the overlays
|
|
610
|
+
output_target: { type: file, path: "{{delta_frontend_plan}}" }
|
|
611
|
+
task: |
|
|
612
|
+
delta-spec.md is the ANCHOR — update the EXPERIENCE delta plan for {{cr_id}} (in
|
|
613
|
+
context) to REALISE it, closing the gaps whose lane is `frontend` (the delta spec
|
|
614
|
+
WINS every time):
|
|
615
|
+
{{analyze_gaps}}
|
|
616
|
+
- Give every uncovered UX-, user story and interaction-state FR- from the delta
|
|
617
|
+
spec a home: a screen, a flow, and the FULL state set (loading, empty, error,
|
|
618
|
+
permission-denied, in-flight). UX- items live HERE and nowhere else.
|
|
619
|
+
- Ensure every MODIFIED component, screen or state container names a REAL element
|
|
620
|
+
from the master frontend plan (in context); if the master does not define it,
|
|
621
|
+
make it an ADDED element instead. A shared component is MODIFIED in place,
|
|
622
|
+
never copied into the change.
|
|
623
|
+
- CONTRACT gaps whose lane is `frontend`: bind ONLY to the service delta's
|
|
624
|
+
"## Contract deltas for the frontend lane" table and to the master plan's
|
|
625
|
+
published surface. CITE them; do not restate, re-derive or contradict them, and
|
|
626
|
+
introduce NO server-side behaviour or persistence assumption. A capability the
|
|
627
|
+
experience needs that neither offers stays under "Contract deltas needed" — it
|
|
628
|
+
is the service lane's to publish, never a client-side workaround.
|
|
629
|
+
- WAVE gaps: name a lower-wave change you build on under "## Depends on", and a
|
|
630
|
+
same-wave overlap under "Other open deltas"; never assume a same-wave change's
|
|
631
|
+
screens, shared components or contract.
|
|
632
|
+
- Use the domain model's UBIQUITOUS LANGUAGE exactly in labels, states and
|
|
633
|
+
messages, and cite BR-nnn rather than restating a rule. DO NOT EDIT
|
|
634
|
+
domain-model.md, the model delta or either master.
|
|
635
|
+
- A state the UI can reach that the delta spec does not describe is a SPEC gap:
|
|
636
|
+
log it as a DA-n that routes to /appweaver specify; never invent the
|
|
637
|
+
requirement here.
|
|
638
|
+
- Stay TECHNOLOGY-AGNOSTIC: no framework, router, state library, component
|
|
639
|
+
library or styling approach. Preserve every already-conformant section
|
|
640
|
+
VERBATIM. Do NOT edit the Wave / Base version / Delta spec / Service delta
|
|
641
|
+
headers — scripts stamp those.
|
|
642
|
+
Return the COMPLETE updated delta plan content only.
|
|
643
|
+
|
|
644
|
+
- id: analyze_gate
|
|
645
|
+
action: verify_context
|
|
646
|
+
require_true: analyze_ok
|
|
647
|
+
on_false: stop
|
|
648
|
+
on_false_message: "The delta plans for {{cr_id}} do not realise the delta spec (gaps: {{analyze_gaps}}) — repair was skipped (see {{cr_dir}}/delta-plan-analyze-report.md), or it could not be reconciled in 3 passes. A 'LIFT-FAILURE:' gap means a domain constraint from the gate checklist was never lifted into the delta spec, and a `model` gap means a plan needs structure the effective model does not define — both are fixed by /appweaver specify, which authors the delta spec and the model delta; this gate may not write either. A `wave` gap is closed by declaring '## Depends on' (and raising the wave with cr-wave) or by planning around the sibling. Otherwise fix out of band, or re-run and choose Repair."
|
|
649
|
+
|
|
650
|
+
# 8. Post-execution hooks.
|
|
651
|
+
- id: resolve_post_hooks
|
|
652
|
+
action: execute_script
|
|
653
|
+
script: { ref: actions }
|
|
654
|
+
subcommand: resolve-hooks
|
|
655
|
+
args: ["--phase", "after_analyze_cr"]
|
|
656
|
+
outputs:
|
|
657
|
+
- { name: after_hooks, from: "$.hooks" }
|
|
658
|
+
- id: dispatch_post_hooks
|
|
659
|
+
action: dispatch_hooks
|
|
660
|
+
hooks_from_variable: after_hooks
|
|
661
|
+
|
|
662
|
+
outputs:
|
|
663
|
+
feature_dir: "{{feature_dir}}"
|
|
664
|
+
cr_id: "{{cr_id}}"
|
|
665
|
+
cr_dir: "{{cr_dir}}"
|
|
666
|
+
wave: "{{wave}}"
|
|
667
|
+
delta_backend_plan: "{{delta_backend_plan}}" # empty when that lane has no delta plan
|
|
668
|
+
delta_frontend_plan: "{{delta_frontend_plan}}"
|
|
669
|
+
conformant: "{{analyze_ok}}"
|
|
670
|
+
gaps: "{{analyze_gaps}}"
|
|
671
|
+
overlaps: "{{overlap_report}}"
|
|
672
|
+
note: "Gated change {{cr_id}} (wave {{wave}}) against its delta spec, the masters it changes, and the EFFECTIVE model — domain-model.md plus this change's model delta plus the {{predecessor_count}} predecessor change(s) from LOWER waves (each one's model delta and its delta-spec). Same-wave changes are visible but never assumed: {{sibling_count}} open at the same or a higher wave, overlapping this one on — {{overlap_report}}. The masters and the model were READ, never written."
|
|
673
|
+
next: "/appweaver implement {{cr_id}} → build → analyze-slice-delta → finalize-delta → analyze-slice → close-delta (implement is one command for both lanes and both paths — passing the id above skips its 'which change' prompt; the delta plans realise the delta spec; the change stays OPEN through finalize-delta's merge and analyze-slice's verification, and only close-delta archives it and bumps the version)"
|