aw-spec-cli 0.1.23 → 0.1.25

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.
Files changed (38) hide show
  1. package/assets/.appweaver/ORCH-DIALECT.md +3 -3
  2. package/assets/.appweaver/RULE-PARTITION.md +41 -28
  3. package/assets/.appweaver/orchestrator/orchestrator.py +92 -14
  4. package/assets/.appweaver/orchestrator/rev-templates/ai-rules.reference.md +3 -3
  5. package/assets/.appweaver/orchestrator/rev-templates/delta-design-template.skeleton.md +19 -12
  6. package/assets/.appweaver/orchestrator/rev-templates/design-template.skeleton.md +25 -17
  7. package/assets/.appweaver/orchestrator/rev-templates/domain-requirements.skeleton.md +2 -2
  8. package/assets/.appweaver/orchestrator/rev-templates/domain-rule-bindings.skeleton.md +10 -10
  9. package/assets/.appweaver/orchestrator/rev-templates/tech-rule-bindings.skeleton.md +28 -17
  10. package/assets/.appweaver/orchestrator/rev-templates/technical-constitution.skeleton.md +22 -24
  11. package/assets/.appweaver/orchestrator/rev-templates/technical-rule-file.skeleton.md +1 -1
  12. package/assets/.appweaver/orchestrator/rev-templates/ui-delta-design-template.skeleton.md +29 -19
  13. package/assets/.appweaver/orchestrator/rev-templates/ui-design-template.skeleton.md +27 -20
  14. package/assets/.appweaver/orchestrator/workflows/aw-spec-adopt.orch.yaml +184 -37
  15. package/assets/.appweaver/orchestrator/workflows/aw-spec-analyze-plan-delta.orch.yaml +18 -0
  16. package/assets/.appweaver/orchestrator/workflows/aw-spec-analyze-plan.orch.yaml +19 -0
  17. package/assets/.appweaver/orchestrator/workflows/aw-spec-analyze-slice-delta.orch.yaml +18 -0
  18. package/assets/.appweaver/orchestrator/workflows/aw-spec-inventory.orch.yaml +55 -29
  19. package/assets/.appweaver/orchestrator/workflows/aw-spec-onboard.orch.yaml +650 -205
  20. package/assets/.appweaver/orchestrator/workflows/aw-spec-plan.orch.yaml +19 -0
  21. package/assets/.appweaver/orchestrator/workflows/aw-spec-select-feature.orch.yaml +5 -5
  22. package/assets/.appweaver/orchestrator/workflows/aw-spec-select-stack.orch.yaml +2 -2
  23. package/assets/.appweaver/orchestrator/workflows/aw-spec-ui-model.orch.yaml +13 -3
  24. package/assets/.appweaver/orchestrator/workflows/aw-spec-ui-prototype.orch.yaml +40 -1
  25. package/assets/.appweaver/orchestrator/workflows/aw-spec-workflow-model.orch.yaml +2 -1
  26. package/assets/.appweaver/scripts/bash/aw-rev-constitution.sh +1 -1
  27. package/assets/.appweaver/scripts/bash/aw-spec-actions.sh +69 -7
  28. package/assets/.appweaver/scripts/powershell/aw-rev-constitution.ps1 +1 -1
  29. package/assets/.appweaver/scripts/powershell/aw-spec-actions.ps1 +58 -2
  30. package/assets/.appweaver/scripts/python/aw-inventory.py +1809 -156
  31. package/assets/.appweaver/scripts/python/aw-rev-constitution.py +106 -145
  32. package/assets/.appweaver/scripts/python/aw-stack.py +45 -1
  33. package/assets/.appweaver/scripts/python/aw-xref.py +73 -2
  34. package/assets/.appweaver/scripts/python/validate_okf.py +10 -5
  35. package/assets/.appweaver/templates/okf-concept-template.md +10 -2
  36. package/assets/.appweaver/templates/proposed-inventory-template.md +100 -48
  37. package/assets/.appweaver/templates/source-map-template.md +14 -6
  38. package/package.json +1 -1
@@ -24,13 +24,25 @@
24
24
  # 3. GOVERNANCE SCAFFOLD — the PROJECT-level governing tier: the split constitution
25
25
  # (technical + domain), the guardrails/projects/brf-<domain>/domain/ rule-file set
26
26
  # (+ domain-rule-bindings), the domain charter that set is headed by, and the
27
- # activated domain. AUTHORED BY THE FIRST CONTEXT TO ONBOARD AND BY NO OTHER —
28
- # re-deriving project principles from one context's evidence is the aggregate-
29
- # scoping bias this tier exists to avoid, so every later run skips the whole block
30
- # and contributes its own concepts and specs tree instead. Because nothing is
31
- # adopted yet, the tier is a PROVISIONAL scaffold evidenced by the SCAN (project
32
- # identity + bounded-context map are firm; principles/rules are marked
33
- # provisional); /appweaver constitution is what amends it.
27
+ # activated domain. The FIRST context to onboard AUTHORS it from the whole-repo
28
+ # scan. Every LATER context AMENDS it from its own code — ADDITIVELY: a rule file
29
+ # for a concern no existing file covers, rules for a variant an existing file does
30
+ # not state, a principle for a project-level trait no principle covers, and the
31
+ # context's entry in every map the tier keeps. It never rewords, renumbers or
32
+ # deletes what an earlier context wrote; where this context's code contradicts a
33
+ # rule, it records a Divergence note under it for /appweaver constitution to
34
+ # decide. Re-deriving the tier per context would be the aggregate-scoping bias the
35
+ # rev-constitution work removed; adding one context's evidence at project scope is
36
+ # not. A TIER that does not exist yet — a lane declared after an earlier onboard —
37
+ # is authored in full by whichever run first sees it. The document templates are
38
+ # written once per lane and never amended: plans already written follow them.
39
+ # Because nothing is adopted yet, the tier is PROVISIONAL, evidenced by the code
40
+ # (project identity + bounded-context map are firm; principles/rules are marked
41
+ # provisional); /appweaver constitution is its human amendment path.
42
+ #
43
+ # Naming a context that is ALREADY onboarded re-runs this governance pass alone —
44
+ # its concepts and specs tree are left as they are. That is how a lane declared
45
+ # after every context was onboarded gets its governance.
34
46
  #
35
47
  # inventory → [edit specs/proposed-inventory.md] → inventory apply
36
48
  # → ONBOARD <Context> (once per context) ← you are here
@@ -81,18 +93,18 @@
81
93
  # source (never from a greenfield UI template's content), then linted like the other
82
94
  # halves and composed in. Parallel to the technical base, so its numbering is its own.
83
95
  # guardrails/projects/brf-<domain>/frontend/*.md — the code-derived lane rule set, the detail
84
- # layer under those UX-* principles, plus `## /aw-spec-ui-constitution` appended to
85
- # tech-rule-bindings.md so a later /appweaver constitution re-ratifies from THIS
86
- # project's lane rules.
96
+ # layer under those UX-* principles, wired into tech-rule-bindings.md under the lane's
97
+ # three headings: `## /aw-spec-ui-constitution` (what a later /appweaver constitution
98
+ # re-ratifies the UI half from), `## /aw-spec-plan-ui` and `## /aw-spec-implement-ui`
99
+ # (what the frontend lane of `plan` and of `implement` load).
87
100
  # .appweaver/templates/overrides/ui-design-template.md + ui-delta-design-template.md — the
88
101
  # lane's own document pair, reverse-engineered from the UI source the same way the
89
102
  # service pair is reverse-engineered from the service code. The lane is governed by a
90
- # different constitution half and implemented by different commands, so it gets its own
91
- # design document rather than a section inside the service design; the only thing that
92
- # crosses between them is the design contract. Their consumers are the FRONTEND LANES
103
+ # different constitution half and generated by a different lane of `implement`, so it
104
+ # gets its own plan document rather than a section inside the backend plan; the only
105
+ # thing that crosses between them is the service's published surface. Their consumers are the FRONTEND LANES
93
106
  # of `plan` and `implement` — one command each, covering both lanes — and the templates
94
- # are written here because the whole-repo evidence for them exists exactly once, at
95
- # onboard.
107
+ # are written here because the whole-repo evidence for them is read at onboard.
96
108
  # RUN /appweaver select-stack FIRST. It is the first command of the brownfield
97
109
  # sequence and this workflow REFUSES to run without it, because it needs to be told three
98
110
  # things before it can start: which lanes this project has, where each lane's source is,
@@ -132,12 +144,13 @@
132
144
  # Launch: /appweaver onboard [<BoundedContext>] [; concerns: a, b, c]
133
145
  # e.g. /appweaver onboard Clinical
134
146
  # e.g. /appweaver onboard # the next context the map has open
147
+ # e.g. /appweaver onboard Clinical # already onboarded: governance pass only
135
148
  # e.g. /appweaver onboard "Clinical; concerns: auditing, concurrency, authorization"
136
149
  # =============================================================================
137
150
 
138
151
  name: aw-spec-onboard
139
- description: Onboard an existing codebase for brownfield DEVELOPMENT — a deterministic whole-repo scan produces a high-level OKF feature map (folders/concepts) PLUS the project-level governance scaffold (split constitution + guardrails/projects/brf-<domain>/ with its DOMAIN rule files at domain/ + domain-rule-bindings + code-derived TECHNICAL rule files at service/ + tech-rule-bindings + activated domain), all provisional-from-scan and refined per slice by adopt. Where the scan finds a frontend lane in the CODE, it also authors that lane's half — constitution.ui.md (UX-*) — and its code-derived rule files at brf-<domain>/frontend/, mapped under `## /aw-spec-ui-constitution`; a backend-only repo gets none of it. Every rule tier is reverse-engineered from the CODE alone (never a greenfield rule file), evidenced-only, and WIRED per-workflow so the whole forward pipeline AND adopt govern against THIS codebase — never a greenfield fallback. It also reverse-engineers the repo's own technical structure into a project-specific design + delta-design template pair, installed as the project template overrides, and — where the lane exists — the frontend lane's own pair from the UI source. Every authoring step is shaped by a NEUTRAL rev-templates skeleton; no greenfield constitution, rule file or document template is ever placed in context. Accepts an optional concerns list to look for (onboard decides which are actually present). Reads any declared lane, never writes one. No migration content; never modifies source.
140
- version: 2.1.0
152
+ description: Onboard an existing codebase for brownfield DEVELOPMENT — a deterministic whole-repo scan produces a high-level OKF feature map (folders/concepts) PLUS the project-level governance scaffold (split constitution + guardrails/projects/brf-<domain>/ with its DOMAIN rule files at domain/ + domain-rule-bindings + code-derived TECHNICAL rule files at service/ + tech-rule-bindings + activated domain), all provisional-from-scan. The first context authors that tier; every later context amends it additively from its own code (new rules, principles and map entries — never a rewrite, renumbering or deletion; a contradiction is recorded as a Divergence note), and a tier that does not exist yet, such as a lane declared after an earlier onboard, is authored in full. Naming an already-onboarded context re-runs that governance pass alone. Where the scan finds a frontend lane in the CODE, it also authors that lane's half — constitution.ui.md (UX-*) — and its code-derived rule files at brf-<domain>/frontend/, mapped under `## /aw-spec-ui-constitution`, `## /aw-spec-plan-ui` and `## /aw-spec-implement-ui`; a backend-only repo gets none of it. Every rule tier is reverse-engineered from the CODE alone (never a greenfield rule file), evidenced-only, and WIRED per-workflow so the whole forward pipeline AND adopt govern against THIS codebase — never a greenfield fallback. It also reverse-engineers the repo's own technical structure into a project-specific design + delta-design template pair, installed as the project template overrides, and — where the lane exists — the frontend lane's own pair from the UI source. Every authoring step is shaped by a NEUTRAL rev-templates skeleton; no greenfield constitution, rule file or document template is ever placed in context. Accepts an optional concerns list to look for (onboard decides which are actually present). Reads any declared lane, never writes one. No migration content; never modifies source.
153
+ version: 2.3.0
141
154
  agent_agnostic: true
142
155
  dialect: aw-spec.orchestrator/v1
143
156
 
@@ -174,15 +187,31 @@ standards:
174
187
  - { path: .appweaver/ai-rules.md } # kit-resident: the universal operating rules, every flow
175
188
 
176
189
  vars:
177
- bundle_present: "false" # inventory bundle_guard driver
190
+ # The provenance stamp every generated file carries. It names THIS workflow's version,
191
+ # so it moves with `version:` above — one value, never a literal repeated per prompt.
192
+ generated_by: "aw-spec-onboard/2.3.0"
193
+ bundle_present: "false" # set by the scan (the bundle holds concepts); reported, gates nothing
178
194
  conformant: "false" # OKF conformance-gate driver
179
- pack_present: "false" # project anti-clobber driver
195
+ pack_present: "false" # the project tier exists ⇒ repo_gov, so this context AMENDS it
180
196
  # The governance tier — constitution halves, rule packs, document templates —
181
- # is PROJECT-scoped, authored by the first context to onboard and left alone by
182
- # every context after it. Re-authoring project principles from one context's
183
- # evidence is the scoping bias the rev-constitution work removed; this var is
184
- # what keeps the second run from doing it.
197
+ # is PROJECT-scoped: the first context to onboard authors it, and every later one
198
+ # amends it additively. Re-authoring project principles from one context's evidence
199
+ # is the scoping bias the rev-constitution work removed; this var is what switches
200
+ # a later run from authoring to amending.
185
201
  repo_gov: "false" # true once the project governance exists
202
+ # Per-lane tier presence, from project-setup. A lane whose tier is absent is authored
203
+ # in full even on a later context — a lane declared after an earlier onboard.
204
+ service_present: "false"
205
+ frontend_present: "false"
206
+ amend_repo: "false" # the domain tier + domain half exist ⇒ amend them
207
+ amend_svc: "false" # the service tier exists and the lane is declared ⇒ amend it
208
+ amend_ui: "false" # the frontend tier exists and the lane is declared ⇒ amend it
209
+ # False when the named context is already onboarded: its concepts and specs tree are
210
+ # left as they are and the run is the governance pass alone.
211
+ bundle_pass: "true"
212
+ amended_domain_files: ""
213
+ amended_service_files: ""
214
+ amended_ui_files: ""
186
215
  # The governance project is named from the PROJECT, never from the context.
187
216
  # Passing the context name here would produce one rule pack per bounded
188
217
  # context, which is the same bias by another route.
@@ -273,6 +302,11 @@ workflow:
273
302
  args: ["--service-root", "{{be_root}}", "--ui-root", "{{fe_root}}"]
274
303
  outputs:
275
304
  - { name: inventory_json, from: "$.inventory_json" }
305
+ # The same substrate cut per lane. A step that authors ONE lane's governance
306
+ # reads its lane's view; the bundle and the lane-neutral domain steps read the
307
+ # whole substrate.
308
+ - { name: inventory_service_json, from: "$.inventory_service_json" }
309
+ - { name: inventory_ui_json, from: "$.inventory_ui_json" }
276
310
  - { name: root, from: "$.root" }
277
311
  - { name: head, from: "$.head" }
278
312
  - { name: file_count, from: "$.file_count" }
@@ -348,6 +382,11 @@ workflow:
348
382
  - { name: contexts_ordered, from: "$.contexts_ordered" }
349
383
  - { name: feature_map, from: "$.feature_map" }
350
384
  - { name: map_error, from: "$.error" }
385
+ - { name: all_onboarded, from: "$.all_onboarded" }
386
+ # The input's "concerns:" clause, split off the context name. Prompts quote
387
+ # `concerns_line`, never the raw input.
388
+ - { name: concerns, from: "$.concerns" }
389
+ - { name: concerns_line, from: "$.concerns_line" }
351
390
 
352
391
  # 1d. No map means the boundaries were never decided. Onboarding without them
353
392
  # is what produced a flat aggregate list with no context level at all.
@@ -362,6 +401,23 @@ workflow:
362
401
  review and edit `specs/proposed-inventory.md` — it is the boundary map and
363
402
  it is yours to change — then run `/appweaver inventory apply`.
364
403
 
404
+ # context-state exits non-zero on the three refusals below and still prints its
405
+ # verdict; `on_error: continue` binds that JSON, so each gate quotes the reason.
406
+ - id: all_done_gate
407
+ condition: "{{all_onboarded}} == true"
408
+ action: verify_context
409
+ require_value: all_onboarded
410
+ equals: "false"
411
+ on_mismatch: stop
412
+ on_mismatch_message: >
413
+ Every bounded context in the feature map is already onboarded
414
+ ({{onboarded_contexts}}), so there is no context left to onboard. Pick a feature
415
+ with /appweaver select-feature and develop it — adopt it first if it exists in
416
+ the code. To re-run the governance pass — for instance after declaring a lane
417
+ with /appweaver select-stack — name a context: /appweaver onboard <Context>. To
418
+ onboard a context the map does not have, edit specs/proposed-inventory.md and run
419
+ /appweaver inventory apply.
420
+
365
421
  - id: require_context
366
422
  action: verify_context
367
423
  require_value: context_known
@@ -369,16 +425,27 @@ workflow:
369
425
  on_mismatch: stop
370
426
  on_mismatch_message: "{{map_error}}"
371
427
 
372
- # 1e. Per-context curation guard — the narrow form of the old bundle guard.
373
- - id: context_done_guard
428
+ # 1e. Per-context curation guard — the narrow form of the old bundle guard. A context
429
+ # whose concepts all exist is not re-mapped: the concept author is skipped, so its
430
+ # curation is never overwritten. The governance pass still runs, because what it
431
+ # amends is project-scoped and may have moved since — a lane declared after this
432
+ # context was onboarded is the case that needs it.
433
+ - id: context_done_refresh
434
+ condition: "{{already_onboarded}} == true"
435
+ action: set
436
+ vars: { bundle_pass: "false" }
437
+ - id: context_done_note
438
+ condition: "{{already_onboarded}} == true"
374
439
  action: verify_context
375
440
  require_value: already_onboarded
376
- equals: "false"
377
- on_mismatch: stop
441
+ equals: "never"
442
+ on_mismatch: continue
378
443
  on_mismatch_message: >
379
444
  Bounded context {{bc}} is already onboarded — every aggregate its
380
- {{bc_feature_count}} feature(s) act on ({{bc_aggregates}}) already has a concept in
381
- {{bundle_dir}}, and re-running would overwrite that curation. Contexts still open: {{remaining_contexts}}
445
+ {{bc_feature_count}} feature(s) act on ({{bc_aggregates}}) has a concept in
446
+ {{bundle_dir}}. Those concepts and its specs tree are left as they are; this run is
447
+ the GOVERNANCE pass alone: it authors any lane tier that does not exist yet and
448
+ amends the rest from {{bc}}'s code.
382
449
 
383
450
  # 1f. Dependency order. A context whose dependencies are still open would be
384
451
  # modelled against aggregates that do not exist yet. A context inside a
@@ -505,12 +572,14 @@ workflow:
505
572
  # OKF format authority, and an OPTIONAL DDD vocabulary aid for naming (no
506
573
  # migration/pipeline reference — this is development).
507
574
  - id: ctx_author
575
+ condition: "{{bundle_pass}} == true"
508
576
  action: build_context
509
577
  context:
510
578
  - { path: "{{inventory_json}}" } # the deterministic substrate (aggregate_signals etc.)
511
579
  - { path: "{{feature_map}}" } # the CONFIRMED boundaries: which features belong to which bounded context, and in what order
512
580
  - { path: .appweaver/templates/okf-concept-template.md } # OKF v0.1 format authority (frontmatter, index, log, rules) — format only, zero project content
513
581
  - id: author_bundle
582
+ condition: "{{bundle_pass}} == true"
514
583
  action: agent_generate
515
584
  tools: "Read,Write,Edit"
516
585
  permission_mode: acceptEdits
@@ -631,9 +700,10 @@ workflow:
631
700
  group). Do NOT impose a fixed Domain/Application/UI taxonomy — the CODE's
632
701
  folders ARE the grouping. Set `timestamp` to the latest commit time across them.
633
702
  Then set `ui_source_files` to the FRONTEND files that serve this aggregate,
634
- grouped the same way. The substrate's `ui_attribution` proposes them per
635
- aggregate — it is a NAME match, so confirm each against what the file actually
636
- is and move or drop one it got wrong. Keep the key and leave it EMPTY where the
703
+ grouped the same way. The substrate proposes them per aggregate (the `ui_files`
704
+ of each aggregate signal, summarised in `ui_attribution`): files under a UI
705
+ feature folder the map names are attributed through the map, the rest by NAME —
706
+ confirm those against what the file actually is and move or drop one it got wrong. Keep the key and leave it EMPTY where the
637
707
  aggregate has no UI (and on a backend-only repo, where every concept has none);
638
708
  never fold these paths into `source_files`, which stays the service surface.
639
709
  - `aggregates/index.md` — the BOUNDED-CONTEXT / feature map (no frontmatter beyond
@@ -652,7 +722,7 @@ workflow:
652
722
 
653
723
  Provenance + safety (OKF hard rules):
654
724
  - Stamp every concept `origin: reverse-engineered`, `generated_by:
655
- aw-spec-onboard/2.0.0` and `bounded_context: {{bc}}` in frontmatter. The
725
+ {{generated_by}}` and `bounded_context: {{bc}}` in frontmatter. The
656
726
  context key is what lets later commands filter features by the context they
657
727
  belong to instead of listing every aggregate under every one.
658
728
  - The CODE is the source of truth; capture what IS (quirks included), not what
@@ -666,16 +736,21 @@ workflow:
666
736
  - { name: bundle_files, from: "$.files" }
667
737
 
668
738
  - id: verify_authored
739
+ condition: "{{bundle_pass}} == true"
669
740
  action: verify_context
670
741
  require_non_empty: bundle_files
671
742
  on_empty: stop
672
743
  on_empty_message: "No feature-map files were written to {{bundle_dir}}. Ensure the substrate {{inventory_json}} has aggregate_signals and re-run."
673
744
 
674
745
  # 4. CONFORMANCE gate — OKF v0.1 validator (errors block; warnings noted).
746
+ # validate exits non-zero on a non-conformant bundle; `on_error: continue` binds the
747
+ # verdict it prints, so the gate below names the errors instead of the run stopping
748
+ # on a bare script failure.
675
749
  - id: validate_bundle
676
750
  action: execute_script
677
751
  script: { ref: inventory }
678
752
  subcommand: validate
753
+ on_error: continue
679
754
  args: ["--bundle", "{{bundle_dir}}", "--repo-root", "{{root}}"]
680
755
  outputs:
681
756
  - { name: conformant, from: "$.conformant" }
@@ -689,6 +764,30 @@ workflow:
689
764
  on_false: stop
690
765
  on_false_message: "The OKF feature map at {{bundle_dir}} is NON-CONFORMANT (errors: {{okf_errors}}). Fix the reported ERRORs (unparseable frontmatter, missing `type`, malformed index.md/log.md) and re-run."
691
766
 
767
+ # Did every aggregate this context acts on get its concept? The conformance gate checks
768
+ # the files that were written; this checks that the ones the map asked for were. Read
769
+ # back through context-state, the same reader that decides whether the context is
770
+ # onboarded, so a concept it cannot find counts as missing.
771
+ - id: concepts_check
772
+ action: execute_script
773
+ script: { ref: inventory }
774
+ subcommand: context-state
775
+ on_error: continue
776
+ args: ["--context", "{{bc}}", "--bundle", "{{bundle_dir}}"]
777
+ outputs:
778
+ - { name: concepts_complete, from: "$.already_onboarded" }
779
+ - { name: concepts_missing, from: "$.pending_aggregates" }
780
+ - id: concepts_gate
781
+ action: verify_context
782
+ require_value: concepts_complete
783
+ equals: "true"
784
+ on_mismatch: stop
785
+ on_mismatch_message: >
786
+ The bundle at {{bundle_dir}} has no concept for these aggregates of {{bc}}:
787
+ {{concepts_missing}}. Each needs a concept whose `type` names an aggregate and whose
788
+ `title` is the aggregate's name exactly as the map spells it. Re-run onboard for
789
+ {{bc}}; the concepts already written are left as they are.
790
+
692
791
  # ═══════════ THE CONTEXT'S SPECS TREE — specs/<Context>/<Feature>/ ═══════════
693
792
  # The concepts above say what this context CONTAINS; these two steps make that
694
793
  # shape exist where every later command looks for it. Until now a context left
@@ -760,31 +859,31 @@ workflow:
760
859
  /appweaver inventory apply, then /appweaver select-feature will offer them.
761
860
 
762
861
  # ═══════════════ PART 2 — GOVERNANCE SCAFFOLD (project-level) ════════════════
763
- # Establish the governing tier ONCE, from the feature map just written (the whole-
764
- # repo vantage). No slice is adopted, so list-adopted returns slice_count=0 but STILL
765
- # yields project_name / overview / project_context (domain evidence) and
766
- # design_context (= overview + platform: the technical evidence) from the bundle.
767
- # There is NO require_adopted gate here — that is the whole point of onboarding first.
862
+ # The first context AUTHORS the governing tier from the whole-repo vantage; every
863
+ # later context AMENDS it additively from its own code (see the flags below).
864
+ # project-context reads the project framing from the OKF bundle only:
865
+ # project_name / overview / project_context (domain evidence) and technical_context
866
+ # (overview + platform: the technical evidence). It never lists adopted features, so
867
+ # a team that re-runs onboard after adopting some still gets a tier evidenced by the
868
+ # code, not by those features' documents.
768
869
 
769
870
  - id: project_ctx
770
871
  action: execute_script
771
872
  script: { ref: revcon }
772
- subcommand: list-adopted
873
+ subcommand: project-context
773
874
  outputs:
774
- - { name: slice_count, from: "$.slice_count" }
775
- - { name: spec_context, from: "$.spec_context" } # at onboard = project_context (no specs yet)
776
- - { name: design_context, from: "$.design_context" } # at onboard = overview + platform (the tech evidence)
875
+ - { name: technical_context, from: "$.technical_context" } # overview + platform (the tech evidence)
777
876
  - { name: project_context, from: "$.project_context" } # overview + aggregates/index + platform + index
778
877
  - { name: project_name, from: "$.project_name" }
779
878
  - { name: overview, from: "$.overview" }
780
879
 
781
880
  # Slugify + `brf-` prefix the domain name and create guardrails/projects/brf-<domain>/.
782
- # Name: explicit arg → PROJECT name from the OKF overview → repo basename. Guarded
783
- # against clobbering a project that already holds .md files.
881
+ # Name: explicit arg → the ACTIVE brf- project → PROJECT name from the OKF overview →
882
+ # repo basename. It reports which tiers already hold rule files, and lists them.
784
883
  # The governance project is named from the PROJECT — `gov_name` is empty, so
785
- # project-setup falls back to the project name from the OKF overview and then
786
- # to the repo basename. Passing the bounded context here would create one rule
787
- # pack per context and split the project's constitution along context lines,
884
+ # project-setup falls back to the active project, then the project name from the OKF
885
+ # overview, then the repo basename. Passing the bounded context here would create one
886
+ # rule pack per context and split the project's constitution along context lines,
788
887
  # which is the aggregate-scoping bias in a new place.
789
888
  - id: pack_setup
790
889
  action: execute_script
@@ -797,48 +896,62 @@ workflow:
797
896
  - { name: domain_rule_bindings, from: "$.domain_rule_bindings" }
798
897
  - { name: domain_constitution_source, from: "$.domain_constitution_source" }
799
898
  - { name: pack_present, from: "$.pack_present" }
800
-
801
- # An existing pack is no longer a reason to stop — it is the signal that the
802
- # project tier has already been authored and this run is onboarding a LATER
803
- # bounded context. The tier is written once and amended by /appweaver
804
- # constitution; what each later context still contributes is its own OKF
805
- # concepts and its own domain model.
899
+ - { name: service_present, from: "$.service_present" }
900
+ - { name: frontend_present, from: "$.frontend_present" }
901
+ - { name: domain_files, from: "$.domain_files" }
902
+ - { name: service_files, from: "$.service_files" }
903
+ - { name: frontend_files, from: "$.frontend_files" }
904
+
905
+ # An existing project is the signal that an earlier context authored the tier and
906
+ # this run AMENDS it.
806
907
  - id: repo_gov_present
807
908
  action: set
808
909
  condition: "{{pack_present}} == true"
809
910
  vars: { repo_gov: "true" }
810
911
 
811
- # WHAT THIS RUN AUTHORS. The engine compares one variable against one value and
812
- # has no compound conditions, so "this lane exists AND the project tier has not
813
- # been written yet" is computed here as an ordered pair of sets rather than
814
- # asked at each step: default to the lane declaration, then clear everything
815
- # once the project tier is present.
912
+ # WHAT THIS RUN AUTHORS AND WHAT IT AMENDS, PER TIER. The engine compares one
913
+ # variable against one value and has no compound conditions, so "this lane is
914
+ # declared AND its tier does not exist yet" is computed here as ordered sets rather
915
+ # than asked at each step: default to authoring whatever the declaration names, then
916
+ # switch each tier that already exists to amending.
816
917
  #
817
- # The second set also SATISFIES the lint guards the skipped block would
818
- # otherwise leave at their "not yet verified" default — the same move
819
- # svc_lane_absent makes for a repo with no service lane. Without it a later
820
- # context would stop at a gate checking work this run correctly did not do.
918
+ # Authoring and amending are exclusive per tier, and between them they cover every
919
+ # declared lane, so every constitution half this run can touch is linted below. The
920
+ # document templates follow the author flags only: they are written when their lane's
921
+ # tier is first authored and never amended, because the plans already written follow
922
+ # their shape.
821
923
  #
822
- # ⌛ OPEN: should a LATER context amend the rule sets? Skipping the whole tier
823
- # also skips the code-derived rule files, and a second context can evidence a
824
- # domain or technical concern the first one's source never showed — that
825
- # evidence reaches nothing today. The two halves of the tier differ here. The
826
- # constitution halves, principle numbering, domain activation and the document
827
- # templates are project-scoped, and re-deriving them per context IS the
828
- # aggregate-scoping bias rev-constitution v1.1.0 removed; /appweaver
829
- # constitution is their amendment path. The rule SETS
830
- # (guardrails/projects/<p>/{domain,service,frontend}/) are evidenced-only, so
831
- # amending them ADDITIVELY from a later context — add a rule for a concern this
832
- # context exhibits, never rewrite or renumber an existing one — would be more
833
- # evidence at the same project scope rather than one context's bias. That
834
- # additive pass is not built; author-once is what runs.
924
+ # AMENDING IS ADDITIVE, and that is what makes it safe to do per context. A later
925
+ # context adds what its own code evidences and the tier does not yet say — a rule
926
+ # file for a new concern, rules for a variant an existing file does not state, a
927
+ # principle for a project-level trait no principle covers, its entry in every map —
928
+ # and never rewords, renumbers or deletes what an earlier context wrote. Re-deriving
929
+ # the tier per context would be the aggregate-scoping bias rev-constitution v1.1.0
930
+ # removed; adding one context's evidence at project scope is more evidence, not bias.
931
+ # A contradiction is recorded as a Divergence note under the rule it contradicts, for
932
+ # /appweaver constitution to decide, never resolved here.
835
933
  - id: author_flags_default
836
934
  action: set
837
- vars: { author_repo: "true", author_svc: "{{svc_lane}}", author_ui_flag: "{{ui_lane}}" }
838
- - id: author_flags_skip
839
- action: set
935
+ vars:
936
+ author_repo: "true"
937
+ author_svc: "{{svc_lane}}"
938
+ author_ui_flag: "{{ui_lane}}"
939
+ gov_mode: "authored — this run wrote the project tier"
940
+ - id: amend_repo_flags
840
941
  condition: "{{repo_gov}} == true"
841
- vars: { author_repo: "false", author_svc: "false", author_ui_flag: "false", technical_ok: "true", domain_ok: "true", ui_ok: "true", numbering_ok: "true" }
942
+ action: set
943
+ vars:
944
+ author_repo: "false"
945
+ amend_repo: "true"
946
+ gov_mode: "amended — an earlier context wrote the project tier and this run added {{bc}}'s evidence to it"
947
+ - id: amend_svc_flags
948
+ condition: "{{service_present}} == true"
949
+ action: set
950
+ vars: { author_svc: "false", amend_svc: "{{svc_lane}}" }
951
+ - id: amend_ui_flags
952
+ condition: "{{frontend_present}} == true"
953
+ action: set
954
+ vars: { author_ui_flag: "false", amend_ui: "{{ui_lane}}" }
842
955
 
843
956
  # ── DOMAIN RULE SET (provisional, evidenced by the SCAN) ────────────────────
844
957
  # Feed NEUTRAL shape skeletons (rev-templates/, zero content to leak) + the rule-
@@ -878,11 +991,10 @@ workflow:
878
991
  vantage — describe the domain / bounded context AS A WHOLE, so any feature later
879
992
  slots in without a rewrite.
880
993
 
881
- CONCERNS HINT: {{USER_INPUT}} may carry a "concerns: a, b, c" clause. Treat any listed
882
- concern as a SEARCH HINT — go look for it in the code — but you still DECIDE presence
883
- from evidence: include a concern's rule file ONLY if the code exhibits it, drop a
884
- listed concern the code shows none of, and ADD an unlisted concern the code clearly
885
- evidences. Ignore any non-concerns text (the domain name / scope hint).
994
+ CONCERNS HINT: {{concerns_line}} Treat any listed concern as a SEARCH HINT — go look
995
+ for it in the code — but you still DECIDE presence from evidence: include a concern's
996
+ rule file ONLY if the code exhibits it, drop a listed concern the code shows none of,
997
+ and ADD an unlisted concern the code clearly evidences.
886
998
 
887
999
  PROVISIONAL BY CONSTRUCTION. Because no slice is adopted, you have the domain's
888
1000
  SHAPE (its features, ubiquitous language, bounded-context map, evident concerns)
@@ -915,7 +1027,7 @@ workflow:
915
1027
  - domain-requirements.md — the PROJECT overview: open with a
916
1028
  `[DOMAIN: Bounded Contexts / Modules]` map (from the overview + aggregates
917
1029
  index), then per-subsection pointers, platform topology, governance overrides.
918
- Stamp every file `origin: reverse-engineered`, `generated_by: aw-spec-onboard/1.6.0`,
1030
+ Stamp every file `origin: reverse-engineered`, `generated_by: {{generated_by}}`,
919
1031
  and note the project is a provisional scaffold reconciled per slice at adopt.
920
1032
 
921
1033
  domain-rule-bindings.md (MANDATORY — /specify's resolve-domain reads this exact filename).
@@ -947,13 +1059,17 @@ workflow:
947
1059
  # ── DOMAIN CONSTITUTION SOURCE — <project>/domain/domain-constitution.md ────────────
948
1060
  # Named and placed exactly as a greenfield industry corpus names and places its charter,
949
1061
  # and already wired as the first `## /aw-spec-constitution` bullet by the step above.
1062
+ # The charter is authored from the domain rule set the step above wrote — its files,
1063
+ # not only the map that lists them. This step has no tools, so every file it cites is
1064
+ # inlined here: `pack_files` is what author_pack reported, narrowed by the engine to
1065
+ # the files actually on disk.
950
1066
  - id: ctx_domain_source
951
1067
  condition: "{{author_repo}} == true"
952
1068
  action: build_context
953
1069
  context:
954
1070
  - { path: "{{domain_rule_bindings}}" }
955
1071
  - { path: .appweaver/orchestrator/rev-templates/domain-constitution.skeleton.md, optional: true }
956
- context_from: project_context
1072
+ context_from: [project_context, pack_files]
957
1073
  - id: author_domain_source
958
1074
  condition: "{{author_repo}} == true"
959
1075
  action: agent_author
@@ -962,8 +1078,10 @@ workflow:
962
1078
  task: |
963
1079
  Author the DOMAIN CONSTITUTION SOURCE (the output target) — the human-readable
964
1080
  charter for the WHOLE PROJECT **{{project_name}}** (domain {{domain_slug}}),
965
- scaffolded from the OKF feature map (architecture/overview.md, aggregates/index.md
966
- — in context) and the generated project's domain-rule-bindings.md. Follow the SHAPE of the
1081
+ scaffolded from the OKF feature map (architecture/overview.md, aggregates/index.md)
1082
+ and the project's generated domain rule set — domain-rule-bindings.md and every rule
1083
+ file it maps, all in context. The rule files were read out of the code; they are
1084
+ the deeper evidence, the map the shallower one. Follow the SHAPE of the
967
1085
  neutral skeleton domain-constitution.skeleton.md (in context) — its Project-Identity
968
1086
  + Domain-Principle structure — so the normal /appweaver constitution can
969
1087
  re-derive the domain half later. The skeleton carries NO content; every value
@@ -980,7 +1098,8 @@ workflow:
980
1098
  - `## Domain Principles` — principles the domain embodies, TITLED by DOMAIN CONCERN
981
1099
  (not by a feature name), each a declarative rule that would hold across features.
982
1100
  Number with a stable "D1, D2, …" convention (the composed constitution assigns
983
- exact roman numerals after the technology base). Cite the feature-map evidence;
1101
+ exact roman numerals after the technology base). Cite the evidence — the rule
1102
+ file a principle rests on, or the feature-map line;
984
1103
  mark any principle whose exact rule ids are not yet enumerable `PROVISIONAL —
985
1104
  reconciled at adopt`.
986
1105
  - AS-BUILT: state the rule the code evidences; do NOT prescribe an ideal it does
@@ -996,9 +1115,9 @@ workflow:
996
1115
  # EVERY setup-constitution call in this workflow, the UI one included: this command
997
1116
  # creates the always-present halves as a side effect of whatever else it is asked to
998
1117
  # do, so a later call without the flag silently recreates the half an earlier call
999
- # was told to skip.
1118
+ # was told to skip. It creates only what is missing and returns every path either way,
1119
+ # so it runs on each pass: an amending run needs the same paths an authoring one does.
1000
1120
  - id: setup_constitution
1001
- condition: "{{author_repo}} == true"
1002
1121
  action: execute_script
1003
1122
  script: { ref: actions }
1004
1123
  subcommand: setup-constitution
@@ -1007,7 +1126,91 @@ workflow:
1007
1126
  - { name: constitution_technical_file, from: "$.constitution_technical_file" }
1008
1127
  - { name: constitution_domain_file, from: "$.constitution_domain_file" }
1009
1128
 
1010
- # TECHNICAL HALF — from the OKF overview + platform note (design_context), DOMAIN-FREE.
1129
+ # ── AMEND THE SERVICE TIER (a later context, the tier exists) ────────────────
1130
+ # One step for the lane's whole tier — its rule files, its headings in the map and
1131
+ # its constitution half — because a new principle is only ever the ratified line over
1132
+ # a rule this context's code evidences, and the two are decided together. Rules first,
1133
+ # principle second, from THIS context's code: the first context's author read the
1134
+ # whole-repo scan, so what a later context adds is the depth it brings to its own
1135
+ # files. Runs before the domain tier's amendment, which continues this half's
1136
+ # numbering. Changing nothing is a valid outcome, so nothing here gates on a result.
1137
+ - id: ctx_amend_service
1138
+ condition: "{{amend_svc}} == true"
1139
+ action: build_context
1140
+ context:
1141
+ - { path: "{{constitution_technical_file}}" } # the ratified half being amended
1142
+ - { path: "{{pack_dir}}/tech-rule-bindings.md" } # the map being amended
1143
+ - { path: "{{inventory_service_json}}" } # the lane's substrate — locate this context's files
1144
+ - { path: .appweaver/orchestrator/rev-templates/technical-rule-file.skeleton.md, optional: true } # SHAPE ONLY for a new rule file
1145
+ - { path: .appweaver/RULE-PARTITION.md } # which heading a new file may go under
1146
+ # The existing rule files, inlined, plus the overview + platform note this run's
1147
+ # concept author may have added this context's technology to.
1148
+ context_from: [technical_context, service_files]
1149
+ - id: amend_service_tier
1150
+ condition: "{{amend_svc}} == true"
1151
+ action: agent_generate
1152
+ tools: "Read,Write,Edit"
1153
+ permission_mode: acceptEdits
1154
+ task: |
1155
+ AMEND the SERVICE lane's governance for **{{project_name}}** (project
1156
+ {{domain_slug}}) with what bounded context `{{bc}}` evidences. The tier exists — an
1157
+ earlier context authored it — and this run ADDS to it. It never re-authors it.
1158
+
1159
+ THE EVIDENCE IS THIS CONTEXT'S CODE. Its aggregates: {{bc_aggregates}} (features:
1160
+ {{bc_features}}). Each has a concept under {{bundle_dir}}/aggregates/ whose `title`
1161
+ is the aggregate's name, and its `source_files` are this context's service code.
1162
+ Read those concepts, then READ the source they list — enough to see how this
1163
+ context handles each technology concern. {{inventory_service_json}} (in context) is
1164
+ the whole lane's substrate, for anything the concepts do not list.
1165
+
1166
+ WHAT EXISTS (in context): every rule file in {{pack_dir}}/service/, the map
1167
+ {{pack_dir}}/tech-rule-bindings.md and the technical half
1168
+ {{constitution_technical_file}}. Read all of it before writing anything.
1169
+
1170
+ WHAT YOU MAY ADD — and only add:
1171
+ - A NEW rule file `{{pack_dir}}/service/<concern>.md` for a technology concern this
1172
+ context's code exhibits and no existing file covers. Same shape as the existing
1173
+ files (frontmatter origin: reverse-engineered, generated_by: {{generated_by}},
1174
+ concern); every rule cites a code coordinate from this context and the numeral
1175
+ of the principle it details. Wire it into tech-rule-bindings.md under the
1176
+ headings its rules serve (RULE-PARTITION.md, in context) and give it a row in
1177
+ the quick-reference table. Nothing but service/domain-modelling.md ever goes
1178
+ under `## /aw-spec-specify`.
1179
+ - NEW rules appended to an EXISTING file, where this context shows a form of that
1180
+ concern the file does not state — each citing this context's coordinate and
1181
+ marked `(context: {{bc}})`.
1182
+ - A NEW principle in the technical half, only for a PROJECT-level technology trait
1183
+ this context evidences and no principle covers. Append it after the last one
1184
+ with the next roman numeral, citing its evidence and marked `PROVISIONAL — code
1185
+ coordinate reconciled at adopt` where the exact coordinate is not pinned.
1186
+ NEVER reword, reorder, renumber or delete an existing rule, principle, map bullet
1187
+ or heading, and never touch the evidence another context contributed. Add no
1188
+ domain-specific principle, identifier or terminology — this tier is domain-free.
1189
+
1190
+ A CONFLICT IS RECORDED, NOT RESOLVED. Where this context's code does what an
1191
+ existing rule or principle says the code does not do (or the reverse), leave that
1192
+ text as it is and add under it one line:
1193
+ `Divergence ({{bc}}): <what this code does> (evidence: <path>)`.
1194
+ Name every divergence in the half's Sync Impact Report as needing a decision
1195
+ through /appweaver constitution.
1196
+
1197
+ WHEN YOU CHANGE THE HALF: bump its version — MINOR for a new principle, PATCH when
1198
+ only a divergence note was added — set Last Amended to today and keep Ratified;
1199
+ replace the leading Sync Impact Report comment with one for this amendment
1200
+ (version old→new, what was added or noted and from which context); and if the
1201
+ principle count moved, update the hand-off line ("Technical principles: I–<N>;
1202
+ domain half continues at <N+1>").
1203
+
1204
+ CHANGING NOTHING IS A VALID OUTCOME. If the tier already covers everything this
1205
+ context's code shows, write no file and say so.
1206
+ Write ONLY inside {{pack_dir}}/service/, {{pack_dir}}/tech-rule-bindings.md and
1207
+ {{constitution_technical_file}} — the domain tier and the frontend lane are
1208
+ amended by their own steps. Modify no source. Report the files you changed (an
1209
+ empty list when none) and, per change, the concern and the code path evidencing it.
1210
+ outputs:
1211
+ - { name: amended_service_files, from: "$.files" }
1212
+
1213
+ # TECHNICAL HALF — from the OKF overview + platform note (technical_context), DOMAIN-FREE.
1011
1214
  # The neutral technical shape skeleton is fed via CONTEXT (not the sticky standards
1012
1215
  # set, which is empty), so nothing leaks into the Part-1 feature-map agent.
1013
1216
  - id: ctx_technical
@@ -1017,7 +1220,7 @@ workflow:
1017
1220
  - { path: "{{constitution_technical_file}}" }
1018
1221
  - { path: .appweaver/orchestrator/rev-templates/technical-constitution.skeleton.md, optional: true }
1019
1222
  - { path: .appweaver/orchestrator/rev-templates/ai-rules.reference.md, optional: true }
1020
- context_from: design_context
1223
+ context_from: technical_context
1021
1224
  - id: author_technical
1022
1225
  action: agent_author
1023
1226
  condition: "{{author_svc}} == true"
@@ -1061,9 +1264,11 @@ workflow:
1061
1264
  the technical count / domain hand-off numeral, and dependent artifacts (✅/⚠).
1062
1265
  Return the complete updated technical constitution content only.
1063
1266
 
1267
+ # Authored or amended, the half is linted: with a service lane declared, one of the
1268
+ # two ran.
1064
1269
  - id: technical_validation_loop
1065
1270
  action: loop
1066
- condition: "{{author_svc}} == true"
1271
+ condition: "{{svc_lane}} == true"
1067
1272
  while: "{{technical_ok}} != true"
1068
1273
  max_iterations: 3
1069
1274
  steps:
@@ -1105,10 +1310,11 @@ workflow:
1105
1310
  # order the technical tier already uses in this workflow.
1106
1311
 
1107
1312
  # Create the UI half from its template — on demand, unlike the other two. Its
1108
- # ABSENCE is meaningful: a repo with no UI never gets the file at all.
1313
+ # ABSENCE is meaningful: a repo with no UI never gets the file at all. Where the half
1314
+ # exists it is left alone and its path returned, for the amending step below.
1109
1315
  - id: setup_ui_constitution
1110
1316
  action: execute_script
1111
- condition: "{{author_ui_flag}} == true"
1317
+ condition: "{{ui_lane}} == true"
1112
1318
  script: { ref: actions }
1113
1319
  subcommand: setup-constitution
1114
1320
  args: ["--ui", "{{setup_tech_flag}}"]
@@ -1116,12 +1322,91 @@ workflow:
1116
1322
  - { name: constitution_ui_file, from: "$.constitution_ui_file" }
1117
1323
  - { name: ui_created, from: "$.ui_created" }
1118
1324
 
1325
+ # ── AMEND THE FRONTEND TIER (a later context, the tier exists) ───────────────
1326
+ # The frontend lane's twin of the service amendment above: its rule files, its three
1327
+ # headings in the map and the UX-* half, from this context's UI code. A lane declared
1328
+ # after an earlier onboard has no tier yet, so it takes the authoring path below
1329
+ # instead — this step never runs for it.
1330
+ - id: ctx_amend_ui
1331
+ condition: "{{amend_ui}} == true"
1332
+ action: build_context
1333
+ context:
1334
+ - { path: "{{constitution_ui_file}}" } # the ratified UX-* half being amended
1335
+ - { path: "{{pack_dir}}/tech-rule-bindings.md" } # the map whose UI headings are amended
1336
+ - { path: "{{inventory_ui_json}}" } # the lane's substrate — locate this context's UI files
1337
+ - { path: .appweaver/orchestrator/rev-templates/frontend-rule-file.skeleton.md, optional: true } # SHAPE ONLY for a new rule file
1338
+ - { path: .appweaver/RULE-PARTITION.md }
1339
+ - { path: "{{bundle_dir}}/architecture/frontend.md", optional: true } # the shared UI surface, as the bundle records it
1340
+ context_from: frontend_files
1341
+ - id: amend_ui_tier
1342
+ condition: "{{amend_ui}} == true"
1343
+ action: agent_generate
1344
+ tools: "Read,Write,Edit"
1345
+ permission_mode: acceptEdits
1346
+ task: |
1347
+ AMEND the FRONTEND lane's governance for **{{project_name}}** (project
1348
+ {{domain_slug}}) with what bounded context `{{bc}}` evidences. The tier exists — an
1349
+ earlier context authored it — and this run ADDS to it. It never re-authors it.
1350
+
1351
+ THE EVIDENCE IS THIS CONTEXT'S UI CODE. Its aggregates: {{bc_aggregates}}
1352
+ (features: {{bc_features}}). Each has a concept under {{bundle_dir}}/aggregates/
1353
+ whose `title` is the aggregate's name, and its `ui_source_files` are the UI files
1354
+ serving it. Read those concepts, then READ the UI source they list — enough to see
1355
+ how this context's screens handle each experience concern. {{inventory_ui_json}}
1356
+ (in context) is the whole lane's substrate. The shared UI surface (app shell,
1357
+ layout, design system) belongs to no context and is already governed; amend it
1358
+ only where this context's screens show something the tier does not state.
1359
+
1360
+ WHAT EXISTS (in context): every rule file in {{pack_dir}}/frontend/, the map
1361
+ {{pack_dir}}/tech-rule-bindings.md and the UX half {{constitution_ui_file}}. Read
1362
+ all of it before writing anything.
1363
+
1364
+ WHAT YOU MAY ADD — and only add:
1365
+ - A NEW rule file `{{pack_dir}}/frontend/<concern>.md` for an experience concern
1366
+ this context's UI exhibits and no existing file covers. Same shape as the
1367
+ existing files (frontmatter origin: reverse-engineered, generated_by:
1368
+ {{generated_by}}, concern); every rule cites a UI code coordinate from this
1369
+ context and the UX numeral it details. Wire it into tech-rule-bindings.md under
1370
+ `## /aw-spec-plan-ui` and/or `## /aw-spec-implement-ui` as its rules serve
1371
+ planning or generating, and give it its table row. frontend/ui-constitution.md
1372
+ stays the only file under `## /aw-spec-ui-constitution` that is not also a
1373
+ concern file.
1374
+ - NEW rules appended to an EXISTING file, where this context shows a form of that
1375
+ concern the file does not state — each citing this context's coordinate and
1376
+ marked `(context: {{bc}})`.
1377
+ - A NEW principle in the UX half, only for a lane-wide experience trait this
1378
+ context evidences and no principle covers. Append it with the next UX-* numeral.
1379
+ NEVER reword, reorder, renumber or delete an existing rule, principle, map bullet
1380
+ or heading, never touch the service lane's headings or files, and add no
1381
+ domain-specific principle, identifier or terminology.
1382
+
1383
+ A CONFLICT IS RECORDED, NOT RESOLVED. Where this context's UI does what an
1384
+ existing rule or principle says the UI does not do (or the reverse), leave that
1385
+ text as it is and add under it one line:
1386
+ `Divergence ({{bc}}): <what this UI does> (evidence: <path>)`.
1387
+ Name every divergence in the half's Sync Impact Report as needing a decision
1388
+ through /appweaver constitution.
1389
+
1390
+ WHEN YOU CHANGE THE HALF: bump its version — MINOR for a new principle, PATCH when
1391
+ only a divergence note was added — set Last Amended to today and keep Ratified,
1392
+ and replace the leading Sync Impact Report comment with one for this amendment
1393
+ (version old→new, what was added or noted and from which context).
1394
+
1395
+ CHANGING NOTHING IS A VALID OUTCOME. If the tier already covers everything this
1396
+ context's UI shows, write no file and say so.
1397
+ Write ONLY inside {{pack_dir}}/frontend/, the UI headings and table rows of
1398
+ {{pack_dir}}/tech-rule-bindings.md, and {{constitution_ui_file}}. Modify no source.
1399
+ Report the files you changed (an empty list when none) and, per change, the
1400
+ concern and the code path evidencing it.
1401
+ outputs:
1402
+ - { name: amended_ui_files, from: "$.files" }
1403
+
1119
1404
  - id: ctx_ui
1120
1405
  action: build_context
1121
1406
  condition: "{{author_ui_flag}} == true"
1122
1407
  context:
1123
1408
  - { path: "{{constitution_ui_file}}" } # the target half being filled
1124
- - { path: "{{inventory_json}}" } # PRIMARY: the COMPLETE deterministic substrate — frontend_signals + the UI file lists to read source from
1409
+ - { path: "{{inventory_ui_json}}" } # PRIMARY: the substrate's UI view — frontend_signals + the UI file lists to read source from
1125
1410
  - { path: .appweaver/orchestrator/rev-templates/ui-constitution.skeleton.md, optional: true } # SHAPE ONLY: heading style, Sync-Impact-Report shape, evidence-line pattern (zero UI content)
1126
1411
  - { path: "{{bundle_dir}}/architecture/frontend.md", optional: true } # SECONDARY (shallow): the OKF as-built frontend note — corroborate, don't rely on alone
1127
1412
  - id: author_ui
@@ -1137,10 +1422,10 @@ workflow:
1137
1422
  base it runs parallel to.
1138
1423
  Why this lane was detected: {{ui_evidence}}
1139
1424
  Lane declaration: {{ui_declaration_note}}
1140
- User hint (optional, may name nothing about the UI): {{USER_INPUT}}
1425
+ Concerns hint: {{concerns_line}} A hint only — the UI code decides what is present.
1141
1426
 
1142
1427
  EVIDENCE = THE UI CODE ITSELF (deep read). Authority, in order:
1143
- 1. THE ACTUAL UI SOURCE (ground truth). Use {{inventory_json}} (in context):
1428
+ 1. THE ACTUAL UI SOURCE (ground truth). Use {{inventory_ui_json}} (in context):
1144
1429
  `frontend_signals` lists the candidate lane roots with their kind
1145
1430
  (spa / server-rendered / desktop), their framework markers, and their
1146
1431
  component / route / store / style file lists. READ ENOUGH OF THOSE FILES to
@@ -1195,7 +1480,7 @@ workflow:
1195
1480
 
1196
1481
  - id: ui_validation_loop
1197
1482
  action: loop
1198
- condition: "{{author_ui_flag}} == true"
1483
+ condition: "{{ui_lane}} == true"
1199
1484
  while: "{{ui_ok}} != true"
1200
1485
  max_iterations: 3
1201
1486
  steps:
@@ -1228,14 +1513,110 @@ workflow:
1228
1513
  # repo no half was created, so the run reports that rather than a bare false a reader
1229
1514
  # would take for a half that needs a manual touch.
1230
1515
  - id: ui_validation_state_absent
1231
- condition: "{{author_repo}} == true"
1232
1516
  action: set
1233
1517
  vars: { ui_validation_state: "n/a — no frontend lane, no UI half authored" }
1234
1518
  - id: ui_validation_state_present
1235
1519
  action: set
1236
- condition: "{{author_ui_flag}} == true"
1520
+ condition: "{{ui_lane}} == true"
1237
1521
  vars: { ui_validation_state: "{{ui_ok}}" }
1238
1522
 
1523
+ # ── AMEND THE DOMAIN TIER (a later context, the tier exists) ─────────────────
1524
+ # The domain rule set, its map, the charter and the domain half, from this context's
1525
+ # domain-carrying code. It runs AFTER both lane halves are settled because the domain
1526
+ # half continues the technical half's numerals: a technical principle added above
1527
+ # moves where the domain series starts, and this is the one step allowed to shift it.
1528
+ # The context maps the tier keeps — the bounded-context/feature map, the requirements
1529
+ # overview's context list, the charter's Project Identity — must carry this context,
1530
+ # so a newly onboarded context always has at least that to write.
1531
+ - id: ctx_amend_domain
1532
+ condition: "{{amend_repo}} == true"
1533
+ action: build_context
1534
+ context:
1535
+ - { path: "{{domain_rule_bindings}}" }
1536
+ - { path: "{{constitution_domain_file}}" }
1537
+ - { path: "{{constitution_technical_file}}", optional: true } # the numerals the domain half continues (absent with no service lane)
1538
+ - { path: .appweaver/orchestrator/rev-templates/domain-rule-file.skeleton.md, optional: true } # SHAPE ONLY for a new rule file
1539
+ - { path: .appweaver/RULE-PARTITION.md }
1540
+ # The existing domain rule files (the charter and the requirements overview among
1541
+ # them), inlined, plus the bundle framing this run just extended with the context.
1542
+ context_from: [project_context, domain_files]
1543
+ - id: amend_domain_tier
1544
+ condition: "{{amend_repo}} == true"
1545
+ action: agent_generate
1546
+ tools: "Read,Write,Edit"
1547
+ permission_mode: acceptEdits
1548
+ task: |
1549
+ AMEND the DOMAIN governance of **{{project_name}}** (project {{domain_slug}}) with
1550
+ bounded context `{{bc}}`. The tier exists — an earlier context authored it — and
1551
+ this run ADDS this context to it. It never re-authors it.
1552
+
1553
+ THE EVIDENCE IS THIS CONTEXT'S CODE. Its aggregates: {{bc_aggregates}} (features:
1554
+ {{bc_features}}; which feature acts on which: {{bc_feature_aggregates}}). Each has
1555
+ a concept under {{bundle_dir}}/aggregates/ whose `title` is the aggregate's name
1556
+ and whose `source_files` list its code. Read those concepts, then READ the
1557
+ domain-carrying files among them — entities, value objects, invariant checks,
1558
+ validation, domain events — enough to state each rule from what the code actually
1559
+ enforces. The OKF overview and aggregates/index.md (in context) already carry this
1560
+ context.
1561
+
1562
+ WHAT EXISTS (in context): every file in {{pack_dir}}/domain/ — the rule files, the
1563
+ requirements overview and the charter {{domain_constitution_source}} — the map
1564
+ {{domain_rule_bindings}}, and the domain half {{constitution_domain_file}}. Read
1565
+ all of it before writing anything.
1566
+
1567
+ WHAT YOU MUST ADD — this context's place in every map the tier keeps, in each
1568
+ file that has one: the bounded-context / feature map and ubiquitous language
1569
+ (domain-model.domain.md, where it exists), the `[DOMAIN: Bounded Contexts /
1570
+ Modules]` map (domain-requirements.md, where it exists), the charter's Project
1571
+ Identity context map, and the domain half's identity / context map. Add `{{bc}}`
1572
+ with its aggregates, its features and the terms its code uses wherever a map does
1573
+ not carry it yet (a re-run for an onboarded context usually finds it there); leave
1574
+ every other context's entry as it is.
1575
+
1576
+ WHAT YOU MAY ADD — and only add:
1577
+ - A NEW rule file `{{pack_dir}}/domain/<concern>.domain.md` for a domain concern
1578
+ this context's code exhibits and no existing file covers, in the existing
1579
+ files' shape (origin: reverse-engineered, generated_by: {{generated_by}}),
1580
+ named after the concern the code exhibits. Wire it into
1581
+ domain-rule-bindings.md under `## /aw-spec-specify` and `## /aw-spec-gate`
1582
+ (plus `## /aw-spec-constitution` for an identity / regulatory file), as the
1583
+ existing files are wired. `## /aw-spec-plan` and `## /aw-spec-implement` keep
1584
+ loading no domain file.
1585
+ - NEW rules appended to an EXISTING rule file, where this context's code enforces
1586
+ a rule of that concern the file does not state — each citing this context's code
1587
+ and marked `(context: {{bc}})`. Mark unresolved specifics `PROVISIONAL —
1588
+ reconciled at adopt`.
1589
+ - A NEW principle in the charter (the next D-n) and in the domain half, only for a
1590
+ project-level domain trait this context evidences and no principle covers.
1591
+ NEVER reword, reorder or delete an existing rule, principle, map bullet or entry,
1592
+ and never touch another context's evidence. Never invent a rule the code does not
1593
+ evidence.
1594
+
1595
+ NUMBERING. The domain half continues the technical half's roman numerals: its
1596
+ first principle is the technical half's last numeral + 1 (the technical half is in
1597
+ context; with no service lane the series starts at I). If the domain half no longer
1598
+ starts there — a technical principle was added earlier in this run — renumber the
1599
+ domain principles IN ORDER to resume at the right numeral, keeping every title and
1600
+ text, and record the shift in its Sync Impact Report. That is the only renumbering
1601
+ you may do. A new domain principle takes the next numeral after the last one.
1602
+
1603
+ A CONFLICT IS RECORDED, NOT RESOLVED. Where this context's code contradicts an
1604
+ existing rule or principle, leave that text as it is and add under it one line:
1605
+ `Divergence ({{bc}}): <what this code does> (evidence: <path>)`, and name it in the
1606
+ domain half's Sync Impact Report as needing a decision through /appweaver
1607
+ constitution.
1608
+
1609
+ THE DOMAIN HALF: bump its version — MINOR for a new principle, PATCH for context-
1610
+ map entries, divergence notes or a numeral shift — set Last Amended to today and
1611
+ keep Ratified, and replace the leading Sync Impact Report comment with one for this
1612
+ amendment (version old→new, what was added and from which context).
1613
+
1614
+ Write ONLY inside {{pack_dir}}/domain/, {{domain_rule_bindings}} and
1615
+ {{constitution_domain_file}}. Modify no source. Report the files you changed and,
1616
+ per change, what was added and the code path evidencing it.
1617
+ outputs:
1618
+ - { name: amended_domain_files, from: "$.files" }
1619
+
1239
1620
  # DOMAIN HALF — from the project + charter, principles continue the technical numbering.
1240
1621
  - id: ctx_domain
1241
1622
  condition: "{{author_repo}} == true"
@@ -1245,7 +1626,8 @@ workflow:
1245
1626
  - { path: "{{constitution_technical_file}}" } # to CONTINUE its numbering (evidenced-only ⇒ not a fixed XV)
1246
1627
  - { path: "{{domain_constitution_source}}" }
1247
1628
  - { path: "{{domain_rule_bindings}}" }
1248
- context_from: project_context
1629
+ # The domain rule files themselves, inlined: this step has no tools to read them by path.
1630
+ context_from: [project_context, pack_files]
1249
1631
  - id: author_domain
1250
1632
  condition: "{{author_repo}} == true"
1251
1633
  action: agent_author
@@ -1254,9 +1636,9 @@ workflow:
1254
1636
  task: |
1255
1637
  Scaffold the DOMAIN ADDENDA constitution for the WHOLE PROJECT **{{project_name}}**
1256
1638
  (domain {{domain_slug}}) — the target file in context — AS-BUILT and PROVISIONAL,
1257
- from the OKF project context (overview, aggregates/index — in context) + the
1258
- domain-constitution source + the generated project (domain-rule-bindings in context; READ
1259
- the project's rule files under guardrails/projects/{{domain_slug}}/). It is a TEMPLATE
1639
+ from the OKF project context (overview, aggregates/index) + the domain-constitution
1640
+ source + the project's generated domain rule set (domain-rule-bindings.md and every
1641
+ rule file it maps) — all in context. It is a TEMPLATE
1260
1642
  with [ALL_CAPS] tokens; this half carries ONLY domain material.
1261
1643
  - Name the SAME project as the technical half / charter: title / any [PROJECT_NAME]
1262
1644
  token = {{project_name}}. This is a PROJECT constitution, not an aggregate spec —
@@ -1287,8 +1669,8 @@ workflow:
1287
1669
  principles, dependent artifacts ✅/⚠ + TODOs).
1288
1670
  Return the complete updated domain addenda content only.
1289
1671
 
1672
+ # The domain half is authored or amended on every run, so it is linted on every run.
1290
1673
  - id: domain_validation_loop
1291
- condition: "{{author_repo}} == true"
1292
1674
  action: loop
1293
1675
  while: "{{domain_ok}} != true"
1294
1676
  max_iterations: 3
@@ -1320,7 +1702,6 @@ workflow:
1320
1702
 
1321
1703
  # ── COMPOSE + ACTIVATE ───────────────────────────────────────────────────────
1322
1704
  - id: compose_constitution
1323
- condition: "{{author_repo}} == true"
1324
1705
  action: execute_script
1325
1706
  script: { ref: actions }
1326
1707
  subcommand: compose-constitution
@@ -1343,7 +1724,6 @@ workflow:
1343
1724
  # Ordered override — the var holds "ok" unless the check reported a problem, because
1344
1725
  # require_non_empty reports on EMPTY.
1345
1726
  - id: numbering_default
1346
- condition: "{{author_repo}} == true"
1347
1727
  action: set
1348
1728
  vars: { numbering_gate: "ok" }
1349
1729
  - id: numbering_detect
@@ -1351,7 +1731,6 @@ workflow:
1351
1731
  condition: "{{numbering_ok}} == false"
1352
1732
  vars: { numbering_gate: "" }
1353
1733
  - id: numbering_warning
1354
- condition: "{{author_repo}} == true"
1355
1734
  action: verify_context
1356
1735
  require_non_empty: numbering_gate
1357
1736
  on_empty: continue
@@ -1365,9 +1744,9 @@ workflow:
1365
1744
  constitution.md was still written so the clash is visible.
1366
1745
 
1367
1746
  # Auto-activate: point .appweaver/domain.json at the scaffolded project so the forward CR
1368
- # loop governs development with it from the first change.
1747
+ # loop governs development with it from the first change. Every pass activates it, so
1748
+ # the project this run authored or amended is the one the pipeline reads afterwards.
1369
1749
  - id: activate_domain
1370
- condition: "{{author_repo}} == true"
1371
1750
  action: execute_script
1372
1751
  script: { ref: actions }
1373
1752
  subcommand: set-domain
@@ -1395,19 +1774,20 @@ workflow:
1395
1774
  # 2. guardrails/projects/<domain>/tech-rule-bindings.md — the TECHNICAL map (resolve-tech +
1396
1775
  # tech-select read it by that exact name), wiring the generated files per-workflow.
1397
1776
  # Because onboard already ACTIVATED brf-<domain>, the forward pipeline's + adopt's tech_select
1398
- # steps now resolve to THESE files — never another project's rules, ever. The project
1399
- # lives inside pack_dir, so pack_guard (above) already protects it from clobber.
1777
+ # steps now resolve to THESE files — never another project's rules, ever. The files live
1778
+ # inside pack_dir, so a later context does not author them again: service_present switches
1779
+ # the lane to amend_service_tier above, which only adds to them.
1400
1780
  - id: ctx_tech_pack
1401
1781
  action: build_context
1402
1782
  condition: "{{author_svc}} == true"
1403
1783
  context:
1404
- - { path: "{{inventory_json}}" } # PRIMARY: the COMPLETE deterministic substrate — read representative SOURCE from its file lists
1784
+ - { path: "{{inventory_service_json}}" } # PRIMARY: the substrate's service view — read representative SOURCE from its file lists
1405
1785
  - { path: "{{constitution_technical_file}}" } # PRIMARY: the VALIDATED as-built technology base — the ratified principles these files detail
1406
1786
  - { path: .appweaver/orchestrator/rev-templates/tech-rule-bindings.skeleton.md, optional: true } # SHAPE ONLY: the technical map's headings + partition + table (zero real files)
1407
1787
  - { path: .appweaver/orchestrator/rev-templates/technical-rule-file.skeleton.md, optional: true } # SHAPE ONLY: one code-derived tech rule file's shape (zero real tech)
1408
1788
  - { path: .appweaver/RULE-PARTITION.md } # the rule-partition authority (which command reads what)
1409
1789
  - { path: "{{bundle_dir}}/architecture/platform.md", optional: true } # SECONDARY (shallow): the OKF as-built platform note — corroborate, don't rely on alone
1410
- context_from: design_context
1790
+ context_from: technical_context
1411
1791
  - id: author_tech_pack
1412
1792
  action: agent_generate
1413
1793
  condition: "{{author_svc}} == true"
@@ -1418,14 +1798,14 @@ workflow:
1418
1798
  {{domain_slug}}) — the CODE-DERIVED replacement for the greenfield technical rule set —
1419
1799
  into guardrails/projects/{{domain_slug}}/service/ (create it), plus the technical map
1420
1800
  guardrails/projects/{{domain_slug}}/tech-rule-bindings.md. This is the TECHNICAL twin of the
1421
- already-generated domain set: it feeds the HOW phases (design/implement/build/…) plus
1801
+ already-generated domain set: it feeds the HOW phases (plan/implement/build/…) plus
1422
1802
  ONE modelling-methodology file for /specify (see domain-modelling below) — and nothing
1423
1803
  else ever reaches /specify from this tier.
1424
1804
 
1425
1805
  EVIDENCE = THE CODE ITSELF (deep read) + THE VALIDATED TECHNICAL CONSTITUTION. Authority,
1426
1806
  in order:
1427
- 1. THE ACTUAL SOURCE CODE (ground truth). Use {{inventory_json}} (in context) to locate
1428
- representative files across top_level_dirs + a few aggregate_signals, and Read enough
1807
+ 1. THE ACTUAL SOURCE CODE (ground truth). Use {{inventory_service_json}} (in context) to
1808
+ locate representative files across top_level_dirs + a few aggregate_signals, and Read enough
1429
1809
  to state each technical rule from what the code ACTUALLY does — the folder/tier/module
1430
1810
  convention, the dependency direction, the persistence approach, concurrency handling,
1431
1811
  testing convention, the auth/cross-cutting posture. Do NOT assert structure you have
@@ -1439,17 +1819,16 @@ workflow:
1439
1819
  greenfield fixture, NOT this project's rules. Every path you write lives under
1440
1820
  guardrails/projects/{{domain_slug}}/service/.
1441
1821
 
1442
- CONCERNS HINT: {{USER_INPUT}} may carry a "concerns: a, b, c" clause. Treat any listed
1443
- concern as a SEARCH HINT — look for it in the code — but DECIDE presence from evidence:
1444
- write a tech rule file for a concern ONLY if the code exhibits it, drop a listed concern
1445
- the code shows none of, and ADD an unlisted concern the code clearly evidences. Ignore any
1446
- non-concerns text.
1822
+ CONCERNS HINT: {{concerns_line}} Treat any listed concern as a SEARCH HINT — look for it
1823
+ in the code — but DECIDE presence from evidence: write a tech rule file for a concern ONLY
1824
+ if the code exhibits it, drop a listed concern the code shows none of, and ADD an unlisted
1825
+ concern the code clearly evidences.
1447
1826
 
1448
1827
  EVIDENCED-ONLY (lean). Write a `service/<concern>.md` ONLY for a technology concern the code
1449
1828
  actually exhibits — e.g. as-built-architecture, persistence, concurrency, testing,
1450
1829
  security-posture, api-surface, eventing, observability, hosting. Follow the SHAPE of
1451
1830
  technical-rule-file.skeleton.md (in context): frontmatter (origin: reverse-engineered,
1452
- generated_by: aw-spec-onboard/1.6.0, concern), a one-line framing, rules each citing a CODE
1831
+ generated_by: {{generated_by}}, concern), a one-line framing, rules each citing a CODE
1453
1832
  COORDINATE (real file/folder path or named type) + the constitution principle numeral where
1454
1833
  it maps. The skeleton carries NO real technology — copy the shape only. State stubs/partials
1455
1834
  AS-BUILT (do not upgrade a stub into a greenfield ideal); omit a concern the code shows none
@@ -1480,12 +1859,12 @@ workflow:
1480
1859
  ONLY a heading you have a generated file for (an absent heading soft-continues → loads
1481
1860
  nothing):
1482
1861
  - `## /aw-spec-specify` — EXACTLY ONE bullet: `service/domain-modelling.md`, the modelling methodology. NEVER an architecture / persistence / codegen / security file here — specify is the domain phase and any technology rule under this heading breaks its domain purity. Omit the heading only if you did not write domain-modelling.md.
1483
- - `## /aw-spec-plan` — the as-built architecture / cross-cutting rules the design author mediates the spec against.
1862
+ - `## /aw-spec-plan` — the as-built architecture / cross-cutting rules the SERVICE lane's plan author mediates the spec against.
1484
1863
  - `## /aw-spec-implement` — the code-generation / convention set the SERVICE lane's generator builds against (from backend-plan.md).
1485
1864
  - `## /aw-spec-implement-delta` — the same set for the service lane on the DELTA path. `implement` is one command that keys this heading when it is generating a change's delta plan and the one above when it is generating the master, so a project that wants the same rules on both paths repeats them here.
1486
1865
  - `## /aw-spec-build` — the layering + convention rules the compile-fixer respects.
1487
- - `## /aw-spec-analyze-slice` — the conformance rules the design↔code gate validates against.
1488
- - `## /aw-spec-adopt` — the technical reference set the reversed design mediates against (a subset of design's).
1866
+ - `## /aw-spec-analyze-slice` — the conformance rules the plan↔code gate validates against.
1867
+ - `## /aw-spec-adopt` — the technical reference set the reversed plan mediates against (a subset of plan's).
1489
1868
  - `## /aw-spec-constitution` — the standards a later `/appweaver constitution` re-ratifies the TECHNICAL half from. You authored that half from code evidence before these files existed; this heading is what makes a re-run author from THIS project's rules rather than from an empty set. Ratifiable standards only, no worked `examples/` sample, no domain file.
1490
1869
  - `## /aw-spec-run` — the runtime / execution conventions the app-run step honors (add ONLY if the code evidences a runtime/hosting concern file; NOT data-migration — migration is the deferred later phase).
1491
1870
  Each bullet is a
@@ -1503,7 +1882,7 @@ workflow:
1503
1882
  on_empty: stop
1504
1883
  on_empty_message: "No technical rule files were written to guardrails/projects/{{domain_slug}}/service/. Ensure the scan substrate (inventory_json) + the validated technical constitution carry an as-built technology base and re-run."
1505
1884
  - id: require_tech_rule_bindings
1506
- condition: "{{author_repo}} == true"
1885
+ condition: "{{author_svc}} == true"
1507
1886
  action: verify_context
1508
1887
  required_files: ["{{pack_dir}}/tech-rule-bindings.md"]
1509
1888
 
@@ -1516,7 +1895,7 @@ workflow:
1516
1895
  # file, and the run's remaining work is worth keeping either way.
1517
1896
  - id: probe_specify_wiring
1518
1897
  action: execute_script
1519
- condition: "{{author_svc}} == true"
1898
+ condition: "{{svc_lane}} == true"
1520
1899
  on_error: continue
1521
1900
  script: { ref: actions }
1522
1901
  subcommand: resolve-tech
@@ -1525,7 +1904,7 @@ workflow:
1525
1904
  - { name: specify_rules, from: "$.candidates" }
1526
1905
  - id: warn_specify_wiring
1527
1906
  action: verify_context
1528
- condition: "{{author_svc}} == true"
1907
+ condition: "{{svc_lane}} == true"
1529
1908
  require_non_empty: specify_rules
1530
1909
  on_empty: continue
1531
1910
  on_empty_message: >
@@ -1542,18 +1921,20 @@ workflow:
1542
1921
  # enforceable rule ↓), exactly as service/ is the detail layer under the technical half.
1543
1922
  #
1544
1923
  # Runs AFTER the technical set because both write the SAME map file: the technical set
1545
- # authors tech-rule-bindings.md, and this step APPENDS the lane's heading to it. That
1546
- # heading is what makes a later /appweaver constitution re-ratify the UI half from
1547
- # THIS project's lane rules — and it is also the authoritative signal that the project
1548
- # HAS a frontend lane, so writing it is what lets the greenfield constitution command
1549
- # find the lane on every future run without stacks.json or a named stack.
1924
+ # authors tech-rule-bindings.md, and this step APPENDS the lane's three headings to it
1925
+ # (or creates the file, in a project with no service lane). `## /aw-spec-ui-constitution`
1926
+ # is what makes a later /appweaver constitution re-ratify the UI half from THIS project's
1927
+ # lane rules, and the authoritative signal that the project HAS a frontend lane.
1928
+ # `## /aw-spec-plan-ui` and `## /aw-spec-implement-ui` are what the frontend lane of
1929
+ # `plan` and of `implement` load; without them that lane plans and generates against no
1930
+ # project rule at all.
1550
1931
  - id: ctx_ui_pack
1551
1932
  action: build_context
1552
1933
  condition: "{{author_ui_flag}} == true"
1553
1934
  context:
1554
- - { path: "{{inventory_json}}" } # PRIMARY: the COMPLETE deterministic substrate — frontend_signals + the UI file lists to read source from
1935
+ - { path: "{{inventory_ui_json}}" } # PRIMARY: the substrate's UI view — frontend_signals + the UI file lists to read source from
1555
1936
  - { path: "{{constitution_ui_file}}" } # PRIMARY: the VALIDATED as-built UX-* base — the ratified principles these files detail
1556
- - { path: "{{pack_dir}}/tech-rule-bindings.md" } # the map to APPEND to — read it so the edit preserves what the technical set wrote
1937
+ - { path: "{{pack_dir}}/tech-rule-bindings.md", optional: true } # the map to APPEND to — absent only where no service lane is declared
1557
1938
  - { path: .appweaver/orchestrator/rev-templates/frontend-rule-file.skeleton.md, optional: true } # SHAPE ONLY: one code-derived lane rule file's shape (zero real UI tech)
1558
1939
  - { path: .appweaver/orchestrator/rev-templates/tech-rule-bindings.skeleton.md, optional: true } # SHAPE ONLY: the technical map's headings + partition + table
1559
1940
  - { path: .appweaver/RULE-PARTITION.md } # the rule-partition authority (which command reads what)
@@ -1573,7 +1954,7 @@ workflow:
1573
1954
 
1574
1955
  EVIDENCE = THE UI CODE ITSELF (deep read) + THE VALIDATED UI CONSTITUTION. Authority,
1575
1956
  in order:
1576
- 1. THE ACTUAL UI SOURCE (ground truth). Use {{inventory_json}} (in context):
1957
+ 1. THE ACTUAL UI SOURCE (ground truth). Use {{inventory_ui_json}} (in context):
1577
1958
  `frontend_signals` gives the lane roots, their kind, their framework markers and
1578
1959
  their component / route / store / style file lists. Read enough of those files to
1579
1960
  state each rule from what the UI ACTUALLY does. Do NOT assert a convention you
@@ -1589,7 +1970,7 @@ workflow:
1589
1970
  Every path you write lives under guardrails/projects/{{domain_slug}}/frontend/.
1590
1971
 
1591
1972
  EVIDENCED-ONLY (lean). Follow the SHAPE of frontend-rule-file.skeleton.md (in context):
1592
- frontmatter (origin: reverse-engineered, generated_by: aw-spec-onboard/1.6.0, concern),
1973
+ frontmatter (origin: reverse-engineered, generated_by: {{generated_by}}, concern),
1593
1974
  a one-line framing, then rules each citing a CODE COORDINATE (a real component / route /
1594
1975
  store / stylesheet / config path) and the UX principle numeral where it maps.
1595
1976
  - `frontend/ui-constitution.md` — ALWAYS, the lane's base file: the lane declaration
@@ -1605,24 +1986,29 @@ workflow:
1605
1986
  divergence with its coordinates. Do not upgrade a partial into a greenfield ideal, and
1606
1987
  do not create a debt/backlog sink — modernization is a separate later phase.
1607
1988
 
1608
- WIRE THE MAP — EDIT guardrails/projects/{{domain_slug}}/tech-rule-bindings.md IN PLACE.
1609
- It already exists and carries the technical headings you wrote; PRESERVE all of them
1610
- byte-for-byte. Make exactly two additions:
1611
- 1. A `## /aw-spec-ui-constitution` section, placed after the last technical heading
1612
- and BEFORE the closing quick-reference table. Bullet ONLY the frontend files you
1613
- just generated, `frontend/ui-constitution.md` first, each as a workspace-relative
1614
- path `- guardrails/projects/{{domain_slug}}/frontend/<file>`. Ratifiable lane
1615
- standards only — no domain file, no technical file, no example. Precede them with
1616
- a short HTML comment saying what this half ratifies and that the heading is also
1617
- the authoritative signal that the project has a frontend lane.
1618
- 2. Its row in the quick-reference table, in the same format as the existing rows.
1619
- Do NOT add `## /aw-spec-plan-ui` or `## /aw-spec-implement-ui` — the frontend lane's
1620
- headings in `plan` and `implement`. ⌛ Both phases DO exist now, but those two headings
1621
- are a different TIER from the one you just wrote: `## /aw-spec-ui-constitution` maps the
1622
- lane's RATIFIABLE standards, and those two map its per-phase authoring and
1623
- code-generation sets. The files above have not been separated into those tiers, and
1624
- mapping one file under a heading of the wrong tier is what makes a generator obey a
1625
- standard nobody ratified. Splitting them is the UI lane's own follow-up.
1989
+ WIRE THE MAP — guardrails/projects/{{domain_slug}}/tech-rule-bindings.md. Where the
1990
+ service rule set was generated it exists and carries the technical headings: EDIT IT IN
1991
+ PLACE and PRESERVE every one of them byte-for-byte. Where this project has no service
1992
+ lane it does not exist yet: CREATE it with the skeleton's title and framing and only the
1993
+ headings below. Add the lane's THREE headings after the last technical heading and
1994
+ BEFORE the closing quick-reference table. Every bullet is a workspace-relative path
1995
+ `- guardrails/projects/{{domain_slug}}/frontend/<file>` naming a file you just generated:
1996
+ 1. `## /aw-spec-ui-constitution` — the lane's RATIFIABLE standards,
1997
+ `frontend/ui-constitution.md` first. It is what a later /appweaver constitution
1998
+ re-ratifies the UI half from, and the authoritative signal that the project has a
1999
+ frontend lane; precede the bullets with a short HTML comment saying both.
2000
+ 2. `## /aw-spec-plan-ui` — the files the FRONTEND lane of `plan` authors
2001
+ frontend-plan.md against: those whose rules decide a feature's screens, navigation,
2002
+ client state, interaction states, forms, accessibility and service binding.
2003
+ 3. `## /aw-spec-implement-ui` — the files the FRONTEND lane of `implement` generates
2004
+ code against, on the master and the delta path alike: those whose rules govern
2005
+ component conventions, state and data fetching, styling, forms and UI tests.
2006
+ A file whose rules carry both a planning half and a generating half is listed under both
2007
+ 2 and 3 — a rule read by only one of the two phases loses its other half. Do NOT list
2008
+ `frontend/ui-constitution.md` under 2 or 3: it is the source the UI half is ratified
2009
+ from, and both phases already read that half (constitution.ui.md) directly. No domain
2010
+ file, no service/ file and no example under any of the three. Give each heading its row
2011
+ in the quick-reference table, in the same format as the existing rows.
1626
2012
 
1627
2013
  Write ONLY inside guardrails/projects/{{domain_slug}}/ (frontend/ + the map edit); modify
1628
2014
  no source. Report the files written, the concerns you found present with the code paths
@@ -1634,6 +2020,7 @@ workflow:
1634
2020
  action: verify_context
1635
2021
  condition: "{{author_ui_flag}} == true"
1636
2022
  require_non_empty: ui_pack_files
2023
+ required_files: ["{{pack_dir}}/frontend/ui-constitution.md", "{{pack_dir}}/tech-rule-bindings.md"]
1637
2024
  on_empty: stop
1638
2025
  on_empty_message: "A frontend lane was detected ({{ui_evidence}}) but no lane rule files were written to guardrails/projects/{{domain_slug}}/frontend/. Check that the scan substrate's frontend_signals carry readable UI source, then re-run."
1639
2026
 
@@ -1644,7 +2031,7 @@ workflow:
1644
2031
  # it. Announce, don't stop — the rule files are on disk and the heading is one edit away.
1645
2032
  - id: probe_ui_wiring
1646
2033
  action: execute_script
1647
- condition: "{{author_ui_flag}} == true"
2034
+ condition: "{{ui_lane}} == true"
1648
2035
  on_error: continue
1649
2036
  script: { ref: actions }
1650
2037
  subcommand: resolve-tech
@@ -1653,7 +2040,7 @@ workflow:
1653
2040
  - { name: ui_map_rules, from: "$.candidates" }
1654
2041
  - id: warn_ui_wiring
1655
2042
  action: verify_context
1656
- condition: "{{author_ui_flag}} == true"
2043
+ condition: "{{ui_lane}} == true"
1657
2044
  require_non_empty: ui_map_rules
1658
2045
  on_empty: continue
1659
2046
  on_empty_message: >
@@ -1664,6 +2051,48 @@ workflow:
1664
2051
  project as backend-only. Add the heading after the last technical one, bulleting
1665
2052
  frontend/ui-constitution.md first, then the rest of the frontend/ set.
1666
2053
 
2054
+ # The same read-back for the two headings the frontend lane's PHASES key on. Empty
2055
+ # means that lane of `plan` / `implement` runs with the ratified UX-* base and no
2056
+ # project rule file at all.
2057
+ - id: probe_ui_plan_wiring
2058
+ action: execute_script
2059
+ condition: "{{ui_lane}} == true"
2060
+ on_error: continue
2061
+ script: { ref: actions }
2062
+ subcommand: resolve-tech
2063
+ args: ["--command", "aw-spec-plan-ui"]
2064
+ outputs:
2065
+ - { name: ui_plan_rules, from: "$.candidates" }
2066
+ - id: warn_ui_plan_wiring
2067
+ action: verify_context
2068
+ condition: "{{ui_lane}} == true"
2069
+ require_non_empty: ui_plan_rules
2070
+ on_empty: continue
2071
+ on_empty_message: >
2072
+ guardrails/projects/{{domain_slug}}/tech-rule-bindings.md maps nothing under
2073
+ `## /aw-spec-plan-ui`, so the frontend lane of /appweaver plan will author
2074
+ frontend-plan.md with no project rule file. Add the heading, bulleting the
2075
+ frontend/ files whose rules shape a feature's screens, state and interactions.
2076
+ - id: probe_ui_impl_wiring
2077
+ action: execute_script
2078
+ condition: "{{ui_lane}} == true"
2079
+ on_error: continue
2080
+ script: { ref: actions }
2081
+ subcommand: resolve-tech
2082
+ args: ["--command", "aw-spec-implement-ui"]
2083
+ outputs:
2084
+ - { name: ui_impl_rules, from: "$.candidates" }
2085
+ - id: warn_ui_impl_wiring
2086
+ action: verify_context
2087
+ condition: "{{ui_lane}} == true"
2088
+ require_non_empty: ui_impl_rules
2089
+ on_empty: continue
2090
+ on_empty_message: >
2091
+ guardrails/projects/{{domain_slug}}/tech-rule-bindings.md maps nothing under
2092
+ `## /aw-spec-implement-ui`, so the frontend lane of /appweaver implement will
2093
+ generate UI code with no project rule file. Add the heading, bulleting the
2094
+ frontend/ files whose rules govern component, state, styling and test conventions.
2095
+
1667
2096
  # ═══════════ LANE DECLARATION — read back, never written ═══════════════════════
1668
2097
  # onboard does not declare lanes. It used to: before select-stack was the first
1669
2098
  # command of this sequence, a repo could arrive here with no declaration at all, so
@@ -1681,7 +2110,6 @@ workflow:
1681
2110
  # the run reports the lanes it actually scanned under rather than a second opinion
1682
2111
  # about them.
1683
2112
  - id: lane_readback
1684
- condition: "{{author_repo}} == true"
1685
2113
  action: execute_script
1686
2114
  on_error: continue
1687
2115
  script: { ref: actions }
@@ -1702,11 +2130,11 @@ workflow:
1702
2130
  # DESIGN CONVENTION by REVERSE-ENGINEERING its own technical structure into a project-
1703
2131
  # specific design + delta-design template pair, written to the PROJECT-LEVEL override slot
1704
2132
  # (.appweaver/templates/overrides/{design,delta-design}-template.md — resolve_template
1705
- # Priority-1). The forward `design` phase's brownfield branch (design-scaffold reports
1706
- # override_active ⇒ design_mode == bootstrap_bf) then authors EVERY new feature against the
1707
- # as-built architecture, and a CHANGE authors its delta-design against the SAME code-derived
1708
- # sections (cr-setup scaffolds the delta from resolve_template("delta-design-template") ⇒
1709
- # the override) — no adopt required, consistent with the backend-plan.md adopt emits.
2133
+ # Priority-1). The service lane of `plan` (plan-scaffold reports override_active ⇒
2134
+ # be_mode == bootstrap_bf) then authors EVERY new feature's backend-plan.md against the
2135
+ # as-built architecture, and a CHANGE authors its delta plan against the SAME code-derived
2136
+ # sections (delta-plan-scaffold resolves "delta-design-template" ⇒ the override) — no adopt
2137
+ # required, consistent with the backend-plan.md adopt emits.
1710
2138
  #
1711
2139
  # THE TEMPLATE IDENTIFIERS KEEP THE `design-template` SPELLING DELIBERATELY. The DOCUMENTS
1712
2140
  # are backend-plan.md / frontend-plan.md now; the template NAMES are not, because a repo
@@ -1728,14 +2156,15 @@ workflow:
1728
2156
  # (header block, the §1.2 domain/data-model anchor, the traceability spine, the two
1729
2157
  # deferral ledgers, Change History, the tech-agnostic authoring rules) with the layering
1730
2158
  # removed and every structural section left as a slot the code fills. The generated
1731
- # template keeps the §0–§6 shape the forward `design` bootstrap_bf branch expects and the
1732
- # two anchors aw-xref keys on, so no workflow change is needed to consume it.
2159
+ # template keeps the §0–§6 shape `plan`'s bootstrap_bf branch expects and the two
2160
+ # anchors aw-xref keys on, so no workflow change is needed to consume it.
1733
2161
  #
1734
2162
  # WHERE A FRONTEND LANE EXISTS the lane gets its OWN pair (ui-design-template +
1735
2163
  # ui-delta-design-template, below), so this pair covers the SERVICE lane only and excludes
1736
2164
  # the lane's roots from the structure it derives. One lane's template never describes the
1737
- # other's code. Re-onboard is gated upstream (bundle_guard / pack_guard) — remove the OKF
1738
- # bundle to regenerate.
2165
+ # other's code. The templates are authored when their lane's tier is first authored — by
2166
+ # the first context, or by the run that first sees a lane declared later — and are never
2167
+ # amended: every plan already written follows their shape.
1739
2168
 
1740
2169
  # DESIGN template — the code-derived evidence (code + inventory + technical constitution)
1741
2170
  # plus a NEUTRAL skeleton for the bones. No greenfield template is in context.
@@ -1743,7 +2172,7 @@ workflow:
1743
2172
  action: build_context
1744
2173
  condition: "{{author_svc}} == true"
1745
2174
  context:
1746
- - { path: "{{inventory_json}}" } # PRIMARY: the COMPLETE deterministic substrate (top_level_dirs, aggregate_signals' per-layer file groupings) — the OKF markdown only SUMMARISES this
2175
+ - { path: "{{inventory_service_json}}" } # PRIMARY: the substrate's service view (top_level_dirs, aggregate_signals' per-layer file groupings) — the OKF markdown only SUMMARISES this
1747
2176
  - { path: "{{constitution_technical_file}}" } # PRIMARY: the VALIDATED as-built technology base (framework/persistence/concurrency/hosting/testing/cross-cutting)
1748
2177
  - { path: .appweaver/orchestrator/rev-templates/design-template.skeleton.md } # SHAPE ONLY: the neutral bones + the pinned anchors + tech-agnostic authoring rules (zero layering, zero technology)
1749
2178
  - { path: .appweaver/DESIGN-FORMAT.md } # the HLD contract + its Brownfield variant note (which anchors are pinned, and why)
@@ -1759,16 +2188,16 @@ workflow:
1759
2188
  REVERSE-ENGINEER this repo's design convention into a PROJECT-SPECIFIC design
1760
2189
  TEMPLATE and Write it to .appweaver/templates/overrides/design-template.md (create the
1761
2190
  overrides/ dir if absent). It is a TEMPLATE — concrete project-derived section HEADERS
1762
- with [PLACEHOLDER] tokens + authoring HTML comments the forward `design` phase fills
1763
- per feature — NOT a filled design.
2191
+ with [PLACEHOLDER] tokens + authoring HTML comments the service lane of `plan` fills
2192
+ per feature into specs/<Context>/<Feature>/backend-plan.md — NOT a filled plan.
1764
2193
 
1765
2194
  GROUND EVERYTHING IN THE CODE + THE REVERSE-ENGINEERED FILES — not the shallow OKF map
1766
2195
  and not any architecture you know from elsewhere. Evidence authority, in order:
1767
2196
  1. THE ACTUAL SOURCE CODE (ground truth). Read REPRESENTATIVE source files across the
1768
- repo's top_level_dirs and a few aggregate_signals (from {{inventory_json}}) — enough
2197
+ repo's top_level_dirs and a few aggregate_signals (from {{inventory_service_json}}) — enough
1769
2198
  to CONFIRM from the code the recurring folder/tier/module convention + the dependency
1770
2199
  direction it actually follows. Do NOT assert structure you have not seen in the code.
1771
- 2. {{inventory_json}} — the COMPLETE deterministic scan substrate (top_level_dirs, each
2200
+ 2. {{inventory_service_json}} — the deterministic scan substrate's service view (top_level_dirs, each
1772
2201
  aggregate_signal's files grouped by layer, categories, tech stack). The OKF markdown
1773
2202
  only SUMMARISES this, shallowly — prefer the substrate + the code over it.
1774
2203
  3. The TECHNICAL CONSTITUTION (constitution.technical.md, in context) — the VALIDATED
@@ -1796,10 +2225,10 @@ workflow:
1796
2225
  folders + the dependency rule) from evidence 1–3 — this ONE template governs every
1797
2226
  future feature.
1798
2227
 
1799
- Then AUTHOR the template on the skeleton's §0–§6 shape (the shape the forward `design`
1800
- brownfield branch expects — keep these section numbers + headings):
1801
- - Keep the skeleton's header block (Aggregate / Design home / Source spec / Version /
1802
- Status) and its TECHNOLOGY-AGNOSTIC authoring rules (behaviour as signatures +
2228
+ Then AUTHOR the template on the skeleton's §0–§6 shape (the shape `plan`'s
2229
+ bootstrap_bf branch expects — keep these section numbers + headings):
2230
+ - Keep the skeleton's header block (Feature / Plan home / Source spec / Source model /
2231
+ Version / Status) and its TECHNOLOGY-AGNOSTIC authoring rules (behaviour as signatures +
1803
2232
  pre/post/invariant/raises, contracts as field shapes, NO code; every element traces to
1804
2233
  a spec id). Fill [GENERATED_STRUCTURE_NOTE] with this project's convention.
1805
2234
  - §0 Design Overview + `### Ubiquitous Language (design delta)` — carry over as-is.
@@ -1829,8 +2258,8 @@ workflow:
1829
2258
  deviations, NOT "organised unlike a reference architecture" (that is the as-built
1830
2259
  shape, §1.1).
1831
2260
  - Change History — carry over.
1832
- Keep every [PLACEHOLDER] and authoring comment so `design` can fill it — and in those
1833
- comments DIRECT the downstream author (forward `design` / adopt) to GROUND each filled
2261
+ Keep every [PLACEHOLDER] and authoring comment so `plan` can fill it — and in those
2262
+ comments DIRECT the downstream author (`plan` / adopt) to GROUND each filled
1834
2263
  section in the ACTUAL CODE + the reverse-engineered files (cite real file/folder paths and
1835
2264
  the relevant technical-constitution principle). Do NOT invent project structure the code
1836
2265
  does not show; where the convention is unclear, template a generic axis and flag it in a
@@ -1844,12 +2273,13 @@ workflow:
1844
2273
  action: verify_context
1845
2274
  condition: "{{author_svc}} == true"
1846
2275
  require_non_empty: design_template_files
2276
+ required_files: [".appweaver/templates/overrides/design-template.md"]
1847
2277
  on_empty: stop
1848
2278
  on_empty_message: "No design template was written to .appweaver/templates/overrides/design-template.md. Ensure the scan substrate (inventory_json) + the technical constitution are present and re-run."
1849
2279
 
1850
2280
  # DELTA-DESIGN template — MIRROR the just-generated master template's OWN sections so a
1851
2281
  # change classifies ADDED/MODIFIED/REMOVED against the code-derived structure, not the
1852
- # greenfield four layers. Aligns with the delta-design module (classifies "per the
2282
+ # greenfield four layers. Aligns with the delta-plan module (classifies "per the
1853
2283
  # master's OWN section structure").
1854
2284
  - id: ctx_delta_design_template
1855
2285
  action: build_context
@@ -1867,20 +2297,21 @@ workflow:
1867
2297
  Author the matching PROJECT-SPECIFIC DELTA-design TEMPLATE and Write it to
1868
2298
  .appweaver/templates/overrides/delta-design-template.md. It is a TEMPLATE (placeholders
1869
2299
  + authoring comments) for classifying a CHANGE to a feature as ADDED / MODIFIED /
1870
- REMOVED against the master design.md.
2300
+ REMOVED against the master backend-plan.md.
1871
2301
 
1872
2302
  MIRROR the just-generated master template (.appweaver/templates/overrides/design-template.md,
1873
2303
  in context — Read it): its ADDED/MODIFIED/REMOVED tables must key off the master's OWN
1874
2304
  code-derived sections (§1.1/§1.2, the §2.n axes it derived, §3). Use the skeleton's
1875
- "Section (§ in design.md)" column and fill its example rows with the ACTUAL sections of
2305
+ "Section (§ in backend-plan.md)" column and fill its example rows with the ACTUAL sections of
1876
2306
  the generated master template. Never name a layering — neither one you know nor one the
1877
2307
  master did not derive.
1878
2308
  - CARRY OVER the neutral parts of rev-templates/delta-design-template.skeleton.md (in
1879
2309
  context): Change summary, Cross-section impact, Regression targets, New assumptions/
1880
- deviations (DA-n / WA-n), On close. Keep behaviour technology-agnostic (signatures +
2310
+ deviations (DA-n / WA-n), On merge — word for word: finalize-delta merges the spec and
2311
+ the model, never this plan, which `plan main` re-derives. Keep behaviour technology-agnostic (signatures +
1881
2312
  contracts, no code); a shared element is MODIFIED in place, never duplicated; every
1882
2313
  changed element serves a spec id.
1883
- - This aligns with the delta-design module, which classifies "per the master's OWN
2314
+ - This aligns with the delta-plan module, which classifies "per the master's OWN
1884
2315
  section structure" — so the template MUST NOT hardcode a fixed layering.
1885
2316
  Keep every [PLACEHOLDER] and authoring comment. Write ONLY the override file; modify no
1886
2317
  source. Report the file written.
@@ -1891,6 +2322,7 @@ workflow:
1891
2322
  action: verify_context
1892
2323
  condition: "{{author_svc}} == true"
1893
2324
  require_non_empty: delta_design_template_files
2325
+ required_files: [".appweaver/templates/overrides/delta-design-template.md"]
1894
2326
  on_empty: stop
1895
2327
  on_empty_message: "No delta-design template was written to .appweaver/templates/overrides/delta-design-template.md. Re-run onboard after confirming the design template override was generated."
1896
2328
 
@@ -1971,6 +2403,7 @@ workflow:
1971
2403
  condition: "{{author_repo}} == true"
1972
2404
  action: verify_context
1973
2405
  require_non_empty: model_template_files
2406
+ required_files: [".appweaver/templates/overrides/domain-model-template.md"]
1974
2407
  on_empty: stop
1975
2408
  on_empty_message: "No domain-model template was written to .appweaver/templates/overrides/domain-model-template.md. Without it every reversed slice authors its aggregate against the kit's GREENFIELD model template, whose shape assumes a domain designed before it was built. Ensure the scan substrate (inventory_json) is present and re-run."
1976
2409
 
@@ -1984,12 +2417,13 @@ workflow:
1984
2417
  # WHY THE LANE NEEDS ITS OWN PAIR rather than a section inside the service design: the
1985
2418
  # two lanes are governed by different constitution halves and different map headings,
1986
2419
  # they are implemented by different commands, and the ONLY thing that crosses between
1987
- # them is the design contract. A UI section inside design.md would put the lane's
1988
- # structure under the service lane's rules and hand ⌛ ui-design the whole service
1989
- # design to read — precisely the context leak the contract projection exists to stop.
2420
+ # them is the service's published surface. A UI section inside backend-plan.md would put
2421
+ # the lane's structure under the service lane's rules and hand the frontend lane of `plan`
2422
+ # the whole backend plan to read — precisely the leak §5's published-surface boundary
2423
+ # exists to stop.
1990
2424
  #
1991
2425
  # THE SECTION LIST IS RATIFIED, THE CONTENT IS THE CODE'S. aw-spec specifies what
1992
- # design.ui.md contains (navigation & screen structure · client state · component
2426
+ # frontend-plan.md contains (navigation & screen structure · client state · component
1993
2427
  # structure · interaction & flow · contract binding · cross-cutting · traceability ·
1994
2428
  # DA-n · WA-n); the skeleton carries exactly that, framework-free. What this step
1995
2429
  # derives from the lane's source is what goes IN those sections — the real composition
@@ -1998,13 +2432,13 @@ workflow:
1998
2432
  # THE CONSUMERS ARE BUILT: the frontend lane of `plan` scaffolds from this override when
1999
2433
  # onboard installed one (plan-scaffold reports override_active), and the frontend lane of
2000
2434
  # `implement` generates from the plan it produced. The templates are written HERE because
2001
- # the evidence for them is the whole-repo vantage that exists exactly once, at onboard, and
2002
- # nothing breaks for their absence in a repo that never onboarded.
2435
+ # the evidence for them is onboard's whole-repo scan, and nothing breaks for their absence
2436
+ # in a repo that never onboarded.
2003
2437
  - id: ctx_ui_design_template
2004
2438
  action: build_context
2005
2439
  condition: "{{author_ui_flag}} == true"
2006
2440
  context:
2007
- - { path: "{{inventory_json}}" } # PRIMARY: the COMPLETE deterministic substrate — frontend_signals + the component/route/store/style file lists to read source from
2441
+ - { path: "{{inventory_ui_json}}" } # PRIMARY: the substrate's UI view — frontend_signals + the component/route/store/style file lists to read source from
2008
2442
  - { path: "{{constitution_ui_file}}" } # PRIMARY: the VALIDATED as-built UX-* base — the ratified principles this structure must serve
2009
2443
  - { path: .appweaver/orchestrator/rev-templates/ui-design-template.skeleton.md } # SHAPE ONLY: the ratified section list + neutral bones (zero framework, zero component library)
2010
2444
  - { path: "{{pack_dir}}/frontend/ui-constitution.md", optional: true } # the generated lane rule set's base file — the detail layer under those principles
@@ -2018,12 +2452,12 @@ workflow:
2018
2452
  REVERSE-ENGINEER this repo's FRONTEND LANE into a PROJECT-SPECIFIC UI DESIGN TEMPLATE
2019
2453
  and Write it to .appweaver/templates/overrides/ui-design-template.md (create the
2020
2454
  overrides/ dir if absent). It is a TEMPLATE — concrete lane-derived section content
2021
- with [PLACEHOLDER] tokens + authoring HTML comments that ⌛ `ui-design` fills per
2022
- feature into specs/<Feature>/design.ui.md — NOT a filled design.
2455
+ with [PLACEHOLDER] tokens + authoring HTML comments that the frontend lane of `plan`
2456
+ fills per feature into specs/<Context>/<Feature>/frontend-plan.md — NOT a filled plan.
2023
2457
  The lane: {{ui_evidence}} · roots: {{frontend_roots}}
2024
2458
 
2025
2459
  GROUND EVERYTHING IN THE LANE'S OWN CODE. Evidence authority, in order:
2026
- 1. THE ACTUAL UI SOURCE (ground truth). Use {{inventory_json}} (in context):
2460
+ 1. THE ACTUAL UI SOURCE (ground truth). Use {{inventory_ui_json}} (in context):
2027
2461
  `frontend_signals` gives the lane roots, their kind (spa / server-rendered /
2028
2462
  desktop), their framework markers and their component / route / store / style
2029
2463
  file lists. READ ENOUGH OF THOSE FILES to state each structural claim from what
@@ -2070,13 +2504,14 @@ workflow:
2070
2504
  shows little. They are the two sections a backend-shaped process drops and where
2071
2505
  most UI defects live. Where the code handles no error or empty state, template the
2072
2506
  section so the downstream author must record that as-built — never delete it.
2073
- - §5 Contract Binding — keep the lane boundary intact: the binding table reads the
2074
- ⌛ design-contract projection, never the service design. Note in the authoring
2075
- comment that where no contract document exists yet the author binds against the
2076
- spec's own IC-/FR- surface and logs a §8 assumption.
2507
+ - §5 Contract Binding — keep the lane boundary intact: the binding table binds
2508
+ against the service's PUBLISHED SURFACE (the spec's IC- ids and the API contracts
2509
+ backend-plan.md states), never the service's internals. Note in the authoring
2510
+ comment that where the surface does not name an operation yet, the author binds
2511
+ against the spec's own IC-/FR- surface and logs a §8 assumption.
2077
2512
  - §7 Traceability, §8 Assumptions (DA-n), §9 Deviations (WA-n), Change History — carry
2078
2513
  over; the §7 Section column uses THIS template's own section refs.
2079
- Keep every [PLACEHOLDER] and authoring comment so ⌛ `ui-design` can fill it — and in
2514
+ Keep every [PLACEHOLDER] and authoring comment so `plan` can fill it — and in
2080
2515
  those comments DIRECT the downstream author to GROUND each filled section in the
2081
2516
  ACTUAL UI CODE and the lane's governance (cite real component/route/store/stylesheet
2082
2517
  paths and the constitution.ui.md UX numeral). Do NOT invent lane structure the code
@@ -2091,6 +2526,7 @@ workflow:
2091
2526
  action: verify_context
2092
2527
  condition: "{{author_ui_flag}} == true"
2093
2528
  require_non_empty: ui_design_template_files
2529
+ required_files: [".appweaver/templates/overrides/ui-design-template.md"]
2094
2530
  on_empty: stop
2095
2531
  on_empty_message: "A frontend lane was detected ({{ui_evidence}}) but no UI design template was written to .appweaver/templates/overrides/ui-design-template.md. Check that the scan substrate's frontend_signals carry readable UI source, then re-run."
2096
2532
 
@@ -2112,18 +2548,19 @@ workflow:
2112
2548
  Author the matching PROJECT-SPECIFIC UI DELTA-design TEMPLATE and Write it to
2113
2549
  .appweaver/templates/overrides/ui-delta-design-template.md. It is a TEMPLATE
2114
2550
  (placeholders + authoring comments) for classifying a CHANGE to a feature's
2115
- EXPERIENCE as ADDED / MODIFIED / REMOVED against the master design.ui.md.
2551
+ EXPERIENCE as ADDED / MODIFIED / REMOVED against the master frontend-plan.md.
2116
2552
 
2117
2553
  MIRROR the just-generated lane master (.appweaver/templates/overrides/ui-design-template.md,
2118
2554
  in context — Read it): its ADDED/MODIFIED/REMOVED tables must key off that master's OWN
2119
2555
  sections, including whatever composition axes its §3 derived. Use the skeleton's
2120
- "Section (§ in design.ui.md)" column and fill its example rows with the ACTUAL sections
2556
+ "Section (§ in frontend-plan.md)" column and fill its example rows with the ACTUAL sections
2121
2557
  of the generated master. Never name a framework or a UI taxonomy the master did not
2122
2558
  derive.
2123
2559
  - CARRY OVER the neutral parts of rev-templates/ui-delta-design-template.skeleton.md
2124
2560
  (in context): Change summary, Interaction states touched, Contract impact,
2125
2561
  Cross-section impact, Regression targets, New assumptions/deviations (DA-n / WA-n),
2126
- On close.
2562
+ On merge — word for word: finalize-delta merges the spec and the model, never this
2563
+ plan, which `plan main` re-derives.
2127
2564
  - KEEP the "Interaction states touched" section whatever this lane's code shows: a new
2128
2565
  interaction that ships without its loading, empty, error and permission-denied states
2129
2566
  is an incomplete delta, and the template is where that is enforced.
@@ -2141,6 +2578,7 @@ workflow:
2141
2578
  action: verify_context
2142
2579
  condition: "{{author_ui_flag}} == true"
2143
2580
  require_non_empty: ui_delta_design_template_files
2581
+ required_files: [".appweaver/templates/overrides/ui-delta-design-template.md"]
2144
2582
  on_empty: stop
2145
2583
  on_empty_message: "No UI delta-design template was written to .appweaver/templates/overrides/ui-delta-design-template.md. Re-run onboard after confirming the UI design template override was generated."
2146
2584
 
@@ -2210,4 +2648,11 @@ outputs:
2210
2648
  ui_delta_design_template_files: "{{ui_delta_design_template_files}}"
2211
2649
  technical_validation_ok: "{{technical_ok}}"
2212
2650
  domain_validation_ok: "{{domain_ok}}"
2213
- next: "Onboarded bounded context {{bc}} ({{bc_feature_count}} feature(s): {{bc_features}}). Its aggregate concepts ({{bc_aggregates}}) are in {{bundle_dir}}, each keyed `bounded_context: {{bc}}` and listing the features that act on it — the bundle is the project's knowledge, one concept per aggregate, never one per feature — and its specs tree now exists at {{bc_dir}}/ with a directory per feature ({{feature_dirs}}) — EMPTY on purpose: the directory says the feature is known, and the documents that describe it are written per feature by /appweaver adopt and per context by /appweaver specify. {{bc}} is now the ACTIVE bounded context (.appweaver/context.json), so /appweaver select-feature lists exactly these features and nothing from a neighbouring context; switch with /appweaver select-bounded-context. ONBOARD RUNS ONCE PER CONTEXT: contexts already done — {{onboarded_contexts}}; still open — {{remaining_contexts}}; the order the map gives is {{contexts_ordered}}. Run /appweaver onboard <NextContext> for each remaining one, or with no argument to take the next one automatically. THE PROJECT TIER IS WRITTEN ONCE, BY THE FIRST CONTEXT (this run was first: {{is_first}}). That tier is the PROVISIONAL governance scaffold — the split constitution, the domain rule set at guardrails/projects/{{domain_slug}}/domain/*.domain.md + domain-rule-bindings.md, each declared LANE\'s rule set and constitution half, the activated domain {{active_domain}}, and the code-derived design / delta-design / domain-model template overrides in .appweaver/templates/overrides/. A later context does NOT re-author any of it: re-deriving project principles from one context\'s evidence is the scoping bias the governance tier exists to avoid. Amend it with /appweaver constitution. ONE HALF AND ONE RULE SET PER LANE: service_lane / ui_lane report which lanes .appweaver/stacks.json declared, and the declaration is what decided. A lane declared (none) in select-stack gets none of it, which is the correct outcome and not an omission. LANE DECLARATION: read, never written — select-stack is its sole writer, and this run scanned the source paths it named (scanned_service_root / scanned_ui_root); scanned_backend_files / scanned_ui_files report each. ui_source_evidence_found false means the UI lane\'s declared path held nothing a scan recognises as UI, so its governance is thin — move the source path with /appweaver select-stack and re-run. The build/test/run commands on each lane are that PROFILE\'s defaults and may not match a legacy layout — review them. Because the domain is activated, resolve-domain + resolve-tech route the WHOLE forward pipeline to these code-derived rules — never another project\'s rules as a fallback. THE BOUNDARIES CAME FROM THE MAP, not from this run: /appweaver inventory proposed them and you confirmed them in specs/proposed-inventory.md. To change a boundary, edit that file and run /appweaver inventory apply — a context whose concepts already exist is not re-onboarded. Develop an EXISTING feature just-in-time: /appweaver adopt <Feature> reverse-engineers its spec.md + backend-plan.md + source-map.md and deepens the OKF concept of the aggregate it acts on. Develop a NEW feature straight through the forward pipeline — /appweaver select-feature FIRST (specify and every stage after it read the active feature and STOP without one), then specify → plan → analyze-plan → implement → build → analyze-slice → run. Then drive every change through the CR delta loop (/appweaver specify → plan → analyze-plan-delta → implement → build → analyze-slice-delta → finalize-delta → analyze-slice → close-delta). If a validation_ok is false, its constitution half needs a manual touch (see its Sync Impact Report)."
2651
+ # Authored (the first context, or a lane tier that did not exist) or amended (a later
2652
+ # context adding its evidence), and what each amendment step changed — empty when the
2653
+ # tier already covered this context.
2654
+ governance_mode: "{{gov_mode}}"
2655
+ amended_domain_files: "{{amended_domain_files}}"
2656
+ amended_service_files: "{{amended_service_files}}"
2657
+ amended_ui_files: "{{amended_ui_files}}"
2658
+ next: "Onboarded bounded context {{bc}} ({{bc_feature_count}} feature(s): {{bc_features}}). Its aggregate concepts ({{bc_aggregates}}) are in {{bundle_dir}}, each keyed `bounded_context: {{bc}}` and listing the features that act on it — the bundle is the project's knowledge, one concept per aggregate, never one per feature — and its specs tree now exists at {{bc_dir}}/ with a directory per feature ({{feature_dirs}}) — EMPTY on purpose: the directory says the feature is known, and the documents that describe it are written per feature by /appweaver adopt and per context by /appweaver specify. {{bc}} is now the ACTIVE bounded context (.appweaver/context.json), so /appweaver select-feature lists exactly these features and nothing from a neighbouring context; switch with /appweaver select-bounded-context. ONBOARD RUNS ONCE PER CONTEXT: contexts already done — {{onboarded_contexts}}; still open — {{remaining_contexts}}; the order the map gives is {{contexts_ordered}}. Run /appweaver onboard <NextContext> for each remaining one, or with no argument to take the next one automatically. GOVERNANCE — {{gov_mode}}. The project tier is the PROVISIONAL governance scaffold — the split constitution, the domain rule set at guardrails/projects/{{domain_slug}}/domain/*.domain.md + domain-rule-bindings.md, each declared LANE's rule set and constitution half, the activated domain {{active_domain}}, and the code-derived design / delta-design / domain-model template overrides in .appweaver/templates/overrides/. The first context authors it; every later context AMENDS it from its own code, additively — rules, principles and map entries its code evidences, never a rewrite, renumbering or deletion of what an earlier context wrote — and a lane tier that did not exist yet is authored in full. Files this run amended — domain: {{amended_domain_files}}; service: {{amended_service_files}}; frontend: {{amended_ui_files}}. Search them for `Divergence ({{bc}})`: each marks a rule this context's code contradicts, left as written for you to decide with /appweaver constitution, which is also how you amend the tier by hand. The templates are written once per lane and never amended. To re-run this governance pass later — after declaring a lane with /appweaver select-stack, say — name an onboarded context: /appweaver onboard <Context>. ONE HALF AND ONE RULE SET PER LANE: service_lane / ui_lane report which lanes .appweaver/stacks.json declared, and the declaration is what decided. A lane declared (none) in select-stack gets none of it, which is the correct outcome and not an omission. LANE DECLARATION: read, never written — select-stack is its sole writer, and this run scanned the source paths it named (scanned_service_root / scanned_ui_root); scanned_backend_files / scanned_ui_files report each. ui_source_evidence_found false means the UI lane's declared path held nothing a scan recognises as UI, so its governance is thin — move the source path with /appweaver select-stack and re-run. The build/test/run commands on each lane are that PROFILE's defaults and may not match a legacy layout — review them. Because the domain is activated, resolve-domain + resolve-tech route the WHOLE forward pipeline to these code-derived rules — never another project's rules as a fallback. THE BOUNDARIES CAME FROM THE MAP, not from this run: /appweaver inventory proposed them and you confirmed them in specs/proposed-inventory.md. To change a boundary, edit that file and run /appweaver inventory apply — a context whose concepts already exist is not re-mapped; naming it re-runs only its governance pass. Develop an EXISTING feature just-in-time: /appweaver adopt <Feature> reverse-engineers its spec.md + backend-plan.md + source-map.md and deepens the OKF concept of the aggregate it acts on. Develop a NEW feature straight through the forward pipeline — /appweaver select-feature FIRST (specify and every stage after it read the active feature and STOP without one), then specify → plan → analyze-plan → implement → build → analyze-slice → run. Then drive every change through the CR delta loop (/appweaver specify → plan → analyze-plan-delta → implement → build → analyze-slice-delta → finalize-delta → analyze-slice → close-delta), and re-derive the master plans after it with /appweaver plan main → analyze-plan — finalize-delta merges a change into spec.md and domain-model.md, never into the plans. If a validation_ok is false, its constitution half needs a manual touch (see its Sync Impact Report)."