specdo 1.0.2

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 (161) hide show
  1. package/CHANGELOG.md +139 -0
  2. package/README.md +308 -0
  3. package/README.zh-CN.md +306 -0
  4. package/bin/specdo.js +3 -0
  5. package/dist/cli/index.d.ts +15 -0
  6. package/dist/cli/index.d.ts.map +1 -0
  7. package/dist/cli/index.js +297 -0
  8. package/dist/cli/index.js.map +1 -0
  9. package/dist/commands/_shared.d.ts +45 -0
  10. package/dist/commands/_shared.d.ts.map +1 -0
  11. package/dist/commands/_shared.js +124 -0
  12. package/dist/commands/_shared.js.map +1 -0
  13. package/dist/commands/apply.d.ts +30 -0
  14. package/dist/commands/apply.d.ts.map +1 -0
  15. package/dist/commands/apply.js +393 -0
  16. package/dist/commands/apply.js.map +1 -0
  17. package/dist/commands/archive.d.ts +25 -0
  18. package/dist/commands/archive.d.ts.map +1 -0
  19. package/dist/commands/archive.js +362 -0
  20. package/dist/commands/archive.js.map +1 -0
  21. package/dist/commands/doctor.d.ts +21 -0
  22. package/dist/commands/doctor.d.ts.map +1 -0
  23. package/dist/commands/doctor.js +180 -0
  24. package/dist/commands/doctor.js.map +1 -0
  25. package/dist/commands/domains.d.ts +14 -0
  26. package/dist/commands/domains.d.ts.map +1 -0
  27. package/dist/commands/domains.js +107 -0
  28. package/dist/commands/domains.js.map +1 -0
  29. package/dist/commands/explore.d.ts +48 -0
  30. package/dist/commands/explore.d.ts.map +1 -0
  31. package/dist/commands/explore.js +378 -0
  32. package/dist/commands/explore.js.map +1 -0
  33. package/dist/commands/init.d.ts +45 -0
  34. package/dist/commands/init.d.ts.map +1 -0
  35. package/dist/commands/init.js +243 -0
  36. package/dist/commands/init.js.map +1 -0
  37. package/dist/commands/list.d.ts +23 -0
  38. package/dist/commands/list.d.ts.map +1 -0
  39. package/dist/commands/list.js +135 -0
  40. package/dist/commands/list.js.map +1 -0
  41. package/dist/commands/propose.d.ts +22 -0
  42. package/dist/commands/propose.d.ts.map +1 -0
  43. package/dist/commands/propose.js +316 -0
  44. package/dist/commands/propose.js.map +1 -0
  45. package/dist/commands/show.d.ts +15 -0
  46. package/dist/commands/show.d.ts.map +1 -0
  47. package/dist/commands/show.js +214 -0
  48. package/dist/commands/show.js.map +1 -0
  49. package/dist/commands/status.d.ts +17 -0
  50. package/dist/commands/status.d.ts.map +1 -0
  51. package/dist/commands/status.js +146 -0
  52. package/dist/commands/status.js.map +1 -0
  53. package/dist/commands/sync.d.ts +21 -0
  54. package/dist/commands/sync.d.ts.map +1 -0
  55. package/dist/commands/sync.js +113 -0
  56. package/dist/commands/sync.js.map +1 -0
  57. package/dist/commands/validate.d.ts +117 -0
  58. package/dist/commands/validate.d.ts.map +1 -0
  59. package/dist/commands/validate.js +446 -0
  60. package/dist/commands/validate.js.map +1 -0
  61. package/dist/core/apply-brief-renderer.d.ts +35 -0
  62. package/dist/core/apply-brief-renderer.d.ts.map +1 -0
  63. package/dist/core/apply-brief-renderer.js +242 -0
  64. package/dist/core/apply-brief-renderer.js.map +1 -0
  65. package/dist/core/config-store.d.ts +190 -0
  66. package/dist/core/config-store.d.ts.map +1 -0
  67. package/dist/core/config-store.js +280 -0
  68. package/dist/core/config-store.js.map +1 -0
  69. package/dist/core/context-store.d.ts +96 -0
  70. package/dist/core/context-store.d.ts.map +1 -0
  71. package/dist/core/context-store.js +426 -0
  72. package/dist/core/context-store.js.map +1 -0
  73. package/dist/core/json-schemas.d.ts +349 -0
  74. package/dist/core/json-schemas.d.ts.map +1 -0
  75. package/dist/core/json-schemas.js +125 -0
  76. package/dist/core/json-schemas.js.map +1 -0
  77. package/dist/core/skill-content/cross-domain.d.ts +12 -0
  78. package/dist/core/skill-content/cross-domain.d.ts.map +1 -0
  79. package/dist/core/skill-content/cross-domain.js +291 -0
  80. package/dist/core/skill-content/cross-domain.js.map +1 -0
  81. package/dist/core/skill-content/protocol-examples.d.ts +13 -0
  82. package/dist/core/skill-content/protocol-examples.d.ts.map +1 -0
  83. package/dist/core/skill-content/protocol-examples.js +190 -0
  84. package/dist/core/skill-content/protocol-examples.js.map +1 -0
  85. package/dist/core/skill-content/workflow-content.d.ts +25 -0
  86. package/dist/core/skill-content/workflow-content.d.ts.map +1 -0
  87. package/dist/core/skill-content/workflow-content.js +1572 -0
  88. package/dist/core/skill-content/workflow-content.js.map +1 -0
  89. package/dist/core/skill-exporter.d.ts +186 -0
  90. package/dist/core/skill-exporter.d.ts.map +1 -0
  91. package/dist/core/skill-exporter.js +922 -0
  92. package/dist/core/skill-exporter.js.map +1 -0
  93. package/dist/core/spec-sync.d.ts +65 -0
  94. package/dist/core/spec-sync.d.ts.map +1 -0
  95. package/dist/core/spec-sync.js +226 -0
  96. package/dist/core/spec-sync.js.map +1 -0
  97. package/dist/core/task-parser.d.ts +58 -0
  98. package/dist/core/task-parser.d.ts.map +1 -0
  99. package/dist/core/task-parser.js +244 -0
  100. package/dist/core/task-parser.js.map +1 -0
  101. package/dist/core/template-renderer.d.ts +51 -0
  102. package/dist/core/template-renderer.d.ts.map +1 -0
  103. package/dist/core/template-renderer.js +362 -0
  104. package/dist/core/template-renderer.js.map +1 -0
  105. package/dist/domains/architecture.d.ts +34 -0
  106. package/dist/domains/architecture.d.ts.map +1 -0
  107. package/dist/domains/architecture.js +341 -0
  108. package/dist/domains/architecture.js.map +1 -0
  109. package/dist/domains/backend.d.ts +35 -0
  110. package/dist/domains/backend.d.ts.map +1 -0
  111. package/dist/domains/backend.js +367 -0
  112. package/dist/domains/backend.js.map +1 -0
  113. package/dist/domains/frontend.d.ts +36 -0
  114. package/dist/domains/frontend.d.ts.map +1 -0
  115. package/dist/domains/frontend.js +373 -0
  116. package/dist/domains/frontend.js.map +1 -0
  117. package/dist/domains/index.d.ts +49 -0
  118. package/dist/domains/index.d.ts.map +1 -0
  119. package/dist/domains/index.js +255 -0
  120. package/dist/domains/index.js.map +1 -0
  121. package/dist/domains/operations.d.ts +37 -0
  122. package/dist/domains/operations.d.ts.map +1 -0
  123. package/dist/domains/operations.js +344 -0
  124. package/dist/domains/operations.js.map +1 -0
  125. package/dist/domains/pool-ranking.d.ts +43 -0
  126. package/dist/domains/pool-ranking.d.ts.map +1 -0
  127. package/dist/domains/pool-ranking.js +153 -0
  128. package/dist/domains/pool-ranking.js.map +1 -0
  129. package/dist/domains/quality.d.ts +45 -0
  130. package/dist/domains/quality.d.ts.map +1 -0
  131. package/dist/domains/quality.js +368 -0
  132. package/dist/domains/quality.js.map +1 -0
  133. package/dist/domains/security.d.ts +19 -0
  134. package/dist/domains/security.d.ts.map +1 -0
  135. package/dist/domains/security.js +364 -0
  136. package/dist/domains/security.js.map +1 -0
  137. package/dist/domains/signal-match.d.ts +25 -0
  138. package/dist/domains/signal-match.d.ts.map +1 -0
  139. package/dist/domains/signal-match.js +67 -0
  140. package/dist/domains/signal-match.js.map +1 -0
  141. package/dist/domains/types.d.ts +354 -0
  142. package/dist/domains/types.d.ts.map +1 -0
  143. package/dist/domains/types.js +12 -0
  144. package/dist/domains/types.js.map +1 -0
  145. package/dist/index.d.ts +9 -0
  146. package/dist/index.d.ts.map +1 -0
  147. package/dist/index.js +9 -0
  148. package/dist/index.js.map +1 -0
  149. package/dist/protocols/index.d.ts +36 -0
  150. package/dist/protocols/index.d.ts.map +1 -0
  151. package/dist/protocols/index.js +85 -0
  152. package/dist/protocols/index.js.map +1 -0
  153. package/dist/protocols/review-to-solid.d.ts +32 -0
  154. package/dist/protocols/review-to-solid.d.ts.map +1 -0
  155. package/dist/protocols/review-to-solid.js +309 -0
  156. package/dist/protocols/review-to-solid.js.map +1 -0
  157. package/dist/utils/prompt.d.ts +37 -0
  158. package/dist/utils/prompt.d.ts.map +1 -0
  159. package/dist/utils/prompt.js +81 -0
  160. package/dist/utils/prompt.js.map +1 -0
  161. package/package.json +80 -0
@@ -0,0 +1,45 @@
1
+ /**
2
+ * commands 共享类型与工具
3
+ *
4
+ * 所有命令遵循同一签名:
5
+ * `handle(options): Promise<CommandResult>`
6
+ *
7
+ * `CommandResult.exitCode` 必须使用 phases/03-phase2-commands.md §"Exit Code
8
+ * 体系" 定义的统一编码。`stdout` / `stderr` 由 CLI wrapper 写入终端;测试
9
+ * 直接断言数组内容,无需 spawn 子进程。
10
+ */
11
+ export interface CommandResult {
12
+ exitCode: 0 | 1 | 2 | 3 | 4;
13
+ stdout: string[];
14
+ stderr: string[];
15
+ }
16
+ export declare function ok(stdout?: string[]): CommandResult;
17
+ export declare function fail(exitCode: 1 | 2 | 3 | 4, stderr: string[], stdout?: string[]): CommandResult;
18
+ /**
19
+ * 检测目标目录是否已经 init(specdo/config.yaml 或 .yml 存在)。
20
+ *
21
+ * 不存在 → 返回 null;存在 → 返回绝对路径。
22
+ */
23
+ export declare function findSpecdoConfig(cwd: string): string | null;
24
+ export declare function getSpecdoDir(cwd: string): string;
25
+ export declare function getChangeDir(cwd: string, changeName: string): string;
26
+ export declare function getArchiveDir(cwd: string, changeName: string): string;
27
+ export declare function getSpecsDir(cwd: string): string;
28
+ /**
29
+ * 从用户的 idea 描述生成 change slug(kebab-case),最多 5 个有意义 token,
30
+ * 总长度 ≤ 50 字符。规则与 phases/03-phase2-commands.md §"Change 名称 slug
31
+ * 生成规则" 完全对齐。
32
+ *
33
+ * 失败:返回空字符串;调用方应转为 exit code 1 提示 "Cannot generate
34
+ * change name from input. Use --change <name>."
35
+ */
36
+ export declare function generateChangeSlug(idea: string): string;
37
+ /** 用户提供的 --change 名称合规性校验 */
38
+ export declare function isValidChangeName(name: string): boolean;
39
+ export declare function safeIsFile(p: string): boolean;
40
+ export declare function safeIsDir(p: string): boolean;
41
+ export declare function safeExists(p: string): boolean;
42
+ import type { ConfigIssue, ConfigLoadResult } from '../core/config-store.js';
43
+ export declare function failOnInvalidConfig(result: ConfigLoadResult): CommandResult | null;
44
+ export declare function renderConfigIssues(issues: ConfigIssue[]): string[];
45
+ //# sourceMappingURL=_shared.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"_shared.d.ts","sourceRoot":"","sources":["../../src/commands/_shared.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAKH,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAC5B,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAED,wBAAgB,EAAE,CAAC,MAAM,GAAE,MAAM,EAAO,GAAG,aAAa,CAEvD;AAED,wBAAgB,IAAI,CAAC,QAAQ,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE,MAAM,GAAE,MAAM,EAAO,GAAG,aAAa,CAEpG;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAM3D;AAED,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAEhD;AAED,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,CAEpE;AAED,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,CAErE;AAED,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAE/C;AAQD;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAmBvD;AAED,6BAA6B;AAC7B,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAGvD;AAED,wBAAgB,UAAU,CAAC,CAAC,EAAE,MAAM,GAAG,OAAO,CAM7C;AAED,wBAAgB,SAAS,CAAC,CAAC,EAAE,MAAM,GAAG,OAAO,CAM5C;AAED,wBAAgB,UAAU,CAAC,CAAC,EAAE,MAAM,GAAG,OAAO,CAO7C;AAID,OAAO,KAAK,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAE7E,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,gBAAgB,GAAG,aAAa,GAAG,IAAI,CAMlF;AAED,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,WAAW,EAAE,GAAG,MAAM,EAAE,CAKlE"}
@@ -0,0 +1,124 @@
1
+ /**
2
+ * commands 共享类型与工具
3
+ *
4
+ * 所有命令遵循同一签名:
5
+ * `handle(options): Promise<CommandResult>`
6
+ *
7
+ * `CommandResult.exitCode` 必须使用 phases/03-phase2-commands.md §"Exit Code
8
+ * 体系" 定义的统一编码。`stdout` / `stderr` 由 CLI wrapper 写入终端;测试
9
+ * 直接断言数组内容,无需 spawn 子进程。
10
+ */
11
+ import * as fs from 'node:fs';
12
+ import * as path from 'node:path';
13
+ export function ok(stdout = []) {
14
+ return { exitCode: 0, stdout, stderr: [] };
15
+ }
16
+ export function fail(exitCode, stderr, stdout = []) {
17
+ return { exitCode, stdout, stderr };
18
+ }
19
+ /**
20
+ * 检测目标目录是否已经 init(specdo/config.yaml 或 .yml 存在)。
21
+ *
22
+ * 不存在 → 返回 null;存在 → 返回绝对路径。
23
+ */
24
+ export function findSpecdoConfig(cwd) {
25
+ for (const candidate of ['specdo/config.yaml', 'specdo/config.yml']) {
26
+ const abs = path.join(cwd, candidate);
27
+ if (safeIsFile(abs))
28
+ return abs;
29
+ }
30
+ return null;
31
+ }
32
+ export function getSpecdoDir(cwd) {
33
+ return path.join(cwd, 'specdo');
34
+ }
35
+ export function getChangeDir(cwd, changeName) {
36
+ return path.join(cwd, 'specdo', 'changes', changeName);
37
+ }
38
+ export function getArchiveDir(cwd, changeName) {
39
+ return path.join(cwd, 'specdo', 'archive', changeName);
40
+ }
41
+ export function getSpecsDir(cwd) {
42
+ return path.join(cwd, 'specdo', 'specs');
43
+ }
44
+ const STOP_WORDS = new Set([
45
+ 'a', 'an', 'and', 'as', 'at', 'be', 'but', 'by', 'do', 'for', 'from', 'in', 'is', 'it', 'of',
46
+ 'on', 'or', 'so', 'the', 'to', 'with', 'add', 'fix', 'create', 'update', 'feature', 'change',
47
+ 'support', 'enable', 'allow',
48
+ ]);
49
+ /**
50
+ * 从用户的 idea 描述生成 change slug(kebab-case),最多 5 个有意义 token,
51
+ * 总长度 ≤ 50 字符。规则与 phases/03-phase2-commands.md §"Change 名称 slug
52
+ * 生成规则" 完全对齐。
53
+ *
54
+ * 失败:返回空字符串;调用方应转为 exit code 1 提示 "Cannot generate
55
+ * change name from input. Use --change <name>."
56
+ */
57
+ export function generateChangeSlug(idea) {
58
+ if (!idea || idea.trim().length === 0)
59
+ return '';
60
+ // 1. 转小写 + 非 ASCII 字符替换为空格
61
+ const ascii = idea.toLowerCase().replace(/[^\x20-\x7e]+/g, ' ');
62
+ // 2. 拆 token
63
+ const rawTokens = ascii.split(/[^a-z0-9]+/).filter(Boolean);
64
+ // 3. 过滤停用词;如果过滤后没有 token,回退为不过滤的列表
65
+ const filtered = rawTokens.filter((t) => !STOP_WORDS.has(t));
66
+ const tokens = filtered.length > 0 ? filtered : rawTokens;
67
+ // 4. 取前 5 个,连接
68
+ const joined = tokens.slice(0, 5).join('-');
69
+ if (!joined)
70
+ return '';
71
+ // 5. 仅保留 [a-z0-9-],去除连续/边缘 -
72
+ let slug = joined.replace(/[^a-z0-9-]+/g, '').replace(/-+/g, '-').replace(/^-+|-+$/g, '');
73
+ // 6. 截断 50 字符
74
+ if (slug.length > 50) {
75
+ slug = slug.slice(0, 50).replace(/-+$/, '');
76
+ }
77
+ return slug;
78
+ }
79
+ /** 用户提供的 --change 名称合规性校验 */
80
+ export function isValidChangeName(name) {
81
+ if (!name || name.length === 0 || name.length > 50)
82
+ return false;
83
+ return /^[a-z0-9][a-z0-9-]*[a-z0-9]$/.test(name) || /^[a-z0-9]$/.test(name);
84
+ }
85
+ export function safeIsFile(p) {
86
+ try {
87
+ return fs.statSync(p).isFile();
88
+ }
89
+ catch {
90
+ return false;
91
+ }
92
+ }
93
+ export function safeIsDir(p) {
94
+ try {
95
+ return fs.statSync(p).isDirectory();
96
+ }
97
+ catch {
98
+ return false;
99
+ }
100
+ }
101
+ export function safeExists(p) {
102
+ try {
103
+ fs.statSync(p);
104
+ return true;
105
+ }
106
+ catch {
107
+ return false;
108
+ }
109
+ }
110
+ export function failOnInvalidConfig(result) {
111
+ if (result.config && result.issues.length === 0)
112
+ return null;
113
+ const issues = result.issues.length > 0
114
+ ? result.issues
115
+ : [{ path: 'specdo/config.yaml', message: 'config could not be loaded' }];
116
+ return fail(1, renderConfigIssues(issues));
117
+ }
118
+ export function renderConfigIssues(issues) {
119
+ return [
120
+ 'Invalid specdo/config.yaml:',
121
+ ...issues.map((issue) => ` - ${issue.path}: ${issue.message}`),
122
+ ];
123
+ }
124
+ //# sourceMappingURL=_shared.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"_shared.js","sourceRoot":"","sources":["../../src/commands/_shared.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,30 @@
1
+ /**
2
+ * specdo apply [--change <name>] [--done N | --undo N] [--evidence "..."]
3
+ *
4
+ * 行为遵循 phases/03-phase2-commands.md §`apply`:
5
+ *
6
+ * - 仅展示当前简报(无 --done/--undo)
7
+ * - 标记任务完成:写入 tasks.md + tasksEvidence + 重新渲染 apply-brief.md
8
+ * - 取消任务完成:删除 evidence 行 + 同步 context
9
+ * - 全部完成时输出"All tasks complete (N/N)"
10
+ *
11
+ * 关键不变量:
12
+ * - tasks.md 是唯一事实来源;context.apply 由解析结果回填,不会自创
13
+ * - --done 与 --undo 互斥
14
+ * - --done 必须带非空 --evidence;--undo 不能带 --evidence
15
+ * - protocol(review-to-solid)注入条件:
16
+ * 1. ctx.propose.domainsUsed 含 'quality'
17
+ * 2. 或 当前任务在完整 resolved domains 中 scoreDomains 命中 quality
18
+ * 满足任一则注入;显式 trigger phrase 仅用于独立检测工具,不直接驱动 apply 注入
19
+ */
20
+ import { CommandResult } from './_shared.js';
21
+ export interface ApplyOptions {
22
+ cwd: string;
23
+ change?: string;
24
+ done?: string;
25
+ undo?: string;
26
+ evidence?: string;
27
+ now?: () => string;
28
+ }
29
+ export declare function handleApply(options: ApplyOptions): Promise<CommandResult>;
30
+ //# sourceMappingURL=apply.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"apply.d.ts","sourceRoot":"","sources":["../../src/commands/apply.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAsBH,OAAO,EACL,aAAa,EAQd,MAAM,cAAc,CAAC;AAEtB,MAAM,WAAW,YAAY;IAC3B,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;CACpB;AAED,wBAAsB,WAAW,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,aAAa,CAAC,CAuK/E"}
@@ -0,0 +1,393 @@
1
+ /**
2
+ * specdo apply [--change <name>] [--done N | --undo N] [--evidence "..."]
3
+ *
4
+ * 行为遵循 phases/03-phase2-commands.md §`apply`:
5
+ *
6
+ * - 仅展示当前简报(无 --done/--undo)
7
+ * - 标记任务完成:写入 tasks.md + tasksEvidence + 重新渲染 apply-brief.md
8
+ * - 取消任务完成:删除 evidence 行 + 同步 context
9
+ * - 全部完成时输出"All tasks complete (N/N)"
10
+ *
11
+ * 关键不变量:
12
+ * - tasks.md 是唯一事实来源;context.apply 由解析结果回填,不会自创
13
+ * - --done 与 --undo 互斥
14
+ * - --done 必须带非空 --evidence;--undo 不能带 --evidence
15
+ * - protocol(review-to-solid)注入条件:
16
+ * 1. ctx.propose.domainsUsed 含 'quality'
17
+ * 2. 或 当前任务在完整 resolved domains 中 scoreDomains 命中 quality
18
+ * 满足任一则注入;显式 trigger phrase 仅用于独立检测工具,不直接驱动 apply 注入
19
+ */
20
+ import * as fs from 'node:fs';
21
+ import * as path from 'node:path';
22
+ import { scoreDomains } from '../domains/index.js';
23
+ import { getProtocolByName } from '../protocols/index.js';
24
+ import { ContextStore } from '../core/context-store.js';
25
+ import { loadConfig, resolveDomains, } from '../core/config-store.js';
26
+ import { applyTaskMutation, findTaskByNumber, isCanonicalTaskReference, parseTasks, } from '../core/task-parser.js';
27
+ import { renderApplyBrief } from '../core/apply-brief-renderer.js';
28
+ import { fail, findSpecdoConfig, getChangeDir, isValidChangeName, safeExists, safeIsDir, failOnInvalidConfig, } from './_shared.js';
29
+ export async function handleApply(options) {
30
+ const { cwd } = options;
31
+ if (!findSpecdoConfig(cwd)) {
32
+ return fail(1, ["Not initialized. Run 'specdo init' first."]);
33
+ }
34
+ if (!options.change) {
35
+ return fail(1, ['apply requires --change <name>.']);
36
+ }
37
+ if (!isValidChangeName(options.change)) {
38
+ return fail(1, [`Invalid --change name: "${options.change}".`]);
39
+ }
40
+ if (options.done !== undefined && options.undo !== undefined) {
41
+ return fail(1, ['--done and --undo are mutually exclusive.']);
42
+ }
43
+ const changeName = options.change;
44
+ const changeDir = getChangeDir(cwd, changeName);
45
+ if (!safeIsDir(changeDir)) {
46
+ return fail(1, [
47
+ `Change directory not found: ${changeDir}.`,
48
+ `Run 'specdo explore' and 'specdo propose' first.`,
49
+ ]);
50
+ }
51
+ const tasksPath = path.join(changeDir, 'tasks.md');
52
+ if (!safeExists(tasksPath)) {
53
+ return fail(1, [
54
+ `tasks.md not found at ${tasksPath}.`,
55
+ `Run 'specdo propose --change ${changeName}' to generate the tasks template first.`,
56
+ ]);
57
+ }
58
+ const configResult = loadConfig(cwd);
59
+ const configFailure = failOnInvalidConfig(configResult);
60
+ if (configFailure)
61
+ return configFailure;
62
+ const resolvedAll = resolveDomains(configResult.config);
63
+ const now = options.now ?? (() => new Date().toISOString());
64
+ const store = new ContextStore({ changeDir, now });
65
+ const ctx = store.read();
66
+ let tasksContent;
67
+ try {
68
+ tasksContent = fs.readFileSync(tasksPath, 'utf-8');
69
+ }
70
+ catch (err) {
71
+ return toFilesystemFailure(`Failed to read tasks.md for change "${changeName}".`, err);
72
+ }
73
+ let parsed;
74
+ try {
75
+ parsed = parseTasks(tasksContent);
76
+ }
77
+ catch (err) {
78
+ return fail(1, [`Invalid tasks.md: ${err.message}`]);
79
+ }
80
+ const briefPath = path.join(changeDir, 'apply-brief.md');
81
+ const originalTasksContent = tasksContent;
82
+ let originalBrief;
83
+ try {
84
+ originalBrief = readOptionalFile(briefPath);
85
+ }
86
+ catch (err) {
87
+ return toFilesystemFailure(`Failed to inspect existing apply-brief.md for change "${changeName}".`, err);
88
+ }
89
+ const shouldRewriteTasks = options.done !== undefined || options.undo !== undefined;
90
+ // ─── 处理 --done ───
91
+ if (options.done !== undefined) {
92
+ const validation = validateDoneArgs(options, parsed.tasks);
93
+ if (validation)
94
+ return validation;
95
+ const target = findTaskByNumber(parsed, options.done);
96
+ tasksContent = applyTaskMutation(tasksContent, target, {
97
+ completed: true,
98
+ evidence: options.evidence ?? null,
99
+ });
100
+ try {
101
+ parsed = parseTasks(tasksContent);
102
+ }
103
+ catch (err) {
104
+ return fail(1, [`Invalid tasks.md after mutation: ${err.message}`]);
105
+ }
106
+ }
107
+ // ─── 处理 --undo ───
108
+ if (options.undo !== undefined) {
109
+ const validation = validateUndoArgs(options, parsed.tasks);
110
+ if (validation)
111
+ return validation;
112
+ const target = findTaskByNumber(parsed, options.undo);
113
+ tasksContent = applyTaskMutation(tasksContent, target, { completed: false, evidence: null });
114
+ try {
115
+ parsed = parseTasks(tasksContent);
116
+ }
117
+ catch (err) {
118
+ return fail(1, [`Invalid tasks.md after mutation: ${err.message}`]);
119
+ }
120
+ }
121
+ // ─── 计算当前任务 + 协议注入 ───
122
+ const completedCount = parsed.tasks.filter((t) => t.completed).length;
123
+ const currentTask = parsed.tasks.find((t) => !t.completed) ?? null;
124
+ const domains = pickDomainsForTask(resolvedAll, currentTask, ctx);
125
+ const protocol = pickProtocol(resolvedAll.map((r) => r.domain), currentTask, ctx);
126
+ // ─── 渲染并写 apply-brief.md ───
127
+ const brief = renderApplyBrief({
128
+ changeName,
129
+ domains,
130
+ protocol,
131
+ tasks: parsed.tasks,
132
+ currentTaskNumber: currentTask?.number ?? null,
133
+ generatedAt: now(),
134
+ });
135
+ // ─── 同步 context.apply ───
136
+ const allDone = parsed.tasks.length > 0 && completedCount === parsed.tasks.length;
137
+ const nextTasksEvidence = buildTasksEvidencePatch(ctx.apply?.tasksEvidence ?? {}, parsed.tasks);
138
+ const writeFailure = syncApplyArtifacts({
139
+ tasksPath,
140
+ tasksContent,
141
+ originalTasksContent,
142
+ shouldRewriteTasks,
143
+ briefPath,
144
+ briefContent: brief,
145
+ originalBrief,
146
+ store,
147
+ applyState: {
148
+ tasksTotal: parsed.tasks.length,
149
+ tasksCompleted: completedCount,
150
+ tasksEvidence: nextTasksEvidence,
151
+ applyBriefGenerated: true,
152
+ completedAt: allDone ? now() : null,
153
+ },
154
+ });
155
+ if (writeFailure)
156
+ return writeFailure;
157
+ // ─── 输出 ───
158
+ const stdout = [];
159
+ for (const w of parsed.warnings) {
160
+ stdout.push(`! ${w}`);
161
+ }
162
+ stdout.push(`# specdo apply --change ${changeName}`);
163
+ stdout.push('');
164
+ stdout.push(`Tasks: ${completedCount}/${parsed.tasks.length} complete`);
165
+ if (options.done !== undefined) {
166
+ stdout.push(`✓ Marked task ${options.done} done.`);
167
+ }
168
+ if (options.undo !== undefined) {
169
+ stdout.push(`✓ Reverted task ${options.undo} to incomplete (evidence cleared).`);
170
+ }
171
+ stdout.push('');
172
+ if (allDone) {
173
+ stdout.push(`All tasks complete (${completedCount}/${parsed.tasks.length}).`);
174
+ stdout.push(`Run 'specdo sync --change ${changeName}' then 'specdo archive --change ${changeName}' to finalize.`);
175
+ }
176
+ else if (currentTask) {
177
+ stdout.push(`Current focus: task ${currentTask.number}. ${currentTask.title}`);
178
+ stdout.push(`Brief written to ${path.relative(cwd, briefPath)}.`);
179
+ stdout.push('');
180
+ stdout.push(`Mark complete with: specdo apply --change ${changeName} --done ${currentTask.number} --evidence "<...>"`);
181
+ }
182
+ else if (parsed.tasks.length === 0) {
183
+ stdout.push('No tasks defined yet. Edit tasks.md to add `- [ ] 1.1 <title>` entries, then re-run apply.');
184
+ }
185
+ if (protocol) {
186
+ stdout.push('');
187
+ stdout.push(`Protocol injected: ${protocol.name}`);
188
+ }
189
+ return { exitCode: 0, stdout, stderr: [] };
190
+ }
191
+ // ─── helpers ────────────────────────────────────────────────────
192
+ function validateDoneArgs(options, tasks) {
193
+ const { done, evidence, undo } = options;
194
+ if (done === undefined)
195
+ return null;
196
+ if (undo !== undefined)
197
+ return fail(1, ['--done and --undo are mutually exclusive.']);
198
+ if (!isCanonicalTaskReference(done)) {
199
+ return fail(1, [`--done expects a task reference like "1" or "1.1"; got ${done}.`]);
200
+ }
201
+ if (tasks.length === 0) {
202
+ return fail(1, [`tasks.md has no parseable tasks; cannot mark ${done} done.`]);
203
+ }
204
+ const target = tasks.find((t) => t.number === done);
205
+ if (!target) {
206
+ return fail(1, [
207
+ `No task numbered ${done} in tasks.md.`,
208
+ `Available task refs include: ${tasks.slice(0, 6).map((t) => t.number).join(', ')}${tasks.length > 6 ? ', ...' : ''}`,
209
+ ]);
210
+ }
211
+ if (target.completed) {
212
+ return fail(1, [
213
+ `Task ${done} is already completed.`,
214
+ `Run 'specdo apply --change ${options.change} --undo ${done}' first to update its evidence.`,
215
+ ]);
216
+ }
217
+ if (evidence === undefined) {
218
+ return fail(1, ['--evidence is required when marking done. Provide a non-empty string.']);
219
+ }
220
+ if (typeof evidence !== 'string' || evidence.trim().length === 0) {
221
+ return fail(1, ['Evidence must be non-empty.']);
222
+ }
223
+ return null;
224
+ }
225
+ function validateUndoArgs(options, tasks) {
226
+ const { undo, evidence } = options;
227
+ if (undo === undefined)
228
+ return null;
229
+ if (evidence !== undefined) {
230
+ return fail(1, ['--evidence cannot be used with --undo. Use --done N --evidence "..." instead.']);
231
+ }
232
+ if (!isCanonicalTaskReference(undo)) {
233
+ return fail(1, [`--undo expects a task reference like "1" or "1.1"; got ${undo}.`]);
234
+ }
235
+ if (tasks.length === 0) {
236
+ return fail(1, [`tasks.md has no parseable tasks; cannot undo ${undo}.`]);
237
+ }
238
+ const target = tasks.find((t) => t.number === undo);
239
+ if (!target) {
240
+ return fail(1, [`No task numbered ${undo} in tasks.md.`]);
241
+ }
242
+ if (!target.completed) {
243
+ return fail(1, [`Task ${undo} is not completed; nothing to undo.`]);
244
+ }
245
+ return null;
246
+ }
247
+ function pickDomainsFromContext(resolvedAll, ctx) {
248
+ const byName = new Map(resolvedAll.map((r) => [r.domain.name, r.domain]));
249
+ const used = ctx?.propose?.domainsUsed;
250
+ if (!used || used.length === 0) {
251
+ return resolvedAll.map((r) => r.domain);
252
+ }
253
+ const out = [];
254
+ for (const name of used) {
255
+ const d = byName.get(name);
256
+ if (d)
257
+ out.push(d);
258
+ }
259
+ return out.length > 0 ? out : resolvedAll.map((r) => r.domain);
260
+ }
261
+ function pickDomainsForTask(resolvedAll, currentTask, ctx) {
262
+ if (!currentTask) {
263
+ return pickDomainsFromContext(resolvedAll, ctx);
264
+ }
265
+ const allDomains = resolvedAll.map((r) => r.domain);
266
+ const taskMatches = scoreDomains(currentTask.title, allDomains);
267
+ if (taskMatches.length === 0) {
268
+ return pickDomainsFromContext(resolvedAll, ctx);
269
+ }
270
+ const byName = new Map(resolvedAll.map((r) => [r.domain.name, r.domain]));
271
+ const out = [];
272
+ for (const match of taskMatches) {
273
+ const d = byName.get(match.name);
274
+ if (d)
275
+ out.push(d);
276
+ }
277
+ return out.length > 0 ? out : pickDomainsFromContext(resolvedAll, ctx);
278
+ }
279
+ function buildTasksEvidenceMap(tasks) {
280
+ const out = {};
281
+ for (const task of tasks) {
282
+ if (!task.completed)
283
+ continue;
284
+ if (!task.evidence || task.evidence.trim().length === 0)
285
+ continue;
286
+ out[String(task.number)] = task.evidence;
287
+ }
288
+ return out;
289
+ }
290
+ function buildTasksEvidencePatch(previous, tasks) {
291
+ const next = buildTasksEvidenceMap(tasks);
292
+ const patch = {};
293
+ for (const [key, value] of Object.entries(next)) {
294
+ patch[key] = value;
295
+ }
296
+ for (const key of Object.keys(previous)) {
297
+ if (!(key in next)) {
298
+ patch[key] = null;
299
+ }
300
+ }
301
+ return patch;
302
+ }
303
+ function syncApplyArtifacts(input) {
304
+ const rollbackSteps = [];
305
+ try {
306
+ if (input.shouldRewriteTasks) {
307
+ atomicWriteText(input.tasksPath, input.tasksContent);
308
+ rollbackSteps.push(() => {
309
+ atomicWriteText(input.tasksPath, input.originalTasksContent);
310
+ });
311
+ }
312
+ atomicWriteText(input.briefPath, input.briefContent);
313
+ rollbackSteps.push(() => {
314
+ restoreOptionalFile(input.briefPath, input.originalBrief);
315
+ });
316
+ input.store.writeDeep({
317
+ apply: input.applyState,
318
+ });
319
+ return null;
320
+ }
321
+ catch (err) {
322
+ const rollbackErrors = [];
323
+ for (let idx = rollbackSteps.length - 1; idx >= 0; idx--) {
324
+ try {
325
+ rollbackSteps[idx]?.();
326
+ }
327
+ catch (rollbackErr) {
328
+ rollbackErrors.push(rollbackErr.message);
329
+ }
330
+ }
331
+ return toFilesystemFailure('Failed to synchronize apply state.', err, rollbackErrors);
332
+ }
333
+ }
334
+ function atomicWriteText(targetPath, content) {
335
+ fs.mkdirSync(path.dirname(targetPath), { recursive: true });
336
+ const tmpPath = `${targetPath}.tmp-${process.pid}-${Date.now().toString(16)}`;
337
+ try {
338
+ fs.writeFileSync(tmpPath, content, 'utf-8');
339
+ fs.renameSync(tmpPath, targetPath);
340
+ }
341
+ finally {
342
+ try {
343
+ fs.rmSync(tmpPath, { force: true });
344
+ }
345
+ catch {
346
+ /* tmp cleanup is best-effort */
347
+ }
348
+ }
349
+ }
350
+ function readOptionalFile(filePath) {
351
+ try {
352
+ return { exists: true, content: fs.readFileSync(filePath, 'utf-8') };
353
+ }
354
+ catch (err) {
355
+ const code = err.code;
356
+ if (code === 'ENOENT')
357
+ return { exists: false, content: null };
358
+ throw err;
359
+ }
360
+ }
361
+ function restoreOptionalFile(filePath, state) {
362
+ if (!state.exists) {
363
+ fs.rmSync(filePath, { force: true });
364
+ return;
365
+ }
366
+ atomicWriteText(filePath, state.content ?? '');
367
+ }
368
+ function toFilesystemFailure(message, err, rollbackErrors = []) {
369
+ const detail = err instanceof Error ? err.message : String(err);
370
+ const stderr = [`${message} ${detail}`];
371
+ if (rollbackErrors.length > 0) {
372
+ stderr.push(`Rollback failed: ${rollbackErrors.join(' | ')}`);
373
+ }
374
+ stderr.push('This is treated as a filesystem reliability failure (exit code 3).');
375
+ return fail(3, stderr);
376
+ }
377
+ function pickProtocol(allResolvedDomains, currentTask, ctx) {
378
+ // 触发条件:
379
+ // 1. domainsUsed 含 quality
380
+ // 2. 当前任务 scoreDomains 命中 quality
381
+ const usedHasQuality = ctx?.propose?.domainsUsed?.includes('quality') ?? false;
382
+ let taskHitsQuality = false;
383
+ if (currentTask) {
384
+ const taskMatches = scoreDomains(currentTask.title, allResolvedDomains);
385
+ taskHitsQuality = taskMatches.some((m) => m.name === 'quality');
386
+ }
387
+ if (!usedHasQuality && !taskHitsQuality)
388
+ return null;
389
+ // 注入 review-to-solid(若可用);否则降级为 TDD(返回 null)
390
+ const protocol = getProtocolByName('review-to-solid');
391
+ return protocol ?? null;
392
+ }
393
+ //# sourceMappingURL=apply.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"apply.js","sourceRoot":"","sources":["../../src/commands/apply.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAClC,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAE1D,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AACxD,OAAO,EACL,UAAU,EACV,cAAc,GAEf,MAAM,yBAAyB,CAAC;AACjC,OAAO,EACL,iBAAiB,EACjB,gBAAgB,EAChB,wBAAwB,EACxB,UAAU,GAGX,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,gBAAgB,EAAE,MAAM,iCAAiC,CAAC;AACnE,OAAO,EAEL,IAAI,EACJ,gBAAgB,EAChB,YAAY,EACZ,iBAAiB,EACjB,UAAU,EACV,SAAS,EACT,mBAAmB,GACpB,MAAM,cAAc,CAAC;AAWtB,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,OAAqB;IACrD,MAAM,EAAE,GAAG,EAAE,GAAG,OAAO,CAAC;IAExB,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,EAAE,CAAC;QAC3B,OAAO,IAAI,CAAC,CAAC,EAAE,CAAC,2CAA2C,CAAC,CAAC,CAAC;IAChE,CAAC;IACD,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC;QACpB,OAAO,IAAI,CAAC,CAAC,EAAE,CAAC,iCAAiC,CAAC,CAAC,CAAC;IACtD,CAAC;IACD,IAAI,CAAC,iBAAiB,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;QACvC,OAAO,IAAI,CAAC,CAAC,EAAE,CAAC,2BAA2B,OAAO,CAAC,MAAM,IAAI,CAAC,CAAC,CAAC;IAClE,CAAC;IACD,IAAI,OAAO,CAAC,IAAI,KAAK,SAAS,IAAI,OAAO,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;QAC7D,OAAO,IAAI,CAAC,CAAC,EAAE,CAAC,2CAA2C,CAAC,CAAC,CAAC;IAChE,CAAC;IAED,MAAM,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC;IAClC,MAAM,SAAS,GAAG,YAAY,CAAC,GAAG,EAAE,UAAU,CAAC,CAAC;IAChD,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,EAAE,CAAC;QAC1B,OAAO,IAAI,CAAC,CAAC,EAAE;YACb,+BAA+B,SAAS,GAAG;YAC3C,kDAAkD;SACnD,CAAC,CAAC;IACL,CAAC;IAED,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,UAAU,CAAC,CAAC;IACnD,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;QAC3B,OAAO,IAAI,CAAC,CAAC,EAAE;YACb,yBAAyB,SAAS,GAAG;YACrC,gCAAgC,UAAU,yCAAyC;SACpF,CAAC,CAAC;IACL,CAAC;IACD,MAAM,YAAY,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC;IACrC,MAAM,aAAa,GAAG,mBAAmB,CAAC,YAAY,CAAC,CAAC;IACxD,IAAI,aAAa;QAAE,OAAO,aAAa,CAAC;IACxC,MAAM,WAAW,GAAG,cAAc,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC;IAExD,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,CAAC;IAC5D,MAAM,KAAK,GAAG,IAAI,YAAY,CAAC,EAAE,SAAS,EAAE,GAAG,EAAE,CAAC,CAAC;IACnD,MAAM,GAAG,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC;IAEzB,IAAI,YAAoB,CAAC;IACzB,IAAI,CAAC;QACH,YAAY,GAAG,EAAE,CAAC,YAAY,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;IACrD,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,mBAAmB,CAAC,uCAAuC,UAAU,IAAI,EAAE,GAAG,CAAC,CAAC;IACzF,CAAC;IAED,IAAI,MAAmB,CAAC;IACxB,IAAI,CAAC;QACH,MAAM,GAAG,UAAU,CAAC,YAAY,CAAC,CAAC;IACpC,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,IAAI,CAAC,CAAC,EAAE,CAAC,qBAAsB,GAAa,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;IAClE,CAAC;IAED,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,gBAAgB,CAAC,CAAC;IACzD,MAAM,oBAAoB,GAAG,YAAY,CAAC;IAC1C,IAAI,aAAgC,CAAC;IACrC,IAAI,CAAC;QACH,aAAa,GAAG,gBAAgB,CAAC,SAAS,CAAC,CAAC;IAC9C,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,mBAAmB,CAAC,yDAAyD,UAAU,IAAI,EAAE,GAAG,CAAC,CAAC;IAC3G,CAAC;IACD,MAAM,kBAAkB,GAAG,OAAO,CAAC,IAAI,KAAK,SAAS,IAAI,OAAO,CAAC,IAAI,KAAK,SAAS,CAAC;IAEpF,oBAAoB;IACpB,IAAI,OAAO,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;QAC/B,MAAM,UAAU,GAAG,gBAAgB,CAAC,OAAO,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC;QAC3D,IAAI,UAAU;YAAE,OAAO,UAAU,CAAC;QAClC,MAAM,MAAM,GAAG,gBAAgB,CAAC,MAAM,EAAE,OAAO,CAAC,IAAI,CAAe,CAAC;QACpE,YAAY,GAAG,iBAAiB,CAAC,YAAY,EAAE,MAAM,EAAE;YACrD,SAAS,EAAE,IAAI;YACf,QAAQ,EAAE,OAAO,CAAC,QAAQ,IAAI,IAAI;SACnC,CAAC,CAAC;QACH,IAAI,CAAC;YACH,MAAM,GAAG,UAAU,CAAC,YAAY,CAAC,CAAC;QACpC,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,IAAI,CAAC,CAAC,EAAE,CAAC,oCAAqC,GAAa,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;QACjF,CAAC;IACH,CAAC;IAED,oBAAoB;IACpB,IAAI,OAAO,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;QAC/B,MAAM,UAAU,GAAG,gBAAgB,CAAC,OAAO,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC;QAC3D,IAAI,UAAU;YAAE,OAAO,UAAU,CAAC;QAClC,MAAM,MAAM,GAAG,gBAAgB,CAAC,MAAM,EAAE,OAAO,CAAC,IAAI,CAAe,CAAC;QACpE,YAAY,GAAG,iBAAiB,CAAC,YAAY,EAAE,MAAM,EAAE,EAAE,SAAS,EAAE,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC;QAC7F,IAAI,CAAC;YACH,MAAM,GAAG,UAAU,CAAC,YAAY,CAAC,CAAC;QACpC,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,IAAI,CAAC,CAAC,EAAE,CAAC,oCAAqC,GAAa,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;QACjF,CAAC;IACH,CAAC;IAED,wBAAwB;IACxB,MAAM,cAAc,GAAG,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC;IACtE,MAAM,WAAW,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,IAAI,IAAI,CAAC;IAEnE,MAAM,OAAO,GAAG,kBAAkB,CAAC,WAAW,EAAE,WAAW,EAAE,GAAG,CAAC,CAAC;IAClE,MAAM,QAAQ,GAAG,YAAY,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,WAAW,EAAE,GAAG,CAAC,CAAC;IAElF,8BAA8B;IAC9B,MAAM,KAAK,GAAG,gBAAgB,CAAC;QAC7B,UAAU;QACV,OAAO;QACP,QAAQ;QACR,KAAK,EAAE,MAAM,CAAC,KAAK;QACnB,iBAAiB,EAAE,WAAW,EAAE,MAAM,IAAI,IAAI;QAC9C,WAAW,EAAE,GAAG,EAAE;KACnB,CAAC,CAAC;IAEH,2BAA2B;IAC3B,MAAM,OAAO,GAAG,MAAM,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,IAAI,cAAc,KAAK,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC;IAClF,MAAM,iBAAiB,GAAG,uBAAuB,CAAC,GAAG,CAAC,KAAK,EAAE,aAAa,IAAI,EAAE,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC;IAEhG,MAAM,YAAY,GAAG,kBAAkB,CAAC;QACtC,SAAS;QACT,YAAY;QACZ,oBAAoB;QACpB,kBAAkB;QAClB,SAAS;QACT,YAAY,EAAE,KAAK;QACnB,aAAa;QACb,KAAK;QACL,UAAU,EAAE;YACV,UAAU,EAAE,MAAM,CAAC,KAAK,CAAC,MAAM;YAC/B,cAAc,EAAE,cAAc;YAC9B,aAAa,EAAE,iBAAiB;YAChC,mBAAmB,EAAE,IAAI;YACzB,WAAW,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,IAAI;SACpC;KACF,CAAC,CAAC;IACH,IAAI,YAAY;QAAE,OAAO,YAAY,CAAC;IAEtC,aAAa;IACb,MAAM,MAAM,GAAa,EAAE,CAAC;IAC5B,KAAK,MAAM,CAAC,IAAI,MAAM,CAAC,QAAQ,EAAE,CAAC;QAChC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IACxB,CAAC;IACD,MAAM,CAAC,IAAI,CAAC,2BAA2B,UAAU,EAAE,CAAC,CAAC;IACrD,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAChB,MAAM,CAAC,IAAI,CAAC,UAAU,cAAc,IAAI,MAAM,CAAC,KAAK,CAAC,MAAM,WAAW,CAAC,CAAC;IACxE,IAAI,OAAO,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;QAC/B,MAAM,CAAC,IAAI,CAAC,iBAAiB,OAAO,CAAC,IAAI,QAAQ,CAAC,CAAC;IACrD,CAAC;IACD,IAAI,OAAO,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;QAC/B,MAAM,CAAC,IAAI,CAAC,mBAAmB,OAAO,CAAC,IAAI,oCAAoC,CAAC,CAAC;IACnF,CAAC;IACD,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAChB,IAAI,OAAO,EAAE,CAAC;QACZ,MAAM,CAAC,IAAI,CAAC,uBAAuB,cAAc,IAAI,MAAM,CAAC,KAAK,CAAC,MAAM,IAAI,CAAC,CAAC;QAC9E,MAAM,CAAC,IAAI,CAAC,6BAA6B,UAAU,mCAAmC,UAAU,gBAAgB,CAAC,CAAC;IACpH,CAAC;SAAM,IAAI,WAAW,EAAE,CAAC;QACvB,MAAM,CAAC,IAAI,CAAC,uBAAuB,WAAW,CAAC,MAAM,KAAK,WAAW,CAAC,KAAK,EAAE,CAAC,CAAC;QAC/E,MAAM,CAAC,IAAI,CAAC,oBAAoB,IAAI,CAAC,QAAQ,CAAC,GAAG,EAAE,SAAS,CAAC,GAAG,CAAC,CAAC;QAClE,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAChB,MAAM,CAAC,IAAI,CACT,6CAA6C,UAAU,WAAW,WAAW,CAAC,MAAM,qBAAqB,CAC1G,CAAC;IACJ,CAAC;SAAM,IAAI,MAAM,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACrC,MAAM,CAAC,IAAI,CAAC,4FAA4F,CAAC,CAAC;IAC5G,CAAC;IACD,IAAI,QAAQ,EAAE,CAAC;QACb,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAChB,MAAM,CAAC,IAAI,CAAC,sBAAsB,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC;IACrD,CAAC;IACD,OAAO,EAAE,QAAQ,EAAE,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC;AAC7C,CAAC;AAED,mEAAmE;AAEnE,SAAS,gBAAgB,CAAC,OAAqB,EAAE,KAAmB;IAClE,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,GAAG,OAAO,CAAC;IACzC,IAAI,IAAI,KAAK,SAAS;QAAE,OAAO,IAAI,CAAC;IACpC,IAAI,IAAI,KAAK,SAAS;QAAE,OAAO,IAAI,CAAC,CAAC,EAAE,CAAC,2CAA2C,CAAC,CAAC,CAAC;IACtF,IAAI,CAAC,wBAAwB,CAAC,IAAI,CAAC,EAAE,CAAC;QACpC,OAAO,IAAI,CAAC,CAAC,EAAE,CAAC,0DAA0D,IAAI,GAAG,CAAC,CAAC,CAAC;IACtF,CAAC;IACD,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACvB,OAAO,IAAI,CAAC,CAAC,EAAE,CAAC,gDAAgD,IAAI,QAAQ,CAAC,CAAC,CAAC;IACjF,CAAC;IACD,MAAM,MAAM,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,IAAI,CAAC,CAAC;IACpD,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,OAAO,IAAI,CAAC,CAAC,EAAE;YACb,oBAAoB,IAAI,eAAe;YACvC,gCAAgC,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE;SACtH,CAAC,CAAC;IACL,CAAC;IACD,IAAI,MAAM,CAAC,SAAS,EAAE,CAAC;QACrB,OAAO,IAAI,CAAC,CAAC,EAAE;YACb,QAAQ,IAAI,wBAAwB;YACpC,8BAA8B,OAAO,CAAC,MAAM,WAAW,IAAI,iCAAiC;SAC7F,CAAC,CAAC;IACL,CAAC;IACD,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;QAC3B,OAAO,IAAI,CAAC,CAAC,EAAE,CAAC,uEAAuE,CAAC,CAAC,CAAC;IAC5F,CAAC;IACD,IAAI,OAAO,QAAQ,KAAK,QAAQ,IAAI,QAAQ,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACjE,OAAO,IAAI,CAAC,CAAC,EAAE,CAAC,6BAA6B,CAAC,CAAC,CAAC;IAClD,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,SAAS,gBAAgB,CAAC,OAAqB,EAAE,KAAmB;IAClE,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,OAAO,CAAC;IACnC,IAAI,IAAI,KAAK,SAAS;QAAE,OAAO,IAAI,CAAC;IACpC,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;QAC3B,OAAO,IAAI,CAAC,CAAC,EAAE,CAAC,+EAA+E,CAAC,CAAC,CAAC;IACpG,CAAC;IACD,IAAI,CAAC,wBAAwB,CAAC,IAAI,CAAC,EAAE,CAAC;QACpC,OAAO,IAAI,CAAC,CAAC,EAAE,CAAC,0DAA0D,IAAI,GAAG,CAAC,CAAC,CAAC;IACtF,CAAC;IACD,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACvB,OAAO,IAAI,CAAC,CAAC,EAAE,CAAC,gDAAgD,IAAI,GAAG,CAAC,CAAC,CAAC;IAC5E,CAAC;IACD,MAAM,MAAM,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,IAAI,CAAC,CAAC;IACpD,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,OAAO,IAAI,CAAC,CAAC,EAAE,CAAC,oBAAoB,IAAI,eAAe,CAAC,CAAC,CAAC;IAC5D,CAAC;IACD,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC;QACtB,OAAO,IAAI,CAAC,CAAC,EAAE,CAAC,QAAQ,IAAI,qCAAqC,CAAC,CAAC,CAAC;IACtE,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,SAAS,sBAAsB,CAC7B,WAA6B,EAC7B,GAAyD;IAEzD,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;IAC1E,MAAM,IAAI,GAAG,GAAG,EAAE,OAAO,EAAE,WAAW,CAAC;IACvC,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC/B,OAAO,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;IAC1C,CAAC;IACD,MAAM,GAAG,GAAmB,EAAE,CAAC;IAC/B,KAAK,MAAM,IAAI,IAAI,IAAI,EAAE,CAAC;QACxB,MAAM,CAAC,GAAG,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAC3B,IAAI,CAAC;YAAE,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACrB,CAAC;IACD,OAAO,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;AACjE,CAAC;AAED,SAAS,kBAAkB,CACzB,WAA6B,EAC7B,WAA8B,EAC9B,GAAyD;IAEzD,IAAI,CAAC,WAAW,EAAE,CAAC;QACjB,OAAO,sBAAsB,CAAC,WAAW,EAAE,GAAG,CAAC,CAAC;IAClD,CAAC;IACD,MAAM,UAAU,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;IACpD,MAAM,WAAW,GAAG,YAAY,CAAC,WAAW,CAAC,KAAK,EAAE,UAAU,CAAC,CAAC;IAChE,IAAI,WAAW,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC7B,OAAO,sBAAsB,CAAC,WAAW,EAAE,GAAG,CAAC,CAAC;IAClD,CAAC;IACD,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;IAC1E,MAAM,GAAG,GAAmB,EAAE,CAAC;IAC/B,KAAK,MAAM,KAAK,IAAI,WAAW,EAAE,CAAC;QAChC,MAAM,CAAC,GAAG,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QACjC,IAAI,CAAC;YAAE,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACrB,CAAC;IACD,OAAO,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,sBAAsB,CAAC,WAAW,EAAE,GAAG,CAAC,CAAC;AACzE,CAAC;AAED,SAAS,qBAAqB,CAAC,KAAmB;IAChD,MAAM,GAAG,GAA2B,EAAE,CAAC;IACvC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,CAAC,IAAI,CAAC,SAAS;YAAE,SAAS;QAC9B,IAAI,CAAC,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC;YAAE,SAAS;QAClE,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC;IAC3C,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,SAAS,uBAAuB,CAC9B,QAAgC,EAChC,KAAmB;IAEnB,MAAM,IAAI,GAAG,qBAAqB,CAAC,KAAK,CAAC,CAAC;IAC1C,MAAM,KAAK,GAAkC,EAAE,CAAC;IAEhD,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;QAChD,KAAK,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;IACrB,CAAC;IACD,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC;QACxC,IAAI,CAAC,CAAC,GAAG,IAAI,IAAI,CAAC,EAAE,CAAC;YACnB,KAAK,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC;QACpB,CAAC;IACH,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC;AAED,SAAS,kBAAkB,CAAC,KAgB3B;IACC,MAAM,aAAa,GAAsB,EAAE,CAAC;IAE5C,IAAI,CAAC;QACH,IAAI,KAAK,CAAC,kBAAkB,EAAE,CAAC;YAC7B,eAAe,CAAC,KAAK,CAAC,SAAS,EAAE,KAAK,CAAC,YAAY,CAAC,CAAC;YACrD,aAAa,CAAC,IAAI,CAAC,GAAG,EAAE;gBACtB,eAAe,CAAC,KAAK,CAAC,SAAS,EAAE,KAAK,CAAC,oBAAoB,CAAC,CAAC;YAC/D,CAAC,CAAC,CAAC;QACL,CAAC;QAED,eAAe,CAAC,KAAK,CAAC,SAAS,EAAE,KAAK,CAAC,YAAY,CAAC,CAAC;QACrD,aAAa,CAAC,IAAI,CAAC,GAAG,EAAE;YACtB,mBAAmB,CAAC,KAAK,CAAC,SAAS,EAAE,KAAK,CAAC,aAAa,CAAC,CAAC;QAC5D,CAAC,CAAC,CAAC;QAEH,KAAK,CAAC,KAAK,CAAC,SAAS,CAAC;YACpB,KAAK,EAAE,KAAK,CAAC,UAAU;SACxB,CAAC,CAAC;QAEH,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,cAAc,GAAa,EAAE,CAAC;QACpC,KAAK,IAAI,GAAG,GAAG,aAAa,CAAC,MAAM,GAAG,CAAC,EAAE,GAAG,IAAI,CAAC,EAAE,GAAG,EAAE,EAAE,CAAC;YACzD,IAAI,CAAC;gBACH,aAAa,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;YACzB,CAAC;YAAC,OAAO,WAAW,EAAE,CAAC;gBACrB,cAAc,CAAC,IAAI,CAAE,WAAqB,CAAC,OAAO,CAAC,CAAC;YACtD,CAAC;QACH,CAAC;QACD,OAAO,mBAAmB,CAAC,oCAAoC,EAAE,GAAG,EAAE,cAAc,CAAC,CAAC;IACxF,CAAC;AACH,CAAC;AAED,SAAS,eAAe,CAAC,UAAkB,EAAE,OAAe;IAC1D,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC5D,MAAM,OAAO,GAAG,GAAG,UAAU,QAAQ,OAAO,CAAC,GAAG,IAAI,IAAI,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,EAAE,CAAC;IAC9E,IAAI,CAAC;QACH,EAAE,CAAC,aAAa,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;QAC5C,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC;IACrC,CAAC;YAAS,CAAC;QACT,IAAI,CAAC;YACH,EAAE,CAAC,MAAM,CAAC,OAAO,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;QACtC,CAAC;QAAC,MAAM,CAAC;YACP,gCAAgC;QAClC,CAAC;IACH,CAAC;AACH,CAAC;AAOD,SAAS,gBAAgB,CAAC,QAAgB;IACxC,IAAI,CAAC;QACH,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE,CAAC,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,EAAE,CAAC;IACvE,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,IAAI,GAAI,GAA6B,CAAC,IAAI,CAAC;QACjD,IAAI,IAAI,KAAK,QAAQ;YAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;QAC/D,MAAM,GAAG,CAAC;IACZ,CAAC;AACH,CAAC;AAED,SAAS,mBAAmB,CAAC,QAAgB,EAAE,KAAwB;IACrE,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC;QAClB,EAAE,CAAC,MAAM,CAAC,QAAQ,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;QACrC,OAAO;IACT,CAAC;IACD,eAAe,CAAC,QAAQ,EAAE,KAAK,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC;AACjD,CAAC;AAED,SAAS,mBAAmB,CAAC,OAAe,EAAE,GAAY,EAAE,iBAA2B,EAAE;IACvF,MAAM,MAAM,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IAChE,MAAM,MAAM,GAAG,CAAC,GAAG,OAAO,IAAI,MAAM,EAAE,CAAC,CAAC;IACxC,IAAI,cAAc,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC9B,MAAM,CAAC,IAAI,CAAC,oBAAoB,cAAc,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IAChE,CAAC;IACD,MAAM,CAAC,IAAI,CAAC,oEAAoE,CAAC,CAAC;IAClF,OAAO,IAAI,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;AACzB,CAAC;AAED,SAAS,YAAY,CACnB,kBAAkC,EAClC,WAA8B,EAC9B,GAAyD;IAEzD,QAAQ;IACR,6BAA6B;IAC7B,oCAAoC;IACpC,MAAM,cAAc,GAAG,GAAG,EAAE,OAAO,EAAE,WAAW,EAAE,QAAQ,CAAC,SAAS,CAAC,IAAI,KAAK,CAAC;IAC/E,IAAI,eAAe,GAAG,KAAK,CAAC;IAC5B,IAAI,WAAW,EAAE,CAAC;QAChB,MAAM,WAAW,GAAG,YAAY,CAAC,WAAW,CAAC,KAAK,EAAE,kBAAkB,CAAC,CAAC;QACxE,eAAe,GAAG,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC;IAClE,CAAC;IACD,IAAI,CAAC,cAAc,IAAI,CAAC,eAAe;QAAE,OAAO,IAAI,CAAC;IACrD,6CAA6C;IAC7C,MAAM,QAAQ,GAAG,iBAAiB,CAAC,iBAAiB,CAAC,CAAC;IACtD,OAAO,QAAQ,IAAI,IAAI,CAAC;AAC1B,CAAC"}
@@ -0,0 +1,25 @@
1
+ /**
2
+ * specdo archive [--change <name>] [--skip-sync-check]
3
+ *
4
+ * 行为:
5
+ * 1. 必须 init;--change 必需
6
+ * 2. 检查 tasks 全部完成 + 每个完成任务有 evidence
7
+ * 3. 实时只读检查当前 changes/<name>/specs 与 specdo/specs 的同步状态
8
+ * - 只要存在 added / conflict → 始终失败(即使 --skip-sync-check)
9
+ * - sync 未运行 → 失败(除非 --skip-sync-check)
10
+ * - sync.completedAt = null → 失败(除非 --skip-sync-check)
11
+ * 4. same-filesystem rename: changes/<name>/ → archive/<name>/
12
+ * 5. 在 archive 目录内写 archive-summary.md 与 context.archive 元数据
13
+ * - rename 失败 EXDEV → exit 3
14
+ * - 目标已存在 → exit 1
15
+ * - 元数据写入失败 → 尝试回滚 rename,避免 active change 脏状态
16
+ */
17
+ import { CommandResult } from './_shared.js';
18
+ export interface ArchiveOptions {
19
+ cwd: string;
20
+ change?: string;
21
+ skipSyncCheck?: boolean;
22
+ now?: () => string;
23
+ }
24
+ export declare function handleArchive(options: ArchiveOptions): Promise<CommandResult>;
25
+ //# sourceMappingURL=archive.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"archive.d.ts","sourceRoot":"","sources":["../../src/commands/archive.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAUH,OAAO,EACL,aAAa,EASd,MAAM,cAAc,CAAC;AAEtB,MAAM,WAAW,cAAc;IAC7B,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;CACpB;AAED,wBAAsB,aAAa,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,aAAa,CAAC,CAkOnF"}