@liangjie559567/ultrapower 5.0.19 → 5.0.21
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/.claude-plugin/plugin.json +1 -1
- package/docs/CLAUDE.md +1 -1
- package/package.json +1 -1
- package/scripts/plugin-setup.mjs +45 -16
- package/skills/omc-doctor/SKILL.md +46 -0
- package/skills/release/SKILL.md +18 -11
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ultrapower",
|
|
3
3
|
"description": "Disciplined multi-agent orchestration: workflow enforcement + parallel execution. Combines superpowers' TDD/debugging discipline with OMC's multi-agent execution capabilities.",
|
|
4
|
-
"version": "5.0.
|
|
4
|
+
"version": "5.0.21",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Jesse Vincent & oh-my-claudecode contributors"
|
|
7
7
|
},
|
package/docs/CLAUDE.md
CHANGED
package/package.json
CHANGED
package/scripts/plugin-setup.mjs
CHANGED
|
@@ -19,9 +19,12 @@ const SETTINGS_FILE = join(CLAUDE_DIR, 'settings.json');
|
|
|
19
19
|
|
|
20
20
|
console.log('[OMC] Running post-install setup...');
|
|
21
21
|
|
|
22
|
-
// Fix: flatten nested cache directories caused by
|
|
23
|
-
//
|
|
24
|
-
//
|
|
22
|
+
// Fix: flatten nested cache directories caused by Claude Code installer bug.
|
|
23
|
+
// Root cause: xF6(src, dest) copies src contents to dest, but dest is a subdirectory of src.
|
|
24
|
+
// After mkdir -p dest, readdir(src) includes the newly created dest subdir, causing recursive copy.
|
|
25
|
+
// Result: cache/.../VERSION/ultrapower/VERSION/ultrapower/VERSION/... infinite nesting.
|
|
26
|
+
// This function detects and fixes arbitrary-depth nesting by finding the real plugin content
|
|
27
|
+
// and moving it up to the version directory, then removing all nested dirs.
|
|
25
28
|
function fixNestedCacheDir() {
|
|
26
29
|
try {
|
|
27
30
|
const pluginCacheBase = join(CLAUDE_DIR, 'plugins/cache/ultrapower/ultrapower');
|
|
@@ -31,25 +34,51 @@ function fixNestedCacheDir() {
|
|
|
31
34
|
const versionDir = join(pluginCacheBase, version);
|
|
32
35
|
const nestedDir = join(versionDir, 'ultrapower');
|
|
33
36
|
if (!existsSync(nestedDir)) continue;
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
//
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
37
|
+
|
|
38
|
+
// Walk down the nesting to find the real plugin content (arbitrary depth)
|
|
39
|
+
// Real content has skills/, dist/, agents/, or hooks/ directly inside
|
|
40
|
+
const PLUGIN_MARKERS = ['skills', 'dist', 'agents', 'hooks'];
|
|
41
|
+
let realContentDir = null;
|
|
42
|
+
let searchDir = nestedDir;
|
|
43
|
+
let depth = 0;
|
|
44
|
+
while (depth < 20) {
|
|
45
|
+
const contents = readdirSync(searchDir);
|
|
46
|
+
if (contents.length === 0) {
|
|
47
|
+
// Empty dir - just remove it
|
|
48
|
+
rmSync(nestedDir, { recursive: true, force: true });
|
|
49
|
+
console.log(`[OMC] Removed empty nested dir for version ${version}`);
|
|
50
|
+
break;
|
|
51
|
+
}
|
|
52
|
+
if (contents.some(f => PLUGIN_MARKERS.includes(f))) {
|
|
53
|
+
realContentDir = searchDir;
|
|
54
|
+
break;
|
|
55
|
+
}
|
|
56
|
+
// Go deeper: look for ultrapower/ or version/ subdir
|
|
57
|
+
const nextDir = join(searchDir, 'ultrapower');
|
|
58
|
+
const nextVerDir = join(searchDir, version);
|
|
59
|
+
if (existsSync(nextDir)) {
|
|
60
|
+
searchDir = nextDir;
|
|
61
|
+
} else if (existsSync(nextVerDir)) {
|
|
62
|
+
searchDir = nextVerDir;
|
|
63
|
+
} else {
|
|
64
|
+
break;
|
|
65
|
+
}
|
|
66
|
+
depth++;
|
|
41
67
|
}
|
|
42
|
-
|
|
43
|
-
if (!
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
68
|
+
|
|
69
|
+
if (!realContentDir) continue;
|
|
70
|
+
|
|
71
|
+
console.log(`[OMC] Fixing nested cache dir for version ${version} (depth ${depth})...`);
|
|
72
|
+
// Move contents of realContentDir up to versionDir
|
|
73
|
+
const realContents = readdirSync(realContentDir);
|
|
74
|
+
for (const item of realContents) {
|
|
75
|
+
const src = join(realContentDir, item);
|
|
48
76
|
const dest = join(versionDir, item);
|
|
49
77
|
if (!existsSync(dest)) {
|
|
50
78
|
renameSync(src, dest);
|
|
51
79
|
}
|
|
52
80
|
}
|
|
81
|
+
// Remove the entire nested ultrapower/ subtree
|
|
53
82
|
rmSync(nestedDir, { recursive: true, force: true });
|
|
54
83
|
console.log(`[OMC] Fixed nested cache dir for version ${version}`);
|
|
55
84
|
}
|
|
@@ -71,6 +71,36 @@ if(f.existsSync(npmCachePkg)){
|
|
|
71
71
|
- `MISMATCH: dir=X pkg.version=Y`:严重错误——npm-cache 复用导致旧内容被安装到新版本目录
|
|
72
72
|
- npm-cache range 显示旧版本范围(如 `^5.0.11`):警告——下次安装仍会复用旧缓存
|
|
73
73
|
|
|
74
|
+
### 第一步 ter:检查无限嵌套缓存目录
|
|
75
|
+
|
|
76
|
+
检查插件缓存目录是否存在无限嵌套(Claude Code 安装器 `xF6` bug 导致):
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
node -e "
|
|
80
|
+
const p=require('path'),f=require('fs'),h=require('os').homedir();
|
|
81
|
+
const d=process.env.CLAUDE_CONFIG_DIR||p.join(h,'.claude');
|
|
82
|
+
const b=p.join(d,'plugins','cache','ultrapower','ultrapower');
|
|
83
|
+
try {
|
|
84
|
+
const vs=f.readdirSync(b).filter(x=>/^\d/.test(x));
|
|
85
|
+
let found=false;
|
|
86
|
+
for(const v of vs){
|
|
87
|
+
const nested=p.join(b,v,'ultrapower');
|
|
88
|
+
if(f.existsSync(nested)){
|
|
89
|
+
console.log('CRITICAL: nested dir found: '+nested);
|
|
90
|
+
found=true;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
if(!found) console.log('OK: no nested ultrapower/ dirs found');
|
|
94
|
+
} catch(e){console.log('Cache not found (normal if not installed)');}
|
|
95
|
+
"
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
**诊断**:
|
|
99
|
+
- `CRITICAL: nested dir found`:严重错误——安装器 `xF6` bug 导致无限嵌套,插件内容可能损坏
|
|
100
|
+
- 根本原因:`xF6(src, dest)` 先 `mkdir -p dest`,再 `readdir(src)`;因 `dest` 是 `src` 子目录,readdir 包含刚创建的子目录,递归复制时把自身复制进去
|
|
101
|
+
- 加剧因素:`PM1()` 检测目标非空则跳过复制,嵌套一旦产生安装器永远不会自动修复
|
|
102
|
+
- 自动修复:5.0.20+ 的 `postinstall` 脚本会自动检测并修复任意深度嵌套
|
|
103
|
+
|
|
74
104
|
### 第二步:检查 settings.json 中的旧版 hook
|
|
75
105
|
|
|
76
106
|
读取 `~/.claude/settings.json`(用户级)和 `./.claude/settings.json`(项目级),检查是否存在包含以下条目的 `"hooks"` 键:
|
|
@@ -157,6 +187,7 @@ ls -la ~/.claude/skills/ 2>/dev/null
|
|
|
157
187
|
|-------|--------|---------|
|
|
158
188
|
| 插件版本 | OK/WARN/CRITICAL | ... |
|
|
159
189
|
| npm-cache 复用 | OK/WARN/CRITICAL | ... |
|
|
190
|
+
| 无限嵌套缓存 | OK/CRITICAL | ... |
|
|
160
191
|
| 旧版 Hook (settings.json) | OK/CRITICAL | ... |
|
|
161
192
|
| 旧版脚本 (~/.claude/hooks/) | OK/WARN | ... |
|
|
162
193
|
| CLAUDE.md | OK/WARN/CRITICAL | ... |
|
|
@@ -198,6 +229,21 @@ rm -f ~/.claude/hooks/stop-continuation.sh
|
|
|
198
229
|
node -e "const p=require('path'),f=require('fs'),d=process.env.CLAUDE_CONFIG_DIR||p.join(require('os').homedir(),'.claude'),b=p.join(d,'plugins','cache','omc','ultrapower');try{f.rmSync(b,{recursive:true,force:true});console.log('Plugin cache cleared. Restart Claude Code to fetch latest version.')}catch{console.log('No plugin cache found')}"
|
|
199
230
|
```
|
|
200
231
|
|
|
232
|
+
### 修复:无限嵌套缓存目录
|
|
233
|
+
|
|
234
|
+
症状:`versionDir/ultrapower/` 子目录存在,插件内容可能损坏。
|
|
235
|
+
|
|
236
|
+
```bash
|
|
237
|
+
# 完整清洁重装(5.0.20+ postinstall 会自动修复残留嵌套)
|
|
238
|
+
claude plugin uninstall ultrapower
|
|
239
|
+
rm -rf ~/.claude/plugins/npm-cache
|
|
240
|
+
rm -rf ~/.claude/plugins/cache/ultrapower
|
|
241
|
+
claude plugin marketplace update ultrapower
|
|
242
|
+
claude plugin install ultrapower
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
> ✅ 安装 5.0.20+ 后,`postinstall` 脚本会自动检测并修复任意深度嵌套,无需手动干预。
|
|
246
|
+
|
|
201
247
|
### 修复:npm-cache 复用(插件内容是旧版本)
|
|
202
248
|
|
|
203
249
|
症状:插件缓存目录版本号与 `package.json` 内 `version` 字段不一致。
|
package/skills/release/SKILL.md
CHANGED
|
@@ -128,26 +128,33 @@ ls ~/.claude/plugins/cache/ultrapower/ultrapower/<version>/skills/
|
|
|
128
128
|
|
|
129
129
|
症状:`cache/ultrapower/ultrapower/5.x.x/ultrapower/5.x.x/ultrapower/...`
|
|
130
130
|
|
|
131
|
-
|
|
131
|
+
**根本原因(已确认)**:Claude Code 安装器的 `xF6(src, dest)` 函数存在 bug:
|
|
132
|
+
1. 先执行 `mkdir -p dest`(`dest = cache/ultrapower/ultrapower/5.x.x`)
|
|
133
|
+
2. 再执行 `readdir(src)`(`src = cache/ultrapower`)
|
|
134
|
+
3. 由于 `dest` 是 `src` 的子目录,`readdir` 结果包含刚创建的 `ultrapower/` 子目录
|
|
135
|
+
4. 递归复制时把自身也复制进去,产生无限嵌套
|
|
132
136
|
|
|
133
|
-
|
|
134
|
-
```bash
|
|
135
|
-
# 1. 卸载插件
|
|
136
|
-
claude plugin uninstall ultrapower
|
|
137
|
+
**加剧因素**:`PM1()` 检查目标目录是否非空,非空则跳过复制(认为已缓存)。一旦嵌套产生,安装器永远不会自动修复。
|
|
137
138
|
|
|
138
|
-
|
|
139
|
+
**自动修复**:5.0.20+ 的 `postinstall` 脚本(`fixNestedCacheDir()`)会自动检测并修复任意深度嵌套。
|
|
140
|
+
|
|
141
|
+
手动修复步骤:
|
|
142
|
+
```bash
|
|
143
|
+
# 1. 清除嵌套的缓存目录
|
|
139
144
|
rm -rf ~/.claude/plugins/cache/ultrapower
|
|
140
|
-
rm -rf ~/.claude/plugins/marketplaces/ultrapower
|
|
141
145
|
|
|
142
|
-
#
|
|
146
|
+
# 2. 清除 npm-cache(防止复用旧内容)
|
|
147
|
+
rm -rf ~/.claude/plugins/npm-cache
|
|
143
148
|
|
|
144
|
-
#
|
|
145
|
-
|
|
149
|
+
# 3. 刷新 marketplace 缓存
|
|
150
|
+
claude plugin marketplace update ultrapower
|
|
146
151
|
|
|
147
|
-
#
|
|
152
|
+
# 4. 重新安装(postinstall 会自动修复任何残留嵌套)
|
|
148
153
|
claude plugin install ultrapower
|
|
149
154
|
```
|
|
150
155
|
|
|
156
|
+
> ⚠️ `.npmignore` 中的 `ultrapower/` 排除项仍然必要,防止开发目录被打包进 npm 包。
|
|
157
|
+
|
|
151
158
|
### 安装后仍是旧版本
|
|
152
159
|
|
|
153
160
|
原因:本地 marketplace 缓存未更新,安装器读取的是旧版 `marketplace.json`。
|