Skip to content

Commit 9b4516d

Browse files
lapc506claude
andauthored
feat(rules): warn-version-readme-changelog-sync + bump 1.15.0 (defense-in-depth ↔ dojo-os) (#22)
* feat(rules): add warn-version-readme-changelog-sync Tier 2 rule Warns when a version manifest (package.json, plugin.json, marketplace.json, or their .claude-plugin/ namespaced variants) is being bumped without a parallel update to README.md + CHANGELOG.md. This closes the gap PR #21 exposed: the toolkit shipped 1.1.0 -> 1.14.0 with no visible version surface (no README line, no CHANGELOG, no git tags). Without an enforcement rule, the same drift will reappear on the next bump. Pattern (DOJ-4064 three-layer drift thesis, Cure 4 - PreToolUse hooks): - Triggers on Write/Edit/MultiEdit to package.json, plugin.json, marketplace.json, .claude-plugin/plugin.json, .claude-plugin/marketplace.json - Detects new `"version": "X.Y.Z"` field in the written content / new_string - Warns the agent to update README.md "Version:" line + CHANGELOG.md entry in the same change - Tier 2 (warn, non-blocking) - hook cannot see other files in the diff, so it nudges rather than enforces - Bypass marker: version-readme-changelog-sync Sister enforcement (defense-in-depth): the dojo-os repo ships its own PostToolUse hook (.claude/hooks/post-write-version-readme-sync.sh) that catches the same drift locally even when the toolkit isn't installed. 11 new tests, all pass. Total rules: 32 (was 31). Created by Claude Code on behalf of @andres. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * chore: bump to 1.15.0 across manifests + README Coordinated bump across the four version surfaces: - package.json 1.14.0 -> 1.15.0 - .claude-plugin/plugin.json 1.14.0 -> 1.15.0 - .claude-plugin/marketplace.json 1.14.0 -> 1.15.0 (top + nested) - README.md "Version: ..." line 1.14.0 -> 1.15.0 This is the first bump that dogfoods the warn-version-readme-changelog-sync rule shipped in the prior commit on this branch: every manifest write would now warn about the README/CHANGELOG update requirement. README is being updated in this same commit; CHANGELOG entry follows in the next commit. Created by Claude Code on behalf of @andres. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * docs(changelog): add 1.15.0 entry (dogfooding the new rule) Adds the 1.15.0 section to CHANGELOG.md immediately above the existing 1.14.0 entry, documenting: - The new warn-version-readme-changelog-sync Tier 2 rule (32 rules total) - The defense-in-depth pattern (toolkit + dojo-os parallel PRs) - The dogfooding observation: this release ships via the rule it adds This is the third atomic commit of the PR: 1. feat(rules): add the rule (commit 5dd0a67) 2. chore: bump to 1.15.0 across manifests + README (commit c9469f0) 3. docs(changelog): add 1.15.0 entry (this commit) Together they demonstrate the full discipline the rule enforces: manifest + README + CHANGELOG all updated in lockstep within the same PR. Created by Claude Code on behalf of @andres. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
1 parent c094e31 commit 9b4516d

7 files changed

Lines changed: 331 additions & 5 deletions

File tree

.claude-plugin/marketplace.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"$schema": "https://anthropic.com/claude-code/marketplace.schema.json",
33
"name": "make-no-mistakes",
4-
"version": "1.14.0",
4+
"version": "1.15.0",
55
"description": "The disciplined dev lifecycle — implement issues, review PRs, sync releases, test E2E, manage sessions, and stash secrets via OS-native prompts. One plugin to make no mistakes.",
66
"owner": {
77
"name": "Luis Andres Pena Castillo",
@@ -11,7 +11,7 @@
1111
{
1212
"name": "make-no-mistakes",
1313
"description": "Dev lifecycle orchestrator: disciplined Linear issue execution with worktree isolation, PR review with Greptile gating, team release sync, E2E test generation and execution, test suite previewer, security pentesting, MoSCoW + RICE prioritization, cross-platform secret stash via OS-native GUI prompts (zenity / kdialog / osascript / Get-Credential), and session management. 18 commands, 6 auto-activating skills, 2 specialized agents.",
14-
"version": "1.14.0",
14+
"version": "1.15.0",
1515
"author": {
1616
"name": "Luis Andres Pena Castillo",
1717
"email": "lapc506@users.noreply.github.com"

.claude-plugin/plugin.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "make-no-mistakes",
3-
"version": "1.14.0",
3+
"version": "1.15.0",
44
"description": "The disciplined dev lifecycle — implement issues, review PRs, sync releases, test E2E, manage sessions, stash secrets, and enforce manifest-driven tool-call hooks. One plugin to make no mistakes.",
55
"author": {
66
"name": "Luis Andres Pena Castillo",

CHANGELOG.md

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,34 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1818
1919
## [Unreleased]
2020

21+
## [1.15.0] - 2026-05-14
22+
23+
### Added
24+
- New rule: `warn-version-readme-changelog-sync` (Tier 2 — warn). Fires on
25+
`Write` / `Edit` / `MultiEdit` to `package.json`, `plugin.json`,
26+
`marketplace.json`, `.claude-plugin/plugin.json`, or
27+
`.claude-plugin/marketplace.json` when the written content includes a
28+
`"version": "X.Y.Z"` field, and warns the agent to also update `README.md`
29+
(the visible `Version:` line) and `CHANGELOG.md` in the same change. Closes
30+
the gap PR #21 exposed: the toolkit shipped 1.1.0 → 1.14.0 with no visible
31+
version surface (no README line, no CHANGELOG, no git tags); without this
32+
rule the same drift would reappear on every future bump. Bypass marker:
33+
`version-readme-changelog-sync`.
34+
35+
### Notes
36+
- Defense-in-depth (DOJ-4064 three-layer drift thesis, Cure 4):
37+
- **Toolkit level (this PR)** — cross-repo enforcement; any consumer of
38+
the toolkit inherits the rule and gets the warning on every manifest bump.
39+
- **Repo level (parallel `dojo-os` PR)** — local `PostToolUse` hook
40+
`.claude/hooks/post-write-version-readme-sync.sh` enforces the same
41+
invariant in the dojo-os repo even if this toolkit isn't installed.
42+
- Dogfooding: this version itself is being shipped via the rule it adds —
43+
`README.md` "Version" line and `CHANGELOG.md` entry are updated alongside
44+
the manifest bumps in the parent commits. If the rule were not warning,
45+
the 1.15.0 release would already have re-introduced the same drift PR #21
46+
fixed.
47+
- 32 rules total (was 31). 210 / 210 tests pass.
48+
2149
## [1.14.0] - 2026-05-14
2250

2351
### Added

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# make-no-mistakes
22

3-
**Version: 1.14.0** · [CHANGELOG](./CHANGELOG.md) · [Marketplace](https://github.com/DojoCodingLabs/make-no-mistakes-toolkit)
3+
**Version: 1.15.0** · [CHANGELOG](./CHANGELOG.md) · [Marketplace](https://github.com/DojoCodingLabs/make-no-mistakes-toolkit)
44

55
The disciplined dev lifecycle — implement issues, review PRs, sync releases, test E2E, and manage sessions. One plugin to make no mistakes.
66

hooks/rules/rules.json

Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2638,5 +2638,152 @@
26382638
"expected_exit": 0
26392639
}
26402640
]
2641+
},
2642+
{
2643+
"id": "warn-version-readme-changelog-sync",
2644+
"description": "Warn when a version manifest (package.json, plugin.json, marketplace.json) is being bumped without a parallel update to README.md + CHANGELOG.md — the visible-version surface drifts silently otherwise (DOJ-4064 defense-in-depth, sister rule to dojo-os repo-local post-write-version-readme-sync.sh)",
2645+
"applies_to": [
2646+
"Edit",
2647+
"Write",
2648+
"MultiEdit"
2649+
],
2650+
"match": [
2651+
{
2652+
"field": "file_path",
2653+
"pattern": "(^|/)(package\\.json|plugin\\.json|marketplace\\.json|\\.claude-plugin/plugin\\.json|\\.claude-plugin/marketplace\\.json)$"
2654+
},
2655+
{
2656+
"field": "content",
2657+
"pattern": "\"version\"[[:space:]]*:[[:space:]]*\"[0-9]"
2658+
}
2659+
],
2660+
"action": "warn",
2661+
"bypass_marker": "version-readme-changelog-sync",
2662+
"memory_ref": "feedback_version_readme_changelog_sync.md",
2663+
"references": [
2664+
"DOJ-4064 — three-layer drift thesis (Cure 4: PreToolUse/PostToolUse hooks)",
2665+
"Sister hook in dojo-os: .claude/hooks/post-write-version-readme-sync.sh",
2666+
"make-no-mistakes-toolkit PR #21 — visible README version + reconstructed CHANGELOG"
2667+
],
2668+
"message": "WARN: a version manifest (package.json / plugin.json / marketplace.json)\nis being written with a \"version\": \"X.Y.Z\" field, but this hook cannot\nsee whether README.md and CHANGELOG.md were updated in the same change.\n\nWhen you bump the version in any manifest, also update in the same PR:\n 1. README.md — the \"Version: X.Y.Z\" line at the top\n 2. CHANGELOG.md — add a new entry under ## [X.Y.Z] - YYYY-MM-DD\n\nWhy this rule exists (DOJ-4064 three-layer drift thesis):\n- The repo shipped 1.1.0 → 1.14.0 with NO visible version anywhere a\n human would look (README, CHANGELOG, or git tags). PR #21 closed that\n gap by reconstructing the CHANGELOG and adding a header version line.\n- Without this rule, the same drift will reappear on the next bump.\n- Defense-in-depth: the dojo-os repo has a sister PostToolUse hook\n (.claude/hooks/post-write-version-readme-sync.sh) that catches the\n same drift locally even if this toolkit isn't installed.\n\nSuggested workflow:\n bump version in manifest(s) → update README.md \"Version: ...\" line →\n append CHANGELOG.md entry → commit all four files together.\n\nIf you're intentionally splitting the bump from the README/CHANGELOG\nupdate (e.g., bumping a vendored sub-manifest's version that isn't user-\nvisible), add \"# hook-bypass: version-readme-changelog-sync\" inline in\na comment near the version field or pass it on the Write call.\n",
2669+
"tests": [
2670+
{
2671+
"name": "warns-on-package-json-version-bump",
2672+
"input": {
2673+
"tool_input": {
2674+
"file_path": "package.json",
2675+
"content": "{\n \"name\": \"@example/pkg\",\n \"version\": \"1.15.0\"\n}\n"
2676+
}
2677+
},
2678+
"expected_exit": 0,
2679+
"expected_stderr_contains": "warn-version-readme-changelog-sync"
2680+
},
2681+
{
2682+
"name": "warns-on-plugin-json-version-bump",
2683+
"input": {
2684+
"tool_input": {
2685+
"file_path": ".claude-plugin/plugin.json",
2686+
"content": "{\n \"name\": \"make-no-mistakes\",\n \"version\": \"1.15.0\"\n}\n"
2687+
}
2688+
},
2689+
"expected_exit": 0,
2690+
"expected_stderr_contains": "warn-version-readme-changelog-sync"
2691+
},
2692+
{
2693+
"name": "warns-on-marketplace-json-version-bump",
2694+
"input": {
2695+
"tool_input": {
2696+
"file_path": ".claude-plugin/marketplace.json",
2697+
"content": "{\n \"name\": \"marketplace\",\n \"version\": \"1.15.0\",\n \"plugins\": [{\"version\": \"1.15.0\"}]\n}\n"
2698+
}
2699+
},
2700+
"expected_exit": 0,
2701+
"expected_stderr_contains": "warn-version-readme-changelog-sync"
2702+
},
2703+
{
2704+
"name": "warns-on-absolute-path-package-json",
2705+
"input": {
2706+
"tool_input": {
2707+
"file_path": "/home/user/repo/package.json",
2708+
"content": "{\"version\": \"2.0.0\"}"
2709+
}
2710+
},
2711+
"expected_exit": 0,
2712+
"expected_stderr_contains": "warn-version-readme-changelog-sync"
2713+
},
2714+
{
2715+
"name": "warns-on-root-plugin-json",
2716+
"input": {
2717+
"tool_input": {
2718+
"file_path": "plugin.json",
2719+
"content": "{\"version\": \"1.0.1\"}"
2720+
}
2721+
},
2722+
"expected_exit": 0,
2723+
"expected_stderr_contains": "warn-version-readme-changelog-sync"
2724+
},
2725+
{
2726+
"name": "warns-on-edit-of-package-json",
2727+
"input": {
2728+
"tool_input": {
2729+
"file_path": "package.json",
2730+
"old_string": "\"version\": \"1.14.0\"",
2731+
"new_string": "\"version\": \"1.15.0\""
2732+
}
2733+
},
2734+
"expected_exit": 0,
2735+
"expected_stderr_contains": "warn-version-readme-changelog-sync"
2736+
},
2737+
{
2738+
"name": "allows-package-json-write-without-version-field",
2739+
"input": {
2740+
"tool_input": {
2741+
"file_path": "package.json",
2742+
"content": "{\n \"name\": \"@example/pkg\",\n \"description\": \"no version field touched\"\n}\n"
2743+
}
2744+
},
2745+
"expected_exit": 0
2746+
},
2747+
{
2748+
"name": "allows-unrelated-json-file",
2749+
"input": {
2750+
"tool_input": {
2751+
"file_path": "tsconfig.json",
2752+
"content": "{\"version\": \"1.0.0\"}"
2753+
}
2754+
},
2755+
"expected_exit": 0
2756+
},
2757+
{
2758+
"name": "allows-readme-write",
2759+
"input": {
2760+
"tool_input": {
2761+
"file_path": "README.md",
2762+
"content": "**Version: 1.15.0**"
2763+
}
2764+
},
2765+
"expected_exit": 0
2766+
},
2767+
{
2768+
"name": "allows-changelog-write",
2769+
"input": {
2770+
"tool_input": {
2771+
"file_path": "CHANGELOG.md",
2772+
"content": "## [1.15.0] - 2026-05-14"
2773+
}
2774+
},
2775+
"expected_exit": 0
2776+
},
2777+
{
2778+
"name": "allows-bypass-marker",
2779+
"input": {
2780+
"tool_input": {
2781+
"file_path": "package.json",
2782+
"content": "{\n \"version\": \"1.15.0\"\n // hook-bypass: version-readme-changelog-sync\n}\n"
2783+
}
2784+
},
2785+
"expected_exit": 0
2786+
}
2787+
]
26412788
}
26422789
]

hooks/rules/rules.yaml

Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2083,3 +2083,154 @@
20832083
tool_input:
20842084
command: 'git push origin main # hook-bypass: cd-worktree-rule'
20852085
expected_exit: 0
2086+
2087+
- id: warn-version-readme-changelog-sync
2088+
description: Warn when a version manifest (package.json, plugin.json, marketplace.json) is being bumped without a parallel update to README.md + CHANGELOG.md — the visible-version surface drifts silently otherwise (DOJ-4064 defense-in-depth, sister rule to dojo-os repo-local post-write-version-readme-sync.sh)
2089+
applies_to: [Edit, Write, MultiEdit]
2090+
match:
2091+
# Anchor on start-of-string OR a leading "/" so the rule fires for both
2092+
# relative and absolute file paths. Covers the four manifest surfaces
2093+
# that ship a "version" field in this repo and most plugin repos:
2094+
# - package.json (npm manifest)
2095+
# - plugin.json (Claude Code plugin manifest at repo root)
2096+
# - marketplace.json (marketplace manifest at repo root)
2097+
# - .claude-plugin/plugin.json (Claude Code plugin manifest, namespaced)
2098+
# - .claude-plugin/marketplace.json (marketplace manifest, namespaced)
2099+
- field: file_path
2100+
pattern: '(^|/)(package\.json|plugin\.json|marketplace\.json|\.claude-plugin/plugin\.json|\.claude-plugin/marketplace\.json)$'
2101+
# Positive: the new content / new_string includes a "version": "X.Y.Z" line.
2102+
# Quote handling: JSON manifest files always use double quotes, so the
2103+
# pattern only needs to match the canonical `"version": "<digit>...` form.
2104+
# `[0-9]` as the first version character is intentional — we only warn on
2105+
# real semver-shaped bumps, not on edits that happen to remove the version
2106+
# field or add unrelated keys.
2107+
- field: content
2108+
pattern: '"version"[[:space:]]*:[[:space:]]*"[0-9]'
2109+
action: warn
2110+
bypass_marker: version-readme-changelog-sync
2111+
memory_ref: feedback_version_readme_changelog_sync.md
2112+
references:
2113+
- "DOJ-4064 — three-layer drift thesis (Cure 4: PreToolUse/PostToolUse hooks)"
2114+
- "Sister hook in dojo-os: .claude/hooks/post-write-version-readme-sync.sh"
2115+
- "make-no-mistakes-toolkit PR #21 — visible README version + reconstructed CHANGELOG"
2116+
message: |
2117+
WARN: a version manifest (package.json / plugin.json / marketplace.json)
2118+
is being written with a "version": "X.Y.Z" field, but this hook cannot
2119+
see whether README.md and CHANGELOG.md were updated in the same change.
2120+
2121+
When you bump the version in any manifest, also update in the same PR:
2122+
1. README.md — the "Version: X.Y.Z" line at the top
2123+
2. CHANGELOG.md — add a new entry under ## [X.Y.Z] - YYYY-MM-DD
2124+
2125+
Why this rule exists (DOJ-4064 three-layer drift thesis):
2126+
- The repo shipped 1.1.0 → 1.14.0 with NO visible version anywhere a
2127+
human would look (README, CHANGELOG, or git tags). PR #21 closed that
2128+
gap by reconstructing the CHANGELOG and adding a header version line.
2129+
- Without this rule, the same drift will reappear on the next bump.
2130+
- Defense-in-depth: the dojo-os repo has a sister PostToolUse hook
2131+
(.claude/hooks/post-write-version-readme-sync.sh) that catches the
2132+
same drift locally even if this toolkit isn't installed.
2133+
2134+
Suggested workflow:
2135+
bump version in manifest(s) → update README.md "Version: ..." line →
2136+
append CHANGELOG.md entry → commit all four files together.
2137+
2138+
If you're intentionally splitting the bump from the README/CHANGELOG
2139+
update (e.g., bumping a vendored sub-manifest's version that isn't user-
2140+
visible), add "# hook-bypass: version-readme-changelog-sync" inline in
2141+
a comment near the version field or pass it on the Write call.
2142+
tests:
2143+
- name: warns-on-package-json-version-bump
2144+
input:
2145+
tool_input:
2146+
file_path: 'package.json'
2147+
content: |
2148+
{
2149+
"name": "@example/pkg",
2150+
"version": "1.15.0"
2151+
}
2152+
expected_exit: 0
2153+
expected_stderr_contains: 'warn-version-readme-changelog-sync'
2154+
- name: warns-on-plugin-json-version-bump
2155+
input:
2156+
tool_input:
2157+
file_path: '.claude-plugin/plugin.json'
2158+
content: |
2159+
{
2160+
"name": "make-no-mistakes",
2161+
"version": "1.15.0"
2162+
}
2163+
expected_exit: 0
2164+
expected_stderr_contains: 'warn-version-readme-changelog-sync'
2165+
- name: warns-on-marketplace-json-version-bump
2166+
input:
2167+
tool_input:
2168+
file_path: '.claude-plugin/marketplace.json'
2169+
content: |
2170+
{
2171+
"name": "marketplace",
2172+
"version": "1.15.0",
2173+
"plugins": [{"version": "1.15.0"}]
2174+
}
2175+
expected_exit: 0
2176+
expected_stderr_contains: 'warn-version-readme-changelog-sync'
2177+
- name: warns-on-absolute-path-package-json
2178+
input:
2179+
tool_input:
2180+
file_path: '/home/user/repo/package.json'
2181+
content: '{"version": "2.0.0"}'
2182+
expected_exit: 0
2183+
expected_stderr_contains: 'warn-version-readme-changelog-sync'
2184+
- name: warns-on-root-plugin-json
2185+
input:
2186+
tool_input:
2187+
file_path: 'plugin.json'
2188+
content: '{"version": "1.0.1"}'
2189+
expected_exit: 0
2190+
expected_stderr_contains: 'warn-version-readme-changelog-sync'
2191+
- name: warns-on-edit-of-package-json
2192+
input:
2193+
tool_input:
2194+
file_path: 'package.json'
2195+
old_string: '"version": "1.14.0"'
2196+
new_string: '"version": "1.15.0"'
2197+
expected_exit: 0
2198+
expected_stderr_contains: 'warn-version-readme-changelog-sync'
2199+
- name: allows-package-json-write-without-version-field
2200+
input:
2201+
tool_input:
2202+
file_path: 'package.json'
2203+
content: |
2204+
{
2205+
"name": "@example/pkg",
2206+
"description": "no version field touched"
2207+
}
2208+
expected_exit: 0
2209+
- name: allows-unrelated-json-file
2210+
input:
2211+
tool_input:
2212+
file_path: 'tsconfig.json'
2213+
content: '{"version": "1.0.0"}'
2214+
expected_exit: 0
2215+
- name: allows-readme-write
2216+
input:
2217+
tool_input:
2218+
file_path: 'README.md'
2219+
content: '**Version: 1.15.0**'
2220+
expected_exit: 0
2221+
- name: allows-changelog-write
2222+
input:
2223+
tool_input:
2224+
file_path: 'CHANGELOG.md'
2225+
content: '## [1.15.0] - 2026-05-14'
2226+
expected_exit: 0
2227+
- name: allows-bypass-marker
2228+
input:
2229+
tool_input:
2230+
file_path: 'package.json'
2231+
content: |
2232+
{
2233+
"version": "1.15.0"
2234+
// hook-bypass: version-readme-changelog-sync
2235+
}
2236+
expected_exit: 0

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@lapc506/make-no-mistakes",
3-
"version": "1.14.0",
3+
"version": "1.15.0",
44
"description": "The disciplined dev lifecycle — implement issues, review PRs, sync releases, test E2E, manage sessions, stash secrets, and enforce manifest-driven tool-call hooks (no SSH+DB, no manual prod, no minified build, no secret leaks, Slack format). OpenCode + Claude Code plugin.",
55
"type": "module",
66
"main": "./dist/index.js",

0 commit comments

Comments
 (0)