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
|
@@ -1,38 +1,48 @@
|
|
|
1
1
|
# =============================================================================
|
|
2
|
-
# aw-spec-foundation (orchestrator) — scaffold
|
|
2
|
+
# aw-spec-foundation (orchestrator) — scaffold every declared lane, backend then frontend
|
|
3
3
|
#
|
|
4
|
-
#
|
|
5
|
-
#
|
|
6
|
-
#
|
|
7
|
-
# is
|
|
8
|
-
#
|
|
9
|
-
# degrades to sdk. No standards/domain/hooks — pure scaffolding, so the merge
|
|
10
|
-
# runs with include_standards: false and a narrow two-file context.
|
|
4
|
+
# ONE RUN, EVERY LANE. The lanes come from .appweaver/stacks.json (select-stack is its sole
|
|
5
|
+
# writer). The run takes the backend lane first and the frontend lane second. For each, a
|
|
6
|
+
# lane that already holds files is asked about first — "Overwrite?", where "no" skips that
|
|
7
|
+
# lane and nothing else is asked — and then the run lists what the lane can be built from
|
|
8
|
+
# and the operator picks:
|
|
11
9
|
#
|
|
12
|
-
#
|
|
13
|
-
#
|
|
10
|
+
# [pack] a verified, compiling project unpacked byte-for-byte into the lane's
|
|
11
|
+
# lane root folder with its sentinel renamed -> modules/foundation-pack
|
|
12
|
+
# [spec] a foundations/<ecosystem>/<Name>/*.spec.txt describing the project; an
|
|
13
|
+
# agent builds it in the lane -> modules/foundation-spec
|
|
14
|
+
# [manual spec] the same, from a file path or text given at the prompt
|
|
15
|
+
# [skip] leave the lane as it is
|
|
14
16
|
#
|
|
15
|
-
# A
|
|
16
|
-
#
|
|
17
|
-
#
|
|
18
|
-
#
|
|
19
|
-
# land in the subtree that lane owns. That is what makes every later phase's "write only
|
|
20
|
-
# into your lane" rule true of the scaffold as well as of generated code: implement,
|
|
21
|
-
# build, test and run all resolve the same path this unpacked into.
|
|
17
|
+
# A lane kind that is not declared is reported and passed over; a lane that is declined,
|
|
18
|
+
# skipped or fails is reported and the run moves on to the next one — the per-lane
|
|
19
|
+
# modules RETURN, they never stop the run. Each lane's outcome is in the run's outputs,
|
|
20
|
+
# which is where the operator reads it.
|
|
22
21
|
#
|
|
23
|
-
#
|
|
24
|
-
#
|
|
25
|
-
# project
|
|
26
|
-
#
|
|
22
|
+
# A SCAFFOLD LANDS IN A LANE. A lane is one self-contained folder: a pack unpacks into it
|
|
23
|
+
# exactly as packed — build files, source and tests together — and a spec build creates
|
|
24
|
+
# the whole project inside it and may write nowhere else. The lane runs its commands in
|
|
25
|
+
# that folder and keeps its tests there; a lane declared the classic way (code in src/,
|
|
26
|
+
# solution and tests/ at the repository root) is reported and passed over, since a
|
|
27
|
+
# project built inside src/ would not be found by a build run at the root. That is what
|
|
28
|
+
# keeps every later phase's "write only into your lane" rule true of the scaffold as well
|
|
29
|
+
# as of generated code: implement, build, test and run all resolve the same paths.
|
|
27
30
|
#
|
|
28
|
-
#
|
|
29
|
-
#
|
|
31
|
+
# WHAT A LANE IS OFFERED. Bundles are filtered by the lane's ecosystem, then by the
|
|
32
|
+
# `# kind:` and `# profiles:` header lines of each pack/spec — an ecosystem is shared by
|
|
33
|
+
# stacks that cannot use each other's scaffold (Next.js, Angular and the Express backend
|
|
34
|
+
# are all `node`). A pack or spec with no `# kind:` line is a backend one.
|
|
35
|
+
#
|
|
36
|
+
# A SPEC BUILD FOLLOWS THE PROJECT'S TECHNICAL RULES. They are mapped per kind in the
|
|
37
|
+
# active project's tech-rule-bindings.md (the folder under guardrails/ that
|
|
38
|
+
# .appweaver/domain.json names — project-specific by default) under
|
|
39
|
+
# `## /aw-spec-foundation-backend` and `## /aw-spec-foundation-frontend`, and load
|
|
40
|
+
# through tech-select.
|
|
30
41
|
#
|
|
31
42
|
# Launch via the parametric skill: /appweaver foundation [strategy]
|
|
32
|
-
#
|
|
33
|
-
#
|
|
34
|
-
#
|
|
35
|
-
# /appweaver foundation agent VerticalSlice AppWeaver.Health
|
|
43
|
+
# Fast path: /appweaver foundation agent VerticalSlice AppWeaver.Health
|
|
44
|
+
# — the name preselects its entry in whichever lane lists it; the app name is used for
|
|
45
|
+
# every lane. There is no output-directory argument.
|
|
36
46
|
#
|
|
37
47
|
# Headless:
|
|
38
48
|
# python3 .appweaver/orchestrator/orchestrator.py \
|
|
@@ -42,14 +52,14 @@
|
|
|
42
52
|
# =============================================================================
|
|
43
53
|
|
|
44
54
|
name: aw-spec-foundation
|
|
45
|
-
description: Scaffold
|
|
46
|
-
version:
|
|
55
|
+
description: Scaffold every declared lane in one run — backend, then frontend. A lane that already has files is asked whether to overwrite them first (no = skip that lane). For each lane pick a verified pack (unpacked into its lane root folder, sentinel renamed), a spec the agent builds the project from (a bundled *.spec.txt or one you give), or skip it. Spec builds follow the technical rules mapped under /aw-spec-foundation-backend and /aw-spec-foundation-frontend.
|
|
56
|
+
version: 2.0.0
|
|
47
57
|
agent_agnostic: true
|
|
48
58
|
dialect: aw-spec.orchestrator/v1
|
|
49
59
|
|
|
50
60
|
inputs:
|
|
51
61
|
user_input:
|
|
52
|
-
description: "Optional fast path: FoundationName [AppName].
|
|
62
|
+
description: "Optional fast path: FoundationName [AppName]. The name preselects that pack or spec in the lane that lists it; the app name is used for every lane. Omit to pick per lane and be asked for the app name once."
|
|
53
63
|
required: false
|
|
54
64
|
bind: USER_INPUT
|
|
55
65
|
|
|
@@ -62,25 +72,52 @@ standards:
|
|
|
62
72
|
- { path: .appweaver/ai-rules.md } # kit-resident: the universal operating rules, every flow
|
|
63
73
|
|
|
64
74
|
vars:
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
stash_found: "false" # true only when the reference flow stashed a DbContext
|
|
68
|
-
app: "" # resolved app name: fast-path 2nd token, else the ask below
|
|
69
|
-
app_typed: "" # app name entered interactively (empty on the fast path)
|
|
75
|
+
app: "" # resolved app name: fast-path 2nd token, else asked by the first lane that needs it
|
|
76
|
+
app_typed: "" # app name entered interactively
|
|
70
77
|
out_ok: "true" # cleared when a third fast-path token names an output directory
|
|
78
|
+
be_status: "not run"
|
|
79
|
+
be_route: ""
|
|
80
|
+
be_name: ""
|
|
81
|
+
be_spec: ""
|
|
82
|
+
be_files: ""
|
|
83
|
+
fe_status: "not run"
|
|
84
|
+
fe_route: ""
|
|
85
|
+
fe_name: ""
|
|
86
|
+
fe_spec: ""
|
|
87
|
+
fe_files: ""
|
|
71
88
|
|
|
72
89
|
workflow:
|
|
73
90
|
|
|
74
|
-
# 0a. THE LANE MODEL
|
|
75
|
-
#
|
|
91
|
+
# 0a. THE LANE MODEL. Read-only: select-stack is the sole writer, and a scaffold has no
|
|
92
|
+
# business declaring the lane it fills. Both kinds come back flattened
|
|
93
|
+
# (backend_* / frontend_*), so one call feeds both sections below.
|
|
76
94
|
- id: lanes
|
|
77
95
|
action: execute_script
|
|
78
96
|
on_error: continue # never crash raw on an absent stacks.json — the gate explains it
|
|
79
97
|
script: { ref: actions }
|
|
80
98
|
subcommand: lane-resolve
|
|
81
99
|
outputs:
|
|
82
|
-
- { name: lane_options,
|
|
83
|
-
- { name:
|
|
100
|
+
- { name: lane_options, from: "$.lane_options" }
|
|
101
|
+
- { name: backend_declared, from: "$.backend_declared" }
|
|
102
|
+
- { name: backend_lane_id, from: "$.backend_lane_id" }
|
|
103
|
+
- { name: backend_profile, from: "$.backend_profile" }
|
|
104
|
+
- { name: backend_title, from: "$.backend_title" }
|
|
105
|
+
- { name: backend_language, from: "$.backend_language" }
|
|
106
|
+
- { name: backend_ecosystem, from: "$.backend_ecosystem" }
|
|
107
|
+
- { name: backend_source_path, from: "$.backend_source_path" }
|
|
108
|
+
- { name: backend_test_path, from: "$.backend_test_path" }
|
|
109
|
+
- { name: backend_workdir, from: "$.backend_workdir" }
|
|
110
|
+
- { name: backend_build, from: "$.backend_build" }
|
|
111
|
+
- { name: frontend_declared, from: "$.frontend_declared" }
|
|
112
|
+
- { name: frontend_lane_id, from: "$.frontend_lane_id" }
|
|
113
|
+
- { name: frontend_profile, from: "$.frontend_profile" }
|
|
114
|
+
- { name: frontend_title, from: "$.frontend_title" }
|
|
115
|
+
- { name: frontend_language, from: "$.frontend_language" }
|
|
116
|
+
- { name: frontend_ecosystem, from: "$.frontend_ecosystem" }
|
|
117
|
+
- { name: frontend_source_path, from: "$.frontend_source_path" }
|
|
118
|
+
- { name: frontend_test_path, from: "$.frontend_test_path" }
|
|
119
|
+
- { name: frontend_workdir, from: "$.frontend_workdir" }
|
|
120
|
+
- { name: frontend_build, from: "$.frontend_build" }
|
|
84
121
|
|
|
85
122
|
- id: require_lanes
|
|
86
123
|
action: verify_context
|
|
@@ -88,74 +125,27 @@ workflow:
|
|
|
88
125
|
on_empty: stop
|
|
89
126
|
on_empty_message: >
|
|
90
127
|
/appweaver foundation cannot run: no lane is declared in .appweaver/stacks.json.
|
|
91
|
-
A scaffold
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
# 0b.
|
|
98
|
-
#
|
|
99
|
-
|
|
100
|
-
- id: pick_lane
|
|
101
|
-
action: user_select
|
|
102
|
-
prompt: "Which lane is this scaffold for? The bundle is unpacked into that lane's source path, and its tests into the lane's test path — nothing lands outside them. Scaffold the other lane by running /appweaver foundation again."
|
|
103
|
-
options_from_variable: lane_options
|
|
104
|
-
single_option_confirm: true
|
|
105
|
-
outputs:
|
|
106
|
-
- { name: chosen_lane, from: selection }
|
|
107
|
-
|
|
108
|
-
# 0c. Resolve the chosen lane to the two paths this run writes into, plus the ecosystem
|
|
109
|
-
# that narrows the bundle list. `lane-resolve` strips the option's label itself, so
|
|
110
|
-
# the selection goes back in as the id it already carries.
|
|
111
|
-
- id: lane_target
|
|
112
|
-
action: execute_script
|
|
113
|
-
script: { ref: actions }
|
|
114
|
-
subcommand: lane-resolve
|
|
115
|
-
args: ["--id", "{{chosen_lane}}"]
|
|
116
|
-
outputs:
|
|
117
|
-
- { name: lane_found, from: "$.found" }
|
|
118
|
-
- { name: lane_id, from: "$.lane_id" }
|
|
119
|
-
- { name: lane_root, from: "$.source_path" }
|
|
120
|
-
- { name: lane_test_path, from: "$.test_path" }
|
|
121
|
-
- { name: lane_ecosystem, from: "$.ecosystem" }
|
|
122
|
-
- { name: lane_language, from: "$.language" }
|
|
123
|
-
|
|
124
|
-
- id: lane_resolved
|
|
125
|
-
action: verify_context
|
|
126
|
-
require_true: lane_found
|
|
127
|
-
on_false: stop
|
|
128
|
-
on_false_message: "No lane matches the selection `{{chosen_lane}}` in .appweaver/stacks.json. Re-run /appweaver select-stack to re-declare the lanes, then re-run foundation."
|
|
129
|
-
|
|
130
|
-
- id: lane_has_root
|
|
131
|
-
action: verify_context
|
|
132
|
-
require_non_empty: lane_root
|
|
133
|
-
on_empty: stop
|
|
134
|
-
on_empty_message: "Lane `{{lane_id}}` declares no source path in .appweaver/stacks.json, and the source path is where this scaffold is unpacked. Re-run /appweaver select-stack and give the lane the directory it owns."
|
|
135
|
-
|
|
136
|
-
# 1a. LIST the foundations available for THAT LANE's ecosystem (deterministic
|
|
137
|
-
# foundations/<ecosystem>/<Name>/<Name>.pack.txt scan — no LLM). A bundle is a whole
|
|
138
|
-
# compiling project in one ecosystem's build system, so a Node UI lane is not offered
|
|
139
|
-
# a .NET bundle even in a repo that also declares a .NET service; `all_foundations`
|
|
140
|
-
# keeps the unfiltered set for the gate message below. A direct "Foundation App"
|
|
141
|
-
# argument is parsed here too as an optional fast path.
|
|
142
|
-
- id: list_foundations
|
|
128
|
+
A scaffold goes into the LANE ROOT FOLDER of the lane it belongs to — that is what keeps a
|
|
129
|
+
project's files inside the subtree every later phase compiles, tests and generates
|
|
130
|
+
into — so there has to be a lane before there is a scaffold. Run
|
|
131
|
+
/appweaver select-stack first: it declares each lane's stack and lane root folder, and is
|
|
132
|
+
the first command of both the greenfield and the brownfield sequence.
|
|
133
|
+
|
|
134
|
+
# 0b. The fast path, parsed once for the whole run: the app name it carries applies to
|
|
135
|
+
# every lane. --ecosystem "" filters the listing to nothing — only the parse is wanted.
|
|
136
|
+
- id: parse_args
|
|
143
137
|
action: execute_script
|
|
144
138
|
script: { ref: actions }
|
|
145
139
|
subcommand: foundation-list
|
|
146
|
-
args: ["--args", "{{USER_INPUT}}", "--ecosystem", "
|
|
140
|
+
args: ["--args", "{{USER_INPUT}}", "--ecosystem", ""]
|
|
147
141
|
outputs:
|
|
148
|
-
- { name:
|
|
149
|
-
- { name:
|
|
150
|
-
- { name:
|
|
151
|
-
- { name: lane_ecosystems, from: "$.lane_ecosystems" }
|
|
152
|
-
- { name: preselect_name, from: "$.preselect_name" }
|
|
153
|
-
- { name: preselect_app, from: "$.preselect_app" }
|
|
154
|
-
- { name: rejected_out, from: "$.rejected_out" }
|
|
142
|
+
- { name: preselect_name, from: "$.preselect_name" }
|
|
143
|
+
- { name: preselect_app, from: "$.preselect_app" }
|
|
144
|
+
- { name: rejected_out, from: "$.rejected_out" }
|
|
155
145
|
|
|
156
|
-
#
|
|
157
|
-
#
|
|
158
|
-
#
|
|
146
|
+
# A third fast-path token used to be an output directory. Refused by name rather than
|
|
147
|
+
# ignored: silently dropping a path argument is how someone believes they scaffolded a
|
|
148
|
+
# sandbox and finds they filled their service lane.
|
|
159
149
|
- id: out_dir_given
|
|
160
150
|
action: set
|
|
161
151
|
condition: "{{rejected_out}} != "
|
|
@@ -167,207 +157,96 @@ workflow:
|
|
|
167
157
|
on_false: stop
|
|
168
158
|
on_false_message: >
|
|
169
159
|
`{{rejected_out}}` was given as an output directory, and foundation has none to give.
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
To scaffold somewhere else, declare a lane there with /appweaver select-stack and
|
|
174
|
-
pick that lane.
|
|
160
|
+
Each lane is scaffolded into its own lane root folder from .appweaver/stacks.json, so that
|
|
161
|
+
everything written is inside the subtree that lane owns. Re-run without it. To
|
|
162
|
+
scaffold somewhere else, declare a lane there with /appweaver select-stack.
|
|
175
163
|
|
|
176
|
-
- id: have_foundations
|
|
177
|
-
action: verify_context
|
|
178
|
-
require_non_empty: foundations
|
|
179
|
-
on_empty: stop
|
|
180
|
-
on_empty_message: >
|
|
181
|
-
No foundation bundle ships for the `{{lane_id}}` lane's ecosystem ({{lane_ecosystem}}).
|
|
182
|
-
Bundles present: {{all_foundations}}. A foundation is a complete project in one
|
|
183
|
-
ecosystem's languages and build system, so one from another ecosystem is not a
|
|
184
|
-
scaffold for this lane — it is a second, foreign project inside it. Either add a
|
|
185
|
-
bundle under foundations/{{lane_ecosystem}}/<Name>/<Name>.pack.txt (see the pack
|
|
186
|
-
scripts in that directory), or scaffold `{{lane_root}}` with the stack's own tooling
|
|
187
|
-
(Spring Initializr, `npm create`, `cargo new`, …) — implement generates INTO a
|
|
188
|
-
project tree and does not require that the kit be the thing that created it.
|
|
189
|
-
|
|
190
|
-
# 1b. PICK the foundation. A matching fast-path arg auto-selects; a lone
|
|
191
|
-
# foundation auto-confirms; otherwise the user chooses from the list.
|
|
192
|
-
- id: pick_foundation
|
|
193
|
-
action: user_select
|
|
194
|
-
prompt: "Select a foundation to scaffold from:"
|
|
195
|
-
options_from_variable: foundations
|
|
196
|
-
preselect_from: preselect_name
|
|
197
|
-
single_option_confirm: true
|
|
198
|
-
outputs:
|
|
199
|
-
- { name: fname, from: selection }
|
|
200
|
-
|
|
201
|
-
# 1c. ASK for the app (project) name — deterministic free-text, no LLM. Skipped
|
|
202
|
-
# when the fast-path arg already supplied it (preselect_app non-empty).
|
|
203
|
-
- id: ask_app
|
|
204
|
-
action: ask
|
|
205
|
-
condition: "{{preselect_app}} == "
|
|
206
|
-
prompt: >
|
|
207
|
-
Enter the project (application) name — it replaces the foundation's sentinel
|
|
208
|
-
across the generated tree (dotted / underscored / hyphen / lower forms),
|
|
209
|
-
e.g. AppWeaver.Health:
|
|
210
|
-
answer_var: app_typed
|
|
211
|
-
|
|
212
|
-
# 1d. Coalesce the app name (engine has no compound conditions → two ordered
|
|
213
|
-
# sets): default to the typed answer, then override with the fast-path token.
|
|
214
|
-
- id: app_from_typed
|
|
215
|
-
action: set
|
|
216
|
-
vars: { app: "{{app_typed}}" }
|
|
217
164
|
- id: app_from_arg
|
|
218
165
|
action: set
|
|
219
166
|
condition: "{{preselect_app}} != "
|
|
220
167
|
vars: { app: "{{preselect_app}}" }
|
|
221
168
|
|
|
222
|
-
#
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
- id:
|
|
246
|
-
action:
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
on_mismatch_message: "Aborted — output files exist and overwrite was declined."
|
|
288
|
-
|
|
289
|
-
# 4. Unpack for real.
|
|
290
|
-
- id: unpack
|
|
291
|
-
action: execute_script
|
|
292
|
-
script: { ref: actions }
|
|
293
|
-
subcommand: foundation-unpack
|
|
294
|
-
args: ["--name", "{{fname}}", "--app", "{{app}}", "--out", "{{lane_root}}", "--test-path", "{{lane_test_path}}", "--force", "{{overwrite}}"]
|
|
295
|
-
outputs:
|
|
296
|
-
- { name: written, from: "$.written" }
|
|
297
|
-
- { name: tests_moved, from: "$.tests_moved" }
|
|
298
|
-
- { name: tests_message, from: "$.tests_message" }
|
|
299
|
-
|
|
300
|
-
# 5. Optional reference sample.
|
|
301
|
-
- id: ask_reference
|
|
302
|
-
action: ask
|
|
303
|
-
prompt: "Include the reference sample project (Projects, Users, Reports slices)?"
|
|
304
|
-
options: ["yes", "no"]
|
|
305
|
-
answer_var: want_reference
|
|
306
|
-
|
|
307
|
-
- id: stash_dbcontext
|
|
308
|
-
action: execute_script
|
|
309
|
-
condition: "{{want_reference}} == yes"
|
|
310
|
-
script: { ref: actions }
|
|
311
|
-
subcommand: foundation-stash-dbcontext
|
|
312
|
-
args: ["--out", "{{lane_root}}"]
|
|
313
|
-
outputs:
|
|
314
|
-
- { name: stash_found, from: "$.found" }
|
|
315
|
-
- { name: db_context, from: "$.dbcontext" }
|
|
316
|
-
- { name: db_backup, from: "$.backup" }
|
|
317
|
-
|
|
318
|
-
- id: reference_unpack
|
|
319
|
-
action: execute_script
|
|
320
|
-
condition: "{{want_reference}} == yes"
|
|
321
|
-
script: { ref: actions }
|
|
322
|
-
subcommand: foundation-unpack
|
|
323
|
-
args: ["--name", "{{fname}}", "--app", "{{app}}", "--out", "{{lane_root}}", "--test-path", "{{lane_test_path}}", "--reference"]
|
|
324
|
-
outputs:
|
|
325
|
-
- { name: ref_written, from: "$.written" }
|
|
326
|
-
|
|
327
|
-
# 6. Merge the foundation DbContext (usings + DbSet<>) back over the reference
|
|
328
|
-
# one. agent_author: read-only generation, the ENGINE writes the target.
|
|
329
|
-
- id: merge_dbcontext
|
|
330
|
-
action: agent_author
|
|
331
|
-
condition: "{{stash_found}} == true"
|
|
332
|
-
context: ["{{db_backup}}", "{{db_context}}"]
|
|
333
|
-
include_standards: false
|
|
334
|
-
task: |
|
|
335
|
-
The target file ({{db_context}}) currently holds the REFERENCE DbContext
|
|
336
|
-
(sample DbSet<> properties, no OnModelCreating). The backup ({{db_backup}})
|
|
337
|
-
holds the FOUNDATION DbContext (full OnModelCreating, no DbSet<>). Produce a
|
|
338
|
-
single merged ApplicationDbContext:
|
|
339
|
-
- Base = the FOUNDATION file (backup).
|
|
340
|
-
- Add any `using` directives from the reference that are missing.
|
|
341
|
-
- Insert every reference `public DbSet<…>` line as a block right after the
|
|
342
|
-
class opening brace (before OnModelCreating), preserving any comment above them.
|
|
343
|
-
- Keep everything else in the foundation file unchanged.
|
|
344
|
-
output_target: { type: file, path: "{{db_context}}" }
|
|
345
|
-
|
|
346
|
-
# 7. Verify (sentinel residue must be zero in the generated tree).
|
|
347
|
-
- id: verify
|
|
348
|
-
action: execute_script
|
|
349
|
-
script: { ref: actions }
|
|
350
|
-
subcommand: foundation-verify
|
|
351
|
-
args: ["--out", "{{lane_root}}", "--sentinel", "{{sentinel}}"]
|
|
352
|
-
outputs:
|
|
353
|
-
- { name: clean, from: "$.clean" }
|
|
354
|
-
- { name: residue, from: "$.residue" }
|
|
169
|
+
# 1. BACKEND. Not declared -> say so and move on to the frontend.
|
|
170
|
+
- id: backend_absent
|
|
171
|
+
action: set
|
|
172
|
+
condition: "{{backend_declared}} != true"
|
|
173
|
+
vars:
|
|
174
|
+
be_status: "no backend lane is declared in .appweaver/stacks.json — nothing scaffolded for a service; run /appweaver select-stack to add one"
|
|
175
|
+
|
|
176
|
+
- id: backend
|
|
177
|
+
action: include
|
|
178
|
+
condition: "{{backend_declared}} == true"
|
|
179
|
+
module: .appweaver/orchestrator/modules/foundation-lane.orch.yaml
|
|
180
|
+
with:
|
|
181
|
+
fl_kind: "backend"
|
|
182
|
+
fl_lane_id: "{{backend_lane_id}}"
|
|
183
|
+
fl_profile: "{{backend_profile}}"
|
|
184
|
+
fl_title: "{{backend_title}}"
|
|
185
|
+
fl_language: "{{backend_language}}"
|
|
186
|
+
fl_ecosystem: "{{backend_ecosystem}}"
|
|
187
|
+
fl_source_path: "{{backend_source_path}}"
|
|
188
|
+
fl_test_path: "{{backend_test_path}}"
|
|
189
|
+
fl_workdir: "{{backend_workdir}}"
|
|
190
|
+
fl_build: "{{backend_build}}"
|
|
191
|
+
|
|
192
|
+
- id: backend_result
|
|
193
|
+
action: set
|
|
194
|
+
condition: "{{backend_declared}} == true"
|
|
195
|
+
vars:
|
|
196
|
+
be_status: "{{fl_status}}"
|
|
197
|
+
be_route: "{{fl_route}}"
|
|
198
|
+
be_name: "{{fl_name}}"
|
|
199
|
+
be_spec: "{{fl_spec_path}}"
|
|
200
|
+
be_files: "{{fl_files}}"
|
|
201
|
+
|
|
202
|
+
# 2. FRONTEND. Not declared -> say so; the run ends after this section either way.
|
|
203
|
+
- id: frontend_absent
|
|
204
|
+
action: set
|
|
205
|
+
condition: "{{frontend_declared}} != true"
|
|
206
|
+
vars:
|
|
207
|
+
fe_status: "no frontend lane is declared in .appweaver/stacks.json — nothing scaffolded for a UI; run /appweaver select-stack to add one"
|
|
208
|
+
|
|
209
|
+
- id: frontend
|
|
210
|
+
action: include
|
|
211
|
+
condition: "{{frontend_declared}} == true"
|
|
212
|
+
module: .appweaver/orchestrator/modules/foundation-lane.orch.yaml
|
|
213
|
+
with:
|
|
214
|
+
fl_kind: "frontend"
|
|
215
|
+
fl_lane_id: "{{frontend_lane_id}}"
|
|
216
|
+
fl_profile: "{{frontend_profile}}"
|
|
217
|
+
fl_title: "{{frontend_title}}"
|
|
218
|
+
fl_language: "{{frontend_language}}"
|
|
219
|
+
fl_ecosystem: "{{frontend_ecosystem}}"
|
|
220
|
+
fl_source_path: "{{frontend_source_path}}"
|
|
221
|
+
fl_test_path: "{{frontend_test_path}}"
|
|
222
|
+
fl_workdir: "{{frontend_workdir}}"
|
|
223
|
+
fl_build: "{{frontend_build}}"
|
|
224
|
+
|
|
225
|
+
- id: frontend_result
|
|
226
|
+
action: set
|
|
227
|
+
condition: "{{frontend_declared}} == true"
|
|
228
|
+
vars:
|
|
229
|
+
fe_status: "{{fl_status}}"
|
|
230
|
+
fe_route: "{{fl_route}}"
|
|
231
|
+
fe_name: "{{fl_name}}"
|
|
232
|
+
fe_spec: "{{fl_spec_path}}"
|
|
233
|
+
fe_files: "{{fl_files}}"
|
|
355
234
|
|
|
356
235
|
outputs:
|
|
357
|
-
|
|
236
|
+
backend: "{{be_status}}"
|
|
237
|
+
frontend: "{{fe_status}}"
|
|
358
238
|
app: "{{app}}"
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
note: "Foundation scaffolded into the {{lane_id}} lane at {{lane_root}} ({{written}} file(s), sentinel renamed to {{app}}); {{tests_message}}. Everything written is inside the subtree that lane owns, which is where implement generates and build/test/run act. Configure your AppWeaver.* NuGet feed and run the AppHost to confirm the scaffold starts before building on it."
|
|
239
|
+
backend_route: "{{be_route}}"
|
|
240
|
+
backend_foundation: "{{be_name}}"
|
|
241
|
+
backend_spec: "{{be_spec}}"
|
|
242
|
+
backend_files: "{{be_files}}"
|
|
243
|
+
frontend_route: "{{fe_route}}"
|
|
244
|
+
frontend_foundation: "{{fe_name}}"
|
|
245
|
+
frontend_spec: "{{fe_spec}}"
|
|
246
|
+
frontend_files: "{{fe_files}}"
|
|
247
|
+
note: "Each lane line above says what was scaffolded into it, or why nothing was. Everything written is inside the lane that owns it, which is where implement generates and build/test/run act. A spec build's spec is kept at .appweaver/foundation/<lane>.spec.md. Run /appweaver foundation again to scaffold a lane that was skipped — answer no to the overwrite question for the lane that is already done."
|
|
369
248
|
# constitution is named here because specify declares constitution.domain.md a
|
|
370
249
|
# REQUIRED context file. It announces rather than stops when the file is absent,
|
|
371
250
|
# so a sequence that skips this step produces a spec authored with no domain
|
|
372
251
|
# frame and only a [context] MISSING line to show for it.
|
|
373
|
-
next: "
|
|
252
|
+
next: "/appweaver constitution → specify. /appweaver constitution is NOT optional — it authors the constitution halves, and specify declares constitution.domain.md as REQUIRED context while plan and implement read constitution.technical.md (plus constitution.ui.md on a frontend lane); it reads the domain rule map of the project .appweaver/domain.json names (guardrails/project-specific/ by default). On a project with no specs yet, constitution also creates the default bounded context MainContext and its feature CoreFeature and makes both active, so specify can run straight after it; to use your own names, run /appweaver select-bounded-context <Name> and then /appweaver select-feature <Name> before specify. Every stage from specify onward reads the active feature and stops without it, and once any bounded context exists select-feature refuses to run until one is selected."
|