@fuxi-ailabs/dsh-ecat 0.0.0-stage → 0.1.0-alpha.1
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/LICENSE +21 -0
- package/README.md +151 -3
- package/assets/skills/ecat-refine/SKILL.md +126 -0
- package/assets/skills/ecat-refine/config.claudecode.yaml +101 -0
- package/assets/skills/ecat-refine/config.deveco.yaml +109 -0
- package/assets/skills/ecat-refine/config.dsh.yaml +104 -0
- package/assets/skills/ecat-refine/config.opencode.yaml +115 -0
- package/assets/skills/ecat-refine/scripts/_cli_path.py +100 -0
- package/assets/skills/ecat-refine/scripts/_proc.py +82 -0
- package/assets/skills/ecat-refine/scripts/preflight.py +372 -0
- package/assets/skills/ecat-refine/scripts/start.py +121 -0
- package/assets/skills/ecat-refine/scripts/stop.py +65 -0
- package/assets/skills/ecat-refine/scripts/watch.py +267 -0
- package/assets/skills/ecat-setup/SKILL.md +220 -0
- package/assets/skills/ecat-setup/references/plugin-design.md +111 -0
- package/assets/skills/ecat-setup/scripts/_profile.py +104 -0
- package/assets/skills/ecat-setup/scripts/check.py +394 -0
- package/assets/skills/ecat-setup/scripts/plugins.py +478 -0
- package/assets/skills/ecat-setup/scripts/seeds.py +244 -0
- package/assets/skills/ecat-setup/scripts/setup.py +543 -0
- package/assets/wheels/ecat-0.1.0-py3-none-any.whl +0 -0
- package/cordis.patch.yml +10 -0
- package/icon.svg +6 -0
- package/locale/en.json +6 -0
- package/locale/zh.json +6 -0
- package/package.json +54 -4
- package/src/ecat.js +212 -0
- package/src/plugin.js +326 -0
- package/src/probe_deps.py +128 -0
- package/src/proc.js +55 -0
- package/src/skills.js +108 -0
- package/src/venv.js +117 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Fuxi AI Labs
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,3 +1,151 @@
|
|
|
1
|
-
#
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
# @fuxi-ailabs/dsh-ecat
|
|
2
|
+
|
|
3
|
+
Two DSH commands over the ECAT refinement loop.
|
|
4
|
+
|
|
5
|
+
| Command | What it does |
|
|
6
|
+
|---|---|
|
|
7
|
+
| `/ecat-setup` | Hands a prompt to the agent, which runs the `ecat-setup` skill: interview, profile, scoring plugins |
|
|
8
|
+
| `/ecat-refine` | Runs the `ecat-refine` scripts directly: `status`, `open`, `preflight`, `start`, `stop` |
|
|
9
|
+
|
|
10
|
+
`/ecat-setup` never writes files itself — every write goes through the agent, so the normal
|
|
11
|
+
approval and sandbox rules apply. `/ecat-refine` only executes fixed subcommands with an
|
|
12
|
+
argv array; the raw input is never passed to a shell.
|
|
13
|
+
|
|
14
|
+
## Install
|
|
15
|
+
|
|
16
|
+
```
|
|
17
|
+
dsh plugin --profile <profile> add @fuxi-ailabs/dsh-ecat
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
Or add the market index source and install from the discovers page. The package is MIT
|
|
21
|
+
licensed; its full contents are the two skills, the ECAT wheel, and the command code.
|
|
22
|
+
|
|
23
|
+
## Requirements
|
|
24
|
+
|
|
25
|
+
- DSH `^0.2.1-rc.2`
|
|
26
|
+
- Python 3.11+ somewhere on the host (`python3`, `python`, or the `py` launcher)
|
|
27
|
+
|
|
28
|
+
ECAT itself is not a prerequisite: the package ships `assets/wheels/ecat-*.whl` and
|
|
29
|
+
`/ecat-setup` creates `~/.dsh/ecat-venv`, installs the wheel into it with `uv pip`
|
|
30
|
+
(falling back to `python -m venv` + `pip`), and points every later command at that
|
|
31
|
+
interpreter. Dependencies are resolved from the network on that first run, which is why
|
|
32
|
+
the installation lives in setup rather than in the loop commands: configuration is the
|
|
33
|
+
point where a missing environment should surface, not the first status check.
|
|
34
|
+
|
|
35
|
+
If the environment cannot be prepared, `/ecat-setup` fails before asking any questions
|
|
36
|
+
and reports the uv and pip errors; `/ecat-refine` has no install step of its own.
|
|
37
|
+
|
|
38
|
+
If you already installed ECAT globally (`uv tool install --editable <repo>`), the plugin
|
|
39
|
+
uses that interpreter instead and never creates a venv.
|
|
40
|
+
|
|
41
|
+
## Configuration
|
|
42
|
+
|
|
43
|
+
| Key | Default | Meaning |
|
|
44
|
+
|---|---|---|
|
|
45
|
+
| `pythonPath` | auto | Interpreter to use. When set it always wins, broken or not. |
|
|
46
|
+
| `ecatPath` | `ecat` | The CLI, used only for preflight's availability check. |
|
|
47
|
+
| `workspaceRoot` | empty | Fixed ECAT workspace; otherwise the hand-off file or session cwd. |
|
|
48
|
+
| `uvPath` | `uv` | Used by `/ecat-setup` to build the venv. Falls back to `python -m venv`. |
|
|
49
|
+
|
|
50
|
+
`ECAT_VENV_DIR` relocates the managed environment; tests and multi-user machines use it.
|
|
51
|
+
|
|
52
|
+
## Usage
|
|
53
|
+
|
|
54
|
+
```
|
|
55
|
+
/ecat-setup
|
|
56
|
+
/ecat-setup help
|
|
57
|
+
/ecat-refine status
|
|
58
|
+
/ecat-refine preflight
|
|
59
|
+
/ecat-refine start
|
|
60
|
+
/ecat-refine open
|
|
61
|
+
/ecat-refine stop
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
Both commands advertise their arguments in the composer hint as soon as you type the
|
|
65
|
+
name: `/ecat-setup [help | <task description>]` and
|
|
66
|
+
`/ecat-refine [help | status | open | start | stop | preflight] [workspace]`.
|
|
67
|
+
|
|
68
|
+
`/ecat-refine` with no subcommand prints the same list as `/ecat-refine help`.
|
|
69
|
+
`/ecat-refine run` starts the runtime-selection conversation explicitly.
|
|
70
|
+
|
|
71
|
+
Help output is echoed back through one agent turn. DSH's chat view treats a session
|
|
72
|
+
whose only nodes are commands as blank and shows the welcome screen, so a command
|
|
73
|
+
that merely returns text stays invisible until something creates a conversation turn.
|
|
74
|
+
|
|
75
|
+
### Worked example — `/ecat-setup help`
|
|
76
|
+
|
|
77
|
+
The environment check lives here, not on `/ecat-refine`, because that is where you go
|
|
78
|
+
when you want to know whether the Python side is usable and where a short wait is
|
|
79
|
+
expected. Real output, DSH `0.2.1-rc.2`, plugin `0.1.0-alpha.1`, Windows:
|
|
80
|
+
|
|
81
|
+
```
|
|
82
|
+
Usage: /ecat-setup [help | <task description>]
|
|
83
|
+
no argument interview me about the task, then write profile and plugins
|
|
84
|
+
<text> same, reusing what this message already says about the task
|
|
85
|
+
help this text, plus whether every ECAT dependency is usable
|
|
86
|
+
|
|
87
|
+
interpreter: C:\Users\me\.dsh\ecat-venv\Scripts\python.exe
|
|
88
|
+
python: 3.11.13
|
|
89
|
+
environment: ready — all 13 runtime dependencies usable
|
|
90
|
+
anthropic 2.1.0
|
|
91
|
+
typer 0.27.3
|
|
92
|
+
...
|
|
93
|
+
ecat: C:\Users\me\.dsh\ecat-venv\Lib\site-packages\ecat\__init__.py
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
The list is not hard-coded: `src/probe_deps.py` reads the installed wheel's own
|
|
97
|
+
`Requires-Dist` entries through `importlib.metadata`, so a dependency added to
|
|
98
|
+
`pyproject.toml` is covered the next time the wheel is built. Each entry is
|
|
99
|
+
checked for presence, for the version range the wheel asks for, and for a
|
|
100
|
+
resolvable top-level module. A failure names the package and how to fix it:
|
|
101
|
+
|
|
102
|
+
```
|
|
103
|
+
environment: NOT ready — 2 of 13 dependencies failed
|
|
104
|
+
openpyxl is not installed
|
|
105
|
+
pydantic has version 2.6.1, needs pydantic>=2.7
|
|
106
|
+
fix with: <interpreter> -m pip install openpyxl
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
This is deliberately not `import ecat`: `ecat/__init__.py` is a version string,
|
|
110
|
+
so importing it succeeds with every third-party package missing. `resolvePython`
|
|
111
|
+
uses the same probe when it chooses an interpreter, so a half-installed
|
|
112
|
+
environment is never picked for `status`, `start`, or anything else.
|
|
113
|
+
|
|
114
|
+
Before the first setup it reads `environment: NOT ready — <venv> does not exist.` and
|
|
115
|
+
tells you to run `/ecat-setup` with no argument. Nothing is installed and no interview
|
|
116
|
+
starts from `help`.
|
|
117
|
+
|
|
118
|
+
### Worked example — `/ecat-refine help`
|
|
119
|
+
|
|
120
|
+
```
|
|
121
|
+
Usage: /ecat-refine [status|open|start|stop|preflight] [workspace]
|
|
122
|
+
status latest run: H, iterations, worst dimension (default)
|
|
123
|
+
...
|
|
124
|
+
No subcommand runs the loop: the agent picks the runtime with you first.
|
|
125
|
+
Check the environment with /ecat-setup help; /ecat-refine has no install step.
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
This is synchronous — it does not spawn Python, so it answers immediately even when
|
|
129
|
+
no interpreter can import ECAT.
|
|
130
|
+
|
|
131
|
+
### Worked example — a common failure
|
|
132
|
+
|
|
133
|
+
`/ecat-refine status` with no workspace configured and no hand-off file:
|
|
134
|
+
|
|
135
|
+
```
|
|
136
|
+
kind: error
|
|
137
|
+
No ECAT workspace found. Run /ecat-setup first, pass it explicitly
|
|
138
|
+
(/ecat-refine status <workspace>), or set workspaceRoot in the plugin config.
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
This is the path a first-time user hits; it names all three ways to resolve it rather
|
|
142
|
+
than silently reading the session's cwd, which could start the loop on the wrong tree.
|
|
143
|
+
|
|
144
|
+
## Failure modes
|
|
145
|
+
|
|
146
|
+
| Symptom | Cause |
|
|
147
|
+
|---|---|
|
|
148
|
+
| `No ECAT workspace found` | `/ecat-setup` has not run and no workspace was passed |
|
|
149
|
+
| `spawn failed: ENOENT` | `pythonPath` does not exist on the DSH host |
|
|
150
|
+
| preflight `exit 15` | `ecat` is not on the host PATH |
|
|
151
|
+
| preflight `exit 13` | the variable named by `api_key_env` has no value in `<ws>/.env` |
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: ecat-refine
|
|
3
|
+
description: 启动、监控、停止 ECAT 的 Android→HarmonyOS 对抗式迁移循环(ecat refine)。当用户说"跑一下 ECAT""继续优化鸿蒙仓""跑迁移修复循环""ECAT 跑到哪了""看看熵降到多少了""停掉 ECAT"时触发。也用于跑之前检查 ECAT 配置是否符合预期。这是小时级后台任务,本 skill 只负责启停与查询,不会同步等待。
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# ecat-refine
|
|
7
|
+
|
|
8
|
+
驱动 ECAT:生成器改鸿蒙代码、判别器打分算熵(H),逐轮对抗直到收敛。
|
|
9
|
+
|
|
10
|
+
## 这是长任务,绝不要同步等
|
|
11
|
+
|
|
12
|
+
一轮的耗时由 target 规模、维度数量和模型速度决定,从几分钟到几十分钟不等;轮次上限默认 300。启动脚本后台跑并立即返回;之后每次想知道进展就调一次 `watch.py`,它秒回。
|
|
13
|
+
|
|
14
|
+
**永远不要**用 `ecat refine` 直接前台跑,也不要在等待循环里反复 sleep。
|
|
15
|
+
|
|
16
|
+
## 第零步:先问用户跑哪个 runtime,打印 config 路径让用户确认
|
|
17
|
+
|
|
18
|
+
**先分清两份配置**:`ecat-setup` 写的是 `<WS>/ecat.config.yaml`(你的 profile、插件集、
|
|
19
|
+
权重、路径),四份 `config.*.yaml` 只是 **runtime preset**(决定用哪个 CLI、endpoint 怎么走)。
|
|
20
|
+
`preflight.py` / `start.py` **默认读 workspace 那份**;只有第一次在某台机器上试跑、或
|
|
21
|
+
workspace 里还没有 `ecat.config.yaml` 时才用 preset。
|
|
22
|
+
|
|
23
|
+
如果 workspace 里已有 `ecat.config.yaml` 而你又显式传了 preset,preflight 会 WARN 并
|
|
24
|
+
列出被忽略的键(`profile` / `entropy.plugin_set` / `paths.target`)——看到这条就别继续。
|
|
25
|
+
|
|
26
|
+
1. **问用户用哪个 runtime**(四选一,列出来让用户选):
|
|
27
|
+
|
|
28
|
+
| 选项 | preset | 说明 |
|
|
29
|
+
|---|---|---|
|
|
30
|
+
| Claude Code | `config.claudecode.yaml` | 走 `claude` CLI + DeepSeek 的 Anthropic 兼容层。可观测性完整(stream-json 事件流、会话续跑、多目录访问) |
|
|
31
|
+
| opencode | `config.opencode.yaml` | 走 `opencode` CLI + OpenAI 兼容端点。**已知降级**:`generator_compact_interval` 无效;附加目录靠公共祖先合并成单个 `--dir` |
|
|
32
|
+
| deveco | `config.deveco.yaml` | 走 `deveco` CLI(npm `@deveco/deveco-code`,opencode 的 fork)+ OpenAI 兼容端点。配置 schema / 事件流 / 429 软中止与 opencode 同构;**已知降级**:同 opencode(`generator_compact_interval` 无效) |
|
|
33
|
+
| DeepSeek Harness | `config.dsh.yaml` | 走 `dsh --profile headless` 的一次性模式(npm `@deepseek-ai/dsh`)。**两处特殊**:`base_url` 必须留空(端点由 dsh 的 profile 决定,配了会被 ECAT 拒绝);模型靠每次调用的临时 patch 指定。**已知降级**:`generator_compact_interval` 无效(无会话内压缩),改由 dsh 自带的 compaction-basic 接管;`.ecat/agents/*/agents/*.md` 不会被加载,judge 的 rubric 走派发提示词 |
|
|
34
|
+
|
|
35
|
+
2. **打印实际会用的 config 绝对路径**,念给用户确认:workspace 有 `ecat.config.yaml` 时
|
|
36
|
+
就是它;没有时才念所选 preset 的路径。
|
|
37
|
+
|
|
38
|
+
3. **用户确认后**才执行 preflight(体检)+ start(启动)。未确认/用户选别的,不要擅自跑。
|
|
39
|
+
|
|
40
|
+
四份 preset 的差异只在 runtime / base_url / api_key_env / model(deveco 与 opencode
|
|
41
|
+
同构,仅 runtime 字段和命令名不同),其余调参完全一致。**`ecat-setup` 已把这些键写进
|
|
42
|
+
`<WS>/ecat.config.yaml`,不要用 preset 覆盖它。**
|
|
43
|
+
|
|
44
|
+
> 选 `dsh` 时额外确认两件事:`dsh` 在 PATH 上(`npm i -g @deepseek-ai/dsh`),以及 `.env` 里有 `DEEPSEEK_API_KEY`。首次运行会在 `.ecat/agents/<role>/` 下自动生成 DSH 的 profile 和 `AGENTS.md`——preflight 会提示"尚未生成",那是正常的。
|
|
45
|
+
|
|
46
|
+
> 确认依据:跑 `preflight.py` 会打印「── 确认 ──」段(runtime + config 绝对路径),**把它念给用户确认后再执行 start.py**。preflight 不是确认,它只是体检;发车前的确认以用户点头为准。
|
|
47
|
+
|
|
48
|
+
## 四步
|
|
49
|
+
|
|
50
|
+
全部是 Python 脚本(Windows / Linux / macOS 通用,不需要 bash)。
|
|
51
|
+
`S` = 本 skill 目录,`WS` = ECAT 工作区根目录。
|
|
52
|
+
|
|
53
|
+
```
|
|
54
|
+
# CFG = config.claudecode.yaml / config.opencode.yaml / config.deveco.yaml / config.dsh.yaml(第零步问出来的)
|
|
55
|
+
|
|
56
|
+
# 1. 体检(必做)—— 摊开"实际会怎么跑",逐项对现实核验
|
|
57
|
+
python <S>/scripts/preflight.py --config <S>/<CFG> --workspace <WS>
|
|
58
|
+
|
|
59
|
+
# 2. 启动(体检 exit 0 之后)
|
|
60
|
+
python <S>/scripts/start.py --config <S>/<CFG> --workspace <WS>
|
|
61
|
+
|
|
62
|
+
# 3. 查进度(随时,秒回)
|
|
63
|
+
python <S>/scripts/watch.py --workspace <WS>
|
|
64
|
+
# 想让用户看曲线:加 --open 用默认浏览器打开 charts/entropy.html
|
|
65
|
+
python <S>/scripts/watch.py --workspace <WS> --open
|
|
66
|
+
|
|
67
|
+
# 4. 停止
|
|
68
|
+
python <S>/scripts/stop.py --workspace <WS>
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
解释器名按平台取 `python` 或 `python3`。脚本只用标准库 + `pyyaml`,
|
|
72
|
+
进程操作可选依赖 `psutil`(ECAT 本身已依赖;缺失时自动退化到 tasklist/kill)。
|
|
73
|
+
|
|
74
|
+
`<WS>` = ECAT 工作区根目录(含 `.ecat/`、鸿蒙仓、安卓源码那个目录)。必须由用户给出,不要猜。
|
|
75
|
+
|
|
76
|
+
不传 `<WS>` 时,脚本和 `/ecat-refine` 命令按 `~/.ecat/active-workspace.json` 解析——那是**最近一次 `ecat-setup` 的 `check.py` 通过时**写入的指针,所以换项目只要重跑 setup,裸命令会自动跟随。命令行显式给的 `<WS>` 永远优先;指针指向的目录被删掉时会跳过它,退回插件配置/会话 cwd。
|
|
77
|
+
|
|
78
|
+
## 配置就在这个 skill 里
|
|
79
|
+
|
|
80
|
+
两份 config 都随 skill 分发。**每次启动前先跑 preflight**,它会打印这份配置实际指向什么,末尾单列一块「项目相关配置」。
|
|
81
|
+
|
|
82
|
+
配置分两类,处理方式不同:
|
|
83
|
+
|
|
84
|
+
| | 字段 | 怎么做 |
|
|
85
|
+
|---|---|---|
|
|
86
|
+
| **项目相关**(每次调用都可能变) | `project`、`paths.android`、`paths.harmony`、`paths.spec`、`paths.feature_checklist` | 把 preflight 末尾那一块念给用户确认;不对就改所选的 config 重跑 |
|
|
87
|
+
| **策略/调参**(ECAT 的经验值) | `loop.*` 阈值、`entropy.weights`、`judge_max_issues`、`timeout_s`、模型与 endpoint | **不要动**。用户明确要求才改,改完说明改了什么 |
|
|
88
|
+
|
|
89
|
+
`paths.spec` 与 `paths.feature_checklist` 是选填:spec 缺失时生成器退化为按文件名匹配安卓源码;feature_checklist 未配置时该熵维度自动跳过(`skipped: no_feature_checklist_configured`),都不会报错。但**配了却指向不存在的文件**是 FAIL——那是写错了,不是没配。
|
|
90
|
+
|
|
91
|
+
## 退出码
|
|
92
|
+
|
|
93
|
+
`preflight.py`
|
|
94
|
+
|
|
95
|
+
| 码 | 含义 | 怎么办 |
|
|
96
|
+
|---|---|---|
|
|
97
|
+
| 0 | 就绪 | 可以启动 |
|
|
98
|
+
| 10 | 配置本身有问题 | 改所选的 config;若报 endpoint 不匹配,多半是两份 config 用混了 |
|
|
99
|
+
| 11 | 路径对不上现实 | 改 `config.yaml` 的 `paths.*`;harmony 不是 git 仓要先 `git init` |
|
|
100
|
+
| 12 | 运行时缺失 | 装/加 PATH:`claude` 或 `opencode`(按所选 runtime) |
|
|
101
|
+
| 13 | 凭据缺失 | 往 `<WS>/.env` 里补 `api_key_env` 指名的变量 |
|
|
102
|
+
| 14 | workspace 未初始化 | 在 `<WS>` 跑 `ecat init` |
|
|
103
|
+
| 15 | `ecat` 不在 PATH | `uv tool install --editable <ECAT 仓>` |
|
|
104
|
+
|
|
105
|
+
`start.py`:0=已启动 / 1=参数或路径错 / 2=已有 run 在跑 / 3=启动失败(看打印的 boot log 末尾)
|
|
106
|
+
|
|
107
|
+
`watch.py`:0=正在跑 / 1=已结束 / 2=异常终止 / 3=没有任何 run
|
|
108
|
+
|
|
109
|
+
`stop.py`:0=已停 / 3=没有在跑的 run
|
|
110
|
+
|
|
111
|
+
## 怎么读 watch 的输出
|
|
112
|
+
|
|
113
|
+
- **H 曲线**是主信号,逐轮下降说明生成器在真的修东西;长期不动说明卡住了
|
|
114
|
+
- **维度分数**指出当前最差的一维(`worst:`),生成器下一轮主要修它
|
|
115
|
+
- **清单行**(配了功能清单时)显示 `OK/ISSUE/TODO` 与上轮推进量——推进量远低于目标说明判别器在敷衍
|
|
116
|
+
- 异常终止(exit 2)时看 `.ecat/skill-refine.boot.log` 和 `runs_*/run.log` 末尾
|
|
117
|
+
|
|
118
|
+
`--open` 打开的是 `runs_*/charts/entropy.html`:每轮判别完成后重写、页面每 30 秒自刷新,
|
|
119
|
+
所以停在浏览器里即可,不必反复 `watch`。首轮判别完成前这个文件还不存在,脚本会直接说明。
|
|
120
|
+
只想确认路径、不想弹浏览器时用 `--open --dry-run`。
|
|
121
|
+
|
|
122
|
+
## 边界
|
|
123
|
+
|
|
124
|
+
- 一个 workspace 同时只允许一个 refine(两个会互相 revert 同一个 git 仓)。`start.py` 会拦。
|
|
125
|
+
- 本 skill 不改鸿蒙代码、不改熵插件、不动 `.ecat/agents/`——那些是 ECAT 自己的事。
|
|
126
|
+
- 跑起来之后 ECAT 会自行 commit 每轮改动到鸿蒙仓;`stop.py` 不回滚已提交的内容。
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
# ─── Identity ────────────────────────────────────────────────────────────────
|
|
2
|
+
project: my-android-app
|
|
3
|
+
work_dir: .
|
|
4
|
+
|
|
5
|
+
# ─── Source / Target paths ───────────────────────────────────────────────────
|
|
6
|
+
# `target` is required; `source` is optional (single-tree tasks omit it).
|
|
7
|
+
paths:
|
|
8
|
+
source: ./Android_code/AIPPT
|
|
9
|
+
target: ./aippt_cc_glm_0705
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
# ─── Agents ──────────────────────────────────────────────────────────────────
|
|
13
|
+
# Each agent can use a different runtime, provider, model, and base_url.
|
|
14
|
+
# base_url: set to your provider's OpenAI-compatible endpoint, or null for default.
|
|
15
|
+
# api_key_env: the NAME of the env var in .env (not the key itself).
|
|
16
|
+
|
|
17
|
+
generator:
|
|
18
|
+
runtime: claude_code # claude_code | opencode | deveco_code | dsh
|
|
19
|
+
model: deepseek-v4-flash[1m] # any model your provider supports
|
|
20
|
+
provider: deepseek
|
|
21
|
+
base_url: https://api.deepseek.com/anthropic # e.g. https://api.deepseek.com/v1
|
|
22
|
+
api_key_env: ANTHROPIC_AUTH_TOKEN
|
|
23
|
+
config_dir: .ecat/agents/generator
|
|
24
|
+
timeout_s: 5400
|
|
25
|
+
extra_args: []
|
|
26
|
+
resume_session: true
|
|
27
|
+
|
|
28
|
+
discriminator:
|
|
29
|
+
runtime: claude_code
|
|
30
|
+
model: deepseek-v4-flash[1m]
|
|
31
|
+
provider: deepseek
|
|
32
|
+
base_url: https://api.deepseek.com/anthropic
|
|
33
|
+
api_key_env: ANTHROPIC_AUTH_TOKEN
|
|
34
|
+
config_dir: .ecat/agents/discriminator
|
|
35
|
+
timeout_s: 3600
|
|
36
|
+
extra_args: []
|
|
37
|
+
evolution_write_paths:
|
|
38
|
+
- .ecat/agents/generator/skills
|
|
39
|
+
- .ecat/agents/generator/memory
|
|
40
|
+
|
|
41
|
+
# ─── Adversarial loop ────────────────────────────────────────────────────────
|
|
42
|
+
loop:
|
|
43
|
+
max_iterations: 300
|
|
44
|
+
entropy_threshold: 0.01
|
|
45
|
+
# stable_iters_to_stop: H 需连续 N 轮低于 entropy_threshold 才提前退出(防单轮"安静"过早收敛)。默认 2。
|
|
46
|
+
stable_iters_to_stop: 2
|
|
47
|
+
# regression_tolerance: 相邻两轮之间的回归容忍度。
|
|
48
|
+
# 如果本轮 H 比上轮 H 增加超过此值,判定为"回归"(代码质量变差)。
|
|
49
|
+
# revert_on_regression=true 时会 git checkout 撤销本轮 Generator 的改动。
|
|
50
|
+
# 作用:防止单次迭代引入破坏性变更。
|
|
51
|
+
regression_tolerance: 0.1
|
|
52
|
+
revert_on_regression: true
|
|
53
|
+
|
|
54
|
+
# oscillation_guard: 检测循环是否陷入"震荡"(反复修改同一问题无法收敛)。
|
|
55
|
+
# window: 回看最近 N 轮的 H 值序列。
|
|
56
|
+
# min_delta: 如果最近 window 轮中相邻两轮的 H 变化绝对值都 < min_delta,
|
|
57
|
+
# 说明 Generator 在原地打转,触发提前终止。
|
|
58
|
+
# 作用:避免浪费 token 在无效迭代上。
|
|
59
|
+
oscillation_guard:
|
|
60
|
+
enabled: true
|
|
61
|
+
window: 5
|
|
62
|
+
min_delta: 0.02
|
|
63
|
+
|
|
64
|
+
generator_compact_interval: 15
|
|
65
|
+
# max_items_per_iter: 每轮传给生成器的 work-list 最大条目数。
|
|
66
|
+
# 调小可缩短每轮耗时但需更多轮次收敛;调大每轮改动更多但速度变慢。默认 25。
|
|
67
|
+
max_items_per_iter: 50
|
|
68
|
+
|
|
69
|
+
# ─── Entropy plugin set ───────────────────────────────────────────────────────
|
|
70
|
+
# Every dimension listed in weights must be registered by a plugin in the
|
|
71
|
+
# selected set; a weight with no plugin is silently ignored, so the dimension
|
|
72
|
+
# never scores and the Generator never gets work for it.
|
|
73
|
+
entropy:
|
|
74
|
+
plugin_set: example
|
|
75
|
+
# judge_max_issues: 每个 agentic judge 子代理最多上报的问题数。
|
|
76
|
+
# 调小让 judge 更早停止探索文件,加快判别器;调大获取更多细节。默认 10。
|
|
77
|
+
judge_max_issues: 20
|
|
78
|
+
weights:
|
|
79
|
+
compile: 0.30
|
|
80
|
+
feature_parity: 0.35
|
|
81
|
+
|
|
82
|
+
# ─── Retry ────────────────────────────────────────────────────────────────────
|
|
83
|
+
retry:
|
|
84
|
+
max_attempts: 3
|
|
85
|
+
base_delay_s: 2
|
|
86
|
+
max_delay_s: 30
|
|
87
|
+
jitter: true
|
|
88
|
+
|
|
89
|
+
# ─── Phase gates ─────────────────────────────────────────────────────────────
|
|
90
|
+
features:
|
|
91
|
+
memory_evolution: true
|
|
92
|
+
skill_evolution: false
|
|
93
|
+
multi_discriminator: false
|
|
94
|
+
in_loop_intervention: false
|
|
95
|
+
|
|
96
|
+
# ─── Reporting ───────────────────────────────────────────────────────────────
|
|
97
|
+
reporting:
|
|
98
|
+
chart_format: png
|
|
99
|
+
chart_on_each_iter: true
|
|
100
|
+
keep_run_artifacts: -1
|
|
101
|
+
log_level: info
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
# ─── deveco_code 变体 ────────────────────────────────────────────────────────
|
|
2
|
+
# 与 config.opencode.yaml 的差异只在 runtime:deveco 是 opencode 的 fork
|
|
3
|
+
# (npm @deveco/deveco-code),配置 schema / 事件流 / 429 软中止与 opencode 同构,
|
|
4
|
+
# 只是命令名为 `deveco`、自动批准用 `--auto`、配置目录环境变量是 DEVECO_CONFIG_DIR、
|
|
5
|
+
# 配置文件名是 deveco.jsonc。ECAT 引擎由 DevecoCodeRunner(继承 OpencodeRunner)驱动。
|
|
6
|
+
#
|
|
7
|
+
# runtime claude_code → deveco_code
|
|
8
|
+
# 其余(base_url / api_key_env / model / provider)与 opencode 变体一致:
|
|
9
|
+
# * 走 @ai-sdk/openai-compatible 裸 OpenAI 端点(不要 /anthropic 后缀)
|
|
10
|
+
# * api_key_env 用 DEEPSEEK_API_KEY 之类标准 AI SDK 槽位(同 opencode)
|
|
11
|
+
# ─── Identity ────────────────────────────────────────────────────────────────
|
|
12
|
+
project: my-android-app
|
|
13
|
+
work_dir: .
|
|
14
|
+
|
|
15
|
+
# ─── Source / Target paths ───────────────────────────────────────────────────
|
|
16
|
+
# `target` is required; `source` is optional (single-tree tasks omit it).
|
|
17
|
+
paths:
|
|
18
|
+
source: ./Android_code/AIPPT
|
|
19
|
+
target: ./ai_ppt_ecat_deveco_skill0910
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
# ─── Agents ──────────────────────────────────────────────────────────────────
|
|
23
|
+
# Each agent can use a different runtime, provider, model, and base_url.
|
|
24
|
+
# base_url: set to your provider's OpenAI-compatible endpoint, or null for default.
|
|
25
|
+
# api_key_env: the NAME of the env var in .env (not the key itself).
|
|
26
|
+
|
|
27
|
+
generator:
|
|
28
|
+
runtime: deveco_code # claude_code | opencode | deveco_code | dsh
|
|
29
|
+
model: glm-5.3-flash # 干净模型名(不带 provider 前缀;deveco runner 会拼成 zhipu/glm-5.3-flash)
|
|
30
|
+
provider: zhipu
|
|
31
|
+
base_url: https://open.bigmodel.cn/api/coding/paas/v4
|
|
32
|
+
api_key_env: GLM_API_KEY_YQ
|
|
33
|
+
config_dir: .ecat/agents/generator
|
|
34
|
+
timeout_s: 5400
|
|
35
|
+
extra_args: []
|
|
36
|
+
resume_session: true
|
|
37
|
+
|
|
38
|
+
discriminator:
|
|
39
|
+
runtime: deveco_code
|
|
40
|
+
model: glm-5.3-flash
|
|
41
|
+
provider: zhipu
|
|
42
|
+
base_url: https://open.bigmodel.cn/api/coding/paas/v4
|
|
43
|
+
api_key_env: GLM_API_KEY_YQ
|
|
44
|
+
config_dir: .ecat/agents/discriminator
|
|
45
|
+
timeout_s: 3600
|
|
46
|
+
extra_args: []
|
|
47
|
+
evolution_write_paths:
|
|
48
|
+
- .ecat/agents/generator/skills
|
|
49
|
+
- .ecat/agents/generator/memory
|
|
50
|
+
|
|
51
|
+
# ─── Adversarial loop ────────────────────────────────────────────────────────
|
|
52
|
+
loop:
|
|
53
|
+
max_iterations: 100
|
|
54
|
+
entropy_threshold: 0.01
|
|
55
|
+
stable_iters_to_stop: 2
|
|
56
|
+
regression_tolerance: 0.1
|
|
57
|
+
revert_on_regression: true
|
|
58
|
+
oscillation_guard:
|
|
59
|
+
enabled: true
|
|
60
|
+
window: 5
|
|
61
|
+
min_delta: 0.02
|
|
62
|
+
generator_compact_interval: 15
|
|
63
|
+
max_items_per_iter: 50
|
|
64
|
+
|
|
65
|
+
# ─── Entropy plugin set ───────────────────────────────────────────────────────
|
|
66
|
+
# Every dimension listed in weights must be registered by a plugin in the
|
|
67
|
+
# selected set; a weight with no plugin is silently ignored, so the dimension
|
|
68
|
+
# never scores and the Generator never gets work for it.
|
|
69
|
+
entropy:
|
|
70
|
+
plugin_set: example
|
|
71
|
+
# judge_max_issues: 每个 agentic judge 子代理最多上报的问题数。
|
|
72
|
+
# 调小让 judge 更早停止探索文件,加快判别器;调大获取更多细节。默认 10。
|
|
73
|
+
judge_max_issues: 20
|
|
74
|
+
weights:
|
|
75
|
+
compile: 0.30
|
|
76
|
+
feature_parity: 0.35
|
|
77
|
+
|
|
78
|
+
# entry_nav: 0.10
|
|
79
|
+
# feature_check: 0.30
|
|
80
|
+
# page_audit: 0.10
|
|
81
|
+
# confidence: 0.10
|
|
82
|
+
# spec_coverage: 0.10
|
|
83
|
+
# source_parity: 0.10
|
|
84
|
+
# hallucination: 0.10
|
|
85
|
+
|
|
86
|
+
# node_align: 0.0
|
|
87
|
+
# ui_align: 0.0
|
|
88
|
+
# runtime_liveness: 0.0
|
|
89
|
+
|
|
90
|
+
# ─── Retry ────────────────────────────────────────────────────────────────────
|
|
91
|
+
retry:
|
|
92
|
+
max_attempts: 3
|
|
93
|
+
base_delay_s: 2
|
|
94
|
+
max_delay_s: 30
|
|
95
|
+
jitter: true
|
|
96
|
+
|
|
97
|
+
# ─── Phase gates ─────────────────────────────────────────────────────────────
|
|
98
|
+
features:
|
|
99
|
+
memory_evolution: false
|
|
100
|
+
skill_evolution: false
|
|
101
|
+
multi_discriminator: false
|
|
102
|
+
in_loop_intervention: false
|
|
103
|
+
|
|
104
|
+
# ─── Reporting ───────────────────────────────────────────────────────────────
|
|
105
|
+
reporting:
|
|
106
|
+
chart_format: png
|
|
107
|
+
chart_on_each_iter: true
|
|
108
|
+
keep_run_artifacts: -1
|
|
109
|
+
log_level: info
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
# ECAT — DeepSeek Harness (dsh) runtime, headless one-shot mode.
|
|
2
|
+
#
|
|
3
|
+
# Differences from the claude_code config:
|
|
4
|
+
# * no base_url — dsh owns its endpoint (official route or DEEPSEEK_BASE_URL);
|
|
5
|
+
# ECAT rejects base_url for this runtime rather than silently ignoring it.
|
|
6
|
+
# * model is written into a per-call patch, because headless has no --model.
|
|
7
|
+
# * api_key_env defaults to DEEPSEEK_API_KEY; the runner exports the resolved
|
|
8
|
+
# value under that name whatever variable the config points at.
|
|
9
|
+
# * each role gets its own DSH_HOME under .ecat/agents/<role>/ (profile +
|
|
10
|
+
# AGENTS.md), created automatically on the first run.
|
|
11
|
+
#
|
|
12
|
+
# Verify with: python <skill>/scripts/preflight.py --config <this file> --workspace <WS>
|
|
13
|
+
|
|
14
|
+
# ─── Identity ────────────────────────────────────────────────────────────────
|
|
15
|
+
project: my-project
|
|
16
|
+
work_dir: .
|
|
17
|
+
|
|
18
|
+
# ─── Prompt profile ──────────────────────────────────────────────────────────
|
|
19
|
+
# Domain fragment under ecat/prompts/profiles/<name>/. "a2h" ships with the
|
|
20
|
+
# repo; create your own with the ecat-setup skill.
|
|
21
|
+
profile: a2h
|
|
22
|
+
|
|
23
|
+
# ─── Source / Target paths ───────────────────────────────────────────────────
|
|
24
|
+
paths:
|
|
25
|
+
# source: ./reference # optional: only for a task with a ground-truth tree
|
|
26
|
+
target: ./target # required, must exist
|
|
27
|
+
|
|
28
|
+
# ─── Agents ──────────────────────────────────────────────────────────────────
|
|
29
|
+
generator:
|
|
30
|
+
runtime: dsh
|
|
31
|
+
model: deepseek-flash
|
|
32
|
+
provider: deepseek
|
|
33
|
+
base_url: null # must stay null for dsh
|
|
34
|
+
api_key_env: DEEPSEEK_API_KEY
|
|
35
|
+
config_dir: .ecat/agents/generator
|
|
36
|
+
timeout_s: 5400
|
|
37
|
+
extra_args: []
|
|
38
|
+
# Continue the same dsh session across iterations (--session-id). Saves
|
|
39
|
+
# cache reads; context grows, so pair it with the loop's compaction setting.
|
|
40
|
+
resume_session: true
|
|
41
|
+
|
|
42
|
+
discriminator:
|
|
43
|
+
runtime: dsh
|
|
44
|
+
model: deepseek-flash
|
|
45
|
+
provider: deepseek
|
|
46
|
+
base_url: null
|
|
47
|
+
api_key_env: DEEPSEEK_API_KEY
|
|
48
|
+
config_dir: .ecat/agents/discriminator
|
|
49
|
+
timeout_s: 3600
|
|
50
|
+
extra_args: []
|
|
51
|
+
evolution_write_paths:
|
|
52
|
+
- .ecat/agents/generator/skills
|
|
53
|
+
- .ecat/agents/generator/memory
|
|
54
|
+
|
|
55
|
+
# ─── Adversarial loop ────────────────────────────────────────────────────────
|
|
56
|
+
loop:
|
|
57
|
+
max_iterations: 100
|
|
58
|
+
entropy_threshold: 0.01
|
|
59
|
+
stable_iters_to_stop: 2
|
|
60
|
+
regression_tolerance: 0.1
|
|
61
|
+
revert_on_regression: true
|
|
62
|
+
oscillation_guard:
|
|
63
|
+
enabled: true
|
|
64
|
+
window: 5
|
|
65
|
+
min_delta: 0.02
|
|
66
|
+
# dsh runs one process per call and has no in-session /compact, so this knob
|
|
67
|
+
# is a no-op here. Context growth is handled by dsh's own compaction-basic
|
|
68
|
+
# (threshold 0.8 of the model window) inside each resumed session.
|
|
69
|
+
generator_compact_interval: 0
|
|
70
|
+
max_items_per_iter: 25
|
|
71
|
+
|
|
72
|
+
# ─── Entropy plugin set ──────────────────────────────────────────────────────
|
|
73
|
+
# `example` ships with the repo. Replace with the set you build; every
|
|
74
|
+
# dimension listed in weights must be registered by some plugin.
|
|
75
|
+
entropy:
|
|
76
|
+
plugin_set: example
|
|
77
|
+
judge_max_issues: 10
|
|
78
|
+
weights:
|
|
79
|
+
compile: 0.30
|
|
80
|
+
feature_parity: 0.35
|
|
81
|
+
|
|
82
|
+
# ─── Retry ────────────────────────────────────────────────────────────────────
|
|
83
|
+
# dsh retries transient provider failures inside the turn (dsh-llm-retry).
|
|
84
|
+
# Keep this modest so an upstream outage surfaces as a failed iteration rather
|
|
85
|
+
# than hours of silent retrying.
|
|
86
|
+
retry:
|
|
87
|
+
max_attempts: 2
|
|
88
|
+
base_delay_s: 2
|
|
89
|
+
max_delay_s: 30
|
|
90
|
+
jitter: true
|
|
91
|
+
|
|
92
|
+
# ─── Phase gates ─────────────────────────────────────────────────────────────
|
|
93
|
+
features:
|
|
94
|
+
memory_evolution: false
|
|
95
|
+
skill_evolution: false
|
|
96
|
+
multi_discriminator: false
|
|
97
|
+
in_loop_intervention: false
|
|
98
|
+
|
|
99
|
+
# ─── Reporting ───────────────────────────────────────────────────────────────
|
|
100
|
+
reporting:
|
|
101
|
+
chart_format: png
|
|
102
|
+
chart_on_each_iter: true
|
|
103
|
+
keep_run_artifacts: -1
|
|
104
|
+
log_level: info
|