openplanr 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (194) hide show
  1. package/dist/agents/agent-factory.d.ts +7 -0
  2. package/dist/agents/agent-factory.d.ts.map +1 -0
  3. package/dist/agents/agent-factory.js +22 -0
  4. package/dist/agents/agent-factory.js.map +1 -0
  5. package/dist/agents/claude-agent.d.ts +13 -0
  6. package/dist/agents/claude-agent.d.ts.map +1 -0
  7. package/dist/agents/claude-agent.js +48 -0
  8. package/dist/agents/claude-agent.js.map +1 -0
  9. package/dist/agents/codex-agent.d.ts +13 -0
  10. package/dist/agents/codex-agent.d.ts.map +1 -0
  11. package/dist/agents/codex-agent.js +47 -0
  12. package/dist/agents/codex-agent.js.map +1 -0
  13. package/dist/agents/cursor-agent.d.ts +13 -0
  14. package/dist/agents/cursor-agent.d.ts.map +1 -0
  15. package/dist/agents/cursor-agent.js +40 -0
  16. package/dist/agents/cursor-agent.js.map +1 -0
  17. package/dist/agents/implementation-bridge.d.ts +21 -0
  18. package/dist/agents/implementation-bridge.d.ts.map +1 -0
  19. package/dist/agents/implementation-bridge.js +173 -0
  20. package/dist/agents/implementation-bridge.js.map +1 -0
  21. package/dist/agents/index.d.ts +6 -0
  22. package/dist/agents/index.d.ts.map +1 -0
  23. package/dist/agents/index.js +5 -0
  24. package/dist/agents/index.js.map +1 -0
  25. package/dist/agents/prompt-composer.d.ts +30 -0
  26. package/dist/agents/prompt-composer.d.ts.map +1 -0
  27. package/dist/agents/prompt-composer.js +81 -0
  28. package/dist/agents/prompt-composer.js.map +1 -0
  29. package/dist/agents/task-parser.d.ts +38 -0
  30. package/dist/agents/task-parser.d.ts.map +1 -0
  31. package/dist/agents/task-parser.js +83 -0
  32. package/dist/agents/task-parser.js.map +1 -0
  33. package/dist/agents/types.d.ts +23 -0
  34. package/dist/agents/types.d.ts.map +1 -0
  35. package/dist/agents/types.js +8 -0
  36. package/dist/agents/types.js.map +1 -0
  37. package/dist/agents/utils.d.ts +9 -0
  38. package/dist/agents/utils.d.ts.map +1 -0
  39. package/dist/agents/utils.js +21 -0
  40. package/dist/agents/utils.js.map +1 -0
  41. package/dist/ai/codebase/context-builder.d.ts +31 -0
  42. package/dist/ai/codebase/context-builder.d.ts.map +1 -0
  43. package/dist/ai/codebase/context-builder.js +93 -0
  44. package/dist/ai/codebase/context-builder.js.map +1 -0
  45. package/dist/ai/codebase/file-reader.d.ts +22 -0
  46. package/dist/ai/codebase/file-reader.d.ts.map +1 -0
  47. package/dist/ai/codebase/file-reader.js +111 -0
  48. package/dist/ai/codebase/file-reader.js.map +1 -0
  49. package/dist/ai/codebase/index.d.ts +5 -0
  50. package/dist/ai/codebase/index.d.ts.map +1 -0
  51. package/dist/ai/codebase/index.js +5 -0
  52. package/dist/ai/codebase/index.js.map +1 -0
  53. package/dist/ai/codebase/stack-detector.d.ts +18 -0
  54. package/dist/ai/codebase/stack-detector.d.ts.map +1 -0
  55. package/dist/ai/codebase/stack-detector.js +147 -0
  56. package/dist/ai/codebase/stack-detector.js.map +1 -0
  57. package/dist/ai/codebase/tree-generator.d.ts +8 -0
  58. package/dist/ai/codebase/tree-generator.d.ts.map +1 -0
  59. package/dist/ai/codebase/tree-generator.js +85 -0
  60. package/dist/ai/codebase/tree-generator.js.map +1 -0
  61. package/dist/ai/errors.d.ts +22 -0
  62. package/dist/ai/errors.d.ts.map +1 -0
  63. package/dist/ai/errors.js +70 -0
  64. package/dist/ai/errors.js.map +1 -0
  65. package/dist/ai/index.d.ts +11 -0
  66. package/dist/ai/index.d.ts.map +1 -0
  67. package/dist/ai/index.js +10 -0
  68. package/dist/ai/index.js.map +1 -0
  69. package/dist/ai/prompts/prompt-builder.d.ts +42 -0
  70. package/dist/ai/prompts/prompt-builder.d.ts.map +1 -0
  71. package/dist/ai/prompts/prompt-builder.js +96 -0
  72. package/dist/ai/prompts/prompt-builder.js.map +1 -0
  73. package/dist/ai/prompts/system-prompts.d.ts +13 -0
  74. package/dist/ai/prompts/system-prompts.d.ts.map +1 -0
  75. package/dist/ai/prompts/system-prompts.js +115 -0
  76. package/dist/ai/prompts/system-prompts.js.map +1 -0
  77. package/dist/ai/provider-factory.d.ts +10 -0
  78. package/dist/ai/provider-factory.d.ts.map +1 -0
  79. package/dist/ai/provider-factory.js +33 -0
  80. package/dist/ai/provider-factory.js.map +1 -0
  81. package/dist/ai/providers/anthropic-provider.d.ts +22 -0
  82. package/dist/ai/providers/anthropic-provider.d.ts.map +1 -0
  83. package/dist/ai/providers/anthropic-provider.js +82 -0
  84. package/dist/ai/providers/anthropic-provider.js.map +1 -0
  85. package/dist/ai/providers/ollama-provider.d.ts +13 -0
  86. package/dist/ai/providers/ollama-provider.d.ts.map +1 -0
  87. package/dist/ai/providers/ollama-provider.js +16 -0
  88. package/dist/ai/providers/ollama-provider.js.map +1 -0
  89. package/dist/ai/providers/openai-provider.d.ts +17 -0
  90. package/dist/ai/providers/openai-provider.d.ts.map +1 -0
  91. package/dist/ai/providers/openai-provider.js +58 -0
  92. package/dist/ai/providers/openai-provider.js.map +1 -0
  93. package/dist/ai/schemas/ai-response-schemas.d.ts +422 -0
  94. package/dist/ai/schemas/ai-response-schemas.d.ts.map +1 -0
  95. package/dist/ai/schemas/ai-response-schemas.js +86 -0
  96. package/dist/ai/schemas/ai-response-schemas.js.map +1 -0
  97. package/dist/ai/types.d.ts +40 -0
  98. package/dist/ai/types.d.ts.map +1 -0
  99. package/dist/ai/types.js +16 -0
  100. package/dist/ai/types.js.map +1 -0
  101. package/dist/cli/commands/config.d.ts +8 -0
  102. package/dist/cli/commands/config.d.ts.map +1 -0
  103. package/dist/cli/commands/config.js +112 -0
  104. package/dist/cli/commands/config.js.map +1 -0
  105. package/dist/cli/commands/epic.d.ts +7 -0
  106. package/dist/cli/commands/epic.d.ts.map +1 -1
  107. package/dist/cli/commands/epic.js +161 -31
  108. package/dist/cli/commands/epic.js.map +1 -1
  109. package/dist/cli/commands/feature.d.ts +6 -0
  110. package/dist/cli/commands/feature.d.ts.map +1 -1
  111. package/dist/cli/commands/feature.js +143 -30
  112. package/dist/cli/commands/feature.js.map +1 -1
  113. package/dist/cli/commands/init.d.ts +6 -0
  114. package/dist/cli/commands/init.d.ts.map +1 -1
  115. package/dist/cli/commands/init.js +48 -6
  116. package/dist/cli/commands/init.js.map +1 -1
  117. package/dist/cli/commands/plan.d.ts +15 -0
  118. package/dist/cli/commands/plan.d.ts.map +1 -0
  119. package/dist/cli/commands/plan.js +259 -0
  120. package/dist/cli/commands/plan.js.map +1 -0
  121. package/dist/cli/commands/refine.d.ts +9 -0
  122. package/dist/cli/commands/refine.d.ts.map +1 -0
  123. package/dist/cli/commands/refine.js +81 -0
  124. package/dist/cli/commands/refine.js.map +1 -0
  125. package/dist/cli/commands/story.d.ts +6 -0
  126. package/dist/cli/commands/story.d.ts.map +1 -1
  127. package/dist/cli/commands/story.js +172 -43
  128. package/dist/cli/commands/story.js.map +1 -1
  129. package/dist/cli/commands/sync.d.ts +12 -0
  130. package/dist/cli/commands/sync.d.ts.map +1 -0
  131. package/dist/cli/commands/sync.js +226 -0
  132. package/dist/cli/commands/sync.js.map +1 -0
  133. package/dist/cli/commands/task.d.ts +9 -0
  134. package/dist/cli/commands/task.d.ts.map +1 -1
  135. package/dist/cli/commands/task.js +348 -35
  136. package/dist/cli/commands/task.js.map +1 -1
  137. package/dist/cli/index.js +10 -2
  138. package/dist/cli/index.js.map +1 -1
  139. package/dist/models/schema.d.ts +41 -0
  140. package/dist/models/schema.d.ts.map +1 -1
  141. package/dist/models/schema.js +9 -0
  142. package/dist/models/schema.js.map +1 -1
  143. package/dist/models/types.d.ts +9 -0
  144. package/dist/models/types.d.ts.map +1 -1
  145. package/dist/services/ai-service.d.ts +40 -0
  146. package/dist/services/ai-service.d.ts.map +1 -0
  147. package/dist/services/ai-service.js +150 -0
  148. package/dist/services/ai-service.js.map +1 -0
  149. package/dist/services/artifact-gathering.d.ts +49 -0
  150. package/dist/services/artifact-gathering.d.ts.map +1 -0
  151. package/dist/services/artifact-gathering.js +128 -0
  152. package/dist/services/artifact-gathering.js.map +1 -0
  153. package/dist/services/artifact-service.d.ts +47 -0
  154. package/dist/services/artifact-service.d.ts.map +1 -1
  155. package/dist/services/artifact-service.js +166 -0
  156. package/dist/services/artifact-service.js.map +1 -1
  157. package/dist/services/credentials-service.d.ts +22 -0
  158. package/dist/services/credentials-service.d.ts.map +1 -0
  159. package/dist/services/credentials-service.js +58 -0
  160. package/dist/services/credentials-service.js.map +1 -0
  161. package/dist/services/id-service.d.ts.map +1 -1
  162. package/dist/services/id-service.js +8 -5
  163. package/dist/services/id-service.js.map +1 -1
  164. package/dist/services/prompt-service.d.ts +1 -0
  165. package/dist/services/prompt-service.d.ts.map +1 -1
  166. package/dist/services/prompt-service.js +4 -1
  167. package/dist/services/prompt-service.js.map +1 -1
  168. package/dist/services/template-service.d.ts.map +1 -1
  169. package/dist/services/template-service.js +1 -0
  170. package/dist/services/template-service.js.map +1 -1
  171. package/dist/templates/checklists/agile-checklist.md.hbs +8 -8
  172. package/dist/templates/epics/epic.md.hbs +8 -2
  173. package/dist/templates/features/feature.md.hbs +3 -3
  174. package/dist/templates/rules/cursor/2001-agile-create-epic.mdc.hbs +1 -1
  175. package/dist/templates/rules/cursor/2002-agile-create-features.mdc.hbs +1 -1
  176. package/dist/templates/rules/cursor/2003-agile-create-user-story.mdc.hbs +1 -1
  177. package/dist/templates/stories/user-story.md.hbs +2 -2
  178. package/dist/templates/tasks/task-list.md.hbs +26 -3
  179. package/package.json +4 -2
  180. package/dist/templates/templates/adrs/adr-general.md.hbs +0 -46
  181. package/dist/templates/templates/checklists/agile-checklist.md.hbs +0 -49
  182. package/dist/templates/templates/epics/epic.md.hbs +0 -46
  183. package/dist/templates/templates/features/feature.md.hbs +0 -42
  184. package/dist/templates/templates/rules/claude/CLAUDE.md.hbs +0 -63
  185. package/dist/templates/templates/rules/codex/AGENTS.md.hbs +0 -28
  186. package/dist/templates/templates/rules/cursor/2000-agile-checklist.mdc.hbs +0 -33
  187. package/dist/templates/templates/rules/cursor/2001-agile-create-epic.mdc.hbs +0 -35
  188. package/dist/templates/templates/rules/cursor/2002-agile-create-features.mdc.hbs +0 -35
  189. package/dist/templates/templates/rules/cursor/2003-agile-create-user-story.mdc.hbs +0 -31
  190. package/dist/templates/templates/rules/cursor/2100-create-task-list.mdc.hbs +0 -36
  191. package/dist/templates/templates/rules/cursor/2101-implement-task-list.mdc.hbs +0 -28
  192. package/dist/templates/templates/stories/gherkin.feature.hbs +0 -13
  193. package/dist/templates/templates/stories/user-story.md.hbs +0 -28
  194. package/dist/templates/templates/tasks/task-list.md.hbs +0 -24
@@ -1,54 +1,50 @@
1
+ /**
2
+ * `planr feature` command group.
3
+ *
4
+ * AI-powered by default: reads the parent epic and generates
5
+ * multiple features automatically. Use --manual for legacy mode.
6
+ */
1
7
  import { loadConfig } from '../../services/config-service.js';
2
- import { createArtifact, listArtifacts, readArtifact } from '../../services/artifact-service.js';
3
- import { promptText, promptMultiText } from '../../services/prompt-service.js';
8
+ import { createArtifact, listArtifacts, readArtifact, readArtifactRaw, resolveArtifactFilename, addChildReference, } from '../../services/artifact-service.js';
9
+ import { isAIConfigured, getAIProvider, generateStreamingJSON } from '../../services/ai-service.js';
10
+ import { promptText, promptMultiText, promptConfirm } from '../../services/prompt-service.js';
11
+ import { buildFeaturesPrompt } from '../../ai/prompts/prompt-builder.js';
12
+ import { aiFeaturesResponseSchema } from '../../ai/schemas/ai-response-schemas.js';
4
13
  import { logger } from '../../utils/logger.js';
14
+ import chalk from 'chalk';
5
15
  export function registerFeatureCommand(program) {
6
16
  const feature = program.command('feature').description('Manage features');
7
17
  feature
8
18
  .command('create')
9
- .description('Create a new feature from an epic')
19
+ .description('Create features from an epic')
10
20
  .requiredOption('--epic <epicId>', 'parent epic ID (e.g., EPIC-001)')
11
21
  .option('--title <title>', 'feature title')
22
+ .option('--count <n>', 'number of features to generate', parseInt)
23
+ .option('--manual', 'use manual interactive prompts instead of AI')
12
24
  .action(async (opts) => {
13
25
  const projectDir = program.opts().projectDir;
14
26
  const config = await loadConfig(projectDir);
15
- // Verify epic exists
16
27
  const epicData = await readArtifact(projectDir, config, 'epic', opts.epic);
17
28
  if (!epicData) {
18
29
  logger.error(`Epic ${opts.epic} not found.`);
19
30
  process.exit(1);
20
31
  }
21
- logger.heading(`Create Feature (from ${opts.epic})`);
22
- const title = opts.title || (await promptText('Feature title:'));
23
- const owner = await promptText('Owner:', config.author);
24
- const overview = await promptText('Overview:');
25
- const functionalRequirements = await promptMultiText('Functional requirements', 'comma-separated');
26
- const dependencies = await promptText('Dependencies:', 'None');
27
- const technicalConsiderations = await promptText('Technical considerations:', 'None');
28
- const risks = await promptText('Risks:', 'None');
29
- const successMetrics = await promptText('Success metrics:');
30
- const { id, filePath } = await createArtifact(projectDir, config, 'feature', 'features/feature.md.hbs', {
31
- title,
32
- epicId: opts.epic,
33
- owner,
34
- overview,
35
- functionalRequirements,
36
- dependencies,
37
- technicalConsiderations,
38
- risks,
39
- successMetrics,
40
- storyIds: [],
41
- });
42
- logger.success(`Created feature ${id}: ${title}`);
43
- logger.dim(` ${filePath}`);
44
- logger.dim('');
45
- logger.dim(`Next: planr story create --feature ${id}`);
32
+ const useAI = !opts.manual && isAIConfigured(config);
33
+ if (useAI) {
34
+ await createFeaturesWithAI(projectDir, config, opts.epic, opts.count);
35
+ }
36
+ else {
37
+ if (!opts.manual && !isAIConfigured(config)) {
38
+ logger.warn('AI not configured. Using manual mode.');
39
+ }
40
+ await createFeatureManually(projectDir, config, opts);
41
+ }
46
42
  });
47
43
  feature
48
44
  .command('list')
49
45
  .description('List features')
50
46
  .option('--epic <epicId>', 'filter by epic ID')
51
- .action(async (opts) => {
47
+ .action(async () => {
52
48
  const projectDir = program.opts().projectDir;
53
49
  const config = await loadConfig(projectDir);
54
50
  const features = await listArtifacts(projectDir, config, 'feature');
@@ -62,4 +58,121 @@ export function registerFeatureCommand(program) {
62
58
  }
63
59
  });
64
60
  }
61
+ async function createFeaturesWithAI(projectDir, config, epicId, featureCount) {
62
+ logger.heading(`Create Features (AI-powered from ${epicId})`);
63
+ const epicRaw = await readArtifactRaw(projectDir, config, 'epic', epicId);
64
+ if (!epicRaw) {
65
+ logger.error(`Could not read epic ${epicId}.`);
66
+ return;
67
+ }
68
+ // Find existing features for THIS epic (for dedup + warning)
69
+ const allFeatures = await listArtifacts(projectDir, config, 'feature');
70
+ const epicFeatures = [];
71
+ for (const f of allFeatures) {
72
+ const data = await readArtifact(projectDir, config, 'feature', f.id);
73
+ if (data && data.data.epicId === epicId) {
74
+ epicFeatures.push({ id: f.id, title: data.data.title || f.title });
75
+ }
76
+ }
77
+ if (epicFeatures.length > 0) {
78
+ logger.warn(`${epicId} already has ${epicFeatures.length} feature(s):`);
79
+ for (const f of epicFeatures) {
80
+ console.log(chalk.dim(` ${f.id}: ${f.title}`));
81
+ }
82
+ const continueCreate = await promptConfirm('Generate additional features? (AI will avoid duplicates)', false);
83
+ if (!continueCreate) {
84
+ logger.info('Feature creation cancelled.');
85
+ return;
86
+ }
87
+ }
88
+ const existingTitles = epicFeatures.map((f) => `${f.id}: ${f.title}`);
89
+ logger.dim('AI is generating features from the epic...');
90
+ try {
91
+ const provider = await getAIProvider(config);
92
+ const messages = buildFeaturesPrompt(epicRaw, existingTitles, featureCount);
93
+ const result = await generateStreamingJSON(provider, messages, aiFeaturesResponseSchema);
94
+ // Display generated features
95
+ console.log(chalk.dim('━'.repeat(50)));
96
+ result.features.forEach((feat, i) => {
97
+ console.log(chalk.bold(` ${i + 1}. ${feat.title}`));
98
+ console.log(chalk.dim(` ${feat.overview}`));
99
+ console.log(` Requirements: ${feat.functionalRequirements.length} items`);
100
+ });
101
+ console.log(chalk.dim('━'.repeat(50)));
102
+ const confirmAll = await promptConfirm(`Create all ${result.features.length} features?`, true);
103
+ if (!confirmAll) {
104
+ logger.info('Feature creation cancelled.');
105
+ return;
106
+ }
107
+ // Create each feature
108
+ const createdIds = [];
109
+ const epicFilename = await resolveArtifactFilename(projectDir, config, 'epic', epicId);
110
+ for (const feat of result.features) {
111
+ const { id, filePath } = await createArtifact(projectDir, config, 'feature', 'features/feature.md.hbs', {
112
+ title: feat.title,
113
+ epicId,
114
+ epicFilename,
115
+ owner: config.author || 'Engineering',
116
+ overview: feat.overview,
117
+ functionalRequirements: feat.functionalRequirements,
118
+ dependencies: feat.dependencies,
119
+ technicalConsiderations: feat.technicalConsiderations,
120
+ risks: feat.risks,
121
+ successMetrics: feat.successMetrics,
122
+ storyIds: [],
123
+ });
124
+ createdIds.push(id);
125
+ await addChildReference(projectDir, config, 'epic', epicId, 'feature', id, feat.title);
126
+ logger.success(`Created ${id}: ${feat.title}`);
127
+ logger.dim(` ${filePath}`);
128
+ }
129
+ logger.dim('');
130
+ logger.heading('Next steps:');
131
+ logger.dim(` 1. planr story create --feature ${createdIds[0]} — Create user stories`);
132
+ logger.dim(` 2. planr task create --story US-* — Generate implementation tasks`);
133
+ logger.dim(` 3. planr task implement TASK-* — Implement with your coding agent`);
134
+ logger.dim('');
135
+ logger.dim(` Or generate stories for all features at once:`);
136
+ logger.dim(` planr plan --epic ${epicId} — Auto-generate stories → tasks`);
137
+ }
138
+ catch (err) {
139
+ const { AIError } = await import('../../ai/errors.js');
140
+ if (err instanceof AIError) {
141
+ logger.error(err.userMessage);
142
+ }
143
+ else {
144
+ throw err;
145
+ }
146
+ }
147
+ }
148
+ async function createFeatureManually(projectDir, config, opts) {
149
+ logger.heading(`Create Feature (from ${opts.epic})`);
150
+ const title = opts.title || (await promptText('Feature title:'));
151
+ const owner = await promptText('Owner:', config.author);
152
+ const overview = await promptText('Overview:');
153
+ const functionalRequirements = await promptMultiText('Functional requirements', 'comma-separated');
154
+ const dependencies = await promptText('Dependencies:', 'None');
155
+ const technicalConsiderations = await promptText('Technical considerations:', 'None');
156
+ const risks = await promptText('Risks:', 'None');
157
+ const successMetrics = await promptText('Success metrics:');
158
+ const epicFilename = await resolveArtifactFilename(projectDir, config, 'epic', opts.epic);
159
+ const { id, filePath } = await createArtifact(projectDir, config, 'feature', 'features/feature.md.hbs', {
160
+ title,
161
+ epicId: opts.epic,
162
+ epicFilename,
163
+ owner,
164
+ overview,
165
+ functionalRequirements,
166
+ dependencies,
167
+ technicalConsiderations,
168
+ risks,
169
+ successMetrics,
170
+ storyIds: [],
171
+ });
172
+ await addChildReference(projectDir, config, 'epic', opts.epic, 'feature', id, title);
173
+ logger.success(`Created feature ${id}: ${title}`);
174
+ logger.dim(` ${filePath}`);
175
+ logger.dim('');
176
+ logger.dim(`Next: planr story create --feature ${id}`);
177
+ }
65
178
  //# sourceMappingURL=feature.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"feature.js","sourceRoot":"","sources":["../../../src/cli/commands/feature.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"feature.js","sourceRoot":"","sources":["../../../src/cli/commands/feature.ts"],"names":[],"mappings":"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"}
@@ -1,3 +1,9 @@
1
+ /**
2
+ * `planr init` command.
3
+ *
4
+ * Initializes a new Planr project with directory structure, config,
5
+ * and optional AI provider setup.
6
+ */
1
7
  import { Command } from 'commander';
2
8
  export declare function registerInitCommand(program: Command): void;
3
9
  //# sourceMappingURL=init.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/init.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAUpC,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,OAAO,QAkDnD"}
1
+ {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/init.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAWpC,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,OAAO,QA8FnD"}
@@ -1,16 +1,23 @@
1
+ /**
2
+ * `planr init` command.
3
+ *
4
+ * Initializes a new Planr project with directory structure, config,
5
+ * and optional AI provider setup.
6
+ */
1
7
  import path from 'node:path';
2
8
  import { createDefaultConfig, saveConfig } from '../../services/config-service.js';
3
9
  import { createChecklist } from '../../services/checklist-service.js';
4
- import { ensureDir } from '../../utils/fs.js';
5
- import { fileExists } from '../../utils/fs.js';
10
+ import { saveCredential } from '../../services/credentials-service.js';
11
+ import { ensureDir, fileExists } from '../../utils/fs.js';
6
12
  import { CONFIG_FILENAME, ARTIFACT_DIRS } from '../../utils/constants.js';
7
13
  import { logger } from '../../utils/logger.js';
8
- import { promptText, promptConfirm } from '../../services/prompt-service.js';
14
+ import { promptText, promptConfirm, promptSelect, promptSecret } from '../../services/prompt-service.js';
9
15
  export function registerInitCommand(program) {
10
16
  program
11
17
  .command('init')
12
18
  .description('Initialize Planr in the current project')
13
19
  .option('--name <name>', 'project name')
20
+ .option('--no-ai', 'skip AI setup')
14
21
  .action(async (opts) => {
15
22
  const projectDir = program.opts().projectDir;
16
23
  const configPath = path.join(projectDir, CONFIG_FILENAME);
@@ -23,27 +30,62 @@ export function registerInitCommand(program) {
23
30
  }
24
31
  const projectName = opts.name || (await promptText('Project name:', path.basename(projectDir)));
25
32
  const config = createDefaultConfig(projectName);
33
+ // --- AI Provider Setup ---
34
+ if (opts.ai !== false) {
35
+ const enableAI = await promptConfirm('Enable AI-powered planning?', true);
36
+ if (enableAI) {
37
+ const provider = await promptSelect('AI provider:', [
38
+ { name: 'Anthropic (Claude)', value: 'anthropic' },
39
+ { name: 'OpenAI (GPT-4o)', value: 'openai' },
40
+ { name: 'Ollama (Local — free, no API key)', value: 'ollama' },
41
+ ]);
42
+ config.ai = { provider };
43
+ // Collect API key for cloud providers
44
+ if (provider === 'anthropic' || provider === 'openai') {
45
+ const keyHint = provider === 'anthropic' ? 'ANTHROPIC_API_KEY' : 'OPENAI_API_KEY';
46
+ const apiKey = await promptSecret(`API key (or press Enter to set ${keyHint} env var later):`);
47
+ if (apiKey.trim()) {
48
+ await saveCredential(provider, apiKey.trim());
49
+ logger.success(`API key saved to ~/.planr/credentials.json`);
50
+ }
51
+ else {
52
+ logger.dim(` No key provided. Set ${keyHint} env var or run \`planr config set-key ${provider}\`.`);
53
+ }
54
+ }
55
+ // Coding agent preference
56
+ const agent = await promptSelect('Default coding agent:', [
57
+ { name: 'Claude Code CLI', value: 'claude' },
58
+ { name: 'Cursor', value: 'cursor' },
59
+ { name: 'Codex', value: 'codex' },
60
+ ]);
61
+ config.defaultAgent = agent;
62
+ }
63
+ }
26
64
  // Create directory structure
27
65
  const agileDir = path.join(projectDir, config.outputPaths.agile);
28
66
  for (const dir of Object.values(ARTIFACT_DIRS)) {
29
67
  await ensureDir(path.join(agileDir, dir));
30
68
  }
31
- // Also create diagrams dir
32
69
  await ensureDir(path.join(agileDir, 'diagrams'));
33
70
  // Save config
34
71
  await saveConfig(projectDir, config);
35
72
  logger.success(`Created ${CONFIG_FILENAME}`);
36
73
  // Create checklist
37
- const checklistPath = await createChecklist(projectDir, config);
74
+ await createChecklist(projectDir, config);
38
75
  logger.success(`Created agile development checklist`);
76
+ // Summary
39
77
  logger.heading('Planr initialized!');
40
78
  logger.info(`Project: ${projectName}`);
41
79
  logger.info(`Artifacts: ${config.outputPaths.agile}/`);
80
+ if (config.ai) {
81
+ logger.info(`AI: ${config.ai.provider} (every command is AI-powered)`);
82
+ logger.info(`Agent: ${config.defaultAgent || 'claude'}`);
83
+ }
42
84
  logger.dim('');
43
85
  logger.dim('Next steps:');
44
86
  logger.dim(' planr epic create — Create your first epic');
45
87
  logger.dim(' planr rules generate — Generate AI agent rules');
46
- logger.dim(' planr checklist show — View the agile checklist');
88
+ logger.dim(' planr config show — View configuration');
47
89
  });
48
90
  }
49
91
  //# sourceMappingURL=init.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"init.js","sourceRoot":"","sources":["../../../src/cli/commands/init.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"init.js","sourceRoot":"","sources":["../../../src/cli/commands/init.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ /**
2
+ * `planr plan` command.
3
+ *
4
+ * Full agile planning flow in a single command:
5
+ * Epic → Features → User Stories → Tasks
6
+ *
7
+ * Can start from any level:
8
+ * --epic EPIC-001 → generates features → stories → tasks
9
+ * --feature FEAT-001 → generates stories → tasks
10
+ * --story US-001 → generates tasks
11
+ * (no flag) → creates epic first, then cascades
12
+ */
13
+ import { Command } from 'commander';
14
+ export declare function registerPlanCommand(program: Command): void;
15
+ //# sourceMappingURL=plan.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plan.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/plan.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AA4BpC,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,OAAO,QAyCnD"}
@@ -0,0 +1,259 @@
1
+ /**
2
+ * `planr plan` command.
3
+ *
4
+ * Full agile planning flow in a single command:
5
+ * Epic → Features → User Stories → Tasks
6
+ *
7
+ * Can start from any level:
8
+ * --epic EPIC-001 → generates features → stories → tasks
9
+ * --feature FEAT-001 → generates stories → tasks
10
+ * --story US-001 → generates tasks
11
+ * (no flag) → creates epic first, then cascades
12
+ */
13
+ import path from 'node:path';
14
+ import { loadConfig } from '../../services/config-service.js';
15
+ import { createArtifact, listArtifacts, readArtifact, readArtifactRaw, getArtifactDir, resolveArtifactFilename, addChildReference, } from '../../services/artifact-service.js';
16
+ import { isAIConfigured, getAIProvider, generateStreamingJSON } from '../../services/ai-service.js';
17
+ import { promptText, promptConfirm } from '../../services/prompt-service.js';
18
+ import { renderTemplate } from '../../services/template-service.js';
19
+ import { writeFile } from '../../utils/fs.js';
20
+ import { buildEpicPrompt, buildFeaturesPrompt, buildStoriesPrompt, buildTasksPrompt } from '../../ai/prompts/prompt-builder.js';
21
+ import { aiEpicResponseSchema, aiFeaturesResponseSchema, aiStoriesResponseSchema, aiTasksResponseSchema, } from '../../ai/schemas/ai-response-schemas.js';
22
+ import { logger } from '../../utils/logger.js';
23
+ import chalk from 'chalk';
24
+ export function registerPlanCommand(program) {
25
+ program
26
+ .command('plan')
27
+ .description('Full agile planning flow: Epic → Features → Stories → Tasks')
28
+ .option('--epic <epicId>', 'start from an existing epic')
29
+ .option('--feature <featureId>', 'start from an existing feature')
30
+ .option('--story <storyId>', 'start from an existing story (generates tasks only)')
31
+ .action(async (opts) => {
32
+ const projectDir = program.opts().projectDir;
33
+ const config = await loadConfig(projectDir);
34
+ if (!isAIConfigured(config)) {
35
+ logger.error('AI must be configured for the plan command. Run `planr config set-provider`.');
36
+ process.exit(1);
37
+ }
38
+ const provider = await getAIProvider(config);
39
+ try {
40
+ if (opts.story) {
41
+ // Start from story → generate tasks
42
+ await generateTasksForStory(projectDir, config, provider, opts.story);
43
+ }
44
+ else if (opts.feature) {
45
+ // Start from feature → stories → tasks
46
+ await planFromFeature(projectDir, config, provider, opts.feature);
47
+ }
48
+ else if (opts.epic) {
49
+ // Start from epic → features → stories → tasks
50
+ await planFromEpic(projectDir, config, provider, opts.epic);
51
+ }
52
+ else {
53
+ // Full flow: create epic first
54
+ await planFromScratch(projectDir, config, provider);
55
+ }
56
+ }
57
+ catch (err) {
58
+ const { AIError } = await import('../../ai/errors.js');
59
+ if (err instanceof AIError) {
60
+ logger.error(err.userMessage);
61
+ }
62
+ else {
63
+ throw err;
64
+ }
65
+ }
66
+ });
67
+ }
68
+ async function planFromScratch(projectDir, config, provider) {
69
+ logger.heading('Full Agile Planning Flow');
70
+ logger.dim('Epic → Features → User Stories → Tasks\n');
71
+ // Step 1: Create Epic
72
+ const brief = await promptText('Describe your epic in a sentence or two:');
73
+ const existingEpics = await listArtifacts(projectDir, config, 'epic');
74
+ const existingTitles = existingEpics.map((e) => `${e.id}: ${e.title}`);
75
+ logger.dim('\n[1/4] Generating epic...');
76
+ const epicMessages = buildEpicPrompt(brief, existingTitles);
77
+ const epicData = await generateStreamingJSON(provider, epicMessages, aiEpicResponseSchema);
78
+ console.log(chalk.bold(`\n Epic: ${epicData.title}`));
79
+ console.log(chalk.dim(` ${epicData.solutionOverview}`));
80
+ const continueFlow = await promptConfirm('Save epic and continue planning?', true);
81
+ if (!continueFlow) {
82
+ logger.info('Planning cancelled.');
83
+ return;
84
+ }
85
+ const epicCriteriaArray = Array.isArray(epicData.successCriteria)
86
+ ? epicData.successCriteria
87
+ : [epicData.successCriteria];
88
+ const { id: epicId } = await createArtifact(projectDir, config, 'epic', 'epics/epic.md.hbs', {
89
+ ...epicData,
90
+ successCriteria: epicCriteriaArray.join('; '),
91
+ successCriteriaList: epicCriteriaArray,
92
+ featureIds: [],
93
+ });
94
+ logger.success(`Created ${epicId}: ${epicData.title}`);
95
+ await planFromEpic(projectDir, config, provider, epicId);
96
+ }
97
+ async function planFromEpic(projectDir, config, provider, epicId) {
98
+ // Step 2: Generate Features
99
+ const epicRaw = await readArtifactRaw(projectDir, config, 'epic', epicId);
100
+ if (!epicRaw) {
101
+ logger.error(`Epic ${epicId} not found.`);
102
+ return;
103
+ }
104
+ const existingFeatures = await listArtifacts(projectDir, config, 'feature');
105
+ const existingFeatureTitles = existingFeatures.map((f) => `${f.id}: ${f.title}`);
106
+ logger.dim('\n[2/4] Generating features...');
107
+ const featureMessages = buildFeaturesPrompt(epicRaw, existingFeatureTitles);
108
+ const featureResult = await generateStreamingJSON(provider, featureMessages, aiFeaturesResponseSchema);
109
+ console.log(chalk.bold(`\n Generated ${featureResult.features.length} features:`));
110
+ featureResult.features.forEach((f, i) => {
111
+ console.log(chalk.dim(` ${i + 1}. ${f.title}`));
112
+ });
113
+ const continueFeatures = await promptConfirm(`Create all ${featureResult.features.length} features and continue?`, true);
114
+ if (!continueFeatures) {
115
+ logger.info('Planning paused after epic.');
116
+ return;
117
+ }
118
+ const featureIds = [];
119
+ const epicFilename = await resolveArtifactFilename(projectDir, config, 'epic', epicId);
120
+ for (const feat of featureResult.features) {
121
+ const { id } = await createArtifact(projectDir, config, 'feature', 'features/feature.md.hbs', {
122
+ title: feat.title,
123
+ epicId,
124
+ epicFilename,
125
+ owner: config.author || 'Engineering',
126
+ overview: feat.overview,
127
+ functionalRequirements: feat.functionalRequirements,
128
+ dependencies: feat.dependencies,
129
+ technicalConsiderations: feat.technicalConsiderations,
130
+ risks: feat.risks,
131
+ successMetrics: feat.successMetrics,
132
+ storyIds: [],
133
+ });
134
+ featureIds.push(id);
135
+ await addChildReference(projectDir, config, 'epic', epicId, 'feature', id, feat.title);
136
+ logger.success(`Created ${id}: ${feat.title}`);
137
+ }
138
+ // Step 3+4: Stories and tasks for each feature
139
+ for (const featureId of featureIds) {
140
+ await planFromFeature(projectDir, config, provider, featureId);
141
+ }
142
+ // Final summary
143
+ logger.heading('\nPlanning Complete!');
144
+ const allFeatures = await listArtifacts(projectDir, config, 'feature');
145
+ const allStories = await listArtifacts(projectDir, config, 'story');
146
+ const allTasks = await listArtifacts(projectDir, config, 'task');
147
+ console.log(` Epic: ${epicId}`);
148
+ console.log(` Features: ${allFeatures.length}`);
149
+ console.log(` Stories: ${allStories.length}`);
150
+ console.log(` Tasks: ${allTasks.length}`);
151
+ logger.dim('');
152
+ logger.dim('Start implementing:');
153
+ logger.dim(' planr task implement TASK-001 --next');
154
+ logger.dim(' planr status');
155
+ }
156
+ async function planFromFeature(projectDir, config, provider, featureId) {
157
+ // Step 3: Generate Stories
158
+ const featureRaw = await readArtifactRaw(projectDir, config, 'feature', featureId);
159
+ if (!featureRaw) {
160
+ logger.error(`Feature ${featureId} not found.`);
161
+ return;
162
+ }
163
+ const featureData = await readArtifact(projectDir, config, 'feature', featureId);
164
+ const epicId = featureData?.data.epicId;
165
+ let epicRaw = '';
166
+ if (epicId) {
167
+ epicRaw = (await readArtifactRaw(projectDir, config, 'epic', epicId)) || '';
168
+ }
169
+ const existingStories = await listArtifacts(projectDir, config, 'story');
170
+ const existingStoryTitles = existingStories.map((s) => `${s.id}: ${s.title}`);
171
+ logger.dim(`\n[3/4] Generating stories for ${featureId}...`);
172
+ const storyMessages = buildStoriesPrompt(featureRaw, epicRaw, existingStoryTitles);
173
+ const storyResult = await generateStreamingJSON(provider, storyMessages, aiStoriesResponseSchema);
174
+ console.log(chalk.dim(` Generated ${storyResult.stories.length} stories for ${featureId}`));
175
+ const storyDir = path.join(projectDir, getArtifactDir(config, 'story'));
176
+ const storyIds = [];
177
+ const featureFilename = await resolveArtifactFilename(projectDir, config, 'feature', featureId);
178
+ for (const story of storyResult.stories) {
179
+ const { id, filePath } = await createArtifact(projectDir, config, 'story', 'stories/user-story.md.hbs', {
180
+ title: story.title,
181
+ featureId,
182
+ featureFilename,
183
+ role: story.role,
184
+ goal: story.goal,
185
+ benefit: story.benefit,
186
+ additionalNotes: story.additionalNotes || undefined,
187
+ });
188
+ // Gherkin file
189
+ const gherkinContent = await renderTemplate('stories/gherkin.feature.hbs', {
190
+ id,
191
+ title: story.title,
192
+ role: story.role,
193
+ goal: story.goal,
194
+ benefit: story.benefit,
195
+ scenarios: story.gherkinScenarios.map((s) => ({
196
+ name: s.name, given: s.given, when: s.when, then: s.then,
197
+ })),
198
+ }, config.templateOverrides);
199
+ await writeFile(path.join(storyDir, `${id}-gherkin.feature`), gherkinContent);
200
+ storyIds.push(id);
201
+ await addChildReference(projectDir, config, 'feature', featureId, 'story', id, story.title);
202
+ logger.success(`Created ${id}: ${story.title}`);
203
+ }
204
+ // Step 4: Generate tasks for each story
205
+ for (const storyId of storyIds) {
206
+ await generateTasksForStory(projectDir, config, provider, storyId);
207
+ }
208
+ }
209
+ async function generateTasksForStory(projectDir, config, provider, storyId) {
210
+ const { gatherStoryArtifacts } = await import('../../services/artifact-gathering.js');
211
+ let ctx;
212
+ try {
213
+ ctx = await gatherStoryArtifacts(projectDir, config, storyId);
214
+ }
215
+ catch {
216
+ logger.error(`Story ${storyId} not found.`);
217
+ return;
218
+ }
219
+ logger.dim(`\n[4/4] Generating tasks for ${storyId}...`);
220
+ ctx.scope = { type: 'story', id: storyId };
221
+ const taskMessages = buildTasksPrompt(ctx);
222
+ const result = await generateStreamingJSON(provider, taskMessages, aiTasksResponseSchema);
223
+ const tasks = result.tasks.map((tg) => ({
224
+ id: tg.id,
225
+ title: tg.title,
226
+ status: 'pending',
227
+ subtasks: (tg.subtasks || []).map((st) => ({
228
+ id: st.id,
229
+ title: st.title,
230
+ status: 'pending',
231
+ subtasks: [],
232
+ })),
233
+ }));
234
+ const storyFilename = await resolveArtifactFilename(projectDir, config, 'story', storyId);
235
+ // Build artifact sources for traceability
236
+ const artifactSources = [];
237
+ for (const s of ctx.stories) {
238
+ artifactSources.push({ type: 'User Story', path: `${config.outputPaths.agile}/stories/${s.id}` });
239
+ }
240
+ for (const g of ctx.gherkinScenarios) {
241
+ artifactSources.push({ type: 'Gherkin', path: `${config.outputPaths.agile}/stories/${g.storyId}-gherkin.feature` });
242
+ }
243
+ for (const a of ctx.adrs) {
244
+ artifactSources.push({ type: 'ADR', path: `${config.outputPaths.agile}/adrs/${a.id}` });
245
+ }
246
+ const { id } = await createArtifact(projectDir, config, 'task', 'tasks/task-list.md.hbs', {
247
+ title: result.title,
248
+ storyId,
249
+ storyFilename,
250
+ tasks,
251
+ artifactSources,
252
+ acceptanceCriteriaMapping: result.acceptanceCriteriaMapping,
253
+ relevantFiles: result.relevantFiles,
254
+ });
255
+ const total = tasks.reduce((sum, t) => sum + t.subtasks.length + 1, 0);
256
+ await addChildReference(projectDir, config, 'story', storyId, 'task', id, result.title);
257
+ logger.success(`Created ${id}: ${result.title} (${total} tasks)`);
258
+ }
259
+ //# sourceMappingURL=plan.js.map