worclaude 2.4.13 → 2.5.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.
package/CHANGELOG.md CHANGED
@@ -4,6 +4,24 @@ All notable changes to worclaude are documented in this file. Format loosely fol
4
4
 
5
5
  ## [Unreleased]
6
6
 
7
+ ## [2.5.0] — 2026-04-21
8
+
9
+ First release under the new per-PR bump declaration workflow. Shifts release mechanism from "every `/sync` publishes" to "every PR declares a bump, `/sync` aggregates, and only user-visible work ships." PR authors now declare `Version bump: {major|minor|patch|none}` in their PR body; `/sync` picks the highest declared bump since the last tag using precedence `major > minor > patch > none`. All-`none` batches update shared-state files on develop but never cut a release — internal-only work (docs, CI, tests) accumulates without triggering noisy publishes.
10
+
11
+ ### Added
12
+
13
+ - **Per-PR `Version bump:` declaration** (PR #99) — new step 6 in `/commit-push-pr` asks authors to declare `major`/`minor`/`patch`/`none` in the PR body; revert PRs match the bump of the PR being reverted; ambiguous cases ASK the user. The declaration is pasted into both `templates/commands/` (scaffolded into user projects) and `.claude/commands/` (Worclaude's own runtime), kept byte-identical by convention.
14
+ - **`/sync` aggregation rewrite** (PR #99) — replaces the single-step version bump with bootstrap (no-tag → yes/custom/cancel prompt, broadened semver regex accepts pre-release/build metadata, push-failure recovery), aggregation (`gh pr list --limit 500`, `%as` date format to avoid GitHub-search incompatibility with `%ai`, release-PR filter via `headRefName=develop`+`baseRefName=main`, missing-declarations treated as `none`+warning carried through to release PR body and CHANGELOG), ship/wait confirmation (always prompts including for `major`), CHANGELOG append with section defaults mapped from bump type (major/minor → Added, patch → Fixed) and content-driven placement across `### Added`/`### Changed`/`### Fixed`/`### Tests`/`### Docs`.
15
+ - **`tests/templates/version-bump-consistency.test.js`** (PR #99) — new 8-case Vitest asserts `Version bump:` appears literally in all 8 authoritative files (`CLAUDE.md`, both tree copies of `commit-push-pr.md`, `sync.md`, `git-conventions`, and `.github/pull_request_template.md`). Catches rename drift (e.g., `Version bump:` → `Release bump:` in one file without the others). Uses `import.meta.dirname`-derived `REPO_ROOT` matching the `v2-audit` test convention.
16
+ - **`.github/pull_request_template.md`** — required `Version bump:` field with HTML-comment placeholder.
17
+
18
+ ### Changed
19
+
20
+ - **CLAUDE.md Rule #13** reworded: "every merge to `main` gets at least a patch bump" → "every merge to `main` IS a release." Internal-only `none`-only batches now update shared-state files on develop but never reach `main`.
21
+ - **`.claude/skills/git-conventions/SKILL.md`** — fixed two pre-existing statements that contradicted the new policy: line 117 "every merge to main gets at least a patch bump" replaced with release-carries-bump wording; line 124 table row for docs/CI/tests changed from `patch` to `none (no release)`. `templates/skills/universal/git-conventions.md` already said "no bump" so no contradiction-fix was needed there; both files now have the new `### Per-PR bump declarations` + `### Edge cases` subsections appended identically. Unrelated wording divergence between the two trees left alone.
22
+ - **`README.md`** — short "Batched releases" bullet in the "Why Worclaude" section.
23
+ - ⚠ **PR #98 (`fix(upstream): advance state on SKIP_ISSUE`)** — no `Version bump:` declaration (merged 2026-04-21 14:58 UTC, before PR #99 introduced the workflow). Treated as `none` with warning per bootstrap handling. Under-documentation made visible here rather than silently lost. The fix itself advances `.github/upstream-state.json` whenever Claude returns `SKIP_ISSUE` so no-new-item runs don't re-evaluate the same feed indefinitely.
24
+
7
25
  ## [2.4.12] — 2026-04-20
8
26
 
9
27
  Internal fix release — first post-v2.4.11 `upstream-check` run on `main` (workflow run 24693290867) failed with `error_max_turns / num_turns: 16` at the Claude cross-reference step. Not a parser issue: the v2.4.11 format-drift fix still works; Claude simply couldn't fit the workload into 15 turns. The prompt requires ~9 `Read` calls (feed inputs + `.claude/commands/upstream-check.md` + cross-reference against agents/commands/hooks templates, `src/data/agents.js`, `src/data/agent-registry.js`, `docs/spec/BACKLOG-v2.1.md`, `CLAUDE.md`) before the final response — each Read burns a turn, so 15 was tight by luck, not by design.
package/README.md CHANGED
@@ -144,6 +144,7 @@ See the [full command reference](https://sefaertunc.github.io/Worclaude/referenc
144
144
  - **Hook profiles.** Dial strictness up or down via one environment variable. `minimal` for CI, `standard` for daily work, `strict` for type-heavy projects.
145
145
  - **Smart merge.** Detects existing Claude Code setups and merges additively — existing files never overwritten without confirmation. Three-tier strategy: additive for missing content, safe-alongside for conflicts, interactive for CLAUDE.md.
146
146
  - **Self-healing doctor.** Catches drift, stale hashes, deprecated models, broken learnings — before they bite.
147
+ - **Batched releases.** Every PR declares `Version bump: {major|minor|patch|none}` in its body; `/sync` aggregates declarations across merged PRs and only cuts a release when at least one rises above `none`. Internal-only work (docs, CI, tests) accumulates on `develop` without triggering noisy publishes.
147
148
 
148
149
  ---
149
150
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "worclaude",
3
- "version": "2.4.13",
3
+ "version": "2.5.0",
4
4
  "description": "The Workflow Layer for Claude Code — scaffold agents, commands, skills, hooks, and memory into any project",
5
5
  "type": "module",
6
6
  "bin": {
@@ -45,12 +45,35 @@ files (see git-conventions.md for the canonical list).
45
45
  3. Write a clear, conventional commit message
46
46
  4. Push to the current branch
47
47
  5. Create a PR targeting develop: gh pr create --base develop
48
- 6. Include in PR description: title, changes, testing done, reviewer notes
48
+ 6. Determine the version bump level for this PR. Read the Versioning Policy
49
+ in the project's git-conventions document to decide: `major`, `minor`,
50
+ `patch`, or `none`.
51
+ - `major` — breaking change to public API, CLI, or scaffold contract
52
+ - `minor` — new feature, command, agent, or flag
53
+ - `patch` — bug fix or user-visible behavior change with no new surface
54
+ - `none` — docs, CI, tests, internal refactor (nothing consumers notice)
55
+
56
+ For revert PRs: declare the same bump level as the PR being reverted.
57
+
58
+ If the change is ambiguous, ASK THE USER. Do not guess.
59
+
60
+ The PR description MUST include this line on its own, verbatim:
61
+
62
+ ```
63
+ Version bump: {major|minor|patch|none}
64
+ ```
65
+
66
+ `/sync` parses this string exactly — other phrasings will be ignored.
67
+ 7. Include in PR description: title, changes, testing done, reviewer notes
49
68
 
50
69
  ## On develop
51
70
 
52
71
  Only used for release merges after /sync has been run.
53
72
 
73
+ Versioning happens in `/sync`, not here. The release PR body is pre-written
74
+ by `/sync` with the aggregated bump summary and the list of feature PRs
75
+ included in the release.
76
+
54
77
  1. Write a session summary to .claude/sessions/:
55
78
  - Filename: YYYY-MM-DD-HHMM-{short-branch-name}.md
56
79
  - Same format as the feature branch session summary above
@@ -35,23 +35,190 @@ and tell the user to run /conflict-resolver first.
35
35
  docs/spec/SPEC.md to reflect the current state.
36
36
  If nothing changed spec-wise, leave it alone.
37
37
 
38
- ## Version bump
38
+ ## Bootstrap: ensure a version tag exists
39
39
 
40
- 6. Determine version bump using the Versioning Policy in
41
- git-conventions.md. If bump needed: update version in package.json.
40
+ 6. Check for a version tag:
41
+
42
+ ```bash
43
+ LAST_TAG=$(git describe --tags --abbrev=0 2>/dev/null || echo "")
44
+ ```
45
+
46
+ If no tag exists, prompt the user. Do NOT silently auto-tag:
47
+
48
+ ```
49
+ No version tag found. /sync needs a starting tag to compute release scope.
50
+
51
+ Proposed: tag current HEAD as v0.1.0
52
+
53
+ - yes → create v0.1.0 tag at HEAD and continue
54
+ - custom → specify your own starting version (e.g., v1.0.0 if this
55
+ project had releases before adopting this workflow)
56
+ - cancel → stop; tag manually before re-running
57
+
58
+ Choose (yes / custom / cancel):
59
+ ```
60
+
61
+ On "yes": `git tag v0.1.0 && git push origin v0.1.0`, then set
62
+ `LAST_TAG="v0.1.0"`.
63
+
64
+ On "custom": prompt for the version string. Accept any string matching
65
+ `^v\d+\.\d+\.\d+(-[0-9A-Za-z.-]+)?(\+[0-9A-Za-z.-]+)?$` (semver with
66
+ optional pre-release and build metadata, e.g. `v1.0.0-rc.1`, `v2.0.0+build.5`).
67
+ Reject non-matching input with a clear message and re-prompt. Then tag
68
+ and push as above.
69
+
70
+ On "cancel": exit cleanly with "Tag the current state manually before
71
+ re-running /sync."
72
+
73
+ If `git push origin {tag}` fails (fork clone, expired credentials,
74
+ network): the local tag is already created and valid. Report:
75
+ "Local tag created but push failed — retry with `git push origin {tag}`
76
+ manually before opening a release PR." Then exit cleanly.
77
+
78
+ After bootstrap, proceed to step 7. Expect "Nothing publishable since
79
+ {tag}" if no PRs have been merged yet — that is correct behavior for
80
+ a first-release bootstrap, not an error.
81
+
82
+ ## Aggregate version bumps from merged PRs
83
+
84
+ 7. Collect `Version bump:` declarations from all PRs merged into develop
85
+ since the last version tag. Use `%as` for the date format (strict
86
+ YYYY-MM-DD; `%ai` breaks GitHub search due to space separator and
87
+ timezone offset). Pass `--limit 500` to avoid the `gh pr list` default
88
+ cap of 30, which would silently truncate on repos with infrequent
89
+ tagging:
90
+
91
+ ```bash
92
+ SINCE=$(git log -1 --format=%as "$LAST_TAG")
93
+ gh pr list --state merged --base develop \
94
+ --limit 500 \
95
+ --search "merged:>=$SINCE" \
96
+ --json number,title,body,headRefName,baseRefName
97
+ ```
98
+
99
+ Filter out release PRs — any PR with `headRefName: develop` AND
100
+ `baseRefName: main` is a release PR from a prior `/sync` run, not an
101
+ input. Skip those.
102
+
103
+ For each remaining PR, extract the `Version bump:` line from the body.
104
+ Valid values: `major`, `minor`, `patch`, `none`.
105
+
106
+ Missing declarations: treat as `none` and add to a warning list
107
+ (carried through to step 9's summary and step 10's CHANGELOG entry).
108
+ Do NOT guess a higher value. Do NOT stop.
109
+
110
+ 8. Compute the release bump using precedence: `major > minor > patch > none`.
111
+ - If the highest is `none`: update PROGRESS.md and SPEC.md if needed,
112
+ commit those, push, and stop. Do NOT bump the version. Do NOT open
113
+ a PR to main. Report:
114
+
115
+ ```
116
+ Nothing publishable since {last-tag}. Shared state updated.
117
+ ```
118
+
119
+ - If the highest is `patch`, `minor`, or `major`: proceed to step 9.
120
+
121
+ 9. Summarize the release group for the user and ask for confirmation.
122
+ Always prompt, including for `major` — that's exactly when the human
123
+ sanity-check is most valuable.
124
+
125
+ If the warnings list from step 7 is empty, omit the warnings section
126
+ entirely — do NOT render an empty block or a "no warnings" line.
127
+
128
+ Summary format (warnings section included only when warnings exist):
129
+
130
+ ```
131
+ Release group since {last-tag}:
132
+ - #{num} {title} — {bump}
133
+ - #{num} {title} — {bump}
134
+ - ...
135
+
136
+ ⚠ PRs without Version bump: declaration (treated as none):
137
+ - #{num} {title}
138
+ - ...
139
+
140
+ Proposed version: {old} → {new} ({highest-bump})
141
+
142
+ Ship now, or wait for more work to land? (ship/wait)
143
+ ```
144
+
145
+ If the user says "wait", stop without bumping. They will re-run `/sync`
146
+ later when more PRs have merged.
147
+
148
+ 10. On "ship":
149
+
150
+ a. Update the `version` field in `package.json` to the new version.
151
+
152
+ b. Append to `CHANGELOG.md` at the top of the entries list (after the
153
+ `# Changelog` header and the `## [Unreleased]` marker if present).
154
+ If `CHANGELOG.md` does not exist, create it with this header:
155
+
156
+ ```markdown
157
+ # Changelog
158
+
159
+ All notable changes to this project are documented in this file.
160
+ Format loosely follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/);
161
+ versions follow [semver](https://semver.org/).
162
+
163
+ ## [Unreleased]
164
+ ```
165
+
166
+ The new entry format:
167
+
168
+ ```markdown
169
+ ## [{new-version}] — {YYYY-MM-DD}
170
+
171
+ {one-paragraph prose summary of what this release does — synthesize
172
+ from the merged PR titles and bodies; no bullet list in the summary}
173
+
174
+ ### {Section}
175
+
176
+ - {bullet per PR mapped to its section, including PR number}
177
+ ```
178
+
179
+ Section mapping — the declared bump determines the MINIMUM section,
180
+ but each PR's content governs its actual placement. PRs may be filed
181
+ under any of `### Added` / `### Changed` / `### Fixed` / `### Tests` /
182
+ `### Docs` as content warrants. Do not force a mapping that fights
183
+ the content.
184
+
185
+ Defaults when content is ambiguous:
186
+ - `major`, `minor` → default `### Added` (or `### Changed` for
187
+ breaking changes)
188
+ - `patch` → default `### Fixed` (but `### Added` is fine for
189
+ patch-level additive surface like new optional flags)
190
+ - `none` with warning → `### Changed` with ⚠ prefix noting
191
+ "no Version bump declaration — under-documented"
192
+
193
+ If a release mixes levels, each PR goes under its own section.
194
+ Multiple sections per release entry are standard.
195
+
196
+ The warning list from step 9 MUST appear in the CHANGELOG entry as
197
+ ⚠-prefixed bullets under `### Changed` — not just in the transient
198
+ prompt. This is how under-documentation becomes permanent record.
42
199
 
43
200
  ## Verify
44
201
 
45
- 7. Run /verify to confirm tests and lint pass.
46
- If anything fails, fix it before proceeding.
202
+ 11. Run /verify to confirm tests and lint pass.
203
+ If anything fails, fix it before proceeding.
47
204
 
48
205
  ## Commit, push, and PR
49
206
 
50
- 8. git add -A
51
- 9. git commit -m "chore: sync progress, spec, and version to [new version]"
52
- Use exactly this message format — no trailers or Co-Authored-By lines.
53
- 10. git push origin develop
54
- 11. gh pr create --base main with description of what was merged
207
+ 12. git add -A
208
+ 13. git commit -m "chore: sync progress, spec, and version to [new version]"
209
+ Use exactly this message format — no trailers or Co-Authored-By lines.
210
+ 14. git push origin develop
211
+ 15. Create the PR to main. Use the release group summary from step 9 as the
212
+ PR body verbatim (including any warnings block) — that becomes the
213
+ release notes:
214
+
215
+ ```bash
216
+ gh pr create --base main --title "release: v{new-version}" --body "{step-9-summary}"
217
+ ```
218
+
219
+ The maintainer then manually creates a GitHub Release against main
220
+ with tag vX.Y.Z — that triggers the release.yml workflow which
221
+ publishes to npm with provenance. /sync does not publish.
55
222
 
56
223
  ## Trigger Phrases
57
224
  - "sync progress"
@@ -135,6 +135,55 @@ Follow [semver](https://semver.org/) when the project publishes releases:
135
135
 
136
136
  **Rule of thumb:** If the change affects what users see, install, or depend on, it needs a version bump. If it only affects the project's internal development workflow, it does not.
137
137
 
138
+ ### Per-PR bump declarations
139
+
140
+ Every PR targeting `develop` declares its intended version bump in the PR
141
+ description:
142
+
143
+ ```
144
+ Version bump: {major|minor|patch|none}
145
+ ```
146
+
147
+ - `major` — breaking change to public API, CLI, or scaffold contract
148
+ - `minor` — new feature, command, agent, or flag
149
+ - `patch` — bug fix or user-visible behavior change with no new surface
150
+ - `none` — docs, CI, tests, internal refactor (nothing consumers notice)
151
+
152
+ `/sync` aggregates declarations from all PRs merged since the last version
153
+ tag and picks the highest: `major > minor > patch > none`. If all merged
154
+ PRs are `none`, no release is cut — `/sync` updates shared-state files but
155
+ does not bump the version or open a PR to `main`.
156
+
157
+ This is how release batching works: internal-only work accumulates on
158
+ develop without triggering publishes, and multiple user-facing PRs group
159
+ into a single well-documented release.
160
+
161
+ ### Edge cases
162
+
163
+ - **Release PRs (develop → main):** `/sync` excludes these from scanning.
164
+ They ARE the release, not an input to one. Known limitation: any
165
+ develop→main PR is excluded regardless of content. Safe in practice
166
+ because that direction is only used for releases.
167
+ - **Revert PRs:** Declare the same bump level as the PR being reverted.
168
+ Reverting a `patch` is itself a `patch`. A `patch` + matching revert
169
+ in the same release group produces a net-zero user-visible change but
170
+ still bumps the version — something shipped internally and was
171
+ un-shipped, which is part of the release's history. Do not cancel
172
+ them out.
173
+ - **Missing declarations:** Treated as `none` with a warning that
174
+ propagates to the release PR body and CHANGELOG entry. Do not manually
175
+ backfill old PR bodies — let them flow through as `none` so
176
+ under-documentation is visible rather than silent.
177
+ - **No tags yet (first release):** `/sync` prompts to create a starting
178
+ tag (default `v0.1.0`, customizable, cancelable). The tool does NOT
179
+ silently invent a tag.
180
+ - **Hotfix merged directly to main:** Bypasses `/sync` entirely. Requires
181
+ manual version management. Known limitation; out of scope.
182
+
183
+ **Optional:** GitHub labels (`release:major`, `release:minor`, etc.) can
184
+ replace body-text declarations for maintainers who prefer them. Deferred
185
+ to a future phase; not scaffolded by default.
186
+
138
187
  ## Gotchas
139
188
 
140
189
  - Never force-push to main/master. Force-push to feature branches only when you