@wipcomputer/wip-ai-devops-toolbox 1.9.30 → 1.9.32
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 +52 -0
- package/SKILL.md +1 -1
- package/_trash/RELEASE-NOTES-v1-9-31.md +26 -0
- package/package.json +1 -1
- package/tools/deploy-public/package.json +1 -1
- package/tools/post-merge-rename/package.json +1 -1
- package/tools/wip-branch-guard/guard.mjs +12 -4
- package/tools/wip-branch-guard/package.json +1 -1
- package/tools/wip-file-guard/guard.mjs +10 -2
- package/tools/wip-file-guard/package.json +1 -1
- package/tools/wip-license-guard/README.md +53 -16
- package/tools/wip-license-guard/cli.mjs +9 -1
- package/tools/wip-license-guard/package.json +1 -1
- package/tools/wip-license-hook/package.json +1 -1
- package/tools/wip-readme-format/format.mjs +7 -0
- package/tools/wip-readme-format/package.json +1 -1
- package/tools/wip-release/cli.js +9 -0
- package/tools/wip-release/package.json +1 -1
- package/tools/wip-repo-init/init.mjs +7 -1
- package/tools/wip-repo-init/package.json +1 -1
- package/tools/wip-repo-permissions-hook/cli.js +10 -0
- package/tools/wip-repo-permissions-hook/package.json +1 -1
- package/tools/wip-repos/cli.mjs +10 -1
- package/tools/wip-repos/package.json +1 -1
- package/tools/wip-universal-installer/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -31,6 +31,58 @@
|
|
|
31
31
|
|
|
32
32
|
|
|
33
33
|
|
|
34
|
+
|
|
35
|
+
## 1.9.32 (2026-03-15)
|
|
36
|
+
|
|
37
|
+
# --version on all CLIs + issue cleanup
|
|
38
|
+
|
|
39
|
+
**Date:** 2026-03-15
|
|
40
|
+
**Closes:** #190, #191, #169, #123, #119
|
|
41
|
+
|
|
42
|
+
## What changed
|
|
43
|
+
|
|
44
|
+
All 7 CLI tools now support `--version` and `-v`. Each reads its own `package.json` and prints the version. Previously, `wip-release --version` printed the help text instead of a version number.
|
|
45
|
+
|
|
46
|
+
Tools updated: wip-release, wip-repos, wip-license-guard, wip-repo-permissions, wip-repo-init, wip-readme-format, wip-file-guard, wip-branch-guard.
|
|
47
|
+
|
|
48
|
+
wip-license-guard also got a proper README (#169) with all commands, config format, and integration docs.
|
|
49
|
+
|
|
50
|
+
## Issues closed
|
|
51
|
+
|
|
52
|
+
- #190: wip-release --version should work
|
|
53
|
+
- #191: enforce --version on all CLI tools
|
|
54
|
+
- #169: wip-license-guard needs its own README
|
|
55
|
+
- #123: Merge/Deploy/Install conflated (enforced across v1.9.25-v1.9.30)
|
|
56
|
+
- #119: All destructive tools must have --dry-run (all confirmed)
|
|
57
|
+
|
|
58
|
+
## 1.9.31 (2026-03-15)
|
|
59
|
+
|
|
60
|
+
# Release Notes: wip-ai-devops-toolbox v1.9.31
|
|
61
|
+
|
|
62
|
+
Branch guard no longer blocks global npm operations on main.
|
|
63
|
+
|
|
64
|
+
## What changed
|
|
65
|
+
|
|
66
|
+
Moved `npm install -g` and `npm link` from BLOCKED_BASH_PATTERNS to ALLOWED_BASH_PATTERNS in `wip-branch-guard/guard.mjs`. Global npm operations modify `/opt/homebrew/`, not the repo. Local `npm install` (no -g flag) remains blocked.
|
|
67
|
+
|
|
68
|
+
## Why
|
|
69
|
+
|
|
70
|
+
During LDM OS v0.4.0 dogfood, a CC session couldn't run `npm install -g @wipcomputer/wip-ldm-os@0.4.0` even after Parker explicitly said "install." The guard was too aggressive. Original intent (issue #137) was to block repo writes on main, not system-level package installs.
|
|
71
|
+
|
|
72
|
+
## Issues closed
|
|
73
|
+
|
|
74
|
+
- Closes #188 (branch guard blocks npm install -g)
|
|
75
|
+
- Cross-ref: wipcomputer/wip-ldm-os#44
|
|
76
|
+
|
|
77
|
+
## How to verify
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
# On main branch, these should now succeed:
|
|
81
|
+
npm install -g @wipcomputer/wip-ldm-os@0.4.0
|
|
82
|
+
npm link
|
|
83
|
+
# This should still be blocked on main:
|
|
84
|
+
npm install
|
|
85
|
+
```
|
|
34
86
|
|
|
35
87
|
## 1.9.30 (2026-03-15)
|
|
36
88
|
|
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.
|
|
8
|
+
version: "1.9.32"
|
|
9
9
|
homepage: "https://github.com/wipcomputer/wip-ai-devops-toolbox"
|
|
10
10
|
author: "Parker Todd Brooks"
|
|
11
11
|
category: dev-tools
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# Release Notes: wip-ai-devops-toolbox v1.9.31
|
|
2
|
+
|
|
3
|
+
Branch guard no longer blocks global npm operations on main.
|
|
4
|
+
|
|
5
|
+
## What changed
|
|
6
|
+
|
|
7
|
+
Moved `npm install -g` and `npm link` from BLOCKED_BASH_PATTERNS to ALLOWED_BASH_PATTERNS in `wip-branch-guard/guard.mjs`. Global npm operations modify `/opt/homebrew/`, not the repo. Local `npm install` (no -g flag) remains blocked.
|
|
8
|
+
|
|
9
|
+
## Why
|
|
10
|
+
|
|
11
|
+
During LDM OS v0.4.0 dogfood, a CC session couldn't run `npm install -g @wipcomputer/wip-ldm-os@0.4.0` even after Parker explicitly said "install." The guard was too aggressive. Original intent (issue #137) was to block repo writes on main, not system-level package installs.
|
|
12
|
+
|
|
13
|
+
## Issues closed
|
|
14
|
+
|
|
15
|
+
- Closes #188 (branch guard blocks npm install -g)
|
|
16
|
+
- Cross-ref: wipcomputer/wip-ldm-os#44
|
|
17
|
+
|
|
18
|
+
## How to verify
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
# On main branch, these should now succeed:
|
|
22
|
+
npm install -g @wipcomputer/wip-ldm-os@0.4.0
|
|
23
|
+
npm link
|
|
24
|
+
# This should still be blocked on main:
|
|
25
|
+
npm install
|
|
26
|
+
```
|
package/package.json
CHANGED
|
@@ -5,8 +5,16 @@
|
|
|
5
5
|
// Agents must work on branches or worktrees. Never on main.
|
|
6
6
|
|
|
7
7
|
import { execSync } from 'node:child_process';
|
|
8
|
-
import { dirname } from 'node:path';
|
|
9
|
-
import { statSync } from 'node:fs';
|
|
8
|
+
import { dirname, join } from 'node:path';
|
|
9
|
+
import { statSync, readFileSync } from 'node:fs';
|
|
10
|
+
import { fileURLToPath } from 'node:url';
|
|
11
|
+
|
|
12
|
+
if (process.argv.includes('--version') || process.argv.includes('-v')) {
|
|
13
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
14
|
+
const pkg = JSON.parse(readFileSync(join(__dirname, 'package.json'), 'utf8'));
|
|
15
|
+
console.log(pkg.version);
|
|
16
|
+
process.exit(0);
|
|
17
|
+
}
|
|
10
18
|
|
|
11
19
|
// Tools that modify files or git state
|
|
12
20
|
const WRITE_TOOLS = new Set(['Write', 'Edit', 'NotebookEdit']);
|
|
@@ -49,8 +57,6 @@ const BLOCKED_BASH_PATTERNS = [
|
|
|
49
57
|
/\brm\s+/,
|
|
50
58
|
/\bmkdir\s+/,
|
|
51
59
|
/\btouch\s+/,
|
|
52
|
-
/\bnpm\s+link\b/,
|
|
53
|
-
/\bnpm\s+install\s+-g\b/,
|
|
54
60
|
/>\s/, // redirects
|
|
55
61
|
/\btee\s+/,
|
|
56
62
|
/\bsed\s+-i/,
|
|
@@ -77,6 +83,8 @@ const ALLOWED_BASH_PATTERNS = [
|
|
|
77
83
|
/--dry-run/,
|
|
78
84
|
/--help/,
|
|
79
85
|
/\bwip-release\b.*--dry-run/,
|
|
86
|
+
/\bnpm\s+install\s+-g\b/, // global installs modify /opt/homebrew/, not the repo
|
|
87
|
+
/\bnpm\s+link\b/, // global operation, not repo-local
|
|
80
88
|
];
|
|
81
89
|
|
|
82
90
|
function deny(reason) {
|
|
@@ -5,8 +5,16 @@
|
|
|
5
5
|
// - Blocks Write tool on protected files entirely
|
|
6
6
|
// - Blocks Edit when net line removal > 2 lines
|
|
7
7
|
|
|
8
|
-
import { basename } from 'node:path';
|
|
9
|
-
import { existsSync } from 'node:fs';
|
|
8
|
+
import { basename, dirname, join } from 'node:path';
|
|
9
|
+
import { existsSync, readFileSync } from 'node:fs';
|
|
10
|
+
import { fileURLToPath } from 'node:url';
|
|
11
|
+
|
|
12
|
+
if (process.argv.includes('--version') || process.argv.includes('-v')) {
|
|
13
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
14
|
+
const pkg = JSON.parse(readFileSync(join(__dirname, 'package.json'), 'utf8'));
|
|
15
|
+
console.log(pkg.version);
|
|
16
|
+
process.exit(0);
|
|
17
|
+
}
|
|
10
18
|
|
|
11
19
|
// Exact basename matches
|
|
12
20
|
export const PROTECTED = new Set([
|
|
@@ -2,31 +2,68 @@
|
|
|
2
2
|
|
|
3
3
|
# License Guard
|
|
4
4
|
|
|
5
|
-
Enforce licensing on every
|
|
5
|
+
Enforce licensing on every repo. Copyright, dual-license, CLA, README license section. Checked automatically on every release.
|
|
6
6
|
|
|
7
|
-
##
|
|
7
|
+
## Commands
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
-
|
|
11
|
-
-
|
|
12
|
-
-
|
|
13
|
-
-
|
|
14
|
-
-
|
|
9
|
+
```bash
|
|
10
|
+
wip-license-guard check # audit current repo
|
|
11
|
+
wip-license-guard check --fix # audit and auto-fix issues
|
|
12
|
+
wip-license-guard init # interactive first-run setup
|
|
13
|
+
wip-license-guard init --from-standard # apply WIP Computer defaults without prompting
|
|
14
|
+
wip-license-guard readme-license # audit license blocks across all repos
|
|
15
|
+
wip-license-guard readme-license --fix # apply standard license block to all READMEs
|
|
16
|
+
wip-license-guard readme-license --dry-run # preview changes without writing
|
|
17
|
+
```
|
|
15
18
|
|
|
16
|
-
##
|
|
19
|
+
## What it checks
|
|
17
20
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
+
- LICENSE file exists and matches configured license type
|
|
22
|
+
- Copyright line is correct and current year
|
|
23
|
+
- CLA.md exists (if configured)
|
|
24
|
+
- README has a `## License` section with the standard block
|
|
25
|
+
- For toolbox repos: checks every sub-tool in `tools/`
|
|
26
|
+
|
|
27
|
+
## Config
|
|
28
|
+
|
|
29
|
+
`.license-guard.json` in repo root. Created by `init`. Contains copyright holder, license type, year, and what to enforce.
|
|
30
|
+
|
|
31
|
+
```json
|
|
32
|
+
{
|
|
33
|
+
"copyright": "WIP Computer, Inc.",
|
|
34
|
+
"license": "MIT+AGPL",
|
|
35
|
+
"year": 2026,
|
|
36
|
+
"enforceCLA": true,
|
|
37
|
+
"enforceReadmeLicense": true
|
|
38
|
+
}
|
|
21
39
|
```
|
|
22
40
|
|
|
23
|
-
##
|
|
41
|
+
## wip-release gate
|
|
42
|
+
|
|
43
|
+
Step 0 of wip-release reads `.license-guard.json` and runs the same checks. If compliance fails, the release is blocked.
|
|
24
44
|
|
|
25
|
-
-
|
|
26
|
-
|
|
45
|
+
## `--from-standard` generates
|
|
46
|
+
|
|
47
|
+
- `.license-guard.json` with WIP Computer defaults
|
|
48
|
+
- `LICENSE` file (dual MIT+AGPL)
|
|
49
|
+
- `CLA.md`
|
|
50
|
+
|
|
51
|
+
## readme-license
|
|
52
|
+
|
|
53
|
+
Scans all repos in a directory and applies a standard license block to every README. Removes duplicate license sections from sub-tool READMEs. Reads templates from `ai/wip-templates/readme/`.
|
|
54
|
+
|
|
55
|
+
## Source
|
|
56
|
+
|
|
57
|
+
Pure JavaScript, no build step. Zero dependencies.
|
|
58
|
+
|
|
59
|
+
- `cli.mjs` ... CLI entry point
|
|
60
|
+
- `core.mjs` ... license checking and generation logic
|
|
61
|
+
- `hook.mjs` ... wip-release gate integration
|
|
27
62
|
|
|
28
63
|
## Interfaces
|
|
29
64
|
|
|
30
|
-
- **CLI**:
|
|
65
|
+
- **CLI**: `wip-license-guard`
|
|
31
66
|
|
|
32
67
|
## Part of [AI DevOps Toolbox](https://github.com/wipcomputer/wip-ai-devops-toolbox)
|
|
68
|
+
|
|
69
|
+
Built by Parker Todd Brooks, Lēsa (OpenClaw, Claude Opus 4.6), Claude Code (Claude Opus 4.6).
|
|
@@ -4,10 +4,18 @@
|
|
|
4
4
|
// Ensures correct copyright, dual-license blocks, and LICENSE files.
|
|
5
5
|
|
|
6
6
|
import { existsSync, readFileSync, writeFileSync, readdirSync } from 'node:fs';
|
|
7
|
-
import { join } from 'node:path';
|
|
7
|
+
import { join, dirname } from 'node:path';
|
|
8
|
+
import { fileURLToPath } from 'node:url';
|
|
8
9
|
import { createInterface } from 'node:readline';
|
|
9
10
|
import { generateLicense, generateCLA, generateReadmeBlock, replaceReadmeLicenseSection, removeReadmeLicenseSection } from './core.mjs';
|
|
10
11
|
|
|
12
|
+
if (process.argv.includes('--version') || process.argv.includes('-v')) {
|
|
13
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
14
|
+
const pkg = JSON.parse(readFileSync(join(__dirname, 'package.json'), 'utf8'));
|
|
15
|
+
console.log(pkg.version);
|
|
16
|
+
process.exit(0);
|
|
17
|
+
}
|
|
18
|
+
|
|
11
19
|
const args = process.argv.slice(2);
|
|
12
20
|
const HELP_FLAGS = ['--help', '-h', 'help'];
|
|
13
21
|
const command = HELP_FLAGS.some(f => args.includes(f)) ? 'help' : (args.find(a => !a.startsWith('--')) || 'check');
|
|
@@ -28,6 +28,13 @@ import { fileURLToPath } from 'node:url';
|
|
|
28
28
|
import { detectInterfaces, detectToolbox } from '../wip-universal-installer/detect.mjs';
|
|
29
29
|
|
|
30
30
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
31
|
+
|
|
32
|
+
if (process.argv.includes('--version') || process.argv.includes('-v')) {
|
|
33
|
+
const pkg = JSON.parse(readFileSync(join(__dirname, 'package.json'), 'utf8'));
|
|
34
|
+
console.log(pkg.version);
|
|
35
|
+
process.exit(0);
|
|
36
|
+
}
|
|
37
|
+
|
|
31
38
|
const args = process.argv.slice(2);
|
|
32
39
|
const DRY_RUN = args.includes('--dry-run');
|
|
33
40
|
const CHECK = args.includes('--check');
|
package/tools/wip-release/cli.js
CHANGED
|
@@ -98,6 +98,15 @@ let notesSource = (notes !== null && notes !== undefined && notes !== '') ? 'fla
|
|
|
98
98
|
}
|
|
99
99
|
}
|
|
100
100
|
|
|
101
|
+
if (args.includes('--version') || args.includes('-v')) {
|
|
102
|
+
const { readFileSync } = await import('node:fs');
|
|
103
|
+
const { join, dirname } = await import('node:path');
|
|
104
|
+
const { fileURLToPath } = await import('node:url');
|
|
105
|
+
const pkg = JSON.parse(readFileSync(join(dirname(fileURLToPath(import.meta.url)), 'package.json'), 'utf8'));
|
|
106
|
+
console.log(pkg.version);
|
|
107
|
+
process.exit(0);
|
|
108
|
+
}
|
|
109
|
+
|
|
101
110
|
if (!level || args.includes('--help') || args.includes('-h')) {
|
|
102
111
|
const cwd = process.cwd();
|
|
103
112
|
let current = '';
|
|
@@ -9,12 +9,18 @@
|
|
|
9
9
|
// 2. Moves old ai/ contents into ai/_sort/ai_old/
|
|
10
10
|
// 3. You sort from there at your own pace.
|
|
11
11
|
|
|
12
|
-
import { existsSync, mkdirSync, cpSync, renameSync, readdirSync, statSync } from 'node:fs';
|
|
12
|
+
import { existsSync, mkdirSync, cpSync, renameSync, readdirSync, statSync, readFileSync } from 'node:fs';
|
|
13
13
|
import { join, resolve, dirname } from 'node:path';
|
|
14
14
|
import { fileURLToPath } from 'node:url';
|
|
15
15
|
import { createInterface } from 'node:readline';
|
|
16
16
|
|
|
17
17
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
18
|
+
|
|
19
|
+
if (process.argv.includes('--version') || process.argv.includes('-v')) {
|
|
20
|
+
const pkg = JSON.parse(readFileSync(join(__dirname, 'package.json'), 'utf8'));
|
|
21
|
+
console.log(pkg.version);
|
|
22
|
+
process.exit(0);
|
|
23
|
+
}
|
|
18
24
|
const TEMPLATE = join(__dirname, 'templates');
|
|
19
25
|
|
|
20
26
|
const targetRepo = resolve(process.argv[2] || process.cwd());
|
|
@@ -9,8 +9,18 @@
|
|
|
9
9
|
* wip-repo-permissions can-publish <org/repo> Alias for check
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
|
+
import { readFileSync } from 'node:fs';
|
|
13
|
+
import { join, dirname } from 'node:path';
|
|
14
|
+
import { fileURLToPath } from 'node:url';
|
|
12
15
|
import { checkPrivateCounterpart, auditOrg } from './core.mjs';
|
|
13
16
|
|
|
17
|
+
if (process.argv.includes('--version') || process.argv.includes('-v')) {
|
|
18
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
19
|
+
const pkg = JSON.parse(readFileSync(join(__dirname, 'package.json'), 'utf8'));
|
|
20
|
+
console.log(pkg.version);
|
|
21
|
+
process.exit(0);
|
|
22
|
+
}
|
|
23
|
+
|
|
14
24
|
const args = process.argv.slice(2);
|
|
15
25
|
const command = args[0];
|
|
16
26
|
const target = args[1];
|
package/tools/wip-repos/cli.mjs
CHANGED
|
@@ -12,7 +12,16 @@
|
|
|
12
12
|
*/
|
|
13
13
|
|
|
14
14
|
import { check, planSync, executeSync, addRepo, moveRepo, generateReadmeTree, loadManifest } from './core.mjs';
|
|
15
|
-
import { resolve, dirname } from 'node:path';
|
|
15
|
+
import { resolve, dirname, join } from 'node:path';
|
|
16
|
+
import { readFileSync } from 'node:fs';
|
|
17
|
+
import { fileURLToPath } from 'node:url';
|
|
18
|
+
|
|
19
|
+
if (process.argv.includes('--version') || process.argv.includes('-v')) {
|
|
20
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
21
|
+
const pkg = JSON.parse(readFileSync(join(__dirname, 'package.json'), 'utf8'));
|
|
22
|
+
console.log(pkg.version);
|
|
23
|
+
process.exit(0);
|
|
24
|
+
}
|
|
16
25
|
|
|
17
26
|
const args = process.argv.slice(2);
|
|
18
27
|
const command = args[0];
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wipcomputer/universal-installer",
|
|
3
|
-
"version": "1.9.
|
|
3
|
+
"version": "1.9.32",
|
|
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",
|