aw-spec-cli 0.1.27 → 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/.appweaver/RULE-PARTITION.md +8 -9
- package/assets/.appweaver/STACK-PROFILES.md +74 -9
- package/assets/.appweaver/interpreter/run-skill.py +28 -7
- package/assets/.appweaver/orchestrator/modules/delta-plan.orch.yaml +17 -7
- package/assets/.appweaver/orchestrator/modules/domain-select.orch.yaml +1 -1
- package/assets/.appweaver/orchestrator/modules/foundation-pack.orch.yaml +44 -1
- package/assets/.appweaver/orchestrator/modules/foundation-spec.orch.yaml +172 -5
- 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-rule-bindings.skeleton.md +16 -8
- package/assets/.appweaver/orchestrator/rev-templates/tech-rule-bindings.skeleton.md +15 -18
- 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/aw-spec-adopt.orch.yaml +7 -6
- 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-deploy.orch.yaml +1 -1
- package/assets/.appweaver/orchestrator/workflows/aw-spec-implement.orch.yaml +224 -16
- package/assets/.appweaver/orchestrator/workflows/aw-spec-onboard.orch.yaml +20 -19
- package/assets/.appweaver/orchestrator/workflows/aw-spec-plan.orch.yaml +35 -11
- package/assets/.appweaver/orchestrator/workflows/aw-spec-select-stack.orch.yaml +1 -1
- package/assets/.appweaver/orchestrator/workflows/aw-spec-specify.orch.yaml +1 -1
- package/assets/.appweaver/scripts/bash/aw-spec-actions.sh +91 -7
- package/assets/.appweaver/scripts/powershell/aw-spec-actions.ps1 +70 -7
- package/assets/.appweaver/scripts/python/aw-foundation.py +88 -12
- package/assets/.appweaver/scripts/python/aw-stack.py +481 -10
- package/assets/.appweaver/stack-profiles/dotnet-webapi.json +2 -0
- package/assets/.appweaver/stack-profiles/java-spring.json +2 -0
- package/assets/.appweaver/stacks.json +5 -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/foundations/dotnet/ModularMonolith/ModularMonolith.lane.json +6 -0
- package/assets/foundations/dotnet/VerticalSlice/VerticalSlice.lane.json +6 -0
- package/assets/foundations/foundation.spec.template.txt +26 -1
- package/assets/foundations/java/Hexagonal/Hexagonal.lane.json +6 -0
- package/assets/foundations/java/Hexagonal/Hexagonal.pack.txt +7 -0
- package/assets/guardrails/project-specific/domain-rule-bindings.md +20 -8
- package/assets/guardrails/project-specific/tech-rule-bindings.md +25 -37
- 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 +1 -1
- 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/package.json +1 -1
|
@@ -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,11 +87,10 @@
|
|
|
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
95
|
# TWO PATHS PER LANE. Each lane owns the lane root folder stacks.json declares for it and the
|
|
91
96
|
# test path lane-verify resolves for it — `backend/tests/` inside a new lane root folder,
|
|
@@ -248,15 +253,37 @@ vars:
|
|
|
248
253
|
fe_completion_ran: "false"
|
|
249
254
|
fe_gap_names: ""
|
|
250
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: ""
|
|
251
281
|
lanes_complete: "true"
|
|
252
282
|
generate_any: "false"
|
|
253
283
|
record_edges: "false"
|
|
254
284
|
overview_ok: "false"
|
|
255
285
|
domain_model: ""
|
|
256
286
|
domain_model_exists: "false"
|
|
257
|
-
# The backend lane's rule-set heading, keyed by MODE — see the header. The frontend
|
|
258
|
-
# lane's is the same on both paths, so it is written inline at its include.
|
|
259
|
-
be_tech_command: "aw-spec-implement"
|
|
260
287
|
# HOOK PHASES. The merged command fires the phase of every branch it actually takes, so
|
|
261
288
|
# an extensions.yml wired to any of the three former commands keeps working:
|
|
262
289
|
# before/after_implement always, the _ui pair when the frontend lane generates, the _cr
|
|
@@ -317,6 +344,8 @@ workflow:
|
|
|
317
344
|
- { name: fe_build, from: "$.frontend_build" }
|
|
318
345
|
- { name: fe_test, from: "$.frontend_test" }
|
|
319
346
|
- { name: fe_reserved, from: "$.frontend_reserved_csv" }
|
|
347
|
+
- { name: fe_workdir, from: "$.frontend_workdir" }
|
|
348
|
+
- { name: fe_client, from: "$.frontend_client" }
|
|
320
349
|
|
|
321
350
|
- id: require_lanes
|
|
322
351
|
action: verify_context
|
|
@@ -402,7 +431,6 @@ workflow:
|
|
|
402
431
|
mode: "delta"
|
|
403
432
|
pre_cr_phase: "before_implement_cr"
|
|
404
433
|
post_cr_phase: "after_implement_cr"
|
|
405
|
-
be_tech_command: "aw-spec-implement-delta"
|
|
406
434
|
|
|
407
435
|
- id: pick_change
|
|
408
436
|
condition: "{{mode}} == delta"
|
|
@@ -755,15 +783,15 @@ workflow:
|
|
|
755
783
|
- { name: fe_existing_count, from: "$.count" }
|
|
756
784
|
|
|
757
785
|
# 9. Each generating lane's code-generation rule files → sticky standards (configuration,
|
|
758
|
-
# not hardcoded). Loaded only for a lane that is actually going to generate,
|
|
759
|
-
#
|
|
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
|
|
760
788
|
# unconfigured project soft-continues, since the constitution halves still carry each
|
|
761
789
|
# lane's ratified base.
|
|
762
790
|
#
|
|
763
791
|
# EACH LANE'S RULES ARE LOADED BESIDE ITS OWN STEPS, AND THE SECOND LANE REPLACES
|
|
764
792
|
# THE FIRST'S. Both includes used to run here, before either lane generated — and
|
|
765
793
|
# sticky standards only accumulate, so on a full-stack run the backend generator was
|
|
766
|
-
# shown `## /aw-spec-implement-
|
|
794
|
+
# shown `## /aw-spec-implement-frontend` and the frontend generator the service set. Each
|
|
767
795
|
# prompt says which lane it is in, but it said so inside an envelope that contradicted
|
|
768
796
|
# it, and the envelope is the part the model cannot argue with. The frontend include
|
|
769
797
|
# now sits immediately before the FRONTEND sections below and passes replace, which
|
|
@@ -772,7 +800,7 @@ workflow:
|
|
|
772
800
|
condition: "{{be_go}} == true"
|
|
773
801
|
action: include
|
|
774
802
|
module: .appweaver/orchestrator/modules/tech-select.orch.yaml
|
|
775
|
-
with: { command:
|
|
803
|
+
with: { command: aw-spec-implement-backend }
|
|
776
804
|
|
|
777
805
|
# 10. Pre-execution hooks — see the hook-phase vars above.
|
|
778
806
|
- id: resolve_pre_hooks
|
|
@@ -892,6 +920,11 @@ workflow:
|
|
|
892
920
|
Cross-Cutting Concerns table (audit / retention / data-exposure — the CN-/DC-
|
|
893
921
|
realisations); and each integration contract (IC-) in the External Integrations
|
|
894
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.
|
|
895
928
|
- Author a paired test for every plan behaviour / use-case / endpoint; derive the
|
|
896
929
|
cases from the plan's pre/post/invariant contracts and cite the spec id (FR / BR /
|
|
897
930
|
CN / DC / IC / US) from its Traceability section. Include tests for the constraints
|
|
@@ -1042,6 +1075,10 @@ workflow:
|
|
|
1042
1075
|
invariant, handler orchestration, API error contract, the Cross-Cutting Concerns
|
|
1043
1076
|
realisations (audit / retention / data-exposure — CN-/DC-) and the External
|
|
1044
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.
|
|
1045
1082
|
- COMPONENTS: if a delta element depends on a framework component, code against its
|
|
1046
1083
|
ABSTRACTION / port as the delta plan declares — do NOT hand-roll it. Installing the
|
|
1047
1084
|
component (packages, wiring, config) is /appweaver add-component <Component>; if
|
|
@@ -1141,7 +1178,8 @@ workflow:
|
|
|
1141
1178
|
under a different name is renamed to the plan's name, with its references — the
|
|
1142
1179
|
plan's names are the ubiquitous language.
|
|
1143
1180
|
- An element the plan names by intent (a port, an adapter, an endpoint route) is done
|
|
1144
|
-
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.
|
|
1145
1183
|
- If an element cannot be realised, do not work around it: report it `blocked` and
|
|
1146
1184
|
say what stops you. A plan that is wrong is fixed in plan / analyze-plan.
|
|
1147
1185
|
- Report every listed element in an `elements` list in your closing JSON block:
|
|
@@ -1186,13 +1224,156 @@ workflow:
|
|
|
1186
1224
|
outputs:
|
|
1187
1225
|
- { name: okf_concept, from: "$.concept" }
|
|
1188
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
|
+
|
|
1189
1370
|
# ══════════════ THE LANE SWAP — the frontend's rules replace the backend's ═══
|
|
1190
1371
|
# build_context already scoped the two lanes' PAYLOADS apart; this is the same boundary
|
|
1191
1372
|
# for their STANDARDS, which the envelope carries and which nothing used to reset. It
|
|
1192
1373
|
# runs here rather than up with the backend's include because standards accumulate:
|
|
1193
1374
|
# loading both before either lane generated is precisely what showed each generator the
|
|
1194
1375
|
# other lane's rule set. `replace` resets to the declared seed (ai-rules stays) and then
|
|
1195
|
-
# loads `## /aw-spec-implement-
|
|
1376
|
+
# loads `## /aw-spec-implement-frontend`, so from here down the envelope is the frontend's.
|
|
1196
1377
|
#
|
|
1197
1378
|
# Nothing after the frontend sections regenerates backend code — the OKF steps that
|
|
1198
1379
|
# follow run include_standards: false — so the swap needs no undo.
|
|
@@ -1200,12 +1381,13 @@ workflow:
|
|
|
1200
1381
|
condition: "{{fe_go}} == true"
|
|
1201
1382
|
action: include
|
|
1202
1383
|
module: .appweaver/orchestrator/modules/tech-select.orch.yaml
|
|
1203
|
-
with: { command: aw-spec-implement-
|
|
1384
|
+
with: { command: aw-spec-implement-frontend, replace: "true" }
|
|
1204
1385
|
|
|
1205
1386
|
# ═══════════ FRONTEND LANE — bootstrap, generate from the MASTER plan ════════
|
|
1206
1387
|
# The experience twin of the service generation, one lane over. Its own build_context,
|
|
1207
1388
|
# because the envelope persists across steps and the two lanes must not see each other's
|
|
1208
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.
|
|
1209
1391
|
- id: ctx_frontend
|
|
1210
1392
|
condition: "{{fe_mode}} == bootstrap"
|
|
1211
1393
|
action: build_context
|
|
@@ -1213,6 +1395,7 @@ workflow:
|
|
|
1213
1395
|
- { path: "{{fe_plan}}" }
|
|
1214
1396
|
- { path: "{{domain_model}}", optional: true } # the UBIQUITOUS LANGUAGE this lane's labels, states and messages use — and what a cited BR-nnn requires
|
|
1215
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
|
|
1216
1399
|
- id: gen_frontend
|
|
1217
1400
|
condition: "{{fe_mode}} == bootstrap"
|
|
1218
1401
|
action: agent_generate
|
|
@@ -1306,6 +1489,17 @@ workflow:
|
|
|
1306
1489
|
semantics and rollback each row states.
|
|
1307
1490
|
• §6 — the cross-cutting decisions as code: what is hidden vs disabled,
|
|
1308
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.
|
|
1309
1503
|
- THE CLIENT IS NOT AN AUTHORITY. A client-side validation or permission check
|
|
1310
1504
|
restates a server rule for feedback; it never replaces it. Generate no server-side
|
|
1311
1505
|
behaviour, no persistence and no business rule evaluation here.
|
|
@@ -1347,6 +1541,7 @@ workflow:
|
|
|
1347
1541
|
- { path: "{{frontend_plan}}", optional: true } # the master plan — READ ONLY, never amended here
|
|
1348
1542
|
- { path: "{{domain_model}}", optional: true } # the master model — the ubiquitous language as it stands BEFORE this change
|
|
1349
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
|
|
1350
1545
|
- id: gen_frontend_delta
|
|
1351
1546
|
condition: "{{fe_mode}} == delta"
|
|
1352
1547
|
action: agent_generate
|
|
@@ -1426,6 +1621,15 @@ workflow:
|
|
|
1426
1621
|
service delta's "Contract deltas for the frontend lane" table as the delta plan
|
|
1427
1622
|
cites them. Generate no server-side behaviour, no persistence and no business rule
|
|
1428
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.
|
|
1429
1633
|
- Author a paired test for every ADDED/MODIFIED screen, interaction and state,
|
|
1430
1634
|
including the unwanted-behaviour states and an accessibility assertion per
|
|
1431
1635
|
interactive surface, citing the requirement id THE DELTA PLAN NAMES for that row
|
|
@@ -1500,6 +1704,10 @@ workflow:
|
|
|
1500
1704
|
plan's names are the ubiquitous language.
|
|
1501
1705
|
- A screen or a binding is done when the code realises it, whatever its route or
|
|
1502
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.
|
|
1503
1711
|
- If an element cannot be realised, do not work around it: report it `blocked` and
|
|
1504
1712
|
say what stops you. A plan that is wrong is fixed in plan / analyze-plan.
|
|
1505
1713
|
- Report every listed element in an `elements` list in your closing JSON block:
|
|
@@ -95,8 +95,8 @@
|
|
|
95
95
|
# guardrails/brf-<domain>/frontend/*.md — the code-derived lane rule set, the detail
|
|
96
96
|
# layer under those UX-* principles, wired into tech-rule-bindings.md under the lane's
|
|
97
97
|
# three headings: `## /aw-spec-ui-constitution` (what a later /appweaver constitution
|
|
98
|
-
# re-ratifies the UI half from), `## /aw-spec-plan-
|
|
99
|
-
# (what the frontend lane of `plan` and of `implement` load).
|
|
98
|
+
# re-ratifies the UI half from), `## /aw-spec-plan-frontend` and
|
|
99
|
+
# `## /aw-spec-implement-frontend` (what the frontend lane of `plan` and of `implement` load).
|
|
100
100
|
# .appweaver/templates/overrides/ui-design-template.md + ui-delta-design-template.md — the
|
|
101
101
|
# lane's own document pair, reverse-engineered from the UI source the same way the
|
|
102
102
|
# service pair is reverse-engineered from the service code. The lane is governed by a
|
|
@@ -149,7 +149,7 @@
|
|
|
149
149
|
# =============================================================================
|
|
150
150
|
|
|
151
151
|
name: aw-spec-onboard
|
|
152
|
-
description: Onboard an existing codebase for brownfield DEVELOPMENT — a deterministic whole-repo scan produces a high-level OKF feature map (folders/concepts) PLUS the project-level governance scaffold (split constitution + guardrails/brf-<domain>/ with its DOMAIN rule files at domain/ + domain-rule-bindings + code-derived TECHNICAL rule files at service/ + tech-rule-bindings + activated domain), all provisional-from-scan. The first context authors that tier; every later context amends it additively from its own code (new rules, principles and map entries — never a rewrite, renumbering or deletion; a contradiction is recorded as a Divergence note), and a tier that does not exist yet, such as a lane declared after an earlier onboard, is authored in full. Naming an already-onboarded context re-runs that governance pass alone. Where the scan finds a frontend lane in the CODE, it also authors that lane's half — constitution.ui.md (UX-*) — and its code-derived rule files at brf-<domain>/frontend/, mapped under `## /aw-spec-ui-constitution`, `## /aw-spec-plan-
|
|
152
|
+
description: Onboard an existing codebase for brownfield DEVELOPMENT — a deterministic whole-repo scan produces a high-level OKF feature map (folders/concepts) PLUS the project-level governance scaffold (split constitution + guardrails/brf-<domain>/ with its DOMAIN rule files at domain/ + domain-rule-bindings + code-derived TECHNICAL rule files at service/ + tech-rule-bindings + activated domain), all provisional-from-scan. The first context authors that tier; every later context amends it additively from its own code (new rules, principles and map entries — never a rewrite, renumbering or deletion; a contradiction is recorded as a Divergence note), and a tier that does not exist yet, such as a lane declared after an earlier onboard, is authored in full. Naming an already-onboarded context re-runs that governance pass alone. Where the scan finds a frontend lane in the CODE, it also authors that lane's half — constitution.ui.md (UX-*) — and its code-derived rule files at brf-<domain>/frontend/, mapped under `## /aw-spec-ui-constitution`, `## /aw-spec-plan-frontend` and `## /aw-spec-implement-frontend`; a backend-only repo gets none of it. Every rule tier is reverse-engineered from the CODE alone (never a greenfield rule file), evidenced-only, and WIRED per-workflow so the whole forward pipeline AND adopt govern against THIS codebase — never a greenfield fallback. It also reverse-engineers the repo's own technical structure into a project-specific design + delta-design template pair, installed as the project template overrides, and — where the lane exists — the frontend lane's own pair from the UI source. Every authoring step is shaped by a NEUTRAL rev-templates skeleton; no greenfield constitution, rule file or document template is ever placed in context. Accepts an optional concerns list to look for (onboard decides which are actually present). Reads any declared lane, never writes one. No migration content; never modifies source.
|
|
153
153
|
version: 2.3.0
|
|
154
154
|
agent_agnostic: true
|
|
155
155
|
dialect: aw-spec.orchestrator/v1
|
|
@@ -1036,8 +1036,10 @@ workflow:
|
|
|
1036
1036
|
charter; a later step in this same run authors it, so wire the bullet now), then the
|
|
1037
1037
|
domain identity/regulatory/interop files → domain principles.
|
|
1038
1038
|
- `## /aw-spec-specify` — the FULL domain set (specify models the domain, lifts CN-/DC-/IC-).
|
|
1039
|
-
- `## /aw-spec-plan` — `_None — plan loads no domain file. Domain reaches
|
|
1040
|
-
- `## /aw-spec-
|
|
1039
|
+
- `## /aw-spec-plan-backend` — `_None — the service lane of plan loads no domain file. Domain reaches it through the spec and the context's domain-model.md._`
|
|
1040
|
+
- `## /aw-spec-plan-frontend` — `_None — the frontend lane of plan loads no domain file. Domain reaches it through the spec and the context's domain-model.md._`
|
|
1041
|
+
- `## /aw-spec-implement-backend` — `_None — the service lane of implement loads no domain file. Domain reaches it through backend-plan.md and the context's domain-model.md._`
|
|
1042
|
+
- `## /aw-spec-implement-frontend` — `_None — the frontend lane of implement loads no domain file. Domain reaches it through frontend-plan.md and the context's domain-model.md._`
|
|
1041
1043
|
- `## /aw-spec-gate` — the conformance-checklist set (the *.domain.md files).
|
|
1042
1044
|
Each bullet is a workspace-relative path `- guardrails/{{domain_slug}}/domain/<file>`.
|
|
1043
1045
|
Write ONLY inside guardrails/{{domain_slug}}/ (domain/ + the map). Report the
|
|
@@ -1367,7 +1369,7 @@ workflow:
|
|
|
1367
1369
|
existing files (frontmatter origin: reverse-engineered, generated_by:
|
|
1368
1370
|
{{generated_by}}, concern); every rule cites a UI code coordinate from this
|
|
1369
1371
|
context and the UX numeral it details. Wire it into tech-rule-bindings.md under
|
|
1370
|
-
`## /aw-spec-plan-
|
|
1372
|
+
`## /aw-spec-plan-frontend` and/or `## /aw-spec-implement-frontend` as its rules serve
|
|
1371
1373
|
planning or generating, and give it its table row. frontend/ui-constitution.md
|
|
1372
1374
|
stays the only file under `## /aw-spec-ui-constitution` that is not also a
|
|
1373
1375
|
concern file.
|
|
@@ -1580,8 +1582,8 @@ workflow:
|
|
|
1580
1582
|
named after the concern the code exhibits. Wire it into
|
|
1581
1583
|
domain-rule-bindings.md under `## /aw-spec-specify` and `## /aw-spec-gate`
|
|
1582
1584
|
(plus `## /aw-spec-constitution` for an identity / regulatory file), as the
|
|
1583
|
-
existing files are wired.
|
|
1584
|
-
loading no domain file.
|
|
1585
|
+
existing files are wired. The plan and implement headings (`-backend` and
|
|
1586
|
+
`-frontend`) keep loading no domain file.
|
|
1585
1587
|
- NEW rules appended to an EXISTING rule file, where this context's code enforces
|
|
1586
1588
|
a rule of that concern the file does not state — each citing this context's code
|
|
1587
1589
|
and marked `(context: {{bc}})`. Mark unresolved specifics `PROVISIONAL —
|
|
@@ -1859,12 +1861,11 @@ workflow:
|
|
|
1859
1861
|
ONLY a heading you have a generated file for (an absent heading soft-continues → loads
|
|
1860
1862
|
nothing):
|
|
1861
1863
|
- `## /aw-spec-specify` — EXACTLY ONE bullet: `service/domain-modelling.md`, the modelling methodology. NEVER an architecture / persistence / codegen / security file here — specify is the domain phase and any technology rule under this heading breaks its domain purity. Omit the heading only if you did not write domain-modelling.md.
|
|
1862
|
-
- `## /aw-spec-plan`
|
|
1863
|
-
- `## /aw-spec-implement`
|
|
1864
|
-
- `## /aw-spec-implement-delta` — the same set for the service lane on the DELTA path. `implement` is one command that keys this heading when it is generating a change's delta plan and the one above when it is generating the master, so a project that wants the same rules on both paths repeats them here.
|
|
1864
|
+
- `## /aw-spec-plan-backend` — the as-built architecture / cross-cutting rules the SERVICE lane's plan author mediates the spec against.
|
|
1865
|
+
- `## /aw-spec-implement-backend` — the code-generation / convention set the SERVICE lane's generator builds against (from backend-plan.md), on both the master and the delta path.
|
|
1865
1866
|
- `## /aw-spec-build` — the layering + convention rules the compile-fixer respects.
|
|
1866
1867
|
- `## /aw-spec-analyze-slice` — the conformance rules the plan↔code gate validates against.
|
|
1867
|
-
- `## /aw-spec-adopt`
|
|
1868
|
+
- `## /aw-spec-adopt-backend` — the technical reference set the reversed backend plan mediates against (a subset of `## /aw-spec-plan-backend`'s).
|
|
1868
1869
|
- `## /aw-spec-constitution` — the standards a later `/appweaver constitution` re-ratifies the TECHNICAL half from. You authored that half from code evidence before these files existed; this heading is what makes a re-run author from THIS project's rules rather than from an empty set. Ratifiable standards only, no worked `examples/` sample, no domain file.
|
|
1869
1870
|
- `## /aw-spec-run` — the runtime / execution conventions the app-run step honors (add ONLY if the code evidences a runtime/hosting concern file; NOT data-migration — migration is the deferred later phase).
|
|
1870
1871
|
Each bullet is a
|
|
@@ -1925,7 +1926,7 @@ workflow:
|
|
|
1925
1926
|
# (or creates the file, in a project with no service lane). `## /aw-spec-ui-constitution`
|
|
1926
1927
|
# is what makes a later /appweaver constitution re-ratify the UI half from THIS project's
|
|
1927
1928
|
# lane rules, and the authoritative signal that the project HAS a frontend lane.
|
|
1928
|
-
# `## /aw-spec-plan-
|
|
1929
|
+
# `## /aw-spec-plan-frontend` and `## /aw-spec-implement-frontend` are what the frontend lane of
|
|
1929
1930
|
# `plan` and of `implement` load; without them that lane plans and generates against no
|
|
1930
1931
|
# project rule at all.
|
|
1931
1932
|
- id: ctx_ui_pack
|
|
@@ -1997,10 +1998,10 @@ workflow:
|
|
|
1997
1998
|
`frontend/ui-constitution.md` first. It is what a later /appweaver constitution
|
|
1998
1999
|
re-ratifies the UI half from, and the authoritative signal that the project has a
|
|
1999
2000
|
frontend lane; precede the bullets with a short HTML comment saying both.
|
|
2000
|
-
2. `## /aw-spec-plan-
|
|
2001
|
+
2. `## /aw-spec-plan-frontend` — the files the FRONTEND lane of `plan` authors
|
|
2001
2002
|
frontend-plan.md against: those whose rules decide a feature's screens, navigation,
|
|
2002
2003
|
client state, interaction states, forms, accessibility and service binding.
|
|
2003
|
-
3. `## /aw-spec-implement-
|
|
2004
|
+
3. `## /aw-spec-implement-frontend` — the files the FRONTEND lane of `implement` generates
|
|
2004
2005
|
code against, on the master and the delta path alike: those whose rules govern
|
|
2005
2006
|
component conventions, state and data fetching, styling, forms and UI tests.
|
|
2006
2007
|
A file whose rules carry both a planning half and a generating half is listed under both
|
|
@@ -2060,7 +2061,7 @@ workflow:
|
|
|
2060
2061
|
on_error: continue
|
|
2061
2062
|
script: { ref: actions }
|
|
2062
2063
|
subcommand: resolve-tech
|
|
2063
|
-
args: ["--command", "aw-spec-plan-
|
|
2064
|
+
args: ["--command", "aw-spec-plan-frontend"]
|
|
2064
2065
|
outputs:
|
|
2065
2066
|
- { name: ui_plan_rules, from: "$.candidates" }
|
|
2066
2067
|
- id: warn_ui_plan_wiring
|
|
@@ -2070,7 +2071,7 @@ workflow:
|
|
|
2070
2071
|
on_empty: continue
|
|
2071
2072
|
on_empty_message: >
|
|
2072
2073
|
guardrails/{{domain_slug}}/tech-rule-bindings.md maps nothing under
|
|
2073
|
-
`## /aw-spec-plan-
|
|
2074
|
+
`## /aw-spec-plan-frontend`, so the frontend lane of /appweaver plan will author
|
|
2074
2075
|
frontend-plan.md with no project rule file. Add the heading, bulleting the
|
|
2075
2076
|
frontend/ files whose rules shape a feature's screens, state and interactions.
|
|
2076
2077
|
- id: probe_ui_impl_wiring
|
|
@@ -2079,7 +2080,7 @@ workflow:
|
|
|
2079
2080
|
on_error: continue
|
|
2080
2081
|
script: { ref: actions }
|
|
2081
2082
|
subcommand: resolve-tech
|
|
2082
|
-
args: ["--command", "aw-spec-implement-
|
|
2083
|
+
args: ["--command", "aw-spec-implement-frontend"]
|
|
2083
2084
|
outputs:
|
|
2084
2085
|
- { name: ui_impl_rules, from: "$.candidates" }
|
|
2085
2086
|
- id: warn_ui_impl_wiring
|
|
@@ -2089,7 +2090,7 @@ workflow:
|
|
|
2089
2090
|
on_empty: continue
|
|
2090
2091
|
on_empty_message: >
|
|
2091
2092
|
guardrails/{{domain_slug}}/tech-rule-bindings.md maps nothing under
|
|
2092
|
-
`## /aw-spec-implement-
|
|
2093
|
+
`## /aw-spec-implement-frontend`, so the frontend lane of /appweaver implement will
|
|
2093
2094
|
generate UI code with no project rule file. Add the heading, bulleting the
|
|
2094
2095
|
frontend/ files whose rules govern component, state, styling and test conventions.
|
|
2095
2096
|
|
|
@@ -17,11 +17,14 @@
|
|
|
17
17
|
# against no declared stack invents its own.
|
|
18
18
|
#
|
|
19
19
|
# ONE COMMAND, TWO LANES, TWO RULE SETS. The lanes take their rules from different
|
|
20
|
-
# headings of tech-rule-bindings (`## /aw-spec-plan` for the service,
|
|
21
|
-
# for the frontend), and
|
|
22
|
-
#
|
|
23
|
-
#
|
|
24
|
-
#
|
|
20
|
+
# headings of tech-rule-bindings (`## /aw-spec-plan-backend` for the service,
|
|
21
|
+
# `## /aw-spec-plan-frontend` for the frontend), and each set is loaded only when its lane
|
|
22
|
+
# is declared. The two are never loaded together: the service set loads at step 1, before
|
|
23
|
+
# the backend sections, and the frontend set REPLACES it at the lane swap before the
|
|
24
|
+
# frontend sections — tech_select_ui_master on the master path, the delta-plan module's
|
|
25
|
+
# own swap on the change path. Each plan is therefore authored with only its own lane's
|
|
26
|
+
# rule set in its envelope. Where the two plans meet is stated in the frontend plan's
|
|
27
|
+
# §5 Contract Binding, which binds to the service's published surface only.
|
|
25
28
|
#
|
|
26
29
|
# RENAMED FROM `design`. design.md → backend-plan.md, design.ui.md → frontend-plan.md,
|
|
27
30
|
# and the former separate `design-ui` command is FOLDED IN here. The scaffold MIGRATES a
|
|
@@ -204,15 +207,15 @@ workflow:
|
|
|
204
207
|
on_false_message: "No lane is declared in .appweaver/stacks.json, so there is nothing to plan. Run /appweaver select-stack and declare the backend stack, the frontend stack, or both — plus each one's lane root folder — then re-run plan. The declaration is what tells this phase which documents to write; a plan written against no declared stack invents its own."
|
|
205
208
|
|
|
206
209
|
# 1. TECHNICAL rule files → sticky standards (configuration, not hardcoded).
|
|
207
|
-
# The service lane's set is loaded under `## /aw-spec-plan`; the frontend lane's
|
|
208
|
-
# `## /aw-spec-plan-
|
|
210
|
+
# The service lane's set is loaded under `## /aw-spec-plan-backend`; the frontend lane's
|
|
211
|
+
# under `## /aw-spec-plan-frontend`, and ONLY when that lane is declared — so a backend-only
|
|
209
212
|
# project's standards are exactly what they were before the two commands merged.
|
|
210
213
|
# No blocking gate: an unconfigured project soft-continues (the constitutions still
|
|
211
214
|
# carry each lane's ratified base).
|
|
212
215
|
#
|
|
213
216
|
# ONLY THE BACKEND'S RULES LOAD HERE. The frontend's used to load alongside them,
|
|
214
217
|
# before either lane authored anything, and sticky standards only accumulate — so the
|
|
215
|
-
# service plan was authored with `## /aw-spec-plan-
|
|
218
|
+
# service plan was authored with `## /aw-spec-plan-frontend` in its envelope and the
|
|
216
219
|
# experience plan with the service set. Each prompt names its lane, but it said so
|
|
217
220
|
# inside an envelope that contradicted it. The UI set now loads at the frontend
|
|
218
221
|
# boundary instead, with `replace`, in both places a frontend document is authored:
|
|
@@ -222,7 +225,7 @@ workflow:
|
|
|
222
225
|
condition: "{{be_declared}} == true"
|
|
223
226
|
action: include
|
|
224
227
|
module: .appweaver/orchestrator/modules/tech-select.orch.yaml
|
|
225
|
-
with: { command: aw-spec-plan }
|
|
228
|
+
with: { command: aw-spec-plan-backend }
|
|
226
229
|
|
|
227
230
|
# 2. Resolve the current feature and require its spec.
|
|
228
231
|
- id: feature_paths
|
|
@@ -617,6 +620,10 @@ workflow:
|
|
|
617
620
|
as field shapes. That section is the ONLY part of this document the frontend plan
|
|
618
621
|
may read; keep it complete and self-contained, because a contract the UI needs and
|
|
619
622
|
this document never states becomes a client-side workaround.
|
|
623
|
+
- NAME EVERY ENDPOINT. Each §3 endpoint carries an **Operation id** — its name in the
|
|
624
|
+
service's published API document (e.g. `CreatePatient`), unique across the
|
|
625
|
+
service and never reused. The frontend plan cites it, and implement gives the
|
|
626
|
+
endpoint exactly this id, so the two lanes meet on it.
|
|
620
627
|
- CONSTITUTION-MANDATED CROSS-CUTTING (from the loaded technical constitution, NOT
|
|
621
628
|
the spec): a NON-NEGOTIABLE technical principle you must apply that has NO
|
|
622
629
|
per-feature spec id. APPLY it (it is non-negotiable), and because it is not
|
|
@@ -704,6 +711,10 @@ workflow:
|
|
|
704
711
|
- PUBLISH THE SURFACE THE FRONTEND LANE BINDS TO: the section carrying this feature's
|
|
705
712
|
endpoints states each contract as field shapes, completely, because it is the only
|
|
706
713
|
part of this document the frontend plan may read.
|
|
714
|
+
- NAME EVERY ENDPOINT with its route, verb and operation id — its name in the
|
|
715
|
+
service's published API document, unique across the service. Where the code
|
|
716
|
+
already gives the endpoint one, record THAT id exactly as the code spells it; the
|
|
717
|
+
frontend plan cites it and implement finds the endpoint by it.
|
|
707
718
|
- CONSTITUTION-MANDATED CROSS-CUTTING (from the loaded technical constitution, NOT
|
|
708
719
|
the spec): a NON-NEGOTIABLE technical principle with no per-feature spec id —
|
|
709
720
|
APPLY it, and LOG it as a §5 DA-n whose basis cites the mandating principle
|
|
@@ -773,6 +784,9 @@ workflow:
|
|
|
773
784
|
workarounds are DECISIONS THIS TEAM MADE, not derivations from the spec — keep
|
|
774
785
|
every one, with its id and its basis, unless the thing it decided about is gone.
|
|
775
786
|
Never renumber a surviving entry: its id is cited elsewhere.
|
|
787
|
+
- OPERATION IDS ARE STABLE. Every endpoint keeps the operation id it already has —
|
|
788
|
+
the frontend plan and the built code both use it. A new endpoint gets one, unique
|
|
789
|
+
across the service; an endpoint without one gets one now.
|
|
776
790
|
- THE CODE THAT EXISTS IS THE WHAT-IS AUTHORITY. {{source_count}} source file(s)
|
|
777
791
|
realise this feature: {{source_files}}. READ them, and where the plan and the code
|
|
778
792
|
disagree about STRUCTURE, the code is what is actually there — conform to it and
|
|
@@ -788,7 +802,7 @@ workflow:
|
|
|
788
802
|
# ══════════════ THE LANE SWAP — the frontend's rules replace the backend's ═══
|
|
789
803
|
# Both tech-select includes used to run up at step 4, before either lane authored
|
|
790
804
|
# anything, and sticky standards only accumulate — so on a full-stack run the backend
|
|
791
|
-
# plan was authored with `## /aw-spec-plan-
|
|
805
|
+
# plan was authored with `## /aw-spec-plan-frontend` in its envelope and the frontend plan with
|
|
792
806
|
# the service set. Each prompt names its lane, but it did so inside an envelope that
|
|
793
807
|
# contradicted it, and the envelope is the half the model cannot argue with.
|
|
794
808
|
#
|
|
@@ -800,7 +814,7 @@ workflow:
|
|
|
800
814
|
condition: "{{fe_mode}} != skip"
|
|
801
815
|
action: include
|
|
802
816
|
module: .appweaver/orchestrator/modules/tech-select.orch.yaml
|
|
803
|
-
with: { command: aw-spec-plan-
|
|
817
|
+
with: { command: aw-spec-plan-frontend, replace: "true" }
|
|
804
818
|
|
|
805
819
|
# ═══════════ FRONTEND LANE — bootstrap, greenfield experience template ═══════
|
|
806
820
|
# The experience twin of the service plan, and the MEDIATOR between spec.md and the
|
|
@@ -867,6 +881,10 @@ workflow:
|
|
|
867
881
|
DELTA raised back to the service lane under "Contract deltas needed" — never a
|
|
868
882
|
workaround in the client. Where no service plan is in context, bind from the
|
|
869
883
|
spec's IC- surface and record that as a §8 DA-n.
|
|
884
|
+
- EVERY §5 ROW CITES ITS OPERATION ID, copied exactly from the endpoint's
|
|
885
|
+
**Operation id** in the backend plan's §3 — implement looks the endpoint up by it
|
|
886
|
+
in the service's exported API document. Where no service plan names one, write
|
|
887
|
+
`—` and record it in the same §8 DA-n.
|
|
870
888
|
- CONSTITUTION-MANDATED CROSS-CUTTING (from the loaded UI constitution, NOT the
|
|
871
889
|
spec): a NON-NEGOTIABLE UX principle you must apply that has no per-feature spec
|
|
872
890
|
id. APPLY it, and because it is not spec-derived, LOG it as a §8 DA-n whose
|
|
@@ -952,6 +970,9 @@ workflow:
|
|
|
952
970
|
states. Cite them; do not restate, re-derive or contradict them, and introduce no
|
|
953
971
|
server-side behaviour. What the experience needs and the surface lacks is a
|
|
954
972
|
contract delta raised back to the service lane, never a client workaround.
|
|
973
|
+
- EVERY BINDING ROW CITES ITS OPERATION ID, copied exactly from the backend plan —
|
|
974
|
+
implement looks the endpoint up by it in the service's exported API document.
|
|
975
|
+
Where no service plan names one, write `—` and record it as a DA-n.
|
|
955
976
|
- CONSTITUTION-MANDATED CROSS-CUTTING with no per-feature spec id: apply it, and
|
|
956
977
|
log it as a DA-n citing the mandating principle ("per constitution.ui.md
|
|
957
978
|
UX-<n>"). Do not fabricate a spec id for it and do not leave it uncited.
|
|
@@ -1010,6 +1031,9 @@ workflow:
|
|
|
1010
1031
|
— the spec's IC- ids and, where the backend plan is in context, the API contracts
|
|
1011
1032
|
it states. What the experience needs and the surface lacks is a contract delta
|
|
1012
1033
|
raised back to the service lane, never a client workaround.
|
|
1034
|
+
- EVERY BINDING ROW CITES ITS OPERATION ID, copied exactly from the backend plan; a
|
|
1035
|
+
row that has none yet gets it now, and a row whose id the backend plan no longer
|
|
1036
|
+
has is re-bound. Where no service plan names one, write `—` with a DA-n.
|
|
1013
1037
|
- TECHNOLOGY-AGNOSTIC: no framework, router, state library, component library or
|
|
1014
1038
|
styling approach — responsibilities, field shapes, events and states only.
|
|
1015
1039
|
- ADD ONE Change History row for this re-derivation, describing what MOVED and why.
|