@dedesfr/prompter 0.9.0 → 1.1.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 (225) hide show
  1. package/CHANGELOG.md +35 -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.map +1 -1
  6. package/dist/commands/init.js +35 -9
  7. package/dist/commands/init.js.map +1 -1
  8. package/dist/commands/login.d.ts +4 -0
  9. package/dist/commands/login.d.ts.map +1 -0
  10. package/dist/commands/login.js +56 -0
  11. package/dist/commands/login.js.map +1 -0
  12. package/dist/commands/logout.d.ts +4 -0
  13. package/dist/commands/logout.d.ts.map +1 -0
  14. package/dist/commands/logout.js +14 -0
  15. package/dist/commands/logout.js.map +1 -0
  16. package/dist/commands/update.d.ts +0 -2
  17. package/dist/commands/update.d.ts.map +1 -1
  18. package/dist/commands/update.js +19 -48
  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/config.d.ts +0 -7
  29. package/dist/core/config.d.ts.map +1 -1
  30. package/dist/core/config.js +0 -128
  31. package/dist/core/config.js.map +1 -1
  32. package/dist/core/registry.d.ts +18 -0
  33. package/dist/core/registry.d.ts.map +1 -0
  34. package/dist/core/registry.js +94 -0
  35. package/dist/core/registry.js.map +1 -0
  36. package/package.json +7 -1
  37. package/AGENTS.md +0 -123
  38. package/CLAUDE.md +0 -17
  39. package/build.js +0 -20
  40. package/convex-setup.md +0 -403
  41. package/dist/core/prompt-templates.d.ts +0 -23
  42. package/dist/core/prompt-templates.d.ts.map +0 -1
  43. package/dist/core/prompt-templates.js +0 -3485
  44. package/dist/core/prompt-templates.js.map +0 -1
  45. package/prompt/ai-humanizer.md +0 -45
  46. package/prompt/api-contract-generator.md +0 -234
  47. package/prompt/apply.md +0 -17
  48. package/prompt/archive.md +0 -21
  49. package/prompt/design-system.md +0 -210
  50. package/prompt/document-explainer.md +0 -149
  51. package/prompt/epic-generator.md +0 -198
  52. package/prompt/epic-single.md +0 -47
  53. package/prompt/erd-generator.md +0 -130
  54. package/prompt/fsd-generator.md +0 -157
  55. package/prompt/prd-agent-generator.md +0 -147
  56. package/prompt/prd-generator.md +0 -195
  57. package/prompt/product-brief.md +0 -289
  58. package/prompt/proposal.md +0 -22
  59. package/prompt/qa-test-scenario.md +0 -133
  60. package/prompt/skill-creator.md +0 -350
  61. package/prompt/story-generator.md +0 -278
  62. package/prompt/story-single.md +0 -70
  63. package/prompt/tdd-generator.md +0 -294
  64. package/prompt/tdd-lite-generator.md +0 -224
  65. package/prompt/wireframe-generator.md +0 -219
  66. package/skills/ai-context-generator/SKILL.md +0 -54
  67. package/skills/ai-context-generator/references/AGENTS.template.md +0 -83
  68. package/skills/ai-context-generator/references/CLAUDE.template.md +0 -39
  69. package/skills/ai-context-generator/references/behavioral-guidelines.md +0 -71
  70. package/skills/ai-context-generator/references/discovery-checklist.md +0 -40
  71. package/skills/ai-context-generator/references/examples/AGENTS.good.md +0 -103
  72. package/skills/ai-context-generator/references/extraction-checklist.md +0 -23
  73. package/skills/ai-context-generator/references/overlays/laravel.md +0 -44
  74. package/skills/ai-humanizer/SKILL.md +0 -50
  75. package/skills/api-contract-generator/SKILL.md +0 -243
  76. package/skills/apply/SKILL.md +0 -23
  77. package/skills/archive/SKILL.md +0 -27
  78. package/skills/cerebro/SKILL.md +0 -187
  79. package/skills/cerebro/references/agents.md +0 -213
  80. package/skills/code-review/SKILL.md +0 -373
  81. package/skills/code-review/assets/report-template-agent.md +0 -212
  82. package/skills/code-review/assets/report-template-compact.md +0 -81
  83. package/skills/code-review/assets/report-template-full.md +0 -264
  84. package/skills/code-review/assets/report-template-human.md +0 -168
  85. package/skills/code-review/references/universal-patterns.md +0 -495
  86. package/skills/design-md/README.md +0 -34
  87. package/skills/design-md/SKILL.md +0 -172
  88. package/skills/design-md/examples/DESIGN.md +0 -154
  89. package/skills/design-system/SKILL.md +0 -216
  90. package/skills/design-system-generator/SKILL.md +0 -324
  91. package/skills/design-system-generator/assets/design-system-template.md +0 -348
  92. package/skills/design-system-generator/references/extraction-patterns.md +0 -321
  93. package/skills/doc-builder/SKILL.md +0 -115
  94. package/skills/doc-builder/references/ui-patterns.md +0 -394
  95. package/skills/document-explainer/SKILL.md +0 -155
  96. package/skills/document-translator/SKILL.md +0 -58
  97. package/skills/enhance/SKILL.md +0 -47
  98. package/skills/enhance-prompt/README.md +0 -34
  99. package/skills/enhance-prompt/SKILL.md +0 -204
  100. package/skills/enhance-prompt/references/KEYWORDS.md +0 -114
  101. package/skills/epic-generator/SKILL.md +0 -204
  102. package/skills/epic-single/SKILL.md +0 -63
  103. package/skills/erd-generator/SKILL.md +0 -138
  104. package/skills/feature-planner/SKILL.md +0 -305
  105. package/skills/feature-planner/assets/implementation-plan-template.md +0 -85
  106. package/skills/frontend-design/LICENSE.txt +0 -177
  107. package/skills/frontend-design/SKILL.md +0 -42
  108. package/skills/fsd-generator/SKILL.md +0 -163
  109. package/skills/gamma-builder/SKILL.md +0 -134
  110. package/skills/laravel-code-review/SKILL.md +0 -383
  111. package/skills/laravel-code-review/assets/report-template-agent.md +0 -195
  112. package/skills/laravel-code-review/assets/report-template-compact.md +0 -79
  113. package/skills/laravel-code-review/assets/report-template-full.md +0 -253
  114. package/skills/laravel-code-review/assets/report-template-human.md +0 -159
  115. package/skills/laravel-code-review/references/laravel-patterns.md +0 -571
  116. package/skills/laravel-code-review/references/php84-features.md +0 -442
  117. package/skills/mcp-builder/LICENSE.txt +0 -202
  118. package/skills/mcp-builder/SKILL.md +0 -236
  119. package/skills/mcp-builder/reference/evaluation.md +0 -602
  120. package/skills/mcp-builder/reference/mcp_best_practices.md +0 -249
  121. package/skills/mcp-builder/reference/node_mcp_server.md +0 -970
  122. package/skills/mcp-builder/reference/python_mcp_server.md +0 -719
  123. package/skills/mcp-builder/scripts/connections.py +0 -151
  124. package/skills/mcp-builder/scripts/evaluation.py +0 -373
  125. package/skills/mcp-builder/scripts/example_evaluation.xml +0 -22
  126. package/skills/mcp-builder/scripts/requirements.txt +0 -2
  127. package/skills/meeting-notes/SKILL.md +0 -159
  128. package/skills/meeting-notes/evals/evals.json +0 -23
  129. package/skills/prd-agent-generator/SKILL.md +0 -132
  130. package/skills/prd-generator/SKILL.md +0 -211
  131. package/skills/product-brief/SKILL.md +0 -141
  132. package/skills/project-orchestrator/SKILL.md +0 -487
  133. package/skills/project-orchestrator/assets/caddy-vps-setup.md +0 -180
  134. package/skills/project-orchestrator/assets/plan-summary-template.md +0 -159
  135. package/skills/prompter-specs/SKILL.md +0 -115
  136. package/skills/prompter-workflow/SKILL.md +0 -166
  137. package/skills/prompter-workflow/evals/evals.json +0 -89
  138. package/skills/proposal/SKILL.md +0 -28
  139. package/skills/qa-test-scenario/SKILL.md +0 -149
  140. package/skills/skill-creator/SKILL.md +0 -173
  141. package/skills/sph-generator/SKILL.md +0 -488
  142. package/skills/story-generator/SKILL.md +0 -285
  143. package/skills/story-single/SKILL.md +0 -86
  144. package/skills/tdd-generator/SKILL.md +0 -300
  145. package/skills/tdd-lite-generator/SKILL.md +0 -230
  146. package/skills/ui-ux-pro/SKILL.md +0 -199
  147. package/skills/ui-ux-pro/assets/design-spec-template.md +0 -173
  148. package/skills/ui-ux-pro/references/component-patterns.md +0 -255
  149. package/skills/ui-ux-pro/references/design-principles.md +0 -167
  150. package/skills/wireframe-generator/SKILL.md +0 -227
  151. package/src/cli/index.ts +0 -223
  152. package/src/commands/archive.ts +0 -302
  153. package/src/commands/change.ts +0 -292
  154. package/src/commands/config.ts +0 -233
  155. package/src/commands/guide.ts +0 -50
  156. package/src/commands/init.ts +0 -597
  157. package/src/commands/list.ts +0 -194
  158. package/src/commands/show.ts +0 -138
  159. package/src/commands/spec.ts +0 -251
  160. package/src/commands/update.ts +0 -129
  161. package/src/commands/upgrade.ts +0 -30
  162. package/src/commands/validate.ts +0 -326
  163. package/src/core/artifact-graph/graph.ts +0 -167
  164. package/src/core/artifact-graph/index.ts +0 -44
  165. package/src/core/artifact-graph/instruction-loader.ts +0 -302
  166. package/src/core/artifact-graph/resolver.ts +0 -226
  167. package/src/core/artifact-graph/schema.ts +0 -124
  168. package/src/core/artifact-graph/state.ts +0 -64
  169. package/src/core/artifact-graph/types.ts +0 -65
  170. package/src/core/completions/command-registry.ts +0 -382
  171. package/src/core/completions/completion-provider.ts +0 -128
  172. package/src/core/completions/generators/bash-generator.ts +0 -191
  173. package/src/core/completions/generators/fish-generator.ts +0 -188
  174. package/src/core/completions/generators/powershell-generator.ts +0 -223
  175. package/src/core/completions/generators/zsh-generator.ts +0 -281
  176. package/src/core/completions/templates/bash-templates.ts +0 -24
  177. package/src/core/completions/templates/fish-templates.ts +0 -40
  178. package/src/core/completions/templates/powershell-templates.ts +0 -25
  179. package/src/core/completions/templates/zsh-templates.ts +0 -36
  180. package/src/core/completions/types.ts +0 -90
  181. package/src/core/config-schema.ts +0 -230
  182. package/src/core/config.ts +0 -181
  183. package/src/core/configurators/slash/antigravity.ts +0 -10
  184. package/src/core/configurators/slash/base.ts +0 -109
  185. package/src/core/configurators/slash/claude.ts +0 -10
  186. package/src/core/configurators/slash/codex.ts +0 -10
  187. package/src/core/configurators/slash/droid.ts +0 -10
  188. package/src/core/configurators/slash/forge.ts +0 -10
  189. package/src/core/configurators/slash/github-copilot.ts +0 -10
  190. package/src/core/configurators/slash/index.ts +0 -10
  191. package/src/core/configurators/slash/kilocode.ts +0 -10
  192. package/src/core/configurators/slash/opencode.ts +0 -10
  193. package/src/core/configurators/slash/registry.ts +0 -51
  194. package/src/core/converters/json-converter.ts +0 -62
  195. package/src/core/global-config.ts +0 -136
  196. package/src/core/parsers/change-parser.ts +0 -234
  197. package/src/core/parsers/markdown-parser.ts +0 -237
  198. package/src/core/parsers/requirement-blocks.ts +0 -234
  199. package/src/core/prompt-templates.ts +0 -3504
  200. package/src/core/schemas/base.schema.ts +0 -20
  201. package/src/core/schemas/change.schema.ts +0 -42
  202. package/src/core/schemas/index.ts +0 -20
  203. package/src/core/schemas/spec.schema.ts +0 -17
  204. package/src/core/skill-discovery.ts +0 -68
  205. package/src/core/specs-apply.ts +0 -483
  206. package/src/core/styles/palette.ts +0 -8
  207. package/src/core/templates/agents-template.ts +0 -459
  208. package/src/core/templates/claude-template.ts +0 -2
  209. package/src/core/templates/index.ts +0 -3
  210. package/src/core/templates/project-template.ts +0 -32
  211. package/src/core/validation/constants.ts +0 -48
  212. package/src/core/validation/types.ts +0 -19
  213. package/src/core/validation/validator.ts +0 -449
  214. package/src/core/view.ts +0 -219
  215. package/src/index.ts +0 -1
  216. package/src/utils/change-metadata.ts +0 -171
  217. package/src/utils/change-utils.ts +0 -131
  218. package/src/utils/file-system.ts +0 -252
  219. package/src/utils/index.ts +0 -12
  220. package/src/utils/interactive.ts +0 -29
  221. package/src/utils/item-discovery.ts +0 -66
  222. package/src/utils/match.ts +0 -26
  223. package/src/utils/shell-detection.ts +0 -62
  224. package/src/utils/task-progress.ts +0 -43
  225. 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
- }