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
|
@@ -254,10 +254,13 @@ text, and do not add a rule the model does not carry)*
|
|
|
254
254
|
per the constitution — adapt for gRPC/GraphQL/CLI if the stack differs), NOT as
|
|
255
255
|
controller code. Pin route, verb, auth, request/response shape, status codes, and
|
|
256
256
|
the error contract. Delegates to an Application use-case; no business logic here.
|
|
257
|
+
The OPERATION ID is the endpoint's name in the published API document, unique across
|
|
258
|
+
the service: the frontend plan cites it, and implement gives the endpoint exactly it.
|
|
257
259
|
-->
|
|
258
260
|
|
|
259
261
|
### `[VERB] [/route]` — [purpose] · Serves US-Y · FR-00X
|
|
260
262
|
|
|
263
|
+
- **Operation id**: `[OperationId]`
|
|
261
264
|
- **Auth**: [required role/scope]
|
|
262
265
|
- **Request**: `[path/query params]` + body `{ [field]: [type], … }`
|
|
263
266
|
- **Success**: `2xx` → `{ [response shape] }`
|
|
@@ -76,7 +76,7 @@ CN-/DC-/IC-) it realises. "Realisation only — no spec delta" for a plan-only c
|
|
|
76
76
|
| Navigation & Screens (§1) | `[screen]` | screen | US-[n] |
|
|
77
77
|
| Component Structure (§3) | `[component]` | component | US-[n] · FR-[nnn] |
|
|
78
78
|
| Client State (§2) | `[state]` | state | FR-[nnn] · DC-[nnn] |
|
|
79
|
-
| Contract Binding (§5) | `[VERB] [/route]` | binding | IC-[nnn] |
|
|
79
|
+
| Contract Binding (§5) | `[OperationId]` · `[VERB] [/route]` | binding | IC-[nnn] |
|
|
80
80
|
|
|
81
81
|
## MODIFIED — existing experience elements
|
|
82
82
|
|
|
@@ -196,11 +196,13 @@ a lost connection mid-flight.]
|
|
|
196
196
|
internals: no table, no handler, no persistence assumption crosses this
|
|
197
197
|
line. An interface the experience needs and the service does not offer is a
|
|
198
198
|
CONTRACT DELTA raised back to the service lane, never a workaround in the
|
|
199
|
-
client.
|
|
199
|
+
client. The OPERATION ID is the one backend-plan.md §3 gives the endpoint —
|
|
200
|
+
the name implement finds it by in the exported API document, and checks
|
|
201
|
+
before generating. `—` when no service plan names it yet, with a §8 DA-n. -->
|
|
200
202
|
|
|
201
|
-
| Screen / component | Operation | Sends (field shape) | Receives (field shape) | Failure handling | Serves |
|
|
202
|
-
|
|
203
|
-
| `[Screen]` | `[operation]` | [field: type, …] | [field: type, …] | [the §4 state it produces] | FR-[nnn] · IC-[nnn] |
|
|
203
|
+
| Screen / component | Operation id | Operation | Sends (field shape) | Receives (field shape) | Failure handling | Serves |
|
|
204
|
+
|---|---|---|---|---|---|---|
|
|
205
|
+
| `[Screen]` | `[OperationId]` | `[operation]` | [field: type, …] | [field: type, …] | [the §4 state it produces] | FR-[nnn] · IC-[nnn] |
|
|
204
206
|
|
|
205
207
|
**Write semantics**: [per mutating operation — optimistic or pessimistic, what
|
|
206
208
|
it invalidates, and how an optimistic update rolls back.]
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
{
|
|
2
|
+
"format": "aw-spec-pack-lane/v1",
|
|
3
|
+
"note": "How this pack's service is started on its own to export its API document. The AppHost (the lane's run command) needs Docker for its infrastructure; the API project alone runs on the local infrastructure. Development keeps HTTPS redirection off so the document is served over http. The pack's configuration carries no ConnectionStrings:SqliteConnection, which the local infrastructure reads, so the command supplies one.",
|
|
4
|
+
"contract_run": "dotnet run --project src/AppWeaver.ModularMonolith.API -- --environment Development --urls http://localhost:5000 --ConnectionStrings:SqliteConnection \"Data Source=App_Data/app.db\"",
|
|
5
|
+
"contract": "http://localhost:5000/swagger/v1/swagger.json"
|
|
6
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
{
|
|
2
|
+
"format": "aw-spec-pack-lane/v1",
|
|
3
|
+
"note": "How this pack's service is started on its own to export its API document. The AppHost (the lane's run command) needs Docker for Postgres and Redis; the Service project alone runs on SQLite. Development keeps HTTPS redirection off so the document is served over http. The pack's configuration carries no ConnectionStrings:SqliteConnection, which the local infrastructure reads, so the command supplies one.",
|
|
4
|
+
"contract_run": "dotnet run --project src/AppWeaver.VerticalSlice.Service -- --environment Development --urls http://localhost:5000 --ConnectionStrings:SqliteConnection \"Data Source=App_Data/app.db\"",
|
|
5
|
+
"contract": "http://localhost:5000/swagger/v1/swagger.json"
|
|
6
|
+
}
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
# kind: backend
|
|
2
2
|
# profiles: dotnet-webapi
|
|
3
3
|
# title: <one line shown in the /appweaver foundation pick list>
|
|
4
|
+
# contract-run: dotnet run --project src/<App>.Api -- --environment Development --urls http://localhost:5000
|
|
5
|
+
# contract: http://localhost:5000/swagger/v1/swagger.json
|
|
4
6
|
#
|
|
5
7
|
# ─────────────────────────────────────────────────────────────────────────────
|
|
6
8
|
# FOUNDATION SPEC TEMPLATE — how to describe a base project for /appweaver foundation
|
|
@@ -22,6 +24,21 @@
|
|
|
22
24
|
# Vue, SvelteKit and the Express backend alike)
|
|
23
25
|
# # title: the label in the pick list
|
|
24
26
|
#
|
|
27
|
+
# Three more header lines carry the API CONTRACT between the lanes. /appweaver foundation
|
|
28
|
+
# records them on the lane in .appweaver/stacks.json once the project is built, and
|
|
29
|
+
# /appweaver implement uses them to export the service's OpenAPI document and generate the
|
|
30
|
+
# frontend's client from it before it generates the frontend. A spec that leaves one out
|
|
31
|
+
# is asked for it at the end of the build; leaving the answer empty keeps the stack
|
|
32
|
+
# profile's default.
|
|
33
|
+
#
|
|
34
|
+
# # contract-run: (backend) the command that starts the API ON ITS OWN — no
|
|
35
|
+
# orchestration host, nothing it needs that is not on this machine —
|
|
36
|
+
# run in the lane root folder. <App> stands for the app name given
|
|
37
|
+
# at /appweaver foundation
|
|
38
|
+
# # contract: (backend) the URL that running API serves its OpenAPI document at
|
|
39
|
+
# # client: (frontend) the command that generates the API client from that
|
|
40
|
+
# document; {{contract}} in it stands for the document's path
|
|
41
|
+
#
|
|
25
42
|
# The header is the leading block of `#` lines; the first line that does not start with
|
|
26
43
|
# `#` ends it. Everything after this header block is the spec itself, written for the
|
|
27
44
|
# agent that builds the project — be concrete. The same shape works for a spec given at
|
|
@@ -64,10 +81,18 @@ middleware, a sample test that proves the test project runs.
|
|
|
64
81
|
Settings files, environment variables, ports, connection strings (placeholders, never
|
|
65
82
|
secrets).
|
|
66
83
|
|
|
84
|
+
## API document
|
|
85
|
+
Backend: the API serves its OpenAPI document at the `# contract:` URL, and the
|
|
86
|
+
`# contract-run:` command starts it on its own on the port that URL names — over http, with
|
|
87
|
+
every setting it needs to start present in its configuration (a local database file, not a
|
|
88
|
+
container). Frontend: say which tool the `# client:` command runs, so it is installed as a
|
|
89
|
+
development dependency.
|
|
90
|
+
|
|
67
91
|
## Tests
|
|
68
92
|
The test project(s): framework, where they live (the lane's test path), and the one test that
|
|
69
93
|
must pass on a fresh scaffold.
|
|
70
94
|
|
|
71
95
|
## Done when
|
|
72
96
|
How to confirm the scaffold works — the lane's build passes, the test command passes, the app
|
|
73
|
-
starts and answers a named URL
|
|
97
|
+
starts and answers a named URL (for a backend, the `# contract:` URL, started with the
|
|
98
|
+
`# contract-run:` command).
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
{
|
|
2
|
+
"format": "aw-spec-pack-lane/v1",
|
|
3
|
+
"note": "How this pack's service is started on its own to export its API document. It is one Maven module on a local H2 file database, so the Maven wrapper starts it as it is; springdoc serves the OpenAPI document at /v3/api-docs. The port is pinned so the URL below is where it answers.",
|
|
4
|
+
"contract_run": "./mvnw spring-boot:run -Dspring-boot.run.arguments=--server.port=8080",
|
|
5
|
+
"contract": "http://localhost:8080/v3/api-docs"
|
|
6
|
+
}
|
|
@@ -657,6 +657,13 @@ Write-Output "MVN_CMD=$MAVEN_HOME/bin/$MVN_CMD"
|
|
|
657
657
|
<artifactId>spring-boot-starter-web</artifactId>
|
|
658
658
|
</dependency>
|
|
659
659
|
|
|
660
|
+
<!-- OpenAPI document at /v3/api-docs and Swagger UI at /swagger-ui.html -->
|
|
661
|
+
<dependency>
|
|
662
|
+
<groupId>org.springdoc</groupId>
|
|
663
|
+
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
|
|
664
|
+
<version>3.1.1</version>
|
|
665
|
+
</dependency>
|
|
666
|
+
|
|
660
667
|
<dependency>
|
|
661
668
|
<groupId>org.springframework.boot</groupId>
|
|
662
669
|
<artifactId>spring-boot-starter-data-jpa</artifactId>
|
|
@@ -74,12 +74,22 @@ through the spec/design (as CN-/DC-/IC- ids).
|
|
|
74
74
|
- guardrails/domain/healthcare/api-versioning.domain.md
|
|
75
75
|
- guardrails/domain/healthcare/vertical-slices.domain.md
|
|
76
76
|
|
|
77
|
-
## /aw-spec-plan
|
|
78
|
-
_None —
|
|
77
|
+
## /aw-spec-plan-backend
|
|
78
|
+
_None — the service lane of plan loads no domain file. Domain reaches it only through the spec
|
|
79
|
+
(BR-/CN-/DC-/IC-) and the context's domain-model.md._
|
|
79
80
|
|
|
80
|
-
## /aw-spec-
|
|
81
|
-
_None —
|
|
82
|
-
|
|
81
|
+
## /aw-spec-plan-frontend
|
|
82
|
+
_None — the frontend lane of plan loads no domain file. Domain reaches it only through the spec
|
|
83
|
+
and the context's domain-model.md._
|
|
84
|
+
|
|
85
|
+
## /aw-spec-implement-backend
|
|
86
|
+
_None — the service lane of implement loads no domain file. Domain reaches it only through
|
|
87
|
+
backend-plan.md and the context's domain-model.md. Framework components are added separately via
|
|
88
|
+
`/appweaver add-component`._
|
|
89
|
+
|
|
90
|
+
## /aw-spec-implement-frontend
|
|
91
|
+
_None — the frontend lane of implement loads no domain file. Domain reaches it only through
|
|
92
|
+
frontend-plan.md and the context's domain-model.md._
|
|
83
93
|
|
|
84
94
|
## /aw-spec-gate
|
|
85
95
|
<!-- Conformance checklist for the gates (analyze-plan · analyze-slice): the domain-derived
|
|
@@ -106,10 +116,12 @@ components are added separately via `/appweaver add-component`._
|
|
|
106
116
|
|
|
107
117
|
| Command | Domain rule files | Role |
|
|
108
118
|
|---|---|---|
|
|
109
|
-
| /aw-spec-constitution |
|
|
119
|
+
| /aw-spec-constitution | 16 | domain principles (XVI+) — the industry constitution + standard industry rules + the project's own requirements |
|
|
110
120
|
| /aw-spec-specify | 19 | author into spec (lift → CN-/DC-/IC-) |
|
|
111
|
-
| /aw-spec-plan | 0 | none — spec
|
|
112
|
-
| /aw-spec-
|
|
121
|
+
| /aw-spec-plan-backend | 0 | none — the spec and the domain model carry the domain |
|
|
122
|
+
| /aw-spec-plan-frontend | 0 | none — the spec and the domain model carry the domain |
|
|
123
|
+
| /aw-spec-implement-backend | 0 | none — backend-plan.md and the domain model carry the domain |
|
|
124
|
+
| /aw-spec-implement-frontend | 0 | none — frontend-plan.md and the domain model carry the domain |
|
|
113
125
|
| /aw-spec-gate | 14 | conformance checklist (validate, don't author) |
|
|
114
126
|
|
|
115
127
|
> Retired in the orchestrator pipeline: the prose `/aw-spec-plan` phase, `/aw-spec-tasks`,
|
|
@@ -15,11 +15,12 @@ NOT listed here — every consumer refers to it directly, as-is.
|
|
|
15
15
|
`guardrails/technology/{{frontend_stack}}/` (the frontend lane). Both are **standard rules
|
|
16
16
|
shared by every project that maps them**, and neither is domain-specific. The frontend corpus is
|
|
17
17
|
read by four headings — `## /aw-spec-ui-constitution` ratifies the lane's base,
|
|
18
|
-
`## /aw-spec-plan-
|
|
19
|
-
`## /aw-spec-foundation-frontend` is what a spec-built scaffold of the lane follows.
|
|
20
|
-
-
|
|
21
|
-
|
|
22
|
-
|
|
18
|
+
`## /aw-spec-plan-frontend` / `## /aw-spec-implement-frontend` carry the detail rules under
|
|
19
|
+
it, and `## /aw-spec-foundation-frontend` is what a spec-built scaffold of the lane follows.
|
|
20
|
+
- `plan`, `implement` and `foundation` are keyed per lane KIND, not per command: each runs
|
|
21
|
+
both lanes in one run and loads one set or the other for each — `## /aw-spec-<command>-backend`
|
|
22
|
+
for the service lane, `## /aw-spec-<command>-frontend` for the frontend lane. `foundation`
|
|
23
|
+
loads its set only when the lane is built from a spec — a pack is unpacked as-is.
|
|
23
24
|
- The two files this project authors — `service/technical-requirements.md` and
|
|
24
25
|
`frontend/ui-requirements.md` — live beside this map. They are the only mapped technical
|
|
25
26
|
files expected to differ between two projects on the same stacks.
|
|
@@ -68,7 +69,7 @@ NOT listed here — every consumer refers to it directly, as-is.
|
|
|
68
69
|
|
|
69
70
|
⚠ The ux/ files sit in a DOMAIN corpus folder but are TECHNICAL-tier inputs: a file's
|
|
70
71
|
tier is the map that lists it, not the folder it lives in. guardrails/domain/healthcare/
|
|
71
|
-
ihe-conformance.md under ## /aw-spec-plan is the same pattern. Unmapping them does not
|
|
72
|
+
ihe-conformance.md under ## /aw-spec-plan-backend is the same pattern. Unmapping them does not
|
|
72
73
|
make the spec's Experience Standards section disappear — the section is unconditional and
|
|
73
74
|
resolves to "None" — it removes the methodology specify fills it from. -->
|
|
74
75
|
- guardrails/technology/{{backend_stack}}/domain-driven-design.md
|
|
@@ -78,7 +79,7 @@ NOT listed here — every consumer refers to it directly, as-is.
|
|
|
78
79
|
- guardrails/domain/healthcare/ux/accessibility-standards.md
|
|
79
80
|
- guardrails/domain/healthcare/ux/content-design.md
|
|
80
81
|
|
|
81
|
-
## /aw-spec-plan
|
|
82
|
+
## /aw-spec-plan-backend
|
|
82
83
|
<!-- The technical/architecture rule files the design author works from (alongside the
|
|
83
84
|
spec and constitution.technical.md), each followed by its worked example. NO domain file
|
|
84
85
|
here — domain reaches design only as spec ids (BR-/CN-/DC-/IC-). -->
|
|
@@ -107,10 +108,10 @@ NOT listed here — every consumer refers to it directly, as-is.
|
|
|
107
108
|
- guardrails/technology/{{backend_stack}}/examples/authorization.md
|
|
108
109
|
- guardrails/technology/{{backend_stack}}/examples/auditing.md
|
|
109
110
|
|
|
110
|
-
## /aw-spec-plan-
|
|
111
|
-
<!-- The FRONTEND LANE's design phase. Its own heading, not a branch of ## /aw-spec-plan:
|
|
111
|
+
## /aw-spec-plan-frontend
|
|
112
|
+
<!-- The FRONTEND LANE's design phase. Its own heading, not a branch of ## /aw-spec-plan-backend:
|
|
112
113
|
the two lanes are governed by different constitution halves and own disjoint source
|
|
113
|
-
paths, so keying the map on
|
|
114
|
+
paths, so keying the map on a heading of its own gives the lane its own rule set for zero
|
|
114
115
|
mechanism change. NO domain file here — the domain reaches design.ui.md as spec ids,
|
|
115
116
|
exactly as it reaches design.md. The lane's ratified base (constitution.ui.md) is
|
|
116
117
|
referred to directly and is NOT mapped.
|
|
@@ -137,11 +138,13 @@ NOT listed here — every consumer refers to it directly, as-is.
|
|
|
137
138
|
- guardrails/technology/{{frontend_stack}}/performance-budgets.md
|
|
138
139
|
- guardrails/technology/{{frontend_stack}}/api-integration.{{backend_stack}}.md
|
|
139
140
|
|
|
140
|
-
## /aw-spec-implement
|
|
141
|
+
## /aw-spec-implement-backend
|
|
141
142
|
<!-- The FRAMEWORK / code-generation rule files the SERVICE lane's generator builds against
|
|
142
|
-
(alongside backend-plan.md and constitution.technical.md)
|
|
143
|
-
|
|
144
|
-
|
|
143
|
+
(alongside backend-plan.md and constitution.technical.md). It is loaded on BOTH paths,
|
|
144
|
+
master and delta: a change's code follows the same rules as the master it changes.
|
|
145
|
+
NO domain file — domain reaches implement only through the plan (on the delta path, the
|
|
146
|
+
master backend-plan.md + the change's delta plan). clean-architecture/cqrs are planning
|
|
147
|
+
concerns; component wiring is a separate /appweaver add-component step. -->
|
|
145
148
|
- guardrails/technology/{{backend_stack}}/coding-standards.md
|
|
146
149
|
- guardrails/technology/{{backend_stack}}/dependency-policy.md
|
|
147
150
|
- guardrails/technology/{{backend_stack}}/folder-structure.md
|
|
@@ -149,10 +152,10 @@ NOT listed here — every consumer refers to it directly, as-is.
|
|
|
149
152
|
- guardrails/technology/{{backend_stack}}/testing.md
|
|
150
153
|
- guardrails/technology/{{backend_stack}}/PACKAGING.md
|
|
151
154
|
|
|
152
|
-
## /aw-spec-implement-
|
|
155
|
+
## /aw-spec-implement-frontend
|
|
153
156
|
<!-- The FRONTEND LANE's code-generation set — the HOW that lane of `implement` builds
|
|
154
157
|
against, alongside frontend-plan.md and constitution.ui.md. It is loaded on BOTH paths,
|
|
155
|
-
master and delta,
|
|
158
|
+
master and delta, as the service lane's set is. NO domain file
|
|
156
159
|
(domain reached the lane through spec -> frontend-plan.md), and NO service-lane file
|
|
157
160
|
beyond the pairing rules below — this lane never writes outside its declared lane root folder.
|
|
158
161
|
|
|
@@ -176,20 +179,6 @@ NOT listed here — every consumer refers to it directly, as-is.
|
|
|
176
179
|
- guardrails/technology/{{frontend_stack}}/observability.md
|
|
177
180
|
- guardrails/technology/{{frontend_stack}}/frontend-testing.md
|
|
178
181
|
|
|
179
|
-
## /aw-spec-implement-delta
|
|
180
|
-
<!-- The SERVICE lane's set on the DELTA path — same FRAMEWORK / code-generation rules (HOW
|
|
181
|
-
to build). `implement` is one command for both paths and both lanes: it keys this
|
|
182
|
-
heading while generating a change's delta-backend-plan.md and `## /aw-spec-implement`
|
|
183
|
-
while generating the master, so keep the two identical unless a change deliberately
|
|
184
|
-
needs different rules. The delta's code is generated against the master backend-plan.md
|
|
185
|
-
+ the delta plan; no domain file (domain reached the delta via delta-spec → delta plan). -->
|
|
186
|
-
- guardrails/technology/{{backend_stack}}/coding-standards.md
|
|
187
|
-
- guardrails/technology/{{backend_stack}}/dependency-policy.md
|
|
188
|
-
- guardrails/technology/{{backend_stack}}/folder-structure.md
|
|
189
|
-
- guardrails/technology/{{backend_stack}}/framework-api-map.md
|
|
190
|
-
- guardrails/technology/{{backend_stack}}/testing.md
|
|
191
|
-
- guardrails/technology/{{backend_stack}}/PACKAGING.md
|
|
192
|
-
|
|
193
182
|
## /aw-spec-build
|
|
194
183
|
<!-- The compile/fix reference set: the layering + coding rules the fixer respects when
|
|
195
184
|
repairing compile errors against the design intent, plus the layering example it repairs
|
|
@@ -289,14 +278,13 @@ NOT listed here — every consumer refers to it directly, as-is.
|
|
|
289
278
|
| Command | Technical rule files | Role |
|
|
290
279
|
|---|---|---|
|
|
291
280
|
| /aw-spec-specify | 6 | the modelling methodology the spec is expressed in: DDD for the domain model (+ its example), and the four ux/ rules for the experience model it lifts as UX- ids — no technology |
|
|
292
|
-
| /aw-spec-plan | 24 | architecture/security/interop the design author mediates the spec against, each with its example |
|
|
293
|
-
| /aw-spec-plan-
|
|
294
|
-
| /aw-spec-implement |
|
|
295
|
-
| /aw-spec-implement-
|
|
296
|
-
| /aw-spec-implement-delta | 5 | the same set as /aw-spec-implement, for the service lane when implement is generating a change's delta plan |
|
|
281
|
+
| /aw-spec-plan-backend | 24 | architecture/security/interop the design author mediates the spec against, each with its example |
|
|
282
|
+
| /aw-spec-plan-frontend | 11 | the frontend lane's design set — composition, routing, client state, interaction states, forms, auth surface, design system, accessibility, i18n, performance, and the cross-lane API pairing the UI design author works from (from spec.md) |
|
|
283
|
+
| /aw-spec-implement-backend | 6 | governance/architecture the SERVICE lane builds against (from backend-plan.md), both paths |
|
|
284
|
+
| /aw-spec-implement-frontend | 13 | the FRONTEND lane's code-generation set (from frontend-plan.md), both paths — conventions, the generated client + its service pairing, auth, client security, states, forms, design system, accessibility, i18n, performance, observability and testing |
|
|
297
285
|
| /aw-spec-build | 3 | layering + coding rules the compile-fixer respects, + the layering example |
|
|
298
|
-
| /aw-spec-analyze-slice |
|
|
299
|
-
| /aw-spec-constitution |
|
|
286
|
+
| /aw-spec-analyze-slice | 3 | testing + coding rules and the framework API map the design↔code gate validates against |
|
|
287
|
+
| /aw-spec-constitution | 18 | what the technical half ratifies — the technology base, the standard technical rules, and the project team's technical-requirements.md |
|
|
300
288
|
| /aw-spec-ui-constitution | 2 | what the frontend lane's half ratifies — the UI base + the project team's ui-requirements.md — and the signal that the lane exists |
|
|
301
289
|
| /aw-spec-run | 2 | persistence rules the execution / data-migration step generates against, + its example |
|
|
302
290
|
| /aw-spec-foundation-backend | 7 | what `foundation` builds the service lane's base project against when it is built from a spec rather than unpacked from a pack |
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# API Versioning Policy
|
|
2
2
|
|
|
3
|
-
> Pure technology (domain-agnostic) — domain (e.g. FHIR) versioning in [[api-versioning.domain]]. Commands: `/aw-spec-plan`.
|
|
3
|
+
> Pure technology (domain-agnostic) — domain (e.g. FHIR) versioning in [[api-versioning.domain]]. Commands: `/aw-spec-plan-backend`.
|
|
4
4
|
|
|
5
5
|
## REST versioning
|
|
6
6
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Auditing & Observability Standards
|
|
2
2
|
|
|
3
|
-
> Pure technology (domain-agnostic) — domain audit additions in [[auditing.domain]]. NON-NEGOTIABLE. Commands: `/aw-spec-plan`.
|
|
3
|
+
> Pure technology (domain-agnostic) — domain audit additions in [[auditing.domain]]. NON-NEGOTIABLE. Commands: `/aw-spec-plan-backend`.
|
|
4
4
|
|
|
5
5
|
## Observability baseline
|
|
6
6
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Authorization Standards
|
|
2
2
|
|
|
3
|
-
> Pure technology (domain-agnostic) — domain roles & matrix in [[authorization.domain]]. NON-NEGOTIABLE. Commands: `/aw-spec-plan`.
|
|
3
|
+
> Pure technology (domain-agnostic) — domain roles & matrix in [[authorization.domain]]. NON-NEGOTIABLE. Commands: `/aw-spec-plan-backend`.
|
|
4
4
|
|
|
5
5
|
## Authorization model
|
|
6
6
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Clean Architecture Standards
|
|
2
2
|
|
|
3
|
-
> Pure technology (domain-agnostic). NON-NEGOTIABLE. Commands: `/aw-spec-plan`, `/aw-spec-build`.
|
|
3
|
+
> Pure technology (domain-agnostic). NON-NEGOTIABLE. Commands: `/aw-spec-plan-backend`, `/aw-spec-build`.
|
|
4
4
|
|
|
5
5
|
## Dependency direction
|
|
6
6
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Coding Standards
|
|
2
2
|
|
|
3
|
-
> Pure technology (domain-agnostic) — domain forbidden patterns & CI gates in [[coding-standards.domain]]. Commands: `/aw-spec-implement
|
|
3
|
+
> Pure technology (domain-agnostic) — domain forbidden patterns & CI gates in [[coding-standards.domain]]. Commands: `/aw-spec-implement-backend`, `/aw-spec-build`, `/aw-spec-analyze-slice`, `/aw-spec-foundation-backend`.
|
|
4
4
|
|
|
5
5
|
## Naming conventions
|
|
6
6
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# CQRS + Mediator Standards
|
|
2
2
|
|
|
3
|
-
> Pure technology (domain-agnostic) — domain additions in [[cqrs.domain]]. NON-NEGOTIABLE. Commands: `/aw-spec-plan`.
|
|
3
|
+
> Pure technology (domain-agnostic) — domain additions in [[cqrs.domain]]. NON-NEGOTIABLE. Commands: `/aw-spec-plan-backend`.
|
|
4
4
|
|
|
5
5
|
## Command / query patterns
|
|
6
6
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Data Classification Standards
|
|
2
2
|
|
|
3
|
-
> Pure technology (domain-agnostic) — domain data categories in [[data-classification.domain]]. NON-NEGOTIABLE. Commands: `/aw-spec-plan`.
|
|
3
|
+
> Pure technology (domain-agnostic) — domain data categories in [[data-classification.domain]]. NON-NEGOTIABLE. Commands: `/aw-spec-plan-backend`.
|
|
4
4
|
|
|
5
5
|
## Classification framework
|
|
6
6
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Dependency Policy
|
|
2
2
|
|
|
3
|
-
> Pure technology (domain-agnostic) — domain package rules in [[dependency-policy.domain]]. Commands: `/aw-spec-implement
|
|
3
|
+
> Pure technology (domain-agnostic) — domain package rules in [[dependency-policy.domain]]. Commands: `/aw-spec-implement-backend`, `/aw-spec-foundation-backend`.
|
|
4
4
|
|
|
5
5
|
## Package governance
|
|
6
6
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Eventing Standards
|
|
2
2
|
|
|
3
|
-
> Pure technology (domain-agnostic) — domain additions in [[eventing.domain]]. Commands: `/aw-spec-plan`.
|
|
3
|
+
> Pure technology (domain-agnostic) — domain additions in [[eventing.domain]]. Commands: `/aw-spec-plan-backend`.
|
|
4
4
|
|
|
5
5
|
## Domain events
|
|
6
6
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Mandatory Folder Structure
|
|
2
2
|
|
|
3
|
-
> Pure technology (domain-agnostic) — domain additions (Interop adapters, conformance tests, fixtures) in [[folder-structure.domain]]. NON-NEGOTIABLE. Commands: `/aw-spec-plan
|
|
3
|
+
> Pure technology (domain-agnostic) — domain additions (Interop adapters, conformance tests, fixtures) in [[folder-structure.domain]]. NON-NEGOTIABLE. Commands: `/aw-spec-plan-backend`, `/aw-spec-implement-backend`, `/aw-spec-foundation-backend`.
|
|
4
4
|
>
|
|
5
5
|
> Replace `<SampleProjectName>` with the project name (e.g. `Acme.Billing`).
|
|
6
6
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# Framework API Map — which package and namespace each cited type comes from
|
|
2
2
|
|
|
3
3
|
> Pure technology (domain-agnostic). NON-NEGOTIABLE where it names a package.
|
|
4
|
-
> Commands: `/aw-spec-implement
|
|
4
|
+
> Commands: `/aw-spec-implement-backend`, `/aw-spec-analyze-slice`, `/aw-spec-foundation-backend`.
|
|
5
5
|
>
|
|
6
6
|
> The rules in this corpus name framework types — `AggregateRootBase<TId>`,
|
|
7
7
|
> `IAggregateChild`, `IUnitOfWork`. This file says where each one LIVES. Without it a
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Persistence Standards
|
|
2
2
|
|
|
3
|
-
> Pure technology (domain-agnostic) — domain additions in [[persistence.domain]]. NON-NEGOTIABLE where marked. Commands: `/aw-spec-plan`, `/aw-spec-run`.
|
|
3
|
+
> Pure technology (domain-agnostic) — domain additions in [[persistence.domain]]. NON-NEGOTIABLE where marked. Commands: `/aw-spec-plan-backend`, `/aw-spec-run`.
|
|
4
4
|
|
|
5
5
|
## EF Core conventions
|
|
6
6
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Testing Standards
|
|
2
2
|
|
|
3
|
-
> Pure technology (domain-agnostic) — domain additions in [[testing.domain]]. Commands: `/aw-spec-plan
|
|
3
|
+
> Pure technology (domain-agnostic) — domain additions in [[testing.domain]]. Commands: `/aw-spec-plan-backend`, `/aw-spec-implement-backend`, `/aw-spec-analyze-slice`, `/aw-spec-foundation-backend`.
|
|
4
4
|
|
|
5
5
|
## Test-first engineering
|
|
6
6
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Vertical Slice Standards
|
|
2
2
|
|
|
3
|
-
> Pure technology (domain-agnostic) — domain additions in [[vertical-slices.domain]]. Commands: `/aw-spec-plan`.
|
|
3
|
+
> Pure technology (domain-agnostic) — domain additions in [[vertical-slices.domain]]. Commands: `/aw-spec-plan-backend`.
|
|
4
4
|
|
|
5
5
|
## Feature organization
|
|
6
6
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Zero-Trust Standards
|
|
2
2
|
|
|
3
|
-
> Pure technology (domain-agnostic) — domain additions in [[zero-trust.domain]]. NON-NEGOTIABLE where marked. Commands: `/aw-spec-plan`.
|
|
3
|
+
> Pure technology (domain-agnostic) — domain additions in [[zero-trust.domain]]. NON-NEGOTIABLE where marked. Commands: `/aw-spec-plan-backend`.
|
|
4
4
|
|
|
5
5
|
## Transport security (mTLS / TLS)
|
|
6
6
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# Accessibility Standards — nextjs (frontend lane)
|
|
2
2
|
|
|
3
3
|
> Pure technology (domain-agnostic). NON-NEGOTIABLE.
|
|
4
|
-
> Commands: `/aw-spec-plan-
|
|
4
|
+
> Commands: `/aw-spec-plan-frontend`, `/aw-spec-implement-frontend`.
|
|
5
5
|
> Detail layer under `constitution.ui.md` UX-I (accessibility floor).
|
|
6
6
|
|
|
7
7
|
UX-I makes the floor non-negotiable; this file is what meeting it means in practice. The
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# API Client Standards — nextjs (frontend lane)
|
|
2
2
|
|
|
3
3
|
> Pure technology (domain-agnostic). NON-NEGOTIABLE.
|
|
4
|
-
> Commands: `/aw-spec-implement-
|
|
4
|
+
> Commands: `/aw-spec-implement-frontend`, `/aw-spec-foundation-frontend`.
|
|
5
5
|
> Detail layer under `constitution.ui.md` UX-IV (the contract is the only server input)
|
|
6
6
|
> and UX-VII (mutations flow through one path).
|
|
7
7
|
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
> The CROSS-LANE pairing rules: how the `nextjs` frontend lane consumes an
|
|
4
4
|
> `dotnet-webapi` service lane. NON-NEGOTIABLE where marked.
|
|
5
|
-
> Commands: `/aw-spec-plan-
|
|
5
|
+
> Commands: `/aw-spec-plan-frontend`, `/aw-spec-implement-frontend`.
|
|
6
6
|
> Detail layer under `constitution.ui.md` UX-IV (the contract is the only server input).
|
|
7
7
|
|
|
8
8
|
This file is named for the service lane it pairs with, and a project maps it through the
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
> The CROSS-LANE pairing rules: how the `nextjs` frontend lane consumes a `java-spring`
|
|
4
4
|
> (Spring Boot) service lane. NON-NEGOTIABLE where marked.
|
|
5
|
-
> Commands: `/aw-spec-plan-
|
|
5
|
+
> Commands: `/aw-spec-plan-frontend`, `/aw-spec-implement-frontend`.
|
|
6
6
|
> Detail layer under `constitution.ui.md` UX-IV (the contract is the only server input).
|
|
7
7
|
|
|
8
8
|
This file is named for the service lane it pairs with, and a project maps it through the
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# Authentication & Session Standards — nextjs (frontend lane)
|
|
2
2
|
|
|
3
3
|
> Pure technology (domain-agnostic). NON-NEGOTIABLE.
|
|
4
|
-
> Commands: `/aw-spec-plan-
|
|
4
|
+
> Commands: `/aw-spec-plan-frontend`, `/aw-spec-implement-frontend`.
|
|
5
5
|
> Detail layer under `constitution.ui.md` UX-VIII (client state carries no secret) and
|
|
6
6
|
> UX-IV (the contract is the only server input).
|
|
7
7
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# Client Security Standards — nextjs (frontend lane)
|
|
2
2
|
|
|
3
3
|
> Pure technology (domain-agnostic). NON-NEGOTIABLE.
|
|
4
|
-
> Commands: `/aw-spec-implement-
|
|
4
|
+
> Commands: `/aw-spec-implement-frontend`.
|
|
5
5
|
> Detail layer under `constitution.ui.md` UX-VIII (client state carries no secret).
|
|
6
6
|
|
|
7
7
|
The client is a hostile environment: its code is readable, its storage is inspectable, and
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Component Architecture Standards — nextjs (frontend lane)
|
|
2
2
|
|
|
3
|
-
> Pure technology (domain-agnostic). Commands: `/aw-spec-plan-
|
|
3
|
+
> Pure technology (domain-agnostic). Commands: `/aw-spec-plan-frontend`, `/aw-spec-foundation-frontend`.
|
|
4
4
|
> Detail layer under `constitution.ui.md` UX-II (design system) and UX-III (server components).
|
|
5
5
|
|
|
6
6
|
The rules the UI design author composes a feature's `§3 Component Structure` from. They
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Component Conventions — nextjs (frontend lane)
|
|
2
2
|
|
|
3
|
-
> Pure technology (domain-agnostic). Commands: `/aw-spec-implement-
|
|
3
|
+
> Pure technology (domain-agnostic). Commands: `/aw-spec-implement-frontend`, `/aw-spec-foundation-frontend`.
|
|
4
4
|
> Detail layer under `constitution.ui.md` UX-II (design system) and its Mandatory
|
|
5
5
|
> Frontend Folder Structure.
|
|
6
6
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# Design System Standards — nextjs (frontend lane)
|
|
2
2
|
|
|
3
3
|
> Pure technology (domain-agnostic). NON-NEGOTIABLE.
|
|
4
|
-
> Commands: `/aw-spec-plan-
|
|
4
|
+
> Commands: `/aw-spec-plan-frontend`, `/aw-spec-implement-frontend`, `/aw-spec-foundation-frontend`.
|
|
5
5
|
> Detail layer under `constitution.ui.md` UX-II (the design system is the only source of
|
|
6
6
|
> visual truth).
|
|
7
7
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Interaction & Error State Standards — nextjs (frontend lane)
|
|
2
2
|
|
|
3
|
-
> Pure technology (domain-agnostic). Commands: `/aw-spec-plan-
|
|
3
|
+
> Pure technology (domain-agnostic). Commands: `/aw-spec-plan-frontend`, `/aw-spec-implement-frontend`.
|
|
4
4
|
> Detail layer under `constitution.ui.md` UX-V (every interaction state is specified).
|
|
5
5
|
|
|
6
6
|
The rules behind `design.ui.md §4 Interaction & Flow` — the section a backend-shaped
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# Forms & Validation Standards — nextjs (frontend lane)
|
|
2
2
|
|
|
3
3
|
> Pure technology (domain-agnostic). NON-NEGOTIABLE where marked.
|
|
4
|
-
> Commands: `/aw-spec-plan-
|
|
4
|
+
> Commands: `/aw-spec-plan-frontend`, `/aw-spec-implement-frontend`.
|
|
5
5
|
> Detail layer under `constitution.ui.md` UX-V (every interaction state is specified) and
|
|
6
6
|
> UX-VII (mutations flow through one path).
|
|
7
7
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# Frontend Testing Standards — nextjs (frontend lane)
|
|
2
2
|
|
|
3
3
|
> Pure technology (domain-agnostic). NON-NEGOTIABLE.
|
|
4
|
-
> Commands: `/aw-spec-implement-
|
|
4
|
+
> Commands: `/aw-spec-implement-frontend`, `/aw-spec-foundation-frontend`.
|
|
5
5
|
> Detail layer under `constitution.ui.md` UX-XI (frontend test-first).
|
|
6
6
|
|
|
7
7
|
Every file `implement-ui` generates ships with its test. The design says what to test: each
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Internationalization Standards — nextjs (frontend lane)
|
|
2
2
|
|
|
3
|
-
> Pure technology (domain-agnostic). Commands: `/aw-spec-plan-
|
|
3
|
+
> Pure technology (domain-agnostic). Commands: `/aw-spec-plan-frontend`, `/aw-spec-implement-frontend`.
|
|
4
4
|
> Detail layer under `constitution.ui.md` UX-X (internationalization is structural).
|
|
5
5
|
|
|
6
6
|
Internationalization is structural: it is cheap while the surface is being designed and
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# Frontend Observability Standards — nextjs (frontend lane)
|
|
2
2
|
|
|
3
3
|
> Pure technology (domain-agnostic). NON-NEGOTIABLE where marked.
|
|
4
|
-
> Commands: `/aw-spec-implement-
|
|
4
|
+
> Commands: `/aw-spec-implement-frontend`.
|
|
5
5
|
> Detail layer under `constitution.ui.md` UX-VIII (client state carries no secret).
|
|
6
6
|
|
|
7
7
|
The service is instrumented end to end — OpenTelemetry, structured logs, trace propagation
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# Performance Budget Standards — nextjs (frontend lane)
|
|
2
2
|
|
|
3
3
|
> Pure technology (domain-agnostic). NON-NEGOTIABLE.
|
|
4
|
-
> Commands: `/aw-spec-plan-
|
|
4
|
+
> Commands: `/aw-spec-plan-frontend`, `/aw-spec-implement-frontend`.
|
|
5
5
|
> Detail layer under `constitution.ui.md` UX-IX (the performance budget is a gate).
|
|
6
6
|
|
|
7
7
|
A budget that is not enforced is an aspiration. Core Web Vitals thresholds and a per-route
|