openfeel 1.1.1 → 1.1.3

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 (196) hide show
  1. package/README.en.md +41 -11
  2. package/README.md +8 -3
  3. package/README.zh-CN.md +42 -12
  4. package/bin/openfeel.js +5 -0
  5. package/dist/cli/index.d.ts +15 -3
  6. package/dist/cli/index.d.ts.map +1 -1
  7. package/dist/cli/index.js +59 -15
  8. package/dist/cli/index.js.map +1 -1
  9. package/dist/cli/output-encoding.d.ts +32 -0
  10. package/dist/cli/output-encoding.d.ts.map +1 -0
  11. package/dist/cli/output-encoding.js +120 -0
  12. package/dist/cli/output-encoding.js.map +1 -0
  13. package/dist/cli/repl.d.ts +2 -2
  14. package/dist/cli/repl.d.ts.map +1 -1
  15. package/dist/cli/repl.js +46 -25
  16. package/dist/cli/repl.js.map +1 -1
  17. package/dist/commands/config.d.ts.map +1 -1
  18. package/dist/commands/config.js +56 -9
  19. package/dist/commands/config.js.map +1 -1
  20. package/dist/commands/flow.d.ts.map +1 -1
  21. package/dist/commands/flow.js +827 -138
  22. package/dist/commands/flow.js.map +1 -1
  23. package/dist/commands/init.d.ts.map +1 -1
  24. package/dist/commands/init.js +56 -42
  25. package/dist/commands/init.js.map +1 -1
  26. package/dist/commands/knowledge.d.ts.map +1 -1
  27. package/dist/commands/knowledge.js +69 -0
  28. package/dist/commands/knowledge.js.map +1 -1
  29. package/dist/commands/lint.d.ts.map +1 -1
  30. package/dist/commands/lint.js +17 -5
  31. package/dist/commands/lint.js.map +1 -1
  32. package/dist/commands/migrate.d.ts.map +1 -1
  33. package/dist/commands/migrate.js +6 -1
  34. package/dist/commands/migrate.js.map +1 -1
  35. package/dist/commands/model.d.ts.map +1 -1
  36. package/dist/commands/model.js +18 -1
  37. package/dist/commands/model.js.map +1 -1
  38. package/dist/commands/plan.d.ts.map +1 -1
  39. package/dist/commands/plan.js +185 -7
  40. package/dist/commands/plan.js.map +1 -1
  41. package/dist/commands/project.js +2 -2
  42. package/dist/commands/project.js.map +1 -1
  43. package/dist/commands/roadmap.d.ts.map +1 -1
  44. package/dist/commands/roadmap.js +20 -5
  45. package/dist/commands/roadmap.js.map +1 -1
  46. package/dist/commands/setup.d.ts +1 -1
  47. package/dist/commands/setup.d.ts.map +1 -1
  48. package/dist/commands/setup.js +8 -2
  49. package/dist/commands/setup.js.map +1 -1
  50. package/dist/commands/shared/errors.d.ts +22 -0
  51. package/dist/commands/shared/errors.d.ts.map +1 -0
  52. package/dist/commands/shared/errors.js +45 -0
  53. package/dist/commands/shared/errors.js.map +1 -0
  54. package/dist/commands/stage.d.ts.map +1 -1
  55. package/dist/commands/stage.js +133 -23
  56. package/dist/commands/stage.js.map +1 -1
  57. package/dist/commands/view.d.ts +1 -1
  58. package/dist/commands/view.d.ts.map +1 -1
  59. package/dist/commands/view.js +4 -26
  60. package/dist/commands/view.js.map +1 -1
  61. package/dist/core/archive/merge.d.ts.map +1 -1
  62. package/dist/core/archive/merge.js +9 -5
  63. package/dist/core/archive/merge.js.map +1 -1
  64. package/dist/core/artifact-graph/graph.d.ts +7 -2
  65. package/dist/core/artifact-graph/graph.d.ts.map +1 -1
  66. package/dist/core/artifact-graph/graph.js +25 -18
  67. package/dist/core/artifact-graph/graph.js.map +1 -1
  68. package/dist/core/artifact-graph/instruction-loader.d.ts.map +1 -1
  69. package/dist/core/artifact-graph/instruction-loader.js +4 -33
  70. package/dist/core/artifact-graph/instruction-loader.js.map +1 -1
  71. package/dist/core/backup.d.ts +28 -0
  72. package/dist/core/backup.d.ts.map +1 -0
  73. package/dist/core/backup.js +118 -0
  74. package/dist/core/backup.js.map +1 -0
  75. package/dist/core/config.d.ts +30 -19
  76. package/dist/core/config.d.ts.map +1 -1
  77. package/dist/core/config.js +86 -26
  78. package/dist/core/config.js.map +1 -1
  79. package/dist/core/flow-manager.d.ts +256 -5
  80. package/dist/core/flow-manager.d.ts.map +1 -1
  81. package/dist/core/flow-manager.js +908 -68
  82. package/dist/core/flow-manager.js.map +1 -1
  83. package/dist/core/fs/atomic-write.d.ts +3 -0
  84. package/dist/core/fs/atomic-write.d.ts.map +1 -1
  85. package/dist/core/fs/atomic-write.js +3 -0
  86. package/dist/core/fs/atomic-write.js.map +1 -1
  87. package/dist/core/fs/safe-read.d.ts +11 -0
  88. package/dist/core/fs/safe-read.d.ts.map +1 -0
  89. package/dist/core/fs/safe-read.js +31 -0
  90. package/dist/core/fs/safe-read.js.map +1 -0
  91. package/dist/core/global-paths.d.ts +16 -7
  92. package/dist/core/global-paths.d.ts.map +1 -1
  93. package/dist/core/global-paths.js +23 -8
  94. package/dist/core/global-paths.js.map +1 -1
  95. package/dist/core/i18n-data/en.d.ts +2 -0
  96. package/dist/core/i18n-data/en.d.ts.map +1 -1
  97. package/dist/core/i18n-data/en.js +259 -23
  98. package/dist/core/i18n-data/en.js.map +1 -1
  99. package/dist/core/i18n-data/zh-CN.d.ts +2 -0
  100. package/dist/core/i18n-data/zh-CN.d.ts.map +1 -1
  101. package/dist/core/i18n-data/zh-CN.js +265 -23
  102. package/dist/core/i18n-data/zh-CN.js.map +1 -1
  103. package/dist/core/i18n.d.ts +8 -0
  104. package/dist/core/i18n.d.ts.map +1 -1
  105. package/dist/core/i18n.js +14 -4
  106. package/dist/core/i18n.js.map +1 -1
  107. package/dist/core/init.d.ts +4 -2
  108. package/dist/core/init.d.ts.map +1 -1
  109. package/dist/core/init.js +38 -13
  110. package/dist/core/init.js.map +1 -1
  111. package/dist/core/managed-region.d.ts +1 -1
  112. package/dist/core/managed-region.js +1 -1
  113. package/dist/core/metrics.d.ts +16 -4
  114. package/dist/core/metrics.d.ts.map +1 -1
  115. package/dist/core/metrics.js +31 -11
  116. package/dist/core/metrics.js.map +1 -1
  117. package/dist/core/migrate.d.ts.map +1 -1
  118. package/dist/core/migrate.js +53 -19
  119. package/dist/core/migrate.js.map +1 -1
  120. package/dist/core/model-config.d.ts.map +1 -1
  121. package/dist/core/model-config.js +4 -2
  122. package/dist/core/model-config.js.map +1 -1
  123. package/dist/core/opencode-config.d.ts +4 -4
  124. package/dist/core/opencode-config.d.ts.map +1 -1
  125. package/dist/core/opencode-config.js +6 -5
  126. package/dist/core/opencode-config.js.map +1 -1
  127. package/dist/core/plan/path.d.ts +40 -0
  128. package/dist/core/plan/path.d.ts.map +1 -1
  129. package/dist/core/plan/path.js +108 -1
  130. package/dist/core/plan/path.js.map +1 -1
  131. package/dist/core/plan/roadmap.js +2 -2
  132. package/dist/core/plan/roadmap.js.map +1 -1
  133. package/dist/core/plan/scheme.d.ts +74 -2
  134. package/dist/core/plan/scheme.d.ts.map +1 -1
  135. package/dist/core/plan/scheme.js +311 -26
  136. package/dist/core/plan/scheme.js.map +1 -1
  137. package/dist/core/plan/stage.d.ts +34 -3
  138. package/dist/core/plan/stage.d.ts.map +1 -1
  139. package/dist/core/plan/stage.js +90 -6
  140. package/dist/core/plan/stage.js.map +1 -1
  141. package/dist/core/public-logger.d.ts +18 -5
  142. package/dist/core/public-logger.d.ts.map +1 -1
  143. package/dist/core/public-logger.js +62 -23
  144. package/dist/core/public-logger.js.map +1 -1
  145. package/dist/core/runtime-log.d.ts +25 -0
  146. package/dist/core/runtime-log.d.ts.map +1 -0
  147. package/dist/core/runtime-log.js +94 -0
  148. package/dist/core/runtime-log.js.map +1 -0
  149. package/dist/core/setup.d.ts.map +1 -1
  150. package/dist/core/setup.js +47 -19
  151. package/dist/core/setup.js.map +1 -1
  152. package/dist/core/template-loader.d.ts.map +1 -1
  153. package/dist/core/template-loader.js +672 -288
  154. package/dist/core/template-loader.js.map +1 -1
  155. package/dist/core/templates.d.ts +2 -2
  156. package/dist/core/templates.d.ts.map +1 -1
  157. package/dist/core/templates.js +13 -9
  158. package/dist/core/templates.js.map +1 -1
  159. package/dist/core/update-infos.d.ts +14 -3
  160. package/dist/core/update-infos.d.ts.map +1 -1
  161. package/dist/core/update-infos.js +67 -15
  162. package/dist/core/update-infos.js.map +1 -1
  163. package/dist/core/update-state.d.ts.map +1 -1
  164. package/dist/core/update-state.js +7 -4
  165. package/dist/core/update-state.js.map +1 -1
  166. package/dist/core/update.d.ts +2 -1
  167. package/dist/core/update.d.ts.map +1 -1
  168. package/dist/core/update.js +253 -61
  169. package/dist/core/update.js.map +1 -1
  170. package/dist/core/view/entry.d.ts +53 -1
  171. package/dist/core/view/entry.d.ts.map +1 -1
  172. package/dist/core/view/entry.js +71 -2
  173. package/dist/core/view/entry.js.map +1 -1
  174. package/dist/core/workspace/identity.d.ts.map +1 -1
  175. package/dist/core/workspace/identity.js +15 -5
  176. package/dist/core/workspace/identity.js.map +1 -1
  177. package/dist/core/workspace/knowledge.d.ts.map +1 -1
  178. package/dist/core/workspace/knowledge.js +125 -19
  179. package/dist/core/workspace/knowledge.js.map +1 -1
  180. package/dist/core/workspace/structure.d.ts.map +1 -1
  181. package/dist/core/workspace/structure.js +6 -2
  182. package/dist/core/workspace/structure.js.map +1 -1
  183. package/dist/index.d.ts +0 -1
  184. package/dist/index.d.ts.map +1 -1
  185. package/dist/index.js +1 -2
  186. package/dist/index.js.map +1 -1
  187. package/dist/utils/kb-dedup.d.ts +5 -1
  188. package/dist/utils/kb-dedup.d.ts.map +1 -1
  189. package/dist/utils/kb-dedup.js +11 -5
  190. package/dist/utils/kb-dedup.js.map +1 -1
  191. package/package.json +6 -6
  192. package/dist/utils/path.d.ts +0 -22
  193. package/dist/utils/path.d.ts.map +0 -1
  194. package/dist/utils/path.js +0 -37
  195. package/dist/utils/path.js.map +0 -1
  196. package/scripts/patch-inquirer.js +0 -70
package/README.en.md CHANGED
@@ -4,9 +4,11 @@
4
4
 
5
5
  OpenFeel is a TypeScript CLI tool for end-to-end process governance in AI Agent development. Core philosophy: **"Slim prompts, process in tools"** — agents understand workflows by reading `flow.json` state, not long text documents.
6
6
 
7
- > **Supported Platform**: Currently only [opencode](https://opencode.ai).
7
+ > **Current adapter harness**: opencode (default); the framework targets multi-harness support (other adapters reserved).
8
8
  > **Default Model Config**: DeepSeek V4 (primary reasoning) + GLM-5.3-flash (cross-review) + DeepSeek-flash (multimodal vision).
9
9
  > `openfeel init` auto-detects registered models and guides configuration.
10
+ >
11
+ > ⚠️ The `openfeel <cmd>` examples below are the **installed-package usage**; when developing/running **inside this source repository**, use `node bin/openfeel.js <cmd>` instead (the global `openfeel` may lag behind this repository — it is not synced with the source here).
10
12
 
11
13
  ## What Problem Does It Solve
12
14
 
@@ -46,20 +48,37 @@ openfeel plan scheme create stage-01 "Implement core features"
46
48
  openfeel flow status
47
49
  ```
48
50
 
51
+ ## What's New in v1.1.2
52
+
53
+ - **Self-description**: `flow phases [--json]` lists all valid phases and the transition table (5 top-level JSON keys: `schemaVersion` / `phases` / `transitions` / `advanceAccepted` / `transitionsDiff`).
54
+ - **Stage governance**: `flow stage remove` / `plan stage add --deps` / `stageId` validation and directory-conflict detection.
55
+ - **Effective config**: `config effective` prints the resolved value plus its source (`status.md > config.yaml > profile.yaml > builtin`).
56
+ - **Structured output**: `flow status/current/health/metrics/overview --json` (pure JSON + `schemaVersion`).
57
+ - **Correction/cleanup CLI surface**: `plan scheme remove/rename/publish`, `flow ops list`, `flow health --fix`, `knowledge dedup`, `lint` non-zero exit on findings.
58
+ - **Deployment & backup**: automatic backup before overwrite at `~/.openfeel/backup/{ts}/`; new skill `openfeel-cli-usage` (skills 16 → 17).
59
+ - **Output encoding adaptation (stage-58 / stage-61 fix)**: `auto` passes through **UTF-8** on Windows non-TTY (pipe-friendly); TTY / POSIX pass through UTF-8; **GBK requires explicit** `--encoding gbk` / `OPENFEEL_ENCODING`; `--json` is **always UTF-8**; unencodable chars degrade to `?` without warning.
60
+ - **Runtime log (stage-58)**: written by default to `~/.openfeel/cli/logs/openfeel-YYYY-MM-DD.log` (UTF-8, one file per day); `--log-file <path>` changes the path, `--no-log` / `OPENFEEL_LOG=0` disables it, `--debug` enables debug-level entries.
61
+
49
62
  ## Command Reference
50
63
 
51
64
  | Command | Purpose |
52
65
  |---------|---------|
53
- | `openfeel init [path]` | Initialize new project with `.openfeel/` workspace and platform adapter (opencode) |
66
+ | `openfeel init [path]` | Initialize new project with `.openfeel/` workspace and platform adapter (current: opencode) |
54
67
  | `openfeel update` | Incrementally deploy platform adapter to existing projects |
55
- | `openfeel flow` | Pipeline state management (status / current / advance / overview) |
68
+ | `openfeel flow` | Pipeline state management (status / phases / overview / current / advance / attempt / ops list / health [--fix] / checkpoint / migrate; status·current·health·metrics·overview support --json) |
56
69
  | `openfeel roadmap` | Version roadmap management (create / show) |
57
- | `openfeel plan` | Stage and scheme management (stage add/list, scheme create/list) |
58
- | `openfeel lint` | Quality gate checks (i18n key symmetry / kb stale references) |
59
- | `openfeel config` | Configuration management (get / set / list, supports --global) |
60
- | `openfeel knowledge` | Knowledge base management (list / search) |
70
+ | `openfeel plan` | Stage and scheme management (stage add/list [--deps/--tasks], scheme create [--draft] / publish / rename / remove / list) |
71
+ | `openfeel lint` | Quality gate checks (i18n key symmetry / kb stale references; **non-zero exit on findings**, no escape hatch) |
72
+ | `openfeel config` | Configuration management (get / set[**all `defaults.*`**] / effective / get-lang / list-projects, supports --global) |
73
+ | `openfeel knowledge` | Knowledge base management (list / add / search / index / dedup) |
61
74
  | `openfeel archive <stage>` | Stage archiving with knowledge extraction |
62
- | `openfeel update` | Update Agent definitions and Skill files |
75
+ | `openfeel setup` | Global-only deployment (global AGENTS.md + agents + skills + adapter config); no project `.openfeel/` |
76
+ | `openfeel migrate` | Migrate legacy-layout projects (detect / backup / rollback) |
77
+ | `openfeel model` | Three-tier agent model config (set / get / list, `--scope`) |
78
+ | `openfeel stage` | Work stage status (status / set / task / create [deprecated]) |
79
+ | `openfeel project` | Project management (overview) |
80
+ | `openfeel view` | Review item management (list / accept; add/update/remove via `flow review add|update|remove`) |
81
+ | `openfeel instructions` | Generate structured instructions (artifact → XML/JSON) |
63
82
 
64
83
  Details: [docs/commands.md](docs/commands.md)
65
84
 
@@ -83,6 +102,12 @@ Feel is the command center, receiving user intent and dispatching downstream Age
83
102
  | Vision | Vision Agent | Multimodal visual analysis |
84
103
  | Archiver | Archiver | Operation archiving and knowledge extraction |
85
104
 
105
+ ### Global Deployment and Workspace Layering
106
+
107
+ Framework assets (9 agents / 17 skills / global `AGENTS.md` / global `opencode.jsonc`) are deployed to `~/.config/opencode/` via `openfeel setup`; **the repository itself keeps no project-level `.opencode/agents|skills`** (since stage-55).
108
+
109
+ Workspace state is layered into two files: `current.md` (team file, cross-user overall progress, ≤5 entries + auto-archiving) and `dev_last.md` (local index + topic directory, cross-session recovery). Framework assets are **automatically backed up** before deployment overwrite to `~/.openfeel/backup/{ts}/`.
110
+
86
111
  ### Three-Tier Planning
87
112
 
88
113
  ```
@@ -103,7 +128,7 @@ Roadmap
103
128
  | `openfeel plan` | Plan formulation |
104
129
  | `openfeel plan scheme` | Scheme formulation |
105
130
  | `openfeel-executor` | Code execution |
106
- | `openfeel view` | Code review |
131
+ | `openfeel view` | Review item acceptance |
107
132
  | `openfeel-feel-tester` | Test acceptance |
108
133
  | `openfeel archive` | Stage archiving |
109
134
  | `openfeel knowledge` | Knowledge base operations |
@@ -112,7 +137,8 @@ Roadmap
112
137
 
113
138
  ```
114
139
  CLI Layer (Commander)
115
- ├── init / update
140
+ ├── init / update / setup / migrate
141
+ ├── stage / project / model
116
142
  ├── flow ← FlowManager (state machine core)
117
143
  ├── roadmap ← Roadmap module
118
144
  ├── plan ← Stage / Scheme module
@@ -130,15 +156,19 @@ Core Layer
130
156
  ├── artifact-graph/ — Dependency graph & instruction generation
131
157
  ├── view/ — Review item CRUD
132
158
  ├── archive/ — Archive consolidation
159
+ ├── backup.ts — pre-overwrite backup (~/.openfeel/backup/{ts}/)
160
+ ├── fs/ — atomic writes + advisory file locks
133
161
  └── workspace/ — Directory structure & knowledge base
134
162
  ```
135
163
 
164
+ > **Global asset deployment**: 9 agents / 17 skills / global `AGENTS.md` / global `opencode.jsonc` are deployed to `~/.config/opencode/` via `openfeel setup`; the repository itself keeps no project-level `.opencode/agents|skills` (since stage-55).
165
+
136
166
  ## Development
137
167
 
138
168
  ```bash
139
169
  npm install # Install dependencies
140
170
  npm run build # Compile TypeScript
141
- npm test # Run tests (395 cases)
171
+ npm test # Run tests (1018 cases / 61 test files; Linux CI skips 1 Windows-only case)
142
172
  ```
143
173
 
144
174
  ## Acknowledgments
package/README.md CHANGED
@@ -1,11 +1,15 @@
1
1
  # OpenFeel — AI Agent 开发流程治理 CLI
2
2
 
3
- [English](README.en.md) | [更新日志](CHANGELOG.md) | [npm](https://www.npmjs.com/package/openfeel)
3
+ [English](README.en.md) | [更新日志](CHANGELOG.md) | [npm](https://www.npmjs.com/package/openfeel) | [入门指南](docs/GETTING_STARTED.md)
4
4
 
5
- > ⚡ **支持平台**:opencode | **默认模型**:DeepSeek(主力推理)+ GLM(交叉审查)+ Alibaba-CN(多模态)
5
+ > ⚡ **当前适配 harness**:opencode(框架面向多 harness 适配,其余适配器预留) | **默认模型**:DeepSeek V4(主力推理)+ GLM-5.3-flash(交叉审查)+ DeepSeek-flash(多模态视觉)
6
+
7
+ > ⚠️ 下文示例命令 `openfeel <cmd>` 为**安装后的一般使用者用法**;若在**本仓库源码**中开发/执行,请改用 `node bin/openfeel.js <cmd>`(全局 `openfeel` 可能滞后于本仓——未随本仓库源码同步更新)。
6
8
 
7
9
  OpenFeel 是一个 TypeScript CLI 工具,为 AI Agent 开发提供端到端的流程治理。核心理念:**「提示词瘦身,流程入工具」** —— Agent 不靠读长文本理解流程,而是通过 `flow.json` 获取当前状态和下一步指令。
8
10
 
11
+ > 📦 **最新版本 v1.1.2** — 自描述 `flow phases`、配置有效值 `config effective`、部署前自动备份;框架资产(agents/skills/AGENTS.md)全局部署。
12
+
9
13
  > 📌 本项目基于 [AI_Prompt](https://github.com/Liuary/AI_Prompt) 开发,参考了 [OpenSpec](https://github.com/Fission-AI/OpenSpec) 等工具的设计思路。
10
14
 
11
15
  ---
@@ -18,10 +22,11 @@ openfeel init ./my-project # 初始化新项目
18
22
  openfeel update # 已有项目?一键部署平台适配器
19
23
  openfeel migrate # 存量旧布局项目?一键迁移(检测/备份/回滚)
20
24
  openfeel flow status # 查看流水线
25
+ openfeel flow phases # 查看合法 phase 与转移表
21
26
 
22
27
  npm install -g openfeel@latest # 更新到最新版本
23
28
  ```
24
29
 
25
- > 💡 `init` 用于新项目首次部署,`update` 为已有项目增量更新(适用于 `init` 之后再引入 OpenFeel 的项目)。存量旧布局项目(项目内 `.opencode/agents|skills|instructions`)用 `openfeel migrate` 迁移到全局部署。
30
+ > 💡 `init` 用于新项目首次部署,`update` 为已有项目增量更新(适用于 `init` 之后再引入 OpenFeel 的项目)。存量旧布局项目(opencode 适配器:项目内 `.opencode/agents|skills|instructions`)用 `openfeel migrate` 迁移到全局部署。框架资产(agents/skills/AGENTS.md)经 `openfeel setup` 全局部署,项目内不再生成 `.opencode/agents|skills`。
26
31
 
27
32
  完整中文文档:[README.zh-CN.md](README.zh-CN.md)
package/README.zh-CN.md CHANGED
@@ -2,9 +2,11 @@
2
2
 
3
3
  [English](README.en.md) | [更新日志](CHANGELOG.md) | [npm](https://www.npmjs.com/package/openfeel) | [入门指南](docs/GETTING_STARTED.md)
4
4
 
5
+ > ⚠️ 下文示例命令 `openfeel <cmd>` 为**安装后的一般使用者用法**;若在**本仓库源码**中开发/执行,请改用 `node bin/openfeel.js <cmd>`(全局 `openfeel` 可能滞后于本仓——未随本仓库源码同步更新)。
6
+
5
7
  OpenFeel 是一个 TypeScript CLI 工具,为 AI Agent 开发提供端到端的流程治理。
6
8
 
7
- > **支持平台**:目前仅支持 [opencode](https://opencode.ai)。
9
+ > **当前适配 harness**:opencode(默认);框架面向多 harness 适配(其余适配器预留)。
8
10
  > **默认模型配置**:DeepSeek V4(主力推理) + GLM-5.3-flash(交叉审查) + DeepSeek-flash(多模态视觉)。
9
11
  > 首次 `openfeel init` 时会自动检测用户已注册的模型并引导配置。
10
12
 
@@ -46,20 +48,37 @@ openfeel plan scheme create stage-01 "实现核心功能"
46
48
  openfeel flow status
47
49
  ```
48
50
 
51
+ ## v1.1.2 新增能力
52
+
53
+ - **自描述**:`flow phases [--json]` 输出全部合法 phase 与转移表(JSON 顶层 5 键:`schemaVersion` / `phases` / `transitions` / `advanceAccepted` / `transitionsDiff`)。
54
+ - **阶段治理**:`flow stage remove` / `plan stage add --deps` / `stageId` 校验与目录冲突检测。
55
+ - **配置有效值**:`config effective` 输出有效值 + 生效来源(`status.md > config.yaml > profile.yaml > builtin`)。
56
+ - **结构化输出**:`flow status/current/health/metrics/overview --json`(纯 JSON + `schemaVersion`)。
57
+ - **纠正/清理侧命令面**:`plan scheme remove/rename/publish`、`flow ops list`、`flow health --fix`、`knowledge dedup`、`lint` 发现问题非 0 退出。
58
+ - **部署与备份**:部署覆盖前自动备份 `~/.openfeel/backup/{ts}/`;新增 skill `openfeel-cli-usage`(skill 16 → 17)。
59
+ - **输出编码自适应(stage-58 / stage-61 修正)**:`auto` 在 Windows 非 TTY(管道/重定向)下**直通 UTF-8**(管道/CI 友好);TTY / POSIX 直通 UTF-8;**GBK 需 `--encoding gbk` / `OPENFEEL_ENCODING` 显式**;`--json` **恒 UTF-8**;不可编码字符降 `?` 不告警。
60
+ - **运行日志(stage-58)**:默认写入 `~/.openfeel/cli/logs/openfeel-YYYY-MM-DD.log`(UTF-8,按日一文件);`--log-file <path>` 改路径,`--no-log` / `OPENFEEL_LOG=0` 关闭,`--debug` 记录 debug 级。
61
+
49
62
  ## 命令参考
50
63
 
51
64
  | 命令 | 用途 |
52
65
  |------|------|
53
- | `openfeel init [path]` | 初始化新项目,创建 `.openfeel/` 目录结构和平台适配器(opencode) |
66
+ | `openfeel init [path]` | 初始化新项目,创建 `.openfeel/` 目录结构和平台适配器(当前:opencode) |
54
67
  | `openfeel update` | 为已有项目增量部署平台适配器(适用于 `init` 之后再引入 OpenFeel 的项目) |
55
- | `openfeel flow` | 流水线状态管理(status / current / advance / overview) |
68
+ | `openfeel flow` | 流水线状态管理(status / phases / overview / current / advance / attempt / ops list / health [--fix] / checkpoint / migrate;status·current·health·metrics·overview 支持 --json) |
56
69
  | `openfeel roadmap` | 分期大纲管理(create / show) |
57
- | `openfeel plan` | 工作阶段与操作方案管理(stage add/list、scheme create/list) |
58
- | `openfeel lint` | 质量门禁检查(i18n 键对称性 / kb 过期引用) |
59
- | `openfeel config` | 配置管理(get / set / list,支持 --global) |
60
- | `openfeel knowledge` | 知识库管理(list / search) |
70
+ | `openfeel plan` | 工作阶段与操作方案管理(stage add/list [--deps/--tasks]、scheme create [--draft] / publish / rename / remove / list) |
71
+ | `openfeel lint` | 质量门禁检查(i18n 键对称性 / kb 过期引用;**发现问题非 0 退出**,无逃生阀) |
72
+ | `openfeel config` | 配置管理(get / set[**全量 `defaults.*`**] / effective / get-lang / list-projects,支持 --global) |
73
+ | `openfeel knowledge` | 知识库管理(list / add / search / index / dedup) |
61
74
  | `openfeel archive <stage>` | 阶段归档,汇总产出、生成摘要、提取知识 |
62
- | `openfeel update` | 更新 Agent 定义和 Skill 文件到目标平台 |
75
+ | `openfeel setup` | 纯全局部署(全局 AGENTS.md + agent + skill + 平台适配器配置),不建项目 `.openfeel/` |
76
+ | `openfeel migrate` | 存量旧布局项目迁移(检测 / 备份 / 回滚) |
77
+ | `openfeel model` | 三层级 agent 模型配置(set / get / list,`--scope`) |
78
+ | `openfeel stage` | 阶段状态(status / set / task / create[已弃用]) |
79
+ | `openfeel project` | 项目管理(overview) |
80
+ | `openfeel view` | 审查条目管理(list / accept;新增/修改/删除改用 `flow review add|update|remove`) |
81
+ | `openfeel instructions` | 生成结构化指令(artifact → XML/JSON) |
63
82
 
64
83
  详细参数见:[docs/commands.md](docs/commands.md)
65
84
 
@@ -79,10 +98,16 @@ Feel 是整个流程的调度中心,负责接收用户意图并调度下游 Ag
79
98
  | Executor | 执行官 | 按方案编码实现 |
80
99
  | Reviewer | 审查官 | 交叉审查代码 |
81
100
  | Feel Tester | 测试官 | 正式测试验收 |
82
- | 事务官 | 事务官 | 文件机械操作 |
101
+ | Utility | 事务官 | 文件机械操作 |
83
102
  | Vision | 视觉官 | 多模态视觉分析 |
84
103
  | Archiver | 归档官 | 归档操作记录与知识提取 |
85
104
 
105
+ ### 全局部署与工作区分层
106
+
107
+ 框架资产(9 agent / 17 skill / 全局 `AGENTS.md` / 全局 `opencode.jsonc`)经 `openfeel setup` 部署到 `~/.config/opencode/`;**仓库自身不保留项目级 `.opencode/agents|skills`**(stage-55 起)。
108
+
109
+ 工作区状态分两层:`current.md`(团队文件,跨用户整体进度,≤5 条 + 自动归档)与 `dev_last.md`(本地索引 + 主题目录,跨会话恢复)。框架资产部署覆盖前**自动备份**至 `~/.openfeel/backup/{ts}/`。
110
+
86
111
  ### 三层计划体系
87
112
 
88
113
  ```
@@ -103,7 +128,7 @@ Roadmap(分期大纲)
103
128
  | `openfeel plan` | 制定分期大纲和工作阶段 |
104
129
  | `openfeel plan scheme` | 制定细粒度操作方案 |
105
130
  | `openfeel-executor` | 按方案编码实现 |
106
- | `openfeel view` | 代码审查 |
131
+ | `openfeel view` | 审查条目验收 |
107
132
  | `openfeel-feel-tester` | 测试验收 |
108
133
  | `openfeel archive` | 归档操作记录 |
109
134
  | `openfeel knowledge` | 知识库操作 |
@@ -112,7 +137,8 @@ Roadmap(分期大纲)
112
137
 
113
138
  ```
114
139
  CLI 层(Commander)
115
- ├── init / update
140
+ ├── init / update / setup / migrate
141
+ ├── stage / project / model
116
142
  ├── flow ← FlowManager(状态机核心)
117
143
  ├── roadmap ← Roadmap 模块
118
144
  ├── plan ← Stage / Scheme 模块
@@ -130,15 +156,19 @@ Core 层
130
156
  ├── artifact-graph/ — 依赖图与指令生成
131
157
  ├── view/ — 审查条目 CRUD
132
158
  ├── archive/ — 归档合并
159
+ ├── backup.ts — 覆盖写前备份(~/.openfeel/backup/{ts}/)
160
+ ├── fs/ — 原子写 + 建议性文件锁
133
161
  └── workspace/ — 目录结构和知识库
134
162
  ```
135
163
 
164
+ > **框架资产全局部署**:9 agent / 17 skill / 全局 `AGENTS.md` / 全局 `opencode.jsonc` 经 `openfeel setup` 部署到 `~/.config/opencode/`;仓库自身不保留项目级 `.opencode/agents|skills`(stage-55 起)。
165
+
136
166
  ## 开发
137
167
 
138
168
  ```bash
139
169
  npm install # 安装依赖
140
170
  npm run build # 编译 TypeScript
141
- npm test # 运行测试(395 用例)
171
+ npm test # 运行测试(1018 用例 / 61 个测试文件;Linux CI 跳过 1 个 Windows 专属用例)
142
172
  ```
143
173
 
144
174
  ## 致谢
package/bin/openfeel.js CHANGED
@@ -2,8 +2,13 @@
2
2
  // OpenFeel CLI 入口 — 加载并启动 Commander 程序
3
3
  // 无参数时进入 REPL 交互模式,有参数时正常 CLI 模式
4
4
  import { program, applyHelpI18n, startRepl, runCli } from '../dist/cli/index.js';
5
+ import { installOutputEncoding } from '../dist/cli/output-encoding.js';
6
+ import { installRuntimeLog } from '../dist/core/runtime-log.js';
5
7
 
6
8
  const args = process.argv.slice(2);
9
+ // 进程入口安装:输出编码 + 运行日志(单一咽喉;库/测试侧未调用即 no-op)
10
+ installOutputEncoding();
11
+ installRuntimeLog();
7
12
  // 在 parse 前注入翻译,此时命令树已就绪
8
13
  applyHelpI18n(program);
9
14
  if (args.length === 0) {
@@ -5,12 +5,24 @@
5
5
  */
6
6
  import { Command } from 'commander';
7
7
  declare const program: Command;
8
+ /**
9
+ * 是否启用彩色输出(B7-1,单一判定入口)。
10
+ * 优先级:`--no-color`(显式关闭,commander 解析为 color=false) > `NO_COLOR` 环境变量(存在且**非空**即关闭,
11
+ * 遵循 no-color.org,**不解析其值**) > 默认(允许彩色)。
12
+ *
13
+ * 注:当前实现**无着色逻辑**,故实际输出恒无 ANSI;本函数为**契约与未来保护**——
14
+ * 将来引入着色时必须经此判定(禁止绕过)。
15
+ * @param options commander 解析结果(`color === false` 表示显式 --no-color)
16
+ */
17
+ export declare function shouldUseColor(options?: {
18
+ color?: boolean;
19
+ }): boolean;
8
20
  export declare function applyHelpI18n(program: Command): void;
9
- /** 并发冲突退出码:与通用错误 1 区分,便于自动化识别「可重试」冲突 */
21
+ /** 并发写冲突退出码:与通用错误 1 区分,便于自动化识别「可重试」冲突 */
10
22
  export declare const EXIT_CONCURRENT = 2;
11
- /** 统一 CLI 错误处理:识别 flow.json 并发冲突并输出可重试提示 */
23
+ /** 统一 CLI 错误处理:识别 flow.json 并发写冲突并输出可重试提示(单点,T38) */
12
24
  export declare function handleCliError(err: unknown): never;
13
- /** CLI 启动入口:包裹 program.parse,统一处理并发冲突 */
25
+ /** CLI 启动入口:包裹 program.parse,统一处理并发写冲突 */
14
26
  export declare function runCli(): void;
15
27
  export { program };
16
28
  export { startRepl } from './repl.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAUpC,QAAA,MAAM,OAAO,SAAgB,CAAC;AA8C9B,wBAAgB,aAAa,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAsEpD;AAED,wCAAwC;AACxC,eAAO,MAAM,eAAe,IAAI,CAAC;AAEjC,4CAA4C;AAC5C,wBAAgB,cAAc,CAAC,GAAG,EAAE,OAAO,GAAG,KAAK,CAQlD;AAED,yCAAyC;AACzC,wBAAgB,MAAM,IAAI,IAAI,CAM7B;AAED,OAAO,EAAE,OAAO,EAAE,CAAC;AACnB,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAYpC,QAAA,MAAM,OAAO,SAAgB,CAAC;AAe9B;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAAC,OAAO,CAAC,EAAE;IAAE,KAAK,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,OAAO,CAYrE;AAyCD,wBAAgB,aAAa,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CA+EpD;AAED,yCAAyC;AACzC,eAAO,MAAM,eAAe,IAAI,CAAC;AAEjC,qDAAqD;AACrD,wBAAgB,cAAc,CAAC,GAAG,EAAE,OAAO,GAAG,KAAK,CAQlD;AAED,0CAA0C;AAC1C,wBAAgB,MAAM,IAAI,IAAI,CAU7B;AAED,OAAO,EAAE,OAAO,EAAE,CAAC;AACnB,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC"}
package/dist/cli/index.js CHANGED
@@ -5,8 +5,10 @@
5
5
  */
6
6
  import { Command } from 'commander';
7
7
  import { createRequire } from 'node:module';
8
- import { t, getCliLang } from '../core/i18n.js';
8
+ import { t, getCliLang, hasKey } from '../core/i18n.js';
9
9
  import { isFlowConcurrentError } from '../core/flow-manager.js';
10
+ import { handleConcurrentConflict } from '../commands/shared/errors.js';
11
+ import { runtimeLog } from '../core/runtime-log.js';
10
12
  // 读取 package.json 获取版本号
11
13
  const require = createRequire(import.meta.url);
12
14
  const pkg = require('../../package.json');
@@ -15,7 +17,37 @@ const program = new Command();
15
17
  program
16
18
  .name('openfeel')
17
19
  .description('AI Agent 开发流程治理 CLI 工具')
18
- .version(pkg.version, '-v, --version', '输出版本号');
20
+ .version(pkg.version, '-v, --version', '输出版本号')
21
+ // B7-2:全局 --no-color(negate 选项;描述在注册时按当前语言求值,applyHelpI18n 会跳过 negate)
22
+ .option('--no-color', t('help.global.noColor', getCliLang(process.cwd())))
23
+ // stage-58 A-5:全局 --encoding(默认 auto;仅用于 --help 展示 + 防 commander 未知选项报错;实际解析从 argv/env 读取)
24
+ .option('--encoding <encoding>', t('help.global.encoding', getCliLang(process.cwd())), 'auto')
25
+ // stage-58 B-4:运行日志全局选项
26
+ .option('--log-file <path>', t('help.global.logFile', getCliLang(process.cwd())))
27
+ .option('--no-log', t('help.global.noLog', getCliLang(process.cwd())))
28
+ .option('--debug', t('help.global.debug', getCliLang(process.cwd())));
29
+ /**
30
+ * 是否启用彩色输出(B7-1,单一判定入口)。
31
+ * 优先级:`--no-color`(显式关闭,commander 解析为 color=false) > `NO_COLOR` 环境变量(存在且**非空**即关闭,
32
+ * 遵循 no-color.org,**不解析其值**) > 默认(允许彩色)。
33
+ *
34
+ * 注:当前实现**无着色逻辑**,故实际输出恒无 ANSI;本函数为**契约与未来保护**——
35
+ * 将来引入着色时必须经此判定(禁止绕过)。
36
+ * @param options commander 解析结果(`color === false` 表示显式 --no-color)
37
+ */
38
+ export function shouldUseColor(options) {
39
+ // 显式 --no-color → 关闭
40
+ if (options?.color === false) {
41
+ return false;
42
+ }
43
+ // NO_COLOR 存在且非空 → 关闭(空串按未设置处理)
44
+ const noColor = process.env.NO_COLOR;
45
+ if (typeof noColor === 'string' && noColor.length > 0) {
46
+ return false;
47
+ }
48
+ // 默认允许彩色(当前无着色实现 → 零可见变化)
49
+ return true;
50
+ }
19
51
  // ── 静态导入命令模块(新增命令在此追加) ──
20
52
  import { registerInitCommand } from '../commands/init.js';
21
53
  import { registerFlowCommand } from '../commands/flow.js';
@@ -76,6 +108,14 @@ export function applyHelpI18n(program) {
76
108
  cmd.description(descTranslated);
77
109
  }
78
110
  }
111
+ // 替换当前命令的 arguments 描述(键约定 help.<commandPath>.arg<name>,T38)
112
+ // 仅命中既有键时替换,避免对未补键的 argument 触发缺失告警
113
+ for (const arg of cmd.registeredArguments ?? []) {
114
+ const argKey = `${keyPrefix}.arg${arg.name()}`;
115
+ if (hasKey(argKey, lang)) {
116
+ arg.description = t(argKey, lang);
117
+ }
118
+ }
79
119
  // 替换当前命令的 option 描述
80
120
  for (const opt of cmd.options) {
81
121
  // 跳过 Commander 自动生成的 --no- 选项(negate 标记为 true)
@@ -87,9 +127,9 @@ export function applyHelpI18n(program) {
87
127
  continue;
88
128
  const optName = toCamelCase(flag);
89
129
  const optKey = `${keyPrefix}.${optName}`;
90
- const optTranslated = t(optKey, lang);
91
- if (optTranslated !== optKey) {
92
- opt.description = optTranslated;
130
+ // 仅命中既有键时替换,避免对未补键的选项触发缺失告警(与 argument 同策略)
131
+ if (hasKey(optKey, lang)) {
132
+ opt.description = t(optKey, lang);
93
133
  }
94
134
  }
95
135
  // 递归处理子命令
@@ -111,9 +151,9 @@ export function applyHelpI18n(program) {
111
151
  continue;
112
152
  const optName = toCamelCase(flag);
113
153
  const optKey = `help.${program.name()}.${optName}`;
114
- const optTranslated = t(optKey, lang);
115
- if (optTranslated !== optKey) {
116
- opt.description = optTranslated;
154
+ // 仅命中既有键时替换,避免对未补键的选项(如 help.openfeel.encoding)触发每命令缺失告警
155
+ if (hasKey(optKey, lang)) {
156
+ opt.description = t(optKey, lang);
117
157
  }
118
158
  }
119
159
  // 子命令路径从命令名开始(不含 root),与 help 域 key 命名对齐
@@ -121,26 +161,30 @@ export function applyHelpI18n(program) {
121
161
  walkCmd(sub, [sub.name()]);
122
162
  }
123
163
  }
124
- /** 并发冲突退出码:与通用错误 1 区分,便于自动化识别「可重试」冲突 */
164
+ /** 并发写冲突退出码:与通用错误 1 区分,便于自动化识别「可重试」冲突 */
125
165
  export const EXIT_CONCURRENT = 2;
126
- /** 统一 CLI 错误处理:识别 flow.json 并发冲突并输出可重试提示 */
166
+ /** 统一 CLI 错误处理:识别 flow.json 并发写冲突并输出可重试提示(单点,T38) */
127
167
  export function handleCliError(err) {
168
+ // stage-58 B-6:记录「命令处理中抛出的异常」。error 级语义边界(REV-002):
169
+ // commander 解析期错误(未知命令/未知选项/缺参)经 program.error() 直接 process.exit(1),不抛异常、不达此处 → 不入日志。
170
+ runtimeLog('error', 'cli error: ' + (err instanceof Error ? err.message : String(err)));
128
171
  if (isFlowConcurrentError(err)) {
129
- console.error(`[并发冲突] flow.json 已被其它进程修改(期望 revision=${err.expectedRevision},磁盘=${err.actualRevision})。`);
130
- console.error('本次修改未写入。请重新执行该命令(将基于最新 flow.json 重试)。');
131
- console.error('若多 Agent 并发推进,请串行化 flow.json 写入后重试。');
132
- process.exit(EXIT_CONCURRENT);
172
+ handleConcurrentConflict(err, getCliLang(process.cwd()));
133
173
  }
134
174
  throw err;
135
175
  }
136
- /** CLI 启动入口:包裹 program.parse,统一处理并发冲突 */
176
+ /** CLI 启动入口:包裹 program.parse,统一处理并发写冲突 */
137
177
  export function runCli() {
178
+ // stage-58 B-6:命令(argv)+ 结果入运行日志;不记录 stdout 内容。
179
+ // 注:--help/--version 由 commander 输出后直接 exit → 不记「cli done」;错误路径经 handleCliError 抛出 → 亦不记「cli done」。
180
+ runtimeLog('info', 'cli start: ' + process.argv.slice(2).join(' '));
138
181
  try {
139
182
  program.parse();
140
183
  }
141
184
  catch (err) {
142
185
  handleCliError(err);
143
186
  }
187
+ runtimeLog('info', 'cli done exit=' + (process.exitCode ?? 0));
144
188
  }
145
189
  export { program };
146
190
  export { startRepl } from './repl.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,32 @@
1
+ /** 目标编码(iconv-lite 支持的编码名) */
2
+ export type OutputEncoding = 'utf8' | 'gbk' | 'gb18030' | 'big5' | 'cp932' | 'cp949';
3
+ /** resolveTargetEncoding 的输入上下文(注入以便纯函数单测) */
4
+ export interface ResolveTargetEncodingContext {
5
+ /** 命令行参数(不含 node 与脚本名),如 process.argv.slice(2) */
6
+ argv: string[];
7
+ /** 环境变量,如 process.env */
8
+ env: NodeJS.ProcessEnv;
9
+ /** 平台,如 process.platform */
10
+ platform: NodeJS.Platform;
11
+ /** 该输出流是否为 TTY */
12
+ isTTY: boolean;
13
+ }
14
+ /** 安装选项(仅注入输出流,便于单测;不含 force——无 env 守卫可绕) */
15
+ export interface InstallOutputEncodingOptions {
16
+ stdout?: NodeJS.WriteStream;
17
+ stderr?: NodeJS.WriteStream;
18
+ }
19
+ /** 归一化编码值:命中别名返回目标编码;'auto'/空/未知返回 null */
20
+ export declare function normalizeEncoding(value: string | undefined): OutputEncoding | null;
21
+ /**
22
+ * 解析目标输出编码(纯函数)。
23
+ * 优先级:① --json→utf8(最高) ② 显式 --encoding ③ OPENFEEL_ENCODING ④ 非 win32/TTY→utf8
24
+ * ⑤ win32 非 TTY→utf8。
25
+ */
26
+ export declare function resolveTargetEncoding(ctx: ResolveTargetEncodingContext): OutputEncoding;
27
+ /**
28
+ * 安装输出编码包装(幂等)。仅由 bin/openfeel.js 调用。
29
+ * 未调用时库/测试侧零副作用(不包装任何流)。
30
+ */
31
+ export declare function installOutputEncoding(opts?: InstallOutputEncodingOptions): void;
32
+ //# sourceMappingURL=output-encoding.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"output-encoding.d.ts","sourceRoot":"","sources":["../../src/cli/output-encoding.ts"],"names":[],"mappings":"AAkBA,8BAA8B;AAC9B,MAAM,MAAM,cAAc,GAAG,MAAM,GAAG,KAAK,GAAG,SAAS,GAAG,MAAM,GAAG,OAAO,GAAG,OAAO,CAAC;AAErF,8CAA8C;AAC9C,MAAM,WAAW,4BAA4B;IAC3C,kDAAkD;IAClD,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,yBAAyB;IACzB,GAAG,EAAE,MAAM,CAAC,UAAU,CAAC;IACvB,4BAA4B;IAC5B,QAAQ,EAAE,MAAM,CAAC,QAAQ,CAAC;IAC1B,kBAAkB;IAClB,KAAK,EAAE,OAAO,CAAC;CAChB;AAED,6CAA6C;AAC7C,MAAM,WAAW,4BAA4B;IAC3C,MAAM,CAAC,EAAE,MAAM,CAAC,WAAW,CAAC;IAC5B,MAAM,CAAC,EAAE,MAAM,CAAC,WAAW,CAAC;CAC7B;AAoBD,2CAA2C;AAC3C,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,cAAc,GAAG,IAAI,CAMlF;AAgBD;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,4BAA4B,GAAG,cAAc,CAsBvF;AA6BD;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,GAAE,4BAAiC,GAAG,IAAI,CAOnF"}
@@ -0,0 +1,120 @@
1
+ /**
2
+ * CLI 输出编码自适应模块(stage-58 op-001)
3
+ *
4
+ * 职责:在 CLI 进程入口(bin/openfeel.js)安装 stdout/stderr 写包装,把人类可读文本按目标编码转码。
5
+ * win32 非 TTY 默认直通 UTF-8(对齐 Node 默认与管道/CI 消费者);GBK 仅经显式
6
+ * `--encoding gbk` / `OPENFEEL_ENCODING=gbk` 生效。
7
+ *
8
+ * 设计边界:
9
+ * - **库侧默认 no-op**:未调用 installOutputEncoding 时不包装任何流(测试 import 零副作用)。
10
+ * - **不设 VITEST/env 守卫**(REV-001 裁定方案 b):安装仅由 bin 调用;in-process 测试从不安装;
11
+ * 若设守卫会被 spawn 子进程继承(vitest 主进程会设置 VITEST 环境变量为真)→ E2E 恒绿。
12
+ * - **--json 恒 UTF-8**:机器合同,resolve 第 1 步旁路,覆盖显式 --encoding / OPENFEEL_ENCODING / auto。
13
+ * - **仅支持 UTF-8 字符串语义**(REV-003):string 分支丢弃调用方 encoding;非默认 encoding 的
14
+ * 直接 write(如 write(str, 'latin1', cb))不受支持。当前全仓 process.stdout/stderr.write 直调为 0。
15
+ * - 不可编码字符由 iconv-lite 降级为 '?',**不额外告警**。
16
+ */
17
+ import iconv from 'iconv-lite';
18
+ /** 已安装标志(幂等) */
19
+ let installed = false;
20
+ /** 编码别名 → iconv 编码名('auto'/空/未知返回 null → 调用方继续回退) */
21
+ const ENCODING_ALIASES = {
22
+ utf8: 'utf8',
23
+ 'utf-8': 'utf8',
24
+ gbk: 'gbk',
25
+ gb2312: 'gbk',
26
+ gb18030: 'gb18030',
27
+ big5: 'big5',
28
+ shift_jis: 'cp932',
29
+ sjis: 'cp932',
30
+ cp932: 'cp932',
31
+ 'euc-kr': 'cp949',
32
+ cp949: 'cp949',
33
+ };
34
+ /** 归一化编码值:命中别名返回目标编码;'auto'/空/未知返回 null */
35
+ export function normalizeEncoding(value) {
36
+ if (typeof value !== 'string') {
37
+ return null;
38
+ }
39
+ const v = value.trim().toLowerCase();
40
+ return ENCODING_ALIASES[v] ?? null;
41
+ }
42
+ /** 从 argv 读取显式 --encoding(支持 `--encoding gbk` 与 `--encoding=gbk`) */
43
+ function readEncodingArg(argv) {
44
+ for (let i = 0; i < argv.length; i++) {
45
+ const arg = argv[i];
46
+ if (arg === '--encoding') {
47
+ return argv[i + 1];
48
+ }
49
+ if (arg.startsWith('--encoding=')) {
50
+ return arg.slice('--encoding='.length);
51
+ }
52
+ }
53
+ return undefined;
54
+ }
55
+ /**
56
+ * 解析目标输出编码(纯函数)。
57
+ * 优先级:① --json→utf8(最高) ② 显式 --encoding ③ OPENFEEL_ENCODING ④ 非 win32/TTY→utf8
58
+ * ⑤ win32 非 TTY→utf8。
59
+ */
60
+ export function resolveTargetEncoding(ctx) {
61
+ const { argv, env, platform, isTTY } = ctx;
62
+ // ① --json 恒 UTF-8(机器合同,覆盖一切显式/env/auto)
63
+ if (argv.includes('--json')) {
64
+ return 'utf8';
65
+ }
66
+ // ② 显式 --encoding
67
+ const fromArg = normalizeEncoding(readEncodingArg(argv));
68
+ if (fromArg) {
69
+ return fromArg;
70
+ }
71
+ // ③ 环境变量
72
+ const fromEnv = normalizeEncoding(env.OPENFEEL_ENCODING);
73
+ if (fromEnv) {
74
+ return fromEnv;
75
+ }
76
+ // ④ 非 win32 或 TTY:现代终端由 Node 控制台 API 直通,无需转码
77
+ if (platform !== 'win32' || isTTY) {
78
+ return 'utf8';
79
+ }
80
+ // ⑤ win32 非 TTY:直接 UTF-8(对齐 Node 默认与管道/CI 消费者;GBK 仅显式 ②/③)
81
+ return 'utf8';
82
+ }
83
+ /** 包装单个输出流:仅字符串 chunk 转码,Buffer 直通,保留 callback/返回值 */
84
+ function wrapStream(stream) {
85
+ const target = resolveTargetEncoding({
86
+ argv: process.argv.slice(2),
87
+ env: process.env,
88
+ platform: process.platform,
89
+ isTTY: Boolean(stream.isTTY),
90
+ });
91
+ // target=utf8 不包装(零行为变更)
92
+ if (target === 'utf8') {
93
+ return;
94
+ }
95
+ const orig = stream.write.bind(stream);
96
+ const wrapped = (chunk, encoding, cb) => {
97
+ if (typeof chunk === 'string') {
98
+ // 仅支持 UTF-8 字符串语义:丢弃调用方 encoding(REV-003);不可编码字符降 '?',不告警
99
+ const callback = typeof encoding === 'function' ? encoding : cb;
100
+ const buf = iconv.encode(chunk, target);
101
+ return orig(buf, callback);
102
+ }
103
+ // Buffer/二进制直通,保留原始签名
104
+ return orig(chunk, encoding, cb);
105
+ };
106
+ stream.write = wrapped;
107
+ }
108
+ /**
109
+ * 安装输出编码包装(幂等)。仅由 bin/openfeel.js 调用。
110
+ * 未调用时库/测试侧零副作用(不包装任何流)。
111
+ */
112
+ export function installOutputEncoding(opts = {}) {
113
+ if (installed) {
114
+ return;
115
+ }
116
+ wrapStream(opts.stdout ?? process.stdout);
117
+ wrapStream(opts.stderr ?? process.stderr);
118
+ installed = true;
119
+ }
120
+ //# sourceMappingURL=output-encoding.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"output-encoding.js","sourceRoot":"","sources":["../../src/cli/output-encoding.ts"],"names":[],"mappings":"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"}