@thebassclef/lite 1.1.1 → 1.2.0-alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (135) hide show
  1. package/dist/cli.cjs +23 -6
  2. package/dist/cli.js +23 -6
  3. package/dist/index.cjs +1 -1
  4. package/dist/index.d.ts +1 -1
  5. package/dist/index.js +1 -1
  6. package/dist/lite/.claude/bassclef-configs.jsonc +56 -0
  7. package/dist/lite/.claude/bassclef-orientation.md +120 -0
  8. package/dist/lite/.claude/hooks/adr-discipline-check.sh +132 -0
  9. package/dist/lite/.claude/hooks/atomic-pr-check.sh +169 -0
  10. package/dist/lite/.claude/hooks/auto-save-idle.sh +51 -0
  11. package/dist/lite/.claude/hooks/bassclef-sync.sh +51 -13
  12. package/dist/lite/.claude/hooks/bet-doc-gate.sh +283 -0
  13. package/dist/lite/.claude/hooks/bug-diagnosis.sh +64 -0
  14. package/dist/lite/.claude/hooks/destructive-command-guard.sh +136 -0
  15. package/dist/lite/.claude/hooks/file-rename-discipline-check.sh +147 -0
  16. package/dist/lite/.claude/hooks/hook-classifier-canary.sh +158 -0
  17. package/dist/lite/.claude/hooks/kiss-default-check.sh +129 -0
  18. package/dist/lite/.claude/hooks/multi-tenancy-check.sh +83 -0
  19. package/dist/lite/.claude/hooks/oo-ad-entry-point-check.sh +216 -0
  20. package/dist/lite/.claude/hooks/operator-private-path-check.sh +203 -0
  21. package/dist/lite/.claude/hooks/pattern-annotation-validate.sh +142 -0
  22. package/dist/lite/.claude/hooks/plain-english-steering.sh +15 -1
  23. package/dist/lite/.claude/hooks/post-write-trace.sh +66 -0
  24. package/dist/lite/.claude/hooks/pr-body-scrub-check.sh +446 -0
  25. package/dist/lite/.claude/hooks/pre-commit-identifier-leak-scrub.sh +137 -0
  26. package/dist/lite/.claude/hooks/pre-gh-pr-body-scrub.sh +192 -0
  27. package/dist/lite/.claude/hooks/pre-gh-pr-title-scrub.sh +172 -0
  28. package/dist/lite/.claude/hooks/role-entry-gate.sh +115 -0
  29. package/dist/lite/.claude/hooks/save-state.sh +268 -0
  30. package/dist/lite/.claude/hooks/session-reflection.d/08-settings-drift.sh +8 -1
  31. package/dist/lite/.claude/hooks/session-reflection.d/10-abrupt-stop-recovery.sh +52 -0
  32. package/dist/lite/.claude/hooks/session-reflection.d/55-orientation-gate.sh +40 -4
  33. package/dist/lite/.claude/hooks/session-reflection.d/80-hook-heartbeat-check.sh +12 -5
  34. package/dist/lite/.claude/hooks/session-reflection.d/81-hook-manifest-staleness.sh +18 -2
  35. package/dist/lite/.claude/hooks/session-reflection.d/91-npm-version-drift.sh +54 -0
  36. package/dist/lite/.claude/hooks/session-reflection.d/tests/10-abrupt-stop-recovery.test.sh +95 -0
  37. package/dist/lite/.claude/hooks/session-reflection.sh +62 -15
  38. package/dist/lite/.claude/hooks/tool-failure-diagnosis.sh +50 -0
  39. package/dist/lite/.claude/luminaries/andrej-karpathy.md +165 -0
  40. package/dist/lite/.claude/luminaries/dave-gray.md +155 -0
  41. package/dist/lite/.claude/luminaries/gary-klein.md +166 -0
  42. package/dist/lite/.claude/luminaries/kaoru-ishikawa.md +162 -0
  43. package/dist/lite/.claude/luminaries/lean-product-canvas.md +33 -0
  44. package/dist/lite/.claude/luminaries/luke-wroblewski.md +224 -0
  45. package/dist/lite/.claude/luminaries/ryan-singer.md +113 -0
  46. package/dist/lite/.claude/luminaries/steve-krug.md +168 -0
  47. package/dist/lite/.claude/luminaries/tony-ulwick.md +134 -0
  48. package/dist/lite/.claude/rules/arc-level-orientation-before-leaf.md +60 -0
  49. package/dist/lite/.claude/rules/architect-review-discipline.md +71 -0
  50. package/dist/lite/.claude/rules/auto-fix-criteria.md +126 -0
  51. package/dist/lite/.claude/rules/bassclef-hook-drift-blocker.md +144 -0
  52. package/dist/lite/.claude/rules/bassclef-models-discovery.md +107 -0
  53. package/dist/lite/.claude/rules/bassclef-workflow-parity.md +104 -0
  54. package/dist/lite/.claude/rules/cost-governance.md +154 -0
  55. package/dist/lite/.claude/rules/file-rename-discipline.md +95 -0
  56. package/dist/lite/.claude/rules/mechanism-fidelity.md +88 -0
  57. package/dist/lite/.claude/rules/prototype-production-coupling.md +125 -0
  58. package/dist/lite/.claude/rules/quick-fix-criteria.md +90 -0
  59. package/dist/lite/.claude/rules/session-artifacts.md +30 -0
  60. package/dist/lite/.claude/rules/sibling-smoke-after-substrate-change.md +107 -0
  61. package/dist/lite/.claude/rules/substrate-as-system.md +67 -0
  62. package/dist/lite/.claude/rules/usability.md +22 -0
  63. package/dist/lite/.claude/settings.json +20 -0
  64. package/dist/lite/.claude/skills/agent-research-spawn/SKILL.md +100 -0
  65. package/dist/lite/.claude/skills/architect-review/SKILL.md +201 -0
  66. package/dist/lite/.claude/skills/auto-fix/SKILL.md +297 -0
  67. package/dist/lite/.claude/skills/autonomous/SKILL.md +300 -0
  68. package/dist/lite/.claude/skills/bind-subdomain/SKILL.md +232 -0
  69. package/dist/lite/.claude/skills/canvas/SKILL.md +41 -0
  70. package/dist/lite/.claude/skills/deploy-prod/SKILL.md +106 -0
  71. package/dist/lite/.claude/skills/docs-sync/SKILL.md +188 -0
  72. package/dist/lite/.claude/skills/eisenhower/SKILL.md +273 -0
  73. package/dist/lite/.claude/skills/empathy-map/SKILL.md +168 -0
  74. package/dist/lite/.claude/skills/frontend-design/SKILL.md +53 -0
  75. package/dist/lite/.claude/skills/interview-me/SKILL.md +171 -0
  76. package/dist/lite/.claude/skills/journal-export/SKILL.md +293 -0
  77. package/dist/lite/.claude/skills/jtbd-tasks/SKILL.md +203 -0
  78. package/dist/lite/.claude/skills/objectory-decompose/SKILL.md +256 -0
  79. package/dist/lite/.claude/skills/pick-luminaries/SKILL.md +100 -0
  80. package/dist/lite/.claude/skills/pre-mortem/SKILL.md +180 -0
  81. package/dist/lite/.claude/skills/prototype-gallery/SKILL.md +264 -0
  82. package/dist/lite/.claude/skills/provision-deploy-host/SKILL.md +257 -0
  83. package/dist/lite/.claude/skills/quick-fix/SKILL.md +273 -0
  84. package/dist/lite/.claude/skills/release/SKILL.md +311 -0
  85. package/dist/lite/.claude/skills/release-notes/SKILL.md +202 -0
  86. package/dist/lite/.claude/skills/rfc/SKILL.md +222 -0
  87. package/dist/lite/.claude/skills/riff-prototypes/SKILL.md +637 -0
  88. package/dist/lite/.claude/skills/secrets-bootstrap/SKILL.md +209 -0
  89. package/dist/lite/.claude/skills/skill/SKILL.md +304 -0
  90. package/dist/lite/.claude/skills/smoke-test/SKILL.md +100 -0
  91. package/dist/lite/.claude/skills/state/SKILL.md +204 -0
  92. package/dist/lite/.claude/skills/substrate-check/SKILL.md +218 -0
  93. package/dist/lite/.claude/skills/synthetic-user/SKILL.md +381 -0
  94. package/dist/lite/.claude/skills/task-scenarios/SKILL.md +105 -0
  95. package/dist/lite/.claude/skills/tier-dependency-audit/SKILL.md +139 -0
  96. package/dist/lite/.claude/skills/ux-migration/SKILL.md +424 -0
  97. package/dist/lite/.claude/skills/value-prop-canvas/SKILL.md +297 -0
  98. package/dist/lite/README.md +5 -1
  99. package/dist/lite/gitignore +6 -0
  100. package/dist/lite/lib/bassclef-dir-resolver.sh +85 -0
  101. package/dist/lite/lib/clone-failure-classifier.sh +59 -0
  102. package/dist/lite/lib/fixture-builder.sh +190 -0
  103. package/dist/lite/lib/fresh-install-check.sh +49 -0
  104. package/dist/lite/lib/hook-heartbeat.sh +0 -1
  105. package/dist/lite/lib/mechanism-fidelity.sh +569 -0
  106. package/dist/lite/lib/npm-version-check.sh +112 -0
  107. package/dist/lite/lib/preview-state.sh +229 -0
  108. package/dist/lite/lib/session-rescue.sh +0 -1
  109. package/dist/lite/scripts/generate-lite-manifest.sh +145 -4
  110. package/dist/lite/scripts/lite-manifest-drift-check.sh +5 -1
  111. package/dist/lite/standards/architect-review-discipline.md +222 -0
  112. package/dist/lite/standards/bassclef-platform.md +249 -0
  113. package/dist/lite/standards/bassclef-test-repos.md +97 -0
  114. package/dist/lite/standards/bassclef-wiring-manifest.json +25 -1
  115. package/dist/lite/standards/cold-adopter-harness.md +205 -0
  116. package/dist/lite/standards/data-management.md +135 -0
  117. package/dist/lite/standards/frontend-stack/nextjs-prisma.md +124 -0
  118. package/dist/lite/standards/lite-manifest-schema-changes.md +27 -0
  119. package/dist/lite/standards/lite-manifest.json +1456 -14
  120. package/dist/lite/standards/mechanism-fidelity.md +205 -0
  121. package/dist/lite/standards/operator-private-discipline.md +200 -0
  122. package/dist/lite/standards/operator-to-public-flow.md +195 -0
  123. package/dist/lite/standards/prototype-gallery.md +251 -0
  124. package/dist/lite/standards/pseudonym-key-schema.md +109 -0
  125. package/dist/lite/standards/sibling-validation-checklist.md +181 -0
  126. package/dist/lite/standards/slack-notifications.md +161 -0
  127. package/dist/lite/standards/synthetic-user-testing.md +173 -0
  128. package/dist/lite/standards/vendor-bindings.md +165 -0
  129. package/dist/lite/standards/vendor-plugins/frontend-design.md +66 -0
  130. package/dist/lite/standards/vpc-fit-validation.md +167 -0
  131. package/dist/lite/templates/gallery-yml.md +113 -0
  132. package/dist/lite/templates/product-canvas.md +169 -0
  133. package/dist/lite/templates/value-prop-canvas.md +180 -0
  134. package/package.json +3 -3
  135. /package/dist/lite/{whereami.md → docs/whereami.md} +0 -0
package/dist/cli.cjs CHANGED
@@ -318,6 +318,12 @@ const GENERATED_BY = "@thebassclef/lite";
318
318
  function manifestTemplate(input) {
319
319
  const value = {
320
320
  schema_version: MANIFEST_SHAPE_VERSION,
321
+ // Top-level `version` — read by the v0.45.0 npm-version-drift hook
322
+ // (fragment 91 under session-reflection) via lib/npm-version-check.sh
323
+ // `jq -r '.version // ""' "$manifest"`. Duplicates
324
+ // $bassclef.generated_by_version on purpose — the hook does not walk
325
+ // into $bassclef. Per bassclef-upstream#1749.
326
+ version: input.pkgVersion,
321
327
  $bassclef: {
322
328
  template: "init.manifest.json",
323
329
  manifest_schema_version: MANIFEST_SCHEMA_VERSION,
@@ -1076,13 +1082,13 @@ function dispatchSubstrateCopy(targetDir, force, verbose, dryRun, allowRoot, say
1076
1082
  );
1077
1083
  const copiedCount = copiedHookEntries.length;
1078
1084
  const declaredCount = result.hookCount;
1079
- const failedCount = result.refused.length + result.errored.length;
1085
+ const erroredCount = result.errored.length;
1080
1086
  const userScope = copiedHookEntries.filter((e) => e.scope === "user").length;
1081
1087
  const projectScope = copiedHookEntries.filter((e) => e.scope === "project").length;
1082
1088
  const scopeSuffix = userScope + projectScope > 0 ? ` ${projectScope} in <repo>/${HOOKS_SUBPATH.replace(/\/$/, "")}, ${userScope} in ~/${HOOKS_SUBPATH.replace(/\/$/, "")}.` : "";
1083
- if (failedCount > 0) {
1089
+ if (erroredCount > 0) {
1084
1090
  say(
1085
- `bassclef init: Installed ${copiedCount} of ${declaredCount} hooks (${RESOLVED_TIER} tier).${scopeSuffix} ${failedCount} failed — see errors above. Rerun bassclef init to retry.
1091
+ `bassclef init: Installed ${copiedCount} of ${declaredCount} hooks (${RESOLVED_TIER} tier).${scopeSuffix} ${erroredCount} failed — see errors above. Rerun bassclef init to retry.
1086
1092
  `
1087
1093
  );
1088
1094
  } else {
@@ -1151,10 +1157,12 @@ function dispatchSubstrateCopy(targetDir, force, verbose, dryRun, allowRoot, say
1151
1157
  `
1152
1158
  );
1153
1159
  }
1154
- say(
1155
- `bassclef init: ${result.refused.length} files refused (path collision).` + (result.refused.length > 0 ? ` Use --force to overwrite existing files.` : ``) + `
1160
+ if (result.refused.length > 0) {
1161
+ say(
1162
+ `bassclef init: ${result.refused.length} files refused (path collision). Use --force to overwrite existing files.
1156
1163
  `
1157
- );
1164
+ );
1165
+ }
1158
1166
  if (verbose && result.erroredMessages) {
1159
1167
  for (const msg of result.erroredMessages) {
1160
1168
  process.stderr.write(` substrate: ${msg}
@@ -2011,6 +2019,12 @@ Proceed?`,
2011
2019
  const errored = copyResult.errored;
2012
2020
  const newManifest = {
2013
2021
  schema_version: MANIFEST_SHAPE_VERSION,
2022
+ // Top-level `.version` — read by the v0.45.0 npm-version-drift hook
2023
+ // (fragment 91 under session-reflection) via lib/npm-version-check.sh
2024
+ // `jq -r '.version // ""' "$manifest"`. Duplicates
2025
+ // $bassclef.generated_by_version on purpose — the hook does not walk
2026
+ // into $bassclef. Per bassclef-upstream#1749; bassclef-cli#129.
2027
+ version: index.version,
2014
2028
  $bassclef: {
2015
2029
  template: "init.manifest.json",
2016
2030
  manifest_schema_version: "0.1.0",
@@ -2178,6 +2192,9 @@ Run \`bassclef migrate --help\` for migrate options + the upgrade paths.
2178
2192
  Version: ${index.version}
2179
2193
  Docs: https://github.com/sunj-labs/bassclef-cli
2180
2194
  `;
2195
+ for (const stream of [process.stdout, process.stderr]) {
2196
+ stream._handle?.setBlocking?.(true);
2197
+ }
2181
2198
  async function main(argv) {
2182
2199
  const first = argv[0];
2183
2200
  if (first === void 0 || first === "--help" || first === "-h" || first === "help") {
package/dist/cli.js CHANGED
@@ -295,6 +295,12 @@ const GENERATED_BY = "@thebassclef/lite";
295
295
  function manifestTemplate(input) {
296
296
  const value = {
297
297
  schema_version: MANIFEST_SHAPE_VERSION,
298
+ // Top-level `version` — read by the v0.45.0 npm-version-drift hook
299
+ // (fragment 91 under session-reflection) via lib/npm-version-check.sh
300
+ // `jq -r '.version // ""' "$manifest"`. Duplicates
301
+ // $bassclef.generated_by_version on purpose — the hook does not walk
302
+ // into $bassclef. Per bassclef-upstream#1749.
303
+ version: input.pkgVersion,
298
304
  $bassclef: {
299
305
  template: "init.manifest.json",
300
306
  manifest_schema_version: MANIFEST_SCHEMA_VERSION,
@@ -1053,13 +1059,13 @@ function dispatchSubstrateCopy(targetDir, force, verbose, dryRun, allowRoot, say
1053
1059
  );
1054
1060
  const copiedCount = copiedHookEntries.length;
1055
1061
  const declaredCount = result.hookCount;
1056
- const failedCount = result.refused.length + result.errored.length;
1062
+ const erroredCount = result.errored.length;
1057
1063
  const userScope = copiedHookEntries.filter((e) => e.scope === "user").length;
1058
1064
  const projectScope = copiedHookEntries.filter((e) => e.scope === "project").length;
1059
1065
  const scopeSuffix = userScope + projectScope > 0 ? ` ${projectScope} in <repo>/${HOOKS_SUBPATH.replace(/\/$/, "")}, ${userScope} in ~/${HOOKS_SUBPATH.replace(/\/$/, "")}.` : "";
1060
- if (failedCount > 0) {
1066
+ if (erroredCount > 0) {
1061
1067
  say(
1062
- `bassclef init: Installed ${copiedCount} of ${declaredCount} hooks (${RESOLVED_TIER} tier).${scopeSuffix} ${failedCount} failed — see errors above. Rerun bassclef init to retry.
1068
+ `bassclef init: Installed ${copiedCount} of ${declaredCount} hooks (${RESOLVED_TIER} tier).${scopeSuffix} ${erroredCount} failed — see errors above. Rerun bassclef init to retry.
1063
1069
  `
1064
1070
  );
1065
1071
  } else {
@@ -1128,10 +1134,12 @@ function dispatchSubstrateCopy(targetDir, force, verbose, dryRun, allowRoot, say
1128
1134
  `
1129
1135
  );
1130
1136
  }
1131
- say(
1132
- `bassclef init: ${result.refused.length} files refused (path collision).` + (result.refused.length > 0 ? ` Use --force to overwrite existing files.` : ``) + `
1137
+ if (result.refused.length > 0) {
1138
+ say(
1139
+ `bassclef init: ${result.refused.length} files refused (path collision). Use --force to overwrite existing files.
1133
1140
  `
1134
- );
1141
+ );
1142
+ }
1135
1143
  if (verbose && result.erroredMessages) {
1136
1144
  for (const msg of result.erroredMessages) {
1137
1145
  process.stderr.write(` substrate: ${msg}
@@ -1988,6 +1996,12 @@ Proceed?`,
1988
1996
  const errored = copyResult.errored;
1989
1997
  const newManifest = {
1990
1998
  schema_version: MANIFEST_SHAPE_VERSION,
1999
+ // Top-level `.version` — read by the v0.45.0 npm-version-drift hook
2000
+ // (fragment 91 under session-reflection) via lib/npm-version-check.sh
2001
+ // `jq -r '.version // ""' "$manifest"`. Duplicates
2002
+ // $bassclef.generated_by_version on purpose — the hook does not walk
2003
+ // into $bassclef. Per bassclef-upstream#1749; bassclef-cli#129.
2004
+ version,
1991
2005
  $bassclef: {
1992
2006
  template: "init.manifest.json",
1993
2007
  manifest_schema_version: "0.1.0",
@@ -2155,6 +2169,9 @@ Run \`bassclef migrate --help\` for migrate options + the upgrade paths.
2155
2169
  Version: ${version}
2156
2170
  Docs: https://github.com/sunj-labs/bassclef-cli
2157
2171
  `;
2172
+ for (const stream of [process.stdout, process.stderr]) {
2173
+ stream._handle?.setBlocking?.(true);
2174
+ }
2158
2175
  async function main(argv) {
2159
2176
  const first = argv[0];
2160
2177
  if (first === void 0 || first === "--help" || first === "-h" || first === "help") {
package/dist/index.cjs CHANGED
@@ -1,4 +1,4 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
- const version = "1.1.1";
3
+ const version = "1.2.0-alpha.1";
4
4
  exports.version = version;
package/dist/index.d.ts CHANGED
@@ -1,2 +1,2 @@
1
- export declare const version: "1.1.1";
1
+ export declare const version: "1.2.0-alpha.1";
2
2
  //# sourceMappingURL=index.d.ts.map
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- const version = "1.1.1";
1
+ const version = "1.2.0-alpha.1";
2
2
  export {
3
3
  version
4
4
  };
@@ -0,0 +1,56 @@
1
+ // tier: lite
2
+ // bassclef adopter config — tune substrate rules from one file.
3
+ // Reference schema: standards/bassclef-configs-schema.md
4
+ // Every block below matches what a substrate rule reads. Values shown
5
+ // are the defaults; delete a block and the default kicks in.
6
+ {
7
+ // What your project runs. Frontend framework the /shadcn-first and
8
+ // /new-dependency-check rules key off. Common values: "vite-react",
9
+ // "nextjs", "remix", "vue", "svelte", "none".
10
+ "tech_stack": {
11
+ "frontend": "none"
12
+ },
13
+
14
+ // Prose discipline. The kiss-check Stop hook watches your writing
15
+ // for jargon. Value "true" = advisory (findings to stderr, no block).
16
+ // Value "strict" = BLOCK the stop, forcing a rewrite turn.
17
+ // Value false = disabled.
18
+ "prose_discipline": {
19
+ "kiss_words_turn_prose": true
20
+ },
21
+
22
+ // Where /promote sends proposals. Two shapes:
23
+ // "<owner>/<repo>" — gh issue create --repo <value>
24
+ // "email:<address>" — mailto: URL printed for adopter to send
25
+ // Absent → /promote files in the current repo (backward-compat).
26
+ // "promote_target": "your-org/your-repo",
27
+
28
+ // Testing tiers per .claude/rules/testing-tier-config.md. Global
29
+ // floor sets the baseline for every path that no matcher covers.
30
+ // Tier 0 = strict TDD (test-first, BLOCK on missing). Tier 1 =
31
+ // test-with (WARN on missing). Tier 2 = smoke test only. Tier 3 =
32
+ // manual verify (no test discipline).
33
+ "testing": {
34
+ "global_floor": 1,
35
+ "path_matchers": [
36
+ { "match": ".claude/rules/*.md", "tier": 3 },
37
+ { "match": "state/markers/*/*", "tier": 3 },
38
+ { "match": "chronicle/*.md", "tier": 3 },
39
+ { "match": "docs/iteration-bets/*.md", "tier": 3 },
40
+ { "match": "docs/decompositions/*.md", "tier": 3 }
41
+ ]
42
+ },
43
+
44
+ // /longrun preset picker per .claude/skills/longrun/SKILL.md. Values:
45
+ // "converged" — plan doc drives; lean prep output
46
+ // "exploratory" — scan-table with no cards until asked
47
+ // "reversible-small" — three-chunk compact for small scope
48
+ // "auto" — picker decides per session signals (default)
49
+ "longrun": {
50
+ "preset": "auto"
51
+ },
52
+
53
+ // Adopter defaults surface. Reserved for future rules. Absent =
54
+ // downstream rules keep their own defaults.
55
+ "adopter_defaults": {}
56
+ }
@@ -0,0 +1,120 @@
1
+ ---
2
+ tier: lite
3
+ purpose: adopter orientation — auto-imported into adopter CLAUDE.md via @.claude/bassclef-orientation.md per ADR-032 + Anthropic @import convention
4
+ last_updated: 2026-06-22
5
+ bet: 2026-06-22b-dispatcher-hardening-rename-orientation (WU-5)
6
+ ---
7
+
8
+ # Bassclef orientation
9
+
10
+ You've inherited the bassclef substrate. This file loads into every session via `@import` from your CLAUDE.md.
11
+
12
+ The substrate is a stable set of skills, rules, hooks, luminaries, agents, and standards that pin discipline at decision boundaries. It evolves upstream in `sunj-labs/bassclef-upstream`; you receive releases from public `sunj-labs/bassclef` via `bassclef-sync` at every session start.
13
+
14
+ ## What you have
15
+
16
+ | Layer | Where | Discover |
17
+ |---|---|---|
18
+ | Skills (invocable workflows) | `.claude/skills/<name>/SKILL.md` | `/skills` |
19
+ | Rules (auto-loaded context) | `.claude/rules/*.md` | All loaded every session via `additionalDirectories` |
20
+ | Luminaries (design + authoring lenses) | `.claude/luminaries/*.md` | `/luminary` |
21
+ | Agents (specialist roles) | `.claude/agents/*.md` | Used by `/autonomous`, `/build`, `/longrun` |
22
+ | Hooks (mechanical enforcement) | `.claude/hooks/*.sh` | Fire automatically; see `/hooks` |
23
+ | Standards (reference docs) | `standards/*.md` | Cited by rules + skills |
24
+ | ADRs (architectural decisions) | `architecture/decisions/ADR-*.md` | Read before changing what they govern |
25
+
26
+ ## Cross-cutting gates — fire across every phase
27
+
28
+ | Gate | When to run |
29
+ |---|---|
30
+ | `/temperance` | Before first edit on a branch + at scope-decision boundaries |
31
+ | `/diagnose` | Before writing any fix code |
32
+ | `/quick-fix` | Localized, obvious, ≤10 lines, no blast radius |
33
+ | `/auto-fix` | Narrow non-trivial bugs within Builder's safe zone |
34
+ | `/verify` | After each task before committing |
35
+ | `/whats-the-plan` | Before any ≥3-skill chain |
36
+ | `/kiss` | When scope bloats or prose drifts toward jargon |
37
+ | `/luminary` | Before ADR authoring + at any design-decision boundary |
38
+
39
+ ## SDLC flow
40
+
41
+ ```
42
+ Canvas → Spec → Design → Issue → Branch → PR → CI → Deploy → Observe
43
+ ```
44
+
45
+ For UI work, run the UX translation chain during Design:
46
+
47
+ ```
48
+ JTBD → HTA → Entity Model → State Diagrams → Sequence Diagrams → /decompose
49
+ ```
50
+
51
+ ## Conventions
52
+
53
+ - **Commits**: `type: description` per `.claude/rules/commit-conventions.md`
54
+ - **PR titles**: ≤72 chars per `.claude/rules/pr-title-shape.md`
55
+ - **PR bodies**: open with `**Problem (≤500 chars):**` per `.claude/rules/pr-body-shape.md`
56
+ - **Specs** reference their source canvas or issue
57
+ - **New standards** go in `standards/`, not inline in other docs
58
+
59
+ ## What NOT to do
60
+
61
+ - **Don't break adopters** (ADR-031). Every change to a downstream-observable surface ships with a compat shim, migration manifest, and changelog entry.
62
+ - **Don't make architectural or design decisions without consulting luminaries.** Design without a named lens drifts toward generic; the lens is what gives you a position to defend in review.
63
+ - **Don't release without checking prior open PRs first.** Cumulative stacks create cascade failures.
64
+ - **Don't write source before tests** on Tier 0 paths (per `.claude/rules/testing-tier-config.md`).
65
+ - **Don't auto-apply discipline changes without `/temperance`** at scope boundaries.
66
+ - **Don't conflate "propose" with "execute".** When operator says "propose," "options," "path forward" — wait for explicit go signal.
67
+ - **Don't use bassclef-internal jargon** in operator-facing prose. Plain English at grade-10 reading level.
68
+ - **Don't push to main without PR review** even on solo workflows.
69
+
70
+ ## Luminaries at design boundaries
71
+
72
+ The substrate ships ~38 luminaries (Linus, Beck, Brooks, Norman, Cooper, Tufte, Nygard, Vernon, Ousterhout, Hyrum, Myers, Hoare, Saltzer-Schroeder, Parnas, Fowler, and more). They pin specific disciplines — they aren't decoration.
73
+
74
+ When to consult:
75
+
76
+ - **Architectural decisions (ADRs)** — pin 1-3 luminaries; the ADR cites their lens
77
+ - **Iteration bets** — declare a luminary map (primary pair + extended pairs per surface in scope) per `.claude/rules/iteration-bet-brief-completeness.md`
78
+ - **UI surfaces** — Norman / Cooper / Tufte / Morville per the surface's job
79
+ - **Cross-cutting design choices** — Bulkhead (Nygard) + Anticorruption Layer (Vernon) + Deep Modules (Ousterhout) converge often
80
+
81
+ `/luminary <slug>` previews one; `/luminary` browses by discipline. Skills with UI / architecture surfaces pin their luminary map in frontmatter — read the skill before invoking.
82
+
83
+ ## Luminaries at the keyboard — not just the whiteboard
84
+
85
+ Beyond ADRs and iteration bets, luminaries inform code authoring directly. **Pick ONE dominant lens per scope** (bet / WU / surface) and check your work against it. Background discipline fires automatically — don't manually verify against each.
86
+
87
+ | Scope | Default dominant authoring luminary |
88
+ |---|---|
89
+ | Most code | @luminary kent-beck (TDD rhythm + test list + simple design) |
90
+ | Bash hooks + scripts | @luminary saltzer-schroeder (7 defensive disciplines) |
91
+ | State-spine writes | @luminary tony-hoare (pre/postconditions; contracts) |
92
+ | UI components | Whichever pair the prototype pinned |
93
+ | Architecture refactoring | @luminary john-ousterhout (deep modules) + @luminary martin-fowler (refactoring patterns) |
94
+
95
+ **Background discipline** (fires automatically — don't manually verify):
96
+
97
+ - **Rules cite anchor luminaries** explaining why each rule exists. Read the rule; the anchor tells you when the rule generalizes vs when an edge case applies
98
+ - **Hooks enforce specific luminary-anchored disciplines mechanically** — `testing-tier-enforce.sh` (Beck), `state-validate.sh` (Hoare), `substrate-clarity-gate.sh` (context engineering)
99
+ - **`@pattern <catalog-path>` annotation** in source code when you CONSCIOUSLY instantiate a named pattern (GoF, Fowler, Vernon DDD). Not every class — only the ones that EMBODY a pattern as a design choice. Per `.claude/rules/pattern-annotation.md`
100
+
101
+ ## Luminary matching — tier ladder
102
+
103
+ `/pick-luminaries` picks luminary fits for an intent paragraph. Adopter capability scales with what keys you provide:
104
+
105
+ - **lite** — stub / deterministic mode; no keys required; for cold-start adopters + CI + tests
106
+ - **standard** — single LLM call picks from the full catalog; semantic matching; needs `ANTHROPIC_API_KEY` (default in bassclef-core)
107
+ - **ultra** — embedding shortlist (Voyage `voyage-3-lite`) + LLM judge re-rank; faster + per-candidate confidence; needs `ANTHROPIC + VOYAGE` keys; load `bassclef-upstream` via `additionalDirectories` to activate
108
+
109
+ Pre-computed catalog embeddings (~230KB) ship with bassclef-upstream so ultra-tier Voyage cost is per-query intent embedding only.
110
+
111
+ Pick the tier that matches your trust + budget. Upgrade path is additive — no migration required to move lite → standard → ultra. See bassclef-upstream#262 for ultra-tier downstream-readiness status; bassclef-upstream#263 for the future "plus" tier (local embedding model, no Voyage key).
112
+
113
+ ## Discovery commands
114
+
115
+ - `/sprint` — what's in flight + what's next
116
+ - `/whereami` — current project state
117
+ - `/substrate-check` — validate substrate wiring
118
+ - `/skills` — phase-grouped skill catalog
119
+ - `/luminary` — design-lens catalog
120
+ - `/hooks` — mechanical-enforcement layer
@@ -0,0 +1,132 @@
1
+ #!/bin/bash
2
+ # tier: lite
3
+ # adr-discipline-check.sh — PreToolUse hook on architectural decision boundaries
4
+ #
5
+ # Detects "load-bearing" architectural decisions via path-shape heuristics and
6
+ # refuses unless an ADR marker at state/markers/adr/<decision-slug>.md exists
7
+ # linking to a real ADR file under docs/adrs/ or architecture/decisions/.
8
+ #
9
+ # Per bassclef#1149 + WU-11 of bet 2026-06-20e.
10
+ # Override: SKIP_ADR_CHECK=1 (logged via trace-helper).
11
+
12
+ set -euo pipefail
13
+
14
+ # ============================================================================
15
+ # Read stdin JSON from Claude Code harness
16
+ # ============================================================================
17
+ PAYLOAD=$(cat 2>/dev/null || echo '{}')
18
+
19
+ TOOL_NAME=$(echo "$PAYLOAD" | jq -r '.tool_name // empty' 2>/dev/null)
20
+ FILE_PATH=$(echo "$PAYLOAD" | jq -r '.tool_input.file_path // empty' 2>/dev/null)
21
+
22
+ # ============================================================================
23
+ # Filters: only fire on Write/Edit/MultiEdit
24
+ # ============================================================================
25
+ case "$TOOL_NAME" in
26
+ Write|Edit|MultiEdit) ;;
27
+ *) exit 0 ;;
28
+ esac
29
+
30
+ if [ -z "$FILE_PATH" ]; then
31
+ exit 0
32
+ fi
33
+
34
+ # ============================================================================
35
+ # Override check
36
+ # ============================================================================
37
+ if [ "${SKIP_ADR_CHECK:-0}" = "1" ]; then
38
+ TRACE_HELPER="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/trace-helper.sh"
39
+ if [ -f "$TRACE_HELPER" ]; then
40
+ bash "$TRACE_HELPER" override "adr-discipline-check" "SKIP_ADR_CHECK=1 on $FILE_PATH" 2>/dev/null || true
41
+ fi
42
+ exit 0
43
+ fi
44
+
45
+ # ============================================================================
46
+ # Architectural-decision detection via path-shape heuristics
47
+ # ============================================================================
48
+ IS_ARCHITECTURAL=0
49
+ DECISION_SLUG=""
50
+
51
+ case "$FILE_PATH" in
52
+ */prisma/schema.prisma|prisma/schema.prisma)
53
+ IS_ARCHITECTURAL=1
54
+ DECISION_SLUG="schema-change"
55
+ ;;
56
+ */docker-compose*.yml|docker-compose*.yml|*/docker-compose*.yaml|docker-compose*.yaml)
57
+ IS_ARCHITECTURAL=1
58
+ DECISION_SLUG="deployment-topology-change"
59
+ ;;
60
+ */middleware.ts|src/middleware.ts|*/middleware.py|*/middleware.rb)
61
+ IS_ARCHITECTURAL=1
62
+ DECISION_SLUG="middleware-change"
63
+ ;;
64
+ */alembic/versions/*.py|*/db/migrate/*.rb|*/migrations/*.go)
65
+ IS_ARCHITECTURAL=1
66
+ DECISION_SLUG="schema-migration"
67
+ ;;
68
+ esac
69
+
70
+ # package.json / pyproject.toml / Gemfile / go.mod / Cargo.toml — only fire on Write (new file or rewrite)
71
+ # Detecting "dependency-add" inside Edit would require diff parsing; deferred to V2
72
+ if [ "$TOOL_NAME" = "Write" ]; then
73
+ case "$FILE_PATH" in
74
+ */package.json|package.json|*/pyproject.toml|pyproject.toml|*/Gemfile|Gemfile|*/go.mod|go.mod|*/Cargo.toml|Cargo.toml)
75
+ IS_ARCHITECTURAL=1
76
+ DECISION_SLUG="dependency-manifest-change"
77
+ ;;
78
+ esac
79
+ fi
80
+
81
+ if [ "$IS_ARCHITECTURAL" -eq 0 ]; then
82
+ exit 0
83
+ fi
84
+
85
+ # ============================================================================
86
+ # Marker check: state/markers/adr/<decision-slug>.md must exist
87
+ # ============================================================================
88
+ REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
89
+ MARKER_DIR="$REPO_ROOT/state/markers/adr"
90
+
91
+ # Explicit marker required — generic "recent ADR in dir" is too permissive
92
+ # (other ADRs unrelated to this decision class would silently satisfy)
93
+ if find "$MARKER_DIR" -maxdepth 1 -name "${DECISION_SLUG}*.md" 2>/dev/null | grep -q .; then
94
+ exit 0
95
+ fi
96
+
97
+ # ============================================================================
98
+ # Block: no marker + no recent ADR
99
+ # ============================================================================
100
+ cat >&2 <<EOF
101
+ 🛑 adr-discipline-check — BLOCK (bassclef#1149)
102
+
103
+ You're about to make a load-bearing architectural decision: ${DECISION_SLUG}
104
+
105
+ Path: ${FILE_PATH}
106
+
107
+ Architectural decisions require an ADR (Architecture Decision Record)
108
+ per Michael Nygard's lifecycle: proposed → accepted → deprecated → superseded.
109
+
110
+ Write one before proceeding:
111
+
112
+ 1. Copy the template:
113
+ cp standards/adr-template.md docs/adrs/ADR-NNN-<slug>.md
114
+ (or architecture/decisions/ADR-NNN-<slug>.md per your project layout)
115
+
116
+ 2. Fill Context + Decision + Status + Consequences sections.
117
+
118
+ 3. Touch the marker:
119
+ mkdir -p ${MARKER_DIR}
120
+ touch ${MARKER_DIR}/${DECISION_SLUG}-<your-slug>.md
121
+
122
+ 4. Retry the original change.
123
+
124
+ Override (logged): SKIP_ADR_CHECK=1 <command>
125
+
126
+ When to use override:
127
+ - Trivial revert of a previously-decided architectural change
128
+ - Emergency rescue when the hook itself misclassifies
129
+ - One-shot migration script that touches many architectural files
130
+ EOF
131
+
132
+ exit 2
@@ -0,0 +1,169 @@
1
+ #!/bin/bash
2
+ # tier: lite
3
+ # Atomic-PR Check — fires on Bash tool calls matching "git push" patterns.
4
+ # Counts distinct WU-N tags in commit messages on the branch. BLOCKs the
5
+ # push if multiple step tags exist unless an iteration goal declares
6
+ # `bundle: true` in frontmatter.
7
+ #
8
+ # Phase II of 8-phase staircase: Trim the Fat (bassclef#382).
9
+ # The methodology rule at .claude/rules/pr-strategy.md is the reasoning;
10
+ # this hook is the mechanical enforcement.
11
+ #
12
+ # Exit codes:
13
+ # 0 — allow (no WU tags, single WU tag, bundle:true in matching bet,
14
+ # or override)
15
+ # 2 — block (multi-step branch without bundle:true)
16
+ #
17
+ # Override: SKIP_ATOMIC_PR_CHECK=1 to bypass (logged via trace-helper)
18
+ #
19
+ # Rule: .claude/rules/pr-strategy.md
20
+ # Issue: bassclef#382
21
+
22
+ set +e # never crash the tool call; fall through to allow on any unexpected error
23
+
24
+ INPUT=$(cat)
25
+ TOOL_NAME=$(jq <<< "$INPUT" -r '.tool_name // ""' 2>/dev/null)
26
+ COMMAND=$(jq <<< "$INPUT" -r '.tool_input.command // ""' 2>/dev/null)
27
+
28
+ # Only fire on Bash with a git push command
29
+ if [ "$TOOL_NAME" != "Bash" ]; then
30
+ exit 0
31
+ fi
32
+
33
+ # Match git push patterns (allow flags like -u, --force, etc.)
34
+ case "$COMMAND" in
35
+ *"git push"*)
36
+ : # match — continue
37
+ ;;
38
+ *)
39
+ exit 0
40
+ ;;
41
+ esac
42
+
43
+ # Override hatch — log and allow
44
+ if [ "${SKIP_ATOMIC_PR_CHECK:-0}" = "1" ]; then
45
+ SCRIPT_DIR="$(cd "$(dirname "$0")" 2>/dev/null && pwd)"
46
+ if [ -n "$SCRIPT_DIR" ] && [ -f "$SCRIPT_DIR/trace-helper.sh" ]; then
47
+ source "$SCRIPT_DIR/trace-helper.sh" 2>/dev/null || true
48
+ trace_log "atomic-pr-check" "OVERRIDE git push" 2>/dev/null || true
49
+ fi
50
+ exit 0
51
+ fi
52
+
53
+ # Find the repo root
54
+ REPO_ROOT=$(git rev-parse --show-toplevel 2>/dev/null)
55
+ if [ -z "$REPO_ROOT" ]; then
56
+ exit 0 # not in a git repo — allow
57
+ fi
58
+ cd "$REPO_ROOT" || exit 0
59
+
60
+ # Get current branch name
61
+ BRANCH=$(git branch --show-current 2>/dev/null)
62
+ if [ -z "$BRANCH" ]; then
63
+ exit 0 # detached HEAD or no branch — allow
64
+ fi
65
+
66
+ # Skip the check on main branch and bare branch names
67
+ case "$BRANCH" in
68
+ main|master|HEAD)
69
+ exit 0
70
+ ;;
71
+ esac
72
+
73
+ # Find commits on this branch not yet on main
74
+ # If main is not available locally, fall back to origin/main, then to all commits
75
+ BASE_REF=""
76
+ if git rev-parse --verify main >/dev/null 2>&1; then
77
+ BASE_REF="main"
78
+ elif git rev-parse --verify origin/main >/dev/null 2>&1; then
79
+ BASE_REF="origin/main"
80
+ fi
81
+
82
+ if [ -n "$BASE_REF" ]; then
83
+ COMMITS=$(git log --format="%s%n%b" "${BASE_REF}..HEAD" 2>/dev/null)
84
+ else
85
+ # No base ref available — check the last 10 commits as a heuristic
86
+ COMMITS=$(git log -10 --format="%s%n%b" HEAD 2>/dev/null)
87
+ fi
88
+
89
+ # Extract distinct WU-N tags from commit messages
90
+ # Match patterns: "WU-1", "WU-2a", "WU-3", etc. (case-sensitive; expects WU-)
91
+ WU_TAGS=$(echo "$COMMITS" | grep -oE '\bWU-[0-9]+[a-z]?\b' | sort -u)
92
+
93
+ # Count distinct WU tags. If WU_TAGS is empty, count is 0.
94
+ if [ -z "$WU_TAGS" ]; then
95
+ WU_COUNT=0
96
+ else
97
+ WU_COUNT=$(echo "$WU_TAGS" | wc -l | tr -d ' ')
98
+ fi
99
+
100
+ # 0 or 1 WU tags — allow
101
+ if [ "$WU_COUNT" -le 1 ]; then
102
+ exit 0
103
+ fi
104
+
105
+ # Multi-WU branch — check for bundle:true in any matching goal doc
106
+ ALLOWED=0
107
+ ITERATION_BETS_DIR="docs/iteration-bets"
108
+ if [ -d "$ITERATION_BETS_DIR" ]; then
109
+ # Look for goal docs that mention any of the step tags AND have bundle: true
110
+ for bet in "$ITERATION_BETS_DIR"/*.md; do
111
+ [ -f "$bet" ] || continue
112
+ # Check if bet has bundle: true in frontmatter
113
+ if awk '/^---$/{c++; next} c==1 && /^bundle:[[:space:]]*true/{print "yes"; exit}' "$bet" | grep -q "yes"; then
114
+ # Verify this goal covers at least one of the step tags
115
+ for wu in $WU_TAGS; do
116
+ if grep -qE "\\b${wu}\\b" "$bet"; then
117
+ ALLOWED=1
118
+ break 2
119
+ fi
120
+ done
121
+ fi
122
+ done
123
+ fi
124
+
125
+ if [ "$ALLOWED" = "1" ]; then
126
+ exit 0
127
+ fi
128
+
129
+ # BLOCK — multi-step branch without bundle:true
130
+ WU_LIST=$(echo "$WU_TAGS" | tr '\n' ' ' | sed 's/ $//')
131
+
132
+ cat >&2 <<EOF
133
+
134
+ ============================================
135
+ 🛑 ATOMIC-PR GATE — BLOCKED 🛑
136
+ ============================================
137
+
138
+ Branch: $BRANCH
139
+ Commits found tagged with multiple steps: $WU_LIST
140
+
141
+ Per .claude/rules/pr-strategy.md, the default is one step per branch
142
+ per PR (atomic). Multiple WUs in one branch defeats the rollback
143
+ discipline — reverting one step also reverts the others.
144
+
145
+ Three resolution paths:
146
+
147
+ 1. Split — create a separate branch per step and a PR for each.
148
+ Operator merges in dependency order.
149
+
150
+ 2. Bundle — if these WUs genuinely belong together (single concern,
151
+ tight coupling, emergency hotfix), declare it explicitly:
152
+ add 'bundle: true' to the iteration goal's frontmatter, then push.
153
+
154
+ 3. Override (rare) — SKIP_ATOMIC_PR_CHECK=1 git push ...
155
+ Logged to trace. Use only for genuine bypass cases.
156
+
157
+ Per pr-strategy.md the bundle option requires one of:
158
+ - Single logical concern across files (changes don't compile if split)
159
+ - Tight coupling that breaks atomic /verify
160
+ - Emergency hotfix
161
+ - Explicit operator request
162
+
163
+ Rule: .claude/rules/pr-strategy.md
164
+ Issue: bassclef#382
165
+ ============================================
166
+
167
+ EOF
168
+
169
+ exit 2