@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,178 +0,0 @@
1
- #!/usr/bin/env bats
2
-
3
- # P170 / Phase 4 P4.1 — behavioural fixture for the
4
- # update-jtbd-references-section.sh "Related problems" extension.
5
- # Adds a fourth lookup-table row (alongside RFCs / Story Maps /
6
- # Stories) so JTBD files auto-maintain a `## Related problems`
7
- # reverse-trace section sourced from problem-ticket frontmatter
8
- # `jtbd:` arrays. Mirrors the parallel-existence one-way reverse-
9
- # trace shape from ADR-060 § Phase 3 + Phase 4 in-scope amendment
10
- # (2026-05-13) P4.1.
11
- #
12
- # Per ADR-060 architect finding A4 + JTBD finding F5: lookup-table
13
- # row addition, NOT a new helper. The body MUST remain
14
- # per-section-name-branchless (assertion in
15
- # update-references-section-sibling-helpers.bats).
16
-
17
- setup() {
18
- REPO_ROOT="$(cd "$(dirname "$BATS_TEST_FILENAME")/../../../.." && pwd)"
19
- SCRIPT="$REPO_ROOT/packages/itil/scripts/update-jtbd-references-section.sh"
20
-
21
- WORKSPACE="$(mktemp -d)"
22
- cd "$WORKSPACE"
23
- mkdir -p docs/problems/open docs/problems/known-error docs/jtbd/solo-developer
24
-
25
- cat > docs/jtbd/solo-developer/JTBD-999-sample-job.proposed.md <<'EOF'
26
- ---
27
- status: proposed
28
- job-id: sample-job
29
- persona: solo-developer
30
- date-created: 2026-05-13
31
- ---
32
-
33
- # JTBD-999: Sample Job
34
-
35
- ## Job Statement
36
-
37
- Sample.
38
-
39
- ## Desired Outcomes
40
-
41
- - Outcome A.
42
- EOF
43
- }
44
-
45
- teardown() {
46
- if [ -n "${WORKSPACE:-}" ] && [ -d "$WORKSPACE" ]; then
47
- rm -rf "$WORKSPACE"
48
- fi
49
- }
50
-
51
- @test "Related problems: extracts user-business problem citing the JTBD" {
52
- cat > docs/problems/open/501-business-problem.md <<'EOF'
53
- ---
54
- type: user-business
55
- jtbd: [JTBD-999]
56
- persona: solo-developer
57
- ---
58
- # Problem 501: Business problem citing JTBD-999
59
-
60
- **Status**: Open
61
-
62
- ## Description
63
-
64
- Business problem.
65
- EOF
66
-
67
- run bash "$SCRIPT" docs/jtbd/solo-developer/JTBD-999-sample-job.proposed.md "Related problems"
68
- [ "$status" -eq 0 ]
69
- grep -q '^## Related problems' docs/jtbd/solo-developer/JTBD-999-sample-job.proposed.md
70
- grep -q '| P501 |' docs/jtbd/solo-developer/JTBD-999-sample-job.proposed.md
71
- }
72
-
73
- @test "Related problems: ignores problems that don't cite the JTBD" {
74
- cat > docs/problems/open/502-unrelated.md <<'EOF'
75
- ---
76
- type: technical
77
- ---
78
- # Problem 502: Unrelated technical problem
79
-
80
- **Status**: Open
81
-
82
- ## Description
83
-
84
- Unrelated.
85
- EOF
86
-
87
- run bash "$SCRIPT" docs/jtbd/solo-developer/JTBD-999-sample-job.proposed.md "Related problems"
88
- [ "$status" -eq 0 ]
89
- ! grep -q '^## Related problems' docs/jtbd/solo-developer/JTBD-999-sample-job.proposed.md
90
- }
91
-
92
- @test "Related problems: lazy-empty when no problem cites the JTBD" {
93
- cat > docs/problems/open/503-something-else.md <<'EOF'
94
- ---
95
- type: user-business
96
- jtbd: [JTBD-001]
97
- ---
98
- # Problem 503: Cites a different JTBD
99
-
100
- **Status**: Open
101
- EOF
102
-
103
- run bash "$SCRIPT" docs/jtbd/solo-developer/JTBD-999-sample-job.proposed.md "Related problems"
104
- [ "$status" -eq 0 ]
105
- ! grep -q '^## Related problems' docs/jtbd/solo-developer/JTBD-999-sample-job.proposed.md
106
- }
107
-
108
- @test "Related problems: searches per-state subdirs (RFC-002 layout)" {
109
- cat > docs/problems/known-error/504-business-known-error.md <<'EOF'
110
- ---
111
- type: user-business
112
- jtbd: [JTBD-999]
113
- persona: solo-developer
114
- ---
115
- # Problem 504: Known-error business problem
116
-
117
- **Status**: Known Error
118
- EOF
119
-
120
- run bash "$SCRIPT" docs/jtbd/solo-developer/JTBD-999-sample-job.proposed.md "Related problems"
121
- [ "$status" -eq 0 ]
122
- grep -q '| P504 |' docs/jtbd/solo-developer/JTBD-999-sample-job.proposed.md
123
- }
124
-
125
- @test "Related problems: idempotent across re-runs" {
126
- cat > docs/problems/open/505-idempotent.md <<'EOF'
127
- ---
128
- type: user-business
129
- jtbd: [JTBD-999]
130
- persona: solo-developer
131
- ---
132
- # Problem 505: Idempotent test
133
-
134
- **Status**: Open
135
- EOF
136
-
137
- run bash "$SCRIPT" docs/jtbd/solo-developer/JTBD-999-sample-job.proposed.md "Related problems"
138
- [ "$status" -eq 0 ]
139
- before_hash=$(md5 -q docs/jtbd/solo-developer/JTBD-999-sample-job.proposed.md 2>/dev/null || md5sum docs/jtbd/solo-developer/JTBD-999-sample-job.proposed.md | awk '{print $1}')
140
-
141
- run bash "$SCRIPT" docs/jtbd/solo-developer/JTBD-999-sample-job.proposed.md "Related problems"
142
- [ "$status" -eq 0 ]
143
- after_hash=$(md5 -q docs/jtbd/solo-developer/JTBD-999-sample-job.proposed.md 2>/dev/null || md5sum docs/jtbd/solo-developer/JTBD-999-sample-job.proposed.md | awk '{print $1}')
144
-
145
- [ "$before_hash" = "$after_hash" ]
146
- }
147
-
148
- @test "Related problems: unknown section-name still fails" {
149
- run bash "$SCRIPT" docs/jtbd/solo-developer/JTBD-999-sample-job.proposed.md "Bogus Section"
150
- [ "$status" -ne 0 ]
151
- }
152
-
153
- @test "Related problems: helper still no per-section-name branch (P4.1 lookup-table-row addition only)" {
154
- ! grep -E 'case[[:space:]]+"\$\{?section[_-]?name\}?"|if[[:space:]]+\[[[:space:]]+"\$\{?section[_-]?name\}?"[[:space:]]+=' "$SCRIPT"
155
- }
156
-
157
- @test "Related problems: extracts problem using body-field **JTBD**: convention (capture-problem schema P3.1)" {
158
- # P3.1 capture-problem skeleton writes body-field **JTBD**: (matches
159
- # existing **Status**: / **Type**: schema); helper must accept both
160
- # frontmatter `jtbd:` arrays AND body-field **JTBD**: lines.
161
- cat > docs/problems/open/506-body-field-business-problem.md <<'EOF'
162
- # Problem 506: Body-field business problem
163
-
164
- **Status**: Open
165
- **Reported**: 2026-05-13
166
- **Type**: user-business
167
- **JTBD**: JTBD-999
168
- **Persona**: solo-developer
169
-
170
- ## Description
171
-
172
- Problem captured via Phase 4 P3.1 capture-problem with body-field JTBD trace.
173
- EOF
174
-
175
- run bash "$SCRIPT" docs/jtbd/solo-developer/JTBD-999-sample-job.proposed.md "Related problems"
176
- [ "$status" -eq 0 ]
177
- grep -q '| P506 |' docs/jtbd/solo-developer/JTBD-999-sample-job.proposed.md
178
- }
@@ -1,242 +0,0 @@
1
- #!/usr/bin/env bats
2
-
3
- # P170 / Phase 2 Slice 2 — behavioural fixture for the generalised
4
- # update-problem-references-section.sh helper. Covers polymorphic
5
- # extraction (HTML data attributes for Story Maps; markdown frontmatter
6
- # for Stories + RFCs) feeding a uniform markdown-row render into the
7
- # target problem ticket's ## <section-name> section. Per ADR-060
8
- # § Phase 2 encoding amendment 2026-05-12 architect finding 4: helper
9
- # body MUST NOT carry per-section-name branching; section-name is a
10
- # positional argument; per-extension dispatch is the only branch.
11
-
12
- setup() {
13
- REPO_ROOT="$(cd "$(dirname "$BATS_TEST_FILENAME")/../../../.." && pwd)"
14
- SCRIPT="$REPO_ROOT/packages/itil/scripts/update-problem-references-section.sh"
15
-
16
- # Build an isolated workspace mirroring the docs layout.
17
- WORKSPACE="$(mktemp -d)"
18
- cd "$WORKSPACE"
19
- mkdir -p docs/problems/open docs/rfcs docs/story-maps/in-progress docs/stories/accepted
20
-
21
- # Sample problem ticket
22
- cat > docs/problems/open/200-sample-problem.md <<'EOF'
23
- # Problem 200: Sample problem ticket
24
-
25
- **Status**: Open
26
- **Reported**: 2026-05-12
27
-
28
- ## Description
29
-
30
- Sample description.
31
-
32
- ## Related
33
-
34
- Sibling refs.
35
- EOF
36
-
37
- # Sample RFC tracing problem 200
38
- cat > docs/rfcs/RFC-100-sample-rfc.in-progress.md <<'EOF'
39
- ---
40
- status: in-progress
41
- rfc-id: sample-rfc
42
- problems: [P200]
43
- adrs: []
44
- jtbd: []
45
- ---
46
-
47
- # RFC-100: Sample RFC
48
- EOF
49
-
50
- # Sample HTML story map tracing problem 200
51
- cat > docs/story-maps/in-progress/STORY-MAP-050-sample-map.html <<'EOF'
52
- <!DOCTYPE html>
53
- <html lang="en">
54
- <head>
55
- <meta charset="UTF-8">
56
- <title>STORY-MAP-050: Sample map</title>
57
- <meta name="story-map-id" content="STORY-MAP-050">
58
- <meta name="status" content="in-progress">
59
- <meta name="problems" content="P200">
60
- <meta name="rfcs" content="RFC-100">
61
- <meta name="jtbd" content="JTBD-008">
62
- </head>
63
- <body>
64
- <h1>STORY-MAP-050: Sample map</h1>
65
- </body>
66
- </html>
67
- EOF
68
-
69
- # Sample markdown story tracing problem 200
70
- cat > docs/stories/accepted/STORY-300-sample-story.md <<'EOF'
71
- ---
72
- status: accepted
73
- story-id: sample-story
74
- problems: [P200]
75
- jtbd: [JTBD-008]
76
- rfcs: [RFC-100]
77
- story-maps: [STORY-MAP-050]
78
- estimated-effort: M
79
- ---
80
-
81
- # STORY-300: Sample story
82
- EOF
83
- }
84
-
85
- teardown() {
86
- rm -rf "$WORKSPACE"
87
- }
88
-
89
- @test "helper: script exists and is executable" {
90
- [ -x "$SCRIPT" ]
91
- }
92
-
93
- @test "helper: requires problem-file argument; bare invocation halts" {
94
- run bash "$SCRIPT"
95
- [ "$status" -ne 0 ]
96
- }
97
-
98
- @test "helper: requires section-name argument" {
99
- run bash "$SCRIPT" docs/problems/open/200-sample-problem.md
100
- [ "$status" -ne 0 ]
101
- }
102
-
103
- @test "helper: refresh ## RFCs section from docs/rfcs/*.md frontmatter (markdown-extraction path)" {
104
- cd "$WORKSPACE"
105
- run bash "$SCRIPT" docs/problems/open/200-sample-problem.md RFCs
106
- [ "$status" -eq 0 ]
107
- grep -q '^## RFCs$' docs/problems/open/200-sample-problem.md
108
- grep -q 'RFC-100' docs/problems/open/200-sample-problem.md
109
- }
110
-
111
- @test "helper: refresh ## Story Maps section from docs/story-maps/*.html data attributes (HTML-extraction path)" {
112
- cd "$WORKSPACE"
113
- run bash "$SCRIPT" docs/problems/open/200-sample-problem.md "Story Maps"
114
- [ "$status" -eq 0 ]
115
- grep -q '^## Story Maps$' docs/problems/open/200-sample-problem.md
116
- grep -q 'STORY-MAP-050' docs/problems/open/200-sample-problem.md
117
- }
118
-
119
- @test "helper: refresh ## Stories section from docs/stories/*.md frontmatter (markdown-extraction path)" {
120
- cd "$WORKSPACE"
121
- run bash "$SCRIPT" docs/problems/open/200-sample-problem.md Stories
122
- [ "$status" -eq 0 ]
123
- grep -q '^## Stories$' docs/problems/open/200-sample-problem.md
124
- grep -q 'STORY-300' docs/problems/open/200-sample-problem.md
125
- }
126
-
127
- @test "helper: lazy-empty — section removed entirely when no traces match" {
128
- cd "$WORKSPACE"
129
- # Create a problem ticket nothing references
130
- cat > docs/problems/open/201-unreferenced-problem.md <<'EOF'
131
- # Problem 201: Unreferenced
132
-
133
- **Status**: Open
134
-
135
- ## Related
136
-
137
- Some related content.
138
-
139
- ## Story Maps
140
-
141
- | ID | Title |
142
- |----|-------|
143
- | STORY-MAP-999 | stale entry |
144
- EOF
145
- run bash "$SCRIPT" docs/problems/open/201-unreferenced-problem.md "Story Maps"
146
- [ "$status" -eq 0 ]
147
- ! grep -q '^## Story Maps$' docs/problems/open/201-unreferenced-problem.md
148
- }
149
-
150
- @test "helper: idempotent — running twice produces no change on second invocation" {
151
- cd "$WORKSPACE"
152
- bash "$SCRIPT" docs/problems/open/200-sample-problem.md RFCs
153
- local first_hash
154
- first_hash=$(md5 -q docs/problems/open/200-sample-problem.md 2>/dev/null || md5sum docs/problems/open/200-sample-problem.md | cut -d' ' -f1)
155
- bash "$SCRIPT" docs/problems/open/200-sample-problem.md RFCs
156
- local second_hash
157
- second_hash=$(md5 -q docs/problems/open/200-sample-problem.md 2>/dev/null || md5sum docs/problems/open/200-sample-problem.md | cut -d' ' -f1)
158
- [ "$first_hash" = "$second_hash" ]
159
- }
160
-
161
- @test "helper: HTML path uses literal data-attribute grep (NOT inline-style match)" {
162
- # Architect finding 5 (Prohibition reinforcement): the helper MUST
163
- # grep on `<meta name="problems" content="...">` literal, not on any
164
- # `style=` attribute. Verify by injecting a fake inline-style on a
165
- # data-bearing element and asserting the helper's extraction is
166
- # unaffected (the prohibition is enforced separately by a doc-lint
167
- # bats; this test asserts the helper's parsing is style-agnostic).
168
- cd "$WORKSPACE"
169
- # The fixture's HTML map already lacks any `style=""` — that's the
170
- # canonical shape. The helper must extract the same set whether the
171
- # map has style or not. Adding a benign body-level style to the
172
- # fixture (NOT on a data-bearing element) and re-running the helper
173
- # must yield the same Story Maps section.
174
- bash "$SCRIPT" docs/problems/open/200-sample-problem.md "Story Maps"
175
- local first_body
176
- first_body=$(grep -A 5 '^## Story Maps$' docs/problems/open/200-sample-problem.md)
177
- # Inject benign body-level style — NOT on a data-bearing element
178
- sed -i.bak 's|<body>|<body style="font-family: sans-serif">|' docs/story-maps/in-progress/STORY-MAP-050-sample-map.html
179
- rm -f docs/story-maps/in-progress/STORY-MAP-050-sample-map.html.bak
180
- bash "$SCRIPT" docs/problems/open/200-sample-problem.md "Story Maps"
181
- local second_body
182
- second_body=$(grep -A 5 '^## Story Maps$' docs/problems/open/200-sample-problem.md)
183
- [ "$first_body" = "$second_body" ]
184
- }
185
-
186
- @test "helper: multi-line section inserts before ## Fix Released under host awk (P392 BSD-awk getline fix)" {
187
- # P392 — the insert-before-## Fix Released branch passed the multi-line
188
- # new_section via `awk -v section=...`; BSD awk (macOS) rejects embedded
189
- # newlines in a -v assignment and aborts (`awk: newline in string`),
190
- # silently dropping the section refresh. This exercises that branch under
191
- # the host awk: it must exit 0 AND place the rendered ## RFCs table
192
- # immediately before ## Fix Released with the table rows intact.
193
- cd "$WORKSPACE"
194
- cat > docs/problems/open/202-released-problem.md <<'EOF'
195
- # Problem 202: Released problem ticket
196
-
197
- **Status**: Verifying
198
-
199
- ## Description
200
-
201
- Sample description.
202
-
203
- ## Fix Released
204
-
205
- Released in v1.2.3.
206
- EOF
207
- # RFC tracing problem 202 so a non-empty multi-line section is rendered
208
- cat > docs/rfcs/RFC-100-sample-rfc.in-progress.md <<'EOF'
209
- ---
210
- status: in-progress
211
- rfc-id: sample-rfc
212
- problems: [P202]
213
- adrs: []
214
- jtbd: []
215
- ---
216
-
217
- # RFC-100: Sample RFC
218
- EOF
219
- run bash "$SCRIPT" docs/problems/open/202-released-problem.md RFCs
220
- [ "$status" -eq 0 ]
221
- grep -q '^## RFCs$' docs/problems/open/202-released-problem.md
222
- grep -q 'RFC-100' docs/problems/open/202-released-problem.md
223
- grep -q '^## Fix Released$' docs/problems/open/202-released-problem.md
224
- # ## RFCs must precede ## Fix Released (inserted at the anchor, not at EOF)
225
- local rfcs_line fix_line
226
- rfcs_line=$(grep -n '^## RFCs$' docs/problems/open/202-released-problem.md | cut -d: -f1)
227
- fix_line=$(grep -n '^## Fix Released$' docs/problems/open/202-released-problem.md | cut -d: -f1)
228
- [ "$rfcs_line" -lt "$fix_line" ]
229
- # The multi-line table row must survive intact
230
- grep -q '| RFC-100 |' docs/problems/open/202-released-problem.md
231
- }
232
-
233
- @test "helper: body does NOT contain a per-section-name branch (architect finding 4)" {
234
- # Structural test (tdd-review: structural-permitted —
235
- # justification: P176 SKILL.md I-invariant harness gap is the
236
- # canonical pattern for asserting no-branching contracts via
237
- # source grep; behavioural enforcement awaits the master harness
238
- # at P012). Asserts the helper body does NOT carry a literal
239
- # `case "$section_name"` or `if [ "$section_name" = "..." ]`
240
- # branch keyed on the section-name value.
241
- ! grep -E 'case[[:space:]]+"\$\{?section[_-]?name\}?"|if[[:space:]]+\[[[:space:]]+"\$\{?section[_-]?name\}?"[[:space:]]+=' "$SCRIPT"
242
- }
@@ -1,242 +0,0 @@
1
- #!/usr/bin/env bats
2
-
3
- # @problem P170 — Slice 3 second half (B5.T8): the auto-maintained
4
- # `## RFCs` section refresh contract on problem ticket bodies. Library
5
- # helper called inline by /wr-itil:capture-rfc Step 6 and
6
- # /wr-itil:manage-rfc Step 7+9 so the cross-tier reverse-trace stays
7
- # current at every commit per ADR-014 single-commit grain.
8
- #
9
- # Behavioural per ADR-052: assert on file output state (idempotent
10
- # table; lazy empty discipline; placement) — not on script source
11
- # content (no structural greps per P081).
12
- #
13
- # Contract (per architect Q3 verdict):
14
- # - Section position: between `## Related` and `## Fix Released`
15
- # (or at EOF if neither sentinel present).
16
- # - Table format: `| RFC | Status | Title |` with separator row.
17
- # - Sort: RFC ID asc.
18
- # - Lazy empty: zero traced RFCs → section absent (no header,
19
- # no `_None._` prose).
20
- # - Idempotent: re-run over current state is a no-op (cmp -s holds).
21
- #
22
- # @adr ADR-060 (Phase 1 item 10 + Confirmation criterion 3)
23
- # @adr ADR-052 (behavioural bats default)
24
- # @adr ADR-022 (`## Fix Released` is the trailing closure section)
25
- # @jtbd JTBD-008 (Decompose a Fix Into Coordinated Changes — reverse
26
- # trace surface)
27
- # @jtbd JTBD-101 (atomic-fix-adopter friction guard — lazy empty)
28
-
29
- setup() {
30
- SCRIPTS_DIR="$(cd "$(dirname "$BATS_TEST_FILENAME")/.." && pwd)"
31
- HELPER="$SCRIPTS_DIR/update-problem-rfcs-section.sh"
32
- RFCS_DIR="$(mktemp -d)"
33
- PROBLEMS_DIR="$(mktemp -d)"
34
- }
35
-
36
- teardown() {
37
- rm -rf "$RFCS_DIR" "$PROBLEMS_DIR"
38
- }
39
-
40
- write_rfc() {
41
- local id="$1" slug="$2" status="$3"
42
- local problems="${4:-[P168]}"
43
- cat > "$RFCS_DIR/RFC-${id}-${slug}.${status}.md" <<EOF
44
- ---
45
- status: ${status}
46
- rfc-id: ${slug}
47
- reported: 2026-05-05
48
- decision-makers: [test]
49
- problems: ${problems}
50
- ---
51
-
52
- # RFC-${id}: ${slug}
53
-
54
- stub
55
- EOF
56
- }
57
-
58
- write_problem() {
59
- local num="$1" slug="$2" trailing="${3:-}"
60
- local file="$PROBLEMS_DIR/${num}-${slug}.open.md"
61
- cat > "$file" <<EOF
62
- # Problem ${num}: ${slug}
63
-
64
- **Status**: Open
65
-
66
- ## Description
67
-
68
- stub
69
-
70
- ## Related
71
-
72
- stub
73
- EOF
74
- if [ -n "$trailing" ]; then
75
- printf '\n%s\n' "$trailing" >> "$file"
76
- fi
77
- echo "$file"
78
- }
79
-
80
- # ── Existence + executable ──────────────────────────────────────────────────
81
-
82
- @test "helper exists" {
83
- [ -f "$HELPER" ]
84
- }
85
-
86
- @test "helper is executable" {
87
- [ -x "$HELPER" ]
88
- }
89
-
90
- # ── Lazy-empty discipline (JTBD-101 friction guard) ─────────────────────────
91
-
92
- @test "no RFCs trace → section absent (lazy empty)" {
93
- pf=$(write_problem "168" "p168")
94
- bash "$HELPER" "$pf" "$RFCS_DIR"
95
- ! grep -q '^## RFCs' "$pf"
96
- }
97
-
98
- @test "no RFCs trace and section exists → section removed" {
99
- # A pre-existing stale section gets cleaned out when zero RFCs claim.
100
- pf=$(write_problem "168" "p168" $'## RFCs\n\n| RFC | Status | Title |\n|-----|--------|-------|\n| RFC-001 | accepted | foo |')
101
- bash "$HELPER" "$pf" "$RFCS_DIR"
102
- ! grep -q '^## RFCs' "$pf"
103
- }
104
-
105
- # ── Single-RFC trace ────────────────────────────────────────────────────────
106
-
107
- @test "one RFC traces P → section appears with one row" {
108
- write_rfc "001" "foo" "accepted"
109
- pf=$(write_problem "168" "p168")
110
- bash "$HELPER" "$pf" "$RFCS_DIR"
111
- grep -q '^## RFCs' "$pf"
112
- grep -q '| RFC-001 | accepted | foo |' "$pf"
113
- }
114
-
115
- @test "table includes header + separator + data row" {
116
- write_rfc "001" "foo" "accepted"
117
- pf=$(write_problem "168" "p168")
118
- bash "$HELPER" "$pf" "$RFCS_DIR"
119
- grep -q '| RFC | Status | Title |' "$pf"
120
- grep -q '|-----|--------|-------|' "$pf"
121
- grep -q '| RFC-001 | accepted | foo |' "$pf"
122
- }
123
-
124
- # ── Multi-RFC trace + sort order ─────────────────────────────────────────────
125
-
126
- @test "multiple RFCs trace P → all rows present, sorted by RFC ID asc" {
127
- write_rfc "002" "second" "proposed"
128
- write_rfc "001" "first" "accepted"
129
- pf=$(write_problem "168" "p168")
130
- bash "$HELPER" "$pf" "$RFCS_DIR"
131
- # Both rows present.
132
- grep -q '| RFC-001 | accepted | first |' "$pf"
133
- grep -q '| RFC-002 | proposed | second |' "$pf"
134
- # RFC-001 appears before RFC-002.
135
- rfc_001_line=$(grep -n '| RFC-001 |' "$pf" | head -1 | cut -d: -f1)
136
- rfc_002_line=$(grep -n '| RFC-002 |' "$pf" | head -1 | cut -d: -f1)
137
- [ "$rfc_001_line" -lt "$rfc_002_line" ]
138
- }
139
-
140
- # ── Idempotency ─────────────────────────────────────────────────────────────
141
-
142
- @test "re-running with no claim change is a no-op (idempotent)" {
143
- write_rfc "001" "foo" "accepted"
144
- pf=$(write_problem "168" "p168")
145
- bash "$HELPER" "$pf" "$RFCS_DIR"
146
- hash1=$(shasum "$pf" | cut -d' ' -f1)
147
- bash "$HELPER" "$pf" "$RFCS_DIR"
148
- hash2=$(shasum "$pf" | cut -d' ' -f1)
149
- [ "$hash1" = "$hash2" ]
150
- }
151
-
152
- # ── Status update on existing row ────────────────────────────────────────────
153
-
154
- @test "RFC status changes (proposed → accepted) → table row reflects new status" {
155
- write_rfc "001" "foo" "proposed"
156
- pf=$(write_problem "168" "p168")
157
- bash "$HELPER" "$pf" "$RFCS_DIR"
158
- grep -q '| RFC-001 | proposed | foo |' "$pf"
159
- # Now transition the RFC to accepted (simulate by renaming on disk).
160
- mv "$RFCS_DIR/RFC-001-foo.proposed.md" "$RFCS_DIR/RFC-001-foo.accepted.md"
161
- bash "$HELPER" "$pf" "$RFCS_DIR"
162
- grep -q '| RFC-001 | accepted | foo |' "$pf"
163
- # Old status should no longer be present for that RFC row.
164
- ! grep -q '| RFC-001 | proposed |' "$pf"
165
- }
166
-
167
- # ── Re-trace add/remove ─────────────────────────────────────────────────────
168
-
169
- @test "RFC newly added trace → row appended" {
170
- write_rfc "001" "foo" "accepted"
171
- pf=$(write_problem "168" "p168")
172
- bash "$HELPER" "$pf" "$RFCS_DIR"
173
- grep -q '| RFC-001 |' "$pf"
174
-
175
- # Add a second RFC traced to P168.
176
- write_rfc "002" "bar" "proposed"
177
- bash "$HELPER" "$pf" "$RFCS_DIR"
178
- grep -q '| RFC-001 |' "$pf"
179
- grep -q '| RFC-002 |' "$pf"
180
- }
181
-
182
- @test "RFC trace removed (frontmatter no longer claims P) → row drops" {
183
- write_rfc "001" "foo" "accepted" "[P168]"
184
- write_rfc "002" "bar" "proposed" "[P168]"
185
- pf=$(write_problem "168" "p168")
186
- bash "$HELPER" "$pf" "$RFCS_DIR"
187
- grep -q '| RFC-001 |' "$pf"
188
- grep -q '| RFC-002 |' "$pf"
189
-
190
- # Re-trace RFC-002 to P169 only.
191
- rm -f "$RFCS_DIR/RFC-002-bar.proposed.md"
192
- write_rfc "002" "bar" "proposed" "[P169]"
193
- bash "$HELPER" "$pf" "$RFCS_DIR"
194
- grep -q '| RFC-001 |' "$pf"
195
- ! grep -q '| RFC-002 |' "$pf"
196
- }
197
-
198
- # ── Section placement ───────────────────────────────────────────────────────
199
-
200
- @test "## RFCs section sits before ## Fix Released when present" {
201
- write_rfc "001" "foo" "verifying"
202
- pf=$(write_problem "168" "p168" $'## Fix Released\n\nReleased trailer prose.')
203
- bash "$HELPER" "$pf" "$RFCS_DIR"
204
- rfcs_line=$(grep -n '^## RFCs' "$pf" | head -1 | cut -d: -f1)
205
- fix_released_line=$(grep -n '^## Fix Released' "$pf" | head -1 | cut -d: -f1)
206
- [ "$rfcs_line" -lt "$fix_released_line" ]
207
- }
208
-
209
- @test "## RFCs section appears at EOF when no ## Fix Released section" {
210
- write_rfc "001" "foo" "accepted"
211
- pf=$(write_problem "168" "p168")
212
- bash "$HELPER" "$pf" "$RFCS_DIR"
213
- # ## RFCs is the last `## ` heading in the file.
214
- last_section=$(grep -E '^## ' "$pf" | tail -1)
215
- [[ "$last_section" == "## RFCs" ]]
216
- }
217
-
218
- # ── Multi-problem RFC composition ────────────────────────────────────────────
219
-
220
- @test "RFC tracing two problems updates both ## RFCs sections" {
221
- write_rfc "001" "foo" "accepted" "[P168, P169]"
222
- pf168=$(write_problem "168" "p168")
223
- pf169=$(write_problem "169" "p169")
224
- bash "$HELPER" "$pf168" "$RFCS_DIR"
225
- bash "$HELPER" "$pf169" "$RFCS_DIR"
226
- grep -q '| RFC-001 |' "$pf168"
227
- grep -q '| RFC-001 |' "$pf169"
228
- }
229
-
230
- # ── ## Related preservation ─────────────────────────────────────────────────
231
-
232
- @test "existing ## Related section is preserved when ## RFCs is added" {
233
- write_rfc "001" "foo" "accepted"
234
- pf=$(write_problem "168" "p168")
235
- bash "$HELPER" "$pf" "$RFCS_DIR"
236
- grep -q '^## Related' "$pf"
237
- grep -q '^## RFCs' "$pf"
238
- related_line=$(grep -n '^## Related' "$pf" | head -1 | cut -d: -f1)
239
- rfcs_line=$(grep -n '^## RFCs' "$pf" | head -1 | cut -d: -f1)
240
- # ## Related comes before ## RFCs.
241
- [ "$related_line" -lt "$rfcs_line" ]
242
- }