@ckanner/flywheel 0.27.3 → 0.28.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/CHANGELOG.md +24 -0
- package/README.en.md +135 -0
- package/README.md +34 -12
- package/bin/flywheel-codex-pro-worker.js +16 -0
- package/bin/flywheel.js +5 -1
- package/bin/runtime.js +14 -1
- package/docs/configuration.md +33 -2
- package/docs/en/configuration.md +193 -0
- package/docs/en/getting-started.md +259 -0
- package/docs/en/workflow.md +155 -0
- package/docs/getting-started.md +34 -12
- package/docs/workflow.md +199 -0
- package/npm/install.js +17 -7
- package/package.json +17 -10
package/docs/getting-started.md
CHANGED
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
# Mac 安装与首个 Flywheel 任务
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
[English](en/getting-started.md) · 简体中文
|
|
4
|
+
|
|
5
|
+
本文适用于 **Flywheel 0.28.0 及以后的完整 npm 发行版**,覆盖 npm 一条命令安装 CLI、worker、DSH 插件与 skills,到配置、启动、观察、停止和恢复一个小任务。DSH 接口目标是已核对的 **Mac 桌面 0.2.1-rc.5**。真实桌面、Seatbelt 和账号调用仍需在自己的 Mac 验收,CI 不能代替这些检查。
|
|
6
|
+
|
|
7
|
+
下文的顶部 **Flywheel 会话视图**从 `0.28.1` 开始提供。`0.28.0` 仍使用底部弹层;需要把 CLI 和桌面插件升级到同一新版本,源码合并或重新载入旧版本不会带来新布局。CLI 和任务目录接口保持一致。
|
|
4
8
|
|
|
5
9
|
安装前用 `npm view @ckanner/flywheel version` 确认 registry 的 latest 已更新到所需版本;源码合并或 GitHub Release 不代表 npm 已发行。旧 0.22.1 没有本教程使用的安装与 DSH 接口,当前发行状态见[发行记录](releasing.md#3-失败恢复)。
|
|
6
10
|
|
|
@@ -16,15 +20,17 @@
|
|
|
16
20
|
8. [升级、排错与卸载](#8-升级排错与卸载)
|
|
17
21
|
9. [开发与备用构建](#9-开发与备用构建)
|
|
18
22
|
|
|
23
|
+
已有业务仓库另见[从需求准备到 PR 合并](workflow.md):模型选择、任务 worktree、Draft PR 与合并时机。
|
|
24
|
+
|
|
19
25
|
## 1. 准备运行环境
|
|
20
26
|
|
|
21
27
|
| 依赖 | 用途与检查 |
|
|
22
28
|
|---|---|
|
|
23
29
|
| Git,已配置提交身份 | Flywheel 使用 worktree 和本地提交交付;执行 `git --version` |
|
|
24
|
-
| Node.js 22 或更高,npm | 安装 Flywheel 并运行 CLI 启动器/DSH worker;执行 `node --version`、`npm --version` |
|
|
30
|
+
| Node.js 22.18.0 或更高,npm | 安装 Flywheel 并运行 CLI 启动器/DSH worker;执行 `node --version`、`npm --version` |
|
|
25
31
|
| DSH Mac 桌面及其安装的 `dsh` 命令 | 在 About 核对具体版本;执行 `command -v dsh`、`dsh --version` |
|
|
26
32
|
| 已登录的 Kimi CLI | 默认 Plan、frontend、Garden 使用它;执行 `kimi --version`、`kimi --help` |
|
|
27
|
-
| 已登录的 Codex
|
|
33
|
+
| 已登录的 Codex 程序 | Codex Pro 插件在 `hard` 路由中启动其 app-server;执行 `codex --version` |
|
|
28
34
|
| SDK profile 的 DeepSeek 和 ChatGPT provider | 默认实现/评审使用;配置与授权见下一节 |
|
|
29
35
|
| Go 1.27 或更高 | 仅本文的 Go 示例和源码构建需要;npm 安装 Flywheel 不需要 Go 工具链 |
|
|
30
36
|
|
|
@@ -46,7 +52,7 @@ npx -y @ckanner/flywheel@latest install --json
|
|
|
46
52
|
|
|
47
53
|
两条命令选择一种即可。安装器按顺序完成:
|
|
48
54
|
|
|
49
|
-
1. 把本次安装器的精确版本装到 npm 全局目录,解析适合本机的 Go
|
|
55
|
+
1. 把本次安装器的精确版本装到 npm 全局目录,解析适合本机的 Go 平台包、同版本 DSH/Codex Pro workers 及精确插件依赖 `dsh-subagent-codex-pro@0.8.0`,核对 CLI 版本。
|
|
50
56
|
2. 从 Go 二进制安装全部 10 个 skills;全局配置不存在时生成默认配置,已有配置保留。
|
|
51
57
|
3. 写入 GUI 启动器和安装记录,使用绝对 Node/CLI 路径。
|
|
52
58
|
4. 通过现有桌面 `dsh` 注册精确版本的 Flywheel 插件,并通过 `plugin list` 验证安装结果。
|
|
@@ -89,7 +95,9 @@ flywheel setup --no-global
|
|
|
89
95
|
|
|
90
96
|
## 3. 桌面入口和 SDK 配置
|
|
91
97
|
|
|
92
|
-
安装器已经调用正式接口 `dsh plugin --profile desktop add --save-exact --ignore-scripts @ckanner/dsh-plugin-flywheel@<本次精确版本>`,随后通过 `list` 核对版本。无需再分别安装 worker 或手动选择压缩包。该命令必须来自桌面安装;独立 npm DSH CLI 不能管理保留的 `desktop` profile
|
|
98
|
+
安装器已经调用正式接口 `dsh plugin --profile desktop add --save-exact --ignore-scripts @ckanner/dsh-plugin-flywheel@<本次精确版本>`,随后通过 `list` 核对版本。无需再分别安装 worker 或手动选择压缩包。该命令必须来自桌面安装;独立 npm DSH CLI 不能管理保留的 `desktop` profile。按照宿主提示重新载入,在顶部“对话/轨迹”所在的原生视图栏选择 **Flywheel**;未直接显示时检查该栏的更多入口。
|
|
99
|
+
|
|
100
|
+
这个视图用于控制和观察已经准备好的任务:看进度、人工处理项、实际模型和环境,显式启动、刷新或停止。它保留 DSH 的原生对话、轨迹、输入区、模型选择器和右侧栏;需求讨论与契约准备仍在原来的对话和 skills 中进行。视图不会自动发现别处启动的任务,需要选择相同的任务目录。
|
|
93
101
|
|
|
94
102
|
### 原生 SDK profile
|
|
95
103
|
|
|
@@ -99,7 +107,9 @@ worker 默认使用独立的 `sdk` profile。桌面已安装 provider,不代
|
|
|
99
107
|
dsh plugin --profile sdk add dsh-plugin-chatgpt@0.1.17
|
|
100
108
|
```
|
|
101
109
|
|
|
102
|
-
随后按该 provider 的文档在对应 profile 完成授权,并保持一致的 `DSH_HOME`。不需要把凭证复制到任务契约或 Git。此处不把 `subagent_codex_pro` 当成原生 LLM provider
|
|
110
|
+
随后按该 provider 的文档在对应 profile 完成授权,并保持一致的 `DSH_HOME`。不需要把凭证复制到任务契约或 Git。此处不把 `subagent_codex_pro` 当成原生 LLM provider。困难任务通过 `codex-pro` worker 直接使用已安装插件的公开 machine API,不需要 DSH 父模型再发一次工具调用。底层 Codex app-server 仍需本机 Codex 与登录;包依赖安装不代替它们。
|
|
111
|
+
|
|
112
|
+
SDK worker 的临时权限与工具策略只用于其子进程,不改写桌面 profile 或移除桌面已有能力。它限制自主委派、辅助模型压缩等工作,当前还禁用整个 web 工具;移到原生会话视图不会让 worker 自动继承桌面插件或轨迹。能力范围及后续检索接入边界见[插件说明](../plugins/dsh/README.md#权限上下文与报告归档)。
|
|
103
113
|
|
|
104
114
|
### Mac GUI 的自动入口
|
|
105
115
|
|
|
@@ -170,7 +180,7 @@ flywheel doctor --cwd "$PWD" --probe --json
|
|
|
170
180
|
|
|
171
181
|
第一条只查有效配置、本地命令版本、目录及已声明环境变量;不会检查凭证文件、发送模型 prompt 或运行 packet 验收。第二条对选中的 DSH 绑定做 SDK 初始化、cwd/沙箱握手及正常关闭;provider 初始化可能联网查询目录,但**没有推理请求**。两者都不创建 Flywheel 状态、运行锁、worktree 或全局配置。
|
|
172
182
|
|
|
173
|
-
结果按 pass/fail/warn/unknown/skipped 展示;有 fail 时退出码 1,JSON 仍完整可读。即使 `ok:true`,unknown 的账号授权、订阅额度与实际推理仍未验证。Kimi/Codex
|
|
183
|
+
结果按 pass/fail/warn/unknown/skipped 展示;有 fail 时退出码 1,JSON 仍完整可读。即使 `ok:true`,unknown 的账号授权、订阅额度与实际推理仍未验证。Kimi/Codex 在这里只检查命令;Codex Pro 额外实际导入精确版本的公开 API,不会自动登录或试调用。Codex Pro 的完整沙箱策略只能事后审查,所以对应 sandbox 项会显示 warn,模型/配置/认证保持 unknown;`--probe` 也不会为它发送推理。DSH 同一账号、模型、effort、目录和权限只探测一次,总预算 40 秒另加清理窗口;超时后明确失败。
|
|
174
184
|
|
|
175
185
|
未指定任务时检查全部配置绑定,可能包括首个任务用不到的 Codex hard 路由。准备好任务后可把范围缩小为所需的 Plan/Execute route/Review/Judge(以及显式启用的 judge-panel):
|
|
176
186
|
|
|
@@ -184,6 +194,8 @@ flywheel doctor --cwd "$PWD" --task-dir docs/add --probe --json
|
|
|
184
194
|
|
|
185
195
|
## 6. 准备首个小任务
|
|
186
196
|
|
|
197
|
+
已有业务仓库应先建立任务集成分支和独立 worktree,再生成契约;启动时的 `cwd` 指向该 worktree。完整步骤见[从需求准备到 PR 合并](workflow.md),下面的小仓库示例用于首次运行验收。
|
|
198
|
+
|
|
187
199
|
首次建议使用单独的小仓库,便于分清安装问题和业务代码问题。npm 包附带的准备脚本会创建一个 Go 加法函数任务:初始实现故意错误,执行者需修复实现并补普通单测;独立 acceptance 测试不可修改。本示例需要 Go 1.27 或更高。
|
|
188
200
|
|
|
189
201
|
```sh
|
|
@@ -226,7 +238,7 @@ git commit -m "docs: prepare first flywheel task"
|
|
|
226
238
|
|
|
227
239
|
Git 提交身份必须已经按自己的设置配置。此时不应创建 `state.json`,它由引擎初始化。coverage 输出已被忽略,所以验收运行不会把生成物误判为候选代码漂移。
|
|
228
240
|
|
|
229
|
-
|
|
241
|
+
对于已有业务仓库,`flywheel-new` 使用当前 DSH 会话的模型生成契约;复杂需求建议选已授权的 `gpt-6-astra`、`high`,简单明确任务可沿用 Flash。它不会自动读取 `loops.plan` 来换模型,后者控制引擎运行后的 Kimi 规划/修订。可以通过 `flywheel-new` 生成并审阅契约,或者用 `flywheel template --list` 查看模板后手工准备。示例 auth 模板不是通用可运行任务,其中路径和验收命令必须改为真实项目的命令。不要照抄后直接启动。
|
|
230
242
|
|
|
231
243
|
## 7. 启动、观察、停止与恢复
|
|
232
244
|
|
|
@@ -237,7 +249,13 @@ flywheel control start --task-dir "$PWD/docs/add" --cwd "$PWD"
|
|
|
237
249
|
flywheel control status --task-dir "$PWD/docs/add" --cwd "$PWD"
|
|
238
250
|
```
|
|
239
251
|
|
|
240
|
-
`ok: true` 只表示控制操作成功;`running` 表示引擎运行状态,最终任务结果看 `state.status
|
|
252
|
+
`ok: true` 只表示控制操作成功;`running` 表示引擎运行状态,最终任务结果看 `state.status`。也可以在顶部 **Flywheel** 视图填入同样两个绝对路径,按需展开“模型配置与环境检查”,再点击“启动/刷新状态/停止”。视图区分未初始化、运行、已完成、暂停、停止和升级,标明最近刷新时间;它不会自动轮询。
|
|
253
|
+
|
|
254
|
+
宿主保留会话绑定期间,路径草稿与快照会按会话保留,切换“对话/轨迹/Flywheel”不丢失;重新载入插件或桌面后可能需要重新选择路径。修改路径清除旧结果并忽略迟到响应,不会停止旧任务。每个会话只等待一个控制请求;启动或停止等待期间锁定目录输入。
|
|
255
|
+
|
|
256
|
+
启动或停止超时、断连后,后台任务的结果可能尚未确认。保留原任务目录,先“刷新状态”和查看日志;界面在成功核对该任务前禁止继续启动/停止,也不会自动重试。已有快照只是上次结果,不能凭页面关闭、切换会话或停止按钮失去等待状态推断引擎已经结束。原生轨迹保留父会话自己的记录,worker 完整历史不自动合并到其中。
|
|
257
|
+
|
|
258
|
+
如果宿主明确报告请求在启动控制进程前已被拒绝,例如目录不存在,则修正目录或环境后可以重新提交;这与响应丢失后的结果未确认不同。界面只接受宿主的结构化确认,不通过错误文字推断任务没有执行。
|
|
241
259
|
|
|
242
260
|
需要人工在 Review 前检查结果时,使用前台监督模式;它与后台 start 二选一:
|
|
243
261
|
|
|
@@ -276,7 +294,9 @@ flywheel control start --task-dir "$PWD/docs/add" --cwd "$PWD"
|
|
|
276
294
|
npx -y @ckanner/flywheel@latest install
|
|
277
295
|
```
|
|
278
296
|
|
|
279
|
-
自定义 prefix、项目 skills 或 DSH 入口时保留原参数。想固定某个已发布版本,可把 `@latest` 换成该精确版本,例如在 registry 确认 0.
|
|
297
|
+
自定义 prefix、项目 skills 或 DSH 入口时保留原参数。想固定某个已发布版本,可把 `@latest` 换成该精确版本,例如在 registry 确认 0.28.0 已发布后使用 `@0.28.0`;安装器始终为 CLI、平台包、worker 和桌面插件选择本次安装器的同一版本。已安装包的配置修复可用 `flywheel setup --no-global`,它不会将 CLI 升级到别的版本。
|
|
298
|
+
|
|
299
|
+
从 0.27.x 升级到本版后,要使用新的默认插件路径,应在有效配置的 `routes.hard`(或其 profile)设置 `"harness": "codex-pro"`,保留所选 model/thinking/channel。先用 `config inspect` 找到实际配置来源;不要把 external subagent 的工具名写成 DSH provider。
|
|
280
300
|
|
|
281
301
|
安装后对照新模板审阅需要迁移的配置,按宿主提示重新载入,运行 doctor,再用小任务验证。已有配置不会自动覆盖;特别检查任务级文件是否遮住了刚修改的项目或全局设置。安装不是跨 npm、DSH 与全部 skills 的单个事务:失败时报告已完成步骤,不擅自回退包管理器或删除用户文件。修正原因后重跑会重新核对版本与内容。
|
|
282
302
|
|
|
@@ -291,6 +311,8 @@ launcher 被手工修改时,先备份修改。希望采用自动入口,可
|
|
|
291
311
|
| 现象 | 先检查什么 |
|
|
292
312
|
|---|---|
|
|
293
313
|
| 没有 `install` 或 `control` 命令 | `npm view @ckanner/flywheel version` 与 `flywheel version`;是否仍是旧 0.22.1,PATH 或显式 `flywheelBinary` 是否指向旧版本 |
|
|
314
|
+
| 仍看到底部大弹层 | 已发布的 `0.28.0` 是旧布局;核对是否安装了包含会话视图修复的构建,再按宿主提示重新载入 |
|
|
315
|
+
| 顶部未直接显示 Flywheel | 检查视图栏更多入口、插件启用状态和实际版本;`/flywheel` 与 CLI 仍可用于诊断 |
|
|
294
316
|
| 安装 `ok:true`,但 `ready:false` | 安装已完成;按 `diagnostic.checks` 补齐当前配置需要的 CLI、目录或环境变量,再运行 doctor |
|
|
295
317
|
| npm 全局目录权限错误 | 使用自己可写的 `--prefix`,并把对应 `bin` 加入 shell PATH |
|
|
296
318
|
| desktop profile 被拒绝 | `--dsh-bin` 是否指向桌面安装的命令,而非单独 npm 安装的 DSH CLI |
|
|
@@ -304,7 +326,7 @@ launcher 被手工修改时,先备份修改。希望采用自动入口,可
|
|
|
304
326
|
| 改 channel 后账号没切换 | channel 是计量/配置别名;实际账号仍由 SDK profile/provider 的授权决定 |
|
|
305
327
|
| doctor 有 unknown 或 skipped | unknown 不等于通过,skipped 可能是非任务路由、mock 或没有请求 SDK probe |
|
|
306
328
|
| 费用显示未知 | 渠道未提供 cost/usage;unknown 不是免费,hard token budget 可能停止 |
|
|
307
|
-
|
|
|
329
|
+
| 启动/停止结果未确认 | 刷新同一任务并查看日志;超时或断连不证明任务未启动或已停止,不能自动重试变更 |
|
|
308
330
|
| L1 在 exit 0 后仍拒绝 | 检查候选漂移、输出截断、超时/取消或进程收尾错误 |
|
|
309
331
|
| 提交/合并/持久化检查失败 | 检查保留 worktree、hook 和 Git 差异,修复原因后恢复,不强制清理 |
|
|
310
332
|
| skills 安装拒绝已有目录 | 查看具体冲突;可能是用户修改、未标记目录、损坏清单或旧标记。按上面的备份恢复流程处理,`--force` 不绕过默认保护 |
|
|
@@ -323,7 +345,7 @@ npm uninstall --global @ckanner/flywheel
|
|
|
323
345
|
|
|
324
346
|
## 9. 开发与备用构建
|
|
325
347
|
|
|
326
|
-
以下用于贡献代码、检查未发布分支或离线备份;普通用户使用 npm 安装。需要 Git、Go 1.27 或更高、Node.js 22 或更高:
|
|
348
|
+
以下用于贡献代码、检查未发布分支或离线备份;普通用户使用 npm 安装。需要 Git、Go 1.27 或更高、Node.js 22.18.0 或更高:
|
|
327
349
|
|
|
328
350
|
```sh
|
|
329
351
|
git clone https://github.com/ckanner/flywheel.git
|
package/docs/workflow.md
ADDED
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
# 从需求准备到 PR 合并
|
|
2
|
+
|
|
3
|
+
[English](en/workflow.md) · 简体中文
|
|
4
|
+
|
|
5
|
+
本文描述 **Flywheel 0.28.0**的推荐工作流。新默认 `hard` 路由使用
|
|
6
|
+
Codex Pro 插件 machine API;源码存在不代表 npm `latest` 已更新,安装状态见
|
|
7
|
+
[发行指南](releasing.md)。下列命令是操作示例,不会因阅读本文自动执行。
|
|
8
|
+
|
|
9
|
+
建议先建立任务集成分支及独立 worktree,再准备契约、开 Draft PR、运行引擎。
|
|
10
|
+
Flywheel 将通过验收的 packet 合入任务分支;整个需求通过终验和远端检查后,
|
|
11
|
+
再由人或已获授权的宿主 Agent 合并 PR 到 `main`。
|
|
12
|
+
|
|
13
|
+
## 1. 选择准备阶段的模型
|
|
14
|
+
|
|
15
|
+
`flywheel-new` 使用当前 DSH 对话的模型。`loops.plan` 只控制引擎启动后的规划
|
|
16
|
+
和修订,不会替准备阶段切换模型。建议按需求的不确定性选择:
|
|
17
|
+
|
|
18
|
+
| 准备任务 | DSH Provider / 模型 | 思考等级 |
|
|
19
|
+
|---|---|---|
|
|
20
|
+
| 跨模块设计、协议与生命周期、复杂边界和验收设计 | `chatgpt` / `gpt-6-astra` | `high` |
|
|
21
|
+
| 范围清楚、已有代码与模式可参考的普通功能 | `chatgpt` / `gpt-6.1-sol` | `high` |
|
|
22
|
+
| 很明确的小修复、文档或重复模式的补充 | `deepseek-official` / `deepseek-flash` | `high` |
|
|
23
|
+
|
|
24
|
+
这是工程起点,不是本项目完成的模型 benchmark。准备错误可能影响多个 packet,
|
|
25
|
+
所以复杂需求值得在冻结契约前多检查一次;不必为每个小单元重复进行完整架构规划。
|
|
26
|
+
先使用 `high`,遇到仍未解决的关键设计问题,再对那次分析选择模型支持的更高档位。
|
|
27
|
+
[OpenAI reasoning 指南](https://developers.openai.com/api/docs/guides/reasoning)
|
|
28
|
+
说明 effort 的速度、用量与推理投入取舍;它不能证明本项目的最优档位。
|
|
29
|
+
|
|
30
|
+
开始前在 DSH 当前账号的模型目录核对 provider、精确模型 ID 和可选 effort。
|
|
31
|
+
目录与实际请求支持也可能有差异,不能把配置示例当成账号可用性证明。
|
|
32
|
+
`Codex Pro` 是插件名,不会自动选择 Pro 模型或最高思考档。
|
|
33
|
+
默认的运行期 Plan 仍为 Kimi CLI `kimi-code/k3.1-pro / high`,详见
|
|
34
|
+
[默认配置](../templates/flywheel.config.example.json);Kimi 别名也须在本机可用。
|
|
35
|
+
|
|
36
|
+
## 2. 先建立任务集成 worktree
|
|
37
|
+
|
|
38
|
+
假设当前位于业务仓库根目录,远端为 `origin`、目标分支为 `main`。
|
|
39
|
+
将示例任务名与目录名替换为本次需求;不同任务使用不同名称。
|
|
40
|
+
|
|
41
|
+
```sh
|
|
42
|
+
git status --short
|
|
43
|
+
git fetch origin
|
|
44
|
+
git worktree add -b task/my-feature ../repo-my-feature origin/main
|
|
45
|
+
cd ../repo-my-feature
|
|
46
|
+
git branch --show-current
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
最后应显示 `task/my-feature`。这组命令创建新分支和新目录,不切换或重置原
|
|
50
|
+
checkout 的分支。若分支或目录已存在,先检查其用途,不用强制参数覆盖。
|
|
51
|
+
在 DSH 中打开新目录 `repo-my-feature`,之后的契约、预检、启动和 PR 操作都以
|
|
52
|
+
这个任务 worktree 为工作目录。运行中不要切换该目录的分支或混入别的任务。
|
|
53
|
+
|
|
54
|
+
引擎中的“主 checkout”指传入的 `--cwd`,不固定指 `main`。单元通过后执行
|
|
55
|
+
`git merge --ff-only` 合回这个 checkout 当前所在分支。因此从任务分支启动,
|
|
56
|
+
内部 packet 就合入 `task/my-feature`;从 `main` 启动则会推进本地 `main`。
|
|
57
|
+
实现依据见 [worktree 操作](../internal/verify/verify.go) 与
|
|
58
|
+
[单元交付](../internal/machine/units.go)。
|
|
59
|
+
|
|
60
|
+
worktree 隔离工作目录和 index,不是安全沙箱。当前引擎默认尝试创建 packet
|
|
61
|
+
worktree,但创建失败时会记录原因并回退 `in-place`;它没有“必须隔离”的开关。
|
|
62
|
+
出现 `worktree unavailable` 时检查日志和工作区状态;需要严格隔离的任务应停止,
|
|
63
|
+
人工安排并核实隔离恢复。已经保存的 `in-place` 状态不会因修复目录或重新启动
|
|
64
|
+
就自动变成独立 worktree;不要手改 `state.json`,也不能把默认开启理解成任何
|
|
65
|
+
情况下都有独立工作区。
|
|
66
|
+
|
|
67
|
+
## 3. 在任务 worktree 中准备并审阅契约
|
|
68
|
+
|
|
69
|
+
确认当前目录仍是 `repo-my-feature`,读取准备 skill:
|
|
70
|
+
|
|
71
|
+
```sh
|
|
72
|
+
flywheel skills read flywheel-new
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
可向当前 DSH Agent 提出:
|
|
76
|
+
|
|
77
|
+
> 按 flywheel-new 为本需求建立 docs/my-feature。先查真实代码,写清需求、
|
|
78
|
+
> packet、路由、修改边界和可执行验收;试跑 L1 并记录结果,完成后供我审阅。
|
|
79
|
+
|
|
80
|
+
审阅至少覆盖:需求与 packet 的对应、L1/L2/L3 命令、失败出口、冻结验收路径,
|
|
81
|
+
以及模型和权限配置。100% 覆盖率如为任务要求,应有实际可执行的门禁命令。
|
|
82
|
+
不要填未经运行的验收结果;环境缺失应标记 unverified。不要手工创建或修改
|
|
83
|
+
`state.json`,它由引擎管理。完整要求见 [flywheel-new](../skills/flywheel-new/SKILL.md)。
|
|
84
|
+
|
|
85
|
+
按已有 Git 授权保存审阅后的契约,仅选择本任务文件:
|
|
86
|
+
|
|
87
|
+
```sh
|
|
88
|
+
git diff -- docs/my-feature
|
|
89
|
+
git add docs/my-feature
|
|
90
|
+
git diff --cached
|
|
91
|
+
git commit -m "docs(my-feature): add approved task contracts"
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
若冻结验收文件位于任务目录之外,审阅后显式补选那些路径。提交前确认暂存区
|
|
95
|
+
没有无关文件或凭证,不使用全仓库的 `git add .` 代替范围检查。契约必须实质
|
|
96
|
+
进入提交,packet worktree 才能从 Git 基线取得它;空提交不能替代这一步。
|
|
97
|
+
|
|
98
|
+
## 4. 尽早建立任务级 Draft PR
|
|
99
|
+
|
|
100
|
+
契约确认并提交后,就可以推送任务分支、建立 Draft PR,不必等全部实现结束。
|
|
101
|
+
以下使用已登录且有仓库权限的 GitHub CLI;也可在 GitHub 页面完成同样操作:
|
|
102
|
+
|
|
103
|
+
```sh
|
|
104
|
+
git push -u origin task/my-feature
|
|
105
|
+
gh pr create --draft --base main --head task/my-feature
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
按提示填写需求、范围、验收计划与当前状态。一个可独立交付的需求或里程碑通常
|
|
109
|
+
对应一个 PR;packet 是引擎内部工作单元,不必逐个开 PR。很大的需求应先拆成
|
|
110
|
+
可独立验证、回滚的里程碑。[Draft PR 无法合并](https://docs.github.com/en/pull-requests/reference/pull-requests),
|
|
111
|
+
适合保留进行中的差异、讨论和检查结果。CI 是否在 Draft 阶段运行取决于仓库配置。
|
|
112
|
+
|
|
113
|
+
## 5. 从同一个任务 worktree 启动
|
|
114
|
+
|
|
115
|
+
当前目录必须仍是 `repo-my-feature`,任务目录也应位于这个 worktree 中:
|
|
116
|
+
|
|
117
|
+
```sh
|
|
118
|
+
flywheel config inspect --cwd "$PWD" --task-dir "$PWD/docs/my-feature" --json
|
|
119
|
+
flywheel doctor --cwd "$PWD" --task-dir "$PWD/docs/my-feature" --probe --json
|
|
120
|
+
flywheel control start --cwd "$PWD" --task-dir "$PWD/docs/my-feature"
|
|
121
|
+
flywheel control status --cwd "$PWD" --task-dir "$PWD/docs/my-feature"
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
预检不发送模型推理,不能证明账号额度或真实模型调用已经通过。启动会实际调用
|
|
125
|
+
所选模型。在 DSH 面板操作时,也填写任务 worktree 的绝对路径及其内部任务路径,
|
|
126
|
+
不要把原 checkout 的 `docs/my-feature` 与新 worktree 的 `cwd` 混用。
|
|
127
|
+
|
|
128
|
+
每个 packet 的实现、L1 与独立 Review 通过后,引擎提交并快进合入任务分支。
|
|
129
|
+
所有 packet 完成后仍需里程碑 L2/L3 与 Judge;单元合并不代表整个需求已通过。
|
|
130
|
+
合并冲突或验证失败时保留产物并处理记录,不强制清理。停止与恢复见
|
|
131
|
+
[入门教程](getting-started.md#7-启动观察停止与恢复)。
|
|
132
|
+
|
|
133
|
+
若报告 `cleanup-unconfirmed` 或 `process cleanup is unconfirmed`,引擎会将本次
|
|
134
|
+
运行升级为 `escalated` 并停止自动执行,保留工作区和审计记录。先核对本次调用
|
|
135
|
+
拥有的 worker、guardian 和 app-server 是否已退出,再按恢复流程继续;不能仅
|
|
136
|
+
因外层 worker 已退出或已等待几秒,就假定内部进程不会再修改工作区。
|
|
137
|
+
|
|
138
|
+
### 5.1 Skills 入口与各 Loop 的工作目录
|
|
139
|
+
|
|
140
|
+
内置 skills 将任务 worktree 约定作为准备、启动、恢复和单环入口的检查步骤。
|
|
141
|
+
`flywheel-new` 在生成契约前创建或复用任务 worktree;`flywheel-run` 以及单环
|
|
142
|
+
skills 从实际任务目录解析同一 worktree 根,再调用 CLI。默认不从 `main`、
|
|
143
|
+
`master` 或 detached HEAD 启动开发;已有明确工作区选择与授权不重复询问。
|
|
144
|
+
恢复复用原任务路径及引擎保存的 packet 状态,不为恢复另建一份任务或复制 state。
|
|
145
|
+
|
|
146
|
+
| 阶段/入口 | 实际工作目录 | 谁负责选择或创建 |
|
|
147
|
+
|---|---|---|
|
|
148
|
+
| `flywheel-new` 准备契约 | 任务集成 worktree | 宿主 Agent 按 skill 创建或复用 |
|
|
149
|
+
| Plan | 任务集成 worktree,修订任务契约 | 引擎使用启动时的根目录 |
|
|
150
|
+
| Execute、L1、Review | 当前 packet 候选工作区;正常模式为 packet worktree | 引擎创建、记录并复用 packet worktree |
|
|
151
|
+
| L2/L3、Judge | 任务集成 worktree | 引擎验证已集成的需求与里程碑 |
|
|
152
|
+
| Intake、Garden | 所选任务所属 worktree | 入口解析目录,Go 写建议结果;DSH/Codex 后端请求只读,默认 Kimi 无 OS 级只读保证 |
|
|
153
|
+
| Status、Stop | 对应原任务路径与根目录 | 直接查询或停止,不要求为此新建 worktree、切分支或提交 |
|
|
154
|
+
|
|
155
|
+
因此,每个 Loop 不会各自新建一份 worktree。任务 worktree 贯穿整个需求,
|
|
156
|
+
packet worktree 贯穿该单元的执行、验收与评审;完成交付才由引擎处理本地合并
|
|
157
|
+
与清理。恢复入口仍是 `flywheel-run`,没有另一个独立的 resume skill。
|
|
158
|
+
`flywheel-verify` 只运行确定性验收:指定 packet 时只检查该单元 L1;未指定时
|
|
159
|
+
检查未完成单元 L1 与当前里程碑 L2/L3。它不调用 Review/Judge,也不创建 worktree。
|
|
160
|
+
|
|
161
|
+
Skill 的启动检查由宿主 Agent 遵守,CLI/GUI 直接调用不会自动执行这些 skill
|
|
162
|
+
正文,也不会自动创建外层任务分支。直接使用控制接口时仍须显式选择正确的
|
|
163
|
+
`cwd`/`taskDir`;引擎现有的 `in-place` 回退边界见第 2 节。只读查询和停止
|
|
164
|
+
不受开发分支检查阻碍,便于处理异常任务。
|
|
165
|
+
|
|
166
|
+
## 6. 完整终验后再合并 PR
|
|
167
|
+
|
|
168
|
+
确认 `state.status` 为 `completed`,需求覆盖、验收报告、独立评审及本地提交
|
|
169
|
+
都齐全,再核对工作区并推送任务分支。`control` 返回 `ok:true` 只代表控制操作成功。
|
|
170
|
+
|
|
171
|
+
```sh
|
|
172
|
+
git status --short
|
|
173
|
+
git log -5 --oneline
|
|
174
|
+
git push origin task/my-feature
|
|
175
|
+
gh pr ready
|
|
176
|
+
gh pr checks
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
由人或获授权的宿主检查 PR 最终差异、文档、剩余验证边界和当前 head 的远端 CI。
|
|
180
|
+
独立审阅应基于契约、差异和测试证据;执行模型自报完成不是审阅通过。
|
|
181
|
+
代码或 base 更新后,重新取得对应候选的检查与审阅,不能沿用旧提交的绿灯。
|
|
182
|
+
所有条件满足后再人工合并;合并后检查 main CI。发布仍是另一个发行步骤。
|
|
183
|
+
|
|
184
|
+
## 7. 自动合并与职责边界
|
|
185
|
+
|
|
186
|
+
当前 Flywheel 引擎负责本地状态、验收、提交和 packet 合并,**不自动 push、
|
|
187
|
+
创建 GitHub PR、等待远端 CI 或合并远端 PR**。本文的 GitHub 步骤由使用者或
|
|
188
|
+
获授权的宿主 Agent 执行,不能据此宣称引擎已实现远端交付自动化。
|
|
189
|
+
|
|
190
|
+
默认保留人工最终合并。若以后允许低风险任务自动合并,应先明确适用范围、
|
|
191
|
+
required checks、审阅要求和授权,再按仓库策略启用;Agent 的 pass 不能绕过门禁。
|
|
192
|
+
[GitHub auto-merge](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/incorporating-changes-from-a-pull-request/automatically-merging-a-pull-request)
|
|
193
|
+
用于等待既定要求满足后合并,不是取消要求。分支更新及过期审阅规则见
|
|
194
|
+
[受保护分支](https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/managing-protected-branches/about-protected-branches)。
|
|
195
|
+
|
|
196
|
+
更多依据:[Git worktree](https://git-scm.com/docs/git-worktree)、
|
|
197
|
+
[Astra 模型与 effort](https://developers.openai.com/api/docs/models/gpt-6-astra)、
|
|
198
|
+
[Kimi 模型配置](https://www.kimi.com/code/docs/en/kimi-code/models)、
|
|
199
|
+
[Flywheel 设计](design.md)。
|
package/npm/install.js
CHANGED
|
@@ -20,7 +20,7 @@ const HELP = `Flywheel npm installation
|
|
|
20
20
|
flywheel setup [options]
|
|
21
21
|
|
|
22
22
|
Install this exact version of the CLI, worker, embedded skills and DSH plugin.
|
|
23
|
-
No model inference or account login is performed. Node >=22 and the existing
|
|
23
|
+
No model inference or account login is performed. Node >=22.18.0 and the existing
|
|
24
24
|
DSH desktop command are prerequisites. Kimi/Codex availability is reported by
|
|
25
25
|
the local preflight; this installer does not replace another harness.
|
|
26
26
|
|
|
@@ -89,7 +89,7 @@ function npmCommand(environment = process.env) {
|
|
|
89
89
|
const script = environment.npm_execpath;
|
|
90
90
|
if (script && path.isAbsolute(script) && fs.existsSync(script)) return [process.execPath, [script]];
|
|
91
91
|
const binary = findExecutable("npm", environment);
|
|
92
|
-
if (!binary) throw new Error("npm is required; install Node.js 22 or newer, then rerun this command");
|
|
92
|
+
if (!binary) throw new Error("npm is required; install Node.js 22.18.0 or newer, then rerun this command");
|
|
93
93
|
return [binary, []];
|
|
94
94
|
}
|
|
95
95
|
|
|
@@ -227,7 +227,7 @@ function launcherContent({ cli, prefix, dshBin, environment = process.env }) {
|
|
|
227
227
|
return lines.join("\n");
|
|
228
228
|
}
|
|
229
229
|
|
|
230
|
-
async function writeLauncher({ directory, previous, cli, prefix, worker, dshBin, environment }) {
|
|
230
|
+
async function writeLauncher({ directory, previous, cli, prefix, worker, codexProWorker, adapter, dshBin, environment }) {
|
|
231
231
|
await fsp.mkdir(directory, { recursive: true });
|
|
232
232
|
const launcher = path.join(directory, "npm-launcher");
|
|
233
233
|
const content = launcherContent({ cli, prefix, dshBin, environment });
|
|
@@ -240,7 +240,7 @@ async function writeLauncher({ directory, previous, cli, prefix, worker, dshBin,
|
|
|
240
240
|
}
|
|
241
241
|
} catch (error) { if (error.code !== "ENOENT") throw error; }
|
|
242
242
|
await atomicWrite(launcher, content, 0o755);
|
|
243
|
-
const receipt = { protocol: 1, owner: OWNER, version: meta.version, prefix, cli, worker,
|
|
243
|
+
const receipt = { protocol: 1, owner: OWNER, version: meta.version, prefix, cli, worker, codexProWorker, adapter,
|
|
244
244
|
node: process.execPath, launcher: { path: launcher, sha256: digest(content) } };
|
|
245
245
|
await atomicWrite(path.join(directory, "installation.json"), JSON.stringify(receipt, null, 2) + "\n", 0o600);
|
|
246
246
|
return receipt;
|
|
@@ -290,7 +290,7 @@ async function install(options, { environment = process.env, cwd = process.cwd()
|
|
|
290
290
|
};
|
|
291
291
|
try {
|
|
292
292
|
if (!['darwin', 'linux'].includes(process.platform) || !['arm64', 'x64'].includes(process.arch)) throw new Error("unsupported installation platform");
|
|
293
|
-
|
|
293
|
+
require('../bin/runtime.js').assertSupportedNode();
|
|
294
294
|
const home = environment.HOME;
|
|
295
295
|
if (!home || !path.isAbsolute(home)) throw new Error("HOME must identify the user's absolute home directory");
|
|
296
296
|
const directory = path.join(home, ".config", "flywheel");
|
|
@@ -314,7 +314,16 @@ async function install(options, { environment = process.env, cwd = process.cwd()
|
|
|
314
314
|
if (installed.name !== OWNER || installed.version !== meta.version) throw new Error("installed package does not match this installer version");
|
|
315
315
|
const installedRequire = createRequire(path.join(installedRoot, "package.json"));
|
|
316
316
|
const runtime = installedRequire("./bin/runtime.js");
|
|
317
|
-
report.paths = { cli: path.join(installedRoot, "bin", "flywheel.js"), native: runtime.loadNativePath(), worker: runtime.loadWorkerPath()
|
|
317
|
+
report.paths = { cli: path.join(installedRoot, "bin", "flywheel.js"), native: runtime.loadNativePath(), worker: runtime.loadWorkerPath(),
|
|
318
|
+
codexProWorker: runtime.loadCodexProWorkerPath() };
|
|
319
|
+
const probe = await run(process.execPath, [report.paths.codexProWorker, '--doctor']);
|
|
320
|
+
requireSuccess(probe, 'installed Codex Pro dependency');
|
|
321
|
+
const adapter = parseDocument(probe, 'installed Codex Pro dependency');
|
|
322
|
+
if (adapter.protocol !== 1 || adapter.type !== 'doctor' || adapter.package !== 'dsh-subagent-codex-pro' ||
|
|
323
|
+
adapter.version !== '0.8.0' || adapter.machineProtocol !== 1 || adapter.available !== true || adapter.inferenceTested !== false) {
|
|
324
|
+
throw new Error('installed Codex Pro dependency did not verify the exact public machine API');
|
|
325
|
+
}
|
|
326
|
+
report.adapter = { package: adapter.package, version: adapter.version, protocol: adapter.machineProtocol, inferenceTested: false };
|
|
318
327
|
const version = requireSuccess(await run(process.execPath, [report.paths.cli, "version"]), "installed CLI version");
|
|
319
328
|
if (!version.split(/\s+/).includes(meta.version)) throw new Error("native binary version does not match the npm package");
|
|
320
329
|
item.version = version;
|
|
@@ -333,7 +342,8 @@ async function install(options, { environment = process.env, cwd = process.cwd()
|
|
|
333
342
|
const requestedDsh = options.dshBin ?? environment.FLYWHEEL_DSH_BIN ?? "dsh";
|
|
334
343
|
const dshBin = findExecutable(requestedDsh, environment);
|
|
335
344
|
await step("desktop-launcher", async item => {
|
|
336
|
-
const receipt = await writeLauncher({ directory, previous, cli: report.paths.cli, prefix, worker: report.paths.worker,
|
|
345
|
+
const receipt = await writeLauncher({ directory, previous, cli: report.paths.cli, prefix, worker: report.paths.worker,
|
|
346
|
+
codexProWorker: report.paths.codexProWorker, adapter: report.adapter, dshBin, environment });
|
|
337
347
|
report.paths.launcher = receipt.launcher.path;
|
|
338
348
|
item.path = receipt.launcher.path;
|
|
339
349
|
});
|
package/package.json
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ckanner/flywheel",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "0.28.1",
|
|
4
|
+
"description": "A deterministic Go orchestrator for coding-agent loops, with task contracts, verification gates, Git worktrees, and DSH desktop integration.",
|
|
5
5
|
"bin": {
|
|
6
6
|
"flywheel": "bin/flywheel.js",
|
|
7
|
-
"flywheel-dsh-worker": "bin/flywheel-dsh-worker.js"
|
|
7
|
+
"flywheel-dsh-worker": "bin/flywheel-dsh-worker.js",
|
|
8
|
+
"flywheel-codex-pro-worker": "bin/flywheel-codex-pro-worker.js"
|
|
8
9
|
},
|
|
9
10
|
"os": [
|
|
10
11
|
"darwin",
|
|
@@ -15,7 +16,7 @@
|
|
|
15
16
|
"arm64"
|
|
16
17
|
],
|
|
17
18
|
"engines": {
|
|
18
|
-
"node": ">=22.
|
|
19
|
+
"node": ">=22.18.0"
|
|
19
20
|
},
|
|
20
21
|
"repository": {
|
|
21
22
|
"type": "git",
|
|
@@ -26,25 +27,31 @@
|
|
|
26
27
|
"bin",
|
|
27
28
|
"npm/*.js",
|
|
28
29
|
"README.md",
|
|
30
|
+
"README.en.md",
|
|
29
31
|
"CHANGELOG.md",
|
|
30
32
|
"docs/getting-started.md",
|
|
31
33
|
"docs/configuration.md",
|
|
34
|
+
"docs/workflow.md",
|
|
35
|
+
"docs/en/getting-started.md",
|
|
36
|
+
"docs/en/configuration.md",
|
|
37
|
+
"docs/en/workflow.md",
|
|
32
38
|
"docs/examples/create-first-task.sh"
|
|
33
39
|
],
|
|
34
40
|
"optionalDependencies": {
|
|
35
|
-
"@ckanner/flywheel-darwin-arm64": "0.
|
|
36
|
-
"@ckanner/flywheel-darwin-amd64": "0.
|
|
37
|
-
"@ckanner/flywheel-linux-arm64": "0.
|
|
38
|
-
"@ckanner/flywheel-linux-amd64": "0.
|
|
41
|
+
"@ckanner/flywheel-darwin-arm64": "0.28.1",
|
|
42
|
+
"@ckanner/flywheel-darwin-amd64": "0.28.1",
|
|
43
|
+
"@ckanner/flywheel-linux-arm64": "0.28.1",
|
|
44
|
+
"@ckanner/flywheel-linux-amd64": "0.28.1"
|
|
39
45
|
},
|
|
40
46
|
"scripts": {
|
|
41
47
|
"release:check": "node scripts/release-preflight.js",
|
|
48
|
+
"release:local": "node scripts/release-local.js",
|
|
42
49
|
"test": "node --test npm/test/*.test.js",
|
|
43
50
|
"test:install": "node --test npm/test/install.integration.js",
|
|
44
51
|
"test:registry": "node npm/test/registry-smoke.js",
|
|
45
|
-
"build:npm": "bash scripts/build-npm.sh 0.
|
|
52
|
+
"build:npm": "bash scripts/build-npm.sh 0.28.1 dist-npm"
|
|
46
53
|
},
|
|
47
54
|
"dependencies": {
|
|
48
|
-
"@ckanner/dsh-plugin-flywheel": "0.
|
|
55
|
+
"@ckanner/dsh-plugin-flywheel": "0.28.1"
|
|
49
56
|
}
|
|
50
57
|
}
|