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.
Files changed (32) hide show
  1. package/assets/.appweaver/STACK-PROFILES.md +1 -1
  2. package/assets/.appweaver/orchestrator/modules/spec-state-gate.orch.yaml +87 -0
  3. package/assets/.appweaver/orchestrator/orchestrator.py +5 -0
  4. package/assets/.appweaver/orchestrator/rev-templates/domain-rule-bindings.skeleton.md +10 -3
  5. package/assets/.appweaver/orchestrator/rev-templates/tech-rule-bindings.skeleton.md +38 -11
  6. package/assets/.appweaver/orchestrator/workflows/aw-spec-adopt.orch.yaml +2 -1
  7. package/assets/.appweaver/orchestrator/workflows/aw-spec-analyze-design.orch.yaml +672 -124
  8. package/assets/.appweaver/orchestrator/workflows/aw-spec-analyze-slice.orch.yaml +700 -72
  9. package/assets/.appweaver/orchestrator/workflows/aw-spec-implement-ui.orch.yaml +531 -135
  10. package/assets/.appweaver/orchestrator/workflows/aw-spec-implement.orch.yaml +573 -145
  11. package/assets/.appweaver/orchestrator/workflows/aw-spec-onboard.orch.yaml +78 -14
  12. package/assets/.appweaver/orchestrator/workflows/aw-spec-plan-ui.orch.yaml +600 -0
  13. package/assets/.appweaver/orchestrator/workflows/aw-spec-plan.orch.yaml +721 -0
  14. package/assets/.appweaver/orchestrator/workflows/aw-spec-select-feature.orch.yaml +3 -3
  15. package/assets/.appweaver/orchestrator/workflows/aw-spec-specify.orch.yaml +119 -32
  16. package/assets/.appweaver/orchestrator/workflows/aw-spec-story-plan.orch.yaml +1147 -0
  17. package/assets/.appweaver/orchestrator/workflows/aw-spec-sync-stories.orch.yaml +1121 -0
  18. package/assets/.appweaver/scripts/bash/aw-spec-actions.sh +2564 -38
  19. package/assets/.appweaver/scripts/bash/aw-xref.sh +2 -1
  20. package/assets/.appweaver/scripts/powershell/aw-spec-actions.ps1 +2458 -22
  21. package/assets/.appweaver/scripts/powershell/aw-xref.ps1 +2 -1
  22. package/assets/.appweaver/scripts/python/aw-payload-parity.py +158 -0
  23. package/assets/.appweaver/scripts/python/aw-xref.py +431 -48
  24. package/assets/.appweaver/templates/design-template.md +88 -54
  25. package/assets/.appweaver/templates/spec-template.md +12 -10
  26. package/assets/.appweaver/templates/story-template.md +83 -12
  27. package/assets/.appweaver/templates/ui-design-template.md +71 -39
  28. package/assets/guardrails/projects/dotnet-default-project/domain-rule-bindings.md +19 -7
  29. package/assets/guardrails/projects/dotnet-default-project/tech-rule-bindings.md +35 -26
  30. package/package.json +1 -1
  31. package/assets/.appweaver/orchestrator/workflows/aw-spec-design-ui.orch.yaml +0 -386
  32. 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]/design.md`
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 <!-- moves in lockstep with the spec; every applied change request bumps this — see Change History -->
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. It is the
17
- MEDIATOR between spec.md (WHAT/WHY, tech-agnostic) and the generated code
18
- (HOW, tech-specific). It is NOT code: it carries structure, contracts,
19
- behaviour, and decisions — enough for ANY capable LLM to generate correct,
20
- spec-satisfying code on ANY target stack, but no complete method bodies.
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 ──▶ design.md ──▶ code (+ tests)
23
- behaviour structure & generated by `implement`
24
- (FR/BR/US/SC) decisions (HLD) (stack-bound at generation time)
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-/US-/SC-) and
28
- the whole spec is covered DOWN here (see §6 Traceability). No design element
29
- without a spec reason; no spec requirement without a design home.
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
- - Feature = aggregate. Commands (CreateOrder, UpdateOrder…) are USER STORIES,
37
- not features. One aggregate = one design.md = one owning design for its code
38
- files. A later requirement is a delta on THIS doc, never a new one.
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 · US-Y |
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 · US-Y · BR-00Z
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 · US-Y
208
+ Serves: FR-00X
186
209
  ```
187
210
 
188
211
  ## 2. Application Layer
189
212
 
190
213
  <!--
191
- Use-cases: one command/query per user-story action, its handler's orchestration,
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 user-story action. This is the LLM's unit of work. -->
232
+ <!-- One block per use-case = one requirement action. This is the LLM's unit of work. -->
210
233
 
211
- #### `[Command/Query]` — Serves US-Y · FR-00X
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 API status in §3]
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 (REST assumed
235
- per the constitution — adapt for gRPC/GraphQL/CLI if the stack differs), NOT as
236
- controller code. Pin route, verb, auth, request/response shape, status codes, and
237
- the error contract. Delegates to an Application use-case; no business logic here.
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
- ### `[VERB] [/route]` — [purpose] · Serves US-Y · FR-00X
241
-
242
- - **Auth**: [required role/scope]
243
- - **Request**: `[path/query params]` + body `{ [field]: [type], … }`
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/US/SC has a design home, and every
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. Every applied change request
373
- appends a row here, carrying the version it ships as. finalize-delta writes the row
374
- when it merges the delta; close-delta then archives the CR, bumps the minor version
375
- in active_version.json and stamps that same number into this document's **Version**
376
- header — one mechanism, one stage, so header, row and active_version.json never
377
- disagree. A change to this aggregate is a DELTA on THIS document (delta-design:
378
- ADDED / MODIFIED / REMOVED sections), never a new design doc. Newest last.
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 | User stories | CR |
382
- |---------|------|--------|--------------|-----|
383
- | v1.0 | [DATE] | Initial design | US-1 | — |
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 + one design.md (specs/[Aggregate]/design.md)
19
- — the DESIGN derives from THIS document.
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 design.ui.md, and putting them here
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-design and ui-implement author from
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 design.ui.md's
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-design and the 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 update-stories; were it visible to the diff, adding a story would read as a
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 update-stories to raise the backlog)_ | | |
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. update-stories reads the rows to refresh the backlog;
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: update-stories and
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-spec has run: specs/<Feature>/stories/<Feature-NNN>/
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, update-spec folds it back through specify's
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
- analyze-story-design. Cross-feature ordering goes in depends_on, not in a second story.
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/. user-story refuses to write over an existing file, so a
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; check-stories
58
- reports it and update-stories acts on it. Restamped on every sync.
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-spec,
68
- update-stories leaves that story untouched and mints a follow-on
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-spec runs, the id is in that directory, in the story-spec and story-design,
76
- in the OKF log, in commit messages and branch names — most of which the kit cannot
77
- rewrite.
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 update-spec, not here. -->
178
+ belongs to the CONTRACT belongs in spec.md via sync-spec, not here. -->