@popoverai/dotrequirements 0.23.0 → 0.24.1
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 +169 -22
- 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-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/{browsertest.js → acceptance-test.js} +36 -29
- package/dist/commands/ai-setup.d.ts +5 -0
- package/dist/commands/ai-setup.js +441 -0
- 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.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/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/handlers/authoring.d.ts +1 -1
- package/dist/mcp/handlers/authoring.js +30 -234
- 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/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/{mcp → requirements}/grep.d.ts +10 -1
- package/dist/{mcp → requirements}/grep.js +89 -44
- package/dist/{mcp/requirements.d.ts → requirements/index.d.ts} +19 -3
- package/dist/{mcp/requirements.js → requirements/index.js} +54 -35
- package/dist/requirements/style-guide.d.ts +67 -0
- package/dist/requirements/style-guide.js +299 -0
- package/dist/{mcp → requirements}/testCodeExtractor.js +24 -26
- 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 +3 -2
- package/dist/commands/browsertest.d.ts +0 -6
- package/dist/commands/login.d.ts +0 -12
- package/dist/commands/login.js +0 -117
- package/dist/commands/logout.d.ts +0 -5
- package/dist/commands/logout.js +0 -17
- package/dist/commands/mcp-setup.d.ts +0 -5
- package/dist/commands/mcp-setup.js +0 -431
- package/dist/commands/test.d.ts +0 -6
- package/dist/commands/test.js +0 -78
- package/dist/mcp/handlers/coverage.d.ts +0 -44
- package/dist/mcp/handlers/coverage.js +0 -105
- package/dist/mcp/types.d.ts +0 -27
- package/dist/mcp/types.js +0 -2
- package/dist/utils/local-project.d.ts +0 -31
- package/dist/utils/local-project.js +0 -33
- package/dist/utils/token-refresh.d.ts +0 -24
- package/dist/utils/token-refresh.js +0 -69
- package/dist/utils/token-storage.d.ts +0 -31
- package/dist/utils/token-storage.js +0 -57
- /package/dist/{mcp → requirements}/testCodeExtractor.d.ts +0 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { execSync } from "child_process";
|
|
2
|
-
import { getTrackedRequirements } from "./tracking.js";
|
|
3
|
-
import { saveCache, getRequirementsToReport } from "./coverageCache.js";
|
|
1
|
+
import { execSync } from "node:child_process";
|
|
4
2
|
import { getProjectInfo } from "../utils/project-settings.js";
|
|
3
|
+
import { getRequirementsToReport, saveCache } from "./coverageCache.js";
|
|
4
|
+
import { getTrackedRequirements } from "./tracking.js";
|
|
5
5
|
/**
|
|
6
6
|
* Get the current git branch, or null if not in a git repo
|
|
7
7
|
*/
|
|
@@ -14,7 +14,7 @@ export function getCurrentBranch(cwd = process.cwd()) {
|
|
|
14
14
|
}).trim();
|
|
15
15
|
return branch;
|
|
16
16
|
}
|
|
17
|
-
catch
|
|
17
|
+
catch {
|
|
18
18
|
// Not in a git repo or git not available
|
|
19
19
|
return "unknown";
|
|
20
20
|
}
|
|
@@ -22,7 +22,7 @@ export function getCurrentBranch(cwd = process.cwd()) {
|
|
|
22
22
|
/**
|
|
23
23
|
* Production Convex deployment URL
|
|
24
24
|
*/
|
|
25
|
-
const CONVEX_URL =
|
|
25
|
+
const CONVEX_URL = "https://data.dotrequirements.io";
|
|
26
26
|
/**
|
|
27
27
|
* Extract file path and line number from caller location string
|
|
28
28
|
*/
|
|
@@ -53,7 +53,9 @@ export async function reportCoverageToConvex(cwd = process.cwd(), trackedReqs) {
|
|
|
53
53
|
// Get project info from .requirements/project-settings.json
|
|
54
54
|
const projectInfo = getProjectInfo(cwd);
|
|
55
55
|
// Skip if no project found or not connected to cloud
|
|
56
|
-
if (!projectInfo ||
|
|
56
|
+
if (!projectInfo ||
|
|
57
|
+
projectInfo.status !== "cloud-connected" ||
|
|
58
|
+
!projectInfo.credentials) {
|
|
57
59
|
console.log("\nℹ️ Skipping cloud coverage reporting (project not connected to cloud)");
|
|
58
60
|
return;
|
|
59
61
|
}
|
|
@@ -113,7 +115,7 @@ export async function reportCoverageToConvex(cwd = process.cwd(), trackedReqs) {
|
|
|
113
115
|
console.warn(`\n⚠️ Failed to report coverage to cloud: ${response.status} ${error}`);
|
|
114
116
|
return;
|
|
115
117
|
}
|
|
116
|
-
|
|
118
|
+
await response.json();
|
|
117
119
|
console.log(`\n✓ Reported ${keysToReport.length} requirement(s) to cloud (branch: ${branch})`);
|
|
118
120
|
// Update cache with current test run
|
|
119
121
|
saveCache({
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { readFileSync, writeFileSync
|
|
2
|
-
import { join } from "path";
|
|
1
|
+
import { existsSync, readFileSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { join } from "node:path";
|
|
3
3
|
import { v4 as uuidv4 } from "uuid";
|
|
4
4
|
const CACHE_FILE = ".requirements/.coverage-cache.json";
|
|
5
5
|
const STALENESS_THRESHOLD_MS = 4 * 60 * 60 * 1000; // 4 hours
|
|
@@ -15,7 +15,7 @@ export function loadCache(cwd = process.cwd()) {
|
|
|
15
15
|
const content = readFileSync(cachePath, "utf-8");
|
|
16
16
|
return JSON.parse(content);
|
|
17
17
|
}
|
|
18
|
-
catch
|
|
18
|
+
catch {
|
|
19
19
|
// If cache is corrupt, start fresh
|
|
20
20
|
console.warn("Warning: Coverage cache is corrupt, starting fresh");
|
|
21
21
|
return { current: null, previous: null };
|
package/dist/harness/finalize.js
CHANGED
|
@@ -9,10 +9,10 @@
|
|
|
9
9
|
*
|
|
10
10
|
* Implements: HARNESS-FINALIZE-1, HARNESS-FINALIZE-2, HARNESS-FINALIZE-3, HARNESS-FINALIZE-4
|
|
11
11
|
*/
|
|
12
|
-
import { execSync } from
|
|
13
|
-
import { randomUUID } from
|
|
14
|
-
import {
|
|
15
|
-
import {
|
|
12
|
+
import { execSync } from "node:child_process";
|
|
13
|
+
import { randomUUID } from "node:crypto";
|
|
14
|
+
import { getProjectInfo } from "../utils/project-settings.js";
|
|
15
|
+
import { cleanupTestRunId, deleteTrackingFile, findProjectRoot, findRequirementsDir, getTestRunId, needsReporting, readCoverageCache, readLookupCache, readTrackingEntries, updateCoverageCache, } from "./cache.js";
|
|
16
16
|
/**
|
|
17
17
|
* Aggregate tracking entries by requirement key
|
|
18
18
|
*/
|
|
@@ -30,15 +30,15 @@ function aggregateEntries(entries) {
|
|
|
30
30
|
*/
|
|
31
31
|
function getCurrentBranch(cwd) {
|
|
32
32
|
try {
|
|
33
|
-
const branch = execSync(
|
|
33
|
+
const branch = execSync("git rev-parse --abbrev-ref HEAD", {
|
|
34
34
|
cwd,
|
|
35
|
-
encoding:
|
|
36
|
-
stdio: [
|
|
35
|
+
encoding: "utf-8",
|
|
36
|
+
stdio: ["pipe", "pipe", "ignore"],
|
|
37
37
|
}).trim();
|
|
38
38
|
return branch;
|
|
39
39
|
}
|
|
40
40
|
catch {
|
|
41
|
-
return
|
|
41
|
+
return "unknown";
|
|
42
42
|
}
|
|
43
43
|
}
|
|
44
44
|
/**
|
|
@@ -51,8 +51,8 @@ function getLineAuthor(cwd, file, line) {
|
|
|
51
51
|
try {
|
|
52
52
|
const output = execSync(`git blame -L ${line},${line} --porcelain -- "${file}"`, {
|
|
53
53
|
cwd,
|
|
54
|
-
encoding:
|
|
55
|
-
stdio: [
|
|
54
|
+
encoding: "utf-8",
|
|
55
|
+
stdio: ["pipe", "pipe", "ignore"],
|
|
56
56
|
});
|
|
57
57
|
const match = output.match(/^author-mail\s+<([^>]+)>/m);
|
|
58
58
|
return match?.[1];
|
|
@@ -68,15 +68,17 @@ function getLineAuthor(cwd, file, line) {
|
|
|
68
68
|
*/
|
|
69
69
|
function printLocalReport(testedKeys, lookup, options) {
|
|
70
70
|
const { showSummary, showTestedList, showUntestedList } = options;
|
|
71
|
-
const allKeys = lookup
|
|
72
|
-
|
|
71
|
+
const allKeys = lookup
|
|
72
|
+
? Object.keys(lookup.requirements).filter((k) => !lookup.requirements[k].isAlias)
|
|
73
|
+
: [];
|
|
74
|
+
const untestedKeys = allKeys.filter((key) => !testedKeys.includes(key));
|
|
73
75
|
const total = allKeys.length;
|
|
74
76
|
const tested = testedKeys.length;
|
|
75
|
-
const coverage = total > 0 ? ((tested / total) * 100).toFixed(1) :
|
|
76
|
-
let report =
|
|
77
|
+
const coverage = total > 0 ? ((tested / total) * 100).toFixed(1) : "0.0";
|
|
78
|
+
let report = "";
|
|
77
79
|
// Show summary stats
|
|
78
80
|
if (showSummary) {
|
|
79
|
-
report +=
|
|
81
|
+
report += "\n=== Requirements Coverage Report ===\n";
|
|
80
82
|
report += `\nTotal Requirements: ${total}\n`;
|
|
81
83
|
report += `Tested Requirements: ${tested}\n`;
|
|
82
84
|
report += `Untested Requirements: ${untestedKeys.length}\n`;
|
|
@@ -84,14 +86,14 @@ function printLocalReport(testedKeys, lookup, options) {
|
|
|
84
86
|
}
|
|
85
87
|
// Show tested requirements
|
|
86
88
|
if (showTestedList && testedKeys.length > 0) {
|
|
87
|
-
report +=
|
|
89
|
+
report += "\n✓ Tested Requirements:\n";
|
|
88
90
|
for (const key of testedKeys) {
|
|
89
91
|
const req = lookup?.requirements[key];
|
|
90
92
|
if (req) {
|
|
91
|
-
const label = req.label ||
|
|
92
|
-
const content = req.content ||
|
|
93
|
-
const preview = content.length > 60 ? content.substring(0, 60)
|
|
94
|
-
const labelPart = label ? ` (${label})` :
|
|
93
|
+
const label = req.label || "";
|
|
94
|
+
const content = req.content || "";
|
|
95
|
+
const preview = content.length > 60 ? `${content.substring(0, 60)}...` : content;
|
|
96
|
+
const labelPart = label ? ` (${label})` : "";
|
|
95
97
|
report += ` - ${key}${labelPart}: ${preview}\n`;
|
|
96
98
|
}
|
|
97
99
|
else {
|
|
@@ -101,14 +103,14 @@ function printLocalReport(testedKeys, lookup, options) {
|
|
|
101
103
|
}
|
|
102
104
|
// Show untested requirements
|
|
103
105
|
if (showUntestedList && untestedKeys.length > 0) {
|
|
104
|
-
report +=
|
|
106
|
+
report += "\n✗ Untested Requirements:\n";
|
|
105
107
|
for (const key of untestedKeys) {
|
|
106
108
|
const req = lookup?.requirements[key];
|
|
107
109
|
if (req) {
|
|
108
|
-
const label = req.label ||
|
|
109
|
-
const content = req.content ||
|
|
110
|
-
const preview = content.length > 60 ? content.substring(0, 60)
|
|
111
|
-
const labelPart = label ? ` (${label})` :
|
|
110
|
+
const label = req.label || "";
|
|
111
|
+
const content = req.content || "";
|
|
112
|
+
const preview = content.length > 60 ? `${content.substring(0, 60)}...` : content;
|
|
113
|
+
const labelPart = label ? ` (${label})` : "";
|
|
112
114
|
report += ` - ${key}${labelPart}: ${preview}\n`;
|
|
113
115
|
}
|
|
114
116
|
else {
|
|
@@ -117,7 +119,7 @@ function printLocalReport(testedKeys, lookup, options) {
|
|
|
117
119
|
}
|
|
118
120
|
}
|
|
119
121
|
if (showSummary) {
|
|
120
|
-
report +=
|
|
122
|
+
report += "\n====================================\n";
|
|
121
123
|
}
|
|
122
124
|
if (report) {
|
|
123
125
|
console.log(report);
|
|
@@ -126,7 +128,7 @@ function printLocalReport(testedKeys, lookup, options) {
|
|
|
126
128
|
/**
|
|
127
129
|
* Production Convex deployment URL
|
|
128
130
|
*/
|
|
129
|
-
const CONVEX_URL =
|
|
131
|
+
const CONVEX_URL = "https://data.dotrequirements.io";
|
|
130
132
|
/**
|
|
131
133
|
* Report coverage to Convex cloud
|
|
132
134
|
*
|
|
@@ -138,9 +140,11 @@ async function reportToConvex(projectRoot, testRunId, aggregated, showCloudStatu
|
|
|
138
140
|
// Get project info from .requirements/project-settings.json
|
|
139
141
|
const projectInfo = getProjectInfo(projectRoot);
|
|
140
142
|
// Skip if no project found or not connected to cloud
|
|
141
|
-
if (!projectInfo ||
|
|
143
|
+
if (!projectInfo ||
|
|
144
|
+
projectInfo.status !== "cloud-connected" ||
|
|
145
|
+
!projectInfo.credentials) {
|
|
142
146
|
if (showCloudStatus) {
|
|
143
|
-
console.log(
|
|
147
|
+
console.log("\nℹ️ Skipping cloud coverage reporting (project not connected to cloud)");
|
|
144
148
|
}
|
|
145
149
|
return { sent: false, count: 0 };
|
|
146
150
|
}
|
|
@@ -161,7 +165,7 @@ async function reportToConvex(projectRoot, testRunId, aggregated, showCloudStatu
|
|
|
161
165
|
const tuplesToReport = allTuples.filter((tuple) => needsReporting(tuple, coverageCache));
|
|
162
166
|
if (tuplesToReport.length === 0) {
|
|
163
167
|
if (showCloudStatus) {
|
|
164
|
-
console.log(
|
|
168
|
+
console.log("\n✓ Coverage unchanged since last run (skipping cloud report)");
|
|
165
169
|
}
|
|
166
170
|
// Still update the cache so the window continues tracking
|
|
167
171
|
updateCoverageCache(requirementsDir, testRunId, allTuples);
|
|
@@ -180,7 +184,7 @@ async function reportToConvex(projectRoot, testRunId, aggregated, showCloudStatu
|
|
|
180
184
|
// Parse "filename.ts:42" format
|
|
181
185
|
let testFile;
|
|
182
186
|
let testLine;
|
|
183
|
-
if (location !==
|
|
187
|
+
if (location !== "unknown") {
|
|
184
188
|
const match = location.match(/^(.+):(\d+)$/);
|
|
185
189
|
if (match) {
|
|
186
190
|
testFile = match[1];
|
|
@@ -213,19 +217,19 @@ async function reportToConvex(projectRoot, testRunId, aggregated, showCloudStatu
|
|
|
213
217
|
// Note: projectId from env is always a slug (e.g., "reduced-cephalopod-288"),
|
|
214
218
|
// not a Convex ID. Use projectSlug field for authentication and slug for target.
|
|
215
219
|
const response = await fetch(`${CONVEX_URL}/api/mutation`, {
|
|
216
|
-
method:
|
|
220
|
+
method: "POST",
|
|
217
221
|
headers: {
|
|
218
|
-
|
|
222
|
+
"Content-Type": "application/json",
|
|
219
223
|
},
|
|
220
224
|
body: JSON.stringify({
|
|
221
|
-
path:
|
|
225
|
+
path: "testCoverage/mutations:recordCoverage",
|
|
222
226
|
args: {
|
|
223
227
|
projectAuth: {
|
|
224
228
|
projectSlug: projectId,
|
|
225
229
|
projectSecret,
|
|
226
230
|
},
|
|
227
231
|
target: {
|
|
228
|
-
type:
|
|
232
|
+
type: "project",
|
|
229
233
|
slug: projectId,
|
|
230
234
|
},
|
|
231
235
|
branch,
|
|
@@ -233,7 +237,7 @@ async function reportToConvex(projectRoot, testRunId, aggregated, showCloudStatu
|
|
|
233
237
|
runId,
|
|
234
238
|
coverage,
|
|
235
239
|
},
|
|
236
|
-
format:
|
|
240
|
+
format: "json",
|
|
237
241
|
}),
|
|
238
242
|
});
|
|
239
243
|
if (!response.ok) {
|
|
@@ -253,10 +257,12 @@ async function reportToConvex(projectRoot, testRunId, aggregated, showCloudStatu
|
|
|
253
257
|
catch {
|
|
254
258
|
// Not JSON, treat as success
|
|
255
259
|
}
|
|
256
|
-
if (responseData &&
|
|
260
|
+
if (responseData &&
|
|
261
|
+
typeof responseData === "object" &&
|
|
262
|
+
"status" in responseData) {
|
|
257
263
|
const convexResponse = responseData;
|
|
258
|
-
if (convexResponse.status ===
|
|
259
|
-
const errorMsg = convexResponse.errorMessage ||
|
|
264
|
+
if (convexResponse.status === "error") {
|
|
265
|
+
const errorMsg = convexResponse.errorMessage || "Unknown Convex error";
|
|
260
266
|
if (showCloudStatus) {
|
|
261
267
|
console.warn(`\n⚠️ Failed to report coverage to cloud: ${errorMsg}`);
|
|
262
268
|
}
|
|
@@ -298,7 +304,7 @@ export async function finalize(options = {}) {
|
|
|
298
304
|
projectRoot = findProjectRoot(cwd);
|
|
299
305
|
}
|
|
300
306
|
if (!projectRoot) {
|
|
301
|
-
console.log(
|
|
307
|
+
console.log("Could not find .requirements directory");
|
|
302
308
|
return {
|
|
303
309
|
requirementsTested: 0,
|
|
304
310
|
totalRequirements: 0,
|
|
@@ -311,7 +317,7 @@ export async function finalize(options = {}) {
|
|
|
311
317
|
// Get test run ID
|
|
312
318
|
const testRunId = getTestRunId(requirementsDir);
|
|
313
319
|
if (!testRunId) {
|
|
314
|
-
console.log(
|
|
320
|
+
console.log("No test run ID found - was prepare() called?");
|
|
315
321
|
return {
|
|
316
322
|
requirementsTested: 0,
|
|
317
323
|
totalRequirements: 0,
|
|
@@ -343,17 +349,24 @@ export async function finalize(options = {}) {
|
|
|
343
349
|
}
|
|
344
350
|
}
|
|
345
351
|
const testedKeys = Array.from(aggregated.keys());
|
|
346
|
-
const totalRequirements = lookup
|
|
347
|
-
|
|
348
|
-
? (testedKeys.length / totalRequirements) * 100
|
|
352
|
+
const totalRequirements = lookup
|
|
353
|
+
? Object.keys(lookup.requirements).filter((k) => !lookup.requirements[k].isAlias).length
|
|
349
354
|
: 0;
|
|
355
|
+
const coveragePercent = totalRequirements > 0 ? (testedKeys.length / totalRequirements) * 100 : 0;
|
|
350
356
|
// HARNESS-FINALIZE-1: Print local report
|
|
351
357
|
const shouldPrintLocal = showSummary || showTestedList || showUntestedList;
|
|
352
358
|
if (shouldPrintLocal) {
|
|
353
|
-
printLocalReport(testedKeys, lookup, {
|
|
359
|
+
printLocalReport(testedKeys, lookup, {
|
|
360
|
+
showSummary,
|
|
361
|
+
showTestedList,
|
|
362
|
+
showUntestedList,
|
|
363
|
+
});
|
|
354
364
|
}
|
|
355
365
|
// HARNESS-FINALIZE-2, HARNESS-FINALIZE-3: Report to cloud
|
|
356
|
-
let cloudResult = {
|
|
366
|
+
let cloudResult = {
|
|
367
|
+
sent: false,
|
|
368
|
+
count: 0,
|
|
369
|
+
};
|
|
357
370
|
if (shouldReportToCloud) {
|
|
358
371
|
cloudResult = await reportToConvex(projectRoot, testRunId, aggregated, showCloudStatus, context);
|
|
359
372
|
}
|
package/dist/harness/index.d.ts
CHANGED
|
@@ -60,11 +60,10 @@ export interface RequirementOptions {
|
|
|
60
60
|
* @returns A formatted string with the first requirement's label and content
|
|
61
61
|
*/
|
|
62
62
|
export declare function requirement(...args: (string | RequirementOptions)[]): string;
|
|
63
|
-
export {
|
|
64
|
-
export
|
|
65
|
-
export {
|
|
66
|
-
export
|
|
67
|
-
export { clearTracking } from
|
|
68
|
-
export {
|
|
69
|
-
export type { Requirement } from './types.js';
|
|
63
|
+
export type { FinalizeOptions, FinalizeResult } from "./finalize.js";
|
|
64
|
+
export { finalize } from "./finalize.js";
|
|
65
|
+
export type { PrepareOptions, PrepareResult } from "./prepare.js";
|
|
66
|
+
export { prepare } from "./prepare.js";
|
|
67
|
+
export { clearTracking, finalizeTestRun, initTestRun } from "./tracking.js";
|
|
68
|
+
export type { Requirement } from "./types.js";
|
|
70
69
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/harness/index.js
CHANGED
|
@@ -27,8 +27,8 @@
|
|
|
27
27
|
* }
|
|
28
28
|
* ```
|
|
29
29
|
*/
|
|
30
|
-
import { getRequirement, loadRequirements } from
|
|
31
|
-
import { ensureTestRun, trackRequirement,
|
|
30
|
+
import { getRequirement, loadRequirements } from "./requirementsLoader.js";
|
|
31
|
+
import { ensureTestRun, saveTrackingData, trackRequirement, } from "./tracking.js";
|
|
32
32
|
/**
|
|
33
33
|
* Main requirements function for test harness.
|
|
34
34
|
*
|
|
@@ -56,15 +56,15 @@ import { ensureTestRun, trackRequirement, saveTrackingData } from './tracking.js
|
|
|
56
56
|
*/
|
|
57
57
|
export function requirement(...args) {
|
|
58
58
|
if (args.length === 0) {
|
|
59
|
-
throw new Error(
|
|
59
|
+
throw new Error("requirement() requires at least one argument");
|
|
60
60
|
}
|
|
61
61
|
// Check if last argument is options object
|
|
62
62
|
const lastArg = args[args.length - 1];
|
|
63
|
-
const hasOptions = typeof lastArg ===
|
|
63
|
+
const hasOptions = typeof lastArg === "object" && lastArg !== null;
|
|
64
64
|
const options = hasOptions ? lastArg : {};
|
|
65
65
|
const requirementRefs = (hasOptions ? args.slice(0, -1) : args);
|
|
66
66
|
if (requirementRefs.length === 0) {
|
|
67
|
-
throw new Error(
|
|
67
|
+
throw new Error("requirement() requires at least one requirement reference");
|
|
68
68
|
}
|
|
69
69
|
// If projectRoot provided, reload requirements from that path
|
|
70
70
|
if (options.projectRoot) {
|
|
@@ -87,17 +87,16 @@ export function requirement(...args) {
|
|
|
87
87
|
}
|
|
88
88
|
// HARNESS-REQUIREMENT-1: Format output as human-readable string
|
|
89
89
|
// Root requirements use 'requirementHeader' label which should not be shown in output
|
|
90
|
-
if (!req.label || req.label ===
|
|
90
|
+
if (!req.label || req.label === "requirementHeader") {
|
|
91
91
|
return req.content;
|
|
92
92
|
}
|
|
93
93
|
const label = req.label.charAt(0).toUpperCase() + req.label.slice(1);
|
|
94
94
|
return `${label}: ${req.content}`;
|
|
95
95
|
}
|
|
96
|
+
export { finalize } from "./finalize.js";
|
|
96
97
|
// Export new lifecycle functions
|
|
97
|
-
export { prepare } from
|
|
98
|
-
export { finalize } from './finalize.js';
|
|
98
|
+
export { prepare } from "./prepare.js";
|
|
99
99
|
// Export tracking utilities
|
|
100
|
-
export { clearTracking } from './tracking.js';
|
|
101
100
|
// Deprecated exports - use prepare() and finalize() instead
|
|
102
|
-
export {
|
|
101
|
+
export { clearTracking, finalizeTestRun, initTestRun } from "./tracking.js";
|
|
103
102
|
//# sourceMappingURL=index.js.map
|
package/dist/harness/prepare.js
CHANGED
|
@@ -8,9 +8,10 @@
|
|
|
8
8
|
*
|
|
9
9
|
* Implements: HARNESS-PREPARE-1, HARNESS-PREPARE-2, HARNESS-PREPARE-3
|
|
10
10
|
*/
|
|
11
|
-
import {
|
|
12
|
-
import { parseRequirementsFromFile, } from
|
|
13
|
-
import { findProjectRoot } from
|
|
11
|
+
import { findRequirementsFilesSync } from "../requirements/index.js";
|
|
12
|
+
import { parseRequirementsFromFile, } from "../schema/index.js";
|
|
13
|
+
import { findProjectRoot } from "../utils/project-settings.js";
|
|
14
|
+
import { clearTrackingFile, findRequirementsDir, initTestRunId, writeLookupCache, writeProjectRoot, } from "./cache.js";
|
|
14
15
|
/**
|
|
15
16
|
* Prepare the test harness for a test run.
|
|
16
17
|
*
|
|
@@ -26,14 +27,14 @@ export function prepare(options = {}) {
|
|
|
26
27
|
// Find the project root by looking for .requirements directory
|
|
27
28
|
const projectRoot = findProjectRoot(cwd);
|
|
28
29
|
if (!projectRoot) {
|
|
29
|
-
throw new Error(
|
|
30
|
+
throw new Error("Could not find .requirements directory. " +
|
|
30
31
|
'Please run "dotrequirements init" to initialize your project.');
|
|
31
32
|
}
|
|
32
33
|
// Set environment variable for cross-process persistence (globalSetup → test workers)
|
|
33
34
|
process.env.DOTREQUIREMENTS_PROJECT_ROOT = projectRoot;
|
|
34
35
|
const requirementsDir = findRequirementsDir(projectRoot);
|
|
35
36
|
// Find all requirements files
|
|
36
|
-
const files =
|
|
37
|
+
const files = findRequirementsFilesSync(projectRoot);
|
|
37
38
|
// Parse all files, collecting requirements and errors
|
|
38
39
|
const allRequirements = [];
|
|
39
40
|
const parseErrors = [];
|
|
@@ -7,8 +7,8 @@
|
|
|
7
7
|
* 2. DOTREQUIREMENTS_PROJECT_ROOT environment variable
|
|
8
8
|
* 3. Cached project root file (.requirements/.cache/project-root) written by prepare()
|
|
9
9
|
*/
|
|
10
|
-
import { type RequirementNode } from
|
|
11
|
-
import { Requirement } from
|
|
10
|
+
import { type RequirementNode } from "../schema/index.js";
|
|
11
|
+
import type { Requirement } from "./types.js";
|
|
12
12
|
export declare const loadedRequirements: Map<string, RequirementNode>;
|
|
13
13
|
export interface LoadOptions {
|
|
14
14
|
/** Explicit project root path. Takes precedence over env var and cached file. */
|
|
@@ -7,11 +7,11 @@
|
|
|
7
7
|
* 2. DOTREQUIREMENTS_PROJECT_ROOT environment variable
|
|
8
8
|
* 3. Cached project root file (.requirements/.cache/project-root) written by prepare()
|
|
9
9
|
*/
|
|
10
|
-
import * as fs from
|
|
11
|
-
import * as path from
|
|
12
|
-
import {
|
|
13
|
-
import { parseRequirementsFromFile, resolveRequirementPath, } from
|
|
14
|
-
import { findCachedProjectRoot, readLookupCache
|
|
10
|
+
import * as fs from "node:fs";
|
|
11
|
+
import * as path from "node:path";
|
|
12
|
+
import { findRequirementsFilesSync } from "../requirements/index.js";
|
|
13
|
+
import { parseRequirementsFromFile, resolveRequirementPath, } from "../schema/index.js";
|
|
14
|
+
import { findCachedProjectRoot, readLookupCache } from "./cache.js";
|
|
15
15
|
// Cache: Maps full requirement IDs (e.g., "REQ-123.0.1") to RequirementNode
|
|
16
16
|
export const loadedRequirements = new Map();
|
|
17
17
|
// Cache: Maps root requirement IDs (e.g., "REQ-123") to their tree
|
|
@@ -36,34 +36,12 @@ function findProjectRoot(options = {}) {
|
|
|
36
36
|
// Priority 3: Cached file (written by prepare())
|
|
37
37
|
return findCachedProjectRoot(process.cwd());
|
|
38
38
|
}
|
|
39
|
-
/**
|
|
40
|
-
* Find all *.requirements.md files under project root synchronously.
|
|
41
|
-
*/
|
|
42
|
-
function findRequirementsFilesSync(projectRoot) {
|
|
43
|
-
const pattern = '**/*.requirements.md';
|
|
44
|
-
const matches = globSync(pattern, {
|
|
45
|
-
cwd: projectRoot,
|
|
46
|
-
ignore: [
|
|
47
|
-
'**/node_modules/**',
|
|
48
|
-
'**/dist/**',
|
|
49
|
-
'**/.git/**',
|
|
50
|
-
'**/build/**',
|
|
51
|
-
'**/example/**',
|
|
52
|
-
'**/examples/**',
|
|
53
|
-
'**/__tests__/**',
|
|
54
|
-
'**/fixtures/**',
|
|
55
|
-
'**/.fixtures/**',
|
|
56
|
-
],
|
|
57
|
-
dot: true, // Include dotfiles/dotdirs like .requirements/
|
|
58
|
-
});
|
|
59
|
-
return matches.map(m => path.join(projectRoot, m));
|
|
60
|
-
}
|
|
61
39
|
/**
|
|
62
40
|
* Try to load requirements from lookup cache (fast path).
|
|
63
41
|
* Returns true if cache was loaded, false if not available.
|
|
64
42
|
*/
|
|
65
43
|
function tryLoadFromCache(projectRoot) {
|
|
66
|
-
const requirementsDir = path.join(projectRoot,
|
|
44
|
+
const requirementsDir = path.join(projectRoot, ".requirements");
|
|
67
45
|
if (!fs.existsSync(requirementsDir)) {
|
|
68
46
|
return false;
|
|
69
47
|
}
|
|
@@ -82,7 +60,7 @@ function tryLoadFromCache(projectRoot) {
|
|
|
82
60
|
};
|
|
83
61
|
loadedRequirements.set(id, node);
|
|
84
62
|
// If this is a root node (no dot in ID), add to trees cache
|
|
85
|
-
if (!id.includes(
|
|
63
|
+
if (!id.includes(".")) {
|
|
86
64
|
requirementTrees.set(id, node);
|
|
87
65
|
}
|
|
88
66
|
}
|
|
@@ -96,7 +74,7 @@ function flattenRequirementTree(node) {
|
|
|
96
74
|
// Add this node to the flat cache
|
|
97
75
|
loadedRequirements.set(node.id, node);
|
|
98
76
|
// If this is a root node (no dot in ID), also add to trees cache
|
|
99
|
-
if (!node.id.includes(
|
|
77
|
+
if (!node.id.includes(".")) {
|
|
100
78
|
requirementTrees.set(node.id, node);
|
|
101
79
|
}
|
|
102
80
|
// Recursively add children
|
|
@@ -119,8 +97,8 @@ export function loadRequirements(options = {}) {
|
|
|
119
97
|
// Find project root
|
|
120
98
|
const projectRoot = findProjectRoot(options);
|
|
121
99
|
if (!projectRoot) {
|
|
122
|
-
throw new Error(
|
|
123
|
-
|
|
100
|
+
throw new Error("Could not find project root. " +
|
|
101
|
+
"Set DOTREQUIREMENTS_PROJECT_ROOT environment variable or run prepare() in globalSetup.");
|
|
124
102
|
}
|
|
125
103
|
// Try cache first (fast path)
|
|
126
104
|
if (tryLoadFromCache(projectRoot)) {
|
|
@@ -128,8 +106,8 @@ export function loadRequirements(options = {}) {
|
|
|
128
106
|
}
|
|
129
107
|
// Fallback: Parse .requirements.md files on-demand
|
|
130
108
|
if (!warnedAboutFallback && !options.projectRoot) {
|
|
131
|
-
console.warn(
|
|
132
|
-
|
|
109
|
+
console.warn("⚠️ Performance warning: prepare() was not called. " +
|
|
110
|
+
"Parsing requirements on-demand. Run prepare() in globalSetup for faster tests.");
|
|
133
111
|
warnedAboutFallback = true;
|
|
134
112
|
}
|
|
135
113
|
// Find all .requirements.md files under the project root
|
|
@@ -144,7 +122,7 @@ export function loadRequirements(options = {}) {
|
|
|
144
122
|
}
|
|
145
123
|
}
|
|
146
124
|
catch (error) {
|
|
147
|
-
const errorMessage = error instanceof Error ? error.message :
|
|
125
|
+
const errorMessage = error instanceof Error ? error.message : "Unknown error";
|
|
148
126
|
console.error(`Error loading ${file}:`, errorMessage);
|
|
149
127
|
}
|
|
150
128
|
}
|
package/dist/harness/tracking.js
CHANGED
|
@@ -6,8 +6,8 @@
|
|
|
6
6
|
*
|
|
7
7
|
* HARNESS-REQUIREMENT-3: Each requirement() call is recorded for coverage reporting
|
|
8
8
|
*/
|
|
9
|
-
import * as path from
|
|
10
|
-
import {
|
|
9
|
+
import * as path from "node:path";
|
|
10
|
+
import { appendTrackingEntry, clearTrackingFile, findProjectRoot, findRequirementsDir, getCacheDir, getTestRunId, initTestRunId, } from "./cache.js";
|
|
11
11
|
const trackedRequirements = new Map();
|
|
12
12
|
// Test run tracking
|
|
13
13
|
let testRunId = null;
|
|
@@ -17,7 +17,7 @@ export function ensureTestRun() {
|
|
|
17
17
|
if (!testRunId) {
|
|
18
18
|
// Priority 1: Use environment variable (cross-process persistence from globalSetup)
|
|
19
19
|
if (process.env.DOTREQUIREMENTS_PROJECT_ROOT) {
|
|
20
|
-
requirementsDirCached = path.join(process.env.DOTREQUIREMENTS_PROJECT_ROOT,
|
|
20
|
+
requirementsDirCached = path.join(process.env.DOTREQUIREMENTS_PROJECT_ROOT, ".requirements");
|
|
21
21
|
}
|
|
22
22
|
// Priority 2: Find from caller directory
|
|
23
23
|
if (!requirementsDirCached) {
|
|
@@ -29,7 +29,7 @@ export function ensureTestRun() {
|
|
|
29
29
|
}
|
|
30
30
|
}
|
|
31
31
|
if (!requirementsDirCached) {
|
|
32
|
-
throw new Error(
|
|
32
|
+
throw new Error("Could not find .requirements directory. Please create one in your project root.");
|
|
33
33
|
}
|
|
34
34
|
// Try to read from shared test run ID file (set by prepare())
|
|
35
35
|
const existingRunId = getTestRunId(requirementsDirCached);
|
|
@@ -48,14 +48,14 @@ export function ensureTestRun() {
|
|
|
48
48
|
// Get caller location for tracking
|
|
49
49
|
export function getCallerLocation() {
|
|
50
50
|
const error = new Error();
|
|
51
|
-
const stack = error.stack?.split(
|
|
51
|
+
const stack = error.stack?.split("\n") || [];
|
|
52
52
|
// Find the first stack frame that's not in our library files
|
|
53
53
|
for (let i = 2; i < stack.length; i++) {
|
|
54
54
|
const frame = stack[i];
|
|
55
|
-
if (!frame.includes(
|
|
56
|
-
!frame.includes(
|
|
57
|
-
!frame.includes(
|
|
58
|
-
!frame.includes(
|
|
55
|
+
if (!frame.includes("/harness/index.ts") &&
|
|
56
|
+
!frame.includes("/harness/index.js") &&
|
|
57
|
+
!frame.includes("/harness/tracking.ts") &&
|
|
58
|
+
!frame.includes("/harness/tracking.js")) {
|
|
59
59
|
// Extract filename and line number
|
|
60
60
|
const regex1 = /\((.+):(\d+):(\d+)\)/;
|
|
61
61
|
const regex2 = /at (.+):(\d+):(\d+)/;
|
|
@@ -67,19 +67,19 @@ export function getCallerLocation() {
|
|
|
67
67
|
}
|
|
68
68
|
}
|
|
69
69
|
}
|
|
70
|
-
return
|
|
70
|
+
return "unknown";
|
|
71
71
|
}
|
|
72
72
|
// Get caller's directory (full path) for finding .requirements
|
|
73
73
|
function getCallerDirectory() {
|
|
74
74
|
const error = new Error();
|
|
75
|
-
const stack = error.stack?.split(
|
|
75
|
+
const stack = error.stack?.split("\n") || [];
|
|
76
76
|
// Find the first stack frame that's not in our library files
|
|
77
77
|
for (let i = 2; i < stack.length; i++) {
|
|
78
78
|
const frame = stack[i];
|
|
79
|
-
if (!frame.includes(
|
|
80
|
-
!frame.includes(
|
|
81
|
-
!frame.includes(
|
|
82
|
-
!frame.includes(
|
|
79
|
+
if (!frame.includes("/harness/index.ts") &&
|
|
80
|
+
!frame.includes("/harness/index.js") &&
|
|
81
|
+
!frame.includes("/harness/tracking.ts") &&
|
|
82
|
+
!frame.includes("/harness/tracking.js")) {
|
|
83
83
|
// Extract filename
|
|
84
84
|
const regex1 = /\((.+):(\d+):(\d+)\)/;
|
|
85
85
|
const regex2 = /at (.+):(\d+):(\d+)/;
|
|
@@ -154,7 +154,7 @@ export function clearTracking() {
|
|
|
154
154
|
export function initTestRun() {
|
|
155
155
|
const projectRoot = findProjectRoot();
|
|
156
156
|
if (!projectRoot) {
|
|
157
|
-
throw new Error(
|
|
157
|
+
throw new Error("Could not find .requirements directory. Please create one in your project root.");
|
|
158
158
|
}
|
|
159
159
|
const reqDir = findRequirementsDir();
|
|
160
160
|
// Initialize test run ID
|
|
@@ -171,9 +171,9 @@ export function initTestRun() {
|
|
|
171
171
|
export function finalizeTestRun() {
|
|
172
172
|
// Import and call the new finalize function
|
|
173
173
|
// Using dynamic import to avoid circular dependencies
|
|
174
|
-
const { finalize } = require(
|
|
174
|
+
const { finalize } = require("./finalize.js");
|
|
175
175
|
finalize().catch((error) => {
|
|
176
|
-
console.error(
|
|
176
|
+
console.error("Error in finalizeTestRun:", error.message);
|
|
177
177
|
});
|
|
178
178
|
}
|
|
179
179
|
//# sourceMappingURL=tracking.js.map
|
package/dist/harness/types.d.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Type definitions for test harness.
|
|
3
3
|
* Uses shared schema types for consistency with CLI and MCP.
|
|
4
4
|
*/
|
|
5
|
-
import type { RequirementNode } from
|
|
5
|
+
import type { RequirementNode } from "../schema/index.js";
|
|
6
6
|
export type { RequirementNode as Requirement };
|
|
7
7
|
export interface CriteriaDetail {
|
|
8
8
|
reqId: string;
|