@windyroad/retrospective 0.27.1 → 0.27.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 (33) hide show
  1. package/.claude-plugin/plugin.json +1 -1
  2. package/package.json +5 -2
  3. package/hooks/test/retrospective-deferral-census.bats +0 -112
  4. package/hooks/test/retrospective-readme-jtbd-currency.bats +0 -312
  5. package/scripts/test/check-ask-hygiene.bats +0 -262
  6. package/scripts/test/check-autocreate-rfc-scope.bats +0 -250
  7. package/scripts/test/check-briefing-budgets.bats +0 -349
  8. package/scripts/test/check-internal-id-leaks.bats +0 -286
  9. package/scripts/test/check-plugin-maturity-drift.bats +0 -269
  10. package/scripts/test/check-readme-jtbd-currency.bats +0 -165
  11. package/scripts/test/check-skill-md-budgets.bats +0 -336
  12. package/scripts/test/check-tarball-shipped-shims.bats +0 -284
  13. package/scripts/test/check-tickets-deferred-cause.bats +0 -330
  14. package/scripts/test/list-plugin-attribution.bats +0 -149
  15. package/scripts/test/measure-context-budget.bats +0 -298
  16. package/skills/analyze-context/test/analyze-context-skill-contract.bats +0 -142
  17. package/skills/migrate-briefing/test/migrate-briefing-contract.bats +0 -105
  18. package/skills/migrate-briefing/test/migrate-briefing-fixture.bats +0 -242
  19. package/skills/run-retro/test/run-retro-anti-pattern-clause.bats +0 -87
  20. package/skills/run-retro/test/run-retro-codification-candidates.bats +0 -168
  21. package/skills/run-retro/test/run-retro-context-usage-step-2c.bats +0 -156
  22. package/skills/run-retro/test/run-retro-pipeline-instability-scan.bats +0 -122
  23. package/skills/run-retro/test/run-retro-signal-vs-noise.bats +0 -137
  24. package/skills/run-retro/test/run-retro-skill-candidates.bats +0 -116
  25. package/skills/run-retro/test/run-retro-stage-1-fallback-gating.bats +0 -65
  26. package/skills/run-retro/test/run-retro-step-2d-r6-auto-flag.bats +0 -82
  27. package/skills/run-retro/test/run-retro-step-3-tier-3-branch-b-evidence-based.bats +0 -189
  28. package/skills/run-retro/test/run-retro-step-4a-cross-plugin-dispatch.bats +0 -114
  29. package/skills/run-retro/test/run-retro-step-4a-prior-session-evidence-drain.bats +0 -168
  30. package/skills/run-retro/test/run-retro-step-4a-recovery-path.bats +0 -84
  31. package/skills/run-retro/test/run-retro-step-4b-retro-auto-ticket-carveout.bats +0 -115
  32. package/skills/run-retro/test/run-retro-ticket-first-flow.bats +0 -161
  33. package/skills/run-retro/test/run-retro-verification-close-housekeeping.bats +0 -132
@@ -1,269 +0,0 @@
1
- #!/usr/bin/env bats
2
-
3
- # @problem P238 — Phase 3b drift detector behavioural confirmation.
4
- # @problem P087 — parent: plugin maturity battle-hardening signal.
5
- # @problem P152 — sibling drift-detector pattern (JTBD-currency).
6
- #
7
- # Contract under test:
8
- # `packages/retrospective/scripts/check-plugin-maturity-drift.sh` is an
9
- # advisory drift detector. It compares each plugin's rendered README
10
- # maturity badge against the canonical `plugin.json` `maturity:` field
11
- # and emits NDJSON-per-drift signals to stdout. Exit code 0 always per
12
- # ADR-013 Rule 6 — drift is data, not failure.
13
- #
14
- # Drift classes:
15
- # missing-badge — plugin.json has maturity but README has no badge
16
- # stale-band — badge band mismatches canonical record
17
- # orphan-badge — README has badge but plugin.json has no maturity
18
- # anti-pattern-section — README has standalone ## Maturity section
19
- # anti-pattern-url — README has shields.io / SVG badge URL
20
- #
21
- # @adr ADR-063 (Plugin maturity presentation layer — Phase 3b contract)
22
- # @adr ADR-051 (Sibling drift-detector pattern — `check-readme-jtbd-currency.sh`)
23
- # @adr ADR-013 Rule 6 (non-interactive fail-safe — exit 0 always)
24
- # @adr ADR-049 (Shim grammar — `wr-retrospective-check-plugin-maturity-drift` on $PATH)
25
- # @adr ADR-052 (Behavioural tests default)
26
-
27
- setup() {
28
- SCRIPTS_DIR="$(cd "$(dirname "$BATS_TEST_FILENAME")/.." && pwd)"
29
- SCRIPT="$SCRIPTS_DIR/check-plugin-maturity-drift.sh"
30
- FIXTURE_DIR="$(mktemp -d)"
31
- PROJECT_ROOT="$FIXTURE_DIR/project"
32
- PKG_DIR="$PROJECT_ROOT/packages"
33
- mkdir -p "$PKG_DIR"
34
- }
35
-
36
- teardown() {
37
- rm -rf "$FIXTURE_DIR"
38
- }
39
-
40
- # Helper: write a synthetic plugin layout with plugin.json + README.md
41
- make_plugin() {
42
- local name="$1"
43
- local plugin_json="$2"
44
- local readme="$3"
45
- local pkg="$PKG_DIR/$name"
46
- mkdir -p "$pkg/.claude-plugin"
47
- printf '%s\n' "$plugin_json" > "$pkg/.claude-plugin/plugin.json"
48
- printf '%s\n' "$readme" > "$pkg/README.md"
49
- }
50
-
51
- # ── Pre-checks ──────────────────────────────────────────────────────────────
52
-
53
- @test "script file exists and is executable" {
54
- [ -f "$SCRIPT" ]
55
- [ -x "$SCRIPT" ]
56
- }
57
-
58
- @test "missing packages dir exits 2 with error message on stderr" {
59
- run bash "$SCRIPT" "$FIXTURE_DIR/does-not-exist"
60
- [ "$status" -eq 2 ]
61
- [[ "$output" == *"packages dir not found"* ]]
62
- }
63
-
64
- @test "empty packages dir exits 0 with empty stdout" {
65
- run bash "$SCRIPT" "$PKG_DIR"
66
- [ "$status" -eq 0 ]
67
- [[ "$output" == *"TOTAL"* ]] || [ -z "$output" ]
68
- }
69
-
70
- # ── Clean fixture: badge matches plugin.json record ─────────────────────────
71
-
72
- @test "clean fixture: matching badge + record emits no drift hints" {
73
- make_plugin "stub" '{"name":"wr-stub","version":"0.1.0","description":"Stub","maturity":{"schema_version":"1.0","band":"Alpha"}}' \
74
- "# @windyroad/stub
75
-
76
- **Stub plugin description.** *Maturity: Alpha.*
77
-
78
- ## Skills
79
- "
80
-
81
- run bash "$SCRIPT" "$PKG_DIR"
82
- [ "$status" -eq 0 ]
83
- [[ "$output" == *"package=stub"* ]]
84
- [[ "$output" == *"drift_hints="* ]]
85
- [[ "$output" != *"stale-band"* ]]
86
- [[ "$output" != *"missing-badge"* ]]
87
- }
88
-
89
- # ── Stale-band fixture: badge != canonical record ───────────────────────────
90
-
91
- @test "stale-band fixture: README badge band mismatches plugin.json record" {
92
- make_plugin "stub" '{"name":"wr-stub","version":"0.1.0","description":"Stub","maturity":{"schema_version":"1.0","band":"Beta"}}' \
93
- "# @windyroad/stub
94
-
95
- **Stub plugin description.** *Maturity: Alpha.*
96
-
97
- ## Skills
98
- "
99
-
100
- run bash "$SCRIPT" "$PKG_DIR"
101
- [ "$status" -eq 0 ]
102
- [[ "$output" == *"package=stub"* ]]
103
- [[ "$output" == *"stale-band"* ]]
104
- }
105
-
106
- # ── Missing-badge fixture: plugin.json has maturity, README has no badge ────
107
-
108
- @test "missing-badge fixture: plugin.json has maturity but README has no badge" {
109
- make_plugin "stub" '{"name":"wr-stub","version":"0.1.0","description":"Stub","maturity":{"schema_version":"1.0","band":"Alpha"}}' \
110
- "# @windyroad/stub
111
-
112
- **Stub plugin description.**
113
-
114
- ## Skills
115
- "
116
-
117
- run bash "$SCRIPT" "$PKG_DIR"
118
- [ "$status" -eq 0 ]
119
- [[ "$output" == *"package=stub"* ]]
120
- [[ "$output" == *"missing-badge"* ]]
121
- }
122
-
123
- # ── Orphan-badge fixture: README has badge, plugin.json has no maturity ─────
124
-
125
- @test "orphan-badge fixture: README badge present but plugin.json lacks maturity field" {
126
- make_plugin "stub" '{"name":"wr-stub","version":"0.1.0","description":"Stub"}' \
127
- "# @windyroad/stub
128
-
129
- **Stub plugin description.** *Maturity: Alpha.*
130
-
131
- ## Skills
132
- "
133
-
134
- run bash "$SCRIPT" "$PKG_DIR"
135
- [ "$status" -eq 0 ]
136
- [[ "$output" == *"package=stub"* ]]
137
- [[ "$output" == *"orphan-badge"* ]]
138
- }
139
-
140
- # ── Anti-pattern: standalone ## Maturity section ────────────────────────────
141
-
142
- @test "anti-pattern: standalone ## Maturity section emits anti-pattern-section hint" {
143
- make_plugin "stub" '{"name":"wr-stub","version":"0.1.0","description":"Stub","maturity":{"schema_version":"1.0","band":"Alpha"}}' \
144
- "# @windyroad/stub
145
-
146
- **Stub plugin description.** *Maturity: Alpha.*
147
-
148
- ## Maturity
149
-
150
- Alpha band.
151
-
152
- ## Skills
153
- "
154
-
155
- run bash "$SCRIPT" "$PKG_DIR"
156
- [ "$status" -eq 0 ]
157
- [[ "$output" == *"package=stub"* ]]
158
- [[ "$output" == *"anti-pattern-section"* ]]
159
- }
160
-
161
- # ── Anti-pattern: shields.io URL ────────────────────────────────────────────
162
-
163
- @test "anti-pattern: shields.io URL emits anti-pattern-url hint" {
164
- make_plugin "stub" '{"name":"wr-stub","version":"0.1.0","description":"Stub","maturity":{"schema_version":"1.0","band":"Alpha"}}' \
165
- "# @windyroad/stub
166
-
167
- **Stub plugin description.** *Maturity: Alpha.* ![Maturity](https://img.shields.io/badge/maturity-alpha-orange)
168
-
169
- ## Skills
170
- "
171
-
172
- run bash "$SCRIPT" "$PKG_DIR"
173
- [ "$status" -eq 0 ]
174
- [[ "$output" == *"package=stub"* ]]
175
- [[ "$output" == *"anti-pattern-url"* ]]
176
- }
177
-
178
- # ── TOTAL summary line ──────────────────────────────────────────────────────
179
-
180
- @test "multi-plugin aggregation: emits TOTAL summary with drift count" {
181
- make_plugin "alpha" '{"name":"wr-alpha","version":"0.1.0","description":"Alpha","maturity":{"schema_version":"1.0","band":"Alpha"}}' \
182
- "# @windyroad/alpha
183
-
184
- **Alpha plugin.** *Maturity: Alpha.*
185
-
186
- ## Skills
187
- "
188
- make_plugin "bravo" '{"name":"wr-bravo","version":"0.1.0","description":"Bravo","maturity":{"schema_version":"1.0","band":"Beta"}}' \
189
- "# @windyroad/bravo
190
-
191
- **Bravo plugin.**
192
-
193
- ## Skills
194
- "
195
-
196
- run bash "$SCRIPT" "$PKG_DIR"
197
- [ "$status" -eq 0 ]
198
- [[ "$output" == *"package=alpha"* ]]
199
- [[ "$output" == *"package=bravo"* ]]
200
- [[ "$output" == *"TOTAL packages=2"* ]]
201
- [[ "$output" == *"drift_instances=1"* ]]
202
- }
203
-
204
- # ── Exit-0-always invariant ─────────────────────────────────────────────────
205
-
206
- @test "exit-0-always: even with multiple drift entries, exit code is 0" {
207
- make_plugin "alpha" '{"name":"wr-alpha","version":"0.1.0","description":"Alpha","maturity":{"schema_version":"1.0","band":"Beta"}}' \
208
- "# @windyroad/alpha
209
-
210
- **Alpha plugin.** *Maturity: Alpha.*
211
-
212
- ## Skills
213
- "
214
- make_plugin "bravo" '{"name":"wr-bravo","version":"0.1.0","description":"Bravo","maturity":{"schema_version":"1.0","band":"Stable"}}' \
215
- "# @windyroad/bravo
216
-
217
- **Bravo plugin.**
218
-
219
- ## Skills
220
- "
221
-
222
- run bash "$SCRIPT" "$PKG_DIR"
223
- [ "$status" -eq 0 ]
224
- }
225
-
226
- # ── Package without README is silently skipped ──────────────────────────────
227
-
228
- @test "package without README.md is silently skipped" {
229
- local pkg="$PKG_DIR/no-readme"
230
- mkdir -p "$pkg/.claude-plugin"
231
- echo '{"name":"wr-no-readme","version":"0.1.0","description":"No README","maturity":{"schema_version":"1.0","band":"Alpha"}}' > "$pkg/.claude-plugin/plugin.json"
232
-
233
- make_plugin "with-readme" '{"name":"wr-with-readme","version":"0.1.0","description":"With README","maturity":{"schema_version":"1.0","band":"Alpha"}}' \
234
- "# @windyroad/with-readme
235
-
236
- **With README.** *Maturity: Alpha.*
237
- "
238
-
239
- run bash "$SCRIPT" "$PKG_DIR"
240
- [ "$status" -eq 0 ]
241
- [[ "$output" != *"package=no-readme"* ]]
242
- [[ "$output" == *"package=with-readme"* ]]
243
- }
244
-
245
- # ── No-network primitive: ADR-035 privacy posture ───────────────────────────
246
-
247
- @test "ADR-035: script body invokes no network primitive" {
248
- run grep -E "(curl|wget|nc -|netcat|ssh |scp |rsync|http\.client|urllib|requests)" "$SCRIPT"
249
- [ "$status" -ne 0 ]
250
- }
251
-
252
- # ── NDJSON output: per-line shape parseable as structured signal ────────────
253
-
254
- @test "NDJSON output: each README line follows package=<name> <key>=<value> shape" {
255
- make_plugin "stub" '{"name":"wr-stub","version":"0.1.0","description":"Stub","maturity":{"schema_version":"1.0","band":"Alpha"}}' \
256
- "# @windyroad/stub
257
-
258
- **Stub plugin description.** *Maturity: Alpha.*
259
-
260
- ## Skills
261
- "
262
-
263
- run bash "$SCRIPT" "$PKG_DIR"
264
- [ "$status" -eq 0 ]
265
- # Per-package README line is space-separated key=value tokens
266
- [[ "$output" == *"README package=stub"* ]]
267
- [[ "$output" == *"badge_band="* ]]
268
- [[ "$output" == *"record_band="* ]]
269
- }
@@ -1,165 +0,0 @@
1
- #!/usr/bin/env bats
2
- #
3
- # packages/retrospective/scripts/test/check-readme-jtbd-currency.bats
4
- #
5
- # Behavioural tests for `check-readme-jtbd-currency.sh` — the skill-inventory
6
- # README currency advisory (ADR-069 / P294, superseding ADR-051's JTBD-ID
7
- # rule). Mirrors the fixture-based pattern of sibling detectors
8
- # (`check-briefing-budgets.bats`, `check-ask-hygiene.bats`).
9
- #
10
- # Tests are behavioural per ADR-005 / ADR-052 / P081 — they exercise the
11
- # script end-to-end against fixture packages/ trees and assert on stdout /
12
- # exit code shape. No structural greps of the script source.
13
- #
14
- # @problem P152 (No pressure or nudge for documentation currency — original driver)
15
- # @problem P294 (ADR-051 superseded — README markets the persona's problem, no JTBD-ID citation)
16
- # @problem P081 (Structural-content tests are wasteful — behavioural preferred)
17
- # @adr ADR-069 (README markets persona problem; skill-inventory currency gate)
18
- # @adr ADR-051 (superseded — original JTBD-anchored README rule)
19
- # @adr ADR-013 Rule 6 (non-interactive fail-safe)
20
- # @adr ADR-005 / ADR-052 (Plugin testing strategy — behavioural tests)
21
-
22
- SCRIPT="${BATS_TEST_DIRNAME}/../check-readme-jtbd-currency.sh"
23
-
24
- setup() {
25
- TEST_DIR="$(mktemp -d)"
26
- PKG_DIR="$TEST_DIR/packages"
27
- mkdir -p "$PKG_DIR"
28
- }
29
-
30
- teardown() {
31
- rm -rf "$TEST_DIR"
32
- }
33
-
34
- # Helper: write a synthetic plugin README into PKG_DIR
35
- make_plugin() {
36
- local name="$1"
37
- local readme_content="$2"
38
- mkdir -p "$PKG_DIR/$name"
39
- printf '%s\n' "$readme_content" > "$PKG_DIR/$name/README.md"
40
- }
41
-
42
- # ── Pre-checks ──────────────────────────────────────────────────────────────
43
-
44
- @test "script file exists and is executable" {
45
- [ -f "$SCRIPT" ]
46
- [ -x "$SCRIPT" ]
47
- }
48
-
49
- @test "missing packages dir exits 2 with error message on stderr" {
50
- run bash "$SCRIPT" "$TEST_DIR/does-not-exist"
51
- [ "$status" -eq 2 ]
52
- [[ "$output" == *"packages dir not found"* ]]
53
- }
54
-
55
- @test "empty packages dir exits 0 with empty stdout" {
56
- run bash "$SCRIPT" "$PKG_DIR"
57
- [ "$status" -eq 0 ]
58
- [ -z "$output" ]
59
- }
60
-
61
- @test "legacy second argument (former jtbd-dir) is accepted and ignored" {
62
- make_plugin "stub" "# @windyroad/stub
63
- A plugin that solves a problem."
64
- run bash "$SCRIPT" "$PKG_DIR" "/some/legacy/jtbd/path"
65
- [ "$status" -eq 0 ]
66
- [[ "$output" == *"package=stub"* ]]
67
- [[ "$output" == *"TOTAL packages=1 drift_instances=0"* ]]
68
- }
69
-
70
- # ── Drift fixture: skills/ directory not named in README ────────────────────
71
-
72
- @test "drift fixture: skills/ directory not named in README emits skill-inventory-drift" {
73
- mkdir -p "$PKG_DIR/stub/skills/orphan-widget"
74
- printf '%s\n' "# @windyroad/stub
75
- This README documents no skills." > "$PKG_DIR/stub/README.md"
76
-
77
- run bash "$SCRIPT" "$PKG_DIR"
78
- [ "$status" -eq 0 ]
79
- [[ "$output" == *"package=stub"* ]]
80
- [[ "$output" == *"skills=1"* ]]
81
- [[ "$output" == *"in_readme=0"* ]]
82
- [[ "$output" == *"drift_hints="*"skill-inventory-drift"* ]]
83
- [[ "$output" == *"TOTAL packages=1 drift_instances=1"* ]]
84
- }
85
-
86
- # ── Clean fixture: every skill named in README ──────────────────────────────
87
-
88
- @test "clean fixture: all skills/ directories named in README emit empty drift_hints" {
89
- mkdir -p "$PKG_DIR/stub/skills/manage-secret"
90
- printf '%s\n' "# @windyroad/stub
91
- Run /wr-stub:manage-secret to rotate a secret." > "$PKG_DIR/stub/README.md"
92
-
93
- run bash "$SCRIPT" "$PKG_DIR"
94
- [ "$status" -eq 0 ]
95
- [[ "$output" == *"package=stub"* ]]
96
- [[ "$output" == *"skills=1"* ]]
97
- [[ "$output" == *"in_readme=1"* ]]
98
- [[ "$output" != *"skill-inventory-drift"* ]]
99
- [[ "$output" == *"TOTAL packages=1 drift_instances=0"* ]]
100
- }
101
-
102
- # ── Regression guard: a JTBD-NNN citation must NOT change the verdict ────────
103
- # (ADR-069 removed the JTBD-ID rule; the detector no longer reads JTBD IDs.)
104
-
105
- @test "regression: README with NO JTBD-NNN citation is clean when its skills are named" {
106
- mkdir -p "$PKG_DIR/stub/skills/do-thing"
107
- printf '%s\n' "# @windyroad/stub
108
- Markets a problem in plain prose. Run /wr-stub:do-thing. No JTBD IDs here." > "$PKG_DIR/stub/README.md"
109
-
110
- run bash "$SCRIPT" "$PKG_DIR"
111
- [ "$status" -eq 0 ]
112
- [[ "$output" != *"missing-jtbd-section"* ]]
113
- [[ "$output" != *"stale-jtbd-citation"* ]]
114
- [[ "$output" == *"TOTAL packages=1 drift_instances=0"* ]]
115
- }
116
-
117
- # ── Package with no skills/ directory ───────────────────────────────────────
118
-
119
- @test "package without a skills/ directory reports skills=0 and no drift" {
120
- make_plugin "umbrella" "# @windyroad/umbrella
121
- A marketplace package with no skills of its own."
122
-
123
- run bash "$SCRIPT" "$PKG_DIR"
124
- [ "$status" -eq 0 ]
125
- [[ "$output" == *"package=umbrella"* ]]
126
- [[ "$output" == *"skills=0"* ]]
127
- [[ "$output" == *"in_readme=0"* ]]
128
- [[ "$output" != *"skill-inventory-drift"* ]]
129
- }
130
-
131
- # ── Multi-package aggregation ───────────────────────────────────────────────
132
-
133
- @test "multi-package aggregation: emits one README line per package + TOTAL summary" {
134
- mkdir -p "$PKG_DIR/alpha/skills/run-alpha"
135
- printf '%s\n' "# alpha
136
- Run /wr-alpha:run-alpha." > "$PKG_DIR/alpha/README.md"
137
- mkdir -p "$PKG_DIR/bravo/skills/lost-skill"
138
- printf '%s\n' "# bravo
139
- README forgot to mention its skill." > "$PKG_DIR/bravo/README.md"
140
- make_plugin "charlie" "# charlie
141
- No skills directory at all."
142
-
143
- run bash "$SCRIPT" "$PKG_DIR"
144
- [ "$status" -eq 0 ]
145
- [[ "$output" == *"package=alpha"* ]]
146
- [[ "$output" == *"package=bravo"* ]]
147
- [[ "$output" == *"package=charlie"* ]]
148
- # only bravo drifts (lost-skill not named)
149
- [[ "$output" == *"TOTAL packages=3 drift_instances=1"* ]]
150
- }
151
-
152
- # ── Package without README is skipped ───────────────────────────────────────
153
-
154
- @test "package without README.md is silently skipped" {
155
- mkdir -p "$PKG_DIR/no-readme/skills/x"
156
- mkdir -p "$PKG_DIR/with-readme/skills/y"
157
- printf '%s\n' "# with-readme
158
- Run /wr-with-readme:y." > "$PKG_DIR/with-readme/README.md"
159
-
160
- run bash "$SCRIPT" "$PKG_DIR"
161
- [ "$status" -eq 0 ]
162
- [[ "$output" != *"package=no-readme"* ]]
163
- [[ "$output" == *"package=with-readme"* ]]
164
- [[ "$output" == *"TOTAL packages=1"* ]]
165
- }