aw-spec-cli 0.1.16 → 0.1.18
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 +18 -18
- package/assets/.appweaver/ORCH-DIALECT.md +1 -3
- package/assets/.appweaver/RULE-PARTITION.md +29 -13
- package/assets/.appweaver/STACK-PROFILES.md +10 -9
- package/assets/.appweaver/orchestrator/.state/smoke.state.json +32 -0
- package/assets/.appweaver/orchestrator/AGENT-PROFILE.md +4 -1
- package/assets/.appweaver/orchestrator/modules/delta-plan.orch.yaml +251 -0
- package/assets/.appweaver/orchestrator/modules/delta-spec.orch.yaml +104 -35
- package/assets/.appweaver/orchestrator/orchestrator.py +5 -4
- package/assets/.appweaver/orchestrator/rev-templates/delta-design-template.skeleton.md +94 -36
- package/assets/.appweaver/orchestrator/rev-templates/design-template.skeleton.md +1 -1
- package/assets/.appweaver/orchestrator/rev-templates/domain-model-template.skeleton.md +115 -0
- package/assets/.appweaver/orchestrator/rev-templates/domain-rule-bindings.skeleton.md +2 -9
- package/assets/.appweaver/orchestrator/rev-templates/tech-rule-bindings.skeleton.md +16 -40
- package/assets/.appweaver/orchestrator/rev-templates/ui-delta-design-template.skeleton.md +38 -17
- package/assets/.appweaver/orchestrator/rev-templates/ui-design-template.skeleton.md +8 -8
- package/assets/.appweaver/orchestrator/workflows/aw-spec-adopt.orch.yaml +10 -11
- package/assets/.appweaver/orchestrator/workflows/aw-spec-analyze-plan-delta.orch.yaml +673 -0
- package/assets/.appweaver/orchestrator/workflows/aw-spec-analyze-plan.orch.yaml +535 -0
- package/assets/.appweaver/orchestrator/workflows/aw-spec-analyze-slice-delta.orch.yaml +643 -0
- package/assets/.appweaver/orchestrator/workflows/aw-spec-analyze-slice.orch.yaml +84 -701
- package/assets/.appweaver/orchestrator/workflows/aw-spec-build.orch.yaml +4 -4
- package/assets/.appweaver/orchestrator/workflows/aw-spec-characterize.orch.yaml +7 -7
- package/assets/.appweaver/orchestrator/workflows/aw-spec-close-delta.orch.yaml +16 -14
- package/assets/.appweaver/orchestrator/workflows/aw-spec-constitution.orch.yaml +2 -2
- package/assets/.appweaver/orchestrator/workflows/aw-spec-finalize-delta.orch.yaml +243 -144
- package/assets/.appweaver/orchestrator/workflows/aw-spec-implement.orch.yaml +877 -578
- package/assets/.appweaver/orchestrator/workflows/aw-spec-inventory.orch.yaml +4 -4
- package/assets/.appweaver/orchestrator/workflows/aw-spec-onboard.orch.yaml +32 -91
- package/assets/.appweaver/orchestrator/workflows/aw-spec-parity.orch.yaml +2 -2
- package/assets/.appweaver/orchestrator/workflows/aw-spec-plan.orch.yaml +836 -514
- package/assets/.appweaver/orchestrator/workflows/aw-spec-run.orch.yaml +2 -2
- package/assets/.appweaver/orchestrator/workflows/aw-spec-select-bounded-context.orch.yaml +132 -0
- package/assets/.appweaver/orchestrator/workflows/aw-spec-select-feature.orch.yaml +38 -5
- package/assets/.appweaver/orchestrator/workflows/aw-spec-select-stack.orch.yaml +3 -3
- package/assets/.appweaver/orchestrator/workflows/aw-spec-specify.orch.yaml +271 -979
- package/assets/.appweaver/scripts/bash/aw-spec-actions.sh +1085 -3385
- package/assets/.appweaver/scripts/bash/aw-xref.sh +1 -2
- package/assets/.appweaver/scripts/bash/common.sh +47 -0
- package/assets/.appweaver/scripts/powershell/aw-spec-actions.ps1 +914 -3220
- package/assets/.appweaver/scripts/powershell/aw-xref.ps1 +1 -2
- package/assets/.appweaver/scripts/python/aw-payload-parity.py +19 -3
- package/assets/.appweaver/scripts/python/aw-stack.py +6 -2
- package/assets/.appweaver/scripts/python/aw-xref.py +86 -350
- package/assets/.appweaver/templates/constitution-ui-template.md +1 -1
- package/assets/.appweaver/templates/delta-design-template.md +120 -30
- package/assets/.appweaver/templates/delta-domain-model-template.md +81 -0
- package/assets/.appweaver/templates/delta-spec-template.md +43 -17
- package/assets/.appweaver/templates/design-template.md +68 -98
- package/assets/.appweaver/templates/domain-model-template.md +130 -0
- package/assets/.appweaver/templates/okf-concept-template.md +2 -2
- package/assets/.appweaver/templates/source-map-template.md +3 -3
- package/assets/.appweaver/templates/spec-template.md +100 -122
- package/assets/.appweaver/templates/ui-delta-design-template.md +159 -0
- package/assets/.appweaver/templates/ui-design-template.md +46 -75
- package/assets/guardrails/projects/dotnet-default-project/domain-rule-bindings.md +7 -18
- package/assets/guardrails/projects/dotnet-default-project/tech-rule-bindings.md +34 -39
- package/assets/guardrails/requirement-spec.txt +2 -2
- package/assets/guardrails/technology/dotnet-webapi/testing.md +1 -1
- package/package.json +1 -1
- package/assets/.appweaver/orchestrator/modules/delta-design.orch.yaml +0 -105
- package/assets/.appweaver/orchestrator/modules/spec-state-gate.orch.yaml +0 -87
- package/assets/.appweaver/orchestrator/workflows/aw-spec-analyze-delta-design.orch.yaml +0 -251
- package/assets/.appweaver/orchestrator/workflows/aw-spec-analyze-design.orch.yaml +0 -813
- package/assets/.appweaver/orchestrator/workflows/aw-spec-implement-delta.orch.yaml +0 -253
- package/assets/.appweaver/orchestrator/workflows/aw-spec-implement-ui.orch.yaml +0 -663
- package/assets/.appweaver/orchestrator/workflows/aw-spec-plan-ui.orch.yaml +0 -600
- package/assets/.appweaver/orchestrator/workflows/aw-spec-story-plan.orch.yaml +0 -1147
- package/assets/.appweaver/orchestrator/workflows/aw-spec-sync-stories.orch.yaml +0 -1121
- package/assets/.appweaver/templates/story-template.md +0 -178
|
@@ -76,7 +76,7 @@ workflow:
|
|
|
76
76
|
with: { require: backend, command: "/appweaver run" }
|
|
77
77
|
|
|
78
78
|
# The slice's source files, from its OKF concept — what the migration fix loop below is
|
|
79
|
-
# handed. Replaces the retired `design-paths` fence scan (the tech-agnostic
|
|
79
|
+
# handed. Replaces the retired `design-paths` fence scan (the tech-agnostic backend-plan.md
|
|
80
80
|
# carries no ```lang path=… code blocks, so it returned nothing and the fixer got an
|
|
81
81
|
# EMPTY context). Read-only, exits 0 with paths=[] when there is no concept yet, and
|
|
82
82
|
# on_error: continue so a missing bundle can never block a migration.
|
|
@@ -144,7 +144,7 @@ workflow:
|
|
|
144
144
|
|
|
145
145
|
# Record what the migration fix loop touched in the slice's OKF concept. Replaces the
|
|
146
146
|
# retired `design-reconcile` (which copied file bodies back into design fences — a
|
|
147
|
-
# silent no-op since
|
|
147
|
+
# silent no-op since backend-plan.md stopped carrying code). The fix loop can CREATE files
|
|
148
148
|
# (a new migration, a config) that implement never recorded. UNION (--merge), never
|
|
149
149
|
# replace. Advisory: conditioned + on_error: continue, never gated.
|
|
150
150
|
- id: okf_merge_run_fixes
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
# =============================================================================
|
|
2
|
+
# aw-spec-select-bounded-context (orchestrator) — pick or create the active
|
|
3
|
+
# BOUNDED CONTEXT
|
|
4
|
+
#
|
|
5
|
+
# A bounded context is the container a feature lives in: specs/<Context>/<Feature>/.
|
|
6
|
+
# It sits between the domain (which project's rules apply) and the feature (which
|
|
7
|
+
# aggregate is being worked on), and it owns ONE domain-model.md that every spec
|
|
8
|
+
# inside it references. That is why it is selected BEFORE select-feature — the
|
|
9
|
+
# feature directory cannot be resolved until the context that holds it is known.
|
|
10
|
+
#
|
|
11
|
+
# Contexts and features are told apart by the only reliable evidence on disk: a
|
|
12
|
+
# directory under specs/ carrying its OWN spec.md is a feature, one that does not is
|
|
13
|
+
# a context. No marker file, so nothing can fall out of sync with the tree.
|
|
14
|
+
#
|
|
15
|
+
# BACKWARD COMPATIBLE BY CONSTRUCTION. A repo that predates bounded contexts has its
|
|
16
|
+
# features flat under specs/ and no context.json; every caller falls back to the flat
|
|
17
|
+
# layout when no context is active, so the tree keeps working untouched and adopts
|
|
18
|
+
# contexts when someone runs this command. The flat features are reported as
|
|
19
|
+
# `legacy_features` rather than being hidden, so an un-migrated repo says so.
|
|
20
|
+
#
|
|
21
|
+
# ZERO LLM: scripts + one select + (conditionally) one ask. Same shape as
|
|
22
|
+
# select-feature, one level up.
|
|
23
|
+
#
|
|
24
|
+
# list-contexts → user_select (existing | "+ create new") → [ask name] → set-context
|
|
25
|
+
#
|
|
26
|
+
# Persists .appweaver/context.json {"context":"<Name>","context_directory":"specs/<Name>"}.
|
|
27
|
+
#
|
|
28
|
+
# Launch:
|
|
29
|
+
# /appweaver select-bounded-context # interactive: list + add-new
|
|
30
|
+
# /appweaver select-bounded-context Sales # direct: create-or-select Sales
|
|
31
|
+
# =============================================================================
|
|
32
|
+
|
|
33
|
+
name: aw-spec-select-bounded-context
|
|
34
|
+
description: Pick an existing bounded context or create a new one, and store it in .appweaver/context.json so select-feature nests its features inside it and every spec in the context shares one domain-model.md. Zero LLM — scripts + one selection only.
|
|
35
|
+
version: 1.0.0
|
|
36
|
+
agent_agnostic: true
|
|
37
|
+
dialect: aw-spec.orchestrator/v1
|
|
38
|
+
|
|
39
|
+
inputs:
|
|
40
|
+
user_input:
|
|
41
|
+
description: Optional bounded context name to create or select directly, e.g. Sales.
|
|
42
|
+
required: false
|
|
43
|
+
bind: USER_INPUT
|
|
44
|
+
|
|
45
|
+
scripts:
|
|
46
|
+
actions:
|
|
47
|
+
sh: .appweaver/scripts/bash/aw-spec-actions.sh
|
|
48
|
+
ps1: .appweaver/scripts/powershell/aw-spec-actions.ps1
|
|
49
|
+
|
|
50
|
+
vars:
|
|
51
|
+
new_sentinel: "+ Create a new bounded context" # source of truth is list-contexts $.sentinel; overwritten below
|
|
52
|
+
typed_name: ""
|
|
53
|
+
target_name: ""
|
|
54
|
+
|
|
55
|
+
workflow:
|
|
56
|
+
|
|
57
|
+
# 1. Enumerate the bounded contexts under specs/. `select_options` carries the
|
|
58
|
+
# "+ create new" sentinel and (when USER_INPUT names a context that does not
|
|
59
|
+
# exist yet) that name injected — so a direct argument is one-list select with
|
|
60
|
+
# no extra round trip, matching select-feature's fast path.
|
|
61
|
+
- id: list_contexts
|
|
62
|
+
action: execute_script
|
|
63
|
+
script: { ref: actions }
|
|
64
|
+
subcommand: list-contexts
|
|
65
|
+
args: ["--preselect", "{{USER_INPUT}}"]
|
|
66
|
+
outputs:
|
|
67
|
+
- { name: contexts, from: "$.contexts" }
|
|
68
|
+
- { name: context_names, from: "$.names" }
|
|
69
|
+
- { name: context_count, from: "$.count" }
|
|
70
|
+
- { name: select_options, from: "$.select_options" }
|
|
71
|
+
- { name: new_sentinel, from: "$.sentinel" }
|
|
72
|
+
- { name: legacy_features, from: "$.legacy_features" }
|
|
73
|
+
- { name: legacy_count, from: "$.legacy_count" }
|
|
74
|
+
|
|
75
|
+
# 2. Choose. A matching USER_INPUT auto-selects with no prompt; the lone sentinel
|
|
76
|
+
# on a repo with no contexts yet auto-confirms.
|
|
77
|
+
- id: pick
|
|
78
|
+
action: user_select
|
|
79
|
+
prompt: "Select the bounded context (e.g. Sales, Billing) — or create a new one:"
|
|
80
|
+
options_from_variable: select_options
|
|
81
|
+
preselect_from: USER_INPUT
|
|
82
|
+
single_option_confirm: true
|
|
83
|
+
outputs:
|
|
84
|
+
- { name: chosen, from: selection }
|
|
85
|
+
|
|
86
|
+
# 3. Only on the "create new" branch do we ask for a name.
|
|
87
|
+
- id: ask_new_name
|
|
88
|
+
action: ask
|
|
89
|
+
condition: "{{chosen}} == {{new_sentinel}}"
|
|
90
|
+
prompt: >
|
|
91
|
+
Name the new bounded context — this is a BOUNDARY in the domain (e.g. Sales,
|
|
92
|
+
Billing, Fulfilment), not a feature and not a layer. Aggregates like Order or
|
|
93
|
+
Invoice become features inside it, and every one of them shares this context's
|
|
94
|
+
single domain-model.md:
|
|
95
|
+
answer_var: typed_name
|
|
96
|
+
|
|
97
|
+
# 4. Coalesce the target name. The engine has no compound conditions, so this is
|
|
98
|
+
# two ordered sets: default to the pick, then override with the typed name on
|
|
99
|
+
# the "create new" branch only.
|
|
100
|
+
- id: name_from_pick
|
|
101
|
+
action: set
|
|
102
|
+
vars: { target_name: "{{chosen}}" }
|
|
103
|
+
- id: name_from_new
|
|
104
|
+
action: set
|
|
105
|
+
condition: "{{chosen}} == {{new_sentinel}}"
|
|
106
|
+
vars: { target_name: "{{typed_name}}" }
|
|
107
|
+
|
|
108
|
+
# 5. Create-or-select the context dir + persist it as the active context.
|
|
109
|
+
# domain-model.md is deliberately NOT created here — specify is the model's only
|
|
110
|
+
# writer, and an empty placeholder would read as "the model exists" downstream.
|
|
111
|
+
- id: set_context
|
|
112
|
+
action: execute_script
|
|
113
|
+
script: { ref: actions }
|
|
114
|
+
subcommand: set-context
|
|
115
|
+
args: ["--context", "{{target_name}}"]
|
|
116
|
+
outputs:
|
|
117
|
+
- { name: context, from: "$.context" }
|
|
118
|
+
- { name: context_dir, from: "$.context_dir" }
|
|
119
|
+
- { name: domain_model, from: "$.domain_model" }
|
|
120
|
+
- { name: existed, from: "$.existed" }
|
|
121
|
+
- { name: created, from: "$.created" }
|
|
122
|
+
- { name: domain_model_exists, from: "$.domain_model_exists" }
|
|
123
|
+
|
|
124
|
+
outputs:
|
|
125
|
+
context: "{{context}}"
|
|
126
|
+
context_dir: "{{context_dir}}"
|
|
127
|
+
domain_model: "{{domain_model}}"
|
|
128
|
+
domain_model_exists: "{{domain_model_exists}}"
|
|
129
|
+
created: "{{created}}"
|
|
130
|
+
legacy_features: "{{legacy_features}}"
|
|
131
|
+
note: "Active bounded context set in .appweaver/context.json. select-feature now creates and lists features inside {{context_dir}}/, and every spec there shares {{domain_model}} as its domain model. Features already sitting flat under specs/ are listed as legacy_features — they keep working exactly as before and are not moved; re-run select-feature after selecting a context to place new work inside it."
|
|
132
|
+
next: "/appweaver select-feature (creates {{context_dir}}/<Feature>/, then specify)"
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
#
|
|
4
4
|
# feature = AGGREGATE (e.g. Order). This is the FIRST step of the spec-anchored
|
|
5
5
|
# pipeline: it fixes the aggregate boundary BEFORE any spec/design exists, so the
|
|
6
|
-
# feature's single spec.md +
|
|
6
|
+
# feature's single spec.md + backend-plan.md and every command (CreateOrder/UpdateOrder =
|
|
7
7
|
# user stories) hang off one directory. It replaces guessing the aggregate out of prose in
|
|
8
8
|
# `specify` — that is why finding #1 (feature=aggregate) is enforced here, not hoped for.
|
|
9
9
|
#
|
|
@@ -13,14 +13,20 @@
|
|
|
13
13
|
# brownfield repo you pick a real discovered code feature BEFORE anything is under
|
|
14
14
|
# specs/; on greenfield (no bundle) the list is specs-only, exactly as before.
|
|
15
15
|
#
|
|
16
|
+
# SCOPED BY THE ACTIVE BOUNDED CONTEXT. When .appweaver/context.json names one, both
|
|
17
|
+
# the listing and the creation happen inside specs/<Context>/ — so a context shows
|
|
18
|
+
# only its own features and new work lands beside the domain-model.md it shares. With
|
|
19
|
+
# no context active the base is specs/ itself and behaviour is identical to before
|
|
20
|
+
# contexts existed, which is what lets a repo adopt them without a migration.
|
|
21
|
+
#
|
|
16
22
|
# ZERO LLM: only scripts + one select + (conditionally) one ask. No generation,
|
|
17
23
|
# no standards, no domain-select. Pure, deterministic orchestration/governance.
|
|
18
24
|
#
|
|
19
25
|
# list-features (specs/ ∪ OKF aggregates) → user_select (existing | "+ create new") → [ask name] → set-feature
|
|
20
26
|
#
|
|
21
27
|
# Persists .appweaver/feature.json {"feature_directory":"specs/<Feature>"} so every
|
|
22
|
-
# later command operates on it: the forward loop (specify/plan/analyze-
|
|
23
|
-
# build/analyze-slice/run/deploy) and the CR loop (analyze-delta
|
|
28
|
+
# later command operates on it: the forward loop (specify/plan/analyze-plan/implement/
|
|
29
|
+
# build/analyze-slice/run/deploy) and the CR loop (analyze-plan-delta/implement/
|
|
24
30
|
# finalize-delta/close-delta — the standalone `cr` is retired; specify and design author
|
|
25
31
|
# the delta docs themselves).
|
|
26
32
|
#
|
|
@@ -54,6 +60,31 @@ vars:
|
|
|
54
60
|
|
|
55
61
|
workflow:
|
|
56
62
|
|
|
63
|
+
# 0. Resolve the bounded context this feature will live in, and REFUSE to guess.
|
|
64
|
+
# scope_ok is false in exactly one state: contexts exist and none is selected.
|
|
65
|
+
# Left to run, the feature would be created at specs/<Feature> — outside every
|
|
66
|
+
# context and with no domain model to share — and nothing downstream would say
|
|
67
|
+
# so. A repo with no contexts at all passes (the flat layout is a valid state),
|
|
68
|
+
# which is what keeps a pre-context tree working untouched.
|
|
69
|
+
- id: context_scope
|
|
70
|
+
action: execute_script
|
|
71
|
+
script: { ref: actions }
|
|
72
|
+
subcommand: list-contexts
|
|
73
|
+
outputs:
|
|
74
|
+
- { name: active_context, from: "$.active" }
|
|
75
|
+
- { name: context_dir, from: "$.active_dir" }
|
|
76
|
+
- { name: feature_base, from: "$.feature_base" }
|
|
77
|
+
- { name: context_count, from: "$.count" }
|
|
78
|
+
- { name: scope_ok, from: "$.scope_ok" }
|
|
79
|
+
- { name: scope_message, from: "$.scope_message" }
|
|
80
|
+
|
|
81
|
+
- id: require_context_scope
|
|
82
|
+
action: verify_context
|
|
83
|
+
require_true: scope_ok
|
|
84
|
+
on_false: stop
|
|
85
|
+
on_false_message: >
|
|
86
|
+
{{scope_message}}
|
|
87
|
+
|
|
57
88
|
# 1. Enumerate selectable aggregates from TWO merged sources (deduped by name):
|
|
58
89
|
# specs/ sub-folders (already scaffolded/adopted) AND the OKF bundle's
|
|
59
90
|
# Aggregate concepts — the brownfield feature map onboard reverse-engineers,
|
|
@@ -77,7 +108,7 @@ workflow:
|
|
|
77
108
|
# no prompt; the lone sentinel at bootstrap (no features yet) auto-confirms.
|
|
78
109
|
- id: pick
|
|
79
110
|
action: user_select
|
|
80
|
-
prompt: "Select a feature (the aggregate, e.g. Order) — or create a new one:"
|
|
111
|
+
prompt: "Select a feature (the aggregate, e.g. Order) in {{feature_base}}/ — or create a new one:"
|
|
81
112
|
options_from_variable: select_options
|
|
82
113
|
preselect_from: USER_INPUT
|
|
83
114
|
single_option_confirm: true
|
|
@@ -118,11 +149,13 @@ workflow:
|
|
|
118
149
|
- { name: existed, from: "$.existed" }
|
|
119
150
|
- { name: created, from: "$.created" }
|
|
120
151
|
- { name: spec_exists, from: "$.spec_exists" }
|
|
152
|
+
- { name: context, from: "$.context" }
|
|
121
153
|
|
|
122
154
|
outputs:
|
|
123
155
|
feature: "{{feature}}"
|
|
124
156
|
feature_dir: "{{feature_dir}}"
|
|
157
|
+
context: "{{context}}"
|
|
125
158
|
created: "{{created}}"
|
|
126
159
|
spec_exists: "{{spec_exists}}"
|
|
127
|
-
note: "Active feature set in .appweaver/feature.json — the aggregate boundary for its single spec.md
|
|
160
|
+
note: "Active feature set in .appweaver/feature.json — the aggregate boundary for its single spec.md + backend-plan.md. `context` names the bounded context it was created in, and is empty on a repo with no active context (the flat specs/<Feature> layout, which keeps working unchanged)."
|
|
128
161
|
next: "/appweaver specify <what this feature does> (authors {{feature_dir}}/spec.md; each operation = a user story)"
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
# and `lane-verify` to gate, and neither can write.
|
|
31
31
|
#
|
|
32
32
|
# WHY THE SOURCE PATH IS ASKED AND NOT INHERITED. A lane's root is the subtree it
|
|
33
|
-
# OWNS: the only place
|
|
33
|
+
# OWNS: the only place implement's lane for it may write, the directory its build and
|
|
34
34
|
# run commands act on, and in brownfield the code onboard reads. A profile's default
|
|
35
35
|
# root describes how a NEW project of that stack is usually laid out, which is a
|
|
36
36
|
# reasonable proposal and a poor assumption — a repo that already exists did not
|
|
@@ -203,7 +203,7 @@ workflow:
|
|
|
203
203
|
- id: ask_ui_source_path
|
|
204
204
|
action: ask
|
|
205
205
|
condition: "{{ui_selected}}"
|
|
206
|
-
prompt: "UI lane SOURCE PATH — the subtree this lane owns, the only place
|
|
206
|
+
prompt: "UI lane SOURCE PATH — the subtree this lane owns, the only place implement's frontend lane may write. It must not overlap the service lane's. Pick one or type your own:"
|
|
207
207
|
options_from_variable: ui_root_options
|
|
208
208
|
answer_var: ui_source_path
|
|
209
209
|
|
|
@@ -292,5 +292,5 @@ outputs:
|
|
|
292
292
|
api_detected: "{{api_detected}} at {{api_detected_root}}"
|
|
293
293
|
ui_detected: "{{ui_detected}} at {{ui_detected_root}}"
|
|
294
294
|
prototype: "{{prototype}}"
|
|
295
|
-
note: "Lanes persisted to .appweaver/stacks.json. Each lane carries a STACK and a SOURCE PATH, and both are load-bearing. The SOURCE PATH is ownership: implement writes only under the service lane's
|
|
295
|
+
note: "Lanes persisted to .appweaver/stacks.json. Each lane carries a STACK and a SOURCE PATH, and both are load-bearing. The SOURCE PATH is ownership: implement's service lane writes only under the service lane's and its frontend lane only under the UI lane's, build/test/run act on it, and onboard reverse-engineers out of it — overlapping paths are refused here rather than discovered later as two generators writing one file. The build/test/run commands are project-supplied strings the engine shells out to, which is how it stays stdlib-only and stack-ignorant. api_detected / ui_detected report what this repo's own files pointed at, whether or not it was chosen — empty on a greenfield repo with nothing to detect. A source path that does not exist yet is NORMAL here and reported rather than refused: greenfield declares src/ before implement creates it. The on-disk check runs in the phases that read the subtree — implement, build, run and onboard all call lane-verify and STOP with the fix named. Declining a lane with (none) is a real declaration and removes any lane of that kind a previous run left behind; it is also what stops that lane's constitution half and rule files being authored. `prototype` is not a lane — it has a root and a run command so an operator can open it, and nothing else. Re-run this workflow any time to re-stack a lane, move a source path, or drop a lane with (none); it is the only workflow that may write this file."
|
|
296
296
|
next: "GREENFIELD: /appweaver select-domain → constitution → select-feature → specify. BROWNFIELD: /appweaver onboard — it reverse-engineers out of the source paths declared here and generates the project (no select-domain; onboard derives and activates it from the code). Run this workflow FIRST in either sequence: constitution reads the declaration to decide which halves to author, and onboard reads it to decide what to scan."
|