@thebassclef/lite 1.0.2 → 1.0.3

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 +24 -1
  2. package/dist/cli.js +24 -1
  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,131 @@
1
+ # tier: lite
2
+ # Settings hook path verifier — fires at every SessionStart via
3
+ # session-reflection.sh. Reads project settings.json (and user
4
+ # settings.json when reachable), enumerates every hook command path,
5
+ # checks each file exists on disk. Fires BLOCKED banner when any wired
6
+ # hook path resolves to a missing file.
7
+ #
8
+ # Closes the silent staleness class per bassclef-upstream#888. When a
9
+ # hook path in settings.json points at a file that got renamed, deleted,
10
+ # or never installed, SessionStart today prints a non-blocking error and
11
+ # the session continues. Adopters miss the signal. Substrate discipline
12
+ # quietly disappears from that session's context.
13
+ #
14
+ # Sourced (not exec'd) by session-reflection.sh. Inherits:
15
+ # - blocked_banner() function
16
+ # - trace_log() function
17
+ # - BASSCLEF_DIR environment variable
18
+ # - CWD (project root; the harness sets it before source)
19
+ #
20
+ # Per @luminary saltzer-schroeder — complete mediation. Every settings
21
+ # entry gets checked, not sampled.
22
+ # Per @luminary linus-torvalds — we do not break adopters. A missing hook
23
+ # is a silent break of the adopter contract; this check surfaces it.
24
+ #
25
+ # Override path — operator can bypass per-session.
26
+ if [ "${SKIP_SETTINGS_HOOK_VERIFY:-0}" = "1" ]; then
27
+ trace_log "skip" "settings-hook-verify" "SKIP_SETTINGS_HOOK_VERIFY=1" 2>/dev/null || true
28
+ return 0 2>/dev/null || true
29
+ fi
30
+
31
+ # Require jq for JSON parsing. Skip silently when absent (rare).
32
+ if ! command -v jq >/dev/null 2>&1; then
33
+ trace_log "skip" "settings-hook-verify" "jq not available" 2>/dev/null || true
34
+ return 0 2>/dev/null || true
35
+ fi
36
+
37
+ __shv_settings_files=""
38
+ __shv_project_settings="${CWD:-${PWD}}/.claude/settings.json"
39
+ if [ -f "$__shv_project_settings" ]; then
40
+ __shv_settings_files="$__shv_project_settings"
41
+ fi
42
+ __shv_user_settings="${HOME}/.claude/settings.json"
43
+ if [ -f "$__shv_user_settings" ]; then
44
+ __shv_settings_files="${__shv_settings_files:+${__shv_settings_files}$'\n'}${__shv_user_settings}"
45
+ fi
46
+
47
+ if [ -z "$__shv_settings_files" ]; then
48
+ trace_log "skip" "settings-hook-verify" "no settings.json readable" 2>/dev/null || true
49
+ unset __shv_settings_files __shv_project_settings __shv_user_settings
50
+ return 0 2>/dev/null || true
51
+ fi
52
+
53
+ # Extract the first token of every hook command across every event class.
54
+ # The command string may be plain path OR `path && next` OR `env=X path`.
55
+ # We take the first whitespace-separated token.
56
+ __shv_missing=""
57
+ __shv_check_file() {
58
+ local raw_cmd="$1"
59
+ local source_file="$2"
60
+ # First token — everything up to the first space, tab, or ampersand.
61
+ local first_token
62
+ first_token=$(printf '%s' "$raw_cmd" | awk '{print $1}')
63
+ # Skip if empty or does not look like a path (starts with quote or brace).
64
+ case "$first_token" in
65
+ ''|'{'*|'['*) return 0 ;;
66
+ esac
67
+ # Expand known env vars. Leave others as-is (best effort).
68
+ local expanded="$first_token"
69
+ expanded="${expanded//\$HOME/$HOME}"
70
+ expanded="${expanded//\$\{HOME\}/$HOME}"
71
+ expanded="${expanded//\$CLAUDE_PROJECT_DIR/${CWD:-${PWD}}}"
72
+ expanded="${expanded//\$\{CLAUDE_PROJECT_DIR\}/${CWD:-${PWD}}}"
73
+ # If still has an unexpanded $VAR, skip (cannot verify with confidence).
74
+ case "$expanded" in
75
+ *'$'*) return 0 ;;
76
+ esac
77
+ # Absolute path required for the check.
78
+ case "$expanded" in
79
+ /*) : ;;
80
+ *) return 0 ;;
81
+ esac
82
+ if [ ! -f "$expanded" ]; then
83
+ __shv_missing="${__shv_missing:+${__shv_missing}$'\n'} - ${expanded} (from ${source_file})"
84
+ fi
85
+ }
86
+
87
+ __shv_scan_settings() {
88
+ local settings="$1"
89
+ local raw
90
+ # Extract every .hooks.*[].hooks[].command as one line per command.
91
+ raw=$(jq -r '
92
+ .hooks // {}
93
+ | to_entries[]?
94
+ | .value[]?
95
+ | .hooks[]?
96
+ | select(.command != null)
97
+ | .command
98
+ ' "$settings" 2>/dev/null)
99
+ if [ -z "$raw" ]; then
100
+ return 0
101
+ fi
102
+ local line
103
+ while IFS= read -r line; do
104
+ [ -n "$line" ] && __shv_check_file "$line" "$settings"
105
+ done <<< "$raw"
106
+ }
107
+
108
+ # Scan each settings file.
109
+ while IFS= read -r __shv_file; do
110
+ [ -n "$__shv_file" ] && __shv_scan_settings "$__shv_file"
111
+ done <<< "$__shv_settings_files"
112
+
113
+ if [ -n "$__shv_missing" ]; then
114
+ blocked_banner "settings-hook-verify" \
115
+ "Hooks wired in settings.json but missing on disk:" \
116
+ "$__shv_missing" \
117
+ "" \
118
+ "Cure paths:" \
119
+ " 1. Re-run bassclef-sync.sh to restore vendored/symlinked hooks" \
120
+ " 2. Edit the settings file and remove the stale entry" \
121
+ " 3. Override this session: SKIP_SETTINGS_HOOK_VERIFY=1" \
122
+ "" \
123
+ "Per bassclef-upstream#888."
124
+ trace_log "fired" "settings-hook-verify" "missing hooks detected" 2>/dev/null || true
125
+ else
126
+ trace_log "pass" "settings-hook-verify" "all wired hooks resolve" 2>/dev/null || true
127
+ fi
128
+
129
+ unset __shv_settings_files __shv_project_settings __shv_user_settings \
130
+ __shv_missing __shv_file
131
+ unset -f __shv_check_file __shv_scan_settings
@@ -0,0 +1,66 @@
1
+ #!/usr/bin/env bash
2
+ # .claude/hooks/session-reflection.d/95-telemetry-emit.sh
3
+ # tier: lite
4
+ # install-class: dual
5
+ #
6
+ # Session-start telemetry emit fragment (bet 2026-07-31f Step 4).
7
+ #
8
+ # Emits `session_start` event when opt-in is ON. If no prior events file
9
+ # exists, also emits an `install_probe` event once — this is the first-
10
+ # session marker used to correlate install source.
11
+ #
12
+ # Silent-fail per @luminary michael-nygard R1 — never crashes session start.
13
+
14
+ # Coordinator-side helpers are provided by the parent session-reflection loop.
15
+ # When sourced from that context, `blocked_banner` + `trace_log` + `BASSCLEF_DIR`
16
+ # are already in scope. When run standalone, we no-op the helpers to stay safe.
17
+
18
+ if ! declare -F trace_log >/dev/null 2>&1; then
19
+ trace_log() { :; }
20
+ fi
21
+ BASSCLEF_DIR="${BASSCLEF_DIR:-${CWD:-$PWD}}"
22
+
23
+ # Probe bundled lib path first (dist/lite/ ship path per #1631 goal
24
+ # 2026-09-14b), then $BASSCLEF_DIR fallback for synced adopters.
25
+ # Pattern matches session-reflection.sh:13.
26
+ _sd="$(dirname "${BASH_SOURCE[0]:-$0}")"
27
+ TL_LIB=""
28
+ for _c in "${_sd}/../../../lib/telemetry.sh" \
29
+ "$BASSCLEF_DIR/lib/telemetry.sh"; do
30
+ [ -f "$_c" ] && TL_LIB="$_c" && break
31
+ done
32
+
33
+ # Fire in a silent-fail block so any error here does not crash session start.
34
+ {
35
+ # Only fire when the lib exists (adopter has telemetry enabled)
36
+ if [ -n "$TL_LIB" ]; then
37
+ # shellcheck source=/dev/null
38
+ source "$TL_LIB" 2>/dev/null || return 0 2>/dev/null || exit 0
39
+
40
+ if telemetry_is_enabled; then
41
+ sid=$(telemetry_session_id)
42
+ today=$(date -u +%Y%m%d)
43
+ events_dir="$BASSCLEF_DIR/state/telemetry"
44
+
45
+ # Install probe fires once per install — check if any prior events exist
46
+ if ! compgen -G "$events_dir/events-*.jsonl" >/dev/null 2>&1; then
47
+ # First session ever — emit install_probe (source: unknown for MVP)
48
+ install_source="unknown"
49
+ [ -d "$BASSCLEF_DIR/node_modules/@thebassclef" ] && install_source="npm"
50
+ [ -f "$BASSCLEF_DIR/.git/HEAD" ] && install_source="github-clone"
51
+
52
+ uid=$(uuidgen 2>/dev/null | tr '[:upper:]' '[:lower:]' || echo "00000000-0000-4000-8000-000000000000")
53
+ ts=$(date -u +%Y-%m-%dT%H:%M:%SZ)
54
+ telemetry_emit "{\"event_type\":\"install_probe\",\"event_id\":\"$uid\",\"session_id\":\"$sid\",\"timestamp\":\"$ts\",\"tier\":\"lite\",\"payload\":{\"install_source\":\"$install_source\"}}"
55
+ fi
56
+
57
+ # Emit session_start
58
+ uid=$(uuidgen 2>/dev/null | tr '[:upper:]' '[:lower:]' || echo "00000000-0000-4000-8000-000000000001")
59
+ ts=$(date -u +%Y-%m-%dT%H:%M:%SZ)
60
+ telemetry_emit "{\"event_type\":\"session_start\",\"event_id\":\"$uid\",\"session_id\":\"$sid\",\"timestamp\":\"$ts\",\"tier\":\"lite\",\"payload\":{}}"
61
+ trace_log "95-telemetry-emit: session_start emitted for session $sid"
62
+ fi
63
+ fi
64
+ } 2>/dev/null || true
65
+
66
+ return 0 2>/dev/null || exit 0
@@ -0,0 +1,57 @@
1
+ #!/usr/bin/env bash
2
+ # tier: lite
3
+ # install-class: dual
4
+ #
5
+ # 97-install-class-dispatch.sh — fragment that sources the install-class
6
+ # dispatch libs so the source-graph closure walker discovers them at
7
+ # build time (per scripts/build-adopter-tree.sh).
8
+ #
9
+ # Behavior today (V0 — goal 14c Steps 0-4 landed):
10
+ # - Sources lib/hook-header-parser.sh + lib/hook-installer.sh + lib/source-graph-walker.sh
11
+ # - Does NOT call install_by_class yet — Steps 5-6 extend this fragment
12
+ # to iterate substrate hooks and dispatch
13
+ #
14
+ # Why source-without-call:
15
+ # - Walker discovers libs via source-graph closure (per canvas Stage 2)
16
+ # - LITE_LIBS ships the 3 libs to dist/lite/lib/
17
+ # - Walker+LITE_LIBS sync check requires walker to find every LITE_LIBS entry
18
+ # - Sourcing without calling makes the libs walker-discoverable without
19
+ # changing SessionStart behavior — belt-and-braces for the Step 5-6 wire
20
+ #
21
+ # Silent-fail per ADR-050 R7 — never crash SessionStart on lib source failure
22
+
23
+ _ICD_SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
24
+
25
+ # Source each dispatch lib. Bundled path first (dist/lite/lib/), $BASSCLEF_DIR fallback.
26
+ # Static .sh literals so scripts/build-adopter-tree.sh source-graph walker discovers them.
27
+
28
+ # hook-header-parser.sh
29
+ if [ -f "$_ICD_SCRIPT_DIR/../../../lib/hook-header-parser.sh" ]; then
30
+ # shellcheck source=/dev/null
31
+ { source "$_ICD_SCRIPT_DIR/../../../lib/hook-header-parser.sh"; } 2>/dev/null || true
32
+ elif [ -f "${BASSCLEF_DIR:-}/lib/hook-header-parser.sh" ]; then
33
+ # shellcheck source=/dev/null
34
+ { source "${BASSCLEF_DIR:-}/lib/hook-header-parser.sh"; } 2>/dev/null || true
35
+ fi
36
+
37
+ # hook-installer.sh
38
+ if [ -f "$_ICD_SCRIPT_DIR/../../../lib/hook-installer.sh" ]; then
39
+ # shellcheck source=/dev/null
40
+ { source "$_ICD_SCRIPT_DIR/../../../lib/hook-installer.sh"; } 2>/dev/null || true
41
+ elif [ -f "${BASSCLEF_DIR:-}/lib/hook-installer.sh" ]; then
42
+ # shellcheck source=/dev/null
43
+ { source "${BASSCLEF_DIR:-}/lib/hook-installer.sh"; } 2>/dev/null || true
44
+ fi
45
+
46
+ # source-graph-walker.sh
47
+ if [ -f "$_ICD_SCRIPT_DIR/../../../lib/source-graph-walker.sh" ]; then
48
+ # shellcheck source=/dev/null
49
+ { source "$_ICD_SCRIPT_DIR/../../../lib/source-graph-walker.sh"; } 2>/dev/null || true
50
+ elif [ -f "${BASSCLEF_DIR:-}/lib/source-graph-walker.sh" ]; then
51
+ # shellcheck source=/dev/null
52
+ { source "${BASSCLEF_DIR:-}/lib/source-graph-walker.sh"; } 2>/dev/null || true
53
+ fi
54
+
55
+ # Steps 5-6 will extend below with actual install_by_class calls per
56
+ # goal 2026-09-14c step sequencing (docs/iteration-bets/2026-09-14c-*.md).
57
+ # Today the fragment sources-without-calls to satisfy walker discovery.