openfeel 1.2.1 → 1.2.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.
- package/README.en.md +23 -1
- package/README.md +23 -1
- package/README.zh-CN.md +23 -1
- package/dist/cli/index.d.ts +17 -3
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +96 -8
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/project-option.d.ts +40 -0
- package/dist/cli/project-option.d.ts.map +1 -0
- package/dist/cli/project-option.js +140 -0
- package/dist/cli/project-option.js.map +1 -0
- package/dist/commands/archive.d.ts.map +1 -1
- package/dist/commands/archive.js +32 -2
- package/dist/commands/archive.js.map +1 -1
- package/dist/commands/config.d.ts.map +1 -1
- package/dist/commands/config.js +65 -7
- package/dist/commands/config.js.map +1 -1
- package/dist/commands/flow.d.ts.map +1 -1
- package/dist/commands/flow.js +394 -114
- package/dist/commands/flow.js.map +1 -1
- package/dist/commands/instructions.d.ts.map +1 -1
- package/dist/commands/instructions.js +13 -3
- package/dist/commands/instructions.js.map +1 -1
- package/dist/commands/knowledge.d.ts.map +1 -1
- package/dist/commands/knowledge.js +113 -17
- package/dist/commands/knowledge.js.map +1 -1
- package/dist/commands/plan.d.ts.map +1 -1
- package/dist/commands/plan.js +24 -6
- package/dist/commands/plan.js.map +1 -1
- package/dist/commands/project.d.ts +66 -0
- package/dist/commands/project.d.ts.map +1 -1
- package/dist/commands/project.js +122 -64
- package/dist/commands/project.js.map +1 -1
- package/dist/commands/req.d.ts.map +1 -1
- package/dist/commands/req.js +23 -11
- package/dist/commands/req.js.map +1 -1
- package/dist/commands/setup.d.ts.map +1 -1
- package/dist/commands/setup.js +11 -3
- package/dist/commands/setup.js.map +1 -1
- package/dist/commands/shared/errors.d.ts +55 -4
- package/dist/commands/shared/errors.d.ts.map +1 -1
- package/dist/commands/shared/errors.js +108 -10
- package/dist/commands/shared/errors.js.map +1 -1
- package/dist/commands/shared/json-output.d.ts +60 -0
- package/dist/commands/shared/json-output.d.ts.map +1 -0
- package/dist/commands/shared/json-output.js +152 -0
- package/dist/commands/shared/json-output.js.map +1 -0
- package/dist/commands/stage.d.ts.map +1 -1
- package/dist/commands/stage.js +62 -6
- package/dist/commands/stage.js.map +1 -1
- package/dist/commands/view.d.ts.map +1 -1
- package/dist/commands/view.js +27 -0
- package/dist/commands/view.js.map +1 -1
- package/dist/core/config.js +2 -2
- package/dist/core/errors.d.ts +100 -0
- package/dist/core/errors.d.ts.map +1 -0
- package/dist/core/errors.js +58 -0
- package/dist/core/errors.js.map +1 -0
- package/dist/core/flow-manager.d.ts +13 -0
- package/dist/core/flow-manager.d.ts.map +1 -1
- package/dist/core/flow-manager.js +22 -0
- package/dist/core/flow-manager.js.map +1 -1
- package/dist/core/fs/file-lock.d.ts +9 -0
- package/dist/core/fs/file-lock.d.ts.map +1 -1
- package/dist/core/fs/file-lock.js +27 -1
- package/dist/core/fs/file-lock.js.map +1 -1
- package/dist/core/i18n-data/en.d.ts.map +1 -1
- package/dist/core/i18n-data/en.js +42 -3
- package/dist/core/i18n-data/en.js.map +1 -1
- package/dist/core/i18n-data/zh-CN.d.ts.map +1 -1
- package/dist/core/i18n-data/zh-CN.js +42 -3
- package/dist/core/i18n-data/zh-CN.js.map +1 -1
- package/dist/core/pipeline-schema.d.ts +7 -0
- package/dist/core/pipeline-schema.d.ts.map +1 -1
- package/dist/core/pipeline-schema.js +7 -0
- package/dist/core/pipeline-schema.js.map +1 -1
- package/dist/core/req/aggregate.d.ts +19 -1
- package/dist/core/req/aggregate.d.ts.map +1 -1
- package/dist/core/req/aggregate.js +18 -5
- package/dist/core/req/aggregate.js.map +1 -1
- package/dist/core/template-loader.d.ts.map +1 -1
- package/dist/core/template-loader.js +33 -9
- package/dist/core/template-loader.js.map +1 -1
- package/dist/core/update.d.ts.map +1 -1
- package/dist/core/update.js +29 -5
- package/dist/core/update.js.map +1 -1
- package/package.json +1 -1
package/README.en.md
CHANGED
|
@@ -80,6 +80,28 @@ openfeel flow status
|
|
|
80
80
|
|
|
81
81
|
Upgrade/migration notes: see [docs/GETTING_STARTED.md](docs/GETTING_STARTED.md) ("工作流模式(full / fast)与自动推进" section, Chinese) and [CHANGELOG.md](CHANGELOG.md) `[1.1.7]`.
|
|
82
82
|
|
|
83
|
+
## Fixes in v1.2.3 (Patch)
|
|
84
|
+
|
|
85
|
+
> Stage covered: **stage-99**. This patch closes the items carried out of v1.2.2 and adds no new features; the 33 successful exports / 34 registered options contract and exit-code semantics are unchanged. This repository's closure baseline: **75 test files / 1911 cases / 21 stages**.
|
|
86
|
+
|
|
87
|
+
- **Unified concurrent JSON exit (REV-95-009)**: the `handleConcurrentConflict` JSON branch now emits the `FLOW_CONCURRENT_CONFLICT` envelope, sets `process.exitCode=2`, and returns (same mechanism as `failCli`, avoiding stdout truncation on Windows pipes); the non-JSON branch is unchanged verbatim; all 10 call sites return without fallthrough.
|
|
88
|
+
- **`--review-tier` help-text correction (REV-98-003 item 6)**: `flow advance --help` and the zh/en i18n entries now say "default = full (zero pruning)" instead of "derived from the workflow mode"; the mode-derived value is the `flow phases --json.reviewTier` display value; default advance behavior is unchanged.
|
|
89
|
+
- **`req` filter single-sourcing (REV-97-006)**: `req show` / `req set --workflow-mode` reuse `listLinkedStages`; `req split` and the core done primitives remain unchanged; behavior is identical.
|
|
90
|
+
- **Lock-timeout E2E test hook (REV-98-006①, test-only)**: an env seam active only when `OPENFEEL_TEST_MODE=1` makes the timeout path assert `INTERNAL_ERROR/internal/3` deterministically; production defaults remain 5000/3000ms.
|
|
91
|
+
|
|
92
|
+
## What's New in v1.2.2
|
|
93
|
+
|
|
94
|
+
> Stages covered: **stage-95 ~ 98**. All capabilities below are **available since v1.2.2**; `docs/json-contract.md` is the single authority for the JSON contract (33 successful exports / 34 registered options). This repository's closure baseline: 74 test files / 1894 cases / 21 stages.
|
|
95
|
+
|
|
96
|
+
- **`openfeel flow next [--json]` (decision authority, read-only)**: 12 keys in fixed order (`schemaVersion,stage,phase,phaseLabel,responsibleAgent,workflowMode,reviewTier,effectiveReviewTier,legalNextPhases,suggestedCommand,guards,blockingReviews`); `responsibleAgent` shares the same source as `mapPhaseToAgent`; every element of `legalNextPhases` is accepted by `flow advance`; zero writes.
|
|
97
|
+
- **Global `--project <path>`**: leading/trailing/`=` forms before or after any command; semantically equivalent to cwd; language resolves from the target project while `--log-file` relative paths resolve from the original cwd; `knowledge dedup` keeps its local declaration (syntactically compatible).
|
|
98
|
+
- **Full read-command `--json` coverage**: 13 command surfaces (`stage status` / `flow recover` / `flow checkpoint list` / `flow log` / `project overview` / `knowledge search|list|index|dedup` / `config get|effective` / `view list` / `plan scheme list`) plus `archive <stage> --json`; **33 successful exports / 34 registered options** in total.
|
|
99
|
+
- **Machine-readable error envelope**: `{schemaVersion:1,error:{code,kind,message,detail}}`; exit codes **0 success / 1 expected refusal / 2 concurrent conflict / 3 internal error (new)**; legacy `{error:'...'}` keeps the string type and key order, appending `errorKind` at the end; 12-row `code→kind→exitCode` mapping.
|
|
100
|
+
- **`--version --json`**: `{schemaVersion:1,version,node}` (three keys; listed separately, not counted among the 33 exports/34 options).
|
|
101
|
+
- **`flow archive --dry-run --json` criteria details + `archive <stage> --json`**: `eligible` / `unfinishedStages` / `blockingReviews`; `archivePath` / counts; `--dry-run` writes nothing.
|
|
102
|
+
- **`reviewTier` disambiguation**: `flow phases --json` / `flow status.stages[]` / `flow next` now expose both the display value `reviewTier`/`displayReviewTier` and the effective value `effectiveReviewTier` (always `full`). **Correction**: when `flow advance` is not given an explicit `--review-tier`, the effective tier is always **`full`** (not derived from the mode); the mode-derived value is `flow phases --json.reviewTier` (display only). Source help-text correction moves to v1.2.3.
|
|
103
|
+
- **Compatibility promise**: the existing 19 successful export field sets are unbroken (additive only); human output is unchanged verbatim; exit codes 0/1/2 keep their semantics while 3 is new only; the 15-phase enum / `advanceAccepted` / full-fast behavior are unchanged; existing `flow.json` files need zero migration and receive zero injection; REQ-001 L80 ("2 = internal or usage error") is registered as a requirement-text erratum (authoritative wording in contract §2/§10).
|
|
104
|
+
|
|
83
105
|
## What's New in v1.2.1
|
|
84
106
|
|
|
85
107
|
> Stages covered: **stage-86 ~ 93 + 94** (94 = out-of-table supplementary stage: model defaults and non-destructive deployment). All capabilities below are **available since v1.2.1**.
|
|
@@ -227,7 +249,7 @@ Core Layer
|
|
|
227
249
|
```bash
|
|
228
250
|
npm install # Install dependencies
|
|
229
251
|
npm run build # Compile TypeScript
|
|
230
|
-
npm test # Run tests (
|
|
252
|
+
npm test # Run tests (1894 cases / 74 test files; Linux CI skips 1 Windows-only case)
|
|
231
253
|
```
|
|
232
254
|
|
|
233
255
|
## Acknowledgments
|
package/README.md
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
|
|
9
9
|
OpenFeel 是一个 TypeScript CLI 工具,为 AI Agent 开发提供端到端的流程治理。核心理念:**「提示词瘦身,流程入工具」** —— Agent 不靠读长文本理解流程,而是通过 `flow.json` 获取当前状态和下一步指令。
|
|
10
10
|
|
|
11
|
-
> 📦 **最新版本 v1.2.
|
|
11
|
+
> 📦 **最新版本 v1.2.3**(v1.2.2 转出项收口 · 补丁) — 并发 JSON 退出机制统一(emit → `process.exitCode=2` → return)+ `flow advance --help --review-tier` 文案订正(缺省=full 零裁剪)+ `req show` / `req set` 过滤单点化 + 锁等待超时 E2E 测试钩子(test-only)。**33 个成功出口 / 34 个注册选项**契约与退出码 0/1/2/3 语义不变。
|
|
12
12
|
|
|
13
13
|
> 📌 本项目基于 [AI_Prompt](https://github.com/Liuary/AI_Prompt) 开发,参考了 [OpenSpec](https://github.com/Fission-AI/OpenSpec) 等工具的设计思路。
|
|
14
14
|
|
|
@@ -48,6 +48,28 @@ npm install -g openfeel@latest # 更新到最新版本
|
|
|
48
48
|
- **查看(只读)**:`openfeel flow mode [--stage <id>] [--json]`(当前模式 + 来源);`openfeel flow phases [--mode full|fast|general] [--stage <id>]`(按模式查看转移表)。
|
|
49
49
|
- **默认自动推进开启**:新部署默认 `auto_advance: enabled`(v1.1.7 起);如需关闭:`openfeel config set auto_advance disabled`。
|
|
50
50
|
|
|
51
|
+
## v1.2.3 修复(补丁)
|
|
52
|
+
|
|
53
|
+
> 对应阶段:**stage-99**。本版为 v1.2.2 转出项收口,不新增功能;JSON 契约 33 成功出口 / 34 注册选项与退出码语义不变。本仓收口基线:**75 文件 / 1911 用例 / 21 阶段**。
|
|
54
|
+
|
|
55
|
+
- **并发 JSON 退出机制统一(REV-95-009)**:`handleConcurrentConflict` JSON 分支改为「输出 `FLOW_CONCURRENT_CONFLICT` envelope → 置 `process.exitCode=2` → return」(与 `failCli` 同机制,规避 Windows 管道 stdout 截断);非 JSON 分支 `console.error + process.exit(2)` 逐字不变;10 个调用点无 fallthrough。
|
|
56
|
+
- **`--review-tier` help 文案订正(REV-98-003 第 6 项)**:`flow advance --help` 与 i18n zh/en 由「缺省=按模式派生」改为「缺省=full(零裁剪)」;按模式派生的是 `flow phases --json.reviewTier` 展示值;缺省推进行为不变。
|
|
57
|
+
- **`req` 过滤单点化(REV-97-006)**:`req show` / `req set --workflow-mode` 复用 `listLinkedStages`;`req split` 与 core 引擎层 done 判定原语保留;行为零变化。
|
|
58
|
+
- **锁等待超时 E2E 测试钩子(REV-98-006①,test-only)**:仅 `OPENFEEL_TEST_MODE=1` 生效的 env seam 使超时路径可稳定断言 `INTERNAL_ERROR/internal/3`;生产默认 5000/3000ms 不变。
|
|
59
|
+
|
|
60
|
+
## v1.2.2 新增能力
|
|
61
|
+
|
|
62
|
+
> 对应阶段:**stage-95 ~ 98**。以下能力**v1.2.2 起提供**;JSON 契约单一权威见 docs/json-contract.md(33 个成功出口 / 34 个注册选项)。本仓收口基线:74 文件 / 1894 用例 / 21 阶段。
|
|
63
|
+
|
|
64
|
+
- **`openfeel flow next [--json]`(决策权威,只读)**:12 键固定序(`schemaVersion,stage,phase,phaseLabel,responsibleAgent,workflowMode,reviewTier,effectiveReviewTier,legalNextPhases,suggestedCommand,guards,blockingReviews`);`responsibleAgent` 与 `mapPhaseToAgent` 同源;`legalNextPhases` 每个元素均被 `flow advance` 接受;零写盘。
|
|
65
|
+
- **全局 `--project <path>`**:任意命令前置/后置/`=` 形态;语义等效 cwd;语言按目标项目、`--log-file` 相对路径按原始 cwd;`knowledge dedup` 保留本地声明(语法兼容)。
|
|
66
|
+
- **读命令 `--json` 全量补全**:13 个命令面(`stage status` / `flow recover` / `flow checkpoint list` / `flow log` / `project overview` / `knowledge search|list|index|dedup` / `config get|effective` / `view list` / `plan scheme list`)+ `archive <stage> --json`;累计 **33 个成功出口 / 34 个注册选项**。
|
|
67
|
+
- **机器可读错误封装**:`{schemaVersion:1,error:{code,kind,message,detail}}`;退出码 **0 成功 / 1 预期拒绝 / 2 并发冲突 / 3 内部错误(新增)**;legacy `{error:'...'}` 保留 string 类型与键序、末尾追加 `errorKind`;12 行 `code→kind→exitCode` 映射表。
|
|
68
|
+
- **`--version --json`**:`{schemaVersion:1,version,node}`(三键;单列,不计入 33 出口/34 选项)。
|
|
69
|
+
- **`flow archive --dry-run --json` 判据明细 + `archive <stage> --json`**:`eligible` / `unfinishedStages` / `blockingReviews`;`archivePath` / 计数;`--dry-run` 零写盘。
|
|
70
|
+
- **`reviewTier` 消歧**:`flow phases --json` / `flow status.stages[]` / `flow next` 同时给出展示值 `reviewTier`/`displayReviewTier` 与生效值 `effectiveReviewTier`(恒 `full`)。**订正**:`flow advance` 未显式传 `--review-tier` 时生效档位恒 **`full`**(不是按模式派生);按模式派生的是 `flow phases --json.reviewTier` 展示值。源码 help 文案订正转 v1.2.3。
|
|
71
|
+
- **兼容承诺**:既有 19 个成功出口字段零破坏(只增不改);人类输出逐字不变;退出码 0/1/2 语义不变、3 仅新增;phase 枚举 15 项 / `advanceAccepted` / full-fast 行为不变;存量 `flow.json` 零迁移零注入;REQ-001 L80「2=内部错误或用法错误」登记为需求文本勘误(权威口径见契约 §2/§10)。
|
|
72
|
+
|
|
51
73
|
## v1.2.1 新增能力
|
|
52
74
|
|
|
53
75
|
> 对应阶段:**stage-86 ~ 93 + 94**(94 = 表外补阶段:模型默认值与部署非破坏性)。以下能力**v1.2.1 起提供**。
|
package/README.zh-CN.md
CHANGED
|
@@ -80,6 +80,28 @@ openfeel flow status
|
|
|
80
80
|
|
|
81
81
|
升级迁移提示见 [docs/GETTING_STARTED.md](docs/GETTING_STARTED.md)「工作流模式(full / fast)与自动推进」小节与 [CHANGELOG.md](CHANGELOG.md) `[1.1.7]`。
|
|
82
82
|
|
|
83
|
+
## v1.2.3 修复(补丁)
|
|
84
|
+
|
|
85
|
+
> 对应阶段:**stage-99**。本版为 v1.2.2 转出项收口,不新增功能;JSON 契约 33 成功出口 / 34 注册选项与退出码语义不变。本仓收口基线:**75 文件 / 1911 用例 / 21 阶段**。
|
|
86
|
+
|
|
87
|
+
- **并发 JSON 退出机制统一(REV-95-009)**:`handleConcurrentConflict` JSON 分支改为「输出 envelope → 置 `process.exitCode=2` → return」;非 JSON 分支逐字不变;10 个调用点无 fallthrough。
|
|
88
|
+
- **`--review-tier` help 文案订正(REV-98-003 第 6 项)**:源码 help 与 i18n zh/en 改为「缺省=full(零裁剪)」;缺省推进行为不变。
|
|
89
|
+
- **`req` 过滤单点化(REV-97-006)**:`req show` / `req set --workflow-mode` 复用 `listLinkedStages`;`req split` 与 core 引擎层 done 判定原语保留。
|
|
90
|
+
- **锁等待超时 E2E 测试钩子(REV-98-006①,test-only)**:仅 `OPENFEEL_TEST_MODE=1` 生效;生产默认 5000/3000ms 不变;E2E 断言 `INTERNAL_ERROR/internal/3`。
|
|
91
|
+
|
|
92
|
+
## v1.2.2 新增能力
|
|
93
|
+
|
|
94
|
+
> 对应阶段:**stage-95 ~ 98**。以下能力**v1.2.2 起提供**;JSON 契约单一权威见 docs/json-contract.md(33 个成功出口 / 34 个注册选项)。本仓收口基线:74 文件 / 1894 用例 / 21 阶段。
|
|
95
|
+
|
|
96
|
+
- **`openfeel flow next [--json]`(决策权威,只读)**:12 键固定序(`schemaVersion,stage,phase,phaseLabel,responsibleAgent,workflowMode,reviewTier,effectiveReviewTier,legalNextPhases,suggestedCommand,guards,blockingReviews`);`responsibleAgent` 与 `mapPhaseToAgent` 同源;`legalNextPhases` 每个元素均被 `flow advance` 接受;零写盘。
|
|
97
|
+
- **全局 `--project <path>`**:任意命令前置/后置/`=` 形态;语义等效 cwd;语言按目标项目、`--log-file` 相对路径按原始 cwd;`knowledge dedup` 保留本地声明(语法兼容)。
|
|
98
|
+
- **读命令 `--json` 全量补全**:13 个命令面(`stage status` / `flow recover` / `flow checkpoint list` / `flow log` / `project overview` / `knowledge search|list|index|dedup` / `config get|effective` / `view list` / `plan scheme list`)+ `archive <stage> --json`;累计 **33 个成功出口 / 34 个注册选项**。
|
|
99
|
+
- **机器可读错误封装**:`{schemaVersion:1,error:{code,kind,message,detail}}`;退出码 **0 成功 / 1 预期拒绝 / 2 并发冲突 / 3 内部错误(新增)**;legacy `{error:'...'}` 保留 string 类型与键序、末尾追加 `errorKind`;12 行 `code→kind→exitCode` 映射表。
|
|
100
|
+
- **`--version --json`**:`{schemaVersion:1,version,node}`(三键;单列,不计入 33 出口/34 选项)。
|
|
101
|
+
- **`flow archive --dry-run --json` 判据明细 + `archive <stage> --json`**:`eligible` / `unfinishedStages` / `blockingReviews`;`archivePath` / 计数;`--dry-run` 零写盘。
|
|
102
|
+
- **`reviewTier` 消歧**:`flow phases --json` / `flow status.stages[]` / `flow next` 同时给出展示值 `reviewTier`/`displayReviewTier` 与生效值 `effectiveReviewTier`(恒 `full`)。**订正**:`flow advance` 未显式传 `--review-tier` 时生效档位恒 **`full`**(不是按模式派生);按模式派生的是 `flow phases --json.reviewTier` 展示值。源码 help 文案订正转 v1.2.3。
|
|
103
|
+
- **兼容承诺**:既有 19 个成功出口字段零破坏(只增不改);人类输出逐字不变;退出码 0/1/2 语义不变、3 仅新增;phase 枚举 15 项 / `advanceAccepted` / full-fast 行为不变;存量 `flow.json` 零迁移零注入;REQ-001 L80「2=内部错误或用法错误」登记为需求文本勘误(权威口径见契约 §2/§10)。
|
|
104
|
+
|
|
83
105
|
## v1.2.1 新增能力
|
|
84
106
|
|
|
85
107
|
> 对应阶段:**stage-86 ~ 93 + 94**(94 = 表外补阶段:模型默认值与部署非破坏性)。以下能力**v1.2.1 起提供**。
|
|
@@ -227,7 +249,7 @@ Core 层
|
|
|
227
249
|
```bash
|
|
228
250
|
npm install # 安装依赖
|
|
229
251
|
npm run build # 编译 TypeScript
|
|
230
|
-
npm test # 运行测试(
|
|
252
|
+
npm test # 运行测试(1894 用例 / 74 个测试文件;Linux CI 跳过 1 个 Windows 专属用例)
|
|
231
253
|
```
|
|
232
254
|
|
|
233
255
|
## 致谢
|
package/dist/cli/index.d.ts
CHANGED
|
@@ -20,9 +20,23 @@ export declare function shouldUseColor(options?: {
|
|
|
20
20
|
export declare function applyHelpI18n(program: Command): void;
|
|
21
21
|
/** 并发写冲突退出码:与通用错误 1 区分,便于自动化识别「可重试」冲突 */
|
|
22
22
|
export declare const EXIT_CONCURRENT = 2;
|
|
23
|
-
/**
|
|
24
|
-
|
|
25
|
-
|
|
23
|
+
/**
|
|
24
|
+
* 统一 CLI 错误处理(单点,T38;stage-95 op-002 扩展 JSON 模式)。
|
|
25
|
+
* 分类优先级:并发冲突(exit 2)→ Commander 用法错误(JSON:INVALID_ARGUMENT/1)→ 其他(JSON:INTERNAL_ERROR/3)。
|
|
26
|
+
* 非 JSON 模式:并发冲突与用法错误保持既有形态;其他异常输出堆栈并置 exit 3(本版新增内部错误码)。
|
|
27
|
+
* @param err 捕获到的异常
|
|
28
|
+
*/
|
|
29
|
+
export declare function handleCliError(err: unknown): void;
|
|
30
|
+
/**
|
|
31
|
+
* CLI 启动入口:JSON 模式单点预扫描 + `--project` 项目锚定 + 统一 catch(并发 / 用法错误 / 内部错误)。
|
|
32
|
+
*
|
|
33
|
+
* 顺序契约(stage-95 op-003,严格):
|
|
34
|
+
* 1. `setJsonMode` —— 错误输出模式须在 `--project` 失败前已知;
|
|
35
|
+
* 2. `--version --json` 短路 —— 纯信息命令,不进入 Commander、不依赖项目(非法 `--project` 不阻断);
|
|
36
|
+
* `--help --json` 不拦截(帮助文本保持);
|
|
37
|
+
* 3. `applyProjectOption` —— 预扫描 + 单点 chdir,必须早于 `logCliStart`(日志 project 字段 = 目标项目);
|
|
38
|
+
* 4. `logCliStart` → `emitGlobalDeployCheck` → `program.parse` → `logCliDone`。
|
|
39
|
+
*/
|
|
26
40
|
export declare function runCli(): void;
|
|
27
41
|
export { program };
|
|
28
42
|
export { startRepl } from './repl.js';
|
package/dist/cli/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAE,OAAO,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAE,OAAO,EAAkB,MAAM,WAAW,CAAC;AAsBpD,QAAA,MAAM,OAAO,SAAgB,CAAC;AAqC9B;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAAC,OAAO,CAAC,EAAE;IAAE,KAAK,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,OAAO,CAYrE;AA2CD,wBAAgB,aAAa,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CA+EpD;AAED,yCAAyC;AACzC,eAAO,MAAM,eAAe,IAAI,CAAC;AAEjC;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,OAAO,GAAG,IAAI,CAwCjD;AAED;;;;;;;;;GASG;AACH,wBAAgB,MAAM,IAAI,IAAI,CAgC7B;AAED,OAAO,EAAE,OAAO,EAAE,CAAC;AACnB,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC"}
|
package/dist/cli/index.js
CHANGED
|
@@ -3,13 +3,15 @@
|
|
|
3
3
|
* 基于 Commander 构建命令行入口,静态导入并注册所有命令模块。
|
|
4
4
|
* 新增命令只需在 src/commands/ 下创建模块并在本文件末尾追加 import + register 调用。
|
|
5
5
|
*/
|
|
6
|
-
import { Command } from 'commander';
|
|
6
|
+
import { Command, CommanderError } from 'commander';
|
|
7
7
|
import { createRequire } from 'node:module';
|
|
8
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';
|
|
10
|
+
import { emitErrorEnvelope, handleConcurrentConflict } from '../commands/shared/errors.js';
|
|
11
|
+
import { isJsonMode, resolveJsonMode, setJsonMode, resolveVersionFlag, withSchemaVersion, emitJson, } from '../commands/shared/json-output.js';
|
|
11
12
|
import { runtimeLog, logCliStart, logCliDone } from '../core/runtime-log.js';
|
|
12
13
|
import { emitGlobalDeployCheck } from './deploy-check-output.js';
|
|
14
|
+
import { applyProjectOption } from './project-option.js';
|
|
13
15
|
// 读取 package.json 获取版本号
|
|
14
16
|
const require = createRequire(import.meta.url);
|
|
15
17
|
const pkg = require('../../package.json');
|
|
@@ -26,7 +28,31 @@ program
|
|
|
26
28
|
// stage-58 B-4:运行日志全局选项
|
|
27
29
|
.option('--log-file <path>', t('help.global.logFile', getCliLang(process.cwd())))
|
|
28
30
|
.option('--no-log', t('help.global.noLog', getCliLang(process.cwd())))
|
|
29
|
-
.option('--debug', t('help.global.debug', getCliLang(process.cwd())))
|
|
31
|
+
.option('--debug', t('help.global.debug', getCliLang(process.cwd())))
|
|
32
|
+
// stage-95 op-003:全局 --project(预扫描 + 单点 chdir;help 文案语言在模块加载期按原始 cwd 求值)
|
|
33
|
+
.option('--project <path>', t('help.global.project', getCliLang(process.cwd())));
|
|
34
|
+
// ── stage-95 op-002:Commander 机制(须在子命令注册前安装,子命令创建时继承) ──
|
|
35
|
+
// 用法错误(未知命令/未知选项/缺参)的 JSON 模式封装:
|
|
36
|
+
// - exitCode===0(--help / --version)放行,走 Commander 原生 process.exit(0);
|
|
37
|
+
// - JSON 模式 throw CommanderError → runCli catch 转 INVALID_ARGUMENT envelope + exit 1;
|
|
38
|
+
// - 非 JSON 模式 process.exit(err.exitCode),与现状逐字等价。
|
|
39
|
+
program.exitOverride((err) => {
|
|
40
|
+
if (err.code === 'commander.executeSubCommandAsync')
|
|
41
|
+
return;
|
|
42
|
+
if (err.exitCode === 0)
|
|
43
|
+
return;
|
|
44
|
+
if (isJsonMode())
|
|
45
|
+
throw err;
|
|
46
|
+
process.exit(err.exitCode);
|
|
47
|
+
});
|
|
48
|
+
// JSON 模式下静默 Commander 人类错误文本(防止混入 stdout/stderr);非 JSON 逐字不变
|
|
49
|
+
program.configureOutput({
|
|
50
|
+
writeErr: (str) => {
|
|
51
|
+
if (!isJsonMode()) {
|
|
52
|
+
process.stderr.write(str);
|
|
53
|
+
}
|
|
54
|
+
},
|
|
55
|
+
});
|
|
30
56
|
/**
|
|
31
57
|
* 是否启用彩色输出(B7-1,单一判定入口)。
|
|
32
58
|
* 优先级:`--no-color`(显式关闭,commander 解析为 color=false) > `NO_COLOR` 环境变量(存在且**非空**即关闭,
|
|
@@ -166,22 +192,84 @@ export function applyHelpI18n(program) {
|
|
|
166
192
|
}
|
|
167
193
|
/** 并发写冲突退出码:与通用错误 1 区分,便于自动化识别「可重试」冲突 */
|
|
168
194
|
export const EXIT_CONCURRENT = 2;
|
|
169
|
-
/**
|
|
195
|
+
/**
|
|
196
|
+
* 统一 CLI 错误处理(单点,T38;stage-95 op-002 扩展 JSON 模式)。
|
|
197
|
+
* 分类优先级:并发冲突(exit 2)→ Commander 用法错误(JSON:INVALID_ARGUMENT/1)→ 其他(JSON:INTERNAL_ERROR/3)。
|
|
198
|
+
* 非 JSON 模式:并发冲突与用法错误保持既有形态;其他异常输出堆栈并置 exit 3(本版新增内部错误码)。
|
|
199
|
+
* @param err 捕获到的异常
|
|
200
|
+
*/
|
|
170
201
|
export function handleCliError(err) {
|
|
171
202
|
// stage-58 B-6:记录「命令处理中抛出的异常」。error 级语义边界(REV-002):
|
|
172
203
|
// commander 解析期错误(未知命令/未知选项/缺参)经 program.error() 直接 process.exit(1),不抛异常、不达此处 → 不入日志。
|
|
204
|
+
// stage-95 op-002:JSON 模式下解析期错误经 exitOverride throw 后到达此处(记日志,形态无回归)。
|
|
173
205
|
runtimeLog('error', 'cli error: ' + (err instanceof Error ? err.message : String(err)));
|
|
174
206
|
if (isFlowConcurrentError(err)) {
|
|
175
207
|
handleConcurrentConflict(err, getCliLang(process.cwd()));
|
|
208
|
+
return;
|
|
209
|
+
}
|
|
210
|
+
const lang = getCliLang(process.cwd());
|
|
211
|
+
if (err instanceof CommanderError) {
|
|
212
|
+
// JSON 模式:用法错误 → INVALID_ARGUMENT envelope + exit 1
|
|
213
|
+
if (isJsonMode()) {
|
|
214
|
+
emitErrorEnvelope({
|
|
215
|
+
code: 'INVALID_ARGUMENT',
|
|
216
|
+
message: t('common.invalidArgumentTmpl', lang, { detail: err.message }),
|
|
217
|
+
detail: { commanderCode: err.code },
|
|
218
|
+
});
|
|
219
|
+
process.exitCode = 1;
|
|
220
|
+
return;
|
|
221
|
+
}
|
|
222
|
+
// 非 JSON:保持既有未捕获形态(正常路径到不了此处,exitOverride 已 process.exit)
|
|
223
|
+
throw err;
|
|
176
224
|
}
|
|
177
|
-
|
|
225
|
+
if (isJsonMode()) {
|
|
226
|
+
// JSON 模式:其他未捕获异常 → INTERNAL_ERROR envelope + exit 3
|
|
227
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
228
|
+
emitErrorEnvelope({
|
|
229
|
+
code: 'INTERNAL_ERROR',
|
|
230
|
+
message: t('common.errorTmpl', lang, { msg }),
|
|
231
|
+
detail: err instanceof Error
|
|
232
|
+
? { name: err.name, message: err.message, stack: err.stack }
|
|
233
|
+
: { name: 'Error', message: String(err) },
|
|
234
|
+
});
|
|
235
|
+
process.exitCode = 3;
|
|
236
|
+
return;
|
|
237
|
+
}
|
|
238
|
+
// 非 JSON:保持既有含堆栈形态,退出码归本版新增的 3(内部错误)
|
|
239
|
+
console.error(err instanceof Error ? (err.stack ?? err.message) : String(err));
|
|
240
|
+
process.exitCode = 3;
|
|
178
241
|
}
|
|
179
|
-
/**
|
|
242
|
+
/**
|
|
243
|
+
* CLI 启动入口:JSON 模式单点预扫描 + `--project` 项目锚定 + 统一 catch(并发 / 用法错误 / 内部错误)。
|
|
244
|
+
*
|
|
245
|
+
* 顺序契约(stage-95 op-003,严格):
|
|
246
|
+
* 1. `setJsonMode` —— 错误输出模式须在 `--project` 失败前已知;
|
|
247
|
+
* 2. `--version --json` 短路 —— 纯信息命令,不进入 Commander、不依赖项目(非法 `--project` 不阻断);
|
|
248
|
+
* `--help --json` 不拦截(帮助文本保持);
|
|
249
|
+
* 3. `applyProjectOption` —— 预扫描 + 单点 chdir,必须早于 `logCliStart`(日志 project 字段 = 目标项目);
|
|
250
|
+
* 4. `logCliStart` → `emitGlobalDeployCheck` → `program.parse` → `logCliDone`。
|
|
251
|
+
*/
|
|
180
252
|
export function runCli() {
|
|
253
|
+
// stage-95 op-002:JSON 模式单点(命令层只读 isJsonMode(),不得各自解析 argv)
|
|
254
|
+
const argv = process.argv.slice(2);
|
|
255
|
+
setJsonMode(resolveJsonMode(argv));
|
|
256
|
+
// stage-95 op-003:--version/-v + --json → 单文档并返回(不进入 Commander;纯信息命令)
|
|
257
|
+
if (resolveVersionFlag(argv) && isJsonMode()) {
|
|
258
|
+
logCliStart(argv);
|
|
259
|
+
emitJson(withSchemaVersion({ version: pkg.version, node: process.version }));
|
|
260
|
+
logCliDone(0);
|
|
261
|
+
return;
|
|
262
|
+
}
|
|
263
|
+
// stage-95 op-003:--project 预扫描必须在 logCliStart 之前(日志 project 字段 = 目标项目)
|
|
264
|
+
if (!applyProjectOption(argv)) {
|
|
265
|
+
// JSON 模式 failCli 仅置 process.exitCode 不退出 → 此处 return 保 logCliDone 记录真实码
|
|
266
|
+
logCliDone(typeof process.exitCode === 'number' ? process.exitCode : 1);
|
|
267
|
+
return;
|
|
268
|
+
}
|
|
181
269
|
// stage-58 B-6:命令(argv)+ 结果入运行日志;不记录 stdout 内容。
|
|
182
270
|
// 注:--help/--version 经 commander 输出后 exit → 由 exit 兜底记「cli done」(v1.2.1-stage-86 有意变更);
|
|
183
|
-
// 错误路径经 handleCliError
|
|
184
|
-
logCliStart(
|
|
271
|
+
// 错误路径经 handleCliError 置退出码后落到 logCliDone,记录真实退出码。
|
|
272
|
+
logCliStart(argv);
|
|
185
273
|
// stage-67:被动部署提示(门控内置于适配器;异常静默,不影响主命令)
|
|
186
274
|
emitGlobalDeployCheck();
|
|
187
275
|
try {
|
package/dist/cli/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/** `--project` 预扫描结果 */
|
|
2
|
+
export interface ProjectArgResult {
|
|
3
|
+
/** 全部 `--project` 原始取值(按出现顺序;路径解析归 applyProjectOption) */
|
|
4
|
+
values: string[];
|
|
5
|
+
/** 是否出现缺值形态(`--project` 末尾/后接选项,或 `--project=` 空值) */
|
|
6
|
+
missingValue: boolean;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* 提取全部 `--project` 值(含 `--project=`;缺失值置标志)。
|
|
10
|
+
* @param argv 命令行参数(不含 node 与脚本路径)
|
|
11
|
+
* @returns 原始取值列表与缺值标志
|
|
12
|
+
*/
|
|
13
|
+
export declare function extractProjectArgs(argv: string[]): ProjectArgResult;
|
|
14
|
+
/**
|
|
15
|
+
* 单值便捷入口:取最后一个出现值(无则 null)。
|
|
16
|
+
* 注:多值冲突判定在 applyProjectOption 内完成,本函数仅用于单值场景。
|
|
17
|
+
* @param argv 命令行参数
|
|
18
|
+
* @returns 最后一个 `--project` 原始值;未出现返回 null
|
|
19
|
+
*/
|
|
20
|
+
export declare function extractProjectArg(argv: string[]): string | null;
|
|
21
|
+
/**
|
|
22
|
+
* 预扫描应用:校验并 chdir 到 `--project` 目标目录。
|
|
23
|
+
* 成功 chdir 返回 true;失败输出错误后返回 false(JSON 模式不 exit,由调用方 return;
|
|
24
|
+
* 非 JSON 模式 failCli 即时退出,测试 mock exit 时可继续返回 false)。
|
|
25
|
+
* @param argv 命令行参数
|
|
26
|
+
* @param originalCwd 原始 cwd(缺省 = process.cwd();用于 chdir 前的路径/语言解析)
|
|
27
|
+
* @returns 是否可继续执行
|
|
28
|
+
*/
|
|
29
|
+
export declare function applyProjectOption(argv: string[], originalCwd?: string): boolean;
|
|
30
|
+
/**
|
|
31
|
+
* 命令层单点解析项目根路径。
|
|
32
|
+
* 预扫描成功时返回绝对路径(禁止对原始相对值二次 resolve);直接 parse(测试/库调用)无预扫描时
|
|
33
|
+
* 回退 `resolve(process.cwd(), raw ?? '.')`,保持既有 `knowledge dedup --project X` 语义。
|
|
34
|
+
* @param raw 命令层取得的原始 `--project` 值(可为 undefined)
|
|
35
|
+
* @returns 绝对项目根路径
|
|
36
|
+
*/
|
|
37
|
+
export declare function resolveProjectPathForCommand(raw?: string): string;
|
|
38
|
+
/** 测试隔离:清空预扫描结果(非生产路径) */
|
|
39
|
+
export declare function resetProjectRootForTest(): void;
|
|
40
|
+
//# sourceMappingURL=project-option.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"project-option.d.ts","sourceRoot":"","sources":["../../src/cli/project-option.ts"],"names":[],"mappings":"AAuBA,wBAAwB;AACxB,MAAM,WAAW,gBAAgB;IAC/B,0DAA0D;IAC1D,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,sDAAsD;IACtD,YAAY,EAAE,OAAO,CAAC;CACvB;AAKD;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,gBAAgB,CAGnE;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,MAAM,GAAG,IAAI,CAG/D;AAED;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,OAAO,CA0EhF;AAED;;;;;;GAMG;AACH,wBAAgB,4BAA4B,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,CAKjE;AAED,0BAA0B;AAC1B,wBAAgB,uBAAuB,IAAI,IAAI,CAE9C"}
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 全局 --project 项目锚定(v1.2.2-stage-95 op-003)
|
|
3
|
+
*
|
|
4
|
+
* 职责:
|
|
5
|
+
* - 预扫描 argv 中的 `--project <path>` / `--project=<path>`(复用 json-output 的 scanArgv,禁止第二套扫描);
|
|
6
|
+
* - 路径校验(存在且为目录)与单点 `process.chdir` 注入;
|
|
7
|
+
* - 错误封装:缺失值 / 多值冲突 → INVALID_ARGUMENT(refusal/1);路径问题 → PROJECT_NOT_FOUND(refusal/1);
|
|
8
|
+
* - 供命令层单点解析项目根(`resolveProjectPathForCommand`),预扫描结果优先。
|
|
9
|
+
*
|
|
10
|
+
* 边界(REV-95-003 / D-95-12~16):
|
|
11
|
+
* - **单进程单命令**:CLI 每次调用至多 chdir 一次,不承诺进程内多项目并发切换;
|
|
12
|
+
* - **--log-file**:由 bin 的 installRuntimeLog 在本函数 chdir 之前按原始 cwd 解析(本模块不解释日志路径);
|
|
13
|
+
* - **help 语言**:bin 的 applyHelpI18n 在本函数之前按原始 cwd 求值;命令输出/错误文案由 chdir 后
|
|
14
|
+
* 的 getCliLang(process.cwd()) 按目标项目解析;
|
|
15
|
+
* - **禁止二次 resolve**:预扫描已把 `--project` 解析为绝对路径,命令层不得对原始相对值再次拼接;
|
|
16
|
+
* - 命令层禁用 `options.project`(根/子同名 flag 实测被根选项吞掉),统一走 optsWithGlobals + 本模块单点。
|
|
17
|
+
*/
|
|
18
|
+
import { statSync } from 'node:fs';
|
|
19
|
+
import { resolve } from 'node:path';
|
|
20
|
+
import { getCliLang, t } from '../core/i18n.js';
|
|
21
|
+
import { failCli } from '../commands/shared/errors.js';
|
|
22
|
+
import { scanArgv } from '../commands/shared/json-output.js';
|
|
23
|
+
/** 进程级预扫描结果:成功 chdir 后的绝对项目根;null = 未指定 */
|
|
24
|
+
let resolvedProjectRoot = null;
|
|
25
|
+
/**
|
|
26
|
+
* 提取全部 `--project` 值(含 `--project=`;缺失值置标志)。
|
|
27
|
+
* @param argv 命令行参数(不含 node 与脚本路径)
|
|
28
|
+
* @returns 原始取值列表与缺值标志
|
|
29
|
+
*/
|
|
30
|
+
export function extractProjectArgs(argv) {
|
|
31
|
+
const scan = scanArgv(argv);
|
|
32
|
+
return { values: scan.projectValues, missingValue: scan.projectMissingValue };
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* 单值便捷入口:取最后一个出现值(无则 null)。
|
|
36
|
+
* 注:多值冲突判定在 applyProjectOption 内完成,本函数仅用于单值场景。
|
|
37
|
+
* @param argv 命令行参数
|
|
38
|
+
* @returns 最后一个 `--project` 原始值;未出现返回 null
|
|
39
|
+
*/
|
|
40
|
+
export function extractProjectArg(argv) {
|
|
41
|
+
const { values } = extractProjectArgs(argv);
|
|
42
|
+
return values.length > 0 ? values[values.length - 1] : null;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* 预扫描应用:校验并 chdir 到 `--project` 目标目录。
|
|
46
|
+
* 成功 chdir 返回 true;失败输出错误后返回 false(JSON 模式不 exit,由调用方 return;
|
|
47
|
+
* 非 JSON 模式 failCli 即时退出,测试 mock exit 时可继续返回 false)。
|
|
48
|
+
* @param argv 命令行参数
|
|
49
|
+
* @param originalCwd 原始 cwd(缺省 = process.cwd();用于 chdir 前的路径/语言解析)
|
|
50
|
+
* @returns 是否可继续执行
|
|
51
|
+
*/
|
|
52
|
+
export function applyProjectOption(argv, originalCwd) {
|
|
53
|
+
const cwd = originalCwd ?? process.cwd();
|
|
54
|
+
// D-95-13:错误文案语言按原始 cwd 解析(目标路径可能不存在)
|
|
55
|
+
const lang = getCliLang(cwd);
|
|
56
|
+
const { values, missingValue } = extractProjectArgs(argv);
|
|
57
|
+
// 缺值:`--project` 后无取值或取值为选项 token
|
|
58
|
+
if (missingValue) {
|
|
59
|
+
const message = t('common.projectMissingValueTmpl', lang);
|
|
60
|
+
failCli({
|
|
61
|
+
code: 'INVALID_ARGUMENT',
|
|
62
|
+
message,
|
|
63
|
+
detail: { option: '--project' },
|
|
64
|
+
stderrLines: [message],
|
|
65
|
+
});
|
|
66
|
+
return false;
|
|
67
|
+
}
|
|
68
|
+
// 未指定:清空预扫描状态,回退 process.cwd()(既有行为逐字不变)
|
|
69
|
+
if (values.length === 0) {
|
|
70
|
+
resolvedProjectRoot = null;
|
|
71
|
+
return true;
|
|
72
|
+
}
|
|
73
|
+
// 多值:解析后路径不一致属用法错误;一致则允许(D-95-12)
|
|
74
|
+
const resolved = values.map((v) => resolve(cwd, v));
|
|
75
|
+
if (new Set(resolved).size > 1) {
|
|
76
|
+
const message = t('common.projectConflictTmpl', lang, { values: resolved.join(', ') });
|
|
77
|
+
failCli({
|
|
78
|
+
code: 'INVALID_ARGUMENT',
|
|
79
|
+
message,
|
|
80
|
+
detail: { option: '--project', values: resolved },
|
|
81
|
+
stderrLines: [message],
|
|
82
|
+
});
|
|
83
|
+
return false;
|
|
84
|
+
}
|
|
85
|
+
const abs = resolved[0];
|
|
86
|
+
// 目录校验:不存在 → not-found;存在但不是目录 → not-directory
|
|
87
|
+
let reason = null;
|
|
88
|
+
try {
|
|
89
|
+
if (!statSync(abs).isDirectory()) {
|
|
90
|
+
reason = 'not-directory';
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
catch {
|
|
94
|
+
reason = 'not-found';
|
|
95
|
+
}
|
|
96
|
+
if (reason !== null) {
|
|
97
|
+
const message = t('common.projectNotFoundTmpl', lang, { path: abs });
|
|
98
|
+
failCli({
|
|
99
|
+
code: 'PROJECT_NOT_FOUND',
|
|
100
|
+
message,
|
|
101
|
+
detail: { path: abs, reason },
|
|
102
|
+
stderrLines: [message],
|
|
103
|
+
});
|
|
104
|
+
return false;
|
|
105
|
+
}
|
|
106
|
+
// 单点 chdir:失败(权限/竞态)同样归 PROJECT_NOT_FOUND
|
|
107
|
+
try {
|
|
108
|
+
process.chdir(abs);
|
|
109
|
+
}
|
|
110
|
+
catch {
|
|
111
|
+
const message = t('common.projectNotFoundTmpl', lang, { path: abs });
|
|
112
|
+
failCli({
|
|
113
|
+
code: 'PROJECT_NOT_FOUND',
|
|
114
|
+
message,
|
|
115
|
+
detail: { path: abs, reason: 'chdir-failed' },
|
|
116
|
+
stderrLines: [message],
|
|
117
|
+
});
|
|
118
|
+
return false;
|
|
119
|
+
}
|
|
120
|
+
resolvedProjectRoot = abs;
|
|
121
|
+
return true;
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* 命令层单点解析项目根路径。
|
|
125
|
+
* 预扫描成功时返回绝对路径(禁止对原始相对值二次 resolve);直接 parse(测试/库调用)无预扫描时
|
|
126
|
+
* 回退 `resolve(process.cwd(), raw ?? '.')`,保持既有 `knowledge dedup --project X` 语义。
|
|
127
|
+
* @param raw 命令层取得的原始 `--project` 值(可为 undefined)
|
|
128
|
+
* @returns 绝对项目根路径
|
|
129
|
+
*/
|
|
130
|
+
export function resolveProjectPathForCommand(raw) {
|
|
131
|
+
if (resolvedProjectRoot) {
|
|
132
|
+
return resolvedProjectRoot;
|
|
133
|
+
}
|
|
134
|
+
return raw ? resolve(process.cwd(), raw) : process.cwd();
|
|
135
|
+
}
|
|
136
|
+
/** 测试隔离:清空预扫描结果(非生产路径) */
|
|
137
|
+
export function resetProjectRootForTest() {
|
|
138
|
+
resolvedProjectRoot = null;
|
|
139
|
+
}
|
|
140
|
+
//# sourceMappingURL=project-option.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"project-option.js","sourceRoot":"","sources":["../../src/cli/project-option.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"archive.d.ts","sourceRoot":"","sources":["../../src/commands/archive.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"archive.d.ts","sourceRoot":"","sources":["../../src/commands/archive.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAOpC,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAiE7D"}
|
package/dist/commands/archive.js
CHANGED
|
@@ -1,19 +1,44 @@
|
|
|
1
1
|
import { archiveStage } from '../core/archive/merge.js';
|
|
2
2
|
import { join } from 'node:path';
|
|
3
3
|
import { t, getCliLang } from '../core/i18n.js';
|
|
4
|
+
import { withSchemaVersion, emitJson } from './shared/json-output.js';
|
|
5
|
+
import { failRefusal, failInternal } from './shared/errors.js';
|
|
4
6
|
export function registerArchiveCommand(program) {
|
|
5
7
|
program
|
|
6
8
|
.command('archive')
|
|
7
9
|
.description('归档指定阶段(汇总产出、生成摘要、提取知识)')
|
|
8
10
|
.argument('<stage>', '阶段名称(如 stage-06)')
|
|
9
|
-
.
|
|
11
|
+
.option('--json', t('help.archive.json', getCliLang(process.cwd())))
|
|
12
|
+
.action((stage, options) => {
|
|
10
13
|
const lang = getCliLang(process.cwd());
|
|
14
|
+
const asJson = options.json === true;
|
|
11
15
|
try {
|
|
12
16
|
const result = archiveStage(process.cwd(), stage);
|
|
13
17
|
if (!result) {
|
|
18
|
+
// 业务拒绝(阶段不存在 / 未初始化):JSON envelope ARCHIVE_FAILED / refusal / 1
|
|
19
|
+
if (asJson) {
|
|
20
|
+
failRefusal({
|
|
21
|
+
code: 'ARCHIVE_FAILED',
|
|
22
|
+
message: t('archive.errorArchiveFailedTmpl', lang, { stage }),
|
|
23
|
+
detail: { stage },
|
|
24
|
+
});
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
14
27
|
console.error(t('archive.errorArchiveFailedTmpl', lang, { stage }));
|
|
15
28
|
process.exit(1);
|
|
16
29
|
}
|
|
30
|
+
const archivePath = join(process.cwd(), '.openfeel', 'log', `archive-${stage}.md`);
|
|
31
|
+
if (asJson) {
|
|
32
|
+
// 成功 6 键(D-97-03-05):stage 为输入原值;archivePath 与人类输出同源
|
|
33
|
+
emitJson(withSchemaVersion({
|
|
34
|
+
stage,
|
|
35
|
+
archivePath,
|
|
36
|
+
opsCount: result.opsCount,
|
|
37
|
+
reviewsCount: result.reviewsCount,
|
|
38
|
+
knowledgeExtracts: result.knowledgeExtracts,
|
|
39
|
+
}));
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
17
42
|
// 输出归档结果
|
|
18
43
|
console.log(t('archive.okTmpl', lang, { stage }));
|
|
19
44
|
console.log(` ${t('archive.opsCount', lang)}: ${result.opsCount}`);
|
|
@@ -26,10 +51,15 @@ export function registerArchiveCommand(program) {
|
|
|
26
51
|
}
|
|
27
52
|
}
|
|
28
53
|
// 输出归档文件路径
|
|
29
|
-
const archivePath = join(process.cwd(), '.openfeel', 'log', `archive-${stage}.md`);
|
|
30
54
|
console.log(` ${t('archive.archivePath', lang)}: ${archivePath}`);
|
|
31
55
|
}
|
|
32
56
|
catch (err) {
|
|
57
|
+
// 异常:JSON → INTERNAL_ERROR / internal / 3;人类保持既有 exit 1 文案
|
|
58
|
+
if (asJson) {
|
|
59
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
60
|
+
failInternal(err, { stderrLines: [t('common.errorTmpl', lang, { msg })] });
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
33
63
|
console.error(t('common.errorTmpl', lang, { msg: err instanceof Error ? err.message : String(err) }));
|
|
34
64
|
process.exit(1);
|
|
35
65
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"archive.js","sourceRoot":"","sources":["../../src/commands/archive.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AACxD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,CAAC,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"archive.js","sourceRoot":"","sources":["../../src/commands/archive.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/commands/config.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/commands/config.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAyEpC;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CA+X5D"}
|