@dedesfr/prompter 0.8.23 → 1.0.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 (247) hide show
  1. package/CHANGELOG.md +70 -0
  2. package/README.md +105 -77
  3. package/dist/cli/index.js +25 -1
  4. package/dist/cli/index.js.map +1 -1
  5. package/dist/commands/init.d.ts +1 -7
  6. package/dist/commands/init.d.ts.map +1 -1
  7. package/dist/commands/init.js +60 -299
  8. package/dist/commands/init.js.map +1 -1
  9. package/dist/commands/login.d.ts +4 -0
  10. package/dist/commands/login.d.ts.map +1 -0
  11. package/dist/commands/login.js +56 -0
  12. package/dist/commands/login.js.map +1 -0
  13. package/dist/commands/logout.d.ts +4 -0
  14. package/dist/commands/logout.d.ts.map +1 -0
  15. package/dist/commands/logout.js +14 -0
  16. package/dist/commands/logout.js.map +1 -0
  17. package/dist/commands/update.d.ts.map +1 -1
  18. package/dist/commands/update.js +31 -41
  19. package/dist/commands/update.js.map +1 -1
  20. package/dist/commands/whoami.d.ts +4 -0
  21. package/dist/commands/whoami.d.ts.map +1 -0
  22. package/dist/commands/whoami.js +42 -0
  23. package/dist/commands/whoami.js.map +1 -0
  24. package/dist/core/auth-store.d.ts +10 -0
  25. package/dist/core/auth-store.d.ts.map +1 -0
  26. package/dist/core/auth-store.js +39 -0
  27. package/dist/core/auth-store.js.map +1 -0
  28. package/dist/core/configurators/slash/antigravity.d.ts +2 -5
  29. package/dist/core/configurators/slash/antigravity.d.ts.map +1 -1
  30. package/dist/core/configurators/slash/antigravity.js +2 -57
  31. package/dist/core/configurators/slash/antigravity.js.map +1 -1
  32. package/dist/core/configurators/slash/base.d.ts +6 -18
  33. package/dist/core/configurators/slash/base.d.ts.map +1 -1
  34. package/dist/core/configurators/slash/base.js +8 -77
  35. package/dist/core/configurators/slash/base.js.map +1 -1
  36. package/dist/core/configurators/slash/claude.d.ts +2 -5
  37. package/dist/core/configurators/slash/claude.d.ts.map +1 -1
  38. package/dist/core/configurators/slash/claude.js +2 -57
  39. package/dist/core/configurators/slash/claude.js.map +1 -1
  40. package/dist/core/configurators/slash/codex.d.ts +2 -5
  41. package/dist/core/configurators/slash/codex.d.ts.map +1 -1
  42. package/dist/core/configurators/slash/codex.js +2 -57
  43. package/dist/core/configurators/slash/codex.js.map +1 -1
  44. package/dist/core/configurators/slash/droid.d.ts +2 -5
  45. package/dist/core/configurators/slash/droid.d.ts.map +1 -1
  46. package/dist/core/configurators/slash/droid.js +2 -32
  47. package/dist/core/configurators/slash/droid.js.map +1 -1
  48. package/dist/core/configurators/slash/forge.d.ts +2 -5
  49. package/dist/core/configurators/slash/forge.d.ts.map +1 -1
  50. package/dist/core/configurators/slash/forge.js +2 -32
  51. package/dist/core/configurators/slash/forge.js.map +1 -1
  52. package/dist/core/configurators/slash/github-copilot.d.ts +2 -7
  53. package/dist/core/configurators/slash/github-copilot.d.ts.map +1 -1
  54. package/dist/core/configurators/slash/github-copilot.js +2 -96
  55. package/dist/core/configurators/slash/github-copilot.js.map +1 -1
  56. package/dist/core/configurators/slash/index.d.ts +1 -1
  57. package/dist/core/configurators/slash/index.d.ts.map +1 -1
  58. package/dist/core/configurators/slash/index.js +1 -1
  59. package/dist/core/configurators/slash/index.js.map +1 -1
  60. package/dist/core/configurators/slash/kilocode.d.ts +2 -5
  61. package/dist/core/configurators/slash/kilocode.d.ts.map +1 -1
  62. package/dist/core/configurators/slash/kilocode.js +2 -57
  63. package/dist/core/configurators/slash/kilocode.js.map +1 -1
  64. package/dist/core/configurators/slash/opencode.d.ts +2 -5
  65. package/dist/core/configurators/slash/opencode.d.ts.map +1 -1
  66. package/dist/core/configurators/slash/opencode.js +2 -57
  67. package/dist/core/configurators/slash/opencode.js.map +1 -1
  68. package/dist/core/configurators/slash/registry.d.ts +4 -4
  69. package/dist/core/configurators/slash/registry.d.ts.map +1 -1
  70. package/dist/core/configurators/slash/registry.js.map +1 -1
  71. package/dist/core/registry.d.ts +18 -0
  72. package/dist/core/registry.d.ts.map +1 -0
  73. package/dist/core/registry.js +94 -0
  74. package/dist/core/registry.js.map +1 -0
  75. package/dist/core/templates/index.d.ts +0 -1
  76. package/dist/core/templates/index.d.ts.map +1 -1
  77. package/dist/core/templates/index.js +0 -1
  78. package/dist/core/templates/index.js.map +1 -1
  79. package/package.json +7 -1
  80. package/AGENTS.md +0 -123
  81. package/CLAUDE.md +0 -17
  82. package/build.js +0 -20
  83. package/convex-setup.md +0 -403
  84. package/dist/core/templates/slash-command-templates.d.ts +0 -7
  85. package/dist/core/templates/slash-command-templates.d.ts.map +0 -1
  86. package/dist/core/templates/slash-command-templates.js +0 -1041
  87. package/dist/core/templates/slash-command-templates.js.map +0 -1
  88. package/prompt/ai-humanizer.md +0 -45
  89. package/prompt/api-contract-generator.md +0 -234
  90. package/prompt/apply.md +0 -17
  91. package/prompt/archive.md +0 -21
  92. package/prompt/design-system.md +0 -210
  93. package/prompt/document-explainer.md +0 -149
  94. package/prompt/epic-generator.md +0 -198
  95. package/prompt/epic-single.md +0 -47
  96. package/prompt/erd-generator.md +0 -130
  97. package/prompt/fsd-generator.md +0 -157
  98. package/prompt/prd-agent-generator.md +0 -147
  99. package/prompt/prd-generator.md +0 -195
  100. package/prompt/product-brief.md +0 -289
  101. package/prompt/proposal.md +0 -22
  102. package/prompt/qa-test-scenario.md +0 -133
  103. package/prompt/skill-creator.md +0 -350
  104. package/prompt/story-generator.md +0 -278
  105. package/prompt/story-single.md +0 -70
  106. package/prompt/tdd-generator.md +0 -294
  107. package/prompt/tdd-lite-generator.md +0 -224
  108. package/prompt/wireframe-generator.md +0 -219
  109. package/skills/ai-context-generator/SKILL.md +0 -54
  110. package/skills/ai-context-generator/references/AGENTS.template.md +0 -83
  111. package/skills/ai-context-generator/references/CLAUDE.template.md +0 -39
  112. package/skills/ai-context-generator/references/behavioral-guidelines.md +0 -71
  113. package/skills/ai-context-generator/references/discovery-checklist.md +0 -40
  114. package/skills/ai-context-generator/references/examples/AGENTS.good.md +0 -103
  115. package/skills/ai-context-generator/references/extraction-checklist.md +0 -23
  116. package/skills/ai-context-generator/references/overlays/laravel.md +0 -44
  117. package/skills/cerebro/SKILL.md +0 -187
  118. package/skills/cerebro/references/agents.md +0 -213
  119. package/skills/code-review/SKILL.md +0 -373
  120. package/skills/code-review/assets/report-template-agent.md +0 -212
  121. package/skills/code-review/assets/report-template-compact.md +0 -81
  122. package/skills/code-review/assets/report-template-full.md +0 -264
  123. package/skills/code-review/assets/report-template-human.md +0 -168
  124. package/skills/code-review/references/universal-patterns.md +0 -495
  125. package/skills/design-md/README.md +0 -34
  126. package/skills/design-md/SKILL.md +0 -172
  127. package/skills/design-md/examples/DESIGN.md +0 -154
  128. package/skills/design-system-generator/SKILL.md +0 -324
  129. package/skills/design-system-generator/assets/design-system-template.md +0 -348
  130. package/skills/design-system-generator/references/extraction-patterns.md +0 -321
  131. package/skills/doc-builder/SKILL.md +0 -115
  132. package/skills/doc-builder/references/ui-patterns.md +0 -394
  133. package/skills/document-translator/SKILL.md +0 -58
  134. package/skills/enhance-prompt/README.md +0 -34
  135. package/skills/enhance-prompt/SKILL.md +0 -204
  136. package/skills/enhance-prompt/references/KEYWORDS.md +0 -114
  137. package/skills/feature-planner/SKILL.md +0 -305
  138. package/skills/feature-planner/assets/implementation-plan-template.md +0 -85
  139. package/skills/frontend-design/LICENSE.txt +0 -177
  140. package/skills/frontend-design/SKILL.md +0 -42
  141. package/skills/gamma-builder/SKILL.md +0 -134
  142. package/skills/laravel-code-review/SKILL.md +0 -383
  143. package/skills/laravel-code-review/assets/report-template-agent.md +0 -195
  144. package/skills/laravel-code-review/assets/report-template-compact.md +0 -79
  145. package/skills/laravel-code-review/assets/report-template-full.md +0 -253
  146. package/skills/laravel-code-review/assets/report-template-human.md +0 -159
  147. package/skills/laravel-code-review/references/laravel-patterns.md +0 -571
  148. package/skills/laravel-code-review/references/php84-features.md +0 -442
  149. package/skills/mcp-builder/LICENSE.txt +0 -202
  150. package/skills/mcp-builder/SKILL.md +0 -236
  151. package/skills/mcp-builder/reference/evaluation.md +0 -602
  152. package/skills/mcp-builder/reference/mcp_best_practices.md +0 -249
  153. package/skills/mcp-builder/reference/node_mcp_server.md +0 -970
  154. package/skills/mcp-builder/reference/python_mcp_server.md +0 -719
  155. package/skills/mcp-builder/scripts/connections.py +0 -151
  156. package/skills/mcp-builder/scripts/evaluation.py +0 -373
  157. package/skills/mcp-builder/scripts/example_evaluation.xml +0 -22
  158. package/skills/mcp-builder/scripts/requirements.txt +0 -2
  159. package/skills/meeting-notes/SKILL.md +0 -159
  160. package/skills/meeting-notes/evals/evals.json +0 -23
  161. package/skills/project-orchestrator/SKILL.md +0 -487
  162. package/skills/project-orchestrator/assets/caddy-vps-setup.md +0 -180
  163. package/skills/project-orchestrator/assets/plan-summary-template.md +0 -159
  164. package/skills/prompter-specs/SKILL.md +0 -115
  165. package/skills/prompter-workflow/SKILL.md +0 -166
  166. package/skills/prompter-workflow/evals/evals.json +0 -89
  167. package/skills/sph-generator/SKILL.md +0 -488
  168. package/skills/ui-ux-pro/SKILL.md +0 -199
  169. package/skills/ui-ux-pro/assets/design-spec-template.md +0 -173
  170. package/skills/ui-ux-pro/references/component-patterns.md +0 -255
  171. package/skills/ui-ux-pro/references/design-principles.md +0 -167
  172. package/src/cli/index.ts +0 -223
  173. package/src/commands/archive.ts +0 -302
  174. package/src/commands/change.ts +0 -292
  175. package/src/commands/config.ts +0 -233
  176. package/src/commands/guide.ts +0 -50
  177. package/src/commands/init.ts +0 -899
  178. package/src/commands/list.ts +0 -194
  179. package/src/commands/show.ts +0 -138
  180. package/src/commands/spec.ts +0 -251
  181. package/src/commands/update.ts +0 -156
  182. package/src/commands/upgrade.ts +0 -30
  183. package/src/commands/validate.ts +0 -326
  184. package/src/core/artifact-graph/graph.ts +0 -167
  185. package/src/core/artifact-graph/index.ts +0 -44
  186. package/src/core/artifact-graph/instruction-loader.ts +0 -302
  187. package/src/core/artifact-graph/resolver.ts +0 -226
  188. package/src/core/artifact-graph/schema.ts +0 -124
  189. package/src/core/artifact-graph/state.ts +0 -64
  190. package/src/core/artifact-graph/types.ts +0 -65
  191. package/src/core/completions/command-registry.ts +0 -382
  192. package/src/core/completions/completion-provider.ts +0 -128
  193. package/src/core/completions/generators/bash-generator.ts +0 -191
  194. package/src/core/completions/generators/fish-generator.ts +0 -188
  195. package/src/core/completions/generators/powershell-generator.ts +0 -223
  196. package/src/core/completions/generators/zsh-generator.ts +0 -281
  197. package/src/core/completions/templates/bash-templates.ts +0 -24
  198. package/src/core/completions/templates/fish-templates.ts +0 -40
  199. package/src/core/completions/templates/powershell-templates.ts +0 -25
  200. package/src/core/completions/templates/zsh-templates.ts +0 -36
  201. package/src/core/completions/types.ts +0 -90
  202. package/src/core/config-schema.ts +0 -230
  203. package/src/core/config.ts +0 -181
  204. package/src/core/configurators/slash/antigravity.ts +0 -70
  205. package/src/core/configurators/slash/base.ts +0 -203
  206. package/src/core/configurators/slash/claude.ts +0 -70
  207. package/src/core/configurators/slash/codex.ts +0 -70
  208. package/src/core/configurators/slash/droid.ts +0 -44
  209. package/src/core/configurators/slash/forge.ts +0 -44
  210. package/src/core/configurators/slash/github-copilot.ts +0 -114
  211. package/src/core/configurators/slash/index.ts +0 -10
  212. package/src/core/configurators/slash/kilocode.ts +0 -70
  213. package/src/core/configurators/slash/opencode.ts +0 -70
  214. package/src/core/configurators/slash/registry.ts +0 -51
  215. package/src/core/converters/json-converter.ts +0 -62
  216. package/src/core/global-config.ts +0 -136
  217. package/src/core/parsers/change-parser.ts +0 -234
  218. package/src/core/parsers/markdown-parser.ts +0 -237
  219. package/src/core/parsers/requirement-blocks.ts +0 -234
  220. package/src/core/prompt-templates.ts +0 -3504
  221. package/src/core/schemas/base.schema.ts +0 -20
  222. package/src/core/schemas/change.schema.ts +0 -42
  223. package/src/core/schemas/index.ts +0 -20
  224. package/src/core/schemas/spec.schema.ts +0 -17
  225. package/src/core/skill-discovery.ts +0 -68
  226. package/src/core/specs-apply.ts +0 -483
  227. package/src/core/styles/palette.ts +0 -8
  228. package/src/core/templates/agents-template.ts +0 -459
  229. package/src/core/templates/claude-template.ts +0 -2
  230. package/src/core/templates/index.ts +0 -4
  231. package/src/core/templates/project-template.ts +0 -32
  232. package/src/core/templates/slash-command-templates.ts +0 -1068
  233. package/src/core/validation/constants.ts +0 -48
  234. package/src/core/validation/types.ts +0 -19
  235. package/src/core/validation/validator.ts +0 -449
  236. package/src/core/view.ts +0 -219
  237. package/src/index.ts +0 -1
  238. package/src/utils/change-metadata.ts +0 -171
  239. package/src/utils/change-utils.ts +0 -131
  240. package/src/utils/file-system.ts +0 -252
  241. package/src/utils/index.ts +0 -12
  242. package/src/utils/interactive.ts +0 -29
  243. package/src/utils/item-discovery.ts +0 -66
  244. package/src/utils/match.ts +0 -26
  245. package/src/utils/shell-detection.ts +0 -62
  246. package/src/utils/task-progress.ts +0 -43
  247. package/tsconfig.json +0 -28
@@ -1,234 +0,0 @@
1
- export interface RequirementBlock {
2
- headerLine: string; // e.g., '### Requirement: Something'
3
- name: string; // e.g., 'Something'
4
- raw: string; // full block including headerLine and following content
5
- }
6
-
7
- export interface RequirementsSectionParts {
8
- before: string;
9
- headerLine: string; // the '## Requirements' line
10
- preamble: string; // content between headerLine and first requirement block
11
- bodyBlocks: RequirementBlock[]; // parsed requirement blocks in order
12
- after: string;
13
- }
14
-
15
- export function normalizeRequirementName(name: string): string {
16
- return name.trim();
17
- }
18
-
19
- const REQUIREMENT_HEADER_REGEX = /^###\s*Requirement:\s*(.+)\s*$/;
20
-
21
- /**
22
- * Extracts the Requirements section from a spec file and parses requirement blocks.
23
- */
24
- export function extractRequirementsSection(content: string): RequirementsSectionParts {
25
- const normalized = normalizeLineEndings(content);
26
- const lines = normalized.split('\n');
27
- const reqHeaderIndex = lines.findIndex(l => /^##\s+Requirements\s*$/i.test(l));
28
-
29
- if (reqHeaderIndex === -1) {
30
- // No requirements section; create an empty one at the end
31
- const before = content.trimEnd();
32
- const headerLine = '## Requirements';
33
- return {
34
- before: before ? before + '\n\n' : '',
35
- headerLine,
36
- preamble: '',
37
- bodyBlocks: [],
38
- after: '\n',
39
- };
40
- }
41
-
42
- // Find end of this section: next line that starts with '## ' at same or higher level
43
- let endIndex = lines.length;
44
- for (let i = reqHeaderIndex + 1; i < lines.length; i++) {
45
- if (/^##\s+/.test(lines[i])) {
46
- endIndex = i;
47
- break;
48
- }
49
- }
50
-
51
- const before = lines.slice(0, reqHeaderIndex).join('\n');
52
- const headerLine = lines[reqHeaderIndex];
53
- const sectionBodyLines = lines.slice(reqHeaderIndex + 1, endIndex);
54
-
55
- // Parse requirement blocks within section body
56
- const blocks: RequirementBlock[] = [];
57
- let cursor = 0;
58
- let preambleLines: string[] = [];
59
-
60
- // Collect preamble lines until first requirement header
61
- while (cursor < sectionBodyLines.length && !/^###\s+Requirement:/.test(sectionBodyLines[cursor])) {
62
- preambleLines.push(sectionBodyLines[cursor]);
63
- cursor++;
64
- }
65
-
66
- while (cursor < sectionBodyLines.length) {
67
- const headerStart = cursor;
68
- const headerLineCandidate = sectionBodyLines[cursor];
69
- const headerMatch = headerLineCandidate.match(REQUIREMENT_HEADER_REGEX);
70
- if (!headerMatch) {
71
- // Not a requirement header; skip line defensively
72
- cursor++;
73
- continue;
74
- }
75
- const name = normalizeRequirementName(headerMatch[1]);
76
- cursor++;
77
- // Gather lines until next requirement header or end of section
78
- const bodyLines: string[] = [headerLineCandidate];
79
- while (cursor < sectionBodyLines.length && !/^###\s+Requirement:/.test(sectionBodyLines[cursor]) && !/^##\s+/.test(sectionBodyLines[cursor])) {
80
- bodyLines.push(sectionBodyLines[cursor]);
81
- cursor++;
82
- }
83
- const raw = bodyLines.join('\n').trimEnd();
84
- blocks.push({ headerLine: headerLineCandidate, name, raw });
85
- }
86
-
87
- const after = lines.slice(endIndex).join('\n');
88
- const preamble = preambleLines.join('\n').trimEnd();
89
-
90
- return {
91
- before: before.trimEnd() ? before + '\n' : before,
92
- headerLine,
93
- preamble,
94
- bodyBlocks: blocks,
95
- after: after.startsWith('\n') ? after : '\n' + after,
96
- };
97
- }
98
-
99
- export interface DeltaPlan {
100
- added: RequirementBlock[];
101
- modified: RequirementBlock[];
102
- removed: string[]; // requirement names
103
- renamed: Array<{ from: string; to: string }>;
104
- sectionPresence: {
105
- added: boolean;
106
- modified: boolean;
107
- removed: boolean;
108
- renamed: boolean;
109
- };
110
- }
111
-
112
- function normalizeLineEndings(content: string): string {
113
- return content.replace(/\r\n?/g, '\n');
114
- }
115
-
116
- /**
117
- * Parse a delta-formatted spec change file content into a DeltaPlan with raw blocks.
118
- */
119
- export function parseDeltaSpec(content: string): DeltaPlan {
120
- const normalized = normalizeLineEndings(content);
121
- const sections = splitTopLevelSections(normalized);
122
- const addedLookup = getSectionCaseInsensitive(sections, 'ADDED Requirements');
123
- const modifiedLookup = getSectionCaseInsensitive(sections, 'MODIFIED Requirements');
124
- const removedLookup = getSectionCaseInsensitive(sections, 'REMOVED Requirements');
125
- const renamedLookup = getSectionCaseInsensitive(sections, 'RENAMED Requirements');
126
- const added = parseRequirementBlocksFromSection(addedLookup.body);
127
- const modified = parseRequirementBlocksFromSection(modifiedLookup.body);
128
- const removedNames = parseRemovedNames(removedLookup.body);
129
- const renamedPairs = parseRenamedPairs(renamedLookup.body);
130
- return {
131
- added,
132
- modified,
133
- removed: removedNames,
134
- renamed: renamedPairs,
135
- sectionPresence: {
136
- added: addedLookup.found,
137
- modified: modifiedLookup.found,
138
- removed: removedLookup.found,
139
- renamed: renamedLookup.found,
140
- },
141
- };
142
- }
143
-
144
- function splitTopLevelSections(content: string): Record<string, string> {
145
- const lines = content.split('\n');
146
- const result: Record<string, string> = {};
147
- const indices: Array<{ title: string; index: number; level: number }> = [];
148
- for (let i = 0; i < lines.length; i++) {
149
- const m = lines[i].match(/^(##)\s+(.+)$/);
150
- if (m) {
151
- const level = m[1].length; // only care for '##'
152
- indices.push({ title: m[2].trim(), index: i, level });
153
- }
154
- }
155
- for (let i = 0; i < indices.length; i++) {
156
- const current = indices[i];
157
- const next = indices[i + 1];
158
- const body = lines.slice(current.index + 1, next ? next.index : lines.length).join('\n');
159
- result[current.title] = body;
160
- }
161
- return result;
162
- }
163
-
164
- function getSectionCaseInsensitive(sections: Record<string, string>, desired: string): { body: string; found: boolean } {
165
- const target = desired.toLowerCase();
166
- for (const [title, body] of Object.entries(sections)) {
167
- if (title.toLowerCase() === target) return { body, found: true };
168
- }
169
- return { body: '', found: false };
170
- }
171
-
172
- function parseRequirementBlocksFromSection(sectionBody: string): RequirementBlock[] {
173
- if (!sectionBody) return [];
174
- const lines = normalizeLineEndings(sectionBody).split('\n');
175
- const blocks: RequirementBlock[] = [];
176
- let i = 0;
177
- while (i < lines.length) {
178
- // Seek next requirement header
179
- while (i < lines.length && !/^###\s+Requirement:/.test(lines[i])) i++;
180
- if (i >= lines.length) break;
181
- const headerLine = lines[i];
182
- const m = headerLine.match(REQUIREMENT_HEADER_REGEX);
183
- if (!m) { i++; continue; }
184
- const name = normalizeRequirementName(m[1]);
185
- const buf: string[] = [headerLine];
186
- i++;
187
- while (i < lines.length && !/^###\s+Requirement:/.test(lines[i]) && !/^##\s+/.test(lines[i])) {
188
- buf.push(lines[i]);
189
- i++;
190
- }
191
- blocks.push({ headerLine, name, raw: buf.join('\n').trimEnd() });
192
- }
193
- return blocks;
194
- }
195
-
196
- function parseRemovedNames(sectionBody: string): string[] {
197
- if (!sectionBody) return [];
198
- const names: string[] = [];
199
- const lines = normalizeLineEndings(sectionBody).split('\n');
200
- for (const line of lines) {
201
- const m = line.match(REQUIREMENT_HEADER_REGEX);
202
- if (m) {
203
- names.push(normalizeRequirementName(m[1]));
204
- continue;
205
- }
206
- // Also support bullet list of headers
207
- const bullet = line.match(/^\s*-\s*`?###\s*Requirement:\s*(.+?)`?\s*$/);
208
- if (bullet) {
209
- names.push(normalizeRequirementName(bullet[1]));
210
- }
211
- }
212
- return names;
213
- }
214
-
215
- function parseRenamedPairs(sectionBody: string): Array<{ from: string; to: string }> {
216
- if (!sectionBody) return [];
217
- const pairs: Array<{ from: string; to: string }> = [];
218
- const lines = normalizeLineEndings(sectionBody).split('\n');
219
- let current: { from?: string; to?: string } = {};
220
- for (const line of lines) {
221
- const fromMatch = line.match(/^\s*-?\s*FROM:\s*`?###\s*Requirement:\s*(.+?)`?\s*$/);
222
- const toMatch = line.match(/^\s*-?\s*TO:\s*`?###\s*Requirement:\s*(.+?)`?\s*$/);
223
- if (fromMatch) {
224
- current.from = normalizeRequirementName(fromMatch[1]);
225
- } else if (toMatch) {
226
- current.to = normalizeRequirementName(toMatch[1]);
227
- if (current.from && current.to) {
228
- pairs.push({ from: current.from, to: current.to });
229
- current = {};
230
- }
231
- }
232
- }
233
- return pairs;
234
- }