@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.
- package/.claude-plugin/plugin.json +1 -1
- package/package.json +5 -2
- package/hooks/test/retrospective-deferral-census.bats +0 -112
- package/hooks/test/retrospective-readme-jtbd-currency.bats +0 -312
- package/scripts/test/check-ask-hygiene.bats +0 -262
- package/scripts/test/check-autocreate-rfc-scope.bats +0 -250
- package/scripts/test/check-briefing-budgets.bats +0 -349
- package/scripts/test/check-internal-id-leaks.bats +0 -286
- package/scripts/test/check-plugin-maturity-drift.bats +0 -269
- package/scripts/test/check-readme-jtbd-currency.bats +0 -165
- package/scripts/test/check-skill-md-budgets.bats +0 -336
- package/scripts/test/check-tarball-shipped-shims.bats +0 -284
- package/scripts/test/check-tickets-deferred-cause.bats +0 -330
- package/scripts/test/list-plugin-attribution.bats +0 -149
- package/scripts/test/measure-context-budget.bats +0 -298
- package/skills/analyze-context/test/analyze-context-skill-contract.bats +0 -142
- package/skills/migrate-briefing/test/migrate-briefing-contract.bats +0 -105
- package/skills/migrate-briefing/test/migrate-briefing-fixture.bats +0 -242
- package/skills/run-retro/test/run-retro-anti-pattern-clause.bats +0 -87
- package/skills/run-retro/test/run-retro-codification-candidates.bats +0 -168
- package/skills/run-retro/test/run-retro-context-usage-step-2c.bats +0 -156
- package/skills/run-retro/test/run-retro-pipeline-instability-scan.bats +0 -122
- package/skills/run-retro/test/run-retro-signal-vs-noise.bats +0 -137
- package/skills/run-retro/test/run-retro-skill-candidates.bats +0 -116
- package/skills/run-retro/test/run-retro-stage-1-fallback-gating.bats +0 -65
- package/skills/run-retro/test/run-retro-step-2d-r6-auto-flag.bats +0 -82
- package/skills/run-retro/test/run-retro-step-3-tier-3-branch-b-evidence-based.bats +0 -189
- package/skills/run-retro/test/run-retro-step-4a-cross-plugin-dispatch.bats +0 -114
- package/skills/run-retro/test/run-retro-step-4a-prior-session-evidence-drain.bats +0 -168
- package/skills/run-retro/test/run-retro-step-4a-recovery-path.bats +0 -84
- package/skills/run-retro/test/run-retro-step-4b-retro-auto-ticket-carveout.bats +0 -115
- package/skills/run-retro/test/run-retro-ticket-first-flow.bats +0 -161
- 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.* 
|
|
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
|
-
}
|