@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
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  tier: lite
3
3
  name: onboard-repo
4
- description: "Bootstrap bassclef framework in a new repo. Installs sync hook + scaffolds config + whereami + CLAUDE.md. Modes: default / --with-deploy-host / --with-secrets / --full / --greenfield-from-intent (cold-adopter magic demo from a paragraph — uses /launch --local)."
4
+ description: "Bootstrap the bassclef framework in a new repo. Installs the sync hook. Scaffolds config, whereami, and CLAUDE.md. Modes: default, --with-deploy-host, --with-secrets, --full, --greenfield-from-intent (cold-adopter magic demo)."
5
5
  problem: "Setting up bassclef in a new repo takes an hour of trial. Missing directories and wrong hook wiring."
6
6
  value: "One command bootstraps everything \u2014 sync hook and config file and whereami scaffold."
7
7
  inputs: [Optional flags — --with-deploy-host or --with-secrets or --full]
@@ -279,7 +279,7 @@ this divider.
279
279
  Run each phase in order. Operator confirms before destructive or
280
280
  cross-repo actions. Each phase is independently re-runnable.
281
281
 
282
- #### Phase 0 — Refuse to run from main (bassclef#956 V0.5)
282
+ #### Phase 0 — Refuse to run from main
283
283
 
284
284
  Substrate changes go through PRs, same as feature work. If `/onboard-repo`
285
285
  runs from `main`, every scaffold (`.claude/`, `CLAUDE.md`,
@@ -496,734 +496,168 @@ JSON
496
496
  Operator confirms — may want to add app-specific hooks (pre-build-gate,
497
497
  pre-commit-gate) if the repo has source code.
498
498
 
499
- ##### 2.2.1 Wire turn-prose-kiss-check Stop hook (bassclef#1138 T5)
499
+ ##### 2.2.1 Wire all Phase 2.2 hooks (13 hooks in one pass)
500
500
 
501
- Symlink the bassclef Stop hook that scans the most recent assistant
502
- message for bassclef-internal jargon (the `/kiss words` BLOCK list
503
- from `standards/bassclef-internal-jargon.md`). When
504
- `prose_discipline.kiss_words_turn_prose` is `true` in
505
- `.claude/bassclef-configs.jsonc` (the adopter-default Phase 2.3.5
506
- writes), the hook fires after every assistant turn and surfaces
507
- findings; when `false`, the hook short-circuits silently.
501
+ Phase 2.2 wires 13 bassclef hooks that gate adopter writes, commits, sessions, and role transitions. Read the whole table first. Then apply the canonical jq recipe. Then run the 3 verify blocks.
508
502
 
509
- Symlink the hook (bassclef lives one directory up per the
510
- `additionalDirectories` convention):
503
+ **Lite adopter note** (bassclef#740 Task 1.2). 6 hooks ship at `tier: standard` and skip on lite. Resolve tier via `lib/tier-check.sh`. The table marks each standard-tier hook with `std`. The bassclef-lite tarball does not carry those 6.
511
504
 
512
- ```bash
513
- mkdir -p .claude/hooks
514
- ln -sf "../../../bassclef/.claude/hooks/turn-prose-kiss-check.sh" \
515
- ".claude/hooks/turn-prose-kiss-check.sh"
516
- ```
517
-
518
- Add the Stop hook block to `.claude/settings.json`. If the file already
519
- has a Stop block (for example, `session-end.sh`), append this hook
520
- alongside — both run, turn-prose-kiss-check first, session-end second:
521
-
522
- ```jsonc
523
- {
524
- "hooks": {
525
- "Stop": [
526
- {
527
- "matcher": "",
528
- "hooks": [
529
- { "type": "command", "command": "$CLAUDE_PROJECT_DIR/.claude/hooks/turn-prose-kiss-check.sh", "timeout": 10 }
530
- ]
531
- }
532
- ]
533
- }
534
- }
535
- ```
536
-
537
- **Composition rule** — when an existing Stop hook is present, leave it
538
- in place and append this one. The turn-prose-kiss-check hook exits 0
539
- even when findings surface (default toggle: advisory), so a downstream
540
- session-end hook still runs. When the adopter opts in to strict mode
541
- (`prose_discipline.kiss_words_turn_prose: "strict"` in
542
- bassclef-configs.jsonc), the hook exits 2 and blocks the stop — that's
543
- the conscious-strict trade-off.
544
-
545
- **Conditional fire** — the hook reads
546
- `.claude/bassclef-configs.jsonc` `prose_discipline.kiss_words_turn_prose`
547
- at runtime and short-circuits when `false`. Adopters who never want the
548
- check can flip the toggle without unwiring the hook.
549
-
550
- **Verify the wiring:**
551
-
552
- ```bash
553
- # Sanity: hook is executable + reachable
554
- ls -l .claude/hooks/turn-prose-kiss-check.sh
555
-
556
- # Sanity: settings.json parses
557
- python3 -c "import json; json.load(open('.claude/settings.json'))"
558
- ```
559
-
560
- **Composes with downstream Phase 2.x steps:**
561
-
562
- - Phase 2.3.5 writes `prose_discipline.kiss_words_turn_prose: true` to
563
- `.claude/bassclef-configs.jsonc` as the adopter default — this hook
564
- fires when that toggle is true.
565
- - Phase 2.5 (security scanning) is a separate hook wiring path; both
566
- hooks can co-exist in the Stop block.
567
-
568
- Source: bassclef#1051 (hook origin), bassclef#1138 (this wiring step).
569
-
570
- ##### 2.2.2 Wire substrate-clarity-gate PreToolUse hook (bassclef#1137 T4)
571
-
572
- Symlink the bassclef PreToolUse hook that BLOCKs writes to
573
- `.claude/skills/`, `.claude/rules/`, and `.claude/luminaries/` when
574
- they violate the clarity discipline bassclef applies to its own
575
- substrate — skill descriptions over 280 chars, rule + luminary
576
- "NEVER" without paired "INSTEAD:" block, jargon usage where plain
577
- language exists. Adopter writes to substrate paths trigger the same
578
- gate bassclef does.
579
-
580
- Symlink the hook + the bassclef baseline allowlist (the file that
581
- grandfathers pre-existing violators during a grace window):
505
+ **Symlink all hooks in one pass:**
582
506
 
583
507
  ```bash
584
508
  mkdir -p .claude/hooks
585
- ln -sf "../../../bassclef/.claude/hooks/substrate-clarity-gate.sh" \
586
- ".claude/hooks/substrate-clarity-gate.sh"
587
- ln -sf "../../../bassclef/.claude/hooks/substrate-clarity-allowlist.txt" \
588
- ".claude/hooks/substrate-clarity-allowlist.txt"
589
- ```
590
-
591
- Add the PreToolUse Edit|Write block to `.claude/settings.json`. If an
592
- `Edit|Write` matcher already exists from a prior phase, append this
593
- hook to its `hooks` array instead of duplicating the matcher entry:
594
-
595
- ```jsonc
596
- {
597
- "hooks": {
598
- "PreToolUse": [
599
- {
600
- "matcher": "Edit|Write",
601
- "hooks": [
602
- { "type": "command", "command": "$CLAUDE_PROJECT_DIR/.claude/hooks/substrate-clarity-gate.sh" }
603
- ]
604
- }
605
- ]
606
- }
607
- }
608
- ```
609
-
610
- **Adopter allowlist convention** the symlinked
611
- `substrate-clarity-allowlist.txt` carries bassclef's baseline
612
- grandfather list (pre-existing violators with a documented grace
613
- window). When the adopter has their own pre-existing substrate
614
- violations they want to grandfather during their own migration,
615
- they create a sibling file:
509
+ cd .claude/hooks
510
+ for h in turn-prose-kiss-check substrate-clarity-gate artifact-ingestion-gate \
511
+ pattern-annotation-validate pre-commit-gate state-validate \
512
+ destructive-command-guard multi-tenancy-check atomic-pr-check \
513
+ post-write-trace testing-tier-enforce role-entry-gate temperance-gate; do
514
+ ln -sf "../../../bassclef/.claude/hooks/${h}.sh" "${h}.sh"
515
+ done
516
+ # Two allowlist files paired with hooks that read them:
517
+ ln -sf "../../../bassclef/.claude/hooks/substrate-clarity-allowlist.txt" substrate-clarity-allowlist.txt
518
+ ln -sf "../../../bassclef/.claude/hooks/testing-tier-enforce-allowlist.txt" testing-tier-enforce-allowlist.txt
519
+ cd -
520
+ ```
521
+
522
+ **Hook table:**
523
+
524
+ | # | Hook | Event | Matcher | Tier | Notes |
525
+ |---|---|---|---|---|---|
526
+ | 1 | turn-prose-kiss-check | Stop | (empty) | lite | Reads `prose_discipline.kiss_words_turn_prose` toggle from bassclef-configs; short-circuits when false; timeout 10s |
527
+ | 2 | substrate-clarity-gate | PreToolUse | Edit\|Write | lite | Reads bassclef baseline allowlist + optional adopter-side `substrate-clarity-allowlist-adopter.txt` |
528
+ | 3 | artifact-ingestion-gate | PreToolUse | Write | lite | Reads `artifact_ingestion.paths` from bassclef-configs; 13 default paths seeded by Phase 2.3.5 |
529
+ | 4 | pattern-annotation-validate | PreToolUse | Edit\|Write\|MultiEdit | std | Reads `tech_stack.lang` for language scoping (Phase 2.3.6) |
530
+ | 5 | pre-commit-gate | PreToolUse | Edit\|Write\|MultiEdit | lite | Runs first; composes testing-tier-enforce internally as one of its check steps |
531
+ | 6 | state-validate | PreToolUse | Edit\|Write\|MultiEdit | lite | Runs after pre-commit-gate; heavier ajv-cli schema check |
532
+ | 7 | destructive-command-guard | PreToolUse | Bash | std | Catches destructive verbs + force flags + amplifiers (rm -rf, FLUSHALL, prisma migrate reset) |
533
+ | 8 | multi-tenancy-check | PreToolUse | Edit\|Write\|MultiEdit | std | Template — customize via `TENANT_MODELS` / `TENANT_CONTEXT_FN` / `TENANT_PARAMS_FN` env vars |
534
+ | 9 | atomic-pr-check | PreToolUse | Bash | std | Fires on `git push` patterns; BLOCKs multi-step branches lacking `bundle: true` in goal frontmatter |
535
+ | 10 | post-write-trace | PostToolUse | Write\|Edit | std | Append-only trace; no override (never blocks) |
536
+ | 11 | testing-tier-enforce | (composed) | (via pre-commit-gate) | lite | Fires inside pre-commit-gate; no separate matcher entry; 60-day allowlist grace |
537
+ | 12 | role-entry-gate | PreToolUse | Edit\|Write\|MultiEdit | std | MVP: source-code file extensions only; reads `state/markers/role/<role>/<session>.marker` |
538
+ | 13 | temperance-gate | PreToolUse | Edit\|Write\|MultiEdit | lite | Fires on high-impact edits (.claude/, standards/, lib/state.sh, SKILL.md) when temperance marker missing |
539
+
540
+ **Order matters within each matcher block.** Place `pre-commit-gate` before `state-validate` (cheap SDLC checks fire first; heavier schema check runs second). Place `role-entry-gate` and `temperance-gate` LAST — methodology gates fire after structural + format + state checks pass.
541
+
542
+ **Canonical jq recipe — write settings.json in one pass.** The recipe uses JSON literal syntax so the `"matcher": "..."` and `"command": "..."` keys land verbatim in `.claude/settings.json` for grep-verifiability:
616
543
 
617
544
  ```bash
618
- touch .claude/hooks/substrate-clarity-allowlist-adopter.txt
619
- ```
620
-
621
- The hook reads BOTH files in series — bassclef's baseline first,
622
- then the adopter-side append. Entries in the adopter file follow
623
- the same one-path-per-line format as bassclef's baseline. The
624
- adopter file is git-tracked in the adopter repo (not symlinked
625
- into bassclef), so each adopter manages their own grandfather
626
- list independently.
627
-
628
- **Composition rule** — when an existing PreToolUse Edit|Write
629
- matcher block is present (for example, `artifact-ingestion-gate.sh`
630
- from Phase 2.x), append this hook's command entry to the same
631
- matcher's `hooks` array. The matcher entry must not be duplicated;
632
- the array of hooks under one matcher can hold multiple commands
633
- that fire in series.
634
-
635
- **Override path** adopter can bypass per-call with
636
- `SKIP_SUBSTRATE_CLARITY=1 <command>` (logged via trace-helper per
637
- bassclef override idiom). The override is for migration scripts
638
- and emergency rescue; routine use should fix the violation, not
639
- bypass.
640
-
641
- **Verify the wiring:**
545
+ # Assumes .claude/settings.json exists from Phase 2.2 (bare SessionStart entry).
546
+ # Reads adopter tier and skips standard-tier hooks on lite.
547
+ TIER=$(bash ../bassclef/lib/tier-check.sh 2>/dev/null || echo lite)
548
+
549
+ # Lite tier 7 hooks land in .claude/settings.json (rows 1,2,3,5,6,11,13).
550
+ # Standard/ultra tier all 13 hooks land in .claude/settings.json.
551
+ jq --arg tier "$TIER" '
552
+ .hooks.Stop = ((.hooks.Stop // []) + [
553
+ { "matcher": "", "hooks": [
554
+ { "type": "command", "command": "$CLAUDE_PROJECT_DIR/.claude/hooks/turn-prose-kiss-check.sh", "timeout": 10 }
555
+ ]}
556
+ ]) |
557
+ .hooks.PreToolUse = ((.hooks.PreToolUse // []) + [
558
+ { "matcher": "Edit|Write|MultiEdit", "hooks": (
559
+ [
560
+ { "type": "command", "command": "$CLAUDE_PROJECT_DIR/.claude/hooks/substrate-clarity-gate.sh" },
561
+ { "type": "command", "command": "$CLAUDE_PROJECT_DIR/.claude/hooks/pre-commit-gate.sh" },
562
+ { "type": "command", "command": "$CLAUDE_PROJECT_DIR/.claude/hooks/state-validate.sh" },
563
+ { "type": "command", "command": "$CLAUDE_PROJECT_DIR/.claude/hooks/temperance-gate.sh" }
564
+ ] +
565
+ (if $tier != "lite" then [
566
+ { "type": "command", "command": "$CLAUDE_PROJECT_DIR/.claude/hooks/pattern-annotation-validate.sh" },
567
+ { "type": "command", "command": "$CLAUDE_PROJECT_DIR/.claude/hooks/multi-tenancy-check.sh" },
568
+ { "type": "command", "command": "$CLAUDE_PROJECT_DIR/.claude/hooks/role-entry-gate.sh" }
569
+ ] else [] end)
570
+ )},
571
+ { "matcher": "Write", "hooks": [
572
+ { "type": "command", "command": "$CLAUDE_PROJECT_DIR/.claude/hooks/artifact-ingestion-gate.sh" }
573
+ ]}
574
+ ] + (if $tier != "lite" then [
575
+ { "matcher": "Bash", "hooks": [
576
+ { "type": "command", "command": "$CLAUDE_PROJECT_DIR/.claude/hooks/destructive-command-guard.sh" },
577
+ { "type": "command", "command": "$CLAUDE_PROJECT_DIR/.claude/hooks/atomic-pr-check.sh" }
578
+ ]}
579
+ ] else [] end)) |
580
+ (if $tier != "lite" then
581
+ .hooks.PostToolUse = ((.hooks.PostToolUse // []) + [
582
+ { "matcher": "Write|Edit", "hooks": [
583
+ { "type": "command", "command": "$CLAUDE_PROJECT_DIR/.claude/hooks/post-write-trace.sh" }
584
+ ]}
585
+ ])
586
+ else . end)
587
+ ' .claude/settings.json > .claude/settings.json.tmp \
588
+ && mv .claude/settings.json.tmp .claude/settings.json
589
+ ```
590
+
591
+ **Alternate matcher notes.** The `"matcher": "Edit|Write"` shape (without MultiEdit) appears in older adopter settings.json — the widening to `"matcher": "Edit|Write|MultiEdit"` in this recipe covers MultiEdit for hooks that need it.
592
+
593
+ **On re-run against existing settings.json** — jq's `+=` appends. Duplicate matcher entries are safe (Claude Code processes all in order), but the cleaner shape merges hooks under one matcher. To dedupe a re-run, strip existing entries with `jq 'del(...)'` before appending.
594
+
595
+ **Verify block 1 — Stop event:**
642
596
 
643
597
  ```bash
644
- # Sanity: hook executable + reachable
645
- ls -l .claude/hooks/substrate-clarity-gate.sh
646
- ls -l .claude/hooks/substrate-clarity-allowlist.txt
647
-
648
- # Sanity: settings.json parses + has the matcher
649
598
  python3 -c "import json; d=json.load(open('.claude/settings.json')); \
650
- print('substrate-clarity-gate wired' if any( \
651
- 'substrate-clarity-gate' in h.get('command','') \
652
- for entry in d.get('hooks',{}).get('PreToolUse',[]) \
653
- for h in entry.get('hooks',[])) else 'NOT wired')"
599
+ hooks=[h.get('command','') for entry in d.get('hooks',{}).get('Stop',[]) for h in entry.get('hooks',[])]; \
600
+ print('turn-prose-kiss-check wired' if any('turn-prose-kiss-check' in c for c in hooks) else 'NOT wired')"
654
601
  ```
655
602
 
656
- Source: bassclef#382 (hook origin), bassclef#1137 (this wiring step), bassclef#1135 (T2 config default — separate concern).
657
-
658
- ##### 2.2.3 Wire artifact-ingestion-gate PreToolUse hook (bassclef#1140 T7)
659
-
660
- Symlink the bassclef PreToolUse hook that BLOCKs writes to adopter
661
- substantive artifacts (specs, decompositions, prototypes, ADRs,
662
- proposals, iteration goals) when the artifact body lacks a
663
- `## Sources read` section. The discipline catches the
664
- "pattern-matched on generic X" failure mode that
665
- `.claude/rules/artifact-ingestion.md` was built to close — applied at
666
- adopter writes, not just at bassclef's own writes.
667
-
668
- Symlink the hook:
603
+ **Verify block 2 PreToolUse event (all matchers):**
669
604
 
670
605
  ```bash
671
- mkdir -p .claude/hooks
672
- ln -sf "../../../bassclef/.claude/hooks/artifact-ingestion-gate.sh" \
673
- ".claude/hooks/artifact-ingestion-gate.sh"
674
- ```
675
-
676
- Add the PreToolUse Write block to `.claude/settings.json`. The hook
677
- matches on `Write` (not `Edit`) — edits to existing artifacts pass
678
- through; only new artifact writes trigger the gate. If a Write
679
- matcher already exists from a prior phase, append this hook to its
680
- `hooks` array:
681
-
682
- ```jsonc
683
- {
684
- "hooks": {
685
- "PreToolUse": [
686
- {
687
- "matcher": "Write",
688
- "hooks": [
689
- { "type": "command", "command": "$CLAUDE_PROJECT_DIR/.claude/hooks/artifact-ingestion-gate.sh" }
690
- ]
691
- }
692
- ]
693
- }
694
- }
695
- ```
696
-
697
- **Adopter-default path matchers** — the hook reads
698
- `.claude/bassclef-configs.jsonc` `artifact_ingestion.paths` to
699
- decide which paths fire the gate. Phase 2.3.5 (bassclef-configs
700
- adopter-default seed) appends this block with the bassclef default
701
- list. Adopters edit the list per repo — adding paths their substrate
702
- considers substantive, or removing paths that do not apply:
703
-
704
- ```jsonc
705
- "artifact_ingestion": {
706
- "paths": [
707
- "docs/specs/**/*.md",
708
- "docs/decompositions/**/*.md",
709
- "docs/prototypes/**/*.html",
710
- "docs/proposals/**/*.md",
711
- "docs/adrs/**/*.md",
712
- "docs/use-cases/**/*.md",
713
- "docs/user-stories/**/*.md",
714
- "docs/ia-models/**/*.md",
715
- "docs/interaction-design/**/*",
716
- "docs/personas/**/*.md",
717
- "docs/jtbd-tasks/**/*.md",
718
- "docs/value-props/**/*.md",
719
- "docs/iteration-bets/**/*.md"
720
- ]
721
- }
722
- ```
723
-
724
- When the `artifact_ingestion.paths` field is absent (older adopters
725
- predating this Phase), the hook falls back to its built-in default
726
- matcher list — the wiring stays safe and quiet.
727
-
728
- **Composition rule** — when an existing PreToolUse Write matcher is
729
- present (for example, from a sibling hook in another Phase 2.x step),
730
- append this hook's command entry to the same matcher's `hooks` array.
731
- The matcher entry must not be duplicated.
732
-
733
- **Override path** — adopter can bypass per-call with
734
- `SKIP_ARTIFACT_INGESTION=1 <command>` (logged via trace-helper). Use
735
- for migration scripts and emergency rescue.
736
-
737
- **Verify the wiring:**
738
-
739
- ```bash
740
- # Sanity: hook executable + reachable
741
- ls -l .claude/hooks/artifact-ingestion-gate.sh
742
-
743
- # Sanity: settings.json has the matcher
744
606
  python3 -c "import json; d=json.load(open('.claude/settings.json')); \
745
- print('artifact-ingestion-gate wired' if any( \
746
- 'artifact-ingestion-gate' in h.get('command','') \
747
- for entry in d.get('hooks',{}).get('PreToolUse',[]) \
748
- for h in entry.get('hooks',[])) else 'NOT wired')"
607
+ cmds=[h.get('command','') for entry in d.get('hooks',{}).get('PreToolUse',[]) for h in entry.get('hooks',[])]; \
608
+ hooks=['substrate-clarity-gate','artifact-ingestion-gate','pre-commit-gate','state-validate','temperance-gate','pattern-annotation-validate','destructive-command-guard','multi-tenancy-check','atomic-pr-check','role-entry-gate']; \
609
+ [print(f'{h}: {\"wired\" if any(h in c for c in cmds) else \"NOT wired\"}') for h in hooks]"
749
610
  ```
750
611
 
751
- Source: bassclef#116 (hook origin), bassclef#1140 (this wiring step).
752
-
753
- ##### 2.2.4 Wire pattern-annotation-validate PreToolUse hook (bassclef#1139 T6)
754
-
755
- **Lite adopter note (bassclef#740 Task 1.2).** This hook ships at `tier: standard`. If your adopter tier is lite (resolved via `lib/tier-check.sh`), skip this Phase step and continue with 2.2.5. The bassclef-lite tarball does not carry this hook.
756
-
757
- Symlink the bassclef PreToolUse hook that validates `@pattern <catalog-path>` annotations in adopter source code. Layer 3 of bassclef#478 traceability — code that instantiates a named pattern from bassclef's catalog (`patterns/<shelf>/<source>/<slug>.md`) must mark itself with the annotation so forward (which code uses this pattern) and reverse (which patterns is this code using) lookups work across the adopter portfolio.
758
-
759
- Symlink the hook:
612
+ **Verify block 3 PostToolUse event:**
760
613
 
761
614
  ```bash
762
- mkdir -p .claude/hooks
763
- ln -sf "../../../bassclef/.claude/hooks/pattern-annotation-validate.sh" \
764
- ".claude/hooks/pattern-annotation-validate.sh"
765
- ```
766
-
767
- Add the PreToolUse Edit|Write|MultiEdit block to `.claude/settings.json`. If an `Edit|Write` matcher already exists from a prior phase, append this hook to its `hooks` array (the bassclef settings.json convention is to widen matchers when adding new hooks that share a tool set):
768
-
769
- ```jsonc
770
- {
771
- "hooks": {
772
- "PreToolUse": [
773
- {
774
- "matcher": "Edit|Write|MultiEdit",
775
- "hooks": [
776
- { "type": "command", "command": "$CLAUDE_PROJECT_DIR/.claude/hooks/pattern-annotation-validate.sh" }
777
- ]
778
- }
779
- ]
780
- }
781
- }
782
- ```
783
-
784
- **Rule propagation** — the `pattern-annotation` rule lives at bassclef's `.claude/rules/pattern-annotation.md` and loads into adopter agent context via the `additionalDirectories: ["../bassclef"]` entry Phase 2.2 wrote. No copy needed; bassclef's rule body is the source of truth.
785
-
786
- **Tech-stack-aware scoping** — the hook reads adopter's `.claude/bassclef-configs.jsonc` `tech_stack.lang` (Phase 2.3.6 writes) and fires only on source files matching the declared language: `.ts/.tsx` for `typescript`, `.py` for `python`, `.rb` for `ruby`, `.go` for `go`, `.rs` for `rust`. Non-source files silent. When `tech_stack.lang` is absent (older adopters or skip path), the hook fires on the union of language matchers (safe default).
787
-
788
- **Composition rule** — when an existing PreToolUse Edit|Write matcher block is present (substrate-clarity-gate from 2.2.2 uses `Edit|Write`), the matcher set widens to `Edit|Write|MultiEdit` to cover both hooks. Adopters can keep the matchers separate if they prefer narrower scoping per hook.
789
-
790
- **Override path** — `SKIP_PATTERN_ANNOTATION=1 <command>` (logged via trace-helper). Use for migration scripts when annotating retroactively is in flight.
791
-
792
- **Verify the wiring:**
793
-
794
- ```bash
795
- # Sanity: hook executable + reachable
796
- ls -l .claude/hooks/pattern-annotation-validate.sh
797
-
798
- # Sanity: rule loads via additionalDirectories
799
- test -f ../bassclef/.claude/rules/pattern-annotation.md && echo "rule reachable" || echo "rule NOT reachable"
800
-
801
- # Sanity: settings.json has the matcher
802
615
  python3 -c "import json; d=json.load(open('.claude/settings.json')); \
803
- print('pattern-annotation-validate wired' if any( \
804
- 'pattern-annotation-validate' in h.get('command','') \
805
- for entry in d.get('hooks',{}).get('PreToolUse',[]) \
806
- for h in entry.get('hooks',[])) else 'NOT wired')"
616
+ cmds=[h.get('command','') for entry in d.get('hooks',{}).get('PostToolUse',[]) for h in entry.get('hooks',[])]; \
617
+ print('post-write-trace wired' if any('post-write-trace' in c for c in cmds) else 'NOT wired')"
807
618
  ```
808
619
 
809
- Source: bassclef#478 (parent traceability goal), bassclef#1139 (this wiring step), bassclef#1127 (tech_stack vocabulary the scoping reads).
810
-
811
- ##### 2.2.5 Wire pre-commit-gate + state-validate PreToolUse hooks (bassclef#1136 T3)
812
-
813
- Symlink the two bassclef PreToolUse hooks that gate adopter writes.
814
-
815
- `pre-commit-gate.sh` runs the SDLC pre-build checks per `.claude/rules/sdlc-gates.md`. Those checks are temperance + diagnosis + scope drift.
816
-
817
- `state-validate.sh` validates state-spine entity writes against JSON Schema per `.claude/rules/state-schema-validation.md`.
818
-
819
- Together the hooks catch two failure classes before any source edit lands: skipped gates (silent SDLC bypass) and malformed state writes (silent schema drift).
820
-
821
- Symlink both hooks:
620
+ **Rule propagation** — 8 rules load into the adopter session on their own via the `additionalDirectories: ["../bassclef"]` entry Phase 2.2 wrote. No per-rule symlink needed. Rules: `sdlc-gates.md`, `state-schema-validation.md`, `testing-tier-config.md`, `test-list-discipline.md`, `test-sufficiency.md`, `destructive-operations.md`, `pattern-annotation.md`, `pr-strategy.md`. Verify with:
822
621
 
823
622
  ```bash
824
- mkdir -p .claude/hooks
825
- ln -sf "../../../bassclef/.claude/hooks/pre-commit-gate.sh" \
826
- ".claude/hooks/pre-commit-gate.sh"
827
- ln -sf "../../../bassclef/.claude/hooks/state-validate.sh" \
828
- ".claude/hooks/state-validate.sh"
829
- ```
830
-
831
- Add the PreToolUse Edit|Write|MultiEdit block to `.claude/settings.json`. If an `Edit|Write` or `Edit|Write|MultiEdit` matcher already exists from a prior phase (substrate-clarity-gate from 2.2.2, pattern-annotation-validate from 2.2.4), append both hooks to its `hooks` array — the matcher set widens to `Edit|Write|MultiEdit` when MultiEdit is not already covered:
832
-
833
- ```jsonc
834
- {
835
- "hooks": {
836
- "PreToolUse": [
837
- {
838
- "matcher": "Edit|Write|MultiEdit",
839
- "hooks": [
840
- { "type": "command", "command": "$CLAUDE_PROJECT_DIR/.claude/hooks/pre-commit-gate.sh" },
841
- { "type": "command", "command": "$CLAUDE_PROJECT_DIR/.claude/hooks/state-validate.sh" }
842
- ]
843
- }
844
- ]
845
- }
846
- }
847
- ```
848
-
849
- **Order matters** — `pre-commit-gate.sh` runs first (cheap SDLC checks), `state-validate.sh` runs second (heavier ajv-cli schema validation). The matcher block lists them in that order; a BLOCK from the first stops the chain before the second fires.
850
-
851
- **Rule propagation** — both rules (`sdlc-gates.md` + `state-schema-validation.md`) live at bassclef's `.claude/rules/` and load into adopter agent context via the `additionalDirectories: ["../bassclef"]` entry Phase 2.2 wrote. No copy needed; bassclef's rule body is the source of truth.
852
-
853
- **Composition rule** — when an existing PreToolUse Edit|Write matcher block is present from earlier Phase 2.x steps, append these two hooks to its `hooks` array (do not duplicate the matcher entry). Hook order within the array determines execution order; place `pre-commit-gate.sh` before `state-validate.sh` per the order rule above.
854
-
855
- **Override paths** — `SKIP_PRE_COMMIT_GATE=1 <command>` and `SKIP_STATE_VALIDATE=1 <command>` (both logged via trace-helper). Use only for one-shot migration scripts (state bootstrapping) or emergency rescue when the hook itself is broken.
856
-
857
- **Verify the wiring:**
858
-
859
- ```bash
860
- # Sanity: both hooks executable + reachable
861
- ls -l .claude/hooks/pre-commit-gate.sh .claude/hooks/state-validate.sh
862
-
863
- # Sanity: both rules reachable via additionalDirectories
864
- test -f ../bassclef/.claude/rules/sdlc-gates.md && echo "sdlc-gates reachable" || echo "sdlc-gates NOT reachable"
865
- test -f ../bassclef/.claude/rules/state-schema-validation.md && echo "state-schema-validation reachable" || echo "state-schema-validation NOT reachable"
866
-
867
- # Sanity: settings.json has both hooks wired in matcher block
868
- python3 -c "import json; d=json.load(open('.claude/settings.json')); \
869
- hooks=[h.get('command','') for entry in d.get('hooks',{}).get('PreToolUse',[]) for h in entry.get('hooks',[])]; \
870
- print('pre-commit-gate wired' if any('pre-commit-gate' in c for c in hooks) else 'NOT wired'); \
871
- print('state-validate wired' if any('state-validate' in c for c in hooks) else 'NOT wired')"
872
- ```
873
-
874
- Source: bassclef#1136 (this wiring step — T3, iteration-2 BLOCKER). Sister rules: `.claude/rules/sdlc-gates.md` + `.claude/rules/state-schema-validation.md`.
875
-
876
- ##### 2.2.6 Wire destructive-command-guard + multi-tenancy-check PreToolUse hooks (bassclef#1141 T8 — partial)
877
-
878
- **Lite adopter note (bassclef#740 Task 1.2).** Both hooks ship at `tier: standard`. Skip this step if your tier is lite. Resolve tier via `lib/tier-check.sh`. Continue with 2.2.7.
879
-
880
- Symlink two bassclef PreToolUse hooks that catch runtime-safety problems before they reach the operator's filesystem or database. `destructive-command-guard.sh` fires on Bash and detects destructive verbs + force flags + amplifiers (catches "prisma migrate reset", "rm -rf", "FLUSHALL" patterns). `multi-tenancy-check.sh` fires on Edit/Write of source files and warns when tenant-scoped patterns are missing (queries without tenant context).
881
-
882
- Bet 2026-06-18b scopes T8 to these two hooks; the ticket's other two (`operator-private-path-check.sh` + `type-check.sh`) are deferred to a follow-on per goal narrowing.
883
-
884
- Symlink both hooks:
885
-
886
- ```bash
887
- mkdir -p .claude/hooks
888
- ln -sf "../../../bassclef/.claude/hooks/destructive-command-guard.sh" \
889
- ".claude/hooks/destructive-command-guard.sh"
890
- ln -sf "../../../bassclef/.claude/hooks/multi-tenancy-check.sh" \
891
- ".claude/hooks/multi-tenancy-check.sh"
892
- ```
893
-
894
- Add both PreToolUse blocks to `.claude/settings.json`. The matchers differ — `destructive-command-guard` watches Bash; `multi-tenancy-check` watches Edit|Write|MultiEdit. The Edit|Write|MultiEdit block likely already exists from Phase 2.2.2 / 2.2.3 / 2.2.4 / 2.2.5 — append `multi-tenancy-check` to its `hooks` array (do not duplicate the matcher entry). The Bash block is new for most adopters; create it if absent.
895
-
896
- ```jsonc
897
- {
898
- "hooks": {
899
- "PreToolUse": [
900
- {
901
- "matcher": "Bash",
902
- "hooks": [
903
- { "type": "command", "command": "$CLAUDE_PROJECT_DIR/.claude/hooks/destructive-command-guard.sh" }
904
- ]
905
- },
906
- {
907
- "matcher": "Edit|Write|MultiEdit",
908
- "hooks": [
909
- { "type": "command", "command": "$CLAUDE_PROJECT_DIR/.claude/hooks/multi-tenancy-check.sh" }
910
- ]
911
- }
912
- ]
913
- }
914
- }
915
- ```
916
-
917
- **Customization** — `multi-tenancy-check.sh` is a template. Adopters with multi-tenant codebases override `TENANT_MODELS` + `TENANT_CONTEXT_FN` + `TENANT_PARAMS_FN` via env vars OR drop a custom `multi-tenancy-check.sh` in `.claude/hooks/` (which wins over the symlink). Single-tenant adopters can disable per-call with `SKIP_MULTI_TENANCY_CHECK=1`.
918
-
919
- **Rule propagation** — `.claude/rules/destructive-operations.md` loads into adopter agent context via the `additionalDirectories: ["../bassclef"]` entry Phase 2.2 wrote. No copy needed.
920
-
921
- **Composition rule** — Bash and Edit|Write|MultiEdit matchers stay separate; never collapse them. When other Phase 2.x steps add Bash hooks (Phase 2.2.7 ships atomic-pr-check on Bash; type-check on Bash if T8 follow-on ships), append to the Bash matcher's `hooks` array — do not duplicate the matcher entry.
922
-
923
- **Override paths** — `SKIP_DESTRUCTIVE_GUARD=1 <command>` (logged) and `SKIP_MULTI_TENANCY_CHECK=1 <command>` (logged). Both bypass logged via trace-helper. Use only for genuine cases (one-shot migrations, single-tenant repos where the check is noise).
924
-
925
- **Verify the wiring:**
926
-
927
- ```bash
928
- # Sanity: both hooks executable + reachable
929
- ls -l .claude/hooks/destructive-command-guard.sh .claude/hooks/multi-tenancy-check.sh
930
-
931
- # Sanity: destructive-operations rule reachable via additionalDirectories
932
- test -f ../bassclef/.claude/rules/destructive-operations.md && echo "destructive-operations reachable" || echo "NOT reachable"
933
-
934
- # Sanity: settings.json has both hooks wired with correct matchers
935
- python3 -c "import json; d=json.load(open('.claude/settings.json')); \
936
- bash_hooks=[h.get('command','') for entry in d.get('hooks',{}).get('PreToolUse',[]) if entry.get('matcher')=='Bash' for h in entry.get('hooks',[])]; \
937
- edit_hooks=[h.get('command','') for entry in d.get('hooks',{}).get('PreToolUse',[]) if 'Edit' in entry.get('matcher','') for h in entry.get('hooks',[])]; \
938
- print('destructive-command-guard wired (Bash)' if any('destructive-command-guard' in c for c in bash_hooks) else 'NOT wired (Bash)'); \
939
- print('multi-tenancy-check wired (Edit|Write|MultiEdit)' if any('multi-tenancy-check' in c for c in edit_hooks) else 'NOT wired (Edit|Write|MultiEdit)')"
940
- ```
941
-
942
- Source: bassclef#1141 (this wiring step — T8, runtime-safety chain). Sister rule: `.claude/rules/destructive-operations.md`. Follow-on: `operator-private-path-check.sh` + `type-check.sh` wires deferred from T8 goal scope.
943
-
944
- ##### 2.2.7 Wire atomic-pr-check + post-write-trace workflow hooks (bassclef#1142 T9)
945
-
946
- **Lite adopter note (bassclef#740 Task 1.2).** Both hooks ship at `tier: standard`. Skip this step if your tier is lite. Resolve tier via `lib/tier-check.sh`. Continue with the next step.
947
-
948
- Symlink two bassclef workflow hooks. `atomic-pr-check.sh` fires on Bash calls matching `git push` patterns and BLOCKs multi-step branches that lack `bundle: true` in the iteration goal's frontmatter — closes the silent atomic-PR-discipline gap that `.claude/rules/pr-strategy.md` describes. `post-write-trace.sh` fires on PostToolUse Write/Edit and records traceability rows so the agent can audit what wrote what.
949
-
950
- Symlink both hooks:
951
-
952
- ```bash
953
- mkdir -p .claude/hooks
954
- ln -sf "../../../bassclef/.claude/hooks/atomic-pr-check.sh" \
955
- ".claude/hooks/atomic-pr-check.sh"
956
- ln -sf "../../../bassclef/.claude/hooks/post-write-trace.sh" \
957
- ".claude/hooks/post-write-trace.sh"
958
- ```
959
-
960
- Add a PreToolUse Bash block + a PostToolUse Write|Edit block to `.claude/settings.json`. The Bash matcher likely already exists from Phase 2.2.6 (destructive-command-guard) — append `atomic-pr-check` to its `hooks` array. The PostToolUse block is new for most adopters.
961
-
962
- ```jsonc
963
- {
964
- "hooks": {
965
- "PreToolUse": [
966
- {
967
- "matcher": "Bash",
968
- "hooks": [
969
- { "type": "command", "command": "$CLAUDE_PROJECT_DIR/.claude/hooks/atomic-pr-check.sh" }
970
- ]
971
- }
972
- ],
973
- "PostToolUse": [
974
- {
975
- "matcher": "Write|Edit",
976
- "hooks": [
977
- { "type": "command", "command": "$CLAUDE_PROJECT_DIR/.claude/hooks/post-write-trace.sh" }
978
- ]
979
- }
980
- ]
981
- }
982
- }
983
- ```
984
-
985
- **Bet narrowing** — ticket #1142 (T9) also lists `post-skill-friction-check.sh`. The goal scopes this step to two hooks; the third deferred to a follow-on per goal shape.
986
-
987
- **Composition rule** — when the Bash matcher already exists (Phase 2.2.6 wires destructive-command-guard on the same matcher), append `atomic-pr-check` to its `hooks` array; do not duplicate the matcher entry. Hook order within the Bash array does not matter for these two — destructive-command-guard and atomic-pr-check check different signals (destructive verbs vs git-push patterns) and never conflict on the same command.
988
-
989
- **Rule propagation** — `.claude/rules/pr-strategy.md` (the methodology atomic-pr-check enforces) loads via `additionalDirectories`. No copy needed.
990
-
991
- **Override paths** — `SKIP_ATOMIC_PR_CHECK=1 <command>` (logged via trace-helper) bypasses the atomic-PR gate for genuine bundle cases that the goal's `bundle: true` flag did not capture. `post-write-trace.sh` has no override — the trace is append-only and never blocks.
992
-
993
- **Verify the wiring:**
994
-
995
- ```bash
996
- # Sanity: both hooks executable + reachable
997
- ls -l .claude/hooks/atomic-pr-check.sh .claude/hooks/post-write-trace.sh
998
-
999
- # Sanity: pr-strategy rule reachable via additionalDirectories
1000
- test -f ../bassclef/.claude/rules/pr-strategy.md && echo "pr-strategy reachable" || echo "NOT reachable"
1001
-
1002
- # Sanity: settings.json has both hooks wired with correct matchers
1003
- python3 -c "import json; d=json.load(open('.claude/settings.json')); \
1004
- bash_hooks=[h.get('command','') for entry in d.get('hooks',{}).get('PreToolUse',[]) if entry.get('matcher')=='Bash' for h in entry.get('hooks',[])]; \
1005
- post_hooks=[h.get('command','') for entry in d.get('hooks',{}).get('PostToolUse',[]) if 'Write' in entry.get('matcher','') or 'Edit' in entry.get('matcher','') for h in entry.get('hooks',[])]; \
1006
- print('atomic-pr-check wired (PreToolUse Bash)' if any('atomic-pr-check' in c for c in bash_hooks) else 'NOT wired'); \
1007
- print('post-write-trace wired (PostToolUse Write|Edit)' if any('post-write-trace' in c for c in post_hooks) else 'NOT wired')"
1008
- ```
1009
-
1010
- Source: bassclef#1142 (this wiring step — T9, workflow chain). Sister rule: `.claude/rules/pr-strategy.md`. Follow-on: `post-skill-friction-check.sh` wire deferred from T9 goal scope.
1011
-
1012
- ##### 2.2.8 Wire testing-tier-enforce + allowlist (bassclef#1143 T10)
1013
-
1014
- Symlink the bassclef testing-tier enforcer into adopter's `.claude/hooks/`. The hook covers Tier 0 through Tier 3. It does not register as its own PreToolUse entry. Instead it runs inside `pre-commit-gate.sh` from Phase 2.2.5. When an adopter edits a Tier 0 source file without touching its matching test file, `pre-commit-gate.sh` calls `testing-tier-enforce.sh`. The commit BLOCKs with a structured stderr message.
1015
-
1016
- Symlink both the hook and the allowlist baseline:
1017
-
1018
- ```bash
1019
- mkdir -p .claude/hooks
1020
- ln -sf "../../../bassclef/.claude/hooks/testing-tier-enforce.sh" \
1021
- ".claude/hooks/testing-tier-enforce.sh"
1022
- ln -sf "../../../bassclef/.claude/hooks/testing-tier-enforce-allowlist.txt" \
1023
- ".claude/hooks/testing-tier-enforce-allowlist.txt"
623
+ for r in sdlc-gates state-schema-validation testing-tier-config test-list-discipline \
624
+ test-sufficiency destructive-operations pattern-annotation pr-strategy; do
625
+ test -f ../bassclef/.claude/rules/${r}.md && echo "${r} reachable" || echo "${r} NOT reachable"
626
+ done
1024
627
  ```
1025
628
 
1026
- The allowlist baseline grandfathers existing untested adopter source files for 60 days (the default grace window). Adopter operators can backfill tests as files are next touched, OR adjust the grace window per `testing-tier-config.md` § Allowlist.
1027
-
1028
- **Composition chain** — `pre-commit-gate.sh` (Phase 2.2.5) calls `testing-tier-enforce.sh` as one of its check steps. No new PreToolUse settings.json entry is needed; the hook fires whenever pre-commit-gate fires (PreToolUse Edit|Write|MultiEdit). This is the chained-composition pattern: Phase 2.2.5 wired the parent gate; Phase 2.2.8 plugs the tier-enforce check into the existing chain.
1029
-
1030
- **Goal-vs-implementation note** — the goal 2026-06-18b WU-4 acceptance describes `testing-tier-enforce.sh` as "PreToolUse Edit|Write" wiring. The actual wiring is via pre-commit-gate composition (no separate matcher entry). Documented per the actual implementation.
1031
-
1032
- **Rule propagation** — `.claude/rules/testing-tier-config.md` + `.claude/rules/test-list-discipline.md` + `.claude/rules/test-sufficiency.md` load via `additionalDirectories`. No copy needed.
629
+ **Composed hook: testing-tier-enforce** Row 11 fires inside `.claude/hooks/pre-commit-gate.sh` as one of its check steps (no separate matcher entry in `.claude/settings.json`). The symlink at `.claude/hooks/testing-tier-enforce.sh` + the allowlist at `.claude/hooks/testing-tier-enforce-allowlist.txt` are enough; the enforcer runs whenever pre-commit-gate fires (PreToolUse Edit|Write|MultiEdit). Grace window: 60 days on the allowlist baseline. When an adopter edits a Tier 0 source file without touching its matching test file, pre-commit-gate calls `.claude/hooks/testing-tier-enforce.sh` and the commit BLOCKs with a structured stderr message.
1033
630
 
1034
- **Override path** `SKIP_TESTING_TIER_ENFORCE=1 <command>` (logged via trace-helper). Use only for one-shot migration scripts that bootstrap test files into the spine.
1035
-
1036
- **Verify the wiring:**
631
+ Sanity check that the hook is reachable and composed into pre-commit-gate:
1037
632
 
1038
633
  ```bash
1039
- # Sanity: hook + allowlist reachable
1040
634
  ls -l .claude/hooks/testing-tier-enforce.sh .claude/hooks/testing-tier-enforce-allowlist.txt
1041
-
1042
- # Sanity: pre-commit-gate composes testing-tier-enforce
1043
635
  grep -q "testing-tier-enforce.sh" .claude/hooks/pre-commit-gate.sh \
1044
636
  && echo "tier-enforce composed in pre-commit-gate" \
1045
- || echo "NOT composed (pre-commit-gate may be stale; resync bassclef)"
1046
-
1047
- # Sanity: testing-tier-config rule reachable
1048
- test -f ../bassclef/.claude/rules/testing-tier-config.md && echo "tier-config rule reachable" || echo "NOT reachable"
1049
- ```
1050
-
1051
- The `testing.path_matchers` seed (per-tech-stack defaults) lands in Phase 2.3.7 below — that is the step the goal flagged for operator-eyes design choices.
1052
-
1053
- Source: bassclef#1143 (this wiring step — T10, iteration-2 BLOCKER). Sister rules: `.claude/rules/testing-tier-config.md` + `.claude/rules/test-list-discipline.md` + `.claude/rules/test-sufficiency.md`. Pairs with Phase 2.2.5 (pre-commit-gate parent chain).
1054
-
1055
- ##### 2.2.9 Verify test-discipline rules propagate to the adopter session (bassclef#1144 T11)
1056
-
1057
- The two test-discipline rules propagate to the adopter session on their own. Those rules are `.claude/rules/test-list-discipline.md` (Beck's test list as planning artifact) and `.claude/rules/test-sufficiency.md` (10-criterion rubric per Myers + Hoare).
1058
-
1059
- The `additionalDirectories: ["../bassclef"]` entry that Phase 2.2 wrote does the work. It tells Claude Code to load every file under bassclef's `.claude/rules/` into the adopter's session context at session-start.
1060
-
1061
- No copy needed. No per-rule symlink needed.
1062
-
1063
- This step is the explicit verification — without it, the install is silent and the adopter does not know the rules are live.
1064
-
1065
- Verify the rules are reachable + loaded:
1066
-
1067
- ```bash
1068
- # Sanity: both rule files reachable via additionalDirectories
1069
- test -f ../bassclef/.claude/rules/test-list-discipline.md \
1070
- && echo "test-list-discipline reachable" \
1071
- || echo "test-list-discipline NOT reachable"
1072
- test -f ../bassclef/.claude/rules/test-sufficiency.md \
1073
- && echo "test-sufficiency reachable" \
1074
- || echo "test-sufficiency NOT reachable"
1075
-
1076
- # Sanity: settings.json carries the additionalDirectories entry
1077
- python3 -c "import json; d=json.load(open('.claude/settings.json')); \
1078
- dirs=d.get('permissions',{}).get('additionalDirectories',[]); \
1079
- print('bassclef loaded via additionalDirectories' if '../bassclef' in dirs else 'NOT loaded — check Phase 2.2 wiring')"
637
+ || echo "NOT composed (pre-commit-gate may be stale; re-run bassclef-sync)"
1080
638
  ```
1081
639
 
1082
- **What this gives the adopter** — every adopter session that touches a test file gets the Beck test-list discipline (open with `# test-list:` block; mark `[x]` as each assertion ships; pending `[ ]` lines are honest in-flight signal) AND the 10-criterion sufficiency rubric (branch coverage / exit-code matrix / matcher coverage / override paths / stdin contract / external-binary handling / trap cleanup / stderr format / state-file interactions). Together they catch tests that pass but miss the intended assertion — the failure class eugene-supplements hit when 26 tests landed after source with zero asserted intent visible.
640
+ **Override paths** — each hook honors a `SKIP_*` env var (logged via trace-helper per bassclef override idiom). Use only for one-shot migrations or emergency rescue:
1083
641
 
1084
- **Composition** the rules pair with Phase 2.2.5 (`pre-commit-gate.sh` parent chain) + Phase 2.2.8 (`testing-tier-enforce.sh` Tier 0/1/2/3 mechanical enforcer). Methodology layer (rules) supplies the why; mechanical layer (hooks) fires at the moment of failure.
1085
-
1086
- **No override needed** — rules are read-only context; they neither block writes nor produce stderr. Adopters can choose to ignore the rules per session, but the agent's own self-check during artifact-write keeps them honest.
1087
-
1088
- Source: bassclef#1144 (this propagation step — T11, iteration-2 BLOCKER). Sister rules: `.claude/rules/test-list-discipline.md` + `.claude/rules/test-sufficiency.md`. Pairs with Phase 2.2.8 (the enforcer the rules guide).
1089
-
1090
- ##### 2.2.10 Wire role-entry-gate PreToolUse hook (bassclef#1145 T13)
1091
-
1092
- **Lite adopter note (bassclef#740 Task 1.2).** This hook ships at `tier: standard`. Skip this step if your tier is lite. Resolve tier via `lib/tier-check.sh`.
1093
-
1094
- Symlink the bassclef PreToolUse hook that catches source-code edits when the matching agent role has not been entered for the current session. MVP scope: Builder role only (matches source files in common languages). Other roles (Architect, Reviewer, Designer) deferred to a follow-on per goal narrowing — the multi-role matching matrix deserves its own design pass.
1095
-
1096
- The hook reads `$CWD/state/markers/role/<role>/<session_id>.marker`. The marker is written by the agent once the role's persona has been loaded (sequential mode: Claude reads `~/.claude/agents/builder.md`, writes the marker, proceeds with the role's discipline loaded; orchestrator-gated mode: Orchestrator routes the dispatch to the Builder agent which writes its own marker before proceeding).
1097
-
1098
- Symlink the hook:
1099
-
1100
- ```bash
1101
- mkdir -p .claude/hooks
1102
- ln -sf "../../../bassclef/.claude/hooks/role-entry-gate.sh" \
1103
- ".claude/hooks/role-entry-gate.sh"
1104
- ```
1105
-
1106
- Add to the PreToolUse Edit|Write|MultiEdit matcher block in `.claude/settings.json`. The matcher likely exists from earlier Phase 2.x steps (substrate-clarity-gate from 2.2.2, pattern-annotation-validate from 2.2.4, the parent gate chain from 2.2.5) — append `role-entry-gate` to its `hooks` array; do not duplicate the matcher entry.
1107
-
1108
- ```jsonc
1109
- {
1110
- "hooks": {
1111
- "PreToolUse": [
1112
- {
1113
- "matcher": "Edit|Write|MultiEdit",
1114
- "hooks": [
1115
- { "type": "command", "command": "$CLAUDE_PROJECT_DIR/.claude/hooks/role-entry-gate.sh" }
1116
- ]
1117
- }
1118
- ]
1119
- }
1120
- }
1121
- ```
1122
-
1123
- **MVP scope** — the hook fires on source-code file extensions only (`.ts`, `.tsx`, `.js`, `.jsx`, `.py`, `.rb`, `.go`, `.rs`, `.java`, `.kt`, `.swift`, `.cs`, `.cpp`, `.c`, `.h`). Non-source paths pass through. Tightening per `tech_stack.lang` reading (so a Python adopter only fires on `.py`) is a follow-on; the safe default union catches the common cases.
1124
-
1125
- **Marker writing** — the agent writes the marker once it enters the role. Marker shape:
1126
-
1127
- ```json
1128
- {
1129
- "role": "builder",
1130
- "session_id": "<uuid from harness>",
1131
- "entered_at": "<ISO 8601 UTC>"
1132
- }
1133
- ```
1134
-
1135
- A future `/role-entry` skill automates the marker write + persona load; until then, the agent writes the marker by hand after reading the persona file. The BLOCK message documents the exact one-liner.
1136
-
1137
- **Composition rule** — when the Edit|Write|MultiEdit matcher block already exists, append `role-entry-gate` to its `hooks` array. Order within the array: place `role-entry-gate` AFTER substrate-clarity-gate + artifact-ingestion-gate + pattern-annotation-validate + pre-commit-gate + state-validate + multi-tenancy-check, so structural / format / state validation fires first; role-discipline check fires last. Role-entry is the methodology gate, not the structural gate — it should not run before the cheap structural checks pass.
1138
-
1139
- **Override path** — `SKIP_ROLE_ENTRY=1 <command>` (logged via trace-helper). Use for one-shot scripts the operator runs without entering an agent role, OR when the adopter is on a workflow that does not map to bassclef's role taxonomy.
1140
-
1141
- **Verify the wiring:**
1142
-
1143
- ```bash
1144
- # Sanity: hook executable + reachable
1145
- ls -l .claude/hooks/role-entry-gate.sh
1146
-
1147
- # Sanity: agent personas reachable via additionalDirectories (the BLOCK message refers to them)
1148
- test -f ~/.claude/agents/builder.md && echo "builder persona reachable" || echo "builder persona NOT reachable (user-level agents missing)"
1149
-
1150
- # Sanity: settings.json has the hook wired under the Edit matcher
1151
- python3 -c "import json; d=json.load(open('.claude/settings.json')); \
1152
- hooks=[h.get('command','') for entry in d.get('hooks',{}).get('PreToolUse',[]) if 'Edit' in entry.get('matcher','') for h in entry.get('hooks',[])]; \
1153
- print('role-entry-gate wired' if any('role-entry-gate' in c for c in hooks) else 'NOT wired')"
1154
- ```
1155
-
1156
- **Not yet wired in bassclef** — this hook ships to the adopter via `/onboard-repo` first. Bassclef's own settings.json adds the hook in a follow-on once the marker convention has run in the wild for a few sessions and the multi-role matching follow-on lands.
1157
-
1158
- Source: bassclef#1145 (this hook step — T13). Sister agent personas: `~/.claude/agents/builder.md` (MVP target) + `~/.claude/agents/architect.md` + `~/.claude/agents/reviewer.md` + `~/.claude/agents/designer.md` (follow-on coverage). Follow-on tickets: multi-role matching matrix + `/role-entry` skill + `state/markers/role/` schema authoring under `standards/state-spine.md`.
1159
-
1160
- ##### 2.2.11 Wire temperance-gate PreToolUse hook (bassclef#1147 T15)
1161
-
1162
- Symlink the bassclef hook that fires the /temperance question at decision boundaries. MVP scope: one active trigger — "high-impact path edit". It catches edits to `.claude/`, `standards/`, `lib/state.sh`, and SKILL.md files when the session has no fresh temperance marker. Other triggers stay as stubs. Follow-on tickets will design them.
1163
-
1164
- <!-- FKGL-EXEMPT: source ticket enumeration -->
1165
- Sources: `2026-06-18b` WU-7 goal (explain-mode entry, chain-anchor entry, non-stacked-branch first edit, post-compaction recovery); ticket #1147 (N consecutive edits, substrate proposal without catalog browse, diagnose-repro marker absence).
1166
- <!-- /FKGL-EXEMPT -->
1167
-
1168
- The hook pairs with `pre-commit-gate.sh` from Phase 2.2.5. That hook handles the first edit on a branch that stands alone. This hook adds one more check. It catches edits to high-impact paths that the other hook misses.
1169
-
1170
- Symlink the hook:
1171
-
1172
- ```bash
1173
- mkdir -p .claude/hooks
1174
- ln -sf "../../../bassclef/.claude/hooks/temperance-gate.sh" \
1175
- ".claude/hooks/temperance-gate.sh"
1176
- ```
1177
-
1178
- Add to the PreToolUse Edit|Write|MultiEdit matcher block in `.claude/settings.json`. The matcher likely already exists; append `temperance-gate` to its `hooks` array. Order: place `temperance-gate` AFTER structural checks (substrate-clarity-gate, artifact-ingestion-gate, pattern-annotation-validate, pre-commit-gate, state-validate, multi-tenancy-check) and AFTER role-entry-gate. Methodology gate fires last; structural + role checks fire first.
1179
-
1180
- ```jsonc
1181
- {
1182
- "hooks": {
1183
- "PreToolUse": [
1184
- {
1185
- "matcher": "Edit|Write|MultiEdit",
1186
- "hooks": [
1187
- { "type": "command", "command": "$CLAUDE_PROJECT_DIR/.claude/hooks/temperance-gate.sh" }
1188
- ]
1189
- }
1190
- ]
1191
- }
1192
- }
1193
- ```
1194
-
1195
- **Marker convention** — the hook reads `$CWD/state/markers/temperance/<session_id>.marker` (session-scoped) AND falls back to any existing marker under `state/markers/temperance/` (loose branch-scoped check; tighter matching-branch check is a follow-on). The temperance marker is written by the agent (or by `/temperance` skill invocation) once the right-thing / right-way questions have been answered.
1196
-
1197
- **Marker shape:**
1198
-
1199
- ```json
1200
- {
1201
- "session_id": "<uuid from harness>",
1202
- "entered_at": "<ISO 8601 UTC>",
1203
- "question_answered": "yes"
1204
- }
1205
- ```
1206
-
1207
- **Override path** — `SKIP_TEMPERANCE_GATE=1 <command>` (logged via trace-helper). Use sparingly; the trigger is the point of the discipline.
1208
-
1209
- **Verify the wiring:**
1210
-
1211
- ```bash
1212
- # Sanity: hook executable + reachable
1213
- ls -l .claude/hooks/temperance-gate.sh
1214
-
1215
- # Sanity: temperance skill reachable via additionalDirectories
1216
- test -f ../bassclef/.claude/skills/temperance/SKILL.md && echo "temperance skill reachable" || echo "NOT reachable"
1217
-
1218
- # Sanity: settings.json has the hook wired under the Edit matcher
1219
- python3 -c "import json; d=json.load(open('.claude/settings.json')); \
1220
- hooks=[h.get('command','') for entry in d.get('hooks',{}).get('PreToolUse',[]) if 'Edit' in entry.get('matcher','') for h in entry.get('hooks',[])]; \
1221
- print('temperance-gate wired' if any('temperance-gate' in c for c in hooks) else 'NOT wired')"
1222
- ```
1223
-
1224
- **Not yet wired in bassclef** — adopters first; bassclef's own settings.json adds the hook in a follow-on once the MVP trigger has run in the wild for a few sessions and the trigger-taxonomy follow-on lands.
1225
-
1226
- Source: bassclef#1147 (this hook step — T15). Sister skill: `.claude/skills/temperance/SKILL.md` (the methodology this gate enforces mechanically). Follow-on tickets: explain-mode + chain-anchor + post-compaction + non-stacked first edit + N consecutive edits + substrate proposal + diagnose-repro triggers + `standards/temperance-discipline.md` documenting the full trigger taxonomy.
642
+ | Hook | Override |
643
+ |---|---|
644
+ | turn-prose-kiss-check | (toggle via `prose_discipline.kiss_words_turn_prose: false` in bassclef-configs) |
645
+ | substrate-clarity-gate | `SKIP_SUBSTRATE_CLARITY=1` |
646
+ | artifact-ingestion-gate | `SKIP_ARTIFACT_INGESTION=1` |
647
+ | pattern-annotation-validate | `SKIP_PATTERN_ANNOTATION=1` |
648
+ | pre-commit-gate | `SKIP_PRE_COMMIT_GATE=1` |
649
+ | state-validate | `SKIP_STATE_VALIDATE=1` |
650
+ | destructive-command-guard | `SKIP_DESTRUCTIVE_GUARD=1` |
651
+ | multi-tenancy-check | `SKIP_MULTI_TENANCY_CHECK=1` |
652
+ | atomic-pr-check | `SKIP_ATOMIC_PR_CHECK=1` |
653
+ | post-write-trace | (none — append-only trace never blocks) |
654
+ | testing-tier-enforce | `SKIP_TESTING_TIER_ENFORCE=1` |
655
+ | role-entry-gate | `SKIP_ROLE_ENTRY=1` |
656
+ | temperance-gate | `SKIP_TEMPERANCE_GATE=1` |
657
+
658
+ **Not yet wired in bassclef** — `role-entry-gate` and `temperance-gate` ship to adopters first. Bassclef's own settings.json adds them in a follow-on after the marker convention runs in the wild for a few sessions and the multi-role + trigger-taxonomy follow-ons land.
659
+
660
+ Source: bassclef#1136 T3 (pre-commit-gate + state-validate), bassclef#1137 T4 (substrate-clarity-gate), bassclef#1138 T5 (turn-prose-kiss-check), bassclef#1139 T6 (pattern-annotation-validate), bassclef#1140 T7 (artifact-ingestion-gate), bassclef#1141 T8 (destructive-command-guard + multi-tenancy-check), bassclef#1142 T9 (atomic-pr-check + post-write-trace), bassclef#1143 T10 (testing-tier-enforce), bassclef#1144 T11 (test-discipline rule propagation), bassclef#1145 T13 (role-entry-gate), bassclef#1147 T15 (temperance-gate). Follow-ons deferred: `operator-private-path-check`, `type-check`, `post-skill-friction-check`, `role-entry` skill, multi-role matcher matrix, `standards/temperance-discipline.md`.
1227
661
 
1228
662
  ##### 2.3 Create the project config file
1229
663
 
@@ -1244,7 +678,7 @@ for:
1244
678
  If operator says "defer", scaffold with placeholders and `TODO:` markers
1245
679
  so next session surfaces them.
1246
680
 
1247
- ##### 2.3.5 Write the bassclef-configs adopter-default seed (bassclef#1135 WU-4)
681
+ ##### 2.3.5 Write the bassclef-configs adopter-default seed
1248
682
 
1249
683
  Write `.claude/bassclef-configs.jsonc` with the adopter-default seed.
1250
684
  Every downstream hook + skill reads from this file; without it, defaults
@@ -1336,7 +770,7 @@ Expect a single `valid` line. The file is now the single source of truth for ado
1336
770
 
1337
771
  If the adopter has a pre-existing `.claude/bassclef-configs.jsonc` from a prior SENTINEL_bassclef_version, prompt before overwriting; offer a `--merge` flow (operator-driven; not automated in V1).
1338
772
 
1339
- ##### 2.3.6 Discover and write the tech_stack block (bassclef#1127 WU-2)
773
+ ##### 2.3.6 Discover and write the tech_stack block
1340
774
 
1341
775
  Stack-bound rules + standards in bassclef (`api-conventions.md`, `sdlc-gates.md`, `schema-management.md`, `new-dependency-check.md`, `frontend-stack.md`, `deployment-topology.md`) read `tech_stack:` from `.claude/bassclef-configs.jsonc` to route per-stack discipline. Without the block, non-matching adopters see false-fires (Prisma rules at SQLAlchemy adopters, Next.js API conventions at FastAPI adopters, etc.). This step writes the block so the bleed stops at install time.
1342
776
 
@@ -1456,7 +890,7 @@ Expect `valid`. If the file fails to validate, revert the append, surface the sc
1456
890
  - Phase 2.5 (security scanning) reads `tech_stack.lang` to seed the scanner adapter.
1457
891
  - Future Phase 2.x for `hook_chain` reads stack signals to pick per-stack hook defaults.
1458
892
 
1459
- ##### 2.3.7 Seed testing.path_matchers per declared tech_stack (bassclef#1143 T10)
893
+ ##### 2.3.7 Seed testing.path_matchers per declared tech_stack
1460
894
 
1461
895
  Phase 2.3.5 wrote the `testing` block with `global_floor: 1` + empty `path_matchers`. Phase 2.3.6 just discovered + wrote `tech_stack`. This step reads `tech_stack.lang` and seeds `testing.path_matchers` with sensible per-stack defaults so the Tier 0 / Tier 1 enforcer (Phase 2.2.8) fires on the right paths from day one.
1462
896
 
@@ -1532,7 +966,7 @@ Expect a single `valid` line. The `testing.path_matchers` items must validate ag
1532
966
 
1533
967
  Source: bassclef#1143 (this seed step — T10, iteration-2 BLOCKER). Sister rule: `.claude/rules/testing-tier-config.md`. Pairs with Phase 2.2.8 (the enforcer that reads this seed).
1534
968
 
1535
- ##### 2.3.8 Surface the wiki_sync toggle (bassclef#1265 — Phase 1 stub)
969
+ ##### 2.3.8 Surface the wiki_sync toggle
1536
970
 
1537
971
  The `wiki_sync` block in `.claude/bassclef-configs.jsonc` controls whether the adopter's repo gets the bassclef-docs-sync workflow vendored from `presence/install/bassclef-docs-sync.template.yml`. This step surfaces the toggle so adopters see the option exists.
1538
972
 
@@ -1561,7 +995,7 @@ The Phase 1 stub keeps this step minimal so the goal stays bounded. Adopters who
1561
995
 
1562
996
  Source: bassclef#1265 (this surfacing step — wiki-sync mechanism adopter inheritance). Sister bet: `docs/iteration-bets/2026-06-20b-cold-adopter-mechanism-inheritance.md` WU-2.
1563
997
 
1564
- ##### 2.3.9 Write the onboard-repo state marker (bassclef-upstream#664)
998
+ ##### 2.3.9 Write the onboard-repo state marker
1565
999
 
1566
1000
  Write `.claude/state/onboard-repo.state.json` after Phase 2.3 has
1567
1001
  populated the config file(s). The marker captures which mode was used,
@@ -1593,7 +1027,7 @@ pin all behavior including re-run history append.
1593
1027
  Source: bassclef-upstream#664 (state marker for onboard-repo). Part of goal
1594
1028
  `docs/iteration-bets/2026-07-08a-configs-ui-iteration-1.md` WU-4.
1595
1029
 
1596
- ##### 2.3.10 Wire the cron installer for auto-save (bassclef-upstream#941)
1030
+ ##### 2.3.10 Wire the cron installer for auto-save
1597
1031
 
1598
1032
  Goal 27b (PR #937) shipped `presence/install/schedule-auto-save.cron.sh` at
1599
1033
  `tier: lite`. The installer writes a cron entry that fires
@@ -1651,7 +1085,7 @@ fires (Cloud Env / mobile / fresh sandboxes / CI). Schema codified at
1651
1085
  `standards/bassclef-source-config.md`; validation hook at
1652
1086
  `.claude/hooks/bassclef-source-config-validate.sh`.
1653
1087
 
1654
- Before writing the file, prompt the adopter explicitly (per bassclef#939):
1088
+ Before writing the file, prompt the adopter explicitly:
1655
1089
 
1656
1090
  ```
1657
1091
  Bassclef can auto-pull the latest skills, rules, and agents into this
@@ -1765,7 +1199,7 @@ PY
1765
1199
  Note: the Python merge re-serializes the file without comments. Operators
1766
1200
  keep the schema-doc reference (`standards/bassclef-configs-schema.md`)
1767
1201
  as the bassclef comment-bearing source; the on-disk file is the values.
1768
- A follow-on (bassclef#1135 V2) may add a comment-preserving JSONC writer.
1202
+ A follow-on may add a comment-preserving JSONC writer.
1769
1203
 
1770
1204
  INSTEAD of asking the operator to know the scanner names: the standard supplies the per-stack defaults; the operator confirms the stack choice only.
1771
1205
 
@@ -1819,7 +1253,7 @@ orientation into every session. The orientation names the gates, the
1819
1253
  luminaries, the tier ladder, and the rules the agent should not break.
1820
1254
 
1821
1255
  The orientation file lands in the adopter repo as a symlink into bassclef.
1822
- The sync template Section 3d-bis writes the symlink (per bassclef-upstream#925).
1256
+ The sync template Section 3d-bis writes the symlink.
1823
1257
  Without this symlink, the import resolves only through `additionalDirectories`.
1824
1258
  If that path breaks — rename, delete, corporate laptop with no sibling — the
1825
1259
  import silently no-ops. The symlink closes that gap.
@@ -1864,7 +1298,7 @@ cp ~/src/sunj-labs/bassclef/templates/whereami-template.md \
1864
1298
  Operator fills in phase + iteration section. If repo is fresh,
1865
1299
  `phase: Inception` with `iteration_bet: none — new repo` is fine.
1866
1300
 
1867
- #### Phase 3.5 — Optional: provision the deploy host + bootstrap secrets (bassclef#522)
1301
+ #### Phase 3.5 — Optional: provision the deploy host + bootstrap secrets
1868
1302
 
1869
1303
  **Working directory: target repo.**
1870
1304
 
@@ -1884,7 +1318,7 @@ still supported).
1884
1318
  | `/onboard-repo --full` | All of the above — substrate scaffolded + Amplify host provisioned + secrets audited in one dispatch. Recommended for new sunj-labs repos. |
1885
1319
  | `/onboard-repo --greenfield-from-intent "<intent>"` | Cold-adopter demo path. Skips Path A entirely and runs Path B — empty directory in, full artifact chain on disk plus localhost gallery URL out. No GitHub repo gets created. No vendor accounts needed. Uses the LLM your Claude Code session provides. For the extended path (deploy mocks to a configured subdomain plus chain to `/build` plus `/launch-preview`), finish Path A first to wire vendor bindings, then dispatch `/launch --voice-input` without `--local`. See `docs/iteration-bets/2026-05-12-phase-v-hey-alexa-mvd.md` and bassclef#923 / PR #924 for the local-mode building block. |
1886
1320
 
1887
- ##### Tier gate (bassclef#740 Task 1.2)
1321
+ ##### Tier gate
1888
1322
 
1889
1323
  Three of the flags above dispatch skills that ship at `tier: standard`.
1890
1324
  Lite adopters running the bassclef-lite tarball do not carry
@@ -1918,8 +1352,8 @@ graceful degrade.
1918
1352
  ##### Interactive prompt (when no flag)
1919
1353
 
1920
1354
  After Phase 3 completes, agent surfaces follow-on prompts. Prompts are
1921
- gated on artifact existence (bassclef#961) and the deploy-host prompt
1922
- uses honest platform framing (bassclef#962):
1355
+ gated on artifact existence and the deploy-host prompt
1356
+ uses honest platform framing:
1923
1357
 
1924
1358
  ```bash
1925
1359
  # Check for substrate.secrets.md (bassclef#961) — silently skip the
@@ -1991,7 +1425,7 @@ onboarding_secrets_skipped: true # set when operator answers 'skip'
1991
1425
  `n` (decline-this-time) does NOT persist — re-runs re-prompt because the
1992
1426
  operator didn't say skip-permanently.
1993
1427
 
1994
- `Y` sets the per-platform provisioning indicator (e.g., `amplify_app_id`) on success. Chain pre-flight Check 6 (bassclef#523) reads that indicator when /launch dispatches. Without it, /launch BLOCKs with three-path remediation. The two flags pair well. `--with-deploy-host` pre-empts the BLOCK. The default flow lets the BLOCK surface the missing setup.
1428
+ `Y` sets the per-platform provisioning indicator (e.g., `amplify_app_id`) on success. Chain pre-flight Check 6 reads that indicator when /launch dispatches. Without it, /launch BLOCKs with three-path remediation. The two flags pair well. `--with-deploy-host` pre-empts the BLOCK. The default flow lets the BLOCK surface the missing setup.
1995
1429
 
1996
1430
  ##### Composes with
1997
1431
 
@@ -2002,7 +1436,7 @@ operator didn't say skip-permanently.
2002
1436
  | `/bind-subdomain <subdomain>` | Separate dispatch — not chained from /onboard-repo (subdomain choice is repo-specific; no good default). Run after deploy host provisioned. |
2003
1437
  | `/launch` | First substantive dispatch after onboarding completes. Chain pre-flight Check 6 verifies the provisioning indicator before variant generation runs. |
2004
1438
 
2005
- #### Phase 3.6 — Closing handoff (bassclef#964)
1439
+ #### Phase 3.6 — Closing handoff
2006
1440
 
2007
1441
  After Phase 3 (and Phase 3.5 if any flag fired), Path A surfaces a
2008
1442
  closing handoff. Two templates — adopter-mode and operator-mode —