@wipcomputer/wip-ai-devops-toolbox 1.9.50 → 1.9.52
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/.publish-skill.json +1 -1
- package/CHANGELOG.md +42 -0
- package/DEV-GUIDE-GENERAL-PUBLIC.md +42 -1
- package/SKILL.md +1 -1
- package/TECHNICAL.md +8 -8
- package/_trash/RELEASE-NOTES-v1-9-51.md +11 -0
- package/_trash/RELEASE-NOTES-v1-9-52.md +25 -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 +41 -1
- package/tools/wip-branch-guard/package.json +1 -1
- package/tools/wip-file-guard/package.json +1 -1
- package/tools/wip-license-guard/package.json +1 -1
- package/tools/wip-license-hook/package.json +1 -1
- package/tools/wip-readme-format/package.json +1 -1
- package/tools/wip-release/core.mjs +28 -10
- package/tools/wip-release/package.json +1 -1
- package/tools/wip-repo-init/package.json +1 -1
- package/tools/wip-repo-permissions-hook/package.json +1 -1
- package/tools/wip-repos/package.json +1 -1
- package/tools/wip-universal-installer/package.json +1 -1
package/.publish-skill.json
CHANGED
package/CHANGELOG.md
CHANGED
|
@@ -31,6 +31,48 @@
|
|
|
31
31
|
|
|
32
32
|
|
|
33
33
|
|
|
34
|
+
|
|
35
|
+
## 1.9.52 (2026-03-27)
|
|
36
|
+
|
|
37
|
+
# Release Notes: wip-ai-devops-toolbox v1.9.52
|
|
38
|
+
|
|
39
|
+
**Fix branch guard false-blocking bash commands targeting worktree paths**
|
|
40
|
+
|
|
41
|
+
## What changed
|
|
42
|
+
|
|
43
|
+
- Branch guard now extracts absolute paths from any bash command (mkdir, cp, mv, touch, etc.) and resolves the git branch from the target path's repo, not the CWD
|
|
44
|
+
- `findRepoRoot()` improved to walk up to existing directories for paths that don't exist yet (handles mkdir for new directories)
|
|
45
|
+
- Added `.ldm/worktrees` to allowed worktree locations alongside `_worktrees/` and `.claude/worktrees`
|
|
46
|
+
|
|
47
|
+
## Why
|
|
48
|
+
|
|
49
|
+
When Claude Code launches from `~/wipcomputerinc/` (on main) and runs bash commands targeting files inside a worktree (e.g., `mkdir -p /path/to/_worktrees/repo--branch/new-dir/`), the guard only knew how to extract paths from `cd` and `git -C` patterns. Any other command fell back to CWD resolution, saw "main", and blocked incorrectly. This caused minutes of wasted time every session.
|
|
50
|
+
|
|
51
|
+
## Issues closed
|
|
52
|
+
|
|
53
|
+
- wipcomputer/wip-ldm-os#187
|
|
54
|
+
|
|
55
|
+
## How to verify
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
# From CWD on main, this should no longer be blocked:
|
|
59
|
+
# mkdir -p /path/to/_worktrees/repo--branch/new-directory/
|
|
60
|
+
# cp file.txt /path/to/_worktrees/repo--branch/
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## 1.9.51 (2026-03-24)
|
|
64
|
+
|
|
65
|
+
# Release Notes: wip-ai-devops-toolbox v1.9.51
|
|
66
|
+
|
|
67
|
+
## Branch Guard: Workspace Files Allowlist (#185)
|
|
68
|
+
|
|
69
|
+
Added TOOLS.md, MEMORY.md, IDENTITY.md, SOUL.md, WHERE-TO-WRITE.md, HEARTBEAT.md to the shared state allowlist. Both agents can now write to workspace files on main without being blocked.
|
|
70
|
+
|
|
71
|
+
Previously only SHARED-CONTEXT.md was allowed. This broke Lesa's ability to edit her own workspace files during the migration to ~/wipcomputerinc/.
|
|
72
|
+
|
|
73
|
+
## TECHNICAL.md: Backup Documentation
|
|
74
|
+
|
|
75
|
+
Updated LDM Dev Tools.app backup section to reflect the unified backup system. backup.sh now calls `~/.ldm/bin/ldm-backup.sh` (deployed by ldm install from wip-ldm-os-private/scripts/).
|
|
34
76
|
|
|
35
77
|
## 1.9.50 (2026-03-20)
|
|
36
78
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Dev Guide ... Best Practices for AI-Assisted Development
|
|
2
2
|
|
|
3
|
-
**WIP team members: also read
|
|
3
|
+
**WIP team members: also read the private Dev Guide at `~/wipcomputerinc/settings/templates/dev-guide-private.md`.** It covers WIP-specific conventions (branch prefixes, agent IDs, deploy paths, incidents) that supplement everything below. Neither guide is complete without the other.
|
|
4
4
|
|
|
5
5
|
## Repo Structure Convention
|
|
6
6
|
|
|
@@ -648,6 +648,47 @@ Product docs drift fast. If roadmap updates only happen "when someone remembers,
|
|
|
648
648
|
|
|
649
649
|
Release notes are the public face of the project. They must be comprehensive. One-liners like "Release v0.6.0" are unacceptable. Every feature, every change, documented section by section. This applies to both private and public GitHub releases.
|
|
650
650
|
|
|
651
|
+
## Feature Planning: 5 Mandatory Questions
|
|
652
|
+
|
|
653
|
+
Before implementing any feature that changes how the system works (installer, config, deploy, architecture), answer these 5 questions in your plan or PR description. Not optional. Not "consider this." Answer all five or the plan is incomplete.
|
|
654
|
+
|
|
655
|
+
1. **What source files change?** (in the repo)
|
|
656
|
+
2. **What does `ldm install` deploy?** (templates, rules, docs, boot config, CLAUDE.md, skills)
|
|
657
|
+
3. **What needs to update for fresh install vs existing install?**
|
|
658
|
+
4. **What docs need updating?** (repo docs, settings/docs, website)
|
|
659
|
+
5. **What are ALL the files the installer touches on deploy?**
|
|
660
|
+
|
|
661
|
+
If you can't answer #5, you don't understand the change well enough to ship it.
|
|
662
|
+
|
|
663
|
+
## Doc Update Dependencies
|
|
664
|
+
|
|
665
|
+
When you change a file on the left, you MUST also update the files on the right. This is not optional.
|
|
666
|
+
|
|
667
|
+
| If you change | You must also update |
|
|
668
|
+
|--------------|---------------------|
|
|
669
|
+
| `SKILL.md` | `references/`, `settings/docs/how-install-works.md`, wip.computer/install/ (auto via wip-release) |
|
|
670
|
+
| `lib/deploy.mjs` | `settings/docs/how-install-works.md`, `docs/universal-installer/SPEC.md`, `docs/universal-installer/TECHNICAL.md` |
|
|
671
|
+
| `catalog.json` | `settings/docs/what-is-ldm-os.md`, `README.md`, `docs/skills/README.md` |
|
|
672
|
+
| `bin/ldm.js` (init) | `settings/docs/how-install-works.md`, `settings/docs/system-directories.md` |
|
|
673
|
+
| `shared/rules/*` | `settings/docs/how-rules-and-commands-work.md` |
|
|
674
|
+
| `shared/boot/*` | `settings/docs/how-agents-work.md` |
|
|
675
|
+
| `lib/detect.mjs` | `docs/universal-installer/SPEC.md`, `settings/docs/how-install-works.md` |
|
|
676
|
+
| Backup scripts | `settings/docs/how-backup-works.md` |
|
|
677
|
+
| Agent identity files | `settings/docs/how-agents-work.md` |
|
|
678
|
+
| Any repo `README.md` | Public repo README (via deploy-public.sh) |
|
|
679
|
+
|
|
680
|
+
Machine-readable version: `~/wipcomputerinc/settings/docs/change-dependencies.json`
|
|
681
|
+
|
|
682
|
+
### Three doc layers
|
|
683
|
+
|
|
684
|
+
Every change flows through three layers:
|
|
685
|
+
|
|
686
|
+
1. **Repo docs** (generic, source of truth): README.md, TECHNICAL.md, SPEC.md per repo. Written for anyone.
|
|
687
|
+
2. **Settings docs** (personalized, deployed by ldm install): `~/wipcomputerinc/settings/docs/`. Written for YOUR system. Personalized from config.json.
|
|
688
|
+
3. **Website docs** (public): wip.computer. SKILL.md auto-deployed by wip-release. Other docs via Mintlify or deploy script.
|
|
689
|
+
|
|
690
|
+
If repo docs change but settings docs don't update, the user's local docs drift. If settings docs change but the website doesn't, the public docs drift. All three layers must stay in sync.
|
|
691
|
+
|
|
651
692
|
## Repo Directory Structure
|
|
652
693
|
|
|
653
694
|
### The Standard Layout
|
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.52"
|
|
9
9
|
homepage: "https://github.com/wipcomputer/wip-ai-devops-toolbox"
|
|
10
10
|
author: "Parker Todd Brooks"
|
|
11
11
|
category: dev-tools
|
package/TECHNICAL.md
CHANGED
|
@@ -60,19 +60,19 @@ Best practices for AI-assisted development teams. Covers release process, repo s
|
|
|
60
60
|
|
|
61
61
|
macOS automation wrapper. A native `.app` bundle that runs scheduled jobs (backup, branch protection audit, etc.) with Full Disk Access. One app to grant permissions to, one place to add new automation.
|
|
62
62
|
|
|
63
|
-
**Source:** Job scripts are plain shell
|
|
63
|
+
**Source:** Job scripts are plain shell. The app provides a Full Disk Access wrapper.
|
|
64
64
|
|
|
65
|
-
| Script | What it does |
|
|
66
|
-
|
|
67
|
-
|
|
|
68
|
-
| [`branch-protect.sh`](tools/ldm-jobs/branch-protect.sh) | Audit and enforce branch protection across all org repos |
|
|
69
|
-
| [`visibility-audit.sh`](tools/ldm-jobs/visibility-audit.sh) | Audit public repos for missing -private counterparts |
|
|
65
|
+
| Script | What it does | Source |
|
|
66
|
+
|--------|-------------|--------|
|
|
67
|
+
| `backup.sh` | Calls `~/.ldm/bin/ldm-backup.sh` (unified backup) | wip-ldm-os-private/scripts/ |
|
|
68
|
+
| [`branch-protect.sh`](tools/ldm-jobs/branch-protect.sh) | Audit and enforce branch protection across all org repos | tools/ldm-jobs/ |
|
|
69
|
+
| [`visibility-audit.sh`](tools/ldm-jobs/visibility-audit.sh) | Audit public repos for missing -private counterparts | tools/ldm-jobs/ |
|
|
70
70
|
|
|
71
|
-
|
|
71
|
+
The backup script is deployed by `ldm install` to `~/.ldm/bin/`. It backs up ~/.ldm/, ~/.openclaw/, ~/.claude/, and the workspace. See `how-backup-works.md` in the workspace docs.
|
|
72
72
|
|
|
73
73
|
```bash
|
|
74
74
|
# Run standalone
|
|
75
|
-
|
|
75
|
+
~/.ldm/bin/ldm-backup.sh # or --dry-run to preview
|
|
76
76
|
bash tools/ldm-jobs/branch-protect.sh
|
|
77
77
|
bash tools/ldm-jobs/visibility-audit.sh
|
|
78
78
|
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# Release Notes: wip-ai-devops-toolbox v1.9.51
|
|
2
|
+
|
|
3
|
+
## Branch Guard: Workspace Files Allowlist (#185)
|
|
4
|
+
|
|
5
|
+
Added TOOLS.md, MEMORY.md, IDENTITY.md, SOUL.md, WHERE-TO-WRITE.md, HEARTBEAT.md to the shared state allowlist. Both agents can now write to workspace files on main without being blocked.
|
|
6
|
+
|
|
7
|
+
Previously only SHARED-CONTEXT.md was allowed. This broke Lesa's ability to edit her own workspace files during the migration to ~/wipcomputerinc/.
|
|
8
|
+
|
|
9
|
+
## TECHNICAL.md: Backup Documentation
|
|
10
|
+
|
|
11
|
+
Updated LDM Dev Tools.app backup section to reflect the unified backup system. backup.sh now calls `~/.ldm/bin/ldm-backup.sh` (deployed by ldm install from wip-ldm-os-private/scripts/).
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# Release Notes: wip-ai-devops-toolbox v1.9.52
|
|
2
|
+
|
|
3
|
+
**Fix branch guard false-blocking bash commands targeting worktree paths**
|
|
4
|
+
|
|
5
|
+
## What changed
|
|
6
|
+
|
|
7
|
+
- Branch guard now extracts absolute paths from any bash command (mkdir, cp, mv, touch, etc.) and resolves the git branch from the target path's repo, not the CWD
|
|
8
|
+
- `findRepoRoot()` improved to walk up to existing directories for paths that don't exist yet (handles mkdir for new directories)
|
|
9
|
+
- Added `.ldm/worktrees` to allowed worktree locations alongside `_worktrees/` and `.claude/worktrees`
|
|
10
|
+
|
|
11
|
+
## Why
|
|
12
|
+
|
|
13
|
+
When Claude Code launches from `~/wipcomputerinc/` (on main) and runs bash commands targeting files inside a worktree (e.g., `mkdir -p /path/to/_worktrees/repo--branch/new-dir/`), the guard only knew how to extract paths from `cd` and `git -C` patterns. Any other command fell back to CWD resolution, saw "main", and blocked incorrectly. This caused minutes of wasted time every session.
|
|
14
|
+
|
|
15
|
+
## Issues closed
|
|
16
|
+
|
|
17
|
+
- wipcomputer/wip-ldm-os#187
|
|
18
|
+
|
|
19
|
+
## How to verify
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
# From CWD on main, this should no longer be blocked:
|
|
23
|
+
# mkdir -p /path/to/_worktrees/repo--branch/new-directory/
|
|
24
|
+
# cp file.txt /path/to/_worktrees/repo--branch/
|
|
25
|
+
```
|
package/package.json
CHANGED
|
@@ -135,6 +135,17 @@ function findRepoRoot(filePath) {
|
|
|
135
135
|
dir = dirname(dir); // File might not exist yet
|
|
136
136
|
}
|
|
137
137
|
|
|
138
|
+
// Walk up until we find an existing directory (handles mkdir for new paths)
|
|
139
|
+
while (dir && dir !== '/') {
|
|
140
|
+
try {
|
|
141
|
+
const s = statSync(dir);
|
|
142
|
+
if (s.isDirectory()) break;
|
|
143
|
+
dir = dirname(dir);
|
|
144
|
+
} catch {
|
|
145
|
+
dir = dirname(dir);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
138
149
|
// Use git rev-parse from the directory
|
|
139
150
|
const result = execSync('git rev-parse --show-toplevel 2>/dev/null', {
|
|
140
151
|
cwd: dir,
|
|
@@ -146,6 +157,18 @@ function findRepoRoot(filePath) {
|
|
|
146
157
|
return null;
|
|
147
158
|
}
|
|
148
159
|
|
|
160
|
+
function extractPathsFromCommand(command) {
|
|
161
|
+
// Extract absolute paths from a bash command
|
|
162
|
+
// Matches paths like /Users/foo/bar, /tmp/something, etc.
|
|
163
|
+
const paths = [];
|
|
164
|
+
const regex = /(\/(?:Users|home|tmp|var|opt|etc|private)[^\s"'|;&>)]+)/g;
|
|
165
|
+
let match;
|
|
166
|
+
while ((match = regex.exec(command)) !== null) {
|
|
167
|
+
paths.push(match[1]);
|
|
168
|
+
}
|
|
169
|
+
return paths;
|
|
170
|
+
}
|
|
171
|
+
|
|
149
172
|
function getCurrentBranch(cwd) {
|
|
150
173
|
try {
|
|
151
174
|
return execSync('git branch --show-current 2>/dev/null', {
|
|
@@ -230,7 +253,7 @@ async function main() {
|
|
|
230
253
|
const wtMatch = cmd.match(/\bgit\s+worktree\s+add\s+["']?([^\s"']+)/);
|
|
231
254
|
if (wtMatch) {
|
|
232
255
|
const wtPath = wtMatch[1];
|
|
233
|
-
if (!wtPath.includes('_worktrees') && !wtPath.includes('.claude/worktrees')) {
|
|
256
|
+
if (!wtPath.includes('_worktrees') && !wtPath.includes('.claude/worktrees') && !wtPath.includes('.ldm/worktrees')) {
|
|
234
257
|
deny(`WARNING: Creating worktree outside _worktrees/. Use: ldm worktree add <branch>
|
|
235
258
|
|
|
236
259
|
The convention is _worktrees/<repo>--<branch>/ so worktrees don't mix with real repos.
|
|
@@ -274,6 +297,17 @@ This is a warning, not a block. If you need to create it here, retry.`);
|
|
|
274
297
|
if (!repoDir && gitCMatch) {
|
|
275
298
|
repoDir = findRepoRoot(gitCMatch[1].trim());
|
|
276
299
|
}
|
|
300
|
+
// Extract absolute paths from the command itself (handles mkdir, cp, mv, etc.)
|
|
301
|
+
if (!repoDir) {
|
|
302
|
+
const paths = extractPathsFromCommand(command);
|
|
303
|
+
for (const p of paths) {
|
|
304
|
+
const resolved = findRepoRoot(p);
|
|
305
|
+
if (resolved) {
|
|
306
|
+
repoDir = resolved;
|
|
307
|
+
break;
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
}
|
|
277
311
|
}
|
|
278
312
|
|
|
279
313
|
// Fall back to CWD
|
|
@@ -313,6 +347,12 @@ This is a warning, not a block. If you need to create it here, retry.`);
|
|
|
313
347
|
const SHARED_STATE_PATTERNS = [
|
|
314
348
|
/CLAUDE\.md$/,
|
|
315
349
|
/workspace\/SHARED-CONTEXT\.md$/,
|
|
350
|
+
/workspace\/TOOLS\.md$/,
|
|
351
|
+
/workspace\/MEMORY\.md$/,
|
|
352
|
+
/workspace\/IDENTITY\.md$/,
|
|
353
|
+
/workspace\/SOUL\.md$/,
|
|
354
|
+
/workspace\/WHERE-TO-WRITE\.md$/,
|
|
355
|
+
/workspace\/HEARTBEAT\.md$/,
|
|
316
356
|
/workspace\/memory\/.*\.md$/,
|
|
317
357
|
/\.ldm\/agents\/.*\/memory\/daily\/.*\.md$/,
|
|
318
358
|
/\.ldm\/memory\/shared-log\.jsonl$/,
|
|
@@ -155,8 +155,10 @@ function gitCommitAndTag(repoPath, newVersion, notes) {
|
|
|
155
155
|
execFileSync('git', ['add', f], { cwd: repoPath, stdio: 'pipe' });
|
|
156
156
|
}
|
|
157
157
|
}
|
|
158
|
-
// Use execFileSync to avoid shell injection via notes
|
|
159
|
-
|
|
158
|
+
// Use execFileSync to avoid shell injection via notes.
|
|
159
|
+
// --no-verify: wip-release legitimately commits on main (version bump + changelog).
|
|
160
|
+
// The pre-commit hook blocks all commits on main, but wip-release is the one exception.
|
|
161
|
+
execFileSync('git', ['commit', '--no-verify', '-m', msg], { cwd: repoPath, stdio: 'pipe' });
|
|
160
162
|
execFileSync('git', ['tag', `v${newVersion}`], { cwd: repoPath, stdio: 'pipe' });
|
|
161
163
|
}
|
|
162
164
|
|
|
@@ -261,6 +263,24 @@ function checkReleaseNotes(notes, notesSource, level) {
|
|
|
261
263
|
issues.push('Notes look like a changelog entry, not a narrative. Explain the impact.');
|
|
262
264
|
}
|
|
263
265
|
|
|
266
|
+
// Narrative quality: must have at least one paragraph (not just bullets/headers)
|
|
267
|
+
// A paragraph is 2+ consecutive lines of prose (not starting with -, *, #, |, or ```)
|
|
268
|
+
const lines = notes.split('\n').filter(l => l.trim().length > 0);
|
|
269
|
+
const proseLines = lines.filter(l => {
|
|
270
|
+
const t = l.trim();
|
|
271
|
+
return !t.startsWith('#') && !t.startsWith('-') && !t.startsWith('*') &&
|
|
272
|
+
!t.startsWith('|') && !t.startsWith('```') && !t.startsWith('>') &&
|
|
273
|
+
t.length > 30;
|
|
274
|
+
});
|
|
275
|
+
if (proseLines.length < 2) {
|
|
276
|
+
issues.push('Release notes need narrative, not just bullets. Write at least one paragraph explaining what changed and why it matters. Tell the story.');
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
// Must be substantial (not just a header + bullets)
|
|
280
|
+
if (notes.length < 200) {
|
|
281
|
+
issues.push('Release notes are too short (under 200 chars). Every release deserves a story: what was broken or missing, what we built, why the user should care.');
|
|
282
|
+
}
|
|
283
|
+
|
|
264
284
|
// Release notes should reference at least one issue
|
|
265
285
|
const hasIssueRef = /#\d+/.test(notes);
|
|
266
286
|
if (!hasIssueRef) {
|
|
@@ -299,16 +319,14 @@ export function scaffoldReleaseNotes(repoPath, version) {
|
|
|
299
319
|
|
|
300
320
|
**One-line summary of what this release does**
|
|
301
321
|
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
- What was built or fixed
|
|
306
|
-
- Why it matters
|
|
307
|
-
- What the user should know
|
|
322
|
+
Tell the story. What was broken or missing? What did we build? Why does the user care?
|
|
323
|
+
Write at least one real paragraph of prose. Not just bullets. The release notes gate
|
|
324
|
+
will block if there is no narrative. Bullets are fine for details, but the story comes first.
|
|
308
325
|
|
|
309
|
-
##
|
|
326
|
+
## The story
|
|
310
327
|
|
|
311
|
-
What problem does this
|
|
328
|
+
(Write a paragraph here. What was the problem? What does this release fix? Why does it matter?
|
|
329
|
+
This is what users read. Make it worth reading.)
|
|
312
330
|
|
|
313
331
|
## Issues closed
|
|
314
332
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wipcomputer/universal-installer",
|
|
3
|
-
"version": "1.9.
|
|
3
|
+
"version": "1.9.52",
|
|
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",
|