openfeel 1.2.1 → 1.2.4

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 (104) hide show
  1. package/README.en.md +34 -1
  2. package/README.md +34 -1
  3. package/README.zh-CN.md +34 -1
  4. package/dist/cli/index.d.ts +17 -3
  5. package/dist/cli/index.d.ts.map +1 -1
  6. package/dist/cli/index.js +96 -8
  7. package/dist/cli/index.js.map +1 -1
  8. package/dist/cli/project-option.d.ts +40 -0
  9. package/dist/cli/project-option.d.ts.map +1 -0
  10. package/dist/cli/project-option.js +140 -0
  11. package/dist/cli/project-option.js.map +1 -0
  12. package/dist/commands/archive.d.ts.map +1 -1
  13. package/dist/commands/archive.js +45 -4
  14. package/dist/commands/archive.js.map +1 -1
  15. package/dist/commands/config.d.ts.map +1 -1
  16. package/dist/commands/config.js +103 -9
  17. package/dist/commands/config.js.map +1 -1
  18. package/dist/commands/flow.d.ts.map +1 -1
  19. package/dist/commands/flow.js +438 -125
  20. package/dist/commands/flow.js.map +1 -1
  21. package/dist/commands/instructions.d.ts.map +1 -1
  22. package/dist/commands/instructions.js +13 -3
  23. package/dist/commands/instructions.js.map +1 -1
  24. package/dist/commands/knowledge.d.ts.map +1 -1
  25. package/dist/commands/knowledge.js +113 -17
  26. package/dist/commands/knowledge.js.map +1 -1
  27. package/dist/commands/lint.d.ts.map +1 -1
  28. package/dist/commands/lint.js +78 -39
  29. package/dist/commands/lint.js.map +1 -1
  30. package/dist/commands/model.d.ts.map +1 -1
  31. package/dist/commands/model.js +86 -8
  32. package/dist/commands/model.js.map +1 -1
  33. package/dist/commands/plan.d.ts.map +1 -1
  34. package/dist/commands/plan.js +45 -7
  35. package/dist/commands/plan.js.map +1 -1
  36. package/dist/commands/project.d.ts +66 -0
  37. package/dist/commands/project.d.ts.map +1 -1
  38. package/dist/commands/project.js +122 -64
  39. package/dist/commands/project.js.map +1 -1
  40. package/dist/commands/req.d.ts.map +1 -1
  41. package/dist/commands/req.js +23 -11
  42. package/dist/commands/req.js.map +1 -1
  43. package/dist/commands/roadmap.d.ts.map +1 -1
  44. package/dist/commands/roadmap.js +21 -2
  45. package/dist/commands/roadmap.js.map +1 -1
  46. package/dist/commands/setup.d.ts.map +1 -1
  47. package/dist/commands/setup.js +11 -3
  48. package/dist/commands/setup.js.map +1 -1
  49. package/dist/commands/shared/errors.d.ts +55 -4
  50. package/dist/commands/shared/errors.d.ts.map +1 -1
  51. package/dist/commands/shared/errors.js +108 -10
  52. package/dist/commands/shared/errors.js.map +1 -1
  53. package/dist/commands/shared/json-output.d.ts +60 -0
  54. package/dist/commands/shared/json-output.d.ts.map +1 -0
  55. package/dist/commands/shared/json-output.js +152 -0
  56. package/dist/commands/shared/json-output.js.map +1 -0
  57. package/dist/commands/stage.d.ts.map +1 -1
  58. package/dist/commands/stage.js +62 -6
  59. package/dist/commands/stage.js.map +1 -1
  60. package/dist/commands/view.d.ts.map +1 -1
  61. package/dist/commands/view.js +27 -0
  62. package/dist/commands/view.js.map +1 -1
  63. package/dist/core/archive/merge.d.ts +16 -1
  64. package/dist/core/archive/merge.d.ts.map +1 -1
  65. package/dist/core/archive/merge.js +27 -4
  66. package/dist/core/archive/merge.js.map +1 -1
  67. package/dist/core/config.js +2 -2
  68. package/dist/core/errors.d.ts +105 -0
  69. package/dist/core/errors.d.ts.map +1 -0
  70. package/dist/core/errors.js +61 -0
  71. package/dist/core/errors.js.map +1 -0
  72. package/dist/core/flow-manager.d.ts +13 -0
  73. package/dist/core/flow-manager.d.ts.map +1 -1
  74. package/dist/core/flow-manager.js +22 -0
  75. package/dist/core/flow-manager.js.map +1 -1
  76. package/dist/core/fs/file-lock.d.ts +9 -0
  77. package/dist/core/fs/file-lock.d.ts.map +1 -1
  78. package/dist/core/fs/file-lock.js +27 -1
  79. package/dist/core/fs/file-lock.js.map +1 -1
  80. package/dist/core/i18n-data/en.d.ts.map +1 -1
  81. package/dist/core/i18n-data/en.js +53 -3
  82. package/dist/core/i18n-data/en.js.map +1 -1
  83. package/dist/core/i18n-data/zh-CN.d.ts.map +1 -1
  84. package/dist/core/i18n-data/zh-CN.js +53 -3
  85. package/dist/core/i18n-data/zh-CN.js.map +1 -1
  86. package/dist/core/pipeline-schema.d.ts +7 -0
  87. package/dist/core/pipeline-schema.d.ts.map +1 -1
  88. package/dist/core/pipeline-schema.js +7 -0
  89. package/dist/core/pipeline-schema.js.map +1 -1
  90. package/dist/core/plan/roadmap.d.ts +29 -0
  91. package/dist/core/plan/roadmap.d.ts.map +1 -1
  92. package/dist/core/plan/roadmap.js +95 -0
  93. package/dist/core/plan/roadmap.js.map +1 -1
  94. package/dist/core/req/aggregate.d.ts +19 -1
  95. package/dist/core/req/aggregate.d.ts.map +1 -1
  96. package/dist/core/req/aggregate.js +18 -5
  97. package/dist/core/req/aggregate.js.map +1 -1
  98. package/dist/core/template-loader.d.ts.map +1 -1
  99. package/dist/core/template-loader.js +48 -14
  100. package/dist/core/template-loader.js.map +1 -1
  101. package/dist/core/update.d.ts.map +1 -1
  102. package/dist/core/update.js +44 -10
  103. package/dist/core/update.js.map +1 -1
  104. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"setup.js","sourceRoot":"","sources":["../../src/commands/setup.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"setup.js","sourceRoot":"","sources":["../../src/commands/setup.ts"],"names":[],"mappings":"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"}
@@ -1,22 +1,73 @@
1
+ import { type CliErrorCode, type CliErrorKind } from '../../core/errors.js';
1
2
  /**
2
3
  * 并发写冲突退出码(与 cli/index.ts EXIT_CONCURRENT 同值)。
3
4
  * 此处独立定义以避免命令层 → cli 的循环依赖。
4
5
  */
5
6
  export declare const EXIT_CONCURRENT = 2;
7
+ /** 新错误 envelope(stdout 单文档;`detail` 无值恒为 `null`) */
8
+ export interface ErrorEnvelope {
9
+ schemaVersion: 1;
10
+ error: {
11
+ code: CliErrorCode;
12
+ kind: CliErrorKind;
13
+ message: string;
14
+ detail: unknown;
15
+ };
16
+ }
17
+ /** 错误出口入参 */
18
+ export interface FailCliInput {
19
+ /** 稳定错误码(kind / exitCode 由码表推导) */
20
+ code: CliErrorCode;
21
+ /** 本地化主文案(JSON envelope.message / 非 JSON 缺省 stderr 行) */
22
+ message: string;
23
+ /** 可定位字段;缺省 null */
24
+ detail?: unknown;
25
+ /** 非 JSON 模式逐行 stderr(缺省 [message]);用于逐字保持既有文案 */
26
+ stderrLines?: string[];
27
+ }
28
+ /** 仅向 stdout 输出 envelope(不退出、不改退出码) */
29
+ export declare function emitErrorEnvelope(input: FailCliInput): void;
6
30
  /**
7
- * 并发写冲突统一处理:输出唯一 i18n 文案并退出码 2(不返回)。
31
+ * 统一错误出口:JSON 模式输出 envelope;非 JSON 模式逐行 stderr。
32
+ * 输出在退出之前完成(避免 Windows 管道下 stdout 被截断)。
33
+ * JSON 模式仅置 `process.exitCode` 后返回,由调用方 `return`(REV-95-007.1);
34
+ * 非 JSON 模式保持既有即时退出语义(0/1/2 语义零改动)。
35
+ * @param input 错误出口入参
36
+ */
37
+ export declare function failCli(input: FailCliInput): void;
38
+ /**
39
+ * 预期拒绝出口:断言码表 kind 为 refusal 后委托 failCli。
40
+ * internal 码误入本出口属编程错误,按内部错误处理(不静默降级)。
41
+ * @param input 错误出口入参
42
+ */
43
+ export declare function failRefusal(input: FailCliInput): void;
44
+ /**
45
+ * 内部错误出口(INTERNAL_ERROR / exit 3)。
46
+ * @param err 原始异常(detail 缺省取 {name,message[,stack]})
47
+ * @param options 可覆盖主文案 / stderr 行 / detail
48
+ */
49
+ export declare function failInternal(err: unknown, options?: {
50
+ message?: string;
51
+ stderrLines?: string[];
52
+ detail?: unknown;
53
+ }): void;
54
+ /**
55
+ * 并发写冲突统一处理:输出唯一 i18n 文案并置退出码 2。
56
+ * JSON 模式输出 FLOW_CONCURRENT_CONFLICT envelope(kind=refusal)后置码返回(由调用方 return);
57
+ * 非 JSON 分支逐字不变(console.error + 即时 process.exit(2))。
8
58
  * @param err 并发写冲突错误(含 expectedRevision / actualRevision)
9
59
  * @param lang 语言标识
10
60
  */
11
61
  export declare function handleConcurrentConflict(err: {
12
62
  expectedRevision: number;
13
63
  actualRevision: number;
14
- }, lang: string): never;
64
+ }, lang: string): void;
15
65
  /**
16
66
  * addStage 失败统一处理(T42):并发写冲突 / 阶段目录冲突 / 其他错误三类分流。
17
- * `stage create` 与 `flow stage add` 共用,保证两入口输出一致(不返回)。
67
+ * `stage create` 与 `flow stage add` 共用,保证两入口输出一致。
68
+ * JSON 并发分支置码返回(调用方须立即 return);其余分支保持即时退出。
18
69
  * @param err 捕获到的错误
19
70
  * @param lang 语言标识
20
71
  */
21
- export declare function handleAddStageError(err: unknown, lang: string): never;
72
+ export declare function handleAddStageError(err: unknown, lang: string): void;
22
73
  //# sourceMappingURL=errors.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../../src/commands/shared/errors.ts"],"names":[],"mappings":"AAOA;;;GAGG;AACH,eAAO,MAAM,eAAe,IAAI,CAAC;AAEjC;;;;GAIG;AACH,wBAAgB,wBAAwB,CACtC,GAAG,EAAE;IAAE,gBAAgB,EAAE,MAAM,CAAC;IAAC,cAAc,EAAE,MAAM,CAAA;CAAE,EACzD,IAAI,EAAE,MAAM,GACX,KAAK,CAMP;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,GAAG,KAAK,CAcrE"}
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../../src/commands/shared/errors.ts"],"names":[],"mappings":"AASA,OAAO,EAAmB,KAAK,YAAY,EAAE,KAAK,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAG7F;;;GAGG;AACH,eAAO,MAAM,eAAe,IAAI,CAAC;AAEjC,oDAAoD;AACpD,MAAM,WAAW,aAAa;IAC5B,aAAa,EAAE,CAAC,CAAC;IACjB,KAAK,EAAE;QACL,IAAI,EAAE,YAAY,CAAC;QACnB,IAAI,EAAE,YAAY,CAAC;QACnB,OAAO,EAAE,MAAM,CAAC;QAChB,MAAM,EAAE,OAAO,CAAC;KACjB,CAAC;CACH;AAED,aAAa;AACb,MAAM,WAAW,YAAY;IAC3B,mCAAmC;IACnC,IAAI,EAAE,YAAY,CAAC;IACnB,yDAAyD;IACzD,OAAO,EAAE,MAAM,CAAC;IAChB,oBAAoB;IACpB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,kDAAkD;IAClD,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;CACxB;AAED,uCAAuC;AACvC,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,YAAY,GAAG,IAAI,CAa3D;AAED;;;;;;GAMG;AACH,wBAAgB,OAAO,CAAC,KAAK,EAAE,YAAY,GAAG,IAAI,CAajD;AAED;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,YAAY,GAAG,IAAI,CAWrD;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAC1B,GAAG,EAAE,OAAO,EACZ,OAAO,CAAC,EAAE;IAAE,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IAAC,MAAM,CAAC,EAAE,OAAO,CAAA;CAAE,GACvE,IAAI,CAeN;AAED;;;;;;GAMG;AACH,wBAAgB,wBAAwB,CACtC,GAAG,EAAE;IAAE,gBAAgB,EAAE,MAAM,CAAC;IAAC,cAAc,EAAE,MAAM,CAAA;CAAE,EACzD,IAAI,EAAE,MAAM,GACX,IAAI,CAqBN;AAED;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAgBpE"}
@@ -1,29 +1,125 @@
1
1
  /**
2
- * 命令层共享错误处理(stage-50 op-004)
3
- * 收敛「并发写冲突」与「addStage 失败」两类逐行复制逻辑到单点(T38 / T42)。
2
+ * 命令层共享错误处理(stage-50 op-004;stage-95 op-002 扩展错误封装)
3
+ *
4
+ * 收敛「并发写冲突」与「addStage 失败」两类逐行复制逻辑到单点(T38 / T42);
5
+ * 新增 JSON 模式统一错误出口(envelope / failCli / failRefusal / failInternal),
6
+ * kind 与 exitCode 一律经 `src/core/errors.ts` 的单一映射表读取。
4
7
  */
5
8
  import { isFlowConcurrentError, StageDirConflictError } from '../../core/flow-manager.js';
6
- import { t } from '../../core/i18n.js';
9
+ import { getCliLang, t } from '../../core/i18n.js';
10
+ import { getCliErrorSpec } from '../../core/errors.js';
11
+ import { emitJson, isJsonMode } from './json-output.js';
7
12
  /**
8
13
  * 并发写冲突退出码(与 cli/index.ts EXIT_CONCURRENT 同值)。
9
14
  * 此处独立定义以避免命令层 → cli 的循环依赖。
10
15
  */
11
16
  export const EXIT_CONCURRENT = 2;
17
+ /** 仅向 stdout 输出 envelope(不退出、不改退出码) */
18
+ export function emitErrorEnvelope(input) {
19
+ const spec = getCliErrorSpec(input.code);
20
+ const doc = {
21
+ // 构造序保证 schemaVersion 为运行时首键(契约 §1.2)
22
+ schemaVersion: 1,
23
+ error: {
24
+ code: spec.code,
25
+ kind: spec.kind,
26
+ message: input.message,
27
+ detail: input.detail ?? null,
28
+ },
29
+ };
30
+ emitJson(doc);
31
+ }
32
+ /**
33
+ * 统一错误出口:JSON 模式输出 envelope;非 JSON 模式逐行 stderr。
34
+ * 输出在退出之前完成(避免 Windows 管道下 stdout 被截断)。
35
+ * JSON 模式仅置 `process.exitCode` 后返回,由调用方 `return`(REV-95-007.1);
36
+ * 非 JSON 模式保持既有即时退出语义(0/1/2 语义零改动)。
37
+ * @param input 错误出口入参
38
+ */
39
+ export function failCli(input) {
40
+ const spec = getCliErrorSpec(input.code);
41
+ if (isJsonMode()) {
42
+ emitErrorEnvelope(input);
43
+ process.exitCode = spec.exitCode;
44
+ return;
45
+ }
46
+ for (const line of input.stderrLines ?? [input.message]) {
47
+ console.error(line);
48
+ }
49
+ // 先置码后退出:兼容既有 `process.exitCode` 断言
50
+ process.exitCode = spec.exitCode;
51
+ process.exit(spec.exitCode);
52
+ }
53
+ /**
54
+ * 预期拒绝出口:断言码表 kind 为 refusal 后委托 failCli。
55
+ * internal 码误入本出口属编程错误,按内部错误处理(不静默降级)。
56
+ * @param input 错误出口入参
57
+ */
58
+ export function failRefusal(input) {
59
+ const spec = getCliErrorSpec(input.code);
60
+ if (spec.kind !== 'refusal') {
61
+ failInternal(new Error(`failRefusal 收到非 refusal 错误码:${input.code}`), {
62
+ message: input.message,
63
+ stderrLines: input.stderrLines,
64
+ detail: input.detail,
65
+ });
66
+ return;
67
+ }
68
+ failCli(input);
69
+ }
70
+ /**
71
+ * 内部错误出口(INTERNAL_ERROR / exit 3)。
72
+ * @param err 原始异常(detail 缺省取 {name,message[,stack]})
73
+ * @param options 可覆盖主文案 / stderr 行 / detail
74
+ */
75
+ export function failInternal(err, options) {
76
+ const lang = getCliLang(process.cwd());
77
+ const msg = err instanceof Error ? err.message : String(err);
78
+ const defaultMessage = t('common.errorTmpl', lang, { msg });
79
+ const detail = options?.detail ?? (err instanceof Error
80
+ ? { name: err.name, message: err.message, stack: err.stack }
81
+ : { name: 'Error', message: String(err) });
82
+ failCli({
83
+ code: 'INTERNAL_ERROR',
84
+ message: options?.message ?? defaultMessage,
85
+ detail,
86
+ stderrLines: options?.stderrLines ?? [defaultMessage],
87
+ });
88
+ }
12
89
  /**
13
- * 并发写冲突统一处理:输出唯一 i18n 文案并退出码 2(不返回)。
90
+ * 并发写冲突统一处理:输出唯一 i18n 文案并置退出码 2。
91
+ * JSON 模式输出 FLOW_CONCURRENT_CONFLICT envelope(kind=refusal)后置码返回(由调用方 return);
92
+ * 非 JSON 分支逐字不变(console.error + 即时 process.exit(2))。
14
93
  * @param err 并发写冲突错误(含 expectedRevision / actualRevision)
15
94
  * @param lang 语言标识
16
95
  */
17
96
  export function handleConcurrentConflict(err, lang) {
18
- console.error(t('common.concurrentConflict', lang, {
19
- expected: String(err.expectedRevision),
20
- actual: String(err.actualRevision),
21
- }));
22
- process.exit(EXIT_CONCURRENT);
97
+ if (isJsonMode()) {
98
+ emitErrorEnvelope({
99
+ code: 'FLOW_CONCURRENT_CONFLICT',
100
+ message: t('common.concurrentConflict', lang, {
101
+ expected: String(err.expectedRevision),
102
+ actual: String(err.actualRevision),
103
+ }),
104
+ detail: { expectedRevision: err.expectedRevision, actualRevision: err.actualRevision },
105
+ });
106
+ process.exitCode = EXIT_CONCURRENT;
107
+ // JSON 模式仅置码返回(REV-95-009):不调用 process.exit,避免 Windows 管道 stdout 截断;
108
+ // 调用方必须立即 return,禁止落入通用错误分支(二次输出 / exit 1)
109
+ return;
110
+ }
111
+ else {
112
+ console.error(t('common.concurrentConflict', lang, {
113
+ expected: String(err.expectedRevision),
114
+ actual: String(err.actualRevision),
115
+ }));
116
+ process.exit(EXIT_CONCURRENT);
117
+ }
23
118
  }
24
119
  /**
25
120
  * addStage 失败统一处理(T42):并发写冲突 / 阶段目录冲突 / 其他错误三类分流。
26
- * `stage create` 与 `flow stage add` 共用,保证两入口输出一致(不返回)。
121
+ * `stage create` 与 `flow stage add` 共用,保证两入口输出一致。
122
+ * JSON 并发分支置码返回(调用方须立即 return);其余分支保持即时退出。
27
123
  * @param err 捕获到的错误
28
124
  * @param lang 语言标识
29
125
  */
@@ -31,6 +127,8 @@ export function handleAddStageError(err, lang) {
31
127
  // 并发写冲突:本次未写入 flow.json,输出可重试提示并退出码 2
32
128
  if (isFlowConcurrentError(err)) {
33
129
  handleConcurrentConflict(err, lang);
130
+ // JSON 模式仅置码返回 → 显式终止分流,避免落入下方通用错误分支(exit 1 二次输出)
131
+ return;
34
132
  }
35
133
  // 阶段目录冲突:按类型分流走 i18n 模板(cli/BUG-002 死键消除)
36
134
  if (err instanceof StageDirConflictError) {
@@ -1 +1 @@
1
- {"version":3,"file":"errors.js","sourceRoot":"","sources":["../../../src/commands/shared/errors.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAE,qBAAqB,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAC;AAC1F,OAAO,EAAE,CAAC,EAAE,MAAM,oBAAoB,CAAC;AAEvC;;;GAGG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,CAAC;AAEjC;;;;GAIG;AACH,MAAM,UAAU,wBAAwB,CACtC,GAAyD,EACzD,IAAY;IAEZ,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,2BAA2B,EAAE,IAAI,EAAE;QACjD,QAAQ,EAAE,MAAM,CAAC,GAAG,CAAC,gBAAgB,CAAC;QACtC,MAAM,EAAE,MAAM,CAAC,GAAG,CAAC,cAAc,CAAC;KACnC,CAAC,CAAC,CAAC;IACJ,OAAO,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;AAChC,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,mBAAmB,CAAC,GAAY,EAAE,IAAY;IAC5D,sCAAsC;IACtC,IAAI,qBAAqB,CAAC,GAAG,CAAC,EAAE,CAAC;QAC/B,wBAAwB,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;IACtC,CAAC;IACD,0CAA0C;IAC1C,IAAI,GAAG,YAAY,qBAAqB,EAAE,CAAC;QACzC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,6BAA6B,EAAE,IAAI,EAAE,EAAE,KAAK,EAAE,GAAG,CAAC,KAAK,EAAE,KAAK,EAAE,GAAG,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;QAC9F,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IACD,cAAc;IACd,MAAM,GAAG,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IAC7D,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,kBAAkB,EAAE,IAAI,EAAE,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC;IACpD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC"}
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../../../src/commands/shared/errors.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,60 @@
1
+ /**
2
+ * JSON 输出契约助手(v1.2.2-stage-95)
3
+ *
4
+ * 职责:
5
+ * - 单文档 JSON 契约的构造与输出(`schemaVersion` 恒为首键、值恒为 1);
6
+ * - 进程级 JSON 模式单点(由 runCli 预扫描后置位,命令层只读);
7
+ * - argv 单点扫描(`--json` / `--version|-v` / `--project`,跳过已知取值选项防误判)。
8
+ *
9
+ * 边界:本模块不承担错误封装(failCli / envelope 归错误层);不改变任何人类输出。
10
+ */
11
+ /** JSON 契约版本号(恒为 1;与单文档首键同值) */
12
+ export declare const SCHEMA_VERSION = 1;
13
+ /**
14
+ * 构造以 `schemaVersion` 为运行时首键的单文档。
15
+ * 运行时键序由对象字面量构造序决定,因此必须写成 `{ schemaVersion, ...doc }`;
16
+ * 禁止 `{ ...doc, schemaVersion }`(类型通过但首键违约,REV-95-004 / D-95-01)。
17
+ * @param doc 业务文档内容(字面量序保持)
18
+ * @returns 首键为 schemaVersion、值为 1 的新对象
19
+ */
20
+ export declare function withSchemaVersion<T extends object>(doc: T): {
21
+ schemaVersion: 1;
22
+ } & T;
23
+ /** 输出单个 JSON 文档(2 空格缩进,stdout) */
24
+ export declare function emitJson(doc: object): void;
25
+ /** 设置进程级 JSON 模式(runCli 预扫描后置位) */
26
+ export declare function setJsonMode(value: boolean): void;
27
+ /** 读取进程级 JSON 模式(命令层只读) */
28
+ export declare function isJsonMode(): boolean;
29
+ /** 重置 JSON 模式(仅测试隔离用,非生产路径) */
30
+ export declare function resetJsonModeForTest(): void;
31
+ /**
32
+ * 已知「取值选项」名单:argv 扫描时跳过其下一个 token。
33
+ * 目的:避免把取值 token(如 `--title --json` 中的 `--json`)误判为开关。
34
+ * 覆盖实测全部取值选项(含 `--lines` / `-n`)。
35
+ */
36
+ export declare const VALUE_OPTIONS: ReadonlySet<string>;
37
+ /** argv 单点扫描结果 */
38
+ export interface ArgvScanResult {
39
+ /** 是否存在 `--json` 开关(`--json=true` 不支持,Commander 原生拒绝) */
40
+ json: boolean;
41
+ /** 是否存在 `--version` / `-v` 开关 */
42
+ version: boolean;
43
+ /** `--project <v>` / `--project=<v>` 收集到的值(原始 token;路径解析归 project-option) */
44
+ projectValues: string[];
45
+ /** `--project` 缺值(下一 token 以 `-` 开头或已到末尾) */
46
+ projectMissingValue: boolean;
47
+ }
48
+ /**
49
+ * argv 单点扫描。
50
+ * 规则:遇 `--` 停止扫描;`--json` / `--version` / `-v` 置位;
51
+ * `--project` 收集值(缺值登记);其余 `VALUE_OPTIONS` 成员跳过下一 token;
52
+ * 未知 `--x=v` 不吞下一 token。
53
+ * @param argv 命令行参数(不含 node 与脚本路径)
54
+ */
55
+ export declare function scanArgv(argv: string[]): ArgvScanResult;
56
+ /** 解析是否处于 `--json` 模式(argv 单点扫描) */
57
+ export declare function resolveJsonMode(argv: string[]): boolean;
58
+ /** 解析是否存在 `--version` / `-v` 开关(argv 单点扫描) */
59
+ export declare function resolveVersionFlag(argv: string[]): boolean;
60
+ //# sourceMappingURL=json-output.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"json-output.d.ts","sourceRoot":"","sources":["../../../src/commands/shared/json-output.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,gCAAgC;AAChC,eAAO,MAAM,cAAc,IAAI,CAAC;AAEhC;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,CAAC,SAAS,MAAM,EAAE,GAAG,EAAE,CAAC,GAAG;IAAE,aAAa,EAAE,CAAC,CAAA;CAAE,GAAG,CAAC,CAEpF;AAED,kCAAkC;AAClC,wBAAgB,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAE1C;AAOD,mCAAmC;AACnC,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI,CAEhD;AAED,2BAA2B;AAC3B,wBAAgB,UAAU,IAAI,OAAO,CAEpC;AAED,+BAA+B;AAC/B,wBAAgB,oBAAoB,IAAI,IAAI,CAE3C;AAED;;;;GAIG;AACH,eAAO,MAAM,aAAa,EAAE,WAAW,CAAC,MAAM,CAwC5C,CAAC;AAEH,kBAAkB;AAClB,MAAM,WAAW,cAAc;IAC7B,yDAAyD;IACzD,IAAI,EAAE,OAAO,CAAC;IACd,iCAAiC;IACjC,OAAO,EAAE,OAAO,CAAC;IACjB,6EAA6E;IAC7E,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,6CAA6C;IAC7C,mBAAmB,EAAE,OAAO,CAAC;CAC9B;AAED;;;;;;GAMG;AACH,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,cAAc,CAiDvD;AAED,oCAAoC;AACpC,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAEvD;AAED,8CAA8C;AAC9C,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAE1D"}
@@ -0,0 +1,152 @@
1
+ /**
2
+ * JSON 输出契约助手(v1.2.2-stage-95)
3
+ *
4
+ * 职责:
5
+ * - 单文档 JSON 契约的构造与输出(`schemaVersion` 恒为首键、值恒为 1);
6
+ * - 进程级 JSON 模式单点(由 runCli 预扫描后置位,命令层只读);
7
+ * - argv 单点扫描(`--json` / `--version|-v` / `--project`,跳过已知取值选项防误判)。
8
+ *
9
+ * 边界:本模块不承担错误封装(failCli / envelope 归错误层);不改变任何人类输出。
10
+ */
11
+ /** JSON 契约版本号(恒为 1;与单文档首键同值) */
12
+ export const SCHEMA_VERSION = 1;
13
+ /**
14
+ * 构造以 `schemaVersion` 为运行时首键的单文档。
15
+ * 运行时键序由对象字面量构造序决定,因此必须写成 `{ schemaVersion, ...doc }`;
16
+ * 禁止 `{ ...doc, schemaVersion }`(类型通过但首键违约,REV-95-004 / D-95-01)。
17
+ * @param doc 业务文档内容(字面量序保持)
18
+ * @returns 首键为 schemaVersion、值为 1 的新对象
19
+ */
20
+ export function withSchemaVersion(doc) {
21
+ return { schemaVersion: SCHEMA_VERSION, ...doc };
22
+ }
23
+ /** 输出单个 JSON 文档(2 空格缩进,stdout) */
24
+ export function emitJson(doc) {
25
+ console.log(JSON.stringify(doc, null, 2));
26
+ }
27
+ // ── 进程级 JSON 模式单点 ──
28
+ // runCli 在预扫描后置位;命令层只读。模块级状态保证「单进程单命令」前提下的单点判定。
29
+ let jsonMode = false;
30
+ /** 设置进程级 JSON 模式(runCli 预扫描后置位) */
31
+ export function setJsonMode(value) {
32
+ jsonMode = value;
33
+ }
34
+ /** 读取进程级 JSON 模式(命令层只读) */
35
+ export function isJsonMode() {
36
+ return jsonMode;
37
+ }
38
+ /** 重置 JSON 模式(仅测试隔离用,非生产路径) */
39
+ export function resetJsonModeForTest() {
40
+ jsonMode = false;
41
+ }
42
+ /**
43
+ * 已知「取值选项」名单:argv 扫描时跳过其下一个 token。
44
+ * 目的:避免把取值 token(如 `--title --json` 中的 `--json`)误判为开关。
45
+ * 覆盖实测全部取值选项(含 `--lines` / `-n`)。
46
+ */
47
+ export const VALUE_OPTIONS = new Set([
48
+ '--encoding',
49
+ '--log-file',
50
+ '--project',
51
+ '--title',
52
+ '--content',
53
+ '--last',
54
+ '--offset',
55
+ '--add',
56
+ '--auto-advance',
57
+ '--auto-fix',
58
+ '--blocking',
59
+ '--category',
60
+ '--change',
61
+ '--deps',
62
+ '--exec-mode',
63
+ '--into',
64
+ '--lang',
65
+ '--limit',
66
+ '--mode',
67
+ '--op',
68
+ '--owner',
69
+ '--priority',
70
+ '--requirement',
71
+ '--result',
72
+ '--review-agent',
73
+ '--review-tier',
74
+ '--schema',
75
+ '--scope',
76
+ '--stage',
77
+ '--status',
78
+ '--target-version',
79
+ '--tasks',
80
+ '--threshold',
81
+ '--to',
82
+ '--tools',
83
+ '--type',
84
+ '--workflow-mode',
85
+ '--lines',
86
+ '-n',
87
+ ]);
88
+ /**
89
+ * argv 单点扫描。
90
+ * 规则:遇 `--` 停止扫描;`--json` / `--version` / `-v` 置位;
91
+ * `--project` 收集值(缺值登记);其余 `VALUE_OPTIONS` 成员跳过下一 token;
92
+ * 未知 `--x=v` 不吞下一 token。
93
+ * @param argv 命令行参数(不含 node 与脚本路径)
94
+ */
95
+ export function scanArgv(argv) {
96
+ let json = false;
97
+ let version = false;
98
+ let projectMissingValue = false;
99
+ const projectValues = [];
100
+ for (let i = 0; i < argv.length; i += 1) {
101
+ const token = argv[i];
102
+ // `--` 之后为位置参数,不再识别选项
103
+ if (token === '--') {
104
+ break;
105
+ }
106
+ if (token === '--json') {
107
+ json = true;
108
+ continue;
109
+ }
110
+ if (token === '--version' || token === '-v') {
111
+ version = true;
112
+ continue;
113
+ }
114
+ if (token === '--project') {
115
+ const next = argv[i + 1];
116
+ // 缺值(末尾或下一 token 形如选项)→ 登记,且不吞下一 token
117
+ if (next === undefined || next.startsWith('-')) {
118
+ projectMissingValue = true;
119
+ continue;
120
+ }
121
+ projectValues.push(next);
122
+ i += 1;
123
+ continue;
124
+ }
125
+ if (token.startsWith('--project=')) {
126
+ const value = token.slice('--project='.length);
127
+ if (value === '') {
128
+ projectMissingValue = true;
129
+ }
130
+ else {
131
+ projectValues.push(value);
132
+ }
133
+ continue;
134
+ }
135
+ // 已知取值选项:跳过其下一个 token(防 `--title --json` 误判)
136
+ if (VALUE_OPTIONS.has(token)) {
137
+ if (i + 1 < argv.length) {
138
+ i += 1;
139
+ }
140
+ }
141
+ }
142
+ return { json, version, projectValues, projectMissingValue };
143
+ }
144
+ /** 解析是否处于 `--json` 模式(argv 单点扫描) */
145
+ export function resolveJsonMode(argv) {
146
+ return scanArgv(argv).json;
147
+ }
148
+ /** 解析是否存在 `--version` / `-v` 开关(argv 单点扫描) */
149
+ export function resolveVersionFlag(argv) {
150
+ return scanArgv(argv).version;
151
+ }
152
+ //# sourceMappingURL=json-output.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"json-output.js","sourceRoot":"","sources":["../../../src/commands/shared/json-output.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"stage.d.ts","sourceRoot":"","sources":["../../src/commands/stage.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAyTpC;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAwR3D"}
1
+ {"version":3,"file":"stage.d.ts","sourceRoot":"","sources":["../../src/commands/stage.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AA6VpC;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CA8T3D"}
@@ -5,10 +5,30 @@ import { withFileLock, projectLockPath } from '../core/fs/file-lock.js';
5
5
  import fastGlob from 'fast-glob';
6
6
  import { t, getCliLang } from '../core/i18n.js';
7
7
  import { FlowManager, STAGE_STATUS_VALUES } from '../core/flow-manager.js';
8
- import { handleAddStageError } from './shared/errors.js';
8
+ import { failRefusal, handleAddStageError } from './shared/errors.js';
9
+ import { withSchemaVersion, emitJson } from './shared/json-output.js';
9
10
  import { findStageStatusPath, planDirToStageId, parseStageId, validateStageId, suggestStageId, normalizeStageId } from '../core/plan/path.js';
10
11
  import { appendStatusTask } from '../core/plan/stage.js';
11
12
  import { getConfigFieldLegalValues } from '../core/config.js';
13
+ /** 将 status.md 原始中文字段映射为规范化键(缺失 → null) */
14
+ function buildCanonicalFields(raw) {
15
+ return {
16
+ execMode: raw['执行模式'] ?? null,
17
+ autoAdvance: raw['自动推进'] ?? null,
18
+ status: raw['状态'] ?? null,
19
+ reviewAgent: raw['当前责任 Agent'] ?? null,
20
+ previousReviewAgent: raw['上一责任 Agent'] ?? null,
21
+ updatedAt: raw['更新时间'] ?? null,
22
+ workflowMode: raw['工作模式'] ?? null,
23
+ raw,
24
+ };
25
+ }
26
+ /** 提取「## 阻塞 / 暂停原因」正文;无内容或「无」→ null */
27
+ function extractBlockedReason(content) {
28
+ const m = content.match(/^## 阻塞 \/ 暂停原因\n\n(.+?)(?:\n##|\n*$)/ms);
29
+ const text = m?.[1]?.trim() ?? '';
30
+ return text === '' || text === '无' ? null : text;
31
+ }
12
32
  /**
13
33
  * 根据 stageId 解析 status.md 文件路径
14
34
  * 三级回退:plan/{series}/ 精确 → plan 递归 → stages 兜底(委托 path.ts)
@@ -74,10 +94,12 @@ function parseTasks(content) {
74
94
  const taskRegex = /^(- \[([ x])\] 任务(\d+)[::].*)$/gm;
75
95
  let match;
76
96
  while ((match = taskRegex.exec(content)) !== null) {
97
+ const descMatch = match[1].match(/任务\d+[::]\s*(.*)/);
77
98
  tasks.push({
78
99
  number: parseInt(match[3], 10),
79
100
  done: match[2] === 'x',
80
101
  line: match[1],
102
+ description: descMatch ? descMatch[1] : match[1],
81
103
  });
82
104
  }
83
105
  return tasks;
@@ -157,10 +179,8 @@ function showStageStatus(statusPath, stageId) {
157
179
  console.log(t('stage.task.taskListTmpl', lang, { done: String(doneCount), total: String(tasks.length) }));
158
180
  for (const task of tasks) {
159
181
  const icon = task.done ? '✅' : '⬜';
160
- // 提取任务描述(去掉 checkbox 和"任务{N}:"前缀)
161
- const descMatch = task.line.match(/任务\d+[::]\s*(.*)/);
162
- const desc = descMatch ? descMatch[1] : task.line;
163
- console.log(` ${icon} ` + t('stage.task.taskItemTmpl', lang, { number: String(task.number), desc }));
182
+ // 任务描述已在 parseTasks 内同源提取(人类输出逐字不变)
183
+ console.log(` ${icon} ` + t('stage.task.taskItemTmpl', lang, { number: String(task.number), desc: task.description }));
164
184
  }
165
185
  }
166
186
  // 输出阻塞原因
@@ -249,12 +269,25 @@ export function registerStageCommand(program) {
249
269
  .command('status')
250
270
  .description('查看阶段状态(无参数时列出所有阶段)')
251
271
  .argument('[stageId]', '阶段 ID(如 v4-stage-04)')
252
- .action((stageId) => {
272
+ .option('--json', t('help.stage.status.json', getCliLang(process.cwd())))
273
+ .action((stageId, options) => {
253
274
  const projectPath = process.cwd();
254
275
  const lang = getCliLang(projectPath);
255
276
  if (!stageId) {
256
277
  // 无参数:列出所有阶段
257
278
  const stages = listAllStages(projectPath);
279
+ // JSON 分支须为首行纯 JSON 单文档(statusPath 统一绝对路径)
280
+ if (options.json) {
281
+ emitJson(withSchemaVersion({
282
+ stages: stages.map((s) => ({
283
+ stageId: s.stageId,
284
+ status: s.status,
285
+ statusPath: resolve(projectPath, s.statusPath),
286
+ })),
287
+ count: stages.length,
288
+ }));
289
+ return;
290
+ }
258
291
  if (stages.length === 0) {
259
292
  console.log(t('stage.status.noStages', lang));
260
293
  return;
@@ -276,10 +309,33 @@ export function registerStageCommand(program) {
276
309
  // 有参数:显示指定阶段详细状态
277
310
  const statusPath = resolveStatusPath(projectPath, stageId);
278
311
  if (!statusPath) {
312
+ // JSON 模式:预期拒绝 envelope(失败 envelope 判定经 isJsonMode() 单点)
313
+ if (options.json) {
314
+ failRefusal({
315
+ code: 'STAGE_NOT_FOUND',
316
+ message: t('stage.errorStageNotFoundTmpl', lang, { stageId }),
317
+ detail: { stageId, hint: t('stage.errorCheckStageId', lang) },
318
+ });
319
+ return;
320
+ }
279
321
  console.error(t('stage.errorStageNotFoundTmpl', lang, { stageId }));
280
322
  console.error(t('stage.errorCheckStageId', lang));
281
323
  process.exit(1);
282
324
  }
325
+ // JSON 分支:单文档输出(fields 7 规范键 + raw;tasks 精简三元组)
326
+ if (options.json) {
327
+ const content = readFileSync(statusPath, 'utf-8');
328
+ const fields = parseStatusFields(content);
329
+ const tasks = parseTasks(content);
330
+ emitJson(withSchemaVersion({
331
+ stageId,
332
+ statusPath,
333
+ fields: buildCanonicalFields(fields),
334
+ tasks: tasks.map(({ number, done, description }) => ({ number, done, description })),
335
+ blockedBy: extractBlockedReason(content),
336
+ }));
337
+ return;
338
+ }
283
339
  showStageStatus(statusPath, stageId);
284
340
  });
285
341
  // ═══ stage set <stageId> [--status|--exec-mode|--auto-advance|--review-agent] ═══