superpowers-zh 1.3.0 → 1.6.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 +3 -3
- package/.claude-plugin/plugin.json +2 -2
- package/.codex-plugin/plugin.json +1 -1
- package/.cursor-plugin/plugin.json +2 -2
- package/.pi/extensions/superpowers.ts +121 -0
- package/CLAUDE.md +1 -1
- package/README.md +77 -34
- package/RELEASE-NOTES.zh.md +150 -0
- package/assets/qr-wechat.jpg +0 -0
- package/assets/sponsors/5cookie-code.png +0 -0
- package/bin/superpowers-zh.js +69 -18
- package/docs/README.antigravity.md +7 -7
- package/docs/README.kimi.md +86 -0
- package/docs/README.openclaw.md +7 -4
- package/docs/README.pi.md +54 -0
- package/docs/README.qoder.md +95 -0
- package/docs/README.trae.md +6 -4
- package/gemini-extension.json +1 -1
- package/hooks/hooks-cursor.json +1 -1
- package/hooks/session-start +4 -12
- package/package.json +18 -5
- 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 +428 -43
- package/skills/brainstorming/scripts/start-server.sh +76 -20
- package/skills/brainstorming/scripts/stop-server.sh +74 -9
- 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 +112 -32
- package/skills/mcp-builder/SKILL.md +5 -0
- package/skills/receiving-code-review/SKILL.md +5 -0
- package/skills/requesting-code-review/SKILL.md +13 -10
- package/skills/requesting-code-review/code-reviewer.md +124 -104
- 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 +104 -97
- package/skills/using-superpowers/SKILL.md +6 -1
- package/skills/using-superpowers/references/pi-tools.md +28 -0
- package/skills/using-superpowers/references/qoder-tools.md +43 -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,28 +101,45 @@ 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
|
|
85
125
|
|
|
86
|
-
|
|
87
|
-
|
|
126
|
+
STATE_DIR="${SESSION_DIR}/state"
|
|
127
|
+
PID_FILE="${STATE_DIR}/server.pid"
|
|
128
|
+
LOG_FILE="${STATE_DIR}/server.log"
|
|
129
|
+
SERVER_ID_FILE="${STATE_DIR}/server-instance-id"
|
|
88
130
|
|
|
89
|
-
# Create fresh session directory
|
|
90
|
-
mkdir -p "$
|
|
131
|
+
# Create fresh session directory with content and state peers
|
|
132
|
+
mkdir -p "${SESSION_DIR}/content" "$STATE_DIR"
|
|
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
|
|
91
143
|
|
|
92
144
|
# Kill any existing server
|
|
93
145
|
if [[ -f "$PID_FILE" ]]; then
|
|
@@ -96,7 +148,7 @@ if [[ -f "$PID_FILE" ]]; then
|
|
|
96
148
|
rm -f "$PID_FILE"
|
|
97
149
|
fi
|
|
98
150
|
|
|
99
|
-
cd "$SCRIPT_DIR"
|
|
151
|
+
cd "$SCRIPT_DIR" || exit 1
|
|
100
152
|
|
|
101
153
|
# Resolve the harness PID (grandparent of this script).
|
|
102
154
|
# $PPID is the ephemeral shell the harness spawned to run us — it dies
|
|
@@ -106,28 +158,32 @@ if [[ -z "$OWNER_PID" || "$OWNER_PID" == "1" ]]; then
|
|
|
106
158
|
OWNER_PID="$PPID"
|
|
107
159
|
fi
|
|
108
160
|
|
|
109
|
-
#
|
|
110
|
-
#
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
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
|
|
114
168
|
|
|
115
169
|
# Foreground mode for environments that reap detached/background processes.
|
|
116
170
|
if [[ "$FOREGROUND" == "true" ]]; then
|
|
117
|
-
|
|
118
|
-
|
|
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"
|
|
119
175
|
exit $?
|
|
120
176
|
fi
|
|
121
177
|
|
|
122
178
|
# Start server, capturing output to log file
|
|
123
179
|
# Use nohup to survive shell exit; disown to remove from job table
|
|
124
|
-
nohup env BRAINSTORM_DIR="$
|
|
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 &
|
|
125
181
|
SERVER_PID=$!
|
|
126
182
|
disown "$SERVER_PID" 2>/dev/null
|
|
127
183
|
echo "$SERVER_PID" > "$PID_FILE"
|
|
128
184
|
|
|
129
185
|
# Wait for server-started message (check log file)
|
|
130
|
-
for
|
|
186
|
+
for _ in {1..50}; do
|
|
131
187
|
if grep -q "server-started" "$LOG_FILE" 2>/dev/null; then
|
|
132
188
|
# Verify server is still alive after a short window (catches process reapers)
|
|
133
189
|
alive="true"
|
|
@@ -1,28 +1,92 @@
|
|
|
1
1
|
#!/usr/bin/env bash
|
|
2
2
|
# Stop the brainstorm server and clean up
|
|
3
|
-
# Usage: stop-server.sh <
|
|
3
|
+
# Usage: stop-server.sh <session_dir>
|
|
4
4
|
#
|
|
5
5
|
# Kills the server process. Only deletes session directory if it's
|
|
6
6
|
# under /tmp (ephemeral). Persistent directories (.superpowers/) are
|
|
7
7
|
# kept so mockups can be reviewed later.
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
SESSION_DIR="$1"
|
|
10
10
|
|
|
11
|
-
if [[ -z "$
|
|
12
|
-
echo '{"error": "Usage: stop-server.sh <
|
|
11
|
+
if [[ -z "$SESSION_DIR" ]]; then
|
|
12
|
+
echo '{"error": "Usage: stop-server.sh <session_dir>"}'
|
|
13
13
|
exit 1
|
|
14
14
|
fi
|
|
15
15
|
|
|
16
|
-
|
|
16
|
+
STATE_DIR="${SESSION_DIR}/state"
|
|
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
|
+
}
|
|
17
72
|
|
|
18
73
|
if [[ -f "$PID_FILE" ]]; then
|
|
19
74
|
pid=$(cat "$PID_FILE")
|
|
20
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
|
+
|
|
21
85
|
# Try to stop gracefully, fallback to force if still alive
|
|
22
86
|
kill "$pid" 2>/dev/null || true
|
|
23
87
|
|
|
24
88
|
# Wait for graceful shutdown (up to ~2s)
|
|
25
|
-
for
|
|
89
|
+
for _ in {1..20}; do
|
|
26
90
|
if ! kill -0 "$pid" 2>/dev/null; then
|
|
27
91
|
break
|
|
28
92
|
fi
|
|
@@ -42,11 +106,12 @@ if [[ -f "$PID_FILE" ]]; then
|
|
|
42
106
|
exit 1
|
|
43
107
|
fi
|
|
44
108
|
|
|
45
|
-
rm -f "$PID_FILE" "${
|
|
109
|
+
rm -f "$PID_FILE" "$SERVER_ID_FILE" "${STATE_DIR}/server.log"
|
|
110
|
+
mark_stopped "stop-server.sh"
|
|
46
111
|
|
|
47
112
|
# Only delete ephemeral /tmp directories
|
|
48
|
-
if [[ "$
|
|
49
|
-
rm -rf "$
|
|
113
|
+
if [[ "$SESSION_DIR" == /tmp/* ]]; then
|
|
114
|
+
rm -rf "$SESSION_DIR"
|
|
50
115
|
fi
|
|
51
116
|
|
|
52
117
|
echo '{"status": "stopped"}'
|
|
@@ -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
|
# 完成开发分支
|
|
@@ -9,7 +14,7 @@ description: 当实现完成、所有测试通过、需要决定如何集成工
|
|
|
9
14
|
|
|
10
15
|
通过提供清晰的选项并执行所选工作流来引导开发工作的收尾。
|
|
11
16
|
|
|
12
|
-
**核心原则:** 验证测试 → 展示选项 → 执行选择 → 清理。
|
|
17
|
+
**核心原则:** 验证测试 → 检测环境 → 展示选项 → 执行选择 → 清理。
|
|
13
18
|
|
|
14
19
|
**开始时宣布:** "我正在使用 finishing-a-development-branch 技能来完成这项工作。"
|
|
15
20
|
|
|
@@ -25,6 +30,7 @@ npm test / cargo test / pytest / go test ./...
|
|
|
25
30
|
```
|
|
26
31
|
|
|
27
32
|
**如果测试失败:**
|
|
33
|
+
|
|
28
34
|
```
|
|
29
35
|
测试失败(<N> 个失败)。必须先修复才能继续:
|
|
30
36
|
|
|
@@ -37,7 +43,24 @@ npm test / cargo test / pytest / go test ./...
|
|
|
37
43
|
|
|
38
44
|
**如果测试通过:** 继续步骤 2。
|
|
39
45
|
|
|
40
|
-
### 步骤 2
|
|
46
|
+
### 步骤 2:检测环境
|
|
47
|
+
|
|
48
|
+
**在展示选项之前,先确定工作区状态:**
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
GIT_DIR=$(cd "$(git rev-parse --git-dir)" 2>/dev/null && pwd -P)
|
|
52
|
+
GIT_COMMON=$(cd "$(git rev-parse --git-common-dir)" 2>/dev/null && pwd -P)
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
这决定了展示哪种菜单、以及清理方式:
|
|
56
|
+
|
|
57
|
+
| 状态 | 菜单 | 清理 |
|
|
58
|
+
|------|------|------|
|
|
59
|
+
| `GIT_DIR == GIT_COMMON`(普通仓库) | 标准 4 个选项 | 无 worktree 可清理 |
|
|
60
|
+
| `GIT_DIR != GIT_COMMON`,命名分支 | 标准 4 个选项 | 按来源判断(见步骤 6) |
|
|
61
|
+
| `GIT_DIR != GIT_COMMON`,分离 HEAD | 收敛 3 个选项(无合并) | 无清理(由外部管理) |
|
|
62
|
+
|
|
63
|
+
### 步骤 3:确定基础分支
|
|
41
64
|
|
|
42
65
|
```bash
|
|
43
66
|
# 尝试常见的基础分支
|
|
@@ -46,9 +69,9 @@ git merge-base HEAD main 2>/dev/null || git merge-base HEAD master 2>/dev/null
|
|
|
46
69
|
|
|
47
70
|
或者询问:"这个分支是从 main 分出来的——对吗?"
|
|
48
71
|
|
|
49
|
-
### 步骤
|
|
72
|
+
### 步骤 4:展示选项
|
|
50
73
|
|
|
51
|
-
|
|
74
|
+
**普通仓库和命名分支 worktree —— 准确展示以下 4 个选项:**
|
|
52
75
|
|
|
53
76
|
```
|
|
54
77
|
实现已完成。你想怎么做?
|
|
@@ -61,30 +84,45 @@ git merge-base HEAD main 2>/dev/null || git merge-base HEAD master 2>/dev/null
|
|
|
61
84
|
选哪个?
|
|
62
85
|
```
|
|
63
86
|
|
|
64
|
-
|
|
87
|
+
**分离 HEAD —— 准确展示以下 3 个选项:**
|
|
88
|
+
|
|
89
|
+
```
|
|
90
|
+
实现已完成。你在分离 HEAD 上(由外部管理的工作区)。
|
|
91
|
+
|
|
92
|
+
1. 作为新分支推送并创建 Pull Request
|
|
93
|
+
2. 保持现状(我稍后处理)
|
|
94
|
+
3. 丢弃这项工作
|
|
95
|
+
|
|
96
|
+
选哪个?
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
**不要添加解释** —— 保持选项简洁。
|
|
65
100
|
|
|
66
|
-
### 步骤
|
|
101
|
+
### 步骤 5:执行选择
|
|
67
102
|
|
|
68
103
|
#### 选项 1:本地合并
|
|
69
104
|
|
|
70
105
|
```bash
|
|
71
|
-
#
|
|
72
|
-
git
|
|
106
|
+
# 切到主仓库根目录,保证 CWD 安全
|
|
107
|
+
MAIN_ROOT=$(git -C "$(git rev-parse --git-common-dir)/.." rev-parse --show-toplevel)
|
|
108
|
+
cd "$MAIN_ROOT"
|
|
73
109
|
|
|
74
|
-
#
|
|
110
|
+
# 先合并 —— 在删除任何东西之前先验证合并成功
|
|
111
|
+
git checkout <base-branch>
|
|
75
112
|
git pull
|
|
76
|
-
|
|
77
|
-
# 合并功能分支
|
|
78
113
|
git merge <feature-branch>
|
|
79
114
|
|
|
80
115
|
# 在合并结果上验证测试
|
|
81
116
|
<test command>
|
|
82
117
|
|
|
83
|
-
#
|
|
84
|
-
git branch -d <feature-branch>
|
|
118
|
+
# 合并成功之后再:清理 worktree(步骤 6),然后删除分支
|
|
85
119
|
```
|
|
86
120
|
|
|
87
|
-
|
|
121
|
+
然后:清理 worktree(步骤 6),再删除分支:
|
|
122
|
+
|
|
123
|
+
```bash
|
|
124
|
+
git branch -d <feature-branch>
|
|
125
|
+
```
|
|
88
126
|
|
|
89
127
|
#### 选项 2:推送并创建 PR
|
|
90
128
|
|
|
@@ -103,7 +141,7 @@ EOF
|
|
|
103
141
|
)"
|
|
104
142
|
```
|
|
105
143
|
|
|
106
|
-
|
|
144
|
+
**不要清理 worktree** —— 用户在 PR 反馈迭代时还需要它存活。
|
|
107
145
|
|
|
108
146
|
#### 选项 3:保持现状
|
|
109
147
|
|
|
@@ -114,6 +152,7 @@ EOF
|
|
|
114
152
|
#### 选项 4:丢弃
|
|
115
153
|
|
|
116
154
|
**先确认:**
|
|
155
|
+
|
|
117
156
|
```
|
|
118
157
|
这将永久删除:
|
|
119
158
|
- 分支 <name>
|
|
@@ -126,28 +165,40 @@ EOF
|
|
|
126
165
|
等待精确的确认。
|
|
127
166
|
|
|
128
167
|
确认后:
|
|
168
|
+
|
|
129
169
|
```bash
|
|
130
|
-
git
|
|
131
|
-
|
|
170
|
+
MAIN_ROOT=$(git -C "$(git rev-parse --git-common-dir)/.." rev-parse --show-toplevel)
|
|
171
|
+
cd "$MAIN_ROOT"
|
|
132
172
|
```
|
|
133
173
|
|
|
134
|
-
|
|
174
|
+
然后:清理 worktree(步骤 6),再强制删除分支:
|
|
175
|
+
|
|
176
|
+
```bash
|
|
177
|
+
git branch -D <feature-branch>
|
|
178
|
+
```
|
|
135
179
|
|
|
136
|
-
### 步骤
|
|
180
|
+
### 步骤 6:清理工作区
|
|
137
181
|
|
|
138
|
-
|
|
182
|
+
**只对选项 1 和 4 执行。** 选项 2 和 3 始终保留 worktree。
|
|
139
183
|
|
|
140
|
-
检查是否在工作树中:
|
|
141
184
|
```bash
|
|
142
|
-
|
|
185
|
+
GIT_DIR=$(cd "$(git rev-parse --git-dir)" 2>/dev/null && pwd -P)
|
|
186
|
+
GIT_COMMON=$(cd "$(git rev-parse --git-common-dir)" 2>/dev/null && pwd -P)
|
|
187
|
+
WORKTREE_PATH=$(git rev-parse --show-toplevel)
|
|
143
188
|
```
|
|
144
189
|
|
|
145
|
-
|
|
190
|
+
**如果 `GIT_DIR == GIT_COMMON`:** 普通仓库,无 worktree 可清理。结束。
|
|
191
|
+
|
|
192
|
+
**如果 worktree 路径在 `.worktrees/` 或 `worktrees/` 之下:** 这是 Superpowers 创建的 worktree —— 我们负责清理。
|
|
193
|
+
|
|
146
194
|
```bash
|
|
147
|
-
git
|
|
195
|
+
MAIN_ROOT=$(git -C "$(git rev-parse --git-common-dir)/.." rev-parse --show-toplevel)
|
|
196
|
+
cd "$MAIN_ROOT"
|
|
197
|
+
git worktree remove "$WORKTREE_PATH"
|
|
198
|
+
git worktree prune # 自愈:清理任何过期的注册记录
|
|
148
199
|
```
|
|
149
200
|
|
|
150
|
-
|
|
201
|
+
**否则:** 这个工作区由宿主环境(harness)管理。**不要**移除它。如果你的平台提供了工作区退出工具,用它。否则原样保留工作区。
|
|
151
202
|
|
|
152
203
|
## 快速参考
|
|
153
204
|
|
|
@@ -161,40 +212,69 @@ git worktree remove <worktree-path>
|
|
|
161
212
|
## 常见错误
|
|
162
213
|
|
|
163
214
|
**跳过测试验证**
|
|
215
|
+
|
|
164
216
|
- **问题:** 合并损坏的代码、创建失败的 PR
|
|
165
217
|
- **修复:** 在提供选项前始终验证测试
|
|
166
218
|
|
|
167
219
|
**开放式问题**
|
|
220
|
+
|
|
168
221
|
- **问题:** "接下来该做什么?" → 含糊不清
|
|
169
|
-
- **修复:** 准确展示 4
|
|
222
|
+
- **修复:** 准确展示 4 个结构化选项(分离 HEAD 时是 3 个)
|
|
223
|
+
|
|
224
|
+
**为选项 2 清理 worktree**
|
|
170
225
|
|
|
171
|
-
|
|
172
|
-
- **问题:** 在可能还需要工作树时就删除了(选项 2、3)
|
|
226
|
+
- **问题:** 删掉用户 PR 迭代还需要的 worktree
|
|
173
227
|
- **修复:** 只在选项 1 和 4 时清理
|
|
174
228
|
|
|
229
|
+
**先删分支再删 worktree**
|
|
230
|
+
|
|
231
|
+
- **问题:** `git branch -d` 失败,因为 worktree 还引用着该分支
|
|
232
|
+
- **修复:** 先合并,再删 worktree,最后删分支
|
|
233
|
+
|
|
234
|
+
**在 worktree 内部跑 `git worktree remove`**
|
|
235
|
+
|
|
236
|
+
- **问题:** 当 CWD 在被删除的 worktree 内时,命令静默失败
|
|
237
|
+
- **修复:** 跑 `git worktree remove` 前先 `cd` 到主仓库根目录
|
|
238
|
+
|
|
239
|
+
**清理 harness 拥有的 worktree**
|
|
240
|
+
|
|
241
|
+
- **问题:** 移除 harness 创建的 worktree 会造成幻影状态
|
|
242
|
+
- **修复:** 只清理 `.worktrees/` 或 `worktrees/` 下的 worktree
|
|
243
|
+
|
|
175
244
|
**丢弃时不确认**
|
|
245
|
+
|
|
176
246
|
- **问题:** 意外删除工作成果
|
|
177
|
-
- **修复:** 要求输入
|
|
247
|
+
- **修复:** 要求输入 'discard' 确认
|
|
178
248
|
|
|
179
249
|
## 红线
|
|
180
250
|
|
|
181
251
|
**绝不:**
|
|
252
|
+
|
|
182
253
|
- 在测试失败时继续
|
|
183
|
-
-
|
|
254
|
+
- 合并前不验证合并结果上的测试
|
|
184
255
|
- 不确认就删除工作成果
|
|
185
256
|
- 未经明确请求就强制推送
|
|
257
|
+
- 在确认合并成功之前移除 worktree
|
|
258
|
+
- 清理不是你创建的 worktree(按来源判断)
|
|
259
|
+
- 在 worktree 内部跑 `git worktree remove`
|
|
186
260
|
|
|
187
261
|
**始终:**
|
|
262
|
+
|
|
188
263
|
- 在提供选项前验证测试
|
|
189
|
-
-
|
|
264
|
+
- 展示菜单前检测环境
|
|
265
|
+
- 准确展示 4 个选项(分离 HEAD 时是 3 个)
|
|
190
266
|
- 选项 4 要求输入确认
|
|
191
|
-
- 只在选项 1 和 4
|
|
267
|
+
- 只在选项 1 和 4 时清理 worktree
|
|
268
|
+
- 移除 worktree 前 `cd` 到主仓库根目录
|
|
269
|
+
- 移除后跑 `git worktree prune`
|
|
192
270
|
|
|
193
271
|
## 集成
|
|
194
272
|
|
|
195
273
|
**被以下技能调用:**
|
|
274
|
+
|
|
196
275
|
- **subagent-driven-development**(步骤 7)- 所有任务完成后
|
|
197
276
|
- **executing-plans**(步骤 5)- 所有批次完成后
|
|
198
277
|
|
|
199
278
|
**配合使用:**
|
|
279
|
+
|
|
200
280
|
- **using-git-worktrees** - 清理由该技能创建的工作树
|