@popoverai/dotrequirements 0.22.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 (230) hide show
  1. package/README.md +173 -23
  2. package/dist/cli.js +121 -61
  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.d.ts +0 -1
  66. package/dist/commands/browsertest.js +51 -26
  67. package/dist/commands/codebase-to-spec/compose.d.ts +14 -0
  68. package/dist/commands/codebase-to-spec/compose.js +57 -0
  69. package/dist/commands/codebase-to-spec/edit-loop.d.ts +16 -0
  70. package/dist/commands/codebase-to-spec/edit-loop.js +83 -0
  71. package/dist/commands/codebase-to-spec/fan-out.d.ts +19 -0
  72. package/dist/commands/codebase-to-spec/fan-out.js +77 -0
  73. package/dist/commands/codebase-to-spec/index.d.ts +9 -0
  74. package/dist/commands/codebase-to-spec/index.js +135 -0
  75. package/dist/commands/codebase-to-spec/pack.d.ts +22 -0
  76. package/dist/commands/codebase-to-spec/pack.js +76 -0
  77. package/dist/commands/codebase-to-spec/plan-loop.d.ts +26 -0
  78. package/dist/commands/codebase-to-spec/plan-loop.js +105 -0
  79. package/dist/commands/codebase-to-spec/present.d.ts +21 -0
  80. package/dist/commands/codebase-to-spec/present.js +92 -0
  81. package/dist/commands/codebase-to-spec/run.d.ts +20 -0
  82. package/dist/commands/codebase-to-spec/run.js +85 -0
  83. package/dist/commands/codebase-to-spec/skill-install.d.ts +20 -0
  84. package/dist/commands/codebase-to-spec/skill-install.js +51 -0
  85. package/dist/commands/codebase-to-spec/specify-area.d.ts +18 -0
  86. package/dist/commands/codebase-to-spec/specify-area.js +82 -0
  87. package/dist/commands/codebase-to-spec/style-check.d.ts +15 -0
  88. package/dist/commands/codebase-to-spec/style-check.js +42 -0
  89. package/dist/commands/codebase-to-spec/validate.d.ts +18 -0
  90. package/dist/commands/codebase-to-spec/validate.js +38 -0
  91. package/dist/commands/create-requirement-document.d.ts +2 -0
  92. package/dist/commands/create-requirement-document.js +41 -0
  93. package/dist/commands/finalize.js +7 -7
  94. package/dist/commands/get.d.ts +2 -0
  95. package/dist/commands/get.js +55 -0
  96. package/dist/commands/init.js +132 -117
  97. package/dist/commands/link.js +27 -27
  98. package/dist/commands/list.d.ts +6 -0
  99. package/dist/commands/list.js +43 -0
  100. package/dist/commands/mcp-setup.js +159 -149
  101. package/dist/commands/mcp.js +1 -1
  102. package/dist/commands/prepare.js +4 -4
  103. package/dist/commands/pull.js +116 -121
  104. package/dist/commands/push.js +106 -112
  105. package/dist/commands/report.d.ts +6 -2
  106. package/dist/commands/report.js +177 -122
  107. package/dist/commands/requirements-for.d.ts +2 -0
  108. package/dist/commands/requirements-for.js +29 -0
  109. package/dist/commands/review-test.d.ts +2 -0
  110. package/dist/commands/review-test.js +75 -0
  111. package/dist/commands/search.d.ts +6 -0
  112. package/dist/commands/search.js +39 -0
  113. package/dist/commands/style-check.d.ts +7 -0
  114. package/dist/commands/style-check.js +75 -0
  115. package/dist/commands/test.js +53 -59
  116. package/dist/commands/tests-for.d.ts +2 -0
  117. package/dist/commands/tests-for.js +80 -0
  118. package/dist/commands/validate.d.ts +6 -0
  119. package/dist/commands/validate.js +72 -0
  120. package/dist/config.js +1 -1
  121. package/dist/convex.d.ts +34 -22
  122. package/dist/convex.js +38 -22
  123. package/dist/harness/cache.d.ts +1 -5
  124. package/dist/harness/cache.js +49 -59
  125. package/dist/harness/convexReporting.d.ts +1 -1
  126. package/dist/harness/convexReporting.js +9 -7
  127. package/dist/harness/coverageCache.js +3 -3
  128. package/dist/harness/finalize.js +59 -46
  129. package/dist/harness/index.d.ts +6 -7
  130. package/dist/harness/index.js +9 -10
  131. package/dist/harness/prepare.js +6 -5
  132. package/dist/harness/requirementsLoader.d.ts +2 -2
  133. package/dist/harness/requirementsLoader.js +13 -35
  134. package/dist/harness/tracking.js +18 -18
  135. package/dist/harness/types.d.ts +1 -1
  136. package/dist/mcp/convexClient.d.ts +0 -39
  137. package/dist/mcp/convexClient.js +2 -107
  138. package/dist/mcp/grep.d.ts +1 -1
  139. package/dist/mcp/grep.js +87 -42
  140. package/dist/mcp/handlers/authoring.d.ts +1 -1
  141. package/dist/mcp/handlers/authoring.js +30 -234
  142. package/dist/mcp/handlers/coverage.d.ts +1 -1
  143. package/dist/mcp/handlers/coverage.js +13 -15
  144. package/dist/mcp/handlers/debug.d.ts +2 -3
  145. package/dist/mcp/handlers/debug.js +10 -10
  146. package/dist/mcp/handlers/get.d.ts +1 -1
  147. package/dist/mcp/handlers/get.js +11 -10
  148. package/dist/mcp/handlers/index.d.ts +20 -20
  149. package/dist/mcp/handlers/index.js +10 -10
  150. package/dist/mcp/handlers/list.d.ts +4 -33
  151. package/dist/mcp/handlers/list.js +16 -38
  152. package/dist/mcp/handlers/push.d.ts +1 -1
  153. package/dist/mcp/handlers/push.js +28 -18
  154. package/dist/mcp/handlers/report.d.ts +16 -0
  155. package/dist/mcp/handlers/report.js +134 -0
  156. package/dist/mcp/handlers/review.d.ts +1 -1
  157. package/dist/mcp/handlers/review.js +40 -59
  158. package/dist/mcp/handlers/search.d.ts +1 -1
  159. package/dist/mcp/handlers/search.js +7 -9
  160. package/dist/mcp/handlers/test-mapping.d.ts +1 -1
  161. package/dist/mcp/handlers/test-mapping.js +14 -14
  162. package/dist/mcp/handlers/types.d.ts +3 -3
  163. package/dist/mcp/handlers/types.js +2 -2
  164. package/dist/mcp/index.d.ts +1 -1
  165. package/dist/mcp/index.js +156 -178
  166. package/dist/mcp/requirements.d.ts +2 -2
  167. package/dist/mcp/requirements.js +30 -30
  168. package/dist/mcp/testCodeExtractor.js +24 -26
  169. package/dist/mcp/types.d.ts +1 -1
  170. package/dist/push/core.d.ts +2 -2
  171. package/dist/push/core.js +20 -20
  172. package/dist/push/index.d.ts +1 -1
  173. package/dist/push/index.js +2 -2
  174. package/dist/requirements/cloud-ai.d.ts +57 -0
  175. package/dist/requirements/cloud-ai.js +104 -0
  176. package/dist/requirements/cloud-coverage.d.ts +41 -0
  177. package/dist/requirements/cloud-coverage.js +60 -0
  178. package/dist/requirements/coverage.d.ts +45 -0
  179. package/dist/requirements/coverage.js +114 -0
  180. package/dist/requirements/grep.d.ts +33 -0
  181. package/dist/requirements/grep.js +306 -0
  182. package/dist/requirements/index.d.ts +73 -0
  183. package/dist/requirements/index.js +174 -0
  184. package/dist/requirements/style-guide.d.ts +67 -0
  185. package/dist/requirements/style-guide.js +299 -0
  186. package/dist/requirements/testCodeExtractor.d.ts +22 -0
  187. package/dist/requirements/testCodeExtractor.js +150 -0
  188. package/dist/schema/browser.d.ts +8 -6
  189. package/dist/schema/browser.js +14 -14
  190. package/dist/schema/builder.d.ts +1 -1
  191. package/dist/schema/builder.js +13 -44
  192. package/dist/schema/conversions.d.ts +2 -2
  193. package/dist/schema/conversions.js +11 -11
  194. package/dist/schema/index.d.ts +9 -7
  195. package/dist/schema/index.js +15 -13
  196. package/dist/schema/parser-core.d.ts +1 -1
  197. package/dist/schema/parser-core.js +23 -22
  198. package/dist/schema/parser.d.ts +3 -3
  199. package/dist/schema/parser.js +27 -31
  200. package/dist/schema/resolver.d.ts +1 -1
  201. package/dist/schema/resolver.js +9 -9
  202. package/dist/schema/scenario.d.ts +91 -0
  203. package/dist/schema/scenario.js +82 -0
  204. package/dist/schema/schemas.d.ts +3 -3
  205. package/dist/schema/schemas.js +41 -28
  206. package/dist/schema/test-schema.js +27 -27
  207. package/dist/templates/context-file-section.md +3 -2
  208. package/dist/templates/example-requirements.js +1 -1
  209. package/dist/templates/example-requirements.ts +3 -1
  210. package/dist/templates/requirements-readme.js +1 -1
  211. package/dist/templates/requirements-readme.ts +1 -1
  212. package/dist/templates/skills/codebase-to-spec/SKILL.md +118 -0
  213. package/dist/utils/brand.js +3 -3
  214. package/dist/utils/browser-launch.js +4 -4
  215. package/dist/utils/context-file.d.ts +1 -1
  216. package/dist/utils/context-file.js +26 -26
  217. package/dist/utils/env.js +7 -7
  218. package/dist/utils/gitignore.js +7 -7
  219. package/dist/utils/oauth-callback-server.d.ts +1 -1
  220. package/dist/utils/oauth-callback-server.js +27 -25
  221. package/dist/utils/oauth-flow.js +32 -29
  222. package/dist/utils/project-discovery.d.ts +3 -3
  223. package/dist/utils/project-discovery.js +18 -17
  224. package/dist/utils/project-name.js +8 -8
  225. package/dist/utils/project-selector.d.ts +1 -1
  226. package/dist/utils/project-selector.js +24 -21
  227. package/dist/utils/project-settings.d.ts +5 -4
  228. package/dist/utils/project-settings.js +28 -20
  229. package/dist/utils/templates.js +6 -6
  230. package/package.json +2 -1
package/dist/mcp/index.js CHANGED
@@ -1,18 +1,18 @@
1
1
  #!/usr/bin/env node
2
- import { Server } from '@modelcontextprotocol/sdk/server/index.js';
3
- import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
4
- import { CallToolRequestSchema, ListToolsRequestSchema, ListPromptsRequestSchema, GetPromptRequestSchema, } from '@modelcontextprotocol/sdk/types.js';
5
- import { loadAllRequirements } from './requirements.js';
6
- import { discoverProjects, resolveProject, } from '../utils/project-discovery.js';
7
- import { getCredentialsFromEnv } from '../utils/project-settings.js';
8
- import { readFileSync } from 'fs';
9
- import { fileURLToPath } from 'url';
10
- import { dirname, join } from 'path';
11
- import { handleDebugMcpEnvironment, handleSearchRequirements, handleListAllRequirements, handleListUntestedRequirements, handleGetRequirement, handleGetRequirementsByTest, handleGetTestsByRequirement, handleGetRequirementCoverage, handleGetProjectCoverageSummary, handleCreateRequirementDocument, handleValidateRequirements, handlePushRequirements, handleStyleCheck, handleReviewTest, } from './handlers/index.js';
2
+ import { readFileSync } from "node:fs";
3
+ import { dirname, join } from "node:path";
4
+ import { fileURLToPath } from "node:url";
5
+ import { Server } from "@modelcontextprotocol/sdk/server/index.js";
6
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
7
+ import { CallToolRequestSchema, GetPromptRequestSchema, ListPromptsRequestSchema, ListToolsRequestSchema, } from "@modelcontextprotocol/sdk/types.js";
8
+ import { loadAllRequirements, } from "../requirements/index.js";
9
+ import { discoverProjects, resolveProject, } from "../utils/project-discovery.js";
10
+ import { getCredentialsFromEnv } from "../utils/project-settings.js";
11
+ import { handleCreateRequirementDocument, handleDebugMcpEnvironment, handleGetRequirement, handleGetRequirementsByTest, handleGetTestsByRequirement, handleList, handlePushRequirements, handleReport, handleReviewTest, handleSearchRequirements, handleStyleCheck, handleValidateRequirements, } from "./handlers/index.js";
12
12
  // Read version from package.json
13
13
  const __filename = fileURLToPath(import.meta.url);
14
14
  const __dirname = dirname(__filename);
15
- const packageJson = JSON.parse(readFileSync(join(__dirname, '../../package.json'), 'utf-8'));
15
+ const packageJson = JSON.parse(readFileSync(join(__dirname, "../../package.json"), "utf-8"));
16
16
  const VERSION = packageJson.version;
17
17
  // Get project paths from environment variables
18
18
  // Supports both PROJ_* pattern (Antigravity) and REQUIREMENTS_DIR fallback
@@ -20,7 +20,7 @@ function getProjectPathsFromEnv() {
20
20
  const projects = new Map();
21
21
  // Check for PROJ_* env vars (project ID -> path mapping)
22
22
  for (const [key, value] of Object.entries(process.env)) {
23
- if (key.startsWith('PROJ_') && value) {
23
+ if (key.startsWith("PROJ_") && value) {
24
24
  const projectId = key.substring(5); // Remove 'PROJ_' prefix
25
25
  projects.set(projectId, value);
26
26
  }
@@ -32,27 +32,26 @@ const WORKSPACE_ROOT = process.env.REQUIREMENTS_DIR || process.cwd();
32
32
  const PROJECT_PATHS = getProjectPathsFromEnv();
33
33
  // Parse --auth-from-env flag for CI/CD environments
34
34
  // When set, credentials are read from DOTREQ_PROJECT_ID and DOTREQ_PROJECT_SECRET env vars
35
- const USE_ENV_AUTH = process.argv.includes('--auth-from-env');
36
- // Cache for loaded requirements (refreshed on each tool call for now)
37
- let cachedRequirements = new Map();
35
+ const USE_ENV_AUTH = process.argv.includes("--auth-from-env");
38
36
  let cachedDiscoveryResult = null;
37
+ // Requirements are loaded fresh on every call. A long-lived in-memory cache
38
+ // silently served stale data when .requirements/*.md files were created or
39
+ // edited mid-session, which is the primary authoring workflow the MCP server
40
+ // is meant to support. If this ever becomes a measured performance concern,
41
+ // invalidate via directory mtime rather than reintroducing a lifetime cache.
39
42
  async function getRequirements(projectId) {
40
43
  const project = await getProjectFromDiscovery(projectId);
41
- const cacheKey = project.projectId;
42
- if (!cachedRequirements.has(cacheKey)) {
43
- const { flattened } = await loadAllRequirements(project.path);
44
- cachedRequirements.set(cacheKey, flattened);
45
- }
46
- return cachedRequirements.get(cacheKey);
44
+ const { flattened } = await loadAllRequirements(project.path);
45
+ return flattened;
47
46
  }
48
47
  async function getProjectFromDiscovery(projectId) {
49
- const { isConfiguredProject } = await import('../utils/project-discovery.js');
48
+ const { isConfiguredProject } = await import("../utils/project-discovery.js");
50
49
  // If --auth-from-env flag is set, use credentials from environment variables
51
50
  // This is the explicit opt-in for CI/CD environments
52
51
  if (USE_ENV_AUTH) {
53
52
  const envCredentials = getCredentialsFromEnv();
54
53
  if (!envCredentials) {
55
- throw new Error('--auth-from-env flag requires DOTREQ_PROJECT_ID and DOTREQ_PROJECT_SECRET environment variables to be set');
54
+ throw new Error("--auth-from-env flag requires DOTREQ_PROJECT_ID and DOTREQ_PROJECT_SECRET environment variables to be set");
56
55
  }
57
56
  // Return a synthetic project using env credentials and workspace root
58
57
  return {
@@ -65,7 +64,7 @@ async function getProjectFromDiscovery(projectId) {
65
64
  if (PROJECT_PATHS.size > 0) {
66
65
  const projects = [];
67
66
  // Validate all env var projects
68
- for (const [id, path] of PROJECT_PATHS.entries()) {
67
+ for (const [, path] of PROJECT_PATHS.entries()) {
69
68
  const project = isConfiguredProject(path);
70
69
  if (project) {
71
70
  projects.push(project);
@@ -74,15 +73,15 @@ async function getProjectFromDiscovery(projectId) {
74
73
  // Build discovery result from env var projects
75
74
  if (projects.length === 0) {
76
75
  cachedDiscoveryResult = {
77
- type: 'none',
78
- message: 'No valid dotrequirements projects found in PROJ_* environment variables',
76
+ type: "none",
77
+ message: "No valid dotrequirements projects found in PROJ_* environment variables",
79
78
  };
80
79
  }
81
80
  else if (projects.length === 1) {
82
- cachedDiscoveryResult = { type: 'single', project: projects[0] };
81
+ cachedDiscoveryResult = { type: "single", project: projects[0] };
83
82
  }
84
83
  else {
85
- cachedDiscoveryResult = { type: 'multiple', projects };
84
+ cachedDiscoveryResult = { type: "multiple", projects };
86
85
  }
87
86
  return resolveProject(cachedDiscoveryResult, projectId);
88
87
  }
@@ -92,175 +91,155 @@ async function getProjectFromDiscovery(projectId) {
92
91
  }
93
92
  return resolveProject(cachedDiscoveryResult, projectId);
94
93
  }
95
- // Invalidate cache (call before operations that should see fresh data)
96
- // Exported for testing
94
+ // Invalidate the project-discovery cache. Requirements are no longer cached,
95
+ // so this only resets discovery state. Exported for testing.
97
96
  export function invalidateCache() {
98
- cachedRequirements.clear();
99
97
  cachedDiscoveryResult = null;
100
98
  }
101
99
  // Tool definitions
102
100
  const tools = [
103
101
  {
104
- name: 'debug_mcp_environment',
105
- description: 'DEBUG TOOL: Returns diagnostic information about the MCP server environment (working directory, env vars, etc.)',
102
+ name: "debug_mcp_environment",
103
+ description: "DEBUG TOOL: Returns diagnostic information about the MCP server environment (working directory, env vars, etc.)",
106
104
  inputSchema: {
107
- type: 'object',
105
+ type: "object",
108
106
  properties: {},
109
107
  required: [],
110
108
  },
111
109
  },
112
110
  {
113
- name: 'search_requirements',
114
- description: 'Search requirements by text or regex query. Searches requirement IDs, content, and labels. Returns matching requirements with their full context.',
111
+ name: "search_requirements",
112
+ description: "Search requirements by text or regex query. Searches requirement IDs, content, and labels. Returns matching requirements with their full context.",
115
113
  inputSchema: {
116
- type: 'object',
114
+ type: "object",
117
115
  properties: {
118
116
  query: {
119
- type: 'string',
120
- description: 'Text or regex pattern to search for in requirement IDs, content, or labels',
117
+ type: "string",
118
+ description: "Text or regex pattern to search for in requirement IDs, content, or labels",
121
119
  },
122
120
  useRegex: {
123
- type: 'boolean',
124
- description: 'If true, treat query as a regular expression (default: false)',
121
+ type: "boolean",
122
+ description: "If true, treat query as a regular expression (default: false)",
125
123
  },
126
124
  projectId: {
127
- type: 'string',
128
- description: 'Optional: Specify which project to search (required when multiple projects exist)',
125
+ type: "string",
126
+ description: "Optional: Specify which project to search (required when multiple projects exist)",
129
127
  },
130
128
  },
131
- required: ['query'],
129
+ required: ["query"],
132
130
  },
133
131
  },
134
132
  {
135
- name: 'get_requirement',
133
+ name: "get_requirement",
136
134
  description: 'Get a requirement and all its children, including test coverage information. Accepts any requirement path (e.g., "REQ-123" returns the root and all children, "REQ-123.0" returns that node and its children). Shows which tests reference this requirement and includes the test code.',
137
135
  inputSchema: {
138
- type: 'object',
136
+ type: "object",
139
137
  properties: {
140
138
  id: {
141
- type: 'string',
139
+ type: "string",
142
140
  description: 'The requirement ID or path (e.g., "REQ-123" for root, "REQ-123.0" for child)',
143
141
  },
144
142
  projectId: {
145
- type: 'string',
146
- description: 'Optional: Specify which project to search (required when multiple projects exist)',
143
+ type: "string",
144
+ description: "Optional: Specify which project to search (required when multiple projects exist)",
147
145
  },
148
146
  },
149
- required: ['id'],
147
+ required: ["id"],
150
148
  },
151
149
  },
152
150
  {
153
- name: 'list_untested_requirements',
154
- description: 'List all requirements that have no test references. Compares requirements in .requirements/ files against requirement() calls in the codebase.',
151
+ name: "list_requirements",
152
+ description: "List requirements in the workspace. Defaults to every root requirement (summary of IDs and content with child counts). Set untested to true to filter to only the root requirements that have no requirement() references in the codebase.",
155
153
  inputSchema: {
156
- type: 'object',
154
+ type: "object",
157
155
  properties: {
158
- projectId: {
159
- type: 'string',
160
- description: 'Optional: Specify which project to search (required when multiple projects exist)',
156
+ untested: {
157
+ type: "boolean",
158
+ description: "When true, return only root requirements that have no test references (default: false)",
161
159
  },
162
- },
163
- required: [],
164
- },
165
- },
166
- {
167
- name: 'list_all_requirements',
168
- description: 'List all requirements in the workspace. Returns a summary of all requirements with their IDs, labels, and content.',
169
- inputSchema: {
170
- type: 'object',
171
- properties: {
172
160
  projectId: {
173
- type: 'string',
174
- description: 'Optional: Specify which project to search (required when multiple projects exist)',
161
+ type: "string",
162
+ description: "Optional: Specify which project to search (required when multiple projects exist)",
175
163
  },
176
164
  },
177
165
  required: [],
178
166
  },
179
167
  },
180
168
  {
181
- name: 'get_requirements_by_test',
182
- description: 'Get the semantic meaning of requirement() references in a test file. Returns requirement content with line numbers where they are referenced.',
169
+ name: "get_requirements_by_test",
170
+ description: "Get the semantic meaning of requirement() references in a test file. Returns requirement content with line numbers where they are referenced.",
183
171
  inputSchema: {
184
- type: 'object',
172
+ type: "object",
185
173
  properties: {
186
174
  testFile: {
187
- type: 'string',
188
- description: 'Path to the test file to analyze',
175
+ type: "string",
176
+ description: "Path to the test file to analyze",
189
177
  },
190
178
  projectId: {
191
- type: 'string',
192
- description: 'Optional: Specify which project to search (required when multiple projects exist)',
179
+ type: "string",
180
+ description: "Optional: Specify which project to search (required when multiple projects exist)",
193
181
  },
194
182
  },
195
- required: ['testFile'],
183
+ required: ["testFile"],
196
184
  },
197
185
  },
198
186
  {
199
- name: 'get_tests_by_requirement',
200
- description: 'Show which requirements from a requirements file have test coverage. Returns a coverage report showing which requirements are tested and where the tests are located. This is the inverse of get_requirements_by_test.',
187
+ name: "get_tests_by_requirement",
188
+ description: "Show which requirements from a requirements file have test coverage. Returns a coverage report showing which requirements are tested and where the tests are located. This is the inverse of get_requirements_by_test.",
201
189
  inputSchema: {
202
- type: 'object',
190
+ type: "object",
203
191
  properties: {
204
192
  requirementsFile: {
205
- type: 'string',
193
+ type: "string",
206
194
  description: 'Path to the requirements file (e.g., ".requirements/auth.requirements.md")',
207
195
  },
208
196
  projectId: {
209
- type: 'string',
210
- description: 'Optional: Specify which project to search (required when multiple projects exist)',
197
+ type: "string",
198
+ description: "Optional: Specify which project to search (required when multiple projects exist)",
211
199
  },
212
200
  },
213
- required: ['requirementsFile'],
201
+ required: ["requirementsFile"],
214
202
  },
215
203
  },
216
204
  {
217
- name: 'get_requirement_coverage',
218
- description: 'Get test coverage information for a specific requirement from dot•requirements cloud. Shows when the requirement was last tested, on which branch, and in which test file. Requires project to be linked to cloud (run `dotrequirements link`).',
205
+ name: "report_coverage",
206
+ description: "Display test coverage for the project's requirements. Defaults to local source (most recent test run on this machine, requires `dotrequirements harness prepare` to have run); set source to cloud to query the dot•requirements cloud-persisted record (requires project to be linked via `dotrequirements link`). Optional requirementKey scopes to a single requirement; branch / sinceTimestamp filter cloud-source results.",
219
207
  inputSchema: {
220
- type: 'object',
208
+ type: "object",
221
209
  properties: {
222
- requirementKey: {
223
- type: 'string',
224
- description: 'The requirement key (e.g., "REQ-123", "AUTH-LOGIN")',
210
+ source: {
211
+ type: "string",
212
+ enum: ["local", "cloud"],
213
+ description: "Where to read coverage from (default: local)",
225
214
  },
226
- projectId: {
227
- type: 'string',
228
- description: 'Optional: Specify which project to use (required when multiple projects exist)',
215
+ requirementKey: {
216
+ type: "string",
217
+ description: 'Optional: scope to a single requirement (e.g., "REQ-123"). For local source, also includes that requirement\'s children.',
229
218
  },
230
- },
231
- required: ['requirementKey'],
232
- },
233
- },
234
- {
235
- name: 'get_project_coverage_summary',
236
- description: 'Get a summary of test coverage for all requirements in the project from dot•requirements cloud. Shows which requirements have been tested and which haven\'t. Optionally filter by branch or time range. Requires project to be linked to cloud (run `dotrequirements link`).',
237
- inputSchema: {
238
- type: 'object',
239
- properties: {
240
219
  branch: {
241
- type: 'string',
242
- description: 'Optional: Filter coverage to a specific git branch (e.g., "main")',
220
+ type: "string",
221
+ description: 'Cloud-only: filter coverage to a specific git branch (e.g., "main")',
243
222
  },
244
223
  sinceTimestamp: {
245
- type: 'number',
246
- description: 'Optional: Only show coverage since this timestamp (milliseconds since epoch)',
224
+ type: "number",
225
+ description: "Cloud-only: only include coverage recorded after this timestamp (milliseconds since epoch)",
247
226
  },
248
227
  projectId: {
249
- type: 'string',
250
- description: 'Optional: Specify which project to use (required when multiple projects exist)',
228
+ type: "string",
229
+ description: "Optional: specify which project to use (required when multiple projects exist)",
251
230
  },
252
231
  },
253
232
  required: [],
254
233
  },
255
234
  },
256
235
  {
257
- name: 'create_requirement_document',
258
- description: 'Returns a well-formatted Markdown template that demonstrates the requirements file format. Use this to understand the format before creating requirements files. AI should use this template as a reference, then use filesystem tools (Read/Write) to create actual files.',
236
+ name: "create_requirement_document",
237
+ description: "Returns a well-formatted Markdown template that demonstrates the requirements file format. Use this to understand the format before creating requirements files. AI should use this template as a reference, then use filesystem tools (Read/Write) to create actual files.",
259
238
  inputSchema: {
260
- type: 'object',
239
+ type: "object",
261
240
  properties: {
262
241
  filePath: {
263
- type: 'string',
242
+ type: "string",
264
243
  description: 'Optional: Suggested file path for documentation purposes (e.g., ".requirements/auth.requirements.md")',
265
244
  },
266
245
  },
@@ -268,97 +247,97 @@ const tools = [
268
247
  },
269
248
  },
270
249
  {
271
- name: 'validate_requirements',
272
- description: 'Validate a requirements Markdown file without pushing to cloud. Checks schema validity and returns detailed error messages. Works offline (no network/auth required). Use this to verify files before pushing.',
250
+ name: "validate_requirements",
251
+ description: "Validate a requirements Markdown file's schema. Returns detailed error messages on syntax problems. Works offline (no network/auth required). Use this to verify files before pushing.",
273
252
  inputSchema: {
274
- type: 'object',
253
+ type: "object",
275
254
  properties: {
276
255
  filePath: {
277
- type: 'string',
256
+ type: "string",
278
257
  description: 'Path to the Markdown file to validate (e.g., ".requirements/auth.requirements.md")',
279
258
  },
280
259
  },
281
- required: ['filePath'],
260
+ required: ["filePath"],
282
261
  },
283
262
  },
284
263
  {
285
- name: 'push_requirements',
286
- description: 'Push local requirements from .requirements/ directory to dot•requirements cloud. First call returns diff summary for user review. Second call with confirmed=true executes the push. Requires project to be linked to cloud (run `dotrequirements link`).',
264
+ name: "push_requirements",
265
+ description: "Push local requirements from .requirements/ directory to dot•requirements cloud. First call returns diff summary for user review. Second call with confirmed=true executes the push. Requires project to be linked to cloud (run `dotrequirements link`).",
287
266
  inputSchema: {
288
- type: 'object',
267
+ type: "object",
289
268
  properties: {
290
269
  filePath: {
291
- type: 'string',
270
+ type: "string",
292
271
  description: 'Optional: Push specific file only (e.g., ".requirements/auth.requirements.md"). If omitted, pushes all files.',
293
272
  },
294
273
  confirmed: {
295
- type: 'boolean',
296
- description: 'Set to true to execute the push after reviewing the diff. First call should omit this.',
274
+ type: "boolean",
275
+ description: "Set to true to execute the push after reviewing the diff. First call should omit this.",
297
276
  },
298
277
  projectId: {
299
- type: 'string',
300
- description: 'Optional: Specify which project to use (required when multiple projects exist)',
278
+ type: "string",
279
+ description: "Optional: Specify which project to use (required when multiple projects exist)",
301
280
  },
302
281
  },
303
282
  required: [],
304
283
  },
305
284
  },
306
285
  {
307
- name: 'style_check',
308
- description: 'Check requirements files or test files for style issues and best practices. Uses AI to provide actionable feedback on writing style, clarity, and conventions. Supports requirements files (*.requirements.md) and test files (*.test.*, *.spec.*). For requirements files, you can optionally specify requirement keys to check only those requirements instead of the entire file. Requires project to be linked to cloud (run `dotrequirements link`).',
286
+ name: "style_check",
287
+ description: "Check requirements files or test files for style issues and best practices. Uses AI to provide actionable feedback on writing style, clarity, and conventions. Supports requirements files (*.requirements.md) and test files (*.test.*, *.spec.*). For requirements files, you can optionally specify requirement keys to check only those requirements instead of the entire file. Requires project to be linked to cloud (run `dotrequirements link`).",
309
288
  inputSchema: {
310
- type: 'object',
289
+ type: "object",
311
290
  properties: {
312
291
  filePath: {
313
- type: 'string',
292
+ type: "string",
314
293
  description: 'Path to the file to check (e.g., ".requirements/auth.requirements.md" or "src/auth.test.ts")',
315
294
  },
316
295
  requirementKeys: {
317
- type: 'array',
318
- items: { type: 'string' },
296
+ type: "array",
297
+ items: { type: "string" },
319
298
  description: 'Optional: Array of requirement keys to check (e.g., ["AUTH-1", "AUTH-2"]). Only valid for requirements files (*.requirements.md). When provided, only these requirements are checked instead of the entire file.',
320
299
  },
321
300
  model: {
322
- type: 'string',
301
+ type: "string",
323
302
  description: 'Optional: AI model to use for style checking (default: "anthropic/claude-haiku-4.5"). Supported models: "anthropic/claude-haiku-4.5", "google/gemini-3-flash"',
324
303
  },
325
304
  },
326
- required: ['filePath'],
305
+ required: ["filePath"],
327
306
  },
328
307
  },
329
308
  {
330
- name: 'review_test',
331
- description: 'Comprehensively review a test file for both style and semantic correctness. Checks if tests actually validate what the requirements specify (not just style). Loads referenced requirements and validates that test setup, actions, and assertions match requirement preconditions, triggers, and outcomes. Requires project to be linked to cloud (run `dotrequirements link`).',
309
+ name: "review_test",
310
+ description: "Comprehensively review a test file for both style and semantic correctness. Checks if tests actually validate what the requirements specify (not just style). Loads referenced requirements and validates that test setup, actions, and assertions match requirement preconditions, triggers, and outcomes. Requires project to be linked to cloud (run `dotrequirements link`).",
332
311
  inputSchema: {
333
- type: 'object',
312
+ type: "object",
334
313
  properties: {
335
314
  testFilePath: {
336
- type: 'string',
315
+ type: "string",
337
316
  description: 'Path to the test file to review (e.g., "src/auth.test.ts")',
338
317
  },
339
318
  projectId: {
340
- type: 'string',
341
- description: 'Optional: Specify which project to use (required when multiple projects exist)',
319
+ type: "string",
320
+ description: "Optional: Specify which project to use (required when multiple projects exist)",
342
321
  },
343
322
  },
344
- required: ['testFilePath'],
323
+ required: ["testFilePath"],
345
324
  },
346
325
  },
347
326
  ];
348
327
  // Prompt definitions
349
328
  const prompts = [
350
329
  {
351
- name: 'capture-requirements',
352
- description: 'Guide the user through capturing requirements for a new feature before implementation',
330
+ name: "capture-requirements",
331
+ description: "Guide the user through capturing requirements for a new feature before implementation",
353
332
  },
354
333
  {
355
- name: 'write-tests',
356
- description: 'Guide writing tests that reference and validate requirements',
334
+ name: "write-tests",
335
+ description: "Guide writing tests that reference and validate requirements",
357
336
  },
358
337
  ];
359
338
  // Create server (exported for testing with InMemoryTransport)
360
339
  export const server = new Server({
361
- name: 'dotrequirements',
340
+ name: "dotrequirements",
362
341
  version: VERSION,
363
342
  }, {
364
343
  capabilities: {
@@ -377,13 +356,13 @@ server.setRequestHandler(ListPromptsRequestSchema, async () => {
377
356
  // Handle get prompt
378
357
  server.setRequestHandler(GetPromptRequestSchema, async (request) => {
379
358
  const { name } = request.params;
380
- if (name === 'capture-requirements') {
359
+ if (name === "capture-requirements") {
381
360
  return {
382
361
  messages: [
383
362
  {
384
- role: 'user',
363
+ role: "user",
385
364
  content: {
386
- type: 'text',
365
+ type: "text",
387
366
  text: `# Capture Requirements for New Feature
388
367
 
389
368
  Let's document what this feature should do before building it.
@@ -431,13 +410,13 @@ After capturing requirements:
431
410
  ],
432
411
  };
433
412
  }
434
- if (name === 'write-tests') {
413
+ if (name === "write-tests") {
435
414
  return {
436
415
  messages: [
437
416
  {
438
- role: 'user',
417
+ role: "user",
439
418
  content: {
440
- type: 'text',
419
+ type: "text",
441
420
  text: `# Write Tests for Requirements
442
421
 
443
422
  Let's write tests that validate the requirements.
@@ -535,7 +514,7 @@ After writing tests:
535
514
 
536
515
  - \`get_requirement\` - Get requirement tree with existing coverage
537
516
  - \`get_requirements_by_test\` - See requirements referenced in a test file
538
- - \`list_untested_requirements\` - Find requirements without tests
517
+ - \`list_requirements\` (with \`untested: true\`) - Find requirements without tests
539
518
  - \`review_test\` - Validate test actually checks what requirement specifies (run after writing tests)`,
540
519
  },
541
520
  },
@@ -559,39 +538,38 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
559
538
  };
560
539
  try {
561
540
  switch (name) {
562
- case 'debug_mcp_environment':
563
- return handleDebugMcpEnvironment(args, handlerContext);
564
- case 'search_requirements':
541
+ case "debug_mcp_environment":
542
+ return handleDebugMcpEnvironment({}, handlerContext);
543
+ case "search_requirements":
565
544
  return handleSearchRequirements(args, handlerContext);
566
- case 'get_requirement':
545
+ case "get_requirement":
567
546
  return handleGetRequirement(args, handlerContext);
568
- case 'list_untested_requirements':
569
- return handleListUntestedRequirements(args, handlerContext);
570
- case 'list_all_requirements':
571
- return handleListAllRequirements(args, handlerContext);
572
- case 'get_requirements_by_test':
547
+ case "list_requirements":
548
+ return handleList(args, handlerContext);
549
+ case "get_requirements_by_test":
573
550
  return handleGetRequirementsByTest(args, handlerContext);
574
- case 'get_tests_by_requirement':
551
+ case "get_tests_by_requirement":
575
552
  return handleGetTestsByRequirement(args, handlerContext);
576
- case 'get_requirement_coverage':
577
- return handleGetRequirementCoverage(args, handlerContext);
578
- case 'get_project_coverage_summary':
579
- return handleGetProjectCoverageSummary(args, handlerContext);
580
- case 'create_requirement_document':
553
+ case "report_coverage":
554
+ return handleReport(args, handlerContext);
555
+ case "create_requirement_document":
581
556
  return handleCreateRequirementDocument(args, handlerContext);
582
- case 'validate_requirements':
557
+ case "validate_requirements":
583
558
  return handleValidateRequirements(args, handlerContext);
584
- case 'push_requirements':
559
+ case "push_requirements":
585
560
  return handlePushRequirements(args, handlerContext);
586
- case 'style_check':
587
- return handleStyleCheck(args, handlerContext, { useEnvAuth: USE_ENV_AUTH, apiBaseUrl: process.env.DOTREQUIREMENTS_API_URL });
588
- case 'review_test':
561
+ case "style_check":
562
+ return handleStyleCheck(args, handlerContext, {
563
+ useEnvAuth: USE_ENV_AUTH,
564
+ apiBaseUrl: process.env.DOTREQUIREMENTS_API_URL,
565
+ });
566
+ case "review_test":
589
567
  return handleReviewTest(args, handlerContext, { apiBaseUrl: process.env.DOTREQUIREMENTS_API_URL });
590
568
  default:
591
569
  return {
592
570
  content: [
593
571
  {
594
- type: 'text',
572
+ type: "text",
595
573
  text: `Unknown tool: ${name}`,
596
574
  },
597
575
  ],
@@ -603,7 +581,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
603
581
  return {
604
582
  content: [
605
583
  {
606
- type: 'text',
584
+ type: "text",
607
585
  text: `Error: ${error instanceof Error ? error.message : String(error)}`,
608
586
  },
609
587
  ],
@@ -615,10 +593,10 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
615
593
  export async function main() {
616
594
  const transport = new StdioServerTransport();
617
595
  await server.connect(transport);
618
- console.error('dot•requirements MCP server running');
619
- console.error('WORKSPACE_ROOT:', WORKSPACE_ROOT);
620
- console.error('process.cwd():', process.cwd());
621
- console.error('REQUIREMENTS_DIR env:', process.env.REQUIREMENTS_DIR);
596
+ console.error("dot•requirements MCP server running");
597
+ console.error("WORKSPACE_ROOT:", WORKSPACE_ROOT);
598
+ console.error("process.cwd():", process.cwd());
599
+ console.error("REQUIREMENTS_DIR env:", process.env.REQUIREMENTS_DIR);
622
600
  }
623
601
  // Only run when executed directly, not when imported (enables InMemoryTransport testing)
624
602
  if (import.meta.url === `file://${process.argv[1]}`) {
@@ -1,5 +1,5 @@
1
- import { type RequirementNode, type Metadata } from '../schema/index.js';
2
- import type { FlattenedRequirement } from './types.js';
1
+ import { type Metadata, type RequirementNode } from "../schema/index.js";
2
+ import type { FlattenedRequirement } from "./types.js";
3
3
  /**
4
4
  * Parsed requirements file
5
5
  */