aw-spec-cli 0.1.20 → 0.1.21
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/ORCH-DIALECT.md +8 -3
- package/assets/.appweaver/orchestrator/modules/delta-spec.orch.yaml +22 -1
- package/assets/.appweaver/orchestrator/orchestrator.py +65 -3
- package/assets/.appweaver/orchestrator/workflows/aw-spec-analyze-plan-delta.orch.yaml +6 -6
- package/assets/.appweaver/orchestrator/workflows/aw-spec-analyze-plan.orch.yaml +107 -48
- package/assets/.appweaver/orchestrator/workflows/aw-spec-analyze-slice-delta.orch.yaml +17 -9
- package/assets/.appweaver/orchestrator/workflows/aw-spec-analyze-slice.orch.yaml +265 -20
- package/assets/.appweaver/orchestrator/workflows/aw-spec-constitution.orch.yaml +4 -4
- package/assets/.appweaver/orchestrator/workflows/aw-spec-finalize-delta.orch.yaml +89 -15
- package/assets/.appweaver/orchestrator/workflows/aw-spec-foundation.orch.yaml +140 -36
- package/assets/.appweaver/orchestrator/workflows/aw-spec-implement.orch.yaml +354 -52
- package/assets/.appweaver/orchestrator/workflows/aw-spec-onboard.orch.yaml +3 -3
- package/assets/.appweaver/orchestrator/workflows/aw-spec-select-stack.orch.yaml +47 -23
- package/assets/.appweaver/orchestrator/workflows/aw-spec-specify.orch.yaml +1 -1
- package/assets/.appweaver/scripts/bash/aw-spec-actions.sh +651 -76
- package/assets/.appweaver/scripts/powershell/aw-spec-actions.ps1 +600 -59
- package/assets/.appweaver/scripts/python/aw-crstate.py +194 -0
- package/assets/.appweaver/scripts/python/aw-foundation.py +151 -0
- package/assets/.appweaver/scripts/python/aw-payload-parity.py +3 -0
- package/assets/.appweaver/scripts/python/aw-plan-coverage.py +423 -0
- package/assets/.appweaver/scripts/python/aw-stack.py +251 -28
- package/assets/.appweaver/scripts/python/aw-testlog.py +148 -0
- package/assets/.appweaver/stack-profiles/dotnet-webapi.json +1 -0
- package/assets/.appweaver/stack-profiles/java-spring.json +1 -0
- package/assets/.appweaver/stack-profiles/node-express.json +1 -0
- package/assets/.appweaver/stack-profiles/python-fastapi.json +1 -0
- package/assets/.appweaver/templates/constitution-domain-template.md +17 -2
- package/assets/guardrails/projects/dotnet-default-project/domain-rule-bindings.md +10 -6
- package/assets/guardrails/projects/dotnet-default-project/tech-rule-bindings.md +4 -0
- package/assets/guardrails/technology/dotnet-webapi/auditing.md +3 -1
- package/assets/guardrails/technology/dotnet-webapi/coding-standards.md +5 -3
- package/assets/guardrails/technology/dotnet-webapi/cqrs.md +5 -1
- package/assets/guardrails/technology/dotnet-webapi/domain-driven-design.md +13 -5
- package/assets/guardrails/technology/dotnet-webapi/examples/cqrs.md +2 -0
- package/assets/guardrails/technology/dotnet-webapi/examples/domain-driven-design.md +6 -2
- package/assets/guardrails/technology/dotnet-webapi/framework-api-map.md +70 -0
- package/assets/guardrails/technology/dotnet-webapi/technology-constitution.md +3 -0
- package/assets/guardrails/technology/dotnet-webapi/testing.md +10 -0
- package/assets/guardrails/technology/nextjs/ui-constitution.md +8 -1
- package/package.json +1 -1
- package/assets/.appweaver/orchestrator/.state/smoke.state.json +0 -32
|
@@ -47,9 +47,10 @@
|
|
|
47
47
|
# about the order the operator ran things in: the lane gates test that the plan FILE EXISTS
|
|
48
48
|
# and nothing more, so `plan` → edit spec.md → `implement` generated at full length from a
|
|
49
49
|
# plan nobody had held against the spec it now contradicts. analyze-plan leaves a receipt of
|
|
50
|
-
# the bytes it
|
|
51
|
-
# lane generates. A feature with no receipt has simply never been gated
|
|
52
|
-
# existed — reported, never refused. One
|
|
50
|
+
# the bytes it checked and its verdict, and plan-gate-check reads it here, on the bootstrap
|
|
51
|
+
# path, before any lane generates. A feature with no receipt has simply never been gated
|
|
52
|
+
# since the receipt existed — reported, never refused. One whose receipt no longer matches,
|
|
53
|
+
# or whose verdict left plan gaps, stops; one whose verdict left only spec/model gaps warns.
|
|
53
54
|
# 3.2.0 — AND NOT delta-spec.md EITHER. The change path used to inline it "only so the
|
|
54
55
|
# paired tests can cite traceability ids", which made the rule true on the bootstrap path
|
|
55
56
|
# and false on the one where changes actually ship: a document in the payload is a document
|
|
@@ -86,11 +87,22 @@
|
|
|
86
87
|
# • FRONTEND — `## /aw-spec-implement-ui`, both paths. There was never a delta heading
|
|
87
88
|
# for this lane because the delta half of it was never built; it is built here.
|
|
88
89
|
#
|
|
89
|
-
#
|
|
90
|
-
#
|
|
91
|
-
#
|
|
92
|
-
#
|
|
93
|
-
#
|
|
90
|
+
# TWO PATHS PER LANE. Each lane owns the source path stacks.json declares for it and the
|
|
91
|
+
# test path lane-verify resolves beside it — `tests/` next to a .NET `src/`, the source
|
|
92
|
+
# path itself for a stack that keeps its tests inside — and writes nothing outside them.
|
|
93
|
+
# The one exception is registering a test project the lane had to create, in whatever
|
|
94
|
+
# file the lane's test command discovers tests through (a .NET solution file). A file
|
|
95
|
+
# written elsewhere belongs to the other lane or to no lane at all, and the project gate
|
|
96
|
+
# is deliberately stricter for the frontend: a manifest found only elsewhere in the
|
|
97
|
+
# repository is the service lane's, and accepting it is how a frontend that was never
|
|
98
|
+
# scaffolded is generated into anyway and reports green.
|
|
99
|
+
#
|
|
100
|
+
# A FILE LIST IS NOT A FINISHED LANE. Each generating lane is handed its plan's element
|
|
101
|
+
# list and reports every element back as done or blocked; `plan-coverage` then checks the
|
|
102
|
+
# code under the lane's source path for every identifier the plan introduces. Whatever
|
|
103
|
+
# either check leaves open gets one completion pass, and anything still open after it
|
|
104
|
+
# stops the run once both lanes have generated — so a pass that stopped at five use-cases
|
|
105
|
+
# of seven is reported, not shipped.
|
|
94
106
|
#
|
|
95
107
|
# A LANE'S GAP DISABLES THAT LANE, NOT THE RUN. Three things a lane needs are checked per
|
|
96
108
|
# lane and reported per lane: its source path is on disk, its plan is there, and a project
|
|
@@ -116,7 +128,7 @@
|
|
|
116
128
|
|
|
117
129
|
name: aw-spec-implement
|
|
118
130
|
description: "Generate the aggregate's source files and paired tests from its lane plans — the backend lane from backend-plan.md when a backend stack is declared, the frontend lane from frontend-plan.md when a frontend stack is, both when both are. One command covers backend-only, frontend-only and full-stack projects and absorbs the former implement-ui and implement-delta. Self-detecting off the changes on disk — with none open it generates from the master plans; with one or more open it ASKS which change and generates only what that change's delta plans mark ADDED or MODIFIED, leaving the masters untouched. Every lane is gated on its own source path, its own plan and its own scaffolded project, and a lane missing any of them is reported and skipped rather than failing the other lane; each runnable lane confirms before it writes. Model-driven, and it does not read the spec — analyze-plan already conformed the plans to it. The plan says WHAT to build; the bounded context's domain-model.md, in context alongside it, says what the domain IS — the entity names, the boundary and the text of every invariant the plan cites by id — joined on the delta path by that change's own model delta, since the master is not merged until finalize-delta. The stack binds here from the lane declaration and the constitution halves; the plans stay technology-agnostic."
|
|
119
|
-
version: 3.
|
|
131
|
+
version: 3.7.0
|
|
120
132
|
agent_agnostic: true
|
|
121
133
|
dialect: aw-spec.orchestrator/v1
|
|
122
134
|
|
|
@@ -162,19 +174,23 @@ vars:
|
|
|
162
174
|
delta_frontend_plan: ""
|
|
163
175
|
delta_frontend_plan_exists: "false"
|
|
164
176
|
wave: ""
|
|
165
|
-
# THE GATE RECEIPT — was this feature's plan pair
|
|
166
|
-
# anything moved since. analyze-plan writes it on
|
|
167
|
-
# reader. Bootstrap path only: a delta generates from delta plans, which
|
|
168
|
-
# gates, and the master receipt says nothing about those.
|
|
177
|
+
# THE GATE RECEIPT — was this feature's plan pair checked against this spec, with what
|
|
178
|
+
# verdict, and has anything moved since. analyze-plan writes it on every master run; this
|
|
179
|
+
# phase is the reader. Bootstrap path only: a delta generates from delta plans, which
|
|
180
|
+
# analyze-plan-delta gates, and the master receipt says nothing about those.
|
|
169
181
|
gate_tracked: "false"
|
|
170
182
|
gate_fresh: "false"
|
|
171
183
|
gate_reason: ""
|
|
172
184
|
gate_at: ""
|
|
185
|
+
gate_verdict: "" # conformant | routed-gaps | gaps — empty with no receipt
|
|
186
|
+
gate_routed_csv: "" # the gaps only /appweaver specify can close
|
|
187
|
+
gate_may_generate: "true"
|
|
188
|
+
gate_no_routed: "true" # lowered when the receipt's verdict is routed-gaps — a warning, not a stop
|
|
173
189
|
# DEFAULTED PERMISSIVE, DELIBERATELY, and it is the one flag here that is. Every tree that
|
|
174
190
|
# predates the receipt has none, and "never gated" is an unknown, not a stale plan —
|
|
175
191
|
# refusing on a missing file would block every existing feature on its first run. The flag
|
|
176
|
-
# is lowered only by a receipt that EXISTS and
|
|
177
|
-
#
|
|
192
|
+
# is lowered only by a receipt that EXISTS and refuses: the bytes moved since it was
|
|
193
|
+
# written, or its verdict left gaps a plan rewrite closes.
|
|
178
194
|
may_generate: "true"
|
|
179
195
|
# PER-LANE STATE. Each lane resolves its own plan, its own project and its own answer;
|
|
180
196
|
# a lane that is not declared never resolves any of them and its steps never run.
|
|
@@ -189,6 +205,15 @@ vars:
|
|
|
189
205
|
be_go: "false"
|
|
190
206
|
be_mode: "skip" # skip | bootstrap | delta
|
|
191
207
|
be_files: []
|
|
208
|
+
# COMPLETENESS, per lane — see step 8b and the checks after each lane generates.
|
|
209
|
+
be_element_names: ""
|
|
210
|
+
be_elements: []
|
|
211
|
+
be_more_files: []
|
|
212
|
+
be_elements_more: []
|
|
213
|
+
be_complete: "true"
|
|
214
|
+
be_completion_ran: "false"
|
|
215
|
+
be_gap_names: ""
|
|
216
|
+
be_gaps_text: "none"
|
|
192
217
|
fe_plan: ""
|
|
193
218
|
fe_plan_ok: "false"
|
|
194
219
|
fe_project_ok: "false"
|
|
@@ -198,6 +223,15 @@ vars:
|
|
|
198
223
|
fe_go: "false"
|
|
199
224
|
fe_mode: "skip" # skip | bootstrap | delta
|
|
200
225
|
fe_files: []
|
|
226
|
+
fe_element_names: ""
|
|
227
|
+
fe_elements: []
|
|
228
|
+
fe_more_files: []
|
|
229
|
+
fe_elements_more: []
|
|
230
|
+
fe_complete: "true"
|
|
231
|
+
fe_completion_ran: "false"
|
|
232
|
+
fe_gap_names: ""
|
|
233
|
+
fe_gaps_text: "none"
|
|
234
|
+
lanes_complete: "true"
|
|
201
235
|
generate_any: "false"
|
|
202
236
|
record_edges: "false"
|
|
203
237
|
overview_ok: "false"
|
|
@@ -245,6 +279,7 @@ workflow:
|
|
|
245
279
|
- { name: be_declared, from: "$.backend_declared" }
|
|
246
280
|
- { name: be_lane_id, from: "$.backend_lane_id" }
|
|
247
281
|
- { name: be_source_path, from: "$.backend_source_path" }
|
|
282
|
+
- { name: be_test_path, from: "$.backend_test_path" }
|
|
248
283
|
- { name: be_root_exists, from: "$.backend_root_exists" }
|
|
249
284
|
- { name: be_profile, from: "$.backend_profile" }
|
|
250
285
|
- { name: be_title, from: "$.backend_title" }
|
|
@@ -255,6 +290,7 @@ workflow:
|
|
|
255
290
|
- { name: fe_declared, from: "$.frontend_declared" }
|
|
256
291
|
- { name: fe_lane_id, from: "$.frontend_lane_id" }
|
|
257
292
|
- { name: fe_source_path, from: "$.frontend_source_path" }
|
|
293
|
+
- { name: fe_test_path, from: "$.frontend_test_path" }
|
|
258
294
|
- { name: fe_root_exists, from: "$.frontend_root_exists" }
|
|
259
295
|
- { name: fe_profile, from: "$.frontend_profile" }
|
|
260
296
|
- { name: fe_title, from: "$.frontend_title" }
|
|
@@ -425,11 +461,15 @@ workflow:
|
|
|
425
461
|
# spec.md, `implement` therefore generated from a plan that was never held against the
|
|
426
462
|
# spec it now contradicts, silently and at full length.
|
|
427
463
|
#
|
|
428
|
-
# plan-gate-check compares today's bytes against the receipt analyze-plan left
|
|
429
|
-
#
|
|
430
|
-
# own `**Version**:` headers cannot answer this and must not be
|
|
431
|
-
# them and spec.md to the same number in lockstep whether or not
|
|
432
|
-
# so the comparison reads equal always.
|
|
464
|
+
# plan-gate-check compares today's bytes against the receipt analyze-plan left — spec.md,
|
|
465
|
+
# the context's domain-model.md and each gated lane plan — and reads the verdict that
|
|
466
|
+
# run reached. The plans' own `**Version**:` headers cannot answer this and must not be
|
|
467
|
+
# used: close-delta stamps them and spec.md to the same number in lockstep whether or not
|
|
468
|
+
# a plan was re-derived, so the comparison reads equal always.
|
|
469
|
+
#
|
|
470
|
+
# THREE OUTCOMES FOR A RECEIPT. Moved bytes refuse. Verdict `gaps` refuses: that run left
|
|
471
|
+
# gaps a plan rewrite closes. Verdict `routed-gaps` generates and warns: what is left
|
|
472
|
+
# can only be closed in the spec or the model, and it is listed for /appweaver specify.
|
|
433
473
|
#
|
|
434
474
|
# BOOTSTRAP ONLY. A delta run generates from delta plans that analyze-plan-delta gates;
|
|
435
475
|
# the master receipt is silent about them, and reading it there would refuse a change
|
|
@@ -441,25 +481,41 @@ workflow:
|
|
|
441
481
|
subcommand: plan-gate-check
|
|
442
482
|
args: ["--feature-dir", "{{feature_dir}}"]
|
|
443
483
|
outputs:
|
|
444
|
-
- { name: gate_tracked,
|
|
445
|
-
- { name: gate_fresh,
|
|
446
|
-
- { name:
|
|
447
|
-
- { name:
|
|
484
|
+
- { name: gate_tracked, from: "$.tracked" }
|
|
485
|
+
- { name: gate_fresh, from: "$.gate_fresh" }
|
|
486
|
+
- { name: gate_verdict, from: "$.verdict" }
|
|
487
|
+
- { name: gate_may_generate, from: "$.may_generate" }
|
|
488
|
+
- { name: gate_routed_csv, from: "$.routed_csv" }
|
|
489
|
+
- { name: gate_reason, from: "$.reason" }
|
|
490
|
+
- { name: gate_at, from: "$.gated" }
|
|
448
491
|
|
|
449
492
|
# The ordered assignment is the AND: only a TRACKED feature can lower the flag, and
|
|
450
|
-
# what lowers it is
|
|
493
|
+
# what lowers it is plan-gate-check's may_generate. An untracked one never reaches
|
|
451
494
|
# this step's assignment and generates, which is the whole accommodation for trees
|
|
452
495
|
# that have not been gated since the receipt existed.
|
|
453
496
|
- id: flag_gate_block
|
|
454
497
|
condition: "{{gate_tracked}} == true"
|
|
455
498
|
action: set
|
|
456
|
-
vars: { may_generate: "{{
|
|
499
|
+
vars: { may_generate: "{{gate_may_generate}}" }
|
|
457
500
|
|
|
458
501
|
- id: require_gate_fresh
|
|
459
502
|
action: verify_context
|
|
460
503
|
require_true: may_generate
|
|
461
504
|
on_false: stop
|
|
462
|
-
on_false_message: "implement REFUSED —
|
|
505
|
+
on_false_message: "implement REFUSED — analyze-plan's receipt does not clear these plans: {{gate_reason}}. This phase generates from the plans and does NOT read the spec, on the strength of that gate having checked them against it, so generating now would realise a plan against requirements nobody held it to. Re-run /appweaver analyze-plan — it re-checks all four checks, repairs the drifting plan on approval, and re-issues the receipt — then re-run /appweaver implement. If what changed was a plan you re-derived with /appweaver plan main, that is the same path: the re-derived plans have not been gated yet. Nothing was generated."
|
|
506
|
+
|
|
507
|
+
# THE WARNING for a receipt whose only open gaps belong to specify. Generation goes on:
|
|
508
|
+
# no plan rewrite could close them, and the plan is what this phase builds from.
|
|
509
|
+
- id: flag_routed_gaps
|
|
510
|
+
condition: "{{gate_verdict}} == routed-gaps"
|
|
511
|
+
action: set
|
|
512
|
+
vars: { gate_no_routed: "false" }
|
|
513
|
+
|
|
514
|
+
- id: warn_routed_gaps
|
|
515
|
+
action: verify_context
|
|
516
|
+
require_true: gate_no_routed
|
|
517
|
+
on_false: continue
|
|
518
|
+
on_false_message: "WARNING — analyze-plan left gaps only the spec or the model can close, so the code generated now will not cover them: {{gate_routed_csv}}. Lift each into spec.md / domain-model.md by opening a change with /appweaver specify."
|
|
463
519
|
|
|
464
520
|
# 4. THE PROJECT each declared lane generates INTO. Deterministic structure gate:
|
|
465
521
|
# detect-project searches the LANE'S OWN subtree for an ecosystem manifest (.sln/
|
|
@@ -575,7 +631,7 @@ workflow:
|
|
|
575
631
|
- id: ask_backend
|
|
576
632
|
condition: "{{be_runnable}} == true"
|
|
577
633
|
action: ask
|
|
578
|
-
prompt: "Implement the BACKEND lane now? Lane `{{be_lane_id}}` — {{be_title}}, {{be_language}} ({{be_ecosystem}}) — generating from {{be_plan}} into {{be_source_path}}."
|
|
634
|
+
prompt: "Implement the BACKEND lane now? Lane `{{be_lane_id}}` — {{be_title}}, {{be_language}} ({{be_ecosystem}}) — generating from {{be_plan}} into {{be_source_path}}, tests into {{be_test_path}}."
|
|
579
635
|
options: ["yes", "no"]
|
|
580
636
|
answer_var: be_answer
|
|
581
637
|
- id: be_go_set
|
|
@@ -586,7 +642,7 @@ workflow:
|
|
|
586
642
|
- id: ask_frontend
|
|
587
643
|
condition: "{{fe_runnable}} == true"
|
|
588
644
|
action: ask
|
|
589
|
-
prompt: "Implement the FRONTEND lane now? Lane `{{fe_lane_id}}` — {{fe_title}}, {{fe_language}} ({{fe_ecosystem}}) — generating from {{fe_plan}} into {{fe_source_path}}."
|
|
645
|
+
prompt: "Implement the FRONTEND lane now? Lane `{{fe_lane_id}}` — {{fe_title}}, {{fe_language}} ({{fe_ecosystem}}) — generating from {{fe_plan}} into {{fe_source_path}}, tests into {{fe_test_path}}."
|
|
590
646
|
options: ["yes", "no"]
|
|
591
647
|
answer_var: fe_answer
|
|
592
648
|
- id: fe_go_set
|
|
@@ -616,6 +672,26 @@ workflow:
|
|
|
616
672
|
action: set
|
|
617
673
|
vars: { fe_mode: "{{mode}}" }
|
|
618
674
|
|
|
675
|
+
# 8b. EACH GENERATING LANE'S ELEMENT LIST, read off its plan by plan-coverage. The
|
|
676
|
+
# generation prompt carries it, and the model reports every name on it — so an
|
|
677
|
+
# element it did not get to is declared rather than silently absent.
|
|
678
|
+
- id: be_plan_elements
|
|
679
|
+
condition: "{{be_go}} == true"
|
|
680
|
+
action: execute_script
|
|
681
|
+
script: { ref: actions }
|
|
682
|
+
subcommand: plan-coverage
|
|
683
|
+
args: ["--plan", "{{be_plan}}", "--kind", "backend", "--mode", "{{be_mode}}", "--list-only"]
|
|
684
|
+
outputs:
|
|
685
|
+
- { name: be_element_names, from: "$.names_text" }
|
|
686
|
+
- id: fe_plan_elements
|
|
687
|
+
condition: "{{fe_go}} == true"
|
|
688
|
+
action: execute_script
|
|
689
|
+
script: { ref: actions }
|
|
690
|
+
subcommand: plan-coverage
|
|
691
|
+
args: ["--plan", "{{fe_plan}}", "--kind", "frontend", "--mode", "{{fe_mode}}", "--list-only"]
|
|
692
|
+
outputs:
|
|
693
|
+
- { name: fe_element_names, from: "$.names_text" }
|
|
694
|
+
|
|
619
695
|
# 9. Each generating lane's code-generation rule files → sticky standards (configuration,
|
|
620
696
|
# not hardcoded). Loaded only for a lane that is actually going to generate, and the
|
|
621
697
|
# backend's heading is keyed by mode (see the header). No blocking gate: an
|
|
@@ -698,15 +774,23 @@ workflow:
|
|
|
698
774
|
loaded standards describe a DIFFERENT stack than the one above, the lane wins on
|
|
699
775
|
language and layout — the standards' stack-specific mechanics do not apply, so
|
|
700
776
|
follow their INTENT and STOP to surface the mismatch in your summary.
|
|
701
|
-
- WRITE ONLY
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
777
|
+
- WRITE ONLY INTO THE LANE'S TWO PATHS, both resolved for the `{{be_lane_id}}` lane
|
|
778
|
+
from .appweaver/stacks.json: production code under `{{be_source_path}}`, paired
|
|
779
|
+
tests under `{{be_test_path}}` (the same directory when the stack keeps its tests
|
|
780
|
+
inside its source). Those subtrees are this lane's, and a file outside them belongs
|
|
781
|
+
to another lane or to no lane at all. NEVER write into the frontend lane's subtree,
|
|
782
|
+
not even to consume a contract. Do not create a parallel source tree because the
|
|
783
|
+
layout inside them is unfamiliar; if the plan needs a place they have no home for,
|
|
784
|
+
STOP and surface it.
|
|
785
|
+
- A MISSING TEST PROJECT IS CREATED, NEVER A REASON TO SKIP THE TESTS. When
|
|
786
|
+
`{{be_test_path}}` holds no test project yet, create one there as the loaded
|
|
787
|
+
testing standard describes, referencing the production project it tests, and
|
|
788
|
+
register it wherever `{{be_test}}` discovers tests (for .NET, the solution file).
|
|
789
|
+
That registration is the ONLY edit allowed outside the lane's two paths; name the
|
|
790
|
+
file you edited in your summary.
|
|
707
791
|
- Follow the project's folder/layer convention + the loaded coding-standards,
|
|
708
792
|
dependency-policy and testing standards for HOW to structure, name and place files
|
|
709
|
-
WITHIN
|
|
793
|
+
WITHIN those subtrees — the plan says WHAT to build; these standards (identical for
|
|
710
794
|
every feature) say HOW.
|
|
711
795
|
- COMPONENTS: when the plan's External Integrations table depends on a framework
|
|
712
796
|
component (e.g. `IEmailService`, `IJobScheduler`), code against that component's
|
|
@@ -727,6 +811,12 @@ workflow:
|
|
|
727
811
|
CN / DC / IC / US) from its Traceability section. Include tests for the constraints
|
|
728
812
|
— e.g. an audit record is emitted, a DC-restricted field is NOT exposed on the
|
|
729
813
|
public surface, an IC- projection round-trips.
|
|
814
|
+
- WIRE WHAT YOU BUILD, in this same pass. Every port, adapter, handler and endpoint
|
|
815
|
+
the plan introduces is registered in the lane's composition root as the plan's §4.3
|
|
816
|
+
Wiring states. A dependency that is injected and never bound COMPILES GREEN — a
|
|
817
|
+
container graph is not compile-checked — and fails on the first request that needs
|
|
818
|
+
it. Where the project registers by assembly scan or convention, confirm the new
|
|
819
|
+
type is actually covered by it rather than assuming it is.
|
|
730
820
|
- Do NOT add behaviour the plan does not state, and do NOT omit any it does. If the
|
|
731
821
|
plan looks wrong or incomplete, STOP and surface it (it is fixed in plan /
|
|
732
822
|
analyze-plan) — never compensate from the spec or from memory.
|
|
@@ -740,8 +830,16 @@ workflow:
|
|
|
740
830
|
one changed, STOP and surface it.
|
|
741
831
|
- Where generated code depends on a plan Assumption (DA-n) or Workaround (WA-n), mark
|
|
742
832
|
it with a comment citing that id so it is easy to revisit later.
|
|
833
|
+
- REPORT EVERY PLAN ELEMENT. The plan's elements, by name: {{be_element_names}}.
|
|
834
|
+
Add an `elements` list to your closing JSON block with one entry per name, spelled
|
|
835
|
+
exactly as listed: {"element": "<name>", "status": "done" | "blocked", "reason":
|
|
836
|
+
"<what stops it, when blocked>"}. `done` means it is realised in code now,
|
|
837
|
+
including one that already existed; `blocked` means you could not realise it. An
|
|
838
|
+
element missing from the list counts as not done, and the code is checked for
|
|
839
|
+
each name after this step.
|
|
743
840
|
outputs:
|
|
744
841
|
- { name: be_files, from: "$.files" }
|
|
842
|
+
- { name: be_elements, from: "$.elements" }
|
|
745
843
|
|
|
746
844
|
# ═══════════ BACKEND LANE — delta, generate ONLY what the change adds ════════
|
|
747
845
|
# The delta plan is the authoritative source of WHAT changed — analyze-plan-delta already
|
|
@@ -816,12 +914,18 @@ workflow:
|
|
|
816
914
|
loaded standards describe a DIFFERENT stack than the one above, the lane wins on
|
|
817
915
|
language and layout — follow the standards' INTENT and STOP to surface the
|
|
818
916
|
mismatch in your summary.
|
|
819
|
-
- WRITE ONLY
|
|
820
|
-
|
|
821
|
-
lane or to no lane at all. NEVER write into the
|
|
917
|
+
- WRITE ONLY INTO THE LANE'S TWO PATHS: production code under `{{be_source_path}}`,
|
|
918
|
+
paired tests under `{{be_test_path}}`. Those subtrees are this lane's, and a file
|
|
919
|
+
outside them belongs to another lane or to no lane at all. NEVER write into the
|
|
920
|
+
frontend lane's subtree.
|
|
921
|
+
- A MISSING TEST PROJECT IS CREATED, NEVER A REASON TO SKIP THE TESTS. When
|
|
922
|
+
`{{be_test_path}}` holds no test project yet, create one there as the loaded
|
|
923
|
+
testing standard describes and register it wherever `{{be_test}}` discovers tests
|
|
924
|
+
(for .NET, the solution file) — the ONLY edit allowed outside the lane's two paths;
|
|
925
|
+
name the file you edited in your summary.
|
|
822
926
|
- Follow the project's EXISTING folder/layer convention + the loaded
|
|
823
927
|
coding-standards, dependency-policy and testing standards for HOW to structure,
|
|
824
|
-
name and place files WITHIN
|
|
928
|
+
name and place files WITHIN those subtrees. Match the surrounding code already there.
|
|
825
929
|
- Realise EVERY ADDED/MODIFIED delta element as code: one file per Domain type /
|
|
826
930
|
Application use-case / API endpoint / Infrastructure adapter, placed by layer.
|
|
827
931
|
Preserve the ubiquitous-language names verbatim. Enforce each new/changed Domain
|
|
@@ -838,13 +942,24 @@ workflow:
|
|
|
838
942
|
The spec is not in context: take the id from the plan and cite it verbatim, never
|
|
839
943
|
guess one from the element's shape. A delta-plan element that names no id is a
|
|
840
944
|
planning gap — surface it rather than inventing the traceability.
|
|
945
|
+
- WIRE WHAT YOU BUILD, in this same pass: every port, adapter, handler and endpoint
|
|
946
|
+
this change introduces is registered in the lane's composition root, as the delta
|
|
947
|
+
plan states. A dependency injected and never bound compiles green and fails on the
|
|
948
|
+
first request; where registration is by assembly scan, confirm the new type is
|
|
949
|
+
covered by it.
|
|
841
950
|
- REGRESSION: for each element in the delta plan's "Regression targets", verify (add
|
|
842
951
|
or adjust a test where needed) that the existing behaviour still holds after a
|
|
843
952
|
shared element changed — but do NOT rewrite that existing behaviour.
|
|
844
953
|
- Where generated code depends on a delta Assumption (DA-n) or Workaround (WA-n),
|
|
845
954
|
mark it with a comment citing that id.
|
|
955
|
+
- REPORT EVERY DELTA ELEMENT. The delta plan's ADDED and MODIFIED elements, by name:
|
|
956
|
+
{{be_element_names}}. Add an `elements` list to your closing JSON block with one
|
|
957
|
+
entry per name, spelled exactly as listed: {"element": "<name>", "status": "done"
|
|
958
|
+
| "blocked", "reason": "<what stops it, when blocked>"}. An element missing from
|
|
959
|
+
the list counts as not done, and the code is checked for each name after this step.
|
|
846
960
|
outputs:
|
|
847
961
|
- { name: be_files, from: "$.files" }
|
|
962
|
+
- { name: be_elements, from: "$.elements" }
|
|
848
963
|
|
|
849
964
|
- id: verify_be_files
|
|
850
965
|
condition: "{{be_go}} == true"
|
|
@@ -853,6 +968,66 @@ workflow:
|
|
|
853
968
|
on_empty: stop
|
|
854
969
|
on_empty_message: "The backend lane generated no files. Ensure {{be_plan}} is a FILLED plan (not the empty template) and that it passed its gate — /appweaver analyze-plan for a master, /appweaver analyze-plan-delta for a change — then re-run implement."
|
|
855
970
|
|
|
971
|
+
# PARTIAL GENERATION. A non-empty file list is not a finished lane: a pass that stopped
|
|
972
|
+
# part-way returns the files it did write. plan-coverage checks every plan element two
|
|
973
|
+
# ways — the lane's code must name each identifier the plan introduces, and the model's
|
|
974
|
+
# own report must say each element is done — and whatever fails either check gets ONE
|
|
975
|
+
# completion pass in the same envelope. What is still missing after it stops the run at
|
|
976
|
+
# step 10b, once both lanes have had their turn.
|
|
977
|
+
- id: be_coverage
|
|
978
|
+
condition: "{{be_go}} == true"
|
|
979
|
+
action: execute_script
|
|
980
|
+
script: { ref: actions }
|
|
981
|
+
subcommand: plan-coverage
|
|
982
|
+
args: ["--plan", "{{be_plan}}", "--kind", "backend", "--mode", "{{be_mode}}", "--source-path", "{{be_source_path}}", "--test-path", "{{be_test_path}}", "--reported", "{{be_elements}}"]
|
|
983
|
+
outputs:
|
|
984
|
+
- { name: be_complete, from: "$.ok" }
|
|
985
|
+
- { name: be_gap_names, from: "$.gap_names_csv" }
|
|
986
|
+
- { name: be_gaps_text, from: "$.gaps_text" }
|
|
987
|
+
- id: be_completion_flag
|
|
988
|
+
condition: "{{be_complete}} == false"
|
|
989
|
+
action: set
|
|
990
|
+
vars: { be_completion_ran: "true" }
|
|
991
|
+
- id: gen_backend_complete
|
|
992
|
+
condition: "{{be_completion_ran}} == true"
|
|
993
|
+
action: agent_generate
|
|
994
|
+
tools: "Read,Write,Edit"
|
|
995
|
+
permission_mode: acceptEdits
|
|
996
|
+
task: |
|
|
997
|
+
COMPLETE the backend lane. The generation pass before this one left these plan
|
|
998
|
+
elements unrealised: {{be_gap_names}}.
|
|
999
|
+
Why each was flagged: {{be_gaps_text}}.
|
|
1000
|
+
The same plan, domain model and constitution are in context, and every rule of that
|
|
1001
|
+
pass still holds: realise each element STRICTLY as the plan states it; production
|
|
1002
|
+
code only under `{{be_source_path}}` and paired tests only under `{{be_test_path}}`;
|
|
1003
|
+
the `{{be_lane_id}}` lane's stack ({{be_title}}, {{be_language}}) and no other;
|
|
1004
|
+
shared aggregate files EXTENDED, never regenerated; nothing the plan does not state.
|
|
1005
|
+
Rules:
|
|
1006
|
+
- Realise each listed element now, with its paired test citing the spec id the plan
|
|
1007
|
+
gives it. Leave what the earlier pass wrote as it is, except to extend a shared file.
|
|
1008
|
+
- Use the plan's name for each element EXACTLY. An element that already exists
|
|
1009
|
+
under a different name is renamed to the plan's name, with its references — the
|
|
1010
|
+
plan's names are the ubiquitous language.
|
|
1011
|
+
- An element the plan names by intent (a port, an adapter, an endpoint route) is done
|
|
1012
|
+
when the code realises it, whatever the framework calls it; report it `done`.
|
|
1013
|
+
- If an element cannot be realised, do not work around it: report it `blocked` and
|
|
1014
|
+
say what stops you. A plan that is wrong is fixed in plan / analyze-plan.
|
|
1015
|
+
- Report every listed element in an `elements` list in your closing JSON block:
|
|
1016
|
+
{"element": "<name as listed>", "status": "done" | "blocked", "reason": "…"}.
|
|
1017
|
+
outputs:
|
|
1018
|
+
- { name: be_more_files, from: "$.files" }
|
|
1019
|
+
- { name: be_elements_more, from: "$.elements" }
|
|
1020
|
+
- id: be_coverage_recheck
|
|
1021
|
+
condition: "{{be_completion_ran}} == true"
|
|
1022
|
+
action: execute_script
|
|
1023
|
+
script: { ref: actions }
|
|
1024
|
+
subcommand: plan-coverage
|
|
1025
|
+
args: ["--plan", "{{be_plan}}", "--kind", "backend", "--mode", "{{be_mode}}", "--source-path", "{{be_source_path}}", "--test-path", "{{be_test_path}}", "--reported", "{{be_elements}}", "--reported", "{{be_elements_more}}"]
|
|
1026
|
+
outputs:
|
|
1027
|
+
- { name: be_complete, from: "$.ok" }
|
|
1028
|
+
- { name: be_gap_names, from: "$.gap_names_csv" }
|
|
1029
|
+
- { name: be_gaps_text, from: "$.gaps_text" }
|
|
1030
|
+
|
|
856
1031
|
# OKF knowledge — the feature has ONE concept across both lanes and both modes, so every
|
|
857
1032
|
# lane's files JOIN it rather than replace it (--merge unions them with what is already
|
|
858
1033
|
# recorded). Without the union a backend run would erase the frontend lane's source_files
|
|
@@ -868,6 +1043,15 @@ workflow:
|
|
|
868
1043
|
args: ["--feature-dir", "{{feature_dir}}", "--source-files", "{{be_files}}", "--merge", "--origin", "greenfield"]
|
|
869
1044
|
outputs:
|
|
870
1045
|
- { name: okf_concept, from: "$.concept" }
|
|
1046
|
+
- id: xref_concept_backend_more
|
|
1047
|
+
condition: "{{be_completion_ran}} == true"
|
|
1048
|
+
action: execute_script
|
|
1049
|
+
on_error: continue
|
|
1050
|
+
script: { ref: xref }
|
|
1051
|
+
subcommand: concept-upsert
|
|
1052
|
+
args: ["--feature-dir", "{{feature_dir}}", "--source-files", "{{be_more_files}}", "--merge", "--origin", "greenfield"]
|
|
1053
|
+
outputs:
|
|
1054
|
+
- { name: okf_concept, from: "$.concept" }
|
|
871
1055
|
|
|
872
1056
|
# ══════════════ THE LANE SWAP — the frontend's rules replace the backend's ═══
|
|
873
1057
|
# build_context already scoped the two lanes' PAYLOADS apart; this is the same boundary
|
|
@@ -932,16 +1116,22 @@ workflow:
|
|
|
932
1116
|
re-decide anything already fixed there. If the loaded standards describe a
|
|
933
1117
|
DIFFERENT stack than the one above, the lane wins on framework and layout — follow
|
|
934
1118
|
the standards' INTENT and STOP to surface the mismatch in your summary.
|
|
935
|
-
- WRITE ONLY
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
lane.
|
|
940
|
-
|
|
941
|
-
|
|
1119
|
+
- WRITE ONLY INTO THE LANE'S TWO PATHS, both resolved for the `{{fe_lane_id}}` lane:
|
|
1120
|
+
production code under `{{fe_source_path}}`, paired tests under `{{fe_test_path}}`
|
|
1121
|
+
(the same directory when the stack keeps its tests inside its source). Those
|
|
1122
|
+
subtrees are this lane's; a file outside them belongs to the service lane or to no
|
|
1123
|
+
lane. NEVER touch the service lane's code, not even to add a field the UI wants: a
|
|
1124
|
+
gap in the service surface is a contract delta raised back to that lane. Do not
|
|
1125
|
+
create a parallel source tree because the layout inside this one is unfamiliar; if
|
|
1126
|
+
the plan needs a place this subtree has no home for, STOP and surface it.
|
|
1127
|
+
- A MISSING TEST SETUP IS CREATED, NEVER A REASON TO SKIP THE TESTS. When the lane
|
|
1128
|
+
has no test project or test runner yet, set one up inside the lane's paths as the
|
|
1129
|
+
loaded testing standard describes, so that `{{fe_test}}` runs the tests you write.
|
|
1130
|
+
Anything outside the lane's two paths that must change for that is the ONLY such
|
|
1131
|
+
edit allowed; name the file you edited in your summary.
|
|
942
1132
|
- Follow the UI constitution's folder structure, naming conventions and forbidden
|
|
943
1133
|
patterns, plus the loaded standards, for HOW to structure, name and place files
|
|
944
|
-
WITHIN
|
|
1134
|
+
WITHIN those subtrees — the plan says WHAT to build; these say HOW.
|
|
945
1135
|
- REALISE EVERY PLAN ELEMENT, changing nothing about WHAT it specifies:
|
|
946
1136
|
• §1 — one route/screen per row, with the navigation shape and the access
|
|
947
1137
|
conditions the row states.
|
|
@@ -974,8 +1164,16 @@ workflow:
|
|
|
974
1164
|
feature. If one of them has to change, STOP and surface it.
|
|
975
1165
|
- Where generated code depends on a plan Assumption (DA-n) or Workaround (WA-n), mark
|
|
976
1166
|
it with a comment citing that id so it is easy to revisit later.
|
|
1167
|
+
- REPORT EVERY PLAN ELEMENT. The plan's elements, by name: {{fe_element_names}}.
|
|
1168
|
+
Add an `elements` list to your closing JSON block with one entry per name, spelled
|
|
1169
|
+
exactly as listed: {"element": "<name>", "status": "done" | "blocked", "reason":
|
|
1170
|
+
"<what stops it, when blocked>"}. `done` means it is realised in code now,
|
|
1171
|
+
including one that already existed; `blocked` means you could not realise it. An
|
|
1172
|
+
element missing from the list counts as not done, and the code is checked for
|
|
1173
|
+
each name after this step.
|
|
977
1174
|
outputs:
|
|
978
1175
|
- { name: fe_files, from: "$.files" }
|
|
1176
|
+
- { name: fe_elements, from: "$.elements" }
|
|
979
1177
|
|
|
980
1178
|
# ═══════════ FRONTEND LANE — delta, generate ONLY what the change adds ═══════
|
|
981
1179
|
# The UI half of the CR loop, which never existed as its own command: the ⌛
|
|
@@ -1031,9 +1229,13 @@ workflow:
|
|
|
1031
1229
|
`{{fe_test}}`. Generate in THAT framework and no other. Take the router, state
|
|
1032
1230
|
approach, component library, design system and styling from the UI constitution +
|
|
1033
1231
|
the loaded standards, and MATCH the code already in the tree.
|
|
1034
|
-
- WRITE ONLY
|
|
1232
|
+
- WRITE ONLY INTO THE LANE'S TWO PATHS: production code under `{{fe_source_path}}`,
|
|
1233
|
+
paired tests under `{{fe_test_path}}`. NEVER touch the service lane's code, not
|
|
1035
1234
|
even to add a field the UI wants — a gap in the service surface is a contract delta
|
|
1036
1235
|
raised back to that lane, never worked around in the client.
|
|
1236
|
+
- A MISSING TEST SETUP IS CREATED, NEVER A REASON TO SKIP THE TESTS: set one up
|
|
1237
|
+
inside the lane's paths so that `{{fe_test}}` runs the tests you write, and name
|
|
1238
|
+
any file outside them you had to edit for that in your summary.
|
|
1037
1239
|
- STATES ARE PART OF THE CHANGE. Every interaction this delta adds or alters ships
|
|
1038
1240
|
its FULL state set — loading, empty, error, permission-denied, in-flight — plus the
|
|
1039
1241
|
validation timing, focus placement and keyboard reachability the delta plan states.
|
|
@@ -1055,8 +1257,14 @@ workflow:
|
|
|
1055
1257
|
feature. If one of them has to change, STOP and surface it.
|
|
1056
1258
|
- Where generated code depends on a delta Assumption (DA-n) or Workaround (WA-n),
|
|
1057
1259
|
mark it with a comment citing that id.
|
|
1260
|
+
- REPORT EVERY DELTA ELEMENT. The delta plan's ADDED and MODIFIED elements, by name:
|
|
1261
|
+
{{fe_element_names}}. Add an `elements` list to your closing JSON block with one
|
|
1262
|
+
entry per name, spelled exactly as listed: {"element": "<name>", "status": "done"
|
|
1263
|
+
| "blocked", "reason": "<what stops it, when blocked>"}. An element missing from
|
|
1264
|
+
the list counts as not done, and the code is checked for each name after this step.
|
|
1058
1265
|
outputs:
|
|
1059
1266
|
- { name: fe_files, from: "$.files" }
|
|
1267
|
+
- { name: fe_elements, from: "$.elements" }
|
|
1060
1268
|
|
|
1061
1269
|
- id: verify_fe_files
|
|
1062
1270
|
condition: "{{fe_go}} == true"
|
|
@@ -1065,6 +1273,62 @@ workflow:
|
|
|
1065
1273
|
on_empty: stop
|
|
1066
1274
|
on_empty_message: "The frontend lane generated no files. Ensure {{fe_plan}} is a FILLED plan (not the empty template) and that it passed its gate — /appweaver analyze-plan for a master, /appweaver analyze-plan-delta for a change — then re-run implement."
|
|
1067
1275
|
|
|
1276
|
+
# PARTIAL GENERATION — the frontend twin of the backend check above.
|
|
1277
|
+
- id: fe_coverage
|
|
1278
|
+
condition: "{{fe_go}} == true"
|
|
1279
|
+
action: execute_script
|
|
1280
|
+
script: { ref: actions }
|
|
1281
|
+
subcommand: plan-coverage
|
|
1282
|
+
args: ["--plan", "{{fe_plan}}", "--kind", "frontend", "--mode", "{{fe_mode}}", "--source-path", "{{fe_source_path}}", "--test-path", "{{fe_test_path}}", "--reported", "{{fe_elements}}"]
|
|
1283
|
+
outputs:
|
|
1284
|
+
- { name: fe_complete, from: "$.ok" }
|
|
1285
|
+
- { name: fe_gap_names, from: "$.gap_names_csv" }
|
|
1286
|
+
- { name: fe_gaps_text, from: "$.gaps_text" }
|
|
1287
|
+
- id: fe_completion_flag
|
|
1288
|
+
condition: "{{fe_complete}} == false"
|
|
1289
|
+
action: set
|
|
1290
|
+
vars: { fe_completion_ran: "true" }
|
|
1291
|
+
- id: gen_frontend_complete
|
|
1292
|
+
condition: "{{fe_completion_ran}} == true"
|
|
1293
|
+
action: agent_generate
|
|
1294
|
+
tools: "Read,Write,Edit"
|
|
1295
|
+
permission_mode: acceptEdits
|
|
1296
|
+
task: |
|
|
1297
|
+
COMPLETE the frontend lane. The generation pass before this one left these plan
|
|
1298
|
+
elements unrealised: {{fe_gap_names}}.
|
|
1299
|
+
Why each was flagged: {{fe_gaps_text}}.
|
|
1300
|
+
The same plan, domain model and UI constitution are in context, and every rule of
|
|
1301
|
+
that pass still holds: realise each element STRICTLY as the plan states it, with its
|
|
1302
|
+
FULL state set; production code only under `{{fe_source_path}}` and paired tests
|
|
1303
|
+
only under `{{fe_test_path}}`; the `{{fe_lane_id}}` lane's stack ({{fe_title}},
|
|
1304
|
+
{{fe_language}}) and no other; never the service lane's code, the app shell, the
|
|
1305
|
+
global layout or the design system; nothing the plan does not state.
|
|
1306
|
+
Rules:
|
|
1307
|
+
- Realise each listed element now, with its paired test citing the spec id the plan
|
|
1308
|
+
gives it. Leave what the earlier pass wrote as it is.
|
|
1309
|
+
- Use the plan's name for each element EXACTLY. An element that already exists
|
|
1310
|
+
under a different name is renamed to the plan's name, with its references — the
|
|
1311
|
+
plan's names are the ubiquitous language.
|
|
1312
|
+
- A screen or a binding is done when the code realises it, whatever its route or
|
|
1313
|
+
file is called; report it `done`.
|
|
1314
|
+
- If an element cannot be realised, do not work around it: report it `blocked` and
|
|
1315
|
+
say what stops you. A plan that is wrong is fixed in plan / analyze-plan.
|
|
1316
|
+
- Report every listed element in an `elements` list in your closing JSON block:
|
|
1317
|
+
{"element": "<name as listed>", "status": "done" | "blocked", "reason": "…"}.
|
|
1318
|
+
outputs:
|
|
1319
|
+
- { name: fe_more_files, from: "$.files" }
|
|
1320
|
+
- { name: fe_elements_more, from: "$.elements" }
|
|
1321
|
+
- id: fe_coverage_recheck
|
|
1322
|
+
condition: "{{fe_completion_ran}} == true"
|
|
1323
|
+
action: execute_script
|
|
1324
|
+
script: { ref: actions }
|
|
1325
|
+
subcommand: plan-coverage
|
|
1326
|
+
args: ["--plan", "{{fe_plan}}", "--kind", "frontend", "--mode", "{{fe_mode}}", "--source-path", "{{fe_source_path}}", "--test-path", "{{fe_test_path}}", "--reported", "{{fe_elements}}", "--reported", "{{fe_elements_more}}"]
|
|
1327
|
+
outputs:
|
|
1328
|
+
- { name: fe_complete, from: "$.ok" }
|
|
1329
|
+
- { name: fe_gap_names, from: "$.gap_names_csv" }
|
|
1330
|
+
- { name: fe_gaps_text, from: "$.gaps_text" }
|
|
1331
|
+
|
|
1068
1332
|
- id: xref_concept_frontend
|
|
1069
1333
|
condition: "{{fe_go}} == true"
|
|
1070
1334
|
action: execute_script
|
|
@@ -1074,6 +1338,34 @@ workflow:
|
|
|
1074
1338
|
args: ["--feature-dir", "{{feature_dir}}", "--source-files", "{{fe_files}}", "--merge", "--origin", "greenfield"]
|
|
1075
1339
|
outputs:
|
|
1076
1340
|
- { name: okf_concept, from: "$.concept" }
|
|
1341
|
+
- id: xref_concept_frontend_more
|
|
1342
|
+
condition: "{{fe_completion_ran}} == true"
|
|
1343
|
+
action: execute_script
|
|
1344
|
+
on_error: continue
|
|
1345
|
+
script: { ref: xref }
|
|
1346
|
+
subcommand: concept-upsert
|
|
1347
|
+
args: ["--feature-dir", "{{feature_dir}}", "--source-files", "{{fe_more_files}}", "--merge", "--origin", "greenfield"]
|
|
1348
|
+
outputs:
|
|
1349
|
+
- { name: okf_concept, from: "$.concept" }
|
|
1350
|
+
|
|
1351
|
+
# 10b. A LANE LEFT INCOMPLETE STOPS THE RUN — after both lanes have generated and every
|
|
1352
|
+
# file written is recorded in the OKF concept, and before the edges, the Overview
|
|
1353
|
+
# and the after-hooks, which all assume a finished slice. Re-running implement
|
|
1354
|
+
# finishes the job: shared files are extended, and a file that exists is not
|
|
1355
|
+
# regenerated.
|
|
1356
|
+
- id: lanes_incomplete_be
|
|
1357
|
+
condition: "{{be_complete}} == false"
|
|
1358
|
+
action: set
|
|
1359
|
+
vars: { lanes_complete: "false" }
|
|
1360
|
+
- id: lanes_incomplete_fe
|
|
1361
|
+
condition: "{{fe_complete}} == false"
|
|
1362
|
+
action: set
|
|
1363
|
+
vars: { lanes_complete: "false" }
|
|
1364
|
+
- id: require_complete_lanes
|
|
1365
|
+
action: verify_context
|
|
1366
|
+
require_true: lanes_complete
|
|
1367
|
+
on_false: stop
|
|
1368
|
+
on_false_message: "PARTIAL GENERATION — implement did not realise every plan element, even after one completion pass. Backend lane: {{be_gaps_text}}. Frontend lane: {{fe_gaps_text}}. Everything written so far is kept and recorded in the OKF concept. An element reported `blocked` names what stops it — a plan that is wrong is fixed with /appweaver plan (then analyze-plan or analyze-plan-delta). An element with no code under the lane's source path is still to be written, or was written under a name that is not the plan's: re-run /appweaver implement to finish, which extends existing files rather than regenerating them."
|
|
1077
1369
|
|
|
1078
1370
|
# 11. CROSS-SLICE EDGES — a Cross-References row written into every SIBLING aggregate
|
|
1079
1371
|
# this one uses, read off the master backend plan (§1 References-by-id + its External
|
|
@@ -1181,15 +1473,25 @@ outputs:
|
|
|
1181
1473
|
frontend_implemented: "{{fe_go}}"
|
|
1182
1474
|
frontend_plan: "{{fe_plan}}" # the document the frontend lane generated FROM
|
|
1183
1475
|
frontend_files: "{{fe_files}}"
|
|
1476
|
+
# Every plan element realised, per lane — `true` for a lane that did not generate.
|
|
1477
|
+
# `*_completion_pass` says whether the first pass left gaps a second one had to close.
|
|
1478
|
+
backend_complete: "{{be_complete}}"
|
|
1479
|
+
backend_completion_pass: "{{be_completion_ran}}"
|
|
1480
|
+
backend_more_files: "{{be_more_files}}"
|
|
1481
|
+
frontend_complete: "{{fe_complete}}"
|
|
1482
|
+
frontend_completion_pass: "{{fe_completion_ran}}"
|
|
1483
|
+
frontend_more_files: "{{fe_more_files}}"
|
|
1184
1484
|
domain_model: "{{domain_model}}" # the master model every generating lane read
|
|
1185
1485
|
delta_model: "{{delta_model}}" # its second half on the delta path — empty on the bootstrap path
|
|
1186
1486
|
okf_concept: "{{okf_concept}}"
|
|
1187
1487
|
xref_edge_count: "{{xref_edge_count}}"
|
|
1188
|
-
# Bootstrap path only. tracked=false means this feature has
|
|
1189
|
-
# since the gate began leaving a receipt — an unknown, not a stale plan,
|
|
1190
|
-
# nothing.
|
|
1488
|
+
# Bootstrap path only. tracked=false means this feature has not been through a master
|
|
1489
|
+
# analyze-plan run since the gate began leaving a receipt — an unknown, not a stale plan,
|
|
1490
|
+
# and it blocks nothing.
|
|
1191
1491
|
plan_gate_tracked: "{{gate_tracked}}"
|
|
1192
1492
|
plan_gate_fresh: "{{gate_fresh}}"
|
|
1193
1493
|
plan_gate_at: "{{gate_at}}"
|
|
1494
|
+
plan_gate_verdict: "{{gate_verdict}}"
|
|
1495
|
+
plan_gate_routed_to_specify: "{{gate_routed_csv}}" # open spec/model gaps this code does not cover
|
|
1194
1496
|
note: "Lanes come from .appweaver/stacks.json — backend declared {{be_declared}} (ready {{be_runnable}}, implemented {{be_go}}), frontend declared {{fe_declared}} (ready {{fe_runnable}}, implemented {{fe_go}}). A declared lane that was skipped printed its reason above and did not stop the other one; an undeclared lane produces nothing and that is not a failure. Each generating lane read its PLAN for what to build and {{domain_model}} for what the domain is — plus {{delta_model}} on the delta path, since the master model does not carry the change until finalize-delta merges it. Every one of those documents was READ and none was written: this phase generates code and nothing else. On the bootstrap path the plans were checked against analyze-plan's receipt before anything generated (tracked={{gate_tracked}}, fresh={{gate_fresh}}, gated {{gate_at}}) — tracked=false means this feature has never passed analyze-plan since the gate began recording what it proved, which is an unknown rather than a stale plan and blocks nothing; run /appweaver analyze-plan once to start the record."
|
|
1195
1497
|
next: "This run was mode `{{mode}}`, change `{{active_change}}` (empty on the bootstrap path). BOOTSTRAP → /appweaver build → analyze-slice → run. DELTA → /appweaver build → analyze-slice-delta {{active_change}} → finalize-delta → analyze-slice → close-delta, with the change still OPEN throughout — compile first, then analyze-slice-delta verifies that every element the delta plans marked ADDED or MODIFIED is actually in the code with a paired test (the gate that catches a lane you declined at the prompt above), then finalize-delta merges it into spec.md + the context's domain-model.md while leaving it open, analyze-slice verifies the slice against those merged masters while a red result is still recoverable, and close-delta LAST archives the change and bumps the version."
|