superpowers-zh 1.5.0 → 1.7.0
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/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/.codex-plugin/plugin.json +3 -2
- package/.cursor-plugin/plugin.json +1 -1
- package/.pi/extensions/superpowers.ts +121 -0
- package/README.md +74 -35
- package/README.zh-Hant.md +353 -0
- package/RELEASE-NOTES.zh.md +59 -0
- package/assets/qr-wechat.jpg +0 -0
- package/bin/superpowers-zh.js +242 -98
- package/docs/README.antigravity.md +7 -7
- package/docs/README.codearts.md +49 -0
- package/docs/README.codebuddy.md +54 -0
- package/docs/README.kimi.md +86 -0
- package/docs/README.pi.md +54 -0
- package/docs/README.trae.md +6 -4
- package/gemini-extension.json +1 -1
- package/hooks/session-start +4 -12
- package/package.json +18 -4
- package/skills/brainstorming/SKILL.md +5 -0
- package/skills/brainstorming/scripts/frame-template.html +25 -26
- package/skills/brainstorming/scripts/helper.js +101 -22
- package/skills/brainstorming/scripts/server.cjs +399 -30
- package/skills/brainstorming/scripts/start-server.sh +70 -9
- package/skills/brainstorming/scripts/stop-server.sh +66 -2
- package/skills/chinese-code-review/SKILL.md +5 -0
- package/skills/chinese-commit-conventions/SKILL.md +5 -0
- package/skills/chinese-documentation/SKILL.md +5 -0
- package/skills/chinese-git-workflow/SKILL.md +5 -0
- package/skills/dispatching-parallel-agents/SKILL.md +5 -0
- package/skills/executing-plans/SKILL.md +7 -2
- package/skills/finishing-a-development-branch/SKILL.md +7 -2
- package/skills/mcp-builder/SKILL.md +5 -0
- package/skills/receiving-code-review/SKILL.md +5 -0
- package/skills/requesting-code-review/SKILL.md +5 -0
- package/skills/subagent-driven-development/SKILL.md +5 -0
- package/skills/systematic-debugging/SKILL.md +5 -0
- package/skills/test-driven-development/SKILL.md +5 -0
- package/skills/using-git-worktrees/SKILL.md +14 -24
- package/skills/using-superpowers/SKILL.md +24 -72
- package/skills/using-superpowers/references/codex-tools.md +2 -2
- package/skills/using-superpowers/references/pi-tools.md +28 -0
- package/skills/verification-before-completion/SKILL.md +5 -0
- package/skills/workflow-runner/SKILL.md +5 -0
- package/skills/writing-plans/SKILL.md +5 -0
- package/skills/writing-skills/SKILL.md +5 -0
|
@@ -11,6 +11,9 @@
|
|
|
11
11
|
# --host <bind-host> Host/interface to bind (default: 127.0.0.1).
|
|
12
12
|
# Use 0.0.0.0 in remote/containerized environments.
|
|
13
13
|
# --url-host <host> Hostname shown in returned URL JSON.
|
|
14
|
+
# --idle-timeout-minutes <n> Shut down after n minutes idle (default 240 = 4h).
|
|
15
|
+
# --open Auto-open the browser on the first screen (use only
|
|
16
|
+
# after the user approves the visual companion).
|
|
14
17
|
# --foreground Run server in the current terminal (no backgrounding).
|
|
15
18
|
# --background Force background mode (overrides Codex auto-foreground).
|
|
16
19
|
|
|
@@ -22,6 +25,7 @@ FOREGROUND="false"
|
|
|
22
25
|
FORCE_BACKGROUND="false"
|
|
23
26
|
BIND_HOST="127.0.0.1"
|
|
24
27
|
URL_HOST=""
|
|
28
|
+
IDLE_TIMEOUT_MINUTES=""
|
|
25
29
|
while [[ $# -gt 0 ]]; do
|
|
26
30
|
case "$1" in
|
|
27
31
|
--project-dir)
|
|
@@ -36,6 +40,14 @@ while [[ $# -gt 0 ]]; do
|
|
|
36
40
|
URL_HOST="$2"
|
|
37
41
|
shift 2
|
|
38
42
|
;;
|
|
43
|
+
--idle-timeout-minutes)
|
|
44
|
+
IDLE_TIMEOUT_MINUTES="$2"
|
|
45
|
+
shift 2
|
|
46
|
+
;;
|
|
47
|
+
--open)
|
|
48
|
+
export BRAINSTORM_OPEN=1
|
|
49
|
+
shift
|
|
50
|
+
;;
|
|
39
51
|
--foreground|--no-daemon)
|
|
40
52
|
FOREGROUND="true"
|
|
41
53
|
shift
|
|
@@ -59,6 +71,29 @@ if [[ -z "$URL_HOST" ]]; then
|
|
|
59
71
|
fi
|
|
60
72
|
fi
|
|
61
73
|
|
|
74
|
+
if [[ -n "$IDLE_TIMEOUT_MINUTES" ]]; then
|
|
75
|
+
if ! [[ "$IDLE_TIMEOUT_MINUTES" =~ ^[0-9]+$ ]] || [[ "$IDLE_TIMEOUT_MINUTES" -lt 1 ]]; then
|
|
76
|
+
echo "{\"error\": \"--idle-timeout-minutes must be a positive integer\"}"
|
|
77
|
+
exit 1
|
|
78
|
+
fi
|
|
79
|
+
export BRAINSTORM_IDLE_TIMEOUT_MS=$(( IDLE_TIMEOUT_MINUTES * 60 * 1000 ))
|
|
80
|
+
fi
|
|
81
|
+
|
|
82
|
+
is_windows_like_shell() {
|
|
83
|
+
case "${OSTYPE:-}" in
|
|
84
|
+
msys*|cygwin*|mingw*) return 0 ;;
|
|
85
|
+
esac
|
|
86
|
+
if [[ -n "${MSYSTEM:-}" ]]; then
|
|
87
|
+
return 0
|
|
88
|
+
fi
|
|
89
|
+
local uname_s
|
|
90
|
+
uname_s="$(uname -s 2>/dev/null || true)"
|
|
91
|
+
case "$uname_s" in
|
|
92
|
+
MSYS*|MINGW*|CYGWIN*) return 0 ;;
|
|
93
|
+
esac
|
|
94
|
+
return 1
|
|
95
|
+
}
|
|
96
|
+
|
|
62
97
|
# Some environments reap detached/background processes. Auto-foreground when detected.
|
|
63
98
|
if [[ -n "${CODEX_CI:-}" && "$FOREGROUND" != "true" && "$FORCE_BACKGROUND" != "true" ]]; then
|
|
64
99
|
FOREGROUND="true"
|
|
@@ -66,19 +101,24 @@ fi
|
|
|
66
101
|
|
|
67
102
|
# Windows/Git Bash reaps nohup background processes. Auto-foreground when detected.
|
|
68
103
|
if [[ "$FOREGROUND" != "true" && "$FORCE_BACKGROUND" != "true" ]]; then
|
|
69
|
-
|
|
70
|
-
msys*|cygwin*|mingw*) FOREGROUND="true" ;;
|
|
71
|
-
esac
|
|
72
|
-
if [[ -n "${MSYSTEM:-}" ]]; then
|
|
104
|
+
if is_windows_like_shell; then
|
|
73
105
|
FOREGROUND="true"
|
|
74
106
|
fi
|
|
75
107
|
fi
|
|
76
108
|
|
|
109
|
+
# Session files (server.log, server-info, .last-token) embed the session key —
|
|
110
|
+
# keep everything this script and the server create owner-only.
|
|
111
|
+
umask 077
|
|
112
|
+
|
|
77
113
|
# Generate unique session directory
|
|
78
114
|
SESSION_ID="$$-$(date +%s)"
|
|
79
115
|
|
|
80
116
|
if [[ -n "$PROJECT_DIR" ]]; then
|
|
81
117
|
SESSION_DIR="${PROJECT_DIR}/.superpowers/brainstorm/${SESSION_ID}"
|
|
118
|
+
# Persist the bound port and key per project so a restart reuses them and an
|
|
119
|
+
# already-open browser tab reconnects to the same URL with a valid cookie.
|
|
120
|
+
export BRAINSTORM_PORT_FILE="${PROJECT_DIR}/.superpowers/brainstorm/.last-port"
|
|
121
|
+
export BRAINSTORM_TOKEN_FILE="${PROJECT_DIR}/.superpowers/brainstorm/.last-token"
|
|
82
122
|
else
|
|
83
123
|
SESSION_DIR="/tmp/brainstorm-${SESSION_ID}"
|
|
84
124
|
fi
|
|
@@ -86,10 +126,21 @@ fi
|
|
|
86
126
|
STATE_DIR="${SESSION_DIR}/state"
|
|
87
127
|
PID_FILE="${STATE_DIR}/server.pid"
|
|
88
128
|
LOG_FILE="${STATE_DIR}/server.log"
|
|
129
|
+
SERVER_ID_FILE="${STATE_DIR}/server-instance-id"
|
|
89
130
|
|
|
90
131
|
# Create fresh session directory with content and state peers
|
|
91
132
|
mkdir -p "${SESSION_DIR}/content" "$STATE_DIR"
|
|
92
133
|
|
|
134
|
+
SERVER_ID=""
|
|
135
|
+
if [[ -r /dev/urandom ]]; then
|
|
136
|
+
SERVER_ID="$(od -An -N24 -tx1 /dev/urandom 2>/dev/null | tr -d ' \n' || true)"
|
|
137
|
+
fi
|
|
138
|
+
if ! [[ "$SERVER_ID" =~ ^[A-Za-z0-9_-]{32,64}$ ]]; then
|
|
139
|
+
SERVER_ID="$(printf '%08x%08x%08x%08x' "$$" "$(date +%s)" "${RANDOM:-0}" "${RANDOM:-0}")"
|
|
140
|
+
fi
|
|
141
|
+
printf '%s\n' "$SERVER_ID" > "$SERVER_ID_FILE"
|
|
142
|
+
chmod 600 "$SERVER_ID_FILE" 2>/dev/null || true
|
|
143
|
+
|
|
93
144
|
# Kill any existing server
|
|
94
145
|
if [[ -f "$PID_FILE" ]]; then
|
|
95
146
|
old_pid=$(cat "$PID_FILE")
|
|
@@ -97,7 +148,7 @@ if [[ -f "$PID_FILE" ]]; then
|
|
|
97
148
|
rm -f "$PID_FILE"
|
|
98
149
|
fi
|
|
99
150
|
|
|
100
|
-
cd "$SCRIPT_DIR"
|
|
151
|
+
cd "$SCRIPT_DIR" || exit 1
|
|
101
152
|
|
|
102
153
|
# Resolve the harness PID (grandparent of this script).
|
|
103
154
|
# $PPID is the ephemeral shell the harness spawned to run us — it dies
|
|
@@ -107,22 +158,32 @@ if [[ -z "$OWNER_PID" || "$OWNER_PID" == "1" ]]; then
|
|
|
107
158
|
OWNER_PID="$PPID"
|
|
108
159
|
fi
|
|
109
160
|
|
|
161
|
+
# Windows/MSYS2: Node.js cannot see POSIX PIDs from the MSYS2 namespace.
|
|
162
|
+
# Passing a PID node cannot verify causes server to log owner-pid-invalid
|
|
163
|
+
# and self-terminate at the 60-second lifecycle check. Clear it so the
|
|
164
|
+
# watchdog is disabled and the idle timeout becomes the only shutdown trigger.
|
|
165
|
+
if is_windows_like_shell; then
|
|
166
|
+
OWNER_PID=""
|
|
167
|
+
fi
|
|
168
|
+
|
|
110
169
|
# Foreground mode for environments that reap detached/background processes.
|
|
111
170
|
if [[ "$FOREGROUND" == "true" ]]; then
|
|
112
|
-
|
|
113
|
-
|
|
171
|
+
env BRAINSTORM_DIR="$SESSION_DIR" BRAINSTORM_HOST="$BIND_HOST" BRAINSTORM_URL_HOST="$URL_HOST" BRAINSTORM_OWNER_PID="$OWNER_PID" node server.cjs "--brainstorm-server-id=$SERVER_ID" &
|
|
172
|
+
SERVER_PID=$!
|
|
173
|
+
echo "$SERVER_PID" > "$PID_FILE"
|
|
174
|
+
wait "$SERVER_PID"
|
|
114
175
|
exit $?
|
|
115
176
|
fi
|
|
116
177
|
|
|
117
178
|
# Start server, capturing output to log file
|
|
118
179
|
# Use nohup to survive shell exit; disown to remove from job table
|
|
119
|
-
nohup env BRAINSTORM_DIR="$SESSION_DIR" BRAINSTORM_HOST="$BIND_HOST" BRAINSTORM_URL_HOST="$URL_HOST" BRAINSTORM_OWNER_PID="$OWNER_PID" node server.cjs > "$LOG_FILE" 2>&1 &
|
|
180
|
+
nohup env BRAINSTORM_DIR="$SESSION_DIR" BRAINSTORM_HOST="$BIND_HOST" BRAINSTORM_URL_HOST="$URL_HOST" BRAINSTORM_OWNER_PID="$OWNER_PID" node server.cjs "--brainstorm-server-id=$SERVER_ID" > "$LOG_FILE" 2>&1 &
|
|
120
181
|
SERVER_PID=$!
|
|
121
182
|
disown "$SERVER_PID" 2>/dev/null
|
|
122
183
|
echo "$SERVER_PID" > "$PID_FILE"
|
|
123
184
|
|
|
124
185
|
# Wait for server-started message (check log file)
|
|
125
|
-
for
|
|
186
|
+
for _ in {1..50}; do
|
|
126
187
|
if grep -q "server-started" "$LOG_FILE" 2>/dev/null; then
|
|
127
188
|
# Verify server is still alive after a short window (catches process reapers)
|
|
128
189
|
alive="true"
|
|
@@ -15,15 +15,78 @@ fi
|
|
|
15
15
|
|
|
16
16
|
STATE_DIR="${SESSION_DIR}/state"
|
|
17
17
|
PID_FILE="${STATE_DIR}/server.pid"
|
|
18
|
+
SERVER_ID_FILE="${STATE_DIR}/server-instance-id"
|
|
19
|
+
|
|
20
|
+
mark_stopped() {
|
|
21
|
+
local reason="$1"
|
|
22
|
+
rm -f "${STATE_DIR}/server-info"
|
|
23
|
+
printf '{"reason":"%s","timestamp":%s}\n' "$reason" "$(date +%s)" > "${STATE_DIR}/server-stopped"
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
read_expected_server_id() {
|
|
27
|
+
[[ -f "$SERVER_ID_FILE" ]] || return 1
|
|
28
|
+
local id
|
|
29
|
+
id="$(tr -d '\r\n' < "$SERVER_ID_FILE" 2>/dev/null || true)"
|
|
30
|
+
[[ "$id" =~ ^[A-Za-z0-9_-]{32,64}$ ]] || return 1
|
|
31
|
+
printf '%s\n' "$id"
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
command_line_for_pid() {
|
|
35
|
+
local pid="$1"
|
|
36
|
+
if [[ -r "/proc/$pid/cmdline" ]]; then
|
|
37
|
+
tr '\0' '\n' < "/proc/$pid/cmdline" 2>/dev/null || true
|
|
38
|
+
return 0
|
|
39
|
+
fi
|
|
40
|
+
ps -ww -p "$pid" -o command= 2>/dev/null || ps -f -p "$pid" 2>/dev/null | sed '1d' || true
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
command_has_server_id() {
|
|
44
|
+
local pid="$1"
|
|
45
|
+
local expected="$2"
|
|
46
|
+
local expected_arg="--brainstorm-server-id=$expected"
|
|
47
|
+
if [[ -r "/proc/$pid/cmdline" ]]; then
|
|
48
|
+
local arg
|
|
49
|
+
while IFS= read -r -d '' arg || [[ -n "$arg" ]]; do
|
|
50
|
+
[[ "$arg" == "$expected_arg" ]] && return 0
|
|
51
|
+
done < "/proc/$pid/cmdline"
|
|
52
|
+
return 1
|
|
53
|
+
fi
|
|
54
|
+
local command_line
|
|
55
|
+
command_line="$(command_line_for_pid "$pid")"
|
|
56
|
+
[[ -n "$command_line" ]] || return 1
|
|
57
|
+
case " $command_line " in
|
|
58
|
+
*" $expected_arg "*) return 0 ;;
|
|
59
|
+
*) return 1 ;;
|
|
60
|
+
esac
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
# Confirm a PID has this session's per-start instance id, not just a familiar
|
|
64
|
+
# process name. Ambiguous or legacy metadata fails closed as stale_pid.
|
|
65
|
+
is_brainstorm_server() {
|
|
66
|
+
kill -0 "$1" 2>/dev/null || return 1
|
|
67
|
+
local expected_id
|
|
68
|
+
expected_id="$(read_expected_server_id)" || return 1
|
|
69
|
+
command_has_server_id "$1" "$expected_id" || return 1
|
|
70
|
+
return 0
|
|
71
|
+
}
|
|
18
72
|
|
|
19
73
|
if [[ -f "$PID_FILE" ]]; then
|
|
20
74
|
pid=$(cat "$PID_FILE")
|
|
21
75
|
|
|
76
|
+
# Refuse to signal a PID we can't prove is our server. A stale pid file may
|
|
77
|
+
# point at an unrelated process after a reboot/PID wraparound.
|
|
78
|
+
if ! is_brainstorm_server "$pid"; then
|
|
79
|
+
rm -f "$PID_FILE" "$SERVER_ID_FILE"
|
|
80
|
+
mark_stopped "stale_pid"
|
|
81
|
+
echo '{"status": "stale_pid"}'
|
|
82
|
+
exit 0
|
|
83
|
+
fi
|
|
84
|
+
|
|
22
85
|
# Try to stop gracefully, fallback to force if still alive
|
|
23
86
|
kill "$pid" 2>/dev/null || true
|
|
24
87
|
|
|
25
88
|
# Wait for graceful shutdown (up to ~2s)
|
|
26
|
-
for
|
|
89
|
+
for _ in {1..20}; do
|
|
27
90
|
if ! kill -0 "$pid" 2>/dev/null; then
|
|
28
91
|
break
|
|
29
92
|
fi
|
|
@@ -43,7 +106,8 @@ if [[ -f "$PID_FILE" ]]; then
|
|
|
43
106
|
exit 1
|
|
44
107
|
fi
|
|
45
108
|
|
|
46
|
-
rm -f "$PID_FILE" "${STATE_DIR}/server.log"
|
|
109
|
+
rm -f "$PID_FILE" "$SERVER_ID_FILE" "${STATE_DIR}/server.log"
|
|
110
|
+
mark_stopped "stop-server.sh"
|
|
47
111
|
|
|
48
112
|
# Only delete ephemeral /tmp directories
|
|
49
113
|
if [[ "$SESSION_DIR" == /tmp/* ]]; then
|
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: chinese-commit-conventions
|
|
3
3
|
description: 中文 commit 与 changelog 配置参考——Conventional Commits 中文适配、commitlint/husky/commitizen 中文模板、conventional-changelog 中文配置。仅在用户显式 /chinese-commit-conventions 时调用,不要根据上下文自动触发。
|
|
4
|
+
version: "1.0.0"
|
|
5
|
+
license: MIT
|
|
6
|
+
metadata:
|
|
7
|
+
hermes:
|
|
8
|
+
tags: [git, chinese]
|
|
4
9
|
---
|
|
5
10
|
|
|
6
11
|
# 中文 Git 提交规范
|
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: chinese-git-workflow
|
|
3
3
|
description: 国内 Git 平台配置参考——Gitee、Coding.net、极狐 GitLab、CNB 的 SSH/HTTPS/凭据/CI 接入差异与镜像同步配置。仅在用户显式 /chinese-git-workflow 时调用,不要根据上下文自动触发。
|
|
4
|
+
version: "1.0.0"
|
|
5
|
+
license: MIT
|
|
6
|
+
metadata:
|
|
7
|
+
hermes:
|
|
8
|
+
tags: [git, chinese]
|
|
4
9
|
---
|
|
5
10
|
|
|
6
11
|
# 国内 Git 工作流规范
|
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: executing-plans
|
|
3
3
|
description: 当你有一份书面实现计划需要在单独的会话中执行,并设有审查检查点时使用
|
|
4
|
+
version: "1.0.0"
|
|
5
|
+
license: MIT
|
|
6
|
+
metadata:
|
|
7
|
+
hermes:
|
|
8
|
+
tags: [execution, planning]
|
|
4
9
|
---
|
|
5
10
|
|
|
6
11
|
# 执行计划
|
|
@@ -80,8 +85,8 @@ $ git commit -m "feat: 添加用户输入验证(任务 2/5)"
|
|
|
80
85
|
--- 任务 2/5 完成 ---
|
|
81
86
|
```
|
|
82
87
|
|
|
83
|
-
|
|
84
|
-
-
|
|
88
|
+
**持续自查:**
|
|
89
|
+
- 执行过程中持续留意:整体方向还对吗?有没有偏离计划?
|
|
85
90
|
- 如果发现前面的实现有问题,先修复再继续,不要带着问题往下走
|
|
86
91
|
|
|
87
92
|
### 步骤 3:处理常见异常
|
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: finishing-a-development-branch
|
|
3
3
|
description: 当实现完成、所有测试通过、需要决定如何集成工作时使用——通过提供合并、PR 或清理等结构化选项来引导开发工作的收尾
|
|
4
|
+
version: "1.0.0"
|
|
5
|
+
license: MIT
|
|
6
|
+
metadata:
|
|
7
|
+
hermes:
|
|
8
|
+
tags: [git, workflow]
|
|
4
9
|
---
|
|
5
10
|
|
|
6
11
|
# 完成开发分支
|
|
@@ -184,7 +189,7 @@ WORKTREE_PATH=$(git rev-parse --show-toplevel)
|
|
|
184
189
|
|
|
185
190
|
**如果 `GIT_DIR == GIT_COMMON`:** 普通仓库,无 worktree 可清理。结束。
|
|
186
191
|
|
|
187
|
-
**如果 worktree 路径在 `.worktrees
|
|
192
|
+
**如果 worktree 路径在 `.worktrees/` 或 `worktrees/` 之下:** 这是 Superpowers 创建的 worktree —— 我们负责清理。
|
|
188
193
|
|
|
189
194
|
```bash
|
|
190
195
|
MAIN_ROOT=$(git -C "$(git rev-parse --git-common-dir)/.." rev-parse --show-toplevel)
|
|
@@ -234,7 +239,7 @@ git worktree prune # 自愈:清理任何过期的注册记录
|
|
|
234
239
|
**清理 harness 拥有的 worktree**
|
|
235
240
|
|
|
236
241
|
- **问题:** 移除 harness 创建的 worktree 会造成幻影状态
|
|
237
|
-
- **修复:** 只清理 `.worktrees
|
|
242
|
+
- **修复:** 只清理 `.worktrees/` 或 `worktrees/` 下的 worktree
|
|
238
243
|
|
|
239
244
|
**丢弃时不确认**
|
|
240
245
|
|
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: using-git-worktrees
|
|
3
3
|
description: 当需要开始与当前工作区隔离的功能开发,或在执行实现计划之前使用——通过原生工具或 git worktree 回退机制确保隔离工作区存在
|
|
4
|
+
version: "1.0.0"
|
|
5
|
+
license: MIT
|
|
6
|
+
metadata:
|
|
7
|
+
hermes:
|
|
8
|
+
tags: [git, workflow]
|
|
4
9
|
---
|
|
5
10
|
|
|
6
11
|
# 使用 Git 工作树
|
|
@@ -30,7 +35,7 @@ BRANCH=$(git branch --show-current)
|
|
|
30
35
|
git rev-parse --show-superproject-working-tree 2>/dev/null
|
|
31
36
|
```
|
|
32
37
|
|
|
33
|
-
**如果 `GIT_DIR != GIT_COMMON`(且不是 submodule):** 你已经在一个 linked worktree 内。跳到步骤
|
|
38
|
+
**如果 `GIT_DIR != GIT_COMMON`(且不是 submodule):** 你已经在一个 linked worktree 内。跳到步骤 2(项目设置)。**不要**再创建一个 worktree。
|
|
34
39
|
|
|
35
40
|
按分支状态报告:
|
|
36
41
|
|
|
@@ -43,7 +48,7 @@ git rev-parse --show-superproject-working-tree 2>/dev/null
|
|
|
43
48
|
|
|
44
49
|
> "你希望我搭一个隔离的 worktree 吗?它能保护你当前分支不被改动。"
|
|
45
50
|
|
|
46
|
-
如果用户已声明过偏好,直接遵循,不再询问。如果用户拒绝同意,原地工作并跳到步骤
|
|
51
|
+
如果用户已声明过偏好,直接遵循,不再询问。如果用户拒绝同意,原地工作并跳到步骤 2。
|
|
47
52
|
|
|
48
53
|
## 步骤 1:创建隔离工作区
|
|
49
54
|
|
|
@@ -51,7 +56,7 @@ git rev-parse --show-superproject-working-tree 2>/dev/null
|
|
|
51
56
|
|
|
52
57
|
### 1a. 原生 Worktree 工具(首选)
|
|
53
58
|
|
|
54
|
-
用户已经请求隔离工作区(步骤 0 已获同意)。你是否已经有创建 worktree 的方法?可能是名为 `EnterWorktree`、`WorktreeCreate` 的工具、`/worktree` 命令,或 `--worktree` 标志。如果有,用它,然后跳到步骤
|
|
59
|
+
用户已经请求隔离工作区(步骤 0 已获同意)。你是否已经有创建 worktree 的方法?可能是名为 `EnterWorktree`、`WorktreeCreate` 的工具、`/worktree` 命令,或 `--worktree` 标志。如果有,用它,然后跳到步骤 2。
|
|
55
60
|
|
|
56
61
|
原生工具自动处理目录放置、分支创建和清理。在你已经有原生工具的情况下使用 `git worktree add`,会创建你的 harness 看不到也无法管理的"幻影状态"。
|
|
57
62
|
|
|
@@ -76,16 +81,7 @@ git rev-parse --show-superproject-working-tree 2>/dev/null
|
|
|
76
81
|
|
|
77
82
|
找到就用。如果两者都存在,`.worktrees` 优先。
|
|
78
83
|
|
|
79
|
-
3.
|
|
80
|
-
|
|
81
|
-
```bash
|
|
82
|
-
project=$(basename "$(git rev-parse --show-toplevel)")
|
|
83
|
-
ls -d ~/.config/superpowers/worktrees/$project 2>/dev/null
|
|
84
|
-
```
|
|
85
|
-
|
|
86
|
-
找到就用(兼容老的全局路径)。
|
|
87
|
-
|
|
88
|
-
4. **如果没有其他可参考的信息**,默认用项目根目录下的 `.worktrees/`。
|
|
84
|
+
3. **如果没有其他可参考的信息**,默认用项目根目录下的 `.worktrees/`。
|
|
89
85
|
|
|
90
86
|
#### 安全验证(仅项目本地目录)
|
|
91
87
|
|
|
@@ -99,16 +95,11 @@ git check-ignore -q .worktrees 2>/dev/null || git check-ignore -q worktrees 2>/d
|
|
|
99
95
|
|
|
100
96
|
**为什么关键:** 防止 worktree 内容被意外提交到仓库。
|
|
101
97
|
|
|
102
|
-
全局目录(`~/.config/superpowers/worktrees/`)无需验证。
|
|
103
|
-
|
|
104
98
|
#### 创建工作树
|
|
105
99
|
|
|
106
100
|
```bash
|
|
107
|
-
project=$(basename "$(git rev-parse --show-toplevel)")
|
|
108
|
-
|
|
109
101
|
# 根据选定位置确定路径
|
|
110
|
-
|
|
111
|
-
# 全局:path="~/.config/superpowers/worktrees/$project/$BRANCH_NAME"
|
|
102
|
+
path="$LOCATION/$BRANCH_NAME"
|
|
112
103
|
|
|
113
104
|
git worktree add "$path" -b "$BRANCH_NAME"
|
|
114
105
|
cd "$path"
|
|
@@ -116,7 +107,7 @@ cd "$path"
|
|
|
116
107
|
|
|
117
108
|
**沙盒回退:** 如果 `git worktree add` 因权限错误(沙盒拒绝)失败,告诉用户沙盒阻止了 worktree 创建,你将在当前目录原地工作。然后原地运行 setup 和基线测试。
|
|
118
109
|
|
|
119
|
-
## 步骤
|
|
110
|
+
## 步骤 2:项目设置
|
|
120
111
|
|
|
121
112
|
自动检测并运行相应的设置命令:
|
|
122
113
|
|
|
@@ -135,7 +126,7 @@ if [ -f pyproject.toml ]; then poetry install; fi
|
|
|
135
126
|
if [ -f go.mod ]; then go mod download; fi
|
|
136
127
|
```
|
|
137
128
|
|
|
138
|
-
## 步骤
|
|
129
|
+
## 步骤 3:验证基线干净
|
|
139
130
|
|
|
140
131
|
运行测试确保工作区初始状态干净:
|
|
141
132
|
|
|
@@ -168,7 +159,6 @@ npm test / cargo test / pytest / go test ./...
|
|
|
168
159
|
| `worktrees/` 存在 | 用它(验证已忽略) |
|
|
169
160
|
| 两者都存在 | 用 `.worktrees/` |
|
|
170
161
|
| 都不存在 | 检查 instructions 文件,再默认 `.worktrees/` |
|
|
171
|
-
| 全局路径存在 | 用它(向后兼容) |
|
|
172
162
|
| 目录未被忽略 | 添加到 .gitignore + 提交 |
|
|
173
163
|
| 创建时权限错误 | 沙盒回退,原地工作 |
|
|
174
164
|
| 基线测试失败 | 报告失败 + 询问 |
|
|
@@ -194,7 +184,7 @@ npm test / cargo test / pytest / go test ./...
|
|
|
194
184
|
### 假设目录位置
|
|
195
185
|
|
|
196
186
|
- **问题:** 造成不一致、违反项目约定
|
|
197
|
-
- **修复:**
|
|
187
|
+
- **修复:** 遵循优先级:明确 instructions > 现有项目本地目录 > 默认
|
|
198
188
|
|
|
199
189
|
### 带着失败的测试继续
|
|
200
190
|
|
|
@@ -216,7 +206,7 @@ npm test / cargo test / pytest / go test ./...
|
|
|
216
206
|
|
|
217
207
|
- 先跑步骤 0 检测
|
|
218
208
|
- 优先原生工具,其次 git 回退
|
|
219
|
-
-
|
|
209
|
+
- 遵循目录优先级:明确 instructions > 现有项目本地目录 > 默认
|
|
220
210
|
- 项目本地目录验证已忽略
|
|
221
211
|
- 自动检测并运行项目设置
|
|
222
212
|
- 验证测试基线干净
|