@thebassclef/lite 0.1.0 → 0.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (163) hide show
  1. package/dist/cli.cjs +40 -6
  2. package/dist/cli.js +40 -6
  3. package/dist/index.cjs +1 -1
  4. package/dist/index.d.ts +1 -1
  5. package/dist/index.js +1 -1
  6. package/package.json +1 -1
  7. package/substrate/.bassclef/lite-manifest.json +999 -92
  8. package/substrate/.claude/hooks/longrun-prep-compounding-axis-check.sh +492 -0
  9. package/substrate/.claude/hooks/longrun-prep-compounding-sequence-check.sh +492 -0
  10. package/substrate/.claude/hooks/pre-commit-gate.sh +1 -2
  11. package/substrate/.claude/hooks/turn-prose-kiss-check.sh +30 -1
  12. package/substrate/.claude/luminaries/glenford-myers.md +230 -0
  13. package/substrate/.claude/luminaries/hunt-thomas.md +115 -0
  14. package/substrate/.claude/luminaries/hyrum-wright.md +94 -0
  15. package/substrate/.claude/luminaries/michael-feathers.md +2 -2
  16. package/substrate/.claude/luminaries/tony-hoare.md +170 -0
  17. package/substrate/.claude/luminaries/vaughn-vernon.md +50 -0
  18. package/substrate/.claude/luminaries/w-edwards-deming.md +158 -0
  19. package/substrate/.claude/rules/accessor-library-discipline.md +138 -0
  20. package/substrate/.claude/rules/adr-discipline.md +120 -0
  21. package/substrate/.claude/rules/api-conventions.md +125 -0
  22. package/substrate/.claude/rules/bootstrap-pair-discipline.md +141 -0
  23. package/substrate/.claude/rules/cold-adopter-harness-discipline.md +129 -0
  24. package/substrate/.claude/rules/compounding-axis-fresh-analysis.md +188 -0
  25. package/substrate/.claude/rules/compounding-sequence-fresh-analysis.md +188 -0
  26. package/substrate/.claude/rules/defensive-bash.md +68 -0
  27. package/substrate/.claude/rules/deferred-actions.md +233 -0
  28. package/substrate/.claude/rules/github-issue-flash-tweet.md +156 -0
  29. package/substrate/.claude/rules/hook-wire-on-author.md +103 -0
  30. package/substrate/.claude/rules/iteration-bet-brief-completeness.md +54 -0
  31. package/substrate/.claude/rules/lite-manifest-schema-change-discipline.md +3 -3
  32. package/substrate/.claude/rules/longrun-prep-plan-doc-compression.md +89 -0
  33. package/substrate/.claude/rules/loop-discipline.md +81 -0
  34. package/substrate/.claude/rules/manual-prod-approval.md +100 -0
  35. package/substrate/.claude/rules/marker-enrichment-discipline.md +99 -0
  36. package/substrate/.claude/rules/mobile-ephemeral-session.md +109 -0
  37. package/substrate/.claude/rules/new-dependency-check.md +51 -0
  38. package/substrate/.claude/rules/option-label-discipline.md +108 -0
  39. package/substrate/.claude/rules/pattern-annotation.md +100 -0
  40. package/substrate/.claude/rules/plain-english-discipline.md +11 -9
  41. package/substrate/.claude/rules/plan-enumeration-needs-value-props.md +211 -0
  42. package/substrate/.claude/rules/pr-title-shape.md +161 -0
  43. package/substrate/.claude/rules/prototype-workflow.md +65 -0
  44. package/substrate/.claude/rules/reserved-skill-names.md +123 -0
  45. package/substrate/.claude/rules/schema-management.md +49 -0
  46. package/substrate/.claude/rules/security.md +37 -0
  47. package/substrate/.claude/rules/skill-composition-declarations.md +124 -0
  48. package/substrate/.claude/rules/skill-description-clarity.md +247 -0
  49. package/substrate/.claude/rules/skill-procedure-step-list.md +137 -0
  50. package/substrate/.claude/rules/stuck-signal-diagnostic.md +140 -0
  51. package/substrate/.claude/rules/substrate-config-schema.md +98 -0
  52. package/substrate/.claude/rules/test-list-discipline.md +175 -0
  53. package/substrate/.claude/rules/test-sufficiency.md +210 -0
  54. package/substrate/.claude/rules/testing-tier-config.md +145 -0
  55. package/substrate/.claude/rules/testing.md +38 -0
  56. package/substrate/.claude/rules/turn-estimate-grounding.md +134 -0
  57. package/substrate/.claude/rules/visual-hierarchy.md +437 -0
  58. package/substrate/.claude/rules/we-dont-break-adopters.md +126 -0
  59. package/substrate/.claude/rules/wu-sequencing-compounds.md +145 -0
  60. package/substrate/.claude/skills/build/SKILL.md +1 -1
  61. package/substrate/.claude/skills/chronicle/SKILL.md +55 -0
  62. package/substrate/.claude/skills/clean-artifacts/SKILL.md +249 -0
  63. package/substrate/.claude/skills/decompose/SKILL.md +1 -1
  64. package/substrate/.claude/skills/diagnose/SKILL.md +1 -1
  65. package/substrate/.claude/skills/feynman/SKILL.md +90 -0
  66. package/substrate/.claude/skills/howdoi/SKILL.md +1 -1
  67. package/substrate/.claude/skills/ia-model/SKILL.md +1 -1
  68. package/substrate/.claude/skills/interaction-design/SKILL.md +1 -1
  69. package/substrate/.claude/skills/interpret-input/SKILL.md +8 -8
  70. package/substrate/.claude/skills/journal/SKILL.md +209 -0
  71. package/substrate/.claude/skills/kiss/SKILL.md +1 -1
  72. package/substrate/.claude/skills/launch/SKILL.md +14 -23
  73. package/substrate/.claude/skills/lean-canvas/SKILL.md +1 -1
  74. package/substrate/.claude/skills/longrun/SKILL.md +45 -8
  75. package/substrate/.claude/skills/luminary/SKILL.md +1 -1
  76. package/substrate/.claude/skills/ogilvy-writing-audit/SKILL.md +1 -1
  77. package/substrate/.claude/skills/onboard-repo/SKILL.md +143 -709
  78. package/substrate/.claude/skills/pattern-review/SKILL.md +1 -1
  79. package/substrate/.claude/skills/personas/SKILL.md +5 -5
  80. package/substrate/.claude/skills/promote/SKILL.md +1 -1
  81. package/substrate/.claude/skills/requirement/SKILL.md +1 -1
  82. package/substrate/.claude/skills/retro/SKILL.md +1 -1
  83. package/substrate/.claude/skills/riff/SKILL.md +1 -1
  84. package/substrate/.claude/skills/roadmap-reconcile/SKILL.md +1 -1
  85. package/substrate/.claude/skills/session-end/SKILL.md +1 -1
  86. package/substrate/.claude/skills/session-log/SKILL.md +3 -3
  87. package/substrate/.claude/skills/skills/SKILL.md +1 -1
  88. package/substrate/.claude/skills/spec/SKILL.md +1 -1
  89. package/substrate/.claude/skills/sprint/SKILL.md +1 -1
  90. package/substrate/.claude/skills/stage/SKILL.md +1 -1
  91. package/substrate/.claude/skills/state-a-problem/SKILL.md +1 -1
  92. package/substrate/.claude/skills/temperance/SKILL.md +1 -1
  93. package/substrate/.claude/skills/use-case/SKILL.md +1 -1
  94. package/substrate/.claude/skills/user-stories/SKILL.md +1 -1
  95. package/substrate/.claude/skills/value-prop/SKILL.md +1 -1
  96. package/substrate/.claude/skills/verify/SKILL.md +1 -1
  97. package/substrate/.claude/skills/visual-review/SKILL.md +503 -0
  98. package/substrate/.claude/skills/whats-the-plan/SKILL.md +202 -0
  99. package/substrate/.claude/skills/whereami/SKILL.md +2 -2
  100. package/substrate/CONTRIBUTING.md +1 -1
  101. package/substrate/README.md +5 -5
  102. package/substrate/lib/prose-scan-boundary.sh +171 -0
  103. package/substrate/lib/tier-check.sh +50 -1
  104. package/substrate/lib/tier-dependency-audit.sh +159 -4
  105. package/substrate/presence/install/bassclef-sync.template.sh +1 -1
  106. package/substrate/scripts/generate-lite-manifest.sh +21 -5
  107. package/substrate/standards/adr-template.md +86 -0
  108. package/substrate/standards/api-conventions/nextjs.md +84 -0
  109. package/substrate/standards/artifact-composition.md +209 -0
  110. package/substrate/standards/bash-hook-safety.md +246 -0
  111. package/substrate/standards/branch-stacking.md +408 -0
  112. package/substrate/standards/code-safety-principles.md +176 -0
  113. package/substrate/standards/composer-prerequisites.md +155 -0
  114. package/substrate/standards/dependency-discipline/cargo.md +39 -0
  115. package/substrate/standards/dependency-discipline/gem.md +43 -0
  116. package/substrate/standards/dependency-discipline/go-mod.md +41 -0
  117. package/substrate/standards/dependency-discipline/npm.md +42 -0
  118. package/substrate/standards/dependency-discipline/pip.md +42 -0
  119. package/substrate/standards/deployment-topology/ec2-tailscale.md +225 -0
  120. package/substrate/standards/deployment-topology.md +69 -0
  121. package/substrate/standards/docs-sync-allowlist.md +4 -4
  122. package/substrate/standards/domain-and-dns.md +145 -0
  123. package/substrate/standards/frontend-stack.md +67 -0
  124. package/substrate/standards/frontmatter-schema.md +154 -0
  125. package/substrate/standards/hook-injection-discipline.md +202 -0
  126. package/substrate/standards/hook-install-class.md +215 -0
  127. package/substrate/standards/input-handler-interface.md +152 -0
  128. package/substrate/standards/lite-manifest-schema-changes.md +60 -0
  129. package/substrate/standards/luminary-matching.md +105 -0
  130. package/substrate/standards/migration-discipline/active-record.md +50 -0
  131. package/substrate/standards/migration-discipline/alembic.md +43 -0
  132. package/substrate/standards/migration-discipline/gorm.md +50 -0
  133. package/substrate/standards/migration-discipline/prisma.md +53 -0
  134. package/substrate/standards/migration-discipline/sqlalchemy.md +51 -0
  135. package/substrate/standards/mobile-ephemeral-session.md +167 -0
  136. package/substrate/standards/model-routing-discipline.md +160 -0
  137. package/substrate/standards/persona-schema.md +229 -0
  138. package/substrate/standards/pluggable-luminaries.md +323 -0
  139. package/substrate/standards/pr-body-discipline.md +115 -0
  140. package/substrate/standards/preview-state-schema.md +189 -0
  141. package/substrate/standards/reserved-skill-names.md +120 -0
  142. package/substrate/standards/scannable-multi-option-output.md +261 -0
  143. package/substrate/standards/sdlc-gates/typescript.md +57 -0
  144. package/substrate/standards/session-board.md +256 -0
  145. package/substrate/standards/state-spine-contract.md +255 -0
  146. package/substrate/standards/steering-hints/kiss-words.md +11 -0
  147. package/substrate/standards/substrate-config-schema.md +267 -0
  148. package/substrate/standards/tier-dependency-analysis.md +1 -1
  149. package/substrate/standards/tier-tag-schema.md +1 -1
  150. package/substrate/standards/two-layer-config.md +99 -0
  151. package/substrate/standards/use-case-format.md +292 -0
  152. package/substrate/standards/user-story-invest.md +268 -0
  153. package/substrate/standards/velocity-and-appetite.md +229 -0
  154. package/substrate/standards/voice-input-pattern.md +119 -0
  155. package/substrate/standards/worktree-management.md +211 -0
  156. package/substrate/templates/chronicle-template.md +75 -0
  157. package/substrate/templates/memory-proposal-template.md +77 -0
  158. package/substrate/templates/persona-template.md +200 -0
  159. package/substrate/templates/pr-faq.md +45 -0
  160. package/substrate/templates/secret-rotation-template.md +162 -0
  161. package/substrate/templates/spec-template.md +131 -0
  162. package/substrate/templates/use-case-template.md +194 -0
  163. package/substrate/templates/user-story-template.md +107 -0
@@ -0,0 +1,202 @@
1
+ ---
2
+ tier: lite
3
+ name: whats-the-plan
4
+ description: "Declare the chain of skills you intend to run for the current task or next stretch of work. Invokable at any natural response point. Composes with /temperance (scope) and /sprint (ticket-level) \u2014 dispatch-path level."
5
+ problem: "Multi-skill chains dispatch without declaring the plan. Operator can't audit mid-flight."
6
+ value: "Declares the chain of skills you intend to run. Invokable before you start."
7
+ inputs: [Current task or scope description]
8
+ outputs: [Ordered skill chain, Rationale per step, Alternative chains]
9
+ user_invocable: true
10
+ disable_model_invocation: false
11
+ ---
12
+
13
+ # What's the Plan
14
+
15
+ Declare the sequence of skills, tool calls, and artifacts you intend
16
+ to produce for the current task. Stated **before** execution, not
17
+ retrospectively. Re-declared when the plan changes materially.
18
+
19
+ ## When to Invoke
20
+
21
+ - **Operator asks**: "what's the plan?", "how are you going to tackle this?", "show me the chain"
22
+ - **Operator types**: `/whats-the-plan`
23
+ - **Self-invoke** (before a non-trivial chain): when the next stretch of
24
+ work involves ≥3 skills OR touches production code OR spans ≥1 hour.
25
+ This is the analogue of `/temperance` firing on the first edit — but
26
+ for sequencing, not scope
27
+ - **Plan change mid-task**: when a skill output forces a swap (new
28
+ interface surfaces, test fails, operator redirects) — re-declare
29
+ with a `was → now` delta
30
+
31
+ ## What this skill is NOT
32
+
33
+ | Skill | Operates at | Time | Output |
34
+ |-------|-------------|------|--------|
35
+ | `/sprint` | Ticket/scope level | Session start | Issues + time budget + iteration name |
36
+ | `/temperance` | Approach/scope | Before edit | Right-thing + right-way questions |
37
+ | `/whats-the-plan` | **Dispatch path** | **Any natural response point** | **Ordered skill chain + swap-points** |
38
+ | `/chronicle` | Narrative | Session end | Retrospective log |
39
+
40
+ The four compose. A typical session:
41
+
42
+ ```
43
+ /sprint → "next: finish iteration X, ~60 turns"
44
+ /temperance → "building Y; right thing because Z; simplest path is W"
45
+ /whats-the-plan → "chain: /decompose → build → /verify → commit"
46
+ [execute]
47
+ /chronicle → "what happened, decisions, open threads"
48
+ ```
49
+
50
+ ## Procedure
51
+
52
+ ### 1. Read inputs
53
+
54
+ Before declaring, know:
55
+
56
+ - **Current task** — the thing operator just asked for, or the next
57
+ scope in the active iteration goal
58
+ - **Active iteration goal** — `docs/iteration-bets/` (latest) — governs
59
+ what's in-scope and what stop-points exist
60
+ - **Applicable gates** — any of: `/temperance`, `/diagnose`, `/verify`,
61
+ `/visual-review`, `/decompose` (per `sdlc-gates.md` and
62
+ `oo-ad-entry-point.md`)
63
+ - **Relevant rules** — `artifact-ingestion.md` dictates sources-read
64
+ block; `design-direction.md` dictates approval-respect; other rules
65
+ may insert steps (e.g., `prototype-workflow.md` inserts render +
66
+ confirm before commit for prototype edits)
67
+
68
+ ### 2. Enumerate the chain
69
+
70
+ List skills, tool calls, and artifact writes in execution order. Use
71
+ `→` between steps. Group by phase if the chain crosses phases.
72
+
73
+ ### 3. Name swap-points
74
+
75
+ A swap-point is a conditional fork: "if skill X produces finding Y,
76
+ insert skill Z before the next step." Swap-points are where the plan
77
+ may branch based on outputs you don't have yet.
78
+
79
+ List the top 2–3 swap-points the chain is sensitive to. More than 3
80
+ signals the chain is under-specified and needs shaping first.
81
+
82
+ ### 4. State stop conditions
83
+
84
+ Where does this chain end? Options:
85
+ - **Operator review point** — "stop before PR open"
86
+ - **Gate** — "stop at /verify output; commit blocks on green"
87
+ - **Natural boundary** — "one WS complete; next WS is separate chain"
88
+ - **Time budget limit** — "stop at 20 turns; re-shape if incomplete"
89
+
90
+ ### 5. State what's NOT in this chain
91
+
92
+ Adjacent work you're deliberately excluding. This is the sequencing
93
+ analogue of `/temperance`'s "what you're NOT doing" question.
94
+
95
+ ## Output format
96
+
97
+ ```
98
+ ## Plan (YYYY-MM-DD HH:MM UTC)
99
+
100
+ **Task**: [one-line description]
101
+ **Iteration**: [goal name, or "none — ad-hoc"]
102
+
103
+ **Chain**:
104
+ 1. /temperance — gate scope + approach
105
+ 2. /decompose — identify interfaces (if Construction)
106
+ 3. [build step] — edit [paths]
107
+ 4. /verify — match change type to verification
108
+ 5. commit — conventional message
109
+
110
+ **Swap-points**:
111
+ - If /decompose surfaces new cross-cutting concern → insert /pattern-review before build
112
+ - If /verify fails visual → insert /visual-review before commit
113
+ - If operator redirects scope → re-run /whats-the-plan with delta
114
+
115
+ **Stops at**: [operator review point / gate / natural boundary]
116
+ **Appetite**: ~N turns, ~M min
117
+ **Not in this chain**: [adjacent work excluded]
118
+ ```
119
+
120
+ ## Re-declare format
121
+
122
+ When the plan changes materially mid-task, emit a delta (not a full
123
+ re-print). Material change = new skill inserted, skill removed, or
124
+ stop-point moved. Trivial reordering within the declared chain does
125
+ not trigger re-declare.
126
+
127
+ ```
128
+ ## Plan update (YYYY-MM-DD HH:MM UTC)
129
+
130
+ **Was**: /temperance → /decompose → build → /verify → commit
131
+ **Now**: /temperance → /decompose → /pattern-review → build → /verify → /visual-review → commit
132
+
133
+ **Why**: /decompose surfaced [specific interface] — triggers
134
+ /pattern-review swap-point. /verify scope now includes UI, pulling
135
+ /visual-review in per post-build gate.
136
+ ```
137
+
138
+ ## Rules
139
+
140
+ - **Declare before execute**, not after. A plan declared after the
141
+ chain ran is a log entry, not a plan.
142
+ - **One plan per coherent task**, not one per turn. Multi-turn
143
+ execution under a single declared plan is the common case.
144
+ - **Re-declare on material change only**, not on every adjustment.
145
+ Chain chatter reduces the signal.
146
+ - **Plan must reference sources** (per `artifact-ingestion.md`) if the
147
+ chain involves producing a canvas, spec, ADR, or prototype. The
148
+ plan itself is a lightweight produce-ahead-of-execution artifact.
149
+ - **Skill chain steps presented to operator MUST follow
150
+ `.claude/rules/plan-enumeration-needs-value-props.md`** — each step
151
+ in the chain carries a tweet (claim + why-it-matters), not a bare
152
+ skill name. Bare "/temperance → /diagnose → /verify" is not a plan;
153
+ each step needs to say what it buys.
154
+ - **Do not declare a plan you know you won't follow**. If the chain is
155
+ genuinely uncertain, say so: "Plan unclear; running /temperance +
156
+ /diagnose first to shape." That is itself a valid plan.
157
+
158
+ ## Chronicle integration
159
+
160
+ When the session chronicle is written, the main-task plan declaration
161
+ SHOULD be linked or quoted. Plan → execution → reference-back is the
162
+ loop that makes plan declaration load-bearing rather than theatrical.
163
+
164
+ If the plan changed during execution, chronicle notes the delta
165
+ (which swap-points fired, which didn't).
166
+
167
+ ## Operator-facing behavior
168
+
169
+ When operator types `/whats-the-plan`:
170
+ - If a plan was declared recently (same task, no material change):
171
+ re-display the current plan
172
+ - If no plan exists or task has shifted: run the procedure and declare
173
+ - If operator asks "what's the plan?" in conversation: same procedure,
174
+ slight framing adjustment — phrase as response, not bassclef output
175
+ block, but include the chain + swap-points + stops-at
176
+
177
+ ## Relationship to other rules
178
+
179
+ - `sdlc-gates.md` — declared plan must include gate skills where
180
+ applicable; hook-enforced gates are not optional plan steps
181
+ - `artifact-ingestion.md` — plans that will produce generative output
182
+ must name sources the chain will read
183
+ - `design-direction.md` — plan changes after operator approval require
184
+ operator reconciliation, not agent-unilateral re-planning
185
+ - `oo-ad-entry-point.md` — Construction chains that edit `src/` must
186
+ include `/decompose` or explicit trivial-work deferral
187
+ - `iteration-goal-brief-completeness.md` — plans delegated to subagents
188
+ are briefs; this skill outputs the brief
189
+
190
+ ## Enforcement
191
+
192
+ V1: methodology-level. Operator invokes or Claude self-invokes based
193
+ on the triggers above.
194
+
195
+ V2 (future): rule `plan-declaration-required.md` + hook that fires
196
+ BLOCKED when a ≥3-skill chain executes without a preceding
197
+ `/whats-the-plan` output in session. Not in v1 scope — shipping the
198
+ skill first lets us learn where auto-fire helps vs. spams.
199
+
200
+ ## Output discipline
201
+
202
+ Dispatch `/kiss words --rewrite` on your skill output before you return it. See `standards/skill-output-discipline.md` for the contract.
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: whereami
3
- description: "Show project state in one glance phase, active goal, agents in flight, subsystem progress, gate checklist, freshness. Reads docs/whereami.md. Run at session start before /sprint to orient."
3
+ description: "Show project state in one glance \u2014 phase, active goal, agents in flight, subsystem progress, gate checklist, freshness. Reads docs/whereami.md. Run at session start before /sprint to orient."
4
4
  problem: "Project state lives across whereami and iteration goals and chronicles and git. No single-glance view."
5
5
  value: "Phase and active goal and agents in flight and gate progress \u2014 one page."
6
6
  inputs: [Optional freshness flag]
@@ -41,7 +41,7 @@ Four skills, four altitudes:
41
41
  | `/whereami` | Project state | Phase + goal + agents + freshness |
42
42
  | `/sprint` | Ticket / scope | Open issues + proposed sprint |
43
43
  | `/whats-the-plan` | Dispatch path | Ordered skill chain |
44
- | `/substrate-check` | Wiring | PASS / WARN / FAIL on symlinks + hooks + CLIs |
44
+ | `/substrate-check` | Wiring | PASS / WARN / FAIL on files + hooks + CLIs |
45
45
 
46
46
  Session-start order: `/whereami`, then `/sprint`, then `/whats-the-plan`, then execute.
47
47
 
@@ -40,7 +40,7 @@ Not sure which surface fits? The `/skill` skill runs a taxonomy gate (skill / ru
40
40
 
41
41
  ### Operator-private vs adopter-facing
42
42
 
43
- The `docs/operator-private/` directory in your clone contains only a README placeholder. That's intentional — operator-private substrate (internal deliberation, strategy notes) lives in a separate private repo. Contributors don't need to populate or interact with it. See [`standards/operator-private-discipline.md`](standards/operator-private-discipline.md) and [`standards/operator-to-public-flow.md`](standards/operator-to-public-flow.md) for the discipline.
43
+ The `docs/operator-private/` directory in your clone contains only a README placeholder. That's intentional — operator-private substrate (internal deliberation, strategy notes) lives in a separate private repo. Contributors don't need to populate or interact with it. The discipline: strategy artifacts stay private; only reference substrate (rules, hooks, standards) ships to the public bassclef repo.
44
44
 
45
45
  If you're the bassclef maintainer (operator), `scripts/operator-setup.sh` sets up the symlink workflow when the private repo is cloned at the expected sibling location. The script is idempotent + a no-op for adopter clones; adopters can ignore it.
46
46
 
@@ -19,7 +19,7 @@ It is not a product. It is not a SaaS. It's a public framework, Apache 2.0: clon
19
19
 
20
20
  ## Who this is for
21
21
 
22
- **Solo system / app / portfolio operators.** The person running multiple software projects in parallel — apps, internal systems, side bets, family operations — around a day job, around family, around the other things that don't pause. Real deadlines, real stakes, no headcount. Other audiences may benefit; this is the one SENTINEL_bassclef_commits to. The full audience commitment lives at [audience commitment](https://github.com/sunj-labs/bassclef/blob/main/strategy/personas/audience-commitment.md).
22
+ **Solo system / app / portfolio operators.** The person running multiple software projects in parallel — apps, internal systems, side bets, family operations — around a day job, around family, around the other things that don't pause. Real deadlines, real stakes, no headcount. Other audiences may benefit; this is the one SENTINEL_bassclef_commits to.
23
23
 
24
24
  ## Why this exists
25
25
 
@@ -38,7 +38,7 @@ The acceptance test for v1 wasn't a demo — it was a live ticket from my parent
38
38
 
39
39
  Not theoretical. Bassclef runs today across eight repos in active use:
40
40
 
41
- - **A private sibling repo for strategy notes** — canvases, audits, and locked decisions. The pattern adopters can replicate per [`standards/operator-private-discipline.md`](https://github.com/sunj-labs/bassclef/blob/main/standards/operator-private-discipline.md).
41
+ - **A private sibling repo for strategy notes** — canvases, audits, and locked decisions. Adopters replicate the pattern with a separate private repo cloned alongside their bassclef checkout.
42
42
  - **Seven application repos in daily use** — from a power-of-attorney tracker for my family to a collaborative travel planner to a recipe database. Each one is code I use myself, not a demo.
43
43
 
44
44
  The pattern: build the apps on the go, each repo's friction feeds back into bassclef as evolution tickets, the substrate hardens with every shipped feature.
@@ -165,9 +165,9 @@ Bassclef is markdown + bash + git. If you can read a file and run a script, you
165
165
  - [Skills catalog](https://github.com/sunj-labs/bassclef/blob/main/docs/skills-catalog.md) · [Hooks catalog](https://github.com/sunj-labs/bassclef/blob/main/docs/hooks-catalog.md) · [Rules catalog](https://github.com/sunj-labs/bassclef/blob/main/docs/rules-catalog.md) — substrate catalogs
166
166
  - [Context engineering framing](https://github.com/sunj-labs/bassclef/blob/main/design/bassclef-as-context-engineering.md) — substrate-truth framing
167
167
  - [Context engineering rule](https://github.com/sunj-labs/bassclef/blob/main/.claude/rules/context-engineering.md) — the foundational rule
168
- - [Agent choreography](https://github.com/sunj-labs/bassclef/blob/main/strategy/agent-choreography.md) — multi-agent operational guide
169
- - [whereami](https://github.com/sunj-labs/bassclef/blob/main/docs/whereami.md) — current project state
168
+ - Agent choreography — multi-agent operational guide (operator substrate)
169
+ - whereami — current project state (operator substrate)
170
170
 
171
171
  ## Operator-private substrate
172
172
 
173
- The `docs/operator-private/` directory contains only a README placeholder in adopter clones. Operator-private substrate (internal deliberation, strategy notes) lives separately. See [operator-private discipline](https://github.com/sunj-labs/bassclef/blob/main/standards/operator-private-discipline.md).
173
+ The `docs/operator-private/` directory contains only a README placeholder in adopter clones. Operator-private substrate (internal deliberation, strategy notes) lives in a separate private repo cloned alongside bassclef.
@@ -0,0 +1,171 @@
1
+ #!/usr/bin/env bash
2
+ # tier: lite
3
+ # install-class: dual
4
+ # lib/prose-scan-boundary.sh
5
+ #
6
+ # Deep module per @luminary john-ousterhout — narrow interface hides
7
+ # the boundary detection and counter file work behind 3 functions.
8
+ #
9
+ # Purpose — every prose scan hook (kiss, appositive, citation)
10
+ # strips fenced or echoed content BEFORE it scans, and writes counter
11
+ # state that plain-english-steering.sh injects into the next prompt.
12
+ #
13
+ # This closes #1443 canonical case — Stop side prose hooks that fire
14
+ # on verbatim BLOCKED banner echoes at session start plus operator
15
+ # picked shorthand labels. 5 rewrite cycles in 20 turns documented
16
+ # the cost during 2026-09-09b prep.
17
+ #
18
+ # Anchor luminaries:
19
+ # @luminary john-ousterhout — deep module hiding the boundary work
20
+ # @luminary donald-norman — feedback loop through the counter markers
21
+ # @luminary tony-hoare — pre and postcondition on each function
22
+ # @luminary michael-feathers — characterization tests pin behavior
23
+ #
24
+ # Consumers source this lib:
25
+ # source lib/prose-scan-boundary.sh
26
+ #
27
+ # Tests: lib/tests/prose-scan-boundary.test.sh (Tier 0 strict TDD)
28
+
29
+ # =========================================================================
30
+ # strip_scan_boundaries — remove content the scan should not read
31
+ # =========================================================================
32
+ # Interface: IProseScanBoundary (Larman)
33
+ # Inputs: $1 = message text
34
+ # Outputs: stdout — message with fenced or echoed content removed
35
+ # Exit: 0 always
36
+ #
37
+ # Removes:
38
+ # 1. BLOCKED banner blocks (session-start hook echoes; agent cannot rewrite)
39
+ # 2. <!--SCAN_SKIP-->...<!--/SCAN_SKIP--> explicit fence markers
40
+ # 3. Fenced code blocks (``` ... ```)
41
+ # 4. Inline code (`...`)
42
+ strip_scan_boundaries() {
43
+ local message_text="$1"
44
+ [ -z "$message_text" ] && return 0
45
+ # Python does the heavy lifting for regex-safe multiline strip.
46
+ # Fall back to raw text when python3 missing (fail-soft per Nygard).
47
+ if command -v python3 >/dev/null 2>&1; then
48
+ printf '%s' "$message_text" | python3 -c '
49
+ import sys
50
+ import re
51
+
52
+ text = sys.stdin.read()
53
+
54
+ # 1. Strip BLOCKED banner blocks. Banner shape:
55
+ # 🛑🛑🛑 BLOCKED 🛑🛑🛑
56
+ # ────────────
57
+ # content
58
+ # ────────────
59
+ # ACTION: resolve OR ...
60
+ # Silence is not deferral. ...
61
+ #
62
+ # Match the banner line and content until one of:
63
+ # - "Silence is not deferral" line followed by newline (canonical end)
64
+ # - Two consecutive newlines (paragraph break)
65
+ # - Next banner line
66
+ # - End of string
67
+ text = re.sub(
68
+ r"\U0001F6D1\U0001F6D1\U0001F6D1 BLOCKED \U0001F6D1\U0001F6D1\U0001F6D1"
69
+ r".*?"
70
+ r"(?:Silence is not deferral\.[^\n]*\n"
71
+ r"|\n\n(?=\S|\n|$)"
72
+ r"|(?=\U0001F6D1\U0001F6D1\U0001F6D1)"
73
+ r"|$)",
74
+ "",
75
+ text,
76
+ flags=re.DOTALL,
77
+ )
78
+
79
+ # 2. Strip explicit SCAN_SKIP fences
80
+ text = re.sub(
81
+ r"<!--SCAN_SKIP-->.*?<!--/SCAN_SKIP-->",
82
+ "",
83
+ text,
84
+ flags=re.DOTALL,
85
+ )
86
+
87
+ # 3. Strip fenced code blocks
88
+ text = re.sub(r"```.*?```", "", text, flags=re.DOTALL)
89
+
90
+ # 4. Strip inline code
91
+ text = re.sub(r"`[^`]+`", "", text)
92
+
93
+ sys.stdout.write(text)
94
+ '
95
+ else
96
+ # No python — return raw text so consumers still work
97
+ printf '%s' "$message_text"
98
+ fi
99
+ return 0
100
+ }
101
+
102
+ # =========================================================================
103
+ # write_prose_counter — persist a per-turn counter for the steering hook
104
+ # =========================================================================
105
+ # Interface: IProseCounterWriter (Larman)
106
+ # Inputs: $1 = counter name (e.g. "kiss_hits", "appositive_hits")
107
+ # $2 = numeric count
108
+ # $3 = optional JSON payload (findings, offenders, etc.)
109
+ # Outputs: writes state/markers/turn-prose-counters/<name>.json atomically
110
+ # Exit: 0 always (fail-soft on write error per Nygard)
111
+ write_prose_counter() {
112
+ local name="$1"
113
+ local count="$2"
114
+ local payload="${3:-{\}}"
115
+ [ -z "$name" ] && return 0
116
+ [ -z "$count" ] && count=0
117
+ local repo_root
118
+ repo_root="$(_prose_scan_repo_root)"
119
+ local dir="${repo_root}/state/markers/turn-prose-counters"
120
+ local out_file="${dir}/${name}.json"
121
+ mkdir -p "$dir" 2>/dev/null || return 0
122
+ local ts
123
+ ts="$(date -u +"%Y-%m-%dT%H:%M:%SZ" 2>/dev/null || echo "unknown")"
124
+ # Atomic write via tmp + mv
125
+ local tmp
126
+ tmp="$(mktemp "${dir}/.${name}.XXXXXX")" || return 0
127
+ cat > "$tmp" <<JSON
128
+ {
129
+ "counter": "${name}",
130
+ "count": ${count},
131
+ "updated_at": "${ts}",
132
+ "payload": ${payload}
133
+ }
134
+ JSON
135
+ mv "$tmp" "$out_file" 2>/dev/null || rm -f "$tmp"
136
+ return 0
137
+ }
138
+
139
+ # =========================================================================
140
+ # read_prose_counter — read a per-turn counter for prompt injection
141
+ # =========================================================================
142
+ # Interface: IProseCounterReader (Larman)
143
+ # Inputs: $1 = counter name
144
+ # Outputs: stdout — JSON content, or empty when marker missing
145
+ # Exit: 0 always (fail-soft per Nygard)
146
+ read_prose_counter() {
147
+ local name="$1"
148
+ [ -z "$name" ] && return 0
149
+ local repo_root
150
+ repo_root="$(_prose_scan_repo_root)"
151
+ local marker="${repo_root}/state/markers/turn-prose-counters/${name}.json"
152
+ [ -f "$marker" ] || return 0
153
+ cat "$marker" 2>/dev/null || true
154
+ return 0
155
+ }
156
+
157
+ # =========================================================================
158
+ # _prose_scan_repo_root — resolve repo root under both install classes
159
+ # =========================================================================
160
+ # Internal helper. Prefer $CLAUDE_PROJECT_DIR (project install), fall
161
+ # back to lib file's parent (operator install). Per install-class: dual
162
+ # discipline from ADR-035 substrate-as-system tenet.
163
+ _prose_scan_repo_root() {
164
+ if [ -n "${CLAUDE_PROJECT_DIR:-}" ] && [ -d "${CLAUDE_PROJECT_DIR}" ]; then
165
+ echo "${CLAUDE_PROJECT_DIR}"
166
+ return 0
167
+ fi
168
+ local script_dir
169
+ script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
170
+ cd "${script_dir}/.." && pwd
171
+ }
@@ -14,7 +14,7 @@
14
14
  #
15
15
  # Rules governed by:
16
16
  # - .claude/rules/testing-tier-config.md (Tier 0 strict TDD)
17
- # - .claude/rules/mechanism-fidelity.md (interface honored end to end)
17
+ # - mechanism-fidelity rule (standard tier; interface honored end to end)
18
18
  #
19
19
  # Anchor luminaries: ousterhout (deep module), feathers (probe pin behavior)
20
20
 
@@ -117,6 +117,55 @@ except Exception:
117
117
  PYEOF
118
118
  }
119
119
 
120
+ # resolve_file_tier <path>
121
+ #
122
+ # Read a file's tier tag and print it to stdout. Returns empty string if
123
+ # no tag is present. Supported shapes:
124
+ # - .md — YAML frontmatter `tier:` field between --- markers
125
+ # - .sh, .py — `# tier:` header line in first 10 lines
126
+ # - .yml, .yaml — `# tier:` comment OR top-level `tier:` field in first 30 lines
127
+ # - .json — root-key `"tier"` or `"_tier"` in first 30 lines
128
+ # - .jsonc — `// tier:` comment or root-key
129
+ # - .txt — first-line `# tier:` convention
130
+ #
131
+ # Mirrors detection shape from .claude/hooks/tier-tag-required-at-write.sh so
132
+ # the reader half and the writer half stay consistent.
133
+ resolve_file_tier() {
134
+ local path="$1"
135
+ if [ ! -f "$path" ]; then
136
+ return 0
137
+ fi
138
+
139
+ local tier=""
140
+ case "$path" in
141
+ *.md)
142
+ # Frontmatter between --- markers, first 30 lines
143
+ tier=$(awk '
144
+ /^---/ { in_fm = !in_fm; if (!in_fm) exit; next }
145
+ in_fm && /^tier:[[:space:]]/ { sub(/^tier:[[:space:]]*/, ""); sub(/[[:space:]]*$/, ""); print; exit }
146
+ NR > 30 { exit }
147
+ ' "$path" 2>/dev/null)
148
+ ;;
149
+ *.sh|*.py)
150
+ tier=$(head -10 "$path" 2>/dev/null | grep -E '^#[[:space:]]*tier:[[:space:]]' | head -1 | sed -E 's/^#[[:space:]]*tier:[[:space:]]*//; s/[[:space:]]*$//')
151
+ ;;
152
+ *.yml|*.yaml)
153
+ tier=$(head -30 "$path" 2>/dev/null | grep -E '^#[[:space:]]*tier:[[:space:]]|^tier:[[:space:]]' | head -1 | sed -E 's/^#?[[:space:]]*tier:[[:space:]]*//; s/[[:space:]]*$//')
154
+ ;;
155
+ *.json|*.jsonc)
156
+ tier=$(head -30 "$path" 2>/dev/null | grep -oE '"(_?tier)"[[:space:]]*:[[:space:]]*"[a-z]+"' | head -1 | sed -E 's/.*:[[:space:]]*"([a-z]+)"/\1/')
157
+ if [ -z "$tier" ]; then
158
+ tier=$(head -30 "$path" 2>/dev/null | grep -oE '//[[:space:]]*tier:[[:space:]]*[a-z]+' | head -1 | sed -E 's/.*tier:[[:space:]]*//')
159
+ fi
160
+ ;;
161
+ *.txt)
162
+ tier=$(head -1 "$path" 2>/dev/null | grep -E '^#[[:space:]]*tier:[[:space:]]' | sed -E 's/^#[[:space:]]*tier:[[:space:]]*//; s/[[:space:]]*$//')
163
+ ;;
164
+ esac
165
+
166
+ echo "$tier"
167
+ }
168
+
120
169
  # tier_at_least <required> [current]
121
170
  #
122
171
  # Returns 0 if current tier >= required, 1 otherwise.
@@ -859,11 +859,24 @@ walk_graph_bfs_inbound() {
859
859
  compute_kind_coverage() {
860
860
  local walk_file="$1"
861
861
  local tier="$2"
862
- # Enumerate all known REFERENCE_KINDS (plus schema_ref extension)
863
- local known_kinds=("composes_with" "source_lib" "additional_directories" \
864
- "bash_scripts" "luminary_ref" "standards_ref" "rules_ref" "schema_ref")
862
+ # Derive known kinds from REFERENCE_KINDS at run time so new
863
+ # extractor rows automatically appear in coverage. Pre-fix this
864
+ # list was hardcoded and drifted from REFERENCE_KINDS — hook_ref
865
+ # existed as a walked kind but was missing from coverage output
866
+ # (bug 1 per docs/audits/2026-09-10-tier-graph-walk-miss.md).
867
+ # schema_ref is not in REFERENCE_KINDS but has its own extractor
868
+ # per _extract_schema_ref; keep it as a static append so schema
869
+ # coverage still emits.
870
+ local known_kinds=()
871
+ local entry name
872
+ for entry in "${REFERENCE_KINDS[@]}"; do
873
+ name="${entry%%|*}"
874
+ known_kinds+=("$name")
875
+ done
876
+ known_kinds+=("schema_ref")
877
+ local kind count
865
878
  for kind in "${known_kinds[@]}"; do
866
- local count=0
879
+ count=0
867
880
  if [ -s "$walk_file" ]; then
868
881
  count="$(awk -F'\t' -v k="$kind" '$1 == k { c++ } END { print c+0 }' "$walk_file")"
869
882
  fi
@@ -931,3 +944,145 @@ read_intended_source_1_extended() {
931
944
  if [ -n "$out" ]; then echo "$out"; fi
932
945
  return 0
933
946
  }
947
+
948
+ # ---------------------------------------------------------------------------
949
+ # G5 extension (goal 2026-09-09b): per-edge tier alignment check
950
+ # Ships in PR-2 alongside Bug 1 fix for coverage reporter. Closes the
951
+ # gap Shape e was designed to catch — SKILL body references to hooks
952
+ # tagged at higher tier than the SKILL itself (broken adopter promise
953
+ # per @luminary linus-torvalds and ADR-043 D1 concentric inclusion).
954
+ # ---------------------------------------------------------------------------
955
+
956
+ # _tier_rank_full — full 5-tier rank map per ADR-043 D1
957
+ # lite < standard < standard-pro < ultra < upstream
958
+ # Rank 0 for unknown or missing tier (treated as neutral).
959
+ _tier_rank_full() {
960
+ case "$1" in
961
+ lite) echo 1 ;;
962
+ standard) echo 2 ;;
963
+ standard-pro) echo 3 ;;
964
+ ultra) echo 4 ;;
965
+ upstream) echo 5 ;;
966
+ *) echo 0 ;;
967
+ esac
968
+ }
969
+
970
+ # _read_file_tier — extract tier tag from a file
971
+ # Mirrors scripts/release-to-bassclef.sh:read_tier per standards/tier-tag-schema.md
972
+ # Returns tier name on stdout; empty when no tag present.
973
+ _read_file_tier() {
974
+ local f="$1"
975
+ [ -f "$f" ] || return 0
976
+ case "$f" in
977
+ *.md)
978
+ awk '
979
+ BEGIN{infm=0}
980
+ NR==1 && /^---/ {infm=1; next}
981
+ infm && /^---/ {exit}
982
+ infm && /^tier:[[:space:]]/ {sub(/^tier:[[:space:]]*/,""); gsub(/[[:space:]]/,""); print; exit}
983
+ ' "$f"
984
+ ;;
985
+ *.sh|*.py)
986
+ head -5 "$f" | awk '/^# tier:[[:space:]]/ {sub(/^# tier:[[:space:]]*/,""); gsub(/[[:space:]]/,""); print; exit}'
987
+ ;;
988
+ *.yml|*.yaml)
989
+ head -5 "$f" | awk '
990
+ /^---/ {next}
991
+ /^# tier:[[:space:]]/ {sub(/^# tier:[[:space:]]*/,""); gsub(/[[:space:]]/,""); print; exit}
992
+ /^tier:[[:space:]]/ {sub(/^tier:[[:space:]]*/,""); gsub(/[[:space:]]/,""); print; exit}
993
+ '
994
+ ;;
995
+ *.jsonc)
996
+ head -5 "$f" | awk '/^\/\/ tier:[[:space:]]/ {sub(/^\/\/ tier:[[:space:]]*/,""); gsub(/[[:space:]]/,""); print; exit}'
997
+ ;;
998
+ *.json)
999
+ head -5 "$f" | awk '
1000
+ /"tier":[[:space:]]*"[^"]+"/ {
1001
+ match($0, /"tier":[[:space:]]*"[^"]+"/); s=substr($0, RSTART, RLENGTH);
1002
+ gsub(/"tier":[[:space:]]*"/, "", s); gsub(/"$/, "", s);
1003
+ print s; exit
1004
+ }
1005
+ /"_tier":[[:space:]]*"[^"]+"/ {
1006
+ match($0, /"_tier":[[:space:]]*"[^"]+"/); s=substr($0, RSTART, RLENGTH);
1007
+ gsub(/"_tier":[[:space:]]*"/, "", s); gsub(/"$/, "", s);
1008
+ print s; exit
1009
+ }
1010
+ '
1011
+ ;;
1012
+ *) : ;;
1013
+ esac
1014
+ }
1015
+
1016
+ # check_tier_alignment_on_edges — per-edge tier alignment check
1017
+ # Interface: ITierAlignmentChecker (per Larman GRASP naming)
1018
+ # Inputs: $1 = walk-with-kinds.tsv path (rows: <kind>\t<from>\t<to>)
1019
+ # $2 = target tier (e.g. "lite")
1020
+ # $3 = optional out-file for violation report (default: stdout)
1021
+ # Outputs: writes violations as "<kind>\t<from>\t<from-tier>\t<to>\t<to-tier>"
1022
+ # Exit: 0 always. Count of violations on final stderr line.
1023
+ # Rule: ADR-043 D1 concentric inclusion — source tier T guarantees
1024
+ # target tier <= T. When source has target tier AND target
1025
+ # file has HIGHER tier rank, source's tier promise breaks.
1026
+ check_tier_alignment_on_edges() {
1027
+ local walk_file="$1"
1028
+ local target_tier="$2"
1029
+ local out_file="${3:-/dev/stdout}"
1030
+ [ -f "$walk_file" ] || { echo "check_tier_alignment_on_edges: walk file missing at $walk_file" >&2; return 1; }
1031
+ local target_rank
1032
+ target_rank="$(_tier_rank_full "$target_tier")"
1033
+ [ "$target_rank" = "0" ] && { echo "check_tier_alignment_on_edges: unknown target tier '$target_tier'" >&2; return 1; }
1034
+ # Optimization: cache tiers per unique file. Then use awk with an
1035
+ # associative array for O(1) lookup during edge walk. Prior shape
1036
+ # ran awk per edge lookup = O(edges * cache) ~ 10M ops on lite tier.
1037
+ # Initialize local var so `set -u` callers do not trip on the trap
1038
+ # when mktemp fails or the local declaration races against the trap.
1039
+ local tier_cache=""
1040
+ tier_cache="$(mktemp)" || tier_cache="/tmp/tier_cache_fallback_$$"
1041
+ # shellcheck disable=SC2064
1042
+ trap "rm -f '${tier_cache}'" RETURN
1043
+ # First pass: collect unique files then read tier per file (bash loop).
1044
+ local file tier
1045
+ while IFS= read -r file; do
1046
+ [ -n "$file" ] || continue
1047
+ tier="$(_read_file_tier "$file" 2>/dev/null || true)"
1048
+ printf "%s\t%s\n" "$file" "${tier:-none}"
1049
+ done < <(awk -F'\t' '{print $2; print $3}' "$walk_file" | sort -u) > "$tier_cache"
1050
+ # Second pass: awk-side associative array; single sweep of walk_file.
1051
+ local violations
1052
+ violations="$(awk -F'\t' \
1053
+ -v target="$target_tier" \
1054
+ -v target_rank="$target_rank" \
1055
+ -v out="$out_file" \
1056
+ -v cache="$tier_cache" '
1057
+ BEGIN {
1058
+ # Preload rank map
1059
+ rank["lite"] = 1; rank["standard"] = 2; rank["standard-pro"] = 3;
1060
+ rank["ultra"] = 4; rank["upstream"] = 5;
1061
+ # Preload tier cache
1062
+ while ((getline line < cache) > 0) {
1063
+ n = split(line, parts, "\t")
1064
+ if (n >= 2) tier_of[parts[1]] = parts[2]
1065
+ }
1066
+ close(cache)
1067
+ v = 0
1068
+ # Truncate out file
1069
+ printf "" > out
1070
+ }
1071
+ {
1072
+ kind = $1; from = $2; to = $3
1073
+ if (kind == "" || from == "" || to == "") next
1074
+ ft = tier_of[from]
1075
+ tt = tier_of[to]
1076
+ if (ft != target) next
1077
+ tr = rank[tt] + 0
1078
+ if (tr == 0) next
1079
+ if (tr > target_rank) {
1080
+ print kind "\t" from "\t" ft "\t" to "\t" tt >> out
1081
+ v++
1082
+ }
1083
+ }
1084
+ END { print v }
1085
+ ' "$walk_file")"
1086
+ echo "check_tier_alignment_on_edges: $violations violations for target_tier=$target_tier" >&2
1087
+ return 0
1088
+ }