openfeel 1.2.4 → 1.3.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.
Files changed (51) hide show
  1. package/README.en.md +40 -74
  2. package/README.md +39 -62
  3. package/README.zh-CN.md +40 -74
  4. package/dist/commands/setup.d.ts.map +1 -1
  5. package/dist/commands/setup.js +90 -5
  6. package/dist/commands/setup.js.map +1 -1
  7. package/dist/commands/update.d.ts.map +1 -1
  8. package/dist/commands/update.js +7 -2
  9. package/dist/commands/update.js.map +1 -1
  10. package/dist/core/config.js +2 -2
  11. package/dist/core/dsh-profile.d.ts +93 -0
  12. package/dist/core/dsh-profile.d.ts.map +1 -0
  13. package/dist/core/dsh-profile.js +400 -0
  14. package/dist/core/dsh-profile.js.map +1 -0
  15. package/dist/core/i18n-data/en.d.ts.map +1 -1
  16. package/dist/core/i18n-data/en.js +21 -2
  17. package/dist/core/i18n-data/en.js.map +1 -1
  18. package/dist/core/i18n-data/zh-CN.d.ts.map +1 -1
  19. package/dist/core/i18n-data/zh-CN.js +21 -2
  20. package/dist/core/i18n-data/zh-CN.js.map +1 -1
  21. package/dist/core/setup.d.ts +12 -1
  22. package/dist/core/setup.d.ts.map +1 -1
  23. package/dist/core/setup.js +25 -10
  24. package/dist/core/setup.js.map +1 -1
  25. package/dist/core/template-loader.d.ts.map +1 -1
  26. package/dist/core/template-loader.js +18 -9
  27. package/dist/core/template-loader.js.map +1 -1
  28. package/dist/core/update.d.ts +2 -0
  29. package/dist/core/update.d.ts.map +1 -1
  30. package/dist/core/update.js +25 -7
  31. package/dist/core/update.js.map +1 -1
  32. package/dsh/ACTION-GUIDE.md +366 -0
  33. package/dsh/ADAPTER.md +65 -0
  34. package/dsh/README.md +264 -0
  35. package/dsh/cordis.patch.yml +26 -0
  36. package/dsh/docs/compat/commands.md +873 -0
  37. package/dsh/docs/compat/kb-skills.md +883 -0
  38. package/dsh/docs/compat/persistence.md +1013 -0
  39. package/dsh/docs/compat/pipeline.md +1565 -0
  40. package/dsh/docs/compat/req.md +1243 -0
  41. package/dsh/docs/compat/stage.md +1437 -0
  42. package/dsh/lib/adapters/cli.js +624 -0
  43. package/dsh/lib/adapters/dashboard.js +393 -0
  44. package/dsh/lib/adapters/workspace.js +150 -0
  45. package/dsh/lib/index.js +189 -0
  46. package/dsh/lib/surface/command.js +186 -0
  47. package/dsh/lib/surface/prompt.js +131 -0
  48. package/dsh/lib/tools/index.js +1245 -0
  49. package/dsh/lib/tools/shared.js +320 -0
  50. package/dsh/package.json +45 -0
  51. package/package.json +9 -2
package/dsh/README.md ADDED
@@ -0,0 +1,264 @@
1
+ # OpenFeel × DSH — Feel 模式适配器
2
+
3
+ > **这是 OpenFeel 的 DSH 适配版本,不是独立项目。**
4
+ > 它把 OpenFeel 的 CLI 与 `.openfeel/` 工作区投影到 DeepSeek Harness(DSH),
5
+ > 让 agent 与用户都能在 DSH 内使用 Feel 流程。**领域逻辑、门禁判定、持久化契约
6
+ > 全部留在 OpenFeel CLI 里**,适配器不做第二份实现。
7
+
8
+ - 适配器位置:**本目录** = OpenFeel 仓库的 `dsh/`(与 `claude/`、`kilo/`、`.opencode/` 同级的
9
+ 一等适配器)。`OpenFeel-DSH/plugin` 是指向本目录的目录联接。
10
+ - 权威契约:[`docs/json-contract.md`](https://github.com/Liuary/OpenFeel/blob/master/docs/json-contract.md)(40 个成功 `--json` 出口冻结表)
11
+ - 宿主:DSH `0.2.0-rc.2`,profile `web` / `desktop`
12
+
13
+ ---
14
+
15
+ ## 1. 设计原则
16
+
17
+ | 原则 | 含义 |
18
+ |---|---|
19
+ | **单一权威** | 相位转移、需求 done 门、REV 阻塞门、版本归档判据、`flow.json` revision CAS —— 全部由 `openfeel` CLI 执行。适配器只翻译意图与结果。 |
20
+ | **零运行时依赖** | 只用 Node 内置模块,因此不依赖任何 DSH 内部包即可被 Loader 加载。 |
21
+ | **拒绝即信息** | CLI 的门禁拒绝原样透传给模型,并附可操作的纠正建议。适配器不吞错、不猜门禁。 |
22
+ | **不碰用户数据** | 不手改 `flow.json` / `status.md`;不读 `.openfeel/flow-archive/**`。 |
23
+
24
+ 为什么不做实现层适配:`flow.json` 有乐观并发(`meta.revision` CAS)、文件锁、
25
+ 跨文件对账等不变量;直接写盘会破坏它们。绕开 CLI 的第二个实现迟早与主体漂移。
26
+
27
+ ---
28
+
29
+ ## 2. 安装
30
+
31
+ **方式 0(推荐,单包)**:适配器已随 `openfeel` npm 包分发(`openfeel` ≥ 1.3.0),无需单独安装本目录:
32
+
33
+ ```bash
34
+ npm i -g openfeel@latest # 1. 安装/升级(包内已含 dsh/)
35
+ openfeel setup --tools dsh # 2. 写入 DSH profile + 按需 pnpm install(可 --dsh-profile web)
36
+ # 3. 重启 DSH 宿主
37
+ ```
38
+
39
+ `setup --tools dsh` 会写入 `<DSH_HOME>/profiles/<name>/package.json` 的
40
+ `dependencies["openfeel-dsh"] = "link:<openfeelRoot>/dsh"` 与 `dsh.profile.bundles`;
41
+ 写前备份、幂等重跑、失败回滚。`openfeel update --tools dsh` 不适用(DSH 是全局部署)。
42
+
43
+ **方式 A(开发态)**:把本目录链接进 profile(改动重启即生效):
44
+
45
+ ```powershell
46
+ # 在 %USERPROFILE%\.dsh\profiles\web\package.json
47
+ # dependencies 加入: "openfeel-dsh": "link:<repo>/dsh"
48
+ # dsh.profile.bundles 加入: "openfeel-dsh"
49
+ # 然后:
50
+ pnpm install --prefer-offline
51
+
52
+ # 方式 B:经插件管理器安装(file: 拷贝,改代码后需重装)
53
+ # plugin_manager install_bundle → file:<repo>\dsh
54
+ ```
55
+
56
+ **前置条件**:已安装 OpenFeel CLI(`npm install -g openfeel`,`openfeel --version` 可用)。
57
+ 适配器会自动在 PATH、npm 全局 bin、`node` 同目录下探测可执行文件——包括
58
+ Windows 上的 `openfeel.cmd` 垫片。
59
+
60
+ > ⚠️ **改完插件代码需重启 DSH 宿主**。Loader 按 URL 缓存 ESM 模块,重新
61
+ > enable bundle 不会重新导入已加载的模块代码。
62
+
63
+ ---
64
+
65
+ ## 3. 配置
66
+
67
+ ```yaml
68
+ - insert:
69
+ - id: openfeel-feel
70
+ name: 'openfeel-dsh'
71
+ config:
72
+ command: openfeel # CLI 可执行文件;也可填绝对路径
73
+ commandPrefix: [] # 从源码跑时:[node, <repo>/bin/openfeel.js]
74
+ timeoutMs: 120000 # 单次调用超时
75
+ log: false # 是否写 ~/.openfeel/cli/logs/(默认关闭,只读沙箱更安全)
76
+ autoPrompt: true # 是否注入 Feel 纪律系统提示段
77
+ language: zh-CN # 提示段语言:zh-CN | en
78
+ cwd: null # 兜底工作目录(默认取会话工作区)
79
+ ```
80
+
81
+ `normalizeConfig` 对非法值做安全回落(如 `timeoutMs: -5` → `120000`)。
82
+
83
+ ---
84
+
85
+ ## 4. 工具面(13 个)
86
+
87
+ 适配器在 DSH 工具注册表上注册 13 个工具,全部经 `openfeel` CLI 执行。
88
+
89
+ | 工具 | 覆盖的 CLI | 能力域 |
90
+ |---|---|---|
91
+ | `feel_status` | `flow next --json`(权威)→ 失败回退 `flow status --json` + `flow mode --json`(+`req list --json`) | **状态快照**:宏观相位、每阶段相位、模式与来源、合法下一相位、负责 Agent、审查档位、守卫、阻塞审查 |
92
+ | `feel_next` | 同上快照的派生决策(`flow next --json` 字段直出) | **该谁做**:负责 Agent、合法下一相位、建议命令、守卫、阻塞审查、推荐工具调用、`[HANDOFF: agent]` 标记 |
93
+ | `feel_flow` | `flow advance/current/overview/phases/mode/log/metrics/retry/repair/migrate/review_*` | 流水线推进与审查条目 |
94
+ | `feel_stage` | `plan stage add/list`、`stage status/set/task`、`flow stage set/reset/remove` | 阶段与 `status.md` |
95
+ | `feel_op` | `flow ops list`、`plan scheme create/publish/rename/remove/register`、`flow attempt/retry` | 操作方案与执行结果 |
96
+ | `feel_req` | `req add/list/show/board/next/claim/release/set/link/advance/split` | 需求分发(7 状态) |
97
+ | `feel_checkpoint` | `flow checkpoint list/restore` | 检查点快照与选择性回退 |
98
+ | `feel_archive` | `flow archive <version>/list/show`、`archive <stage>` | 版本分片归档 + 阶段摘要归档 |
99
+ | `feel_kb` | `knowledge list/add/search/index/dedup` | 知识库(4 个固定分类) |
100
+ | `feel_verify` | `flow health`、`lint i18n/kb`、`flow recover`、`project overview`、`config get/set/effective` | 健康检查与配置 |
101
+ | `feel_review` | `view list/accept` | REV 条目视图 |
102
+ | `feel_plan` | `plan stage list`、`plan scheme list`、`roadmap create/show`、`instructions` | 计划与路线图 |
103
+ | `feel_model` | `model list/get/set` | Agent 模型意识配置 |
104
+
105
+ ### 输出契约
106
+
107
+ 所有工具返回统一封装:
108
+
109
+ ```json
110
+ {
111
+ "ok": true,
112
+ "action": "advance",
113
+ "summary": "v1.2.3-stage-99 已推进到 done。",
114
+ "details": "{ …CLI 结构化数据的 JSON 文本… }",
115
+ "next": { "tool": "feel_next", "arguments": "{}", "why": "…" }
116
+ }
117
+ ```
118
+
119
+ **为什么结构化数据是字符串**:DSH 强制的 JSON Schema 子集不接受无类型节点,而
120
+ provider 桥接层会把「只有 description、没有 type」的节点转成 `type: null`,API 随即
121
+ 以 `schema must be a JSON Schema of 'type: "object"', got 'type: null'` 拒绝整个工具。
122
+ 把载荷序列化成 `details: string` 是跨 provider 稳定的唯一写法。
123
+
124
+ ### 错误分类(v1.2.3 契约)
125
+
126
+ `--json` 失败时 CLI 输出单文档 envelope:
127
+
128
+ ```json
129
+ { "schemaVersion": 1, "error": { "code": "PHASE_TRANSITION_ILLEGAL", "kind": "refusal", "message": "…", "detail": { "from": "done", "to": "exec_running" } } }
130
+ ```
131
+
132
+ `errorFromResult` 的判定顺序:
133
+
134
+ 1. stdout 是可解析 JSON 且 `error` 为**对象** → 透传 `error.code` / `error.kind` / `error.message` / `error.detail`。
135
+ 2. 退出码 `2` → `refusal`(flow.json 乐观并发冲突,唯一可重试信号)。
136
+ 3. 退出码 `3` → `internal`。
137
+ 4. 退出码 `1` 且无 envelope → 按 `kind`(若 legacy `errorKind` 存在)或「有无堆栈」启发式兜底。
138
+ 5. legacy `{ "error": "..." }`(`error` 为字符串)与无 JSON 的人类输出保持兼容。
139
+
140
+ ### 参数 schema
141
+
142
+ 模拟器直连 `ctx.tools.register()`(不经 `defineTool`),而注册表**既不编译也不校验**
143
+ `parameters`,会原样投影给模型。因此作者侧沿用属性级 `required: true`,在交出前由
144
+ `compileParameters()` 统一转成裸 JSON Schema(根 `type: 'object'` + 对象级 `required` 数组)。
145
+
146
+ ---
147
+
148
+ ## 5. 命令面 `/feel`
149
+
150
+ 面向人的轻量入口,直接回显 OpenFeel 原生可读输出:
151
+
152
+ ```
153
+ /feel 帮助
154
+ /feel status 流水线状态
155
+ /feel next 下一步该谁做
156
+ /feel overview 全状态视图
157
+ /feel board 需求看板(7 组)
158
+ /feel recover 跨会话上下文恢复
159
+ /feel health [--fix] 健康检查
160
+ /feel stage [<id>] 阶段状态
161
+ /feel req <REQ-NNN> 需求详情
162
+ /feel claim <REQ-NNN> 认领需求
163
+ /feel advance <stage> <phase> 推进相位
164
+ /feel archive list 已归档版本
165
+ /feel kb <query> 知识库检索
166
+ /feel config 有效配置与来源
167
+ ```
168
+
169
+ 写操作一律交给 CLI:门禁拒绝原因原样回显。
170
+
171
+ ---
172
+
173
+ ## 6. 系统提示面
174
+
175
+ 启用 `autoPrompt` 时注入 `<feel_mode>` 段落,教会 agent **OpenFeel 的纪律**而非重复工具说明:
176
+
177
+ - 角色 = 调度者不是执行者;15 相位各有负责 Agent。
178
+ - **调度目标是活跃阶段**:`pipeline.phase` 只是宏观态,取 `phase != done` 的阶段。
179
+ - 禁止手改 `flow.json` / `status.md`。
180
+ - 门禁拒绝是预期结果,不得用 `force` 绕过(`--force` 也不能绕过 blocking REV 门与归档判据)。
181
+ - 退出码 `2` = 并发冲突,可重试;`3` = 内部故障;`--json` 失败 envelope 是分类权威(见 §4「错误分类」)。
182
+ - `auto_advance=disabled` 时推进前必须询问用户。
183
+ - 三种模式(full / fast / general)与需求 7 状态流转。
184
+
185
+ 段落正文每次装配时探测 `.openfeel/` 是否存在,因此提示会随工作区状态变化。
186
+
187
+ ---
188
+
189
+ ## 7. 验证
190
+
191
+ 三套测试,全部本地可跑:
192
+
193
+ ```powershell
194
+ cd plugin
195
+ node test/contract.js # DSH 契约:schema 子集、无 type:null、参数契约(42 项)
196
+ node test/verify.js # 行为:真实 CLI + 真实 .openfeel 副本(77 项)
197
+ node test/integration.js # 真实注册表:真 cordis + 真 ToolRuntime 挂载(10 项)
198
+ ```
199
+
200
+ - `contract.js` 用宿主 asar 提取出的**真实** `assertSupportedJsonSchema`。
201
+ - `verify.js` 对真实 OpenFeel 项目做只读校验,**所有写操作只打在 `os.tmpdir()` 副本上**,并断言原项目 `revision` 未被改动。
202
+ - `integration.js` 构造真实 Cordis 上下文 + 真实 `ToolRuntime`,调用适配器 `apply()`,断言 13 个工具真的完成注册与投影。
203
+
204
+ 依赖提取:三套测试默认读 `%TEMP%\dsh-asar\dsh\node_modules\@deepseek-ai`(从宿主
205
+ `app.asar` 解出的包)。缺失时 `contract.js` / `integration.js` 会跳过并说明。
206
+
207
+ ---
208
+
209
+ ## 8. 目录结构
210
+
211
+ ```
212
+ dsh/ # OpenFeel 仓库内的一等适配器目录
213
+ ├── ADAPTER.md # 适配器说明(对齐 claude/ADAPTER.md、kilo/ADAPTER.md)
214
+ ├── package.json # dsh.bundle.patch 声明 → Loader 可挂载
215
+ ├── cordis.patch.yml # 一行 insert:id=openfeel-feel, name=openfeel-dsh
216
+ ├── lib/
217
+ │ ├── index.js # 插件入口:name / inject / apply / normalizeConfig
218
+ │ ├── adapters/
219
+ │ │ ├── cli.js # CLI 执行器:可执行文件解析、UTF-8/无色/无日志、退出码语义
220
+ │ │ ├── workspace.js # 会话工作区 = 项目根(与 CLI 一致,**不回溯**)
221
+ │ │ └── dashboard.js # 状态快照 + 「下一步」决策(消费 flow next/status,无相位→Agent 本地镜像)
222
+ │ ├── tools/
223
+ │ │ ├── index.js # 13 个工具定义与 CLI argv 翻译
224
+ │ │ └── shared.js # 输出封装、参数编译、渲染
225
+ │ └── surface/
226
+ │ ├── command.js # /feel 命令
227
+ │ └── prompt.js # <feel_mode> 系统提示段
228
+ ├── docs/compat/ # OpenFeel v1.2.1 逆向兼容性契约(6 份,仅供回归参照)
229
+ └── test/
230
+ ├── contract.js # DSH schema 契约
231
+ ├── verify.js # 行为验证(真实 CLI)
232
+ └── integration.js # 真实注册表挂载
233
+ ```
234
+
235
+ > `OpenFeel-DSH/` 是集成工作区:`plugin/` 与 `docs/compat/` 都是指向本目录的**目录联接**,
236
+ > 因此两处的相对路径引用同时有效,而真实文件只有一份。
237
+
238
+ ---
239
+
240
+ ## 9. 已知限制
241
+
242
+ 1. **改代码需重启宿主**:Loader 按 URL 缓存 ESM 模块;`set_bundle enable` 不会重新导入。
243
+ 用 `link:` 依赖可避免每次重装,但仍需重启。
244
+ 2. **项目解析与 CLI 一致,不回溯**:会话工作区**本身**即项目根(`openfeel flow status`
245
+ 在深层子目录返回空态可证 CLI 从不回溯)。判定项目以 `.openfeel/flow.json` 或
246
+ `config.yaml` 为标记;`~/.openfeel/`(`openfeel setup` 的**全局家目录**)不含这些标记,
247
+ 因此不会被误判为项目。未命中项目时工具返回 `refusal` 并提示 `openfeel init`,
248
+ 提示段则**完全不注入**。
249
+ > 若需要 monorepo(子目录里工作),那应作为 OpenFeel CLI 的能力
250
+ > (如 `openfeel project resolve --json`)由各适配器共享,而不是每个 harness 各写一套回溯。
251
+ 3. **CLI 契约(v1.3.0)**:`flow next --json` 提供调度决策;`flow status --json` 的
252
+ `stages[]` 已含 `workflowMode` / `requirementId` / `reviewTier` / `effectiveReviewTier` /
253
+ `opsSummary`;`--json` 失败输出 envelope(`error.code` / `kind` / `detail`)为分类权威;
254
+ `flow advance --json` 仅用于失败 envelope。v1.2.4 起共 **40 个成功 `--json` 出口**,
255
+ 适配器消费其中 **32 处**。详见 [操作指南](https://github.com/Liuary/OpenFeel/blob/master/dsh/ACTION-GUIDE.md) 与
256
+ [更新说明](https://github.com/Liuary/OpenFeel/blob/master/docs/dsh-cli-requirements-supplement-1.2.3.md)。
257
+ 4. **读命令已全面结构化**:v1.2.4 补齐了 `plan stage list` / `model list|get` / `flow retry` /
258
+ `lint` / `roadmap show` / `config get --all`,适配器文本回显降到 **1 处**
259
+ (仅 `instructions` 的 XML 默认形态)。`--json` 调用点 **32** 处。
260
+ 5. **`stage_summary` 默认拒绝覆盖**:v1.2.4 起 `archive <stage>` 对已存在的归档文件返回
261
+ `ARCHIVE_EXISTS`(refusal)且零写盘;确需覆盖须传 `force=true`,会冲掉人工整理的摘要。
262
+ 6. **超时**:默认单次 120s。超大 `flow.json`(数百 KB)的 `flow status` 可能接近上限。
263
+ 7. **不替代 agent 委派**:`feel_next` 给出负责 Agent 与 `[HANDOFF: agent]` 标记,实际派发
264
+ 由 DSH 的 `subagent` / `workflow` 完成——DSH 没有 OpenFeel 的 `Task` 语义。
@@ -0,0 +1,26 @@
1
+ # OpenFeel × DSH bundle patch
2
+ #
3
+ # This is the DSH adaptation layer of OpenFeel: one loader row that mounts the
4
+ # Feel-mode adapter. The adapter projects OpenFeel's CLI and `.openfeel/`
5
+ # workspace into DeepSeek Harness — it owns no domain state of its own, so all
6
+ # pipeline, requirement, and archive authority stays with the OpenFeel CLI.
7
+ #
8
+ # A profile mounts this bundle by listing `openfeel-dsh` in
9
+ # `dsh.profile.bundles`; the row below is then inserted over the profile root.
10
+ # Later layers (and the user's own cordis.patch.yml) address it by `id`.
11
+
12
+ - insert:
13
+ - id: openfeel-feel
14
+ name: 'openfeel-dsh'
15
+ config:
16
+ # CLI 可执行文件:默认走 PATH / npm 全局 bin / node 同目录探测。
17
+ command: openfeel
18
+ # 单次调用超时(毫秒)。大项目 flow.json 可达数百 KB,放宽到 120s。
19
+ timeoutMs: 120000
20
+ # 是否写 OpenFeel CLI 运行日志(~/.openfeel/cli/logs/)。
21
+ # 默认关闭:只读沙箱下写全局目录会失败,且该日志对 agent 无价值。
22
+ log: false
23
+ # 是否注入 Feel 纪律系统提示段。启用 Feel 模式时通常应为 true。
24
+ autoPrompt: true
25
+ # 系统提示段语言:zh-CN | en
26
+ language: zh-CN