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.
Files changed (98) hide show
  1. package/assets/.agents/skills/appweaver/SKILL.md +7 -47
  2. package/assets/.appweaver/ORCH-DIALECT.md +13 -9
  3. package/assets/.appweaver/RULE-PARTITION.md +3 -3
  4. package/assets/.appweaver/STACK-PROFILES.md +188 -101
  5. package/assets/.appweaver/domain.json +1 -1
  6. package/assets/.appweaver/orchestrator/AGENT-PROFILE.md +38 -10
  7. package/assets/.appweaver/orchestrator/LAUNCHER.md +88 -0
  8. package/assets/.appweaver/orchestrator/README.md +120 -53
  9. package/assets/.appweaver/orchestrator/adapters/claude_agent_sdk.py +1 -1
  10. package/assets/.appweaver/orchestrator/modules/domain-select.orch.yaml +6 -4
  11. package/assets/.appweaver/orchestrator/modules/foundation-lane.orch.yaml +237 -0
  12. package/assets/.appweaver/orchestrator/modules/foundation-pack.orch.yaml +349 -0
  13. package/assets/.appweaver/orchestrator/modules/foundation-spec.orch.yaml +381 -0
  14. package/assets/.appweaver/orchestrator/modules/lane-gate.orch.yaml +4 -4
  15. package/assets/.appweaver/orchestrator/modules/tech-select.orch.yaml +3 -3
  16. package/assets/.appweaver/orchestrator/orchestrator.py +162 -63
  17. package/assets/.appweaver/orchestrator/rev-templates/domain-constitution.skeleton.md +2 -2
  18. package/assets/.appweaver/orchestrator/rev-templates/domain-requirements.skeleton.md +2 -2
  19. package/assets/.appweaver/orchestrator/rev-templates/domain-rule-bindings.skeleton.md +5 -5
  20. package/assets/.appweaver/orchestrator/rev-templates/frontend-rule-file.skeleton.md +1 -1
  21. package/assets/.appweaver/orchestrator/rev-templates/tech-rule-bindings.skeleton.md +14 -14
  22. package/assets/.appweaver/orchestrator/rev-templates/technical-constitution.skeleton.md +2 -2
  23. package/assets/.appweaver/orchestrator/rev-templates/technical-rule-file.skeleton.md +1 -1
  24. package/assets/.appweaver/orchestrator/rev-templates/ui-constitution.skeleton.md +3 -3
  25. package/assets/.appweaver/orchestrator/workflows/_smoke.orch.yaml +41 -3
  26. package/assets/.appweaver/orchestrator/workflows/aw-spec-add-component.orch.yaml +1 -1
  27. package/assets/.appweaver/orchestrator/workflows/aw-spec-adopt.orch.yaml +13 -13
  28. package/assets/.appweaver/orchestrator/workflows/aw-spec-analyze-slice-delta.orch.yaml +3 -3
  29. package/assets/.appweaver/orchestrator/workflows/aw-spec-analyze-slice.orch.yaml +3 -3
  30. package/assets/.appweaver/orchestrator/workflows/aw-spec-build.orch.yaml +4 -4
  31. package/assets/.appweaver/orchestrator/workflows/aw-spec-characterize.orch.yaml +2 -2
  32. package/assets/.appweaver/orchestrator/workflows/aw-spec-constitution.orch.yaml +61 -12
  33. package/assets/.appweaver/orchestrator/workflows/aw-spec-foundation.orch.yaml +172 -293
  34. package/assets/.appweaver/orchestrator/workflows/aw-spec-implement.orch.yaml +29 -28
  35. package/assets/.appweaver/orchestrator/workflows/aw-spec-onboard.orch.yaml +53 -53
  36. package/assets/.appweaver/orchestrator/workflows/aw-spec-parity.orch.yaml +2 -2
  37. package/assets/.appweaver/orchestrator/workflows/aw-spec-plan.orch.yaml +3 -3
  38. package/assets/.appweaver/orchestrator/workflows/aw-spec-run.orch.yaml +4 -4
  39. package/assets/.appweaver/orchestrator/workflows/aw-spec-select-bounded-context.orch.yaml +26 -2
  40. package/assets/.appweaver/orchestrator/workflows/aw-spec-select-domain.orch.yaml +21 -15
  41. package/assets/.appweaver/orchestrator/workflows/aw-spec-select-stack.orch.yaml +14 -14
  42. package/assets/.appweaver/orchestrator/workflows/aw-spec-specify.orch.yaml +2 -2
  43. package/assets/.appweaver/orchestrator/workflows/aw-spec-ui-model.orch.yaml +3 -3
  44. package/assets/.appweaver/orchestrator/workflows/aw-spec-ui-prototype.orch.yaml +6 -6
  45. package/assets/.appweaver/scripts/bash/aw-spec-actions.sh +284 -128
  46. package/assets/.appweaver/scripts/powershell/aw-spec-actions.ps1 +224 -70
  47. package/assets/.appweaver/scripts/python/aw-foundation.py +809 -20
  48. package/assets/.appweaver/scripts/python/aw-inventory.py +28 -21
  49. package/assets/.appweaver/scripts/python/aw-plan-coverage.py +2 -2
  50. package/assets/.appweaver/scripts/python/aw-rev-constitution.py +6 -6
  51. package/assets/.appweaver/scripts/python/aw-stack.py +195 -89
  52. package/assets/.appweaver/stack-profiles/angular.json +2 -1
  53. package/assets/.appweaver/stack-profiles/blazor-wasm.json +2 -1
  54. package/assets/.appweaver/stack-profiles/dotnet-webapi.json +16 -3
  55. package/assets/.appweaver/stack-profiles/go-chi.json +6 -1
  56. package/assets/.appweaver/stack-profiles/java-spring.json +12 -5
  57. package/assets/.appweaver/stack-profiles/nextjs.json +2 -1
  58. package/assets/.appweaver/stack-profiles/node-express.json +8 -2
  59. package/assets/.appweaver/stack-profiles/python-fastapi.json +9 -2
  60. package/assets/.appweaver/stack-profiles/react-vite.json +2 -1
  61. package/assets/.appweaver/stack-profiles/sveltekit.json +2 -1
  62. package/assets/.appweaver/stack-profiles/vue-vite.json +2 -1
  63. package/assets/.appweaver/stacks.json +37 -1
  64. package/assets/.appweaver/templates/constitution-ui-template.md +2 -2
  65. package/assets/.claude/skills/appweaver/SKILL.md +7 -46
  66. package/assets/foundations/dotnet/ModularMonolith/ModularMonolith.Reference.rules.json +31 -0
  67. package/assets/foundations/dotnet/VerticalSlice/VerticalSlice.Reference.rules.json +16 -0
  68. package/assets/foundations/foundation.spec.template.txt +73 -0
  69. package/assets/foundations/java/Hexagonal/Hexagonal.pack.txt +1 -1
  70. package/assets/foundations/java/Hexagonal/unpack-foundation.sh +4 -5
  71. package/assets/foundations/node/NextAppRouter/NextAppRouter.spec.txt +68 -0
  72. package/assets/guardrails/README.md +31 -17
  73. package/assets/guardrails/{projects/dotnet-default-project → project-specific}/domain-rule-bindings.md +5 -5
  74. package/assets/guardrails/{projects/dotnet-default-project → project-specific}/tech-rule-bindings.md +151 -114
  75. package/assets/guardrails/technology/dotnet-webapi/PACKAGING.md +58 -4
  76. package/assets/guardrails/technology/dotnet-webapi/coding-standards.md +1 -1
  77. package/assets/guardrails/technology/dotnet-webapi/dependency-policy.md +1 -1
  78. package/assets/guardrails/technology/dotnet-webapi/folder-structure.md +1 -1
  79. package/assets/guardrails/technology/dotnet-webapi/framework-api-map.md +1 -1
  80. package/assets/guardrails/technology/dotnet-webapi/testing.md +1 -1
  81. package/assets/guardrails/technology/nextjs/api-client.md +1 -1
  82. package/assets/guardrails/technology/nextjs/component-architecture.md +1 -1
  83. package/assets/guardrails/technology/nextjs/component-conventions.md +2 -2
  84. package/assets/guardrails/technology/nextjs/design-system.md +1 -1
  85. package/assets/guardrails/technology/nextjs/frontend-testing.md +1 -1
  86. package/assets/guardrails/technology/nextjs/routing-navigation.md +1 -1
  87. package/assets/guardrails/technology/nextjs/ui-constitution.md +3 -3
  88. package/package.json +1 -1
  89. package/assets/.agents/skills/appweaver-demo/SKILL.md +0 -59
  90. package/assets/.appweaver/orchestrator/.smoke-out/smoke.md +0 -6
  91. package/assets/.appweaver/orchestrator/workflows/aw-spec-demo.orch.yaml +0 -100
  92. package/assets/.claude/skills/appweaver-demo/SKILL.md +0 -59
  93. package/assets/.kilocode/agent.json +0 -28
  94. package/assets/.kilocode/workflows/appweaver-demo.md +0 -59
  95. package/assets/.kilocode/workflows/appweaver.md +0 -55
  96. /package/assets/guardrails/{projects/dotnet-default-project → project-specific}/domain/domain-requirements.md +0 -0
  97. /package/assets/guardrails/{projects/dotnet-default-project → project-specific}/frontend/ui-requirements.md +0 -0
  98. /package/assets/guardrails/{projects/dotnet-default-project → project-specific}/service/technical-requirements.md +0 -0
@@ -0,0 +1,381 @@
1
+ # =============================================================================
2
+ # foundation-spec (orchestrator) — build ONE lane's project from a spec
3
+ #
4
+ # Included by foundation-lane when the operator picks a `[spec]` entry (a bundle's
5
+ # *.spec.txt) or `[manual spec]` (a file path or text they give at the prompt). Where a
6
+ # pack is a verified project unpacked byte-for-byte, a spec DESCRIBES the project and an
7
+ # agent builds it in the lane — so the three things a pack guarantees by construction are
8
+ # made explicit here instead:
9
+ #
10
+ # WHERE the whole project — build files, source and tests — goes inside the lane
11
+ # root folder, the way a pack holds it, and the agent may write nothing outside it.
12
+ # That is checked, not trusted: the repo is recorded before the build and
13
+ # compared after it, and a build that touched anything outside the lane root
14
+ # folder is not accepted, with what it created there removed again.
15
+ # foundation-lane only gets here for a lane that runs its commands in that
16
+ # folder and keeps its tests there, so the project builds where it is created.
17
+ # HOW the technical rules mapped for this command (`## /aw-spec-foundation-backend`
18
+ # or `## /aw-spec-foundation-frontend` in the active project's
19
+ # tech-rule-bindings.md) load as standards through tech-select, so the scaffold
20
+ # agrees with the rules plan and implement apply to the same lane later.
21
+ # PROOF the lane must hold a project of its ecosystem afterwards (the check implement
22
+ # gates on), and its own build command can be run on it.
23
+ #
24
+ # The spec actually used is copied to .appweaver/foundation/<lane>.spec.md — the record of
25
+ # what the project was built from.
26
+ #
27
+ # Every refusal RETURNS rather than stops, with the reason in fl_status, so the run
28
+ # carries on with the next lane.
29
+ #
30
+ # Inputs (shared vars, set by foundation-lane):
31
+ # fl_route (spec | manual), fl_spec_file (the bundle spec, route spec), fl_overwrite,
32
+ # fl_files_summary, app, fl_kind, fl_lane_id, fl_title, fl_language, fl_profile,
33
+ # fl_ecosystem, fl_source_path, fl_test_path, fl_workdir, fl_build
34
+ # Produces: fl_status, fl_spec_path, fl_files, and the fs_* details.
35
+ # =============================================================================
36
+
37
+ name: foundation-spec
38
+ dialect: aw-spec.orchestrator/v1
39
+
40
+ scripts:
41
+ actions:
42
+ sh: .appweaver/scripts/bash/aw-spec-actions.sh
43
+ ps1: .appweaver/scripts/powershell/aw-spec-actions.ps1
44
+
45
+ workflow:
46
+
47
+ # 0. Shared vars: the second lane must not read the first lane's answers.
48
+ - id: fs_reset
49
+ action: set
50
+ vars:
51
+ fs_spec_input: ""
52
+ fs_overwrite_how: ""
53
+ fs_existing_note: "The lane root folder is empty."
54
+ fs_ok: ""
55
+ fs_spec_path: ""
56
+ fs_source: ""
57
+ fs_title: ""
58
+ fs_rules_ack: ""
59
+ fs_rules_why: ""
60
+ fs_rules_line: "none"
61
+ fs_proceed: ""
62
+ fs_snapshot_path: ""
63
+ fs_files: []
64
+ fs_summary: ""
65
+ fs_inside_only: ""
66
+ fs_outside_summary: ""
67
+ fs_found: ""
68
+ fs_build_ack: ""
69
+ fs_build_ok: ""
70
+ fs_build_note: "build not run — /appweaver build compiles it and repairs compile errors"
71
+
72
+ # 1. A lane that already had files reaches this module only when the operator agreed, in
73
+ # foundation-lane, to overwrite them. The agent is told so, with what that means for
74
+ # the lane's kind: a backend generator needs its overwrite flag; a frontend generator
75
+ # refuses a non-empty folder outright and leaves node_modules out of step with the new
76
+ # package.json. The engine has no AND, so the kind's text is chosen first and only
77
+ # used when the lane is being overwritten.
78
+ - id: fs_overwrite_backend
79
+ action: set
80
+ condition: "{{fl_kind}} == backend"
81
+ vars:
82
+ fs_overwrite_how: >-
83
+ If a generator refuses to write over existing files (for example `dotnet new`
84
+ without `--force`), use that generator's own overwrite flag.
85
+
86
+ - id: fs_overwrite_frontend
87
+ action: set
88
+ condition: "{{fl_kind}} == frontend"
89
+ vars:
90
+ fs_overwrite_how: >-
91
+ Scaffolding tools that refuse a non-empty directory (create-next-app, npm create
92
+ vite, ng new) must run in a temporary directory OUTSIDE the repository — the only
93
+ place outside the lane root folder you may write — with the result copied into
94
+ {{fl_source_path}} and the temporary directory removed afterwards; or write the
95
+ files directly. Then reinstall the dependencies, so node_modules matches the new
96
+ package.json.
97
+
98
+ - id: fs_overwrite_noted
99
+ action: set
100
+ condition: "{{fl_overwrite}} == yes"
101
+ vars:
102
+ fs_existing_note: >-
103
+ THE LANE ALREADY HOLDS FILES ({{fl_files_summary}}) and the operator agreed to
104
+ overwrite them. Replace a file only where the project you build needs that path;
105
+ leave every other file where it is, and delete nothing. {{fs_overwrite_how}}
106
+
107
+ # 2. The spec. A bundle spec is already named; a manual one is asked for here.
108
+ - id: fs_ask_spec
109
+ action: ask
110
+ condition: "{{fl_route}} == manual"
111
+ prompt: >
112
+ Give the spec for the {{fl_kind}} project in lane `{{fl_lane_id}}` ({{fl_title}}):
113
+ either the path of a file that holds it (e.g. docs/{{fl_kind}}-foundation.md), or the
114
+ spec text itself — what to create, with which tools and packages, the folder layout,
115
+ and the starter files. foundations/foundation.spec.template.txt shows the shape.
116
+ answer_var: fs_spec_input
117
+
118
+ - id: fs_capture_bundle
119
+ action: execute_script
120
+ condition: "{{fl_route}} == spec"
121
+ script: { ref: actions }
122
+ subcommand: foundation-spec-capture
123
+ args: ["--lane", "{{fl_lane_id}}", "--kind", "{{fl_kind}}", "--file", "{{fl_spec_file}}"]
124
+ outputs:
125
+ - { name: fs_ok, from: "$.ok" }
126
+ - { name: fs_spec_path, from: "$.spec_path" }
127
+ - { name: fs_source, from: "$.source" }
128
+ - { name: fs_title, from: "$.title" }
129
+ - { name: fs_reason, from: "$.reason" }
130
+
131
+ - id: fs_capture_manual
132
+ action: execute_script
133
+ condition: "{{fl_route}} == manual"
134
+ script: { ref: actions }
135
+ subcommand: foundation-spec-capture
136
+ args: ["--lane", "{{fl_lane_id}}", "--kind", "{{fl_kind}}", "--input", "{{fs_spec_input}}"]
137
+ outputs:
138
+ - { name: fs_ok, from: "$.ok" }
139
+ - { name: fs_spec_path, from: "$.spec_path" }
140
+ - { name: fs_source, from: "$.source" }
141
+ - { name: fs_title, from: "$.title" }
142
+ - { name: fs_reason, from: "$.reason" }
143
+
144
+ - id: fs_capture_gate
145
+ action: verify_context
146
+ require_true: fs_ok
147
+ on_false: return
148
+ message_var: fl_status
149
+ on_false_message: "not built — {{fs_reason}}"
150
+
151
+ # 3. The technical rules mapped for this command, loaded as standards. `replace` resets
152
+ # the set to the workflow's seed first, so the frontend lane is never handed the
153
+ # backend lane's rules. tg_mode/tg_subset are cleared because tech-select only asks
154
+ # when the map has candidates — a stale answer from the other lane would otherwise
155
+ # load that lane's subset here.
156
+ - id: fs_rules
157
+ action: include
158
+ module: .appweaver/orchestrator/modules/tech-select.orch.yaml
159
+ with:
160
+ command: "aw-spec-foundation-{{fl_kind}}"
161
+ replace: "true"
162
+ tg_mode: ""
163
+ tg_subset: []
164
+
165
+ - id: fs_rules_why_project
166
+ action: set
167
+ condition: "{{tech_domain}} == "
168
+ vars: { fs_rules_why: "no project is named in .appweaver/domain.json — run /appweaver select-domain, or set \"domain\" to a folder under guardrails/ (project-specific by default)" }
169
+
170
+ - id: fs_rules_why_heading
171
+ action: set
172
+ condition: "{{tech_domain}} != "
173
+ vars: { fs_rules_why: "guardrails/{{tech_domain}}/tech-rule-bindings.md maps no file that exists under `## /aw-spec-foundation-{{fl_kind}}`" }
174
+
175
+ - id: fs_no_rules_ask
176
+ action: ask
177
+ condition: "{{tg_candidates}} == []"
178
+ prompt: "No technical rules apply to this build: {{fs_rules_why}}. Without them the agent builds from the spec alone, and the project may not follow the rules plan and implement apply to this lane later. Continue?"
179
+ options: ["continue without them", "stop — leave this lane"]
180
+ answer_var: fs_rules_ack
181
+
182
+ - id: fs_no_rules_gate
183
+ action: verify_context
184
+ condition: "{{tg_candidates}} == []"
185
+ require_value: fs_rules_ack
186
+ equals: "continue without them"
187
+ on_mismatch: return
188
+ message_var: fl_status
189
+ on_mismatch_message: "not built — no technical rules apply ({{fs_rules_why}}); spec kept at {{fs_spec_path}}"
190
+
191
+ - id: fs_rules_line_none
192
+ action: set
193
+ condition: "{{tg_candidates}} == []"
194
+ vars: { fs_rules_line: "none — {{fs_rules_why}}" }
195
+
196
+ - id: fs_rules_line_all
197
+ action: set
198
+ condition: "{{tg_mode}} == all"
199
+ vars: { fs_rules_line: "{{tg_candidates}}" }
200
+
201
+ - id: fs_rules_line_subset
202
+ action: set
203
+ condition: "{{tg_mode}} == subset"
204
+ vars: { fs_rules_line: "{{tg_subset}}" }
205
+
206
+ - id: fs_rules_line_declined
207
+ action: set
208
+ condition: "{{tg_mode}} == none"
209
+ vars: { fs_rules_line: "none — declined at the selection" }
210
+
211
+ # 4. Confirm the build plan.
212
+ - id: fs_confirm
213
+ action: ask
214
+ prompt: |
215
+ Build the {{fl_kind}} lane from a spec
216
+ Spec: {{fs_spec_path}} (from {{fs_source}}: {{fs_title}})
217
+ App name: {{app}}
218
+ Lane: {{fl_lane_id}} — {{fl_title}}, {{fl_language}}
219
+ Folder: {{fl_source_path}} <- the whole project: build files, source and tests
220
+ Tests: {{fl_test_path}}
221
+ Commands: `{{fl_build}}` runs in {{fl_workdir}}
222
+ Rules: {{fs_rules_line}}
223
+ The agent follows the spec with the stack's own tooling, and writes nothing outside
224
+ these paths. Proceed?
225
+ options: ["yes", "no"]
226
+ answer_var: fs_proceed
227
+
228
+ - id: fs_confirm_gate
229
+ action: verify_context
230
+ require_value: fs_proceed
231
+ equals: "yes"
232
+ on_mismatch: return
233
+ message_var: fl_status
234
+ on_mismatch_message: "not built — declined at the confirmation; the spec is kept at {{fs_spec_path}}"
235
+
236
+ # 5. Build it. agent_generate: the agent has write tools and Bash, so it can run the
237
+ # stack's scaffolding CLI. The spec reaches it as context; the mapped rules are
238
+ # already in the standards. The repo is recorded first, so what the build does outside
239
+ # the lane root folder can be found afterwards (6).
240
+ - id: fs_snapshot
241
+ action: execute_script
242
+ script: { ref: actions }
243
+ subcommand: foundation-snapshot
244
+ args: ["--out", ".appweaver/orchestrator/.state/foundation-{{fl_lane_id}}.snapshot.json"]
245
+ outputs:
246
+ - { name: fs_snapshot_path, from: "$.snapshot" }
247
+
248
+ - id: fs_generate
249
+ action: agent_generate
250
+ context: ["{{fs_spec_path}}"]
251
+ task: |
252
+ Create the base project for the {{fl_kind}} lane `{{fl_lane_id}}` — {{fl_title}}
253
+ ({{fl_language}}, stack profile `{{fl_profile}}`) — exactly as the spec in
254
+ {{fs_spec_path}} (in your context) describes. Name it after `{{app}}`, in the form
255
+ this stack uses for a project name.
256
+
257
+ WHERE YOU MAY WRITE — {{fl_source_path}}, the lane root folder, and nothing else, ever.
258
+ The WHOLE project goes inside it, complete: its build files (solution, workspace or
259
+ package manifest, build props, wrapper scripts), its source, and its tests — the
260
+ tests at {{fl_test_path}}, inside the same folder. Create the folder if absent. The
261
+ lane's commands run in that folder (`{{fl_build}}` runs in {{fl_workdir}}), so
262
+ nothing the build needs may sit outside it. Never write under .appweaver/,
263
+ guardrails/, foundations/ or specs/, at the repository root, or into another lane
264
+ root folder. This is checked when you finish: if anything outside the lane root
265
+ folder was created, changed or deleted, the lane is not accepted and what you
266
+ created there is removed.
267
+
268
+ WHAT IS THERE ALREADY: {{fs_existing_note}}
269
+
270
+ HOW:
271
+ - Follow the spec. Where it is silent, follow the technical rules in your standards;
272
+ where the spec and a rule disagree, follow the spec and name the conflict in your
273
+ summary.
274
+ - Where the spec names a scaffolding tool (dotnet new, npm create, mvn archetype,
275
+ …), run it so its output lands in the lane root folder itself — not a new folder
276
+ inside or beside it.
277
+ - This is the lane's BASE project. Business features are generated later by
278
+ /appweaver implement from the plans, so add none the spec does not ask for.
279
+ - The project must build with `{{fl_build}}` run in {{fl_workdir}}. Restore or
280
+ install what that needs; run the build once if you can and fix what it reports.
281
+ - Do not commit, push, or change git configuration.
282
+
283
+ List every file you created or changed in `files` (paths relative to the repository
284
+ root; for a tool that generated many files, list the manifest and entry points).
285
+ outputs:
286
+ - { name: fs_files, from: "$.files" }
287
+ - { name: fs_summary, from: "$.summary" }
288
+
289
+ # 6. Did the build stay inside its lane root folder? Compared with the snapshot: anything
290
+ # created, changed or deleted elsewhere — the repository root, another lane, the kit's
291
+ # own folders — and the lane is not accepted. What the build created out there is
292
+ # removed again; what it changed or deleted is listed, since there is no copy to put
293
+ # back. Checked before anything else, so a build that wrote nothing in the lane still
294
+ # has its stray files found.
295
+ - id: fs_outside
296
+ action: execute_script
297
+ script: { ref: actions }
298
+ subcommand: foundation-outside
299
+ args: ["--snapshot", "{{fs_snapshot_path}}", "--lane", "{{fl_source_path}}", "--undo"]
300
+ outputs:
301
+ - { name: fs_inside_only, from: "$.clean" }
302
+ - { name: fs_outside_summary, from: "$.summary" }
303
+
304
+ - id: fs_outside_gate
305
+ action: verify_context
306
+ require_true: fs_inside_only
307
+ on_false: return
308
+ message_var: fl_status
309
+ on_false_message: "NOT accepted — the spec build wrote outside its lane root folder {{fl_source_path}}: {{fs_outside_summary}}. The spec is kept at {{fs_spec_path}}"
310
+
311
+ - id: fs_files_gate
312
+ action: verify_context
313
+ require_non_empty: fs_files
314
+ on_empty: return
315
+ message_var: fl_status
316
+ on_empty_message: "NOT built — the spec build reported no file that exists on disk; the spec is kept at {{fs_spec_path}}"
317
+
318
+ # 6. Proof: a project of this lane's ecosystem now sits INSIDE the lane — the same
319
+ # check implement gates on. A repo-scope hit (another lane's manifest) does not count.
320
+ - id: fs_detect
321
+ action: execute_script
322
+ script: { ref: actions }
323
+ subcommand: detect-project
324
+ args: ["--root", "{{fl_source_path}}", "--ecosystem", "{{fl_ecosystem}}"]
325
+ outputs:
326
+ - { name: fs_scope, from: "$.scope" }
327
+ - { name: fs_eco_match, from: "$.ecosystem_match" }
328
+ - { name: fs_markers, from: "$.markers" }
329
+
330
+ - id: fs_found_in_lane
331
+ action: set
332
+ condition: "{{fs_scope}} == lane"
333
+ vars: { fs_found: "true" }
334
+
335
+ - id: fs_found_wrong_eco
336
+ action: set
337
+ condition: "{{fs_eco_match}} == false"
338
+ vars: { fs_found: "" }
339
+
340
+ - id: fs_found_gate
341
+ action: verify_context
342
+ require_true: fs_found
343
+ on_false: return
344
+ message_var: fl_status
345
+ on_false_message: "NOT usable — the spec build ran ({{fs_summary}}) but no {{fl_ecosystem}} project manifest is under {{fl_source_path}} (searched at scope `{{fs_scope}}`, found {{fs_markers}}); implement will skip this lane until one is there. The spec is kept at {{fs_spec_path}}"
346
+
347
+ # 7. Optionally run the lane's own build on it. It may need the network (restore /
348
+ # install), which is why it is asked rather than assumed.
349
+ - id: fs_ask_build
350
+ action: ask
351
+ prompt: "Run this lane's build now to confirm the project compiles — `{{fl_build}}` in {{fl_workdir}}? It may download packages."
352
+ options: ["yes — build it now", "no — I'll build later"]
353
+ answer_var: fs_build_ack
354
+
355
+ - id: fs_build
356
+ action: execute_script
357
+ condition: "{{fs_build_ack}} == yes — build it now"
358
+ on_error: continue
359
+ script: { ref: actions }
360
+ subcommand: build-compile
361
+ args: ["--kind", "{{fl_kind}}"]
362
+ outputs:
363
+ - { name: fs_build_ok, from: "$.ok" }
364
+ - { name: fs_build_tail, from: "$.failing_excerpt" }
365
+
366
+ - id: fs_build_passed
367
+ action: set
368
+ condition: "{{fs_build_ok}} == true"
369
+ vars: { fs_build_note: "build passed (`{{fl_build}}`)" }
370
+
371
+ - id: fs_build_failed
372
+ action: set
373
+ condition: "{{fs_build_ok}} == false"
374
+ vars: { fs_build_note: "build FAILED — run /appweaver build, which repairs compile errors: {{fs_build_tail}}" }
375
+
376
+ - id: fs_done
377
+ action: set
378
+ vars:
379
+ fl_spec_path: "{{fs_spec_path}}"
380
+ fl_files: "{{fs_files}}"
381
+ fl_status: "built from the spec in {{fs_spec_path}} (from {{fs_source}}) into {{fl_source_path}} — {{fs_summary}}; {{fs_build_note}}"
@@ -1,12 +1,12 @@
1
1
  # =============================================================================
2
- # lane-gate (orchestrator) — shared LANE + SOURCE PATH gate
2
+ # lane-gate (orchestrator) — shared LANE + LANE ROOT FOLDER gate
3
3
  #
4
4
  # Included by every phase that reads or writes a lane's subtree. It answers one
5
5
  # question before that phase starts doing work:
6
6
  #
7
- # is there a lane of the kind I need, and is its source path really there?
7
+ # is there a lane of the kind I need, and is its lane root folder really there?
8
8
  #
9
- # WHY A GATE AND NOT A FALLBACK. A phase that cannot find a source path has two
9
+ # WHY A GATE AND NOT A FALLBACK. A phase that cannot find a lane root folder has two
10
10
  # options: guess, or stop. Guessing is what the kit did before the lane model —
11
11
  # `build` sniffed for a .sln, `run-migrate` hardcoded `src/`, and `implement` let
12
12
  # the model decide where files should go. Each of those is right on the layout the
@@ -27,7 +27,7 @@
27
27
  # needs a declaration to work from but no particular kind of one — `build`
28
28
  # compiles every declared lane, so a frontend-only project is as buildable
29
29
  # as a backend-only one. It narrows nothing else: no lane declared at all, a
30
- # lane with no source path, a source path that is not on disk and two lanes
30
+ # lane with no lane root folder, a lane root folder that is not on disk and two lanes
31
31
  # claiming overlapping subtrees all still stop the run. The required kind's
32
32
  # fields below then bind from the backend block, which an empty-require
33
33
  # caller reads none of.
@@ -2,10 +2,10 @@
2
2
  # tech-select (orchestrator) — shared TECHNICAL rule-file selection module
3
3
  #
4
4
  # The technical counterpart of domain-select. Where domain-select loads the
5
- # per-command DOMAIN rule files from guardrails/projects/<project>/domain-rule-bindings.md,
5
+ # per-command DOMAIN rule files from guardrails/<project>/domain-rule-bindings.md,
6
6
  # this module loads the per-command TECHNICAL rule files — the project's mapped technical rules and
7
7
  # the worked examples/ samples that go with them — from
8
- # guardrails/projects/<project>/tech-rule-bindings.md
8
+ # guardrails/<project>/tech-rule-bindings.md
9
9
  # Included (via `action: include`) by every technical-rule consumer so the set is
10
10
  # CONFIGURATION, not code — tune the map, not the workflow.
11
11
  #
@@ -87,7 +87,7 @@ workflow:
87
87
  on_mismatch_message: >
88
88
  Stopped before loading technical rules from {{tg_mismatched}} into a
89
89
  {{tg_declared_stacks}} repository. Point the `## /` headings in
90
- guardrails/projects/{{tech_domain}}/tech-rule-bindings.md at a corpus for this
90
+ guardrails/{{tech_domain}}/tech-rule-bindings.md at a corpus for this
91
91
  stack, or write the corpus segment of the path as a stack PLACEHOLDER (see the
92
92
  header of resolve-tech) so one map resolves from .appweaver/stacks.json and serves
93
93
  every stack this project declares. A corpus