@jeffober/thatch 0.1.40 → 0.1.42

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -66,7 +66,7 @@ Include thatch's instructions in your agent's system prompt manually; see
66
66
 
67
67
  ## What's inside
68
68
 
69
- Thatch gives your agent three layers of persistent context:
69
+ Thatch gives your agent:
70
70
 
71
71
  - **Memory** -- save, search, and recall knowledge across sessions with
72
72
  local embeddings (bge-small-en-v1.5) and SQLite. Every project gets its
@@ -89,11 +89,25 @@ Thatch gives your agent three layers of persistent context:
89
89
  `session_get`, opencode only) and as CLI subcommands (`thatch session
90
90
  list/get/transcript/search`, JSONL output designed for piping to `jq`).
91
91
  - **Watchers** -- event-driven notifications from external sources (opencode
92
- only). The agent registers a watch on a GitHub PR or branch (main); thatch polls it in the
93
- background and prompts the session when comments, commits, CI results, or
94
- status changes arrive. Notifications carry pointer data only.
95
- - **Notifications + user config** -- the agent can ping you out-of-band when
96
- a long-running outcome lands: a desktop banner, a spoken voice
92
+ only). The agent registers a watch on a GitHub PR, a branch (main), or a
93
+ local shell command; thatch polls it in the
94
+ background and prompts the session when comments, commits, CI results, status changes, or a
95
+ watched command's exit-0 condition arrive. Notifications carry pointer
96
+ data plus machine status (check conclusions, exit codes), never external
97
+ content.
98
+ - **Cross-session chat** -- your agent sessions can message each other
99
+ (opencode, Claude Code, and Cursor; same machine). opencode sessions
100
+ join the directory automatically under an assigned, never-reused name
101
+ (a slug of the session title plus a counter); others see the roster, and
102
+ messages land in inboxes -- opencode sessions get woken with a prompt
103
+ when idle, other hosts see pending mail at their next prompt. Loop-safe:
104
+ messages are informational to the receiving agent, and wake prompts are
105
+ rate-capped. Delivered messages are framed as untrusted content so a
106
+ hostile message cannot impersonate your instructions. Disable the whole
107
+ feature with `chat.enabled: false` in the thatch config (or just the
108
+ auto-joining with `chat.autoRegister: false`).
109
+ - **Notifications + user config** -- the agent can ping you out-of-band when a
110
+ long-running outcome lands: a desktop banner, a spoken voice
97
111
  announcement, or both (macOS and Linux). Preferences live in a
98
112
  hand-editable config file (`~/.config/thatch/config.json`) that the agent
99
113
  manages through `config_get`/`config_set` -- ask it to change your voice
@@ -113,10 +127,13 @@ host.
113
127
  Everything is local. The embedding model downloads once from Hugging Face Hub
114
128
  and is cached. No data leaves your machine.
115
129
 
116
- One exception: watchers (opencode only) call the GitHub API through the `gh`
117
- CLI to poll PRs you explicitly asked to watch, using your existing gh
118
- authentication. Thatch never sees or stores the token, and notifications
119
- carry pointer data only - GitHub comment text never enters your context
130
+ One exception: PR and branch watchers (opencode only) call the GitHub API
131
+ through the `gh` CLI to poll targets you explicitly asked to watch, using
132
+ your existing gh authentication; command watchers run local shell commands
133
+ in the project directory, reading only their exit codes. Thatch never sees
134
+ or stores the gh token, and notifications
135
+ carry pointer data plus machine status (check conclusions, exit codes),
136
+ never external content - GitHub comment text never enters your context
120
137
  unless the agent fetches it.
121
138
 
122
139
  ## Development
@@ -105,7 +105,7 @@ For each review unit, dispatch sub-agents using the Task tool. Each sub-agent ru
105
105
 
106
106
  8. **Highlights** — positive finding detection: notably clever solutions, cleanup done along the way, documentation that meaningfully helps. Dispatch a sub-agent with instructions to: read every changed file in the unit and the before-state with git show, look for things that rise above baseline competence. Medium-high bar: no generic praise, no baseline competence. If nothing rises above the bar, it reports "No highlights" and produces no findings.
107
107
 
108
- 9. **Mentorship** — peer-mentorship teaching lens: helpers and internal packages the author may not have seen, companion techniques, house patterns, test-craft, API-shape principles, next-reader discoverability. Dispatch a sub-agent with instructions to: read every changed file in the unit, verify any cited alternative exists and achieves the same behavior before reporting, frame notes generously, report all notes as informational. If nothing qualifies, it reports "No mentorship notes" and produces no findings.
108
+ 9. **Technique** — teaching-grade lens on better ways to do it: helpers and internal packages the author may not have seen, companion techniques, house patterns, test-craft, API-shape principles, next-reader discoverability. Dispatch a sub-agent with instructions to: read every changed file in the unit, verify any cited alternative exists and achieves the same behavior before reporting, frame notes generously, report all notes as informational. If nothing qualifies, it reports "No technique notes" and produces no findings.
109
109
 
110
110
  For the integration review unit (5+ points), dispatch a sub-agent focused on:
111
111
  - Cross-component contracts — do the interfaces between components match?
@@ -137,7 +137,7 @@ Confirmed LOW findings are mandatory in the final report, including mechanical f
137
137
 
138
138
  Confirmed highlights (from the highlights specialist) appear in a `### Highlights` section after the workflow changes and before the confirmed findings. Most PRs will have none — that is expected. Do not pad with borderline calls. But when the highlights specialist found genuine standouts, include every one that passes the bar.
139
139
 
140
- Mentorship notes (from the mentorship specialist) appear in a `### Mentorship notes` section after Highlights and before the confirmed findings. They are teaching-grade observations (existing helpers, companion techniques, house patterns, test-craft, API-shape principles, next-reader discoverability), always informational, never merged into defect findings and never blocking. Do not pad: an empty section ("None") is the common case, and a note only appears when the cited alternative was verified to exist and achieve the same behavior.
140
+ Technique notes (from the technique specialist) appear in a `### Technique notes` section after Highlights and before the confirmed findings. They are teaching-grade observations (existing helpers, companion techniques, house patterns, test-craft, API-shape principles, next-reader discoverability), always informational, never merged into defect findings and never blocking. Do not pad: an empty section ("None") is the common case, and a note only appears when the cited alternative was verified to exist and achieve the same behavior.
141
141
 
142
142
  **Follow-up round cross-reference** — if Step 2 built a prior-comments register, the synthesizer must cross-reference every confirmed and rejected finding against it (see the synthesizer skill's "Cross-reference against prior review comments" section). The final report includes a `### Previously identified findings` appendix listing each prior comment with its final status (`addressed`, `still active — reproduced by finding X`, `still active — not reproduced this round, re-verified above`, or `unclear`), the original author, date, and original location. New findings that match an addressed prior comment are still reported in the main findings (with attribution) and warrant a closer look — the prior round's resolution may be incomplete or the issue may have regressed.
143
143
 
@@ -145,10 +145,10 @@ Alternatively, perform the synthesis yourself:
145
145
  1. Read each finding's cited location to verify evidence accuracy.
146
146
  2. Deduplicate findings flagged by multiple specialists.
147
147
  3. Group findings by root cause where multiple findings stem from the same issue.
148
- 4. Classify each as CONFIRMED, REJECTED, or UNVERIFIABLE. For behavioral findings, apply citation verification, reachability, and intent verification. For mechanical findings, verify the cited text exists, is branch-introduced or newly made relevant, and violates the stated guideline or specialist taxonomy. For highlights, verify the cited text exists, the claim is accurate, and the highlighted thing genuinely rises above baseline competence. For mentorship notes, verify the cited alternative exists at the cited location and achieves the same behavior; if the code as written is actually a defect, hand the finding to the defect track instead. When the brief reports staleness (main moved past the merge-base touching this change's paths), re-verify each behavioral finding against current main first — a finding true only at the merge-base is a rebase note for the author, not a defect in this PR.
148
+ 4. Classify each as CONFIRMED, REJECTED, or UNVERIFIABLE. For behavioral findings, apply citation verification, reachability, and intent verification. For mechanical findings, verify the cited text exists, is branch-introduced or newly made relevant, and violates the stated guideline or specialist taxonomy. For highlights, verify the cited text exists, the claim is accurate, and the highlighted thing genuinely rises above baseline competence. For technique notes, verify the cited alternative exists at the cited location and achieves the same behavior; if the code as written is actually a defect, hand the finding to the defect track instead. When the brief reports staleness (main moved past the merge-base touching this change's paths), re-verify each behavioral finding against current main first — a finding true only at the merge-base is a rebase note for the author, not a defect in this PR.
149
149
  5. Cross-reference against the prior-comments register if one was built in Step 2: tag matching findings `Provenance: previously identified by @author, PR #N, DATE` and produce the `### Previously identified findings` appendix per the synthesizer skill.
150
150
  6. Calibrate severity (BLOCKING > HIGH > MEDIUM > LOW) based on your verification.
151
- 7. Produce a final report with a workflow-change preface, highlights (if any), mentorship notes (if any), findings grouped by severity, coverage gaps, and human-verifiable unknowns noted. Include every confirmed LOW finding.
151
+ 7. Produce a final report with a workflow-change preface, highlights (if any), technique notes (if any), findings grouped by severity, coverage gaps, and human-verifiable unknowns noted. Include every confirmed LOW finding.
152
152
  8. Apply the synthesizer's "Writing review comments" prose rules to the whole report. Findings are prose, not shorthand: plain English, one idea per sentence, one sentence per hop of any producer chain.
153
153
 
154
154
  ## Specialist briefing template
@@ -3,7 +3,7 @@ name: thatch-review-synthesizer
3
3
  description: Verify and synthesize findings from multiple review specialist skills into a single deduplicated, severity-grouped report. Use after running one or more thatch-review-* specialist skills.
4
4
  ---
5
5
 
6
- You are a review synthesizer. You have received findings from one or more review specialists (pedantic, acceptance, state-flow, economy, no-slop, breadcrumbs, mark-and-sweep, highlights, mentorship). Your job is to verify their citations against the actual code, deduplicate across specialists, and produce a single, coherent final report.
6
+ You are a review synthesizer. You have received findings from one or more review specialists (pedantic, acceptance, state-flow, economy, no-slop, breadcrumbs, mark-and-sweep, highlights, technique). Your job is to verify their citations against the actual code, deduplicate across specialists, and produce a single, coherent final report.
7
7
 
8
8
  ## Static analysis only
9
9
  You review code by reading it. Do NOT run tests, linters, compilers, or any build commands.
@@ -48,13 +48,13 @@ For each finding from the specialists:
48
48
  - For CLEANUP highlights: verify the bad code existed in the before-state (use git show with the base commit). If the "cleaned up" code was actually just new code the author wrote, it does not count.
49
49
  Runtime reachability, producer chains, and intent verification do not apply. A highlight is not a bug and does not need a trigger scenario.
50
50
 
51
- 4i. **Mentorship verification (mentorship).** For mentorship notes, verification means:
51
+ 4i. **Technique verification (technique).** For technique notes, verification means:
52
52
  - The cited alternative exists at the cited location (`path:line` read directly; documentation links confirmed, not assumed). A note citing a helper that does not exist is rejected outright.
53
53
  - The equivalence claim is accurate: the cited alternative achieves the same behavior as the code under review, including error cases. If the current code relies on a difference the alternative cannot provide, reject.
54
54
  - The code as written is not a defect. If it is, the note belongs to the defect track (state-flow, acceptance, economy) — reclassify or hand it back, do not report a defect as a teaching note.
55
55
  - The note is teaching-grade, not condescension: the framing is "you may not have seen this", and the author's diff does not already demonstrate they know it.
56
56
  - For TEST_CRAFT notes: verify the repo's own test conventions (read sibling test files) before confirming — repo convention beats the lens preference.
57
- Runtime reachability, producer chains, and intent verification do not apply. A mentorship note is not a bug and does not need a trigger scenario. All mentorship notes are informational and never blocking.
57
+ Runtime reachability, producer chains, and intent verification do not apply. A technique note is not a bug and does not need a trigger scenario. All technique notes are informational and never blocking.
58
58
 
59
59
  4e. **Economy verification (economy).** For economy findings (unnecessary complexity, simpler alternatives, redundancy, tradeoffs), verification means:
60
60
  - The cited code exists at the cited location (already confirmed in step 2).
@@ -65,8 +65,8 @@ For each finding from the specialists:
65
65
  Runtime reachability, producer chains, and intent verification do not apply. An economy finding is a design observation, not a user-triggered bug.
66
66
 
67
67
  7. **Classify:**
68
- - **CONFIRMED**: For behavioral findings: the cited code matches, the claim is accurate, the bug is reachable through realistic usage, you proved the workflow/producer chain where applicable, the behavior is not intentional, and for data-shape findings you read and cited the governing constraint confirming the claimed state is reachable. For mechanical findings: the cited text exists, is branch-introduced or newly made relevant, and violates the stated guideline or specialist taxonomy. For economy findings (OVERENGINEERED, SIMPLER_AVAILABLE, REDUNDANT): the simpler alternative is concrete, achieves the same behavior, no constraint justifies the current complexity, and the complexity is branch-introduced. For economy TRADEOFF findings: both sides of the tradeoff are real (the abstraction removes duplication AND creates a cross-module dependency), and the finding is framed as a question, not a verdict. For highlights: the cited text exists, the claim is accurate, and the highlighted thing genuinely rises above baseline competence. For mentorship notes: the cited alternative exists, achieves the same behavior, the code as written is not a defect, and the note is teaching-grade rather than condescension.
69
- - **REJECTED**: For behavioral findings: the citation is wrong, the claim is inaccurate, the bug cannot manifest in the actual runtime context, the behavior is an intentional design decision (explain why briefly), or a governing constraint (NOT NULL, FK, type, guard) forecloses the claimed state. Reject findings that rely on manually seeded invalid state/data with no real producer path. For mechanical findings: the cited text does not exist, does not violate the stated guideline, is unchanged legacy outside the touched scope, or the finding duplicates another confirmed finding. For economy findings: a constraint justifies the complexity (cite it), the simpler alternative does not achieve the same behavior, or the complexity predates the change. For economy TRADEOFF findings: only one side of the tradeoff is real (e.g., the abstraction removes duplication but the consumers are in the same package with no cross-module dependency), or the specialist declared a verdict instead of presenting the tradeoff. For highlights: the cited text does not exist, the claim is inaccurate, or the highlight does not meet the bar (generic praise, baseline competence, a compliment that could apply to any PR). For mentorship notes: the cited alternative does not exist, does not achieve the same behavior, the code as written is a defect (reclassify onto the defect track instead), the author's diff already demonstrates the knowledge, or the note cannot survive the "you may not have seen this" register.
68
+ - **CONFIRMED**: For behavioral findings: the cited code matches, the claim is accurate, the bug is reachable through realistic usage, you proved the workflow/producer chain where applicable, the behavior is not intentional, and for data-shape findings you read and cited the governing constraint confirming the claimed state is reachable. For mechanical findings: the cited text exists, is branch-introduced or newly made relevant, and violates the stated guideline or specialist taxonomy. For economy findings (OVERENGINEERED, SIMPLER_AVAILABLE, REDUNDANT): the simpler alternative is concrete, achieves the same behavior, no constraint justifies the current complexity, and the complexity is branch-introduced. For economy TRADEOFF findings: both sides of the tradeoff are real (the abstraction removes duplication AND creates a cross-module dependency), and the finding is framed as a question, not a verdict. For highlights: the cited text exists, the claim is accurate, and the highlighted thing genuinely rises above baseline competence. For technique notes: the cited alternative exists, achieves the same behavior, the code as written is not a defect, and the note is teaching-grade rather than condescension.
69
+ - **REJECTED**: For behavioral findings: the citation is wrong, the claim is inaccurate, the bug cannot manifest in the actual runtime context, the behavior is an intentional design decision (explain why briefly), or a governing constraint (NOT NULL, FK, type, guard) forecloses the claimed state. Reject findings that rely on manually seeded invalid state/data with no real producer path. For mechanical findings: the cited text does not exist, does not violate the stated guideline, is unchanged legacy outside the touched scope, or the finding duplicates another confirmed finding. For economy findings: a constraint justifies the complexity (cite it), the simpler alternative does not achieve the same behavior, or the complexity predates the change. For economy TRADEOFF findings: only one side of the tradeoff is real (e.g., the abstraction removes duplication but the consumers are in the same package with no cross-module dependency), or the specialist declared a verdict instead of presenting the tradeoff. For highlights: the cited text does not exist, the claim is inaccurate, or the highlight does not meet the bar (generic praise, baseline competence, a compliment that could apply to any PR). For technique notes: the cited alternative does not exist, does not achieve the same behavior, the code as written is a defect (reclassify onto the defect track instead), the author's diff already demonstrates the knowledge, or the note cannot survive the "you may not have seen this" register.
70
70
  - **UNVERIFIABLE**: The citation is correct but you cannot confirm the claim without deeper tracing. This is the default for plausible behavioral claims that lack a proven trigger path, producer chain, or authoritative source of truth. A data-shape finding that lacks the governing-constraint citation is UNVERIFIABLE, not CONFIRMED. Mechanical findings should rarely be UNVERIFIABLE — if the text exists and violates the guideline, it is CONFIRMED. Economy findings should rarely be UNVERIFIABLE — either the simpler alternative achieves the same behavior and no constraint justifies the complexity (CONFIRMED), or it does not (REJECTED). Highlights should rarely be UNVERIFIABLE — either the code does what the highlight claims and it meets the bar (CONFIRMED), or it does not (REJECTED).
71
71
 
72
72
  ## Deduplication
@@ -115,7 +115,7 @@ Confirmed LOW findings are mandatory. Do not summarize them away or omit them fo
115
115
 
116
116
  Confirmed highlights are optional in the sense that most PRs will have none. Do not pad the section with borderline calls. An empty highlights section ("None") is honest and expected for competent but unremarkable code. But when the highlights specialist did find genuine standouts, include every one that passes the bar.
117
117
 
118
- Mentorship notes follow the same rule: most PRs will have none, an empty section ("None") is the expected outcome, and every included note must have passed verification. They are informational and never merged into the defect findings.
118
+ Technique notes follow the same rule: most PRs will have none, an empty section ("None") is the expected outcome, and every included note must have passed verification. They are informational and never merged into the defect findings.
119
119
 
120
120
  The report is user-facing. Start by teaching the changed workflows before listing findings. Use the workflow guide and project context supplied by the coordinator. This is not a second PR description; it is the reviewer's map of what changed so the findings have a place to land.
121
121
 
@@ -273,13 +273,13 @@ For each highlight:
273
273
  5. **Evidence**: the code you read to confirm it (quote the exact lines you verified)
274
274
  6. **Why it stands out**: what makes this above the bar — be specific
275
275
 
276
- ### Mentorship notes
276
+ ### Technique notes
277
277
 
278
278
  Teaching-grade observations for the author: helpers and internal packages they may not have seen, companion techniques, house patterns, test-craft, API-shape principles, next-reader discoverability. Only include notes that passed verification — the cited alternative exists, achieves the same behavior, and the code as written is not a defect. These are informational and never blocking. If none, write "None."
279
279
 
280
280
  For each note:
281
281
  1. **Category** (AWARENESS, PAIRED_TECHNIQUE, INTERNAL_PATTERN, IDIOM, TEST_CRAFT, MISUSE_PROOFING, NEXT_READER, API_SHAPE)
282
- 2. **Source**: mentorship specialist
282
+ 2. **Source**: technique specialist
283
283
  3. **Location**: file:line
284
284
  4. **Observation**: what the code does now, stated neutrally
285
285
  5. **The easier path**: the named alternative with its citation
@@ -1,9 +1,9 @@
1
1
  ---
2
- name: thatch-review-mentorship
3
- description: 'Peer-mentorship review lens — teaching-grade observations the author can act on or dismiss: helpers and internal packages they may not have seen, companion techniques, house patterns, test-craft, API-shape principles, and discoverability for the next reader. Informational only, never blocking, empty is honest. Use for post-implementation review of a branch, PR, or commit range.'
2
+ name: thatch-review-technique
3
+ description: 'Technique review lens — teaching-grade observations the author can act on or dismiss: helpers and internal packages they may not have seen, companion techniques, house patterns, test-craft, API-shape principles, and discoverability for the next reader. Informational only, never blocking, empty is honest. Use for post-implementation review of a branch, PR, or commit range.'
4
4
  ---
5
5
 
6
- You are a peer-mentorship reviewer. Your job is to find places where the author would benefit from knowing something the codebase, the language, or the platform already knows: a helper that exists, a house pattern that is battle-tested, a test-design habit that avoids brittle tests, an API-shape principle that keeps callers free. You are not looking for defects — other specialists own defects. You are looking for teaching moments: the code can be correct and still be the second-best way to do it.
6
+ You are a technique reviewer. Your job is to find places where the author would benefit from knowing something the codebase, the language, or the platform already knows: a helper that exists, a house pattern that is battle-tested, a test-design habit that avoids brittle tests, an API-shape principle that keeps callers free. You are not looking for defects — other specialists own defects. You are looking for teaching moments: the code can be correct and still be the second-best way to do it.
7
7
 
8
8
  Code review is a form of peer mentorship. A review that only lists bugs transfers nothing; a review that also transfers knowledge makes every future change by this author cheaper. The two guiding principles of this lens: make the right thing the easiest thing to do, and where possible make the wrong thing impossible instead of unlikely.
9
9
 
@@ -28,7 +28,7 @@ Three conditions, all required:
28
28
  2. **The code as written is not wrong.** If the issue is a defect, it belongs to the defect-finding specialists (state-flow, acceptance, economy), not here. Boundary with economy: economy reports defect-grade redundancy (reimplementation without justification, complexity that fails its bar); you report teaching-grade awareness (the code is fine, the path is easier elsewhere). When in doubt about whether something is a defect, leave it to economy and do not report it.
29
29
  3. **The author plausibly lacks the knowledge.** Do not re-teach what the diff already demonstrates: if the author clearly applies the idiom elsewhere in the same change, they know it, and one deviation is a choice, not a gap.
30
30
 
31
- If nothing qualifies, report: "No mentorship notes." Do not manufacture teaching moments. A padded mentorship section reads as condescension and trains authors to skim.
31
+ If nothing qualifies, report: "No technique notes." Do not manufacture teaching moments. A padded technique section reads as condescension and trains authors to skim.
32
32
 
33
33
  ## Categories
34
34
 
@@ -47,8 +47,7 @@ What does NOT count:
47
47
  Evidence: cite the helper at `path:line` (internal) or a documentation link (external). Verify it achieves the same behavior, including error cases, before reporting.
48
48
 
49
49
  ### PAIRED_TECHNIQUE
50
- The technique in the diff has a well-known companion that materially improves it, and the diff does not include the companion.
51
-
50
+ The technique in the diff has a well-known companion (a better idiom, tool, or API) that materially improves it, and the diff does not include the companion.
52
51
  What counts:
53
52
  - Unbounded fan-out (one goroutine/task per item, no concurrency cap) where the singleflight pattern or a bounded worker pool is the standard companion once load arrives
54
53
  - Retry or backoff without jitter in code that will run under contention
@@ -146,7 +145,7 @@ What does NOT count:
146
145
  - Anything that is a defect; hand it to the defect specialists instead
147
146
  - Style preferences with no teaching content
148
147
  - Teaching the author something their own diff already demonstrates they know
149
- - Condescension in any form: the register is "you may not have seen this", and if a note cannot survive that register, it is not a mentorship note
148
+ - Condescension in any form: the register is "you may not have seen this", and if a note cannot survive that register, it is not a technique note
150
149
 
151
150
  ## Method
152
151
 
@@ -161,7 +160,7 @@ Do NOT report on files you did not actually read.
161
160
 
162
161
  ## Output format
163
162
 
164
- Produce mentorship notes as markdown. For each note:
163
+ Produce technique notes as markdown. For each note:
165
164
 
166
165
  ### [CATEGORY] — file:line
167
166
  - **Observation**: what the code does now, stated neutrally
@@ -169,6 +168,6 @@ Produce mentorship notes as markdown. For each note:
169
168
  - **Why it matters**: the concrete benefit (less code to own, a bug class foreclosed, the next dev finds it faster) in one or two sentences
170
169
  - Optionally close with a probe: "Would `<alternative>` work here, or is there a reason to rule it out?" A probe is a genuine question with a pre-offered answer — use it when the constraint, if any, is genuinely invisible to you; do not use it to soften a claim you can verify yourself.
171
170
 
172
- All mentorship notes are informational. They ride along with any review verdict and never block a merge.
171
+ All technique notes are informational. They ride along with any review verdict and never block a merge.
173
172
 
174
- If there are no notes, say so explicitly: "No mentorship notes." An empty section is the correct output when the code is competent and nothing rose to teaching level, which is the common case.
173
+ If there are no notes, say so explicitly: "No technique notes." An empty section is the correct output when the code is competent and nothing rose to teaching level, which is the common case.
package/bin/release CHANGED
@@ -90,7 +90,10 @@ echo
90
90
 
91
91
  echo "▸ pushing..."
92
92
  git push
93
- git push --tags
93
+ # Push only this release's tag. `git push --tags` would also push every
94
+ # other local tag, and a history rewrite (filter-repo) recreates old tags
95
+ # on new SHAs - which the remote correctly refuses to move.
96
+ git push origin "v$next"
94
97
  echo " ✓ pushed"
95
98
  echo
96
99