aw-spec-cli 0.1.31 → 0.1.33
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 +10 -3
- package/assets/.appweaver/STACK-PROFILES.md +9 -1
- package/assets/.appweaver/orchestrator/rev-templates/delta-design-template.skeleton.md +10 -6
- package/assets/.appweaver/orchestrator/rev-templates/design-template.skeleton.md +53 -3
- package/assets/.appweaver/orchestrator/workflows/aw-spec-adopt.orch.yaml +128 -22
- package/assets/.appweaver/orchestrator/workflows/aw-spec-inventory.orch.yaml +77 -26
- package/assets/.appweaver/orchestrator/workflows/aw-spec-onboard.orch.yaml +104 -33
- package/assets/.appweaver/orchestrator/workflows/aw-spec-plan.orch.yaml +6 -2
- package/assets/.appweaver/orchestrator/workflows/aw-spec-select-lane.orch.yaml +7 -4
- package/assets/.appweaver/scripts/powershell/aw-inventory.ps1 +20 -5
- package/assets/.appweaver/scripts/python/aw-inventory.py +2064 -259
- package/assets/.appweaver/scripts/python/aw-stack.py +13 -4
- package/assets/.appweaver/scripts/python/aw-xref.py +63 -43
- package/assets/.appweaver/templates/okf-concept-template.md +3 -1
- package/assets/.appweaver/templates/proposed-inventory-template.md +52 -13
- package/assets/foundations/java/Hexagonal/unpack-foundation.ps1 +168 -0
- package/package.json +1 -1
|
@@ -10,16 +10,20 @@
|
|
|
10
10
|
# ← you are here
|
|
11
11
|
#
|
|
12
12
|
# It reads back the model the greenfield sequence writes — bounded context →
|
|
13
|
-
# aggregate → feature → operation — from the code: the module folder
|
|
14
|
-
# a declared aggregate-root type is the aggregate, a UI
|
|
15
|
-
# the capability, and a slice under the
|
|
16
|
-
#
|
|
17
|
-
#
|
|
13
|
+
# aggregate → feature → operation — from the code, whatever its stack: the module folder
|
|
14
|
+
# is the context, a declared aggregate-root type is the aggregate, a UI
|
|
15
|
+
# features/<Feature>/ folder is the capability, and an operation is a slice under the
|
|
16
|
+
# module's Features/, a command/query handler, a use case or an endpoint (a controller
|
|
17
|
+
# action, an annotated or decorated handler, a router call) — never a feature. Three
|
|
18
|
+
# passes; the generated document explains each to the operator reading it, in the
|
|
19
|
+
# wording of the template
|
|
18
20
|
# .appweaver/templates/proposed-inventory-template.md, overridable per project:
|
|
19
21
|
# A the aggregates. Four strategies — domain (the roots the code declares),
|
|
20
22
|
# structure, reference graph, persistence — each offered only where its
|
|
21
23
|
# evidence exists, each reporting its own numbers. Declared roots that
|
|
22
|
-
# operations act on are chosen ahead of any measured strategy.
|
|
24
|
+
# operations act on are chosen ahead of any measured strategy. A project that
|
|
25
|
+
# declares a UI lane and no service lane has one strategy, `ui`: the API
|
|
26
|
+
# resources its UI calls are the aggregates, its calls the operations.
|
|
23
27
|
# B the operations and their seams — each operation's route, the aggregate it
|
|
24
28
|
# acts on, whether it creates one. Emits signals, never decisions.
|
|
25
29
|
# C the features — one per UI feature folder, holding the operations it calls;
|
|
@@ -40,8 +44,8 @@
|
|
|
40
44
|
# =============================================================================
|
|
41
45
|
|
|
42
46
|
name: aw-spec-inventory
|
|
43
|
-
description: Brownfield discovery — scan an existing codebase and propose its Features and Bounded Contexts, in dependency order with their dependencies, as an editable specs/proposed-inventory.md. Runs three passes (aggregate identification by a selectable evidence-gated strategy, a seam overlay over application/API/UI, and a 1:1-by-default feature proposal with evidenced splits offered but never applied). `apply` validates the operator's edits and regenerates the machine map onboard consumes. Never modifies source.
|
|
44
|
-
version: 2.
|
|
47
|
+
description: Brownfield discovery — scan an existing codebase in any stack and propose its Features and Bounded Contexts, in dependency order with their dependencies, as an editable specs/proposed-inventory.md. Runs three passes (aggregate identification by a selectable evidence-gated strategy, a seam overlay over application/API/UI, and a 1:1-by-default feature proposal with evidenced splits offered but never applied); a project with a UI lane and no service lane is read from the API calls its UI makes. `apply` validates the operator's edits and regenerates the machine map onboard consumes. Never modifies source.
|
|
48
|
+
version: 2.1.0
|
|
45
49
|
agent_agnostic: true
|
|
46
50
|
dialect: aw-spec.orchestrator/v1
|
|
47
51
|
|
|
@@ -51,10 +55,12 @@ inputs:
|
|
|
51
55
|
Either the literal word `apply` — validate the edited specs/proposed-inventory.md
|
|
52
56
|
and regenerate the machine map — or an optional Pass A strategy name
|
|
53
57
|
(domain | structure | reference | persistence) to force, plus free-text focus
|
|
54
|
-
hints.
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
+
hints. A strategy named as the first word is used without asking; a first word
|
|
59
|
+
that names none forces nothing. With no strategy named, `domain` is proposed where
|
|
60
|
+
the code declares aggregate roots that operations act on, and otherwise the
|
|
61
|
+
highest-coverage available strategy; the operator confirms it from a menu carrying
|
|
62
|
+
each strategy's measured numbers, the proposed one first. A project with no
|
|
63
|
+
service lane is read by `ui` alone.
|
|
58
64
|
required: false
|
|
59
65
|
bind: USER_INPUT
|
|
60
66
|
|
|
@@ -73,7 +79,6 @@ standards:
|
|
|
73
79
|
|
|
74
80
|
vars:
|
|
75
81
|
mode: "propose" # apply-mode driver
|
|
76
|
-
strategy: "" # forced Pass A strategy; empty = probe default
|
|
77
82
|
feature_count: "0"
|
|
78
83
|
proposal_ok: "false"
|
|
79
84
|
|
|
@@ -142,17 +147,27 @@ workflow:
|
|
|
142
147
|
|
|
143
148
|
# 1. WHICH LANES, AND WHERE IS THEIR SOURCE. Same declaration onboard reads:
|
|
144
149
|
# the scan is scoped to the declared subtrees so backend candidates are not
|
|
145
|
-
# drawn from UI source and vice versa.
|
|
150
|
+
# drawn from UI source and vice versa. A lane can be declared before it is built,
|
|
151
|
+
# so a lane root folder that does not exist yet is allowed here: the scan reads
|
|
152
|
+
# the lanes whose folders exist and the proposal names the one it did not read.
|
|
146
153
|
- id: lane_model
|
|
147
154
|
action: execute_script
|
|
148
155
|
condition: "{{mode}} == propose"
|
|
149
156
|
script: { ref: actions }
|
|
150
157
|
subcommand: lane-verify
|
|
151
|
-
args: ["--command", "/appweaver inventory"]
|
|
158
|
+
args: ["--command", "/appweaver inventory", "--allow-missing-root"]
|
|
152
159
|
outputs:
|
|
153
160
|
- { name: lane_model_ok, from: "$.ok" }
|
|
154
161
|
- { name: lane_model_issues, from: "$.message" }
|
|
162
|
+
- { name: kinds_on_disk, from: "$.kinds_on_disk" }
|
|
163
|
+
- { name: missing_roots, from: "$.missing_roots" }
|
|
164
|
+
- { name: be_declared, from: "$.backend_declared" }
|
|
165
|
+
- { name: be_built, from: "$.backend_root_exists" }
|
|
166
|
+
- { name: be_lane_id, from: "$.backend_lane_id" }
|
|
155
167
|
- { name: be_root, from: "$.backend_source_path" }
|
|
168
|
+
- { name: fe_declared, from: "$.frontend_declared" }
|
|
169
|
+
- { name: fe_built, from: "$.frontend_root_exists" }
|
|
170
|
+
- { name: fe_lane_id, from: "$.frontend_lane_id" }
|
|
156
171
|
- { name: fe_root, from: "$.frontend_source_path" }
|
|
157
172
|
|
|
158
173
|
- id: lane_model_gate
|
|
@@ -166,16 +181,48 @@ workflow:
|
|
|
166
181
|
holds which lane before it starts. Run /appweaver select-stack first — it
|
|
167
182
|
detects what this repo already is and lets you correct the proposal.
|
|
168
183
|
|
|
184
|
+
- id: lane_built_gate
|
|
185
|
+
action: verify_context
|
|
186
|
+
condition: "{{mode}} == propose"
|
|
187
|
+
require_non_empty: kinds_on_disk
|
|
188
|
+
on_empty: stop
|
|
189
|
+
on_empty_message: >
|
|
190
|
+
/appweaver inventory has no code to read: {{missing_roots}}
|
|
191
|
+
Inventory reads the code of the lanes whose folders exist, and no declared lane
|
|
192
|
+
has one yet.
|
|
193
|
+
|
|
194
|
+
# A declared lane with no folder yet is not read. Said once, here, and in the
|
|
195
|
+
# proposal's Scanned line; the run goes on with the lane that exists.
|
|
196
|
+
- id: be_unbuilt_warning
|
|
197
|
+
action: verify_context
|
|
198
|
+
condition: "{{be_declared}}"
|
|
199
|
+
require_true: be_built
|
|
200
|
+
on_false: continue
|
|
201
|
+
on_false_message: >
|
|
202
|
+
Service lane '{{be_lane_id}}' is declared at {{be_root}}, which does not exist
|
|
203
|
+
yet, so it is not read: the map is read from the UI lane alone.
|
|
204
|
+
|
|
205
|
+
- id: fe_unbuilt_warning
|
|
206
|
+
action: verify_context
|
|
207
|
+
condition: "{{fe_declared}}"
|
|
208
|
+
require_true: fe_built
|
|
209
|
+
on_false: continue
|
|
210
|
+
on_false_message: >
|
|
211
|
+
Frontend lane '{{fe_lane_id}}' is declared at {{fe_root}}, which does not exist
|
|
212
|
+
yet, so it is not read: features come from the service lane alone.
|
|
213
|
+
|
|
169
214
|
# 2. PASS A + B + C. One deterministic call: every AVAILABLE strategy's
|
|
170
215
|
# clustering is run (cheap — the expensive half is authoring, which does not
|
|
171
216
|
# happen here), the seam overlay is laid over the chosen one, and the
|
|
172
|
-
# proposal is written with its dependency waves.
|
|
217
|
+
# proposal is written with its dependency waves. The request goes to it whole:
|
|
218
|
+
# the script reads a strategy from its first word, and only when that word
|
|
219
|
+
# names one, so focus hints alone force nothing.
|
|
173
220
|
- id: propose
|
|
174
221
|
action: execute_script
|
|
175
222
|
condition: "{{mode}} == propose"
|
|
176
223
|
script: { ref: inventory }
|
|
177
224
|
subcommand: propose
|
|
178
|
-
args: ["--service-root", "{{be_root}}", "--ui-root", "{{fe_root}}", "--strategy", "{{
|
|
225
|
+
args: ["--service-root", "{{be_root}}", "--ui-root", "{{fe_root}}", "--strategy", "{{USER_INPUT}}"]
|
|
179
226
|
outputs:
|
|
180
227
|
- { name: proposal_ok, from: "$.ok" }
|
|
181
228
|
- { name: proposal_md, from: "$.proposal_md" }
|
|
@@ -190,6 +237,7 @@ workflow:
|
|
|
190
237
|
- { name: split_candidates, from: "$.split_candidates" }
|
|
191
238
|
- { name: contexts_ordered, from: "$.contexts_ordered" }
|
|
192
239
|
- { name: strategy_options, from: "$.strategy_options" }
|
|
240
|
+
- { name: forced_option, from: "$.forced_option" }
|
|
193
241
|
- { name: proposal_error, from: "$.error" }
|
|
194
242
|
|
|
195
243
|
# 2b. Substance gate. A scan with nothing to propose is the one outcome that
|
|
@@ -204,26 +252,29 @@ workflow:
|
|
|
204
252
|
on_mismatch: stop
|
|
205
253
|
on_mismatch_message: >
|
|
206
254
|
/appweaver inventory found nothing to propose. {{proposal_error}}
|
|
207
|
-
Check that
|
|
208
|
-
|
|
209
|
-
|
|
255
|
+
Check that each lane in .appweaver/stacks.json names the directory that holds
|
|
256
|
+
its source (/appweaver select-stack re-declares them), then re-run
|
|
257
|
+
/appweaver inventory.
|
|
210
258
|
|
|
211
259
|
# 3. THE STRATEGY PICK. Offered from the probe, each option carrying its own
|
|
212
260
|
# measured numbers — features found, share of source covered, how many
|
|
213
261
|
# one-file candidates it produced. A strategy that would return nothing is
|
|
214
262
|
# not in the list, because choosing it would be the zero-candidate stop
|
|
215
|
-
# arrived at deliberately. One option auto-confirms.
|
|
263
|
+
# arrived at deliberately. One option auto-confirms. A strategy the request
|
|
264
|
+
# named is taken without asking (`forced_option` is its option line, empty when
|
|
265
|
+
# none was named); otherwise the proposed strategy is the first option, so a
|
|
266
|
+
# run that cannot ask takes the proposal.
|
|
216
267
|
- id: pick_strategy
|
|
217
268
|
action: user_select
|
|
218
269
|
condition: "{{mode}} == propose"
|
|
219
270
|
prompt: >
|
|
220
271
|
Pass A found these candidate aggregates. Which evidence should the map be
|
|
221
|
-
built from? (`{{chosen_strategy}}` is proposed: the roots the
|
|
222
|
-
where operations act on them, otherwise the highest coverage, ties
|
|
223
|
-
fewest single-file candidates. Coverage is how much code a strategy
|
|
224
|
-
not whether it placed it right — compare the aggregate counts too.)
|
|
272
|
+
built from? (`{{chosen_strategy}}` is proposed and listed first: the roots the
|
|
273
|
+
code declares where operations act on them, otherwise the highest coverage, ties
|
|
274
|
+
broken by fewest single-file candidates. Coverage is how much code a strategy
|
|
275
|
+
placed, not whether it placed it right — compare the aggregate counts too.)
|
|
225
276
|
options_from_variable: strategy_options
|
|
226
|
-
preselect_from:
|
|
277
|
+
preselect_from: forced_option
|
|
227
278
|
single_option_confirm: true
|
|
228
279
|
outputs:
|
|
229
280
|
- { name: picked, from: selection }
|
|
@@ -112,9 +112,11 @@
|
|
|
112
112
|
# generated, which subtrees are scanned, and what technology the derived rules name.
|
|
113
113
|
# select-stack detects all three from the repo's own files and proposes them, so answering
|
|
114
114
|
# it on an existing codebase is mostly confirmation — but it is a person's confirmation,
|
|
115
|
-
# which is exactly what detection on a legacy repo needs. A
|
|
116
|
-
#
|
|
117
|
-
#
|
|
115
|
+
# which is exactly what detection on a legacy repo needs. A lane can be declared before
|
|
116
|
+
# it is built: a declared lane whose lane root folder does not exist yet is governed as
|
|
117
|
+
# absent for this run, with a warning naming it, and its governance is left to the
|
|
118
|
+
# developer. When no declared lane's folder exists the run stops, rather than producing a
|
|
119
|
+
# scaffold reverse-engineered from nothing.
|
|
118
120
|
#
|
|
119
121
|
# WHICH LANES EXIST is therefore the DECLARATION's answer, and it answers in both
|
|
120
122
|
# directions — a project that declared `(none)` for the UI lane gets no UI half, no
|
|
@@ -149,8 +151,8 @@
|
|
|
149
151
|
# =============================================================================
|
|
150
152
|
|
|
151
153
|
name: aw-spec-onboard
|
|
152
|
-
description: Onboard an existing codebase for brownfield DEVELOPMENT — a deterministic whole-repo scan produces a high-level OKF feature map (folders/concepts) PLUS the project-level governance scaffold (split constitution + guardrails/brf-<domain>/ with its DOMAIN rule files at domain/ + domain-rule-bindings + code-derived TECHNICAL rule files at service/ + tech-rule-bindings + activated domain), all provisional-from-scan. The first context authors that tier; every later context amends it additively from its own code (new rules, principles and map entries — never a rewrite, renumbering or deletion; a contradiction is recorded as a Divergence note), and a tier that does not exist yet, such as a lane declared after an earlier onboard, is authored in full. Naming an already-onboarded context re-runs that governance pass alone. Where the scan finds a frontend lane in the CODE, it also authors that lane's half — constitution.ui.md (UX-*) — and its code-derived rule files at brf-<domain>/frontend/, mapped under `## /aw-spec-ui-constitution`, `## /aw-spec-plan-frontend` and `## /aw-spec-implement-frontend`; a backend-only repo gets none of it. Every rule tier is reverse-engineered from the CODE alone (never a greenfield rule file), evidenced-only, and WIRED per-workflow so the whole forward pipeline AND adopt govern against THIS codebase — never a greenfield fallback. It also reverse-engineers the repo's own technical structure into a project-specific design + delta-design template pair, installed as the project template overrides, and — where the lane exists — the frontend lane's own pair from the UI source. Every authoring step is shaped by a NEUTRAL rev-templates skeleton; no greenfield constitution, rule file or document template is ever placed in context. Accepts an optional concerns list to look for (onboard decides which are actually present). Reads any declared lane, never writes one. No migration content; never modifies source.
|
|
153
|
-
version: 2.
|
|
154
|
+
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/brf-<domain>/ with its DOMAIN rule files at domain/ + domain-rule-bindings + code-derived TECHNICAL rule files at service/ + tech-rule-bindings + activated domain), all provisional-from-scan. The first context authors that tier; every later context amends it additively from its own code (new rules, principles and map entries — never a rewrite, renumbering or deletion; a contradiction is recorded as a Divergence note), and a tier that does not exist yet, such as a lane declared after an earlier onboard, is authored in full. Naming an already-onboarded context re-runs that governance pass alone. Where the scan finds a frontend lane in the CODE, it also authors that lane's half — constitution.ui.md (UX-*) — and its code-derived rule files at brf-<domain>/frontend/, mapped under `## /aw-spec-ui-constitution`, `## /aw-spec-plan-frontend` and `## /aw-spec-implement-frontend`; 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 whose folder exists, never writes one; a lane declared before it is built is governed as absent and its governance left to the developer. No migration content; never modifies source.
|
|
155
|
+
version: 2.5.0
|
|
154
156
|
agent_agnostic: true
|
|
155
157
|
dialect: aw-spec.orchestrator/v1
|
|
156
158
|
|
|
@@ -189,7 +191,7 @@ standards:
|
|
|
189
191
|
vars:
|
|
190
192
|
# The provenance stamp every generated file carries. It names THIS workflow's version,
|
|
191
193
|
# so it moves with `version:` above — one value, never a literal repeated per prompt.
|
|
192
|
-
generated_by: "aw-spec-onboard/2.
|
|
194
|
+
generated_by: "aw-spec-onboard/2.5.0"
|
|
193
195
|
bundle_present: "false" # set by the scan (the bundle holds concepts); reported, gates nothing
|
|
194
196
|
conformant: "false" # OKF conformance-gate driver
|
|
195
197
|
pack_present: "false" # the project tier exists ⇒ repo_gov, so this context AMENDS it
|
|
@@ -241,24 +243,29 @@ workflow:
|
|
|
241
243
|
# what to scan), and what each lane's stack is (so the derived rules name the
|
|
242
244
|
# right technology).
|
|
243
245
|
#
|
|
244
|
-
#
|
|
245
|
-
#
|
|
246
|
-
#
|
|
247
|
-
#
|
|
246
|
+
# This run is about to READ those directories, so it needs at least one to exist.
|
|
247
|
+
# A lane can be declared before it is built, so a lane root folder that does not
|
|
248
|
+
# exist yet is allowed here: that lane is governed as absent below, and the scan
|
|
249
|
+
# reads the lanes whose folders exist. When none exists the run stops rather than
|
|
250
|
+
# producing a governance scaffold reverse-engineered from nothing.
|
|
248
251
|
- id: lane_model
|
|
249
252
|
action: execute_script
|
|
250
253
|
script: { ref: actions }
|
|
251
254
|
subcommand: lane-verify
|
|
252
|
-
args: ["--command", "/appweaver onboard"]
|
|
255
|
+
args: ["--command", "/appweaver onboard", "--allow-missing-root"]
|
|
253
256
|
outputs:
|
|
254
257
|
- { name: lane_model_ok, from: "$.ok" }
|
|
255
258
|
- { name: lane_model_issues, from: "$.message" }
|
|
256
259
|
- { name: lane_kinds, from: "$.kinds" }
|
|
260
|
+
- { name: kinds_on_disk, from: "$.kinds_on_disk" }
|
|
261
|
+
- { name: missing_roots, from: "$.missing_roots" }
|
|
257
262
|
- { name: be_declared, from: "$.backend_declared" }
|
|
263
|
+
- { name: be_built, from: "$.backend_root_exists" }
|
|
258
264
|
- { name: be_lane_id, from: "$.backend_lane_id" }
|
|
259
265
|
- { name: be_profile, from: "$.backend_profile" }
|
|
260
266
|
- { name: be_root, from: "$.backend_source_path" }
|
|
261
267
|
- { name: fe_declared, from: "$.frontend_declared" }
|
|
268
|
+
- { name: fe_built, from: "$.frontend_root_exists" }
|
|
262
269
|
- { name: fe_lane_id, from: "$.frontend_lane_id" }
|
|
263
270
|
- { name: fe_profile, from: "$.frontend_profile" }
|
|
264
271
|
- { name: fe_root, from: "$.frontend_source_path" }
|
|
@@ -283,13 +290,24 @@ workflow:
|
|
|
283
290
|
nor a UI lane, so onboard has no source to reverse-engineer. Re-run
|
|
284
291
|
/appweaver select-stack and declare at least one lane.
|
|
285
292
|
|
|
293
|
+
- id: lane_built_gate
|
|
294
|
+
action: verify_context
|
|
295
|
+
require_non_empty: kinds_on_disk
|
|
296
|
+
on_empty: stop
|
|
297
|
+
on_empty_message: >
|
|
298
|
+
/appweaver onboard has no code to reverse-engineer: {{missing_roots}}
|
|
299
|
+
onboard derives governance from the code of the lanes whose folders exist, and
|
|
300
|
+
no declared lane has one yet.
|
|
301
|
+
|
|
286
302
|
# 1. DETERMINISTIC scan of the current codebase → JSON substrate (files, churn,
|
|
287
303
|
# categories, aggregate_signals = candidate feature roots), and reports whether
|
|
288
304
|
# a bundle already holds curation.
|
|
289
305
|
#
|
|
290
306
|
# SCOPED BY THE DECLARATION. Backend signals come from outside the UI lane's
|
|
291
307
|
# subtree (and inside the service lane's); frontend signals come from the UI
|
|
292
|
-
# lane's subtree alone.
|
|
308
|
+
# lane's subtree alone. A project with a UI lane and no service lane has no backend
|
|
309
|
+
# signals: its candidates are the API resources the UI calls, the same reading
|
|
310
|
+
# inventory proposed the map from. This substrate is inlined verbatim into every agent
|
|
293
311
|
# request this run makes, so an unscoped scan puts the whole frontend file list in
|
|
294
312
|
# front of the step deriving the SERVICE rules and every backend aggregate in front
|
|
295
313
|
# of the steps deriving the UI's — while each prompt tells the model to ignore what
|
|
@@ -314,11 +332,13 @@ workflow:
|
|
|
314
332
|
- { name: bundle_dir, from: "$.bundle_dir" }
|
|
315
333
|
- { name: bundle_present, from: "$.bundle_present" }
|
|
316
334
|
- { name: bundle_md_count, from: "$.bundle_md_count" }
|
|
317
|
-
# The frontend lane, as the CODE evidences it. `
|
|
335
|
+
# The frontend lane, as the CODE evidences it. `frontend_evidenced` is true only
|
|
318
336
|
# where a candidate root reached lane strength (a frontend build config, or a
|
|
319
337
|
# real set of component/view files) — loose scripts and stylesheets under a
|
|
320
|
-
# wwwroot/ are reported in the substrate but are NOT a lane.
|
|
321
|
-
|
|
338
|
+
# wwwroot/ are reported in the substrate but are NOT a lane. It is the code's
|
|
339
|
+
# answer, kept apart from `frontend_present` (the UI rule tier exists, from
|
|
340
|
+
# pack_setup); which lanes this run governs is the declaration's answer, ui_lane.
|
|
341
|
+
- { name: frontend_evidenced, from: "$.frontend_present" }
|
|
322
342
|
- { name: frontend_separable, from: "$.frontend_separable" }
|
|
323
343
|
- { name: frontend_roots, from: "$.frontend_roots" }
|
|
324
344
|
- { name: frontend_root_count, from: "$.frontend_root_count" }
|
|
@@ -335,13 +355,6 @@ workflow:
|
|
|
335
355
|
- { name: scoped_service_root, from: "$.declared_service_root" }
|
|
336
356
|
- { name: scoped_ui_root, from: "$.declared_ui_root" }
|
|
337
357
|
|
|
338
|
-
# 1b. Substance gate: no candidate features → nothing to map.
|
|
339
|
-
- id: require_aggregates
|
|
340
|
-
action: verify_context
|
|
341
|
-
require_true: aggregate_count
|
|
342
|
-
on_false: stop
|
|
343
|
-
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."
|
|
344
|
-
|
|
345
358
|
# 1c. WHICH BOUNDED CONTEXT, AND IS IT THIS ONE'S TURN. onboard runs once per
|
|
346
359
|
# context, so before anything is written it reads the map inventory
|
|
347
360
|
# produced and asks four questions: is this a context the map knows, what
|
|
@@ -494,13 +507,15 @@ workflow:
|
|
|
494
507
|
# The declaration selects the subtree; it never supplies a word of the governance.
|
|
495
508
|
# No service lane ⇒ the technical lint loop has nothing to check, so its guard is
|
|
496
509
|
# satisfied rather than left at its "not yet verified" default; a declared lane
|
|
497
|
-
# restores it, because that half does get authored and does get linted.
|
|
510
|
+
# restores it, because that half does get authored and does get linted. A lane is
|
|
511
|
+
# governed when it is declared AND its lane root folder exists: one declared before it
|
|
512
|
+
# is built has no code to reverse-engineer, so it is governed as absent.
|
|
498
513
|
- id: svc_lane_absent
|
|
499
514
|
action: set
|
|
500
515
|
vars: { svc_lane: "false", technical_ok: "true", setup_tech_flag: "--no-technical" }
|
|
501
516
|
- id: svc_lane_declared
|
|
502
517
|
action: set
|
|
503
|
-
condition: "{{
|
|
518
|
+
condition: "{{be_built}}"
|
|
504
519
|
vars: { svc_lane: "true", technical_ok: "false", setup_tech_flag: "" }
|
|
505
520
|
|
|
506
521
|
# A repo with no service lane. Rare in brownfield and real — a static site, a
|
|
@@ -510,7 +525,7 @@ workflow:
|
|
|
510
525
|
# someone to notice that guardrails/<p>/service/ is empty.
|
|
511
526
|
- id: svc_lane_warning
|
|
512
527
|
action: verify_context
|
|
513
|
-
require_true:
|
|
528
|
+
require_true: be_declared
|
|
514
529
|
on_false: continue
|
|
515
530
|
on_false_message: >
|
|
516
531
|
No service lane in .appweaver/stacks.json — skipping the TECHNICAL constitution
|
|
@@ -521,24 +536,62 @@ workflow:
|
|
|
521
536
|
this repo does have backend source, run /appweaver select-stack, declare it and
|
|
522
537
|
re-run onboard.
|
|
523
538
|
|
|
539
|
+
# A service lane declared before it is built — a new service planned beside a front end
|
|
540
|
+
# that exists. Its governance is the developer's to provide before the forward
|
|
541
|
+
# pipeline builds it; this run authors none of it.
|
|
542
|
+
- id: svc_lane_unbuilt_warning
|
|
543
|
+
action: verify_context
|
|
544
|
+
condition: "{{be_declared}}"
|
|
545
|
+
require_true: be_built
|
|
546
|
+
on_false: continue
|
|
547
|
+
on_false_message: >
|
|
548
|
+
Service lane '{{be_lane_id}}' ({{be_profile}}) is declared at {{be_root}}, which
|
|
549
|
+
does not exist yet, so there is no service code to reverse-engineer. This run
|
|
550
|
+
authors none of the service lane's governance — the TECHNICAL constitution half,
|
|
551
|
+
the service rule set and the service design/delta-design template overrides.
|
|
552
|
+
Provide them before building the lane through the forward pipeline. Once the lane
|
|
553
|
+
has code, naming an onboarded context (/appweaver onboard <Context>) reverse-engineers
|
|
554
|
+
them from it instead.
|
|
555
|
+
|
|
524
556
|
- id: ui_lane_absent
|
|
525
557
|
action: set
|
|
526
558
|
vars:
|
|
527
559
|
ui_lane: "false"
|
|
528
560
|
ui_evidence: ""
|
|
529
561
|
ui_declaration_note: "no frontend lane is declared in .appweaver/stacks.json — this repo is governed as backend-only"
|
|
530
|
-
- id:
|
|
562
|
+
- id: ui_lane_unbuilt
|
|
531
563
|
action: set
|
|
532
564
|
condition: "{{fe_declared}}"
|
|
565
|
+
vars:
|
|
566
|
+
ui_declaration_note: "lane '{{fe_lane_id}}' ({{fe_profile}}) is declared at {{fe_root}}, which does not exist yet — no UI governance was authored for it"
|
|
567
|
+
- id: ui_lane_declared
|
|
568
|
+
action: set
|
|
569
|
+
condition: "{{fe_built}}"
|
|
533
570
|
vars:
|
|
534
571
|
ui_lane: "true"
|
|
535
572
|
ui_evidence: "lane '{{fe_lane_id}}' ({{fe_profile}}) is declared at the lane root folder {{fe_root}}; the scan found UI source there — {{frontend_roots}}"
|
|
536
573
|
ui_declaration_note: "lane '{{fe_lane_id}}' ({{fe_profile}}) at {{fe_root}} — the declared lane root folder this run reverse-engineered the UI governance out of"
|
|
537
574
|
|
|
575
|
+
# A frontend lane declared before it is built — a new front end planned beside a
|
|
576
|
+
# service that exists. Its governance is the developer's to provide before the forward
|
|
577
|
+
# pipeline builds it; this run authors none of it.
|
|
578
|
+
- id: ui_lane_unbuilt_warning
|
|
579
|
+
action: verify_context
|
|
580
|
+
condition: "{{fe_declared}}"
|
|
581
|
+
require_true: fe_built
|
|
582
|
+
on_false: continue
|
|
583
|
+
on_false_message: >
|
|
584
|
+
Frontend lane '{{fe_lane_id}}' ({{fe_profile}}) is declared at {{fe_root}}, which
|
|
585
|
+
does not exist yet, so there is no UI code to reverse-engineer. This run authors
|
|
586
|
+
none of the frontend lane's governance — constitution.ui.md, the frontend rule set
|
|
587
|
+
and the UI design/delta-design template overrides. Provide them before building the
|
|
588
|
+
lane through the forward pipeline. Once the lane has code, naming an onboarded
|
|
589
|
+
context (/appweaver onboard <Context>) reverse-engineers them from it instead.
|
|
590
|
+
|
|
538
591
|
# A declared UI lane whose lane root folder holds nothing a scan recognises as UI. The
|
|
539
|
-
# path exists — lane
|
|
540
|
-
# broken declaration, it is an empty one: a lane scaffolded but not yet built, or
|
|
541
|
-
# lane root folder one directory too high. Announce and continue rather than stop: the
|
|
592
|
+
# path exists — a lane whose folder does not is governed as absent above — so this is
|
|
593
|
+
# not a broken declaration, it is an empty one: a lane scaffolded but not yet built, or
|
|
594
|
+
# a lane root folder one directory too high. Announce and continue rather than stop: the
|
|
542
595
|
# declaration is a person's statement and is left exactly as it stands, but the UI
|
|
543
596
|
# governance below will be thin, and it is better to say why now than to let someone
|
|
544
597
|
# discover a UX base derived from an empty directory.
|
|
@@ -706,6 +759,9 @@ workflow:
|
|
|
706
759
|
confirm those against what the file actually is and move or drop one it got wrong. Keep the key and leave it EMPTY where the
|
|
707
760
|
aggregate has no UI (and on a backend-only repo, where every concept has none);
|
|
708
761
|
never fold these paths into `source_files`, which stays the service surface.
|
|
762
|
+
Where the aggregate signals' `strategy` is `ui` (a project with no service
|
|
763
|
+
lane), every file a signal lists is the UI lane's, its `api_files` included: list
|
|
764
|
+
them all under `ui_source_files` and leave `source_files` empty.
|
|
709
765
|
- `aggregates/index.md` — the BOUNDED-CONTEXT / feature map (no frontmatter beyond
|
|
710
766
|
OKF index rules). Group the links under a `## <BoundedContext>` heading per
|
|
711
767
|
context, so the file shows which aggregates belong to which context rather than one
|
|
@@ -2249,6 +2305,16 @@ workflow:
|
|
|
2249
2305
|
signature form + the ports/contracts. Keep exactly one subsection whose heading
|
|
2250
2306
|
contains the word "Integration" (the External Integrations table — one port/adapter row
|
|
2251
2307
|
per IC-): aw-xref matches it by keyword, so it is pinned regardless of layout.
|
|
2308
|
+
- THE PUBLISHED SURFACE IS A PINNED FORM. In the §2 axis this project publishes its
|
|
2309
|
+
endpoints from (titled with the project's own name for it), keep the skeleton's
|
|
2310
|
+
endpoint block exactly — the heading `#### `[VERB] [/route]` — [purpose] · Serves …`,
|
|
2311
|
+
then **Operation id**, Auth, Request, Success, the Errors table and Maps to — and the
|
|
2312
|
+
`#### Requests from the frontend lane` table after the blocks. The contract scripts
|
|
2313
|
+
read exactly this form: the API draft is written from the headings and the request
|
|
2314
|
+
ledger between the lanes reads the operation ids and the table, so endpoints listed
|
|
2315
|
+
in a table instead leave both empty. Keep the Operation id comment: an endpoint the
|
|
2316
|
+
code already serves keeps the id it publishes, `—` with a §5 DA-n where it publishes
|
|
2317
|
+
none, never an invented one. Omit both only where the code publishes no endpoint.
|
|
2252
2318
|
- §3 Cross-Cutting Concerns — one row per concern THIS project's governance carries, read
|
|
2253
2319
|
from the technical constitution (Serves = a spec id or a §5 DA-n). Do not import a
|
|
2254
2320
|
standard concern list the constitution does not evidence.
|
|
@@ -2307,9 +2373,14 @@ workflow:
|
|
|
2307
2373
|
the generated master template. Never name a layering — neither one you know nor one the
|
|
2308
2374
|
master did not derive.
|
|
2309
2375
|
- CARRY OVER the neutral parts of rev-templates/delta-design-template.skeleton.md (in
|
|
2310
|
-
context): Change summary,
|
|
2311
|
-
|
|
2312
|
-
|
|
2376
|
+
context): Change summary, Model changes this plan realises, Depends on, Cross-section
|
|
2377
|
+
impact, Contract deltas for the frontend lane, Other open deltas, Regression targets,
|
|
2378
|
+
New assumptions/deviations (DA-n / WA-n), On merge — word for word: finalize-delta
|
|
2379
|
+
merges the spec and the model, never this plan, which `plan main` re-derives. Keep
|
|
2380
|
+
the contract table's Operation id and Change columns and its added / changed /
|
|
2381
|
+
removed values: analyze-plan-delta reads them to warn when a change alters or
|
|
2382
|
+
removes an operation the frontend binds to. Omit that section only where the code
|
|
2383
|
+
has no frontend lane. Keep behaviour technology-agnostic (signatures +
|
|
2313
2384
|
contracts, no code); a shared element is MODIFIED in place, never duplicated; every
|
|
2314
2385
|
changed element serves a spec id.
|
|
2315
2386
|
- This aligns with the delta-plan module, which classifies "per the master's OWN
|
|
@@ -2656,4 +2727,4 @@ outputs:
|
|
|
2656
2727
|
amended_domain_files: "{{amended_domain_files}}"
|
|
2657
2728
|
amended_service_files: "{{amended_service_files}}"
|
|
2658
2729
|
amended_ui_files: "{{amended_ui_files}}"
|
|
2659
|
-
next: "Onboarded bounded context {{bc}} ({{bc_feature_count}} feature(s): {{bc_features}}). Its aggregate concepts ({{bc_aggregates}}) are in {{bundle_dir}}, each keyed `bounded_context: {{bc}}` and listing the features that act on it — the bundle is the project's knowledge, one concept per aggregate, never one per feature — and its specs tree now exists at {{bc_dir}}/ with a directory per feature ({{feature_dirs}}) — EMPTY on purpose: the directory says the feature is known, and the documents that describe it are written per feature by /appweaver adopt and per context by /appweaver specify. {{bc}} is now the ACTIVE bounded context (.appweaver/context.json), so /appweaver select-feature lists exactly these features and nothing from a neighbouring context; switch with /appweaver select-bounded-context. ONBOARD RUNS ONCE PER CONTEXT: contexts already done — {{onboarded_contexts}}; still open — {{remaining_contexts}}; the order the map gives is {{contexts_ordered}}. Run /appweaver onboard <NextContext> for each remaining one, or with no argument to take the next one automatically. GOVERNANCE — {{gov_mode}}. The project tier is the PROVISIONAL governance scaffold — the split constitution, the domain rule set at guardrails/{{domain_slug}}/domain/*.domain.md + domain-rule-bindings.md, each declared LANE's rule set and constitution half, the activated domain {{active_domain}}, and the code-derived design / delta-design / domain-model template overrides in .appweaver/templates/overrides/. The first context authors it; every later context AMENDS it from its own code, additively — rules, principles and map entries its code evidences, never a rewrite, renumbering or deletion of what an earlier context wrote — and a lane tier that did not exist yet is authored in full. Files this run amended — domain: {{amended_domain_files}}; service: {{amended_service_files}}; frontend: {{amended_ui_files}}. Search them for `Divergence ({{bc}})`: each marks a rule this context's code contradicts, left as written for you to decide with /appweaver constitution, which is also how you amend the tier by hand. The templates are written once per lane and never amended. To re-run this governance pass later — after declaring a lane with /appweaver select-stack, say — name an onboarded context: /appweaver onboard <Context>. ONE HALF AND ONE RULE SET PER LANE: service_lane / ui_lane report which lanes .appweaver/stacks.json
|
|
2730
|
+
next: "Onboarded bounded context {{bc}} ({{bc_feature_count}} feature(s): {{bc_features}}). Its aggregate concepts ({{bc_aggregates}}) are in {{bundle_dir}}, each keyed `bounded_context: {{bc}}` and listing the features that act on it — the bundle is the project's knowledge, one concept per aggregate, never one per feature — and its specs tree now exists at {{bc_dir}}/ with a directory per feature ({{feature_dirs}}) — EMPTY on purpose: the directory says the feature is known, and the documents that describe it are written per feature by /appweaver adopt and per context by /appweaver specify. {{bc}} is now the ACTIVE bounded context (.appweaver/context.json), so /appweaver select-feature lists exactly these features and nothing from a neighbouring context; switch with /appweaver select-bounded-context. ONBOARD RUNS ONCE PER CONTEXT: contexts already done — {{onboarded_contexts}}; still open — {{remaining_contexts}}; the order the map gives is {{contexts_ordered}}. Run /appweaver onboard <NextContext> for each remaining one, or with no argument to take the next one automatically. GOVERNANCE — {{gov_mode}}. The project tier is the PROVISIONAL governance scaffold — the split constitution, the domain rule set at guardrails/{{domain_slug}}/domain/*.domain.md + domain-rule-bindings.md, each declared LANE's rule set and constitution half, the activated domain {{active_domain}}, and the code-derived design / delta-design / domain-model template overrides in .appweaver/templates/overrides/. The first context authors it; every later context AMENDS it from its own code, additively — rules, principles and map entries its code evidences, never a rewrite, renumbering or deletion of what an earlier context wrote — and a lane tier that did not exist yet is authored in full. Files this run amended — domain: {{amended_domain_files}}; service: {{amended_service_files}}; frontend: {{amended_ui_files}}. Search them for `Divergence ({{bc}})`: each marks a rule this context's code contradicts, left as written for you to decide with /appweaver constitution, which is also how you amend the tier by hand. The templates are written once per lane and never amended. To re-run this governance pass later — after declaring a lane with /appweaver select-stack, say — name an onboarded context: /appweaver onboard <Context>. ONE HALF AND ONE RULE SET PER LANE: service_lane / ui_lane report which lanes this run governed — each lane .appweaver/stacks.json declares whose lane root folder exists. A lane declared (none) in select-stack gets none of it, which is the correct outcome and not an omission, and so does a lane whose folder does not exist yet: its governance is yours to provide before the forward pipeline builds it. LANE DECLARATION: read, never written — select-stack is its sole writer, and this run scanned the lane root folders it named (scanned_service_root / scanned_ui_root); scanned_backend_files / scanned_ui_files report each. ui_source_evidence_found false means the declared lane root folder of the UI lane held nothing a scan recognises as UI, so its governance is thin — move the lane root folder with /appweaver select-stack and re-run. The build/test/run commands on each lane are that PROFILE's defaults and may not match a legacy layout — review them. Because the domain is activated, resolve-domain + resolve-tech route the WHOLE forward pipeline to these code-derived rules — never another project's rules as a fallback. THE BOUNDARIES CAME FROM THE MAP, not from this run: /appweaver inventory proposed them and you confirmed them in specs/proposed-inventory.md. To change a boundary, edit that file and run /appweaver inventory apply — a context whose concepts already exist is not re-mapped; naming it re-runs only its governance pass. Develop an EXISTING feature just-in-time: /appweaver adopt <Feature> reverse-engineers its spec.md + backend-plan.md + source-map.md and deepens the OKF concept of the aggregate it acts on. Develop a NEW feature straight through the forward pipeline — /appweaver select-feature FIRST (specify and every stage after it read the active feature and STOP without one), then specify → plan → analyze-plan → implement → build → analyze-slice → run. Then drive every change through the CR delta loop (/appweaver specify → plan → analyze-plan-delta → implement → build → analyze-slice-delta → finalize-delta → analyze-slice → close-delta), and re-derive the master plans after it with /appweaver plan main → analyze-plan — finalize-delta merges a change into spec.md and domain-model.md, never into the plans. If a validation_ok is false, its constitution half needs a manual touch (see its Sync Impact Report)."
|
|
@@ -117,7 +117,7 @@
|
|
|
117
117
|
|
|
118
118
|
name: aw-spec-plan
|
|
119
119
|
description: "Author the feature's lane plans from the spec and the bounded context's domain model — backend-plan.md when a backend lane is declared, frontend-plan.md when a frontend lane is, both when both are. Lanes come from .appweaver/stacks.json, so one command covers backend-only, frontend-only and full-stack projects; the former separate design-ui command is folded in. It ASKS what it is planning, the way implement asks what it is building: the master (`main`), one of the OPEN CHANGES, or a new plan-only change for a refactor with no spec delta — the argument doubles as the answer, and the menu appears only once a master exists, so a first run bootstraps with no prompt. `main` on a feature that already has masters RE-DERIVES them from the merged spec.md + domain-model.md — the operation finalize-delta's contract assumes when it merges a change's spec and model halves and no lane plan — and is confirmed before it rewrites anything. A change instead gets delta-backend-plan.md / delta-frontend-plan.md inside changes/<CR-id>/ while the masters stay untouched, written against the effective model (the master model, the change's own model delta, and the pending model deltas of LOWER waves, which are its predecessors) and against the feature's real source files from its OKF concept. Master authoring is template-driven: the kit's templates by default, or the code-derived as-built structure when onboard installed an override. Authoring only — a master gates at analyze-plan; a change ships through the CR chain."
|
|
120
|
-
version: 5.5.
|
|
120
|
+
version: 5.5.1
|
|
121
121
|
agent_agnostic: true
|
|
122
122
|
dialect: aw-spec.orchestrator/v1
|
|
123
123
|
|
|
@@ -880,7 +880,11 @@ workflow:
|
|
|
880
880
|
- NAME EVERY ENDPOINT with its route, verb and operation id — its name in the
|
|
881
881
|
service's published API document, unique across the service. Where the code
|
|
882
882
|
already gives the endpoint one, record THAT id exactly as the code spells it; the
|
|
883
|
-
frontend plan cites it and implement finds the endpoint by it.
|
|
883
|
+
frontend plan cites it and implement finds the endpoint by it. An endpoint the code
|
|
884
|
+
already serves under no id keeps `—`, with a §5 DA-n saying so — never an invented
|
|
885
|
+
id. Write each endpoint as the template's endpoint block — the heading
|
|
886
|
+
`#### `VERB /route` — …` with its **Operation id** field — never as a row in a table
|
|
887
|
+
of endpoints: the API draft and the request ledger between the lanes read that form.
|
|
884
888
|
- ANSWER THE FRONTEND LANE'S CONTRACT REQUESTS. Still open in the frontend plan's
|
|
885
889
|
"Contract deltas needed" table: {{req_backend_text}}. Answer each one in a
|
|
886
890
|
"Requests from the frontend lane" table beside this feature's endpoints (| Request
|
|
@@ -16,7 +16,10 @@
|
|
|
16
16
|
# still READ the other lane where they need it: a frontend plan binds to the backend
|
|
17
17
|
# plan's published surface, which the backend developer owns. specify, finalize-delta and
|
|
18
18
|
# close-delta do NOT follow it: the spec is written whole, from its rules and standards,
|
|
19
|
-
# and a change merges and closes with whatever its lanes have delivered.
|
|
19
|
+
# and a change merges and closes with whatever its lanes have delivered. Brownfield adopt
|
|
20
|
+
# does not follow it either: it reverses a feature once, every half its code has, because
|
|
21
|
+
# it cannot run a second time for the other lane, so the other lane's developer finds
|
|
22
|
+
# their plan already written.
|
|
20
23
|
#
|
|
21
24
|
# THE OPTIONS COME FROM stacks.json. Both lanes declared → backend, frontend and both.
|
|
22
25
|
# One lane declared → that lane only, picked without a question (there is nothing to
|
|
@@ -32,8 +35,8 @@
|
|
|
32
35
|
# =============================================================================
|
|
33
36
|
|
|
34
37
|
name: aw-spec-select-lane
|
|
35
|
-
description: Choose the lane this developer works on — backend, frontend or both — and store it in .appweaver/lane.json, which is not committed, so each developer keeps their own. The options come from the stacks declared in .appweaver/stacks.json, all three when both lanes are declared and only the declared one otherwise. plan, analyze-plan, implement, build and analyze-slice then write only that lane while still reading the other; specify, finalize-delta
|
|
36
|
-
version: 1.0.
|
|
38
|
+
description: Choose the lane this developer works on — backend, frontend or both — and store it in .appweaver/lane.json, which is not committed, so each developer keeps their own. The options come from the stacks declared in .appweaver/stacks.json, all three when both lanes are declared and only the declared one otherwise. plan, analyze-plan, implement, build and analyze-slice then write only that lane while still reading the other; specify, finalize-delta, close-delta and brownfield adopt do not follow it. select-stack writes the default (every declared lane); run this to narrow it.
|
|
39
|
+
version: 1.0.1
|
|
37
40
|
agent_agnostic: true
|
|
38
41
|
dialect: aw-spec.orchestrator/v1
|
|
39
42
|
|
|
@@ -100,5 +103,5 @@ outputs:
|
|
|
100
103
|
working_lane: "{{working_lane}}"
|
|
101
104
|
working_kinds: "{{working_kinds}}"
|
|
102
105
|
lane_file: "{{lane_file}}"
|
|
103
|
-
note: "Working lane `{{working_lane}}` stored in {{lane_file}}. The file is not committed — it is this developer's choice, and another developer on the same repository keeps their own. From now on plan, analyze-plan, implement, build and analyze-slice write only the working lane: they plan it, gate it with its own receipt, generate it, compile it and test it. They still READ the other lane where they need it — a frontend plan binds to the operation ids the backend plan publishes. specify writes the whole spec whatever lane is chosen, and finalize-delta and close-delta merge and close a change with whatever its lanes have delivered. Re-running /appweaver select-stack resets the working lane to every declared lane."
|
|
106
|
+
note: "Working lane `{{working_lane}}` stored in {{lane_file}}. The file is not committed — it is this developer's choice, and another developer on the same repository keeps their own. From now on plan, analyze-plan, implement, build and analyze-slice write only the working lane: they plan it, gate it with its own receipt, generate it, compile it and test it. They still READ the other lane where they need it — a frontend plan binds to the operation ids the backend plan publishes. specify writes the whole spec whatever lane is chosen, and finalize-delta and close-delta merge and close a change with whatever its lanes have delivered. Brownfield adopt reverses a feature once, every half its code has, whatever lane is chosen, so the other lane's developer finds their plan already written. Re-running /appweaver select-stack resets the working lane to every declared lane."
|
|
104
107
|
next: "Run the lane's flow on the active feature: /appweaver plan → analyze-plan → implement → build → analyze-slice. Switch lanes any time with /appweaver select-lane backend | frontend | both."
|
|
@@ -3,17 +3,19 @@
|
|
|
3
3
|
# The brownfield inventory logic lives ONCE in ../python/aw-inventory.py (a
|
|
4
4
|
# faithful cross-platform port of Reference/okf-inventory.sh + aggregate-root
|
|
5
5
|
# signals). This wrapper exists only so the orchestrator's execute_script,
|
|
6
|
-
# which dispatches sh:/ps1: variants, can invoke it.
|
|
7
|
-
#
|
|
6
|
+
# which dispatches sh:/ps1: variants, can invoke it. Args pass through, each flag
|
|
7
|
+
# joined to its value (see below).
|
|
8
8
|
#
|
|
9
9
|
# aw-inventory.ps1 scan [--root <dir>] [--out <path>] [--bundle <dir>] [--config <yml>]
|
|
10
10
|
# [--service-root <p>] [--ui-root <p>] (the declared lane paths:
|
|
11
11
|
# backend signals come from outside the UI subtree, frontend
|
|
12
12
|
# signals from inside it, so neither carries the other's files)
|
|
13
13
|
# aw-inventory.ps1 propose [--root <dir>] [--service-root <p>] [--ui-root <p>]
|
|
14
|
-
# [--strategy structure|reference|persistence]
|
|
14
|
+
# [--strategy domain|structure|reference|persistence|ui]
|
|
15
|
+
# [--out <md>] [--map <json>]
|
|
15
16
|
# (Pass A+B+C: writes the editable specs/proposed-inventory.md
|
|
16
|
-
# and the machine map onboard reads
|
|
17
|
+
# and the machine map onboard reads; with a UI lane and no
|
|
18
|
+
# service lane the map is read from the UI lane, strategy `ui`)
|
|
17
19
|
# aw-inventory.ps1 apply [--root <dir>] [--proposal <md>] [--map <json>]
|
|
18
20
|
# (validates the operator's edits to the proposal and
|
|
19
21
|
# regenerates the machine map; reports the row it cannot resolve)
|
|
@@ -28,5 +30,18 @@
|
|
|
28
30
|
# aw-inventory.ps1 validate --bundle <dir> [--repo-root <dir>]
|
|
29
31
|
$ErrorActionPreference = "Stop"
|
|
30
32
|
$core = Join-Path $PSScriptRoot "..\python\aw-inventory.py"
|
|
31
|
-
|
|
33
|
+
# Each value travels to python as ONE `--flag=value` argument. Windows PowerShell 5.1, and
|
|
34
|
+
# pwsh before 7.3, drop an empty argument when calling a program, which would leave a flag
|
|
35
|
+
# such as --service-root (empty in a project with no service lane) or --strategy (empty on
|
|
36
|
+
# a first run) with the next flag as its value, or with none. Every flag here takes a value.
|
|
37
|
+
$fwd = @()
|
|
38
|
+
for ($i = 0; $i -lt $args.Count; $i++) {
|
|
39
|
+
$a = "$($args[$i])"
|
|
40
|
+
if ($a.StartsWith('--') -and -not $a.Contains('=') -and $i + 1 -lt $args.Count) {
|
|
41
|
+
$fwd += ($a + '=' + $args[++$i])
|
|
42
|
+
} else {
|
|
43
|
+
$fwd += $a
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
& python3 $core @fwd
|
|
32
47
|
exit $LASTEXITCODE
|