@weotro/dx 0.1.17 → 0.1.19
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 +5 -4
- package/lib/codex-initial.js +2 -0
- package/package.json +1 -1
- package/skills/ask_3th/SKILL.md +27 -0
- package/skills/{ask_cc/scripts/ask_cc.py → ask_3th/scripts/ask_3th.py} +3 -3
- package/skills/delegate_3th/SKILL.md +87 -0
- package/skills/delegate_3th/scripts/__pycache__/delegate_3th.cpython-314.pyc +0 -0
- package/skills/{delegate-cc/scripts/delegate_cc.py → delegate_3th/scripts/delegate_3th.py} +10 -8
- package/skills/{delegate-cc/scripts/test_delegate_cc.py → delegate_3th/scripts/test_delegate_3th.py} +68 -46
- package/skills/gh-dependabot-cleanup/SKILL.md +18 -6
- package/skills/git-release/SKILL.md +3 -1
- package/skills/ship-issue-pr/SKILL.md +34 -83
- package/skills/ask_cc/SKILL.md +0 -30
- package/skills/delegate-cc/SKILL.md +0 -66
- /package/skills/{ask_cc → ask_3th}/agents/openai.yaml +0 -0
- /package/skills/{delegate-cc → delegate_3th}/agents/openai.yaml +0 -0
- /package/skills/{delegate-cc → delegate_3th}/scripts/__pycache__/delegate_cc.cpython-314.pyc +0 -0
- /package/skills/{delegate-cc → delegate_3th}/scripts/__pycache__/test_delegate_cc.cpython-314.pyc +0 -0
package/README.md
CHANGED
|
@@ -307,12 +307,13 @@ dx cache clear -Y
|
|
|
307
307
|
- `~/.codex/skills` 中包内管理的同名非软链接 skill 会被清理;已有软链接不会按旧副本删除。
|
|
308
308
|
- 从包内移除的历史 skill 会在 `~/.agents/skills`、`~/.claude/skills`、`~/.codex/skills` 中一并清理。
|
|
309
309
|
- 不属于包内管理的其他用户自有 skill 目录会保留。
|
|
310
|
-
-
|
|
311
|
-
-
|
|
310
|
+
- `ask_3th` 用于向第三方咨询,`delegate_3th` 用于委托第三方执行。可显式调用,也可由已授权的 `ship-issue-pr` 流程调用。
|
|
311
|
+
- 运行时判断由这两个技能内部完成:Codex 宿主调用 Claude,Claude Code 宿主调用 Codex。调用失败后立即使用 fresh sub-agent 接续,返回结果时说明实际执行者与回退原因。
|
|
312
|
+
- `dx initial` 不安装 Python、Claude CLI 或 Codex 插件,也不修改认证配置。
|
|
312
313
|
|
|
313
|
-
|
|
314
|
+
从 `ask_cc` / `delegate-cc` 升级:运行 `dx initial` 后旧技能目录会被清理,请将技能调用改为 `ask_3th` / `delegate_3th`。Claude 通道的脚本路径分别改为 `~/.agents/skills/ask_3th/scripts/ask_3th.py` 和 `~/.agents/skills/delegate_3th/scripts/delegate_3th.py`。脚本调用失败统一返回 `fallback_required`,不再自动轮换模型或返回 `continuation_required` / `next_model`;由技能执行者启动 fresh sub-agent 并等待完成。`--timeout` 仍是无活动告警阈值。
|
|
314
315
|
|
|
315
|
-
Issue/PR 交付统一使用 `ship-issue-pr`:在 Codex 中调用 `$ship-issue-pr`,在 Claude Code 中调用 `/ship-issue-pr
|
|
316
|
+
Issue/PR 交付统一使用 `ship-issue-pr`:在 Codex 中调用 `$ship-issue-pr`,在 Claude Code 中调用 `/ship-issue-pr`。该技能只调用咨询或委托接口、验收结果并记录执行说明,运行时和回退决策封装在依赖技能内部。
|
|
316
317
|
|
|
317
318
|
升级 dx 后再次运行 `dx initial`,会整体更新 `~/.agents/skills/ship-issue-pr/`,并清理已移除的技能和独立引用文件。现有调用统一改为 `ship-issue-pr`。Claude 的软链接直接读取同一份更新;入口同时声明 Codex 和 Claude 的显式调用策略。外部 Claude CLI 或 Codex 插件仍需自行安装并完成认证,目录兼容不代表外部通道已可用。
|
|
318
319
|
|
package/lib/codex-initial.js
CHANGED
|
@@ -13,6 +13,8 @@ const REMOVED_AGENT_REFERENCES = ['ship-issue-pr-core.md']
|
|
|
13
13
|
// 这些名字需要在 ~/.agents、~/.claude、~/.codex 三处彻底清理(软链或真实目录都清)。
|
|
14
14
|
// 将来从 skills/ 删除新的 skill 时,把它追加到这里即可。
|
|
15
15
|
const DELETED_SKILLS = [
|
|
16
|
+
'ask_cc',
|
|
17
|
+
'delegate-cc',
|
|
16
18
|
'oo-ship-issue-pr',
|
|
17
19
|
'cc-ship-issue-pr',
|
|
18
20
|
'autospec',
|
package/package.json
CHANGED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: ask_3th
|
|
3
|
+
description: 显式调用 ask_3th 或被已授权流程调用时,向第三方提问、咨询或获取独立审查意见。
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# ask_3th
|
|
7
|
+
|
|
8
|
+
向第三方获取答案或第二意见,咨询与审查只读。调用方提供问题、必要事实、源码或 diff、约束和预期输出;运行时选择、调用与失败回退由本技能负责,调用方只接收最终结果和执行说明。
|
|
9
|
+
|
|
10
|
+
## 执行流程
|
|
11
|
+
|
|
12
|
+
1. 整理自包含的问题材料,排除凭据。审查材料覆盖请求范围,证据不足时先补充,不假定咨询者拥有当前对话。
|
|
13
|
+
2. 读取 [delegate_3th](../delegate_3th/SKILL.md),使用其 `consult` 模式完成运行时判断:Codex 宿主调用 Claude,Claude Code 宿主调用 Codex。按相应通道调用,咨询不授予写权限。
|
|
14
|
+
3. 第三方调用失败时,立即执行该技能的 fresh sub-agent 回退流程,等待实质答案后返回。回退在本技能内部完成,不把中间的 `fallback_required` 当作最终答复交给调用方。
|
|
15
|
+
4. 核实答案回应原问题,按依赖技能的返回契约交付答案、实际执行者及回退说明。独立审查使用未参与实现或修复的全新会话。
|
|
16
|
+
|
|
17
|
+
用户要求修改代码或执行任务时,转入 `delegate_3th` 的 `task` 模式,沿用已有任务范围与授权。
|
|
18
|
+
|
|
19
|
+
## Claude 通道脚本
|
|
20
|
+
|
|
21
|
+
仅在上述路由选择 Claude 时使用当前技能目录的 `scripts/ask_3th.py`;它固定为咨询模式,调用细节与失败状态由 `delegate_3th` 维护。脚本自身不能启动宿主 sub-agent,收到失败状态后由执行本技能的 agent 完成回退。
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
python3 "$HOME/.agents/skills/ask_3th/scripts/ask_3th.py" --prompt-file /绝对路径/问题.txt
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
`--timeout` 是无活动告警阈值(默认 120 秒),不是答复截止时间。通过宿主异步工具持续读取同一会话;静默或单次等待超时本身不算调用失败。
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
#!/usr/bin/env python3
|
|
2
|
-
"""
|
|
2
|
+
"""第三方技能的 Claude 咨询入口;统一实现位于 delegate_3th。"""
|
|
3
3
|
|
|
4
4
|
from pathlib import Path
|
|
5
5
|
import sys
|
|
6
6
|
|
|
7
|
-
sys.path.insert(0, str(Path(__file__).resolve().parents[2] / "
|
|
8
|
-
from
|
|
7
|
+
sys.path.insert(0, str(Path(__file__).resolve().parents[2] / "delegate_3th" / "scripts"))
|
|
8
|
+
from delegate_3th import ask, main
|
|
9
9
|
|
|
10
10
|
|
|
11
11
|
if __name__ == "__main__":
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: delegate_3th
|
|
3
|
+
description: 显式调用 delegate_3th 或被已授权流程调用时,委托第三方执行任务;内部选择 Claude 或 Codex,失败后由 fresh sub-agent 接续并返回结果。
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# delegate_3th
|
|
7
|
+
|
|
8
|
+
本技能负责第三方运行时路由、调用、失败回退及验收。调用方提供任务并接收最终结果,不需要选择 CLI、模型或接管方式。`ask_3th` 使用这里的 `consult` 模式;委托开发工作使用 `task` 模式。
|
|
9
|
+
|
|
10
|
+
## 1. 准备交接
|
|
11
|
+
|
|
12
|
+
遵循宿主指令、当前任务要求与已有授权、目标项目适用的 AGENTS.md。保留现有认证,任务授权不因切换执行者而扩大,权限拒绝不能靠回退绕过。
|
|
13
|
+
|
|
14
|
+
- **咨询 `consult`**:提供问题、事实、源码或 diff、约束与预期输出,只读;Claude CLI 不开放工具,Codex 通道与回退执行者仅允许必要的只读检索。
|
|
15
|
+
- **执行 `task`**:任务书包含工作目录、目标、责任文件或模块、项目指令、已有成果、验收标准和实际验证命令。告知执行者还有其他协作者,保留他人改动,只处理分配范围。
|
|
16
|
+
|
|
17
|
+
执行前检查 `git status --short`、相关 diff 和未跟踪文件,记录基线。分配互不重叠的文件;需要隔离时使用独立 worktree,并带入任务所需的未提交版本。原执行者仍在工作时,其他执行者不修改其责任文件。
|
|
18
|
+
|
|
19
|
+
将必要上下文写入本次临时 UTF-8 任务文件,排除凭据。默认只授权本地实现与验证;调用方明确委托独立 Issue 的完整交付时,任务书须带上该授权与 `ship-issue-pr` 流程,才可执行对应 Git/GitHub 操作。
|
|
20
|
+
|
|
21
|
+
## 2. 在技能内部选择运行时
|
|
22
|
+
|
|
23
|
+
依据当前会话宿主和实际暴露的工具判断,不根据模型名称或本机安装了哪些 CLI 猜测,也不要求调用方选择。
|
|
24
|
+
|
|
25
|
+
| 当前宿主 | 第三方通道 |
|
|
26
|
+
| --- | --- |
|
|
27
|
+
| Codex | 下文 Claude CLI |
|
|
28
|
+
| Claude Code | 下文 Codex 插件 |
|
|
29
|
+
| 宿主无法确定或对应通道缺失 | 直接进入 fresh sub-agent 回退 |
|
|
30
|
+
|
|
31
|
+
每次请求只尝试选定的第三方一次。调用失败后立即回退,不换另一个 Claude 模型、不重试另一条外部通道。单次等待超时、静默告警或任务尚未返回不等于失败;用户取消则停止,不启动接续任务。
|
|
32
|
+
|
|
33
|
+
### Claude CLI
|
|
34
|
+
|
|
35
|
+
需要 `python3` 和已认证的 `claude`;`dx initial` 只同步技能文件。使用当前技能目录的脚本,默认安装示例:
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
# 咨询,无活动告警阈值默认 120 秒。
|
|
39
|
+
python3 "$HOME/.agents/skills/delegate_3th/scripts/delegate_3th.py" --prompt-file /绝对路径/问题.txt
|
|
40
|
+
|
|
41
|
+
# 执行,无活动告警阈值默认 900 秒。
|
|
42
|
+
python3 "$HOME/.agents/skills/delegate_3th/scripts/delegate_3th.py" --mode task --cwd /绝对路径/工作区 --prompt-file /绝对路径/任务.txt
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
默认请求 `claude-fable-5-1`。兼容参数 `--start-model` 仅选择本次任务请求的模型,不构成重试链。需要运行验证命令时按已有授权追加具体的 `--allow-command '仓库实际验证命令'`,可重复传入。
|
|
46
|
+
|
|
47
|
+
执行模式开放 `Read,Glob,Grep,Edit,Write,Bash`,使用 `acceptEdits`,无法获批的工具请求自动拒绝;现有权限规则继续生效,允许命令不是独立沙箱。两种模式关闭 hooks、MCP 和技能,因此任务书必须包含必要项目规则。脚本默认仅执行本地开发;完整交付等超出该边界的任务直接进入 fresh sub-agent,由其承接明确授权。
|
|
48
|
+
|
|
49
|
+
通过宿主异步工具保留会话 ID 并持续读取结果,至少每 60 秒汇报有意义的进度。`--timeout` 只控制无活动告警,不自动终止任务。脚本通过输出字节和 Git 跟踪及未忽略文件的变化观察活动;忽略目录产物需另查,观测不可用不代表停滞。
|
|
50
|
+
|
|
51
|
+
脚本 stdout 返回单个 JSON:`ok` 表示咨询已返回,`review_required` 表示任务报告待验收,`fallback_required` 表示立即进入下文回退。脚本只报告失败,启动宿主 sub-agent 和等待结果是本技能执行者的职责。
|
|
52
|
+
|
|
53
|
+
### Codex 插件
|
|
54
|
+
|
|
55
|
+
使用当前 Claude Code 会话实际暴露的 Codex 插件能力:任务或咨询可用 `Agent(subagent_type: "codex:codex-rescue")`;普通审查可用 companion 的 `review`,挑战方案假设可用 `adversarial-review`。选择符合当前请求的一条通道,只读或写入范围写入任务书。
|
|
56
|
+
|
|
57
|
+
companion 使用实际安装路径;需要定位时仅检查当前 Claude 配置目录对应的 marketplace/cache,以 `scripts/codex-companion.mjs --help` 核实参数,不硬编码缓存版本。审查示例:
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
node "<plugin-root>/scripts/codex-companion.mjs" review --wait --base "<actual-base>"
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
保存 job/agent ID、工作目录与输出位置,异步等待同一任务。插件缺失、启动失败、认证或额度错误、非零退出、明确失败报告或无效结果均进入回退。
|
|
64
|
+
|
|
65
|
+
## 3. 失败后立即交给 fresh sub-agent
|
|
66
|
+
|
|
67
|
+
fresh sub-agent(refresh subagent)指本次新建、独立上下文的执行者,不复用当前 agent 或此前的实现/审查会话。即使本技能当前由 sub-agent 执行,也应新建执行者,不能直接由它自称 fresh 后接手。
|
|
68
|
+
|
|
69
|
+
1. 确认原调用及其写进程已停止;仍在运行时先检查会话、子命令和权限等待,确认实际失败或无法推进后终止并核实停止。用户取消不触发回退。
|
|
70
|
+
2. 检查现有 diff、测试与外部副作用,将已完成成果和剩余工作加入任务书,避免从头重放。保留原权限限制与只读/写入边界。
|
|
71
|
+
3. 立即创建一个使用宿主默认模型的全新 sub-agent:Codex 使用 `spawn_agent`,设置 `fork_turns: "none"`;Claude Code 使用新的 `Agent(subagent_type: "general-purpose")`,不 resume 旧会话。传入自包含任务书,要求直接处理本次失败调用的剩余工作,不将同一工作再次交给 `ask_3th` / `delegate_3th` 或外部 CLI,避免递归回退。完整交付中的后续独立咨询/审查仍按交付流程调用技能。独立审查者不得是原实现者。
|
|
72
|
+
4. 等待该 sub-agent 完成并验收其结果,再向调用方返回。若 sub-agent 工具不可用、达到嵌套限制或回退也失败,如实返回未完成项与具体阻塞;不冒充已接管或已完成,也不无限创建新 agent。
|
|
73
|
+
|
|
74
|
+
## 4. 验收与返回
|
|
75
|
+
|
|
76
|
+
咨询确认获得实质答案;执行对照基线、完整 diff、责任范围及验收标准核查,运行必要测试,复用仍有效的验证证据。`permission_denials` 非零或报告包含权限拒绝时,核实缺失项并保留权限边界。第三方成功声明不等于验收通过。
|
|
77
|
+
|
|
78
|
+
向调用方返回答案或实际变更、验证结果、未完成项,并附简短执行说明,包含:
|
|
79
|
+
|
|
80
|
+
- `requested_provider`:原定 Claude、Codex,或宿主未知。
|
|
81
|
+
- `actual_executor`:实际第三方及请求模型(可得时),或 fresh sub-agent 及其 ID。
|
|
82
|
+
- `fallback_used` 与 `fallback_reason`:是否回退及具体原因;未回退时注明无。
|
|
83
|
+
- `status`:验收后为 `ok` / `completed`,仍有缺口为 `blocked`,并说明恢复所需条件。
|
|
84
|
+
|
|
85
|
+
例如:“Claude 调用因额度不足失败,已由 fresh sub-agent <ID> 完成;验证通过。”这段说明供调用方记录,运行时与回退决策已在本技能内完成。请求模型 ID 不保证服务端未切换模型。
|
|
86
|
+
|
|
87
|
+
清理本次临时任务文件;保留仍有成果待整合的 worktree。
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env python3
|
|
2
|
-
"""
|
|
2
|
+
"""第三方技能的 Claude 通道;单次调用失败后通知宿主启动 fresh sub-agent。"""
|
|
3
3
|
|
|
4
4
|
import argparse
|
|
5
5
|
import json
|
|
@@ -86,8 +86,9 @@ def ask(prompt, timeout=120, *, mode="consult", cwd=None, start_model=None, allo
|
|
|
86
86
|
attempts = []
|
|
87
87
|
cli = shutil.which("claude")
|
|
88
88
|
if not cli:
|
|
89
|
-
return {"status": "fallback_required", "attempts": [], "reason": "未找到 claude 命令"
|
|
90
|
-
|
|
89
|
+
return {"status": "fallback_required", "attempts": [], "reason": "未找到 claude 命令",
|
|
90
|
+
"next_executor": "fresh_subagent", "partial_work_possible": False}
|
|
91
|
+
models = (start_model or MODELS[0],)
|
|
91
92
|
for model in models:
|
|
92
93
|
if model not in MODELS:
|
|
93
94
|
raise ValueError("模型不在委派链中")
|
|
@@ -147,10 +148,9 @@ def ask(prompt, timeout=120, *, mode="consult", cwd=None, start_model=None, allo
|
|
|
147
148
|
else:
|
|
148
149
|
reason = f"CLI 未返回有效答案(退出码 {process.returncode})"
|
|
149
150
|
attempts.append({"requested_model": model, "reason": reason})
|
|
150
|
-
result = {"status": "fallback_required", "attempts": attempts
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
next_model=MODELS[1] if models[0] == MODELS[0] else None)
|
|
151
|
+
result = {"status": "fallback_required", "attempts": attempts,
|
|
152
|
+
"reason": attempts[-1]["reason"], "next_executor": "fresh_subagent",
|
|
153
|
+
"partial_work_possible": mode == "task"}
|
|
154
154
|
return result
|
|
155
155
|
|
|
156
156
|
|
|
@@ -176,7 +176,9 @@ def main(argv=None):
|
|
|
176
176
|
if not prompt.strip():
|
|
177
177
|
raise ValueError("问题为空")
|
|
178
178
|
except (OSError, UnicodeError, ValueError):
|
|
179
|
-
result = {"status": "fallback_required", "attempts": [],
|
|
179
|
+
result = {"status": "fallback_required", "attempts": [],
|
|
180
|
+
"reason": "问题文件不可读或为空,请宿主向 fresh sub-agent 提供原任务",
|
|
181
|
+
"next_executor": "fresh_subagent", "partial_work_possible": False}
|
|
180
182
|
else:
|
|
181
183
|
result = ask(prompt, args.timeout, mode=args.mode, cwd=args.cwd,
|
|
182
184
|
start_model=args.start_model, allow_commands=args.allow_command)
|
package/skills/{delegate-cc/scripts/test_delegate_cc.py → delegate_3th/scripts/test_delegate_3th.py}
RENAMED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"""
|
|
1
|
+
"""覆盖 Claude 单次调用、失败回退信号与任务活性。"""
|
|
2
2
|
|
|
3
3
|
import json
|
|
4
4
|
import io
|
|
@@ -10,7 +10,7 @@ import tempfile
|
|
|
10
10
|
from pathlib import Path
|
|
11
11
|
from unittest.mock import patch
|
|
12
12
|
|
|
13
|
-
import
|
|
13
|
+
import delegate_3th as ask_3th
|
|
14
14
|
|
|
15
15
|
|
|
16
16
|
def result(answer, failed=False):
|
|
@@ -24,9 +24,9 @@ class AskCCTest(unittest.TestCase):
|
|
|
24
24
|
def test_cli_entrypoints_do_not_switch_models_after_idle_threshold(self):
|
|
25
25
|
skills = Path(__file__).resolve().parents[2]
|
|
26
26
|
entries = [
|
|
27
|
-
(skills / "
|
|
28
|
-
(skills / "
|
|
29
|
-
(skills / "
|
|
27
|
+
(skills / "ask_3th/scripts/ask_3th.py", "consult"),
|
|
28
|
+
(skills / "delegate_3th/scripts/delegate_3th.py", "consult"),
|
|
29
|
+
(skills / "delegate_3th/scripts/delegate_3th.py", "task"),
|
|
30
30
|
]
|
|
31
31
|
for entry, mode in entries:
|
|
32
32
|
with self.subTest(entry=entry, mode=mode), tempfile.TemporaryDirectory() as tmp:
|
|
@@ -56,45 +56,48 @@ class AskCCTest(unittest.TestCase):
|
|
|
56
56
|
response = json.loads(completed.stdout)
|
|
57
57
|
self.assertEqual(response["status"], "review_required" if mode == "task" else "ok")
|
|
58
58
|
self.assertEqual(response["attempts"], [])
|
|
59
|
-
self.assertEqual(calls.read_text().splitlines(), [
|
|
59
|
+
self.assertEqual(calls.read_text().splitlines(), [ask_3th.MODELS[0]])
|
|
60
60
|
self.assertIn("疑似停滞", completed.stderr)
|
|
61
61
|
|
|
62
|
-
@patch.object(
|
|
62
|
+
@patch.object(ask_3th.shutil, "which", return_value="/fake/claude")
|
|
63
63
|
def test_task_permissions_and_review(self, _which):
|
|
64
|
-
with tempfile.TemporaryDirectory() as cwd, patch.object(
|
|
65
|
-
response =
|
|
64
|
+
with tempfile.TemporaryDirectory() as cwd, patch.object(ask_3th, "run_task", return_value=result("完成")) as run:
|
|
65
|
+
response = ask_3th.ask("修改代码", mode="task", cwd=cwd, allow_commands=["python3 -m unittest"])
|
|
66
66
|
command = run.call_args.args[0]
|
|
67
67
|
self.assertEqual(response["status"], "review_required")
|
|
68
68
|
self.assertEqual(command[command.index("--permission-mode") + 1], "acceptEdits")
|
|
69
69
|
self.assertIn("Bash(python3 -m unittest)", command)
|
|
70
70
|
self.assertNotIn("bypassPermissions", command)
|
|
71
71
|
|
|
72
|
-
@patch.object(
|
|
72
|
+
@patch.object(ask_3th.shutil, "which", return_value="/fake/claude")
|
|
73
73
|
def test_partial_task_is_not_blindly_retried(self, _which):
|
|
74
74
|
with tempfile.TemporaryDirectory() as cwd:
|
|
75
75
|
def partial(*args):
|
|
76
76
|
Path(cwd, "partial.txt").write_text("已完成部分")
|
|
77
77
|
raise OSError("CLI connection failed")
|
|
78
|
-
with patch.object(
|
|
79
|
-
response =
|
|
78
|
+
with patch.object(ask_3th, "run_task", side_effect=partial) as run:
|
|
79
|
+
response = ask_3th.ask("修改代码", mode="task", cwd=cwd)
|
|
80
80
|
self.assertEqual(run.call_count, 1)
|
|
81
81
|
self.assertEqual(Path(cwd, "partial.txt").read_text(), "已完成部分")
|
|
82
|
-
self.assertEqual(response["status"], "
|
|
83
|
-
self.assertEqual(response["
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
82
|
+
self.assertEqual(response["status"], "fallback_required")
|
|
83
|
+
self.assertEqual(response["next_executor"], "fresh_subagent")
|
|
84
|
+
self.assertTrue(response["partial_work_possible"])
|
|
85
|
+
self.assertNotIn("next_model", response)
|
|
86
|
+
|
|
87
|
+
@patch.object(ask_3th.shutil, "which", return_value="/fake/claude")
|
|
88
|
+
def test_explicit_model_failure_requests_fresh_subagent(self, _which):
|
|
89
|
+
with tempfile.TemporaryDirectory() as cwd, patch.object(ask_3th, "run_task", return_value=result("usage limit", True)):
|
|
90
|
+
response = ask_3th.ask("接续", mode="task", cwd=cwd, start_model="claude-opus-5")
|
|
91
|
+
self.assertEqual(response["status"], "fallback_required")
|
|
92
|
+
self.assertEqual(response["next_executor"], "fresh_subagent")
|
|
93
|
+
self.assertNotIn("next_model", response)
|
|
91
94
|
|
|
92
95
|
def test_task_requires_explicit_directory(self):
|
|
93
96
|
with self.assertRaises(ValueError):
|
|
94
|
-
|
|
97
|
+
ask_3th.ask("修改代码", mode="task")
|
|
95
98
|
|
|
96
|
-
@patch.object(
|
|
97
|
-
def
|
|
99
|
+
@patch.object(ask_3th.shutil, "which", return_value="/fake/claude")
|
|
100
|
+
def test_first_failure_requests_fallback_without_second_model(self, _which):
|
|
98
101
|
seen = []
|
|
99
102
|
|
|
100
103
|
def cli(command, *args):
|
|
@@ -106,30 +109,49 @@ class AskCCTest(unittest.TestCase):
|
|
|
106
109
|
return result("OK")
|
|
107
110
|
return result(f"There's an issue with the selected model ({model}).", True)
|
|
108
111
|
|
|
109
|
-
with patch.object(
|
|
110
|
-
response =
|
|
111
|
-
self.assertEqual(response["status"], "
|
|
112
|
-
self.assertEqual(seen, ["claude-fable-5-1"
|
|
113
|
-
self.assertEqual(response["
|
|
112
|
+
with patch.object(ask_3th, "run_task", side_effect=cli):
|
|
113
|
+
response = ask_3th.ask("仅回答 OK")
|
|
114
|
+
self.assertEqual(response["status"], "fallback_required")
|
|
115
|
+
self.assertEqual(seen, ["claude-fable-5-1"])
|
|
116
|
+
self.assertEqual(response["next_executor"], "fresh_subagent")
|
|
117
|
+
self.assertEqual(response["reason"], "额度不足或限流")
|
|
118
|
+
|
|
119
|
+
@patch.object(ask_3th.shutil, "which", return_value=None)
|
|
120
|
+
def test_missing_cli_requests_fresh_subagent(self, _which):
|
|
121
|
+
with patch.object(ask_3th, "run_task") as run:
|
|
122
|
+
response = ask_3th.ask("问题")
|
|
123
|
+
run.assert_not_called()
|
|
124
|
+
self.assertEqual(response["status"], "fallback_required")
|
|
125
|
+
self.assertEqual(response["next_executor"], "fresh_subagent")
|
|
126
|
+
self.assertFalse(response["partial_work_possible"])
|
|
127
|
+
|
|
128
|
+
@patch.object(ask_3th.shutil, "which", return_value="/fake/claude")
|
|
129
|
+
def test_invalid_result_requests_fresh_subagent_once(self, _which):
|
|
130
|
+
for output in ["not json", json.dumps({"type": "result", "subtype": "success", "result": " "})]:
|
|
131
|
+
with self.subTest(output=output), patch.object(ask_3th, "run_task", return_value=
|
|
132
|
+
subprocess.CompletedProcess([], 0, output, "")) as run:
|
|
133
|
+
response = ask_3th.ask("问题")
|
|
134
|
+
self.assertEqual(run.call_count, 1)
|
|
135
|
+
self.assertEqual(response["next_executor"], "fresh_subagent")
|
|
114
136
|
|
|
115
|
-
@patch.object(
|
|
137
|
+
@patch.object(ask_3th.shutil, "which", return_value="/fake/claude")
|
|
116
138
|
def test_unrecognized_model_is_reported(self, _which):
|
|
117
139
|
failure = result("There's an issue with the selected model (fable-5.1). It may not exist or you may not have access to it.", True)
|
|
118
|
-
with patch.object(
|
|
119
|
-
response =
|
|
140
|
+
with patch.object(ask_3th, "run_task", return_value=failure):
|
|
141
|
+
response = ask_3th.ask("问题")
|
|
120
142
|
self.assertEqual(response["status"], "fallback_required")
|
|
121
143
|
self.assertEqual(response["attempts"][0]["reason"], "模型名称无效或当前账户无权访问")
|
|
122
144
|
|
|
123
|
-
@patch.object(
|
|
145
|
+
@patch.object(ask_3th.shutil, "which", return_value="/fake/claude")
|
|
124
146
|
def test_login_error_is_distinct(self, _which):
|
|
125
|
-
with patch.object(
|
|
126
|
-
response =
|
|
147
|
+
with patch.object(ask_3th, "run_task", return_value=result("Not logged in · Please run /login", True)):
|
|
148
|
+
response = ask_3th.ask("问题")
|
|
127
149
|
self.assertEqual(response["attempts"][0]["reason"], "认证不可用")
|
|
128
150
|
|
|
129
151
|
def test_silent_process_survives_idle_warning(self):
|
|
130
152
|
command = [sys.executable, "-c", "import time; time.sleep(0.2); print('done')"]
|
|
131
|
-
with patch.object(
|
|
132
|
-
completed =
|
|
153
|
+
with patch.object(ask_3th.sys, "stderr", new_callable=io.StringIO) as log:
|
|
154
|
+
completed = ask_3th.run_task(command, "", 0.05, None)
|
|
133
155
|
self.assertEqual(completed.returncode, 0)
|
|
134
156
|
self.assertEqual(completed.stdout.strip(), "done")
|
|
135
157
|
self.assertIn("疑似停滞", log.getvalue())
|
|
@@ -137,8 +159,8 @@ class AskCCTest(unittest.TestCase):
|
|
|
137
159
|
def test_streaming_process_survives_total_duration(self):
|
|
138
160
|
command = [sys.executable, "-u", "-c",
|
|
139
161
|
"import time\nfor i in range(8):\n print(i)\n time.sleep(0.04)"]
|
|
140
|
-
with patch.object(
|
|
141
|
-
completed =
|
|
162
|
+
with patch.object(ask_3th.sys, "stderr", new_callable=io.StringIO):
|
|
163
|
+
completed = ask_3th.run_task(command, "", 0.1, None)
|
|
142
164
|
self.assertEqual(completed.returncode, 0)
|
|
143
165
|
self.assertEqual(completed.stdout.splitlines(), [str(i) for i in range(8)])
|
|
144
166
|
|
|
@@ -147,19 +169,19 @@ class AskCCTest(unittest.TestCase):
|
|
|
147
169
|
subprocess.run(["git", "init", "-q", cwd], check=True)
|
|
148
170
|
file = Path(cwd, "work.txt")
|
|
149
171
|
file.write_text("before")
|
|
150
|
-
before =
|
|
172
|
+
before = ask_3th.workspace_activity(cwd)
|
|
151
173
|
file.write_text("after!")
|
|
152
|
-
self.assertNotEqual(before,
|
|
153
|
-
before =
|
|
174
|
+
self.assertNotEqual(before, ask_3th.workspace_activity(cwd))
|
|
175
|
+
before = ask_3th.workspace_activity(cwd)
|
|
154
176
|
file.unlink()
|
|
155
|
-
self.assertNotEqual(before,
|
|
177
|
+
self.assertNotEqual(before, ask_3th.workspace_activity(cwd))
|
|
156
178
|
|
|
157
|
-
@patch.object(
|
|
179
|
+
@patch.object(ask_3th.shutil, "which", return_value="/fake/claude")
|
|
158
180
|
def test_stream_events_resolve_final_result(self, _which):
|
|
159
181
|
output = result("完成")
|
|
160
182
|
output.stdout = json.dumps({"type": "assistant", "message": "working"}) + "\n" + output.stdout
|
|
161
|
-
with patch.object(
|
|
162
|
-
response =
|
|
183
|
+
with patch.object(ask_3th, "run_task", return_value=output) as run:
|
|
184
|
+
response = ask_3th.ask("问题")
|
|
163
185
|
self.assertEqual(response["answer"], "完成")
|
|
164
186
|
self.assertIn("stream-json", run.call_args.args[0])
|
|
165
187
|
|
|
@@ -25,8 +25,9 @@ Use this skill to complete a Dependabot remediation loop with minimal manual inp
|
|
|
25
25
|
5. Apply dependency changes (prefer overrides/resolutions for transitive alerts).
|
|
26
26
|
6. Refresh lockfile.
|
|
27
27
|
7. Run required project verification commands.
|
|
28
|
-
8. For
|
|
29
|
-
9.
|
|
28
|
+
8. For authorized issue and PR delivery, find and reuse a matching tracking issue or create one with the alert scope, remediation plan, and verification results. Commit, push, and open a focused PR linked to that issue. A local remediation request finishes with verified local changes and drafts for any requested delivery that still lacks authorization.
|
|
29
|
+
9. If the user requests merging, continue through the merge workflow below using the existing authorization; opening a PR alone does not complete that request.
|
|
30
|
+
10. Report the issue, PR, merge outcome, and residual risk using the final reply requirements below.
|
|
30
31
|
|
|
31
32
|
## Default Commands
|
|
32
33
|
```bash
|
|
@@ -51,7 +52,18 @@ pnpm install --lockfile-only
|
|
|
51
52
|
|
|
52
53
|
## PR Requirements
|
|
53
54
|
Include these sections:
|
|
54
|
-
1.
|
|
55
|
-
2.
|
|
56
|
-
3.
|
|
57
|
-
4.
|
|
55
|
+
1. Tracking issue: issue number and URL; use `Closes #<issue>` only when the PR completes the issue's entire scope. Otherwise use `Refs #<issue>` and keep the remaining work tracked.
|
|
56
|
+
2. Fixed alerts: alert id, package, target version
|
|
57
|
+
3. Remaining alerts: alert id, reason (for example, no upstream patch)
|
|
58
|
+
4. Verification: exact commands run and outcomes
|
|
59
|
+
5. Risk note: what is deferred and why
|
|
60
|
+
|
|
61
|
+
## Merge Workflow
|
|
62
|
+
- Before merging, verify the PR's current head, required checks, review requirements, and mergeability. Follow the repository's merge strategy and branch protection; do not bypass required checks or reviews.
|
|
63
|
+
- When merge is authorized and requirements pass, merge with `gh pr merge`, binding the operation to the verified head via `--match-head-commit`. If the head changes, verify the new head before retrying.
|
|
64
|
+
- If checks or reviews block merging, resolve actionable failures within scope and recheck. Report any remaining blocker precisely. Enabling auto-merge or entering a merge queue is pending, not a completed merge.
|
|
65
|
+
- After merging, verify the PR's `MERGED` state and merge commit, check the tracking issue's state, and fetch Dependabot alerts again. Report still-open alerts as observed; distinguish scan results that have not yet updated from confirmed remediation failures.
|
|
66
|
+
|
|
67
|
+
## Final Reply Requirements
|
|
68
|
+
Always explicitly mention both **Issue** and **PR**, including their numbers, URLs, and observed states. If either was not created or reused, say so and explain why; never substitute a Dependabot alert number for an issue number.
|
|
69
|
+
State whether the PR was actually merged, with the merge commit when available, or give the concrete pending condition or blocker. Include verification results and remaining alerts. Do not claim completion of a requested merge based only on PR creation, auto-merge configuration, or queue entry.
|
|
@@ -11,6 +11,8 @@ description: 仅在显式调用 git-release 时使用:准备或执行版本发
|
|
|
11
11
|
只读检索、本地草稿、可回滚编辑和常规测试可自主推断并继续;从相关文件和直接依赖开始,仅在证据不足或影响跨模块时扩大范围,复用仍有效的验证。
|
|
12
12
|
仅在不可逆或难以回滚的修改缺少具体授权时,先完成预览、草稿与验证,再说明对象和影响并等待确认;会话中已有授权继续有效。缺少事实时先查证、标注假设并推进独立工作,确实无法确定操作目标时才询问。对外发送消息须有明确授权。
|
|
13
13
|
|
|
14
|
+
用户显式调用本技能执行发布,即明确授权在本次目标仓库创建并推送目标版本的 tag,以及创建并发布对应的 GitHub Release。完成准备和验证后连续执行至发布结果核验,无需再次询问是否推送 tag 或创建 Release。用户明确限定为仅准备、草稿、审计或修改技能时,按该范围执行;本授权不包含覆盖冲突 tag、删除既有 Release 或额外的生产操作。
|
|
15
|
+
|
|
14
16
|
## 发布准备
|
|
15
17
|
|
|
16
18
|
从当前 release 分支、用户指定版本或项目版本策略确定目标版本,说明来源。若项目采用 `release/vX.Y.Z`(也支持 alpha/beta/rc)则沿用;其他命名服从项目规则。没有版本策略时可以准备下一补丁版本的本地草稿,公开发布前核实目标。
|
|
@@ -27,7 +29,7 @@ description: 仅在显式调用 git-release 时使用:准备或执行版本发
|
|
|
27
29
|
|
|
28
30
|
## 创建发布
|
|
29
31
|
|
|
30
|
-
|
|
32
|
+
执行前核对目标仓库、版本、commit 和发行说明,确认发布检查通过、目标 tag 无冲突,然后依据「执行边界与优先级」中的明确授权直接推送 tag 并创建 GitHub Release。发布流程可能自动触发制品发布或部署,不因此追加确认步骤;仅在目标无法确定、检查失败或远端状态冲突时暂停受阻操作并说明原因。
|
|
31
33
|
|
|
32
34
|
按项目发布流程创建 tag、推送并创建 Release;例如:
|
|
33
35
|
```bash
|
|
@@ -8,7 +8,7 @@ disable-model-invocation: true
|
|
|
8
8
|
|
|
9
9
|
统一 Codex 与 Claude Code 的 Issue → 实现 → PR → 审查修复 → 验证 → 合并交付流程。
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
本文件包含完整交付流程,第三方协作统一通过 `ask_3th` 与 `delegate_3th` 完成。依次完成下列步骤;已有成果按验收标准承接,缺失的 Issue、方案审核、审查评论或验证报告必须补齐。
|
|
12
12
|
|
|
13
13
|
## 执行边界与优先级
|
|
14
14
|
|
|
@@ -51,27 +51,37 @@ Issue/PR 正文及评论优先使用结构化工具参数;使用 CLI 时将多
|
|
|
51
51
|
|
|
52
52
|
简单任务由主线程拟定必要步骤并直接实现。复杂任务必须依次完成:
|
|
53
53
|
|
|
54
|
+
### 每次交付的第三方调用次数
|
|
55
|
+
|
|
56
|
+
同一 Issue/PR 的本次交付中,以下三个阶段分别只有一次有效调用机会,独立计数:
|
|
57
|
+
|
|
58
|
+
| 阶段 | 技能 | 有效返回后的后续工作 |
|
|
59
|
+
| --- | --- | --- |
|
|
60
|
+
| 复杂方案讨论与审核 | `ask_3th` | 主 agent 处理进一步讨论、分歧与方案修订 |
|
|
61
|
+
| 复杂修改与实现 | `delegate_3th` | 主 agent 完成补充修改、修复与验证 |
|
|
62
|
+
| 复杂 Code Review | `ask_3th` | 主 agent 处理 findings、修复及后续复审 |
|
|
63
|
+
|
|
64
|
+
调用失败不占次数,可以通过同一技能重试;重试沿用已有成果,只处理剩余工作。按技能的最终返回计数,内部运行时选择与回退仍由技能负责。获得实质意见、审查报告或可供复核的实施结果即占用一次机会;存在分歧、findings 或验收需要补修,不视为调用失败。失败且仍无有效结果时保留该阶段待完成状态,有明确阻塞则先处理阻塞,避免无进展地重复调用。
|
|
65
|
+
|
|
66
|
+
在交付记录中维护三个阶段的有效调用状态和结果摘要。后续讨论、修复循环、推送新提交或恢复同一交付不会重置次数;已有对应阶段的有效结果时直接承接。独立 follow-up Issue 的交付单独计数。主 agent 接手后仍须完成验收、评论与验证,调用次数限制不缩减这些要求。
|
|
67
|
+
|
|
68
|
+
### 方案步骤
|
|
69
|
+
|
|
54
70
|
1. 主线程先提出方案,包含现状、目标、拟改文件/模块、接口与数据影响、风险、验收和测试计划。
|
|
55
|
-
2.
|
|
56
|
-
3.
|
|
71
|
+
2. 调用 `ask_3th` 审核方案,提供需求、规划约束及相关源码;仅咨询,不授予写权限。
|
|
72
|
+
3. 主线程核验返回意见,修订方案,记录采纳项、未采纳理由及最终方案。有效咨询后的关键分歧由主 agent 查证并解决,方案确定后才进入实施。
|
|
57
73
|
|
|
58
|
-
如果接手时复杂改动已存在,先根据现有 diff
|
|
74
|
+
如果接手时复杂改动已存在,先根据现有 diff 整理方案,按阶段记录补齐尚未取得有效结果的咨询或实施委托;已用过对应机会的阶段由主 agent 核查和修正,无需删除成果重做。
|
|
59
75
|
|
|
60
76
|
## 4. 实施与主线程复核
|
|
61
77
|
|
|
62
|
-
|
|
78
|
+
复杂任务尚未取得有效实施结果时调用 `delegate_3th`,有效返回后的补充修改与修复由主 agent 直接完成;简单任务主线程直接实施。交接包含最终方案、Issue、工作目录、责任文件、项目约束、已完成成果、验收标准及实际验证命令。主线程负责方案定稿、协调、验收及本次 Git/GitHub 交付,实施者只修改分配文件。
|
|
63
79
|
|
|
64
80
|
咨询与审查只读,实施才授予必要写权限。不同执行者避免同时修改同一范围,可在不重叠文件上继续工作;需要隔离时使用独立 worktree。任务书必须带上相关流程和项目规则,不能假定执行通道能加载技能。
|
|
65
81
|
|
|
66
82
|
第三方完成后,主线程核对完整 diff、责任范围和验收标准,检查遗漏、回归、越界改动与测试证据,处理发现的问题。第三方返回成功不等于主线程已验收,也不替代后续 PR Code Review。
|
|
67
83
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
### 委派活性与接管
|
|
71
|
-
|
|
72
|
-
保存本次任务 ID、工作目录、输出来源和责任文件基线,持续观察同一任务。有效日志、工具进展或责任文件变化可以证明活动;只读任务不要求文件修改。
|
|
73
|
-
|
|
74
|
-
单次等待超时或静默告警只触发诊断,检查原会话、子命令、权限等待与错误;重复空心跳不代表进展。确认失败或无法推进后优先恢复;接管前确认原执行者及其写进程已停止,再核对现有成果,仅完成剩余工作。遵守用户取消要求,不盲目重放任务或绕过权限拒绝。
|
|
84
|
+
复杂任务的方案审核、实施与 Code Review 各取得一次对应技能的有效结果,后续工作由主 agent 直接完成。本流程按返回的答案、改动与验证证据验收,将技能附带的执行说明记录到 Issue/PR;未完成项按实际缺口处理。
|
|
75
85
|
|
|
76
86
|
## 5. 提交代码并创建或更新 PR
|
|
77
87
|
|
|
@@ -83,13 +93,13 @@ Issue/PR 正文及评论优先使用结构化工具参数;使用 CLI 时将多
|
|
|
83
93
|
|
|
84
94
|
## 6. Code Review、评论与修复循环
|
|
85
95
|
|
|
86
|
-
按最新复杂度选择审查方式:简单任务由主线程直接 Code Review
|
|
96
|
+
按最新复杂度选择审查方式:简单任务由主线程直接 Code Review;复杂任务在尚未取得本次交付的有效 Code Review 时调用 `ask_3th`,要求独立审查。有效返回后,主线程核验关键证据并负责后续复审,如实标注主 agent 审查。
|
|
87
97
|
|
|
88
98
|
首次审查覆盖本次完整 PR diff 及必要上下文。每轮完成后都向 PR 发布 Code Review 结果评论,包括审查方式、实际审查者、被审查 head SHA、覆盖范围、发现及结论;无发现也要留下记录。每条发现给出严重程度、文件位置、触发条件、影响与修复建议。
|
|
89
99
|
|
|
90
100
|
存在有效问题时完成修复并推送,在 PR 发布修复报告评论:逐项关联发现、说明修复内容、提交与验证结果;不采纳的意见写明证据和理由。阻塞验收或影响正确性、安全的未解决问题不能转成 follow-up 后视为通过。
|
|
91
101
|
|
|
92
|
-
修复后判断是否需要再次 Code Review
|
|
102
|
+
修复后判断是否需要再次 Code Review:修改行为、接口、数据/并发逻辑,修复重大问题,或引入新风险时必须由主 agent 复审。复审覆盖修复增量与受影响调用方,范围扩大时重新覆盖完整 diff,并发布新一轮审查评论。纯文字或不改变行为的修正可核对后不再审查,但在修复报告中写明理由。主 agent 持续修复和复审直至阻塞性发现解决,不再增加第三方有效调用次数。
|
|
93
103
|
|
|
94
104
|
## 7. 最终运行、编译与测试验证
|
|
95
105
|
|
|
@@ -126,11 +136,11 @@ Issue/PR 正文及评论优先使用结构化工具参数;使用 CLI 时将多
|
|
|
126
136
|
|
|
127
137
|
| Follow-up 状态 | 处理 |
|
|
128
138
|
| --- | --- |
|
|
129
|
-
| 无阻塞,代码与所需资源均可用 | 直接创建独立 worktree
|
|
139
|
+
| 无阻塞,代码与所需资源均可用 | 直接创建独立 worktree,调用 `delegate_3th` 委托完整交付,要求执行 `ship-issue-pr` 同一套流程 |
|
|
130
140
|
| 依赖当前 PR、其他任务或尚未满足的条件 | 在 Issue 按项目支持的状态/标签标记等待,写明阻塞对象与解除条件;条件满足后再派发 |
|
|
131
141
|
| 需要额外外部资源、人工决策、账号或权限 | 只创建 Issue 并列出需要谁提供什么,不派发执行者 |
|
|
132
142
|
|
|
133
|
-
主线程维护后续队列,记录 Issue、状态、依赖、worktree
|
|
143
|
+
主线程维护后续队列,记录 Issue、状态、依赖、worktree、委托标识与交付进度,避免重复派发。运行中的依赖完成、当前 PR 合并或收到条件变更时重查等待项;如需跨会话等待,使用宿主可用的持久任务/提醒机制,记录唤醒条件与检查方式。宿主不支持持久等待时,将等待项与恢复条件明确交付,不能声称会自动唤醒。
|
|
134
144
|
|
|
135
145
|
子任务采用各自责任范围与正确基线,交接 Issue、验收、项目规则和完整交付终点。依赖父 PR 时等合并后从最新基线派发。子任务发现新问题仍创建 follow-up Issue,交回主线程统一去重与调度,避免重复或递归派发。外部资源后来齐备时,重新判断阻塞并进入可派发队列。
|
|
136
146
|
|
|
@@ -138,76 +148,17 @@ Issue/PR 正文及评论优先使用结构化工具参数;使用 CLI 时将多
|
|
|
138
148
|
|
|
139
149
|
最终报告实际终点、本次改动、复杂度、第三方执行情况、审查/修复/验证评论链接、Issue/PR 状态,以及 follow-up 的已派发、等待和外部资源清单。已设置自动合并与已合并分别陈述;有阻塞时明确停在哪一步、缺什么以及恢复条件。
|
|
140
150
|
|
|
141
|
-
##
|
|
151
|
+
## 第三方协作接口
|
|
142
152
|
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
| 当前宿主 | 需要外部协作时使用 |
|
|
153
|
+
| 工作 | 调用技能 |
|
|
146
154
|
| --- | --- |
|
|
147
|
-
|
|
|
148
|
-
|
|
|
149
|
-
| 其他或外部工具不可用 | 简单任务由当前执行者完成;复杂任务记录第三方通道阻塞,按第 4 步处理 |
|
|
150
|
-
|
|
151
|
-
简单任务直接推进。复杂任务必须使用当前宿主对应的第三方通道:Codex 调用 Claude Code,Claude Code 调用 Codex。普通同宿主 sub-agent 可承接 follow-up,但不替代复杂任务的第三方步骤。外部执行者接手的是分配范围,完整交付与事实核验仍由主线程负责。
|
|
152
|
-
|
|
153
|
-
## Codex 运行时
|
|
154
|
-
|
|
155
|
-
以下工具仅适用于 Codex 宿主确实需要 Claude 协作或已授权的后续委派时;交付范围、权限、验证复用与完成条件遵循共享流程。
|
|
156
|
-
|
|
157
|
-
### Claude 路由
|
|
158
|
-
|
|
159
|
-
| 工作 | 技能 |
|
|
160
|
-
| --- | --- |
|
|
161
|
-
| 方案咨询、普通审查、对抗审查 | [ask_cc](../ask_cc/SKILL.md) |
|
|
162
|
-
| 已明确范围的实现与修复 | [delegate-cc](../delegate-cc/SKILL.md) 的 `task` 模式 |
|
|
163
|
-
|
|
164
|
-
用户显式调用统一入口后,可在其任务范围内调用这些依赖。只读取当前模式的必要说明。CLI 参数、模型顺序、认证、权限、状态解析和接续规则由依赖技能维护,不在这里复制。
|
|
165
|
-
|
|
166
|
-
`ask_cc` 的咨询模式无工具权限。交接提供问题、相关源码与 diff、路径和必要验证结果;首次完整审查覆盖本次 PR diff,后续只补增量及其影响,不要求咨询方自行读仓库。证据不足时主进程补充材料。
|
|
167
|
-
|
|
168
|
-
独立审查不复用实现或修复会话;主进程自审不得冒充独立审查。报告 findings 的位置、条件、影响与建议,主进程核验关键证据。
|
|
169
|
-
|
|
170
|
-
执行任务提供工作目录、可修改文件或模块、项目指令与实际验收命令。明确存在其他协作者,只负责分配范围,保留他人修改。需要运行验证时按依赖技能设置具体允许命令。
|
|
171
|
-
|
|
172
|
-
### 等待、验收与后续任务
|
|
173
|
-
|
|
174
|
-
保存会话 ID,读取同一任务的流式结果;静默或宿主单次等待超时先排查,接管前确保原写进程停止。依赖缺失或确实无法运行时按第 4 步记录阻塞与已完成成果,不能把降级接手计为第三方完成。
|
|
175
|
-
|
|
176
|
-
可核实的验证结果按共享流程复用,不因来自其他执行者而全部重跑。
|
|
177
|
-
|
|
178
|
-
对第 9 步已满足派发条件的 follow-up,使用 `spawn_agent` 的可用角色,prompt 指定独立 worktree、Issue、目标、交付终点和责任文件,并要求调用 `ship-issue-pr`。子任务发现新问题创建或复用 Issue,交回主线程统一调度。
|
|
179
|
-
|
|
180
|
-
## Claude Code 运行时
|
|
181
|
-
|
|
182
|
-
以下工具仅适用于 Claude Code 宿主确实需要 Codex 协作或已授权的后续委派时;交付范围、权限、验证复用与完成条件遵循共享流程。
|
|
183
|
-
|
|
184
|
-
### Codex 通道
|
|
185
|
-
|
|
186
|
-
先使用当前会话已暴露的插件能力。已安装对应 Codex 插件时,可用:
|
|
187
|
-
|
|
188
|
-
- 方案咨询、实现或定制审查:`Agent(subagent_type: "codex:codex-rescue")`,在任务书中明确只读或可写责任范围。
|
|
189
|
-
- 普通审查:Codex companion 的 `review`。
|
|
190
|
-
- 需要挑战方案假设时:companion 的 `adversarial-review`。
|
|
191
|
-
|
|
192
|
-
通道不可用时按第 4 步记录复杂任务的阻塞,并继续可独立完成的准备。
|
|
193
|
-
|
|
194
|
-
### companion 与结果
|
|
195
|
-
|
|
196
|
-
使用插件提供的实际路径。需要定位时,仅检查当前 Claude 配置目录内对应的 marketplace/cache 路径;常见默认位置是 `~/.claude/plugins/marketplaces/openai-codex/plugins/codex` 或 `~/.claude/plugins/cache/openai-codex/codex/<version>`。以实际安装版本与 `scripts/codex-companion.mjs --help` 核实参数,不硬编码某个缓存版本。
|
|
197
|
-
|
|
198
|
-
确认后通过宿主异步工具运行,例如:
|
|
199
|
-
```bash
|
|
200
|
-
node "<plugin-root>/scripts/codex-companion.mjs" review --wait --base "<actual-base>"
|
|
201
|
-
```
|
|
202
|
-
|
|
203
|
-
保存本次返回的 job/agent ID、worktree 和输出位置,持续观察同一任务。返回报告仍需核对 diff、验收范围与验证证据。
|
|
204
|
-
|
|
205
|
-
### 责任与验证
|
|
155
|
+
| 方案咨询、Code Review、对抗审查 | [ask_3th](../ask_3th/SKILL.md) |
|
|
156
|
+
| 已明确范围的实现、修复或独立后续任务 | [delegate_3th](../delegate_3th/SKILL.md) 的 `task` 模式 |
|
|
206
157
|
|
|
207
|
-
|
|
158
|
+
用户显式调用本流程后,可在原任务范围与已有授权内调用上述依赖。运行时、模型、失败回退和执行者调度全部由依赖技能内部处理。本流程只提交任务、等待最终结果、验收,并将返回的执行说明附在报告中。
|
|
208
159
|
|
|
209
|
-
|
|
160
|
+
咨询提供问题、相关源码与 diff、路径和必要验证结果,标明只读及独立审查要求;首次审查覆盖本次完整 PR diff,复审补充增量和影响。证据不足时补充材料。
|
|
210
161
|
|
|
211
|
-
|
|
162
|
+
执行提供工作目录、责任文件、项目规则、已有成果、验收标准及实际验证命令。本次 PR 的实现者只负责分配范围,Git/GitHub 交付仍由主线程完成;独立 follow-up 的委托则明确授权完整交付,要求执行 `ship-issue-pr`,新发现的后续问题交回主线程统一调度。
|
|
212
163
|
|
|
213
|
-
|
|
164
|
+
保留委托标识并等待同一调用完成。收到结果后核对事实与验证证据,复用仍有效的验证;执行说明用于如实记录,不根据其内部通道或回退情况另设验收门槛。
|
package/skills/ask_cc/SKILL.md
DELETED
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: ask_cc
|
|
3
|
-
description: 仅在显式调用 ask_cc 时使用:咨询 Claude Code 获取第二意见。
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# ask_cc
|
|
7
|
-
|
|
8
|
-
## 执行边界与优先级
|
|
9
|
-
|
|
10
|
-
在宿主系统与开发者指令约束内,冲突时依次采用:当前任务的具体要求与已有授权 > 目标项目适用的 AGENTS.md > 本技能及其引用的通用流程。
|
|
11
|
-
只读检索、本地草稿、可回滚编辑和常规测试可自主推断并继续;从相关文件和直接依赖开始,仅在证据不足或影响跨模块时扩大范围,复用仍有效的验证。
|
|
12
|
-
仅在不可逆或难以回滚的修改缺少具体授权时,先完成预览、草稿与验证,再说明对象和影响并等待确认;会话中已有授权继续有效。缺少事实时先查证、标注假设并推进独立工作,确实无法确定操作目标时才询问。对外发送消息须有明确授权。
|
|
13
|
-
|
|
14
|
-
使用 [delegate-cc](../delegate-cc/SKILL.md) 的咨询流程获取答案或第二意见,默认不授予工具权限。
|
|
15
|
-
|
|
16
|
-
已显式调用的 `ship-issue-pr` 需要咨询时可进入本技能,沿用原任务范围与授权。
|
|
17
|
-
|
|
18
|
-
调用前读取该技能的咨询调用与结果处理部分,按需查看诊断和接续规则。咨询没有文件修改是正常现象,以本次会话的流式输出和进程状态辅助判断;静默只触发排查,不能仅因尚无答案就停止或换模型。
|
|
19
|
-
|
|
20
|
-
若用户明确要求修改代码或执行开发任务,转入该技能的 `task` 模式,按任务范围完成实现和验收。
|
|
21
|
-
|
|
22
|
-
旧命令 `scripts/ask_cc.py --prompt-file /绝对路径/问题.txt` 继续可用,仅运行咨询模式;模型顺序和降级逻辑复用 `delegate-cc`。
|
|
23
|
-
|
|
24
|
-
旧入口的 `--timeout` 同样表示无活动告警阈值(默认 120 秒),不是答复截止时间。通过宿主异步工具保留原会话并持续取结果;只有原调用已退出且结果无效或失败时,脚本才尝试下一个模型。
|
|
25
|
-
|
|
26
|
-
`dx initial` 会同时安装这两个技能。使用当前 `SKILL.md` 所在目录下的脚本;默认安装后的调用方式:
|
|
27
|
-
|
|
28
|
-
```bash
|
|
29
|
-
python3 "$HOME/.agents/skills/ask_cc/scripts/ask_cc.py" --prompt-file /绝对路径/问题.txt
|
|
30
|
-
```
|
|
@@ -1,66 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: delegate-cc
|
|
3
|
-
description: 仅在显式调用 delegate-cc 时使用:委派 Claude Code 执行开发任务或咨询。
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# delegate-cc
|
|
7
|
-
|
|
8
|
-
## 执行边界与优先级
|
|
9
|
-
|
|
10
|
-
在宿主系统与开发者指令约束内,冲突时依次采用:当前任务的具体要求与已有授权 > 目标项目适用的 AGENTS.md > 本技能及其引用的通用流程。
|
|
11
|
-
只读检索、本地草稿、可回滚编辑和常规测试可自主推断并继续;从相关文件和直接依赖开始,仅在证据不足或影响跨模块时扩大范围,复用仍有效的验证。
|
|
12
|
-
仅在不可逆或难以回滚的修改缺少具体授权时,先完成预览、草稿与验证,再说明对象和影响并等待确认;会话中已有授权继续有效。缺少事实时先查证、标注假设并推进独立工作,确实无法确定操作目标时才询问。对外发送消息须有明确授权。
|
|
13
|
-
|
|
14
|
-
把 Claude Code 当作协作者。模型顺序固定为 Fable 5.1(`claude-fable-5-1`)→ Opus 5(`claude-opus-5`)→ 当前 sub-agent。保留本机现有认证。
|
|
15
|
-
|
|
16
|
-
已显式调用的 `ask_cc` 或 `ship-issue-pr` 需要委派时可进入本技能,沿用原任务范围与授权。
|
|
17
|
-
|
|
18
|
-
## 1. 准备交接
|
|
19
|
-
|
|
20
|
-
- **咨询 `consult`**:用户需要答案、决策建议或评审意见。提供问题、相关代码或事实、约束;CLI 无工具权限,只返回建议。
|
|
21
|
-
- **执行 `task`**:用户要求实现、修复或把开发任务交给 CC。任务书必须包含工作目录、目标、可修改文件或模块、适用的项目指令、验收标准和仓库实际验证命令。明确告知 CC 还有其他协作者,保留他人的改动,只负责分配范围。
|
|
22
|
-
|
|
23
|
-
执行前检查 `git status --short` 和任务涉及文件的 diff,记录这些文件的初始状态及相关未跟踪文件。分配互不重叠的文件;需要并发改同一文件时,先拆分责任或使用独立 worktree,指定由谁整合。worktree 不会自动携带未提交改动,必须提供任务所需的当前版本。CC 执行期间,主 agent 不同时修改其负责的文件。
|
|
24
|
-
|
|
25
|
-
将任务书写入临时 UTF-8 文件,只传必要上下文,排除凭据。完成条件:CC 无需当前对话即可理解目标、权限范围与完成标准。
|
|
26
|
-
|
|
27
|
-
## 2. 调用 CLI
|
|
28
|
-
|
|
29
|
-
需要本机提供 `python3` 和已完成认证的 `claude` CLI;`dx initial` 只同步技能文件,不安装运行时或配置认证。
|
|
30
|
-
|
|
31
|
-
运行当前 `SKILL.md` 所在目录下的 `scripts/delegate_cc.py`。以下路径适用于 `dx initial` 的默认安装位置;通过其他方式安装时使用实际技能目录:
|
|
32
|
-
|
|
33
|
-
```bash
|
|
34
|
-
# 咨询:默认模式,无活动告警阈值默认 120 秒。
|
|
35
|
-
python3 "$HOME/.agents/skills/delegate-cc/scripts/delegate_cc.py" --prompt-file /绝对路径/问题.txt
|
|
36
|
-
|
|
37
|
-
# 执行:必须指定工作目录,无活动告警阈值默认 900 秒。
|
|
38
|
-
python3 "$HOME/.agents/skills/delegate-cc/scripts/delegate_cc.py" --mode task --cwd /绝对路径/工作区 --prompt-file /绝对路径/任务.txt
|
|
39
|
-
```
|
|
40
|
-
|
|
41
|
-
需要 CC 自行运行验证命令时,按本次授权追加 `--allow-command '仓库实际验证命令'`,可重复传入。使用具体命令而非开放全部 Bash;根据命令和已知脚本判断副作用,仅对未知或可能破坏数据的脚本进一步检查。现有 Claude Code 权限规则仍生效,`--allow-command` 只是增加允许规则,不是独立沙箱。文件责任范围通过任务书和验收控制,需要隔离时使用 worktree 或已有沙箱。
|
|
42
|
-
|
|
43
|
-
执行模式保留默认编码系统提示,开放 `Read,Glob,Grep,Edit,Write,Bash`,使用 `acceptEdits`,不能获批的工具请求自动拒绝。两种模式都关闭 hooks、MCP 和技能,避免额外任务链;主 agent 应把所需项目规则及技能要求写入任务书。本技能不使用 `bypassPermissions`,也不扩大任务至提交、推送、部署或对外发送消息。
|
|
44
|
-
|
|
45
|
-
通过工具异步运行,至少每 60 秒向用户汇报进度,保留会话 ID。脚本读取流式输出,并比较工作目录中文件的大小和纳秒级修改/变更时间,能识别同一文件持续编辑;stderr 输出 PID、输出字节数、静默时长及观测可用性,不转发原始敏感日志。任务退出后 stdout 仍返回单个 JSON 结果。
|
|
46
|
-
|
|
47
|
-
`--timeout` 现表示无活动告警阈值,保留参数名和默认秒数;原先依赖它限制总运行时间的调用方应迁移为活性监控。达到阈值仅提示疑似停滞,脚本继续运行,不自动杀进程或换模型。输出或文件变化会重置静默计时;文件观测只覆盖 Git 跟踪及未忽略的新文件,忽略目录中的测试产物需由主进程另查。观测不可用不表示无活动,日志字节增长也需排除重复错误和空心跳。
|
|
48
|
-
|
|
49
|
-
静默告警后主进程检查原会话、日志和子命令,区分推理/测试、权限等待与实际故障;有进展则继续,无进展但证据不足则报告状态并保持任务。诊断证实无法推进时先尝试恢复原任务,必要时显式中断脚本并确认任务进程组已停止,再按下一节接续。宿主单次等待超时只继续读取同一会话,不设置固定总时长的自动终止器。完成条件:获得 JSON 结果或明确的执行失败,旧进程已结束。
|
|
50
|
-
|
|
51
|
-
## 3. 验收或接续
|
|
52
|
-
|
|
53
|
-
- `ok`:咨询获得答案;检查是否回应原问题,不能把空泛回复当作完成。
|
|
54
|
-
- `review_required`:执行已返回报告,尚待主 agent 验收。对照初始状态检查 diff、新文件及责任范围,运行必要的格式化、检查和测试。发现越界修改时先核对归属,只修正本次 CC 引入的变化。`permission_denials` 非零时核实未执行工作,使用已获授权的宿主工具完成,或准确报告实际权限阻塞。
|
|
55
|
-
- `continuation_required`:任务可能已部分执行。先检查现有 diff、测试状态及外部副作用;更新任务书为“保留已完成部分,仅完成剩余工作”。若 `next_model` 有值,以 `--start-model` 传入该值接续;每个模型最多尝试一次。禁止将同一任务从头盲目重放。
|
|
56
|
-
- `fallback_required`、第二模型也失败或 CLI 无法运行:当前执行者已经是 sub-agent 时直接接手;主 agent 则委派一个继承当前模型的 sub-agent,环境不支持委派时自己接手。提供原任务、已完成改动和剩余工作,明确跳过本技能及 CLI,避免递归。权限拒绝不能靠切换模型绕过。
|
|
57
|
-
|
|
58
|
-
咨询模式只有在原调用已退出且失败或结果无效后,脚本才尝试下一个模型;执行模式每次只运行一个模型,由主 agent 检查现场后接续。尚未返回、静默告警和宿主等待超时均不触发降级。认证、额度和模型不可用也不等于任务完成。
|
|
59
|
-
|
|
60
|
-
完成条件:咨询得到实质答案,或执行任务的代码和验证满足验收标准;仍有缺口时明确列出,而非仅转述 CC 的成功声明。
|
|
61
|
-
|
|
62
|
-
## 4. 交付
|
|
63
|
-
|
|
64
|
-
用简体中文说明答案或实际改动、验证结果、未完成项,简短注明使用的模型及降级情况。`requested_model` 是请求 ID,不保证服务端未自动切换模型。清理本次临时任务文件;保留仍有成果待整合的 worktree。
|
|
65
|
-
|
|
66
|
-
参数或模型出错时核对本机 `claude --help`、[CLI 参考](https://code.claude.com/docs/en/cli-reference)和[模型 ID](https://platform.claude.com/docs/en/models/overview)。用 `claude auth status` 区分认证状态,`unrecognized_model` 不表示未登录。
|
|
File without changes
|
|
File without changes
|
/package/skills/{delegate-cc → delegate_3th}/scripts/__pycache__/delegate_cc.cpython-314.pyc
RENAMED
|
File without changes
|
/package/skills/{delegate-cc → delegate_3th}/scripts/__pycache__/test_delegate_cc.cpython-314.pyc
RENAMED
|
File without changes
|