@applica-software-guru/sdd-core 1.8.0 → 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 (61) 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 +2 -19
  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 +2 -20
  49. package/tests/agent-defaults.test.ts +24 -0
  50. package/tests/api-client.test.ts +6 -6
  51. package/tests/bug.test.ts +22 -0
  52. package/tests/draft-prompt.test.ts +78 -0
  53. package/tests/integration.test.ts +1 -1
  54. package/tests/prompt.test.ts +3 -5
  55. package/tests/remote-state.test.ts +2 -2
  56. package/dist/prompt/apply-prompt-generator.d.ts +0 -4
  57. package/dist/prompt/apply-prompt-generator.d.ts.map +0 -1
  58. package/dist/prompt/apply-prompt-generator.js +0 -97
  59. package/dist/prompt/apply-prompt-generator.js.map +0 -1
  60. package/src/prompt/apply-prompt-generator.ts +0 -117
  61. package/tests/apply.test.ts +0 -119
@@ -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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"}
@@ -1,117 +0,0 @@
1
- import type { Bug, ChangeRequest, StoryFile } from '../types.js';
2
- import { getFileDiff } from '../git/git.js';
3
- import type { DraftElements } from './draft-prompt-generator.js';
4
-
5
- export function generateApplyPrompt(
6
- bugs: Bug[],
7
- changeRequests: ChangeRequest[],
8
- pendingFiles: StoryFile[],
9
- root: string,
10
- drafts?: DraftElements,
11
- projectContext?: StoryFile[],
12
- projectDescription?: string,
13
- ): string | null {
14
- const hasDrafts = drafts && (drafts.docs.length > 0 || drafts.crs.length > 0 || drafts.bugs.length > 0);
15
- if (bugs.length === 0 && changeRequests.length === 0 && pendingFiles.length === 0 && !hasDrafts) {
16
- return null;
17
- }
18
-
19
- const sections: string[] = [];
20
-
21
- // Draft enrichment section (takes priority)
22
- if (hasDrafts) {
23
- sections.push(`# Draft Enrichment\n`);
24
-
25
- if (projectDescription) {
26
- sections.push(`## Project\n\n${projectDescription}\n`);
27
- }
28
-
29
- // Global context for enrichment
30
- if (projectContext && projectContext.length > 0) {
31
- const ctxLines = [`## Project context (${projectContext.length} documents)\n`];
32
- ctxLines.push('Use the following existing documents as context to produce complete, coherent documentation.\n');
33
- for (const f of projectContext) {
34
- ctxLines.push(`### \`${f.relativePath}\` — ${f.frontmatter.title}\n`);
35
- ctxLines.push(f.body.trim());
36
- ctxLines.push('');
37
- }
38
- sections.push(ctxLines.join('\n'));
39
- }
40
-
41
- if (drafts!.docs.length > 0) {
42
- const lines = [`## Draft documents to enrich (${drafts!.docs.length})\n`];
43
- 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');
44
- for (const f of drafts!.docs) {
45
- lines.push(`### \`${f.relativePath}\` — ${f.frontmatter.title}\n`);
46
- lines.push(f.body.trim());
47
- lines.push('');
48
- }
49
- sections.push(lines.join('\n'));
50
- }
51
-
52
- if (drafts!.crs.length > 0) {
53
- const lines = [`## Draft change requests to enrich (${drafts!.crs.length})\n`];
54
- lines.push('Each draft CR contains a rough description of requested changes. Produce a complete, actionable change request for each.\n');
55
- for (const cr of drafts!.crs) {
56
- lines.push(`### \`${cr.relativePath}\` — ${cr.frontmatter.title}\n`);
57
- lines.push(cr.body.trim());
58
- lines.push('');
59
- }
60
- sections.push(lines.join('\n'));
61
- }
62
-
63
- if (drafts!.bugs.length > 0) {
64
- const lines = [`## Draft bugs to enrich (${drafts!.bugs.length})\n`];
65
- lines.push('Each draft bug contains a rough description of an issue. Produce a complete bug report for each.\n');
66
- for (const bug of drafts!.bugs) {
67
- lines.push(`### \`${bug.relativePath}\` — ${bug.frontmatter.title}\n`);
68
- lines.push(bug.body.trim());
69
- lines.push('');
70
- }
71
- sections.push(lines.join('\n'));
72
- }
73
- }
74
-
75
- // Bugs
76
- if (bugs.length > 0) {
77
- const lines = [`## Open bugs (${bugs.length})\n`];
78
- for (const bug of bugs) {
79
- lines.push(`### \`${bug.relativePath}\` — ${bug.frontmatter.title}\n`);
80
- lines.push(bug.body.trim());
81
- lines.push('');
82
- }
83
- sections.push(lines.join('\n'));
84
- }
85
-
86
- // Change Requests
87
- if (changeRequests.length > 0) {
88
- const lines = [`## Pending change requests (${changeRequests.length})\n`];
89
- for (const cr of changeRequests) {
90
- lines.push(`### \`${cr.relativePath}\` — ${cr.frontmatter.title}\n`);
91
- lines.push(cr.body.trim());
92
- lines.push('');
93
- }
94
- sections.push(lines.join('\n'));
95
- }
96
-
97
- // Pending files
98
- if (pendingFiles.length > 0) {
99
- const lines = [`## Pending files (${pendingFiles.length})\n`];
100
- for (const f of pendingFiles) {
101
- lines.push(`- \`${f.relativePath}\` — **${f.frontmatter.status}**`);
102
- }
103
-
104
- const changed = pendingFiles.filter((f) => f.frontmatter.status === 'changed');
105
- for (const f of changed) {
106
- const diff = getFileDiff(root, f.relativePath);
107
- if (diff) {
108
- lines.push('');
109
- lines.push(`### Diff: \`${f.relativePath}\`\n\n\`\`\`diff\n${diff}\n\`\`\``);
110
- }
111
- }
112
-
113
- sections.push(lines.join('\n'));
114
- }
115
-
116
- return sections.join('\n\n');
117
- }
@@ -1,119 +0,0 @@
1
- import { describe, it, expect } from 'vitest';
2
- import { generateApplyPrompt } from '../src/prompt/apply-prompt-generator.js';
3
- import { resolveAgentCommand, DEFAULT_AGENTS } from '../src/agent/agent-defaults.js';
4
- import type { Bug, ChangeRequest, StoryFile } from '../src/types.js';
5
-
6
- function makeBug(overrides: Partial<Bug> = {}): Bug {
7
- return {
8
- relativePath: 'bugs/BUG-001.md',
9
- frontmatter: {
10
- title: 'Login button broken',
11
- status: 'open',
12
- author: 'test',
13
- 'created-at': '2024-01-01T00:00:00.000Z',
14
- },
15
- body: '## Description\n\nThe login button does not work.',
16
- ...overrides,
17
- };
18
- }
19
-
20
- function makeCR(overrides: Partial<ChangeRequest> = {}): ChangeRequest {
21
- return {
22
- relativePath: 'change-requests/CR-001.md',
23
- frontmatter: {
24
- title: 'Add dark mode',
25
- status: 'draft',
26
- author: 'test',
27
- 'created-at': '2024-01-01T00:00:00.000Z',
28
- },
29
- body: '## Changes\n\nAdd dark mode support.',
30
- ...overrides,
31
- };
32
- }
33
-
34
- function makeFile(overrides: Partial<StoryFile> = {}): StoryFile {
35
- return {
36
- relativePath: 'product/features/auth.md',
37
- frontmatter: {
38
- title: 'Auth',
39
- status: 'new',
40
- author: 'test',
41
- 'last-modified': '2024-01-01T00:00:00.000Z',
42
- version: '1.0',
43
- },
44
- body: '# Auth Feature',
45
- pendingItems: [],
46
- agentNotes: null,
47
- crossRefs: [],
48
- hash: 'abc',
49
- ...overrides,
50
- };
51
- }
52
-
53
- describe('generateApplyPrompt', () => {
54
- it('returns null when nothing to do', () => {
55
- const result = generateApplyPrompt([], [], [], '/tmp');
56
- expect(result).toBeNull();
57
- });
58
-
59
- it('generates prompt with only bugs', () => {
60
- const prompt = generateApplyPrompt([makeBug()], [], [], '/tmp');
61
- expect(prompt).not.toBeNull();
62
- expect(prompt).toContain('# SDD Apply');
63
- expect(prompt).toContain('Open Bugs (1)');
64
- expect(prompt).toContain('Login button broken');
65
- expect(prompt).toContain('bugs/BUG-001.md');
66
- expect(prompt).not.toContain('Pending Change Requests');
67
- expect(prompt).not.toContain('Pending Files');
68
- });
69
-
70
- it('generates prompt with only CRs', () => {
71
- const prompt = generateApplyPrompt([], [makeCR()], [], '/tmp');
72
- expect(prompt).not.toBeNull();
73
- expect(prompt).toContain('Pending Change Requests (1)');
74
- expect(prompt).toContain('Add dark mode');
75
- expect(prompt).not.toContain('Open Bugs');
76
- expect(prompt).not.toContain('Pending Files');
77
- });
78
-
79
- it('generates prompt with only pending files', () => {
80
- const prompt = generateApplyPrompt([], [], [makeFile()], '/tmp');
81
- expect(prompt).not.toBeNull();
82
- expect(prompt).toContain('Pending Files (1)');
83
- expect(prompt).toContain('product/features/auth.md');
84
- expect(prompt).toContain('**new**');
85
- expect(prompt).not.toContain('Open Bugs');
86
- expect(prompt).not.toContain('Pending Change Requests');
87
- });
88
-
89
- it('generates prompt with all three', () => {
90
- const prompt = generateApplyPrompt([makeBug()], [makeCR()], [makeFile()], '/tmp');
91
- expect(prompt).not.toBeNull();
92
- expect(prompt).toContain('Open Bugs (1)');
93
- expect(prompt).toContain('Pending Change Requests (1)');
94
- expect(prompt).toContain('Pending Files (1)');
95
- expect(prompt).toContain('## Instructions');
96
- });
97
- });
98
-
99
- describe('resolveAgentCommand', () => {
100
- it('resolves built-in agent', () => {
101
- const cmd = resolveAgentCommand('claude');
102
- expect(cmd).toBe(DEFAULT_AGENTS.claude);
103
- });
104
-
105
- it('resolves config agent over built-in', () => {
106
- const cmd = resolveAgentCommand('claude', { claude: 'my-claude $PROMPT' });
107
- expect(cmd).toBe('my-claude $PROMPT');
108
- });
109
-
110
- it('resolves custom agent from config', () => {
111
- const cmd = resolveAgentCommand('my-agent', { 'my-agent': 'my-agent-cmd $PROMPT' });
112
- expect(cmd).toBe('my-agent-cmd $PROMPT');
113
- });
114
-
115
- it('returns undefined for unknown agent', () => {
116
- const cmd = resolveAgentCommand('unknown');
117
- expect(cmd).toBeUndefined();
118
- });
119
- });