@thebassclef/lite 1.1.0 → 1.2.0-alpha.1

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 (135) hide show
  1. package/dist/cli.cjs +258 -63
  2. package/dist/cli.js +258 -63
  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/bassclef-configs.jsonc +56 -0
  7. package/dist/lite/.claude/bassclef-orientation.md +120 -0
  8. package/dist/lite/.claude/hooks/adr-discipline-check.sh +132 -0
  9. package/dist/lite/.claude/hooks/atomic-pr-check.sh +169 -0
  10. package/dist/lite/.claude/hooks/auto-save-idle.sh +51 -0
  11. package/dist/lite/.claude/hooks/bassclef-sync.sh +51 -13
  12. package/dist/lite/.claude/hooks/bet-doc-gate.sh +283 -0
  13. package/dist/lite/.claude/hooks/bug-diagnosis.sh +64 -0
  14. package/dist/lite/.claude/hooks/destructive-command-guard.sh +136 -0
  15. package/dist/lite/.claude/hooks/file-rename-discipline-check.sh +147 -0
  16. package/dist/lite/.claude/hooks/hook-classifier-canary.sh +158 -0
  17. package/dist/lite/.claude/hooks/kiss-default-check.sh +129 -0
  18. package/dist/lite/.claude/hooks/multi-tenancy-check.sh +83 -0
  19. package/dist/lite/.claude/hooks/oo-ad-entry-point-check.sh +216 -0
  20. package/dist/lite/.claude/hooks/operator-private-path-check.sh +203 -0
  21. package/dist/lite/.claude/hooks/pattern-annotation-validate.sh +142 -0
  22. package/dist/lite/.claude/hooks/plain-english-steering.sh +15 -1
  23. package/dist/lite/.claude/hooks/post-write-trace.sh +66 -0
  24. package/dist/lite/.claude/hooks/pr-body-scrub-check.sh +446 -0
  25. package/dist/lite/.claude/hooks/pre-commit-identifier-leak-scrub.sh +137 -0
  26. package/dist/lite/.claude/hooks/pre-gh-pr-body-scrub.sh +192 -0
  27. package/dist/lite/.claude/hooks/pre-gh-pr-title-scrub.sh +172 -0
  28. package/dist/lite/.claude/hooks/role-entry-gate.sh +115 -0
  29. package/dist/lite/.claude/hooks/save-state.sh +268 -0
  30. package/dist/lite/.claude/hooks/session-reflection.d/08-settings-drift.sh +8 -1
  31. package/dist/lite/.claude/hooks/session-reflection.d/10-abrupt-stop-recovery.sh +52 -0
  32. package/dist/lite/.claude/hooks/session-reflection.d/55-orientation-gate.sh +40 -4
  33. package/dist/lite/.claude/hooks/session-reflection.d/80-hook-heartbeat-check.sh +12 -5
  34. package/dist/lite/.claude/hooks/session-reflection.d/81-hook-manifest-staleness.sh +18 -2
  35. package/dist/lite/.claude/hooks/session-reflection.d/91-npm-version-drift.sh +54 -0
  36. package/dist/lite/.claude/hooks/session-reflection.d/tests/10-abrupt-stop-recovery.test.sh +95 -0
  37. package/dist/lite/.claude/hooks/session-reflection.sh +62 -15
  38. package/dist/lite/.claude/hooks/tool-failure-diagnosis.sh +50 -0
  39. package/dist/lite/.claude/luminaries/andrej-karpathy.md +165 -0
  40. package/dist/lite/.claude/luminaries/dave-gray.md +155 -0
  41. package/dist/lite/.claude/luminaries/gary-klein.md +166 -0
  42. package/dist/lite/.claude/luminaries/kaoru-ishikawa.md +162 -0
  43. package/dist/lite/.claude/luminaries/lean-product-canvas.md +33 -0
  44. package/dist/lite/.claude/luminaries/luke-wroblewski.md +224 -0
  45. package/dist/lite/.claude/luminaries/ryan-singer.md +113 -0
  46. package/dist/lite/.claude/luminaries/steve-krug.md +168 -0
  47. package/dist/lite/.claude/luminaries/tony-ulwick.md +134 -0
  48. package/dist/lite/.claude/rules/arc-level-orientation-before-leaf.md +60 -0
  49. package/dist/lite/.claude/rules/architect-review-discipline.md +71 -0
  50. package/dist/lite/.claude/rules/auto-fix-criteria.md +126 -0
  51. package/dist/lite/.claude/rules/bassclef-hook-drift-blocker.md +144 -0
  52. package/dist/lite/.claude/rules/bassclef-models-discovery.md +107 -0
  53. package/dist/lite/.claude/rules/bassclef-workflow-parity.md +104 -0
  54. package/dist/lite/.claude/rules/cost-governance.md +154 -0
  55. package/dist/lite/.claude/rules/file-rename-discipline.md +95 -0
  56. package/dist/lite/.claude/rules/mechanism-fidelity.md +88 -0
  57. package/dist/lite/.claude/rules/prototype-production-coupling.md +125 -0
  58. package/dist/lite/.claude/rules/quick-fix-criteria.md +90 -0
  59. package/dist/lite/.claude/rules/session-artifacts.md +30 -0
  60. package/dist/lite/.claude/rules/sibling-smoke-after-substrate-change.md +107 -0
  61. package/dist/lite/.claude/rules/substrate-as-system.md +67 -0
  62. package/dist/lite/.claude/rules/usability.md +22 -0
  63. package/dist/lite/.claude/settings.json +20 -0
  64. package/dist/lite/.claude/skills/agent-research-spawn/SKILL.md +100 -0
  65. package/dist/lite/.claude/skills/architect-review/SKILL.md +201 -0
  66. package/dist/lite/.claude/skills/auto-fix/SKILL.md +297 -0
  67. package/dist/lite/.claude/skills/autonomous/SKILL.md +300 -0
  68. package/dist/lite/.claude/skills/bind-subdomain/SKILL.md +232 -0
  69. package/dist/lite/.claude/skills/canvas/SKILL.md +41 -0
  70. package/dist/lite/.claude/skills/deploy-prod/SKILL.md +106 -0
  71. package/dist/lite/.claude/skills/docs-sync/SKILL.md +188 -0
  72. package/dist/lite/.claude/skills/eisenhower/SKILL.md +273 -0
  73. package/dist/lite/.claude/skills/empathy-map/SKILL.md +168 -0
  74. package/dist/lite/.claude/skills/frontend-design/SKILL.md +53 -0
  75. package/dist/lite/.claude/skills/interview-me/SKILL.md +171 -0
  76. package/dist/lite/.claude/skills/journal-export/SKILL.md +293 -0
  77. package/dist/lite/.claude/skills/jtbd-tasks/SKILL.md +203 -0
  78. package/dist/lite/.claude/skills/objectory-decompose/SKILL.md +256 -0
  79. package/dist/lite/.claude/skills/pick-luminaries/SKILL.md +100 -0
  80. package/dist/lite/.claude/skills/pre-mortem/SKILL.md +180 -0
  81. package/dist/lite/.claude/skills/prototype-gallery/SKILL.md +264 -0
  82. package/dist/lite/.claude/skills/provision-deploy-host/SKILL.md +257 -0
  83. package/dist/lite/.claude/skills/quick-fix/SKILL.md +273 -0
  84. package/dist/lite/.claude/skills/release/SKILL.md +311 -0
  85. package/dist/lite/.claude/skills/release-notes/SKILL.md +202 -0
  86. package/dist/lite/.claude/skills/rfc/SKILL.md +222 -0
  87. package/dist/lite/.claude/skills/riff-prototypes/SKILL.md +637 -0
  88. package/dist/lite/.claude/skills/secrets-bootstrap/SKILL.md +209 -0
  89. package/dist/lite/.claude/skills/skill/SKILL.md +304 -0
  90. package/dist/lite/.claude/skills/smoke-test/SKILL.md +100 -0
  91. package/dist/lite/.claude/skills/state/SKILL.md +204 -0
  92. package/dist/lite/.claude/skills/substrate-check/SKILL.md +218 -0
  93. package/dist/lite/.claude/skills/synthetic-user/SKILL.md +381 -0
  94. package/dist/lite/.claude/skills/task-scenarios/SKILL.md +105 -0
  95. package/dist/lite/.claude/skills/tier-dependency-audit/SKILL.md +139 -0
  96. package/dist/lite/.claude/skills/ux-migration/SKILL.md +424 -0
  97. package/dist/lite/.claude/skills/value-prop-canvas/SKILL.md +297 -0
  98. package/dist/lite/README.md +5 -1
  99. package/dist/lite/gitignore +6 -0
  100. package/dist/lite/lib/bassclef-dir-resolver.sh +85 -0
  101. package/dist/lite/lib/clone-failure-classifier.sh +59 -0
  102. package/dist/lite/lib/fixture-builder.sh +190 -0
  103. package/dist/lite/lib/fresh-install-check.sh +49 -0
  104. package/dist/lite/lib/hook-heartbeat.sh +0 -1
  105. package/dist/lite/lib/mechanism-fidelity.sh +569 -0
  106. package/dist/lite/lib/npm-version-check.sh +112 -0
  107. package/dist/lite/lib/preview-state.sh +229 -0
  108. package/dist/lite/lib/session-rescue.sh +0 -1
  109. package/dist/lite/scripts/generate-lite-manifest.sh +145 -4
  110. package/dist/lite/scripts/lite-manifest-drift-check.sh +5 -1
  111. package/dist/lite/standards/architect-review-discipline.md +222 -0
  112. package/dist/lite/standards/bassclef-platform.md +249 -0
  113. package/dist/lite/standards/bassclef-test-repos.md +97 -0
  114. package/dist/lite/standards/bassclef-wiring-manifest.json +25 -1
  115. package/dist/lite/standards/cold-adopter-harness.md +205 -0
  116. package/dist/lite/standards/data-management.md +135 -0
  117. package/dist/lite/standards/frontend-stack/nextjs-prisma.md +124 -0
  118. package/dist/lite/standards/lite-manifest-schema-changes.md +27 -0
  119. package/dist/lite/standards/lite-manifest.json +1456 -14
  120. package/dist/lite/standards/mechanism-fidelity.md +205 -0
  121. package/dist/lite/standards/operator-private-discipline.md +200 -0
  122. package/dist/lite/standards/operator-to-public-flow.md +195 -0
  123. package/dist/lite/standards/prototype-gallery.md +251 -0
  124. package/dist/lite/standards/pseudonym-key-schema.md +109 -0
  125. package/dist/lite/standards/sibling-validation-checklist.md +181 -0
  126. package/dist/lite/standards/slack-notifications.md +161 -0
  127. package/dist/lite/standards/synthetic-user-testing.md +173 -0
  128. package/dist/lite/standards/vendor-bindings.md +165 -0
  129. package/dist/lite/standards/vendor-plugins/frontend-design.md +66 -0
  130. package/dist/lite/standards/vpc-fit-validation.md +167 -0
  131. package/dist/lite/templates/gallery-yml.md +113 -0
  132. package/dist/lite/templates/product-canvas.md +169 -0
  133. package/dist/lite/templates/value-prop-canvas.md +180 -0
  134. package/package.json +12 -5
  135. /package/dist/lite/{whereami.md → docs/whereami.md} +0 -0
@@ -0,0 +1,158 @@
1
+ #!/usr/bin/env bash
2
+ # tier: lite
3
+ # install-class: project
4
+ # hook-classifier-canary.sh — advises author when a new hook lands
5
+ # without any recognized wiring (settings.json / .github/workflows /
6
+ # scripts/release-to-bassclef.sh / launchd header / sourced-lib
7
+ # header). Fires at PreToolUse on Edit|Write against paths under
8
+ # .claude/hooks/*.sh.
9
+ #
10
+ # Layer 4 cure for sunj-labs/bassclef-upstream#1163. Same class as
11
+ # the hook-wire-on-author rule; extends discipline to catch mislabels
12
+ # at author time — not release time.
13
+ #
14
+ # Anchors: @luminary saltzer-schroeder (complete mediation at earliest
15
+ # cheap gate), @luminary david-parnas (canary hides classifier
16
+ # vocabulary from author), @luminary michael-feathers (characterization
17
+ # tests pin behavior at author boundary).
18
+ #
19
+ # Reads stdin JSON per Claude Code hook contract:
20
+ # { "tool_name": "Edit|Write", "tool_input": { "file_path": "..." } }
21
+ #
22
+ # Exit codes:
23
+ # 0 — pass (V1 ADVISORY only writes to stderr; V2 may flip to BLOCK)
24
+ # 2 — reserved for V2 BLOCK escalation
25
+ #
26
+ # Override:
27
+ # SKIP_HOOK_CLASSIFIER_CANARY=1 bypass; logged via trace-helper
28
+
29
+ set -uo pipefail
30
+
31
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
32
+ REPO_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
33
+
34
+ # Override
35
+ if [ "${SKIP_HOOK_CLASSIFIER_CANARY:-}" = "1" ]; then
36
+ TRACE_HELPER="$SCRIPT_DIR/trace-helper.sh"
37
+ if [ -f "$TRACE_HELPER" ]; then
38
+ # shellcheck disable=SC1090
39
+ source "$TRACE_HELPER" 2>/dev/null || true
40
+ trace_record "hook-classifier-canary" "skipped via SKIP_HOOK_CLASSIFIER_CANARY=1" 2>/dev/null || true
41
+ fi
42
+ exit 0
43
+ fi
44
+
45
+ # Read stdin JSON. If jq not available, degrade gracefully.
46
+ INPUT=$(cat)
47
+ if [ -z "$INPUT" ]; then
48
+ exit 0
49
+ fi
50
+
51
+ if command -v jq >/dev/null 2>&1; then
52
+ TOOL_NAME=$(echo "$INPUT" | jq -r '.tool_name // empty' 2>/dev/null || echo "")
53
+ FILE_PATH=$(echo "$INPUT" | jq -r '.tool_input.file_path // empty' 2>/dev/null || echo "")
54
+ else
55
+ # Fallback — crude sed parse
56
+ TOOL_NAME=$(echo "$INPUT" | sed -n 's/.*"tool_name"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/p' | head -1)
57
+ FILE_PATH=$(echo "$INPUT" | sed -n 's/.*"file_path"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/p' | head -1)
58
+ fi
59
+
60
+ # Pass-through — non-Edit/Write tools
61
+ case "$TOOL_NAME" in
62
+ Edit|Write|MultiEdit) ;;
63
+ *) exit 0 ;;
64
+ esac
65
+
66
+ # Pass-through — no file path
67
+ [ -z "$FILE_PATH" ] && exit 0
68
+
69
+ # Pass-through — path outside .claude/hooks/*.sh
70
+ case "$FILE_PATH" in
71
+ */.claude/hooks/*.sh) ;;
72
+ *) exit 0 ;;
73
+ esac
74
+
75
+ # Pass-through — path is under .claude/hooks/tests/ or fixtures
76
+ case "$FILE_PATH" in
77
+ */.claude/hooks/tests/*|*/.claude/hooks/*/tests/*) exit 0 ;;
78
+ esac
79
+
80
+ # Get bare hook name for classifier lookup
81
+ HOOK_NAME=$(basename "$FILE_PATH")
82
+
83
+ # Pass-through — this file exists on disk already (edit, not new)
84
+ if [ -f "$FILE_PATH" ]; then
85
+ exit 0
86
+ fi
87
+
88
+ # Load classifier
89
+ LIB="$REPO_ROOT/lib/mechanism-fidelity.sh"
90
+ if [ ! -f "$LIB" ]; then
91
+ # Classifier lib missing — cannot advise; pass silently
92
+ exit 0
93
+ fi
94
+ # shellcheck disable=SC1090
95
+ source "$LIB"
96
+
97
+ # Ask classifier what pattern it detects for this hook name
98
+ PATTERN=$(classify_hook_install_pattern "$HOOK_NAME" "$REPO_ROOT" 2>/dev/null)
99
+
100
+ # Recognized patterns → pass
101
+ case "$PATTERN" in
102
+ ci|launchd|lib|release)
103
+ exit 0
104
+ ;;
105
+ esac
106
+
107
+ # Standard means classifier could not place it AND file does not exist yet.
108
+ # Check settings.json — hook may be wired for PreToolUse there.
109
+ SETTINGS="$REPO_ROOT/.claude/settings.json"
110
+ if [ -f "$SETTINGS" ] && grep -qF "$HOOK_NAME" "$SETTINGS" 2>/dev/null; then
111
+ exit 0
112
+ fi
113
+
114
+ # No recognized wiring signal found. Emit ADVISORY.
115
+ cat >&2 <<EOF
116
+
117
+ ============================================
118
+ 🚨 hook-classifier-canary — ADVISORY
119
+ ============================================
120
+
121
+ New hook detected: $HOOK_NAME
122
+ Author path: $FILE_PATH
123
+
124
+ The classifier at lib/mechanism-fidelity.sh does not recognize any
125
+ wiring signal for this hook. If this ships as-is, the cold-adopter
126
+ harness Shape d checks will flag it as DEAD-LETTER.
127
+
128
+ Five remediation paths (pick one before commit):
129
+
130
+ 1. settings.json wiring — add hook entry to .claude/settings.json
131
+ under PreToolUse/PostToolUse/SessionStart/Stop event matcher.
132
+ For hooks that fire on tool calls.
133
+
134
+ 2. CI workflow — reference the hook name in a .github/workflows/*.yml
135
+ file. For hooks that fire on push/PR events.
136
+
137
+ 3. Release script — reference the hook name in
138
+ scripts/release-to-bassclef.sh. For hooks that gate on /release
139
+ dispatch. Classifier returns "release".
140
+
141
+ 4. launchd header — add "# Runs via launchd" (or "scheduled job" /
142
+ "cron job") to the hook's top-of-file comment block. For
143
+ scheduled jobs. Classifier returns "launchd".
144
+
145
+ 5. Sourced-library header — add "# sourced by <caller>" to the
146
+ hook's top-of-file comment block. For helper libraries loaded
147
+ via source. Classifier returns "lib".
148
+
149
+ If genuinely bypassing (rare): SKIP_HOOK_CLASSIFIER_CANARY=1 <command>
150
+
151
+ Per rule: .claude/rules/hook-wire-on-author.md
152
+ Per Layer 4 of: bassclef-upstream#1163
153
+ ============================================
154
+
155
+ EOF
156
+
157
+ # V1 — ADVISORY only. V2 may flip to exit 2 (BLOCK).
158
+ exit 0
@@ -0,0 +1,129 @@
1
+ #!/bin/bash
2
+ # tier: lite
3
+ # install-class: project
4
+ # kiss-default-check.sh — pre-push /kiss enforcement check
5
+ # Per bassclef#907 Part 4.
6
+ #
7
+ # Reads a draft body file. Checks for BLOCK-tier bassclef-internal jargon
8
+ # per standards/bassclef-internal-jargon.md. BLOCKs if jargon present and
9
+ # no opt-out signal.
10
+ #
11
+ # Composes with .claude/hooks/pr-body-scrub-check.sh (CI-time enforcement).
12
+ # This hook runs pre-push; the scrub hook runs at CI. Both read the same
13
+ # BLOCK list from the standards source-of-truth.
14
+ #
15
+ # Usage:
16
+ # bash kiss-default-check.sh <body-file>
17
+ #
18
+ # Optional env:
19
+ # PR_LABELS=label1,label2,... — labels on the PR (newline or comma separated)
20
+ # SKIP_KISS=1 — operator opt-out for one invocation
21
+ # KISS_STANDARDS_FILE=<path> — override standards file location (testing)
22
+ #
23
+ # Exit codes:
24
+ # 0 — pass (no BLOCK terms found, OR opt-out signal present)
25
+ # 1 — block (BLOCK terms found + no opt-out)
26
+ # 2 — usage error
27
+
28
+ set +e
29
+
30
+ BODY_FILE="${1:-}"
31
+ if [ -z "$BODY_FILE" ] || [ ! -f "$BODY_FILE" ]; then
32
+ echo "usage: $0 <body-file>" >&2
33
+ exit 2
34
+ fi
35
+
36
+ # Find the repo root + standards file
37
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
38
+ REPO_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
39
+ STANDARDS_FILE="${KISS_STANDARDS_FILE:-$REPO_ROOT/standards/bassclef-internal-jargon.md}"
40
+
41
+ if [ ! -f "$STANDARDS_FILE" ]; then
42
+ # Try the bassclef-sync'd path (when run from a consumer repo)
43
+ STANDARDS_FILE="${HOME}/src/sunj-labs/bassclef/standards/bassclef-internal-jargon.md"
44
+ fi
45
+
46
+ if [ ! -f "$STANDARDS_FILE" ]; then
47
+ echo "kiss-default-check: standards file not found at $STANDARDS_FILE" >&2
48
+ echo " set KISS_STANDARDS_FILE=<path> or skip this check" >&2
49
+ exit 2
50
+ fi
51
+
52
+ # Opt-out — env var
53
+ if [ "${SKIP_KISS:-0}" = "1" ]; then
54
+ echo "kiss-default-check: SKIP_KISS=1 — skipped (logged)" >&2
55
+ exit 0
56
+ fi
57
+
58
+ # Opt-out — label
59
+ PR_LABELS="${PR_LABELS:-}"
60
+ LABELS_NORMALIZED=$(echo "$PR_LABELS" | tr ',' '\n' | sed 's/^ *//;s/ *$//' | grep -v '^$' || true)
61
+ if echo "$LABELS_NORMALIZED" | grep -qx "bassclef-internal-prose-ok"; then
62
+ echo "kiss-default-check: bassclef-internal-prose-ok label — advisory mode" >&2
63
+ ADVISORY=1
64
+ else
65
+ ADVISORY=0
66
+ fi
67
+
68
+ # Extract BLOCK terms from the standards table
69
+ # The standards table has lines like: | term | plain-english | BLOCK |
70
+ # Allows digits in the first column so terms like "12-pattern matcher"
71
+ # (added under bassclef-upstream#101) are picked up.
72
+ BLOCK_TERMS=$(awk -F'|' '
73
+ /^\| [a-zA-Z0-9-]+ / && /BLOCK *\|$/ {
74
+ gsub(/^ +| +$/, "", $2)
75
+ print $2
76
+ }
77
+ ' "$STANDARDS_FILE")
78
+
79
+ if [ -z "$BLOCK_TERMS" ]; then
80
+ echo "kiss-default-check: no BLOCK terms found in standards file" >&2
81
+ exit 0
82
+ fi
83
+
84
+ # Strip code blocks + inline backtick spans + URLs so they don't trigger false positives
85
+ SCRUBBED=$(awk '
86
+ BEGIN { in_code = 0 }
87
+ /^```/ { in_code = !in_code; next }
88
+ in_code { next }
89
+ { print }
90
+ ' "$BODY_FILE" | sed -E 's/`[^`]*`//g; s|https?://[^ )]+||g')
91
+
92
+ # Check each BLOCK term
93
+ FINDINGS=""
94
+ FINDING_COUNT=0
95
+ while IFS= read -r term; do
96
+ [ -z "$term" ] && continue
97
+ count=$(echo "$SCRUBBED" | grep -ioE "\\b${term}\\b" | wc -l | tr -d ' ')
98
+ if [ "$count" -gt 0 ]; then
99
+ FINDINGS="${FINDINGS}- \`${term}\` (${count}x)"$'\n'
100
+ FINDING_COUNT=$((FINDING_COUNT + count))
101
+ fi
102
+ done <<< "$BLOCK_TERMS"
103
+
104
+ if [ "$FINDING_COUNT" -eq 0 ]; then
105
+ echo "kiss-default-check: pass — no BLOCK terms in draft" >&2
106
+ exit 0
107
+ fi
108
+
109
+ # Report findings
110
+ {
111
+ echo ""
112
+ echo "kiss-default-check: $FINDING_COUNT BLOCK-tier jargon term(s) found in draft body:"
113
+ echo ""
114
+ echo "$FINDINGS"
115
+ echo "Plain-English alternatives at: $STANDARDS_FILE"
116
+ echo ""
117
+ echo "Options:"
118
+ echo " 1. Run /kiss --grade11 on the draft and re-push"
119
+ echo " 2. Add label 'bassclef-internal-prose-ok' for advisory-only"
120
+ echo " 3. Set SKIP_KISS=1 for one-time bypass (logged)"
121
+ echo ""
122
+ } >&2
123
+
124
+ if [ "$ADVISORY" = "1" ]; then
125
+ echo "kiss-default-check: ADVISORY (label) — passing with warnings" >&2
126
+ exit 0
127
+ fi
128
+
129
+ exit 1
@@ -0,0 +1,83 @@
1
+ #!/bin/bash
2
+ # tier: lite
3
+ # Multi-Tenancy Check — bassclef template.
4
+ # Fires on Edit/Write of source files.
5
+ # Warns when tenant-scoped patterns are missing.
6
+ #
7
+ # App repos should customize:
8
+ # TENANT_MODELS — pipe-separated list of tenant-scoped model names
9
+ # TENANT_CONTEXT_FN — function name that resolves tenant context
10
+ # TENANT_PARAMS_FN — function name for tenant-specific parameters
11
+ #
12
+ # Override by placing your own multi-tenancy-check.sh in .claude/hooks/
13
+
14
+ INPUT=$(cat)
15
+ FILE_PATH=$(echo "$INPUT" | jq -r '.tool_input.file_path // .tool_input.file_path // ""')
16
+ CONTENT=$(echo "$INPUT" | jq -r '.tool_input.new_string // .tool_input.content // ""')
17
+
18
+ # Skip non-source files
19
+ if echo "$FILE_PATH" | grep -qE '\.(sh|json|md)$|/\.claude/|/memory/|/docs/|/scripts/|__tests__'; then
20
+ exit 0
21
+ fi
22
+
23
+ # === Customizable per project (override these in your app's copy) ===
24
+ TENANT_CONTEXT_FN="${TENANT_CONTEXT_FN:-getTenantContext}"
25
+ TENANT_PARAMS_FN="${TENANT_PARAMS_FN:-getTenantParams}"
26
+ # Default: no models (app must define its own)
27
+ TENANT_MODELS="${TENANT_MODELS:-}"
28
+
29
+ # Skip if no tenant models defined (not a multi-tenant project)
30
+ if [ -z "$TENANT_MODELS" ]; then
31
+ exit 0
32
+ fi
33
+
34
+ WARNINGS=""
35
+
36
+ # Check 1: Hardcoded numeric thresholds that should use params facade
37
+ if echo "$CONTENT" | grep -qE '[0-9]{3,}\.?[0-9]*\.?[0-9]*' ; then
38
+ if echo "$CONTENT" | grep -qE '_FLOOR|_CEILING|_THRESHOLD|_LIMIT|_MIN|_MAX'; then
39
+ if ! echo "$CONTENT" | grep -q "$TENANT_PARAMS_FN"; then
40
+ WARNINGS="${WARNINGS}
41
+ MULTI-TENANCY: Possible hardcoded threshold detected.
42
+ Use ${TENANT_PARAMS_FN}() instead of hardcoded values.
43
+ Financial and geographic thresholds must flow through
44
+ the tenant params facade for multi-tenant readiness."
45
+ fi
46
+ fi
47
+ fi
48
+
49
+ # Check 2: Prisma queries on tenant-scoped models without context
50
+ if echo "$CONTENT" | grep -qiE "prisma\.(${TENANT_MODELS})\.(findMany|findFirst|create|update|delete)" ; then
51
+ if ! echo "$CONTENT" | grep -q "$TENANT_CONTEXT_FN"; then
52
+ WARNINGS="${WARNINGS}
53
+ MULTI-TENANCY: Query on tenant-scoped model without ${TENANT_CONTEXT_FN}().
54
+ Tenant-scoped models must be filtered by tenant/user context.
55
+ Use ${TENANT_CONTEXT_FN}() and filter appropriately."
56
+ fi
57
+ fi
58
+
59
+ # Check 3: API routes missing tenant context
60
+ if echo "$FILE_PATH" | grep -qE 'src/app/api/.*route\.ts'; then
61
+ if echo "$CONTENT" | grep -qE 'export async function (GET|POST|PATCH|DELETE|PUT)'; then
62
+ if ! echo "$CONTENT" | grep -q "$TENANT_CONTEXT_FN"; then
63
+ WARNINGS="${WARNINGS}
64
+ MULTI-TENANCY: API route handler without ${TENANT_CONTEXT_FN}().
65
+ All API routes touching tenant-scoped data must resolve
66
+ tenant context. Even GET routes need this for data isolation."
67
+ fi
68
+ fi
69
+ fi
70
+
71
+ if [ -n "$WARNINGS" ]; then
72
+ echo "============================================"
73
+ echo "MULTI-TENANCY GUARDRAIL"
74
+ echo "============================================"
75
+ echo "$WARNINGS"
76
+ echo ""
77
+ echo "These are WARNs, not BLOCKs. If this is intentional"
78
+ echo "(e.g., platform-wide data), proceed."
79
+ echo "If tenant-scoped, add the missing context/facade."
80
+ echo "============================================"
81
+ fi
82
+
83
+ exit 0
@@ -0,0 +1,216 @@
1
+ #!/bin/bash
2
+ # tier: lite
3
+ # oo-ad-entry-point-check.sh — PreToolUse Edit/Write hook mechanizing .claude/rules/oo-ad-entry-point.md.
4
+ #
5
+ # Fires on Write to a new file matching the rule's globs. Requires:
6
+ # 1. A decomposition marker at state/markers/decompose/<branch>.marker
7
+ # OR any file under docs/decompositions/
8
+ # 2. A use-case artifact under docs/use-cases/ matching the code class
9
+ #
10
+ # Per bassclef-upstream#1169 + canvas docs/canvases/2026-08-25-ooad-chain-as-substrate-offering.md.
11
+ # Composes with .claude/hooks/adr-discipline-check.sh (sister hook on architectural boundaries).
12
+ # Override: SKIP_OO_AD_ENTRY_POINT=1 (logged via trace-helper).
13
+
14
+ set -euo pipefail
15
+
16
+ # ============================================================================
17
+ # Read stdin JSON from Claude Code harness
18
+ # ============================================================================
19
+ PAYLOAD=$(cat 2>/dev/null || echo '{}')
20
+
21
+ TOOL_NAME=$(echo "$PAYLOAD" | jq -r '.tool_name // empty' 2>/dev/null)
22
+ FILE_PATH=$(echo "$PAYLOAD" | jq -r '.tool_input.file_path // empty' 2>/dev/null)
23
+
24
+ # ============================================================================
25
+ # Filter: only fire on Write / Edit / MultiEdit
26
+ # ============================================================================
27
+ case "$TOOL_NAME" in
28
+ Write|Edit|MultiEdit) ;;
29
+ *) exit 0 ;;
30
+ esac
31
+
32
+ # Defensive precondition — empty file_path
33
+ if [ -z "$FILE_PATH" ]; then
34
+ exit 0
35
+ fi
36
+
37
+ # ============================================================================
38
+ # Override check
39
+ # ============================================================================
40
+ if [ "${SKIP_OO_AD_ENTRY_POINT:-0}" = "1" ]; then
41
+ TRACE_HELPER="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/trace-helper.sh"
42
+ if [ -f "$TRACE_HELPER" ]; then
43
+ bash "$TRACE_HELPER" override "oo-ad-entry-point-check" "SKIP_OO_AD_ENTRY_POINT=1 on $FILE_PATH" 2>/dev/null || true
44
+ fi
45
+ exit 0
46
+ fi
47
+
48
+ # ============================================================================
49
+ # Path matcher — classify code class per rule oo-ad-entry-point.md L18-25
50
+ # Bash case globs do NOT expand ** — use per-level cases + src/ recursive fallback.
51
+ # ============================================================================
52
+ CODE_CLASS=""
53
+ case "$FILE_PATH" in
54
+ */.claude/hooks/*.sh|.claude/hooks/*.sh)
55
+ CODE_CLASS="substrate-hook"
56
+ ;;
57
+ */lib/*.sh|lib/*.sh)
58
+ CODE_CLASS="substrate-lib"
59
+ ;;
60
+ */scripts/*.sh|scripts/*.sh)
61
+ CODE_CLASS="adopter-script"
62
+ ;;
63
+ esac
64
+
65
+ # src/ handled via recursive path check — any depth under src/ with .ts/.tsx/.js/.py extension
66
+ if [ -z "$CODE_CLASS" ]; then
67
+ case "$FILE_PATH" in
68
+ src/*|*/src/*)
69
+ case "$FILE_PATH" in
70
+ *.ts|*.tsx|*.js|*.py) CODE_CLASS="adopter-app" ;;
71
+ esac
72
+ ;;
73
+ esac
74
+ fi
75
+
76
+ # Not a matched path → pass through
77
+ if [ -z "$CODE_CLASS" ]; then
78
+ exit 0
79
+ fi
80
+
81
+ # ============================================================================
82
+ # Cockburn casual tier — existing file Edit passes through
83
+ # ============================================================================
84
+ # Edit / MultiEdit on existing files needs no new artifacts per rule L24.
85
+ # Only new files (Write, OR Edit of missing file) require ceremony.
86
+ REPO_ROOT="${HOOK_TEST_REPO_ROOT:-$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)}"
87
+
88
+ # Resolve absolute path — file_path may be relative
89
+ if [ "${FILE_PATH:0:1}" = "/" ]; then
90
+ ABS_PATH="$FILE_PATH"
91
+ else
92
+ ABS_PATH="$REPO_ROOT/$FILE_PATH"
93
+ fi
94
+
95
+ if [ -f "$ABS_PATH" ]; then
96
+ exit 0
97
+ fi
98
+
99
+ # ============================================================================
100
+ # Decomposition check
101
+ # ============================================================================
102
+ BRANCH="${HOOK_TEST_BRANCH:-}"
103
+ if [ -z "$BRANCH" ]; then
104
+ BRANCH=$(cd "$REPO_ROOT" && git rev-parse --abbrev-ref HEAD 2>/dev/null || echo "unknown")
105
+ fi
106
+
107
+ MARKER_PATH="$REPO_ROOT/state/markers/decompose/${BRANCH}.marker"
108
+ DECOMP_DIR="$REPO_ROOT/docs/decompositions"
109
+
110
+ DECOMP_OK=0
111
+ if [ -f "$MARKER_PATH" ]; then
112
+ DECOMP_OK=1
113
+ elif [ -d "$DECOMP_DIR" ] && find "$DECOMP_DIR" -maxdepth 1 -name '*.md' -type f 2>/dev/null | grep -q .; then
114
+ DECOMP_OK=1
115
+ fi
116
+
117
+ # ============================================================================
118
+ # Use case check per code class
119
+ # ============================================================================
120
+ UC_DIR="$REPO_ROOT/docs/use-cases"
121
+ UC_OK=0
122
+
123
+ if [ -d "$UC_DIR" ]; then
124
+ case "$CODE_CLASS" in
125
+ adopter-app)
126
+ # UC-*.md that does NOT start with UC-hook-, UC-lib-, or UC-script-
127
+ if find "$UC_DIR" -maxdepth 1 -name 'UC-*.md' -type f \
128
+ -not -name 'UC-hook-*' -not -name 'UC-lib-*' -not -name 'UC-script-*' \
129
+ 2>/dev/null | grep -q .; then
130
+ UC_OK=1
131
+ fi
132
+ ;;
133
+ substrate-hook)
134
+ if find "$UC_DIR" -maxdepth 1 -name 'UC-hook-*.md' -type f 2>/dev/null | grep -q .; then
135
+ UC_OK=1
136
+ fi
137
+ ;;
138
+ substrate-lib)
139
+ if find "$UC_DIR" -maxdepth 1 -name 'UC-lib-*.md' -type f 2>/dev/null | grep -q .; then
140
+ UC_OK=1
141
+ fi
142
+ ;;
143
+ adopter-script)
144
+ if find "$UC_DIR" -maxdepth 1 -name 'UC-script-*.md' -type f 2>/dev/null | grep -q .; then
145
+ UC_OK=1
146
+ fi
147
+ ;;
148
+ esac
149
+ fi
150
+
151
+ # ============================================================================
152
+ # Pass or block
153
+ # ============================================================================
154
+ if [ "$DECOMP_OK" -eq 1 ] && [ "$UC_OK" -eq 1 ]; then
155
+ exit 0
156
+ fi
157
+
158
+ # ============================================================================
159
+ # Block message
160
+ # ============================================================================
161
+ case "$CODE_CLASS" in
162
+ adopter-app)
163
+ CEREMONY="Fully-dressed use case + /decompose + /spec"
164
+ UC_PATTERN="docs/use-cases/UC-<slug>.md"
165
+ ;;
166
+ substrate-hook)
167
+ CEREMONY="Brief use case + /decompose"
168
+ UC_PATTERN="docs/use-cases/UC-hook-<slug>.md"
169
+ ;;
170
+ substrate-lib)
171
+ CEREMONY="Brief use case + /decompose"
172
+ UC_PATTERN="docs/use-cases/UC-lib-<slug>.md"
173
+ ;;
174
+ adopter-script)
175
+ CEREMONY="Brief use case + Tier 0 tests"
176
+ UC_PATTERN="docs/use-cases/UC-script-<slug>.md"
177
+ ;;
178
+ esac
179
+
180
+ cat >&2 <<EOF
181
+ 🛑 oo-ad-entry-point-check — BLOCK (bassclef-upstream#1169)
182
+
183
+ You are creating a new file in the ${CODE_CLASS} class.
184
+
185
+ Path: ${FILE_PATH}
186
+ Branch: ${BRANCH}
187
+
188
+ The rule .claude/rules/oo-ad-entry-point.md requires design artifacts
189
+ before this file lands. Ceremony for this class:
190
+ ${CEREMONY}
191
+
192
+ Missing artifacts:
193
+ $([ "$DECOMP_OK" -eq 0 ] && echo " - Decomposition: marker at ${MARKER_PATH} OR any file under docs/decompositions/")
194
+ $([ "$UC_OK" -eq 0 ] && echo " - Use case: ${UC_PATTERN}")
195
+
196
+ Three resolution paths:
197
+
198
+ 1. Run /decompose to produce the decomposition, then write a use case.
199
+ Touch the marker after:
200
+ mkdir -p $(dirname "$MARKER_PATH")
201
+ touch $MARKER_PATH
202
+
203
+ 2. Write the artifacts by hand per the rule table (L18-25) and touch
204
+ the marker.
205
+
206
+ 3. Override for genuine trivial work:
207
+ SKIP_OO_AD_ENTRY_POINT=1 <command>
208
+
209
+ Then retry the original write.
210
+
211
+ Per .claude/rules/oo-ad-entry-point.md
212
+ Composes with .claude/hooks/adr-discipline-check.sh
213
+ Cockburn ceremony tiering — Writing Effective Use Cases (2000)
214
+ EOF
215
+
216
+ exit 2