@popoverai/dotrequirements 0.23.0 → 0.24.1
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/README.md +169 -22
- package/dist/cli.js +121 -60
- package/dist/codebase-to-spec/budget.d.ts +53 -0
- package/dist/codebase-to-spec/budget.js +80 -0
- package/dist/codebase-to-spec/cache.d.ts +49 -0
- package/dist/codebase-to-spec/cache.js +54 -0
- package/dist/codebase-to-spec/claude.d.ts +69 -0
- package/dist/codebase-to-spec/claude.js +126 -0
- package/dist/codebase-to-spec/compose.d.ts +49 -0
- package/dist/codebase-to-spec/compose.js +124 -0
- package/dist/codebase-to-spec/edit-loop.d.ts +54 -0
- package/dist/codebase-to-spec/edit-loop.js +195 -0
- package/dist/codebase-to-spec/editor.d.ts +54 -0
- package/dist/codebase-to-spec/editor.js +74 -0
- package/dist/codebase-to-spec/exit-codes.d.ts +40 -0
- package/dist/codebase-to-spec/exit-codes.js +58 -0
- package/dist/codebase-to-spec/fan-out.d.ts +63 -0
- package/dist/codebase-to-spec/fan-out.js +215 -0
- package/dist/codebase-to-spec/interactive.d.ts +30 -0
- package/dist/codebase-to-spec/interactive.js +48 -0
- package/dist/codebase-to-spec/outline-review-loop.d.ts +51 -0
- package/dist/codebase-to-spec/outline-review-loop.js +187 -0
- package/dist/codebase-to-spec/pack.d.ts +51 -0
- package/dist/codebase-to-spec/pack.js +127 -0
- package/dist/codebase-to-spec/planner.d.ts +41 -0
- package/dist/codebase-to-spec/planner.js +76 -0
- package/dist/codebase-to-spec/present.d.ts +94 -0
- package/dist/codebase-to-spec/present.js +288 -0
- package/dist/codebase-to-spec/progress.d.ts +33 -0
- package/dist/codebase-to-spec/progress.js +28 -0
- package/dist/codebase-to-spec/prompts/editor.d.ts +13 -0
- package/dist/codebase-to-spec/prompts/editor.js +57 -0
- package/dist/codebase-to-spec/prompts/outline-reviewer.d.ts +12 -0
- package/dist/codebase-to-spec/prompts/outline-reviewer.js +87 -0
- package/dist/codebase-to-spec/prompts/planner-initial.d.ts +11 -0
- package/dist/codebase-to-spec/prompts/planner-initial.js +125 -0
- package/dist/codebase-to-spec/prompts/planner-revise.d.ts +14 -0
- package/dist/codebase-to-spec/prompts/planner-revise.js +60 -0
- package/dist/codebase-to-spec/prompts/spec-reviewer.d.ts +16 -0
- package/dist/codebase-to-spec/prompts/spec-reviewer.js +96 -0
- package/dist/codebase-to-spec/prompts/specifier.d.ts +12 -0
- package/dist/codebase-to-spec/prompts/specifier.js +100 -0
- package/dist/codebase-to-spec/prompts/style-check.d.ts +12 -0
- package/dist/codebase-to-spec/prompts/style-check.js +78 -0
- package/dist/codebase-to-spec/schemas.d.ts +257 -0
- package/dist/codebase-to-spec/schemas.js +183 -0
- package/dist/codebase-to-spec/skill-install.d.ts +57 -0
- package/dist/codebase-to-spec/skill-install.js +79 -0
- package/dist/codebase-to-spec/slice.d.ts +49 -0
- package/dist/codebase-to-spec/slice.js +111 -0
- package/dist/codebase-to-spec/specifier.d.ts +60 -0
- package/dist/codebase-to-spec/specifier.js +79 -0
- package/dist/codebase-to-spec/style-check.d.ts +29 -0
- package/dist/codebase-to-spec/style-check.js +33 -0
- package/dist/codebase-to-spec/summary.d.ts +51 -0
- package/dist/codebase-to-spec/summary.js +183 -0
- package/dist/codebase-to-spec/validate.d.ts +46 -0
- package/dist/codebase-to-spec/validate.js +130 -0
- package/dist/commands/acceptance-test.d.ts +6 -0
- package/dist/commands/{browsertest.js → acceptance-test.js} +36 -29
- package/dist/commands/ai-setup.d.ts +5 -0
- package/dist/commands/ai-setup.js +441 -0
- package/dist/commands/codebase-to-spec/compose.d.ts +14 -0
- package/dist/commands/codebase-to-spec/compose.js +57 -0
- package/dist/commands/codebase-to-spec/edit-loop.d.ts +16 -0
- package/dist/commands/codebase-to-spec/edit-loop.js +83 -0
- package/dist/commands/codebase-to-spec/fan-out.d.ts +19 -0
- package/dist/commands/codebase-to-spec/fan-out.js +77 -0
- package/dist/commands/codebase-to-spec/index.d.ts +9 -0
- package/dist/commands/codebase-to-spec/index.js +135 -0
- package/dist/commands/codebase-to-spec/pack.d.ts +22 -0
- package/dist/commands/codebase-to-spec/pack.js +76 -0
- package/dist/commands/codebase-to-spec/plan-loop.d.ts +26 -0
- package/dist/commands/codebase-to-spec/plan-loop.js +105 -0
- package/dist/commands/codebase-to-spec/present.d.ts +21 -0
- package/dist/commands/codebase-to-spec/present.js +92 -0
- package/dist/commands/codebase-to-spec/run.d.ts +20 -0
- package/dist/commands/codebase-to-spec/run.js +85 -0
- package/dist/commands/codebase-to-spec/skill-install.d.ts +20 -0
- package/dist/commands/codebase-to-spec/skill-install.js +51 -0
- package/dist/commands/codebase-to-spec/specify-area.d.ts +18 -0
- package/dist/commands/codebase-to-spec/specify-area.js +82 -0
- package/dist/commands/codebase-to-spec/style-check.d.ts +15 -0
- package/dist/commands/codebase-to-spec/style-check.js +42 -0
- package/dist/commands/codebase-to-spec/validate.d.ts +18 -0
- package/dist/commands/codebase-to-spec/validate.js +38 -0
- package/dist/commands/create-requirement-document.d.ts +2 -0
- package/dist/commands/create-requirement-document.js +41 -0
- package/dist/commands/finalize.js +7 -7
- package/dist/commands/get.d.ts +2 -0
- package/dist/commands/get.js +55 -0
- package/dist/commands/init.js +132 -117
- package/dist/commands/link.js +27 -27
- package/dist/commands/list.d.ts +6 -0
- package/dist/commands/list.js +43 -0
- package/dist/commands/mcp.js +1 -1
- package/dist/commands/prepare.js +4 -4
- package/dist/commands/pull.js +116 -121
- package/dist/commands/push.js +106 -112
- package/dist/commands/report.d.ts +6 -2
- package/dist/commands/report.js +177 -122
- package/dist/commands/requirements-for.d.ts +2 -0
- package/dist/commands/requirements-for.js +29 -0
- package/dist/commands/review-test.d.ts +2 -0
- package/dist/commands/review-test.js +75 -0
- package/dist/commands/search.d.ts +6 -0
- package/dist/commands/search.js +39 -0
- package/dist/commands/style-check.d.ts +7 -0
- package/dist/commands/style-check.js +75 -0
- package/dist/commands/tests-for.d.ts +2 -0
- package/dist/commands/tests-for.js +80 -0
- package/dist/commands/validate.d.ts +6 -0
- package/dist/commands/validate.js +72 -0
- package/dist/config.js +1 -1
- package/dist/convex.d.ts +34 -22
- package/dist/convex.js +38 -22
- package/dist/harness/cache.d.ts +1 -5
- package/dist/harness/cache.js +49 -59
- package/dist/harness/convexReporting.d.ts +1 -1
- package/dist/harness/convexReporting.js +9 -7
- package/dist/harness/coverageCache.js +3 -3
- package/dist/harness/finalize.js +59 -46
- package/dist/harness/index.d.ts +6 -7
- package/dist/harness/index.js +9 -10
- package/dist/harness/prepare.js +6 -5
- package/dist/harness/requirementsLoader.d.ts +2 -2
- package/dist/harness/requirementsLoader.js +13 -35
- package/dist/harness/tracking.js +18 -18
- package/dist/harness/types.d.ts +1 -1
- package/dist/mcp/convexClient.d.ts +0 -39
- package/dist/mcp/convexClient.js +2 -107
- package/dist/mcp/handlers/authoring.d.ts +1 -1
- package/dist/mcp/handlers/authoring.js +30 -234
- package/dist/mcp/handlers/debug.d.ts +2 -3
- package/dist/mcp/handlers/debug.js +10 -10
- package/dist/mcp/handlers/get.d.ts +1 -1
- package/dist/mcp/handlers/get.js +11 -10
- package/dist/mcp/handlers/index.d.ts +20 -20
- package/dist/mcp/handlers/index.js +10 -10
- package/dist/mcp/handlers/list.d.ts +4 -33
- package/dist/mcp/handlers/list.js +16 -38
- package/dist/mcp/handlers/push.d.ts +1 -1
- package/dist/mcp/handlers/push.js +28 -18
- package/dist/mcp/handlers/report.d.ts +16 -0
- package/dist/mcp/handlers/report.js +134 -0
- package/dist/mcp/handlers/review.d.ts +1 -1
- package/dist/mcp/handlers/review.js +40 -59
- package/dist/mcp/handlers/search.d.ts +1 -1
- package/dist/mcp/handlers/search.js +7 -9
- package/dist/mcp/handlers/test-mapping.d.ts +1 -1
- package/dist/mcp/handlers/test-mapping.js +14 -14
- package/dist/mcp/handlers/types.d.ts +3 -3
- package/dist/mcp/handlers/types.js +2 -2
- package/dist/mcp/index.d.ts +1 -1
- package/dist/mcp/index.js +147 -167
- package/dist/push/core.d.ts +2 -2
- package/dist/push/core.js +20 -20
- package/dist/push/index.d.ts +1 -1
- package/dist/push/index.js +2 -2
- package/dist/requirements/cloud-ai.d.ts +57 -0
- package/dist/requirements/cloud-ai.js +104 -0
- package/dist/requirements/cloud-coverage.d.ts +41 -0
- package/dist/requirements/cloud-coverage.js +60 -0
- package/dist/requirements/coverage.d.ts +45 -0
- package/dist/requirements/coverage.js +114 -0
- package/dist/{mcp → requirements}/grep.d.ts +10 -1
- package/dist/{mcp → requirements}/grep.js +89 -44
- package/dist/{mcp/requirements.d.ts → requirements/index.d.ts} +19 -3
- package/dist/{mcp/requirements.js → requirements/index.js} +54 -35
- package/dist/requirements/style-guide.d.ts +67 -0
- package/dist/requirements/style-guide.js +299 -0
- package/dist/{mcp → requirements}/testCodeExtractor.js +24 -26
- package/dist/schema/browser.d.ts +8 -8
- package/dist/schema/browser.js +13 -15
- package/dist/schema/builder.d.ts +1 -1
- package/dist/schema/builder.js +13 -44
- package/dist/schema/conversions.d.ts +2 -2
- package/dist/schema/conversions.js +11 -11
- package/dist/schema/index.d.ts +9 -9
- package/dist/schema/index.js +15 -15
- package/dist/schema/parser-core.d.ts +1 -1
- package/dist/schema/parser-core.js +23 -22
- package/dist/schema/parser.d.ts +3 -3
- package/dist/schema/parser.js +27 -31
- package/dist/schema/resolver.d.ts +1 -1
- package/dist/schema/resolver.js +9 -9
- package/dist/schema/scenario.d.ts +1 -1
- package/dist/schema/scenario.js +1 -1
- package/dist/schema/schemas.d.ts +3 -3
- package/dist/schema/schemas.js +41 -28
- package/dist/schema/test-schema.js +27 -27
- package/dist/templates/context-file-section.md +3 -2
- package/dist/templates/example-requirements.js +1 -1
- package/dist/templates/example-requirements.ts +3 -1
- package/dist/templates/requirements-readme.js +1 -1
- package/dist/templates/requirements-readme.ts +1 -1
- package/dist/templates/skills/codebase-to-spec/SKILL.md +118 -0
- package/dist/utils/brand.js +3 -3
- package/dist/utils/browser-launch.js +4 -4
- package/dist/utils/context-file.d.ts +1 -1
- package/dist/utils/context-file.js +26 -26
- package/dist/utils/env.js +7 -7
- package/dist/utils/gitignore.js +7 -7
- package/dist/utils/oauth-callback-server.d.ts +1 -1
- package/dist/utils/oauth-callback-server.js +27 -25
- package/dist/utils/oauth-flow.js +32 -29
- package/dist/utils/project-discovery.d.ts +3 -3
- package/dist/utils/project-discovery.js +18 -17
- package/dist/utils/project-name.js +8 -8
- package/dist/utils/project-selector.d.ts +1 -1
- package/dist/utils/project-selector.js +24 -21
- package/dist/utils/project-settings.d.ts +1 -1
- package/dist/utils/project-settings.js +24 -22
- package/dist/utils/templates.js +6 -6
- package/package.json +3 -2
- package/dist/commands/browsertest.d.ts +0 -6
- package/dist/commands/login.d.ts +0 -12
- package/dist/commands/login.js +0 -117
- package/dist/commands/logout.d.ts +0 -5
- package/dist/commands/logout.js +0 -17
- package/dist/commands/mcp-setup.d.ts +0 -5
- package/dist/commands/mcp-setup.js +0 -431
- package/dist/commands/test.d.ts +0 -6
- package/dist/commands/test.js +0 -78
- package/dist/mcp/handlers/coverage.d.ts +0 -44
- package/dist/mcp/handlers/coverage.js +0 -105
- package/dist/mcp/types.d.ts +0 -27
- package/dist/mcp/types.js +0 -2
- package/dist/utils/local-project.d.ts +0 -31
- package/dist/utils/local-project.js +0 -33
- package/dist/utils/token-refresh.d.ts +0 -24
- package/dist/utils/token-refresh.js +0 -69
- package/dist/utils/token-storage.d.ts +0 -31
- package/dist/utils/token-storage.js +0 -57
- /package/dist/{mcp → requirements}/testCodeExtractor.d.ts +0 -0
package/dist/push/core.js
CHANGED
|
@@ -9,11 +9,11 @@
|
|
|
9
9
|
* - Executing the push
|
|
10
10
|
* - Updating local files with document IDs and timestamps
|
|
11
11
|
*/
|
|
12
|
-
import * as fs from
|
|
13
|
-
import * as path from
|
|
14
|
-
import { ConvexHttpClient } from
|
|
15
|
-
import {
|
|
16
|
-
import {
|
|
12
|
+
import * as fs from "node:fs";
|
|
13
|
+
import * as path from "node:path";
|
|
14
|
+
import { ConvexHttpClient } from "convex/browser";
|
|
15
|
+
import { api } from "../convex.js";
|
|
16
|
+
import { buildRequirementsFile, getAllRequirements, parseRequirementKey, parseRequirementsFromFile, } from "../schema/index.js";
|
|
17
17
|
// ============================================================================
|
|
18
18
|
// Parsing
|
|
19
19
|
// ============================================================================
|
|
@@ -36,7 +36,7 @@ export function parseFilesForPush(filePaths) {
|
|
|
36
36
|
let totalRequirements = 0;
|
|
37
37
|
for (const filePath of filePaths) {
|
|
38
38
|
// Read raw file content
|
|
39
|
-
const rawContent = fs.readFileSync(filePath,
|
|
39
|
+
const rawContent = fs.readFileSync(filePath, "utf-8");
|
|
40
40
|
// Parse to get metadata and requirements
|
|
41
41
|
const parsed = parseRequirementsFromFile(filePath);
|
|
42
42
|
const flatRequirements = getAllRequirements(parsed.requirements);
|
|
@@ -82,9 +82,9 @@ export async function dryRunPush(parsedFiles, credentials) {
|
|
|
82
82
|
file,
|
|
83
83
|
result: {
|
|
84
84
|
dryRun: true,
|
|
85
|
-
action:
|
|
85
|
+
action: "invalid",
|
|
86
86
|
title: fileName,
|
|
87
|
-
error:
|
|
87
|
+
error: "Missing document section in frontmatter",
|
|
88
88
|
},
|
|
89
89
|
});
|
|
90
90
|
continue;
|
|
@@ -95,7 +95,7 @@ export async function dryRunPush(parsedFiles, credentials) {
|
|
|
95
95
|
projectSlug: credentials.projectId,
|
|
96
96
|
projectSecret: credentials.projectSecret,
|
|
97
97
|
},
|
|
98
|
-
target: { type:
|
|
98
|
+
target: { type: "project", slug: credentials.projectId },
|
|
99
99
|
documentId: doc.id,
|
|
100
100
|
title: doc.title,
|
|
101
101
|
markdownContent: file.markdownContent,
|
|
@@ -109,7 +109,7 @@ export async function dryRunPush(parsedFiles, credentials) {
|
|
|
109
109
|
file,
|
|
110
110
|
result: {
|
|
111
111
|
dryRun: true,
|
|
112
|
-
action:
|
|
112
|
+
action: "invalid",
|
|
113
113
|
title: doc.title,
|
|
114
114
|
error: err.message,
|
|
115
115
|
},
|
|
@@ -117,10 +117,10 @@ export async function dryRunPush(parsedFiles, credentials) {
|
|
|
117
117
|
}
|
|
118
118
|
}
|
|
119
119
|
// Categorize results
|
|
120
|
-
const updates = dryRunResults.filter((r) => r.result.action ===
|
|
121
|
-
const creates = dryRunResults.filter((r) => r.result.action ===
|
|
122
|
-
const notFound = dryRunResults.filter((r) => r.result.action ===
|
|
123
|
-
const invalid = dryRunResults.filter((r) => r.result.action ===
|
|
120
|
+
const updates = dryRunResults.filter((r) => r.result.action === "update");
|
|
121
|
+
const creates = dryRunResults.filter((r) => r.result.action === "create");
|
|
122
|
+
const notFound = dryRunResults.filter((r) => r.result.action === "not_found");
|
|
123
|
+
const invalid = dryRunResults.filter((r) => r.result.action === "invalid");
|
|
124
124
|
// Check for conflicts on updates (cloud changed since last pull)
|
|
125
125
|
const conflicts = [];
|
|
126
126
|
if (updates.length > 0) {
|
|
@@ -130,7 +130,7 @@ export async function dryRunPush(parsedFiles, credentials) {
|
|
|
130
130
|
projectSlug: credentials.projectId,
|
|
131
131
|
projectSecret: credentials.projectSecret,
|
|
132
132
|
},
|
|
133
|
-
target: { type:
|
|
133
|
+
target: { type: "project", slug: credentials.projectId },
|
|
134
134
|
documentIds: docIds,
|
|
135
135
|
});
|
|
136
136
|
const cloudMetaByDocId = new Map(cloudMetadata.map((m) => [m.documentId, m]));
|
|
@@ -174,28 +174,28 @@ export async function executePush(dryRunResult, credentials) {
|
|
|
174
174
|
const doc = file.metadata.document;
|
|
175
175
|
const fileName = path.basename(file.filePath);
|
|
176
176
|
// For not_found, clear the ID so we create a new document
|
|
177
|
-
const effectiveDocId = result.action ===
|
|
177
|
+
const effectiveDocId = result.action === "not_found" ? undefined : doc.id;
|
|
178
178
|
try {
|
|
179
179
|
const pushResult = (await client.mutation(api.documents.saveWithRequirements.saveWithRequirements, {
|
|
180
180
|
projectAuth: {
|
|
181
181
|
projectSlug: credentials.projectId,
|
|
182
182
|
projectSecret: credentials.projectSecret,
|
|
183
183
|
},
|
|
184
|
-
target: { type:
|
|
184
|
+
target: { type: "project", slug: credentials.projectId },
|
|
185
185
|
documentId: effectiveDocId,
|
|
186
186
|
title: doc.title,
|
|
187
187
|
markdownContent: file.markdownContent,
|
|
188
188
|
defaultPrefix: doc.defaultPrefix,
|
|
189
189
|
dryRun: false,
|
|
190
190
|
}));
|
|
191
|
-
const isCreate = result.action ===
|
|
191
|
+
const isCreate = result.action === "create" || result.action === "not_found";
|
|
192
192
|
if (isCreate) {
|
|
193
193
|
// New document - write ID back to file
|
|
194
194
|
doc.id = pushResult;
|
|
195
195
|
file.metadata.pulledAt = new Date().toISOString();
|
|
196
196
|
file.metadata.version = 1;
|
|
197
197
|
const updatedContent = buildRequirementsFile(file.metadata, file.markdownContent);
|
|
198
|
-
fs.writeFileSync(file.filePath, updatedContent,
|
|
198
|
+
fs.writeFileSync(file.filePath, updatedContent, "utf-8");
|
|
199
199
|
created++;
|
|
200
200
|
}
|
|
201
201
|
else {
|
|
@@ -203,7 +203,7 @@ export async function executePush(dryRunResult, credentials) {
|
|
|
203
203
|
file.metadata.pulledAt = new Date().toISOString();
|
|
204
204
|
file.metadata.version = (file.metadata.version || 0) + 1;
|
|
205
205
|
const updatedContent = buildRequirementsFile(file.metadata, file.markdownContent);
|
|
206
|
-
fs.writeFileSync(file.filePath, updatedContent,
|
|
206
|
+
fs.writeFileSync(file.filePath, updatedContent, "utf-8");
|
|
207
207
|
updated++;
|
|
208
208
|
}
|
|
209
209
|
}
|
package/dist/push/index.d.ts
CHANGED
|
@@ -4,5 +4,5 @@
|
|
|
4
4
|
* Shared push logic for syncing local requirements files to the cloud.
|
|
5
5
|
* Used by both CLI push command and MCP push_requirements tool.
|
|
6
6
|
*/
|
|
7
|
-
export { type
|
|
7
|
+
export { type CloudDocumentMetadata, type ConflictInfo, type DryRunResult, type DryRunResultItem, dryRunPush, executePush, extractMarkdownContent, type FileWithDryRun, type ParsedFile, type PushCredentials, type PushResult, parseFilesForPush, } from "./core.js";
|
|
8
8
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/push/index.js
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Shared push logic for syncing local requirements files to the cloud.
|
|
5
5
|
* Used by both CLI push command and MCP push_requirements tool.
|
|
6
6
|
*/
|
|
7
|
-
export {
|
|
7
|
+
export { dryRunPush, executePush,
|
|
8
8
|
// Functions
|
|
9
|
-
extractMarkdownContent, parseFilesForPush,
|
|
9
|
+
extractMarkdownContent, parseFilesForPush, } from "./core.js";
|
|
10
10
|
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cloud-AI library — hosted endpoints for style review, test review, and
|
|
3
|
+
* project context retrieval. Shared between the MCP handlers and the CLI
|
|
4
|
+
* verbs that wrap them.
|
|
5
|
+
*
|
|
6
|
+
* Each function does one cloud call and returns the unwrapped result (or
|
|
7
|
+
* throws on failure). Surface-specific concerns (error formatting, exit
|
|
8
|
+
* codes, MCP tool responses) live in the callers.
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
11
|
+
* Default base URL for the hosted AI endpoints (`/api/style-check`,
|
|
12
|
+
* `/api/review-test`). Overridable via the `apiBaseUrl` argument or
|
|
13
|
+
* the `DOTREQUIREMENTS_API_URL` environment variable in callers.
|
|
14
|
+
*/
|
|
15
|
+
export declare const DEFAULT_API_BASE_URL = "https://app.dotrequirements.io";
|
|
16
|
+
export interface StyleCheckParams {
|
|
17
|
+
apiBaseUrl: string;
|
|
18
|
+
projectId: string;
|
|
19
|
+
projectSecret: string;
|
|
20
|
+
fileContents: string;
|
|
21
|
+
fileType: "requirements" | "test";
|
|
22
|
+
model?: string;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* POST to `/api/style-check`. Returns the feedback text on success;
|
|
26
|
+
* throws an Error with the underlying failure reason on a non-OK
|
|
27
|
+
* response or a network error.
|
|
28
|
+
*/
|
|
29
|
+
export declare function fetchStyleCheckFeedback(params: StyleCheckParams): Promise<string>;
|
|
30
|
+
export interface ReviewTestParams {
|
|
31
|
+
apiBaseUrl: string;
|
|
32
|
+
projectId: string;
|
|
33
|
+
projectSecret: string;
|
|
34
|
+
testFileContents: string;
|
|
35
|
+
requirements: Array<{
|
|
36
|
+
id: string;
|
|
37
|
+
content: string;
|
|
38
|
+
testedIds: string[];
|
|
39
|
+
}>;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* POST to `/api/review-test`. Returns the feedback text on success;
|
|
43
|
+
* throws an Error with the underlying failure reason on a non-OK
|
|
44
|
+
* response or a network error.
|
|
45
|
+
*/
|
|
46
|
+
export declare function fetchReviewTestFeedback(params: ReviewTestParams): Promise<string>;
|
|
47
|
+
export interface ProjectContext {
|
|
48
|
+
projectContext: string | null;
|
|
49
|
+
requirementsStyleContext: string | null;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Query Convex for project-level AI context (project description and
|
|
53
|
+
* requirements style guidance). Returns null on any failure — the caller
|
|
54
|
+
* is expected to degrade gracefully if context is unavailable.
|
|
55
|
+
*/
|
|
56
|
+
export declare function getProjectContext(projectId: string, projectSecret: string, convexUrl: string): Promise<ProjectContext | null>;
|
|
57
|
+
//# sourceMappingURL=cloud-ai.d.ts.map
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cloud-AI library — hosted endpoints for style review, test review, and
|
|
3
|
+
* project context retrieval. Shared between the MCP handlers and the CLI
|
|
4
|
+
* verbs that wrap them.
|
|
5
|
+
*
|
|
6
|
+
* Each function does one cloud call and returns the unwrapped result (or
|
|
7
|
+
* throws on failure). Surface-specific concerns (error formatting, exit
|
|
8
|
+
* codes, MCP tool responses) live in the callers.
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
11
|
+
* Default base URL for the hosted AI endpoints (`/api/style-check`,
|
|
12
|
+
* `/api/review-test`). Overridable via the `apiBaseUrl` argument or
|
|
13
|
+
* the `DOTREQUIREMENTS_API_URL` environment variable in callers.
|
|
14
|
+
*/
|
|
15
|
+
export const DEFAULT_API_BASE_URL = "https://app.dotrequirements.io";
|
|
16
|
+
/**
|
|
17
|
+
* POST to `/api/style-check`. Returns the feedback text on success;
|
|
18
|
+
* throws an Error with the underlying failure reason on a non-OK
|
|
19
|
+
* response or a network error.
|
|
20
|
+
*/
|
|
21
|
+
export async function fetchStyleCheckFeedback(params) {
|
|
22
|
+
const response = await fetch(`${params.apiBaseUrl}/api/style-check`, {
|
|
23
|
+
method: "POST",
|
|
24
|
+
headers: { "Content-Type": "application/json" },
|
|
25
|
+
body: JSON.stringify({
|
|
26
|
+
projectId: params.projectId,
|
|
27
|
+
projectSecret: params.projectSecret,
|
|
28
|
+
fileContents: params.fileContents,
|
|
29
|
+
fileType: params.fileType,
|
|
30
|
+
model: params.model,
|
|
31
|
+
}),
|
|
32
|
+
});
|
|
33
|
+
if (!response.ok) {
|
|
34
|
+
const errorData = (await response.json().catch(() => ({})));
|
|
35
|
+
throw new Error(errorData.error || response.statusText);
|
|
36
|
+
}
|
|
37
|
+
const data = (await response.json());
|
|
38
|
+
return data.feedback;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* POST to `/api/review-test`. Returns the feedback text on success;
|
|
42
|
+
* throws an Error with the underlying failure reason on a non-OK
|
|
43
|
+
* response or a network error.
|
|
44
|
+
*/
|
|
45
|
+
export async function fetchReviewTestFeedback(params) {
|
|
46
|
+
const response = await fetch(`${params.apiBaseUrl}/api/review-test`, {
|
|
47
|
+
method: "POST",
|
|
48
|
+
headers: { "Content-Type": "application/json" },
|
|
49
|
+
body: JSON.stringify({
|
|
50
|
+
projectId: params.projectId,
|
|
51
|
+
projectSecret: params.projectSecret,
|
|
52
|
+
testFileContents: params.testFileContents,
|
|
53
|
+
requirements: params.requirements,
|
|
54
|
+
}),
|
|
55
|
+
});
|
|
56
|
+
if (!response.ok) {
|
|
57
|
+
const errorData = (await response.json().catch(() => ({})));
|
|
58
|
+
throw new Error(errorData.error || response.statusText);
|
|
59
|
+
}
|
|
60
|
+
const data = (await response.json());
|
|
61
|
+
return data.feedback;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Query Convex for project-level AI context (project description and
|
|
65
|
+
* requirements style guidance). Returns null on any failure — the caller
|
|
66
|
+
* is expected to degrade gracefully if context is unavailable.
|
|
67
|
+
*/
|
|
68
|
+
export async function getProjectContext(projectId, projectSecret, convexUrl) {
|
|
69
|
+
try {
|
|
70
|
+
const response = await fetch(`${convexUrl}/api/query`, {
|
|
71
|
+
method: "POST",
|
|
72
|
+
headers: { "Content-Type": "application/json" },
|
|
73
|
+
body: JSON.stringify({
|
|
74
|
+
path: "projects/queries:get",
|
|
75
|
+
args: {
|
|
76
|
+
projectAuth: {
|
|
77
|
+
projectSlug: projectId,
|
|
78
|
+
projectSecret,
|
|
79
|
+
},
|
|
80
|
+
target: {
|
|
81
|
+
type: "project",
|
|
82
|
+
slug: projectId,
|
|
83
|
+
},
|
|
84
|
+
},
|
|
85
|
+
format: "json",
|
|
86
|
+
}),
|
|
87
|
+
});
|
|
88
|
+
if (!response.ok) {
|
|
89
|
+
return null;
|
|
90
|
+
}
|
|
91
|
+
const json = (await response.json());
|
|
92
|
+
if (json.status === "error" || !json.value) {
|
|
93
|
+
return null;
|
|
94
|
+
}
|
|
95
|
+
return {
|
|
96
|
+
projectContext: json.value.projectContext ?? null,
|
|
97
|
+
requirementsStyleContext: json.value.requirementsStyleContext ?? null,
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
catch {
|
|
101
|
+
return null;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
//# sourceMappingURL=cloud-ai.js.map
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cloud-coverage library — hosted endpoints for querying persisted test
|
|
3
|
+
* coverage from dot•requirements cloud. Shared between the MCP `report`
|
|
4
|
+
* tool and the CLI `report` verb's `--source cloud` mode.
|
|
5
|
+
*/
|
|
6
|
+
export interface RequirementCoverageRecord {
|
|
7
|
+
requirementKey: string;
|
|
8
|
+
lastTestedAt: number | null;
|
|
9
|
+
branch: string | null;
|
|
10
|
+
testFile: string | null;
|
|
11
|
+
testLine: number | null;
|
|
12
|
+
allBranches: Array<{
|
|
13
|
+
branch: string;
|
|
14
|
+
lastTestedAt: number;
|
|
15
|
+
testFile?: string;
|
|
16
|
+
testLine?: number;
|
|
17
|
+
}>;
|
|
18
|
+
}
|
|
19
|
+
export interface ProjectCoverageRecord {
|
|
20
|
+
tested: Array<{
|
|
21
|
+
requirementKey: string;
|
|
22
|
+
lastTestedAt: number;
|
|
23
|
+
branch: string;
|
|
24
|
+
testFile?: string;
|
|
25
|
+
testLine?: number;
|
|
26
|
+
}>;
|
|
27
|
+
untested: string[];
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Query cloud for coverage on a single requirement.
|
|
31
|
+
*/
|
|
32
|
+
export declare function getRequirementCoverage(requirementKey: string, projectId: string, projectSecret: string, convexUrl: string): Promise<RequirementCoverageRecord>;
|
|
33
|
+
/**
|
|
34
|
+
* Query cloud for project-wide coverage summary, optionally filtered by
|
|
35
|
+
* branch or recorded-since timestamp.
|
|
36
|
+
*/
|
|
37
|
+
export declare function getProjectCoverage(projectId: string, projectSecret: string, convexUrl: string, options?: {
|
|
38
|
+
branch?: string;
|
|
39
|
+
sinceTimestamp?: number;
|
|
40
|
+
}): Promise<ProjectCoverageRecord>;
|
|
41
|
+
//# sourceMappingURL=cloud-coverage.d.ts.map
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cloud-coverage library — hosted endpoints for querying persisted test
|
|
3
|
+
* coverage from dot•requirements cloud. Shared between the MCP `report`
|
|
4
|
+
* tool and the CLI `report` verb's `--source cloud` mode.
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Query cloud for coverage on a single requirement.
|
|
8
|
+
*/
|
|
9
|
+
export async function getRequirementCoverage(requirementKey, projectId, projectSecret, convexUrl) {
|
|
10
|
+
const response = await fetch(`${convexUrl}/api/query`, {
|
|
11
|
+
method: "POST",
|
|
12
|
+
headers: { "Content-Type": "application/json" },
|
|
13
|
+
body: JSON.stringify({
|
|
14
|
+
path: "testCoverage/queries:getRequirementCoverage",
|
|
15
|
+
args: {
|
|
16
|
+
projectAuth: { projectSlug: projectId, projectSecret },
|
|
17
|
+
target: { type: "project", slug: projectId },
|
|
18
|
+
requirementKey,
|
|
19
|
+
},
|
|
20
|
+
format: "json",
|
|
21
|
+
}),
|
|
22
|
+
});
|
|
23
|
+
if (!response.ok) {
|
|
24
|
+
throw new Error(`Failed to query coverage: ${response.statusText}`);
|
|
25
|
+
}
|
|
26
|
+
const json = (await response.json());
|
|
27
|
+
if (json.status === "error") {
|
|
28
|
+
throw new Error(`Convex query failed: ${json.errorMessage}`);
|
|
29
|
+
}
|
|
30
|
+
return json.value;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Query cloud for project-wide coverage summary, optionally filtered by
|
|
34
|
+
* branch or recorded-since timestamp.
|
|
35
|
+
*/
|
|
36
|
+
export async function getProjectCoverage(projectId, projectSecret, convexUrl, options) {
|
|
37
|
+
const response = await fetch(`${convexUrl}/api/query`, {
|
|
38
|
+
method: "POST",
|
|
39
|
+
headers: { "Content-Type": "application/json" },
|
|
40
|
+
body: JSON.stringify({
|
|
41
|
+
path: "testCoverage/queries:getProjectCoverage",
|
|
42
|
+
args: {
|
|
43
|
+
projectAuth: { projectSlug: projectId, projectSecret },
|
|
44
|
+
target: { type: "project", slug: projectId },
|
|
45
|
+
branch: options?.branch,
|
|
46
|
+
sinceTimestamp: options?.sinceTimestamp,
|
|
47
|
+
},
|
|
48
|
+
format: "json",
|
|
49
|
+
}),
|
|
50
|
+
});
|
|
51
|
+
if (!response.ok) {
|
|
52
|
+
throw new Error(`Failed to query coverage: ${response.statusText}`);
|
|
53
|
+
}
|
|
54
|
+
const json = (await response.json());
|
|
55
|
+
if (json.status === "error") {
|
|
56
|
+
throw new Error(`Convex query failed: ${json.errorMessage}`);
|
|
57
|
+
}
|
|
58
|
+
return json.value;
|
|
59
|
+
}
|
|
60
|
+
//# sourceMappingURL=cloud-coverage.js.map
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Local-coverage library — reads the test-harness cache produced by
|
|
3
|
+
* `dotreq harness prepare` + your test run, and turns it into a structured
|
|
4
|
+
* coverage report. Shared between the CLI `report` verb's local mode and
|
|
5
|
+
* the MCP `report` tool's `source: "local"` mode.
|
|
6
|
+
*
|
|
7
|
+
* Cloud-side coverage queries live next door in cloud-coverage.ts.
|
|
8
|
+
*/
|
|
9
|
+
export interface CoverageEntry {
|
|
10
|
+
key: string;
|
|
11
|
+
label: string | null;
|
|
12
|
+
content: string;
|
|
13
|
+
tested: boolean;
|
|
14
|
+
locations: string[];
|
|
15
|
+
}
|
|
16
|
+
export interface LocalReportSummary {
|
|
17
|
+
total: number;
|
|
18
|
+
tested: number;
|
|
19
|
+
untested: number;
|
|
20
|
+
coveragePercent: number;
|
|
21
|
+
}
|
|
22
|
+
export interface LocalReportResult {
|
|
23
|
+
entries: CoverageEntry[];
|
|
24
|
+
summary: LocalReportSummary;
|
|
25
|
+
/** Soft warnings the caller may want to surface (stale cache, empty
|
|
26
|
+
* tracking file, etc.). Hard errors throw instead. */
|
|
27
|
+
warnings: string[];
|
|
28
|
+
}
|
|
29
|
+
export declare class LocalReportCacheMissingError extends Error {
|
|
30
|
+
constructor(message: string);
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Build a coverage report from the project's local test-harness cache.
|
|
34
|
+
*
|
|
35
|
+
* Throws {@link LocalReportCacheMissingError} when the cache is missing
|
|
36
|
+
* entirely (the caller hasn't run `dotreq harness prepare` yet). Soft
|
|
37
|
+
* issues — stale cache, missing or empty tracking file — are returned
|
|
38
|
+
* as `warnings` so the caller can decide where they belong (stderr for
|
|
39
|
+
* CLI, response body for MCP).
|
|
40
|
+
*/
|
|
41
|
+
export declare function buildLocalReport(opts: {
|
|
42
|
+
projectRoot: string;
|
|
43
|
+
requirementFilter?: string;
|
|
44
|
+
}): LocalReportResult;
|
|
45
|
+
//# sourceMappingURL=coverage.d.ts.map
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Local-coverage library — reads the test-harness cache produced by
|
|
3
|
+
* `dotreq harness prepare` + your test run, and turns it into a structured
|
|
4
|
+
* coverage report. Shared between the CLI `report` verb's local mode and
|
|
5
|
+
* the MCP `report` tool's `source: "local"` mode.
|
|
6
|
+
*
|
|
7
|
+
* Cloud-side coverage queries live next door in cloud-coverage.ts.
|
|
8
|
+
*/
|
|
9
|
+
import * as fs from "node:fs";
|
|
10
|
+
import * as path from "node:path";
|
|
11
|
+
import { findRequirementsDir, isCacheStale, readTrackingEntries, } from "../harness/cache.js";
|
|
12
|
+
export class LocalReportCacheMissingError extends Error {
|
|
13
|
+
constructor(message) {
|
|
14
|
+
super(message);
|
|
15
|
+
this.name = "LocalReportCacheMissingError";
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Build a coverage report from the project's local test-harness cache.
|
|
20
|
+
*
|
|
21
|
+
* Throws {@link LocalReportCacheMissingError} when the cache is missing
|
|
22
|
+
* entirely (the caller hasn't run `dotreq harness prepare` yet). Soft
|
|
23
|
+
* issues — stale cache, missing or empty tracking file — are returned
|
|
24
|
+
* as `warnings` so the caller can decide where they belong (stderr for
|
|
25
|
+
* CLI, response body for MCP).
|
|
26
|
+
*/
|
|
27
|
+
export function buildLocalReport(opts) {
|
|
28
|
+
const requirementsDir = findRequirementsDir(opts.projectRoot);
|
|
29
|
+
if (!requirementsDir) {
|
|
30
|
+
throw new LocalReportCacheMissingError('No .requirements/ directory found. Run "dotrequirements init" to initialize your project.');
|
|
31
|
+
}
|
|
32
|
+
const cacheDir = path.join(requirementsDir, ".cache");
|
|
33
|
+
const lookupPath = path.join(cacheDir, "lookup.json");
|
|
34
|
+
if (!fs.existsSync(lookupPath)) {
|
|
35
|
+
throw new LocalReportCacheMissingError('No lookup cache found. Run "dotrequirements harness prepare" first to build the cache.');
|
|
36
|
+
}
|
|
37
|
+
const warnings = [];
|
|
38
|
+
const lookup = JSON.parse(fs.readFileSync(lookupPath, "utf-8"));
|
|
39
|
+
try {
|
|
40
|
+
const cacheStat = fs.statSync(lookupPath);
|
|
41
|
+
if (isCacheStale(requirementsDir, cacheStat.mtimeMs)) {
|
|
42
|
+
warnings.push('Cache may be stale — requirements have changed since last prepare. Run "dotrequirements harness prepare" to rebuild.');
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
catch {
|
|
46
|
+
// ignore stat errors
|
|
47
|
+
}
|
|
48
|
+
const trackingPath = path.join(cacheDir, "tracking.jsonl");
|
|
49
|
+
const trackingExists = fs.existsSync(trackingPath);
|
|
50
|
+
const entries = readTrackingEntries(requirementsDir);
|
|
51
|
+
if (!trackingExists) {
|
|
52
|
+
warnings.push('No tracking data found. Run your tests first, or run "dotrequirements harness prepare" to start a new tracking session.');
|
|
53
|
+
}
|
|
54
|
+
else if (entries.length === 0) {
|
|
55
|
+
warnings.push("Tracking file is empty — no requirements were tracked during tests.");
|
|
56
|
+
}
|
|
57
|
+
const coverageEntries = buildCoverageEntries(lookup, entries, opts.requirementFilter);
|
|
58
|
+
const tested = coverageEntries.filter((c) => c.tested).length;
|
|
59
|
+
const total = coverageEntries.length;
|
|
60
|
+
const coveragePercent = total > 0 ? parseFloat(((tested / total) * 100).toFixed(1)) : 0;
|
|
61
|
+
return {
|
|
62
|
+
entries: coverageEntries,
|
|
63
|
+
summary: {
|
|
64
|
+
total,
|
|
65
|
+
tested,
|
|
66
|
+
untested: total - tested,
|
|
67
|
+
coveragePercent,
|
|
68
|
+
},
|
|
69
|
+
warnings,
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
function buildCoverageEntries(lookup, entries, filterKey) {
|
|
73
|
+
const locationsByKey = new Map();
|
|
74
|
+
for (const entry of entries) {
|
|
75
|
+
if (!locationsByKey.has(entry.requirementKey)) {
|
|
76
|
+
locationsByKey.set(entry.requirementKey, new Set());
|
|
77
|
+
}
|
|
78
|
+
locationsByKey.get(entry.requirementKey).add(entry.callerLocation);
|
|
79
|
+
}
|
|
80
|
+
const results = [];
|
|
81
|
+
for (const [key, req] of Object.entries(lookup.requirements)) {
|
|
82
|
+
if (req.isAlias)
|
|
83
|
+
continue;
|
|
84
|
+
if (filterKey && key !== filterKey && !key.startsWith(`${filterKey}.`)) {
|
|
85
|
+
continue;
|
|
86
|
+
}
|
|
87
|
+
const locations = new Set();
|
|
88
|
+
const keyLocations = locationsByKey.get(key);
|
|
89
|
+
if (keyLocations) {
|
|
90
|
+
keyLocations.forEach((l) => {
|
|
91
|
+
locations.add(l);
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
for (const [aliasKey, aliasReq] of Object.entries(lookup.requirements)) {
|
|
95
|
+
if (aliasReq.isAlias && aliasReq.id === req.id) {
|
|
96
|
+
const aliasLocations = locationsByKey.get(aliasKey);
|
|
97
|
+
if (aliasLocations) {
|
|
98
|
+
aliasLocations.forEach((l) => {
|
|
99
|
+
locations.add(l);
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
results.push({
|
|
105
|
+
key,
|
|
106
|
+
label: req.label || null,
|
|
107
|
+
content: req.content,
|
|
108
|
+
tested: locations.size > 0,
|
|
109
|
+
locations: Array.from(locations),
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
return results;
|
|
113
|
+
}
|
|
114
|
+
//# sourceMappingURL=coverage.js.map
|
|
@@ -1,4 +1,13 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* A `requirement(...)` call site found in source code.
|
|
3
|
+
*/
|
|
4
|
+
export interface TestReference {
|
|
5
|
+
file: string;
|
|
6
|
+
line: number;
|
|
7
|
+
column: number;
|
|
8
|
+
requirementId: string;
|
|
9
|
+
context: string;
|
|
10
|
+
}
|
|
2
11
|
/**
|
|
3
12
|
* Find all test files that reference a specific requirement ID
|
|
4
13
|
*
|