@wipcomputer/wip-ai-devops-toolbox 1.9.20
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/.license-guard.json +7 -0
- package/.publish-skill.json +4 -0
- package/CHANGELOG.md +1120 -0
- package/CLA.md +19 -0
- package/DEV-GUIDE-GENERAL-PUBLIC.md +882 -0
- package/LICENSE +52 -0
- package/README.md +238 -0
- package/SKILL.md +728 -0
- package/TECHNICAL.md +282 -0
- package/UNIVERSAL-INTERFACE.md +180 -0
- package/_trash/RELEASE-NOTES-v1-8-0.md +29 -0
- package/_trash/RELEASE-NOTES-v1-8-1.md +7 -0
- package/_trash/RELEASE-NOTES-v1-8-2.md +7 -0
- package/_trash/RELEASE-NOTES-v1-9-0.md +37 -0
- package/_trash/RELEASE-NOTES-v1-9-1.md +38 -0
- package/_trash/RELEASE-NOTES-v1-9-10.md +40 -0
- package/_trash/RELEASE-NOTES-v1-9-2.md +40 -0
- package/_trash/RELEASE-NOTES-v1-9-6.md +72 -0
- package/_trash/RELEASE-NOTES-v1-9-7.md +23 -0
- package/_trash/RELEASE-NOTES-v1-9-9.md +75 -0
- package/_trash/guide 2/DEV-GUIDE.md +487 -0
- package/_trash/guide 2/scripts/deploy-public.sh +152 -0
- package/package.json +27 -0
- package/scripts/SKILL-deploy-public.md +61 -0
- package/scripts/SKILL-post-merge-rename.md +47 -0
- package/scripts/deploy-public.sh +264 -0
- package/scripts/post-merge-rename.sh +205 -0
- package/scripts/publish-skill.sh +134 -0
- package/tools/deploy-public/LICENSE +52 -0
- package/tools/deploy-public/README.md +31 -0
- package/tools/deploy-public/SKILL.md +71 -0
- package/tools/deploy-public/deploy-public.sh +264 -0
- package/tools/deploy-public/package.json +9 -0
- package/tools/ldm-jobs/LICENSE +52 -0
- package/tools/ldm-jobs/README.md +46 -0
- package/tools/ldm-jobs/backup.sh +16 -0
- package/tools/ldm-jobs/branch-protect.sh +39 -0
- package/tools/ldm-jobs/crystal-capture.sh +19 -0
- package/tools/ldm-jobs/setup-shell.sh +27 -0
- package/tools/ldm-jobs/visibility-audit.sh +27 -0
- package/tools/post-merge-rename/LICENSE +52 -0
- package/tools/post-merge-rename/README.md +29 -0
- package/tools/post-merge-rename/SKILL.md +57 -0
- package/tools/post-merge-rename/package.json +9 -0
- package/tools/post-merge-rename/post-merge-rename.sh +122 -0
- package/tools/wip-branch-guard/INSTALL.md +41 -0
- package/tools/wip-branch-guard/guard.mjs +259 -0
- package/tools/wip-branch-guard/package.json +11 -0
- package/tools/wip-file-guard/CHANGELOG.md +6 -0
- package/tools/wip-file-guard/LICENSE +52 -0
- package/tools/wip-file-guard/README.md +113 -0
- package/tools/wip-file-guard/REFERENCE.md +86 -0
- package/tools/wip-file-guard/SKILL.md +105 -0
- package/tools/wip-file-guard/guard.mjs +128 -0
- package/tools/wip-file-guard/openclaw.plugin.json +8 -0
- package/tools/wip-file-guard/package.json +27 -0
- package/tools/wip-file-guard/test.sh +119 -0
- package/tools/wip-license-guard/LICENSE +52 -0
- package/tools/wip-license-guard/README.md +32 -0
- package/tools/wip-license-guard/SKILL.md +65 -0
- package/tools/wip-license-guard/cli.mjs +464 -0
- package/tools/wip-license-guard/core.mjs +310 -0
- package/tools/wip-license-guard/hook.mjs +146 -0
- package/tools/wip-license-guard/package.json +15 -0
- package/tools/wip-license-hook/CHANGELOG.md +17 -0
- package/tools/wip-license-hook/LICENSE +52 -0
- package/tools/wip-license-hook/README.md +200 -0
- package/tools/wip-license-hook/SKILL.md +111 -0
- package/tools/wip-license-hook/dist/cli/index.d.ts +15 -0
- package/tools/wip-license-hook/dist/cli/index.js +170 -0
- package/tools/wip-license-hook/dist/cli/index.js.map +1 -0
- package/tools/wip-license-hook/dist/core/detector.d.ts +12 -0
- package/tools/wip-license-hook/dist/core/detector.js +104 -0
- package/tools/wip-license-hook/dist/core/detector.js.map +1 -0
- package/tools/wip-license-hook/dist/core/index.d.ts +4 -0
- package/tools/wip-license-hook/dist/core/index.js +5 -0
- package/tools/wip-license-hook/dist/core/index.js.map +1 -0
- package/tools/wip-license-hook/dist/core/ledger.d.ts +49 -0
- package/tools/wip-license-hook/dist/core/ledger.js +72 -0
- package/tools/wip-license-hook/dist/core/ledger.js.map +1 -0
- package/tools/wip-license-hook/dist/core/reporter.d.ts +14 -0
- package/tools/wip-license-hook/dist/core/reporter.js +227 -0
- package/tools/wip-license-hook/dist/core/reporter.js.map +1 -0
- package/tools/wip-license-hook/dist/core/scanner.d.ts +39 -0
- package/tools/wip-license-hook/dist/core/scanner.js +325 -0
- package/tools/wip-license-hook/dist/core/scanner.js.map +1 -0
- package/tools/wip-license-hook/hooks/pre-pull.sh +55 -0
- package/tools/wip-license-hook/hooks/pre-push.sh +51 -0
- package/tools/wip-license-hook/mcp-server.mjs +119 -0
- package/tools/wip-license-hook/package-lock.json +54 -0
- package/tools/wip-license-hook/package.json +43 -0
- package/tools/wip-license-hook/src/cli/index.ts +189 -0
- package/tools/wip-license-hook/src/core/detector.ts +130 -0
- package/tools/wip-license-hook/src/core/index.ts +4 -0
- package/tools/wip-license-hook/src/core/ledger.ts +116 -0
- package/tools/wip-license-hook/src/core/reporter.ts +255 -0
- package/tools/wip-license-hook/src/core/scanner.ts +367 -0
- package/tools/wip-license-hook/tsconfig.json +16 -0
- package/tools/wip-readme-format/README.md +49 -0
- package/tools/wip-readme-format/SKILL.md +84 -0
- package/tools/wip-readme-format/format.mjs +570 -0
- package/tools/wip-readme-format/package.json +15 -0
- package/tools/wip-release/CHANGELOG.md +42 -0
- package/tools/wip-release/LICENSE +52 -0
- package/tools/wip-release/README.md +45 -0
- package/tools/wip-release/REFERENCE.md +100 -0
- package/tools/wip-release/SKILL.md +139 -0
- package/tools/wip-release/cli.js +161 -0
- package/tools/wip-release/core.mjs +1174 -0
- package/tools/wip-release/mcp-server.mjs +109 -0
- package/tools/wip-release/package.json +36 -0
- package/tools/wip-repo-init/README.md +38 -0
- package/tools/wip-repo-init/SKILL.md +77 -0
- package/tools/wip-repo-init/init.mjs +142 -0
- package/tools/wip-repo-init/package.json +11 -0
- package/tools/wip-repo-permissions-hook/LICENSE +52 -0
- package/tools/wip-repo-permissions-hook/README.md +86 -0
- package/tools/wip-repo-permissions-hook/SKILL.md +73 -0
- package/tools/wip-repo-permissions-hook/cli.js +83 -0
- package/tools/wip-repo-permissions-hook/core.mjs +122 -0
- package/tools/wip-repo-permissions-hook/guard.mjs +64 -0
- package/tools/wip-repo-permissions-hook/mcp-server.mjs +92 -0
- package/tools/wip-repo-permissions-hook/openclaw.plugin.json +8 -0
- package/tools/wip-repo-permissions-hook/package.json +31 -0
- package/tools/wip-repos/LICENSE +52 -0
- package/tools/wip-repos/README.md +77 -0
- package/tools/wip-repos/SKILL.md +80 -0
- package/tools/wip-repos/cli.mjs +176 -0
- package/tools/wip-repos/core.mjs +290 -0
- package/tools/wip-repos/mcp-server.mjs +157 -0
- package/tools/wip-repos/package.json +34 -0
- package/tools/wip-universal-installer/CHANGELOG.md +57 -0
- package/tools/wip-universal-installer/LICENSE +52 -0
- package/tools/wip-universal-installer/README.md +81 -0
- package/tools/wip-universal-installer/REFERENCE.md +122 -0
- package/tools/wip-universal-installer/SKILL.md +87 -0
- package/tools/wip-universal-installer/SPEC.md +180 -0
- package/tools/wip-universal-installer/detect.mjs +130 -0
- package/tools/wip-universal-installer/examples/minimal/README.md +20 -0
- package/tools/wip-universal-installer/examples/minimal/SKILL.md +28 -0
- package/tools/wip-universal-installer/examples/minimal/cli.mjs +4 -0
- package/tools/wip-universal-installer/examples/minimal/core.mjs +8 -0
- package/tools/wip-universal-installer/examples/minimal/mcp-server.mjs +27 -0
- package/tools/wip-universal-installer/examples/minimal/package.json +12 -0
- package/tools/wip-universal-installer/install.js +930 -0
- package/tools/wip-universal-installer/package.json +36 -0
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: wip-file-guard
|
|
3
|
+
description: Hook that blocks destructive edits to protected identity files. For Claude Code CLI and OpenClaw.
|
|
4
|
+
license: MIT
|
|
5
|
+
interface: [cli, module, hook, plugin, skill]
|
|
6
|
+
metadata:
|
|
7
|
+
display-name: "Identity File Protection"
|
|
8
|
+
version: "1.0.1"
|
|
9
|
+
homepage: "https://github.com/wipcomputer/wip-file-guard"
|
|
10
|
+
author: "Parker Todd Brooks"
|
|
11
|
+
category: dev-tools
|
|
12
|
+
capabilities:
|
|
13
|
+
- file-protection
|
|
14
|
+
- edit-blocking
|
|
15
|
+
- identity-guard
|
|
16
|
+
requires:
|
|
17
|
+
bins: [node]
|
|
18
|
+
openclaw:
|
|
19
|
+
requires:
|
|
20
|
+
bins: [node]
|
|
21
|
+
install:
|
|
22
|
+
- id: node
|
|
23
|
+
kind: node
|
|
24
|
+
package: "@wipcomputer/wip-file-guard"
|
|
25
|
+
bins: [wip-file-guard]
|
|
26
|
+
label: "Install via npm"
|
|
27
|
+
emoji: "🛡️"
|
|
28
|
+
compatibility: Requires node. Node.js 18+.
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
# wip-file-guard
|
|
32
|
+
|
|
33
|
+
Hook that blocks destructive edits to protected identity files. For Claude Code CLI and OpenClaw.
|
|
34
|
+
|
|
35
|
+
## When to Use This Skill
|
|
36
|
+
|
|
37
|
+
**Use wip-file-guard for:**
|
|
38
|
+
- Protecting CLAUDE.md, SOUL.md, IDENTITY.md, MEMORY.md, and other identity files from being overwritten
|
|
39
|
+
- Blocking AI agents from replacing file content instead of extending it
|
|
40
|
+
- Surviving context compaction (behavioral rules get erased, but hooks don't)
|
|
41
|
+
|
|
42
|
+
**This is a technical guardrail, not a prompt.** It blocks the operation before it happens.
|
|
43
|
+
|
|
44
|
+
### Do NOT Use For
|
|
45
|
+
|
|
46
|
+
- Protecting binary files or images
|
|
47
|
+
- Blocking all edits (it allows small edits, only blocks destructive ones)
|
|
48
|
+
- Repos without identity files
|
|
49
|
+
|
|
50
|
+
## How It Works
|
|
51
|
+
|
|
52
|
+
Two rules:
|
|
53
|
+
|
|
54
|
+
1. **Write is blocked** on protected files. Always. Use Edit instead.
|
|
55
|
+
2. **Edit is blocked** when it removes more than 2 net lines from a protected file.
|
|
56
|
+
|
|
57
|
+
### Protected Files
|
|
58
|
+
|
|
59
|
+
CLAUDE.md, SHARED-CONTEXT.md, SOUL.md, IDENTITY.md, CONTEXT.md, TOOLS.md, MEMORY.md
|
|
60
|
+
|
|
61
|
+
### Protected Patterns
|
|
62
|
+
|
|
63
|
+
Any file matching: memory, memories, journal, diary, daily log
|
|
64
|
+
|
|
65
|
+
## API Reference
|
|
66
|
+
|
|
67
|
+
### CLI
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
node guard.mjs --list # list protected files
|
|
71
|
+
bash test.sh # run test suite
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
### Claude Code Hook
|
|
75
|
+
|
|
76
|
+
Add to `~/.claude/settings.json`:
|
|
77
|
+
|
|
78
|
+
```json
|
|
79
|
+
{
|
|
80
|
+
"hooks": {
|
|
81
|
+
"PreToolUse": [
|
|
82
|
+
{
|
|
83
|
+
"matcher": "Edit|Write",
|
|
84
|
+
"hooks": [
|
|
85
|
+
{
|
|
86
|
+
"type": "command",
|
|
87
|
+
"command": "node \"/path/to/wip-file-guard/guard.mjs\"",
|
|
88
|
+
"timeout": 5
|
|
89
|
+
}
|
|
90
|
+
]
|
|
91
|
+
}
|
|
92
|
+
]
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
## Troubleshooting
|
|
98
|
+
|
|
99
|
+
### Agent keeps trying to Write
|
|
100
|
+
|
|
101
|
+
The deny message tells the agent to re-read the file and use Edit instead. If the agent ignores it, it's likely post-compaction and has lost context. The hook will keep blocking.
|
|
102
|
+
|
|
103
|
+
### Edit blocked unexpectedly
|
|
104
|
+
|
|
105
|
+
Check the net line removal. Edits that remove more than 2 lines from a protected file are blocked. Small edits (adding or replacing 1-2 lines) are allowed.
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// cc-file-guard/guard.mjs
|
|
3
|
+
// PreToolUse hook for Claude Code.
|
|
4
|
+
// Blocks destructive edits to protected files.
|
|
5
|
+
// - Blocks Write tool on protected files entirely
|
|
6
|
+
// - Blocks Edit when net line removal > 2 lines
|
|
7
|
+
|
|
8
|
+
import { basename } from 'node:path';
|
|
9
|
+
import { existsSync } from 'node:fs';
|
|
10
|
+
|
|
11
|
+
// Exact basename matches
|
|
12
|
+
export const PROTECTED = new Set([
|
|
13
|
+
'CLAUDE.md',
|
|
14
|
+
'SHARED-CONTEXT.md',
|
|
15
|
+
'SOUL.md',
|
|
16
|
+
'IDENTITY.md',
|
|
17
|
+
'CONTEXT.md',
|
|
18
|
+
'TOOLS.md',
|
|
19
|
+
'MEMORY.md',
|
|
20
|
+
]);
|
|
21
|
+
|
|
22
|
+
// Pattern matches (case-insensitive, checked against full path and basename)
|
|
23
|
+
export const PROTECTED_PATTERNS = [
|
|
24
|
+
/memory/i,
|
|
25
|
+
/memories/i,
|
|
26
|
+
/journal/i,
|
|
27
|
+
/diary/i,
|
|
28
|
+
/daily.*log/i,
|
|
29
|
+
];
|
|
30
|
+
|
|
31
|
+
function isProtected(filePath) {
|
|
32
|
+
const name = basename(filePath);
|
|
33
|
+
if (PROTECTED.has(name)) return name;
|
|
34
|
+
for (const pattern of PROTECTED_PATTERNS) {
|
|
35
|
+
if (pattern.test(filePath)) return name + ` (matched pattern: ${pattern})`;
|
|
36
|
+
}
|
|
37
|
+
return null;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function deny(reason) {
|
|
41
|
+
const output = {
|
|
42
|
+
hookSpecificOutput: {
|
|
43
|
+
hookEventName: 'PreToolUse',
|
|
44
|
+
permissionDecision: 'deny',
|
|
45
|
+
permissionDecisionReason: reason,
|
|
46
|
+
},
|
|
47
|
+
};
|
|
48
|
+
process.stdout.write(JSON.stringify(output));
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function countLines(str) {
|
|
52
|
+
if (!str) return 0;
|
|
53
|
+
return str.split('\n').length;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// CLI mode: node guard.mjs --list
|
|
57
|
+
if (process.argv.includes('--list')) {
|
|
58
|
+
console.log('Protected files (exact):');
|
|
59
|
+
for (const f of PROTECTED) console.log(` ${f}`);
|
|
60
|
+
console.log('Protected patterns:');
|
|
61
|
+
for (const p of PROTECTED_PATTERNS) console.log(` ${p}`);
|
|
62
|
+
process.exit(0);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
async function main() {
|
|
66
|
+
let raw = '';
|
|
67
|
+
for await (const chunk of process.stdin) {
|
|
68
|
+
raw += chunk;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
let input;
|
|
72
|
+
try {
|
|
73
|
+
input = JSON.parse(raw);
|
|
74
|
+
} catch {
|
|
75
|
+
// Can't parse input, allow by default
|
|
76
|
+
process.exit(0);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
const toolName = input.tool_name || '';
|
|
80
|
+
const toolInput = input.tool_input || {};
|
|
81
|
+
const filePath = toolInput.file_path || toolInput.filePath || '';
|
|
82
|
+
const fileName = basename(filePath);
|
|
83
|
+
|
|
84
|
+
// Only check protected files
|
|
85
|
+
const match = isProtected(filePath);
|
|
86
|
+
if (!match) {
|
|
87
|
+
process.exit(0);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// Block Write on protected files
|
|
91
|
+
// Exact matches: always block Write (use Edit instead)
|
|
92
|
+
// Pattern matches: only block if file already exists (allow creating new files)
|
|
93
|
+
if (toolName === 'Write') {
|
|
94
|
+
const isExactMatch = PROTECTED.has(fileName);
|
|
95
|
+
if (isExactMatch || existsSync(filePath)) {
|
|
96
|
+
deny(`BLOCKED: Write tool on ${match} is not allowed. Use Edit to make specific changes. Never overwrite protected files.`);
|
|
97
|
+
process.exit(0);
|
|
98
|
+
}
|
|
99
|
+
// Pattern match but file doesn't exist yet — allow creation
|
|
100
|
+
process.exit(0);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// For Edit, check line removal AND large replacements
|
|
104
|
+
if (toolName === 'Edit') {
|
|
105
|
+
const oldString = toolInput.old_string || '';
|
|
106
|
+
const newString = toolInput.new_string || '';
|
|
107
|
+
const oldLines = countLines(oldString);
|
|
108
|
+
const newLines = countLines(newString);
|
|
109
|
+
const removed = oldLines - newLines;
|
|
110
|
+
|
|
111
|
+
// Block net removal of more than 2 lines
|
|
112
|
+
if (removed > 2) {
|
|
113
|
+
deny(`BLOCKED: You are removing ${removed} lines from ${match} (old: ${oldLines} lines, new: ${newLines} lines). Re-read the file and add content instead of replacing it.`);
|
|
114
|
+
process.exit(0);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// Block large replacements (swapping big chunks even if line count is similar)
|
|
118
|
+
if (oldLines > 4 && oldString !== newString) {
|
|
119
|
+
deny(`BLOCKED: You are replacing ${oldLines} lines in ${match}. Edit smaller sections or append new content instead of replacing existing content.`);
|
|
120
|
+
process.exit(0);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// Allow
|
|
125
|
+
process.exit(0);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
main().catch(() => process.exit(0));
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@wipcomputer/wip-file-guard",
|
|
3
|
+
"version": "1.9.20",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"description": "Hook that blocks destructive edits to protected identity files. For Claude Code CLI and OpenClaw.",
|
|
6
|
+
"main": "guard.mjs",
|
|
7
|
+
"bin": {
|
|
8
|
+
"wip-file-guard": "./guard.mjs"
|
|
9
|
+
},
|
|
10
|
+
"scripts": {
|
|
11
|
+
"test": "bash test.sh"
|
|
12
|
+
},
|
|
13
|
+
"keywords": [
|
|
14
|
+
"claude-code",
|
|
15
|
+
"openclaw",
|
|
16
|
+
"hook",
|
|
17
|
+
"file-guard",
|
|
18
|
+
"ai-safety",
|
|
19
|
+
"pretooluse"
|
|
20
|
+
],
|
|
21
|
+
"author": "Parker Todd Brooks",
|
|
22
|
+
"license": "MIT",
|
|
23
|
+
"repository": {
|
|
24
|
+
"type": "git",
|
|
25
|
+
"url": "git+https://github.com/wipcomputer/wip-file-guard.git"
|
|
26
|
+
}
|
|
27
|
+
}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# test.sh - Test wip-file-guard hook
|
|
3
|
+
# Run: bash test.sh
|
|
4
|
+
|
|
5
|
+
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
6
|
+
GUARD="$SCRIPT_DIR/guard.mjs"
|
|
7
|
+
PASS=0
|
|
8
|
+
FAIL=0
|
|
9
|
+
|
|
10
|
+
check() {
|
|
11
|
+
local desc="$1"
|
|
12
|
+
local input="$2"
|
|
13
|
+
local expect="$3" # "block" or "allow"
|
|
14
|
+
|
|
15
|
+
local output
|
|
16
|
+
output=$(echo "$input" | node "$GUARD" 2>/dev/null)
|
|
17
|
+
local code=$?
|
|
18
|
+
|
|
19
|
+
if [ "$expect" = "block" ]; then
|
|
20
|
+
if echo "$output" | grep -q "deny"; then
|
|
21
|
+
echo "PASS: $desc"
|
|
22
|
+
((PASS++))
|
|
23
|
+
else
|
|
24
|
+
echo "FAIL: $desc (expected block, got allow)"
|
|
25
|
+
((FAIL++))
|
|
26
|
+
fi
|
|
27
|
+
else
|
|
28
|
+
if [ -z "$output" ] && [ $code -eq 0 ]; then
|
|
29
|
+
echo "PASS: $desc"
|
|
30
|
+
((PASS++))
|
|
31
|
+
else
|
|
32
|
+
echo "FAIL: $desc (expected allow, got: $output)"
|
|
33
|
+
((FAIL++))
|
|
34
|
+
fi
|
|
35
|
+
fi
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
echo "wip-file-guard tests"
|
|
39
|
+
echo "==================="
|
|
40
|
+
echo ""
|
|
41
|
+
|
|
42
|
+
# Write tests
|
|
43
|
+
check "Block Write to CLAUDE.md" \
|
|
44
|
+
'{"tool_name":"Write","tool_input":{"file_path":"/foo/CLAUDE.md","content":"new"}}' \
|
|
45
|
+
"block"
|
|
46
|
+
|
|
47
|
+
check "Block Write to SHARED-CONTEXT.md" \
|
|
48
|
+
'{"tool_name":"Write","tool_input":{"file_path":"/bar/workspace/SHARED-CONTEXT.md","content":"new"}}' \
|
|
49
|
+
"block"
|
|
50
|
+
|
|
51
|
+
check "Allow Write to random file" \
|
|
52
|
+
'{"tool_name":"Write","tool_input":{"file_path":"/foo/bar.js","content":"new"}}' \
|
|
53
|
+
"allow"
|
|
54
|
+
|
|
55
|
+
# Edit tests - line removal
|
|
56
|
+
check "Block Edit removing 5 lines from CLAUDE.md" \
|
|
57
|
+
'{"tool_name":"Edit","tool_input":{"file_path":"/foo/CLAUDE.md","old_string":"a\nb\nc\nd\ne\nf","new_string":"replaced"}}' \
|
|
58
|
+
"block"
|
|
59
|
+
|
|
60
|
+
check "Allow Edit adding lines to CLAUDE.md" \
|
|
61
|
+
'{"tool_name":"Edit","tool_input":{"file_path":"/foo/CLAUDE.md","old_string":"a","new_string":"a\nb\nc"}}' \
|
|
62
|
+
"allow"
|
|
63
|
+
|
|
64
|
+
check "Allow Edit on non-protected file (even removing lines)" \
|
|
65
|
+
'{"tool_name":"Edit","tool_input":{"file_path":"/foo/bar.js","old_string":"a\nb\nc\nd\ne","new_string":"x"}}' \
|
|
66
|
+
"allow"
|
|
67
|
+
|
|
68
|
+
check "Allow Edit with small removal (2 lines)" \
|
|
69
|
+
'{"tool_name":"Edit","tool_input":{"file_path":"/foo/SOUL.md","old_string":"a\nb\nc","new_string":"x"}}' \
|
|
70
|
+
"allow"
|
|
71
|
+
|
|
72
|
+
check "Block Edit with 4 line removal from SOUL.md" \
|
|
73
|
+
'{"tool_name":"Edit","tool_input":{"file_path":"/foo/SOUL.md","old_string":"a\nb\nc\nd\ne\nf","new_string":"x\ny"}}' \
|
|
74
|
+
"block"
|
|
75
|
+
|
|
76
|
+
# Protected file coverage
|
|
77
|
+
check "Block Write to IDENTITY.md" \
|
|
78
|
+
'{"tool_name":"Write","tool_input":{"file_path":"/any/path/IDENTITY.md","content":"new"}}' \
|
|
79
|
+
"block"
|
|
80
|
+
|
|
81
|
+
check "Block Write to TOOLS.md" \
|
|
82
|
+
'{"tool_name":"Write","tool_input":{"file_path":"/any/path/TOOLS.md","content":"new"}}' \
|
|
83
|
+
"block"
|
|
84
|
+
|
|
85
|
+
# Large replacement (same line count, different content)
|
|
86
|
+
check "Block Edit replacing 8 lines with 8 different lines in SHARED-CONTEXT.md" \
|
|
87
|
+
'{"tool_name":"Edit","tool_input":{"file_path":"/foo/SHARED-CONTEXT.md","old_string":"line1\nline2\nline3\nline4\nline5\nline6\nline7\nline8","new_string":"new1\nnew2\nnew3\nnew4\nnew5\nnew6\nnew7\nnew8"}}' \
|
|
88
|
+
"block"
|
|
89
|
+
|
|
90
|
+
check "Allow Edit replacing 3 lines in CLAUDE.md" \
|
|
91
|
+
'{"tool_name":"Edit","tool_input":{"file_path":"/foo/CLAUDE.md","old_string":"a\nb\nc","new_string":"x\ny\nz"}}' \
|
|
92
|
+
"allow"
|
|
93
|
+
|
|
94
|
+
# Pattern matching - Write
|
|
95
|
+
# Pattern-matched files: allow Write for NEW files, block for existing files
|
|
96
|
+
check "Allow Write to NEW file in memory/ directory (file doesn't exist)" \
|
|
97
|
+
'{"tool_name":"Write","tool_input":{"file_path":"/nonexistent/memory/2099-01-01.md","content":"new"}}' \
|
|
98
|
+
"allow"
|
|
99
|
+
|
|
100
|
+
check "Allow Write to NEW journal file (file doesn't exist)" \
|
|
101
|
+
'{"tool_name":"Write","tool_input":{"file_path":"/nonexistent/journals/new-entry.md","content":"new"}}' \
|
|
102
|
+
"allow"
|
|
103
|
+
|
|
104
|
+
# Pattern matching - Edit (existing files still protected from destructive edits)
|
|
105
|
+
check "Block Edit removing lines from daily log" \
|
|
106
|
+
'{"tool_name":"Edit","tool_input":{"file_path":"/memory/daily/2026-02-19.md","old_string":"a\nb\nc\nd\ne","new_string":"x"}}' \
|
|
107
|
+
"block"
|
|
108
|
+
|
|
109
|
+
# Block Write to pattern-matched file that EXISTS on disk
|
|
110
|
+
check "Block Write to existing test.sh (matched pattern: memory in path)" \
|
|
111
|
+
"{\"tool_name\":\"Write\",\"tool_input\":{\"file_path\":\"$SCRIPT_DIR/test.sh\",\"content\":\"new\"}}" \
|
|
112
|
+
"allow"
|
|
113
|
+
|
|
114
|
+
check "Allow Write to unrelated file with no pattern match" \
|
|
115
|
+
'{"tool_name":"Write","tool_input":{"file_path":"/src/utils/helper.js","content":"new"}}' \
|
|
116
|
+
"allow"
|
|
117
|
+
|
|
118
|
+
echo ""
|
|
119
|
+
echo "Results: $PASS passed, $FAIL failed"
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
Dual License: MIT + AGPLv3
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 WIP Computer, Inc.
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
1. MIT License (local and personal use)
|
|
7
|
+
---------------------------------------
|
|
8
|
+
|
|
9
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
10
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
11
|
+
in the Software without restriction, including without limitation the rights
|
|
12
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
13
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
14
|
+
furnished to do so, subject to the following conditions:
|
|
15
|
+
|
|
16
|
+
The above copyright notice and this permission notice shall be included in all
|
|
17
|
+
copies or substantial portions of the Software.
|
|
18
|
+
|
|
19
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
20
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
21
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
22
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
23
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
24
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
25
|
+
SOFTWARE.
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
2. GNU Affero General Public License v3.0 (commercial and cloud use)
|
|
29
|
+
--------------------------------------------------------------------
|
|
30
|
+
|
|
31
|
+
If you run this software as part of a hosted service, cloud platform,
|
|
32
|
+
marketplace listing, or any network-accessible offering for commercial
|
|
33
|
+
purposes, the AGPLv3 terms apply. You must either:
|
|
34
|
+
|
|
35
|
+
a) Release your complete source code under AGPLv3, or
|
|
36
|
+
b) Obtain a commercial license.
|
|
37
|
+
|
|
38
|
+
This program is free software: you can redistribute it and/or modify
|
|
39
|
+
it under the terms of the GNU Affero General Public License as published
|
|
40
|
+
by the Free Software Foundation, either version 3 of the License, or
|
|
41
|
+
(at your option) any later version.
|
|
42
|
+
|
|
43
|
+
This program is distributed in the hope that it will be useful,
|
|
44
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
45
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
46
|
+
GNU Affero General Public License for more details.
|
|
47
|
+
|
|
48
|
+
You should have received a copy of the GNU Affero General Public License
|
|
49
|
+
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
AGPLv3 for personal use is free. Commercial licenses available.
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
###### WIP Computer
|
|
2
|
+
|
|
3
|
+
# License Guard
|
|
4
|
+
|
|
5
|
+
Enforce licensing on every commit. Copyright, dual-license, CLA. Checked automatically.
|
|
6
|
+
|
|
7
|
+
## What it does
|
|
8
|
+
|
|
9
|
+
- Ensures your own repos have correct copyright, license type, and LICENSE files
|
|
10
|
+
- Interactive first-run setup
|
|
11
|
+
- Toolbox-aware: checks every sub-tool
|
|
12
|
+
- Auto-fix mode repairs issues
|
|
13
|
+
- `readme-license` scans all your repos and applies a standard license block to every README in one command
|
|
14
|
+
- Removes duplicate license sections from sub-tool READMEs
|
|
15
|
+
|
|
16
|
+
## Usage
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
node tools/wip-license-guard/cli.mjs /path/to/repo
|
|
20
|
+
node tools/wip-license-guard/cli.mjs /path/to/repo --fix
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## Requirements
|
|
24
|
+
|
|
25
|
+
- node (18+)
|
|
26
|
+
- git
|
|
27
|
+
|
|
28
|
+
## Interfaces
|
|
29
|
+
|
|
30
|
+
- **CLI**: Command-line tool
|
|
31
|
+
|
|
32
|
+
## Part of [AI DevOps Toolbox](https://github.com/wipcomputer/wip-ai-devops-toolbox)
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: wip-license-guard
|
|
3
|
+
description: License compliance for your own repos. Ensures correct copyright headers, dual-license blocks, and LICENSE files across all source files.
|
|
4
|
+
license: MIT
|
|
5
|
+
interface: [cli, skill]
|
|
6
|
+
metadata:
|
|
7
|
+
display-name: "License Guard"
|
|
8
|
+
version: "1.0.0"
|
|
9
|
+
homepage: "https://github.com/wipcomputer/wip-ai-devops-toolbox"
|
|
10
|
+
author: "Parker Todd Brooks"
|
|
11
|
+
category: dev-tools
|
|
12
|
+
capabilities:
|
|
13
|
+
- copyright-enforcement
|
|
14
|
+
- license-compliance
|
|
15
|
+
- license-file-check
|
|
16
|
+
requires:
|
|
17
|
+
bins: [node, git]
|
|
18
|
+
openclaw:
|
|
19
|
+
requires:
|
|
20
|
+
bins: [node, git]
|
|
21
|
+
install:
|
|
22
|
+
- id: node
|
|
23
|
+
kind: node
|
|
24
|
+
package: "@wipcomputer/wip-license-guard"
|
|
25
|
+
bins: [wip-license-guard]
|
|
26
|
+
label: "Install via npm"
|
|
27
|
+
emoji: "📜"
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
# wip-license-guard
|
|
31
|
+
|
|
32
|
+
License compliance for your own repos. Ensures correct copyright, dual-license blocks, LICENSE files, and README license sections.
|
|
33
|
+
|
|
34
|
+
## When to Use This Skill
|
|
35
|
+
|
|
36
|
+
- Before a release, to verify all files have correct license headers
|
|
37
|
+
- After adding new source files to a repo
|
|
38
|
+
- To enforce the MIT/AGPL dual-license pattern
|
|
39
|
+
- To standardize README license sections across all your repos
|
|
40
|
+
|
|
41
|
+
## CLI
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
wip-license-guard check [path] # audit repo against config
|
|
45
|
+
wip-license-guard check --fix [path] # auto-fix LICENSE, CLA, copyright issues
|
|
46
|
+
wip-license-guard init [path] # interactive setup
|
|
47
|
+
wip-license-guard init --from-standard # apply WIP Computer defaults (no prompts)
|
|
48
|
+
wip-license-guard readme-license [path] # audit README license sections
|
|
49
|
+
wip-license-guard readme-license --dry-run # preview what would change
|
|
50
|
+
wip-license-guard readme-license --fix # apply standard block to all READMEs
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
### readme-license
|
|
54
|
+
|
|
55
|
+
Scans all repos for README license sections. Three modes:
|
|
56
|
+
|
|
57
|
+
- **No flags**: audit only. Reports non-standard, missing, and sub-tool READMEs that shouldn't have license sections.
|
|
58
|
+
- **--dry-run**: preview. Shows what each README has now and what would change. No files touched.
|
|
59
|
+
- **--fix**: apply. Replaces non-standard sections with the standard dual MIT/AGPLv3 block. Removes license sections from sub-tool READMEs.
|
|
60
|
+
|
|
61
|
+
Works on a single repo or a directory of repos:
|
|
62
|
+
```bash
|
|
63
|
+
wip-license-guard readme-license /path/to/one-repo
|
|
64
|
+
wip-license-guard readme-license /path/to/directory-of-repos
|
|
65
|
+
```
|