@thebassclef/lite 0.1.0 → 0.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (163) hide show
  1. package/dist/cli.cjs +40 -6
  2. package/dist/cli.js +40 -6
  3. package/dist/index.cjs +1 -1
  4. package/dist/index.d.ts +1 -1
  5. package/dist/index.js +1 -1
  6. package/package.json +1 -1
  7. package/substrate/.bassclef/lite-manifest.json +999 -92
  8. package/substrate/.claude/hooks/longrun-prep-compounding-axis-check.sh +492 -0
  9. package/substrate/.claude/hooks/longrun-prep-compounding-sequence-check.sh +492 -0
  10. package/substrate/.claude/hooks/pre-commit-gate.sh +1 -2
  11. package/substrate/.claude/hooks/turn-prose-kiss-check.sh +30 -1
  12. package/substrate/.claude/luminaries/glenford-myers.md +230 -0
  13. package/substrate/.claude/luminaries/hunt-thomas.md +115 -0
  14. package/substrate/.claude/luminaries/hyrum-wright.md +94 -0
  15. package/substrate/.claude/luminaries/michael-feathers.md +2 -2
  16. package/substrate/.claude/luminaries/tony-hoare.md +170 -0
  17. package/substrate/.claude/luminaries/vaughn-vernon.md +50 -0
  18. package/substrate/.claude/luminaries/w-edwards-deming.md +158 -0
  19. package/substrate/.claude/rules/accessor-library-discipline.md +138 -0
  20. package/substrate/.claude/rules/adr-discipline.md +120 -0
  21. package/substrate/.claude/rules/api-conventions.md +125 -0
  22. package/substrate/.claude/rules/bootstrap-pair-discipline.md +141 -0
  23. package/substrate/.claude/rules/cold-adopter-harness-discipline.md +129 -0
  24. package/substrate/.claude/rules/compounding-axis-fresh-analysis.md +188 -0
  25. package/substrate/.claude/rules/compounding-sequence-fresh-analysis.md +188 -0
  26. package/substrate/.claude/rules/defensive-bash.md +68 -0
  27. package/substrate/.claude/rules/deferred-actions.md +233 -0
  28. package/substrate/.claude/rules/github-issue-flash-tweet.md +156 -0
  29. package/substrate/.claude/rules/hook-wire-on-author.md +103 -0
  30. package/substrate/.claude/rules/iteration-bet-brief-completeness.md +54 -0
  31. package/substrate/.claude/rules/lite-manifest-schema-change-discipline.md +3 -3
  32. package/substrate/.claude/rules/longrun-prep-plan-doc-compression.md +89 -0
  33. package/substrate/.claude/rules/loop-discipline.md +81 -0
  34. package/substrate/.claude/rules/manual-prod-approval.md +100 -0
  35. package/substrate/.claude/rules/marker-enrichment-discipline.md +99 -0
  36. package/substrate/.claude/rules/mobile-ephemeral-session.md +109 -0
  37. package/substrate/.claude/rules/new-dependency-check.md +51 -0
  38. package/substrate/.claude/rules/option-label-discipline.md +108 -0
  39. package/substrate/.claude/rules/pattern-annotation.md +100 -0
  40. package/substrate/.claude/rules/plain-english-discipline.md +11 -9
  41. package/substrate/.claude/rules/plan-enumeration-needs-value-props.md +211 -0
  42. package/substrate/.claude/rules/pr-title-shape.md +161 -0
  43. package/substrate/.claude/rules/prototype-workflow.md +65 -0
  44. package/substrate/.claude/rules/reserved-skill-names.md +123 -0
  45. package/substrate/.claude/rules/schema-management.md +49 -0
  46. package/substrate/.claude/rules/security.md +37 -0
  47. package/substrate/.claude/rules/skill-composition-declarations.md +124 -0
  48. package/substrate/.claude/rules/skill-description-clarity.md +247 -0
  49. package/substrate/.claude/rules/skill-procedure-step-list.md +137 -0
  50. package/substrate/.claude/rules/stuck-signal-diagnostic.md +140 -0
  51. package/substrate/.claude/rules/substrate-config-schema.md +98 -0
  52. package/substrate/.claude/rules/test-list-discipline.md +175 -0
  53. package/substrate/.claude/rules/test-sufficiency.md +210 -0
  54. package/substrate/.claude/rules/testing-tier-config.md +145 -0
  55. package/substrate/.claude/rules/testing.md +38 -0
  56. package/substrate/.claude/rules/turn-estimate-grounding.md +134 -0
  57. package/substrate/.claude/rules/visual-hierarchy.md +437 -0
  58. package/substrate/.claude/rules/we-dont-break-adopters.md +126 -0
  59. package/substrate/.claude/rules/wu-sequencing-compounds.md +145 -0
  60. package/substrate/.claude/skills/build/SKILL.md +1 -1
  61. package/substrate/.claude/skills/chronicle/SKILL.md +55 -0
  62. package/substrate/.claude/skills/clean-artifacts/SKILL.md +249 -0
  63. package/substrate/.claude/skills/decompose/SKILL.md +1 -1
  64. package/substrate/.claude/skills/diagnose/SKILL.md +1 -1
  65. package/substrate/.claude/skills/feynman/SKILL.md +90 -0
  66. package/substrate/.claude/skills/howdoi/SKILL.md +1 -1
  67. package/substrate/.claude/skills/ia-model/SKILL.md +1 -1
  68. package/substrate/.claude/skills/interaction-design/SKILL.md +1 -1
  69. package/substrate/.claude/skills/interpret-input/SKILL.md +8 -8
  70. package/substrate/.claude/skills/journal/SKILL.md +209 -0
  71. package/substrate/.claude/skills/kiss/SKILL.md +1 -1
  72. package/substrate/.claude/skills/launch/SKILL.md +14 -23
  73. package/substrate/.claude/skills/lean-canvas/SKILL.md +1 -1
  74. package/substrate/.claude/skills/longrun/SKILL.md +45 -8
  75. package/substrate/.claude/skills/luminary/SKILL.md +1 -1
  76. package/substrate/.claude/skills/ogilvy-writing-audit/SKILL.md +1 -1
  77. package/substrate/.claude/skills/onboard-repo/SKILL.md +143 -709
  78. package/substrate/.claude/skills/pattern-review/SKILL.md +1 -1
  79. package/substrate/.claude/skills/personas/SKILL.md +5 -5
  80. package/substrate/.claude/skills/promote/SKILL.md +1 -1
  81. package/substrate/.claude/skills/requirement/SKILL.md +1 -1
  82. package/substrate/.claude/skills/retro/SKILL.md +1 -1
  83. package/substrate/.claude/skills/riff/SKILL.md +1 -1
  84. package/substrate/.claude/skills/roadmap-reconcile/SKILL.md +1 -1
  85. package/substrate/.claude/skills/session-end/SKILL.md +1 -1
  86. package/substrate/.claude/skills/session-log/SKILL.md +3 -3
  87. package/substrate/.claude/skills/skills/SKILL.md +1 -1
  88. package/substrate/.claude/skills/spec/SKILL.md +1 -1
  89. package/substrate/.claude/skills/sprint/SKILL.md +1 -1
  90. package/substrate/.claude/skills/stage/SKILL.md +1 -1
  91. package/substrate/.claude/skills/state-a-problem/SKILL.md +1 -1
  92. package/substrate/.claude/skills/temperance/SKILL.md +1 -1
  93. package/substrate/.claude/skills/use-case/SKILL.md +1 -1
  94. package/substrate/.claude/skills/user-stories/SKILL.md +1 -1
  95. package/substrate/.claude/skills/value-prop/SKILL.md +1 -1
  96. package/substrate/.claude/skills/verify/SKILL.md +1 -1
  97. package/substrate/.claude/skills/visual-review/SKILL.md +503 -0
  98. package/substrate/.claude/skills/whats-the-plan/SKILL.md +202 -0
  99. package/substrate/.claude/skills/whereami/SKILL.md +2 -2
  100. package/substrate/CONTRIBUTING.md +1 -1
  101. package/substrate/README.md +5 -5
  102. package/substrate/lib/prose-scan-boundary.sh +171 -0
  103. package/substrate/lib/tier-check.sh +50 -1
  104. package/substrate/lib/tier-dependency-audit.sh +159 -4
  105. package/substrate/presence/install/bassclef-sync.template.sh +1 -1
  106. package/substrate/scripts/generate-lite-manifest.sh +21 -5
  107. package/substrate/standards/adr-template.md +86 -0
  108. package/substrate/standards/api-conventions/nextjs.md +84 -0
  109. package/substrate/standards/artifact-composition.md +209 -0
  110. package/substrate/standards/bash-hook-safety.md +246 -0
  111. package/substrate/standards/branch-stacking.md +408 -0
  112. package/substrate/standards/code-safety-principles.md +176 -0
  113. package/substrate/standards/composer-prerequisites.md +155 -0
  114. package/substrate/standards/dependency-discipline/cargo.md +39 -0
  115. package/substrate/standards/dependency-discipline/gem.md +43 -0
  116. package/substrate/standards/dependency-discipline/go-mod.md +41 -0
  117. package/substrate/standards/dependency-discipline/npm.md +42 -0
  118. package/substrate/standards/dependency-discipline/pip.md +42 -0
  119. package/substrate/standards/deployment-topology/ec2-tailscale.md +225 -0
  120. package/substrate/standards/deployment-topology.md +69 -0
  121. package/substrate/standards/docs-sync-allowlist.md +4 -4
  122. package/substrate/standards/domain-and-dns.md +145 -0
  123. package/substrate/standards/frontend-stack.md +67 -0
  124. package/substrate/standards/frontmatter-schema.md +154 -0
  125. package/substrate/standards/hook-injection-discipline.md +202 -0
  126. package/substrate/standards/hook-install-class.md +215 -0
  127. package/substrate/standards/input-handler-interface.md +152 -0
  128. package/substrate/standards/lite-manifest-schema-changes.md +60 -0
  129. package/substrate/standards/luminary-matching.md +105 -0
  130. package/substrate/standards/migration-discipline/active-record.md +50 -0
  131. package/substrate/standards/migration-discipline/alembic.md +43 -0
  132. package/substrate/standards/migration-discipline/gorm.md +50 -0
  133. package/substrate/standards/migration-discipline/prisma.md +53 -0
  134. package/substrate/standards/migration-discipline/sqlalchemy.md +51 -0
  135. package/substrate/standards/mobile-ephemeral-session.md +167 -0
  136. package/substrate/standards/model-routing-discipline.md +160 -0
  137. package/substrate/standards/persona-schema.md +229 -0
  138. package/substrate/standards/pluggable-luminaries.md +323 -0
  139. package/substrate/standards/pr-body-discipline.md +115 -0
  140. package/substrate/standards/preview-state-schema.md +189 -0
  141. package/substrate/standards/reserved-skill-names.md +120 -0
  142. package/substrate/standards/scannable-multi-option-output.md +261 -0
  143. package/substrate/standards/sdlc-gates/typescript.md +57 -0
  144. package/substrate/standards/session-board.md +256 -0
  145. package/substrate/standards/state-spine-contract.md +255 -0
  146. package/substrate/standards/steering-hints/kiss-words.md +11 -0
  147. package/substrate/standards/substrate-config-schema.md +267 -0
  148. package/substrate/standards/tier-dependency-analysis.md +1 -1
  149. package/substrate/standards/tier-tag-schema.md +1 -1
  150. package/substrate/standards/two-layer-config.md +99 -0
  151. package/substrate/standards/use-case-format.md +292 -0
  152. package/substrate/standards/user-story-invest.md +268 -0
  153. package/substrate/standards/velocity-and-appetite.md +229 -0
  154. package/substrate/standards/voice-input-pattern.md +119 -0
  155. package/substrate/standards/worktree-management.md +211 -0
  156. package/substrate/templates/chronicle-template.md +75 -0
  157. package/substrate/templates/memory-proposal-template.md +77 -0
  158. package/substrate/templates/persona-template.md +200 -0
  159. package/substrate/templates/pr-faq.md +45 -0
  160. package/substrate/templates/secret-rotation-template.md +162 -0
  161. package/substrate/templates/spec-template.md +131 -0
  162. package/substrate/templates/use-case-template.md +194 -0
  163. package/substrate/templates/user-story-template.md +107 -0
@@ -0,0 +1,154 @@
1
+ ---
2
+ tier: lite
3
+ description: Schema for the YAML frontmatter that opens substrate files — .claude/skills/<name>/SKILL.md and .claude/rules/<name>.md.
4
+ ---
5
+
6
+ # Frontmatter Schema
7
+
8
+ Schema for the YAML frontmatter that opens substrate files — `.claude/skills/<name>/SKILL.md` and `.claude/rules/<name>.md`. Validated by `.claude/hooks/substrate-clarity-gate.sh` on Edit / Write (bassclef#862 Gap 1; WU-3 of bet 2026-06-18a).
9
+
10
+ Without write-time validation, `tech_stack_match:` declarations from WU-8 + WU-9, future `composes_with:` + `depends_on:` declarations from WU-15, and ordinary skill description fields ship with typos or missing required fields and only surface in adopter sessions. This schema closes the gap at the authoring surface.
11
+
12
+ ## When the hook fires
13
+
14
+ On any Edit / Write to:
15
+
16
+ - `.claude/skills/<name>/SKILL.md`
17
+ - `.claude/rules/<name>.md`
18
+
19
+ Other substrate surfaces (luminaries, chronicles, iteration goals, decompositions, journal entries) keep their existing validation rules and do not gain frontmatter-schema enforcement in WU-3.
20
+
21
+ ## What the hook validates
22
+
23
+ Three checks fire in order. The first to fail returns the exit code; further checks do not run.
24
+
25
+ | Check | Outcome | Exit |
26
+ |---|---|---|
27
+ | Frontmatter present at top of file (starts with `---`) | Required for files NOT on allowlist; missing → BLOCK | 2 |
28
+ | YAML parses cleanly | Malformed YAML → BLOCK | 2 |
29
+ | Required fields present + non-empty | Missing required → BLOCK | 2 |
30
+ | All field names are recognized | Unknown field → WARN; written to stderr | 0 |
31
+
32
+ The hook continues running existing checks (description length, INSTEAD-block, jargon ladder) after the schema pass.
33
+
34
+ ## Skill schema
35
+
36
+ Frontmatter required for every `.claude/skills/<name>/SKILL.md`.
37
+
38
+ **Required fields:**
39
+
40
+ - `name` — the skill's slash-command alias. Lowercase, hyphens, no spaces.
41
+ - `description` — operator-readable one-liner. Length + verb-first + plain-language checks per `.claude/rules/skill-description-clarity.md`.
42
+
43
+ **Recognized optional fields:**
44
+
45
+ | Field | Used by | Type |
46
+ |---|---|---|
47
+ | `args` | skill body (operator-visible args reference) | string |
48
+ | `authoring_luminaries` | skills that declare which luminary lenses shaped their design; picked via `/extract-intent` Voyage matching or `/pick-luminaries` | object (primary: list, supporting: list) |
49
+ | `composes_baseline` | `/launch`, `/riff-prototypes`, `/frontend-design`, `/visual-review` | list[string] (luminary slugs) |
50
+ | `composes_with` | future — WU-15 (bassclef#862 Gap 3) | list[string] (skill slugs) |
51
+ | `depends_on` | future — WU-15 (bassclef#862 Gap 3) | list[string] (skill slugs) |
52
+ | `deprecated` | retirement metadata | bool |
53
+ | `deprecated_decision` | retirement metadata | string |
54
+ | `deprecated_in_favor_of` | retirement metadata | string |
55
+ | `disable_friction_check` | `/promote`-skip discipline | bool |
56
+ | `disable_model_invocation` | Claude Code harness routing | bool |
57
+ | `maturity` | skills declaring lifecycle stage — `alpha`, `beta`, `stable`, `hardened` per ADR-043 | string |
58
+ | `model_tier` | per-agent LLM tier routing | string |
59
+ | `modes` | mode-bearing skills (e.g., `/longrun`) | list[string] |
60
+ | `no_user_modes` | mode-bearing-skill opt-out | bool |
61
+ | `prereqs` | runtime prerequisites — richer shape per bassclef-web#94 | object (see prereqs schema below) |
62
+ | `requires` | runtime prerequisites — older simpler shape | object (cli + network) |
63
+ | `reserved_name_override` | reserved-name-shadow allow path | string |
64
+ | `sizes` | size-bearing skills (e.g., `/value-prop`) | list[string] |
65
+ | `tech_stack_match` | future — stack-bound skills | object |
66
+ | `tiers` | tier-bearing skills (e.g., `/shape`) | list[string] |
67
+ | `user_invocable` | Claude Code harness routing | bool |
68
+
69
+ Unknown fields surface as WARN — adopter-authored fields might appear here; the warning surfaces the new field but does not block.
70
+
71
+ ## Prereqs schema (bassclef-web#94)
72
+
73
+ The `prereqs:` block splits runtime prerequisites into required + optional buckets so docs sites can render a signifier per bucket. Skills without a `prereqs:` block still work — docs render a generic "check the skill body" fallback.
74
+
75
+ ```yaml
76
+ prereqs:
77
+ required:
78
+ cli: [git, gh]
79
+ env: [ANTHROPIC_API_KEY]
80
+ network: true
81
+ optional:
82
+ cli: [jq]
83
+ env: [VOYAGE_API_KEY]
84
+ note: "VOYAGE_API_KEY enables semantic ranking; grep-only fallback works without."
85
+ ```
86
+
87
+ Design rules per ticket:
88
+
89
+ - Optional. Skills without the block still work.
90
+ - 4-8 lines typical; 12 lines max. Docs sites render as a collapsed `<details>` block by default (progressive disclosure per Cooper).
91
+ - Uses tool names adopters already know — `git`, `gh`, `python3`, `jq`, `curl`. No bassclef vocabulary.
92
+ - Zero prereqs beyond "you have Claude Code running" — skip the block entirely.
93
+
94
+ Relationship to `requires:`:
95
+
96
+ - `requires:` is the older simpler shape (cli + network only). Existing skills that use it keep working.
97
+ - `prereqs:` is the newer richer shape (required / optional split + env vars + note). Preferred for new lite skills.
98
+ - No migration required. Both fields are recognized. Adopters pick per skill.
99
+
100
+ Docs render logic is out of scope for bassclef — docs sites (Fumadocs or similar) read the manifest and render the signifier block. Bassclef's job is to define the schema and apply it as an exemplar.
101
+
102
+ ## Rule schema
103
+
104
+ Frontmatter is OPTIONAL for `.claude/rules/<name>.md`. Many existing rules carry no frontmatter and start with the body directly. When frontmatter IS present, it must conform.
105
+
106
+ **Required fields (when frontmatter is present):**
107
+
108
+ - `description` — one-line operator-readable description of what the rule enforces.
109
+
110
+ **Recognized optional fields:**
111
+
112
+ | Field | Used by | Type |
113
+ |---|---|---|
114
+ | `composes_with` | future — WU-15 (bassclef#862 Gap 3) | list[string] |
115
+ | `depends_on` | future — WU-15 (bassclef#862 Gap 3) | list[string] |
116
+ | `globs` | rule-routing (which file paths the rule applies to) | list[string] |
117
+ | `model_tier` | per-rule LLM tier routing | string |
118
+ | `tech_stack_match` | per-stack rule routing (WU-8 + WU-9; future Phase 2 work) | object — admits `lang`, `frontend`, `backend`, `orm`, `pkg_manager`, `deploy` per `standards/tech-stack-config.md` |
119
+
120
+ Unknown fields surface as WARN.
121
+
122
+ Rules with NO frontmatter pass through validation entirely (the schema applies only when frontmatter is present). Authors adding frontmatter to legacy rules pick the required + optional fields as appropriate.
123
+
124
+ ## Allowlist baseline
125
+
126
+ `.claude/hooks/substrate-frontmatter-allowlist.txt` grandfathers files that fail validation today with a 60-day grace window. Same shape as `testing-tier-enforce-allowlist.txt` per bassclef#1037.
127
+
128
+ Format: `<repo-relative-path>|<grace-until ISO 8601>`.
129
+
130
+ At WU-3 ship, the allowlist is empty — current files (75 skills + 19 rules with frontmatter + 33 rules without) all pass. The file ships with its header explaining the shape so future violators can be added with grace if/when they surface.
131
+
132
+ ## What this schema does NOT do
133
+
134
+ - Does not enforce field VALUE shape beyond presence + non-empty. `tech_stack_match` content is not validated against the `tech-stack.schema.json` ranges shipped in WU-2. That richer validation lives in the consumer-side hooks that USE the field (future Phase 3 work).
135
+ - Does not require frontmatter on legacy rules without one. 33 rules ship with no frontmatter today; the schema applies only when frontmatter IS present.
136
+ - Does not validate luminary, chronicle, iteration-bet, decomposition, or journal-entry frontmatter. Those surfaces have their own checks in the same hook.
137
+ - Does not catch description-quality issues — that's the existing `.claude/rules/skill-description-clarity.md` rule.
138
+
139
+ ## Override path
140
+
141
+ `SKIP_SUBSTRATE_CLARITY=1` — same env var as the rest of the hook's checks. Logged via trace-helper. Use sparingly.
142
+
143
+ ## Refs
144
+
145
+ - bassclef#862 Gap 1 — this schema closes it.
146
+ - bassclef#382 — substrate-clarity-gate hook (parent of this validation pass).
147
+ - WU-3 of bet `docs/iteration-bets/2026-06-18a-public-adopter-leverage-longrun.md` — ships the validation.
148
+ - Sister WU-15 (bassclef#862 Gap 3) — adds `composes_with` + `depends_on` field schemas + targets-exist validation.
149
+ - Pairs with `standards/tech-stack-config.md` (WU-2) — tech_stack_match values map to that schema's enums.
150
+ - Sister discipline: `.claude/rules/testing-tier-config.md` (bassclef#1037) — allowlist baseline pattern.
151
+
152
+ ## Retirement condition
153
+
154
+ This schema retires only if bassclef migrates off YAML frontmatter as a substrate convention. Field set evolves as new substrate fields ship (e.g., WU-15 introduces composes_with + depends_on into the recognized set).
@@ -0,0 +1,202 @@
1
+ ---
2
+ tier: lite
3
+ status: live
4
+ date: 2026-06-27
5
+ authority: ADR-035
6
+ references:
7
+ - {type: adr, id: ADR-035, anchor: hooks as steering surfaces}
8
+ - {type: rule, id: .claude/rules/cold-adopter-harness-discipline.md, anchor: per-PR harness gate}
9
+ - {type: rule, id: .claude/rules/testing-tier-config.md, anchor: Tier 0 strict-TDD on .claude/hooks/*.sh}
10
+ - {type: rule, id: .claude/rules/bootstrap-pair-discipline.md, anchor: hook ships with paired test + settings entry}
11
+ - {type: standard, id: standards/hook-install-class.md, anchor: install-class header pairs with this discipline}
12
+ - {type: standard, id: standards/mechanism-fidelity.md, anchor: audit verifies injection hooks fire correctly}
13
+ - {type: external, id: code.claude.com/docs/en/hooks, anchor: hook event taxonomy as of 2026-06-27}
14
+ luminaries:
15
+ primary: [hyrum-wright, tony-hoare]
16
+ supporting: [john-ousterhout, kent-beck, michael-nygard]
17
+ description: - ADR-035 (just shipped, 8632d15) — 9-surface hook taxonomy + block-vs-inject menu; this standard names the contract for the inject side - code.claude.com/docs/en/hooks (WebFetch 2026-06-27) — additionalContext injection JSON shape; 10K char limit…
18
+ ---
19
+
20
+ # Hook injection discipline
21
+
22
+ > **Anthropic docs reference:** Cites code.claude.com/docs/en/hooks as of 2026-06-27. Hook events and capabilities evolve. Before authoring a new injection hook, verify the event taxonomy and `additionalContext` capability against the current docs. The 10,000-character limit + JSON envelope shape + per-event injection support documented here may shift in future Claude Code releases.
23
+
24
+ ## Sources read
25
+
26
+ - ADR-035 (just shipped, `8632d15`) — 9-surface hook taxonomy + block-vs-inject menu; this standard names the contract for the inject side
27
+ - `code.claude.com/docs/en/hooks` (WebFetch 2026-06-27) — `additionalContext` injection JSON shape; 10K char limit; six events that support injection
28
+ - `.claude/hooks/turn-prose-kiss-check.sh` (existing pattern) — example of a Stop hook that emits stderr (block) but does not yet inject `additionalContext`
29
+ - `.claude/hooks/pr-body-scrub-check.sh` (sibling pattern) — example of structured stderr + exit code 2
30
+ - `standards/bash-hook-safety.md` (sibling standard) — seven defensive disciplines for bash hooks
31
+
32
+ ## What this standard covers
33
+
34
+ The contract for hooks that **inject context** into Claude's working memory rather than **block** a tool call. Six of nine Anthropic hook events accept an `additionalContext` field that becomes a system reminder attached to the agent's next turn. Bassclef has used hooks mostly as blockers; this standard names the contract for the other shape.
35
+
36
+ Companion standards:
37
+ - `standards/hook-install-class.md` — every hook declares whether it installs operator-class (`$HOME`) or project-class (`$CLAUDE_PROJECT_DIR`); injection hooks honor the declaration
38
+ - `standards/mechanism-fidelity.md` — the audit method that verifies an injection hook actually fires + produces observable effect
39
+ - `standards/bash-hook-safety.md` — seven defensive bash disciplines that injection hooks follow
40
+
41
+ ## When to inject vs block
42
+
43
+ Per ADR-035 decision menu:
44
+
45
+ | Discipline shape | Output mechanism | Hook event |
46
+ |---|---|---|
47
+ | **Refuse** the tool call (the gate must have authority) | `exit 2` | PreToolUse (also Stop for post-write rewrite) |
48
+ | **Steer** the agent (rule sits at recency edge of context) | `additionalContext` injection | UserPromptSubmit, UserPromptExpansion, PostToolUse, PostToolBatch, Stop, SubagentStop, SessionStart |
49
+ | **Verify** the hook works | Tier 0 strict-TDD per `testing-tier-config.md` | n/a — applies to all hook types |
50
+ | **End-to-end test** the hook's stated effect | cold-adopter harness check class | n/a — applies to all hook types |
51
+
52
+ Pick block when the gate's job is to refuse. Pick inject when the gate's job is to remind, prime, or shape the next generation step. Use both when both apply (block + inject in the same hook).
53
+
54
+ ## JSON envelope contract
55
+
56
+ Every injection hook returns valid JSON on stdout with this shape:
57
+
58
+ ```json
59
+ {
60
+ "hookSpecificOutput": {
61
+ "hookEventName": "<EventName>",
62
+ "additionalContext": "<text that becomes a system reminder>"
63
+ }
64
+ }
65
+ ```
66
+
67
+ Event-specific fields (per Anthropic docs):
68
+
69
+ | Event | Additional fields allowed |
70
+ |---|---|
71
+ | `SessionStart` | `sessionTitle`, `initialUserMessage`, `watchPaths`, `reloadSkills` |
72
+ | `UserPromptSubmit` | `decision: "block"`, `reason` |
73
+ | `UserPromptExpansion` | `decision: "block"`, `reason` |
74
+ | `PreToolUse` | `permissionDecision`, `permissionDecisionReason`, `updatedInput` |
75
+ | `PostToolUse` | `updatedToolOutput`, `decision: "block"` |
76
+ | `PostToolBatch` | `decision: "block"` |
77
+ | `Stop` | `decision: "block"` (the special pattern that lets the rewrite turn continue) |
78
+ | `SubagentStop` | `decision: "block"` |
79
+
80
+ When in doubt, verify against the latest Anthropic docs. The verify-latest header at the top of this standard names the reference.
81
+
82
+ ## 10,000-character rule
83
+
84
+ `additionalContext` is capped at 10,000 characters by Anthropic. Excess is saved to file with a preview shown to the agent. For a hook that injects a wordlist + reminder text, this is ample (a 30-term wordlist + per-term gloss + 2-3 sentences of framing typically lands under 2,000 chars).
85
+
86
+ If a hook's intended injection exceeds the cap, restructure rather than truncate — either inject the index + write the full content to a file the agent can Read, OR split across multiple injection surfaces (SessionStart for full wordlist; UserPromptSubmit for compressed reminder).
87
+
88
+ ## Marker-driven injection
89
+
90
+ When a hook should fire injection only on specific surfaces (e.g., turn-prose check only on /longrun-dispatched surfaces), it reads a marker file from `state/markers/<surface-type>/<surface-name>.marker`. Marker presence = the surface applies; marker absence = pass-through silently.
91
+
92
+ Two marker conventions:
93
+
94
+ - **Persistent markers** (per session or across sessions) — committed to git. Examples: `state/markers/temperance/`, `state/markers/luminary/`, `state/markers/arc-walk/`, `state/markers/adr/`, `state/markers/reviewer/`. These form audit trail.
95
+ - **Transient markers** (per turn or per surface, expire after the hook reads) — gitignored. Examples: `state/markers/turn-prose-surface/`. These signal the NEXT hook firing only and must not persist in committed state. Persisting them breaks tests that assume clean repo state (see bet 2026-06-27c WU-1 chronicle for the live failure example).
96
+
97
+ Per `standards/hook-install-class.md`, the marker location is consistent across install classes: hooks read from `$CLAUDE_PROJECT_DIR/state/markers/` if the dir exists, falling back to `$HOME/state/markers/` for operator-class hooks.
98
+
99
+ ## Fail-soft contract
100
+
101
+ Every injection hook fails soft on missing prerequisites. Order of fallback (per ADR-035 Class A cure pattern):
102
+
103
+ 1. Read project-relative path (`$CLAUDE_PROJECT_DIR/<resource>`) — preferred
104
+ 2. Read env-var override (`$<HOOK_PREFIX>_<RESOURCE>` — e.g., `KISS_STANDARDS_FILE`)
105
+ 3. Read user-level path (`$HOME/.claude/<resource>`) — operator-class fallback
106
+ 4. Use inline defaults — last resort
107
+
108
+ If all four fail, the hook still exits 0 (silent pass) but emits a structured stderr message describing the fallback chain that failed. Adopters running the cold-adopter harness see the stderr in the harness output; the harness check class catches silent fallbacks per `standards/mechanism-fidelity.md`.
109
+
110
+ The shared helper library `lib/hook-inject.sh` (lands in WU-3 of bet 2026-06-27c) implements this fallback chain so individual hooks call `resolve_<resource>_path` rather than repeating the logic.
111
+
112
+ ## Tier 0 testing requirement
113
+
114
+ Per `.claude/rules/testing-tier-config.md`, every hook in `.claude/hooks/*.sh` lands Tier 0 strict TDD. For injection hooks specifically, the test asserts:
115
+
116
+ 1. **JSON output validity** — stdout parses as JSON
117
+ 2. **Event name correctness** — `hookSpecificOutput.hookEventName` matches the wired event
118
+ 3. **Injection content presence** — `additionalContext` non-empty when expected
119
+ 4. **Fail-soft behavior** — missing inputs produce exit 0 + structured stderr (not exit 2)
120
+ 5. **Both install classes** — test runs under project-class install layout AND operator-class install layout (per `standards/hook-install-class.md`)
121
+ 6. **10,000-char ceiling** — injection content does not exceed the cap
122
+
123
+ The cold-adopter harness `hook-end-to-end-smoke` check class (lands in WU-5 of bet 2026-06-27c) re-runs steps 1-5 in adopter-shaped fixtures so the contract holds end-to-end.
124
+
125
+ ## Worked example
126
+
127
+ A hypothetical UserPromptSubmit hook that injects the BLOCK wordlist on every operator turn (the cure pattern for bassclef-upstream#1027 / #1051):
128
+
129
+ ```bash
130
+ #!/bin/bash
131
+ # tier: standard
132
+ # install-class: dual
133
+ # user-prompt-submit-kiss-prime.sh — inject BLOCK wordlist as additionalContext
134
+ set -euo pipefail
135
+
136
+ # Source the shared helper
137
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
138
+ source "${SCRIPT_DIR}/_lib/hook-inject.sh" 2>/dev/null \
139
+ || source "${CLAUDE_PROJECT_DIR:-}/lib/hook-inject.sh" 2>/dev/null \
140
+ || { echo "lib/hook-inject.sh missing" >&2; exit 0; }
141
+
142
+ # Resolve wordlist path (project → env → user → inline defaults)
143
+ WORDLIST=$(resolve_standards_path "bassclef-internal-jargon.md") || exit 0
144
+
145
+ # Build the injection
146
+ TERMS=$(extract_block_terms "$WORDLIST")
147
+ INJECTION="REMINDER: scan your draft against these BLOCK terms before posting:
148
+ ${TERMS}
149
+ Substitute per the grade-10 plain-English table. Reserved-name allowlist: substrate, bassclef, cameo, Studio, Band, bandleader."
150
+
151
+ # Emit the JSON envelope (10K char-safe; structured stderr on failure)
152
+ emit_additional_context "UserPromptSubmit" "$INJECTION"
153
+ exit 0
154
+ ```
155
+
156
+ Tier 0 test asserts the hook produces valid JSON envelope + non-empty `additionalContext` + exit 0 under both install layouts.
157
+
158
+ ## Anti-patterns
159
+
160
+ ### Inject when you should block
161
+
162
+ If a discipline genuinely requires refusing the action (e.g., destructive-command-guard), inject is wrong. The agent reads the injection and can still proceed. INSTEAD use PreToolUse exit 2.
163
+
164
+ ### Block when you should inject
165
+
166
+ If a discipline benefits from steering the agent's generation rather than refusing the action (e.g., remind about the wordlist before the agent drafts a PR body), block is wrong — the agent sees the block AFTER drafting; the draft is already in transcript. INSTEAD use UserPromptSubmit injection so the rule sits at the recency edge BEFORE generation.
167
+
168
+ ### Read project resources via SCRIPT_DIR/../.. under operator-class install
169
+
170
+ Per the Class A cure pattern (`turn-prose-kiss-check.sh` live failure example), a hook authored with project-relative reads but wired at `$HOME` resolves paths to `~/standards/` (nonexistent). INSTEAD use `lib/hook-inject.sh`'s resolve-helpers which honor declared install-class.
171
+
172
+ ### Inject without test
173
+
174
+ A hook that injects but has no Tier 0 test isn't verified to produce its claimed effect. Per ADR-035 substrate-as-system tenet, this is legacy code. INSTEAD: ship the Tier 0 test in the same PR as the hook.
175
+
176
+ ### Persist a transient marker
177
+
178
+ Committing a `state/markers/turn-prose-surface/*.marker` to git makes the hook see a marker that should expire per-turn. Tests that check "no marker → no advisory" break. INSTEAD: per the gitignore convention in `.gitignore`, transient marker directories are excluded.
179
+
180
+ ## Composes with
181
+
182
+ - `standards/hook-install-class.md` — every injection hook declares install-class header; `lib/hook-inject.sh` honors it
183
+ - `standards/mechanism-fidelity.md` — audit verifies injection hooks fire + produce observable effect
184
+ - `standards/bash-hook-safety.md` — seven defensive bash disciplines that injection hooks follow
185
+ - `standards/cold-adopter-harness.md` — `hook-end-to-end-smoke` check class re-verifies injection contract
186
+ - `.claude/rules/testing-tier-config.md` — Tier 0 strict-TDD on `.claude/hooks/*.sh`
187
+ - `.claude/rules/bootstrap-pair-discipline.md` — every hook ships with paired test + settings.json entry
188
+ - `.claude/rules/blocked-items.md` — protocol when an injection hook surfaces a `BLOCKED:` condition
189
+
190
+ ## Refs
191
+
192
+ - ADR-035 — hooks-as-steering-surfaces decision
193
+ - bassclef-upstream#417 — umbrella tracking for bet 2026-06-27c
194
+ - bassclef-upstream#1027 / #1051 / #1304 — prior lineage of turn-prose-kiss-check (Class B steering layer)
195
+ - `code.claude.com/docs/en/hooks` — Anthropic hook reference
196
+ - Michael Nygard — *Release It!* (stability patterns; fail-soft framing)
197
+ - Tony Hoare — pre/postcondition contract programming
198
+ - Hyrum Wright — Hyrum's Law (observable behavior becomes contract)
199
+
200
+ ## Retirement condition
201
+
202
+ This standard retires only if Claude Code's hook event surface changes shape enough that `additionalContext` is no longer the injection mechanism. The verify-latest header is the cue: every reader checks the Anthropic reference before authoring; if the surface has shifted, the standard amends or supersedes.
@@ -0,0 +1,215 @@
1
+ ---
2
+ tier: lite
3
+ status: live
4
+ date: 2026-06-27
5
+ authority: ADR-035
6
+ references:
7
+ - {type: adr, id: ADR-035, anchor: substrate-as-system tenet + hooks as steering surfaces}
8
+ - {type: adr, id: ADR-032, anchor: adopter sync dispatcher architecture}
9
+ - {type: adr, id: ADR-034, anchor: operator-class two-stage bootstrap}
10
+ - {type: standard, id: standards/hook-injection-discipline.md, anchor: injection hooks honor install-class}
11
+ - {type: standard, id: standards/cold-adopter-harness.md, anchor: harness verifies install-class matches actual wiring}
12
+ - {type: rule, id: .claude/rules/bootstrap-pair-discipline.md, anchor: new hook ships with install-class declaration}
13
+ - {type: rule, id: .claude/rules/cold-adopter-harness-discipline.md, anchor: per-PR harness gate}
14
+ luminaries:
15
+ primary: [john-ousterhout, linus-torvalds]
16
+ supporting: [hyrum-wright, frederick-brooks]
17
+ description: "- ADR-035 — names the install-class declaration as a foundational invariant (# install-class: operator | project | dual header) - ADR-032 — adopter sync dispatcher architecture (operator-class hooks wired at $HOME; project-class hooks wired at…"
18
+ ---
19
+
20
+ # Hook install class
21
+
22
+ > **Anthropic docs reference:** This standard does not depend on a specific Anthropic surface — it is a bassclef convention layered over the Claude Code hook system. The convention applies regardless of future Claude Code hook event additions.
23
+
24
+ ## Sources read
25
+
26
+ - ADR-035 — names the install-class declaration as a foundational invariant (`# install-class: operator | project | dual` header)
27
+ - ADR-032 — adopter sync dispatcher architecture (operator-class hooks wired at `$HOME`; project-class hooks wired at `$CLAUDE_PROJECT_DIR`)
28
+ - ADR-034 — extends ADR-032 to operator's own machine; both hook types now exist
29
+ - `.claude/hooks/turn-prose-kiss-check.sh` — the live Class A failure: code reads `$SCRIPT_DIR/../..` (project-relative); wiring at `$HOME` (operator-class); paths resolve to nonexistent locations
30
+ - `presence/install/bassclef-sync.template.sh` — the install template that copies hooks; will read install-class headers to decide where each goes
31
+ - `scripts/cold-adopter-harness-sync.sh` — runs structural checks today; will gain `hook-path-resolution-under-install-class` check class in WU-5
32
+
33
+ ## What this standard covers
34
+
35
+ Every hook in `.claude/hooks/*.sh` declares its install class via a header line:
36
+
37
+ ```bash
38
+ # install-class: operator | project | dual
39
+ ```
40
+
41
+ The install class tells the install template (`presence/install/bassclef-sync.template.sh`) where to install the hook + tells the hook's code which path resolution layout to use + tells the cold-adopter harness which install layout to verify against.
42
+
43
+ This standard exists because the 2026-06-27 /diagnose of `turn-prose-kiss-check.sh` surfaced the Class A failure: hook authored project-relative reads but wired operator-class. Declared install-class makes the mismatch a declarative property the harness can verify rather than a latent bug.
44
+
45
+ ## Install classes
46
+
47
+ ### `operator`
48
+
49
+ The hook lives at `$HOME/.claude/hooks/<name>.sh` and is invoked by the operator's user-level Claude Code settings. Examples (current):
50
+
51
+ - `bassclef-sync.sh` — adopter sync engine; operator runs it; updates ride to adopters via the install template
52
+ - `session-end.sh` — session lifecycle; operator-scope
53
+ - `bug-diagnosis.sh` — diagnosis trigger; operator-scope
54
+ - `tool-failure-diagnosis.sh` — failure trigger; operator-scope
55
+ - `deploy-guard.sh` — deploy gate; operator-scope
56
+ - `memory-write-audit.sh` — memory write trigger; operator-scope
57
+
58
+ Operator-class hooks resolve project resources via the fallback chain (per `standards/hook-injection-discipline.md` fail-soft contract):
59
+ 1. `$CLAUDE_PROJECT_DIR/<resource>` — when the active session has a project
60
+ 2. Env-var override
61
+ 3. `$HOME/.claude/<resource>` — operator-scope fallback
62
+ 4. Inline defaults
63
+
64
+ Operator-class hooks MUST NOT read via `$SCRIPT_DIR/../../<project-resource>` because under `$HOME` install layout, that resolves to `~/<project-resource>` (nonexistent).
65
+
66
+ ### `project`
67
+
68
+ The hook lives at `$CLAUDE_PROJECT_DIR/.claude/hooks/<name>.sh` and is invoked by the project's `.claude/settings.json`. Examples (current):
69
+
70
+ - `artifact-ingestion-gate.sh` — fires on Edit/Write of generative artifacts in the project
71
+ - `atomic-pr-check.sh` — fires on `git push` for this project
72
+ - `bet-doc-gate.sh` — fires on Edit/Write of `docs/iteration-bets/*.md`
73
+ - `destructive-command-guard.sh` — fires on Bash for destructive commands
74
+ - `pre-build-gate.sh` — fires on Edit/Write before first edit per branch
75
+ - `pre-commit-gate.sh` — fires on Bash matching git commit
76
+ - `pre-gh-pr-body-scrub.sh` — fires on Bash matching gh pr create
77
+ - `pre-gh-pr-title-scrub.sh` — fires on same
78
+ - `pre-git-commit-msg-scrub.sh` — fires on git commit messages
79
+ - `reviewer-dispatch-check.sh` — fires at Stop event
80
+ - `session-reflection.sh` — fires at SessionStart for the project
81
+ - `state-validate.sh` — fires on Edit/Write of state-spine entities
82
+ - `temperance-gate.sh` — fires per-branch
83
+ - `testing-tier-enforce.sh` — fires on Edit/Write of substrate-internal paths
84
+
85
+ Project-class hooks can use `$SCRIPT_DIR/../..` to reach project resources because under `$CLAUDE_PROJECT_DIR` install layout, that resolves correctly to the project root.
86
+
87
+ ### `dual`
88
+
89
+ The hook works correctly under both install classes. Either:
90
+ - Code uses `lib/hook-inject.sh` resolve-helpers (preferred — always works regardless of install layout)
91
+ - Code reads only its own directory + env-var overrides + inline defaults (no project-resource reads)
92
+
93
+ Examples that should be `dual`:
94
+ - `turn-prose-kiss-check.sh` — needs to fire at Stop for operator-class scenarios (Stop is session-level) AND for project-class scenarios (cure work in follow-on goal)
95
+ - Future injection hooks that ship to adopters
96
+
97
+ ## Header convention
98
+
99
+ Position: top of file, after the shebang + tier declaration, before the description.
100
+
101
+ ```bash
102
+ #!/bin/bash
103
+ # tier: standard
104
+ # install-class: dual
105
+ # <one-line description>
106
+ #
107
+ # <rest of header comment>
108
+ ```
109
+
110
+ The header is parseable by simple grep:
111
+
112
+ ```bash
113
+ INSTALL_CLASS=$(grep -m1 '^# install-class:' .claude/hooks/<name>.sh | sed 's/^# install-class: *//')
114
+ ```
115
+
116
+ If the header is missing, the hook is treated as `project` (current default).
117
+
118
+ ## Install template enforcement
119
+
120
+ The install template (`presence/install/bassclef-sync.template.sh`) reads the install-class header at sync time. For each hook in the source tree:
121
+
122
+ | Declared install-class | Action |
123
+ |---|---|
124
+ | `operator` | Copy to `$HOME/.claude/hooks/<name>.sh`. Refuse to copy into `$CLAUDE_PROJECT_DIR/.claude/hooks/`. |
125
+ | `project` | Refuse to copy into `$HOME/.claude/hooks/`. Project-class hooks land via bassclef-sync's project file resolution, not via copy. |
126
+ | `dual` | Copy to `$HOME` AND make available under `$CLAUDE_PROJECT_DIR`. |
127
+ | `missing` | Treat as `project` (backwards-compatible default). |
128
+
129
+ This enforcement closes the failure mode where an operator-class hook copy + project-relative reads produce silent fallbacks.
130
+
131
+ (The actual template amendment lands in a follow-on goal; the standard documents the contract now so future authors honor it from the start.)
132
+
133
+ ## Cold-adopter harness verification
134
+
135
+ The cold-adopter harness check class `hook-path-resolution-under-install-class` (lands in WU-5 of bet 2026-06-27c) verifies that declared install-class matches actual behavior. Per hook:
136
+
137
+ 1. Read declared install-class from header
138
+ 2. Install the hook fresh under the declared layout (operator-class → `$HOME`; project-class → `$CLAUDE_PROJECT_DIR`; dual → both)
139
+ 3. Run the hook against a fixture trigger
140
+ 4. Assert all path resolutions succeed (no `falls back to defaults` warnings in stderr)
141
+ 5. Fail the check if any path lookup misses
142
+
143
+ This is the mechanical layer that catches future instances of the Class A failure at PR time.
144
+
145
+ ## Worked example
146
+
147
+ ### Operator-class hook (existing)
148
+
149
+ ```bash
150
+ #!/bin/bash
151
+ # tier: standard
152
+ # install-class: operator
153
+ # bassclef-sync.sh — adopter sync engine; invoked by user-level Claude Code settings.
154
+ # ...
155
+ ```
156
+
157
+ ### Project-class hook (existing)
158
+
159
+ ```bash
160
+ #!/bin/bash
161
+ # tier: standard
162
+ # install-class: project
163
+ # bet-doc-gate.sh — PreToolUse Edit/Write on docs/iteration-bets/*.md.
164
+ # Fires arc-walk + produces/consumes checks per goal doc discipline.
165
+ # ...
166
+ ```
167
+
168
+ ### Dual hook (the cure for turn-prose-kiss-check.sh in follow-on goal)
169
+
170
+ ```bash
171
+ #!/bin/bash
172
+ # tier: standard
173
+ # install-class: dual
174
+ # turn-prose-kiss-check.sh — Stop hook that scans assistant prose against
175
+ # BLOCK wordlist. Uses lib/hook-inject.sh resolve-helpers so path resolution
176
+ # works under both operator-class wiring at $HOME and project-class wiring
177
+ # at $CLAUDE_PROJECT_DIR.
178
+ # ...
179
+ ```
180
+
181
+ ## Anti-patterns
182
+
183
+ ### Author project-relative reads + wire operator-class
184
+
185
+ The Class A failure pattern from bet 2026-06-27c /diagnose. INSTEAD: declare `# install-class: dual` + use `lib/hook-inject.sh` resolve-helpers.
186
+
187
+ ### Decline to declare install-class
188
+
189
+ A hook without the header defaults to `project` and the install template refuses to copy it to `$HOME`. INSTEAD: pick `operator` / `project` / `dual` deliberately at author time.
190
+
191
+ ### Mix install-class with hard-coded `$HOME` or `$CLAUDE_PROJECT_DIR` references
192
+
193
+ Defeats the abstraction. INSTEAD: source `lib/hook-inject.sh` + call its resolve-helpers; the helpers do the install-class-aware lookup.
194
+
195
+ ## Composes with
196
+
197
+ - `standards/hook-injection-discipline.md` — injection hooks honor install-class via the fallback chain
198
+ - `standards/cold-adopter-harness.md` (standard tier) — `hook-path-resolution-under-install-class` check class verifies declared header matches actual behavior
199
+ - `presence/install/bassclef-sync.template.sh` — install template reads the header to decide install path
200
+ - `.claude/rules/bootstrap-pair-discipline.md` — new hook ships with install-class header in its bootstrap pair
201
+ - `.claude/rules/cold-adopter-harness-discipline.md` — per-PR harness gate runs the verification
202
+
203
+ ## Refs
204
+
205
+ - ADR-035 — names install-class as a foundational invariant
206
+ - ADR-032 — adopter sync dispatcher architecture (operator-class vs project-class distinction)
207
+ - ADR-034 — operator-class two-stage bootstrap (where the operator-class hooks fold in)
208
+ - bassclef-upstream#417 — umbrella tracking for bet 2026-06-27c
209
+ - `architecture/audits/2026-06-27-mechanism-fidelity.md` (lands in WU-6) — first audit run will classify each hook by install-class + flag Class A mismatches
210
+ - @luminary john-ousterhout — deep modules: declared install-class is the small interface that hides path-resolution complexity
211
+ - @luminary linus-torvalds — we-don't-break-adopters: install-class declaration prevents a hook from silently breaking under adopter install layout
212
+
213
+ ## Retirement condition
214
+
215
+ This standard retires only if bassclef stops distinguishing operator-class vs project-class hooks. The `dual` class may become the default if all future hooks are authored to use `lib/hook-inject.sh` resolve-helpers from the start, but the discipline of declaring install-class persists as audit trail.