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.
- package/assets/.appweaver/DESIGN-FORMAT.md +45 -21
- package/assets/.appweaver/orchestrator/modules/delta-plan.orch.yaml +62 -14
- package/assets/.appweaver/orchestrator/modules/delta-spec.orch.yaml +6 -4
- package/assets/.appweaver/orchestrator/modules/lane-gate.orch.yaml +9 -1
- package/assets/.appweaver/orchestrator/modules/tech-select.orch.yaml +21 -0
- package/assets/.appweaver/orchestrator/orchestrator.py +23 -1
- package/assets/.appweaver/orchestrator/rev-templates/design-template.skeleton.md +18 -11
- package/assets/.appweaver/orchestrator/rev-templates/ui-design-template.skeleton.md +5 -3
- package/assets/.appweaver/orchestrator/workflows/aw-spec-adopt.orch.yaml +298 -109
- package/assets/.appweaver/orchestrator/workflows/aw-spec-analyze-plan.orch.yaml +161 -34
- package/assets/.appweaver/orchestrator/workflows/aw-spec-analyze-slice.orch.yaml +125 -24
- package/assets/.appweaver/orchestrator/workflows/aw-spec-build.orch.yaml +18 -7
- package/assets/.appweaver/orchestrator/workflows/aw-spec-close-delta.orch.yaml +182 -39
- package/assets/.appweaver/orchestrator/workflows/aw-spec-finalize-delta.orch.yaml +300 -35
- package/assets/.appweaver/orchestrator/workflows/aw-spec-implement.orch.yaml +190 -31
- package/assets/.appweaver/orchestrator/workflows/aw-spec-onboard.orch.yaml +93 -8
- package/assets/.appweaver/orchestrator/workflows/aw-spec-plan.orch.yaml +34 -7
- package/assets/.appweaver/orchestrator/workflows/aw-spec-recall-delta.orch.yaml +319 -0
- package/assets/.appweaver/orchestrator/workflows/aw-spec-specify.orch.yaml +125 -24
- package/assets/.appweaver/scripts/bash/aw-spec-actions.sh +846 -35
- package/assets/.appweaver/scripts/bash/common.sh +28 -1
- package/assets/.appweaver/scripts/powershell/aw-spec-actions.ps1 +843 -46
- package/assets/.appweaver/scripts/python/aw-inventory.py +3 -2
- package/assets/.appweaver/templates/design-template.md +41 -30
- package/assets/.appweaver/templates/spec-template.md +7 -4
- package/assets/.appweaver/templates/ui-design-template.md +7 -3
- package/assets/guardrails/domain/healthcare/auditing.domain.md +3 -3
- package/assets/guardrails/domain/pharma/auditing.domain.md +3 -3
- package/assets/guardrails/technology/dotnet-webapi/api-versioning.md +1 -1
- package/assets/guardrails/technology/dotnet-webapi/auditing.md +1 -1
- package/assets/guardrails/technology/dotnet-webapi/authorization.md +1 -1
- package/assets/guardrails/technology/dotnet-webapi/clean-architecture.md +1 -1
- package/assets/guardrails/technology/dotnet-webapi/cqrs.md +1 -1
- package/assets/guardrails/technology/dotnet-webapi/data-classification.md +1 -1
- package/assets/guardrails/technology/dotnet-webapi/eventing.md +1 -1
- package/assets/guardrails/technology/dotnet-webapi/folder-structure.md +1 -1
- package/assets/guardrails/technology/dotnet-webapi/modular-monolith.md +1 -1
- package/assets/guardrails/technology/dotnet-webapi/persistence.md +1 -1
- package/assets/guardrails/technology/dotnet-webapi/vertical-slices.md +1 -1
- package/assets/guardrails/technology/dotnet-webapi/zero-trust.md +1 -1
- package/assets/guardrails/technology/nextjs/accessibility-implementation.md +1 -1
- package/assets/guardrails/technology/nextjs/api-integration.dotnet-webapi.md +1 -1
- package/assets/guardrails/technology/nextjs/api-integration.java-spring.md +1 -1
- package/assets/guardrails/technology/nextjs/auth-session.md +1 -1
- package/assets/guardrails/technology/nextjs/component-architecture.md +1 -1
- package/assets/guardrails/technology/nextjs/design-system.md +1 -1
- package/assets/guardrails/technology/nextjs/error-handling.md +1 -1
- package/assets/guardrails/technology/nextjs/forms-and-validation.md +1 -1
- package/assets/guardrails/technology/nextjs/i18n.md +1 -1
- package/assets/guardrails/technology/nextjs/performance-budgets.md +1 -1
- package/assets/guardrails/technology/nextjs/routing-navigation.md +1 -1
- package/assets/guardrails/technology/nextjs/state-management.md +1 -1
- 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
|
|
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
|
-
#
|
|
9
|
-
# a reasoning step, stamped `origin: reverse-engineered` with
|
|
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
|
|
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
|
|
22
|
-
# the CR delta loop + forward pipeline consume
|
|
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
|
|
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:
|
|
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
|
-
|
|
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
|
|
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
|
|
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.)
|
|
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
|
-
-
|
|
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:
|
|
263
|
-
args: ["--feature-dir", "{{feature_dir}}"]
|
|
340
|
+
subcommand: model-scaffold
|
|
341
|
+
args: ["--feature-dir", "{{feature_dir}}"]
|
|
264
342
|
outputs:
|
|
265
|
-
- { name:
|
|
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
|
|
303
|
-
# ui-design-template ->
|
|
304
|
-
# GENERATED that override from this repo's own UI source, so the reversed
|
|
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:
|
|
392
|
+
- id: scaffold_ui_plan
|
|
307
393
|
condition: "{{ui_lane}} == true"
|
|
308
394
|
action: execute_script
|
|
309
395
|
script: { ref: actions }
|
|
310
|
-
subcommand:
|
|
311
|
-
args: ["--feature-dir", "{{feature_dir}}", "--lane", "
|
|
396
|
+
subcommand: plan-scaffold
|
|
397
|
+
args: ["--feature-dir", "{{feature_dir}}", "--lane", "frontend"]
|
|
312
398
|
outputs:
|
|
313
|
-
- { name:
|
|
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
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
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
|
-
#
|
|
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)
|
|
426
|
-
#
|
|
427
|
-
#
|
|
428
|
-
|
|
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: "{{
|
|
432
|
-
- { path: "{{spec_file}}" } # the reversed spec = the
|
|
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:
|
|
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: "{{
|
|
598
|
+
output_target: { type: file, path: "{{backend_plan}}" }
|
|
442
599
|
task: |
|
|
443
|
-
Reverse-engineer the
|
|
444
|
-
context — it is the BROWNFIELD
|
|
445
|
-
MEDIATES the reversed spec ↔ the existing code. Ground every element
|
|
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
|
|
455
|
-
actual STRUCTURE — and NO domain rule
|
|
456
|
-
|
|
457
|
-
→ surface it (it belongs in the spec
|
|
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
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
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:
|
|
490
|
-
# spec's UX- and the user stories' interaction, and it CONSUMES
|
|
491
|
-
# rather than restating them. Both are in context for exactly that reason.
|
|
492
|
-
- id:
|
|
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: "{{
|
|
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: "{{
|
|
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:
|
|
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: "{{
|
|
669
|
+
output_target: { type: file, path: "{{frontend_plan}}" }
|
|
507
670
|
task: |
|
|
508
|
-
Reverse-engineer the FRONTEND LANE's
|
|
509
|
-
in context — it is this project's code-derived UI
|
|
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
|
|
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: "{{
|
|
547
|
-
- { path: "{{
|
|
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 /
|
|
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
|
|
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
|
|
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
|
-
#
|
|
577
|
-
#
|
|
578
|
-
# BLOCKING gaps = unmapped code / fabricated spec
|
|
579
|
-
# rest (inferred items, quirks, missing-invariant candidates) are
|
|
580
|
-
# → written to an Adopt Review report and closed OUT OF BAND (Brownfield
|
|
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
|
-
- "{{
|
|
586
|
-
-
|
|
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
|
|
591
|
-
schema: { ok: true, report_needed: false, blocking_gaps: [ { severity: "high", artefact: "<source file / spec id /
|
|
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
|
-
(
|
|
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
|
|
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-
|
|
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
|
|
603
|
-
(2) fabricated-spec / fabricated-
|
|
604
|
-
basis in the code (reverse-engineering must
|
|
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}}", "{{
|
|
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↔
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
on-touch fence) — it is
|
|
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
|
|
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 +
|
|
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: "{{
|
|
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 +
|
|
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
|
-
|
|
682
|
-
|
|
683
|
-
|
|
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
|
|
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", "{{
|
|
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: "{{
|
|
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 +
|
|
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: "{{
|
|
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
|
|
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
|
-
|
|
925
|
-
|
|
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 +
|
|
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."
|