aw-spec-cli 0.1.18 → 0.1.20
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 +63 -31
- package/assets/.appweaver/orchestrator/modules/delta-plan.orch.yaml +62 -14
- package/assets/.appweaver/orchestrator/modules/delta-spec.orch.yaml +10 -6
- 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/delta-design-template.skeleton.md +1 -1
- package/assets/.appweaver/orchestrator/rev-templates/design-template.skeleton.md +22 -13
- package/assets/.appweaver/orchestrator/rev-templates/ui-delta-design-template.skeleton.md +1 -1
- package/assets/.appweaver/orchestrator/rev-templates/ui-design-template.skeleton.md +6 -4
- package/assets/.appweaver/orchestrator/workflows/aw-spec-adopt.orch.yaml +399 -131
- package/assets/.appweaver/orchestrator/workflows/aw-spec-analyze-plan-delta.orch.yaml +1 -1
- package/assets/.appweaver/orchestrator/workflows/aw-spec-analyze-plan.orch.yaml +199 -38
- package/assets/.appweaver/orchestrator/workflows/aw-spec-analyze-slice-delta.orch.yaml +1 -1
- package/assets/.appweaver/orchestrator/workflows/aw-spec-analyze-slice.orch.yaml +159 -25
- package/assets/.appweaver/orchestrator/workflows/aw-spec-build.orch.yaml +20 -9
- package/assets/.appweaver/orchestrator/workflows/aw-spec-characterize.orch.yaml +1 -1
- package/assets/.appweaver/orchestrator/workflows/aw-spec-close-delta.orch.yaml +183 -40
- package/assets/.appweaver/orchestrator/workflows/aw-spec-deploy.orch.yaml +1 -1
- package/assets/.appweaver/orchestrator/workflows/aw-spec-finalize-delta.orch.yaml +311 -36
- package/assets/.appweaver/orchestrator/workflows/aw-spec-implement.orch.yaml +221 -40
- package/assets/.appweaver/orchestrator/workflows/aw-spec-inventory.orch.yaml +217 -174
- package/assets/.appweaver/orchestrator/workflows/aw-spec-onboard.orch.yaml +494 -109
- package/assets/.appweaver/orchestrator/workflows/aw-spec-parity.orch.yaml +1 -1
- package/assets/.appweaver/orchestrator/workflows/aw-spec-plan.orch.yaml +83 -18
- package/assets/.appweaver/orchestrator/workflows/aw-spec-recall-delta.orch.yaml +319 -0
- package/assets/.appweaver/orchestrator/workflows/aw-spec-run.orch.yaml +1 -1
- package/assets/.appweaver/orchestrator/workflows/aw-spec-select-feature.orch.yaml +29 -23
- package/assets/.appweaver/orchestrator/workflows/aw-spec-specify.orch.yaml +143 -34
- package/assets/.appweaver/scripts/bash/aw-inventory.sh +15 -0
- package/assets/.appweaver/scripts/bash/aw-spec-actions.sh +878 -51
- package/assets/.appweaver/scripts/bash/aw-xref.sh +3 -0
- package/assets/.appweaver/scripts/bash/common.sh +28 -1
- package/assets/.appweaver/scripts/powershell/aw-inventory.ps1 +15 -0
- package/assets/.appweaver/scripts/powershell/aw-spec-actions.ps1 +868 -51
- package/assets/.appweaver/scripts/powershell/aw-xref.ps1 +3 -0
- package/assets/.appweaver/scripts/python/aw-inventory.py +1832 -65
- package/assets/.appweaver/scripts/python/aw-xref.py +500 -81
- package/assets/.appweaver/templates/delta-design-template.md +1 -1
- package/assets/.appweaver/templates/delta-domain-model-template.md +1 -1
- package/assets/.appweaver/templates/delta-spec-template.md +4 -3
- package/assets/.appweaver/templates/design-template.md +56 -40
- package/assets/.appweaver/templates/okf-concept-template.md +11 -1
- package/assets/.appweaver/templates/proposed-inventory-template.md +127 -0
- package/assets/.appweaver/templates/source-map-template.md +5 -3
- package/assets/.appweaver/templates/spec-template.md +24 -21
- package/assets/.appweaver/templates/ui-delta-design-template.md +1 -1
- package/assets/.appweaver/templates/ui-design-template.md +11 -7
- package/assets/foundations/dotnet/ModularMonolith/ModularMonolith.pack.txt +4489 -361
- package/assets/foundations/dotnet/VerticalSlice/VerticalSlice.pack.txt +2274 -125
- 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,27 +2,40 @@
|
|
|
2
2
|
# aw-spec-onboard (orchestrator) — the entry step of the Brownfield DEVELOPMENT flow
|
|
3
3
|
#
|
|
4
4
|
# Onboard an EXISTING codebase into aw-spec so it can be DEVELOPED (evolved, not
|
|
5
|
-
# migrated) governed exactly like greenfield and as lightly as OpenSpec. Runs ONCE
|
|
6
|
-
#
|
|
7
|
-
#
|
|
5
|
+
# migrated) governed exactly like greenfield and as lightly as OpenSpec. Runs ONCE PER
|
|
6
|
+
# BOUNDED CONTEXT, against the boundaries /appweaver inventory proposed and the
|
|
7
|
+
# operator confirmed. No slice is adopted yet; each run does three things:
|
|
8
8
|
#
|
|
9
|
-
# 1. FEATURE MAP — a HIGH-LEVEL OKF discovery index of
|
|
10
|
-
#
|
|
11
|
-
#
|
|
12
|
-
#
|
|
13
|
-
#
|
|
9
|
+
# 1. FEATURE MAP — a HIGH-LEVEL OKF discovery index of THIS CONTEXT's aggregates —
|
|
10
|
+
# ONE concept per aggregate, listing the features that act on it — plus the tech
|
|
11
|
+
# stack, added beside whatever earlier contexts already wrote. The bundle is the
|
|
12
|
+
# PROJECT's knowledge: a concept is an aggregate, never a feature. It is a shallow map to pick from, NOT a deep reverse — the deep
|
|
13
|
+
# per-feature reverse (spec.md + the context's domain-model.md + the lane plans)
|
|
14
|
+
# is /appweaver adopt, done just-in-time when you are about to develop that
|
|
15
|
+
# feature.
|
|
14
16
|
#
|
|
15
|
-
# 2.
|
|
16
|
-
# the
|
|
17
|
-
#
|
|
18
|
-
#
|
|
19
|
-
#
|
|
20
|
-
#
|
|
21
|
-
# map are firm; principles/rules are marked provisional). adopt then RECONCILES
|
|
22
|
-
# each with the slice's own evidence (BR-/CN-/DC-/IC- ids) when that feature is
|
|
23
|
-
# developed — the "created here, updated when taking each slice" contract.
|
|
17
|
+
# 2. THE CONTEXT'S SPECS TREE — specs/<Context>/ with an EMPTY directory per feature,
|
|
18
|
+
# and the context made active in .appweaver/context.json. This is what makes the
|
|
19
|
+
# context real to the commands that read the tree rather than the bundle:
|
|
20
|
+
# select-bounded-context lists it, select-feature offers exactly its features, and
|
|
21
|
+
# adopt has somewhere to write. No spec.md and no domain-model.md — a placeholder
|
|
22
|
+
# for either reads as "the document exists" to every gate downstream.
|
|
24
23
|
#
|
|
25
|
-
#
|
|
24
|
+
# 3. GOVERNANCE SCAFFOLD — the PROJECT-level governing tier: the split constitution
|
|
25
|
+
# (technical + domain), the guardrails/projects/brf-<domain>/domain/ rule-file set
|
|
26
|
+
# (+ domain-rule-bindings), the domain charter that set is headed by, and the
|
|
27
|
+
# activated domain. AUTHORED BY THE FIRST CONTEXT TO ONBOARD AND BY NO OTHER —
|
|
28
|
+
# re-deriving project principles from one context's evidence is the aggregate-
|
|
29
|
+
# scoping bias this tier exists to avoid, so every later run skips the whole block
|
|
30
|
+
# and contributes its own concepts and specs tree instead. Because nothing is
|
|
31
|
+
# adopted yet, the tier is a PROVISIONAL scaffold evidenced by the SCAN (project
|
|
32
|
+
# identity + bounded-context map are firm; principles/rules are marked
|
|
33
|
+
# provisional); /appweaver constitution is what amends it.
|
|
34
|
+
#
|
|
35
|
+
# inventory → [edit specs/proposed-inventory.md] → inventory apply
|
|
36
|
+
# → ONBOARD <Context> (once per context) ← you are here
|
|
37
|
+
# → adopt <Feature> (JIT) → specify → plan → analyze-plan-delta → implement → build
|
|
38
|
+
# → analyze-slice-delta → finalize-delta → analyze-slice → close-delta
|
|
26
39
|
#
|
|
27
40
|
# Establishing the PROJECT-scoped constitution here (whole-repo vantage) — not from a
|
|
28
41
|
# single adopted slice — is deliberate: it keeps governance project-scoped from day
|
|
@@ -112,32 +125,32 @@
|
|
|
112
125
|
# pass was re-deriving an answer the run already had. `lane-declare` has one caller again
|
|
113
126
|
# — select-stack — and this workflow only reads.
|
|
114
127
|
#
|
|
115
|
-
# Never modifies source — every write lands in the OKF bundle, the specs
|
|
116
|
-
# guardrails/projects/ (domain/ + service/ + frontend/ rule sets + both
|
|
117
|
-
# .appweaver/templates/overrides/ design templates.
|
|
128
|
+
# Never modifies source — every write lands in the OKF bundle, the context's specs/
|
|
129
|
+
# directories, guardrails/projects/ (domain/ + service/ + frontend/ rule sets + both
|
|
130
|
+
# maps), or the .appweaver/templates/overrides/ design templates.
|
|
118
131
|
#
|
|
119
|
-
# Launch: /appweaver onboard [
|
|
120
|
-
# e.g. /appweaver onboard
|
|
121
|
-
# e.g. /appweaver onboard
|
|
132
|
+
# Launch: /appweaver onboard [<BoundedContext>] [; concerns: a, b, c]
|
|
133
|
+
# e.g. /appweaver onboard Clinical
|
|
134
|
+
# e.g. /appweaver onboard # the next context the map has open
|
|
135
|
+
# e.g. /appweaver onboard "Clinical; concerns: auditing, concurrency, authorization"
|
|
122
136
|
# =============================================================================
|
|
123
137
|
|
|
124
138
|
name: aw-spec-onboard
|
|
125
139
|
description: Onboard an existing codebase for brownfield DEVELOPMENT — a deterministic whole-repo scan produces a high-level OKF feature map (folders/concepts) PLUS the project-level governance scaffold (split constitution + guardrails/projects/brf-<domain>/ with its DOMAIN rule files at domain/ + domain-rule-bindings + code-derived TECHNICAL rule files at service/ + tech-rule-bindings + activated domain), all provisional-from-scan and refined per slice by adopt. Where the scan finds a frontend lane in the CODE, it also authors that lane's half — constitution.ui.md (UX-*) — and its code-derived rule files at brf-<domain>/frontend/, mapped under `## /aw-spec-ui-constitution`; a backend-only repo gets none of it. Every rule tier is reverse-engineered from the CODE alone (never a greenfield rule file), evidenced-only, and WIRED per-workflow so the whole forward pipeline AND adopt govern against THIS codebase — never a greenfield fallback. It also reverse-engineers the repo's own technical structure into a project-specific design + delta-design template pair, installed as the project template overrides, and — where the lane exists — the frontend lane's own pair from the UI source. Every authoring step is shaped by a NEUTRAL rev-templates skeleton; no greenfield constitution, rule file or document template is ever placed in context. Accepts an optional concerns list to look for (onboard decides which are actually present). Reads any declared lane, never writes one. No migration content; never modifies source.
|
|
126
|
-
version:
|
|
140
|
+
version: 2.0.0
|
|
127
141
|
agent_agnostic: true
|
|
128
142
|
dialect: aw-spec.orchestrator/v1
|
|
129
143
|
|
|
130
144
|
inputs:
|
|
131
145
|
user_input:
|
|
132
146
|
description: >-
|
|
133
|
-
|
|
134
|
-
(e.g.
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
concerns
|
|
147
|
+
The BOUNDED CONTEXT to onboard, as named in the feature map that
|
|
148
|
+
/appweaver inventory produced (e.g. Billing). Onboard runs once per context;
|
|
149
|
+
with no argument it takes the first context in the map that is not yet
|
|
150
|
+
onboarded. May also carry a CONCERNS LIST to look for, as a
|
|
151
|
+
"concerns: a, b, c" clause (e.g. "Billing; concerns: auditing, concurrency").
|
|
152
|
+
The concerns are a SEARCH HINT only — the rule-set authors still DECIDE which
|
|
138
153
|
concerns are actually present from the code, and are never limited to the list.
|
|
139
|
-
When omitted, the domain defaults to the PROJECT name from the OKF overview,
|
|
140
|
-
then the repo basename; concerns are auto-discovered from the code.
|
|
141
154
|
required: false
|
|
142
155
|
bind: USER_INPUT
|
|
143
156
|
|
|
@@ -164,6 +177,20 @@ vars:
|
|
|
164
177
|
bundle_present: "false" # inventory bundle_guard driver
|
|
165
178
|
conformant: "false" # OKF conformance-gate driver
|
|
166
179
|
pack_present: "false" # project anti-clobber driver
|
|
180
|
+
# The governance tier — constitution halves, rule packs, document templates —
|
|
181
|
+
# is PROJECT-scoped, authored by the first context to onboard and left alone by
|
|
182
|
+
# every context after it. Re-authoring project principles from one context's
|
|
183
|
+
# evidence is the scoping bias the rev-constitution work removed; this var is
|
|
184
|
+
# what keeps the second run from doing it.
|
|
185
|
+
repo_gov: "false" # true once the project governance exists
|
|
186
|
+
# The governance project is named from the PROJECT, never from the context.
|
|
187
|
+
# Passing the context name here would produce one rule pack per bounded
|
|
188
|
+
# context, which is the same bias by another route.
|
|
189
|
+
gov_name: ""
|
|
190
|
+
context_known: "false"
|
|
191
|
+
is_blocked: "false"
|
|
192
|
+
in_cycle: "false"
|
|
193
|
+
already_onboarded: "false"
|
|
167
194
|
technical_ok: "false" # technical-half lint guard
|
|
168
195
|
domain_ok: "false" # domain-half lint guard
|
|
169
196
|
ui_ok: "false" # UI-half lint guard
|
|
@@ -281,14 +308,106 @@ workflow:
|
|
|
281
308
|
on_false: stop
|
|
282
309
|
on_false_message: "Scan found no candidate features in {{root}} (file_count={{file_count}}). Point /appweaver onboard at a codebase with a recognizable domain/vertical-slice layout, or scan a subtree that contains one."
|
|
283
310
|
|
|
284
|
-
# 1c.
|
|
285
|
-
#
|
|
286
|
-
|
|
311
|
+
# 1c. WHICH BOUNDED CONTEXT, AND IS IT THIS ONE'S TURN. onboard runs once per
|
|
312
|
+
# context, so before anything is written it reads the map inventory
|
|
313
|
+
# produced and asks four questions: is this a context the map knows, what
|
|
314
|
+
# does it hold, has it already been onboarded, and is everything it depends
|
|
315
|
+
# on onboarded first.
|
|
316
|
+
#
|
|
317
|
+
# This replaces the bundle-wide curation guard. That guard stopped whenever
|
|
318
|
+
# the bundle held any concept at all, which is indistinguishable from
|
|
319
|
+
# "context 1 has been onboarded" — so it made onboarding a second context
|
|
320
|
+
# impossible. The curation it protects is still protected, per context:
|
|
321
|
+
# a context whose concepts already exist is not regenerated.
|
|
322
|
+
- id: context_state
|
|
323
|
+
action: execute_script
|
|
324
|
+
script: { ref: inventory }
|
|
325
|
+
subcommand: context-state
|
|
326
|
+
args: ["--context", "{{USER_INPUT}}", "--bundle", "{{bundle_dir}}"]
|
|
327
|
+
on_error: continue
|
|
328
|
+
outputs:
|
|
329
|
+
- { name: map_present, from: "$.map_present" }
|
|
330
|
+
- { name: context_known, from: "$.context_known" }
|
|
331
|
+
- { name: bc, from: "$.context" }
|
|
332
|
+
- { name: bc_slug, from: "$.context_slug" }
|
|
333
|
+
- { name: bc_features, from: "$.features" }
|
|
334
|
+
- { name: bc_feature_count, from: "$.feature_count" }
|
|
335
|
+
- { name: pending_features, from: "$.pending_features" }
|
|
336
|
+
- { name: pending_count, from: "$.pending_count" }
|
|
337
|
+
- { name: bc_aggregates, from: "$.aggregates" }
|
|
338
|
+
- { name: bc_feature_aggregates, from: "$.feature_aggregates" }
|
|
339
|
+
- { name: pending_aggregates, from: "$.pending_aggregates" }
|
|
340
|
+
- { name: already_onboarded, from: "$.already_onboarded" }
|
|
341
|
+
- { name: is_blocked, from: "$.is_blocked" }
|
|
342
|
+
- { name: blocked_by, from: "$.blocked_by" }
|
|
343
|
+
- { name: in_cycle, from: "$.in_cycle" }
|
|
344
|
+
- { name: cycle_with, from: "$.cycle_with" }
|
|
345
|
+
- { name: is_first, from: "$.is_first" }
|
|
346
|
+
- { name: onboarded_contexts, from: "$.onboarded_contexts" }
|
|
347
|
+
- { name: remaining_contexts, from: "$.remaining_contexts" }
|
|
348
|
+
- { name: contexts_ordered, from: "$.contexts_ordered" }
|
|
349
|
+
- { name: feature_map, from: "$.feature_map" }
|
|
350
|
+
- { name: map_error, from: "$.error" }
|
|
351
|
+
|
|
352
|
+
# 1d. No map means the boundaries were never decided. Onboarding without them
|
|
353
|
+
# is what produced a flat aggregate list with no context level at all.
|
|
354
|
+
- id: require_map
|
|
355
|
+
action: verify_context
|
|
356
|
+
require_value: map_present
|
|
357
|
+
equals: "true"
|
|
358
|
+
on_mismatch: stop
|
|
359
|
+
on_mismatch_message: >
|
|
360
|
+
No feature map was found. Onboard works one BOUNDED CONTEXT at a time and
|
|
361
|
+
reads the map /appweaver inventory produces. Run `/appweaver inventory`,
|
|
362
|
+
review and edit `specs/proposed-inventory.md` — it is the boundary map and
|
|
363
|
+
it is yours to change — then run `/appweaver inventory apply`.
|
|
364
|
+
|
|
365
|
+
- id: require_context
|
|
287
366
|
action: verify_context
|
|
288
|
-
require_value:
|
|
367
|
+
require_value: context_known
|
|
368
|
+
equals: "true"
|
|
369
|
+
on_mismatch: stop
|
|
370
|
+
on_mismatch_message: "{{map_error}}"
|
|
371
|
+
|
|
372
|
+
# 1e. Per-context curation guard — the narrow form of the old bundle guard.
|
|
373
|
+
- id: context_done_guard
|
|
374
|
+
action: verify_context
|
|
375
|
+
require_value: already_onboarded
|
|
289
376
|
equals: "false"
|
|
290
377
|
on_mismatch: stop
|
|
291
|
-
on_mismatch_message:
|
|
378
|
+
on_mismatch_message: >
|
|
379
|
+
Bounded context {{bc}} is already onboarded — every aggregate its
|
|
380
|
+
{{bc_feature_count}} feature(s) act on ({{bc_aggregates}}) already has a concept in
|
|
381
|
+
{{bundle_dir}}, and re-running would overwrite that curation. Contexts still open: {{remaining_contexts}}
|
|
382
|
+
|
|
383
|
+
# 1f. Dependency order. A context whose dependencies are still open would be
|
|
384
|
+
# modelled against aggregates that do not exist yet. A context inside a
|
|
385
|
+
# CYCLE is released rather than blocked — each member is waiting on the
|
|
386
|
+
# other, so blocking both deadlocks the sequence.
|
|
387
|
+
- id: context_order_gate
|
|
388
|
+
action: verify_context
|
|
389
|
+
require_value: is_blocked
|
|
390
|
+
equals: "false"
|
|
391
|
+
on_mismatch: stop
|
|
392
|
+
on_mismatch_message: >
|
|
393
|
+
Bounded context {{bc}} depends on a context that has not been onboarded yet:
|
|
394
|
+
{{blocked_by}}. Its features cite aggregates that will not exist until then, so
|
|
395
|
+
onboard in the order the map gives — {{contexts_ordered}} — or run
|
|
396
|
+
/appweaver onboard with no argument to take the next one automatically.
|
|
397
|
+
To change that order, edit the Depends On column in specs/proposed-inventory.md
|
|
398
|
+
and re-run /appweaver inventory apply.
|
|
399
|
+
|
|
400
|
+
- id: cycle_warning
|
|
401
|
+
action: verify_context
|
|
402
|
+
condition: "{{in_cycle}} == true"
|
|
403
|
+
require_value: in_cycle
|
|
404
|
+
equals: "never"
|
|
405
|
+
on_mismatch: continue
|
|
406
|
+
on_mismatch_message: >
|
|
407
|
+
NOTE: {{bc}} and {{cycle_with}} depend on each other. They cannot be ordered,
|
|
408
|
+
so {{bc}} is released rather than blocked — but the two share a seam, and the
|
|
409
|
+
aggregates each cites from the other will be incomplete until both are
|
|
410
|
+
onboarded. Break the cycle with a seam, or onboard the ring back to back.
|
|
292
411
|
|
|
293
412
|
# 1d. FRONTEND LANE — the DECLARATION decides that it exists, and the CODE decides
|
|
294
413
|
# what its governance says. Those are two different questions and they used to be
|
|
@@ -389,6 +508,7 @@ workflow:
|
|
|
389
508
|
action: build_context
|
|
390
509
|
context:
|
|
391
510
|
- { path: "{{inventory_json}}" } # the deterministic substrate (aggregate_signals etc.)
|
|
511
|
+
- { path: "{{feature_map}}" } # the CONFIRMED boundaries: which features belong to which bounded context, and in what order
|
|
392
512
|
- { path: .appweaver/templates/okf-concept-template.md } # OKF v0.1 format authority (frontmatter, index, log, rules) — format only, zero project content
|
|
393
513
|
- id: author_bundle
|
|
394
514
|
action: agent_generate
|
|
@@ -396,31 +516,55 @@ workflow:
|
|
|
396
516
|
permission_mode: acceptEdits
|
|
397
517
|
task: |
|
|
398
518
|
Act as the OKF enrichment agent for the Brownfield DEVELOPMENT onboard step.
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
519
|
+
Extend the OKF v0.1 knowledge bundle at {{bundle_dir}} with the features of ONE
|
|
520
|
+
BOUNDED CONTEXT — a discovery index of what that context contains — from the
|
|
521
|
+
deterministic substrate {{inventory_json}} and the confirmed boundary map
|
|
522
|
+
{{feature_map}} (both in context). Follow the OKF concept template in context for
|
|
523
|
+
format (frontmatter, index.md/log.md rules, cross-linking, hard rules).
|
|
524
|
+
|
|
525
|
+
THE CONTEXT YOU ARE ONBOARDING IS `{{bc}}`.
|
|
526
|
+
Its features, already confirmed by the operator: {{bc_features}}
|
|
527
|
+
The aggregates those features act on: {{bc_aggregates}}
|
|
528
|
+
Which feature acts on which: {{bc_feature_aggregates}}
|
|
529
|
+
Aggregates still without a concept, to be written this run: {{pending_aggregates}}
|
|
530
|
+
|
|
531
|
+
THE BUNDLE IS THE PROJECT'S KNOWLEDGE, AND A CONCEPT IS AN AGGREGATE — NEVER A
|
|
532
|
+
FEATURE. Features are the specs tree's unit (this run creates their directories);
|
|
533
|
+
they are LISTED on their aggregate's concept and never given concepts of their own.
|
|
534
|
+
Several features can act on one aggregate — the map split it into capabilities —
|
|
535
|
+
and that aggregate still gets exactly one concept.
|
|
536
|
+
|
|
537
|
+
THE BOUNDARIES ARE DECIDED — DO NOT REDRAW THEM. The feature map is the output of
|
|
538
|
+
a scan the operator has already reviewed and edited by hand. Write one concept per
|
|
539
|
+
AGGREGATE the map names for this context, and no others. Do not merge two
|
|
540
|
+
aggregates, do not split one, do not invent an aggregate or a feature the map does
|
|
541
|
+
not list, and do not write a concept for an aggregate belonging to another bounded
|
|
542
|
+
context — those are onboarded by their own runs. Where the substrate's `aggregate_signals` disagree with the map,
|
|
543
|
+
THE MAP WINS; note the disagreement in `open_questions` on the concept.
|
|
544
|
+
|
|
545
|
+
THIS IS ADDITIVE. Other bounded contexts may already have concepts in this bundle.
|
|
546
|
+
Read the bundle before writing. Create the files this context needs, UPDATE the
|
|
547
|
+
shared index/log files in place, and NEVER delete, rewrite or re-scope a concept
|
|
548
|
+
belonging to another context. If a file you would create already exists, it belongs
|
|
549
|
+
to an earlier run — leave it alone.
|
|
550
|
+
|
|
551
|
+
THIS IS A MAP, NOT A DEEP REVERSE. Keep every concept SHALLOW — enough to
|
|
552
|
+
recognize the aggregate and pick a feature over it to develop next. Do NOT deep-model
|
|
553
|
+
invariants/behaviour here.
|
|
554
|
+
|
|
555
|
+
Read the substrate for EVIDENCE about the map's aggregates. Its `aggregate_signals`
|
|
556
|
+
carry each root's files grouped by layer plus detected entities; `ui_attribution`
|
|
557
|
+
says which FRONTEND files serve which root (and which serve none);
|
|
414
558
|
`git.history.churn` ranks significance; the category lists and `top_level_dirs`
|
|
415
|
-
fill in the rest.
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
559
|
+
fill in the rest. Where several features act on one aggregate (two seams on one
|
|
560
|
+
root), its ONE concept carries the whole module — domain and behaviour files alike
|
|
561
|
+
— and names each feature with the capability it covers. Which files serve which
|
|
562
|
+
capability is recorded per feature later, in the source-map adopt writes.
|
|
419
563
|
- Treat service-level / shared infrastructure (a shared persistence context,
|
|
420
564
|
cross-cutting adapters, host / service-defaults projects) as a Platform/Shared
|
|
421
565
|
concept, NOT a feature.
|
|
422
566
|
- Fold value objects, entities, domain events, commands and endpoints into the
|
|
423
|
-
|
|
567
|
+
aggregate that OWNS them — one aggregate concept, not one per type.
|
|
424
568
|
NAME EVERY CONCEPT IN THE CODE'S OWN VOCABULARY — read the identifiers the source
|
|
425
569
|
actually uses. "Aggregate", "entity" and "value object" are how aw-spec ORGANIZES a
|
|
426
570
|
feature map; they are not a claim that this codebase is modelled that way. Where the
|
|
@@ -428,9 +572,19 @@ workflow:
|
|
|
428
572
|
grouping around it.
|
|
429
573
|
|
|
430
574
|
Write the bundle (all paths under {{bundle_dir}}; bundle-relative links begin
|
|
431
|
-
with "/", per OKF §5.1)
|
|
575
|
+
with "/", per OKF §5.1).
|
|
576
|
+
|
|
577
|
+
IS THIS THE FIRST CONTEXT IN THIS BUNDLE? `{{is_first}}`
|
|
578
|
+
The three `architecture/` notes below describe the WHOLE repository, not one
|
|
579
|
+
context, so they are written ONCE — by the first context to onboard. When
|
|
580
|
+
`{{is_first}}` is false they already exist: do not rewrite them, and add to them
|
|
581
|
+
only where this context introduces a technology or integration point the note
|
|
582
|
+
genuinely lacks. Everything else below is written on every run, for this
|
|
583
|
+
context's features only.
|
|
584
|
+
|
|
432
585
|
- `index.md` (bundle root) — frontmatter EXACTLY `okf_version: "0.1"` and nothing
|
|
433
586
|
else; body = sections of bulleted links reusing each concept's `description`.
|
|
587
|
+
On a later context, ADD this context's entries and leave the rest in place.
|
|
434
588
|
- `architecture/overview.md` (type: Reference) — the system at a glance. Its
|
|
435
589
|
`## Purpose` section MUST open with the whole solution/product name in bold
|
|
436
590
|
followed by "is a …" (e.g. "**Medicinal.Healthcare** is a …") — this bold token
|
|
@@ -463,11 +617,14 @@ workflow:
|
|
|
463
617
|
unattributed` lists the files serving no single aggregate (app shell, layout,
|
|
464
618
|
design system, global styles). Describe what they provide; they belong here
|
|
465
619
|
precisely because no slice owns them.
|
|
466
|
-
- `aggregates/<
|
|
620
|
+
- `aggregates/<aggregate>.md` (type: Aggregate) — ONE per aggregate, SHALLOW, its
|
|
621
|
+
`title:` EXACTLY the aggregate's name as the map spells it (`MedicinalProduct`,
|
|
622
|
+
never `Medicinal Product` — later commands find the concept by that name):
|
|
467
623
|
Responsibilities; the entities / value objects / domain events / commands / API
|
|
468
624
|
endpoints / persistence it OWNS (named at a glance from the signal's layer
|
|
469
|
-
files — a list, not a deep model); and
|
|
470
|
-
|
|
625
|
+
files — a list, not a deep model); and `features:` in frontmatter — the map's
|
|
626
|
+
features that act on it, each of which is a `specs/{{bc}}/<Feature>/` directory
|
|
627
|
+
this run creates. Set `source_files` to the module's files, grouped
|
|
471
628
|
with YAML comment headers by each file's OWN folder — the path segment that
|
|
472
629
|
VARIES across the files after their shared parent (the layer folder in a
|
|
473
630
|
vertical slice; the tier project in an n-tier app; tests → a single `tests`
|
|
@@ -479,18 +636,25 @@ workflow:
|
|
|
479
636
|
is and move or drop one it got wrong. Keep the key and leave it EMPTY where the
|
|
480
637
|
aggregate has no UI (and on a backend-only repo, where every concept has none);
|
|
481
638
|
never fold these paths into `source_files`, which stays the service surface.
|
|
482
|
-
- `aggregates/index.md` — the
|
|
483
|
-
OKF index rules)
|
|
639
|
+
- `aggregates/index.md` — the BOUNDED-CONTEXT / feature map (no frontmatter beyond
|
|
640
|
+
OKF index rules). Group the links under a `## <BoundedContext>` heading per
|
|
641
|
+
context, so the file shows which aggregates belong to which context rather than one
|
|
642
|
+
flat list, each link followed by the features that act on that aggregate. Add a
|
|
643
|
+
`## {{bc}}` section with this context's aggregates; leave every
|
|
644
|
+
other section exactly as it is.
|
|
484
645
|
- An `index.md` in EVERY subdirectory (no frontmatter).
|
|
485
|
-
- `log.md` (bundle root) —
|
|
486
|
-
`Commit: ` + backtick + `{{head}}` + backtick (validator rule E4), then a
|
|
487
|
-
one-line
|
|
646
|
+
- `log.md` (bundle root) — APPEND under a `## <today's date>` heading whose first
|
|
647
|
+
line is `Commit: ` + backtick + `{{head}}` + backtick (validator rule E4), then a
|
|
648
|
+
one-line entry naming the bounded context onboarded and its concept count. Keep
|
|
649
|
+
every earlier dated entry.
|
|
488
650
|
Do NOT write a migration-backlog, a seam/clean-torn analysis, or an adopt-order —
|
|
489
651
|
those are migration artifacts and are out of scope for the development flow.
|
|
490
652
|
|
|
491
653
|
Provenance + safety (OKF hard rules):
|
|
492
|
-
- Stamp every concept `origin: reverse-engineered
|
|
493
|
-
aw-spec-onboard/
|
|
654
|
+
- Stamp every concept `origin: reverse-engineered`, `generated_by:
|
|
655
|
+
aw-spec-onboard/2.0.0` and `bounded_context: {{bc}}` in frontmatter. The
|
|
656
|
+
context key is what lets later commands filter features by the context they
|
|
657
|
+
belong to instead of listing every aggregate under every one.
|
|
494
658
|
- The CODE is the source of truth; capture what IS (quirks included), not what
|
|
495
659
|
SHOULD be. Where intent is unclear from code + git history, add a concrete
|
|
496
660
|
`open_questions` entry rather than inventing one.
|
|
@@ -525,6 +689,76 @@ workflow:
|
|
|
525
689
|
on_false: stop
|
|
526
690
|
on_false_message: "The OKF feature map at {{bundle_dir}} is NON-CONFORMANT (errors: {{okf_errors}}). Fix the reported ERRORs (unparseable frontmatter, missing `type`, malformed index.md/log.md) and re-run."
|
|
527
691
|
|
|
692
|
+
# ═══════════ THE CONTEXT'S SPECS TREE — specs/<Context>/<Feature>/ ═══════════
|
|
693
|
+
# The concepts above say what this context CONTAINS; these two steps make that
|
|
694
|
+
# shape exist where every later command looks for it. Until now a context left
|
|
695
|
+
# no trace under specs/ at all: `list-contexts` reads the tree rather than the
|
|
696
|
+
# bundle, so the context it had just onboarded reported as absent, and
|
|
697
|
+
# select-feature's refusal-to-guess gate — contexts exist, none is active —
|
|
698
|
+
# could not even be reached. select-feature merges the bundle's aggregates into
|
|
699
|
+
# its list to cover the gap, but a feature that exists only as a concept has
|
|
700
|
+
# nowhere for adopt to write, and picking one would create its directory at
|
|
701
|
+
# whatever base happened to be active.
|
|
702
|
+
#
|
|
703
|
+
# DIRECTORIES ONLY. No spec.md, no domain-model.md, no plan: adopt reverse-
|
|
704
|
+
# engineers the first per feature and specify authors the second per context,
|
|
705
|
+
# and a placeholder for either reads as "the document exists" to every gate
|
|
706
|
+
# downstream. The directory says the feature is KNOWN; the documents say it is
|
|
707
|
+
# described.
|
|
708
|
+
- id: activate_context
|
|
709
|
+
action: execute_script
|
|
710
|
+
script: { ref: actions }
|
|
711
|
+
subcommand: set-context
|
|
712
|
+
args: ["--context", "{{bc}}"]
|
|
713
|
+
outputs:
|
|
714
|
+
- { name: bc_dir, from: "$.context_dir" }
|
|
715
|
+
- { name: bc_domain_model, from: "$.domain_model" }
|
|
716
|
+
- { name: bc_dir_created, from: "$.created" }
|
|
717
|
+
|
|
718
|
+
- id: scaffold_features
|
|
719
|
+
action: execute_script
|
|
720
|
+
script: { ref: inventory }
|
|
721
|
+
subcommand: scaffold-context
|
|
722
|
+
args: ["--context", "{{bc}}", "--map", "{{feature_map}}"]
|
|
723
|
+
on_error: continue
|
|
724
|
+
outputs:
|
|
725
|
+
- { name: scaffold_ok, from: "$.ok" }
|
|
726
|
+
- { name: feature_dirs, from: "$.feature_dirs" }
|
|
727
|
+
- { name: dirs_created, from: "$.created" }
|
|
728
|
+
- { name: dirs_created_num, from: "$.created_count" }
|
|
729
|
+
- { name: dirs_rejected, from: "$.rejected" }
|
|
730
|
+
- { name: dirs_rejected_any, from: "$.rejected_present" }
|
|
731
|
+
- { name: scaffold_error, from: "$.error" }
|
|
732
|
+
|
|
733
|
+
- id: scaffold_gate
|
|
734
|
+
action: verify_context
|
|
735
|
+
require_value: scaffold_ok
|
|
736
|
+
equals: "true"
|
|
737
|
+
on_mismatch: stop
|
|
738
|
+
on_mismatch_message: >
|
|
739
|
+
The feature directories for {{bc}} could not be created: {{scaffold_error}}
|
|
740
|
+
The OKF concepts for this context ARE written — only the specs/ tree is
|
|
741
|
+
missing, so fix the name the message reports in specs/proposed-inventory.md,
|
|
742
|
+
run /appweaver inventory apply, and re-run onboard for this context.
|
|
743
|
+
|
|
744
|
+
# A feature name the map carries that is not a usable directory identifier. Named
|
|
745
|
+
# rather than dropped silently: the concept exists, so the feature is pickable from
|
|
746
|
+
# the bundle and would land in a directory nobody chose.
|
|
747
|
+
# The never-satisfiable `equals` is the engine's announce-only idiom: the step is
|
|
748
|
+
# entered only when there IS something to report, and the comparison is written so
|
|
749
|
+
# it always misses, so the message is emitted and the run continues.
|
|
750
|
+
- id: scaffold_name_warning
|
|
751
|
+
action: verify_context
|
|
752
|
+
condition: "{{dirs_rejected_any}} == true"
|
|
753
|
+
require_value: dirs_rejected_any
|
|
754
|
+
equals: "never"
|
|
755
|
+
on_mismatch: continue
|
|
756
|
+
on_mismatch_message: >
|
|
757
|
+
These feature names are not valid directory identifiers and got no directory:
|
|
758
|
+
{{dirs_rejected}}. A feature name has to be a letter-led alphanumeric aggregate
|
|
759
|
+
(Order, MedicinalProduct). Rename them in specs/proposed-inventory.md, re-run
|
|
760
|
+
/appweaver inventory apply, then /appweaver select-feature will offer them.
|
|
761
|
+
|
|
528
762
|
# ═══════════════ PART 2 — GOVERNANCE SCAFFOLD (project-level) ════════════════
|
|
529
763
|
# Establish the governing tier ONCE, from the feature map just written (the whole-
|
|
530
764
|
# repo vantage). No slice is adopted, so list-adopted returns slice_count=0 but STILL
|
|
@@ -547,11 +781,16 @@ workflow:
|
|
|
547
781
|
# Slugify + `brf-` prefix the domain name and create guardrails/projects/brf-<domain>/.
|
|
548
782
|
# Name: explicit arg → PROJECT name from the OKF overview → repo basename. Guarded
|
|
549
783
|
# against clobbering a project that already holds .md files.
|
|
784
|
+
# The governance project is named from the PROJECT — `gov_name` is empty, so
|
|
785
|
+
# project-setup falls back to the project name from the OKF overview and then
|
|
786
|
+
# to the repo basename. Passing the bounded context here would create one rule
|
|
787
|
+
# pack per context and split the project's constitution along context lines,
|
|
788
|
+
# which is the aggregate-scoping bias in a new place.
|
|
550
789
|
- id: pack_setup
|
|
551
790
|
action: execute_script
|
|
552
791
|
script: { ref: revcon }
|
|
553
792
|
subcommand: project-setup
|
|
554
|
-
args: ["--name", "{{
|
|
793
|
+
args: ["--name", "{{gov_name}}", "--fallback", "{{project_name}}"]
|
|
555
794
|
outputs:
|
|
556
795
|
- { name: domain_slug, from: "$.domain_slug" }
|
|
557
796
|
- { name: pack_dir, from: "$.pack_dir" }
|
|
@@ -559,18 +798,54 @@ workflow:
|
|
|
559
798
|
- { name: domain_constitution_source, from: "$.domain_constitution_source" }
|
|
560
799
|
- { name: pack_present, from: "$.pack_present" }
|
|
561
800
|
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
801
|
+
# An existing pack is no longer a reason to stop — it is the signal that the
|
|
802
|
+
# project tier has already been authored and this run is onboarding a LATER
|
|
803
|
+
# bounded context. The tier is written once and amended by /appweaver
|
|
804
|
+
# constitution; what each later context still contributes is its own OKF
|
|
805
|
+
# concepts and its own domain model.
|
|
806
|
+
- id: repo_gov_present
|
|
807
|
+
action: set
|
|
808
|
+
condition: "{{pack_present}} == true"
|
|
809
|
+
vars: { repo_gov: "true" }
|
|
810
|
+
|
|
811
|
+
# WHAT THIS RUN AUTHORS. The engine compares one variable against one value and
|
|
812
|
+
# has no compound conditions, so "this lane exists AND the project tier has not
|
|
813
|
+
# been written yet" is computed here as an ordered pair of sets rather than
|
|
814
|
+
# asked at each step: default to the lane declaration, then clear everything
|
|
815
|
+
# once the project tier is present.
|
|
816
|
+
#
|
|
817
|
+
# The second set also SATISFIES the lint guards the skipped block would
|
|
818
|
+
# otherwise leave at their "not yet verified" default — the same move
|
|
819
|
+
# svc_lane_absent makes for a repo with no service lane. Without it a later
|
|
820
|
+
# context would stop at a gate checking work this run correctly did not do.
|
|
821
|
+
#
|
|
822
|
+
# ⌛ OPEN: should a LATER context amend the rule sets? Skipping the whole tier
|
|
823
|
+
# also skips the code-derived rule files, and a second context can evidence a
|
|
824
|
+
# domain or technical concern the first one's source never showed — that
|
|
825
|
+
# evidence reaches nothing today. The two halves of the tier differ here. The
|
|
826
|
+
# constitution halves, principle numbering, domain activation and the document
|
|
827
|
+
# templates are project-scoped, and re-deriving them per context IS the
|
|
828
|
+
# aggregate-scoping bias rev-constitution v1.1.0 removed; /appweaver
|
|
829
|
+
# constitution is their amendment path. The rule SETS
|
|
830
|
+
# (guardrails/projects/<p>/{domain,service,frontend}/) are evidenced-only, so
|
|
831
|
+
# amending them ADDITIVELY from a later context — add a rule for a concern this
|
|
832
|
+
# context exhibits, never rewrite or renumber an existing one — would be more
|
|
833
|
+
# evidence at the same project scope rather than one context's bias. That
|
|
834
|
+
# additive pass is not built; author-once is what runs.
|
|
835
|
+
- id: author_flags_default
|
|
836
|
+
action: set
|
|
837
|
+
vars: { author_repo: "true", author_svc: "{{svc_lane}}", author_ui_flag: "{{ui_lane}}" }
|
|
838
|
+
- id: author_flags_skip
|
|
839
|
+
action: set
|
|
840
|
+
condition: "{{repo_gov}} == true"
|
|
841
|
+
vars: { author_repo: "false", author_svc: "false", author_ui_flag: "false", technical_ok: "true", domain_ok: "true", ui_ok: "true", numbering_ok: "true" }
|
|
568
842
|
|
|
569
843
|
# ── DOMAIN RULE SET (provisional, evidenced by the SCAN) ────────────────────
|
|
570
844
|
# Feed NEUTRAL shape skeletons (rev-templates/, zero content to leak) + the rule-
|
|
571
845
|
# partition authority + the project context (the feature map). NO adopted specs
|
|
572
846
|
# exist — the evidence is the OKF overview + aggregates/index + platform.
|
|
573
847
|
- id: ctx_pack
|
|
848
|
+
condition: "{{author_repo}} == true"
|
|
574
849
|
action: build_context
|
|
575
850
|
context:
|
|
576
851
|
- { path: "{{inventory_json}}" } # the COMPLETE deterministic scan substrate — read representative SOURCE from its file lists (the OKF map only SUMMARISES this)
|
|
@@ -580,6 +855,7 @@ workflow:
|
|
|
580
855
|
- { path: .appweaver/RULE-PARTITION.md } # the rule-partition authority (which command reads what)
|
|
581
856
|
context_from: project_context
|
|
582
857
|
- id: author_pack
|
|
858
|
+
condition: "{{author_repo}} == true"
|
|
583
859
|
action: agent_generate
|
|
584
860
|
tools: "Read,Write,Edit"
|
|
585
861
|
permission_mode: acceptEdits
|
|
@@ -648,8 +924,8 @@ workflow:
|
|
|
648
924
|
charter; a later step in this same run authors it, so wire the bullet now), then the
|
|
649
925
|
domain identity/regulatory/interop files → domain principles.
|
|
650
926
|
- `## /aw-spec-specify` — the FULL domain set (specify models the domain, lifts CN-/DC-/IC-).
|
|
651
|
-
- `## /aw-spec-plan` — `_None —
|
|
652
|
-
- `## /aw-spec-implement` — `_None — implement loads no domain file. Domain reaches implement
|
|
927
|
+
- `## /aw-spec-plan` — `_None — plan loads no domain file. Domain reaches plan through the spec and the context's domain-model.md._`
|
|
928
|
+
- `## /aw-spec-implement` — `_None — implement loads no domain file. Domain reaches implement through the lane plans and the context's domain-model.md._`
|
|
653
929
|
- `## /aw-spec-gate` — the conformance-checklist set (the *.domain.md files).
|
|
654
930
|
Each bullet is a workspace-relative path `- guardrails/projects/{{domain_slug}}/domain/<file>`.
|
|
655
931
|
Write ONLY inside guardrails/projects/{{domain_slug}}/ (domain/ + the map). Report the
|
|
@@ -658,11 +934,13 @@ workflow:
|
|
|
658
934
|
- { name: pack_files, from: "$.files" }
|
|
659
935
|
|
|
660
936
|
- id: verify_pack
|
|
937
|
+
condition: "{{author_repo}} == true"
|
|
661
938
|
action: verify_context
|
|
662
939
|
require_non_empty: pack_files
|
|
663
940
|
on_empty: stop
|
|
664
941
|
on_empty_message: "No domain rule files were written to guardrails/projects/{{domain_slug}}/domain/. Ensure the feature map carries a modellable domain (a feature map + ubiquitous language) and re-run."
|
|
665
942
|
- id: require_domain_rule_bindings
|
|
943
|
+
condition: "{{author_repo}} == true"
|
|
666
944
|
action: verify_context
|
|
667
945
|
required_files: ["{{domain_rule_bindings}}"]
|
|
668
946
|
|
|
@@ -670,12 +948,14 @@ workflow:
|
|
|
670
948
|
# Named and placed exactly as a greenfield industry corpus names and places its charter,
|
|
671
949
|
# and already wired as the first `## /aw-spec-constitution` bullet by the step above.
|
|
672
950
|
- id: ctx_domain_source
|
|
951
|
+
condition: "{{author_repo}} == true"
|
|
673
952
|
action: build_context
|
|
674
953
|
context:
|
|
675
954
|
- { path: "{{domain_rule_bindings}}" }
|
|
676
955
|
- { path: .appweaver/orchestrator/rev-templates/domain-constitution.skeleton.md, optional: true }
|
|
677
956
|
context_from: project_context
|
|
678
957
|
- id: author_domain_source
|
|
958
|
+
condition: "{{author_repo}} == true"
|
|
679
959
|
action: agent_author
|
|
680
960
|
include_standards: false
|
|
681
961
|
output_target: { type: file, path: "{{domain_constitution_source}}" }
|
|
@@ -718,6 +998,7 @@ workflow:
|
|
|
718
998
|
# do, so a later call without the flag silently recreates the half an earlier call
|
|
719
999
|
# was told to skip.
|
|
720
1000
|
- id: setup_constitution
|
|
1001
|
+
condition: "{{author_repo}} == true"
|
|
721
1002
|
action: execute_script
|
|
722
1003
|
script: { ref: actions }
|
|
723
1004
|
subcommand: setup-constitution
|
|
@@ -731,7 +1012,7 @@ workflow:
|
|
|
731
1012
|
# set, which is empty), so nothing leaks into the Part-1 feature-map agent.
|
|
732
1013
|
- id: ctx_technical
|
|
733
1014
|
action: build_context
|
|
734
|
-
condition: "{{
|
|
1015
|
+
condition: "{{author_svc}} == true"
|
|
735
1016
|
context:
|
|
736
1017
|
- { path: "{{constitution_technical_file}}" }
|
|
737
1018
|
- { path: .appweaver/orchestrator/rev-templates/technical-constitution.skeleton.md, optional: true }
|
|
@@ -739,7 +1020,7 @@ workflow:
|
|
|
739
1020
|
context_from: design_context
|
|
740
1021
|
- id: author_technical
|
|
741
1022
|
action: agent_author
|
|
742
|
-
condition: "{{
|
|
1023
|
+
condition: "{{author_svc}} == true"
|
|
743
1024
|
include_standards: false
|
|
744
1025
|
output_target: { type: file, path: "{{constitution_technical_file}}" }
|
|
745
1026
|
task: |
|
|
@@ -782,7 +1063,7 @@ workflow:
|
|
|
782
1063
|
|
|
783
1064
|
- id: technical_validation_loop
|
|
784
1065
|
action: loop
|
|
785
|
-
condition: "{{
|
|
1066
|
+
condition: "{{author_svc}} == true"
|
|
786
1067
|
while: "{{technical_ok}} != true"
|
|
787
1068
|
max_iterations: 3
|
|
788
1069
|
steps:
|
|
@@ -827,7 +1108,7 @@ workflow:
|
|
|
827
1108
|
# ABSENCE is meaningful: a repo with no UI never gets the file at all.
|
|
828
1109
|
- id: setup_ui_constitution
|
|
829
1110
|
action: execute_script
|
|
830
|
-
condition: "{{
|
|
1111
|
+
condition: "{{author_ui_flag}} == true"
|
|
831
1112
|
script: { ref: actions }
|
|
832
1113
|
subcommand: setup-constitution
|
|
833
1114
|
args: ["--ui", "{{setup_tech_flag}}"]
|
|
@@ -837,7 +1118,7 @@ workflow:
|
|
|
837
1118
|
|
|
838
1119
|
- id: ctx_ui
|
|
839
1120
|
action: build_context
|
|
840
|
-
condition: "{{
|
|
1121
|
+
condition: "{{author_ui_flag}} == true"
|
|
841
1122
|
context:
|
|
842
1123
|
- { path: "{{constitution_ui_file}}" } # the target half being filled
|
|
843
1124
|
- { path: "{{inventory_json}}" } # PRIMARY: the COMPLETE deterministic substrate — frontend_signals + the UI file lists to read source from
|
|
@@ -845,7 +1126,7 @@ workflow:
|
|
|
845
1126
|
- { path: "{{bundle_dir}}/architecture/frontend.md", optional: true } # SECONDARY (shallow): the OKF as-built frontend note — corroborate, don't rely on alone
|
|
846
1127
|
- id: author_ui
|
|
847
1128
|
action: agent_author
|
|
848
|
-
condition: "{{
|
|
1129
|
+
condition: "{{author_ui_flag}} == true"
|
|
849
1130
|
include_standards: false
|
|
850
1131
|
tools: Read # EVIDENCE = THE UI CODE ITSELF; the inventory inlines the file LISTS, not the files
|
|
851
1132
|
output_target: { type: file, path: "{{constitution_ui_file}}" }
|
|
@@ -914,7 +1195,7 @@ workflow:
|
|
|
914
1195
|
|
|
915
1196
|
- id: ui_validation_loop
|
|
916
1197
|
action: loop
|
|
917
|
-
condition: "{{
|
|
1198
|
+
condition: "{{author_ui_flag}} == true"
|
|
918
1199
|
while: "{{ui_ok}} != true"
|
|
919
1200
|
max_iterations: 3
|
|
920
1201
|
steps:
|
|
@@ -947,15 +1228,17 @@ workflow:
|
|
|
947
1228
|
# repo no half was created, so the run reports that rather than a bare false a reader
|
|
948
1229
|
# would take for a half that needs a manual touch.
|
|
949
1230
|
- id: ui_validation_state_absent
|
|
1231
|
+
condition: "{{author_repo}} == true"
|
|
950
1232
|
action: set
|
|
951
1233
|
vars: { ui_validation_state: "n/a — no frontend lane, no UI half authored" }
|
|
952
1234
|
- id: ui_validation_state_present
|
|
953
1235
|
action: set
|
|
954
|
-
condition: "{{
|
|
1236
|
+
condition: "{{author_ui_flag}} == true"
|
|
955
1237
|
vars: { ui_validation_state: "{{ui_ok}}" }
|
|
956
1238
|
|
|
957
1239
|
# DOMAIN HALF — from the project + charter, principles continue the technical numbering.
|
|
958
1240
|
- id: ctx_domain
|
|
1241
|
+
condition: "{{author_repo}} == true"
|
|
959
1242
|
action: build_context
|
|
960
1243
|
context:
|
|
961
1244
|
- { path: "{{constitution_domain_file}}" }
|
|
@@ -964,6 +1247,7 @@ workflow:
|
|
|
964
1247
|
- { path: "{{domain_rule_bindings}}" }
|
|
965
1248
|
context_from: project_context
|
|
966
1249
|
- id: author_domain
|
|
1250
|
+
condition: "{{author_repo}} == true"
|
|
967
1251
|
action: agent_author
|
|
968
1252
|
include_standards: false
|
|
969
1253
|
output_target: { type: file, path: "{{constitution_domain_file}}" }
|
|
@@ -1004,6 +1288,7 @@ workflow:
|
|
|
1004
1288
|
Return the complete updated domain addenda content only.
|
|
1005
1289
|
|
|
1006
1290
|
- id: domain_validation_loop
|
|
1291
|
+
condition: "{{author_repo}} == true"
|
|
1007
1292
|
action: loop
|
|
1008
1293
|
while: "{{domain_ok}} != true"
|
|
1009
1294
|
max_iterations: 3
|
|
@@ -1035,6 +1320,7 @@ workflow:
|
|
|
1035
1320
|
|
|
1036
1321
|
# ── COMPOSE + ACTIVATE ───────────────────────────────────────────────────────
|
|
1037
1322
|
- id: compose_constitution
|
|
1323
|
+
condition: "{{author_repo}} == true"
|
|
1038
1324
|
action: execute_script
|
|
1039
1325
|
script: { ref: actions }
|
|
1040
1326
|
subcommand: compose-constitution
|
|
@@ -1057,6 +1343,7 @@ workflow:
|
|
|
1057
1343
|
# Ordered override — the var holds "ok" unless the check reported a problem, because
|
|
1058
1344
|
# require_non_empty reports on EMPTY.
|
|
1059
1345
|
- id: numbering_default
|
|
1346
|
+
condition: "{{author_repo}} == true"
|
|
1060
1347
|
action: set
|
|
1061
1348
|
vars: { numbering_gate: "ok" }
|
|
1062
1349
|
- id: numbering_detect
|
|
@@ -1064,6 +1351,7 @@ workflow:
|
|
|
1064
1351
|
condition: "{{numbering_ok}} == false"
|
|
1065
1352
|
vars: { numbering_gate: "" }
|
|
1066
1353
|
- id: numbering_warning
|
|
1354
|
+
condition: "{{author_repo}} == true"
|
|
1067
1355
|
action: verify_context
|
|
1068
1356
|
require_non_empty: numbering_gate
|
|
1069
1357
|
on_empty: continue
|
|
@@ -1079,6 +1367,7 @@ workflow:
|
|
|
1079
1367
|
# Auto-activate: point .appweaver/domain.json at the scaffolded project so the forward CR
|
|
1080
1368
|
# loop governs development with it from the first change.
|
|
1081
1369
|
- id: activate_domain
|
|
1370
|
+
condition: "{{author_repo}} == true"
|
|
1082
1371
|
action: execute_script
|
|
1083
1372
|
script: { ref: actions }
|
|
1084
1373
|
subcommand: set-domain
|
|
@@ -1110,7 +1399,7 @@ workflow:
|
|
|
1110
1399
|
# lives inside pack_dir, so pack_guard (above) already protects it from clobber.
|
|
1111
1400
|
- id: ctx_tech_pack
|
|
1112
1401
|
action: build_context
|
|
1113
|
-
condition: "{{
|
|
1402
|
+
condition: "{{author_svc}} == true"
|
|
1114
1403
|
context:
|
|
1115
1404
|
- { path: "{{inventory_json}}" } # PRIMARY: the COMPLETE deterministic substrate — read representative SOURCE from its file lists
|
|
1116
1405
|
- { path: "{{constitution_technical_file}}" } # PRIMARY: the VALIDATED as-built technology base — the ratified principles these files detail
|
|
@@ -1121,7 +1410,7 @@ workflow:
|
|
|
1121
1410
|
context_from: design_context
|
|
1122
1411
|
- id: author_tech_pack
|
|
1123
1412
|
action: agent_generate
|
|
1124
|
-
condition: "{{
|
|
1413
|
+
condition: "{{author_svc}} == true"
|
|
1125
1414
|
tools: "Read,Write,Edit"
|
|
1126
1415
|
permission_mode: acceptEdits
|
|
1127
1416
|
task: |
|
|
@@ -1209,11 +1498,12 @@ workflow:
|
|
|
1209
1498
|
|
|
1210
1499
|
- id: verify_tech_pack
|
|
1211
1500
|
action: verify_context
|
|
1212
|
-
condition: "{{
|
|
1501
|
+
condition: "{{author_svc}} == true"
|
|
1213
1502
|
require_non_empty: tech_pack_files
|
|
1214
1503
|
on_empty: stop
|
|
1215
1504
|
on_empty_message: "No technical rule files were written to guardrails/projects/{{domain_slug}}/service/. Ensure the scan substrate (inventory_json) + the validated technical constitution carry an as-built technology base and re-run."
|
|
1216
1505
|
- id: require_tech_rule_bindings
|
|
1506
|
+
condition: "{{author_repo}} == true"
|
|
1217
1507
|
action: verify_context
|
|
1218
1508
|
required_files: ["{{pack_dir}}/tech-rule-bindings.md"]
|
|
1219
1509
|
|
|
@@ -1226,7 +1516,7 @@ workflow:
|
|
|
1226
1516
|
# file, and the run's remaining work is worth keeping either way.
|
|
1227
1517
|
- id: probe_specify_wiring
|
|
1228
1518
|
action: execute_script
|
|
1229
|
-
condition: "{{
|
|
1519
|
+
condition: "{{author_svc}} == true"
|
|
1230
1520
|
on_error: continue
|
|
1231
1521
|
script: { ref: actions }
|
|
1232
1522
|
subcommand: resolve-tech
|
|
@@ -1235,7 +1525,7 @@ workflow:
|
|
|
1235
1525
|
- { name: specify_rules, from: "$.candidates" }
|
|
1236
1526
|
- id: warn_specify_wiring
|
|
1237
1527
|
action: verify_context
|
|
1238
|
-
condition: "{{
|
|
1528
|
+
condition: "{{author_svc}} == true"
|
|
1239
1529
|
require_non_empty: specify_rules
|
|
1240
1530
|
on_empty: continue
|
|
1241
1531
|
on_empty_message: >
|
|
@@ -1259,7 +1549,7 @@ workflow:
|
|
|
1259
1549
|
# find the lane on every future run without stacks.json or a named stack.
|
|
1260
1550
|
- id: ctx_ui_pack
|
|
1261
1551
|
action: build_context
|
|
1262
|
-
condition: "{{
|
|
1552
|
+
condition: "{{author_ui_flag}} == true"
|
|
1263
1553
|
context:
|
|
1264
1554
|
- { path: "{{inventory_json}}" } # PRIMARY: the COMPLETE deterministic substrate — frontend_signals + the UI file lists to read source from
|
|
1265
1555
|
- { path: "{{constitution_ui_file}}" } # PRIMARY: the VALIDATED as-built UX-* base — the ratified principles these files detail
|
|
@@ -1270,7 +1560,7 @@ workflow:
|
|
|
1270
1560
|
- { path: "{{bundle_dir}}/architecture/frontend.md", optional: true } # SECONDARY (shallow): the OKF as-built frontend note
|
|
1271
1561
|
- id: author_ui_pack
|
|
1272
1562
|
action: agent_generate
|
|
1273
|
-
condition: "{{
|
|
1563
|
+
condition: "{{author_ui_flag}} == true"
|
|
1274
1564
|
tools: "Read,Write,Edit"
|
|
1275
1565
|
permission_mode: acceptEdits
|
|
1276
1566
|
task: |
|
|
@@ -1342,7 +1632,7 @@ workflow:
|
|
|
1342
1632
|
|
|
1343
1633
|
- id: verify_ui_pack
|
|
1344
1634
|
action: verify_context
|
|
1345
|
-
condition: "{{
|
|
1635
|
+
condition: "{{author_ui_flag}} == true"
|
|
1346
1636
|
require_non_empty: ui_pack_files
|
|
1347
1637
|
on_empty: stop
|
|
1348
1638
|
on_empty_message: "A frontend lane was detected ({{ui_evidence}}) but no lane rule files were written to guardrails/projects/{{domain_slug}}/frontend/. Check that the scan substrate's frontend_signals carry readable UI source, then re-run."
|
|
@@ -1354,7 +1644,7 @@ workflow:
|
|
|
1354
1644
|
# it. Announce, don't stop — the rule files are on disk and the heading is one edit away.
|
|
1355
1645
|
- id: probe_ui_wiring
|
|
1356
1646
|
action: execute_script
|
|
1357
|
-
condition: "{{
|
|
1647
|
+
condition: "{{author_ui_flag}} == true"
|
|
1358
1648
|
on_error: continue
|
|
1359
1649
|
script: { ref: actions }
|
|
1360
1650
|
subcommand: resolve-tech
|
|
@@ -1363,7 +1653,7 @@ workflow:
|
|
|
1363
1653
|
- { name: ui_map_rules, from: "$.candidates" }
|
|
1364
1654
|
- id: warn_ui_wiring
|
|
1365
1655
|
action: verify_context
|
|
1366
|
-
condition: "{{
|
|
1656
|
+
condition: "{{author_ui_flag}} == true"
|
|
1367
1657
|
require_non_empty: ui_map_rules
|
|
1368
1658
|
on_empty: continue
|
|
1369
1659
|
on_empty_message: >
|
|
@@ -1391,6 +1681,7 @@ workflow:
|
|
|
1391
1681
|
# the run reports the lanes it actually scanned under rather than a second opinion
|
|
1392
1682
|
# about them.
|
|
1393
1683
|
- id: lane_readback
|
|
1684
|
+
condition: "{{author_repo}} == true"
|
|
1394
1685
|
action: execute_script
|
|
1395
1686
|
on_error: continue
|
|
1396
1687
|
script: { ref: actions }
|
|
@@ -1415,7 +1706,13 @@ workflow:
|
|
|
1415
1706
|
# override_active ⇒ design_mode == bootstrap_bf) then authors EVERY new feature against the
|
|
1416
1707
|
# as-built architecture, and a CHANGE authors its delta-design against the SAME code-derived
|
|
1417
1708
|
# sections (cr-setup scaffolds the delta from resolve_template("delta-design-template") ⇒
|
|
1418
|
-
# the override) — no adopt required, consistent with the
|
|
1709
|
+
# the override) — no adopt required, consistent with the backend-plan.md adopt emits.
|
|
1710
|
+
#
|
|
1711
|
+
# THE TEMPLATE IDENTIFIERS KEEP THE `design-template` SPELLING DELIBERATELY. The DOCUMENTS
|
|
1712
|
+
# are backend-plan.md / frontend-plan.md now; the template NAMES are not, because a repo
|
|
1713
|
+
# that already ran onboard carries its override at overrides/design-template.md and
|
|
1714
|
+
# renaming the identifier would make that file stop resolving — silently falling back to
|
|
1715
|
+
# the kit's greenfield template and imposing a layering the codebase never chose.
|
|
1419
1716
|
#
|
|
1420
1717
|
# GROUNDED IN CODE + REVERSE-ENGINEERED FILES ONLY. The Part-1 OKF feature map is a SHALLOW
|
|
1421
1718
|
# discovery index (by design — NOT a deep reverse), so it is NOT the authority: the section
|
|
@@ -1444,7 +1741,7 @@ workflow:
|
|
|
1444
1741
|
# plus a NEUTRAL skeleton for the bones. No greenfield template is in context.
|
|
1445
1742
|
- id: ctx_design_template
|
|
1446
1743
|
action: build_context
|
|
1447
|
-
condition: "{{
|
|
1744
|
+
condition: "{{author_svc}} == true"
|
|
1448
1745
|
context:
|
|
1449
1746
|
- { path: "{{inventory_json}}" } # PRIMARY: the COMPLETE deterministic substrate (top_level_dirs, aggregate_signals' per-layer file groupings) — the OKF markdown only SUMMARISES this
|
|
1450
1747
|
- { path: "{{constitution_technical_file}}" } # PRIMARY: the VALIDATED as-built technology base (framework/persistence/concurrency/hosting/testing/cross-cutting)
|
|
@@ -1455,7 +1752,7 @@ workflow:
|
|
|
1455
1752
|
- { path: "{{bundle_dir}}/aggregates/index.md", optional: true } # SECONDARY (shallow): the bounded-context / feature map
|
|
1456
1753
|
- id: gen_design_template
|
|
1457
1754
|
action: agent_generate
|
|
1458
|
-
condition: "{{
|
|
1755
|
+
condition: "{{author_svc}} == true"
|
|
1459
1756
|
tools: "Read,Write,Edit"
|
|
1460
1757
|
permission_mode: acceptEdits
|
|
1461
1758
|
task: |
|
|
@@ -1545,7 +1842,7 @@ workflow:
|
|
|
1545
1842
|
|
|
1546
1843
|
- id: verify_design_template
|
|
1547
1844
|
action: verify_context
|
|
1548
|
-
condition: "{{
|
|
1845
|
+
condition: "{{author_svc}} == true"
|
|
1549
1846
|
require_non_empty: design_template_files
|
|
1550
1847
|
on_empty: stop
|
|
1551
1848
|
on_empty_message: "No design template was written to .appweaver/templates/overrides/design-template.md. Ensure the scan substrate (inventory_json) + the technical constitution are present and re-run."
|
|
@@ -1556,14 +1853,14 @@ workflow:
|
|
|
1556
1853
|
# master's OWN section structure").
|
|
1557
1854
|
- id: ctx_delta_design_template
|
|
1558
1855
|
action: build_context
|
|
1559
|
-
condition: "{{
|
|
1856
|
+
condition: "{{author_svc}} == true"
|
|
1560
1857
|
context:
|
|
1561
1858
|
- { path: .appweaver/templates/overrides/design-template.md, optional: true } # PRIMARY: the JUST-generated code-derived master — mirror its ACTUAL sections
|
|
1562
1859
|
- { path: .appweaver/orchestrator/rev-templates/delta-design-template.skeleton.md } # SHAPE ONLY: the neutral change-record bones (zero layering, zero technology)
|
|
1563
1860
|
- { path: "{{constitution_technical_file}}" } # the validated as-built technology base (keep the delta consistent with the master)
|
|
1564
1861
|
- id: gen_delta_design_template
|
|
1565
1862
|
action: agent_generate
|
|
1566
|
-
condition: "{{
|
|
1863
|
+
condition: "{{author_svc}} == true"
|
|
1567
1864
|
tools: "Read,Write,Edit"
|
|
1568
1865
|
permission_mode: acceptEdits
|
|
1569
1866
|
task: |
|
|
@@ -1592,11 +1889,91 @@ workflow:
|
|
|
1592
1889
|
|
|
1593
1890
|
- id: verify_delta_design_template
|
|
1594
1891
|
action: verify_context
|
|
1595
|
-
condition: "{{
|
|
1892
|
+
condition: "{{author_svc}} == true"
|
|
1596
1893
|
require_non_empty: delta_design_template_files
|
|
1597
1894
|
on_empty: stop
|
|
1598
1895
|
on_empty_message: "No delta-design template was written to .appweaver/templates/overrides/delta-design-template.md. Re-run onboard after confirming the design template override was generated."
|
|
1599
1896
|
|
|
1897
|
+
# ═══════ CODE-DERIVED DOMAIN-MODEL TEMPLATE (the context's structure) ════════
|
|
1898
|
+
# The same argument as the design pair, for the document that carries the DOMAIN. A
|
|
1899
|
+
# bounded context's domain-model.md is where the aggregate root, its boundary, its
|
|
1900
|
+
# entities and the TEXT of every BR-nnn live; `specify` fills it on the forward path and
|
|
1901
|
+
# `adopt` fills it per reversed slice. Without a code-derived override both author
|
|
1902
|
+
# against the kit's GREENFIELD model template, whose shape assumes a domain that was
|
|
1903
|
+
# designed before it was built — the one assumption a brownfield repo is guaranteed to
|
|
1904
|
+
# break.
|
|
1905
|
+
#
|
|
1906
|
+
# NOT GATED ON A LANE. The domain model is ubiquitous language and invariants, which a
|
|
1907
|
+
# frontend-only project has as much as any other; WHERE an invariant is enforced is the
|
|
1908
|
+
# backend plan's concern and is gated with the service block above.
|
|
1909
|
+
#
|
|
1910
|
+
# A TEMPLATE OF A TEMPLATE. What this writes is not a filled model — it is the project's
|
|
1911
|
+
# domain-model TEMPLATE, keeping every [PLACEHOLDER] and authoring comment. What onboard
|
|
1912
|
+
# replaces is the STRUCTURE, never the content, and it must name NO aggregate and NO
|
|
1913
|
+
# entity: naming one would hand the downstream author the answer to the single question
|
|
1914
|
+
# the reverse exists to ask the code.
|
|
1915
|
+
- id: ctx_model_template
|
|
1916
|
+
condition: "{{author_repo}} == true"
|
|
1917
|
+
action: build_context
|
|
1918
|
+
context:
|
|
1919
|
+
- { path: "{{inventory_json}}" } # PRIMARY: the COMPLETE deterministic substrate
|
|
1920
|
+
- { path: .appweaver/orchestrator/rev-templates/domain-model-template.skeleton.md } # SHAPE ONLY: the neutral bones + the pinned anchors
|
|
1921
|
+
- { path: "{{constitution_domain_file}}", optional: true } # the reversed DOMAIN frame — vocabulary, not structure
|
|
1922
|
+
- { path: "{{bundle_dir}}/aggregates/index.md", optional: true } # SECONDARY (shallow): the bounded-context / feature map
|
|
1923
|
+
- id: gen_model_template
|
|
1924
|
+
condition: "{{author_repo}} == true"
|
|
1925
|
+
action: agent_generate
|
|
1926
|
+
tools: "Read,Write,Edit"
|
|
1927
|
+
permission_mode: acceptEdits
|
|
1928
|
+
task: |
|
|
1929
|
+
REVERSE-ENGINEER this repo's DOMAIN MODEL convention into a PROJECT-SPECIFIC
|
|
1930
|
+
domain-model TEMPLATE and Write it to
|
|
1931
|
+
.appweaver/templates/overrides/domain-model-template.md (create the overrides/ dir if
|
|
1932
|
+
absent). It is a TEMPLATE — section headers with [PLACEHOLDER] tokens + authoring
|
|
1933
|
+
HTML comments that `specify` (forward) and `adopt` (per reversed slice) fill per
|
|
1934
|
+
context — NOT a filled model.
|
|
1935
|
+
|
|
1936
|
+
GROUND EVERYTHING IN THE CODE. Read REPRESENTATIVE source files; the OKF map in
|
|
1937
|
+
context is a SHALLOW discovery index and corroborates, it does not decide.
|
|
1938
|
+
|
|
1939
|
+
KEEP THE PINNED ANCHORS from the skeleton in context — each is machinery something
|
|
1940
|
+
keys on, not taste:
|
|
1941
|
+
- `## Aggregate: <Name>` is the MERGE UNIT. finalize-delta merges a model delta one
|
|
1942
|
+
such section at a time, so the heading FORM cannot be reshaped per project. Keep it
|
|
1943
|
+
as ONE repeatable block.
|
|
1944
|
+
- `### Invariants` carries stable BR-nnn ids — specs cite them and the conformance
|
|
1945
|
+
gates trace them, so the id class cannot be renamed.
|
|
1946
|
+
- `**Serving specs**:` is what makes a cross-spec aggregate visible from the model
|
|
1947
|
+
side; keep it.
|
|
1948
|
+
- The Change History table is the model's version ledger. close-delta appends to it
|
|
1949
|
+
and stamps the context version; the model never writes its own.
|
|
1950
|
+
|
|
1951
|
+
WHAT YOU MAY ADAPT is everything else: which subsections an aggregate section carries
|
|
1952
|
+
and what they are CALLED, in this codebase's own vocabulary. If the code expresses
|
|
1953
|
+
structure through something it names differently, template THAT and say in a comment
|
|
1954
|
+
which code paths evidence it.
|
|
1955
|
+
|
|
1956
|
+
NAME NO AGGREGATE, NO ENTITY AND NO TECHNOLOGY. Every [BRACKET] token stays a token.
|
|
1957
|
+
Write the authoring comments so the downstream author derives from the code the way
|
|
1958
|
+
the skeleton's BROWNFIELD DERIVATION note describes — aggregate roots from the types
|
|
1959
|
+
referenced by id but never navigated into and the transaction boundaries the
|
|
1960
|
+
persistence layer commits; entity vs value object by IDENTITY; invariants from the
|
|
1961
|
+
guards and the persistence constraints, recording that the CODE is their current
|
|
1962
|
+
authority; the ubiquitous language from the names the code actually uses, recording
|
|
1963
|
+
BOTH where code and business disagree rather than silently picking one.
|
|
1964
|
+
|
|
1965
|
+
Write ONLY the override file; modify no source. Report the file written and the
|
|
1966
|
+
structural choices you derived, with the code paths that evidence them.
|
|
1967
|
+
outputs:
|
|
1968
|
+
- { name: model_template_files, from: "$.files" }
|
|
1969
|
+
|
|
1970
|
+
- id: verify_model_template
|
|
1971
|
+
condition: "{{author_repo}} == true"
|
|
1972
|
+
action: verify_context
|
|
1973
|
+
require_non_empty: model_template_files
|
|
1974
|
+
on_empty: stop
|
|
1975
|
+
on_empty_message: "No domain-model template was written to .appweaver/templates/overrides/domain-model-template.md. Without it every reversed slice authors its aggregate against the kit's GREENFIELD model template, whose shape assumes a domain designed before it was built. Ensure the scan substrate (inventory_json) is present and re-run."
|
|
1976
|
+
|
|
1600
1977
|
# ═══════ UI DESIGN TEMPLATES (frontend lane only) — the LANE's own pair ═══════
|
|
1601
1978
|
# The lane's twin of the two steps above, on the same terms: reverse-engineered from
|
|
1602
1979
|
# the UI SOURCE, shaped by a NEUTRAL skeleton, installed in the project override slot
|
|
@@ -1625,7 +2002,7 @@ workflow:
|
|
|
1625
2002
|
# nothing breaks for their absence in a repo that never onboarded.
|
|
1626
2003
|
- id: ctx_ui_design_template
|
|
1627
2004
|
action: build_context
|
|
1628
|
-
condition: "{{
|
|
2005
|
+
condition: "{{author_ui_flag}} == true"
|
|
1629
2006
|
context:
|
|
1630
2007
|
- { path: "{{inventory_json}}" } # PRIMARY: the COMPLETE deterministic substrate — frontend_signals + the component/route/store/style file lists to read source from
|
|
1631
2008
|
- { path: "{{constitution_ui_file}}" } # PRIMARY: the VALIDATED as-built UX-* base — the ratified principles this structure must serve
|
|
@@ -1634,7 +2011,7 @@ workflow:
|
|
|
1634
2011
|
- { path: "{{bundle_dir}}/architecture/frontend.md", optional: true } # SECONDARY (shallow): the OKF as-built frontend note
|
|
1635
2012
|
- id: gen_ui_design_template
|
|
1636
2013
|
action: agent_generate
|
|
1637
|
-
condition: "{{
|
|
2014
|
+
condition: "{{author_ui_flag}} == true"
|
|
1638
2015
|
tools: "Read,Write,Edit"
|
|
1639
2016
|
permission_mode: acceptEdits
|
|
1640
2017
|
task: |
|
|
@@ -1712,7 +2089,7 @@ workflow:
|
|
|
1712
2089
|
|
|
1713
2090
|
- id: verify_ui_design_template
|
|
1714
2091
|
action: verify_context
|
|
1715
|
-
condition: "{{
|
|
2092
|
+
condition: "{{author_ui_flag}} == true"
|
|
1716
2093
|
require_non_empty: ui_design_template_files
|
|
1717
2094
|
on_empty: stop
|
|
1718
2095
|
on_empty_message: "A frontend lane was detected ({{ui_evidence}}) but no UI design template was written to .appweaver/templates/overrides/ui-design-template.md. Check that the scan substrate's frontend_signals carry readable UI source, then re-run."
|
|
@@ -1721,14 +2098,14 @@ workflow:
|
|
|
1721
2098
|
# as the service delta mirrors the service master.
|
|
1722
2099
|
- id: ctx_ui_delta_design_template
|
|
1723
2100
|
action: build_context
|
|
1724
|
-
condition: "{{
|
|
2101
|
+
condition: "{{author_ui_flag}} == true"
|
|
1725
2102
|
context:
|
|
1726
2103
|
- { path: .appweaver/templates/overrides/ui-design-template.md, optional: true } # PRIMARY: the JUST-generated lane master — mirror its ACTUAL sections
|
|
1727
2104
|
- { path: .appweaver/orchestrator/rev-templates/ui-delta-design-template.skeleton.md } # SHAPE ONLY: the neutral change-record bones (zero framework)
|
|
1728
2105
|
- { path: "{{constitution_ui_file}}" } # the validated UX-* base (keep the delta consistent with the master)
|
|
1729
2106
|
- id: gen_ui_delta_design_template
|
|
1730
2107
|
action: agent_generate
|
|
1731
|
-
condition: "{{
|
|
2108
|
+
condition: "{{author_ui_flag}} == true"
|
|
1732
2109
|
tools: "Read,Write,Edit"
|
|
1733
2110
|
permission_mode: acceptEdits
|
|
1734
2111
|
task: |
|
|
@@ -1762,7 +2139,7 @@ workflow:
|
|
|
1762
2139
|
|
|
1763
2140
|
- id: verify_ui_delta_design_template
|
|
1764
2141
|
action: verify_context
|
|
1765
|
-
condition: "{{
|
|
2142
|
+
condition: "{{author_ui_flag}} == true"
|
|
1766
2143
|
require_non_empty: ui_delta_design_template_files
|
|
1767
2144
|
on_empty: stop
|
|
1768
2145
|
on_empty_message: "No UI delta-design template was written to .appweaver/templates/overrides/ui-delta-design-template.md. Re-run onboard after confirming the UI design template override was generated."
|
|
@@ -1781,6 +2158,13 @@ workflow:
|
|
|
1781
2158
|
|
|
1782
2159
|
outputs:
|
|
1783
2160
|
bundle_dir: "{{bundle_dir}}"
|
|
2161
|
+
# The context's specs tree — created here, empty by design. It is what makes the
|
|
2162
|
+
# context visible to list-contexts and its features pickable by select-feature.
|
|
2163
|
+
bounded_context: "{{bc}}"
|
|
2164
|
+
context_dir: "{{bc_dir}}"
|
|
2165
|
+
context_domain_model: "{{bc_domain_model}}"
|
|
2166
|
+
feature_dirs: "{{feature_dirs}}"
|
|
2167
|
+
feature_dirs_created: "{{dirs_created}}"
|
|
1784
2168
|
aggregate_count: "{{aggregate_count}}"
|
|
1785
2169
|
concepts: "{{concepts}}"
|
|
1786
2170
|
warnings: "{{okf_warnings}}"
|
|
@@ -1820,9 +2204,10 @@ outputs:
|
|
|
1820
2204
|
delta_design_template_override: ".appweaver/templates/overrides/delta-design-template.md"
|
|
1821
2205
|
design_template_files: "{{design_template_files}}"
|
|
1822
2206
|
delta_design_template_files: "{{delta_design_template_files}}"
|
|
2207
|
+
model_template_files: "{{model_template_files}}" # the context's domain-model template — not lane-gated
|
|
1823
2208
|
# The lane's own template pair. Empty on a backend-only repo — no lane, no files.
|
|
1824
2209
|
ui_design_template_files: "{{ui_design_template_files}}"
|
|
1825
2210
|
ui_delta_design_template_files: "{{ui_delta_design_template_files}}"
|
|
1826
2211
|
technical_validation_ok: "{{technical_ok}}"
|
|
1827
2212
|
domain_validation_ok: "{{domain_ok}}"
|
|
1828
|
-
next: "Onboarded {{
|
|
2213
|
+
next: "Onboarded bounded context {{bc}} ({{bc_feature_count}} feature(s): {{bc_features}}). Its aggregate concepts ({{bc_aggregates}}) are in {{bundle_dir}}, each keyed `bounded_context: {{bc}}` and listing the features that act on it — the bundle is the project's knowledge, one concept per aggregate, never one per feature — and its specs tree now exists at {{bc_dir}}/ with a directory per feature ({{feature_dirs}}) — EMPTY on purpose: the directory says the feature is known, and the documents that describe it are written per feature by /appweaver adopt and per context by /appweaver specify. {{bc}} is now the ACTIVE bounded context (.appweaver/context.json), so /appweaver select-feature lists exactly these features and nothing from a neighbouring context; switch with /appweaver select-bounded-context. ONBOARD RUNS ONCE PER CONTEXT: contexts already done — {{onboarded_contexts}}; still open — {{remaining_contexts}}; the order the map gives is {{contexts_ordered}}. Run /appweaver onboard <NextContext> for each remaining one, or with no argument to take the next one automatically. THE PROJECT TIER IS WRITTEN ONCE, BY THE FIRST CONTEXT (this run was first: {{is_first}}). That tier is the PROVISIONAL governance scaffold — the split constitution, the domain rule set at guardrails/projects/{{domain_slug}}/domain/*.domain.md + domain-rule-bindings.md, each declared LANE\'s rule set and constitution half, the activated domain {{active_domain}}, and the code-derived design / delta-design / domain-model template overrides in .appweaver/templates/overrides/. A later context does NOT re-author any of it: re-deriving project principles from one context\'s evidence is the scoping bias the governance tier exists to avoid. Amend it with /appweaver constitution. ONE HALF AND ONE RULE SET PER LANE: service_lane / ui_lane report which lanes .appweaver/stacks.json declared, and the declaration is what decided. A lane declared (none) in select-stack gets none of it, which is the correct outcome and not an omission. LANE DECLARATION: read, never written — select-stack is its sole writer, and this run scanned the source paths it named (scanned_service_root / scanned_ui_root); scanned_backend_files / scanned_ui_files report each. ui_source_evidence_found false means the UI lane\'s declared path held nothing a scan recognises as UI, so its governance is thin — move the source path with /appweaver select-stack and re-run. The build/test/run commands on each lane are that PROFILE\'s defaults and may not match a legacy layout — review them. Because the domain is activated, resolve-domain + resolve-tech route the WHOLE forward pipeline to these code-derived rules — never another project\'s rules as a fallback. THE BOUNDARIES CAME FROM THE MAP, not from this run: /appweaver inventory proposed them and you confirmed them in specs/proposed-inventory.md. To change a boundary, edit that file and run /appweaver inventory apply — a context whose concepts already exist is not re-onboarded. Develop an EXISTING feature just-in-time: /appweaver adopt <Feature> reverse-engineers its spec.md + design.md + source-map.md and deepens the OKF concept of the aggregate it acts on. Develop a NEW feature straight through the forward pipeline (/appweaver specify → plan → implement). Then drive every change through the CR delta loop (/appweaver specify → plan → analyze-plan-delta → implement → build → analyze-slice-delta → finalize-delta → analyze-slice → close-delta). If a validation_ok is false, its constitution half needs a manual touch (see its Sync Impact Report)."
|