@thebassclef/lite 1.0.3 → 1.1.0
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.
- package/dist/cli.cjs +92 -6
- package/dist/cli.js +92 -6
- package/dist/index.cjs +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/lite/.claude/agents/architect.md +70 -0
- package/dist/lite/.claude/agents/builder.md +114 -0
- package/dist/lite/.claude/agents/designer.md +156 -0
- package/dist/lite/.claude/agents/reviewer.md +88 -0
- package/dist/lite/.claude/hooks/bassclef-sync.sh +85 -27
- package/dist/lite/.claude/hooks/longrun-prep-compounding-axis-check.sh +492 -0
- package/dist/lite/.claude/hooks/longrun-prep-render-check.sh +236 -0
- package/dist/lite/.claude/hooks/persona-name-scrub-check.sh +105 -0
- package/dist/lite/.claude/hooks/skill-step-list-check.sh +171 -0
- package/dist/lite/.claude/luminaries/alan-cooper.md +170 -0
- package/dist/lite/.claude/luminaries/alistair-cockburn.md +140 -0
- package/dist/lite/.claude/luminaries/amazon-pr-faq.md +34 -0
- package/dist/lite/.claude/luminaries/andreas-zeller.md +74 -0
- package/dist/lite/.claude/luminaries/ash-maurya.md +121 -0
- package/dist/lite/.claude/luminaries/bill-buxton.md +210 -0
- package/dist/lite/.claude/luminaries/charles-sanders-peirce.md +150 -0
- package/dist/lite/.claude/luminaries/david-ogilvy.md +192 -0
- package/dist/lite/.claude/luminaries/don-norman.md +173 -0
- package/dist/lite/.claude/luminaries/edward-tufte.md +179 -0
- package/dist/lite/.claude/luminaries/eric-evans.md +160 -0
- package/dist/lite/.claude/luminaries/frederick-brooks.md +50 -0
- package/dist/lite/.claude/luminaries/gang-of-four.md +157 -0
- package/dist/lite/.claude/luminaries/glenford-myers.md +230 -0
- package/dist/lite/.claude/luminaries/hunt-thomas.md +115 -0
- package/dist/lite/.claude/luminaries/hyrum-wright.md +94 -0
- package/dist/lite/.claude/luminaries/jason-fried-dhh.md +46 -0
- package/dist/lite/.claude/luminaries/jesse-james-garrett.md +154 -0
- package/dist/lite/.claude/luminaries/john-ousterhout.md +94 -0
- package/dist/lite/.claude/luminaries/karl-popper.md +132 -0
- package/dist/lite/.claude/luminaries/kent-beck.md +168 -0
- package/dist/lite/.claude/luminaries/linus-torvalds.md +218 -0
- package/dist/lite/.claude/luminaries/martin-fowler.md +164 -0
- package/dist/lite/.claude/luminaries/michael-feathers.md +125 -0
- package/dist/lite/.claude/luminaries/michael-nygard.md +118 -0
- package/dist/lite/.claude/luminaries/robert-c-martin.md +164 -0
- package/dist/lite/.claude/luminaries/saltzer-schroeder.md +194 -0
- package/dist/lite/.claude/luminaries/sophia-prater.md +193 -0
- package/dist/lite/.claude/luminaries/stephen-toulmin.md +131 -0
- package/dist/lite/.claude/luminaries/tony-hoare.md +170 -0
- package/dist/lite/.claude/luminaries/vaughn-vernon.md +50 -0
- package/dist/lite/.claude/luminaries/w-edwards-deming.md +158 -0
- package/dist/lite/.claude/rules/accessor-library-discipline.md +110 -0
- package/dist/lite/.claude/rules/adr-discipline.md +96 -0
- package/dist/lite/.claude/rules/api-conventions.md +115 -0
- package/dist/lite/.claude/rules/artifact-ingestion.md +137 -0
- package/dist/lite/.claude/rules/assert-only-after-verify.md +111 -0
- package/dist/lite/.claude/rules/blocked-items.md +139 -0
- package/dist/lite/.claude/rules/bootstrap-pair-discipline.md +106 -0
- package/dist/lite/.claude/rules/branching.md +28 -0
- package/dist/lite/.claude/rules/cold-adopter-harness-discipline.md +93 -0
- package/dist/lite/.claude/rules/commit-conventions.md +22 -0
- package/dist/lite/.claude/rules/compounding-axis-fresh-analysis.md +173 -0
- package/dist/lite/.claude/rules/compounding-sequence-fresh-analysis.md +173 -0
- package/dist/lite/.claude/rules/context-engineering.md +155 -0
- package/dist/lite/.claude/rules/context-management.md +85 -0
- package/dist/lite/.claude/rules/defensive-bash.md +52 -0
- package/dist/lite/.claude/rules/deferred-actions.md +233 -0
- package/dist/lite/.claude/rules/destructive-operations.md +69 -0
- package/dist/lite/.claude/rules/diagnosis.md +38 -0
- package/dist/lite/.claude/rules/github-issue-flash-tweet.md +114 -0
- package/dist/lite/.claude/rules/guardrails.md +73 -0
- package/dist/lite/.claude/rules/hook-wire-on-author.md +77 -0
- package/dist/lite/.claude/rules/identifier-leak-prevention.md +73 -0
- package/dist/lite/.claude/rules/iteration-bet-brief-completeness.md +43 -0
- package/dist/lite/.claude/rules/lite-manifest-schema-change-discipline.md +79 -0
- package/dist/lite/.claude/rules/longrun-prep-plan-doc-compression.md +77 -0
- package/dist/lite/.claude/rules/loop-discipline.md +71 -0
- package/dist/lite/.claude/rules/manual-prod-approval.md +100 -0
- package/dist/lite/.claude/rules/marker-enrichment-discipline.md +72 -0
- package/dist/lite/.claude/rules/mobile-ephemeral-session.md +109 -0
- package/dist/lite/.claude/rules/new-dependency-check.md +44 -0
- package/dist/lite/.claude/rules/oo-ad-entry-point.md +95 -0
- package/dist/lite/.claude/rules/operator-facing-prose.md +177 -0
- package/dist/lite/.claude/rules/option-label-discipline.md +82 -0
- package/dist/lite/.claude/rules/pattern-annotation.md +83 -0
- package/dist/lite/.claude/rules/persona-name-leak-scrub.md +90 -0
- package/dist/lite/.claude/rules/plain-english-discipline.md +132 -0
- package/dist/lite/.claude/rules/plan-enumeration-needs-value-props.md +177 -0
- package/dist/lite/.claude/rules/pr-body-shape.md +195 -0
- package/dist/lite/.claude/rules/pr-strategy.md +142 -0
- package/dist/lite/.claude/rules/pr-title-shape.md +90 -0
- package/dist/lite/.claude/rules/prototype-workflow.md +53 -0
- package/dist/lite/.claude/rules/reserved-skill-names.md +103 -0
- package/dist/lite/.claude/rules/schema-management.md +42 -0
- package/dist/lite/.claude/rules/sdlc-gates.md +149 -0
- package/dist/lite/.claude/rules/security.md +37 -0
- package/dist/lite/.claude/rules/session-artifacts.md +236 -0
- package/dist/lite/.claude/rules/skill-composition-declarations.md +105 -0
- package/dist/lite/.claude/rules/skill-description-clarity.md +196 -0
- package/dist/lite/.claude/rules/skill-procedure-step-list.md +119 -0
- package/dist/lite/.claude/rules/sprint-prep-preset-picker.md +76 -0
- package/dist/lite/.claude/rules/state-schema-validation.md +156 -0
- package/dist/lite/.claude/rules/stuck-signal-diagnostic.md +111 -0
- package/dist/lite/.claude/rules/substrate-config-schema.md +85 -0
- package/dist/lite/.claude/rules/test-list-discipline.md +129 -0
- package/dist/lite/.claude/rules/test-sufficiency.md +186 -0
- package/dist/lite/.claude/rules/testing-tier-config.md +125 -0
- package/dist/lite/.claude/rules/testing.md +38 -0
- package/dist/lite/.claude/rules/turn-estimate-grounding.md +82 -0
- package/dist/lite/.claude/rules/visual-hierarchy.md +427 -0
- package/dist/lite/.claude/rules/we-dont-break-adopters.md +103 -0
- package/dist/lite/.claude/rules/whereami-load-bearing.md +184 -0
- package/dist/lite/.claude/rules/writing-craft-discipline.md +72 -0
- package/dist/lite/.claude/rules/wu-sequencing-compounds.md +119 -0
- package/dist/lite/.claude/skills/build/SKILL.md +640 -0
- package/dist/lite/.claude/skills/chronicle/SKILL.md +55 -0
- package/dist/lite/.claude/skills/clean-artifacts/SKILL.md +249 -0
- package/dist/lite/.claude/skills/decompose/SKILL.md +280 -0
- package/dist/lite/.claude/skills/diagnose/SKILL.md +297 -0
- package/dist/lite/.claude/skills/feynman/SKILL.md +90 -0
- package/dist/lite/.claude/skills/howdoi/SKILL.md +105 -0
- package/dist/lite/.claude/skills/ia-model/SKILL.md +108 -0
- package/dist/lite/.claude/skills/interaction-design/SKILL.md +112 -0
- package/dist/lite/.claude/skills/interpret-input/SKILL.md +180 -0
- package/dist/lite/.claude/skills/journal/SKILL.md +209 -0
- package/dist/lite/.claude/skills/kiss/SKILL.md +449 -0
- package/dist/lite/.claude/skills/launch/SKILL.md +915 -0
- package/dist/lite/.claude/skills/lean-canvas/SKILL.md +332 -0
- package/dist/lite/.claude/skills/longrun/SKILL.md +512 -0
- package/dist/lite/.claude/skills/luminary/SKILL.md +481 -0
- package/dist/lite/.claude/skills/ogilvy-writing-audit/SKILL.md +177 -0
- package/dist/lite/.claude/skills/onboard-repo/SKILL.md +1640 -0
- package/dist/lite/.claude/skills/pattern-review/SKILL.md +99 -0
- package/dist/lite/.claude/skills/personas/SKILL.md +207 -0
- package/dist/lite/.claude/skills/promote/SKILL.md +283 -0
- package/dist/lite/.claude/skills/requirement/SKILL.md +98 -0
- package/dist/lite/.claude/skills/retro/SKILL.md +117 -0
- package/dist/lite/.claude/skills/riff/SKILL.md +114 -0
- package/dist/lite/.claude/skills/roadmap-reconcile/SKILL.md +163 -0
- package/dist/lite/.claude/skills/session-end/SKILL.md +309 -0
- package/dist/lite/.claude/skills/session-log/SKILL.md +299 -0
- package/dist/lite/.claude/skills/skills/SKILL.md +228 -0
- package/dist/lite/.claude/skills/spec/SKILL.md +105 -0
- package/dist/lite/.claude/skills/sprint/SKILL.md +418 -0
- package/dist/lite/.claude/skills/stage/SKILL.md +384 -0
- package/dist/lite/.claude/skills/state-a-problem/SKILL.md +185 -0
- package/dist/lite/.claude/skills/temperance/SKILL.md +108 -0
- package/dist/lite/.claude/skills/use-case/SKILL.md +417 -0
- package/dist/lite/.claude/skills/user-stories/SKILL.md +268 -0
- package/dist/lite/.claude/skills/value-prop/SKILL.md +251 -0
- package/dist/lite/.claude/skills/verify/SKILL.md +160 -0
- package/dist/lite/.claude/skills/visual-review/SKILL.md +503 -0
- package/dist/lite/.claude/skills/whats-the-plan/SKILL.md +202 -0
- package/dist/lite/.claude/skills/whereami/SKILL.md +307 -0
- package/dist/lite/AGENTS.md +79 -0
- package/dist/lite/CLAUDE-lite.md +85 -0
- package/dist/lite/CODE_OF_CONDUCT.md +28 -0
- package/dist/lite/CONTRIBUTING.md +177 -0
- package/dist/lite/README.md +173 -0
- package/dist/lite/SECURITY.md +19 -0
- package/dist/lite/architecture/decisions/ADR-029-release-pipeline.md +79 -0
- package/dist/lite/architecture/decisions/ADR-031-non-breaking-changes-adopter-discipline.md +139 -0
- package/dist/lite/architecture/decisions/ADR-032-adopter-sync-dispatcher-architecture.md +192 -0
- package/dist/lite/architecture/decisions/ADR-039-release-tagging-scheme.md +145 -0
- package/dist/lite/architecture/decisions/ADR-040-planning-skill-vocabulary-and-lite-profile.md +155 -0
- package/dist/lite/architecture/decisions/ADR-044-unified-skill-body-template.md +162 -0
- package/dist/lite/lib/clean-artifacts-sweep.sh +112 -0
- package/dist/lite/lib/code-comment-discipline.sh +144 -0
- package/dist/lite/lib/composer-preflight.sh +459 -0
- package/dist/lite/lib/deferred-actions.sh +146 -0
- package/dist/lite/lib/hook-header-parser.sh +61 -0
- package/dist/lite/lib/hook-heartbeat.sh +152 -0
- package/dist/lite/lib/hook-inject.sh +255 -0
- package/dist/lite/lib/hook-installer.sh +195 -0
- package/dist/lite/lib/luminary-pick.sh +96 -0
- package/dist/lite/lib/output-discipline.sh +143 -0
- package/dist/lite/lib/prose-scan-boundary.sh +171 -0
- package/dist/lite/lib/rewrite-check.sh +214 -0
- package/dist/lite/lib/session-rescue.sh +151 -0
- package/dist/lite/lib/source-graph-walker.sh +277 -0
- package/dist/lite/lib/state.sh +1372 -0
- package/dist/lite/lib/telemetry.sh +205 -0
- package/dist/lite/lib/tier-check.sh +187 -0
- package/dist/lite/lib/tier-dependency-audit.sh +1088 -0
- package/dist/lite/presence/install/bassclef-hook-connect.sh +178 -0
- package/dist/lite/presence/install/bassclef-sync.dispatcher.template.sh +841 -0
- package/dist/lite/presence/install/bassclef-sync.template.sh +2278 -0
- package/dist/lite/presence/install/schedule-auto-save.cron.sh +88 -0
- package/dist/lite/presence/install/schedule-auto-save.taskscheduler.md +122 -0
- package/dist/lite/scripts/aggregate-telemetry.sh +217 -0
- package/dist/lite/scripts/analyze-tier-dependencies.sh +239 -0
- package/dist/lite/scripts/generate-lite-manifest.sh +505 -0
- package/dist/lite/scripts/generate-tier-manifest.sh +28 -0
- package/dist/lite/scripts/intent-drift-check.sh +456 -0
- package/dist/lite/scripts/lite-manifest-drift-check.sh +146 -0
- package/dist/lite/scripts/render-lite-manifest-doc.sh +150 -0
- package/dist/lite/standards/adr-template.md +86 -0
- package/dist/lite/standards/api-conventions/nextjs.md +84 -0
- package/dist/lite/standards/artifact-composition.md +209 -0
- package/dist/lite/standards/bash-hook-safety.md +246 -0
- package/dist/lite/standards/bassclef-configs-schema.md +232 -0
- package/dist/lite/standards/bassclef-evolution.md +143 -0
- package/dist/lite/standards/bassclef-internal-jargon.md +244 -0
- package/dist/lite/standards/bassclef-managed-sentinel.md +96 -0
- package/dist/lite/standards/bassclef-source-config.md +228 -0
- package/dist/lite/standards/branch-stacking.md +408 -0
- package/dist/lite/standards/code-safety-principles.md +176 -0
- package/dist/lite/standards/composer-prerequisites.md +155 -0
- package/dist/lite/standards/deferred-actions-schema.md +204 -0
- package/dist/lite/standards/dependency-discipline/cargo.md +39 -0
- package/dist/lite/standards/dependency-discipline/gem.md +43 -0
- package/dist/lite/standards/dependency-discipline/go-mod.md +41 -0
- package/dist/lite/standards/dependency-discipline/npm.md +42 -0
- package/dist/lite/standards/dependency-discipline/pip.md +42 -0
- package/dist/lite/standards/deployment-topology/ec2-tailscale.md +225 -0
- package/dist/lite/standards/deployment-topology.md +69 -0
- package/dist/lite/standards/docs-sync-allowlist.md +76 -0
- package/dist/lite/standards/domain-and-dns.md +145 -0
- package/dist/lite/standards/frontend-stack.md +67 -0
- package/dist/lite/standards/frontmatter-schema.md +154 -0
- package/dist/lite/standards/graceful-exit.md +227 -0
- package/dist/lite/standards/hook-idempotency.md +102 -0
- package/dist/lite/standards/hook-injection-discipline.md +202 -0
- package/dist/lite/standards/hook-install-class.md +215 -0
- package/dist/lite/standards/input-handler-interface.md +152 -0
- package/dist/lite/standards/lite-manifest-schema-changes.md +180 -0
- package/dist/lite/standards/lite-manifest.json +2797 -0
- package/dist/lite/standards/luminary-matching.md +105 -0
- package/dist/lite/standards/luminary-problem-patterns.md +481 -0
- package/dist/lite/standards/migration-discipline/active-record.md +50 -0
- package/dist/lite/standards/migration-discipline/alembic.md +43 -0
- package/dist/lite/standards/migration-discipline/gorm.md +50 -0
- package/dist/lite/standards/migration-discipline/prisma.md +53 -0
- package/dist/lite/standards/migration-discipline/sqlalchemy.md +51 -0
- package/dist/lite/standards/mobile-ephemeral-session.md +167 -0
- package/dist/lite/standards/model-routing-discipline.md +160 -0
- package/dist/lite/standards/ogilvy-writing-rules.md +225 -0
- package/dist/lite/standards/opener-discipline.md +96 -0
- package/dist/lite/standards/operator-facing-prose-discipline.md +201 -0
- package/dist/lite/standards/persona-schema.md +229 -0
- package/dist/lite/standards/pluggable-luminaries.md +323 -0
- package/dist/lite/standards/pr-body-discipline.md +115 -0
- package/dist/lite/standards/preview-state-schema.md +189 -0
- package/dist/lite/standards/project-directory-layout.md +276 -0
- package/dist/lite/standards/release-tagging.md +137 -0
- package/dist/lite/standards/reserved-skill-names.md +120 -0
- package/dist/lite/standards/scannable-multi-option-output.md +265 -0
- package/dist/lite/standards/sdlc-compliance.md +286 -0
- package/dist/lite/standards/sdlc-gates/typescript.md +57 -0
- package/dist/lite/standards/secrets-lifecycle.md +210 -0
- package/dist/lite/standards/security-scanner-adapter.md +145 -0
- package/dist/lite/standards/session-board.md +256 -0
- package/dist/lite/standards/skill-output-discipline.md +121 -0
- package/dist/lite/standards/state-spine-contract.md +255 -0
- package/dist/lite/standards/state-spine.md +511 -0
- package/dist/lite/standards/steering-hints/kiss-words.md +11 -0
- package/dist/lite/standards/substrate-config-schema.md +267 -0
- package/dist/lite/standards/tech-stack-config.md +109 -0
- package/dist/lite/standards/tier-dependency-analysis.md +167 -0
- package/dist/lite/standards/tier-runtime-deps/lite.md +57 -0
- package/dist/lite/standards/tier-tag-schema.md +155 -0
- package/dist/lite/standards/two-layer-config.md +99 -0
- package/dist/lite/standards/use-case-format.md +292 -0
- package/dist/lite/standards/user-story-invest.md +268 -0
- package/dist/lite/standards/velocity-and-appetite.md +229 -0
- package/dist/lite/standards/voice-input-pattern.md +119 -0
- package/dist/lite/standards/whereami-schema.md +301 -0
- package/dist/lite/standards/worktree-management.md +211 -0
- package/dist/lite/standards/writing-guide.md +213 -0
- package/dist/lite/templates/chronicle-template.md +75 -0
- package/dist/lite/templates/deferred-action-template.md +45 -0
- package/dist/lite/templates/memory-proposal-template.md +77 -0
- package/dist/lite/templates/persona-template.md +200 -0
- package/dist/lite/templates/pr-faq.md +45 -0
- package/dist/lite/templates/secret-rotation-template.md +162 -0
- package/dist/lite/templates/spec-template.md +131 -0
- package/dist/lite/templates/use-case-template.md +194 -0
- package/dist/lite/templates/user-story-template.md +107 -0
- package/dist/lite/templates/whereami-template.md +101 -0
- package/package.json +1 -1
|
@@ -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)
|