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
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
#
|
|
4
4
|
# feature = AGGREGATE (e.g. Order). This is the FIRST step of the spec-anchored
|
|
5
5
|
# pipeline: it fixes the aggregate boundary BEFORE any spec/design exists, so the
|
|
6
|
-
# feature's single spec.md +
|
|
6
|
+
# feature's single spec.md + its per-lane plans and every command (CreateOrder/UpdateOrder =
|
|
7
7
|
# user stories) hang off one directory. It replaces guessing the aggregate out of prose in
|
|
8
8
|
# `specify` — that is why finding #1 (feature=aggregate) is enforced here, not hoped for.
|
|
9
9
|
#
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
# list-features (specs/ ∪ OKF aggregates) → user_select (existing | "+ create new") → [ask name] → set-feature
|
|
20
20
|
#
|
|
21
21
|
# Persists .appweaver/feature.json {"feature_directory":"specs/<Feature>"} so every
|
|
22
|
-
# later command operates on it: the forward loop (specify/
|
|
22
|
+
# later command operates on it: the forward loop (specify/plan/analyze-design/implement/
|
|
23
23
|
# build/analyze-slice/run/deploy) and the CR loop (analyze-delta-design/implement-delta/
|
|
24
24
|
# finalize-delta/close-delta — the standalone `cr` is retired; specify and design author
|
|
25
25
|
# the delta docs themselves).
|
|
@@ -124,5 +124,5 @@ outputs:
|
|
|
124
124
|
feature_dir: "{{feature_dir}}"
|
|
125
125
|
created: "{{created}}"
|
|
126
126
|
spec_exists: "{{spec_exists}}"
|
|
127
|
-
note: "Active feature set in .appweaver/feature.json — the aggregate boundary for its single spec.md
|
|
127
|
+
note: "Active feature set in .appweaver/feature.json — the aggregate boundary for its single spec.md and the per-lane plans derived from it (backend-plan.md / frontend-plan.md)."
|
|
128
128
|
next: "/appweaver specify <what this feature does> (authors {{feature_dir}}/spec.md; each operation = a user story)"
|
|
@@ -4,13 +4,14 @@
|
|
|
4
4
|
# Spec-anchored pipeline, spec phase. feature = AGGREGATE (picked/created by
|
|
5
5
|
# /appweaver select-feature, which sets .appweaver/feature.json). specify does
|
|
6
6
|
# NOT guess or create the feature — it CONSUMES the active one, and is phase-pure
|
|
7
|
-
# (spec side only; the
|
|
7
|
+
# (spec side only; the per-lane plans are the `plan` / `plan-ui` phases).
|
|
8
8
|
#
|
|
9
9
|
# specify writes ONE artifact: spec.md, plus the Change History row that records what
|
|
10
10
|
# it wrote. It does not touch stories/. The spec is the CONTRACT; a story is an
|
|
11
11
|
# execution SLICE over it, and the two directions between them each have their own
|
|
12
|
-
# workflow — /appweaver
|
|
13
|
-
# /appweaver
|
|
12
|
+
# workflow — /appweaver sync-stories refreshes the backlog after the spec moves,
|
|
13
|
+
# /appweaver sync-spec (⌛ not yet built — .appweaver/SPEC-EDIT-PROTOCOL.md is the hand
|
|
14
|
+
# route meanwhile) folds a hand-edited story back into the contract. Keeping
|
|
14
15
|
# specify story-blind is what stops the spec->story rule having two implementations.
|
|
15
16
|
#
|
|
16
17
|
# Auto-detects first-vs-subsequent from spec.md:
|
|
@@ -32,7 +33,7 @@
|
|
|
32
33
|
# bootstrap diffs the finished document against nothing, which yields every id it
|
|
33
34
|
# carries and is exactly the v1.0 row's content. A row the model declared could omit a
|
|
34
35
|
# requirement the quality loop rewrote on its way past, and an omitted id is silent —
|
|
35
|
-
#
|
|
36
|
+
# sync-stories would never learn it moved.
|
|
36
37
|
# 2. The row and the hash are written by ONE call (ledger-append), so a row can never
|
|
37
38
|
# exist without the hash that proves the body it describes.
|
|
38
39
|
# 3. The ledger is checked on ENTRY, not only stamped on exit. A spec hand-edited with
|
|
@@ -42,11 +43,11 @@
|
|
|
42
43
|
# Launch: /appweaver specify [strategy] <what the feature needs, or what changes>
|
|
43
44
|
# e.g. /appweaver specify Customers place an order for one or more items
|
|
44
45
|
# Prereq: /appweaver select-feature (sets the active aggregate)
|
|
45
|
-
# Next: /appweaver
|
|
46
|
+
# Next: /appweaver sync-stories (turns the new/changed requirements into stories)
|
|
46
47
|
# =============================================================================
|
|
47
48
|
|
|
48
49
|
name: aw-spec-specify
|
|
49
|
-
description: Author or extend the specification of the ACTIVE feature (aggregate). The first call writes spec.md from the template; a later call edits spec.md in place, adding the requirements the input describes and amending the ones it changes. Both paths run the checklist/clarify/validate converge loop over spec.md. An extend appends a Change History row whose requirement ids are COMPUTED from a before/after diff, and re-baselines the ledger hash. Writes no stories — /appweaver
|
|
50
|
+
description: Author or extend the specification of the ACTIVE feature (aggregate). The first call writes spec.md from the template; a later call edits spec.md in place, adding the requirements the input describes and amending the ones it changes. Both paths run the checklist/clarify/validate converge loop over spec.md. An extend appends a Change History row whose requirement ids are COMPUTED from a before/after diff, and re-baselines the ledger hash. Writes no stories — /appweaver sync-stories owns the backlog. Spec phase only; design is separate.
|
|
50
51
|
version: 3.4.0
|
|
51
52
|
agent_agnostic: true
|
|
52
53
|
dialect: aw-spec.orchestrator/v1
|
|
@@ -101,7 +102,7 @@ vars:
|
|
|
101
102
|
disturbed_csv: "" # which of them
|
|
102
103
|
disturbed_ids: "" # the same, as a list — the options of the per-requirement ask
|
|
103
104
|
disturbed_stories: "" # the open stories citing those ids
|
|
104
|
-
disturbed_flying: "" # the subset already past story-
|
|
105
|
+
disturbed_flying: "" # the subset already past story-plan — a follow-on, not an edit
|
|
105
106
|
may_change: "" # the requirements the author approved for amendment
|
|
106
107
|
approved_csv: "" # the same, normalised
|
|
107
108
|
preserve_csv: "" # disturbed minus approved — restored and re-expressed additively
|
|
@@ -239,7 +240,7 @@ workflow:
|
|
|
239
240
|
story, never an "As a … I want …" block, never a Given/When/Then acceptance
|
|
240
241
|
scenario, and never a section for any of those. A story is an execution slice
|
|
241
242
|
that lives beside this file in stories/ and cites the ids below; it is written
|
|
242
|
-
by /appweaver
|
|
243
|
+
by /appweaver sync-stories, not here. Design and code trace to the ids in
|
|
243
244
|
this document, which is what lets the backlog churn without disturbing them.
|
|
244
245
|
- SPECIFY IS THE ONLY PHASE THAT READS THE DOMAIN RULES. Design and implement
|
|
245
246
|
work from the spec/design, never the domain docs — so this spec is the SOLE
|
|
@@ -291,7 +292,7 @@ workflow:
|
|
|
291
292
|
read this section — so a bound the SERVICE must meet stays a CN-, cross-referenced.
|
|
292
293
|
HIGH-LEVEL ONLY, and this is the rule that matters most: every entry is a standard
|
|
293
294
|
the whole product holds to, checkable on ANY surface. NEVER a screen, page, layout,
|
|
294
|
-
navigation model, component or visual-design choice — the prototype and
|
|
295
|
+
navigation model, component or visual-design choice — the prototype and frontend-plan.md
|
|
295
296
|
settle those, and an entry satisfiable only one way is a design decision smuggled
|
|
296
297
|
into the spec. A per-feature interaction BEHAVIOUR stays an EARS FR-n; only the
|
|
297
298
|
standard that governs every such behaviour is a UX-n.
|
|
@@ -301,7 +302,7 @@ workflow:
|
|
|
301
302
|
"Requirements changed" cell as the template has them. The kit rewrites that row
|
|
302
303
|
from the finished document, so ids listed here are discarded — the same rule that
|
|
303
304
|
makes every later version row an observation rather than a claim. Leave its Stories cell as "—";
|
|
304
|
-
|
|
305
|
+
sync-stories fills that in when it raises the backlog.
|
|
305
306
|
- LEAVE THE "## Story Coverage" BLOCK ALONE, placeholder row and all. Everything
|
|
306
307
|
between the AW:COVERAGE markers is generated from the stories/ directory after
|
|
307
308
|
this step; anything written there by hand is discarded at the next write.
|
|
@@ -328,7 +329,7 @@ workflow:
|
|
|
328
329
|
#
|
|
329
330
|
# unledgered_edit spec.md was hand-edited and no Change History row was added.
|
|
330
331
|
# Appending this run's row would bump the version past that edit
|
|
331
|
-
# without ever naming its ids, so
|
|
332
|
+
# without ever naming its ids, so sync-stories could not
|
|
332
333
|
# reconcile it and every story citing it stays silently stale.
|
|
333
334
|
# delta_open a change is open AND its delta-spec has been authored, so a delta
|
|
334
335
|
# is measured against this master. Temporary — the guard retires with
|
|
@@ -392,6 +393,12 @@ workflow:
|
|
|
392
393
|
# nothing. Fed to the author as a preference, then checked against the diff below —
|
|
393
394
|
# the preference is a nudge, the check after the fact is the detector.
|
|
394
395
|
# Empty until the backlog exists, which degrades to "no preference, no ask".
|
|
396
|
+
# CARRIED, NOT COVERED. `covered_csv` is the DELIVERY relation — the FR-/BR- ids open
|
|
397
|
+
# stories are delivering — and a story also CARRIES the bounds it is built to satisfy.
|
|
398
|
+
# Amending or removing a CN-/DC-/IC-/UX- moves ground somebody is standing on exactly
|
|
399
|
+
# as amending an FR- does, and reading the narrower set here meant it raised no ask at
|
|
400
|
+
# all and printed "nobody has open work" while stories were being built against it.
|
|
401
|
+
# `carried_csv` is exercises: ∪ the `constraints:` frontmatter story-stamp lifts.
|
|
395
402
|
- id: ext_story_context
|
|
396
403
|
condition: "{{needs_bootstrap}} == false"
|
|
397
404
|
action: execute_script
|
|
@@ -401,18 +408,21 @@ workflow:
|
|
|
401
408
|
args: ["--feature-dir", "{{feature_dir}}"]
|
|
402
409
|
outputs:
|
|
403
410
|
- { name: covered_csv, from: "$.covered_csv" }
|
|
411
|
+
- { name: carried_csv, from: "$.carried_csv" }
|
|
412
|
+
- { name: backlog_scanned, from: "$.ok" }
|
|
404
413
|
|
|
405
414
|
# 6b-bis. WORD THE PREFERENCE FOR THE CASE AT HAND. The rule below is an argument for
|
|
406
415
|
# preferring an ADDITION over an amendment, and it only makes sense while somebody is
|
|
407
|
-
# actually building. Interpolating
|
|
416
|
+
# actually building. Interpolating the carried set straight into it left a spec with no
|
|
408
417
|
# backlog reading an eight-line case for adding requirements under a blank list — the
|
|
409
418
|
# logic was vacuous ("one of those" names nothing) but the rhetoric was not, and the
|
|
410
419
|
# first extend of a spec nobody has stories against is exactly where amending in place
|
|
411
|
-
# is the honest thing to do.
|
|
412
|
-
# same idiom as readdit_verdict_na/_real: the no-backlog wording is the default,
|
|
413
|
-
#
|
|
414
|
-
#
|
|
415
|
-
#
|
|
420
|
+
# is the honest thing to do. THREE ORDERED SETS rather than a compound condition, the
|
|
421
|
+
# same idiom as readdit_verdict_na/_real: the no-backlog wording is the default, the
|
|
422
|
+
# preference replaces it where there is open work to protect, and the scan-failed
|
|
423
|
+
# wording is last so it wins over both.
|
|
424
|
+
# Safe on the bootstrap path too — ext_story_context is skipped there, so nothing is
|
|
425
|
+
# bound and only the default can fire.
|
|
416
426
|
- id: ext_covered_none
|
|
417
427
|
action: set
|
|
418
428
|
vars:
|
|
@@ -424,11 +434,13 @@ workflow:
|
|
|
424
434
|
without inventing a companion requirement to avoid touching anything.
|
|
425
435
|
|
|
426
436
|
- id: ext_covered_some
|
|
427
|
-
condition: "{{
|
|
437
|
+
condition: "{{carried_csv}} != ''"
|
|
428
438
|
action: set
|
|
429
439
|
vars:
|
|
430
440
|
covered_note: >
|
|
431
|
-
THESE REQUIREMENTS ARE BEING BUILT RIGHT NOW: {{
|
|
441
|
+
THESE REQUIREMENTS AND BOUNDS ARE BEING BUILT AGAINST RIGHT NOW: {{carried_csv}}.
|
|
442
|
+
(FR-/BR- are what open stories DELIVER; CN-/DC-/IC-/UX- are what they are built to
|
|
443
|
+
MEET — moving either moves ground someone is standing on.) Where the change can
|
|
432
444
|
be expressed EITHER as an amendment to one of those or as a new requirement
|
|
433
445
|
alongside it, prefer the new requirement — an amendment moves ground someone is
|
|
434
446
|
standing on, and a requirement that gains a companion leaves their work correct as
|
|
@@ -438,6 +450,21 @@ workflow:
|
|
|
438
450
|
Requirements NOT in that list have no open work against them: amend those in place
|
|
439
451
|
wherever the change genuinely belongs to them.
|
|
440
452
|
|
|
453
|
+
# THE SCAN ITSELF CAN FAIL, and ext_story_context carries `on_error: continue` because a
|
|
454
|
+
# spec must stay editable when its backlog cannot be read. What it must not do is answer
|
|
455
|
+
# as though the scan had run and found nothing: nothing binds, ext_covered_some cannot
|
|
456
|
+
# fire, and the unconditional default above then tells the author NOBODY HAS OPEN WORK —
|
|
457
|
+
# the strongest claim available, on no evidence at all.
|
|
458
|
+
- id: ext_covered_unknown
|
|
459
|
+
condition: "{{backlog_scanned}} != true"
|
|
460
|
+
action: set
|
|
461
|
+
vars:
|
|
462
|
+
covered_note: >
|
|
463
|
+
THE BACKLOG COULD NOT BE READ THIS RUN, so this run does not know who is building
|
|
464
|
+
what. Treat every requirement as possibly under way: prefer adding a requirement to
|
|
465
|
+
amending one, and where you must amend, say in the Change History row exactly what
|
|
466
|
+
moved so the next sync can find every story that carries it.
|
|
467
|
+
|
|
441
468
|
- id: ext_ctx
|
|
442
469
|
condition: "{{needs_bootstrap}} == false"
|
|
443
470
|
action: build_context
|
|
@@ -474,7 +501,7 @@ workflow:
|
|
|
474
501
|
- {{covered_note}}
|
|
475
502
|
- THIS DOCUMENT HOLDS NO USER STORIES. Do not add an "As a … I want …" block, a
|
|
476
503
|
Given/When/Then acceptance scenario, or a section for either. Stories live in
|
|
477
|
-
stories/ beside this file and are written by /appweaver
|
|
504
|
+
stories/ beside this file and are written by /appweaver sync-stories.
|
|
478
505
|
- DO NOT TOUCH the "**Version**" header or the "## Change History" table, and leave everything between the AW:COVERAGE markers exactly as it is. Both are
|
|
479
506
|
written by the kit after this step, from a diff of what you actually changed —
|
|
480
507
|
editing them here produces a duplicate row and a version nothing agrees on.
|
|
@@ -651,7 +678,7 @@ workflow:
|
|
|
651
678
|
# Asked, not decided, and RECORD IS FIRST on purpose. spec.md is already written by this
|
|
652
679
|
# point: a run that refuses the ledger row leaves a document with no row, which is the
|
|
653
680
|
# `unledgered_edit` state the next run refuses outright. Recording a red spec is honest
|
|
654
|
-
# and recoverable — the row names what moved, so
|
|
681
|
+
# and recoverable — the row names what moved, so sync-stories still works, and the
|
|
655
682
|
# failures are in the checklist file. Stopping is the safer-feeling option that costs
|
|
656
683
|
# more, so the prompt says what it costs and how to undo it.
|
|
657
684
|
- id: quality_ask
|
|
@@ -691,7 +718,7 @@ workflow:
|
|
|
691
718
|
# diff for the reason this file opens with: a row the model DECLARED can omit an id it
|
|
692
719
|
# moved, and an omitted id is silent. v1.0 was the one exception — written by the
|
|
693
720
|
# author from a template whose placeholder reads "FR-001…FR-00n", so nothing
|
|
694
|
-
# downstream could trust it and
|
|
721
|
+
# downstream could trust it and sync-stories had to be told to enumerate from the
|
|
695
722
|
# document instead. Diffing against no snapshot yields every id the finished spec
|
|
696
723
|
# carries, which is exactly the v1.0 row's content, so the first row is now derived
|
|
697
724
|
# the same way as the rest and the special case downstream goes away.
|
|
@@ -755,6 +782,26 @@ workflow:
|
|
|
755
782
|
- { name: disturbing_csv, from: "$.disturbing_csv" }
|
|
756
783
|
- { name: reissued_csv, from: "$.reissued_csv" }
|
|
757
784
|
- { name: change_count, from: "$.change_count" }
|
|
785
|
+
- { name: diff_warnings, from: "$.warnings_note" }
|
|
786
|
+
|
|
787
|
+
# 10a-bis. IDS THE LEDGER CANNOT KEY TO A DEFINITION. The diff keys an id to the line that
|
|
788
|
+
# DEFINES it and hashes the block under it; three authoring forms fall outside that,
|
|
789
|
+
# and each one is silent — the requirement moves, change_count stays 0, no row is
|
|
790
|
+
# appended, and the stamp below re-baselines the new body as clean. A standing
|
|
791
|
+
# property of the document rather than a verdict on this run, so it is reported every
|
|
792
|
+
# time until the requirement is rewritten in the shape the template uses.
|
|
793
|
+
- id: diff_warning_notice
|
|
794
|
+
condition: "{{diff_warnings}} != ''"
|
|
795
|
+
action: verify_context
|
|
796
|
+
require_value: diff_warnings
|
|
797
|
+
equals: ""
|
|
798
|
+
on_mismatch: continue
|
|
799
|
+
on_mismatch_message: >
|
|
800
|
+
THE LEDGER CANNOT SEE PART OF THIS SPEC. {{spec_file}} states requirements in a form
|
|
801
|
+
the version diff cannot key to a definition, so an edit to one of them raises no
|
|
802
|
+
Change History row and no story citing it is ever told: {{diff_warnings}}. Rewrite them
|
|
803
|
+
in the template's shape — `- **FR-001**: …`, defined ABOVE the Change History table,
|
|
804
|
+
with any continuation on the lines directly under the id and no blank line between.
|
|
758
805
|
|
|
759
806
|
# 10b. DID THIS MOVE GROUND SOMEONE IS STANDING ON? The diff is fact, so this is the
|
|
760
807
|
# detector the pre-authoring preference lacked: of the requirements this run
|
|
@@ -784,7 +831,7 @@ workflow:
|
|
|
784
831
|
# two outcomes differ sharply for the people downstream —
|
|
785
832
|
#
|
|
786
833
|
# amend the contract moves. Every open story citing it goes stale, and
|
|
787
|
-
#
|
|
834
|
+
# sync-stories reconciles them: edited in place if no story plan
|
|
788
835
|
# exists yet, carried by a follow-on if one does (§5.5).
|
|
789
836
|
# add the amended requirements go back to how they read, and the change is
|
|
790
837
|
# expressed as new requirements alongside them. Nobody's work goes
|
|
@@ -803,10 +850,10 @@ workflow:
|
|
|
803
850
|
This change MODIFIED or REMOVED requirements that people have open stories against.
|
|
804
851
|
Requirements: {{disturbed_csv}}
|
|
805
852
|
Open stories: {{disturbed_stories}}
|
|
806
|
-
Already in flight (story
|
|
853
|
+
Already in flight (story plan exists): {{disturbed_flying}}
|
|
807
854
|
Pick the ones this change MAY alter. Each one you pick moves the contract: its open
|
|
808
|
-
stories go stale, and
|
|
809
|
-
minting a follow-on where a story
|
|
855
|
+
stories go stale, and sync-stories reconciles them — editing a story in place, or
|
|
856
|
+
minting a follow-on where a story plan already exists. Each one you LEAVE OUT is put
|
|
810
857
|
back exactly as it read, and the change it was carrying is expressed as a new
|
|
811
858
|
requirement alongside it, so the work already under way stays correct.
|
|
812
859
|
Which may be changed?
|
|
@@ -1024,7 +1071,7 @@ workflow:
|
|
|
1024
1071
|
# It announces rather than stops. spec.md is already written by this point, so a stop
|
|
1025
1072
|
# here leaves a document on disk with no ledger row, which is the state the next run's
|
|
1026
1073
|
# tripwire refuses. Announcing keeps the ledger row honest — the violated ids ARE in
|
|
1027
|
-
# it, so
|
|
1074
|
+
# it, so sync-stories still reconciles their stories — and moves them out of the
|
|
1028
1075
|
# "preserved" column of the report into a column that says what actually happened.
|
|
1029
1076
|
- id: ext_restore_check
|
|
1030
1077
|
condition: "{{preserve_count}} != 0"
|
|
@@ -1045,7 +1092,7 @@ workflow:
|
|
|
1045
1092
|
on_false_message: >
|
|
1046
1093
|
The re-authoring did NOT restore {{violated_csv}} — you declined to change these and
|
|
1047
1094
|
they moved anyway. They are recorded in this version's Change History row, so
|
|
1048
|
-
/appweaver
|
|
1095
|
+
/appweaver sync-stories will reconcile the stories citing them rather than leaving
|
|
1049
1096
|
them silently stale; check that the wording it landed on is one you can live with.
|
|
1050
1097
|
|
|
1051
1098
|
# 10h. Re-read the affected stories from the FINAL document. After a restore, the
|
|
@@ -1065,6 +1112,23 @@ workflow:
|
|
|
1065
1112
|
args: ["--feature-dir", "{{feature_dir}}", "--ids", "{{disturbing_csv}}"]
|
|
1066
1113
|
outputs:
|
|
1067
1114
|
- { name: disturbed_stories, from: "$.story_csv" }
|
|
1115
|
+
- { name: final_refs_ok, from: "$.ok" }
|
|
1116
|
+
|
|
1117
|
+
# 10h-bis. THE SAME HONESTY THE PRE-AUTHORING SCAN NOW HAS. This step carries
|
|
1118
|
+
# `on_error: continue` so a failed re-scan cannot strand a written document, and on
|
|
1119
|
+
# failure disturbed_stories binds to nothing — which the post-restore report (law 45)
|
|
1120
|
+
# then reads as "nobody was disturbed", the one claim it must not make on no evidence.
|
|
1121
|
+
- id: final_refs_unknown_notice
|
|
1122
|
+
condition: "{{final_refs_ok}} != true"
|
|
1123
|
+
action: verify_context
|
|
1124
|
+
require_value: final_refs_ok
|
|
1125
|
+
equals: "true"
|
|
1126
|
+
on_mismatch: continue
|
|
1127
|
+
on_mismatch_message: >
|
|
1128
|
+
The final backlog re-scan did not complete, so the disturbed-stories list below is
|
|
1129
|
+
NOT a list of nobody — it is unknown. The requirements this run moved are
|
|
1130
|
+
{{disturbing_csv}}; run /appweaver sync-stories to find and reconcile the stories
|
|
1131
|
+
carrying them.
|
|
1068
1132
|
|
|
1069
1133
|
# 10i. AN ID THE LEDGER HAS ALREADY SPENT. Ids are permanent: re-issuing a retired one
|
|
1070
1134
|
# silently re-points stories, designs and code that have already shipped, which is
|
|
@@ -1087,7 +1151,7 @@ workflow:
|
|
|
1087
1151
|
# 11. One call writes the row, bumps the version, stamps the header and re-hashes, so
|
|
1088
1152
|
# a row cannot exist without the hash that proves the body it describes. Skipped
|
|
1089
1153
|
# when the run changed no requirement — a version that names no ids is a bump
|
|
1090
|
-
#
|
|
1154
|
+
# sync-stories can do nothing with.
|
|
1091
1155
|
- id: ext_ledger_append
|
|
1092
1156
|
condition: "{{change_count}} != 0"
|
|
1093
1157
|
action: execute_script
|
|
@@ -1097,6 +1161,29 @@ workflow:
|
|
|
1097
1161
|
outputs:
|
|
1098
1162
|
- { name: ledger_version, from: "$.version" }
|
|
1099
1163
|
|
|
1164
|
+
# 11a-bis. A PROSE-ONLY EDIT RE-BASELINES WITH NO ROW, AND SAYS SO. ledger-append is
|
|
1165
|
+
# conditional on change_count, because law 5 requires a version row to NAME at least
|
|
1166
|
+
# one id and an edit that touched no requirement has none to give. The stamp below is
|
|
1167
|
+
# not conditional, so this run rewrites the baseline and the document's own history
|
|
1168
|
+
# records nothing — which is right, and was silent. Aggregate Boundary, Experience
|
|
1169
|
+
# Scope and the rest of the load-bearing prose are read by every later phase and have
|
|
1170
|
+
# no staleness signal of their own; the least this can do is say that the baseline
|
|
1171
|
+
# moved and nothing recorded why.
|
|
1172
|
+
- id: prose_only_notice
|
|
1173
|
+
condition: "{{change_count}} == 0"
|
|
1174
|
+
action: verify_context
|
|
1175
|
+
require_value: needs_bootstrap
|
|
1176
|
+
equals: "true"
|
|
1177
|
+
on_mismatch: continue
|
|
1178
|
+
on_mismatch_message: >
|
|
1179
|
+
This run changed {{spec_file}} but moved no requirement: the diff found no id added,
|
|
1180
|
+
modified or removed, so no Change History row was appended — a row must name at least
|
|
1181
|
+
one id, and there is none to name. The document is still RE-BASELINED below, so the
|
|
1182
|
+
next run reads it as clean. Nothing else is: if the edit touched load-bearing prose
|
|
1183
|
+
(Aggregate Boundary, Experience Scope, Scope & Assumptions), no story is stale, no
|
|
1184
|
+
sync will notice, and the only record is this message and your commit. Say what moved
|
|
1185
|
+
in the commit message.
|
|
1186
|
+
|
|
1100
1187
|
# ═══════════════ STORY COVERAGE — both paths, before the baseline ══════════
|
|
1101
1188
|
# 11b. Rewrite the spec's AW:COVERAGE block: every FR-/BR- in the document and the
|
|
1102
1189
|
# stories delivering it, read out of the stories/ frontmatter. The relation is
|
|
@@ -1105,7 +1192,7 @@ workflow:
|
|
|
1105
1192
|
#
|
|
1106
1193
|
# Deliberately OUTSIDE the ledger. The hash guards the CONTRACT, and coverage is a
|
|
1107
1194
|
# projection of the backlog — spec-check, spec-diff and ledger-append all cut this
|
|
1108
|
-
# block out before they look. That is what lets
|
|
1195
|
+
# block out before they look. That is what lets add-story and sync-stories write
|
|
1109
1196
|
# it too without a story creation reading as an unledgered spec edit, or a story
|
|
1110
1197
|
# raised against FR-003 reading as FR-003 having changed.
|
|
1111
1198
|
#
|
|
@@ -1172,7 +1259,7 @@ outputs:
|
|
|
1172
1259
|
spec_file: "{{spec_file}}"
|
|
1173
1260
|
version: "{{version}}"
|
|
1174
1261
|
requirements_changed: "{{changed_csv}}" # every class — what the ledger row records
|
|
1175
|
-
requirements_for_stories: "{{story_ids_csv}}" # the FR-/BR- subset — what
|
|
1262
|
+
requirements_for_stories: "{{story_ids_csv}}" # the FR-/BR- subset — what sync-stories acts on
|
|
1176
1263
|
requirements_removed: "{{removed_csv}}"
|
|
1177
1264
|
requirements_amended: "{{modified_csv}}" # what finally stands amended, ask or no ask
|
|
1178
1265
|
requirements_preserved: "{{held_csv}}" # the ones the restore actually put back
|
|
@@ -1183,4 +1270,4 @@ outputs:
|
|
|
1183
1270
|
stories_disturbed: "{{disturbed_stories}}"
|
|
1184
1271
|
checklist_file: "{{checklist_file}}"
|
|
1185
1272
|
checklist_quality: "{{checklist_passed}}/{{checklist_total}} items passing"
|
|
1186
|
-
next: "spec.md is at {{version}}. Run /appweaver
|
|
1273
|
+
next: "spec.md is at {{version}}. Run /appweaver sync-stories — it raises or refreshes the backlog for the requirements this run touched that a story can cite ({{story_ids_csv}}), and nothing else keeps the contract and its stories in step. That is the FR-/BR- subset of requirements_changed on purpose: the ledger row records every class this run moved, but only these are slices of work. Then /appweaver plan authors or conforms backend-plan.md to this spec version, and names the /appweaver plan-ui follow-up when a frontend lane is declared. READ THE FIELDS ABOVE BEFORE YOU DO: requirements_removed orphans every story citing them and needs deciding by hand; requirements_not_restored moved despite you declining them; requirements_reissued point at something other than what cited them before; open_change will be merged into this document by finalize-delta; and checklist_quality is what the spec actually scored."
|