@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
@@ -0,0 +1,92 @@
1
+ /**
2
+ * `dotrequirements codebase-to-spec present` subcommand.
3
+ *
4
+ * Writes the final spec to `.requirements/` and emits a pipeline summary.
5
+ *
6
+ * Requirements covered:
7
+ * - CTS-CLI-2: granular `present` subcommand
8
+ * - CTS-CLI-4: TTY-driven interactive/non-interactive selection
9
+ * - CTS-PRESENT-1..4
10
+ */
11
+ import { existsSync, writeFileSync } from "node:fs";
12
+ import { cachePaths } from "../../codebase-to-spec/cache.js";
13
+ import { ExitCode } from "../../codebase-to-spec/exit-codes.js";
14
+ import { detectMode } from "../../codebase-to-spec/interactive.js";
15
+ import { runPresent, } from "../../codebase-to-spec/present.js";
16
+ import { StdoutProgress } from "../../codebase-to-spec/progress.js";
17
+ import { buildPipelineSummary, renderSummaryText, } from "../../codebase-to-spec/summary.js";
18
+ import { findProjectRoot } from "../../utils/project-settings.js";
19
+ import { readFinalOutline } from "./plan-loop.js";
20
+ function resolveOverwritePolicy(isInteractive, options) {
21
+ if (options.overwrite && options.skipExisting) {
22
+ return { error: "--overwrite and --skip-existing are mutually exclusive." };
23
+ }
24
+ if (options.overwrite)
25
+ return "overwrite";
26
+ if (options.skipExisting)
27
+ return "skip-existing";
28
+ if (isInteractive)
29
+ return "prompt";
30
+ return "fail-fast";
31
+ }
32
+ export async function presentCommand(rawOptions = {}) {
33
+ const progress = new StdoutProgress();
34
+ const projectRoot = rawOptions.projectRoot ?? findProjectRoot(process.cwd()) ?? process.cwd();
35
+ const paths = cachePaths(projectRoot);
36
+ if (!existsSync(paths.outlineFinal)) {
37
+ process.stderr.write(`Missing outline at ${paths.outlineFinal}. Run \`dotrequirements cts plan-loop\` first.\n`);
38
+ process.exitCode = ExitCode.MissingInput;
39
+ return;
40
+ }
41
+ if (!existsSync(paths.specFinal)) {
42
+ process.stderr.write(`Missing final spec at ${paths.specFinal}. Run \`dotrequirements cts edit-loop\` first.\n`);
43
+ process.exitCode = ExitCode.MissingInput;
44
+ return;
45
+ }
46
+ const outline = readFinalOutline(projectRoot);
47
+ const { isInteractive } = detectMode(rawOptions.forceMode);
48
+ const policy = resolveOverwritePolicy(isInteractive, rawOptions);
49
+ if (typeof policy === "object") {
50
+ process.stderr.write(`${policy.error}\n`);
51
+ process.exitCode = ExitCode.InvalidFlags;
52
+ return;
53
+ }
54
+ progress.emit({
55
+ stage: "present",
56
+ step: "start",
57
+ message: `Writing final spec to .requirements/ (mode: ${isInteractive ? "interactive" : "non-interactive"}, policy: ${policy})`,
58
+ });
59
+ const result = await runPresent({
60
+ outline,
61
+ finalSpecPath: paths.specFinal,
62
+ projectRoot,
63
+ overwritePolicy: policy,
64
+ });
65
+ // Per-file outcome announcements.
66
+ for (const action of result.actions) {
67
+ progress.emit({
68
+ stage: "present",
69
+ step: action.action,
70
+ message: `${action.action}: ${action.path}`,
71
+ });
72
+ }
73
+ if (!result.allWritten) {
74
+ if (result.conflictPath) {
75
+ // fail-fast bailed before any write.
76
+ process.stderr.write(`Refusing to overwrite ${result.conflictPath}. Re-run with --overwrite or --skip-existing, or run in interactive mode.\n`);
77
+ process.exitCode = ExitCode.OverwriteRefused;
78
+ return;
79
+ }
80
+ // Other partial failures (validation, merge conflict, etc.).
81
+ process.exitCode = ExitCode.StageFailed;
82
+ }
83
+ // Emit the pipeline summary.
84
+ const summary = buildPipelineSummary({
85
+ outline,
86
+ paths,
87
+ outputPaths: result.outputPaths,
88
+ });
89
+ writeFileSync(paths.pipelineSummary, `${JSON.stringify(summary, null, 2)}\n`, "utf-8");
90
+ process.stdout.write(`\n${renderSummaryText(summary)}\n`);
91
+ }
92
+ //# sourceMappingURL=present.js.map
@@ -0,0 +1,20 @@
1
+ /**
2
+ * `dotrequirements codebase-to-spec run` subcommand.
3
+ *
4
+ * Chains the pipeline stages. Currently: pack → plan-loop. Subsequent
5
+ * increments will chain specify → compose → edit → present.
6
+ *
7
+ * Requirements covered (incrementally):
8
+ * - CTS-CLI-1: User can run the pipeline end-to-end with a single command
9
+ */
10
+ import { type PackOptions } from "./pack.js";
11
+ export interface RunOptions extends PackOptions {
12
+ maxTurns?: number;
13
+ model?: string;
14
+ concurrency?: number;
15
+ forceMode?: "interactive" | "non-interactive";
16
+ overwrite?: boolean;
17
+ skipExisting?: boolean;
18
+ }
19
+ export declare function runCommand(options?: RunOptions): Promise<void>;
20
+ //# sourceMappingURL=run.d.ts.map
@@ -0,0 +1,85 @@
1
+ /**
2
+ * `dotrequirements codebase-to-spec run` subcommand.
3
+ *
4
+ * Chains the pipeline stages. Currently: pack → plan-loop. Subsequent
5
+ * increments will chain specify → compose → edit → present.
6
+ *
7
+ * Requirements covered (incrementally):
8
+ * - CTS-CLI-1: User can run the pipeline end-to-end with a single command
9
+ */
10
+ import { ExitCode } from "../../codebase-to-spec/exit-codes.js";
11
+ import { composeCommand } from "./compose.js";
12
+ import { editLoopCommand } from "./edit-loop.js";
13
+ import { fanOutCommand } from "./fan-out.js";
14
+ import { packCommand } from "./pack.js";
15
+ import { planLoopCommand } from "./plan-loop.js";
16
+ import { presentCommand } from "./present.js";
17
+ export async function runCommand(options = {}) {
18
+ // Stage 1 — Pack
19
+ await packCommand(options);
20
+ if (process.exitCode && process.exitCode !== 0) {
21
+ return;
22
+ }
23
+ // Stage 2 — Plan + outline review loop
24
+ await planLoopCommand({
25
+ maxTurns: options.maxTurns,
26
+ model: options.model,
27
+ progress: options.progress,
28
+ projectRoot: options.projectRoot,
29
+ });
30
+ if (process.exitCode &&
31
+ process.exitCode !== 0 &&
32
+ process.exitCode !== ExitCode.MaxTurnsHit) {
33
+ return;
34
+ }
35
+ // Reset exit code from MaxTurnsHit so downstream stages can still proceed
36
+ // (we use the latest outline anyway per CTS-PLAN-6).
37
+ if (process.exitCode === ExitCode.MaxTurnsHit) {
38
+ process.exitCode = 0;
39
+ }
40
+ // Stage 3 — Specifier fan-out
41
+ await fanOutCommand({
42
+ concurrency: options.concurrency,
43
+ model: options.model,
44
+ projectRoot: options.projectRoot,
45
+ });
46
+ if (process.exitCode &&
47
+ process.exitCode !== 0 &&
48
+ process.exitCode !== ExitCode.StageFailed) {
49
+ return;
50
+ }
51
+ // StageFailed from fan-out means some specifiers failed; per CTS-SPEC-5 the
52
+ // pipeline continues. Other areas still produced partials.
53
+ if (process.exitCode === ExitCode.StageFailed) {
54
+ process.exitCode = 0;
55
+ }
56
+ // Stage 4 — Compose
57
+ await composeCommand({ projectRoot: options.projectRoot });
58
+ if (process.exitCode && process.exitCode !== 0) {
59
+ return;
60
+ }
61
+ // Stage 5 — Spec review + edit loop
62
+ await editLoopCommand({
63
+ maxTurns: options.maxTurns,
64
+ model: options.model,
65
+ projectRoot: options.projectRoot,
66
+ });
67
+ if (process.exitCode &&
68
+ process.exitCode !== 0 &&
69
+ process.exitCode !== ExitCode.MaxTurnsHit) {
70
+ return;
71
+ }
72
+ if (process.exitCode === ExitCode.MaxTurnsHit) {
73
+ process.exitCode = 0;
74
+ }
75
+ // Stage 6 — Present (write final spec to .requirements/ + emit summary)
76
+ await presentCommand({
77
+ forceMode: options.forceMode,
78
+ overwrite: options.overwrite,
79
+ skipExisting: options.skipExisting,
80
+ projectRoot: options.projectRoot,
81
+ });
82
+ // Present sets a non-zero exit code on overwrite refusal or validation
83
+ // failure; let it propagate.
84
+ }
85
+ //# sourceMappingURL=run.js.map
@@ -0,0 +1,20 @@
1
+ /**
2
+ * `dotrequirements codebase-to-spec skill-install` subcommand.
3
+ *
4
+ * Installs the codebase-to-spec SKILL.md into the host's skill directory.
5
+ * Defaults to the project's `.claude/skills/` (Claude Code convention);
6
+ * `--global` installs into `~/.claude/skills/`; `--target-dir <dir>` writes
7
+ * to a custom location for other hosts.
8
+ *
9
+ * Requirements covered:
10
+ * - CTS-CLI-2: granular subcommand
11
+ * - CTS-SKILL-1, CTS-SKILL-5: install the skill artifact in a host-agnostic way
12
+ */
13
+ export interface SkillInstallCmdOptions {
14
+ global?: boolean;
15
+ targetDir?: string;
16
+ overwrite?: boolean;
17
+ projectRoot?: string;
18
+ }
19
+ export declare function skillInstallCommand(options?: SkillInstallCmdOptions): Promise<void>;
20
+ //# sourceMappingURL=skill-install.d.ts.map
@@ -0,0 +1,51 @@
1
+ /**
2
+ * `dotrequirements codebase-to-spec skill-install` subcommand.
3
+ *
4
+ * Installs the codebase-to-spec SKILL.md into the host's skill directory.
5
+ * Defaults to the project's `.claude/skills/` (Claude Code convention);
6
+ * `--global` installs into `~/.claude/skills/`; `--target-dir <dir>` writes
7
+ * to a custom location for other hosts.
8
+ *
9
+ * Requirements covered:
10
+ * - CTS-CLI-2: granular subcommand
11
+ * - CTS-SKILL-1, CTS-SKILL-5: install the skill artifact in a host-agnostic way
12
+ */
13
+ import { ExitCode } from "../../codebase-to-spec/exit-codes.js";
14
+ import { installSkill, } from "../../codebase-to-spec/skill-install.js";
15
+ import { findProjectRoot } from "../../utils/project-settings.js";
16
+ export async function skillInstallCommand(options = {}) {
17
+ if (options.global && options.targetDir) {
18
+ process.stderr.write("--global and --target-dir cannot be combined. Pick one.\n");
19
+ process.exitCode = ExitCode.InvalidFlags;
20
+ return;
21
+ }
22
+ const scope = options.targetDir
23
+ ? "custom"
24
+ : options.global
25
+ ? "global"
26
+ : "project";
27
+ const projectRoot = options.projectRoot ?? findProjectRoot(process.cwd()) ?? process.cwd();
28
+ try {
29
+ const result = installSkill({
30
+ scope,
31
+ targetDir: options.targetDir,
32
+ projectRoot,
33
+ overwrite: options.overwrite,
34
+ });
35
+ if (result.installed && result.overwrote) {
36
+ process.stdout.write(`Replaced SKILL.md at ${result.installedPath}\n`);
37
+ }
38
+ else if (result.installed) {
39
+ process.stdout.write(`Installed SKILL.md at ${result.installedPath}\n`);
40
+ }
41
+ else {
42
+ process.stdout.write(`SKILL.md already up to date at ${result.installedPath}\n`);
43
+ }
44
+ process.stdout.write("Skill ready. In Claude Code, invoke it with `/codebase-to-spec` (or via natural language).\n");
45
+ }
46
+ catch (err) {
47
+ process.stderr.write(`${err instanceof Error ? err.message : String(err)}\n`);
48
+ process.exitCode = ExitCode.StageFailed;
49
+ }
50
+ }
51
+ //# sourceMappingURL=skill-install.js.map
@@ -0,0 +1,18 @@
1
+ /**
2
+ * `dotrequirements codebase-to-spec specify-area <name>` subcommand.
3
+ *
4
+ * Runs a single specifier for one named area from the cached outline. Useful
5
+ * for retrying a single failed area, or for scripting.
6
+ *
7
+ * Requirements covered:
8
+ * - CTS-CLI-2: granular `specify-area` subcommand
9
+ * - CTS-SPEC-1..4: per-area specifier behavior
10
+ */
11
+ export interface SpecifyAreaOptions {
12
+ model?: string;
13
+ /** Path to the CLI binary (defaults to `dotrequirements`). */
14
+ cliBinary?: string;
15
+ projectRoot?: string;
16
+ }
17
+ export declare function specifyAreaCommand(areaName: string, options?: SpecifyAreaOptions): Promise<void>;
18
+ //# sourceMappingURL=specify-area.d.ts.map
@@ -0,0 +1,82 @@
1
+ /**
2
+ * `dotrequirements codebase-to-spec specify-area <name>` subcommand.
3
+ *
4
+ * Runs a single specifier for one named area from the cached outline. Useful
5
+ * for retrying a single failed area, or for scripting.
6
+ *
7
+ * Requirements covered:
8
+ * - CTS-CLI-2: granular `specify-area` subcommand
9
+ * - CTS-SPEC-1..4: per-area specifier behavior
10
+ */
11
+ import { existsSync } from "node:fs";
12
+ import { cachePaths } from "../../codebase-to-spec/cache.js";
13
+ import { ExitCode } from "../../codebase-to-spec/exit-codes.js";
14
+ import { sanitizeAreaName } from "../../codebase-to-spec/fan-out.js";
15
+ import { StdoutProgress } from "../../codebase-to-spec/progress.js";
16
+ import { extractSlice } from "../../codebase-to-spec/slice.js";
17
+ import { runSpecifier } from "../../codebase-to-spec/specifier.js";
18
+ import { findProjectRoot } from "../../utils/project-settings.js";
19
+ import { readFinalOutline } from "./plan-loop.js";
20
+ export async function specifyAreaCommand(areaName, options = {}) {
21
+ const progress = new StdoutProgress();
22
+ const projectRoot = options.projectRoot ?? findProjectRoot(process.cwd()) ?? process.cwd();
23
+ const paths = cachePaths(projectRoot);
24
+ const cliBinary = options.cliBinary ?? "dotrequirements";
25
+ if (!existsSync(paths.outlineFinal)) {
26
+ process.stderr.write(`Missing outline at ${paths.outlineFinal}. Run \`dotrequirements cts plan-loop\` first.\n`);
27
+ process.exitCode = ExitCode.MissingInput;
28
+ return;
29
+ }
30
+ if (!existsSync(paths.source)) {
31
+ process.stderr.write(`Missing uncompressed pack at ${paths.source}. Run \`dotrequirements cts pack\` first.\n`);
32
+ process.exitCode = ExitCode.MissingInput;
33
+ return;
34
+ }
35
+ const outline = readFinalOutline(projectRoot);
36
+ const area = outline.areas.find((a) => a.name === areaName ||
37
+ a.prefix === areaName ||
38
+ sanitizeAreaName(a.name) === sanitizeAreaName(areaName));
39
+ if (!area) {
40
+ process.stderr.write(`No area named "${areaName}" in outline. Available areas:\n${outline.areas
41
+ .map((a) => ` - ${a.name} (prefix: ${a.prefix})`)
42
+ .join("\n")}\n`);
43
+ process.exitCode = ExitCode.MissingInput;
44
+ return;
45
+ }
46
+ const sanitized = sanitizeAreaName(area.name);
47
+ const slicePath = `${paths.partialsDir}/slice-${sanitized}.txt`;
48
+ const partialPath = paths.partial(sanitized);
49
+ progress.emit({
50
+ stage: "specify",
51
+ step: area.prefix,
52
+ message: `Extracting slice for ${area.name}`,
53
+ });
54
+ extractSlice(paths.source, slicePath, area.files);
55
+ progress.emit({
56
+ stage: "specify",
57
+ step: area.prefix,
58
+ message: `Running specifier for ${area.name}`,
59
+ });
60
+ const result = await runSpecifier({
61
+ outline,
62
+ area,
63
+ slicePath,
64
+ fullPackPath: paths.source,
65
+ partialPath,
66
+ validateCommand: `${cliBinary} cts validate`,
67
+ styleCheckCommand: `${cliBinary} cts style-check`,
68
+ addDirs: [paths.root],
69
+ model: options.model,
70
+ });
71
+ if (!result.wrotePartial) {
72
+ process.stderr.write(`Specifier for ${area.name} produced no partial (exit ${result.exitCode}).\n${result.stderr}\n`);
73
+ process.exitCode = ExitCode.StageFailed;
74
+ return;
75
+ }
76
+ progress.emit({
77
+ stage: "specify",
78
+ step: area.prefix,
79
+ message: `Done. Partial saved to ${partialPath} (${result.partialBytes} bytes)`,
80
+ });
81
+ }
82
+ //# sourceMappingURL=specify-area.js.map
@@ -0,0 +1,15 @@
1
+ /**
2
+ * `dotrequirements codebase-to-spec style-check <path>` subcommand.
3
+ *
4
+ * Invoked by specifier workers via Bash to get severity-categorized feedback
5
+ * on their own partial drafts. Stateless — fresh claude -p call.
6
+ *
7
+ * Requirements covered:
8
+ * - CTS-SPEC-3: local style-check tool runs offline without cloud credentials
9
+ * - CTS-CLI-2: granular subcommand
10
+ */
11
+ export interface StyleCheckCmdOptions {
12
+ model?: string;
13
+ }
14
+ export declare function styleCheckCommand(partialPath: string, options?: StyleCheckCmdOptions): Promise<void>;
15
+ //# sourceMappingURL=style-check.d.ts.map
@@ -0,0 +1,42 @@
1
+ /**
2
+ * `dotrequirements codebase-to-spec style-check <path>` subcommand.
3
+ *
4
+ * Invoked by specifier workers via Bash to get severity-categorized feedback
5
+ * on their own partial drafts. Stateless — fresh claude -p call.
6
+ *
7
+ * Requirements covered:
8
+ * - CTS-SPEC-3: local style-check tool runs offline without cloud credentials
9
+ * - CTS-CLI-2: granular subcommand
10
+ */
11
+ import { existsSync } from "node:fs";
12
+ import { resolve } from "node:path";
13
+ import { ExitCode } from "../../codebase-to-spec/exit-codes.js";
14
+ import { runStyleCheck } from "../../codebase-to-spec/style-check.js";
15
+ export async function styleCheckCommand(partialPath, options = {}) {
16
+ const absPath = resolve(partialPath);
17
+ if (!existsSync(absPath)) {
18
+ process.stderr.write(`File not found: ${partialPath}\n`);
19
+ process.exitCode = ExitCode.MissingInput;
20
+ return;
21
+ }
22
+ try {
23
+ const result = await runStyleCheck({
24
+ partialPath: absPath,
25
+ model: options.model,
26
+ });
27
+ if (result.exitCode !== 0) {
28
+ process.stderr.write(`style-check failed (exit ${result.exitCode})\n`);
29
+ process.exitCode = ExitCode.StageFailed;
30
+ return;
31
+ }
32
+ process.stdout.write(result.feedback);
33
+ if (!result.feedback.endsWith("\n")) {
34
+ process.stdout.write("\n");
35
+ }
36
+ }
37
+ catch (err) {
38
+ process.stderr.write(`style-check error: ${err instanceof Error ? err.message : String(err)}\n`);
39
+ process.exitCode = ExitCode.StageFailed;
40
+ }
41
+ }
42
+ //# sourceMappingURL=style-check.js.map
@@ -0,0 +1,18 @@
1
+ /**
2
+ * `dotrequirements codebase-to-spec validate <partial-path>` subcommand.
3
+ *
4
+ * Invoked by specifier workers via Bash to get a deterministic syntax check
5
+ * on their own partial drafts before they run the AI-driven style-check.
6
+ * Mirrors the validate-then-style-check ordering documented in CLAUDE.md.
7
+ *
8
+ * Exit code is non-zero on validation failure so the specifier can detect
9
+ * the failure programmatically if it wants to; the formatted feedback is
10
+ * always written to stdout so the agent can read it via Bash output.
11
+ *
12
+ * Requirements covered:
13
+ * - CTS-SPEC-3: Specifier runs a local schema validator on its draft,
14
+ * applying any reported errors as MUST FIX before style-check.
15
+ * - CTS-CLI-2: granular subcommand
16
+ */
17
+ export declare function validateCommand(partialPath: string): Promise<void>;
18
+ //# sourceMappingURL=validate.d.ts.map
@@ -0,0 +1,38 @@
1
+ /**
2
+ * `dotrequirements codebase-to-spec validate <partial-path>` subcommand.
3
+ *
4
+ * Invoked by specifier workers via Bash to get a deterministic syntax check
5
+ * on their own partial drafts before they run the AI-driven style-check.
6
+ * Mirrors the validate-then-style-check ordering documented in CLAUDE.md.
7
+ *
8
+ * Exit code is non-zero on validation failure so the specifier can detect
9
+ * the failure programmatically if it wants to; the formatted feedback is
10
+ * always written to stdout so the agent can read it via Bash output.
11
+ *
12
+ * Requirements covered:
13
+ * - CTS-SPEC-3: Specifier runs a local schema validator on its draft,
14
+ * applying any reported errors as MUST FIX before style-check.
15
+ * - CTS-CLI-2: granular subcommand
16
+ */
17
+ import { existsSync } from "node:fs";
18
+ import { resolve } from "node:path";
19
+ import { ExitCode } from "../../codebase-to-spec/exit-codes.js";
20
+ import { formatValidateFeedback, runValidate, } from "../../codebase-to-spec/validate.js";
21
+ export async function validateCommand(partialPath) {
22
+ const absPath = resolve(partialPath);
23
+ if (!existsSync(absPath)) {
24
+ process.stderr.write(`File not found: ${partialPath}\n`);
25
+ process.exitCode = ExitCode.MissingInput;
26
+ return;
27
+ }
28
+ const result = runValidate({ partialPath: absPath });
29
+ const feedback = formatValidateFeedback(result);
30
+ process.stdout.write(feedback);
31
+ if (!feedback.endsWith("\n")) {
32
+ process.stdout.write("\n");
33
+ }
34
+ if (!result.ok) {
35
+ process.exitCode = ExitCode.StageFailed;
36
+ }
37
+ }
38
+ //# sourceMappingURL=validate.js.map
@@ -0,0 +1,2 @@
1
+ export declare function createRequirementDocumentCommand(filePath: string | undefined): Promise<void>;
2
+ //# sourceMappingURL=create-requirement-document.d.ts.map
@@ -0,0 +1,41 @@
1
+ import { getProjectContext } from "../requirements/cloud-ai.js";
2
+ import { loadAllRequirements } from "../requirements/index.js";
3
+ import { generateStyleGuide, readLocalStyleGuide, } from "../requirements/style-guide.js";
4
+ import { findProjectRoot, getProjectCredentials, } from "../utils/project-settings.js";
5
+ const CONVEX_URL = "https://data.dotrequirements.io";
6
+ export async function createRequirementDocumentCommand(filePath) {
7
+ const workspaceRoot = process.cwd();
8
+ // CLI-CREATE-DOC-1.1 / .2: discover existing patterns from the workspace.
9
+ // Best-effort — if the workspace has no requirements yet, we just have
10
+ // an empty pattern set.
11
+ let requirements = [];
12
+ try {
13
+ const result = await loadAllRequirements(workspaceRoot);
14
+ requirements = result.flattened;
15
+ }
16
+ catch {
17
+ // No requirements found — generateStyleGuide handles empty input
18
+ }
19
+ // CLI-CREATE-DOC-1.4 / .5: optional cloud-side custom style guidance.
20
+ // Silently skipped if the project isn't linked or the cloud is unavailable.
21
+ let customStyleGuidance = null;
22
+ const projectRoot = findProjectRoot(workspaceRoot);
23
+ if (projectRoot) {
24
+ try {
25
+ const { projectId, projectSecret } = getProjectCredentials(workspaceRoot);
26
+ const contextData = await getProjectContext(projectId, projectSecret, CONVEX_URL);
27
+ customStyleGuidance = contextData?.requirementsStyleContext ?? null;
28
+ }
29
+ catch {
30
+ // Not linked or cloud unavailable — fall through with defaults
31
+ }
32
+ }
33
+ const localStyleGuide = readLocalStyleGuide(workspaceRoot);
34
+ console.log(generateStyleGuide({
35
+ requirements,
36
+ customStyleGuidance,
37
+ filePath,
38
+ localStyleGuide,
39
+ }));
40
+ }
41
+ //# sourceMappingURL=create-requirement-document.js.map
@@ -1,8 +1,8 @@
1
- import * as fs from 'fs';
2
- import * as path from 'path';
3
- import { finalize } from '../harness/finalize.js';
4
- import { findRequirementsDir, isCacheStale } from '../harness/cache.js';
5
- import { findProjectRoot } from '../utils/project-settings.js';
1
+ import * as fs from "node:fs";
2
+ import * as path from "node:path";
3
+ import { findRequirementsDir, isCacheStale } from "../harness/cache.js";
4
+ import { finalize } from "../harness/finalize.js";
5
+ import { findProjectRoot } from "../utils/project-settings.js";
6
6
  export async function finalizeCommand(options) {
7
7
  // Warn if cache is stale before finalizing
8
8
  if (!options.quiet) {
@@ -10,11 +10,11 @@ export async function finalizeCommand(options) {
10
10
  if (projectRoot) {
11
11
  const requirementsDir = findRequirementsDir(projectRoot);
12
12
  if (requirementsDir) {
13
- const lookupPath = path.join(requirementsDir, '.cache', 'lookup.json');
13
+ const lookupPath = path.join(requirementsDir, ".cache", "lookup.json");
14
14
  try {
15
15
  const cacheStat = fs.statSync(lookupPath);
16
16
  if (isCacheStale(requirementsDir, cacheStat.mtimeMs)) {
17
- console.error('Warning: Cache may be stale — requirements have changed since last prepare. Run "dotrequirements prepare" to rebuild.\n');
17
+ console.error('Warning: Cache may be stale — requirements have changed since last prepare. Run "dotrequirements harness prepare" to rebuild.\n');
18
18
  }
19
19
  }
20
20
  catch {
@@ -0,0 +1,2 @@
1
+ export declare function getCommand(id: string): Promise<void>;
2
+ //# sourceMappingURL=get.d.ts.map
@@ -0,0 +1,55 @@
1
+ import { glob } from "glob";
2
+ import { formatRequirementTree, getRequirementTree, loadAllRequirements, } from "../requirements/index.js";
3
+ import { findFilesWithRequirement, findTestCodeForRequirement, } from "../requirements/testCodeExtractor.js";
4
+ export async function getCommand(id) {
5
+ const workspaceRoot = process.cwd();
6
+ const { flattened } = await loadAllRequirements(workspaceRoot);
7
+ const tree = getRequirementTree(flattened, id);
8
+ // CLI-FIND-GET-1.2: missing ID → error + non-zero exit
9
+ if (tree.length === 0) {
10
+ throw new Error(`Requirement "${id}" not found`);
11
+ }
12
+ const root = tree[0];
13
+ // CLI-FIND-GET-1.0 / 1.1: print the tree (root or subtree)
14
+ console.log(`${id}`);
15
+ console.log(` Document: ${root.documentTitle}`);
16
+ console.log(` Source: ${root.sourceFile}`);
17
+ console.log();
18
+ console.log(formatRequirementTree(tree));
19
+ console.log();
20
+ // CLI-FIND-GET-1.3 / 1.4: print test references + code snippets
21
+ const testFiles = await glob("**/*.{test,spec}.{js,jsx,ts,tsx}", {
22
+ cwd: workspaceRoot,
23
+ absolute: true,
24
+ ignore: ["**/node_modules/**", "**/dist/**", "**/build/**"],
25
+ });
26
+ const matchingFiles = findFilesWithRequirement(testFiles, id);
27
+ const testCodeSections = [];
28
+ for (const file of matchingFiles) {
29
+ const testRefs = findTestCodeForRequirement(file, id);
30
+ // Deduplicate nested blocks — keep only outermost
31
+ const deduplicated = testRefs.filter((ref, i) => {
32
+ const isNested = testRefs.some((other, j) => {
33
+ if (i === j)
34
+ return false;
35
+ return (other.startLine <= ref.startLine &&
36
+ other.endLine >= ref.endLine &&
37
+ (other.startLine < ref.startLine || other.endLine > ref.endLine));
38
+ });
39
+ return !isNested;
40
+ });
41
+ testCodeSections.push(...deduplicated);
42
+ }
43
+ // CLI-FIND-GET-1.5: explicit "no tests" message
44
+ if (testCodeSections.length === 0) {
45
+ console.log("Test Coverage: No tests found referencing this requirement.");
46
+ return;
47
+ }
48
+ console.log(`Test Coverage (${testCodeSections.length} reference(s)):\n`);
49
+ for (const ref of testCodeSections) {
50
+ console.log(`${ref.requirementId} — ${ref.file}:${ref.startLine}-${ref.endLine}`);
51
+ console.log(ref.code);
52
+ console.log();
53
+ }
54
+ }
55
+ //# sourceMappingURL=get.js.map