aw-spec-cli 0.1.33 → 0.1.35
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +76 -81
- package/assets/.appweaver/DESIGN-FORMAT.md +57 -25
- package/assets/.appweaver/STACK-PROFILES.md +95 -60
- package/assets/.appweaver/orchestrator/LAUNCHER.md +1 -1
- package/assets/.appweaver/orchestrator/modules/delta-plan.orch.yaml +173 -32
- package/assets/.appweaver/orchestrator/modules/domain-select.orch.yaml +29 -1
- package/assets/.appweaver/orchestrator/modules/foundation-pack.orch.yaml +7 -4
- package/assets/.appweaver/orchestrator/modules/foundation-spec.orch.yaml +49 -60
- package/assets/.appweaver/orchestrator/modules/tech-select.orch.yaml +58 -0
- package/assets/.appweaver/orchestrator/orchestrator.py +26 -8
- package/assets/.appweaver/orchestrator/rev-templates/delta-design-template.skeleton.md +20 -20
- package/assets/.appweaver/orchestrator/rev-templates/design-template.skeleton.md +22 -48
- package/assets/.appweaver/orchestrator/rev-templates/ui-delta-design-template.skeleton.md +9 -7
- package/assets/.appweaver/orchestrator/rev-templates/ui-design-template.skeleton.md +5 -5
- package/assets/.appweaver/orchestrator/workflows/aw-spec-adopt.orch.yaml +239 -40
- package/assets/.appweaver/orchestrator/workflows/aw-spec-analyze-plan-delta.orch.yaml +254 -43
- package/assets/.appweaver/orchestrator/workflows/aw-spec-analyze-plan.orch.yaml +248 -68
- package/assets/.appweaver/orchestrator/workflows/aw-spec-analyze-slice-delta.orch.yaml +251 -20
- package/assets/.appweaver/orchestrator/workflows/aw-spec-analyze-slice.orch.yaml +316 -10
- package/assets/.appweaver/orchestrator/workflows/aw-spec-build.orch.yaml +6 -47
- package/assets/.appweaver/orchestrator/workflows/aw-spec-close-delta.orch.yaml +62 -16
- package/assets/.appweaver/orchestrator/workflows/aw-spec-finalize-delta.orch.yaml +132 -9
- package/assets/.appweaver/orchestrator/workflows/aw-spec-fix-test-coverage.orch.yaml +965 -0
- package/assets/.appweaver/orchestrator/workflows/aw-spec-implement.orch.yaml +222 -169
- package/assets/.appweaver/orchestrator/workflows/aw-spec-onboard.orch.yaml +21 -22
- package/assets/.appweaver/orchestrator/workflows/aw-spec-plan.orch.yaml +453 -120
- package/assets/.appweaver/orchestrator/workflows/aw-spec-select-lane.orch.yaml +2 -2
- package/assets/.appweaver/orchestrator/workflows/aw-spec-select-stack.orch.yaml +83 -6
- package/assets/.appweaver/orchestrator/workflows/aw-spec-specify.orch.yaml +45 -2
- package/assets/.appweaver/scripts/bash/aw-spec-actions.sh +324 -74
- package/assets/.appweaver/scripts/powershell/aw-spec-actions.ps1 +275 -44
- package/assets/.appweaver/scripts/python/aw-foundation.py +16 -13
- package/assets/.appweaver/scripts/python/aw-gaps.py +11 -3
- package/assets/.appweaver/scripts/python/aw-model-guard.py +295 -0
- package/assets/.appweaver/scripts/python/aw-plan-coverage.py +412 -3
- package/assets/.appweaver/scripts/python/aw-plangate.py +23 -16
- package/assets/.appweaver/scripts/python/aw-stack.py +1794 -265
- package/assets/.appweaver/stack-profiles/dotnet-webapi.json +0 -2
- package/assets/.appweaver/stack-profiles/java-spring.json +0 -2
- package/assets/.appweaver/templates/api-plan-template.md +107 -0
- package/assets/.appweaver/templates/delta-api-plan-template.md +87 -0
- package/assets/.appweaver/templates/delta-design-template.md +25 -23
- package/assets/.appweaver/templates/delta-spec-template.md +3 -3
- package/assets/.appweaver/templates/design-template.md +20 -42
- package/assets/.appweaver/templates/domain-model-template.md +3 -0
- package/assets/.appweaver/templates/ui-delta-design-template.md +11 -8
- package/assets/.appweaver/templates/ui-design-template.md +4 -4
- package/assets/foundations/foundation.spec.template.txt +25 -18
- package/assets/guardrails/README.md +61 -25
- package/assets/guardrails/methodology/ux/accessibility-standards.md +38 -0
- package/assets/guardrails/methodology/ux/content-design.md +34 -0
- package/assets/guardrails/methodology/ux/interaction-states.md +45 -0
- package/assets/guardrails/methodology/ux/journey-mapping.md +41 -0
- package/assets/guardrails/project-specific/domain/domain-requirements.md +25 -38
- package/assets/guardrails/project-specific/domain-rule-bindings.md +33 -69
- package/assets/guardrails/project-specific/frontend/ui-requirements.md +2 -2
- package/assets/guardrails/project-specific/service/technical-requirements.md +2 -2
- package/assets/guardrails/project-specific/tech-rule-bindings.md +16 -13
- package/assets/guardrails/sample-healthcare/domain/domain-requirements.md +58 -0
- package/assets/guardrails/sample-healthcare/domain-rule-bindings.md +138 -0
- package/assets/guardrails/sample-healthcare/frontend/ui-requirements.md +43 -0
- package/assets/guardrails/sample-healthcare/service/technical-requirements.md +40 -0
- package/assets/guardrails/sample-healthcare/tech-rule-bindings.md +303 -0
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +216 -7
- package/dist/commands/init.js.map +1 -1
- package/dist/utils/config.js +1 -1
- package/dist/utils/config.js.map +1 -1
- package/dist/utils/foundation.d.ts +36 -0
- package/dist/utils/foundation.d.ts.map +1 -0
- package/dist/utils/foundation.js +109 -0
- package/dist/utils/foundation.js.map +1 -0
- package/dist/utils/paths.js +1 -1
- package/dist/utils/paths.js.map +1 -1
- package/package.json +1 -1
|
@@ -2,8 +2,9 @@
|
|
|
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, the bounded context's domain-model.md
|
|
6
|
-
# aligned lane plans (+ a source-map.md sidecar),
|
|
5
|
+
# slice from its code into a living spec.md, the bounded context's domain-model.md, the
|
|
6
|
+
# API the slice publishes (api-plan.md) and aligned lane plans (+ a source-map.md sidecar),
|
|
7
|
+
# THEN reconciling this feature's evidence into the project governance that
|
|
7
8
|
# /appweaver onboard established. Adopt is the inverse of implement: implement reads the
|
|
8
9
|
# plans + the model and generates code; adopt reads code and generates the spec, the model
|
|
9
10
|
# and the plans — equally a reasoning step, stamped `origin: reverse-engineered` with
|
|
@@ -28,9 +29,12 @@
|
|
|
28
29
|
# project default). So adopt = reverse an EXISTING feature; the forward pipeline = a
|
|
29
30
|
# new one. Both then evolve through the CR delta loop.
|
|
30
31
|
#
|
|
31
|
-
# The reverse output is a NORMAL feature: spec.md, domain-model.md
|
|
32
|
-
# frontend-plan.md are the very documents the CR delta loop + forward
|
|
33
|
-
# unchanged — under those names, so nothing downstream needs a brownfield
|
|
32
|
+
# The reverse output is a NORMAL feature: spec.md, domain-model.md, api-plan.md and
|
|
33
|
+
# backend-plan.md / frontend-plan.md are the very documents the CR delta loop + forward
|
|
34
|
+
# pipeline consume unchanged — under those names, so nothing downstream needs a brownfield
|
|
35
|
+
# special case. The API plan is written from the kit's api-plan-template, which onboard
|
|
36
|
+
# does not override: its endpoint block form is the one the contract scripts read in every
|
|
37
|
+
# project, so only the plans around it follow the code's own structure.
|
|
34
38
|
# plan-scaffold's backend/frontend lanes also MIGRATE a legacy design.md / design.ui.md left
|
|
35
39
|
# by an adopt that ran before the rename, so an already-adopted repo is carried forward. All brownfield provenance
|
|
36
40
|
# lives in `origin:` frontmatter + the source-map sidecar. Adopt inits
|
|
@@ -71,7 +75,13 @@
|
|
|
71
75
|
# =============================================================================
|
|
72
76
|
|
|
73
77
|
name: aw-spec-adopt
|
|
74
|
-
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 its lane plans — backend-plan.md where a backend lane is declared and the slice has service code, 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)
|
|
78
|
+
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 its lane plans — api-plan.md (the endpoints the slice publishes, with the operation ids the code gives them) and backend-plan.md where a backend lane is declared and the slice has service code, 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), record its cross-slice edges and draw its API plan into api-draft.json, the API the frontend lane binds to. 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. Every reverse step is scoped to the feature's own operations from the confirmed boundary map, so two features over one aggregate never claim the same operation, and the spec continues the context's BR-nnn numbering from its domain model. Where a frontend lane is declared and this slice owns none of its surface, the feature records lanes=backend so later phases neither author nor demand a frontend plan for it. 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.
|
|
79
|
+
# 2.5.0 — the endpoints the slice publishes are reversed into the feature's own api-plan.md,
|
|
80
|
+
# before the backend plan, which realises them and points to it; the frontend plan
|
|
81
|
+
# takes its operation ids from the API plan and never reads the backend plan; the
|
|
82
|
+
# source-map and the fidelity check cover the API plan too; once fidelity passes,
|
|
83
|
+
# the API plan is drawn into api-draft.json, so the slice is in the frontend's
|
|
84
|
+
# combined document from the start.
|
|
75
85
|
# 2.3.0 — the SERVICE half is reversed only where the slice has one (svc_lane: a backend lane
|
|
76
86
|
# is declared and the slice has service files), the twin of ui_lane. A frontend-only
|
|
77
87
|
# project gets no backend plan and no cross-slice edges, and its model is read from
|
|
@@ -98,7 +108,7 @@ description: The JIT per-feature step of brownfield development — reverse-engi
|
|
|
98
108
|
# 1.3.0 — reverse design scaffolds from the DEFAULT `design-template` (onboard's code-derived
|
|
99
109
|
# override) instead of the never-shipped `brownfield-design-template`, unifying the
|
|
100
110
|
# whole brownfield pipeline on one code-derived template.
|
|
101
|
-
version: 2.
|
|
111
|
+
version: 2.5.0
|
|
102
112
|
agent_agnostic: true
|
|
103
113
|
dialect: aw-spec.orchestrator/v1
|
|
104
114
|
|
|
@@ -164,6 +174,21 @@ vars:
|
|
|
164
174
|
# left by an earlier adopt, so a repo that was adopted before the rename is carried
|
|
165
175
|
# forward rather than left with two spellings of one master.
|
|
166
176
|
backend_plan: ""
|
|
177
|
+
# THE API THE SLICE PUBLISHES — its own document, reversed before the backend plan, which
|
|
178
|
+
# realises each endpoint. `api_blocked` is the scaffold refusing because a backend plan
|
|
179
|
+
# already in the folder carries the endpoints: that plan keeps them for this run, as
|
|
180
|
+
# before API plans existed, and the frontend plan reads it in their place (`api_read`).
|
|
181
|
+
api_plan: ""
|
|
182
|
+
api_blocked: "false"
|
|
183
|
+
api_reverse: "false"
|
|
184
|
+
api_read: ""
|
|
185
|
+
draft_path: "" # api-draft.json, drawn after fidelity passes (contract_draft)
|
|
186
|
+
draft_plan: ""
|
|
187
|
+
draft_ops: "0"
|
|
188
|
+
draft_unread: "0"
|
|
189
|
+
draft_unread_text: ""
|
|
190
|
+
draft_clean: "true"
|
|
191
|
+
be_api_rule: "THE ENDPOINTS ARE IN api-plan.md (in context), reversed just before this document from the same code: the API contract the frontend lane binds to. Do NOT restate them here — the §2 axis that publishes them carries the one line pointing to api-plan.md, and where the template has an endpoint block or a requests table there (a template generated before API plans existed), that line goes in their place. REALISE every endpoint instead: each names under **Maps to** the code unit that serves it, and that unit is this document's element, under the same name, with request and response shapes that match the endpoint's. An endpoint with no element here is unrealised. The traceability spine cites an endpoint as `VERB /route`."
|
|
167
192
|
# THE BOUNDED CONTEXT'S DOMAIN MODEL — shared by every feature in the context, and the
|
|
168
193
|
# authority on the aggregate root, its entities and the TEXT of every BR-nnn. Reversed
|
|
169
194
|
# here in the same run as the spec, exactly as greenfield `specify` authors the two
|
|
@@ -172,6 +197,10 @@ vars:
|
|
|
172
197
|
context_dir: ""
|
|
173
198
|
domain_model: ""
|
|
174
199
|
domain_model_exists: "false"
|
|
200
|
+
model_guard_ok: "false" # model-guard-check's verdict on the reverse_model rewrite. DEFAULTS
|
|
201
|
+
# TO REFUSE: only the check's own `ok` lets the run past the gate
|
|
202
|
+
model_guard_losses: "" # what the rejected rewrite lost, one clause per item
|
|
203
|
+
model_guard_rejected: "" # where the rejected rewrite was kept
|
|
175
204
|
spec_exists: "false"
|
|
176
205
|
fidelity_ok: "false"
|
|
177
206
|
rulemap_exists: "false" # governance-present signal (onboard ran) — bound from resolve-domain
|
|
@@ -563,6 +592,21 @@ workflow:
|
|
|
563
592
|
action: set
|
|
564
593
|
vars: { model_files: "{{ui_source_files}}" }
|
|
565
594
|
|
|
595
|
+
# THE API PLAN FIRST, where the slice has a service half — scaffolded from the kit's
|
|
596
|
+
# api-plan-template before the backend plan, as `plan` does it: the scaffold refuses
|
|
597
|
+
# (`blocked`) while a backend plan in the folder carries the API, and a backend plan
|
|
598
|
+
# scaffolded from a template generated before API plans existed carries an empty requests
|
|
599
|
+
# table, so it must not be there yet.
|
|
600
|
+
- id: scaffold_api_plan
|
|
601
|
+
condition: "{{svc_lane}} == true"
|
|
602
|
+
action: execute_script
|
|
603
|
+
script: { ref: actions }
|
|
604
|
+
subcommand: plan-scaffold
|
|
605
|
+
args: ["--feature-dir", "{{feature_dir}}", "--lane", "api"]
|
|
606
|
+
outputs:
|
|
607
|
+
- { name: api_plan, from: "$.plan_doc" }
|
|
608
|
+
- { name: api_blocked, from: "$.blocked" }
|
|
609
|
+
|
|
566
610
|
- id: scaffold_plan
|
|
567
611
|
condition: "{{svc_lane}} == true"
|
|
568
612
|
action: execute_script
|
|
@@ -572,6 +616,22 @@ workflow:
|
|
|
572
616
|
outputs:
|
|
573
617
|
- { name: backend_plan, from: "$.plan_doc" }
|
|
574
618
|
|
|
619
|
+
# WHERE THE API IS REVERSED, and what the frontend plan reads of the service: the API plan
|
|
620
|
+
# just scaffolded — or, where the scaffold refused, the backend plan, which then keeps its
|
|
621
|
+
# endpoint blocks for this run. Nothing where the slice has no service half.
|
|
622
|
+
- id: api_reverse_arm
|
|
623
|
+
condition: "{{svc_lane}} == true"
|
|
624
|
+
action: set
|
|
625
|
+
vars: { api_reverse: "true", api_read: "{{api_plan}}" }
|
|
626
|
+
- id: api_reverse_blocked
|
|
627
|
+
condition: "{{api_blocked}} == true"
|
|
628
|
+
action: set
|
|
629
|
+
vars:
|
|
630
|
+
api_plan: ""
|
|
631
|
+
api_reverse: "false"
|
|
632
|
+
api_read: "{{backend_plan}}"
|
|
633
|
+
be_api_rule: "EVERY ENDPOINT THIS FEATURE PUBLISHES IS AN ENDPOINT BLOCK IN THIS DOCUMENT — a backend plan already in the folder carries the API, so it stays here for this run — in the §2 axis that publishes it: the heading `#### `VERB /route` — <purpose> · Serves <US/FR ids>`, then **Operation id**, Auth, Request, Success, the Errors table and Maps to, exactly as the template's endpoint block — never a row in a table of endpoints. The contract scripts read this form: the API draft is written from the headings, and the request ledger between the lanes reads the operation ids. The **Operation id** is the id the code publishes the endpoint under, spelled exactly as the code spells it; the boundary map records each operation's published id where the code declares one ('published as …' above). Where the code publishes none, write `—` and record a §5 DA-n saying the endpoint has no published operation id — never invent one: the service's as-built API document would not carry it, so the frontend would bind to an id the service does not answer, and analyze-slice would report it. After the endpoint blocks, a `#### Requests from the frontend lane` heading with `None` under it: a frontend reversed from the same code binds only to what the service already serves, so no request is open yet."
|
|
634
|
+
|
|
575
635
|
# Scaffold the LANE's plan from ITS template pair (--lane frontend resolves
|
|
576
636
|
# ui-design-template -> frontend-plan.md), the twin of scaffold_plan above. onboard
|
|
577
637
|
# GENERATED that override from this repo's own UI source, so the reversed frontend plan
|
|
@@ -741,6 +801,18 @@ workflow:
|
|
|
741
801
|
- { path: "{{spec_file}}" } # the reversed spec — the BR-nnn ids this model must define
|
|
742
802
|
- { path: "{{concept_path}}" } # source_files + seam
|
|
743
803
|
- { path: .appweaver/memory/constitution.domain.md, optional: true }
|
|
804
|
+
|
|
805
|
+
# THE REWRITE IS CHECKED. The engine writes the agent's reply over the WHOLE model, which
|
|
806
|
+
# on a context's second slice holds the sections, BR-/XBR- rules and ledger rows the
|
|
807
|
+
# features adopted or specified before it rely on. The snapshot copies it aside; the check
|
|
808
|
+
# after the step compares the two (python/aw-model-guard.py) and, on a loss, puts the
|
|
809
|
+
# model back and keeps the rewrite as domain-model.rejected.md.
|
|
810
|
+
- id: reverse_model_snapshot
|
|
811
|
+
action: execute_script
|
|
812
|
+
script: { ref: actions }
|
|
813
|
+
subcommand: model-guard-snapshot
|
|
814
|
+
args: ["--model", "{{domain_model}}"]
|
|
815
|
+
|
|
744
816
|
- id: reverse_model
|
|
745
817
|
action: agent_author
|
|
746
818
|
include_standards: false # the technical/arch sticky set is for the plans, never the model
|
|
@@ -784,6 +856,12 @@ workflow:
|
|
|
784
856
|
already there — other specs cite their ids, and a renumbered BR breaks every
|
|
785
857
|
citation silently. Add `{{feature_name}}` to the `Serving specs` line of any
|
|
786
858
|
existing aggregate this slice also acts on.
|
|
859
|
+
- A SCRIPT COMPARES YOUR FILE WITH THE MODEL AS IT WAS, and puts the old one back if
|
|
860
|
+
any of these is gone: an `## Aggregate:` section under its name; a BR-n or XBR-n,
|
|
861
|
+
in the same section, with the same rule text, defined once; a name on an
|
|
862
|
+
aggregate's `Serving specs` line; a Ubiquitous Language term; a context the
|
|
863
|
+
Context Map names; a Change History row; the Context version. Add to any of them
|
|
864
|
+
freely; never remove, rename, renumber, move or reword one.
|
|
787
865
|
- MODEL WHAT THE CODE EXHIBITS, NOT WHAT GOOD DESIGN WOULD WANT. Classify entities
|
|
788
866
|
vs value objects by whether the code gives the thing an IDENTITY; draw the
|
|
789
867
|
boundary where the code actually draws it (what it loads and saves together).
|
|
@@ -807,6 +885,95 @@ workflow:
|
|
|
807
885
|
Source files to read (the slice's code — its UI files where it has no service code,
|
|
808
886
|
the one place a frontend-only app keeps its types, states and rules): {{model_files}}
|
|
809
887
|
|
|
888
|
+
- id: reverse_model_check
|
|
889
|
+
action: execute_script
|
|
890
|
+
script: { ref: actions }
|
|
891
|
+
subcommand: model-guard-check
|
|
892
|
+
args: ["--model", "{{domain_model}}"]
|
|
893
|
+
outputs:
|
|
894
|
+
- { name: model_guard_ok, from: "$.ok" }
|
|
895
|
+
- { name: model_guard_losses, from: "$.losses_text" }
|
|
896
|
+
- { name: model_guard_rejected, from: "$.rejected" }
|
|
897
|
+
|
|
898
|
+
# On a stop the model is already restored; this slice's spec.md is written, so the
|
|
899
|
+
# already-adopted guard would refuse a plain re-run — the feature folder goes first.
|
|
900
|
+
- id: reverse_model_guard
|
|
901
|
+
action: verify_context
|
|
902
|
+
require_true: model_guard_ok
|
|
903
|
+
on_false: stop
|
|
904
|
+
on_false_message: "The domain model lost content other features rely on, so {{domain_model}} was put back as it was before this run. Lost: {{model_guard_losses}}. The rejected rewrite is kept at {{model_guard_rejected}} for inspection. This slice's spec.md was already written, so remove {{feature_dir}} and run /appweaver adopt {{feature_name}} again."
|
|
905
|
+
|
|
906
|
+
# ═══════════ REVERSE API PLAN — the endpoints the slice publishes, AS-BUILT ═══
|
|
907
|
+
# The contract between the lanes, reversed before the backend plan exactly as `plan`
|
|
908
|
+
# authors it first: the backend plan then realises each endpoint, and the frontend plan
|
|
909
|
+
# binds to the operation ids written here. One template in every project — the kit's
|
|
910
|
+
# api-plan-template, whose endpoint block form is what the contract scripts read — so the
|
|
911
|
+
# code decides which endpoints there are and what they carry, never the document's shape.
|
|
912
|
+
- id: ctx_reverse_api
|
|
913
|
+
condition: "{{api_reverse}} == true"
|
|
914
|
+
action: build_context
|
|
915
|
+
context:
|
|
916
|
+
- { path: "{{api_plan}}" } # the scaffolded template = the fixed endpoint block form
|
|
917
|
+
- { path: "{{spec_file}}" } # the reversed spec = the US/FR ids each endpoint serves
|
|
918
|
+
- { path: "{{domain_model}}" } # the ubiquitous language, and the BR-nnn an error answers to — READ, never written
|
|
919
|
+
- { path: "{{concept_path}}" } # source_files + seam
|
|
920
|
+
- { path: .appweaver/DESIGN-FORMAT.md } # the HLD contract, and The API plan in it
|
|
921
|
+
- { path: .appweaver/memory/constitution.technical.md, optional: true } # technology base ONLY — the protocol the service publishes
|
|
922
|
+
- id: reverse_api
|
|
923
|
+
condition: "{{api_reverse}} == true"
|
|
924
|
+
action: agent_author
|
|
925
|
+
include_standards: true # the technical sticky set (reference only — the CODE wins)
|
|
926
|
+
tools: Read # grounded in the CODE, which arrives as {{source_files}} paths
|
|
927
|
+
output_target: { type: file, path: "{{api_plan}}" }
|
|
928
|
+
task: |
|
|
929
|
+
Reverse-engineer the API PLAN of the feature '{{feature_name}}' (the target
|
|
930
|
+
api-plan.md in context — the kit's API plan template) FROM ITS CODE: every endpoint
|
|
931
|
+
the slice publishes for this feature. It is the API contract between the lanes — the
|
|
932
|
+
frontend plan binds to its operation ids, a script drafts it into api-draft.json,
|
|
933
|
+
analyze-slice checks the built service against it — and it is written BEFORE the
|
|
934
|
+
backend plan, which then realises each endpoint. READ the source files listed below;
|
|
935
|
+
the code is the SOURCE OF TRUTH.
|
|
936
|
+
Rules:
|
|
937
|
+
- DESCRIBE THE API AS-BUILT, quirks included: each endpoint's route, verb,
|
|
938
|
+
parameters, request and response fields, status codes and error bodies exactly as
|
|
939
|
+
the code serves them, with the field names as they appear on the wire. Never tidy
|
|
940
|
+
a route, rename a field or add a status the code does not return.
|
|
941
|
+
- THE FEATURE'S SCOPE. {{operations_note}} An endpoint that serves only a sibling
|
|
942
|
+
feature's operation is that feature's and is left out, even though its file is
|
|
943
|
+
listed; a read both features call is this feature's too.
|
|
944
|
+
- KEEP THE TEMPLATE'S FORM EXACTLY: one block per endpoint under "## Endpoints" — the
|
|
945
|
+
heading `### `VERB /route` — purpose · Serves …` citing the reversed spec's US/FR
|
|
946
|
+
ids, then **Operation id**, **Auth**, **Request**, **Success**, the **Errors** table
|
|
947
|
+
and **Maps to**. The contract scripts read exactly this form; an endpoint written
|
|
948
|
+
as a table row or in prose reaches neither api-draft.json nor the frontend.
|
|
949
|
+
- EVERY SHAPE IS `{ field: type }` in conceptual types (string, int, decimal, bool,
|
|
950
|
+
enum(A|B), list<T>, id<T>, money, date, datetime), never the code's own types. A
|
|
951
|
+
shape in prose reaches the frontend's client untyped.
|
|
952
|
+
- THE OPERATION ID is the id the code publishes the endpoint under, spelled exactly as
|
|
953
|
+
the code spells it; the boundary map records each operation's published id where
|
|
954
|
+
the code declares one (the scope line above). Where the code publishes none, write
|
|
955
|
+
`—` and say so in the block — never invent one: the service's as-built API document
|
|
956
|
+
would not carry it, so the frontend would bind to an id the service does not
|
|
957
|
+
answer, and analyze-slice would report it.
|
|
958
|
+
- **Maps to** names the code's own unit that serves the endpoint — its handler,
|
|
959
|
+
use-case or service operation — by the name the code gives it; the backend plan,
|
|
960
|
+
reversed next from the same code, realises it under that name.
|
|
961
|
+
- THE ERROR CONTRACT is what the code returns: one row per failure it actually
|
|
962
|
+
produces, with its status, when it is returned and its body shape. An error the
|
|
963
|
+
code never produces is not written.
|
|
964
|
+
- Under "## Requests from the frontend lane" write `None`: a frontend reversed from
|
|
965
|
+
the same code binds only to what the service already serves, so no request is
|
|
966
|
+
open yet.
|
|
967
|
+
- A SERVICE THAT PUBLISHES ANOTHER PROTOCOL (messages, remote procedures) states each
|
|
968
|
+
operation in the same block form, headed by the code's own name for it.
|
|
969
|
+
- Write `None` under "## Endpoints" when the slice publishes no endpoint.
|
|
970
|
+
- TECHNOLOGY-AGNOSTIC: protocol level only — no controller code, framework
|
|
971
|
+
attributes, serializer settings or language types.
|
|
972
|
+
- Add `origin: reverse-engineered` near the Version field. This is v1.0: write the
|
|
973
|
+
first Change History row.
|
|
974
|
+
|
|
975
|
+
Source files to read (the slice's code): {{source_files}}
|
|
976
|
+
|
|
810
977
|
# ═══════════ REVERSE BACKEND PLAN — from the SPEC + MODEL + CODE, AS-BUILT ═══
|
|
811
978
|
# Anchored to the reversed spec's ids (§4 Traceability → forward-compatible),
|
|
812
979
|
# grounded in the code's ACTUAL structure, tech-agnostic. NO domain rule files (rule
|
|
@@ -820,6 +987,7 @@ workflow:
|
|
|
820
987
|
context:
|
|
821
988
|
- { path: "{{backend_plan}}" } # the scaffolded code-derived template = structure + embedded guidance
|
|
822
989
|
- { path: "{{spec_file}}" } # the reversed spec = WHAT the slice must do
|
|
990
|
+
- { path: "{{api_plan}}", optional: true } # the reversed API = the endpoints this plan realises — absent where the scaffold refused
|
|
823
991
|
- { path: "{{domain_model}}" } # the reversed model = what the domain IS — READ, never written here
|
|
824
992
|
- { path: "{{concept_path}}" } # source_files + seam (structure hints)
|
|
825
993
|
- { path: .appweaver/DESIGN-FORMAT.md } # the HLD contract (see its Brownfield variant note)
|
|
@@ -871,21 +1039,7 @@ workflow:
|
|
|
871
1039
|
the EXTERNAL INTEGRATIONS table (heading contains "Integration") realising the
|
|
872
1040
|
spec's IC-. Realise CN- (structural → §1.2 invariants/events; retention/audit →
|
|
873
1041
|
§2 persistence / §3 cross-cutting), DC- (§3 + projection surface).
|
|
874
|
-
-
|
|
875
|
-
publishes it: the heading `#### `VERB /route` — <purpose> · Serves <US/FR ids>`, then
|
|
876
|
-
**Operation id**, Auth, Request, Success, the Errors table and Maps to, exactly as
|
|
877
|
-
the template's endpoint block — never a row in a table of endpoints. The contract
|
|
878
|
-
scripts read this form: the API draft is written from the headings, and the request
|
|
879
|
-
ledger between the lanes reads the operation ids. The **Operation id** is the id the
|
|
880
|
-
code publishes the endpoint under, spelled exactly as the code spells it; the
|
|
881
|
-
boundary map records each operation's published id where the code declares one
|
|
882
|
-
("published as …" above). Where the code publishes none, write `—` and record a §5
|
|
883
|
-
DA-n saying the endpoint has no published operation id — never invent one: the
|
|
884
|
-
service's exported API document would not carry it, so nothing could bind to it.
|
|
885
|
-
- After the endpoint blocks, a `#### Requests from the frontend lane` heading with
|
|
886
|
-
`None` under it: a frontend reversed from the same code binds only to what the
|
|
887
|
-
service already serves, so no request is open yet. Later plans answer requests
|
|
888
|
-
there.
|
|
1042
|
+
- {{be_api_rule}}
|
|
889
1043
|
- AS-BUILT DEBT, not architecture drift. §6 records ONLY debt the CODE ITSELF
|
|
890
1044
|
evidences — stubs/no-ops, dead or duplicate code, torn seams (shared table/
|
|
891
1045
|
transaction), TODOs, hard-coded values. The code being organised differently
|
|
@@ -904,8 +1058,9 @@ workflow:
|
|
|
904
1058
|
# ═══════ REVERSE UI DESIGN — the LANE's half, from the UI code, AS-BUILT ═══
|
|
905
1059
|
# Runs only where this slice HAS a surface (ui_lane). The service design above is
|
|
906
1060
|
# NOT its parent: backend-plan.md realises the spec's FR/BR/CN-, frontend-plan.md
|
|
907
|
-
# realises the spec's UX- and the user stories' interaction, and it CONSUMES the
|
|
908
|
-
# plan's contracts rather than restating them.
|
|
1061
|
+
# realises the spec's UX- and the user stories' interaction, and it CONSUMES the API
|
|
1062
|
+
# plan's contracts rather than restating them. The spec and the API plan are in context
|
|
1063
|
+
# for exactly that reason; the backend plan, the service's internals, is not.
|
|
909
1064
|
# THE FRONTEND'S RULES REPLACE THE BACKEND'S before the lane's plan is authored — the
|
|
910
1065
|
# swap the forward `plan` makes at the same boundary. Sticky standards only accumulate,
|
|
911
1066
|
# so without it the UI plan was authored under the service rule set and none of the
|
|
@@ -923,7 +1078,7 @@ workflow:
|
|
|
923
1078
|
context:
|
|
924
1079
|
- { path: "{{frontend_plan}}" } # the scaffolded code-derived lane template = structure + embedded guidance
|
|
925
1080
|
- { path: "{{spec_file}}" } # the reversed spec — UX- + the user stories this surface serves
|
|
926
|
-
- { path: "{{
|
|
1081
|
+
- { path: "{{api_read}}", optional: true } # the API plan — the contracts the UI consumes, never re-specified here; absent with no service lane
|
|
927
1082
|
- { path: "{{domain_model}}", optional: true } # the ubiquitous language labels and states must use — READ, never written
|
|
928
1083
|
- { path: .appweaver/memory/constitution.ui.md, optional: true } # the lane's UX-* base, reversed by onboard from this same UI
|
|
929
1084
|
- { path: "{{bundle_dir}}/architecture/frontend.md", optional: true } # the as-built UI architecture + the SHARED surface no slice owns
|
|
@@ -949,16 +1104,17 @@ workflow:
|
|
|
949
1104
|
operation — typically that feature's own UI folder — is that feature's. Where this
|
|
950
1105
|
feature's screen hosts it, cite it as the sibling's; never plan it here.
|
|
951
1106
|
- STAY IN THE LANE. Realise the spec's Experience Standards (UX-) and the
|
|
952
|
-
interaction its User Stories imply. The
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
1107
|
+
interaction its User Stories imply. The API plan (in context — api-plan.md, or the
|
|
1108
|
+
backend plan where this feature's endpoints stayed in it) supplies the CONTRACTS
|
|
1109
|
+
this surface consumes — cite them; do NOT restate, re-derive or contradict them,
|
|
1110
|
+
and introduce no server-side behaviour here. With no API plan in context the
|
|
1111
|
+
service is outside this repo: bind against the routes the UI code calls and the
|
|
1112
|
+
spec's IC-, as an external contract. Where the domain
|
|
957
1113
|
model is in context, use its UBIQUITOUS LANGUAGE exactly in labels, states and
|
|
958
1114
|
messages, and cite BR-nnn rather than restating a rule.
|
|
959
1115
|
- CONTRACT BINDING CITES OPERATION IDS. Each row of the Contract Binding table names,
|
|
960
|
-
in its Operation id column, the **Operation id**
|
|
961
|
-
the UI code calls — `—` where the
|
|
1116
|
+
in its Operation id column, the **Operation id** the API plan gives the endpoint
|
|
1117
|
+
the UI code calls — `—` where the API plan records none. The id is how
|
|
962
1118
|
implement finds the endpoint, and how a later change that alters or removes it is
|
|
963
1119
|
reported to this lane. The "Contract deltas needed" table reads `None`: the UI calls
|
|
964
1120
|
only what the service already serves.
|
|
@@ -987,6 +1143,7 @@ workflow:
|
|
|
987
1143
|
- { path: .appweaver/templates/source-map-template.md } # the sidecar structure
|
|
988
1144
|
- { path: "{{spec_file}}" }
|
|
989
1145
|
- { path: "{{backend_plan}}", optional: true } # the service lane's plan, where this slice has one
|
|
1146
|
+
- { path: "{{api_plan}}", optional: true } # the endpoints the slice publishes, where it has a service half
|
|
990
1147
|
- { path: "{{frontend_plan}}", optional: true } # the lane's design, where this slice has one
|
|
991
1148
|
- { path: "{{concept_path}}" } # both file lists to map
|
|
992
1149
|
- id: source_map
|
|
@@ -1000,7 +1157,8 @@ workflow:
|
|
|
1000
1157
|
spine — it keeps spec.md / backend-plan.md clean while recording provenance here.
|
|
1001
1158
|
- One row per legacy artefact in the bundle concept's `source_files` (read
|
|
1002
1159
|
them under {{module_dir}}): map each to the spec ids (FR/BR/US/CN/DC/IC)
|
|
1003
|
-
and the backend-plan element (§/name) that now describe it,
|
|
1160
|
+
and the backend-plan element (§/name) that now describe it — and, for a file
|
|
1161
|
+
that publishes an endpoint, its `VERB /route` block in api-plan.md — with CONFIDENCE
|
|
1004
1162
|
(certain | inferred). EVERY source file MUST appear — the Fidelity gate
|
|
1005
1163
|
checks full coverage both ways.
|
|
1006
1164
|
- THE CONCEPT IS THE AGGREGATE'S ('{{aggregate_primary}}') and lists every feature's
|
|
@@ -1042,6 +1200,7 @@ workflow:
|
|
|
1042
1200
|
- "{{spec_file}}"
|
|
1043
1201
|
- "{{domain_model}}"
|
|
1044
1202
|
- { path: "{{backend_plan}}", optional: true } # the service lane's plan, where this slice has one
|
|
1203
|
+
- { path: "{{api_plan}}", optional: true } # the endpoints it publishes, where this slice has a service half
|
|
1045
1204
|
- { path: "{{frontend_plan}}", optional: true } # the lane's plan, where this slice has one
|
|
1046
1205
|
- "{{feature_dir}}/source-map.md"
|
|
1047
1206
|
- "{{concept_path}}"
|
|
@@ -1056,7 +1215,10 @@ workflow:
|
|
|
1056
1215
|
{{module_dir}}). Where frontend-plan.md is in context, it is judged the same way
|
|
1057
1216
|
against the slice's UI files ({{ui_source_files}}) — a screen, state store or
|
|
1058
1217
|
route it describes that the UI code does not have is a fabricated-plan, and a
|
|
1059
|
-
UI file with no home in the source-map is unmapped-code.
|
|
1218
|
+
UI file with no home in the source-map is unmapped-code. Where api-plan.md is in
|
|
1219
|
+
context, it is judged against the service code the same way: an endpoint the code
|
|
1220
|
+
does not serve, a field or status it does not have, or an operation id the code does
|
|
1221
|
+
not publish is a fabricated-plan. Classify findings:
|
|
1060
1222
|
- BLOCKING (structural — set ok=false if any):
|
|
1061
1223
|
(1) unmapped-code: a source file with NO home in the source-map — one recorded
|
|
1062
1224
|
there as `sibling: <Feature>` has a home;
|
|
@@ -1106,6 +1268,7 @@ workflow:
|
|
|
1106
1268
|
- "{{spec_file}}"
|
|
1107
1269
|
- "{{domain_model}}"
|
|
1108
1270
|
- { path: "{{backend_plan}}", optional: true }
|
|
1271
|
+
- { path: "{{api_plan}}", optional: true }
|
|
1109
1272
|
- { path: "{{frontend_plan}}", optional: true }
|
|
1110
1273
|
- "{{feature_dir}}/source-map.md"
|
|
1111
1274
|
output_target: { type: file, path: "{{feature_dir}}/adopt-review-report.md" }
|
|
@@ -1137,7 +1300,7 @@ workflow:
|
|
|
1137
1300
|
action: verify_context
|
|
1138
1301
|
require_true: fidelity_ok
|
|
1139
1302
|
on_false: stop
|
|
1140
|
-
on_false_message: "Fidelity FAILED for {{feature_name}} — the reversed documents do not match the code (blocking gaps: {{blocking_gaps}}). See {{feature_dir}}/adopt-review-report.md. Resolve it one of two ways. RE-ADOPT: remove {{feature_dir}} and run /appweaver adopt {{feature_name}} again; the documents are reversed afresh from the code, so edits made to them first are not kept. Removing the folder leaves what this run added to {{domain_model}} (git diff shows it), and a re-adopt extends it, so remove that first. CORRECT BY HAND: re-read the source and refine spec.md, {{domain_model}}, the lane plans this slice has (backend: {{backend_plan}}; frontend: {{frontend_plan}}) and source-map.md — map the unmapped code, remove what is fabricated. This run stopped before it completed the OKF concept {{aggregate_primary}}
|
|
1303
|
+
on_false_message: "Fidelity FAILED for {{feature_name}} — the reversed documents do not match the code (blocking gaps: {{blocking_gaps}}). See {{feature_dir}}/adopt-review-report.md. Resolve it one of two ways. RE-ADOPT: remove {{feature_dir}} and run /appweaver adopt {{feature_name}} again; the documents are reversed afresh from the code, so edits made to them first are not kept. Removing the folder leaves what this run added to {{domain_model}} (git diff shows it), and a re-adopt extends it, so remove that first. CORRECT BY HAND: re-read the source and refine spec.md, {{domain_model}}, the API plan and lane plans this slice has (API: {{api_plan}}; backend: {{backend_plan}}; frontend: {{frontend_plan}}) and source-map.md — map the unmapped code, remove what is fabricated. This run stopped before it completed the OKF concept {{aggregate_primary}}, recorded cross-slice edges and drew the API draft, so on this path the concept and the edges stay as onboard left them and the slice has no api-draft.json until /appweaver analyze-plan draws it. 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. A `foreign-operation` gap means a document claims an operation the boundary map gives only to another feature; remove it here — it belongs to that feature's adopt."
|
|
1141
1304
|
|
|
1142
1305
|
# ═══════════ OKF CONCEPT — COMPLETE the shallow scan concept (deep reverse) ═══
|
|
1143
1306
|
# onboard wrote this aggregate's OKF concept SHALLOW (a discovery stub — enough to pick the
|
|
@@ -1155,6 +1318,7 @@ workflow:
|
|
|
1155
1318
|
- { path: "{{spec_file}}" } # the deep reversed spec (entities, US, BR/CN/DC/IC)
|
|
1156
1319
|
- { path: "{{domain_model}}" } # the deep reversed model (entities, boundary, invariants)
|
|
1157
1320
|
- { path: "{{backend_plan}}", optional: true } # the deep reversed service plan (components, ports, integrations), where the slice has one
|
|
1321
|
+
- { path: "{{api_plan}}", optional: true } # the deep reversed API (the endpoints it publishes), where the slice has a service half
|
|
1158
1322
|
- { path: "{{frontend_plan}}", optional: true } # the deep reversed UI plan, where the slice has one
|
|
1159
1323
|
- { path: "{{feature_dir}}/source-map.md" } # the source anchor (files, seam, quirks)
|
|
1160
1324
|
- { path: .appweaver/templates/okf-concept-template.md } # OKF v0.1 format authority
|
|
@@ -1167,8 +1331,8 @@ workflow:
|
|
|
1167
1331
|
COMPLETE the OKF concept of the aggregate '{{aggregate_primary}}' at {{concept_path}} —
|
|
1168
1332
|
the aggregate this run adopted the feature '{{feature_name}}' over. onboard wrote it
|
|
1169
1333
|
SHALLOW (a discovery stub from the whole-repo scan). The deep reverse has now
|
|
1170
|
-
produced a TRUSTWORTHY spec.md + domain-model.md +
|
|
1171
|
-
context); deepen the
|
|
1334
|
+
produced a TRUSTWORTHY spec.md + domain-model.md + api-plan.md + backend-plan.md +
|
|
1335
|
+
source-map.md (in context, each the slice has); deepen the
|
|
1172
1336
|
concept to match and LINK those artifacts. Follow the OKF concept template in context.
|
|
1173
1337
|
THE CONCEPT IS THE AGGREGATE'S, NOT THE FEATURE'S. Where its `features:` names more
|
|
1174
1338
|
than one feature, another feature's adopt may already have deepened it, and nothing
|
|
@@ -1180,8 +1344,9 @@ workflow:
|
|
|
1180
1344
|
the authority on them; correct any drift the shallow scan got wrong (the deep docs
|
|
1181
1345
|
win). A sibling capability's commands and endpoints stay where they are.
|
|
1182
1346
|
- LINK the deep artifacts: add bundle links to {{feature_dir}}/spec.md,
|
|
1183
|
-
backend-plan.md, source-map.md and the context's domain-model.md
|
|
1184
|
-
points at the deep truth. Keep every link another
|
|
1347
|
+
backend-plan.md, api-plan.md, source-map.md and the context's domain-model.md (each
|
|
1348
|
+
the slice has) so the concept points at the deep truth. Keep every link another
|
|
1349
|
+
feature's adopt added.
|
|
1185
1350
|
- UNION `source_files` with the source-map's mapped files (grouped by the code's OWN
|
|
1186
1351
|
folders, per OKF) — never drop a file already listed, which may be a sibling
|
|
1187
1352
|
capability's. The boundary map was drawn at the baseline commit, whose time is
|
|
@@ -1222,6 +1387,37 @@ workflow:
|
|
|
1222
1387
|
- { name: xref_wrote, from: "$.wrote" }
|
|
1223
1388
|
- { name: xref_edge_count, from: "$.edge_count" }
|
|
1224
1389
|
|
|
1390
|
+
# 3c. THE API DRAFT — api-draft.json beside the plans, drawn by script from the API plan just
|
|
1391
|
+
# reversed (the backend plan, where its endpoints stayed in it): the API contract the
|
|
1392
|
+
# frontend lane's combined document reads and analyze-slice checks the built service
|
|
1393
|
+
# against. Drawn here, after fidelity passed, so the adopted slice is in the combined
|
|
1394
|
+
# document from the start rather than only once plan or analyze-plan next runs for it.
|
|
1395
|
+
# Advisory — a plan the script cannot read leaves the run going; a shape it cannot type
|
|
1396
|
+
# is reported, because the frontend's client gets that data untyped.
|
|
1397
|
+
- id: contract_draft
|
|
1398
|
+
condition: "{{svc_lane}} == true"
|
|
1399
|
+
action: execute_script
|
|
1400
|
+
on_error: continue
|
|
1401
|
+
script: { ref: actions }
|
|
1402
|
+
subcommand: contract-draft
|
|
1403
|
+
args: ["--feature-dir", "{{feature_dir}}"]
|
|
1404
|
+
outputs:
|
|
1405
|
+
- { name: draft_path, from: "$.path" }
|
|
1406
|
+
- { name: draft_plan, from: "$.plan" }
|
|
1407
|
+
- { name: draft_ops, from: "$.operations" }
|
|
1408
|
+
- { name: draft_unread, from: "$.unread_count" }
|
|
1409
|
+
- { name: draft_unread_text, from: "$.unread_text" }
|
|
1410
|
+
- id: draft_unread_flag
|
|
1411
|
+
condition: "{{draft_unread}} != 0"
|
|
1412
|
+
action: set
|
|
1413
|
+
vars: { draft_clean: "false" }
|
|
1414
|
+
- id: warn_draft_unread
|
|
1415
|
+
condition: "{{svc_lane}} == true"
|
|
1416
|
+
action: verify_context
|
|
1417
|
+
require_true: draft_clean
|
|
1418
|
+
on_false: continue
|
|
1419
|
+
on_false_message: "API DRAFT — {{draft_unread}} endpoint shape(s) in {{draft_plan}} are not written as `{ field: type }`, so the frontend's client gets that data untyped: {{draft_unread_text}}. Write each request and response the way the API plan template's endpoint block does, with the fields the code puts on the wire, then run /appweaver analyze-plan, which redraws the draft."
|
|
1420
|
+
|
|
1225
1421
|
# ═══════════ GOVERNANCE RECONCILE — upgrade onboard's PROVISIONAL scaffold ═══
|
|
1226
1422
|
# ⏸ HELD 2026-07-29: every step in this block is gated on `reconcile_governance`
|
|
1227
1423
|
# (default "false"), so adopt currently does NOT touch the constitution halves
|
|
@@ -1432,6 +1628,9 @@ workflow:
|
|
|
1432
1628
|
outputs:
|
|
1433
1629
|
feature_dir: "{{feature_dir}}"
|
|
1434
1630
|
spec_file: "{{spec_file}}"
|
|
1631
|
+
api_plan: "{{api_plan}}" # empty where this slice has no service half, or its backend plan keeps the endpoints
|
|
1632
|
+
api_draft: "{{draft_path}}" # api-draft.json drawn from it — empty where the slice has no service half or publishes no endpoint
|
|
1633
|
+
api_draft_operations: "{{draft_ops}}"
|
|
1435
1634
|
backend_plan: "{{backend_plan}}"
|
|
1436
1635
|
frontend_plan: "{{frontend_plan}}" # empty where this slice has no UI half
|
|
1437
1636
|
domain_model: "{{domain_model}}" # the CONTEXT's, shared — this run ADDED an aggregate section to it
|
|
@@ -1458,4 +1657,4 @@ outputs:
|
|
|
1458
1657
|
composed_file: "{{composed_file}}"
|
|
1459
1658
|
technical_reconcile_ok: "{{technical_ok}}"
|
|
1460
1659
|
domain_reconcile_ok: "{{domain_ok}}"
|
|
1461
|
-
next: "Adopted {{feature_name}} (spec.md, source-map.md and the lane plans this slice has — backend: {{backend_plan}}; frontend: {{frontend_plan}} — v1.0) and wrote {{aggregate_sections}} — the model section(s) for the aggregate(s) it acts on, resolved from the {{aggregate_source}} — in 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. A section another feature over the same aggregate wrote first was EXTENDED, never duplicated; every other section is untouched. COMPLETED the OKF concept of {{aggregate_primary}} (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. In the second case, where a frontend lane IS declared, the feature records lanes=[backend] in its active_version.json (feature_lanes shows it), so plan and the analyze gates treat the frontend lane as absent for THIS feature; run `aw-spec-actions feature-lanes --clear` if it later gains a UI. SERVICE HALF: svc_lane={{svc_lane}} — false where the repo declares no backend lane (a frontend-only project: no backend plan, no cross-slice edges, and the model was read from the UI code) or this slice has no service code; in the second case, where a frontend lane carries it, the feature records lanes=[frontend] the same way. 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/{{gov_domain}}/ rule set, so they keep onboard's provisional scaffold. Close any items in {{feature_dir}}/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."
|
|
1660
|
+
next: "Adopted {{feature_name}} (spec.md, source-map.md, the API plan and the lane plans this slice has — API: {{api_plan}}; backend: {{backend_plan}}; frontend: {{frontend_plan}} — v1.0) and wrote {{aggregate_sections}} — the model section(s) for the aggregate(s) it acts on, resolved from the {{aggregate_source}} — in 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. A section another feature over the same aggregate wrote first was EXTENDED, never duplicated; every other section is untouched. COMPLETED the OKF concept of {{aggregate_primary}} (deepened + linked the deep artifacts; {{xref_edge_count}} cross-slice edge(s) recorded). API DRAFT: {{draft_ops}} operation(s) drawn from the API plan into api-draft.json beside it, the API the frontend lane binds to and analyze-slice checks the service against (0 where the slice has no service half). 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. In the second case, where a frontend lane IS declared, the feature records lanes=[backend] in its active_version.json (feature_lanes shows it), so plan and the analyze gates treat the frontend lane as absent for THIS feature; run `aw-spec-actions feature-lanes --clear` if it later gains a UI. SERVICE HALF: svc_lane={{svc_lane}} — false where the repo declares no backend lane (a frontend-only project: no backend plan, no cross-slice edges, and the model was read from the UI code) or this slice has no service code; in the second case, where a frontend lane carries it, the feature records lanes=[frontend] the same way. 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/{{gov_domain}}/ rule set, so they keep onboard's provisional scaffold. Close any items in {{feature_dir}}/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."
|