aw-spec-cli 0.1.16 → 0.1.18
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,643 @@
|
|
|
1
|
+
# =============================================================================
|
|
2
|
+
# aw-spec-analyze-slice-delta (orchestrator) — the DELTA spec↔code gate
|
|
3
|
+
#
|
|
4
|
+
# The fourth conformance gate, and the one the CR loop was missing. The family is a
|
|
5
|
+
# 2×2 — static vs dynamic, master vs change — and only three corners were built. Every
|
|
6
|
+
# corner is anchored on the REQUIREMENTS; what changes across the grid is what they are
|
|
7
|
+
# compared to, and which set of them is in scope:
|
|
8
|
+
#
|
|
9
|
+
# MASTER (bootstrap) CHANGE (delta)
|
|
10
|
+
# STATIC spec↔plan analyze-plan analyze-plan-delta
|
|
11
|
+
# DYNAMIC spec↔code analyze-slice analyze-slice-delta ← this
|
|
12
|
+
#
|
|
13
|
+
# WHAT IT ANSWERS, AND WHY analyze-slice CANNOT. analyze-slice scores the WHOLE slice
|
|
14
|
+
# against the MERGED master, and it is test-driven: a behaviour that is implemented WRONG
|
|
15
|
+
# fails its paired test and is caught. A behaviour that was never implemented AT ALL leaves
|
|
16
|
+
# no failing test — it leaves NO test — so nothing fails and the gate reports green. That
|
|
17
|
+
# is not a hypothetical state: `implement` skips a lane whose plan or project is missing and
|
|
18
|
+
# ASKS before each lane, so "the frontend half of this change was declined and nobody
|
|
19
|
+
# noticed" is reachable. Merge that and spec.md asserts behaviour with no code behind it.
|
|
20
|
+
# This gate asks the question analyze-slice structurally cannot, and asks it of the CHANGE'S
|
|
21
|
+
# OWN REQUIREMENTS: does the code do what this delta spec asked for?
|
|
22
|
+
#
|
|
23
|
+
# IT RUNS BEFORE finalize-delta, WHICH IS THE POINT. The existing fence there refuses a
|
|
24
|
+
# change that BREAKS A DEPENDENT; this is the same principle one step earlier — a change
|
|
25
|
+
# that WAS NOT IMPLEMENTED must not reach the master documents either. It is also the first
|
|
26
|
+
# time anything RUNS the tests on the change path: `build` only compiles, so without this
|
|
27
|
+
# stage a change whose new tests are red is merged into spec.md and domain-model.md before
|
|
28
|
+
# a single one of them has been executed.
|
|
29
|
+
#
|
|
30
|
+
# specify → plan → analyze-plan-delta → implement → build
|
|
31
|
+
# → analyze-slice-delta ← you are here
|
|
32
|
+
# → finalize-delta → analyze-slice → close-delta
|
|
33
|
+
#
|
|
34
|
+
# delta-spec.md IS THE ANCHOR — THE REQUIREMENTS, NOT THE PLAN. This gate asks whether the
|
|
35
|
+
# change DOES WHAT IT WAS ASKED TO DO, and the thing that asked is the delta spec (plus the
|
|
36
|
+
# invariants in the change's model delta, which are requirements too). Every gate in this
|
|
37
|
+
# family anchors the same way: spec.md anchors analyze-plan and analyze-slice, delta-spec.md
|
|
38
|
+
# anchors analyze-plan-delta and this.
|
|
39
|
+
# ANCHORING ON THE PLAN INSTEAD WOULD MISS THE WORST CASE. A plan-anchored gate can only
|
|
40
|
+
# ever ask "did the code do what the plan said" — so a requirement that BOTH the plan and
|
|
41
|
+
# the code dropped comes back green, because nothing in its evidence ever mentioned it.
|
|
42
|
+
# The delta spec is the only document that knows the change was asked for at all.
|
|
43
|
+
# The DELTA PLAN is in context as the MAP, not the authority: it says which element serves
|
|
44
|
+
# which requirement, so a finding can point at the place the behaviour was supposed to land
|
|
45
|
+
# instead of just reporting a requirement as absent. It is also cross-checked in its own
|
|
46
|
+
# right (check 3), because an element the plan promised and nobody built is a real defect
|
|
47
|
+
# even when the requirement it served looks satisfied elsewhere.
|
|
48
|
+
# The MASTERS are read-only context for what was already there — nothing here compares the
|
|
49
|
+
# slice to a master that does not yet carry the change.
|
|
50
|
+
#
|
|
51
|
+
# IT VERIFIES; IT NEVER BUILDS AND NEVER REPAIRS. An unrealised requirement means the code
|
|
52
|
+
# was never generated, and generating it here would do it with none of `implement`'s inputs — no
|
|
53
|
+
# lane rule set, no constitution, no stack binding — which is the same reason analyze-plan
|
|
54
|
+
# stops naming `/appweaver plan` instead of filling an empty template itself. So every
|
|
55
|
+
# finding is REPORTED with the command that closes it (implement for missing code, plan for
|
|
56
|
+
# a delta plan that is wrong, specify for a spec or model gap) and the gate stops. The
|
|
57
|
+
# repair loops stay in analyze-slice, where the merged master is the anchor and the job is
|
|
58
|
+
# fixing what is BROKEN rather than building what is ABSENT.
|
|
59
|
+
#
|
|
60
|
+
# NO NEW RULE-MAP HEADING. It loads `## /aw-spec-analyze-slice` — the same testing +
|
|
61
|
+
# coding-standards set its master twin reads — so no project has to add configuration to
|
|
62
|
+
# get this gate. The DOMAIN gate overlays are deliberately NOT loaded: full domain
|
|
63
|
+
# conformance of the slice is analyze-slice's pass 2, against the merged model, and running
|
|
64
|
+
# it twice against two different versions of the model is how one gate contradicts another.
|
|
65
|
+
# The invariants THIS CHANGE adds are checked here anyway, from its model delta, because
|
|
66
|
+
# they are requirements of the change rather than standing domain policy.
|
|
67
|
+
#
|
|
68
|
+
# Launch: /appweaver analyze-slice-delta [CR-id]
|
|
69
|
+
# Prereq: /appweaver implement (this change) then /appweaver build.
|
|
70
|
+
# =============================================================================
|
|
71
|
+
|
|
72
|
+
name: aw-spec-analyze-slice-delta
|
|
73
|
+
version: 1.0.0
|
|
74
|
+
description: "The delta-spec↔delta-code gate — verify that the open change DOES WHAT IT WAS ASKED TO DO, before it reaches the master documents. delta-spec.md is the anchor, exactly as it is for analyze-plan-delta. Asks which open change it is gating, runs the slice's tests (the first execution on the change path, since build only compiles), then evaluates the code and its paired tests against the change's REQUIREMENTS — every ADDED or MODIFIED delta-spec item realised in code, every one covered by a test that cites its id, every invariant the model delta adds actually enforced — with the delta plan in context as the map from requirement to code and cross-checked in its own right, so an element the plan promised and nobody built is caught too. The dynamic twin of analyze-plan-delta and the delta twin of analyze-slice, which cannot see a missing implementation because a behaviour that was never built leaves no failing test. Verify-only — it reports each finding with the command that closes it and stops; it generates no code and repairs nothing."
|
|
75
|
+
agent_agnostic: true
|
|
76
|
+
dialect: aw-spec.orchestrator/v1
|
|
77
|
+
|
|
78
|
+
inputs:
|
|
79
|
+
user_input:
|
|
80
|
+
description: "Optional — a bare CR id selects which open change to gate without a prompt."
|
|
81
|
+
required: false
|
|
82
|
+
bind: USER_INPUT
|
|
83
|
+
|
|
84
|
+
scripts:
|
|
85
|
+
actions:
|
|
86
|
+
sh: .appweaver/scripts/bash/aw-spec-actions.sh
|
|
87
|
+
ps1: .appweaver/scripts/powershell/aw-spec-actions.ps1
|
|
88
|
+
xref:
|
|
89
|
+
sh: .appweaver/scripts/bash/aw-xref.sh
|
|
90
|
+
ps1: .appweaver/scripts/powershell/aw-xref.ps1
|
|
91
|
+
|
|
92
|
+
# Sticky standards seed = the UNIVERSAL always-on rule only. A gate needs it above all: a
|
|
93
|
+
# gate passes when it RAN and returned a pass, never by inference. The technical set
|
|
94
|
+
# (testing + coding-standards — what a paired test has to look like for check 2 to mean
|
|
95
|
+
# anything) is loaded per-command by tech-select, under analyze-slice's own heading.
|
|
96
|
+
standards:
|
|
97
|
+
- { path: .appweaver/ai-rules.md } # kit-resident: the universal operating rules, every flow
|
|
98
|
+
|
|
99
|
+
vars:
|
|
100
|
+
cr_id: ""
|
|
101
|
+
cr_choice: ""
|
|
102
|
+
cr_dir: ""
|
|
103
|
+
wave: ""
|
|
104
|
+
has_changes: "false"
|
|
105
|
+
delta_spec: ""
|
|
106
|
+
delta_model: ""
|
|
107
|
+
delta_backend_plan: ""
|
|
108
|
+
delta_backend_plan_exists: "false"
|
|
109
|
+
delta_frontend_plan: ""
|
|
110
|
+
delta_frontend_plan_exists: "false"
|
|
111
|
+
domain_model: ""
|
|
112
|
+
# WHICH LANES THIS GATE CHECKS — a lane is gated when it is DECLARED and this change has
|
|
113
|
+
# a delta plan for it. An experience-untouched change has no frontend delta plan, and
|
|
114
|
+
# skipping that lane's checks is correct rather than a pass by omission. Each AND is an
|
|
115
|
+
# ordered assignment; the engine has no compound conditions.
|
|
116
|
+
be_declared: "false"
|
|
117
|
+
fe_declared: "false"
|
|
118
|
+
be_gated: "false"
|
|
119
|
+
fe_gated: "false"
|
|
120
|
+
any_lane: "false"
|
|
121
|
+
# Slice evidence.
|
|
122
|
+
source_files: []
|
|
123
|
+
source_count: "0"
|
|
124
|
+
test_ok: "false"
|
|
125
|
+
test_tool: ""
|
|
126
|
+
test_log: ""
|
|
127
|
+
test_scoped: "false"
|
|
128
|
+
test_ran: "false"
|
|
129
|
+
test_matched: "false"
|
|
130
|
+
# Verdict.
|
|
131
|
+
requirements_ok: "false"
|
|
132
|
+
gate_ok: "false"
|
|
133
|
+
|
|
134
|
+
workflow:
|
|
135
|
+
|
|
136
|
+
# 0. TECHNICAL rule files → sticky standards. Keyed on `## /aw-spec-analyze-slice`, NOT on
|
|
137
|
+
# a heading of this command's own name: the set this gate needs is exactly the
|
|
138
|
+
# set its master twin reads, and inventing a heading would silently load nothing in
|
|
139
|
+
# every project that has not been reconfigured. No blocking gate — an unconfigured
|
|
140
|
+
# project soft-continues and the checks below still run on the documents themselves.
|
|
141
|
+
- id: tech_select
|
|
142
|
+
action: include
|
|
143
|
+
module: .appweaver/orchestrator/modules/tech-select.orch.yaml
|
|
144
|
+
with: { command: aw-spec-analyze-slice }
|
|
145
|
+
|
|
146
|
+
# 1. WHICH LANES EXIST. Declaration only — this gate reads code, it does not write it, so
|
|
147
|
+
# it has no reason to require a source path on disk.
|
|
148
|
+
- id: lane_resolve
|
|
149
|
+
action: execute_script
|
|
150
|
+
on_error: continue
|
|
151
|
+
script: { ref: actions }
|
|
152
|
+
subcommand: lane-resolve
|
|
153
|
+
outputs:
|
|
154
|
+
- { name: lanes_declared, from: "$.declared" }
|
|
155
|
+
- { name: be_declared, from: "$.backend_declared" }
|
|
156
|
+
- { name: be_lane_id, from: "$.backend_lane_id" }
|
|
157
|
+
- { name: be_source_path, from: "$.backend_source_path" }
|
|
158
|
+
- { name: fe_declared, from: "$.frontend_declared" }
|
|
159
|
+
- { name: fe_lane_id, from: "$.frontend_lane_id" }
|
|
160
|
+
- { name: fe_source_path, from: "$.frontend_source_path" }
|
|
161
|
+
|
|
162
|
+
- id: require_lane
|
|
163
|
+
action: verify_context
|
|
164
|
+
require_true: lanes_declared
|
|
165
|
+
on_false: stop
|
|
166
|
+
on_false_message: "No lane is declared in .appweaver/stacks.json, so there is no code to gate. Run /appweaver select-stack, then take the change through /appweaver plan → analyze-plan-delta → implement → build before gating it here."
|
|
167
|
+
|
|
168
|
+
# 2. The active feature.
|
|
169
|
+
- id: feature_paths
|
|
170
|
+
action: execute_script
|
|
171
|
+
on_error: continue
|
|
172
|
+
script: { ref: actions }
|
|
173
|
+
subcommand: feature-paths
|
|
174
|
+
outputs:
|
|
175
|
+
- { name: feature, from: "$.feature" }
|
|
176
|
+
- { name: feature_dir, from: "$.feature_dir" }
|
|
177
|
+
- { name: spec_file, from: "$.spec_file" }
|
|
178
|
+
- { name: backend_plan, from: "$.backend_plan" }
|
|
179
|
+
- { name: frontend_plan, from: "$.frontend_plan" }
|
|
180
|
+
|
|
181
|
+
- id: require_feature
|
|
182
|
+
action: verify_context
|
|
183
|
+
require_non_empty: feature_dir
|
|
184
|
+
on_empty: stop
|
|
185
|
+
on_empty_message: "No active feature. Run /appweaver select-feature first (pick the aggregate, e.g. Order), then re-run analyze-slice-delta."
|
|
186
|
+
|
|
187
|
+
# 3. WHICH CHANGE. Same selection contract as plan, analyze-plan-delta and implement:
|
|
188
|
+
# cr-list enumerates the open changes (evidence = changes/<CR-id>/ on disk), a bare CR
|
|
189
|
+
# id in the argument auto-selects, one open change auto-confirms, and the pick is
|
|
190
|
+
# ACTIVATED so finalize-delta and close-delta act on the change this gate cleared.
|
|
191
|
+
- id: cr_list
|
|
192
|
+
action: execute_script
|
|
193
|
+
script: { ref: actions }
|
|
194
|
+
subcommand: cr-list
|
|
195
|
+
args: ["--feature-dir", "{{feature_dir}}", "--preselect", "{{USER_INPUT}}"]
|
|
196
|
+
outputs:
|
|
197
|
+
- { name: change_options, from: "$.select_options" }
|
|
198
|
+
- { name: matched_label, from: "$.matched_label" }
|
|
199
|
+
- { name: has_changes, from: "$.has_changes" }
|
|
200
|
+
- { name: change_count, from: "$.count" }
|
|
201
|
+
|
|
202
|
+
- id: require_change
|
|
203
|
+
action: verify_context
|
|
204
|
+
require_true: has_changes
|
|
205
|
+
on_false: stop
|
|
206
|
+
on_false_message: "No open change on this feature — there is no delta to gate. This is the CHANGE path's gate; on the bootstrap path the whole slice is gated by /appweaver analyze-slice after build. A change is opened by /appweaver specify."
|
|
207
|
+
|
|
208
|
+
- id: pick_change
|
|
209
|
+
action: user_select
|
|
210
|
+
prompt: "Which open change is being gated? This checks that the change was actually BUILT, before finalize-delta merges it into the masters."
|
|
211
|
+
options_from_variable: change_options
|
|
212
|
+
preselect_from: matched_label
|
|
213
|
+
single_option_confirm: true
|
|
214
|
+
outputs:
|
|
215
|
+
- { name: cr_choice, from: selection }
|
|
216
|
+
|
|
217
|
+
- id: activate
|
|
218
|
+
action: execute_script
|
|
219
|
+
script: { ref: actions }
|
|
220
|
+
subcommand: cr-activate
|
|
221
|
+
args: ["--cr-id", "{{cr_choice}}", "--feature-dir", "{{feature_dir}}"]
|
|
222
|
+
outputs:
|
|
223
|
+
- { name: active_change, from: "$.active_change" }
|
|
224
|
+
|
|
225
|
+
- id: cr_paths
|
|
226
|
+
action: execute_script
|
|
227
|
+
script: { ref: actions }
|
|
228
|
+
subcommand: cr-paths
|
|
229
|
+
args: ["--cr-id", "{{cr_choice}}", "--feature-dir", "{{feature_dir}}"]
|
|
230
|
+
outputs:
|
|
231
|
+
- { name: cr_id, from: "$.cr_id" }
|
|
232
|
+
- { name: cr_dir, from: "$.cr_dir" }
|
|
233
|
+
- { name: delta_spec, from: "$.delta_spec" }
|
|
234
|
+
- { name: delta_model, from: "$.delta_model" }
|
|
235
|
+
- { name: delta_backend_plan, from: "$.delta_backend_plan" }
|
|
236
|
+
- { name: delta_backend_plan_exists, from: "$.delta_backend_plan_exists" }
|
|
237
|
+
- { name: delta_frontend_plan, from: "$.delta_frontend_plan" }
|
|
238
|
+
- { name: delta_frontend_plan_exists, from: "$.delta_frontend_plan_exists" }
|
|
239
|
+
- { name: wave, from: "$.wave" }
|
|
240
|
+
- { name: domain_model, from: "$.domain_model" }
|
|
241
|
+
|
|
242
|
+
# 3a. WHICH LANES ARE GATED — declared AND this change has a delta plan for that lane.
|
|
243
|
+
- id: be_gated_flag
|
|
244
|
+
condition: "{{delta_backend_plan_exists}} == true"
|
|
245
|
+
action: set
|
|
246
|
+
vars: { be_gated: "{{be_declared}}" }
|
|
247
|
+
- id: fe_gated_flag
|
|
248
|
+
condition: "{{delta_frontend_plan_exists}} == true"
|
|
249
|
+
action: set
|
|
250
|
+
vars: { fe_gated: "{{fe_declared}}" }
|
|
251
|
+
- id: any_lane_be
|
|
252
|
+
condition: "{{be_gated}} == true"
|
|
253
|
+
action: set
|
|
254
|
+
vars: { any_lane: "true" }
|
|
255
|
+
- id: any_lane_fe
|
|
256
|
+
condition: "{{fe_gated}} == true"
|
|
257
|
+
action: set
|
|
258
|
+
vars: { any_lane: "true" }
|
|
259
|
+
|
|
260
|
+
- id: require_any_lane
|
|
261
|
+
action: verify_context
|
|
262
|
+
require_true: any_lane
|
|
263
|
+
on_false: stop
|
|
264
|
+
on_false_message: "Change {{cr_id}} has no delta plan for any declared lane — backend declared {{be_declared}} (delta plan {{delta_backend_plan_exists}}), frontend declared {{fe_declared}} (delta plan {{delta_frontend_plan_exists}}). There is nothing to gate the code against. Run /appweaver plan {{cr_id}} to author the delta plans, then analyze-plan-delta → implement → build, and gate it here."
|
|
265
|
+
|
|
266
|
+
# 4. THE SLICE'S REAL SOURCE FILES, from its OKF concept — the same resolution
|
|
267
|
+
# analyze-slice uses. They arrive as a PATH LIST and the check steps declare
|
|
268
|
+
# `tools: Read`, because a slice does not fit in a payload. THE PLANS CARRY NO PATHS,
|
|
269
|
+
# BY CONTRACT: they are technology-agnostic, so an ADDED element names a type, a
|
|
270
|
+
# use-case or an endpoint and never a file. That is why this gate is a model pass over
|
|
271
|
+
# real files rather than a deterministic existence check — the same reason design-paths
|
|
272
|
+
# was retired when the plan stopped carrying ```lang path=…``` fences.
|
|
273
|
+
- id: concept_paths
|
|
274
|
+
action: execute_script
|
|
275
|
+
on_error: continue
|
|
276
|
+
script: { ref: xref }
|
|
277
|
+
subcommand: concept-paths
|
|
278
|
+
args: ["--feature-dir", "{{feature_dir}}"]
|
|
279
|
+
outputs:
|
|
280
|
+
- { name: source_files, from: "$.paths" }
|
|
281
|
+
- { name: source_count, from: "$.count" }
|
|
282
|
+
|
|
283
|
+
- id: require_source
|
|
284
|
+
action: verify_context
|
|
285
|
+
require_non_empty: source_files
|
|
286
|
+
on_empty: stop
|
|
287
|
+
on_empty_message: "The OKF concept for {{feature}} lists no source files, so there is no implementation to gate. Either /appweaver implement has not run for change {{cr_id}} yet, or it ran and reported no files. Run /appweaver implement {{cr_id}} → build, then re-run this gate."
|
|
288
|
+
|
|
289
|
+
# 5. Pre-execution hooks.
|
|
290
|
+
- id: resolve_pre_hooks
|
|
291
|
+
action: execute_script
|
|
292
|
+
script: { ref: actions }
|
|
293
|
+
subcommand: resolve-hooks
|
|
294
|
+
args: ["--phase", "before_analyze_slice_cr"]
|
|
295
|
+
outputs:
|
|
296
|
+
- { name: before_hooks, from: "$.hooks" }
|
|
297
|
+
- id: dispatch_pre_hooks
|
|
298
|
+
action: dispatch_hooks
|
|
299
|
+
hooks_from_variable: before_hooks
|
|
300
|
+
|
|
301
|
+
# ═══════════════ PASS 1 — BEHAVIOUR. Run the slice's tests. ═══════════════
|
|
302
|
+
# THE FIRST EXECUTION ON THE CHANGE PATH. `build` compiles and does not test, and
|
|
303
|
+
# analyze-slice does not run until after finalize-delta — so without this the change's own
|
|
304
|
+
# new tests are merged into the masters before anything has run them once.
|
|
305
|
+
# scope=slice: this feature's tests only. Referring aggregates are the downstream fence's
|
|
306
|
+
# subject in finalize-delta and the integrity pass's in analyze-slice; this gate is about
|
|
307
|
+
# THIS change.
|
|
308
|
+
# NO FIX LOOP, deliberately — see the header. A red fence is reported and stops.
|
|
309
|
+
- id: run_tests
|
|
310
|
+
action: execute_script
|
|
311
|
+
on_error: continue
|
|
312
|
+
script: { ref: actions }
|
|
313
|
+
subcommand: test-run
|
|
314
|
+
args: ["--feature-dir", "{{feature_dir}}", "--scope", "slice"]
|
|
315
|
+
outputs:
|
|
316
|
+
- { name: test_ok, from: "$.fence_green" }
|
|
317
|
+
- { name: test_tool, from: "$.tool" }
|
|
318
|
+
- { name: test_log, from: "$.log_tail" }
|
|
319
|
+
- { name: test_scoped, from: "$.scoped" }
|
|
320
|
+
# A GREEN FENCE IS NOT ALWAYS AN EXECUTED SUITE. test-run reports fence_green true
|
|
321
|
+
# with ran=false on a project whose lanes declare no test command — the vacuous pass
|
|
322
|
+
# its own ladder warns about. It is not made fatal here (that would fail every project
|
|
323
|
+
# that has not declared one, and analyze-slice scores the same fence the same way),
|
|
324
|
+
# but it IS reported, so "BUILT ✓" is never read as "the tests passed" when nothing
|
|
325
|
+
# ran. The requirement checks below are what actually answer whether the change
|
|
326
|
+
# does what it asked for, and they do not depend on a suite existing.
|
|
327
|
+
- { name: test_ran, from: "$.ran" }
|
|
328
|
+
- { name: test_matched, from: "$.matched" }
|
|
329
|
+
|
|
330
|
+
# ══════ PASS 2 — REQUIREMENTS. Does the code do what the change asked for? ══════
|
|
331
|
+
# THE REQUIREMENTS ARE THE ANCHOR; the plan is the map; the masters are read-only context
|
|
332
|
+
# for what was already there. Per lane, because the two lanes' evidence is disjoint and a
|
|
333
|
+
# lane with no delta plan is not gated.
|
|
334
|
+
- id: ctx_backend
|
|
335
|
+
condition: "{{be_gated}} == true"
|
|
336
|
+
action: build_context
|
|
337
|
+
context:
|
|
338
|
+
- { path: "{{delta_spec}}", optional: true } # THE ANCHOR — what this change was asked to do
|
|
339
|
+
- { path: "{{delta_model}}", optional: true } # the invariants it adds or changes — requirements too
|
|
340
|
+
- { path: "{{delta_backend_plan}}" } # THE MAP — which element serves which requirement
|
|
341
|
+
- { path: "{{spec_file}}", optional: true } # the master spec — the EXISTING ids a plan-only change still serves
|
|
342
|
+
- { path: "{{backend_plan}}", optional: true } # the master plan — what was already there
|
|
343
|
+
- { path: "{{domain_model}}", optional: true } # the model as it stands before the merge
|
|
344
|
+
- id: check_backend
|
|
345
|
+
condition: "{{be_gated}} == true"
|
|
346
|
+
action: agent_query
|
|
347
|
+
tools: Read # the slice's files arrive as {{source_files}} paths, not inlined
|
|
348
|
+
include_standards: true
|
|
349
|
+
schema: { ok: true, gaps: [ { severity: "high", check: "<requirement|test|plan|model|regression|scope|placement>", lane: "backend", ref: "<delta-spec id, or the delta-plan element where the check is 'plan'>", where: "<file or 'absent'>", gap: "<what is missing or wrong>", fix: "<implement|plan|specify>" } ] }
|
|
350
|
+
mock: { ok: true, gaps: [] }
|
|
351
|
+
task: |
|
|
352
|
+
Gate the SERVICE lane's CODE for change {{cr_id}} (wave {{wave}}) against
|
|
353
|
+
delta-spec.md — THE ANCHOR in context. The question is not "is this code good" and
|
|
354
|
+
not "does it match the plan": it is DOES THIS CHANGE DO WHAT IT WAS ASKED TO DO?
|
|
355
|
+
{{source_count}} file(s) realise this slice: {{source_files}} — READ the ones this
|
|
356
|
+
change should have touched.
|
|
357
|
+
The delta plan is in context as the MAP from a requirement to the element that serves
|
|
358
|
+
it — use it to know WHERE to look, and to write a finding that names the place the
|
|
359
|
+
behaviour was supposed to land. It is not the authority: a requirement the plan never
|
|
360
|
+
planned is still this gate's finding, because the delta spec is the only document
|
|
361
|
+
that knows it was asked for.
|
|
362
|
+
The master spec, master plan and master domain model are what was ALREADY there; they
|
|
363
|
+
do not yet carry this change (finalize-delta merges it AFTER this gate), so never
|
|
364
|
+
report an element as missing from them.
|
|
365
|
+
|
|
366
|
+
CHECK 1 — REQUIREMENTS → CODE (the reason this gate exists). For EVERY ADDED or
|
|
367
|
+
MODIFIED item in the delta-spec — FR-, BR-, CN-, DC-, IC-, user story — the code must
|
|
368
|
+
actually DO what it states:
|
|
369
|
+
(a) find where the behaviour lives (the delta plan says which element should serve it)
|
|
370
|
+
and confirm the code realises the REQUIREMENT, not merely that some element with the
|
|
371
|
+
right name exists. A requirement with no realisation anywhere in the slice is a HIGH
|
|
372
|
+
`requirement` gap, fix `implement`. This is the failure no other gate can see: an
|
|
373
|
+
unbuilt requirement leaves NO failing test, so analyze-slice reports green on it;
|
|
374
|
+
(b) a requirement realised PARTIALLY — the happy path only, a rule enforced in one
|
|
375
|
+
caller and not another, an error contract the spec states and the code omits — is a
|
|
376
|
+
HIGH gap too. Say which part is missing;
|
|
377
|
+
(c) a MODIFIED item whose code still behaves the pre-change way is a HIGH gap;
|
|
378
|
+
(d) EXCEPT the Experience Standards (UX-), which this lane excludes by contract —
|
|
379
|
+
they belong to the frontend lane and are checked there.
|
|
380
|
+
Set `ref` to the delta-spec id and `where` to the file you looked in (or "absent").
|
|
381
|
+
|
|
382
|
+
CHECK 2 — TESTS PROVE THE REQUIREMENT. Every ADDED or MODIFIED delta-spec item has a
|
|
383
|
+
test that CITES its id and actually EXERCISES what it states — including the
|
|
384
|
+
constraints (an audit record is emitted, a DC-restricted field is not exposed, an IC-
|
|
385
|
+
projection round-trips). A requirement with code but no test is a HIGH `test` gap; a
|
|
386
|
+
test that exercises it but cites no id is MEDIUM. Judge what counts as a test by the
|
|
387
|
+
loaded testing standards: one that constructs the type and asserts nothing is not a
|
|
388
|
+
test for this purpose.
|
|
389
|
+
|
|
390
|
+
CHECK 3 — THE PLAN'S OWN PROMISES (cross-check, not the anchor). Every element the
|
|
391
|
+
delta plan marks ADDED exists, every MODIFIED one carries its change, every REMOVED
|
|
392
|
+
one is gone and unreferenced. A promised element nobody built is a HIGH `plan` gap
|
|
393
|
+
even when the requirement it served looks satisfied elsewhere — the two usually mean
|
|
394
|
+
the change was implemented in a different shape than was planned, which is worth
|
|
395
|
+
knowing before the masters are re-derived from it. Where the code satisfies the
|
|
396
|
+
requirement in a DIFFERENT and coherent shape, report it MEDIUM with `fix` = `plan`:
|
|
397
|
+
the plan is what is now wrong.
|
|
398
|
+
|
|
399
|
+
CHECK 4 — MODEL REALISATION. For every item in this change's MODEL DELTA (in
|
|
400
|
+
context): the entity, value object or event exists with the model's OWN name, and
|
|
401
|
+
each ADDED or CHANGED invariant (BR-nnn) is ENFORCED in the code. An invariant the
|
|
402
|
+
model delta introduces and no code enforces is a HIGH `model` gap — a BR- is a
|
|
403
|
+
requirement, not documentation. Do NOT restate the rule in your finding; cite its id,
|
|
404
|
+
say where it should be enforced and what you found there.
|
|
405
|
+
|
|
406
|
+
CHECK 5 — REGRESSION TARGETS. Each element under the delta plan's regression targets
|
|
407
|
+
has a test exercising the behaviour that was supposed to SURVIVE this change. A named
|
|
408
|
+
target with nothing testing it is a MEDIUM `regression` gap.
|
|
409
|
+
|
|
410
|
+
CHECK 6 — NO OVER-REACH. Behaviour this change introduced that NO delta-spec item
|
|
411
|
+
asked for and no delta-plan element declared is a MEDIUM `scope` gap — the change did
|
|
412
|
+
more than it was asked to, and the masters are about to be re-derived from documents
|
|
413
|
+
that do not describe it. Judge this only over what this change touched; do not report
|
|
414
|
+
the pre-existing slice.
|
|
415
|
+
|
|
416
|
+
CHECK 7 — PLACEMENT. Every file this change added or edited sits under the lane that
|
|
417
|
+
owns it: this lane's source path is `{{be_source_path}}`. A service-lane element
|
|
418
|
+
written into the frontend lane's subtree — or outside every lane root — is a HIGH
|
|
419
|
+
`placement` gap.
|
|
420
|
+
|
|
421
|
+
PLAN-ONLY CHANGE — if the delta-spec is an unfilled stub, this change deliberately
|
|
422
|
+
alters only HOW the EXISTING spec is realised (a refactor, an architectural decision).
|
|
423
|
+
Then checks 1 and 2 have no anchor and are SKIPPED, not failed. What applies instead:
|
|
424
|
+
the observable behaviour of every EXISTING spec id (master spec, in context) must be
|
|
425
|
+
UNCHANGED — a plan-only change that alters behaviour is a HIGH `requirement` gap
|
|
426
|
+
routing to `specify`, because that behaviour was never asked for — and checks 3 to 7
|
|
427
|
+
run as written.
|
|
428
|
+
|
|
429
|
+
Tag every gap with its `check`, its `severity` (high | medium) and the `fix` command
|
|
430
|
+
that closes it: `implement` when the code is missing or wrong, `plan` when the delta
|
|
431
|
+
plan is what is wrong, `specify` when the delta spec or the model delta is what is
|
|
432
|
+
missing. Set ok=true ONLY when every applicable check passes.
|
|
433
|
+
outputs:
|
|
434
|
+
- { name: be_ok, from: "$.ok" }
|
|
435
|
+
- { name: be_gaps, from: "$.gaps" }
|
|
436
|
+
|
|
437
|
+
- id: ctx_frontend
|
|
438
|
+
condition: "{{fe_gated}} == true"
|
|
439
|
+
action: build_context
|
|
440
|
+
context:
|
|
441
|
+
- { path: "{{delta_spec}}", optional: true } # THE ANCHOR — including this change's UX- items
|
|
442
|
+
- { path: "{{delta_model}}", optional: true } # the terms and rules the UI must speak
|
|
443
|
+
- { path: "{{delta_frontend_plan}}" } # THE MAP — which screen serves which requirement
|
|
444
|
+
- { path: "{{spec_file}}", optional: true } # the master spec — existing ids a plan-only change still serves
|
|
445
|
+
- { path: "{{frontend_plan}}", optional: true } # the master plan — what was already there
|
|
446
|
+
- { path: "{{domain_model}}", optional: true }
|
|
447
|
+
- id: check_frontend
|
|
448
|
+
condition: "{{fe_gated}} == true"
|
|
449
|
+
action: agent_query
|
|
450
|
+
tools: Read
|
|
451
|
+
include_standards: true
|
|
452
|
+
schema: { ok: true, gaps: [ { severity: "high", check: "<requirement|test|plan|model|regression|scope|placement>", lane: "frontend", ref: "<delta-spec id, or the delta-plan element where the check is 'plan'>", where: "<file or 'absent'>", gap: "<what is missing or wrong>", fix: "<implement|plan|specify>" } ] }
|
|
453
|
+
mock: { ok: true, gaps: [] }
|
|
454
|
+
task: |
|
|
455
|
+
Gate the FRONTEND lane's CODE for change {{cr_id}} (wave {{wave}}) against
|
|
456
|
+
delta-spec.md — THE ANCHOR in context. The question is: DOES THIS CHANGE DO WHAT IT
|
|
457
|
+
WAS ASKED TO DO? {{source_count}} file(s) realise this slice: {{source_files}} — READ
|
|
458
|
+
the ones this change should have touched.
|
|
459
|
+
The delta plan is in context as the MAP from a requirement to the screen, component
|
|
460
|
+
or state that serves it — it says WHERE to look, and it is not the authority: a
|
|
461
|
+
requirement the plan never planned is still this gate's finding. The master spec,
|
|
462
|
+
master plan and master model are what was ALREADY there and do not yet carry this
|
|
463
|
+
change.
|
|
464
|
+
|
|
465
|
+
CHECK 1 — REQUIREMENTS → CODE. For every ADDED or MODIFIED delta-spec item this lane
|
|
466
|
+
owns, the UI must actually DO what it states:
|
|
467
|
+
(a) every UX- Experience Standard is realised HERE — the service lane excludes them
|
|
468
|
+
by contract, so one realised in neither lane is a DROPPED requirement, a HIGH
|
|
469
|
+
`requirement` gap;
|
|
470
|
+
(b) every user story has a reachable screen and a working flow; every
|
|
471
|
+
interaction-state FR- is realised as the state it describes;
|
|
472
|
+
(c) the lifted constraints are honoured — CN- as what is hidden, disabled or
|
|
473
|
+
permission-gated; DC- as what never reaches client state, storage, the URL or
|
|
474
|
+
telemetry; IC-/SC- as the binding and the performance behaviour;
|
|
475
|
+
(d) a requirement realised PARTIALLY — the happy path only, one screen of two — is a
|
|
476
|
+
HIGH gap too; say which part is missing.
|
|
477
|
+
Set `ref` to the delta-spec id and `where` to the file (or "absent").
|
|
478
|
+
|
|
479
|
+
CHECK 2 — INTERACTION STATES ARE PART OF THE REQUIREMENT. For every interaction this
|
|
480
|
+
change adds or alters, the code renders its FULL state set — loading, empty, error,
|
|
481
|
+
permission-denied, in-flight/disabled — plus the validation timing, focus placement
|
|
482
|
+
and keyboard reachability. A state the delta describes and the code does not render
|
|
483
|
+
is a HIGH `requirement` gap: these are requirements, not polish, and they are the
|
|
484
|
+
first thing a generator drops.
|
|
485
|
+
|
|
486
|
+
CHECK 3 — TESTS PROVE THE REQUIREMENT. Every ADDED or MODIFIED delta-spec item has a
|
|
487
|
+
test citing its id (UX-/US-/FR-/CN-/DC-/IC-/SC-) that exercises what it states,
|
|
488
|
+
including the unwanted-behaviour states from check 2 and an accessibility assertion
|
|
489
|
+
per interactive surface. Missing test = HIGH `test` gap; a snapshot alone is not a
|
|
490
|
+
test; a test that exercises the change but cites no id is MEDIUM.
|
|
491
|
+
|
|
492
|
+
CHECK 4 — THE PLAN'S OWN PROMISES (cross-check, not the anchor). Every screen, route,
|
|
493
|
+
component, state container and binding the delta plan marks ADDED exists, every
|
|
494
|
+
MODIFIED one carries its change, every REMOVED one is gone and unreferenced. A
|
|
495
|
+
promised element nobody built is a HIGH `plan` gap; a requirement satisfied in a
|
|
496
|
+
DIFFERENT and coherent shape than planned is MEDIUM with `fix` = `plan`.
|
|
497
|
+
|
|
498
|
+
CHECK 5 — LANGUAGE AND AUTHORITY. Labels, states and messages use the ubiquitous
|
|
499
|
+
language of the model delta and the master model EXACTLY — a term this change renames
|
|
500
|
+
is renamed in the UI too, and a synonym is a MEDIUM `model` gap. A client-side check
|
|
501
|
+
may restate a server-enforced rule for FEEDBACK; if the client has become the ONLY
|
|
502
|
+
place a rule is enforced, that is a HIGH `model` gap.
|
|
503
|
+
|
|
504
|
+
CHECK 6 — NO OVER-REACH. A screen, control or behaviour this change introduced that
|
|
505
|
+
no delta-spec item asked for and no delta-plan element declared is a MEDIUM `scope`
|
|
506
|
+
gap. Judge it only over what this change touched.
|
|
507
|
+
|
|
508
|
+
CHECK 7 — PLACEMENT. Every file this change added or edited sits under this lane's
|
|
509
|
+
source path, `{{fe_source_path}}`. A file written into the service lane's subtree is a
|
|
510
|
+
HIGH `placement` gap — a gap in the service surface is a contract delta raised back to
|
|
511
|
+
that lane, never a client-side edit to it.
|
|
512
|
+
|
|
513
|
+
PLAN-ONLY CHANGE — if the delta-spec is an unfilled stub, this change alters only HOW
|
|
514
|
+
the existing spec is realised. Checks 1 to 3 have no anchor and are SKIPPED, not
|
|
515
|
+
failed; instead the observable experience of every EXISTING spec id must be UNCHANGED
|
|
516
|
+
(an alteration is a HIGH `requirement` gap routing to `specify`), and checks 4 to 7
|
|
517
|
+
run as written.
|
|
518
|
+
|
|
519
|
+
Tag every gap with its `check`, its `severity` (high | medium) and the `fix` command:
|
|
520
|
+
`implement` when the code is missing or wrong, `plan` when the delta plan is what is
|
|
521
|
+
wrong, `specify` when the delta spec or model delta is what is missing. Set ok=true
|
|
522
|
+
ONLY when every applicable check passes.
|
|
523
|
+
outputs:
|
|
524
|
+
- { name: fe_ok, from: "$.ok" }
|
|
525
|
+
- { name: fe_gaps, from: "$.gaps" }
|
|
526
|
+
|
|
527
|
+
# ═══════════════════════════ THE VERDICT ═══════════════════════════
|
|
528
|
+
# requirements_ok = every GATED lane passed. Expressed as a raise-then-knock-down chain,
|
|
529
|
+
# because the engine has no compound conditions and an ungated lane must not vote.
|
|
530
|
+
- id: requirements_seed
|
|
531
|
+
action: set
|
|
532
|
+
vars: { requirements_ok: "true" }
|
|
533
|
+
- id: requirements_clear_backend
|
|
534
|
+
condition: "{{be_ok}} == false"
|
|
535
|
+
action: set
|
|
536
|
+
vars: { requirements_ok: "false" }
|
|
537
|
+
- id: requirements_clear_frontend
|
|
538
|
+
condition: "{{fe_ok}} == false"
|
|
539
|
+
action: set
|
|
540
|
+
vars: { requirements_ok: "false" }
|
|
541
|
+
|
|
542
|
+
# gate_ok = the tests ran green AND every gated lane's requirements are met.
|
|
543
|
+
- id: gate_flag
|
|
544
|
+
condition: "{{test_ok}} == true"
|
|
545
|
+
action: set
|
|
546
|
+
vars: { gate_ok: "{{requirements_ok}}" }
|
|
547
|
+
|
|
548
|
+
# THE REPORT IS ALWAYS WRITTEN — green or red. A green one is the record that this change
|
|
549
|
+
# was verified built before it was merged, which is what makes the merge auditable; a red
|
|
550
|
+
# one is the work list. It lands beside the change's other documents, so close-delta
|
|
551
|
+
# archives it with them.
|
|
552
|
+
# An EMPTY envelope, on purpose. build_context REPLACES the payload and PERSISTS, so
|
|
553
|
+
# without this the report would inherit whichever lane's documents were checked last —
|
|
554
|
+
# and a report step holding the plans it is reporting on starts re-deriving findings
|
|
555
|
+
# instead of writing down the ones the checks returned. Everything it needs is in the
|
|
556
|
+
# variables below.
|
|
557
|
+
- id: ctx_report
|
|
558
|
+
action: build_context
|
|
559
|
+
context: []
|
|
560
|
+
- id: write_report
|
|
561
|
+
action: agent_author
|
|
562
|
+
include_standards: false
|
|
563
|
+
output_target: { type: file, path: "{{cr_dir}}/delta-slice-analyze-report.md" }
|
|
564
|
+
task: |
|
|
565
|
+
Write a Delta Slice Analyze Report for change {{cr_id}} (wave {{wave}}) to the
|
|
566
|
+
output. This gate asked whether the change's CODE does what its DELTA SPEC asked for
|
|
567
|
+
— the requirements are the anchor, the delta plan was the map — before finalize-delta
|
|
568
|
+
merges the change into spec.md and domain-model.md.
|
|
569
|
+
Evidence:
|
|
570
|
+
- tests: green={{test_ok}}, tool `{{test_tool}}`, actually ran={{test_ran}},
|
|
571
|
+
matched a slice filter={{test_matched}}, slice-scoped={{test_scoped}}. Log tail:
|
|
572
|
+
{{test_log}}
|
|
573
|
+
- service lane gated={{be_gated}}, verdict ok={{be_ok}}, gaps: {{be_gaps}}
|
|
574
|
+
- experience lane gated={{fe_gated}}, verdict ok={{fe_ok}}, gaps: {{fe_gaps}}
|
|
575
|
+
Markdown format:
|
|
576
|
+
- "# Delta Slice Analyze Report — {{cr_id}}" plus today's date.
|
|
577
|
+
- A verdict line: "verdict: REQUIREMENTS MET ✓" when the tests are green and every
|
|
578
|
+
gated lane passed, else "verdict: NOT READY ✗ · <n> finding(s)".
|
|
579
|
+
- "## Evidence" — the test fence (tool, green or red, and the log tail when red), and
|
|
580
|
+
which lanes were gated. A lane that was NOT gated is listed as "not gated — this
|
|
581
|
+
change has no delta plan for it", never as a pass. WHERE `actually ran` IS FALSE,
|
|
582
|
+
say so in that section in plain words — the fence went green because this project's
|
|
583
|
+
lanes declare no test command, not because a suite passed — and note that the
|
|
584
|
+
requirement findings below, not the fence, are what answer whether the change does
|
|
585
|
+
what it was asked to.
|
|
586
|
+
- "## Findings" as a table — | # | check | lane | severity | delta-spec ref | where |
|
|
587
|
+
finding | fixed by | — ordered high severity first, and within that the
|
|
588
|
+
`requirement` check first, because an unrealised requirement is the finding this
|
|
589
|
+
gate exists for. Omit the section entirely when there are none, and say so under
|
|
590
|
+
the verdict.
|
|
591
|
+
- "## How to resolve": group by the `fix` command. `implement` — re-run
|
|
592
|
+
/appweaver implement {{cr_id}} for the lane concerned; it generates only what the
|
|
593
|
+
delta plans mark ADDED/MODIFIED, so re-running it fills the gap without touching
|
|
594
|
+
what is already correct. `plan` — the requirement is met but the delta plan no
|
|
595
|
+
longer describes how, or it promised an element the code does not have; re-run
|
|
596
|
+
/appweaver plan {{cr_id}}, then analyze-plan-delta. `specify` — the delta spec or
|
|
597
|
+
the model delta is what is missing (a requirement realised in code that nothing
|
|
598
|
+
asked for lands here too, as does a plan-only change that moved behaviour); re-run
|
|
599
|
+
/appweaver specify, which is the only phase that authors either. Then re-run
|
|
600
|
+
/appweaver analyze-slice-delta {{cr_id}}.
|
|
601
|
+
- Close with one line stating that this gate verifies only; it generated no code and
|
|
602
|
+
repaired nothing.
|
|
603
|
+
Return the complete report markdown only.
|
|
604
|
+
outputs:
|
|
605
|
+
- { name: report_written, from: "$.status" }
|
|
606
|
+
|
|
607
|
+
- id: gate
|
|
608
|
+
action: verify_context
|
|
609
|
+
require_true: gate_ok
|
|
610
|
+
on_false: stop
|
|
611
|
+
on_false_message: "Change {{cr_id}} does NOT yet meet its delta spec. Tests green={{test_ok}} (tool `{{test_tool}}`); service lane gated={{be_gated}} ok={{be_ok}}; experience lane gated={{fe_gated}} ok={{fe_ok}}. Findings — backend: {{be_gaps}} · frontend: {{fe_gaps}}. The full report, with the command that closes each finding, is at {{cr_dir}}/delta-slice-analyze-report.md. DO NOT run finalize-delta yet: merging now would write requirements into spec.md and domain-model.md that the code does not satisfy, and the masters would describe an intention rather than the system. Fix the findings (a `requirement` or `plan` finding is usually /appweaver implement {{cr_id}}), re-run build, then re-run this gate."
|
|
612
|
+
|
|
613
|
+
# 6. Post-execution hooks.
|
|
614
|
+
- id: resolve_post_hooks
|
|
615
|
+
action: execute_script
|
|
616
|
+
script: { ref: actions }
|
|
617
|
+
subcommand: resolve-hooks
|
|
618
|
+
args: ["--phase", "after_analyze_slice_cr"]
|
|
619
|
+
outputs:
|
|
620
|
+
- { name: after_hooks, from: "$.hooks" }
|
|
621
|
+
- id: dispatch_post_hooks
|
|
622
|
+
action: dispatch_hooks
|
|
623
|
+
hooks_from_variable: after_hooks
|
|
624
|
+
|
|
625
|
+
outputs:
|
|
626
|
+
feature_dir: "{{feature_dir}}"
|
|
627
|
+
cr_id: "{{cr_id}}"
|
|
628
|
+
cr_dir: "{{cr_dir}}"
|
|
629
|
+
wave: "{{wave}}"
|
|
630
|
+
built: "{{gate_ok}}"
|
|
631
|
+
tests_green: "{{test_ok}}"
|
|
632
|
+
tests_ran: "{{test_ran}}" # false + green = the project declares no test command
|
|
633
|
+
test_tool: "{{test_tool}}"
|
|
634
|
+
backend_gated: "{{be_gated}}"
|
|
635
|
+
backend_ok: "{{be_ok}}"
|
|
636
|
+
backend_gaps: "{{be_gaps}}"
|
|
637
|
+
frontend_gated: "{{fe_gated}}"
|
|
638
|
+
frontend_ok: "{{fe_ok}}"
|
|
639
|
+
frontend_gaps: "{{fe_gaps}}"
|
|
640
|
+
report: "{{cr_dir}}/delta-slice-analyze-report.md"
|
|
641
|
+
source_count: "{{source_count}}"
|
|
642
|
+
note: "Gated change {{cr_id}} (wave {{wave}}) — delta-spec.md is the ANCHOR, so the question answered here is whether the CODE does what the change asked for, not whether it matches the plan. The delta plan is the MAP from a requirement to the element that serves it, and is cross-checked in its own right; the change's model delta supplies the invariants the code must enforce, and they are requirements too. The masters are read-only context for what was already there — they do not carry this change until finalize-delta merges it. Only a lane with a delta plan for THIS change is gated: backend {{be_gated}}, frontend {{fe_gated}} — an ungated lane is reported as not gated, never as a pass. The tests ran here for the first time on the change path, since build only compiles. This gate verifies: it generated no code and repaired nothing, and every finding names the command that closes it."
|
|
643
|
+
next: "/appweaver finalize-delta → analyze-slice → close-delta. The change MEETS ITS SPEC and is still OPEN: finalize-delta merges it into spec.md + the context's domain-model.md — writing requirements the code has now been shown to satisfy — analyze-slice then scores the WHOLE slice against those merged masters (behaviour, domain conformance and the referrer blast radius) while a red result is still recoverable, and close-delta LAST archives the change and bumps the version."
|