@thebassclef/lite 1.0.4 → 1.1.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 (275) hide show
  1. package/dist/cli.cjs +298 -55
  2. package/dist/cli.js +298 -55
  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/agents/architect.md +70 -0
  7. package/dist/lite/.claude/agents/builder.md +114 -0
  8. package/dist/lite/.claude/agents/designer.md +156 -0
  9. package/dist/lite/.claude/agents/reviewer.md +88 -0
  10. package/dist/lite/.claude/hooks/bassclef-sync.sh +85 -27
  11. package/dist/lite/.claude/hooks/longrun-prep-compounding-axis-check.sh +492 -0
  12. package/dist/lite/.claude/hooks/longrun-prep-render-check.sh +236 -0
  13. package/dist/lite/.claude/hooks/persona-name-scrub-check.sh +105 -0
  14. package/dist/lite/.claude/hooks/skill-step-list-check.sh +171 -0
  15. package/dist/lite/.claude/luminaries/alan-cooper.md +170 -0
  16. package/dist/lite/.claude/luminaries/alistair-cockburn.md +140 -0
  17. package/dist/lite/.claude/luminaries/amazon-pr-faq.md +34 -0
  18. package/dist/lite/.claude/luminaries/andreas-zeller.md +74 -0
  19. package/dist/lite/.claude/luminaries/ash-maurya.md +121 -0
  20. package/dist/lite/.claude/luminaries/bill-buxton.md +210 -0
  21. package/dist/lite/.claude/luminaries/charles-sanders-peirce.md +150 -0
  22. package/dist/lite/.claude/luminaries/david-ogilvy.md +192 -0
  23. package/dist/lite/.claude/luminaries/don-norman.md +173 -0
  24. package/dist/lite/.claude/luminaries/edward-tufte.md +179 -0
  25. package/dist/lite/.claude/luminaries/eric-evans.md +160 -0
  26. package/dist/lite/.claude/luminaries/frederick-brooks.md +50 -0
  27. package/dist/lite/.claude/luminaries/gang-of-four.md +157 -0
  28. package/dist/lite/.claude/luminaries/glenford-myers.md +230 -0
  29. package/dist/lite/.claude/luminaries/hunt-thomas.md +115 -0
  30. package/dist/lite/.claude/luminaries/hyrum-wright.md +94 -0
  31. package/dist/lite/.claude/luminaries/jason-fried-dhh.md +46 -0
  32. package/dist/lite/.claude/luminaries/jesse-james-garrett.md +154 -0
  33. package/dist/lite/.claude/luminaries/john-ousterhout.md +94 -0
  34. package/dist/lite/.claude/luminaries/karl-popper.md +132 -0
  35. package/dist/lite/.claude/luminaries/kent-beck.md +168 -0
  36. package/dist/lite/.claude/luminaries/linus-torvalds.md +218 -0
  37. package/dist/lite/.claude/luminaries/martin-fowler.md +164 -0
  38. package/dist/lite/.claude/luminaries/michael-feathers.md +125 -0
  39. package/dist/lite/.claude/luminaries/michael-nygard.md +118 -0
  40. package/dist/lite/.claude/luminaries/robert-c-martin.md +164 -0
  41. package/dist/lite/.claude/luminaries/saltzer-schroeder.md +194 -0
  42. package/dist/lite/.claude/luminaries/sophia-prater.md +193 -0
  43. package/dist/lite/.claude/luminaries/stephen-toulmin.md +131 -0
  44. package/dist/lite/.claude/luminaries/tony-hoare.md +170 -0
  45. package/dist/lite/.claude/luminaries/vaughn-vernon.md +50 -0
  46. package/dist/lite/.claude/luminaries/w-edwards-deming.md +158 -0
  47. package/dist/lite/.claude/rules/accessor-library-discipline.md +110 -0
  48. package/dist/lite/.claude/rules/adr-discipline.md +96 -0
  49. package/dist/lite/.claude/rules/api-conventions.md +115 -0
  50. package/dist/lite/.claude/rules/artifact-ingestion.md +137 -0
  51. package/dist/lite/.claude/rules/assert-only-after-verify.md +111 -0
  52. package/dist/lite/.claude/rules/blocked-items.md +139 -0
  53. package/dist/lite/.claude/rules/bootstrap-pair-discipline.md +106 -0
  54. package/dist/lite/.claude/rules/branching.md +28 -0
  55. package/dist/lite/.claude/rules/cold-adopter-harness-discipline.md +93 -0
  56. package/dist/lite/.claude/rules/commit-conventions.md +22 -0
  57. package/dist/lite/.claude/rules/compounding-axis-fresh-analysis.md +173 -0
  58. package/dist/lite/.claude/rules/compounding-sequence-fresh-analysis.md +173 -0
  59. package/dist/lite/.claude/rules/context-engineering.md +155 -0
  60. package/dist/lite/.claude/rules/context-management.md +85 -0
  61. package/dist/lite/.claude/rules/defensive-bash.md +52 -0
  62. package/dist/lite/.claude/rules/deferred-actions.md +233 -0
  63. package/dist/lite/.claude/rules/destructive-operations.md +69 -0
  64. package/dist/lite/.claude/rules/diagnosis.md +38 -0
  65. package/dist/lite/.claude/rules/github-issue-flash-tweet.md +114 -0
  66. package/dist/lite/.claude/rules/guardrails.md +73 -0
  67. package/dist/lite/.claude/rules/hook-wire-on-author.md +77 -0
  68. package/dist/lite/.claude/rules/identifier-leak-prevention.md +73 -0
  69. package/dist/lite/.claude/rules/iteration-bet-brief-completeness.md +43 -0
  70. package/dist/lite/.claude/rules/lite-manifest-schema-change-discipline.md +79 -0
  71. package/dist/lite/.claude/rules/longrun-prep-plan-doc-compression.md +77 -0
  72. package/dist/lite/.claude/rules/loop-discipline.md +71 -0
  73. package/dist/lite/.claude/rules/manual-prod-approval.md +100 -0
  74. package/dist/lite/.claude/rules/marker-enrichment-discipline.md +72 -0
  75. package/dist/lite/.claude/rules/mobile-ephemeral-session.md +109 -0
  76. package/dist/lite/.claude/rules/new-dependency-check.md +44 -0
  77. package/dist/lite/.claude/rules/oo-ad-entry-point.md +95 -0
  78. package/dist/lite/.claude/rules/operator-facing-prose.md +177 -0
  79. package/dist/lite/.claude/rules/option-label-discipline.md +82 -0
  80. package/dist/lite/.claude/rules/pattern-annotation.md +83 -0
  81. package/dist/lite/.claude/rules/persona-name-leak-scrub.md +90 -0
  82. package/dist/lite/.claude/rules/plain-english-discipline.md +132 -0
  83. package/dist/lite/.claude/rules/plan-enumeration-needs-value-props.md +177 -0
  84. package/dist/lite/.claude/rules/pr-body-shape.md +195 -0
  85. package/dist/lite/.claude/rules/pr-strategy.md +142 -0
  86. package/dist/lite/.claude/rules/pr-title-shape.md +90 -0
  87. package/dist/lite/.claude/rules/prototype-workflow.md +53 -0
  88. package/dist/lite/.claude/rules/reserved-skill-names.md +103 -0
  89. package/dist/lite/.claude/rules/schema-management.md +42 -0
  90. package/dist/lite/.claude/rules/sdlc-gates.md +149 -0
  91. package/dist/lite/.claude/rules/security.md +37 -0
  92. package/dist/lite/.claude/rules/session-artifacts.md +236 -0
  93. package/dist/lite/.claude/rules/skill-composition-declarations.md +105 -0
  94. package/dist/lite/.claude/rules/skill-description-clarity.md +196 -0
  95. package/dist/lite/.claude/rules/skill-procedure-step-list.md +119 -0
  96. package/dist/lite/.claude/rules/sprint-prep-preset-picker.md +76 -0
  97. package/dist/lite/.claude/rules/state-schema-validation.md +156 -0
  98. package/dist/lite/.claude/rules/stuck-signal-diagnostic.md +111 -0
  99. package/dist/lite/.claude/rules/substrate-config-schema.md +85 -0
  100. package/dist/lite/.claude/rules/test-list-discipline.md +129 -0
  101. package/dist/lite/.claude/rules/test-sufficiency.md +186 -0
  102. package/dist/lite/.claude/rules/testing-tier-config.md +125 -0
  103. package/dist/lite/.claude/rules/testing.md +38 -0
  104. package/dist/lite/.claude/rules/turn-estimate-grounding.md +82 -0
  105. package/dist/lite/.claude/rules/visual-hierarchy.md +427 -0
  106. package/dist/lite/.claude/rules/we-dont-break-adopters.md +103 -0
  107. package/dist/lite/.claude/rules/whereami-load-bearing.md +184 -0
  108. package/dist/lite/.claude/rules/writing-craft-discipline.md +72 -0
  109. package/dist/lite/.claude/rules/wu-sequencing-compounds.md +119 -0
  110. package/dist/lite/.claude/skills/build/SKILL.md +640 -0
  111. package/dist/lite/.claude/skills/chronicle/SKILL.md +55 -0
  112. package/dist/lite/.claude/skills/clean-artifacts/SKILL.md +249 -0
  113. package/dist/lite/.claude/skills/decompose/SKILL.md +280 -0
  114. package/dist/lite/.claude/skills/diagnose/SKILL.md +297 -0
  115. package/dist/lite/.claude/skills/feynman/SKILL.md +90 -0
  116. package/dist/lite/.claude/skills/howdoi/SKILL.md +105 -0
  117. package/dist/lite/.claude/skills/ia-model/SKILL.md +108 -0
  118. package/dist/lite/.claude/skills/interaction-design/SKILL.md +112 -0
  119. package/dist/lite/.claude/skills/interpret-input/SKILL.md +180 -0
  120. package/dist/lite/.claude/skills/journal/SKILL.md +209 -0
  121. package/dist/lite/.claude/skills/kiss/SKILL.md +449 -0
  122. package/dist/lite/.claude/skills/launch/SKILL.md +915 -0
  123. package/dist/lite/.claude/skills/lean-canvas/SKILL.md +332 -0
  124. package/dist/lite/.claude/skills/longrun/SKILL.md +512 -0
  125. package/dist/lite/.claude/skills/luminary/SKILL.md +481 -0
  126. package/dist/lite/.claude/skills/ogilvy-writing-audit/SKILL.md +177 -0
  127. package/dist/lite/.claude/skills/onboard-repo/SKILL.md +1640 -0
  128. package/dist/lite/.claude/skills/pattern-review/SKILL.md +99 -0
  129. package/dist/lite/.claude/skills/personas/SKILL.md +207 -0
  130. package/dist/lite/.claude/skills/promote/SKILL.md +283 -0
  131. package/dist/lite/.claude/skills/requirement/SKILL.md +98 -0
  132. package/dist/lite/.claude/skills/retro/SKILL.md +117 -0
  133. package/dist/lite/.claude/skills/riff/SKILL.md +114 -0
  134. package/dist/lite/.claude/skills/roadmap-reconcile/SKILL.md +163 -0
  135. package/dist/lite/.claude/skills/session-end/SKILL.md +309 -0
  136. package/dist/lite/.claude/skills/session-log/SKILL.md +299 -0
  137. package/dist/lite/.claude/skills/skills/SKILL.md +228 -0
  138. package/dist/lite/.claude/skills/spec/SKILL.md +105 -0
  139. package/dist/lite/.claude/skills/sprint/SKILL.md +418 -0
  140. package/dist/lite/.claude/skills/stage/SKILL.md +384 -0
  141. package/dist/lite/.claude/skills/state-a-problem/SKILL.md +185 -0
  142. package/dist/lite/.claude/skills/temperance/SKILL.md +108 -0
  143. package/dist/lite/.claude/skills/use-case/SKILL.md +417 -0
  144. package/dist/lite/.claude/skills/user-stories/SKILL.md +268 -0
  145. package/dist/lite/.claude/skills/value-prop/SKILL.md +251 -0
  146. package/dist/lite/.claude/skills/verify/SKILL.md +160 -0
  147. package/dist/lite/.claude/skills/visual-review/SKILL.md +503 -0
  148. package/dist/lite/.claude/skills/whats-the-plan/SKILL.md +202 -0
  149. package/dist/lite/.claude/skills/whereami/SKILL.md +307 -0
  150. package/dist/lite/AGENTS.md +79 -0
  151. package/dist/lite/CLAUDE-lite.md +85 -0
  152. package/dist/lite/CODE_OF_CONDUCT.md +28 -0
  153. package/dist/lite/CONTRIBUTING.md +177 -0
  154. package/dist/lite/README.md +173 -0
  155. package/dist/lite/SECURITY.md +19 -0
  156. package/dist/lite/architecture/decisions/ADR-029-release-pipeline.md +79 -0
  157. package/dist/lite/architecture/decisions/ADR-031-non-breaking-changes-adopter-discipline.md +139 -0
  158. package/dist/lite/architecture/decisions/ADR-032-adopter-sync-dispatcher-architecture.md +192 -0
  159. package/dist/lite/architecture/decisions/ADR-039-release-tagging-scheme.md +145 -0
  160. package/dist/lite/architecture/decisions/ADR-040-planning-skill-vocabulary-and-lite-profile.md +155 -0
  161. package/dist/lite/architecture/decisions/ADR-044-unified-skill-body-template.md +162 -0
  162. package/dist/lite/lib/clean-artifacts-sweep.sh +112 -0
  163. package/dist/lite/lib/code-comment-discipline.sh +144 -0
  164. package/dist/lite/lib/composer-preflight.sh +459 -0
  165. package/dist/lite/lib/deferred-actions.sh +146 -0
  166. package/dist/lite/lib/hook-header-parser.sh +61 -0
  167. package/dist/lite/lib/hook-heartbeat.sh +152 -0
  168. package/dist/lite/lib/hook-inject.sh +255 -0
  169. package/dist/lite/lib/hook-installer.sh +195 -0
  170. package/dist/lite/lib/luminary-pick.sh +96 -0
  171. package/dist/lite/lib/output-discipline.sh +143 -0
  172. package/dist/lite/lib/prose-scan-boundary.sh +171 -0
  173. package/dist/lite/lib/rewrite-check.sh +214 -0
  174. package/dist/lite/lib/session-rescue.sh +151 -0
  175. package/dist/lite/lib/source-graph-walker.sh +277 -0
  176. package/dist/lite/lib/state.sh +1372 -0
  177. package/dist/lite/lib/telemetry.sh +205 -0
  178. package/dist/lite/lib/tier-check.sh +187 -0
  179. package/dist/lite/lib/tier-dependency-audit.sh +1088 -0
  180. package/dist/lite/presence/install/bassclef-hook-connect.sh +178 -0
  181. package/dist/lite/presence/install/bassclef-sync.dispatcher.template.sh +841 -0
  182. package/dist/lite/presence/install/bassclef-sync.template.sh +2278 -0
  183. package/dist/lite/presence/install/schedule-auto-save.cron.sh +88 -0
  184. package/dist/lite/presence/install/schedule-auto-save.taskscheduler.md +122 -0
  185. package/dist/lite/scripts/aggregate-telemetry.sh +217 -0
  186. package/dist/lite/scripts/analyze-tier-dependencies.sh +239 -0
  187. package/dist/lite/scripts/generate-lite-manifest.sh +505 -0
  188. package/dist/lite/scripts/generate-tier-manifest.sh +28 -0
  189. package/dist/lite/scripts/intent-drift-check.sh +456 -0
  190. package/dist/lite/scripts/lite-manifest-drift-check.sh +146 -0
  191. package/dist/lite/scripts/render-lite-manifest-doc.sh +150 -0
  192. package/dist/lite/standards/adr-template.md +86 -0
  193. package/dist/lite/standards/api-conventions/nextjs.md +84 -0
  194. package/dist/lite/standards/artifact-composition.md +209 -0
  195. package/dist/lite/standards/bash-hook-safety.md +246 -0
  196. package/dist/lite/standards/bassclef-configs-schema.md +232 -0
  197. package/dist/lite/standards/bassclef-evolution.md +143 -0
  198. package/dist/lite/standards/bassclef-internal-jargon.md +244 -0
  199. package/dist/lite/standards/bassclef-managed-sentinel.md +96 -0
  200. package/dist/lite/standards/bassclef-source-config.md +228 -0
  201. package/dist/lite/standards/branch-stacking.md +408 -0
  202. package/dist/lite/standards/code-safety-principles.md +176 -0
  203. package/dist/lite/standards/composer-prerequisites.md +155 -0
  204. package/dist/lite/standards/deferred-actions-schema.md +204 -0
  205. package/dist/lite/standards/dependency-discipline/cargo.md +39 -0
  206. package/dist/lite/standards/dependency-discipline/gem.md +43 -0
  207. package/dist/lite/standards/dependency-discipline/go-mod.md +41 -0
  208. package/dist/lite/standards/dependency-discipline/npm.md +42 -0
  209. package/dist/lite/standards/dependency-discipline/pip.md +42 -0
  210. package/dist/lite/standards/deployment-topology/ec2-tailscale.md +225 -0
  211. package/dist/lite/standards/deployment-topology.md +69 -0
  212. package/dist/lite/standards/docs-sync-allowlist.md +76 -0
  213. package/dist/lite/standards/domain-and-dns.md +145 -0
  214. package/dist/lite/standards/frontend-stack.md +67 -0
  215. package/dist/lite/standards/frontmatter-schema.md +154 -0
  216. package/dist/lite/standards/graceful-exit.md +227 -0
  217. package/dist/lite/standards/hook-idempotency.md +102 -0
  218. package/dist/lite/standards/hook-injection-discipline.md +202 -0
  219. package/dist/lite/standards/hook-install-class.md +215 -0
  220. package/dist/lite/standards/input-handler-interface.md +152 -0
  221. package/dist/lite/standards/lite-manifest-schema-changes.md +180 -0
  222. package/dist/lite/standards/lite-manifest.json +2797 -0
  223. package/dist/lite/standards/luminary-matching.md +105 -0
  224. package/dist/lite/standards/luminary-problem-patterns.md +481 -0
  225. package/dist/lite/standards/migration-discipline/active-record.md +50 -0
  226. package/dist/lite/standards/migration-discipline/alembic.md +43 -0
  227. package/dist/lite/standards/migration-discipline/gorm.md +50 -0
  228. package/dist/lite/standards/migration-discipline/prisma.md +53 -0
  229. package/dist/lite/standards/migration-discipline/sqlalchemy.md +51 -0
  230. package/dist/lite/standards/mobile-ephemeral-session.md +167 -0
  231. package/dist/lite/standards/model-routing-discipline.md +160 -0
  232. package/dist/lite/standards/ogilvy-writing-rules.md +225 -0
  233. package/dist/lite/standards/opener-discipline.md +96 -0
  234. package/dist/lite/standards/operator-facing-prose-discipline.md +201 -0
  235. package/dist/lite/standards/persona-schema.md +229 -0
  236. package/dist/lite/standards/pluggable-luminaries.md +323 -0
  237. package/dist/lite/standards/pr-body-discipline.md +115 -0
  238. package/dist/lite/standards/preview-state-schema.md +189 -0
  239. package/dist/lite/standards/project-directory-layout.md +276 -0
  240. package/dist/lite/standards/release-tagging.md +137 -0
  241. package/dist/lite/standards/reserved-skill-names.md +120 -0
  242. package/dist/lite/standards/scannable-multi-option-output.md +265 -0
  243. package/dist/lite/standards/sdlc-compliance.md +286 -0
  244. package/dist/lite/standards/sdlc-gates/typescript.md +57 -0
  245. package/dist/lite/standards/secrets-lifecycle.md +210 -0
  246. package/dist/lite/standards/security-scanner-adapter.md +145 -0
  247. package/dist/lite/standards/session-board.md +256 -0
  248. package/dist/lite/standards/skill-output-discipline.md +121 -0
  249. package/dist/lite/standards/state-spine-contract.md +255 -0
  250. package/dist/lite/standards/state-spine.md +511 -0
  251. package/dist/lite/standards/steering-hints/kiss-words.md +11 -0
  252. package/dist/lite/standards/substrate-config-schema.md +267 -0
  253. package/dist/lite/standards/tech-stack-config.md +109 -0
  254. package/dist/lite/standards/tier-dependency-analysis.md +167 -0
  255. package/dist/lite/standards/tier-runtime-deps/lite.md +57 -0
  256. package/dist/lite/standards/tier-tag-schema.md +155 -0
  257. package/dist/lite/standards/two-layer-config.md +99 -0
  258. package/dist/lite/standards/use-case-format.md +292 -0
  259. package/dist/lite/standards/user-story-invest.md +268 -0
  260. package/dist/lite/standards/velocity-and-appetite.md +229 -0
  261. package/dist/lite/standards/voice-input-pattern.md +119 -0
  262. package/dist/lite/standards/whereami-schema.md +301 -0
  263. package/dist/lite/standards/worktree-management.md +211 -0
  264. package/dist/lite/standards/writing-guide.md +213 -0
  265. package/dist/lite/templates/chronicle-template.md +75 -0
  266. package/dist/lite/templates/deferred-action-template.md +45 -0
  267. package/dist/lite/templates/memory-proposal-template.md +77 -0
  268. package/dist/lite/templates/persona-template.md +200 -0
  269. package/dist/lite/templates/pr-faq.md +45 -0
  270. package/dist/lite/templates/secret-rotation-template.md +162 -0
  271. package/dist/lite/templates/spec-template.md +131 -0
  272. package/dist/lite/templates/use-case-template.md +194 -0
  273. package/dist/lite/templates/user-story-template.md +107 -0
  274. package/dist/lite/templates/whereami-template.md +101 -0
  275. package/package.json +12 -5
@@ -0,0 +1,246 @@
1
+ ---
2
+ tier: lite
3
+ description: "This standard codifies the defensive coding discipline for bassclef's bash hooks (.claude/hooks/.sh) + supporting bash scripts (scripts/.sh, lib/*.sh)."
4
+ ---
5
+
6
+ # Bash Hook Safety Standard
7
+
8
+ This standard codifies the defensive coding discipline for bassclef's bash hooks (`.claude/hooks/*.sh`) + supporting bash scripts (`scripts/*.sh`, `lib/*.sh`). It is the bash-specific instantiation of `standards/code-safety-principles.md`.
9
+
10
+ ## Why this standard exists
11
+
12
+ Bassclef's hooks are bash scripts that fire on every tool call. They sit between the operator's intent and every Edit / Write / Bash invocation. A bug in a hook is amplified: every session in every consumer repo runs the hook on every tool call. Three months of substrate-evolution surfaced four same-shape failures (bassclef#1027, #1054, #1058, #1060) — all in bash code, all caught after PR open, all preventable by hooks at the moment of failure.
13
+
14
+ The existing `.claude/rules/security.md` is scoped to web-application source files (`.ts`, `.tsx`, `.json`, `.env`, `Dockerfile`). It does not cover `.sh`. This standard closes that gap with hook-specific discipline anchored to Saltzer & Schroeder's 8 principles per `@luminary saltzer-schroeder`.
15
+
16
+ ## Anchors
17
+
18
+ - `@luminary saltzer-schroeder` — the 8 protection-mechanism principles this standard instantiates
19
+ - `@luminary john-ousterhout` — Deep modules + define-errors-out-of-existence framing for hook interface design
20
+ - `@luminary kent-beck` — TDD discipline for hooks (Tier 0 per `.claude/rules/testing-tier-config.md`)
21
+ - `standards/code-safety-principles.md` — language-agnostic principles this standard instantiates for bash
22
+
23
+ ## The seven disciplines
24
+
25
+ ### 1. Strict mode at the top
26
+
27
+ Every bash hook + script starts with:
28
+
29
+ ```bash
30
+ #!/bin/bash
31
+ set -euo pipefail
32
+ ```
33
+
34
+ - `-e` exits on any command failure
35
+ - `-u` exits on undefined variable use
36
+ - `-o pipefail` makes pipelines fail if any stage fails (default is "last stage's exit code only")
37
+
38
+ INSTEAD of "I'll handle errors explicitly where they matter": strict mode makes errors loud by default. Explicit error handling overrides apply per-command via `command || true` or `command 2>/dev/null` with intent.
39
+
40
+ **Why mandatory**: bash's default behavior is "continue on error, use the empty string for undefined variables." Bassclef's hooks run in environments where silent failure causes incorrect downstream state. PR #1054 demonstrated this: `log()` function's quiet-mode toggle behavior depended on an unset variable being treated as false; strict mode would have surfaced the bug at write-time.
41
+
42
+ ### 2. Quote every variable expansion
43
+
44
+ Every `$var` or `${var}` reference inside a string context gets double-quoted:
45
+
46
+ ```bash
47
+ # Correct
48
+ file_path="$1"
49
+ if [[ -f "$file_path" ]]; then
50
+ cat "$file_path"
51
+ fi
52
+
53
+ # Wrong — word-splits on spaces; glob-expands; breaks on empty
54
+ if [[ -f $1 ]]; then
55
+ cat $1
56
+ fi
57
+ ```
58
+
59
+ INSTEAD of "I know this variable will never contain a space": quote universally. The cost of consistent quoting is zero; the cost of one missed quote in a path with a space is silent corruption.
60
+
61
+ **Exception**: `local` declarations of arrays + variables that intentionally word-split (rare; document with an inline comment).
62
+
63
+ ### 3. `local` in functions
64
+
65
+ Every variable declared inside a function uses `local`:
66
+
67
+ ```bash
68
+ parse_config() {
69
+ local config_path="$1"
70
+ local mode="${2:-default}"
71
+ # ...
72
+ }
73
+ ```
74
+
75
+ INSTEAD of relying on bash's default of global scope: `local` keeps function-internal state inside the function. A function that pollutes parent scope is a defect waiting to surface — the bug appears when a different caller reuses the same variable name.
76
+
77
+ ### 4. Trap EXIT for cleanup
78
+
79
+ Hooks that create temporary files, lock files, or background processes register a trap for cleanup:
80
+
81
+ ```bash
82
+ TMP_DIR=$(mktemp -d)
83
+ trap 'rm -rf "$TMP_DIR"' EXIT
84
+
85
+ # ... use $TMP_DIR ...
86
+ # Cleanup happens automatically on any exit path
87
+ ```
88
+
89
+ INSTEAD of "I'll clean up at the end of the happy path": cleanup at every exit path including error paths and SIGINT. `trap '...' EXIT` runs the cleanup regardless of how the script exits.
90
+
91
+ For hooks specifically: clean up `/tmp` markers, release `flock`s, kill background `tee`s.
92
+
93
+ ### 5. Explicit return codes
94
+
95
+ Hook exit codes carry meaning. Bassclef's hook protocol:
96
+
97
+ - `0` — allow the tool call (default)
98
+ - `1` — generic non-blocking failure (usually a bug in the hook itself; logged but doesn't block)
99
+ - `2` — BLOCK the tool call (the operator-facing surface)
100
+ - `>2` — reserved; treat as `1`
101
+
102
+ Every hook ends with explicit `exit 0` (or `exit 2` on block). Relying on bash's "exit code of last command" default produces silent breakage when refactors reorder statements.
103
+ INSTEAD of implicit "last-command exit code": explicit `exit N` at every termination point. Hook readers should see the exit value next to the BLOCK decision.
104
+
105
+ ### 6. Glob-tolerance via fallthrough
106
+
107
+ Bash's `for f in pattern/*` fails silently when the pattern matches nothing — the loop body runs once with the literal pattern string. The shape that tolerates empty match:
108
+
109
+ ```bash
110
+ shopt -s nullglob # empty match = empty loop, not literal pattern
111
+
112
+ for f in "$dir"/*.json; do
113
+ process "$f"
114
+ done
115
+
116
+ shopt -u nullglob # restore default
117
+ ```
118
+
119
+ INSTEAD of assuming a glob always matches: `nullglob` makes empty-match an empty loop. The hook handles "no files" naturally.
120
+
121
+ For one-off patterns: `[[ ${#files[@]} -gt 0 ]]` after assigning to an array via `files=("$dir"/*.json)`.
122
+
123
+ ### 7. Audit emission at every exit path
124
+
125
+ Every hook emits a trace record before exit:
126
+
127
+ ```bash
128
+ source "$(dirname "$0")/../lib/trace-helper.sh"
129
+
130
+ # ... hook body ...
131
+
132
+ trace_record "hook-name" "decision" "context"
133
+ exit 0
134
+ ```
135
+
136
+ INSTEAD of audit-only-on-block: audit on allow + block + override usage + skip path. Post-incident reconstruction needs the full trace.
137
+
138
+ ## Common idioms
139
+
140
+ ### `find | head` under `set -euo pipefail` — SIGPIPE kills the script
141
+
142
+ Under `set -euo pipefail`, piping `find` into `head -N` can silently kill the script when `find` produces more than N results. `head` closes stdin after N lines, `find` receives SIGPIPE from the closed pipe, `find` exits 141, and `pipefail` promotes 141 to the pipeline exit code. `set -e` then kills the script silently.
143
+
144
+ Anti-pattern:
145
+
146
+ ```bash
147
+ set -euo pipefail
148
+ broken=$(find . -type l \! -exec test -e {} \; -print 2>/dev/null | head -10)
149
+ # ^ script may exit here with no error output when find produces >10 results
150
+ ```
151
+
152
+ INSTEAD — Option 5d (preferred): bash-native array truncation. No pipe means no SIGPIPE.
153
+
154
+ ```bash
155
+ set -euo pipefail
156
+ readarray -t all_broken < <(find . -type l \! -exec test -e {} \; -print 2>/dev/null)
157
+ broken="$(printf '%s\n' "${all_broken[@]:0:10}")"
158
+ ```
159
+
160
+ Three alternatives, each with tradeoffs:
161
+
162
+ - **SIGPIPE catch** — `find ... 2>/dev/null | head -10 || true`. Swallows all pipeline errors including real ones; less specific than the SIGPIPE-only class.
163
+ - **No-pipe restructure** — `find ... -print | while read; do ... done` with an explicit counter break. More lines; keeps structural-code style.
164
+ - **Fallthrough with `|| true`** — cheapest to write; hides every non-zero pipeline exit; least safe under production loads.
165
+
166
+ Option 5d preserves the structural read shape AND removes the SIGPIPE vector at the source. Strictly stronger error propagation than SIGPIPE catch — the pipe never exists, so no pipe error class can fire.
167
+
168
+ Anchors:
169
+
170
+ - `@luminary linus-torvalds` — adopter contract on observable script behavior; silent-exit is worse than loud-fail
171
+ - `@luminary michael-feathers` — characterization test pins the FAIL contract (find-produces-N-plus-1 case) before the fix ships
172
+
173
+ Per sunj-labs/bassclef-upstream#912. Cure 4 shipped inside the #901 install-corrupts-tree epic; PR #892 carries the exemplar. See the ticket body for the second-AI consultation write-up + the linus lens shift from Option 1 (SIGPIPE catch) to Option 5d.
174
+
175
+ ## The Saltzer & Schroeder stack-translation
176
+
177
+ This standard's seven disciplines instantiate Saltzer & Schroeder's 8 principles (per `@luminary saltzer-schroeder` stack-translation table):
178
+
179
+ | Saltzer & Schroeder principle | Bash discipline |
180
+ |---|---|
181
+ | Economy of mechanism | Hook body ≤200 lines; helpers in `lib/*.sh` |
182
+ | Fail-safe defaults | Strict mode `set -euo pipefail`; default `exit 2` on uncertainty |
183
+ | Complete mediation | PreToolUse fires on every matching call |
184
+ | Open design | Triggers documented in `docs/hooks-index.md`; BLOCK banners name the read path |
185
+ | Separation of privilege | Destructive hooks require multiple independent signals |
186
+ | Least privilege | `cd` only when needed; scope git/file ops to specific paths |
187
+ | Least common mechanism | Per-hook trace; per-hook test; no global state between hooks |
188
+ | Psychological acceptability | `SKIP_<HOOK>=1` per-call override; logged via trace-helper |
189
+
190
+ ## Shellcheck
191
+
192
+ Every bash hook + script passes `shellcheck` (current version). Tier 0 strict-TDD discipline per `.claude/rules/testing-tier-config.md` extends to shellcheck: an edit that introduces a shellcheck finding fails CI per Phase X-4's shellcheck workflow.
193
+
194
+ **Local install**:
195
+
196
+ | OS | Command |
197
+ |---|---|
198
+ | macOS | `brew install shellcheck` |
199
+ | Ubuntu/Debian | `apt install shellcheck` |
200
+ | Fedora | `dnf install ShellCheck` |
201
+ | Arch | `pacman -S shellcheck` |
202
+ | Container builds | Add `shellcheck` to the base image |
203
+
204
+ **Local run**:
205
+
206
+ ```bash
207
+ shellcheck .claude/hooks/*.sh scripts/*.sh lib/*.sh
208
+ ```
209
+
210
+ **Phase X-4** ships the CI workflow that runs shellcheck on every PR + a baseline allowlist (`.claude/hooks/shellcheck-allowlist.txt`) with 60-day grace through 2026-08-17 for existing findings.
211
+
212
+ ## What this standard does NOT do
213
+
214
+ - Does not cover language interop (bash calling Python, Python calling bash) — handle at the boundary
215
+ - Does not specify which utilities to use (`gh` vs `curl` vs `jq` vs `yq`) — that is a stack-choice question
216
+ - Does not cover bash 4+ features absent from macOS's default install (`${var^^}` uppercase conversion, associative arrays) — bash 3.2 compatibility is the baseline.
217
+ INSTEAD of using a bash 4+ feature implicitly: opt in via explicit shebang line (`#!/usr/bin/env bash` with version check) or fallback shape.
218
+
219
+ ## When this standard fires
220
+
221
+ | Surface | Check |
222
+ |---|---|
223
+ | New hook in `.claude/hooks/` | All 7 disciplines + shellcheck-clean + sibling test (Tier 0) |
224
+ | New script in `scripts/` | All 7 disciplines + shellcheck-clean (Tier 1) |
225
+ | Edit to existing hook | Same — Phase A's testing-tier hook BLOCKs without test mtime ≤ source mtime |
226
+ | Code review on PR touching `.sh` | Reviewer applies the 7 disciplines |
227
+ | `/security-review` skill invocation | Skill cites this standard for any `.sh` change |
228
+
229
+ ## Refs
230
+
231
+ - `@luminary saltzer-schroeder` — anchor
232
+ - `@luminary john-ousterhout` — Deep modules framing for hook interface design
233
+ - `@luminary kent-beck` — TDD anchor; Tier 0 strict-TDD discipline applies
234
+ - `standards/code-safety-principles.md` — language-agnostic principles this standard instantiates
235
+ - `.claude/rules/destructive-operations.md` — agent self-assessment companion
236
+ - `.claude/rules/security.md` — web-layer rule (`.ts/.tsx/.json/.env/Dockerfile` scope); this standard extends to bash
237
+ - `.claude/rules/testing-tier-config.md` — Tier 0 strict-TDD discipline for hooks
238
+ - `.claude/rules/defensive-bash.md` — companion methodology rule (auto-loaded; points here)
239
+ - `.github/workflows/shellcheck.yml` (Phase X-4) — CI enforcement
240
+ - bassclef#1054 — `log()` quiet-mode bug (strict-mode would have caught at write-time)
241
+ - bassclef#1058 — auto-save scope hole (fail-safe-defaults + least-privilege violation)
242
+ - docs/iteration-bets/2026-06-17a-secure-coding-foundations-longrun.md — goal authoring this standard
243
+
244
+ ## Retirement
245
+
246
+ This standard retires only if bassclef migrates off bash for its hook implementation language (e.g., adopting Python or Go for hooks). The 7 disciplines themselves remain valid; the language-specific instantiation changes.
@@ -0,0 +1,232 @@
1
+ ---
2
+ tier: lite
3
+ description: .claude/bassclef-configs.jsonc is the unified configuration discovery surface for bassclef adoption.
4
+ ---
5
+
6
+ # bassclef-configs Schema
7
+
8
+ `.claude/bassclef-configs.jsonc` is the **unified configuration discovery surface** for bassclef adoption. One file. Read the inline comments. Edit the values.
9
+
10
+ ## Why this exists
11
+
12
+ Before this standard, adopter configuration lived in four places:
13
+
14
+ | Surface | What it holds | Adopter discovery cost |
15
+ |---|---|---|
16
+ | `.claude/settings.json` | hooks, permissions, environment | high (Claude Code platform format) |
17
+ | `substrate.config.md` | resource references (Doc IDs, URLs) | medium (markdown frontmatter) |
18
+ | `.claude/agents/<role>.md` frontmatter | per-agent `model_tier` | low (already structured) |
19
+ | Hook env vars | per-session disables | high (no central registry) |
20
+
21
+ The new file consolidates substrate-level configuration into one surface. `substrate.config.md` keeps resource references (its existing job). `.claude/bassclef-configs.jsonc` holds the bassclef-adoption settings.
22
+
23
+ ## File format — JSONC
24
+
25
+ JSON with comments. Standard tooling supports it directly (VS Code, IntelliJ, most editors). Strict JSON parsers strip comments first:
26
+
27
+ ```bash
28
+ perl -pe 's,^\s*//.*$,,; s,/\*.*?\*/,,g' .claude/bassclef-configs.jsonc | jq .
29
+ ```
30
+
31
+ The hook layer (`bassclef-sync.sh` and others reading the file) handles the comment strip before passing to `jq`.
32
+
33
+ ## Three-question comment discipline
34
+
35
+ Every setting carries a comment block answering three questions:
36
+
37
+ 1. **What does this setting do** — plain English, /kiss-passed for grade-11 readability. One paragraph max.
38
+ 2. **What's the default + why** — adopter vs operator distinction where audiences diverge. State both defaults inline.
39
+ 3. **Which substrate component does this control** — file path or skill name or ADR reference. Adopter can read deeper.
40
+
41
+ Optional fourth line:
42
+
43
+ 4. **Schema reference** — bassclef ticket or ADR governing the setting.
44
+
45
+ ## Concrete shape
46
+
47
+ ```jsonc
48
+ {
49
+ // Whether bassclef's substrate (skills, rules, hooks, agents) syncs from
50
+ // the upstream bassclef repo to your local .claude/ directory at session start.
51
+ // Adopter default: false (opt-in trust posture; you control when updates land).
52
+ // Operator default: true (substrate maintainers want always-latest).
53
+ // Pairs with: .claude/hooks/bassclef-sync.sh
54
+ // Schema reference: bassclef#900 sync opt-in default
55
+ "sync": { "enabled": true },
56
+
57
+ // Per-agent LLM model routing. Maps agent role to capability tier.
58
+ // Pairs with: .claude/agents/<role>.md frontmatter (model_tier field)
59
+ // Schema reference: bassclef#873 model_tier dogfood
60
+ "model_tier": { "Builder": "balanced" },
61
+
62
+ // Adopter plan tier. Caps concurrent parallel agent dispatch per Anthropic plan limits.
63
+ // Pairs with: .claude/skills/longrun/SKILL.md parallel-dispatch logic
64
+ // Schema reference: bassclef#877 parallel-dispatch ceiling per adopter plan tier
65
+ "plan_tier": "tier-1"
66
+ }
67
+ ```
68
+
69
+ ## Adopter vs operator default distinction
70
+
71
+ Two roles, two defaults. The mechanism for runtime resolution:
72
+
73
+ | Context | File state | Defaults applied |
74
+ |---|---|---|
75
+ | Operator (bassclef's own repo) | file present with operator-default values | `sync.enabled: true`, etc. |
76
+ | Adopter clone | file absent OR present with adopter defaults | `sync.enabled: false`, etc. |
77
+ | Adopter clone after `/onboard-repo` | file written by skill with adopter defaults | adopter defaults applied |
78
+
79
+ Adopter-mode detection (basic version): hook checks if current repo's `origin` remote URL is `sunj-labs/bassclef`. If yes → operator. If no → adopter.
80
+
81
+ Per-setting runtime resolution detail in each setting's comment block. Hook layer (`bassclef-sync.sh` and others) implements the resolution.
82
+
83
+ ## What this is NOT
84
+
85
+ - **Not a replacement for `settings.json`** — `.claude/settings.json` stays as the Claude Code platform format (hooks array, permissions, environment). This new file is bassclef's adoption layer above it.
86
+ - **Not a replacement for `substrate.config.md`** — `substrate.config.md` stays as the resource-reference single source (Doc IDs, URLs, env-var names). This new file holds bassclef-adoption settings.
87
+ - **JSON-Schema-validated as of bassclef#1135** — Shape contract at `standards/state-spine/schemas/bassclef-configs.schema.json`. Tier 0 strict-TDD tests under `standards/state-spine/schemas/tests/bassclef-configs.test.sh`. Per-block `additionalProperties:false` catches typos; root-level `additionalProperties:true` keeps the file forward-compat for downstream T3-T24 work.
88
+
89
+ ## Adopter-default vs operator-default per field
90
+
91
+ Adopters and operators get different defaults from the same surface. `/onboard-repo` writes the adopter-default seed; bassclef's own repo ships operator-default values. Per-field summary:
92
+
93
+ | Block / field | Adopter default | Operator default | Why the difference |
94
+ |---|---|---|---|
95
+ | `sync.enabled` | `false` | `true` | Adopters control update cadence; operators want always-latest |
96
+ | `model_tier.Builder` | `balanced` | `balanced` | Code quality matters everywhere |
97
+ | `model_tier.<reviewer-class>` | `cheap-fast` | `cheap-fast` | Checklist work; Haiku handles it cleanly |
98
+ | `model_tier.Shaper` | `capable` | `capable` | Problem framing is highest-leverage; Opus earns its keep |
99
+ | `plan_tier` | `tier-1` | `tier-1` | Single-agent serial is the safe default for both |
100
+ | `prose_discipline.kiss_words_turn_prose` | `true` | `true` | Plain prose helps everyone reading agent output |
101
+ | `testing.global_floor` | `1` (WARN) | `1` (WARN) | Both audiences want the test-with prompt by default |
102
+ | `testing.path_matchers` | `[]` | seed list (hooks Tier 0, etc.) | Operators carry bassclef's substrate-internal matchers; adopters add their own at `/onboard-repo` Phase 2.x |
103
+ | `tech_stack` | declared at onboarding | reference operator stack | Per-adopter; bassclef declares its own as reference |
104
+ | `longrun.orchestrator_merge.mode` | `operator-gated` | `operator-gated` | Safest mode wins by default for both |
105
+ | `hook_chain.<hook>` | `true` for foundation hooks; explicit opt-in for new layers | `true` for everything substrate ships | Adopters layer in disciplines; operators run the full chain |
106
+ | `discipline_layers.<layer>` | `"advisory"` for new disciplines | `true` / strict for shipped disciplines | Adopters get the easier on-ramp; operators dogfood the strict path |
107
+ | `security_scanning.stack` | auto-detected at `/onboard-repo` Phase 2.5 | per repo | Both pick a stack; off by default until adopter confirms |
108
+ | `security_scanning.block_on_high_severity` | `true` | `true` | Production-bound work blocks on highs; early exploratory opts down |
109
+
110
+ Adopter-mode detection (basic version): hook checks if the current repo's `origin` remote URL points at `sunj-labs/bassclef`. If yes → operator. If no → adopter. Per-setting comments in the JSONC file restate the distinction inline for adopter discoverability.
111
+
112
+ ## When to add a setting
113
+
114
+ A new setting belongs in `bassclef-configs.jsonc` when:
115
+
116
+ 1. It controls bassclef's adoption behavior (not Claude Code platform behavior — that's `settings.json`)
117
+ 2. Multiple hooks or skills read it (not just one — single-hook settings stay in hook env vars)
118
+ 3. It has a clear three-question comment block answer
119
+ 4. It pairs with a substrate component the adopter can read
120
+
121
+ If the setting fails any of those, file an issue first and discuss before adding.
122
+
123
+ ## Migration path
124
+
125
+ Settings currently scattered across other surfaces migrate into `bassclef-configs.jsonc` over time:
126
+
127
+ | Setting | Current home | Migration target | Tracking |
128
+ |---|---|---|---|
129
+ | Per-agent `model_tier` | `.claude/agents/<role>.md` frontmatter | `model_tier` block in bassclef-configs | bassclef#873 → afternoon work |
130
+ | Sync enabled / disabled | `.no-bassclef-sync` sentinel + env vars | `sync.enabled` block | bassclef#900 |
131
+ | Parallel-dispatch ceiling | not yet implemented | `plan_tier` block | bassclef#877 |
132
+ | Testing tier per path | not yet implemented (honor-system `.claude/rules/testing.md`) | `testing` block (global_floor + path_matchers) | bassclef#1037 |
133
+ | Hook enable flags | scattered across per-hook env vars | `hook_chain` block (named boolean fields, forward-compat) | bassclef#1135 (T2 seed; T3-T24 wire individual hooks to read) |
134
+ | Discipline enable / mode | scattered across per-rule env vars | `discipline_layers` block (bool or "advisory"/"strict"/"off" mode) | bassclef#1135 (T2 seed) |
135
+ | Security scanner adapter | inline at `/onboard-repo` Phase 2.5 | `security_scanning` block (stack + additional_scanners + block_on_high_severity) | bet 2026-06-17a Phase Y + bassclef#1135 |
136
+
137
+ Migration preserves backward compatibility — old surfaces continue working during the migration window; the new file becomes the source of truth as each setting migrates.
138
+
139
+ ## Composes with
140
+
141
+ - `standards/substrate-config-schema.md` — sibling for resource references (Doc IDs, URLs)
142
+ - `.claude/bassclef-configs.jsonc` — the file itself (this standard's primary subject)
143
+ - `standards/state-spine/schemas/bassclef-configs.schema.json` — JSON Schema shape contract (bassclef#1135 WU-4)
144
+ - `.claude/skills/onboard-repo/SKILL.md` — writes adopter-default file on first install
145
+ - `.claude/hooks/bassclef-sync.sh` — first consumer (per bassclef#900)
146
+ - `.claude/rules/testing-tier-config.md` — owns the `testing` section reasoning (bassclef#1037)
147
+ - `.claude/hooks/testing-tier-enforce.sh` — testing-section consumer (bassclef#1037 WU-3)
148
+ - `standards/state-spine/schemas/testing-tier-overrides.schema.json` — per-file override entries that take precedence over the testing.path_matchers array (bassclef#1037)
149
+ - `standards/security-scanner-adapter.md` — owns the `security_scanning` section reasoning (bet 2026-06-17a Phase Y); supplies per-stack scanner default sets
150
+ - `config/security-scanners/<stack>.yml` — per-stack reference workflows (Phase Y-3); adopter copies + customizes
151
+
152
+ ## Settings reference
153
+
154
+ ### `testing` (bassclef#1037)
155
+
156
+ Per-path testing-tier enforcement. Four tiers — 0 strict TDD / 1 test-with / 2 smoke / 3 manual verify — pick by blast radius. Most-specific path-matcher wins; `global_floor` applies when no entry matches.
157
+
158
+ | Field | Type | Default (adopter) | Default (operator) | What it does |
159
+ |---|---|---|---|---|
160
+ | `global_floor` | integer 0-3 | 1 | 1 | Tier applied when no path_matcher matches. Tier 1 (WARN on missing test) is the cautious default — adopters add stricter tiers per surface as discipline matures. |
161
+ | `path_matchers` | array of `{match, tier}` | `[]` | seeded list (hooks Tier 0, schemas Tier 0, scripts Tier 1, narrative Tier 3) | Per-path tier overrides. Array order is most-specific to least-specific; first match wins. Glob patterns supported via shell-glob matching. |
162
+
163
+ Per-file overrides live in `state/testing-tier-overrides.jsonl` (append-only JSONL; schema at `standards/state-spine/schemas/testing-tier-overrides.schema.json`). The hook walks overrides first, then path_matchers, then global_floor. Overrides carry a timestamp and optional expiry to time-bound relief.
164
+
165
+ The rule `.claude/rules/testing-tier-config.md` carries the full reasoning, per-tier semantics, and override discipline. The hook `.claude/hooks/testing-tier-enforce.sh` (WU-3) is the mechanical enforcement layer.
166
+
167
+ ### `security_scanning` (bassclef bet 2026-06-17a Phase Y)
168
+
169
+ Per-stack security scanner adapter configuration. Adopter declares the stack; bassclef-supplied reference workflows use the default scanner set from `standards/security-scanner-adapter.md` stack reference matrix.
170
+
171
+ | Field | Type | Default (adopter) | Default (operator) | What it does |
172
+ |---|---|---|---|---|
173
+ | `stack` | string OR null | `null` | adopter-set when bassclef onboards | Stack name from the matrix in `standards/security-scanner-adapter.md` — one of `node-typescript`, `python`, `ruby`, `java`, `go`, `custom`, or `null` (OFF). `null` = no scanners configured; `/onboard-repo` prompts at next session. |
174
+ | `additional_scanners` | array of strings | `[]` | `[]` | Names of additional scanners beyond the stack defaults (e.g., commercial tools like `snyk`, `veracode`). Names are advisory; adopter writes their own workflow steps. |
175
+ | `block_on_high_severity` | boolean | `true` | `true` | Block CI on high-severity findings (workflow exits non-zero). When `false`, findings post as advisory comments only. Recommended `true` for production-bound work. |
176
+
177
+ Stack-gated opt-in: the reference workflow's `if: hashFiles('.claude/bassclef-configs.jsonc') == '' || fromJSON(...).security_scanning.stack == null` skips the entire job when `stack` is null. New adopters get OFF-by-default; explicit stack choice activates scanners.
178
+
179
+ The block name `security_scanning` is intentionally independent of `.claude/bassclef-configs.jsonc`'s file name. If the file is later renamed (per the deferred bassclef rename event under ADR-022), this block's semantics persist; only the file path changes.
180
+
181
+ The standard `standards/security-scanner-adapter.md` carries the per-stack default scanner set + adapter pattern. The skill `/onboard-repo` (Phase Y-4) writes the stack value at install time.
182
+
183
+ ### `longrun` (bassclef#1064)
184
+
185
+ Configures /longrun's autonomous PR merge cadence. Two modes, with hard ceilings the mode cannot relax. Pairs with `.claude/skills/longrun/SKILL.md` (procedure reads this block) and `.claude/rules/guardrails.md` (hard ceilings).
186
+
187
+ | Field | Type | Default (adopter) | Default (operator) | What it does |
188
+ |---|---|---|---|---|
189
+ | `orchestrator_merge.mode` | string enum | `operator-gated` | `operator-gated` | `operator-gated` — every PR opened during /longrun pauses for operator review + merge (safest; default for adopters learning bassclef). `agent-merges-within-scope` — orchestrator merges PRs autonomously when the change is within the goal's declared scope AND does not hit a hard ceiling (operator-sleep mode; for solo operators with full-time jobs running /longrun overnight). |
190
+ | `orchestrator_merge.hard_ceilings` | array of strings | `[auth, schema, security, prod-deploy, blast-radius-floor]` | `[auth, schema, security, prod-deploy, blast-radius-floor]` | Non-overridable list of change categories that ALWAYS pause for operator regardless of mode. Operators can ADD entries; the SKILL refuses removals. Hard ceilings are the guardrails bassclef#1064 made explicit so adopters see the trade-off. |
191
+
192
+ Three motivations baked into the schema:
193
+
194
+ 1. **Operator-sleep mode** — solo operators with full-time jobs run /longrun overnight; orchestrator-merge mode keeps the queue moving while they sleep. Validated 2026-06-17 (17 PRs / 64 min via verbal authorization during Phase B); bassclef#1064 codifies the configuration surface so adopters opt in per-/longrun.
195
+ 2. **Discipline-teaching surface** — the toggle exposes WHY orchestrator-merge is constrained. Pair the surface with a teaching panel mapping hard ceilings to bassclef's discipline principles. Adopters learn what bassclef considers safe-to-automate vs requires-human.
196
+ 3. **Trust gradient** — adopters new to bassclef pick `operator-gated` while learning the substrate; adopters deep in bassclef pick `agent-merges-within-scope` for velocity. Same primitive serves both.
197
+
198
+ Backwards-compatible: missing `longrun` block defaults to `operator-gated` (per /longrun SKILL.md procedure). Existing /longrun invocations continue working without config changes.
199
+
200
+ Per-PR override syntax (a single PR pauses regardless of mode) is out of scope for V1; the hard-ceiling list covers the safety case. Operator can name a one-off pause via verbal interjection ("pause on this one").
201
+
202
+ ### `wiki_sync` (bassclef#1265)
203
+
204
+ Configures whether the adopter's repo runs the bassclef-docs-sync workflow that syncs allowlisted docs to the GitHub Wiki on push-to-main. Pairs with `.claude/skills/docs-sync/SKILL.md` (reads this block at runtime), `.claude/rules/session-artifacts.md` § Wiki-as-we-go discipline (methodology rule), `presence/install/bassclef-docs-sync.template.yml` (the workflow adopters vendor), `presence/install/docs-sync-allowlist.template.md` (the allowlist seed).
205
+
206
+ | Field | Type | Default (adopter) | Default (operator) | What it does |
207
+ |---|---|---|---|---|
208
+ | `enabled` | boolean | `false` | `false` | When `true`, /onboard-repo Phase 2.3.8 surfaces the vendoring stub. Phase 2 of bet 2026-06-20b ships full auto-vendoring of the workflow + allowlist templates. Bassclef itself runs the workflow directly (not via template) because it's the bassclef source; the operator-default `false` is correct for bassclef's own repo. |
209
+ | `target_wiki_repo` | string | `""` | `""` | Override target — owner/repo of the GitHub wiki to sync to. Empty string defaults to current repo's wiki (the `.wiki` suffix on the repo URL). Most adopters leave empty. |
210
+ | `allowlist_path` | string | `standards/docs-sync-allowlist.md` | `standards/docs-sync-allowlist.md` | Adopter-side path to the docs-sync allowlist. Used by /docs-sync skill to locate the operator-readable contract. |
211
+
212
+ Three motivations:
213
+
214
+ 1. **Discipline-mechanism pairing** — `wiki-as-we-go` rule (bassclef#1208) propagates to adopters via `additionalDirectories` but the workflow that enforces it does not — it lives in bassclef's own `.github/` and its allowlist names bassclef paths. Adopters answering "yes" to the closeout question have nowhere for the mechanism to fire. This block lets them opt in.
215
+ 2. **Cold-adopter friction** — without this toggle + template, adopters who want wiki-sync have to hand-author the workflow + allowlist, multiplying the cost of adopting bassclef's documentation discipline.
216
+ 3. **Discoverability** — the toggle appears at /onboard-repo Phase 2.3.8 (Phase 1 stub today; full vendoring in Phase 2 of bet 2026-06-20b). Adopters see the option exists; they decide when to flip it.
217
+
218
+ Backwards-compatible: missing `wiki_sync` block defaults to `enabled: false`; bassclef's existing workflow keeps running for bassclef-public docs.
219
+
220
+ ## Refs
221
+
222
+ - bassclef#898 — adopter configuration discovery parent
223
+ - bassclef#899 — this standard's parent ticket
224
+ - bassclef#900 — sync opt-in default (first consumer)
225
+ - bassclef#873 — model_tier dogfood (migrating into schema)
226
+ - bassclef#877 — parallel-dispatch ceiling per plan tier
227
+ - bassclef#643 — substrate.config.md → YAML schema (sibling discipline)
228
+ - bassclef#1037 — testing-tier-config primitive (testing section + rule + hook)
229
+ - bassclef#1064 — /longrun orchestrator-merge toggle (longrun section)
230
+ - bassclef#1036 — Ousterhout luminary stub (sibling rule citation source)
231
+ - bassclef#1265 — wiki-sync mechanism adopter inheritance (wiki_sync section)
232
+ - bassclef#1208 — wiki-as-we-go discipline rule (methodology layer wiki_sync mechanizes)
@@ -0,0 +1,143 @@
1
+ ---
2
+ tier: lite
3
+ description: Bassclef evolves from three sources. Each source has a defined path to promotion. No standard enters bassclef without review.
4
+ ---
5
+
6
+ # Bassclef Evolution Standard
7
+
8
+ ## Principle
9
+
10
+ Bassclef evolves from three sources. Each source has a defined path
11
+ to promotion. No standard enters bassclef without review.
12
+
13
+ ## Three Sources
14
+
15
+ ### 1. User-proposed (explicit)
16
+
17
+ The operator identifies a pattern worth standardizing and invokes
18
+ `/promote` in an app repo.
19
+
20
+ **Path**: User runs `/promote` → issue created in app repo with
21
+ `bassclef-evolution` label → bassclef session reviews → accept/defer/reject.
22
+
23
+ **Examples**:
24
+ - "This hook pattern solved a real problem, other repos should have it"
25
+ - "I wrote a better diagnosis workflow, promote it"
26
+ - "This skill works, make it bassclef"
27
+
28
+ **Signal quality**: Highest. The operator saw the value firsthand.
29
+
30
+ ### 2. Hook-driven (automated detection)
31
+
32
+ Hooks detect patterns that suggest bassclef should evolve:
33
+ - Pre-build gate fires on a file type with no matching diagram check
34
+ - Session-end finds a new artifact type being written consistently
35
+ - Self-test discovers a skill requirement pattern across repos
36
+
37
+ **Path**: Hook logs the observation to `docs/sdlc-traces/` → bassclef
38
+ session-start hook aggregates traces → patterns with ≥3 occurrences
39
+ surface as promotion candidates.
40
+
41
+ **Examples**:
42
+ - "pre-build-gate triggered for .py files but has no Python-specific
43
+ diagram loading — should bassclef support Python projects?"
44
+ - "session-end wrote a new artifact type (design-token.json) in 3
45
+ consecutive sessions — should this be in the artifact chain?"
46
+
47
+ **Signal quality**: Medium. Frequency ≠ importance, but repeated
48
+ patterns are worth investigating.
49
+
50
+ ### 3. Agent-proposed (discovered during work)
51
+
52
+ An agent working in an app repo discovers that a local pattern should
53
+ be general. This happens during Construction when the Builder writes
54
+ something that the sdlc-gates checkpoint flags.
55
+
56
+ **Path**: Agent runs `/promote` (same as user-proposed, but agent-initiated)
57
+ → issue created with `bassclef-evolution` label + `agent-proposed` tag
58
+ → bassclef session reviews with extra scrutiny (agents over-promote).
59
+
60
+ **Examples**:
61
+ - Builder writes a hook in POA, sdlc-gates asks "Is this general?"
62
+ - Architect writes an ADR pattern that could be a template
63
+ - Reviewer flags a testing pattern that should be a standard
64
+
65
+ **Signal quality**: Variable. Agents tend to over-generalize. Review
66
+ with skepticism: "Would this actually help in a DIFFERENT repo?"
67
+
68
+ ## Ingestion Protocol (bassclef sessions)
69
+
70
+ The bassclef session-start hook scans for `bassclef-evolution` issues
71
+ across all child repos. During a bassclef session:
72
+
73
+ ### Triage
74
+
75
+ For each promotion candidate:
76
+
77
+ 1. **Is it general?** Would it help in a repo we haven't built yet?
78
+ If it only makes sense for POA's domain, reject.
79
+
80
+ 2. **Does it conflict?** Does it contradict an existing standard, ADR,
81
+ or design principle? If yes, the conflict must be resolved — either
82
+ the new pattern supersedes the old (update the ADR) or it's rejected.
83
+
84
+ 3. **Is it bassclef-shaped?** Does it fit as a skill, rule, standard,
85
+ hook, or agent definition? Or is it application logic wearing a
86
+ governance hat?
87
+
88
+ ### Actions
89
+
90
+ | Decision | Action | Issue |
91
+ |----------|--------|-------|
92
+ | Accept | Promote content to bassclef. Commit with `feat:` or `docs:`. | Close source issue |
93
+ | Defer | Not ready — needs more evidence or refinement | Keep open, add rationale |
94
+ | Reject | Not general enough, conflicts with existing standards, or app-specific | Close with explanation |
95
+
96
+ ### After acceptance
97
+
98
+ 1. Add the new content to bassclef (skill, rule, standard, etc.)
99
+ 2. Update CLAUDE.md counts if a new skill/standard was added
100
+ 3. Run `/substrate-check` to verify the substrate is still consistent
101
+ 4. Child repos pick up the change on next `boot-bassclef.sh` sync
102
+
103
+ ## Tracking
104
+
105
+ The bassclef session-start hook outputs a "BASSCLEF EVOLUTION — PENDING
106
+ PROMOTIONS" section showing all open `bassclef-evolution` issues across
107
+ child repos. This ensures promotions are never silently ignored.
108
+
109
+ Each child repo is registered in the session-start hook:
110
+ ```bash
111
+ CHILD_REPOS="sunj-labs/poa" # add new repos here
112
+ ```
113
+
114
+ ## What Triggers a Promotion Check
115
+
116
+ Not just `.claude/` changes — any change that establishes a pattern
117
+ other repos might need. The pre-commit hook flags these automatically.
118
+
119
+ | Change type | Examples | Hook detects |
120
+ |-------------|----------|-------------|
121
+ | Substrate files | skills, rules, hooks, agents in `.claude/` | yes |
122
+ | Settings | `settings.json`, model routing, hook config | yes |
123
+ | Package scripts | `package.json` script additions or changes | yes |
124
+ | Tooling config | `.eslintrc`, `tsconfig`, `.prettierrc`, `.env.example` | yes |
125
+ | Workflow patterns | testing approaches, deployment scripts, seed patterns | no — agent judgment |
126
+
127
+ Settings changes are the most commonly missed. When an app repo modifies
128
+ agent behavior or hook configuration in `settings.json`, that's almost
129
+ always a global decision. The hook flags it — don't dismiss the warning.
130
+
131
+ When unsure: promote. It's cheaper to reject a promotion in bassclef
132
+ than to rediscover the same pattern in a second repo.
133
+
134
+ ## Rules
135
+
136
+ - Promotions always originate in the SOURCE repo, never directly on bassclef
137
+ - App repos never need write access to bassclef
138
+ - The `bassclef-evolution` label is the signal — use it consistently
139
+ - Don't block app work on promotion decisions — log and move on
140
+ - Agent-proposed promotions get extra scrutiny (agents over-generalize)
141
+ - Hook-driven patterns need ≥3 occurrences before surfacing
142
+ - User-proposed patterns can be promoted immediately if clearly general
143
+ - When unsure whether a change is local or global → promote (default to global)