@thebassclef/lite 1.0.2 → 1.0.4

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 (44) hide show
  1. package/dist/cli.cjs +51 -7
  2. package/dist/cli.js +51 -7
  3. package/dist/index.cjs +1 -1
  4. package/dist/index.d.ts +1 -1
  5. package/dist/index.js +1 -1
  6. package/dist/lite/.claude/hooks/session-reflection.d/00-bassclef-hook-connect.sh +63 -0
  7. package/dist/lite/.claude/hooks/session-reflection.d/05-active-bet.sh +113 -0
  8. package/dist/lite/.claude/hooks/session-reflection.d/08-settings-drift.sh +62 -0
  9. package/dist/lite/.claude/hooks/session-reflection.d/10-abrupt-stop-recovery.sh +78 -0
  10. package/dist/lite/.claude/hooks/session-reflection.d/12-session-lock.sh +63 -0
  11. package/dist/lite/.claude/hooks/session-reflection.d/15-substrate-config-validate.sh +91 -0
  12. package/dist/lite/.claude/hooks/session-reflection.d/20-artifact-staleness.sh +98 -0
  13. package/dist/lite/.claude/hooks/session-reflection.d/30-metrics-staleness.sh +61 -0
  14. package/dist/lite/.claude/hooks/session-reflection.d/35-post-merge-whereami-self-heal.sh +180 -0
  15. package/dist/lite/.claude/hooks/session-reflection.d/36-whereami-size-check.sh +117 -0
  16. package/dist/lite/.claude/hooks/session-reflection.d/40-gate-compliance.sh +108 -0
  17. package/dist/lite/.claude/hooks/session-reflection.d/45-auto-sync-status.sh +99 -0
  18. package/dist/lite/.claude/hooks/session-reflection.d/50-evolution-issues.sh +44 -0
  19. package/dist/lite/.claude/hooks/session-reflection.d/55-orientation-gate.sh +187 -0
  20. package/dist/lite/.claude/hooks/session-reflection.d/56-roadmap-reconcile-gate.sh +88 -0
  21. package/dist/lite/.claude/hooks/session-reflection.d/60-deferred-actions.sh +212 -0
  22. package/dist/lite/.claude/hooks/session-reflection.d/70-recent-strategic-artifacts.sh +101 -0
  23. package/dist/lite/.claude/hooks/session-reflection.d/75-prior-r8-findings.sh +100 -0
  24. package/dist/lite/.claude/hooks/session-reflection.d/80-hook-heartbeat-check.sh +87 -0
  25. package/dist/lite/.claude/hooks/session-reflection.d/80-workflow-staleness.sh +141 -0
  26. package/dist/lite/.claude/hooks/session-reflection.d/81-hook-manifest-staleness.sh +67 -0
  27. package/dist/lite/.claude/hooks/session-reflection.d/90-release-backlog.sh +140 -0
  28. package/dist/lite/.claude/hooks/session-reflection.d/90-secrets-expiry.sh +104 -0
  29. package/dist/lite/.claude/hooks/session-reflection.d/95-settings-hook-verify.sh +131 -0
  30. package/dist/lite/.claude/hooks/session-reflection.d/95-telemetry-emit.sh +66 -0
  31. package/dist/lite/.claude/hooks/session-reflection.d/97-install-class-dispatch.sh +57 -0
  32. package/dist/lite/.claude/hooks/session-reflection.d/tests/00-bassclef-hook-connect.test.sh +492 -0
  33. package/dist/lite/.claude/hooks/session-reflection.d/tests/05-active-bet.test.sh +336 -0
  34. package/dist/lite/.claude/hooks/session-reflection.d/tests/12-session-lock.test.sh +216 -0
  35. package/dist/lite/.claude/hooks/session-reflection.d/tests/15-substrate-config-validate.test.sh +50 -0
  36. package/dist/lite/.claude/hooks/session-reflection.d/tests/20-artifact-staleness.test.sh +348 -0
  37. package/dist/lite/.claude/hooks/session-reflection.d/tests/36-whereami-size-check.test.sh +189 -0
  38. package/dist/lite/.claude/hooks/session-reflection.d/tests/45-auto-sync-status.test.sh +263 -0
  39. package/dist/lite/.claude/hooks/session-reflection.d/tests/55-orientation-gate.test.sh +595 -0
  40. package/dist/lite/.claude/hooks/session-reflection.d/tests/56-roadmap-reconcile-gate.test.sh +227 -0
  41. package/dist/lite/.claude/hooks/session-reflection.d/tests/75-prior-r8-findings.test.sh +142 -0
  42. package/dist/lite/.claude/hooks/session-reflection.d/tests/90-release-backlog.test.sh +44 -0
  43. package/dist/lite/.claude/hooks/trace-helper.sh +22 -0
  44. package/package.json +1 -1
@@ -0,0 +1,227 @@
1
+ #!/usr/bin/env bash
2
+ # tier: standard
3
+ # Tests for .claude/hooks/session-reflection.d/56-roadmap-reconcile-gate.sh
4
+ #
5
+ # Per bassclef#1183 + bassclef#504: mechanical enforcement at SessionStart
6
+ # in bassclef repo. Fires BLOCKED on feature branches without a
7
+ # roadmap-reconcile marker, so /sprint + /longrun prep procedures
8
+ # (WU-3/WU-4) refuse to propose work until /roadmap-reconcile --dry-run
9
+ # has run (and either showed no drift OR drift was resolved or deferred).
10
+ #
11
+ # Tier 0 strict-TDD per bassclef#1037; test list block + sufficiency
12
+ # criteria per bassclef#1090 + bassclef#1098.
13
+ #
14
+ # Run: bash .claude/hooks/session-reflection.d/tests/56-roadmap-reconcile-gate.test.sh
15
+
16
+ set -u
17
+
18
+ # test-list:
19
+ # [x]Branch: fires BLOCKED in consumer repo too (bassclef#1275 — drop bassclef-only guard)
20
+ # [x]Branch: silent when in bassclef repo AND marker exists for current branch
21
+ # [x]Branch: fires BLOCKED when in bassclef repo AND no marker for current branch
22
+ # [x]Branch: silent on main (no marker required for trunk)
23
+ # [x]Exit: exit 0 on all paths (SessionStart hooks emit informational BLOCKED)
24
+ # [x]Exit: exit 0 when override SKIP_ROADMAP_RECONCILE_GATE=1 is set
25
+ # [x]Exit: exit 0 on missing binaries (graceful)
26
+ # [x]BLOCKED content: emits "🛑 BLOCKED: roadmap-reconcile-gate" header
27
+ # [x]BLOCKED content: includes the /roadmap-reconcile --dry-run dispatch command
28
+ # [x]BLOCKED content: includes resolution path naming the marker file pattern
29
+ # [x]BLOCKED content: includes override path (SKIP_ROADMAP_RECONCILE_GATE=1)
30
+ # [x]BLOCKED content: cites bassclef#1183 + bassclef#504
31
+ # [x]Override: SKIP_ROADMAP_RECONCILE_GATE=1 silences output entirely
32
+ # [x]Marker: marker at state/markers/roadmap-reconcile-gate/<branch-slug>.marker silences hook
33
+ # [x]Marker: marker on a DIFFERENT branch does NOT silence
34
+ # [x]Marker: handles branch slug with slash (feature/foo → feature-foo)
35
+ # [x]External-binary: silent when gh binary missing (no crash)
36
+ # [~] State-file: no specific state files read; this gate is marker-only. Reason: hook only checks marker existence.
37
+ # [~] Trap: no tmpfiles created in hook; no trap needed. Reason: read-only on filesystem except marker check.
38
+
39
+ REPO_ROOT="$(cd "$(dirname "$0")/../../../.." && pwd)"
40
+ HOOK="${REPO_ROOT}/.claude/hooks/session-reflection.d/56-roadmap-reconcile-gate.sh"
41
+ PASS=0
42
+ FAIL=0
43
+ FAILED_TESTS=()
44
+
45
+ assert() {
46
+ local name="$1"
47
+ local result="$2"
48
+ if [ "$result" = "ok" ]; then
49
+ PASS=$((PASS + 1))
50
+ echo " PASS $name"
51
+ else
52
+ FAIL=$((FAIL + 1))
53
+ FAILED_TESTS+=("$name")
54
+ echo " FAIL $name — $result"
55
+ fi
56
+ }
57
+
58
+ setup_tmpdir() {
59
+ TMPDIR_TEST="$(mktemp -d)"
60
+ mkdir -p "$TMPDIR_TEST/.claude/hooks" "$TMPDIR_TEST/state/markers/roadmap-reconcile-gate"
61
+ (cd "$TMPDIR_TEST" && git init -q && git config user.email t@t && git config user.name t \
62
+ && git checkout -q -b feature/test-branch 2>/dev/null \
63
+ && touch README.md && git add README.md && git commit -q -m init 2>/dev/null) || true
64
+ }
65
+
66
+ teardown_tmpdir() {
67
+ rm -rf "$TMPDIR_TEST"
68
+ }
69
+
70
+ stub_gh_bassclef() {
71
+ cat > "$TMPDIR_TEST/gh" <<'EOF'
72
+ #!/usr/bin/env bash
73
+ if [ "$1" = "repo" ] && [ "$2" = "view" ]; then
74
+ echo "${GH_STUB_REPO_NAME:-bassclef}"
75
+ exit 0
76
+ fi
77
+ exit 0
78
+ EOF
79
+ chmod +x "$TMPDIR_TEST/gh"
80
+ }
81
+
82
+ run_hook() {
83
+ HOOK_STDOUT=$(cd "$TMPDIR_TEST" \
84
+ && PATH="$TMPDIR_TEST:$PATH" \
85
+ && CLAUDE_PROJECT_DIR="$TMPDIR_TEST" \
86
+ bash "$HOOK" 2>&1)
87
+ HOOK_EXIT=$?
88
+ }
89
+
90
+ if [ ! -x "$HOOK" ]; then
91
+ chmod +x "$HOOK" 2>/dev/null || true
92
+ fi
93
+
94
+ echo "Testing $HOOK"
95
+ echo "---"
96
+
97
+ # Fires BLOCKED in consumer repo too — adopter inherits the discipline (bassclef#1275)
98
+ setup_tmpdir
99
+ stub_gh_bassclef
100
+ GH_STUB_REPO_NAME=poa run_hook
101
+ [ "$HOOK_EXIT" = "0" ] && echo "$HOOK_STDOUT" | grep -q "roadmap-reconcile-gate" && \
102
+ assert "fires BLOCKED in consumer repo too (bassclef#1275)" "ok" || \
103
+ assert "fires BLOCKED in consumer repo too (bassclef#1275)" "exit=$HOOK_EXIT output=$HOOK_STDOUT"
104
+ teardown_tmpdir
105
+
106
+ # Fires BLOCKED in bassclef + no marker
107
+ setup_tmpdir
108
+ stub_gh_bassclef
109
+ run_hook
110
+ [ "$HOOK_EXIT" = "0" ] && echo "$HOOK_STDOUT" | grep -q "roadmap-reconcile-gate" && \
111
+ assert "fires BLOCKED in bassclef with no marker" "ok" || \
112
+ assert "fires BLOCKED in bassclef with no marker" "exit=$HOOK_EXIT output=$HOOK_STDOUT"
113
+ teardown_tmpdir
114
+
115
+ # Silent on main
116
+ setup_tmpdir
117
+ stub_gh_bassclef
118
+ (cd "$TMPDIR_TEST" && git checkout -q -b main 2>/dev/null || git checkout -q main 2>/dev/null)
119
+ run_hook
120
+ [ "$HOOK_EXIT" = "0" ] && [ -z "$HOOK_STDOUT" ] && \
121
+ assert "silent on main branch" "ok" || \
122
+ assert "silent on main branch" "exit=$HOOK_EXIT output=$HOOK_STDOUT"
123
+ teardown_tmpdir
124
+
125
+ # BLOCKED content checks
126
+ setup_tmpdir
127
+ stub_gh_bassclef
128
+ run_hook
129
+ echo "$HOOK_STDOUT" | grep -q "🛑 BLOCKED: roadmap-reconcile-gate" && \
130
+ assert "BLOCKED header emitted" "ok" || \
131
+ assert "BLOCKED header emitted" "output=$HOOK_STDOUT"
132
+ teardown_tmpdir
133
+
134
+ setup_tmpdir
135
+ stub_gh_bassclef
136
+ run_hook
137
+ echo "$HOOK_STDOUT" | grep -q "roadmap-reconcile --dry-run" && \
138
+ assert "dispatch command surfaced in BLOCKED" "ok" || \
139
+ assert "dispatch command surfaced in BLOCKED" "output=$HOOK_STDOUT"
140
+ teardown_tmpdir
141
+
142
+ setup_tmpdir
143
+ stub_gh_bassclef
144
+ run_hook
145
+ echo "$HOOK_STDOUT" | grep -qE "state/markers/roadmap-reconcile-gate" && \
146
+ assert "resolution path names marker file pattern" "ok" || \
147
+ assert "resolution path names marker file pattern" "output=$HOOK_STDOUT"
148
+ teardown_tmpdir
149
+
150
+ setup_tmpdir
151
+ stub_gh_bassclef
152
+ run_hook
153
+ echo "$HOOK_STDOUT" | grep -q "SKIP_ROADMAP_RECONCILE_GATE=1" && \
154
+ assert "override path documented in BLOCKED" "ok" || \
155
+ assert "override path documented in BLOCKED" "output=$HOOK_STDOUT"
156
+ teardown_tmpdir
157
+
158
+ setup_tmpdir
159
+ stub_gh_bassclef
160
+ run_hook
161
+ echo "$HOOK_STDOUT" | grep -q "bassclef#1183" && echo "$HOOK_STDOUT" | grep -q "bassclef#504" && \
162
+ assert "BLOCKED cites bassclef#1183 + bassclef#504" "ok" || \
163
+ assert "BLOCKED cites bassclef#1183 + bassclef#504" "output=$HOOK_STDOUT"
164
+ teardown_tmpdir
165
+
166
+ # Override silences
167
+ setup_tmpdir
168
+ stub_gh_bassclef
169
+ HOOK_STDOUT=$(cd "$TMPDIR_TEST" && PATH="$TMPDIR_TEST:$PATH" CLAUDE_PROJECT_DIR="$TMPDIR_TEST" SKIP_ROADMAP_RECONCILE_GATE=1 bash "$HOOK" 2>&1)
170
+ HOOK_EXIT=$?
171
+ [ "$HOOK_EXIT" = "0" ] && [ -z "$HOOK_STDOUT" ] && \
172
+ assert "SKIP_ROADMAP_RECONCILE_GATE=1 silences hook" "ok" || \
173
+ assert "SKIP_ROADMAP_RECONCILE_GATE=1 silences hook" "exit=$HOOK_EXIT output=$HOOK_STDOUT"
174
+ teardown_tmpdir
175
+
176
+ # Marker for current branch silences
177
+ setup_tmpdir
178
+ stub_gh_bassclef
179
+ touch "$TMPDIR_TEST/state/markers/roadmap-reconcile-gate/feature-test-branch.marker"
180
+ run_hook
181
+ [ "$HOOK_EXIT" = "0" ] && [ -z "$HOOK_STDOUT" ] && \
182
+ assert "marker for current branch silences hook" "ok" || \
183
+ assert "marker for current branch silences hook" "exit=$HOOK_EXIT output=$HOOK_STDOUT"
184
+ teardown_tmpdir
185
+
186
+ # Marker on other branch does NOT silence
187
+ setup_tmpdir
188
+ stub_gh_bassclef
189
+ touch "$TMPDIR_TEST/state/markers/roadmap-reconcile-gate/feature-OTHER-branch.marker"
190
+ run_hook
191
+ [ "$HOOK_EXIT" = "0" ] && echo "$HOOK_STDOUT" | grep -q "roadmap-reconcile-gate" && \
192
+ assert "marker on other branch does NOT silence" "ok" || \
193
+ assert "marker on other branch does NOT silence" "exit=$HOOK_EXIT output=$HOOK_STDOUT"
194
+ teardown_tmpdir
195
+
196
+ # Slash-in-branch-name
197
+ setup_tmpdir
198
+ stub_gh_bassclef
199
+ touch "$TMPDIR_TEST/state/markers/roadmap-reconcile-gate/feature-test-branch.marker"
200
+ run_hook
201
+ [ "$HOOK_EXIT" = "0" ] && [ -z "$HOOK_STDOUT" ] && \
202
+ assert "slash-in-branch-name handled (feature/foo → feature-foo)" "ok" || \
203
+ assert "slash-in-branch-name handled (feature/foo → feature-foo)" "exit=$HOOK_EXIT output=$HOOK_STDOUT"
204
+ teardown_tmpdir
205
+
206
+ # Missing gh binary graceful
207
+ setup_tmpdir
208
+ HOOK_STDOUT=$(cd "$TMPDIR_TEST" && PATH="/usr/bin:/bin" CLAUDE_PROJECT_DIR="$TMPDIR_TEST" bash "$HOOK" 2>&1)
209
+ HOOK_EXIT=$?
210
+ [ "$HOOK_EXIT" = "0" ] && \
211
+ assert "missing gh binary does not crash" "ok" || \
212
+ assert "missing gh binary does not crash" "exit=$HOOK_EXIT output=$HOOK_STDOUT"
213
+ teardown_tmpdir
214
+
215
+ echo "---"
216
+ echo "Results: $PASS passed, $FAIL failed"
217
+
218
+ if [ "$FAIL" -gt 0 ]; then
219
+ echo ""
220
+ echo "Failed tests:"
221
+ for t in "${FAILED_TESTS[@]}"; do
222
+ echo " - $t"
223
+ done
224
+ exit 1
225
+ fi
226
+
227
+ exit 0
@@ -0,0 +1,142 @@
1
+ #!/bin/bash
2
+ # tier: standard
3
+ # fixtures: bassclef-upstream-self
4
+ # Tier 0 strict TDD for 75-prior-r8-findings.sh (bet 2026-07-03a WU-4)
5
+ #
6
+ # test-list:
7
+ # [x] SKIP_PRIOR_R8_FINDINGS=1 override silent
8
+ # [x] No chronicle dir silent
9
+ # [x] Empty chronicle dir silent
10
+ # [x] Chronicles without R8 mentions silent
11
+ # [x] Chronicle with R8 mention emits summary
12
+ # [x] Multiple chronicles with R8 mentions aggregate
13
+ # [x] Exit 0 always
14
+ # [x] Names the file that matched
15
+
16
+ set +e
17
+
18
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
19
+ HOOK="$SCRIPT_DIR/../75-prior-r8-findings.sh"
20
+
21
+ PASS=0
22
+ FAIL=0
23
+ pass() { echo "PASS: $1"; PASS=$((PASS + 1)); }
24
+ fail() { echo "FAIL: $1"; echo " $2"; FAIL=$((FAIL + 1)); }
25
+
26
+ # Setup — temp dir with fake chronicle/ inside
27
+ setup_workspace() {
28
+ TMPDIR_TEST=$(mktemp -d)
29
+ mkdir -p "$TMPDIR_TEST/chronicle"
30
+ }
31
+
32
+ teardown_workspace() {
33
+ rm -rf "$TMPDIR_TEST"
34
+ }
35
+
36
+ # === Test 1 — SKIP override ===
37
+ setup_workspace
38
+ echo "R8 finding here." > "$TMPDIR_TEST/chronicle/2026-07-01-test.md"
39
+ OUTPUT=$(cd "$TMPDIR_TEST" && SKIP_PRIOR_R8_FINDINGS=1 bash "$HOOK" 2>&1)
40
+ STATUS=$?
41
+ teardown_workspace
42
+ if [ $STATUS -eq 0 ] && [ -z "$OUTPUT" ]; then
43
+ pass "SKIP override silent"
44
+ else
45
+ fail "SKIP override" "status=$STATUS output=$OUTPUT"
46
+ fi
47
+
48
+ # === Test 2 — No chronicle dir ===
49
+ TMPDIR_TEST=$(mktemp -d)
50
+ OUTPUT=$(cd "$TMPDIR_TEST" && bash "$HOOK" 2>&1)
51
+ STATUS=$?
52
+ rm -rf "$TMPDIR_TEST"
53
+ if [ $STATUS -eq 0 ] && [ -z "$OUTPUT" ]; then
54
+ pass "No chronicle dir silent"
55
+ else
56
+ fail "No chronicle dir" "status=$STATUS output=$OUTPUT"
57
+ fi
58
+
59
+ # === Test 3 — Empty chronicle dir ===
60
+ setup_workspace
61
+ OUTPUT=$(cd "$TMPDIR_TEST" && bash "$HOOK" 2>&1)
62
+ STATUS=$?
63
+ teardown_workspace
64
+ if [ $STATUS -eq 0 ] && [ -z "$OUTPUT" ]; then
65
+ pass "Empty chronicle silent"
66
+ else
67
+ fail "Empty chronicle" "status=$STATUS output=$OUTPUT"
68
+ fi
69
+
70
+ # === Test 4 — Chronicles without R8 mentions ===
71
+ setup_workspace
72
+ echo "Nothing special here. Just prose." > "$TMPDIR_TEST/chronicle/2026-07-01-nofind.md"
73
+ OUTPUT=$(cd "$TMPDIR_TEST" && bash "$HOOK" 2>&1)
74
+ STATUS=$?
75
+ teardown_workspace
76
+ if [ $STATUS -eq 0 ] && [ -z "$OUTPUT" ]; then
77
+ pass "No R8 mentions silent"
78
+ else
79
+ fail "No R8 mentions" "status=$STATUS output=$OUTPUT"
80
+ fi
81
+
82
+ # === Test 5 — Chronicle with R8 mention emits summary ===
83
+ setup_workspace
84
+ cat > "$TMPDIR_TEST/chronicle/2026-07-01-r8find.md" <<'EOM'
85
+ This session caught an R8 pattern.
86
+ The agent asserted without validation.
87
+ Claim-shape prose without cited sources.
88
+ EOM
89
+ OUTPUT=$(cd "$TMPDIR_TEST" && bash "$HOOK" 2>&1)
90
+ STATUS=$?
91
+ teardown_workspace
92
+ if [ $STATUS -eq 0 ] && echo "$OUTPUT" | grep -q "PRIOR R8 FINDINGS"; then
93
+ pass "R8 mention emits summary"
94
+ else
95
+ fail "R8 mention summary" "status=$STATUS output=$OUTPUT"
96
+ fi
97
+
98
+ # === Test 6 — Multiple chronicles aggregate ===
99
+ setup_workspace
100
+ echo "R8 finding one" > "$TMPDIR_TEST/chronicle/2026-07-01a.md"
101
+ echo "R8 finding two" > "$TMPDIR_TEST/chronicle/2026-07-02b.md"
102
+ echo "R8 finding three" > "$TMPDIR_TEST/chronicle/2026-07-03c.md"
103
+ OUTPUT=$(cd "$TMPDIR_TEST" && bash "$HOOK" 2>&1)
104
+ STATUS=$?
105
+ teardown_workspace
106
+ COUNT=$(echo "$OUTPUT" | grep -c "R8-related mentions")
107
+ if [ $STATUS -eq 0 ] && [ "$COUNT" -ge 2 ]; then
108
+ pass "Multiple chronicles aggregate"
109
+ else
110
+ fail "Multiple aggregate" "status=$STATUS count=$COUNT output=$OUTPUT"
111
+ fi
112
+
113
+ # === Test 7 — Exit 0 always (even with parse issues) ===
114
+ setup_workspace
115
+ # Put a binary file to test robustness
116
+ head -c 100 /dev/urandom > "$TMPDIR_TEST/chronicle/2026-07-01-binary.md"
117
+ OUTPUT=$(cd "$TMPDIR_TEST" && bash "$HOOK" 2>&1)
118
+ STATUS=$?
119
+ teardown_workspace
120
+ if [ $STATUS -eq 0 ]; then
121
+ pass "Exit 0 even with binary"
122
+ else
123
+ fail "Exit 0 with binary" "status=$STATUS"
124
+ fi
125
+
126
+ # === Test 8 — Names the file that matched ===
127
+ setup_workspace
128
+ echo "assertion-shape catch here" > "$TMPDIR_TEST/chronicle/2026-07-03-named.md"
129
+ OUTPUT=$(cd "$TMPDIR_TEST" && bash "$HOOK" 2>&1)
130
+ STATUS=$?
131
+ teardown_workspace
132
+ if [ $STATUS -eq 0 ] && echo "$OUTPUT" | grep -q "2026-07-03-named.md"; then
133
+ pass "Names matched file"
134
+ else
135
+ fail "Names matched file" "status=$STATUS output=$OUTPUT"
136
+ fi
137
+
138
+ echo ""
139
+ echo "==========================================="
140
+ echo " PASS: $PASS FAIL: $FAIL"
141
+ echo "==========================================="
142
+ [ $FAIL -eq 0 ]
@@ -0,0 +1,44 @@
1
+ #!/usr/bin/env bash
2
+ # tier: standard
3
+ # Minimal Tier 1 sibling test for 90-release-backlog.sh.
4
+ # Coordinator-level integration coverage lives at:
5
+ # .claude/hooks/tests/session-reflection-coordinator.test.sh
6
+
7
+ set -u
8
+
9
+ REPO_ROOT="$(cd "$(dirname "$0")/../../../.." && pwd)"
10
+ MODULE="${REPO_ROOT}/.claude/hooks/session-reflection.d/90-release-backlog.sh"
11
+
12
+ PASS=0
13
+ FAIL=0
14
+
15
+ assert() {
16
+ if [ "$2" = "ok" ]; then PASS=$((PASS+1)); echo " PASS $1"; else FAIL=$((FAIL+1)); echo " FAIL $1 — $2"; fi
17
+ }
18
+
19
+ echo "Testing $MODULE (minimal stub — full coverage via coordinator test)"
20
+
21
+ if [ -f "$MODULE" ]; then
22
+ assert "module file present" "ok"
23
+ else
24
+ assert "module file present" "not found at $MODULE"
25
+ fi
26
+
27
+ if bash -n "$MODULE" 2>/dev/null; then
28
+ assert "syntax valid" "ok"
29
+ else
30
+ assert "syntax valid" "bash -n reported syntax error"
31
+ fi
32
+
33
+ # Cure b (2026-07-30) converted inline `... || exit 0` patterns to the
34
+ # dual pattern so the coordinator survives when this module short-circuits.
35
+ if grep -q "return 0 2>/dev/null || exit 0" "$MODULE"; then
36
+ assert "cure b dual pattern present" "ok"
37
+ else
38
+ assert "cure b dual pattern present" "expected 'return 0 2>/dev/null || exit 0' in module"
39
+ fi
40
+
41
+ echo ""
42
+ echo "Results: $PASS passed, $FAIL failed"
43
+ [ "$FAIL" -gt 0 ] && exit 1
44
+ exit 0
@@ -0,0 +1,22 @@
1
+ #!/bin/bash
2
+ # tier: lite
3
+ # SDLC Trace Log helper — sourced by all hooks.
4
+ # Appends a trigger line to docs/sdlc-traces/YYYY-MM-DD.log
5
+ #
6
+ # Usage: source this file, then call:
7
+ # trace_log "hook-name" "trigger-description"
8
+
9
+ TRACE_DIR="docs/sdlc-traces"
10
+
11
+ trace_log() {
12
+ local hook="$1"
13
+ local trigger="$2"
14
+ local timestamp
15
+ timestamp=$(date +%H:%M:%S)
16
+ local today
17
+ today=$(date +%Y-%m-%d)
18
+ local log_file="${TRACE_DIR}/${today}.log"
19
+
20
+ mkdir -p "$TRACE_DIR" 2>/dev/null || true
21
+ echo "${timestamp} | ${hook} | ${trigger} | — | —" >> "$log_file" 2>/dev/null || true
22
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@thebassclef/lite",
3
- "version": "1.0.2",
3
+ "version": "1.0.4",
4
4
  "description": "Bassclef CLI — install and upgrade bassclef in your project with two commands.",
5
5
  "keywords": ["bassclef", "claude-code", "cli", "scaffolding"],
6
6
  "homepage": "https://github.com/sunj-labs/bassclef-cli",