@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,150 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Extract test code context using @babel/parser AST traversal.
|
|
3
|
+
*
|
|
4
|
+
* Finds requirement() call references and extracts the enclosing
|
|
5
|
+
* meaningful code block (function, describe, test, etc.)
|
|
6
|
+
*/
|
|
7
|
+
import * as fs from "node:fs";
|
|
8
|
+
import { parse } from "@babel/parser";
|
|
9
|
+
import traverse from "@babel/traverse";
|
|
10
|
+
import * as t from "@babel/types";
|
|
11
|
+
/**
|
|
12
|
+
* Find all test code blocks that reference a specific requirement
|
|
13
|
+
*/
|
|
14
|
+
export function findTestCodeForRequirement(filePath, requirementId) {
|
|
15
|
+
try {
|
|
16
|
+
const code = fs.readFileSync(filePath, "utf-8");
|
|
17
|
+
const results = [];
|
|
18
|
+
// Parse with TypeScript and JSX support
|
|
19
|
+
const ast = parse(code, {
|
|
20
|
+
sourceType: "module",
|
|
21
|
+
plugins: ["typescript", "jsx"],
|
|
22
|
+
errorRecovery: true,
|
|
23
|
+
});
|
|
24
|
+
// Handle both ES module and CommonJS exports
|
|
25
|
+
const traverseFunc =
|
|
26
|
+
// biome-ignore lint/suspicious/noExplicitAny: @babel/traverse CJS default-export interop (callable function vs namespace import)
|
|
27
|
+
typeof traverse === "function" ? traverse : traverse.default;
|
|
28
|
+
traverseFunc(ast, {
|
|
29
|
+
CallExpression(path) {
|
|
30
|
+
// Check if this is a requirement('ID', ...) call
|
|
31
|
+
const callee = path.node.callee;
|
|
32
|
+
if (t.isIdentifier(callee) && callee.name === "requirement") {
|
|
33
|
+
const args = path.node.arguments;
|
|
34
|
+
// Extract all string literal arguments (supports multi-requirement calls)
|
|
35
|
+
const refIds = [];
|
|
36
|
+
for (const arg of args) {
|
|
37
|
+
if (t.isStringLiteral(arg)) {
|
|
38
|
+
refIds.push(arg.value);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
// Check if any argument matches the requirement we're looking for
|
|
42
|
+
// Match exact ID or if it's a child (e.g., searching for REQ-123 matches REQ-123.0)
|
|
43
|
+
for (const refId of refIds) {
|
|
44
|
+
const isMatch = refId === requirementId || refId.startsWith(`${requirementId}.`);
|
|
45
|
+
if (isMatch) {
|
|
46
|
+
// Find the meaningful enclosing block
|
|
47
|
+
const contextNode = findMeaningfulParent(path);
|
|
48
|
+
if (contextNode?.node.loc) {
|
|
49
|
+
const { start, end } = contextNode.node.loc;
|
|
50
|
+
const nodeStart = contextNode.node.start ?? 0;
|
|
51
|
+
const nodeEnd = contextNode.node.end ?? code.length;
|
|
52
|
+
results.push({
|
|
53
|
+
file: filePath,
|
|
54
|
+
startLine: start.line,
|
|
55
|
+
endLine: end.line,
|
|
56
|
+
code: code.slice(nodeStart, nodeEnd),
|
|
57
|
+
requirementId: refId,
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
// Only add one result per call expression, even if multiple refs match
|
|
61
|
+
break;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
},
|
|
66
|
+
});
|
|
67
|
+
return results;
|
|
68
|
+
}
|
|
69
|
+
catch (error) {
|
|
70
|
+
console.error(`Error parsing ${filePath}:`, error);
|
|
71
|
+
return [];
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Walk up the AST to find the nearest "meaningful" parent node.
|
|
76
|
+
* This could be a function, describe/test/it call, method, etc.
|
|
77
|
+
*/
|
|
78
|
+
function findMeaningfulParent(path) {
|
|
79
|
+
let current = path;
|
|
80
|
+
while (current) {
|
|
81
|
+
const node = current.node;
|
|
82
|
+
// Check for various meaningful boundaries
|
|
83
|
+
if (t.isFunctionDeclaration(node) ||
|
|
84
|
+
t.isFunctionExpression(node) ||
|
|
85
|
+
t.isArrowFunctionExpression(node) ||
|
|
86
|
+
t.isClassMethod(node) ||
|
|
87
|
+
t.isObjectMethod(node)) {
|
|
88
|
+
return current;
|
|
89
|
+
}
|
|
90
|
+
// Check for call expressions (describe, test, it, etc.)
|
|
91
|
+
if (t.isCallExpression(node)) {
|
|
92
|
+
const callee = node.callee;
|
|
93
|
+
// Common test framework function names
|
|
94
|
+
const testFunctionNames = [
|
|
95
|
+
"describe",
|
|
96
|
+
"it",
|
|
97
|
+
"test",
|
|
98
|
+
"suite",
|
|
99
|
+
"context",
|
|
100
|
+
"beforeEach",
|
|
101
|
+
"afterEach",
|
|
102
|
+
"beforeAll",
|
|
103
|
+
"afterAll",
|
|
104
|
+
];
|
|
105
|
+
if (t.isIdentifier(callee) && testFunctionNames.includes(callee.name)) {
|
|
106
|
+
return current;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
// Check for variable declarations that might contain test functions
|
|
110
|
+
if (t.isVariableDeclarator(node)) {
|
|
111
|
+
return current;
|
|
112
|
+
}
|
|
113
|
+
// Check for export declarations (for Storybook stories, etc.)
|
|
114
|
+
if (t.isExportNamedDeclaration(node) ||
|
|
115
|
+
t.isExportDefaultDeclaration(node)) {
|
|
116
|
+
return current;
|
|
117
|
+
}
|
|
118
|
+
current = current.parentPath;
|
|
119
|
+
}
|
|
120
|
+
return null;
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Find all files that reference a requirement
|
|
124
|
+
*/
|
|
125
|
+
export function findFilesWithRequirement(files, requirementId) {
|
|
126
|
+
const matchingFiles = [];
|
|
127
|
+
for (const file of files) {
|
|
128
|
+
try {
|
|
129
|
+
const code = fs.readFileSync(file, "utf-8");
|
|
130
|
+
// Check for exact match or child references (e.g., AUTH-VALID-LOGIN or AUTH-VALID-LOGIN.0)
|
|
131
|
+
// Simple string search first for performance
|
|
132
|
+
// Patterns match both single and multi-arg calls:
|
|
133
|
+
// requirement('REQ-123')
|
|
134
|
+
// requirement('REQ-123', 'REQ-456')
|
|
135
|
+
// requirement('REQ-456', 'REQ-123') <-- ID anywhere in args
|
|
136
|
+
const hasMatch = code.includes(`'${requirementId}'`) ||
|
|
137
|
+
code.includes(`"${requirementId}"`) ||
|
|
138
|
+
code.includes(`\`${requirementId}\``) ||
|
|
139
|
+
code.includes(`'${requirementId}.`) ||
|
|
140
|
+
code.includes(`"${requirementId}.`) ||
|
|
141
|
+
code.includes(`\`${requirementId}.`);
|
|
142
|
+
if (hasMatch) {
|
|
143
|
+
matchingFiles.push(file);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
catch { }
|
|
147
|
+
}
|
|
148
|
+
return matchingFiles;
|
|
149
|
+
}
|
|
150
|
+
//# sourceMappingURL=testCodeExtractor.js.map
|
package/dist/schema/browser.d.ts
CHANGED
|
@@ -3,12 +3,12 @@
|
|
|
3
3
|
* This file excludes Node.js-specific functionality (file I/O, fs module).
|
|
4
4
|
* Use this entry point when importing from browser/web environments.
|
|
5
5
|
*/
|
|
6
|
-
export {
|
|
7
|
-
export type {
|
|
8
|
-
export {
|
|
9
|
-
export
|
|
10
|
-
export {
|
|
11
|
-
export {
|
|
12
|
-
export {
|
|
13
|
-
export
|
|
6
|
+
export { buildRequirementMarkdown, buildRequirementsMarkdown, DEFAULT_DELIMITER, } from "./builder.js";
|
|
7
|
+
export type { ConvexRequirement } from "./conversions.js";
|
|
8
|
+
export { buildMetadata, constructKey, convexToRequirements, extractRequirementKeys, groupByRoot, parseKey, requirementsToConvex, } from "./conversions.js";
|
|
9
|
+
export { DELIMITER_PATTERN, extractRequirementBlocks, findRequirementById, flattenRequirementTree, getAllRequirements, parseCriterionLine, parseRequirementBlock, parseRequirementBlocksFromMarkdown, parseRootLine, } from "./parser-core.js";
|
|
10
|
+
export type { Metadata, ParsedCriterion, RequirementKey, RequirementNode, RequirementPrefix, RequirementsFile, } from "./schemas.js";
|
|
11
|
+
export { buildRequirementKey, MetadataSchema, normalizePrefix, ParsedCriterionSchema, parseRequirementKey, REQUIREMENT_KEY_PATTERN, REQUIREMENT_PREFIX_PATTERN, RequirementKeySchema, RequirementNodeSchema, RequirementPrefixSchema, RequirementsFileSchema, ValidationError, validateKey, validateMetadata, validatePrefix, validateRequirementNode, validateRequirementsFile, } from "./schemas.js";
|
|
12
|
+
export type { BuildScenarioOptions, Scenario, ScenarioAssertionSource, ScenarioStep, } from "./scenario.js";
|
|
13
|
+
export { buildScenarioFromRequirements, requirementTreeToScenario, } from "./scenario.js";
|
|
14
14
|
//# sourceMappingURL=browser.d.ts.map
|
package/dist/schema/browser.js
CHANGED
|
@@ -3,24 +3,22 @@
|
|
|
3
3
|
* This file excludes Node.js-specific functionality (file I/O, fs module).
|
|
4
4
|
* Use this entry point when importing from browser/web environments.
|
|
5
5
|
*/
|
|
6
|
+
// Building (uses yaml package - browser-safe)
|
|
7
|
+
export { buildRequirementMarkdown, buildRequirementsMarkdown, DEFAULT_DELIMITER, } from "./builder.js";
|
|
8
|
+
export { buildMetadata, constructKey, convexToRequirements, extractRequirementKeys, groupByRoot, parseKey, requirementsToConvex, } from "./conversions.js";
|
|
9
|
+
// Parser core (pure TypeScript - browser-safe, no fs dependency)
|
|
10
|
+
// These functions parse markdown strings directly without file I/O
|
|
11
|
+
export { DELIMITER_PATTERN, extractRequirementBlocks, findRequirementById, flattenRequirementTree, getAllRequirements, parseCriterionLine, parseRequirementBlock, parseRequirementBlocksFromMarkdown, parseRootLine, } from "./parser-core.js";
|
|
6
12
|
// Schemas and types (uses zod - browser-safe)
|
|
7
|
-
export {
|
|
13
|
+
export { buildRequirementKey,
|
|
8
14
|
// Zod schemas
|
|
9
|
-
MetadataSchema,
|
|
15
|
+
MetadataSchema,
|
|
16
|
+
// Prefix/key utilities
|
|
17
|
+
normalizePrefix, ParsedCriterionSchema, parseRequirementKey, REQUIREMENT_KEY_PATTERN,
|
|
10
18
|
// Patterns (for external validation)
|
|
11
|
-
REQUIREMENT_PREFIX_PATTERN,
|
|
19
|
+
REQUIREMENT_PREFIX_PATTERN, RequirementKeySchema, RequirementNodeSchema, RequirementPrefixSchema, RequirementsFileSchema,
|
|
12
20
|
// Validation
|
|
13
|
-
ValidationError, validateMetadata, validateRequirementNode, validateRequirementsFile,
|
|
14
|
-
// Prefix/key utilities
|
|
15
|
-
normalizePrefix, parseRequirementKey, buildRequirementKey, } from './schemas.js';
|
|
16
|
-
// Building (uses yaml package - browser-safe)
|
|
17
|
-
export { DEFAULT_DELIMITER, buildRequirementsMarkdown, buildRequirementMarkdown, } from './builder.js';
|
|
18
|
-
export { convexToRequirements, requirementsToConvex, buildMetadata, extractRequirementKeys, groupByRoot, constructKey, parseKey, } from './conversions.js';
|
|
19
|
-
// Parser core (pure TypeScript - browser-safe, no fs dependency)
|
|
20
|
-
// These functions parse markdown strings directly without file I/O
|
|
21
|
-
export { DELIMITER_PATTERN, parseCriterionLine, parseRootLine, parseRequirementBlock, extractRequirementBlocks, parseRequirementBlocksFromMarkdown, flattenRequirementTree, findRequirementById, getAllRequirements, } from './parser-core.js';
|
|
22
|
-
// NOTE: parser.ts and resolver.ts are excluded because they use Node.js 'fs' module.
|
|
23
|
-
// Use parser-core.ts functions above for browser/Convex environments.
|
|
21
|
+
ValidationError, validateKey, validateMetadata, validatePrefix, validateRequirementNode, validateRequirementsFile, } from "./schemas.js";
|
|
24
22
|
// Scenario building (pure TypeScript - browser-safe, used by Convex Node actions)
|
|
25
|
-
export { buildScenarioFromRequirements, requirementTreeToScenario, } from
|
|
23
|
+
export { buildScenarioFromRequirements, requirementTreeToScenario, } from "./scenario.js";
|
|
26
24
|
//# sourceMappingURL=browser.js.map
|
package/dist/schema/builder.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Build Markdown requirements files from structured data.
|
|
3
3
|
*/
|
|
4
|
-
import {
|
|
4
|
+
import type { Metadata, RequirementNode } from "./schemas.js";
|
|
5
5
|
/**
|
|
6
6
|
* Default delimiter for requirements.
|
|
7
7
|
* Can be overridden for organization-specific preferences.
|
package/dist/schema/builder.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Build Markdown requirements files from structured data.
|
|
3
3
|
*/
|
|
4
|
-
import YAML from
|
|
4
|
+
import YAML from "yaml";
|
|
5
5
|
/**
|
|
6
6
|
* Default delimiter for requirements.
|
|
7
7
|
* Can be overridden for organization-specific preferences.
|
|
8
8
|
*/
|
|
9
|
-
export const DEFAULT_DELIMITER =
|
|
9
|
+
export const DEFAULT_DELIMITER = "→";
|
|
10
10
|
/**
|
|
11
11
|
* Build YAML frontmatter from metadata.
|
|
12
12
|
*/
|
|
@@ -17,51 +17,20 @@ function buildFrontmatter(metadata) {
|
|
|
17
17
|
});
|
|
18
18
|
return `---\n${yamlStr.trim()}\n---`;
|
|
19
19
|
}
|
|
20
|
-
/**
|
|
21
|
-
* Build a dotrequirements block from a requirement node.
|
|
22
|
-
* Formats children with explicit position paths and proper indentation.
|
|
23
|
-
*/
|
|
24
|
-
function buildRequirementBlock(node, delimiter = DEFAULT_DELIMITER) {
|
|
25
|
-
// First line: root requirement with delimiter
|
|
26
|
-
// Include label if it's not empty (empty string means unlabeled)
|
|
27
|
-
const rootLabel = node.label
|
|
28
|
-
? `${node.label.charAt(0).toUpperCase() + node.label.slice(1)} `
|
|
29
|
-
: '';
|
|
30
|
-
let block = `${rootLabel}${delimiter} ${node.content}\n`;
|
|
31
|
-
// Recursively build criteria lines
|
|
32
|
-
function addCriteria(children, parentPosition = '') {
|
|
33
|
-
children.forEach((child, index) => {
|
|
34
|
-
const position = parentPosition === '' ? `${index}` : `${parentPosition}.${index}`;
|
|
35
|
-
const depth = position.split('.').length - 1;
|
|
36
|
-
const indent = ' '.repeat(depth + 1); // 2 spaces per level
|
|
37
|
-
// Include label if present, otherwise just delimiter
|
|
38
|
-
const labelPart = child.label
|
|
39
|
-
? `${child.label.charAt(0).toUpperCase() + child.label.slice(1)} `
|
|
40
|
-
: '';
|
|
41
|
-
block += `${indent}${position}. ${labelPart}${delimiter} ${child.content}\n`;
|
|
42
|
-
// Recursively add grandchildren
|
|
43
|
-
if (child.children && child.children.length > 0) {
|
|
44
|
-
addCriteria(child.children, position);
|
|
45
|
-
}
|
|
46
|
-
});
|
|
47
|
-
}
|
|
48
|
-
addCriteria(node.children);
|
|
49
|
-
return block.trimEnd();
|
|
50
|
-
}
|
|
51
20
|
/**
|
|
52
21
|
* Build the children portion of a requirement block (without the root line).
|
|
53
22
|
*/
|
|
54
23
|
function buildChildrenBlock(children) {
|
|
55
|
-
let block =
|
|
56
|
-
function addChildren(nodes, parentPosition =
|
|
24
|
+
let block = "";
|
|
25
|
+
function addChildren(nodes, parentPosition = "") {
|
|
57
26
|
nodes.forEach((child, index) => {
|
|
58
|
-
const position = parentPosition ===
|
|
59
|
-
const depth = position.split(
|
|
60
|
-
const indent =
|
|
27
|
+
const position = parentPosition === "" ? `${index}` : `${parentPosition}.${index}`;
|
|
28
|
+
const depth = position.split(".").length - 1;
|
|
29
|
+
const indent = " ".repeat(depth + 1); // 2 spaces per level
|
|
61
30
|
// Include label if present, otherwise just delimiter
|
|
62
31
|
const labelPart = child.label
|
|
63
32
|
? `${child.label.charAt(0).toUpperCase() + child.label.slice(1)} `
|
|
64
|
-
:
|
|
33
|
+
: "";
|
|
65
34
|
block += `${indent}${position}. ${labelPart}→ ${child.content}\n`;
|
|
66
35
|
// Recursively add grandchildren
|
|
67
36
|
if (child.children && child.children.length > 0) {
|
|
@@ -79,14 +48,14 @@ function buildRequirementSection(node, title) {
|
|
|
79
48
|
const displayTitle = title || node.content;
|
|
80
49
|
// Heading now just has the title, no key
|
|
81
50
|
let section = `## ${displayTitle}\n\n`;
|
|
82
|
-
section +=
|
|
51
|
+
section += "```dotrequirements\n";
|
|
83
52
|
// First line of block has the key
|
|
84
53
|
section += `${node.id}: ${node.content}\n`;
|
|
85
54
|
// Then add children
|
|
86
55
|
if (node.children && node.children.length > 0) {
|
|
87
56
|
section += buildChildrenBlock(node.children);
|
|
88
57
|
}
|
|
89
|
-
section +=
|
|
58
|
+
section += "\n```\n";
|
|
90
59
|
return section;
|
|
91
60
|
}
|
|
92
61
|
/**
|
|
@@ -94,7 +63,7 @@ function buildRequirementSection(node, title) {
|
|
|
94
63
|
*/
|
|
95
64
|
export function buildRequirementsMarkdown(metadata, requirements, documentTitle) {
|
|
96
65
|
let markdown = buildFrontmatter(metadata);
|
|
97
|
-
markdown +=
|
|
66
|
+
markdown += "\n\n";
|
|
98
67
|
// Add document title if provided
|
|
99
68
|
if (documentTitle) {
|
|
100
69
|
markdown += `# ${documentTitle}\n\n`;
|
|
@@ -102,9 +71,9 @@ export function buildRequirementsMarkdown(metadata, requirements, documentTitle)
|
|
|
102
71
|
// Add each requirement section
|
|
103
72
|
for (const req of requirements) {
|
|
104
73
|
markdown += buildRequirementSection(req);
|
|
105
|
-
markdown +=
|
|
74
|
+
markdown += "\n";
|
|
106
75
|
}
|
|
107
|
-
return markdown.trimEnd()
|
|
76
|
+
return `${markdown.trimEnd()}\n`;
|
|
108
77
|
}
|
|
109
78
|
/**
|
|
110
79
|
* Build Markdown for a single requirement (for testing/debugging).
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Convert between Convex flat representation and hierarchical RequirementNode trees.
|
|
3
3
|
*/
|
|
4
|
-
import {
|
|
4
|
+
import type { Metadata, RequirementNode } from "./schemas.js";
|
|
5
5
|
/**
|
|
6
6
|
* Convex requirement type (flat structure with position paths).
|
|
7
7
|
* This mirrors the Convex database schema.
|
|
@@ -16,7 +16,7 @@ export interface ConvexRequirement {
|
|
|
16
16
|
projectId: string;
|
|
17
17
|
rootId?: string;
|
|
18
18
|
position?: string;
|
|
19
|
-
metadata?:
|
|
19
|
+
metadata?: unknown;
|
|
20
20
|
externalLinks?: {
|
|
21
21
|
jira?: string;
|
|
22
22
|
notion?: string;
|
|
@@ -25,7 +25,7 @@ export function parseKey(key) {
|
|
|
25
25
|
*/
|
|
26
26
|
export function convexToRequirements(convexReqs) {
|
|
27
27
|
// Separate roots from children
|
|
28
|
-
const roots = convexReqs.filter(r => !r.rootId);
|
|
28
|
+
const roots = convexReqs.filter((r) => !r.rootId);
|
|
29
29
|
// Build a map of all requirements by their position path for each root
|
|
30
30
|
const reqsByRoot = new Map();
|
|
31
31
|
for (const req of convexReqs) {
|
|
@@ -35,11 +35,11 @@ export function convexToRequirements(convexReqs) {
|
|
|
35
35
|
rootMap = new Map();
|
|
36
36
|
reqsByRoot.set(req.rootId, rootMap);
|
|
37
37
|
}
|
|
38
|
-
rootMap.set(req.position ||
|
|
38
|
+
rootMap.set(req.position || "", req);
|
|
39
39
|
}
|
|
40
40
|
}
|
|
41
41
|
// Build trees for each root
|
|
42
|
-
return roots.map(root => buildTreeFromPositions(root, reqsByRoot.get(root._id)));
|
|
42
|
+
return roots.map((root) => buildTreeFromPositions(root, reqsByRoot.get(root._id)));
|
|
43
43
|
}
|
|
44
44
|
/**
|
|
45
45
|
* Recursively build a RequirementNode tree from position-based flat structure.
|
|
@@ -70,9 +70,9 @@ function buildTreeFromPositions(convexReq, positionMap) {
|
|
|
70
70
|
// Find direct children based on position paths
|
|
71
71
|
// If this is a root (no position), find children at positions like ".0", ".1"
|
|
72
72
|
// If this has position ".0", find children at positions like ".0.0", ".0.1"
|
|
73
|
-
const currentPosition = convexReq.position ||
|
|
73
|
+
const currentPosition = convexReq.position || "";
|
|
74
74
|
const childPositionPattern = currentPosition
|
|
75
|
-
? new RegExp(`^${currentPosition.replace(/\./g,
|
|
75
|
+
? new RegExp(`^${currentPosition.replace(/\./g, "\\.")}\\.\\d+$`)
|
|
76
76
|
: /^\.\d+$/;
|
|
77
77
|
const children = [];
|
|
78
78
|
for (const [pos, req] of positionMap.entries()) {
|
|
@@ -82,10 +82,10 @@ function buildTreeFromPositions(convexReq, positionMap) {
|
|
|
82
82
|
}
|
|
83
83
|
// Sort children by position
|
|
84
84
|
const sortedChildren = children.sort((a, b) => {
|
|
85
|
-
return comparePositions(a.position ||
|
|
85
|
+
return comparePositions(a.position || "", b.position || "");
|
|
86
86
|
});
|
|
87
87
|
// Recursively build child nodes
|
|
88
|
-
node.children = sortedChildren.map(child => buildTreeFromPositions(child, positionMap));
|
|
88
|
+
node.children = sortedChildren.map((child) => buildTreeFromPositions(child, positionMap));
|
|
89
89
|
return node;
|
|
90
90
|
}
|
|
91
91
|
/**
|
|
@@ -93,8 +93,8 @@ function buildTreeFromPositions(convexReq, positionMap) {
|
|
|
93
93
|
* Positions are like ".0", ".1", ".0.0", ".0.1"
|
|
94
94
|
*/
|
|
95
95
|
function comparePositions(a, b) {
|
|
96
|
-
const aParts = a.split(
|
|
97
|
-
const bParts = b.split(
|
|
96
|
+
const aParts = a.split(".").filter(Boolean).map(Number);
|
|
97
|
+
const bParts = b.split(".").filter(Boolean).map(Number);
|
|
98
98
|
for (let i = 0; i < Math.max(aParts.length, bParts.length); i++) {
|
|
99
99
|
const aVal = aParts[i] ?? -1;
|
|
100
100
|
const bVal = bParts[i] ?? -1;
|
|
@@ -125,7 +125,7 @@ function flattenNode(node, projectId, rootId, position, result, documentId) {
|
|
|
125
125
|
// Get prefix/index from metadata (if from round-trip) or parse from node.id
|
|
126
126
|
let prefix;
|
|
127
127
|
let index;
|
|
128
|
-
if (node.metadata?.prefix && typeof node.metadata?.index ===
|
|
128
|
+
if (node.metadata?.prefix && typeof node.metadata?.index === "number") {
|
|
129
129
|
// Round-trip case: use stored prefix/index
|
|
130
130
|
prefix = node.metadata.prefix;
|
|
131
131
|
index = node.metadata.index;
|
|
@@ -181,7 +181,7 @@ export function buildMetadata(version = 1, document) {
|
|
|
181
181
|
* Useful for detecting duplicates or tracking which requirements exist.
|
|
182
182
|
*/
|
|
183
183
|
export function extractRequirementKeys(convexReqs) {
|
|
184
|
-
return new Set(convexReqs.map(r => constructKey(r.prefix, r.index)));
|
|
184
|
+
return new Set(convexReqs.map((r) => constructKey(r.prefix, r.index)));
|
|
185
185
|
}
|
|
186
186
|
/**
|
|
187
187
|
* Group Convex requirements by their root.
|
package/dist/schema/index.d.ts
CHANGED
|
@@ -4,13 +4,13 @@
|
|
|
4
4
|
* This module provides types, validation, parsing, and building utilities
|
|
5
5
|
* for the Markdown requirements format.
|
|
6
6
|
*/
|
|
7
|
-
export {
|
|
8
|
-
export type {
|
|
9
|
-
export {
|
|
10
|
-
export {
|
|
11
|
-
export {
|
|
12
|
-
export type {
|
|
13
|
-
export {
|
|
14
|
-
export {
|
|
15
|
-
export
|
|
7
|
+
export { buildRequirementMarkdown, buildRequirementsFile, buildRequirementsMarkdown, } from "./builder.js";
|
|
8
|
+
export type { ConvexRequirement } from "./conversions.js";
|
|
9
|
+
export { buildMetadata, constructKey, convexToRequirements, extractRequirementKeys, groupByRoot, parseKey, requirementsToConvex, } from "./conversions.js";
|
|
10
|
+
export { findRequirementById, flattenRequirementTree, getAllRequirements, parseCriterionLine, parseRequirementBlock, parseRequirementsFile, parseRequirementsFromFile, } from "./parser.js";
|
|
11
|
+
export { checkPathAmbiguity, findChildrenByLabel, getAllLabelPaths, parsePathSegment, parseRequirementPath, resolvePathSegment, resolveRequirementPath, resolveToNumericPath, } from "./resolver.js";
|
|
12
|
+
export type { BuildScenarioOptions, Scenario, ScenarioAssertionSource, ScenarioStep, } from "./scenario.js";
|
|
13
|
+
export { buildScenarioFromRequirements, requirementTreeToScenario, } from "./scenario.js";
|
|
14
|
+
export type { Metadata, ParsedCriterion, PushValidationResult, RequirementKey, RequirementNode, RequirementPrefix, RequirementsFile, } from "./schemas.js";
|
|
15
|
+
export { buildRequirementKey, CONVEX_ID_PATTERN, MetadataSchema, normalizePrefix, ParsedCriterionSchema, parseRequirementKey, REQUIREMENT_KEY_PATTERN, REQUIREMENT_PREFIX_PATTERN, RequirementKeySchema, RequirementNodeSchema, RequirementPrefixSchema, RequirementsFileSchema, ValidationError, validateForPush, validateKey, validateMetadata, validatePrefix, validateRequirementNode, validateRequirementsFile, } from "./schemas.js";
|
|
16
16
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/schema/index.js
CHANGED
|
@@ -4,23 +4,23 @@
|
|
|
4
4
|
* This module provides types, validation, parsing, and building utilities
|
|
5
5
|
* for the Markdown requirements format.
|
|
6
6
|
*/
|
|
7
|
+
// Building
|
|
8
|
+
export { buildRequirementMarkdown, buildRequirementsFile, buildRequirementsMarkdown, } from "./builder.js";
|
|
9
|
+
export { buildMetadata, constructKey, convexToRequirements, extractRequirementKeys, groupByRoot, parseKey, requirementsToConvex, } from "./conversions.js";
|
|
10
|
+
// Parsing
|
|
11
|
+
export { findRequirementById, flattenRequirementTree, getAllRequirements, parseCriterionLine, parseRequirementBlock, parseRequirementsFile, parseRequirementsFromFile, } from "./parser.js";
|
|
12
|
+
// Path resolution
|
|
13
|
+
export { checkPathAmbiguity, findChildrenByLabel, getAllLabelPaths, parsePathSegment, parseRequirementPath, resolvePathSegment, resolveRequirementPath, resolveToNumericPath, } from "./resolver.js";
|
|
14
|
+
// Scenario building (for browser-automation / runScenario)
|
|
15
|
+
export { buildScenarioFromRequirements, requirementTreeToScenario, } from "./scenario.js";
|
|
7
16
|
// Schemas and types
|
|
8
|
-
export {
|
|
17
|
+
export { buildRequirementKey, CONVEX_ID_PATTERN,
|
|
9
18
|
// Zod schemas
|
|
10
|
-
MetadataSchema,
|
|
19
|
+
MetadataSchema,
|
|
20
|
+
// Prefix/key utilities
|
|
21
|
+
normalizePrefix, ParsedCriterionSchema, parseRequirementKey, REQUIREMENT_KEY_PATTERN,
|
|
11
22
|
// Patterns (for external validation)
|
|
12
|
-
REQUIREMENT_PREFIX_PATTERN,
|
|
23
|
+
REQUIREMENT_PREFIX_PATTERN, RequirementKeySchema, RequirementNodeSchema, RequirementPrefixSchema, RequirementsFileSchema,
|
|
13
24
|
// Validation
|
|
14
|
-
ValidationError,
|
|
15
|
-
// Prefix/key utilities
|
|
16
|
-
normalizePrefix, parseRequirementKey, buildRequirementKey, } from './schemas.js';
|
|
17
|
-
// Parsing
|
|
18
|
-
export { parseCriterionLine, parseRequirementBlock, parseRequirementsFile, parseRequirementsFromFile, flattenRequirementTree, findRequirementById, getAllRequirements, } from './parser.js';
|
|
19
|
-
// Building
|
|
20
|
-
export { buildRequirementsMarkdown, buildRequirementMarkdown, buildRequirementsFile, } from './builder.js';
|
|
21
|
-
// Path resolution
|
|
22
|
-
export { parseRequirementPath, parsePathSegment, findChildrenByLabel, resolvePathSegment, resolveRequirementPath, resolveToNumericPath, getAllLabelPaths, checkPathAmbiguity, } from './resolver.js';
|
|
23
|
-
export { convexToRequirements, requirementsToConvex, buildMetadata, extractRequirementKeys, groupByRoot, constructKey, parseKey, } from './conversions.js';
|
|
24
|
-
// Scenario building (for browser-automation / runScenario)
|
|
25
|
-
export { buildScenarioFromRequirements, requirementTreeToScenario, } from './scenario.js';
|
|
25
|
+
ValidationError, validateForPush, validateKey, validateMetadata, validatePrefix, validateRequirementNode, validateRequirementsFile, } from "./schemas.js";
|
|
26
26
|
//# sourceMappingURL=index.js.map
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* This module contains pure parsing functions with no Node.js dependencies,
|
|
5
5
|
* making it safe to import in Convex runtime or browser environments.
|
|
6
6
|
*/
|
|
7
|
-
import {
|
|
7
|
+
import { type ParsedCriterion, type RequirementNode } from "./schemas.js";
|
|
8
8
|
/**
|
|
9
9
|
* Default delimiter for requirements.
|
|
10
10
|
* Can be overridden for organization-specific preferences.
|