@popoverai/dotrequirements 0.23.0 → 0.24.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +167 -20
- package/dist/cli.js +121 -60
- package/dist/codebase-to-spec/budget.d.ts +53 -0
- package/dist/codebase-to-spec/budget.js +80 -0
- package/dist/codebase-to-spec/cache.d.ts +49 -0
- package/dist/codebase-to-spec/cache.js +54 -0
- package/dist/codebase-to-spec/claude.d.ts +69 -0
- package/dist/codebase-to-spec/claude.js +126 -0
- package/dist/codebase-to-spec/compose.d.ts +49 -0
- package/dist/codebase-to-spec/compose.js +124 -0
- package/dist/codebase-to-spec/edit-loop.d.ts +54 -0
- package/dist/codebase-to-spec/edit-loop.js +195 -0
- package/dist/codebase-to-spec/editor.d.ts +54 -0
- package/dist/codebase-to-spec/editor.js +74 -0
- package/dist/codebase-to-spec/exit-codes.d.ts +40 -0
- package/dist/codebase-to-spec/exit-codes.js +58 -0
- package/dist/codebase-to-spec/fan-out.d.ts +63 -0
- package/dist/codebase-to-spec/fan-out.js +215 -0
- package/dist/codebase-to-spec/interactive.d.ts +30 -0
- package/dist/codebase-to-spec/interactive.js +48 -0
- package/dist/codebase-to-spec/outline-review-loop.d.ts +51 -0
- package/dist/codebase-to-spec/outline-review-loop.js +187 -0
- package/dist/codebase-to-spec/pack.d.ts +51 -0
- package/dist/codebase-to-spec/pack.js +127 -0
- package/dist/codebase-to-spec/planner.d.ts +41 -0
- package/dist/codebase-to-spec/planner.js +76 -0
- package/dist/codebase-to-spec/present.d.ts +94 -0
- package/dist/codebase-to-spec/present.js +288 -0
- package/dist/codebase-to-spec/progress.d.ts +33 -0
- package/dist/codebase-to-spec/progress.js +28 -0
- package/dist/codebase-to-spec/prompts/editor.d.ts +13 -0
- package/dist/codebase-to-spec/prompts/editor.js +57 -0
- package/dist/codebase-to-spec/prompts/outline-reviewer.d.ts +12 -0
- package/dist/codebase-to-spec/prompts/outline-reviewer.js +87 -0
- package/dist/codebase-to-spec/prompts/planner-apply.d.ts +12 -0
- package/dist/codebase-to-spec/prompts/planner-apply.js +32 -0
- package/dist/codebase-to-spec/prompts/planner-initial.d.ts +11 -0
- package/dist/codebase-to-spec/prompts/planner-initial.js +125 -0
- package/dist/codebase-to-spec/prompts/planner-revise.d.ts +14 -0
- package/dist/codebase-to-spec/prompts/planner-revise.js +60 -0
- package/dist/codebase-to-spec/prompts/spec-reviewer.d.ts +16 -0
- package/dist/codebase-to-spec/prompts/spec-reviewer.js +96 -0
- package/dist/codebase-to-spec/prompts/specifier.d.ts +12 -0
- package/dist/codebase-to-spec/prompts/specifier.js +100 -0
- package/dist/codebase-to-spec/prompts/style-check.d.ts +12 -0
- package/dist/codebase-to-spec/prompts/style-check.js +78 -0
- package/dist/codebase-to-spec/schemas.d.ts +257 -0
- package/dist/codebase-to-spec/schemas.js +183 -0
- package/dist/codebase-to-spec/skill-install.d.ts +57 -0
- package/dist/codebase-to-spec/skill-install.js +79 -0
- package/dist/codebase-to-spec/slice.d.ts +49 -0
- package/dist/codebase-to-spec/slice.js +111 -0
- package/dist/codebase-to-spec/specifier.d.ts +60 -0
- package/dist/codebase-to-spec/specifier.js +79 -0
- package/dist/codebase-to-spec/style-check.d.ts +29 -0
- package/dist/codebase-to-spec/style-check.js +33 -0
- package/dist/codebase-to-spec/summary.d.ts +51 -0
- package/dist/codebase-to-spec/summary.js +183 -0
- package/dist/codebase-to-spec/validate.d.ts +46 -0
- package/dist/codebase-to-spec/validate.js +130 -0
- package/dist/commands/acceptance-test.d.ts +6 -0
- package/dist/commands/acceptance-test.js +212 -0
- package/dist/commands/ai-setup.d.ts +5 -0
- package/dist/commands/ai-setup.js +441 -0
- package/dist/commands/browsertest.js +34 -27
- package/dist/commands/codebase-to-spec/compose.d.ts +14 -0
- package/dist/commands/codebase-to-spec/compose.js +57 -0
- package/dist/commands/codebase-to-spec/edit-loop.d.ts +16 -0
- package/dist/commands/codebase-to-spec/edit-loop.js +83 -0
- package/dist/commands/codebase-to-spec/fan-out.d.ts +19 -0
- package/dist/commands/codebase-to-spec/fan-out.js +77 -0
- package/dist/commands/codebase-to-spec/index.d.ts +9 -0
- package/dist/commands/codebase-to-spec/index.js +135 -0
- package/dist/commands/codebase-to-spec/pack.d.ts +22 -0
- package/dist/commands/codebase-to-spec/pack.js +76 -0
- package/dist/commands/codebase-to-spec/plan-loop.d.ts +26 -0
- package/dist/commands/codebase-to-spec/plan-loop.js +105 -0
- package/dist/commands/codebase-to-spec/present.d.ts +21 -0
- package/dist/commands/codebase-to-spec/present.js +92 -0
- package/dist/commands/codebase-to-spec/run.d.ts +20 -0
- package/dist/commands/codebase-to-spec/run.js +85 -0
- package/dist/commands/codebase-to-spec/skill-install.d.ts +20 -0
- package/dist/commands/codebase-to-spec/skill-install.js +51 -0
- package/dist/commands/codebase-to-spec/specify-area.d.ts +18 -0
- package/dist/commands/codebase-to-spec/specify-area.js +82 -0
- package/dist/commands/codebase-to-spec/style-check.d.ts +15 -0
- package/dist/commands/codebase-to-spec/style-check.js +42 -0
- package/dist/commands/codebase-to-spec/validate.d.ts +18 -0
- package/dist/commands/codebase-to-spec/validate.js +38 -0
- package/dist/commands/create-requirement-document.d.ts +2 -0
- package/dist/commands/create-requirement-document.js +41 -0
- package/dist/commands/finalize.js +7 -7
- package/dist/commands/get.d.ts +2 -0
- package/dist/commands/get.js +55 -0
- package/dist/commands/init.js +132 -117
- package/dist/commands/link.js +27 -27
- package/dist/commands/list.d.ts +6 -0
- package/dist/commands/list.js +43 -0
- package/dist/commands/mcp-setup.js +159 -149
- package/dist/commands/mcp.js +1 -1
- package/dist/commands/prepare.js +4 -4
- package/dist/commands/pull.js +116 -121
- package/dist/commands/push.js +106 -112
- package/dist/commands/report.d.ts +6 -2
- package/dist/commands/report.js +177 -122
- package/dist/commands/requirements-for.d.ts +2 -0
- package/dist/commands/requirements-for.js +29 -0
- package/dist/commands/review-test.d.ts +2 -0
- package/dist/commands/review-test.js +75 -0
- package/dist/commands/search.d.ts +6 -0
- package/dist/commands/search.js +39 -0
- package/dist/commands/style-check.d.ts +7 -0
- package/dist/commands/style-check.js +75 -0
- package/dist/commands/test.js +53 -59
- package/dist/commands/tests-for.d.ts +2 -0
- package/dist/commands/tests-for.js +80 -0
- package/dist/commands/validate.d.ts +6 -0
- package/dist/commands/validate.js +72 -0
- package/dist/config.js +1 -1
- package/dist/convex.d.ts +34 -22
- package/dist/convex.js +38 -22
- package/dist/harness/cache.d.ts +1 -5
- package/dist/harness/cache.js +49 -59
- package/dist/harness/convexReporting.d.ts +1 -1
- package/dist/harness/convexReporting.js +9 -7
- package/dist/harness/coverageCache.js +3 -3
- package/dist/harness/finalize.js +59 -46
- package/dist/harness/index.d.ts +6 -7
- package/dist/harness/index.js +9 -10
- package/dist/harness/prepare.js +6 -5
- package/dist/harness/requirementsLoader.d.ts +2 -2
- package/dist/harness/requirementsLoader.js +13 -35
- package/dist/harness/tracking.js +18 -18
- package/dist/harness/types.d.ts +1 -1
- package/dist/mcp/convexClient.d.ts +0 -39
- package/dist/mcp/convexClient.js +2 -107
- package/dist/mcp/grep.d.ts +1 -1
- package/dist/mcp/grep.js +87 -42
- package/dist/mcp/handlers/authoring.d.ts +1 -1
- package/dist/mcp/handlers/authoring.js +30 -234
- package/dist/mcp/handlers/coverage.d.ts +1 -1
- package/dist/mcp/handlers/coverage.js +13 -15
- package/dist/mcp/handlers/debug.d.ts +2 -3
- package/dist/mcp/handlers/debug.js +10 -10
- package/dist/mcp/handlers/get.d.ts +1 -1
- package/dist/mcp/handlers/get.js +11 -10
- package/dist/mcp/handlers/index.d.ts +20 -20
- package/dist/mcp/handlers/index.js +10 -10
- package/dist/mcp/handlers/list.d.ts +4 -33
- package/dist/mcp/handlers/list.js +16 -38
- package/dist/mcp/handlers/push.d.ts +1 -1
- package/dist/mcp/handlers/push.js +28 -18
- package/dist/mcp/handlers/report.d.ts +16 -0
- package/dist/mcp/handlers/report.js +134 -0
- package/dist/mcp/handlers/review.d.ts +1 -1
- package/dist/mcp/handlers/review.js +40 -59
- package/dist/mcp/handlers/search.d.ts +1 -1
- package/dist/mcp/handlers/search.js +7 -9
- package/dist/mcp/handlers/test-mapping.d.ts +1 -1
- package/dist/mcp/handlers/test-mapping.js +14 -14
- package/dist/mcp/handlers/types.d.ts +3 -3
- package/dist/mcp/handlers/types.js +2 -2
- package/dist/mcp/index.d.ts +1 -1
- package/dist/mcp/index.js +147 -167
- package/dist/mcp/requirements.d.ts +2 -2
- package/dist/mcp/requirements.js +30 -30
- package/dist/mcp/testCodeExtractor.js +24 -26
- package/dist/mcp/types.d.ts +1 -1
- package/dist/push/core.d.ts +2 -2
- package/dist/push/core.js +20 -20
- package/dist/push/index.d.ts +1 -1
- package/dist/push/index.js +2 -2
- package/dist/requirements/cloud-ai.d.ts +57 -0
- package/dist/requirements/cloud-ai.js +104 -0
- package/dist/requirements/cloud-coverage.d.ts +41 -0
- package/dist/requirements/cloud-coverage.js +60 -0
- package/dist/requirements/coverage.d.ts +45 -0
- package/dist/requirements/coverage.js +114 -0
- package/dist/requirements/grep.d.ts +33 -0
- package/dist/requirements/grep.js +306 -0
- package/dist/requirements/index.d.ts +73 -0
- package/dist/requirements/index.js +174 -0
- package/dist/requirements/style-guide.d.ts +67 -0
- package/dist/requirements/style-guide.js +299 -0
- package/dist/requirements/testCodeExtractor.d.ts +22 -0
- package/dist/requirements/testCodeExtractor.js +150 -0
- package/dist/schema/browser.d.ts +8 -8
- package/dist/schema/browser.js +13 -15
- package/dist/schema/builder.d.ts +1 -1
- package/dist/schema/builder.js +13 -44
- package/dist/schema/conversions.d.ts +2 -2
- package/dist/schema/conversions.js +11 -11
- package/dist/schema/index.d.ts +9 -9
- package/dist/schema/index.js +15 -15
- package/dist/schema/parser-core.d.ts +1 -1
- package/dist/schema/parser-core.js +23 -22
- package/dist/schema/parser.d.ts +3 -3
- package/dist/schema/parser.js +27 -31
- package/dist/schema/resolver.d.ts +1 -1
- package/dist/schema/resolver.js +9 -9
- package/dist/schema/scenario.d.ts +1 -1
- package/dist/schema/scenario.js +1 -1
- package/dist/schema/schemas.d.ts +3 -3
- package/dist/schema/schemas.js +41 -28
- package/dist/schema/test-schema.js +27 -27
- package/dist/templates/context-file-section.md +3 -2
- package/dist/templates/example-requirements.js +1 -1
- package/dist/templates/example-requirements.ts +3 -1
- package/dist/templates/requirements-readme.js +1 -1
- package/dist/templates/requirements-readme.ts +1 -1
- package/dist/templates/skills/codebase-to-spec/SKILL.md +118 -0
- package/dist/utils/brand.js +3 -3
- package/dist/utils/browser-launch.js +4 -4
- package/dist/utils/context-file.d.ts +1 -1
- package/dist/utils/context-file.js +26 -26
- package/dist/utils/env.js +7 -7
- package/dist/utils/gitignore.js +7 -7
- package/dist/utils/oauth-callback-server.d.ts +1 -1
- package/dist/utils/oauth-callback-server.js +27 -25
- package/dist/utils/oauth-flow.js +32 -29
- package/dist/utils/project-discovery.d.ts +3 -3
- package/dist/utils/project-discovery.js +18 -17
- package/dist/utils/project-name.js +8 -8
- package/dist/utils/project-selector.d.ts +1 -1
- package/dist/utils/project-selector.js +24 -21
- package/dist/utils/project-settings.d.ts +1 -1
- package/dist/utils/project-settings.js +24 -22
- package/dist/utils/templates.js +6 -6
- package/package.json +2 -1
|
@@ -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,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
|
|
2
|
-
import * as path from
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import { findProjectRoot } from
|
|
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,
|
|
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,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
|