@ranger1/dx 0.1.42 → 0.1.44
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/@opencode/agents/__pycache__/pr_context.cpython-314.pyc +0 -0
- package/@opencode/agents/__pycache__/pr_precheck.cpython-314.pyc +0 -0
- package/@opencode/agents/pr_context.py +41 -6
- package/@opencode/agents/pr_precheck.py +3 -12
- package/@opencode/commands/doctor.md +177 -106
- package/@opencode/commands/git-commit-and-pr.md +4 -2
- package/@opencode/commands/oh_attach.json +9 -9
- package/@opencode/commands/opencode_attach.json +2 -2
- package/@opencode/commands/pr-review-loop.md +6 -0
- package/lib/worktree.js +1 -1
- package/package.json +1 -1
|
Binary file
|
|
Binary file
|
|
@@ -116,9 +116,37 @@ def _git_fetch_origin(ref):
|
|
|
116
116
|
subprocess.run(["git", "fetch", "origin", ref], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
|
|
117
117
|
|
|
118
118
|
|
|
119
|
-
def
|
|
120
|
-
|
|
121
|
-
|
|
119
|
+
def _gh_default_branch(owner_repo):
|
|
120
|
+
if not owner_repo:
|
|
121
|
+
return ""
|
|
122
|
+
rc, out, _ = _run_capture(
|
|
123
|
+
[
|
|
124
|
+
"gh",
|
|
125
|
+
"repo",
|
|
126
|
+
"view",
|
|
127
|
+
"--repo",
|
|
128
|
+
owner_repo,
|
|
129
|
+
"--json",
|
|
130
|
+
"defaultBranchRef",
|
|
131
|
+
"--jq",
|
|
132
|
+
".defaultBranchRef.name",
|
|
133
|
+
]
|
|
134
|
+
)
|
|
135
|
+
if rc != 0:
|
|
136
|
+
return ""
|
|
137
|
+
return (out or "").strip()
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
def _git_numstat(base_ref, base_oid):
|
|
141
|
+
# Prefer commit-oid diff when available; it's unambiguous for stacked PRs.
|
|
142
|
+
candidates = []
|
|
143
|
+
if base_oid:
|
|
144
|
+
candidates.append(f"{base_oid}...HEAD")
|
|
145
|
+
if base_ref:
|
|
146
|
+
candidates.append(f"origin/{base_ref}...HEAD")
|
|
147
|
+
candidates.append(f"{base_ref}...HEAD")
|
|
148
|
+
|
|
149
|
+
for lhs in candidates:
|
|
122
150
|
rc, out, _ = _run_capture(["git", "diff", "--numstat", lhs])
|
|
123
151
|
if rc == 0:
|
|
124
152
|
return out
|
|
@@ -205,15 +233,22 @@ def main(argv):
|
|
|
205
233
|
return 1
|
|
206
234
|
|
|
207
235
|
head_oid = (pr.get("headRefOid") or "").strip()
|
|
208
|
-
|
|
236
|
+
base_oid = (pr.get("baseRefOid") or "").strip()
|
|
237
|
+
base_ref = (pr.get("baseRefName") or "").strip()
|
|
238
|
+
if not base_ref:
|
|
239
|
+
base_ref = _gh_default_branch(owner_repo)
|
|
240
|
+
if not base_ref and not base_oid:
|
|
241
|
+
_json_out({"error": "PR_BASE_REF_NOT_FOUND"})
|
|
242
|
+
return 1
|
|
209
243
|
head_ref = (pr.get("headRefName") or "").strip()
|
|
210
244
|
url = (pr.get("url") or "").strip()
|
|
211
245
|
|
|
212
246
|
seed = f"{pr_number}:{round_num}:{head_oid}".encode("utf-8")
|
|
213
247
|
run_id = hashlib.sha1(seed).hexdigest()[:12]
|
|
214
248
|
|
|
215
|
-
|
|
216
|
-
|
|
249
|
+
if base_ref:
|
|
250
|
+
_git_fetch_origin(base_ref)
|
|
251
|
+
file_rows = _parse_numstat(_git_numstat(base_ref, base_oid))
|
|
217
252
|
|
|
218
253
|
labels = []
|
|
219
254
|
for l in (pr.get("labels") or []):
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
# - Verify GitHub auth (gh)
|
|
5
5
|
# - Read PR info (headRefName/baseRefName/mergeable)
|
|
6
6
|
# - Checkout PR branch (gh pr checkout) if needed
|
|
7
|
-
# - Fetch base branch (origin/<base
|
|
7
|
+
# - Fetch base branch (origin/<base>)
|
|
8
8
|
# - If mergeable == CONFLICTING: return {"error":"PR_MERGE_CONFLICTS_UNRESOLVED"}
|
|
9
9
|
# - Run dx cache clear
|
|
10
10
|
# - Run dx lint and dx build all concurrently
|
|
@@ -227,17 +227,8 @@ def main():
|
|
|
227
227
|
return 1
|
|
228
228
|
|
|
229
229
|
if run(["git", "fetch", "origin", base]) != 0:
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
if fallback == base:
|
|
233
|
-
continue
|
|
234
|
-
if run(["git", "fetch", "origin", fallback]) == 0:
|
|
235
|
-
base = fallback
|
|
236
|
-
ok = True
|
|
237
|
-
break
|
|
238
|
-
if not ok:
|
|
239
|
-
print(json.dumps({"error": "PR_BASE_REF_FETCH_FAILED"}))
|
|
240
|
-
return 1
|
|
230
|
+
print(json.dumps({"error": "PR_BASE_REF_FETCH_FAILED", "baseRefName": base}))
|
|
231
|
+
return 1
|
|
241
232
|
|
|
242
233
|
if mergeable == "CONFLICTING":
|
|
243
234
|
print(json.dumps({"error": "PR_MERGE_CONFLICTS_UNRESOLVED"}))
|
|
@@ -6,158 +6,229 @@ agent: build
|
|
|
6
6
|
|
|
7
7
|
---
|
|
8
8
|
|
|
9
|
-
## Step 0:
|
|
9
|
+
## Step 0: Bootstrap(dx + 模板 + pnpm)
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
目标:
|
|
12
12
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
```
|
|
13
|
+
- dx 安装/升级到最新
|
|
14
|
+
- 刷新 `~/.opencode/commands/*`(确保 `opencode_attach.py` 可用)
|
|
16
15
|
|
|
17
|
-
|
|
16
|
+
```bash
|
|
17
|
+
set -euo pipefail
|
|
18
18
|
|
|
19
|
-
|
|
19
|
+
# 必要前提:node + corepack(用于 pnpm)
|
|
20
|
+
if ! command -v node >/dev/null 2>&1; then
|
|
21
|
+
echo "ERROR: node NOT_FOUND (need Node.js >= 20)"
|
|
22
|
+
echo "macOS: brew install node"
|
|
23
|
+
echo "Debian/Ubuntu: curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash - && sudo apt-get install -y nodejs"
|
|
24
|
+
exit 1
|
|
25
|
+
fi
|
|
20
26
|
|
|
21
|
-
|
|
27
|
+
if ! command -v pnpm >/dev/null 2>&1; then
|
|
28
|
+
corepack enable >/dev/null 2>&1 || true
|
|
29
|
+
corepack prepare pnpm@latest --activate
|
|
30
|
+
fi
|
|
22
31
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
echo "=== CLI_VERSIONS ===";
|
|
26
|
-
echo "opencode:" && (which opencode && opencode --version 2>/dev/null || echo "NOT_FOUND");
|
|
27
|
-
echo "dx:" && (which dx && dx --version 2>/dev/null || echo "NOT_FOUND");
|
|
28
|
-
echo "agent-browser:" && (which agent-browser && agent-browser --version 2>/dev/null || echo "NOT_FOUND");
|
|
29
|
-
```
|
|
32
|
+
# 安装/升级 dx 到最新(幂等)
|
|
33
|
+
pnpm add -g @ranger1/dx@latest
|
|
30
34
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
35
|
+
# 备份后刷新模板(避免覆盖导致不可回退)
|
|
36
|
+
ts="$(date +%Y%m%d%H%M%S)"
|
|
37
|
+
if [ -d "$HOME/.opencode/commands" ]; then
|
|
38
|
+
cp -a "$HOME/.opencode/commands" "$HOME/.opencode/commands.bak.${ts}" 2>/dev/null || true
|
|
39
|
+
fi
|
|
40
|
+
if [ -d "$HOME/.opencode/agents" ]; then
|
|
41
|
+
cp -a "$HOME/.opencode/agents" "$HOME/.opencode/agents.bak.${ts}" 2>/dev/null || true
|
|
42
|
+
fi
|
|
36
43
|
|
|
37
|
-
|
|
38
|
-
# 批次 3: OpenCode 插件检测
|
|
39
|
-
# 注意:插件名可能带版本号(如 @1.3.0),使用模糊匹配
|
|
40
|
-
echo "=== OPENCODE_PLUGINS ===";
|
|
41
|
-
echo "oh-my-opencode:" && (opencode plugin list 2>/dev/null | grep -q 'oh-my-opencode' && echo "INSTALLED" || echo "NOT_INSTALLED");
|
|
42
|
-
echo "opencode-openai-codex-auth:" && (opencode plugin list 2>/dev/null | grep -q 'opencode-openai-codex-auth' && echo "INSTALLED" || echo "NOT_INSTALLED");
|
|
44
|
+
dx initial
|
|
43
45
|
```
|
|
44
46
|
|
|
45
|
-
|
|
46
|
-
# 批次 4: attach 配置(统一)
|
|
47
|
-
echo "=== OPENCODE_ATTACH ===";
|
|
48
|
-
echo "attach:" && (python3 ~/.opencode/commands/opencode_attach.py --dry-run >/dev/null 2>&1 && echo "READY" || echo "NOT_READY");
|
|
49
|
-
```
|
|
47
|
+
---
|
|
50
48
|
|
|
51
|
-
|
|
52
|
-
# 批次 5: Python 检测(python3 + python 软链接)
|
|
53
|
-
echo "=== PYTHON ===";
|
|
54
|
-
echo "python3:" && (which python3 && python3 --version 2>/dev/null || echo "NOT_FOUND");
|
|
55
|
-
echo "python:" && (which python && python --version 2>/dev/null || echo "NOT_FOUND");
|
|
56
|
-
```
|
|
49
|
+
## Step 1: 快速检测(单次 Bash)
|
|
57
50
|
|
|
58
|
-
|
|
51
|
+
目标:一次 Bash 输出完整状态表,减少 tool 调用与 token。
|
|
59
52
|
|
|
60
|
-
|
|
53
|
+
```bash
|
|
54
|
+
set -euo pipefail
|
|
55
|
+
|
|
56
|
+
os="$(uname -s 2>/dev/null || echo unknown)"
|
|
57
|
+
pm="none"
|
|
58
|
+
if command -v brew >/dev/null 2>&1; then pm="brew"; fi
|
|
59
|
+
if command -v apt-get >/dev/null 2>&1; then pm="apt"; fi
|
|
60
|
+
|
|
61
|
+
ver() {
|
|
62
|
+
# usage: ver <bin> <cmd>
|
|
63
|
+
b="$1"; shift
|
|
64
|
+
if command -v "$b" >/dev/null 2>&1; then
|
|
65
|
+
("$@" 2>/dev/null | head -n 1) || true
|
|
66
|
+
else
|
|
67
|
+
echo "NOT_FOUND"
|
|
68
|
+
fi
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
has_agents="NOT_FOUND"; [ -f AGENTS.md ] && has_agents="FOUND"
|
|
72
|
+
|
|
73
|
+
dx_v="$(ver dx dx --version)"
|
|
74
|
+
opencode_v="$(ver opencode opencode --version)"
|
|
75
|
+
rg_v="$(ver rg rg --version)"
|
|
76
|
+
agent_browser_v="$(ver agent-browser agent-browser --version)"
|
|
77
|
+
py3_v="$(ver python3 python3 --version)"
|
|
78
|
+
py_v="$(ver python python --version)"
|
|
79
|
+
|
|
80
|
+
attach_status="NOT_READY"
|
|
81
|
+
if command -v python3 >/dev/null 2>&1 && [ -f "$HOME/.opencode/commands/opencode_attach.py" ]; then
|
|
82
|
+
python3 "$HOME/.opencode/commands/opencode_attach.py" --dry-run >/dev/null 2>&1 && attach_status="READY" || true
|
|
83
|
+
fi
|
|
61
84
|
|
|
62
|
-
|
|
85
|
+
# 插件以“配置是否就绪”为准(真正安装由 opencode 启动时自动完成)
|
|
86
|
+
cfg_opencode="$HOME/.config/opencode/opencode.json"
|
|
87
|
+
plug_oh="NOT_CONFIGURED"
|
|
88
|
+
plug_codex="NOT_CONFIGURED"
|
|
89
|
+
plug_antigravity="NOT_CONFIGURED"
|
|
90
|
+
if [ -f "$cfg_opencode" ]; then
|
|
91
|
+
grep -q 'oh-my-opencode' "$cfg_opencode" && plug_oh="CONFIGURED" || true
|
|
92
|
+
grep -q 'opencode-openai-codex-auth' "$cfg_opencode" && plug_codex="CONFIGURED" || true
|
|
93
|
+
grep -q 'opencode-antigravity-auth' "$cfg_opencode" && plug_antigravity="CONFIGURED" || true
|
|
94
|
+
fi
|
|
63
95
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
96
|
+
echo "OS: ${os} | PM: ${pm}"
|
|
97
|
+
echo
|
|
98
|
+
printf '%-34s | %-12s | %s\n' "tool" "status" "version"
|
|
99
|
+
printf '%-34s | %-12s | %s\n' "opencode" "$( [ "$opencode_v" = NOT_FOUND ] && echo MISSING || echo OK )" "$opencode_v"
|
|
100
|
+
printf '%-34s | %-12s | %s\n' "dx" "$( [ "$dx_v" = NOT_FOUND ] && echo MISSING || echo OK )" "$dx_v"
|
|
101
|
+
printf '%-34s | %-12s | %s\n' "rg" "$( [ "$rg_v" = NOT_FOUND ] && echo MISSING || echo OK )" "$rg_v"
|
|
102
|
+
printf '%-34s | %-12s | %s\n' "agent-browser" "$( [ "$agent_browser_v" = NOT_FOUND ] && echo MISSING || echo OK )" "$agent_browser_v"
|
|
103
|
+
printf '%-34s | %-12s | %s\n' "python3" "$( [ "$py3_v" = NOT_FOUND ] && echo MISSING || echo OK )" "$py3_v"
|
|
104
|
+
printf '%-34s | %-12s | %s\n' "python (softlink)" "$( [ "$py_v" = NOT_FOUND ] && echo MISSING || echo OK )" "$py_v"
|
|
105
|
+
printf '%-34s | %-12s | %s\n' "AGENTS.md" "$has_agents" "-"
|
|
106
|
+
printf '%-34s | %-12s | %s\n' "attach (global config)" "$attach_status" "-"
|
|
107
|
+
printf '%-34s | %-12s | %s\n' "plugin: oh-my-opencode" "$plug_oh" "-"
|
|
108
|
+
printf '%-34s | %-12s | %s\n' "plugin: opencode-openai-codex-auth" "$plug_codex" "-"
|
|
109
|
+
printf '%-34s | %-12s | %s\n' "plugin: opencode-antigravity-auth" "$plug_antigravity" "-"
|
|
110
|
+
|
|
111
|
+
missing=0
|
|
112
|
+
for x in "$opencode_v" "$dx_v" "$rg_v" "$agent_browser_v" "$py3_v"; do
|
|
113
|
+
[ "$x" = NOT_FOUND ] && missing=1
|
|
114
|
+
done
|
|
115
|
+
[ "$attach_status" != READY ] && missing=1
|
|
116
|
+
for x in "$plug_oh" "$plug_codex" "$plug_antigravity"; do
|
|
117
|
+
[ "$x" != CONFIGURED ] && missing=1
|
|
118
|
+
done
|
|
119
|
+
|
|
120
|
+
echo
|
|
121
|
+
if [ "$missing" = 0 ]; then
|
|
122
|
+
echo "OK: all dependencies ready"
|
|
123
|
+
else
|
|
124
|
+
echo "NEED_FIX: missing or not-ready items detected"
|
|
125
|
+
fi
|
|
75
126
|
```
|
|
76
127
|
|
|
77
128
|
---
|
|
78
129
|
|
|
79
|
-
## Step
|
|
80
|
-
|
|
81
|
-
**如检测到任何缺失项,统一询问一次:**
|
|
82
|
-
|
|
83
|
-
`AskUserQuestion`: 检测到以下缺失项,是否自动安装/配置所有?
|
|
130
|
+
## Step 2: 只问一次(缺失/升级)
|
|
84
131
|
|
|
85
|
-
|
|
132
|
+
如果出现 `NEED_FIX`,只问一次:是否一键安装 + 升级到最新版本(包含插件配置 attach)。
|
|
86
133
|
|
|
87
|
-
|
|
134
|
+
`AskUserQuestion`: 检测到缺失/未就绪项,是否一键修复并升级到最新版本?
|
|
88
135
|
|
|
89
|
-
|
|
136
|
+
选项:
|
|
90
137
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
brew install opencode || npm install -g opencode
|
|
94
|
-
```
|
|
95
|
-
|
|
96
|
-
### 3.2 AGENTS.md 未找到
|
|
97
|
-
|
|
98
|
-
提示用户:
|
|
138
|
+
- 一键修复(Recommended)
|
|
139
|
+
- 跳过(只输出检测表)
|
|
99
140
|
|
|
100
|
-
|
|
101
|
-
- 建议创建或检查文件路径
|
|
141
|
+
---
|
|
102
142
|
|
|
103
|
-
|
|
143
|
+
## Step 3: 一键修复(安装 + 升级到最新)
|
|
104
144
|
|
|
105
|
-
|
|
145
|
+
确认后直接执行以下脚本(幂等;尽量走包管理器升级;插件用 attach 配置确保可自动安装/更新):
|
|
106
146
|
|
|
107
147
|
```bash
|
|
108
|
-
|
|
109
|
-
|
|
148
|
+
set -euo pipefail
|
|
149
|
+
|
|
150
|
+
os="$(uname -s 2>/dev/null || echo unknown)"
|
|
151
|
+
has_brew=0; command -v brew >/dev/null 2>&1 && has_brew=1
|
|
152
|
+
has_apt=0; command -v apt-get >/dev/null 2>&1 && has_apt=1
|
|
110
153
|
|
|
111
|
-
|
|
154
|
+
need_sudo=0
|
|
155
|
+
if [ "$has_apt" = 1 ] && command -v sudo >/dev/null 2>&1; then
|
|
156
|
+
need_sudo=1
|
|
157
|
+
fi
|
|
112
158
|
|
|
113
|
-
|
|
159
|
+
if ! command -v pnpm >/dev/null 2>&1; then
|
|
160
|
+
corepack enable >/dev/null 2>&1 || true
|
|
161
|
+
corepack prepare pnpm@latest --activate
|
|
162
|
+
fi
|
|
114
163
|
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
brew install python
|
|
118
|
-
```
|
|
164
|
+
# dx(始终升级到最新)
|
|
165
|
+
pnpm add -g @ranger1/dx@latest
|
|
119
166
|
|
|
120
|
-
|
|
167
|
+
if ! command -v dx >/dev/null 2>&1; then
|
|
168
|
+
echo "WARN: dx still NOT_FOUND (check PATH for pnpm global bin: pnpm bin -g)"
|
|
169
|
+
fi
|
|
121
170
|
|
|
122
|
-
|
|
171
|
+
# OpenCode 模板(确保 opencode_attach.py 存在)
|
|
172
|
+
if [ ! -f "$HOME/.opencode/commands/opencode_attach.py" ]; then
|
|
173
|
+
dx initial
|
|
174
|
+
fi
|
|
123
175
|
|
|
124
|
-
|
|
125
|
-
|
|
176
|
+
# opencode CLI
|
|
177
|
+
if [ "$os" = "Darwin" ] && [ "$has_brew" = 1 ]; then
|
|
178
|
+
brew update >/dev/null
|
|
179
|
+
brew tap anomalyco/tap >/dev/null 2>&1 || true
|
|
180
|
+
brew install anomalyco/tap/opencode >/dev/null 2>&1 || brew upgrade opencode >/dev/null 2>&1 || true
|
|
181
|
+
else
|
|
182
|
+
# 官方支持 npm/bun/pnpm;这里统一用 pnpm
|
|
183
|
+
pnpm add -g opencode-ai@latest
|
|
184
|
+
fi
|
|
126
185
|
|
|
127
|
-
if command -v
|
|
128
|
-
|
|
129
|
-
exit 0
|
|
186
|
+
if ! command -v opencode >/dev/null 2>&1; then
|
|
187
|
+
echo "WARN: opencode still NOT_FOUND (check PATH for pnpm global bin: pnpm bin -g)"
|
|
130
188
|
fi
|
|
131
189
|
|
|
132
|
-
|
|
133
|
-
if [
|
|
134
|
-
|
|
135
|
-
|
|
190
|
+
# ripgrep
|
|
191
|
+
if [ "$has_brew" = 1 ]; then
|
|
192
|
+
brew install ripgrep >/dev/null 2>&1 || brew upgrade ripgrep >/dev/null 2>&1 || true
|
|
193
|
+
elif [ "$has_apt" = 1 ] && [ "$need_sudo" = 1 ]; then
|
|
194
|
+
sudo apt-get update -y >/dev/null
|
|
195
|
+
sudo apt-get install -y ripgrep
|
|
196
|
+
else
|
|
197
|
+
echo "WARN: no brew/apt-get; skip ripgrep auto-install"
|
|
136
198
|
fi
|
|
137
199
|
|
|
138
|
-
|
|
139
|
-
if [
|
|
140
|
-
|
|
141
|
-
|
|
200
|
+
# python3 (+ python 软链接尽量走系统包)
|
|
201
|
+
if [ "$has_brew" = 1 ]; then
|
|
202
|
+
brew install python >/dev/null 2>&1 || brew upgrade python >/dev/null 2>&1 || true
|
|
203
|
+
elif [ "$has_apt" = 1 ] && [ "$need_sudo" = 1 ]; then
|
|
204
|
+
sudo apt-get update -y >/dev/null
|
|
205
|
+
sudo apt-get install -y python3 python3-venv python3-pip python-is-python3
|
|
142
206
|
else
|
|
143
|
-
|
|
144
|
-
echo "linked: $HOME/.local/bin/python -> $PY3"
|
|
145
|
-
echo "NOTE: ensure $HOME/.local/bin is in PATH"
|
|
207
|
+
echo "WARN: no brew/apt-get; skip python auto-install"
|
|
146
208
|
fi
|
|
147
209
|
|
|
148
|
-
|
|
149
|
-
|
|
210
|
+
# agent-browser(安装/升级 + 安装 Chromium)
|
|
211
|
+
if [ "$os" = "Darwin" ] && [ "$has_brew" = 1 ]; then
|
|
212
|
+
brew install agent-browser >/dev/null 2>&1 || brew upgrade agent-browser >/dev/null 2>&1 || true
|
|
213
|
+
else
|
|
214
|
+
pnpm add -g agent-browser@latest
|
|
215
|
+
fi
|
|
150
216
|
|
|
151
|
-
|
|
217
|
+
if command -v agent-browser >/dev/null 2>&1; then
|
|
218
|
+
agent-browser install >/dev/null 2>&1 || agent-browser install --with-deps
|
|
219
|
+
fi
|
|
152
220
|
|
|
153
|
-
|
|
221
|
+
# attach(写入 ~/.config/opencode/*.json;自动备份 .bak.*)
|
|
222
|
+
if command -v python3 >/dev/null 2>&1 && [ -f "$HOME/.opencode/commands/opencode_attach.py" ]; then
|
|
223
|
+
python3 "$HOME/.opencode/commands/opencode_attach.py"
|
|
224
|
+
else
|
|
225
|
+
echo "ERROR: python3/opencode_attach.py NOT_READY"
|
|
226
|
+
exit 1
|
|
227
|
+
fi
|
|
154
228
|
|
|
155
|
-
|
|
156
|
-
python3 ~/.opencode/commands/opencode_attach.py
|
|
229
|
+
echo "DONE"
|
|
157
230
|
```
|
|
158
231
|
|
|
159
|
-
|
|
160
|
-
|
|
161
232
|
---
|
|
162
233
|
|
|
163
234
|
## 输出格式
|
|
@@ -175,4 +246,4 @@ python3 ~/.opencode/commands/opencode_attach.py
|
|
|
175
246
|
```
|
|
176
247
|
|
|
177
248
|
**修复完成后:**
|
|
178
|
-
|
|
249
|
+
重复执行 Step 1,输出最终状态表格,确认所有项目均为 OK/READY/CONFIGURED。
|
|
@@ -223,8 +223,10 @@ git push -u origin HEAD
|
|
|
223
223
|
#### 4.2 分析变更
|
|
224
224
|
|
|
225
225
|
```bash
|
|
226
|
-
|
|
227
|
-
git
|
|
226
|
+
# 优先使用 origin/HEAD(远端默认分支),避免硬编码 main/master。
|
|
227
|
+
# 如需指定基准分支,使用:/git-commit-and-pr --pr --base <BRANCH>
|
|
228
|
+
git log origin/HEAD..HEAD --oneline
|
|
229
|
+
git diff origin/HEAD...HEAD --stat
|
|
228
230
|
```
|
|
229
231
|
|
|
230
232
|
#### 4.3 创建 PR
|
|
@@ -7,18 +7,18 @@
|
|
|
7
7
|
},
|
|
8
8
|
"agents": {
|
|
9
9
|
"sisyphus": {
|
|
10
|
-
"model": "openai/gpt-5.
|
|
10
|
+
"model": "openai/gpt-5.3-codex",
|
|
11
11
|
"variant": "none"
|
|
12
12
|
},
|
|
13
13
|
"oracle": {
|
|
14
|
-
"model": "openai/gpt-5.
|
|
14
|
+
"model": "openai/gpt-5.3-codex",
|
|
15
15
|
"variant": "high"
|
|
16
16
|
},
|
|
17
17
|
"librarian": {
|
|
18
|
-
"model": "
|
|
18
|
+
"model": "openai/gpt-5.1-codex-mini"
|
|
19
19
|
},
|
|
20
20
|
"explore": {
|
|
21
|
-
"model": "
|
|
21
|
+
"model": "openai/gpt-5.1-codex-mini"
|
|
22
22
|
},
|
|
23
23
|
"multimodal-looker": {
|
|
24
24
|
"model": "github-copilot/gemini-3-flash-preview"
|
|
@@ -36,10 +36,10 @@
|
|
|
36
36
|
"variant": "medium"
|
|
37
37
|
},
|
|
38
38
|
"atlas": {
|
|
39
|
-
"model": "openai/gpt-5.
|
|
39
|
+
"model": "openai/gpt-5.3-codex"
|
|
40
40
|
},
|
|
41
41
|
"codex-reviewer": {
|
|
42
|
-
"model": "openai/gpt-5.
|
|
42
|
+
"model": "openai/gpt-5.3-codex",
|
|
43
43
|
"variant": "xhigh",
|
|
44
44
|
"temperature": 0.1
|
|
45
45
|
},
|
|
@@ -64,7 +64,7 @@
|
|
|
64
64
|
"variant": "high"
|
|
65
65
|
},
|
|
66
66
|
"ultrabrain": {
|
|
67
|
-
"model": "openai/gpt-5.
|
|
67
|
+
"model": "openai/gpt-5.3-codex",
|
|
68
68
|
"variant": "xhigh"
|
|
69
69
|
},
|
|
70
70
|
"artistry": {
|
|
@@ -72,7 +72,7 @@
|
|
|
72
72
|
"variant": "max"
|
|
73
73
|
},
|
|
74
74
|
"quick": {
|
|
75
|
-
"model": "
|
|
75
|
+
"model": "openai/gpt-5.1-codex-mini"
|
|
76
76
|
},
|
|
77
77
|
"middle": {
|
|
78
78
|
"model": "github-copilot/claude-sonnet-4.5"
|
|
@@ -82,7 +82,7 @@
|
|
|
82
82
|
"variant": "medium"
|
|
83
83
|
},
|
|
84
84
|
"unspecified-high": {
|
|
85
|
-
"model": "openai/gpt-5.
|
|
85
|
+
"model": "openai/gpt-5.3-codex",
|
|
86
86
|
"variant": "medium"
|
|
87
87
|
},
|
|
88
88
|
"writing": {
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
],
|
|
11
11
|
"agent": {
|
|
12
12
|
"quick": {
|
|
13
|
-
"model": "
|
|
13
|
+
"model": "openai/gpt-5.1-codex-mini"
|
|
14
14
|
},
|
|
15
15
|
"middle": {
|
|
16
16
|
"model": "github-copilot/claude-sonnet-4.5"
|
|
@@ -22,5 +22,5 @@
|
|
|
22
22
|
"*.env.*": "allow"
|
|
23
23
|
}
|
|
24
24
|
},
|
|
25
|
-
"model": "openai/gpt-5.
|
|
25
|
+
"model": "openai/gpt-5.3-codex"
|
|
26
26
|
}
|
|
@@ -6,6 +6,12 @@ agent: sisyphus
|
|
|
6
6
|
|
|
7
7
|
# PR Review Loop
|
|
8
8
|
|
|
9
|
+
## Stacked PR / PR -> PR(重要)
|
|
10
|
+
|
|
11
|
+
- 本流程的 diff 基准来自 GitHub PR 元数据的 `baseRefName`(不是硬编码 main/master),因此天然支持“PR 合并到另一个 PR 分支”的 stacked PR。
|
|
12
|
+
- 当 `baseRefName` 缺失时:会回退到仓库默认分支(`defaultBranchRef.name`)。
|
|
13
|
+
- 当 base 分支 fetch 失败时:会直接报错终止(不再静默回退到 main/master),避免 review/changed-files 基准悄悄跑偏。
|
|
14
|
+
|
|
9
15
|
## 输入
|
|
10
16
|
|
|
11
17
|
- `{{PR_NUMBER}}`
|
package/lib/worktree.js
CHANGED
|
@@ -685,7 +685,7 @@ class WorktreeManager {
|
|
|
685
685
|
|
|
686
686
|
// 检查未推送的提交
|
|
687
687
|
const unpushed = execSync(
|
|
688
|
-
`git log origin/${branchName}..${branchName} --oneline 2>/dev/null || git log origin/
|
|
688
|
+
`git log origin/${branchName}..${branchName} --oneline 2>/dev/null || git log origin/HEAD..${branchName} --oneline`,
|
|
689
689
|
).toString()
|
|
690
690
|
if (unpushed.trim()) {
|
|
691
691
|
hasUnpushedCommits = true
|