@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,292 +0,0 @@
1
- import { promises as fs } from 'fs';
2
- import path from 'path';
3
- import { JsonConverter } from '../core/converters/json-converter.js';
4
- import { Validator } from '../core/validation/validator.js';
5
- import { ChangeParser } from '../core/parsers/change-parser.js';
6
- import { Change } from '../core/schemas/index.js';
7
- import { isInteractive } from '../utils/interactive.js';
8
- import { getActiveChangeIds } from '../utils/item-discovery.js';
9
-
10
- // Constants for better maintainability
11
- const ARCHIVE_DIR = 'archive';
12
- const TASK_PATTERN = /^[-*]\s+\[[\sx]\]/i;
13
- const COMPLETED_TASK_PATTERN = /^[-*]\s+\[x\]/i;
14
-
15
- export class ChangeCommand {
16
- private converter: JsonConverter;
17
-
18
- constructor() {
19
- this.converter = new JsonConverter();
20
- }
21
-
22
- /**
23
- * Show a change proposal.
24
- * - Text mode: raw markdown passthrough (no filters)
25
- * - JSON mode: minimal object with deltas; --deltas-only returns same object with filtered deltas
26
- * Note: --requirements-only is deprecated alias for --deltas-only
27
- */
28
- async show(changeName?: string, options?: { json?: boolean; requirementsOnly?: boolean; deltasOnly?: boolean; noInteractive?: boolean }): Promise<void> {
29
- const changesPath = path.join(process.cwd(), 'prompter', 'changes');
30
-
31
- if (!changeName) {
32
- const canPrompt = isInteractive(options);
33
- const changes = await this.getActiveChanges(changesPath);
34
- if (canPrompt && changes.length > 0) {
35
- const { select } = await import('@inquirer/prompts');
36
- const selected = await select({
37
- message: 'Select a change to show',
38
- choices: changes.map(id => ({ name: id, value: id })),
39
- });
40
- changeName = selected;
41
- } else {
42
- if (changes.length === 0) {
43
- console.error('No change specified. No active changes found.');
44
- } else {
45
- console.error(`No change specified. Available IDs: ${changes.join(', ')}`);
46
- }
47
- console.error('Hint: use "prompter change list" to view available changes.');
48
- process.exitCode = 1;
49
- return;
50
- }
51
- }
52
-
53
- const proposalPath = path.join(changesPath, changeName, 'proposal.md');
54
-
55
- try {
56
- await fs.access(proposalPath);
57
- } catch {
58
- throw new Error(`Change "${changeName}" not found at ${proposalPath}`);
59
- }
60
-
61
- if (options?.json) {
62
- const jsonOutput = await this.converter.convertChangeToJson(proposalPath);
63
-
64
- if (options.requirementsOnly) {
65
- console.error('Flag --requirements-only is deprecated; use --deltas-only instead.');
66
- }
67
-
68
- const parsed: Change = JSON.parse(jsonOutput);
69
- const contentForTitle = await fs.readFile(proposalPath, 'utf-8');
70
- const title = this.extractTitle(contentForTitle, changeName);
71
- const id = parsed.name;
72
- const deltas = parsed.deltas || [];
73
-
74
- if (options.requirementsOnly || options.deltasOnly) {
75
- const output = { id, title, deltaCount: deltas.length, deltas };
76
- console.log(JSON.stringify(output, null, 2));
77
- } else {
78
- const output = {
79
- id,
80
- title,
81
- deltaCount: deltas.length,
82
- deltas,
83
- };
84
- console.log(JSON.stringify(output, null, 2));
85
- }
86
- } else {
87
- const content = await fs.readFile(proposalPath, 'utf-8');
88
- console.log(content);
89
- }
90
- }
91
-
92
- /**
93
- * List active changes.
94
- * - Text default: IDs only; --long prints minimal details (title, counts)
95
- * - JSON: array of { id, title, deltaCount, taskStatus }, sorted by id
96
- */
97
- async list(options?: { json?: boolean; long?: boolean }): Promise<void> {
98
- const changesPath = path.join(process.cwd(), 'prompter', 'changes');
99
-
100
- const changes = await this.getActiveChanges(changesPath);
101
-
102
- if (options?.json) {
103
- const changeDetails = await Promise.all(
104
- changes.map(async (changeName) => {
105
- const proposalPath = path.join(changesPath, changeName, 'proposal.md');
106
- const tasksPath = path.join(changesPath, changeName, 'tasks.md');
107
-
108
- try {
109
- const content = await fs.readFile(proposalPath, 'utf-8');
110
- const changeDir = path.join(changesPath, changeName);
111
- const parser = new ChangeParser(content, changeDir);
112
- const change = await parser.parseChangeWithDeltas(changeName);
113
-
114
- let taskStatus = { total: 0, completed: 0 };
115
- try {
116
- const tasksContent = await fs.readFile(tasksPath, 'utf-8');
117
- taskStatus = this.countTasks(tasksContent);
118
- } catch (error) {
119
- // Tasks file may not exist, which is okay
120
- if (process.env.DEBUG) {
121
- console.error(`Failed to read tasks file at ${tasksPath}:`, error);
122
- }
123
- }
124
-
125
- return {
126
- id: changeName,
127
- title: this.extractTitle(content, changeName),
128
- deltaCount: change.deltas.length,
129
- taskStatus,
130
- };
131
- } catch (error) {
132
- return {
133
- id: changeName,
134
- title: 'Unknown',
135
- deltaCount: 0,
136
- taskStatus: { total: 0, completed: 0 },
137
- };
138
- }
139
- })
140
- );
141
-
142
- const sorted = changeDetails.sort((a, b) => a.id.localeCompare(b.id));
143
- console.log(JSON.stringify(sorted, null, 2));
144
- } else {
145
- if (changes.length === 0) {
146
- console.log('No items found');
147
- return;
148
- }
149
- const sorted = [...changes].sort();
150
- if (!options?.long) {
151
- // IDs only
152
- sorted.forEach(id => console.log(id));
153
- return;
154
- }
155
-
156
- // Long format: id: title and minimal counts
157
- for (const changeName of sorted) {
158
- const proposalPath = path.join(changesPath, changeName, 'proposal.md');
159
- const tasksPath = path.join(changesPath, changeName, 'tasks.md');
160
- try {
161
- const content = await fs.readFile(proposalPath, 'utf-8');
162
- const title = this.extractTitle(content, changeName);
163
- let taskStatusText = '';
164
- try {
165
- const tasksContent = await fs.readFile(tasksPath, 'utf-8');
166
- const { total, completed } = this.countTasks(tasksContent);
167
- taskStatusText = ` [tasks ${completed}/${total}]`;
168
- } catch (error) {
169
- if (process.env.DEBUG) {
170
- console.error(`Failed to read tasks file at ${tasksPath}:`, error);
171
- }
172
- }
173
- const changeDir = path.join(changesPath, changeName);
174
- const parser = new ChangeParser(await fs.readFile(proposalPath, 'utf-8'), changeDir);
175
- const change = await parser.parseChangeWithDeltas(changeName);
176
- const deltaCountText = ` [deltas ${change.deltas.length}]`;
177
- console.log(`${changeName}: ${title}${deltaCountText}${taskStatusText}`);
178
- } catch {
179
- console.log(`${changeName}: (unable to read)`);
180
- }
181
- }
182
- }
183
- }
184
-
185
- async validate(changeName?: string, options?: { strict?: boolean; json?: boolean; noInteractive?: boolean }): Promise<void> {
186
- const changesPath = path.join(process.cwd(), 'prompter', 'changes');
187
-
188
- if (!changeName) {
189
- const canPrompt = isInteractive(options);
190
- const changes = await getActiveChangeIds();
191
- if (canPrompt && changes.length > 0) {
192
- const { select } = await import('@inquirer/prompts');
193
- const selected = await select({
194
- message: 'Select a change to validate',
195
- choices: changes.map(id => ({ name: id, value: id })),
196
- });
197
- changeName = selected;
198
- } else {
199
- if (changes.length === 0) {
200
- console.error('No change specified. No active changes found.');
201
- } else {
202
- console.error(`No change specified. Available IDs: ${changes.join(', ')}`);
203
- }
204
- console.error('Hint: use "prompter change list" to view available changes.');
205
- process.exitCode = 1;
206
- return;
207
- }
208
- }
209
-
210
- const changeDir = path.join(changesPath, changeName);
211
-
212
- try {
213
- await fs.access(changeDir);
214
- } catch {
215
- throw new Error(`Change "${changeName}" not found at ${changeDir}`);
216
- }
217
-
218
- const validator = new Validator(options?.strict || false);
219
- const report = await validator.validateChangeDeltaSpecs(changeDir);
220
-
221
- if (options?.json) {
222
- console.log(JSON.stringify(report, null, 2));
223
- } else {
224
- if (report.valid) {
225
- console.log(`Change "${changeName}" is valid`);
226
- } else {
227
- console.error(`Change "${changeName}" has issues`);
228
- report.issues.forEach(issue => {
229
- const label = issue.level === 'ERROR' ? 'ERROR' : 'WARNING';
230
- const prefix = issue.level === 'ERROR' ? '✗' : '⚠';
231
- console.error(`${prefix} [${label}] ${issue.path}: ${issue.message}`);
232
- });
233
- // Next steps footer to guide fixing issues
234
- this.printNextSteps();
235
- if (!options?.json) {
236
- process.exitCode = 1;
237
- }
238
- }
239
- }
240
- }
241
-
242
- private async getActiveChanges(changesPath: string): Promise<string[]> {
243
- try {
244
- const entries = await fs.readdir(changesPath, { withFileTypes: true });
245
- const result: string[] = [];
246
- for (const entry of entries) {
247
- if (!entry.isDirectory() || entry.name.startsWith('.') || entry.name === ARCHIVE_DIR) continue;
248
- const proposalPath = path.join(changesPath, entry.name, 'proposal.md');
249
- try {
250
- await fs.access(proposalPath);
251
- result.push(entry.name);
252
- } catch {
253
- // skip directories without proposal.md
254
- }
255
- }
256
- return result.sort();
257
- } catch {
258
- return [];
259
- }
260
- }
261
-
262
- private extractTitle(content: string, changeName: string): string {
263
- const match = content.match(/^#\s+(?:Change:\s+)?(.+)$/im);
264
- return match ? match[1].trim() : changeName;
265
- }
266
-
267
- private countTasks(content: string): { total: number; completed: number } {
268
- const lines = content.split('\n');
269
- let total = 0;
270
- let completed = 0;
271
-
272
- for (const line of lines) {
273
- if (line.match(TASK_PATTERN)) {
274
- total++;
275
- if (line.match(COMPLETED_TASK_PATTERN)) {
276
- completed++;
277
- }
278
- }
279
- }
280
-
281
- return { total, completed };
282
- }
283
-
284
- private printNextSteps(): void {
285
- const bullets: string[] = [];
286
- bullets.push('- Ensure change has deltas in specs/: use headers ## ADDED/MODIFIED/REMOVED/RENAMED Requirements');
287
- bullets.push('- Each requirement MUST include at least one #### Scenario: block');
288
- bullets.push('- Debug parsed deltas: prompter change show <id> --json --deltas-only');
289
- console.error('Next steps:');
290
- bullets.forEach(b => console.error(` ${b}`));
291
- }
292
- }
@@ -1,233 +0,0 @@
1
- import { Command } from 'commander';
2
- import { spawn } from 'node:child_process';
3
- import * as fs from 'node:fs';
4
- import {
5
- getGlobalConfigPath,
6
- getGlobalConfig,
7
- saveGlobalConfig,
8
- GlobalConfig,
9
- } from '../core/global-config.js';
10
- import {
11
- getNestedValue,
12
- setNestedValue,
13
- deleteNestedValue,
14
- coerceValue,
15
- formatValueYaml,
16
- validateConfigKeyPath,
17
- validateConfig,
18
- DEFAULT_CONFIG,
19
- } from '../core/config-schema.js';
20
-
21
- /**
22
- * Register the config command and all its subcommands.
23
- *
24
- * @param program - The Commander program instance
25
- */
26
- export function registerConfigCommand(program: Command): void {
27
- const configCmd = program
28
- .command('config')
29
- .description('View and modify global Prompter configuration')
30
- .option('--scope <scope>', 'Config scope (only "global" supported currently)')
31
- .hook('preAction', (thisCommand) => {
32
- const opts = thisCommand.opts();
33
- if (opts.scope && opts.scope !== 'global') {
34
- console.error('Error: Project-local config is not yet implemented');
35
- process.exit(1);
36
- }
37
- });
38
-
39
- // config path
40
- configCmd
41
- .command('path')
42
- .description('Show config file location')
43
- .action(() => {
44
- console.log(getGlobalConfigPath());
45
- });
46
-
47
- // config list
48
- configCmd
49
- .command('list')
50
- .description('Show all current settings')
51
- .option('--json', 'Output as JSON')
52
- .action((options: { json?: boolean }) => {
53
- const config = getGlobalConfig();
54
-
55
- if (options.json) {
56
- console.log(JSON.stringify(config, null, 2));
57
- } else {
58
- console.log(formatValueYaml(config));
59
- }
60
- });
61
-
62
- // config get
63
- configCmd
64
- .command('get <key>')
65
- .description('Get a specific value (raw, scriptable)')
66
- .action((key: string) => {
67
- const config = getGlobalConfig();
68
- const value = getNestedValue(config as Record<string, unknown>, key);
69
-
70
- if (value === undefined) {
71
- process.exitCode = 1;
72
- return;
73
- }
74
-
75
- if (typeof value === 'object' && value !== null) {
76
- console.log(JSON.stringify(value));
77
- } else {
78
- console.log(String(value));
79
- }
80
- });
81
-
82
- // config set
83
- configCmd
84
- .command('set <key> <value>')
85
- .description('Set a value (auto-coerce types)')
86
- .option('--string', 'Force value to be stored as string')
87
- .option('--allow-unknown', 'Allow setting unknown keys')
88
- .action((key: string, value: string, options: { string?: boolean; allowUnknown?: boolean }) => {
89
- const allowUnknown = Boolean(options.allowUnknown);
90
- const keyValidation = validateConfigKeyPath(key);
91
- if (!keyValidation.valid && !allowUnknown) {
92
- const reason = keyValidation.reason ? ` ${keyValidation.reason}.` : '';
93
- console.error(`Error: Invalid configuration key "${key}".${reason}`);
94
- console.error('Use "prompter config list" to see available keys.');
95
- console.error('Pass --allow-unknown to bypass this check.');
96
- process.exitCode = 1;
97
- return;
98
- }
99
-
100
- const config = getGlobalConfig() as Record<string, unknown>;
101
- const coercedValue = coerceValue(value, options.string || false);
102
-
103
- // Create a copy to validate before saving
104
- const newConfig = JSON.parse(JSON.stringify(config));
105
- setNestedValue(newConfig, key, coercedValue);
106
-
107
- // Validate the new config
108
- const validation = validateConfig(newConfig);
109
- if (!validation.success) {
110
- console.error(`Error: Invalid configuration - ${validation.error}`);
111
- process.exitCode = 1;
112
- return;
113
- }
114
-
115
- // Apply changes and save
116
- setNestedValue(config, key, coercedValue);
117
- saveGlobalConfig(config as GlobalConfig);
118
-
119
- const displayValue =
120
- typeof coercedValue === 'string' ? `"${coercedValue}"` : String(coercedValue);
121
- console.log(`Set ${key} = ${displayValue}`);
122
- });
123
-
124
- // config unset
125
- configCmd
126
- .command('unset <key>')
127
- .description('Remove a key (revert to default)')
128
- .action((key: string) => {
129
- const config = getGlobalConfig() as Record<string, unknown>;
130
- const existed = deleteNestedValue(config, key);
131
-
132
- if (existed) {
133
- saveGlobalConfig(config as GlobalConfig);
134
- console.log(`Unset ${key} (reverted to default)`);
135
- } else {
136
- console.log(`Key "${key}" was not set`);
137
- }
138
- });
139
-
140
- // config reset
141
- configCmd
142
- .command('reset')
143
- .description('Reset configuration to defaults')
144
- .option('--all', 'Reset all configuration (required)')
145
- .option('-y, --yes', 'Skip confirmation prompts')
146
- .action(async (options: { all?: boolean; yes?: boolean }) => {
147
- if (!options.all) {
148
- console.error('Error: --all flag is required for reset');
149
- console.error('Usage: prompter config reset --all [-y]');
150
- process.exitCode = 1;
151
- return;
152
- }
153
-
154
- if (!options.yes) {
155
- const { confirm } = await import('@inquirer/prompts');
156
- const confirmed = await confirm({
157
- message: 'Reset all configuration to defaults?',
158
- default: false,
159
- });
160
-
161
- if (!confirmed) {
162
- console.log('Reset cancelled.');
163
- return;
164
- }
165
- }
166
-
167
- saveGlobalConfig({ ...DEFAULT_CONFIG });
168
- console.log('Configuration reset to defaults');
169
- });
170
-
171
- // config edit
172
- configCmd
173
- .command('edit')
174
- .description('Open config in $EDITOR')
175
- .action(async () => {
176
- const editor = process.env.EDITOR || process.env.VISUAL;
177
-
178
- if (!editor) {
179
- console.error('Error: No editor configured');
180
- console.error('Set the EDITOR or VISUAL environment variable to your preferred editor');
181
- console.error('Example: export EDITOR=vim');
182
- process.exitCode = 1;
183
- return;
184
- }
185
-
186
- const configPath = getGlobalConfigPath();
187
-
188
- // Ensure config file exists with defaults
189
- if (!fs.existsSync(configPath)) {
190
- saveGlobalConfig({ ...DEFAULT_CONFIG });
191
- }
192
-
193
- // Spawn editor and wait for it to close
194
- // Avoid shell parsing to correctly handle paths with spaces in both
195
- // the editor path and config path
196
- const child = spawn(editor, [configPath], {
197
- stdio: 'inherit',
198
- shell: false,
199
- });
200
-
201
- await new Promise<void>((resolve, reject) => {
202
- child.on('close', (code) => {
203
- if (code === 0) {
204
- resolve();
205
- } else {
206
- reject(new Error(`Editor exited with code ${code}`));
207
- }
208
- });
209
- child.on('error', reject);
210
- });
211
-
212
- try {
213
- const rawConfig = fs.readFileSync(configPath, 'utf-8');
214
- const parsedConfig = JSON.parse(rawConfig);
215
- const validation = validateConfig(parsedConfig);
216
-
217
- if (!validation.success) {
218
- console.error(`Error: Invalid configuration - ${validation.error}`);
219
- process.exitCode = 1;
220
- }
221
- } catch (error) {
222
- if ((error as NodeJS.ErrnoException).code === 'ENOENT') {
223
- console.error(`Error: Config file not found at ${configPath}`);
224
- } else if (error instanceof SyntaxError) {
225
- console.error(`Error: Invalid JSON in ${configPath}`);
226
- console.error(error.message);
227
- } else {
228
- console.error(`Error: Unable to validate configuration - ${error instanceof Error ? error.message : String(error)}`);
229
- }
230
- process.exitCode = 1;
231
- }
232
- });
233
- }
@@ -1,50 +0,0 @@
1
- import chalk from 'chalk';
2
-
3
- export class GuideCommand {
4
- async execute(): Promise<void> {
5
- console.log(chalk.blue('\nGuides:'));
6
- console.log(chalk.gray(' 1. Provide a detailed and filled-out version of the "prompter/project.md"'));
7
- console.log(chalk.gray(' document based on the project\'s specifics, including a clear description'));
8
- console.log(chalk.gray(' of the project, its purpose, the technologies used (tech stack), and any'));
9
- console.log(chalk.gray(' conventions or standards being followed.'));
10
-
11
- console.log(chalk.blue('\nDocument Workflow & Dependencies:'));
12
- console.log(chalk.gray(' This table shows the recommended order for document generation:\n'));
13
-
14
- // Print table header
15
- console.log(chalk.cyan(' Document │ Required Inputs │ Extra Inputs │ Recommended Model'));
16
- console.log(chalk.cyan(' ─────────────────┼───────────────────────────────────────┼───────────────────────────────────┼──────────────────────────'));
17
-
18
- // Table rows
19
- const rows = [
20
- ['Product Brief ', '— ', '— ', 'Opus'],
21
- ['PRD ', 'Product Brief ', '— ', 'Sonnet'],
22
- ['FSD ', 'PRD ', 'Product Brief ', 'Sonnet'],
23
- ['ERD ', 'FSD ', '— ', 'Sonnet'],
24
- ['API Contract ', 'FSD + ERD ', '— ', 'Sonnet / GPT 5.2 Codex'],
25
- ['UI Wireframes ', 'FSD + ERD + API Contract ', '— ', 'Gemini 3 Pro / Sonnet'],
26
- ['Design System ', 'UI Wireframes (new) / FSD (existing) ', 'Brand guide / existing UI ', 'Sonnet'],
27
- ['TDD ', 'FSD ', 'ERD + API + UI + Design System ', 'Sonnet'],
28
- ['Epics ', 'FSD + TDD-Lite ', 'UI Wireframes + Design System ', 'Sonnet'],
29
- ['Stories ', 'Epics ', 'FSD + UI Wireframes + API ', 'Sonnet'],
30
- ['Proposal ', 'Specs (FSD/TDD/etc) ', '— ', 'Opus'],
31
- ['Apply ', 'Approved Proposal ', '— ', 'Sonnet / Gemini 3 / GPT 5.2 / GLM / Haiku']
32
- ];
33
-
34
- rows.forEach(row => {
35
- console.log(chalk.gray(` ${row[0]} │ ${row[1]} │ ${row[2]} │ ${row[3]}`));
36
- });
37
-
38
- console.log(chalk.blue('\n Complexity-Based Workflows:'));
39
- console.log(chalk.gray(' Small → Brief → FSD → Design System → Stories'));
40
- console.log(chalk.gray(' Medium → Brief → PRD → FSD → UI → Design System → Stories'));
41
- console.log(chalk.gray(' High → Brief → PRD → FSD → ERD → API → UI → Design System → TDD → Epics → Stories'));
42
-
43
- console.log(chalk.blue('\n Prompter Solo Dev 🤓 Workflow:'));
44
- console.log(chalk.green.bold(' Step 1 📄: Brief → PRD → Epic (Foundation)'));
45
- console.log(chalk.green.bold(' Step 2 🚀: [ Proposal ⇄ Apply ⇄ Archive ] ↺ (Development Loop)'));
46
- console.log(chalk.gray(' • Initial setup: Create Brief, PRD and Epic to establish context.'));
47
- console.log(chalk.gray(' • Active Dev: Repeat Step 2 for every feature, bugfix, or improvement.'));
48
- console.log(chalk.gray(' • Archive step automatically updates your specs to keep them current.'));
49
- }
50
- }