@applica-software-guru/sdd-core 1.8.1 → 1.8.2

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 (57) hide show
  1. package/dist/index.d.ts +1 -1
  2. package/dist/index.d.ts.map +1 -1
  3. package/dist/index.js +3 -3
  4. package/dist/index.js.map +1 -1
  5. package/dist/parser/bug-parser.d.ts.map +1 -1
  6. package/dist/parser/bug-parser.js +2 -1
  7. package/dist/parser/bug-parser.js.map +1 -1
  8. package/dist/parser/cr-parser.d.ts.map +1 -1
  9. package/dist/parser/cr-parser.js +2 -1
  10. package/dist/parser/cr-parser.js.map +1 -1
  11. package/dist/prompt/draft-prompt-generator.d.ts +1 -1
  12. package/dist/prompt/draft-prompt-generator.d.ts.map +1 -1
  13. package/dist/prompt/draft-prompt-generator.js +19 -35
  14. package/dist/prompt/draft-prompt-generator.js.map +1 -1
  15. package/dist/remote/api-client.d.ts +2 -2
  16. package/dist/remote/api-client.d.ts.map +1 -1
  17. package/dist/remote/api-client.js +4 -4
  18. package/dist/remote/api-client.js.map +1 -1
  19. package/dist/remote/sync-engine.js +12 -8
  20. package/dist/remote/sync-engine.js.map +1 -1
  21. package/dist/scaffold/skill-adapters.d.ts +0 -9
  22. package/dist/scaffold/skill-adapters.d.ts.map +1 -1
  23. package/dist/scaffold/skill-adapters.js +17 -0
  24. package/dist/scaffold/skill-adapters.js.map +1 -1
  25. package/dist/scaffold/templates.d.ts +1 -5
  26. package/dist/scaffold/templates.d.ts.map +1 -1
  27. package/dist/scaffold/templates.generated.d.ts +7 -0
  28. package/dist/scaffold/templates.generated.d.ts.map +1 -0
  29. package/dist/scaffold/templates.generated.js +464 -0
  30. package/dist/scaffold/templates.generated.js.map +1 -0
  31. package/dist/scaffold/templates.js +8 -338
  32. package/dist/scaffold/templates.js.map +1 -1
  33. package/dist/sdd.d.ts +0 -1
  34. package/dist/sdd.d.ts.map +1 -1
  35. package/dist/sdd.js +1 -18
  36. package/dist/sdd.js.map +1 -1
  37. package/package.json +2 -1
  38. package/scripts/generate-templates.mjs +38 -0
  39. package/src/index.ts +1 -1
  40. package/src/parser/bug-parser.ts +5 -3
  41. package/src/parser/cr-parser.ts +5 -3
  42. package/src/prompt/draft-prompt-generator.ts +18 -38
  43. package/src/remote/api-client.ts +2 -2
  44. package/src/remote/sync-engine.ts +15 -15
  45. package/src/scaffold/skill-adapters.ts +18 -11
  46. package/src/scaffold/templates.generated.ts +466 -0
  47. package/src/scaffold/templates.ts +9 -342
  48. package/src/sdd.ts +1 -19
  49. package/tests/agent-defaults.test.ts +24 -0
  50. package/tests/api-client.test.ts +6 -6
  51. package/tests/draft-prompt.test.ts +78 -0
  52. package/dist/prompt/apply-prompt-generator.d.ts +0 -4
  53. package/dist/prompt/apply-prompt-generator.d.ts.map +0 -1
  54. package/dist/prompt/apply-prompt-generator.js +0 -97
  55. package/dist/prompt/apply-prompt-generator.js.map +0 -1
  56. package/src/prompt/apply-prompt-generator.ts +0 -117
  57. package/tests/apply.test.ts +0 -117
@@ -1,3 +1,12 @@
1
+ export {
2
+ SKILL_MD_TEMPLATE,
3
+ SKILL_UI_MD_TEMPLATE,
4
+ SKILL_REMOTE_MD_TEMPLATE,
5
+ FILE_FORMAT_REFERENCE,
6
+ CHANGE_REQUESTS_REFERENCE,
7
+ BUGS_REFERENCE,
8
+ } from "./templates.generated.js";
9
+
1
10
  const now = () => new Date().toISOString();
2
11
 
3
12
  function mdTemplate(title: string, content: string): string {
@@ -17,348 +26,6 @@ export interface ProjectInfo {
17
26
  description: string;
18
27
  }
19
28
 
20
- export const SKILL_MD_TEMPLATE = `---
21
- name: sdd
22
- description: >
23
- Story Driven Development workflow. Use when working in a project
24
- with .sdd/config.yaml, or when the user mentions SDD, sdd sync,
25
- story driven development, or spec-driven development.
26
- license: MIT
27
- compatibility: Requires sdd CLI (npm i -g @applica-software-guru/sdd)
28
- allowed-tools: Bash(sdd:*) Read Glob Grep
29
- metadata:
30
- author: applica-software-guru
31
- version: "1.0"
32
- ---
33
-
34
- # SDD — Story Driven Development
35
-
36
- ## Detection
37
-
38
- This project uses SDD if \`.sdd/config.yaml\` exists in the project root.
39
-
40
- ## Workflow
41
-
42
- Follow this loop every time you work on an SDD project:
43
-
44
- 1. Run \`sdd bug open\` — check if there are open bugs to fix first
45
- 2. If there are open bugs, fix the code/docs, then run \`sdd mark-bug-resolved\`
46
- 3. Run \`sdd cr pending\` — check if there are change requests to process
47
- 4. If there are pending CRs, apply them to the docs, then run \`sdd mark-cr-applied\`
48
- 5. Run \`sdd sync\` to see what needs to be implemented
49
- 6. Read the documentation files listed in the sync output
50
- 7. Implement what each file describes, writing code inside \`code/\`
51
- 8. After implementing, mark files as synced:
52
-
53
- \`\`\`
54
- sdd mark-synced product/features/auth.md
55
- \`\`\`
56
-
57
- Or mark all pending files at once:
58
-
59
- \`\`\`
60
- sdd mark-synced
61
- \`\`\`
62
-
63
- 9. **Commit immediately after mark-synced** — this is mandatory:
64
-
65
- \`\`\`
66
- git add -A && git commit -m "sdd sync: <brief description of what was implemented>"
67
- \`\`\`
68
-
69
- Do NOT skip this step. Every mark-synced must be followed by a git commit.
70
-
71
- ### Removing a feature
72
-
73
- If a documentation file has \`status: deleted\`, it means that feature should be removed.
74
- Delete the related code in \`code/\`, then run \`sdd mark-synced <file>\` (the doc file will be removed automatically), then commit.
75
-
76
- ## Available commands
77
-
78
- - \`sdd status\` — See all documentation files and their state (new/changed/deleted/synced)
79
- - \`sdd diff\` — See what changed since last sync
80
- - \`sdd sync\` — Get the sync prompt for pending files (includes git diff for changed files)
81
- - \`sdd validate\` — Check for broken references and issues
82
- - \`sdd mark-synced [files...]\` — Mark specific files (or all) as synced
83
- - \`sdd cr list\` — List all change requests with their status
84
- - \`sdd cr pending\` — Show draft change requests to process
85
- - \`sdd mark-cr-applied [files...]\` — Mark change requests as applied
86
- - \`sdd bug list\` — List all bugs with their status
87
- - \`sdd bug open\` — Show open bugs to fix
88
- - \`sdd mark-bug-resolved [files...]\` — Mark bugs as resolved
89
-
90
- ## Rules
91
-
92
- 1. **Always commit after mark-synced** — run \`git add -A && git commit -m "sdd sync: ..."\` immediately after \`sdd mark-synced\`. Never leave synced files uncommitted.
93
- 2. Before running \`sdd sync\`, check for open bugs with \`sdd bug open\` and pending change requests with \`sdd cr pending\`
94
- 3. If there are pending CRs, apply them to the docs first, then mark them with \`sdd mark-cr-applied\`
95
- 4. Only implement what the sync prompt asks for
96
- 5. All generated code goes inside \`code/\`
97
- 6. Respect all constraints in \`## Agent Notes\` sections (if present)
98
- 7. Do not edit files inside \`.sdd/\` manually
99
-
100
- ## Project structure
101
-
102
- - \`product/\` — What to build (vision, users, features)
103
- - \`system/\` — How to build it (entities, architecture, tech stack, interfaces)
104
- - \`code/\` — All generated source code goes here
105
- - \`change-requests/\` — Change requests to the documentation
106
- - \`bugs/\` — Bug reports
107
- - \`.sdd/\` — Project config and sync state (do not edit)
108
-
109
- ## References
110
-
111
- For detailed information on specific topics, see:
112
-
113
- - [File format and status lifecycle](references/file-format.md)
114
- - [Change Requests workflow](references/change-requests.md)
115
- - [Bug workflow](references/bugs.md)
116
- `;
117
-
118
- export const SKILL_UI_MD_TEMPLATE = `---
119
- name: sdd-ui
120
- description: >
121
- UI Component Editor workflow. Use when the user wants to implement a React component
122
- from a screenshot in an SDD project, iterating visually with live preview.
123
- license: MIT
124
- compatibility: >
125
- Requires sdd CLI (npm i -g @applica-software-guru/sdd).
126
- Requires Playwright MCP configured in Claude Code
127
- (e.g. @playwright/mcp or @executeautomation/playwright-mcp).
128
- allowed-tools: Bash(sdd:*) Read Glob Grep Edit Write mcp__playwright__screenshot mcp__playwright__navigate mcp__playwright__click
129
- metadata:
130
- author: applica-software-guru
131
- version: "1.1"
132
- ---
133
-
134
- # SDD UI — Visual Component Editor
135
-
136
- ## Purpose
137
-
138
- Use this workflow when implementing a React component from a screenshot reference in an SDD project.
139
- The split-panel editor shows the spec screenshot on the left and the live component on the right,
140
- so you can iterate visually until they match.
141
-
142
- ## Prerequisites
143
-
144
- - \`sdd\` CLI installed globally
145
- - Playwright MCP configured in Claude Code settings
146
- - e.g. \`@playwright/mcp\` or \`@executeautomation/playwright-mcp\`
147
- - If not configured, inform the user and stop — visual feedback won't work without it
148
-
149
- ## Workflow
150
-
151
- ### Step 1 — Read the spec
152
-
153
- Read the SDD feature file to understand what the component should look like and do.
154
- Look for any screenshot paths referenced in the feature doc.
155
-
156
- ### Step 2 — Launch the editor
157
-
158
- \`\`\`bash
159
- # Single screenshot — detached (recommended when run by an agent)
160
- sdd ui launch-editor LoginForm \\
161
- --screenshot product/features/auth/login.png \\
162
- --detach
163
-
164
- # Multiple screenshots (e.g. desktop + mobile)
165
- sdd ui launch-editor LoginForm \\
166
- --screenshot product/features/auth/login-desktop.png \\
167
- --screenshot product/features/auth/login-mobile.png \\
168
- --detach
169
- \`\`\`
170
-
171
- The command will:
172
- - Scaffold \`code/components/LoginForm.tsx\` if it doesn't exist
173
- - Print the exact component file path to edit
174
- - Start the editor at \`http://localhost:5174\`
175
-
176
- With \`--detach\` the process runs in background and the terminal is immediately free.
177
- Without \`--detach\` it runs in foreground (use Ctrl+C to stop).
178
-
179
- With multiple screenshots, the left panel shows a tab per screenshot.
180
- With a single screenshot, no tab bar is shown.
181
-
182
- ### Step 3 — Implement the component
183
-
184
- Edit the file printed by \`sdd ui launch-editor\` (e.g. \`code/components/LoginForm.tsx\`).
185
-
186
- Write a React component that matches the screenshot. Use standard HTML/CSS or inline styles —
187
- no external UI library unless the project already uses one.
188
-
189
- Vite HMR will update the right panel automatically on every save.
190
-
191
- ### Step 4 — Visual check with Playwright
192
-
193
- After each save, screenshot the live preview and compare it with the spec:
194
-
195
- \`\`\`
196
- mcp__playwright__navigate http://localhost:5174
197
- mcp__playwright__screenshot
198
- \`\`\`
199
-
200
- The left panel already shows the spec screenshot for direct comparison.
201
- Note differences in layout, spacing, typography, colors, and component structure.
202
-
203
- ### Step 5 — Iterate
204
-
205
- Edit component → Playwright screenshot → compare → repeat until the preview matches the spec.
206
-
207
- ### Step 6 — Finalize
208
-
209
- \`\`\`bash
210
- sdd ui stop
211
- sdd mark-synced product/features/auth/login.md
212
- git add -A && git commit -m "sdd sync: implement LoginForm component"
213
- \`\`\`
214
-
215
- ## Notes
216
-
217
- - The component file is permanent — it lives in \`code/components/\` and is part of your project
218
- - Port \`5174\` by default (not \`5173\`) to avoid conflicts with the user's app dev server
219
- - If the component needs props, scaffold it with hardcoded sample data for the preview
220
-
221
- ## Troubleshooting
222
-
223
- **Playwright MCP not configured:**
224
- Stop and ask the user to add it to their Claude Code MCP settings before continuing.
225
-
226
- **Component import fails in preview:**
227
- Check that the component file has a valid default export and no TypeScript errors.
228
-
229
- **Port already in use:**
230
- \`sdd ui launch-editor LoginForm --screenshot login.png --port 5175\`
231
- `;
232
-
233
- export const FILE_FORMAT_REFERENCE = `# File Format and Status Lifecycle
234
-
235
- ## YAML Frontmatter
236
-
237
- Every \`.md\` file in \`product/\` and \`system/\` must start with this YAML frontmatter:
238
-
239
- \`\`\`yaml
240
- ---
241
- title: "File title"
242
- status: new
243
- author: ""
244
- last-modified: "2025-01-01T00:00:00.000Z"
245
- version: "1.0"
246
- ---
247
- \`\`\`
248
-
249
- ## Status values
250
-
251
- - **\`new\`** — new file, needs to be implemented
252
- - **\`changed\`** — modified since last sync, code needs updating
253
- - **\`deleted\`** — feature to be removed, agent should delete related code
254
- - **\`synced\`** — already implemented, up to date
255
-
256
- ## Version
257
-
258
- Patch-bump on each edit: 1.0 → 1.1 → 1.2
259
-
260
- ## Last-modified
261
-
262
- ISO 8601 datetime, updated on each edit.
263
-
264
- ## How sync works
265
-
266
- \`sdd sync\` generates a structured prompt for the agent based on pending files:
267
-
268
- - **\`new\` files**: the agent reads the full documentation and implements it from scratch
269
- - **\`changed\` files**: SDD uses \`git diff\` to compute what changed in the documentation since the last commit, and includes the diff in the sync prompt — this way the agent sees exactly what was modified and can update only the affected code
270
- - **\`deleted\` files**: the agent removes the related code
271
-
272
- This is why **committing after every mark-synced is mandatory** — the git history is what SDD uses to detect changes.
273
-
274
- ## UX and screenshots
275
-
276
- When a feature has UX mockups or screenshots, place them next to the feature doc:
277
-
278
- - **Simple feature** (no screenshots): \`product/features/auth.md\`
279
- - **Feature with screenshots**: use a folder with \`index.md\`:
280
-
281
- \`\`\`
282
- product/features/auth/
283
- index.md ← feature doc
284
- login.png ← screenshot
285
- register.png ← screenshot
286
- \`\`\`
287
-
288
- Reference images in the markdown with relative paths:
289
-
290
- \`\`\`markdown
291
- ## UX
292
-
293
- ![Login screen](login.png)
294
- ![Register screen](register.png)
295
- \`\`\`
296
-
297
- Both formats work — use a folder only when you have screenshots or multiple files for a feature.
298
- `;
299
-
300
- export const CHANGE_REQUESTS_REFERENCE = `# Change Requests
301
-
302
- Change Requests (CRs) are markdown files in \`change-requests/\` that describe modifications to the documentation.
303
-
304
- ## CR format
305
-
306
- \`\`\`yaml
307
- ---
308
- title: "Add authentication feature"
309
- status: draft
310
- author: "user"
311
- created-at: "2025-01-01T00:00:00.000Z"
312
- ---
313
- \`\`\`
314
-
315
- - **status**: \`draft\` (pending) or \`applied\` (already processed)
316
-
317
- ## CR workflow
318
-
319
- 1. Check for pending CRs: \`sdd cr pending\`
320
- 2. Read each pending CR and apply the described changes to the documentation files (marking them as \`new\`, \`changed\`, or \`deleted\`)
321
- 3. After applying a CR to the docs, mark it: \`sdd mark-cr-applied change-requests/CR-001.md\`
322
- 4. Then run \`sdd sync\` to implement the code changes
323
-
324
- ## CR commands
325
-
326
- - \`sdd cr list\` — See all change requests and their status
327
- - \`sdd cr pending\` — Show only draft CRs to process
328
- - \`sdd mark-cr-applied [files...]\` — Mark CRs as applied after updating the docs
329
- `;
330
-
331
- export const BUGS_REFERENCE = `# Bugs
332
-
333
- Bugs are markdown files in \`bugs/\` that describe problems found in the codebase.
334
-
335
- ## Bug format
336
-
337
- \`\`\`yaml
338
- ---
339
- title: "Login fails with empty password"
340
- status: open
341
- author: "user"
342
- created-at: "2025-01-01T00:00:00.000Z"
343
- ---
344
- \`\`\`
345
-
346
- - **status**: \`open\` (needs fixing) or \`resolved\` (already fixed)
347
-
348
- ## Bug workflow
349
-
350
- 1. Check for open bugs: \`sdd bug open\`
351
- 2. Read each open bug and fix the code and/or documentation
352
- 3. After fixing a bug, mark it: \`sdd mark-bug-resolved bugs/BUG-001.md\`
353
- 4. Commit the fix
354
-
355
- ## Bug commands
356
-
357
- - \`sdd bug list\` — See all bugs and their status
358
- - \`sdd bug open\` — Show only open bugs to fix
359
- - \`sdd mark-bug-resolved [files...]\` — Mark bugs as resolved after fixing
360
- `;
361
-
362
29
  export const EMPTY_LOCK_TEMPLATE =
363
30
  () => `synced-at: "${new Date().toISOString()}"
364
31
  files: {}
package/src/sdd.ts CHANGED
@@ -4,7 +4,6 @@ import type { StoryStatus, ValidationResult, SDDConfig, ChangeRequest, Bug } fro
4
4
  import { ProjectNotInitializedError } from "./errors.js";
5
5
  import { parseAllStoryFiles } from "./parser/story-parser.js";
6
6
  import { generatePrompt } from "./prompt/prompt-generator.js";
7
- import { generateApplyPrompt } from "./prompt/apply-prompt-generator.js";
8
7
  import { generateDraftEnrichmentPrompt } from "./prompt/draft-prompt-generator.js";
9
8
  import { validate } from "./validate/validator.js";
10
9
  import { initProject } from "./scaffold/init.js";
@@ -78,20 +77,6 @@ export class SDD {
78
77
  return generatePrompt(pending, this.root);
79
78
  }
80
79
 
81
- async applyPrompt(): Promise<string | null> {
82
- this.ensureInitialized();
83
- const [bugs, changeRequests, pendingFiles, drafts, allFiles, config] = await Promise.all([
84
- this.openBugs(),
85
- this.pendingChangeRequests(),
86
- this.pending(),
87
- this.drafts(),
88
- parseAllStoryFiles(this.root),
89
- readConfig(this.root),
90
- ]);
91
- const projectContext = allFiles.filter((f) => f.frontmatter.status !== "draft");
92
- return generateApplyPrompt(bugs, changeRequests, pendingFiles, this.root, drafts, projectContext, config.description);
93
- }
94
-
95
80
  async validate(): Promise<ValidationResult> {
96
81
  this.ensureInitialized();
97
82
  const files = await parseAllStoryFiles(this.root);
@@ -204,10 +189,7 @@ export class SDD {
204
189
  async draftEnrichmentPrompt(): Promise<string | null> {
205
190
  this.ensureInitialized();
206
191
  const drafts = await this.drafts();
207
- const allFiles = await parseAllStoryFiles(this.root);
208
- const projectContext = allFiles.filter((f) => f.frontmatter.status !== "draft");
209
- const config = await readConfig(this.root);
210
- return generateDraftEnrichmentPrompt(drafts, projectContext, config.description);
192
+ return generateDraftEnrichmentPrompt(drafts);
211
193
  }
212
194
 
213
195
  async markDraftsEnriched(paths?: string[]): Promise<string[]> {
@@ -0,0 +1,24 @@
1
+ import { describe, it, expect } from 'vitest';
2
+ import { resolveAgentCommand, DEFAULT_AGENTS } from '../src/agent/agent-defaults.js';
3
+
4
+ describe('resolveAgentCommand', () => {
5
+ it('resolves built-in agent', () => {
6
+ const cmd = resolveAgentCommand('claude');
7
+ expect(cmd).toBe(DEFAULT_AGENTS.claude);
8
+ });
9
+
10
+ it('resolves config agent over built-in', () => {
11
+ const cmd = resolveAgentCommand('claude', { claude: 'my-claude $PROMPT' });
12
+ expect(cmd).toBe('my-claude $PROMPT');
13
+ });
14
+
15
+ it('resolves custom agent from config', () => {
16
+ const cmd = resolveAgentCommand('my-agent', { 'my-agent': 'my-agent-cmd $PROMPT' });
17
+ expect(cmd).toBe('my-agent-cmd $PROMPT');
18
+ });
19
+
20
+ it('returns undefined for unknown agent', () => {
21
+ const cmd = resolveAgentCommand('unknown');
22
+ expect(cmd).toBeUndefined();
23
+ });
24
+ });
@@ -4,8 +4,8 @@ import {
4
4
  buildApiConfig,
5
5
  pullDocs,
6
6
  pushDocs,
7
- fetchPendingCRs,
8
- fetchOpenBugs,
7
+ pullPendingCRs,
8
+ pullOpenBugs,
9
9
  markCRAppliedRemote,
10
10
  markBugResolvedRemote,
11
11
  } from '../src/remote/api-client.js';
@@ -134,22 +134,22 @@ describe('API client functions', () => {
134
134
  );
135
135
  });
136
136
 
137
- it('fetchPendingCRs sends GET to correct endpoint', async () => {
137
+ it('pullPendingCRs sends GET to correct endpoint', async () => {
138
138
  const mock = mockFetch([]);
139
139
  globalThis.fetch = mock;
140
140
 
141
- await fetchPendingCRs(API);
141
+ await pullPendingCRs(API);
142
142
  expect(mock).toHaveBeenCalledWith(
143
143
  'http://test.local/api/v1/cli/pending-crs',
144
144
  expect.objectContaining({ method: 'GET' }),
145
145
  );
146
146
  });
147
147
 
148
- it('fetchOpenBugs sends GET to correct endpoint', async () => {
148
+ it('pullOpenBugs sends GET to correct endpoint', async () => {
149
149
  const mock = mockFetch([]);
150
150
  globalThis.fetch = mock;
151
151
 
152
- await fetchOpenBugs(API);
152
+ await pullOpenBugs(API);
153
153
  expect(mock).toHaveBeenCalledWith(
154
154
  'http://test.local/api/v1/cli/open-bugs',
155
155
  expect.objectContaining({ method: 'GET' }),
@@ -0,0 +1,78 @@
1
+ import { describe, it, expect } from 'vitest';
2
+ import { generateDraftEnrichmentPrompt, type DraftElements } from '../src/prompt/draft-prompt-generator.js';
3
+ import type { Bug, ChangeRequest, StoryFile } from '../src/types.js';
4
+
5
+ function makeFile(overrides: Partial<StoryFile> = {}): StoryFile {
6
+ return {
7
+ relativePath: 'product/features/auth.md',
8
+ frontmatter: {
9
+ title: 'Auth',
10
+ status: 'draft',
11
+ author: 'test',
12
+ 'last-modified': '2024-01-01T00:00:00.000Z',
13
+ version: '1.0',
14
+ },
15
+ body: '# Auth Feature',
16
+ pendingItems: [],
17
+ agentNotes: null,
18
+ crossRefs: [],
19
+ hash: 'abc',
20
+ ...overrides,
21
+ };
22
+ }
23
+
24
+ function makeCR(overrides: Partial<ChangeRequest> = {}): ChangeRequest {
25
+ return {
26
+ relativePath: 'change-requests/CR-001.md',
27
+ frontmatter: {
28
+ title: 'Add dark mode',
29
+ status: 'draft',
30
+ author: 'test',
31
+ 'created-at': '2024-01-01T00:00:00.000Z',
32
+ },
33
+ body: '## Changes\n\nAdd dark mode support.',
34
+ ...overrides,
35
+ };
36
+ }
37
+
38
+ function makeBug(overrides: Partial<Bug> = {}): Bug {
39
+ return {
40
+ relativePath: 'bugs/BUG-001.md',
41
+ frontmatter: {
42
+ title: 'Login button broken',
43
+ status: 'draft',
44
+ author: 'test',
45
+ 'created-at': '2024-01-01T00:00:00.000Z',
46
+ },
47
+ body: '## Description\n\nThe login button does not work.',
48
+ ...overrides,
49
+ };
50
+ }
51
+
52
+ describe('generateDraftEnrichmentPrompt', () => {
53
+ it('returns null when there are no drafts', () => {
54
+ const drafts: DraftElements = { docs: [], crs: [], bugs: [] };
55
+ const prompt = generateDraftEnrichmentPrompt(drafts);
56
+ expect(prompt).toBeNull();
57
+ });
58
+
59
+ it('includes only draft task lists', () => {
60
+ const drafts: DraftElements = {
61
+ docs: [makeFile()],
62
+ crs: [makeCR()],
63
+ bugs: [makeBug()],
64
+ };
65
+ const prompt = generateDraftEnrichmentPrompt(drafts);
66
+
67
+ expect(prompt).not.toBeNull();
68
+ expect(prompt).toContain('# Draft Tasks');
69
+ expect(prompt).toContain('## Draft documents (1)');
70
+ expect(prompt).toContain('## Draft change requests (1)');
71
+ expect(prompt).toContain('## Draft bugs (1)');
72
+ expect(prompt).toContain('`product/features/auth.md`');
73
+ expect(prompt).toContain('`change-requests/CR-001.md`');
74
+ expect(prompt).toContain('`bugs/BUG-001.md`');
75
+ expect(prompt).not.toContain('## Project');
76
+ expect(prompt).not.toContain('## Project context');
77
+ });
78
+ });
@@ -1,4 +0,0 @@
1
- import type { Bug, ChangeRequest, StoryFile } from '../types.js';
2
- import type { DraftElements } from './draft-prompt-generator.js';
3
- export declare function generateApplyPrompt(bugs: Bug[], changeRequests: ChangeRequest[], pendingFiles: StoryFile[], root: string, drafts?: DraftElements, projectContext?: StoryFile[], projectDescription?: string): string | null;
4
- //# sourceMappingURL=apply-prompt-generator.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"apply-prompt-generator.d.ts","sourceRoot":"","sources":["../../src/prompt/apply-prompt-generator.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAEjE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAEjE,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,GAAG,EAAE,EACX,cAAc,EAAE,aAAa,EAAE,EAC/B,YAAY,EAAE,SAAS,EAAE,EACzB,IAAI,EAAE,MAAM,EACZ,MAAM,CAAC,EAAE,aAAa,EACtB,cAAc,CAAC,EAAE,SAAS,EAAE,EAC5B,kBAAkB,CAAC,EAAE,MAAM,GAC1B,MAAM,GAAG,IAAI,CAwGf"}
@@ -1,97 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.generateApplyPrompt = generateApplyPrompt;
4
- const git_js_1 = require("../git/git.js");
5
- function generateApplyPrompt(bugs, changeRequests, pendingFiles, root, drafts, projectContext, projectDescription) {
6
- const hasDrafts = drafts && (drafts.docs.length > 0 || drafts.crs.length > 0 || drafts.bugs.length > 0);
7
- if (bugs.length === 0 && changeRequests.length === 0 && pendingFiles.length === 0 && !hasDrafts) {
8
- return null;
9
- }
10
- const sections = [];
11
- // Draft enrichment section (takes priority)
12
- if (hasDrafts) {
13
- sections.push(`# Draft Enrichment\n`);
14
- if (projectDescription) {
15
- sections.push(`## Project\n\n${projectDescription}\n`);
16
- }
17
- // Global context for enrichment
18
- if (projectContext && projectContext.length > 0) {
19
- const ctxLines = [`## Project context (${projectContext.length} documents)\n`];
20
- ctxLines.push('Use the following existing documents as context to produce complete, coherent documentation.\n');
21
- for (const f of projectContext) {
22
- ctxLines.push(`### \`${f.relativePath}\` — ${f.frontmatter.title}\n`);
23
- ctxLines.push(f.body.trim());
24
- ctxLines.push('');
25
- }
26
- sections.push(ctxLines.join('\n'));
27
- }
28
- if (drafts.docs.length > 0) {
29
- const lines = [`## Draft documents to enrich (${drafts.docs.length})\n`];
30
- lines.push('Each draft below contains incomplete human-written content. Produce a complete version for each document, preserving the original intent while adding missing details based on project context.\n');
31
- for (const f of drafts.docs) {
32
- lines.push(`### \`${f.relativePath}\` — ${f.frontmatter.title}\n`);
33
- lines.push(f.body.trim());
34
- lines.push('');
35
- }
36
- sections.push(lines.join('\n'));
37
- }
38
- if (drafts.crs.length > 0) {
39
- const lines = [`## Draft change requests to enrich (${drafts.crs.length})\n`];
40
- lines.push('Each draft CR contains a rough description of requested changes. Produce a complete, actionable change request for each.\n');
41
- for (const cr of drafts.crs) {
42
- lines.push(`### \`${cr.relativePath}\` — ${cr.frontmatter.title}\n`);
43
- lines.push(cr.body.trim());
44
- lines.push('');
45
- }
46
- sections.push(lines.join('\n'));
47
- }
48
- if (drafts.bugs.length > 0) {
49
- const lines = [`## Draft bugs to enrich (${drafts.bugs.length})\n`];
50
- lines.push('Each draft bug contains a rough description of an issue. Produce a complete bug report for each.\n');
51
- for (const bug of drafts.bugs) {
52
- lines.push(`### \`${bug.relativePath}\` — ${bug.frontmatter.title}\n`);
53
- lines.push(bug.body.trim());
54
- lines.push('');
55
- }
56
- sections.push(lines.join('\n'));
57
- }
58
- }
59
- // Bugs
60
- if (bugs.length > 0) {
61
- const lines = [`## Open bugs (${bugs.length})\n`];
62
- for (const bug of bugs) {
63
- lines.push(`### \`${bug.relativePath}\` — ${bug.frontmatter.title}\n`);
64
- lines.push(bug.body.trim());
65
- lines.push('');
66
- }
67
- sections.push(lines.join('\n'));
68
- }
69
- // Change Requests
70
- if (changeRequests.length > 0) {
71
- const lines = [`## Pending change requests (${changeRequests.length})\n`];
72
- for (const cr of changeRequests) {
73
- lines.push(`### \`${cr.relativePath}\` — ${cr.frontmatter.title}\n`);
74
- lines.push(cr.body.trim());
75
- lines.push('');
76
- }
77
- sections.push(lines.join('\n'));
78
- }
79
- // Pending files
80
- if (pendingFiles.length > 0) {
81
- const lines = [`## Pending files (${pendingFiles.length})\n`];
82
- for (const f of pendingFiles) {
83
- lines.push(`- \`${f.relativePath}\` — **${f.frontmatter.status}**`);
84
- }
85
- const changed = pendingFiles.filter((f) => f.frontmatter.status === 'changed');
86
- for (const f of changed) {
87
- const diff = (0, git_js_1.getFileDiff)(root, f.relativePath);
88
- if (diff) {
89
- lines.push('');
90
- lines.push(`### Diff: \`${f.relativePath}\`\n\n\`\`\`diff\n${diff}\n\`\`\``);
91
- }
92
- }
93
- sections.push(lines.join('\n'));
94
- }
95
- return sections.join('\n\n');
96
- }
97
- //# sourceMappingURL=apply-prompt-generator.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"apply-prompt-generator.js","sourceRoot":"","sources":["../../src/prompt/apply-prompt-generator.ts"],"names":[],"mappings":"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"}