@thebassclef/lite 0.0.1 → 0.1.2
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/LICENSE +202 -0
- package/README.md +85 -4
- package/dist/cli.cjs +1612 -0
- package/dist/cli.js +1589 -0
- package/dist/index.cjs +4 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +4 -0
- package/package.json +51 -3
- package/substrate/.bassclef/lite-manifest.json +2701 -0
- package/substrate/.claude/agents/architect.md +70 -0
- package/substrate/.claude/agents/builder.md +114 -0
- package/substrate/.claude/agents/designer.md +156 -0
- package/substrate/.claude/agents/reviewer.md +88 -0
- package/substrate/.claude/hooks/artifact-ingestion-gate.sh +357 -0
- package/substrate/.claude/hooks/assert-verify-steering.sh +77 -0
- package/substrate/.claude/hooks/bassclef-source-config-validate.sh +215 -0
- package/substrate/.claude/hooks/bassclef-sync.sh +634 -0
- package/substrate/.claude/hooks/compound-noun-scrub.sh +292 -0
- package/substrate/.claude/hooks/kiss-expansion-inject.sh +69 -0
- package/substrate/.claude/hooks/longrun-prep-compounding-axis-check.sh +492 -0
- package/substrate/.claude/hooks/longrun-prep-compounding-sequence-check.sh +492 -0
- package/substrate/.claude/hooks/plain-english-steering.sh +156 -0
- package/substrate/.claude/hooks/post-skill-friction-check.sh +177 -0
- package/substrate/.claude/hooks/post-skill-telemetry.sh +62 -0
- package/substrate/.claude/hooks/pre-build-gate.sh +511 -0
- package/substrate/.claude/hooks/pre-commit-gate.sh +451 -0
- package/substrate/.claude/hooks/session-end.sh +433 -0
- package/substrate/.claude/hooks/session-reflection.sh +303 -0
- package/substrate/.claude/hooks/skill-body-grade-gate.sh +219 -0
- package/substrate/.claude/hooks/skill-body-intent-drift.sh +107 -0
- package/substrate/.claude/hooks/skill-step-list-check.sh +171 -0
- package/substrate/.claude/hooks/state-validate.sh +271 -0
- package/substrate/.claude/hooks/substrate-clarity-gate.sh +1110 -0
- package/substrate/.claude/hooks/temperance-gate.sh +147 -0
- package/substrate/.claude/hooks/testing-tier-enforce.sh +233 -0
- package/substrate/.claude/hooks/turn-prose-grade-measure.sh +219 -0
- package/substrate/.claude/hooks/turn-prose-kiss-check.sh +463 -0
- package/substrate/.claude/hooks/vocabulary-migration-check.sh +171 -0
- package/substrate/.claude/hooks/whereami-utc-gate.sh +142 -0
- package/substrate/.claude/luminaries/alan-cooper.md +170 -0
- package/substrate/.claude/luminaries/alistair-cockburn.md +140 -0
- package/substrate/.claude/luminaries/amazon-pr-faq.md +34 -0
- package/substrate/.claude/luminaries/ash-maurya.md +121 -0
- package/substrate/.claude/luminaries/bill-buxton.md +210 -0
- package/substrate/.claude/luminaries/charles-sanders-peirce.md +150 -0
- package/substrate/.claude/luminaries/david-ogilvy.md +192 -0
- package/substrate/.claude/luminaries/don-norman.md +173 -0
- package/substrate/.claude/luminaries/edward-tufte.md +179 -0
- package/substrate/.claude/luminaries/eric-evans.md +160 -0
- package/substrate/.claude/luminaries/frederick-brooks.md +50 -0
- package/substrate/.claude/luminaries/gang-of-four.md +157 -0
- package/substrate/.claude/luminaries/glenford-myers.md +230 -0
- package/substrate/.claude/luminaries/hunt-thomas.md +115 -0
- package/substrate/.claude/luminaries/hyrum-wright.md +94 -0
- package/substrate/.claude/luminaries/jason-fried-dhh.md +46 -0
- package/substrate/.claude/luminaries/jesse-james-garrett.md +154 -0
- package/substrate/.claude/luminaries/john-ousterhout.md +94 -0
- package/substrate/.claude/luminaries/karl-popper.md +132 -0
- package/substrate/.claude/luminaries/kent-beck.md +168 -0
- package/substrate/.claude/luminaries/linus-torvalds.md +218 -0
- package/substrate/.claude/luminaries/martin-fowler.md +164 -0
- package/substrate/.claude/luminaries/michael-feathers.md +125 -0
- package/substrate/.claude/luminaries/michael-nygard.md +118 -0
- package/substrate/.claude/luminaries/robert-c-martin.md +164 -0
- package/substrate/.claude/luminaries/saltzer-schroeder.md +194 -0
- package/substrate/.claude/luminaries/sophia-prater.md +193 -0
- package/substrate/.claude/luminaries/stephen-toulmin.md +131 -0
- package/substrate/.claude/luminaries/tony-hoare.md +170 -0
- package/substrate/.claude/luminaries/vaughn-vernon.md +50 -0
- package/substrate/.claude/luminaries/w-edwards-deming.md +158 -0
- package/substrate/.claude/rules/accessor-library-discipline.md +138 -0
- package/substrate/.claude/rules/adr-discipline.md +120 -0
- package/substrate/.claude/rules/api-conventions.md +125 -0
- package/substrate/.claude/rules/artifact-ingestion.md +179 -0
- package/substrate/.claude/rules/assert-only-after-verify.md +137 -0
- package/substrate/.claude/rules/blocked-items.md +146 -0
- package/substrate/.claude/rules/bootstrap-pair-discipline.md +141 -0
- package/substrate/.claude/rules/branching.md +28 -0
- package/substrate/.claude/rules/cold-adopter-harness-discipline.md +129 -0
- package/substrate/.claude/rules/commit-conventions.md +22 -0
- package/substrate/.claude/rules/compounding-axis-fresh-analysis.md +188 -0
- package/substrate/.claude/rules/compounding-sequence-fresh-analysis.md +188 -0
- package/substrate/.claude/rules/context-engineering.md +202 -0
- package/substrate/.claude/rules/context-management.md +85 -0
- package/substrate/.claude/rules/defensive-bash.md +68 -0
- package/substrate/.claude/rules/deferred-actions.md +233 -0
- package/substrate/.claude/rules/destructive-operations.md +69 -0
- package/substrate/.claude/rules/diagnosis.md +38 -0
- package/substrate/.claude/rules/github-issue-flash-tweet.md +156 -0
- package/substrate/.claude/rules/guardrails.md +73 -0
- package/substrate/.claude/rules/hook-wire-on-author.md +103 -0
- package/substrate/.claude/rules/identifier-leak-prevention.md +104 -0
- package/substrate/.claude/rules/iteration-bet-brief-completeness.md +54 -0
- package/substrate/.claude/rules/lite-manifest-schema-change-discipline.md +98 -0
- package/substrate/.claude/rules/longrun-prep-plan-doc-compression.md +89 -0
- package/substrate/.claude/rules/loop-discipline.md +81 -0
- package/substrate/.claude/rules/manual-prod-approval.md +100 -0
- package/substrate/.claude/rules/marker-enrichment-discipline.md +99 -0
- package/substrate/.claude/rules/mobile-ephemeral-session.md +109 -0
- package/substrate/.claude/rules/new-dependency-check.md +51 -0
- package/substrate/.claude/rules/oo-ad-entry-point.md +117 -0
- package/substrate/.claude/rules/operator-facing-prose.md +196 -0
- package/substrate/.claude/rules/option-label-discipline.md +108 -0
- package/substrate/.claude/rules/pattern-annotation.md +100 -0
- package/substrate/.claude/rules/plain-english-discipline.md +156 -0
- package/substrate/.claude/rules/plan-enumeration-needs-value-props.md +211 -0
- package/substrate/.claude/rules/pr-body-shape.md +317 -0
- package/substrate/.claude/rules/pr-strategy.md +167 -0
- package/substrate/.claude/rules/pr-title-shape.md +161 -0
- package/substrate/.claude/rules/prototype-workflow.md +65 -0
- package/substrate/.claude/rules/reserved-skill-names.md +123 -0
- package/substrate/.claude/rules/schema-management.md +49 -0
- package/substrate/.claude/rules/sdlc-gates.md +149 -0
- package/substrate/.claude/rules/security.md +37 -0
- package/substrate/.claude/rules/session-artifacts.md +236 -0
- package/substrate/.claude/rules/skill-composition-declarations.md +124 -0
- package/substrate/.claude/rules/skill-description-clarity.md +247 -0
- package/substrate/.claude/rules/skill-procedure-step-list.md +137 -0
- package/substrate/.claude/rules/state-schema-validation.md +162 -0
- package/substrate/.claude/rules/stuck-signal-diagnostic.md +140 -0
- package/substrate/.claude/rules/substrate-config-schema.md +98 -0
- package/substrate/.claude/rules/test-list-discipline.md +175 -0
- package/substrate/.claude/rules/test-sufficiency.md +210 -0
- package/substrate/.claude/rules/testing-tier-config.md +145 -0
- package/substrate/.claude/rules/testing.md +38 -0
- package/substrate/.claude/rules/turn-estimate-grounding.md +134 -0
- package/substrate/.claude/rules/visual-hierarchy.md +437 -0
- package/substrate/.claude/rules/we-dont-break-adopters.md +126 -0
- package/substrate/.claude/rules/whereami-load-bearing.md +202 -0
- package/substrate/.claude/rules/writing-craft-discipline.md +92 -0
- package/substrate/.claude/rules/wu-sequencing-compounds.md +145 -0
- package/substrate/.claude/skills/build/SKILL.md +640 -0
- package/substrate/.claude/skills/chronicle/SKILL.md +55 -0
- package/substrate/.claude/skills/clean-artifacts/SKILL.md +249 -0
- package/substrate/.claude/skills/decompose/SKILL.md +280 -0
- package/substrate/.claude/skills/diagnose/SKILL.md +297 -0
- package/substrate/.claude/skills/feynman/SKILL.md +90 -0
- package/substrate/.claude/skills/howdoi/SKILL.md +105 -0
- package/substrate/.claude/skills/ia-model/SKILL.md +108 -0
- package/substrate/.claude/skills/interaction-design/SKILL.md +112 -0
- package/substrate/.claude/skills/interpret-input/SKILL.md +180 -0
- package/substrate/.claude/skills/journal/SKILL.md +209 -0
- package/substrate/.claude/skills/kiss/SKILL.md +449 -0
- package/substrate/.claude/skills/launch/SKILL.md +915 -0
- package/substrate/.claude/skills/lean-canvas/SKILL.md +332 -0
- package/substrate/.claude/skills/longrun/SKILL.md +463 -0
- package/substrate/.claude/skills/luminary/SKILL.md +481 -0
- package/substrate/.claude/skills/ogilvy-writing-audit/SKILL.md +177 -0
- package/substrate/.claude/skills/onboard-repo/SKILL.md +1624 -0
- package/substrate/.claude/skills/pattern-review/SKILL.md +99 -0
- package/substrate/.claude/skills/personas/SKILL.md +207 -0
- package/substrate/.claude/skills/promote/SKILL.md +283 -0
- package/substrate/.claude/skills/requirement/SKILL.md +98 -0
- package/substrate/.claude/skills/retro/SKILL.md +117 -0
- package/substrate/.claude/skills/riff/SKILL.md +114 -0
- package/substrate/.claude/skills/roadmap-reconcile/SKILL.md +163 -0
- package/substrate/.claude/skills/session-end/SKILL.md +309 -0
- package/substrate/.claude/skills/session-log/SKILL.md +299 -0
- package/substrate/.claude/skills/skills/SKILL.md +228 -0
- package/substrate/.claude/skills/spec/SKILL.md +105 -0
- package/substrate/.claude/skills/sprint/SKILL.md +392 -0
- package/substrate/.claude/skills/stage/SKILL.md +384 -0
- package/substrate/.claude/skills/state-a-problem/SKILL.md +185 -0
- package/substrate/.claude/skills/temperance/SKILL.md +108 -0
- package/substrate/.claude/skills/use-case/SKILL.md +417 -0
- package/substrate/.claude/skills/user-stories/SKILL.md +268 -0
- package/substrate/.claude/skills/value-prop/SKILL.md +251 -0
- package/substrate/.claude/skills/verify/SKILL.md +160 -0
- package/substrate/.claude/skills/visual-review/SKILL.md +503 -0
- package/substrate/.claude/skills/whats-the-plan/SKILL.md +202 -0
- package/substrate/.claude/skills/whereami/SKILL.md +307 -0
- package/substrate/AGENTS.md +79 -0
- package/substrate/CLAUDE-lite.md +85 -0
- package/substrate/CODE_OF_CONDUCT.md +28 -0
- package/substrate/CONTRIBUTING.md +177 -0
- package/substrate/README.md +173 -0
- package/substrate/SECURITY.md +19 -0
- package/substrate/architecture/decisions/ADR-029-release-pipeline.md +79 -0
- package/substrate/architecture/decisions/ADR-031-non-breaking-changes-adopter-discipline.md +139 -0
- package/substrate/architecture/decisions/ADR-032-adopter-sync-dispatcher-architecture.md +192 -0
- package/substrate/architecture/decisions/ADR-039-release-tagging-scheme.md +145 -0
- package/substrate/architecture/decisions/ADR-040-planning-skill-vocabulary-and-lite-profile.md +155 -0
- package/substrate/architecture/decisions/ADR-044-unified-skill-body-template.md +162 -0
- package/substrate/lib/clean-artifacts-sweep.sh +112 -0
- package/substrate/lib/code-comment-discipline.sh +144 -0
- package/substrate/lib/composer-preflight.sh +459 -0
- package/substrate/lib/hook-inject.sh +255 -0
- package/substrate/lib/luminary-pick.sh +96 -0
- package/substrate/lib/output-discipline.sh +143 -0
- package/substrate/lib/prose-scan-boundary.sh +171 -0
- package/substrate/lib/rewrite-check.sh +214 -0
- package/substrate/lib/state.sh +1372 -0
- package/substrate/lib/telemetry.sh +205 -0
- package/substrate/lib/tier-check.sh +187 -0
- package/substrate/lib/tier-dependency-audit.sh +1088 -0
- package/substrate/presence/install/bassclef-hook-connect.sh +178 -0
- package/substrate/presence/install/bassclef-sync.dispatcher.template.sh +841 -0
- package/substrate/presence/install/bassclef-sync.template.sh +2076 -0
- package/substrate/presence/install/schedule-auto-save.cron.sh +88 -0
- package/substrate/presence/install/schedule-auto-save.taskscheduler.md +122 -0
- package/substrate/scripts/aggregate-telemetry.sh +217 -0
- package/substrate/scripts/analyze-tier-dependencies.sh +239 -0
- package/substrate/scripts/generate-lite-manifest.sh +505 -0
- package/substrate/scripts/generate-tier-manifest.sh +28 -0
- package/substrate/scripts/intent-drift-check.sh +456 -0
- package/substrate/scripts/lite-manifest-drift-check.sh +146 -0
- package/substrate/scripts/render-lite-manifest-doc.sh +150 -0
- package/substrate/standards/adr-template.md +86 -0
- package/substrate/standards/api-conventions/nextjs.md +84 -0
- package/substrate/standards/artifact-composition.md +209 -0
- package/substrate/standards/bash-hook-safety.md +246 -0
- package/substrate/standards/bassclef-configs-schema.md +232 -0
- package/substrate/standards/bassclef-evolution.md +143 -0
- package/substrate/standards/bassclef-internal-jargon.md +244 -0
- package/substrate/standards/bassclef-managed-sentinel.md +96 -0
- package/substrate/standards/bassclef-source-config.md +228 -0
- package/substrate/standards/branch-stacking.md +408 -0
- package/substrate/standards/code-safety-principles.md +176 -0
- package/substrate/standards/composer-prerequisites.md +155 -0
- package/substrate/standards/deferred-actions-schema.md +204 -0
- package/substrate/standards/dependency-discipline/cargo.md +39 -0
- package/substrate/standards/dependency-discipline/gem.md +43 -0
- package/substrate/standards/dependency-discipline/go-mod.md +41 -0
- package/substrate/standards/dependency-discipline/npm.md +42 -0
- package/substrate/standards/dependency-discipline/pip.md +42 -0
- package/substrate/standards/deployment-topology/ec2-tailscale.md +225 -0
- package/substrate/standards/deployment-topology.md +69 -0
- package/substrate/standards/docs-sync-allowlist.md +76 -0
- package/substrate/standards/domain-and-dns.md +145 -0
- package/substrate/standards/frontend-stack.md +67 -0
- package/substrate/standards/frontmatter-schema.md +154 -0
- package/substrate/standards/graceful-exit.md +227 -0
- package/substrate/standards/hook-idempotency.md +102 -0
- package/substrate/standards/hook-injection-discipline.md +202 -0
- package/substrate/standards/hook-install-class.md +215 -0
- package/substrate/standards/input-handler-interface.md +152 -0
- package/substrate/standards/lite-manifest-schema-changes.md +135 -0
- package/substrate/standards/luminary-matching.md +105 -0
- package/substrate/standards/luminary-problem-patterns.md +481 -0
- package/substrate/standards/migration-discipline/active-record.md +50 -0
- package/substrate/standards/migration-discipline/alembic.md +43 -0
- package/substrate/standards/migration-discipline/gorm.md +50 -0
- package/substrate/standards/migration-discipline/prisma.md +53 -0
- package/substrate/standards/migration-discipline/sqlalchemy.md +51 -0
- package/substrate/standards/mobile-ephemeral-session.md +167 -0
- package/substrate/standards/model-routing-discipline.md +160 -0
- package/substrate/standards/ogilvy-writing-rules.md +225 -0
- package/substrate/standards/opener-discipline.md +96 -0
- package/substrate/standards/operator-facing-prose-discipline.md +201 -0
- package/substrate/standards/persona-schema.md +229 -0
- package/substrate/standards/pluggable-luminaries.md +323 -0
- package/substrate/standards/pr-body-discipline.md +115 -0
- package/substrate/standards/preview-state-schema.md +189 -0
- package/substrate/standards/project-directory-layout.md +276 -0
- package/substrate/standards/release-tagging.md +137 -0
- package/substrate/standards/reserved-skill-names.md +120 -0
- package/substrate/standards/scannable-multi-option-output.md +261 -0
- package/substrate/standards/sdlc-compliance.md +286 -0
- package/substrate/standards/sdlc-gates/typescript.md +57 -0
- package/substrate/standards/secrets-lifecycle.md +210 -0
- package/substrate/standards/security-scanner-adapter.md +145 -0
- package/substrate/standards/session-board.md +256 -0
- package/substrate/standards/skill-output-discipline.md +90 -0
- package/substrate/standards/state-spine-contract.md +255 -0
- package/substrate/standards/state-spine.md +511 -0
- package/substrate/standards/steering-hints/kiss-words.md +11 -0
- package/substrate/standards/substrate-config-schema.md +267 -0
- package/substrate/standards/tech-stack-config.md +109 -0
- package/substrate/standards/tier-dependency-analysis.md +167 -0
- package/substrate/standards/tier-runtime-deps/lite.md +57 -0
- package/substrate/standards/tier-tag-schema.md +155 -0
- package/substrate/standards/two-layer-config.md +99 -0
- package/substrate/standards/use-case-format.md +292 -0
- package/substrate/standards/user-story-invest.md +268 -0
- package/substrate/standards/velocity-and-appetite.md +229 -0
- package/substrate/standards/voice-input-pattern.md +119 -0
- package/substrate/standards/whereami-schema.md +301 -0
- package/substrate/standards/worktree-management.md +211 -0
- package/substrate/standards/writing-guide.md +213 -0
- package/substrate/templates/chronicle-template.md +75 -0
- package/substrate/templates/deferred-action-template.md +45 -0
- package/substrate/templates/memory-proposal-template.md +77 -0
- package/substrate/templates/persona-template.md +200 -0
- package/substrate/templates/pr-faq.md +45 -0
- package/substrate/templates/secret-rotation-template.md +162 -0
- package/substrate/templates/spec-template.md +131 -0
- package/substrate/templates/use-case-template.md +194 -0
- package/substrate/templates/user-story-template.md +107 -0
- package/substrate/templates/whereami-template.md +101 -0
|
@@ -0,0 +1,1624 @@
|
|
|
1
|
+
---
|
|
2
|
+
tier: lite
|
|
3
|
+
name: onboard-repo
|
|
4
|
+
description: "Bootstrap the bassclef framework in a new repo. Installs the sync hook. Scaffolds config, whereami, and CLAUDE.md. Modes: default, --with-deploy-host, --with-secrets, --full, --greenfield-from-intent (cold-adopter magic demo)."
|
|
5
|
+
problem: "Setting up bassclef in a new repo takes an hour of trial. Missing directories and wrong hook wiring."
|
|
6
|
+
value: "One command bootstraps everything \u2014 sync hook and config file and whereami scaffold."
|
|
7
|
+
inputs: [Optional flags — --with-deploy-host or --with-secrets or --full]
|
|
8
|
+
outputs: [Installed bassclef-sync hook, Config scaffold, Whereami stub]
|
|
9
|
+
user_invocable: true
|
|
10
|
+
disable_model_invocation: false
|
|
11
|
+
requires:
|
|
12
|
+
cli: [git, gh]
|
|
13
|
+
network: true
|
|
14
|
+
modes: [default, --with-deploy-host, --with-secrets, --full, --greenfield-from-intent]
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
# /onboard-repo — bassclef substrate adoption for a new repo
|
|
18
|
+
|
|
19
|
+
Brings a repo from "zero bassclef wiring" to "inherits full substrate
|
|
20
|
+
on desktop + mobile" in a single operator-gated session. Distinct from:
|
|
21
|
+
|
|
22
|
+
- `scripts/boot-bassclef.sh` — **machine-level** one-time setup (gh
|
|
23
|
+
auth, service account, launchd). Run once per machine.
|
|
24
|
+
- `/autonomous start` — **session-level** scaffolding (iteration goal,
|
|
25
|
+
phase state, risk register) for a repo that's ALREADY wired into
|
|
26
|
+
bassclef.
|
|
27
|
+
|
|
28
|
+
This skill sits between them: it's **repo-level** substrate adoption.
|
|
29
|
+
Run once per new consumer repo.
|
|
30
|
+
|
|
31
|
+
## When to invoke
|
|
32
|
+
|
|
33
|
+
- Adding a new repo that will use bassclef
|
|
34
|
+
- Re-onboarding a repo that pre-dates the bassclef substrate
|
|
35
|
+
- Refreshing substrate wiring in an existing consumer (idempotent)
|
|
36
|
+
|
|
37
|
+
## Prerequisites (fail fast if missing)
|
|
38
|
+
|
|
39
|
+
Different prereqs apply to Path A (standard onboarding) vs Path B
|
|
40
|
+
(`--greenfield-from-intent` cold-adopter magic demo). Check the path
|
|
41
|
+
the operator picked before validating.
|
|
42
|
+
|
|
43
|
+
### Path A — standard onboarding
|
|
44
|
+
|
|
45
|
+
- `gh` authenticated (`gh auth status`)
|
|
46
|
+
- `claude` resolvable in PATH (`command -v claude`) — required for the
|
|
47
|
+
acceptance test at the end. If missing from a Zellij/tmux subpane,
|
|
48
|
+
move `eval "$(/opt/homebrew/bin/brew shellenv)"` from `~/.zprofile`
|
|
49
|
+
to `~/.zshenv` so non-login shells pick up homebrew's PATH.
|
|
50
|
+
- Target repo exists on GitHub under your org
|
|
51
|
+
- Target repo has a default branch (`main` preferred)
|
|
52
|
+
- Bassclef is cloned as a peer at `$BASSCLEF_DIR` (default `~/src/<your-org>/bassclef`, for
|
|
53
|
+
desktop `additionalDirectories` resolution)
|
|
54
|
+
- You are currently `cd`'d into the target repo's working directory
|
|
55
|
+
- Claude Code session was started with `--add-dir ~/src/sunj-labs/bassclef`
|
|
56
|
+
so this skill file is accessible
|
|
57
|
+
|
|
58
|
+
### Path B — `--greenfield-from-intent` (cold-adopter magic demo)
|
|
59
|
+
|
|
60
|
+
- `claude` resolvable in PATH
|
|
61
|
+
- `git` available
|
|
62
|
+
- `python3` available (for the localhost gallery server)
|
|
63
|
+
- `jq` available (JSON parsing for bassclef-sync + LLM-pick adapter)
|
|
64
|
+
- `curl` available (bassclef-sync fallback + LLM-pick API calls)
|
|
65
|
+
- No separate API key needed. The skill uses whichever LLM your Claude Code session provides. Per the tier reframe (bassclef-web#190 + #193), tier is about catalog size, not credentials.
|
|
66
|
+
- You are currently `cd`'d into an **empty target directory** (or one
|
|
67
|
+
with only files Path B is allowed to overwrite — see "Working
|
|
68
|
+
directory convention" below)
|
|
69
|
+
- `gh` is NOT required (no GitHub repo gets created)
|
|
70
|
+
- A peer bassclef checkout at `~/src/sunj-labs/bassclef` is preferred
|
|
71
|
+
but not required (the thin-pointer dispatcher falls back to the
|
|
72
|
+
GitHub tarball when the sibling is absent — Path B's `Phase B.3`
|
|
73
|
+
installs it)
|
|
74
|
+
|
|
75
|
+
### When prereqs are missing — operator menu
|
|
76
|
+
|
|
77
|
+
If a prereq fails, surface it to the operator and present this menu
|
|
78
|
+
verbatim before stopping:
|
|
79
|
+
|
|
80
|
+
```
|
|
81
|
+
Prerequisite missing for standard onboarding: <name of failed check>.
|
|
82
|
+
|
|
83
|
+
Pick one:
|
|
84
|
+
|
|
85
|
+
1. Cold-adopter magic demo — runs /launch --local, no GitHub repo
|
|
86
|
+
created, no vendor accounts needed. Switches this dispatch to
|
|
87
|
+
--greenfield-from-intent (Path B below). No separate API key
|
|
88
|
+
needed — uses the LLM your Claude Code session provides.
|
|
89
|
+
2. Fix the prereq and re-run standard onboarding (Path A).
|
|
90
|
+
3. Cancel.
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
Operator picks `1` → continue under Path B. Picks `2` → stop and wait
|
|
94
|
+
for the operator to fix + re-dispatch. Picks `3` → stop.
|
|
95
|
+
|
|
96
|
+
Silence is not deferral. Wait for an explicit choice.
|
|
97
|
+
|
|
98
|
+
## Working directory convention
|
|
99
|
+
|
|
100
|
+
| Path | Working directory |
|
|
101
|
+
|---|---|
|
|
102
|
+
| Path A — Phases 1–3 | **target repo** (existing GitHub repo) |
|
|
103
|
+
| Path A — Phase 4 | retired (see Phase 4 note below) |
|
|
104
|
+
| Path B — all phases | **target directory** (typically empty; never leaves it) |
|
|
105
|
+
|
|
106
|
+
For Path A the `pwd` check at the start of each phase exists for a
|
|
107
|
+
reason — don't lose track. Path B runs entirely inside one directory
|
|
108
|
+
and never reaches out to GitHub.
|
|
109
|
+
|
|
110
|
+
## Procedure
|
|
111
|
+
|
|
112
|
+
The Procedure branches at the top into **Path A** (standard
|
|
113
|
+
onboarding) or **Path B** (`--greenfield-from-intent` cold-adopter
|
|
114
|
+
magic demo). Decide first, then walk only the phases under the chosen
|
|
115
|
+
path. Do not mix.
|
|
116
|
+
|
|
117
|
+
### Choosing the path
|
|
118
|
+
|
|
119
|
+
| Signal | Path |
|
|
120
|
+
|---|---|
|
|
121
|
+
| Operator dispatched `/onboard-repo --greenfield-from-intent ...` | B |
|
|
122
|
+
| Operator picked option `1` from the prereqs-missing menu | B |
|
|
123
|
+
| All Path A prereqs pass + no `--greenfield-from-intent` flag | A |
|
|
124
|
+
| Operator dispatched `/onboard-repo --with-deploy-host` / `--with-secrets` / `--full` | A (with Phase 3.5 chained) |
|
|
125
|
+
|
|
126
|
+
When in doubt, ask the operator which path; don't infer.
|
|
127
|
+
|
|
128
|
+
---
|
|
129
|
+
|
|
130
|
+
### Path B — `--greenfield-from-intent` (cold-adopter magic demo)
|
|
131
|
+
|
|
132
|
+
**Working directory: empty.** Never leaves it. No GitHub repo. No vendor accounts touched. The path runs in ≤5 steps using the LLM your Claude Code session provides.
|
|
133
|
+
|
|
134
|
+
The task list the agent generates for Path B MUST be exactly these
|
|
135
|
+
five tasks, in this order. Do not add Phase 1 GitHub work, Phase 1.3
|
|
136
|
+
prod environment, Phase 3.5 follow-on prompts, or Phase 4 matrix PRs.
|
|
137
|
+
Those belong to Path A.
|
|
138
|
+
|
|
139
|
+
#### Phase B.1 — Confirm intent
|
|
140
|
+
|
|
141
|
+
Operator pastes a paragraph or voice transcript describing what they
|
|
142
|
+
want to build (the recipe-test example: "a wiki app for sharing
|
|
143
|
+
recipes with family"). Agent echoes the intent back and asks for
|
|
144
|
+
operator confirmation before continuing. No edits hit disk yet.
|
|
145
|
+
|
|
146
|
+
#### Phase B.2 — Init local git
|
|
147
|
+
|
|
148
|
+
```bash
|
|
149
|
+
git init
|
|
150
|
+
git commit --allow-empty -m "chore: init repo"
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
First empty commit so subsequent file writes have a baseline.
|
|
154
|
+
|
|
155
|
+
#### Phase B.3 — Scaffold the bassclef wiring
|
|
156
|
+
|
|
157
|
+
Subset of Path A Phase 2 — only the files `/launch --local` actually
|
|
158
|
+
reads. Skip everything that needs a remote.
|
|
159
|
+
|
|
160
|
+
```bash
|
|
161
|
+
mkdir -p .claude/hooks docs
|
|
162
|
+
|
|
163
|
+
# Install the thin-pointer dispatcher (same source as Path A Phase 2.1).
|
|
164
|
+
# Sibling-fast-path preferred; the curl fallback works for cold adopters.
|
|
165
|
+
cp ~/src/sunj-labs/bassclef/presence/install/bassclef-sync.dispatcher.template.sh \
|
|
166
|
+
.claude/hooks/bassclef-sync.sh 2>/dev/null \
|
|
167
|
+
|| curl -sL https://raw.githubusercontent.com/sunj-labs/bassclef/main/presence/install/bassclef-sync.dispatcher.template.sh \
|
|
168
|
+
-o .claude/hooks/bassclef-sync.sh
|
|
169
|
+
chmod +x .claude/hooks/bassclef-sync.sh
|
|
170
|
+
|
|
171
|
+
# Minimal settings.json — only the SessionStart hook
|
|
172
|
+
cat > .claude/settings.json <<'JSON'
|
|
173
|
+
{
|
|
174
|
+
"permissions": {
|
|
175
|
+
"additionalDirectories": ["../bassclef"]
|
|
176
|
+
},
|
|
177
|
+
"hooks": {
|
|
178
|
+
"SessionStart": [
|
|
179
|
+
{
|
|
180
|
+
"matcher": "",
|
|
181
|
+
"hooks": [
|
|
182
|
+
{ "type": "command", "command": "$CLAUDE_PROJECT_DIR/.claude/hooks/bassclef-sync.sh", "timeout": 30 }
|
|
183
|
+
]
|
|
184
|
+
}
|
|
185
|
+
]
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
JSON
|
|
189
|
+
|
|
190
|
+
# Minimal substrate.config.md
|
|
191
|
+
cat > substrate.config.md <<'MD'
|
|
192
|
+
# substrate.config.md
|
|
193
|
+
|
|
194
|
+
hosting_platform: none
|
|
195
|
+
deploy_targets:
|
|
196
|
+
prod: false
|
|
197
|
+
budget:
|
|
198
|
+
session_ceiling: $0
|
|
199
|
+
iteration_ceiling: $0
|
|
200
|
+
MD
|
|
201
|
+
|
|
202
|
+
# Minimal .claude/bassclef-configs.jsonc — adopter-default seed (bassclef#1135 WU-4)
|
|
203
|
+
cat > .claude/bassclef-configs.jsonc <<'JSONC'
|
|
204
|
+
// bassclef-configs.jsonc — unified adopter configuration discovery surface.
|
|
205
|
+
// JSON Schema: standards/state-spine/schemas/bassclef-configs.schema.json
|
|
206
|
+
{
|
|
207
|
+
"sync": { "enabled": false },
|
|
208
|
+
"model_tier": {
|
|
209
|
+
"Builder": "balanced",
|
|
210
|
+
"Closer": "cheap-fast",
|
|
211
|
+
"Deployer": "cheap-fast",
|
|
212
|
+
"DocsWriter": "cheap-fast",
|
|
213
|
+
"Explorer": "cheap-fast",
|
|
214
|
+
"Orchestrator": "cheap-fast",
|
|
215
|
+
"Reviewer": "cheap-fast",
|
|
216
|
+
"Shaper": "capable"
|
|
217
|
+
},
|
|
218
|
+
"plan_tier": "tier-1",
|
|
219
|
+
"prose_discipline": { "kiss_words_turn_prose": true },
|
|
220
|
+
"testing": { "global_floor": 1, "path_matchers": [] }
|
|
221
|
+
}
|
|
222
|
+
JSONC
|
|
223
|
+
|
|
224
|
+
# Minimal CLAUDE.md — operator owns this going forward
|
|
225
|
+
cat > CLAUDE.md <<'MD'
|
|
226
|
+
# <repo-name>
|
|
227
|
+
|
|
228
|
+
## What this repo is
|
|
229
|
+
|
|
230
|
+
Cold-adopter magic demo from a stated intent. Substrate inherited from
|
|
231
|
+
bassclef via `--add-dir ../bassclef` or thin-pointer fetch.
|
|
232
|
+
|
|
233
|
+
## Stack
|
|
234
|
+
|
|
235
|
+
To be determined by `/launch --local` output.
|
|
236
|
+
MD
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
Skip in Path B:
|
|
240
|
+
|
|
241
|
+
- `gh repo create` (no remote)
|
|
242
|
+
- Phase 1.1 standard labels (no remote to apply them to)
|
|
243
|
+
- Phase 1.2 branch protection (same)
|
|
244
|
+
- Phase 1.3 prod environment (same)
|
|
245
|
+
- `.bassclef-source.json` (only needed for cloud/mobile sessions
|
|
246
|
+
where the sibling sync isn't available; cold adopters running
|
|
247
|
+
locally don't need it for the magic demo)
|
|
248
|
+
- Phase 3.5 interactive follow-on prompts (no `/provision-deploy-host`,
|
|
249
|
+
no `/secrets-bootstrap` — Path B has no vendor surfaces to bind)
|
|
250
|
+
|
|
251
|
+
#### Phase B.4 — Dispatch `/launch --local --voice-input`
|
|
252
|
+
|
|
253
|
+
Hand the intent paragraph straight to `/launch`:
|
|
254
|
+
|
|
255
|
+
```
|
|
256
|
+
/launch medium --local --voice-input "<intent paragraph from Phase B.1>"
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
Path B's last action is this dispatch. Do not chain `/build` or
|
|
260
|
+
`/launch-preview` afterward — those belong to the extended path for
|
|
261
|
+
operators with vendor bindings.
|
|
262
|
+
|
|
263
|
+
#### Phase B.5 — `/launch --local` runs
|
|
264
|
+
|
|
265
|
+
`/launch` writes the full artifact chain to disk (input-artifact, spec,
|
|
266
|
+
prototypes gallery, user stories, decomposition, migration plan) and
|
|
267
|
+
serves the gallery on `localhost:8000+`. The localhost URL is the
|
|
268
|
+
deliverable. Operator inspects, picks a direction, and either keeps
|
|
269
|
+
iterating locally or moves to standard onboarding (Path A) when they're
|
|
270
|
+
ready to push to a GitHub repo.
|
|
271
|
+
|
|
272
|
+
When `/launch --local` returns, Path B is done. Skip everything below
|
|
273
|
+
this divider.
|
|
274
|
+
|
|
275
|
+
---
|
|
276
|
+
|
|
277
|
+
### Path A — standard onboarding
|
|
278
|
+
|
|
279
|
+
Run each phase in order. Operator confirms before destructive or
|
|
280
|
+
cross-repo actions. Each phase is independently re-runnable.
|
|
281
|
+
|
|
282
|
+
#### Phase 0 — Refuse to run from main
|
|
283
|
+
|
|
284
|
+
Substrate changes go through PRs, same as feature work. If `/onboard-repo`
|
|
285
|
+
runs from `main`, every scaffold (`.claude/`, `CLAUDE.md`,
|
|
286
|
+
`docs/whereami.md`, `substrate.config.md`, `.bassclef-source.json`,
|
|
287
|
+
`.gitignore`) lands as a direct-to-main commit by surprise. Path A
|
|
288
|
+
refuses that shape and prints the remediation:
|
|
289
|
+
|
|
290
|
+
```bash
|
|
291
|
+
CURRENT_BRANCH=$(git branch --show-current 2>/dev/null || echo "")
|
|
292
|
+
|
|
293
|
+
case "$CURRENT_BRANCH" in
|
|
294
|
+
main|master)
|
|
295
|
+
cat >&2 <<'EOF'
|
|
296
|
+
|
|
297
|
+
🛑 /onboard-repo refuses to run from main.
|
|
298
|
+
|
|
299
|
+
Why: substrate scaffolding (`.claude/`, `CLAUDE.md`, `docs/whereami.md`,
|
|
300
|
+
`substrate.config.md`, `.bassclef-source.json`, `.gitignore`) is a
|
|
301
|
+
substrate change — it goes through a PR, not a direct commit to main.
|
|
302
|
+
|
|
303
|
+
Remediation:
|
|
304
|
+
|
|
305
|
+
git checkout -b chore/bassclef-bootstrap
|
|
306
|
+
# re-run /onboard-repo
|
|
307
|
+
|
|
308
|
+
When you reach the end of Phase 3, /onboard-repo will guide you to
|
|
309
|
+
open the bootstrap PR; merging it lands the substrate on main with
|
|
310
|
+
audit history (this is flywheel turn 1 from the first-use sequence —
|
|
311
|
+
see docs/first-use-sequence.md).
|
|
312
|
+
|
|
313
|
+
V1 (bassclef#956 follow-up) will auto-create the branch + PR. V0.5
|
|
314
|
+
keeps the operator in the loop on the branching decision.
|
|
315
|
+
|
|
316
|
+
EOF
|
|
317
|
+
exit 1
|
|
318
|
+
;;
|
|
319
|
+
"")
|
|
320
|
+
cat >&2 <<'EOF'
|
|
321
|
+
|
|
322
|
+
🛑 /onboard-repo cannot detect the current git branch.
|
|
323
|
+
|
|
324
|
+
The cwd may not be a git repository, OR git is in a detached-HEAD state.
|
|
325
|
+
|
|
326
|
+
Remediation:
|
|
327
|
+
|
|
328
|
+
git init # if not a git repo
|
|
329
|
+
git checkout -b chore/bassclef-bootstrap # from a fresh branch
|
|
330
|
+
# re-run /onboard-repo
|
|
331
|
+
|
|
332
|
+
EOF
|
|
333
|
+
exit 1
|
|
334
|
+
;;
|
|
335
|
+
*)
|
|
336
|
+
# Any other branch — proceed
|
|
337
|
+
;;
|
|
338
|
+
esac
|
|
339
|
+
```
|
|
340
|
+
|
|
341
|
+
The remediation message is the contract. If a cold adopter dispatches
|
|
342
|
+
`/onboard-repo` from `main`, they see exactly what to do — no operator
|
|
343
|
+
coaching, no second-guess. V0.5 ships in bassclef#956; V1
|
|
344
|
+
(auto-create branch + PR) is post-launch hardening per the goal's
|
|
345
|
+
operator-decision items.
|
|
346
|
+
|
|
347
|
+
#### Phase 1 — Set up the GitHub repo (labels, branch protection)
|
|
348
|
+
|
|
349
|
+
**Working directory: target repo** (`pwd` should match `gh repo view --json name -q .name`).
|
|
350
|
+
|
|
351
|
+
Idempotent API calls against the target repo via `gh`.
|
|
352
|
+
|
|
353
|
+
##### 1.1 Create the 11 standard labels
|
|
354
|
+
|
|
355
|
+
```bash
|
|
356
|
+
# Read from git remote — don't infer from cwd basename (cwd can be renamed)
|
|
357
|
+
REPO=$(gh repo view --json nameWithOwner -q .nameWithOwner)
|
|
358
|
+
|
|
359
|
+
declare -A LABELS=(
|
|
360
|
+
[bassclef-evolution]="A6E0F2:Candidate for promotion to bassclef"
|
|
361
|
+
[agent-user-proposed]="D4A5F5:Proposed by agent in an app repo"
|
|
362
|
+
[bassclef-sync]="8FD4A4:Related to bassclef substrate syncing"
|
|
363
|
+
[review-required]="F5B94A:Blocks — human review required"
|
|
364
|
+
[bug]="E4443A:Defect"
|
|
365
|
+
[enhancement]="A2EEEF:New or improved functionality"
|
|
366
|
+
[security]="FF0000:Security-relevant"
|
|
367
|
+
[infra]="C9D1D9:Infrastructure / workflows / tooling"
|
|
368
|
+
[priority-high]="E4443A:High priority"
|
|
369
|
+
[priority-medium]="F5B94A:Medium priority"
|
|
370
|
+
[question]="D876E3:Needs operator input or design discussion"
|
|
371
|
+
)
|
|
372
|
+
|
|
373
|
+
for NAME in "${!LABELS[@]}"; do
|
|
374
|
+
COLOR="${LABELS[$NAME]%%:*}"
|
|
375
|
+
DESC="${LABELS[$NAME]#*:}"
|
|
376
|
+
gh label create "$NAME" --repo "$REPO" --color "$COLOR" --description "$DESC" --force >/dev/null
|
|
377
|
+
done
|
|
378
|
+
```
|
|
379
|
+
|
|
380
|
+
Uses `--force` so the call is idempotent (updates existing label or
|
|
381
|
+
creates new). This matches the bootstrap logic shipped in bassclef
|
|
382
|
+
#160 (sync hook does the same for `bassclef-evolution` + `agent-user-proposed`);
|
|
383
|
+
this phase adds the broader set up-front so the operator can label issues
|
|
384
|
+
immediately without waiting for a sync cycle.
|
|
385
|
+
|
|
386
|
+
##### 1.2 Protect main from force-push and deletion
|
|
387
|
+
|
|
388
|
+
```bash
|
|
389
|
+
DEFAULT_BRANCH=$(gh repo view "$REPO" --json defaultBranchRef -q '.defaultBranchRef.name')
|
|
390
|
+
|
|
391
|
+
gh api "repos/$REPO/branches/$DEFAULT_BRANCH/protection" \
|
|
392
|
+
--method PUT \
|
|
393
|
+
--input - <<EOF
|
|
394
|
+
{
|
|
395
|
+
"required_status_checks": null,
|
|
396
|
+
"enforce_admins": false,
|
|
397
|
+
"required_pull_request_reviews": null,
|
|
398
|
+
"restrictions": null,
|
|
399
|
+
"allow_force_pushes": false,
|
|
400
|
+
"allow_deletions": false
|
|
401
|
+
}
|
|
402
|
+
EOF
|
|
403
|
+
```
|
|
404
|
+
|
|
405
|
+
Minimum defense: no force-push or deletion of main. PR reviews NOT
|
|
406
|
+
required here — agent-created PRs (bassclef-sync) need to merge
|
|
407
|
+
without human intervention for the mobile-sync story. Add stricter
|
|
408
|
+
rules per-repo in `.github/branch-protection.yml` if the repo warrants.
|
|
409
|
+
|
|
410
|
+
##### 1.3 Add the production approval gate (if this repo deploys to prod)
|
|
411
|
+
|
|
412
|
+
If the repo will deploy to production, per `manual-prod-approval.md`:
|
|
413
|
+
|
|
414
|
+
```bash
|
|
415
|
+
# Prompt operator: "Does this repo deploy to prod? [y/N]"
|
|
416
|
+
# If yes:
|
|
417
|
+
USER_ID=$(gh api user --jq '.id')
|
|
418
|
+
gh api "repos/$REPO/environments/prod" --method PUT \
|
|
419
|
+
-f "wait_timer=0" \
|
|
420
|
+
-f "deployment_branch_policy[protected_branches]=false" \
|
|
421
|
+
-f "deployment_branch_policy[custom_branch_policies]=true"
|
|
422
|
+
|
|
423
|
+
gh api "repos/$REPO/environments/prod" --method PUT \
|
|
424
|
+
-F "reviewers[][type]=User" \
|
|
425
|
+
-F "reviewers[][id]=$USER_ID"
|
|
426
|
+
```
|
|
427
|
+
|
|
428
|
+
Skip if repo is docs-only (like bassclef itself) or doesn't have a
|
|
429
|
+
production deploy target.
|
|
430
|
+
|
|
431
|
+
#### Phase 2 — Install bassclef wiring (settings, sync script, config)
|
|
432
|
+
|
|
433
|
+
**Working directory: target repo.** All file writes happen here.
|
|
434
|
+
|
|
435
|
+
##### 2.1 Install the auto-update script (off by default per bassclef#939)
|
|
436
|
+
|
|
437
|
+
```bash
|
|
438
|
+
mkdir -p .claude/hooks
|
|
439
|
+
|
|
440
|
+
# Install thin-pointer dispatcher from bassclef's own template directory.
|
|
441
|
+
# This is the source-of-truth file consumers vendor.
|
|
442
|
+
cp ~/src/sunj-labs/bassclef/presence/install/bassclef-sync.dispatcher.template.sh \
|
|
443
|
+
.claude/hooks/bassclef-sync.sh
|
|
444
|
+
|
|
445
|
+
# OR — if bassclef isn't checked out alongside this repo, fetch from
|
|
446
|
+
# bassclef's main branch on GitHub (public tarball release works too
|
|
447
|
+
# once bassclef itself goes public):
|
|
448
|
+
# curl -sL https://raw.githubusercontent.com/sunj-labs/bassclef/main/presence/install/bassclef-sync.dispatcher.template.sh \
|
|
449
|
+
# -o .claude/hooks/bassclef-sync.sh
|
|
450
|
+
|
|
451
|
+
chmod +x .claude/hooks/bassclef-sync.sh
|
|
452
|
+
|
|
453
|
+
# Verify the version header reads `thin-pointer-2026-05-15` or later:
|
|
454
|
+
head -2 .claude/hooks/bassclef-sync.sh
|
|
455
|
+
```
|
|
456
|
+
|
|
457
|
+
The thin-pointer dispatcher does NOT vendor bassclef's sync logic.
|
|
458
|
+
It reads `.bassclef-source.json` (Phase 2.4) for the upstream tarball
|
|
459
|
+
URL + auth, fetches it, and execs the included template — always-current.
|
|
460
|
+
Eliminates two prior patching layers: hook content drift (vendored
|
|
461
|
+
template diverging from bassclef's) and URL refresh ceremony.
|
|
462
|
+
|
|
463
|
+
When the dispatcher can't load the substrate (sibling missing AND curl
|
|
464
|
+
fallback unconfigured / unauthenticated), it prints a plain-language
|
|
465
|
+
explanation with three resolution paths (public adopter, local dev,
|
|
466
|
+
private fork). External adopters get actionable guidance instead of
|
|
467
|
+
internal-vocabulary errors. Closes the adoption-friendliness gap noted
|
|
468
|
+
in bassclef#715.
|
|
469
|
+
|
|
470
|
+
##### 2.2 Configure Claude Code for this repo
|
|
471
|
+
|
|
472
|
+
Standard bassclef settings — SessionStart → `bassclef-sync.sh`, +
|
|
473
|
+
other hooks per-agent configuration. Copy from a reference consumer
|
|
474
|
+
(POA or ops) and scrub for repo-specific paths:
|
|
475
|
+
|
|
476
|
+
```bash
|
|
477
|
+
cat > .claude/settings.json <<'JSON'
|
|
478
|
+
{
|
|
479
|
+
"permissions": {
|
|
480
|
+
"additionalDirectories": ["../bassclef"]
|
|
481
|
+
},
|
|
482
|
+
"hooks": {
|
|
483
|
+
"SessionStart": [
|
|
484
|
+
{
|
|
485
|
+
"matcher": "",
|
|
486
|
+
"hooks": [
|
|
487
|
+
{ "type": "command", "command": "$CLAUDE_PROJECT_DIR/.claude/hooks/bassclef-sync.sh", "timeout": 30 }
|
|
488
|
+
]
|
|
489
|
+
}
|
|
490
|
+
]
|
|
491
|
+
}
|
|
492
|
+
}
|
|
493
|
+
JSON
|
|
494
|
+
```
|
|
495
|
+
|
|
496
|
+
Operator confirms — may want to add app-specific hooks (pre-build-gate,
|
|
497
|
+
pre-commit-gate) if the repo has source code.
|
|
498
|
+
|
|
499
|
+
##### 2.2.1 Wire all Phase 2.2 hooks (13 hooks in one pass)
|
|
500
|
+
|
|
501
|
+
Phase 2.2 wires 13 bassclef hooks that gate adopter writes, commits, sessions, and role transitions. Read the whole table first. Then apply the canonical jq recipe. Then run the 3 verify blocks.
|
|
502
|
+
|
|
503
|
+
**Lite adopter note** (bassclef#740 Task 1.2). 6 hooks ship at `tier: standard` and skip on lite. Resolve tier via `lib/tier-check.sh`. The table marks each standard-tier hook with `std`. The bassclef-lite tarball does not carry those 6.
|
|
504
|
+
|
|
505
|
+
**Symlink all hooks in one pass:**
|
|
506
|
+
|
|
507
|
+
```bash
|
|
508
|
+
mkdir -p .claude/hooks
|
|
509
|
+
cd .claude/hooks
|
|
510
|
+
for h in turn-prose-kiss-check substrate-clarity-gate artifact-ingestion-gate \
|
|
511
|
+
pattern-annotation-validate pre-commit-gate state-validate \
|
|
512
|
+
destructive-command-guard multi-tenancy-check atomic-pr-check \
|
|
513
|
+
post-write-trace testing-tier-enforce role-entry-gate temperance-gate; do
|
|
514
|
+
ln -sf "../../../bassclef/.claude/hooks/${h}.sh" "${h}.sh"
|
|
515
|
+
done
|
|
516
|
+
# Two allowlist files paired with hooks that read them:
|
|
517
|
+
ln -sf "../../../bassclef/.claude/hooks/substrate-clarity-allowlist.txt" substrate-clarity-allowlist.txt
|
|
518
|
+
ln -sf "../../../bassclef/.claude/hooks/testing-tier-enforce-allowlist.txt" testing-tier-enforce-allowlist.txt
|
|
519
|
+
cd -
|
|
520
|
+
```
|
|
521
|
+
|
|
522
|
+
**Hook table:**
|
|
523
|
+
|
|
524
|
+
| # | Hook | Event | Matcher | Tier | Notes |
|
|
525
|
+
|---|---|---|---|---|---|
|
|
526
|
+
| 1 | turn-prose-kiss-check | Stop | (empty) | lite | Reads `prose_discipline.kiss_words_turn_prose` toggle from bassclef-configs; short-circuits when false; timeout 10s |
|
|
527
|
+
| 2 | substrate-clarity-gate | PreToolUse | Edit\|Write | lite | Reads bassclef baseline allowlist + optional adopter-side `substrate-clarity-allowlist-adopter.txt` |
|
|
528
|
+
| 3 | artifact-ingestion-gate | PreToolUse | Write | lite | Reads `artifact_ingestion.paths` from bassclef-configs; 13 default paths seeded by Phase 2.3.5 |
|
|
529
|
+
| 4 | pattern-annotation-validate | PreToolUse | Edit\|Write\|MultiEdit | std | Reads `tech_stack.lang` for language scoping (Phase 2.3.6) |
|
|
530
|
+
| 5 | pre-commit-gate | PreToolUse | Edit\|Write\|MultiEdit | lite | Runs first; composes testing-tier-enforce internally as one of its check steps |
|
|
531
|
+
| 6 | state-validate | PreToolUse | Edit\|Write\|MultiEdit | lite | Runs after pre-commit-gate; heavier ajv-cli schema check |
|
|
532
|
+
| 7 | destructive-command-guard | PreToolUse | Bash | std | Catches destructive verbs + force flags + amplifiers (rm -rf, FLUSHALL, prisma migrate reset) |
|
|
533
|
+
| 8 | multi-tenancy-check | PreToolUse | Edit\|Write\|MultiEdit | std | Template — customize via `TENANT_MODELS` / `TENANT_CONTEXT_FN` / `TENANT_PARAMS_FN` env vars |
|
|
534
|
+
| 9 | atomic-pr-check | PreToolUse | Bash | std | Fires on `git push` patterns; BLOCKs multi-step branches lacking `bundle: true` in goal frontmatter |
|
|
535
|
+
| 10 | post-write-trace | PostToolUse | Write\|Edit | std | Append-only trace; no override (never blocks) |
|
|
536
|
+
| 11 | testing-tier-enforce | (composed) | (via pre-commit-gate) | lite | Fires inside pre-commit-gate; no separate matcher entry; 60-day allowlist grace |
|
|
537
|
+
| 12 | role-entry-gate | PreToolUse | Edit\|Write\|MultiEdit | std | MVP: source-code file extensions only; reads `state/markers/role/<role>/<session>.marker` |
|
|
538
|
+
| 13 | temperance-gate | PreToolUse | Edit\|Write\|MultiEdit | lite | Fires on high-impact edits (.claude/, standards/, lib/state.sh, SKILL.md) when temperance marker missing |
|
|
539
|
+
|
|
540
|
+
**Order matters within each matcher block.** Place `pre-commit-gate` before `state-validate` (cheap SDLC checks fire first; heavier schema check runs second). Place `role-entry-gate` and `temperance-gate` LAST — methodology gates fire after structural + format + state checks pass.
|
|
541
|
+
|
|
542
|
+
**Canonical jq recipe — write settings.json in one pass.** The recipe uses JSON literal syntax so the `"matcher": "..."` and `"command": "..."` keys land verbatim in `.claude/settings.json` for grep-verifiability:
|
|
543
|
+
|
|
544
|
+
```bash
|
|
545
|
+
# Assumes .claude/settings.json exists from Phase 2.2 (bare SessionStart entry).
|
|
546
|
+
# Reads adopter tier and skips standard-tier hooks on lite.
|
|
547
|
+
TIER=$(bash ../bassclef/lib/tier-check.sh 2>/dev/null || echo lite)
|
|
548
|
+
|
|
549
|
+
# Lite tier — 7 hooks land in .claude/settings.json (rows 1,2,3,5,6,11,13).
|
|
550
|
+
# Standard/ultra tier — all 13 hooks land in .claude/settings.json.
|
|
551
|
+
jq --arg tier "$TIER" '
|
|
552
|
+
.hooks.Stop = ((.hooks.Stop // []) + [
|
|
553
|
+
{ "matcher": "", "hooks": [
|
|
554
|
+
{ "type": "command", "command": "$CLAUDE_PROJECT_DIR/.claude/hooks/turn-prose-kiss-check.sh", "timeout": 10 }
|
|
555
|
+
]}
|
|
556
|
+
]) |
|
|
557
|
+
.hooks.PreToolUse = ((.hooks.PreToolUse // []) + [
|
|
558
|
+
{ "matcher": "Edit|Write|MultiEdit", "hooks": (
|
|
559
|
+
[
|
|
560
|
+
{ "type": "command", "command": "$CLAUDE_PROJECT_DIR/.claude/hooks/substrate-clarity-gate.sh" },
|
|
561
|
+
{ "type": "command", "command": "$CLAUDE_PROJECT_DIR/.claude/hooks/pre-commit-gate.sh" },
|
|
562
|
+
{ "type": "command", "command": "$CLAUDE_PROJECT_DIR/.claude/hooks/state-validate.sh" },
|
|
563
|
+
{ "type": "command", "command": "$CLAUDE_PROJECT_DIR/.claude/hooks/temperance-gate.sh" }
|
|
564
|
+
] +
|
|
565
|
+
(if $tier != "lite" then [
|
|
566
|
+
{ "type": "command", "command": "$CLAUDE_PROJECT_DIR/.claude/hooks/pattern-annotation-validate.sh" },
|
|
567
|
+
{ "type": "command", "command": "$CLAUDE_PROJECT_DIR/.claude/hooks/multi-tenancy-check.sh" },
|
|
568
|
+
{ "type": "command", "command": "$CLAUDE_PROJECT_DIR/.claude/hooks/role-entry-gate.sh" }
|
|
569
|
+
] else [] end)
|
|
570
|
+
)},
|
|
571
|
+
{ "matcher": "Write", "hooks": [
|
|
572
|
+
{ "type": "command", "command": "$CLAUDE_PROJECT_DIR/.claude/hooks/artifact-ingestion-gate.sh" }
|
|
573
|
+
]}
|
|
574
|
+
] + (if $tier != "lite" then [
|
|
575
|
+
{ "matcher": "Bash", "hooks": [
|
|
576
|
+
{ "type": "command", "command": "$CLAUDE_PROJECT_DIR/.claude/hooks/destructive-command-guard.sh" },
|
|
577
|
+
{ "type": "command", "command": "$CLAUDE_PROJECT_DIR/.claude/hooks/atomic-pr-check.sh" }
|
|
578
|
+
]}
|
|
579
|
+
] else [] end)) |
|
|
580
|
+
(if $tier != "lite" then
|
|
581
|
+
.hooks.PostToolUse = ((.hooks.PostToolUse // []) + [
|
|
582
|
+
{ "matcher": "Write|Edit", "hooks": [
|
|
583
|
+
{ "type": "command", "command": "$CLAUDE_PROJECT_DIR/.claude/hooks/post-write-trace.sh" }
|
|
584
|
+
]}
|
|
585
|
+
])
|
|
586
|
+
else . end)
|
|
587
|
+
' .claude/settings.json > .claude/settings.json.tmp \
|
|
588
|
+
&& mv .claude/settings.json.tmp .claude/settings.json
|
|
589
|
+
```
|
|
590
|
+
|
|
591
|
+
**Alternate matcher notes.** The `"matcher": "Edit|Write"` shape (without MultiEdit) appears in older adopter settings.json — the widening to `"matcher": "Edit|Write|MultiEdit"` in this recipe covers MultiEdit for hooks that need it.
|
|
592
|
+
|
|
593
|
+
**On re-run against existing settings.json** — jq's `+=` appends. Duplicate matcher entries are safe (Claude Code processes all in order), but the cleaner shape merges hooks under one matcher. To dedupe a re-run, strip existing entries with `jq 'del(...)'` before appending.
|
|
594
|
+
|
|
595
|
+
**Verify block 1 — Stop event:**
|
|
596
|
+
|
|
597
|
+
```bash
|
|
598
|
+
python3 -c "import json; d=json.load(open('.claude/settings.json')); \
|
|
599
|
+
hooks=[h.get('command','') for entry in d.get('hooks',{}).get('Stop',[]) for h in entry.get('hooks',[])]; \
|
|
600
|
+
print('turn-prose-kiss-check wired' if any('turn-prose-kiss-check' in c for c in hooks) else 'NOT wired')"
|
|
601
|
+
```
|
|
602
|
+
|
|
603
|
+
**Verify block 2 — PreToolUse event (all matchers):**
|
|
604
|
+
|
|
605
|
+
```bash
|
|
606
|
+
python3 -c "import json; d=json.load(open('.claude/settings.json')); \
|
|
607
|
+
cmds=[h.get('command','') for entry in d.get('hooks',{}).get('PreToolUse',[]) for h in entry.get('hooks',[])]; \
|
|
608
|
+
hooks=['substrate-clarity-gate','artifact-ingestion-gate','pre-commit-gate','state-validate','temperance-gate','pattern-annotation-validate','destructive-command-guard','multi-tenancy-check','atomic-pr-check','role-entry-gate']; \
|
|
609
|
+
[print(f'{h}: {\"wired\" if any(h in c for c in cmds) else \"NOT wired\"}') for h in hooks]"
|
|
610
|
+
```
|
|
611
|
+
|
|
612
|
+
**Verify block 3 — PostToolUse event:**
|
|
613
|
+
|
|
614
|
+
```bash
|
|
615
|
+
python3 -c "import json; d=json.load(open('.claude/settings.json')); \
|
|
616
|
+
cmds=[h.get('command','') for entry in d.get('hooks',{}).get('PostToolUse',[]) for h in entry.get('hooks',[])]; \
|
|
617
|
+
print('post-write-trace wired' if any('post-write-trace' in c for c in cmds) else 'NOT wired')"
|
|
618
|
+
```
|
|
619
|
+
|
|
620
|
+
**Rule propagation** — 8 rules load into the adopter session on their own via the `additionalDirectories: ["../bassclef"]` entry Phase 2.2 wrote. No per-rule symlink needed. Rules: `sdlc-gates.md`, `state-schema-validation.md`, `testing-tier-config.md`, `test-list-discipline.md`, `test-sufficiency.md`, `destructive-operations.md`, `pattern-annotation.md`, `pr-strategy.md`. Verify with:
|
|
621
|
+
|
|
622
|
+
```bash
|
|
623
|
+
for r in sdlc-gates state-schema-validation testing-tier-config test-list-discipline \
|
|
624
|
+
test-sufficiency destructive-operations pattern-annotation pr-strategy; do
|
|
625
|
+
test -f ../bassclef/.claude/rules/${r}.md && echo "${r} reachable" || echo "${r} NOT reachable"
|
|
626
|
+
done
|
|
627
|
+
```
|
|
628
|
+
|
|
629
|
+
**Composed hook: testing-tier-enforce** — Row 11 fires inside `.claude/hooks/pre-commit-gate.sh` as one of its check steps (no separate matcher entry in `.claude/settings.json`). The symlink at `.claude/hooks/testing-tier-enforce.sh` + the allowlist at `.claude/hooks/testing-tier-enforce-allowlist.txt` are enough; the enforcer runs whenever pre-commit-gate fires (PreToolUse Edit|Write|MultiEdit). Grace window: 60 days on the allowlist baseline. When an adopter edits a Tier 0 source file without touching its matching test file, pre-commit-gate calls `.claude/hooks/testing-tier-enforce.sh` and the commit BLOCKs with a structured stderr message.
|
|
630
|
+
|
|
631
|
+
Sanity check that the hook is reachable and composed into pre-commit-gate:
|
|
632
|
+
|
|
633
|
+
```bash
|
|
634
|
+
ls -l .claude/hooks/testing-tier-enforce.sh .claude/hooks/testing-tier-enforce-allowlist.txt
|
|
635
|
+
grep -q "testing-tier-enforce.sh" .claude/hooks/pre-commit-gate.sh \
|
|
636
|
+
&& echo "tier-enforce composed in pre-commit-gate" \
|
|
637
|
+
|| echo "NOT composed (pre-commit-gate may be stale; re-run bassclef-sync)"
|
|
638
|
+
```
|
|
639
|
+
|
|
640
|
+
**Override paths** — each hook honors a `SKIP_*` env var (logged via trace-helper per bassclef override idiom). Use only for one-shot migrations or emergency rescue:
|
|
641
|
+
|
|
642
|
+
| Hook | Override |
|
|
643
|
+
|---|---|
|
|
644
|
+
| turn-prose-kiss-check | (toggle via `prose_discipline.kiss_words_turn_prose: false` in bassclef-configs) |
|
|
645
|
+
| substrate-clarity-gate | `SKIP_SUBSTRATE_CLARITY=1` |
|
|
646
|
+
| artifact-ingestion-gate | `SKIP_ARTIFACT_INGESTION=1` |
|
|
647
|
+
| pattern-annotation-validate | `SKIP_PATTERN_ANNOTATION=1` |
|
|
648
|
+
| pre-commit-gate | `SKIP_PRE_COMMIT_GATE=1` |
|
|
649
|
+
| state-validate | `SKIP_STATE_VALIDATE=1` |
|
|
650
|
+
| destructive-command-guard | `SKIP_DESTRUCTIVE_GUARD=1` |
|
|
651
|
+
| multi-tenancy-check | `SKIP_MULTI_TENANCY_CHECK=1` |
|
|
652
|
+
| atomic-pr-check | `SKIP_ATOMIC_PR_CHECK=1` |
|
|
653
|
+
| post-write-trace | (none — append-only trace never blocks) |
|
|
654
|
+
| testing-tier-enforce | `SKIP_TESTING_TIER_ENFORCE=1` |
|
|
655
|
+
| role-entry-gate | `SKIP_ROLE_ENTRY=1` |
|
|
656
|
+
| temperance-gate | `SKIP_TEMPERANCE_GATE=1` |
|
|
657
|
+
|
|
658
|
+
**Not yet wired in bassclef** — `role-entry-gate` and `temperance-gate` ship to adopters first. Bassclef's own settings.json adds them in a follow-on after the marker convention runs in the wild for a few sessions and the multi-role + trigger-taxonomy follow-ons land.
|
|
659
|
+
|
|
660
|
+
Source: bassclef#1136 T3 (pre-commit-gate + state-validate), bassclef#1137 T4 (substrate-clarity-gate), bassclef#1138 T5 (turn-prose-kiss-check), bassclef#1139 T6 (pattern-annotation-validate), bassclef#1140 T7 (artifact-ingestion-gate), bassclef#1141 T8 (destructive-command-guard + multi-tenancy-check), bassclef#1142 T9 (atomic-pr-check + post-write-trace), bassclef#1143 T10 (testing-tier-enforce), bassclef#1144 T11 (test-discipline rule propagation), bassclef#1145 T13 (role-entry-gate), bassclef#1147 T15 (temperance-gate). Follow-ons deferred: `operator-private-path-check`, `type-check`, `post-skill-friction-check`, `role-entry` skill, multi-role matcher matrix, `standards/temperance-discipline.md`.
|
|
661
|
+
|
|
662
|
+
##### 2.3 Create the project config file
|
|
663
|
+
|
|
664
|
+
Copy from `presence/install/substrate-config.md`, then prompt operator
|
|
665
|
+
for:
|
|
666
|
+
|
|
667
|
+
- `journal_doc_id` (optional — create Google Doc now or later)
|
|
668
|
+
- `changelog_doc_id` (optional)
|
|
669
|
+
- `deploy_targets` (local/staging/prod booleans)
|
|
670
|
+
- `budget.session_ceiling` / `iteration_ceiling` (sequential mode → `$0`)
|
|
671
|
+
- `hosting_platform` (REQUIRED for any consumer that ships a UI). Default
|
|
672
|
+
to `amplify` per ADR-008 + app-consumer precedent. Set `none` for
|
|
673
|
+
docs-only / no-UI repos. Enum:
|
|
674
|
+
`amplify | ec2-tailscale | vercel | netlify | cloudflare-pages | none`.
|
|
675
|
+
`/bind-subdomain` + `/launch-preview` refuse on `none` unless
|
|
676
|
+
`BIND_SUBDOMAIN_OVERRIDE=1` is set. Closes bassclef#449.
|
|
677
|
+
|
|
678
|
+
If operator says "defer", scaffold with placeholders and `TODO:` markers
|
|
679
|
+
so next session surfaces them.
|
|
680
|
+
|
|
681
|
+
##### 2.3.5 Write the bassclef-configs adopter-default seed
|
|
682
|
+
|
|
683
|
+
Write `.claude/bassclef-configs.jsonc` with the adopter-default seed.
|
|
684
|
+
Every downstream hook + skill reads from this file; without it, defaults
|
|
685
|
+
are invisible to the adopter. Phase 2.5 (security_scanning) appends to
|
|
686
|
+
this file later in the same Procedure run, so the foundation MUST land
|
|
687
|
+
first.
|
|
688
|
+
|
|
689
|
+
```bash
|
|
690
|
+
cat > .claude/bassclef-configs.jsonc <<'JSONC'
|
|
691
|
+
// bassclef-configs.jsonc — unified adopter configuration discovery surface
|
|
692
|
+
//
|
|
693
|
+
// Edit the values below. Each block has a comment explaining what it does,
|
|
694
|
+
// what the default is, and which bassclef substrate component reads it.
|
|
695
|
+
//
|
|
696
|
+
// JSON Schema: standards/state-spine/schemas/bassclef-configs.schema.json
|
|
697
|
+
// Full reference: standards/bassclef-configs-schema.md
|
|
698
|
+
{
|
|
699
|
+
// Whether bassclef's substrate syncs from upstream at SessionStart.
|
|
700
|
+
// Adopter default: false (opt-in trust posture). Turn on when you want
|
|
701
|
+
// bassclef to keep itself current automatically.
|
|
702
|
+
// Pairs with: .claude/hooks/bassclef-sync.sh
|
|
703
|
+
"sync": { "enabled": false },
|
|
704
|
+
|
|
705
|
+
// Per-agent LLM model routing. Most agents stay cheap-fast; Builder
|
|
706
|
+
// gets balanced for code quality; Shaper gets capable for problem framing.
|
|
707
|
+
// Pairs with: .claude/agents/<role>.md frontmatter
|
|
708
|
+
"model_tier": {
|
|
709
|
+
"Builder": "balanced",
|
|
710
|
+
"Closer": "cheap-fast",
|
|
711
|
+
"Deployer": "cheap-fast",
|
|
712
|
+
"DocsWriter": "cheap-fast",
|
|
713
|
+
"Explorer": "cheap-fast",
|
|
714
|
+
"Orchestrator": "cheap-fast",
|
|
715
|
+
"Reviewer": "cheap-fast",
|
|
716
|
+
"Shaper": "capable"
|
|
717
|
+
},
|
|
718
|
+
|
|
719
|
+
// Adopter plan tier. Caps parallel agent dispatch per Anthropic plan limits.
|
|
720
|
+
// tier-1 = single-agent serial (safest); tier-2 = 2-3 parallel after upgrade;
|
|
721
|
+
// tier-4 = 5+ parallel for operator-scale workflows.
|
|
722
|
+
// Pairs with: .claude/skills/longrun/SKILL.md parallel-dispatch logic
|
|
723
|
+
"plan_tier": "tier-1",
|
|
724
|
+
|
|
725
|
+
// Plain-English discipline for agent reply prose to operator. When true,
|
|
726
|
+
// the Stop hook scans the agent's last message for bassclef-internal
|
|
727
|
+
// jargon and surfaces findings to stderr (advisory). 'strict' makes the
|
|
728
|
+
// hook block the stop until prose is clean. false disables the scan.
|
|
729
|
+
//
|
|
730
|
+
// Optional: kiss_words_strict_places escalates specific places to strict
|
|
731
|
+
// even when the global toggle stays advisory. V1 places (bassclef#1171):
|
|
732
|
+
// - closeout_blocks — matches a "## Closeout audit" heading
|
|
733
|
+
// - summary_tables — matches a "## Status" heading
|
|
734
|
+
// - next_pickup — matches a "## Next pickup" heading
|
|
735
|
+
// Adopter default: advisory everywhere; no strict places. Flip to strict
|
|
736
|
+
// or add places when you want the rule to actually catch you.
|
|
737
|
+
//
|
|
738
|
+
// Pairs with: .claude/rules/plain-english-discipline.md
|
|
739
|
+
// .claude/hooks/turn-prose-kiss-check.sh
|
|
740
|
+
"prose_discipline": {
|
|
741
|
+
"kiss_words_turn_prose": true
|
|
742
|
+
// "kiss_words_strict_places": ["closeout_blocks"] // uncomment when ready
|
|
743
|
+
},
|
|
744
|
+
|
|
745
|
+
// Per-path testing-tier enforcement (4 tiers: 0 strict TDD / 1 test-with /
|
|
746
|
+
// 2 smoke / 3 manual verify). global_floor applies when no path_matcher matches.
|
|
747
|
+
// Adopter default: floor=1 (WARN on missing test); empty matchers (add your own).
|
|
748
|
+
// Pairs with: .claude/rules/testing-tier-config.md
|
|
749
|
+
"testing": {
|
|
750
|
+
"global_floor": 1,
|
|
751
|
+
"path_matchers": []
|
|
752
|
+
}
|
|
753
|
+
|
|
754
|
+
// Phase 2.5 below appends "security_scanning" here.
|
|
755
|
+
// /onboard-repo Phase 2.x or future tickets append "tech_stack", "hook_chain",
|
|
756
|
+
// "discipline_layers" as those vocabularies stabilize. Per bassclef#1135.
|
|
757
|
+
}
|
|
758
|
+
JSONC
|
|
759
|
+
```
|
|
760
|
+
|
|
761
|
+
Validate the written file against the schema:
|
|
762
|
+
|
|
763
|
+
```bash
|
|
764
|
+
perl -pe 's,^\s*//.*$,,; s,/\*.*?\*/,,g' .claude/bassclef-configs.jsonc \
|
|
765
|
+
| ajv validate -s ~/src/sunj-labs/bassclef/standards/state-spine/schemas/bassclef-configs.schema.json \
|
|
766
|
+
-d - --spec=draft2020 -c ajv-formats
|
|
767
|
+
```
|
|
768
|
+
|
|
769
|
+
Expect a single `valid` line. The file is now the single source of truth for adopter configuration; subsequent Phase 2.x steps APPEND to it (Phase 2.3.6 tech_stack, Phase 2.5 security_scanning, future T-tickets for hook_chain etc.) rather than rewriting from empty.
|
|
770
|
+
|
|
771
|
+
If the adopter has a pre-existing `.claude/bassclef-configs.jsonc` from a prior SENTINEL_bassclef_version, prompt before overwriting; offer a `--merge` flow (operator-driven; not automated in V1).
|
|
772
|
+
|
|
773
|
+
##### 2.3.6 Discover and write the tech_stack block
|
|
774
|
+
|
|
775
|
+
Stack-bound rules + standards in bassclef (`api-conventions.md`, `sdlc-gates.md`, `schema-management.md`, `new-dependency-check.md`, `frontend-stack.md`, `deployment-topology.md`) read `tech_stack:` from `.claude/bassclef-configs.jsonc` to route per-stack discipline. Without the block, non-matching adopters see false-fires (Prisma rules at SQLAlchemy adopters, Next.js API conventions at FastAPI adopters, etc.). This step writes the block so the bleed stops at install time.
|
|
776
|
+
|
|
777
|
+
Schema reference: `standards/state-spine/schemas/tech-stack.schema.json`. Standard: `standards/tech-stack-config.md`.
|
|
778
|
+
|
|
779
|
+
**Auto-detection signals** (per `standards/tech-stack-config.md` § Auto-detection at `/onboard-repo`):
|
|
780
|
+
|
|
781
|
+
| Build file present | Suggests |
|
|
782
|
+
|---|---|
|
|
783
|
+
| `package.json` with `"next"` dep | `frontend: nextjs`, `lang: typescript` (if `tsconfig.json` also present) |
|
|
784
|
+
| `package.json` with `"react"` dep (no `next`) | `frontend: react-vite` (if `vite.config.*` present) |
|
|
785
|
+
| `package.json` with `"prisma"` dep | `orm: prisma` |
|
|
786
|
+
| `package.json` with `"drizzle-orm"` dep | `orm: drizzle` |
|
|
787
|
+
| `package.json` + `pnpm-lock.yaml` | `pkg_manager: pnpm` |
|
|
788
|
+
| `package.json` + `yarn.lock` | `pkg_manager: yarn` |
|
|
789
|
+
| `package.json` + `package-lock.json` | `pkg_manager: npm` |
|
|
790
|
+
| `pyproject.toml` or `requirements.txt` | `lang: python` |
|
|
791
|
+
| `pyproject.toml` with `sqlalchemy` | `orm: sqlalchemy` |
|
|
792
|
+
| `pyproject.toml` with `alembic` | `orm: alembic` |
|
|
793
|
+
| `pyproject.toml` with `fastapi` | `frontend: fastapi`, `backend: python` |
|
|
794
|
+
| `pyproject.toml` with `django` | `frontend: django`, `backend: python` |
|
|
795
|
+
| `Gemfile` | `lang: ruby`, `pkg_manager: gem` |
|
|
796
|
+
| `Gemfile` with `rails` | `frontend: rails`, `backend: ruby` |
|
|
797
|
+
| `go.mod` | `lang: go`, `pkg_manager: go-mod`, `backend: go` |
|
|
798
|
+
| `Cargo.toml` | `lang: rust`, `pkg_manager: cargo`, `backend: rust` |
|
|
799
|
+
| `vercel.json` or `.vercelrc` | `deploy: vercel` |
|
|
800
|
+
| `fly.toml` | `deploy: fly` |
|
|
801
|
+
| `netlify.toml` | `deploy: netlify` |
|
|
802
|
+
| `render.yaml` | `deploy: render` |
|
|
803
|
+
|
|
804
|
+
No signal → field stays `none` and waits for operator override.
|
|
805
|
+
|
|
806
|
+
**Operator prompt** (surface this exact text):
|
|
807
|
+
|
|
808
|
+
```
|
|
809
|
+
Detected stack signals:
|
|
810
|
+
|
|
811
|
+
lang: <detected or "(no signal)">
|
|
812
|
+
frontend: <detected or "(no signal)">
|
|
813
|
+
backend: <detected or "(no signal)">
|
|
814
|
+
orm: <detected or "(no signal)">
|
|
815
|
+
pkg_manager: <detected or "(no signal)">
|
|
816
|
+
deploy: <detected or "(no signal)">
|
|
817
|
+
|
|
818
|
+
Stack-bound rules route per-adopter from this block. Without it,
|
|
819
|
+
non-matching adopters see false-fires from rules written for the
|
|
820
|
+
default stack (TypeScript + Next.js + Prisma + EC2-Tailscale).
|
|
821
|
+
|
|
822
|
+
Three paths:
|
|
823
|
+
|
|
824
|
+
[a] Accept detected values
|
|
825
|
+
[b] Override per field (5-7 short prompts)
|
|
826
|
+
[c] Skip — write declared_via: deferred and revisit later
|
|
827
|
+
(rules fall back to operator defaults; expect some false-fires
|
|
828
|
+
until you set the block)
|
|
829
|
+
|
|
830
|
+
Pick a/b/c:
|
|
831
|
+
```
|
|
832
|
+
|
|
833
|
+
**On accept (a):** write the block with detected values + `declared_via: onboard-repo` + `declared_at: <ISO date>`.
|
|
834
|
+
|
|
835
|
+
**On per-field override (b):** prompt each field in order with detected value as the default. Field-level enums per `standards/tech-stack-config.md` § Fields.
|
|
836
|
+
|
|
837
|
+
**On skip (c):** write `tech_stack: { declared_via: "deferred", declared_at: <ISO date> }` only. The schema admits all fields as optional; rules fall back gracefully. Operator can revisit by re-running `/onboard-repo` or editing the block directly.
|
|
838
|
+
|
|
839
|
+
**Append to `.claude/bassclef-configs.jsonc`** using `jq` or in-place edit; the block goes immediately before the closing brace + after `testing`:
|
|
840
|
+
|
|
841
|
+
```bash
|
|
842
|
+
# Pseudo-procedure; actual implementation reads the operator's path choice
|
|
843
|
+
# and constructs the block from detected + override values.
|
|
844
|
+
cat >> .claude/bassclef-configs.jsonc <<TECH_STACK
|
|
845
|
+
,
|
|
846
|
+
|
|
847
|
+
// Tech stack vocabulary. Stack-bound rules read this to route per-
|
|
848
|
+
// stack discipline (schema-management.md ORM routing, api-conventions
|
|
849
|
+
// frontend routing, sdlc-gates lang routing, etc.).
|
|
850
|
+
// Auto-detected at /onboard-repo Phase 2.3.6; operator confirms or
|
|
851
|
+
// overrides per field.
|
|
852
|
+
// Pairs with: standards/tech-stack-config.md (schema + semantics),
|
|
853
|
+
// standards/state-spine/schemas/tech-stack.schema.json
|
|
854
|
+
// Schema reference: bassclef#1127 tech_stack discovery
|
|
855
|
+
"tech_stack": {
|
|
856
|
+
"lang": "<value>",
|
|
857
|
+
"frontend": "<value>",
|
|
858
|
+
"backend": "<value>",
|
|
859
|
+
"orm": "<value>",
|
|
860
|
+
"pkg_manager": "<value>",
|
|
861
|
+
"deploy": "<value>",
|
|
862
|
+
"declared_at": "<ISO date>",
|
|
863
|
+
"declared_via": "onboard-repo"
|
|
864
|
+
}
|
|
865
|
+
TECH_STACK
|
|
866
|
+
```
|
|
867
|
+
|
|
868
|
+
(In practice the writer holds the file open as JSON-with-comments, mutates the parsed object, re-emits with comments preserved per the comment-aware JSONC editor pattern; the heredoc above is illustrative.)
|
|
869
|
+
|
|
870
|
+
**Validate after append:**
|
|
871
|
+
|
|
872
|
+
```bash
|
|
873
|
+
perl -pe 's,^\s*//.*$,,; s,/\*.*?\*/,,g' .claude/bassclef-configs.jsonc \
|
|
874
|
+
| ajv validate -s ~/src/sunj-labs/bassclef/standards/state-spine/schemas/bassclef-configs.schema.json \
|
|
875
|
+
-d - --spec=draft2020 -c ajv-formats
|
|
876
|
+
```
|
|
877
|
+
|
|
878
|
+
Expect `valid`. If the file fails to validate, revert the append, surface the schema error, and re-prompt.
|
|
879
|
+
|
|
880
|
+
**Acceptance:**
|
|
881
|
+
|
|
882
|
+
- After Phase 2.3.6 completes, `.claude/bassclef-configs.jsonc` contains a `tech_stack:` block.
|
|
883
|
+
- Block validates against `tech-stack.schema.json`.
|
|
884
|
+
- `declared_via` is one of `onboard-repo` (path a or b) or `deferred` (path c); `migrated` and `demo-prompt` reserved for other callers.
|
|
885
|
+
- Operator can re-run `/onboard-repo` and the existing block is detected; prompt asks whether to keep, re-detect, or edit per-field.
|
|
886
|
+
|
|
887
|
+
**Composes with downstream Phase 2.x steps:**
|
|
888
|
+
|
|
889
|
+
- Phase 2.3.7 (testing-tier path_matchers seed) reads `tech_stack.lang` to pick the per-stack default tier matchers.
|
|
890
|
+
- Phase 2.5 (security scanning) reads `tech_stack.lang` to seed the scanner adapter.
|
|
891
|
+
- Future Phase 2.x for `hook_chain` reads stack signals to pick per-stack hook defaults.
|
|
892
|
+
|
|
893
|
+
##### 2.3.7 Seed testing.path_matchers per declared tech_stack
|
|
894
|
+
|
|
895
|
+
Phase 2.3.5 wrote the `testing` block with `global_floor: 1` + empty `path_matchers`. Phase 2.3.6 just discovered + wrote `tech_stack`. This step reads `tech_stack.lang` and seeds `testing.path_matchers` with sensible per-stack defaults so the Tier 0 / Tier 1 enforcer (Phase 2.2.8) fires on the right paths from day one.
|
|
896
|
+
|
|
897
|
+
**Per-stack default seeds** (operator-eyes design choices):
|
|
898
|
+
|
|
899
|
+
For `tech_stack.lang: typescript` + `tech_stack.frontend: nextjs` (bassclef default):
|
|
900
|
+
|
|
901
|
+
```jsonc
|
|
902
|
+
"testing": {
|
|
903
|
+
"global_floor": 1,
|
|
904
|
+
"path_matchers": [
|
|
905
|
+
{ "match": "lib/domain/**/*.ts", "tier": 0 },
|
|
906
|
+
{ "match": "lib/infra/**/*.ts", "tier": 0 },
|
|
907
|
+
{ "match": "app/api/**/*.ts", "tier": 1 },
|
|
908
|
+
{ "match": "app/actions/**/*.ts", "tier": 1 },
|
|
909
|
+
{ "match": "app/_components/**/*.tsx", "tier": 2 },
|
|
910
|
+
{ "match": "app/**/*.tsx", "tier": 2 },
|
|
911
|
+
{ "match": "docs/**/*.md", "tier": 3 }
|
|
912
|
+
]
|
|
913
|
+
}
|
|
914
|
+
```
|
|
915
|
+
|
|
916
|
+
For `tech_stack.lang: python` + `tech_stack.frontend: fastapi`:
|
|
917
|
+
|
|
918
|
+
```jsonc
|
|
919
|
+
"testing": {
|
|
920
|
+
"global_floor": 1,
|
|
921
|
+
"path_matchers": [
|
|
922
|
+
{ "match": "domain/**/*.py", "tier": 0 },
|
|
923
|
+
{ "match": "infrastructure/**/*.py", "tier": 0 },
|
|
924
|
+
{ "match": "api/**/*.py", "tier": 1 },
|
|
925
|
+
{ "match": "templates/**/*", "tier": 2 },
|
|
926
|
+
{ "match": "docs/**/*.md", "tier": 3 }
|
|
927
|
+
]
|
|
928
|
+
}
|
|
929
|
+
```
|
|
930
|
+
|
|
931
|
+
Other stacks (ruby-rails, go-gin, java-spring) ship default seeds as per-stack siblings under `standards/testing-tier-seeds/<stack>.md` — deferred to a follow-on ticket when an adopter on that stack files for them. The pattern is the same: Tier 0 on the essential pure-domain layer; Tier 1 on the API + actions layer; Tier 2 on UI + template surfaces; Tier 3 on docs.
|
|
932
|
+
|
|
933
|
+
**On `tech_stack.lang: none` or `deferred`** — skip the seed; leave `path_matchers: []` empty. The `global_floor: 1` keeps the WARN posture; adopter can hand-edit later.
|
|
934
|
+
|
|
935
|
+
**Operator prompt** (surface this exact text after Phase 2.3.6 completes):
|
|
936
|
+
|
|
937
|
+
```
|
|
938
|
+
Tech stack: <detected lang + frontend>
|
|
939
|
+
|
|
940
|
+
Seed testing.path_matchers with the per-stack default for <stack>?
|
|
941
|
+
|
|
942
|
+
[a] Yes, accept default seed (recommended)
|
|
943
|
+
[b] Show me the seed first
|
|
944
|
+
[c] Skip — keep path_matchers empty (manual seed later)
|
|
945
|
+
|
|
946
|
+
Pick a/b/c:
|
|
947
|
+
```
|
|
948
|
+
|
|
949
|
+
**On accept (a)** — write the matching per-stack seed into `testing.path_matchers` in `bassclef-configs.jsonc`. Use the comment-aware JSONC editor pattern so the existing comments + `global_floor` survive.
|
|
950
|
+
|
|
951
|
+
**On show first (b)** — print the seed inline; ask for accept/edit/skip.
|
|
952
|
+
|
|
953
|
+
**On skip (c)** — leave empty; print "Adopter chose to skip — `testing.path_matchers` stays empty. Set with `/onboard-repo` re-run or hand-edit later."
|
|
954
|
+
|
|
955
|
+
**Validate after write:**
|
|
956
|
+
|
|
957
|
+
```bash
|
|
958
|
+
perl -pe 's,^\s*//.*$,,; s,/\*.*?\*/,,g' .claude/bassclef-configs.jsonc \
|
|
959
|
+
| ajv validate -s ~/src/sunj-labs/bassclef/standards/state-spine/schemas/bassclef-configs.schema.json \
|
|
960
|
+
-d - --spec=draft2020 -c ajv-formats
|
|
961
|
+
```
|
|
962
|
+
|
|
963
|
+
Expect a single `valid` line. The `testing.path_matchers` items must validate against the bassclef-configs schema.
|
|
964
|
+
|
|
965
|
+
**Stack siblings deferred** — only typescript-nextjs + python-fastapi ship in this step. Adopters on ruby-rails / go-gin / java-spring / rust-axum etc. get `global_floor: 1` + empty matchers (the safe default WARN posture) and can hand-seed per their layout. A follow-on ticket adds per-stack seed siblings under `standards/testing-tier-seeds/<stack>.md` as adopters request them.
|
|
966
|
+
|
|
967
|
+
Source: bassclef#1143 (this seed step — T10, iteration-2 BLOCKER). Sister rule: `.claude/rules/testing-tier-config.md`. Pairs with Phase 2.2.8 (the enforcer that reads this seed).
|
|
968
|
+
|
|
969
|
+
##### 2.3.8 Surface the wiki_sync toggle
|
|
970
|
+
|
|
971
|
+
The `wiki_sync` block in `.claude/bassclef-configs.jsonc` controls whether the adopter's repo gets the bassclef-docs-sync workflow vendored from `presence/install/bassclef-docs-sync.template.yml`. This step surfaces the toggle so adopters see the option exists.
|
|
972
|
+
|
|
973
|
+
**Phase 1 (this step — bet 2026-06-20b) — minimal stub:**
|
|
974
|
+
|
|
975
|
+
Read the adopter's `wiki_sync.enabled` value from the bassclef-configs file just written. Print one of the following:
|
|
976
|
+
|
|
977
|
+
- **`enabled: false`** (default — universal): print
|
|
978
|
+
> Wiki-sync is OFF. The wiki-as-we-go discipline rule still loads at session-start, but no workflow fires. To enable later: edit `.claude/bassclef-configs.jsonc` `wiki_sync.enabled` to `true` and re-run `/onboard-repo` for the vendoring step (full vendoring lands in Phase 2 of bet 2026-06-20b — see `docs/iteration-bets/2026-06-20b-cold-adopter-mechanism-inheritance.md`).
|
|
979
|
+
- **`enabled: true`**: print
|
|
980
|
+
> Wiki-sync is ON. Full vendoring of `presence/install/bassclef-docs-sync.template.yml` → `.github/workflows/bassclef-docs-sync.yml` + `presence/install/docs-sync-allowlist.template.md` → `standards/docs-sync-allowlist.md` is **deferred to Phase 2 of bet 2026-06-20b**. For now, copy both templates manually if you need the wiki to update from main pushes today.
|
|
981
|
+
|
|
982
|
+
**Phase 2 (next session) — full vendoring (deferred):**
|
|
983
|
+
|
|
984
|
+
- Auto-copy both templates into the adopter's repo
|
|
985
|
+
- Open a follow-up PR for GHA secrets if `target_wiki_repo` requires non-default auth
|
|
986
|
+
- Walk the adopter through the three workflow-edit surfaces (the `on.push.paths` glob, the Filter step's case-glob, the Sync step's source-path → wiki-page mapping)
|
|
987
|
+
- Smoke-test by pushing a docs change and verifying the wiki updates
|
|
988
|
+
|
|
989
|
+
The Phase 1 stub keeps this step minimal so the goal stays bounded. Adopters who want wiki-sync today can copy the templates by hand from bassclef's `presence/install/` (workflows + cold-adopter assets).
|
|
990
|
+
|
|
991
|
+
**Composes with:**
|
|
992
|
+
|
|
993
|
+
- `.claude/skills/docs-sync/SKILL.md` § Adopter mode (read at runtime; surfaces BLOCK if templates not vendored)
|
|
994
|
+
- `.claude/rules/session-artifacts.md` § Wiki-as-we-go discipline (methodology rule that triggers the closeout question)
|
|
995
|
+
|
|
996
|
+
Source: bassclef#1265 (this surfacing step — wiki-sync mechanism adopter inheritance). Sister bet: `docs/iteration-bets/2026-06-20b-cold-adopter-mechanism-inheritance.md` WU-2.
|
|
997
|
+
|
|
998
|
+
##### 2.3.9 Write the onboard-repo state marker
|
|
999
|
+
|
|
1000
|
+
Write `.claude/state/onboard-repo.state.json` after Phase 2.3 has
|
|
1001
|
+
populated the config file(s). The marker captures which mode was used,
|
|
1002
|
+
the ISO timestamp, and which files were written. The configs UI reads
|
|
1003
|
+
this marker to render the first-run overlay (per canvas 2026-07-08
|
|
1004
|
+
Appendix C). Future audits trace how a repo got wired.
|
|
1005
|
+
|
|
1006
|
+
Re-runs append a history entry — the marker keeps prior runs, not
|
|
1007
|
+
clobber them.
|
|
1008
|
+
|
|
1009
|
+
Invoke the helper script that ships alongside this SKILL:
|
|
1010
|
+
|
|
1011
|
+
```bash
|
|
1012
|
+
# ONBOARD_MODE is set earlier in Procedure —
|
|
1013
|
+
# default / --with-deploy-host / --with-secrets / --full / --greenfield-from-intent
|
|
1014
|
+
bash .claude/skills/onboard-repo/write-state-marker.sh "${ONBOARD_MODE:-default}"
|
|
1015
|
+
```
|
|
1016
|
+
|
|
1017
|
+
The script writes / updates `.claude/state/onboard-repo.state.json`
|
|
1018
|
+
with shape `{mode, timestamp_iso, paths_written[], history[], skill_version}`.
|
|
1019
|
+
Tier 0 tests at `.claude/skills/onboard-repo/tests/write-state-marker.test.sh`
|
|
1020
|
+
pin all behavior including re-run history append.
|
|
1021
|
+
|
|
1022
|
+
**Composes with:**
|
|
1023
|
+
|
|
1024
|
+
- Configs UI first-run overlay (`bassclef/configs/`, bet 2026-07-08a WU-7)
|
|
1025
|
+
- Future audits reading `.claude/state/onboard-repo.state.json`
|
|
1026
|
+
|
|
1027
|
+
Source: bassclef-upstream#664 (state marker for onboard-repo). Part of goal
|
|
1028
|
+
`docs/iteration-bets/2026-07-08a-configs-ui-iteration-1.md` WU-4.
|
|
1029
|
+
|
|
1030
|
+
##### 2.3.10 Wire the cron installer for auto-save
|
|
1031
|
+
|
|
1032
|
+
Goal 27b (PR #937) shipped `presence/install/schedule-auto-save.cron.sh` at
|
|
1033
|
+
`tier: lite`. The installer writes a cron entry that fires
|
|
1034
|
+
`save-state.sh --auto --quiet` on idle. Sam's magic demo per canvas
|
|
1035
|
+
`docs/canvases/2026-07-19-bassclef-lite.md` L67-71 promises session-state
|
|
1036
|
+
continuity as part of onboarding. This step wires the installer in.
|
|
1037
|
+
|
|
1038
|
+
Behavior per OS:
|
|
1039
|
+
|
|
1040
|
+
- **macOS + Linux + WSL** — run the installer directly. It appends one
|
|
1041
|
+
crontab entry and is idempotent (re-running is safe per PR #937 Test 4).
|
|
1042
|
+
- **Native Windows (no WSL)** — cron is not available. Point the adopter at
|
|
1043
|
+
`presence/install/schedule-auto-save.taskscheduler.md` for the manual
|
|
1044
|
+
Task Scheduler setup.
|
|
1045
|
+
|
|
1046
|
+
```bash
|
|
1047
|
+
OS_KIND="$(uname -s)"
|
|
1048
|
+
case "$OS_KIND" in
|
|
1049
|
+
Darwin|Linux)
|
|
1050
|
+
if [ -x "$BASSCLEF_DIR/presence/install/schedule-auto-save.cron.sh" ]; then
|
|
1051
|
+
bash "$BASSCLEF_DIR/presence/install/schedule-auto-save.cron.sh" \
|
|
1052
|
+
|| echo "WARNING: cron installer failed; run manually to enable auto-save" >&2
|
|
1053
|
+
else
|
|
1054
|
+
echo "WARNING: schedule-auto-save.cron.sh not found; skip auto-save wire" >&2
|
|
1055
|
+
fi
|
|
1056
|
+
;;
|
|
1057
|
+
MINGW*|CYGWIN*|MSYS*)
|
|
1058
|
+
echo "Native Windows detected. Cron is not available."
|
|
1059
|
+
echo "See presence/install/schedule-auto-save.taskscheduler.md for the"
|
|
1060
|
+
echo "manual Task Scheduler setup that wires auto-save on Windows."
|
|
1061
|
+
;;
|
|
1062
|
+
*)
|
|
1063
|
+
echo "Unknown OS '$OS_KIND'; skip auto-save wire"
|
|
1064
|
+
;;
|
|
1065
|
+
esac
|
|
1066
|
+
```
|
|
1067
|
+
|
|
1068
|
+
The installer prints its own progress. Failures do not stop onboarding —
|
|
1069
|
+
auto-save is a nice-to-have on first install, and adopters can re-run
|
|
1070
|
+
the installer any time via `bash $BASSCLEF_DIR/presence/install/schedule-auto-save.cron.sh`.
|
|
1071
|
+
|
|
1072
|
+
**Composes with:**
|
|
1073
|
+
|
|
1074
|
+
- `presence/install/schedule-auto-save.cron.sh` (PR #937 — the cron installer)
|
|
1075
|
+
- `presence/install/schedule-auto-save.taskscheduler.md` (PR #937 — Windows guide)
|
|
1076
|
+
- ADR-046 cross-OS scheduling (accepted; Option C picked)
|
|
1077
|
+
|
|
1078
|
+
Source: bassclef-upstream#941 (wire cron into onboard for Sam's magic demo).
|
|
1079
|
+
|
|
1080
|
+
##### 2.4 Point at bassclef's source (URL + auth)
|
|
1081
|
+
|
|
1082
|
+
The thin-pointer dispatcher installed in 2.1 reads `.bassclef-source.json`
|
|
1083
|
+
for the upstream tarball URL + auth metadata when the curl fallback
|
|
1084
|
+
fires (Cloud Env / mobile / fresh sandboxes / CI). Schema codified at
|
|
1085
|
+
`standards/bassclef-source-config.md`; validation hook at
|
|
1086
|
+
`.claude/hooks/bassclef-source-config-validate.sh`.
|
|
1087
|
+
|
|
1088
|
+
Before writing the file, prompt the adopter explicitly:
|
|
1089
|
+
|
|
1090
|
+
```
|
|
1091
|
+
Bassclef can auto-pull the latest skills, rules, and agents into this
|
|
1092
|
+
repo at every Claude Code session start. Keeps you current with bassclef's
|
|
1093
|
+
evolution; you never manually update.
|
|
1094
|
+
|
|
1095
|
+
Off by default. Turn on now? [y/N]
|
|
1096
|
+
```
|
|
1097
|
+
|
|
1098
|
+
Persist the adopter's answer to the `auto_sync` field. Default is `false` when in doubt.
|
|
1099
|
+
|
|
1100
|
+
```bash
|
|
1101
|
+
cat > .bassclef-source.json <<JSON
|
|
1102
|
+
{
|
|
1103
|
+
"source_url": "https://api.github.com/repos/sunj-labs/bassclef/tarball/main",
|
|
1104
|
+
"auth_method": "Bearer",
|
|
1105
|
+
"token_env": "BASSCLEF_TOKEN",
|
|
1106
|
+
"auto_sync": false,
|
|
1107
|
+
"comment": "Provider: GitHub repo tarball API. Auth: fine-grained PAT 'bassclef-substrate-read' (Contents:read on sunj-labs/bassclef), stored as BASSCLEF_TOKEN in the consumer's Cloud Code environment. Schema: standards/bassclef-source-config.md. auto_sync controls whether SessionStart fetches bassclef's latest substrate; off by default per bassclef#939."
|
|
1108
|
+
}
|
|
1109
|
+
JSON
|
|
1110
|
+
```
|
|
1111
|
+
|
|
1112
|
+
**Operator action — out of band, one-time per consumer:**
|
|
1113
|
+
|
|
1114
|
+
1. Create fine-grained GitHub PAT scoped to `sunj-labs/bassclef`
|
|
1115
|
+
- Permission: Contents: read
|
|
1116
|
+
- Expiry: 90 days
|
|
1117
|
+
- Name: `bassclef-read-{REPO_SHORT}-{YYYYMMDD}`
|
|
1118
|
+
2. Paste into the consumer's Cloud Code environment as `BASSCLEF_TOKEN`.
|
|
1119
|
+
3. Track the PAT lifecycle in operator's `substrate.secrets.md` per
|
|
1120
|
+
`standards/secrets-lifecycle.md`.
|
|
1121
|
+
|
|
1122
|
+
Provider alternatives (see `standards/bassclef-source-config.md` for
|
|
1123
|
+
GitHub public, GitHub private release, ADO Repos, GitLab examples).
|
|
1124
|
+
|
|
1125
|
+
After writing the file, run the hook once locally to validate via
|
|
1126
|
+
sibling fast-path (no PAT needed for desktop):
|
|
1127
|
+
|
|
1128
|
+
```bash
|
|
1129
|
+
echo "{\"cwd\":\"$PWD\"}" | bash .claude/hooks/bassclef-sync.sh
|
|
1130
|
+
```
|
|
1131
|
+
|
|
1132
|
+
Expect: `### BASSCLEF SUBSTRATE — SYNCED` banner; skills/rules/hooks/
|
|
1133
|
+
luminaries symlinked into `.claude/`; no errors surfaced.
|
|
1134
|
+
|
|
1135
|
+
##### 2.5 Configure security scanning (per bassclef goal 2026-06-17a Phase Y)
|
|
1136
|
+
|
|
1137
|
+
Auto-detect the adopter's stack from build files, confirm with the operator, and write the `security_scanning` block to `.claude/bassclef-configs.jsonc`. Adopter copies the matching reference workflow next.
|
|
1138
|
+
|
|
1139
|
+
Auto-detection signals (per `standards/security-scanner-adapter.md` § Stack auto-detection):
|
|
1140
|
+
|
|
1141
|
+
```bash
|
|
1142
|
+
# Detect stack by build-file signal.
|
|
1143
|
+
STACK_GUESS="custom"
|
|
1144
|
+
if [ -f "package.json" ]; then
|
|
1145
|
+
if grep -q '"typescript"\|"@types/' package.json; then
|
|
1146
|
+
STACK_GUESS="node-typescript"
|
|
1147
|
+
else
|
|
1148
|
+
STACK_GUESS="node-typescript" # TS opt-out can happen later
|
|
1149
|
+
fi
|
|
1150
|
+
elif [ -f "requirements.txt" ] || [ -f "pyproject.toml" ] || [ -f "setup.py" ]; then
|
|
1151
|
+
STACK_GUESS="python"
|
|
1152
|
+
elif [ -f "Gemfile" ] || ls *.gemspec >/dev/null 2>&1; then
|
|
1153
|
+
STACK_GUESS="ruby"
|
|
1154
|
+
elif [ -f "pom.xml" ] || [ -f "build.gradle" ] || ls **/*.java >/dev/null 2>&1; then
|
|
1155
|
+
STACK_GUESS="java"
|
|
1156
|
+
elif [ -f "go.mod" ] || ls **/*.go >/dev/null 2>&1; then
|
|
1157
|
+
STACK_GUESS="go"
|
|
1158
|
+
fi
|
|
1159
|
+
```
|
|
1160
|
+
|
|
1161
|
+
Prompt the operator (sample):
|
|
1162
|
+
|
|
1163
|
+
```
|
|
1164
|
+
Bassclef security scanner adapter detected stack: <STACK_GUESS>
|
|
1165
|
+
|
|
1166
|
+
Default scanners for this stack (per standards/security-scanner-adapter.md):
|
|
1167
|
+
- node-typescript: eslint-plugin-security + audit-ci + gitleaks
|
|
1168
|
+
- python: bandit + safety + gitleaks
|
|
1169
|
+
- ruby: brakeman + bundler-audit + gitleaks
|
|
1170
|
+
- java: spotbugs-security + dependency-check + gitleaks
|
|
1171
|
+
- go: gosec + govulncheck + gitleaks
|
|
1172
|
+
- custom: adopter-supplied list
|
|
1173
|
+
|
|
1174
|
+
Activate scanners with stack=<STACK_GUESS>? [Y/n/custom/skip]
|
|
1175
|
+
```
|
|
1176
|
+
|
|
1177
|
+
Persist the answer to the bassclef-configs block. Phase 2.3.5 (bassclef#1135 WU-4) wrote the seed file; this step adds the `security_scanning` block to it via a Python merge to keep the JSONC valid.
|
|
1178
|
+
|
|
1179
|
+
```bash
|
|
1180
|
+
# Add security_scanning block to .claude/bassclef-configs.jsonc (bassclef#1135).
|
|
1181
|
+
# Phase 2.3.5 already wrote the seed; we add a block via JSONC-aware Python merge.
|
|
1182
|
+
python3 - "$STACK_GUESS" <<'PY'
|
|
1183
|
+
import json, re, sys, pathlib
|
|
1184
|
+
path = pathlib.Path('.claude/bassclef-configs.jsonc')
|
|
1185
|
+
raw = path.read_text()
|
|
1186
|
+
# Strip line + block comments before parsing
|
|
1187
|
+
stripped = re.sub(r'/\*.*?\*/', '', re.sub(r'//.*$', '', raw, flags=re.M), flags=re.S)
|
|
1188
|
+
data = json.loads(stripped)
|
|
1189
|
+
stack = sys.argv[1]
|
|
1190
|
+
data['security_scanning'] = {
|
|
1191
|
+
'stack': None if stack in ('null', 'skip', '') else stack,
|
|
1192
|
+
'additional_scanners': [],
|
|
1193
|
+
'block_on_high_severity': True,
|
|
1194
|
+
}
|
|
1195
|
+
path.write_text(json.dumps(data, indent=2) + '\n')
|
|
1196
|
+
PY
|
|
1197
|
+
```
|
|
1198
|
+
|
|
1199
|
+
Note: the Python merge re-serializes the file without comments. Operators
|
|
1200
|
+
keep the schema-doc reference (`standards/bassclef-configs-schema.md`)
|
|
1201
|
+
as the bassclef comment-bearing source; the on-disk file is the values.
|
|
1202
|
+
A follow-on may add a comment-preserving JSONC writer.
|
|
1203
|
+
|
|
1204
|
+
INSTEAD of asking the operator to know the scanner names: the standard supplies the per-stack defaults; the operator confirms the stack choice only.
|
|
1205
|
+
|
|
1206
|
+
If the operator answers `skip`, write `"stack": null` — scanners stay off until the next session re-runs the question.
|
|
1207
|
+
|
|
1208
|
+
**Operator follow-up — copy the reference workflow:**
|
|
1209
|
+
|
|
1210
|
+
After the bassclef-configs block is written, point the operator at the matching reference workflow:
|
|
1211
|
+
|
|
1212
|
+
```
|
|
1213
|
+
Next step: copy the per-stack reference workflow into your repo's CI.
|
|
1214
|
+
|
|
1215
|
+
cp ~/src/sunj-labs/bassclef/config/security-scanners/<STACK_GUESS>.yml \
|
|
1216
|
+
.github/workflows/security-scan.yml
|
|
1217
|
+
|
|
1218
|
+
The workflow auto-skips when the bassclef-configs stack value is null,
|
|
1219
|
+
so copying is harmless if you're not ready to activate yet.
|
|
1220
|
+
```
|
|
1221
|
+
|
|
1222
|
+
For stacks beyond node-typescript + python (which ship reference workflows), the operator authors their own workflow guided by `standards/security-scanner-adapter.md` § Stack reference matrix.
|
|
1223
|
+
|
|
1224
|
+
##### 2.6 Set up .gitignore for bassclef's runtime files
|
|
1225
|
+
|
|
1226
|
+
If `.gitignore` doesn't exist, create with bassclef runtime markers:
|
|
1227
|
+
|
|
1228
|
+
```bash
|
|
1229
|
+
[ -f .gitignore ] || cat > .gitignore <<'EOF'
|
|
1230
|
+
# Bassclef runtime artifacts (per-machine, not content)
|
|
1231
|
+
.claude/LAST_SAVE
|
|
1232
|
+
.claude/SESSION_LOCK
|
|
1233
|
+
.claude/CHECKPOINT.md
|
|
1234
|
+
.claude/settings.local.json
|
|
1235
|
+
state/markers/verify/
|
|
1236
|
+
EOF
|
|
1237
|
+
```
|
|
1238
|
+
|
|
1239
|
+
The sync hook will add its managed symlink block on next run; this
|
|
1240
|
+
seeds the file with everything else.
|
|
1241
|
+
|
|
1242
|
+
#### Phase 3 — Create starter docs (CLAUDE.md, whereami)
|
|
1243
|
+
|
|
1244
|
+
**Working directory: target repo.**
|
|
1245
|
+
|
|
1246
|
+
##### 3.1 Create the starter CLAUDE.md
|
|
1247
|
+
|
|
1248
|
+
Minimal starter. Operator owns this file going forward.
|
|
1249
|
+
|
|
1250
|
+
The first non-title line reads `@.claude/bassclef-orientation.md` (per
|
|
1251
|
+
ADR-032 + Anthropic's `@filename` convention). This import loads bassclef's
|
|
1252
|
+
orientation into every session. The orientation names the gates, the
|
|
1253
|
+
luminaries, the tier ladder, and the rules the agent should not break.
|
|
1254
|
+
|
|
1255
|
+
The orientation file lands in the adopter repo as a symlink into bassclef.
|
|
1256
|
+
The sync template Section 3d-bis writes the symlink.
|
|
1257
|
+
Without this symlink, the import resolves only through `additionalDirectories`.
|
|
1258
|
+
If that path breaks — rename, delete, corporate laptop with no sibling — the
|
|
1259
|
+
import silently no-ops. The symlink closes that gap.
|
|
1260
|
+
|
|
1261
|
+
Bassclef updates the file via release. The adopter's CLAUDE.md stays
|
|
1262
|
+
adopter-owned outside the import line.
|
|
1263
|
+
|
|
1264
|
+
```markdown
|
|
1265
|
+
# [repo-name]
|
|
1266
|
+
|
|
1267
|
+
@.claude/bassclef-orientation.md
|
|
1268
|
+
|
|
1269
|
+
## What this repo is
|
|
1270
|
+
|
|
1271
|
+
[One-paragraph description]
|
|
1272
|
+
|
|
1273
|
+
## Substrate
|
|
1274
|
+
|
|
1275
|
+
Inherits bassclef substrate via `--add-dir ../bassclef` (desktop) and
|
|
1276
|
+
S3 tarball sync (mobile). The `@.claude/bassclef-orientation.md` import
|
|
1277
|
+
above auto-loads the substrate discipline (gates, luminaries, tier ladder,
|
|
1278
|
+
what-NOT-to-do). For the upstream role declaration, see
|
|
1279
|
+
`~/src/sunj-labs/bassclef/CLAUDE.md`.
|
|
1280
|
+
|
|
1281
|
+
## Stack
|
|
1282
|
+
|
|
1283
|
+
[Framework, language, key dependencies — or "documentation only"]
|
|
1284
|
+
|
|
1285
|
+
## Current state
|
|
1286
|
+
|
|
1287
|
+
[Phase, active iteration, any context a fresh session needs]
|
|
1288
|
+
```
|
|
1289
|
+
|
|
1290
|
+
##### 3.2 Create the starter docs/whereami.md
|
|
1291
|
+
|
|
1292
|
+
```bash
|
|
1293
|
+
mkdir -p docs
|
|
1294
|
+
cp ~/src/sunj-labs/bassclef/templates/whereami-template.md \
|
|
1295
|
+
docs/whereami.md
|
|
1296
|
+
```
|
|
1297
|
+
|
|
1298
|
+
Operator fills in phase + iteration section. If repo is fresh,
|
|
1299
|
+
`phase: Inception` with `iteration_bet: none — new repo` is fine.
|
|
1300
|
+
|
|
1301
|
+
#### Phase 3.5 — Optional: provision the deploy host + bootstrap secrets
|
|
1302
|
+
|
|
1303
|
+
**Working directory: target repo.**
|
|
1304
|
+
|
|
1305
|
+
After Phase 3 (docs stubs) lands the substrate config files, three opt-in
|
|
1306
|
+
flags chain follow-on skills inline so every new sunj-labs repo bootstraps
|
|
1307
|
+
in one dispatch instead of four manual steps. Without these flags, the
|
|
1308
|
+
operator runs the follow-on skills separately afterward (older pattern,
|
|
1309
|
+
still supported).
|
|
1310
|
+
|
|
1311
|
+
##### Flag reference
|
|
1312
|
+
|
|
1313
|
+
| Invocation | Behavior |
|
|
1314
|
+
|---|---|
|
|
1315
|
+
| `/onboard-repo` (no flag) | Phases 1–3 only. Interactive prompt at end: "Run /provision-deploy-host now? [Y/n/skip]" + same for /secrets-bootstrap. Skip-state persists per below. |
|
|
1316
|
+
| `/onboard-repo --with-deploy-host` | Phases 1–3, then dispatches `/provision-deploy-host` inline (operator-confirms before AWS calls). Skips the interactive prompt for deploy-host. |
|
|
1317
|
+
| `/onboard-repo --with-secrets` | Phases 1–3, then dispatches `/secrets-bootstrap` inline (audits + bootstraps env per substrate.secrets.md). Skips the interactive prompt for secrets. |
|
|
1318
|
+
| `/onboard-repo --full` | All of the above — substrate scaffolded + Amplify host provisioned + secrets audited in one dispatch. Recommended for new sunj-labs repos. |
|
|
1319
|
+
| `/onboard-repo --greenfield-from-intent "<intent>"` | Cold-adopter demo path. Skips Path A entirely and runs Path B — empty directory in, full artifact chain on disk plus localhost gallery URL out. No GitHub repo gets created. No vendor accounts needed. Uses the LLM your Claude Code session provides. For the extended path (deploy mocks to a configured subdomain plus chain to `/build` plus `/launch-preview`), finish Path A first to wire vendor bindings, then dispatch `/launch --voice-input` without `--local`. See `docs/iteration-bets/2026-05-12-phase-v-hey-alexa-mvd.md` and bassclef#923 / PR #924 for the local-mode building block. |
|
|
1320
|
+
|
|
1321
|
+
##### Tier gate
|
|
1322
|
+
|
|
1323
|
+
Three of the flags above dispatch skills that ship at `tier: standard`.
|
|
1324
|
+
Lite adopters running the bassclef-lite tarball do not carry
|
|
1325
|
+
`/provision-deploy-host` or `/secrets-bootstrap`. Before dispatching
|
|
1326
|
+
`--with-deploy-host`, `--with-secrets`, or `--full`, resolve the
|
|
1327
|
+
adopter tier through `lib/tier-check.sh`:
|
|
1328
|
+
|
|
1329
|
+
```bash
|
|
1330
|
+
source lib/tier-check.sh
|
|
1331
|
+
tier=$(resolve_adopter_tier)
|
|
1332
|
+
```
|
|
1333
|
+
|
|
1334
|
+
The check reads `.claude/bassclef-configs.jsonc` `adopter.tier` field
|
|
1335
|
+
first. Falls back to skill probe — presence of `/provision-deploy-host`
|
|
1336
|
+
skill returns `standard`. Safe default is `standard`.
|
|
1337
|
+
|
|
1338
|
+
Behavior per tier:
|
|
1339
|
+
|
|
1340
|
+
| Invocation | tier=lite | tier=standard or pro |
|
|
1341
|
+
|---|---|---|
|
|
1342
|
+
| `/onboard-repo` (no flag) | Phases 1–3 run. Skip interactive prompts for /provision-deploy-host and /secrets-bootstrap. | Phases 1–3 + interactive prompts. |
|
|
1343
|
+
| `/onboard-repo --with-deploy-host` (lite adopter) | Print graceful upgrade message: "--with-deploy-host requires bassclef standard. Reason: /provision-deploy-host is a standard-tier skill. Upgrade path: install bassclef standard, or run Phases 1–3 without the flag and provision the deploy host manually later." Continue Phases 1–3 as if no flag was passed. | Phases 1–3 + `/provision-deploy-host` dispatched inline. |
|
|
1344
|
+
| `/onboard-repo --with-secrets` (lite adopter) | Print graceful upgrade message: "--with-secrets requires bassclef standard. Reason: /secrets-bootstrap is a standard-tier skill. Upgrade path: install bassclef standard, or run Phases 1–3 without the flag and manage secrets manually via substrate.secrets.md." Continue Phases 1–3. | Phases 1–3 + `/secrets-bootstrap` dispatched inline. |
|
|
1345
|
+
| `/onboard-repo --full` (lite adopter) | Print graceful upgrade message: "--full requires bassclef standard. Reason: /provision-deploy-host and /secrets-bootstrap are both standard-tier skills. Upgrade path: install bassclef standard." Continue Phases 1–3. | Phases 1–3 + both skills dispatched inline. |
|
|
1346
|
+
| `/onboard-repo --greenfield-from-intent` | Runs Path B via `/launch --local`. Lite-safe by design. | Same. |
|
|
1347
|
+
|
|
1348
|
+
Per canvas 2026-07-19-bassclef-lite Q6 Option E — one SKILL.md file,
|
|
1349
|
+
same name in both tiers, body carries runtime tier awareness with
|
|
1350
|
+
graceful degrade.
|
|
1351
|
+
|
|
1352
|
+
##### Interactive prompt (when no flag)
|
|
1353
|
+
|
|
1354
|
+
After Phase 3 completes, agent surfaces follow-on prompts. Prompts are
|
|
1355
|
+
gated on artifact existence and the deploy-host prompt
|
|
1356
|
+
uses honest platform framing:
|
|
1357
|
+
|
|
1358
|
+
```bash
|
|
1359
|
+
# Check for substrate.secrets.md (bassclef#961) — silently skip the
|
|
1360
|
+
# secrets prompt if the manifest doesn't exist. No point prompting an
|
|
1361
|
+
# adopter to bootstrap secrets when they haven't declared any.
|
|
1362
|
+
HAS_SECRETS_MANIFEST=0
|
|
1363
|
+
if [ -f substrate.secrets.md ]; then
|
|
1364
|
+
HAS_SECRETS_MANIFEST=1
|
|
1365
|
+
fi
|
|
1366
|
+
```
|
|
1367
|
+
|
|
1368
|
+
Then surface (deploy-host always; secrets only when manifest present):
|
|
1369
|
+
|
|
1370
|
+
```
|
|
1371
|
+
Substrate scaffolded. One or two follow-on steps remain before /launch
|
|
1372
|
+
runs cleanly end-to-end:
|
|
1373
|
+
|
|
1374
|
+
1. /provision-deploy-host — provisions a preview deploy host. Tested
|
|
1375
|
+
today with AWS Amplify; other platforms (Vercel, Netlify, Cloudflare
|
|
1376
|
+
Pages, GCP, Azure) ship via adapter PRs. If you want a platform that
|
|
1377
|
+
doesn't ship yet, file a ticket — or build the adapter (it's a single
|
|
1378
|
+
shell script following `scripts/adapters/deploy/amplify.sh` as the
|
|
1379
|
+
reference). The provision takes ~1-2h, mostly waiting. Required
|
|
1380
|
+
before /launch can bind a subdomain on the chosen host. Skip if this
|
|
1381
|
+
repo opts out of preview deployment (hosting_platform: none) or if
|
|
1382
|
+
you want to provision later.
|
|
1383
|
+
|
|
1384
|
+
2. /secrets-bootstrap — audits + bootstraps env credentials per
|
|
1385
|
+
substrate.secrets.md. Required before /launch, /deploy-prod, or
|
|
1386
|
+
/journal push. Skip if creds are already known-good.
|
|
1387
|
+
|
|
1388
|
+
Run /provision-deploy-host now? [Y/n/skip]
|
|
1389
|
+
Run /secrets-bootstrap now? [Y/n/skip]
|
|
1390
|
+
```
|
|
1391
|
+
|
|
1392
|
+
When `HAS_SECRETS_MANIFEST=0` (no substrate.secrets.md on disk), the
|
|
1393
|
+
agent OMITS step 2 entirely + the second prompt — no "(likely no-op)"
|
|
1394
|
+
hedge, no prompt asking the adopter to bootstrap secrets they haven't
|
|
1395
|
+
declared. The numbered list collapses to "One follow-on step remains".
|
|
1396
|
+
|
|
1397
|
+
Each `Y` triggers the inline dispatch (operator-confirms any destructive
|
|
1398
|
+
substep — AWS calls, env writes). Each `n` defers to a later session.
|
|
1399
|
+
Each `skip` persists in `substrate.config.md` so re-running /onboard-repo
|
|
1400
|
+
on this repo doesn't re-prompt for that step.
|
|
1401
|
+
|
|
1402
|
+
The deploy-host prompt wording matters: cold adopters reading it should
|
|
1403
|
+
understand bassclef's posture on multi-platform support without
|
|
1404
|
+
operator coaching. "Tested with AWS Amplify; other platforms via
|
|
1405
|
+
adapter PRs" reads as honest (we have one tested path + a clear
|
|
1406
|
+
contribution route) instead of overpromising. Filing a ticket for an
|
|
1407
|
+
unsupported platform is invited, not gated.
|
|
1408
|
+
|
|
1409
|
+
##### Skip-state persistence
|
|
1410
|
+
|
|
1411
|
+
When operator chooses `skip` (not `n`) for a follow-on step, the agent
|
|
1412
|
+
writes one of these fields to `substrate.config.md`:
|
|
1413
|
+
|
|
1414
|
+
```yaml
|
|
1415
|
+
# === Onboarding follow-on skip state (bassclef#522) ===
|
|
1416
|
+
#
|
|
1417
|
+
# Set by /onboard-repo when the operator explicitly skips a follow-on
|
|
1418
|
+
# step. Re-runs of /onboard-repo do NOT re-prompt for skipped steps;
|
|
1419
|
+
# operator can dispatch the underlying skill directly when ready, or
|
|
1420
|
+
# unset the field to re-enable the prompt.
|
|
1421
|
+
onboarding_deploy_host_skipped: true # set when operator answers 'skip'
|
|
1422
|
+
onboarding_secrets_skipped: true # set when operator answers 'skip'
|
|
1423
|
+
```
|
|
1424
|
+
|
|
1425
|
+
`n` (decline-this-time) does NOT persist — re-runs re-prompt because the
|
|
1426
|
+
operator didn't say skip-permanently.
|
|
1427
|
+
|
|
1428
|
+
`Y` sets the per-platform provisioning indicator (e.g., `amplify_app_id`) on success. Chain pre-flight Check 6 reads that indicator when /launch dispatches. Without it, /launch BLOCKs with three-path remediation. The two flags pair well. `--with-deploy-host` pre-empts the BLOCK. The default flow lets the BLOCK surface the missing setup.
|
|
1429
|
+
|
|
1430
|
+
##### Composes with
|
|
1431
|
+
|
|
1432
|
+
| Skill | Role |
|
|
1433
|
+
|---|---|
|
|
1434
|
+
| `/provision-deploy-host` | Inline dispatch when `--with-deploy-host` or interactive `Y`. Populates `amplify_app_id` (or platform-equivalent indicator). |
|
|
1435
|
+
| `/secrets-bootstrap` | Inline dispatch when `--with-secrets` or interactive `Y`. Audits creds against `substrate.secrets.md`. |
|
|
1436
|
+
| `/bind-subdomain <subdomain>` | Separate dispatch — not chained from /onboard-repo (subdomain choice is repo-specific; no good default). Run after deploy host provisioned. |
|
|
1437
|
+
| `/launch` | First substantive dispatch after onboarding completes. Chain pre-flight Check 6 verifies the provisioning indicator before variant generation runs. |
|
|
1438
|
+
|
|
1439
|
+
#### Phase 3.6 — Closing handoff
|
|
1440
|
+
|
|
1441
|
+
After Phase 3 (and Phase 3.5 if any flag fired), Path A surfaces a
|
|
1442
|
+
closing handoff. Two templates — adopter-mode and operator-mode —
|
|
1443
|
+
mirror the same split documented at `.claude/skills/launch/SKILL.md`
|
|
1444
|
+
Phase 14b.
|
|
1445
|
+
|
|
1446
|
+
##### Adopter-mode auto-chain (default when context signals cold-adopter)
|
|
1447
|
+
|
|
1448
|
+
Cold-adopter signals: `/onboard-repo` was invoked from a fresh
|
|
1449
|
+
directory (no prior chronicle / no whereami / no iteration-goal), OR
|
|
1450
|
+
the `--greenfield-from-intent "<paragraph>"` flag was used. In either
|
|
1451
|
+
shape, the agent has a paragraph in hand (either from the flag or
|
|
1452
|
+
asked at Phase 1 as part of the "what is this repo for?" prompt).
|
|
1453
|
+
|
|
1454
|
+
The adopter-mode handoff template re-uses that paragraph and offers
|
|
1455
|
+
the build:
|
|
1456
|
+
|
|
1457
|
+
```
|
|
1458
|
+
Your repo is wired. Two things you can do next — pick one:
|
|
1459
|
+
|
|
1460
|
+
1. Build something now. I'll take the paragraph you gave me earlier
|
|
1461
|
+
("<INTENT_PARAGRAPH>") and run /launch --local. About 4 minutes
|
|
1462
|
+
later you'll have four clickable mock directions to pick from on
|
|
1463
|
+
your phone or laptop. After you pick a direction, I'll write the
|
|
1464
|
+
formal artifacts + the app code for that direction only (~15 min
|
|
1465
|
+
total). You'll have a working local version to play with.
|
|
1466
|
+
|
|
1467
|
+
2. Stop here and come back later. I'll save your spot. When you come
|
|
1468
|
+
back, just open Claude Code in this repo and say "/launch --local"
|
|
1469
|
+
to pick up where we left off.
|
|
1470
|
+
|
|
1471
|
+
Build now? [Y/n]
|
|
1472
|
+
```
|
|
1473
|
+
|
|
1474
|
+
`Y` triggers `/launch --local "<INTENT_PARAGRAPH>"` inline in the
|
|
1475
|
+
same session — no context switch, no second dispatch. `n` writes
|
|
1476
|
+
the paragraph to `docs/whereami.md` under "Pending intent" so the
|
|
1477
|
+
next session's `/sprint` surfaces it.
|
|
1478
|
+
|
|
1479
|
+
Substitute `<INTENT_PARAGRAPH>` with the actual paragraph (from
|
|
1480
|
+
`--greenfield-from-intent` flag value OR from the Phase 1 "what is
|
|
1481
|
+
this repo for?" prompt — operator confirms it's still accurate before
|
|
1482
|
+
the auto-chain fires).
|
|
1483
|
+
|
|
1484
|
+
The adopter-mode handoff **skips entirely**:
|
|
1485
|
+
- "Run /sprint to orient" — adopter has no work in flight to orient
|
|
1486
|
+
to
|
|
1487
|
+
- "Run /whereami" — same
|
|
1488
|
+
- Bare command names (`/launch`) without the plain-English explanation
|
|
1489
|
+
of what /launch produces
|
|
1490
|
+
|
|
1491
|
+
##### Operator-mode handoff (non-cold-adopter context)
|
|
1492
|
+
|
|
1493
|
+
This mode fires when cold-adopter signals are absent. Signals absent means: the repo has prior chronicles, whereami is populated, OR the operator passed `--no-auto-chain`. The agent uses this wording:
|
|
1494
|
+
|
|
1495
|
+
```
|
|
1496
|
+
Your bassclef is ready.
|
|
1497
|
+
|
|
1498
|
+
What landed this session:
|
|
1499
|
+
- Skills, rules, and hooks synced from bassclef
|
|
1500
|
+
- GitHub labels + branch protection set up
|
|
1501
|
+
- Session-start wiring wired
|
|
1502
|
+
|
|
1503
|
+
Best single next move — try /sprint in a fresh session. It reads
|
|
1504
|
+
your current state and proposes the next work.
|
|
1505
|
+
|
|
1506
|
+
Other useful next moves:
|
|
1507
|
+
- /whereami — current state in one glance
|
|
1508
|
+
- /launch <tier> "<paragraph>" — start a new feature; see /launch
|
|
1509
|
+
SKILL.md for sizes + flags
|
|
1510
|
+
- /launch --local "<paragraph>" — same as above but writes artifacts
|
|
1511
|
+
to disk + serves the gallery on localhost (no vendor accounts
|
|
1512
|
+
needed)
|
|
1513
|
+
|
|
1514
|
+
Run any of those in a fresh session.
|
|
1515
|
+
```
|
|
1516
|
+
|
|
1517
|
+
Operator-mode keeps a hard break between onboard and build. Operators often onboard a repo as one task. They pick up build work later in a fresh session.
|
|
1518
|
+
|
|
1519
|
+
##### Composes with
|
|
1520
|
+
|
|
1521
|
+
| Skill | How it composes |
|
|
1522
|
+
|---|---|
|
|
1523
|
+
| `/launch --local` | Adopter-mode auto-chain dispatch. Inline in same session. |
|
|
1524
|
+
| `/sprint` | Operator-mode orientation skill. Surfaces "Pending intent" if `n` was chosen for the build-now prompt. |
|
|
1525
|
+
| `/whereami` | Same. |
|
|
1526
|
+
|
|
1527
|
+
#### Phase 4 — Bassclef-side matrix PRs
|
|
1528
|
+
|
|
1529
|
+
**Phase 4 retired under bassclef goal 2026-05-03-consumer-bassclef-sync-rollout WU-7.**
|
|
1530
|
+
|
|
1531
|
+
Under thin-pointer architecture (Phase 2.1 + 2.4 above), the `bassclef-template-sync.yml` workflow is deleted (no more auto-PRs). The `bassclef-s3-publish.yml` URL-refresh matrix is unused by thin-pointer (no `.bassclef-url`); a follow-on issue tracks its retirement separately.
|
|
1532
|
+
|
|
1533
|
+
**No matrix-PR step is needed for new consumers.** The thin-pointer dispatcher reads from `.bassclef-source.json` directly; bassclef's matrix list is no longer the source of truth for which consumers receive substrate updates — every consumer fetches HEAD on every session-start.
|
|
1534
|
+
|
|
1535
|
+
Skip this phase entirely. Phase 5 (Verify) below validates that the consumer is correctly wired without any bassclef-side matrix change.
|
|
1536
|
+
|
|
1537
|
+
#### Historical note
|
|
1538
|
+
|
|
1539
|
+
Pre-2026-05-03, this phase added the new consumer to BOTH `bassclef-s3-publish.yml` and `bassclef-template-sync.yml` matrices. The 2026-04-18 lesson (#166 caught a one-of-two miss after #158) drove the bassclef-workflow-parity rule. With both workflows retired/unused under thin-pointer, the parity rule no longer applies to this surface.
|
|
1540
|
+
|
|
1541
|
+
## Verify (acceptance)
|
|
1542
|
+
|
|
1543
|
+
Acceptance differs per path.
|
|
1544
|
+
|
|
1545
|
+
### Path A — verify everything's wired correctly (after Phases 1–3 + 3.5 if flagged)
|
|
1546
|
+
|
|
1547
|
+
- [ ] `gh label list --repo "$REPO"` shows all 11 standard labels
|
|
1548
|
+
- [ ] `gh api repos/$REPO/branches/$DEFAULT_BRANCH/protection` returns 200
|
|
1549
|
+
- [ ] (If applicable) `gh api repos/$REPO/environments/prod` shows required_reviewers
|
|
1550
|
+
- [ ] `.claude/hooks/bassclef-sync.sh` is executable
|
|
1551
|
+
- [ ] `.claude/settings.json` validates as JSON
|
|
1552
|
+
- [ ] `substrate.config.md` has no `TODO:` markers (or operator approved deferring them)
|
|
1553
|
+
- [ ] `.bassclef-source.json` exists, validates against bassclef schema (`standards/bassclef-source/schemas/bassclef-source.schema.json`), references a valid `BASSCLEF_TOKEN` env var, and has an explicit `auto_sync` value (true OR false) set by the adopter at Phase 2.4 — silence is not deferral here
|
|
1554
|
+
- [ ] Running the sync hook produces no errors; banner shows `### BASSCLEF SUBSTRATE — SYNCED`; symlinks resolve
|
|
1555
|
+
- [ ] `CLAUDE.md` exists with at least a one-paragraph description
|
|
1556
|
+
- [ ] `docs/whereami.md` exists with phase + iteration filled in
|
|
1557
|
+
- [ ] **(Retired)** ~~Bassclef PR opened with both workflow matrices updated~~ — Phase 4 retired under bassclef goal 2026-05-03 WU-7
|
|
1558
|
+
- [ ] Test session in target repo: `claude` → SessionStart hook fires → no BLOCKED items from missing substrate
|
|
1559
|
+
|
|
1560
|
+
### Path B acceptance — after Phases B.1–B.5
|
|
1561
|
+
|
|
1562
|
+
- [ ] Generated task list had at most 5 tasks (Phase B.1–B.5); no Path A phases queued
|
|
1563
|
+
- [ ] No `gh` calls fired during the dispatch
|
|
1564
|
+
- [ ] No `gh repo create`, no `gh api .../environments/prod`, no branch-protection writes
|
|
1565
|
+
- [ ] `.git/` exists with at least one commit
|
|
1566
|
+
- [ ] `.claude/hooks/bassclef-sync.sh` is executable
|
|
1567
|
+
- [ ] `.claude/settings.json` validates as JSON
|
|
1568
|
+
- [ ] `substrate.config.md` exists with `hosting_platform: none`
|
|
1569
|
+
- [ ] `CLAUDE.md` exists
|
|
1570
|
+
- [ ] `/launch --local --voice-input` was the final dispatch (not extended `/launch` and not `/build` and not `/launch-preview`)
|
|
1571
|
+
- [ ] `/launch` emitted a `localhost:80xx` URL pointing at the generated gallery
|
|
1572
|
+
- [ ] Operator opened the URL and saw the variants gallery
|
|
1573
|
+
|
|
1574
|
+
## What NOT to do
|
|
1575
|
+
|
|
1576
|
+
- **Do not** restore Phase 4 — the bassclef-template-sync.yml workflow is retired. Adding new consumers to a deleted matrix produces nothing.
|
|
1577
|
+
- **Do not** vendor `bassclef-sync.template.sh` directly — that was the pre-2026-05-03 pattern. The thin-pointer dispatcher reads `.bassclef-source.json` and fetches bassclef's CURRENT logic at fire-time. Vendoring reproduces the drift problem WU-7 retires.
|
|
1578
|
+
- **Do not** auto-merge the bassclef-side PR. Bassclef is the trust
|
|
1579
|
+
root; every matrix change needs operator review.
|
|
1580
|
+
- **Do not** hardcode the presigned URL anywhere — read from
|
|
1581
|
+
`.bassclef-url` at runtime.
|
|
1582
|
+
- **Do not** copy `.claude/settings.local.json` from another repo — it's
|
|
1583
|
+
machine-local per-operator permission grants.
|
|
1584
|
+
- **Do not** commit secrets. The sync URL expires in ~7 days; don't
|
|
1585
|
+
treat it as a secret, but don't commit long-lived tokens either.
|
|
1586
|
+
- **Do not** mix Path A and Path B in one dispatch. If the operator picked
|
|
1587
|
+
Path B at the prereqs-missing menu, skip every Path A phase — don't
|
|
1588
|
+
generate a task list that walks Phase 1.1 / 1.2 / 1.3 / 2.4 / 3.5 /
|
|
1589
|
+
Phase 4. The whole point of Path B is the ≤5-step task list ending
|
|
1590
|
+
in `/launch --local --voice-input`. Any Path A task that leaks into a
|
|
1591
|
+
Path B run is the bassclef#934 regression.
|
|
1592
|
+
- **Do not** chain `/build` or `/launch-preview` after Path B's final
|
|
1593
|
+
dispatch. Path B's deliverable is the localhost URL `/launch --local`
|
|
1594
|
+
emits; the extended chain belongs to operators with vendor bindings.
|
|
1595
|
+
|
|
1596
|
+
## Relationship to other skills
|
|
1597
|
+
|
|
1598
|
+
- **`/autonomous start`** — runs AFTER `/onboard-repo` to set up iteration
|
|
1599
|
+
scaffolding. `/onboard-repo` does the one-time wiring; `/autonomous
|
|
1600
|
+
start` does the per-iteration setup.
|
|
1601
|
+
- **`/substrate-check`** — validates substrate wiring AFTER onboarding.
|
|
1602
|
+
Run it as a post-flight check.
|
|
1603
|
+
- **`/promote`** — once onboarded, the new repo can file
|
|
1604
|
+
`bassclef-evolution` issues. The labels bootstrapped in Phase 1.1
|
|
1605
|
+
make them scannable.
|
|
1606
|
+
|
|
1607
|
+
## Source
|
|
1608
|
+
|
|
1609
|
+
Ritual observed 4x on 2026-04-17: four consumer repos (refresh). Each took ~15 minutes by hand.
|
|
1610
|
+
Codified here so the fifth, sixth, and nth take ~3 minutes.
|
|
1611
|
+
|
|
1612
|
+
Closes bassclef #164.
|
|
1613
|
+
|
|
1614
|
+
Path B added 2026-06-13. Cold-adopter smoke test on `new-recipe-test`
|
|
1615
|
+
2026-06-13 01:30am showed PR #931's edit to the flag-row description
|
|
1616
|
+
was cosmetic — `--greenfield-from-intent` still queued 12 standard
|
|
1617
|
+
onboarding tasks because the Procedure was monolithic. Refactor splits
|
|
1618
|
+
Procedure into Path A (standard, unchanged) and Path B (≤5 steps, no
|
|
1619
|
+
GitHub-remote operations, ends in `/launch --local --voice-input`).
|
|
1620
|
+
Closes bassclef#934.
|
|
1621
|
+
|
|
1622
|
+
## Output discipline
|
|
1623
|
+
|
|
1624
|
+
Dispatch `/kiss words --rewrite` on your skill output before you return it. See `standards/skill-output-discipline.md` for the contract.
|