@popoverai/dotrequirements 0.23.0 → 0.24.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/README.md +167 -20
- 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-apply.d.ts +12 -0
- package/dist/codebase-to-spec/prompts/planner-apply.js +32 -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/acceptance-test.js +212 -0
- package/dist/commands/ai-setup.d.ts +5 -0
- package/dist/commands/ai-setup.js +441 -0
- package/dist/commands/browsertest.js +34 -27
- 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-setup.js +159 -149
- 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/test.js +53 -59
- 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/grep.d.ts +1 -1
- package/dist/mcp/grep.js +87 -42
- package/dist/mcp/handlers/authoring.d.ts +1 -1
- package/dist/mcp/handlers/authoring.js +30 -234
- package/dist/mcp/handlers/coverage.d.ts +1 -1
- package/dist/mcp/handlers/coverage.js +13 -15
- 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/mcp/requirements.d.ts +2 -2
- package/dist/mcp/requirements.js +30 -30
- package/dist/mcp/testCodeExtractor.js +24 -26
- package/dist/mcp/types.d.ts +1 -1
- 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/requirements/grep.d.ts +33 -0
- package/dist/requirements/grep.js +306 -0
- package/dist/requirements/index.d.ts +73 -0
- package/dist/requirements/index.js +174 -0
- package/dist/requirements/style-guide.d.ts +67 -0
- package/dist/requirements/style-guide.js +299 -0
- package/dist/requirements/testCodeExtractor.d.ts +22 -0
- package/dist/requirements/testCodeExtractor.js +150 -0
- 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 +2 -1
package/dist/commands/test.js
CHANGED
|
@@ -1,67 +1,61 @@
|
|
|
1
|
-
import * as fs from
|
|
2
|
-
import * as path from
|
|
3
|
-
import { parseRequirementsFromFile } from
|
|
1
|
+
import * as fs from "node:fs";
|
|
2
|
+
import * as path from "node:path";
|
|
3
|
+
import { parseRequirementsFromFile, } from "../schema/index.js";
|
|
4
4
|
export async function testCommand(options) {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
count += countRequirementsInTree(req);
|
|
41
|
-
}
|
|
42
|
-
totalRequirements += count;
|
|
43
|
-
console.log(` ✓ Valid structure (${count} requirement(s))`);
|
|
44
|
-
console.log(` ✓ Version: ${metadata.version}`);
|
|
45
|
-
console.log(` ✓ Last sync: ${metadata.pulledAt}`);
|
|
46
|
-
passCount++;
|
|
47
|
-
}
|
|
48
|
-
catch (error) {
|
|
49
|
-
console.error(` ✗ Validation failed:`, error);
|
|
50
|
-
failCount++;
|
|
5
|
+
console.log("Parsing and validating requirements...");
|
|
6
|
+
const requirementsDir = path.join(process.cwd(), ".requirements");
|
|
7
|
+
if (!fs.existsSync(requirementsDir)) {
|
|
8
|
+
console.error("Error: .requirements/ directory not found.");
|
|
9
|
+
console.log('Run "dotrequirements pull" first to sync requirements.');
|
|
10
|
+
process.exit(1);
|
|
11
|
+
}
|
|
12
|
+
// Get files to test
|
|
13
|
+
let files;
|
|
14
|
+
if (options.file) {
|
|
15
|
+
files = [options.file];
|
|
16
|
+
}
|
|
17
|
+
else {
|
|
18
|
+
files = fs
|
|
19
|
+
.readdirSync(requirementsDir)
|
|
20
|
+
.filter((f) => f.endsWith(".requirements.md"))
|
|
21
|
+
.map((f) => path.join(requirementsDir, f));
|
|
22
|
+
}
|
|
23
|
+
if (files.length === 0) {
|
|
24
|
+
console.log("No Markdown requirements files found to test.");
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
let totalRequirements = 0;
|
|
28
|
+
let passCount = 0;
|
|
29
|
+
let failCount = 0;
|
|
30
|
+
for (const filePath of files) {
|
|
31
|
+
const fileName = path.basename(filePath);
|
|
32
|
+
console.log(`\nTesting: ${fileName}`);
|
|
33
|
+
try {
|
|
34
|
+
// Parse and validate using shared schema module
|
|
35
|
+
const { metadata, requirements } = parseRequirementsFromFile(filePath);
|
|
36
|
+
// Count total requirements (root + all descendants)
|
|
37
|
+
let count = 0;
|
|
38
|
+
for (const req of requirements) {
|
|
39
|
+
count += countRequirementsInTree(req);
|
|
51
40
|
}
|
|
41
|
+
totalRequirements += count;
|
|
42
|
+
console.log(` ✓ Valid structure (${count} requirement(s))`);
|
|
43
|
+
console.log(` ✓ Version: ${metadata.version}`);
|
|
44
|
+
console.log(` ✓ Last sync: ${metadata.pulledAt}`);
|
|
45
|
+
passCount++;
|
|
52
46
|
}
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
console.log(`Failed: ${failCount}`);
|
|
57
|
-
console.log(`Total requirements: ${totalRequirements}`);
|
|
58
|
-
if (failCount > 0) {
|
|
59
|
-
process.exit(1);
|
|
47
|
+
catch (error) {
|
|
48
|
+
console.error(` ✗ Validation failed:`, error);
|
|
49
|
+
failCount++;
|
|
60
50
|
}
|
|
61
51
|
}
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
52
|
+
console.log(`\n${"=".repeat(50)}`);
|
|
53
|
+
console.log(`Total files: ${files.length}`);
|
|
54
|
+
console.log(`Passed: ${passCount}`);
|
|
55
|
+
console.log(`Failed: ${failCount}`);
|
|
56
|
+
console.log(`Total requirements: ${totalRequirements}`);
|
|
57
|
+
if (failCount > 0) {
|
|
58
|
+
process.exit(1);
|
|
65
59
|
}
|
|
66
60
|
}
|
|
67
61
|
/**
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { existsSync } from "node:fs";
|
|
2
|
+
import { relative, resolve } from "node:path";
|
|
3
|
+
import { findAllTestReferences } from "../requirements/grep.js";
|
|
4
|
+
import { loadAllRequirements } from "../requirements/index.js";
|
|
5
|
+
export async function testsForCommand(requirementsFile) {
|
|
6
|
+
const workspaceRoot = process.cwd();
|
|
7
|
+
const fullPath = resolve(workspaceRoot, requirementsFile);
|
|
8
|
+
// CLI-FIND-MAP-2.3: missing file or wrong extension → error + non-zero exit
|
|
9
|
+
if (!existsSync(fullPath)) {
|
|
10
|
+
throw new Error(`Requirements file not found: ${requirementsFile}`);
|
|
11
|
+
}
|
|
12
|
+
if (!requirementsFile.endsWith(".requirements.md")) {
|
|
13
|
+
throw new Error(`File must be a requirements file: *.requirements.md`);
|
|
14
|
+
}
|
|
15
|
+
const { flattened } = await loadAllRequirements(workspaceRoot);
|
|
16
|
+
const fileRequirements = flattened.filter((req) => resolve(workspaceRoot, req.sourceFile) === fullPath);
|
|
17
|
+
if (fileRequirements.length === 0) {
|
|
18
|
+
console.log(`No requirements found in "${requirementsFile}".`);
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
const rootIds = new Set(fileRequirements.map((req) => req.rootId));
|
|
22
|
+
const allTestRefs = await findAllTestReferences(workspaceRoot);
|
|
23
|
+
// Build coverage map: requirement ID → test refs
|
|
24
|
+
const coverageMap = new Map();
|
|
25
|
+
for (const ref of allTestRefs) {
|
|
26
|
+
if (!coverageMap.has(ref.requirementId)) {
|
|
27
|
+
coverageMap.set(ref.requirementId, []);
|
|
28
|
+
}
|
|
29
|
+
coverageMap.get(ref.requirementId).push(ref);
|
|
30
|
+
}
|
|
31
|
+
// CLI-FIND-MAP-2.0: group by coverage status
|
|
32
|
+
const covered = [];
|
|
33
|
+
const notCovered = [];
|
|
34
|
+
for (const rootId of rootIds) {
|
|
35
|
+
const reqAndChildren = fileRequirements.filter((r) => r.rootId === rootId);
|
|
36
|
+
const allIds = reqAndChildren.map((r) => r.id);
|
|
37
|
+
const testsForThisReq = [];
|
|
38
|
+
for (const id of allIds) {
|
|
39
|
+
const refs = coverageMap.get(id);
|
|
40
|
+
if (refs) {
|
|
41
|
+
testsForThisReq.push(...refs);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
if (testsForThisReq.length > 0) {
|
|
45
|
+
covered.push({ id: rootId, tests: testsForThisReq });
|
|
46
|
+
}
|
|
47
|
+
else {
|
|
48
|
+
notCovered.push(rootId);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
console.log(`Test coverage for "${requirementsFile}":\n`);
|
|
52
|
+
if (covered.length > 0) {
|
|
53
|
+
console.log(`Covered (${covered.length}):`);
|
|
54
|
+
// CLI-FIND-MAP-2.1: test file path + line numbers for each covered req
|
|
55
|
+
for (const { id, tests } of covered) {
|
|
56
|
+
const testsByFile = new Map();
|
|
57
|
+
for (const test of tests) {
|
|
58
|
+
if (!testsByFile.has(test.file)) {
|
|
59
|
+
testsByFile.set(test.file, []);
|
|
60
|
+
}
|
|
61
|
+
testsByFile.get(test.file).push(test.line);
|
|
62
|
+
}
|
|
63
|
+
console.log(` ${id}: ${tests.length} test${tests.length === 1 ? "" : "s"}`);
|
|
64
|
+
for (const [file, lines] of testsByFile) {
|
|
65
|
+
const relPath = relative(workspaceRoot, file);
|
|
66
|
+
const lineList = lines.sort((a, b) => a - b).join(", ");
|
|
67
|
+
console.log(` ${relPath} (lines ${lineList})`);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
console.log();
|
|
71
|
+
}
|
|
72
|
+
// CLI-FIND-MAP-2.2: uncovered group
|
|
73
|
+
if (notCovered.length > 0) {
|
|
74
|
+
console.log(`Not Covered (${notCovered.length}):`);
|
|
75
|
+
for (const id of notCovered) {
|
|
76
|
+
console.log(` ${id}: No tests found`);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
//# sourceMappingURL=tests-for.js.map
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import * as fs from "node:fs";
|
|
2
|
+
import * as path from "node:path";
|
|
3
|
+
import { parseRequirementsFromFile, } from "../schema/index.js";
|
|
4
|
+
export async function validateCommand(options) {
|
|
5
|
+
console.log("Parsing and validating requirements...");
|
|
6
|
+
const requirementsDir = path.join(process.cwd(), ".requirements");
|
|
7
|
+
if (!fs.existsSync(requirementsDir)) {
|
|
8
|
+
console.error("Error: .requirements/ directory not found.");
|
|
9
|
+
console.log('Run "dotrequirements pull" first to sync requirements.');
|
|
10
|
+
process.exit(1);
|
|
11
|
+
}
|
|
12
|
+
// Get files to test
|
|
13
|
+
let files;
|
|
14
|
+
if (options.file) {
|
|
15
|
+
files = [options.file];
|
|
16
|
+
}
|
|
17
|
+
else {
|
|
18
|
+
files = fs
|
|
19
|
+
.readdirSync(requirementsDir)
|
|
20
|
+
.filter((f) => f.endsWith(".requirements.md"))
|
|
21
|
+
.map((f) => path.join(requirementsDir, f));
|
|
22
|
+
}
|
|
23
|
+
if (files.length === 0) {
|
|
24
|
+
console.log("No Markdown requirements files found to test.");
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
let totalRequirements = 0;
|
|
28
|
+
let passCount = 0;
|
|
29
|
+
let failCount = 0;
|
|
30
|
+
for (const filePath of files) {
|
|
31
|
+
const fileName = path.basename(filePath);
|
|
32
|
+
console.log(`\nTesting: ${fileName}`);
|
|
33
|
+
try {
|
|
34
|
+
// Parse and validate using shared schema module
|
|
35
|
+
const { metadata, requirements } = parseRequirementsFromFile(filePath);
|
|
36
|
+
// Count total requirements (root + all descendants)
|
|
37
|
+
let count = 0;
|
|
38
|
+
for (const req of requirements) {
|
|
39
|
+
count += countRequirementsInTree(req);
|
|
40
|
+
}
|
|
41
|
+
totalRequirements += count;
|
|
42
|
+
console.log(` ✓ Valid structure (${count} requirement(s))`);
|
|
43
|
+
console.log(` ✓ Version: ${metadata.version}`);
|
|
44
|
+
console.log(` ✓ Last sync: ${metadata.pulledAt}`);
|
|
45
|
+
passCount++;
|
|
46
|
+
}
|
|
47
|
+
catch (error) {
|
|
48
|
+
console.error(` ✗ Validation failed:`, error);
|
|
49
|
+
failCount++;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
console.log(`\n${"=".repeat(50)}`);
|
|
53
|
+
console.log(`Total files: ${files.length}`);
|
|
54
|
+
console.log(`Passed: ${passCount}`);
|
|
55
|
+
console.log(`Failed: ${failCount}`);
|
|
56
|
+
console.log(`Total requirements: ${totalRequirements}`);
|
|
57
|
+
if (failCount > 0) {
|
|
58
|
+
process.exit(1);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Recursively count requirements in a tree (1 for root + all descendants)
|
|
63
|
+
*/
|
|
64
|
+
function countRequirementsInTree(node) {
|
|
65
|
+
let count = 1; // Count this node
|
|
66
|
+
// Count all children
|
|
67
|
+
for (const child of node.children) {
|
|
68
|
+
count += countRequirementsInTree(child);
|
|
69
|
+
}
|
|
70
|
+
return count;
|
|
71
|
+
}
|
|
72
|
+
//# sourceMappingURL=validate.js.map
|
package/dist/config.js
CHANGED
package/dist/convex.d.ts
CHANGED
|
@@ -1,66 +1,78 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Convex API stub for CLI usage
|
|
3
|
-
*
|
|
2
|
+
* Convex API stub for CLI usage.
|
|
3
|
+
*
|
|
4
|
+
* The CLI doesn't import generated convex types (those live in the convex
|
|
5
|
+
* package and aren't shipped to npm consumers), so we hand-roll the `api`
|
|
6
|
+
* object that gets passed into `ConvexHttpClient.query/mutation/action`.
|
|
7
|
+
*
|
|
8
|
+
* `makeFunctionReference<"query" | "mutation" | "action">("path:fn")` is the
|
|
9
|
+
* official escape hatch for this exact case — it builds a `FunctionReference`
|
|
10
|
+
* with the right shape for the convex client to consume, without us having to
|
|
11
|
+
* cast through `any`.
|
|
12
|
+
*
|
|
13
|
+
* The args/return types default to `any` inside the convex library types
|
|
14
|
+
* (that's `FunctionReference`'s public surface), but at the call site we still
|
|
15
|
+
* get a properly typed reference object — no user-authored `any` here.
|
|
4
16
|
*/
|
|
5
17
|
export declare const api: {
|
|
6
18
|
documents: {
|
|
7
19
|
queries: {
|
|
8
|
-
exportForCli: any
|
|
9
|
-
exportProjectForCli: any
|
|
10
|
-
checkDocumentsExist: any
|
|
11
|
-
getDocumentsMetadata: any
|
|
20
|
+
exportForCli: import("convex/server").FunctionReference<"query", "public", any, any, string | undefined>;
|
|
21
|
+
exportProjectForCli: import("convex/server").FunctionReference<"query", "public", any, any, string | undefined>;
|
|
22
|
+
checkDocumentsExist: import("convex/server").FunctionReference<"query", "public", any, any, string | undefined>;
|
|
23
|
+
getDocumentsMetadata: import("convex/server").FunctionReference<"query", "public", any, any, string | undefined>;
|
|
12
24
|
};
|
|
13
25
|
mutations: {
|
|
14
|
-
create: any
|
|
15
|
-
update: any
|
|
26
|
+
create: import("convex/server").FunctionReference<"mutation", "public", any, any, string | undefined>;
|
|
27
|
+
update: import("convex/server").FunctionReference<"mutation", "public", any, any, string | undefined>;
|
|
16
28
|
};
|
|
17
29
|
saveWithRequirements: {
|
|
18
|
-
saveWithRequirements: any
|
|
30
|
+
saveWithRequirements: import("convex/server").FunctionReference<"mutation", "public", any, any, string | undefined>;
|
|
19
31
|
};
|
|
20
32
|
};
|
|
21
33
|
requirements: {
|
|
22
34
|
queries: {
|
|
23
|
-
listByProject: any
|
|
35
|
+
listByProject: import("convex/server").FunctionReference<"query", "public", any, any, string | undefined>;
|
|
24
36
|
};
|
|
25
37
|
mutations: {
|
|
26
|
-
bulkUpdate: any
|
|
38
|
+
bulkUpdate: import("convex/server").FunctionReference<"mutation", "public", any, any, string | undefined>;
|
|
27
39
|
};
|
|
28
40
|
};
|
|
29
41
|
projects: {
|
|
30
42
|
mutations: {
|
|
31
|
-
create: any
|
|
43
|
+
create: import("convex/server").FunctionReference<"mutation", "public", any, any, string | undefined>;
|
|
32
44
|
};
|
|
33
45
|
};
|
|
34
46
|
teams: {
|
|
35
47
|
queries: {
|
|
36
|
-
listForUserWithUsage: any
|
|
48
|
+
listForUserWithUsage: import("convex/server").FunctionReference<"query", "public", any, any, string | undefined>;
|
|
37
49
|
};
|
|
38
50
|
mutations: {
|
|
39
|
-
ensureDefaultTeam: any
|
|
51
|
+
ensureDefaultTeam: import("convex/server").FunctionReference<"mutation", "public", any, any, string | undefined>;
|
|
40
52
|
};
|
|
41
53
|
};
|
|
42
54
|
teamInvites: {
|
|
43
55
|
queries: {
|
|
44
|
-
getInviteInfo: any
|
|
56
|
+
getInviteInfo: import("convex/server").FunctionReference<"query", "public", any, any, string | undefined>;
|
|
45
57
|
};
|
|
46
58
|
};
|
|
47
59
|
polar: {
|
|
48
|
-
acceptTeamInvite: any
|
|
60
|
+
acceptTeamInvite: import("convex/server").FunctionReference<"action", "public", any, any, string | undefined>;
|
|
49
61
|
};
|
|
50
62
|
projectSecrets: {
|
|
51
63
|
queries: {
|
|
52
|
-
getOwnSecret: any
|
|
53
|
-
listOwnSecretsForTeam: any
|
|
64
|
+
getOwnSecret: import("convex/server").FunctionReference<"query", "public", any, any, string | undefined>;
|
|
65
|
+
listOwnSecretsForTeam: import("convex/server").FunctionReference<"query", "public", any, any, string | undefined>;
|
|
54
66
|
};
|
|
55
67
|
mutations: {
|
|
56
|
-
ensureOwnSecret: any
|
|
57
|
-
revokeOwnSecret: any
|
|
68
|
+
ensureOwnSecret: import("convex/server").FunctionReference<"mutation", "public", any, any, string | undefined>;
|
|
69
|
+
revokeOwnSecret: import("convex/server").FunctionReference<"mutation", "public", any, any, string | undefined>;
|
|
58
70
|
};
|
|
59
71
|
};
|
|
60
72
|
lib: {
|
|
61
73
|
authActions: {
|
|
62
|
-
exchangeAuthorizationCode: any
|
|
63
|
-
refreshAccessToken: any
|
|
74
|
+
exchangeAuthorizationCode: import("convex/server").FunctionReference<"action", "public", any, any, string | undefined>;
|
|
75
|
+
refreshAccessToken: import("convex/server").FunctionReference<"action", "public", any, any, string | undefined>;
|
|
64
76
|
};
|
|
65
77
|
};
|
|
66
78
|
};
|
package/dist/convex.js
CHANGED
|
@@ -1,68 +1,84 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Convex API stub for CLI usage
|
|
3
|
-
*
|
|
2
|
+
* Convex API stub for CLI usage.
|
|
3
|
+
*
|
|
4
|
+
* The CLI doesn't import generated convex types (those live in the convex
|
|
5
|
+
* package and aren't shipped to npm consumers), so we hand-roll the `api`
|
|
6
|
+
* object that gets passed into `ConvexHttpClient.query/mutation/action`.
|
|
7
|
+
*
|
|
8
|
+
* `makeFunctionReference<"query" | "mutation" | "action">("path:fn")` is the
|
|
9
|
+
* official escape hatch for this exact case — it builds a `FunctionReference`
|
|
10
|
+
* with the right shape for the convex client to consume, without us having to
|
|
11
|
+
* cast through `any`.
|
|
12
|
+
*
|
|
13
|
+
* The args/return types default to `any` inside the convex library types
|
|
14
|
+
* (that's `FunctionReference`'s public surface), but at the call site we still
|
|
15
|
+
* get a properly typed reference object — no user-authored `any` here.
|
|
4
16
|
*/
|
|
17
|
+
import { makeFunctionReference } from "convex/server";
|
|
18
|
+
const query = (name) => makeFunctionReference(name);
|
|
19
|
+
const mutation = (name) => makeFunctionReference(name);
|
|
20
|
+
const action = (name) => makeFunctionReference(name);
|
|
5
21
|
export const api = {
|
|
6
22
|
documents: {
|
|
7
23
|
queries: {
|
|
8
|
-
exportForCli:
|
|
9
|
-
exportProjectForCli:
|
|
10
|
-
checkDocumentsExist:
|
|
24
|
+
exportForCli: query("documents/queries:exportForCli"),
|
|
25
|
+
exportProjectForCli: query("documents/queries:exportProjectForCli"),
|
|
26
|
+
checkDocumentsExist: query("documents/queries:checkDocumentsExist"),
|
|
11
27
|
// SYNC-CLI-EDIT-2: Get document metadata for conflict detection
|
|
12
|
-
getDocumentsMetadata:
|
|
28
|
+
getDocumentsMetadata: query("documents/queries:getDocumentsMetadata"),
|
|
13
29
|
},
|
|
14
30
|
mutations: {
|
|
15
|
-
create:
|
|
16
|
-
update:
|
|
31
|
+
create: mutation("documents/mutations:create"),
|
|
32
|
+
update: mutation("documents/mutations:update"),
|
|
17
33
|
},
|
|
18
34
|
// SYNC-ARCH-1: Save document with requirements derivation
|
|
19
35
|
saveWithRequirements: {
|
|
20
|
-
saveWithRequirements:
|
|
36
|
+
saveWithRequirements: mutation("documents/saveWithRequirements:saveWithRequirements"),
|
|
21
37
|
},
|
|
22
38
|
},
|
|
23
39
|
requirements: {
|
|
24
40
|
queries: {
|
|
25
|
-
listByProject:
|
|
41
|
+
listByProject: query("requirements/queries:listByProject"),
|
|
26
42
|
},
|
|
27
43
|
mutations: {
|
|
28
|
-
bulkUpdate:
|
|
44
|
+
bulkUpdate: mutation("requirements/mutations:bulkUpdate"),
|
|
29
45
|
},
|
|
30
46
|
},
|
|
31
47
|
projects: {
|
|
32
48
|
mutations: {
|
|
33
|
-
create:
|
|
49
|
+
create: mutation("projects/mutations:create"),
|
|
34
50
|
},
|
|
35
51
|
},
|
|
36
52
|
teams: {
|
|
37
53
|
queries: {
|
|
38
|
-
listForUserWithUsage:
|
|
54
|
+
listForUserWithUsage: query("teams/queries:listForUserWithUsage"),
|
|
39
55
|
},
|
|
40
56
|
mutations: {
|
|
41
|
-
ensureDefaultTeam:
|
|
57
|
+
ensureDefaultTeam: mutation("teams/mutations:ensureDefaultTeam"),
|
|
42
58
|
},
|
|
43
59
|
},
|
|
44
60
|
teamInvites: {
|
|
45
61
|
queries: {
|
|
46
|
-
getInviteInfo:
|
|
62
|
+
getInviteInfo: query("teamInvites/queries:getInviteInfo"),
|
|
47
63
|
},
|
|
48
64
|
},
|
|
49
65
|
polar: {
|
|
50
|
-
acceptTeamInvite:
|
|
66
|
+
acceptTeamInvite: action("polar:acceptTeamInvite"),
|
|
51
67
|
},
|
|
52
68
|
projectSecrets: {
|
|
53
69
|
queries: {
|
|
54
|
-
getOwnSecret:
|
|
55
|
-
listOwnSecretsForTeam:
|
|
70
|
+
getOwnSecret: query("projectSecrets/queries:getOwnSecret"),
|
|
71
|
+
listOwnSecretsForTeam: query("projectSecrets/queries:listOwnSecretsForTeam"),
|
|
56
72
|
},
|
|
57
73
|
mutations: {
|
|
58
|
-
ensureOwnSecret:
|
|
59
|
-
revokeOwnSecret:
|
|
74
|
+
ensureOwnSecret: mutation("projectSecrets/mutations:ensureOwnSecret"),
|
|
75
|
+
revokeOwnSecret: mutation("projectSecrets/mutations:revokeOwnSecret"),
|
|
60
76
|
},
|
|
61
77
|
},
|
|
62
78
|
lib: {
|
|
63
79
|
authActions: {
|
|
64
|
-
exchangeAuthorizationCode:
|
|
65
|
-
refreshAccessToken:
|
|
80
|
+
exchangeAuthorizationCode: action("lib/authActions:exchangeAuthorizationCode"),
|
|
81
|
+
refreshAccessToken: action("lib/authActions:refreshAccessToken"),
|
|
66
82
|
},
|
|
67
83
|
},
|
|
68
84
|
};
|
package/dist/harness/cache.d.ts
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* - tracking.jsonl: Append-only tracking of requirement() calls (cross-process safe)
|
|
7
7
|
* - coverage.json: Deduplication cache for cloud reporting
|
|
8
8
|
*/
|
|
9
|
-
import {
|
|
9
|
+
import type { RequirementNode } from "../schema/index.js";
|
|
10
10
|
/**
|
|
11
11
|
* Tracking entry for a single requirement() call.
|
|
12
12
|
* Stored as one JSON object per line in tracking.jsonl
|
|
@@ -68,10 +68,6 @@ export declare function findProjectRoot(startDir?: string): string | null;
|
|
|
68
68
|
* Get the cache directory path, creating it if necessary
|
|
69
69
|
*/
|
|
70
70
|
export declare function getCacheDir(requirementsDir: string, create?: boolean): string;
|
|
71
|
-
/**
|
|
72
|
-
* Find all *.requirements.md files under project root
|
|
73
|
-
*/
|
|
74
|
-
export declare function findRequirementsFiles(projectRoot: string): string[];
|
|
75
71
|
/**
|
|
76
72
|
* Write the lookup cache with all pre-parsed requirements
|
|
77
73
|
*/
|