@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.
Files changed (229) hide show
  1. package/README.md +167 -20
  2. package/dist/cli.js +121 -60
  3. package/dist/codebase-to-spec/budget.d.ts +53 -0
  4. package/dist/codebase-to-spec/budget.js +80 -0
  5. package/dist/codebase-to-spec/cache.d.ts +49 -0
  6. package/dist/codebase-to-spec/cache.js +54 -0
  7. package/dist/codebase-to-spec/claude.d.ts +69 -0
  8. package/dist/codebase-to-spec/claude.js +126 -0
  9. package/dist/codebase-to-spec/compose.d.ts +49 -0
  10. package/dist/codebase-to-spec/compose.js +124 -0
  11. package/dist/codebase-to-spec/edit-loop.d.ts +54 -0
  12. package/dist/codebase-to-spec/edit-loop.js +195 -0
  13. package/dist/codebase-to-spec/editor.d.ts +54 -0
  14. package/dist/codebase-to-spec/editor.js +74 -0
  15. package/dist/codebase-to-spec/exit-codes.d.ts +40 -0
  16. package/dist/codebase-to-spec/exit-codes.js +58 -0
  17. package/dist/codebase-to-spec/fan-out.d.ts +63 -0
  18. package/dist/codebase-to-spec/fan-out.js +215 -0
  19. package/dist/codebase-to-spec/interactive.d.ts +30 -0
  20. package/dist/codebase-to-spec/interactive.js +48 -0
  21. package/dist/codebase-to-spec/outline-review-loop.d.ts +51 -0
  22. package/dist/codebase-to-spec/outline-review-loop.js +187 -0
  23. package/dist/codebase-to-spec/pack.d.ts +51 -0
  24. package/dist/codebase-to-spec/pack.js +127 -0
  25. package/dist/codebase-to-spec/planner.d.ts +41 -0
  26. package/dist/codebase-to-spec/planner.js +76 -0
  27. package/dist/codebase-to-spec/present.d.ts +94 -0
  28. package/dist/codebase-to-spec/present.js +288 -0
  29. package/dist/codebase-to-spec/progress.d.ts +33 -0
  30. package/dist/codebase-to-spec/progress.js +28 -0
  31. package/dist/codebase-to-spec/prompts/editor.d.ts +13 -0
  32. package/dist/codebase-to-spec/prompts/editor.js +57 -0
  33. package/dist/codebase-to-spec/prompts/outline-reviewer.d.ts +12 -0
  34. package/dist/codebase-to-spec/prompts/outline-reviewer.js +87 -0
  35. package/dist/codebase-to-spec/prompts/planner-apply.d.ts +12 -0
  36. package/dist/codebase-to-spec/prompts/planner-apply.js +32 -0
  37. package/dist/codebase-to-spec/prompts/planner-initial.d.ts +11 -0
  38. package/dist/codebase-to-spec/prompts/planner-initial.js +125 -0
  39. package/dist/codebase-to-spec/prompts/planner-revise.d.ts +14 -0
  40. package/dist/codebase-to-spec/prompts/planner-revise.js +60 -0
  41. package/dist/codebase-to-spec/prompts/spec-reviewer.d.ts +16 -0
  42. package/dist/codebase-to-spec/prompts/spec-reviewer.js +96 -0
  43. package/dist/codebase-to-spec/prompts/specifier.d.ts +12 -0
  44. package/dist/codebase-to-spec/prompts/specifier.js +100 -0
  45. package/dist/codebase-to-spec/prompts/style-check.d.ts +12 -0
  46. package/dist/codebase-to-spec/prompts/style-check.js +78 -0
  47. package/dist/codebase-to-spec/schemas.d.ts +257 -0
  48. package/dist/codebase-to-spec/schemas.js +183 -0
  49. package/dist/codebase-to-spec/skill-install.d.ts +57 -0
  50. package/dist/codebase-to-spec/skill-install.js +79 -0
  51. package/dist/codebase-to-spec/slice.d.ts +49 -0
  52. package/dist/codebase-to-spec/slice.js +111 -0
  53. package/dist/codebase-to-spec/specifier.d.ts +60 -0
  54. package/dist/codebase-to-spec/specifier.js +79 -0
  55. package/dist/codebase-to-spec/style-check.d.ts +29 -0
  56. package/dist/codebase-to-spec/style-check.js +33 -0
  57. package/dist/codebase-to-spec/summary.d.ts +51 -0
  58. package/dist/codebase-to-spec/summary.js +183 -0
  59. package/dist/codebase-to-spec/validate.d.ts +46 -0
  60. package/dist/codebase-to-spec/validate.js +130 -0
  61. package/dist/commands/acceptance-test.d.ts +6 -0
  62. package/dist/commands/acceptance-test.js +212 -0
  63. package/dist/commands/ai-setup.d.ts +5 -0
  64. package/dist/commands/ai-setup.js +441 -0
  65. package/dist/commands/browsertest.js +34 -27
  66. package/dist/commands/codebase-to-spec/compose.d.ts +14 -0
  67. package/dist/commands/codebase-to-spec/compose.js +57 -0
  68. package/dist/commands/codebase-to-spec/edit-loop.d.ts +16 -0
  69. package/dist/commands/codebase-to-spec/edit-loop.js +83 -0
  70. package/dist/commands/codebase-to-spec/fan-out.d.ts +19 -0
  71. package/dist/commands/codebase-to-spec/fan-out.js +77 -0
  72. package/dist/commands/codebase-to-spec/index.d.ts +9 -0
  73. package/dist/commands/codebase-to-spec/index.js +135 -0
  74. package/dist/commands/codebase-to-spec/pack.d.ts +22 -0
  75. package/dist/commands/codebase-to-spec/pack.js +76 -0
  76. package/dist/commands/codebase-to-spec/plan-loop.d.ts +26 -0
  77. package/dist/commands/codebase-to-spec/plan-loop.js +105 -0
  78. package/dist/commands/codebase-to-spec/present.d.ts +21 -0
  79. package/dist/commands/codebase-to-spec/present.js +92 -0
  80. package/dist/commands/codebase-to-spec/run.d.ts +20 -0
  81. package/dist/commands/codebase-to-spec/run.js +85 -0
  82. package/dist/commands/codebase-to-spec/skill-install.d.ts +20 -0
  83. package/dist/commands/codebase-to-spec/skill-install.js +51 -0
  84. package/dist/commands/codebase-to-spec/specify-area.d.ts +18 -0
  85. package/dist/commands/codebase-to-spec/specify-area.js +82 -0
  86. package/dist/commands/codebase-to-spec/style-check.d.ts +15 -0
  87. package/dist/commands/codebase-to-spec/style-check.js +42 -0
  88. package/dist/commands/codebase-to-spec/validate.d.ts +18 -0
  89. package/dist/commands/codebase-to-spec/validate.js +38 -0
  90. package/dist/commands/create-requirement-document.d.ts +2 -0
  91. package/dist/commands/create-requirement-document.js +41 -0
  92. package/dist/commands/finalize.js +7 -7
  93. package/dist/commands/get.d.ts +2 -0
  94. package/dist/commands/get.js +55 -0
  95. package/dist/commands/init.js +132 -117
  96. package/dist/commands/link.js +27 -27
  97. package/dist/commands/list.d.ts +6 -0
  98. package/dist/commands/list.js +43 -0
  99. package/dist/commands/mcp-setup.js +159 -149
  100. package/dist/commands/mcp.js +1 -1
  101. package/dist/commands/prepare.js +4 -4
  102. package/dist/commands/pull.js +116 -121
  103. package/dist/commands/push.js +106 -112
  104. package/dist/commands/report.d.ts +6 -2
  105. package/dist/commands/report.js +177 -122
  106. package/dist/commands/requirements-for.d.ts +2 -0
  107. package/dist/commands/requirements-for.js +29 -0
  108. package/dist/commands/review-test.d.ts +2 -0
  109. package/dist/commands/review-test.js +75 -0
  110. package/dist/commands/search.d.ts +6 -0
  111. package/dist/commands/search.js +39 -0
  112. package/dist/commands/style-check.d.ts +7 -0
  113. package/dist/commands/style-check.js +75 -0
  114. package/dist/commands/test.js +53 -59
  115. package/dist/commands/tests-for.d.ts +2 -0
  116. package/dist/commands/tests-for.js +80 -0
  117. package/dist/commands/validate.d.ts +6 -0
  118. package/dist/commands/validate.js +72 -0
  119. package/dist/config.js +1 -1
  120. package/dist/convex.d.ts +34 -22
  121. package/dist/convex.js +38 -22
  122. package/dist/harness/cache.d.ts +1 -5
  123. package/dist/harness/cache.js +49 -59
  124. package/dist/harness/convexReporting.d.ts +1 -1
  125. package/dist/harness/convexReporting.js +9 -7
  126. package/dist/harness/coverageCache.js +3 -3
  127. package/dist/harness/finalize.js +59 -46
  128. package/dist/harness/index.d.ts +6 -7
  129. package/dist/harness/index.js +9 -10
  130. package/dist/harness/prepare.js +6 -5
  131. package/dist/harness/requirementsLoader.d.ts +2 -2
  132. package/dist/harness/requirementsLoader.js +13 -35
  133. package/dist/harness/tracking.js +18 -18
  134. package/dist/harness/types.d.ts +1 -1
  135. package/dist/mcp/convexClient.d.ts +0 -39
  136. package/dist/mcp/convexClient.js +2 -107
  137. package/dist/mcp/grep.d.ts +1 -1
  138. package/dist/mcp/grep.js +87 -42
  139. package/dist/mcp/handlers/authoring.d.ts +1 -1
  140. package/dist/mcp/handlers/authoring.js +30 -234
  141. package/dist/mcp/handlers/coverage.d.ts +1 -1
  142. package/dist/mcp/handlers/coverage.js +13 -15
  143. package/dist/mcp/handlers/debug.d.ts +2 -3
  144. package/dist/mcp/handlers/debug.js +10 -10
  145. package/dist/mcp/handlers/get.d.ts +1 -1
  146. package/dist/mcp/handlers/get.js +11 -10
  147. package/dist/mcp/handlers/index.d.ts +20 -20
  148. package/dist/mcp/handlers/index.js +10 -10
  149. package/dist/mcp/handlers/list.d.ts +4 -33
  150. package/dist/mcp/handlers/list.js +16 -38
  151. package/dist/mcp/handlers/push.d.ts +1 -1
  152. package/dist/mcp/handlers/push.js +28 -18
  153. package/dist/mcp/handlers/report.d.ts +16 -0
  154. package/dist/mcp/handlers/report.js +134 -0
  155. package/dist/mcp/handlers/review.d.ts +1 -1
  156. package/dist/mcp/handlers/review.js +40 -59
  157. package/dist/mcp/handlers/search.d.ts +1 -1
  158. package/dist/mcp/handlers/search.js +7 -9
  159. package/dist/mcp/handlers/test-mapping.d.ts +1 -1
  160. package/dist/mcp/handlers/test-mapping.js +14 -14
  161. package/dist/mcp/handlers/types.d.ts +3 -3
  162. package/dist/mcp/handlers/types.js +2 -2
  163. package/dist/mcp/index.d.ts +1 -1
  164. package/dist/mcp/index.js +147 -167
  165. package/dist/mcp/requirements.d.ts +2 -2
  166. package/dist/mcp/requirements.js +30 -30
  167. package/dist/mcp/testCodeExtractor.js +24 -26
  168. package/dist/mcp/types.d.ts +1 -1
  169. package/dist/push/core.d.ts +2 -2
  170. package/dist/push/core.js +20 -20
  171. package/dist/push/index.d.ts +1 -1
  172. package/dist/push/index.js +2 -2
  173. package/dist/requirements/cloud-ai.d.ts +57 -0
  174. package/dist/requirements/cloud-ai.js +104 -0
  175. package/dist/requirements/cloud-coverage.d.ts +41 -0
  176. package/dist/requirements/cloud-coverage.js +60 -0
  177. package/dist/requirements/coverage.d.ts +45 -0
  178. package/dist/requirements/coverage.js +114 -0
  179. package/dist/requirements/grep.d.ts +33 -0
  180. package/dist/requirements/grep.js +306 -0
  181. package/dist/requirements/index.d.ts +73 -0
  182. package/dist/requirements/index.js +174 -0
  183. package/dist/requirements/style-guide.d.ts +67 -0
  184. package/dist/requirements/style-guide.js +299 -0
  185. package/dist/requirements/testCodeExtractor.d.ts +22 -0
  186. package/dist/requirements/testCodeExtractor.js +150 -0
  187. package/dist/schema/browser.d.ts +8 -8
  188. package/dist/schema/browser.js +13 -15
  189. package/dist/schema/builder.d.ts +1 -1
  190. package/dist/schema/builder.js +13 -44
  191. package/dist/schema/conversions.d.ts +2 -2
  192. package/dist/schema/conversions.js +11 -11
  193. package/dist/schema/index.d.ts +9 -9
  194. package/dist/schema/index.js +15 -15
  195. package/dist/schema/parser-core.d.ts +1 -1
  196. package/dist/schema/parser-core.js +23 -22
  197. package/dist/schema/parser.d.ts +3 -3
  198. package/dist/schema/parser.js +27 -31
  199. package/dist/schema/resolver.d.ts +1 -1
  200. package/dist/schema/resolver.js +9 -9
  201. package/dist/schema/scenario.d.ts +1 -1
  202. package/dist/schema/scenario.js +1 -1
  203. package/dist/schema/schemas.d.ts +3 -3
  204. package/dist/schema/schemas.js +41 -28
  205. package/dist/schema/test-schema.js +27 -27
  206. package/dist/templates/context-file-section.md +3 -2
  207. package/dist/templates/example-requirements.js +1 -1
  208. package/dist/templates/example-requirements.ts +3 -1
  209. package/dist/templates/requirements-readme.js +1 -1
  210. package/dist/templates/requirements-readme.ts +1 -1
  211. package/dist/templates/skills/codebase-to-spec/SKILL.md +118 -0
  212. package/dist/utils/brand.js +3 -3
  213. package/dist/utils/browser-launch.js +4 -4
  214. package/dist/utils/context-file.d.ts +1 -1
  215. package/dist/utils/context-file.js +26 -26
  216. package/dist/utils/env.js +7 -7
  217. package/dist/utils/gitignore.js +7 -7
  218. package/dist/utils/oauth-callback-server.d.ts +1 -1
  219. package/dist/utils/oauth-callback-server.js +27 -25
  220. package/dist/utils/oauth-flow.js +32 -29
  221. package/dist/utils/project-discovery.d.ts +3 -3
  222. package/dist/utils/project-discovery.js +18 -17
  223. package/dist/utils/project-name.js +8 -8
  224. package/dist/utils/project-selector.d.ts +1 -1
  225. package/dist/utils/project-selector.js +24 -21
  226. package/dist/utils/project-settings.d.ts +1 -1
  227. package/dist/utils/project-settings.js +24 -22
  228. package/dist/utils/templates.js +6 -6
  229. package/package.json +2 -1
@@ -1,67 +1,61 @@
1
- import * as fs from 'fs';
2
- import * as path from 'path';
3
- import { parseRequirementsFromFile } from '../schema/index.js';
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
- try {
6
- console.log('Parsing and validating requirements...');
7
- const requirementsDir = path.join(process.cwd(), '.requirements');
8
- if (!fs.existsSync(requirementsDir)) {
9
- console.error('Error: .requirements/ directory not found.');
10
- console.log('Run "dotrequirements pull" first to sync requirements.');
11
- process.exit(1);
12
- }
13
- // Get files to test
14
- let files;
15
- if (options.file) {
16
- files = [options.file];
17
- }
18
- else {
19
- files = fs
20
- .readdirSync(requirementsDir)
21
- .filter((f) => f.endsWith('.requirements.md'))
22
- .map((f) => path.join(requirementsDir, f));
23
- }
24
- if (files.length === 0) {
25
- console.log('No Markdown requirements files found to test.');
26
- return;
27
- }
28
- let totalRequirements = 0;
29
- let passCount = 0;
30
- let failCount = 0;
31
- for (const filePath of files) {
32
- const fileName = path.basename(filePath);
33
- console.log(`\nTesting: ${fileName}`);
34
- try {
35
- // Parse and validate using shared schema module
36
- const { metadata, requirements } = parseRequirementsFromFile(filePath);
37
- // Count total requirements (root + all descendants)
38
- let count = 0;
39
- for (const req of requirements) {
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
- console.log(`\n${'='.repeat(50)}`);
54
- console.log(`Total files: ${files.length}`);
55
- console.log(`Passed: ${passCount}`);
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
- catch (error) {
63
- // Re-throw to let the CLI error handler display it cleanly
64
- throw error;
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,2 @@
1
+ export declare function testsForCommand(requirementsFile: string): Promise<void>;
2
+ //# sourceMappingURL=tests-for.d.ts.map
@@ -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,6 @@
1
+ interface ValidateOptions {
2
+ file?: string;
3
+ }
4
+ export declare function validateCommand(options: ValidateOptions): Promise<void>;
5
+ export {};
6
+ //# sourceMappingURL=validate.d.ts.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
@@ -2,7 +2,7 @@
2
2
  * Production Convex deployment URL
3
3
  * All users connect to the same backend
4
4
  */
5
- const CONVEX_URL = 'https://data.dotrequirements.io';
5
+ const CONVEX_URL = "https://data.dotrequirements.io";
6
6
  /**
7
7
  * Get the Convex deployment URL
8
8
  */
package/dist/convex.d.ts CHANGED
@@ -1,66 +1,78 @@
1
1
  /**
2
- * Convex API stub for CLI usage
3
- * This will be replaced with actual generated types when linked to the Convex backend
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
- * This will be replaced with actual generated types when linked to the Convex backend
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: 'documents/queries:exportForCli',
9
- exportProjectForCli: 'documents/queries:exportProjectForCli',
10
- checkDocumentsExist: 'documents/queries: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: 'documents/queries:getDocumentsMetadata',
28
+ getDocumentsMetadata: query("documents/queries:getDocumentsMetadata"),
13
29
  },
14
30
  mutations: {
15
- create: 'documents/mutations:create',
16
- update: 'documents/mutations: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: 'documents/saveWithRequirements:saveWithRequirements',
36
+ saveWithRequirements: mutation("documents/saveWithRequirements:saveWithRequirements"),
21
37
  },
22
38
  },
23
39
  requirements: {
24
40
  queries: {
25
- listByProject: 'requirements/queries:listByProject',
41
+ listByProject: query("requirements/queries:listByProject"),
26
42
  },
27
43
  mutations: {
28
- bulkUpdate: 'requirements/mutations:bulkUpdate',
44
+ bulkUpdate: mutation("requirements/mutations:bulkUpdate"),
29
45
  },
30
46
  },
31
47
  projects: {
32
48
  mutations: {
33
- create: 'projects/mutations:create',
49
+ create: mutation("projects/mutations:create"),
34
50
  },
35
51
  },
36
52
  teams: {
37
53
  queries: {
38
- listForUserWithUsage: 'teams/queries:listForUserWithUsage',
54
+ listForUserWithUsage: query("teams/queries:listForUserWithUsage"),
39
55
  },
40
56
  mutations: {
41
- ensureDefaultTeam: 'teams/mutations:ensureDefaultTeam',
57
+ ensureDefaultTeam: mutation("teams/mutations:ensureDefaultTeam"),
42
58
  },
43
59
  },
44
60
  teamInvites: {
45
61
  queries: {
46
- getInviteInfo: 'teamInvites/queries:getInviteInfo',
62
+ getInviteInfo: query("teamInvites/queries:getInviteInfo"),
47
63
  },
48
64
  },
49
65
  polar: {
50
- acceptTeamInvite: 'polar:acceptTeamInvite',
66
+ acceptTeamInvite: action("polar:acceptTeamInvite"),
51
67
  },
52
68
  projectSecrets: {
53
69
  queries: {
54
- getOwnSecret: 'projectSecrets/queries:getOwnSecret',
55
- listOwnSecretsForTeam: 'projectSecrets/queries:listOwnSecretsForTeam',
70
+ getOwnSecret: query("projectSecrets/queries:getOwnSecret"),
71
+ listOwnSecretsForTeam: query("projectSecrets/queries:listOwnSecretsForTeam"),
56
72
  },
57
73
  mutations: {
58
- ensureOwnSecret: 'projectSecrets/mutations:ensureOwnSecret',
59
- revokeOwnSecret: 'projectSecrets/mutations: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: 'lib/authActions:exchangeAuthorizationCode',
65
- refreshAccessToken: 'lib/authActions:refreshAccessToken',
80
+ exchangeAuthorizationCode: action("lib/authActions:exchangeAuthorizationCode"),
81
+ refreshAccessToken: action("lib/authActions:refreshAccessToken"),
66
82
  },
67
83
  },
68
84
  };
@@ -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 { type RequirementNode } from '../schema/index.js';
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
  */