@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.
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -3
- package/dist/index.js.map +1 -1
- package/dist/parser/bug-parser.d.ts.map +1 -1
- package/dist/parser/bug-parser.js +2 -1
- package/dist/parser/bug-parser.js.map +1 -1
- package/dist/parser/cr-parser.d.ts.map +1 -1
- package/dist/parser/cr-parser.js +2 -1
- package/dist/parser/cr-parser.js.map +1 -1
- package/dist/prompt/draft-prompt-generator.d.ts +1 -1
- package/dist/prompt/draft-prompt-generator.d.ts.map +1 -1
- package/dist/prompt/draft-prompt-generator.js +19 -35
- package/dist/prompt/draft-prompt-generator.js.map +1 -1
- package/dist/remote/api-client.d.ts +2 -2
- package/dist/remote/api-client.d.ts.map +1 -1
- package/dist/remote/api-client.js +4 -4
- package/dist/remote/api-client.js.map +1 -1
- package/dist/remote/sync-engine.js +12 -8
- package/dist/remote/sync-engine.js.map +1 -1
- package/dist/scaffold/skill-adapters.d.ts +0 -9
- package/dist/scaffold/skill-adapters.d.ts.map +1 -1
- package/dist/scaffold/skill-adapters.js +17 -0
- package/dist/scaffold/skill-adapters.js.map +1 -1
- package/dist/scaffold/templates.d.ts +1 -5
- package/dist/scaffold/templates.d.ts.map +1 -1
- package/dist/scaffold/templates.generated.d.ts +7 -0
- package/dist/scaffold/templates.generated.d.ts.map +1 -0
- package/dist/scaffold/templates.generated.js +464 -0
- package/dist/scaffold/templates.generated.js.map +1 -0
- package/dist/scaffold/templates.js +8 -338
- package/dist/scaffold/templates.js.map +1 -1
- package/dist/sdd.d.ts +0 -1
- package/dist/sdd.d.ts.map +1 -1
- package/dist/sdd.js +2 -19
- package/dist/sdd.js.map +1 -1
- package/package.json +2 -1
- package/scripts/generate-templates.mjs +38 -0
- package/src/index.ts +1 -1
- package/src/parser/bug-parser.ts +5 -3
- package/src/parser/cr-parser.ts +5 -3
- package/src/prompt/draft-prompt-generator.ts +18 -38
- package/src/remote/api-client.ts +2 -2
- package/src/remote/sync-engine.ts +15 -15
- package/src/scaffold/skill-adapters.ts +18 -11
- package/src/scaffold/templates.generated.ts +466 -0
- package/src/scaffold/templates.ts +9 -342
- package/src/sdd.ts +2 -20
- package/tests/agent-defaults.test.ts +24 -0
- package/tests/api-client.test.ts +6 -6
- package/tests/bug.test.ts +22 -0
- package/tests/draft-prompt.test.ts +78 -0
- package/tests/integration.test.ts +1 -1
- package/tests/prompt.test.ts +3 -5
- package/tests/remote-state.test.ts +2 -2
- package/dist/prompt/apply-prompt-generator.d.ts +0 -4
- package/dist/prompt/apply-prompt-generator.d.ts.map +0 -1
- package/dist/prompt/apply-prompt-generator.js +0 -97
- package/dist/prompt/apply-prompt-generator.js.map +0 -1
- package/src/prompt/apply-prompt-generator.ts +0 -117
- package/tests/apply.test.ts +0 -119
|
@@ -8,67 +8,47 @@ export interface DraftElements {
|
|
|
8
8
|
|
|
9
9
|
export function generateDraftEnrichmentPrompt(
|
|
10
10
|
drafts: DraftElements,
|
|
11
|
-
projectContext: StoryFile[],
|
|
12
|
-
projectDescription: string,
|
|
13
11
|
): string | null {
|
|
14
12
|
const totalDrafts = drafts.docs.length + drafts.crs.length + drafts.bugs.length;
|
|
15
13
|
if (totalDrafts === 0) {
|
|
16
14
|
return null;
|
|
17
15
|
}
|
|
18
16
|
|
|
19
|
-
const sections: string[] = [
|
|
17
|
+
const sections: string[] = [
|
|
18
|
+
'# Draft Tasks',
|
|
19
|
+
'',
|
|
20
|
+
'Enrich all draft elements listed below.',
|
|
21
|
+
'Read each file directly from disk, complete missing details, and save it keeping `status: draft`.',
|
|
22
|
+
'Do not mark statuses automatically in this step.',
|
|
23
|
+
'',
|
|
24
|
+
];
|
|
20
25
|
|
|
21
|
-
// Project context header
|
|
22
|
-
sections.push(`# Draft Enrichment\n`);
|
|
23
|
-
sections.push(`## Project\n\n${projectDescription}\n`);
|
|
24
|
-
|
|
25
|
-
// Global context: all non-draft documents
|
|
26
|
-
if (projectContext.length > 0) {
|
|
27
|
-
const ctxLines = [`## Project context (${projectContext.length} documents)\n`];
|
|
28
|
-
ctxLines.push('Use the following existing documents as context to produce complete, coherent documentation.\n');
|
|
29
|
-
for (const f of projectContext) {
|
|
30
|
-
ctxLines.push(`### \`${f.relativePath}\` — ${f.frontmatter.title}\n`);
|
|
31
|
-
ctxLines.push(f.body.trim());
|
|
32
|
-
ctxLines.push('');
|
|
33
|
-
}
|
|
34
|
-
sections.push(ctxLines.join('\n'));
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
// Draft documents
|
|
38
26
|
if (drafts.docs.length > 0) {
|
|
39
|
-
const lines = [`## Draft documents
|
|
40
|
-
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');
|
|
27
|
+
const lines = [`## Draft documents (${drafts.docs.length})`];
|
|
41
28
|
for (const f of drafts.docs) {
|
|
42
|
-
lines.push(
|
|
43
|
-
lines.push(f.body.trim());
|
|
44
|
-
lines.push('');
|
|
29
|
+
lines.push(`- \`${f.relativePath}\` — ${f.frontmatter.title}`);
|
|
45
30
|
}
|
|
46
31
|
sections.push(lines.join('\n'));
|
|
32
|
+
sections.push('');
|
|
47
33
|
}
|
|
48
34
|
|
|
49
|
-
// Draft change requests
|
|
50
35
|
if (drafts.crs.length > 0) {
|
|
51
|
-
const lines = [`## Draft change requests
|
|
52
|
-
lines.push('Each draft CR contains a rough description of requested changes. Produce a complete, actionable change request for each, specifying which documents are affected and what changes should be made.\n');
|
|
36
|
+
const lines = [`## Draft change requests (${drafts.crs.length})`];
|
|
53
37
|
for (const cr of drafts.crs) {
|
|
54
|
-
lines.push(
|
|
55
|
-
lines.push(cr.body.trim());
|
|
56
|
-
lines.push('');
|
|
38
|
+
lines.push(`- \`${cr.relativePath}\` — ${cr.frontmatter.title}`);
|
|
57
39
|
}
|
|
58
40
|
sections.push(lines.join('\n'));
|
|
41
|
+
sections.push('');
|
|
59
42
|
}
|
|
60
43
|
|
|
61
|
-
// Draft bugs
|
|
62
44
|
if (drafts.bugs.length > 0) {
|
|
63
|
-
const lines = [`## Draft bugs
|
|
64
|
-
lines.push('Each draft bug contains a rough description of an issue. Produce a complete bug report for each, including affected components, expected vs actual behavior, and steps to reproduce when possible.\n');
|
|
45
|
+
const lines = [`## Draft bugs (${drafts.bugs.length})`];
|
|
65
46
|
for (const bug of drafts.bugs) {
|
|
66
|
-
lines.push(
|
|
67
|
-
lines.push(bug.body.trim());
|
|
68
|
-
lines.push('');
|
|
47
|
+
lines.push(`- \`${bug.relativePath}\` — ${bug.frontmatter.title}`);
|
|
69
48
|
}
|
|
70
49
|
sections.push(lines.join('\n'));
|
|
50
|
+
sections.push('');
|
|
71
51
|
}
|
|
72
52
|
|
|
73
|
-
return sections.join('\n
|
|
53
|
+
return sections.join('\n');
|
|
74
54
|
}
|
package/src/remote/api-client.ts
CHANGED
|
@@ -180,7 +180,7 @@ export async function pushDocs(
|
|
|
180
180
|
}
|
|
181
181
|
|
|
182
182
|
/** GET /cli/pending-crs */
|
|
183
|
-
export async function
|
|
183
|
+
export async function pullPendingCRs(config: ApiClientConfig): Promise<RemoteCRResponse[]> {
|
|
184
184
|
return request<RemoteCRResponse[]>(config, 'GET', '/cli/pending-crs');
|
|
185
185
|
}
|
|
186
186
|
|
|
@@ -193,7 +193,7 @@ export async function pushCRs(
|
|
|
193
193
|
}
|
|
194
194
|
|
|
195
195
|
/** GET /cli/open-bugs */
|
|
196
|
-
export async function
|
|
196
|
+
export async function pullOpenBugs(config: ApiClientConfig): Promise<RemoteBugResponse[]> {
|
|
197
197
|
return request<RemoteBugResponse[]>(config, 'GET', '/cli/open-bugs');
|
|
198
198
|
}
|
|
199
199
|
|
|
@@ -8,7 +8,7 @@ import { readConfig } from '../config/config-manager.js';
|
|
|
8
8
|
import { parseAllStoryFiles } from '../parser/story-parser.js';
|
|
9
9
|
import { parseAllCRFiles } from '../parser/cr-parser.js';
|
|
10
10
|
import { parseAllBugFiles } from '../parser/bug-parser.js';
|
|
11
|
-
import { buildApiConfig, pullDocs, pushDocs, pushCRs, pushBugs, deleteDocs, deleteCRs, deleteBugs,
|
|
11
|
+
import { buildApiConfig, pullDocs, pushDocs, pushCRs, pushBugs, deleteDocs, deleteCRs, deleteBugs, pullPendingCRs, pullOpenBugs, resetProject } from './api-client.js';
|
|
12
12
|
import { readRemoteState, writeRemoteState } from './state.js';
|
|
13
13
|
import type {
|
|
14
14
|
PushResult,
|
|
@@ -194,13 +194,13 @@ export async function pushToRemote(root: string, options?: PushOptions): Promise
|
|
|
194
194
|
const crResult = await pushCRs(api, crPayload);
|
|
195
195
|
|
|
196
196
|
for (const cr of crResult.change_requests) {
|
|
197
|
-
const localPath =
|
|
198
|
-
(f) => f.frontmatter.title === cr.title
|
|
199
|
-
)?.relativePath;
|
|
197
|
+
const localPath = cr.path
|
|
198
|
+
?? crsToPush.find((f) => f.frontmatter.title === cr.title)?.relativePath;
|
|
200
199
|
if (localPath) {
|
|
201
|
-
const
|
|
200
|
+
const normalized = normalizePath(localPath);
|
|
201
|
+
const absPath = resolve(root, normalized);
|
|
202
202
|
const rawContent = existsSync(absPath) ? await readFile(absPath, 'utf-8') : '';
|
|
203
|
-
state.changeRequests![
|
|
203
|
+
state.changeRequests![normalized] = {
|
|
204
204
|
remoteId: cr.id,
|
|
205
205
|
localHash: sha256(rawContent),
|
|
206
206
|
lastSynced: new Date().toISOString(),
|
|
@@ -247,13 +247,13 @@ export async function pushToRemote(root: string, options?: PushOptions): Promise
|
|
|
247
247
|
const bugResult = await pushBugs(api, bugPayload);
|
|
248
248
|
|
|
249
249
|
for (const bug of bugResult.bugs) {
|
|
250
|
-
const localPath =
|
|
251
|
-
(b) => b.frontmatter.title === bug.title
|
|
252
|
-
)?.relativePath;
|
|
250
|
+
const localPath = bug.path
|
|
251
|
+
?? bugsToPush.find((b) => b.frontmatter.title === bug.title)?.relativePath;
|
|
253
252
|
if (localPath) {
|
|
254
|
-
const
|
|
253
|
+
const normalized = normalizePath(localPath);
|
|
254
|
+
const absPath = resolve(root, normalized);
|
|
255
255
|
const rawContent = existsSync(absPath) ? await readFile(absPath, 'utf-8') : '';
|
|
256
|
-
state.bugs![
|
|
256
|
+
state.bugs![normalized] = {
|
|
257
257
|
remoteId: bug.id,
|
|
258
258
|
localHash: sha256(rawContent),
|
|
259
259
|
lastSynced: new Date().toISOString(),
|
|
@@ -432,7 +432,7 @@ export async function pullCRsFromRemote(root: string, timeout?: number): Promise
|
|
|
432
432
|
const config = await readConfig(root);
|
|
433
433
|
const api = buildApiConfig(config, timeout);
|
|
434
434
|
|
|
435
|
-
const remoteCRs = await
|
|
435
|
+
const remoteCRs = await pullPendingCRs(api);
|
|
436
436
|
const state = await readRemoteState(root);
|
|
437
437
|
if (!state.changeRequests) state.changeRequests = {};
|
|
438
438
|
|
|
@@ -448,7 +448,7 @@ export async function pullCRsFromRemote(root: string, timeout?: number): Promise
|
|
|
448
448
|
|
|
449
449
|
// Detect remote deletions: tracked locally but not in remote response
|
|
450
450
|
const remoteCRIdSet = new Set(remoteCRs.map((cr) => cr.id));
|
|
451
|
-
for (const [localPath, tracked] of Object.entries(state.changeRequests
|
|
451
|
+
for (const [localPath, tracked] of Object.entries(state.changeRequests)) {
|
|
452
452
|
if (!remoteCRIdSet.has(tracked.remoteId)) {
|
|
453
453
|
const absPath = resolve(root, localPath);
|
|
454
454
|
if (existsSync(absPath)) {
|
|
@@ -522,7 +522,7 @@ export async function pullBugsFromRemote(root: string, timeout?: number): Promis
|
|
|
522
522
|
const config = await readConfig(root);
|
|
523
523
|
const api = buildApiConfig(config, timeout);
|
|
524
524
|
|
|
525
|
-
const remoteBugs = await
|
|
525
|
+
const remoteBugs = await pullOpenBugs(api);
|
|
526
526
|
const state = await readRemoteState(root);
|
|
527
527
|
if (!state.bugs) state.bugs = {};
|
|
528
528
|
|
|
@@ -538,7 +538,7 @@ export async function pullBugsFromRemote(root: string, timeout?: number): Promis
|
|
|
538
538
|
|
|
539
539
|
// Detect remote deletions: tracked locally but not in remote response
|
|
540
540
|
const remoteBugIdSet = new Set(remoteBugs.map((b) => b.id));
|
|
541
|
-
for (const [localPath, tracked] of Object.entries(state.bugs
|
|
541
|
+
for (const [localPath, tracked] of Object.entries(state.bugs)) {
|
|
542
542
|
if (!remoteBugIdSet.has(tracked.remoteId)) {
|
|
543
543
|
const absPath = resolve(root, localPath);
|
|
544
544
|
if (existsSync(absPath)) {
|
|
@@ -6,6 +6,7 @@ import {
|
|
|
6
6
|
CHANGE_REQUESTS_REFERENCE,
|
|
7
7
|
FILE_FORMAT_REFERENCE,
|
|
8
8
|
SKILL_MD_TEMPLATE,
|
|
9
|
+
SKILL_REMOTE_MD_TEMPLATE,
|
|
9
10
|
SKILL_UI_MD_TEMPLATE,
|
|
10
11
|
} from "./templates.js";
|
|
11
12
|
|
|
@@ -81,22 +82,20 @@ const CANONICAL_SKILLS: Array<{
|
|
|
81
82
|
},
|
|
82
83
|
],
|
|
83
84
|
},
|
|
85
|
+
{
|
|
86
|
+
id: "sdd-remote",
|
|
87
|
+
files: [
|
|
88
|
+
{
|
|
89
|
+
path: `${CANONICAL_BASE_DIR}/sdd-remote/SKILL.md`,
|
|
90
|
+
content: SKILL_REMOTE_MD_TEMPLATE,
|
|
91
|
+
},
|
|
92
|
+
],
|
|
93
|
+
},
|
|
84
94
|
];
|
|
85
95
|
|
|
86
96
|
const CANONICAL_FILES: Array<{ path: string; content: string }> =
|
|
87
97
|
CANONICAL_SKILLS.flatMap((skill) => skill.files);
|
|
88
98
|
|
|
89
|
-
export interface SkillPathsDefinition {
|
|
90
|
-
skillId: string;
|
|
91
|
-
paths: string[];
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
export interface SkillAdapterDefinition {
|
|
95
|
-
id: string;
|
|
96
|
-
mode: AdapterMode;
|
|
97
|
-
skills: SkillPathsDefinition[];
|
|
98
|
-
}
|
|
99
|
-
|
|
100
99
|
export const SKILL_ADAPTERS: SkillAdapterDefinition[] = [
|
|
101
100
|
{
|
|
102
101
|
id: "claude",
|
|
@@ -115,6 +114,10 @@ export const SKILL_ADAPTERS: SkillAdapterDefinition[] = [
|
|
|
115
114
|
skillId: "sdd-ui",
|
|
116
115
|
paths: [".claude/skills/sdd-ui/SKILL.md"],
|
|
117
116
|
},
|
|
117
|
+
{
|
|
118
|
+
skillId: "sdd-remote",
|
|
119
|
+
paths: [".claude/skills/sdd-remote/SKILL.md"],
|
|
120
|
+
},
|
|
118
121
|
],
|
|
119
122
|
},
|
|
120
123
|
{
|
|
@@ -134,6 +137,10 @@ export const SKILL_ADAPTERS: SkillAdapterDefinition[] = [
|
|
|
134
137
|
skillId: "sdd-ui",
|
|
135
138
|
paths: [".agents/skills/sdd-ui/SKILL.md"],
|
|
136
139
|
},
|
|
140
|
+
{
|
|
141
|
+
skillId: "sdd-remote",
|
|
142
|
+
paths: [".agents/skills/sdd-remote/SKILL.md"],
|
|
143
|
+
},
|
|
137
144
|
],
|
|
138
145
|
},
|
|
139
146
|
];
|