docspec 0.3.0 → 0.4.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.
- package/dist/__tests__/cli.test.js +14 -3
- package/dist/__tests__/cli.test.js.map +1 -1
- package/dist/__tests__/generate.test.js +39 -0
- package/dist/__tests__/generate.test.js.map +1 -1
- package/dist/changed.d.ts.map +1 -1
- package/dist/changed.js +1 -2
- package/dist/changed.js.map +1 -1
- package/dist/cli.js +1 -1
- package/dist/create.d.ts +3 -1
- package/dist/create.d.ts.map +1 -1
- package/dist/create.js +10 -6
- package/dist/create.js.map +1 -1
- package/dist/generate.d.ts.map +1 -1
- package/dist/generate.js +4 -3
- package/dist/generate.js.map +1 -1
- package/package.json +1 -1
- package/dist/__tests__/generator.test.d.ts +0 -2
- package/dist/__tests__/generator.test.d.ts.map +0 -1
- package/dist/__tests__/generator.test.js +0 -122
- package/dist/__tests__/generator.test.js.map +0 -1
- package/dist/__tests__/validator.test.d.ts +0 -2
- package/dist/__tests__/validator.test.d.ts.map +0 -1
- package/dist/__tests__/validator.test.js +0 -331
- package/dist/__tests__/validator.test.js.map +0 -1
- package/dist/docspec-changed.d.ts +0 -25
- package/dist/docspec-changed.d.ts.map +0 -1
- package/dist/docspec-changed.js +0 -210
- package/dist/docspec-changed.js.map +0 -1
- package/dist/docspec-generate.d.ts +0 -22
- package/dist/docspec-generate.d.ts.map +0 -1
- package/dist/docspec-generate.js +0 -171
- package/dist/docspec-generate.js.map +0 -1
- package/dist/format-parser.d.ts +0 -24
- package/dist/format-parser.d.ts.map +0 -1
- package/dist/format-parser.js +0 -205
- package/dist/format-parser.js.map +0 -1
- package/dist/generator.d.ts +0 -12
- package/dist/generator.d.ts.map +0 -1
- package/dist/generator.js +0 -89
- package/dist/generator.js.map +0 -1
- package/dist/types.d.ts +0 -16
- package/dist/types.d.ts.map +0 -1
- package/dist/types.js +0 -3
- package/dist/types.js.map +0 -1
- package/dist/validator.d.ts +0 -7
- package/dist/validator.d.ts.map +0 -1
- package/dist/validator.js +0 -211
- package/dist/validator.js.map +0 -1
|
@@ -1,331 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
-
if (k2 === undefined) k2 = k;
|
|
4
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
-
}
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
-
}) : function(o, v) {
|
|
16
|
-
o["default"] = v;
|
|
17
|
-
});
|
|
18
|
-
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
-
var ownKeys = function(o) {
|
|
20
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
-
var ar = [];
|
|
22
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
-
return ar;
|
|
24
|
-
};
|
|
25
|
-
return ownKeys(o);
|
|
26
|
-
};
|
|
27
|
-
return function (mod) {
|
|
28
|
-
if (mod && mod.__esModule) return mod;
|
|
29
|
-
var result = {};
|
|
30
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
-
__setModuleDefault(result, mod);
|
|
32
|
-
return result;
|
|
33
|
-
};
|
|
34
|
-
})();
|
|
35
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
-
const fs = __importStar(require("fs/promises"));
|
|
37
|
-
const path = __importStar(require("path"));
|
|
38
|
-
const os = __importStar(require("os"));
|
|
39
|
-
const validator_1 = require("../validator");
|
|
40
|
-
const generator_1 = require("../generator");
|
|
41
|
-
const constants_1 = require("../constants");
|
|
42
|
-
describe("validator", () => {
|
|
43
|
-
let tempDir;
|
|
44
|
-
beforeEach(async () => {
|
|
45
|
-
tempDir = await fs.mkdtemp(path.join(os.tmpdir(), "docspec-test-"));
|
|
46
|
-
});
|
|
47
|
-
afterEach(async () => {
|
|
48
|
-
await fs.rm(tempDir, { recursive: true, force: true });
|
|
49
|
-
});
|
|
50
|
-
describe("validateDocspec", () => {
|
|
51
|
-
it("should validate a properly customized docspec file", async () => {
|
|
52
|
-
const filePath = path.join(tempDir, "valid.docspec.md");
|
|
53
|
-
// Create a valid docspec with customized content
|
|
54
|
-
const validContent = `# DOCSPEC: Test Document
|
|
55
|
-
|
|
56
|
-
> Short phrase: *Test document*
|
|
57
|
-
|
|
58
|
-
## 1. Document Purpose
|
|
59
|
-
|
|
60
|
-
This document describes the test suite for the docspec validator. It provides comprehensive test coverage for all validation scenarios and edge cases that the validator needs to handle correctly.
|
|
61
|
-
|
|
62
|
-
## 2. Update Triggers
|
|
63
|
-
|
|
64
|
-
Update this document when adding new test cases or when the validation logic changes. It should always reflect the current state of the test suite.
|
|
65
|
-
|
|
66
|
-
## 3. Expected Structure
|
|
67
|
-
|
|
68
|
-
This section describes the test structure and how tests are organized. Each test file covers a specific module or functionality area of the docspec package.
|
|
69
|
-
|
|
70
|
-
## 4. Editing Guidelines
|
|
71
|
-
|
|
72
|
-
Keep test descriptions clear and concise. Use descriptive test names that explain what is being tested. Follow the AAA pattern: Arrange, Act, Assert. Do: Write comprehensive tests that cover edge cases. Don't: Skip edge cases or write tests that are too simple. Always test both success and failure scenarios.
|
|
73
|
-
|
|
74
|
-
## 5. Intentional Omissions
|
|
75
|
-
|
|
76
|
-
No gaps at this time. All major functionality is covered by the test suite.
|
|
77
|
-
`;
|
|
78
|
-
await fs.writeFile(filePath, validContent, "utf-8");
|
|
79
|
-
const result = await (0, validator_1.validateDocspec)(filePath);
|
|
80
|
-
expect(result.valid).toBe(true);
|
|
81
|
-
expect(result.errors).toHaveLength(0);
|
|
82
|
-
});
|
|
83
|
-
it("should reject a file with only boilerplate content", async () => {
|
|
84
|
-
const filePath = path.join(tempDir, "boilerplate.docspec.md");
|
|
85
|
-
await (0, generator_1.generateDocspec)(filePath);
|
|
86
|
-
const result = await (0, validator_1.validateDocspec)(filePath);
|
|
87
|
-
expect(result.valid).toBe(false);
|
|
88
|
-
expect(result.errors.length).toBeGreaterThan(0);
|
|
89
|
-
expect(result.errors.some(e => e.includes("boilerplate"))).toBe(true);
|
|
90
|
-
});
|
|
91
|
-
it("should detect missing sections", async () => {
|
|
92
|
-
const filePath = path.join(tempDir, "incomplete.docspec.md");
|
|
93
|
-
const incompleteContent = `# DOCSPEC: Test
|
|
94
|
-
|
|
95
|
-
## 1. Document Purpose
|
|
96
|
-
|
|
97
|
-
Custom content here.
|
|
98
|
-
|
|
99
|
-
## 2. Update Triggers
|
|
100
|
-
|
|
101
|
-
More custom content.
|
|
102
|
-
`;
|
|
103
|
-
await fs.writeFile(filePath, incompleteContent, "utf-8");
|
|
104
|
-
const result = await (0, validator_1.validateDocspec)(filePath);
|
|
105
|
-
expect(result.valid).toBe(false);
|
|
106
|
-
// Should have errors for missing sections
|
|
107
|
-
expect(result.errors.some(e => e.includes("Missing required section"))).toBe(true);
|
|
108
|
-
});
|
|
109
|
-
it("should detect empty sections", async () => {
|
|
110
|
-
const filePath = path.join(tempDir, "empty-section.docspec.md");
|
|
111
|
-
let content = `# DOCSPEC: Test
|
|
112
|
-
|
|
113
|
-
`;
|
|
114
|
-
// Add all sections but leave one empty
|
|
115
|
-
constants_1.REQUIRED_SECTIONS.forEach((section, index) => {
|
|
116
|
-
content += `## ${index + 1}. ${section}\n\n`;
|
|
117
|
-
if (index === 2) {
|
|
118
|
-
// Leave section 3 empty
|
|
119
|
-
content += "\n";
|
|
120
|
-
}
|
|
121
|
-
else {
|
|
122
|
-
content += "Custom content for this section.\n";
|
|
123
|
-
}
|
|
124
|
-
content += "\n\n";
|
|
125
|
-
});
|
|
126
|
-
await fs.writeFile(filePath, content, "utf-8");
|
|
127
|
-
const result = await (0, validator_1.validateDocspec)(filePath);
|
|
128
|
-
expect(result.valid).toBe(false);
|
|
129
|
-
expect(result.errors.some(e => e.includes("empty"))).toBe(true);
|
|
130
|
-
});
|
|
131
|
-
it("should handle files with section numbers in headers", async () => {
|
|
132
|
-
const filePath = path.join(tempDir, "numbered.docspec.md");
|
|
133
|
-
const content = `# DOCSPEC: Test
|
|
134
|
-
|
|
135
|
-
## 1. Document Purpose
|
|
136
|
-
|
|
137
|
-
This document serves as a test case for validating docspec files with numbered section headers. It contains custom content that is different from the boilerplate template.
|
|
138
|
-
|
|
139
|
-
## 2. Update Triggers
|
|
140
|
-
|
|
141
|
-
This document should be updated whenever the validation logic for numbered headers changes. It tests the parser's ability to handle section numbers correctly.
|
|
142
|
-
|
|
143
|
-
## 3. Expected Structure
|
|
144
|
-
|
|
145
|
-
This section describes the structure of the test document. It includes all required sections with sufficient content to pass validation checks.
|
|
146
|
-
|
|
147
|
-
## 4. Editing Guidelines
|
|
148
|
-
|
|
149
|
-
The style for this test document is straightforward and technical. It focuses on clarity and precision in describing test scenarios. Do: Ensure all sections have adequate content. Don't: Use boilerplate text or leave sections empty. Always provide meaningful test data.
|
|
150
|
-
|
|
151
|
-
## 5. Intentional Omissions
|
|
152
|
-
|
|
153
|
-
There are no known gaps in this test document. All sections are complete and properly formatted.
|
|
154
|
-
`;
|
|
155
|
-
await fs.writeFile(filePath, content, "utf-8");
|
|
156
|
-
const result = await (0, validator_1.validateDocspec)(filePath);
|
|
157
|
-
expect(result.valid).toBe(true);
|
|
158
|
-
});
|
|
159
|
-
it("should handle files without section numbers in headers", async () => {
|
|
160
|
-
const filePath = path.join(tempDir, "unnumbered.docspec.md");
|
|
161
|
-
const content = `# DOCSPEC: Test
|
|
162
|
-
|
|
163
|
-
---
|
|
164
|
-
|
|
165
|
-
## Document Purpose
|
|
166
|
-
|
|
167
|
-
This document serves as a test case for validating docspec files without numbered section headers. It contains custom content that differs from the boilerplate template.
|
|
168
|
-
|
|
169
|
-
## Update Triggers
|
|
170
|
-
|
|
171
|
-
This document should be updated whenever the validation logic for unnumbered headers changes. It tests the parser's flexibility in handling different header formats.
|
|
172
|
-
|
|
173
|
-
## Expected Structure
|
|
174
|
-
|
|
175
|
-
This section describes the structure of the test document. It includes all required sections with sufficient content to pass validation checks.
|
|
176
|
-
|
|
177
|
-
## Editing Guidelines
|
|
178
|
-
|
|
179
|
-
The style for this test document is straightforward and technical. It focuses on clarity and precision in describing test scenarios. Do: Ensure all sections have adequate content. Don't: Use boilerplate text or leave sections empty. Always provide meaningful test data.
|
|
180
|
-
|
|
181
|
-
## Intentional Omissions
|
|
182
|
-
|
|
183
|
-
There are no known gaps in this test document. All sections are complete and properly formatted.
|
|
184
|
-
`;
|
|
185
|
-
await fs.writeFile(filePath, content, "utf-8");
|
|
186
|
-
const result = await (0, validator_1.validateDocspec)(filePath);
|
|
187
|
-
expect(result.valid).toBe(true);
|
|
188
|
-
});
|
|
189
|
-
it("should handle files without separators between sections", async () => {
|
|
190
|
-
const filePath = path.join(tempDir, "no-separators.docspec.md");
|
|
191
|
-
const content = `# DOCSPEC: Test
|
|
192
|
-
|
|
193
|
-
## 1. Document Purpose
|
|
194
|
-
|
|
195
|
-
This document tests the validator's ability to handle files without separator lines between sections. The content here is custom and different from boilerplate.
|
|
196
|
-
|
|
197
|
-
## 2. Update Triggers
|
|
198
|
-
|
|
199
|
-
This document should be updated when testing files without separators. The content is sufficient to pass validation.
|
|
200
|
-
|
|
201
|
-
## 3. Expected Structure
|
|
202
|
-
|
|
203
|
-
This section describes the document structure. It includes all required sections with adequate content length.
|
|
204
|
-
|
|
205
|
-
## 4. Editing Guidelines
|
|
206
|
-
|
|
207
|
-
The style rules for this test document are straightforward. Content is technical and precise. Do: Test files without separators. Don't: Require separators for validation. Ensure content is meaningful.
|
|
208
|
-
|
|
209
|
-
## 5. Intentional Omissions
|
|
210
|
-
|
|
211
|
-
No gaps in this test document. All sections are complete with sufficient content.
|
|
212
|
-
`;
|
|
213
|
-
await fs.writeFile(filePath, content, "utf-8");
|
|
214
|
-
const result = await (0, validator_1.validateDocspec)(filePath);
|
|
215
|
-
// Should be valid without separators
|
|
216
|
-
expect(result.valid).toBe(true);
|
|
217
|
-
});
|
|
218
|
-
it("should reject content that only differs by whitespace from boilerplate", async () => {
|
|
219
|
-
const filePath = path.join(tempDir, "whitespace-only.docspec.md");
|
|
220
|
-
let content = `# DOCSPEC: Test
|
|
221
|
-
|
|
222
|
-
`;
|
|
223
|
-
// Create content that's just boilerplate with different whitespace
|
|
224
|
-
constants_1.REQUIRED_SECTIONS.forEach((section, index) => {
|
|
225
|
-
content += `## ${index + 1}. ${section}\n\n`;
|
|
226
|
-
// Use boilerplate but with extra spaces
|
|
227
|
-
const boilerplate = constants_1.SECTION_BOILERPLATE[section];
|
|
228
|
-
content += boilerplate.replace(/\n/g, " \n") + "\n";
|
|
229
|
-
content += "\n\n";
|
|
230
|
-
});
|
|
231
|
-
await fs.writeFile(filePath, content, "utf-8");
|
|
232
|
-
const result = await (0, validator_1.validateDocspec)(filePath);
|
|
233
|
-
expect(result.valid).toBe(false);
|
|
234
|
-
expect(result.errors.some(e => e.includes("too similar to boilerplate"))).toBe(true);
|
|
235
|
-
});
|
|
236
|
-
it("should reject sections that are too short", async () => {
|
|
237
|
-
const filePath = path.join(tempDir, "short-section.docspec.md");
|
|
238
|
-
let content = `# DOCSPEC: Test
|
|
239
|
-
|
|
240
|
-
`;
|
|
241
|
-
constants_1.REQUIRED_SECTIONS.forEach((section, index) => {
|
|
242
|
-
content += `## ${index + 1}. ${section}\n\n`;
|
|
243
|
-
if (index === 0) {
|
|
244
|
-
// Make first section too short
|
|
245
|
-
content += "Short.\n";
|
|
246
|
-
}
|
|
247
|
-
else {
|
|
248
|
-
content += "This is a longer section with enough content to pass validation.\n";
|
|
249
|
-
}
|
|
250
|
-
content += "\n\n";
|
|
251
|
-
});
|
|
252
|
-
await fs.writeFile(filePath, content, "utf-8");
|
|
253
|
-
const result = await (0, validator_1.validateDocspec)(filePath);
|
|
254
|
-
expect(result.valid).toBe(false);
|
|
255
|
-
expect(result.errors.some(e => e.includes("too short") || e.includes("incomplete"))).toBe(true);
|
|
256
|
-
});
|
|
257
|
-
it("should handle non-existent files gracefully", async () => {
|
|
258
|
-
const filePath = path.join(tempDir, "nonexistent.docspec.md");
|
|
259
|
-
const result = await (0, validator_1.validateDocspec)(filePath);
|
|
260
|
-
expect(result.valid).toBe(false);
|
|
261
|
-
expect(result.errors.length).toBeGreaterThan(0);
|
|
262
|
-
expect(result.errors[0]).toContain("Failed to read file");
|
|
263
|
-
});
|
|
264
|
-
it("should handle files with extra sections (non-required)", async () => {
|
|
265
|
-
const filePath = path.join(tempDir, "extra-sections.docspec.md");
|
|
266
|
-
const content = `# DOCSPEC: Test
|
|
267
|
-
|
|
268
|
-
## 1. Document Purpose
|
|
269
|
-
|
|
270
|
-
This document tests the validator's handling of extra sections beyond the required ones. The content is custom and sufficient to pass validation.
|
|
271
|
-
|
|
272
|
-
## 2. Update Triggers
|
|
273
|
-
|
|
274
|
-
This document should be updated when testing extra section handling. The content is meaningful and not boilerplate.
|
|
275
|
-
|
|
276
|
-
## 3. Expected Structure
|
|
277
|
-
|
|
278
|
-
This section describes the document structure including both required and optional sections. All content is customized.
|
|
279
|
-
|
|
280
|
-
## 4. Editing Guidelines
|
|
281
|
-
|
|
282
|
-
The style rules for this test document are clear and technical. Content is sufficient in length. Do: Test extra sections. Don't: Reject valid documents with additional sections. Ensure all required sections are present.
|
|
283
|
-
|
|
284
|
-
## 5. Intentional Omissions
|
|
285
|
-
|
|
286
|
-
No gaps in this test document. All sections are complete with adequate content.
|
|
287
|
-
|
|
288
|
-
## 7. Additional Section
|
|
289
|
-
|
|
290
|
-
This is an extra section that shouldn't cause validation to fail. It contains additional information beyond the required sections.
|
|
291
|
-
`;
|
|
292
|
-
await fs.writeFile(filePath, content, "utf-8");
|
|
293
|
-
const result = await (0, validator_1.validateDocspec)(filePath);
|
|
294
|
-
// Extra sections should be allowed
|
|
295
|
-
expect(result.valid).toBe(true);
|
|
296
|
-
});
|
|
297
|
-
it("should handle case-insensitive section matching", async () => {
|
|
298
|
-
const filePath = path.join(tempDir, "case-test.docspec.md");
|
|
299
|
-
const content = `# DOCSPEC: Test
|
|
300
|
-
|
|
301
|
-
---
|
|
302
|
-
|
|
303
|
-
## 1. PURPOSE OF THIS DOCUMENT
|
|
304
|
-
|
|
305
|
-
Custom content.
|
|
306
|
-
|
|
307
|
-
## 2. when this document should be updated
|
|
308
|
-
|
|
309
|
-
Custom content.
|
|
310
|
-
|
|
311
|
-
## 3. Expected Structure
|
|
312
|
-
|
|
313
|
-
Custom content.
|
|
314
|
-
|
|
315
|
-
## 4. Editing Guidelines
|
|
316
|
-
|
|
317
|
-
Custom style and editing guidelines content.
|
|
318
|
-
|
|
319
|
-
## 5. Intentional Omissions
|
|
320
|
-
|
|
321
|
-
Custom gaps content.
|
|
322
|
-
`;
|
|
323
|
-
await fs.writeFile(filePath, content, "utf-8");
|
|
324
|
-
const result = await (0, validator_1.validateDocspec)(filePath);
|
|
325
|
-
// Currently the validator is case-sensitive, so this will fail
|
|
326
|
-
// This test documents current behavior - could be enhanced later
|
|
327
|
-
expect(result.valid).toBe(false);
|
|
328
|
-
});
|
|
329
|
-
});
|
|
330
|
-
});
|
|
331
|
-
//# sourceMappingURL=validator.test.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"validator.test.js","sourceRoot":"","sources":["../../src/__tests__/validator.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
export interface DocspecChangedOptions {
|
|
2
|
-
/** List of changed file paths (repo-relative). If not set, base and merge must be set. */
|
|
3
|
-
changedFiles?: string[];
|
|
4
|
-
/** Base SHA for git diff (e.g. PR base). */
|
|
5
|
-
base?: string;
|
|
6
|
-
/** Merge SHA for git diff (e.g. PR merge commit). */
|
|
7
|
-
merge?: string;
|
|
8
|
-
/** Max number of docspecs to include. */
|
|
9
|
-
maxDocspecs?: number;
|
|
10
|
-
/** Max characters of diff to include. */
|
|
11
|
-
maxDiffChars?: number;
|
|
12
|
-
/** Repo root (default process.cwd()). */
|
|
13
|
-
repoRoot?: string;
|
|
14
|
-
}
|
|
15
|
-
/**
|
|
16
|
-
* Build the docspec-changed prompt and return it as a string.
|
|
17
|
-
* If options.outputPath is set, writes the prompt to that file.
|
|
18
|
-
*/
|
|
19
|
-
export declare function buildDocspecChangedPrompt(options: DocspecChangedOptions & {
|
|
20
|
-
outputPath?: string;
|
|
21
|
-
}): Promise<{
|
|
22
|
-
prompt: string;
|
|
23
|
-
outputPath: string | null;
|
|
24
|
-
}>;
|
|
25
|
-
//# sourceMappingURL=docspec-changed.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"docspec-changed.d.ts","sourceRoot":"","sources":["../src/docspec-changed.ts"],"names":[],"mappings":"AASA,MAAM,WAAW,qBAAqB;IACpC,0FAA0F;IAC1F,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,4CAA4C;IAC5C,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,qDAAqD;IACrD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,yCAAyC;IACzC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,yCAAyC;IACzC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,yCAAyC;IACzC,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAiHD;;;GAGG;AACH,wBAAsB,yBAAyB,CAC7C,OAAO,EAAE,qBAAqB,GAAG;IAAE,UAAU,CAAC,EAAE,MAAM,CAAA;CAAE,GACvD,OAAO,CAAC;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,CAAC,CAmGxD"}
|
package/dist/docspec-changed.js
DELETED
|
@@ -1,210 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
-
if (k2 === undefined) k2 = k;
|
|
4
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
-
}
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
-
}) : function(o, v) {
|
|
16
|
-
o["default"] = v;
|
|
17
|
-
});
|
|
18
|
-
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
-
var ownKeys = function(o) {
|
|
20
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
-
var ar = [];
|
|
22
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
-
return ar;
|
|
24
|
-
};
|
|
25
|
-
return ownKeys(o);
|
|
26
|
-
};
|
|
27
|
-
return function (mod) {
|
|
28
|
-
if (mod && mod.__esModule) return mod;
|
|
29
|
-
var result = {};
|
|
30
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
-
__setModuleDefault(result, mod);
|
|
32
|
-
return result;
|
|
33
|
-
};
|
|
34
|
-
})();
|
|
35
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
-
exports.buildDocspecChangedPrompt = buildDocspecChangedPrompt;
|
|
37
|
-
const fs = __importStar(require("fs/promises"));
|
|
38
|
-
const fsSync = __importStar(require("fs"));
|
|
39
|
-
const path = __importStar(require("path"));
|
|
40
|
-
const child_process_1 = require("child_process");
|
|
41
|
-
const path_utils_1 = require("./path-utils");
|
|
42
|
-
const DEFAULT_MAX_DOCSPECS = 10;
|
|
43
|
-
const DEFAULT_MAX_DIFF_CHARS = 120000;
|
|
44
|
-
/**
|
|
45
|
-
* List changed files via git diff --name-only base...merge
|
|
46
|
-
*/
|
|
47
|
-
function listChangedFiles(base, merge, repoRoot) {
|
|
48
|
-
const out = (0, child_process_1.execSync)(`git diff --name-only ${base}...${merge}`, {
|
|
49
|
-
encoding: "utf-8",
|
|
50
|
-
cwd: repoRoot,
|
|
51
|
-
}).trim();
|
|
52
|
-
return out ? out.split("\n").map((line) => line.trim()).filter(Boolean) : [];
|
|
53
|
-
}
|
|
54
|
-
/**
|
|
55
|
-
* Get diff text via git diff base...merge, truncated if needed.
|
|
56
|
-
*/
|
|
57
|
-
function getDiffText(base, merge, repoRoot, maxChars) {
|
|
58
|
-
let diff;
|
|
59
|
-
try {
|
|
60
|
-
diff = (0, child_process_1.execSync)(`git diff ${base}...${merge}`, { encoding: "utf-8", cwd: repoRoot });
|
|
61
|
-
}
|
|
62
|
-
catch {
|
|
63
|
-
return "";
|
|
64
|
-
}
|
|
65
|
-
if (diff.length > maxChars) {
|
|
66
|
-
diff = diff.slice(0, maxChars) + "\n\n[DIFF TRUNCATED]\n";
|
|
67
|
-
}
|
|
68
|
-
return diff;
|
|
69
|
-
}
|
|
70
|
-
/**
|
|
71
|
-
* Find all docspec paths under .docspec/ in the repo.
|
|
72
|
-
*/
|
|
73
|
-
async function findAllDocspecPaths(docspecDir) {
|
|
74
|
-
const files = [];
|
|
75
|
-
try {
|
|
76
|
-
const entries = await fs.readdir(docspecDir, { withFileTypes: true });
|
|
77
|
-
for (const entry of entries) {
|
|
78
|
-
const full = path.join(docspecDir, entry.name);
|
|
79
|
-
if (entry.isDirectory()) {
|
|
80
|
-
files.push(...(await findAllDocspecPaths(full)));
|
|
81
|
-
}
|
|
82
|
-
else if (entry.isFile() && entry.name.endsWith(".docspec.md")) {
|
|
83
|
-
files.push(full);
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
catch (e) {
|
|
88
|
-
if (e.code !== "ENOENT")
|
|
89
|
-
throw e;
|
|
90
|
-
}
|
|
91
|
-
return files;
|
|
92
|
-
}
|
|
93
|
-
/**
|
|
94
|
-
* Find candidate docspec files to process given changed files.
|
|
95
|
-
* Strategy:
|
|
96
|
-
* 1) Changed files that are under .docspec/ and end with .docspec.md are included.
|
|
97
|
-
* 2) For each other changed file, walk up from its directory to repo root; at each level,
|
|
98
|
-
* include docspecs whose target markdown lives in that directory.
|
|
99
|
-
*/
|
|
100
|
-
function findCandidateDocspecs(repoRoot, docspecPaths, changedFiles, maxDocspecs) {
|
|
101
|
-
const normalizedRoot = path.normalize(repoRoot).replace(/\\/g, "/");
|
|
102
|
-
const candidates = [];
|
|
103
|
-
const seen = new Set();
|
|
104
|
-
const add = (p) => {
|
|
105
|
-
const norm = path.normalize(p).replace(/\\/g, "/");
|
|
106
|
-
if (!seen.has(norm)) {
|
|
107
|
-
seen.add(norm);
|
|
108
|
-
candidates.push(p);
|
|
109
|
-
}
|
|
110
|
-
};
|
|
111
|
-
// 1) Directly changed docspecs (under .docspec/)
|
|
112
|
-
for (const f of changedFiles) {
|
|
113
|
-
const normalized = path.normalize(f).replace(/\\/g, "/");
|
|
114
|
-
if ((0, path_utils_1.isDocspecPath)(normalized) || (normalized.startsWith(".docspec/") && normalized.endsWith(".docspec.md"))) {
|
|
115
|
-
const full = path.join(repoRoot, f);
|
|
116
|
-
add(full);
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
// 2) For each changed file, walk up directory and include docspecs whose target markdown is in that directory
|
|
120
|
-
for (const f of changedFiles) {
|
|
121
|
-
const normalized = path.normalize(f).replace(/\\/g, "/");
|
|
122
|
-
if (normalized.startsWith(".docspec/"))
|
|
123
|
-
continue; // already handled
|
|
124
|
-
const fullPath = path.join(repoRoot, f);
|
|
125
|
-
let dir = path.dirname(fullPath);
|
|
126
|
-
while (true) {
|
|
127
|
-
const relDir = path.relative(repoRoot, dir).replace(/\\/g, "/") || ".";
|
|
128
|
-
for (const { docspecPath, targetMdPath } of docspecPaths) {
|
|
129
|
-
const targetDir = path.dirname(targetMdPath).replace(/\\/g, "/") || ".";
|
|
130
|
-
if (targetDir === relDir) {
|
|
131
|
-
add(docspecPath);
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
const parent = path.dirname(dir);
|
|
135
|
-
if (parent === dir || path.relative(repoRoot, parent).startsWith(".."))
|
|
136
|
-
break;
|
|
137
|
-
dir = parent;
|
|
138
|
-
}
|
|
139
|
-
// Include if the changed file is the target markdown
|
|
140
|
-
for (const { docspecPath, targetMdPath } of docspecPaths) {
|
|
141
|
-
if (path.normalize(f).replace(/\\/g, "/") === path.normalize(targetMdPath).replace(/\\/g, "/")) {
|
|
142
|
-
add(docspecPath);
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
return candidates.slice(0, maxDocspecs);
|
|
147
|
-
}
|
|
148
|
-
/**
|
|
149
|
-
* Build the docspec-changed prompt and return it as a string.
|
|
150
|
-
* If options.outputPath is set, writes the prompt to that file.
|
|
151
|
-
*/
|
|
152
|
-
async function buildDocspecChangedPrompt(options) {
|
|
153
|
-
const repoRoot = path.resolve(options.repoRoot ?? process.cwd());
|
|
154
|
-
const docspecDir = path.join(repoRoot, ".docspec");
|
|
155
|
-
let changedFiles = options.changedFiles ?? [];
|
|
156
|
-
let diffText = "";
|
|
157
|
-
if (changedFiles.length === 0 && options.base && options.merge) {
|
|
158
|
-
changedFiles = listChangedFiles(options.base, options.merge, repoRoot);
|
|
159
|
-
diffText = getDiffText(options.base, options.merge, repoRoot, options.maxDiffChars ?? DEFAULT_MAX_DIFF_CHARS);
|
|
160
|
-
}
|
|
161
|
-
else if (options.changedFiles && options.changedFiles.length > 0 && options.base && options.merge) {
|
|
162
|
-
diffText = getDiffText(options.base, options.merge, repoRoot, options.maxDiffChars ?? DEFAULT_MAX_DIFF_CHARS);
|
|
163
|
-
}
|
|
164
|
-
const allDocspecPaths = await findAllDocspecPaths(docspecDir);
|
|
165
|
-
const docspecWithTargets = allDocspecPaths
|
|
166
|
-
.map((p) => {
|
|
167
|
-
const rel = path.relative(repoRoot, p).replace(/\\/g, "/");
|
|
168
|
-
const targetMd = (0, path_utils_1.docspecToMarkdownPath)(rel);
|
|
169
|
-
return { docspecPath: p, targetMdPath: targetMd };
|
|
170
|
-
})
|
|
171
|
-
.filter(({ docspecPath }) => fsSync.existsSync(docspecPath));
|
|
172
|
-
const candidates = findCandidateDocspecs(repoRoot, docspecWithTargets, changedFiles, options.maxDocspecs ?? DEFAULT_MAX_DOCSPECS);
|
|
173
|
-
const parts = [
|
|
174
|
-
"Merged PR diff (context):",
|
|
175
|
-
"<diff>",
|
|
176
|
-
diffText || "(no diff available)",
|
|
177
|
-
"</diff>",
|
|
178
|
-
"",
|
|
179
|
-
"The following docspec files were discovered based on the PR changes. For each docspec, check if its target markdown file needs to be updated based on the code changes:",
|
|
180
|
-
"",
|
|
181
|
-
];
|
|
182
|
-
let added = 0;
|
|
183
|
-
for (const docspecPath of candidates) {
|
|
184
|
-
const relDocspec = path.relative(repoRoot, docspecPath).replace(/\\/g, "/");
|
|
185
|
-
const targetMdPath = (0, path_utils_1.docspecToMarkdownPath)(relDocspec);
|
|
186
|
-
const targetFull = path.join(repoRoot, targetMdPath);
|
|
187
|
-
try {
|
|
188
|
-
await fs.access(targetFull);
|
|
189
|
-
}
|
|
190
|
-
catch {
|
|
191
|
-
continue;
|
|
192
|
-
}
|
|
193
|
-
const docspecContent = await fs.readFile(docspecPath, "utf-8");
|
|
194
|
-
const mdContent = await fs.readFile(targetFull, "utf-8");
|
|
195
|
-
parts.push(`## Docspec: ${relDocspec}`, `Target markdown: ${targetMdPath}`, "", "<docspec>", docspecContent, "</docspec>", "", "<markdown>", mdContent, "</markdown>", "");
|
|
196
|
-
added++;
|
|
197
|
-
}
|
|
198
|
-
if (added === 0) {
|
|
199
|
-
return { prompt: "", outputPath: null };
|
|
200
|
-
}
|
|
201
|
-
parts.push("Task:", "1. Explore the repository using your available tools to understand the codebase context", "2. Understand how the code changes in the diff relate to each docspec's requirements", "3. For each markdown file listed above, check if it already satisfies its docspec given the code changes", "4. Only update markdown files if changes are actually necessary to satisfy their docspecs - avoid making unnecessary changes", "5. Use the Edit tool to modify markdown files directly if changes are needed", "6. Do not provide any text output - files are modified directly using tools");
|
|
202
|
-
const prompt = parts.join("\n");
|
|
203
|
-
const outPath = options.outputPath ? path.resolve(repoRoot, options.outputPath) : null;
|
|
204
|
-
if (outPath && prompt) {
|
|
205
|
-
await fs.mkdir(path.dirname(outPath), { recursive: true });
|
|
206
|
-
await fs.writeFile(outPath, prompt, "utf-8");
|
|
207
|
-
}
|
|
208
|
-
return { prompt, outputPath: outPath };
|
|
209
|
-
}
|
|
210
|
-
//# sourceMappingURL=docspec-changed.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"docspec-changed.js","sourceRoot":"","sources":["../src/docspec-changed.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
export interface DocspecGenerateOptions {
|
|
2
|
-
/** Path to the markdown file (repo-relative, e.g. README.md or docs/deploy.md). */
|
|
3
|
-
markdownPath: string;
|
|
4
|
-
/** If true, overwrite existing docspec. If false and docspec exists, throws. */
|
|
5
|
-
overwrite?: boolean;
|
|
6
|
-
/** Repo root (default process.cwd()). */
|
|
7
|
-
repoRoot?: string;
|
|
8
|
-
}
|
|
9
|
-
/**
|
|
10
|
-
* Generate the docspec file (if missing or overwrite), then build plan and implementation prompts.
|
|
11
|
-
* Returns combined prompt (implementation prompt with {{PLAN}} placeholder) and optional paths to write.
|
|
12
|
-
*/
|
|
13
|
-
export declare function buildDocspecGeneratePrompts(options: DocspecGenerateOptions & {
|
|
14
|
-
outputPromptPath?: string;
|
|
15
|
-
outputPlanPath?: string;
|
|
16
|
-
}): Promise<{
|
|
17
|
-
planPrompt: string;
|
|
18
|
-
implPrompt: string;
|
|
19
|
-
outputPromptPath?: string;
|
|
20
|
-
outputPlanPath?: string;
|
|
21
|
-
}>;
|
|
22
|
-
//# sourceMappingURL=docspec-generate.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"docspec-generate.d.ts","sourceRoot":"","sources":["../src/docspec-generate.ts"],"names":[],"mappings":"AAqFA,MAAM,WAAW,sBAAsB;IACrC,mFAAmF;IACnF,YAAY,EAAE,MAAM,CAAC;IACrB,gFAAgF;IAChF,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,yCAAyC;IACzC,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;;GAGG;AACH,wBAAsB,2BAA2B,CAC/C,OAAO,EAAE,sBAAsB,GAAG;IAChC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB,GACA,OAAO,CAAC;IAAE,UAAU,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC;IAAC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAAC,cAAc,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CA0DzG"}
|