aw-spec-cli 0.1.26 → 0.1.27
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/.agents/skills/appweaver/SKILL.md +7 -47
- package/assets/.appweaver/ORCH-DIALECT.md +13 -9
- package/assets/.appweaver/RULE-PARTITION.md +3 -3
- package/assets/.appweaver/STACK-PROFILES.md +188 -101
- package/assets/.appweaver/domain.json +1 -1
- package/assets/.appweaver/orchestrator/AGENT-PROFILE.md +38 -10
- package/assets/.appweaver/orchestrator/LAUNCHER.md +88 -0
- package/assets/.appweaver/orchestrator/README.md +120 -53
- package/assets/.appweaver/orchestrator/adapters/claude_agent_sdk.py +1 -1
- package/assets/.appweaver/orchestrator/modules/domain-select.orch.yaml +6 -4
- package/assets/.appweaver/orchestrator/modules/foundation-lane.orch.yaml +237 -0
- package/assets/.appweaver/orchestrator/modules/foundation-pack.orch.yaml +349 -0
- package/assets/.appweaver/orchestrator/modules/foundation-spec.orch.yaml +381 -0
- package/assets/.appweaver/orchestrator/modules/lane-gate.orch.yaml +4 -4
- package/assets/.appweaver/orchestrator/modules/tech-select.orch.yaml +3 -3
- package/assets/.appweaver/orchestrator/orchestrator.py +162 -63
- package/assets/.appweaver/orchestrator/rev-templates/domain-constitution.skeleton.md +2 -2
- package/assets/.appweaver/orchestrator/rev-templates/domain-requirements.skeleton.md +2 -2
- package/assets/.appweaver/orchestrator/rev-templates/domain-rule-bindings.skeleton.md +5 -5
- package/assets/.appweaver/orchestrator/rev-templates/frontend-rule-file.skeleton.md +1 -1
- package/assets/.appweaver/orchestrator/rev-templates/tech-rule-bindings.skeleton.md +14 -14
- package/assets/.appweaver/orchestrator/rev-templates/technical-constitution.skeleton.md +2 -2
- package/assets/.appweaver/orchestrator/rev-templates/technical-rule-file.skeleton.md +1 -1
- package/assets/.appweaver/orchestrator/rev-templates/ui-constitution.skeleton.md +3 -3
- package/assets/.appweaver/orchestrator/workflows/_smoke.orch.yaml +41 -3
- package/assets/.appweaver/orchestrator/workflows/aw-spec-add-component.orch.yaml +1 -1
- package/assets/.appweaver/orchestrator/workflows/aw-spec-adopt.orch.yaml +13 -13
- package/assets/.appweaver/orchestrator/workflows/aw-spec-analyze-slice-delta.orch.yaml +3 -3
- package/assets/.appweaver/orchestrator/workflows/aw-spec-analyze-slice.orch.yaml +3 -3
- package/assets/.appweaver/orchestrator/workflows/aw-spec-build.orch.yaml +4 -4
- package/assets/.appweaver/orchestrator/workflows/aw-spec-characterize.orch.yaml +2 -2
- package/assets/.appweaver/orchestrator/workflows/aw-spec-constitution.orch.yaml +61 -12
- package/assets/.appweaver/orchestrator/workflows/aw-spec-foundation.orch.yaml +172 -293
- package/assets/.appweaver/orchestrator/workflows/aw-spec-implement.orch.yaml +29 -28
- package/assets/.appweaver/orchestrator/workflows/aw-spec-onboard.orch.yaml +53 -53
- package/assets/.appweaver/orchestrator/workflows/aw-spec-parity.orch.yaml +2 -2
- package/assets/.appweaver/orchestrator/workflows/aw-spec-plan.orch.yaml +3 -3
- package/assets/.appweaver/orchestrator/workflows/aw-spec-run.orch.yaml +4 -4
- package/assets/.appweaver/orchestrator/workflows/aw-spec-select-bounded-context.orch.yaml +26 -2
- package/assets/.appweaver/orchestrator/workflows/aw-spec-select-domain.orch.yaml +21 -15
- package/assets/.appweaver/orchestrator/workflows/aw-spec-select-stack.orch.yaml +14 -14
- package/assets/.appweaver/orchestrator/workflows/aw-spec-specify.orch.yaml +2 -2
- package/assets/.appweaver/orchestrator/workflows/aw-spec-ui-model.orch.yaml +3 -3
- package/assets/.appweaver/orchestrator/workflows/aw-spec-ui-prototype.orch.yaml +6 -6
- package/assets/.appweaver/scripts/bash/aw-spec-actions.sh +284 -128
- package/assets/.appweaver/scripts/powershell/aw-spec-actions.ps1 +224 -70
- package/assets/.appweaver/scripts/python/aw-foundation.py +809 -20
- package/assets/.appweaver/scripts/python/aw-inventory.py +28 -21
- package/assets/.appweaver/scripts/python/aw-plan-coverage.py +2 -2
- package/assets/.appweaver/scripts/python/aw-rev-constitution.py +6 -6
- package/assets/.appweaver/scripts/python/aw-stack.py +195 -89
- package/assets/.appweaver/stack-profiles/angular.json +2 -1
- package/assets/.appweaver/stack-profiles/blazor-wasm.json +2 -1
- package/assets/.appweaver/stack-profiles/dotnet-webapi.json +16 -3
- package/assets/.appweaver/stack-profiles/go-chi.json +6 -1
- package/assets/.appweaver/stack-profiles/java-spring.json +12 -5
- package/assets/.appweaver/stack-profiles/nextjs.json +2 -1
- package/assets/.appweaver/stack-profiles/node-express.json +8 -2
- package/assets/.appweaver/stack-profiles/python-fastapi.json +9 -2
- package/assets/.appweaver/stack-profiles/react-vite.json +2 -1
- package/assets/.appweaver/stack-profiles/sveltekit.json +2 -1
- package/assets/.appweaver/stack-profiles/vue-vite.json +2 -1
- package/assets/.appweaver/stacks.json +37 -1
- package/assets/.appweaver/templates/constitution-ui-template.md +2 -2
- package/assets/.claude/skills/appweaver/SKILL.md +7 -46
- package/assets/foundations/dotnet/ModularMonolith/ModularMonolith.Reference.rules.json +31 -0
- package/assets/foundations/dotnet/VerticalSlice/VerticalSlice.Reference.rules.json +16 -0
- package/assets/foundations/foundation.spec.template.txt +73 -0
- package/assets/foundations/java/Hexagonal/Hexagonal.pack.txt +1 -1
- package/assets/foundations/java/Hexagonal/unpack-foundation.sh +4 -5
- package/assets/foundations/node/NextAppRouter/NextAppRouter.spec.txt +68 -0
- package/assets/guardrails/README.md +31 -17
- package/assets/guardrails/{projects/dotnet-default-project → project-specific}/domain-rule-bindings.md +5 -5
- package/assets/guardrails/{projects/dotnet-default-project → project-specific}/tech-rule-bindings.md +151 -114
- package/assets/guardrails/technology/dotnet-webapi/PACKAGING.md +58 -4
- package/assets/guardrails/technology/dotnet-webapi/coding-standards.md +1 -1
- package/assets/guardrails/technology/dotnet-webapi/dependency-policy.md +1 -1
- package/assets/guardrails/technology/dotnet-webapi/folder-structure.md +1 -1
- package/assets/guardrails/technology/dotnet-webapi/framework-api-map.md +1 -1
- package/assets/guardrails/technology/dotnet-webapi/testing.md +1 -1
- package/assets/guardrails/technology/nextjs/api-client.md +1 -1
- package/assets/guardrails/technology/nextjs/component-architecture.md +1 -1
- package/assets/guardrails/technology/nextjs/component-conventions.md +2 -2
- package/assets/guardrails/technology/nextjs/design-system.md +1 -1
- package/assets/guardrails/technology/nextjs/frontend-testing.md +1 -1
- package/assets/guardrails/technology/nextjs/routing-navigation.md +1 -1
- package/assets/guardrails/technology/nextjs/ui-constitution.md +3 -3
- package/package.json +1 -1
- package/assets/.agents/skills/appweaver-demo/SKILL.md +0 -59
- package/assets/.appweaver/orchestrator/.smoke-out/smoke.md +0 -6
- package/assets/.appweaver/orchestrator/workflows/aw-spec-demo.orch.yaml +0 -100
- package/assets/.claude/skills/appweaver-demo/SKILL.md +0 -59
- package/assets/.kilocode/agent.json +0 -28
- package/assets/.kilocode/workflows/appweaver-demo.md +0 -59
- package/assets/.kilocode/workflows/appweaver.md +0 -55
- /package/assets/guardrails/{projects/dotnet-default-project → project-specific}/domain/domain-requirements.md +0 -0
- /package/assets/guardrails/{projects/dotnet-default-project → project-specific}/frontend/ui-requirements.md +0 -0
- /package/assets/guardrails/{projects/dotnet-default-project → project-specific}/service/technical-requirements.md +0 -0
|
@@ -5,13 +5,15 @@
|
|
|
5
5
|
# Exercises every extended construct in one run: inputs, set (raw object),
|
|
6
6
|
# execute_script (read-only subcommand), verify_context gates, ask
|
|
7
7
|
# (non-interactive default), foreach + while loops + break, agent_query
|
|
8
|
-
# (mock:), agent_author (mock content), build_context,
|
|
9
|
-
#
|
|
8
|
+
# (mock:), agent_author (mock content), build_context, agent_generate (the
|
|
9
|
+
# mock writes SmokeGenerated.cs), agent_review (mock: pass when the files
|
|
10
|
+
# exist), include (domain-select module), dispatch_hooks (empty).
|
|
10
11
|
#
|
|
11
12
|
# Run:
|
|
12
13
|
# python3 .appweaver/orchestrator/orchestrator.py \
|
|
13
14
|
# .appweaver/orchestrator/workflows/_smoke.orch.yaml --non-interactive --json
|
|
14
|
-
# Expected: status ok, echo=hello, sum of foreach passes, smoke.md
|
|
15
|
+
# Expected: status ok, echo=hello, sum of foreach passes, smoke.md and
|
|
16
|
+
# SmokeGenerated.cs written, review_pass=true.
|
|
15
17
|
# =============================================================================
|
|
16
18
|
|
|
17
19
|
name: orch-smoke
|
|
@@ -138,6 +140,40 @@ workflow:
|
|
|
138
140
|
action: verify_context
|
|
139
141
|
required_files: ["{{out_dir}}/smoke.md"]
|
|
140
142
|
|
|
143
|
+
# agent_generate — the edit step: the agent writes the file itself and reports
|
|
144
|
+
# files[]. The mock names the file after the task's first `backtick` word and
|
|
145
|
+
# writes it under out_dir; a reported path not on disk is dropped before binding,
|
|
146
|
+
# so the non-empty gate proves the file was written.
|
|
147
|
+
- id: gen_file
|
|
148
|
+
action: agent_generate
|
|
149
|
+
tools: "Read,Write,Edit"
|
|
150
|
+
permission_mode: acceptEdits
|
|
151
|
+
task: |
|
|
152
|
+
Write exactly one file, {{out_dir}}/SmokeGenerated.cs, holding the single
|
|
153
|
+
line `SmokeGenerated` and nothing else. Write nothing outside {{out_dir}}.
|
|
154
|
+
outputs:
|
|
155
|
+
- { name: gen_files, from: "$.files" }
|
|
156
|
+
- id: gate_gen
|
|
157
|
+
action: verify_context
|
|
158
|
+
require_non_empty: gen_files
|
|
159
|
+
on_empty: stop
|
|
160
|
+
on_empty_message: "agent_generate wrote nothing, or files[] binding is broken"
|
|
161
|
+
|
|
162
|
+
# agent_review — read-only review of the files the generation reported; the
|
|
163
|
+
# mock passes when every reviewed file exists
|
|
164
|
+
- id: review_file
|
|
165
|
+
action: agent_review
|
|
166
|
+
review_of_var: gen_files
|
|
167
|
+
task: Check that the file holds the single line SmokeGenerated. Decide pass/fail.
|
|
168
|
+
outputs:
|
|
169
|
+
- { name: review_pass, from: "$.pass" }
|
|
170
|
+
- { name: review_issues, from: "$.issues" }
|
|
171
|
+
- id: gate_review
|
|
172
|
+
action: verify_context
|
|
173
|
+
require_true: review_pass
|
|
174
|
+
on_false: stop
|
|
175
|
+
on_false_message: "agent_review result binding is broken"
|
|
176
|
+
|
|
141
177
|
# F9: include — the shared domain-select module (read-only script + asks;
|
|
142
178
|
# non-interactive: gate→continue, mode→all)
|
|
143
179
|
- id: domain
|
|
@@ -156,5 +192,7 @@ outputs:
|
|
|
156
192
|
mode: "{{mode}}"
|
|
157
193
|
seen: "{{seen}}"
|
|
158
194
|
q_items: "{{q_items}}"
|
|
195
|
+
generated: "{{gen_files}}"
|
|
196
|
+
review_pass: "{{review_pass}}"
|
|
159
197
|
domain: "{{domain}}"
|
|
160
198
|
note: "all engine constructs exercised"
|
|
@@ -141,7 +141,7 @@ workflow:
|
|
|
141
141
|
on_false: stop
|
|
142
142
|
on_false_message: >
|
|
143
143
|
No .NET host/startup project found — nothing named Program.cs under `{{host_search}}`,
|
|
144
|
-
the
|
|
144
|
+
the lane root folder the backend lane declares, nor elsewhere in this repository. Wiring a
|
|
145
145
|
component means editing a host project's startup registration, so there has to be one
|
|
146
146
|
to edit. If this is a .NET repository, scaffold it first with /appweaver foundation.
|
|
147
147
|
If it is not — this lane's ecosystem is `{{host_eco}}` — then this catalogue's runbooks
|
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
# active_version.json (v1.0) so the CR loop works immediately after.
|
|
38
38
|
#
|
|
39
39
|
# GOVERNANCE RECONCILE (the JIT contract, gap-fix #1) — ⏸ HELD, OFF BY DEFAULT.
|
|
40
|
-
# onboard established the PROJECT constitution + guardrails
|
|
40
|
+
# onboard established the PROJECT constitution + guardrails/<project>/ rule set
|
|
41
41
|
# from the whole-repo SCAN, with per-feature specifics marked PROVISIONAL. The reconcile
|
|
42
42
|
# block below carries this feature's real evidence (BR-/CN-/DC-/IC- ids, code coordinates)
|
|
43
43
|
# INTO that scaffold — upgrading provisional → evidenced. It RECONCILES, never re-authors:
|
|
@@ -55,7 +55,7 @@
|
|
|
55
55
|
#
|
|
56
56
|
# Adopt does NOT generate code and does NOT modify source — writes land under
|
|
57
57
|
# specs/<Context>/<Feature>/, in the context's specs/<Context>/domain-model.md, and in the
|
|
58
|
-
# aggregate's OKF concept; the constitution halves and guardrails
|
|
58
|
+
# aggregate's OKF concept; the constitution halves and guardrails/<project>/ are
|
|
59
59
|
# written only when the reconcile block below is enabled.
|
|
60
60
|
# Fidelity checks spec/design ↔ CODE; the Adopt review is REPORTED for out-of-band
|
|
61
61
|
# closure — it blocks only on structural failures (unmapped code / fabricated spec/design).
|
|
@@ -111,7 +111,7 @@ scripts:
|
|
|
111
111
|
# Sticky standards seed = the UNIVERSAL always-on rule only (ai-rules). The TECHNICAL/
|
|
112
112
|
# architecture set for the reversed DESIGN step (mirrors aw-spec-design) is no longer
|
|
113
113
|
# hardcoded here — it is now CONFIGURATION, loaded per-command from
|
|
114
|
-
# guardrails
|
|
114
|
+
# guardrails/<project>/tech-rule-bindings.md under "## /aw-spec-adopt" by the
|
|
115
115
|
# tech-select module (see the tech_select step below). The reversed SPEC step runs
|
|
116
116
|
# include_standards:false and takes its domain frame from constitution.domain.md via
|
|
117
117
|
# build_context — so design never sees a domain rule file (rule partition preserved); the
|
|
@@ -335,7 +335,7 @@ workflow:
|
|
|
335
335
|
on_false_message: "No concept for the aggregate '{{aggregate_primary}}' — the one feature '{{feature_name}}' acts on — in the onboard bundle under {{bundle_dir}}. If its bounded context has not been onboarded, run /appweaver onboard <Context> first; {{bundle_dir}}/aggregates/index.md lists each aggregate with the features that act on it. If '{{feature_name}}' is a NEW feature (no existing code), do NOT adopt it — author it through the forward pipeline (/appweaver specify → plan → implement), which onboard already made brownfield-ready."
|
|
336
336
|
|
|
337
337
|
# Governance prerequisite: the reverse steps below are authored AGAINST the project
|
|
338
|
-
# onboard established (the constitution halves + guardrails
|
|
338
|
+
# onboard established (the constitution halves + guardrails/<project>/ rule set).
|
|
339
339
|
# Resolve the active domain now and require its rule map to exist — without it there is
|
|
340
340
|
# no code-derived rule set for tech_select to load, no domain frame for the reversed
|
|
341
341
|
# spec, and nothing for the reconcile block to upgrade when it is enabled. Reconciling
|
|
@@ -363,10 +363,10 @@ workflow:
|
|
|
363
363
|
action: verify_context
|
|
364
364
|
require_true: rulemap_exists
|
|
365
365
|
on_false: stop
|
|
366
|
-
on_false_message: "No active governance for adopt to work against — run /appweaver onboard first. onboard establishes the PROJECT constitution + guardrails
|
|
366
|
+
on_false_message: "No active governance for adopt to work against — run /appweaver onboard first. onboard establishes the PROJECT constitution + guardrails/<project>/ rule set (provisional-from-scan) and activates it. Reversing '{{feature_name}}' without that scaffold would author the spec and design against no code-derived rules at all, and leave them with no governance home."
|
|
367
367
|
|
|
368
368
|
# TECHNICAL rule files → sticky standards (configuration, not hardcoded). tech-select
|
|
369
|
-
# reads guardrails
|
|
369
|
+
# reads guardrails/<project>/tech-rule-bindings.md under "## /aw-spec-adopt" and
|
|
370
370
|
# loads that reference set into the sticky standards for reverse_plan
|
|
371
371
|
# (include_standards:true) — the reversed SPEC and MODEL steps turn it off
|
|
372
372
|
# (include_standards:false), keeping them free of architecture (rule partition). No domain
|
|
@@ -1119,7 +1119,7 @@ workflow:
|
|
|
1119
1119
|
# ═══════════ GOVERNANCE RECONCILE — upgrade onboard's PROVISIONAL scaffold ═══
|
|
1120
1120
|
# ⏸ HELD 2026-07-29: every step in this block is gated on `reconcile_governance`
|
|
1121
1121
|
# (default "false"), so adopt currently does NOT touch the constitution halves
|
|
1122
|
-
# or the guardrails
|
|
1122
|
+
# or the guardrails/<project>/ rule set — onboard's provisional scaffold
|
|
1123
1123
|
# is left as-is. Flip the var to "true" (workflow vars) to restore the behaviour.
|
|
1124
1124
|
# Now that this feature is reversed to a TRUSTWORTHY spec (real BR-/CN-/DC-/IC- ids)
|
|
1125
1125
|
# + design (real code coordinates), reconcile that evidence INTO the governance
|
|
@@ -1145,7 +1145,7 @@ workflow:
|
|
|
1145
1145
|
- { path: "{{spec_file}}" } # the feature's real BR-/CN-/DC-/IC-
|
|
1146
1146
|
- { path: "{{backend_plan}}" }
|
|
1147
1147
|
- { path: "{{feature_dir}}/source-map.md" }
|
|
1148
|
-
- { path: "guardrails/
|
|
1148
|
+
- { path: "guardrails/{{gov_domain}}/domain-rule-bindings.md", optional: true }
|
|
1149
1149
|
- { path: .appweaver/RULE-PARTITION.md } # the rule-partition authority (which command reads what)
|
|
1150
1150
|
- id: reconcile_pack
|
|
1151
1151
|
condition: "{{reconcile_governance}} == true" # HELD — governance reconcile paused (see vars)
|
|
@@ -1153,12 +1153,12 @@ workflow:
|
|
|
1153
1153
|
tools: "Read,Write,Edit"
|
|
1154
1154
|
permission_mode: acceptEdits
|
|
1155
1155
|
task: |
|
|
1156
|
-
RECONCILE the domain rule-file set in guardrails/
|
|
1156
|
+
RECONCILE the domain rule-file set in guardrails/{{gov_domain}}/domain/ with the
|
|
1157
1157
|
newly-adopted feature '{{feature_name}}'. onboard authored these rule files from the
|
|
1158
1158
|
whole-repo scan with per-feature specifics marked `PROVISIONAL — reconciled at
|
|
1159
1159
|
adopt`. READ this feature's reversed spec.md + backend-plan.md + source-map.md (in
|
|
1160
1160
|
context — the real evidence) and the EXISTING rule files under
|
|
1161
|
-
guardrails/
|
|
1161
|
+
guardrails/{{gov_domain}}/.
|
|
1162
1162
|
|
|
1163
1163
|
RECONCILE, do NOT re-author:
|
|
1164
1164
|
- UPGRADE the provisional entries this feature now evidences: replace a
|
|
@@ -1174,7 +1174,7 @@ workflow:
|
|
|
1174
1174
|
- Preserve the RULE PARTITION in domain-rule-bindings.md (constitution / specify / gate get
|
|
1175
1175
|
the domain files; design / implement get None). Keep each file's frontmatter and
|
|
1176
1176
|
note in `generated_by` that adopt reconciled '{{feature_name}}'.
|
|
1177
|
-
Write ONLY inside guardrails/
|
|
1177
|
+
Write ONLY inside guardrails/{{gov_domain}}/. Report the files changed/added.
|
|
1178
1178
|
outputs:
|
|
1179
1179
|
- { name: pack_reconciled, from: "$.files" }
|
|
1180
1180
|
|
|
@@ -1250,7 +1250,7 @@ workflow:
|
|
|
1250
1250
|
- { path: "{{constitution_domain_file}}" }
|
|
1251
1251
|
- { path: "{{constitution_technical_file}}" }
|
|
1252
1252
|
- { path: "{{spec_file}}" }
|
|
1253
|
-
- { path: "guardrails/
|
|
1253
|
+
- { path: "guardrails/{{gov_domain}}/domain-rule-bindings.md", optional: true }
|
|
1254
1254
|
- id: reconcile_domain
|
|
1255
1255
|
condition: "{{reconcile_governance}} == true" # HELD — governance reconcile paused (see vars)
|
|
1256
1256
|
action: agent_author
|
|
@@ -1351,4 +1351,4 @@ outputs:
|
|
|
1351
1351
|
composed_file: "{{composed_file}}"
|
|
1352
1352
|
technical_reconcile_ok: "{{technical_ok}}"
|
|
1353
1353
|
domain_reconcile_ok: "{{domain_ok}}"
|
|
1354
|
-
next: "Adopted {{feature_name}} (spec.md + backend-plan.md + source-map.md, v1.0) and wrote {{aggregate_sections}} — the model section(s) for the aggregate(s) it acts on, resolved from the {{aggregate_source}} — in the bounded context `{{context}}`'s shared {{domain_model}}. The spec cites BR-nnn by id, the model carries their text, so this slice is checkable by the same gates as a greenfield one and analyze-plan's check 4 now has a model to check against. A section another feature over the same aggregate wrote first was EXTENDED, never duplicated; every other section is untouched. COMPLETED the OKF concept of {{aggregate_primary}} (deepened + linked the deep artifacts; {{xref_edge_count}} cross-slice edge(s) recorded). UI HALF: ui_lane={{ui_lane}} — where it is true this slice also has frontend-plan.md, reversed from the {{ui_count}} UI file(s) the feature map attributes to it; where it is false the repo declared no frontend lane, or this aggregate owns no part of its surface, and a service-only adoption is the correct outcome rather than a gap. In the second case, where a frontend lane IS declared, the feature records lanes=[backend] in its active_version.json (feature_lanes shows it), so plan and the analyze gates treat the frontend lane as absent for THIS feature; run `aw-spec-actions feature-lanes --clear` if it later gains a UI. The SHARED UI surface (app shell, layout, design system) belongs to no slice and stays in {{bundle_dir}}/architecture/frontend.md. NOTE — governance reconcile is currently HELD (reconcile_governance=false): this run did NOT modify the constitution halves or the guardrails/
|
|
1354
|
+
next: "Adopted {{feature_name}} (spec.md + backend-plan.md + source-map.md, v1.0) and wrote {{aggregate_sections}} — the model section(s) for the aggregate(s) it acts on, resolved from the {{aggregate_source}} — in the bounded context `{{context}}`'s shared {{domain_model}}. The spec cites BR-nnn by id, the model carries their text, so this slice is checkable by the same gates as a greenfield one and analyze-plan's check 4 now has a model to check against. A section another feature over the same aggregate wrote first was EXTENDED, never duplicated; every other section is untouched. COMPLETED the OKF concept of {{aggregate_primary}} (deepened + linked the deep artifacts; {{xref_edge_count}} cross-slice edge(s) recorded). UI HALF: ui_lane={{ui_lane}} — where it is true this slice also has frontend-plan.md, reversed from the {{ui_count}} UI file(s) the feature map attributes to it; where it is false the repo declared no frontend lane, or this aggregate owns no part of its surface, and a service-only adoption is the correct outcome rather than a gap. In the second case, where a frontend lane IS declared, the feature records lanes=[backend] in its active_version.json (feature_lanes shows it), so plan and the analyze gates treat the frontend lane as absent for THIS feature; run `aw-spec-actions feature-lanes --clear` if it later gains a UI. The SHARED UI surface (app shell, layout, design system) belongs to no slice and stays in {{bundle_dir}}/architecture/frontend.md. NOTE — governance reconcile is currently HELD (reconcile_governance=false): this run did NOT modify the constitution halves or the guardrails/{{gov_domain}}/ rule set, so they keep onboard's provisional scaffold. Close any items in {{feature_dir}}/adopt-review-report.md out of band. The slice is now a NORMAL feature: refine via /appweaver analyze-plan, then drive every change through the CR delta loop (/appweaver specify → plan → analyze-plan-delta → implement → build → analyze-slice-delta → finalize-delta → analyze-slice → close-delta). If a change edits untested legacy behaviour with blast radius, characterize just that surface first (optional on-touch fence). To restore governance reconcile, set reconcile_governance to \"true\" in the workflow vars."
|
|
@@ -158,7 +158,7 @@ workflow:
|
|
|
158
158
|
with: { command: aw-spec-analyze-slice }
|
|
159
159
|
|
|
160
160
|
# 1. WHICH LANES EXIST. Declaration only — this gate reads code, it does not write it, so
|
|
161
|
-
# it has no reason to require a
|
|
161
|
+
# it has no reason to require a lane root folder on disk.
|
|
162
162
|
- id: lane_resolve
|
|
163
163
|
action: execute_script
|
|
164
164
|
on_error: continue
|
|
@@ -448,7 +448,7 @@ workflow:
|
|
|
448
448
|
the pre-existing slice.
|
|
449
449
|
|
|
450
450
|
CHECK 7 — PLACEMENT. Every file this change added or edited sits under the lane that
|
|
451
|
-
owns it: this lane's production code under its
|
|
451
|
+
owns it: this lane's production code under its lane root folder `{{be_source_path}}`, its
|
|
452
452
|
tests under its test path `{{be_test_path}}`. A service-lane element written into the
|
|
453
453
|
frontend lane's subtree — or outside every lane's paths — is a HIGH `placement` gap.
|
|
454
454
|
One edit outside them is allowed: registering a test project this change created in
|
|
@@ -542,7 +542,7 @@ workflow:
|
|
|
542
542
|
gap. Judge it only over what this change touched.
|
|
543
543
|
|
|
544
544
|
CHECK 7 — PLACEMENT. Every file this change added or edited sits under this lane's
|
|
545
|
-
|
|
545
|
+
lane root folder, `{{fe_source_path}}`, or — for a test — its test path, `{{fe_test_path}}`.
|
|
546
546
|
A file written into the service lane's subtree is a HIGH `placement` gap — a gap in the
|
|
547
547
|
service surface is a contract delta raised back to that lane, never a client-side edit
|
|
548
548
|
to it. The one edit allowed outside them is the test setup this change had to create,
|
|
@@ -85,7 +85,7 @@ scripts:
|
|
|
85
85
|
|
|
86
86
|
# No hardcoded technical standards seed. The technical rule files the code/conformance
|
|
87
87
|
# passes check against (testing + coding-standards) are now CONFIGURATION, loaded per-
|
|
88
|
-
# command from guardrails
|
|
88
|
+
# command from guardrails/<project>/tech-rule-bindings.md under "## /aw-spec-analyze-slice"
|
|
89
89
|
# by the tech-select module (see the tech_select step below). The DOMAIN gate overlays are
|
|
90
90
|
# still loaded separately, as before (resolve_gate_overlays → load_gate_overlays). This gate
|
|
91
91
|
# does not reference constitution.technical.md. The seed below is behaviour-only — the kit's
|
|
@@ -149,7 +149,7 @@ vars:
|
|
|
149
149
|
workflow:
|
|
150
150
|
|
|
151
151
|
# 0. TECHNICAL rule files → sticky standards (configuration, not hardcoded).
|
|
152
|
-
# tech-select reads guardrails
|
|
152
|
+
# tech-select reads guardrails/<project>/tech-rule-bindings.md under
|
|
153
153
|
# "## /aw-spec-analyze-slice" and loads that set (testing + coding-standards) into
|
|
154
154
|
# the sticky standards the conformance query reads (include_standards: true). The
|
|
155
155
|
# DOMAIN gate overlays are loaded separately below. No blocking gate: an unconfigured
|
|
@@ -559,7 +559,7 @@ workflow:
|
|
|
559
559
|
mock: { ok: true, unbound: [], notes: [] }
|
|
560
560
|
task: |
|
|
561
561
|
WOULD THIS SLICE RUN? Check the service lane's composition against its code.
|
|
562
|
-
The lane is `{{be_lane_id}}` and its
|
|
562
|
+
The lane is `{{be_lane_id}}` and its lane root folder is `{{be_source_path}}`; the
|
|
563
563
|
backend plan is in context, and its §2.1 Ports, §4.1 Persistence and §4.3 Wiring
|
|
564
564
|
say what has to be bound.
|
|
565
565
|
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
# compiled by its own build command, so what this stage needs is a declaration to compile
|
|
27
27
|
# from, not a particular kind of one; requiring the service lane blocked a frontend-only
|
|
28
28
|
# project that `plan` and `implement` both accept. The rest of the gate is unchanged: no
|
|
29
|
-
# lane declared, a lane with no
|
|
29
|
+
# lane declared, a lane with no lane root folder, a lane root folder that is not on disk, and two
|
|
30
30
|
# lanes claiming overlapping subtrees all still stop the run.
|
|
31
31
|
#
|
|
32
32
|
# Launch: /appweaver build [strategy]
|
|
@@ -48,7 +48,7 @@ scripts:
|
|
|
48
48
|
|
|
49
49
|
# Sticky standards seed = the UNIVERSAL always-on rule only (ai-rules). The technical
|
|
50
50
|
# rule files (the compile/fix reference set) are CONFIGURATION, loaded per-command from
|
|
51
|
-
# guardrails
|
|
51
|
+
# guardrails/<project>/tech-rule-bindings.md by the tech-select module (see the
|
|
52
52
|
# tech_select step below). Technical rules ONLY — build loads no domain rules and does
|
|
53
53
|
# not reference constitution.technical.md. A required file that is missing is reported
|
|
54
54
|
# at assembly time (`[system] MISSING (required)`), an `optional:` one is skipped.
|
|
@@ -61,7 +61,7 @@ vars:
|
|
|
61
61
|
workflow:
|
|
62
62
|
|
|
63
63
|
# Rule files → sticky standards: TECHNICAL only, via tech-select, read from
|
|
64
|
-
# guardrails
|
|
64
|
+
# guardrails/<project>/tech-rule-bindings.md under "## /aw-spec-build".
|
|
65
65
|
# NO domain-select here — see the header: build repairs compile errors, a purely
|
|
66
66
|
# technical job, and the domain never reaches this stage anyway (specify is its sole
|
|
67
67
|
# carrier; build reads code and design intent, not spec).
|
|
@@ -90,7 +90,7 @@ workflow:
|
|
|
90
90
|
# project compiles the one it has, whichever kind that is. A frontend-only project is a
|
|
91
91
|
# legal project: `plan` and `implement` both accept one, so refusing it here stopped it
|
|
92
92
|
# at the first stage that had no reason to care. Passing no required kind leaves every
|
|
93
|
-
# other check armed — no lane declared at all, a lane with no
|
|
93
|
+
# other check armed — no lane declared at all, a lane with no lane root folder, a lane root folder
|
|
94
94
|
# that is not on disk, and two lanes claiming overlapping subtrees.
|
|
95
95
|
- id: lane_gate
|
|
96
96
|
action: include
|
|
@@ -58,7 +58,7 @@ scripts:
|
|
|
58
58
|
# Sticky standards seed = the UNIVERSAL always-on rule only (ai-rules). The FRAMEWORK /
|
|
59
59
|
# test-generation set (same as implement/analyze-slice — HOW to write + place tests) is no
|
|
60
60
|
# longer hardcoded here — it is now CONFIGURATION, loaded per-command from
|
|
61
|
-
# guardrails
|
|
61
|
+
# guardrails/<project>/tech-rule-bindings.md under "## /aw-spec-characterize" by the
|
|
62
62
|
# tech-select module (see the tech_select step below). No domain files: the behaviour to
|
|
63
63
|
# fence comes from the CODE + the adopted spec/design/source-map (constitution.technical.md
|
|
64
64
|
# is referred to directly as context), not from domain rules — the tech map lists only
|
|
@@ -79,7 +79,7 @@ vars:
|
|
|
79
79
|
workflow:
|
|
80
80
|
|
|
81
81
|
# 0. TECHNICAL rule files → sticky standards (configuration, not hardcoded). tech-select
|
|
82
|
-
# reads guardrails
|
|
82
|
+
# reads guardrails/<project>/tech-rule-bindings.md under "## /aw-spec-characterize"
|
|
83
83
|
# and loads that test-generation set into the sticky standards the agent_generate steps
|
|
84
84
|
# ALWAYS prepend. No domain rule file is loaded here — the tech map lists only technical
|
|
85
85
|
# files. No blocking gate: an unconfigured project soft-continues (the golden-master is
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
# aw-spec-constitution (orchestrator) — create/update the SPLIT project constitution
|
|
3
3
|
#
|
|
4
4
|
# Authors up to THREE files. Each ratifies its own MAPPED rule set. The two maps live in
|
|
5
|
-
# the ACTIVE PROJECT (guardrails
|
|
5
|
+
# the ACTIVE PROJECT (guardrails/<project>/); the files they list live in the
|
|
6
6
|
# shared corpora (guardrails/technology/<stack>/, guardrails/domain/<industry>/), except
|
|
7
7
|
# the three the project's own team authors:
|
|
8
8
|
# .appweaver/memory/constitution.technical.md ← "## /aw-spec-constitution" in
|
|
@@ -72,6 +72,13 @@
|
|
|
72
72
|
# a bounded self-correction loop (max 3) — so the whole skill works under every
|
|
73
73
|
# strategy (sdk/sdk-apply/spawn/agent), --checkpoint, or headless.
|
|
74
74
|
#
|
|
75
|
+
# THE DEFAULT SCOPE. On a project with no specs yet the run ends by creating the bounded
|
|
76
|
+
# context MainContext and its feature CoreFeature (specs/MainContext/CoreFeature/) and
|
|
77
|
+
# making both active, so a simple project goes from constitution straight to specify.
|
|
78
|
+
# Any other state is left alone. A developer who wants other names runs
|
|
79
|
+
# select-bounded-context and select-feature, which re-point both pointer files; the empty
|
|
80
|
+
# default folders can then be deleted.
|
|
81
|
+
#
|
|
75
82
|
# NOT part of the per-feature pipeline. Project-level, run-once / amend-on-change.
|
|
76
83
|
#
|
|
77
84
|
# Launch: /appweaver constitution [strategy] [principles or values…]
|
|
@@ -79,8 +86,8 @@
|
|
|
79
86
|
# =============================================================================
|
|
80
87
|
|
|
81
88
|
name: aw-spec-constitution
|
|
82
|
-
description: Create or update the split project constitution — constitution.technical.md (technology base) + constitution.ui.md (the frontend lane's base, only where a lane exists) + constitution.domain.md (active domain addenda), each version-bumped with a Sync Impact Report, then composed into constitution.md. Project-level, run-once/amend — not a per-feature phase.
|
|
83
|
-
version: 2.
|
|
89
|
+
description: Create or update the split project constitution — constitution.technical.md (technology base) + constitution.ui.md (the frontend lane's base, only where a lane exists) + constitution.domain.md (active domain addenda), each version-bumped with a Sync Impact Report, then composed into constitution.md. On a project with no specs yet it also creates and activates the default bounded context MainContext and its feature CoreFeature. Project-level, run-once/amend — not a per-feature phase.
|
|
90
|
+
version: 2.6.0
|
|
84
91
|
agent_agnostic: true
|
|
85
92
|
dialect: aw-spec.orchestrator/v1
|
|
86
93
|
|
|
@@ -97,7 +104,7 @@ scripts:
|
|
|
97
104
|
|
|
98
105
|
# Sticky standards seed = the UNIVERSAL always-on rule only (ai-rules). The technology-
|
|
99
106
|
# constitution base the TECHNICAL half ratifies is no longer hardcoded here — it is now
|
|
100
|
-
# CONFIGURATION, loaded per-command from guardrails
|
|
107
|
+
# CONFIGURATION, loaded per-command from guardrails/<project>/tech-rule-bindings.md
|
|
101
108
|
# under "## /aw-spec-constitution" by the tech-select module (see the tech_select step
|
|
102
109
|
# below). tech_select runs BEFORE the technical half AND before domain-select, so the
|
|
103
110
|
# technical author still sees only the technology base + ai-rules — NO domain file: the
|
|
@@ -112,6 +119,11 @@ vars:
|
|
|
112
119
|
domain_ok: "false" # domain-half validation-loop guard, flipped by constitution-verify
|
|
113
120
|
ui_ok: "false" # UI-half validation-loop guard, flipped by constitution-verify
|
|
114
121
|
ui_lane: "false" # set by the three-signal probe below; gates the whole UI block
|
|
122
|
+
default_context: "MainContext" # the bounded context a project with no specs yet starts in
|
|
123
|
+
default_feature: "CoreFeature" # the feature created inside it and made active
|
|
124
|
+
scope_created: "false" # default-scope: whether this run created the pair
|
|
125
|
+
scope_skipped: "" # default-scope: why it did not, when it did not
|
|
126
|
+
active_feature_dir: "" # default-scope: the active feature after the step
|
|
115
127
|
|
|
116
128
|
workflow:
|
|
117
129
|
|
|
@@ -121,7 +133,7 @@ workflow:
|
|
|
121
133
|
# what makes `(none)` in select-stack a real declaration rather than a shrug.
|
|
122
134
|
#
|
|
123
135
|
# --allow-missing-root because nothing here reads the subtree: constitution
|
|
124
|
-
# ratifies rules, and a greenfield project's
|
|
136
|
+
# ratifies rules, and a greenfield project's lane root folder does not exist until
|
|
125
137
|
# implement creates it. The on-disk check belongs to the phases that read code.
|
|
126
138
|
- id: lane_model
|
|
127
139
|
action: execute_script
|
|
@@ -179,7 +191,7 @@ workflow:
|
|
|
179
191
|
vars: { svc_lane: "true", setup_tech_flag: "" }
|
|
180
192
|
|
|
181
193
|
# 0. TECHNICAL rule files → sticky standards (configuration, not hardcoded). tech-select
|
|
182
|
-
# reads guardrails
|
|
194
|
+
# reads guardrails/<project>/tech-rule-bindings.md under "## /aw-spec-constitution"
|
|
183
195
|
# and loads the technology-constitution base into the sticky standards the TECHNICAL
|
|
184
196
|
# half ratifies. Placed FIRST — before the technical half AND before domain-select — so
|
|
185
197
|
# the technical author sees only technical files: the seam that keeps it domain-free is
|
|
@@ -376,7 +388,7 @@ workflow:
|
|
|
376
388
|
vars:
|
|
377
389
|
ui_lane: "true"
|
|
378
390
|
ui_stack: "{{fe_lane_profile}}"
|
|
379
|
-
ui_evidence: "lane '{{fe_lane_id}}' ({{fe_lane_profile}}) is declared in .appweaver/stacks.json, owning the
|
|
391
|
+
ui_evidence: "lane '{{fe_lane_id}}' ({{fe_lane_profile}}) is declared in .appweaver/stacks.json, owning the lane root folder {{fe_lane_root}}"
|
|
380
392
|
|
|
381
393
|
# 9. A mapped UI rule set with no lane to govern. Not fatal and not a reason to
|
|
382
394
|
# author the half — the declaration decides that — but worth saying out loud,
|
|
@@ -405,8 +417,8 @@ workflow:
|
|
|
405
417
|
No frontend lane in .appweaver/stacks.json — skipping the UI constitution half
|
|
406
418
|
(constitution.ui.md is not created). This is the expected path for a backend-only
|
|
407
419
|
project. To author it, run `/appweaver select-stack`, pick a UI stack and give
|
|
408
|
-
it a
|
|
409
|
-
`## /aw-spec-ui-constitution` in guardrails
|
|
420
|
+
it a lane root folder, then re-run `/appweaver constitution`. Mapping
|
|
421
|
+
`## /aw-spec-ui-constitution` in guardrails/<project>/tech-rule-bindings.md
|
|
410
422
|
supplies the rules that half ratifies, but no longer creates the lane on its own —
|
|
411
423
|
a lane exists because the project declared it.
|
|
412
424
|
|
|
@@ -693,7 +705,41 @@ workflow:
|
|
|
693
705
|
removed automatically. Delete that file by hand if the lane is gone for good and
|
|
694
706
|
re-run; otherwise restore the lane's signal.
|
|
695
707
|
|
|
696
|
-
# 21.
|
|
708
|
+
# 21. THE DEFAULT SCOPE. A project with no specs yet gets the bounded context named by
|
|
709
|
+
# default_context and the feature named by default_feature inside it, both made
|
|
710
|
+
# active, so /appweaver specify can run next with no select command in between.
|
|
711
|
+
# default-scope acts only when specs/ holds no directory and no feature is active;
|
|
712
|
+
# every other state is reported as skipped and left untouched, so amending the
|
|
713
|
+
# constitution never moves the active feature and an onboarded brownfield tree is
|
|
714
|
+
# never added to.
|
|
715
|
+
- id: default_scope
|
|
716
|
+
action: execute_script
|
|
717
|
+
script: { ref: actions }
|
|
718
|
+
subcommand: default-scope
|
|
719
|
+
args: ["--context", "{{default_context}}", "--feature", "{{default_feature}}"]
|
|
720
|
+
outputs:
|
|
721
|
+
- { name: scope_created, from: "$.created" }
|
|
722
|
+
- { name: scope_skipped, from: "$.skipped_reason" }
|
|
723
|
+
- { name: active_feature_dir, from: "$.feature_dir" }
|
|
724
|
+
|
|
725
|
+
# 21b. Say what was created and how to choose other names. The never-satisfiable
|
|
726
|
+
# `equals` is the engine's announce-only idiom: the step is entered only when the
|
|
727
|
+
# pair was created, and the comparison always misses, so the message is emitted
|
|
728
|
+
# and the run continues.
|
|
729
|
+
- id: default_scope_notice
|
|
730
|
+
action: verify_context
|
|
731
|
+
condition: "{{scope_created}} == true"
|
|
732
|
+
require_value: scope_created
|
|
733
|
+
equals: "never"
|
|
734
|
+
on_mismatch: continue
|
|
735
|
+
on_mismatch_message: >
|
|
736
|
+
Created the default bounded context {{default_context}} and its feature
|
|
737
|
+
{{default_feature}} at {{active_feature_dir}}/ and made both active, so
|
|
738
|
+
/appweaver specify <what it does> can run next. To use your own names instead, run
|
|
739
|
+
/appweaver select-bounded-context <Name> and then /appweaver select-feature <Name>;
|
|
740
|
+
the empty default folders can then be deleted.
|
|
741
|
+
|
|
742
|
+
# 22. Post-execution hooks.
|
|
697
743
|
- id: resolve_post_hooks
|
|
698
744
|
action: execute_script
|
|
699
745
|
script: { ref: actions }
|
|
@@ -723,5 +769,8 @@ outputs:
|
|
|
723
769
|
ui_rule_files: "{{ui_rule_files}}"
|
|
724
770
|
ui_validation_ok: "{{ui_ok}}"
|
|
725
771
|
ui_validation_issues: "{{ui_issues}}"
|
|
726
|
-
|
|
727
|
-
|
|
772
|
+
default_scope_created: "{{scope_created}}"
|
|
773
|
+
default_scope_skipped: "{{scope_skipped}}"
|
|
774
|
+
active_feature: "{{active_feature_dir}}"
|
|
775
|
+
note: "Split constitution authored, one half per LANE the project declared in .appweaver/stacks.json. service_lane / ui_lane report which lanes were found there, and the declaration is the ONLY signal read: a half is a lane's standing governance, so a lane declared `(none)` in select-stack gets no half AND no file. constitution.technical.md is the service lane's base (standing input to the SERVICE lane of plan + implement); constitution.ui.md is the UI lane's UX-* base (standing input to their FRONTEND lane); constitution.domain.md is the domain addenda (standing input to specify + a gate checklist), and it is always authored because domain is not a lane — it addends whichever halves exist. All are composed into constitution.md, which now tolerates an absent technical half: a UI-only project's domain half opens the roman-numeral sequence at I instead of continuing one, and numbering_checked reports false because that check has no subject rather than because it silently passed. Mapping ## /aw-spec-ui-constitution supplies the rules the UI half ratifies but no longer creates the lane on its own — a mapped rule set with no declared lane produces a warning naming both fixes. ui_lane false with ui_included true means a lane was retired after its half was authored: the file is left alone and the log says so, because a ratified governance file is never deleted automatically. If a validation_ok is false, the matching validation_issues lists what still needs a manual touch. See each half's Sync Impact Report for its version bump. DEFAULT SCOPE: on a project with no specs yet this run created the bounded context {{default_context}} and its feature {{default_feature}} and made both active (default_scope_created true); any other state is left untouched and default_scope_skipped says why. active_feature is the feature specify will write to. Suggested commit: 'docs: amend split constitution'."
|
|
776
|
+
next: "/appweaver specify <what the feature does> when active_feature is set — on a project with no specs yet that is the default {{default_context}}/{{default_feature}} this run created. To use your own names, run /appweaver select-bounded-context <Name> and then /appweaver select-feature <Name> first; the empty default folders can then be deleted. When no feature is active, run /appweaver select-feature first — every stage from specify onward reads the active feature and stops without it; if the repo uses bounded contexts, pick one with /appweaver select-bounded-context before it, since once any context exists select-feature refuses to run without one. From specify the greenfield sequence runs plan → analyze-plan → implement → build → analyze-slice → run → deploy. THE HALVES ARE LOADED PER CONCERN, not all at once — /appweaver specify loads constitution.domain.md; the SERVICE lane of plan + implement loads constitution.technical.md; their FRONTEND lane loads constitution.ui.md. Re-run /appweaver constitution to amend, including to pick up a lane declared or dropped after this run — re-run /appweaver select-stack first to change which lanes exist."
|