openplanr 0.1.0 → 0.3.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 (209) hide show
  1. package/README.md +23 -5
  2. package/dist/agents/agent-factory.d.ts +7 -0
  3. package/dist/agents/agent-factory.d.ts.map +1 -0
  4. package/dist/agents/agent-factory.js +22 -0
  5. package/dist/agents/agent-factory.js.map +1 -0
  6. package/dist/agents/claude-agent.d.ts +13 -0
  7. package/dist/agents/claude-agent.d.ts.map +1 -0
  8. package/dist/agents/claude-agent.js +48 -0
  9. package/dist/agents/claude-agent.js.map +1 -0
  10. package/dist/agents/codex-agent.d.ts +13 -0
  11. package/dist/agents/codex-agent.d.ts.map +1 -0
  12. package/dist/agents/codex-agent.js +47 -0
  13. package/dist/agents/codex-agent.js.map +1 -0
  14. package/dist/agents/cursor-agent.d.ts +13 -0
  15. package/dist/agents/cursor-agent.d.ts.map +1 -0
  16. package/dist/agents/cursor-agent.js +40 -0
  17. package/dist/agents/cursor-agent.js.map +1 -0
  18. package/dist/agents/implementation-bridge.d.ts +21 -0
  19. package/dist/agents/implementation-bridge.d.ts.map +1 -0
  20. package/dist/agents/implementation-bridge.js +173 -0
  21. package/dist/agents/implementation-bridge.js.map +1 -0
  22. package/dist/agents/index.d.ts +6 -0
  23. package/dist/agents/index.d.ts.map +1 -0
  24. package/dist/agents/index.js +5 -0
  25. package/dist/agents/index.js.map +1 -0
  26. package/dist/agents/prompt-composer.d.ts +30 -0
  27. package/dist/agents/prompt-composer.d.ts.map +1 -0
  28. package/dist/agents/prompt-composer.js +81 -0
  29. package/dist/agents/prompt-composer.js.map +1 -0
  30. package/dist/agents/task-parser.d.ts +38 -0
  31. package/dist/agents/task-parser.d.ts.map +1 -0
  32. package/dist/agents/task-parser.js +83 -0
  33. package/dist/agents/task-parser.js.map +1 -0
  34. package/dist/agents/types.d.ts +23 -0
  35. package/dist/agents/types.d.ts.map +1 -0
  36. package/dist/agents/types.js +8 -0
  37. package/dist/agents/types.js.map +1 -0
  38. package/dist/agents/utils.d.ts +9 -0
  39. package/dist/agents/utils.d.ts.map +1 -0
  40. package/dist/agents/utils.js +21 -0
  41. package/dist/agents/utils.js.map +1 -0
  42. package/dist/ai/codebase/context-builder.d.ts +31 -0
  43. package/dist/ai/codebase/context-builder.d.ts.map +1 -0
  44. package/dist/ai/codebase/context-builder.js +93 -0
  45. package/dist/ai/codebase/context-builder.js.map +1 -0
  46. package/dist/ai/codebase/file-reader.d.ts +22 -0
  47. package/dist/ai/codebase/file-reader.d.ts.map +1 -0
  48. package/dist/ai/codebase/file-reader.js +111 -0
  49. package/dist/ai/codebase/file-reader.js.map +1 -0
  50. package/dist/ai/codebase/index.d.ts +5 -0
  51. package/dist/ai/codebase/index.d.ts.map +1 -0
  52. package/dist/ai/codebase/index.js +5 -0
  53. package/dist/ai/codebase/index.js.map +1 -0
  54. package/dist/ai/codebase/stack-detector.d.ts +18 -0
  55. package/dist/ai/codebase/stack-detector.d.ts.map +1 -0
  56. package/dist/ai/codebase/stack-detector.js +147 -0
  57. package/dist/ai/codebase/stack-detector.js.map +1 -0
  58. package/dist/ai/codebase/tree-generator.d.ts +8 -0
  59. package/dist/ai/codebase/tree-generator.d.ts.map +1 -0
  60. package/dist/ai/codebase/tree-generator.js +85 -0
  61. package/dist/ai/codebase/tree-generator.js.map +1 -0
  62. package/dist/ai/errors.d.ts +22 -0
  63. package/dist/ai/errors.d.ts.map +1 -0
  64. package/dist/ai/errors.js +70 -0
  65. package/dist/ai/errors.js.map +1 -0
  66. package/dist/ai/index.d.ts +11 -0
  67. package/dist/ai/index.d.ts.map +1 -0
  68. package/dist/ai/index.js +10 -0
  69. package/dist/ai/index.js.map +1 -0
  70. package/dist/ai/prompts/prompt-builder.d.ts +42 -0
  71. package/dist/ai/prompts/prompt-builder.d.ts.map +1 -0
  72. package/dist/ai/prompts/prompt-builder.js +96 -0
  73. package/dist/ai/prompts/prompt-builder.js.map +1 -0
  74. package/dist/ai/prompts/system-prompts.d.ts +13 -0
  75. package/dist/ai/prompts/system-prompts.d.ts.map +1 -0
  76. package/dist/ai/prompts/system-prompts.js +124 -0
  77. package/dist/ai/prompts/system-prompts.js.map +1 -0
  78. package/dist/ai/provider-factory.d.ts +10 -0
  79. package/dist/ai/provider-factory.d.ts.map +1 -0
  80. package/dist/ai/provider-factory.js +33 -0
  81. package/dist/ai/provider-factory.js.map +1 -0
  82. package/dist/ai/providers/anthropic-provider.d.ts +22 -0
  83. package/dist/ai/providers/anthropic-provider.d.ts.map +1 -0
  84. package/dist/ai/providers/anthropic-provider.js +82 -0
  85. package/dist/ai/providers/anthropic-provider.js.map +1 -0
  86. package/dist/ai/providers/ollama-provider.d.ts +13 -0
  87. package/dist/ai/providers/ollama-provider.d.ts.map +1 -0
  88. package/dist/ai/providers/ollama-provider.js +16 -0
  89. package/dist/ai/providers/ollama-provider.js.map +1 -0
  90. package/dist/ai/providers/openai-provider.d.ts +17 -0
  91. package/dist/ai/providers/openai-provider.d.ts.map +1 -0
  92. package/dist/ai/providers/openai-provider.js +58 -0
  93. package/dist/ai/providers/openai-provider.js.map +1 -0
  94. package/dist/ai/schemas/ai-response-schemas.d.ts +425 -0
  95. package/dist/ai/schemas/ai-response-schemas.d.ts.map +1 -0
  96. package/dist/ai/schemas/ai-response-schemas.js +87 -0
  97. package/dist/ai/schemas/ai-response-schemas.js.map +1 -0
  98. package/dist/ai/types.d.ts +40 -0
  99. package/dist/ai/types.d.ts.map +1 -0
  100. package/dist/ai/types.js +16 -0
  101. package/dist/ai/types.js.map +1 -0
  102. package/dist/cli/commands/checklist.d.ts.map +1 -1
  103. package/dist/cli/commands/checklist.js +60 -1
  104. package/dist/cli/commands/checklist.js.map +1 -1
  105. package/dist/cli/commands/config.d.ts +8 -0
  106. package/dist/cli/commands/config.d.ts.map +1 -0
  107. package/dist/cli/commands/config.js +112 -0
  108. package/dist/cli/commands/config.js.map +1 -0
  109. package/dist/cli/commands/epic.d.ts +7 -0
  110. package/dist/cli/commands/epic.d.ts.map +1 -1
  111. package/dist/cli/commands/epic.js +161 -31
  112. package/dist/cli/commands/epic.js.map +1 -1
  113. package/dist/cli/commands/feature.d.ts +6 -0
  114. package/dist/cli/commands/feature.d.ts.map +1 -1
  115. package/dist/cli/commands/feature.js +143 -30
  116. package/dist/cli/commands/feature.js.map +1 -1
  117. package/dist/cli/commands/init.d.ts +6 -0
  118. package/dist/cli/commands/init.d.ts.map +1 -1
  119. package/dist/cli/commands/init.js +48 -6
  120. package/dist/cli/commands/init.js.map +1 -1
  121. package/dist/cli/commands/plan.d.ts +15 -0
  122. package/dist/cli/commands/plan.d.ts.map +1 -0
  123. package/dist/cli/commands/plan.js +259 -0
  124. package/dist/cli/commands/plan.js.map +1 -0
  125. package/dist/cli/commands/refine.d.ts +9 -0
  126. package/dist/cli/commands/refine.d.ts.map +1 -0
  127. package/dist/cli/commands/refine.js +101 -0
  128. package/dist/cli/commands/refine.js.map +1 -0
  129. package/dist/cli/commands/status.d.ts.map +1 -1
  130. package/dist/cli/commands/status.js +150 -18
  131. package/dist/cli/commands/status.js.map +1 -1
  132. package/dist/cli/commands/story.d.ts +6 -0
  133. package/dist/cli/commands/story.d.ts.map +1 -1
  134. package/dist/cli/commands/story.js +259 -45
  135. package/dist/cli/commands/story.js.map +1 -1
  136. package/dist/cli/commands/sync.d.ts +12 -0
  137. package/dist/cli/commands/sync.d.ts.map +1 -0
  138. package/dist/cli/commands/sync.js +227 -0
  139. package/dist/cli/commands/sync.js.map +1 -0
  140. package/dist/cli/commands/task.d.ts +9 -0
  141. package/dist/cli/commands/task.d.ts.map +1 -1
  142. package/dist/cli/commands/task.js +350 -35
  143. package/dist/cli/commands/task.js.map +1 -1
  144. package/dist/cli/index.js +16 -2
  145. package/dist/cli/index.js.map +1 -1
  146. package/dist/models/schema.d.ts +41 -0
  147. package/dist/models/schema.d.ts.map +1 -1
  148. package/dist/models/schema.js +9 -0
  149. package/dist/models/schema.js.map +1 -1
  150. package/dist/models/types.d.ts +9 -0
  151. package/dist/models/types.d.ts.map +1 -1
  152. package/dist/services/ai-service.d.ts +40 -0
  153. package/dist/services/ai-service.d.ts.map +1 -0
  154. package/dist/services/ai-service.js +150 -0
  155. package/dist/services/ai-service.js.map +1 -0
  156. package/dist/services/artifact-gathering.d.ts +49 -0
  157. package/dist/services/artifact-gathering.d.ts.map +1 -0
  158. package/dist/services/artifact-gathering.js +128 -0
  159. package/dist/services/artifact-gathering.js.map +1 -0
  160. package/dist/services/artifact-service.d.ts +47 -0
  161. package/dist/services/artifact-service.d.ts.map +1 -1
  162. package/dist/services/artifact-service.js +169 -0
  163. package/dist/services/artifact-service.js.map +1 -1
  164. package/dist/services/checklist-service.d.ts +23 -0
  165. package/dist/services/checklist-service.d.ts.map +1 -1
  166. package/dist/services/checklist-service.js +44 -0
  167. package/dist/services/checklist-service.js.map +1 -1
  168. package/dist/services/credentials-service.d.ts +22 -0
  169. package/dist/services/credentials-service.d.ts.map +1 -0
  170. package/dist/services/credentials-service.js +58 -0
  171. package/dist/services/credentials-service.js.map +1 -0
  172. package/dist/services/id-service.d.ts.map +1 -1
  173. package/dist/services/id-service.js +8 -5
  174. package/dist/services/id-service.js.map +1 -1
  175. package/dist/services/prompt-service.d.ts +6 -0
  176. package/dist/services/prompt-service.d.ts.map +1 -1
  177. package/dist/services/prompt-service.js +7 -1
  178. package/dist/services/prompt-service.js.map +1 -1
  179. package/dist/services/template-service.d.ts.map +1 -1
  180. package/dist/services/template-service.js +6 -0
  181. package/dist/services/template-service.js.map +1 -1
  182. package/dist/templates/checklists/agile-checklist.md.hbs +8 -8
  183. package/dist/templates/epics/epic.md.hbs +8 -2
  184. package/dist/templates/features/feature.md.hbs +3 -3
  185. package/dist/templates/rules/cursor/2001-agile-create-epic.mdc.hbs +1 -1
  186. package/dist/templates/rules/cursor/2002-agile-create-features.mdc.hbs +1 -1
  187. package/dist/templates/rules/cursor/2003-agile-create-user-story.mdc.hbs +1 -1
  188. package/dist/templates/stories/user-story.md.hbs +2 -2
  189. package/dist/templates/tasks/task-list.md.hbs +26 -3
  190. package/dist/utils/logger.d.ts +3 -0
  191. package/dist/utils/logger.d.ts.map +1 -1
  192. package/dist/utils/logger.js +12 -0
  193. package/dist/utils/logger.js.map +1 -1
  194. package/package.json +12 -5
  195. package/dist/templates/templates/adrs/adr-general.md.hbs +0 -46
  196. package/dist/templates/templates/checklists/agile-checklist.md.hbs +0 -49
  197. package/dist/templates/templates/epics/epic.md.hbs +0 -46
  198. package/dist/templates/templates/features/feature.md.hbs +0 -42
  199. package/dist/templates/templates/rules/claude/CLAUDE.md.hbs +0 -63
  200. package/dist/templates/templates/rules/codex/AGENTS.md.hbs +0 -28
  201. package/dist/templates/templates/rules/cursor/2000-agile-checklist.mdc.hbs +0 -33
  202. package/dist/templates/templates/rules/cursor/2001-agile-create-epic.mdc.hbs +0 -35
  203. package/dist/templates/templates/rules/cursor/2002-agile-create-features.mdc.hbs +0 -35
  204. package/dist/templates/templates/rules/cursor/2003-agile-create-user-story.mdc.hbs +0 -31
  205. package/dist/templates/templates/rules/cursor/2100-create-task-list.mdc.hbs +0 -36
  206. package/dist/templates/templates/rules/cursor/2101-implement-task-list.mdc.hbs +0 -28
  207. package/dist/templates/templates/stories/gherkin.feature.hbs +0 -13
  208. package/dist/templates/templates/stories/user-story.md.hbs +0 -28
  209. package/dist/templates/templates/tasks/task-list.md.hbs +0 -24
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/models/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,SAAS,GAAG,OAAO,GAAG,MAAM,GAAG,KAAK,GAAG,WAAW,CAAC;AACvF,MAAM,MAAM,SAAS,GAAG,QAAQ,GAAG,QAAQ,GAAG,OAAO,CAAC;AACtD,MAAM,MAAM,UAAU,GAAG,SAAS,GAAG,aAAa,GAAG,MAAM,CAAC;AAE5D,MAAM,WAAW,eAAe;IAC9B,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,SAAS,EAAE,CAAC;IACrB,WAAW,EAAE;QACX,KAAK,EAAE,MAAM,CAAC;QACd,WAAW,EAAE,MAAM,CAAC;QACpB,YAAY,EAAE,MAAM,CAAC;QACrB,WAAW,EAAE,MAAM,CAAC;KACrB,CAAC;IACF,QAAQ,EAAE;QACR,IAAI,EAAE,MAAM,CAAC;QACb,OAAO,EAAE,MAAM,CAAC;QAChB,KAAK,EAAE,MAAM,CAAC;QACd,IAAI,EAAE,MAAM,CAAC;KACd,CAAC;IACF,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,IAAK,SAAQ,YAAY;IACxC,KAAK,EAAE,MAAM,CAAC;IACd,aAAa,EAAE,MAAM,CAAC;IACtB,WAAW,EAAE,MAAM,CAAC;IACpB,gBAAgB,EAAE,MAAM,CAAC;IACzB,gBAAgB,EAAE,MAAM,CAAC;IACzB,eAAe,EAAE,MAAM,CAAC;IACxB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,EAAE,CAAC;CACtB;AAED,MAAM,WAAW,OAAQ,SAAQ,YAAY;IAC3C,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,UAAU,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,sBAAsB,EAAE,MAAM,EAAE,CAAC;IACjC,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAED,MAAM,WAAW,SAAU,SAAQ,YAAY;IAC7C,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,QAAQ;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,UAAU,CAAC;IACnB,QAAQ,EAAE,QAAQ,EAAE,CAAC;CACtB;AAED,MAAM,WAAW,QAAS,SAAQ,YAAY;IAC5C,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,QAAQ,EAAE,CAAC;CACnB;AAED,MAAM,WAAW,kBAAkB;IACjC,KAAK,EAAE,IAAI,EAAE,CAAC;IACd,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,OAAO,EAAE,SAAS,EAAE,CAAC;IACrB,KAAK,EAAE,QAAQ,EAAE,CAAC;CACnB;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/models/types.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,40 @@
1
+ /**
2
+ * High-level AI orchestration service.
3
+ *
4
+ * Bridges the gap between CLI commands and the AI provider layer.
5
+ * Handles provider initialization, streaming output, and structured
6
+ * JSON generation with Zod validation and retry logic.
7
+ */
8
+ import type { ZodSchema } from 'zod';
9
+ import type { AIProvider, AIMessage, AIRequestOptions } from '../ai/types.js';
10
+ import type { OpenPlanrConfig } from '../models/types.js';
11
+ /**
12
+ * Initialize an AI provider from project config.
13
+ * Dynamically imports the factory to keep non-AI commands fast.
14
+ */
15
+ export declare function getAIProvider(config: OpenPlanrConfig): Promise<AIProvider>;
16
+ /**
17
+ * Check whether AI is configured and available for a given project config.
18
+ */
19
+ export declare function isAIConfigured(config: OpenPlanrConfig): boolean;
20
+ /**
21
+ * Stream AI output to the terminal in real time.
22
+ * Returns the fully accumulated text once streaming completes.
23
+ */
24
+ export declare function streamToTerminal(stream: AsyncIterable<string>): Promise<string>;
25
+ /**
26
+ * Generate a validated JSON response from the AI.
27
+ *
28
+ * Flow:
29
+ * 1. Send messages with JSON mode hint
30
+ * 2. Parse response as JSON
31
+ * 3. Validate with Zod schema
32
+ * 4. On failure, retry once with error feedback
33
+ */
34
+ export declare function generateJSON<T>(provider: AIProvider, messages: AIMessage[], schema: ZodSchema<T>, options?: AIRequestOptions): Promise<T>;
35
+ /**
36
+ * Generate JSON with streaming — shows progress dots in the terminal
37
+ * while the AI generates, then parses the complete response.
38
+ */
39
+ export declare function generateStreamingJSON<T>(provider: AIProvider, messages: AIMessage[], schema: ZodSchema<T>, options?: AIRequestOptions): Promise<T>;
40
+ //# sourceMappingURL=ai-service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ai-service.d.ts","sourceRoot":"","sources":["../../src/services/ai-service.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,KAAK,CAAC;AACrC,OAAO,KAAK,EAAE,UAAU,EAAE,SAAS,EAAE,gBAAgB,EAAoB,MAAM,gBAAgB,CAAC;AAChG,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAI1D;;;GAGG;AACH,wBAAsB,aAAa,CAAC,MAAM,EAAE,eAAe,GAAG,OAAO,CAAC,UAAU,CAAC,CAmBhF;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,eAAe,GAAG,OAAO,CAE/D;AAED;;;GAGG;AACH,wBAAsB,gBAAgB,CACpC,MAAM,EAAE,aAAa,CAAC,MAAM,CAAC,GAC5B,OAAO,CAAC,MAAM,CAAC,CAWjB;AAED;;;;;;;;GAQG;AACH,wBAAsB,YAAY,CAAC,CAAC,EAClC,QAAQ,EAAE,UAAU,EACpB,QAAQ,EAAE,SAAS,EAAE,EACrB,MAAM,EAAE,SAAS,CAAC,CAAC,CAAC,EACpB,OAAO,CAAC,EAAE,gBAAgB,GACzB,OAAO,CAAC,CAAC,CAAC,CA+BZ;AAED;;;GAGG;AACH,wBAAsB,qBAAqB,CAAC,CAAC,EAC3C,QAAQ,EAAE,UAAU,EACpB,QAAQ,EAAE,SAAS,EAAE,EACrB,MAAM,EAAE,SAAS,CAAC,CAAC,CAAC,EACpB,OAAO,CAAC,EAAE,gBAAgB,GACzB,OAAO,CAAC,CAAC,CAAC,CA8CZ"}
@@ -0,0 +1,150 @@
1
+ /**
2
+ * High-level AI orchestration service.
3
+ *
4
+ * Bridges the gap between CLI commands and the AI provider layer.
5
+ * Handles provider initialization, streaming output, and structured
6
+ * JSON generation with Zod validation and retry logic.
7
+ */
8
+ import { AIError } from '../ai/errors.js';
9
+ import { resolveApiKey } from './credentials-service.js';
10
+ /**
11
+ * Initialize an AI provider from project config.
12
+ * Dynamically imports the factory to keep non-AI commands fast.
13
+ */
14
+ export async function getAIProvider(config) {
15
+ if (!config.ai) {
16
+ throw new AIError('AI is not configured. Run `planr init` or `planr config set-provider <name>`.', 'auth');
17
+ }
18
+ const apiKey = await resolveApiKey(config.ai.provider);
19
+ const providerConfig = {
20
+ provider: config.ai.provider,
21
+ model: config.ai.model,
22
+ apiKey,
23
+ baseUrl: config.ai.ollamaBaseUrl,
24
+ };
25
+ const { createAIProvider } = await import('../ai/provider-factory.js');
26
+ return createAIProvider(providerConfig);
27
+ }
28
+ /**
29
+ * Check whether AI is configured and available for a given project config.
30
+ */
31
+ export function isAIConfigured(config) {
32
+ return config.ai != null && config.ai.provider != null;
33
+ }
34
+ /**
35
+ * Stream AI output to the terminal in real time.
36
+ * Returns the fully accumulated text once streaming completes.
37
+ */
38
+ export async function streamToTerminal(stream) {
39
+ const chunks = [];
40
+ for await (const chunk of stream) {
41
+ process.stdout.write(chunk);
42
+ chunks.push(chunk);
43
+ }
44
+ // Ensure a trailing newline after streaming
45
+ process.stdout.write('\n');
46
+ return chunks.join('');
47
+ }
48
+ /**
49
+ * Generate a validated JSON response from the AI.
50
+ *
51
+ * Flow:
52
+ * 1. Send messages with JSON mode hint
53
+ * 2. Parse response as JSON
54
+ * 3. Validate with Zod schema
55
+ * 4. On failure, retry once with error feedback
56
+ */
57
+ export async function generateJSON(provider, messages, schema, options) {
58
+ const requestOptions = {
59
+ temperature: 0.5,
60
+ ...options,
61
+ jsonMode: true,
62
+ };
63
+ let rawResponse = await provider.chatSync(messages, requestOptions);
64
+ let parsed = tryParseAndValidate(rawResponse, schema);
65
+ if (parsed.success)
66
+ return parsed.data;
67
+ // Retry once with error feedback
68
+ const retryMessages = [
69
+ ...messages,
70
+ { role: 'assistant', content: rawResponse },
71
+ {
72
+ role: 'user',
73
+ content: `Your response was not valid JSON or failed validation:\n${parsed.error}\n\nPlease fix and return valid JSON only.`,
74
+ },
75
+ ];
76
+ rawResponse = await provider.chatSync(retryMessages, requestOptions);
77
+ parsed = tryParseAndValidate(rawResponse, schema);
78
+ if (parsed.success)
79
+ return parsed.data;
80
+ throw new AIError(`AI returned invalid JSON after retry: ${parsed.error}`, 'invalid_response');
81
+ }
82
+ /**
83
+ * Generate JSON with streaming — shows progress dots in the terminal
84
+ * while the AI generates, then parses the complete response.
85
+ */
86
+ export async function generateStreamingJSON(provider, messages, schema, options) {
87
+ const requestOptions = {
88
+ temperature: 0.5,
89
+ ...options,
90
+ jsonMode: true,
91
+ };
92
+ // Stream the response, showing dots for progress
93
+ const chunks = [];
94
+ let dotCount = 0;
95
+ const stream = provider.chat(messages, requestOptions);
96
+ for await (const chunk of stream) {
97
+ chunks.push(chunk);
98
+ // Show a dot every ~200 chars of content
99
+ if (chunks.join('').length > (dotCount + 1) * 200) {
100
+ process.stdout.write('.');
101
+ dotCount++;
102
+ }
103
+ }
104
+ if (dotCount > 0)
105
+ process.stdout.write('\n');
106
+ const rawResponse = chunks.join('');
107
+ let parsed = tryParseAndValidate(rawResponse, schema);
108
+ if (parsed.success)
109
+ return parsed.data;
110
+ // Retry once with error feedback (non-streaming for retry)
111
+ const retryMessages = [
112
+ ...messages,
113
+ { role: 'assistant', content: rawResponse },
114
+ {
115
+ role: 'user',
116
+ content: `Your response was not valid JSON or failed validation:\n${parsed.error}\n\nPlease fix and return valid JSON only.`,
117
+ },
118
+ ];
119
+ const retryResponse = await provider.chatSync(retryMessages, requestOptions);
120
+ parsed = tryParseAndValidate(retryResponse, schema);
121
+ if (parsed.success)
122
+ return parsed.data;
123
+ throw new AIError(`AI returned invalid JSON after retry: ${parsed.error}`, 'invalid_response');
124
+ }
125
+ /** Extract JSON from a response that might contain markdown code fences. */
126
+ function extractJSON(raw) {
127
+ // Strip markdown code fences if present
128
+ const fenceMatch = raw.match(/```(?:json)?\s*\n?([\s\S]*?)\n?\s*```/);
129
+ if (fenceMatch)
130
+ return fenceMatch[1].trim();
131
+ return raw.trim();
132
+ }
133
+ function tryParseAndValidate(raw, schema) {
134
+ try {
135
+ const cleaned = extractJSON(raw);
136
+ const json = JSON.parse(cleaned);
137
+ const result = schema.safeParse(json);
138
+ if (result.success) {
139
+ return { success: true, data: result.data };
140
+ }
141
+ const errors = result.error.issues
142
+ .map((i) => ` ${i.path.join('.')}: ${i.message}`)
143
+ .join('\n');
144
+ return { success: false, error: `Validation errors:\n${errors}` };
145
+ }
146
+ catch (err) {
147
+ return { success: false, error: `JSON parse error: ${err.message}` };
148
+ }
149
+ }
150
+ //# sourceMappingURL=ai-service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ai-service.js","sourceRoot":"","sources":["../../src/services/ai-service.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,49 @@
1
+ /**
2
+ * Shared artifact-gathering utilities for task generation prompts.
3
+ *
4
+ * Collects all related artifacts (stories, gherkin, ADRs, epic, feature)
5
+ * into a single context object that `buildTasksPrompt()` consumes.
6
+ */
7
+ import type { OpenPlanrConfig } from '../models/types.js';
8
+ export interface TasksPromptContext {
9
+ /** One or more user stories to generate tasks from. */
10
+ stories: Array<{
11
+ id: string;
12
+ raw: string;
13
+ }>;
14
+ /** Gherkin acceptance criteria for stories. */
15
+ gherkinScenarios: Array<{
16
+ storyId: string;
17
+ content: string;
18
+ }>;
19
+ /** Parent feature raw markdown. */
20
+ featureRaw?: string;
21
+ /** Parent epic raw markdown. */
22
+ epicRaw?: string;
23
+ /** Architecture decision records. */
24
+ adrs: Array<{
25
+ id: string;
26
+ content: string;
27
+ }>;
28
+ /** Formatted codebase context (tech stack, folder tree, related files). */
29
+ codebaseContext?: string;
30
+ /** Creation scope hint for AI task naming. */
31
+ scope?: {
32
+ type: 'feature';
33
+ id: string;
34
+ } | {
35
+ type: 'story';
36
+ id: string;
37
+ };
38
+ }
39
+ /**
40
+ * Gather all context for a single user story.
41
+ * Used by `--story` flag and `planr plan` per-story generation.
42
+ */
43
+ export declare function gatherStoryArtifacts(projectDir: string, config: OpenPlanrConfig, storyId: string): Promise<TasksPromptContext>;
44
+ /**
45
+ * Gather all context for a feature — all stories + gherkin + ADRs + parent epic.
46
+ * Used by `--feature` flag.
47
+ */
48
+ export declare function gatherFeatureArtifacts(projectDir: string, config: OpenPlanrConfig, featureId: string): Promise<TasksPromptContext>;
49
+ //# sourceMappingURL=artifact-gathering.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"artifact-gathering.d.ts","sourceRoot":"","sources":["../../src/services/artifact-gathering.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAUH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAE1D,MAAM,WAAW,kBAAkB;IACjC,uDAAuD;IACvD,OAAO,EAAE,KAAK,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC5C,+CAA+C;IAC/C,gBAAgB,EAAE,KAAK,CAAC;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC9D,mCAAmC;IACnC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,gCAAgC;IAChC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,qCAAqC;IACrC,IAAI,EAAE,KAAK,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC7C,2EAA2E;IAC3E,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,8CAA8C;IAC9C,KAAK,CAAC,EAAE;QAAE,IAAI,EAAE,SAAS,CAAC;QAAC,EAAE,EAAE,MAAM,CAAA;KAAE,GAAG;QAAE,IAAI,EAAE,OAAO,CAAC;QAAC,EAAE,EAAE,MAAM,CAAA;KAAE,CAAC;CACzE;AAED;;;GAGG;AACH,wBAAsB,oBAAoB,CACxC,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,eAAe,EACvB,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,kBAAkB,CAAC,CAmC7B;AAED;;;GAGG;AACH,wBAAsB,sBAAsB,CAC1C,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,eAAe,EACvB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,kBAAkB,CAAC,CA2C7B"}
@@ -0,0 +1,128 @@
1
+ /**
2
+ * Shared artifact-gathering utilities for task generation prompts.
3
+ *
4
+ * Collects all related artifacts (stories, gherkin, ADRs, epic, feature)
5
+ * into a single context object that `buildTasksPrompt()` consumes.
6
+ */
7
+ import path from 'node:path';
8
+ import { readArtifact, readArtifactRaw, listArtifacts, getArtifactDir, } from './artifact-service.js';
9
+ import { readFile, listFiles } from '../utils/fs.js';
10
+ /**
11
+ * Gather all context for a single user story.
12
+ * Used by `--story` flag and `planr plan` per-story generation.
13
+ */
14
+ export async function gatherStoryArtifacts(projectDir, config, storyId) {
15
+ const storyRaw = await readArtifactRaw(projectDir, config, 'story', storyId);
16
+ if (!storyRaw)
17
+ throw new Error(`Story ${storyId} not found.`);
18
+ const stories = [{ id: storyId, raw: storyRaw }];
19
+ // Read gherkin for this story
20
+ const gherkinScenarios = [];
21
+ const gherkinContent = await findGherkinContent(projectDir, config, storyId);
22
+ if (gherkinContent) {
23
+ gherkinScenarios.push({ storyId, content: gherkinContent });
24
+ }
25
+ // Read parent feature + epic
26
+ const storyData = await readArtifact(projectDir, config, 'story', storyId);
27
+ const featureId = storyData?.data.featureId;
28
+ let featureRaw;
29
+ let epicRaw;
30
+ if (featureId) {
31
+ featureRaw = (await readArtifactRaw(projectDir, config, 'feature', featureId)) || undefined;
32
+ const featureData = await readArtifact(projectDir, config, 'feature', featureId);
33
+ const epicId = featureData?.data.epicId;
34
+ if (epicId) {
35
+ epicRaw = (await readArtifactRaw(projectDir, config, 'epic', epicId)) || undefined;
36
+ }
37
+ }
38
+ // Read ADRs
39
+ const adrs = await readAllADRs(projectDir, config);
40
+ // Build codebase context
41
+ const codebaseContext = await buildCodebaseStr(projectDir, storyRaw + (featureRaw || ''));
42
+ return { stories, gherkinScenarios, featureRaw, epicRaw, adrs, codebaseContext };
43
+ }
44
+ /**
45
+ * Gather all context for a feature — all stories + gherkin + ADRs + parent epic.
46
+ * Used by `--feature` flag.
47
+ */
48
+ export async function gatherFeatureArtifacts(projectDir, config, featureId) {
49
+ const featureRaw = await readArtifactRaw(projectDir, config, 'feature', featureId);
50
+ if (!featureRaw)
51
+ throw new Error(`Feature ${featureId} not found.`);
52
+ // Read parent epic
53
+ const featureData = await readArtifact(projectDir, config, 'feature', featureId);
54
+ const epicId = featureData?.data.epicId;
55
+ let epicRaw;
56
+ if (epicId) {
57
+ epicRaw = (await readArtifactRaw(projectDir, config, 'epic', epicId)) || undefined;
58
+ }
59
+ // Find all stories under this feature
60
+ const allStories = await listArtifacts(projectDir, config, 'story');
61
+ const stories = [];
62
+ const gherkinScenarios = [];
63
+ for (const s of allStories) {
64
+ const data = await readArtifact(projectDir, config, 'story', s.id);
65
+ if (data && data.data.featureId === featureId) {
66
+ const raw = await readArtifactRaw(projectDir, config, 'story', s.id);
67
+ if (raw) {
68
+ stories.push({ id: s.id, raw });
69
+ const gherkin = await findGherkinContent(projectDir, config, s.id);
70
+ if (gherkin) {
71
+ gherkinScenarios.push({ storyId: s.id, content: gherkin });
72
+ }
73
+ }
74
+ }
75
+ }
76
+ if (stories.length === 0) {
77
+ throw new Error(`No user stories found for feature ${featureId}. Create stories first with: planr story create --feature ${featureId}`);
78
+ }
79
+ // Read ADRs
80
+ const adrs = await readAllADRs(projectDir, config);
81
+ // Build codebase context from all story + feature content
82
+ const allText = stories.map((s) => s.raw).join('\n') + '\n' + featureRaw;
83
+ const codebaseContext = await buildCodebaseStr(projectDir, allText);
84
+ return { stories, gherkinScenarios, featureRaw, epicRaw, adrs, codebaseContext };
85
+ }
86
+ /**
87
+ * Read a gherkin file for a given story ID. Returns content or null.
88
+ */
89
+ async function findGherkinContent(projectDir, config, storyId) {
90
+ const storyDir = path.join(projectDir, getArtifactDir(config, 'story'));
91
+ const files = await listFiles(storyDir, new RegExp(`^${storyId}-gherkin\\.feature$`));
92
+ if (files.length === 0)
93
+ return null;
94
+ return readFile(path.join(storyDir, files[0]));
95
+ }
96
+ /**
97
+ * Read all ADR artifacts in the project.
98
+ */
99
+ async function readAllADRs(projectDir, config) {
100
+ const adrs = [];
101
+ try {
102
+ const allAdrs = await listArtifacts(projectDir, config, 'adr');
103
+ for (const a of allAdrs) {
104
+ const raw = await readArtifactRaw(projectDir, config, 'adr', a.id);
105
+ if (raw)
106
+ adrs.push({ id: a.id, content: raw });
107
+ }
108
+ }
109
+ catch {
110
+ // ADRs may not exist — graceful fallback
111
+ }
112
+ return adrs;
113
+ }
114
+ /**
115
+ * Build formatted codebase context string from text content.
116
+ */
117
+ async function buildCodebaseStr(projectDir, textContent) {
118
+ try {
119
+ const { buildCodebaseContext, formatCodebaseContext, extractKeywords } = await import('../ai/codebase/index.js');
120
+ const keywords = extractKeywords(textContent);
121
+ const ctx = await buildCodebaseContext(projectDir, keywords);
122
+ return formatCodebaseContext(ctx);
123
+ }
124
+ catch {
125
+ return undefined;
126
+ }
127
+ }
128
+ //# sourceMappingURL=artifact-gathering.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"artifact-gathering.js","sourceRoot":"","sources":["../../src/services/artifact-gathering.ts"],"names":[],"mappings":"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"}
@@ -14,4 +14,51 @@ export declare function readArtifact(projectDir: string, config: OpenPlanrConfig
14
14
  content: string;
15
15
  filePath: string;
16
16
  } | null>;
17
+ /**
18
+ * Read the full raw content of an artifact file (frontmatter + body).
19
+ * Useful for passing the complete artifact text to AI prompts.
20
+ */
21
+ export declare function readArtifactRaw(projectDir: string, config: OpenPlanrConfig, type: ArtifactType, id: string): Promise<string | null>;
22
+ /**
23
+ * Overwrite an existing artifact file in place.
24
+ */
25
+ export declare function updateArtifact(projectDir: string, config: OpenPlanrConfig, type: ArtifactType, id: string, content: string): Promise<void>;
26
+ /**
27
+ * Resolve an artifact ID to its actual filename (without path).
28
+ * Returns the filename like "EPIC-002-markdown-to-kanban-board.md"
29
+ * or falls back to "ID.md" if the file can't be found.
30
+ */
31
+ export declare function resolveArtifactFilename(projectDir: string, config: OpenPlanrConfig, type: ArtifactType, id: string): Promise<string>;
32
+ /**
33
+ * Add a child reference link to a parent artifact's markdown file.
34
+ *
35
+ * Replaces the "No X created yet" placeholder with a link list,
36
+ * or appends to existing links in the appropriate section.
37
+ *
38
+ * @param childId e.g. "FEAT-002"
39
+ * @param childTitle e.g. "Markdown Task Parser Engine"
40
+ * @param childType e.g. "feature"
41
+ */
42
+ export declare function addChildReference(projectDir: string, config: OpenPlanrConfig, parentType: ArtifactType, parentId: string, childType: ArtifactType, childId: string, childTitle: string): Promise<void>;
43
+ /**
44
+ * Determine artifact type from an ID prefix.
45
+ */
46
+ export declare function findArtifactTypeById(id: string): ArtifactType | null;
47
+ /**
48
+ * Read the parent chain for an artifact (story → feature → epic).
49
+ */
50
+ export declare function getParentChain(projectDir: string, config: OpenPlanrConfig, type: ArtifactType, id: string): Promise<{
51
+ epic?: {
52
+ data: Record<string, unknown>;
53
+ content: string;
54
+ };
55
+ feature?: {
56
+ data: Record<string, unknown>;
57
+ content: string;
58
+ };
59
+ story?: {
60
+ data: Record<string, unknown>;
61
+ content: string;
62
+ };
63
+ }>;
17
64
  //# sourceMappingURL=artifact-service.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"artifact-service.d.ts","sourceRoot":"","sources":["../../src/services/artifact-service.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAWxE,wBAAgB,cAAc,CAAC,MAAM,EAAE,eAAe,EAAE,IAAI,EAAE,YAAY,GAAG,MAAM,CAElF;AAED,wBAAsB,cAAc,CAClC,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,eAAe,EACvB,IAAI,EAAE,YAAY,EAClB,YAAY,EAAE,MAAM,EACpB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC5B,OAAO,CAAC;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAC,CAqB3C;AAED,wBAAsB,aAAa,CACjC,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,eAAe,EACvB,IAAI,EAAE,YAAY,GACjB,OAAO,CAAC,KAAK,CAAC;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC,CAgBjE;AAED,wBAAsB,YAAY,CAChC,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,eAAe,EACvB,IAAI,EAAE,YAAY,EAClB,EAAE,EAAE,MAAM,GACT,OAAO,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAAC,CAStF"}
1
+ {"version":3,"file":"artifact-service.d.ts","sourceRoot":"","sources":["../../src/services/artifact-service.ts"],"names":[],"mappings":"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"}
@@ -4,6 +4,7 @@ import { slugify } from '../utils/slugify.js';
4
4
  import { parseMarkdown } from '../utils/markdown.js';
5
5
  import { getNextId } from './id-service.js';
6
6
  import { renderTemplate } from './template-service.js';
7
+ import { logger } from '../utils/logger.js';
7
8
  const ARTIFACT_DIR_MAP = {
8
9
  epic: 'epics',
9
10
  feature: 'features',
@@ -32,6 +33,7 @@ export async function createArtifact(projectDir, config, type, templateFile, dat
32
33
  projectName: config.projectName,
33
34
  }, config.templateOverrides);
34
35
  await writeFile(filePath, content);
36
+ logger.debug(`Created ${type} artifact: ${id} → ${filePath}`);
35
37
  return { id, filePath };
36
38
  }
37
39
  export async function listArtifacts(projectDir, config, type) {
@@ -56,8 +58,175 @@ export async function readArtifact(projectDir, config, type, id) {
56
58
  if (files.length === 0)
57
59
  return null;
58
60
  const filePath = path.join(dir, files[0]);
61
+ logger.debug(`Reading ${type} artifact: ${id} ← ${filePath}`);
59
62
  const raw = await readFile(filePath);
60
63
  const parsed = parseMarkdown(raw);
61
64
  return { ...parsed, filePath };
62
65
  }
66
+ /**
67
+ * Read the full raw content of an artifact file (frontmatter + body).
68
+ * Useful for passing the complete artifact text to AI prompts.
69
+ */
70
+ export async function readArtifactRaw(projectDir, config, type, id) {
71
+ const dir = path.join(projectDir, getArtifactDir(config, type));
72
+ const files = await listFiles(dir, new RegExp(`^${id}-.*\\.md$`));
73
+ if (files.length === 0)
74
+ return null;
75
+ return readFile(path.join(dir, files[0]));
76
+ }
77
+ /**
78
+ * Overwrite an existing artifact file in place.
79
+ */
80
+ export async function updateArtifact(projectDir, config, type, id, content) {
81
+ const dir = path.join(projectDir, getArtifactDir(config, type));
82
+ const files = await listFiles(dir, new RegExp(`^${id}-.*\\.md$`));
83
+ if (files.length === 0)
84
+ throw new Error(`Artifact ${id} not found.`);
85
+ const filePath = path.join(dir, files[0]);
86
+ await writeFile(filePath, content);
87
+ }
88
+ /**
89
+ * Resolve an artifact ID to its actual filename (without path).
90
+ * Returns the filename like "EPIC-002-markdown-to-kanban-board.md"
91
+ * or falls back to "ID.md" if the file can't be found.
92
+ */
93
+ export async function resolveArtifactFilename(projectDir, config, type, id) {
94
+ const dir = path.join(projectDir, getArtifactDir(config, type));
95
+ const files = await listFiles(dir, new RegExp(`^${id}-.*\\.md$`));
96
+ if (files.length > 0)
97
+ return files[0].replace(/\.md$/, '');
98
+ return id;
99
+ }
100
+ /**
101
+ * Add a child reference link to a parent artifact's markdown file.
102
+ *
103
+ * Replaces the "No X created yet" placeholder with a link list,
104
+ * or appends to existing links in the appropriate section.
105
+ *
106
+ * @param childId e.g. "FEAT-002"
107
+ * @param childTitle e.g. "Markdown Task Parser Engine"
108
+ * @param childType e.g. "feature"
109
+ */
110
+ export async function addChildReference(projectDir, config, parentType, parentId, childType, childId, childTitle) {
111
+ const parentRaw = await readArtifactRaw(projectDir, config, parentType, parentId);
112
+ if (!parentRaw)
113
+ return;
114
+ const childFilename = await resolveArtifactFilename(projectDir, config, childType, childId);
115
+ const relDir = ARTIFACT_DIR_MAP[childType] || childType;
116
+ const link = `- [${childId}: ${childTitle}](../${relDir}/${childFilename}.md)`;
117
+ // Pattern to match placeholder lines like "_No X created yet..._" or "_Run `planr ...` to generate..._"
118
+ const placeholderPattern = /^_(?:No .+ created yet\.|Run .+ to (?:generate|create)).+_$/m;
119
+ let updated;
120
+ if (placeholderPattern.test(parentRaw)) {
121
+ // Replace placeholder with the first child link
122
+ updated = parentRaw.replace(placeholderPattern, link);
123
+ }
124
+ else {
125
+ // Append after the last existing child link in the same section
126
+ // Find the section heading for children (## Features, ## User Stories, ## Tasks)
127
+ const sectionMap = {
128
+ feature: '## Features',
129
+ story: '## User Stories',
130
+ task: '## Tasks',
131
+ };
132
+ const sectionHeading = sectionMap[childType];
133
+ if (!sectionHeading)
134
+ return;
135
+ const sectionIdx = parentRaw.indexOf(sectionHeading);
136
+ if (sectionIdx === -1)
137
+ return;
138
+ // Find the end of the child links block (last line starting with "- [")
139
+ const afterSection = parentRaw.slice(sectionIdx);
140
+ const lines = afterSection.split('\n');
141
+ let lastLinkLineIdx = -1;
142
+ for (let i = 1; i < lines.length; i++) {
143
+ if (lines[i].startsWith('- [')) {
144
+ lastLinkLineIdx = i;
145
+ }
146
+ else if (lines[i].startsWith('#') || (lastLinkLineIdx > -1 && lines[i].trim() !== '')) {
147
+ break;
148
+ }
149
+ }
150
+ if (lastLinkLineIdx > -1) {
151
+ // Insert after the last link line
152
+ lines.splice(lastLinkLineIdx + 1, 0, link);
153
+ updated = parentRaw.slice(0, sectionIdx) + lines.join('\n');
154
+ }
155
+ else {
156
+ // No links found after heading, add after the heading line
157
+ lines.splice(1, 0, link);
158
+ updated = parentRaw.slice(0, sectionIdx) + lines.join('\n');
159
+ }
160
+ }
161
+ await updateArtifact(projectDir, config, parentType, parentId, updated);
162
+ }
163
+ /**
164
+ * Determine artifact type from an ID prefix.
165
+ */
166
+ export function findArtifactTypeById(id) {
167
+ const prefix = id.split('-')[0];
168
+ const map = {
169
+ EPIC: 'epic',
170
+ FEAT: 'feature',
171
+ US: 'story',
172
+ TASK: 'task',
173
+ ADR: 'adr',
174
+ };
175
+ return map[prefix] || null;
176
+ }
177
+ /**
178
+ * Read the parent chain for an artifact (story → feature → epic).
179
+ */
180
+ export async function getParentChain(projectDir, config, type, id) {
181
+ const result = {};
182
+ const artifact = await readArtifact(projectDir, config, type, id);
183
+ if (!artifact)
184
+ return result;
185
+ if (type === 'task') {
186
+ const storyId = artifact.data.storyId;
187
+ if (storyId) {
188
+ const story = await readArtifact(projectDir, config, 'story', storyId);
189
+ if (story) {
190
+ result.story = { data: story.data, content: story.content };
191
+ const featureId = story.data.featureId;
192
+ if (featureId) {
193
+ const feature = await readArtifact(projectDir, config, 'feature', featureId);
194
+ if (feature) {
195
+ result.feature = { data: feature.data, content: feature.content };
196
+ const epicId = feature.data.epicId;
197
+ if (epicId) {
198
+ const epic = await readArtifact(projectDir, config, 'epic', epicId);
199
+ if (epic)
200
+ result.epic = { data: epic.data, content: epic.content };
201
+ }
202
+ }
203
+ }
204
+ }
205
+ }
206
+ }
207
+ else if (type === 'story') {
208
+ const featureId = artifact.data.featureId;
209
+ if (featureId) {
210
+ const feature = await readArtifact(projectDir, config, 'feature', featureId);
211
+ if (feature) {
212
+ result.feature = { data: feature.data, content: feature.content };
213
+ const epicId = feature.data.epicId;
214
+ if (epicId) {
215
+ const epic = await readArtifact(projectDir, config, 'epic', epicId);
216
+ if (epic)
217
+ result.epic = { data: epic.data, content: epic.content };
218
+ }
219
+ }
220
+ }
221
+ }
222
+ else if (type === 'feature') {
223
+ const epicId = artifact.data.epicId;
224
+ if (epicId) {
225
+ const epic = await readArtifact(projectDir, config, 'epic', epicId);
226
+ if (epic)
227
+ result.epic = { data: epic.data, content: epic.content };
228
+ }
229
+ }
230
+ return result;
231
+ }
63
232
  //# sourceMappingURL=artifact-service.js.map