aw-spec-cli 0.1.26 → 0.1.28
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/assets/.agents/skills/appweaver/SKILL.md +7 -47
- package/assets/.appweaver/ORCH-DIALECT.md +13 -9
- package/assets/.appweaver/RULE-PARTITION.md +11 -12
- package/assets/.appweaver/STACK-PROFILES.md +260 -108
- package/assets/.appweaver/domain.json +1 -1
- package/assets/.appweaver/interpreter/run-skill.py +28 -7
- package/assets/.appweaver/orchestrator/AGENT-PROFILE.md +38 -10
- package/assets/.appweaver/orchestrator/LAUNCHER.md +88 -0
- package/assets/.appweaver/orchestrator/README.md +120 -53
- package/assets/.appweaver/orchestrator/adapters/claude_agent_sdk.py +1 -1
- package/assets/.appweaver/orchestrator/modules/delta-plan.orch.yaml +17 -7
- package/assets/.appweaver/orchestrator/modules/domain-select.orch.yaml +6 -4
- package/assets/.appweaver/orchestrator/modules/foundation-lane.orch.yaml +237 -0
- package/assets/.appweaver/orchestrator/modules/foundation-pack.orch.yaml +392 -0
- package/assets/.appweaver/orchestrator/modules/foundation-spec.orch.yaml +548 -0
- package/assets/.appweaver/orchestrator/modules/lane-gate.orch.yaml +4 -4
- package/assets/.appweaver/orchestrator/modules/tech-select.orch.yaml +3 -3
- package/assets/.appweaver/orchestrator/orchestrator.py +162 -63
- package/assets/.appweaver/orchestrator/rev-templates/delta-design-template.skeleton.md +5 -4
- package/assets/.appweaver/orchestrator/rev-templates/design-template.skeleton.md +3 -1
- package/assets/.appweaver/orchestrator/rev-templates/domain-constitution.skeleton.md +2 -2
- package/assets/.appweaver/orchestrator/rev-templates/domain-requirements.skeleton.md +2 -2
- package/assets/.appweaver/orchestrator/rev-templates/domain-rule-bindings.skeleton.md +21 -13
- package/assets/.appweaver/orchestrator/rev-templates/frontend-rule-file.skeleton.md +1 -1
- package/assets/.appweaver/orchestrator/rev-templates/tech-rule-bindings.skeleton.md +28 -31
- package/assets/.appweaver/orchestrator/rev-templates/technical-constitution.skeleton.md +2 -2
- package/assets/.appweaver/orchestrator/rev-templates/technical-rule-file.skeleton.md +1 -1
- package/assets/.appweaver/orchestrator/rev-templates/ui-constitution.skeleton.md +3 -3
- package/assets/.appweaver/orchestrator/rev-templates/ui-delta-design-template.skeleton.md +4 -1
- package/assets/.appweaver/orchestrator/rev-templates/ui-design-template.skeleton.md +6 -4
- package/assets/.appweaver/orchestrator/workflows/_smoke.orch.yaml +41 -3
- package/assets/.appweaver/orchestrator/workflows/aw-spec-add-component.orch.yaml +1 -1
- package/assets/.appweaver/orchestrator/workflows/aw-spec-adopt.orch.yaml +17 -16
- package/assets/.appweaver/orchestrator/workflows/aw-spec-analyze-plan-delta.orch.yaml +7 -1
- package/assets/.appweaver/orchestrator/workflows/aw-spec-analyze-plan.orch.yaml +7 -1
- package/assets/.appweaver/orchestrator/workflows/aw-spec-analyze-slice-delta.orch.yaml +3 -3
- package/assets/.appweaver/orchestrator/workflows/aw-spec-analyze-slice.orch.yaml +3 -3
- package/assets/.appweaver/orchestrator/workflows/aw-spec-build.orch.yaml +4 -4
- package/assets/.appweaver/orchestrator/workflows/aw-spec-characterize.orch.yaml +2 -2
- package/assets/.appweaver/orchestrator/workflows/aw-spec-constitution.orch.yaml +61 -12
- package/assets/.appweaver/orchestrator/workflows/aw-spec-deploy.orch.yaml +1 -1
- package/assets/.appweaver/orchestrator/workflows/aw-spec-foundation.orch.yaml +172 -293
- package/assets/.appweaver/orchestrator/workflows/aw-spec-implement.orch.yaml +253 -44
- package/assets/.appweaver/orchestrator/workflows/aw-spec-onboard.orch.yaml +72 -71
- package/assets/.appweaver/orchestrator/workflows/aw-spec-parity.orch.yaml +2 -2
- package/assets/.appweaver/orchestrator/workflows/aw-spec-plan.orch.yaml +38 -14
- package/assets/.appweaver/orchestrator/workflows/aw-spec-run.orch.yaml +4 -4
- package/assets/.appweaver/orchestrator/workflows/aw-spec-select-bounded-context.orch.yaml +26 -2
- package/assets/.appweaver/orchestrator/workflows/aw-spec-select-domain.orch.yaml +21 -15
- package/assets/.appweaver/orchestrator/workflows/aw-spec-select-stack.orch.yaml +14 -14
- package/assets/.appweaver/orchestrator/workflows/aw-spec-specify.orch.yaml +3 -3
- package/assets/.appweaver/orchestrator/workflows/aw-spec-ui-model.orch.yaml +3 -3
- package/assets/.appweaver/orchestrator/workflows/aw-spec-ui-prototype.orch.yaml +6 -6
- package/assets/.appweaver/scripts/bash/aw-spec-actions.sh +371 -131
- package/assets/.appweaver/scripts/powershell/aw-spec-actions.ps1 +293 -76
- package/assets/.appweaver/scripts/python/aw-foundation.py +885 -20
- package/assets/.appweaver/scripts/python/aw-inventory.py +28 -21
- package/assets/.appweaver/scripts/python/aw-plan-coverage.py +2 -2
- package/assets/.appweaver/scripts/python/aw-rev-constitution.py +6 -6
- package/assets/.appweaver/scripts/python/aw-stack.py +676 -99
- package/assets/.appweaver/stack-profiles/angular.json +2 -1
- package/assets/.appweaver/stack-profiles/blazor-wasm.json +2 -1
- package/assets/.appweaver/stack-profiles/dotnet-webapi.json +18 -3
- package/assets/.appweaver/stack-profiles/go-chi.json +6 -1
- package/assets/.appweaver/stack-profiles/java-spring.json +14 -5
- package/assets/.appweaver/stack-profiles/nextjs.json +2 -1
- package/assets/.appweaver/stack-profiles/node-express.json +8 -2
- package/assets/.appweaver/stack-profiles/python-fastapi.json +9 -2
- package/assets/.appweaver/stack-profiles/react-vite.json +2 -1
- package/assets/.appweaver/stack-profiles/sveltekit.json +2 -1
- package/assets/.appweaver/stack-profiles/vue-vite.json +2 -1
- package/assets/.appweaver/stacks.json +40 -1
- package/assets/.appweaver/templates/constitution-ui-template.md +2 -2
- package/assets/.appweaver/templates/delta-design-template.md +7 -5
- package/assets/.appweaver/templates/design-template.md +3 -0
- package/assets/.appweaver/templates/ui-delta-design-template.md +1 -1
- package/assets/.appweaver/templates/ui-design-template.md +6 -4
- package/assets/.claude/skills/appweaver/SKILL.md +7 -46
- package/assets/foundations/dotnet/ModularMonolith/ModularMonolith.Reference.rules.json +31 -0
- package/assets/foundations/dotnet/ModularMonolith/ModularMonolith.lane.json +6 -0
- package/assets/foundations/dotnet/VerticalSlice/VerticalSlice.Reference.rules.json +16 -0
- package/assets/foundations/dotnet/VerticalSlice/VerticalSlice.lane.json +6 -0
- package/assets/foundations/foundation.spec.template.txt +98 -0
- package/assets/foundations/java/Hexagonal/Hexagonal.lane.json +6 -0
- package/assets/foundations/java/Hexagonal/Hexagonal.pack.txt +8 -1
- package/assets/foundations/java/Hexagonal/unpack-foundation.sh +4 -5
- package/assets/foundations/node/NextAppRouter/NextAppRouter.spec.txt +68 -0
- package/assets/guardrails/README.md +31 -17
- package/assets/guardrails/{projects/dotnet-default-project → project-specific}/domain-rule-bindings.md +25 -13
- package/assets/guardrails/project-specific/tech-rule-bindings.md +296 -0
- package/assets/guardrails/technology/dotnet-webapi/PACKAGING.md +58 -4
- package/assets/guardrails/technology/dotnet-webapi/api-versioning.md +1 -1
- package/assets/guardrails/technology/dotnet-webapi/auditing.md +1 -1
- package/assets/guardrails/technology/dotnet-webapi/authorization.md +1 -1
- package/assets/guardrails/technology/dotnet-webapi/clean-architecture.md +1 -1
- package/assets/guardrails/technology/dotnet-webapi/coding-standards.md +1 -1
- package/assets/guardrails/technology/dotnet-webapi/cqrs.md +1 -1
- package/assets/guardrails/technology/dotnet-webapi/data-classification.md +1 -1
- package/assets/guardrails/technology/dotnet-webapi/dependency-policy.md +1 -1
- package/assets/guardrails/technology/dotnet-webapi/eventing.md +1 -1
- package/assets/guardrails/technology/dotnet-webapi/folder-structure.md +1 -1
- package/assets/guardrails/technology/dotnet-webapi/framework-api-map.md +1 -1
- package/assets/guardrails/technology/dotnet-webapi/modular-monolith.md +1 -1
- package/assets/guardrails/technology/dotnet-webapi/persistence.md +1 -1
- package/assets/guardrails/technology/dotnet-webapi/testing.md +1 -1
- package/assets/guardrails/technology/dotnet-webapi/vertical-slices.md +1 -1
- package/assets/guardrails/technology/dotnet-webapi/zero-trust.md +1 -1
- package/assets/guardrails/technology/nextjs/accessibility-implementation.md +1 -1
- package/assets/guardrails/technology/nextjs/api-client.md +1 -1
- package/assets/guardrails/technology/nextjs/api-integration.dotnet-webapi.md +1 -1
- package/assets/guardrails/technology/nextjs/api-integration.java-spring.md +1 -1
- package/assets/guardrails/technology/nextjs/auth-session.md +1 -1
- package/assets/guardrails/technology/nextjs/client-security.md +1 -1
- package/assets/guardrails/technology/nextjs/component-architecture.md +1 -1
- package/assets/guardrails/technology/nextjs/component-conventions.md +2 -2
- package/assets/guardrails/technology/nextjs/design-system.md +1 -1
- package/assets/guardrails/technology/nextjs/error-handling.md +1 -1
- package/assets/guardrails/technology/nextjs/forms-and-validation.md +1 -1
- package/assets/guardrails/technology/nextjs/frontend-testing.md +1 -1
- package/assets/guardrails/technology/nextjs/i18n.md +1 -1
- package/assets/guardrails/technology/nextjs/observability.md +1 -1
- package/assets/guardrails/technology/nextjs/performance-budgets.md +1 -1
- package/assets/guardrails/technology/nextjs/routing-navigation.md +1 -1
- package/assets/guardrails/technology/nextjs/state-management.md +1 -1
- package/assets/guardrails/technology/nextjs/ui-constitution.md +3 -3
- package/package.json +1 -1
- package/assets/.agents/skills/appweaver-demo/SKILL.md +0 -59
- package/assets/.appweaver/orchestrator/.smoke-out/smoke.md +0 -6
- package/assets/.appweaver/orchestrator/workflows/aw-spec-demo.orch.yaml +0 -100
- package/assets/.claude/skills/appweaver-demo/SKILL.md +0 -59
- package/assets/.kilocode/agent.json +0 -28
- package/assets/.kilocode/workflows/appweaver-demo.md +0 -59
- package/assets/.kilocode/workflows/appweaver.md +0 -55
- package/assets/guardrails/projects/dotnet-default-project/tech-rule-bindings.md +0 -271
- /package/assets/guardrails/{projects/dotnet-default-project → project-specific}/domain/domain-requirements.md +0 -0
- /package/assets/guardrails/{projects/dotnet-default-project → project-specific}/frontend/ui-requirements.md +0 -0
- /package/assets/guardrails/{projects/dotnet-default-project → project-specific}/service/technical-requirements.md +0 -0
|
@@ -0,0 +1,548 @@
|
|
|
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. The API-contract settings its header gives — or the
|
|
26
|
+
# operator types when it gives none — are recorded on the lane once the project is built.
|
|
27
|
+
#
|
|
28
|
+
# Every refusal RETURNS rather than stops, with the reason in fl_status, so the run
|
|
29
|
+
# carries on with the next lane.
|
|
30
|
+
#
|
|
31
|
+
# Inputs (shared vars, set by foundation-lane):
|
|
32
|
+
# fl_route (spec | manual), fl_spec_file (the bundle spec, route spec), fl_overwrite,
|
|
33
|
+
# fl_files_summary, app, fl_kind, fl_lane_id, fl_title, fl_language, fl_profile,
|
|
34
|
+
# fl_ecosystem, fl_source_path, fl_test_path, fl_workdir, fl_build
|
|
35
|
+
# Produces: fl_status, fl_spec_path, fl_files, and the fs_* details.
|
|
36
|
+
# =============================================================================
|
|
37
|
+
|
|
38
|
+
name: foundation-spec
|
|
39
|
+
dialect: aw-spec.orchestrator/v1
|
|
40
|
+
|
|
41
|
+
scripts:
|
|
42
|
+
actions:
|
|
43
|
+
sh: .appweaver/scripts/bash/aw-spec-actions.sh
|
|
44
|
+
ps1: .appweaver/scripts/powershell/aw-spec-actions.ps1
|
|
45
|
+
|
|
46
|
+
workflow:
|
|
47
|
+
|
|
48
|
+
# 0. Shared vars: the second lane must not read the first lane's answers.
|
|
49
|
+
- id: fs_reset
|
|
50
|
+
action: set
|
|
51
|
+
vars:
|
|
52
|
+
fs_spec_input: ""
|
|
53
|
+
fs_overwrite_how: ""
|
|
54
|
+
fs_existing_note: "The lane root folder is empty."
|
|
55
|
+
fs_ok: ""
|
|
56
|
+
fs_spec_path: ""
|
|
57
|
+
fs_source: ""
|
|
58
|
+
fs_title: ""
|
|
59
|
+
fs_rules_ack: ""
|
|
60
|
+
fs_rules_why: ""
|
|
61
|
+
fs_rules_line: "none"
|
|
62
|
+
fs_proceed: ""
|
|
63
|
+
fs_snapshot_path: ""
|
|
64
|
+
fs_files: []
|
|
65
|
+
fs_summary: ""
|
|
66
|
+
fs_inside_only: ""
|
|
67
|
+
fs_outside_summary: ""
|
|
68
|
+
fs_found: ""
|
|
69
|
+
fs_build_ack: ""
|
|
70
|
+
fs_build_ok: ""
|
|
71
|
+
fs_build_note: "build not run — /appweaver build compiles it and repairs compile errors"
|
|
72
|
+
fs_hdr_contract_run: ""
|
|
73
|
+
fs_hdr_contract: ""
|
|
74
|
+
fs_hdr_client: ""
|
|
75
|
+
fs_settings_text: "none"
|
|
76
|
+
fs_placeholder: ""
|
|
77
|
+
fs_is_backend: "false"
|
|
78
|
+
fs_is_frontend: "false"
|
|
79
|
+
fs_need_run: "false"
|
|
80
|
+
fs_need_url: "false"
|
|
81
|
+
fs_need_client: "false"
|
|
82
|
+
fs_ans_contract_run: ""
|
|
83
|
+
fs_ans_contract: ""
|
|
84
|
+
fs_ans_client: ""
|
|
85
|
+
fs_set_run: ""
|
|
86
|
+
fs_set_url: ""
|
|
87
|
+
fs_set_client: ""
|
|
88
|
+
fs_cur_contract_run: ""
|
|
89
|
+
fs_cur_contract: ""
|
|
90
|
+
fs_cur_client: ""
|
|
91
|
+
fs_cur_run_shown: "none — the export is skipped until one is set"
|
|
92
|
+
fs_cur_url_shown: "none — the export is skipped until one is set"
|
|
93
|
+
fs_cur_client_shown: "none — implement asks for one before it generates the frontend"
|
|
94
|
+
fs_lane_written: ""
|
|
95
|
+
fs_lane_note: ""
|
|
96
|
+
|
|
97
|
+
# 1. A lane that already had files reaches this module only when the operator agreed, in
|
|
98
|
+
# foundation-lane, to overwrite them. The agent is told so, with what that means for
|
|
99
|
+
# the lane's kind: a backend generator needs its overwrite flag; a frontend generator
|
|
100
|
+
# refuses a non-empty folder outright and leaves node_modules out of step with the new
|
|
101
|
+
# package.json. The engine has no AND, so the kind's text is chosen first and only
|
|
102
|
+
# used when the lane is being overwritten.
|
|
103
|
+
- id: fs_overwrite_backend
|
|
104
|
+
action: set
|
|
105
|
+
condition: "{{fl_kind}} == backend"
|
|
106
|
+
vars:
|
|
107
|
+
fs_overwrite_how: >-
|
|
108
|
+
If a generator refuses to write over existing files (for example `dotnet new`
|
|
109
|
+
without `--force`), use that generator's own overwrite flag.
|
|
110
|
+
|
|
111
|
+
- id: fs_overwrite_frontend
|
|
112
|
+
action: set
|
|
113
|
+
condition: "{{fl_kind}} == frontend"
|
|
114
|
+
vars:
|
|
115
|
+
fs_overwrite_how: >-
|
|
116
|
+
Scaffolding tools that refuse a non-empty directory (create-next-app, npm create
|
|
117
|
+
vite, ng new) must run in a temporary directory OUTSIDE the repository — the only
|
|
118
|
+
place outside the lane root folder you may write — with the result copied into
|
|
119
|
+
{{fl_source_path}} and the temporary directory removed afterwards; or write the
|
|
120
|
+
files directly. Then reinstall the dependencies, so node_modules matches the new
|
|
121
|
+
package.json.
|
|
122
|
+
|
|
123
|
+
- id: fs_overwrite_noted
|
|
124
|
+
action: set
|
|
125
|
+
condition: "{{fl_overwrite}} == yes"
|
|
126
|
+
vars:
|
|
127
|
+
fs_existing_note: >-
|
|
128
|
+
THE LANE ALREADY HOLDS FILES ({{fl_files_summary}}) and the operator agreed to
|
|
129
|
+
overwrite them. Replace a file only where the project you build needs that path;
|
|
130
|
+
leave every other file where it is, and delete nothing. {{fs_overwrite_how}}
|
|
131
|
+
|
|
132
|
+
# 2. The spec. A bundle spec is already named; a manual one is asked for here.
|
|
133
|
+
- id: fs_ask_spec
|
|
134
|
+
action: ask
|
|
135
|
+
condition: "{{fl_route}} == manual"
|
|
136
|
+
prompt: >
|
|
137
|
+
Give the spec for the {{fl_kind}} project in lane `{{fl_lane_id}}` ({{fl_title}}):
|
|
138
|
+
either the path of a file that holds it (e.g. docs/{{fl_kind}}-foundation.md), or the
|
|
139
|
+
spec text itself — what to create, with which tools and packages, the folder layout,
|
|
140
|
+
and the starter files. foundations/foundation.spec.template.txt shows the shape.
|
|
141
|
+
answer_var: fs_spec_input
|
|
142
|
+
|
|
143
|
+
- id: fs_capture_bundle
|
|
144
|
+
action: execute_script
|
|
145
|
+
condition: "{{fl_route}} == spec"
|
|
146
|
+
script: { ref: actions }
|
|
147
|
+
subcommand: foundation-spec-capture
|
|
148
|
+
args: ["--lane", "{{fl_lane_id}}", "--kind", "{{fl_kind}}", "--file", "{{fl_spec_file}}", "--app", "{{app}}"]
|
|
149
|
+
outputs:
|
|
150
|
+
- { name: fs_ok, from: "$.ok" }
|
|
151
|
+
- { name: fs_spec_path, from: "$.spec_path" }
|
|
152
|
+
- { name: fs_source, from: "$.source" }
|
|
153
|
+
- { name: fs_title, from: "$.title" }
|
|
154
|
+
- { name: fs_reason, from: "$.reason" }
|
|
155
|
+
- { name: fs_hdr_contract_run, from: "$.contract_run" }
|
|
156
|
+
- { name: fs_hdr_contract, from: "$.contract" }
|
|
157
|
+
- { name: fs_hdr_client, from: "$.client" }
|
|
158
|
+
- { name: fs_settings_text, from: "$.settings_text" }
|
|
159
|
+
- { name: fs_placeholder, from: "$.placeholder" }
|
|
160
|
+
|
|
161
|
+
- id: fs_capture_manual
|
|
162
|
+
action: execute_script
|
|
163
|
+
condition: "{{fl_route}} == manual"
|
|
164
|
+
script: { ref: actions }
|
|
165
|
+
subcommand: foundation-spec-capture
|
|
166
|
+
args: ["--lane", "{{fl_lane_id}}", "--kind", "{{fl_kind}}", "--input", "{{fs_spec_input}}", "--app", "{{app}}"]
|
|
167
|
+
outputs:
|
|
168
|
+
- { name: fs_ok, from: "$.ok" }
|
|
169
|
+
- { name: fs_spec_path, from: "$.spec_path" }
|
|
170
|
+
- { name: fs_source, from: "$.source" }
|
|
171
|
+
- { name: fs_title, from: "$.title" }
|
|
172
|
+
- { name: fs_reason, from: "$.reason" }
|
|
173
|
+
- { name: fs_hdr_contract_run, from: "$.contract_run" }
|
|
174
|
+
- { name: fs_hdr_contract, from: "$.contract" }
|
|
175
|
+
- { name: fs_hdr_client, from: "$.client" }
|
|
176
|
+
- { name: fs_settings_text, from: "$.settings_text" }
|
|
177
|
+
- { name: fs_placeholder, from: "$.placeholder" }
|
|
178
|
+
|
|
179
|
+
- id: fs_capture_gate
|
|
180
|
+
action: verify_context
|
|
181
|
+
require_true: fs_ok
|
|
182
|
+
on_false: return
|
|
183
|
+
message_var: fl_status
|
|
184
|
+
on_false_message: "not built — {{fs_reason}}"
|
|
185
|
+
|
|
186
|
+
# 3. The technical rules mapped for this command, loaded as standards. `replace` resets
|
|
187
|
+
# the set to the workflow's seed first, so the frontend lane is never handed the
|
|
188
|
+
# backend lane's rules. tg_mode/tg_subset are cleared because tech-select only asks
|
|
189
|
+
# when the map has candidates — a stale answer from the other lane would otherwise
|
|
190
|
+
# load that lane's subset here.
|
|
191
|
+
- id: fs_rules
|
|
192
|
+
action: include
|
|
193
|
+
module: .appweaver/orchestrator/modules/tech-select.orch.yaml
|
|
194
|
+
with:
|
|
195
|
+
command: "aw-spec-foundation-{{fl_kind}}"
|
|
196
|
+
replace: "true"
|
|
197
|
+
tg_mode: ""
|
|
198
|
+
tg_subset: []
|
|
199
|
+
|
|
200
|
+
- id: fs_rules_why_project
|
|
201
|
+
action: set
|
|
202
|
+
condition: "{{tech_domain}} == "
|
|
203
|
+
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)" }
|
|
204
|
+
|
|
205
|
+
- id: fs_rules_why_heading
|
|
206
|
+
action: set
|
|
207
|
+
condition: "{{tech_domain}} != "
|
|
208
|
+
vars: { fs_rules_why: "guardrails/{{tech_domain}}/tech-rule-bindings.md maps no file that exists under `## /aw-spec-foundation-{{fl_kind}}`" }
|
|
209
|
+
|
|
210
|
+
- id: fs_no_rules_ask
|
|
211
|
+
action: ask
|
|
212
|
+
condition: "{{tg_candidates}} == []"
|
|
213
|
+
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?"
|
|
214
|
+
options: ["continue without them", "stop — leave this lane"]
|
|
215
|
+
answer_var: fs_rules_ack
|
|
216
|
+
|
|
217
|
+
- id: fs_no_rules_gate
|
|
218
|
+
action: verify_context
|
|
219
|
+
condition: "{{tg_candidates}} == []"
|
|
220
|
+
require_value: fs_rules_ack
|
|
221
|
+
equals: "continue without them"
|
|
222
|
+
on_mismatch: return
|
|
223
|
+
message_var: fl_status
|
|
224
|
+
on_mismatch_message: "not built — no technical rules apply ({{fs_rules_why}}); spec kept at {{fs_spec_path}}"
|
|
225
|
+
|
|
226
|
+
- id: fs_rules_line_none
|
|
227
|
+
action: set
|
|
228
|
+
condition: "{{tg_candidates}} == []"
|
|
229
|
+
vars: { fs_rules_line: "none — {{fs_rules_why}}" }
|
|
230
|
+
|
|
231
|
+
- id: fs_rules_line_all
|
|
232
|
+
action: set
|
|
233
|
+
condition: "{{tg_mode}} == all"
|
|
234
|
+
vars: { fs_rules_line: "{{tg_candidates}}" }
|
|
235
|
+
|
|
236
|
+
- id: fs_rules_line_subset
|
|
237
|
+
action: set
|
|
238
|
+
condition: "{{tg_mode}} == subset"
|
|
239
|
+
vars: { fs_rules_line: "{{tg_subset}}" }
|
|
240
|
+
|
|
241
|
+
- id: fs_rules_line_declined
|
|
242
|
+
action: set
|
|
243
|
+
condition: "{{tg_mode}} == none"
|
|
244
|
+
vars: { fs_rules_line: "none — declined at the selection" }
|
|
245
|
+
|
|
246
|
+
# 4. Confirm the build plan.
|
|
247
|
+
- id: fs_confirm
|
|
248
|
+
action: ask
|
|
249
|
+
prompt: |
|
|
250
|
+
Build the {{fl_kind}} lane from a spec
|
|
251
|
+
Spec: {{fs_spec_path}} (from {{fs_source}}: {{fs_title}})
|
|
252
|
+
App name: {{app}}
|
|
253
|
+
Lane: {{fl_lane_id}} — {{fl_title}}, {{fl_language}}
|
|
254
|
+
Folder: {{fl_source_path}} <- the whole project: build files, source and tests
|
|
255
|
+
Tests: {{fl_test_path}}
|
|
256
|
+
Commands: `{{fl_build}}` runs in {{fl_workdir}}
|
|
257
|
+
Rules: {{fs_rules_line}}
|
|
258
|
+
The agent follows the spec with the stack's own tooling, and writes nothing outside
|
|
259
|
+
these paths. Proceed?
|
|
260
|
+
options: ["yes", "no"]
|
|
261
|
+
answer_var: fs_proceed
|
|
262
|
+
|
|
263
|
+
- id: fs_confirm_gate
|
|
264
|
+
action: verify_context
|
|
265
|
+
require_value: fs_proceed
|
|
266
|
+
equals: "yes"
|
|
267
|
+
on_mismatch: return
|
|
268
|
+
message_var: fl_status
|
|
269
|
+
on_mismatch_message: "not built — declined at the confirmation; the spec is kept at {{fs_spec_path}}"
|
|
270
|
+
|
|
271
|
+
# 5. Build it. agent_generate: the agent has write tools and Bash, so it can run the
|
|
272
|
+
# stack's scaffolding CLI. The spec reaches it as context; the mapped rules are
|
|
273
|
+
# already in the standards. The repo is recorded first, so what the build does outside
|
|
274
|
+
# the lane root folder can be found afterwards (6).
|
|
275
|
+
- id: fs_snapshot
|
|
276
|
+
action: execute_script
|
|
277
|
+
script: { ref: actions }
|
|
278
|
+
subcommand: foundation-snapshot
|
|
279
|
+
args: ["--out", ".appweaver/orchestrator/.state/foundation-{{fl_lane_id}}.snapshot.json"]
|
|
280
|
+
outputs:
|
|
281
|
+
- { name: fs_snapshot_path, from: "$.snapshot" }
|
|
282
|
+
|
|
283
|
+
- id: fs_generate
|
|
284
|
+
action: agent_generate
|
|
285
|
+
context: ["{{fs_spec_path}}"]
|
|
286
|
+
task: |
|
|
287
|
+
Create the base project for the {{fl_kind}} lane `{{fl_lane_id}}` — {{fl_title}}
|
|
288
|
+
({{fl_language}}, stack profile `{{fl_profile}}`) — exactly as the spec in
|
|
289
|
+
{{fs_spec_path}} (in your context) describes. Name it after `{{app}}`, in the form
|
|
290
|
+
this stack uses for a project name.
|
|
291
|
+
|
|
292
|
+
WHERE YOU MAY WRITE — {{fl_source_path}}, the lane root folder, and nothing else, ever.
|
|
293
|
+
The WHOLE project goes inside it, complete: its build files (solution, workspace or
|
|
294
|
+
package manifest, build props, wrapper scripts), its source, and its tests — the
|
|
295
|
+
tests at {{fl_test_path}}, inside the same folder. Create the folder if absent. The
|
|
296
|
+
lane's commands run in that folder (`{{fl_build}}` runs in {{fl_workdir}}), so
|
|
297
|
+
nothing the build needs may sit outside it. Never write under .appweaver/,
|
|
298
|
+
guardrails/, foundations/ or specs/, at the repository root, or into another lane
|
|
299
|
+
root folder. This is checked when you finish: if anything outside the lane root
|
|
300
|
+
folder was created, changed or deleted, the lane is not accepted and what you
|
|
301
|
+
created there is removed.
|
|
302
|
+
|
|
303
|
+
WHAT IS THERE ALREADY: {{fs_existing_note}}
|
|
304
|
+
|
|
305
|
+
HOW:
|
|
306
|
+
- Follow the spec. Where it is silent, follow the technical rules in your standards;
|
|
307
|
+
where the spec and a rule disagree, follow the spec and name the conflict in your
|
|
308
|
+
summary.
|
|
309
|
+
- Where the spec names a scaffolding tool (dotnet new, npm create, mvn archetype,
|
|
310
|
+
…), run it so its output lands in the lane root folder itself — not a new folder
|
|
311
|
+
inside or beside it.
|
|
312
|
+
- This is the lane's BASE project. Business features are generated later by
|
|
313
|
+
/appweaver implement from the plans, so add none the spec does not ask for.
|
|
314
|
+
- The project must build with `{{fl_build}}` run in {{fl_workdir}}. Restore or
|
|
315
|
+
install what that needs; run the build once if you can and fix what it reports.
|
|
316
|
+
- THE API CONTRACT SETTINGS the spec's header gives: {{fs_settings_text}}. They are
|
|
317
|
+
recorded on the lane, and /appweaver implement uses them before it generates the
|
|
318
|
+
frontend, so the project you build has to honour them exactly:
|
|
319
|
+
· a START COMMAND (backend) — the API starts with exactly that command, run in
|
|
320
|
+
{{fl_workdir}}, ON ITS OWN: no orchestration host, and nothing it needs that
|
|
321
|
+
is not on this machine. Name the project so the path the command names exists.
|
|
322
|
+
· a DOCUMENT URL (backend) — the running API serves its OpenAPI document at
|
|
323
|
+
exactly that URL, over http, on the port it names.
|
|
324
|
+
· a CLIENT COMMAND (frontend) — that command can run in {{fl_workdir}}: install
|
|
325
|
+
its tool as a development dependency. Do not run it; the service's document
|
|
326
|
+
does not exist yet.
|
|
327
|
+
A backend built without them still serves an OpenAPI document; say at what URL,
|
|
328
|
+
and how the API starts on its own, in your summary.
|
|
329
|
+
- Do not commit, push, or change git configuration.
|
|
330
|
+
|
|
331
|
+
List every file you created or changed in `files` (paths relative to the repository
|
|
332
|
+
root; for a tool that generated many files, list the manifest and entry points).
|
|
333
|
+
outputs:
|
|
334
|
+
- { name: fs_files, from: "$.files" }
|
|
335
|
+
- { name: fs_summary, from: "$.summary" }
|
|
336
|
+
|
|
337
|
+
# 6. Did the build stay inside its lane root folder? Compared with the snapshot: anything
|
|
338
|
+
# created, changed or deleted elsewhere — the repository root, another lane, the kit's
|
|
339
|
+
# own folders — and the lane is not accepted. What the build created out there is
|
|
340
|
+
# removed again; what it changed or deleted is listed, since there is no copy to put
|
|
341
|
+
# back. Checked before anything else, so a build that wrote nothing in the lane still
|
|
342
|
+
# has its stray files found.
|
|
343
|
+
- id: fs_outside
|
|
344
|
+
action: execute_script
|
|
345
|
+
script: { ref: actions }
|
|
346
|
+
subcommand: foundation-outside
|
|
347
|
+
args: ["--snapshot", "{{fs_snapshot_path}}", "--lane", "{{fl_source_path}}", "--undo"]
|
|
348
|
+
outputs:
|
|
349
|
+
- { name: fs_inside_only, from: "$.clean" }
|
|
350
|
+
- { name: fs_outside_summary, from: "$.summary" }
|
|
351
|
+
|
|
352
|
+
- id: fs_outside_gate
|
|
353
|
+
action: verify_context
|
|
354
|
+
require_true: fs_inside_only
|
|
355
|
+
on_false: return
|
|
356
|
+
message_var: fl_status
|
|
357
|
+
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}}"
|
|
358
|
+
|
|
359
|
+
- id: fs_files_gate
|
|
360
|
+
action: verify_context
|
|
361
|
+
require_non_empty: fs_files
|
|
362
|
+
on_empty: return
|
|
363
|
+
message_var: fl_status
|
|
364
|
+
on_empty_message: "NOT built — the spec build reported no file that exists on disk; the spec is kept at {{fs_spec_path}}"
|
|
365
|
+
|
|
366
|
+
# 6. Proof: a project of this lane's ecosystem now sits INSIDE the lane — the same
|
|
367
|
+
# check implement gates on. A repo-scope hit (another lane's manifest) does not count.
|
|
368
|
+
- id: fs_detect
|
|
369
|
+
action: execute_script
|
|
370
|
+
script: { ref: actions }
|
|
371
|
+
subcommand: detect-project
|
|
372
|
+
args: ["--root", "{{fl_source_path}}", "--ecosystem", "{{fl_ecosystem}}"]
|
|
373
|
+
outputs:
|
|
374
|
+
- { name: fs_scope, from: "$.scope" }
|
|
375
|
+
- { name: fs_eco_match, from: "$.ecosystem_match" }
|
|
376
|
+
- { name: fs_markers, from: "$.markers" }
|
|
377
|
+
|
|
378
|
+
- id: fs_found_in_lane
|
|
379
|
+
action: set
|
|
380
|
+
condition: "{{fs_scope}} == lane"
|
|
381
|
+
vars: { fs_found: "true" }
|
|
382
|
+
|
|
383
|
+
- id: fs_found_wrong_eco
|
|
384
|
+
action: set
|
|
385
|
+
condition: "{{fs_eco_match}} == false"
|
|
386
|
+
vars: { fs_found: "" }
|
|
387
|
+
|
|
388
|
+
- id: fs_found_gate
|
|
389
|
+
action: verify_context
|
|
390
|
+
require_true: fs_found
|
|
391
|
+
on_false: return
|
|
392
|
+
message_var: fl_status
|
|
393
|
+
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}}"
|
|
394
|
+
|
|
395
|
+
# 7. Optionally run the lane's own build on it. It may need the network (restore /
|
|
396
|
+
# install), which is why it is asked rather than assumed.
|
|
397
|
+
- id: fs_ask_build
|
|
398
|
+
action: ask
|
|
399
|
+
prompt: "Run this lane's build now to confirm the project compiles — `{{fl_build}}` in {{fl_workdir}}? It may download packages."
|
|
400
|
+
options: ["yes — build it now", "no — I'll build later"]
|
|
401
|
+
answer_var: fs_build_ack
|
|
402
|
+
|
|
403
|
+
- id: fs_build
|
|
404
|
+
action: execute_script
|
|
405
|
+
condition: "{{fs_build_ack}} == yes — build it now"
|
|
406
|
+
on_error: continue
|
|
407
|
+
script: { ref: actions }
|
|
408
|
+
subcommand: build-compile
|
|
409
|
+
args: ["--kind", "{{fl_kind}}"]
|
|
410
|
+
outputs:
|
|
411
|
+
- { name: fs_build_ok, from: "$.ok" }
|
|
412
|
+
- { name: fs_build_tail, from: "$.failing_excerpt" }
|
|
413
|
+
|
|
414
|
+
- id: fs_build_passed
|
|
415
|
+
action: set
|
|
416
|
+
condition: "{{fs_build_ok}} == true"
|
|
417
|
+
vars: { fs_build_note: "build passed (`{{fl_build}}`)" }
|
|
418
|
+
|
|
419
|
+
- id: fs_build_failed
|
|
420
|
+
action: set
|
|
421
|
+
condition: "{{fs_build_ok}} == false"
|
|
422
|
+
vars: { fs_build_note: "build FAILED — run /appweaver build, which repairs compile errors: {{fs_build_tail}}" }
|
|
423
|
+
|
|
424
|
+
# 8. THE API CONTRACT SETTINGS — what implement uses between the lanes to export the
|
|
425
|
+
# service's OpenAPI document and generate the frontend's client from it
|
|
426
|
+
# (STACK-PROFILES.md §4.5). A backend lane needs its start command and document URL,
|
|
427
|
+
# a frontend lane its client command. Each comes from the spec's header
|
|
428
|
+
# (`# contract-run:`, `# contract:`, `# client:`, read at capture); one the header
|
|
429
|
+
# does not give is asked for, and an empty answer keeps the lane's current value —
|
|
430
|
+
# the stack profile's, unless something set it already. What there is, is recorded
|
|
431
|
+
# on the lane with lane-set, as the pack route records a pack's .lane.json.
|
|
432
|
+
- id: fs_kind_backend
|
|
433
|
+
action: set
|
|
434
|
+
condition: "{{fl_kind}} == backend"
|
|
435
|
+
vars: { fs_is_backend: "true" }
|
|
436
|
+
- id: fs_kind_frontend
|
|
437
|
+
action: set
|
|
438
|
+
condition: "{{fl_kind}} == frontend"
|
|
439
|
+
vars: { fs_is_frontend: "true" }
|
|
440
|
+
- id: fs_need_run_arm
|
|
441
|
+
action: set
|
|
442
|
+
condition: "{{fs_hdr_contract_run}} == "
|
|
443
|
+
vars: { fs_need_run: "{{fs_is_backend}}" }
|
|
444
|
+
- id: fs_need_url_arm
|
|
445
|
+
action: set
|
|
446
|
+
condition: "{{fs_hdr_contract}} == "
|
|
447
|
+
vars: { fs_need_url: "{{fs_is_backend}}" }
|
|
448
|
+
- id: fs_need_client_arm
|
|
449
|
+
action: set
|
|
450
|
+
condition: "{{fs_hdr_client}} == "
|
|
451
|
+
vars: { fs_need_client: "{{fs_is_frontend}}" }
|
|
452
|
+
|
|
453
|
+
# The lane's current values, shown as what an empty answer keeps.
|
|
454
|
+
- id: fs_current
|
|
455
|
+
action: execute_script
|
|
456
|
+
on_error: continue
|
|
457
|
+
script: { ref: actions }
|
|
458
|
+
subcommand: lane-resolve
|
|
459
|
+
args: ["--id", "{{fl_lane_id}}"]
|
|
460
|
+
outputs:
|
|
461
|
+
- { name: fs_cur_contract_run, from: "$.backend_contract_run" }
|
|
462
|
+
- { name: fs_cur_contract, from: "$.backend_contract" }
|
|
463
|
+
- { name: fs_cur_client, from: "$.frontend_client" }
|
|
464
|
+
- id: fs_cur_run_known
|
|
465
|
+
action: set
|
|
466
|
+
condition: "{{fs_cur_contract_run}} != "
|
|
467
|
+
vars: { fs_cur_run_shown: "{{fs_cur_contract_run}}" }
|
|
468
|
+
- id: fs_cur_url_known
|
|
469
|
+
action: set
|
|
470
|
+
condition: "{{fs_cur_contract}} != "
|
|
471
|
+
vars: { fs_cur_url_shown: "{{fs_cur_contract}}" }
|
|
472
|
+
- id: fs_cur_client_known
|
|
473
|
+
action: set
|
|
474
|
+
condition: "{{fs_cur_client}} != "
|
|
475
|
+
vars: { fs_cur_client_shown: "{{fs_cur_client}}" }
|
|
476
|
+
|
|
477
|
+
- id: fs_ask_contract_run
|
|
478
|
+
action: ask
|
|
479
|
+
condition: "{{fs_need_run}} == true"
|
|
480
|
+
prompt: |
|
|
481
|
+
How does the API in lane `{{fl_lane_id}}` start ON ITS OWN? /appweaver implement starts
|
|
482
|
+
it with this command to fetch its OpenAPI document before it generates the frontend.
|
|
483
|
+
The spec's header gives no `# contract-run:`.
|
|
484
|
+
Type the command — it runs in {{fl_workdir}} — with no orchestration host and nothing
|
|
485
|
+
the API cannot reach on this machine.
|
|
486
|
+
Leave it empty to keep the current one: {{fs_cur_run_shown}}
|
|
487
|
+
answer_var: fs_ans_contract_run
|
|
488
|
+
- id: fs_ask_contract
|
|
489
|
+
action: ask
|
|
490
|
+
condition: "{{fs_need_url}} == true"
|
|
491
|
+
prompt: |
|
|
492
|
+
At what URL does that running API serve its OpenAPI document? The spec's header gives
|
|
493
|
+
no `# contract:`.
|
|
494
|
+
Leave it empty to keep the current one: {{fs_cur_url_shown}}
|
|
495
|
+
answer_var: fs_ans_contract
|
|
496
|
+
- id: fs_ask_client
|
|
497
|
+
action: ask
|
|
498
|
+
condition: "{{fs_need_client}} == true"
|
|
499
|
+
prompt: |
|
|
500
|
+
Which command generates this frontend's API client from the service's OpenAPI
|
|
501
|
+
document? The spec's header gives no `# client:`.
|
|
502
|
+
It runs in {{fl_workdir}}, and {{fs_placeholder}} in it stands for the document's path —
|
|
503
|
+
for example: npx openapi-typescript {{fs_placeholder}} -o lib/api/schema.d.ts
|
|
504
|
+
Leave it empty to keep the current one: {{fs_cur_client_shown}}
|
|
505
|
+
answer_var: fs_ans_client
|
|
506
|
+
|
|
507
|
+
# What to record: the header's value for this lane's kind, or the answer where it gave
|
|
508
|
+
# none. An empty value is left out by lane-set, so the lane keeps what it has.
|
|
509
|
+
- id: fs_set_backend
|
|
510
|
+
action: set
|
|
511
|
+
condition: "{{fs_is_backend}} == true"
|
|
512
|
+
vars: { fs_set_run: "{{fs_hdr_contract_run}}", fs_set_url: "{{fs_hdr_contract}}" }
|
|
513
|
+
- id: fs_set_run_answer
|
|
514
|
+
action: set
|
|
515
|
+
condition: "{{fs_need_run}} == true"
|
|
516
|
+
vars: { fs_set_run: "{{fs_ans_contract_run}}" }
|
|
517
|
+
- id: fs_set_url_answer
|
|
518
|
+
action: set
|
|
519
|
+
condition: "{{fs_need_url}} == true"
|
|
520
|
+
vars: { fs_set_url: "{{fs_ans_contract}}" }
|
|
521
|
+
- id: fs_set_frontend
|
|
522
|
+
action: set
|
|
523
|
+
condition: "{{fs_is_frontend}} == true"
|
|
524
|
+
vars: { fs_set_client: "{{fs_hdr_client}}" }
|
|
525
|
+
- id: fs_set_client_answer
|
|
526
|
+
action: set
|
|
527
|
+
condition: "{{fs_need_client}} == true"
|
|
528
|
+
vars: { fs_set_client: "{{fs_ans_client}}" }
|
|
529
|
+
|
|
530
|
+
- id: fs_lane_record
|
|
531
|
+
action: execute_script
|
|
532
|
+
on_error: continue
|
|
533
|
+
script: { ref: actions }
|
|
534
|
+
subcommand: lane-set
|
|
535
|
+
args: ["--id", "{{fl_lane_id}}", "--set", "contract_run={{fs_set_run}}", "--set", "contract={{fs_set_url}}", "--set", "client={{fs_set_client}}"]
|
|
536
|
+
outputs:
|
|
537
|
+
- { name: fs_lane_written, from: "$.written" }
|
|
538
|
+
- id: fs_lane_noted
|
|
539
|
+
action: set
|
|
540
|
+
condition: "{{fs_lane_written}} == true"
|
|
541
|
+
vars: { fs_lane_note: "; API-contract settings recorded on the {{fl_lane_id}} lane" }
|
|
542
|
+
|
|
543
|
+
- id: fs_done
|
|
544
|
+
action: set
|
|
545
|
+
vars:
|
|
546
|
+
fl_spec_path: "{{fs_spec_path}}"
|
|
547
|
+
fl_files: "{{fs_files}}"
|
|
548
|
+
fl_status: "built from the spec in {{fs_spec_path}} (from {{fs_source}}) into {{fl_source_path}} — {{fs_summary}}; {{fs_build_note}}{{fs_lane_note}}"
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
# =============================================================================
|
|
2
|
-
# lane-gate (orchestrator) — shared LANE +
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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/
|
|
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
|