@wipcomputer/wip-ai-devops-toolbox 1.9.29 → 1.9.30

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
@@ -31,6 +31,41 @@
31
31
 
32
32
 
33
33
 
34
+
35
+ ## 1.9.30 (2026-03-15)
36
+
37
+ # Release notes must be a file on disk
38
+
39
+ **Date:** 2026-03-15
40
+
41
+ ## What changed
42
+
43
+ wip-release no longer accepts the `--notes` flag. Release notes MUST come from a file on disk:
44
+
45
+ 1. `RELEASE-NOTES-v{version}.md` in repo root (auto-detected)
46
+ 2. `ai/dev-updates/YYYY-MM-DD--description.md` (auto-detected)
47
+ 3. `--notes-file=path` (explicit file path)
48
+
49
+ If no file exists, the release is blocked. The gate scaffolds a template (`RELEASE-NOTES-v{version}.md`) so the agent has something to fill in.
50
+
51
+ ## Why
52
+
53
+ The `--notes` flag was the root cause of every bad release note. Agents passed one-liners like `--notes="fix bug"` and the gate let them through. Even after we added length checks and changelog detection, agents found ways around it. The flag was an escape hatch that undermined the entire system.
54
+
55
+ The file-on-disk requirement solves three problems:
56
+ 1. **Reviewability.** The file is on the branch. It shows up in the PR diff. Parker can read and approve the release notes before merge.
57
+ 2. **Quality.** Writing a file forces the agent to think about what changed and why. A flag encourages one-liners.
58
+ 3. **History.** The file is committed to git. The release notes are part of the repo history, not a transient CLI argument.
59
+
60
+ ## What agents need to do
61
+
62
+ Before running `wip-release`:
63
+ 1. Write `RELEASE-NOTES-v{version}.md` or `ai/dev-updates/YYYY-MM-DD--description.md`
64
+ 2. Commit it on the branch
65
+ 3. The file shows up in the PR for review
66
+ 4. After merge to main, `wip-release` auto-detects it
67
+
68
+ If the agent forgets, `wip-release` blocks and scaffolds a template.
34
69
 
35
70
  ## 1.9.29 (2026-03-15)
36
71
 
package/SKILL.md CHANGED
@@ -5,7 +5,7 @@ license: MIT
5
5
  interface: [cli, module, mcp, skill, hook, plugin]
6
6
  metadata:
7
7
  display-name: "WIP AI DevOps Toolbox"
8
- version: "1.9.29"
8
+ version: "1.9.30"
9
9
  homepage: "https://github.com/wipcomputer/wip-ai-devops-toolbox"
10
10
  author: "Parker Todd Brooks"
11
11
  category: dev-tools
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wipcomputer/wip-ai-devops-toolbox",
3
- "version": "1.9.29",
3
+ "version": "1.9.30",
4
4
  "type": "module",
5
5
  "description": "The complete AI DevOps toolkit for AI-assisted development teams.",
6
6
  "license": "MIT",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wipcomputer/deploy-public",
3
- "version": "1.9.29",
3
+ "version": "1.9.30",
4
4
  "description": "Private-to-public repo sync. Excludes ai/ folder, creates PR, merges, cleans up branches.",
5
5
  "bin": {
6
6
  "deploy-public": "./deploy-public.sh"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wipcomputer/post-merge-rename",
3
- "version": "1.9.29",
3
+ "version": "1.9.30",
4
4
  "description": "Post-merge branch renaming. Appends --merged-YYYY-MM-DD to preserve history.",
5
5
  "bin": {
6
6
  "post-merge-rename": "./post-merge-rename.sh"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wipcomputer/wip-branch-guard",
3
- "version": "1.9.29",
3
+ "version": "1.9.30",
4
4
  "description": "PreToolUse hook that blocks all writes on main branch. Forces agents to work on branches or worktrees.",
5
5
  "type": "module",
6
6
  "main": "guard.mjs",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wipcomputer/wip-file-guard",
3
- "version": "1.9.29",
3
+ "version": "1.9.30",
4
4
  "type": "module",
5
5
  "description": "Hook that blocks destructive edits to protected identity files. For Claude Code CLI and OpenClaw.",
6
6
  "main": "guard.mjs",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wipcomputer/wip-license-guard",
3
- "version": "1.9.29",
3
+ "version": "1.9.30",
4
4
  "description": "License compliance for your own repos. Ensures correct copyright, dual-license blocks, and LICENSE files.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wipcomputer/wip-license-hook",
3
- "version": "1.9.29",
3
+ "version": "1.9.30",
4
4
  "description": "License rug-pull detection and dependency license compliance for open source projects",
5
5
  "type": "module",
6
6
  "main": "dist/cli/index.js",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wipcomputer/wip-readme-format",
3
- "version": "1.9.29",
3
+ "version": "1.9.30",
4
4
  "description": "Reformat any repo's README to follow the WIP Computer standard. Agent-first, human-readable.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -253,6 +253,12 @@ function checkReleaseNotes(notes, notesSource, level) {
253
253
  issues.push('Notes look like a changelog entry, not a narrative. Explain the impact.');
254
254
  }
255
255
 
256
+ // Release notes should reference at least one issue
257
+ const hasIssueRef = /#\d+/.test(notes);
258
+ if (!hasIssueRef) {
259
+ issues.push('No issue reference found (#XX). Every release should close or reference an issue.');
260
+ }
261
+
256
262
  return { ok: issues.length === 0, issues, block: issues.length > 0 };
257
263
  }
258
264
 
@@ -268,6 +274,19 @@ export function scaffoldReleaseNotes(repoPath, version) {
268
274
  const pkg = JSON.parse(readFileSync(join(repoPath, 'package.json'), 'utf8'));
269
275
  const name = pkg.name?.replace(/^@[^/]+\//, '') || basename(repoPath);
270
276
 
277
+ // Auto-detect issue references from commits since last tag
278
+ let issueRefs = '';
279
+ try {
280
+ const lastTag = execFileSync('git', ['describe', '--tags', '--abbrev=0'],
281
+ { cwd: repoPath, encoding: 'utf8' }).trim();
282
+ const log = execFileSync('git', ['log', `${lastTag}..HEAD`, '--oneline'],
283
+ { cwd: repoPath, encoding: 'utf8' });
284
+ const issues = [...new Set(log.match(/#\d+/g) || [])];
285
+ if (issues.length > 0) {
286
+ issueRefs = issues.map(i => `- ${i}`).join('\n');
287
+ }
288
+ } catch {}
289
+
271
290
  const template = `# Release Notes: ${name} v${version}
272
291
 
273
292
  **One-line summary of what this release does**
@@ -283,6 +302,10 @@ Describe the changes. Not a commit list. Explain:
283
302
 
284
303
  What problem does this solve? What was broken or missing?
285
304
 
305
+ ## Issues closed
306
+
307
+ ${issueRefs || '- #XX (replace with actual issue numbers)'}
308
+
286
309
  ## How to verify
287
310
 
288
311
  \`\`\`bash
@@ -499,6 +522,23 @@ export function createGitHubRelease(repoPath, newVersion, notes, currentVersion)
499
522
  console.warn(` ! GitHub release body is only ${bodyLen} chars. Notes may be truncated.`);
500
523
  }
501
524
  } catch {}
525
+
526
+ // Auto-close referenced issues
527
+ const issueNums = [...new Set((body.match(/#(\d+)/g) || []).map(m => m.slice(1)))];
528
+ for (const num of issueNums) {
529
+ try {
530
+ // Only close if issue exists and is open on the public repo
531
+ const publicSlug = repoSlug.replace(/-private$/, '');
532
+ execFileSync('gh', [
533
+ 'issue', 'close', num,
534
+ '--repo', publicSlug,
535
+ '--comment', `Closed by v${newVersion}. See release notes.`
536
+ ], { cwd: repoPath, stdio: 'pipe' });
537
+ console.log(` ✓ Closed #${num} on ${publicSlug}`);
538
+ } catch {
539
+ // Issue doesn't exist on public repo or already closed. Fine.
540
+ }
541
+ }
502
542
  } finally {
503
543
  try { execFileSync('rm', ['-f', tmpFile]); } catch {}
504
544
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wipcomputer/wip-release",
3
- "version": "1.9.29",
3
+ "version": "1.9.30",
4
4
  "type": "module",
5
5
  "description": "One-command release pipeline. Bumps version, updates changelog + SKILL.md, publishes to npm + GitHub.",
6
6
  "main": "core.mjs",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wipcomputer/wip-repo-init",
3
- "version": "1.9.29",
3
+ "version": "1.9.30",
4
4
  "description": "Scaffold the standard ai/ directory structure in any repo",
5
5
  "type": "module",
6
6
  "bin": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wipcomputer/wip-repo-permissions-hook",
3
- "version": "1.9.29",
3
+ "version": "1.9.30",
4
4
  "type": "module",
5
5
  "description": "Repo visibility guard. Blocks repos from going public without a -private counterpart.",
6
6
  "main": "core.mjs",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wipcomputer/wip-repos",
3
- "version": "1.9.29",
3
+ "version": "1.9.30",
4
4
  "type": "module",
5
5
  "description": "Repo manifest reconciler. Single source of truth for repo organization. Like prettier for folder structure.",
6
6
  "main": "core.mjs",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wipcomputer/universal-installer",
3
- "version": "1.9.29",
3
+ "version": "1.9.30",
4
4
  "type": "module",
5
5
  "description": "The Universal Interface specification for agent-native software. Teaches your AI how to build repos with every interface: CLI, Module, MCP Server, OpenClaw Plugin, Skill, Claude Code Hook.",
6
6
  "main": "detect.mjs",