aw-spec-cli 0.1.33 → 0.1.35
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +76 -81
- package/assets/.appweaver/DESIGN-FORMAT.md +57 -25
- package/assets/.appweaver/STACK-PROFILES.md +95 -60
- package/assets/.appweaver/orchestrator/LAUNCHER.md +1 -1
- package/assets/.appweaver/orchestrator/modules/delta-plan.orch.yaml +173 -32
- package/assets/.appweaver/orchestrator/modules/domain-select.orch.yaml +29 -1
- package/assets/.appweaver/orchestrator/modules/foundation-pack.orch.yaml +7 -4
- package/assets/.appweaver/orchestrator/modules/foundation-spec.orch.yaml +49 -60
- package/assets/.appweaver/orchestrator/modules/tech-select.orch.yaml +58 -0
- package/assets/.appweaver/orchestrator/orchestrator.py +26 -8
- package/assets/.appweaver/orchestrator/rev-templates/delta-design-template.skeleton.md +20 -20
- package/assets/.appweaver/orchestrator/rev-templates/design-template.skeleton.md +22 -48
- package/assets/.appweaver/orchestrator/rev-templates/ui-delta-design-template.skeleton.md +9 -7
- package/assets/.appweaver/orchestrator/rev-templates/ui-design-template.skeleton.md +5 -5
- package/assets/.appweaver/orchestrator/workflows/aw-spec-adopt.orch.yaml +239 -40
- package/assets/.appweaver/orchestrator/workflows/aw-spec-analyze-plan-delta.orch.yaml +254 -43
- package/assets/.appweaver/orchestrator/workflows/aw-spec-analyze-plan.orch.yaml +248 -68
- package/assets/.appweaver/orchestrator/workflows/aw-spec-analyze-slice-delta.orch.yaml +251 -20
- package/assets/.appweaver/orchestrator/workflows/aw-spec-analyze-slice.orch.yaml +316 -10
- package/assets/.appweaver/orchestrator/workflows/aw-spec-build.orch.yaml +6 -47
- package/assets/.appweaver/orchestrator/workflows/aw-spec-close-delta.orch.yaml +62 -16
- package/assets/.appweaver/orchestrator/workflows/aw-spec-finalize-delta.orch.yaml +132 -9
- package/assets/.appweaver/orchestrator/workflows/aw-spec-fix-test-coverage.orch.yaml +965 -0
- package/assets/.appweaver/orchestrator/workflows/aw-spec-implement.orch.yaml +222 -169
- package/assets/.appweaver/orchestrator/workflows/aw-spec-onboard.orch.yaml +21 -22
- package/assets/.appweaver/orchestrator/workflows/aw-spec-plan.orch.yaml +453 -120
- package/assets/.appweaver/orchestrator/workflows/aw-spec-select-lane.orch.yaml +2 -2
- package/assets/.appweaver/orchestrator/workflows/aw-spec-select-stack.orch.yaml +83 -6
- package/assets/.appweaver/orchestrator/workflows/aw-spec-specify.orch.yaml +45 -2
- package/assets/.appweaver/scripts/bash/aw-spec-actions.sh +324 -74
- package/assets/.appweaver/scripts/powershell/aw-spec-actions.ps1 +275 -44
- package/assets/.appweaver/scripts/python/aw-foundation.py +16 -13
- package/assets/.appweaver/scripts/python/aw-gaps.py +11 -3
- package/assets/.appweaver/scripts/python/aw-model-guard.py +295 -0
- package/assets/.appweaver/scripts/python/aw-plan-coverage.py +412 -3
- package/assets/.appweaver/scripts/python/aw-plangate.py +23 -16
- package/assets/.appweaver/scripts/python/aw-stack.py +1794 -265
- package/assets/.appweaver/stack-profiles/dotnet-webapi.json +0 -2
- package/assets/.appweaver/stack-profiles/java-spring.json +0 -2
- package/assets/.appweaver/templates/api-plan-template.md +107 -0
- package/assets/.appweaver/templates/delta-api-plan-template.md +87 -0
- package/assets/.appweaver/templates/delta-design-template.md +25 -23
- package/assets/.appweaver/templates/delta-spec-template.md +3 -3
- package/assets/.appweaver/templates/design-template.md +20 -42
- package/assets/.appweaver/templates/domain-model-template.md +3 -0
- package/assets/.appweaver/templates/ui-delta-design-template.md +11 -8
- package/assets/.appweaver/templates/ui-design-template.md +4 -4
- package/assets/foundations/foundation.spec.template.txt +25 -18
- package/assets/guardrails/README.md +61 -25
- package/assets/guardrails/methodology/ux/accessibility-standards.md +38 -0
- package/assets/guardrails/methodology/ux/content-design.md +34 -0
- package/assets/guardrails/methodology/ux/interaction-states.md +45 -0
- package/assets/guardrails/methodology/ux/journey-mapping.md +41 -0
- package/assets/guardrails/project-specific/domain/domain-requirements.md +25 -38
- package/assets/guardrails/project-specific/domain-rule-bindings.md +33 -69
- package/assets/guardrails/project-specific/frontend/ui-requirements.md +2 -2
- package/assets/guardrails/project-specific/service/technical-requirements.md +2 -2
- package/assets/guardrails/project-specific/tech-rule-bindings.md +16 -13
- package/assets/guardrails/sample-healthcare/domain/domain-requirements.md +58 -0
- package/assets/guardrails/sample-healthcare/domain-rule-bindings.md +138 -0
- package/assets/guardrails/sample-healthcare/frontend/ui-requirements.md +43 -0
- package/assets/guardrails/sample-healthcare/service/technical-requirements.md +40 -0
- package/assets/guardrails/sample-healthcare/tech-rule-bindings.md +303 -0
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +216 -7
- package/dist/commands/init.js.map +1 -1
- package/dist/utils/config.js +1 -1
- package/dist/utils/config.js.map +1 -1
- package/dist/utils/foundation.d.ts +36 -0
- package/dist/utils/foundation.d.ts.map +1 -0
- package/dist/utils/foundation.js +109 -0
- package/dist/utils/foundation.js.map +1 -0
- package/dist/utils/paths.js +1 -1
- package/dist/utils/paths.js.map +1 -1
- package/package.json +1 -1
|
@@ -53,7 +53,8 @@
|
|
|
53
53
|
# lane rule set, no constitution, no stack binding — which is the same reason analyze-plan
|
|
54
54
|
# stops naming `/appweaver plan` instead of filling an empty template itself. So every
|
|
55
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
|
|
56
|
+
# a delta plan that is wrong, specify for a spec or model gap, fix-test-coverage for a
|
|
57
|
+
# requirement no test names) and the gate stops. The
|
|
57
58
|
# repair loops stay in analyze-slice, where the merged master is the anchor and the job is
|
|
58
59
|
# fixing what is BROKEN rather than building what is ABSENT.
|
|
59
60
|
#
|
|
@@ -73,6 +74,29 @@
|
|
|
73
74
|
# way: a developer working one lane of two writes delta-slice-analyze-report.<lane>.md, and
|
|
74
75
|
# a developer on every lane writes delta-slice-analyze-report.md.
|
|
75
76
|
#
|
|
77
|
+
# EVERY REQUIREMENT THE CHANGE'S PLAN SERVES IS NAMED BY A TEST — checked by a script as
|
|
78
|
+
# well as by the model. Check 2 asks the model whether each ADDED or MODIFIED item has a
|
|
79
|
+
# test citing its id; `test-citations` answers the same question deterministically for the
|
|
80
|
+
# FR- and BR- ids each gated lane's delta plan rows serve (ADDED, MODIFIED, model changes,
|
|
81
|
+
# interaction states — removed rows aside), over the slice's test files. An id no test
|
|
82
|
+
# names fails that lane's requirement vote and joins its findings, so it is stamped and
|
|
83
|
+
# reported like the model's own, and routed to /appweaver fix-test-coverage <CR-id> — the
|
|
84
|
+
# workflow that writes the missing tests; one the model already reported as untested is not
|
|
85
|
+
# reported twice. analyze-slice runs the master-plan half of this after the merge, but the
|
|
86
|
+
# change's new ids reach the master plans only when plan re-derives them, so this is where
|
|
87
|
+
# they are checked.
|
|
88
|
+
#
|
|
89
|
+
# THE SERVICE SERVES THE CHANGE'S API AS ITS DELTA API PLAN DRAFTS IT — checked by a script
|
|
90
|
+
# too. The frontend lane binds to the change's API draft (changes/<CR-id>/api-draft.json,
|
|
91
|
+
# drafted from delta-api-plan.md, or from the delta backend plan of a change planned before
|
|
92
|
+
# delta API plans existed) while the change is open, so for a gated service lane the
|
|
93
|
+
# service's as-built document is written the way the lane says and compared with it
|
|
94
|
+
# (contract-verify --cr): an endpoint the change adds or changes that is not served as
|
|
95
|
+
# drafted, or one it removes that is still served, fails that lane's requirement vote and
|
|
96
|
+
# joins its findings, routed to implement. A field that differs is reported. A lane that sets
|
|
97
|
+
# no way to write its document is not checked, and the run says so. A change that drafts no
|
|
98
|
+
# API change is not checked either, and its document is not written.
|
|
99
|
+
#
|
|
76
100
|
# NO NEW RULE-MAP HEADING. It loads `## /aw-spec-analyze-slice` — the same testing +
|
|
77
101
|
# coding-standards set its master twin reads — so no project has to add configuration to
|
|
78
102
|
# get this gate. The DOMAIN gate overlays are deliberately NOT loaded: full domain
|
|
@@ -86,8 +110,8 @@
|
|
|
86
110
|
# =============================================================================
|
|
87
111
|
|
|
88
112
|
name: aw-spec-analyze-slice-delta
|
|
89
|
-
version: 1.
|
|
90
|
-
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 (only the changes naming a lane you work on are listed) and gates only the lanes the change names that you work on. Each gated lane runs its own tests (the first execution on the change path, since build only compiles), then its code and paired tests are evaluated 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. Each gated lane's pass or fail is recorded in the change as .aw-slice-gate.<lane>.json. 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."
|
|
113
|
+
version: 1.7.0
|
|
114
|
+
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 (only the changes naming a lane you work on are listed) and gates only the lanes the change names that you work on. Each gated lane runs its own tests (the first execution on the change path, since build only compiles), then its code and paired tests are evaluated 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 (and, by script, every FR- and BR- the lane's delta plan rows serve named by a test of the slice), the service lane serving the API the change's delta API plan drafts (by script, against its as-built document), 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. Each gated lane's pass or fail is recorded in the change as .aw-slice-gate.<lane>.json. 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."
|
|
91
115
|
agent_agnostic: true
|
|
92
116
|
dialect: aw-spec.orchestrator/v1
|
|
93
117
|
|
|
@@ -124,6 +148,8 @@ vars:
|
|
|
124
148
|
delta_backend_plan_exists: "false"
|
|
125
149
|
delta_frontend_plan: ""
|
|
126
150
|
delta_frontend_plan_exists: "false"
|
|
151
|
+
delta_api_plan: "" # the change's API — absent for a change whose delta backend plan carries it
|
|
152
|
+
api_plan: "" # the feature's API plan — absent for a feature whose backend plan carries it
|
|
127
153
|
domain_model: ""
|
|
128
154
|
# WHICH LANES THIS GATE CHECKS — a lane is gated when it is DECLARED for this feature, the
|
|
129
155
|
# change's **Lanes** line NAMES it, this developer WORKS on it (.appweaver/lane.json) and
|
|
@@ -191,6 +217,39 @@ vars:
|
|
|
191
217
|
be_req_vote: "true"
|
|
192
218
|
fe_req_vote: "true"
|
|
193
219
|
requirements_ok: "false"
|
|
220
|
+
# The test-citation check, per gated lane. Its `ok` votes into that lane's requirement
|
|
221
|
+
# vote only when the lane is gated, and a check that never answered votes not met.
|
|
222
|
+
be_cite_ok: "false"
|
|
223
|
+
be_cite_clean: "false"
|
|
224
|
+
be_cite_warning: ""
|
|
225
|
+
be_uncited: "not checked — the lane is not gated"
|
|
226
|
+
be_cite_findings: []
|
|
227
|
+
be_cite_vote: "true"
|
|
228
|
+
fe_cite_ok: "false"
|
|
229
|
+
fe_cite_clean: "false"
|
|
230
|
+
fe_cite_warning: ""
|
|
231
|
+
fe_uncited: "not checked — the lane is not gated"
|
|
232
|
+
fe_cite_findings: []
|
|
233
|
+
fe_cite_vote: "true"
|
|
234
|
+
# The API check of a gated service lane — the same refusing default as the citation
|
|
235
|
+
# check, voting only when its document was written, and only for a change that drafts an
|
|
236
|
+
# API change.
|
|
237
|
+
be_api_needed: "false" # contract-verify --cr --check: the change drafts something to check
|
|
238
|
+
be_api_plan_note: "" # why it drafts nothing, when it does not
|
|
239
|
+
be_api_way: ""
|
|
240
|
+
be_api_placeholder: ""
|
|
241
|
+
be_api_export_ok: "false"
|
|
242
|
+
be_api_export_reason: ""
|
|
243
|
+
be_api_export_log: ""
|
|
244
|
+
be_api_has_way: "true"
|
|
245
|
+
be_api_export_vote: "true"
|
|
246
|
+
be_api_export_clean: "true"
|
|
247
|
+
be_api_ok: ""
|
|
248
|
+
be_api_issues: "not checked — no as-built API document was written in this run"
|
|
249
|
+
be_api_warning: ""
|
|
250
|
+
be_api_clean: "true"
|
|
251
|
+
be_api_findings: []
|
|
252
|
+
be_api_vote: "true"
|
|
194
253
|
# Findings split by the command that closes them (gap-route). Defaults read as
|
|
195
254
|
# "nothing found", so a run where the router could not execute still prints.
|
|
196
255
|
gap_summary: "no findings"
|
|
@@ -201,6 +260,8 @@ vars:
|
|
|
201
260
|
fix_plan_n: "0"
|
|
202
261
|
fix_spec: "none"
|
|
203
262
|
fix_spec_n: "0"
|
|
263
|
+
fix_tests: "none"
|
|
264
|
+
fix_tests_n: "0"
|
|
204
265
|
fix_review: "none"
|
|
205
266
|
fix_review_n: "0"
|
|
206
267
|
gate_ok: "false"
|
|
@@ -253,6 +314,7 @@ workflow:
|
|
|
253
314
|
- { name: spec_file, from: "$.spec_file" }
|
|
254
315
|
- { name: backend_plan, from: "$.backend_plan" }
|
|
255
316
|
- { name: frontend_plan, from: "$.frontend_plan" }
|
|
317
|
+
- { name: api_plan, from: "$.api_plan" }
|
|
256
318
|
|
|
257
319
|
# THIS FEATURE'S LANES. lane_resolve above read the REPO's declaration; one feature may
|
|
258
320
|
# own no part of a lane's surface — adopt records `lanes: [backend]` in
|
|
@@ -354,6 +416,7 @@ workflow:
|
|
|
354
416
|
- { name: delta_backend_plan_exists, from: "$.delta_backend_plan_exists" }
|
|
355
417
|
- { name: delta_frontend_plan, from: "$.delta_frontend_plan" }
|
|
356
418
|
- { name: delta_frontend_plan_exists, from: "$.delta_frontend_plan_exists" }
|
|
419
|
+
- { name: delta_api_plan, from: "$.delta_api_plan" }
|
|
357
420
|
- { name: wave, from: "$.wave" }
|
|
358
421
|
- { name: domain_model, from: "$.domain_model" }
|
|
359
422
|
# The lanes this change touches — its delta-spec's **Lanes** line, every lane when it
|
|
@@ -557,8 +620,10 @@ workflow:
|
|
|
557
620
|
- { path: "{{delta_spec}}", optional: true } # THE ANCHOR — what this change was asked to do
|
|
558
621
|
- { path: "{{delta_model}}", optional: true } # the invariants it adds or changes — requirements too
|
|
559
622
|
- { path: "{{delta_backend_plan}}" } # THE MAP — which element serves which requirement
|
|
623
|
+
- { path: "{{delta_api_plan}}", optional: true } # the change's API — the endpoints it adds, changes or removes, and their error contracts
|
|
560
624
|
- { path: "{{spec_file}}", optional: true } # the master spec — the EXISTING ids a plan-only change still serves
|
|
561
625
|
- { path: "{{backend_plan}}", optional: true } # the master plan — what was already there
|
|
626
|
+
- { path: "{{api_plan}}", optional: true } # the master API plan — the endpoints as they were
|
|
562
627
|
- { path: "{{domain_model}}", optional: true } # the model as it stands before the merge
|
|
563
628
|
- id: check_backend
|
|
564
629
|
condition: "{{be_gated}} == true"
|
|
@@ -573,14 +638,15 @@ workflow:
|
|
|
573
638
|
not "does it match the plan": it is DOES THIS CHANGE DO WHAT IT WAS ASKED TO DO?
|
|
574
639
|
{{source_count}} file(s) realise this slice: {{source_files}} — READ the ones this
|
|
575
640
|
change should have touched.
|
|
576
|
-
The delta plan
|
|
577
|
-
|
|
641
|
+
The delta plan — with the change's delta-api-plan.md, in context where it has one —
|
|
642
|
+
is in context as the MAP from a requirement to the element or endpoint that serves
|
|
643
|
+
it: use it to know WHERE to look, and to write a finding that names the place the
|
|
578
644
|
behaviour was supposed to land. It is not the authority: a requirement the plan never
|
|
579
645
|
planned is still this gate's finding, because the delta spec is the only document
|
|
580
646
|
that knows it was asked for.
|
|
581
|
-
The master spec, master plan and master domain model are what was
|
|
582
|
-
do not yet carry this change (finalize-delta merges it AFTER this
|
|
583
|
-
report an element as missing from them.
|
|
647
|
+
The master spec, master plan, master API plan and master domain model are what was
|
|
648
|
+
ALREADY there; they do not yet carry this change (finalize-delta merges it AFTER this
|
|
649
|
+
gate), so never report an element as missing from them.
|
|
584
650
|
|
|
585
651
|
CHECK 1 — REQUIREMENTS → CODE (the reason this gate exists). For EVERY ADDED or
|
|
586
652
|
MODIFIED item in the delta-spec — FR-, BR-, CN-, DC-, IC-, user story — the code must
|
|
@@ -608,7 +674,9 @@ workflow:
|
|
|
608
674
|
|
|
609
675
|
CHECK 3 — THE PLAN'S OWN PROMISES (cross-check, not the anchor). Every element the
|
|
610
676
|
delta plan marks ADDED exists, every MODIFIED one carries its change, every REMOVED
|
|
611
|
-
one is gone and unreferenced
|
|
677
|
+
one is gone and unreferenced; every endpoint the API delta adds or changes is served
|
|
678
|
+
at the route and verb its block gives, with its error contract, and every one it
|
|
679
|
+
removes is no longer served. A promised element nobody built is a HIGH `plan` gap
|
|
612
680
|
even when the requirement it served looks satisfied elsewhere — the two usually mean
|
|
613
681
|
the change was implemented in a different shape than was planned, which is worth
|
|
614
682
|
knowing before the masters are re-derived from it. Where the code satisfies the
|
|
@@ -747,6 +815,131 @@ workflow:
|
|
|
747
815
|
- { name: fe_ok, from: "$.ok" }
|
|
748
816
|
- { name: fe_gaps, from: "$.gaps" }
|
|
749
817
|
|
|
818
|
+
# ══════ PASS 3 — TEST CITATIONS. Is every requirement the change serves named by a test? ══════
|
|
819
|
+
# The deterministic half of check 2: the FR- and BR- ids each gated lane's delta plan rows
|
|
820
|
+
# serve, looked for in the slice's test files. An id the lane's check already reported as
|
|
821
|
+
# untested is not reported again (`--known-gaps`).
|
|
822
|
+
- id: cite_backend
|
|
823
|
+
condition: "{{be_gated}} == true"
|
|
824
|
+
action: execute_script
|
|
825
|
+
on_error: continue
|
|
826
|
+
script: { ref: actions }
|
|
827
|
+
subcommand: test-citations
|
|
828
|
+
args: ["--plan", "{{delta_backend_plan}}", "--kind", "backend", "--mode", "delta", "--paths", "{{source_files}}", "--source-path", "{{be_source_path}}", "--test-path", "{{be_test_path}}", "--known-gaps", "{{be_gaps}}"]
|
|
829
|
+
outputs:
|
|
830
|
+
- { name: be_cite_ok, from: "$.ok" }
|
|
831
|
+
- { name: be_cite_clean, from: "$.clean" }
|
|
832
|
+
- { name: be_cite_warning, from: "$.warning" }
|
|
833
|
+
- { name: be_uncited, from: "$.uncited_text" }
|
|
834
|
+
- { name: be_cite_findings, from: "$.findings" }
|
|
835
|
+
- id: warn_cite_backend
|
|
836
|
+
condition: "{{be_gated}} == true"
|
|
837
|
+
action: verify_context
|
|
838
|
+
require_true: be_cite_clean
|
|
839
|
+
on_false: continue
|
|
840
|
+
on_false_message: "{{be_cite_warning}}"
|
|
841
|
+
- id: cite_frontend
|
|
842
|
+
condition: "{{fe_gated}} == true"
|
|
843
|
+
action: execute_script
|
|
844
|
+
on_error: continue
|
|
845
|
+
script: { ref: actions }
|
|
846
|
+
subcommand: test-citations
|
|
847
|
+
args: ["--plan", "{{delta_frontend_plan}}", "--kind", "frontend", "--mode", "delta", "--paths", "{{source_files}}", "--source-path", "{{fe_source_path}}", "--test-path", "{{fe_test_path}}", "--known-gaps", "{{fe_gaps}}"]
|
|
848
|
+
outputs:
|
|
849
|
+
- { name: fe_cite_ok, from: "$.ok" }
|
|
850
|
+
- { name: fe_cite_clean, from: "$.clean" }
|
|
851
|
+
- { name: fe_cite_warning, from: "$.warning" }
|
|
852
|
+
- { name: fe_uncited, from: "$.uncited_text" }
|
|
853
|
+
- { name: fe_cite_findings, from: "$.findings" }
|
|
854
|
+
- id: warn_cite_frontend
|
|
855
|
+
condition: "{{fe_gated}} == true"
|
|
856
|
+
action: verify_context
|
|
857
|
+
require_true: fe_cite_clean
|
|
858
|
+
on_false: continue
|
|
859
|
+
on_false_message: "{{fe_cite_warning}}"
|
|
860
|
+
|
|
861
|
+
# ══════ PASS 4 — API. Does the built service serve the change's API as its delta API plan drafts it? ══════
|
|
862
|
+
# Only for a change that drafts an API change: contract-verify --cr --check reads the
|
|
863
|
+
# change's draft without the as-built document, so a behaviour-only change never runs the
|
|
864
|
+
# lane's export or its warnings. Only an explicit `needed: false` skips: a check that does
|
|
865
|
+
# not answer leaves the export armed.
|
|
866
|
+
- id: api_plan_check
|
|
867
|
+
condition: "{{be_gated}} == true"
|
|
868
|
+
action: execute_script
|
|
869
|
+
on_error: continue
|
|
870
|
+
script: { ref: actions }
|
|
871
|
+
subcommand: contract-verify
|
|
872
|
+
args: ["--feature-dir", "{{feature_dir}}", "--cr", "{{cr_id}}", "--check"]
|
|
873
|
+
outputs:
|
|
874
|
+
- { name: be_api_needed, from: "$.needed" }
|
|
875
|
+
- { name: be_api_plan_note, from: "$.note" }
|
|
876
|
+
- id: api_nothing_to_check
|
|
877
|
+
condition: "{{be_api_plan_note}} != "
|
|
878
|
+
action: set
|
|
879
|
+
vars: { be_api_issues: "{{be_api_plan_note}}" }
|
|
880
|
+
- id: api_export
|
|
881
|
+
condition: "{{be_api_needed}} != false"
|
|
882
|
+
action: execute_script
|
|
883
|
+
on_error: continue
|
|
884
|
+
script: { ref: actions }
|
|
885
|
+
subcommand: contract-export
|
|
886
|
+
outputs:
|
|
887
|
+
- { name: be_api_export_ok, from: "$.ok" }
|
|
888
|
+
- { name: be_api_way, from: "$.way" }
|
|
889
|
+
- { name: be_api_export_reason, from: "$.reason" }
|
|
890
|
+
- { name: be_api_export_log, from: "$.log_tail" }
|
|
891
|
+
- { name: be_api_placeholder, from: "$.placeholder" }
|
|
892
|
+
- id: api_no_way_flag
|
|
893
|
+
condition: "{{be_api_way}} == none"
|
|
894
|
+
action: set
|
|
895
|
+
vars: { be_api_has_way: "false" }
|
|
896
|
+
- id: warn_api_no_way
|
|
897
|
+
condition: "{{be_api_needed}} != false"
|
|
898
|
+
action: verify_context
|
|
899
|
+
require_true: be_api_has_way
|
|
900
|
+
on_false: continue
|
|
901
|
+
on_false_message: "API NOT CHECKED — {{be_api_export_reason}}. The frontend lane binds to the API this change's delta API plan drafts (changes/{{cr_id}}/api-draft.json); without the service's as-built document nothing checks that the code serves it. `contract_write` is any command that writes the service's OpenAPI document to the path {{be_api_placeholder}} stands for, with no server started."
|
|
902
|
+
- id: api_export_vote_set
|
|
903
|
+
condition: "{{be_api_needed}} != false"
|
|
904
|
+
action: set
|
|
905
|
+
vars: { be_api_export_vote: "{{be_api_export_ok}}" }
|
|
906
|
+
- id: api_export_failed
|
|
907
|
+
condition: "{{be_api_export_vote}} != true"
|
|
908
|
+
action: set
|
|
909
|
+
vars: { be_api_export_clean: "false" }
|
|
910
|
+
- id: api_export_no_way
|
|
911
|
+
condition: "{{be_api_has_way}} == false"
|
|
912
|
+
action: set
|
|
913
|
+
vars: { be_api_export_clean: "true" }
|
|
914
|
+
- id: warn_api_export
|
|
915
|
+
condition: "{{be_api_needed}} != false"
|
|
916
|
+
action: verify_context
|
|
917
|
+
require_true: be_api_export_clean
|
|
918
|
+
on_false: continue
|
|
919
|
+
on_false_message: "API NOT CHECKED — the service's as-built API document could not be written: {{be_api_export_reason}}. Correct `contract_write` (or `contract_run` / `contract`) on the service lane in .appweaver/stacks.json, start anything it needs, and re-run analyze-slice-delta {{cr_id}}. Output: {{be_api_export_log}}"
|
|
920
|
+
- id: api_verify
|
|
921
|
+
condition: "{{be_api_export_ok}} == true"
|
|
922
|
+
action: execute_script
|
|
923
|
+
on_error: continue
|
|
924
|
+
script: { ref: actions }
|
|
925
|
+
subcommand: contract-verify
|
|
926
|
+
args: ["--feature-dir", "{{feature_dir}}", "--cr", "{{cr_id}}"]
|
|
927
|
+
outputs:
|
|
928
|
+
- { name: be_api_ok, from: "$.ok" }
|
|
929
|
+
- { name: be_api_issues, from: "$.issues_text" }
|
|
930
|
+
- { name: be_api_warning, from: "$.warning" }
|
|
931
|
+
- { name: be_api_findings, from: "$.findings" }
|
|
932
|
+
- id: api_warning_flag
|
|
933
|
+
condition: "{{be_api_warning}} != "
|
|
934
|
+
action: set
|
|
935
|
+
vars: { be_api_clean: "false" }
|
|
936
|
+
- id: warn_api_fields
|
|
937
|
+
condition: "{{be_api_export_ok}} == true"
|
|
938
|
+
action: verify_context
|
|
939
|
+
require_true: be_api_clean
|
|
940
|
+
on_false: continue
|
|
941
|
+
on_false_message: "{{be_api_warning}}"
|
|
942
|
+
|
|
750
943
|
# ═══════════════════════════ THE VERDICT ═══════════════════════════
|
|
751
944
|
# requirements_ok = every GATED lane passed. Expressed as a raise-then-knock-down chain,
|
|
752
945
|
# because the engine has no compound conditions and an ungated lane must not vote. A gated
|
|
@@ -768,6 +961,32 @@ workflow:
|
|
|
768
961
|
condition: "{{fe_ok}} == true"
|
|
769
962
|
action: set
|
|
770
963
|
vars: { fe_req_vote: "true" }
|
|
964
|
+
# A requirement no test names knocks the lane's vote down, whatever its check said.
|
|
965
|
+
- id: be_cite_vote_set
|
|
966
|
+
condition: "{{be_gated}} == true"
|
|
967
|
+
action: set
|
|
968
|
+
vars: { be_cite_vote: "{{be_cite_ok}}" }
|
|
969
|
+
- id: be_req_vote_uncited
|
|
970
|
+
condition: "{{be_cite_vote}} != true"
|
|
971
|
+
action: set
|
|
972
|
+
vars: { be_req_vote: "false" }
|
|
973
|
+
# So does an endpoint the change drafts that the service does not serve as drafted.
|
|
974
|
+
- id: be_api_vote_set
|
|
975
|
+
condition: "{{be_api_export_ok}} == true"
|
|
976
|
+
action: set
|
|
977
|
+
vars: { be_api_vote: "{{be_api_ok}}" }
|
|
978
|
+
- id: be_req_vote_api
|
|
979
|
+
condition: "{{be_api_vote}} != true"
|
|
980
|
+
action: set
|
|
981
|
+
vars: { be_req_vote: "false" }
|
|
982
|
+
- id: fe_cite_vote_set
|
|
983
|
+
condition: "{{fe_gated}} == true"
|
|
984
|
+
action: set
|
|
985
|
+
vars: { fe_cite_vote: "{{fe_cite_ok}}" }
|
|
986
|
+
- id: fe_req_vote_uncited
|
|
987
|
+
condition: "{{fe_cite_vote}} != true"
|
|
988
|
+
action: set
|
|
989
|
+
vars: { fe_req_vote: "false" }
|
|
771
990
|
- id: requirements_seed
|
|
772
991
|
action: set
|
|
773
992
|
vars: { requirements_ok: "true" }
|
|
@@ -791,7 +1010,7 @@ workflow:
|
|
|
791
1010
|
on_error: continue
|
|
792
1011
|
script: { ref: actions }
|
|
793
1012
|
subcommand: gap-route
|
|
794
|
-
args: ["--cr", "{{cr_id}}", "--gaps", "{{be_gaps}}", "--gaps", "{{fe_gaps}}"]
|
|
1013
|
+
args: ["--cr", "{{cr_id}}", "--gaps", "{{be_gaps}}", "--gaps", "{{fe_gaps}}", "--gaps", "{{be_cite_findings}}", "--gaps", "{{fe_cite_findings}}", "--gaps", "{{be_api_findings}}"]
|
|
795
1014
|
outputs:
|
|
796
1015
|
- { name: gap_summary, from: "$.summary" }
|
|
797
1016
|
- { name: gap_total, from: "$.total" }
|
|
@@ -801,6 +1020,8 @@ workflow:
|
|
|
801
1020
|
- { name: fix_plan_n, from: "$.plan_count" }
|
|
802
1021
|
- { name: fix_spec, from: "$.specify_text" }
|
|
803
1022
|
- { name: fix_spec_n, from: "$.specify_count" }
|
|
1023
|
+
- { name: fix_tests, from: "$.tests_text" }
|
|
1024
|
+
- { name: fix_tests_n, from: "$.tests_count" }
|
|
804
1025
|
- { name: fix_review, from: "$.review_text" }
|
|
805
1026
|
- { name: fix_review_n, from: "$.review_count" }
|
|
806
1027
|
|
|
@@ -820,7 +1041,7 @@ workflow:
|
|
|
820
1041
|
on_error: continue
|
|
821
1042
|
script: { ref: actions }
|
|
822
1043
|
subcommand: slice-gate-stamp
|
|
823
|
-
args: ["--cr-id", "{{cr_id}}", "--feature-dir", "{{feature_dir}}", "--tests-green", "{{be_test_ok}}", "--tests-ran", "{{be_test_ran}}", "--requirements-ok", "{{be_req_vote}}", "--findings", "{{be_gaps}}", "--lane", "backend"]
|
|
1044
|
+
args: ["--cr-id", "{{cr_id}}", "--feature-dir", "{{feature_dir}}", "--tests-green", "{{be_test_ok}}", "--tests-ran", "{{be_test_ran}}", "--requirements-ok", "{{be_req_vote}}", "--findings", "{{be_gaps}}", "--findings", "{{be_cite_findings}}", "--findings", "{{be_api_findings}}", "--lane", "backend"]
|
|
824
1045
|
outputs:
|
|
825
1046
|
- { name: be_verdict, from: "$.verdict" }
|
|
826
1047
|
- id: stamp_frontend
|
|
@@ -829,7 +1050,7 @@ workflow:
|
|
|
829
1050
|
on_error: continue
|
|
830
1051
|
script: { ref: actions }
|
|
831
1052
|
subcommand: slice-gate-stamp
|
|
832
|
-
args: ["--cr-id", "{{cr_id}}", "--feature-dir", "{{feature_dir}}", "--tests-green", "{{fe_test_ok}}", "--tests-ran", "{{fe_test_ran}}", "--requirements-ok", "{{fe_req_vote}}", "--findings", "{{fe_gaps}}", "--lane", "frontend"]
|
|
1053
|
+
args: ["--cr-id", "{{cr_id}}", "--feature-dir", "{{feature_dir}}", "--tests-green", "{{fe_test_ok}}", "--tests-ran", "{{fe_test_ran}}", "--requirements-ok", "{{fe_req_vote}}", "--findings", "{{fe_gaps}}", "--findings", "{{fe_cite_findings}}", "--lane", "frontend"]
|
|
833
1054
|
outputs:
|
|
834
1055
|
- { name: fe_verdict, from: "$.verdict" }
|
|
835
1056
|
|
|
@@ -850,7 +1071,7 @@ workflow:
|
|
|
850
1071
|
- id: be_state_gated
|
|
851
1072
|
condition: "{{be_gated}} == true"
|
|
852
1073
|
action: set
|
|
853
|
-
vars: { be_state: "gated — tests green={{be_test_ok}} (tool `{{be_test_tool}}`, actually ran={{be_test_ran}}), requirements met={{be_req_vote}}, recorded `{{be_verdict}}` in .aw-slice-gate.backend.json" }
|
|
1074
|
+
vars: { be_state: "gated — tests green={{be_test_ok}} (tool `{{be_test_tool}}`, actually ran={{be_test_ran}}), requirements met={{be_req_vote}} (requirement ids no test names: {{be_uncited}}; the change's API as served: {{be_api_issues}}), recorded `{{be_verdict}}` in .aw-slice-gate.backend.json" }
|
|
854
1075
|
- id: fe_state_unnamed
|
|
855
1076
|
condition: "{{fe_declared}} == true"
|
|
856
1077
|
action: set
|
|
@@ -866,7 +1087,7 @@ workflow:
|
|
|
866
1087
|
- id: fe_state_gated
|
|
867
1088
|
condition: "{{fe_gated}} == true"
|
|
868
1089
|
action: set
|
|
869
|
-
vars: { fe_state: "gated — tests green={{fe_test_ok}} (tool `{{fe_test_tool}}`, actually ran={{fe_test_ran}}), requirements met={{fe_req_vote}}, recorded `{{fe_verdict}}` in .aw-slice-gate.frontend.json" }
|
|
1090
|
+
vars: { fe_state: "gated — tests green={{fe_test_ok}} (tool `{{fe_test_tool}}`, actually ran={{fe_test_ran}}), requirements met={{fe_req_vote}} (requirement ids no test names: {{fe_uncited}}), recorded `{{fe_verdict}}` in .aw-slice-gate.frontend.json" }
|
|
870
1091
|
|
|
871
1092
|
# THE REPORT IS ALWAYS WRITTEN — green or red. A green one is the record that this change
|
|
872
1093
|
# was verified built before it was merged, which is what makes the merge auditable; a red
|
|
@@ -903,10 +1124,14 @@ workflow:
|
|
|
903
1124
|
`{{working_lane}}`. Each gated lane ran its own tests and was checked on its own:
|
|
904
1125
|
- service lane: {{be_state}}. Matched a slice filter={{be_test_matched}},
|
|
905
1126
|
slice-scoped={{be_test_scoped}}. Failing lines: {{be_test_excerpt}} · Log tail:
|
|
906
|
-
{{be_test_log}} · gaps: {{be_gaps}}
|
|
1127
|
+
{{be_test_log}} · gaps: {{be_gaps}} · test-citation findings (by script — an FR- or
|
|
1128
|
+
BR- the delta plan serves that no test names): {{be_cite_findings}} · API findings
|
|
1129
|
+
(by script — an endpoint the change adds or changes that the service does not serve
|
|
1130
|
+
as its draft states, or one it removes that is still served): {{be_api_findings}}
|
|
907
1131
|
- experience lane: {{fe_state}}. Matched a slice filter={{fe_test_matched}},
|
|
908
1132
|
slice-scoped={{fe_test_scoped}}. Failing lines: {{fe_test_excerpt}} · Log tail:
|
|
909
|
-
{{fe_test_log}} · gaps: {{fe_gaps}}
|
|
1133
|
+
{{fe_test_log}} · gaps: {{fe_gaps}} · test-citation findings (by script):
|
|
1134
|
+
{{fe_cite_findings}}
|
|
910
1135
|
Markdown format:
|
|
911
1136
|
- "# Delta Slice Analyze Report — {{cr_id}}" plus today's date.
|
|
912
1137
|
- A verdict line: "verdict: REQUIREMENTS MET ✓" when every gated lane's tests are
|
|
@@ -921,7 +1146,7 @@ workflow:
|
|
|
921
1146
|
requirement findings below, not the fence, are what answer whether the change does
|
|
922
1147
|
what it was asked to.
|
|
923
1148
|
- "## Findings" as a table — | # | check | lane | severity | delta-spec ref | where |
|
|
924
|
-
finding | fixed by | — ordered high severity first, and within that the
|
|
1149
|
+
finding | fixed by | — the gaps, the test-citation findings AND the API findings, ordered high severity first, and within that the
|
|
925
1150
|
`requirement` check first, because an unrealised requirement is the finding this
|
|
926
1151
|
gate exists for. Omit the section entirely when there are none, and say so under
|
|
927
1152
|
the verdict.
|
|
@@ -933,8 +1158,10 @@ workflow:
|
|
|
933
1158
|
/appweaver plan {{cr_id}}, then analyze-plan-delta. `specify` — the delta spec or
|
|
934
1159
|
the model delta is what is missing (a requirement realised in code that nothing
|
|
935
1160
|
asked for lands here too, as does a plan-only change that moved behaviour); re-run
|
|
936
|
-
/appweaver specify, which is the only phase that authors either.
|
|
937
|
-
|
|
1161
|
+
/appweaver specify, which is the only phase that authors either.
|
|
1162
|
+
`fix-test-coverage` — a requirement no test names (the test-citation findings); run
|
|
1163
|
+
/appweaver fix-test-coverage {{cr_id}}, which writes the tests and never code. Then
|
|
1164
|
+
re-run /appweaver analyze-slice-delta {{cr_id}}.
|
|
938
1165
|
- Close with one line stating that this gate verifies only; it generated no code and
|
|
939
1166
|
repaired nothing.
|
|
940
1167
|
Return the complete report markdown only.
|
|
@@ -959,10 +1186,12 @@ workflow:
|
|
|
959
1186
|
|
|
960
1187
|
CODE ({{fix_code_n}}): {{fix_code}}
|
|
961
1188
|
|
|
1189
|
+
TESTS ({{fix_tests_n}}): {{fix_tests}}
|
|
1190
|
+
|
|
962
1191
|
UNROUTED ({{fix_review_n}}): {{fix_review}}
|
|
963
1192
|
|
|
964
1193
|
Work them in that order — the spec before the plan that realises it, the plan before
|
|
965
|
-
the code that maps to it. Re-running /appweaver plan {{cr_id}} re-derives the delta
|
|
1194
|
+
the code that maps to it, the code before its tests. Re-running /appweaver plan {{cr_id}} re-derives the delta
|
|
966
1195
|
plans with this report in context, so a plan finding is fixed by re-deriving rather
|
|
967
1196
|
than by hand-editing a generated document. The full report is at
|
|
968
1197
|
{{report_file}}. DO NOT run finalize-delta yet: merging now
|
|
@@ -999,6 +1228,7 @@ outputs:
|
|
|
999
1228
|
backend_ok: "{{be_ok}}"
|
|
1000
1229
|
backend_gaps: "{{be_gaps}}"
|
|
1001
1230
|
backend_verdict: "{{be_verdict}}" # as recorded in .aw-slice-gate.backend.json
|
|
1231
|
+
backend_untraced: "{{be_uncited}}" # FR-/BR- ids the backend delta plan serves that no test names
|
|
1002
1232
|
frontend_gated: "{{fe_gated}}"
|
|
1003
1233
|
frontend_state: "{{fe_state}}"
|
|
1004
1234
|
frontend_tests_green: "{{fe_test_ok}}"
|
|
@@ -1007,6 +1237,7 @@ outputs:
|
|
|
1007
1237
|
frontend_ok: "{{fe_ok}}"
|
|
1008
1238
|
frontend_gaps: "{{fe_gaps}}"
|
|
1009
1239
|
frontend_verdict: "{{fe_verdict}}" # as recorded in .aw-slice-gate.frontend.json
|
|
1240
|
+
frontend_untraced: "{{fe_uncited}}"
|
|
1010
1241
|
report: "{{report_file}}" # delta-slice-analyze-report.<lane>.md when one lane of two is worked
|
|
1011
1242
|
source_count: "{{source_count}}"
|
|
1012
1243
|
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 the change names, that you work on and that has a delta plan for THIS change is gated: backend — {{be_state}}; frontend — {{fe_state}}. An ungated lane is reported as not gated, never as a pass, and a lane somebody else works on is gated in their own run. Each gated lane ran its own tests, here for the first time on the change path since build only compiles, and its pass or fail is recorded in {{cr_dir}}/.aw-slice-gate.<lane>.json. This gate verifies: it generated no code and repaired nothing, and every finding names the command that closes it."
|