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,237 @@
|
|
|
1
|
+
# =============================================================================
|
|
2
|
+
# foundation-lane (orchestrator) — scaffold ONE declared lane
|
|
3
|
+
#
|
|
4
|
+
# Included by aw-spec-foundation once per lane kind — backend first, then frontend — with
|
|
5
|
+
# that lane's fields passed through `with:`. It answers "what is this lane built from?"
|
|
6
|
+
# and hands off:
|
|
7
|
+
#
|
|
8
|
+
# 1. Can the lane take a foundation — does it run its commands inside its lane root folder
|
|
9
|
+
# and keep its tests there? If not, it is reported and passed over. Then: does it
|
|
10
|
+
# already hold files? If so, ask to overwrite them; "no" skips the lane and nothing
|
|
11
|
+
# else is asked. Each lane is asked on its own.
|
|
12
|
+
# 2. List what fits the lane: every pack and spec under foundations/<ecosystem>/ whose
|
|
13
|
+
# `# kind:` / `# profiles:` header admits this lane, then [manual spec] and [skip].
|
|
14
|
+
# 3. Pick one. A fast-path name (`/appweaver foundation VerticalSlice App`) preselects
|
|
15
|
+
# its entry in whichever lane lists it.
|
|
16
|
+
# 4. pack -> foundation-pack (unpack the verified bundle, as before)
|
|
17
|
+
# spec | manual spec -> foundation-spec (an agent builds the project from the spec)
|
|
18
|
+
# skip -> nothing is written.
|
|
19
|
+
#
|
|
20
|
+
# Every refusal in here and in the two route modules RETURNS rather than stops, so the
|
|
21
|
+
# caller always reaches the next lane; the reason is in fl_status, which the caller
|
|
22
|
+
# reports per lane at the end of the run.
|
|
23
|
+
#
|
|
24
|
+
# Inputs (via include `with:`):
|
|
25
|
+
# fl_kind, fl_lane_id, fl_profile, fl_title, fl_language, fl_ecosystem,
|
|
26
|
+
# fl_source_path, fl_test_path, fl_workdir, fl_build
|
|
27
|
+
# Shared with the caller: USER_INPUT (the fast path) and `app` (asked once per run, the
|
|
28
|
+
# first time a lane needs it, and reused by the next lane).
|
|
29
|
+
# Produces: fl_status, fl_route, fl_name, fl_spec_path, fl_files, and fl_overwrite ("yes"
|
|
30
|
+
# when the lane already had files and the operator agreed to overwrite them), which the
|
|
31
|
+
# two route modules read.
|
|
32
|
+
# =============================================================================
|
|
33
|
+
|
|
34
|
+
name: foundation-lane
|
|
35
|
+
dialect: aw-spec.orchestrator/v1
|
|
36
|
+
|
|
37
|
+
scripts:
|
|
38
|
+
actions:
|
|
39
|
+
sh: .appweaver/scripts/bash/aw-spec-actions.sh
|
|
40
|
+
ps1: .appweaver/scripts/powershell/aw-spec-actions.ps1
|
|
41
|
+
|
|
42
|
+
workflow:
|
|
43
|
+
|
|
44
|
+
# 0. Vars are shared across the two includes; start this lane clean.
|
|
45
|
+
- id: fl_reset
|
|
46
|
+
action: set
|
|
47
|
+
vars:
|
|
48
|
+
fl_status: "not scaffolded"
|
|
49
|
+
fl_route: ""
|
|
50
|
+
fl_name: ""
|
|
51
|
+
fl_spec_file: ""
|
|
52
|
+
fl_spec_path: ""
|
|
53
|
+
fl_files: ""
|
|
54
|
+
fl_has_files: ""
|
|
55
|
+
fl_files_summary: ""
|
|
56
|
+
fl_self_contained: ""
|
|
57
|
+
fl_shape_reason: ""
|
|
58
|
+
fl_overwrite_answer: ""
|
|
59
|
+
fl_overwrite: ""
|
|
60
|
+
fl_overwrite_note: ""
|
|
61
|
+
fl_go: "true"
|
|
62
|
+
fl_spec_route: ""
|
|
63
|
+
|
|
64
|
+
- id: fl_has_root
|
|
65
|
+
action: verify_context
|
|
66
|
+
require_non_empty: fl_source_path
|
|
67
|
+
on_empty: return
|
|
68
|
+
message_var: fl_status
|
|
69
|
+
on_empty_message: "not scaffolded — lane `{{fl_lane_id}}` declares no lane root folder in .appweaver/stacks.json; re-run /appweaver select-stack and give it its lane root folder"
|
|
70
|
+
|
|
71
|
+
# 1. Does the lane already hold files? Any file in its lane root folder or test path counts,
|
|
72
|
+
# whatever stack wrote it, and so do its build files where its commands run when that
|
|
73
|
+
# is outside the lane (a .NET solution at the repo root). Asked BEFORE the pick list,
|
|
74
|
+
# so "no" skips this lane with nothing else asked and the run moves on to the next one.
|
|
75
|
+
# The first option is the non-interactive default, so an unattended run never
|
|
76
|
+
# overwrites. The answer key carries the lane kind, so a scripted run answers each lane
|
|
77
|
+
# on its own: --answer fl_overwrite_backend=yes --answer fl_overwrite_frontend=no.
|
|
78
|
+
- id: fl_files_check
|
|
79
|
+
action: execute_script
|
|
80
|
+
script: { ref: actions }
|
|
81
|
+
subcommand: foundation-lane-files
|
|
82
|
+
args: ["--source", "{{fl_source_path}}", "--test", "{{fl_test_path}}", "--workdir", "{{fl_workdir}}", "--profile", "{{fl_profile}}"]
|
|
83
|
+
outputs:
|
|
84
|
+
- { name: fl_has_files, from: "$.has_files" }
|
|
85
|
+
- { name: fl_files_summary, from: "$.summary" }
|
|
86
|
+
- { name: fl_self_contained, from: "$.self_contained" }
|
|
87
|
+
- { name: fl_shape_reason, from: "$.shape_reason" }
|
|
88
|
+
|
|
89
|
+
# A foundation is a complete project that lands INSIDE the lane root folder — build files,
|
|
90
|
+
# source and tests — so the lane has to run its commands there and keep its tests there.
|
|
91
|
+
# A lane declared the classic way (code in src/, solution and tests/ at the repo root)
|
|
92
|
+
# suits existing code but would get a project its own build cannot find; it is reported
|
|
93
|
+
# here, before anything is asked, and the run moves on to the next lane.
|
|
94
|
+
- id: fl_shape_gate
|
|
95
|
+
action: verify_context
|
|
96
|
+
require_true: fl_self_contained
|
|
97
|
+
on_false: return
|
|
98
|
+
message_var: fl_status
|
|
99
|
+
on_false_message: "not scaffolded — {{fl_shape_reason}}"
|
|
100
|
+
|
|
101
|
+
- id: fl_ask_overwrite
|
|
102
|
+
action: ask
|
|
103
|
+
condition: "{{fl_has_files}} == true"
|
|
104
|
+
prompt: >
|
|
105
|
+
{{fl_kind}} lane `{{fl_lane_id}}` ({{fl_profile}}) already has files — {{fl_files_summary}}.
|
|
106
|
+
Scaffolding it writes into these folders and replaces files with the same path; files
|
|
107
|
+
with other names stay, and nothing is deleted. Overwrite?
|
|
108
|
+
options: ["no — skip this lane", "yes — overwrite"]
|
|
109
|
+
answer_key: "fl_overwrite_{{fl_kind}}"
|
|
110
|
+
answer_var: fl_overwrite_answer
|
|
111
|
+
|
|
112
|
+
# The answer is free text from the launcher: the full option and a bare `yes` both count.
|
|
113
|
+
- id: fl_overwrite_option
|
|
114
|
+
action: set
|
|
115
|
+
condition: "{{fl_overwrite_answer}} == yes — overwrite"
|
|
116
|
+
vars: { fl_overwrite: "yes" }
|
|
117
|
+
|
|
118
|
+
- id: fl_overwrite_short
|
|
119
|
+
action: set
|
|
120
|
+
condition: "{{fl_overwrite_answer}} == yes"
|
|
121
|
+
vars: { fl_overwrite: "yes" }
|
|
122
|
+
|
|
123
|
+
- id: fl_overwrite_gate
|
|
124
|
+
action: verify_context
|
|
125
|
+
condition: "{{fl_has_files}} == true"
|
|
126
|
+
require_value: fl_overwrite
|
|
127
|
+
equals: "yes"
|
|
128
|
+
on_mismatch: return
|
|
129
|
+
message_var: fl_status
|
|
130
|
+
on_mismatch_message: "skipped — the lane already has files ({{fl_files_summary}}) and overwriting them was declined"
|
|
131
|
+
|
|
132
|
+
- id: fl_overwrite_noted
|
|
133
|
+
action: set
|
|
134
|
+
condition: "{{fl_overwrite}} == yes"
|
|
135
|
+
vars: { fl_overwrite_note: " It already has files, and you chose to overwrite them." }
|
|
136
|
+
|
|
137
|
+
# 2. What fits this lane.
|
|
138
|
+
- id: fl_list
|
|
139
|
+
action: execute_script
|
|
140
|
+
script: { ref: actions }
|
|
141
|
+
subcommand: foundation-list
|
|
142
|
+
args: ["--kind", "{{fl_kind}}", "--profile", "{{fl_profile}}", "--ecosystem", "{{fl_ecosystem}}", "--lane-id", "{{fl_lane_id}}", "--args", "{{USER_INPUT}}"]
|
|
143
|
+
outputs:
|
|
144
|
+
- { name: fl_options, from: "$.options" }
|
|
145
|
+
- { name: fl_count, from: "$.count" }
|
|
146
|
+
- { name: fl_all, from: "$.all_foundations" }
|
|
147
|
+
- { name: fl_preselect, from: "$.preselect_option" }
|
|
148
|
+
|
|
149
|
+
# 3. Pick. There are always at least two options ([manual spec] and [skip]), so this
|
|
150
|
+
# always asks unless the fast path named an entry this lane offers.
|
|
151
|
+
- id: fl_pick
|
|
152
|
+
action: user_select
|
|
153
|
+
prompt: >
|
|
154
|
+
{{fl_kind}} lane `{{fl_lane_id}}` — {{fl_title}} at {{fl_source_path}}.{{fl_overwrite_note}}
|
|
155
|
+
What should it be scaffolded from? A [pack] is a verified project unpacked as-is; a
|
|
156
|
+
[spec] describes a project the agent builds into the lane; [manual spec] lets you give
|
|
157
|
+
that description yourself; [skip] leaves the lane untouched.
|
|
158
|
+
({{fl_count}} of the foundations shipped fit this lane; all of them: {{fl_all}})
|
|
159
|
+
options_from_variable: fl_options
|
|
160
|
+
preselect_from: fl_preselect
|
|
161
|
+
outputs:
|
|
162
|
+
- { name: fl_selection, from: selection }
|
|
163
|
+
|
|
164
|
+
- id: fl_choice
|
|
165
|
+
action: execute_script
|
|
166
|
+
script: { ref: actions }
|
|
167
|
+
subcommand: foundation-choice
|
|
168
|
+
args: ["--selection", "{{fl_selection}}", "--kind", "{{fl_kind}}", "--profile", "{{fl_profile}}", "--ecosystem", "{{fl_ecosystem}}"]
|
|
169
|
+
outputs:
|
|
170
|
+
- { name: fl_choice_ok, from: "$.ok" }
|
|
171
|
+
- { name: fl_route, from: "$.route" }
|
|
172
|
+
- { name: fl_name, from: "$.name" }
|
|
173
|
+
- { name: fl_spec_file, from: "$.file" }
|
|
174
|
+
- { name: fl_choice_msg, from: "$.reason" }
|
|
175
|
+
|
|
176
|
+
- id: fl_choice_gate
|
|
177
|
+
action: verify_context
|
|
178
|
+
require_true: fl_choice_ok
|
|
179
|
+
on_false: return
|
|
180
|
+
message_var: fl_status
|
|
181
|
+
on_false_message: "not scaffolded — {{fl_choice_msg}}"
|
|
182
|
+
|
|
183
|
+
- id: fl_skip
|
|
184
|
+
action: set
|
|
185
|
+
condition: "{{fl_route}} == skip"
|
|
186
|
+
vars: { fl_go: "" }
|
|
187
|
+
|
|
188
|
+
- id: fl_skip_gate
|
|
189
|
+
action: verify_context
|
|
190
|
+
require_true: fl_go
|
|
191
|
+
on_false: return
|
|
192
|
+
message_var: fl_status
|
|
193
|
+
on_false_message: "skipped — left as it is, by choice"
|
|
194
|
+
|
|
195
|
+
# 4. The project name — asked once per run, the first time a lane needs it, unless the
|
|
196
|
+
# fast path gave it. The next lane reuses it.
|
|
197
|
+
- id: fl_ask_app
|
|
198
|
+
action: ask
|
|
199
|
+
condition: "{{app}} == "
|
|
200
|
+
prompt: >
|
|
201
|
+
Enter the project (application) name, e.g. AppWeaver.Health. A pack renames its
|
|
202
|
+
sentinel to it; a spec build names the project after it, in the form the stack uses.
|
|
203
|
+
It is asked once and used for every lane in this run.
|
|
204
|
+
answer_var: app_typed
|
|
205
|
+
|
|
206
|
+
- id: fl_app_from_typed
|
|
207
|
+
action: set
|
|
208
|
+
condition: "{{app}} == "
|
|
209
|
+
vars: { app: "{{app_typed}}" }
|
|
210
|
+
|
|
211
|
+
- id: fl_app_gate
|
|
212
|
+
action: verify_context
|
|
213
|
+
require_non_empty: app
|
|
214
|
+
on_empty: return
|
|
215
|
+
message_var: fl_status
|
|
216
|
+
on_empty_message: "not scaffolded — no project name was given"
|
|
217
|
+
|
|
218
|
+
# 5. Hand off. The engine has no OR, so the two spec routes set one flag.
|
|
219
|
+
- id: fl_route_spec
|
|
220
|
+
action: set
|
|
221
|
+
condition: "{{fl_route}} == spec"
|
|
222
|
+
vars: { fl_spec_route: "true" }
|
|
223
|
+
|
|
224
|
+
- id: fl_route_manual
|
|
225
|
+
action: set
|
|
226
|
+
condition: "{{fl_route}} == manual"
|
|
227
|
+
vars: { fl_spec_route: "true" }
|
|
228
|
+
|
|
229
|
+
- id: pack
|
|
230
|
+
action: include
|
|
231
|
+
condition: "{{fl_route}} == pack"
|
|
232
|
+
module: .appweaver/orchestrator/modules/foundation-pack.orch.yaml
|
|
233
|
+
|
|
234
|
+
- id: spec
|
|
235
|
+
action: include
|
|
236
|
+
condition: "{{fl_spec_route}} == true"
|
|
237
|
+
module: .appweaver/orchestrator/modules/foundation-spec.orch.yaml
|
|
@@ -0,0 +1,392 @@
|
|
|
1
|
+
# =============================================================================
|
|
2
|
+
# foundation-pack (orchestrator) — scaffold ONE lane by unpacking a foundation pack
|
|
3
|
+
#
|
|
4
|
+
# Included by foundation-lane when the operator picks a `[pack]` entry. Almost entirely
|
|
5
|
+
# deterministic: locate the verified byte-for-byte bundle, confirm, dry-run for
|
|
6
|
+
# collisions, unpack into the lane root folder exactly as packed with the sentinel renamed,
|
|
7
|
+
# optionally add the reference sample on top, and check that no sentinel is left behind.
|
|
8
|
+
#
|
|
9
|
+
# Its LANE SETTINGS (<pack name>.lane.json beside the pack), when it has any, are recorded
|
|
10
|
+
# on the lane once it is unpacked.
|
|
11
|
+
#
|
|
12
|
+
# Every file in a pack lands as packed, replacing a file already there — except the ones
|
|
13
|
+
# its RULE FILE (<pack name>.rules.json beside the pack) says to merge. The model is used
|
|
14
|
+
# ONLY for those merges: an `agent_author` (read-only generation, the ENGINE writes the
|
|
15
|
+
# file) with include_standards: false and a two-file context — the file that was there
|
|
16
|
+
# and the pack's version — following the rule's own instruction.
|
|
17
|
+
#
|
|
18
|
+
# Every refusal RETURNS rather than stops: the run carries on with the next lane, and the
|
|
19
|
+
# reason lands in fl_status (message_var), which the caller reports per lane.
|
|
20
|
+
#
|
|
21
|
+
# Inputs (shared vars, set by foundation-lane):
|
|
22
|
+
# fl_name, app, fl_kind, fl_lane_id, fl_title, fl_language, fl_ecosystem,
|
|
23
|
+
# fl_source_path, fl_test_path, fl_overwrite
|
|
24
|
+
# Produces: fl_status, fl_files (files written), and the fp_* details.
|
|
25
|
+
# =============================================================================
|
|
26
|
+
|
|
27
|
+
name: foundation-pack
|
|
28
|
+
dialect: aw-spec.orchestrator/v1
|
|
29
|
+
|
|
30
|
+
scripts:
|
|
31
|
+
actions:
|
|
32
|
+
sh: .appweaver/scripts/bash/aw-spec-actions.sh
|
|
33
|
+
ps1: .appweaver/scripts/powershell/aw-spec-actions.ps1
|
|
34
|
+
|
|
35
|
+
workflow:
|
|
36
|
+
|
|
37
|
+
# 0. This module runs once per lane in the same run, and vars are shared — the second
|
|
38
|
+
# lane must not inherit the first lane's overwrite answer or reference choice.
|
|
39
|
+
- id: fp_reset
|
|
40
|
+
action: set
|
|
41
|
+
vars:
|
|
42
|
+
fp_overwrite: "no"
|
|
43
|
+
fp_has_collisions: "false"
|
|
44
|
+
fp_want_reference: "no"
|
|
45
|
+
fp_has_reference: "false"
|
|
46
|
+
fp_merge_state: ".appweaver/orchestrator/.state/foundation-{{fl_lane_id}}.merge/"
|
|
47
|
+
fp_rules_ok: ""
|
|
48
|
+
fp_rules_reason: ""
|
|
49
|
+
fp_rules_file: ""
|
|
50
|
+
fp_merges: "[]"
|
|
51
|
+
fp_rules_note: ""
|
|
52
|
+
fp_ref_rules_ok: ""
|
|
53
|
+
fp_ref_rules_reason: ""
|
|
54
|
+
fp_ref_rules_file: ""
|
|
55
|
+
fp_ref_merges: "[]"
|
|
56
|
+
fp_ref_rules_note: ""
|
|
57
|
+
fp_ref_go: "no"
|
|
58
|
+
fp_ok: ""
|
|
59
|
+
fp_written: "0"
|
|
60
|
+
fp_tests_message: ""
|
|
61
|
+
fp_tests_note: ""
|
|
62
|
+
fp_ref_ok: ""
|
|
63
|
+
fp_ref_written: "0"
|
|
64
|
+
fp_ref_tests_message: ""
|
|
65
|
+
fp_ref_note: ""
|
|
66
|
+
fp_clean: ""
|
|
67
|
+
fp_residue: ""
|
|
68
|
+
fp_residue_note: "not checked"
|
|
69
|
+
fp_lane_found: "false"
|
|
70
|
+
fp_lane_file: ""
|
|
71
|
+
fp_lane_contract_run: ""
|
|
72
|
+
fp_lane_contract: ""
|
|
73
|
+
fp_lane_client: ""
|
|
74
|
+
fp_lane_recorded: ""
|
|
75
|
+
fp_lane_note: ""
|
|
76
|
+
|
|
77
|
+
# 1. Locate the bundle + its unpacker and read the (bounded) pack header: the sentinel,
|
|
78
|
+
# the file count, and whether a Reference pack ships beside it.
|
|
79
|
+
- id: fp_locate
|
|
80
|
+
action: execute_script
|
|
81
|
+
script: { ref: actions }
|
|
82
|
+
subcommand: foundation-locate
|
|
83
|
+
args: ["--name", "{{fl_name}}", "--app", "{{app}}", "--out", "{{fl_source_path}}"]
|
|
84
|
+
outputs:
|
|
85
|
+
- { name: fp_locate_ok, from: "$.ok" }
|
|
86
|
+
- { name: fp_locate_msg, from: "$.reason" }
|
|
87
|
+
- { name: fp_available, from: "$.available" }
|
|
88
|
+
- { name: fp_sentinel, from: "$.sentinel" }
|
|
89
|
+
- { name: fp_file_count, from: "$.file_count" }
|
|
90
|
+
- { name: fp_has_reference, from: "$.has_reference" }
|
|
91
|
+
|
|
92
|
+
- id: fp_locate_gate
|
|
93
|
+
action: verify_context
|
|
94
|
+
require_true: fp_locate_ok
|
|
95
|
+
on_false: return
|
|
96
|
+
message_var: fl_status
|
|
97
|
+
on_false_message: "not scaffolded — {{fp_locate_msg}} (packs available: {{fp_available}})"
|
|
98
|
+
|
|
99
|
+
# 1b. The lane already had files and foundation-lane's overwrite question was answered
|
|
100
|
+
# yes before the pick list: that answer stands, so the unpack overwrites and the
|
|
101
|
+
# collision question below is not asked a second time.
|
|
102
|
+
- id: fp_overwrite_agreed
|
|
103
|
+
action: set
|
|
104
|
+
condition: "{{fl_overwrite}} == yes"
|
|
105
|
+
vars: { fp_overwrite: "yes" }
|
|
106
|
+
|
|
107
|
+
# 2. Confirm (checkpoint kind 'ask' under every strategy).
|
|
108
|
+
- id: fp_confirm
|
|
109
|
+
action: ask
|
|
110
|
+
prompt: |
|
|
111
|
+
Foundation: {{fl_name}} pack (sentinel {{fp_sentinel}}, {{fp_file_count}} files)
|
|
112
|
+
App name: {{app}}
|
|
113
|
+
Lane: {{fl_lane_id}} — {{fl_title}}, {{fl_language}} ({{fl_ecosystem}})
|
|
114
|
+
Folder: {{fl_source_path}} <- the pack unpacks here as packed: build files, source and tests
|
|
115
|
+
Tests: {{fl_test_path}}
|
|
116
|
+
Overwrite: {{fp_overwrite}} <- yes: files the pack writes replace existing ones
|
|
117
|
+
The sentinel {{fp_sentinel}} is renamed to {{app}} in file contents and paths, as the
|
|
118
|
+
replacement contract in the pack's header describes. Proceed?
|
|
119
|
+
options: ["yes", "no"]
|
|
120
|
+
answer_var: fp_proceed
|
|
121
|
+
|
|
122
|
+
- id: fp_confirm_gate
|
|
123
|
+
action: verify_context
|
|
124
|
+
require_value: fp_proceed
|
|
125
|
+
equals: "yes"
|
|
126
|
+
on_mismatch: return
|
|
127
|
+
message_var: fl_status
|
|
128
|
+
on_mismatch_message: "not scaffolded — the {{fl_name}} pack was declined at the confirmation; nothing was written to {{fl_source_path}}"
|
|
129
|
+
|
|
130
|
+
# 3. Dry-run to surface collisions, then confirm overwrite if needed — only for a lane
|
|
131
|
+
# that was empty: one that already had files was asked before the pick list (step 1b).
|
|
132
|
+
- id: fp_dry_run
|
|
133
|
+
action: execute_script
|
|
134
|
+
condition: "{{fl_overwrite}} != yes"
|
|
135
|
+
script: { ref: actions }
|
|
136
|
+
subcommand: foundation-unpack
|
|
137
|
+
args: ["--name", "{{fl_name}}", "--app", "{{app}}", "--out", "{{fl_source_path}}", "--dry-run"]
|
|
138
|
+
outputs:
|
|
139
|
+
- { name: fp_has_collisions, from: "$.has_collisions" }
|
|
140
|
+
|
|
141
|
+
- id: fp_ask_overwrite
|
|
142
|
+
action: ask
|
|
143
|
+
condition: "{{fp_has_collisions}} == true"
|
|
144
|
+
prompt: "Files the {{fl_name}} pack writes already exist under {{fl_source_path}}. Overwrite them?"
|
|
145
|
+
options: ["yes", "no"]
|
|
146
|
+
answer_var: fp_overwrite
|
|
147
|
+
|
|
148
|
+
- id: fp_overwrite_gate
|
|
149
|
+
action: verify_context
|
|
150
|
+
condition: "{{fp_has_collisions}} == true"
|
|
151
|
+
require_value: fp_overwrite
|
|
152
|
+
equals: "yes"
|
|
153
|
+
on_mismatch: return
|
|
154
|
+
message_var: fl_status
|
|
155
|
+
on_mismatch_message: "not scaffolded — files the {{fl_name}} pack writes already exist under {{fl_source_path}} and overwriting them was declined"
|
|
156
|
+
|
|
157
|
+
# 4. The pack's rule file: which of its files are merged with what the lane holds now.
|
|
158
|
+
# Read before anything is written, so a broken rule file leaves the lane untouched;
|
|
159
|
+
# the files to merge with are put aside under fp_merge_state.
|
|
160
|
+
- id: fp_rules
|
|
161
|
+
action: execute_script
|
|
162
|
+
script: { ref: actions }
|
|
163
|
+
subcommand: foundation-rules
|
|
164
|
+
args: ["--name", "{{fl_name}}", "--app", "{{app}}", "--out", "{{fl_source_path}}", "--state", "{{fp_merge_state}}"]
|
|
165
|
+
outputs:
|
|
166
|
+
- { name: fp_rules_ok, from: "$.ok" }
|
|
167
|
+
- { name: fp_rules_reason, from: "$.reason" }
|
|
168
|
+
- { name: fp_rules_file, from: "$.rules_file" }
|
|
169
|
+
- { name: fp_merges, from: "$.merges" }
|
|
170
|
+
- { name: fp_rules_note, from: "$.note" }
|
|
171
|
+
|
|
172
|
+
- id: fp_rules_gate
|
|
173
|
+
action: verify_context
|
|
174
|
+
require_true: fp_rules_ok
|
|
175
|
+
on_false: return
|
|
176
|
+
message_var: fl_status
|
|
177
|
+
on_false_message: "not scaffolded — {{fp_rules_reason}}; nothing was written to {{fl_source_path}}"
|
|
178
|
+
|
|
179
|
+
# 5. Unpack for real, and check it worked: an unpacker that refuses (existing files, a
|
|
180
|
+
# bad name) exits non-zero with 0 files written, and reporting that as a scaffold is
|
|
181
|
+
# how a lane with no project gets as far as implement.
|
|
182
|
+
- id: fp_unpack
|
|
183
|
+
action: execute_script
|
|
184
|
+
script: { ref: actions }
|
|
185
|
+
subcommand: foundation-unpack
|
|
186
|
+
args: ["--name", "{{fl_name}}", "--app", "{{app}}", "--out", "{{fl_source_path}}", "--test-path", "{{fl_test_path}}", "--force", "{{fp_overwrite}}"]
|
|
187
|
+
outputs:
|
|
188
|
+
- { name: fp_ok, from: "$.ok" }
|
|
189
|
+
- { name: fp_written, from: "$.written" }
|
|
190
|
+
- { name: fp_tests_message, from: "$.tests_message" }
|
|
191
|
+
- { name: fp_unpack_out, from: "$.stdout" }
|
|
192
|
+
|
|
193
|
+
- id: fp_unpack_gate
|
|
194
|
+
action: verify_context
|
|
195
|
+
require_true: fp_ok
|
|
196
|
+
on_false: return
|
|
197
|
+
message_var: fl_status
|
|
198
|
+
on_false_message: "NOT scaffolded — the {{fl_name}} unpacker failed and wrote {{fp_written}} file(s). Its output ends: {{fp_unpack_out}}"
|
|
199
|
+
|
|
200
|
+
# 5b. The pack's LANE SETTINGS (<pack name>.lane.json beside it): what only the pack
|
|
201
|
+
# knows about the project it scaffolds — chiefly how its service is started on its
|
|
202
|
+
# own so implement can export the API document. Recorded on the lane with lane-set;
|
|
203
|
+
# a key the file leaves empty is not touched, and a pack with no such file leaves
|
|
204
|
+
# the lane on its stack profile's values.
|
|
205
|
+
- id: fp_lane_settings
|
|
206
|
+
action: execute_script
|
|
207
|
+
on_error: continue
|
|
208
|
+
script: { ref: actions }
|
|
209
|
+
subcommand: foundation-pack-lane
|
|
210
|
+
args: ["--name", "{{fl_name}}", "--app", "{{app}}"]
|
|
211
|
+
outputs:
|
|
212
|
+
- { name: fp_lane_found, from: "$.found" }
|
|
213
|
+
- { name: fp_lane_file, from: "$.file" }
|
|
214
|
+
- { name: fp_lane_contract_run, from: "$.contract_run" }
|
|
215
|
+
- { name: fp_lane_contract, from: "$.contract" }
|
|
216
|
+
- { name: fp_lane_client, from: "$.client" }
|
|
217
|
+
|
|
218
|
+
- id: fp_lane_record
|
|
219
|
+
action: execute_script
|
|
220
|
+
condition: "{{fp_lane_found}} == true"
|
|
221
|
+
on_error: continue
|
|
222
|
+
script: { ref: actions }
|
|
223
|
+
subcommand: lane-set
|
|
224
|
+
args: ["--id", "{{fl_lane_id}}", "--set", "contract_run={{fp_lane_contract_run}}", "--set", "contract={{fp_lane_contract}}", "--set", "client={{fp_lane_client}}"]
|
|
225
|
+
outputs:
|
|
226
|
+
- { name: fp_lane_recorded, from: "$.ok" }
|
|
227
|
+
|
|
228
|
+
- id: fp_lane_noted
|
|
229
|
+
action: set
|
|
230
|
+
condition: "{{fp_lane_recorded}} == true"
|
|
231
|
+
vars: { fp_lane_note: "; the pack's API-export settings ({{fp_lane_file}}) recorded on the {{fl_lane_id}} lane" }
|
|
232
|
+
|
|
233
|
+
# 6. The merges the rule file asks for: the file that was there (put aside) and the
|
|
234
|
+
# pack's version (now on disk) become one, as the rule's instruction says.
|
|
235
|
+
- id: fp_merge
|
|
236
|
+
action: loop
|
|
237
|
+
over: "{{fp_merges}}"
|
|
238
|
+
as: m
|
|
239
|
+
steps:
|
|
240
|
+
- id: fp_merge_file
|
|
241
|
+
action: agent_author
|
|
242
|
+
context: ["{{m.existing}}", "{{m.target}}"]
|
|
243
|
+
include_standards: false
|
|
244
|
+
task: |
|
|
245
|
+
Merge two versions of {{m.target}} into one file.
|
|
246
|
+
EXISTING {{m.existing}} — the file as it was in the lane before the {{fl_name}} pack was unpacked
|
|
247
|
+
INCOMING {{m.target}} — the file as the pack ships it, with {{fp_sentinel}} renamed to {{app}}
|
|
248
|
+
The pack's rule file ({{fp_rules_file}}) says how, in its rule for {{m.rule}}:
|
|
249
|
+
{{m.instruction}}
|
|
250
|
+
Change nothing that instruction does not ask for.
|
|
251
|
+
output_target: { type: file, path: "{{m.target}}" }
|
|
252
|
+
|
|
253
|
+
- id: fp_rules_done
|
|
254
|
+
action: execute_script
|
|
255
|
+
script: { ref: actions }
|
|
256
|
+
subcommand: foundation-rules-done
|
|
257
|
+
args: ["--state", "{{fp_merge_state}}"]
|
|
258
|
+
|
|
259
|
+
# 7. Optional reference sample — offered only when the pack ships one. It goes on top
|
|
260
|
+
# of the base project the same way: its own rule file, the unpack, its merges.
|
|
261
|
+
- id: fp_ask_reference
|
|
262
|
+
action: ask
|
|
263
|
+
condition: "{{fp_has_reference}} == true"
|
|
264
|
+
prompt: "The {{fl_name}} foundation also ships a reference sample ({{fl_name}}.Reference.pack.txt): worked example code unpacked on top of the base project. Include it?"
|
|
265
|
+
options: ["yes", "no"]
|
|
266
|
+
answer_var: fp_want_reference
|
|
267
|
+
|
|
268
|
+
- id: fp_ref_rules
|
|
269
|
+
action: execute_script
|
|
270
|
+
condition: "{{fp_want_reference}} == yes"
|
|
271
|
+
script: { ref: actions }
|
|
272
|
+
subcommand: foundation-rules
|
|
273
|
+
args: ["--name", "{{fl_name}}", "--app", "{{app}}", "--out", "{{fl_source_path}}", "--reference", "--state", "{{fp_merge_state}}"]
|
|
274
|
+
outputs:
|
|
275
|
+
- { name: fp_ref_rules_ok, from: "$.ok" }
|
|
276
|
+
- { name: fp_ref_rules_reason, from: "$.reason" }
|
|
277
|
+
- { name: fp_ref_rules_file, from: "$.rules_file" }
|
|
278
|
+
- { name: fp_ref_merges, from: "$.merges" }
|
|
279
|
+
- { name: fp_ref_rules_note, from: "$.note" }
|
|
280
|
+
|
|
281
|
+
# A broken rule file keeps the sample out but leaves the base project in place, so this
|
|
282
|
+
# reports and carries on rather than returning.
|
|
283
|
+
- id: fp_ref_rules_gate
|
|
284
|
+
action: verify_context
|
|
285
|
+
condition: "{{fp_want_reference}} == yes"
|
|
286
|
+
require_true: fp_ref_rules_ok
|
|
287
|
+
on_false: continue
|
|
288
|
+
message_var: fp_ref_note
|
|
289
|
+
on_false_message: "; the reference sample was NOT added — {{fp_ref_rules_reason}}"
|
|
290
|
+
|
|
291
|
+
- id: fp_ref_go
|
|
292
|
+
action: set
|
|
293
|
+
condition: "{{fp_ref_rules_ok}} == true"
|
|
294
|
+
vars: { fp_ref_go: "yes" }
|
|
295
|
+
|
|
296
|
+
- id: fp_reference_unpack
|
|
297
|
+
action: execute_script
|
|
298
|
+
condition: "{{fp_ref_go}} == yes"
|
|
299
|
+
script: { ref: actions }
|
|
300
|
+
subcommand: foundation-unpack
|
|
301
|
+
args: ["--name", "{{fl_name}}", "--app", "{{app}}", "--out", "{{fl_source_path}}", "--test-path", "{{fl_test_path}}", "--reference"]
|
|
302
|
+
outputs:
|
|
303
|
+
- { name: fp_ref_ok, from: "$.ok" }
|
|
304
|
+
- { name: fp_ref_written, from: "$.written" }
|
|
305
|
+
- { name: fp_ref_tests_message, from: "$.tests_message" }
|
|
306
|
+
- { name: fp_ref_out, from: "$.stdout" }
|
|
307
|
+
|
|
308
|
+
# A failed reference sample does not undo the base project, so this reports and carries
|
|
309
|
+
# on to the residue check rather than returning.
|
|
310
|
+
- id: fp_reference_gate
|
|
311
|
+
action: verify_context
|
|
312
|
+
condition: "{{fp_ref_go}} == yes"
|
|
313
|
+
require_true: fp_ref_ok
|
|
314
|
+
on_false: continue
|
|
315
|
+
message_var: fp_ref_note
|
|
316
|
+
on_false_message: "; the reference sample FAILED to unpack ({{fp_ref_out}})"
|
|
317
|
+
|
|
318
|
+
- id: fp_reference_done
|
|
319
|
+
action: set
|
|
320
|
+
condition: "{{fp_ref_ok}} == true"
|
|
321
|
+
vars: { fp_ref_note: "; reference sample added ({{fp_ref_written}} file(s))" }
|
|
322
|
+
|
|
323
|
+
# The sample's own test tree is lifted onto the lane's test path like the base pack's;
|
|
324
|
+
# say what happened to it, or the lane line reports only the base pack's tests.
|
|
325
|
+
- id: fp_reference_tests_noted
|
|
326
|
+
action: set
|
|
327
|
+
condition: "{{fp_ref_tests_message}} != "
|
|
328
|
+
vars: { fp_ref_note: "{{fp_ref_note}} — its tests: {{fp_ref_tests_message}}" }
|
|
329
|
+
|
|
330
|
+
# The sample's merges: what the base project (or the lane before it) had, and the
|
|
331
|
+
# sample's version, become one as the sample's rule file says.
|
|
332
|
+
- id: fp_ref_merge
|
|
333
|
+
action: loop
|
|
334
|
+
condition: "{{fp_ref_ok}} == true"
|
|
335
|
+
over: "{{fp_ref_merges}}"
|
|
336
|
+
as: m
|
|
337
|
+
steps:
|
|
338
|
+
- id: fp_ref_merge_file
|
|
339
|
+
action: agent_author
|
|
340
|
+
context: ["{{m.existing}}", "{{m.target}}"]
|
|
341
|
+
include_standards: false
|
|
342
|
+
task: |
|
|
343
|
+
Merge two versions of {{m.target}} into one file.
|
|
344
|
+
EXISTING {{m.existing}} — the file as it was in the lane before the {{fl_name}} reference sample was unpacked
|
|
345
|
+
INCOMING {{m.target}} — the file as the reference sample ships it, with {{fp_sentinel}} renamed to {{app}}
|
|
346
|
+
The sample's rule file ({{fp_ref_rules_file}}) says how, in its rule for {{m.rule}}:
|
|
347
|
+
{{m.instruction}}
|
|
348
|
+
Change nothing that instruction does not ask for.
|
|
349
|
+
output_target: { type: file, path: "{{m.target}}" }
|
|
350
|
+
|
|
351
|
+
- id: fp_ref_merged_noted
|
|
352
|
+
action: set
|
|
353
|
+
condition: "{{fp_ref_ok}} == true"
|
|
354
|
+
vars: { fp_ref_note: "{{fp_ref_note}}{{fp_ref_rules_note}}" }
|
|
355
|
+
|
|
356
|
+
- id: fp_ref_rules_done
|
|
357
|
+
action: execute_script
|
|
358
|
+
condition: "{{fp_ref_go}} == yes"
|
|
359
|
+
script: { ref: actions }
|
|
360
|
+
subcommand: foundation-rules-done
|
|
361
|
+
args: ["--state", "{{fp_merge_state}}"]
|
|
362
|
+
|
|
363
|
+
# 8. Verify — sentinel residue must be zero in the generated tree.
|
|
364
|
+
- id: fp_verify
|
|
365
|
+
action: execute_script
|
|
366
|
+
script: { ref: actions }
|
|
367
|
+
subcommand: foundation-verify
|
|
368
|
+
args: ["--out", "{{fl_source_path}}", "--sentinel", "{{fp_sentinel}}"]
|
|
369
|
+
outputs:
|
|
370
|
+
- { name: fp_clean, from: "$.clean" }
|
|
371
|
+
- { name: fp_residue, from: "$.residue" }
|
|
372
|
+
|
|
373
|
+
- id: fp_residue_clean
|
|
374
|
+
action: set
|
|
375
|
+
condition: "{{fp_clean}} == true"
|
|
376
|
+
vars: { fp_residue_note: "no sentinel left" }
|
|
377
|
+
|
|
378
|
+
- id: fp_residue_found
|
|
379
|
+
action: set
|
|
380
|
+
condition: "{{fp_clean}} == false"
|
|
381
|
+
vars: { fp_residue_note: "SENTINEL {{fp_sentinel}} STILL IN {{fp_residue}}" }
|
|
382
|
+
|
|
383
|
+
- id: fp_tests_noted
|
|
384
|
+
action: set
|
|
385
|
+
condition: "{{fp_tests_message}} != "
|
|
386
|
+
vars: { fp_tests_note: "; {{fp_tests_message}}" }
|
|
387
|
+
|
|
388
|
+
- id: fp_done
|
|
389
|
+
action: set
|
|
390
|
+
vars:
|
|
391
|
+
fl_files: "{{fp_written}}"
|
|
392
|
+
fl_status: "scaffolded from the {{fl_name}} pack — {{fp_written}} file(s) into {{fl_source_path}}{{fp_tests_note}}{{fp_rules_note}}{{fp_ref_note}}{{fp_lane_note}}; {{fp_residue_note}}"
|