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
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
#
|
|
29
29
|
# EACH LANE IS GATED ON ITS OWN, AND A LANE'S GAP IS NOT THE RUN'S. A declared lane needs
|
|
30
30
|
# two things before it can generate: the plan for THIS run (its master plan, or this
|
|
31
|
-
# change's delta plan) and a scaffolded project under the
|
|
31
|
+
# change's delta plan) and a scaffolded project under the lane root folder it declares. A lane
|
|
32
32
|
# that is missing either is REPORTED with the fix named and SKIPPED — the other lane still
|
|
33
33
|
# runs. Failing the whole command for the frontend's sake is how a backend that was ready
|
|
34
34
|
# goes unbuilt; failing silently is how a frontend that was never generated reports green.
|
|
@@ -38,6 +38,12 @@
|
|
|
38
38
|
# pipeline, so each runnable lane confirms first, naming its stack, its plan and the
|
|
39
39
|
# subtree it will write into. Answering no to one lane leaves the other free to run.
|
|
40
40
|
#
|
|
41
|
+
# THE FRONTEND BINDS TO THE SERVICE AS BUILT. Between the two lanes, the service's API
|
|
42
|
+
# document is exported from the running code, the frontend's client is generated from it,
|
|
43
|
+
# and the operation ids the frontend plan cites are checked against it; the frontend then
|
|
44
|
+
# generates with the document in context. Each of those steps warns rather than stops —
|
|
45
|
+
# see the API CONTRACT block before the lane swap.
|
|
46
|
+
#
|
|
41
47
|
# THE PLAN SAYS WHAT TO BUILD, THE MODEL SAYS WHAT THE DOMAIN IS. This phase does NOT read
|
|
42
48
|
# spec.md — analyze-plan already conformed the plans to it, so the plan is the complete,
|
|
43
49
|
# authoritative source for WHICH elements exist, where each lives and what surface they
|
|
@@ -81,15 +87,15 @@
|
|
|
81
87
|
# the constitution halves + this phase's rule sets. Each lane takes its rules from its own
|
|
82
88
|
# heading of tech-rule-bindings, and the frontend set is loaded only when that lane runs,
|
|
83
89
|
# so a backend-only project sees exactly the rules it did before:
|
|
84
|
-
# • BACKEND — `## /aw-spec-implement
|
|
85
|
-
#
|
|
86
|
-
#
|
|
87
|
-
#
|
|
88
|
-
# for this lane because the delta half of it was never built; it is built here.
|
|
90
|
+
# • BACKEND — `## /aw-spec-implement-backend`, both paths.
|
|
91
|
+
# • FRONTEND — `## /aw-spec-implement-frontend`, both paths.
|
|
92
|
+
# A change's code is generated against the same rules as the master it changes, so
|
|
93
|
+
# neither lane has a separate delta heading.
|
|
89
94
|
#
|
|
90
|
-
# TWO PATHS PER LANE. Each lane owns the
|
|
91
|
-
# test path lane-verify resolves
|
|
92
|
-
#
|
|
95
|
+
# TWO PATHS PER LANE. Each lane owns the lane root folder stacks.json declares for it and the
|
|
96
|
+
# test path lane-verify resolves for it — `backend/tests/` inside a new lane root folder,
|
|
97
|
+
# `tests/` next to a classic .NET `src/`, the lane root folder itself for a stack that keeps
|
|
98
|
+
# its tests inside — and writes nothing outside them.
|
|
93
99
|
# The one exception is registering a test project the lane had to create, in whatever
|
|
94
100
|
# file the lane's test command discovers tests through (a .NET solution file). A file
|
|
95
101
|
# written elsewhere belongs to the other lane or to no lane at all, and the project gate
|
|
@@ -99,35 +105,35 @@
|
|
|
99
105
|
#
|
|
100
106
|
# A FILE LIST IS NOT A FINISHED LANE. Each generating lane is handed its plan's element
|
|
101
107
|
# list and reports every element back as done or blocked; `plan-coverage` then checks the
|
|
102
|
-
# code under the lane
|
|
108
|
+
# code under the lane root folder for every identifier the plan introduces. Whatever
|
|
103
109
|
# either check leaves open gets one completion pass, and anything still open after it
|
|
104
110
|
# stops the run once both lanes have generated — so a pass that stopped at five use-cases
|
|
105
111
|
# of seven is reported, not shipped.
|
|
106
112
|
#
|
|
107
113
|
# A LANE'S GAP DISABLES THAT LANE, NOT THE RUN. Three things a lane needs are checked per
|
|
108
|
-
# lane and reported per lane: its
|
|
114
|
+
# lane and reported per lane: its lane root folder is on disk, its plan is there, and a project
|
|
109
115
|
# is scaffolded under it. Any of them missing skips that lane with the command that fixes
|
|
110
116
|
# it named, and every other declared lane still generates; only when NOTHING can run does
|
|
111
117
|
# the run stop, with all the reasons printed. The whole-run stop is reserved for states
|
|
112
118
|
# with no correct lane to fall back on — no lane declared at all, a lane declaring no
|
|
113
|
-
#
|
|
119
|
+
# lane root folder, and two lanes claiming overlapping subtrees.
|
|
114
120
|
#
|
|
115
121
|
# WHAT IT DOES NOT DO. It never writes spec.md, a master plan or the domain model, and it
|
|
116
122
|
# never closes a change — finalize-delta merges the change's spec and model halves,
|
|
117
123
|
# analyze-slice verifies the slice, and close-delta archives it and bumps the version.
|
|
118
124
|
#
|
|
119
125
|
# Prereqs: /appweaver plan (+ analyze-plan, or analyze-plan-delta for a change), and a
|
|
120
|
-
# project scaffolded under each lane
|
|
121
|
-
# so with no project there is nowhere to place the files. /appweaver foundation
|
|
122
|
-
#
|
|
123
|
-
#
|
|
126
|
+
# project scaffolded under each lane root folder — this phase GENERATES into that tree,
|
|
127
|
+
# so with no project there is nowhere to place the files. /appweaver foundation scaffolds one,
|
|
128
|
+
# from a pack or from a spec; a team may also scaffold with the stack's own tooling, and the
|
|
129
|
+
# gate accepts any of them, since it tests for a project rather than for how it got there.
|
|
124
130
|
#
|
|
125
131
|
# Launch: /appweaver implement [guidance]
|
|
126
132
|
# /appweaver implement CR-20260910-… (implement THAT open change, no prompt)
|
|
127
133
|
# =============================================================================
|
|
128
134
|
|
|
129
135
|
name: aw-spec-implement
|
|
130
|
-
description: "Generate the aggregate's source files and paired tests from its lane plans — the backend lane from backend-plan.md when a backend stack is declared, the frontend lane from frontend-plan.md when a frontend stack is, both when both are. One command covers backend-only, frontend-only and full-stack projects and absorbs the former implement-ui and implement-delta. Self-detecting off the changes on disk — with none open it generates from the master plans; with one or more open it ASKS which change and generates only what that change's delta plans mark ADDED or MODIFIED, leaving the masters untouched. Every lane is gated on its own
|
|
136
|
+
description: "Generate the aggregate's source files and paired tests from its lane plans — the backend lane from backend-plan.md when a backend stack is declared, the frontend lane from frontend-plan.md when a frontend stack is, both when both are. One command covers backend-only, frontend-only and full-stack projects and absorbs the former implement-ui and implement-delta. Self-detecting off the changes on disk — with none open it generates from the master plans; with one or more open it ASKS which change and generates only what that change's delta plans mark ADDED or MODIFIED, leaving the masters untouched. Every lane is gated on its own lane root folder, its own plan and its own scaffolded project, and a lane missing any of them is reported and skipped rather than failing the other lane; each runnable lane confirms before it writes. Model-driven, and it does not read the spec — analyze-plan already conformed the plans to it. The plan says WHAT to build; the bounded context's domain-model.md, in context alongside it, says what the domain IS — the entity names, the boundary and the text of every invariant the plan cites by id — joined on the delta path by that change's own model delta, since the master is not merged until finalize-delta. The stack binds here from the lane declaration and the constitution halves; the plans stay technology-agnostic."
|
|
131
137
|
version: 3.10.0
|
|
132
138
|
agent_agnostic: true
|
|
133
139
|
dialect: aw-spec.orchestrator/v1
|
|
@@ -148,7 +154,7 @@ scripts:
|
|
|
148
154
|
|
|
149
155
|
# Sticky standards seed = the UNIVERSAL always-on rule only (ai-rules). Each lane's
|
|
150
156
|
# FRAMEWORK / code-generation rule files are CONFIGURATION, loaded per-lane from
|
|
151
|
-
# guardrails
|
|
157
|
+
# guardrails/<project>/tech-rule-bindings.md by the tech-select module (see the
|
|
152
158
|
# tech_select steps below). Per the rule-partition this phase loads NO domain rule file —
|
|
153
159
|
# everything domain reached the code through spec → plan. The architecture and UX bases
|
|
154
160
|
# arrive via constitution.technical.md / constitution.ui.md (referred to directly, as-is —
|
|
@@ -247,15 +253,37 @@ vars:
|
|
|
247
253
|
fe_completion_ran: "false"
|
|
248
254
|
fe_gap_names: ""
|
|
249
255
|
fe_gaps_text: "none"
|
|
256
|
+
# THE API CONTRACT between the lanes — see the block before the lane swap. Every flag
|
|
257
|
+
# starts lowered, so a run without a frontend lane never touches any of it.
|
|
258
|
+
contract_go: "false"
|
|
259
|
+
contract_ok: ""
|
|
260
|
+
contract_doc: ""
|
|
261
|
+
contract_doc_exists: "false"
|
|
262
|
+
contract_reason: ""
|
|
263
|
+
contract_already: "false"
|
|
264
|
+
contract_fresh: "true"
|
|
265
|
+
contract_log: ""
|
|
266
|
+
contract_placeholder: ""
|
|
267
|
+
contract_export_status: ""
|
|
268
|
+
contract_status: "not exported — no API document is in context, so take each binding from the plan alone and say so in your summary"
|
|
269
|
+
client_go: "false"
|
|
270
|
+
client_ask: "false"
|
|
271
|
+
client_answer: ""
|
|
272
|
+
client_saved: "false"
|
|
273
|
+
client_run: "false"
|
|
274
|
+
client_present: "false"
|
|
275
|
+
client_ok: ""
|
|
276
|
+
client_cmd: ""
|
|
277
|
+
client_log: ""
|
|
278
|
+
client_status: "none was generated — write the calls in the lane's client layer from the API document, exactly as it states them"
|
|
279
|
+
check_ok: ""
|
|
280
|
+
check_reason: ""
|
|
250
281
|
lanes_complete: "true"
|
|
251
282
|
generate_any: "false"
|
|
252
283
|
record_edges: "false"
|
|
253
284
|
overview_ok: "false"
|
|
254
285
|
domain_model: ""
|
|
255
286
|
domain_model_exists: "false"
|
|
256
|
-
# The backend lane's rule-set heading, keyed by MODE — see the header. The frontend
|
|
257
|
-
# lane's is the same on both paths, so it is written inline at its include.
|
|
258
|
-
be_tech_command: "aw-spec-implement"
|
|
259
287
|
# HOOK PHASES. The merged command fires the phase of every branch it actually takes, so
|
|
260
288
|
# an extensions.yml wired to any of the three former commands keeps working:
|
|
261
289
|
# before/after_implement always, the _ui pair when the frontend lane generates, the _cr
|
|
@@ -272,15 +300,15 @@ workflow:
|
|
|
272
300
|
# kind: a backend-only and a frontend-only project are both correct states, and which
|
|
273
301
|
# lanes exist is exactly what it is here to find out.
|
|
274
302
|
#
|
|
275
|
-
# --allow-missing-root, because a lane whose
|
|
303
|
+
# --allow-missing-root, because a lane whose lane root folder is not on disk is THAT LANE'S
|
|
276
304
|
# gap, not the run's. This phase is per-lane throughout — a missing plan or a missing
|
|
277
305
|
# project is reported at step 5 and the other lane still generates — and a missing root
|
|
278
306
|
# is the same kind of gap, most often a declared frontend that `foundation` has not
|
|
279
|
-
#
|
|
307
|
+
# scaffolded yet. With the check left on it arrives here instead, as a whole-run stop
|
|
280
308
|
# that takes the ready lane down with it. It is re-checked per lane at step 5 from
|
|
281
309
|
# `*_root_exists`, which lane-verify reports whether or not the on-disk half is armed.
|
|
282
310
|
#
|
|
283
|
-
# What still stops the run: no lane declared at all, a lane declaring no
|
|
311
|
+
# What still stops the run: no lane declared at all, a lane declaring no lane root folder,
|
|
284
312
|
# and two lanes claiming overlapping subtrees. Those are declaration errors with no
|
|
285
313
|
# correct lane to fall back to, and none of them is a state any phase can work around.
|
|
286
314
|
- id: lane_verify
|
|
@@ -316,6 +344,8 @@ workflow:
|
|
|
316
344
|
- { name: fe_build, from: "$.frontend_build" }
|
|
317
345
|
- { name: fe_test, from: "$.frontend_test" }
|
|
318
346
|
- { name: fe_reserved, from: "$.frontend_reserved_csv" }
|
|
347
|
+
- { name: fe_workdir, from: "$.frontend_workdir" }
|
|
348
|
+
- { name: fe_client, from: "$.frontend_client" }
|
|
319
349
|
|
|
320
350
|
- id: require_lanes
|
|
321
351
|
action: verify_context
|
|
@@ -401,7 +431,6 @@ workflow:
|
|
|
401
431
|
mode: "delta"
|
|
402
432
|
pre_cr_phase: "before_implement_cr"
|
|
403
433
|
post_cr_phase: "after_implement_cr"
|
|
404
|
-
be_tech_command: "aw-spec-implement-delta"
|
|
405
434
|
|
|
406
435
|
- id: pick_change
|
|
407
436
|
condition: "{{mode}} == delta"
|
|
@@ -539,8 +568,8 @@ workflow:
|
|
|
539
568
|
# detect-project searches the LANE'S OWN subtree for an ecosystem manifest (.sln/
|
|
540
569
|
# .csproj, pom.xml, build.gradle, package.json, go.mod, Cargo.toml, pyproject.toml),
|
|
541
570
|
# falls back to the whole repo, and reports which scope answered. How the project got
|
|
542
|
-
# there is not asked — `foundation` unpacked it, or the team scaffolded it with
|
|
543
|
-
# stack's own tooling.
|
|
571
|
+
# there is not asked — `foundation` unpacked or built it, or the team scaffolded it with
|
|
572
|
+
# the stack's own tooling.
|
|
544
573
|
- id: be_detect_project
|
|
545
574
|
condition: "{{be_declared}} == true"
|
|
546
575
|
action: execute_script
|
|
@@ -555,7 +584,7 @@ workflow:
|
|
|
555
584
|
# in a two-lane project is the service lane's manifest, and generating this lane's code
|
|
556
585
|
# against it is exactly the failure the lane model exists to prevent — a frontend that
|
|
557
586
|
# was never scaffolded, generated into anyway, reporting green. The service lane accepts
|
|
558
|
-
# either scope, because the layout that keeps a manifest beside the lane root rather than
|
|
587
|
+
# either scope, because the layout that keeps a manifest beside the lane root folder rather than
|
|
559
588
|
# inside it is a normal one for it.
|
|
560
589
|
- id: fe_detect_project
|
|
561
590
|
condition: "{{fe_declared}} == true"
|
|
@@ -586,13 +615,13 @@ workflow:
|
|
|
586
615
|
action: verify_context
|
|
587
616
|
require_true: be_root_exists
|
|
588
617
|
on_false: continue
|
|
589
|
-
on_false_message: "BACKEND LANE SKIPPED — lane `{{be_lane_id}}` ({{be_title}}) declares
|
|
618
|
+
on_false_message: "BACKEND LANE SKIPPED — lane `{{be_lane_id}}` ({{be_title}}) declares lane root folder `{{be_source_path}}` in .appweaver/stacks.json, and that path is not a directory in this repository. A lane owns its subtree and this phase writes into it, so there is nothing to generate into: scaffold a project there with /appweaver foundation (a pack or a spec for {{be_profile}}, or a spec you give it), create one with the stack's own tooling, or re-run /appweaver select-stack and point the lane at the directory that really holds its source. Nothing is generated for this lane; any other declared lane still runs."
|
|
590
619
|
- id: warn_be_project
|
|
591
620
|
condition: "{{be_declared}} == true"
|
|
592
621
|
action: verify_context
|
|
593
622
|
require_true: be_project_ok
|
|
594
623
|
on_false: continue
|
|
595
|
-
on_false_message: "BACKEND LANE SKIPPED — no project found under the {{be_lane_id}} lane
|
|
624
|
+
on_false_message: "BACKEND LANE SKIPPED — no project found under the {{be_lane_id}} lane root folder `{{be_source_path}}`, nor anywhere else in this repository. This phase GENERATES into an existing project tree, so one has to be scaffolded first: run /appweaver foundation, which scaffolds it from a pack or from a spec (one it ships for {{be_profile}}, or one you give it), or create the project with the stack's own tooling under that path. Any ecosystem manifest marks it — .sln/.csproj, pom.xml, build.gradle(.kts), package.json, go.mod, Cargo.toml or pyproject.toml."
|
|
596
625
|
- id: warn_fe_plan
|
|
597
626
|
condition: "{{fe_declared}} == true"
|
|
598
627
|
action: verify_context
|
|
@@ -604,15 +633,15 @@ workflow:
|
|
|
604
633
|
action: verify_context
|
|
605
634
|
require_true: fe_root_exists
|
|
606
635
|
on_false: continue
|
|
607
|
-
on_false_message: "FRONTEND LANE SKIPPED — lane `{{fe_lane_id}}` ({{fe_title}}) declares
|
|
636
|
+
on_false_message: "FRONTEND LANE SKIPPED — lane `{{fe_lane_id}}` ({{fe_title}}) declares lane root folder `{{fe_source_path}}` in .appweaver/stacks.json, and that path is not a directory in this repository. A lane owns its subtree and this phase writes into it, so there is nothing to generate into: scaffold a project there with /appweaver foundation (a pack or a spec for {{fe_profile}}, or a spec you give it), create one with the stack's own tooling, or re-run /appweaver select-stack and point the lane at the directory that really holds its source. Nothing is generated for this lane; any other declared lane still runs."
|
|
608
637
|
- id: warn_fe_project
|
|
609
638
|
condition: "{{fe_declared}} == true"
|
|
610
639
|
action: verify_context
|
|
611
640
|
require_true: fe_project_ok
|
|
612
641
|
on_false: continue
|
|
613
|
-
on_false_message: "FRONTEND LANE SKIPPED — no frontend project found under the {{fe_lane_id}} lane
|
|
642
|
+
on_false_message: "FRONTEND LANE SKIPPED — no frontend project found under the {{fe_lane_id}} lane root folder `{{fe_source_path}}`. detect-project searched that subtree and then the whole repository, and answered at scope `{{fe_project_scope}}`; `lane` is the only scope this lane accepts. Scaffold a project there — /appweaver foundation, from a pack or a spec for {{fe_profile}} or a spec you give it, or the stack's own tooling — and re-run implement. A manifest found elsewhere in the repository does NOT count: that one belongs to another lane, and generating this lane's code against it is how a frontend that was never built reports green."
|
|
614
643
|
|
|
615
|
-
# 6. RUNNABLE = declared AND its
|
|
644
|
+
# 6. RUNNABLE = declared AND its lane root folder is on disk AND its plan is there AND its
|
|
616
645
|
# project is there, as one ordered assignment plus a knockdown per condition, since
|
|
617
646
|
# the engine has no compound conditions. An undeclared lane stays false either way —
|
|
618
647
|
# its `declared` value is what the raise assigns.
|
|
@@ -676,7 +705,7 @@ workflow:
|
|
|
676
705
|
action: verify_context
|
|
677
706
|
require_true: generate_any
|
|
678
707
|
on_false: stop
|
|
679
|
-
on_false_message: "Nothing to implement — no declared lane is both ready and confirmed. Either every declared lane was skipped for a reason printed above (its
|
|
708
|
+
on_false_message: "Nothing to implement — no declared lane is both ready and confirmed. Either every declared lane was skipped for a reason printed above (its lane root folder, its plan or its project is missing), or each one that was ready was declined at the prompt. Backend lane declared {{be_declared}}, ready {{be_runnable}}; frontend lane declared {{fe_declared}}, ready {{fe_runnable}}. Fix the reasons named above, or re-run and confirm a lane."
|
|
680
709
|
|
|
681
710
|
# 8. EACH GENERATING LANE'S authoring MODE — the run's mode where the lane is going, and
|
|
682
711
|
# `skip` where it is not, which silences both of that lane's branches without a
|
|
@@ -754,15 +783,15 @@ workflow:
|
|
|
754
783
|
- { name: fe_existing_count, from: "$.count" }
|
|
755
784
|
|
|
756
785
|
# 9. Each generating lane's code-generation rule files → sticky standards (configuration,
|
|
757
|
-
# not hardcoded). Loaded only for a lane that is actually going to generate,
|
|
758
|
-
#
|
|
786
|
+
# not hardcoded). Loaded only for a lane that is actually going to generate, under
|
|
787
|
+
# the same heading on both paths (see the header). No blocking gate: an
|
|
759
788
|
# unconfigured project soft-continues, since the constitution halves still carry each
|
|
760
789
|
# lane's ratified base.
|
|
761
790
|
#
|
|
762
791
|
# EACH LANE'S RULES ARE LOADED BESIDE ITS OWN STEPS, AND THE SECOND LANE REPLACES
|
|
763
792
|
# THE FIRST'S. Both includes used to run here, before either lane generated — and
|
|
764
793
|
# sticky standards only accumulate, so on a full-stack run the backend generator was
|
|
765
|
-
# shown `## /aw-spec-implement-
|
|
794
|
+
# shown `## /aw-spec-implement-frontend` and the frontend generator the service set. Each
|
|
766
795
|
# prompt says which lane it is in, but it said so inside an envelope that contradicted
|
|
767
796
|
# it, and the envelope is the part the model cannot argue with. The frontend include
|
|
768
797
|
# now sits immediately before the FRONTEND sections below and passes replace, which
|
|
@@ -771,7 +800,7 @@ workflow:
|
|
|
771
800
|
condition: "{{be_go}} == true"
|
|
772
801
|
action: include
|
|
773
802
|
module: .appweaver/orchestrator/modules/tech-select.orch.yaml
|
|
774
|
-
with: { command:
|
|
803
|
+
with: { command: aw-spec-implement-backend }
|
|
775
804
|
|
|
776
805
|
# 10. Pre-execution hooks — see the hook-phase vars above.
|
|
777
806
|
- id: resolve_pre_hooks
|
|
@@ -891,6 +920,11 @@ workflow:
|
|
|
891
920
|
Cross-Cutting Concerns table (audit / retention / data-exposure — the CN-/DC-
|
|
892
921
|
realisations); and each integration contract (IC-) in the External Integrations
|
|
893
922
|
table. Implement every port the plan declares.
|
|
923
|
+
- GIVE EVERY ENDPOINT ITS OPERATION ID. Where the plan names an endpoint's
|
|
924
|
+
**Operation id**, set it as this stack's published API document names operations
|
|
925
|
+
(its OpenAPI operationId), spelled exactly as the plan writes it. The frontend lane
|
|
926
|
+
finds the endpoint by that id in the document exported from this code, so an
|
|
927
|
+
endpoint left on a framework-generated name is one it cannot find.
|
|
894
928
|
- Author a paired test for every plan behaviour / use-case / endpoint; derive the
|
|
895
929
|
cases from the plan's pre/post/invariant contracts and cite the spec id (FR / BR /
|
|
896
930
|
CN / DC / IC / US) from its Traceability section. Include tests for the constraints
|
|
@@ -1041,6 +1075,10 @@ workflow:
|
|
|
1041
1075
|
invariant, handler orchestration, API error contract, the Cross-Cutting Concerns
|
|
1042
1076
|
realisations (audit / retention / data-exposure — CN-/DC-) and the External
|
|
1043
1077
|
Integrations table's contracts (IC-) exactly as the delta plan states.
|
|
1078
|
+
- GIVE EVERY ENDPOINT THIS CHANGE ADDS OR CHANGES the operation id the delta plan
|
|
1079
|
+
names, set as this stack's published API document names operations (its OpenAPI
|
|
1080
|
+
operationId) and spelled exactly; an existing endpoint keeps the id it has. The
|
|
1081
|
+
frontend lane finds each endpoint by that id in the exported document.
|
|
1044
1082
|
- COMPONENTS: if a delta element depends on a framework component, code against its
|
|
1045
1083
|
ABSTRACTION / port as the delta plan declares — do NOT hand-roll it. Installing the
|
|
1046
1084
|
component (packages, wiring, config) is /appweaver add-component <Component>; if
|
|
@@ -1140,7 +1178,8 @@ workflow:
|
|
|
1140
1178
|
under a different name is renamed to the plan's name, with its references — the
|
|
1141
1179
|
plan's names are the ubiquitous language.
|
|
1142
1180
|
- An element the plan names by intent (a port, an adapter, an endpoint route) is done
|
|
1143
|
-
when the code realises it, whatever the framework calls it; report it `done`.
|
|
1181
|
+
when the code realises it, whatever the framework calls it; report it `done`. An
|
|
1182
|
+
endpoint still carries the operation id the plan names, set exactly.
|
|
1144
1183
|
- If an element cannot be realised, do not work around it: report it `blocked` and
|
|
1145
1184
|
say what stops you. A plan that is wrong is fixed in plan / analyze-plan.
|
|
1146
1185
|
- Report every listed element in an `elements` list in your closing JSON block:
|
|
@@ -1165,7 +1204,7 @@ workflow:
|
|
|
1165
1204
|
# recorded). Without the union a backend run would erase the frontend lane's source_files
|
|
1166
1205
|
# and vice-versa, and either lane may have run first. ⌛ The trade-off is that a file this
|
|
1167
1206
|
# lane DELETED stays listed until something prunes it; a lane-scoped replace needs
|
|
1168
|
-
# concept-upsert to learn about lane
|
|
1207
|
+
# concept-upsert to learn about lane root folders, which is a script change and not built.
|
|
1169
1208
|
- id: xref_concept_backend
|
|
1170
1209
|
condition: "{{be_go}} == true"
|
|
1171
1210
|
action: execute_script
|
|
@@ -1185,13 +1224,156 @@ workflow:
|
|
|
1185
1224
|
outputs:
|
|
1186
1225
|
- { name: okf_concept, from: "$.concept" }
|
|
1187
1226
|
|
|
1227
|
+
# ══════════════ THE API CONTRACT — the built service, as the frontend sees it ═══
|
|
1228
|
+
# The frontend binds to the service through its published API document, and the document
|
|
1229
|
+
# that counts is the one the CODE serves: routes, verbs, parameters, field names and
|
|
1230
|
+
# status codes as built, which the plans only describe. So before the frontend lane
|
|
1231
|
+
# generates, three steps, each of which WARNS and carries on — the frontend still
|
|
1232
|
+
# generates, from its plan, when one of them cannot run:
|
|
1233
|
+
# 1. EXPORT — start the service with its lane's `contract_run`, save what it serves at
|
|
1234
|
+
# `contract` under its lane root folder, stop it (contract-export). The two values
|
|
1235
|
+
# come from the lane in stacks.json — where foundation records a pack's own — or
|
|
1236
|
+
# else from the stack profile.
|
|
1237
|
+
# 2. CLIENT — run the frontend lane's `client` command, which generates the client from
|
|
1238
|
+
# that document. A lane with none yet asks the developer once and records the
|
|
1239
|
+
# answer on the lane; an empty answer carries on without a generated client.
|
|
1240
|
+
# 3. CHECK — every operation id the frontend plan cites must be in the document
|
|
1241
|
+
# (contract-check, by script).
|
|
1242
|
+
# It runs whenever the frontend lane does, including when the service was built in an
|
|
1243
|
+
# earlier run, and only where a service lane is declared.
|
|
1244
|
+
- id: contract_arm
|
|
1245
|
+
condition: "{{fe_go}} == true"
|
|
1246
|
+
action: set
|
|
1247
|
+
vars: { contract_go: "{{be_declared}}" }
|
|
1248
|
+
- id: contract_export
|
|
1249
|
+
condition: "{{contract_go}} == true"
|
|
1250
|
+
action: execute_script
|
|
1251
|
+
on_error: continue
|
|
1252
|
+
script: { ref: actions }
|
|
1253
|
+
subcommand: contract-export
|
|
1254
|
+
outputs:
|
|
1255
|
+
- { name: contract_ok, from: "$.ok" }
|
|
1256
|
+
- { name: contract_doc, from: "$.doc" }
|
|
1257
|
+
- { name: contract_doc_exists, from: "$.doc_exists" }
|
|
1258
|
+
- { name: contract_reason, from: "$.reason" }
|
|
1259
|
+
- { name: contract_already, from: "$.already_running" }
|
|
1260
|
+
- { name: contract_ops, from: "$.operations" }
|
|
1261
|
+
- { name: contract_log, from: "$.log_tail" }
|
|
1262
|
+
- { name: contract_placeholder, from: "$.placeholder" }
|
|
1263
|
+
- { name: contract_export_status, from: "$.status" }
|
|
1264
|
+
- id: warn_contract_export
|
|
1265
|
+
condition: "{{contract_go}} == true"
|
|
1266
|
+
action: verify_context
|
|
1267
|
+
require_true: contract_ok
|
|
1268
|
+
on_false: continue
|
|
1269
|
+
on_false_message: "API DOCUMENT NOT EXPORTED — {{contract_reason}}. The service lane `{{be_lane_id}}` is started with its `contract_run` command and its document fetched from its `contract` URL, both read from .appweaver/stacks.json or else its stack profile; correct them on the lane there if they do not fit this project, start anything the service needs, and re-run implement. Until then the frontend lane binds from its plan alone. Service output: {{contract_log}}"
|
|
1270
|
+
- id: contract_stale_flag
|
|
1271
|
+
condition: "{{contract_already}} == true"
|
|
1272
|
+
action: set
|
|
1273
|
+
vars: { contract_fresh: "false" }
|
|
1274
|
+
- id: warn_contract_stale
|
|
1275
|
+
condition: "{{contract_go}} == true"
|
|
1276
|
+
action: verify_context
|
|
1277
|
+
require_true: contract_fresh
|
|
1278
|
+
on_false: continue
|
|
1279
|
+
on_false_message: "WARNING — the API document was {{contract_reason}}. Stop that service and re-run implement to export the code as it is now."
|
|
1280
|
+
- id: contract_status_set
|
|
1281
|
+
condition: "{{contract_doc_exists}} == true"
|
|
1282
|
+
action: set
|
|
1283
|
+
vars: { contract_status: "{{contract_export_status}}; it is in context" }
|
|
1284
|
+
|
|
1285
|
+
# 2. THE CLIENT, generated from the document — so only once there is one.
|
|
1286
|
+
- id: client_arm
|
|
1287
|
+
condition: "{{contract_doc_exists}} == true"
|
|
1288
|
+
action: set
|
|
1289
|
+
vars: { client_go: "{{fe_go}}" }
|
|
1290
|
+
- id: client_ask_arm
|
|
1291
|
+
condition: "{{fe_client}} == "
|
|
1292
|
+
action: set
|
|
1293
|
+
vars: { client_ask: "{{client_go}}" }
|
|
1294
|
+
- id: ask_client
|
|
1295
|
+
condition: "{{client_ask}} == true"
|
|
1296
|
+
action: ask
|
|
1297
|
+
prompt: |
|
|
1298
|
+
The frontend lane `{{fe_lane_id}}` ({{fe_title}}) has no `client` command, so its API
|
|
1299
|
+
client cannot be generated from the service's document ({{contract_doc}}).
|
|
1300
|
+
Type the command that generates it. It runs in `{{fe_workdir}}`, and
|
|
1301
|
+
{{contract_placeholder}} in it stands for the document's path — for example:
|
|
1302
|
+
npx openapi-typescript {{contract_placeholder}} -o lib/api/schema.d.ts
|
|
1303
|
+
It is saved on the lane in .appweaver/stacks.json and used on every run after this one.
|
|
1304
|
+
Leave it empty to carry on without a generated client.
|
|
1305
|
+
answer_var: client_answer
|
|
1306
|
+
- id: client_save
|
|
1307
|
+
condition: "{{client_ask}} == true"
|
|
1308
|
+
action: execute_script
|
|
1309
|
+
on_error: continue
|
|
1310
|
+
script: { ref: actions }
|
|
1311
|
+
subcommand: lane-set
|
|
1312
|
+
args: ["--id", "{{fe_lane_id}}", "--set", "client={{client_answer}}"]
|
|
1313
|
+
outputs:
|
|
1314
|
+
- { name: client_saved, from: "$.written" }
|
|
1315
|
+
- id: client_saved_set
|
|
1316
|
+
condition: "{{client_saved}} == true"
|
|
1317
|
+
action: set
|
|
1318
|
+
vars: { fe_client: "{{client_answer}}" }
|
|
1319
|
+
- id: client_run_arm
|
|
1320
|
+
condition: "{{fe_client}} != "
|
|
1321
|
+
action: set
|
|
1322
|
+
vars: { client_run: "{{client_go}}" }
|
|
1323
|
+
- id: contract_client
|
|
1324
|
+
condition: "{{client_run}} == true"
|
|
1325
|
+
action: execute_script
|
|
1326
|
+
on_error: continue
|
|
1327
|
+
script: { ref: actions }
|
|
1328
|
+
subcommand: contract-client
|
|
1329
|
+
outputs:
|
|
1330
|
+
- { name: client_ok, from: "$.ok" }
|
|
1331
|
+
- { name: client_cmd, from: "$.cmd" }
|
|
1332
|
+
- { name: client_log, from: "$.failing_excerpt" }
|
|
1333
|
+
- id: warn_client_failed
|
|
1334
|
+
condition: "{{client_run}} == true"
|
|
1335
|
+
action: verify_context
|
|
1336
|
+
require_true: client_ok
|
|
1337
|
+
on_false: continue
|
|
1338
|
+
on_false_message: "API CLIENT NOT GENERATED — the frontend lane's `client` command failed: {{client_log}}. Correct `client` on the `{{fe_lane_id}}` lane in .appweaver/stacks.json and re-run implement. Until then the frontend lane writes its calls from the API document."
|
|
1339
|
+
- id: client_status_set
|
|
1340
|
+
condition: "{{client_ok}} == true"
|
|
1341
|
+
action: set
|
|
1342
|
+
vars:
|
|
1343
|
+
client_present: "true"
|
|
1344
|
+
client_status: "generated just now by `{{client_cmd}}` from the API document — call the service THROUGH it, and never edit a generated file"
|
|
1345
|
+
- id: warn_no_client
|
|
1346
|
+
condition: "{{client_go}} == true"
|
|
1347
|
+
action: verify_context
|
|
1348
|
+
require_true: client_present
|
|
1349
|
+
on_false: continue
|
|
1350
|
+
on_false_message: "NO API CLIENT GENERATED — the frontend lane `{{fe_lane_id}}` has no working `client` command, so this run writes its calls from the API document {{contract_doc}} instead. Set `client` on the lane in .appweaver/stacks.json (`{{contract_placeholder}}` stands for the document) to generate the client on the next run."
|
|
1351
|
+
|
|
1352
|
+
# 3. THE CHECK — the operation ids the frontend plan cites, against the document.
|
|
1353
|
+
- id: contract_check
|
|
1354
|
+
condition: "{{contract_doc_exists}} == true"
|
|
1355
|
+
action: execute_script
|
|
1356
|
+
on_error: continue
|
|
1357
|
+
script: { ref: actions }
|
|
1358
|
+
subcommand: contract-check
|
|
1359
|
+
args: ["--plan", "{{fe_plan}}", "--doc", "{{contract_doc}}"]
|
|
1360
|
+
outputs:
|
|
1361
|
+
- { name: check_ok, from: "$.ok" }
|
|
1362
|
+
- { name: check_reason, from: "$.reason" }
|
|
1363
|
+
- id: warn_contract_check
|
|
1364
|
+
condition: "{{contract_doc_exists}} == true"
|
|
1365
|
+
action: verify_context
|
|
1366
|
+
require_true: check_ok
|
|
1367
|
+
on_false: continue
|
|
1368
|
+
on_false_message: "CONTRACT CHECK — {{check_reason}}. Each binding in {{fe_plan}} names the endpoint it calls by the operation id the backend plan gives it, and the built service must serve that id. Either the plan cites the wrong id (fix it with /appweaver plan, then analyze-plan) or the service never gave the endpoint that id (re-run implement for the backend lane). The frontend lane still generates; these bindings are where a call will fail."
|
|
1369
|
+
|
|
1188
1370
|
# ══════════════ THE LANE SWAP — the frontend's rules replace the backend's ═══
|
|
1189
1371
|
# build_context already scoped the two lanes' PAYLOADS apart; this is the same boundary
|
|
1190
1372
|
# for their STANDARDS, which the envelope carries and which nothing used to reset. It
|
|
1191
1373
|
# runs here rather than up with the backend's include because standards accumulate:
|
|
1192
1374
|
# loading both before either lane generated is precisely what showed each generator the
|
|
1193
1375
|
# other lane's rule set. `replace` resets to the declared seed (ai-rules stays) and then
|
|
1194
|
-
# loads `## /aw-spec-implement-
|
|
1376
|
+
# loads `## /aw-spec-implement-frontend`, so from here down the envelope is the frontend's.
|
|
1195
1377
|
#
|
|
1196
1378
|
# Nothing after the frontend sections regenerates backend code — the OKF steps that
|
|
1197
1379
|
# follow run include_standards: false — so the swap needs no undo.
|
|
@@ -1199,12 +1381,13 @@ workflow:
|
|
|
1199
1381
|
condition: "{{fe_go}} == true"
|
|
1200
1382
|
action: include
|
|
1201
1383
|
module: .appweaver/orchestrator/modules/tech-select.orch.yaml
|
|
1202
|
-
with: { command: aw-spec-implement-
|
|
1384
|
+
with: { command: aw-spec-implement-frontend, replace: "true" }
|
|
1203
1385
|
|
|
1204
1386
|
# ═══════════ FRONTEND LANE — bootstrap, generate from the MASTER plan ════════
|
|
1205
1387
|
# The experience twin of the service generation, one lane over. Its own build_context,
|
|
1206
1388
|
# because the envelope persists across steps and the two lanes must not see each other's
|
|
1207
1389
|
# payload — the frontend binds to the service's PUBLISHED surface, never its internals.
|
|
1390
|
+
# That surface is the API document the contract block exported, when there is one.
|
|
1208
1391
|
- id: ctx_frontend
|
|
1209
1392
|
condition: "{{fe_mode}} == bootstrap"
|
|
1210
1393
|
action: build_context
|
|
@@ -1212,6 +1395,7 @@ workflow:
|
|
|
1212
1395
|
- { path: "{{fe_plan}}" }
|
|
1213
1396
|
- { path: "{{domain_model}}", optional: true } # the UBIQUITOUS LANGUAGE this lane's labels, states and messages use — and what a cited BR-nnn requires
|
|
1214
1397
|
- { path: .appweaver/memory/constitution.ui.md, optional: true } # the lane's ratified UX-* base — conventions, forbidden patterns, gates
|
|
1398
|
+
- { path: "{{contract_doc}}", optional: true } # the service's API document as BUILT — what every §5 binding calls
|
|
1215
1399
|
- id: gen_frontend
|
|
1216
1400
|
condition: "{{fe_mode}} == bootstrap"
|
|
1217
1401
|
action: agent_generate
|
|
@@ -1305,6 +1489,17 @@ workflow:
|
|
|
1305
1489
|
semantics and rollback each row states.
|
|
1306
1490
|
• §6 — the cross-cutting decisions as code: what is hidden vs disabled,
|
|
1307
1491
|
accessibility obligations, localization, performance and offline behaviour.
|
|
1492
|
+
- THE SERVICE'S API DOCUMENT IS THE CONTRACT. API document: {{contract_status}}.
|
|
1493
|
+
Each §5 row names its endpoint by Operation id; find that operation in the
|
|
1494
|
+
document and take EVERYTHING about the call from it — route, verb, path and query
|
|
1495
|
+
parameters, request and response field names and their casing, status codes and
|
|
1496
|
+
error codes. Never take a route, a field name or a paging convention from memory,
|
|
1497
|
+
from convention or from the loaded standards' examples: the document is what the
|
|
1498
|
+
built service actually answers. A §5 row whose id the document does not have is a
|
|
1499
|
+
broken binding — realise the screen, leave that call unbound, report the element
|
|
1500
|
+
`blocked` naming the id, and never guess a substitute.
|
|
1501
|
+
- THE CLIENT: {{client_status}}. The client lives in this lane's client layer; a
|
|
1502
|
+
generated client is called, never edited.
|
|
1308
1503
|
- THE CLIENT IS NOT AN AUTHORITY. A client-side validation or permission check
|
|
1309
1504
|
restates a server rule for feedback; it never replaces it. Generate no server-side
|
|
1310
1505
|
behaviour, no persistence and no business rule evaluation here.
|
|
@@ -1346,6 +1541,7 @@ workflow:
|
|
|
1346
1541
|
- { path: "{{frontend_plan}}", optional: true } # the master plan — READ ONLY, never amended here
|
|
1347
1542
|
- { path: "{{domain_model}}", optional: true } # the master model — the ubiquitous language as it stands BEFORE this change
|
|
1348
1543
|
- { path: .appweaver/memory/constitution.ui.md, optional: true }
|
|
1544
|
+
- { path: "{{contract_doc}}", optional: true } # the service's API document as BUILT — what every binding row calls
|
|
1349
1545
|
- id: gen_frontend_delta
|
|
1350
1546
|
condition: "{{fe_mode}} == delta"
|
|
1351
1547
|
action: agent_generate
|
|
@@ -1425,6 +1621,15 @@ workflow:
|
|
|
1425
1621
|
service delta's "Contract deltas for the frontend lane" table as the delta plan
|
|
1426
1622
|
cites them. Generate no server-side behaviour, no persistence and no business rule
|
|
1427
1623
|
evaluation.
|
|
1624
|
+
- THE SERVICE'S API DOCUMENT IS THE CONTRACT. API document: {{contract_status}}.
|
|
1625
|
+
Each binding row leads with its endpoint's operation id; find that operation in
|
|
1626
|
+
the document and take EVERYTHING about the call from it — route, verb, path and
|
|
1627
|
+
query parameters, request and response field names and their casing, status
|
|
1628
|
+
codes and error codes — never from memory, convention or the standards' examples.
|
|
1629
|
+
A binding whose id the document does not have is broken: leave that call unbound,
|
|
1630
|
+
report the element `blocked` naming the id, and never guess a substitute.
|
|
1631
|
+
- THE CLIENT: {{client_status}}. The client lives in this lane's client layer; a
|
|
1632
|
+
generated client is called, never edited.
|
|
1428
1633
|
- Author a paired test for every ADDED/MODIFIED screen, interaction and state,
|
|
1429
1634
|
including the unwanted-behaviour states and an accessibility assertion per
|
|
1430
1635
|
interactive surface, citing the requirement id THE DELTA PLAN NAMES for that row
|
|
@@ -1499,6 +1704,10 @@ workflow:
|
|
|
1499
1704
|
plan's names are the ubiquitous language.
|
|
1500
1705
|
- A screen or a binding is done when the code realises it, whatever its route or
|
|
1501
1706
|
file is called; report it `done`.
|
|
1707
|
+
- A binding calls the operation its id names in the service's API document
|
|
1708
|
+
({{contract_status}}), taking route, verb, parameters, field names and status codes
|
|
1709
|
+
from there, through the client ({{client_status}}). An id the document does not
|
|
1710
|
+
have stays `blocked`; never guess a substitute.
|
|
1502
1711
|
- If an element cannot be realised, do not work around it: report it `blocked` and
|
|
1503
1712
|
say what stops you. A plan that is wrong is fixed in plan / analyze-plan.
|
|
1504
1713
|
- Report every listed element in an `elements` list in your closing JSON block:
|
|
@@ -1554,7 +1763,7 @@ workflow:
|
|
|
1554
1763
|
action: verify_context
|
|
1555
1764
|
require_true: lanes_complete
|
|
1556
1765
|
on_false: stop
|
|
1557
|
-
on_false_message: "PARTIAL GENERATION — implement did not realise every plan element, even after one completion pass. Backend lane: {{be_gaps_text}}. Frontend lane: {{fe_gaps_text}}. Everything written so far is kept and recorded in the OKF concept. An element reported `blocked` names what stops it — a plan that is wrong is fixed with /appweaver plan (then analyze-plan or analyze-plan-delta). An element with no code under the lane
|
|
1766
|
+
on_false_message: "PARTIAL GENERATION — implement did not realise every plan element, even after one completion pass. Backend lane: {{be_gaps_text}}. Frontend lane: {{fe_gaps_text}}. Everything written so far is kept and recorded in the OKF concept. An element reported `blocked` names what stops it — a plan that is wrong is fixed with /appweaver plan (then analyze-plan or analyze-plan-delta). An element with no code under the lane root folder is still to be written, or was written under a name that is not the plan's: re-run /appweaver implement to finish, which extends existing files rather than regenerating them."
|
|
1558
1767
|
|
|
1559
1768
|
# 11. CROSS-SLICE EDGES — a Cross-References row written into every SIBLING aggregate
|
|
1560
1769
|
# this one uses, read off the master backend plan (§1 References-by-id + its External
|
|
@@ -1691,5 +1900,5 @@ outputs:
|
|
|
1691
1900
|
plan_gate_at: "{{gate_at}}"
|
|
1692
1901
|
plan_gate_verdict: "{{gate_verdict}}"
|
|
1693
1902
|
plan_gate_routed_to_specify: "{{gate_routed_csv}}" # open spec/model gaps this code does not cover
|
|
1694
|
-
note: "Lanes come from .appweaver/stacks.json — backend declared {{be_declared}} (ready {{be_runnable}}, implemented {{be_go}}), frontend declared {{fe_declared}} (ready {{fe_runnable}}, implemented {{fe_go}}). A declared lane that was skipped printed its reason above and did not stop the other one; an undeclared lane produces nothing and that is not a failure. Each generating lane read its PLAN for what to build and {{domain_model}} for what the domain is — plus {{delta_model}} on the delta path, since the master model does not carry the change until finalize-delta merges it. Every one of those documents was READ and none was written: this phase generates code and nothing else. Each lane's outcome is backend={{be_outcome}}, frontend={{fe_outcome}} — `already-implemented` means the lane wrote no files because every plan element was already realised in its
|
|
1903
|
+
note: "Lanes come from .appweaver/stacks.json — backend declared {{be_declared}} (ready {{be_runnable}}, implemented {{be_go}}), frontend declared {{fe_declared}} (ready {{fe_runnable}}, implemented {{fe_go}}). A declared lane that was skipped printed its reason above and did not stop the other one; an undeclared lane produces nothing and that is not a failure. Each generating lane read its PLAN for what to build and {{domain_model}} for what the domain is — plus {{delta_model}} on the delta path, since the master model does not carry the change until finalize-delta merges it. Every one of those documents was READ and none was written: this phase generates code and nothing else. Each lane's outcome is backend={{be_outcome}}, frontend={{fe_outcome}} — `already-implemented` means the lane wrote no files because every plan element was already realised in its lane root folder, which is the correct result of re-running implement on a finished feature and not a failure. On the bootstrap path the plans were checked against analyze-plan's receipt before anything generated (tracked={{gate_tracked}}, fresh={{gate_fresh}}, gated {{gate_at}}) — tracked=false means this feature has never passed analyze-plan since the gate began recording what it proved, which is an unknown rather than a stale plan and blocks nothing; run /appweaver analyze-plan once to start the record."
|
|
1695
1904
|
next: "This run was mode `{{mode}}`, change `{{active_change}}` (empty on the bootstrap path). BOOTSTRAP → /appweaver build → analyze-slice → run. DELTA → /appweaver build → analyze-slice-delta {{active_change}} → finalize-delta → analyze-slice → close-delta, with the change still OPEN throughout — compile first, then analyze-slice-delta verifies that every element the delta plans marked ADDED or MODIFIED is actually in the code with a paired test (the gate that catches a lane you declined at the prompt above), then finalize-delta merges it into spec.md + the context's domain-model.md while leaving it open, analyze-slice verifies the slice against those merged masters while a red result is still recoverable, and close-delta LAST archives the change and bumps the version."
|