@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,330 +0,0 @@
1
- #!/usr/bin/env bats
2
- #
3
- # packages/retrospective/scripts/test/check-tickets-deferred-cause.bats
4
- #
5
- # Behavioural tests for `check-tickets-deferred-cause.sh` — the
6
- # Tickets Deferred cause-allowlist advisory script (P148). Mirrors
7
- # the fixture-based test pattern of `check-ask-hygiene.bats`.
8
- #
9
- # Tests are behavioural per ADR-005 / ADR-037 / P081 — they exercise
10
- # the script end-to-end against fixture retro summary directories
11
- # and assert on stdout / stderr / exit shape. No structural greps of
12
- # the script source itself.
13
- #
14
- # @problem P148 (Agent defers ticket creation — broadens Stage 1 fallback gate)
15
- # @problem P081 (Structural-content tests are wasteful — behavioural preferred)
16
- # @adr ADR-044 (Decision-Delegation Contract)
17
- # @adr ADR-040 (Tier 3 advisory-not-fail-closed)
18
- # @adr ADR-013 Rule 6 (non-interactive fail-safe)
19
- # @adr ADR-005 / ADR-037 (Plugin testing strategy — behavioural tests)
20
- # @jtbd JTBD-001 / JTBD-006 / JTBD-201
21
-
22
- SCRIPT="${BATS_TEST_DIRNAME}/../check-tickets-deferred-cause.sh"
23
-
24
- setup() {
25
- TEST_DIR="$(mktemp -d)"
26
- }
27
-
28
- teardown() {
29
- rm -rf "$TEST_DIR"
30
- }
31
-
32
- # ── Pre-checks ──────────────────────────────────────────────────────────────
33
-
34
- @test "script file exists and is executable" {
35
- [ -f "$SCRIPT" ]
36
- [ -x "$SCRIPT" ]
37
- }
38
-
39
- @test "missing retros dir exits 2 with error message on stderr" {
40
- run bash "$SCRIPT" "$TEST_DIR/does-not-exist"
41
- [ "$status" -eq 2 ]
42
- [[ "$output" == *"retros dir not found"* ]]
43
- }
44
-
45
- @test "empty retros dir exits 0 with empty stdout" {
46
- run bash "$SCRIPT" "$TEST_DIR"
47
- [ "$status" -eq 0 ]
48
- [ -z "$output" ]
49
- }
50
-
51
- @test "default retros-dir argument is docs/retros (when omitted)" {
52
- cd "$TEST_DIR"
53
- run bash "$SCRIPT"
54
- [ "$status" -eq 2 ]
55
- [[ "$output" == *"docs/retros"* ]]
56
- }
57
-
58
- # ── No-defer steady state ───────────────────────────────────────────────────
59
-
60
- @test "retro file with no Tickets Deferred section emits no output" {
61
- cat > "$TEST_DIR/2026-04-29-retro.md" <<'RETRO'
62
- ## Session Retrospective
63
-
64
- ### Briefing Changes
65
- - Added: foo
66
-
67
- ### Problems Created/Updated
68
- - P148: opened
69
-
70
- ### No Action Needed
71
- - learning captured
72
- RETRO
73
- run bash "$SCRIPT" "$TEST_DIR"
74
- [ "$status" -eq 0 ]
75
- [ -z "$output" ]
76
- }
77
-
78
- # ── Good fixture (skill_unavailable cause) ──────────────────────────────────
79
-
80
- @test "good fixture: skill_unavailable cause → 0 violations" {
81
- cat > "$TEST_DIR/2026-04-29-retro.md" <<'RETRO'
82
- ## Session Retrospective
83
-
84
- ### Tickets Deferred
85
-
86
- | Observation | Cause | Citation |
87
- |-------------|-------|----------|
88
- | Polling regex deadlock observation | `skill_unavailable` | Step 2b detection |
89
- | SIGTERM flush caveat | `skill_unavailable` | Step 4a verification |
90
- RETRO
91
- run bash "$SCRIPT" "$TEST_DIR"
92
- [ "$status" -eq 0 ]
93
- [[ "$output" == *"deferred=2"* ]]
94
- [[ "$output" == *"with_valid_cause=2"* ]]
95
- [[ "$output" == *"violations=0"* ]]
96
- }
97
-
98
- # ── Bad fixture (session_pressure cause — the P148 anti-pattern) ────────────
99
-
100
- @test "bad fixture: session_pressure cause → all entries are violations" {
101
- cat > "$TEST_DIR/2026-04-29-retro.md" <<'RETRO'
102
- ## Session Retrospective
103
-
104
- ### Tickets Deferred
105
-
106
- | Observation | Cause | Citation |
107
- |-------------|-------|----------|
108
- | Polling regex deadlock | `session_pressure` | Step 2b |
109
- | SIGTERM flush caveat | `context_heavyweight` | Step 4a |
110
- RETRO
111
- run bash "$SCRIPT" "$TEST_DIR"
112
- [ "$status" -eq 0 ]
113
- [[ "$output" == *"deferred=2"* ]]
114
- [[ "$output" == *"with_valid_cause=0"* ]]
115
- [[ "$output" == *"violations=2"* ]]
116
- }
117
-
118
- # ── Legacy fixture (no Cause column — pre-P148 retro shape) ─────────────────
119
-
120
- @test "legacy fixture: no Cause column → all entries are violations" {
121
- cat > "$TEST_DIR/2026-04-29-retro.md" <<'RETRO'
122
- ## Session Retrospective
123
-
124
- ### Tickets Deferred
125
-
126
- | Observation | Citation |
127
- |-------------|----------|
128
- | Polling regex deadlock | Step 2b |
129
- | SIGTERM flush caveat | Step 4a |
130
- RETRO
131
- run bash "$SCRIPT" "$TEST_DIR"
132
- [ "$status" -eq 0 ]
133
- [[ "$output" == *"deferred=2"* ]]
134
- [[ "$output" == *"violations=2"* ]]
135
- }
136
-
137
- @test "legacy fixture exit code is 0 — advisory contract holds for AFK safety" {
138
- # JTBD-006 line 32 (extended AFK safety): legacy retros lacking the Cause
139
- # column would break AFK loops if exit code went non-zero. Fail-closed
140
- # escalation belongs at a future hook tier per P135 R6 trajectory, not
141
- # at the script.
142
- cat > "$TEST_DIR/2026-04-29-retro.md" <<'RETRO'
143
- ### Tickets Deferred
144
-
145
- | Observation | Citation |
146
- |-------------|----------|
147
- | obs1 | step1 |
148
- RETRO
149
- run bash "$SCRIPT" "$TEST_DIR"
150
- [ "$status" -eq 0 ]
151
- }
152
-
153
- # ── Mixed fixture ───────────────────────────────────────────────────────────
154
-
155
- @test "mixed fixture: one valid + one invalid → violations=1, with_valid_cause=1" {
156
- cat > "$TEST_DIR/2026-04-29-retro.md" <<'RETRO'
157
- ### Tickets Deferred
158
-
159
- | Observation | Cause | Citation |
160
- |-------------|-------|----------|
161
- | Valid observation | `skill_unavailable` | Step 2b |
162
- | Invalid observation | `session_pressure` | Step 4a |
163
- RETRO
164
- run bash "$SCRIPT" "$TEST_DIR"
165
- [ "$status" -eq 0 ]
166
- [[ "$output" == *"deferred=2"* ]]
167
- [[ "$output" == *"with_valid_cause=1"* ]]
168
- [[ "$output" == *"violations=1"* ]]
169
- }
170
-
171
- # ── Empty Cause cell ────────────────────────────────────────────────────────
172
-
173
- @test "empty Cause cell counts as a violation (cause-required invariant)" {
174
- cat > "$TEST_DIR/2026-04-29-retro.md" <<'RETRO'
175
- ### Tickets Deferred
176
-
177
- | Observation | Cause | Citation |
178
- |-------------|-------|----------|
179
- | Observation with empty cause | | Step 2b |
180
- RETRO
181
- run bash "$SCRIPT" "$TEST_DIR"
182
- [ "$status" -eq 0 ]
183
- [[ "$output" == *"violations=1"* ]]
184
- }
185
-
186
- # ── Format tolerance ────────────────────────────────────────────────────────
187
-
188
- @test "Cause cell tolerates surrounding whitespace and bold markers" {
189
- cat > "$TEST_DIR/2026-04-29-retro.md" <<'RETRO'
190
- ### Tickets Deferred
191
-
192
- | Observation | Cause | Citation |
193
- |-------------|-------|----------|
194
- | obs1 | `skill_unavailable` | Step 2b |
195
- | obs2 | **skill_unavailable** | Step 4a |
196
- RETRO
197
- run bash "$SCRIPT" "$TEST_DIR"
198
- [ "$status" -eq 0 ]
199
- [[ "$output" == *"deferred=2"* ]]
200
- [[ "$output" == *"with_valid_cause=2"* ]]
201
- [[ "$output" == *"violations=0"* ]]
202
- }
203
-
204
- @test "placeholder template row is skipped — not counted as a deferred entry" {
205
- # The retro summary template includes a placeholder example row in the
206
- # SKILL.md template (with `<one-line observation summary>` literal text).
207
- # When a retro is rendered with no real deferred entries, the template
208
- # row may persist; the script must NOT count it as a real deferred
209
- # observation.
210
- cat > "$TEST_DIR/2026-04-29-retro.md" <<'RETRO'
211
- ### Tickets Deferred
212
-
213
- | Observation | Cause | Citation |
214
- |-------------|-------|----------|
215
- | <one-line observation summary> | `skill_unavailable` | <retro-step-citation> |
216
- RETRO
217
- run bash "$SCRIPT" "$TEST_DIR"
218
- [ "$status" -eq 0 ]
219
- [ -z "$output" ]
220
- }
221
-
222
- # ── Multi-file behaviour ────────────────────────────────────────────────────
223
-
224
- @test "multiple retro files emit per-file lines plus a TOTAL summary line" {
225
- cat > "$TEST_DIR/2026-04-25-retro.md" <<'RETRO'
226
- ### Tickets Deferred
227
-
228
- | Observation | Cause | Citation |
229
- |-------------|-------|----------|
230
- | good obs | `skill_unavailable` | Step 2b |
231
- RETRO
232
- cat > "$TEST_DIR/2026-04-29-retro.md" <<'RETRO'
233
- ### Tickets Deferred
234
-
235
- | Observation | Cause | Citation |
236
- |-------------|-------|----------|
237
- | bad obs | `session_pressure` | Step 4a |
238
- RETRO
239
- run bash "$SCRIPT" "$TEST_DIR"
240
- [ "$status" -eq 0 ]
241
- [[ "$output" == *"RETRO 2026-04-25"* ]]
242
- [[ "$output" == *"RETRO 2026-04-29"* ]]
243
- [[ "$output" == *"TOTAL files=2 deferred=2 with_valid_cause=1 violations=1"* ]]
244
- }
245
-
246
- @test "files sorted oldest-first by date prefix" {
247
- for d in 27 25 26; do
248
- cat > "$TEST_DIR/2026-04-$d-retro.md" <<RETRO
249
- ### Tickets Deferred
250
-
251
- | Observation | Cause | Citation |
252
- |-------------|-------|----------|
253
- | obs$d | \`skill_unavailable\` | Step$d |
254
- RETRO
255
- done
256
- run bash "$SCRIPT" "$TEST_DIR"
257
- [ "$status" -eq 0 ]
258
- line1="${lines[0]}"
259
- line2="${lines[1]}"
260
- line3="${lines[2]}"
261
- [[ "$line1" == *"2026-04-25"* ]]
262
- [[ "$line2" == *"2026-04-26"* ]]
263
- [[ "$line3" == *"2026-04-27"* ]]
264
- }
265
-
266
- # ── File-type filtering ─────────────────────────────────────────────────────
267
-
268
- @test "ask-hygiene trail files are skipped (not retro summaries)" {
269
- cat > "$TEST_DIR/2026-04-29-ask-hygiene.md" <<'TRAIL'
270
- ### Tickets Deferred
271
-
272
- | Observation | Cause | Citation |
273
- |-------------|-------|----------|
274
- | should be ignored | `session_pressure` | irrelevant |
275
- TRAIL
276
- run bash "$SCRIPT" "$TEST_DIR"
277
- [ "$status" -eq 0 ]
278
- [ -z "$output" ]
279
- }
280
-
281
- @test "context-analysis files are skipped (not retro summaries)" {
282
- cat > "$TEST_DIR/2026-04-29-context-analysis.md" <<'CTX'
283
- ### Tickets Deferred
284
-
285
- | Observation | Cause | Citation |
286
- |-------------|-------|----------|
287
- | should be ignored | `session_pressure` | irrelevant |
288
- CTX
289
- run bash "$SCRIPT" "$TEST_DIR"
290
- [ "$status" -eq 0 ]
291
- [ -z "$output" ]
292
- }
293
-
294
- @test "files without a YYYY-MM-DD date prefix are skipped" {
295
- cat > "$TEST_DIR/README.md" <<'RM'
296
- ### Tickets Deferred
297
-
298
- | Observation | Cause | Citation |
299
- |-------------|-------|----------|
300
- | should be ignored | `session_pressure` | irrelevant |
301
- RM
302
- run bash "$SCRIPT" "$TEST_DIR"
303
- [ "$status" -eq 0 ]
304
- [ -z "$output" ]
305
- }
306
-
307
- # ── Cross-shell portability (P124 / P133 lessons) ───────────────────────────
308
-
309
- @test "script glob iteration uses portable for-loop existence check" {
310
- run bash "$SCRIPT" "$TEST_DIR"
311
- [ "$status" -eq 0 ]
312
- [[ "$output" != *"*.md"* ]]
313
- }
314
-
315
- # ── Read-only contract ──────────────────────────────────────────────────────
316
-
317
- @test "script is read-only — fixture tree unchanged after run" {
318
- cat > "$TEST_DIR/2026-04-29-retro.md" <<'RETRO'
319
- ### Tickets Deferred
320
-
321
- | Observation | Cause | Citation |
322
- |-------------|-------|----------|
323
- | obs1 | `skill_unavailable` | Step 2b |
324
- RETRO
325
- pre_hash=$(find "$TEST_DIR" -type f -exec cksum {} \; 2>/dev/null | sort | cksum | awk '{print $1}')
326
- run bash "$SCRIPT" "$TEST_DIR"
327
- [ "$status" -eq 0 ]
328
- post_hash=$(find "$TEST_DIR" -type f -exec cksum {} \; 2>/dev/null | sort | cksum | awk '{print $1}')
329
- [ "$pre_hash" = "$post_hash" ]
330
- }
@@ -1,149 +0,0 @@
1
- #!/usr/bin/env bats
2
-
3
- # @problem P153 — Published skills enumerate repo-relative directories.
4
- # `/wr-retrospective:analyze-context` SKILL.md L56-67 used a `for plugin_dir
5
- # in packages/*/hooks; do ... done` glob loop that expanded to nothing in
6
- # adopter trees, silently emitting zero PLUGIN-HOOKS / PLUGIN-SKILLS rows.
7
- #
8
- # Fix: extract the loop into a helper script that probes for the source-
9
- # tree first (preserves dev-session output) and falls back to a `$PATH`-
10
- # derived plugin-cache walk so adopter sessions resolve too. Same row
11
- # shape; backward compatible with deep-layer SKILL.md Step 4 sum-check.
12
- #
13
- # Contract:
14
- # list-plugin-attribution.sh [<project-root>]
15
- #
16
- # Default project-root is the current working directory.
17
- #
18
- # Output (one line per row, terse machine-readable per ADR-038 ≤150 bytes):
19
- # PLUGIN-HOOKS <plugin> bytes=<N>
20
- # PLUGIN-SKILLS <plugin> bytes=<N>
21
- # PLUGIN-ATTRIBUTION not-measured reason=<reason>
22
- #
23
- # Exit code: 0 always (advisory, matches measure-context-budget.sh contract).
24
- #
25
- # Resolution order:
26
- # 1. Source-tree mode — if `<project-root>/packages/*/hooks` glob expands
27
- # to anything, walk it. Same applies to `packages/*/skills`.
28
- # 2. Cache-fallback mode — sniff `$PATH` entries that match
29
- # `*/cache/<owner>/<plugin>/<version>/bin`; walk back to each
30
- # plugin's root and emit the same row shape.
31
- # 3. Neither — emit `PLUGIN-ATTRIBUTION not-measured
32
- # reason=no-plugin-source-resolvable`.
33
- #
34
- # @adr ADR-049 (Plugin-bundled scripts via `bin/` on `$PATH` —
35
- # reassessment-criteria clause 3 explicitly anticipates this surface)
36
- # @adr ADR-038 (Progressive disclosure — per-row byte budget)
37
- # @adr ADR-026 (Agent output grounding — explicit not-measured sentinels)
38
- # @adr ADR-005 (Plugin testing strategy)
39
- # @adr ADR-037 (Skill testing strategy — bats-contract precedent)
40
- # @jtbd JTBD-301 (Plugin-user) / JTBD-101 (Plugin-developer)
41
-
42
- setup() {
43
- SCRIPTS_DIR="$(cd "$(dirname "$BATS_TEST_FILENAME")/.." && pwd)"
44
- SCRIPT="$SCRIPTS_DIR/list-plugin-attribution.sh"
45
- FIXTURE_DIR="$(mktemp -d)"
46
- # Minimal PATH for bash + coreutils, but no plugin-cache bin dirs.
47
- # Tests that exercise cache-fallback explicitly prepend a synthetic
48
- # cache bin to this MIN_PATH.
49
- MIN_PATH="/usr/bin:/bin"
50
- }
51
-
52
- teardown() {
53
- rm -rf "$FIXTURE_DIR"
54
- }
55
-
56
- # ── Existence + executable ──────────────────────────────────────────────────
57
-
58
- @test "list-plugin-attribution: script file exists at expected path" {
59
- [ -f "$SCRIPT" ]
60
- }
61
-
62
- @test "list-plugin-attribution: script is executable" {
63
- [ -x "$SCRIPT" ]
64
- }
65
-
66
- # ── Exit code ───────────────────────────────────────────────────────────────
67
-
68
- @test "list-plugin-attribution: empty fixture exits 0 (advisory)" {
69
- # Run with an empty PATH so the cache-fallback yields nothing too.
70
- run env PATH="$MIN_PATH" bash "$SCRIPT" "$FIXTURE_DIR"
71
- [ "$status" -eq 0 ]
72
- }
73
-
74
- # ── Source-tree mode ────────────────────────────────────────────────────────
75
-
76
- @test "list-plugin-attribution: source-tree mode emits PLUGIN-HOOKS row for packages/<plugin>/hooks" {
77
- mkdir -p "$FIXTURE_DIR/packages/foo/hooks"
78
- printf '%s' 'echo hi' > "$FIXTURE_DIR/packages/foo/hooks/h.sh"
79
- run env PATH="$MIN_PATH" bash "$SCRIPT" "$FIXTURE_DIR"
80
- [ "$status" -eq 0 ]
81
- echo "$output" | grep -qE '^PLUGIN-HOOKS foo bytes=[0-9]+$'
82
- }
83
-
84
- @test "list-plugin-attribution: source-tree mode emits PLUGIN-SKILLS row for packages/<plugin>/skills" {
85
- mkdir -p "$FIXTURE_DIR/packages/foo/skills/wizard"
86
- printf '%s' '# Wizard' > "$FIXTURE_DIR/packages/foo/skills/wizard/SKILL.md"
87
- run env PATH="$MIN_PATH" bash "$SCRIPT" "$FIXTURE_DIR"
88
- [ "$status" -eq 0 ]
89
- echo "$output" | grep -qE '^PLUGIN-SKILLS foo bytes=[0-9]+$'
90
- }
91
-
92
- @test "list-plugin-attribution: source-tree mode reports nonzero hook bytes when files present" {
93
- mkdir -p "$FIXTURE_DIR/packages/foo/hooks"
94
- printf '%s' 'echo hi' > "$FIXTURE_DIR/packages/foo/hooks/h.sh" # 7 bytes
95
- run env PATH="$MIN_PATH" bash "$SCRIPT" "$FIXTURE_DIR"
96
- bytes=$(echo "$output" | awk '/^PLUGIN-HOOKS foo bytes=/{ split($3, a, "="); print a[2] }')
97
- [ "${bytes:-0}" -gt 0 ]
98
- }
99
-
100
- @test "list-plugin-attribution: source-tree mode emits one row per plugin (multi-plugin)" {
101
- mkdir -p "$FIXTURE_DIR/packages/foo/hooks" "$FIXTURE_DIR/packages/bar/hooks"
102
- printf 'x' > "$FIXTURE_DIR/packages/foo/hooks/h.sh"
103
- printf 'x' > "$FIXTURE_DIR/packages/bar/hooks/h.sh"
104
- run env PATH="$MIN_PATH" bash "$SCRIPT" "$FIXTURE_DIR"
105
- echo "$output" | grep -qE '^PLUGIN-HOOKS foo bytes='
106
- echo "$output" | grep -qE '^PLUGIN-HOOKS bar bytes='
107
- }
108
-
109
- # ── Cache-fallback mode ─────────────────────────────────────────────────────
110
-
111
- @test "list-plugin-attribution: cache-fallback mode resolves plugins via PATH-derived bin dirs" {
112
- # Synthesise an adopter-shaped layout: ~/.claude/plugins/cache/<owner>/<plugin>/<version>/
113
- cache_root="$FIXTURE_DIR/.claude/plugins/cache/wroad/myplug/0.0.1"
114
- mkdir -p "$cache_root/bin" "$cache_root/hooks" "$cache_root/skills/s1"
115
- printf '%s' 'exec true' > "$cache_root/bin/wr-myplug-cmd"
116
- chmod +x "$cache_root/bin/wr-myplug-cmd"
117
- printf 'hook' > "$cache_root/hooks/h.sh"
118
- printf 'skill' > "$cache_root/skills/s1/SKILL.md"
119
-
120
- # CWD has no packages/ dir → forces cache-fallback path.
121
- empty_cwd="$FIXTURE_DIR/empty"
122
- mkdir -p "$empty_cwd"
123
-
124
- run env PATH="$cache_root/bin:$MIN_PATH" bash "$SCRIPT" "$empty_cwd"
125
- [ "$status" -eq 0 ]
126
- echo "$output" | grep -qE '^PLUGIN-HOOKS myplug bytes=[0-9]+$'
127
- echo "$output" | grep -qE '^PLUGIN-SKILLS myplug bytes=[0-9]+$'
128
- }
129
-
130
- # ── Neither source nor cache resolves ───────────────────────────────────────
131
-
132
- @test "list-plugin-attribution: emits not-measured sentinel when nothing resolves" {
133
- # Empty fixture, empty PATH → zero source + zero cache.
134
- run env PATH="$MIN_PATH" bash "$SCRIPT" "$FIXTURE_DIR"
135
- [ "$status" -eq 0 ]
136
- echo "$output" | grep -qE '^PLUGIN-ATTRIBUTION not-measured reason=no-plugin-source-resolvable$'
137
- }
138
-
139
- # ── Output budget ───────────────────────────────────────────────────────────
140
-
141
- @test "list-plugin-attribution: every output row is under 150 bytes (ADR-038)" {
142
- mkdir -p "$FIXTURE_DIR/packages/foo/hooks" "$FIXTURE_DIR/packages/foo/skills/s1"
143
- printf 'x' > "$FIXTURE_DIR/packages/foo/hooks/h.sh"
144
- printf 'x' > "$FIXTURE_DIR/packages/foo/skills/s1/SKILL.md"
145
- run env PATH="$MIN_PATH" bash "$SCRIPT" "$FIXTURE_DIR"
146
- while IFS= read -r line; do
147
- [ "${#line}" -le 150 ]
148
- done <<< "$output"
149
- }