@thebassclef/lite 0.0.1 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (182) hide show
  1. package/LICENSE +202 -0
  2. package/README.md +85 -4
  3. package/dist/cli.cjs +1610 -0
  4. package/dist/cli.js +1587 -0
  5. package/dist/index.cjs +4 -0
  6. package/dist/index.d.ts +2 -0
  7. package/dist/index.js +4 -0
  8. package/package.json +51 -3
  9. package/substrate/.bassclef/lite-manifest.json +1794 -0
  10. package/substrate/.claude/agents/architect.md +70 -0
  11. package/substrate/.claude/agents/builder.md +114 -0
  12. package/substrate/.claude/agents/designer.md +156 -0
  13. package/substrate/.claude/agents/reviewer.md +88 -0
  14. package/substrate/.claude/hooks/artifact-ingestion-gate.sh +357 -0
  15. package/substrate/.claude/hooks/assert-verify-steering.sh +77 -0
  16. package/substrate/.claude/hooks/bassclef-source-config-validate.sh +215 -0
  17. package/substrate/.claude/hooks/bassclef-sync.sh +634 -0
  18. package/substrate/.claude/hooks/compound-noun-scrub.sh +292 -0
  19. package/substrate/.claude/hooks/kiss-expansion-inject.sh +69 -0
  20. package/substrate/.claude/hooks/plain-english-steering.sh +156 -0
  21. package/substrate/.claude/hooks/post-skill-friction-check.sh +177 -0
  22. package/substrate/.claude/hooks/post-skill-telemetry.sh +62 -0
  23. package/substrate/.claude/hooks/pre-build-gate.sh +511 -0
  24. package/substrate/.claude/hooks/pre-commit-gate.sh +452 -0
  25. package/substrate/.claude/hooks/session-end.sh +433 -0
  26. package/substrate/.claude/hooks/session-reflection.sh +303 -0
  27. package/substrate/.claude/hooks/skill-body-grade-gate.sh +219 -0
  28. package/substrate/.claude/hooks/skill-body-intent-drift.sh +107 -0
  29. package/substrate/.claude/hooks/skill-step-list-check.sh +171 -0
  30. package/substrate/.claude/hooks/state-validate.sh +271 -0
  31. package/substrate/.claude/hooks/substrate-clarity-gate.sh +1110 -0
  32. package/substrate/.claude/hooks/temperance-gate.sh +147 -0
  33. package/substrate/.claude/hooks/testing-tier-enforce.sh +233 -0
  34. package/substrate/.claude/hooks/turn-prose-grade-measure.sh +219 -0
  35. package/substrate/.claude/hooks/turn-prose-kiss-check.sh +434 -0
  36. package/substrate/.claude/hooks/vocabulary-migration-check.sh +171 -0
  37. package/substrate/.claude/hooks/whereami-utc-gate.sh +142 -0
  38. package/substrate/.claude/luminaries/alan-cooper.md +170 -0
  39. package/substrate/.claude/luminaries/alistair-cockburn.md +140 -0
  40. package/substrate/.claude/luminaries/amazon-pr-faq.md +34 -0
  41. package/substrate/.claude/luminaries/ash-maurya.md +121 -0
  42. package/substrate/.claude/luminaries/bill-buxton.md +210 -0
  43. package/substrate/.claude/luminaries/charles-sanders-peirce.md +150 -0
  44. package/substrate/.claude/luminaries/david-ogilvy.md +192 -0
  45. package/substrate/.claude/luminaries/don-norman.md +173 -0
  46. package/substrate/.claude/luminaries/edward-tufte.md +179 -0
  47. package/substrate/.claude/luminaries/eric-evans.md +160 -0
  48. package/substrate/.claude/luminaries/frederick-brooks.md +50 -0
  49. package/substrate/.claude/luminaries/gang-of-four.md +157 -0
  50. package/substrate/.claude/luminaries/jason-fried-dhh.md +46 -0
  51. package/substrate/.claude/luminaries/jesse-james-garrett.md +154 -0
  52. package/substrate/.claude/luminaries/john-ousterhout.md +94 -0
  53. package/substrate/.claude/luminaries/karl-popper.md +132 -0
  54. package/substrate/.claude/luminaries/kent-beck.md +168 -0
  55. package/substrate/.claude/luminaries/linus-torvalds.md +218 -0
  56. package/substrate/.claude/luminaries/martin-fowler.md +164 -0
  57. package/substrate/.claude/luminaries/michael-feathers.md +125 -0
  58. package/substrate/.claude/luminaries/michael-nygard.md +118 -0
  59. package/substrate/.claude/luminaries/robert-c-martin.md +164 -0
  60. package/substrate/.claude/luminaries/saltzer-schroeder.md +194 -0
  61. package/substrate/.claude/luminaries/sophia-prater.md +193 -0
  62. package/substrate/.claude/luminaries/stephen-toulmin.md +131 -0
  63. package/substrate/.claude/rules/artifact-ingestion.md +179 -0
  64. package/substrate/.claude/rules/assert-only-after-verify.md +137 -0
  65. package/substrate/.claude/rules/blocked-items.md +146 -0
  66. package/substrate/.claude/rules/branching.md +28 -0
  67. package/substrate/.claude/rules/commit-conventions.md +22 -0
  68. package/substrate/.claude/rules/context-engineering.md +202 -0
  69. package/substrate/.claude/rules/context-management.md +85 -0
  70. package/substrate/.claude/rules/destructive-operations.md +69 -0
  71. package/substrate/.claude/rules/diagnosis.md +38 -0
  72. package/substrate/.claude/rules/guardrails.md +73 -0
  73. package/substrate/.claude/rules/identifier-leak-prevention.md +104 -0
  74. package/substrate/.claude/rules/lite-manifest-schema-change-discipline.md +98 -0
  75. package/substrate/.claude/rules/oo-ad-entry-point.md +117 -0
  76. package/substrate/.claude/rules/operator-facing-prose.md +196 -0
  77. package/substrate/.claude/rules/plain-english-discipline.md +154 -0
  78. package/substrate/.claude/rules/pr-body-shape.md +317 -0
  79. package/substrate/.claude/rules/pr-strategy.md +167 -0
  80. package/substrate/.claude/rules/sdlc-gates.md +149 -0
  81. package/substrate/.claude/rules/session-artifacts.md +236 -0
  82. package/substrate/.claude/rules/state-schema-validation.md +162 -0
  83. package/substrate/.claude/rules/whereami-load-bearing.md +202 -0
  84. package/substrate/.claude/rules/writing-craft-discipline.md +92 -0
  85. package/substrate/.claude/skills/build/SKILL.md +640 -0
  86. package/substrate/.claude/skills/decompose/SKILL.md +280 -0
  87. package/substrate/.claude/skills/diagnose/SKILL.md +297 -0
  88. package/substrate/.claude/skills/howdoi/SKILL.md +105 -0
  89. package/substrate/.claude/skills/ia-model/SKILL.md +108 -0
  90. package/substrate/.claude/skills/interaction-design/SKILL.md +112 -0
  91. package/substrate/.claude/skills/interpret-input/SKILL.md +180 -0
  92. package/substrate/.claude/skills/kiss/SKILL.md +449 -0
  93. package/substrate/.claude/skills/launch/SKILL.md +924 -0
  94. package/substrate/.claude/skills/lean-canvas/SKILL.md +332 -0
  95. package/substrate/.claude/skills/longrun/SKILL.md +426 -0
  96. package/substrate/.claude/skills/luminary/SKILL.md +481 -0
  97. package/substrate/.claude/skills/ogilvy-writing-audit/SKILL.md +177 -0
  98. package/substrate/.claude/skills/onboard-repo/SKILL.md +2190 -0
  99. package/substrate/.claude/skills/pattern-review/SKILL.md +99 -0
  100. package/substrate/.claude/skills/personas/SKILL.md +207 -0
  101. package/substrate/.claude/skills/promote/SKILL.md +283 -0
  102. package/substrate/.claude/skills/requirement/SKILL.md +98 -0
  103. package/substrate/.claude/skills/retro/SKILL.md +117 -0
  104. package/substrate/.claude/skills/riff/SKILL.md +114 -0
  105. package/substrate/.claude/skills/roadmap-reconcile/SKILL.md +163 -0
  106. package/substrate/.claude/skills/session-end/SKILL.md +309 -0
  107. package/substrate/.claude/skills/session-log/SKILL.md +299 -0
  108. package/substrate/.claude/skills/skills/SKILL.md +228 -0
  109. package/substrate/.claude/skills/spec/SKILL.md +105 -0
  110. package/substrate/.claude/skills/sprint/SKILL.md +392 -0
  111. package/substrate/.claude/skills/stage/SKILL.md +384 -0
  112. package/substrate/.claude/skills/state-a-problem/SKILL.md +185 -0
  113. package/substrate/.claude/skills/temperance/SKILL.md +108 -0
  114. package/substrate/.claude/skills/use-case/SKILL.md +417 -0
  115. package/substrate/.claude/skills/user-stories/SKILL.md +268 -0
  116. package/substrate/.claude/skills/value-prop/SKILL.md +251 -0
  117. package/substrate/.claude/skills/verify/SKILL.md +160 -0
  118. package/substrate/.claude/skills/whereami/SKILL.md +307 -0
  119. package/substrate/AGENTS.md +79 -0
  120. package/substrate/CLAUDE-lite.md +85 -0
  121. package/substrate/CODE_OF_CONDUCT.md +28 -0
  122. package/substrate/CONTRIBUTING.md +177 -0
  123. package/substrate/README.md +173 -0
  124. package/substrate/SECURITY.md +19 -0
  125. package/substrate/architecture/decisions/ADR-029-release-pipeline.md +79 -0
  126. package/substrate/architecture/decisions/ADR-031-non-breaking-changes-adopter-discipline.md +139 -0
  127. package/substrate/architecture/decisions/ADR-032-adopter-sync-dispatcher-architecture.md +192 -0
  128. package/substrate/architecture/decisions/ADR-039-release-tagging-scheme.md +145 -0
  129. package/substrate/architecture/decisions/ADR-040-planning-skill-vocabulary-and-lite-profile.md +155 -0
  130. package/substrate/architecture/decisions/ADR-044-unified-skill-body-template.md +162 -0
  131. package/substrate/lib/clean-artifacts-sweep.sh +112 -0
  132. package/substrate/lib/code-comment-discipline.sh +144 -0
  133. package/substrate/lib/composer-preflight.sh +459 -0
  134. package/substrate/lib/hook-inject.sh +255 -0
  135. package/substrate/lib/luminary-pick.sh +96 -0
  136. package/substrate/lib/output-discipline.sh +143 -0
  137. package/substrate/lib/rewrite-check.sh +214 -0
  138. package/substrate/lib/state.sh +1372 -0
  139. package/substrate/lib/telemetry.sh +205 -0
  140. package/substrate/lib/tier-check.sh +138 -0
  141. package/substrate/lib/tier-dependency-audit.sh +933 -0
  142. package/substrate/presence/install/bassclef-hook-connect.sh +178 -0
  143. package/substrate/presence/install/bassclef-sync.dispatcher.template.sh +841 -0
  144. package/substrate/presence/install/bassclef-sync.template.sh +2076 -0
  145. package/substrate/presence/install/schedule-auto-save.cron.sh +88 -0
  146. package/substrate/presence/install/schedule-auto-save.taskscheduler.md +122 -0
  147. package/substrate/scripts/aggregate-telemetry.sh +217 -0
  148. package/substrate/scripts/analyze-tier-dependencies.sh +239 -0
  149. package/substrate/scripts/generate-lite-manifest.sh +489 -0
  150. package/substrate/scripts/generate-tier-manifest.sh +28 -0
  151. package/substrate/scripts/intent-drift-check.sh +456 -0
  152. package/substrate/scripts/lite-manifest-drift-check.sh +146 -0
  153. package/substrate/scripts/render-lite-manifest-doc.sh +150 -0
  154. package/substrate/standards/bassclef-configs-schema.md +232 -0
  155. package/substrate/standards/bassclef-evolution.md +143 -0
  156. package/substrate/standards/bassclef-internal-jargon.md +244 -0
  157. package/substrate/standards/bassclef-managed-sentinel.md +96 -0
  158. package/substrate/standards/bassclef-source-config.md +228 -0
  159. package/substrate/standards/deferred-actions-schema.md +204 -0
  160. package/substrate/standards/docs-sync-allowlist.md +76 -0
  161. package/substrate/standards/graceful-exit.md +227 -0
  162. package/substrate/standards/hook-idempotency.md +102 -0
  163. package/substrate/standards/lite-manifest-schema-changes.md +75 -0
  164. package/substrate/standards/luminary-problem-patterns.md +481 -0
  165. package/substrate/standards/ogilvy-writing-rules.md +225 -0
  166. package/substrate/standards/opener-discipline.md +96 -0
  167. package/substrate/standards/operator-facing-prose-discipline.md +201 -0
  168. package/substrate/standards/project-directory-layout.md +276 -0
  169. package/substrate/standards/release-tagging.md +137 -0
  170. package/substrate/standards/sdlc-compliance.md +286 -0
  171. package/substrate/standards/secrets-lifecycle.md +210 -0
  172. package/substrate/standards/security-scanner-adapter.md +145 -0
  173. package/substrate/standards/skill-output-discipline.md +90 -0
  174. package/substrate/standards/state-spine.md +511 -0
  175. package/substrate/standards/tech-stack-config.md +109 -0
  176. package/substrate/standards/tier-dependency-analysis.md +167 -0
  177. package/substrate/standards/tier-runtime-deps/lite.md +57 -0
  178. package/substrate/standards/tier-tag-schema.md +155 -0
  179. package/substrate/standards/whereami-schema.md +301 -0
  180. package/substrate/standards/writing-guide.md +213 -0
  181. package/substrate/templates/deferred-action-template.md +45 -0
  182. package/substrate/templates/whereami-template.md +101 -0
@@ -0,0 +1,154 @@
1
+ ---
2
+ tier: lite
3
+ description: All bassclef writing — skills, rules, luminaries, PR bodies, commit messages, chronicles, journal entries, iteration goals — should be plain digestible English at a grade-10…
4
+ ---
5
+
6
+ # Plain-English Discipline
7
+
8
+ All bassclef writing — skills, rules, luminaries, PR bodies, commit messages, chronicles, journal entries, iteration goals — should be plain digestible English at a grade-10 reading level. Keep standard technical vocabulary that any digital team would understand. Drop bassclef-internal jargon. Drive for extreme simplicity.
9
+
10
+ This rule is the master discipline. Other rules cover narrow surfaces:
11
+
12
+ - `skill-description-clarity.md` — skill description field (≤280 chars, verb-first, no jargon)
13
+ - `github-issue-flash-tweet.md` — GitHub issue body shape (flash + tweet + detail)
14
+ - `visual-hierarchy.md` — long agent output formatting
15
+ - `context-engineering.md` — INSTEAD-block discipline (the pairing rule for negations)
16
+
17
+ This rule extends those into a unified bar across every writing surface in bassclef.
18
+
19
+ ## Why this matters
20
+
21
+ Agent volume keeps climbing. Skills produce more PRs, more chronicles, more draft text. Humans review the output to figure out what's happening with the code. If the writing isn't simple, review collapses. The operator stops trusting the output. The substrate's value compounds in the wrong direction.
22
+
23
+ INSTEAD of writing for "people who know bassclef": write for a senior engineer with no bassclef context. They should grok every PR body, chronicle, and skill description in 60 seconds.
24
+
25
+ ## Keep standard technical vocabulary
26
+
27
+ These are common digital-team words. They stay as-is.
28
+
29
+ INSTEAD of expanding them into multi-sentence explanations: use them directly. The reader already knows what an API or schema is.
30
+
31
+ ```
32
+ API, SDK, CLI, GUI, HTTP, REST, JSON, YAML, schema, regex, hook,
33
+ repo, branch, commit, PR, MR, CI, CD, workflow, action, artifact,
34
+ function, class, method, property, field, constant, variable, enum,
35
+ database, query, index, migration, transaction, cache, queue, lock,
36
+ container, image, pod, cluster, node, runner, build, deploy, rollback,
37
+ test, assert, mock, stub, fixture, snapshot, regression,
38
+ auth, token, secret, credential, scope, permission, role,
39
+ file, directory, path, glob, pattern, prefix, suffix
40
+ ```
41
+
42
+ If a term is in this list, it's fine to use directly. Operator can extend the list when more standard vocabulary surfaces.
43
+
44
+ ## Drop bassclef-internal jargon
45
+
46
+ These need substitution because they require bassclef context to parse:
47
+
48
+ | Bassclef jargon | Plain English alternatives |
49
+ |---|---|
50
+ | substrate | the framework / bassclef / the rules |
51
+ | primitive | building block |
52
+ | load-bearing | required / essential |
53
+ | composer | runs / chains / combines |
54
+ | tier-preset | preset / size |
55
+ | compose-with | uses / builds on |
56
+ | scope-bounded | small / tight |
57
+ | operationalize | do / ship |
58
+ | blast radius | impact / what it can break |
59
+ | INSTEAD-block discipline | the pairing rule |
60
+ | stuck-signal | repeated warning |
61
+ | substrate-defect | bug in the rules |
62
+
63
+ These words exist for a reason inside bassclef's design discussions. They belong in design docs, not in PR bodies, chronicles, or any writing aimed at humans without bassclef context.
64
+
65
+ ## Drive for extreme simplicity
66
+
67
+ INSTEAD of long sentences and qualifying clauses: short sentences, active voice, concrete examples.
68
+
69
+ | Anti-pattern | INSTEAD |
70
+ |---|---|
71
+ | Long sentences (>30 words) | Break into 2-3 short sentences. Each carries one idea. |
72
+ | Passive voice ("the file was created by the agent") | Active voice ("the agent created the file") |
73
+ | Hedging words ("perhaps", "could potentially", "in some cases") | Direct statement. Either it does or it doesn't. |
74
+ | Buzz adjectives ("comprehensive", "robust", "leverages") | Drop them. Or replace with concrete data. |
75
+ | Methodology references ("Phase 14 of buildable-spec chain") | Either explain the term inline OR drop the reference |
76
+ | Multi-clause noun phrases ("the per-tier deploy-host adapter schema split") | Full plain sentence ("we split the deploy-host adapter schema by tier") |
77
+
78
+ Extreme simplicity is not the same as dumbing down. It means saying the thing once, in the shortest sentence that carries the point.
79
+
80
+ ## What this rule does NOT require
81
+
82
+ - Replacing every instance of a banned word — only when context allows. If a word is unavoidable (e.g., quoting a memory file's name), it stays.
83
+ - Hand-paraphrasing technical terms — API stays API. Schema stays schema. Hook stays hook.
84
+ - Grade-school reading level — grade 8 is the aim (per ticket #935; grade 10 stays as the ceiling for simple technical sentences). Operator-readable, not dumbed down.
85
+ - Multi-paragraph expansion of every term — that is contortion, the opposite of what this rule asks for.
86
+
87
+ INSTEAD of trying to scrub every word: focus on the highest-leverage substitutions (bassclef jargon, long sentences, passive voice).
88
+
89
+ ## When this rule fires
90
+
91
+ | Surface | Bar | Enforcement |
92
+ |---|---|---|
93
+ | Skill description field (frontmatter) | strict (≤280 chars, no jargon, verb-first) | substrate-clarity-gate hook BLOCKs (file-write) |
94
+ | Skill body | grade-10 plain English; no bassclef jargon | substrate-clarity-gate + skill-body-grade-gate (FKGL 80% at 8-9, ceiling 10) + compound-noun-scrub (blocklist from standards/bassclef-internal-jargon.md per bassclef-upstream#782) — all BLOCK at PreToolUse Edit/Write |
95
+ | Rule body | grade-10 plain English; INSTEAD-block discipline on negations | substrate-clarity-gate + compound-noun-scrub BLOCK at PreToolUse Edit/Write |
96
+ | Luminary body | grade-10 plain English; INSTEAD-block discipline on negations | substrate-clarity-gate hook BLOCKs (file-write) |
97
+ | PR body | grade-10 plain English; no bassclef jargon | bassclef-pr-ci body-clarity advisory job (comments suggestions) |
98
+ | Commit message | conventional-commits format; plain English in body | commit-conventions rule (methodology) |
99
+ | Chronicle | narrative grade-10 plain English | substrate-clarity-gate hook (advisory; new path matcher in WU-7b) |
100
+ | journal entry | personal/sensory/story-driven voice (per writing voice memory) | advisory only; voice trumps strict rule |
101
+ | Iteration goal body | grade-10 plain English | substrate-clarity-gate hook (advisory) |
102
+ | Agent turn prose to operator | grade-10 plain English; no bassclef jargon (banned-word list per "Drop bassclef-internal jargon" table above) | Stop hook `turn-prose-kiss-check.sh` scans the most recent assistant message (bassclef#1051). Toggle in `.claude/bassclef-configs.jsonc` (`prose_discipline.kiss_words_turn_prose`): `true` advisory (default), `"strict"` blocks stop, `false` disables. |
103
+
104
+ The hook is the primary backstop. The rule is the reasoning. Skills (`/promote`, `/longrun closeout`, `/chronicle`, `/journal`, `/kiss words`) compose the prevention.
105
+
106
+ **Compound-noun blocklist architecture (V2, bassclef-upstream#782 shipped 2026-07-20 goal 20a Session 2).** The `compound-noun-scrub.sh` hook reads a blocklist from `standards/bassclef-internal-jargon.md` at fire time. Only BLOCK-tier hyphenated compounds trigger. Standard tech compounds (`pre-commit`, `real-time`, `data-driven`) pass automatically because they are not in the blocklist. New invented compounds pass by default until the operator adds a row to the wordlist file. The wordlist is the single operator-editable source of truth. Both `compound-noun-scrub.sh` and `turn-prose-kiss-check.sh` read from the same file — one source of truth, two hook surfaces. Override at hook: `SKIP_COMPOUND_NOUN_SCRUB=1`. Override path at wordlist: `BASSCLEF_JARGON_WORDLIST=<path>` (test-only). Missing wordlist file fails safe (exit 0 with stderr warning).
107
+
108
+ **Turn prose IS hook-reachable via the Stop event** (bassclef#1051 closed bassclef#1027's wrong-premise reading). Claude Code's Stop hook receives `transcript_path` in stdin and can read the most recent assistant message. The `turn-prose-kiss-check.sh` hook fires after every assistant turn, scans the last message against BLOCK terms from `standards/bassclef-internal-jargon.md`, and surfaces findings per the toggle. The per-adopter toggle (`prose_discipline.kiss_words_turn_prose` in `.claude/bassclef-configs.jsonc`): `true` (default) advisory — exit 0, findings to stderr surface at next turn; `"strict"` — exit 2, block stop, force a rewrite turn; `false` disables. The discipline applies to every substantive reply, every status update, every summary — anywhere the agent writes to the operator between tool calls.
109
+
110
+ ## Override path
111
+
112
+ `SKIP_PLAIN_ENGLISH=1 <command>` — logged via trace-helper. Use rarely. Examples of legitimate overrides:
113
+
114
+ - Quoting an exact phrase from a memory file or external doc
115
+ - Migrating legacy text where rewriting would lose the audit trail
116
+ - Code blocks where the bassclef jargon IS the variable name
117
+
118
+ Override discipline: silence is not deferral. If you can't pair the override with a one-line reason, the rule probably applies.
119
+
120
+ For turn prose specifically, the override is the per-adopter toggle in `.claude/bassclef-configs.jsonc` — `prose_discipline.kiss_words_turn_prose: false` — not a per-command flag. Turn prose has no command to wrap, so the bypass lives at the configuration layer instead.
121
+
122
+ ## Composes with
123
+
124
+ - `skill-description-clarity.md` — narrow case at description surface
125
+ - `github-issue-flash-tweet.md` — narrow case at issue-body surface
126
+ - `context-engineering.md` — INSTEAD-block discipline (foundational)
127
+ - `visual-hierarchy.md` — formatting discipline for long output
128
+ - `commit-conventions.md` — commit message format (separate concern)
129
+ - `pr-strategy.md` — atomic PR rule (separate concern; both ship in Phase II Trim the Fat)
130
+ - `.claude/bassclef-configs.jsonc` — `prose_discipline.kiss_words_turn_prose` toggle backs the turn-prose row in the surfaces table (bassclef#1027)
131
+
132
+ ## Distinct from
133
+
134
+ - Code comment style (separate; not a top priority)
135
+ - API documentation (separate; OpenAPI/JSDoc conventions govern)
136
+ - Marketing copy (different audience; brand voice may override)
137
+
138
+ ## Sources read
139
+
140
+ - 2026-05-07 session — operator framing: "all writing must be in plain digestible english while not inventing words for common technical terms... drive for extreme simplicity. With so much agentic code and work to review, PRs and markdowns become the key areas where humans will interact"
141
+ - bassclef#557 PR body (rewritten in same session) — exemplar of obtuse-then-fixed prose
142
+ - bassclef#559 — broader plain-English discipline ticket
143
+ - `.claude/rules/skill-description-clarity.md` — narrow precedent at description surface
144
+ - `.claude/rules/context-engineering.md` — foundational INSTEAD-block rule
145
+ - `.claude/rules/github-issue-flash-tweet.md` — narrow precedent at issue surface
146
+ - Memory: `feedback_amazon_writing_style`, `feedback_plain_english_no_pseudo_intellectual`, `feedback_writing_voice`, `feedback_kiss_must_be_hook_enforced_on_skill_writes`, `feedback_kiss_prose_discipline_interactive`
147
+ - bassclef#1027 — turn-prose row + `prose_discipline.kiss_words_turn_prose` toggle (this rule's extension; original wrong-premise claim that turn prose was hook-unreachable corrected by bassclef#1051)
148
+ - bassclef#1051 — Stop hook `turn-prose-kiss-check.sh` (mechanical enforcement at the surface bassclef#1027 marked unreachable; sibling of `pr-body-scrub-check.sh`)
149
+ - bassclef#1026 — auto-save commit-sequence batch defect (today's session; sister discipline-application gap)
150
+ - bassclef#382 — substrate-clarity-gate hook (file-write enforcement at write surfaces; this row covers the gap that hook structurally can't reach)
151
+
152
+ ## Closes
153
+
154
+ Phase II WU-7a of Trim the Fat. Sister to WU-7b (hook extension) and WU-7c (skill updates). Master rule for all bassclef writing surfaces.
@@ -0,0 +1,317 @@
1
+ ---
2
+ tier: lite
3
+ description: Every PR body opens with a ## Problem section drafted by /state-a-problem brief + --- + ## Goal.
4
+ ---
5
+
6
+ # PR Body Shape Contract
7
+
8
+ Every PR body opens with a `## Problem` section drafted by `/state-a-problem brief` + `---` + `## Goal`. Detail comes AFTER. Operators and reviewers scan on mobile and multi-pane desktop. Without a problem-grounded opener, readers re-derive the reason for the PR every time. The skill is the contract. Hand-rolling reproduces the failure pattern bet 25k closed (see `docs/iteration-bets/2026-06-25k-discipline-visibility-and-pr-body-scrub-fix.md` § WU-1 L66 diagnosis).
9
+
10
+ This rule closes two gaps:
11
+
12
+ - **Mechanical.** Bassclef enforces what NOT to include in PR bodies (jargon BLOCK list + operator-private paths + strategic framing via `pr-body-scrub-check.sh`). No prior contract said what MUST appear at the opener.
13
+ - **Methodology.** The prior Flash + Tweet pair (bassclef#906) was solution-framed twice — neither stated user pain. bassclef#1178 retires the pair at PR + issue surfaces and replaces both with a single `## Problem` section that centers user pain before solution.
14
+
15
+ Sister to `.claude/rules/github-issue-flash-tweet.md` at the issue surface.
16
+
17
+ ## Why this rule exists
18
+
19
+ `/diagnose` on 2026-06-10 surfaced two root causes for PR body drift:
20
+
21
+ - **Root cause A** — no PR body shape contract. Authors improvised the first section name ("Goal", "What this PR ships", "What this PR delivers"). Sample drift across 12 recent PRs: 5 with explicit `## Goal`; 7 in other shapes.
22
+ - **Root cause B** — the `/kiss` substitution table and the PR-body-scrub hook JARGON_TERMS list used different word sets. Closed by bassclef#907 (single source of truth in `standards/bassclef-internal-jargon.md`).
23
+
24
+ V1 of this rule (bassclef#906) addressed Root cause A with Flash + Tweet + Goal. Operator observation on 2026-06-18 surfaced the gap. Flash and Tweet were both solution-framed. Neither stated user pain. Three UX research frameworks (NN/g, UX Design Institute, OpinionX) converge on a stable problem statement template (Who / What / When / Why-now / Outcome). bassclef#1178 retires Flash + Tweet at PR + issue surfaces and replaces both with a single `## Problem` section drafted by `/state-a-problem brief`.
25
+
26
+ The shape contract still does what V1 did — gives readers a clean entry. The entry is now grounded in the problem, not in the solution claim.
27
+
28
+ ## Format contract
29
+
30
+ Every PR body MUST open with:
31
+
32
+ ```markdown
33
+ **Problem (≤500 chars):** <Who + What + When + Why now + Outcome — framework implicit; drafted by /state-a-problem brief>
34
+
35
+ ---
36
+
37
+ ## Goal
38
+
39
+ <What this PR ships, in one paragraph. Why now.>
40
+
41
+ ## Evidence
42
+
43
+ - Source: <file path, ticket number, commit SHA — what backs the claim>
44
+ - Warrant: <one sentence tying the source to the claim>
45
+ ```
46
+
47
+ Format rules:
48
+
49
+ - **Problem label is bold and enclosed in `**`** — a visual scan handle, not body prose
50
+ - **Length limit enforced** — Problem ≤500 chars (matches `/state-a-problem brief` mode cap)
51
+ - **Plain language** — no bassclef jargon in the Problem section. The Problem section is the FIRST place a reader meets the work. Jargon here destroys orientation. `/state-a-problem` runs `/kiss --grade10` inline by default so the rule is hard to violate
52
+ - **Horizontal rule** (`---`) separates Problem from the structured body
53
+ - **`## Goal` is the first section after the rule** — not `## Summary`, not `## What this PR ships`, not `## Why this matters`. Goal is the agreed label
54
+ - **`## Evidence` follows Goal** — cites the source that backs the claim in Goal. Per `.claude/rules/assert-only-after-verify.md` — every operator-facing assertion carries source + warrant. Per `standards/opener-discipline.md` — the three-block opener extends to PR body via Problem + Goal + Evidence
55
+ - **One paragraph per** — Problem is 3-4 sentences; Goal is one paragraph; Evidence is one bullet source + one bullet warrant
56
+
57
+ ## Required sections (in order)
58
+
59
+ After Problem + `---`:
60
+
61
+ | Section | Required? | Purpose |
62
+ |---|---|---|
63
+ | `## Goal` | **MUST** | One paragraph. What this PR ships. Why now |
64
+ | `## Evidence` | **MUST** | Source + warrant per `.claude/rules/assert-only-after-verify.md`. Cites what backs the Goal claim |
65
+ | `## Summary` | MUST when scope >1 file | Bullet list of substantive changes |
66
+ | `## Test plan` | MUST | Checklist of how reviewer verifies |
67
+ | `## Out of scope` | SHOULD | What this PR explicitly does NOT do |
68
+ | `## /temperance + /luminary + /loop discipline` | **MUST under /longrun dispatch** | The three-skill cycle this PR ran (see below) |
69
+ | `## Refs` | SHOULD | Issue numbers, related PRs, source chronicles |
70
+
71
+ Other sections (Bundle justification, Inventory findings, Migration notes) appear between Goal and Test plan as needed. Drop sections that do not apply (e.g., Out of scope on a doc-only PR).
72
+
73
+ ## /temperance + /luminary + /loop discipline section (per bassclef-upstream#366)
74
+
75
+ Every PR authored under `/longrun` dispatch MUST carry a section with the literal header `## /temperance + /luminary + /loop discipline`. The section makes the per-PR cycle named in `.claude/rules/loop-discipline.md` visible at PR review time.
76
+
77
+ The header string is fixed and case-sensitive. The hook `pr-body-loop-discipline-check.sh` greps for it exactly. The section body names three things, one per bullet:
78
+
79
+ - **/temperance** fired at `<surface>`. Scope decision answer in one line. Drift trigger in one line.
80
+ - **/luminary** primary lens `<luminary-slug>` — one line on what the lens caught. Supporting lenses optional.
81
+ - **/loop** iteration count `<N>`. Outcome — RED then GREEN, OR rework cycle if any.
82
+
83
+ The fixed shape lets the grep check pass cleanly. It also gives readers a scannable three-line surface to verify discipline at PR review.
84
+
85
+ Why this section exists: bets 25h + 25i + 25j ran the discipline floor. Markers landed under `state/markers/temperance/`, `state/markers/luminary/`, and `state/markers/loop/` per branch. But the PR bodies stayed silent. The operator caught the gap mid-goal 25j: "I'm not seeing /luminary listed for PR review and /loop iteration through to closure." The mechanical floor was correct. The visible bar was missing. This section closes the bar the moment a reader scans the PR.
86
+
87
+ Forward-only enforcement. Already-merged PRs stay as is. Trivial-fix PRs under 3 files MAY skip the section per the Problem-section exception below.
88
+
89
+ ## What NOT to do
90
+
91
+ - **Don't open with a section header** before Problem. INSTEAD: Problem is the headline. Section headers come after the `---` rule.
92
+ - **Don't fall back to Flash + Tweet** — the V1 shape was solution-framed twice; neither stated user pain. INSTEAD: draft the Problem section via `/state-a-problem brief` mode. The skill produces the contract. The Who/What/When/Why-now/Outcome framework is implicit in the sentence shape it returns.
93
+ - **Don't replace `## Goal` with synonyms.** INSTEAD: `## Goal` is the bassclef first section label after Problem. Reviewers and substrate-coherence checks grep for it.
94
+ - **Don't bury the claim in `## Why this is needed` or `## Context` before Goal.** INSTEAD: the claim is the Problem + Goal pair. Context goes after.
95
+ - **Don't use bassclef jargon in Problem or Goal.** INSTEAD: substitute plain English per `.claude/rules/plain-english-discipline.md` and `standards/bassclef-internal-jargon.md`. `/state-a-problem` runs `/kiss --grade10` inline by default. Hand-rolled drafts run `/kiss --grade10` separately before push.
96
+
97
+ ## Trivial-fix exception
98
+
99
+ PRs with scope under 3 files AND no new SKILL.md AND no new rule MAY skip the Problem section. Trivial fixes (typo, env-var, off-by-one, one-line) often have no user-pain framing worth a section. The shape contract still requires `## Goal` as the opener in that case.
100
+
101
+ The CI shape check skips the Problem requirement when the touched-file count is under 3 AND no SKILL.md or rule file is in the change.
102
+
103
+ ## Ticket-close keyword discipline (bassclef#974)
104
+
105
+ When PR title carries `feat(#NNN):` or `fix(#NNN):` pattern, the body MUST include a `Closes #NNN` (or `Fixes #NNN` / `Resolves #NNN`) keyword. GitHub auto-closes tickets only when the closing keyword appears in the PR body — title alone does not trigger the close. Without the keyword, tickets stay open even after PRs merge, and the state-spine drifts from shipping reality.
106
+
107
+ Per whereami#28b diagnose — of the last 20 merged PRs at 2026-07-29, only 4 carried a closing keyword in the body. 16 shipped work but left the ticket open (including #934 and #935 which required manual backfill during Session 28b).
108
+
109
+ The `Refs` section is a good home for the keyword. Example:
110
+
111
+ ```markdown
112
+ ## Refs
113
+
114
+ - Closes bassclef#123 (parent ticket — this PR ships the acceptance)
115
+ - Refs bassclef#456 (related context — not closed by this PR)
116
+ ```
117
+
118
+ Use `Refs` for context-only tickets that survive this PR. Use `Closes` / `Fixes` / `Resolves` for tickets whose acceptance criteria this PR satisfies fully.
119
+
120
+ When a PR intentionally does NOT close its referenced ticket — for example, when the title cites a parent umbrella ticket but only ships one step — use `Refs #NNN` in the body and add a line explaining scope. Do NOT drop the closing keyword silently; document the choice.
121
+
122
+ **Mechanical layer.** `pr-body-scrub-check.sh` Rule 7 fires as ADVISORY in V1. Reads `$PR_TITLE` env var passed by `pre-gh-pr-body-scrub.sh` wrapper. Extracts `feat|fix(#NNN)` pattern from title. Checks body for `(Closes|Fixes|Resolves)\s+#NNN`. Emits stderr note when missing. Exit 0 (does not block). Advisory in V1 while adopters get used to the discipline; may flip to blocking after calibration.
123
+
124
+ ## Vocabulary discipline at authoring time (bassclef#915)
125
+
126
+ Per bassclef#915 V1: PR body authoring is a `/kiss` surface. Before invoking `gh pr create` (or `gh pr edit --body-file`), the agent runs `/kiss` words discipline against the body. It substitutes BLOCK and ADVISE-PHRASE terms from `standards/bassclef-internal-jargon.md`.
127
+
128
+ - **BLOCK terms** — substitute per `/kiss --grade10` table; PR-body-scrub Rule 1 catches what slips
129
+ - **ADVISE terms** — substitute per `/kiss --grade10` table; PR-body-scrub does not block on these
130
+ - **ADVISE-PHRASE terms** — substitute or rephrase; PR-body-scrub Rule 5 emits advisory CI annotations on hits (does not block)
131
+ - **ALLOW terms** (reserved per bassclef#763 — substrate, bassclef, cameo, Studio, Band, bandleader) — preserve
132
+
133
+ V2 pre-push hook for `/kiss`-on-PR-body authoring ships per bassclef#1176 (PR #1179 merged 2026-06-18). Local PreToolUse Bash hook scrubs PR body before `gh pr create` reaches GitHub.
134
+
135
+ ## When this rule fires
136
+
137
+ Every NEW PR body authored via:
138
+
139
+ - `gh pr create` — local PreToolUse hook fires (bassclef#1176); CI hook fires as backstop (bassclef#739)
140
+ - `gh pr edit` (body rewrite) — same shape contract applies
141
+ - Manual operator authoring via GitHub web UI — `.github/pull_request_template.md` auto-fills the shape; operator amends
142
+
143
+ Existing PRs are NOT retroactively backfilled. Forward-only enforcement keeps the discipline visible at the PR-creation surface where it lands.
144
+
145
+ ## Mechanical enforcement
146
+
147
+ V1 shipped methodology + `.github/pull_request_template.md` template + the rule (bassclef#906). V2 shipped local + CI Bash-matcher hooks for jargon scrub (bassclef#1176 + bassclef#1177). V3 (this bassclef#1178 amendment) ships:
148
+
149
+ - Shape contract enforces `## Problem` opener at feature-scope PRs
150
+ - `pr-body-scrub-check.sh` extended with a shape check that flags a missing `## Problem` section on feature-scope PRs
151
+ - `/state-a-problem brief` skill drafts the section (runs `/kiss --grade10` inline by default)
152
+ - `.github/pull_request_template.md` template updated to show the Problem-section shape
153
+
154
+ V4 (bassclef#974) ships Rule 7 — ticket-close keyword advisory. Local + CI hook layers extended:
155
+
156
+ - `pre-gh-pr-body-scrub.sh` extracts PR title, passes as `$PR_TITLE` env var
157
+ - `pr-body-scrub-check.sh` Rule 7 checks title-vs-body correlation for closing keyword
158
+ - 4 new Tier 0 tests pin behavior (Tests 27-30 in `.claude/hooks/tests/pre-gh-pr-body-scrub.test.sh`)
159
+ - Advisory in V1; V2 may flip to BLOCK after calibration
160
+
161
+ ## Override path
162
+
163
+ `SKIP_PR_BODY_SHAPE=1 <command>` — for genuinely-not-PR-body cases (e.g., release-tag PRs, automated bot PRs, dependabot updates where the bot controls the body format). Logged via trace-helper.
164
+
165
+ INSTEAD of overriding for tight scope: write the Problem section. Three sentences carrying the framework cost less than reviewer re-derivation.
166
+
167
+ ## Worked examples
168
+
169
+ ### Anti-pattern (Root cause A — what NOT to do)
170
+
171
+ ```markdown
172
+ ## Summary
173
+
174
+ Add `/longrun` skill for autonomous long-running sessions...
175
+
176
+ ## Why this is needed
177
+
178
+ Recurring pattern observed over March-April 2026 sessions...
179
+ ```
180
+
181
+ Reviewer reads title → "Summary" header → 3 paragraphs to find the claim. Claim is buried. User pain stays unstated.
182
+
183
+ ### Anti-pattern (V1 Flash + Tweet — superseded by bassclef#1178)
184
+
185
+ ```markdown
186
+ **Flash (≤180 chars):** Add `/longrun` skill — autonomous sessions paced by checkpoints and closeout discipline.
187
+
188
+ **Tweet (≤280 chars):** Sessions over 50 turns drift without checkpoints. `/longrun` adds prep / checkpoint / closeout modes.
189
+ ```
190
+
191
+ Better than no shape. But solution-framed twice. Reader still does not know WHY this work exists — only WHAT it does.
192
+
193
+ ### Conformant pattern (bassclef#1178 — Problem opener)
194
+
195
+ ```markdown
196
+ **Problem (≤500 chars):** Today autonomous sessions over 50 turns drift without structured checkpoints — operators return mid-session to mid-stream context, no anchor on what shipped, what's blocked, or what's next. The /longrun skill adds prep / checkpoint / closeout modes that pace the session against named phase boundaries. The change we want is sessions over 50 turns that return clean state every time, not a context-archaeology task on every wake.
197
+
198
+ ---
199
+
200
+ ## Goal
201
+
202
+ Ship `/longrun` skill so autonomous sessions running >50 turns or across compaction boundaries have substrate-enforced pacing.
203
+
204
+ ## Summary
205
+
206
+ - New `.claude/skills/longrun/SKILL.md` with three modes
207
+ - ...
208
+ ```
209
+
210
+ Reviewer gets user pain → solution → diff in 60 seconds. Detail follows for those who want depth.
211
+
212
+ ## Composes with
213
+
214
+ - `.claude/skills/state-a-problem/SKILL.md` — drafts the Problem section in brief mode (≤500 chars); runs `/kiss --grade10` inline by default
215
+ - `.claude/rules/github-issue-flash-tweet.md` (bassclef#484 — amended by bassclef#1178) — sister rule at issue-body surface
216
+ - `.claude/rules/plain-english-discipline.md` (bassclef#790) — plain language requirement for Problem and Goal
217
+ - `standards/pr-body-discipline.md` (bassclef#787) — scrub discipline at same surface
218
+ - `.claude/rules/operator-facing-prose.md` (bassclef#790) — operator-facing prose discipline
219
+ - `.claude/hooks/pr-body-scrub-check.sh` — sibling mechanical surface (CI hook); extended in bassclef#1178 with shape check
220
+ - `.claude/hooks/pre-gh-pr-body-scrub.sh` — local pre-push hook (bassclef#1176)
221
+ - `.github/pull_request_template.md` — auto-fill at PR-creation surface; updated for the Problem shape
222
+ - bassclef#915 — phrase-shaped advisory perimeter (sister at vocabulary surface)
223
+ - bassclef#907 — `/kiss` overhaul (single source of truth wordlist)
224
+
225
+ ## Distinct from
226
+
227
+ - `commit-conventions.md` — commit messages have a separate format; this rule applies to PR BODIES, not commits
228
+ - `iteration-bet-brief-completeness.md` — that's about delegation briefs (handoff content); this is about the PR-creation surface
229
+ - `pattern-annotation.md` — that's source-code annotation discipline; orthogonal
230
+
231
+ ## Sources read
232
+
233
+ - bassclef#906 — V1 parent ticket (Flash + Tweet + Goal shape; superseded at the opener)
234
+ - bassclef#1178 — V3 amendment (Problem section + `/state-a-problem` skill)
235
+ - bassclef#484 (`.claude/rules/github-issue-flash-tweet.md`) — sister discipline at issue surface
236
+ - bassclef#787 (`standards/pr-body-discipline.md`) — sister discipline at scrub surface
237
+ - bassclef#907 — `/kiss` overhaul (closes Root cause B)
238
+ - bassclef#915 — phrase-shaped advisory perimeter
239
+ - bassclef#1176 — V2 local PR-body scrub hook (PR #1179 merged 2026-06-18)
240
+ - bassclef#1177 — V2 extends to gh issue + commit messages (PR #1180 merged 2026-06-18)
241
+ - 2026-06-10 chronicle — V1 /diagnose finding
242
+ - 2026-06-18 chronicle `chronicle/2026-06-18-v2-issue-and-commit-scrub.md` — V3 operator observation
243
+ - NN/g, UX Design Institute, OpinionX problem-statement frameworks — the templates `/state-a-problem` synthesizes
244
+
245
+ ## Closes
246
+
247
+ - V1 of bassclef#906 — Flash + Tweet + Goal shape
248
+ - V2 of bassclef#906 — local + CI scrub at the opener (bassclef#1176 + bassclef#1177)
249
+ - V3 of bassclef#906 — Problem section opener replacing Flash + Tweet (bassclef#1178 — this amendment)
250
+
251
+ ## Section-level DON'T / INSTEAD catalog (bassclef#1241)
252
+
253
+ The catalog rows below encode authoring-time discipline per section. The wordlist scrub hook is the FLOOR. This catalog is the BAR. Apply the per-section catalog before the body ships rather than relying on the hook to catch what slipped past you.
254
+
255
+ The catalog was drafted from two PR-authoring failures on 2026-06-19 (one wordlist-bypass via curl, one wordlist-as-bar drift). See bassclef#1241 for the source incidents.
256
+
257
+ ### Problem section
258
+
259
+ Composes with `/state-a-problem brief`. Catalog rows below apply per-sentence inside the Problem block.
260
+
261
+ | Don't | INSTEAD |
262
+ |---|---|
263
+ | Name script line numbers for internal mechanics ("L17 structural --execute gate") | Name the user-visible behavior ("the --execute flag is what makes it run") |
264
+ | Third-person self-reference ("the operator can...", "the agent has no...") | Address the operator directly ("you can...", "I do not know your...") |
265
+ | Bassclef-invented compounds (`discovery surface`, `registry shape`, `local-only discipline`, `Pattern-B'd`, `wiki-as-we-go discipline`, `source-of-truth`, `narrative moment`) | Plain restatement of what the compound names ("the screens the operator sees", "the file structure", "this rule that keeps chronicles local", "moved", "this rule that says check the wiki at every closeout", "the authoritative answer", "story worth telling") |
266
+ | Buzz adjectives (`substantive`, `comprehensive`, `robust`, `leverage`) | Concrete data ("25-line block", "13/13 tests pass") |
267
+ | Bassclef-internal nouns without gloss (`deferred-action`, `INFORM`, `Pattern B`) at first mention | First-mention gloss ("deferred-action file (the next session sees it as a TODO)") |
268
+ | Nested parentheticals (`X (which is Y (per Z))`) | Split into separate sentences |
269
+
270
+ ### Goal section
271
+
272
+ | Don't | INSTEAD |
273
+ |---|---|
274
+ | Methodology references the reader doesn't carry ("Phase 14 of the chain") | Name what ships and why now |
275
+ | Multi-clause noun-piles ("substantive N-line block documenting A, B, C, D, and E") | Split into a bullet list |
276
+ | Quote the rule's title as if it were the goal ("Apply bassclef#790 Rule 2 meta-discipline") | Name what the operator sees after merge ("/longrun's skill body reads in plain English") |
277
+
278
+ ### Summary section
279
+
280
+ | Don't | INSTEAD |
281
+ |---|---|
282
+ | Invented compound verbs (`Pattern-B'd`, `scrubbed-and-shipped`) | Plain English ("moved to completed/", "rewrote and pushed") |
283
+ | Code-fenced literals used as if prose (`` `_comment` replaced with substantive block ``) | Plain restatement ("Added a 25-line comment header that documents...") |
284
+ | Restate the goal doc verbatim | Pick the 3-5 changes that matter to a reviewer |
285
+
286
+ ### Test plan section
287
+
288
+ | Don't | INSTEAD |
289
+ |---|---|
290
+ | Assertions in bassclef-internal idiom ("Deferred-action surfaces at next session-start as INFORM") | Observable behavior ("Next session-start banner shows this under 'Info' (not 'Blocked')") |
291
+ | Tense the reviewer can't verify without running ("hook fires clean") | What the reviewer can grep / run (`jq .pseudonyms[].pseudonym` returns `Falcon`) |
292
+
293
+ ### Out of scope section
294
+
295
+ | Don't | INSTEAD |
296
+ |---|---|
297
+ | Third-person reference ("the agent cannot author...") | Direct ("I can't author entries — only you know your codenames") |
298
+ | Defer-and-justify in the same line | Split: "X — not in this PR. Y — already tracked at #N" |
299
+
300
+ ### Refs section
301
+
302
+ | Don't | INSTEAD |
303
+ |---|---|
304
+ | Long bassclef-internal qualifiers in parentheses | One-line ref per line, plain |
305
+
306
+ ### Section-cross-cutting rules
307
+
308
+ | Don't | INSTEAD |
309
+ |---|---|
310
+ | Repeat literal filenames in title and body Summary together | Plain title; filenames in body where they're grep-anchored |
311
+ | Mix `skillname` and `/skillname` for the same skill | Use `/skillname` consistently when referencing the skill; plain filename when referencing the file |
312
+ | Use bassclef-internal verbs (`flip`, `Pattern-B'd`, `seed` as noun) | Plain verbs (`update`, `move`, `set up`) |
313
+ | Drop session-invented shorthand (`Bucket 2a`, `Path B`, `S2`, `Option F`, `LR-1`) without an appositive on first mention per section | Gloss inline: `Bucket 2a (audit files with no tier tag at all)`; `S2 (Session 2 — Traceability Phase 1)`; per `.claude/rules/operator-facing-prose.md` Rule 1 extended per bassclef-upstream#1267 |
314
+
315
+ ## Retirement condition
316
+
317
+ If observed across 6 months with zero operator-flagged shape drift on the Problem section, this rule is correctly calibrated. If `## Problem` first-section drift returns above 10% of sampled feature-scope PRs, the V3 CI shape check escalates from advisory to blocking. The catalog rows ship without an a-priori retirement condition — they encode discipline that survives any future skill or hook build.
@@ -0,0 +1,167 @@
1
+ ---
2
+ tier: lite
3
+ description: "The default PR strategy for any multi-issue iteration is stacked atomic branches: one branch per issue, one PR per branch, each independently reviewable and revertable."
4
+ ---
5
+
6
+ # PR Strategy — Stacked Default (Mechanically Enforced)
7
+
8
+ The default PR strategy for any multi-issue iteration is **stacked atomic
9
+ branches**: one branch per issue, one PR per branch, each independently
10
+ reviewable and revertable. Bundling multiple issues into a single PR is
11
+ the **explicit override**, requested via `bundle: true` in the iteration
12
+ goal's frontmatter (or operator statement) at iteration scaffold time.
13
+
14
+ This rule was methodology-only in v0. **As of Phase II Trim the Fat
15
+ (2026-05-07), it is mechanically enforced** by the `atomic-pr-check.sh`
16
+ hook, which fires on `git push` and BLOCKs branches with multiple WU-N
17
+ tags in commit messages unless a matching iteration goal declares
18
+ `bundle: true` in frontmatter.
19
+
20
+ INSTEAD of relying on agent self-discipline: the hook reads the branch's
21
+ commits, counts distinct WU-N tags, and either passes (≤1 distinct tag)
22
+ or BLOCKs with a structured remediation message (multi-step without
23
+ `bundle: true`).
24
+
25
+ ## Default behavior
26
+
27
+ When `/autonomous start` enters Construction with N≥2 issues in scope:
28
+
29
+ - Each issue → its own branch (`feature/ISSUE-NNN-stack-N-slug`)
30
+ - Each branch → its own PR
31
+ - Per `standards/branch-stacking.md`: independence is designed in,
32
+ graceful unwind is mechanical, manifest declares dependencies
33
+ - Boot sequence does NOT ask "stacked or bundled?" — assumes stacked
34
+
35
+ ## Override: `bundle` flag
36
+
37
+ To collapse a multi-issue iteration into a single PR, the operator
38
+ supplies `bundle` at boot:
39
+
40
+ ```
41
+ /autonomous start orchestrator-gated bundle
42
+ /autonomous start operator-gated sequential bundle
43
+ ```
44
+
45
+ Or states it conversationally during scope confirmation. The default
46
+ short-circuits unless the override is present.
47
+
48
+ ## When bundling IS acceptable
49
+
50
+ Use `bundle` when ALL of these hold:
51
+
52
+ 1. **Single logical concern** — all changes serve one decision; splitting
53
+ would be artificial (e.g., a tightly-coupled rename across N files
54
+ that doesn't compile in isolation).
55
+ 2. **Tight coupling that breaks atomic verification** — branch N can't
56
+ pass `/verify` without branch M's changes (decomposition gap, not a
57
+ feature).
58
+ 3. **Emergency hotfix** — staging delay between PRs would compound the
59
+ incident; one PR + one merge gets fixes to prod faster.
60
+ 4. **Operator explicitly requests** — `bundle` flag or verbatim
61
+ instruction.
62
+
63
+ If only #4 holds without #1-3, push back: "stacked is default; what
64
+ about this scope makes bundling correct?"
65
+
66
+ ## When stacking is mandatory
67
+
68
+ Stack regardless of operator preference when:
69
+
70
+ - **Mix of skill + rule + hook changes** — different review surfaces;
71
+ reviewer needs to evaluate each independently
72
+ - **Mix of new files + existing-file edits** — independent revert paths
73
+ - **Different blast radii** — high-radius changes (hooks, schemas)
74
+ shouldn't ride with low-radius (doc edits) in one PR
75
+ - **Multi-WS iteration goal** — workstreams are separate intents by
76
+ definition
77
+
78
+ ## Why this rule exists
79
+
80
+ Every autonomous session before this rule asked "stacked or bundled?"
81
+ Operator answered "stacked" 100% of the time, with `bundle` as a rare
82
+ tactical override (~1 in 20 sessions). Codifying the default eliminates
83
+ the round-trip per bet × bet count × consumer count.
84
+
85
+ Source: operator feedback 2026-04-18 — "default is 'stacked', override
86
+ is 'bundle', so '/pr bundle'." Filed bassclef #177.
87
+
88
+ ## Eat-our-own-dogfood note
89
+
90
+ The PR that ships this rule is itself stacked (with #173) — proves the
91
+ default in the same iteration that codifies it.
92
+
93
+ ## Enforcement
94
+
95
+ - **Hook (mechanical)**: `.claude/hooks/atomic-pr-check.sh` fires on
96
+ Bash tool calls matching `git push`. Counts distinct WU-N tags in
97
+ branch commits. BLOCKs multi-step branches without `bundle: true` in
98
+ a matching iteration goal's frontmatter. Phase II Trim the Fat
99
+ shipped this as the v1 mechanical-enforcement layer.
100
+ - **Boot sequence** (`strategy/autonomous-boot-sequence.md` Step 4):
101
+ scaffold prompt skips PR-strategy question unless `bundle: true`
102
+ supplied
103
+ - **Skill args** (`.claude/skills/autonomous/SKILL.md`): `bundle` listed
104
+ in args reference table
105
+ - **Standard** (`standards/branch-stacking.md`): declares stacked as
106
+ default at the top
107
+ - **Methodology**: agent self-checks before pushing; the hook is the
108
+ backstop, not the only line of defense
109
+
110
+ INSTEAD of methodology-only enforcement: the hook fires automatically
111
+ on every `git push`. Bypass with `SKIP_ATOMIC_PR_CHECK=1` (logged via
112
+ trace-helper) only for genuine bypass cases.
113
+
114
+ ## Override path
115
+
116
+ `bundle` at boot. No mid-session switch — once a stack manifest is
117
+ written, the strategy is locked for that bet (changing mid-flight would
118
+ require re-decomposing scope).
119
+
120
+ ## Merge protocol — MUST read before merging any stacked PR
121
+
122
+ When merging stacked PRs with declared dependencies (Graphite-style:
123
+ dependent PR's `baseRefName` is another feature branch, not `main`),
124
+ **read `standards/branch-stacking.md` §"Squash merge — two protocols"
125
+ BEFORE the first merge in the stack**.
126
+
127
+ Two protocols exist; picking one is mandatory:
128
+
129
+ 1. **Retarget-before-merge** (preferred) — retarget dependents to
130
+ `main` via `gh pr edit <PR> --base main` before merging the parent.
131
+ Dependents survive the cascade.
132
+ 2. **Rebase-after-merge** (fallback) — only if auto-close already
133
+ fired. Per-PR rebase + re-create. Costs 3-8 turns per stack.
134
+
135
+ Helper: `scripts/check-stack-dependents.sh <PR-N>` lists PRs that
136
+ will auto-close when PR N merges with `--delete-branch`.
137
+
138
+ **Why this rule repeats what the standard says**: agents load the
139
+ `.claude/rules/` directory automatically. Standards live in
140
+ `standards/` and are referenced by path. Moving the ceremony-layer
141
+ pointer into the rule means an agent that reads `pr-strategy.md`
142
+ at merge-time is told to go read the protocol — closes the
143
+ "standard exists but agent didn't read it before acting" gap
144
+ observed 2026-04-22 (#245 auto-closed on #244 merge because the
145
+ retarget protocol wasn't consulted).
146
+
147
+ ## Relationship to other rules
148
+
149
+ - `branching.md` — trunk-based + squash merge (governs all branches)
150
+ - `iteration-bet-brief-completeness.md` — Orchestrator transmits
151
+ manifest to Builder; manifest carries the strategy decision
152
+ - `commit-conventions.md` — PR titles per format regardless of strategy
153
+ - `bassclef-workflow-parity.md` — sibling-grep discipline applies per
154
+ PR, not per strategy
155
+ - `standards/branch-stacking.md` §"Squash merge — two protocols" —
156
+ merge-time recovery protocols; MUST read before first merge in any
157
+ stack
158
+
159
+ ## Retirement condition
160
+
161
+ If observed over 6 months and `bundle` ratio stays below 5% with zero
162
+ operator corrections of the default, this rule is correctly calibrated.
163
+ If `bundle` ratio rises above 25%, re-shape — the default may have
164
+ drifted from operator intent. If 0% bundle for 12 months, consider
165
+ removing the override entirely.
166
+
167
+ Closes bassclef #177.