@thebassclef/lite 1.9.16 → 1.9.19

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 (45) hide show
  1. package/README.md +1 -1
  2. package/dist/index.cjs +1 -1
  3. package/dist/index.d.ts +1 -1
  4. package/dist/index.js +1 -1
  5. package/dist/lite/.claude/agents/builder.md +7 -4
  6. package/dist/lite/.claude/bassclef-orientation.md +22 -0
  7. package/dist/lite/.claude/hooks/artifact-ingestion-gate.sh +11 -3
  8. package/dist/lite/.claude/hooks/assert-verify-steering.sh +1 -19
  9. package/dist/lite/.claude/hooks/plain-english-steering.sh +86 -41
  10. package/dist/lite/.claude/hooks/pre-commit-gate.sh +10 -2
  11. package/dist/lite/.claude/hooks/pre-push-shellcheck.sh +196 -0
  12. package/dist/lite/.claude/hooks/reviewer-dispatch-check.sh +153 -0
  13. package/dist/lite/.claude/hooks/session-reflection.d/83-install-written-paths-rebuild.sh +15 -32
  14. package/dist/lite/.claude/hooks/turn-prose-density-measure.sh +109 -0
  15. package/dist/lite/.claude/hooks/turn-prose-kiss-check.sh +28 -0
  16. package/dist/lite/.claude/rules/branching.md +2 -0
  17. package/dist/lite/.claude/rules/identifier-leak-prevention.md +2 -1
  18. package/dist/lite/.claude/rules/install-written-paths-mediation.md +7 -0
  19. package/dist/lite/.claude/rules/lite-manifest-schema-change-discipline.md +23 -0
  20. package/dist/lite/.claude/rules/reviewer-dispatch.md +95 -0
  21. package/dist/lite/.claude/settings.json +10 -0
  22. package/dist/lite/.claude/skills/build/SKILL.md +81 -6
  23. package/dist/lite/.claude/skills/eisenhower/SKILL.md +26 -0
  24. package/dist/lite/.claude/skills/launch/SKILL.md +45 -2
  25. package/dist/lite/.claude/skills/onboard-repo/SKILL.md +208 -40
  26. package/dist/lite/.claude/skills/onboard-repo/claude-oauth-probe.sh +60 -0
  27. package/dist/lite/.claude/skills/onboard-repo/concise-prompt.sh +73 -0
  28. package/dist/lite/.claude/skills/onboard-repo/write-state-marker.sh +81 -0
  29. package/dist/lite/.claude/skills/pre-mortem/SKILL.md +56 -0
  30. package/dist/lite/.claude/skills/sprint/SKILL.md +24 -3
  31. package/dist/lite/.claude/skills/temperance/SKILL.md +15 -4
  32. package/dist/lite/README.md +2 -0
  33. package/dist/lite/bassclef-version.json +5 -5
  34. package/dist/lite/lib/install-written-paths.sh +250 -3
  35. package/dist/lite/lib/prose-marker.sh +203 -0
  36. package/dist/lite/lib/tier-dependency-audit.sh +52 -25
  37. package/dist/lite/presence/install/bassclef-sync.template.sh +86 -8
  38. package/dist/lite/presence/install/schedule-auto-save.cron.sh +30 -2
  39. package/dist/lite/scripts/generate-lite-manifest.sh +15 -0
  40. package/dist/lite/scripts/launch/local-serve.sh +149 -8
  41. package/dist/lite/standards/bassclef-wiring-manifest.json +12 -0
  42. package/dist/lite/standards/lite-manifest-schema-changes.md +84 -0
  43. package/dist/lite/standards/lite-manifest.json +100 -29
  44. package/dist/lite/standards/prose-marker-format.md +105 -0
  45. package/package.json +1 -1
@@ -0,0 +1,153 @@
1
+ #!/bin/bash
2
+ # tier: lite
3
+ # reviewer-dispatch-check.sh — Stop hook on code-shipping sessions
4
+ #
5
+ # Refuses to let a session end if it shipped source code (>0 src/ file
6
+ # changes per git diff) without a reviewer marker at
7
+ # state/markers/reviewer/<session-id>.md or *.md naming the session.
8
+ #
9
+ # Mode-agnostic: orchestrator-gated dispatches Reviewer agent; sequential
10
+ # mode self-invokes Reviewer responsibilities and writes the marker.
11
+ #
12
+ # Per bassclef#1146 + WU-12 of bet 2026-06-20e.
13
+ # Override: SKIP_REVIEWER_CHECK=1 (logged via trace-helper).
14
+
15
+ set -euo pipefail
16
+
17
+ # ============================================================================
18
+ # Read stdin JSON from Claude Code harness (Stop event payload)
19
+ # ============================================================================
20
+ PAYLOAD=$(cat 2>/dev/null || echo '{}')
21
+
22
+ # ============================================================================
23
+ # Override check (FIRST — before any work)
24
+ # ============================================================================
25
+ if [ "${SKIP_REVIEWER_CHECK:-0}" = "1" ]; then
26
+ TRACE_HELPER="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/trace-helper.sh"
27
+ if [ -f "$TRACE_HELPER" ]; then
28
+ bash "$TRACE_HELPER" override "reviewer-dispatch-check" "SKIP_REVIEWER_CHECK=1" 2>/dev/null || true
29
+ fi
30
+ exit 0
31
+ fi
32
+
33
+ # ============================================================================
34
+ # Repo root + check if we're in a git repo
35
+ # ============================================================================
36
+ REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
37
+
38
+ # If REVIEWER_CHECK_REPO is set, override (for tests)
39
+ if [ -n "${REVIEWER_CHECK_REPO:-}" ]; then
40
+ REPO_ROOT="$REVIEWER_CHECK_REPO"
41
+ fi
42
+
43
+ if ! (cd "$REPO_ROOT" && git rev-parse --git-dir >/dev/null 2>&1); then
44
+ # Not a git repo — skip
45
+ exit 0
46
+ fi
47
+
48
+ # ============================================================================
49
+ # Detect source-file changes in this session
50
+ # Uses git diff against origin/main as proxy for session changes; this is a
51
+ # heuristic — a more precise version would track session-start ref.
52
+ # ============================================================================
53
+ cd "$REPO_ROOT"
54
+
55
+ # Define source-file path matchers — files that count as "shipped code"
56
+ SOURCE_MATCHERS=(
57
+ 'src/'
58
+ 'apps/'
59
+ 'packages/'
60
+ 'lib/'
61
+ 'app/'
62
+ )
63
+
64
+ # Count source files changed (uncommitted + committed-since-origin)
65
+ SHIPPED_SOURCE_COUNT=0
66
+
67
+ # Uncommitted changes
68
+ for matcher in "${SOURCE_MATCHERS[@]}"; do
69
+ count=$(git diff --name-only -- "$matcher" 2>/dev/null | wc -l | tr -d ' ')
70
+ SHIPPED_SOURCE_COUNT=$((SHIPPED_SOURCE_COUNT + count))
71
+ done
72
+
73
+ # Committed-since-origin/main
74
+ if git rev-parse origin/main >/dev/null 2>&1; then
75
+ for matcher in "${SOURCE_MATCHERS[@]}"; do
76
+ count=$(git diff --name-only origin/main..HEAD -- "$matcher" 2>/dev/null | wc -l | tr -d ' ')
77
+ SHIPPED_SOURCE_COUNT=$((SHIPPED_SOURCE_COUNT + count))
78
+ done
79
+ fi
80
+
81
+ # No source files changed — session is non-code (docs, config, etc.); pass
82
+ if [ "$SHIPPED_SOURCE_COUNT" -eq 0 ]; then
83
+ exit 0
84
+ fi
85
+
86
+ # ============================================================================
87
+ # Marker check: state/markers/reviewer/*.md
88
+ # ============================================================================
89
+ MARKER_DIR="$REPO_ROOT/state/markers/reviewer"
90
+
91
+ if [ -d "$MARKER_DIR" ] && find "$MARKER_DIR" -maxdepth 1 -name "*.md" 2>/dev/null | grep -q .; then
92
+ # At least one reviewer marker exists — pass
93
+ exit 0
94
+ fi
95
+
96
+ # ============================================================================
97
+ # Block: source shipped + no reviewer marker
98
+ # ============================================================================
99
+ cat >&2 <<EOF
100
+ 🛑 reviewer-dispatch-check — BLOCK (bassclef#1146)
101
+
102
+ This session shipped source code (${SHIPPED_SOURCE_COUNT} source files
103
+ changed across src/ apps/ packages/ lib/ app/) but no reviewer marker
104
+ exists at state/markers/reviewer/.
105
+
106
+ Reviewer responsibilities (per ~/.claude/agents/reviewer.md):
107
+ - Verify spec acceptance criteria met
108
+ - Verify tests present + green
109
+ - Check for TDD test-after pattern (Kent Beck)
110
+ - Verify ADR compliance for architectural decisions
111
+ - Verify Designer sign-off for UX changes
112
+ - Verify /architect-review invoked for Construction work
113
+
114
+ Resolve via one of:
115
+
116
+ 1. Orchestrator-gated mode — dispatch Reviewer agent + capture marker:
117
+ /reviewer-pass
118
+ (or invoke via your orchestrator's handoff to Reviewer)
119
+
120
+ 2. Sequential mode — self-invoke Reviewer responsibilities + write marker:
121
+ mkdir -p $MARKER_DIR
122
+ cat > $MARKER_DIR/<session-id>.md <<MARKER
123
+ # Reviewer pass — <session-id>
124
+
125
+ mode: sequential
126
+ reviewed_at: $(date -u +%Y-%m-%dT%H:%M:%SZ)
127
+ source_files_changed: $SHIPPED_SOURCE_COUNT
128
+
129
+ ## Checks
130
+ - spec acceptance criteria: PASS | FAIL | N/A
131
+ - tests present + green: PASS | FAIL
132
+ - test-after pattern check: NONE FOUND | FOUND (list)
133
+ - ADR compliance: PASS | N/A
134
+ - Designer sign-off: PRESENT | N/A
135
+ - architect-review: INVOKED | N/A
136
+
137
+ ## Findings
138
+ - <severity>: <description> # BLOCK / WARN / NOTE
139
+
140
+ acknowledged: true
141
+ MARKER
142
+
143
+ 3. Defer to next session — write marker NOW with "deferred to next session"
144
+ note + commit; resolve at next session start per deferred-actions protocol.
145
+
146
+ Override (logged): SKIP_REVIEWER_CHECK=1 <command>
147
+
148
+ When to use override:
149
+ - Documentation-only session that accidentally touched a src/ comment
150
+ - Emergency rescue when hook itself misclassifies
151
+ EOF
152
+
153
+ exit 2
@@ -66,43 +66,26 @@ _iwp_fragment_main() {
66
66
  return 0
67
67
  fi
68
68
 
69
- # Source lib — subshell so caller scope stays clean
69
+ # Source lib — subshell so caller scope stays clean.
70
+ # Per bassclef-upstream#2200 — bulk-rebuild verb replaces the prior
71
+ # 451×700ms serial register loop that timed out before completion.
72
+ # New verb builds one jq write + one ajv validate at the end.
70
73
  (
71
74
  # shellcheck source=/dev/null
72
75
  . "$lib" 2>/dev/null || exit 0
73
76
 
74
- if ! declare -F install_written_paths_register >/dev/null 2>&1; then
75
- _iwp_fragment_log "skip reason=lib-missing-verb"
76
- exit 0
77
- fi
78
-
79
- # Reset manifest to empty, then walk lite-manifest entries
80
- rm -f "$write_manifest" 2>/dev/null || true
81
- install_written_paths_rebuild 2>/dev/null || true
82
-
83
- local registered=0
84
- local skipped=0
85
-
86
- # Each lite-manifest entry has .path field — register when file exists on disk
87
- while IFS= read -r path; do
88
- [ -z "$path" ] && continue
89
- local full
90
- case "$path" in
91
- /*) full="$path" ;;
92
- *) full="$project_root/$path" ;;
93
- esac
94
- if [ -f "$full" ]; then
95
- if install_written_paths_register "$path" "bassclef-sync-template" 2>/dev/null; then
96
- registered=$((registered + 1))
97
- else
98
- skipped=$((skipped + 1))
99
- fi
100
- else
101
- skipped=$((skipped + 1))
77
+ if declare -F install_written_paths_rebuild_from_lite_manifest >/dev/null 2>&1; then
78
+ # Preserve verb's stderr (ajv-fail warnings etc.) by piping to trace
79
+ # instead of swallowing with 2>/dev/null (architect-review F3).
80
+ local verb_stderr
81
+ verb_stderr=$(install_written_paths_rebuild_from_lite_manifest "$lite_manifest" 2>&1 >/dev/null) || true
82
+ if [ -n "$verb_stderr" ]; then
83
+ _iwp_fragment_log "bulk-rebuild stderr=$verb_stderr"
102
84
  fi
103
- done < <(jq -r '.entries[]?.path // empty' "$lite_manifest" 2>/dev/null)
104
-
105
- _iwp_fragment_log "rebuild complete registered=$registered skipped=$skipped"
85
+ _iwp_fragment_log "bulk-rebuild dispatched lite=$lite_manifest"
86
+ else
87
+ _iwp_fragment_log "skip reason=lib-missing-bulk-rebuild-verb"
88
+ fi
106
89
  ) || true
107
90
 
108
91
  return 0
@@ -0,0 +1,109 @@
1
+ #!/bin/bash
2
+ # tier: lite
3
+ # install-class: dual
4
+ # Turn-prose density measure — Stop hook that reads the last assistant message
5
+ # from the transcript, counts non-standard hyphenated compounds, and writes
6
+ # the number to a marker file at state/markers/turn-prose-density/last-turn.json
7
+ # via lib/prose-marker.sh per standards/prose-marker-format.md.
8
+ #
9
+ # Density = count of [a-z]{2,}-[a-z]{2,}(?:-[a-z]{2,})? matches MINUS the
10
+ # 25-entry standard-tech allowlist. Proxy for jargon load distinct from
11
+ # grade-measure's existing hyphen_words count (which includes standard tech).
12
+ #
13
+ # The pre-turn plain-english-steering.sh reads the marker on next turn
14
+ # (extended at Step 2d) and injects the density number into the steering
15
+ # block alongside grade + appositive misses.
16
+ #
17
+ # Sibling scorers:
18
+ # - turn-prose-grade-measure.sh — grade metric
19
+ # - turn-prose-kiss-check.sh — appositive miss count (Step 2c extension)
20
+ #
21
+ # Input (stdin): JSON with transcript_path + session_id
22
+ # Output: writes state/markers/turn-prose-density/last-turn.json
23
+ # Exit: 0 always (measurement only, no gate)
24
+ #
25
+ # Override: SKIP_TURN_PROSE_DENSITY=1
26
+
27
+ set +e
28
+
29
+ # === Override path ===
30
+ if [ "${SKIP_TURN_PROSE_DENSITY:-0}" = "1" ]; then
31
+ exit 0
32
+ fi
33
+
34
+ # === Parse stdin JSON ===
35
+ STDIN_JSON=$(cat 2>/dev/null || echo '{}')
36
+ if ! command -v jq >/dev/null 2>&1; then
37
+ exit 0
38
+ fi
39
+ TRANSCRIPT_PATH=$(echo "$STDIN_JSON" | jq -r '.transcript_path // ""' 2>/dev/null)
40
+
41
+ [ -z "$TRANSCRIPT_PATH" ] && exit 0
42
+ [ ! -f "$TRANSCRIPT_PATH" ] && exit 0
43
+
44
+ # === Resolve lib path (install-class: dual) ===
45
+ # Project install — lib relative to this hook. Operator install — lib under $HOME.
46
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
47
+ LIB_PATH=""
48
+ for candidate in \
49
+ "${SCRIPT_DIR}/../../lib/prose-marker.sh" \
50
+ "${HOME:-/}/lib/prose-marker.sh" \
51
+ "${CLAUDE_PROJECT_DIR:-}/lib/prose-marker.sh"; do
52
+ if [ -f "$candidate" ]; then
53
+ LIB_PATH="$candidate"
54
+ break
55
+ fi
56
+ done
57
+
58
+ [ -z "$LIB_PATH" ] && exit 0
59
+ # shellcheck disable=SC1090
60
+ source "$LIB_PATH" 2>/dev/null || exit 0
61
+
62
+ # === Extract last assistant text ===
63
+ LAST_ASSISTANT_LINE=$(grep '"type":"assistant"' "$TRANSCRIPT_PATH" 2>/dev/null | tail -1)
64
+ [ -z "$LAST_ASSISTANT_LINE" ] && exit 0
65
+
66
+ MESSAGE_TEXT=$(echo "$LAST_ASSISTANT_LINE" \
67
+ | jq -r '.message.content[]? | select(.type == "text") | .text' 2>/dev/null)
68
+ [ -z "$MESSAGE_TEXT" ] && exit 0
69
+
70
+ # === Strip code blocks + inline backticks + URLs (prose only) ===
71
+ SCRUBBED=$(echo "$MESSAGE_TEXT" | awk '
72
+ BEGIN { in_code = 0 }
73
+ /^```/ { in_code = !in_code; next }
74
+ in_code { next }
75
+ { print }
76
+ ' | sed -E 's/`[^`]*`//g; s|https?://[^ )]+||g')
77
+
78
+ # Short message after strip → density=0
79
+ STRIPPED_LEN=${#SCRUBBED}
80
+ if [ "$STRIPPED_LEN" -lt 50 ]; then
81
+ write_prose_marker "turn-prose-density" "0" "short message under 50 chars"
82
+ exit 0
83
+ fi
84
+
85
+ # === Compute density via python ===
86
+ # Standard-tech allowlist excluded. Pattern per standards/prose-marker-format.md.
87
+ DENSITY=$(printf '%s' "$SCRUBBED" | python3 -c '
88
+ import sys, re
89
+
90
+ STANDARD_TECH = {
91
+ "pre-commit", "real-time", "data-driven", "end-to-end", "fire-and-forget",
92
+ "run-time", "compile-time", "read-only", "write-only", "fail-soft",
93
+ "fail-fast", "post-commit", "pre-push", "post-merge", "op-ed",
94
+ "self-test", "self-check", "re-read", "re-run", "re-fire",
95
+ "op-cost", "copy-paste", "cut-off", "set-up", "built-in",
96
+ }
97
+
98
+ text = sys.stdin.read().lower()
99
+ pattern = re.compile(r"\b[a-z]{2,}-[a-z]{2,}(?:-[a-z]{2,})?\b")
100
+ matches = pattern.findall(text)
101
+ density = sum(1 for m in matches if m not in STANDARD_TECH)
102
+ print(density)
103
+ ' 2>/dev/null)
104
+
105
+ [ -z "$DENSITY" ] && DENSITY=0
106
+
107
+ # === Write density marker via lib ===
108
+ write_prose_marker "turn-prose-density" "$DENSITY" 2>/dev/null
109
+ exit 0
@@ -83,6 +83,20 @@ for _candidate in \
83
83
  done
84
84
  unset _candidate
85
85
 
86
+ # === Source lib/prose-marker.sh (deep module per Longrun 2 Step 2b #2197) ===
87
+ # Provides write_prose_marker for appositive-miss count persistence.
88
+ # Silent-fail — no lib = no marker write; existing stderr display path unchanged.
89
+ for _candidate in \
90
+ "${SCRIPT_DIR}/../../lib/prose-marker.sh" \
91
+ "${HOME_OVERRIDE:-${HOME:-/}}/lib/prose-marker.sh"; do
92
+ if [ -f "$_candidate" ]; then
93
+ # shellcheck disable=SC1090
94
+ source "$_candidate"
95
+ break
96
+ fi
97
+ done
98
+ unset _candidate
99
+
86
100
  # === Parse stdin JSON ===
87
101
  STDIN_JSON=$(cat 2>/dev/null || echo '{}')
88
102
  TRANSCRIPT_PATH=$(echo "$STDIN_JSON" | jq -r '.transcript_path // ""' 2>/dev/null)
@@ -417,8 +431,15 @@ for pattern, label in patterns:
417
431
 
418
432
  for f in flagged[:5]: # cap at 5 findings per turn to avoid noise
419
433
  print(f)
434
+ # Emit total count on final line as sentinel — bash strips before display.
435
+ # Per Longrun 2 Step 2c (#2197) — scorer-stack appositive marker.
436
+ print(f"__APPOSITIVE_COUNT__={len(flagged)}")
420
437
  ' 2>/dev/null)
421
438
 
439
+ # Extract the count sentinel; strip it from the display output.
440
+ APPOSITIVE_COUNT=$(echo "$APPOSITIVE_FINDINGS" | grep '^__APPOSITIVE_COUNT__=' | tail -1 | sed 's/^__APPOSITIVE_COUNT__=//')
441
+ APPOSITIVE_FINDINGS=$(echo "$APPOSITIVE_FINDINGS" | grep -v '^__APPOSITIVE_COUNT__=')
442
+
422
443
  if [ -n "$APPOSITIVE_FINDINGS" ]; then
423
444
  cat >&2 <<EOF
424
445
  [turn-prose-kiss-check: ADVISORY — appositive discipline (bassclef-upstream#1313)]
@@ -434,6 +455,13 @@ Override one-time: SKIP_APPOSITIVE_CHECK=1.
434
455
  V1 advisory; V2 (deferred) BLOCKs after calibration.
435
456
  EOF
436
457
  fi
458
+
459
+ # === Write appositive-miss marker via lib/prose-marker.sh (Longrun 2 Step 2c) ===
460
+ # Count is total matches (not capped at 5 — that cap is display-only).
461
+ # Silent-fail — missing lib or write error does not affect existing path.
462
+ if declare -f write_prose_marker >/dev/null 2>&1 && [ -n "$APPOSITIVE_COUNT" ]; then
463
+ write_prose_marker "turn-prose-appositive" "$APPOSITIVE_COUNT" 2>/dev/null
464
+ fi
437
465
  fi
438
466
 
439
467
  # === Emit findings + exit per mode ===
@@ -13,6 +13,8 @@ Branch naming:
13
13
 
14
14
  Every branch ties to a GitHub Issue. No branch without an issue.
15
15
 
16
+ **Exception — `/launch --local`.** Adopter prototype branches created by `/launch --local` are exempt from the issue-per-branch rule. Local prototype mode exists for adopters who do not yet have a GitHub repo or who iterate ahead of filing issues. Per bassclef-upstream#2175 Batch A (F2) + bassclef-cli#328 Finding 2.
17
+
16
18
  Flow: issue → branch from main → work → PR → CI passes → squash merge → delete branch
17
19
 
18
20
  Rules:
@@ -30,8 +30,9 @@ No commit lands with these patterns in message OR staged content:
30
30
 
31
31
  - **Hostname shapes**: `[A-Za-z][A-Za-z0-9]*-MacBook-(Air|Pro)`, `DESKTOP-[A-Z0-9]{4,}`, `*-server-*`, `*-desktop-*`
32
32
  - **Absolute paths**: `/Users/<name>`, `/home/<name>`
33
+ - **GitHub no-reply derived slug**: `operator-[0-9]+\+[a-zA-Z0-9][a-zA-Z0-9-]*` — the shape `/personas` historically derived from a GitHub no-reply email local part (`<id>+<handle>`), leaking account ID plus handle into committed persona + use-case + jobs docs. Per bassclef-upstream#2146. Scope-safe — the pattern targets the derived slug only; the raw email format `<id>+<handle>@users.noreply.github.com` stays allowed as a git author (Check 3 pins that in Test 22) because GitHub recommends no-reply as the privacy format for commit identity.
33
34
 
34
- Extension mechanism — future pattern classes added to the hook's `IDENTIFIER_PATTERNS` regex + a corresponding Tier 0 test.
35
+ Extension mechanism — future pattern classes added to `standards/identifier-leak-patterns.txt` + a corresponding Tier 0 test. The hook reads the pattern file at run time; adding a line there extends the scrub without a hook edit.
35
36
 
36
37
  ## Anti-patterns
37
38
 
@@ -13,6 +13,7 @@ The lib + manifest ship per bassclef-upstream#2036 Finding #8 (Kunal cold-adopte
13
13
  Any discipline hook that currently fires on file content without discriminating install-written from author-edited. Candidate hooks:
14
14
 
15
15
  - `.claude/hooks/pre-commit-gate.sh` — lead-lens 3-marker gate section (consumer wired per this cure's V1 PR)
16
+ - `.claude/hooks/pre-push-shellcheck.sh` — adopter 2; retrofitted per bassclef-upstream#2253 (cold-adopter first-push BLOCKed on 72 install-written findings)
16
17
  - `.claude/hooks/pre-commit-identifier-leak-scrub.sh` — identifier-leak sister per Kunal #1 (future adopter per R2 risk ledger)
17
18
  - Any new discipline hook authored under the loop discipline (`.claude/rules/loop-discipline.md`) that assumes author-edit
18
19
 
@@ -67,6 +68,12 @@ INSTEAD of overriding routinely: trust the lib. Overrides are for one-shot debug
67
68
  - `presence/install/bassclef-sync.template.sh` — registers each path on sync
68
69
  - `.claude/hooks/session-reflection.d/83-install-written-paths-rebuild.sh` — regenerates manifest when missing at session-start
69
70
 
71
+ ## Adopter 2 — pre-push-shellcheck retrofit (bassclef-upstream#2253)
72
+
73
+ Second mediation consumer landed under v1.11.1 hotfix. Peer bassclef-cli-06 cold-adopter smoke on `giveisusfree` profile caught v1.11.0's `pre-push-shellcheck.sh` (shipped #2108) BLOCKing first push after `bassclef init` on 72 shellcheck findings in bassclef-shipped `.sh` files — Linus adopter contract break.
74
+
75
+ Cure retrofit — `pre-push-shellcheck.sh` now sources `lib/install-written-paths.sh` with fail-soft and filters `EXISTING_FILES` through `is_install_written_path` before shellcheck fires. Adopter edits to install-written files mismatch the recorded content_hash and still get scanned (lib's existing contract). The sister test `.claude/hooks/tests/pre-push-shellcheck.test.sh` added one real-lib integration test (Test 19) per Feathers characterization — the integration test caught a `set -u` leak the stub tests missed. Cure guards sourced block with `set +u` scope.
76
+
70
77
  ## Deferred to follow-on
71
78
 
72
79
  - `bassclef init` npm-side registration (lands in bassclef-cli; sources the lib via package symlink)
@@ -36,6 +36,29 @@ When a PR changes the manifest schema OR output shape:
36
36
  3. **Downstream cure named** — the entry names what adopters need to do. If nothing (backward-compatible add), say so explicitly. If code change (like the v0.36.0 `upstream_commit` removal), name the pattern.
37
37
  4. **Release script pre-flight** — before every `/release`, the script reads the ledger and confirms an entry exists for the outgoing `manifest_version`. Missing entry BLOCKs the cascade.
38
38
 
39
+ ## Ledger-edit-then-regen order (bassclef-upstream#2110)
40
+
41
+ The ledger file at `standards/lite-manifest-schema-changes.md` is ITSELF a `tier: lite` artifact. Its content_hash lives inside the manifest. So the regen must capture the FINAL ledger state. Order matters:
42
+
43
+ 1. **Edit ledger first.** Write the entry explaining the schema change.
44
+ 2. **Regen second.** Run `scripts/generate-lite-manifest.sh`.
45
+
46
+ Natural authoring instinct is "regen first (see the hashes), then explain." That order ships a stale ledger hash in the manifest. CI drift check fails. A second regen commit is then needed.
47
+
48
+ **Preferred cure — use the wrapper.** `scripts/update-lite-manifest.sh` enforces the order:
49
+
50
+ ```bash
51
+ # Append a pre-written entry
52
+ scripts/update-lite-manifest.sh --entry-file path/to/entry.md
53
+
54
+ # Open $EDITOR on the ledger
55
+ scripts/update-lite-manifest.sh --edit
56
+ ```
57
+
58
+ Both modes hash the ledger before and after. The wrapper refuses to regen when the ledger is unchanged. Then it dispatches `scripts/generate-lite-manifest.sh` + the renderer when present.
59
+
60
+ Per `.claude/rules/bootstrap-pair-discipline.md` — the wrapper ships with Tier 0 tests at `scripts/tests/update-lite-manifest.test.sh`.
61
+
39
62
  ## Retirements
40
63
 
41
64
  Retirement-class changes (content-remove: a file previously shipped in the lite manifest gets deleted intentionally) ship with the same discipline shape as additions. Three paired artifacts, same PR:
@@ -0,0 +1,95 @@
1
+ ---
2
+ tier: lite
3
+ description: Any session that ships source code (files under src/, apps/, packages/, lib/, app/) MUST invoke Reviewer responsibilities before the session ends.
4
+ ---
5
+
6
+ # Reviewer Dispatch
7
+
8
+ Any session that ships source code (files under `src/`, `apps/`, `packages/`, `lib/`, `app/`) MUST invoke Reviewer responsibilities before the session ends. Mode-agnostic — orchestrator-gated mode dispatches the Reviewer agent; sequential mode self-invokes Reviewer responsibilities (read against spec, check tests, validate ADR compliance, flag TDD test-after patterns per Kent Beck).
9
+
10
+ The discipline lives at the rule layer (this file) plus the mechanical layer (`.claude/hooks/reviewer-dispatch-check.sh` — Stop hook). Both required for adopter code quality.
11
+
12
+ ## When this rule fires
13
+
14
+ At session end (Stop event), the hook:
15
+
16
+ 1. Counts source files changed since session-start (heuristic: `git diff` against `origin/main`; uncommitted + committed changes both count)
17
+ 2. Path matchers for "source": `src/`, `apps/`, `packages/`, `lib/`, `app/`
18
+ 3. When source count > 0, the hook checks for any marker at `state/markers/reviewer/*.md`
19
+ 4. When no marker exists, the hook BLOCKs with reviewer-checklist remediation
20
+
21
+ ## Reviewer marker contract
22
+
23
+ The marker captures the Reviewer pass per the agent definition (`~/.claude/agents/reviewer.md`):
24
+
25
+ ```markdown
26
+ # Reviewer pass — <session-id>
27
+
28
+ mode: sequential | orchestrator-gated
29
+ reviewed_at: <ISO-8601>
30
+ source_files_changed: <count>
31
+ wu_id: <e.g., bet-2026-06-25k WU-3> # bet 25k WU-5 extension
32
+ iteration_count: <N> # bet 25k WU-5 extension
33
+ lens_used: [<luminary-slug>, ...] # bet 25k WU-5 extension
34
+
35
+ ## Checks
36
+ - spec acceptance criteria: PASS | FAIL | N/A
37
+ - tests present + green: PASS | FAIL
38
+ - test-after pattern check: NONE FOUND | FOUND (list)
39
+ - ADR compliance: PASS | N/A
40
+ - Designer sign-off: PRESENT | N/A
41
+ - architect-review: INVOKED | N/A
42
+
43
+ ## Findings
44
+ - <severity>: <description> # BLOCK / WARN / NOTE
45
+
46
+ acknowledged: true
47
+ ```
48
+
49
+ ### Field extensions per bassclef-upstream#366 (bet 25k WU-5)
50
+
51
+ Three fields extend the prior contract to make the /loop discipline auditable per step:
52
+
53
+ - **`wu_id`** — goal identifier + WU number (e.g., `bet-2026-06-25k WU-3`). Lets future audits grep markers by WU. Required when the marker is written under /longrun dispatch; optional for ad-hoc reviews.
54
+ - **`iteration_count`** — number of /loop iterations the step ran before landing GREEN. Iteration 1 GREEN is the cleanest path; counts above 1 record rework cycles (RED → fix → GREEN). Required under /longrun dispatch.
55
+ - **`lens_used`** — YAML list of luminary slugs that drove the review. Mirrors the goal doc's `authoring_luminaries` for the relevant WU. Required under /longrun dispatch.
56
+
57
+ The three fields together let future operators answer questions like "which WUs in bet 25k ran more than one /loop iteration" or "which luminary lens caught the most rework" by greppable markers, not by chronicle archaeology. The mechanical layer (greppable fields) compounds across every goal; the bar (`## /temperance + /luminary + /loop discipline` section in the PR body) gives the immediate operator-visible read.
58
+
59
+ Forward-only enforcement. Markers written before WU-5 stay as-is; markers written from WU-5 onwards carry the three new fields under /longrun dispatch.
60
+
61
+ ## Mode behavior
62
+
63
+ **Orchestrator-gated mode** — orchestrator dispatches Reviewer agent at code-shipping handoffs. Reviewer agent reads against spec, runs checks, writes the marker per the contract above, returns PASS/FAIL/WARN findings to orchestrator.
64
+
65
+ **Sequential mode** — agent self-invokes Reviewer responsibilities. Read the Reviewer agent definition. Apply checks against the session's source diff. Write the marker. The self-invocation is honor-system at the methodology layer; the marker is the mechanical evidence the hook reads.
66
+
67
+ ## Override path
68
+
69
+ `SKIP_REVIEWER_CHECK=1 <command>` — logged via trace-helper. Use rarely:
70
+
71
+ - Documentation-only session that accidentally touched a comment in src/ (operator confirms the source touch is non-behavioral)
72
+ - Emergency rescue when the hook itself misclassifies (file substrate-defect)
73
+ - One-shot migration script that ships hundreds of source files (operator has reviewed externally)
74
+ - Bulk dependency-bump where the package-manager touched lockfile entries only
75
+
76
+ INSTEAD of overriding for routine work: write the marker. The Reviewer-self-invocation cost is small (~5 minutes); the audit trail compounds across every adopter session.
77
+
78
+ ## What the rule does NOT cover
79
+
80
+ - Code review process content (covered in `~/.claude/agents/reviewer.md`)
81
+ - TDD test-list discipline (covered in `.claude/rules/test-list-discipline.md`)
82
+ - Sufficiency rubric for tests (covered in `.claude/rules/test-sufficiency.md`)
83
+ - ADR discipline (covered in `.claude/rules/adr-discipline.md`)
84
+ - Architect review timing (covered in `.claude/skills/architect-review/SKILL.md`)
85
+
86
+ This rule is the gate. Sister rules + skills carry the content.
87
+
88
+ ## Composition with other rules
89
+
90
+ - `.claude/rules/testing-tier-config.md` — Tier 0 strict-TDD on hook + tests (this hook + its test file land Tier 0)
91
+ - `.claude/rules/blocked-items.md` — BLOCK protocol the hook fires
92
+ - `.claude/rules/test-sufficiency.md` — what Reviewer checks for under "tests present + green"
93
+ - `.claude/rules/test-list-discipline.md` — what Reviewer checks for under "test-after pattern check" (Beck's test-list-as-planning-artifact)
94
+ - `.claude/rules/adr-discipline.md` — what Reviewer checks for under "ADR compliance"
95
+ - `~/.claude/agents/reviewer.md` — the full Reviewer responsibilities definition
@@ -52,6 +52,11 @@
52
52
  "type": "command",
53
53
  "command": "$CLAUDE_PROJECT_DIR/.claude/hooks/git-stash-u-guard.sh",
54
54
  "timeout": 5
55
+ },
56
+ {
57
+ "type": "command",
58
+ "command": "$CLAUDE_PROJECT_DIR/.claude/hooks/pre-push-shellcheck.sh",
59
+ "timeout": 60
55
60
  }
56
61
  ]
57
62
  },
@@ -167,6 +172,11 @@
167
172
  "command": "$CLAUDE_PROJECT_DIR/.claude/hooks/turn-prose-grade-measure.sh",
168
173
  "timeout": 10
169
174
  },
175
+ {
176
+ "type": "command",
177
+ "command": "$CLAUDE_PROJECT_DIR/.claude/hooks/turn-prose-density-measure.sh",
178
+ "timeout": 10
179
+ },
170
180
  {
171
181
  "type": "command",
172
182
  "command": "$CLAUDE_PROJECT_DIR/.claude/hooks/longrun-prep-compounding-sequence-check.sh",