eslint-plugin-traceability 1.21.0 → 1.22.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/CHANGELOG.md +7 -2
- package/README.md +6 -6
- package/lib/src/maintenance/batch.js +0 -1
- package/lib/src/maintenance/cli.js +8 -10
- package/lib/src/maintenance/commands.d.ts +2 -2
- package/lib/src/maintenance/commands.js +2 -2
- package/lib/src/maintenance/detect.js +7 -7
- package/lib/src/maintenance/report.js +2 -2
- package/lib/src/maintenance/storyParser.d.ts +16 -0
- package/lib/src/maintenance/storyParser.js +167 -0
- package/lib/src/rules/helpers/pattern-validators.d.ts +42 -0
- package/lib/src/rules/helpers/pattern-validators.js +65 -0
- package/lib/src/rules/helpers/prefer-implements-inline.d.ts +16 -0
- package/lib/src/rules/helpers/prefer-implements-inline.js +146 -0
- package/lib/src/rules/helpers/require-story-comment-detection.d.ts +47 -0
- package/lib/src/rules/helpers/require-story-comment-detection.js +141 -0
- package/lib/src/rules/helpers/require-story-core.d.ts +6 -6
- package/lib/src/rules/helpers/require-story-core.js +10 -10
- package/lib/src/rules/helpers/require-story-helpers.d.ts +5 -63
- package/lib/src/rules/helpers/require-story-helpers.js +29 -337
- package/lib/src/rules/helpers/require-story-io.js +1 -0
- package/lib/src/rules/helpers/require-story-name-extraction.d.ts +35 -0
- package/lib/src/rules/helpers/require-story-name-extraction.js +107 -0
- package/lib/src/rules/helpers/require-story-node-utils.d.ts +43 -0
- package/lib/src/rules/helpers/require-story-node-utils.js +115 -0
- package/lib/src/rules/helpers/require-test-traceability-helpers.js +1 -0
- package/lib/src/rules/helpers/valid-annotation-format-internal.d.ts +2 -2
- package/lib/src/rules/helpers/valid-annotation-format-internal.js +13 -5
- package/lib/src/rules/helpers/valid-annotation-format-validators.d.ts +14 -14
- package/lib/src/rules/helpers/valid-annotation-format-validators.js +31 -22
- package/lib/src/rules/helpers/valid-annotation-options.d.ts +0 -10
- package/lib/src/rules/helpers/valid-annotation-options.js +22 -92
- package/lib/src/rules/helpers/valid-annotation-utils.js +1 -0
- package/lib/src/rules/helpers/valid-req-reference-helpers.js +1 -1
- package/lib/src/rules/no-redundant-annotation.js +4 -238
- package/lib/src/rules/prefer-implements-annotation.d.ts +12 -0
- package/lib/src/rules/prefer-implements-annotation.js +9 -164
- package/lib/src/rules/require-traceability.d.ts +8 -0
- package/lib/src/rules/require-traceability.js +8 -0
- package/lib/src/rules/valid-annotation-format.js +14 -10
- package/lib/src/utils/annotation-checker.d.ts +3 -2
- package/lib/src/utils/annotation-checker.js +4 -2
- package/lib/src/utils/branch-annotation-catch-helpers.d.ts +22 -0
- package/lib/src/utils/branch-annotation-catch-helpers.js +70 -0
- package/lib/src/utils/branch-annotation-helpers.js +11 -187
- package/lib/src/utils/branch-annotation-if-helpers.d.ts +1 -0
- package/lib/src/utils/branch-annotation-if-helpers.js +59 -0
- package/lib/src/utils/branch-annotation-indent-helpers.d.ts +1 -1
- package/lib/src/utils/branch-annotation-switch-helpers.d.ts +8 -2
- package/lib/src/utils/branch-annotation-switch-helpers.js +10 -4
- package/lib/src/utils/branch-validation.d.ts +9 -0
- package/lib/src/utils/branch-validation.js +58 -0
- package/lib/src/utils/comment-text-helpers.d.ts +31 -0
- package/lib/src/utils/comment-text-helpers.js +54 -0
- package/lib/src/utils/redundancy-detector.d.ts +85 -0
- package/lib/src/utils/redundancy-detector.js +235 -0
- package/lib/src/utils/reqAnnotationDetection.js +1 -0
- package/lib/tests/config/eslint-config-validation.test.js +1 -0
- package/lib/tests/config/flat-config-presets-integration.test.js +1 -0
- package/lib/tests/config/require-story-annotation-config.test.js +1 -0
- package/lib/tests/fixtures/stale/example.js +1 -0
- package/lib/tests/fixtures/update/example.js +1 -0
- package/lib/tests/integration/annotation-placement-inside-prettier.integration.test.js +1 -0
- package/lib/tests/integration/catch-annotation-prettier.integration.test.js +1 -0
- package/lib/tests/integration/else-if-annotation-prettier.integration.test.js +1 -0
- package/lib/tests/integration/prettier-test-helpers.js +1 -0
- package/lib/tests/integration/require-traceability-test-callbacks.integration.test.js +1 -0
- package/lib/tests/maintenance/detect-isolated.test.js +1 -0
- package/lib/tests/maintenance/storyParser.test.d.ts +8 -0
- package/lib/tests/maintenance/storyParser.test.js +505 -0
- package/lib/tests/perf/maintenance-large-workspace.test.js +1 -0
- package/lib/tests/perf/valid-annotation-format-large-file.test.js +1 -0
- package/lib/tests/plugin-setup.test.js +1 -0
- package/lib/tests/rules/error-reporting.test.js +1 -0
- package/lib/tests/rules/no-redundant-annotation.test.js +1 -0
- package/lib/tests/rules/require-story-helpers.test.js +3 -2
- package/lib/tests/rules/require-test-traceability.test.js +1 -0
- package/lib/tests/rules/valid-req-reference.test.js +2 -0
- package/lib/tests/utils/branch-annotation-catch-insert-position.test.js +1 -0
- package/lib/tests/utils/branch-annotation-else-if-insert-position.test.js +1 -0
- package/lib/tests/utils/branch-annotation-helpers.test.js +1 -0
- package/package.json +18 -10
- package/user-docs/api-reference.md +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,9 +1,14 @@
|
|
|
1
|
-
# [1.
|
|
1
|
+
# [1.22.0](https://github.com/voder-ai/eslint-plugin-traceability/compare/v1.21.1...v1.22.0) (2026-01-10)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Bug Fixes
|
|
5
|
+
|
|
6
|
+
* move voder-ai to optionalDependencies to allow CI without GitHub Packages access ([1a674cb](https://github.com/voder-ai/eslint-plugin-traceability/commit/1a674cb65d5223c75710910817393667435bfcd8))
|
|
2
7
|
|
|
3
8
|
|
|
4
9
|
### Features
|
|
5
10
|
|
|
6
|
-
*
|
|
11
|
+
* **ci:** add post-deployment verification step ([00d3d21](https://github.com/voder-ai/eslint-plugin-traceability/commit/00d3d214f21e18bfc26e3de4fbcb0bd9f0aa8f28))
|
|
7
12
|
|
|
8
13
|
# Changelog
|
|
9
14
|
|
package/README.md
CHANGED
|
@@ -121,15 +121,15 @@ Traceability annotations are typically placed immediately adjacent to the code t
|
|
|
121
121
|
|
|
122
122
|
- **Function-level (`traceability/require-story-annotation`, `traceability/require-req-annotation`)**
|
|
123
123
|
|
|
124
|
-
Function-level rules
|
|
125
|
-
-
|
|
126
|
-
-
|
|
124
|
+
Function-level rules support both before-function and inside-body placement, controlled by the same `annotationPlacement` option described above:
|
|
125
|
+
- `"before"` – Annotations are written as JSDoc blocks immediately preceding the function, or as line comments placed directly before the function declaration or expression.
|
|
126
|
+
- `"inside"` – Annotations are expected to appear on the first comment-only lines inside function and method bodies; comments before the function are ignored for block-bodied functions in this mode, while TypeScript declarations and signature-only nodes still rely on before-node annotations.
|
|
127
127
|
|
|
128
|
-
|
|
128
|
+
For full details and migration guidance between placement styles, see the [API Reference](user-docs/api-reference.md) and the migration guide ([user-docs/migration-guide.md](user-docs/migration-guide.md)).
|
|
129
129
|
|
|
130
130
|
For full configuration details and migration guidance between placement styles, see:
|
|
131
131
|
|
|
132
|
-
- `traceability/require-branch-annotation` rule docs: [docs/rules/require-branch-annotation.md](docs/rules/require-branch-annotation.md)
|
|
132
|
+
- `traceability/require-branch-annotation` rule docs: [docs/rules/require-branch-annotation.md](https://github.com/voder-ai/eslint-plugin-traceability/blob/main/docs/rules/require-branch-annotation.md)
|
|
133
133
|
- Migration guide: [user-docs/migration-guide.md](user-docs/migration-guide.md)
|
|
134
134
|
|
|
135
135
|
### Available Rules
|
|
@@ -280,7 +280,7 @@ Removing "duplicate" annotations would break the verification workflow by forcin
|
|
|
280
280
|
|
|
281
281
|
## Verification Workflow Guide
|
|
282
282
|
|
|
283
|
-
For detailed verification workflows, examples, and best practices, see the [Verification Workflow Guide](docs/verification-workflow-guide.md).
|
|
283
|
+
For detailed verification workflows, examples, and best practices, see the [Verification Workflow Guide](https://github.com/voder-ai/eslint-plugin-traceability/blob/main/docs/verification-workflow-guide.md).
|
|
284
284
|
|
|
285
285
|
## API Reference
|
|
286
286
|
|
|
@@ -15,7 +15,6 @@ const detect_1 = require("./detect");
|
|
|
15
15
|
*/
|
|
16
16
|
function batchUpdateAnnotations(codebasePath, mappings) {
|
|
17
17
|
let totalUpdated = 0;
|
|
18
|
-
// @story docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md // @req REQ-MAINT-BATCH - Perform batch updates
|
|
19
18
|
for (const { oldPath, newPath } of mappings) {
|
|
20
19
|
totalUpdated += (0, update_1.updateAnnotationReferences)(codebasePath, oldPath, newPath);
|
|
21
20
|
}
|
|
@@ -19,7 +19,6 @@ function runMaintenanceCli(rawArgv) {
|
|
|
19
19
|
const { subcommand: command } = initialNormalized;
|
|
20
20
|
if (!command || command === "-h" || command === "--help") {
|
|
21
21
|
// @supports docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md REQ-MAINT-SAFE
|
|
22
|
-
// @supports docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md REQ-MAINT-SAFE - Branch to show usage when no command or help flag is provided; handle help requests safely and provide discoverable usage output
|
|
23
22
|
printHelp();
|
|
24
23
|
return commands_1.EXIT_OK;
|
|
25
24
|
}
|
|
@@ -28,35 +27,34 @@ function runMaintenanceCli(rawArgv) {
|
|
|
28
27
|
const normalized = initialNormalized;
|
|
29
28
|
try {
|
|
30
29
|
// @supports docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md REQ-MAINT-SAFE
|
|
31
|
-
// @supports docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md REQ-MAINT-SAFE - Catch unexpected errors and surface concise diagnostics without crashing
|
|
32
30
|
switch (command) {
|
|
33
31
|
case "detect":
|
|
34
|
-
// @supports docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md REQ-MAINT-DETECT
|
|
32
|
+
// @supports docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md REQ-MAINT-DETECT
|
|
35
33
|
return (0, commands_1.handleDetect)(normalized);
|
|
36
34
|
case "verify":
|
|
37
|
-
// @supports docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md REQ-MAINT-VERIFY
|
|
35
|
+
// @supports docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md REQ-MAINT-VERIFY
|
|
38
36
|
return (0, commands_1.handleVerify)(normalized);
|
|
39
37
|
case "report":
|
|
40
|
-
// @supports docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md REQ-MAINT-REPORT
|
|
38
|
+
// @supports docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md REQ-MAINT-REPORT
|
|
41
39
|
return (0, commands_1.handleReport)(normalized);
|
|
42
40
|
case "update": {
|
|
43
|
-
// @supports docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md REQ-MAINT-UPDATE
|
|
41
|
+
// @supports docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md REQ-MAINT-UPDATE
|
|
44
42
|
const result = (0, commands_1.handleUpdate)(normalized);
|
|
45
43
|
if (result === commands_1.EXIT_USAGE) {
|
|
46
|
-
// @supports docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md REQ-MAINT-SAFE
|
|
44
|
+
// @supports docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md REQ-MAINT-SAFE
|
|
47
45
|
printHelp();
|
|
48
46
|
}
|
|
49
47
|
return result;
|
|
50
48
|
}
|
|
51
49
|
default:
|
|
52
|
-
// @supports docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md REQ-MAINT-SAFE
|
|
50
|
+
// @supports docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md REQ-MAINT-SAFE
|
|
53
51
|
console.error(`Unknown command: ${command}`);
|
|
54
52
|
printHelp();
|
|
55
53
|
return commands_1.EXIT_USAGE;
|
|
56
54
|
}
|
|
57
55
|
}
|
|
58
56
|
catch (error) {
|
|
59
|
-
// @supports docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md REQ-MAINT-SAFE
|
|
57
|
+
// @supports docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md REQ-MAINT-SAFE
|
|
60
58
|
const message = error instanceof Error
|
|
61
59
|
? error.message
|
|
62
60
|
: "Unknown error in maintenance CLI";
|
|
@@ -70,7 +68,7 @@ function runMaintenanceCli(rawArgv) {
|
|
|
70
68
|
* @req REQ-MAINT-SAFE - Provide discoverable CLI usage information
|
|
71
69
|
*/
|
|
72
70
|
function printHelp() {
|
|
73
|
-
// @supports docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md REQ-MAINT-SAFE
|
|
71
|
+
// @supports docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md REQ-MAINT-SAFE
|
|
74
72
|
console.log(`traceability-maint - Traceability annotation maintenance tools
|
|
75
73
|
|
|
76
74
|
Usage:
|
|
@@ -3,7 +3,7 @@ export declare const EXIT_OK = 0;
|
|
|
3
3
|
export declare const EXIT_STALE = 1;
|
|
4
4
|
export declare const EXIT_USAGE = 2;
|
|
5
5
|
/**
|
|
6
|
-
* Handle the `detect` subcommand for stale
|
|
6
|
+
* Handle the `detect` subcommand for stale story annotations.
|
|
7
7
|
* @story docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md
|
|
8
8
|
* @req REQ-MAINT-DETECT - CLI surface for detection of stale annotations
|
|
9
9
|
* @req REQ-MAINT-SAFE - Return specific exit codes for stale vs clean states
|
|
@@ -27,7 +27,7 @@ export declare function handleVerify(normalized: NormalizedCliArgs): number;
|
|
|
27
27
|
*/
|
|
28
28
|
export declare function handleReport(normalized: NormalizedCliArgs): number;
|
|
29
29
|
/**
|
|
30
|
-
* Handle the `update` subcommand to rewrite
|
|
30
|
+
* Handle the `update` subcommand to rewrite story annotation references.
|
|
31
31
|
* @story docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md
|
|
32
32
|
* @req REQ-MAINT-UPDATE - CLI surface for updating annotation references
|
|
33
33
|
* @req REQ-MAINT-SAFE - Provide dry-run mode and explicit parameter checks
|
|
@@ -24,7 +24,7 @@ exports.EXIT_OK = 0;
|
|
|
24
24
|
exports.EXIT_STALE = 1;
|
|
25
25
|
exports.EXIT_USAGE = 2;
|
|
26
26
|
/**
|
|
27
|
-
* Handle the `detect` subcommand for stale
|
|
27
|
+
* Handle the `detect` subcommand for stale story annotations.
|
|
28
28
|
* @story docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md
|
|
29
29
|
* @req REQ-MAINT-DETECT - CLI surface for detection of stale annotations
|
|
30
30
|
* @req REQ-MAINT-SAFE - Return specific exit codes for stale vs clean states
|
|
@@ -95,7 +95,7 @@ function handleReport(normalized) {
|
|
|
95
95
|
return exports.EXIT_OK;
|
|
96
96
|
}
|
|
97
97
|
/**
|
|
98
|
-
* Handle the `update` subcommand to rewrite
|
|
98
|
+
* Handle the `update` subcommand to rewrite story annotation references.
|
|
99
99
|
* @story docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md
|
|
100
100
|
* @req REQ-MAINT-UPDATE - CLI surface for updating annotation references
|
|
101
101
|
* @req REQ-MAINT-SAFE - Provide dry-run mode and explicit parameter checks
|
|
@@ -84,7 +84,7 @@ function processFileForStaleAnnotations(file, workspaceRoot, cwd, stale) {
|
|
|
84
84
|
}
|
|
85
85
|
catch {
|
|
86
86
|
// @supports docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md REQ-MAINT-DETECT
|
|
87
|
-
// @supports docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md REQ-MAINT-SAFE
|
|
87
|
+
// @supports docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md REQ-MAINT-SAFE
|
|
88
88
|
return;
|
|
89
89
|
}
|
|
90
90
|
const regex = /@story\s+([^\s]+)/g;
|
|
@@ -115,7 +115,7 @@ function handleStoryMatch(storyPath, workspaceRoot, cwd, stale) {
|
|
|
115
115
|
const inProjectCandidates = getInProjectCandidates(storyProjectCandidate, storyCodebaseCandidate, workspaceRoot);
|
|
116
116
|
// If both candidates are out-of-project, do not mark as stale and skip FS checks
|
|
117
117
|
if (inProjectCandidates.length === 0) {
|
|
118
|
-
// @supports docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md REQ-MAINT-DETECT
|
|
118
|
+
// @supports docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md REQ-MAINT-DETECT
|
|
119
119
|
return;
|
|
120
120
|
}
|
|
121
121
|
// @story docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md
|
|
@@ -141,7 +141,7 @@ function getInProjectCandidates(storyProjectCandidate, storyCodebaseCandidate, w
|
|
|
141
141
|
}
|
|
142
142
|
catch {
|
|
143
143
|
// @supports docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md REQ-MAINT-DETECT
|
|
144
|
-
// @supports docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md REQ-MAINT-SAFE
|
|
144
|
+
// @supports docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md REQ-MAINT-SAFE
|
|
145
145
|
projectBoundary = {
|
|
146
146
|
isWithinProject: false,
|
|
147
147
|
candidate: storyProjectCandidate,
|
|
@@ -153,7 +153,7 @@ function getInProjectCandidates(storyProjectCandidate, storyCodebaseCandidate, w
|
|
|
153
153
|
}
|
|
154
154
|
catch {
|
|
155
155
|
// @supports docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md REQ-MAINT-DETECT
|
|
156
|
-
// @supports docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md REQ-MAINT-SAFE
|
|
156
|
+
// @supports docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md REQ-MAINT-SAFE
|
|
157
157
|
codebaseBoundary = {
|
|
158
158
|
isWithinProject: false,
|
|
159
159
|
candidate: storyCodebaseCandidate,
|
|
@@ -161,11 +161,11 @@ function getInProjectCandidates(storyProjectCandidate, storyCodebaseCandidate, w
|
|
|
161
161
|
}
|
|
162
162
|
const inProjectCandidates = [];
|
|
163
163
|
if (projectBoundary.isWithinProject) {
|
|
164
|
-
// @supports docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md REQ-MAINT-DETECT
|
|
164
|
+
// @supports docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md REQ-MAINT-DETECT
|
|
165
165
|
inProjectCandidates.push(projectBoundary.candidate);
|
|
166
166
|
}
|
|
167
167
|
if (codebaseBoundary.isWithinProject) {
|
|
168
|
-
// @supports docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md REQ-MAINT-DETECT
|
|
168
|
+
// @supports docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md REQ-MAINT-DETECT
|
|
169
169
|
inProjectCandidates.push(codebaseBoundary.candidate);
|
|
170
170
|
}
|
|
171
171
|
return inProjectCandidates;
|
|
@@ -182,7 +182,7 @@ function anyInProjectCandidateExists(inProjectCandidates) {
|
|
|
182
182
|
(p) => {
|
|
183
183
|
const exists = fs.existsSync(p);
|
|
184
184
|
if (!exists) {
|
|
185
|
-
// @supports docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md REQ-MAINT-SAFE
|
|
185
|
+
// @supports docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md REQ-MAINT-SAFE
|
|
186
186
|
}
|
|
187
187
|
return exists;
|
|
188
188
|
});
|
|
@@ -12,8 +12,8 @@ const detect_1 = require("./detect");
|
|
|
12
12
|
*/
|
|
13
13
|
function generateMaintenanceReport(codebasePath) {
|
|
14
14
|
const staleAnnotations = (0, detect_1.detectStaleAnnotations)(codebasePath);
|
|
15
|
-
// @supports docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md REQ-MAINT-SAFE
|
|
16
|
-
// @supports docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md REQ-MAINT-REPORT
|
|
15
|
+
// @supports docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md REQ-MAINT-SAFE
|
|
16
|
+
// @supports docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md REQ-MAINT-REPORT
|
|
17
17
|
if (staleAnnotations.length === 0) {
|
|
18
18
|
return "";
|
|
19
19
|
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Extract requirement IDs from story file content
|
|
3
|
+
* @story docs/stories/010.0-DEV-DEEP-VALIDATION.story.md
|
|
4
|
+
* @req REQ-DEEP-PARSE - Parse story file content to identify available requirements
|
|
5
|
+
* @req REQ-DEEP-FORMAT - Support finding requirement IDs in multiple markdown contexts
|
|
6
|
+
* @req REQ-DEEP-SECTION - Handle requirements in different story file sections
|
|
7
|
+
*/
|
|
8
|
+
export declare function extractRequirementsFromStoryFile(filePath: string): Set<string>;
|
|
9
|
+
/**
|
|
10
|
+
* Extract requirement IDs from story file content string
|
|
11
|
+
* @story docs/stories/010.0-DEV-DEEP-VALIDATION.story.md
|
|
12
|
+
* @req REQ-DEEP-PARSE - Parse story file content to identify available requirements
|
|
13
|
+
* @req REQ-DEEP-FORMAT - Support finding requirement IDs in multiple markdown contexts
|
|
14
|
+
* @req REQ-DEEP-SECTION - Handle requirements in different story file sections
|
|
15
|
+
*/
|
|
16
|
+
export declare function extractRequirementsFromContent(content: string): Set<string>;
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.extractRequirementsFromStoryFile = extractRequirementsFromStoryFile;
|
|
37
|
+
exports.extractRequirementsFromContent = extractRequirementsFromContent;
|
|
38
|
+
/**
|
|
39
|
+
* Parser for extracting requirements from story files
|
|
40
|
+
* @story docs/stories/010.0-DEV-DEEP-VALIDATION.story.md
|
|
41
|
+
* @req REQ-DEEP-PARSE - Parse story file content to identify available requirements
|
|
42
|
+
* @req REQ-DEEP-FORMAT - Support finding requirement IDs in multiple markdown contexts
|
|
43
|
+
* @req REQ-DEEP-SECTION - Handle requirements in different story file sections
|
|
44
|
+
*/
|
|
45
|
+
const fs = __importStar(require("fs"));
|
|
46
|
+
/**
|
|
47
|
+
* Extract requirement IDs from story file content
|
|
48
|
+
* @story docs/stories/010.0-DEV-DEEP-VALIDATION.story.md
|
|
49
|
+
* @req REQ-DEEP-PARSE - Parse story file content to identify available requirements
|
|
50
|
+
* @req REQ-DEEP-FORMAT - Support finding requirement IDs in multiple markdown contexts
|
|
51
|
+
* @req REQ-DEEP-SECTION - Handle requirements in different story file sections
|
|
52
|
+
*/
|
|
53
|
+
function extractRequirementsFromStoryFile(filePath) {
|
|
54
|
+
try {
|
|
55
|
+
const content = fs.readFileSync(filePath, "utf8");
|
|
56
|
+
return extractRequirementsFromContent(content);
|
|
57
|
+
}
|
|
58
|
+
catch {
|
|
59
|
+
// @story docs/stories/010.0-DEV-DEEP-VALIDATION.story.md
|
|
60
|
+
// @req REQ-DEEP-PARSE - Handle file read errors gracefully
|
|
61
|
+
return new Set();
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Extract requirement IDs from story file content string
|
|
66
|
+
* @story docs/stories/010.0-DEV-DEEP-VALIDATION.story.md
|
|
67
|
+
* @req REQ-DEEP-PARSE - Parse story file content to identify available requirements
|
|
68
|
+
* @req REQ-DEEP-FORMAT - Support finding requirement IDs in multiple markdown contexts
|
|
69
|
+
* @req REQ-DEEP-SECTION - Handle requirements in different story file sections
|
|
70
|
+
*/
|
|
71
|
+
function extractRequirementsFromContent(content) {
|
|
72
|
+
const requirements = new Set();
|
|
73
|
+
// Strategy 1: Extract from structured sections (## Requirements, ## Acceptance Criteria)
|
|
74
|
+
// @story docs/stories/010.0-DEV-DEEP-VALIDATION.story.md
|
|
75
|
+
// @req REQ-DEEP-SECTION - Handle requirements in different story file sections
|
|
76
|
+
const sectionRequirements = extractFromSections(content);
|
|
77
|
+
sectionRequirements.forEach((req) => requirements.add(req));
|
|
78
|
+
// Strategy 2: Fallback to regex-based extraction for REQ-XXX-YYY patterns anywhere in file
|
|
79
|
+
// @story docs/stories/010.0-DEV-DEEP-VALIDATION.story.md
|
|
80
|
+
// @req REQ-DEEP-FORMAT - Support finding requirement IDs in multiple markdown contexts
|
|
81
|
+
const regexRequirements = extractWithRegex(content);
|
|
82
|
+
regexRequirements.forEach((req) => requirements.add(req));
|
|
83
|
+
return requirements;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Extract requirements from structured markdown sections
|
|
87
|
+
* @story docs/stories/010.0-DEV-DEEP-VALIDATION.story.md
|
|
88
|
+
* @req REQ-DEEP-SECTION - Handle requirements in different story file sections
|
|
89
|
+
* @req REQ-DEEP-FORMAT - Support finding requirement IDs in multiple markdown contexts
|
|
90
|
+
*/
|
|
91
|
+
function extractFromSections(content) {
|
|
92
|
+
const requirements = new Set();
|
|
93
|
+
const lines = content.split("\n");
|
|
94
|
+
let inRequirementsSection = false;
|
|
95
|
+
let inAcceptanceCriteriaSection = false;
|
|
96
|
+
for (const line of lines) {
|
|
97
|
+
// Detect section headers
|
|
98
|
+
if (line.match(/^##\s+Requirements/i)) {
|
|
99
|
+
// @story docs/stories/010.0-DEV-DEEP-VALIDATION.story.md
|
|
100
|
+
// @req REQ-DEEP-SECTION - Parse ## Requirements sections
|
|
101
|
+
inRequirementsSection = true;
|
|
102
|
+
inAcceptanceCriteriaSection = false;
|
|
103
|
+
continue;
|
|
104
|
+
}
|
|
105
|
+
else if (line.match(/^##\s+Acceptance\s+Criteria/i)) {
|
|
106
|
+
// @story docs/stories/010.0-DEV-DEEP-VALIDATION.story.md
|
|
107
|
+
// @req REQ-DEEP-SECTION - Parse ## Acceptance Criteria sections
|
|
108
|
+
inAcceptanceCriteriaSection = true;
|
|
109
|
+
inRequirementsSection = false;
|
|
110
|
+
continue;
|
|
111
|
+
}
|
|
112
|
+
else if (line.match(/^##\s+/)) {
|
|
113
|
+
// New section that's not Requirements or Acceptance Criteria
|
|
114
|
+
inRequirementsSection = false;
|
|
115
|
+
inAcceptanceCriteriaSection = false;
|
|
116
|
+
continue;
|
|
117
|
+
}
|
|
118
|
+
// Extract requirements from active sections
|
|
119
|
+
if (inRequirementsSection || inAcceptanceCriteriaSection) {
|
|
120
|
+
// @story docs/stories/010.0-DEV-DEEP-VALIDATION.story.md
|
|
121
|
+
// @req REQ-DEEP-FORMAT - Extract requirement IDs from list items
|
|
122
|
+
const reqIds = extractReqIdsFromLine(line);
|
|
123
|
+
reqIds.forEach((req) => requirements.add(req));
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
return requirements;
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Extract requirement IDs from a single line
|
|
130
|
+
* @story docs/stories/010.0-DEV-DEEP-VALIDATION.story.md
|
|
131
|
+
* @req REQ-DEEP-FORMAT - Support finding requirement IDs in multiple markdown contexts
|
|
132
|
+
*/
|
|
133
|
+
function extractReqIdsFromLine(line) {
|
|
134
|
+
const requirements = [];
|
|
135
|
+
// Pattern 1: - **REQ-XXX-YYY**: Description
|
|
136
|
+
// @story docs/stories/010.0-DEV-DEEP-VALIDATION.story.md
|
|
137
|
+
// @req REQ-DEEP-FORMAT - Extract from bold requirement format
|
|
138
|
+
const boldPattern = /\*\*(REQ-[A-Z0-9-]+)\*\*/g;
|
|
139
|
+
let match;
|
|
140
|
+
while ((match = boldPattern.exec(line)) !== null) {
|
|
141
|
+
requirements.push(match[1]);
|
|
142
|
+
}
|
|
143
|
+
// Pattern 2: REQ-XXX-YYY anywhere in the line (not already captured)
|
|
144
|
+
// @story docs/stories/010.0-DEV-DEEP-VALIDATION.story.md
|
|
145
|
+
// @req REQ-DEEP-FORMAT - Extract from plain text mentions
|
|
146
|
+
const plainPattern = /\b(REQ-[A-Z0-9-]+)\b/g;
|
|
147
|
+
while ((match = plainPattern.exec(line)) !== null) {
|
|
148
|
+
if (!requirements.includes(match[1])) {
|
|
149
|
+
requirements.push(match[1]);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
return requirements;
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Extract requirements using regex fallback (for content outside structured sections)
|
|
156
|
+
* @story docs/stories/010.0-DEV-DEEP-VALIDATION.story.md
|
|
157
|
+
* @req REQ-DEEP-FORMAT - Support finding requirement IDs in multiple markdown contexts
|
|
158
|
+
*/
|
|
159
|
+
function extractWithRegex(content) {
|
|
160
|
+
const requirements = new Set();
|
|
161
|
+
const regex = /\b(REQ-[A-Z0-9-]+)\b/g;
|
|
162
|
+
let match;
|
|
163
|
+
while ((match = regex.exec(content)) !== null) {
|
|
164
|
+
requirements.add(match[1]);
|
|
165
|
+
}
|
|
166
|
+
return requirements;
|
|
167
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pattern validation helpers for valid-annotation-format options.
|
|
3
|
+
*
|
|
4
|
+
* @story docs/stories/010.1-DEV-CONFIGURABLE-PATTERNS.story.md
|
|
5
|
+
* @req REQ-REGEX-VALIDATION - Validate that configured patterns are valid regular expressions
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Build an error message for an invalid regex pattern.
|
|
9
|
+
*
|
|
10
|
+
* @supports docs/stories/010.1-DEV-CONFIGURABLE-PATTERNS.story.md REQ-REGEX-VALIDATION
|
|
11
|
+
*/
|
|
12
|
+
export declare function buildInvalidRegexError(field: string, pattern: string): string;
|
|
13
|
+
/**
|
|
14
|
+
* Arguments for the resolvePattern helper.
|
|
15
|
+
*/
|
|
16
|
+
export interface ResolvePatternArgs {
|
|
17
|
+
nestedPattern: string | undefined;
|
|
18
|
+
nestedFieldName: string;
|
|
19
|
+
flatPattern: string | undefined;
|
|
20
|
+
flatFieldName: string;
|
|
21
|
+
defaultPattern: RegExp;
|
|
22
|
+
errors?: string[];
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Resolve a user-configured regex pattern, handling both nested and flat
|
|
26
|
+
* configuration shapes and accumulating validation errors.
|
|
27
|
+
*
|
|
28
|
+
* @story docs/stories/010.1-DEV-CONFIGURABLE-PATTERNS.story.md
|
|
29
|
+
* @req REQ-PATTERN-CONFIG
|
|
30
|
+
* @req REQ-REGEX-VALIDATION
|
|
31
|
+
* @req REQ-BACKWARD-COMPAT
|
|
32
|
+
*/
|
|
33
|
+
export declare function resolvePattern({ nestedPattern, nestedFieldName, flatPattern, flatFieldName, defaultPattern, errors, }: ResolvePatternArgs): RegExp;
|
|
34
|
+
/**
|
|
35
|
+
* Resolve an example string, preferring nested over flat configuration,
|
|
36
|
+
* and falling back to the provided default when necessary.
|
|
37
|
+
*
|
|
38
|
+
* @story docs/stories/010.1-DEV-CONFIGURABLE-PATTERNS.story.md
|
|
39
|
+
* @req REQ-EXAMPLE-MESSAGES
|
|
40
|
+
* @req REQ-BACKWARD-COMPAT
|
|
41
|
+
*/
|
|
42
|
+
export declare function resolveExample(nestedExample: string | undefined, flatExample: string | undefined, defaultExample: string): string;
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Pattern validation helpers for valid-annotation-format options.
|
|
4
|
+
*
|
|
5
|
+
* @story docs/stories/010.1-DEV-CONFIGURABLE-PATTERNS.story.md
|
|
6
|
+
* @req REQ-REGEX-VALIDATION - Validate that configured patterns are valid regular expressions
|
|
7
|
+
*/
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.buildInvalidRegexError = buildInvalidRegexError;
|
|
10
|
+
exports.resolvePattern = resolvePattern;
|
|
11
|
+
exports.resolveExample = resolveExample;
|
|
12
|
+
/**
|
|
13
|
+
* Build an error message for an invalid regex pattern.
|
|
14
|
+
*
|
|
15
|
+
* @supports docs/stories/010.1-DEV-CONFIGURABLE-PATTERNS.story.md REQ-REGEX-VALIDATION
|
|
16
|
+
*/
|
|
17
|
+
function buildInvalidRegexError(field, pattern) {
|
|
18
|
+
return `Invalid regular expression for option "${field}": "${pattern}"`;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Resolve a user-configured regex pattern, handling both nested and flat
|
|
22
|
+
* configuration shapes and accumulating validation errors.
|
|
23
|
+
*
|
|
24
|
+
* @story docs/stories/010.1-DEV-CONFIGURABLE-PATTERNS.story.md
|
|
25
|
+
* @req REQ-PATTERN-CONFIG
|
|
26
|
+
* @req REQ-REGEX-VALIDATION
|
|
27
|
+
* @req REQ-BACKWARD-COMPAT
|
|
28
|
+
*/
|
|
29
|
+
function resolvePattern({ nestedPattern, nestedFieldName, flatPattern, flatFieldName, defaultPattern, errors, }) {
|
|
30
|
+
const effective = typeof nestedPattern === "string"
|
|
31
|
+
? { value: nestedPattern, field: nestedFieldName }
|
|
32
|
+
: typeof flatPattern === "string"
|
|
33
|
+
? { value: flatPattern, field: flatFieldName }
|
|
34
|
+
: null;
|
|
35
|
+
if (!effective) {
|
|
36
|
+
return defaultPattern;
|
|
37
|
+
}
|
|
38
|
+
try {
|
|
39
|
+
return new RegExp(effective.value);
|
|
40
|
+
}
|
|
41
|
+
catch {
|
|
42
|
+
const error = buildInvalidRegexError(effective.field, effective.value);
|
|
43
|
+
if (errors) {
|
|
44
|
+
errors.push(error);
|
|
45
|
+
}
|
|
46
|
+
return defaultPattern;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Resolve an example string, preferring nested over flat configuration,
|
|
51
|
+
* and falling back to the provided default when necessary.
|
|
52
|
+
*
|
|
53
|
+
* @story docs/stories/010.1-DEV-CONFIGURABLE-PATTERNS.story.md
|
|
54
|
+
* @req REQ-EXAMPLE-MESSAGES
|
|
55
|
+
* @req REQ-BACKWARD-COMPAT
|
|
56
|
+
*/
|
|
57
|
+
function resolveExample(nestedExample, flatExample, defaultExample) {
|
|
58
|
+
if (typeof nestedExample === "string" && nestedExample.trim()) {
|
|
59
|
+
return nestedExample;
|
|
60
|
+
}
|
|
61
|
+
if (typeof flatExample === "string" && flatExample.trim()) {
|
|
62
|
+
return flatExample;
|
|
63
|
+
}
|
|
64
|
+
return defaultExample;
|
|
65
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Inline comment processing for prefer-implements-annotation rule.
|
|
3
|
+
* Handles migration of inline comment story and requirement patterns to supports format.
|
|
4
|
+
*
|
|
5
|
+
* @story docs/stories/010.3-DEV-MIGRATE-TO-SUPPORTS.story.md
|
|
6
|
+
* @req REQ-MIGRATE-INLINE
|
|
7
|
+
*/
|
|
8
|
+
import type { Rule } from "eslint";
|
|
9
|
+
export type LineComment = {
|
|
10
|
+
type: "Line";
|
|
11
|
+
} & any;
|
|
12
|
+
/**
|
|
13
|
+
* Scan sequences of Line comments for inline legacy story and requirement patterns
|
|
14
|
+
* and report diagnostics with optional auto-fixes.
|
|
15
|
+
*/
|
|
16
|
+
export declare function processInlineComments(context: Rule.RuleContext, lineComments: LineComment[]): void;
|