aw-spec-cli 0.1.16 → 0.1.17
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/DESIGN-FORMAT.md +18 -18
- package/assets/.appweaver/ORCH-DIALECT.md +1 -3
- package/assets/.appweaver/RULE-PARTITION.md +29 -13
- package/assets/.appweaver/STACK-PROFILES.md +10 -9
- package/assets/.appweaver/orchestrator/.state/smoke.state.json +32 -0
- package/assets/.appweaver/orchestrator/AGENT-PROFILE.md +4 -1
- package/assets/.appweaver/orchestrator/modules/delta-plan.orch.yaml +251 -0
- package/assets/.appweaver/orchestrator/modules/delta-spec.orch.yaml +104 -35
- package/assets/.appweaver/orchestrator/orchestrator.py +5 -4
- package/assets/.appweaver/orchestrator/rev-templates/delta-design-template.skeleton.md +94 -36
- package/assets/.appweaver/orchestrator/rev-templates/design-template.skeleton.md +1 -1
- package/assets/.appweaver/orchestrator/rev-templates/domain-model-template.skeleton.md +115 -0
- package/assets/.appweaver/orchestrator/rev-templates/domain-rule-bindings.skeleton.md +2 -9
- package/assets/.appweaver/orchestrator/rev-templates/tech-rule-bindings.skeleton.md +16 -40
- package/assets/.appweaver/orchestrator/rev-templates/ui-delta-design-template.skeleton.md +38 -17
- package/assets/.appweaver/orchestrator/rev-templates/ui-design-template.skeleton.md +8 -8
- package/assets/.appweaver/orchestrator/workflows/aw-spec-adopt.orch.yaml +10 -11
- package/assets/.appweaver/orchestrator/workflows/aw-spec-analyze-plan-delta.orch.yaml +673 -0
- package/assets/.appweaver/orchestrator/workflows/aw-spec-analyze-plan.orch.yaml +535 -0
- package/assets/.appweaver/orchestrator/workflows/aw-spec-analyze-slice-delta.orch.yaml +643 -0
- package/assets/.appweaver/orchestrator/workflows/aw-spec-analyze-slice.orch.yaml +84 -701
- package/assets/.appweaver/orchestrator/workflows/aw-spec-build.orch.yaml +4 -4
- package/assets/.appweaver/orchestrator/workflows/aw-spec-characterize.orch.yaml +7 -7
- package/assets/.appweaver/orchestrator/workflows/aw-spec-close-delta.orch.yaml +16 -14
- package/assets/.appweaver/orchestrator/workflows/aw-spec-constitution.orch.yaml +2 -2
- package/assets/.appweaver/orchestrator/workflows/aw-spec-finalize-delta.orch.yaml +243 -144
- package/assets/.appweaver/orchestrator/workflows/aw-spec-implement.orch.yaml +877 -578
- package/assets/.appweaver/orchestrator/workflows/aw-spec-inventory.orch.yaml +4 -4
- package/assets/.appweaver/orchestrator/workflows/aw-spec-onboard.orch.yaml +32 -91
- package/assets/.appweaver/orchestrator/workflows/aw-spec-parity.orch.yaml +2 -2
- package/assets/.appweaver/orchestrator/workflows/aw-spec-plan.orch.yaml +836 -514
- package/assets/.appweaver/orchestrator/workflows/aw-spec-run.orch.yaml +2 -2
- package/assets/.appweaver/orchestrator/workflows/aw-spec-select-bounded-context.orch.yaml +132 -0
- package/assets/.appweaver/orchestrator/workflows/aw-spec-select-feature.orch.yaml +38 -5
- package/assets/.appweaver/orchestrator/workflows/aw-spec-select-stack.orch.yaml +3 -3
- package/assets/.appweaver/orchestrator/workflows/aw-spec-specify.orch.yaml +271 -979
- package/assets/.appweaver/scripts/bash/aw-spec-actions.sh +1085 -3385
- package/assets/.appweaver/scripts/bash/aw-xref.sh +1 -2
- package/assets/.appweaver/scripts/bash/common.sh +47 -0
- package/assets/.appweaver/scripts/powershell/aw-spec-actions.ps1 +914 -3220
- package/assets/.appweaver/scripts/powershell/aw-xref.ps1 +1 -2
- package/assets/.appweaver/scripts/python/aw-payload-parity.py +19 -3
- package/assets/.appweaver/scripts/python/aw-stack.py +6 -2
- package/assets/.appweaver/scripts/python/aw-xref.py +86 -350
- package/assets/.appweaver/templates/constitution-ui-template.md +1 -1
- package/assets/.appweaver/templates/delta-design-template.md +120 -30
- package/assets/.appweaver/templates/delta-domain-model-template.md +81 -0
- package/assets/.appweaver/templates/delta-spec-template.md +43 -17
- package/assets/.appweaver/templates/design-template.md +68 -98
- package/assets/.appweaver/templates/domain-model-template.md +130 -0
- package/assets/.appweaver/templates/okf-concept-template.md +2 -2
- package/assets/.appweaver/templates/source-map-template.md +3 -3
- package/assets/.appweaver/templates/spec-template.md +100 -122
- package/assets/.appweaver/templates/ui-delta-design-template.md +159 -0
- package/assets/.appweaver/templates/ui-design-template.md +46 -75
- package/assets/guardrails/projects/dotnet-default-project/domain-rule-bindings.md +7 -18
- package/assets/guardrails/projects/dotnet-default-project/tech-rule-bindings.md +34 -39
- package/assets/guardrails/requirement-spec.txt +2 -2
- package/assets/guardrails/technology/dotnet-webapi/testing.md +1 -1
- package/package.json +1 -1
- package/assets/.appweaver/orchestrator/modules/delta-design.orch.yaml +0 -105
- package/assets/.appweaver/orchestrator/modules/spec-state-gate.orch.yaml +0 -87
- package/assets/.appweaver/orchestrator/workflows/aw-spec-analyze-delta-design.orch.yaml +0 -251
- package/assets/.appweaver/orchestrator/workflows/aw-spec-analyze-design.orch.yaml +0 -813
- package/assets/.appweaver/orchestrator/workflows/aw-spec-implement-delta.orch.yaml +0 -253
- package/assets/.appweaver/orchestrator/workflows/aw-spec-implement-ui.orch.yaml +0 -663
- package/assets/.appweaver/orchestrator/workflows/aw-spec-plan-ui.orch.yaml +0 -600
- package/assets/.appweaver/orchestrator/workflows/aw-spec-story-plan.orch.yaml +0 -1147
- package/assets/.appweaver/orchestrator/workflows/aw-spec-sync-stories.orch.yaml +0 -1121
- package/assets/.appweaver/templates/story-template.md +0 -178
|
@@ -1,84 +1,52 @@
|
|
|
1
1
|
# =============================================================================
|
|
2
|
-
# aw-spec-analyze-slice (orchestrator) — the
|
|
2
|
+
# aw-spec-analyze-slice (orchestrator) — the design↔code conformance GATE
|
|
3
3
|
#
|
|
4
4
|
# The second of the two discrete conformance gates on the forward path, and the
|
|
5
|
-
# sibling of analyze-
|
|
6
|
-
# analyze-
|
|
7
|
-
# analyze-slice gates
|
|
8
|
-
#
|
|
9
|
-
#
|
|
10
|
-
# against the design, which only ever proved that two documents agreed with each
|
|
11
|
-
# other. The contract is spec.md — its FR-/BR- wording, and the CN-/DC-/IC-/UX- a
|
|
12
|
-
# slice is bound by — and this is the stage that asks whether the code delivers it.
|
|
13
|
-
# The design is how the question is ANSWERABLE: the story's design pass names which
|
|
14
|
-
# elements realise which id, and the feature plan says where those elements live in
|
|
15
|
-
# the architecture. Trace runs spec id → design element → code, and a break at either
|
|
16
|
-
# hop is a different finding with a different route:
|
|
17
|
-
# the code does not deliver an id the design maps → the code is wrong (implement)
|
|
18
|
-
# no design maps an in-scope id at all → the BRIDGE is broken (story-plan)
|
|
19
|
-
# the code is right and the spec words it wrongly → the spec is wrong (sync-spec)
|
|
20
|
-
# The bridge's own integrity is REPORTED, never gated: a documented gap in a design
|
|
21
|
-
# does not make working code fail its contract.
|
|
22
|
-
#
|
|
23
|
-
# SCOPED TO A STORY WHEN ONE IS NAMED. `/appweaver analyze-slice Order-002` judges that
|
|
24
|
-
# story's ids; with no story named the whole feature is judged, MINUS every id that has
|
|
25
|
-
# an open story, because in-flight work is not drift (law 39). And a story narrows the
|
|
26
|
-
# QUESTION, not the file set: the code under analysis is always the slice's whole OKF
|
|
27
|
-
# file list, both lanes, because a requirement can only be judged against everything
|
|
28
|
-
# that could realise it.
|
|
29
|
-
#
|
|
30
|
-
# THE SPEC IS THE WORDING; THE STORY IS THE EXTENT. A story rarely delivers a whole
|
|
31
|
-
# requirement — its "## Requirements delivered" section says which part — so a
|
|
32
|
-
# story-scoped run judges the code against the spec's wording of that part alone. A
|
|
33
|
-
# slice is never failed for the half of a requirement it never claimed.
|
|
34
|
-
#
|
|
35
|
-
# FIVE PASSES over the slice — its code, its paired tests, its OKF concept:
|
|
5
|
+
# sibling of analyze-plan:
|
|
6
|
+
# analyze-plan gates spec ↔ plan — STATIC, before implement
|
|
7
|
+
# analyze-slice gates plan ↔ slice — DYNAMIC, after build
|
|
8
|
+
# "Slice" is the unit under analysis: the aggregate's code, its paired tests, and
|
|
9
|
+
# its OKF knowledge concept. Three passes over it —
|
|
36
10
|
# 1. BEHAVIOUR run the tests (paired to the spec's acceptance criteria by the
|
|
37
11
|
# design docs); on red, fix up to 3×.
|
|
38
|
-
# 2.
|
|
39
|
-
#
|
|
40
|
-
#
|
|
41
|
-
#
|
|
42
|
-
#
|
|
43
|
-
#
|
|
44
|
-
#
|
|
45
|
-
# Then the report + the machine-readable verdict, then the stop. Every fix made along
|
|
46
|
-
# the way is merged into the slice's OKF concept, which is also where the file list is
|
|
47
|
-
# READ from (`aw-xref concept-coverage`, both lanes — `concept-paths` reads only
|
|
48
|
-
# `source_files`, so since implement-ui began writing `ui_source_files` a UI-bearing
|
|
49
|
-
# requirement had no UI code in view to be traced to).
|
|
12
|
+
# 2. CONFORMANCE check the code against the domain gate overlays (validate-only).
|
|
13
|
+
# 3. KNOWLEDGE refresh + review the slice's OKF concept (advisory).
|
|
14
|
+
# Every fix made here is recorded in that concept, which is also where the slice's
|
|
15
|
+
# file list is READ from (2.3.0 — `aw-xref concept-paths`, replacing the retired
|
|
16
|
+
# `design-paths` scan for ```lang path=… fences that the tech-agnostic backend-plan.md no
|
|
17
|
+
# longer carries; the paired `design-reconcile` write-back is retired with it, its job
|
|
18
|
+
# already done by the concept-upsert --merge steps in pass 3).
|
|
50
19
|
#
|
|
51
20
|
# TWO POSITIONS, one gate — and in BOTH the master spec.md is the whole truth:
|
|
52
21
|
# BOOTSTRAP implement → build → analyze-slice → run
|
|
53
|
-
# CHANGE implement
|
|
22
|
+
# CHANGE implement (the delta) → build → analyze-slice-delta → finalize-delta
|
|
23
|
+
# → analyze-slice → close-delta
|
|
54
24
|
# On the CHANGE path this gate deliberately runs AFTER finalize-delta, which has already
|
|
55
|
-
# merged the delta into spec.md +
|
|
25
|
+
# merged the delta into spec.md + domain-model.md — so the master carries the change and needs
|
|
56
26
|
# no delta-awareness here. It runs BEFORE close-delta, so the change is still OPEN: a red
|
|
57
27
|
# result is recoverable ("fix and re-run"), not a defect on an already-shipped version.
|
|
58
28
|
# The only thing this gate reads the open change for is where to send you next.
|
|
59
29
|
#
|
|
60
|
-
# IT
|
|
61
|
-
#
|
|
62
|
-
#
|
|
63
|
-
#
|
|
64
|
-
#
|
|
30
|
+
# IT HAS A DELTA TWIN, AND THE TWO ASK THE SAME QUESTION OF DIFFERENT SCOPES.
|
|
31
|
+
# analyze-slice-delta runs one stage earlier, before the merge, and asks whether the code
|
|
32
|
+
# does what THE CHANGE'S delta-spec asked for — the same requirements-anchored question this
|
|
33
|
+
# gate asks of the whole spec, narrowed to one change's ids and answered while the delta is
|
|
34
|
+
# still the only document that carries them. This gate cannot substitute for it: it is
|
|
35
|
+
# test-driven, and a requirement that was never implemented leaves NO test rather than a
|
|
36
|
+
# failing one, so nothing here fails on it. What this gate does that its twin cannot is
|
|
37
|
+
# score the WHOLE slice, against masters that carry the change, with the fix loops and the
|
|
38
|
+
# referrer blast radius.
|
|
65
39
|
#
|
|
66
|
-
# Launch: /appweaver analyze-slice [
|
|
40
|
+
# Launch: /appweaver analyze-slice [strategy]
|
|
67
41
|
# Prereq: /appweaver build (compiled code for the active feature).
|
|
68
42
|
# =============================================================================
|
|
69
43
|
|
|
70
44
|
name: aw-spec-analyze-slice
|
|
71
|
-
description:
|
|
72
|
-
version: 3.0
|
|
45
|
+
description: The design↔code conformance gate — run the slice's tests against its acceptance criteria, check the code against the domain gate overlays, verify the change did not break any referring aggregate (the OKF referrer blast radius) and write a triage report before stopping if it did, refresh + review its OKF concept, and record every fix in it. Sits after finalize-delta on the change path, so the master spec it scores against already carries the change, and before close-delta, so a red gate leaves the change open and recoverable.
|
|
46
|
+
version: 2.3.0
|
|
73
47
|
agent_agnostic: true
|
|
74
48
|
dialect: aw-spec.orchestrator/v1
|
|
75
49
|
|
|
76
|
-
inputs:
|
|
77
|
-
user_input:
|
|
78
|
-
description: Optional story id to scope the gate to (e.g. "Order-002"). With none, the whole feature is judged minus its in-flight ids.
|
|
79
|
-
required: false
|
|
80
|
-
bind: USER_INPUT
|
|
81
|
-
|
|
82
50
|
scripts:
|
|
83
51
|
actions:
|
|
84
52
|
sh: .appweaver/scripts/bash/aw-spec-actions.sh
|
|
@@ -88,8 +56,8 @@ scripts:
|
|
|
88
56
|
ps1: .appweaver/scripts/powershell/aw-xref.ps1
|
|
89
57
|
|
|
90
58
|
# No hardcoded technical standards seed. The technical rule files the code/conformance
|
|
91
|
-
# passes check against (testing + coding-standards) are CONFIGURATION, loaded per-
|
|
92
|
-
# from guardrails/projects/<project>/tech-rule-bindings.md under "## /aw-spec-analyze-slice"
|
|
59
|
+
# passes check against (testing + coding-standards) are now CONFIGURATION, loaded per-
|
|
60
|
+
# command from guardrails/projects/<project>/tech-rule-bindings.md under "## /aw-spec-analyze-slice"
|
|
93
61
|
# by the tech-select module (see the tech_select step below). The DOMAIN gate overlays are
|
|
94
62
|
# still loaded separately, as before (resolve_gate_overlays → load_gate_overlays). This gate
|
|
95
63
|
# does not reference constitution.technical.md. The seed below is behaviour-only — the kit's
|
|
@@ -99,99 +67,24 @@ standards:
|
|
|
99
67
|
- { path: .appweaver/ai-rules.md } # kit-resident: the universal operating rules, every flow
|
|
100
68
|
|
|
101
69
|
vars:
|
|
102
|
-
# --- the feature and its documents --------------------------------------
|
|
103
|
-
feature_dir: ""
|
|
104
|
-
spec_file: ""
|
|
105
|
-
spec_exists: "false"
|
|
106
|
-
be_plan: ""
|
|
107
|
-
be_plan_exists: "false"
|
|
108
|
-
fe_plan: ""
|
|
109
|
-
fe_plan_exists: "false"
|
|
110
|
-
# --- scope --------------------------------------------------------------
|
|
111
|
-
# Defaults describe the FEATURE-scoped run, which is what happens when no story is
|
|
112
|
-
# named — including on brownfield, where adopt emits an empty backlog by design.
|
|
113
|
-
scope: "feature"
|
|
114
|
-
story: ""
|
|
115
|
-
story_path: ""
|
|
116
|
-
story_title: ""
|
|
117
|
-
story_type: ""
|
|
118
|
-
story_status: ""
|
|
119
|
-
story_dir: ""
|
|
120
|
-
story_resolved: "false"
|
|
121
|
-
is_technical: "false"
|
|
122
|
-
exercises_csv: ""
|
|
123
|
-
constraints_csv: ""
|
|
124
|
-
current_version: ""
|
|
125
|
-
stale_csv: ""
|
|
126
|
-
stale_note: ""
|
|
127
|
-
inflight_csv: ""
|
|
128
|
-
backlog_digest: ""
|
|
129
|
-
# Non-empty only when the caller said SOMETHING and no story came back from it — the
|
|
130
|
-
# one case where widening to feature scope is more likely a typo than a choice.
|
|
131
|
-
unresolved_input: ""
|
|
132
|
-
scope_brief: "SCOPE — the WHOLE FEATURE. No story was named, so every FR- and BR- in spec.md is in scope and each is judged in FULL. EXTENT: the whole of each id."
|
|
133
|
-
story_be_doc: ""
|
|
134
|
-
story_be_exists: "false"
|
|
135
|
-
story_be_pass: "0"
|
|
136
|
-
story_fe_doc: ""
|
|
137
|
-
story_fe_exists: "false"
|
|
138
|
-
story_fe_pass: "0"
|
|
139
|
-
bridge_note: "BRIDGE — the FEATURE PLANS (backend-plan.md, and frontend-plan.md where a frontend lane is declared). No story design is in scope this run, so the plans are the only map from a spec id to the elements that realise it."
|
|
140
|
-
# --- the code under analysis (OKF) --------------------------------------
|
|
141
|
-
coverage_digest: ""
|
|
142
|
-
be_count: "0"
|
|
143
|
-
fe_count: "0"
|
|
144
|
-
paths_missing: ""
|
|
145
|
-
okf_concept: ""
|
|
146
|
-
# --- pass 1: behaviour ---------------------------------------------------
|
|
147
70
|
test_ok: "false"
|
|
148
|
-
no_test_edit_rule: ""
|
|
149
|
-
fixed_files: ""
|
|
150
|
-
# --- pass 2: the technical-story oracle ----------------------------------
|
|
151
|
-
# Named per case rather than derived, because "the suite is clean" and "the suite
|
|
152
|
-
# could not be read" must never collapse into one another: a gate that treats "could
|
|
153
|
-
# not look" as "nothing found" is the false green the kit refuses everywhere else.
|
|
154
|
-
oracle: "clean"
|
|
155
|
-
oracle_case: ""
|
|
156
|
-
tests_changed_csv: ""
|
|
157
|
-
tests_changed_count: "0"
|
|
158
|
-
tdiff_digest: ""
|
|
159
|
-
tdiff_base: ""
|
|
160
|
-
tdiff_base_kind: ""
|
|
161
|
-
tech_gate_ok: "true"
|
|
162
|
-
tech_note: "Not a technical story — the unchanged-suite oracle does not apply."
|
|
163
|
-
# --- pass 3: domain conformance ------------------------------------------
|
|
164
71
|
conformance_ok: "false"
|
|
165
|
-
conformance_violations: ""
|
|
166
|
-
conformance_fixes: ""
|
|
167
|
-
# --- pass 4: integrity (referrer blast radius) ---------------------------
|
|
168
|
-
# Defaults are safe values if xref/test-run is skipped or errors, so the gate reads a
|
|
169
|
-
# real verdict rather than an empty var.
|
|
170
|
-
integrity_ok: "false"
|
|
171
|
-
referrer_csv: ""
|
|
172
|
-
referrer_count: "0"
|
|
173
|
-
referrer_names: ""
|
|
174
|
-
integrity_log: ""
|
|
175
|
-
# --- pass 5: trace (the verdict) -----------------------------------------
|
|
176
|
-
trace_ok: "false"
|
|
177
|
-
bridge_ok: "true"
|
|
178
|
-
trace_gaps: ""
|
|
179
|
-
trace_gap_count: "0"
|
|
180
|
-
trace_gap_refs: ""
|
|
181
|
-
trace_coverage: ""
|
|
182
|
-
bridge_gaps: ""
|
|
183
|
-
# --- OKF knowledge (advisory) --------------------------------------------
|
|
184
|
-
okf_ok: "unknown"
|
|
185
|
-
okf_orphans: "0"
|
|
186
|
-
# --- reporting ------------------------------------------------------------
|
|
187
|
-
report_path: ""
|
|
188
|
-
result_file: ""
|
|
189
72
|
# NAVIGATION ONLY. Whether a change is open decides where this gate sends you next
|
|
190
73
|
# (close-delta vs run) — nothing else in this workflow reads them. On the CHANGE path
|
|
191
74
|
# finalize-delta has already merged the delta into the master docs, so the delta files
|
|
192
75
|
# are redundant here and are deliberately NOT loaded into any context.
|
|
193
76
|
active_change: ""
|
|
194
77
|
has_change: "false"
|
|
78
|
+
# Integrity pass (referrer blast radius) defaults — safe values if xref/test-run is
|
|
79
|
+
# skipped or errors, so the gate reads a real verdict rather than an empty var.
|
|
80
|
+
integrity_ok: "false"
|
|
81
|
+
referrer_csv: ""
|
|
82
|
+
referrer_count: "0"
|
|
83
|
+
referrer_names: ""
|
|
84
|
+
# Pass-3 (OKF) reporting defaults — the knowledge pass is advisory, so these stay
|
|
85
|
+
# readable in the outputs even when a step is skipped or errors out.
|
|
86
|
+
okf_ok: "unknown"
|
|
87
|
+
okf_orphans: "0"
|
|
195
88
|
|
|
196
89
|
workflow:
|
|
197
90
|
|
|
@@ -212,13 +105,8 @@ workflow:
|
|
|
212
105
|
script: { ref: actions }
|
|
213
106
|
subcommand: feature-paths
|
|
214
107
|
outputs:
|
|
215
|
-
- { name: feature_dir,
|
|
216
|
-
- { name: spec_file,
|
|
217
|
-
- { name: spec_exists, from: "$.spec_exists" }
|
|
218
|
-
- { name: be_plan, from: "$.backend_plan_file" }
|
|
219
|
-
- { name: be_plan_exists, from: "$.backend_plan_exists" }
|
|
220
|
-
- { name: fe_plan, from: "$.frontend_plan_file" }
|
|
221
|
-
- { name: fe_plan_exists, from: "$.frontend_plan_exists" }
|
|
108
|
+
- { name: feature_dir, from: "$.feature_dir" }
|
|
109
|
+
- { name: spec_file, from: "$.spec_file" }
|
|
222
110
|
|
|
223
111
|
- id: require_feature
|
|
224
112
|
action: verify_context
|
|
@@ -226,149 +114,6 @@ workflow:
|
|
|
226
114
|
on_empty: stop
|
|
227
115
|
on_empty_message: "No active feature. Run /appweaver select-feature first (pick or create the aggregate, e.g. Order), then re-run analyze-slice."
|
|
228
116
|
|
|
229
|
-
# The anchor. Every judgement below resolves an id's meaning from this document, so a
|
|
230
|
-
# feature without one has nothing for the code to be measured against.
|
|
231
|
-
- id: require_spec
|
|
232
|
-
action: verify_context
|
|
233
|
-
require_true: spec_exists
|
|
234
|
-
on_false: stop
|
|
235
|
-
on_false_message: "No spec.md for the current feature. Run /appweaver specify first — the spec is this gate's oracle, and code cannot be conformed to a contract that does not exist."
|
|
236
|
-
|
|
237
|
-
# THE ORACLE HAS TO BE HONEST ABOUT ITS OWN VERSION. This is the only gate whose
|
|
238
|
-
# declared oracle IS spec.md — every judgement below resolves an id's meaning from it
|
|
239
|
-
# — and it stamps {{current_version}} into the machine-readable verdict a pipeline
|
|
240
|
-
# branches on. A spec whose version no longer names its contents makes that stamp a
|
|
241
|
-
# false claim about what was certified, so the fence every other consumer carries
|
|
242
|
-
# belongs here most of all.
|
|
243
|
-
- id: spec_state_guard
|
|
244
|
-
action: include
|
|
245
|
-
module: .appweaver/orchestrator/modules/spec-state-gate.orch.yaml
|
|
246
|
-
with: { command: "/appweaver analyze-slice" }
|
|
247
|
-
|
|
248
|
-
# 1. WHICH STORY, if any. An id in the input scopes the gate to that story; anything
|
|
249
|
-
# else widens it to the feature. Deliberately NO ask: this gate has to be runnable
|
|
250
|
-
# unattended, and a gate that stops to ask cannot run in CI. Naming a story narrows
|
|
251
|
-
# it, naming none widens it, and both are legitimate runs.
|
|
252
|
-
- id: story_scan
|
|
253
|
-
action: execute_script
|
|
254
|
-
on_error: continue
|
|
255
|
-
script: { ref: actions }
|
|
256
|
-
subcommand: story-plan-check
|
|
257
|
-
args: ["--feature-dir", "{{feature_dir}}", "--input", "{{USER_INPUT}}"]
|
|
258
|
-
outputs:
|
|
259
|
-
- { name: story_resolved, from: "$.resolved" }
|
|
260
|
-
- { name: story, from: "$.story" }
|
|
261
|
-
- { name: story_path, from: "$.story_path" }
|
|
262
|
-
- { name: story_title, from: "$.story_title" }
|
|
263
|
-
- { name: story_type, from: "$.story_type" }
|
|
264
|
-
- { name: story_status, from: "$.story_status" }
|
|
265
|
-
- { name: story_dir, from: "$.story_dir" }
|
|
266
|
-
- { name: is_technical, from: "$.is_technical" }
|
|
267
|
-
- { name: exercises_csv, from: "$.exercises_csv" }
|
|
268
|
-
- { name: constraints_csv, from: "$.constraints_csv" }
|
|
269
|
-
- { name: current_version, from: "$.current_version" }
|
|
270
|
-
- { name: stale_csv, from: "$.stale_csv" }
|
|
271
|
-
- { name: stale_note, from: "$.stale_note" }
|
|
272
|
-
- { name: backlog_digest, from: "$.digest" }
|
|
273
|
-
- { name: story_be_doc, from: "$.be_doc_path" }
|
|
274
|
-
- { name: story_be_exists, from: "$.be_doc_exists" }
|
|
275
|
-
- { name: story_be_pass, from: "$.be_last_pass" }
|
|
276
|
-
- { name: story_fe_doc, from: "$.fe_doc_path" }
|
|
277
|
-
- { name: story_fe_exists, from: "$.fe_doc_exists" }
|
|
278
|
-
- { name: story_fe_pass, from: "$.fe_last_pass" }
|
|
279
|
-
|
|
280
|
-
# WHICH IDS ARE IN FLIGHT. On a feature-scoped run these are subtracted from the
|
|
281
|
-
# question: a requirement with an OPEN story is work someone is doing, and reporting
|
|
282
|
-
# it as missing code turns every partially-built feature red (law 39). Story-scoped
|
|
283
|
-
# runs subtract nothing — the story under analysis IS the work in flight.
|
|
284
|
-
- id: inflight_ids
|
|
285
|
-
action: execute_script
|
|
286
|
-
on_error: continue
|
|
287
|
-
script: { ref: actions }
|
|
288
|
-
subcommand: story-refs
|
|
289
|
-
args: ["--feature-dir", "{{feature_dir}}"]
|
|
290
|
-
outputs:
|
|
291
|
-
- { name: inflight_csv, from: "$.covered_csv" }
|
|
292
|
-
|
|
293
|
-
# 2. SCOPE + BRIDGE, stated once as the two sentences the trace pass reads. Both vars
|
|
294
|
-
# default to the feature-scoped wording (see `vars:`) and are overwritten only when
|
|
295
|
-
# a story actually resolved, so nothing here can half-apply.
|
|
296
|
-
- id: scope_story
|
|
297
|
-
condition: "{{story_resolved}} == true"
|
|
298
|
-
action: set
|
|
299
|
-
vars:
|
|
300
|
-
scope: "story"
|
|
301
|
-
scope_brief: "SCOPE — story {{story}} ({{story_title}}), type {{story_type}}, status {{story_status}}. In scope: {{exercises_csv}} (delivered by this story) and {{constraints_csv}} (bounds it must meet). EXTENT — the story's '## Requirements delivered' section says which PART of each id this slice delivers; judge the code against the spec's wording of THAT PART alone. A slice is never failed for the half of a requirement it never claimed, and an id no story has claimed yet is not this run's business."
|
|
302
|
-
# A technical story delivers no requirement, so `exercises:` is empty BY DESIGN and there
|
|
303
|
-
# is nothing to trace forward. Its real check already ran — the unchanged-suite oracle —
|
|
304
|
-
# and what is left for trace is the bounds it is still held to. Without this the pass
|
|
305
|
-
# would be handed "in scope: (nothing)" and would go looking for something to report.
|
|
306
|
-
- id: scope_story_technical
|
|
307
|
-
condition: "{{is_technical}} == true"
|
|
308
|
-
action: set
|
|
309
|
-
vars:
|
|
310
|
-
scope_brief: "SCOPE — story {{story}} ({{story_title}}) is a TECHNICAL story: a refactor, dependency upgrade or performance fix that delivers NO requirement. `exercises:` is empty by design, so there is no FR-/BR- to trace forward and NONE is expected. Judge only this: the code still meets the bounds this story is held to ({{constraints_csv}}), and nothing it changed has quietly altered behaviour the spec fixes. Its real oracle is the UNCHANGED test suite, which has already been checked this run. Report NO gap for a requirement — an unimplemented requirement is some other story's business, and a technical story that had to change behaviour was already caught upstream."
|
|
311
|
-
|
|
312
|
-
- id: scope_feature_note
|
|
313
|
-
condition: "{{story_resolved}} == false"
|
|
314
|
-
action: set
|
|
315
|
-
vars:
|
|
316
|
-
scope_brief: "SCOPE — the WHOLE FEATURE, because no story was named. In scope: every FR- and BR- you can see in spec.md EXCEPT these, which have OPEN stories and are work in flight rather than drift: {{inflight_csv}}. EXTENT — the whole of each in-scope id. Also in scope are the CN-/DC-/IC-/UX- the spec binds this feature by, and the SC- Success Criteria — this phase is the one the spec names as their verifier, and a feature-scoped run is the only scope at which a feature-level outcome can be judged. SC- is scored differently from every other class; see the SUCCESS CRITERIA rules below."
|
|
317
|
-
- id: bridge_story
|
|
318
|
-
condition: "{{story_be_exists}} == true"
|
|
319
|
-
action: set
|
|
320
|
-
vars:
|
|
321
|
-
bridge_note: "BRIDGE — the STORY DESIGN, service lane: design pass {{story_be_pass}} of {{story_be_doc}} (the LAST pass; earlier ones are superseded history). Its '### Changes' section is the map from this slice's ids to the files that realise them. The feature plans are in context underneath it as ARCHITECTURE — where those elements live — not as a second contract."
|
|
322
|
-
- id: bridge_story_ui
|
|
323
|
-
condition: "{{story_fe_exists}} == true"
|
|
324
|
-
action: set
|
|
325
|
-
vars:
|
|
326
|
-
bridge_note: "BRIDGE — the STORY DESIGN, both lanes: service pass {{story_be_pass}} of {{story_be_doc}} and UI pass {{story_fe_pass}} of {{story_fe_doc}} (the LAST pass of each; earlier ones are superseded history). Their '### Changes' sections are the map from this slice's ids to the files that realise them. A requirement with a user-facing surface is realised in BOTH lanes and needs a home in each. The feature plans are in context underneath as ARCHITECTURE, not as a second contract."
|
|
327
|
-
|
|
328
|
-
# 3. WHERE THE VERDICT GOES. A story-scoped verdict written at feature level would be
|
|
329
|
-
# overwritten by the next story's run and then read as the feature's, so each scope
|
|
330
|
-
# keeps its own file. gate-result writes the JSON beside the markdown and names it
|
|
331
|
-
# after it, so a job holding either path holds the other.
|
|
332
|
-
# A named story that matched nothing would otherwise widen the run to feature scope in
|
|
333
|
-
# silence, which is a different gate than the one that was asked for. Announced, never
|
|
334
|
-
# refused: the input may equally have been guidance that names no story at all.
|
|
335
|
-
- id: mark_unresolved_input
|
|
336
|
-
condition: "{{story_resolved}} == false"
|
|
337
|
-
action: set
|
|
338
|
-
vars: { unresolved_input: "{{USER_INPUT}}" }
|
|
339
|
-
- id: unresolved_input_notice
|
|
340
|
-
action: verify_context
|
|
341
|
-
require_value: unresolved_input
|
|
342
|
-
equals: ""
|
|
343
|
-
on_mismatch: continue
|
|
344
|
-
on_mismatch_message: |
|
|
345
|
-
No story matched "{{unresolved_input}}", so this run is FEATURE-SCOPED — every FR- and
|
|
346
|
-
BR- in the spec except the ids with open stories. If you meant to gate one story, re-run
|
|
347
|
-
naming it exactly as its file does. The open backlog:
|
|
348
|
-
{{backlog_digest}}
|
|
349
|
-
|
|
350
|
-
- id: report_paths
|
|
351
|
-
action: set
|
|
352
|
-
vars: { report_path: "{{feature_dir}}/slice-analyze-report.md" }
|
|
353
|
-
- id: report_paths_story
|
|
354
|
-
condition: "{{story_resolved}} == true"
|
|
355
|
-
action: set
|
|
356
|
-
vars: { report_path: "{{story_dir}}/slice-analyze-report.md" }
|
|
357
|
-
|
|
358
|
-
# 3a. INVALIDATE any previous verdict, before anything downstream can stop. A gate that
|
|
359
|
-
# writes its result only on completion leaves the LAST run's verdict on disk for
|
|
360
|
-
# every run that aborts — a red test loop, a broken referrer — and a pipeline
|
|
361
|
-
# reading that file would act on a certification this run never made. Every exit
|
|
362
|
-
# from here on therefore leaves at least a red; the real verdict overwrites it.
|
|
363
|
-
- id: gate_result_open
|
|
364
|
-
action: execute_script
|
|
365
|
-
script: { ref: actions }
|
|
366
|
-
subcommand: gate-result
|
|
367
|
-
# The lenient loader needs a flow sequence on ONE line.
|
|
368
|
-
args: ["--gate", "analyze-slice", "--feature-dir", "{{feature_dir}}", "--ok", "false", "--report", "{{report_path}}", "--story", "{{story}}", "--note", "analyze-slice started and has not reached a verdict; a run that stops before certifying leaves this red on purpose"]
|
|
369
|
-
outputs:
|
|
370
|
-
- { name: result_file, from: "$.result_file" }
|
|
371
|
-
|
|
372
117
|
# Is a change OPEN on this feature? Read for NAVIGATION only — see the vars note. Safe
|
|
373
118
|
# on the bootstrap path: with no active_version.json, version-read returns
|
|
374
119
|
# active_change="" / has_change=false and exits 0, so nothing here is conditional on it.
|
|
@@ -381,35 +126,21 @@ workflow:
|
|
|
381
126
|
- { name: active_change, from: "$.active_change" }
|
|
382
127
|
- { name: has_change, from: "$.has_change" }
|
|
383
128
|
|
|
384
|
-
#
|
|
385
|
-
#
|
|
386
|
-
#
|
|
387
|
-
#
|
|
388
|
-
#
|
|
389
|
-
#
|
|
390
|
-
|
|
391
|
-
# on_error: continue so a missing bundle degrades the gate rather than blocking it.
|
|
392
|
-
- id: concept_coverage
|
|
129
|
+
# The slice's source files, from its OKF concept — the context all three passes below
|
|
130
|
+
# work over (test fix loop, integrity triage, conformance). Replaces the retired
|
|
131
|
+
# `design-paths` fence scan: backend-plan.md is tech-agnostic prose with no ```lang path=…
|
|
132
|
+
# code blocks, so that scan returned nothing and every pass ran on an EMPTY file list.
|
|
133
|
+
# Read-only, exits 0 with paths=[] when there is no concept yet; on_error: continue so
|
|
134
|
+
# a missing bundle degrades the gate to its pre-existing (empty) behaviour, never blocks.
|
|
135
|
+
- id: concept_paths
|
|
393
136
|
action: execute_script
|
|
394
137
|
on_error: continue
|
|
395
138
|
script: { ref: xref }
|
|
396
|
-
subcommand: concept-
|
|
397
|
-
args: ["--feature-dir", "{{feature_dir}}"
|
|
139
|
+
subcommand: concept-paths
|
|
140
|
+
args: ["--feature-dir", "{{feature_dir}}"]
|
|
398
141
|
outputs:
|
|
399
|
-
- { name: all_paths,
|
|
400
|
-
|
|
401
|
-
# inlining them. `context_from: all_paths` APPENDS every one of those paths to the
|
|
402
|
-
# envelope, and the engine reads the envelope IN FULL into the user block — so this
|
|
403
|
-
# gate inlined the feature's whole codebase four times over, and again on every fix
|
|
404
|
-
# iteration. Every consumer of that list can open a file itself; what it needed was
|
|
405
|
-
# to be told which files, not to be handed their contents.
|
|
406
|
-
- { name: all_csv, from: "$.all_csv" }
|
|
407
|
-
- { name: all_count, from: "$.all_count" }
|
|
408
|
-
- { name: paths_missing, from: "$.all_missing_csv" }
|
|
409
|
-
- { name: coverage_digest, from: "$.digest" }
|
|
410
|
-
- { name: be_count, from: "$.backend_count" }
|
|
411
|
-
- { name: fe_count, from: "$.frontend_count" }
|
|
412
|
-
- { name: okf_concept, from: "$.concept" }
|
|
142
|
+
- { name: all_paths, from: "$.paths" }
|
|
143
|
+
- { name: paths_missing, from: "$.missing" }
|
|
413
144
|
|
|
414
145
|
- id: resolve_pre_hooks
|
|
415
146
|
action: execute_script
|
|
@@ -424,15 +155,6 @@ workflow:
|
|
|
424
155
|
|
|
425
156
|
# ═══════ PASS 1 — BEHAVIOUR: the slice's tests vs the spec's acceptance criteria ═══════
|
|
426
157
|
# Run tests → (if red) fix → re-run, up to 3×.
|
|
427
|
-
#
|
|
428
|
-
# For a TECHNICAL story the fix loop is told not to touch a test, because a test it
|
|
429
|
-
# edited to reach green is itself the behaviour change pass 2 exists to catch — and
|
|
430
|
-
# pass 2 counts this loop's edits, so the rule and the oracle agree.
|
|
431
|
-
- id: arm_no_test_edit
|
|
432
|
-
condition: "{{is_technical}} == true"
|
|
433
|
-
action: set
|
|
434
|
-
vars:
|
|
435
|
-
no_test_edit_rule: "THIS IS A TECHNICAL STORY. Do NOT modify, weaken, delete or rename a single test — the existing suite is this story's only oracle, and a test that has to change means behaviour changed and the work was a functional story citing a requirement. Fix the CODE until the tests as written pass. If a test genuinely cannot pass without changing it, STOP and say so rather than editing it: that finding is the point of the story, not an obstacle to it."
|
|
436
158
|
- id: test_loop
|
|
437
159
|
action: loop
|
|
438
160
|
while: "{{test_ok}} != true"
|
|
@@ -461,24 +183,18 @@ workflow:
|
|
|
461
183
|
action: build_context
|
|
462
184
|
vars:
|
|
463
185
|
test_log: "{{test_log}}"
|
|
464
|
-
no_test_edit_rule: "{{no_test_edit_rule}}"
|
|
465
|
-
all_csv: "{{all_csv}}"
|
|
466
|
-
all_count: "{{all_count}}"
|
|
467
186
|
context:
|
|
468
187
|
- { path: "{{spec_file}}" }
|
|
188
|
+
context_from: all_paths
|
|
469
189
|
- id: fix
|
|
470
190
|
action: agent_generate
|
|
471
191
|
tools: "Read,Write,Edit,Bash"
|
|
472
192
|
permission_mode: acceptEdits
|
|
473
193
|
task: |
|
|
474
194
|
Tests failed. Make them pass by fixing the code (or a genuinely wrong
|
|
475
|
-
test), keeping behaviour aligned with the spec's
|
|
476
|
-
in context).
|
|
195
|
+
test) in the files in context, keeping behaviour aligned with the spec's
|
|
196
|
+
acceptance criteria (spec in context). Test log:
|
|
477
197
|
{{test_log}}
|
|
478
|
-
|
|
479
|
-
This slice's code, both lanes ({{all_count}} file(s)) — READ the ones the
|
|
480
|
-
failures point at; they are named, not inlined:
|
|
481
|
-
{{all_csv}}
|
|
482
198
|
outputs:
|
|
483
199
|
- { name: fixed_files, from: "$.files" }
|
|
484
200
|
|
|
@@ -496,89 +212,7 @@ workflow:
|
|
|
496
212
|
ones this feature did not cause; matched is not meaningful in that case. Last log:
|
|
497
213
|
{{test_log}}
|
|
498
214
|
|
|
499
|
-
# ═══════ PASS 2 —
|
|
500
|
-
# A technical story (a refactor, a dependency upgrade, a performance fix) delivers no
|
|
501
|
-
# requirement, so `exercises:` is empty and there is no FR- to trace it to. The
|
|
502
|
-
# existing test suite is its whole oracle, and the rule is stronger than "the tests are
|
|
503
|
-
# green": a test that had to be MODIFIED means behaviour moved, and the work was a
|
|
504
|
-
# functional story citing a requirement (law 32). Run AFTER pass 1 on purpose, so the
|
|
505
|
-
# fix loop's own edits are counted — a gate that had to rewrite a test to reach green
|
|
506
|
-
# has proved the same thing.
|
|
507
|
-
#
|
|
508
|
-
# A new test is not a changed one: adding characterisation tests around a refactor is
|
|
509
|
-
# exactly the work a technical story exists to do. Deletions count as changes.
|
|
510
|
-
- id: test_diff
|
|
511
|
-
action: execute_script
|
|
512
|
-
on_error: continue
|
|
513
|
-
script: { ref: actions }
|
|
514
|
-
subcommand: test-diff
|
|
515
|
-
args: ["--feature-dir", "{{feature_dir}}"]
|
|
516
|
-
outputs:
|
|
517
|
-
- { name: oracle, from: "$.oracle" }
|
|
518
|
-
- { name: tests_changed_csv, from: "$.tests_changed_csv" }
|
|
519
|
-
- { name: tests_changed_count, from: "$.tests_changed_count" }
|
|
520
|
-
- { name: tdiff_digest, from: "$.digest" }
|
|
521
|
-
- { name: tdiff_base, from: "$.base" }
|
|
522
|
-
- { name: tdiff_base_kind, from: "$.base_kind" }
|
|
523
|
-
|
|
524
|
-
# The story's type and the diff's state, combined into ONE string so each case is a
|
|
525
|
-
# single comparison the evaluator can make. Both halves are strings, so this needs no
|
|
526
|
-
# boolean gymnastics — a bool rendered by {{ }} and a bool read by require_value never
|
|
527
|
-
# compare equal (law 43), which is why the type arrives as a word rather than a flag.
|
|
528
|
-
- id: oracle_case_set
|
|
529
|
-
action: set
|
|
530
|
-
vars: { oracle_case: "{{story_type}}/{{oracle}}" }
|
|
531
|
-
- id: oracle_fail
|
|
532
|
-
condition: "{{oracle_case}} == technical/changed"
|
|
533
|
-
action: set
|
|
534
|
-
vars:
|
|
535
|
-
tech_gate_ok: "false"
|
|
536
|
-
tech_note: "FAILED — {{tests_changed_count}} test(s) modified or deleted: {{tests_changed_csv}}"
|
|
537
|
-
- id: oracle_unverified
|
|
538
|
-
condition: "{{oracle_case}} == technical/unverified"
|
|
539
|
-
action: set
|
|
540
|
-
vars:
|
|
541
|
-
tech_note: "UNVERIFIED — this is not a git working copy, so the suite's history cannot be read. The oracle did not pass; it could not run."
|
|
542
|
-
- id: oracle_clean
|
|
543
|
-
condition: "{{oracle_case}} == technical/clean"
|
|
544
|
-
action: set
|
|
545
|
-
vars:
|
|
546
|
-
tech_note: "PASSED — no test was modified or deleted against {{tdiff_base_kind}} baseline {{tdiff_base}}."
|
|
547
|
-
|
|
548
|
-
# An oracle that could not be read never fails the gate — it announces. Refusing on the
|
|
549
|
-
# strength of a check that did not run is the mirror image of passing on one.
|
|
550
|
-
- id: oracle_unverified_notice
|
|
551
|
-
condition: "{{oracle_case}} == technical/unverified"
|
|
552
|
-
action: verify_context
|
|
553
|
-
require_value: oracle
|
|
554
|
-
equals: "clean"
|
|
555
|
-
on_mismatch: continue
|
|
556
|
-
on_mismatch_message: |
|
|
557
|
-
TECHNICAL-STORY ORACLE UNVERIFIED for story {{story}}. A technical story delivers no
|
|
558
|
-
requirement, so the unchanged test suite is the only thing that can say whether its
|
|
559
|
-
behaviour moved — and that history is not readable here (this is not a git working
|
|
560
|
-
copy). Everything else in this gate ran; this one check did not, and it is recorded
|
|
561
|
-
as unverified rather than as a pass in {{result_file}}.
|
|
562
|
-
|
|
563
|
-
- id: oracle_gate
|
|
564
|
-
action: verify_context
|
|
565
|
-
require_true: tech_gate_ok
|
|
566
|
-
on_false: stop
|
|
567
|
-
on_false_message: |
|
|
568
|
-
TECHNICAL-STORY ORACLE FAILED — story {{story}} is type `technical`, and a technical
|
|
569
|
-
story's oracle is the UNCHANGED test suite. These tests were modified or deleted:
|
|
570
|
-
{{tests_changed_csv}}
|
|
571
|
-
{{tdiff_digest}}
|
|
572
|
-
A test that had to change means behaviour changed, and behaviour that changes belongs
|
|
573
|
-
to a FUNCTIONAL story citing the requirement it moves. Two ways out, and they are not
|
|
574
|
-
interchangeable: restore the tests and make the refactor behaviour-preserving, or
|
|
575
|
-
accept that this work changes behaviour — close this story as cancelled, raise a
|
|
576
|
-
functional story for the change through /appweaver sync-spec (⌛ not yet built — until it is, fold the change back by hand under .appweaver/SPEC-EDIT-PROTOCOL.md) (if the contract moves)
|
|
577
|
-
or by raising a story by hand from .appweaver/templates/story-template.md
|
|
578
|
-
(/appweaver add-story, which mints the id and stamps the frontmatter, is ⌛ not yet
|
|
579
|
-
built), and build it there where an FR- can be traced to it.
|
|
580
|
-
|
|
581
|
-
# ═══════ PASS 3 — DOMAIN CONFORMANCE: code vs the gate overlay checklist ═══════
|
|
215
|
+
# ═══════ PASS 2 — DOMAIN CONFORMANCE: code vs the gate overlay checklist (validation) ═══════
|
|
582
216
|
# With tests green, scan the feature's CODE against the domain gate overlays (the
|
|
583
217
|
# forbidden-patterns / refusal conditions / CI gates). The overlays load as the
|
|
584
218
|
# checklist — VALIDATION only, never an authoring input to feature code. No-op for a
|
|
@@ -602,28 +236,18 @@ workflow:
|
|
|
602
236
|
steps:
|
|
603
237
|
- id: ctx_conformance
|
|
604
238
|
action: build_context
|
|
605
|
-
vars:
|
|
606
|
-
no_test_edit_rule: "{{no_test_edit_rule}}"
|
|
607
|
-
all_csv: "{{all_csv}}"
|
|
608
|
-
all_count: "{{all_count}}"
|
|
609
239
|
context:
|
|
610
240
|
- { path: "{{spec_file}}" }
|
|
241
|
+
context_from: all_paths
|
|
611
242
|
- id: check_overlays
|
|
612
243
|
action: agent_query
|
|
613
|
-
# A query step is PAYLOAD-ONLY unless it declares tools. It read the code because
|
|
614
|
-
# context_from inlined every file; naming them instead without granting Read would
|
|
615
|
-
# leave it reasoning about a codebase it cannot open.
|
|
616
|
-
tools: Read
|
|
617
244
|
include_standards: true # the gate overlays (checklist) are in the standards
|
|
618
245
|
schema: { ok: true, violations: [ { rule: "<overlay rule / id>", where: "<file:symbol>", issue: "<what is violated>" } ] }
|
|
619
246
|
mock: { ok: true, violations: [] }
|
|
620
247
|
task: |
|
|
621
248
|
The domain gate checklist is loaded in the standards (the overlay
|
|
622
|
-
forbidden-patterns, refusal conditions, and CI gates).
|
|
623
|
-
|
|
624
|
-
inlined:
|
|
625
|
-
{{all_csv}}
|
|
626
|
-
Check them against EACH checklist rule and list
|
|
249
|
+
forbidden-patterns, refusal conditions, and CI gates). Check the feature's
|
|
250
|
+
generated code + tests (in context) against EACH checklist rule and list
|
|
627
251
|
EVERY violation, e.g.: a hard delete of a retention-protected aggregate /
|
|
628
252
|
version history / audit record; a second write path bypassing the aggregate
|
|
629
253
|
or interop adapter; an invented/free-text coded value where a validated code
|
|
@@ -646,8 +270,7 @@ workflow:
|
|
|
646
270
|
Fix these domain-conformance violations in the feature's code (in context),
|
|
647
271
|
following the gate checklist rules (in the standards) and keeping the design's
|
|
648
272
|
behaviour intact. Do NOT weaken or delete a test to hide a violation — fix the
|
|
649
|
-
code.
|
|
650
|
-
they stay green.
|
|
273
|
+
code. After fixing, re-run the tests (Bash) to confirm they stay green.
|
|
651
274
|
Violations: {{conformance_violations}}
|
|
652
275
|
outputs:
|
|
653
276
|
- { name: conformance_fixes, from: "$.files" }
|
|
@@ -656,9 +279,9 @@ workflow:
|
|
|
656
279
|
action: verify_context
|
|
657
280
|
require_true: conformance_ok
|
|
658
281
|
on_false: stop
|
|
659
|
-
on_false_message: "Code violates the domain gate checklist after 2 fix attempts (violations: {{conformance_violations}}). These are the domain constraints
|
|
282
|
+
on_false_message: "Code violates the domain gate checklist after 2 fix attempts (violations: {{conformance_violations}}). These are the domain constraints plan/implement must satisfy — fix the code, or if the constraint itself is wrong, correct it upstream (/appweaver specify → plan)."
|
|
660
283
|
|
|
661
|
-
# ═══════
|
|
284
|
+
# ═══════ INTEGRITY — did this feature's change break any aggregate that USES it? ═══════
|
|
662
285
|
# The slice is green + domain-conformant on its own. But a change to a feature can break
|
|
663
286
|
# any OTHER aggregate that references it. Ask the OKF Cross-References index "who refers to
|
|
664
287
|
# me?" (the transitive referrer closure — C→B→A all count), then RE-RUN the feature's tests
|
|
@@ -676,7 +299,7 @@ workflow:
|
|
|
676
299
|
outputs:
|
|
677
300
|
- { name: referrer_csv, from: "$.referrer_closure_csv" }
|
|
678
301
|
- { name: referrer_count, from: "$.referrer_closure_count" }
|
|
679
|
-
- { name: referrer_names, from: "$.
|
|
302
|
+
- { name: referrer_names, from: "$.referrer_closure" }
|
|
680
303
|
|
|
681
304
|
- id: run_integrity
|
|
682
305
|
action: execute_script
|
|
@@ -700,16 +323,12 @@ workflow:
|
|
|
700
323
|
referrer_names: "{{referrer_names}}"
|
|
701
324
|
referrer_count: "{{referrer_count}}"
|
|
702
325
|
integrity_log: "{{integrity_log}}"
|
|
703
|
-
all_csv: "{{all_csv}}"
|
|
704
|
-
all_count: "{{all_count}}"
|
|
705
326
|
context:
|
|
706
327
|
- { path: "{{spec_file}}" }
|
|
328
|
+
context_from: all_paths
|
|
707
329
|
- id: write_broken_referrers
|
|
708
330
|
action: agent_author
|
|
709
331
|
condition: "{{integrity_ok}} != true"
|
|
710
|
-
# An author step is PAYLOAD-ONLY unless it declares tools. The triage report has to
|
|
711
|
-
# name what this slice CHANGED that the referrers depend on, which means reading it.
|
|
712
|
-
tools: Read
|
|
713
332
|
include_standards: false # a triage report, not generated code
|
|
714
333
|
output_target: { type: file, path: "{{feature_dir}}/broken-referrers.md" }
|
|
715
334
|
task: |
|
|
@@ -719,9 +338,6 @@ workflow:
|
|
|
719
338
|
referrer (that is the referrer's own slice's job). Referrer blast radius
|
|
720
339
|
({{referrer_count}}): {{referrer_names}}. Failing test log:
|
|
721
340
|
{{integrity_log}}
|
|
722
|
-
This slice's code, both lanes ({{all_count}} file(s)) — READ what it changed on the
|
|
723
|
-
published surface to say WHY the referrers broke; the files are named, not inlined:
|
|
724
|
-
{{all_csv}}
|
|
725
341
|
Write markdown, in this order:
|
|
726
342
|
- `# Broken Referrers — <feature>` and a one-line statement of what this file is:
|
|
727
343
|
aggregates that USE this feature and whose tests went red when this feature's
|
|
@@ -754,151 +370,7 @@ workflow:
|
|
|
754
370
|
on_false: stop
|
|
755
371
|
on_false_message: "Integrity check failed — this feature's change breaks a test in an aggregate that REFERS to it. Referrer blast radius ({{referrer_count}}): {{referrer_names}}. Triage written to {{feature_dir}}/broken-referrers.md — resolve each in the referrer's own slice (or reconsider this feature's contract change), then re-run. Last log: {{integrity_log}}"
|
|
756
372
|
|
|
757
|
-
# ═══════ PASS
|
|
758
|
-
# The question this gate exists to answer, asked last because everything before it is a
|
|
759
|
-
# precondition: the code runs, it changed no oracle it should not have, it violates no
|
|
760
|
-
# domain constraint, and it broke nobody. What is left is the only thing that matters —
|
|
761
|
-
# is this the thing the contract asked for?
|
|
762
|
-
#
|
|
763
|
-
# READ-ONLY. It reports and never repairs: a missing requirement is feature work, and
|
|
764
|
-
# writing it here would produce code no design pass names and no gate ever conformed.
|
|
765
|
-
# Nothing between this step and the report can stop the run, so the verdict always
|
|
766
|
-
# reaches both the markdown and the JSON.
|
|
767
|
-
- id: ctx_trace
|
|
768
|
-
action: build_context
|
|
769
|
-
vars:
|
|
770
|
-
scope_brief: "{{scope_brief}}"
|
|
771
|
-
bridge_note: "{{bridge_note}}"
|
|
772
|
-
coverage_digest: "{{coverage_digest}}"
|
|
773
|
-
stale_note: "{{stale_note}}"
|
|
774
|
-
all_csv: "{{all_csv}}"
|
|
775
|
-
all_count: "{{all_count}}"
|
|
776
|
-
context:
|
|
777
|
-
- { path: "{{spec_file}}" } # THE ORACLE — the contract's own wording
|
|
778
|
-
- { path: "{{story_path}}", optional: true } # the extent: what this slice claims of each id
|
|
779
|
-
- { path: "{{story_be_doc}}", optional: true } # the BRIDGE, service lane — the latest pass
|
|
780
|
-
- { path: "{{story_fe_doc}}", optional: true } # the BRIDGE, UI lane — the latest pass
|
|
781
|
-
- { path: "{{be_plan}}", optional: true } # architecture: where those elements live
|
|
782
|
-
- { path: "{{fe_plan}}", optional: true }
|
|
783
|
-
- { path: "{{feature_dir}}/interfaces.md", optional: true } # the published surface, cited by IF- id
|
|
784
|
-
- { path: "{{feature_dir}}/adr.md", optional: true } # ratified decisions
|
|
785
|
-
- id: trace
|
|
786
|
-
action: agent_query
|
|
787
|
-
tools: Read # follow a call out of the listed files when a trace needs it
|
|
788
|
-
include_standards: false # the contract is the spec, not a rule corpus
|
|
789
|
-
schema: { ok: true, bridge_ok: true, gap_count: 0, gap_refs: "<comma-separated spec ids the gaps touch>", coverage: "<one line per in-scope id — id | what the spec requires | the design element that maps it | the code that realises it | DELIVERED or GAP>", gaps: [ { severity: "high", spec_ref: "<FR/BR/CN/DC/IC/UX/SC id>", kind: "code-missing|code-wrong|bridge-missing|spec-wrong", where: "<file:symbol, or the document>", gap: "<what the spec requires and what is actually there>", route: "<the command that fixes it>" } ], bridge_gaps: "<one line per in-scope id no design maps, or empty>" }
|
|
790
|
-
mock: { ok: true, bridge_ok: true, gap_count: 0, gap_refs: "", coverage: "", gaps: [], bridge_gaps: "" }
|
|
791
|
-
task: |
|
|
792
|
-
spec.md is the ORACLE. Judge the CODE against it and report every id it fails to
|
|
793
|
-
deliver. The design is the BRIDGE that makes the question answerable — it says
|
|
794
|
-
which elements realise which id — and it is never the standard: where the design
|
|
795
|
-
and the spec disagree about an in-scope id, the SPEC is what the code is measured
|
|
796
|
-
against, and the disagreement is itself a finding.
|
|
797
|
-
|
|
798
|
-
{{scope_brief}}
|
|
799
|
-
|
|
800
|
-
{{bridge_note}}
|
|
801
|
-
|
|
802
|
-
THIS SLICE'S CODE, both lanes, from the OKF concept ({{all_count}} file(s)) — READ
|
|
803
|
-
the ones each id's trace needs, and follow anything they call. They are named here
|
|
804
|
-
rather than inlined, because a real codebase does not fit a payload:
|
|
805
|
-
{{all_csv}}
|
|
806
|
-
Do NOT modify a single file — this step is read-only by contract.
|
|
807
|
-
|
|
808
|
-
{{coverage_digest}}
|
|
809
|
-
|
|
810
|
-
HOW TO TRACE each in-scope id, in this order:
|
|
811
|
-
(1) Resolve the id's wording from spec.md. That wording — not the design's
|
|
812
|
-
restatement of it — is the standard.
|
|
813
|
-
(2) Find the DESIGN element that maps it (the story pass's "### Changes" and
|
|
814
|
-
"### Approach", or the feature plan's traceability section). If nothing maps
|
|
815
|
-
it, that is a BRIDGE gap: record it in `bridge_gaps` with kind
|
|
816
|
-
"bridge-missing". Then keep going — code may well deliver the id anyway, and
|
|
817
|
-
an undocumented realisation is a documentation defect, not a broken contract.
|
|
818
|
-
(3) Find the CODE that realises the element, and read it. Judge whether it
|
|
819
|
-
delivers what the spec words, to the extent this scope claims.
|
|
820
|
-
(4) Where the id has a user-facing surface, it is realised in BOTH lanes and needs
|
|
821
|
-
a home in each. A UX- lives only in the UI lane; a BR- only in the service
|
|
822
|
-
lane. Do not report a UI gap for a slice that has no UI lane in scope.
|
|
823
|
-
|
|
824
|
-
SUCCESS CRITERIA (SC-) ARE SCORED AS OUTCOMES, NOT AS REALISATIONS. An SC- is a
|
|
825
|
-
measurable result the whole feature is supposed to produce — "a customer can place
|
|
826
|
-
an order in under two minutes", "90% of first-time users complete an order without
|
|
827
|
-
assistance" — so no design element "maps" one and no file "realises" one. Four
|
|
828
|
-
rules, and they override steps (2) and (3) and the ok/bridge_ok sentences below for
|
|
829
|
-
this class alone:
|
|
830
|
-
• Score each in-scope SC- as MET, NOT MET, or NOT ASSESSABLE FROM A STATIC READ.
|
|
831
|
-
Most are the third: a latency budget, an adoption rate or a support-ticket
|
|
832
|
-
reduction cannot be decided by reading code, and inventing a verdict is worse
|
|
833
|
-
than recording that it needs measuring.
|
|
834
|
-
• NOT ASSESSABLE is not a gap. It does not set ok=false and it is not counted in
|
|
835
|
-
gap_count — say in its `coverage` line what would have to be measured, and by
|
|
836
|
-
what, to settle it.
|
|
837
|
-
• NOT MET does fail ok: reserve it for the case where the code plainly cannot
|
|
838
|
-
satisfy the criterion (the feature has no such surface at all, or the design
|
|
839
|
-
rules the outcome out).
|
|
840
|
-
• An SC- NEVER sets bridge_ok=false and is NEVER a "bridge-missing" gap. There is
|
|
841
|
-
no design element to be missing, so routing one to story-plan sends someone to
|
|
842
|
-
design a document entry that should not exist.
|
|
843
|
-
Every in-scope SC- still gets its `coverage` line. The record is the point: this is
|
|
844
|
-
the phase the spec names as their verifier, and "measured how, and when" is the
|
|
845
|
-
answer it is meant to leave behind.
|
|
846
|
-
|
|
847
|
-
CLASSIFY every gap by `kind`, because the four routes are different commands:
|
|
848
|
-
code-missing the design maps the id and no code realises it → /appweaver implement
|
|
849
|
-
code-wrong code exists and does something else → /appweaver implement
|
|
850
|
-
bridge-missing no design maps the id at all → /appweaver story-plan
|
|
851
|
-
spec-wrong the code is right and the SPEC words it wrongly → /appweaver sync-spec
|
|
852
|
-
Use `spec-wrong` sparingly and only with a reason: the spec is the oracle, and
|
|
853
|
-
"the code disagrees" is evidence about the code first.
|
|
854
|
-
|
|
855
|
-
THESE ARE NOT GAPS, and reporting them is noise that hides the real ones:
|
|
856
|
-
- an id that is out of scope for this run — another story's work, or one nobody
|
|
857
|
-
has claimed yet;
|
|
858
|
-
- the part of a requirement this scope explicitly does not claim;
|
|
859
|
-
- style, naming, structure, layering or test-coverage opinions — other gates own
|
|
860
|
-
every one of those;
|
|
861
|
-
- anything a design pass deliberately deferred and named under its risks;
|
|
862
|
-
- a missing element you inferred from the design alone with no spec basis. The
|
|
863
|
-
design is the bridge, not the contract.
|
|
864
|
-
|
|
865
|
-
Fill `coverage` with ONE LINE PER IN-SCOPE ID, delivered or not — that table is the
|
|
866
|
-
traceability record this gate exists to leave behind, and it is written on a green
|
|
867
|
-
run too. Set gap_count and gap_refs from `gaps`. Set ok=true ONLY when every
|
|
868
|
-
in-scope FR-/BR-/CN-/DC-/IC-/UX- is delivered as the spec words it and no in-scope
|
|
869
|
-
SC- is NOT MET — an SC- scored not-assessable leaves ok exactly as it was. Set
|
|
870
|
-
bridge_ok=false when any in-scope id OTHER THAN AN SC- has no design mapping it,
|
|
871
|
-
INDEPENDENTLY of ok — working code with a documentation gap is a true state and must
|
|
872
|
-
be reportable as one.
|
|
873
|
-
{{stale_note}}
|
|
874
|
-
outputs:
|
|
875
|
-
- { name: trace_ok, from: "$.ok" }
|
|
876
|
-
- { name: bridge_ok, from: "$.bridge_ok" }
|
|
877
|
-
- { name: trace_gaps, from: "$.gaps" }
|
|
878
|
-
- { name: trace_gap_count, from: "$.gap_count" }
|
|
879
|
-
- { name: trace_gap_refs, from: "$.gap_refs" }
|
|
880
|
-
- { name: trace_coverage, from: "$.coverage" }
|
|
881
|
-
- { name: bridge_gaps, from: "$.bridge_gaps" }
|
|
882
|
-
|
|
883
|
-
# The bridge's integrity is ANNOUNCED, not gated. An id the design never mapped, whose
|
|
884
|
-
# code nonetheless delivers the spec, is a documentation defect — failing the slice for
|
|
885
|
-
# it would refuse working, contract-satisfying code over a missing row in a document
|
|
886
|
-
# the next story-plan pass rewrites anyway.
|
|
887
|
-
- id: bridge_notice
|
|
888
|
-
condition: "{{bridge_ok}} == false"
|
|
889
|
-
action: verify_context
|
|
890
|
-
require_value: bridge_ok
|
|
891
|
-
equals: "true"
|
|
892
|
-
on_mismatch: continue
|
|
893
|
-
on_mismatch_message: |
|
|
894
|
-
BRIDGE INCOMPLETE — in-scope ids that no design maps:
|
|
895
|
-
{{bridge_gaps}}
|
|
896
|
-
The code may well deliver them; what is missing is the record of WHERE. Nothing was
|
|
897
|
-
failed for this. Append a pass that maps them — /appweaver story-plan for the story
|
|
898
|
-
that owns the id, or /appweaver plan when the gap is feature-level — so the next run
|
|
899
|
-
of this gate can trace them instead of inferring them.
|
|
900
|
-
|
|
901
|
-
# ═══════ OKF KNOWLEDGE — keep the slice's concept true to what now exists ═══════
|
|
373
|
+
# ═══════ PASS 3 — OKF KNOWLEDGE: keep the slice's concept true to what now exists ═══════
|
|
902
374
|
# analyze-slice is the LAST stage that changes a greenfield slice's files: both fix loops
|
|
903
375
|
# above run with Write/Edit, and the conformance loop is explicitly asked to ADD missing
|
|
904
376
|
# constraint tests. Those files did not exist when implement wrote the OKF concept, so its
|
|
@@ -906,18 +378,20 @@ workflow:
|
|
|
906
378
|
# the concept holds the full set implement recorded, these two vars hold only what the fix
|
|
907
379
|
# loops touched), then report cross-reference drift.
|
|
908
380
|
#
|
|
909
|
-
#
|
|
910
|
-
#
|
|
911
|
-
#
|
|
912
|
-
#
|
|
381
|
+
# These two steps are now the WHOLE write-back: the former `design-reconcile` step that
|
|
382
|
+
# preceded them was deleted (it copied on-disk file bodies into path-tagged design fences
|
|
383
|
+
# — meaningless once backend-plan.md became tech-agnostic prose, and it read the same
|
|
384
|
+
# fixed_files/paths these steps already own). Recording the files in the concept IS the
|
|
385
|
+
# current reconcile.
|
|
913
386
|
#
|
|
914
387
|
# Deliberately NOT re-running `record`: the Depends-On/Cross-References edges derive from
|
|
915
|
-
#
|
|
916
|
-
#
|
|
917
|
-
#
|
|
918
|
-
# `reverse-engineered` provenance instead of
|
|
388
|
+
# backend-plan.md §1 + its External integrations table, and no step in this stage edits
|
|
389
|
+
# backend-plan.md — the edge sources
|
|
390
|
+
# cannot have moved here. `--origin` is likewise omitted: concept-upsert setdefaults it,
|
|
391
|
+
# so an adopted (brownfield) slice keeps its `reverse-engineered` provenance instead of
|
|
392
|
+
# being restamped greenfield.
|
|
919
393
|
#
|
|
920
|
-
# Advisory by design (on_error: continue, no gate): a green,
|
|
394
|
+
# Advisory by design (on_error: continue, no gate): a green, domain-conformant slice is
|
|
921
395
|
# never failed over its knowledge index — drift is reported in the outputs and fixed by
|
|
922
396
|
# `aw-xref validate --prune` / re-running the owning slice's `record`.
|
|
923
397
|
- id: okf_merge_test_fixes
|
|
@@ -926,7 +400,7 @@ workflow:
|
|
|
926
400
|
on_error: continue
|
|
927
401
|
script: { ref: xref }
|
|
928
402
|
subcommand: concept-upsert
|
|
929
|
-
args: ["--feature-dir", "{{feature_dir}}", "--source-files", "{{fixed_files}}", "--merge"
|
|
403
|
+
args: ["--feature-dir", "{{feature_dir}}", "--source-files", "{{fixed_files}}", "--merge"]
|
|
930
404
|
outputs:
|
|
931
405
|
- { name: okf_concept, from: "$.concept" }
|
|
932
406
|
|
|
@@ -936,7 +410,7 @@ workflow:
|
|
|
936
410
|
on_error: continue
|
|
937
411
|
script: { ref: xref }
|
|
938
412
|
subcommand: concept-upsert
|
|
939
|
-
args: ["--feature-dir", "{{feature_dir}}", "--source-files", "{{conformance_fixes}}", "--merge"
|
|
413
|
+
args: ["--feature-dir", "{{feature_dir}}", "--source-files", "{{conformance_fixes}}", "--merge"]
|
|
940
414
|
outputs:
|
|
941
415
|
- { name: okf_concept, from: "$.concept" }
|
|
942
416
|
|
|
@@ -949,86 +423,6 @@ workflow:
|
|
|
949
423
|
- { name: okf_ok, from: "$.ok" }
|
|
950
424
|
- { name: okf_orphans, from: "$.orphan_count" }
|
|
951
425
|
|
|
952
|
-
# ═══════ THE RECORD — written on EVERY run that gets here, green or red ═══════
|
|
953
|
-
# A gate that leaves nothing behind when it passes gives a reviewer no evidence that it
|
|
954
|
-
# ran at all, and the spec→design→code table is the whole point of tracing rather than
|
|
955
|
-
# merely testing.
|
|
956
|
-
- id: ctx_report
|
|
957
|
-
action: build_context
|
|
958
|
-
vars:
|
|
959
|
-
scope_brief: "{{scope_brief}}"
|
|
960
|
-
trace_coverage: "{{trace_coverage}}"
|
|
961
|
-
trace_gaps: "{{trace_gaps}}"
|
|
962
|
-
bridge_gaps: "{{bridge_gaps}}"
|
|
963
|
-
tech_note: "{{tech_note}}"
|
|
964
|
-
tdiff_digest: "{{tdiff_digest}}"
|
|
965
|
-
- id: write_report
|
|
966
|
-
action: agent_author
|
|
967
|
-
include_standards: false
|
|
968
|
-
output_target: { type: file, path: "{{report_path}}" }
|
|
969
|
-
task: |
|
|
970
|
-
Write the Slice Analyze Report to the output. It records what this gate found
|
|
971
|
-
tracing spec.md through the design to the code.
|
|
972
|
-
|
|
973
|
-
Verdict: contract satisfied={{trace_ok}}, bridge complete={{bridge_ok}}.
|
|
974
|
-
Gaps: {{trace_gap_count}} on {{trace_gap_refs}}.
|
|
975
|
-
Scope: {{scope}}-scoped, story "{{story}}" (empty on a feature-scoped run) ·
|
|
976
|
-
spec version {{current_version}}.
|
|
977
|
-
{{scope_brief}}
|
|
978
|
-
Passes: tests green={{test_ok}} (tool {{test_tool}}); technical oracle —
|
|
979
|
-
{{tech_note}}; domain conformance={{conformance_ok}}; integrity fence={{integrity_ok}}
|
|
980
|
-
over {{referrer_count}} referrer(s) ({{referrer_names}}). Code analysed:
|
|
981
|
-
{{be_count}} service file(s) + {{fe_count}} UI file(s) from the OKF concept
|
|
982
|
-
{{okf_concept}}; declared but absent from disk: {{paths_missing}}.
|
|
983
|
-
Coverage rows:
|
|
984
|
-
{{trace_coverage}}
|
|
985
|
-
Gaps:
|
|
986
|
-
{{trace_gaps}}
|
|
987
|
-
Bridge gaps:
|
|
988
|
-
{{bridge_gaps}}
|
|
989
|
-
|
|
990
|
-
Markdown format:
|
|
991
|
-
- `# Slice Analyze Report — <aggregate>` and, under it, a line naming the scope
|
|
992
|
-
(story id or "whole feature"), the spec version, and when this ran.
|
|
993
|
-
- A verdict line: "verdict: DELIVERS ✓" or "verdict: GAPS ✗ · <n> open". Add a
|
|
994
|
-
second line for the bridge when it is incomplete.
|
|
995
|
-
- `## Traceability (spec → design → code)`: a table
|
|
996
|
-
| spec id | what the spec requires | design element | code | status |
|
|
997
|
-
one row per in-scope id, from the coverage rows above. This is the reason the
|
|
998
|
-
report exists — write it on a green run too. If a row's design cell is empty the
|
|
999
|
-
id is unbridged; say so in the cell rather than leaving it blank.
|
|
1000
|
-
- `## Gaps`: a table | # | severity | spec ref | kind | where | gap | route |.
|
|
1001
|
-
Omit the section when there were none.
|
|
1002
|
-
- `## Passes`: one line each for behaviour, the technical-story oracle, domain
|
|
1003
|
-
conformance and integrity, with the result given above. Say plainly when the
|
|
1004
|
-
oracle was UNVERIFIED rather than passed.
|
|
1005
|
-
- `## How to resolve`: group the gaps by route and give the exact command for
|
|
1006
|
-
each — code-missing/code-wrong go to /appweaver implement (correct the design
|
|
1007
|
-
pass first if the pass is what is wrong), bridge-missing to /appweaver story-plan,
|
|
1008
|
-
spec-wrong to /appweaver sync-spec. Omit on a clean run.
|
|
1009
|
-
Do not invent ids, versions, dates or findings beyond the values given above.
|
|
1010
|
-
Return the complete report markdown only.
|
|
1011
|
-
|
|
1012
|
-
# The machine-readable verdict, written beside the report by the SCRIPT — CI cannot
|
|
1013
|
-
# branch on prose, and a verdict is exactly the kind of dated, derived record the model
|
|
1014
|
-
# never writes. `ok` from this step means the file was written; the pass/fail verdict is
|
|
1015
|
-
# `status` inside it.
|
|
1016
|
-
- id: gate_result
|
|
1017
|
-
action: execute_script
|
|
1018
|
-
script: { ref: actions }
|
|
1019
|
-
subcommand: gate-result
|
|
1020
|
-
# The lenient loader needs a flow sequence on ONE line.
|
|
1021
|
-
args: ["--gate", "analyze-slice", "--feature-dir", "{{feature_dir}}", "--ok", "{{trace_ok}}", "--spec-version", "{{current_version}}", "--story", "{{story}}", "--report", "{{report_path}}", "--gap-count", "{{trace_gap_count}}", "--gap-refs", "{{trace_gap_refs}}", "--field", "scope={{scope}}", "--field", "story_type={{story_type}}", "--field", "bridge_ok={{bridge_ok}}", "--field", "tests_green={{test_ok}}", "--field", "test_suite_diff={{oracle}}", "--field", "technical_oracle={{tech_note}}", "--field", "tests_changed={{tests_changed_csv}}", "--field", "domain_conformance={{conformance_ok}}", "--field", "integrity={{integrity_ok}}", "--field", "referrers={{referrer_names}}", "--field", "okf_concept={{okf_concept}}", "--field", "okf_index_ok={{okf_ok}}", "--field", "stale_ids={{stale_csv}}"]
|
|
1022
|
-
outputs:
|
|
1023
|
-
- { name: result_file, from: "$.result_file" }
|
|
1024
|
-
|
|
1025
|
-
# THE GATE. Last, so the report and the verdict are on disk whichever way it goes.
|
|
1026
|
-
- id: trace_gate
|
|
1027
|
-
action: verify_context
|
|
1028
|
-
require_true: trace_ok
|
|
1029
|
-
on_false: stop
|
|
1030
|
-
on_false_message: "The code does not deliver the contract — {{trace_gap_count}} gap(s) on {{trace_gap_refs}}. The traceability report is at {{report_path}} and the machine-readable verdict at {{result_file}}. Nothing was repaired: a missing requirement is feature work, and writing it inside a gate would produce code no design pass names and no gate ever conformed. Route by each gap's `kind` — code-missing / code-wrong: correct the design pass if it is what is wrong (/appweaver story-plan), then /appweaver implement; bridge-missing: /appweaver story-plan, which appends a pass that maps the id; spec-wrong: /appweaver sync-spec, which is the ONLY way the contract moves. Then re-run /appweaver analyze-slice."
|
|
1031
|
-
|
|
1032
426
|
- id: resolve_post_hooks
|
|
1033
427
|
action: execute_script
|
|
1034
428
|
script: { ref: actions }
|
|
@@ -1042,24 +436,13 @@ workflow:
|
|
|
1042
436
|
|
|
1043
437
|
outputs:
|
|
1044
438
|
feature_dir: "{{feature_dir}}"
|
|
1045
|
-
|
|
1046
|
-
delivers_contract: "{{trace_ok}}"
|
|
1047
|
-
bridge_complete: "{{bridge_ok}}"
|
|
1048
|
-
gaps: "{{trace_gap_count}} on {{trace_gap_refs}}"
|
|
1049
|
-
gap_detail: "{{trace_gaps}}"
|
|
1050
|
-
bridge_gaps: "{{bridge_gaps}}"
|
|
1051
|
-
report: "{{report_path}}"
|
|
1052
|
-
result_json: "{{result_file}}"
|
|
1053
|
-
tests: "green={{test_ok}} (tool {{test_tool}})"
|
|
1054
|
-
technical_oracle: "{{tech_note}}"
|
|
1055
|
-
domain_conformance: "{{conformance_ok}}"
|
|
439
|
+
test_tool: "{{test_tool}}"
|
|
1056
440
|
referrer_count: "{{referrer_count}}"
|
|
1057
441
|
referrer_blast_radius: "{{referrer_names}}"
|
|
1058
|
-
|
|
1059
|
-
# Declared in the concept but absent on disk — advisory index drift, never gated.
|
|
1060
|
-
stale_source_files: "{{paths_missing}}"
|
|
442
|
+
okf_concept: "{{okf_concept}}"
|
|
1061
443
|
okf_index_ok: "{{okf_ok}}"
|
|
1062
444
|
okf_orphans: "{{okf_orphans}}"
|
|
1063
|
-
|
|
445
|
+
# Declared in the concept but absent on disk — advisory index drift, never gated.
|
|
446
|
+
stale_source_files: "{{paths_missing}}"
|
|
1064
447
|
active_change: "{{active_change}}"
|
|
1065
|
-
next: "CHANGE OPEN ({{active_change}}): /appweaver close-delta — the slice
|
|
448
|
+
next: "CHANGE OPEN ({{active_change}}): /appweaver close-delta — the slice is green, domain-conformant and did not break a referrer, and its delta is already merged into the master docs, so the change may now be archived and the version bumped. NO OPEN CHANGE: /appweaver run."
|