@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,291 +0,0 @@
1
- #!/usr/bin/env bats
2
-
3
- # @problem P328 — BSD `grep` / `sed` / `awk` on macOS silently mis-process
4
- # UTF-8 multi-byte characters (em-dash, smart quotes) without
5
- # `LC_ALL=en_US.UTF-8` set. Lint detects unprotected invocations so the
6
- # class of silent-wrong-result bugs can't reach the codebase undetected.
7
- #
8
- # Contract: `check-locale-discipline.sh [<repo-root>]` walks scripts under
9
- # `packages/*/scripts/`, `packages/*/hooks/` (incl. nested `lib/`), and
10
- # `packages/*/lib/`, then emits one WARN line per unprotected grep/sed/awk
11
- # invocation. Default Phase 1 advisory exits 0; `WR_LOCALE_DISCIPLINE_WARN_ONLY=0`
12
- # promotes to Phase 2 load-bearing (exit 1 on any violation).
13
- #
14
- # Behavioural fixture (ADR-052 default): every test exercises the script
15
- # against a synthesised packages/ fixture tree containing known-state
16
- # scripts. No grep of SKILL.md / agent prose / source content.
17
- #
18
- # @adr ADR-040 (advisory-then-load-bearing reusable pattern)
19
- # @adr ADR-049 (plugin-bundled scripts; PATH shim)
20
- # @adr ADR-052 (behavioural-tests-default — temp script with known violations)
21
- # @adr ADR-080 (highest-version-wins shim wrapper)
22
- # @adr ADR-005 (Plugin testing strategy — bats coverage)
23
- # @jtbd JTBD-001 (Enforce Governance Without Slowing Down)
24
- # @jtbd JTBD-101 (Extend the Suite with New Plugins)
25
-
26
- setup() {
27
- SCRIPTS_DIR="$(cd "$(dirname "$BATS_TEST_FILENAME")/.." && pwd)"
28
- SCRIPT="$SCRIPTS_DIR/check-locale-discipline.sh"
29
- FIXTURE_ROOT="$(mktemp -d)"
30
- mkdir -p "$FIXTURE_ROOT/packages/demo/scripts"
31
- mkdir -p "$FIXTURE_ROOT/packages/demo/hooks"
32
- mkdir -p "$FIXTURE_ROOT/packages/demo/hooks/lib"
33
- mkdir -p "$FIXTURE_ROOT/packages/demo/lib"
34
- }
35
-
36
- teardown() {
37
- rm -rf "$FIXTURE_ROOT"
38
- }
39
-
40
- # ── Existence + executable ──────────────────────────────────────────────────
41
-
42
- @test "check-locale-discipline: script exists" {
43
- [ -f "$SCRIPT" ]
44
- }
45
-
46
- @test "check-locale-discipline: script is executable" {
47
- [ -x "$SCRIPT" ]
48
- }
49
-
50
- # ── Negative cases (violations expected) ────────────────────────────────────
51
-
52
- @test "check-locale-discipline: grep without LC_ALL emits WARN and counts violation" {
53
- cat > "$FIXTURE_ROOT/packages/demo/scripts/raw-grep.sh" <<'EOF'
54
- #!/usr/bin/env bash
55
- grep -c '^### ' README.md
56
- EOF
57
- run "$SCRIPT" "$FIXTURE_ROOT"
58
- [ "$status" -eq 0 ] # Phase 1 advisory
59
- echo "$output" | grep -E "WARN.*raw-grep.sh:2.*grep without preceding LC_ALL"
60
- echo "$output" | grep -E "1 violation"
61
- }
62
-
63
- @test "check-locale-discipline: sed without LC_ALL emits WARN" {
64
- cat > "$FIXTURE_ROOT/packages/demo/scripts/raw-sed.sh" <<'EOF'
65
- #!/usr/bin/env bash
66
- sed -n '/^### /p' README.md
67
- EOF
68
- run "$SCRIPT" "$FIXTURE_ROOT"
69
- [ "$status" -eq 0 ]
70
- echo "$output" | grep -E "WARN.*raw-sed.sh:2.*sed without preceding LC_ALL"
71
- }
72
-
73
- @test "check-locale-discipline: awk without LC_ALL emits WARN" {
74
- cat > "$FIXTURE_ROOT/packages/demo/scripts/raw-awk.sh" <<'EOF'
75
- #!/usr/bin/env bash
76
- awk '/^### /' README.md
77
- EOF
78
- run "$SCRIPT" "$FIXTURE_ROOT"
79
- [ "$status" -eq 0 ]
80
- echo "$output" | grep -E "WARN.*raw-awk.sh:2.*awk without preceding LC_ALL"
81
- }
82
-
83
- # ── Positive cases (file-wide protection — silent pass) ─────────────────────
84
-
85
- @test "check-locale-discipline: file-wide export LC_ALL above grep — silent pass" {
86
- cat > "$FIXTURE_ROOT/packages/demo/scripts/protected.sh" <<'EOF'
87
- #!/usr/bin/env bash
88
- export LC_ALL=en_US.UTF-8
89
- grep -c '^### ' README.md
90
- sed -n '/^### /p' README.md
91
- awk '/^### /' README.md
92
- EOF
93
- run "$SCRIPT" "$FIXTURE_ROOT"
94
- [ "$status" -eq 0 ]
95
- ! echo "$output" | grep -qE "protected.sh.*WARN"
96
- echo "$output" | grep -E "clean"
97
- }
98
-
99
- @test "check-locale-discipline: inline LC_ALL= prefix on same line — silent pass" {
100
- cat > "$FIXTURE_ROOT/packages/demo/scripts/inline.sh" <<'EOF'
101
- #!/usr/bin/env bash
102
- LC_ALL=en_US.UTF-8 grep -c '^### ' README.md
103
- LC_ALL=en_US.UTF-8 sed -n '/^### /p' README.md
104
- LC_ALL=en_US.UTF-8 awk '/^### /' README.md
105
- EOF
106
- run "$SCRIPT" "$FIXTURE_ROOT"
107
- [ "$status" -eq 0 ]
108
- ! echo "$output" | grep -qE "inline.sh.*WARN"
109
- }
110
-
111
- # ── Edge cases ──────────────────────────────────────────────────────────────
112
-
113
- @test "check-locale-discipline: multiple grep/sed/awk on one line — line is flagged" {
114
- cat > "$FIXTURE_ROOT/packages/demo/scripts/multi.sh" <<'EOF'
115
- #!/usr/bin/env bash
116
- grep -c '^### ' README.md | sed 's/ //g' | awk '{print $1}'
117
- EOF
118
- run "$SCRIPT" "$FIXTURE_ROOT"
119
- [ "$status" -eq 0 ]
120
- # At least one tool is reported; we don't over-specify the count.
121
- echo "$output" | grep -E "WARN.*multi.sh:2.*(grep|sed|awk) without preceding LC_ALL"
122
- }
123
-
124
- @test "check-locale-discipline: git grep is skipped" {
125
- cat > "$FIXTURE_ROOT/packages/demo/scripts/git-grep.sh" <<'EOF'
126
- #!/usr/bin/env bash
127
- git grep -nE 'pattern' -- '*.md'
128
- EOF
129
- run "$SCRIPT" "$FIXTURE_ROOT"
130
- [ "$status" -eq 0 ]
131
- ! echo "$output" | grep -qE "git-grep.sh.*WARN"
132
- }
133
-
134
- @test "check-locale-discipline: heredoc body containing grep is not flagged" {
135
- cat > "$FIXTURE_ROOT/packages/demo/scripts/heredoc.sh" <<'EOF'
136
- #!/usr/bin/env bash
137
- cat <<'INNER'
138
- The way to do this is to run: grep '^### ' README.md
139
- And then: sed -n '/^### /p'
140
- INNER
141
- echo "done"
142
- EOF
143
- run "$SCRIPT" "$FIXTURE_ROOT"
144
- [ "$status" -eq 0 ]
145
- # Heredoc body lines must NOT produce WARNs.
146
- ! echo "$output" | grep -qE "heredoc.sh:[34].*WARN"
147
- }
148
-
149
- @test "check-locale-discipline: comment-only line is not flagged" {
150
- cat > "$FIXTURE_ROOT/packages/demo/scripts/commented.sh" <<'EOF'
151
- #!/usr/bin/env bash
152
- # Future work: replace this awk with a sed | grep pipeline.
153
- echo "no grep here"
154
- EOF
155
- run "$SCRIPT" "$FIXTURE_ROOT"
156
- [ "$status" -eq 0 ]
157
- ! echo "$output" | grep -qE "commented.sh.*WARN"
158
- }
159
-
160
- @test "check-locale-discipline: identifiers containing grep/sed/awk substrings are not flagged" {
161
- cat > "$FIXTURE_ROOT/packages/demo/scripts/identifiers.sh" <<'EOF'
162
- #!/usr/bin/env bash
163
- grep_helper="something"
164
- result_from_sed=42
165
- my_awkward_var="x"
166
- echo "$grep_helper $result_from_sed $my_awkward_var"
167
- EOF
168
- run "$SCRIPT" "$FIXTURE_ROOT"
169
- [ "$status" -eq 0 ]
170
- ! echo "$output" | grep -qE "identifiers.sh.*WARN"
171
- }
172
-
173
- # ── Scope: hooks/ + lib/ + nested hooks/lib/ ────────────────────────────────
174
-
175
- @test "check-locale-discipline: scans packages/*/hooks/ scripts" {
176
- cat > "$FIXTURE_ROOT/packages/demo/hooks/raw-grep-hook.sh" <<'EOF'
177
- #!/usr/bin/env bash
178
- grep -c '^### ' README.md
179
- EOF
180
- run "$SCRIPT" "$FIXTURE_ROOT"
181
- [ "$status" -eq 0 ]
182
- echo "$output" | grep -E "WARN.*hooks/raw-grep-hook.sh:2"
183
- }
184
-
185
- @test "check-locale-discipline: scans packages/*/hooks/lib/ scripts" {
186
- cat > "$FIXTURE_ROOT/packages/demo/hooks/lib/nested.sh" <<'EOF'
187
- #!/usr/bin/env bash
188
- awk '/^### /' README.md
189
- EOF
190
- run "$SCRIPT" "$FIXTURE_ROOT"
191
- [ "$status" -eq 0 ]
192
- echo "$output" | grep -E "WARN.*hooks/lib/nested.sh:2"
193
- }
194
-
195
- @test "check-locale-discipline: scans packages/*/lib/ scripts" {
196
- cat > "$FIXTURE_ROOT/packages/demo/lib/raw-sed-lib.sh" <<'EOF'
197
- #!/usr/bin/env bash
198
- sed -n '/^### /p' README.md
199
- EOF
200
- run "$SCRIPT" "$FIXTURE_ROOT"
201
- [ "$status" -eq 0 ]
202
- echo "$output" | grep -E "WARN.*lib/raw-sed-lib.sh:2"
203
- }
204
-
205
- # ── Phase 1 advisory vs Phase 2 load-bearing ────────────────────────────────
206
-
207
- @test "check-locale-discipline: Phase 1 default exits 0 even with violations" {
208
- cat > "$FIXTURE_ROOT/packages/demo/scripts/violation.sh" <<'EOF'
209
- #!/usr/bin/env bash
210
- grep -c '^### ' README.md
211
- EOF
212
- run "$SCRIPT" "$FIXTURE_ROOT"
213
- [ "$status" -eq 0 ]
214
- }
215
-
216
- @test "check-locale-discipline: Phase 2 load-bearing exits 1 on violations" {
217
- cat > "$FIXTURE_ROOT/packages/demo/scripts/violation.sh" <<'EOF'
218
- #!/usr/bin/env bash
219
- grep -c '^### ' README.md
220
- EOF
221
- WR_LOCALE_DISCIPLINE_WARN_ONLY=0 run "$SCRIPT" "$FIXTURE_ROOT"
222
- [ "$status" -eq 1 ]
223
- }
224
-
225
- @test "check-locale-discipline: Phase 2 load-bearing exits 0 on clean tree" {
226
- cat > "$FIXTURE_ROOT/packages/demo/scripts/clean.sh" <<'EOF'
227
- #!/usr/bin/env bash
228
- export LC_ALL=en_US.UTF-8
229
- grep -c '^### ' README.md
230
- EOF
231
- WR_LOCALE_DISCIPLINE_WARN_ONLY=0 run "$SCRIPT" "$FIXTURE_ROOT"
232
- [ "$status" -eq 0 ]
233
- }
234
-
235
- # ── Argument and error handling ─────────────────────────────────────────────
236
-
237
- @test "check-locale-discipline: missing repo-root directory exits 2" {
238
- run "$SCRIPT" "$FIXTURE_ROOT/does-not-exist"
239
- [ "$status" -eq 2 ]
240
- echo "$output" | grep -iE "not a directory"
241
- }
242
-
243
- @test "check-locale-discipline: repo-root without packages/ subdir exits 2" {
244
- mkdir -p "$FIXTURE_ROOT/empty"
245
- run "$SCRIPT" "$FIXTURE_ROOT/empty"
246
- [ "$status" -eq 2 ]
247
- echo "$output" | grep -iE "no packages/"
248
- }
249
-
250
- @test "check-locale-discipline: defaults to current working directory when no arg" {
251
- cat > "$FIXTURE_ROOT/packages/demo/scripts/violation.sh" <<'EOF'
252
- #!/usr/bin/env bash
253
- grep -c '^### ' README.md
254
- EOF
255
- cd "$FIXTURE_ROOT"
256
- run "$SCRIPT"
257
- [ "$status" -eq 0 ]
258
- echo "$output" | grep -E "WARN.*scripts/violation.sh:2"
259
- }
260
-
261
- # ── Output shape ────────────────────────────────────────────────────────────
262
-
263
- @test "check-locale-discipline: clean tree emits summary on stdout" {
264
- cat > "$FIXTURE_ROOT/packages/demo/scripts/clean.sh" <<'EOF'
265
- #!/usr/bin/env bash
266
- export LC_ALL=en_US.UTF-8
267
- grep -c '^### ' README.md
268
- EOF
269
- run "$SCRIPT" "$FIXTURE_ROOT"
270
- [ "$status" -eq 0 ]
271
- echo "$output" | grep -E "^check-locale-discipline: clean"
272
- }
273
-
274
- @test "check-locale-discipline: violation summary cites P328" {
275
- cat > "$FIXTURE_ROOT/packages/demo/scripts/violation.sh" <<'EOF'
276
- #!/usr/bin/env bash
277
- grep -c '^### ' README.md
278
- EOF
279
- run "$SCRIPT" "$FIXTURE_ROOT"
280
- [ "$status" -eq 0 ]
281
- echo "$output" | grep -E "P328"
282
- }
283
-
284
- # ── Self-application: lint script itself is locale-discipline-compliant ─────
285
-
286
- @test "check-locale-discipline: own script declares export LC_ALL at top" {
287
- # The lint walks UTF-8 prose; it must lead by example. This guards
288
- # against a future edit that strips the export and reintroduces P328
289
- # in the lint itself.
290
- head -80 "$SCRIPT" | grep -qE "^export LC_ALL=en_US.UTF-8$"
291
- }
@@ -1,192 +0,0 @@
1
- #!/usr/bin/env bats
2
-
3
- # @problem P134 — docs/problems/README.md line 3 narrative-blob accumulator
4
- # bloat. Sibling to P099 (briefing tier 3) on a different surface. The
5
- # "Last reviewed" line accumulates session-summary fragments unbounded;
6
- # at ~62 KB it breaks the Read tool entirely (25K-token limit on the
7
- # whole file regardless of offset/limit). P134 promotes the same
8
- # advisory-triplet pattern P099 documented (advisory script + behavioural
9
- # bats + ADR-040-tier-budget enforcement clause) to this surface.
10
- #
11
- # Contract: `check-problems-readme-budget.sh [<readme-path>]` is a
12
- # diagnose-only advisory script. It reads `docs/problems/README.md`
13
- # (or the supplied path), measures the byte size of line 3, and reports
14
- # overflow when line 3 is at or above the configured threshold (default
15
- # 5120 bytes per ADR-040 Tier 3 envelope; overridable via the
16
- # `PROBLEMS_README_LINE3_MAX_BYTES` env var).
17
- #
18
- # Exit codes:
19
- # 0 = always (advisory only — overflow is signal, not failure)
20
- # 2 = parse error (README path missing or unreadable)
21
- #
22
- # Output format on overflow (one line, terse machine-readable per
23
- # ADR-038 progressive-disclosure budget):
24
- # OVER <readme-path> line=3 bytes=<N> threshold=<N>
25
- #
26
- # Output is empty (no lines) when line 3 is under the threshold.
27
- #
28
- # The script is read-only — it does NOT mutate the README. Truncation
29
- # is owned by the per-operation refresh contracts in `manage-problem`
30
- # Step 5 P094 + Step 7 P062 (and the sibling skills `transition-problem`,
31
- # `transition-problems`, `review-problems`, `reconcile-readme`).
32
- #
33
- # @jtbd JTBD-001 (Enforce Governance Without Slowing Down — restores
34
- # Read-tool affordance to the highest-traffic problems-management surface)
35
- # @jtbd JTBD-006 (Progress the Backlog While I'm Away — every AFK iter's
36
- # manage-problem call previously paid an awk/grep workaround tax)
37
- # @jtbd JTBD-101 (Extend the Suite with Clear Patterns — re-applies P099's
38
- # advisory-script + bats + ADR-tier-budget triplet to a new surface,
39
- # exactly the reusable shape ADR-040 line 92 documents)
40
- #
41
- # Cross-reference:
42
- # P134: docs/problems/134-docs-problems-readme-md-line-3-narrative-blob-accumulator-bloat-sibling-p099.*.md
43
- # P099: docs/problems/099-briefing-md-grows-unbounded-via-run-retro-appends-violating-progressive-disclosure.*.md
44
- # ADR-040 — Session-start briefing surface (Tier 3 budget; line 92's
45
- # reusable-pattern note explicitly names "problems index" as a
46
- # candidate surface for this triplet)
47
- # ADR-038 — Progressive disclosure (per-row terse budget)
48
- # ADR-013 Rule 6 — non-interactive fail-safe (advisory-only / exit 0)
49
- # ADR-005 — Plugin testing strategy (script-level bats governance)
50
-
51
- setup() {
52
- SCRIPTS_DIR="$(cd "$(dirname "$BATS_TEST_FILENAME")/.." && pwd)"
53
- SCRIPT="$SCRIPTS_DIR/check-problems-readme-budget.sh"
54
- FIXTURE_DIR="$(mktemp -d)"
55
- }
56
-
57
- teardown() {
58
- rm -rf "$FIXTURE_DIR"
59
- }
60
-
61
- # Helper: write a problems README fixture with the given line-3 byte size.
62
- # Lines 1, 2 are short header; line 3 is the synthetic "Last reviewed"
63
- # blob padded to target_bytes; lines 4+ contain a short stub so the
64
- # multi-line shape mirrors the production README.
65
- write_problems_readme() {
66
- local path="$1"
67
- local target_bytes="$2"
68
- : > "$path"
69
- printf '# Problem Backlog\n\n' >> "$path"
70
- if [ "$target_bytes" -gt 0 ]; then
71
- # Build a single line of exactly target_bytes bytes (no trailing
72
- # newline before the byte budget completes). The newline at the
73
- # end is part of the file structure but not counted in line 3's
74
- # byte size — `awk 'NR==3' | wc -c` would include it; the script
75
- # under test must strip it to match the threshold semantics.
76
- local prefix='> Last reviewed: '
77
- local prefix_size=${#prefix}
78
- local body_target=$(( target_bytes - prefix_size ))
79
- if [ "$body_target" -gt 0 ]; then
80
- printf '%s' "$prefix" >> "$path"
81
- # Append body_target dots — a single contiguous line.
82
- printf '%.0s.' $(seq 1 "$body_target") >> "$path"
83
- else
84
- # target smaller than prefix — emit only the requested bytes
85
- printf '%.0s.' $(seq 1 "$target_bytes") >> "$path"
86
- fi
87
- printf '\n' >> "$path"
88
- else
89
- printf '\n' >> "$path"
90
- fi
91
- printf '\n## WSJF Rankings\n\n(stub)\n' >> "$path"
92
- }
93
-
94
- # ── Existence + executable ──────────────────────────────────────────────────
95
-
96
- @test "check-problems-readme-budget: script exists" {
97
- [ -f "$SCRIPT" ]
98
- }
99
-
100
- @test "check-problems-readme-budget: script is executable" {
101
- [ -x "$SCRIPT" ]
102
- }
103
-
104
- # ── Default-threshold behaviour (5120 bytes per ADR-040 Tier 3 envelope) ────
105
-
106
- @test "check-problems-readme-budget: line 3 well under threshold produces no output and exits 0" {
107
- write_problems_readme "$FIXTURE_DIR/README.md" 1024
108
- run "$SCRIPT" "$FIXTURE_DIR/README.md"
109
- [ "$status" -eq 0 ]
110
- [ -z "$output" ]
111
- }
112
-
113
- @test "check-problems-readme-budget: line 3 at exactly the default threshold emits OVER (>= boundary)" {
114
- write_problems_readme "$FIXTURE_DIR/README.md" 5120
115
- run "$SCRIPT" "$FIXTURE_DIR/README.md"
116
- [ "$status" -eq 0 ]
117
- echo "$output" | grep -E "^OVER .*README.md line=3 bytes=5120 threshold=5120$"
118
- }
119
-
120
- @test "check-problems-readme-budget: line 3 well over threshold emits OVER with bytes + threshold" {
121
- write_problems_readme "$FIXTURE_DIR/README.md" 12000
122
- run "$SCRIPT" "$FIXTURE_DIR/README.md"
123
- [ "$status" -eq 0 ]
124
- echo "$output" | grep -E "^OVER .*README.md line=3 bytes=12000 threshold=5120$"
125
- }
126
-
127
- @test "check-problems-readme-budget: short line 3 (single fragment ~600 bytes) produces no output" {
128
- write_problems_readme "$FIXTURE_DIR/README.md" 600
129
- run "$SCRIPT" "$FIXTURE_DIR/README.md"
130
- [ "$status" -eq 0 ]
131
- [ -z "$output" ]
132
- }
133
-
134
- # ── Configurable threshold via env var ──────────────────────────────────────
135
-
136
- @test "check-problems-readme-budget: PROBLEMS_README_LINE3_MAX_BYTES env var overrides default" {
137
- write_problems_readme "$FIXTURE_DIR/README.md" 3000
138
- # Default 5120: under threshold, no output. With env var set to 2000:
139
- # over threshold, expect OVER line.
140
- PROBLEMS_README_LINE3_MAX_BYTES=2000 run "$SCRIPT" "$FIXTURE_DIR/README.md"
141
- [ "$status" -eq 0 ]
142
- echo "$output" | grep -E "^OVER .*README.md line=3 bytes=3000 threshold=2000$"
143
- }
144
-
145
- @test "check-problems-readme-budget: env var threshold of 0 emits OVER for non-empty line 3 (sanity)" {
146
- write_problems_readme "$FIXTURE_DIR/README.md" 100
147
- PROBLEMS_README_LINE3_MAX_BYTES=0 run "$SCRIPT" "$FIXTURE_DIR/README.md"
148
- [ "$status" -eq 0 ]
149
- echo "$output" | grep -E "^OVER .*README.md line=3 bytes=100 threshold=0$"
150
- }
151
-
152
- # ── Argument and error handling ─────────────────────────────────────────────
153
-
154
- @test "check-problems-readme-budget: defaults to docs/problems/README.md when no arg provided" {
155
- cd "$FIXTURE_DIR"
156
- mkdir -p docs/problems
157
- write_problems_readme docs/problems/README.md 8000
158
- run "$SCRIPT"
159
- [ "$status" -eq 0 ]
160
- echo "$output" | grep -E "^OVER docs/problems/README.md line=3 bytes=8000 threshold=5120$"
161
- }
162
-
163
- @test "check-problems-readme-budget: missing README path exits 2 with parse error on stderr" {
164
- run "$SCRIPT" "$FIXTURE_DIR/does-not-exist/README.md"
165
- [ "$status" -eq 2 ]
166
- echo "$output" | grep -iE "not found|missing|does not exist"
167
- }
168
-
169
- @test "check-problems-readme-budget: file with no line 3 (only 2 lines) exits 0 with no output" {
170
- printf '# Problem Backlog\n\n' > "$FIXTURE_DIR/README.md"
171
- run "$SCRIPT" "$FIXTURE_DIR/README.md"
172
- [ "$status" -eq 0 ]
173
- [ -z "$output" ]
174
- }
175
-
176
- @test "check-problems-readme-budget: file with empty line 3 exits 0 with no output" {
177
- printf '# Problem Backlog\n\n\n## WSJF Rankings\n\n(stub)\n' > "$FIXTURE_DIR/README.md"
178
- run "$SCRIPT" "$FIXTURE_DIR/README.md"
179
- [ "$status" -eq 0 ]
180
- [ -z "$output" ]
181
- }
182
-
183
- # ── Read-only contract ──────────────────────────────────────────────────────
184
-
185
- @test "check-problems-readme-budget: script does not mutate the README under audit" {
186
- write_problems_readme "$FIXTURE_DIR/README.md" 12000
187
- pre_hash=$(shasum -a 256 "$FIXTURE_DIR/README.md" | awk '{print $1}')
188
- run "$SCRIPT" "$FIXTURE_DIR/README.md"
189
- [ "$status" -eq 0 ]
190
- post_hash=$(shasum -a 256 "$FIXTURE_DIR/README.md" | awk '{print $1}')
191
- [ "$pre_hash" = "$post_hash" ]
192
- }
@@ -1,69 +0,0 @@
1
- #!/usr/bin/env bats
2
- # Behavioural test for check-rfc-has-stories.sh (ADR-089 — every RFC has >=1 story).
3
- # The predicate exits non-zero when an RFC's `stories:` frontmatter is empty or
4
- # missing (the empty-stories fallback ADR-089 removes); exit 0 when >=1 story is
5
- # listed. This is the load-bearing detection half of the proposed->accepted gate.
6
- #
7
- # @adr ADR-089 (every RFC has at least one story)
8
- # @problem P404 (implement ADR-089 + ADR-090)
9
-
10
- setup() {
11
- REPO_ROOT="$(cd "$(dirname "$BATS_TEST_FILENAME")/../../../.." && pwd)"
12
- SCRIPT="${REPO_ROOT}/packages/itil/scripts/check-rfc-has-stories.sh"
13
- TMPD="$(mktemp -d)"
14
- }
15
- teardown() { rm -rf "$TMPD"; }
16
-
17
- @test "check-rfc-has-stories: empty stories: [] is REJECTED (exit non-zero + directive)" {
18
- cat > "$TMPD/RFC-901-empty.proposed.md" <<'EOF'
19
- ---
20
- status: proposed
21
- problems: [P170]
22
- stories: []
23
- ---
24
- # RFC-901: empty
25
- EOF
26
- run bash "$SCRIPT" "$TMPD/RFC-901-empty.proposed.md"
27
- [ "$status" -ne 0 ]
28
- [[ "$output" == *"stories"* ]]
29
- }
30
-
31
- @test "check-rfc-has-stories: missing stories: field is REJECTED" {
32
- cat > "$TMPD/RFC-902-none.proposed.md" <<'EOF'
33
- ---
34
- status: proposed
35
- problems: [P170]
36
- ---
37
- # RFC-902: no stories field
38
- EOF
39
- run bash "$SCRIPT" "$TMPD/RFC-902-none.proposed.md"
40
- [ "$status" -ne 0 ]
41
- [[ "$output" == *"stories"* ]]
42
- }
43
-
44
- @test "check-rfc-has-stories: inline >=1 story is ACCEPTED (exit 0)" {
45
- cat > "$TMPD/RFC-903-ok.proposed.md" <<'EOF'
46
- ---
47
- status: proposed
48
- problems: [P170]
49
- stories: [STORY-020, STORY-021]
50
- ---
51
- # RFC-903: has stories
52
- EOF
53
- run bash "$SCRIPT" "$TMPD/RFC-903-ok.proposed.md"
54
- [ "$status" -eq 0 ]
55
- }
56
-
57
- @test "check-rfc-has-stories: block-list >=1 story is ACCEPTED (exit 0)" {
58
- cat > "$TMPD/RFC-904-block.proposed.md" <<'EOF'
59
- ---
60
- status: proposed
61
- problems: [P170]
62
- stories:
63
- - STORY-020
64
- ---
65
- # RFC-904: block-list stories
66
- EOF
67
- run bash "$SCRIPT" "$TMPD/RFC-904-block.proposed.md"
68
- [ "$status" -eq 0 ]
69
- }
@@ -1,108 +0,0 @@
1
- #!/usr/bin/env bats
2
-
3
- # @problem P310 — RFCs carry independent decisions invisible to the ADR-066
4
- # human-oversight net. ADR-070 closes the blind spot; this lint enforces it.
5
- # @adr ADR-070 (RFCs hold no independent decisions — the invariant under test)
6
- # @adr ADR-052 (behavioural-tests-default — this is an artefact-state behavioural
7
- # assertion: it RUNS the checker against fixture RFC corpora + the real corpus
8
- # and asserts the verdict (exit code + output). It does NOT structurally grep
9
- # the checker's own source, the SKILL.md, or any agent prose — that would be
10
- # the P081 structural-test-disguised-as-behavioural anti-pattern.)
11
- # @adr ADR-071 (every fix via RFC — composes; the lint guards the RFC corpus)
12
- #
13
- # Contract under test (ADR-070 § Confirmation): no RFC body in docs/rfcs/
14
- # contains a "Considered Options / Alternatives Rejected" HEADING block
15
- # without a matching `adrs:` frontmatter reference. The detector targets a
16
- # markdown heading, never a prose mention of the phrase.
17
-
18
- setup() {
19
- REPO_ROOT="$(cd "$(dirname "$BATS_TEST_FILENAME")/../../../.." && pwd)"
20
- SCRIPT="$REPO_ROOT/packages/itil/scripts/check-rfc-rejected-alternatives.sh"
21
- FIXTURE_DIR="$(mktemp -d)"
22
- }
23
-
24
- teardown() {
25
- rm -rf "$FIXTURE_DIR"
26
- }
27
-
28
- # ── Fixture helper: write an RFC file with given adrs-line + body ────────────
29
- write_rfc() {
30
- local name="$1" adrs_line="$2" body="$3"
31
- cat > "$FIXTURE_DIR/$name" <<EOF
32
- ---
33
- status: accepted
34
- rfc-id: ${name%.md}
35
- problems: [P999]
36
- $adrs_line
37
- stories: []
38
- ---
39
-
40
- # ${name%.md}: fixture
41
-
42
- ## Summary
43
-
44
- A fixture RFC.
45
-
46
- $body
47
- EOF
48
- }
49
-
50
- @test "violation: rejected-alternatives heading block WITH empty adrs: -> exit 1 + VIOLATION" {
51
- write_rfc "RFC-901-bad.md" "adrs: []" $'## Considered Options / Alternatives Rejected\n\n- F1 alternative rejected: foo.'
52
- run bash "$SCRIPT" "$FIXTURE_DIR"
53
- [ "$status" -eq 1 ]
54
- [[ "$output" == *"VIOLATION"* ]]
55
- [[ "$output" == *"RFC-901-bad.md"* ]]
56
- }
57
-
58
- @test "allowed: rejected-alternatives heading block WITH a matching adrs: reference -> exit 0 (clean)" {
59
- write_rfc "RFC-902-homed.md" "adrs: [ADR-072, ADR-073]" $'## Considered Options / Alternatives Rejected\n\n- The contested choice is recorded in ADR-072; this block references it.'
60
- run bash "$SCRIPT" "$FIXTURE_DIR"
61
- [ "$status" -eq 0 ]
62
- [[ "$output" == *"clean"* ]]
63
- }
64
-
65
- @test "clean: no rejected-alternatives block, empty adrs: -> exit 0" {
66
- write_rfc "RFC-903-scope.md" "adrs: []" $'## Scope\n\nPure scope + decomposition + traces. No decisions here.'
67
- run bash "$SCRIPT" "$FIXTURE_DIR"
68
- [ "$status" -eq 0 ]
69
- [[ "$output" == *"clean"* ]]
70
- }
71
-
72
- @test "prose mention (not a heading) of the phrase does NOT trigger -> exit 0" {
73
- # Guards the RFC-005 retrofit-banner false positive: a blockquote/prose line
74
- # mentioning the struck section must not be flagged.
75
- write_rfc "RFC-904-retrofit.md" "adrs: []" $'> Retrofitted: this RFC originally carried a "Considered Options / Alternatives Rejected" section, now struck per ADR-070.'
76
- run bash "$SCRIPT" "$FIXTURE_DIR"
77
- [ "$status" -eq 0 ]
78
- [[ "$output" == *"clean"* ]]
79
- }
80
-
81
- @test "variant heading 'Alternatives Rejected' WITH empty adrs: -> exit 1" {
82
- write_rfc "RFC-905-variant.md" "adrs: []" $'### Alternatives Rejected\n\n- rejected: bar.'
83
- run bash "$SCRIPT" "$FIXTURE_DIR"
84
- [ "$status" -eq 1 ]
85
- [[ "$output" == *"RFC-905-variant.md"* ]]
86
- }
87
-
88
- @test "mixed corpus: one violation among clean RFCs -> exit 1, names only the offender" {
89
- write_rfc "RFC-906-ok.md" "adrs: [ADR-001]" $'## Considered Options\n\n- references ADR-001.'
90
- write_rfc "RFC-907-bad.md" "adrs: []" $'## Considered Options\n\n- no adr.'
91
- write_rfc "RFC-908-scope.md" "adrs: []" $'## Scope\n\nclean.'
92
- run bash "$SCRIPT" "$FIXTURE_DIR"
93
- [ "$status" -eq 1 ]
94
- [[ "$output" == *"RFC-907-bad.md"* ]]
95
- [[ "$output" != *"RFC-906-ok.md"* ]]
96
- [[ "$output" != *"RFC-908-scope.md"* ]]
97
- }
98
-
99
- @test "non-existent directory -> exit 2 (usage error)" {
100
- run bash "$SCRIPT" "$FIXTURE_DIR/does-not-exist"
101
- [ "$status" -eq 2 ]
102
- }
103
-
104
- @test "dogfood: the real docs/rfcs/ corpus is clean -> exit 0" {
105
- run bash "$SCRIPT" "$REPO_ROOT/docs/rfcs"
106
- [ "$status" -eq 0 ]
107
- [[ "$output" == *"clean"* ]]
108
- }