aw-spec-cli 0.1.8 → 0.1.9

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.
Files changed (257) hide show
  1. package/assets/.appweaver/DESIGN-FORMAT.md +200 -0
  2. package/assets/.appweaver/ORCH-DIALECT.md +156 -0
  3. package/assets/.appweaver/RULE-PARTITION.md +175 -0
  4. package/assets/.appweaver/STACK-PROFILES.md +461 -0
  5. package/assets/.appweaver/ai-rules.md +180 -0
  6. package/assets/.appweaver/domain.json +1 -0
  7. package/assets/.appweaver/extensions/.registry +19 -0
  8. package/assets/.appweaver/extensions/agent-context/README.md +57 -0
  9. package/assets/.appweaver/extensions/agent-context/agent-context-config.yml +4 -0
  10. package/assets/.appweaver/extensions/agent-context/commands/aw-spec.agent-context.update.md +26 -0
  11. package/assets/.appweaver/extensions/agent-context/extension.yml +37 -0
  12. package/assets/.appweaver/extensions/agent-context/scripts/bash/update-agent-context.sh +201 -0
  13. package/assets/.appweaver/extensions/agent-context/scripts/powershell/update-agent-context.ps1 +237 -0
  14. package/assets/.appweaver/extensions.yml +16 -0
  15. package/assets/.appweaver/feature.json +3 -0
  16. package/assets/.appweaver/init-options.json +9 -0
  17. package/assets/.appweaver/integration.json +15 -0
  18. package/assets/.appweaver/integrations/aw-spec.manifest.json +9 -0
  19. package/assets/.appweaver/interpreter/run-skill.py +1176 -0
  20. package/assets/.appweaver/memory/constitution.md +50 -0
  21. package/assets/.appweaver/orchestrator/.smoke-out/smoke.md +6 -0
  22. package/assets/.appweaver/orchestrator/AGENT-PROFILE.md +94 -0
  23. package/assets/.appweaver/orchestrator/README.md +300 -0
  24. package/assets/.appweaver/orchestrator/adapters/claude_agent_sdk.py +74 -0
  25. package/assets/.appweaver/orchestrator/adapters/google_antigravity.py +74 -0
  26. package/assets/.appweaver/orchestrator/modules/delta-design.orch.yaml +105 -0
  27. package/assets/.appweaver/orchestrator/modules/delta-spec.orch.yaml +101 -0
  28. package/assets/.appweaver/orchestrator/modules/domain-select.orch.yaml +90 -0
  29. package/assets/.appweaver/orchestrator/modules/lane-gate.orch.yaml +126 -0
  30. package/assets/.appweaver/orchestrator/modules/tech-select.orch.yaml +123 -0
  31. package/assets/.appweaver/orchestrator/orchestrator.py +1721 -0
  32. package/assets/.appweaver/orchestrator/rev-templates/ai-rules.reference.md +40 -0
  33. package/assets/.appweaver/orchestrator/rev-templates/delta-design-template.skeleton.md +101 -0
  34. package/assets/.appweaver/orchestrator/rev-templates/design-template.skeleton.md +245 -0
  35. package/assets/.appweaver/orchestrator/rev-templates/domain-constitution.skeleton.md +63 -0
  36. package/assets/.appweaver/orchestrator/rev-templates/domain-requirements.skeleton.md +48 -0
  37. package/assets/.appweaver/orchestrator/rev-templates/domain-rule-bindings.skeleton.md +59 -0
  38. package/assets/.appweaver/orchestrator/rev-templates/domain-rule-file.skeleton.md +39 -0
  39. package/assets/.appweaver/orchestrator/rev-templates/frontend-rule-file.skeleton.md +63 -0
  40. package/assets/.appweaver/orchestrator/rev-templates/tech-rule-bindings.skeleton.md +116 -0
  41. package/assets/.appweaver/orchestrator/rev-templates/technical-constitution.skeleton.md +106 -0
  42. package/assets/.appweaver/orchestrator/rev-templates/technical-rule-file.skeleton.md +54 -0
  43. package/assets/.appweaver/orchestrator/rev-templates/ui-constitution.skeleton.md +125 -0
  44. package/assets/.appweaver/orchestrator/rev-templates/ui-delta-design-template.skeleton.md +123 -0
  45. package/assets/.appweaver/orchestrator/rev-templates/ui-design-template.skeleton.md +294 -0
  46. package/assets/.appweaver/orchestrator/workflows/_smoke.orch.yaml +160 -0
  47. package/assets/.appweaver/orchestrator/workflows/aw-spec-add-component.orch.yaml +270 -0
  48. package/assets/.appweaver/orchestrator/workflows/aw-spec-adopt.orch.yaml +934 -0
  49. package/assets/.appweaver/orchestrator/workflows/aw-spec-analyze-delta-design.orch.yaml +251 -0
  50. package/assets/.appweaver/orchestrator/workflows/aw-spec-analyze-design.orch.yaml +265 -0
  51. package/assets/.appweaver/orchestrator/workflows/aw-spec-analyze-slice.orch.yaml +437 -0
  52. package/assets/.appweaver/orchestrator/workflows/aw-spec-build.orch.yaml +197 -0
  53. package/assets/.appweaver/orchestrator/workflows/aw-spec-characterize.orch.yaml +475 -0
  54. package/assets/.appweaver/orchestrator/workflows/aw-spec-close-delta.orch.yaml +181 -0
  55. package/assets/.appweaver/orchestrator/workflows/aw-spec-constitution.orch.yaml +727 -0
  56. package/assets/.appweaver/orchestrator/workflows/aw-spec-demo.orch.yaml +100 -0
  57. package/assets/.appweaver/orchestrator/workflows/aw-spec-dependency-tree.orch.yaml +69 -0
  58. package/assets/.appweaver/orchestrator/workflows/aw-spec-deploy.orch.yaml +85 -0
  59. package/assets/.appweaver/orchestrator/workflows/aw-spec-design-ui.orch.yaml +386 -0
  60. package/assets/.appweaver/orchestrator/workflows/aw-spec-design.orch.yaml +382 -0
  61. package/assets/.appweaver/orchestrator/workflows/aw-spec-finalize-delta.orch.yaml +462 -0
  62. package/assets/.appweaver/orchestrator/workflows/aw-spec-foundation.orch.yaml +265 -0
  63. package/assets/.appweaver/orchestrator/workflows/aw-spec-implement-delta.orch.yaml +253 -0
  64. package/assets/.appweaver/orchestrator/workflows/aw-spec-implement-ui.orch.yaml +267 -0
  65. package/assets/.appweaver/orchestrator/workflows/aw-spec-implement.orch.yaml +287 -0
  66. package/assets/.appweaver/orchestrator/workflows/aw-spec-inventory.orch.yaml +238 -0
  67. package/assets/.appweaver/orchestrator/workflows/aw-spec-onboard.orch.yaml +1822 -0
  68. package/assets/.appweaver/orchestrator/workflows/aw-spec-parity.orch.yaml +293 -0
  69. package/assets/.appweaver/orchestrator/workflows/aw-spec-run.orch.yaml +194 -0
  70. package/assets/.appweaver/orchestrator/workflows/aw-spec-select-domain.orch.yaml +83 -0
  71. package/assets/.appweaver/orchestrator/workflows/aw-spec-select-feature.orch.yaml +128 -0
  72. package/assets/.appweaver/orchestrator/workflows/aw-spec-select-stack.orch.yaml +296 -0
  73. package/assets/.appweaver/orchestrator/workflows/aw-spec-specify.orch.yaml +439 -0
  74. package/assets/.appweaver/scripts/bash/aw-inventory.sh +17 -0
  75. package/assets/.appweaver/scripts/bash/aw-parity.sh +13 -0
  76. package/assets/.appweaver/scripts/bash/aw-rev-constitution.sh +13 -0
  77. package/assets/.appweaver/scripts/bash/aw-spec-actions.sh +2626 -0
  78. package/assets/.appweaver/scripts/bash/aw-xref.sh +15 -0
  79. package/assets/.appweaver/scripts/bash/common.sh +533 -0
  80. package/assets/.appweaver/scripts/powershell/aw-inventory.ps1 +17 -0
  81. package/assets/.appweaver/scripts/powershell/aw-parity.ps1 +13 -0
  82. package/assets/.appweaver/scripts/powershell/aw-rev-constitution.ps1 +13 -0
  83. package/assets/.appweaver/scripts/powershell/aw-spec-actions.ps1 +2232 -0
  84. package/assets/.appweaver/scripts/powershell/aw-xref.ps1 +15 -0
  85. package/assets/.appweaver/scripts/python/aw-component-catalog.py +121 -0
  86. package/assets/.appweaver/scripts/python/aw-inventory.py +1180 -0
  87. package/assets/.appweaver/scripts/python/aw-parity.py +380 -0
  88. package/assets/.appweaver/scripts/python/aw-rev-constitution.py +329 -0
  89. package/assets/.appweaver/scripts/python/aw-stack.py +1251 -0
  90. package/assets/.appweaver/scripts/python/aw-xref.py +1330 -0
  91. package/assets/.appweaver/scripts/python/validate_okf.py +352 -0
  92. package/assets/.appweaver/stack-profiles/angular.json +16 -0
  93. package/assets/.appweaver/stack-profiles/blazor-wasm.json +17 -0
  94. package/assets/.appweaver/stack-profiles/dotnet-webapi.json +15 -0
  95. package/assets/.appweaver/stack-profiles/go-chi.json +14 -0
  96. package/assets/.appweaver/stack-profiles/java-spring.json +16 -0
  97. package/assets/.appweaver/stack-profiles/nextjs.json +16 -0
  98. package/assets/.appweaver/stack-profiles/node-express.json +15 -0
  99. package/assets/.appweaver/stack-profiles/python-fastapi.json +16 -0
  100. package/assets/.appweaver/stack-profiles/react-vite.json +17 -0
  101. package/assets/.appweaver/stack-profiles/sveltekit.json +16 -0
  102. package/assets/.appweaver/stack-profiles/vue-vite.json +17 -0
  103. package/assets/.appweaver/stacks.json +3 -0
  104. package/assets/.appweaver/templates/constitution-domain-template.md +116 -0
  105. package/assets/.appweaver/templates/constitution-technical-template.md +108 -0
  106. package/assets/.appweaver/templates/constitution-ui-template.md +116 -0
  107. package/assets/.appweaver/templates/delta-design-template.md +69 -0
  108. package/assets/.appweaver/templates/delta-spec-template.md +63 -0
  109. package/assets/.appweaver/templates/design-template.md +383 -0
  110. package/assets/.appweaver/templates/okf-concept-template.md +114 -0
  111. package/assets/.appweaver/templates/parity-manifest-template.json +49 -0
  112. package/assets/.appweaver/templates/source-map-template.md +85 -0
  113. package/assets/.appweaver/templates/spec-template.md +309 -0
  114. package/assets/.appweaver/templates/ui-design-template.md +273 -0
  115. package/assets/foundations/dotnet/ModularMonolith/ModularMonolith.Reference.pack.txt +25248 -0
  116. package/assets/foundations/dotnet/ModularMonolith/ModularMonolith.pack.txt +5726 -0
  117. package/assets/foundations/dotnet/ModularMonolith/pack-foundation.ps1 +145 -0
  118. package/assets/foundations/dotnet/ModularMonolith/pack-foundation.sh +196 -0
  119. package/assets/foundations/dotnet/ModularMonolith/pack-reference-foundation.ps1 +157 -0
  120. package/assets/foundations/dotnet/ModularMonolith/pack-reference-foundation.sh +209 -0
  121. package/assets/foundations/dotnet/ModularMonolith/unpack-foundation.ps1 +126 -0
  122. package/assets/foundations/dotnet/ModularMonolith/unpack-foundation.sh +217 -0
  123. package/assets/foundations/dotnet/ModularMonolith/unpack-reference-foundation.ps1 +129 -0
  124. package/assets/foundations/dotnet/ModularMonolith/unpack-reference-foundation.sh +218 -0
  125. package/assets/foundations/dotnet/VerticalSlice/VerticalSlice.Reference.pack.txt +19318 -0
  126. package/assets/foundations/dotnet/VerticalSlice/VerticalSlice.pack.txt +2833 -0
  127. package/assets/foundations/dotnet/VerticalSlice/pack-foundation.ps1 +145 -0
  128. package/assets/foundations/dotnet/VerticalSlice/pack-foundation.sh +196 -0
  129. package/assets/foundations/dotnet/VerticalSlice/pack-reference-foundation.ps1 +157 -0
  130. package/assets/foundations/dotnet/VerticalSlice/pack-reference-foundation.sh +209 -0
  131. package/assets/foundations/dotnet/VerticalSlice/unpack-foundation.ps1 +126 -0
  132. package/assets/foundations/dotnet/VerticalSlice/unpack-foundation.sh +217 -0
  133. package/assets/foundations/dotnet/VerticalSlice/unpack-reference-foundation.ps1 +129 -0
  134. package/assets/foundations/dotnet/VerticalSlice/unpack-reference-foundation.sh +218 -0
  135. package/assets/foundations/dotnet/components/Email/README.md +119 -0
  136. package/assets/foundations/dotnet/components/Email/ReferenceEndpoints/SendEmailEndpoint.cs +84 -0
  137. package/assets/foundations/dotnet/components/Email/integration.md +300 -0
  138. package/assets/foundations/dotnet/components/Jobs/README.md +113 -0
  139. package/assets/foundations/dotnet/components/Jobs/integration.md +259 -0
  140. package/assets/foundations/dotnet/components/QrGenerator/README.md +85 -0
  141. package/assets/foundations/dotnet/components/QrGenerator/ReferenceEndpoints/GenerateQrEndpoint.cs +57 -0
  142. package/assets/foundations/dotnet/components/QrGenerator/integration.md +230 -0
  143. package/assets/foundations/dotnet/components/README.md +74 -0
  144. package/assets/guardrails/README.md +222 -0
  145. package/assets/guardrails/domain/healthcare/ai-rules.domain.md +34 -0
  146. package/assets/guardrails/domain/healthcare/api-versioning.domain.md +17 -0
  147. package/assets/guardrails/domain/healthcare/auditing.domain.md +97 -0
  148. package/assets/guardrails/domain/healthcare/authorization.domain.md +26 -0
  149. package/assets/guardrails/domain/healthcare/clinical-terms.md +20 -0
  150. package/assets/guardrails/domain/healthcare/coding-standards.domain.md +26 -0
  151. package/assets/guardrails/domain/healthcare/consent.md +19 -0
  152. package/assets/guardrails/domain/healthcare/cqrs.domain.md +12 -0
  153. package/assets/guardrails/domain/healthcare/data-classification.domain.md +28 -0
  154. package/assets/guardrails/domain/healthcare/dependency-policy.domain.md +11 -0
  155. package/assets/guardrails/domain/healthcare/dicom.md +15 -0
  156. package/assets/guardrails/domain/healthcare/domain-constitution.md +119 -0
  157. package/assets/guardrails/domain/healthcare/domain-driven-design.domain.md +28 -0
  158. package/assets/guardrails/domain/healthcare/eventing.domain.md +18 -0
  159. package/assets/guardrails/domain/healthcare/fhir.md +36 -0
  160. package/assets/guardrails/domain/healthcare/folder-structure.domain.md +25 -0
  161. package/assets/guardrails/domain/healthcare/hipaa.md +34 -0
  162. package/assets/guardrails/domain/healthcare/hl7.md +15 -0
  163. package/assets/guardrails/domain/healthcare/ihe-conformance.md +31 -0
  164. package/assets/guardrails/domain/healthcare/integration-terms.md +21 -0
  165. package/assets/guardrails/domain/healthcare/persistence.domain.md +20 -0
  166. package/assets/guardrails/domain/healthcare/terminology.md +30 -0
  167. package/assets/guardrails/domain/healthcare/testing.domain.md +15 -0
  168. package/assets/guardrails/domain/healthcare/ux/accessibility-standards.md +36 -0
  169. package/assets/guardrails/domain/healthcare/ux/content-design.md +32 -0
  170. package/assets/guardrails/domain/healthcare/ux/interaction-states.md +44 -0
  171. package/assets/guardrails/domain/healthcare/ux/journey-mapping.md +40 -0
  172. package/assets/guardrails/domain/healthcare/vertical-slices.domain.md +18 -0
  173. package/assets/guardrails/domain/healthcare/zero-trust.domain.md +12 -0
  174. package/assets/guardrails/domain/pharma/ai-rules.domain.md +32 -0
  175. package/assets/guardrails/domain/pharma/api-versioning.domain.md +20 -0
  176. package/assets/guardrails/domain/pharma/atc.md +22 -0
  177. package/assets/guardrails/domain/pharma/auditing.domain.md +90 -0
  178. package/assets/guardrails/domain/pharma/authorization.domain.md +25 -0
  179. package/assets/guardrails/domain/pharma/coding-standards.domain.md +28 -0
  180. package/assets/guardrails/domain/pharma/cqrs.domain.md +16 -0
  181. package/assets/guardrails/domain/pharma/data-classification.domain.md +24 -0
  182. package/assets/guardrails/domain/pharma/data-provenance.md +21 -0
  183. package/assets/guardrails/domain/pharma/dependency-policy.domain.md +11 -0
  184. package/assets/guardrails/domain/pharma/domain-constitution.md +113 -0
  185. package/assets/guardrails/domain/pharma/domain-driven-design.domain.md +36 -0
  186. package/assets/guardrails/domain/pharma/domain-requirements.sample.md +103 -0
  187. package/assets/guardrails/domain/pharma/eventing.domain.md +18 -0
  188. package/assets/guardrails/domain/pharma/fhir.md +31 -0
  189. package/assets/guardrails/domain/pharma/folder-structure.domain.md +26 -0
  190. package/assets/guardrails/domain/pharma/hl7.md +17 -0
  191. package/assets/guardrails/domain/pharma/idmp.md +26 -0
  192. package/assets/guardrails/domain/pharma/integration-terms.md +21 -0
  193. package/assets/guardrails/domain/pharma/ndc.md +28 -0
  194. package/assets/guardrails/domain/pharma/persistence.domain.md +23 -0
  195. package/assets/guardrails/domain/pharma/pharma-terms.md +27 -0
  196. package/assets/guardrails/domain/pharma/product-lifecycle.domain.md +30 -0
  197. package/assets/guardrails/domain/pharma/regulatory-compliance.md +19 -0
  198. package/assets/guardrails/domain/pharma/terminology.md +32 -0
  199. package/assets/guardrails/domain/pharma/testing.domain.md +19 -0
  200. package/assets/guardrails/domain/pharma/vertical-slices.domain.md +17 -0
  201. package/assets/guardrails/domain/pharma/zero-trust.domain.md +12 -0
  202. package/assets/guardrails/projects/dotnet-default-project/domain/domain-requirements.md +58 -0
  203. package/assets/guardrails/projects/dotnet-default-project/domain-rule-bindings.md +113 -0
  204. package/assets/guardrails/projects/dotnet-default-project/frontend/ui-requirements.md +43 -0
  205. package/assets/guardrails/projects/dotnet-default-project/service/technical-requirements.md +40 -0
  206. package/assets/guardrails/projects/dotnet-default-project/tech-rule-bindings.md +263 -0
  207. package/assets/guardrails/requirement-spec.txt +27 -0
  208. package/assets/guardrails/technology/dotnet-webapi/PACKAGING.md +184 -0
  209. package/assets/guardrails/technology/dotnet-webapi/api-versioning.md +44 -0
  210. package/assets/guardrails/technology/dotnet-webapi/auditing.md +96 -0
  211. package/assets/guardrails/technology/dotnet-webapi/authorization-matrix.md +14 -0
  212. package/assets/guardrails/technology/dotnet-webapi/authorization.md +39 -0
  213. package/assets/guardrails/technology/dotnet-webapi/clean-architecture.md +54 -0
  214. package/assets/guardrails/technology/dotnet-webapi/coding-standards.md +87 -0
  215. package/assets/guardrails/technology/dotnet-webapi/cqrs.md +63 -0
  216. package/assets/guardrails/technology/dotnet-webapi/data-classification.md +38 -0
  217. package/assets/guardrails/technology/dotnet-webapi/dependency-policy.md +40 -0
  218. package/assets/guardrails/technology/dotnet-webapi/domain-driven-design.md +91 -0
  219. package/assets/guardrails/technology/dotnet-webapi/eventing.md +57 -0
  220. package/assets/guardrails/technology/dotnet-webapi/examples/api-versioning.md +75 -0
  221. package/assets/guardrails/technology/dotnet-webapi/examples/auditing.md +84 -0
  222. package/assets/guardrails/technology/dotnet-webapi/examples/authorization.md +68 -0
  223. package/assets/guardrails/technology/dotnet-webapi/examples/clean-architecture.md +37 -0
  224. package/assets/guardrails/technology/dotnet-webapi/examples/cqrs.md +97 -0
  225. package/assets/guardrails/technology/dotnet-webapi/examples/domain-driven-design.md +141 -0
  226. package/assets/guardrails/technology/dotnet-webapi/examples/eventing.md +46 -0
  227. package/assets/guardrails/technology/dotnet-webapi/examples/persistence.md +207 -0
  228. package/assets/guardrails/technology/dotnet-webapi/examples/vertical-slices.md +151 -0
  229. package/assets/guardrails/technology/dotnet-webapi/examples/zero-trust.md +48 -0
  230. package/assets/guardrails/technology/dotnet-webapi/folder-structure.md +61 -0
  231. package/assets/guardrails/technology/dotnet-webapi/modular-monolith.md +47 -0
  232. package/assets/guardrails/technology/dotnet-webapi/persistence.md +82 -0
  233. package/assets/guardrails/technology/dotnet-webapi/technology-constitution.md +162 -0
  234. package/assets/guardrails/technology/dotnet-webapi/testing.md +55 -0
  235. package/assets/guardrails/technology/dotnet-webapi/vertical-slices.md +70 -0
  236. package/assets/guardrails/technology/dotnet-webapi/zero-trust.md +48 -0
  237. package/assets/guardrails/technology/java-spring/README.md +62 -0
  238. package/assets/guardrails/technology/nextjs/accessibility-implementation.md +56 -0
  239. package/assets/guardrails/technology/nextjs/api-client.md +56 -0
  240. package/assets/guardrails/technology/nextjs/api-integration.dotnet-webapi.md +174 -0
  241. package/assets/guardrails/technology/nextjs/api-integration.java-spring.md +203 -0
  242. package/assets/guardrails/technology/nextjs/auth-session.md +68 -0
  243. package/assets/guardrails/technology/nextjs/client-security.md +69 -0
  244. package/assets/guardrails/technology/nextjs/component-architecture.md +60 -0
  245. package/assets/guardrails/technology/nextjs/component-conventions.md +58 -0
  246. package/assets/guardrails/technology/nextjs/design-system.md +60 -0
  247. package/assets/guardrails/technology/nextjs/error-handling.md +72 -0
  248. package/assets/guardrails/technology/nextjs/forms-and-validation.md +75 -0
  249. package/assets/guardrails/technology/nextjs/frontend-testing.md +94 -0
  250. package/assets/guardrails/technology/nextjs/i18n.md +57 -0
  251. package/assets/guardrails/technology/nextjs/observability.md +67 -0
  252. package/assets/guardrails/technology/nextjs/performance-budgets.md +66 -0
  253. package/assets/guardrails/technology/nextjs/routing-navigation.md +52 -0
  254. package/assets/guardrails/technology/nextjs/state-management.md +70 -0
  255. package/assets/guardrails/technology/nextjs/ui-constitution.md +166 -0
  256. package/package.json +1 -1
  257. package/assets/docs/pharma-constitution.my-ref.md +0 -86
@@ -0,0 +1,461 @@
1
+ # Stack profiles and the lane model
2
+
3
+ Authoritative on two files: `.appweaver/stacks.json` (the lane declaration a project
4
+ makes) and `.appweaver/stack-profiles/*.json` (the candidates it chooses from).
5
+
6
+ `DESIGN-FORMAT.md` is to `design.md` what this document is to `stacks.json`.
7
+
8
+ ---
9
+
10
+ ## 1. What a lane is
11
+
12
+ A **lane** is a technology target that owns disjoint source paths, compiles and tests
13
+ independently, and carries its own technical rules and constitution half — while
14
+ *sharing* the feature, the spec, the domain, the version, and the knowledge bundle with
15
+ every other lane.
16
+
17
+ > One spec, one prototype, two designs, two implements, one build, one version.
18
+
19
+ A lane is not a project, not a module, and not a layer. Two lanes exist when two
20
+ toolchains do, which is why `kind` has exactly two values today (`backend`, `frontend`)
21
+ and why nothing in the format assumes there are only two lanes.
22
+
23
+ **Lanes get command names, never a `--lane` flag.** Rule maps are keyed on
24
+ `## /aw-spec-<command>`, so a lane's phases are reached as `ui-implement`, `ui-foundation`
25
+ and so on. A flag would have no heading to key on.
26
+
27
+ ---
28
+
29
+ ## 2. `.appweaver/stacks.json`
30
+
31
+ ```jsonc
32
+ {
33
+ "lanes": [
34
+ { "id": "service", "kind": "backend", "profile": "dotnet-webapi", "root": "src/",
35
+ "build": "dotnet build", "test": "dotnet test", "run": "dotnet run --project src/" },
36
+ { "id": "web", "kind": "frontend", "profile": "react-vite", "root": "web/",
37
+ "run_from": "root",
38
+ "build": "npm run build", "test": "npm test", "run": "npm run dev" }
39
+ ],
40
+ "prototype": { "root": "prototype/", "run": "npm run dev --prefix prototype" }
41
+ }
42
+ ```
43
+
44
+ | Field | Meaning |
45
+ |---|---|
46
+ | `id` | the lane's **role** in the project (`service`, `web`). Paths, rules and the constitution half hang off it. Defaults: `service` for backend, `web` for frontend |
47
+ | `kind` | `backend` or `frontend` — selects which phases and which rule headings apply |
48
+ | `profile` | the stack profile the lane was declared from. Records the technology, so re-stacking a lane never renames the lane. `detected` where the kit ships no profile for what the code is |
49
+ | `stack` | *(optional)* what the code was found to be, when `profile` is `detected` — e.g. `asp.net-webforms`. The honest record for a legacy lane |
50
+ | `origin` | *(optional)* `reverse-engineered` on a lane `onboard` derived from an existing codebase. Absent means a person declared it, which is the greenfield shape and the historical one |
51
+ | `root` | the lane's **source path** — the subtree it owns (see §3). `--source-path` and `--root` are two spellings of this one field |
52
+ | `run_from` | *(optional)* **where the commands run**: `repo` (the default, and the shape of every lane written before this key existed) at the repository root, or `root` inside the lane's own source path. See §3.1 |
53
+ | `build` / `test` / `run` | project-supplied command strings the engine shells out to. These are the matched **profile's** defaults and may not fit a legacy layout — reviewing them is what `select-stack` is for. `{{root}}` in a command resolves to this lane's `root` (§4.2) |
54
+ | `migrate` | *(optional)* the lane's schema-migration command, recorded only when the profile declares one. Absent, `run-migrate` falls back to `dotnet ef` and otherwise reports that nothing ran (§4.2) |
55
+
56
+ ### Three properties matter more than the schema
57
+
58
+ 1. **`root` is ownership, and it is the source path.** `implement` writes only under a
59
+ backend lane's root, `ui-implement` only under a frontend lane's, `build`/`test`/`run`
60
+ act on it, and `onboard` reverse-engineers out of it.
61
+ 2. **The commands are project-supplied strings.** The engine stays stdlib-only and
62
+ stack-ignorant. This is how `build` already avoids knowing what a compiler is, and it
63
+ is the only thing that makes "any frontend stack" tractable.
64
+ 3. **`prototype` is not a lane.** It has a root and a run command so an operator can look
65
+ at it, and nothing else. It is never built by `build`, never tested by `analyze-slice`,
66
+ never deployed, and never gated.
67
+
68
+ ### 3.1 `root` is where the code is; `run_from` is where the commands run
69
+
70
+ These are two questions and for most stacks they have two answers. `dotnet build` needs the
71
+ solution file at the top while the lane owns `src/`; `go build ./...` needs the go.mod there
72
+ while the lane owns `internal/`. Those profiles leave `run_from` at its default and run at
73
+ the repository root.
74
+
75
+ A stack whose **manifest lives inside the subtree** needs the other answer, and cannot work
76
+ without it: a Maven wrapper at `backend/orderservice/mvnw` is unreachable from the repository
77
+ root, so `java-spring` declares `run_from: "root"`. The five npm frontends and `blazor-wasm`
78
+ declare it too, which is what let their commands stop hardcoding `--prefix web` — the lane
79
+ already declares that directory, and a lane rooted at `client/` was previously building `web/`
80
+ regardless.
81
+
82
+ Two consequences worth knowing:
83
+
84
+ - **Declare a `run_from: "root"` lane at the directory holding its manifest**, not at its
85
+ source directory. `java-spring`'s profile default root is `src/main/java/`, which is where
86
+ the *code* goes; detection proposes the directory `pom.xml` actually sits in, which is the
87
+ one to accept. A lane rooted at `src/main/java/` will fail loudly with `./mvnw: not found`
88
+ rather than silently.
89
+ - **A single-module project declares `.`** — stored as `./`, the repository root. It owns
90
+ everything, so it overlaps every other lane by definition and cannot be combined with one.
91
+
92
+ ### Where the source path is checked against the disk
93
+
94
+ `lane-declare` records a path; it does **not** require the path to exist. In a greenfield
95
+ project it does not exist yet — the whole point of declaring `src/` on day one is that
96
+ `implement` will create it.
97
+
98
+ `lane-verify` is the check, and it runs where the path has to be real: before `implement`,
99
+ `implement-delta`, `build`, `run`, and before `onboard` reverse-engineers a codebase out of
100
+ it. That split is what lets one file serve a project with no code yet and a project that is
101
+ nothing but code.
102
+
103
+ Two failure classes, deliberately distinguished:
104
+
105
+ - **MISSING** — the phase needs a lane of this kind and none is declared. Reported only for
106
+ the kinds a caller names with `--require`, because "no frontend lane" is a correct and
107
+ common state that must never fail a backend build.
108
+ - **BROKEN** — a lane *is* declared and its source path is empty, is not a directory, or
109
+ overlaps another lane's. Checked for **every** declared lane whether or not the caller
110
+ asked about it. A stack named against a path that is not there is a mistake in every
111
+ phase, and letting it through means discovering it as an empty build or a generator
112
+ writing into a directory it created by accident. The overlap check is a second reading of
113
+ a rule `lane-declare` already enforces, and it earns its place because a hand-edited file
114
+ never passes `lane-declare`.
115
+
116
+ ### The file ships empty, and may be filled in by hand
117
+
118
+ The kit installs `.appweaver/stacks.json` holding `{"lanes": []}`, alongside `domain.json` and
119
+ `feature.json`. It is there so a project can open it and fill it in directly — the block at
120
+ the top of this section is the whole schema, and `select-stack` writes nothing a person
121
+ could not have typed.
122
+
123
+ **An empty file and an absent one are the same state.** Shipping the file means its presence
124
+ no longer says anything about whether a lane was declared, so `declared` reports on the
125
+ `lanes` array and never on the file: `resolve` reports `exists: true, declared: false` for
126
+ the untouched seed, and `verify` raises the same "no lane is declared" issue it raises when
127
+ the file is missing, naming which of the two it found.
128
+
129
+ Hand-editing and `select-stack` are the same file and the same schema, so they interleave
130
+ freely: fill in the service lane by hand and run `select-stack` later to add the UI one, or
131
+ run it first and correct a source path in the editor. What hand-editing gives up is the
132
+ checking `select-stack` does on the way in — an unknown `profile`, a missing `root`, and two
133
+ lanes whose roots overlap are all refused there and merely written here. `lane-verify` still
134
+ catches the last two before any phase acts on them; a profile id that matches nothing
135
+ surfaces as a wrong or empty stack later. Running `select-stack` once over a hand-written
136
+ file re-checks all three.
137
+
138
+ ### Absence is not a valid state for a governed project
139
+
140
+ `lane-resolve` still reports `declared: false` and exits 0 when the file is missing — reading
141
+ is never fatal. What changed is that the phases which *act* on a lane no longer proceed
142
+ without one. `constitution`, `onboard`, `implement`, `implement-delta`, `build` and `run` all
143
+ call `lane-verify` and stop with the fix named, because each of them needs an answer this
144
+ file is the only place to get: which lanes to govern, which subtree to scan, where to write.
145
+
146
+ Declaring **`(none)`** for a lane is a real answer and the way a project says it has none.
147
+
148
+ ---
149
+
150
+ ## 3. The ownership rule
151
+
152
+ **Lane roots own their subtree and must be disjoint.** Two generators must never be able
153
+ to write the same file.
154
+
155
+ `lane-declare` refuses a declaration whose root contains, or is contained by, another
156
+ lane's — compared as `/`-terminated paths, so `src/` is clear of `src-gen/` but collides
157
+ with `src/api/`. The refusal is a non-zero exit and **`stacks.json` is left untouched**.
158
+
159
+ This is checked at declaration time on purpose. The alternative — discovering it when two
160
+ implement phases fight over a file — is a much worse place to find out.
161
+
162
+ ---
163
+
164
+ ## 4. Stack profiles — `.appweaver/stack-profiles/*.json`
165
+
166
+ One JSON file per selectable stack. `stack-list` enumerates them; this is the extension
167
+ point, so **a project adds its own stack by dropping a file in here, never by editing a
168
+ workflow.**
169
+
170
+ ```jsonc
171
+ {
172
+ "id": "react-vite", // required — unique, and unique ACROSS kinds
173
+ "kind": "frontend", // required — backend | frontend
174
+ "title": "React + Vite", // shown in the menu
175
+ "language": "TypeScript", // shown in the menu, parenthesised
176
+ "ecosystem": "node", // which stack-partitioned corpus this stack draws from
177
+ "root": "web/", // the lane root this profile defaults to
178
+ "run_from": "root", // where the commands run — see §3.1
179
+ "build": "npm run build",
180
+ "test": "npm test",
181
+ "run": "npm run dev",
182
+ "migrate": "", // optional — schema migration, if the stack has one
183
+ "prototype_run": "npm run dev --prefix prototype", // frontend only — fills the prototype block
184
+ "detect": ["web/package.json", "web/vite.config.*"] // ANY-of markers — how stack-detect recognises this stack
185
+ }
186
+ ```
187
+
188
+ `id` and `kind` are required; a file missing either, or containing invalid JSON, is
189
+ **skipped rather than fatal** — one bad profile must not make the menu unopenable.
190
+
191
+ ### 4.1 `ecosystem` — which stack-partitioned corpus this stack draws from
192
+
193
+ `language` names what a person writes; `ecosystem` names the **toolchain family the kit
194
+ partitions its corpora by**, and the two are not the same question. `dotnet-webapi` and
195
+ `blazor-wasm` are C# and F#-adjacent respectively but share one ecosystem, `dotnet`; the five
196
+ JavaScript frontends and `node-express` share `node`. It is the directory key for the two
197
+ trees that are physically per-ecosystem:
198
+
199
+ | Tree | Keyed by | Read through |
200
+ |---|---|---|
201
+ | `foundations/<ecosystem>/<Name>/` | `ecosystem` | `foundation-list`, `foundation-locate` |
202
+ | `foundations/<ecosystem>/components/<C>/` | `ecosystem` | `list-components`, `add-component` |
203
+
204
+ **Why those two are filtered and the rule corpora are not.** A foundation bundle is a whole
205
+ compiling project and a component runbook edits a host project's build files — both are
206
+ executable artifacts in one toolchain, so offering a `dotnet` bundle to a Spring repo does not
207
+ produce a scaffold, it produces a second foreign project beside the real one. `foundation-list`
208
+ therefore narrows to the declared lanes' ecosystems, and reports `all_foundations` alongside so
209
+ the gate can say *what exists and why none of it applies*. A repo that has declared nothing yet
210
+ is not filtered — there is no answer to filter on.
211
+
212
+ The technical RULE corpora at `guardrails/technology/<stack>/` are keyed by **profile id**, not
213
+ ecosystem, because Spring and Quarkus are both `java` and do not share a persistence rule. They
214
+ are selected through the project's `tech-rule-bindings.md` rather than filtered here — see §7.
215
+
216
+ ### 4.2 `run_from`, `{{root}}` and `migrate`
217
+
218
+ A profile command sometimes has to name the source path — `dotnet run --project src/`. Written
219
+ literally that is the profile's *default* root frozen into the command, and it stays frozen when
220
+ a lane declares a different one. Write **`{{root}}`** instead and it resolves to the lane's own
221
+ root, expanded at run time so a hand-edited `root` in `stacks.json` stays consistent with it:
222
+
223
+ ```jsonc
224
+ "run": "dotnet run --project {{root}}", // Services/Api/ ⇒ dotnet run --project Services/Api
225
+ "build": "python -m compileall {{root}}" // repo-root lane ⇒ python -m compileall .
226
+ ```
227
+
228
+ A command with no placeholder is used verbatim, so every literal command already on disk is
229
+ unaffected. `{{root}}` is the answer when the command needs the *path*; `run_from: "root"` (§3.1)
230
+ is the answer when it needs the *working directory*.
231
+
232
+ `migrate` is an optional fourth phase command, alongside `build`/`test`/`run`. **No shipped
233
+ profile declares one**, deliberately: Flyway, Liquibase, Alembic, Prisma and golang-migrate all
234
+ coexist and no sniffer can pick between them, so a default here would be a guess dressed up as
235
+ configuration. Declare it and `run-migrate` runs it in the lane's working directory like any
236
+ other phase; leave it and `run-migrate` keeps its .NET `dotnet ef` path, reporting `ran:false`
237
+ elsewhere rather than implying a migration succeeded.
238
+
239
+ `detect` is an **ANY-of** list, not an all-of: `java-spring` names both `pom.xml` and
240
+ `build.gradle` because a project has one or the other, and requiring both would make it
241
+ undetectable. `stack-detect` scores a profile by how many of its patterns hit. Patterns are
242
+ matched first as written (repo-root-relative, with `**` spanning separators), then relocated
243
+ under any directory prefix — so a profile shipping `web/package.json` still recognises the
244
+ same stack in `client/` or `apps/portal/`, which a brownfield repo that never saw our
245
+ profiles will need. An anchored hit outranks a relocated one.
246
+
247
+ `detect` and `root` are independent, and deliberately so: `go-chi` detects on `go.mod` at the
248
+ repo root and declares a root of `internal/`. Detection reports the shallowest directory its
249
+ evidence actually sits in, and that directory is what `select-stack` offers first when it asks
250
+ for the lane's source path — ahead of the profile's own default, because a repo that already
251
+ exists did not choose its layout from our profiles. The operator picks from the list or types
252
+ a path the kit has never seen.
253
+
254
+ **Detection leads the menu; it never fills `preselect`.** The engine treats `preselect_from`
255
+ as the answer, ahead of a headless `--select`, so filling it from a scan would let a repo's
256
+ files silently overrule an operator who named a stack on the command line. Leading the option
257
+ list is the right strength for a proposal — it is what an interactive menu opens on and what
258
+ `--non-interactive` takes, and both remain choices anyone can override.
259
+
260
+ **Profile ids must be unique across kinds, not just within one.** The direct-argument fast
261
+ path (`select-stack dotnet-webapi react-vite`) matches each id against its own kind's list,
262
+ and that is what lets a single argument answer both selections unambiguously. An id
263
+ appearing under two kinds breaks it.
264
+
265
+ The menu label is `<id> — <title> (<language>)`, and the id is its leading token. That is
266
+ the contract between `stack-list` and `lane-declare`: `--profile` accepts either a bare id
267
+ or a full menu label.
268
+
269
+ **The id is also what `lane-probe` looks for in free prose** — the whole id and its `-`/`_`
270
+ parts of three characters or more, so `react-vite` is found by "react". `title` and `language`
271
+ are deliberately *not* searched: "TypeScript", "Next" and "Web" all appear in ordinary prose
272
+ about a backend, and the two errors are not symmetric. A false positive authors a governed file
273
+ the project never asked for; a false negative only produces a warning that names the fix. Pick
274
+ ids accordingly — a profile whose id is a common English word will be matched too eagerly.
275
+
276
+ ---
277
+
278
+ ## 5. Who may write this file
279
+
280
+ **`lane-declare` writes it. Nothing else does, and it has exactly ONE caller** — so the
281
+ rule is a grep, not a convention:
282
+
283
+ ```sh
284
+ grep -rl "lane-declare" .appweaver/orchestrator/workflows/ # must print exactly one file
285
+ # aw-spec-select-stack.orch.yaml — a person picks
286
+ ```
287
+
288
+ `onboard` used to be a second caller. Before `select-stack` was the first command of the
289
+ brownfield sequence a repo could reach `onboard` undeclared, so `onboard` ran its own
290
+ detection pass, recorded what it found marked `origin: reverse-engineered`, and was gated
291
+ never to overwrite a lane a person had confirmed. With the declaration now **required** at
292
+ the top of `onboard` — it is what tells the scan which subtrees to read — that gate can
293
+ never open, and the pass was re-deriving an answer the run already had. The detection moved
294
+ to where a person can see it: `stack-list --suggest`, inside `select-stack`.
295
+
296
+ The `origin` key stays in the schema and stays optional. Nothing writes
297
+ `reverse-engineered` today; a future caller that proposes a lane without a person in the
298
+ loop would, and readers that branch on it keep working.
299
+
300
+ `lane-resolve` reads and can never write, which is why these are separate subcommands
301
+ rather than one with a mode flag: a reader that could write, given the wrong argument,
302
+ gives up the property. `lane-verify` cannot write either, and always exits 0 — the calling
303
+ workflow's gate owns the stop, so the reason reaches it as text instead of as an exit code
304
+ nobody sees.
305
+
306
+ **A person with a text editor is not a violation of this** — it is the other supported way
307
+ to fill the file in, and the kit ships it empty for that. "One writer" is a rule about the
308
+ *kit*: no second workflow may reach in and set a lane behind the operator's back. What it
309
+ costs is that a hand-edited file skips the writer's checks, which is why `lane-verify`
310
+ re-runs the roots-disjoint one on every read (see §2).
311
+
312
+ Consequences worth stating, because they are the reason for the design:
313
+
314
+ - **`foundation` / `ui-foundation` scaffold *against* a declared lane** and verify what
315
+ they produced against it — stopping `STACK-MISMATCH:` rather than rewriting the
316
+ declaration to fit the scaffold. A wrong declaration surfaces at the scaffold instead of
317
+ being absorbed by it, and the lane a project *chose* stays the authority over the lane a
318
+ generator *happened to produce*.
319
+ - **`build` runs every declared lane's own build command**, in declaration order, and
320
+ fails if any lane fails. Without a declaration it falls back to the historic
321
+ first-match-wins sniffer, which is right for one lane and silently skips the second —
322
+ reporting green for a frontend it never compiled.
323
+
324
+ ## 5a. What this file IS for
325
+
326
+ **It records which lanes a project has.** That is its first job, and everything else
327
+ follows from it:
328
+
329
+ | Question | Answered by |
330
+ |---|---|
331
+ | Which constitution halves does this project ratify? | a declared service lane ⇒ `constitution.technical.md`; a declared UI lane ⇒ `constitution.ui.md`. `(none)` ⇒ no half, and no file |
332
+ | Which rule sets does `onboard` generate? | the same, per lane — `service/` and `frontend/` under the project folder |
333
+ | Which subtree does `implement` write into? | that lane's `root` |
334
+ | What does `build` compile, and `run` migrate? | every declared lane's own command, against its own root |
335
+ | What does `onboard` scan? | the declared source paths — backend signals from outside the UI subtree, frontend signals from inside it |
336
+
337
+ This is a change of authority, and worth being explicit about. The question "does this
338
+ project have a UI lane" used to be answered by OR-ing three heuristics: a
339
+ `## /aw-spec-ui-constitution` heading in the technical rule map, a frontend lane in this
340
+ file, and a UI stack named in the request. A heuristic OR can only ever turn a lane **on**.
341
+ It had no way to express *this project has no UI*, so a stale heading or the word "react" in
342
+ a request authored a ratified governance file for a lane that does not exist.
343
+
344
+ The declaration answers in both directions, and it is the same file `build`, `implement` and
345
+ `onboard` are held to. So it decides — and the rule map goes back to doing the job it is
346
+ good at: **supplying the rules a lane's half ratifies**, not asserting that the lane exists.
347
+ A mapped `## /aw-spec-ui-constitution` with no declared lane is reported as an
348
+ inconsistency, naming both fixes (declare the lane, or drop the mapping if it was retired).
349
+
350
+ `stacks.json` also serves the steps a rule file cannot reach: `build`, `analyze-slice`, `run`
351
+ and `deploy` shell out from `execute_script` steps, and a bash script cannot read a markdown
352
+ rule. Supplying the commands here is what stops them guessing.
353
+
354
+ Choosing `(none)` for either lane routes through the same writer, which is what makes a
355
+ re-run correct: a lane declared in an earlier run is removed — along with the `prototype`
356
+ block for a retired frontend — rather than left stranded.
357
+
358
+ ## 5b. The starting sequence
359
+
360
+ `select-stack` is the **first command of both sequences**, and the setup order now has one
361
+ constraint where it previously had none. That is a deliberate trade: what it buys is that
362
+ every later phase can ask this file a question and get an answer, instead of inferring one.
363
+
364
+ ```
365
+ GREENFIELD select-stack → select-domain → constitution → select-feature → specify → …
366
+ BROWNFIELD select-stack → onboard → select-feature → adopt → …
367
+ ```
368
+
369
+ `select-domain` is greenfield-only: `onboard` derives the project from the code and
370
+ activates it. On an existing codebase `select-stack` is mostly confirmation — it detects the
371
+ stack and the source path from the repo's own files and leads the menu with them — but it is
372
+ a person's confirmation, which is what detection on a legacy repo needs.
373
+
374
+ ## 6. Subcommands
375
+
376
+ Deterministic work lives in `aw-spec-actions` — **a true bash + powershell pair.** Both
377
+ shells delegate to `.appweaver/scripts/python/aw-stack.py`, so the JSON contract has one
378
+ implementation and the twins cannot drift.
379
+
380
+ | Subcommand | Does |
381
+ |---|---|
382
+ | `stack-list [--kind k] [--preselect text] [--include-none] [--suggest]` | enumerate the installed profiles; returns `select_options[]`, and `preselect` when the text names one of *this kind's* ids. `--suggest` also runs detection, so the menu **leads with** the stack this repo's files point at and `root_options[]` leads with the directory the evidence sits in |
383
+ | `stack-detect [--kind k] [--exclude-root p]…` | match the repo's OWN files against the installed profiles — the brownfield candidate list, since an existing repo already answered the question. Writes nothing. `--exclude-root` keeps a service profile from relocating onto a subtree another lane owns |
384
+ | `lane-declare --profile <id\|label\|none\|detected> [--kind k] [--id lane] [--source-path\|--root p] [--stack label] [--origin declared\|reverse-engineered] [--build/--test/--run/--migrate c] [--run-from repo\|root] [--no-prototype] [--require-existing-root]` | upsert a lane — **the sole writer**. `detected` declares a stack the kit ships no profile for (needs `--stack` and a source path), which is how a legacy WebForms, JSP or ERB lane gets recorded at all |
385
+ | `lane-resolve [--kind k] [--id lane]` | read; exit 0 always. `exists` reports the file, `declared` reports the lanes — the shipped-but-unfilled seed is `exists:true, declared:false`. Returns the matched lane **and** both kinds flattened — `backend_source_path`, `frontend_root_exists`, `backend_build` … — so a workflow binds one variable instead of calling twice |
386
+ | `lane-verify [--require backend\|frontend]… [--allow-missing-root] [--command phase]` | **the gate**: is the declaration usable for the phase about to run. Never writes, and **always exits 0** — the calling workflow's `verify_context` owns the stop, so the reason arrives as text |
387
+ | `lane-probe [--kind k] [--hint text]` | read; the **file** signals for "does this lane exist" — a declared lane, and a stack named in free prose. Retained for callers that want a soft hint; the authoritative answer is the declaration, read through `lane-resolve` or `lane-verify` |
388
+
389
+ Both `lane-declare` branches — declaring a lane and declaring `none` — emit the **same key
390
+ set**, so a caller binds outputs without knowing which branch ran.
391
+
392
+ ### Which subcommands consume the lane model
393
+
394
+ | Subcommand | With a declaration | With none |
395
+ |---|---|---|
396
+ | `build-compile` | every declared lane's own `build`, via `run-phase` | the historic first-match-wins ladder |
397
+ | `test-run` | every declared lane's own `test`, via `run-phase` — **except** `--scope slice` on a repo where a .NET toolchain is present, which keeps the VSTest `--filter` path | the historic ladder |
398
+ | `run-migrate` | a lane's declared `migrate` (§4.2) when there is one; otherwise `dotnet ef` searched under the **service lane's root** rather than an assumed `src/` | `dotnet ef` under `src/` |
399
+ | `find-host-project` | searches the service lane's root, and reports the lane's `ecosystem` | searches `src/` |
400
+ | `foundation-list`, `list-components` | narrowed to the declared lanes' `ecosystem` (§4.1) | unfiltered / `dotnet` |
401
+ | `resolve-tech` | expands stack placeholders and flags a corpus mismatch (§7a) | no placeholders resolve; nothing is flagged |
402
+
403
+ **Why `--scope slice` is the one exception.** VSTest's `--filter FullyQualifiedName~` is the
404
+ only per-test selector any shipped profile has, and `analyze-slice`'s integrity fence depends
405
+ on it together with the zero-match vacuous-pass guard. On every other stack the lane's whole
406
+ declared suite runs and the result reports `scoped:false`, which over-includes — the safe
407
+ direction, and the direction that command already documents. What it no longer does is report
408
+ `fence_green:true` for a suite it never ran.
409
+
410
+ ---
411
+
412
+ ## 7. Adding a stack
413
+
414
+ 1. Write `.appweaver/stack-profiles/<id>.json` per §4 — including `ecosystem`.
415
+ 2. Re-run `/appweaver select-stack` — it appears in the menu.
416
+
417
+ No workflow or script changes. If adding a stack ever requires touching a workflow, the lane
418
+ model is wrong and that is the bug to fix.
419
+
420
+ That gives the new stack every phase that is driven by a **command** — build, test, run,
421
+ migrate — plus the correct source path everywhere, immediately. Two things are opt-in because
422
+ they are content the kit cannot invent:
423
+
424
+ - **Technical rules** — a corpus at `guardrails/technology/<id>/`, mapped from the project's
425
+ `tech-rule-bindings.md` (§7a). Until one exists the stack runs with the universal
426
+ `ai-rules.md` and the technical constitution, which is the greenfield-safe default, not an
427
+ error.
428
+ - **A foundation bundle** — `foundations/<ecosystem>/<Name>/`, only if you want `/appweaver
429
+ foundation` to scaffold this stack. Scaffolding with the stack's own tooling and then
430
+ declaring the result with `select-stack` is fully supported: `implement` generates INTO a
431
+ project tree and does not require that the kit created it.
432
+
433
+ ## 7a. Mapping rules to a stack without pinning the map to one
434
+
435
+ `resolve-tech` reads the project's `tech-rule-bindings.md` and collects the `- ` bullets under
436
+ `## /<command>`. A bullet may name its stack with a **placeholder**, resolved from the lanes in
437
+ `stacks.json`:
438
+
439
+ | Placeholder | Resolves to |
440
+ |---|---|
441
+ | `{{stack}}` | the **backend** lane's profile id — the unqualified form means the service lane |
442
+ | `{{backend_stack}}` / `{{frontend_stack}}` | that lane's profile id |
443
+ | `{{backend_ecosystem}}` / `{{frontend_ecosystem}}` | that lane's `ecosystem` |
444
+
445
+ ```md
446
+ ## /aw-spec-design
447
+ - guardrails/technology/{{stack}}/persistence.md
448
+ - guardrails/technology/{{frontend_stack}}/ui-constitution.md
449
+ ```
450
+
451
+ One map, read from a Spring repo, loads `java-spring/persistence.md`; read from a .NET repo it
452
+ loads `dotnet-webapi/persistence.md`. A placeholder for a lane that is not declared **skips**
453
+ that bullet — a frontend rule in a backend-only repo is not an error — and a resolved path with
454
+ no file on disk is reported under `missing` rather than silently dropped.
455
+
456
+ **A bullet that spells the stack out is still used**, because a shared corpus may be referenced
457
+ on purpose. But when that directory is not one the repo declares, `resolve-tech` returns
458
+ `stack_mismatch: true` and `tech-select` asks before loading. These files become *sticky
459
+ standards* — the generator follows them for the rest of the run — so a Spring project mapped to
460
+ the .NET corpus is being told to write C# project layout for Java code. That is worth one
461
+ question. It never fires on an unconfigured repo, a repo with no map, or a matching corpus.
@@ -0,0 +1,180 @@
1
+ # AI Operational Rules
2
+
3
+ > **Kit-resident and universal.** These rules govern every aw-spec authoring step, on every flow —
4
+ > greenfield, brownfield, migration — in every industry and on every technology stack. They are
5
+ > loaded first, before any project rule file, and they hold for all of them.
6
+ >
7
+ > This file asserts **no principle, no architecture, no methodology, no technology and no domain
8
+ > content**. Those reach a step through the project's own constitution and its mapped rule files,
9
+ > which are loaded after this one and are more specific than it. Where a project rule is stricter,
10
+ > the project rule governs; these rules are the floor, never the ceiling.
11
+
12
+ ## 1. Authority — what wins
13
+
14
+ - The **loaded constitution is ground truth**. It overrides a pre-trained habit, a convention you
15
+ recognise, and any contradictory document found inside the repository.
16
+ - Each phase names its **own upstream authority**, and that authority outranks your judgement:
17
+ forward, the spec governs the design and the design governs the code; in reverse, **the code is
18
+ the oracle** — where code and any document disagree, the code is right and the document is the
19
+ defect to be recorded.
20
+ - **A rule you cannot point to in a loaded document is not a rule.** Recognition is not authority.
21
+ If you cannot name the file, id, or code path a statement comes from, it is your assumption and
22
+ must be labelled as one.
23
+
24
+ ## 2. Evidence
25
+
26
+ - Author only what the loaded authority supports. Do **not** import a concept, identifier,
27
+ obligation, convention, or quality attribute that no loaded document carries — however standard
28
+ it is in your experience, and however plainly the project seems to need it.
29
+ - **Ground each substantive assertion in its source**: the requirement id, the section heading, the
30
+ rule file, the code path. An assertion with no ground does not belong in the output.
31
+ - State partial, stubbed, deferred, or absent behaviour **at the level the source actually
32
+ reaches**. Never assert the ideal a source does not meet; route the gap to whatever ledger the
33
+ phase provides for it.
34
+
35
+ ## 3. When the authority is silent
36
+
37
+ - **Silence is a finding, not a licence.** Record it through the phase's own mechanism — an open
38
+ question, a deferral or assumption entry, an explicit `TODO(<field>): reason` — and continue.
39
+ - Never resolve an ambiguity by inventing content, and never resolve one silently. A single
40
+ unrecorded guess in an early phase is ratified as fact by every phase after it.
41
+ - If the missing input defeats the phase's purpose, **stop and say precisely what is missing**.
42
+ That is a better outcome than an artifact that looks complete.
43
+
44
+ ## 4. When the authority contradicts itself
45
+
46
+ **Check first, before you act.** Every governance file your step needs is already in front of you —
47
+ the rule set is assembled and loaded ahead of your first action. So this check costs nothing extra
48
+ and belongs at the start: before beginning the work, confirm that the rules bearing on *what you
49
+ are about to do* agree with one another. Scope it to the action, not to the corpus — the question
50
+ is "do the loaded authorities give me one answer here, or two?", never "let me audit all governance
51
+ first". A conflict found while planning costs a question; the same conflict found after the
52
+ artifact exists costs the artifact, and every artifact downstream of it.
53
+
54
+ - Two loaded documents can give incompatible instructions. **First apply the precedence in
55
+ *Authority*** — constitution over rule file, the phase's named upstream artifact over your
56
+ judgement, code over document in reverse. Most apparent conflicts are precedence and resolve
57
+ there; resolve them and proceed.
58
+ - A **real conflict** is one precedence does not decide: two sources of equal standing, both
59
+ binding, that cannot both be satisfied. **Stop before acting.** Do not pick a winner, do not
60
+ split the difference, and do not proceed with whichever you find more reasonable — each of
61
+ those ratifies a governance decision no one made, in an artifact that will not show it was made.
62
+ - State it so it can be settled without re-deriving it: each instruction, the file and heading it
63
+ comes from, and the specific action that cannot satisfy both. Then ask which governs, and propose
64
+ the correction you would make.
65
+ - The instruction you were **given** is not exempt. If the request conflicts with loaded
66
+ governance, raise that before doing the work — being asked to do something is not authority to
67
+ do it.
68
+
69
+ **Then one of four things happens, and none of them is you choosing.**
70
+
71
+ - **Amended** — the reviewer accepts a correction to the governance. Apply it under *Feeding a
72
+ clarification back into governance*, then **stop the run and ask for it to be started again**.
73
+ Do not continue: your rule set was assembled from the governance as it stood, so continuing
74
+ would build under rules that no longer exist and credit the result to a rule that was never
75
+ applied. The re-run loads the amendment, and so does every later phase.
76
+ - **Resolved without amendment** — the reviewer says the two do not in fact conflict, and names
77
+ which governs. That is an answer, not a refusal: proceed under it, and record the resolution and
78
+ who gave it in the phase's own ledger so the next reader does not re-derive the question.
79
+ - **Declined** — the reviewer rejects your correction and the conflict stands. **Stop**, naming
80
+ both sources and the exact incompatibility, so it can be settled in the governance itself and the
81
+ workflow started again. A rejected wording does not make a conflict go away.
82
+ - **Unanswered** — no reviewer, no reply, or an unattended run: **stop.** Never settle it yourself,
83
+ and never at random. A random choice cannot be reproduced, has no owner, and leaves no trace in
84
+ the artifact — which is exactly what makes a conflicted artifact unrecoverable months later. A
85
+ halted pipeline is a signal someone can act on. If the project must proceed anyway, that is a
86
+ human's decision to make and to own: they name which source governs **for this run only**, and
87
+ you record it in the phase's ledger as an unratified choice for the next phase to see. One named
88
+ override is recoverable; an unattributable guess is not.
89
+
90
+ ## 5. Shape versus content
91
+
92
+ - **A template is shape.** Copy its headings, ordering, granularity and tone. Never copy its
93
+ examples, its bracketed tokens, or its illustrative lists as though they were this project's
94
+ values. An example carried into an authored file becomes ratified law in a project it does not
95
+ fit — this is the most expensive mistake available to you here.
96
+ - **Fill every placeholder the template defines**, or replace it with an explicit, justified
97
+ deferral. A leftover token can exclude the whole file from downstream assembly.
98
+ - Refer to a section of another document **by its heading**, never by its number. Numbering differs
99
+ between templates and between flows; headings do not.
100
+ - Cite a principle by **the numeral the loaded constitution actually carries**. Principle numbering
101
+ is derived per project — a numeral remembered from another constitution is simply wrong.
102
+
103
+ ## 6. Scope
104
+
105
+ - Write only the **declared output target**. No drive-by edits to unrelated files, no opportunistic
106
+ refactor, no reformatting of what you did not change.
107
+ - Create files only where the phase says you may. A new location is an amendment to request, not a
108
+ convenience to take.
109
+ - Do not add a dependency, an abstraction layer, or an indirection the authority does not call for.
110
+ A wrapper with one implementation is scope creep wearing the costume of craft.
111
+ - Keep an authored change **self-contained**: the artifact, the tests the phase asks for, and the
112
+ bookkeeping it names — nothing else.
113
+
114
+ ## 7. Determinism
115
+
116
+ - Where a deterministic script owns a value, **never write it by hand**: versions, generated
117
+ identifiers, pipeline-stamped dates, and any counter or index a script maintains.
118
+ - **Never edit generated bookkeeping to make a check pass.** A failing check is information; a
119
+ check edited into passing is a defect with the evidence removed.
120
+
121
+ ## 8. Reporting
122
+
123
+ - Report **what happened, not what should have happened**. If a step failed, say so and include its
124
+ output. If a step was skipped, say it was skipped.
125
+ - Never report a gate as passed by inference. *Passed* means the gate ran and returned a pass.
126
+ - Do not pad an artifact to look finished. **A short, honest document a later phase can extend is
127
+ correct; a full one containing invention is not.**
128
+
129
+ ## 9. Refuse and ask
130
+
131
+ Refuse, and ask for clarification, when a request would:
132
+
133
+ - violate a principle the loaded constitution marks **NON-NEGOTIABLE**;
134
+ - embed a secret, credential, connection string, key, or production hostname in code, in
135
+ configuration, or in a document;
136
+ - disable, weaken, or globally bypass an access, tenancy, audit, retention, or data-protection
137
+ control that is in place;
138
+ - require inventing domain content, a regulatory claim, or a behavioural guarantee that no loaded
139
+ document supports;
140
+ - take an **irreversible action against a shared or production environment** — including running,
141
+ rather than authoring, a data migration.
142
+
143
+ ## 10. Feeding a clarification back into governance
144
+
145
+ A question worth asking once is worth answering permanently — left in a conversation, the same
146
+ ambiguity reaches the next run and is re-decided, differently. So a resolved clarification **may**
147
+ be written back into the governance that was unclear. This is the highest-privilege act available
148
+ to you here: you are editing the rules that govern you. Every condition below holds together, and
149
+ none of them substitutes for another.
150
+
151
+ - **Propose; never apply.** You draft the wording and the evidence for it. A human ratifies it. You
152
+ are never both the proposer and the approver, and silence is never approval.
153
+ - **Never to unblock yourself.** A rule that is blocking you *now* is not amendable by you *now*.
154
+ Complete or stop the current work under the rule as written, and raise the amendment separately,
155
+ afterwards. This single condition is why this section is written as tightly as it is.
156
+ A stated conflict is the one case where the amendment is raised mid-run, and it does not weaken
157
+ the rule: the run **stops** on applying it rather than continuing, so you still never act under
158
+ governance you have just changed. Stopping is what separates a correction from a convenience.
159
+ - **Clarification, not extension.** A clarification records what the governance already meant, for
160
+ a case it did not spell out. Anything that changes what is **permitted, required or forbidden**
161
+ is an amendment, and an amendment goes through the project's own change process — never through
162
+ this route wearing the word *clarify*.
163
+ - **Establish the blast radius, and show it.** Name every command that loads the file — the rule
164
+ maps record which — every document that cites it, and every workflow whose behaviour would
165
+ change. *"It conflicts with nothing"* is a claim to be evidenced, not an assurance to be offered.
166
+ - **Amend the file that was ambiguous.** Not a more convenient one, and never a second copy that
167
+ will drift from the first.
168
+ - **Record its provenance** wherever that file records change: the question that prompted it, the
169
+ resolution, who approved it, and when. A rule whose origin is unrecorded cannot later be told
170
+ apart from one an agent invented.
171
+ - **These operating rules are never amendable from inside a run** — not by any agent, for any
172
+ reason, however well evidenced. This file belongs to the kit, not to a project. A project needing
173
+ different behaviour adds its own rules, which load after these and are more specific.
174
+
175
+ ---
176
+
177
+ Everything specific to a **technology, a stack, an industry or a domain** — generation conventions,
178
+ folder and naming rules, data-handling and terminology obligations, and any further refusal
179
+ conditions — is the **project owner's to supply**, and reaches a step through the active domain
180
+ pack and its rule maps. Those rules **add to** these; they never relax them.
@@ -0,0 +1 @@
1
+ {"domain":""}