@thebassclef/lite 0.1.3 → 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.cjs +431 -135
- package/dist/cli.js +433 -137
- package/dist/index.cjs +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/lite/.bassclef-source.json +10 -0
- package/{substrate → dist/lite}/.claude/hooks/artifact-ingestion-gate.sh +0 -0
- package/{substrate → dist/lite}/.claude/hooks/assert-verify-steering.sh +0 -0
- package/{substrate → dist/lite}/.claude/hooks/bassclef-source-config-validate.sh +0 -0
- package/{substrate → dist/lite}/.claude/hooks/bassclef-sync.sh +0 -0
- package/{substrate → dist/lite}/.claude/hooks/compound-noun-scrub.sh +0 -0
- package/{substrate → dist/lite}/.claude/hooks/kiss-expansion-inject.sh +0 -0
- package/{substrate → dist/lite}/.claude/hooks/longrun-prep-compounding-sequence-check.sh +0 -0
- package/{substrate → dist/lite}/.claude/hooks/plain-english-steering.sh +0 -0
- package/{substrate → dist/lite}/.claude/hooks/post-skill-friction-check.sh +0 -0
- package/{substrate → dist/lite}/.claude/hooks/post-skill-telemetry.sh +0 -0
- package/{substrate → dist/lite}/.claude/hooks/pre-build-gate.sh +0 -0
- package/{substrate → dist/lite}/.claude/hooks/pre-commit-gate.sh +0 -0
- package/{substrate → dist/lite}/.claude/hooks/session-end.sh +0 -0
- package/{substrate → dist/lite}/.claude/hooks/session-reflection.sh +0 -0
- package/{substrate → dist/lite}/.claude/hooks/skill-body-grade-gate.sh +0 -0
- package/{substrate → dist/lite}/.claude/hooks/skill-body-intent-drift.sh +0 -0
- package/{substrate → dist/lite}/.claude/hooks/state-validate.sh +0 -0
- package/{substrate → dist/lite}/.claude/hooks/substrate-clarity-gate.sh +0 -0
- package/{substrate → dist/lite}/.claude/hooks/temperance-gate.sh +0 -0
- package/{substrate → dist/lite}/.claude/hooks/testing-tier-enforce.sh +0 -0
- package/{substrate → dist/lite}/.claude/hooks/turn-prose-grade-measure.sh +0 -0
- package/{substrate → dist/lite}/.claude/hooks/turn-prose-kiss-check.sh +0 -0
- package/{substrate → dist/lite}/.claude/hooks/vocabulary-migration-check.sh +0 -0
- package/{substrate → dist/lite}/.claude/hooks/whereami-utc-gate.sh +0 -0
- package/dist/lite/.claude/settings.json +212 -0
- package/dist/lite/CLAUDE.md +41 -0
- package/dist/lite/gitignore +58 -0
- package/dist/lite/standards/bassclef-wiring-manifest.json +497 -0
- package/dist/lite/whereami.md +24 -0
- package/package.json +8 -2
- package/substrate/.bassclef/lite-manifest.json +0 -2701
- package/substrate/.claude/agents/architect.md +0 -70
- package/substrate/.claude/agents/builder.md +0 -114
- package/substrate/.claude/agents/designer.md +0 -156
- package/substrate/.claude/agents/reviewer.md +0 -88
- package/substrate/.claude/hooks/longrun-prep-compounding-axis-check.sh +0 -492
- package/substrate/.claude/hooks/skill-step-list-check.sh +0 -171
- package/substrate/.claude/luminaries/alan-cooper.md +0 -170
- package/substrate/.claude/luminaries/alistair-cockburn.md +0 -140
- package/substrate/.claude/luminaries/amazon-pr-faq.md +0 -34
- package/substrate/.claude/luminaries/ash-maurya.md +0 -121
- package/substrate/.claude/luminaries/bill-buxton.md +0 -210
- package/substrate/.claude/luminaries/charles-sanders-peirce.md +0 -150
- package/substrate/.claude/luminaries/david-ogilvy.md +0 -192
- package/substrate/.claude/luminaries/don-norman.md +0 -173
- package/substrate/.claude/luminaries/edward-tufte.md +0 -179
- package/substrate/.claude/luminaries/eric-evans.md +0 -160
- package/substrate/.claude/luminaries/frederick-brooks.md +0 -50
- package/substrate/.claude/luminaries/gang-of-four.md +0 -157
- package/substrate/.claude/luminaries/glenford-myers.md +0 -230
- package/substrate/.claude/luminaries/hunt-thomas.md +0 -115
- package/substrate/.claude/luminaries/hyrum-wright.md +0 -94
- package/substrate/.claude/luminaries/jason-fried-dhh.md +0 -46
- package/substrate/.claude/luminaries/jesse-james-garrett.md +0 -154
- package/substrate/.claude/luminaries/john-ousterhout.md +0 -94
- package/substrate/.claude/luminaries/karl-popper.md +0 -132
- package/substrate/.claude/luminaries/kent-beck.md +0 -168
- package/substrate/.claude/luminaries/linus-torvalds.md +0 -218
- package/substrate/.claude/luminaries/martin-fowler.md +0 -164
- package/substrate/.claude/luminaries/michael-feathers.md +0 -125
- package/substrate/.claude/luminaries/michael-nygard.md +0 -118
- package/substrate/.claude/luminaries/robert-c-martin.md +0 -164
- package/substrate/.claude/luminaries/saltzer-schroeder.md +0 -194
- package/substrate/.claude/luminaries/sophia-prater.md +0 -193
- package/substrate/.claude/luminaries/stephen-toulmin.md +0 -131
- package/substrate/.claude/luminaries/tony-hoare.md +0 -170
- package/substrate/.claude/luminaries/vaughn-vernon.md +0 -50
- package/substrate/.claude/luminaries/w-edwards-deming.md +0 -158
- package/substrate/.claude/rules/accessor-library-discipline.md +0 -138
- package/substrate/.claude/rules/adr-discipline.md +0 -120
- package/substrate/.claude/rules/api-conventions.md +0 -125
- package/substrate/.claude/rules/artifact-ingestion.md +0 -179
- package/substrate/.claude/rules/assert-only-after-verify.md +0 -137
- package/substrate/.claude/rules/blocked-items.md +0 -146
- package/substrate/.claude/rules/bootstrap-pair-discipline.md +0 -141
- package/substrate/.claude/rules/branching.md +0 -28
- package/substrate/.claude/rules/cold-adopter-harness-discipline.md +0 -129
- package/substrate/.claude/rules/commit-conventions.md +0 -22
- package/substrate/.claude/rules/compounding-axis-fresh-analysis.md +0 -188
- package/substrate/.claude/rules/compounding-sequence-fresh-analysis.md +0 -188
- package/substrate/.claude/rules/context-engineering.md +0 -202
- package/substrate/.claude/rules/context-management.md +0 -85
- package/substrate/.claude/rules/defensive-bash.md +0 -68
- package/substrate/.claude/rules/deferred-actions.md +0 -233
- package/substrate/.claude/rules/destructive-operations.md +0 -69
- package/substrate/.claude/rules/diagnosis.md +0 -38
- package/substrate/.claude/rules/github-issue-flash-tweet.md +0 -156
- package/substrate/.claude/rules/guardrails.md +0 -73
- package/substrate/.claude/rules/hook-wire-on-author.md +0 -103
- package/substrate/.claude/rules/identifier-leak-prevention.md +0 -104
- package/substrate/.claude/rules/iteration-bet-brief-completeness.md +0 -54
- package/substrate/.claude/rules/lite-manifest-schema-change-discipline.md +0 -98
- package/substrate/.claude/rules/longrun-prep-plan-doc-compression.md +0 -89
- package/substrate/.claude/rules/loop-discipline.md +0 -81
- package/substrate/.claude/rules/manual-prod-approval.md +0 -100
- package/substrate/.claude/rules/marker-enrichment-discipline.md +0 -99
- package/substrate/.claude/rules/mobile-ephemeral-session.md +0 -109
- package/substrate/.claude/rules/new-dependency-check.md +0 -51
- package/substrate/.claude/rules/oo-ad-entry-point.md +0 -117
- package/substrate/.claude/rules/operator-facing-prose.md +0 -196
- package/substrate/.claude/rules/option-label-discipline.md +0 -108
- package/substrate/.claude/rules/pattern-annotation.md +0 -100
- package/substrate/.claude/rules/plain-english-discipline.md +0 -156
- package/substrate/.claude/rules/plan-enumeration-needs-value-props.md +0 -211
- package/substrate/.claude/rules/pr-body-shape.md +0 -317
- package/substrate/.claude/rules/pr-strategy.md +0 -167
- package/substrate/.claude/rules/pr-title-shape.md +0 -161
- package/substrate/.claude/rules/prototype-workflow.md +0 -65
- package/substrate/.claude/rules/reserved-skill-names.md +0 -123
- package/substrate/.claude/rules/schema-management.md +0 -49
- package/substrate/.claude/rules/sdlc-gates.md +0 -149
- package/substrate/.claude/rules/security.md +0 -37
- package/substrate/.claude/rules/session-artifacts.md +0 -236
- package/substrate/.claude/rules/skill-composition-declarations.md +0 -124
- package/substrate/.claude/rules/skill-description-clarity.md +0 -247
- package/substrate/.claude/rules/skill-procedure-step-list.md +0 -137
- package/substrate/.claude/rules/state-schema-validation.md +0 -162
- package/substrate/.claude/rules/stuck-signal-diagnostic.md +0 -140
- package/substrate/.claude/rules/substrate-config-schema.md +0 -98
- package/substrate/.claude/rules/test-list-discipline.md +0 -175
- package/substrate/.claude/rules/test-sufficiency.md +0 -210
- package/substrate/.claude/rules/testing-tier-config.md +0 -145
- package/substrate/.claude/rules/testing.md +0 -38
- package/substrate/.claude/rules/turn-estimate-grounding.md +0 -134
- package/substrate/.claude/rules/visual-hierarchy.md +0 -437
- package/substrate/.claude/rules/we-dont-break-adopters.md +0 -126
- package/substrate/.claude/rules/whereami-load-bearing.md +0 -202
- package/substrate/.claude/rules/writing-craft-discipline.md +0 -92
- package/substrate/.claude/rules/wu-sequencing-compounds.md +0 -145
- package/substrate/.claude/skills/build/SKILL.md +0 -640
- package/substrate/.claude/skills/chronicle/SKILL.md +0 -55
- package/substrate/.claude/skills/clean-artifacts/SKILL.md +0 -249
- package/substrate/.claude/skills/decompose/SKILL.md +0 -280
- package/substrate/.claude/skills/diagnose/SKILL.md +0 -297
- package/substrate/.claude/skills/feynman/SKILL.md +0 -90
- package/substrate/.claude/skills/howdoi/SKILL.md +0 -105
- package/substrate/.claude/skills/ia-model/SKILL.md +0 -108
- package/substrate/.claude/skills/interaction-design/SKILL.md +0 -112
- package/substrate/.claude/skills/interpret-input/SKILL.md +0 -180
- package/substrate/.claude/skills/journal/SKILL.md +0 -209
- package/substrate/.claude/skills/kiss/SKILL.md +0 -449
- package/substrate/.claude/skills/launch/SKILL.md +0 -915
- package/substrate/.claude/skills/lean-canvas/SKILL.md +0 -332
- package/substrate/.claude/skills/longrun/SKILL.md +0 -463
- package/substrate/.claude/skills/luminary/SKILL.md +0 -481
- package/substrate/.claude/skills/ogilvy-writing-audit/SKILL.md +0 -177
- package/substrate/.claude/skills/onboard-repo/SKILL.md +0 -1624
- package/substrate/.claude/skills/pattern-review/SKILL.md +0 -99
- package/substrate/.claude/skills/personas/SKILL.md +0 -207
- package/substrate/.claude/skills/promote/SKILL.md +0 -283
- package/substrate/.claude/skills/requirement/SKILL.md +0 -98
- package/substrate/.claude/skills/retro/SKILL.md +0 -117
- package/substrate/.claude/skills/riff/SKILL.md +0 -114
- package/substrate/.claude/skills/roadmap-reconcile/SKILL.md +0 -163
- package/substrate/.claude/skills/session-end/SKILL.md +0 -309
- package/substrate/.claude/skills/session-log/SKILL.md +0 -299
- package/substrate/.claude/skills/skills/SKILL.md +0 -228
- package/substrate/.claude/skills/spec/SKILL.md +0 -105
- package/substrate/.claude/skills/sprint/SKILL.md +0 -392
- package/substrate/.claude/skills/stage/SKILL.md +0 -384
- package/substrate/.claude/skills/state-a-problem/SKILL.md +0 -185
- package/substrate/.claude/skills/temperance/SKILL.md +0 -108
- package/substrate/.claude/skills/use-case/SKILL.md +0 -417
- package/substrate/.claude/skills/user-stories/SKILL.md +0 -268
- package/substrate/.claude/skills/value-prop/SKILL.md +0 -251
- package/substrate/.claude/skills/verify/SKILL.md +0 -160
- package/substrate/.claude/skills/visual-review/SKILL.md +0 -503
- package/substrate/.claude/skills/whats-the-plan/SKILL.md +0 -202
- package/substrate/.claude/skills/whereami/SKILL.md +0 -307
- package/substrate/AGENTS.md +0 -79
- package/substrate/CLAUDE-lite.md +0 -85
- package/substrate/CODE_OF_CONDUCT.md +0 -28
- package/substrate/CONTRIBUTING.md +0 -177
- package/substrate/README.md +0 -173
- package/substrate/SECURITY.md +0 -19
- package/substrate/architecture/decisions/ADR-029-release-pipeline.md +0 -79
- package/substrate/architecture/decisions/ADR-031-non-breaking-changes-adopter-discipline.md +0 -139
- package/substrate/architecture/decisions/ADR-032-adopter-sync-dispatcher-architecture.md +0 -192
- package/substrate/architecture/decisions/ADR-039-release-tagging-scheme.md +0 -145
- package/substrate/architecture/decisions/ADR-040-planning-skill-vocabulary-and-lite-profile.md +0 -155
- package/substrate/architecture/decisions/ADR-044-unified-skill-body-template.md +0 -162
- package/substrate/lib/clean-artifacts-sweep.sh +0 -112
- package/substrate/lib/code-comment-discipline.sh +0 -144
- package/substrate/lib/composer-preflight.sh +0 -459
- package/substrate/lib/hook-inject.sh +0 -255
- package/substrate/lib/luminary-pick.sh +0 -96
- package/substrate/lib/output-discipline.sh +0 -143
- package/substrate/lib/prose-scan-boundary.sh +0 -171
- package/substrate/lib/rewrite-check.sh +0 -214
- package/substrate/lib/state.sh +0 -1372
- package/substrate/lib/telemetry.sh +0 -205
- package/substrate/lib/tier-check.sh +0 -187
- package/substrate/lib/tier-dependency-audit.sh +0 -1088
- package/substrate/presence/install/bassclef-hook-connect.sh +0 -178
- package/substrate/presence/install/bassclef-sync.dispatcher.template.sh +0 -841
- package/substrate/presence/install/bassclef-sync.template.sh +0 -2076
- package/substrate/presence/install/schedule-auto-save.cron.sh +0 -88
- package/substrate/presence/install/schedule-auto-save.taskscheduler.md +0 -122
- package/substrate/scripts/aggregate-telemetry.sh +0 -217
- package/substrate/scripts/analyze-tier-dependencies.sh +0 -239
- package/substrate/scripts/generate-lite-manifest.sh +0 -505
- package/substrate/scripts/generate-tier-manifest.sh +0 -28
- package/substrate/scripts/intent-drift-check.sh +0 -456
- package/substrate/scripts/lite-manifest-drift-check.sh +0 -146
- package/substrate/scripts/render-lite-manifest-doc.sh +0 -150
- package/substrate/standards/adr-template.md +0 -86
- package/substrate/standards/api-conventions/nextjs.md +0 -84
- package/substrate/standards/artifact-composition.md +0 -209
- package/substrate/standards/bash-hook-safety.md +0 -246
- package/substrate/standards/bassclef-configs-schema.md +0 -232
- package/substrate/standards/bassclef-evolution.md +0 -143
- package/substrate/standards/bassclef-internal-jargon.md +0 -244
- package/substrate/standards/bassclef-managed-sentinel.md +0 -96
- package/substrate/standards/bassclef-source-config.md +0 -228
- package/substrate/standards/branch-stacking.md +0 -408
- package/substrate/standards/code-safety-principles.md +0 -176
- package/substrate/standards/composer-prerequisites.md +0 -155
- package/substrate/standards/deferred-actions-schema.md +0 -204
- package/substrate/standards/dependency-discipline/cargo.md +0 -39
- package/substrate/standards/dependency-discipline/gem.md +0 -43
- package/substrate/standards/dependency-discipline/go-mod.md +0 -41
- package/substrate/standards/dependency-discipline/npm.md +0 -42
- package/substrate/standards/dependency-discipline/pip.md +0 -42
- package/substrate/standards/deployment-topology/ec2-tailscale.md +0 -225
- package/substrate/standards/deployment-topology.md +0 -69
- package/substrate/standards/docs-sync-allowlist.md +0 -76
- package/substrate/standards/domain-and-dns.md +0 -145
- package/substrate/standards/frontend-stack.md +0 -67
- package/substrate/standards/frontmatter-schema.md +0 -154
- package/substrate/standards/graceful-exit.md +0 -227
- package/substrate/standards/hook-idempotency.md +0 -102
- package/substrate/standards/hook-injection-discipline.md +0 -202
- package/substrate/standards/hook-install-class.md +0 -215
- package/substrate/standards/input-handler-interface.md +0 -152
- package/substrate/standards/lite-manifest-schema-changes.md +0 -135
- package/substrate/standards/luminary-matching.md +0 -105
- package/substrate/standards/luminary-problem-patterns.md +0 -481
- package/substrate/standards/migration-discipline/active-record.md +0 -50
- package/substrate/standards/migration-discipline/alembic.md +0 -43
- package/substrate/standards/migration-discipline/gorm.md +0 -50
- package/substrate/standards/migration-discipline/prisma.md +0 -53
- package/substrate/standards/migration-discipline/sqlalchemy.md +0 -51
- package/substrate/standards/mobile-ephemeral-session.md +0 -167
- package/substrate/standards/model-routing-discipline.md +0 -160
- package/substrate/standards/ogilvy-writing-rules.md +0 -225
- package/substrate/standards/opener-discipline.md +0 -96
- package/substrate/standards/operator-facing-prose-discipline.md +0 -201
- package/substrate/standards/persona-schema.md +0 -229
- package/substrate/standards/pluggable-luminaries.md +0 -323
- package/substrate/standards/pr-body-discipline.md +0 -115
- package/substrate/standards/preview-state-schema.md +0 -189
- package/substrate/standards/project-directory-layout.md +0 -276
- package/substrate/standards/release-tagging.md +0 -137
- package/substrate/standards/reserved-skill-names.md +0 -120
- package/substrate/standards/scannable-multi-option-output.md +0 -261
- package/substrate/standards/sdlc-compliance.md +0 -286
- package/substrate/standards/sdlc-gates/typescript.md +0 -57
- package/substrate/standards/secrets-lifecycle.md +0 -210
- package/substrate/standards/security-scanner-adapter.md +0 -145
- package/substrate/standards/session-board.md +0 -256
- package/substrate/standards/skill-output-discipline.md +0 -90
- package/substrate/standards/state-spine-contract.md +0 -255
- package/substrate/standards/state-spine.md +0 -511
- package/substrate/standards/steering-hints/kiss-words.md +0 -11
- package/substrate/standards/substrate-config-schema.md +0 -267
- package/substrate/standards/tech-stack-config.md +0 -109
- package/substrate/standards/tier-dependency-analysis.md +0 -167
- package/substrate/standards/tier-runtime-deps/lite.md +0 -57
- package/substrate/standards/tier-tag-schema.md +0 -155
- package/substrate/standards/two-layer-config.md +0 -99
- package/substrate/standards/use-case-format.md +0 -292
- package/substrate/standards/user-story-invest.md +0 -268
- package/substrate/standards/velocity-and-appetite.md +0 -229
- package/substrate/standards/voice-input-pattern.md +0 -119
- package/substrate/standards/whereami-schema.md +0 -301
- package/substrate/standards/worktree-management.md +0 -211
- package/substrate/standards/writing-guide.md +0 -213
- package/substrate/templates/chronicle-template.md +0 -75
- package/substrate/templates/deferred-action-template.md +0 -45
- package/substrate/templates/memory-proposal-template.md +0 -77
- package/substrate/templates/persona-template.md +0 -200
- package/substrate/templates/pr-faq.md +0 -45
- package/substrate/templates/secret-rotation-template.md +0 -162
- package/substrate/templates/spec-template.md +0 -131
- package/substrate/templates/use-case-template.md +0 -194
- package/substrate/templates/user-story-template.md +0 -107
- package/substrate/templates/whereami-template.md +0 -101
|
@@ -1,841 +0,0 @@
|
|
|
1
|
-
#!/bin/bash
|
|
2
|
-
# tier: lite
|
|
3
|
-
# description: Retagged standard → lite per #1301 concentric rule (ADR-052 D1) —
|
|
4
|
-
# Retagged standard → lite per #1301 concentric rule (ADR-052 D1) —
|
|
5
|
-
# this dispatcher IS the sync entry point every adopter vendors into
|
|
6
|
-
# .claude/hooks/bassclef-sync.sh. Without ship at lite, lite adopters
|
|
7
|
-
# have no sync at all. Closes #1301 sister file.
|
|
8
|
-
# BASSCLEF_SYNC_VERSION=thin-pointer-2026-07-28a
|
|
9
|
-
# ^^ DO NOT REMOVE — used by bassclef's drift check + Layer 3 self-heal
|
|
10
|
-
# detection (per ADR-032). Version string format: descriptor-YYYY-MM-DD.
|
|
11
|
-
#
|
|
12
|
-
# Thin-pointer bassclef-sync dispatcher.
|
|
13
|
-
#
|
|
14
|
-
# Source of truth for the dispatcher consumers vendor into their
|
|
15
|
-
# .claude/hooks/bassclef-sync.sh. See standards/bassclef-source-config.md
|
|
16
|
-
# for the .bassclef-source.json schema this dispatcher reads.
|
|
17
|
-
#
|
|
18
|
-
# Two paths, tried in order:
|
|
19
|
-
#
|
|
20
|
-
# 1. Sibling fast-path (local dev, desktop, multi-repo workspaces)
|
|
21
|
-
# — if $CWD/../bassclef/presence/install/bassclef-sync.template.sh
|
|
22
|
-
# exists, exec it directly. Always-current because the file is
|
|
23
|
-
# read fresh on every fire.
|
|
24
|
-
#
|
|
25
|
-
# 2. Curl fallback (Cloud Env, mobile, fresh sandboxes, CI)
|
|
26
|
-
# — read .bassclef-source.json for upstream URL + auth metadata,
|
|
27
|
-
# fetch the tarball, extract, exec the included template.
|
|
28
|
-
#
|
|
29
|
-
# When neither path works, the dispatcher prints a plain-language
|
|
30
|
-
# explanation with three resolution paths (public adopter / local dev
|
|
31
|
-
# / private fork). Always exits 0 so SessionStart hooks don't crash;
|
|
32
|
-
# consumers that want CI fail-fast behavior should pre-check inside
|
|
33
|
-
# their workflow.
|
|
34
|
-
#
|
|
35
|
-
# Versioning: bump BASSCLEF_SYNC_VERSION when the dispatcher's
|
|
36
|
-
# semantics change. Format: YYYY-MM-DD or descriptor-YYYY-MM-DD.
|
|
37
|
-
#
|
|
38
|
-
# thin-pointer-2026-07-09: pointer-file rename cure (bet 2026-07-09a).
|
|
39
|
-
# Adopters onboarded before 2026-06-20 rename carry
|
|
40
|
-
# .canonical-source.json. Dispatcher now reads new
|
|
41
|
-
# name first, falls back to old, and self-heals
|
|
42
|
-
# (writes new name from old content; removes old on
|
|
43
|
-
# second cycle per Hoare two-step atomic). Fires
|
|
44
|
-
# before auto_sync check + Path 2 curl fallback.
|
|
45
|
-
# Overrides: SKIP_SELF_HEAL_POINTER=1 skips write.
|
|
46
|
-
# Prior version: thin-pointer-2026-06-29c.
|
|
47
|
-
# thin-pointer-2026-06-29c: fallback message names the cure (bet 29e WU-10).
|
|
48
|
-
# emit_error() now lists option 4 — the curl
|
|
49
|
-
# one-liner that runs migrate-adopter-references.sh
|
|
50
|
-
# for adopters whose tree carries leftover
|
|
51
|
-
# canonical-* references from the 2026-06-20 rename
|
|
52
|
-
# event. Discoverable cure inside the error itself;
|
|
53
|
-
# the adopter does not need to read the wiki.
|
|
54
|
-
# Prior version: thin-pointer-2026-06-29b.
|
|
55
|
-
# thin-pointer-2026-06-29b: auto-invocation added (bet 29e WU-4). Detection
|
|
56
|
-
# step now runs the migrate script automatically
|
|
57
|
-
# via curl-pipe + continues to Path 1/Path 2.
|
|
58
|
-
# SKIP_AUTO_INVOKE=1 falls back to WU-2's BLOCKED
|
|
59
|
-
# behavior. Passes BASSCLEF_DISPATCHER_TEMPLATE
|
|
60
|
-
# to migrate when sibling template available.
|
|
61
|
-
# Prior version: thin-pointer-2026-06-29.
|
|
62
|
-
# thin-pointer-2026-06-29: canonical-* reference detection step added
|
|
63
|
-
# (bet 29e WU-2). Scans adopter .claude/settings.json
|
|
64
|
-
# + vendored bassclef-sync.sh for refs surviving the
|
|
65
|
-
# 2026-06-20 rename. Emits BLOCKED + exits 0. WU-4 will
|
|
66
|
-
# replace exit with auto-invocation of migrate-adopter-
|
|
67
|
-
# references.sh. Override: SKIP_CANONICAL_DETECTION=1.
|
|
68
|
-
# Prior version: thin-pointer-2026-06-22.
|
|
69
|
-
# thin-pointer-2026-06-22: version-detection helper added per ADR-032
|
|
70
|
-
# (Layer 2 two-stage rocket). __bassclef_dispatcher_version
|
|
71
|
-
# function exposes BASSCLEF_SYNC_VERSION to external
|
|
72
|
-
# tooling (Layer 3 self-heal in WU-4). No protocol
|
|
73
|
-
# break; purely additive. Prior version: thin-pointer-2026-06-13.
|
|
74
|
-
# thin-pointer-2026-06-13: auto_sync flag check — dispatcher short-
|
|
75
|
-
# circuits when .bassclef-source.json has
|
|
76
|
-
# auto_sync:false or the field absent. Per
|
|
77
|
-
# bassclef#939. Prior version: 2026-05-15.
|
|
78
|
-
# thin-pointer-2026-05-15: friendly error messages with three
|
|
79
|
-
# resolution paths. Closes bassclef#715
|
|
80
|
-
# Layer A. Prior version: 2026-05-02.
|
|
81
|
-
|
|
82
|
-
# === Version-detection helper (per ADR-032) ===
|
|
83
|
-
# Layer 3 self-heal (WU-4 of bet 2026-06-22b) calls this to detect
|
|
84
|
-
# bootstrap version drift. External tooling can also grep
|
|
85
|
-
# BASSCLEF_SYNC_VERSION from line 3, but the function gives a stable
|
|
86
|
-
# programmatic interface that survives header-comment reformatting.
|
|
87
|
-
__bassclef_dispatcher_version() {
|
|
88
|
-
echo "thin-pointer-2026-07-09"
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
# === Pointer-file fallback + self-heal (bet 2026-07-09a) ===
|
|
92
|
-
#
|
|
93
|
-
# Every adopter onboarded before the 2026-06-20 canonical → bassclef
|
|
94
|
-
# rename carries .canonical-source.json. The dispatcher previously read
|
|
95
|
-
# .bassclef-source.json only; stale adopters saw substrate refuse to
|
|
96
|
-
# load. These two functions cure the class:
|
|
97
|
-
#
|
|
98
|
-
# bassclef_sync_resolve_pointer_file(cwd)
|
|
99
|
-
# Echoes the path of the pointer file to use. Prefers new name;
|
|
100
|
-
# falls back to old name; echoes empty when neither exists.
|
|
101
|
-
#
|
|
102
|
-
# bassclef_sync_self_heal_pointer(cwd)
|
|
103
|
-
# Two-step atomic rename per Tony Hoare. First cycle: writes new
|
|
104
|
-
# name from old content, keeps old file for safety. Second cycle:
|
|
105
|
-
# removes old file when new already exists. Never deletes new.
|
|
106
|
-
# Honors SKIP_SELF_HEAL_POINTER=1 for one-shot recovery scenarios.
|
|
107
|
-
#
|
|
108
|
-
# Composing luminaries:
|
|
109
|
-
# @luminary linus-torvalds — we-dont-break-adopters (ADR-031)
|
|
110
|
-
# @luminary jerome-saltzer-and-michael-schroeder — complete mediation
|
|
111
|
-
# @luminary tony-hoare — pre/post conditions on two-step rename
|
|
112
|
-
# @luminary michael-feathers — characterization tests using real Quorum
|
|
113
|
-
#
|
|
114
|
-
# Tests: .claude/hooks/tests/bassclef-sync-pointer-fallback.test.sh
|
|
115
|
-
# Refs: bassclef-upstream#679
|
|
116
|
-
bassclef_sync_resolve_pointer_file() {
|
|
117
|
-
local cwd="${1:-$CWD}"
|
|
118
|
-
local new="$cwd/.bassclef-source.json"
|
|
119
|
-
local old="$cwd/.canonical-source.json"
|
|
120
|
-
if [ -f "$new" ]; then
|
|
121
|
-
echo "$new"
|
|
122
|
-
elif [ -f "$old" ]; then
|
|
123
|
-
echo "$old"
|
|
124
|
-
else
|
|
125
|
-
echo ""
|
|
126
|
-
fi
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
bassclef_sync_self_heal_pointer() {
|
|
130
|
-
local cwd="${1:-$CWD}"
|
|
131
|
-
if [ "${SKIP_SELF_HEAL_POINTER:-0}" = "1" ]; then
|
|
132
|
-
return 0
|
|
133
|
-
fi
|
|
134
|
-
local new="$cwd/.bassclef-source.json"
|
|
135
|
-
local old="$cwd/.canonical-source.json"
|
|
136
|
-
# Second cycle: both exist → remove old, keep new (Hoare postcondition)
|
|
137
|
-
if [ -f "$new" ] && [ -f "$old" ]; then
|
|
138
|
-
rm -f "$old"
|
|
139
|
-
return 0
|
|
140
|
-
fi
|
|
141
|
-
# First cycle: only old exists → write new from old content, keep old for safety
|
|
142
|
-
if [ ! -f "$new" ] && [ -f "$old" ]; then
|
|
143
|
-
cp "$old" "$new" 2>/dev/null || return 0
|
|
144
|
-
# Emit a one-line note so operator sees the self-heal firing
|
|
145
|
-
echo "bassclef-sync: renamed .canonical-source.json → .bassclef-source.json (auto-heal; original kept for one session)" >&2
|
|
146
|
-
return 0
|
|
147
|
-
fi
|
|
148
|
-
# Only new exists OR neither exists → no-op
|
|
149
|
-
return 0
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
# bassclef_sync_self_heal_pointer_content(cwd)
|
|
153
|
-
# Rewrites drift in .bassclef-source.json content on adopters onboarded
|
|
154
|
-
# before the 2026-06-20 canonical → bassclef rename.
|
|
155
|
-
# - source_url: sunj-labs/canonical -> sunj-labs/bassclef
|
|
156
|
-
# - token_env: CANONICAL_TOKEN -> BASSCLEF_TOKEN
|
|
157
|
-
# Preserves auth_method (Bearer during beta), auto_sync flag, and every
|
|
158
|
-
# other field. Idempotent — no-op when content already uses new names.
|
|
159
|
-
# Honors SKIP_SELF_HEAL_POINTER_CONTENT=1 for one-shot recovery cases.
|
|
160
|
-
# Per bet 2026-07-09c WU-2 (bassclef-upstream#680). Sister to
|
|
161
|
-
# bassclef_sync_self_heal_pointer (filename cure from bet 09a).
|
|
162
|
-
bassclef_sync_self_heal_pointer_content() {
|
|
163
|
-
local cwd="${1:-$CWD}"
|
|
164
|
-
if [ "${SKIP_SELF_HEAL_POINTER_CONTENT:-0}" = "1" ]; then
|
|
165
|
-
return 0
|
|
166
|
-
fi
|
|
167
|
-
local pointer="$cwd/.bassclef-source.json"
|
|
168
|
-
if [ ! -f "$pointer" ]; then
|
|
169
|
-
return 0
|
|
170
|
-
fi
|
|
171
|
-
# Detect drift — cheap grep before invoking jq
|
|
172
|
-
local drift=0
|
|
173
|
-
if grep -q "sunj-labs/canonical" "$pointer" 2>/dev/null; then
|
|
174
|
-
drift=1
|
|
175
|
-
fi
|
|
176
|
-
if grep -q "CANONICAL_TOKEN" "$pointer" 2>/dev/null; then
|
|
177
|
-
drift=1
|
|
178
|
-
fi
|
|
179
|
-
if [ "$drift" = "0" ]; then
|
|
180
|
-
return 0
|
|
181
|
-
fi
|
|
182
|
-
# Rewrite via jq — preserves JSON structure and untouched fields
|
|
183
|
-
local new_json
|
|
184
|
-
new_json=$(jq '
|
|
185
|
-
(if (.source_url // "" | contains("sunj-labs/canonical"))
|
|
186
|
-
then .source_url = (.source_url | sub("sunj-labs/canonical"; "sunj-labs/bassclef"))
|
|
187
|
-
else . end)
|
|
188
|
-
| (if (.token_env // "") == "CANONICAL_TOKEN"
|
|
189
|
-
then .token_env = "BASSCLEF_TOKEN"
|
|
190
|
-
else . end)
|
|
191
|
-
| (if (.comment // "" | contains("sunj-labs/canonical"))
|
|
192
|
-
then .comment = (.comment | gsub("sunj-labs/canonical"; "sunj-labs/bassclef"))
|
|
193
|
-
else . end)
|
|
194
|
-
' "$pointer" 2>/dev/null)
|
|
195
|
-
if [ -n "$new_json" ]; then
|
|
196
|
-
echo "$new_json" > "$pointer.tmp" 2>/dev/null && mv "$pointer.tmp" "$pointer" 2>/dev/null
|
|
197
|
-
echo "bassclef-sync: cured .bassclef-source.json content drift (source_url + token_env → bassclef names)" >&2
|
|
198
|
-
fi
|
|
199
|
-
return 0
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
# bassclef_sync_self_heal_claude_md_content(cwd)
|
|
203
|
-
# Inserts @.claude/bassclef-orientation.md after the first heading in
|
|
204
|
-
# adopter CLAUDE.md when missing. Rewrites stale sunj-labs/canonical
|
|
205
|
-
# URL references + ../canonical path references. Preserves adopter-
|
|
206
|
-
# authored sections. Backs up to CLAUDE.md.bak.<ts> before edit.
|
|
207
|
-
# Idempotent — no-op on cured content.
|
|
208
|
-
# Honors SKIP_SELF_HEAL_CLAUDE_MD_CONTENT=1 for adopters who want to
|
|
209
|
-
# own their CLAUDE.md fully.
|
|
210
|
-
# Per bet 2026-07-09c WU-3 (bassclef-upstream#687 Path 2). Sister to
|
|
211
|
-
# bassclef_sync_self_heal_pointer_content (WU-2 pointer content cure).
|
|
212
|
-
bassclef_sync_self_heal_claude_md_content() {
|
|
213
|
-
local cwd="${1:-$CWD}"
|
|
214
|
-
if [ "${SKIP_SELF_HEAL_CLAUDE_MD_CONTENT:-0}" = "1" ]; then
|
|
215
|
-
return 0
|
|
216
|
-
fi
|
|
217
|
-
local file="$cwd/CLAUDE.md"
|
|
218
|
-
if [ ! -f "$file" ]; then
|
|
219
|
-
return 0
|
|
220
|
-
fi
|
|
221
|
-
local drift_import=0
|
|
222
|
-
local drift_url=0
|
|
223
|
-
local drift_path=0
|
|
224
|
-
if ! grep -q "@.claude/bassclef-orientation.md" "$file" 2>/dev/null; then
|
|
225
|
-
drift_import=1
|
|
226
|
-
fi
|
|
227
|
-
if grep -q "sunj-labs/canonical" "$file" 2>/dev/null; then
|
|
228
|
-
drift_url=1
|
|
229
|
-
fi
|
|
230
|
-
if grep -q "\\.\\./canonical" "$file" 2>/dev/null; then
|
|
231
|
-
drift_path=1
|
|
232
|
-
fi
|
|
233
|
-
if [ "$drift_import" = "0" ] && [ "$drift_url" = "0" ] && [ "$drift_path" = "0" ]; then
|
|
234
|
-
return 0
|
|
235
|
-
fi
|
|
236
|
-
local backup_ts
|
|
237
|
-
backup_ts=$(date +%s)
|
|
238
|
-
cp "$file" "${file}.bak.${backup_ts}" 2>/dev/null
|
|
239
|
-
if [ "$drift_import" = "1" ]; then
|
|
240
|
-
awk 'BEGIN{added=0} /^# / && added==0 {print; print ""; print "@.claude/bassclef-orientation.md"; added=1; next} {print}' \
|
|
241
|
-
"$file" > "${file}.tmp" 2>/dev/null && mv "${file}.tmp" "$file" 2>/dev/null
|
|
242
|
-
fi
|
|
243
|
-
sed 's|sunj-labs/canonical|sunj-labs/bassclef|g; s|\.\./canonical|../bassclef|g' \
|
|
244
|
-
"$file" > "${file}.tmp" 2>/dev/null && mv "${file}.tmp" "$file" 2>/dev/null
|
|
245
|
-
echo "bassclef-sync: cured CLAUDE.md content drift (@import + canonical references → bassclef; backup at ${file}.bak.${backup_ts})" >&2
|
|
246
|
-
return 0
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
INPUT=$(cat)
|
|
250
|
-
CWD=$(echo "$INPUT" | jq -r '.cwd // "."')
|
|
251
|
-
cd "$CWD"
|
|
252
|
-
|
|
253
|
-
# Opt-out sentinel (bassclef#119): repos that must NOT inherit substrate.
|
|
254
|
-
if [ -f "$CWD/.no-bassclef-sync" ]; then
|
|
255
|
-
echo "Bassclef substrate sync: skipped (.no-bassclef-sync sentinel present)."
|
|
256
|
-
exit 0
|
|
257
|
-
fi
|
|
258
|
-
|
|
259
|
-
# === SELF_MODE detection (#929 — closes dispatcher-level bypass of #915) ===
|
|
260
|
-
# Sister to Section 0a in .claude/hooks/bassclef-sync.sh (which shipped in
|
|
261
|
-
# #915 PR #920 and guards the sync flow). This guard sits earlier in the
|
|
262
|
-
# call chain — at the dispatcher — so canonical-* auto-invoke + auto_sync
|
|
263
|
-
# fetch + Path 1 / Path 2 branches ALL skip when the current repo is the
|
|
264
|
-
# substrate source (bassclef or bassclef-upstream).
|
|
265
|
-
#
|
|
266
|
-
# Rationale: session 26g SessionStart re-symlinked ~63 hooks in
|
|
267
|
-
# bassclef-upstream despite #915. The project hook's SELF_MODE fired but
|
|
268
|
-
# only AFTER the dispatcher had already invoked the migrate script + fired
|
|
269
|
-
# other paths that touched the tree. Guard early = complete mediation.
|
|
270
|
-
#
|
|
271
|
-
# Env override SKIP_SELF_MODE_DETECTION=1 forces SELF_MODE=0 regardless
|
|
272
|
-
# of remote — for adopter forks of bassclef-upstream that legitimately
|
|
273
|
-
# want the sync flow.
|
|
274
|
-
#
|
|
275
|
-
# Non-breaking for adopters per ADR-031: SELF_MODE returns 0 for any repo
|
|
276
|
-
# whose git remote is NOT sunj-labs/bassclef or sunj-labs/bassclef-upstream.
|
|
277
|
-
# All 5 existing adopters keep their normal recovery + sync paths.
|
|
278
|
-
__bassclef_dispatcher_detect_self_mode() {
|
|
279
|
-
local cwd="${1:-.}"
|
|
280
|
-
|
|
281
|
-
# Env override wins
|
|
282
|
-
if [ "${SKIP_SELF_MODE_DETECTION:-0}" = "1" ]; then
|
|
283
|
-
echo "0"
|
|
284
|
-
return 0
|
|
285
|
-
fi
|
|
286
|
-
|
|
287
|
-
# No git → not substrate source
|
|
288
|
-
command -v git >/dev/null 2>&1 || { echo "0"; return 0; }
|
|
289
|
-
|
|
290
|
-
# Get remote origin URL
|
|
291
|
-
local remote_url
|
|
292
|
-
remote_url=$(git -C "$cwd" config --get remote.origin.url 2>/dev/null)
|
|
293
|
-
if [ -z "$remote_url" ]; then
|
|
294
|
-
echo "0"
|
|
295
|
-
return 0
|
|
296
|
-
fi
|
|
297
|
-
|
|
298
|
-
# Match sunj-labs/(bassclef|bassclef-upstream) with optional .git suffix
|
|
299
|
-
# HTTPS: https://github.com/sunj-labs/bassclef.git
|
|
300
|
-
# SSH: git@github.com:sunj-labs/bassclef-upstream.git
|
|
301
|
-
if echo "$remote_url" | grep -qE 'sunj-labs/(bassclef|bassclef-upstream)(\.git)?$'; then
|
|
302
|
-
echo "1"
|
|
303
|
-
return 0
|
|
304
|
-
fi
|
|
305
|
-
|
|
306
|
-
echo "0"
|
|
307
|
-
return 0
|
|
308
|
-
}
|
|
309
|
-
|
|
310
|
-
__DISPATCHER_SELF_MODE=$(__bassclef_dispatcher_detect_self_mode "$CWD")
|
|
311
|
-
if [ "$__DISPATCHER_SELF_MODE" = "1" ]; then
|
|
312
|
-
# #895: park user-scope orphans that shadow project scope before exit.
|
|
313
|
-
# Without this, pre-existing symlinks planted by sibling syncs (POA,
|
|
314
|
-
# twoDo, utilities) shadow bassclef-upstream's project scope in the
|
|
315
|
-
# Claude Code menu — 92 skills appear twice. The parking helper leaves
|
|
316
|
-
# real user-scope dirs (operator-authored content) untouched per its
|
|
317
|
-
# v3 contract. Adopters never hit this path (SELF_MODE=0 for their
|
|
318
|
-
# remotes per __bassclef_dispatcher_detect_self_mode).
|
|
319
|
-
#
|
|
320
|
-
# Override: SKIP_SELF_MODE_PARKING=1 for one-shot recovery scenarios.
|
|
321
|
-
if [ "${SKIP_SELF_MODE_PARKING:-0}" != "1" ]; then
|
|
322
|
-
__parking_helper="$CWD/scripts/bassclef-orphan-parking.sh"
|
|
323
|
-
if [ -x "$__parking_helper" ]; then
|
|
324
|
-
for __surface in skills agents hooks; do
|
|
325
|
-
__user_surface="$HOME/.claude/$__surface"
|
|
326
|
-
__project_surface="$CWD/.claude/$__surface"
|
|
327
|
-
if [ -d "$__user_surface" ] && [ -d "$__project_surface" ]; then
|
|
328
|
-
# v4 (bassclef-upstream#1077): pass BOTH user + project settings.json
|
|
329
|
-
# as variadic 5th+ args. Parking helper unions the $HOME wirings
|
|
330
|
-
# across both files. Any hook wired at $HOME by either settings
|
|
331
|
-
# scope is preserved. Missing paths silently skip (helper v4 contract).
|
|
332
|
-
bash "$__parking_helper" "$__user_surface" "$__project_surface" "$HOME/.claude" "$__surface" "$HOME/.claude/settings.json" "$CWD/.claude/settings.json" 2>/dev/null || true
|
|
333
|
-
fi
|
|
334
|
-
done
|
|
335
|
-
fi
|
|
336
|
-
fi
|
|
337
|
-
echo "Bassclef dispatcher SELF_MODE — skipping sync in substrate source repo." >&2
|
|
338
|
-
echo " (Override with SKIP_SELF_MODE_DETECTION=1 for adopter forks;" >&2
|
|
339
|
-
echo " SKIP_SELF_MODE_PARKING=1 to skip user-scope orphan parking.)" >&2
|
|
340
|
-
exit 0
|
|
341
|
-
fi
|
|
342
|
-
|
|
343
|
-
# === auto_sync flag check (bassclef#939) ===
|
|
344
|
-
#
|
|
345
|
-
# Per bassclef#939, fresh consumers default to OFF — the dispatcher
|
|
346
|
-
# only fetches when the consumer explicitly opts in via auto_sync: true
|
|
347
|
-
# in .bassclef-source.json. Cold adopters get a one-line note + the
|
|
348
|
-
# opt-in path instead of opaque auto-fetch.
|
|
349
|
-
#
|
|
350
|
-
# Default behavior on absence (file or field): OFF.
|
|
351
|
-
#
|
|
352
|
-
# Self-heal first (bet 2026-07-09a): stale adopters carrying
|
|
353
|
-
# .canonical-source.json get the file renamed to .bassclef-source.json
|
|
354
|
-
# so this pre-check sees the correct file. Second cycle drops the old.
|
|
355
|
-
bassclef_sync_self_heal_pointer "$CWD"
|
|
356
|
-
# Content-drift cure runs AFTER filename cure so the file we rewrite exists at the new name.
|
|
357
|
-
bassclef_sync_self_heal_pointer_content "$CWD"
|
|
358
|
-
# CLAUDE.md content cure runs at same lifecycle point — before Path 1 / Path 2 pick.
|
|
359
|
-
bassclef_sync_self_heal_claude_md_content "$CWD"
|
|
360
|
-
SOURCE_FILE_PRECHECK=$(bassclef_sync_resolve_pointer_file "$CWD")
|
|
361
|
-
if [ -n "$SOURCE_FILE_PRECHECK" ] && [ -f "$SOURCE_FILE_PRECHECK" ]; then
|
|
362
|
-
AUTO_SYNC=$(jq -r '.auto_sync // false' "$SOURCE_FILE_PRECHECK" 2>/dev/null)
|
|
363
|
-
if [ "$AUTO_SYNC" != "true" ]; then
|
|
364
|
-
cat <<NOTE
|
|
365
|
-
### bassclef-sync — auto-update is OFF
|
|
366
|
-
|
|
367
|
-
Bassclef can keep your skills, rules, and agents current at every
|
|
368
|
-
session start by pulling its latest substrate. It's off by default
|
|
369
|
-
for fresh repos so nothing fetches without your say-so.
|
|
370
|
-
|
|
371
|
-
Turn on anytime by saying "enable auto-sync" or by setting:
|
|
372
|
-
|
|
373
|
-
"auto_sync": true
|
|
374
|
-
|
|
375
|
-
in .bassclef-source.json. Run a manual sync once with:
|
|
376
|
-
|
|
377
|
-
bash .claude/hooks/bassclef-sync.sh
|
|
378
|
-
|
|
379
|
-
More: https://github.com/sunj-labs/bassclef/blob/main/standards/bassclef-source-config.md
|
|
380
|
-
|
|
381
|
-
NOTE
|
|
382
|
-
exit 0
|
|
383
|
-
fi
|
|
384
|
-
fi
|
|
385
|
-
|
|
386
|
-
# === Plain-language error printer ===
|
|
387
|
-
#
|
|
388
|
-
# Args: $1 = short heading, $2 = context paragraph (one or more sentences).
|
|
389
|
-
# Always exits 0 to keep SessionStart hooks non-blocking.
|
|
390
|
-
emit_error() {
|
|
391
|
-
local heading="$1"
|
|
392
|
-
local context="$2"
|
|
393
|
-
cat <<HEADER
|
|
394
|
-
|
|
395
|
-
### bassclef-sync — $heading
|
|
396
|
-
|
|
397
|
-
$context
|
|
398
|
-
|
|
399
|
-
Three ways to fix this:
|
|
400
|
-
|
|
401
|
-
1) PUBLIC adopters (most common)
|
|
402
|
-
Edit .bassclef-source.json to point at the public release tarball:
|
|
403
|
-
|
|
404
|
-
{
|
|
405
|
-
"source_url": "https://github.com/sunj-labs/bassclef/releases/latest/download/substrate.tar.gz",
|
|
406
|
-
"auth_method": "none",
|
|
407
|
-
"token_env": "",
|
|
408
|
-
"comment": "Public bassclef substrate. No auth needed."
|
|
409
|
-
}
|
|
410
|
-
|
|
411
|
-
Pre-launch note: while bassclef is still private, the public
|
|
412
|
-
release URL above may not yet exist. Until it does, use option 3.
|
|
413
|
-
|
|
414
|
-
2) LOCAL DEV — clone bassclef alongside this repo
|
|
415
|
-
|
|
416
|
-
cd ../ && git clone https://github.com/sunj-labs/bassclef.git
|
|
417
|
-
|
|
418
|
-
Re-run your session. The dispatcher uses the local checkout via
|
|
419
|
-
the sibling fast-path; no auth needed.
|
|
420
|
-
|
|
421
|
-
3) PRIVATE / pre-launch — create a fine-grained GitHub PAT
|
|
422
|
-
|
|
423
|
-
a) GitHub -> Settings -> Developer settings -> Personal access tokens
|
|
424
|
-
-> Fine-grained -> Generate new token
|
|
425
|
-
b) Resource owner: sunj-labs
|
|
426
|
-
c) Repository access: select sunj-labs/bassclef only
|
|
427
|
-
d) Permissions -> Repository -> Contents -> Read
|
|
428
|
-
e) Set the token as BASSCLEF_TOKEN in your environment:
|
|
429
|
-
CI: gh secret set BASSCLEF_TOKEN -R <your-org/your-repo>
|
|
430
|
-
Local: export BASSCLEF_TOKEN=<paste>
|
|
431
|
-
Cloud Code: set BASSCLEF_TOKEN in your environment config
|
|
432
|
-
|
|
433
|
-
4) STALE REFERENCES — your repo installed bassclef before 2026-06-29
|
|
434
|
-
|
|
435
|
-
If your tree carries leftover canonical-* references from the
|
|
436
|
-
2026-06-20 rename event, refresh them in place by running the
|
|
437
|
-
migrate script directly:
|
|
438
|
-
|
|
439
|
-
curl -sL https://raw.githubusercontent.com/sunj-labs/bassclef/main/scripts/migrate-adopter-references.sh \\
|
|
440
|
-
| bash -s -- --apply "\$CWD"
|
|
441
|
-
|
|
442
|
-
Open a fresh Claude Code session afterward. The fresh dispatcher
|
|
443
|
-
carries detection that runs the cure automatically when needed.
|
|
444
|
-
|
|
445
|
-
More: https://github.com/sunj-labs/bassclef/blob/main/standards/bassclef-source-config.md
|
|
446
|
-
https://github.com/sunj-labs/bassclef/wiki/Troubleshooting#substrate-fails-to-load-and-you-do-not-see-the-self-heal-banner
|
|
447
|
-
|
|
448
|
-
HEADER
|
|
449
|
-
exit 0
|
|
450
|
-
}
|
|
451
|
-
|
|
452
|
-
# === Recovery script resolver + checksum verifier ===
|
|
453
|
-
#
|
|
454
|
-
# Per goal 2026-08-27 step 7 PR #1 — cures external security review HIGH
|
|
455
|
-
# finding on the self-heal curl|bash fallback (source audit tracked in
|
|
456
|
-
# operator-only artifact; not shipped to public bassclef).
|
|
457
|
-
#
|
|
458
|
-
# Two functions cover Adam's Options A (bundle local) + B (checksum on curl).
|
|
459
|
-
#
|
|
460
|
-
# @pattern strategy (RecoveryScriptResolver picks one of three sources)
|
|
461
|
-
# @pattern guard-clause (verify_checksum fails loud on mismatch)
|
|
462
|
-
|
|
463
|
-
# resolve_recovery_script — prints one of:
|
|
464
|
-
# LOCAL:<path> env override set + file exists
|
|
465
|
-
# SIBLING:<path> sibling checkout has the script
|
|
466
|
-
# CURL:<url>|<sha> neither available; use curl with checksum
|
|
467
|
-
#
|
|
468
|
-
# Priority chain per docs/decompositions/2026-08-27-step-7-pr-1-dispatcher-cure-responsibilities.md
|
|
469
|
-
resolve_recovery_script() {
|
|
470
|
-
# Priority 1 — env override
|
|
471
|
-
if [ -n "${BASSCLEF_RECOVERY_SCRIPT_PATH:-}" ] && [ -f "$BASSCLEF_RECOVERY_SCRIPT_PATH" ]; then
|
|
472
|
-
printf 'LOCAL:%s\n' "$BASSCLEF_RECOVERY_SCRIPT_PATH"
|
|
473
|
-
return 0
|
|
474
|
-
fi
|
|
475
|
-
|
|
476
|
-
# Priority 2 — sibling checkout (matches SIBLING_TEMPLATE pattern at L594)
|
|
477
|
-
local sibling_script="${CWD:-$(pwd)}/../bassclef/scripts/migrate-adopter-references.sh"
|
|
478
|
-
if [ -f "$sibling_script" ]; then
|
|
479
|
-
printf 'SIBLING:%s\n' "$sibling_script"
|
|
480
|
-
return 0
|
|
481
|
-
fi
|
|
482
|
-
|
|
483
|
-
# Priority 3 — curl fallback with checksum sidecar
|
|
484
|
-
local recovery_url="https://raw.githubusercontent.com/sunj-labs/bassclef/main/scripts/migrate-adopter-references.sh"
|
|
485
|
-
local sha_url="${recovery_url}.sha256"
|
|
486
|
-
printf 'CURL:%s|%s\n' "$recovery_url" "$sha_url"
|
|
487
|
-
return 0
|
|
488
|
-
}
|
|
489
|
-
|
|
490
|
-
# verify_checksum <file> <expected_sha256>
|
|
491
|
-
# Returns 0 on match; non-zero + loud stderr on mismatch or missing tool.
|
|
492
|
-
# @luminary saltzer-schroeder — complete mediation; no silent pass.
|
|
493
|
-
verify_checksum() {
|
|
494
|
-
local file="$1"
|
|
495
|
-
local expected="$2"
|
|
496
|
-
local computed=""
|
|
497
|
-
|
|
498
|
-
if command -v shasum >/dev/null 2>&1; then
|
|
499
|
-
computed=$(shasum -a 256 "$file" 2>/dev/null | awk '{print $1}')
|
|
500
|
-
elif command -v sha256sum >/dev/null 2>&1; then
|
|
501
|
-
computed=$(sha256sum "$file" 2>/dev/null | awk '{print $1}')
|
|
502
|
-
else
|
|
503
|
-
echo "verify_checksum: neither shasum nor sha256sum found in PATH" >&2
|
|
504
|
-
echo "verify_checksum: install one before continuing" >&2
|
|
505
|
-
return 2
|
|
506
|
-
fi
|
|
507
|
-
|
|
508
|
-
if [ -z "$computed" ]; then
|
|
509
|
-
echo "verify_checksum: could not compute SHA-256 of $file" >&2
|
|
510
|
-
return 3
|
|
511
|
-
fi
|
|
512
|
-
|
|
513
|
-
if [ "$computed" = "$expected" ]; then
|
|
514
|
-
return 0
|
|
515
|
-
fi
|
|
516
|
-
|
|
517
|
-
echo "verify_checksum: SHA-256 mismatch on $file" >&2
|
|
518
|
-
echo "verify_checksum: expected: $expected" >&2
|
|
519
|
-
echo "verify_checksum: computed: $computed" >&2
|
|
520
|
-
return 1
|
|
521
|
-
}
|
|
522
|
-
|
|
523
|
-
# === Canonical-* reference detection (per bet 29e WU-2) ===
|
|
524
|
-
#
|
|
525
|
-
# Self-heal for adopters carrying canonical-* references from the
|
|
526
|
-
# 2026-06-20 rename. Scans the adopter .claude/ tree at session-start
|
|
527
|
-
# BEFORE Path 1 / Path 2. When canonical-* refs are found, emits a
|
|
528
|
-
# BLOCKED block naming the recovery command (curl one-liner shipped
|
|
529
|
-
# in WU-3 of bet 29e) and exits 0 so SessionStart stays non-blocking.
|
|
530
|
-
#
|
|
531
|
-
# WU-2 emits BLOCKED + exits. WU-4 will rewrite this block to auto-
|
|
532
|
-
# invoke the recovery and continue the dispatcher chain.
|
|
533
|
-
#
|
|
534
|
-
# Override: SKIP_CANONICAL_DETECTION=1 bypasses the scan. Reserved for
|
|
535
|
-
# migration scripts; not for routine adopter use.
|
|
536
|
-
#
|
|
537
|
-
# Primary lens: @luminary michael-nygard — self-healing integration
|
|
538
|
-
# point per Release It! Stability Patterns. Composing lenses:
|
|
539
|
-
# @luminary jerome-saltzer-and-michael-schroeder (complete mediation —
|
|
540
|
-
# every session-start sees the scan), @luminary tony-hoare (when no
|
|
541
|
-
# canonical refs found, scan is silent; postcondition holds), @luminary
|
|
542
|
-
# john-ousterhout (deep dispatcher hides migration complexity).
|
|
543
|
-
if [ "${SKIP_CANONICAL_DETECTION:-0}" != "1" ]; then
|
|
544
|
-
CANONICAL_FINDINGS=()
|
|
545
|
-
|
|
546
|
-
# Surface 2: settings.json additionalDirectories contains "canonical"
|
|
547
|
-
SETTINGS_PATH="$CWD/.claude/settings.json"
|
|
548
|
-
if [ -f "$SETTINGS_PATH" ]; then
|
|
549
|
-
STALE_DIRS=$(jq -r '.permissions.additionalDirectories // [] | .[] | select(test("canonical"))' "$SETTINGS_PATH" 2>/dev/null || true)
|
|
550
|
-
if [ -n "$STALE_DIRS" ]; then
|
|
551
|
-
CANONICAL_FINDINGS+=(".claude/settings.json additionalDirectories contains canonical")
|
|
552
|
-
fi
|
|
553
|
-
fi
|
|
554
|
-
|
|
555
|
-
# Surface 3: vendored dispatcher BASSCLEF_SYNC_VERSION drift
|
|
556
|
-
# (per ADR-032 Layer 3 self-heal; mirrors migrate-adopter-references.sh Surface 3)
|
|
557
|
-
# Read the current version from the helper to avoid drift between the
|
|
558
|
-
# comment header, the function, and this constant.
|
|
559
|
-
CURRENT_VERSION=$(__bassclef_dispatcher_version)
|
|
560
|
-
for CANDIDATE in "$CWD/.claude/hooks/bassclef-sync.sh" "$CWD/.claude/hooks/canonical-sync.sh"; do
|
|
561
|
-
if [ -f "$CANDIDATE" ] && [ ! -L "$CANDIDATE" ]; then
|
|
562
|
-
VENDORED_VERSION=$(grep -m1 'BASSCLEF_SYNC_VERSION=' "$CANDIDATE" 2>/dev/null | sed 's/.*BASSCLEF_SYNC_VERSION=\([^ ]*\).*/\1/' | head -1)
|
|
563
|
-
if [ -z "$VENDORED_VERSION" ] || [[ "$VENDORED_VERSION" < "$CURRENT_VERSION" ]]; then
|
|
564
|
-
BASENAME=$(basename "$CANDIDATE")
|
|
565
|
-
DISPLAY_VERSION="${VENDORED_VERSION:-<missing>}"
|
|
566
|
-
CANONICAL_FINDINGS+=(".claude/hooks/$BASENAME stale (BASSCLEF_SYNC_VERSION=$DISPLAY_VERSION; current=$CURRENT_VERSION)")
|
|
567
|
-
fi
|
|
568
|
-
break
|
|
569
|
-
fi
|
|
570
|
-
done
|
|
571
|
-
|
|
572
|
-
if [ "${#CANONICAL_FINDINGS[@]}" -gt 0 ]; then
|
|
573
|
-
RECOVERY_URL="https://raw.githubusercontent.com/sunj-labs/bassclef/main/scripts/migrate-adopter-references.sh"
|
|
574
|
-
SIBLING_DISPATCHER_TEMPLATE="$CWD/../bassclef/presence/install/bassclef-sync.dispatcher.template.sh"
|
|
575
|
-
# Per bet 30a WU-5 (F7 cure): the migrate script reads three env vars
|
|
576
|
-
# for path overrides. Local layout sibling files for each.
|
|
577
|
-
SIBLING_RENAME_MAP="$CWD/../bassclef/standards/file-renames.json"
|
|
578
|
-
SIBLING_STATUSLINE_TEMPLATE="$CWD/../bassclef/presence/cli/bassclef-statusline.dispatcher.sh"
|
|
579
|
-
|
|
580
|
-
# Decide auto-invoke vs BLOCKED-only path (per bet 29e WU-4)
|
|
581
|
-
AUTO_INVOKE_READY=0
|
|
582
|
-
if [ "${SKIP_AUTO_INVOKE:-0}" != "1" ]; then
|
|
583
|
-
if [ -n "${BASSCLEF_RECOVERY_SCRIPT_PATH:-}" ] && [ -f "$BASSCLEF_RECOVERY_SCRIPT_PATH" ]; then
|
|
584
|
-
AUTO_INVOKE_READY=1
|
|
585
|
-
elif command -v curl >/dev/null 2>&1; then
|
|
586
|
-
AUTO_INVOKE_READY=1
|
|
587
|
-
fi
|
|
588
|
-
fi
|
|
589
|
-
|
|
590
|
-
if [ "$AUTO_INVOKE_READY" = "1" ]; then
|
|
591
|
-
# === Leg 3 of self-healing — auto-invocation (WU-4) ===
|
|
592
|
-
# Detection found canonical-* refs; run the migrate script
|
|
593
|
-
# automatically; continue the dispatcher chain afterward so the
|
|
594
|
-
# adopter sees one clean session-start (no second paste needed).
|
|
595
|
-
echo ""
|
|
596
|
-
echo "🩹 bassclef self-heal — canonical-* references detected; running recovery automatically"
|
|
597
|
-
for finding in "${CANONICAL_FINDINGS[@]}"; do
|
|
598
|
-
echo " - $finding"
|
|
599
|
-
done
|
|
600
|
-
|
|
601
|
-
# Source the migrate script (env-var override for tests, curl in prod).
|
|
602
|
-
# Per bet 30a WU-5 (F7 cure): pass all three env vars the migrate
|
|
603
|
-
# script reads — DISPATCHER_TEMPLATE + RENAME_MAP + STATUSLINE_TEMPLATE
|
|
604
|
-
# — when their sibling files exist. Without these, the script's
|
|
605
|
-
# fallback expansion `$(cd "$(dirname "$0")/..")` resolves wrong
|
|
606
|
-
# under curl-pipe ($0 = bash), and Surfaces 5 + 6 silently no-op.
|
|
607
|
-
# POA was broken for 8+ days because only the dispatcher template
|
|
608
|
-
# env var was passed.
|
|
609
|
-
ENV_ARGS=()
|
|
610
|
-
[ -f "$SIBLING_DISPATCHER_TEMPLATE" ] && ENV_ARGS+=("BASSCLEF_DISPATCHER_TEMPLATE=$SIBLING_DISPATCHER_TEMPLATE")
|
|
611
|
-
[ -f "$SIBLING_RENAME_MAP" ] && ENV_ARGS+=("BASSCLEF_RENAME_MAP=$SIBLING_RENAME_MAP")
|
|
612
|
-
[ -f "$SIBLING_STATUSLINE_TEMPLATE" ] && ENV_ARGS+=("BASSCLEF_STATUSLINE_TEMPLATE=$SIBLING_STATUSLINE_TEMPLATE")
|
|
613
|
-
|
|
614
|
-
# Per bet 2026-08-27 step 7 PR #1 — resolver picks source with priority
|
|
615
|
-
# env override → sibling → curl+checksum. Verifier gates curl path.
|
|
616
|
-
RESOLVED=$(resolve_recovery_script)
|
|
617
|
-
RESOLVED_KIND="${RESOLVED%%:*}"
|
|
618
|
-
RESOLVED_REST="${RESOLVED#*:}"
|
|
619
|
-
|
|
620
|
-
case "$RESOLVED_KIND" in
|
|
621
|
-
LOCAL|SIBLING)
|
|
622
|
-
echo "🩹 recovery source: $RESOLVED_KIND ($RESOLVED_REST)" >&2
|
|
623
|
-
if [ "${#ENV_ARGS[@]}" -gt 0 ]; then
|
|
624
|
-
cat "$RESOLVED_REST" | env "${ENV_ARGS[@]}" bash -s -- --apply "$CWD" || true
|
|
625
|
-
else
|
|
626
|
-
cat "$RESOLVED_REST" | bash -s -- --apply "$CWD" || true
|
|
627
|
-
fi
|
|
628
|
-
;;
|
|
629
|
-
CURL)
|
|
630
|
-
RECOVERY_URL_RESOLVED="${RESOLVED_REST%|*}"
|
|
631
|
-
SHA_URL="${RESOLVED_REST#*|}"
|
|
632
|
-
echo "🩹 recovery source: CURL ($RECOVERY_URL_RESOLVED)" >&2
|
|
633
|
-
TMP_SCRIPT=$(mktemp -t bassclef-recovery.XXXXXX.sh) || {
|
|
634
|
-
echo "⚠ bassclef self-heal: mktemp failed; skipping recovery" >&2
|
|
635
|
-
true
|
|
636
|
-
}
|
|
637
|
-
TMP_SHA=$(mktemp -t bassclef-recovery.XXXXXX.sha) || {
|
|
638
|
-
rm -f "$TMP_SCRIPT" 2>/dev/null
|
|
639
|
-
echo "⚠ bassclef self-heal: mktemp failed; skipping recovery" >&2
|
|
640
|
-
true
|
|
641
|
-
}
|
|
642
|
-
# Fetch both files; abort verify path if either fetch fails
|
|
643
|
-
if curl -sL --fail "$RECOVERY_URL_RESOLVED" -o "$TMP_SCRIPT" 2>/dev/null \
|
|
644
|
-
&& curl -sL --fail "$SHA_URL" -o "$TMP_SHA" 2>/dev/null; then
|
|
645
|
-
EXPECTED_SHA=$(awk '{print $1}' "$TMP_SHA")
|
|
646
|
-
if verify_checksum "$TMP_SCRIPT" "$EXPECTED_SHA"; then
|
|
647
|
-
echo "🩹 recovery: checksum verified; executing" >&2
|
|
648
|
-
if [ "${#ENV_ARGS[@]}" -gt 0 ]; then
|
|
649
|
-
cat "$TMP_SCRIPT" | env "${ENV_ARGS[@]}" bash -s -- --apply "$CWD" || true
|
|
650
|
-
else
|
|
651
|
-
cat "$TMP_SCRIPT" | bash -s -- --apply "$CWD" || true
|
|
652
|
-
fi
|
|
653
|
-
else
|
|
654
|
-
echo "🛑 recovery: SHA-256 mismatch; refusing to execute" >&2
|
|
655
|
-
echo " URL: $RECOVERY_URL_RESOLVED" >&2
|
|
656
|
-
echo " To retry manually after investigating:" >&2
|
|
657
|
-
echo " SKIP_CANONICAL_DETECTION=1 <re-run session>" >&2
|
|
658
|
-
fi
|
|
659
|
-
else
|
|
660
|
-
echo "⚠ bassclef self-heal: fetch failed for recovery or checksum" >&2
|
|
661
|
-
echo " Falls back to manual recovery via BLOCKED path below" >&2
|
|
662
|
-
fi
|
|
663
|
-
rm -f "$TMP_SCRIPT" "$TMP_SHA" 2>/dev/null
|
|
664
|
-
;;
|
|
665
|
-
*)
|
|
666
|
-
echo "⚠ bassclef self-heal: resolver returned unknown kind ($RESOLVED_KIND); skipping" >&2
|
|
667
|
-
;;
|
|
668
|
-
esac
|
|
669
|
-
|
|
670
|
-
echo "🩹 bassclef self-heal: recovery applied; continuing"
|
|
671
|
-
echo ""
|
|
672
|
-
# Fall through to Path 1 / Path 2 — substrate now loadable
|
|
673
|
-
else
|
|
674
|
-
# === Fall back: BLOCKED + exit (WU-2 behavior) ===
|
|
675
|
-
# SKIP_AUTO_INVOKE=1 set, OR neither curl nor BASSCLEF_RECOVERY_SCRIPT_PATH
|
|
676
|
-
# available. Surface the recovery shape and stop here.
|
|
677
|
-
cat <<DETECT
|
|
678
|
-
|
|
679
|
-
🛑 BLOCKED: bassclef substrate — canonical-* references detected
|
|
680
|
-
|
|
681
|
-
Your adopter tree carries references from before the 2026-06-20
|
|
682
|
-
canonical→bassclef rename. Bassclef cannot load substrate cleanly
|
|
683
|
-
until these are repaired.
|
|
684
|
-
|
|
685
|
-
Found:
|
|
686
|
-
DETECT
|
|
687
|
-
for finding in "${CANONICAL_FINDINGS[@]}"; do
|
|
688
|
-
echo " - $finding"
|
|
689
|
-
done
|
|
690
|
-
cat <<RECOVERY
|
|
691
|
-
|
|
692
|
-
Recovery — one paste, no extra setup:
|
|
693
|
-
|
|
694
|
-
curl -sL $RECOVERY_URL | bash -s -- --apply "$CWD"
|
|
695
|
-
|
|
696
|
-
After it runs, open a fresh Claude Code session in this repo.
|
|
697
|
-
|
|
698
|
-
To skip this check once (override): SKIP_CANONICAL_DETECTION=1
|
|
699
|
-
To skip auto-invocation (manual recovery): SKIP_AUTO_INVOKE=1
|
|
700
|
-
|
|
701
|
-
Refs: scripts/migrate-adopter-references.sh, .claude/rules/we-dont-break-adopters.md
|
|
702
|
-
|
|
703
|
-
RECOVERY
|
|
704
|
-
exit 0
|
|
705
|
-
fi
|
|
706
|
-
fi
|
|
707
|
-
fi
|
|
708
|
-
|
|
709
|
-
# === Path 1. Sibling fast-path ===
|
|
710
|
-
SIBLING_TEMPLATE="$CWD/../bassclef/presence/install/bassclef-sync.template.sh"
|
|
711
|
-
if [ -f "$SIBLING_TEMPLATE" ]; then
|
|
712
|
-
echo "$INPUT" | bash "$SIBLING_TEMPLATE"
|
|
713
|
-
exit $?
|
|
714
|
-
fi
|
|
715
|
-
|
|
716
|
-
# === Path 2. Curl fallback ===
|
|
717
|
-
# Uses the same resolver as auto_sync pre-check so old-name adopters
|
|
718
|
-
# still get here (self-heal already fired above, but resolve for safety
|
|
719
|
-
# in case self-heal was skipped via SKIP_SELF_HEAL_POINTER).
|
|
720
|
-
SOURCE_FILE=$(bassclef_sync_resolve_pointer_file "$CWD")
|
|
721
|
-
if [ -z "$SOURCE_FILE" ] || [ ! -f "$SOURCE_FILE" ]; then
|
|
722
|
-
emit_error "couldn't find bassclef substrate" \
|
|
723
|
-
"This repo doesn't have a sibling bassclef checkout at ../bassclef AND
|
|
724
|
-
doesn't have a .bassclef-source.json file to fetch from a remote source.
|
|
725
|
-
|
|
726
|
-
The dispatcher needs ONE of those to load bassclef's substrate (skills,
|
|
727
|
-
rules, hooks, luminaries) into your session."
|
|
728
|
-
fi
|
|
729
|
-
|
|
730
|
-
SOURCE_URL=$(jq -r '.source_url // empty' "$SOURCE_FILE")
|
|
731
|
-
AUTH_METHOD=$(jq -r '.auth_method // "none"' "$SOURCE_FILE")
|
|
732
|
-
TOKEN_ENV=$(jq -r '.token_env // "BASSCLEF_TOKEN"' "$SOURCE_FILE")
|
|
733
|
-
|
|
734
|
-
if [ -z "$SOURCE_URL" ]; then
|
|
735
|
-
emit_error ".bassclef-source.json is missing source_url" \
|
|
736
|
-
"Your .bassclef-source.json file exists but doesn't specify where to fetch
|
|
737
|
-
bassclef from. The 'source_url' field is required.
|
|
738
|
-
|
|
739
|
-
See standards/bassclef-source-config.md for the schema and provider
|
|
740
|
-
examples (GitHub public release, GitHub private repo, Azure DevOps, GitLab)."
|
|
741
|
-
fi
|
|
742
|
-
|
|
743
|
-
# Resolve auth header from env-stored token.
|
|
744
|
-
TOKEN_VALUE=""
|
|
745
|
-
AUTH_HEADER=""
|
|
746
|
-
if [ "$AUTH_METHOD" != "none" ]; then
|
|
747
|
-
TOKEN_VALUE=$(printenv "$TOKEN_ENV" 2>/dev/null || true)
|
|
748
|
-
if [ -z "$TOKEN_VALUE" ]; then
|
|
749
|
-
emit_error "auth token not set in environment" \
|
|
750
|
-
"Your .bassclef-source.json uses auth_method '$AUTH_METHOD' and expects the
|
|
751
|
-
'$TOKEN_ENV' environment variable to hold the token. That variable isn't set
|
|
752
|
-
in this environment.
|
|
753
|
-
|
|
754
|
-
If you're in CI: the secret needs to be configured on the repo
|
|
755
|
-
(gh secret set $TOKEN_ENV -R <repo>).
|
|
756
|
-
If you're on a laptop: export $TOKEN_ENV=<token> in your shell.
|
|
757
|
-
If you're in Cloud Code: set $TOKEN_ENV in your environment config.
|
|
758
|
-
|
|
759
|
-
If you don't have a token yet, follow option 3 below to create one."
|
|
760
|
-
fi
|
|
761
|
-
case "$AUTH_METHOD" in
|
|
762
|
-
Bearer) AUTH_HEADER="Authorization: Bearer $TOKEN_VALUE" ;;
|
|
763
|
-
Basic) AUTH_HEADER="Authorization: Basic $(printf ':%s' "$TOKEN_VALUE" | base64)" ;;
|
|
764
|
-
*) AUTH_HEADER="Authorization: $AUTH_METHOD $TOKEN_VALUE" ;;
|
|
765
|
-
esac
|
|
766
|
-
fi
|
|
767
|
-
|
|
768
|
-
# Fetch tarball
|
|
769
|
-
TARBALL="/tmp/bassclef-thin-pointer-$$.tar.gz"
|
|
770
|
-
if [ -n "$AUTH_HEADER" ]; then
|
|
771
|
-
HTTP_CODE=$(curl -sS -L -H "$AUTH_HEADER" -w "%{http_code}" -o "$TARBALL" "$SOURCE_URL" 2>/dev/null || echo "000")
|
|
772
|
-
else
|
|
773
|
-
HTTP_CODE=$(curl -sS -L -w "%{http_code}" -o "$TARBALL" "$SOURCE_URL" 2>/dev/null || echo "000")
|
|
774
|
-
fi
|
|
775
|
-
|
|
776
|
-
if [ "$HTTP_CODE" != "200" ]; then
|
|
777
|
-
rm -f "$TARBALL" 2>/dev/null
|
|
778
|
-
emit_error "fetch returned HTTP $HTTP_CODE" \
|
|
779
|
-
"The dispatcher tried to download bassclef from:
|
|
780
|
-
|
|
781
|
-
$SOURCE_URL
|
|
782
|
-
|
|
783
|
-
The server returned HTTP $HTTP_CODE instead of 200. Common causes:
|
|
784
|
-
|
|
785
|
-
HTTP 401: token is invalid or expired. Regenerate it.
|
|
786
|
-
HTTP 403: token is valid but doesn't have the required permission
|
|
787
|
-
(needs Contents:read on the bassclef repo).
|
|
788
|
-
HTTP 404: source_url is wrong, OR the bassclef repo / release
|
|
789
|
-
doesn't exist at that URL.
|
|
790
|
-
HTTP 000: network couldn't reach the host. Check DNS / firewall /
|
|
791
|
-
whether you're offline."
|
|
792
|
-
fi
|
|
793
|
-
|
|
794
|
-
# Extract to a stable per-user location.
|
|
795
|
-
BASSCLEF_FRESH="$HOME/bassclef-fresh"
|
|
796
|
-
rm -rf "$BASSCLEF_FRESH" 2>/dev/null
|
|
797
|
-
mkdir -p "$BASSCLEF_FRESH"
|
|
798
|
-
if ! tar -xzf "$TARBALL" -C "$BASSCLEF_FRESH" --strip-components=1 2>/dev/null; then
|
|
799
|
-
rm -f "$TARBALL"
|
|
800
|
-
emit_error "couldn't extract the downloaded tarball" \
|
|
801
|
-
"The dispatcher downloaded the file from $SOURCE_URL but tar -xzf failed.
|
|
802
|
-
|
|
803
|
-
This usually means the response wasn't a real tarball. Check:
|
|
804
|
-
|
|
805
|
-
- Is source_url correct? It should return a gzipped tarball, not HTML.
|
|
806
|
-
- Is a network proxy / SSO portal injecting a login page instead?
|
|
807
|
-
- To inspect what the server is actually sending, run:
|
|
808
|
-
|
|
809
|
-
curl -sSL -H \"Authorization: ...\" \"$SOURCE_URL\" | file -
|
|
810
|
-
|
|
811
|
-
If the output says 'HTML document' instead of 'gzip compressed data',
|
|
812
|
-
you're being intercepted."
|
|
813
|
-
fi
|
|
814
|
-
rm -f "$TARBALL"
|
|
815
|
-
|
|
816
|
-
# Exec the big template.
|
|
817
|
-
#
|
|
818
|
-
# Export the extracted tarball root so §3c-hooks (dynamic-derive hook connect,
|
|
819
|
-
# per bassclef-upstream#625) can read bassclef's own .claude/settings.json.
|
|
820
|
-
# The template sources presence/install/bassclef-hook-connect.sh and calls
|
|
821
|
-
# bassclef_hook_connect_apply "$CWD" — the function reads
|
|
822
|
-
# $BASSCLEF_SOURCE_ROOT/.claude/settings.json to learn the current hook list
|
|
823
|
-
# across every event type, then merges every entry additively into the
|
|
824
|
-
# adopter's settings.json.
|
|
825
|
-
export BASSCLEF_SOURCE_ROOT="$BASSCLEF_FRESH"
|
|
826
|
-
|
|
827
|
-
FALLBACK_TEMPLATE="$BASSCLEF_FRESH/presence/install/bassclef-sync.template.sh"
|
|
828
|
-
if [ ! -f "$FALLBACK_TEMPLATE" ]; then
|
|
829
|
-
emit_error "tarball is missing bassclef-sync.template.sh" \
|
|
830
|
-
"The dispatcher downloaded and extracted the tarball, but it doesn't
|
|
831
|
-
contain presence/install/bassclef-sync.template.sh — bassclef's
|
|
832
|
-
main sync logic.
|
|
833
|
-
|
|
834
|
-
This usually means source_url points at a tarball that isn't bassclef
|
|
835
|
-
(e.g., a different repo, or a branch / tag that's missing the template
|
|
836
|
-
file). Verify the URL in .bassclef-source.json points at bassclef's
|
|
837
|
-
main branch or a release that includes strategy/templates/."
|
|
838
|
-
fi
|
|
839
|
-
|
|
840
|
-
echo "$INPUT" | bash "$FALLBACK_TEMPLATE"
|
|
841
|
-
exit $?
|