openfeel 1.1.6 → 1.2.0

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 (97) hide show
  1. package/README.en.md +25 -6
  2. package/README.md +17 -2
  3. package/README.zh-CN.md +25 -6
  4. package/dist/cli/index.d.ts.map +1 -1
  5. package/dist/cli/index.js +2 -0
  6. package/dist/cli/index.js.map +1 -1
  7. package/dist/commands/config.d.ts.map +1 -1
  8. package/dist/commands/config.js +85 -4
  9. package/dist/commands/config.js.map +1 -1
  10. package/dist/commands/flow.d.ts +8 -0
  11. package/dist/commands/flow.d.ts.map +1 -1
  12. package/dist/commands/flow.js +447 -15
  13. package/dist/commands/flow.js.map +1 -1
  14. package/dist/commands/plan.d.ts.map +1 -1
  15. package/dist/commands/plan.js +71 -7
  16. package/dist/commands/plan.js.map +1 -1
  17. package/dist/commands/req.d.ts +14 -0
  18. package/dist/commands/req.d.ts.map +1 -0
  19. package/dist/commands/req.js +562 -0
  20. package/dist/commands/req.js.map +1 -0
  21. package/dist/commands/stage.d.ts.map +1 -1
  22. package/dist/commands/stage.js +56 -2
  23. package/dist/commands/stage.js.map +1 -1
  24. package/dist/core/config.d.ts +17 -2
  25. package/dist/core/config.d.ts.map +1 -1
  26. package/dist/core/config.js +21 -6
  27. package/dist/core/config.js.map +1 -1
  28. package/dist/core/flow-archive/archive-file.d.ts +35 -0
  29. package/dist/core/flow-archive/archive-file.d.ts.map +1 -0
  30. package/dist/core/flow-archive/archive-file.js +3 -0
  31. package/dist/core/flow-archive/archive-file.js.map +1 -0
  32. package/dist/core/flow-archive/archive-health.d.ts +34 -0
  33. package/dist/core/flow-archive/archive-health.d.ts.map +1 -0
  34. package/dist/core/flow-archive/archive-health.js +76 -0
  35. package/dist/core/flow-archive/archive-health.js.map +1 -0
  36. package/dist/core/flow-archive/archive-ops.d.ts +68 -0
  37. package/dist/core/flow-archive/archive-ops.d.ts.map +1 -0
  38. package/dist/core/flow-archive/archive-ops.js +184 -0
  39. package/dist/core/flow-archive/archive-ops.js.map +1 -0
  40. package/dist/core/flow-archive/grouping.d.ts +58 -0
  41. package/dist/core/flow-archive/grouping.d.ts.map +1 -0
  42. package/dist/core/flow-archive/grouping.js +153 -0
  43. package/dist/core/flow-archive/grouping.js.map +1 -0
  44. package/dist/core/flow-manager.d.ts +78 -14
  45. package/dist/core/flow-manager.d.ts.map +1 -1
  46. package/dist/core/flow-manager.js +311 -55
  47. package/dist/core/flow-manager.js.map +1 -1
  48. package/dist/core/i18n-data/en.d.ts +1 -0
  49. package/dist/core/i18n-data/en.d.ts.map +1 -1
  50. package/dist/core/i18n-data/en.js +159 -3
  51. package/dist/core/i18n-data/en.js.map +1 -1
  52. package/dist/core/i18n-data/zh-CN.d.ts +1 -0
  53. package/dist/core/i18n-data/zh-CN.d.ts.map +1 -1
  54. package/dist/core/i18n-data/zh-CN.js +161 -3
  55. package/dist/core/i18n-data/zh-CN.js.map +1 -1
  56. package/dist/core/i18n.js +4 -4
  57. package/dist/core/i18n.js.map +1 -1
  58. package/dist/core/pipeline-schema.d.ts +5 -0
  59. package/dist/core/pipeline-schema.d.ts.map +1 -1
  60. package/dist/core/pipeline-schema.js +5 -0
  61. package/dist/core/pipeline-schema.js.map +1 -1
  62. package/dist/core/plan/path.d.ts +17 -0
  63. package/dist/core/plan/path.d.ts.map +1 -1
  64. package/dist/core/plan/path.js +31 -0
  65. package/dist/core/plan/path.js.map +1 -1
  66. package/dist/core/plan/scheme.d.ts +22 -0
  67. package/dist/core/plan/scheme.d.ts.map +1 -1
  68. package/dist/core/plan/scheme.js +71 -2
  69. package/dist/core/plan/scheme.js.map +1 -1
  70. package/dist/core/plan/stage.d.ts +2 -0
  71. package/dist/core/plan/stage.d.ts.map +1 -1
  72. package/dist/core/plan/stage.js +8 -0
  73. package/dist/core/plan/stage.js.map +1 -1
  74. package/dist/core/req/aggregate.d.ts +61 -0
  75. package/dist/core/req/aggregate.d.ts.map +1 -0
  76. package/dist/core/req/aggregate.js +134 -0
  77. package/dist/core/req/aggregate.js.map +1 -0
  78. package/dist/core/req/body-file.d.ts +16 -0
  79. package/dist/core/req/body-file.d.ts.map +1 -0
  80. package/dist/core/req/body-file.js +80 -0
  81. package/dist/core/req/body-file.js.map +1 -0
  82. package/dist/core/req/requirement-ops.d.ts +74 -0
  83. package/dist/core/req/requirement-ops.d.ts.map +1 -0
  84. package/dist/core/req/requirement-ops.js +290 -0
  85. package/dist/core/req/requirement-ops.js.map +1 -0
  86. package/dist/core/req/types.d.ts +40 -0
  87. package/dist/core/req/types.d.ts.map +1 -0
  88. package/dist/core/req/types.js +13 -0
  89. package/dist/core/req/types.js.map +1 -0
  90. package/dist/core/setup.js +4 -4
  91. package/dist/core/template-loader.d.ts.map +1 -1
  92. package/dist/core/template-loader.js +649 -65
  93. package/dist/core/template-loader.js.map +1 -1
  94. package/dist/core/update.d.ts.map +1 -1
  95. package/dist/core/update.js +131 -15
  96. package/dist/core/update.js.map +1 -1
  97. package/package.json +1 -1
@@ -0,0 +1,74 @@
1
+ /**
2
+ * 需求原语 — 需求层纯内存操作的单一入口
3
+ *
4
+ * 职责:需求读取(读侧宽容 + 浅副本)、ID 分配、写路径原语(add / claim / release / update / advance / link)
5
+ * 与共用谓词(终态判定 / 全部关联阶段 done)。全部为**纯内存**操作 + 审计内嵌(`data.log`),
6
+ * 零独立写盘点——落盘恒走调用方(命令层)的 `FlowManager` 落盘方法。
7
+ * 正交声明:不依赖归档层 / 不引用工作流模式字段。
8
+ */
9
+ import type { FlowData } from '../flow-manager.js';
10
+ import { type RequirementData, type RequirementPriority, type RequirementStatus } from './types.js';
11
+ /** 需求原语错误码(冻结;命令层据此映射 exit 非 0 零写盘) */
12
+ export type RequirementErrorCode = 'not_found' | 'stage_not_found' | 'already_claimed' | 'already_linked' | 'invalid_status' | 'invalid_field';
13
+ /** 写路径原语结果(ok=false 时携错误码;命令层映射 exit 非 0 零写盘) */
14
+ export type RequirementOpResult = {
15
+ ok: true;
16
+ changed: boolean;
17
+ } | {
18
+ ok: false;
19
+ code: RequirementErrorCode;
20
+ };
21
+ /** 全量需求(读侧宽容:缺失/非数组 → [];数组 + 元素浅副本,防外部直改内存) */
22
+ export declare function getRequirements(data: FlowData): RequirementData[];
23
+ /** 按 id 查询(未命中 null;返回浅副本) */
24
+ export declare function getRequirement(data: FlowData, id: string): RequirementData | null;
25
+ /** 过滤查询(status 精确 / target_version 精确 / owner 精确;多条件 AND;API 面命名统一 target_version——REV-81-012) */
26
+ export declare function listRequirements(data: FlowData, filter?: {
27
+ status?: RequirementStatus;
28
+ target_version?: string;
29
+ owner?: string;
30
+ }): RequirementData[];
31
+ /** 下一个需求 ID:现存 id 数字部分 max+1(不回收;异常 id 跳过不崩) */
32
+ export declare function nextRequirementId(data: FlowData): string;
33
+ /** 终态判定(done/cancelled/rejected;claim / link 门共用) */
34
+ export declare function isTerminalRequirementStatus(status: RequirementStatus): boolean;
35
+ /** 裁定 4:全部关联阶段 done(零关联 → false,空集守卫) */
36
+ export declare function allLinkedStagesDone(data: FlowData, requirementId: string): boolean;
37
+ /**
38
+ * 新建需求(恒 `status: 'draft'`;读侧宽容写路径;返回**本体**供调用方继续设 body_path)。
39
+ * 非法入参(空 title / 非法 priority / 空 target_version)属构造期契约违反 → 抛错(唯一抛错原语,REV-81-015)。
40
+ * REV-81-018 登记:add 构造期抛错 / update 运行期错误码为接受差异(与命令层分流矩阵同口径,REV-82-002);stage-81 冻结面不统一。
41
+ */
42
+ export declare function addRequirement(data: FlowData, input: {
43
+ title: string;
44
+ target_version?: string;
45
+ priority?: RequirementPriority;
46
+ }): RequirementData;
47
+ /** 认领需求(占用校验;同 owner 幂等;终态拒绝;他人占用零变更零审计) */
48
+ export declare function claimRequirement(data: FlowData, id: string, owner: string): RequirementOpResult;
49
+ /** 释放认领(裁定 5:无占用者 = no-op 成功——不刷 updated_at / 不写审计;不设状态门) */
50
+ export declare function releaseRequirement(data: FlowData, id: string): RequirementOpResult;
51
+ /**
52
+ * 当前状态的合法目标列表(只读纯函数;领域外状态 → [])。
53
+ * 命令层「列合法目标」的唯一来源——禁第二份流转表(REV-82-003);返回副本,防调用方直改内部表。
54
+ */
55
+ export declare function getAllowedNextStatuses(status: RequirementStatus): RequirementStatus[];
56
+ /**
57
+ * 更新需求(patch 白名单;全部维度先校验后落地——校验失败整 patch 零变更)。
58
+ * 恒 raw find 改 `data.requirements` 本体(禁经 getRequirement 的浅副本——副本陷阱,REV-81-011)。
59
+ */
60
+ export declare function updateRequirement(data: FlowData, id: string, patch: {
61
+ status?: RequirementStatus;
62
+ title?: string;
63
+ target_version?: string;
64
+ priority?: RequirementPriority;
65
+ }): RequirementOpResult;
66
+ /** 显式人工推进(裁定 M);语义与 update({status}) 完全一致(同表同门同审计,零第二套) */
67
+ export declare function advanceRequirement(data: FlowData, id: string, to: RequirementStatus): RequirementOpResult;
68
+ /**
69
+ * 阶段关联需求(stage 侧写点;`null` = 解绑)。
70
+ * 终态需求拒绝关联、他人已关联阶段拒绝重绑(须先解绑);
71
+ * 不刷新 requirement.updated_at(关联写点落在 stage 记录,需求对象零变更)。
72
+ */
73
+ export declare function linkRequirement(data: FlowData, stageId: string, requirementId: string | null): RequirementOpResult;
74
+ //# sourceMappingURL=requirement-ops.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"requirement-ops.d.ts","sourceRoot":"","sources":["../../../src/core/req/requirement-ops.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,EAEL,KAAK,eAAe,EAAE,KAAK,mBAAmB,EAAE,KAAK,iBAAiB,EACvE,MAAM,YAAY,CAAC;AAEpB,uCAAuC;AACvC,MAAM,MAAM,oBAAoB,GAC5B,WAAW,GACX,iBAAiB,GACjB,iBAAiB,GACjB,gBAAgB,GAChB,gBAAgB,GAChB,eAAe,CAAC;AAEpB,iDAAiD;AACjD,MAAM,MAAM,mBAAmB,GAAG;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,IAAI,EAAE,oBAAoB,CAAA;CAAE,CAAC;AAS7G,gDAAgD;AAChD,wBAAgB,eAAe,CAAC,IAAI,EAAE,QAAQ,GAAG,eAAe,EAAE,CAGjE;AAED,8BAA8B;AAC9B,wBAAgB,cAAc,CAAC,IAAI,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,GAAG,eAAe,GAAG,IAAI,CAGjF;AAED,kGAAkG;AAClG,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,QAAQ,EACd,MAAM,CAAC,EAAE;IAAE,MAAM,CAAC,EAAE,iBAAiB,CAAC;IAAC,cAAc,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,GAC/E,eAAe,EAAE,CAMnB;AAED,gDAAgD;AAChD,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,QAAQ,GAAG,MAAM,CASxD;AAED,qDAAqD;AACrD,wBAAgB,2BAA2B,CAAC,MAAM,EAAE,iBAAiB,GAAG,OAAO,CAE9E;AAED,yCAAyC;AACzC,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,GAAG,OAAO,CAGlF;AAID;;;;GAIG;AACH,wBAAgB,cAAc,CAC5B,IAAI,EAAE,QAAQ,EACd,KAAK,EAAE;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,cAAc,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,mBAAmB,CAAA;CAAE,GAChF,eAAe,CAuBjB;AAED,4CAA4C;AAC5C,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,mBAAmB,CAa/F;AAED,6DAA6D;AAC7D,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,GAAG,mBAAmB,CASlF;AAWD;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,iBAAiB,GAAG,iBAAiB,EAAE,CAErF;AAoBD;;;GAGG;AACH,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,QAAQ,EACd,EAAE,EAAE,MAAM,EACV,KAAK,EAAE;IAAE,MAAM,CAAC,EAAE,iBAAiB,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,cAAc,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,mBAAmB,CAAA;CAAE,GAC7G,mBAAmB,CAyDrB;AAED,2DAA2D;AAC3D,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,iBAAiB,GAAG,mBAAmB,CAEzG;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,GAAG,IAAI,GAAG,mBAAmB,CAoBlH"}
@@ -0,0 +1,290 @@
1
+ import { REQ_ID_PATTERN, REQ_PRIORITIES, REQ_STATUSES, } from './types.js';
2
+ /** 追加需求审计日志(纯内存;save 由调用方承担) */
3
+ function appendRequirementLog(data, action, detail) {
4
+ data.log.push({ time: new Date().toISOString(), agent: 'cli', action, detail });
5
+ }
6
+ // ═══ 读取与分配(读侧宽容 + 浅副本,裁定 2/8)═══
7
+ /** 全量需求(读侧宽容:缺失/非数组 → [];数组 + 元素浅副本,防外部直改内存) */
8
+ export function getRequirements(data) {
9
+ const list = data.requirements;
10
+ return Array.isArray(list) ? list.map((r) => ({ ...r })) : [];
11
+ }
12
+ /** 按 id 查询(未命中 null;返回浅副本) */
13
+ export function getRequirement(data, id) {
14
+ const found = (Array.isArray(data.requirements) ? data.requirements : []).find((r) => r?.id === id);
15
+ return found ? { ...found } : null;
16
+ }
17
+ /** 过滤查询(status 精确 / target_version 精确 / owner 精确;多条件 AND;API 面命名统一 target_version——REV-81-012) */
18
+ export function listRequirements(data, filter) {
19
+ let result = getRequirements(data);
20
+ if (filter?.status !== undefined) {
21
+ result = result.filter((r) => r.status === filter.status);
22
+ }
23
+ if (filter?.target_version !== undefined) {
24
+ result = result.filter((r) => r.target_version === filter.target_version);
25
+ }
26
+ if (filter?.owner !== undefined) {
27
+ result = result.filter((r) => r.owner === filter.owner);
28
+ }
29
+ return result;
30
+ }
31
+ /** 下一个需求 ID:现存 id 数字部分 max+1(不回收;异常 id 跳过不崩) */
32
+ export function nextRequirementId(data) {
33
+ let max = 0;
34
+ for (const r of getRequirements(data)) {
35
+ const m = REQ_ID_PATTERN.exec(typeof r?.id === 'string' ? r.id : '');
36
+ if (!m) {
37
+ continue;
38
+ } // 异常 id 跳过(不崩)
39
+ const n = Number.parseInt(m[1], 10);
40
+ if (Number.isFinite(n) && n > max) {
41
+ max = n;
42
+ }
43
+ }
44
+ return `REQ-${String(max + 1).padStart(3, '0')}`;
45
+ }
46
+ /** 终态判定(done/cancelled/rejected;claim / link 门共用) */
47
+ export function isTerminalRequirementStatus(status) {
48
+ return status === 'done' || status === 'cancelled' || status === 'rejected';
49
+ }
50
+ /** 裁定 4:全部关联阶段 done(零关联 → false,空集守卫) */
51
+ export function allLinkedStagesDone(data, requirementId) {
52
+ const linked = Object.values(data.stages ?? {}).filter((s) => (s.requirement_id ?? null) === requirementId);
53
+ return linked.length > 0 && linked.every((s) => s.phase === 'done');
54
+ }
55
+ // ═══ 写路径原语 ═══
56
+ /**
57
+ * 新建需求(恒 `status: 'draft'`;读侧宽容写路径;返回**本体**供调用方继续设 body_path)。
58
+ * 非法入参(空 title / 非法 priority / 空 target_version)属构造期契约违反 → 抛错(唯一抛错原语,REV-81-015)。
59
+ * REV-81-018 登记:add 构造期抛错 / update 运行期错误码为接受差异(与命令层分流矩阵同口径,REV-82-002);stage-81 冻结面不统一。
60
+ */
61
+ export function addRequirement(data, input) {
62
+ const title = typeof input?.title === 'string' ? input.title.trim() : '';
63
+ if (title === '') {
64
+ throw new Error('需求标题不能为空');
65
+ } // 非法入参:编程错误抛错(非业务冲突)
66
+ if (input.priority !== undefined && !REQ_PRIORITIES.includes(input.priority)) {
67
+ throw new Error(`需求优先级非法:${String(input.priority)}`); // 值域单点 = REQ_PRIORITIES
68
+ }
69
+ // 命名统一(REV-81-012):API 面恒 target_version(与存储字段同名,零映射层)
70
+ if (input.target_version !== undefined && String(input.target_version).trim() === '') {
71
+ throw new Error('预估版本不能为空串');
72
+ }
73
+ // 非数组(损坏数据)视同空集重建——与其余原语「非数组 ≡ 空集」宽容口径统一(req/BUG-001 = REV-81-019 单点收口);改自 ??=(??= 不替换非数组真值 → push 抛 TypeError)
74
+ data.requirements = Array.isArray(data.requirements) ? data.requirements : [];
75
+ const now = new Date().toISOString();
76
+ const req = {
77
+ id: nextRequirementId(data), // 须在 push 之前分配
78
+ title,
79
+ status: 'draft', // 新建即 draft(REV-81-005)
80
+ created_at: now,
81
+ updated_at: now,
82
+ };
83
+ if (input.target_version !== undefined) {
84
+ req.target_version = String(input.target_version).trim();
85
+ }
86
+ if (input.priority !== undefined) {
87
+ req.priority = input.priority;
88
+ }
89
+ data.requirements.push(req);
90
+ appendRequirementLog(data, 'requirement_add', { id: req.id, title: req.title });
91
+ return req; // 本体(调用方继续设 body_path)
92
+ }
93
+ /** 认领需求(占用校验;同 owner 幂等;终态拒绝;他人占用零变更零审计) */
94
+ export function claimRequirement(data, id, owner) {
95
+ const name = typeof owner === 'string' ? owner.trim() : '';
96
+ if (name === '') {
97
+ return { ok: false, code: 'invalid_field' };
98
+ }
99
+ const req = (Array.isArray(data.requirements) ? data.requirements : []).find((r) => r?.id === id);
100
+ if (!req) {
101
+ return { ok: false, code: 'not_found' };
102
+ }
103
+ if (isTerminalRequirementStatus(req.status)) {
104
+ return { ok: false, code: 'invalid_status' };
105
+ }
106
+ if (req.owner && req.owner !== name) {
107
+ return { ok: false, code: 'already_claimed' };
108
+ } // 数据零变更
109
+ if (req.owner === name) {
110
+ return { ok: true, changed: false };
111
+ } // 同 owner 幂等
112
+ req.owner = name;
113
+ req.claimed_at = new Date().toISOString();
114
+ req.updated_at = req.claimed_at;
115
+ appendRequirementLog(data, 'requirement_claim', { id, owner: name });
116
+ return { ok: true, changed: true };
117
+ }
118
+ /** 释放认领(裁定 5:无占用者 = no-op 成功——不刷 updated_at / 不写审计;不设状态门) */
119
+ export function releaseRequirement(data, id) {
120
+ const req = (Array.isArray(data.requirements) ? data.requirements : []).find((r) => r?.id === id);
121
+ if (!req) {
122
+ return { ok: false, code: 'not_found' };
123
+ }
124
+ if (!req.owner) {
125
+ return { ok: true, changed: false };
126
+ } // 无占用者:no-op 成功(不刷 updated_at / 不写审计)
127
+ const prevOwner = req.owner;
128
+ delete req.owner;
129
+ delete req.claimed_at;
130
+ req.updated_at = new Date().toISOString();
131
+ appendRequirementLog(data, 'requirement_release', { id, owner: prevOwner });
132
+ return { ok: true, changed: true };
133
+ }
134
+ /** 显式流转表(裁定 3;终态不再流转)——状态流转单点 */
135
+ const ALLOWED_TRANSITIONS = {
136
+ draft: ['scheduled', 'blocked', 'cancelled', 'rejected'],
137
+ scheduled: ['in_progress', 'blocked', 'cancelled', 'rejected'],
138
+ in_progress: ['done', 'blocked', 'cancelled', 'rejected'],
139
+ blocked: ['scheduled', 'in_progress', 'cancelled', 'rejected'],
140
+ done: [], cancelled: [], rejected: [],
141
+ };
142
+ /**
143
+ * 当前状态的合法目标列表(只读纯函数;领域外状态 → [])。
144
+ * 命令层「列合法目标」的唯一来源——禁第二份流转表(REV-82-003);返回副本,防调用方直改内部表。
145
+ */
146
+ export function getAllowedNextStatuses(status) {
147
+ return [...(ALLOWED_TRANSITIONS[status] ?? [])];
148
+ }
149
+ /** 状态变更应用(唯一实现):返回 false = invalid_status(含 done 门不满足) */
150
+ function applyStatusChange(data, req, to) {
151
+ if (!REQ_STATUSES.includes(to)) {
152
+ return false;
153
+ }
154
+ if (to === req.status) {
155
+ return false;
156
+ } // 同值由调用方按幂等 no-op 处理
157
+ // 域外 status(存量脏数据 / 人工篡改)→ 查表得 undefined,守卫后与「表外组合」同语义,不抛 TypeError(REV-81-016)
158
+ const allowed = ALLOWED_TRANSITIONS[req.status];
159
+ if (!allowed || !allowed.includes(to)) {
160
+ return false;
161
+ }
162
+ if (to === 'done' && !allLinkedStagesDone(data, req.id)) {
163
+ return false;
164
+ } // 裁定 4(零关联拒绝)
165
+ const from = req.status;
166
+ req.status = to;
167
+ req.updated_at = new Date().toISOString(); // 状态维度刷新(单次赋值纪律,REV-81-013)
168
+ appendRequirementLog(data, 'requirement_status', { id: req.id, from, to });
169
+ return true;
170
+ }
171
+ /** 字段白名单(= RequirementData 可变字段名子集) */
172
+ const PATCH_WHITELIST = ['status', 'title', 'target_version', 'priority'];
173
+ /**
174
+ * 更新需求(patch 白名单;全部维度先校验后落地——校验失败整 patch 零变更)。
175
+ * 恒 raw find 改 `data.requirements` 本体(禁经 getRequirement 的浅副本——副本陷阱,REV-81-011)。
176
+ */
177
+ export function updateRequirement(data, id, patch) {
178
+ // ① 内联 raw find(与 claim / release 同款)
179
+ const req = (Array.isArray(data.requirements) ? data.requirements : []).find((r) => r?.id === id);
180
+ if (!req) {
181
+ return { ok: false, code: 'not_found' };
182
+ }
183
+ const p = patch ?? {};
184
+ const keys = Object.entries(p).filter(([, v]) => v !== undefined).map(([k]) => k);
185
+ // ② 白名单外键(值非 undefined 才计)
186
+ for (const k of keys) {
187
+ if (!PATCH_WHITELIST.includes(k)) {
188
+ return { ok: false, code: 'invalid_field' };
189
+ }
190
+ }
191
+ // ③ 全空 patch(或全 undefined 值)
192
+ if (keys.length === 0) {
193
+ return { ok: true, changed: false };
194
+ }
195
+ // ④ 值校验(全部维度先校验,失败即整 patch 零变更)
196
+ // REV-81-018 登记:add 构造期抛错 / update 运行期错误码为接受差异(与命令层分流矩阵同口径,REV-82-002);stage-81 冻结面不统一。
197
+ if (p.title !== undefined && String(p.title).trim() === '') {
198
+ return { ok: false, code: 'invalid_field' };
199
+ }
200
+ if (p.target_version !== undefined && (typeof p.target_version !== 'string' || p.target_version.trim() === '')) {
201
+ return { ok: false, code: 'invalid_field' };
202
+ }
203
+ if (p.priority !== undefined && !REQ_PRIORITIES.includes(p.priority)) {
204
+ return { ok: false, code: 'invalid_field' };
205
+ }
206
+ if (p.status !== undefined && !REQ_STATUSES.includes(p.status)) {
207
+ return { ok: false, code: 'invalid_status' };
208
+ }
209
+ // ⑥ 状态维度(= 当前则无变更;≠ 走单点 applyStatusChange)
210
+ let statusChanged = false;
211
+ if (p.status !== undefined && p.status !== req.status) {
212
+ if (!applyStatusChange(data, req, p.status)) {
213
+ return { ok: false, code: 'invalid_status' };
214
+ }
215
+ statusChanged = true;
216
+ }
217
+ // ⑦ 字段维度(逐字段比较后对 raw 本体赋值;仅实际不同才赋值)
218
+ const changedFields = [];
219
+ if (p.title !== undefined) {
220
+ const v = String(p.title).trim();
221
+ if (req.title !== v) {
222
+ req.title = v;
223
+ changedFields.push('title');
224
+ }
225
+ }
226
+ if (p.target_version !== undefined) {
227
+ const v = String(p.target_version).trim();
228
+ if (req.target_version !== v) {
229
+ req.target_version = v;
230
+ changedFields.push('target_version');
231
+ }
232
+ }
233
+ if (p.priority !== undefined) {
234
+ if (req.priority !== p.priority) {
235
+ req.priority = p.priority;
236
+ changedFields.push('priority');
237
+ }
238
+ }
239
+ // ⑧ updated_at 单次赋值纪律(REV-81-013):字段维度实际变更且状态维度未变时刷新一次;
240
+ // 状态维度已由 applyStatusChange 刷新,两维度并存时不重复赋值
241
+ if (changedFields.length > 0) {
242
+ if (!statusChanged) {
243
+ req.updated_at = new Date().toISOString();
244
+ }
245
+ appendRequirementLog(data, 'requirement_update', { id, fields: changedFields });
246
+ }
247
+ // ⑩
248
+ return { ok: true, changed: statusChanged || changedFields.length > 0 };
249
+ }
250
+ /** 显式人工推进(裁定 M);语义与 update({status}) 完全一致(同表同门同审计,零第二套) */
251
+ export function advanceRequirement(data, id, to) {
252
+ return updateRequirement(data, id, { status: to });
253
+ }
254
+ /**
255
+ * 阶段关联需求(stage 侧写点;`null` = 解绑)。
256
+ * 终态需求拒绝关联、他人已关联阶段拒绝重绑(须先解绑);
257
+ * 不刷新 requirement.updated_at(关联写点落在 stage 记录,需求对象零变更)。
258
+ */
259
+ export function linkRequirement(data, stageId, requirementId) {
260
+ const stage = data.stages?.[stageId];
261
+ if (!stage) {
262
+ return { ok: false, code: 'stage_not_found' };
263
+ } // ① 阶段不存在
264
+ if (requirementId !== null) {
265
+ const req = (Array.isArray(data.requirements) ? data.requirements : []).find((r) => r?.id === requirementId);
266
+ if (!req) {
267
+ return { ok: false, code: 'not_found' };
268
+ } // 需求不存在
269
+ if (isTerminalRequirementStatus(req.status)) {
270
+ return { ok: false, code: 'invalid_status' };
271
+ } // 终态拒绝
272
+ if ((stage.requirement_id ?? null) === requirementId) {
273
+ return { ok: true, changed: false };
274
+ } // 同值幂等
275
+ if (stage.requirement_id != null) {
276
+ return { ok: false, code: 'already_linked' };
277
+ } // 跨需求重绑
278
+ stage.requirement_id = requirementId;
279
+ appendRequirementLog(data, 'requirement_link', { stage: stageId, requirementId });
280
+ return { ok: true, changed: true };
281
+ }
282
+ // ③ null = 解绑(显式 null,对齐「可空」裁定 D)
283
+ if (stage.requirement_id == null) {
284
+ return { ok: true, changed: false };
285
+ }
286
+ stage.requirement_id = null;
287
+ appendRequirementLog(data, 'requirement_link', { stage: stageId, requirementId: null });
288
+ return { ok: true, changed: true };
289
+ }
290
+ //# sourceMappingURL=requirement-ops.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"requirement-ops.js","sourceRoot":"","sources":["../../../src/core/req/requirement-ops.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,40 @@
1
+ /**
2
+ * 需求层类型与常量 — 单一来源(叶子模块)
3
+ *
4
+ * 职责:需求状态值域、优先级值域、需求 ID 格式与 `RequirementData` 字段表的**唯一权威定义**。
5
+ * 正交声明:零 import(叶子模块);不依赖归档层 / 不引用工作流模式字段。
6
+ */
7
+ /** 需求状态值域(7 值,裁定 B;单一来源——stage-82 命令层校验须从此派生,禁硬编码) */
8
+ export declare const REQ_STATUSES: readonly ["draft", "scheduled", "in_progress", "done", "blocked", "cancelled", "rejected"];
9
+ /** 需求状态联合类型(自 REQ_STATUSES 派生,唯一权威) */
10
+ export type RequirementStatus = (typeof REQ_STATUSES)[number];
11
+ /** 需求优先级值域(三档;单一来源) */
12
+ export declare const REQ_PRIORITIES: readonly ["P0", "P1", "P2"];
13
+ /** 需求优先级类型(自 REQ_PRIORITIES 派生) */
14
+ export type RequirementPriority = (typeof REQ_PRIORITIES)[number];
15
+ /** 需求 ID 格式(REQ-NNN 三位起补零;含数字捕获组;非全局标志,防 lastIndex 状态污染) */
16
+ export declare const REQ_ID_PATTERN: RegExp;
17
+ /** 需求条目数据(需求层显式字段;聚合方向归 stage-83) */
18
+ export interface RequirementData {
19
+ /** 需求 ID(REQ-NNN,max+1 不回收;格式见 REQ_ID_PATTERN) */
20
+ id: string;
21
+ /** 需求标题(人读简明描述;非空) */
22
+ title: string;
23
+ /** 显式粗粒度状态;新建恒 'draft'(REV-81-005) */
24
+ status: RequirementStatus;
25
+ /** 预估版本(如 v1.3.0;可选) */
26
+ target_version?: string;
27
+ /** 优先级 P0/P1/P2(可选) */
28
+ priority?: RequirementPriority;
29
+ /** 认领人(claim 写入;未认领缺省) */
30
+ owner?: string;
31
+ /** 认领时间 ISO 8601(与 owner 同批写入/清除) */
32
+ claimed_at?: string;
33
+ /** 创建时间 ISO 8601 */
34
+ created_at: string;
35
+ /** 最近更新时间 ISO 8601(仅实际变更时刷新) */
36
+ updated_at: string;
37
+ /** 正文相对路径(POSIX 分隔符,如 .openfeel/requirements/REQ-001.md) */
38
+ body_path?: string;
39
+ }
40
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/core/req/types.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,sDAAsD;AACtD,eAAO,MAAM,YAAY,4FAA6F,CAAC;AACvH,uCAAuC;AACvC,MAAM,MAAM,iBAAiB,GAAG,CAAC,OAAO,YAAY,CAAC,CAAC,MAAM,CAAC,CAAC;AAE9D,uBAAuB;AACvB,eAAO,MAAM,cAAc,6BAA8B,CAAC;AAC1D,mCAAmC;AACnC,MAAM,MAAM,mBAAmB,GAAG,CAAC,OAAO,cAAc,CAAC,CAAC,MAAM,CAAC,CAAC;AAElE,4DAA4D;AAC5D,eAAO,MAAM,cAAc,QAAmB,CAAC;AAE/C,qCAAqC;AACrC,MAAM,WAAW,eAAe;IAC9B,kDAAkD;IAClD,EAAE,EAAE,MAAM,CAAC;IACX,sBAAsB;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,sCAAsC;IACtC,MAAM,EAAE,iBAAiB,CAAC;IAC1B,wBAAwB;IACxB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,uBAAuB;IACvB,QAAQ,CAAC,EAAE,mBAAmB,CAAC;IAC/B,0BAA0B;IAC1B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,qCAAqC;IACrC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,oBAAoB;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,gCAAgC;IAChC,UAAU,EAAE,MAAM,CAAC;IACnB,4DAA4D;IAC5D,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * 需求层类型与常量 — 单一来源(叶子模块)
3
+ *
4
+ * 职责:需求状态值域、优先级值域、需求 ID 格式与 `RequirementData` 字段表的**唯一权威定义**。
5
+ * 正交声明:零 import(叶子模块);不依赖归档层 / 不引用工作流模式字段。
6
+ */
7
+ /** 需求状态值域(7 值,裁定 B;单一来源——stage-82 命令层校验须从此派生,禁硬编码) */
8
+ export const REQ_STATUSES = ['draft', 'scheduled', 'in_progress', 'done', 'blocked', 'cancelled', 'rejected'];
9
+ /** 需求优先级值域(三档;单一来源) */
10
+ export const REQ_PRIORITIES = ['P0', 'P1', 'P2'];
11
+ /** 需求 ID 格式(REQ-NNN 三位起补零;含数字捕获组;非全局标志,防 lastIndex 状态污染) */
12
+ export const REQ_ID_PATTERN = /^REQ-(\d{3,})$/; // 含数字捕获组(m[1] 供 nextRequirementId 解析);非全局标志
13
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/core/req/types.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,sDAAsD;AACtD,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,EAAE,SAAS,EAAE,WAAW,EAAE,UAAU,CAAU,CAAC;AAIvH,uBAAuB;AACvB,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,CAAU,CAAC;AAI1D,4DAA4D;AAC5D,MAAM,CAAC,MAAM,cAAc,GAAG,gBAAgB,CAAC,CAAG,4CAA4C"}
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * setup 命令核心模块(v1.1.1)
3
- * 纯全局部署:全局 AGENTS.md + 9 agent + 17 skill + 全局平台适配器配置文件(opencode.jsonc)。
3
+ * 纯全局部署:全局 AGENTS.md + 9 agent + 18 skill + 全局平台适配器配置文件(opencode.jsonc)。
4
4
  * 不建立项目 .openfeel/;复用 deployGlobalAsset(受管区三态,幂等可重跑)。
5
5
  */
6
6
  import { mkdirSync, existsSync, readFileSync } from 'node:fs';
@@ -45,7 +45,7 @@ export function setupGlobalFramework(lang = 'zh-CN', tools = ['opencode']) {
45
45
  const p = join(agentsDir, `${id}.md`);
46
46
  push(deployGlobalAsset(p, loadAgentTemplate(lang, id), globalState, 'setup'), p);
47
47
  }
48
- // 3. 17 skill → 全局 skills 目录
48
+ // 3. 18 skill → 全局 skills 目录
49
49
  const skillsDir = getGlobalSkillsDir();
50
50
  mkdirSync(skillsDir, { recursive: true });
51
51
  for (const [name, content] of Object.entries(SKILL_DEFINITIONS)) {
@@ -95,7 +95,7 @@ export function setupGlobalFramework(lang = 'zh-CN', tools = ['opencode']) {
95
95
  }
96
96
  }
97
97
  }
98
- // claude 分支:CLAUDE.md + 9 agent + 17 共享 skill + settings.json(stage-73)
98
+ // claude 分支:CLAUDE.md + 9 agent + 18 共享 skill + settings.json(stage-73)
99
99
  if (tools.includes('claude')) {
100
100
  // 1c. 全局约束 CLAUDE.md(受管区三态复用 deployGlobalAsset)
101
101
  const claudeMd = getClaudeMdPath();
@@ -107,7 +107,7 @@ export function setupGlobalFramework(lang = 'zh-CN', tools = ['opencode']) {
107
107
  const p = join(claudeAgentsDir, `${id}.md`);
108
108
  push(deployGlobalAsset(p, loadClaudeAgentTemplate(lang, id), globalState, 'setup'), p);
109
109
  }
110
- // 3c. 17 个共享 skill → ~/.claude/skills/
110
+ // 3c. 18 个共享 skill → ~/.claude/skills/
111
111
  const claudeSkillsDir = getClaudeSkillsDir();
112
112
  mkdirSync(claudeSkillsDir, { recursive: true });
113
113
  for (const [name, content] of Object.entries(SKILL_DEFINITIONS)) {
@@ -1 +1 @@
1
- {"version":3,"file":"template-loader.d.ts","sourceRoot":"","sources":["../../src/core/template-loader.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AA+pHH;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAWvE;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAGnD;AAED,yCAAyC;AACzC,MAAM,MAAM,YAAY,GAAG,WAAW,CAAC;AAEvC,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,YAAY,EAAE,YAAY,GAAG,MAAM,CAS7E;AAyoPD,eAAO,MAAM,kBAAkB,EAAE,MAAqC,CAAC;AAEvE;;;GAGG;AACH,wBAAgB,yBAAyB,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAO/E;AAED;;GAEG;AACH,wBAAgB,yBAAyB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAMnE;AAED;;;;GAIG;AACH,wBAAgB,0BAA0B,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,CAWnF;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAG3D;AAED;;GAEG;AACH,wBAAgB,sBAAsB,IAAI,MAAM,EAAE,CAEjD;AAED;;;GAGG;AACH,wBAAgB,4BAA4B,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAMjE;AAED;;;GAGG;AACH,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAO7E;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAGzD"}
1
+ {"version":3,"file":"template-loader.d.ts","sourceRoot":"","sources":["../../src/core/template-loader.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AA2zHH;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAWvE;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAGnD;AAED,yCAAyC;AACzC,MAAM,MAAM,YAAY,GAAG,WAAW,CAAC;AAEvC,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,YAAY,EAAE,YAAY,GAAG,MAAM,CAS7E;AAqjQD,eAAO,MAAM,kBAAkB,EAAE,MAAqC,CAAC;AAEvE;;;GAGG;AACH,wBAAgB,yBAAyB,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAO/E;AAED;;GAEG;AACH,wBAAgB,yBAAyB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAMnE;AAED;;;;GAIG;AACH,wBAAgB,0BAA0B,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,CAWnF;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAG3D;AAED;;GAEG;AACH,wBAAgB,sBAAsB,IAAI,MAAM,EAAE,CAEjD;AAED;;;GAGG;AACH,wBAAgB,4BAA4B,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAMjE;AAED;;;GAGG;AACH,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAO7E;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAGzD"}