@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
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,7 +32,7 @@ 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');
35
+ const USE_ENV_AUTH = process.argv.includes("--auth-from-env");
36
36
  let cachedDiscoveryResult = null;
37
37
  // Requirements are loaded fresh on every call. A long-lived in-memory cache
38
38
  // silently served stale data when .requirements/*.md files were created or
@@ -45,13 +45,13 @@ async function getRequirements(projectId) {
45
45
  return flattened;
46
46
  }
47
47
  async function getProjectFromDiscovery(projectId) {
48
- const { isConfiguredProject } = await import('../utils/project-discovery.js');
48
+ const { isConfiguredProject } = await import("../utils/project-discovery.js");
49
49
  // If --auth-from-env flag is set, use credentials from environment variables
50
50
  // This is the explicit opt-in for CI/CD environments
51
51
  if (USE_ENV_AUTH) {
52
52
  const envCredentials = getCredentialsFromEnv();
53
53
  if (!envCredentials) {
54
- 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");
55
55
  }
56
56
  // Return a synthetic project using env credentials and workspace root
57
57
  return {
@@ -64,7 +64,7 @@ async function getProjectFromDiscovery(projectId) {
64
64
  if (PROJECT_PATHS.size > 0) {
65
65
  const projects = [];
66
66
  // Validate all env var projects
67
- for (const [id, path] of PROJECT_PATHS.entries()) {
67
+ for (const [, path] of PROJECT_PATHS.entries()) {
68
68
  const project = isConfiguredProject(path);
69
69
  if (project) {
70
70
  projects.push(project);
@@ -73,15 +73,15 @@ async function getProjectFromDiscovery(projectId) {
73
73
  // Build discovery result from env var projects
74
74
  if (projects.length === 0) {
75
75
  cachedDiscoveryResult = {
76
- type: 'none',
77
- message: 'No valid dotrequirements projects found in PROJ_* environment variables',
76
+ type: "none",
77
+ message: "No valid dotrequirements projects found in PROJ_* environment variables",
78
78
  };
79
79
  }
80
80
  else if (projects.length === 1) {
81
- cachedDiscoveryResult = { type: 'single', project: projects[0] };
81
+ cachedDiscoveryResult = { type: "single", project: projects[0] };
82
82
  }
83
83
  else {
84
- cachedDiscoveryResult = { type: 'multiple', projects };
84
+ cachedDiscoveryResult = { type: "multiple", projects };
85
85
  }
86
86
  return resolveProject(cachedDiscoveryResult, projectId);
87
87
  }
@@ -99,166 +99,147 @@ export function invalidateCache() {
99
99
  // Tool definitions
100
100
  const tools = [
101
101
  {
102
- name: 'debug_mcp_environment',
103
- 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.)",
104
104
  inputSchema: {
105
- type: 'object',
105
+ type: "object",
106
106
  properties: {},
107
107
  required: [],
108
108
  },
109
109
  },
110
110
  {
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.',
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.",
113
113
  inputSchema: {
114
- type: 'object',
114
+ type: "object",
115
115
  properties: {
116
116
  query: {
117
- type: 'string',
118
- 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",
119
119
  },
120
120
  useRegex: {
121
- type: 'boolean',
122
- 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)",
123
123
  },
124
124
  projectId: {
125
- type: 'string',
126
- 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)",
127
127
  },
128
128
  },
129
- required: ['query'],
129
+ required: ["query"],
130
130
  },
131
131
  },
132
132
  {
133
- name: 'get_requirement',
133
+ name: "get_requirement",
134
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.',
135
135
  inputSchema: {
136
- type: 'object',
136
+ type: "object",
137
137
  properties: {
138
138
  id: {
139
- type: 'string',
139
+ type: "string",
140
140
  description: 'The requirement ID or path (e.g., "REQ-123" for root, "REQ-123.0" for child)',
141
141
  },
142
142
  projectId: {
143
- type: 'string',
144
- 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)",
145
145
  },
146
146
  },
147
- required: ['id'],
147
+ required: ["id"],
148
148
  },
149
149
  },
150
150
  {
151
- name: 'list_untested_requirements',
152
- 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.",
153
153
  inputSchema: {
154
- type: 'object',
154
+ type: "object",
155
155
  properties: {
156
- projectId: {
157
- type: 'string',
158
- 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)",
159
159
  },
160
- },
161
- required: [],
162
- },
163
- },
164
- {
165
- name: 'list_all_requirements',
166
- description: 'List all requirements in the workspace. Returns a summary of all requirements with their IDs, labels, and content.',
167
- inputSchema: {
168
- type: 'object',
169
- properties: {
170
160
  projectId: {
171
- type: 'string',
172
- 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)",
173
163
  },
174
164
  },
175
165
  required: [],
176
166
  },
177
167
  },
178
168
  {
179
- name: 'get_requirements_by_test',
180
- 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.",
181
171
  inputSchema: {
182
- type: 'object',
172
+ type: "object",
183
173
  properties: {
184
174
  testFile: {
185
- type: 'string',
186
- description: 'Path to the test file to analyze',
175
+ type: "string",
176
+ description: "Path to the test file to analyze",
187
177
  },
188
178
  projectId: {
189
- type: 'string',
190
- 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)",
191
181
  },
192
182
  },
193
- required: ['testFile'],
183
+ required: ["testFile"],
194
184
  },
195
185
  },
196
186
  {
197
- name: 'get_tests_by_requirement',
198
- 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.",
199
189
  inputSchema: {
200
- type: 'object',
190
+ type: "object",
201
191
  properties: {
202
192
  requirementsFile: {
203
- type: 'string',
193
+ type: "string",
204
194
  description: 'Path to the requirements file (e.g., ".requirements/auth.requirements.md")',
205
195
  },
206
196
  projectId: {
207
- type: 'string',
208
- 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)",
209
199
  },
210
200
  },
211
- required: ['requirementsFile'],
201
+ required: ["requirementsFile"],
212
202
  },
213
203
  },
214
204
  {
215
- name: 'get_requirement_coverage',
216
- 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.",
217
207
  inputSchema: {
218
- type: 'object',
208
+ type: "object",
219
209
  properties: {
220
- requirementKey: {
221
- type: 'string',
222
- 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)",
223
214
  },
224
- projectId: {
225
- type: 'string',
226
- 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.',
227
218
  },
228
- },
229
- required: ['requirementKey'],
230
- },
231
- },
232
- {
233
- name: 'get_project_coverage_summary',
234
- 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`).',
235
- inputSchema: {
236
- type: 'object',
237
- properties: {
238
219
  branch: {
239
- type: 'string',
240
- 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")',
241
222
  },
242
223
  sinceTimestamp: {
243
- type: 'number',
244
- 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)",
245
226
  },
246
227
  projectId: {
247
- type: 'string',
248
- 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)",
249
230
  },
250
231
  },
251
232
  required: [],
252
233
  },
253
234
  },
254
235
  {
255
- name: 'create_requirement_document',
256
- 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.",
257
238
  inputSchema: {
258
- type: 'object',
239
+ type: "object",
259
240
  properties: {
260
241
  filePath: {
261
- type: 'string',
242
+ type: "string",
262
243
  description: 'Optional: Suggested file path for documentation purposes (e.g., ".requirements/auth.requirements.md")',
263
244
  },
264
245
  },
@@ -266,97 +247,97 @@ const tools = [
266
247
  },
267
248
  },
268
249
  {
269
- name: 'validate_requirements',
270
- 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.",
271
252
  inputSchema: {
272
- type: 'object',
253
+ type: "object",
273
254
  properties: {
274
255
  filePath: {
275
- type: 'string',
256
+ type: "string",
276
257
  description: 'Path to the Markdown file to validate (e.g., ".requirements/auth.requirements.md")',
277
258
  },
278
259
  },
279
- required: ['filePath'],
260
+ required: ["filePath"],
280
261
  },
281
262
  },
282
263
  {
283
- name: 'push_requirements',
284
- 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`).",
285
266
  inputSchema: {
286
- type: 'object',
267
+ type: "object",
287
268
  properties: {
288
269
  filePath: {
289
- type: 'string',
270
+ type: "string",
290
271
  description: 'Optional: Push specific file only (e.g., ".requirements/auth.requirements.md"). If omitted, pushes all files.',
291
272
  },
292
273
  confirmed: {
293
- type: 'boolean',
294
- 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.",
295
276
  },
296
277
  projectId: {
297
- type: 'string',
298
- 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)",
299
280
  },
300
281
  },
301
282
  required: [],
302
283
  },
303
284
  },
304
285
  {
305
- name: 'style_check',
306
- 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`).",
307
288
  inputSchema: {
308
- type: 'object',
289
+ type: "object",
309
290
  properties: {
310
291
  filePath: {
311
- type: 'string',
292
+ type: "string",
312
293
  description: 'Path to the file to check (e.g., ".requirements/auth.requirements.md" or "src/auth.test.ts")',
313
294
  },
314
295
  requirementKeys: {
315
- type: 'array',
316
- items: { type: 'string' },
296
+ type: "array",
297
+ items: { type: "string" },
317
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.',
318
299
  },
319
300
  model: {
320
- type: 'string',
301
+ type: "string",
321
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"',
322
303
  },
323
304
  },
324
- required: ['filePath'],
305
+ required: ["filePath"],
325
306
  },
326
307
  },
327
308
  {
328
- name: 'review_test',
329
- 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`).",
330
311
  inputSchema: {
331
- type: 'object',
312
+ type: "object",
332
313
  properties: {
333
314
  testFilePath: {
334
- type: 'string',
315
+ type: "string",
335
316
  description: 'Path to the test file to review (e.g., "src/auth.test.ts")',
336
317
  },
337
318
  projectId: {
338
- type: 'string',
339
- 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)",
340
321
  },
341
322
  },
342
- required: ['testFilePath'],
323
+ required: ["testFilePath"],
343
324
  },
344
325
  },
345
326
  ];
346
327
  // Prompt definitions
347
328
  const prompts = [
348
329
  {
349
- name: 'capture-requirements',
350
- 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",
351
332
  },
352
333
  {
353
- name: 'write-tests',
354
- description: 'Guide writing tests that reference and validate requirements',
334
+ name: "write-tests",
335
+ description: "Guide writing tests that reference and validate requirements",
355
336
  },
356
337
  ];
357
338
  // Create server (exported for testing with InMemoryTransport)
358
339
  export const server = new Server({
359
- name: 'dotrequirements',
340
+ name: "dotrequirements",
360
341
  version: VERSION,
361
342
  }, {
362
343
  capabilities: {
@@ -375,13 +356,13 @@ server.setRequestHandler(ListPromptsRequestSchema, async () => {
375
356
  // Handle get prompt
376
357
  server.setRequestHandler(GetPromptRequestSchema, async (request) => {
377
358
  const { name } = request.params;
378
- if (name === 'capture-requirements') {
359
+ if (name === "capture-requirements") {
379
360
  return {
380
361
  messages: [
381
362
  {
382
- role: 'user',
363
+ role: "user",
383
364
  content: {
384
- type: 'text',
365
+ type: "text",
385
366
  text: `# Capture Requirements for New Feature
386
367
 
387
368
  Let's document what this feature should do before building it.
@@ -429,13 +410,13 @@ After capturing requirements:
429
410
  ],
430
411
  };
431
412
  }
432
- if (name === 'write-tests') {
413
+ if (name === "write-tests") {
433
414
  return {
434
415
  messages: [
435
416
  {
436
- role: 'user',
417
+ role: "user",
437
418
  content: {
438
- type: 'text',
419
+ type: "text",
439
420
  text: `# Write Tests for Requirements
440
421
 
441
422
  Let's write tests that validate the requirements.
@@ -533,7 +514,7 @@ After writing tests:
533
514
 
534
515
  - \`get_requirement\` - Get requirement tree with existing coverage
535
516
  - \`get_requirements_by_test\` - See requirements referenced in a test file
536
- - \`list_untested_requirements\` - Find requirements without tests
517
+ - \`list_requirements\` (with \`untested: true\`) - Find requirements without tests
537
518
  - \`review_test\` - Validate test actually checks what requirement specifies (run after writing tests)`,
538
519
  },
539
520
  },
@@ -557,39 +538,38 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
557
538
  };
558
539
  try {
559
540
  switch (name) {
560
- case 'debug_mcp_environment':
561
- return handleDebugMcpEnvironment(args, handlerContext);
562
- case 'search_requirements':
541
+ case "debug_mcp_environment":
542
+ return handleDebugMcpEnvironment({}, handlerContext);
543
+ case "search_requirements":
563
544
  return handleSearchRequirements(args, handlerContext);
564
- case 'get_requirement':
545
+ case "get_requirement":
565
546
  return handleGetRequirement(args, handlerContext);
566
- case 'list_untested_requirements':
567
- return handleListUntestedRequirements(args, handlerContext);
568
- case 'list_all_requirements':
569
- return handleListAllRequirements(args, handlerContext);
570
- case 'get_requirements_by_test':
547
+ case "list_requirements":
548
+ return handleList(args, handlerContext);
549
+ case "get_requirements_by_test":
571
550
  return handleGetRequirementsByTest(args, handlerContext);
572
- case 'get_tests_by_requirement':
551
+ case "get_tests_by_requirement":
573
552
  return handleGetTestsByRequirement(args, handlerContext);
574
- case 'get_requirement_coverage':
575
- return handleGetRequirementCoverage(args, handlerContext);
576
- case 'get_project_coverage_summary':
577
- return handleGetProjectCoverageSummary(args, handlerContext);
578
- case 'create_requirement_document':
553
+ case "report_coverage":
554
+ return handleReport(args, handlerContext);
555
+ case "create_requirement_document":
579
556
  return handleCreateRequirementDocument(args, handlerContext);
580
- case 'validate_requirements':
557
+ case "validate_requirements":
581
558
  return handleValidateRequirements(args, handlerContext);
582
- case 'push_requirements':
559
+ case "push_requirements":
583
560
  return handlePushRequirements(args, handlerContext);
584
- case 'style_check':
585
- return handleStyleCheck(args, handlerContext, { useEnvAuth: USE_ENV_AUTH, apiBaseUrl: process.env.DOTREQUIREMENTS_API_URL });
586
- 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":
587
567
  return handleReviewTest(args, handlerContext, { apiBaseUrl: process.env.DOTREQUIREMENTS_API_URL });
588
568
  default:
589
569
  return {
590
570
  content: [
591
571
  {
592
- type: 'text',
572
+ type: "text",
593
573
  text: `Unknown tool: ${name}`,
594
574
  },
595
575
  ],
@@ -601,7 +581,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
601
581
  return {
602
582
  content: [
603
583
  {
604
- type: 'text',
584
+ type: "text",
605
585
  text: `Error: ${error instanceof Error ? error.message : String(error)}`,
606
586
  },
607
587
  ],
@@ -613,10 +593,10 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
613
593
  export async function main() {
614
594
  const transport = new StdioServerTransport();
615
595
  await server.connect(transport);
616
- console.error('dot•requirements MCP server running');
617
- console.error('WORKSPACE_ROOT:', WORKSPACE_ROOT);
618
- console.error('process.cwd():', process.cwd());
619
- 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);
620
600
  }
621
601
  // Only run when executed directly, not when imported (enables InMemoryTransport testing)
622
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
  */