aw-spec-cli 0.1.14 → 0.1.16
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/STACK-PROFILES.md +1 -1
- package/assets/.appweaver/orchestrator/modules/spec-state-gate.orch.yaml +87 -0
- package/assets/.appweaver/orchestrator/orchestrator.py +5 -0
- package/assets/.appweaver/orchestrator/rev-templates/domain-rule-bindings.skeleton.md +10 -3
- package/assets/.appweaver/orchestrator/rev-templates/tech-rule-bindings.skeleton.md +38 -11
- package/assets/.appweaver/orchestrator/workflows/aw-spec-adopt.orch.yaml +2 -1
- package/assets/.appweaver/orchestrator/workflows/aw-spec-analyze-design.orch.yaml +672 -124
- package/assets/.appweaver/orchestrator/workflows/aw-spec-analyze-slice.orch.yaml +700 -72
- package/assets/.appweaver/orchestrator/workflows/aw-spec-implement-ui.orch.yaml +531 -135
- package/assets/.appweaver/orchestrator/workflows/aw-spec-implement.orch.yaml +573 -145
- package/assets/.appweaver/orchestrator/workflows/aw-spec-onboard.orch.yaml +78 -14
- package/assets/.appweaver/orchestrator/workflows/aw-spec-plan-ui.orch.yaml +600 -0
- package/assets/.appweaver/orchestrator/workflows/aw-spec-plan.orch.yaml +721 -0
- package/assets/.appweaver/orchestrator/workflows/aw-spec-select-feature.orch.yaml +3 -3
- package/assets/.appweaver/orchestrator/workflows/aw-spec-specify.orch.yaml +119 -32
- package/assets/.appweaver/orchestrator/workflows/aw-spec-story-plan.orch.yaml +1147 -0
- package/assets/.appweaver/orchestrator/workflows/aw-spec-sync-stories.orch.yaml +1121 -0
- package/assets/.appweaver/scripts/bash/aw-spec-actions.sh +2564 -38
- package/assets/.appweaver/scripts/bash/aw-xref.sh +2 -1
- package/assets/.appweaver/scripts/powershell/aw-spec-actions.ps1 +2458 -22
- package/assets/.appweaver/scripts/powershell/aw-xref.ps1 +2 -1
- package/assets/.appweaver/scripts/python/aw-payload-parity.py +158 -0
- package/assets/.appweaver/scripts/python/aw-xref.py +431 -48
- package/assets/.appweaver/templates/design-template.md +88 -54
- package/assets/.appweaver/templates/spec-template.md +12 -10
- package/assets/.appweaver/templates/story-template.md +83 -12
- package/assets/.appweaver/templates/ui-design-template.md +71 -39
- package/assets/guardrails/projects/dotnet-default-project/domain-rule-bindings.md +19 -7
- package/assets/guardrails/projects/dotnet-default-project/tech-rule-bindings.md +35 -26
- package/package.json +1 -1
- package/assets/.appweaver/orchestrator/workflows/aw-spec-design-ui.orch.yaml +0 -386
- package/assets/.appweaver/orchestrator/workflows/aw-spec-design.orch.yaml +0 -382
|
@@ -2,40 +2,56 @@
|
|
|
2
2
|
|
|
3
3
|
**Aggregate (feature)**: `[Aggregate]` <!-- the feature = the aggregate, e.g. Order -->
|
|
4
4
|
|
|
5
|
-
**Design home**: `specs/[Aggregate]/
|
|
5
|
+
**Design home**: `specs/[Aggregate]/backend-plan.md` <!-- the service lane; the frontend twin is frontend-plan.md, owned by /appweaver plan-ui -->
|
|
6
6
|
|
|
7
7
|
**Source spec**: `specs/[Aggregate]/spec.md`
|
|
8
8
|
|
|
9
|
-
**Version**: v1.0 <!--
|
|
9
|
+
**Version**: v1.0 <!-- SCRIPT-OWNED: plan-stamp sets this to the spec version this plan derives from. Never edit it by hand. -->
|
|
10
10
|
|
|
11
11
|
**Status**: Draft
|
|
12
12
|
|
|
13
13
|
<!--
|
|
14
14
|
WHAT THIS DOCUMENT IS
|
|
15
15
|
=====================
|
|
16
|
-
The single, living High-Level Design (HLD) for ONE aggregate
|
|
17
|
-
MEDIATOR between spec.md (WHAT/WHY,
|
|
18
|
-
(HOW, tech-specific). It is NOT code: it
|
|
19
|
-
behaviour, and decisions — enough for ANY capable LLM
|
|
20
|
-
spec-satisfying code on ANY target stack, but no complete
|
|
16
|
+
The single, living High-Level Design (HLD) for ONE aggregate — the FEATURE-LEVEL
|
|
17
|
+
ARCHITECTURAL CONFIRMATION. It is the MEDIATOR between spec.md (WHAT/WHY,
|
|
18
|
+
tech-agnostic) and the generated code (HOW, tech-specific). It is NOT code: it
|
|
19
|
+
carries structure, contracts, behaviour, and decisions — enough for ANY capable LLM
|
|
20
|
+
to generate correct, spec-satisfying code on ANY target stack, but no complete
|
|
21
|
+
method bodies.
|
|
21
22
|
|
|
22
|
-
spec.md ──▶
|
|
23
|
-
behaviour structure &
|
|
24
|
-
(FR/BR/
|
|
23
|
+
spec.md ──▶ backend-plan.md ──▶ story-backend-plan.md ──▶ code (+ tests)
|
|
24
|
+
behaviour structure & the story's slice generated by `implement`
|
|
25
|
+
(FR/BR/CN/SC) decisions (HLD) (concrete, ephemeral)
|
|
26
|
+
|
|
27
|
+
It is LONG-LIVED and moves FORWARD with the spec: /appweaver plan authors it, and
|
|
28
|
+
conforms it whenever the spec's Change History says something it realises has moved.
|
|
29
|
+
Story designs READ it and never write back — nothing merges into this document.
|
|
25
30
|
|
|
26
31
|
ANCHORING RULES
|
|
27
|
-
- Every design element traces UP to a spec id (FR-/BR-/CN-/DC-/IC-/
|
|
28
|
-
|
|
29
|
-
|
|
32
|
+
- Every design element traces UP to a spec id (FR-/BR-/CN-/DC-/IC-/SC-) and the
|
|
33
|
+
whole spec is covered DOWN here (see §6 Traceability). No design element without
|
|
34
|
+
a spec reason; no spec requirement without a design home.
|
|
30
35
|
- THE SPEC IS THE ONLY DOMAIN INPUT. Design reads the spec + the technical/
|
|
31
36
|
architecture standards — NOT the domain rule files. The domain reached this doc
|
|
32
37
|
only as spec ids: business invariants (BR-), domain-derived constraints (CN- —
|
|
33
38
|
retention/immutability/audit/limits), data classification (DC-), and interop
|
|
34
39
|
obligations (IC-). Realise each of those; invent no domain rule the spec omits
|
|
35
40
|
(if one seems missing, record it as an Assumption in §7, never smuggle it in).
|
|
36
|
-
-
|
|
37
|
-
|
|
38
|
-
|
|
41
|
+
- THE CODE IS THE WHAT-EXISTS INPUT, and it is a different authority from the spec.
|
|
42
|
+
Where code already realises this feature, the plan describes and ADJUSTS TO the
|
|
43
|
+
structure that is actually there rather than an idealised one, and names any
|
|
44
|
+
deliberate divergence as a §8 WA-n. The code never overrides the spec on
|
|
45
|
+
BEHAVIOUR, and it may not introduce a domain rule the spec omits — code that
|
|
46
|
+
contradicts the spec is a finding to report, not a design to bless.
|
|
47
|
+
- NO STORY IDS ANYWHERE IN THIS DOCUMENT. Stories live in stories/ and cite the
|
|
48
|
+
requirement ids they deliver; this design traces to FR-/BR-, which is what keeps
|
|
49
|
+
it stable while the backlog churns, is reprioritised and is re-raised.
|
|
50
|
+
- Feature = aggregate. Commands (CreateOrder, UpdateOrder…) are REQUIREMENTS
|
|
51
|
+
(FR-n) in the spec, not features and not stories. One aggregate = one
|
|
52
|
+
backend-plan.md = one owning design for its code files. A later requirement is
|
|
53
|
+
CONFORMED into this document by /appweaver plan's update mode — never a new
|
|
54
|
+
design doc, and never a delta document.
|
|
39
55
|
|
|
40
56
|
WHAT LIVES ELSEWHERE (do NOT repeat it here — it is identical for every feature)
|
|
41
57
|
- The clean-architecture layering + dependency rule (API → Application → Domain
|
|
@@ -47,6 +63,13 @@
|
|
|
47
63
|
- Physical persistence (PKs/FKs, columns, indexes, JSON shapes, migration SQL)
|
|
48
64
|
belongs to a technical-data-model. This doc states WHAT is stored and WHICH
|
|
49
65
|
port persists it, not the schema.
|
|
66
|
+
- THE PUBLISHED SURFACE belongs to `interfaces.md`, this feature's APPEND-ONLY
|
|
67
|
+
interface log — the anchor the frontend lane designs against. /appweaver plan
|
|
68
|
+
publishes each entry there (the script assigns IF-nnn, the date and
|
|
69
|
+
status: proposed); /appweaver plan-ui and the FE story designs READ the latest
|
|
70
|
+
entry per id. §3 here is the INDEX that cites those ids, never a second copy of
|
|
71
|
+
the contract: two copies drift, and only the log has a lifecycle and a
|
|
72
|
+
supersedes: chain.
|
|
50
73
|
|
|
51
74
|
TECHNOLOGY-AGNOSTIC (mandatory)
|
|
52
75
|
- Express behaviour as SIGNATURES + pre/post/invariant/raises pseudocode and
|
|
@@ -128,7 +151,7 @@ trade-off. Layering follows the project architecture standard (constitution).]
|
|
|
128
151
|
|
|
129
152
|
| Event | Raised by | Trigger | Key payload | Serves |
|
|
130
153
|
|---|---|---|---|---|
|
|
131
|
-
| `[EntityStateChanged]` | `[Root/Entity]` | [what causes it] | `[id, key fields]` | FR-00X ·
|
|
154
|
+
| `[EntityStateChanged]` | `[Root/Entity]` | [what causes it] | `[id, key fields]` | FR-00X · BR-00Z |
|
|
132
155
|
|
|
133
156
|
### 1.3 Entities
|
|
134
157
|
|
|
@@ -162,7 +185,7 @@ trade-off. Layering follows the project architecture standard (constitution).]
|
|
|
162
185
|
Invariant: [what must hold — maps to a spec BR-nnn]
|
|
163
186
|
Post-condition: [resulting state / outputs]
|
|
164
187
|
Raises: [DomainEvent]
|
|
165
|
-
Serves: FR-00X ·
|
|
188
|
+
Serves: FR-00X · BR-00Z
|
|
166
189
|
```
|
|
167
190
|
|
|
168
191
|
**Invariants** *(always-true; each maps to a spec BR-nnn — do not add rules absent from the spec)*
|
|
@@ -182,13 +205,13 @@ trade-off. Layering follows the project architecture standard (constitution).]
|
|
|
182
205
|
Purpose: [why this can't live on one entity]
|
|
183
206
|
Steps: 1. … 2. … 3. …
|
|
184
207
|
Touches: [aggregates/ports coordinated]
|
|
185
|
-
Serves: FR-00X
|
|
208
|
+
Serves: FR-00X
|
|
186
209
|
```
|
|
187
210
|
|
|
188
211
|
## 2. Application Layer
|
|
189
212
|
|
|
190
213
|
<!--
|
|
191
|
-
Use-cases: one command/query per
|
|
214
|
+
Use-cases: one command/query per requirement action (FR-n), its handler's orchestration,
|
|
192
215
|
the ports it depends on, application-level rules (authorization, input validation,
|
|
193
216
|
transaction + event publication), and the request/response DTO shapes. Consumes
|
|
194
217
|
Domain types and the PORTS the Domain/Application defines; NEVER touches
|
|
@@ -206,9 +229,9 @@ trade-off. Layering follows the project architecture standard (constitution).]
|
|
|
206
229
|
|
|
207
230
|
### 2.2 Use-cases (commands / queries)
|
|
208
231
|
|
|
209
|
-
<!-- One block per use-case = one
|
|
232
|
+
<!-- One block per use-case = one requirement action. This is the LLM's unit of work. -->
|
|
210
233
|
|
|
211
|
-
#### `[Command/Query]` — Serves
|
|
234
|
+
#### `[Command/Query]` — Serves FR-00X
|
|
212
235
|
|
|
213
236
|
- **Type**: command (writes) | query (reads)
|
|
214
237
|
- **Request (DTO)**: `{ [field]: [type], … }`
|
|
@@ -224,33 +247,41 @@ trade-off. Layering follows the project architecture standard (constitution).]
|
|
|
224
247
|
4. [persist via port] (single transaction boundary)
|
|
225
248
|
5. [publish domain events]
|
|
226
249
|
6. return [Response]
|
|
227
|
-
On failure: [which error → which
|
|
250
|
+
On failure: [which error → which published-interface status; the contract is the
|
|
251
|
+
IF- entry cited in §3]
|
|
228
252
|
```
|
|
229
253
|
- **Emits**: `[DomainEvent]` (from §1.2)
|
|
230
254
|
|
|
231
|
-
## 3. API Layer
|
|
255
|
+
## 3. API Layer — the published surface (INDEX; the wording lives in `interfaces.md`)
|
|
232
256
|
|
|
233
257
|
<!--
|
|
234
|
-
The contract other systems couple to. Describe it at PROTOCOL level
|
|
235
|
-
per the constitution — adapt for gRPC/GraphQL/CLI if the stack differs),
|
|
236
|
-
controller code.
|
|
237
|
-
|
|
258
|
+
The contract other systems and the frontend couple to. Describe it at PROTOCOL level
|
|
259
|
+
(REST assumed per the constitution — adapt for gRPC/GraphQL/CLI if the stack differs),
|
|
260
|
+
NEVER as controller code. Delegates to an Application use-case; no business logic here.
|
|
261
|
+
|
|
262
|
+
WHERE IT LIVES. Each published interface is an entry in `specs/[Aggregate]/interfaces.md`,
|
|
263
|
+
the append-only interface log: route/verb, auth, request and response shapes, status
|
|
264
|
+
codes and the error contract. `plan` publishes those entries — the script assigns the
|
|
265
|
+
IF-nnn id, the date and status: proposed — and `plan-ui`, the FE story designs and any
|
|
266
|
+
consuming feature read the LATEST entry per id. This section is the INDEX only.
|
|
267
|
+
|
|
268
|
+
HOW TO FILL IT
|
|
269
|
+
- An interface that ALREADY has an entry in the log (it is in context on an update
|
|
270
|
+
run): cite its IF- id here, and describe nothing.
|
|
271
|
+
- An interface being published for the FIRST TIME in this run: describe it in the
|
|
272
|
+
"Interface" cell in one line and leave the IF- id cell as `(this run)` — the log
|
|
273
|
+
assigns the real id after this document is written, and the next update run cites
|
|
274
|
+
it. Never invent an IF- number: the script is the only id authority.
|
|
275
|
+
- CHANGING a published interface is a NEW entry that supersedes the old one, never
|
|
276
|
+
an edit to the existing entry and never a change to this table alone.
|
|
277
|
+
- Every row cites the spec ids it serves and the use-case that implements it, so
|
|
278
|
+
§6 Traceability and the analyze gate can follow the chain both ways.
|
|
238
279
|
-->
|
|
239
280
|
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
-
|
|
243
|
-
|
|
244
|
-
- **Success**: `2xx` → `{ [response shape] }`
|
|
245
|
-
- **Errors** *(the error contract)*:
|
|
246
|
-
|
|
247
|
-
| Status | When | Body shape |
|
|
248
|
-
|---|---|---|
|
|
249
|
-
| 400 | [validation failure] | `{ errors: [{ field, message }] }` |
|
|
250
|
-
| 403 | [unauthorized] | `{ error }` |
|
|
251
|
-
| 409 | [conflict / duplicate — maps to a BR] | `{ error }` |
|
|
252
|
-
|
|
253
|
-
- **Maps to**: `[Command/Query]` (§2.2)
|
|
281
|
+
| Interface | IF- id | Serves | Implemented by |
|
|
282
|
+
|---|---|---|---|
|
|
283
|
+
| `[VERB] [/route]` — [purpose] | IF-00n | FR-00X | `[Command/Query]` (§2.2) |
|
|
284
|
+
| `[DomainEvent]` published outside this feature | (this run) | FR-00X · BR-00X | §2.2 emits, §1.2 |
|
|
254
285
|
|
|
255
286
|
## 4. Infrastructure Layer
|
|
256
287
|
|
|
@@ -316,7 +347,7 @@ trade-off. Layering follows the project architecture standard (constitution).]
|
|
|
316
347
|
## 6. Traceability (the spine)
|
|
317
348
|
|
|
318
349
|
<!--
|
|
319
|
-
The two-way guarantee: every FR/BR/CN/DC/IC/
|
|
350
|
+
The two-way guarantee: every FR/BR/CN/DC/IC/SC has a design home, and every
|
|
320
351
|
design element has a spec reason. This is what makes impact analysis exact and lets
|
|
321
352
|
the analyze gate verify coverage. Keep it complete — EVERY CN-/DC-/IC- in the spec
|
|
322
353
|
MUST appear as a row here (that is how the analyze gate proves no lifted constraint
|
|
@@ -331,7 +362,6 @@ trade-off. Layering follows the project architecture standard (constitution).]
|
|
|
331
362
|
| CN-001 | constraint | [where realised — §1 invariant / §4 persistence / §5 cross-cutting] | [layer] |
|
|
332
363
|
| DC-001 | classification | [exposure enforcement — §2 projection / §5 data-protection] | App·Infra |
|
|
333
364
|
| IC-001 | contract | [adapter/port realising it — §4.2] | Infra |
|
|
334
|
-
| US-1 | story | [end-to-end elements realising it] | all |
|
|
335
365
|
| SC-001 | success | [where it is met + how verified] | [layer] |
|
|
336
366
|
|
|
337
367
|
## 7. Assumptions (to clarify later)
|
|
@@ -369,15 +399,19 @@ trade-off. Layering follows the project architecture standard (constitution).]
|
|
|
369
399
|
## 9. Change History
|
|
370
400
|
|
|
371
401
|
<!--
|
|
372
|
-
The living-truth ledger, in lockstep with spec.md
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
402
|
+
The living-truth ledger, in lockstep with spec.md — MANDATORY, and the one section
|
|
403
|
+
whose loss is refused rather than absorbed: plan-stamp writes no baseline at all if
|
|
404
|
+
this section went missing, so a dropped ledger can never be silently stamped over.
|
|
405
|
+
|
|
406
|
+
SCRIPT-OWNED. `plan-stamp` is the only writer: it appends one row per update naming
|
|
407
|
+
the requirement ids conformed, and moves the **Version** header to the spec version
|
|
408
|
+
this plan now derives from. The model writes NO version and NO row, ever — not here,
|
|
409
|
+
not in the header. Newest last.
|
|
410
|
+
|
|
411
|
+
Three columns, matching exactly what the stamp writes: the derived spec version, the
|
|
412
|
+
date, and what changed (the conformed ids are carried in that cell).
|
|
379
413
|
-->
|
|
380
414
|
|
|
381
|
-
| Version | Date | Change |
|
|
382
|
-
|
|
383
|
-
| v1.0 | [DATE] | Initial design |
|
|
415
|
+
| Version | Date | Change |
|
|
416
|
+
|---------|------|--------|
|
|
417
|
+
| v1.0 | [DATE] | Initial design |
|
|
@@ -15,8 +15,10 @@
|
|
|
15
15
|
single LIVING source of truth for its whole lifecycle. Every operation on it
|
|
16
16
|
(CreateOrder, UpdateOrder, …) is a REQUIREMENT below (FR-n) — NOT a separate
|
|
17
17
|
feature and NOT a user story. A later requirement is a new FR-n added here,
|
|
18
|
-
never a new spec folder. One spec
|
|
19
|
-
|
|
18
|
+
never a new spec folder. One spec, and one PLAN per lane that derives from it:
|
|
19
|
+
specs/[Aggregate]/backend-plan.md (/appweaver plan) and, where a frontend lane is
|
|
20
|
+
declared, specs/[Aggregate]/frontend-plan.md (/appweaver plan-ui). Both move FORWARD
|
|
21
|
+
with this document and never write back to it.
|
|
20
22
|
|
|
21
23
|
THIS DOCUMENT HOLDS NO USER STORIES. A story is an execution SLICE over this
|
|
22
24
|
spec and lives beside it in stories/, citing the FR-/BR- ids it delivers. This
|
|
@@ -84,7 +86,7 @@
|
|
|
84
86
|
only place the spec describes the delivery surface at all.
|
|
85
87
|
|
|
86
88
|
NOT SCREENS. No pages, layouts, navigation, components or visual design — those are
|
|
87
|
-
realisation decisions owned by the prototype and
|
|
89
|
+
realisation decisions owned by the prototype and frontend-plan.md, and putting them here
|
|
88
90
|
would break the WHAT/HOW line the whole kit rests on.
|
|
89
91
|
|
|
90
92
|
Lifted with the Experience Standards below, from the frontend lane's constitution
|
|
@@ -203,17 +205,17 @@
|
|
|
203
205
|
The PROJECT-WIDE experience standards this aggregate's UI must satisfy, lifted here by
|
|
204
206
|
specify out of the frontend lane's constitution (constitution.ui.md — the UX-* principle
|
|
205
207
|
series) and the mapped ux/ rule files, exactly as CN-/DC-/IC- lift the domain rules.
|
|
206
|
-
The lift is what makes them binding: prototype, ui
|
|
208
|
+
The lift is what makes them binding: prototype, plan-ui and implement-ui author from
|
|
207
209
|
the SPEC and never from the rule files, so a standard not carried here reaches no UI
|
|
208
210
|
phase and is gated by nothing.
|
|
209
211
|
|
|
210
212
|
HIGH-LEVEL AND PROJECT-WIDE ONLY. Each entry is a standard the whole product holds to,
|
|
211
213
|
stated so it can be checked on ANY surface — never a screen, page, layout, navigation
|
|
212
|
-
model, component or visual-design choice. Those are the prototype's and
|
|
214
|
+
model, component or visual-design choice. Those are the prototype's and frontend-plan.md's
|
|
213
215
|
to settle. An entry that can be satisfied only one way has stopped being a standard and
|
|
214
216
|
has become a design decision in the wrong document.
|
|
215
217
|
|
|
216
|
-
Give each a STABLE id (UX-001, …). Its OWN id class on purpose: ui
|
|
218
|
+
Give each a STABLE id (UX-001, …). Its OWN id class on purpose: plan-ui and the UI
|
|
217
219
|
code gate review and verify these separately from the service lane, so the two never
|
|
218
220
|
have to be untangled out of one list. The consequence to respect — the service-side
|
|
219
221
|
gates (analyze-design, analyze-slice) trace CN- and never read this section, so a bound
|
|
@@ -275,7 +277,7 @@
|
|
|
275
277
|
Fenced out of the ledger ON PURPOSE. The sha256 that guards this document covers the
|
|
276
278
|
CONTRACT, and this section is not contract — it is a projection of the backlog. Were it
|
|
277
279
|
inside the hash, creating a story would look like an unledgered spec edit and refuse the
|
|
278
|
-
next
|
|
280
|
+
next sync-stories; were it visible to the diff, adding a story would read as a
|
|
279
281
|
requirement change and mint a version row. So spec-check, spec-diff and ledger-append
|
|
280
282
|
all cut this block out before they look at anything.
|
|
281
283
|
-->
|
|
@@ -283,7 +285,7 @@
|
|
|
283
285
|
<!-- AW:COVERAGE:BEGIN -->
|
|
284
286
|
| Requirement | Open stories | Closed / cancelled |
|
|
285
287
|
|-------------|--------------|--------------------|
|
|
286
|
-
| _(none yet — run /appweaver
|
|
288
|
+
| _(none yet — run /appweaver sync-stories to raise the backlog)_ | | |
|
|
287
289
|
<!-- AW:COVERAGE:END -->
|
|
288
290
|
|
|
289
291
|
## Change History
|
|
@@ -294,12 +296,12 @@
|
|
|
294
296
|
Each row names the requirement ids that version touched. Every story records the spec
|
|
295
297
|
version it last synced at (spec_version: in its frontmatter), so a story is stale when
|
|
296
298
|
some row above its version names an id that story cites — one version comparison, no
|
|
297
|
-
per-requirement content hashing.
|
|
299
|
+
per-requirement content hashing. sync-stories reads the rows to refresh the backlog;
|
|
298
300
|
update-spec appends one when it folds a hand-edited story back into this document.
|
|
299
301
|
|
|
300
302
|
The ledger is hand-written, so it is guarded. active_version.json carries a sha256 of
|
|
301
303
|
this whole file as of the last ledger-aware write. A body that has changed while the
|
|
302
|
-
version stands still is a hand edit that skipped the ledger:
|
|
304
|
+
version stands still is a hand edit that skipped the ledger: sync-stories and
|
|
303
305
|
check-stories refuse until a row is added, because otherwise every affected story goes
|
|
304
306
|
quietly stale and nothing says so.
|
|
305
307
|
|
|
@@ -4,9 +4,13 @@ type: functional
|
|
|
4
4
|
status: open
|
|
5
5
|
title: [one line — the outcome this story delivers]
|
|
6
6
|
exercises: []
|
|
7
|
+
constraints: []
|
|
7
8
|
spec_version: [vN.N]
|
|
8
9
|
depends_on: []
|
|
10
|
+
wave: 1
|
|
9
11
|
follows:
|
|
12
|
+
designed_lanes: []
|
|
13
|
+
dropped_lanes: []
|
|
10
14
|
work_item:
|
|
11
15
|
created: [DATE]
|
|
12
16
|
---
|
|
@@ -15,21 +19,25 @@ created: [DATE]
|
|
|
15
19
|
USER STORY — one execution slice over a feature's spec.
|
|
16
20
|
|
|
17
21
|
Canonical home: specs/<Feature>/stories/<Feature-NNN>.md
|
|
18
|
-
Execution artefacts, once story-
|
|
22
|
+
Execution artefacts, once story-plan has run: specs/<Feature>/stories/<Feature-NNN>/
|
|
23
|
+
(story-backend-plan.md and story-frontend-plan.md — the ephemeral designs, one per
|
|
24
|
+
declared lane; every run appends a pass to each lane in scope, the latest pass wins,
|
|
25
|
+
and a hand edit to that pass is what implement builds)
|
|
19
26
|
|
|
20
27
|
A story is a slice of work over a spec that is already written. It is NEVER a proposal
|
|
21
28
|
to change the spec — nothing here merges back into spec.md. When a story genuinely
|
|
22
|
-
needs the contract to change,
|
|
29
|
+
needs the contract to change, sync-spec (⌛ not built yet — the hand route is
|
|
30
|
+
.appweaver/SPEC-EDIT-PROTOCOL.md) folds it back through specify's
|
|
23
31
|
checklist -> clarify -> validate loop, and the spec's Change History gains a row.
|
|
24
32
|
|
|
25
33
|
ONE STORY, ONE FEATURE. A story whose design touches a second feature is failed by
|
|
26
|
-
|
|
34
|
+
analysis. Cross-feature ordering goes in depends_on, not in a second story.
|
|
27
35
|
|
|
28
36
|
FRONTMATTER — every field the gates read lives here, so checking the backlog is a
|
|
29
37
|
directory scan rather than a markdown parse.
|
|
30
38
|
|
|
31
39
|
id Minted by the kit: the feature name plus the next free number in
|
|
32
|
-
stories/.
|
|
40
|
+
stories/. The writer refuses to overwrite an existing file, so a
|
|
33
41
|
collision is an add/add git conflict, never a silent overwrite.
|
|
34
42
|
change-story-id corrects it while it is still legal — see below.
|
|
35
43
|
|
|
@@ -53,28 +61,64 @@ created: [DATE]
|
|
|
53
61
|
id. A requirement is DELIVERED when it has NO OPEN STORIES — not when a
|
|
54
62
|
particular story closed, because a follow-on may carry the remainder.
|
|
55
63
|
|
|
64
|
+
constraints The spec-level bounds this slice must satisfy: the CN-/DC-/IC-/UX- ids,
|
|
65
|
+
lifted from spec.md by the kit and never typed by hand. Spec constraints
|
|
66
|
+
are declared aggregate-wide, so the feature's WHOLE set binds every slice
|
|
67
|
+
of it and there is nothing to choose. This field is the gate surface —
|
|
68
|
+
implement, implement-ui and analyze-slice read it — and the "## Constraints"
|
|
69
|
+
section below is where each id gets the line saying what THIS slice does
|
|
70
|
+
about it. Stamped by sync-stories; a story written before this field
|
|
71
|
+
existed has no key at all, and its readers fall back to the section.
|
|
72
|
+
|
|
56
73
|
spec_version The spec version this story last synced at. A row above this version
|
|
57
|
-
naming an id in exercises means the story is stale;
|
|
58
|
-
reports it and
|
|
74
|
+
naming an id in exercises OR constraints means the story is stale;
|
|
75
|
+
check-stories reports it and sync-stories acts on it. Restamped on
|
|
76
|
+
every sync.
|
|
59
77
|
|
|
60
78
|
depends_on Story ids that must land first, e.g. [Payment-004]. About CODE ordering,
|
|
61
79
|
not spec: implement warns on an open dependency, which is where calling
|
|
62
80
|
into code that does not exist starts to cost something. close-story
|
|
63
81
|
warns but does not block — a dependency still being open does not make
|
|
64
82
|
this story's own work wrong. A cycle is rejected at authoring time.
|
|
83
|
+
sync-stories writes this as a UNION with what is already here, so an
|
|
84
|
+
edge added by hand — including one naming another feature's story — is
|
|
85
|
+
never lost to a re-sync.
|
|
86
|
+
|
|
87
|
+
wave The dependency LEVEL this story sits at, computed by sync-stories from
|
|
88
|
+
depends_on:. Wave 1 means nothing has to land before it; wave N means
|
|
89
|
+
every story in depends_on: sits in a wave below N. STORIES SHARING A WAVE
|
|
90
|
+
HAVE NO ORDERING BETWEEN THEM and can be picked up in parallel — which is
|
|
91
|
+
why it is a wave and not an order or a priority. A rank would have to
|
|
92
|
+
invent a difference between two stories that genuinely have none, and the
|
|
93
|
+
fact that they are equal is the useful half.
|
|
94
|
+
|
|
95
|
+
It says when a story becomes ELIGIBLE, not when anyone should start it.
|
|
96
|
+
Nothing waits for a whole wave to finish: a story is startable the moment
|
|
97
|
+
its own dependencies are done, whatever else shares its wave. A story
|
|
98
|
+
raised by hand floors at 1 — nothing is KNOWN to come first.
|
|
99
|
+
|
|
100
|
+
designed_lanes Which lanes story-plan actually designed, e.g. [backend, frontend].
|
|
101
|
+
dropped_lanes Which lanes it DROPPED, and why the pair exists: a story with no UI
|
|
102
|
+
design either has no user-facing surface or had its UI lane dropped when
|
|
103
|
+
it was designed — an undeclared frontend lane, or a frontend-plan.md
|
|
104
|
+
missing or behind the spec — and one field cannot say which. Written by
|
|
105
|
+
story-plan (never by sync-stories: stories are not designed there);
|
|
106
|
+
designed accumulates across passes, dropped holds what has been dropped
|
|
107
|
+
and not since designed. Both absent on a story that predates them, which
|
|
108
|
+
implement-ui reports as exactly that rather than guessing.
|
|
65
109
|
|
|
66
110
|
follows On a follow-on only: the story id this one carries the remainder of.
|
|
67
|
-
When the spec moves under a story that already has a story
|
|
68
|
-
|
|
111
|
+
When the spec moves under a story that already has a story plan,
|
|
112
|
+
sync-stories leaves that story untouched and mints a follow-on
|
|
69
113
|
instead. There is no superseded status; the link is the whole record.
|
|
70
114
|
|
|
71
115
|
work_item Optional tracker id (JIRA-1234). The kit's id and the tracker's id stay
|
|
72
116
|
separate so the kit depends on no particular tracker.
|
|
73
117
|
|
|
74
118
|
CHANGE-STORY-ID IS LEGAL only while the story is open and stories/<ID>/ does not exist.
|
|
75
|
-
After story-
|
|
76
|
-
|
|
77
|
-
|
|
119
|
+
After story-plan runs, the id is in that directory's name, in the OKF log, in commit
|
|
120
|
+
messages and branch names — most of which the kit cannot rewrite. (The story plan's
|
|
121
|
+
TEXT never carries the id; its directory is its identity.)
|
|
78
122
|
|
|
79
123
|
stories.md beside this file is a GENERATED index. Never hand-edit it; it is rebuilt
|
|
80
124
|
from this directory, which is what keeps close-story conflict-free.
|
|
@@ -93,6 +137,33 @@ As a [role], I want [capability], so that [outcome].
|
|
|
93
137
|
|
|
94
138
|
- **[FR-00n]** — [the part of this requirement this story delivers]
|
|
95
139
|
|
|
140
|
+
## Constraints
|
|
141
|
+
|
|
142
|
+
<!-- The spec-level bounds this slice must satisfy, carried BY ID from spec.md and never
|
|
143
|
+
restated — the spec is the wording, this is the subset that binds this story:
|
|
144
|
+
|
|
145
|
+
CN- constraints & NFRs DC- data classification
|
|
146
|
+
IC- integration contracts UX- experience standards
|
|
147
|
+
|
|
148
|
+
Plus the Experience Scope floors (device / browser / assistive technology) wherever
|
|
149
|
+
this slice has a UI surface. UX- and the floors are what stop a story being built to
|
|
150
|
+
a standard the product does not hold, and they are the half most often lost: they
|
|
151
|
+
reach no UI phase except through the story.
|
|
152
|
+
|
|
153
|
+
THE IDS ARE STAMPED FOR YOU into `constraints:` above — the kit lifts every one the
|
|
154
|
+
spec declares, because spec constraints bind the aggregate rather than a single
|
|
155
|
+
operation. This section is where each gets its LINE. Write one per id saying what
|
|
156
|
+
this slice has to do about it, and where one genuinely does not apply, say so in its
|
|
157
|
+
line rather than dropping it: an omission used to be indistinguishable from a bound
|
|
158
|
+
nobody noticed, which is how a slice gets built without one.
|
|
159
|
+
|
|
160
|
+
These are NOT in `exercises:`. That field is FR-/BR- only, because it is the
|
|
161
|
+
delivery relation — what this story DELIVERS — and a constraint is not delivered,
|
|
162
|
+
it is met. story-plan carries these ids into its design pass; analyze-slice
|
|
163
|
+
traces it. -->
|
|
164
|
+
|
|
165
|
+
- **[UX-00n]** — [what this slice must satisfy of it]
|
|
166
|
+
|
|
96
167
|
## Acceptance
|
|
97
168
|
|
|
98
169
|
<!-- Checkable statements, in the spec's vocabulary. These are what analyze-slice pairs
|
|
@@ -104,4 +175,4 @@ As a [role], I want [capability], so that [outcome].
|
|
|
104
175
|
## Notes
|
|
105
176
|
|
|
106
177
|
<!-- Optional: sequencing, risks, what is deliberately out of this slice. Anything that
|
|
107
|
-
belongs to the CONTRACT belongs in spec.md via
|
|
178
|
+
belongs to the CONTRACT belongs in spec.md via sync-spec, not here. -->
|