aw-spec-cli 0.1.21 → 0.1.22
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 +87 -8
- package/assets/.appweaver/orchestrator/modules/delta-plan.orch.yaml +30 -0
- package/assets/.appweaver/orchestrator/workflows/aw-spec-analyze-plan.orch.yaml +41 -8
- package/assets/.appweaver/orchestrator/workflows/aw-spec-analyze-slice-delta.orch.yaml +62 -2
- package/assets/.appweaver/orchestrator/workflows/aw-spec-analyze-slice.orch.yaml +18 -5
- package/assets/.appweaver/orchestrator/workflows/aw-spec-finalize-delta.orch.yaml +115 -27
- package/assets/.appweaver/orchestrator/workflows/aw-spec-implement.orch.yaml +225 -27
- package/assets/.appweaver/orchestrator/workflows/aw-spec-plan.orch.yaml +39 -0
- package/assets/.appweaver/orchestrator/workflows/aw-spec-recall-delta.orch.yaml +28 -7
- package/assets/.appweaver/orchestrator/workflows/aw-spec-specify.orch.yaml +100 -0
- package/assets/.appweaver/orchestrator/workflows/aw-spec-ui-model.orch.yaml +141 -0
- package/assets/.appweaver/orchestrator/workflows/aw-spec-ui-prototype.orch.yaml +386 -0
- package/assets/.appweaver/orchestrator/workflows/aw-spec-workflow-model.orch.yaml +135 -0
- package/assets/.appweaver/scripts/bash/aw-spec-actions.sh +190 -209
- package/assets/.appweaver/scripts/bash/aw-xref.sh +4 -1
- package/assets/.appweaver/scripts/powershell/aw-spec-actions.ps1 +182 -224
- package/assets/.appweaver/scripts/powershell/aw-xref.ps1 +4 -1
- package/assets/.appweaver/scripts/python/aw-crstate.py +127 -2
- package/assets/.appweaver/scripts/python/aw-gaps.py +119 -0
- package/assets/.appweaver/scripts/python/aw-payload-parity.py +17 -1
- package/assets/.appweaver/scripts/python/aw-plan-coverage.py +84 -4
- package/assets/.appweaver/scripts/python/aw-plangate.py +216 -0
- package/assets/.appweaver/scripts/python/aw-principles.py +108 -0
- package/assets/.appweaver/scripts/python/aw-stack.py +6 -0
- package/assets/.appweaver/scripts/python/aw-xref.py +141 -4
- package/assets/.appweaver/stack-profiles/angular.json +26 -0
- package/assets/.appweaver/stack-profiles/blazor-wasm.json +38 -0
- package/assets/.appweaver/stack-profiles/dotnet-webapi.json +38 -0
- package/assets/.appweaver/stack-profiles/java-spring.json +19 -0
- package/assets/.appweaver/stack-profiles/nextjs.json +26 -0
- package/assets/.appweaver/stack-profiles/node-express.json +26 -0
- package/assets/.appweaver/stack-profiles/python-fastapi.json +15 -0
- package/assets/.appweaver/stack-profiles/react-vite.json +26 -0
- package/assets/.appweaver/stack-profiles/sveltekit.json +26 -0
- package/assets/.appweaver/stack-profiles/vue-vite.json +26 -0
- package/assets/.appweaver/templates/ui-model-template.md +67 -0
- package/assets/.appweaver/templates/workflow-model-template.md +62 -0
- package/assets/guardrails/technology/dotnet-webapi/framework-api-map.md +44 -0
- package/package.json +1 -1
|
@@ -60,7 +60,7 @@
|
|
|
60
60
|
# risk of "fixing" the change's new tests back toward pre-change behaviour.
|
|
61
61
|
# 2. A red analyze-slice still lands on an OPEN change, so the remedy is "fix and
|
|
62
62
|
# re-run" rather than a NEW change to repair the one already shipped.
|
|
63
|
-
# The
|
|
63
|
+
# The regression fence below still guards the MERGE (a change that breaks a dependent or a co-owner
|
|
64
64
|
# must not reach the master docs); close-delta guards nothing — it is the bookkeeping.
|
|
65
65
|
#
|
|
66
66
|
# Prereqs: run /appweaver implement (answering it with THIS change), then build, then
|
|
@@ -89,7 +89,7 @@
|
|
|
89
89
|
# is one close-delta could never archive, so it must not reach the masters.
|
|
90
90
|
#
|
|
91
91
|
# THE MERGE FENCE — THREE REFUSALS, read off disk in one cr-merge-check call and placed
|
|
92
|
-
# before the
|
|
92
|
+
# before the regression fence, because they are free while that one runs a test suite:
|
|
93
93
|
#
|
|
94
94
|
# REBASE. The delta carries the master version it was authored against (`**Base version**:`,
|
|
95
95
|
# stamped by cr-setup). If the master has moved, the delta's MODIFIED items name a BEFORE
|
|
@@ -137,8 +137,8 @@
|
|
|
137
137
|
# =============================================================================
|
|
138
138
|
|
|
139
139
|
name: aw-spec-finalize-delta
|
|
140
|
-
description: Merge ONE chosen open change's delta-spec into the feature's spec.md and its model delta into the bounded context's domain-model.md — one aggregate section at a time, only the aggregates the delta names — in a single transaction, and append the spec's Change History row. ASKS which change (a bare CR id as the argument skips the prompt) and activates it, rather than taking whichever was last opened. Fenced by three hard refusals read off disk before anything is written — a moved base_version (rebase first), another change merged but not yet closed, and an open LOWER-wave predecessor — then by a SCOPED
|
|
141
|
-
version: 2.
|
|
140
|
+
description: Merge ONE chosen open change's delta-spec into the feature's spec.md and its model delta into the bounded context's domain-model.md — one aggregate section at a time, only the aggregates the delta names — in a single transaction, and append the spec's Change History row. ASKS which change (a bare CR id as the argument skips the prompt) and activates it, rather than taking whichever was last opened. Fenced by three hard refusals read off disk before anything is written — a moved base_version (rebase first), another change merged but not yet closed, and an open LOWER-wave predecessor — then by a SCOPED regression fence over the whole blast radius (fence_green) — the transitive REFERRER closure and the features that CO-OWN the aggregates this delta touches, which hold no edge to it but whose code is in the same files — writing a triage report and asking Abort/Override on red. Snapshots both masters to changes/<id>/pre-merge/ immediately before the rewrite. The lane plans are NOT merged — backend-plan.md and frontend-plan.md are derived from these two documents and are re-derived by /appweaver plan main. Leaves the change OPEN — analyze-slice runs next against the merged masters, and close-delta archives the change and bumps the version.
|
|
141
|
+
version: 2.5.0
|
|
142
142
|
agent_agnostic: true
|
|
143
143
|
dialect: aw-spec.orchestrator/v1
|
|
144
144
|
|
|
@@ -165,8 +165,16 @@ vars:
|
|
|
165
165
|
has_changes: "false" # from cr-list — the DIRECTORY's answer to "is anything open", not the ledger's
|
|
166
166
|
version: "" # the CURRENT version — unchanged by this stage
|
|
167
167
|
next_version: "" # what close-delta will bump to; the number the Change History rows carry
|
|
168
|
-
downstream_count: "0" # transitive + placeholder-filtered dependents
|
|
168
|
+
downstream_count: "0" # transitive + placeholder-filtered dependents THAT HAVE CODE; drives the gate
|
|
169
169
|
downstream_csv: "" # the blast-radius names, fed to the scoped fence's --also and shown to the human
|
|
170
|
+
unbuilt_count: "0" # dependants that are planned and not implemented: real, with nothing to re-test
|
|
171
|
+
unbuilt_csv: ""
|
|
172
|
+
reached_count: "0" # the whole closure — what this change reaches, built or not
|
|
173
|
+
co_owner_count: "0" # features that CO-OWN the aggregates this delta touches
|
|
174
|
+
co_owner_csv: "" # their names, fed to the same fence as a second --also
|
|
175
|
+
co_owner_aggs: "" # the aggregates the co-owner search was scoped to
|
|
176
|
+
co_owner_source: "" # `delta` (the change's own header) or `feature-owned` (the fallback)
|
|
177
|
+
blast_any: "" # truthy when EITHER half of the blast radius is non-empty
|
|
170
178
|
fence_ok: "true" # default green so the gate is a no-op when nothing downstream
|
|
171
179
|
gate_decision: "clean" # audit: 'clean' unless a RED fence was deliberately overridden
|
|
172
180
|
# The change's own `## Depends on` vs its wave — the fence that keeps the number and the
|
|
@@ -186,12 +194,13 @@ vars:
|
|
|
186
194
|
delta_model_exists: "false" # false ⇒ a behaviour-only change: the spec merge is the whole merge
|
|
187
195
|
model_orphan: "false" # a model delta whose context has no master to merge it into
|
|
188
196
|
model_master_ok: "true" # lowered by model_orphan_raise; the gate reads only this
|
|
189
|
-
# THE MERGE FENCE. All
|
|
197
|
+
# THE MERGE FENCE. All four flags default DOWN and are raised only by the good state, so
|
|
190
198
|
# a cr-merge-check that errored or a field that was renamed leaves the merge refused.
|
|
191
199
|
# Fail-closed is the only safe default in front of an in-place edit of the masters.
|
|
192
200
|
rebase_ok: "false"
|
|
193
201
|
merged_open_ok: "false"
|
|
194
202
|
no_blockers: "false"
|
|
203
|
+
wave_ordering_ok: "false"
|
|
195
204
|
rebase_needed: "true" # the raw readings, defaulted to the blocking value for the
|
|
196
205
|
has_merged_open: "true" # same reason — an unanswered question is not a clean answer
|
|
197
206
|
has_blockers: "true"
|
|
@@ -200,7 +209,11 @@ vars:
|
|
|
200
209
|
blocker_ids: ""
|
|
201
210
|
blocker_count: "0"
|
|
202
211
|
merged_open_ids: ""
|
|
203
|
-
|
|
212
|
+
wave_problem: "" # which changes could not be ordered, and why that ends the check
|
|
213
|
+
unordered_ids: ""
|
|
214
|
+
unordered_count: "0"
|
|
215
|
+
merge_wave: "" # EMPTY, not 1: an unreadable wave is not the floor, and the
|
|
216
|
+
# gate below refuses rather than letting it pass as one
|
|
204
217
|
snapshot_dir: "" # changes/<id>/pre-merge/ — the before-image recall-delta restores
|
|
205
218
|
snapshot_count: "0"
|
|
206
219
|
# THE OKF OVERVIEW'S SUBJECT. The Overview step selects a `## Aggregate:` section BY
|
|
@@ -416,6 +429,10 @@ workflow:
|
|
|
416
429
|
- { name: has_merged_open, from: "$.has_merged_open" }
|
|
417
430
|
- { name: merged_open_ids, from: "$.merged_open_ids" }
|
|
418
431
|
- { name: merge_wave, from: "$.wave" }
|
|
432
|
+
- { name: wave_ordering_ok, from: "$.wave_ordering_ok" }
|
|
433
|
+
- { name: wave_problem, from: "$.wave_problem" }
|
|
434
|
+
- { name: unordered_ids, from: "$.unordered_ids" }
|
|
435
|
+
- { name: unordered_count, from: "$.unordered_count" }
|
|
419
436
|
|
|
420
437
|
- id: rebase_ok_raise
|
|
421
438
|
condition: "{{rebase_needed}} == false"
|
|
@@ -435,7 +452,21 @@ workflow:
|
|
|
435
452
|
action: verify_context
|
|
436
453
|
require_true: merged_open_ok
|
|
437
454
|
on_false: stop
|
|
438
|
-
on_false_message: "finalize-delta REFUSED —
|
|
455
|
+
on_false_message: "finalize-delta REFUSED — a change has already been MERGED into a master but not yet CLOSED, so the masters carry it while the version still reads {{current_version}}: {{merged_open_ids}}. The feature named beside it is where it lives — domain-model.md is shared, so a SIBLING feature's merge moves a master this delta was authored against, and it is counted here when it touched an aggregate this delta also names. Change {{active_change}} was authored against those pre-merge masters and the version comparison cannot see the difference. Finish the merged change first, under ITS OWN feature: select that feature (/appweaver select-feature), then /appweaver analyze-slice and /appweaver close-delta on it, which bumps the version — then rebase this one against the new number and re-run /appweaver finalize-delta {{active_change}}."
|
|
456
|
+
|
|
457
|
+
# WAVE ORDERING IS A PRECONDITION OF THE FENCE BELOW, not a finding of it. The predecessor
|
|
458
|
+
# test is `their wave < mine`, and a wave that cannot be read used to answer that question
|
|
459
|
+
# as 1 — the floor — so an unstamped delta posed as a predecessor to everything above it,
|
|
460
|
+
# and an unstamped SUBJECT compared against nothing at all and sailed through. Neither
|
|
461
|
+
# showed up as a refusal, because both look exactly like "no blockers found".
|
|
462
|
+
# It is narrow by construction: nothing sits below the floor, so a change AT wave 1 is
|
|
463
|
+
# never held up by a neighbour nobody stamped. Above it, the fence says so instead of
|
|
464
|
+
# guessing.
|
|
465
|
+
- id: require_wave_ordering
|
|
466
|
+
action: verify_context
|
|
467
|
+
require_true: wave_ordering_ok
|
|
468
|
+
on_false: stop
|
|
469
|
+
on_false_message: "finalize-delta REFUSED — the wave fence cannot order change {{active_change}}, so it cannot tell you whether a predecessor is still open: {{wave_problem}}. A wave is stamped by a script and read by both merge gates; `**Wave**: [N]` is the unfilled template line, which means the stamp never ran on that document. Stamp each one — `.appweaver/scripts/bash/aw-spec-actions.sh cr-wave-derive --cr-id <CR-id> --stamp` derives the wave from that change's own `## Depends on` section and writes it — then re-run /appweaver finalize-delta {{active_change}}. A change in another feature is stamped under that feature (/appweaver select-feature first)."
|
|
439
470
|
|
|
440
471
|
- id: no_blockers_raise
|
|
441
472
|
condition: "{{has_blockers}} == false"
|
|
@@ -445,7 +476,7 @@ workflow:
|
|
|
445
476
|
action: verify_context
|
|
446
477
|
require_true: no_blockers
|
|
447
478
|
on_false: stop
|
|
448
|
-
on_false_message: "finalize-delta REFUSED — change {{active_change}} is at wave {{merge_wave}} and {{blocker_count}} open change(s) sit at a LOWER wave
|
|
479
|
+
on_false_message: "finalize-delta REFUSED — change {{active_change}} is at wave {{merge_wave}} and {{blocker_count}} open change(s) sit at a LOWER wave. A lower wave is committed to landing FIRST, and this delta was planned with those in its context as the base it builds on — merging it now folds in behaviour that assumes a predecessor the masters do not yet carry. THE LOWER-WAVE CHANGES: {{blocker_ids}}. This scan is context-wide, so one of them may belong to a feature you have never opened — and finalize-delta resolves a change under the ACTIVE feature. Select the feature named beside a change (/appweaver select-feature) before running /appweaver finalize-delta <CR-id> → analyze-slice → close-delta on it; then rebase and re-run this one. Same-wave changes are independent and are not counted here; if this delta does NOT in fact build on them, correct its `## Depends on` section (naming only the deltas it truly builds on) and re-run /appweaver specify's wave derivation — `.appweaver/scripts/bash/aw-spec-actions.sh cr-wave-derive --cr-id {{active_change}} --stamp` applies it directly."
|
|
449
480
|
|
|
450
481
|
# THE DECLARED DEPENDENCIES AND THE WAVE MUST AGREE. The fence above orders changes by
|
|
451
482
|
# their wave NUMBER; this one checks that number against what the change's own documents
|
|
@@ -472,15 +503,21 @@ workflow:
|
|
|
472
503
|
# its OKF Cross-References, TRANSITIVELY (C→B→A all count) and placeholder-filtered
|
|
473
504
|
# (the "_(none observed)_" row is NOT a dependent) = the real blast radius. If any
|
|
474
505
|
# slice does, this change could ripple into it, so run a SCOPED regression fence over
|
|
475
|
-
# this feature + its
|
|
506
|
+
# this feature + its blast radius (--scope slice --also <referrers> --also <co-owners>) BEFORE the
|
|
476
507
|
# doc merge, so a block leaves the repo untouched. The fence binds fence_GREEN (ran
|
|
477
508
|
# AND matched >=1), not raw ok, so an empty / zero-match run is RED, never a vacuous
|
|
478
509
|
# pass. If RED we do NOT hard-stop blindly: we WRITE a triage report, then surface the
|
|
479
|
-
# failing log +
|
|
510
|
+
# failing log + affected slices and ASK the developer — Abort (a real downstream
|
|
480
511
|
# break: fix it first) or, having reviewed the log (pre-existing / flaky / unrelated),
|
|
481
512
|
# deliberately Override and close anyway. Non-interactive / CI runs take the FIRST
|
|
482
513
|
# option (Abort), so automation never silently overrides. Skipped when nothing depends
|
|
483
|
-
# on this slice
|
|
514
|
+
# on this slice and nothing co-owns its aggregates, or the fence is green.
|
|
515
|
+
# THE FENCE RUNS TESTS, so it takes the BUILT half of the closure. Edges are read off
|
|
516
|
+
# the lane PLAN, not off code, so a dependant can be fully planned and hold none:
|
|
517
|
+
# selecting it would hand the fence a slice with no tests, and the fence counts a
|
|
518
|
+
# zero-match run as RED. An unbuilt dependant is still reported — it is a real
|
|
519
|
+
# dependant with nothing to re-test yet, which is a different thing from being
|
|
520
|
+
# unaffected, and it is what /appweaver implement on that feature will settle.
|
|
484
521
|
- id: xref_impact
|
|
485
522
|
action: execute_script
|
|
486
523
|
on_error: continue
|
|
@@ -488,16 +525,49 @@ workflow:
|
|
|
488
525
|
subcommand: list
|
|
489
526
|
args: ["--feature-dir", "{{feature_dir}}"]
|
|
490
527
|
outputs:
|
|
491
|
-
- { name: downstream_count, from: "$.
|
|
492
|
-
- { name: downstream_csv, from: "$.
|
|
528
|
+
- { name: downstream_count, from: "$.built_count" } # transitive, placeholder-filtered, HAS CODE
|
|
529
|
+
- { name: downstream_csv, from: "$.built_closure_csv" } # blast-radius names → --also + display
|
|
530
|
+
- { name: unbuilt_count, from: "$.unbuilt_count" } # dependants planned but never implemented
|
|
531
|
+
- { name: unbuilt_csv, from: "$.unbuilt_closure_csv" }
|
|
532
|
+
- { name: reached_count, from: "$.referrer_closure_count" } # the whole closure, for the report
|
|
533
|
+
|
|
534
|
+
# THE OTHER HALF OF THE BLAST RADIUS. A referrer reaches this aggregate through an edge;
|
|
535
|
+
# a CO-OWNER has no edge to it because it is not a user of the aggregate — it is one of
|
|
536
|
+
# the capabilities the aggregate is made of, and its code is in the very files this merge
|
|
537
|
+
# rewrites. `Encounter.cs` is extended by every feature claiming Encounter, so a change to
|
|
538
|
+
# it can break a co-owner while every referrer still passes. Scoped to the aggregates THIS
|
|
539
|
+
# delta names, so a feature owning two aggregates does not drag the second one's co-owners
|
|
540
|
+
# through a fence they cannot have been affected by.
|
|
541
|
+
- id: xref_co_owners
|
|
542
|
+
action: execute_script
|
|
543
|
+
on_error: continue
|
|
544
|
+
script: { ref: xref }
|
|
545
|
+
subcommand: co-owners
|
|
546
|
+
args: ["--cr", "{{active_change}}", "--feature-dir", "{{feature_dir}}"]
|
|
547
|
+
outputs:
|
|
548
|
+
- { name: co_owner_count, from: "$.count" }
|
|
549
|
+
- { name: co_owner_csv, from: "$.features_csv" }
|
|
550
|
+
- { name: co_owner_aggs, from: "$.aggregates_csv" }
|
|
551
|
+
- { name: co_owner_source, from: "$.source" }
|
|
552
|
+
|
|
553
|
+
# The fence runs when EITHER half is non-empty. Two ordered assignments rather than one
|
|
554
|
+
# condition, because the dialect has no compound conditions.
|
|
555
|
+
- id: blast_from_referrers
|
|
556
|
+
condition: "{{downstream_count}} != 0"
|
|
557
|
+
action: set
|
|
558
|
+
vars: { blast_any: "true" }
|
|
559
|
+
- id: blast_from_co_owners
|
|
560
|
+
condition: "{{co_owner_count}} != 0"
|
|
561
|
+
action: set
|
|
562
|
+
vars: { blast_any: "true" }
|
|
493
563
|
|
|
494
564
|
- id: run_downstream_fence
|
|
495
|
-
condition: "{{
|
|
565
|
+
condition: "{{blast_any}}"
|
|
496
566
|
action: execute_script
|
|
497
567
|
on_error: continue
|
|
498
568
|
script: { ref: actions }
|
|
499
569
|
subcommand: test-run
|
|
500
|
-
args: ["--feature-dir", "{{feature_dir}}", "--scope", "slice", "--also", "{{downstream_csv}}"]
|
|
570
|
+
args: ["--feature-dir", "{{feature_dir}}", "--scope", "slice", "--also", "{{downstream_csv}}", "--also", "{{co_owner_csv}}"]
|
|
501
571
|
outputs:
|
|
502
572
|
- { name: fence_ok, from: "$.fence_green" }
|
|
503
573
|
- { name: fence_tool, from: "$.tool" }
|
|
@@ -511,11 +581,14 @@ workflow:
|
|
|
511
581
|
# only when nothing depends on this slice (no fence ran, nothing to report).
|
|
512
582
|
- id: ctx_broken_downstream
|
|
513
583
|
action: build_context
|
|
514
|
-
condition: "{{
|
|
584
|
+
condition: "{{blast_any}}"
|
|
515
585
|
vars:
|
|
516
586
|
active_change: "{{active_change}}"
|
|
517
587
|
downstream_count: "{{downstream_count}}"
|
|
518
588
|
downstream_csv: "{{downstream_csv}}"
|
|
589
|
+
co_owner_count: "{{co_owner_count}}"
|
|
590
|
+
co_owner_csv: "{{co_owner_csv}}"
|
|
591
|
+
co_owner_aggs: "{{co_owner_aggs}}"
|
|
519
592
|
fence_ok: "{{fence_ok}}"
|
|
520
593
|
fence_log: "{{fence_log}}"
|
|
521
594
|
context:
|
|
@@ -526,14 +599,27 @@ workflow:
|
|
|
526
599
|
- { path: "{{delta_backend_plan}}", optional: true }
|
|
527
600
|
- id: write_broken_downstream
|
|
528
601
|
action: agent_author
|
|
529
|
-
condition: "{{
|
|
602
|
+
condition: "{{blast_any}}"
|
|
530
603
|
include_standards: false # a triage report, not generated code
|
|
531
604
|
output_target: { type: file, path: "{{feature_dir}}/changes/{{active_change}}/broken-downstream.md" }
|
|
532
605
|
task: |
|
|
533
606
|
Author the DOWNSTREAM report for change {{active_change}}: the result of re-running this
|
|
534
|
-
change against
|
|
535
|
-
downstream slice (that is the downstream slice's own job).
|
|
536
|
-
|
|
607
|
+
change against everything it could have broken. finalize-delta does NOT fix a
|
|
608
|
+
downstream slice (that is the downstream slice's own job).
|
|
609
|
+
THE BLAST RADIUS HAS TWO HALVES and they fail for different reasons — say which is which
|
|
610
|
+
wherever the report names a slice:
|
|
611
|
+
- DEPENDENTS ({{downstream_count}}): {{downstream_csv}} — aggregates that USE this one
|
|
612
|
+
through a Cross-Reference edge. A failure here is a broken CONTRACT between two slices.
|
|
613
|
+
- NOT YET BUILT ({{unbuilt_count}}): {{unbuilt_csv}} — aggregates that also depend on this
|
|
614
|
+
one and hold no code yet, so the fence had nothing to run for them. Edges come from the
|
|
615
|
+
lane PLAN, so these are real dependants whose contract with this aggregate has never
|
|
616
|
+
been exercised. Say so plainly: they were NOT tested, which is not the same as passing,
|
|
617
|
+
and /appweaver implement on those features is what settles them.
|
|
618
|
+
- CO-OWNERS ({{co_owner_count}}): {{co_owner_csv}} — features that share the aggregate(s)
|
|
619
|
+
this change touches ({{co_owner_aggs}}). They hold no edge to it: their code is IN the
|
|
620
|
+
files this merge rewrites, so a failure here is this change breaking a sibling
|
|
621
|
+
capability of the same aggregate, not a contract between two of them.
|
|
622
|
+
Either list may be empty. The fence result was fence_green={{fence_ok}}
|
|
537
623
|
(true = every downstream test passed; false = at least one failed). Test log:
|
|
538
624
|
{{fence_log}}
|
|
539
625
|
Always write the file (it is regenerated on every finalize-delta run so a green close never
|
|
@@ -541,8 +627,9 @@ workflow:
|
|
|
541
627
|
|
|
542
628
|
IF fence_green is TRUE (all passed): write a SHORT all-clear — the heading
|
|
543
629
|
`# Broken Downstream — change {{active_change}}`, then a few lines stating that the
|
|
544
|
-
{{downstream_count}} slice(s)
|
|
545
|
-
this change and all passed, so nothing
|
|
630
|
+
{{downstream_count}} dependent slice(s) ({{downstream_csv}}) and {{co_owner_count}} co-owner
|
|
631
|
+
feature(s) ({{co_owner_csv}}) were re-run against this change and all passed, so nothing it
|
|
632
|
+
could reach broke. No per-slice sections; invent nothing.
|
|
546
633
|
|
|
547
634
|
IF fence_green is FALSE (something failed): write the triage record —
|
|
548
635
|
- `# Broken Downstream — change {{active_change}}` and a one-line statement: aggregates that
|
|
@@ -550,10 +637,11 @@ workflow:
|
|
|
550
637
|
finalize-delta's downstream gate. Note it is the record a human reads while deciding Abort vs
|
|
551
638
|
Override, and if the change is Overridden it is archived with the change as the record of
|
|
552
639
|
what was knowingly closed over.
|
|
553
|
-
- A SUMMARY line: total
|
|
554
|
-
- One `##` section per
|
|
555
|
-
slice by matching the failing test names in the log to the slice's name
|
|
556
|
-
|
|
640
|
+
- A SUMMARY line: total slices in the blast radius (dependents + co-owners), and how many have a failing test.
|
|
641
|
+
- One `##` section per slice with a failing test, from EITHER half — attribute a failure to a
|
|
642
|
+
slice by matching the failing test names in the log to the slice's name, and label the
|
|
643
|
+
section `dependent` or `co-owner`. Under it, on their
|
|
644
|
+
own labelled lines: the aggregate or feature, the failing test(s) named in the log, what
|
|
557
645
|
broke (as far as the log shows), and a RESOLUTION line — either this change broke the
|
|
558
646
|
downstream slice's expected contract (fix it in the downstream slice's OWN CR, or re-baseline
|
|
559
647
|
its golden-master) or the failure is pre-existing / flaky / unrelated (a candidate for a
|