@windyroad/itil 0.61.1 → 0.61.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (171) hide show
  1. package/.claude-plugin/plugin.json +1 -1
  2. package/package.json +7 -2
  3. package/agents/test/fixtures/proceed-new-genuinely-new.md +0 -43
  4. package/agents/test/fixtures/proceed-new-subtle-sibling.md +0 -47
  5. package/agents/test/fixtures/regression-p347-vs-p346.md +0 -54
  6. package/agents/test/hang-off-check.bats +0 -225
  7. package/hooks/test/block-list.bats +0 -153
  8. package/hooks/test/command-detect.bats +0 -181
  9. package/hooks/test/itil-assistant-output-gate.bats +0 -114
  10. package/hooks/test/itil-assistant-output-review.bats +0 -224
  11. package/hooks/test/itil-bash-polling-antipattern-detect.bats +0 -154
  12. package/hooks/test/itil-changeset-discipline.bats +0 -603
  13. package/hooks/test/itil-claude-space-protection.bats +0 -294
  14. package/hooks/test/itil-commit-trailer-transition-advisory.bats +0 -80
  15. package/hooks/test/itil-correction-detect.bats +0 -189
  16. package/hooks/test/itil-deferral-cadence-gate.bats +0 -187
  17. package/hooks/test/itil-fictional-defer-detect.bats +0 -292
  18. package/hooks/test/itil-fix-title-lifecycle-advisory.bats +0 -129
  19. package/hooks/test/itil-mid-loop-ask-detect.bats +0 -220
  20. package/hooks/test/itil-no-implement-draft-gate.bats +0 -210
  21. package/hooks/test/itil-pending-questions-surface.bats +0 -307
  22. package/hooks/test/itil-readme-refresh-discipline.bats +0 -642
  23. package/hooks/test/itil-rfc-oversight-nudge.bats +0 -83
  24. package/hooks/test/itil-rfc-trailer-advisory.bats +0 -375
  25. package/hooks/test/itil-story-mirror-migration-nudge.bats +0 -122
  26. package/hooks/test/manage-problem-enforce-create.bats +0 -424
  27. package/hooks/test/p057-staging-trap-detect.bats +0 -231
  28. package/hooks/test/pre-publish-intake-gate.bats +0 -144
  29. package/hooks/test/runtime-sid-marker.bats +0 -90
  30. package/hooks/test/session-id.bats +0 -370
  31. package/scripts/migrate-problems-add-type.sh +0 -116
  32. package/scripts/test/catchup-scan.bats +0 -274
  33. package/scripts/test/check-afk-accept-eligible.bats +0 -310
  34. package/scripts/test/check-fail-soft-skip-discipline.bats +0 -172
  35. package/scripts/test/check-fix-rfc-trace.bats +0 -164
  36. package/scripts/test/check-locale-discipline.bats +0 -291
  37. package/scripts/test/check-problems-readme-budget.bats +0 -192
  38. package/scripts/test/check-rfc-has-stories.bats +0 -69
  39. package/scripts/test/check-rfc-rejected-alternatives.bats +0 -108
  40. package/scripts/test/check-rfc-stories-ratified.bats +0 -82
  41. package/scripts/test/check-upstream-responses.bats +0 -503
  42. package/scripts/test/classify-readme-drift.bats +0 -392
  43. package/scripts/test/derive-first-dispatch.bats +0 -274
  44. package/scripts/test/derive-release-vehicle.bats +0 -454
  45. package/scripts/test/detect-unratified-stories-maps.bats +0 -60
  46. package/scripts/test/dual-tolerant-glob-rfc-002-t2.bats +0 -309
  47. package/scripts/test/effort-tally.bats +0 -170
  48. package/scripts/test/evaluate-relevance.bats +0 -773
  49. package/scripts/test/kind-a-commands.bats +0 -46
  50. package/scripts/test/mark-create-gate.bats +0 -59
  51. package/scripts/test/mark-story-oversight-confirmed.bats +0 -53
  52. package/scripts/test/migrate-problems-add-type.bats +0 -280
  53. package/scripts/test/migrate-story-status-mirror.bats +0 -167
  54. package/scripts/test/no-type-regression-guard.bats +0 -74
  55. package/scripts/test/oversight-mirror-corpus-lint.bats +0 -150
  56. package/scripts/test/plugin-exercise-index.bats +0 -386
  57. package/scripts/test/plugin-maturity-doc-lint.bats +0 -470
  58. package/scripts/test/plugin-maturity-populate.bats +0 -631
  59. package/scripts/test/plugin-maturity-render.bats +0 -469
  60. package/scripts/test/plugin-validate-ci-gate.bats +0 -208
  61. package/scripts/test/reconcile-readme.bats +0 -1007
  62. package/scripts/test/reconcile-rfcs.bats +0 -496
  63. package/scripts/test/reconcile-stories.bats +0 -173
  64. package/scripts/test/reconcile-story-maps.bats +0 -74
  65. package/scripts/test/release-watch-poll-loop.bats +0 -180
  66. package/scripts/test/resolve-governance-plugin-dirs.bats +0 -78
  67. package/scripts/test/rfc-stories-extension.bats +0 -175
  68. package/scripts/test/skill-invocations.bats +0 -535
  69. package/scripts/test/skill-md-dual-tolerant-coverage-rfc-002-t3.bats +0 -374
  70. package/scripts/test/story-oversight-lib.bats +0 -190
  71. package/scripts/test/update-jtbd-references-related-problems.bats +0 -178
  72. package/scripts/test/update-problem-references-section.bats +0 -242
  73. package/scripts/test/update-problem-rfcs-section.bats +0 -242
  74. package/scripts/test/update-references-section-sibling-helpers.bats +0 -80
  75. package/scripts/test/update-rfc-commits-section.bats +0 -77
  76. package/scripts/test/verify-iter-summary.bats +0 -196
  77. package/scripts/test/working-the-problem-traversal.bats +0 -116
  78. package/skills/capture-problem/test/capture-problem-step-1-5b-jtbd-trace.bats +0 -398
  79. package/skills/capture-problem/test/capture-problem.bats +0 -389
  80. package/skills/capture-story/test/capture-story-behavioural.bats +0 -317
  81. package/skills/capture-story-map/test/capture-story-map-behavioural.bats +0 -98
  82. package/skills/close-incident/test/close-incident-contract.bats +0 -146
  83. package/skills/link-incident/test/link-incident-contract.bats +0 -125
  84. package/skills/list-incidents/test/list-incidents-contract.bats +0 -115
  85. package/skills/list-problems/test/list-problems-contract.bats +0 -100
  86. package/skills/list-stories/test/list-stories-contract.bats +0 -127
  87. package/skills/list-story-maps/test/list-story-maps-contract.bats +0 -46
  88. package/skills/manage-incident/test/manage-incident-adr-044-contract.bats +0 -206
  89. package/skills/manage-incident/test/manage-incident-close-forwarder.bats +0 -67
  90. package/skills/manage-incident/test/manage-incident-link-forwarder.bats +0 -67
  91. package/skills/manage-incident/test/manage-incident-list-forwarder.bats +0 -68
  92. package/skills/manage-incident/test/manage-incident-mitigate-forwarder.bats +0 -66
  93. package/skills/manage-incident/test/manage-incident-restore-forwarder.bats +0 -66
  94. package/skills/manage-incident/test/manage-incident.bats +0 -171
  95. package/skills/manage-problem/test/manage-problem-adr-044-step4-derive-first.bats +0 -151
  96. package/skills/manage-problem/test/manage-problem-auto-migrate-step.bats +0 -53
  97. package/skills/manage-problem/test/manage-problem-concern-boundary.bats +0 -64
  98. package/skills/manage-problem/test/manage-problem-effort-buckets.bats +0 -56
  99. package/skills/manage-problem/test/manage-problem-external-root-cause-detection.bats +0 -119
  100. package/skills/manage-problem/test/manage-problem-first-run-intake-prompt.bats +0 -43
  101. package/skills/manage-problem/test/manage-problem-git-mv-restage-reminder.bats +0 -48
  102. package/skills/manage-problem/test/manage-problem-id-collision-guard.bats +0 -39
  103. package/skills/manage-problem/test/manage-problem-list-forwarder.bats +0 -66
  104. package/skills/manage-problem/test/manage-problem-next-id-origin-lookup.bats +0 -50
  105. package/skills/manage-problem/test/manage-problem-no-prose-options.bats +0 -74
  106. package/skills/manage-problem/test/manage-problem-output-formatting.bats +0 -30
  107. package/skills/manage-problem/test/manage-problem-parked-and-cache.bats +0 -73
  108. package/skills/manage-problem/test/manage-problem-readme-refresh-on-transition.bats +0 -62
  109. package/skills/manage-problem/test/manage-problem-readme-tie-break-order.bats +0 -318
  110. package/skills/manage-problem/test/manage-problem-readme-vq-sort-order.bats +0 -206
  111. package/skills/manage-problem/test/manage-problem-release-vehicle-seed.bats +0 -83
  112. package/skills/manage-problem/test/manage-problem-review-forwarder.bats +0 -71
  113. package/skills/manage-problem/test/manage-problem-step-9d-recovery-path.bats +0 -97
  114. package/skills/manage-problem/test/manage-problem-transition-forwarder.bats +0 -96
  115. package/skills/manage-problem/test/manage-problem-transitive-dependencies.bats +0 -365
  116. package/skills/manage-problem/test/manage-problem-verification-detection.bats +0 -64
  117. package/skills/manage-problem/test/manage-problem-verification-pending.bats +0 -114
  118. package/skills/manage-problem/test/manage-problem-work-forwarder.bats +0 -88
  119. package/skills/manage-story/test/manage-story-contract.bats +0 -174
  120. package/skills/manage-story-map/test/manage-story-map-contract.bats +0 -63
  121. package/skills/mitigate-incident/test/mitigate-incident-contract.bats +0 -258
  122. package/skills/reconcile-readme/test/reconcile-readme-contract.bats +0 -201
  123. package/skills/report-upstream/test/report-upstream-contract.bats +0 -394
  124. package/skills/restore-incident/test/restore-incident-contract.bats +0 -170
  125. package/skills/review-problems/test/inbound-channels-cache-shape.bats +0 -127
  126. package/skills/review-problems/test/inbound-discovery-contract.bats +0 -383
  127. package/skills/review-problems/test/jtbd-301-verdict-shape-contract.bats +0 -225
  128. package/skills/review-problems/test/review-problems-contract.bats +0 -235
  129. package/skills/review-problems/test/review-problems-likely-verified-cell-shape.bats +0 -229
  130. package/skills/scaffold-intake/test/scaffold-intake-contract.bats +0 -126
  131. package/skills/scaffold-intake/test/scaffold-intake-fixture.bats +0 -164
  132. package/skills/scaffold-intake/test/scaffold-intake-secrets-absent.bats +0 -87
  133. package/skills/transition-problem/test/transition-problem-contract.bats +0 -285
  134. package/skills/transition-problems/test/transition-problems-contract.bats +0 -331
  135. package/skills/update-upstream/test/update-upstream-contract.bats +0 -375
  136. package/skills/work-problem/test/work-problem-contract.bats +0 -294
  137. package/skills/work-problems/test/work-problems-above-appetite-remediation.bats +0 -139
  138. package/skills/work-problems/test/work-problems-adr-013-rule-6-p352-amendment.bats +0 -166
  139. package/skills/work-problems/test/work-problems-auto-migrate-step.bats +0 -57
  140. package/skills/work-problems/test/work-problems-cost-logging.bats +0 -109
  141. package/skills/work-problems/test/work-problems-deviation-candidate-shape.bats +0 -121
  142. package/skills/work-problems/test/work-problems-first-run-intake-prompt.bats +0 -36
  143. package/skills/work-problems/test/work-problems-inter-iteration-verify.bats +0 -59
  144. package/skills/work-problems/test/work-problems-mid-loop-userpromptsubmit-handler.bats +0 -69
  145. package/skills/work-problems/test/work-problems-no-mid-loop-asking.bats +0 -192
  146. package/skills/work-problems/test/work-problems-p341-pre-all-done-gate.bats +0 -122
  147. package/skills/work-problems/test/work-problems-p342-r007-derive-then-pass-flags.bats +0 -170
  148. package/skills/work-problems/test/work-problems-p342-retro-auto-ticket-carveout.bats +0 -120
  149. package/skills/work-problems/test/work-problems-preflight-failure-handling.bats +0 -248
  150. package/skills/work-problems/test/work-problems-preflight-session-continuity.bats +0 -139
  151. package/skills/work-problems/test/work-problems-preflight.bats +0 -69
  152. package/skills/work-problems/test/work-problems-release-cadence.bats +0 -63
  153. package/skills/work-problems/test/work-problems-step-0-iter-error-staleness.bats +0 -93
  154. package/skills/work-problems/test/work-problems-step-0b-cache-staleness-behavioural.bats +0 -138
  155. package/skills/work-problems/test/work-problems-step-0c-deferred-placeholder-staleness-behavioural.bats +0 -238
  156. package/skills/work-problems/test/work-problems-step-0d-outbound-responses-staleness-behavioural.bats +0 -174
  157. package/skills/work-problems/test/work-problems-step-2-5-routing.bats +0 -80
  158. package/skills/work-problems/test/work-problems-step-2-5b-cross-halt-routing.bats +0 -149
  159. package/skills/work-problems/test/work-problems-step-3-5-jtbd-ratification-predicate.bats +0 -191
  160. package/skills/work-problems/test/work-problems-step-5-bats-polling-discipline.bats +0 -91
  161. package/skills/work-problems/test/work-problems-step-5-delegation.bats +0 -333
  162. package/skills/work-problems/test/work-problems-step-5-idle-timeout-sigterm.bats +0 -421
  163. package/skills/work-problems/test/work-problems-step-5-is-error-transient-halt.bats +0 -278
  164. package/skills/work-problems/test/work-problems-step-5-iter-changeset-required.bats +0 -95
  165. package/skills/work-problems/test/work-problems-step-5-prompt-body-re-grounding.bats +0 -128
  166. package/skills/work-problems/test/work-problems-step-5-stream-timeout-salvage.bats +0 -251
  167. package/skills/work-problems/test/work-problems-step-6-5-always-drain.bats +0 -203
  168. package/skills/work-problems/test/work-problems-step-6-5-cache-refresh-chain.bats +0 -174
  169. package/skills/work-problems/test/work-problems-step-6-5-fix-and-continue.bats +0 -254
  170. package/skills/work-problems/test/work-problems-step-6-5-postrelease-kv-callback.bats +0 -209
  171. package/skills/work-problems/test/work-problems-stop-condition-questions.bats +0 -85
@@ -1,496 +0,0 @@
1
- #!/usr/bin/env bats
2
-
3
- # @problem P170 — docs/rfcs/README.md needs a sibling drift-detector to
4
- # reconcile-readme.sh once `/wr-itil:capture-rfc` and `/wr-itil:manage-rfc`
5
- # start writing RFC files. P170 Slice 3 task B5.T6 ships this script;
6
- # B5.T7 ships the `wr-itil-reconcile-rfcs` $PATH shim per ADR-049.
7
- #
8
- # Contract: `reconcile-rfcs.sh [<rfcs-dir>]` is a diagnose-only mechanical
9
- # drift detector. It reads `<rfcs-dir>/RFC-<NNN>-*.<status>.md` files
10
- # (default `docs/rfcs`), parses the WSJF Rankings + Verification Queue
11
- # + Closed tables in `<rfcs-dir>/README.md`, and reports each
12
- # disagreement between README claim and filesystem ground truth.
13
- #
14
- # Exit codes:
15
- # 0 = clean (README matches filesystem for every parsed row)
16
- # 1 = drift detected (structured diff to stdout, one row per drift)
17
- # 2 = parse error (README missing or malformed beyond recovery)
18
- #
19
- # Drift line format per ADR-038 progressive-disclosure budget (≤150 bytes/row):
20
- # DRIFT RFC-<NNN> wsjf-rankings: claims=open actual=<status>
21
- # MISSING RFC-<NNN> wsjf-rankings: actual=<status>
22
- # STALE RFC-<NNN> verification-queue: actual=<status>
23
- # MISMATCH RFC-<NNN> closed: actual=<status>
24
- #
25
- # Sibling to packages/itil/scripts/reconcile-readme.sh (P118) — same
26
- # parse + diff structure applied at the RFC tier instead of the
27
- # problems tier.
28
- #
29
- # @jtbd JTBD-008 (Decompose a Fix Into Coordinated Changes — RFC ranking
30
- # integrity supports the capture-time decomposition surface)
31
- # @jtbd JTBD-006 (Progress the Backlog While I'm Away — orchestrators
32
- # composing with RFC-level WSJF rankings need them to match disk truth)
33
- #
34
- # Cross-reference:
35
- # P170: docs/problems/170-...open.md
36
- # ADR-060 (Problem-RFC-Story framework — Phase 1 item 5)
37
- # ADR-049 (Plugin script resolution via bin/ on PATH — paired bin shim)
38
- # ADR-005 — Plugin testing strategy (script-level bats governance)
39
-
40
- setup() {
41
- SCRIPTS_DIR="$(cd "$(dirname "$BATS_TEST_FILENAME")/.." && pwd)"
42
- SCRIPT="$SCRIPTS_DIR/reconcile-rfcs.sh"
43
- FIXTURE_DIR="$(mktemp -d)"
44
- PROBLEMS_DIR="$(mktemp -d)"
45
- }
46
-
47
- teardown() {
48
- rm -rf "$FIXTURE_DIR" "$PROBLEMS_DIR"
49
- }
50
-
51
- # Helper: write a minimal valid RFC README to fixture dir.
52
- write_minimal_readme() {
53
- local body="$1"
54
- cat > "$FIXTURE_DIR/README.md" <<EOF
55
- # RFC Backlog
56
-
57
- > Last reviewed: 2026-05-05
58
-
59
- ## Status
60
-
61
- (intro)
62
-
63
- ## RFC Rankings
64
-
65
- | WSJF | ID | Title | Severity | Status | Effort | Reported |
66
- |------|-----|-------|----------|--------|--------|----------|
67
- ${body}
68
-
69
- ## Verification Queue
70
-
71
- | ID | Title | Released | Verification check |
72
- |----|-------|----------|--------------------|
73
-
74
- ## Closed
75
-
76
- | ID | Title | Closed | Driving problems |
77
- |----|-------|--------|------------------|
78
- EOF
79
- }
80
-
81
- # Helper: write an RFC ticket file with the given status suffix.
82
- # Optional 4th arg overrides the `problems:` list (default `[P168]`).
83
- write_rfc() {
84
- local id="$1" slug="$2" status="$3"
85
- local problems="${4:-[P168]}"
86
- cat > "$FIXTURE_DIR/RFC-${id}-${slug}.${status}.md" <<EOF
87
- ---
88
- status: ${status}
89
- rfc-id: ${slug}
90
- reported: 2026-05-05
91
- decision-makers: [test]
92
- problems: ${problems}
93
- ---
94
-
95
- # RFC-${id}: ${slug}
96
-
97
- stub
98
- EOF
99
- }
100
-
101
- # Helper: write a problem ticket file with optional `## RFCs` table rows.
102
- # Args: <pid-num> <slug> <status> <rfcs-rows-block>
103
- # rfcs-rows-block is the markdown rows (already pipe-formatted) inserted under
104
- # the `## RFCs` table header — pass an empty string to omit the section
105
- # entirely (lazy-empty discipline per JTBD-101 atomic-fix-adopter friction guard).
106
- write_problem() {
107
- local num="$1" slug="$2" status="$3" rfcs_rows="${4:-}"
108
- local file="$PROBLEMS_DIR/${num}-${slug}.${status}.md"
109
- cat > "$file" <<EOF
110
- # Problem ${num}: ${slug}
111
-
112
- **Status**: ${status}
113
-
114
- ## Description
115
-
116
- stub
117
-
118
- ## Related
119
-
120
- stub
121
- EOF
122
- if [ -n "$rfcs_rows" ]; then
123
- cat >> "$file" <<EOF
124
-
125
- ## RFCs
126
-
127
- | RFC | Status | Title |
128
- |-----|--------|-------|
129
- ${rfcs_rows}
130
- EOF
131
- fi
132
- }
133
-
134
- # Helper: write a problem ticket under the per-state subdir layout per
135
- # ADR-031 (state is the parent directory; filename has NO `.state.md` suffix).
136
- # Args: <pid-num> <slug> <state> <rfcs-rows-block>
137
- # Used to regression-test P312 — reconcile-rfcs reverse-trace must traverse
138
- # docs/problems/<state>/<NNN>-*.md, not just flat docs/problems/<NNN>-*.<state>.md.
139
- write_problem_subdir() {
140
- local num="$1" slug="$2" state="$3" rfcs_rows="${4:-}"
141
- mkdir -p "$PROBLEMS_DIR/$state"
142
- local file="$PROBLEMS_DIR/$state/${num}-${slug}.md"
143
- cat > "$file" <<EOF
144
- # Problem ${num}: ${slug}
145
-
146
- **Status**: ${state}
147
-
148
- ## Description
149
-
150
- stub
151
-
152
- ## Related
153
-
154
- stub
155
- EOF
156
- if [ -n "$rfcs_rows" ]; then
157
- cat >> "$file" <<EOF
158
-
159
- ## RFCs
160
-
161
- | RFC | Status | Title |
162
- |-----|--------|-------|
163
- ${rfcs_rows}
164
- EOF
165
- fi
166
- }
167
-
168
- # ── Existence + executable ──────────────────────────────────────────────────
169
-
170
- @test "reconcile-rfcs: script exists" {
171
- [ -f "$SCRIPT" ]
172
- }
173
-
174
- @test "reconcile-rfcs: script is executable" {
175
- [ -x "$SCRIPT" ]
176
- }
177
-
178
- # ── Parse-error path ────────────────────────────────────────────────────────
179
-
180
- @test "reconcile-rfcs: missing README → exit 2 (parse error)" {
181
- run bash "$SCRIPT" "$FIXTURE_DIR"
182
- [ "$status" -eq 2 ]
183
- [[ "$output" == *"PARSE_ERROR"* ]]
184
- }
185
-
186
- @test "reconcile-rfcs: README without RFC Rankings header → exit 2" {
187
- cat > "$FIXTURE_DIR/README.md" <<'EOF'
188
- # RFC Backlog
189
-
190
- (no Rankings section)
191
- EOF
192
- run bash "$SCRIPT" "$FIXTURE_DIR"
193
- [ "$status" -eq 2 ]
194
- }
195
-
196
- # ── Clean path ──────────────────────────────────────────────────────────────
197
-
198
- @test "reconcile-rfcs: empty filesystem + empty README → exit 0 (clean)" {
199
- write_minimal_readme ""
200
- run bash "$SCRIPT" "$FIXTURE_DIR"
201
- [ "$status" -eq 0 ]
202
- }
203
-
204
- @test "reconcile-rfcs: README and filesystem agree on one proposed RFC → exit 0" {
205
- write_rfc "001" "foo" "proposed"
206
- write_minimal_readme "| 1.5 | RFC-001 | foo | 3 Med | Proposed | M | 2026-05-05 |"
207
- run bash "$SCRIPT" "$FIXTURE_DIR"
208
- [ "$status" -eq 0 ]
209
- }
210
-
211
- @test "reconcile-rfcs: accepted RFC matches Rankings (proposed/accepted/in-progress are all WSJF queue)" {
212
- write_rfc "002" "bar" "accepted"
213
- write_minimal_readme "| 2.0 | RFC-002 | bar | 4 High | Accepted | M | 2026-05-05 |"
214
- run bash "$SCRIPT" "$FIXTURE_DIR"
215
- [ "$status" -eq 0 ]
216
- }
217
-
218
- @test "reconcile-rfcs: in-progress RFC matches Rankings" {
219
- write_rfc "003" "baz" "in-progress"
220
- write_minimal_readme "| 1.5 | RFC-003 | baz | 3 Med | In-Progress | M | 2026-05-05 |"
221
- run bash "$SCRIPT" "$FIXTURE_DIR"
222
- [ "$status" -eq 0 ]
223
- }
224
-
225
- # ── Drift paths ─────────────────────────────────────────────────────────────
226
-
227
- @test "reconcile-rfcs: filesystem RFC missing from README → MISSING drift" {
228
- write_rfc "004" "qux" "proposed"
229
- write_minimal_readme ""
230
- run bash "$SCRIPT" "$FIXTURE_DIR"
231
- [ "$status" -eq 1 ]
232
- [[ "$output" == *"MISSING RFC-004"* ]]
233
- [[ "$output" == *"actual=proposed"* ]]
234
- }
235
-
236
- @test "reconcile-rfcs: README claims RFC in Rankings but filesystem says verifying → DRIFT" {
237
- write_rfc "005" "blip" "verifying"
238
- write_minimal_readme "| 0 | RFC-005 | blip | 3 Med | Proposed | M | 2026-05-05 |"
239
- run bash "$SCRIPT" "$FIXTURE_DIR"
240
- [ "$status" -eq 1 ]
241
- [[ "$output" == *"DRIFT RFC-005"* ]]
242
- [[ "$output" == *"actual=verifying"* ]]
243
- }
244
-
245
- @test "reconcile-rfcs: verifying RFC missing from Verification Queue → MISSING in queue" {
246
- write_rfc "006" "ver" "verifying"
247
- write_minimal_readme ""
248
- run bash "$SCRIPT" "$FIXTURE_DIR"
249
- [ "$status" -eq 1 ]
250
- [[ "$output" == *"MISSING RFC-006"* ]]
251
- [[ "$output" == *"verification-queue"* ]]
252
- }
253
-
254
- @test "reconcile-rfcs: closed RFC listed in Verification Queue → STALE" {
255
- write_rfc "007" "stale" "closed"
256
- cat > "$FIXTURE_DIR/README.md" <<'EOF'
257
- # RFC Backlog
258
-
259
- ## RFC Rankings
260
-
261
- | WSJF | ID | Title | Severity | Status | Effort | Reported |
262
- |------|-----|-------|----------|--------|--------|----------|
263
-
264
- ## Verification Queue
265
-
266
- | ID | Title | Released | Verification check |
267
- |----|-------|----------|--------------------|
268
- | RFC-007 | stale | 2026-05-05 | check |
269
-
270
- ## Closed
271
-
272
- | ID | Title | Closed | Driving problems |
273
- |----|-------|--------|------------------|
274
- EOF
275
- run bash "$SCRIPT" "$FIXTURE_DIR"
276
- [ "$status" -eq 1 ]
277
- [[ "$output" == *"STALE RFC-007"* ]]
278
- [[ "$output" == *"actual=closed"* ]]
279
- }
280
-
281
- @test "reconcile-rfcs: open-shape RFC listed in Closed section → MISMATCH" {
282
- write_rfc "008" "mis" "proposed"
283
- cat > "$FIXTURE_DIR/README.md" <<'EOF'
284
- # RFC Backlog
285
-
286
- ## RFC Rankings
287
-
288
- | WSJF | ID | Title | Severity | Status | Effort | Reported |
289
- |------|-----|-------|----------|--------|--------|----------|
290
- | 1.5 | RFC-008 | mis | 3 Med | Proposed | M | 2026-05-05 |
291
-
292
- ## Verification Queue
293
-
294
- | ID | Title | Released | Verification check |
295
- |----|-------|----------|--------------------|
296
-
297
- ## Closed
298
-
299
- | ID | Title | Closed | Driving problems |
300
- |----|-------|--------|------------------|
301
- | RFC-008 | mis | 2026-05-05 | P168 |
302
- EOF
303
- run bash "$SCRIPT" "$FIXTURE_DIR"
304
- [ "$status" -eq 1 ]
305
- [[ "$output" == *"MISMATCH RFC-008"* ]]
306
- }
307
-
308
- # ── Output format ───────────────────────────────────────────────────────────
309
-
310
- @test "reconcile-rfcs: drift output is per-line and ≤150 bytes per line (ADR-038)" {
311
- write_rfc "010" "byte-budget-test-with-an-extra-long-slug-to-stress-row-width" "proposed"
312
- write_minimal_readme ""
313
- run bash "$SCRIPT" "$FIXTURE_DIR"
314
- [ "$status" -eq 1 ]
315
- while IFS= read -r line; do
316
- [ ${#line} -le 150 ] || { echo "row exceeds 150 bytes: '$line' (${#line} bytes)"; return 1; }
317
- done <<< "$output"
318
- }
319
-
320
- @test "reconcile-rfcs: stable sort order (deterministic for snapshot diffing)" {
321
- write_rfc "020" "second" "proposed"
322
- write_rfc "010" "first" "proposed"
323
- write_minimal_readme ""
324
- run bash "$SCRIPT" "$FIXTURE_DIR"
325
- [ "$status" -eq 1 ]
326
- # Both should appear; lower ID first per sort.
327
- first_line=$(echo "$output" | head -1)
328
- second_line=$(echo "$output" | sed -n '2p')
329
- [[ "$first_line" == *"RFC-010"* ]]
330
- [[ "$second_line" == *"RFC-020"* ]]
331
- }
332
-
333
- # ── Reverse-trace drift detection (B5.T8 — closes ADR-060 Confirmation criterion 3) ──
334
- #
335
- # Per architect Q5 verdict: when a problems-dir is provided as second positional
336
- # arg, reconcile-rfcs.sh extends to detect drift in the `## RFCs` reverse-trace
337
- # section on driving problem tickets. Three new drift conditions:
338
- #
339
- # MISSING_REVERSE_TRACE RFC-<NNN> in P<NNN> ## RFCs
340
- # RFC frontmatter `problems:` claims P<NNN> but P<NNN>'s `## RFCs` table
341
- # does not list RFC-<NNN>.
342
- #
343
- # STALE_REVERSE_TRACE RFC-<NNN> in P<NNN> ## RFCs
344
- # P<NNN>'s `## RFCs` table lists RFC-<NNN> but the RFC's frontmatter
345
- # `problems:` no longer claims P<NNN>.
346
- #
347
- # STATUS_MISMATCH RFC-<NNN> in P<NNN> ## RFCs claims=<X> actual=<Y>
348
- # P<NNN>'s `## RFCs` row claims status <X> but RFC's filesystem suffix is <Y>.
349
- #
350
- # Backward-compat: when no problems-dir arg is supplied (or the dir is absent),
351
- # the script preserves the single-arg behaviour from B5.T6 (existing 18 cases
352
- # above pass unchanged).
353
-
354
- @test "reverse-trace: clean — RFC traces P, P has matching ## RFCs row → no drift" {
355
- write_rfc "001" "foo" "accepted"
356
- write_minimal_readme "| 2.0 | RFC-001 | foo | 3 Med | Accepted | M | 2026-05-05 |"
357
- write_problem "168" "p168" "verifying" "| RFC-001 | accepted | foo |"
358
- run bash "$SCRIPT" "$FIXTURE_DIR" "$PROBLEMS_DIR"
359
- [ "$status" -eq 0 ]
360
- }
361
-
362
- @test "reverse-trace: MISSING_REVERSE_TRACE — RFC claims P, P has no ## RFCs section" {
363
- write_rfc "001" "foo" "accepted"
364
- write_minimal_readme "| 2.0 | RFC-001 | foo | 3 Med | Accepted | M | 2026-05-05 |"
365
- write_problem "168" "p168" "verifying" ""
366
- run bash "$SCRIPT" "$FIXTURE_DIR" "$PROBLEMS_DIR"
367
- [ "$status" -eq 1 ]
368
- [[ "$output" == *"MISSING_REVERSE_TRACE"* ]]
369
- [[ "$output" == *"RFC-001"* ]]
370
- [[ "$output" == *"P168"* ]]
371
- }
372
-
373
- @test "reverse-trace: MISSING_REVERSE_TRACE — RFC claims P, P has ## RFCs but RFC absent from table" {
374
- write_rfc "001" "foo" "accepted"
375
- write_rfc "002" "bar" "proposed"
376
- write_minimal_readme "| 2.0 | RFC-001 | foo | 3 Med | Accepted | M | 2026-05-05 |"
377
- # P168 has ## RFCs section listing RFC-002 but not RFC-001
378
- write_problem "168" "p168" "verifying" "| RFC-002 | proposed | bar |"
379
- run bash "$SCRIPT" "$FIXTURE_DIR" "$PROBLEMS_DIR"
380
- [ "$status" -eq 1 ]
381
- [[ "$output" == *"MISSING_REVERSE_TRACE"* ]]
382
- [[ "$output" == *"RFC-001"* ]]
383
- [[ "$output" == *"P168"* ]]
384
- }
385
-
386
- @test "reverse-trace: STALE_REVERSE_TRACE — P lists RFC, RFC frontmatter no longer claims P" {
387
- # RFC-001 traces P169 only; P168's ## RFCs table still lists RFC-001
388
- write_rfc "001" "foo" "accepted" "[P169]"
389
- write_minimal_readme "| 2.0 | RFC-001 | foo | 3 Med | Accepted | M | 2026-05-05 |"
390
- write_problem "168" "p168" "verifying" "| RFC-001 | accepted | foo |"
391
- write_problem "169" "p169" "open" "| RFC-001 | accepted | foo |"
392
- run bash "$SCRIPT" "$FIXTURE_DIR" "$PROBLEMS_DIR"
393
- [ "$status" -eq 1 ]
394
- [[ "$output" == *"STALE_REVERSE_TRACE"* ]]
395
- [[ "$output" == *"RFC-001"* ]]
396
- [[ "$output" == *"P168"* ]]
397
- }
398
-
399
- @test "reverse-trace: STATUS_MISMATCH — P ## RFCs row claims status X but RFC suffix is Y" {
400
- write_rfc "001" "foo" "in-progress"
401
- write_minimal_readme "| 1.5 | RFC-001 | foo | 3 Med | In-Progress | M | 2026-05-05 |"
402
- # P168's ## RFCs table claims RFC-001 is `accepted` but the on-disk suffix is in-progress
403
- write_problem "168" "p168" "verifying" "| RFC-001 | accepted | foo |"
404
- run bash "$SCRIPT" "$FIXTURE_DIR" "$PROBLEMS_DIR"
405
- [ "$status" -eq 1 ]
406
- [[ "$output" == *"STATUS_MISMATCH"* ]]
407
- [[ "$output" == *"RFC-001"* ]]
408
- [[ "$output" == *"P168"* ]]
409
- [[ "$output" == *"claims=accepted"* ]]
410
- [[ "$output" == *"actual=in-progress"* ]]
411
- }
412
-
413
- @test "reverse-trace: backward-compat — single-arg invocation skips reverse-trace check" {
414
- # No problems-dir → existing 18-case behaviour
415
- write_rfc "001" "foo" "accepted"
416
- write_minimal_readme "| 2.0 | RFC-001 | foo | 3 Med | Accepted | M | 2026-05-05 |"
417
- run bash "$SCRIPT" "$FIXTURE_DIR"
418
- [ "$status" -eq 0 ]
419
- }
420
-
421
- @test "reverse-trace: problems-dir absent on disk → reverse-trace check skipped (warn-only)" {
422
- write_rfc "001" "foo" "accepted"
423
- write_minimal_readme "| 2.0 | RFC-001 | foo | 3 Med | Accepted | M | 2026-05-05 |"
424
- rm -rf "$PROBLEMS_DIR"
425
- run bash "$SCRIPT" "$FIXTURE_DIR" "$PROBLEMS_DIR"
426
- # absent problems-dir does not promote to drift; treat as backward-compat
427
- [ "$status" -eq 0 ]
428
- }
429
-
430
- @test "reverse-trace: RFC has no problems frontmatter → reverse-trace skipped for that RFC" {
431
- # Empty problems list; RFC-001 frontmatter has no claims to validate
432
- write_rfc "001" "foo" "accepted" "[]"
433
- write_minimal_readme "| 2.0 | RFC-001 | foo | 3 Med | Accepted | M | 2026-05-05 |"
434
- write_problem "168" "p168" "verifying" ""
435
- run bash "$SCRIPT" "$FIXTURE_DIR" "$PROBLEMS_DIR"
436
- [ "$status" -eq 0 ]
437
- }
438
-
439
- @test "reverse-trace: drift output is per-line and ≤150 bytes per line (ADR-038)" {
440
- write_rfc "001" "byte-budget-test-with-an-extra-long-slug-to-stress-row-width" "accepted"
441
- write_minimal_readme "| 2.0 | RFC-001 | byte-budget-test-with-an-extra-long-slug-to-stress-row-width | 3 Med | Accepted | M | 2026-05-05 |"
442
- write_problem "168" "p168" "verifying" ""
443
- run bash "$SCRIPT" "$FIXTURE_DIR" "$PROBLEMS_DIR"
444
- [ "$status" -eq 1 ]
445
- while IFS= read -r line; do
446
- [ ${#line} -le 150 ] || { echo "row exceeds 150 bytes: '$line' (${#line} bytes)"; return 1; }
447
- done <<< "$output"
448
- }
449
-
450
- # ── P312: per-state subdir reverse-trace (ADR-031 layout) ───────────────────
451
- # Closes P312 — reconcile-rfcs reported spurious MISSING_REVERSE_TRACE for
452
- # tickets that live under docs/problems/<state>/<NNN>-*.md because the
453
- # reverse-trace pass only globbed the flat docs/problems/<NNN>-*.md layout.
454
- # RFC-002-class dual-tolerant-glob fix mirroring the sibling already shipped
455
- # in reconcile-readme.sh (P118).
456
-
457
- @test "P312: reverse-trace clean when problem ticket lives in per-state subdir" {
458
- write_rfc "001" "foo" "accepted"
459
- write_minimal_readme "| 2.0 | RFC-001 | foo | 3 Med | Accepted | M | 2026-05-05 |"
460
- # Ticket lives under docs/problems/verifying/168-p168.md (no .state suffix).
461
- write_problem_subdir "168" "p168" "verifying" "| RFC-001 | accepted | foo |"
462
- run bash "$SCRIPT" "$FIXTURE_DIR" "$PROBLEMS_DIR"
463
- [ "$status" -eq 0 ]
464
- [[ "$output" != *"MISSING_REVERSE_TRACE"* ]]
465
- }
466
-
467
- @test "P312: reverse-trace detects missing trace when problem ticket lives in per-state subdir" {
468
- write_rfc "001" "foo" "accepted"
469
- write_minimal_readme "| 2.0 | RFC-001 | foo | 3 Med | Accepted | M | 2026-05-05 |"
470
- # Subdir ticket WITHOUT a `## RFCs` section → MISSING_REVERSE_TRACE must fire.
471
- write_problem_subdir "168" "p168" "verifying" ""
472
- run bash "$SCRIPT" "$FIXTURE_DIR" "$PROBLEMS_DIR"
473
- [ "$status" -eq 1 ]
474
- [[ "$output" == *"MISSING_REVERSE_TRACE"* ]]
475
- [[ "$output" == *"RFC-001"* ]]
476
- [[ "$output" == *"P168"* ]]
477
- }
478
-
479
- # ── ADR-049 bin shim contract ───────────────────────────────────────────────
480
-
481
- @test "wr-itil-reconcile-rfcs bin shim exists" {
482
- BIN_SHIM="$(cd "$SCRIPTS_DIR/../bin" && pwd)/wr-itil-reconcile-rfcs"
483
- [ -f "$BIN_SHIM" ]
484
- }
485
-
486
- @test "wr-itil-reconcile-rfcs bin shim is executable" {
487
- BIN_SHIM="$(cd "$SCRIPTS_DIR/../bin" && pwd)/wr-itil-reconcile-rfcs"
488
- [ -x "$BIN_SHIM" ]
489
- }
490
-
491
- @test "wr-itil-reconcile-rfcs bin shim dispatches to canonical script" {
492
- BIN_SHIM="$(cd "$SCRIPTS_DIR/../bin" && pwd)/wr-itil-reconcile-rfcs"
493
- write_minimal_readme ""
494
- run bash "$BIN_SHIM" "$FIXTURE_DIR"
495
- [ "$status" -eq 0 ]
496
- }
@@ -1,173 +0,0 @@
1
- #!/usr/bin/env bats
2
- # Behavioural fixtures for reconcile-stories.sh + bin shim + skill
3
- # (P170 Phase 2 Slice 9 — ADR-060 amendment 2026-05-10 line 270 +
4
- # reconcile-rfcs.sh / reconcile-readme.sh sibling).
5
- #
6
- # Per ADR-052: behavioural tests on observable script outputs. The
7
- # load-bearing surfaces under test are:
8
- # 1. Script existence + executable + valid Bash.
9
- # 2. README parse error (exit 2) on missing README or missing
10
- # Story Rankings header.
11
- # 3. Clean run (exit 0) on a fresh stories directory + empty README.
12
- # 4. Drift detection (exit 1) when README claims a story that isn't
13
- # on filesystem in the right lifecycle state.
14
- # 5. STALE detection when filesystem has a story not listed in
15
- # either Story Rankings (active) or Done section.
16
- # 6. Bin shim resolves to the script.
17
- # 7. SKILL.md presence + canonical name + read-only contract.
18
-
19
- setup() {
20
- REPO_ROOT="$(cd "$(dirname "$BATS_TEST_FILENAME")/../../../.." && pwd)"
21
- SCRIPT="${REPO_ROOT}/packages/itil/scripts/reconcile-stories.sh"
22
- BIN_SHIM="${REPO_ROOT}/packages/itil/bin/wr-itil-reconcile-stories"
23
- SKILL_FILE="${REPO_ROOT}/packages/itil/skills/reconcile-stories/SKILL.md"
24
-
25
- TMPROOT=$(mktemp -d)
26
- ORIG_DIR="$PWD"
27
- cd "$TMPROOT"
28
- }
29
-
30
- teardown() {
31
- cd "$ORIG_DIR"
32
- rm -rf "$TMPROOT"
33
- }
34
-
35
- # ---------------------------------------------------------------------------
36
- # Surface 1: Script + bin shim existence
37
- # ---------------------------------------------------------------------------
38
-
39
- @test "reconcile-stories: script exists and is executable" {
40
- [ -f "$SCRIPT" ]
41
- [ -x "$SCRIPT" ]
42
- }
43
-
44
- @test "reconcile-stories: bin shim exists, is executable, and exec's the script" {
45
- [ -f "$BIN_SHIM" ]
46
- [ -x "$BIN_SHIM" ]
47
- run grep -E 'exec.*scripts/reconcile-stories\.sh' "$BIN_SHIM"
48
- [ "$status" -eq 0 ]
49
- }
50
-
51
- # ---------------------------------------------------------------------------
52
- # Surface 2: Parse errors (exit 2)
53
- # ---------------------------------------------------------------------------
54
-
55
- @test "reconcile-stories: exits 2 when README is missing" {
56
- mkdir -p docs/stories
57
- run bash "$SCRIPT" docs/stories
58
- [ "$status" -eq 2 ]
59
- [[ "$output" == *"PARSE_ERROR"* ]] || [[ "$stderr" == *"PARSE_ERROR"* ]]
60
- }
61
-
62
- @test "reconcile-stories: exits 2 when README missing Story Rankings header" {
63
- mkdir -p docs/stories
64
- echo "# Stories" > docs/stories/README.md
65
- run bash "$SCRIPT" docs/stories
66
- [ "$status" -eq 2 ]
67
- }
68
-
69
- # ---------------------------------------------------------------------------
70
- # Surface 3: Clean run (exit 0)
71
- # ---------------------------------------------------------------------------
72
-
73
- @test "reconcile-stories: exits 0 on empty stories dir with empty README tables" {
74
- mkdir -p docs/stories/draft docs/stories/accepted docs/stories/in-progress docs/stories/done docs/stories/archived
75
- cat > docs/stories/README.md <<'EOF'
76
- # Story Backlog
77
-
78
- ## Story Rankings
79
-
80
- | ID | Title | Status |
81
- |----|-------|--------|
82
-
83
- ## Done
84
-
85
- | ID | Title | Done |
86
- |----|-------|------|
87
- EOF
88
- run bash "$SCRIPT" docs/stories
89
- [ "$status" -eq 0 ]
90
- }
91
-
92
- # ---------------------------------------------------------------------------
93
- # Surface 4: Drift detection on filesystem vs README mismatch (exit 1)
94
- # ---------------------------------------------------------------------------
95
-
96
- @test "reconcile-stories: detects STALE when filesystem has a draft story not in README" {
97
- mkdir -p docs/stories/draft docs/stories/done
98
- touch docs/stories/draft/STORY-007-foo.md
99
- cat > docs/stories/README.md <<'EOF'
100
- # Story Backlog
101
-
102
- ## Story Rankings
103
-
104
- | ID | Title | Status |
105
- |----|-------|--------|
106
-
107
- ## Done
108
-
109
- | ID | Title | Done |
110
- |----|-------|------|
111
- EOF
112
- run bash "$SCRIPT" docs/stories
113
- [ "$status" -eq 1 ]
114
- [[ "$output" == *"STALE"* ]]
115
- [[ "$output" == *"STORY-007"* ]]
116
- }
117
-
118
- @test "reconcile-stories: detects DRIFT when README claims a story in Rankings but it's actually done on disk" {
119
- mkdir -p docs/stories/draft docs/stories/done
120
- touch docs/stories/done/STORY-007-foo.md
121
- cat > docs/stories/README.md <<'EOF'
122
- # Story Backlog
123
-
124
- ## Story Rankings
125
-
126
- | ID | Title | Status |
127
- |----|-------|--------|
128
- | STORY-007 | Foo | draft |
129
-
130
- ## Done
131
-
132
- | ID | Title | Done |
133
- |----|-------|------|
134
- EOF
135
- run bash "$SCRIPT" docs/stories
136
- [ "$status" -eq 1 ]
137
- [[ "$output" == *"DRIFT"* ]]
138
- [[ "$output" == *"STORY-007"* ]]
139
- [[ "$output" == *"actual=done"* ]]
140
- }
141
-
142
- @test "reconcile-stories: archived stories are hidden from both tables (no drift)" {
143
- mkdir -p docs/stories/archived
144
- touch docs/stories/archived/STORY-007-foo.md
145
- cat > docs/stories/README.md <<'EOF'
146
- # Story Backlog
147
-
148
- ## Story Rankings
149
-
150
- | ID | Title | Status |
151
- |----|-------|--------|
152
-
153
- ## Done
154
-
155
- | ID | Title | Done |
156
- |----|-------|------|
157
- EOF
158
- run bash "$SCRIPT" docs/stories
159
- [ "$status" -eq 0 ]
160
- }
161
-
162
- # ---------------------------------------------------------------------------
163
- # Surface 5: SKILL.md presence + read-only contract
164
- # ---------------------------------------------------------------------------
165
-
166
- @test "reconcile-stories: SKILL.md exists" {
167
- [ -f "$SKILL_FILE" ]
168
- }
169
-
170
- @test "reconcile-stories: SKILL.md declares canonical name wr-itil:reconcile-stories" {
171
- run grep -E '^name: wr-itil:reconcile-stories$' "$SKILL_FILE"
172
- [ "$status" -eq 0 ]
173
- }