@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,336 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env bats
|
|
2
|
-
|
|
3
|
-
# @problem P097 — SKILL.md files mix runtime-necessary steps with maintainer-
|
|
4
|
-
# facing rationale, bloating every skill invocation. ADR-054 codifies the
|
|
5
|
-
# classification taxonomy ([runtime] / [reference] / [deprecated]), the
|
|
6
|
-
# sibling REFERENCE.md lazy-load pattern, and the byte budgets (WARN ≥
|
|
7
|
-
# 8192, MUST_SPLIT ≥ 16384). This bats fixture covers the advisory
|
|
8
|
-
# detector script that surfaces SKILL.md files exceeding the budget.
|
|
9
|
-
#
|
|
10
|
-
# Contract: `check-skill-md-budgets.sh [<root-dir>]` is a diagnose-only
|
|
11
|
-
# advisory script. It walks `<root-dir>/packages/*/skills/*/SKILL.md` and
|
|
12
|
-
# `<root-dir>/.claude/skills/*/SKILL.md` (default `<root-dir>` is `.`),
|
|
13
|
-
# measures byte size per file, and reports each SKILL.md whose size is at
|
|
14
|
-
# or above the WARN threshold (default 8192 bytes, overridable via
|
|
15
|
-
# SKILL_MD_WARN_BYTES env var).
|
|
16
|
-
#
|
|
17
|
-
# Exit codes:
|
|
18
|
-
# 0 = always (advisory only — overflow is signal, not failure)
|
|
19
|
-
# 2 = parse error (root dir missing or unreadable)
|
|
20
|
-
#
|
|
21
|
-
# Output format on overflow (one line per file, terse machine-readable
|
|
22
|
-
# per ADR-038 progressive-disclosure budget):
|
|
23
|
-
# OVER <plugin>/<skill> bytes=<N> threshold=<N>
|
|
24
|
-
#
|
|
25
|
-
# Files at >= MUST_SPLIT (default 16384, overridable via SKILL_MD_MUST_SPLIT_BYTES)
|
|
26
|
-
# also emit a second line:
|
|
27
|
-
# MUST_SPLIT <plugin>/<skill> reason=<code>
|
|
28
|
-
#
|
|
29
|
-
# This mirrors the OVER / MUST_SPLIT pair shape from `check-briefing-budgets.sh`
|
|
30
|
-
# (P099 / P145 / ADR-040) deliberately so adopters learn one concept across
|
|
31
|
-
# two surfaces.
|
|
32
|
-
#
|
|
33
|
-
# Output ordering (deterministic for stable retro-summary diffs):
|
|
34
|
-
# 1. All OVER lines, sorted by `<plugin>/<skill>` identifier.
|
|
35
|
-
# 2. Then all MUST_SPLIT lines, sorted by identifier.
|
|
36
|
-
#
|
|
37
|
-
# Output is empty (no lines) when no SKILL.md exceeds the WARN threshold.
|
|
38
|
-
# REFERENCE.md sibling files (per ADR-054) are excluded from the scan —
|
|
39
|
-
# they are intentionally lazy-loaded and not subject to the runtime budget.
|
|
40
|
-
#
|
|
41
|
-
# Read-only — does NOT mutate any SKILL.md file. Extraction priority is
|
|
42
|
-
# surfaced to the maintainer; rotation is opportunistic per ADR-052
|
|
43
|
-
# migration shape.
|
|
44
|
-
#
|
|
45
|
-
# This fixture is BEHAVIOURAL per ADR-052 — it asserts script output on
|
|
46
|
-
# temp-fixture skill trees, NOT script source content. No greps of
|
|
47
|
-
# check-skill-md-budgets.sh source.
|
|
48
|
-
#
|
|
49
|
-
# @jtbd JTBD-001 (Enforce Governance Without Slowing Down — solo dev;
|
|
50
|
-
# read-only, no interactive friction on the happy path)
|
|
51
|
-
# @jtbd JTBD-006 (Progress the Backlog While I'm Away — AFK-safe advisory)
|
|
52
|
-
# @jtbd JTBD-101 (Extend the Suite with Clear Patterns — reusable
|
|
53
|
-
# advisory-script + bats + ADR-amendment shape for context-budget surfaces)
|
|
54
|
-
#
|
|
55
|
-
# Cross-reference:
|
|
56
|
-
# P097: docs/problems/097-skill-md-runtime-size-mixes-policy-with-runtime-steps.*.md
|
|
57
|
-
# ADR-054 — SKILL.md runtime budget policy (taxonomy + sibling pattern + budget)
|
|
58
|
-
# ADR-040 — Session-start briefing surface (Tier 3 OVER / MUST_SPLIT precedent)
|
|
59
|
-
# ADR-038 — Progressive disclosure (per-row byte budget on diff output)
|
|
60
|
-
# ADR-052 — Behavioural-tests-default (this fixture's pattern)
|
|
61
|
-
# ADR-005 — Plugin testing strategy (script-level bats governance)
|
|
62
|
-
|
|
63
|
-
setup() {
|
|
64
|
-
SCRIPTS_DIR="$(cd "$(dirname "$BATS_TEST_FILENAME")/.." && pwd)"
|
|
65
|
-
SCRIPT="$SCRIPTS_DIR/check-skill-md-budgets.sh"
|
|
66
|
-
FIXTURE_ROOT="$(mktemp -d)"
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
teardown() {
|
|
70
|
-
rm -rf "$FIXTURE_ROOT"
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
# Helper: write a SKILL.md with N bytes of body content under a fixture
|
|
74
|
-
# plugin/skill path. Creates the directory tree as needed.
|
|
75
|
-
write_skill() {
|
|
76
|
-
local plugin="$1"
|
|
77
|
-
local skill="$2"
|
|
78
|
-
local target_bytes="$3"
|
|
79
|
-
local skill_dir="$FIXTURE_ROOT/packages/$plugin/skills/$skill"
|
|
80
|
-
mkdir -p "$skill_dir"
|
|
81
|
-
local path="$skill_dir/SKILL.md"
|
|
82
|
-
: > "$path"
|
|
83
|
-
printf '# Skill\n\n' >> "$path"
|
|
84
|
-
local header_size
|
|
85
|
-
header_size=$(wc -c < "$path" | tr -d ' ')
|
|
86
|
-
local body_target=$(( target_bytes - header_size ))
|
|
87
|
-
if [ "$body_target" -gt 0 ]; then
|
|
88
|
-
local line="- step text padded out to a known length for byte-budget testing. "
|
|
89
|
-
local line_size=${#line}
|
|
90
|
-
line+=$'\n'
|
|
91
|
-
local line_count=$(( (body_target + line_size) / (line_size + 1) ))
|
|
92
|
-
local i=0
|
|
93
|
-
while [ "$i" -lt "$line_count" ]; do
|
|
94
|
-
printf '%s' "$line" >> "$path"
|
|
95
|
-
i=$(( i + 1 ))
|
|
96
|
-
done
|
|
97
|
-
fi
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
# Helper: write a project-local SKILL.md under .claude/skills/<skill>/SKILL.md
|
|
101
|
-
# (the project-local skill surface, in scope per ADR-054 §Phase 1 deliverable).
|
|
102
|
-
write_local_skill() {
|
|
103
|
-
local skill="$1"
|
|
104
|
-
local target_bytes="$2"
|
|
105
|
-
local skill_dir="$FIXTURE_ROOT/.claude/skills/$skill"
|
|
106
|
-
mkdir -p "$skill_dir"
|
|
107
|
-
local path="$skill_dir/SKILL.md"
|
|
108
|
-
: > "$path"
|
|
109
|
-
printf '# Skill\n\n' >> "$path"
|
|
110
|
-
local header_size
|
|
111
|
-
header_size=$(wc -c < "$path" | tr -d ' ')
|
|
112
|
-
local body_target=$(( target_bytes - header_size ))
|
|
113
|
-
if [ "$body_target" -gt 0 ]; then
|
|
114
|
-
local line="- step text padded out to a known length for byte-budget testing. "
|
|
115
|
-
local line_size=${#line}
|
|
116
|
-
line+=$'\n'
|
|
117
|
-
local line_count=$(( (body_target + line_size) / (line_size + 1) ))
|
|
118
|
-
local i=0
|
|
119
|
-
while [ "$i" -lt "$line_count" ]; do
|
|
120
|
-
printf '%s' "$line" >> "$path"
|
|
121
|
-
i=$(( i + 1 ))
|
|
122
|
-
done
|
|
123
|
-
fi
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
# ── Existence + executable ──────────────────────────────────────────────────
|
|
127
|
-
|
|
128
|
-
@test "check-skill-md-budgets: script exists" {
|
|
129
|
-
[ -f "$SCRIPT" ]
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
@test "check-skill-md-budgets: script is executable" {
|
|
133
|
-
[ -x "$SCRIPT" ]
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
# ── Default-threshold behaviour (WARN 8192, MUST_SPLIT 16384) ───────────────
|
|
137
|
-
|
|
138
|
-
@test "check-skill-md-budgets: empty tree produces no output and exits 0" {
|
|
139
|
-
mkdir -p "$FIXTURE_ROOT/packages"
|
|
140
|
-
run "$SCRIPT" "$FIXTURE_ROOT"
|
|
141
|
-
[ "$status" -eq 0 ]
|
|
142
|
-
[ -z "$output" ]
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
@test "check-skill-md-budgets: all skills under WARN produces no output" {
|
|
146
|
-
write_skill "alpha" "small" 1024
|
|
147
|
-
write_skill "beta" "medium" 4096
|
|
148
|
-
write_skill "gamma" "near-warn" 7000
|
|
149
|
-
run "$SCRIPT" "$FIXTURE_ROOT"
|
|
150
|
-
[ "$status" -eq 0 ]
|
|
151
|
-
[ -z "$output" ]
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
@test "check-skill-md-budgets: skill at WARN band emits OVER line with bytes + threshold" {
|
|
155
|
-
write_skill "alpha" "warn-band" 10000
|
|
156
|
-
run "$SCRIPT" "$FIXTURE_ROOT"
|
|
157
|
-
[ "$status" -eq 0 ]
|
|
158
|
-
echo "$output" | grep -E "^OVER alpha/warn-band bytes=[0-9]+ threshold=8192$"
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
@test "check-skill-md-budgets: skill exactly at WARN threshold emits OVER (>= boundary)" {
|
|
162
|
-
local skill_dir="$FIXTURE_ROOT/packages/alpha/skills/edge"
|
|
163
|
-
mkdir -p "$skill_dir"
|
|
164
|
-
printf '%.0s.' $(seq 1 8192) > "$skill_dir/SKILL.md"
|
|
165
|
-
run "$SCRIPT" "$FIXTURE_ROOT"
|
|
166
|
-
[ "$status" -eq 0 ]
|
|
167
|
-
echo "$output" | grep -E "^OVER alpha/edge bytes=8192 threshold=8192$"
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
@test "check-skill-md-budgets: skill at WARN band but under MUST_SPLIT emits OVER only (no MUST_SPLIT)" {
|
|
171
|
-
write_skill "alpha" "warn-only" 12000
|
|
172
|
-
run "$SCRIPT" "$FIXTURE_ROOT"
|
|
173
|
-
[ "$status" -eq 0 ]
|
|
174
|
-
echo "$output" | grep -E "^OVER alpha/warn-only bytes=[0-9]+ threshold=8192"
|
|
175
|
-
! echo "$output" | grep -q "MUST_SPLIT"
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
@test "check-skill-md-budgets: skill at exactly MUST_SPLIT emits OVER + MUST_SPLIT" {
|
|
179
|
-
local skill_dir="$FIXTURE_ROOT/packages/alpha/skills/exactly-must-split"
|
|
180
|
-
mkdir -p "$skill_dir"
|
|
181
|
-
printf '%.0s.' $(seq 1 16384) > "$skill_dir/SKILL.md"
|
|
182
|
-
run "$SCRIPT" "$FIXTURE_ROOT"
|
|
183
|
-
[ "$status" -eq 0 ]
|
|
184
|
-
echo "$output" | grep -E "^OVER alpha/exactly-must-split bytes=16384 threshold=8192"
|
|
185
|
-
echo "$output" | grep -E "^MUST_SPLIT alpha/exactly-must-split reason=ratio-exceeds-must-split$"
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
@test "check-skill-md-budgets: skill well over MUST_SPLIT emits both lines" {
|
|
189
|
-
write_skill "alpha" "very-bloated" 80000
|
|
190
|
-
run "$SCRIPT" "$FIXTURE_ROOT"
|
|
191
|
-
[ "$status" -eq 0 ]
|
|
192
|
-
echo "$output" | grep -E "^OVER alpha/very-bloated bytes=[0-9]+ threshold=8192"
|
|
193
|
-
echo "$output" | grep -E "^MUST_SPLIT alpha/very-bloated reason=ratio-exceeds-must-split$"
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
@test "check-skill-md-budgets: only over-threshold skills appear in output" {
|
|
197
|
-
write_skill "alpha" "under" 2000
|
|
198
|
-
write_skill "beta" "over-warn" 10000
|
|
199
|
-
write_skill "gamma" "over-must-split" 20000
|
|
200
|
-
run "$SCRIPT" "$FIXTURE_ROOT"
|
|
201
|
-
[ "$status" -eq 0 ]
|
|
202
|
-
echo "$output" | grep -E "^OVER beta/over-warn bytes=[0-9]+ threshold=8192"
|
|
203
|
-
echo "$output" | grep -E "^OVER gamma/over-must-split bytes=[0-9]+ threshold=8192"
|
|
204
|
-
! echo "$output" | grep -q "alpha/under"
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
# ── Sibling REFERENCE.md exclusion (ADR-054) ────────────────────────────────
|
|
208
|
-
|
|
209
|
-
@test "check-skill-md-budgets: REFERENCE.md sibling is excluded from the scan" {
|
|
210
|
-
write_skill "alpha" "with-ref" 1000
|
|
211
|
-
# Write a bloated REFERENCE.md that would otherwise trip MUST_SPLIT
|
|
212
|
-
printf '%.0s.' $(seq 1 50000) > "$FIXTURE_ROOT/packages/alpha/skills/with-ref/REFERENCE.md"
|
|
213
|
-
run "$SCRIPT" "$FIXTURE_ROOT"
|
|
214
|
-
[ "$status" -eq 0 ]
|
|
215
|
-
# No output — only SKILL.md is measured, not REFERENCE.md
|
|
216
|
-
[ -z "$output" ]
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
# ── Project-local .claude/skills discovery ──────────────────────────────────
|
|
220
|
-
|
|
221
|
-
@test "check-skill-md-budgets: .claude/skills/* SKILL.md files are scanned" {
|
|
222
|
-
write_local_skill "install-updates" 12000
|
|
223
|
-
run "$SCRIPT" "$FIXTURE_ROOT"
|
|
224
|
-
[ "$status" -eq 0 ]
|
|
225
|
-
# The project-local prefix is .claude in the identifier
|
|
226
|
-
echo "$output" | grep -E "^OVER .claude/install-updates bytes=[0-9]+ threshold=8192"
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
@test "check-skill-md-budgets: project-local + plugin-skill outputs both appear" {
|
|
230
|
-
write_skill "alpha" "plugin-skill" 10000
|
|
231
|
-
write_local_skill "local-skill" 12000
|
|
232
|
-
run "$SCRIPT" "$FIXTURE_ROOT"
|
|
233
|
-
[ "$status" -eq 0 ]
|
|
234
|
-
echo "$output" | grep -E "^OVER .claude/local-skill"
|
|
235
|
-
echo "$output" | grep -E "^OVER alpha/plugin-skill"
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
# ── Configurable thresholds via env vars ────────────────────────────────────
|
|
239
|
-
|
|
240
|
-
@test "check-skill-md-budgets: SKILL_MD_WARN_BYTES env var overrides default" {
|
|
241
|
-
write_skill "alpha" "small-by-default" 4096
|
|
242
|
-
# Default 8192: no output. With env var 2000: over threshold.
|
|
243
|
-
SKILL_MD_WARN_BYTES=2000 run "$SCRIPT" "$FIXTURE_ROOT"
|
|
244
|
-
[ "$status" -eq 0 ]
|
|
245
|
-
echo "$output" | grep -E "^OVER alpha/small-by-default bytes=[0-9]+ threshold=2000"
|
|
246
|
-
}
|
|
247
|
-
|
|
248
|
-
@test "check-skill-md-budgets: SKILL_MD_MUST_SPLIT_BYTES env var overrides default" {
|
|
249
|
-
write_skill "alpha" "moderate" 9000
|
|
250
|
-
# Default WARN 8192: emits OVER. Default MUST_SPLIT 16384: no MUST_SPLIT.
|
|
251
|
-
# With MUST_SPLIT override 8500: should emit MUST_SPLIT too.
|
|
252
|
-
SKILL_MD_MUST_SPLIT_BYTES=8500 run "$SCRIPT" "$FIXTURE_ROOT"
|
|
253
|
-
[ "$status" -eq 0 ]
|
|
254
|
-
echo "$output" | grep -E "^OVER alpha/moderate"
|
|
255
|
-
echo "$output" | grep -E "^MUST_SPLIT alpha/moderate reason=ratio-exceeds-must-split$"
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
@test "check-skill-md-budgets: env var threshold of 0 emits every skill (sanity)" {
|
|
259
|
-
write_skill "alpha" "tiny-one" 100
|
|
260
|
-
write_skill "beta" "tiny-two" 200
|
|
261
|
-
SKILL_MD_WARN_BYTES=0 run "$SCRIPT" "$FIXTURE_ROOT"
|
|
262
|
-
[ "$status" -eq 0 ]
|
|
263
|
-
echo "$output" | grep -q "OVER alpha/tiny-one"
|
|
264
|
-
echo "$output" | grep -q "OVER beta/tiny-two"
|
|
265
|
-
}
|
|
266
|
-
|
|
267
|
-
# ── Argument and error handling ─────────────────────────────────────────────
|
|
268
|
-
|
|
269
|
-
@test "check-skill-md-budgets: defaults to current directory when no arg provided" {
|
|
270
|
-
cd "$FIXTURE_ROOT"
|
|
271
|
-
write_skill "alpha" "default-arg" 12000
|
|
272
|
-
run "$SCRIPT"
|
|
273
|
-
[ "$status" -eq 0 ]
|
|
274
|
-
echo "$output" | grep -E "^OVER alpha/default-arg bytes=[0-9]+ threshold=8192"
|
|
275
|
-
}
|
|
276
|
-
|
|
277
|
-
@test "check-skill-md-budgets: missing root dir exits 2 with parse error on stderr" {
|
|
278
|
-
run "$SCRIPT" "$FIXTURE_ROOT/does-not-exist"
|
|
279
|
-
[ "$status" -eq 2 ]
|
|
280
|
-
echo "$output" | grep -iE "not found|missing|does not exist"
|
|
281
|
-
}
|
|
282
|
-
|
|
283
|
-
@test "check-skill-md-budgets: ignores non-SKILL.md files in skill dirs" {
|
|
284
|
-
local skill_dir="$FIXTURE_ROOT/packages/alpha/skills/with-extras"
|
|
285
|
-
mkdir -p "$skill_dir"
|
|
286
|
-
# Bloated non-SKILL.md files should not trip the scan
|
|
287
|
-
printf '%.0s.' $(seq 1 50000) > "$skill_dir/NOTES.md"
|
|
288
|
-
printf '%.0s.' $(seq 1 50000) > "$skill_dir/scratch.txt"
|
|
289
|
-
# Small SKILL.md under threshold
|
|
290
|
-
printf '%.0s.' $(seq 1 1000) > "$skill_dir/SKILL.md"
|
|
291
|
-
run "$SCRIPT" "$FIXTURE_ROOT"
|
|
292
|
-
[ "$status" -eq 0 ]
|
|
293
|
-
[ -z "$output" ]
|
|
294
|
-
}
|
|
295
|
-
|
|
296
|
-
# ── Output stability ────────────────────────────────────────────────────────
|
|
297
|
-
|
|
298
|
-
@test "check-skill-md-budgets: output is sorted by identifier for stable diffs" {
|
|
299
|
-
write_skill "zeta" "one" 10000
|
|
300
|
-
write_skill "alpha" "one" 10000
|
|
301
|
-
write_skill "middle" "one" 10000
|
|
302
|
-
run "$SCRIPT" "$FIXTURE_ROOT"
|
|
303
|
-
[ "$status" -eq 0 ]
|
|
304
|
-
first_line=$(echo "$output" | head -1)
|
|
305
|
-
last_line=$(echo "$output" | tail -1)
|
|
306
|
-
echo "$first_line" | grep -q "alpha/one"
|
|
307
|
-
echo "$last_line" | grep -q "zeta/one"
|
|
308
|
-
}
|
|
309
|
-
|
|
310
|
-
@test "check-skill-md-budgets: mixed OVER + MUST_SPLIT output uses block ordering" {
|
|
311
|
-
# Three OVER files; two of them also MUST_SPLIT. Output must be
|
|
312
|
-
# deterministic so retro summary diffs stay stable across cycles.
|
|
313
|
-
# Contract: OVER block (sorted by identifier) followed by MUST_SPLIT
|
|
314
|
-
# block (sorted by identifier).
|
|
315
|
-
write_skill "zeta" "over-only" 10000
|
|
316
|
-
write_skill "alpha" "must-split" 20000
|
|
317
|
-
write_skill "middle" "must-split" 25000
|
|
318
|
-
run "$SCRIPT" "$FIXTURE_ROOT"
|
|
319
|
-
[ "$status" -eq 0 ]
|
|
320
|
-
# Three OVER lines — alpha first, middle next, zeta last
|
|
321
|
-
over_lines=$(echo "$output" | grep "^OVER ")
|
|
322
|
-
[ "$(echo "$over_lines" | wc -l | tr -d ' ')" = "3" ]
|
|
323
|
-
echo "$over_lines" | sed -n '1p' | grep -q "alpha/must-split"
|
|
324
|
-
echo "$over_lines" | sed -n '2p' | grep -q "middle/must-split"
|
|
325
|
-
echo "$over_lines" | sed -n '3p' | grep -q "zeta/over-only"
|
|
326
|
-
# Two MUST_SPLIT lines — alpha first, middle second; zeta-over-only NOT present
|
|
327
|
-
must_lines=$(echo "$output" | grep "^MUST_SPLIT ")
|
|
328
|
-
[ "$(echo "$must_lines" | wc -l | tr -d ' ')" = "2" ]
|
|
329
|
-
echo "$must_lines" | sed -n '1p' | grep -q "alpha/must-split"
|
|
330
|
-
echo "$must_lines" | sed -n '2p' | grep -q "middle/must-split"
|
|
331
|
-
! echo "$must_lines" | grep -q "zeta/over-only"
|
|
332
|
-
# All OVER lines come before any MUST_SPLIT line (block ordering)
|
|
333
|
-
first_must_line_no=$(echo "$output" | grep -n "^MUST_SPLIT " | head -1 | cut -d: -f1)
|
|
334
|
-
last_over_line_no=$(echo "$output" | grep -n "^OVER " | tail -1 | cut -d: -f1)
|
|
335
|
-
[ "$last_over_line_no" -lt "$first_must_line_no" ]
|
|
336
|
-
}
|
|
@@ -1,284 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env bats
|
|
2
|
-
|
|
3
|
-
# Behavioural fixture for the tarball-shipped-shims advisory detector — per
|
|
4
|
-
# WR-P154 (P137 namespace-prefix detector must run against npm pack output
|
|
5
|
-
# not source tree) and the WR-ADR-049 / WR-ADR-052 / WR-ADR-055 cluster.
|
|
6
|
-
#
|
|
7
|
-
# Contract: `check-tarball-shipped-shims.sh [<root-dir>]` is a diagnose-only
|
|
8
|
-
# advisory script. It walks workspaces under `<root-dir>/packages/*/`, runs
|
|
9
|
-
# `npm pack --dry-run --json` per workspace to enumerate the file set that
|
|
10
|
-
# ships, then asserts that every WR-ADR-049-grammar bin shim
|
|
11
|
-
# (`bin/wr-<plugin>-<name>`) in the tarball has its `exec`'d
|
|
12
|
-
# `scripts/<name>.sh` target also in the tarball.
|
|
13
|
-
#
|
|
14
|
-
# Surface: shipped publish-manifest integrity for bin/scripts/ shim
|
|
15
|
-
# resolvability — different correctness axis than check-internal-id-leaks.sh
|
|
16
|
-
# (which measures source-tree namespace-prefix drift).
|
|
17
|
-
#
|
|
18
|
-
# WR-ADR-049-grammar shims that this script considers:
|
|
19
|
-
# bin/wr-<plugin>-<name>
|
|
20
|
-
# Non-grammar bins (e.g. `bin/install.mjs`, `bin/check-deps.sh`,
|
|
21
|
-
# `bin/windyroad-<plugin>` legacy installers) are skipped — they don't
|
|
22
|
-
# follow the script-resolution-via-bin-on-PATH ADR-049 contract this
|
|
23
|
-
# script enforces.
|
|
24
|
-
#
|
|
25
|
-
# Exit codes:
|
|
26
|
-
# 0 = always (advisory only — drift is signal, not failure)
|
|
27
|
-
# 2 = parse error (root dir missing/unreadable, or npm unavailable)
|
|
28
|
-
#
|
|
29
|
-
# Output format on drift (terse machine-readable per WR-ADR-038):
|
|
30
|
-
# TARBALL_DRIFT package=<name> shim=<bin/wr-...> target=<scripts/...> tarball-status=missing
|
|
31
|
-
#
|
|
32
|
-
# Followed by a final summary line (always emitted when any drift exists):
|
|
33
|
-
# TOTAL packages=<N> with_drift=<M> missing_targets=<K>
|
|
34
|
-
#
|
|
35
|
-
# Output is empty (no lines) when no shipped artefact carries broken
|
|
36
|
-
# shims — silent-on-pass per WR-ADR-045 hook injection budget.
|
|
37
|
-
#
|
|
38
|
-
# Output ordering (deterministic for stable retro-summary diffs):
|
|
39
|
-
# TARBALL_DRIFT lines sorted by `<package>/<shim>` identifier.
|
|
40
|
-
# TOTAL line last.
|
|
41
|
-
#
|
|
42
|
-
# Read-only — does NOT mutate any artefact. Per WR-ADR-052, this fixture
|
|
43
|
-
# is BEHAVIOURAL — it asserts script output on temp-fixture trees, NOT
|
|
44
|
-
# script source content. No greps of check-tarball-shipped-shims.sh source.
|
|
45
|
-
#
|
|
46
|
-
# @problem P154 (P137 namespace-prefix detector must run against
|
|
47
|
-
# npm pack output not source tree)
|
|
48
|
-
# @problem P140 (Step 6.5 fix-and-continue — same prevention surface)
|
|
49
|
-
# @adr ADR-049 (Plugin script resolution via bin/ on PATH)
|
|
50
|
-
# @adr ADR-038 (Progressive disclosure — terse machine-readable signal)
|
|
51
|
-
# @adr ADR-045 (Hook injection budget — silent-on-pass)
|
|
52
|
-
# @adr ADR-052 (Behavioural-tests-default — fixture pattern)
|
|
53
|
-
# @adr ADR-055 (Plugin-published namespace-prefixed permalinks —
|
|
54
|
-
# sibling adopter-context decision)
|
|
55
|
-
# @jtbd JTBD-302 (Trust That the README Describes the Plugin I Just
|
|
56
|
-
# Installed — executable correctness axis of adopter-facing content)
|
|
57
|
-
# @jtbd JTBD-101 (Extend the Suite with New Plugins — secondary
|
|
58
|
-
# plugin-developer feedback surface)
|
|
59
|
-
|
|
60
|
-
setup() {
|
|
61
|
-
SCRIPTS_DIR="$(cd "$(dirname "$BATS_TEST_FILENAME")/.." && pwd)"
|
|
62
|
-
SCRIPT="$SCRIPTS_DIR/check-tarball-shipped-shims.sh"
|
|
63
|
-
FIXTURE_ROOT="$(mktemp -d)"
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
teardown() {
|
|
67
|
-
rm -rf "$FIXTURE_ROOT"
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
# Helper: write a workspace package.json with a controlled `files` array.
|
|
71
|
-
# Args: <plugin> <files-json-array>
|
|
72
|
-
# Example: write_package_json alpha '["bin/", "scripts/"]'
|
|
73
|
-
write_package_json() {
|
|
74
|
-
local plugin="$1"
|
|
75
|
-
local files="$2"
|
|
76
|
-
local plugin_dir="$FIXTURE_ROOT/packages/$plugin"
|
|
77
|
-
mkdir -p "$plugin_dir"
|
|
78
|
-
cat > "$plugin_dir/package.json" <<EOF
|
|
79
|
-
{
|
|
80
|
-
"name": "@test/$plugin",
|
|
81
|
-
"version": "0.1.0",
|
|
82
|
-
"files": $files
|
|
83
|
-
}
|
|
84
|
-
EOF
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
# Helper: write an WR-ADR-049-grammar bin shim that exec-s a scripts/ target.
|
|
88
|
-
# Args: <plugin> <name> (shim becomes bin/wr-<plugin>-<name>, exec-s ../scripts/<name>.sh)
|
|
89
|
-
write_adr049_shim() {
|
|
90
|
-
local plugin="$1"
|
|
91
|
-
local name="$2"
|
|
92
|
-
local bin_dir="$FIXTURE_ROOT/packages/$plugin/bin"
|
|
93
|
-
mkdir -p "$bin_dir"
|
|
94
|
-
cat > "$bin_dir/wr-$plugin-$name" <<EOF
|
|
95
|
-
#!/usr/bin/env bash
|
|
96
|
-
exec "\$(dirname "\$0")/../scripts/$name.sh" "\$@"
|
|
97
|
-
EOF
|
|
98
|
-
chmod +x "$bin_dir/wr-$plugin-$name"
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
# Helper: write a script body matching the shim's exec target.
|
|
102
|
-
write_script() {
|
|
103
|
-
local plugin="$1"
|
|
104
|
-
local name="$2"
|
|
105
|
-
local script_dir="$FIXTURE_ROOT/packages/$plugin/scripts"
|
|
106
|
-
mkdir -p "$script_dir"
|
|
107
|
-
cat > "$script_dir/$name.sh" <<'EOF'
|
|
108
|
-
#!/usr/bin/env bash
|
|
109
|
-
echo "fixture script body"
|
|
110
|
-
EOF
|
|
111
|
-
chmod +x "$script_dir/$name.sh"
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
# Helper: write a non-WR-ADR-049-grammar bin entry (e.g. legacy installer).
|
|
115
|
-
# These should be silently ignored by the script.
|
|
116
|
-
write_non_grammar_bin() {
|
|
117
|
-
local plugin="$1"
|
|
118
|
-
local name="$2"
|
|
119
|
-
local bin_dir="$FIXTURE_ROOT/packages/$plugin/bin"
|
|
120
|
-
mkdir -p "$bin_dir"
|
|
121
|
-
cat > "$bin_dir/$name" <<'EOF'
|
|
122
|
-
#!/usr/bin/env bash
|
|
123
|
-
echo "legacy installer"
|
|
124
|
-
EOF
|
|
125
|
-
chmod +x "$bin_dir/$name"
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
# ── Existence + executable ──────────────────────────────────────────────────
|
|
129
|
-
|
|
130
|
-
@test "check-tarball-shipped-shims: script exists" {
|
|
131
|
-
[ -f "$SCRIPT" ]
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
@test "check-tarball-shipped-shims: script is executable" {
|
|
135
|
-
[ -x "$SCRIPT" ]
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
# ── Empty / clean trees ─────────────────────────────────────────────────────
|
|
139
|
-
|
|
140
|
-
@test "check-tarball-shipped-shims: empty tree (no packages dir) produces no output and exits 0" {
|
|
141
|
-
run "$SCRIPT" "$FIXTURE_ROOT"
|
|
142
|
-
[ "$status" -eq 0 ]
|
|
143
|
-
[ -z "$output" ]
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
@test "check-tarball-shipped-shims: packages dir with no workspaces produces no output and exits 0" {
|
|
147
|
-
mkdir -p "$FIXTURE_ROOT/packages"
|
|
148
|
-
run "$SCRIPT" "$FIXTURE_ROOT"
|
|
149
|
-
[ "$status" -eq 0 ]
|
|
150
|
-
[ -z "$output" ]
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
@test "check-tarball-shipped-shims: workspace with no WR-ADR-049 shims produces no output" {
|
|
154
|
-
write_package_json "alpha" '["bin/"]'
|
|
155
|
-
write_non_grammar_bin "alpha" "windyroad-alpha"
|
|
156
|
-
run "$SCRIPT" "$FIXTURE_ROOT"
|
|
157
|
-
[ "$status" -eq 0 ]
|
|
158
|
-
[ -z "$output" ]
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
@test "check-tarball-shipped-shims: clean workspace (shim + target both ship) produces no output" {
|
|
162
|
-
write_package_json "alpha" '["bin/", "scripts/"]'
|
|
163
|
-
write_adr049_shim "alpha" "good"
|
|
164
|
-
write_script "alpha" "good"
|
|
165
|
-
run "$SCRIPT" "$FIXTURE_ROOT"
|
|
166
|
-
[ "$status" -eq 0 ]
|
|
167
|
-
[ -z "$output" ]
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
# ── Drift detection — the iter-20 P033 sibling-finding shape ────────────────
|
|
171
|
-
|
|
172
|
-
@test "check-tarball-shipped-shims: shim present in tarball, target NOT in tarball — flagged" {
|
|
173
|
-
# The canonical broken shape: scripts/ exists on disk, shim references it,
|
|
174
|
-
# but package.json#files omits scripts/ so the target isn't shipped.
|
|
175
|
-
write_package_json "alpha" '["bin/"]'
|
|
176
|
-
write_adr049_shim "alpha" "broken"
|
|
177
|
-
write_script "alpha" "broken"
|
|
178
|
-
run "$SCRIPT" "$FIXTURE_ROOT"
|
|
179
|
-
[ "$status" -eq 0 ]
|
|
180
|
-
echo "$output" | grep -E "^TARBALL_DRIFT package=@test/alpha shim=bin/wr-alpha-broken target=scripts/broken.sh tarball-status=missing$"
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
@test "check-tarball-shipped-shims: TOTAL summary emitted on any drift" {
|
|
184
|
-
write_package_json "alpha" '["bin/"]'
|
|
185
|
-
write_adr049_shim "alpha" "broken"
|
|
186
|
-
write_script "alpha" "broken"
|
|
187
|
-
run "$SCRIPT" "$FIXTURE_ROOT"
|
|
188
|
-
[ "$status" -eq 0 ]
|
|
189
|
-
echo "$output" | grep -E "^TOTAL packages=1 with_drift=1 missing_targets=1$"
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
@test "check-tarball-shipped-shims: multiple shims in one workspace — each missing target flagged" {
|
|
193
|
-
write_package_json "alpha" '["bin/"]'
|
|
194
|
-
write_adr049_shim "alpha" "alpha-one"
|
|
195
|
-
write_script "alpha" "alpha-one"
|
|
196
|
-
write_adr049_shim "alpha" "alpha-two"
|
|
197
|
-
write_script "alpha" "alpha-two"
|
|
198
|
-
run "$SCRIPT" "$FIXTURE_ROOT"
|
|
199
|
-
[ "$status" -eq 0 ]
|
|
200
|
-
echo "$output" | grep -E "^TARBALL_DRIFT package=@test/alpha shim=bin/wr-alpha-alpha-one target=scripts/alpha-one.sh tarball-status=missing$"
|
|
201
|
-
echo "$output" | grep -E "^TARBALL_DRIFT package=@test/alpha shim=bin/wr-alpha-alpha-two target=scripts/alpha-two.sh tarball-status=missing$"
|
|
202
|
-
echo "$output" | grep -E "^TOTAL packages=1 with_drift=1 missing_targets=2$"
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
@test "check-tarball-shipped-shims: drift across multiple packages aggregates correctly" {
|
|
206
|
-
write_package_json "alpha" '["bin/"]'
|
|
207
|
-
write_adr049_shim "alpha" "a-broken"
|
|
208
|
-
write_script "alpha" "a-broken"
|
|
209
|
-
write_package_json "beta" '["bin/"]'
|
|
210
|
-
write_adr049_shim "beta" "b-broken"
|
|
211
|
-
write_script "beta" "b-broken"
|
|
212
|
-
run "$SCRIPT" "$FIXTURE_ROOT"
|
|
213
|
-
[ "$status" -eq 0 ]
|
|
214
|
-
echo "$output" | grep -E "^TOTAL packages=2 with_drift=2 missing_targets=2$"
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
# ── Mixed clean + drift workspaces ──────────────────────────────────────────
|
|
218
|
-
|
|
219
|
-
@test "check-tarball-shipped-shims: clean workspace + broken workspace — only broken flagged, TOTAL counts only with_drift" {
|
|
220
|
-
write_package_json "alpha" '["bin/", "scripts/"]'
|
|
221
|
-
write_adr049_shim "alpha" "good"
|
|
222
|
-
write_script "alpha" "good"
|
|
223
|
-
write_package_json "beta" '["bin/"]'
|
|
224
|
-
write_adr049_shim "beta" "broken"
|
|
225
|
-
write_script "beta" "broken"
|
|
226
|
-
run "$SCRIPT" "$FIXTURE_ROOT"
|
|
227
|
-
[ "$status" -eq 0 ]
|
|
228
|
-
! echo "$output" | grep -q "alpha"
|
|
229
|
-
echo "$output" | grep -E "^TARBALL_DRIFT package=@test/beta shim=bin/wr-beta-broken target=scripts/broken.sh tarball-status=missing$"
|
|
230
|
-
echo "$output" | grep -E "^TOTAL packages=1 with_drift=1 missing_targets=1$"
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
# ── Determinism ─────────────────────────────────────────────────────────────
|
|
234
|
-
|
|
235
|
-
@test "check-tarball-shipped-shims: TARBALL_DRIFT lines sorted deterministically by package/shim" {
|
|
236
|
-
write_package_json "zeta" '["bin/"]'
|
|
237
|
-
write_adr049_shim "zeta" "z-shim"
|
|
238
|
-
write_script "zeta" "z-shim"
|
|
239
|
-
write_package_json "alpha" '["bin/"]'
|
|
240
|
-
write_adr049_shim "alpha" "a-shim"
|
|
241
|
-
write_script "alpha" "a-shim"
|
|
242
|
-
write_package_json "mu" '["bin/"]'
|
|
243
|
-
write_adr049_shim "mu" "m-shim"
|
|
244
|
-
write_script "mu" "m-shim"
|
|
245
|
-
run "$SCRIPT" "$FIXTURE_ROOT"
|
|
246
|
-
[ "$status" -eq 0 ]
|
|
247
|
-
local first
|
|
248
|
-
first=$(echo "$output" | grep '^TARBALL_DRIFT' | head -1)
|
|
249
|
-
echo "$first" | grep -q "package=@test/alpha"
|
|
250
|
-
local last
|
|
251
|
-
last=$(echo "$output" | grep '^TARBALL_DRIFT' | tail -1)
|
|
252
|
-
echo "$last" | grep -q "package=@test/zeta"
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
# ── Mixed grammar — non-WR-ADR-049 bins ignored ─────────────────────────────
|
|
256
|
-
|
|
257
|
-
@test "check-tarball-shipped-shims: legacy bin (non-WR-ADR-049 grammar) alongside grammar shim — only grammar shim checked" {
|
|
258
|
-
write_package_json "alpha" '["bin/"]'
|
|
259
|
-
write_non_grammar_bin "alpha" "windyroad-alpha"
|
|
260
|
-
write_adr049_shim "alpha" "broken"
|
|
261
|
-
write_script "alpha" "broken"
|
|
262
|
-
run "$SCRIPT" "$FIXTURE_ROOT"
|
|
263
|
-
[ "$status" -eq 0 ]
|
|
264
|
-
! echo "$output" | grep -q "windyroad-alpha"
|
|
265
|
-
echo "$output" | grep -E "^TARBALL_DRIFT package=@test/alpha shim=bin/wr-alpha-broken target=scripts/broken.sh tarball-status=missing$"
|
|
266
|
-
}
|
|
267
|
-
|
|
268
|
-
# ── Pre-check error path ────────────────────────────────────────────────────
|
|
269
|
-
|
|
270
|
-
@test "check-tarball-shipped-shims: missing root dir exits 2" {
|
|
271
|
-
run "$SCRIPT" "/nonexistent/path/$$"
|
|
272
|
-
[ "$status" -eq 2 ]
|
|
273
|
-
}
|
|
274
|
-
|
|
275
|
-
# ── Silent-on-pass invariant ────────────────────────────────────────────────
|
|
276
|
-
|
|
277
|
-
@test "check-tarball-shipped-shims: no TOTAL line emitted when output is empty" {
|
|
278
|
-
write_package_json "alpha" '["bin/", "scripts/"]'
|
|
279
|
-
write_adr049_shim "alpha" "good"
|
|
280
|
-
write_script "alpha" "good"
|
|
281
|
-
run "$SCRIPT" "$FIXTURE_ROOT"
|
|
282
|
-
[ "$status" -eq 0 ]
|
|
283
|
-
[ -z "$output" ]
|
|
284
|
-
}
|