aw-spec-cli 0.1.18 → 0.1.19

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 (53) hide show
  1. package/assets/.appweaver/DESIGN-FORMAT.md +45 -21
  2. package/assets/.appweaver/orchestrator/modules/delta-plan.orch.yaml +62 -14
  3. package/assets/.appweaver/orchestrator/modules/delta-spec.orch.yaml +6 -4
  4. package/assets/.appweaver/orchestrator/modules/lane-gate.orch.yaml +9 -1
  5. package/assets/.appweaver/orchestrator/modules/tech-select.orch.yaml +21 -0
  6. package/assets/.appweaver/orchestrator/orchestrator.py +23 -1
  7. package/assets/.appweaver/orchestrator/rev-templates/design-template.skeleton.md +18 -11
  8. package/assets/.appweaver/orchestrator/rev-templates/ui-design-template.skeleton.md +5 -3
  9. package/assets/.appweaver/orchestrator/workflows/aw-spec-adopt.orch.yaml +298 -109
  10. package/assets/.appweaver/orchestrator/workflows/aw-spec-analyze-plan.orch.yaml +161 -34
  11. package/assets/.appweaver/orchestrator/workflows/aw-spec-analyze-slice.orch.yaml +125 -24
  12. package/assets/.appweaver/orchestrator/workflows/aw-spec-build.orch.yaml +18 -7
  13. package/assets/.appweaver/orchestrator/workflows/aw-spec-close-delta.orch.yaml +182 -39
  14. package/assets/.appweaver/orchestrator/workflows/aw-spec-finalize-delta.orch.yaml +300 -35
  15. package/assets/.appweaver/orchestrator/workflows/aw-spec-implement.orch.yaml +190 -31
  16. package/assets/.appweaver/orchestrator/workflows/aw-spec-onboard.orch.yaml +93 -8
  17. package/assets/.appweaver/orchestrator/workflows/aw-spec-plan.orch.yaml +34 -7
  18. package/assets/.appweaver/orchestrator/workflows/aw-spec-recall-delta.orch.yaml +319 -0
  19. package/assets/.appweaver/orchestrator/workflows/aw-spec-specify.orch.yaml +125 -24
  20. package/assets/.appweaver/scripts/bash/aw-spec-actions.sh +846 -35
  21. package/assets/.appweaver/scripts/bash/common.sh +28 -1
  22. package/assets/.appweaver/scripts/powershell/aw-spec-actions.ps1 +843 -46
  23. package/assets/.appweaver/scripts/python/aw-inventory.py +3 -2
  24. package/assets/.appweaver/templates/design-template.md +41 -30
  25. package/assets/.appweaver/templates/spec-template.md +7 -4
  26. package/assets/.appweaver/templates/ui-design-template.md +7 -3
  27. package/assets/guardrails/domain/healthcare/auditing.domain.md +3 -3
  28. package/assets/guardrails/domain/pharma/auditing.domain.md +3 -3
  29. package/assets/guardrails/technology/dotnet-webapi/api-versioning.md +1 -1
  30. package/assets/guardrails/technology/dotnet-webapi/auditing.md +1 -1
  31. package/assets/guardrails/technology/dotnet-webapi/authorization.md +1 -1
  32. package/assets/guardrails/technology/dotnet-webapi/clean-architecture.md +1 -1
  33. package/assets/guardrails/technology/dotnet-webapi/cqrs.md +1 -1
  34. package/assets/guardrails/technology/dotnet-webapi/data-classification.md +1 -1
  35. package/assets/guardrails/technology/dotnet-webapi/eventing.md +1 -1
  36. package/assets/guardrails/technology/dotnet-webapi/folder-structure.md +1 -1
  37. package/assets/guardrails/technology/dotnet-webapi/modular-monolith.md +1 -1
  38. package/assets/guardrails/technology/dotnet-webapi/persistence.md +1 -1
  39. package/assets/guardrails/technology/dotnet-webapi/vertical-slices.md +1 -1
  40. package/assets/guardrails/technology/dotnet-webapi/zero-trust.md +1 -1
  41. package/assets/guardrails/technology/nextjs/accessibility-implementation.md +1 -1
  42. package/assets/guardrails/technology/nextjs/api-integration.dotnet-webapi.md +1 -1
  43. package/assets/guardrails/technology/nextjs/api-integration.java-spring.md +1 -1
  44. package/assets/guardrails/technology/nextjs/auth-session.md +1 -1
  45. package/assets/guardrails/technology/nextjs/component-architecture.md +1 -1
  46. package/assets/guardrails/technology/nextjs/design-system.md +1 -1
  47. package/assets/guardrails/technology/nextjs/error-handling.md +1 -1
  48. package/assets/guardrails/technology/nextjs/forms-and-validation.md +1 -1
  49. package/assets/guardrails/technology/nextjs/i18n.md +1 -1
  50. package/assets/guardrails/technology/nextjs/performance-budgets.md +1 -1
  51. package/assets/guardrails/technology/nextjs/routing-navigation.md +1 -1
  52. package/assets/guardrails/technology/nextjs/state-management.md +1 -1
  53. package/package.json +1 -1
@@ -2,11 +2,21 @@
2
2
  # aw-spec-adopt (orchestrator) — the JUST-IN-TIME per-feature step of Brownfield DEV
3
3
  #
4
4
  # Develop an EXISTING feature by first reverse-engineering ONE aggregate / vertical
5
- # slice from its code into a living spec.md + aligned design.md (+ a source-map.md
6
- # sidecar), THEN reconciling this feature's evidence into the project governance that
7
- # /appweaver onboard established. Adopt is the inverse of implement: implement reads
8
- # spec+design and generates code; adopt reads code and generates spec+design — equally
9
- # a reasoning step, stamped `origin: reverse-engineered` with per-item confidence.
5
+ # slice from its code into a living spec.md, the bounded context's domain-model.md and
6
+ # aligned lane plans (+ a source-map.md sidecar), THEN reconciling this feature's evidence into the project governance that
7
+ # /appweaver onboard established. Adopt is the inverse of implement: implement reads the
8
+ # plans + the model and generates code; adopt reads code and generates the spec, the model
9
+ # and the plans — equally a reasoning step, stamped `origin: reverse-engineered` with
10
+ # per-item confidence.
11
+ #
12
+ # THE SPEC/MODEL SPLIT HOLDS ON THE REVERSE TOO (2026-09-14). The spec says what the slice
13
+ # DOES and cites BR-nnn by id; the bounded context's domain-model.md says what the domain IS
14
+ # and carries the aggregate root, its boundary, its entities and the TEXT of every invariant.
15
+ # Adopt used to write the model INTO the spec as Key Entities / Business Rules, which left a
16
+ # brownfield feature as the only kind the forward gates could not fully check: analyze-plan's
17
+ # check 4 has nothing to check without a model, and implement generated with no authority on
18
+ # the entity names it was using. The model is CONTEXT-level and shared, so a second adopted
19
+ # slice ADDS its aggregate section and never touches the ones already there.
10
20
  #
11
21
  # onboard → ADOPT <Feature> (JIT, one feature at a time) → [ forward / CR delta loop ] ← you are here
12
22
  #
@@ -14,12 +24,15 @@
14
24
  # develop, never the whole codebase (that scale is what onboard's shallow feature map
15
25
  # avoids). A NEW feature (no existing code) is NOT adopted — it is authored straight
16
26
  # through the forward pipeline (/appweaver specify → plan → implement), which
17
- # onboard already made brownfield-ready (the code-derived design template is the
27
+ # onboard already made brownfield-ready (the code-derived plan template is the
18
28
  # project default). So adopt = reverse an EXISTING feature; the forward pipeline = a
19
29
  # new one. Both then evolve through the CR delta loop.
20
30
  #
21
- # The reverse output is a NORMAL feature: spec.md + design.md are the very documents
22
- # the CR delta loop + forward pipeline consume unchanged. All brownfield provenance
31
+ # The reverse output is a NORMAL feature: spec.md, domain-model.md and backend-plan.md /
32
+ # frontend-plan.md are the very documents the CR delta loop + forward pipeline consume
33
+ # unchanged — under those names, so nothing downstream needs a brownfield special case.
34
+ # plan-scaffold's backend/frontend lanes also MIGRATE a legacy design.md / design.ui.md left
35
+ # by an adopt that ran before the rename, so an already-adopted repo is carried forward. All brownfield provenance
23
36
  # lives in `origin:` frontmatter + the source-map sidecar. Adopt inits
24
37
  # active_version.json (v1.0) so the CR loop works immediately after.
25
38
  #
@@ -56,7 +69,7 @@
56
69
  # =============================================================================
57
70
 
58
71
  name: aw-spec-adopt
59
- description: The JIT per-feature step of brownfield development — reverse-engineer ONE existing feature into a living spec.md + design.md (+ design.ui.md where a frontend lane is declared and this slice owns part of its surface) + source-map.md (origin reverse-engineered, per-item confidence, code-derived design template), then COMPLETE its shallow OKF concept (deepen it to the reversed reality + link the deep artifacts) and record its cross-slice edges. Fidelity gate is spec/design vs code; the review is reported for out-of-band closure. The governance reconcile — carrying this feature's real evidence into the provisional rule files + constitution onboard wrote — is HELD (reconcile_governance=false), so an ordinary run does not touch the governance tier. A NEW feature is authored via the forward pipeline instead. Output is a normal feature for the CR + forward loop.
72
+ description: The JIT per-feature step of brownfield development — reverse-engineer ONE existing feature into a living spec.md, an aggregate section in the bounded context's shared domain-model.md, and backend-plan.md (+ frontend-plan.md where a frontend lane is declared and this slice owns part of its surface) + source-map.md (origin reverse-engineered, per-item confidence, code-derived plan template), then COMPLETE its shallow OKF concept (deepen it to the reversed reality + link the deep artifacts) and record its cross-slice edges. The spec cites BR-nnn by id and the model defines them, exactly as on the greenfield path, so a reversed slice is checkable by the same gates as any other. Fidelity gate is spec + model + plans vs code, and an invented entity, boundary or invariant is a fabrication exactly as an invented FR- is; the review is reported for out-of-band closure. The governance reconcile — carrying this feature's real evidence into the provisional rule files + constitution onboard wrote — is HELD (reconcile_governance=false), so an ordinary run does not touch the governance tier. A NEW feature is authored via the forward pipeline instead. Output is a normal feature for the CR + forward loop.
60
73
  # 1.5.0 — user_input is now OPTIONAL: adopt CONSUMES the ACTIVE feature (select-feature's
61
74
  # .appweaver/feature.json) when no arg is passed, so onboard→select-feature→adopt needs
62
75
  # no re-typing; an explicit <Feature> still selects directly (and wins). One coalesced
@@ -66,7 +79,7 @@ description: The JIT per-feature step of brownfield development — reverse-engi
66
79
  # 1.3.0 — reverse design scaffolds from the DEFAULT `design-template` (onboard's code-derived
67
80
  # override) instead of the never-shipped `brownfield-design-template`, unifying the
68
81
  # whole brownfield pipeline on one code-derived template.
69
- version: 1.5.0
82
+ version: 2.0.0
70
83
  agent_agnostic: true
71
84
  dialect: aw-spec.orchestrator/v1
72
85
 
@@ -108,8 +121,22 @@ vars:
108
121
  ui_lane: "false" # THIS slice reverses a UI half: a frontend lane is declared AND the slice owns UI files
109
122
  ui_count: "0" # how many UI files the concept attributes to this aggregate (aw-inventory ui_source_files)
110
123
  ui_source_files: ""
111
- ui_design_doc: ""
124
+ frontend_plan: ""
112
125
  ui_tpl_source: ""
126
+ # THE LANE PLANS, under the names the forward pipeline reads. A reversed slice is a
127
+ # NORMAL feature, so it carries backend-plan.md / frontend-plan.md like any other —
128
+ # plan-scaffold's backend/frontend lanes also MIGRATE a legacy design.md / design.ui.md
129
+ # left by an earlier adopt, so a repo that was adopted before the rename is carried
130
+ # forward rather than left with two spellings of one master.
131
+ backend_plan: ""
132
+ # THE BOUNDED CONTEXT'S DOMAIN MODEL — shared by every feature in the context, and the
133
+ # authority on the aggregate root, its entities and the TEXT of every BR-nnn. Reversed
134
+ # here in the same run as the spec, exactly as greenfield `specify` authors the two
135
+ # together, so the model is never behind the spec that cites it.
136
+ context: ""
137
+ context_dir: ""
138
+ domain_model: ""
139
+ domain_model_exists: "false"
113
140
  spec_exists: "false"
114
141
  fidelity_ok: "false"
115
142
  rulemap_exists: "false" # governance-present signal (onboard ran) — bound from resolve-domain
@@ -164,6 +191,35 @@ workflow:
164
191
  on_empty: stop
165
192
  on_empty_message: "No feature to adopt. Either run /appweaver select-feature first (pick the aggregate from the onboard feature map), then /appweaver adopt; or name it directly: /appweaver adopt <Feature>."
166
193
 
194
+ # WHICH BOUNDED CONTEXT THIS FEATURE LANDS IN, and a refusal to guess — the same gate
195
+ # select-feature carries, and needed here for the same reason: this stage also creates a
196
+ # feature directory. scope_ok is false in exactly one state, contexts exist and none is
197
+ # selected, and in that state set-feature resolves the target under a bare specs/ where
198
+ # it is outside every context. Worse on this path than on the forward one, because an
199
+ # adopted name comes from the reversed code rather than from a menu: adopting an
200
+ # aggregate that happens to share a name with an empty bounded context would write that
201
+ # context's own spec.md and orphan every feature meant to live inside it. A repo with no
202
+ # contexts at all passes, which keeps the flat brownfield layout working untouched.
203
+ - id: context_scope
204
+ action: execute_script
205
+ script: { ref: actions }
206
+ subcommand: list-contexts
207
+ outputs:
208
+ - { name: active_context, from: "$.active" }
209
+ - { name: context_count, from: "$.count" }
210
+ - { name: scope_ok, from: "$.scope_ok" }
211
+ - { name: scope_message, from: "$.scope_message" }
212
+
213
+ - id: require_context_scope
214
+ action: verify_context
215
+ require_true: scope_ok
216
+ on_false: stop
217
+ on_false_message: >
218
+ {{scope_message}}
219
+ Adopting reverse-engineers one aggregate into a feature directory, so the context
220
+ that owns it has to be chosen before the directory is created — moving a feature
221
+ between contexts afterwards means re-specifying it in the new one.
222
+
167
223
  # Create-or-select the feature dir + persist it active (idempotent in the no-arg
168
224
  # path where it is already active; creates it in the explicit-arg path). set-feature
169
225
  # canonicalises to the PascalCase aggregate id → the single feature_name used below.
@@ -242,27 +298,57 @@ workflow:
242
298
  on_false_message: "No active governance for adopt to work against — run /appweaver onboard first. onboard establishes the PROJECT constitution + guardrails/projects/<project>/ rule set (provisional-from-scan) and activates it. Reversing '{{feature_name}}' without that scaffold would author the spec and design against no code-derived rules at all, and leave them with no governance home."
243
299
 
244
300
  # 2. Scaffold the living docs. The SPEC reuses the forward spec-template (it is
245
- # tech-agnostic WHAT/WHY — no architectural bias). The DESIGN scaffolds from the
301
+ # tech-agnostic WHAT/WHY — no architectural bias). The BACKEND PLAN scaffolds from the
246
302
  # DEFAULT `design-template` — which /appweaver onboard REPLACED with the repo's
247
303
  # code-derived override (resolve_template Priority-1, reverse-engineered from the
248
- # code), so the reversed design's structural sections follow the code's own
304
+ # code), so the reversed plan's structural sections follow the code's own
249
305
  # architecture rather than a fixed greenfield layering, describing the system
250
- # as-built. (Falls back to the greenfield base if onboard has not run.) Both are
306
+ # as-built. (Falls back to the greenfield base if onboard has not run.) The DOMAIN
307
+ # MODEL scaffolds into the bounded CONTEXT, not the feature — it is shared. All are
251
308
  # still normal forward docs (same identity + spine) that the CR delta loop consumes
252
309
  # unchanged. Then init active_version.json (v1.0).
310
+ #
311
+ # THE TEMPLATE IDENTIFIERS KEEP THE `design-template` SPELLING ON PURPOSE. The
312
+ # DOCUMENTS moved to the plan names; the template NAMES did not, because a repo that
313
+ # has already run onboard carries its code-derived override at
314
+ # .appweaver/templates/overrides/design-template.md. Renaming the identifier would
315
+ # make that file stop resolving and silently fall back to the kit's greenfield
316
+ # template — imposing a four-layer structure on a codebase that chose another, which
317
+ # is the exact failure require_ui_template below exists to prevent.
318
+ - id: context_paths
319
+ action: execute_script
320
+ script: { ref: actions }
321
+ subcommand: context-paths
322
+ outputs:
323
+ - { name: context, from: "$.context" }
324
+ - { name: context_dir, from: "$.context_dir" }
325
+ - { name: domain_model, from: "$.domain_model" }
326
+ - { name: domain_model_exists, from: "$.domain_model_exists" }
327
+
253
328
  - id: scaffold_spec
254
329
  action: execute_script
255
330
  script: { ref: actions }
256
331
  subcommand: scaffold
257
332
  args: ["--feature-dir", "{{feature_dir}}", "--allow-existing"]
258
333
 
259
- - id: scaffold_design
334
+ # Idempotent and non-destructive: a context whose model already exists (an earlier
335
+ # feature in it was adopted, or authored greenfield) keeps it, and the reverse below
336
+ # ADDS this aggregate's section rather than replacing the document.
337
+ - id: scaffold_model
260
338
  action: execute_script
261
339
  script: { ref: actions }
262
- subcommand: design-scaffold
263
- args: ["--feature-dir", "{{feature_dir}}"] # default `design-template` = onboard's code-derived override (greenfield base if onboard has not run)
340
+ subcommand: model-scaffold
341
+ args: ["--feature-dir", "{{feature_dir}}"]
264
342
  outputs:
265
- - { name: design_doc, from: "$.design_doc" }
343
+ - { name: domain_model, from: "$.domain_model" }
344
+
345
+ - id: scaffold_plan
346
+ action: execute_script
347
+ script: { ref: actions }
348
+ subcommand: plan-scaffold
349
+ args: ["--feature-dir", "{{feature_dir}}", "--lane", "backend"] # `design-template` = onboard's code-derived override (greenfield base if onboard has not run)
350
+ outputs:
351
+ - { name: backend_plan, from: "$.plan_doc" }
266
352
 
267
353
  - id: version_init
268
354
  action: execute_script
@@ -299,18 +385,18 @@ workflow:
299
385
  condition: "{{ui_count}} == 0"
300
386
  vars: { ui_lane: "false" }
301
387
 
302
- # Scaffold the LANE's design doc from ITS template pair (--lane ui resolves
303
- # ui-design-template -> design.ui.md), the twin of scaffold_design above. onboard
304
- # GENERATED that override from this repo's own UI source, so the reversed UI design
388
+ # Scaffold the LANE's plan from ITS template pair (--lane frontend resolves
389
+ # ui-design-template -> frontend-plan.md), the twin of scaffold_plan above. onboard
390
+ # GENERATED that override from this repo's own UI source, so the reversed frontend plan
305
391
  # follows the code's real composition axes rather than a fixed screen taxonomy.
306
- - id: scaffold_ui_design
392
+ - id: scaffold_ui_plan
307
393
  condition: "{{ui_lane}} == true"
308
394
  action: execute_script
309
395
  script: { ref: actions }
310
- subcommand: design-scaffold
311
- args: ["--feature-dir", "{{feature_dir}}", "--lane", "ui"]
396
+ subcommand: plan-scaffold
397
+ args: ["--feature-dir", "{{feature_dir}}", "--lane", "frontend"]
312
398
  outputs:
313
- - { name: ui_design_doc, from: "$.design_doc" }
399
+ - { name: frontend_plan, from: "$.plan_doc" }
314
400
  - { name: ui_tpl_source, from: "$.template_source" }
315
401
  - { name: ui_tpl_override, from: "$.override_active" }
316
402
 
@@ -378,12 +464,15 @@ workflow:
378
464
  never a separate feature. Derive its Given/When/Then from the code's paths.
379
465
  - System Requirements in EARS (THE SYSTEM SHALL / WHEN / IF…THEN / WHILE /
380
466
  WHERE), each atomic + testable, derived from observed behaviour.
381
- - Always-true invariants the code enforces → Business Rules (BR-n).
382
- - MODEL IN THE TEMPLATE'S OWN VOCABULARY: a ubiquitous language, the
383
- aggregate + its root, entities vs value objects, aggregate-owned
384
- invariants — as domain MODEL, never as the language's own types.
385
- Classify from what the code EXHIBITS. A distinction the code does not
386
- draw is not a gap to fill in: record the model as-built, however thin.
467
+ - Always-true invariants the code enforces get stable BR-nnn ids, CITED here and
468
+ DEFINED in the domain model — see the next bullet.
469
+ - THE DOMAIN MODEL IS NOT THIS DOCUMENT'S. Fill "### Domain Model Reference" with
470
+ the aggregate's NAME and the ids of the invariants this spec relies on
471
+ (BR-nnn), and nothing more. Do NOT write the ubiquitous language, the aggregate
472
+ boundary, the entity/value-object split, the lifecycle states, or the TEXT of any
473
+ invariant: all of that lives in the bounded context's domain-model.md, which the
474
+ NEXT step reverses out of this same code, and several specs act on one aggregate
475
+ so a per-spec copy drifts. Cite by id; never restate.
387
476
  - DOMAIN LIFT — where the CODE enforces them, lift into the three sections
388
477
  (cite the source file): Constraints & NFRs (CN-, e.g. retention /
389
478
  immutability / append-only audit the code implements), Data Classification
@@ -419,31 +508,99 @@ workflow:
419
508
 
420
509
  Source files to read (the slice's code): {{source_files}}
421
510
 
422
- # ═══════════ REVERSE DESIGN — from the reversed SPEC + CODE, AS-BUILT ═══════
511
+ # ══════════ REVERSE DOMAIN MODEL — the CONTEXT's structure, from the CODE ══════
512
+ # The greenfield split, applied to the reverse: the spec says what the system DOES, the
513
+ # bounded context's domain-model.md says what the domain IS — the aggregate root, its
514
+ # boundary, its entities and value objects, its lifecycle, and the TEXT of every BR-nnn
515
+ # the spec cites by id. Authored in the SAME run as the spec, exactly as `specify` does,
516
+ # so the model is never behind the spec that depends on it.
517
+ #
518
+ # THE MODEL IS THE CONTEXT'S, NOT THIS FEATURE'S. Every feature in the bounded context
519
+ # reads it, so adopting a second slice ADDS an aggregate section and must not touch the
520
+ # ones already there — a renumbered BR breaks every citation in every sibling spec,
521
+ # silently. The scaffold above is non-destructive for the same reason.
522
+ #
523
+ # THE CODE IS STILL THE ORACLE. No modelling rule file is loaded, for the reason the
524
+ # reversed spec loads none: a prescriptive standard states what a model OUGHT to be, and
525
+ # an anemic legacy slice must reverse as exactly that. A distinction the code does not
526
+ # draw is not a gap to fill in.
527
+ - id: ctx_reverse_model
528
+ action: build_context
529
+ context:
530
+ - { path: "{{domain_model}}" } # the model — template on the context's first slice, POPULATED on a later one
531
+ - { path: "{{spec_file}}" } # the reversed spec — the BR-nnn ids this model must define
532
+ - { path: "{{concept_path}}" } # source_files + seam
533
+ - { path: .appweaver/memory/constitution.domain.md, optional: true }
534
+ - id: reverse_model
535
+ action: agent_author
536
+ include_standards: false # the technical/arch sticky set is for the plans, never the model
537
+ tools: Read # the structure is reversed from the CODE, which arrives as a path list
538
+ output_target: { type: file, path: "{{domain_model}}" }
539
+ task: |
540
+ Reverse-engineer the BOUNDED CONTEXT's DOMAIN MODEL (the target domain-model.md in
541
+ context) for the aggregate '{{feature_name}}', FROM ITS CODE. The reversed spec (in
542
+ context) names the aggregate and cites the invariant ids; this document DEFINES them.
543
+ READ the source files listed below — the code is the SOURCE OF TRUTH.
544
+
545
+ - ADD ONE `## Aggregate: <Name>` SECTION for this feature's aggregate: its boundary
546
+ (owns / references by id / out of scope), entities, value objects, domain events,
547
+ lifecycle states, and every always-true invariant the code enforces as a stable
548
+ BR-nnn with its RULE TEXT. The spec cites those ids and never restates them.
549
+ - IF THE MODEL ALREADY HAS CONTENT, this is the context's SECOND (or later) adopted
550
+ slice. ADD this aggregate as a new section and EXTEND the ubiquitous language. Do
551
+ NOT rewrite, renumber or "tidy" the aggregates already there — other specs cite
552
+ their ids, and a renumbered BR breaks every citation silently. Add
553
+ `{{feature_name}}` to the `Serving specs` line of any existing aggregate this
554
+ slice also acts on.
555
+ - MODEL WHAT THE CODE EXHIBITS, NOT WHAT GOOD DESIGN WOULD WANT. Classify entities
556
+ vs value objects by whether the code gives the thing an IDENTITY; draw the
557
+ boundary where the code actually draws it (what it loads and saves together).
558
+ A slice that is anemic, or models nothing at all, reverses as exactly that — an
559
+ aggregate with no invariants is a true finding, and the fidelity gate scores an
560
+ invented one as a fabrication. Where the code's own grouping is unclear, record
561
+ what it shows and mark the item "(inferred)".
562
+ - CROSS-AGGREGATE REFERENCES BY ID ONLY, never a navigable link — where the code
563
+ does hold a direct object reference across a boundary, record the reference by id
564
+ here and leave the coupling fact to the source-map's Seam section.
565
+ - Fill "## Cross-Aggregate Invariants" (XBR-n) with rules the code enforces ACROSS
566
+ two or more aggregates — they belong to no single spec, which is why they can only
567
+ live here. "None (as of v1.0)" when the code shows none; never delete the section.
568
+ - Fill "## Context Map" with this context's relationships to others where the code
569
+ evidences them, or "None (as of v1.0)". Never delete the section.
570
+ - TECHNOLOGY-AGNOSTIC. No types, no persistence, no framework, no layering. WHERE an
571
+ invariant is ENFORCED is a plan concern and belongs in backend-plan.md.
572
+ - Add `origin: reverse-engineered` near the identity block. Do NOT write the Context
573
+ version or the Change History version column — scripts stamp those.
574
+
575
+ Source files to read (the slice's code): {{source_files}}
576
+
577
+ # ═══════════ REVERSE BACKEND PLAN — from the SPEC + MODEL + CODE, AS-BUILT ═══
423
578
  # Anchored to the reversed spec's ids (§4 Traceability → forward-compatible),
424
- # grounded in the code's ACTUAL structure, tech-agnostic. NO domain files (rule
425
- # partition). The scaffolded design.md IS onboard's code-derived `design-template`
426
- # override — its §2 component sections follow the code's own folders/modules, not a
427
- # fixed layering.
428
- - id: ctx_reverse_design
579
+ # grounded in the code's ACTUAL structure, tech-agnostic. NO domain rule files (rule
580
+ # partition) — the domain reaches this plan as the reversed spec's ids and as the
581
+ # context's domain model, which is READ here and never written. The scaffolded
582
+ # backend-plan.md IS onboard's code-derived `design-template` override — its §2
583
+ # component sections follow the code's own folders/modules, not a fixed layering.
584
+ - id: ctx_reverse_plan
429
585
  action: build_context
430
586
  context:
431
- - { path: "{{design_doc}}" } # the scaffolded code-derived template = structure + embedded guidance
432
- - { path: "{{spec_file}}" } # the reversed spec = the ONLY domain input
587
+ - { path: "{{backend_plan}}" } # the scaffolded code-derived template = structure + embedded guidance
588
+ - { path: "{{spec_file}}" } # the reversed spec = WHAT the slice must do
589
+ - { path: "{{domain_model}}" } # the reversed model = what the domain IS — READ, never written here
433
590
  - { path: "{{concept_path}}" } # source_files + seam (structure hints)
434
591
  - { path: .appweaver/DESIGN-FORMAT.md } # the HLD contract (see its Brownfield variant note)
435
592
  - { path: "{{bundle_dir}}/architecture/overview.md", optional: true } # the as-built architecture (inventory) — cite, don't re-derive
436
593
  - { path: .appweaver/memory/constitution.technical.md, optional: true } # technology base ONLY — no domain
437
- - id: reverse_design
594
+ - id: reverse_plan
438
595
  action: agent_author
439
596
  include_standards: true # the technical/architecture sticky set (reference only — the CODE wins)
440
597
  tools: Read # grounded in the CODE, which arrives as {{source_files}} paths
441
- output_target: { type: file, path: "{{design_doc}}" }
598
+ output_target: { type: file, path: "{{backend_plan}}" }
442
599
  task: |
443
- Reverse-engineer the MASTER high-level design (the target design.md in
444
- context — it is the BROWNFIELD design template) — the tech-agnostic HLD that
445
- MEDIATES the reversed spec ↔ the existing code. Ground every element in the
446
- CODE (read the source files listed below) but ANCHOR each to a spec id from
600
+ Reverse-engineer the BACKEND LANE's master plan (the target backend-plan.md in
601
+ context — it is the BROWNFIELD plan template) — the tech-agnostic HLD that
602
+ MEDIATES the reversed spec + domain model ↔ the existing code. Ground every element
603
+ in the CODE (read the source files listed below) but ANCHOR each to a spec id from
447
604
  the reversed spec (in context) so §4 Traceability is complete and the doc is
448
605
  forward-compatible. Guidance: {{feature_name}}
449
606
 
@@ -451,10 +608,12 @@ workflow:
451
608
  it toward any reference architecture; the technical standards in context are a
452
609
  vocabulary to NAME what you find, never a target to bend the code toward.
453
610
  Rules:
454
- - THE SPEC IS THE ONLY DOMAIN INPUT. You have the reversed spec + the code's
455
- actual STRUCTURE — and NO domain rule files. Realise the spec ids; introduce
456
- no domain rule the spec omits. A concept the code exhibits but the spec lacks
457
- → surface it (it belongs in the spec) and record a §5 DA-n; do not smuggle it in.
611
+ - THE SPEC AND THE MODEL ARE THE ONLY DOMAIN INPUTS. You have the reversed spec,
612
+ the reversed domain model and the code's actual STRUCTURE — and NO domain rule
613
+ files. Realise the spec ids; introduce no domain rule neither document states. A
614
+ concept the code exhibits but both lack → surface it (it belongs in the spec or
615
+ the model) and record a §5 DA-n; do not smuggle it in. DO NOT EDIT
616
+ domain-model.md — it is spec-tier and read-only here.
458
617
  - STRUCTURE FOLLOWS THE CODE. Fill §1.1 As-Built Architecture from the code's
459
618
  real shape (its folders / projects / modules — name the style, don't prescribe
460
619
  one). Then create ONE §2 subsection per structural axis the slice's code
@@ -464,11 +623,14 @@ workflow:
464
623
  fits no textbook layer (a UI tier, a worker, a shared library) gets its own
465
624
  section; a layer the code lacks does NOT appear.
466
625
  - KEEP THE NEUTRAL ANCHORS (the template pins these): §1.2 is the domain/data
467
- MODEL and MUST match the spec's Key Entities / Business Rules (same names,
468
- cite BR-/CN-) with cross-slice References-by-id kept here; one §2 subsection
469
- is the EXTERNAL INTEGRATIONS table (heading contains "Integration") realising
470
- the spec's IC-. Realise CN- (structural → §1.2 invariants/events; retention/
471
- audit → §2 persistence / §3 cross-cutting), DC- (§3 + projection surface).
626
+ MODEL and MUST match the CONTEXT'S DOMAIN MODEL exactly — the same entity and
627
+ value-object NAMES, the same boundary, the same lifecycle states — with
628
+ cross-slice References-by-id kept here. Every BR-nnn the model defines gets a
629
+ named ENFORCEMENT POINT in this plan: cite it by id and NEVER restate what it
630
+ says, because the model is the only place that text lives. One §2 subsection is
631
+ the EXTERNAL INTEGRATIONS table (heading contains "Integration") realising the
632
+ spec's IC-. Realise CN- (structural → §1.2 invariants/events; retention/audit →
633
+ §2 persistence / §3 cross-cutting), DC- (§3 + projection surface).
472
634
  - AS-BUILT DEBT, not architecture drift. §6 records ONLY debt the CODE ITSELF
473
635
  evidences — stubs/no-ops, dead or duplicate code, torn seams (shared table/
474
636
  transaction), TODOs, hard-coded values. The code being organised differently
@@ -486,27 +648,28 @@ workflow:
486
648
 
487
649
  # ═══════ REVERSE UI DESIGN — the LANE's half, from the UI code, AS-BUILT ═══
488
650
  # Runs only where this slice HAS a surface (ui_lane). The service design above is
489
- # NOT its parent: design.md realises the spec's FR/BR/CN-, design.ui.md realises the
490
- # spec's UX- and the user stories' interaction, and it CONSUMES design.md's contracts
491
- # rather than restating them. Both are in context for exactly that reason.
492
- - id: ctx_reverse_ui_design
651
+ # NOT its parent: backend-plan.md realises the spec's FR/BR/CN-, frontend-plan.md
652
+ # realises the spec's UX- and the user stories' interaction, and it CONSUMES the backend
653
+ # plan's contracts rather than restating them. Both are in context for exactly that reason.
654
+ - id: ctx_reverse_ui_plan
493
655
  condition: "{{ui_lane}} == true"
494
656
  action: build_context
495
657
  context:
496
- - { path: "{{ui_design_doc}}" } # the scaffolded code-derived lane template = structure + embedded guidance
658
+ - { path: "{{frontend_plan}}" } # the scaffolded code-derived lane template = structure + embedded guidance
497
659
  - { path: "{{spec_file}}" } # the reversed spec — UX- + the user stories this surface serves
498
- - { path: "{{design_doc}}" } # the service design — the contracts the UI consumes, never re-specified here
660
+ - { path: "{{backend_plan}}" } # the backend plan — the contracts the UI consumes, never re-specified here
661
+ - { path: "{{domain_model}}", optional: true } # the ubiquitous language labels and states must use — READ, never written
499
662
  - { path: .appweaver/memory/constitution.ui.md, optional: true } # the lane's UX-* base, reversed by onboard from this same UI
500
663
  - { path: "{{bundle_dir}}/architecture/frontend.md", optional: true } # the as-built UI architecture + the SHARED surface no slice owns
501
- - id: reverse_ui_design
664
+ - id: reverse_ui_plan
502
665
  condition: "{{ui_lane}} == true"
503
666
  action: agent_author
504
667
  include_standards: true # the lane's sticky technical set (reference only — the CODE wins)
505
668
  tools: Read # same, for the lane's surface ({{ui_source_files}})
506
- output_target: { type: file, path: "{{ui_design_doc}}" }
669
+ output_target: { type: file, path: "{{frontend_plan}}" }
507
670
  task: |
508
- Reverse-engineer the FRONTEND LANE's high-level design (the target design.ui.md
509
- in context — it is this project's code-derived UI design template) for the
671
+ Reverse-engineer the FRONTEND LANE's master plan (the target frontend-plan.md
672
+ in context — it is this project's code-derived UI plan template) for the
510
673
  aggregate '{{feature_name}}', FROM ITS UI CODE. Fill the template; preserve its
511
674
  section order.
512
675
 
@@ -516,9 +679,11 @@ workflow:
516
679
  surface with no loading states is recorded as having none, NEVER as needing them.
517
680
  Rules:
518
681
  - STAY IN THE LANE. Realise the spec's Experience Standards (UX-) and the
519
- interaction its User Stories imply. The service design (in context) supplies
682
+ interaction its User Stories imply. The backend plan (in context) supplies
520
683
  the CONTRACTS this surface consumes — cite them; do NOT restate, re-derive or
521
- contradict them, and introduce no server-side behaviour here.
684
+ contradict them, and introduce no server-side behaviour here. Where the domain
685
+ model is in context, use its UBIQUITOUS LANGUAGE exactly in labels, states and
686
+ messages, and cite BR-nnn rather than restating a rule.
522
687
  - STRUCTURE FOLLOWS THE UI CODE. Fill each section from the lane's real shape —
523
688
  its actual routes and screens, its own composition axes (however it groups
524
689
  components), where client state and server data-fetching really live, its
@@ -543,8 +708,8 @@ workflow:
543
708
  context:
544
709
  - { path: .appweaver/templates/source-map-template.md } # the sidecar structure
545
710
  - { path: "{{spec_file}}" }
546
- - { path: "{{design_doc}}" }
547
- - { path: "{{ui_design_doc}}", optional: true } # the lane's design, where this slice has one
711
+ - { path: "{{backend_plan}}" }
712
+ - { path: "{{frontend_plan}}", optional: true } # the lane's design, where this slice has one
548
713
  - { path: "{{concept_path}}" } # both file lists to map
549
714
  - id: source_map
550
715
  action: agent_author
@@ -554,14 +719,14 @@ workflow:
554
719
  task: |
555
720
  Author the source-map sidecar (the target in context) from the template,
556
721
  for aggregate '{{feature_name}}'. It is the SOURCE ANCHOR of the traceability
557
- spine — it keeps spec.md / design.md clean while recording provenance here.
722
+ spine — it keeps spec.md / backend-plan.md clean while recording provenance here.
558
723
  - One row per legacy artefact in the bundle concept's `source_files` (read
559
724
  them under {{module_dir}}): map each to the spec ids (FR/BR/US/CN/DC/IC)
560
- and the design element (§/name) that now describe it, with CONFIDENCE
725
+ and the backend-plan element (§/name) that now describe it, with CONFIDENCE
561
726
  (certain | inferred). EVERY source file MUST appear — the Fidelity gate
562
727
  checks full coverage both ways.
563
728
  - Where this slice has a UI half, its files map the same way, to the UX-/US-
564
- they realise and the design.ui.md section (§/name) that describes them —
729
+ they realise and the frontend-plan.md section (§/name) that describes them —
565
730
  one spine, both lanes. UI files to map: {{ui_source_files}}
566
731
  - Also map DB tables, endpoints, and background jobs the slice owns.
567
732
  - Fill the Seam section: the boundary this slice owns (endpoint / table
@@ -573,35 +738,51 @@ workflow:
573
738
  - Baseline commit = the inventory HEAD.
574
739
  Source files to map: {{source_files}}
575
740
 
576
- # ═══════════════ FIDELITY — does spec+design describe the CODE? ═════════════
577
- # spec/design ↔ CODE (NOT spec ↔ design). The agent can READ the source files.
578
- # BLOCKING gaps = unmapped code / fabricated spec-or-design (structural). The
579
- # rest (inferred items, quirks, missing-invariant candidates) are REVIEW items
580
- # → written to an Adopt Review report and closed OUT OF BAND (Brownfield B1·R).
741
+ # ═══════ FIDELITY — do spec + model + plans describe the CODE? ══════════════
742
+ # documents ↔ CODE (NOT document ↔ document). The agent can READ the source files.
743
+ # BLOCKING gaps = unmapped code / a fabricated spec id, model element or plan element
744
+ # (structural). The rest (inferred items, quirks, missing-invariant candidates) are
745
+ # REVIEW items → written to an Adopt Review report and closed OUT OF BAND (Brownfield
746
+ # B1·R).
747
+ #
748
+ # THE MODEL IS JUDGED THE SAME WAY AS EVERYTHING ELSE, and it is the document most
749
+ # likely to be embellished: a reverse that "tidies" an anemic legacy slice into a clean
750
+ # aggregate produces a model the code does not have, which every later plan and slice
751
+ # gate would then be checked against. An invented entity, boundary or invariant is a
752
+ # fabrication exactly as an invented FR- is.
581
753
  - id: fidelity
582
754
  action: agent_query
583
755
  context:
584
756
  - "{{spec_file}}"
585
- - "{{design_doc}}"
586
- - { path: "{{ui_design_doc}}", optional: true } # the lane's design, where this slice has one
757
+ - "{{domain_model}}"
758
+ - "{{backend_plan}}"
759
+ - { path: "{{frontend_plan}}", optional: true } # the lane's plan, where this slice has one
587
760
  - "{{feature_dir}}/source-map.md"
588
761
  - "{{concept_path}}"
589
762
  include_standards: false
590
- tools: Read # the check is spec/design vs CODE; with no code it degrades to spec vs design and certifies fabrication as ok
591
- schema: { ok: true, report_needed: false, blocking_gaps: [ { severity: "high", artefact: "<source file / spec id / design element>", kind: "unmapped-code | fabricated-spec | fabricated-design", detail: "<why>" } ], review_items: [ { kind: "inferred | as-built-quirk | missing-invariant | confidence", where: "<spec/design/source-map location>", note: "<what to confirm out of band>" } ] }
763
+ tools: Read # the check is documents vs CODE; with no code it degrades to doc vs doc and certifies fabrication as ok
764
+ schema: { ok: true, report_needed: false, blocking_gaps: [ { severity: "high", artefact: "<source file / spec id / model element / plan element>", kind: "unmapped-code | fabricated-spec | fabricated-model | fabricated-plan", detail: "<why>" } ], review_items: [ { kind: "inferred | as-built-quirk | missing-invariant | confidence", where: "<spec/model/plan/source-map location>", note: "<what to confirm out of band>" } ] }
592
765
  mock: { ok: true, report_needed: false, blocking_gaps: [], review_items: [] }
593
766
  task: |
594
767
  FIDELITY CHECK — do the reversed documents actually describe the CODE
595
- (spec/design ↔ CODE, NOT spec ↔ design)? Use the source-map (in context) and
768
+ (documents ↔ CODE, NOT document ↔ document)? Use the source-map (in context) and
596
769
  READ the slice's source files (the concept's `source_files`, under
597
- {{module_dir}}). Where design.ui.md is in context, it is judged the same way
770
+ {{module_dir}}). Where frontend-plan.md is in context, it is judged the same way
598
771
  against the slice's UI files ({{ui_source_files}}) — a screen, state store or
599
- route it describes that the UI code does not have is a fabricated-design, and a
772
+ route it describes that the UI code does not have is a fabricated-plan, and a
600
773
  UI file with no home in the source-map is unmapped-code. Classify findings:
601
774
  - BLOCKING (structural — set ok=false if any):
602
- (1) unmapped-code: a source file with NO spec/design home in the source-map;
603
- (2) fabricated-spec / fabricated-design: a spec id or design element with NO
604
- basis in the code (reverse-engineering must not invent behaviour).
775
+ (1) unmapped-code: a source file with NO home in the source-map;
776
+ (2) fabricated-spec / fabricated-model / fabricated-plan: a spec id, model
777
+ element or plan element with NO basis in the code (reverse-engineering must
778
+ not invent behaviour or structure). For the MODEL specifically: an entity or
779
+ value object the code does not have, an aggregate boundary it does not draw,
780
+ a lifecycle state it never enters, or a BR-nnn whose rule nothing enforces.
781
+ An anemic slice reversing as an anemic model is CORRECT, not a gap.
782
+ - ONLY ONE AGGREGATE SECTION IS THIS RUN'S. domain-model.md is the CONTEXT's and
783
+ may already carry sections from earlier adopted slices — judge ONLY the aggregate
784
+ '{{feature_name}}' reversed here. Do not report a sibling aggregate as unmapped
785
+ because this slice's code does not contain it.
605
786
  - REVIEW (does NOT block ok — these are the Adopt review worklist, closed out
606
787
  of band): items marked "(inferred)"; as-built quirks the code shows but the
607
788
  spec under-states; invariants the code enforces that may be missing/weak;
@@ -620,7 +801,7 @@ workflow:
620
801
  condition: "{{report_needed}} == true"
621
802
  action: agent_author
622
803
  include_standards: false
623
- context: ["{{spec_file}}", "{{design_doc}}", "{{feature_dir}}/source-map.md"]
804
+ context: ["{{spec_file}}", "{{domain_model}}", "{{backend_plan}}", "{{feature_dir}}/source-map.md"]
624
805
  output_target: { type: file, path: "{{feature_dir}}/adopt-review-report.md" }
625
806
  task: |
626
807
  Write an Adopt Review report (the target) for aggregate '{{feature_name}}' —
@@ -637,22 +818,23 @@ workflow:
637
818
  spec.md (a resolved [NEEDS CLARIFICATION] / Assumption) or log a deviation.
638
819
  Review items: {{review_items}}
639
820
  - "## How to proceed": resolve blocking gaps first; then the slice is a normal
640
- feature — run /appweaver analyze-plan (spec↔design gate) if desired, then
641
- drive every change through the CR delta loop. If a change edits untested legacy
642
- behaviour with blast radius, characterize just that surface first (optional
643
- on-touch fence) — it is not a required phase.
821
+ feature — run /appweaver analyze-plan (the spec↔plan gate, which also checks both
822
+ plans against the context's domain model) if desired, then drive every change
823
+ through the CR delta loop. If a change edits untested legacy behaviour with blast
824
+ radius, characterize just that surface first (optional on-touch fence) — it is
825
+ not a required phase.
644
826
  Return the report markdown only.
645
827
 
646
828
  - id: fidelity_gate
647
829
  action: verify_context
648
830
  require_true: fidelity_ok
649
831
  on_false: stop
650
- on_false_message: "Fidelity FAILED for {{feature_name}} — the reversed spec/design do not match the code (blocking gaps: {{blocking_gaps}}). See specs/{{feature_name}}/adopt-review-report.md. Fix the unmapped code / remove fabricated items (re-read the source, refine spec.md + design.md + source-map.md), then re-run /appweaver adopt (after removing the dir) or resolve out of band."
832
+ on_false_message: "Fidelity FAILED for {{feature_name}} — the reversed documents do not match the code (blocking gaps: {{blocking_gaps}}). See specs/{{feature_name}}/adopt-review-report.md. Fix the unmapped code / remove fabricated items (re-read the source, refine spec.md, {{domain_model}}, backend-plan.md and source-map.md), then re-run /appweaver adopt (after removing the dir) or resolve out of band. A `fabricated-model` gap means the reverse gave this slice structure its code does not have — an entity, a boundary, a lifecycle state or a BR-nnn nothing enforces; the fix is to record the domain as thin as the code really is, never to leave it flattering."
651
833
 
652
834
  # ═══════════ OKF CONCEPT — COMPLETE the shallow scan concept (deep reverse) ═══
653
835
  # onboard wrote this aggregate's OKF concept SHALLOW (a discovery stub — enough to pick the
654
- # feature). Now that the deep reverse produced a TRUSTWORTHY spec.md + design.md +
655
- # source-map.md, COMPLETE the concept: deepen its detail to the reversed reality, LINK the
836
+ # feature). Now that the deep reverse produced a TRUSTWORTHY spec.md + domain-model.md +
837
+ # backend-plan.md + source-map.md, COMPLETE the concept: deepen its detail to the reversed reality, LINK the
656
838
  # authored artifacts, refresh source_files, and mark it ADOPTED. RECONCILE, not rewrite —
657
839
  # keep OKF format + the bundle links; do NOT touch the Depends-On / Cross-References
658
840
  # sections (xref_record owns those, next). Runs only after fidelity passes (deepened from
@@ -663,7 +845,8 @@ workflow:
663
845
  context:
664
846
  - { path: "{{concept_path}}" } # the shallow onboard concept to complete
665
847
  - { path: "{{spec_file}}" } # the deep reversed spec (entities, US, BR/CN/DC/IC)
666
- - { path: "{{design_doc}}" } # the deep reversed design (components, ports, integrations)
848
+ - { path: "{{domain_model}}" } # the deep reversed model (entities, boundary, invariants)
849
+ - { path: "{{backend_plan}}" } # the deep reversed plan (components, ports, integrations)
667
850
  - { path: "{{feature_dir}}/source-map.md" } # the source anchor (files, seam, quirks)
668
851
  - { path: .appweaver/templates/okf-concept-template.md } # OKF v0.1 format authority
669
852
  - id: complete_concept
@@ -673,14 +856,18 @@ workflow:
673
856
  task: |
674
857
  COMPLETE the OKF aggregate concept for '{{feature_name}}' at {{concept_path}} — onboard
675
858
  wrote it SHALLOW (a discovery stub from the whole-repo scan). The deep reverse has now
676
- produced a TRUSTWORTHY spec.md + design.md + source-map.md (in context); deepen the
859
+ produced a TRUSTWORTHY spec.md + domain-model.md + backend-plan.md + source-map.md (in
860
+ context); deepen the
677
861
  concept to match and LINK those artifacts. Follow the OKF concept template in context.
678
862
  RECONCILE, do NOT rewrite:
679
863
  - DEEPEN the responsibilities + the owned entities / value objects / domain events /
680
- commands (user stories) / API endpoints / persistence to match the reversed spec +
681
- design — correct any drift the shallow scan got wrong (the deep docs win).
682
- - LINK the deep artifacts: add bundle links to specs/{{feature_name}}/spec.md, design.md,
683
- and source-map.md so the concept points at the deep truth.
864
+ commands (user stories) / API endpoints / persistence to match the reversed spec,
865
+ model and plan — the ENTITIES and VALUE OBJECTS come from domain-model.md, which is
866
+ the authority on them; correct any drift the shallow scan got wrong (the deep docs
867
+ win).
868
+ - LINK the deep artifacts: add bundle links to specs/{{feature_name}}/spec.md,
869
+ backend-plan.md, source-map.md and the context's domain-model.md so the concept
870
+ points at the deep truth.
684
871
  - Refresh `source_files` from the source-map (grouped by the code's OWN folders, per
685
872
  OKF), and set `timestamp` to the baseline (inventory HEAD) commit time.
686
873
  - Update frontmatter: keep `origin: reverse-engineered`; mark the concept ADOPTED /
@@ -694,7 +881,7 @@ workflow:
694
881
  outputs:
695
882
  - { name: concept_completed, from: "$.files" }
696
883
 
697
- # 3b. OKF cross-references (brownfield seed). The reversed design.md now names this
884
+ # 3b. OKF cross-references (brownfield seed). The reversed backend-plan.md now names this
698
885
  # slice's cross-aggregate references (§1 References-by-id) + integration contracts
699
886
  # (its External integrations table, IC-); record them into the shared OKF bundle — a
700
887
  # Cross-References row in every
@@ -706,7 +893,7 @@ workflow:
706
893
  action: execute_script
707
894
  script: { ref: xref }
708
895
  subcommand: record
709
- args: ["--using", "{{feature_name}}", "--design", "{{design_doc}}", "--bundle", "{{bundle_dir}}", "--origin", "reverse-engineered"]
896
+ args: ["--using", "{{feature_name}}", "--design", "{{backend_plan}}", "--bundle", "{{bundle_dir}}", "--origin", "reverse-engineered"]
710
897
  outputs:
711
898
  - { name: xref_wrote, from: "$.wrote" }
712
899
  - { name: xref_edge_count, from: "$.edge_count" }
@@ -738,7 +925,7 @@ workflow:
738
925
  action: build_context
739
926
  context:
740
927
  - { path: "{{spec_file}}" } # the feature's real BR-/CN-/DC-/IC-
741
- - { path: "{{design_doc}}" }
928
+ - { path: "{{backend_plan}}" }
742
929
  - { path: "{{feature_dir}}/source-map.md" }
743
930
  - { path: "guardrails/projects/{{gov_domain}}/domain-rule-bindings.md", optional: true }
744
931
  - { path: .appweaver/RULE-PARTITION.md } # the rule-partition authority (which command reads what)
@@ -751,7 +938,7 @@ workflow:
751
938
  RECONCILE the domain rule-file set in guardrails/projects/{{gov_domain}}/domain/ with the
752
939
  newly-adopted feature '{{feature_name}}'. onboard authored these rule files from the
753
940
  whole-repo scan with per-feature specifics marked `PROVISIONAL — reconciled at
754
- adopt`. READ this feature's reversed spec.md + design.md + source-map.md (in
941
+ adopt`. READ this feature's reversed spec.md + backend-plan.md + source-map.md (in
755
942
  context — the real evidence) and the EXISTING rule files under
756
943
  guardrails/projects/{{gov_domain}}/.
757
944
 
@@ -780,7 +967,7 @@ workflow:
780
967
  action: build_context
781
968
  context:
782
969
  - { path: "{{constitution_technical_file}}" }
783
- - { path: "{{design_doc}}" }
970
+ - { path: "{{backend_plan}}" }
784
971
  - { path: "{{feature_dir}}/source-map.md" }
785
972
  - id: reconcile_technical
786
973
  condition: "{{reconcile_governance}} == true" # HELD — governance reconcile paused (see vars)
@@ -790,7 +977,7 @@ workflow:
790
977
  task: |
791
978
  RECONCILE the TECHNICAL constitution (target in context) with the adopted feature
792
979
  '{{feature_name}}'. onboard discovered the technology principle SET from the scan and
793
- marked per-feature code coordinates `PROVISIONAL`. READ this feature's design.md +
980
+ marked per-feature code coordinates `PROVISIONAL`. READ this feature's backend-plan.md +
794
981
  source-map.md (in context — the code-coordinate bridge: real file paths / type names).
795
982
 
796
983
  RECONCILE, do NOT re-author:
@@ -921,8 +1108,10 @@ workflow:
921
1108
  outputs:
922
1109
  feature_dir: "{{feature_dir}}"
923
1110
  spec_file: "{{spec_file}}"
924
- design_doc: "{{design_doc}}"
925
- ui_design_doc: "{{ui_design_doc}}" # empty where this slice has no UI half
1111
+ backend_plan: "{{backend_plan}}"
1112
+ frontend_plan: "{{frontend_plan}}" # empty where this slice has no UI half
1113
+ domain_model: "{{domain_model}}" # the CONTEXT's, shared — this run ADDED an aggregate section to it
1114
+ bounded_context: "{{context}}"
926
1115
  ui_lane: "{{ui_lane}}"
927
1116
  ui_count: "{{ui_count}}"
928
1117
  source_map: "{{feature_dir}}/source-map.md"
@@ -936,4 +1125,4 @@ outputs:
936
1125
  composed_file: "{{composed_file}}"
937
1126
  technical_reconcile_ok: "{{technical_ok}}"
938
1127
  domain_reconcile_ok: "{{domain_ok}}"
939
- next: "Adopted {{feature_name}} (spec.md + design.md + source-map.md, v1.0) and COMPLETED its OKF concept (deepened + linked the deep artifacts; {{xref_edge_count}} cross-slice edge(s) recorded). UI HALF: ui_lane={{ui_lane}} — where it is true this slice also has design.ui.md, reversed from the {{ui_count}} UI file(s) the feature map attributes to it; where it is false the repo declared no frontend lane, or this aggregate owns no part of its surface, and a service-only adoption is the correct outcome rather than a gap. The SHARED UI surface (app shell, layout, design system) belongs to no slice and stays in {{bundle_dir}}/architecture/frontend.md. NOTE — governance reconcile is currently HELD (reconcile_governance=false): this run did NOT modify the constitution halves or the guardrails/projects/{{gov_domain}}/ rule set, so they keep onboard's provisional scaffold. Close any items in specs/{{feature_name}}/adopt-review-report.md out of band. The slice is now a NORMAL feature: refine via /appweaver analyze-plan, 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 change edits untested legacy behaviour with blast radius, characterize just that surface first (optional on-touch fence). To restore governance reconcile, set reconcile_governance to \"true\" in the workflow vars."
1128
+ next: "Adopted {{feature_name}} (spec.md + backend-plan.md + source-map.md, v1.0) and ADDED its aggregate section to the bounded context `{{context}}`'s shared {{domain_model}} — the spec cites BR-nnn by id, the model carries their text, so this slice is checkable by the same gates as a greenfield one and analyze-plan's check 4 now has a model to check against. Other features in this context keep their own aggregate sections untouched. COMPLETED its OKF concept (deepened + linked the deep artifacts; {{xref_edge_count}} cross-slice edge(s) recorded). UI HALF: ui_lane={{ui_lane}} — where it is true this slice also has frontend-plan.md, reversed from the {{ui_count}} UI file(s) the feature map attributes to it; where it is false the repo declared no frontend lane, or this aggregate owns no part of its surface, and a service-only adoption is the correct outcome rather than a gap. The SHARED UI surface (app shell, layout, design system) belongs to no slice and stays in {{bundle_dir}}/architecture/frontend.md. NOTE — governance reconcile is currently HELD (reconcile_governance=false): this run did NOT modify the constitution halves or the guardrails/projects/{{gov_domain}}/ rule set, so they keep onboard's provisional scaffold. Close any items in specs/{{feature_name}}/adopt-review-report.md out of band. The slice is now a NORMAL feature: refine via /appweaver analyze-plan, 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 change edits untested legacy behaviour with blast radius, characterize just that surface first (optional on-touch fence). To restore governance reconcile, set reconcile_governance to \"true\" in the workflow vars."