@ranger1/dx 0.1.77 → 0.1.78
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/README.md +92 -31
- package/bin/dx.js +3 -3
- package/lib/cli/commands/stack.js +198 -237
- package/lib/cli/commands/start.js +0 -6
- package/lib/cli/dx-cli.js +10 -1
- package/lib/cli/help.js +4 -4
- package/lib/{opencode-initial.js → codex-initial.js} +3 -82
- package/package.json +1 -2
- package/@opencode/agents/__pycache__/gh_review_harvest.cpython-314.pyc +0 -0
- 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/__pycache__/pr_review_aggregate.cpython-314.pyc +0 -0
- package/@opencode/agents/__pycache__/test_pr_review_aggregate.cpython-314-pytest-9.0.2.pyc +0 -0
- package/@opencode/agents/__pycache__/test_pr_review_aggregate.cpython-314.pyc +0 -0
- package/@opencode/agents/claude-reviewer.md +0 -82
- package/@opencode/agents/codex-reviewer.md +0 -83
- package/@opencode/agents/gemini-reviewer.md +0 -82
- package/@opencode/agents/gh-thread-reviewer.md +0 -122
- package/@opencode/agents/gh_review_harvest.py +0 -292
- package/@opencode/agents/pr-context.md +0 -82
- package/@opencode/agents/pr-fix.md +0 -243
- package/@opencode/agents/pr-precheck.md +0 -89
- package/@opencode/agents/pr-review-aggregate.md +0 -151
- package/@opencode/agents/pr_context.py +0 -351
- package/@opencode/agents/pr_precheck.py +0 -505
- package/@opencode/agents/pr_review_aggregate.py +0 -868
- package/@opencode/agents/test_pr_review_aggregate.py +0 -701
- package/@opencode/commands/doctor.md +0 -271
- package/@opencode/commands/git-commit-and-pr.md +0 -282
- package/@opencode/commands/git-release.md +0 -642
- package/@opencode/commands/oh_attach.json +0 -92
- package/@opencode/commands/opencode_attach.json +0 -29
- package/@opencode/commands/opencode_attach.py +0 -142
- package/@opencode/commands/pr-review-loop.md +0 -211
|
@@ -4,41 +4,6 @@ import os from 'node:os'
|
|
|
4
4
|
|
|
5
5
|
import { logger } from './logger.js'
|
|
6
6
|
|
|
7
|
-
async function collectTemplateFiles(dir) {
|
|
8
|
-
const out = []
|
|
9
|
-
|
|
10
|
-
async function walk(current) {
|
|
11
|
-
let entries
|
|
12
|
-
try {
|
|
13
|
-
entries = await fs.readdir(current, { withFileTypes: true })
|
|
14
|
-
} catch {
|
|
15
|
-
return
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
for (const entry of entries) {
|
|
19
|
-
const full = join(current, entry.name)
|
|
20
|
-
if (entry.isDirectory()) {
|
|
21
|
-
// 跳过 __pycache__ 和其他缓存目录
|
|
22
|
-
if (entry.name === '__pycache__' || entry.name === '.pytest_cache') {
|
|
23
|
-
continue
|
|
24
|
-
}
|
|
25
|
-
await walk(full)
|
|
26
|
-
continue
|
|
27
|
-
}
|
|
28
|
-
if (!entry.isFile()) continue
|
|
29
|
-
const lowerName = entry.name.toLowerCase()
|
|
30
|
-
// 拷贝 .md / .py / .json 文件
|
|
31
|
-
if (!lowerName.endsWith('.md') && !lowerName.endsWith('.py') && !lowerName.endsWith('.json')) continue
|
|
32
|
-
// 跳过 Python 编译文件
|
|
33
|
-
if (lowerName.endsWith('.pyc') || lowerName.endsWith('.pyo') || lowerName.endsWith('.pyd')) continue
|
|
34
|
-
out.push(full)
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
await walk(dir)
|
|
39
|
-
return out
|
|
40
|
-
}
|
|
41
|
-
|
|
42
7
|
async function collectAllFiles(dir) {
|
|
43
8
|
const out = []
|
|
44
9
|
|
|
@@ -146,70 +111,26 @@ async function copySkillsDirectories({ srcSkillsDir, dstSkillsDir }) {
|
|
|
146
111
|
return { copiedDirs, copiedFiles }
|
|
147
112
|
}
|
|
148
113
|
|
|
149
|
-
function
|
|
150
|
-
return [join(packageRoot, '@opencode')]
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
export async function runOpenCodeInitial(options = {}) {
|
|
114
|
+
export async function runCodexInitial(options = {}) {
|
|
154
115
|
const packageRoot = options.packageRoot
|
|
155
|
-
if (!packageRoot) throw new Error('
|
|
116
|
+
if (!packageRoot) throw new Error('runCodexInitial: 缺少 packageRoot')
|
|
156
117
|
|
|
157
118
|
const homeDir = options.homeDir || os.homedir()
|
|
158
|
-
const dstRoot = join(homeDir, '.opencode')
|
|
159
|
-
|
|
160
|
-
const roots = resolveTemplateRoot(packageRoot)
|
|
161
|
-
const existingRoot = await (async () => {
|
|
162
|
-
for (const p of roots) {
|
|
163
|
-
try {
|
|
164
|
-
const st = await fs.stat(p)
|
|
165
|
-
if (st.isDirectory()) return p
|
|
166
|
-
} catch {
|
|
167
|
-
// ignore
|
|
168
|
-
}
|
|
169
|
-
}
|
|
170
|
-
return null
|
|
171
|
-
})()
|
|
172
|
-
|
|
173
|
-
if (!existingRoot) {
|
|
174
|
-
const tried = roots.map(p => `- ${p}`).join('\n')
|
|
175
|
-
throw new Error(`未找到 opencode 模板目录,已尝试路径:\n${tried}`)
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
const srcOpenCodeAgents = join(existingRoot, 'agents')
|
|
179
|
-
const srcCommands = join(existingRoot, 'commands')
|
|
180
|
-
const dstOpenCodeAgents = join(dstRoot, 'agents')
|
|
181
|
-
const dstCommands = join(dstRoot, 'commands')
|
|
182
119
|
const srcSkills = join(packageRoot, 'codex', 'skills')
|
|
183
120
|
const dstSkills = join(homeDir, '.codex', 'skills')
|
|
184
121
|
const srcCodexAgents = join(packageRoot, 'codex', 'agents')
|
|
185
122
|
const dstCodexAgents = join(homeDir, '.codex', 'agents')
|
|
186
123
|
|
|
187
|
-
await assertDirExists(srcOpenCodeAgents, '模板目录 agents')
|
|
188
|
-
await assertDirExists(srcCommands, '模板目录 commands')
|
|
189
124
|
await assertDirExists(srcSkills, '模板目录 codex/skills')
|
|
190
125
|
await assertDirExists(srcCodexAgents, '模板目录 codex/agents')
|
|
191
126
|
|
|
192
|
-
await ensureDir(dstOpenCodeAgents)
|
|
193
|
-
await ensureDir(dstCommands)
|
|
194
127
|
await ensureDir(dstSkills)
|
|
195
128
|
await ensureDir(dstCodexAgents)
|
|
196
129
|
|
|
197
|
-
const agentsStats = await copyTemplateTree({ srcDir: srcOpenCodeAgents, dstDir: dstOpenCodeAgents })
|
|
198
|
-
const commandsStats = await copyTemplateTree({ srcDir: srcCommands, dstDir: dstCommands })
|
|
199
130
|
const skillsStats = await copySkillsDirectories({ srcSkillsDir: srcSkills, dstSkillsDir: dstSkills })
|
|
200
131
|
const codexAgentsStats = await copyDirMerge({ srcDir: srcCodexAgents, dstDir: dstCodexAgents })
|
|
201
132
|
|
|
202
|
-
logger.success(`已初始化
|
|
203
|
-
logger.info(
|
|
204
|
-
`agents: ${agentsStats.md} 个 .md 文件` +
|
|
205
|
-
`${agentsStats.py > 0 ? ` + ${agentsStats.py} 个 .py 文件` : ''}` +
|
|
206
|
-
`${agentsStats.json > 0 ? ` + ${agentsStats.json} 个 .json 文件` : ''}`
|
|
207
|
-
)
|
|
208
|
-
logger.info(
|
|
209
|
-
`commands: ${commandsStats.md} 个 .md 文件` +
|
|
210
|
-
`${commandsStats.py > 0 ? ` + ${commandsStats.py} 个 .py 文件` : ''}` +
|
|
211
|
-
`${commandsStats.json > 0 ? ` + ${commandsStats.json} 个 .json 文件` : ''}`
|
|
212
|
-
)
|
|
133
|
+
logger.success(`已初始化 Codex 模板到: ${join(homeDir, '.codex')}`)
|
|
213
134
|
logger.info(`skills: ${skillsStats.copiedDirs} 个目录,覆盖复制 ${skillsStats.copiedFiles} 个文件 -> ${dstSkills}`)
|
|
214
135
|
logger.info(`codex agents: 覆盖复制 ${codexAgentsStats.fileCount} 个文件 -> ${dstCodexAgents}`)
|
|
215
136
|
}
|
package/package.json
CHANGED
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -1,82 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
description: review (Claude)
|
|
3
|
-
mode: subagent
|
|
4
|
-
model: openai/gpt-5.2
|
|
5
|
-
tools:
|
|
6
|
-
write: true
|
|
7
|
-
edit: false
|
|
8
|
-
bash: true
|
|
9
|
-
---
|
|
10
|
-
|
|
11
|
-
# PR Reviewer (Claude)
|
|
12
|
-
|
|
13
|
-
## 输入(prompt 必须包含)
|
|
14
|
-
|
|
15
|
-
- `PR #<number>`
|
|
16
|
-
- `round: <number>`
|
|
17
|
-
- `runId: <string>`(必须透传,格式 `<PR>-<ROUND>-<HEAD_SHORT>`,禁止自行生成)
|
|
18
|
-
- `contextFile: <filename>`
|
|
19
|
-
|
|
20
|
-
## 输出(强制)
|
|
21
|
-
|
|
22
|
-
只输出一行:
|
|
23
|
-
|
|
24
|
-
`reviewFile: ./.cache/<file>.md`
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
## 规则
|
|
28
|
-
|
|
29
|
-
- 默认已在 PR head 分支(可直接读工作区代码)
|
|
30
|
-
- 可用 `git`/`gh` 只读命令获取 diff/上下文
|
|
31
|
-
- 写入 reviewFile:`./.cache/review-CLD-pr<PR_NUMBER>-r<ROUND>-<RUN_ID>.md`
|
|
32
|
-
- findings id 必须以 `CLD-` 开头
|
|
33
|
-
|
|
34
|
-
## 决策日志约束(强制)
|
|
35
|
-
|
|
36
|
-
如果 prompt 中提供了 `decisionLogFile`,必须先读取并遵守以下规则:
|
|
37
|
-
|
|
38
|
-
1. **已修复问题**:不再提出本质相同的问题
|
|
39
|
-
2. **已拒绝问题**:
|
|
40
|
-
- 若你的发现 priority 比原问题高 ≥2 级(如 P3→P1, P2→P0),可以升级质疑
|
|
41
|
-
- 否则不再提出
|
|
42
|
-
|
|
43
|
-
4. **文件一致性**:
|
|
44
|
-
- 匹配 Decision Log 时,**必须检查 `file` 字段是否与当前 finding 的文件一致**。
|
|
45
|
-
- 若 decision-log 中的 `file` 与当前文件不一致(包括重命名、移动、删除),则**视为不同问题**,不进行 essence 匹配(即作为新问题处理)。
|
|
46
|
-
- 若 decision-log 条目缺少 `file` 字段,也视为不匹配。
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
### 禁止事项
|
|
50
|
-
- ⛔ 不质疑已修复问题的实现方式(除非发现修复引入了新 bug)
|
|
51
|
-
- ⛔ 不重复提出已拒绝问题(除非满足升级质疑条件)
|
|
52
|
-
|
|
53
|
-
## Cache 约定(强制)
|
|
54
|
-
|
|
55
|
-
- 缓存目录固定为 `./.cache/`;交接一律传 `./.cache/<file>`(repo 相对路径),禁止 basename-only(如 `foo.md`)。
|
|
56
|
-
|
|
57
|
-
## reviewFile 格式(强制)
|
|
58
|
-
|
|
59
|
-
```md
|
|
60
|
-
# Review (CLD)
|
|
61
|
-
|
|
62
|
-
PR: <PR_NUMBER>
|
|
63
|
-
Round: <ROUND>
|
|
64
|
-
|
|
65
|
-
## Summary
|
|
66
|
-
|
|
67
|
-
P0: <n>
|
|
68
|
-
P1: <n>
|
|
69
|
-
P2: <n>
|
|
70
|
-
P3: <n>
|
|
71
|
-
|
|
72
|
-
## Findings
|
|
73
|
-
|
|
74
|
-
- id: CLD-001
|
|
75
|
-
priority: P1
|
|
76
|
-
category: quality|performance|security|architecture
|
|
77
|
-
file: <path>
|
|
78
|
-
line: <number|null>
|
|
79
|
-
title: <short>
|
|
80
|
-
description: <text>
|
|
81
|
-
suggestion: <text>
|
|
82
|
-
```
|
|
@@ -1,83 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
description: review (Codex)
|
|
3
|
-
mode: subagent
|
|
4
|
-
model: openai/gpt-5.3-codex
|
|
5
|
-
temperature: 0.1
|
|
6
|
-
tools:
|
|
7
|
-
write: true
|
|
8
|
-
edit: false
|
|
9
|
-
bash: true
|
|
10
|
-
---
|
|
11
|
-
|
|
12
|
-
# PR Reviewer (Codex)
|
|
13
|
-
|
|
14
|
-
## 输入(prompt 必须包含)
|
|
15
|
-
|
|
16
|
-
- `PR #<number>`
|
|
17
|
-
- `round: <number>`
|
|
18
|
-
- `runId: <string>`(必须透传,格式 `<PR>-<ROUND>-<HEAD_SHORT>`,禁止自行生成)
|
|
19
|
-
- `contextFile: <filename>`
|
|
20
|
-
|
|
21
|
-
## 输出(强制)
|
|
22
|
-
|
|
23
|
-
只输出一行:
|
|
24
|
-
|
|
25
|
-
`reviewFile: ./.cache/<file>.md`
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
## 规则
|
|
29
|
-
|
|
30
|
-
- 默认已在 PR head 分支(可直接读工作区代码)
|
|
31
|
-
- 可用 `git`/`gh` 只读命令获取 diff/上下文
|
|
32
|
-
- 写入 reviewFile:`./.cache/review-CDX-pr<PR_NUMBER>-r<ROUND>-<RUN_ID>.md`
|
|
33
|
-
- findings id 必须以 `CDX-` 开头
|
|
34
|
-
|
|
35
|
-
## 决策日志约束(强制)
|
|
36
|
-
|
|
37
|
-
如果 prompt 中提供了 `decisionLogFile`,必须先读取并遵守以下规则:
|
|
38
|
-
|
|
39
|
-
1. **已修复问题**:不再提出本质相同的问题
|
|
40
|
-
2. **已拒绝问题**:
|
|
41
|
-
- 若你的发现 priority 比原问题高 ≥2 级(如 P3→P1, P2→P0),可以升级质疑
|
|
42
|
-
- 否则不再提出
|
|
43
|
-
|
|
44
|
-
4. **文件一致性**:
|
|
45
|
-
- 匹配 Decision Log 时,**必须检查 `file` 字段是否与当前 finding 的文件一致**。
|
|
46
|
-
- 若 decision-log 中的 `file` 与当前文件不一致(包括重命名、移动、删除),则**视为不同问题**,不进行 essence 匹配(即作为新问题处理)。
|
|
47
|
-
- 若 decision-log 条目缺少 `file` 字段,也视为不匹配。
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
### 禁止事项
|
|
51
|
-
- ⛔ 不质疑已修复问题的实现方式(除非发现修复引入了新 bug)
|
|
52
|
-
- ⛔ 不重复提出已拒绝问题(除非满足升级质疑条件)
|
|
53
|
-
|
|
54
|
-
## Cache 约定(强制)
|
|
55
|
-
|
|
56
|
-
- 缓存目录固定为 `./.cache/`;交接一律传 `./.cache/<file>`(repo 相对路径),禁止 basename-only(如 `foo.md`)。
|
|
57
|
-
|
|
58
|
-
## reviewFile 格式(强制)
|
|
59
|
-
|
|
60
|
-
```md
|
|
61
|
-
# Review (CDX)
|
|
62
|
-
|
|
63
|
-
PR: <PR_NUMBER>
|
|
64
|
-
Round: <ROUND>
|
|
65
|
-
|
|
66
|
-
## Summary
|
|
67
|
-
|
|
68
|
-
P0: <n>
|
|
69
|
-
P1: <n>
|
|
70
|
-
P2: <n>
|
|
71
|
-
P3: <n>
|
|
72
|
-
|
|
73
|
-
## Findings
|
|
74
|
-
|
|
75
|
-
- id: CDX-001
|
|
76
|
-
priority: P1
|
|
77
|
-
category: quality|performance|security|architecture
|
|
78
|
-
file: <path>
|
|
79
|
-
line: <number|null>
|
|
80
|
-
title: <short>
|
|
81
|
-
description: <text>
|
|
82
|
-
suggestion: <text>
|
|
83
|
-
```
|
|
@@ -1,82 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
description: review (Gemini)
|
|
3
|
-
mode: subagent
|
|
4
|
-
model: openai/gpt-5.1-codex
|
|
5
|
-
tools:
|
|
6
|
-
write: true
|
|
7
|
-
edit: false
|
|
8
|
-
bash: true
|
|
9
|
-
---
|
|
10
|
-
|
|
11
|
-
# PR Reviewer (Gemini)
|
|
12
|
-
|
|
13
|
-
## 输入(prompt 必须包含)
|
|
14
|
-
|
|
15
|
-
- `PR #<number>`
|
|
16
|
-
- `round: <number>`
|
|
17
|
-
- `runId: <string>`(必须透传,格式 `<PR>-<ROUND>-<HEAD_SHORT>`,禁止自行生成)
|
|
18
|
-
- `contextFile: <filename>`
|
|
19
|
-
|
|
20
|
-
## 输出(强制)
|
|
21
|
-
|
|
22
|
-
只输出一行:
|
|
23
|
-
|
|
24
|
-
`reviewFile: ./.cache/<file>.md`
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
## 规则
|
|
28
|
-
|
|
29
|
-
- 默认已在 PR head 分支(可直接读工作区代码)
|
|
30
|
-
- 可用 `git`/`gh` 只读命令获取 diff/上下文
|
|
31
|
-
- 写入 reviewFile:`./.cache/review-GMN-pr<PR_NUMBER>-r<ROUND>-<RUN_ID>.md`
|
|
32
|
-
- findings id 必须以 `GMN-` 开头
|
|
33
|
-
|
|
34
|
-
## 决策日志约束(强制)
|
|
35
|
-
|
|
36
|
-
如果 prompt 中提供了 `decisionLogFile`,必须先读取并遵守以下规则:
|
|
37
|
-
|
|
38
|
-
1. **已修复问题**:不再提出本质相同的问题
|
|
39
|
-
2. **已拒绝问题**:
|
|
40
|
-
- 若你的发现 priority 比原问题高 ≥2 级(如 P3→P1, P2→P0),可以升级质疑
|
|
41
|
-
- 否则不再提出
|
|
42
|
-
|
|
43
|
-
4. **文件一致性**:
|
|
44
|
-
- 匹配 Decision Log 时,**必须检查 `file` 字段是否与当前 finding 的文件一致**。
|
|
45
|
-
- 若 decision-log 中的 `file` 与当前文件不一致(包括重命名、移动、删除),则**视为不同问题**,不进行 essence 匹配(即作为新问题处理)。
|
|
46
|
-
- 若 decision-log 条目缺少 `file` 字段,也视为不匹配。
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
### 禁止事项
|
|
50
|
-
- ⛔ 不质疑已修复问题的实现方式(除非发现修复引入了新 bug)
|
|
51
|
-
- ⛔ 不重复提出已拒绝问题(除非满足升级质疑条件)
|
|
52
|
-
|
|
53
|
-
## Cache 约定(强制)
|
|
54
|
-
|
|
55
|
-
- 缓存目录固定为 `./.cache/`;交接一律传 `./.cache/<file>`(repo 相对路径),禁止 basename-only(如 `foo.md`)。
|
|
56
|
-
|
|
57
|
-
## reviewFile 格式(强制)
|
|
58
|
-
|
|
59
|
-
```md
|
|
60
|
-
# Review (GMN)
|
|
61
|
-
|
|
62
|
-
PR: <PR_NUMBER>
|
|
63
|
-
Round: <ROUND>
|
|
64
|
-
|
|
65
|
-
## Summary
|
|
66
|
-
|
|
67
|
-
P0: <n>
|
|
68
|
-
P1: <n>
|
|
69
|
-
P2: <n>
|
|
70
|
-
P3: <n>
|
|
71
|
-
|
|
72
|
-
## Findings
|
|
73
|
-
|
|
74
|
-
- id: GMN-001
|
|
75
|
-
priority: P1
|
|
76
|
-
category: quality|performance|security|architecture
|
|
77
|
-
file: <path>
|
|
78
|
-
line: <number|null>
|
|
79
|
-
title: <short>
|
|
80
|
-
description: <text>
|
|
81
|
-
suggestion: <text>
|
|
82
|
-
```
|
|
@@ -1,122 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
description: review (GitHub Harvest)
|
|
3
|
-
mode: subagent
|
|
4
|
-
model: openai/gpt-5.3-codex
|
|
5
|
-
temperature: 0.2
|
|
6
|
-
tools:
|
|
7
|
-
write: true
|
|
8
|
-
edit: false
|
|
9
|
-
bash: true
|
|
10
|
-
---
|
|
11
|
-
|
|
12
|
-
# PR Reviewer (GitHub Harvest)
|
|
13
|
-
|
|
14
|
-
Harvest all GitHub PR review feedback (humans + bots, including Copilot) and normalize into a standard `reviewFile`.
|
|
15
|
-
|
|
16
|
-
## 输入(prompt 必须包含)
|
|
17
|
-
|
|
18
|
-
- `PR #<number>`
|
|
19
|
-
- `round: <number>`
|
|
20
|
-
- `runId: <string>`(必须透传,格式 `<PR>-<ROUND>-<HEAD_SHORT>`,禁止自行生成)
|
|
21
|
-
- `contextFile: <filename>`
|
|
22
|
-
|
|
23
|
-
## Cache 约定(强制)
|
|
24
|
-
|
|
25
|
-
- 缓存目录固定为 `./.cache/`;交接一律传 `./.cache/<file>`(repo 相对路径),禁止 basename-only(如 `foo.md`)。
|
|
26
|
-
|
|
27
|
-
## 输出(强制)
|
|
28
|
-
|
|
29
|
-
只输出一行:
|
|
30
|
-
|
|
31
|
-
`reviewFile: ./.cache/<file>.md`
|
|
32
|
-
|
|
33
|
-
## reviewFile 格式(强制)
|
|
34
|
-
|
|
35
|
-
```md
|
|
36
|
-
# Review (GHR)
|
|
37
|
-
|
|
38
|
-
PR: <PR_NUMBER>
|
|
39
|
-
Round: <ROUND>
|
|
40
|
-
|
|
41
|
-
## Summary
|
|
42
|
-
|
|
43
|
-
P0: <n>
|
|
44
|
-
P1: <n>
|
|
45
|
-
P2: <n>
|
|
46
|
-
P3: <n>
|
|
47
|
-
|
|
48
|
-
## Findings
|
|
49
|
-
|
|
50
|
-
- id: GHR-RC-2752827557
|
|
51
|
-
priority: P1
|
|
52
|
-
category: quality|performance|security|architecture
|
|
53
|
-
file: <path>
|
|
54
|
-
line: <number|null>
|
|
55
|
-
title: <short>
|
|
56
|
-
description: <single-line text>
|
|
57
|
-
suggestion: <single-line text>
|
|
58
|
-
```
|
|
59
|
-
|
|
60
|
-
## ID 规则(强制)
|
|
61
|
-
|
|
62
|
-
- Inline 评审(discussion_r...):`GHR-RC-<databaseId>`(databaseId 可映射到 `#discussion_r<databaseId>`)
|
|
63
|
-
- PR Review 总评:`GHR-RV-<reviewId>`
|
|
64
|
-
- PR 普通评论:`GHR-IC-<issueCommentId>`
|
|
65
|
-
|
|
66
|
-
## 执行步骤(强制)
|
|
67
|
-
|
|
68
|
-
1) Harvest(确定性)
|
|
69
|
-
|
|
70
|
-
- 调用脚本生成 raw JSON:
|
|
71
|
-
|
|
72
|
-
```bash
|
|
73
|
-
python3 ~/.opencode/agents/gh_review_harvest.py \
|
|
74
|
-
--pr <PR_NUMBER> \
|
|
75
|
-
--round <ROUND> \
|
|
76
|
-
--run-id <RUN_ID>
|
|
77
|
-
```
|
|
78
|
-
|
|
79
|
-
- 脚本 stdout 会输出一行 JSON:`{"rawFile":"./.cache/...json"}`,从中取 `rawFile`。
|
|
80
|
-
|
|
81
|
-
2) Normalize(LLM 分类)
|
|
82
|
-
|
|
83
|
-
- 读取 `rawFile`(JSON)后,提取“建议/问题”并生成 findings:
|
|
84
|
-
- 覆盖 humans + bots(不做作者白名单)。
|
|
85
|
-
- 忽略纯审批/无内容:如 `LGTM`、`Looks good`、`Approved` 等。
|
|
86
|
-
- 分类规则(大致):
|
|
87
|
-
- P0: 明确安全漏洞/数据泄漏/资金损失/远程执行
|
|
88
|
-
- P1: 逻辑 bug/权限绕过/会导致线上错误
|
|
89
|
-
- P2: 潜在 bug/鲁棒性/边界条件/可维护性重大问题
|
|
90
|
-
- P3: 风格/命名/小优化/可选建议
|
|
91
|
-
- `category` 只能取:quality|performance|security|architecture
|
|
92
|
-
|
|
93
|
-
3) 写入 reviewFile
|
|
94
|
-
|
|
95
|
-
- 文件名固定:`./.cache/review-GHR-pr<PR_NUMBER>-r<ROUND>-<RUN_ID>.md`
|
|
96
|
-
- 重要:`title/description/suggestion` 必须是单行;原文有换行时用 `\\n` 转义。
|
|
97
|
-
|
|
98
|
-
## 禁止事项(强制)
|
|
99
|
-
|
|
100
|
-
- ⛔ 不发布 GitHub 评论(不调用 `gh pr comment/review`)
|
|
101
|
-
- ⛔ 不修改代码(只输出 reviewFile)
|
|
102
|
-
- ⛔ 不生成/伪造 runId
|
|
103
|
-
|
|
104
|
-
## 决策日志约束(强制)
|
|
105
|
-
|
|
106
|
-
如果 prompt 中提供了 `decisionLogFile`,必须先读取并遵守以下规则:
|
|
107
|
-
|
|
108
|
-
1. **已修复问题**:不再提出本质相同的问题
|
|
109
|
-
2. **已拒绝问题**:
|
|
110
|
-
- 若你的发现 priority 比原问题高 ≥2 级(如 P3→P1, P2→P0),可以升级质疑
|
|
111
|
-
- 否则不再提出
|
|
112
|
-
|
|
113
|
-
3. **文件一致性**:
|
|
114
|
-
- 匹配 Decision Log 时,**必须检查 `file` 字段是否与当前 finding 的文件一致**。
|
|
115
|
-
- 若 decision-log 中的 `file` 与当前文件不一致(包括重命名、移动、删除),则**视为不同问题**,不进行 essence 匹配(即作为新问题处理)。
|
|
116
|
-
- 若 decision-log 条目缺少 `file` 字段,也视为不匹配。
|
|
117
|
-
|
|
118
|
-
判断"问题本质相同"时,比对 decision-log 中的 `essence` 字段与你发现的问题描述。
|
|
119
|
-
|
|
120
|
-
### 禁止事项
|
|
121
|
-
- ⛔ 不质疑已修复问题的实现方式(除非发现修复引入了新 bug)
|
|
122
|
-
- ⛔ 不重复提出已拒绝问题(除非满足升级质疑条件)
|