@thebassclef/lite 0.1.2 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (293) hide show
  1. package/dist/cli.cjs +238 -127
  2. package/dist/cli.js +240 -129
  3. package/dist/index.cjs +1 -1
  4. package/dist/index.d.ts +1 -1
  5. package/dist/index.js +1 -1
  6. package/dist/lite/.bassclef-source.json +10 -0
  7. package/dist/lite/.claude/settings.json +212 -0
  8. package/dist/lite/CLAUDE.md +41 -0
  9. package/dist/lite/gitignore +58 -0
  10. package/dist/lite/standards/bassclef-wiring-manifest.json +497 -0
  11. package/dist/lite/whereami.md +24 -0
  12. package/package.json +8 -2
  13. package/substrate/.bassclef/lite-manifest.json +0 -2701
  14. package/substrate/.claude/agents/architect.md +0 -70
  15. package/substrate/.claude/agents/builder.md +0 -114
  16. package/substrate/.claude/agents/designer.md +0 -156
  17. package/substrate/.claude/agents/reviewer.md +0 -88
  18. package/substrate/.claude/hooks/artifact-ingestion-gate.sh +0 -357
  19. package/substrate/.claude/hooks/assert-verify-steering.sh +0 -77
  20. package/substrate/.claude/hooks/bassclef-source-config-validate.sh +0 -215
  21. package/substrate/.claude/hooks/bassclef-sync.sh +0 -634
  22. package/substrate/.claude/hooks/compound-noun-scrub.sh +0 -292
  23. package/substrate/.claude/hooks/kiss-expansion-inject.sh +0 -69
  24. package/substrate/.claude/hooks/longrun-prep-compounding-axis-check.sh +0 -492
  25. package/substrate/.claude/hooks/longrun-prep-compounding-sequence-check.sh +0 -492
  26. package/substrate/.claude/hooks/plain-english-steering.sh +0 -156
  27. package/substrate/.claude/hooks/post-skill-friction-check.sh +0 -177
  28. package/substrate/.claude/hooks/post-skill-telemetry.sh +0 -62
  29. package/substrate/.claude/hooks/pre-build-gate.sh +0 -511
  30. package/substrate/.claude/hooks/pre-commit-gate.sh +0 -451
  31. package/substrate/.claude/hooks/session-end.sh +0 -433
  32. package/substrate/.claude/hooks/session-reflection.sh +0 -303
  33. package/substrate/.claude/hooks/skill-body-grade-gate.sh +0 -219
  34. package/substrate/.claude/hooks/skill-body-intent-drift.sh +0 -107
  35. package/substrate/.claude/hooks/skill-step-list-check.sh +0 -171
  36. package/substrate/.claude/hooks/state-validate.sh +0 -271
  37. package/substrate/.claude/hooks/substrate-clarity-gate.sh +0 -1110
  38. package/substrate/.claude/hooks/temperance-gate.sh +0 -147
  39. package/substrate/.claude/hooks/testing-tier-enforce.sh +0 -233
  40. package/substrate/.claude/hooks/turn-prose-grade-measure.sh +0 -219
  41. package/substrate/.claude/hooks/turn-prose-kiss-check.sh +0 -463
  42. package/substrate/.claude/hooks/vocabulary-migration-check.sh +0 -171
  43. package/substrate/.claude/hooks/whereami-utc-gate.sh +0 -142
  44. package/substrate/.claude/luminaries/alan-cooper.md +0 -170
  45. package/substrate/.claude/luminaries/alistair-cockburn.md +0 -140
  46. package/substrate/.claude/luminaries/amazon-pr-faq.md +0 -34
  47. package/substrate/.claude/luminaries/ash-maurya.md +0 -121
  48. package/substrate/.claude/luminaries/bill-buxton.md +0 -210
  49. package/substrate/.claude/luminaries/charles-sanders-peirce.md +0 -150
  50. package/substrate/.claude/luminaries/david-ogilvy.md +0 -192
  51. package/substrate/.claude/luminaries/don-norman.md +0 -173
  52. package/substrate/.claude/luminaries/edward-tufte.md +0 -179
  53. package/substrate/.claude/luminaries/eric-evans.md +0 -160
  54. package/substrate/.claude/luminaries/frederick-brooks.md +0 -50
  55. package/substrate/.claude/luminaries/gang-of-four.md +0 -157
  56. package/substrate/.claude/luminaries/glenford-myers.md +0 -230
  57. package/substrate/.claude/luminaries/hunt-thomas.md +0 -115
  58. package/substrate/.claude/luminaries/hyrum-wright.md +0 -94
  59. package/substrate/.claude/luminaries/jason-fried-dhh.md +0 -46
  60. package/substrate/.claude/luminaries/jesse-james-garrett.md +0 -154
  61. package/substrate/.claude/luminaries/john-ousterhout.md +0 -94
  62. package/substrate/.claude/luminaries/karl-popper.md +0 -132
  63. package/substrate/.claude/luminaries/kent-beck.md +0 -168
  64. package/substrate/.claude/luminaries/linus-torvalds.md +0 -218
  65. package/substrate/.claude/luminaries/martin-fowler.md +0 -164
  66. package/substrate/.claude/luminaries/michael-feathers.md +0 -125
  67. package/substrate/.claude/luminaries/michael-nygard.md +0 -118
  68. package/substrate/.claude/luminaries/robert-c-martin.md +0 -164
  69. package/substrate/.claude/luminaries/saltzer-schroeder.md +0 -194
  70. package/substrate/.claude/luminaries/sophia-prater.md +0 -193
  71. package/substrate/.claude/luminaries/stephen-toulmin.md +0 -131
  72. package/substrate/.claude/luminaries/tony-hoare.md +0 -170
  73. package/substrate/.claude/luminaries/vaughn-vernon.md +0 -50
  74. package/substrate/.claude/luminaries/w-edwards-deming.md +0 -158
  75. package/substrate/.claude/rules/accessor-library-discipline.md +0 -138
  76. package/substrate/.claude/rules/adr-discipline.md +0 -120
  77. package/substrate/.claude/rules/api-conventions.md +0 -125
  78. package/substrate/.claude/rules/artifact-ingestion.md +0 -179
  79. package/substrate/.claude/rules/assert-only-after-verify.md +0 -137
  80. package/substrate/.claude/rules/blocked-items.md +0 -146
  81. package/substrate/.claude/rules/bootstrap-pair-discipline.md +0 -141
  82. package/substrate/.claude/rules/branching.md +0 -28
  83. package/substrate/.claude/rules/cold-adopter-harness-discipline.md +0 -129
  84. package/substrate/.claude/rules/commit-conventions.md +0 -22
  85. package/substrate/.claude/rules/compounding-axis-fresh-analysis.md +0 -188
  86. package/substrate/.claude/rules/compounding-sequence-fresh-analysis.md +0 -188
  87. package/substrate/.claude/rules/context-engineering.md +0 -202
  88. package/substrate/.claude/rules/context-management.md +0 -85
  89. package/substrate/.claude/rules/defensive-bash.md +0 -68
  90. package/substrate/.claude/rules/deferred-actions.md +0 -233
  91. package/substrate/.claude/rules/destructive-operations.md +0 -69
  92. package/substrate/.claude/rules/diagnosis.md +0 -38
  93. package/substrate/.claude/rules/github-issue-flash-tweet.md +0 -156
  94. package/substrate/.claude/rules/guardrails.md +0 -73
  95. package/substrate/.claude/rules/hook-wire-on-author.md +0 -103
  96. package/substrate/.claude/rules/identifier-leak-prevention.md +0 -104
  97. package/substrate/.claude/rules/iteration-bet-brief-completeness.md +0 -54
  98. package/substrate/.claude/rules/lite-manifest-schema-change-discipline.md +0 -98
  99. package/substrate/.claude/rules/longrun-prep-plan-doc-compression.md +0 -89
  100. package/substrate/.claude/rules/loop-discipline.md +0 -81
  101. package/substrate/.claude/rules/manual-prod-approval.md +0 -100
  102. package/substrate/.claude/rules/marker-enrichment-discipline.md +0 -99
  103. package/substrate/.claude/rules/mobile-ephemeral-session.md +0 -109
  104. package/substrate/.claude/rules/new-dependency-check.md +0 -51
  105. package/substrate/.claude/rules/oo-ad-entry-point.md +0 -117
  106. package/substrate/.claude/rules/operator-facing-prose.md +0 -196
  107. package/substrate/.claude/rules/option-label-discipline.md +0 -108
  108. package/substrate/.claude/rules/pattern-annotation.md +0 -100
  109. package/substrate/.claude/rules/plain-english-discipline.md +0 -156
  110. package/substrate/.claude/rules/plan-enumeration-needs-value-props.md +0 -211
  111. package/substrate/.claude/rules/pr-body-shape.md +0 -317
  112. package/substrate/.claude/rules/pr-strategy.md +0 -167
  113. package/substrate/.claude/rules/pr-title-shape.md +0 -161
  114. package/substrate/.claude/rules/prototype-workflow.md +0 -65
  115. package/substrate/.claude/rules/reserved-skill-names.md +0 -123
  116. package/substrate/.claude/rules/schema-management.md +0 -49
  117. package/substrate/.claude/rules/sdlc-gates.md +0 -149
  118. package/substrate/.claude/rules/security.md +0 -37
  119. package/substrate/.claude/rules/session-artifacts.md +0 -236
  120. package/substrate/.claude/rules/skill-composition-declarations.md +0 -124
  121. package/substrate/.claude/rules/skill-description-clarity.md +0 -247
  122. package/substrate/.claude/rules/skill-procedure-step-list.md +0 -137
  123. package/substrate/.claude/rules/state-schema-validation.md +0 -162
  124. package/substrate/.claude/rules/stuck-signal-diagnostic.md +0 -140
  125. package/substrate/.claude/rules/substrate-config-schema.md +0 -98
  126. package/substrate/.claude/rules/test-list-discipline.md +0 -175
  127. package/substrate/.claude/rules/test-sufficiency.md +0 -210
  128. package/substrate/.claude/rules/testing-tier-config.md +0 -145
  129. package/substrate/.claude/rules/testing.md +0 -38
  130. package/substrate/.claude/rules/turn-estimate-grounding.md +0 -134
  131. package/substrate/.claude/rules/visual-hierarchy.md +0 -437
  132. package/substrate/.claude/rules/we-dont-break-adopters.md +0 -126
  133. package/substrate/.claude/rules/whereami-load-bearing.md +0 -202
  134. package/substrate/.claude/rules/writing-craft-discipline.md +0 -92
  135. package/substrate/.claude/rules/wu-sequencing-compounds.md +0 -145
  136. package/substrate/.claude/skills/build/SKILL.md +0 -640
  137. package/substrate/.claude/skills/chronicle/SKILL.md +0 -55
  138. package/substrate/.claude/skills/clean-artifacts/SKILL.md +0 -249
  139. package/substrate/.claude/skills/decompose/SKILL.md +0 -280
  140. package/substrate/.claude/skills/diagnose/SKILL.md +0 -297
  141. package/substrate/.claude/skills/feynman/SKILL.md +0 -90
  142. package/substrate/.claude/skills/howdoi/SKILL.md +0 -105
  143. package/substrate/.claude/skills/ia-model/SKILL.md +0 -108
  144. package/substrate/.claude/skills/interaction-design/SKILL.md +0 -112
  145. package/substrate/.claude/skills/interpret-input/SKILL.md +0 -180
  146. package/substrate/.claude/skills/journal/SKILL.md +0 -209
  147. package/substrate/.claude/skills/kiss/SKILL.md +0 -449
  148. package/substrate/.claude/skills/launch/SKILL.md +0 -915
  149. package/substrate/.claude/skills/lean-canvas/SKILL.md +0 -332
  150. package/substrate/.claude/skills/longrun/SKILL.md +0 -463
  151. package/substrate/.claude/skills/luminary/SKILL.md +0 -481
  152. package/substrate/.claude/skills/ogilvy-writing-audit/SKILL.md +0 -177
  153. package/substrate/.claude/skills/onboard-repo/SKILL.md +0 -1624
  154. package/substrate/.claude/skills/pattern-review/SKILL.md +0 -99
  155. package/substrate/.claude/skills/personas/SKILL.md +0 -207
  156. package/substrate/.claude/skills/promote/SKILL.md +0 -283
  157. package/substrate/.claude/skills/requirement/SKILL.md +0 -98
  158. package/substrate/.claude/skills/retro/SKILL.md +0 -117
  159. package/substrate/.claude/skills/riff/SKILL.md +0 -114
  160. package/substrate/.claude/skills/roadmap-reconcile/SKILL.md +0 -163
  161. package/substrate/.claude/skills/session-end/SKILL.md +0 -309
  162. package/substrate/.claude/skills/session-log/SKILL.md +0 -299
  163. package/substrate/.claude/skills/skills/SKILL.md +0 -228
  164. package/substrate/.claude/skills/spec/SKILL.md +0 -105
  165. package/substrate/.claude/skills/sprint/SKILL.md +0 -392
  166. package/substrate/.claude/skills/stage/SKILL.md +0 -384
  167. package/substrate/.claude/skills/state-a-problem/SKILL.md +0 -185
  168. package/substrate/.claude/skills/temperance/SKILL.md +0 -108
  169. package/substrate/.claude/skills/use-case/SKILL.md +0 -417
  170. package/substrate/.claude/skills/user-stories/SKILL.md +0 -268
  171. package/substrate/.claude/skills/value-prop/SKILL.md +0 -251
  172. package/substrate/.claude/skills/verify/SKILL.md +0 -160
  173. package/substrate/.claude/skills/visual-review/SKILL.md +0 -503
  174. package/substrate/.claude/skills/whats-the-plan/SKILL.md +0 -202
  175. package/substrate/.claude/skills/whereami/SKILL.md +0 -307
  176. package/substrate/AGENTS.md +0 -79
  177. package/substrate/CLAUDE-lite.md +0 -85
  178. package/substrate/CODE_OF_CONDUCT.md +0 -28
  179. package/substrate/CONTRIBUTING.md +0 -177
  180. package/substrate/README.md +0 -173
  181. package/substrate/SECURITY.md +0 -19
  182. package/substrate/architecture/decisions/ADR-029-release-pipeline.md +0 -79
  183. package/substrate/architecture/decisions/ADR-031-non-breaking-changes-adopter-discipline.md +0 -139
  184. package/substrate/architecture/decisions/ADR-032-adopter-sync-dispatcher-architecture.md +0 -192
  185. package/substrate/architecture/decisions/ADR-039-release-tagging-scheme.md +0 -145
  186. package/substrate/architecture/decisions/ADR-040-planning-skill-vocabulary-and-lite-profile.md +0 -155
  187. package/substrate/architecture/decisions/ADR-044-unified-skill-body-template.md +0 -162
  188. package/substrate/lib/clean-artifacts-sweep.sh +0 -112
  189. package/substrate/lib/code-comment-discipline.sh +0 -144
  190. package/substrate/lib/composer-preflight.sh +0 -459
  191. package/substrate/lib/hook-inject.sh +0 -255
  192. package/substrate/lib/luminary-pick.sh +0 -96
  193. package/substrate/lib/output-discipline.sh +0 -143
  194. package/substrate/lib/prose-scan-boundary.sh +0 -171
  195. package/substrate/lib/rewrite-check.sh +0 -214
  196. package/substrate/lib/state.sh +0 -1372
  197. package/substrate/lib/telemetry.sh +0 -205
  198. package/substrate/lib/tier-check.sh +0 -187
  199. package/substrate/lib/tier-dependency-audit.sh +0 -1088
  200. package/substrate/presence/install/bassclef-hook-connect.sh +0 -178
  201. package/substrate/presence/install/bassclef-sync.dispatcher.template.sh +0 -841
  202. package/substrate/presence/install/bassclef-sync.template.sh +0 -2076
  203. package/substrate/presence/install/schedule-auto-save.cron.sh +0 -88
  204. package/substrate/presence/install/schedule-auto-save.taskscheduler.md +0 -122
  205. package/substrate/scripts/aggregate-telemetry.sh +0 -217
  206. package/substrate/scripts/analyze-tier-dependencies.sh +0 -239
  207. package/substrate/scripts/generate-lite-manifest.sh +0 -505
  208. package/substrate/scripts/generate-tier-manifest.sh +0 -28
  209. package/substrate/scripts/intent-drift-check.sh +0 -456
  210. package/substrate/scripts/lite-manifest-drift-check.sh +0 -146
  211. package/substrate/scripts/render-lite-manifest-doc.sh +0 -150
  212. package/substrate/standards/adr-template.md +0 -86
  213. package/substrate/standards/api-conventions/nextjs.md +0 -84
  214. package/substrate/standards/artifact-composition.md +0 -209
  215. package/substrate/standards/bash-hook-safety.md +0 -246
  216. package/substrate/standards/bassclef-configs-schema.md +0 -232
  217. package/substrate/standards/bassclef-evolution.md +0 -143
  218. package/substrate/standards/bassclef-internal-jargon.md +0 -244
  219. package/substrate/standards/bassclef-managed-sentinel.md +0 -96
  220. package/substrate/standards/bassclef-source-config.md +0 -228
  221. package/substrate/standards/branch-stacking.md +0 -408
  222. package/substrate/standards/code-safety-principles.md +0 -176
  223. package/substrate/standards/composer-prerequisites.md +0 -155
  224. package/substrate/standards/deferred-actions-schema.md +0 -204
  225. package/substrate/standards/dependency-discipline/cargo.md +0 -39
  226. package/substrate/standards/dependency-discipline/gem.md +0 -43
  227. package/substrate/standards/dependency-discipline/go-mod.md +0 -41
  228. package/substrate/standards/dependency-discipline/npm.md +0 -42
  229. package/substrate/standards/dependency-discipline/pip.md +0 -42
  230. package/substrate/standards/deployment-topology/ec2-tailscale.md +0 -225
  231. package/substrate/standards/deployment-topology.md +0 -69
  232. package/substrate/standards/docs-sync-allowlist.md +0 -76
  233. package/substrate/standards/domain-and-dns.md +0 -145
  234. package/substrate/standards/frontend-stack.md +0 -67
  235. package/substrate/standards/frontmatter-schema.md +0 -154
  236. package/substrate/standards/graceful-exit.md +0 -227
  237. package/substrate/standards/hook-idempotency.md +0 -102
  238. package/substrate/standards/hook-injection-discipline.md +0 -202
  239. package/substrate/standards/hook-install-class.md +0 -215
  240. package/substrate/standards/input-handler-interface.md +0 -152
  241. package/substrate/standards/lite-manifest-schema-changes.md +0 -135
  242. package/substrate/standards/luminary-matching.md +0 -105
  243. package/substrate/standards/luminary-problem-patterns.md +0 -481
  244. package/substrate/standards/migration-discipline/active-record.md +0 -50
  245. package/substrate/standards/migration-discipline/alembic.md +0 -43
  246. package/substrate/standards/migration-discipline/gorm.md +0 -50
  247. package/substrate/standards/migration-discipline/prisma.md +0 -53
  248. package/substrate/standards/migration-discipline/sqlalchemy.md +0 -51
  249. package/substrate/standards/mobile-ephemeral-session.md +0 -167
  250. package/substrate/standards/model-routing-discipline.md +0 -160
  251. package/substrate/standards/ogilvy-writing-rules.md +0 -225
  252. package/substrate/standards/opener-discipline.md +0 -96
  253. package/substrate/standards/operator-facing-prose-discipline.md +0 -201
  254. package/substrate/standards/persona-schema.md +0 -229
  255. package/substrate/standards/pluggable-luminaries.md +0 -323
  256. package/substrate/standards/pr-body-discipline.md +0 -115
  257. package/substrate/standards/preview-state-schema.md +0 -189
  258. package/substrate/standards/project-directory-layout.md +0 -276
  259. package/substrate/standards/release-tagging.md +0 -137
  260. package/substrate/standards/reserved-skill-names.md +0 -120
  261. package/substrate/standards/scannable-multi-option-output.md +0 -261
  262. package/substrate/standards/sdlc-compliance.md +0 -286
  263. package/substrate/standards/sdlc-gates/typescript.md +0 -57
  264. package/substrate/standards/secrets-lifecycle.md +0 -210
  265. package/substrate/standards/security-scanner-adapter.md +0 -145
  266. package/substrate/standards/session-board.md +0 -256
  267. package/substrate/standards/skill-output-discipline.md +0 -90
  268. package/substrate/standards/state-spine-contract.md +0 -255
  269. package/substrate/standards/state-spine.md +0 -511
  270. package/substrate/standards/steering-hints/kiss-words.md +0 -11
  271. package/substrate/standards/substrate-config-schema.md +0 -267
  272. package/substrate/standards/tech-stack-config.md +0 -109
  273. package/substrate/standards/tier-dependency-analysis.md +0 -167
  274. package/substrate/standards/tier-runtime-deps/lite.md +0 -57
  275. package/substrate/standards/tier-tag-schema.md +0 -155
  276. package/substrate/standards/two-layer-config.md +0 -99
  277. package/substrate/standards/use-case-format.md +0 -292
  278. package/substrate/standards/user-story-invest.md +0 -268
  279. package/substrate/standards/velocity-and-appetite.md +0 -229
  280. package/substrate/standards/voice-input-pattern.md +0 -119
  281. package/substrate/standards/whereami-schema.md +0 -301
  282. package/substrate/standards/worktree-management.md +0 -211
  283. package/substrate/standards/writing-guide.md +0 -213
  284. package/substrate/templates/chronicle-template.md +0 -75
  285. package/substrate/templates/deferred-action-template.md +0 -45
  286. package/substrate/templates/memory-proposal-template.md +0 -77
  287. package/substrate/templates/persona-template.md +0 -200
  288. package/substrate/templates/pr-faq.md +0 -45
  289. package/substrate/templates/secret-rotation-template.md +0 -162
  290. package/substrate/templates/spec-template.md +0 -131
  291. package/substrate/templates/use-case-template.md +0 -194
  292. package/substrate/templates/user-story-template.md +0 -107
  293. package/substrate/templates/whereami-template.md +0 -101
@@ -1,634 +0,0 @@
1
- #!/bin/bash
2
- # tier: lite
3
- # Bassclef Substrate Sync — fires on SessionStart.
4
- # Operator-class hook: lives on bassclef-upstream operators' machines only.
5
- # Adopter consumers receive presence/install/bassclef-sync.template.sh instead
6
- # (sourced from canonical until the WU-0 absorb gap is closed).
7
- # Ensures bassclef standards are available regardless of device.
8
- #
9
- # 1. Clones/pulls bassclef repo
10
- # 2. Symlinks bassclef skills into project .claude/skills/ (auto-discovery)
11
- # 3. Installs general hooks + agents to ~/.claude/
12
- # 4. Writes ~/.claude/settings.json for user-level hook wiring (cloud)
13
- # 5. Sets env var for rules/CLAUDE.md inheritance
14
-
15
- # === Section 0a: SELF_MODE detection (#915) ===
16
- # Sister to Cure 1 in #901 (commit 4b6c258d) which added SELF_MODE
17
- # detection to the adopter template at presence/install/bassclef-sync.template.sh.
18
- # This is the operator-class SessionStart hook — it needs the same guard.
19
- #
20
- # Detection: git remote origin URL matches sunj-labs/(bassclef|bassclef-upstream)(\.git)?$
21
- # on both HTTPS and SSH URL shapes. When SELF_MODE=1, hook exits 0 early
22
- # to prevent the sync flow from re-symlinking tracked hooks in the
23
- # substrate source repo.
24
- #
25
- # Live proof of the class this cures: session 2026-07-26d WU-0 reverted 84
26
- # T + 1 M hooks caused by this SessionStart re-symlink in bassclef-upstream.
27
- #
28
- # Env override SKIP_SELF_MODE_DETECTION=1 forces SELF_MODE=0 regardless
29
- # of remote — for adopter forks of bassclef-upstream that legitimately
30
- # want the sync flow.
31
- #
32
- # Function is defined ABOVE the main-body INPUT read so tests can source
33
- # the hook with BASSCLEF_SYNC_TEST_MODE=1 and access the function without
34
- # triggering the sync flow.
35
- bassclef_detect_self_mode() {
36
- local cwd="${1:-.}"
37
-
38
- # Env override wins
39
- if [ "${SKIP_SELF_MODE_DETECTION:-0}" = "1" ]; then
40
- echo "0"
41
- return 0
42
- fi
43
-
44
- # No git → not substrate source
45
- command -v git >/dev/null 2>&1 || { echo "0"; return 0; }
46
-
47
- # Get remote origin URL
48
- local remote_url
49
- remote_url=$(git -C "$cwd" config --get remote.origin.url 2>/dev/null)
50
- if [ -z "$remote_url" ]; then
51
- echo "0"
52
- return 0
53
- fi
54
-
55
- # Match sunj-labs/(bassclef|bassclef-upstream) with optional .git suffix
56
- # HTTPS: https://github.com/sunj-labs/bassclef.git
57
- # SSH: git@github.com:sunj-labs/bassclef-upstream.git
58
- if echo "$remote_url" | grep -qE 'sunj-labs/(bassclef|bassclef-upstream)(\.git)?$'; then
59
- echo "1"
60
- return 0
61
- fi
62
-
63
- echo "0"
64
- return 0
65
- }
66
-
67
- # === Test-mode guard (#915) ===
68
- # Tests source this hook to access helpers without triggering main sync.
69
- # Early return under BASSCLEF_SYNC_TEST_MODE=1. Helpers defined ABOVE.
70
- if [ "${BASSCLEF_SYNC_TEST_MODE:-0}" = "1" ]; then
71
- return 0 2>/dev/null || exit 0
72
- fi
73
-
74
- # === Hook liveness heartbeat (WU-3 of bet 2026-07-31d; closes #1002) ===
75
- # Silent-fail — a missing lib never crashes the hook. Discipline: ADR-048 +
76
- # standards/hook-cadence.json. Session-start reflection module (WU-4.5) checks
77
- # marker mtime against expected cadence.
78
- {
79
- _hb_sd="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
80
- for _hb_c in "${_hb_sd}/../../lib/hook-heartbeat.sh" "${HOME:-/}/lib/hook-heartbeat.sh"; do
81
- [ -f "$_hb_c" ] && source "$_hb_c" && heartbeat_mark "bassclef-sync" && break
82
- done
83
- unset _hb_sd _hb_c
84
- } 2>/dev/null || true
85
-
86
- INPUT=$(cat)
87
- CWD=$(echo "$INPUT" | jq -r '.cwd // "."')
88
- cd "$CWD"
89
-
90
- # === Section 0a fires: exit early if this repo is substrate source ===
91
- SELF_MODE=$(bassclef_detect_self_mode "$CWD")
92
- if [ "$SELF_MODE" = "1" ]; then
93
- echo "SELF_MODE detected — skipping sync in substrate source repo." >&2
94
- echo " (Override with SKIP_SELF_MODE_DETECTION=1 for adopter forks.)" >&2
95
- exit 0
96
- fi
97
-
98
- # Bassclef substrate location — peer clone at ../bassclef (post-rename).
99
- # Pre-rename ../canonical fallback removed 2026-06-24 per bassclef-upstream#317
100
- # Phase 0: zero adopters carry the canonical/ path; operator's local
101
- # ~/src/sunj-labs/canonical was removed before this cleanup.
102
- BASSCLEF_DIR="$CWD/../bassclef"
103
- BASSCLEF_REPO="https://github.com/sunj-labs/bassclef.git"
104
- SYNC_STATUS="up-to-date"
105
- SYNC_NEW=""
106
-
107
- # === 1. Clone or pull bassclef ===
108
- if [ ! -d "$BASSCLEF_DIR/.claude" ]; then
109
- if git clone "$BASSCLEF_REPO" "$BASSCLEF_DIR" 2>/dev/null; then
110
- SYNC_STATUS="freshly cloned"
111
- else
112
- echo "### BASSCLEF SYNC FAILED"
113
- echo ""
114
- echo "Could not clone bassclef. Skills, rules, and agents unavailable."
115
- echo "Check GitHub auth: is your account connected at claude.ai?"
116
- echo ""
117
- exit 0
118
- fi
119
- else
120
- BEFORE=$(git -C "$BASSCLEF_DIR" rev-parse HEAD 2>/dev/null)
121
- git -C "$BASSCLEF_DIR" pull --quiet 2>/dev/null || true
122
- AFTER=$(git -C "$BASSCLEF_DIR" rev-parse HEAD 2>/dev/null)
123
-
124
- if [ "$BEFORE" != "$AFTER" ]; then
125
- SYNC_STATUS="updated"
126
- SYNC_NEW=$(git -C "$BASSCLEF_DIR" log --oneline "$BEFORE".."$AFTER" 2>/dev/null)
127
- fi
128
- fi
129
-
130
- # === 2. Symlink bassclef skills into project for auto-discovery ===
131
- mkdir -p "$CWD/.claude/skills" 2>/dev/null || true
132
- for SKILL_DIR in "$BASSCLEF_DIR/.claude/skills/"*/; do
133
- SKILL_NAME=$(basename "$SKILL_DIR")
134
- TARGET="$CWD/.claude/skills/$SKILL_NAME"
135
- # Only symlink if not already an app-specific skill (real directory, not symlink)
136
- if [ -L "$TARGET" ]; then
137
- # Existing symlink — update it
138
- rm "$TARGET"
139
- ln -s "$SKILL_DIR" "$TARGET"
140
- elif [ ! -d "$TARGET" ]; then
141
- # Doesn't exist — create symlink
142
- ln -s "$SKILL_DIR" "$TARGET"
143
- fi
144
- # If it's a real directory (app-specific), leave it alone
145
- done
146
-
147
- # === 2b. Park orphan ~/.claude/skills + agents + hooks symlinks (widened per ADR-033 + bassclef#278) ===
148
- # Uses the shared orphan-parking helper. Closes the skill / agent / hook
149
- # duplication-in-available-skills bug. The helper parks user-level
150
- # symlinks AND cp'd files whose basename appears in project-level —
151
- # preserves real directories untouched + EXCLUDES hooks wired in
152
- # settings.json at $HOME paths (per #294); backs up moved entries to
153
- # dated dirs that survive at least 30 days per Hyrum + Linus discipline.
154
- PARKING_HELPER="$BASSCLEF_DIR/scripts/bassclef-orphan-parking.sh"
155
- USER_SETTINGS="$HOME/.claude/settings.json"
156
- ORPHAN_COUNT=0
157
- if [ -f "$PARKING_HELPER" ]; then
158
- for surface in skills agents hooks; do
159
- USER_SURFACE="$HOME/.claude/$surface"
160
- PROJECT_SURFACE="$CWD/.claude/$surface"
161
- if [ -d "$USER_SURFACE" ] && [ -d "$PROJECT_SURFACE" ]; then
162
- mkdir -p "$HOME/.claude" 2>/dev/null
163
- # Pass user settings.json as 5th arg so wired hooks are excluded
164
- # from parking. Per #294 — broke the Stop hook on this machine when
165
- # parking removed session-end.sh that settings.json wires.
166
- PARKED_LINE=$(bash "$PARKING_HELPER" "$USER_SURFACE" "$PROJECT_SURFACE" "$HOME/.claude" "$surface" "$USER_SETTINGS" 2>/dev/null || echo "")
167
- if [ -n "$PARKED_LINE" ]; then
168
- # Extract the count from "parked N <surface> orphans → <dir>"
169
- COUNT_N=$(echo "$PARKED_LINE" | grep -oE 'parked [0-9]+' | grep -oE '[0-9]+' | head -1)
170
- [ -n "$COUNT_N" ] && ORPHAN_COUNT=$((ORPHAN_COUNT + COUNT_N))
171
- fi
172
- fi
173
- done
174
- fi
175
-
176
- # === 2c. Adopter self-heal — auto-migrate stale canonical references ===
177
- # Per ADR-031 we-dont-break-adopters + Nygard's Steady State pattern.
178
- # When this hook runs in an adopter repo (CWD is NOT bassclef-upstream and
179
- # does NOT have architecture/dual-repo-flow.md), invoke the migration script
180
- # to repair any stale ../canonical/ references in symlinks + settings.json
181
- # + dispatcher + statusline. Idempotent — no-op on already-migrated repos.
182
- #
183
- # Banner surfaces per-surface info (not just count) so adopters who
184
- # customized any of the migrated surfaces see exactly what changed.
185
- # Closes Yellow 2 of the 2026-06-22 release-readiness review.
186
- MIGRATE_SCRIPT="$BASSCLEF_DIR/scripts/migrate-adopter-references.sh"
187
- SUMMARY_HELPER="$BASSCLEF_DIR/scripts/bassclef-migrate-summary.sh"
188
- if [ -f "$MIGRATE_SCRIPT" ] && [ ! -f "$CWD/architecture/dual-repo-flow.md" ]; then
189
- MIGRATE_OUT=$(bash "$MIGRATE_SCRIPT" --apply "$CWD" 2>&1)
190
- MIGRATE_CHANGES=$(echo "$MIGRATE_OUT" | awk -F: '/^changes:/ {print $2}' | tr -d ' ')
191
- if [ -n "$MIGRATE_CHANGES" ] && [ "$MIGRATE_CHANGES" -gt 0 ]; then
192
- PER_SURFACE=""
193
- # Check -f (file exists), not -x (executable). We invoke via `bash $HELPER`
194
- # so the executable bit is irrelevant; the bit may not survive tarball
195
- # fetches across adopter clones (per reviewer note on PR #291).
196
- if [ -f "$SUMMARY_HELPER" ]; then
197
- PER_SURFACE=$(echo "$MIGRATE_OUT" | bash "$SUMMARY_HELPER" 2>/dev/null)
198
- fi
199
- SYNC_NEW="${SYNC_NEW}
200
- Adopter self-heal: $MIGRATE_CHANGES surface(s) migrated. Old setup keeps working; new setup matches current bassclef substrate. Per ADR-031."
201
- if [ -n "$PER_SURFACE" ]; then
202
- SYNC_NEW="${SYNC_NEW}
203
- ${PER_SURFACE}"
204
- fi
205
- fi
206
- fi
207
-
208
- # === 3. Install general hooks to ~/.claude/ ===
209
- # This list MUST be in lock-step with §4's settings.json template +
210
- # any older settings.json that may still wire $HOME paths (per #294).
211
- # Adding session-end.sh because older bassclef versions wired it in
212
- # settings.json; current parking widen would otherwise leave the wiring
213
- # broken on operator machines whose settings.json predates #294.
214
- mkdir -p ~/.claude/hooks 2>/dev/null || true
215
- for HOOK in bug-diagnosis.sh tool-failure-diagnosis.sh trace-helper.sh deploy-guard.sh memory-write-audit.sh turn-prose-kiss-check.sh session-end.sh bet-doc-gate.sh substrate-clarity-gate.sh; do
216
- if [ -f "$BASSCLEF_DIR/.claude/hooks/$HOOK" ]; then
217
- cp "$BASSCLEF_DIR/.claude/hooks/$HOOK" ~/.claude/hooks/ 2>/dev/null || true
218
- chmod +x ~/.claude/hooks/"$HOOK" 2>/dev/null || true
219
- fi
220
- done
221
-
222
- # === Install agents to ~/.claude/ ===
223
- mkdir -p ~/.claude/agents 2>/dev/null || true
224
- cp "$BASSCLEF_DIR/.claude/agents/"*.md ~/.claude/agents/ 2>/dev/null || true
225
-
226
- # === 4. Versioned self-heal of ~/.claude/settings.json ===
227
- # WU-3 of bet 2026-06-24a-settings-hardening (#313). Replaces the
228
- # brittle multi-grep + destructive heredoc rewrite with:
229
- # 1. Version-field comparison (read_settings_version).
230
- # 2. Additive merge that preserves operator's top-level keys (theme,
231
- # statusLine, permissions, alwaysThinkingEnabled, etc.) and
232
- # operator-only event types — bassclef wins per-event for events
233
- # it ships.
234
- # 3. Hoare postcondition: after self-heal, drift detector MUST
235
- # return clean (compare_wirings .ok == true). Else exit 1 with
236
- # structured stderr — failure compounds across every adopter,
237
- # so failing loud beats failing silent.
238
- # Closes the bug class diagnosed 2026-06-24 (operator's settings.json
239
- # never picked up substrate's new hook wirings).
240
- WIRINGS_LIB="$BASSCLEF_DIR/.claude/hooks/_lib/wirings.sh"
241
- PROJECT_SETTINGS="$BASSCLEF_DIR/.claude/settings.json"
242
- USER_SETTINGS="$HOME/.claude/settings.json"
243
-
244
- sync_self_heal() {
245
- if [ ! -f "$WIRINGS_LIB" ] || [ ! -f "$PROJECT_SETTINGS" ]; then
246
- # Substrate not fully synced yet OR project settings.json not
247
- # checked out on this branch. Fall back silently — drift detector
248
- # at next session-start will surface the gap.
249
- return 0
250
- fi
251
- # shellcheck source=/dev/null
252
- source "$WIRINGS_LIB"
253
-
254
- local required_version user_version
255
- required_version=$(read_settings_version "$PROJECT_SETTINGS")
256
- user_version=$(read_settings_version "$USER_SETTINGS")
257
-
258
- if [ ! -f "$USER_SETTINGS" ] || [ "$user_version" -lt "$required_version" ]; then
259
- additive_merge_settings "$USER_SETTINGS" "$PROJECT_SETTINGS"
260
- fi
261
-
262
- # Hoare postcondition: required ⊆ loaded after self-heal.
263
- local required loaded diff ok missing
264
- required=$(read_required_wirings "$PROJECT_SETTINGS")
265
- loaded=$(read_loaded_wirings)
266
- diff=$(compare_wirings "$required" "$loaded")
267
- ok=$(echo "$diff" | jq -r '.ok')
268
- if [ "$ok" != "true" ]; then
269
- missing=$(echo "$diff" | jq -c '.missing')
270
- echo "🛑 bassclef-sync postcondition FAILED — required wirings missing after self-heal:" >&2
271
- echo "$missing" | jq -r '.[] | " - " + .event + " → " + .command' >&2
272
- echo "" >&2
273
- echo "Resolve: edit ~/.claude/settings.json to include the missing wirings, then re-run bassclef-sync." >&2
274
- if command -v trace_log >/dev/null 2>&1; then
275
- trace_log "fail" "bassclef-sync-postcondition" "$missing"
276
- fi
277
- return 1
278
- fi
279
- if command -v trace_log >/dev/null 2>&1; then
280
- trace_log "ok" "bassclef-sync-postcondition" "version=$required_version"
281
- fi
282
- return 0
283
- }
284
-
285
- sync_self_heal || exit 1
286
-
287
- # === 4b. PreToolUse template embedding — operator settings.json self-heal ===
288
- # Per bassclef-upstream#336 — ensure operator's ~/.claude/settings.json wires
289
- # the bassclef-managed PreToolUse hooks (substrate-clarity-gate + bet-doc-gate).
290
- # Mirrors §3c-hooks in presence/install/bassclef-sync.template.sh (consumer-side)
291
- # but targets ~/.claude/settings.json with $HOME-prefixed commands.
292
- #
293
- # Why this lives here even though §4 sync_self_heal runs additive-merge:
294
- # wirings.sh merges bassclef's project settings.json into operator's user
295
- # settings.json — but during a sync where wirings.sh itself is being upgraded,
296
- # OR when the operator's settings.json predates the wirings library entirely,
297
- # the merge may not fire. This §4b is the literal-text fallback: greppable
298
- # guards re-emit the PreToolUse template when entries are missing, regardless
299
- # of wirings.sh state. Bootstrap-pair discipline (per
300
- # .claude/rules/bootstrap-pair-discipline.md) — wiring ships in the same place
301
- # as the hook reference.
302
- #
303
- # Template (operator settings.json fragment, "PreToolUse": event):
304
- # {
305
- # "hooks": {
306
- # "PreToolUse": [
307
- # {
308
- # "matcher": "Edit|Write|MultiEdit",
309
- # "hooks": [
310
- # {"type": "command", "command": "$HOME/.claude/hooks/substrate-clarity-gate.sh"},
311
- # {"type": "command", "command": "$HOME/.claude/hooks/bet-doc-gate.sh"}
312
- # ]
313
- # }
314
- # ]
315
- # }
316
- # }
317
- #
318
- # Idempotent via jq additive merge — re-runs detect existing entries and skip.
319
- # Skip paths:
320
- # - SKIP_PRETOOLUSE_EMBED=1 — operator override (logged)
321
- # - jq missing — graceful skip with stderr notice
322
- # - ~/.claude/settings.json missing — skip (sync_self_heal handles creation)
323
- if [ "${SKIP_PRETOOLUSE_EMBED:-0}" != "1" ] && \
324
- command -v jq >/dev/null 2>&1 && \
325
- [ -f "$USER_SETTINGS" ]; then
326
-
327
- # Guard re-emit when bet-doc-gate missing (existing-adopter self-heal)
328
- if ! grep -q 'bet-doc-gate' ~/.claude/settings.json 2>/dev/null; then
329
- BET_DOC_GATE_MISSING=1
330
- else
331
- BET_DOC_GATE_MISSING=0
332
- fi
333
- # Guard re-emit when substrate-clarity-gate missing
334
- if ! grep -q 'substrate-clarity-gate' ~/.claude/settings.json 2>/dev/null; then
335
- SUBSTRATE_CLARITY_GATE_MISSING=1
336
- else
337
- SUBSTRATE_CLARITY_GATE_MISSING=0
338
- fi
339
-
340
- if [ "$BET_DOC_GATE_MISSING" = "1" ] || [ "$SUBSTRATE_CLARITY_GATE_MISSING" = "1" ]; then
341
- # Operator-class PreToolUse template — note the $HOME prefix (left literal
342
- # in JSON; Claude Code expands at hook-fire time per presence/install
343
- # consumer-side §4 line 820 precedent).
344
- OPERATOR_PRETOOLUSE_JSON='[
345
- {"matcher": "Edit|Write|MultiEdit", "command": "$HOME/.claude/hooks/substrate-clarity-gate.sh"},
346
- {"matcher": "Edit|Write|MultiEdit", "command": "$HOME/.claude/hooks/bet-doc-gate.sh"}
347
- ]'
348
-
349
- # Additive jq merge — mirrors §3c-hooks logic but writes to USER_SETTINGS:
350
- # 1. Ensure .hooks.PreToolUse array exists
351
- # 2. For each bassclef hook:
352
- # - If matcher exists, ensure command is in the matcher's hooks array
353
- # - If matcher missing, create new matcher entry with the command
354
- # Operator-managed entries (other matchers, other commands) stay untouched.
355
- NEW_OPERATOR_SETTINGS=$(jq --argjson bassclef "$OPERATOR_PRETOOLUSE_JSON" '
356
- .hooks //= {} |
357
- .hooks.PreToolUse //= [] |
358
- reduce $bassclef[] as $hook (
359
- .;
360
- if (.hooks.PreToolUse | map(.matcher) | index($hook.matcher)) != null then
361
- .hooks.PreToolUse |= map(
362
- if .matcher == $hook.matcher then
363
- if (.hooks | map(.command) | index($hook.command)) == null then
364
- .hooks += [{"type": "command", "command": $hook.command}]
365
- else . end
366
- else . end
367
- )
368
- else
369
- .hooks.PreToolUse += [{
370
- "matcher": $hook.matcher,
371
- "hooks": [{"type": "command", "command": $hook.command}]
372
- }]
373
- end
374
- )
375
- ' "$USER_SETTINGS" 2>/dev/null)
376
-
377
- if [ -n "$NEW_OPERATOR_SETTINGS" ]; then
378
- echo "$NEW_OPERATOR_SETTINGS" > "$USER_SETTINGS.tmp" && \
379
- mv "$USER_SETTINGS.tmp" "$USER_SETTINGS"
380
- if command -v trace_log >/dev/null 2>&1; then
381
- trace_log "ok" "bassclef-sync-pretooluse-embed" \
382
- "added_bet_doc=$BET_DOC_GATE_MISSING added_substrate_clarity=$SUBSTRATE_CLARITY_GATE_MISSING"
383
- fi
384
- fi
385
- fi
386
- fi
387
-
388
- # === 4c. Stop template embedding — operator settings.json self-heal ===
389
- # Same pattern as §4b but for the "Stop": event — wires
390
- # $HOME/.claude/hooks/turn-prose-kiss-check.sh so the per-turn /kiss scan
391
- # fires at session-stop boundaries. Per bassclef-upstream#336 sister gap
392
- # (Stop template embedding missing alongside PreToolUse).
393
- #
394
- # Template (operator settings.json fragment, "Stop": event):
395
- # {
396
- # "hooks": {
397
- # "Stop": [
398
- # {
399
- # "matcher": "",
400
- # "hooks": [
401
- # {"type": "command", "command": "$HOME/.claude/hooks/turn-prose-kiss-check.sh", "timeout": 30}
402
- # ]
403
- # }
404
- # ]
405
- # }
406
- # }
407
- #
408
- # Timeout 30s: turn-prose-kiss-check scans the most-recent assistant message
409
- # against the BLOCK wordlist; finishes well under 30s on any realistic
410
- # transcript. ≥5s minimum per session-artifacts rule (Stop hooks need
411
- # adequate timeout or they get killed mid-write).
412
- if [ "${SKIP_STOP_EMBED:-0}" != "1" ] && \
413
- command -v jq >/dev/null 2>&1 && \
414
- [ -f "$USER_SETTINGS" ]; then
415
-
416
- # Guard re-emit when turn-prose entry missing
417
- if ! grep -q 'turn-prose' ~/.claude/settings.json 2>/dev/null; then
418
- TURN_PROSE_MISSING=1
419
- else
420
- TURN_PROSE_MISSING=0
421
- fi
422
-
423
- if [ "$TURN_PROSE_MISSING" = "1" ]; then
424
- # Stop-event entry — empty matcher (Stop fires once per session-end;
425
- # no per-tool matcher applies). Command uses $HOME-prefixed path
426
- # (Claude Code expands at hook-fire time). Timeout 30 per above.
427
- OPERATOR_STOP_JSON='[
428
- {"matcher": "", "command": "$HOME/.claude/hooks/turn-prose-kiss-check.sh", "timeout": 30}
429
- ]'
430
-
431
- NEW_STOP_SETTINGS=$(jq --argjson bassclef "$OPERATOR_STOP_JSON" '
432
- .hooks //= {} |
433
- .hooks.Stop //= [] |
434
- reduce $bassclef[] as $hook (
435
- .;
436
- if (.hooks.Stop | map(.matcher) | index($hook.matcher)) != null then
437
- .hooks.Stop |= map(
438
- if .matcher == $hook.matcher then
439
- if (.hooks | map(.command) | index($hook.command)) == null then
440
- .hooks += [{"type": "command", "command": $hook.command, "timeout": $hook.timeout}]
441
- else . end
442
- else . end
443
- )
444
- else
445
- .hooks.Stop += [{
446
- "matcher": $hook.matcher,
447
- "hooks": [{"type": "command", "command": $hook.command, "timeout": $hook.timeout}]
448
- }]
449
- end
450
- )
451
- ' "$USER_SETTINGS" 2>/dev/null)
452
-
453
- if [ -n "$NEW_STOP_SETTINGS" ]; then
454
- echo "$NEW_STOP_SETTINGS" > "$USER_SETTINGS.tmp" && \
455
- mv "$USER_SETTINGS.tmp" "$USER_SETTINGS"
456
- if command -v trace_log >/dev/null 2>&1; then
457
- trace_log "ok" "bassclef-sync-stop-embed" \
458
- "added_turn_prose=$TURN_PROSE_MISSING"
459
- fi
460
- fi
461
- fi
462
- fi
463
-
464
- # === 5. Set env var for rules/CLAUDE.md inheritance ===
465
- if [ -n "$CLAUDE_ENV_FILE" ]; then
466
- echo "CLAUDE_CODE_ADDITIONAL_DIRECTORIES_CLAUDE_MD=1" >> "$CLAUDE_ENV_FILE"
467
- fi
468
-
469
- # === Summary ===
470
- SKILL_COUNT=$(ls "$BASSCLEF_DIR/.claude/skills/" 2>/dev/null | wc -l | tr -d ' ')
471
- RULE_COUNT=$(ls "$BASSCLEF_DIR/.claude/rules/" 2>/dev/null | wc -l | tr -d ' ')
472
- AGENT_COUNT=$(ls ~/.claude/agents/ 2>/dev/null | wc -l | tr -d ' ')
473
- HOOK_COUNT=$(ls ~/.claude/hooks/*.sh 2>/dev/null | wc -l | tr -d ' ')
474
-
475
- echo ""
476
- echo "### BASSCLEF SUBSTRATE — SYNCED"
477
- echo ""
478
- echo "Status: $SYNC_STATUS"
479
- echo "Skills: ${SKILL_COUNT} (symlinked to .claude/skills/ for auto-discovery)"
480
- echo "Rules: ${RULE_COUNT} (loaded via additionalDirectories + env var)"
481
- echo "Agents: ${AGENT_COUNT} (installed to ~/.claude/agents/)"
482
- echo "Hooks: ${HOOK_COUNT} user-level (bug-diagnosis, tool-failure, trace-helper)"
483
- echo ""
484
-
485
- if [ -n "$SYNC_NEW" ]; then
486
- echo "### NEW SINCE LAST SYNC — REVIEW BEFORE PROCEEDING"
487
- echo ""
488
- echo "$SYNC_NEW"
489
- echo ""
490
- echo "→ New bassclef standards detected. Ask the user to confirm"
491
- echo " before proceeding. These may change how this session operates."
492
- echo ""
493
- fi
494
-
495
- if [ "$ORPHAN_COUNT" -gt 0 ]; then
496
- echo "### USER-LEVEL SUBSTRATE CLEANUP (per ADR-033 + bassclef#278)"
497
- echo ""
498
- echo "Parked $ORPHAN_COUNT user-level entries (skills + agents + hooks; symlinks AND cp'd files)"
499
- echo "whose basenames duplicated project-level entries. Backup dirs:"
500
- echo " ~/.claude/skills.orphans.$(date +%Y%m%d)/"
501
- echo " ~/.claude/agents.orphans.$(date +%Y%m%d)/"
502
- echo " ~/.claude/hooks.orphans.$(date +%Y%m%d)/"
503
- echo ""
504
- echo "Project-level entries now load without dedupe conflict."
505
- echo "Backups survive 30 days minimum; restore if a script you wrote"
506
- echo "depends on the user-level location."
507
- echo ""
508
- fi
509
-
510
- echo "YOU MUST confirm to the user:"
511
- echo " 'Bassclef substrate synced: ${SKILL_COUNT} skills, ${RULE_COUNT} rules,"
512
- echo " ${AGENT_COUNT} agents, ${HOOK_COUNT} hooks. Status: ${SYNC_STATUS}.'"
513
- echo ""
514
-
515
- # === 6. Worktree cleanup — prune stale worktrees from crashed parallel sessions ===
516
- STALE_WORKTREES=$(git -C "$CWD" worktree list --porcelain 2>/dev/null | grep "^worktree " | grep -v "$CWD$" | wc -l | tr -d ' ')
517
- if [ "$STALE_WORKTREES" -gt 0 ]; then
518
- # Prune worktrees whose directories no longer exist
519
- git -C "$CWD" worktree prune 2>/dev/null || true
520
-
521
- # Clean up .claude/worktrees/ directory if it exists
522
- if [ -d "$CWD/.claude/worktrees" ]; then
523
- rm -rf "$CWD/.claude/worktrees" 2>/dev/null || true
524
- fi
525
-
526
- REMAINING=$(git -C "$CWD" worktree list --porcelain 2>/dev/null | grep "^worktree " | grep -v "$CWD$" | wc -l | tr -d ' ')
527
- if [ "$REMAINING" -gt 0 ]; then
528
- echo "### STALE WORKTREES DETECTED"
529
- echo ""
530
- echo "$REMAINING worktree(s) from a previous session still exist."
531
- echo "These may hold branch locks. Review and remove:"
532
- echo ""
533
- git -C "$CWD" worktree list 2>/dev/null | grep -v "$CWD "
534
- echo ""
535
- echo "To remove: git worktree remove <path>"
536
- echo ""
537
- fi
538
- fi
539
-
540
- # === 7. Boot check — only report what's missing ===
541
- MISSING=""
542
-
543
- # Google service account (needed for journal → Google Docs)
544
- SA_KEY="$HOME/.config/gcloud/sunjay-google-ops.json"
545
- if [ ! -f "$SA_KEY" ]; then
546
- MISSING="${MISSING}\n- Google Docs service account key missing at $SA_KEY (needed for /journal → Google Doc push)"
547
- fi
548
-
549
- # gh CLI auth (needed for /promote, issue creation)
550
- if ! command -v gh &>/dev/null; then
551
- MISSING="${MISSING}\n- gh CLI not installed (needed for /promote, issue creation)"
552
- elif ! gh auth status &>/dev/null 2>&1; then
553
- MISSING="${MISSING}\n- gh CLI not authenticated (run: gh auth login)"
554
- fi
555
-
556
- if [ -n "$MISSING" ]; then
557
- echo "### SUBSTRATE DEPENDENCIES — OPTIONAL SETUP NEEDED"
558
- echo ""
559
- echo "The following are not blocking but limit some skills:"
560
- echo -e "$MISSING"
561
- echo ""
562
- echo "Run: bassclef/scripts/boot-bassclef.sh for full setup guide."
563
- echo "These are informational — proceed with your work."
564
- echo ""
565
- fi
566
-
567
- # === 8. journal draft staleness check ===
568
- # Check both bassclef and the current repo for stale drafts.
569
- #
570
- # Fetch origin first (per bassclef-upstream#403): the staleness check
571
- # below reads local filesystem state + local git log, which diverges
572
- # from origin when another session has pushed since the last pull
573
- # (e.g., a prior session-end's commit). Without the fetch, the banner
574
- # shows wrong-now data (observed 2026-06-26c — local saw 2026-06-19
575
- # while origin had 2026-06-26.md from #401).
576
- #
577
- # Best-effort: || true keeps the check working when offline / no remote.
578
- CURRENT_BRANCH_FOR_FETCH=$(git -C "$CWD" symbolic-ref --short HEAD 2>/dev/null)
579
- if [ -n "$CURRENT_BRANCH_FOR_FETCH" ]; then
580
- git -C "$CWD" fetch origin "$CURRENT_BRANCH_FOR_FETCH" --quiet 2>/dev/null || true
581
- fi
582
-
583
- DRAFT_DIRS=""
584
- if [ -d "$CWD/docs/operator-private/journals" ]; then
585
- DRAFT_DIRS="$CWD/docs/operator-private/journals"
586
- elif [ -d "$CWD/docs/journals" ]; then
587
- # Pre-2026-06-27 path — migrated to operator-private per bassclef-upstream#405
588
- DRAFT_DIRS="$CWD/docs/journals"
589
- elif [ -d "$CWD/docs/linkedin-drafts" ]; then
590
- # Legacy path — pre-/linkedin-→-/journal rename
591
- DRAFT_DIRS="$CWD/docs/linkedin-drafts"
592
- fi
593
- if [ -d "$BASSCLEF_DIR/docs/operator-private/journals" ] && [ "$BASSCLEF_DIR" != "$CWD" ]; then
594
- DRAFT_DIRS="$DRAFT_DIRS $BASSCLEF_DIR/docs/operator-private/journals"
595
- elif [ -d "$BASSCLEF_DIR/docs/journals" ] && [ "$BASSCLEF_DIR" != "$CWD" ]; then
596
- DRAFT_DIRS="$DRAFT_DIRS $BASSCLEF_DIR/docs/journals"
597
- fi
598
-
599
- if [ -n "$DRAFT_DIRS" ]; then
600
- LATEST_DRAFT=""
601
- for DIR in $DRAFT_DIRS; do
602
- LAST=$(ls -1 "$DIR"/*.md 2>/dev/null | sort | tail -1)
603
- if [ -n "$LAST" ]; then
604
- DRAFT_DATE=$(basename "$LAST" .md | head -c 10)
605
- if [ -z "$LATEST_DRAFT" ] || [ "$DRAFT_DATE" \> "$LATEST_DRAFT" ]; then
606
- LATEST_DRAFT="$DRAFT_DATE"
607
- fi
608
- fi
609
- done
610
-
611
- if [ -n "$LATEST_DRAFT" ]; then
612
- TODAY=$(date +%Y-%m-%d)
613
- # Count commits since last draft
614
- COMMITS_SINCE=$(git -C "$CWD" log --oneline --since="$LATEST_DRAFT" 2>/dev/null | wc -l | tr -d ' ')
615
-
616
- if [ "$LATEST_DRAFT" != "$TODAY" ] && [ "$COMMITS_SINCE" -gt 3 ]; then
617
- DAYS_AGO=$(( ( $(date +%s) - $(date -j -f "%Y-%m-%d" "$LATEST_DRAFT" +%s 2>/dev/null || echo 0) ) / 86400 ))
618
- echo "### JOURNAL DRAFTS OVERDUE (SHOULD — backfill before other work)"
619
- echo ""
620
- echo "Last draft: $LATEST_DRAFT ($DAYS_AGO days ago, $COMMITS_SINCE commits since)"
621
- echo ""
622
- echo "→ BACKFILL NOW — before starting new work."
623
- echo " 1. Read chronicles since $LATEST_DRAFT"
624
- echo " 2. Write drafts for each session with a notable decision or insight"
625
- echo " 3. Push to Google Doc (oldest first)"
626
- echo " 4. Then proceed with session work"
627
- echo ""
628
- echo "This is a SHOULD gate. Do not skip without documented rationale."
629
- echo ""
630
- fi
631
- fi
632
- fi
633
-
634
- exit 0