eslint-plugin-traceability 1.21.1 → 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 +3 -4
- package/lib/src/maintenance/batch.js +0 -2
- package/lib/src/maintenance/cli.js +8 -11
- package/lib/src/maintenance/commands.d.ts +2 -2
- package/lib/src/maintenance/commands.js +2 -3
- package/lib/src/maintenance/detect.js +7 -8
- package/lib/src/maintenance/report.js +2 -3
- package/lib/src/maintenance/storyParser.d.ts +16 -0
- package/lib/src/maintenance/storyParser.js +167 -0
- package/lib/src/maintenance/update.js +0 -1
- 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 -11
- 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-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/valid-annotation-format-internal.js +11 -3
- 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-req-reference-helpers.js +0 -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/utils/annotation-checker.d.ts +3 -2
- package/lib/src/utils/annotation-checker.js +3 -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/tests/maintenance/storyParser.test.d.ts +8 -0
- package/lib/tests/maintenance/storyParser.test.js +505 -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/valid-req-reference.test.js +2 -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.22.0](https://github.com/voder-ai/eslint-plugin-traceability/compare/v1.21.1...v1.22.0) (2026-01-10)
|
|
2
2
|
|
|
3
3
|
|
|
4
4
|
### Bug Fixes
|
|
5
5
|
|
|
6
|
-
*
|
|
6
|
+
* move voder-ai to optionalDependencies to allow CI without GitHub Packages access ([1a674cb](https://github.com/voder-ai/eslint-plugin-traceability/commit/1a674cb65d5223c75710910817393667435bfcd8))
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
### Features
|
|
10
|
+
|
|
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
|
@@ -122,7 +122,6 @@ Traceability annotations are typically placed immediately adjacent to the code t
|
|
|
122
122
|
- **Function-level (`traceability/require-story-annotation`, `traceability/require-req-annotation`)**
|
|
123
123
|
|
|
124
124
|
Function-level rules support both before-function and inside-body placement, controlled by the same `annotationPlacement` option described above:
|
|
125
|
-
|
|
126
125
|
- `"before"` – Annotations are written as JSDoc blocks immediately preceding the function, or as line comments placed directly before the function declaration or expression.
|
|
127
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.
|
|
128
127
|
|
|
@@ -130,7 +129,7 @@ Traceability annotations are typically placed immediately adjacent to the code t
|
|
|
130
129
|
|
|
131
130
|
For full configuration details and migration guidance between placement styles, see:
|
|
132
131
|
|
|
133
|
-
- `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)
|
|
134
133
|
- Migration guide: [user-docs/migration-guide.md](user-docs/migration-guide.md)
|
|
135
134
|
|
|
136
135
|
### Available Rules
|
|
@@ -281,7 +280,7 @@ Removing "duplicate" annotations would break the verification workflow by forcin
|
|
|
281
280
|
|
|
282
281
|
## Verification Workflow Guide
|
|
283
282
|
|
|
284
|
-
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).
|
|
285
284
|
|
|
286
285
|
## API Reference
|
|
287
286
|
|
|
@@ -430,4 +429,4 @@ For the canonical, user-facing security policy (including how to report vulnerab
|
|
|
430
429
|
- Contribution guide: <https://github.com/voder-ai/eslint-plugin-traceability/blob/main/CONTRIBUTING.md>
|
|
431
430
|
- Issue tracker: <https://github.com/voder-ai/eslint-plugin-traceability/issues>
|
|
432
431
|
- Changelog: [CHANGELOG.md](CHANGELOG.md)
|
|
433
|
-
- Versioning and Releases: This project uses semantic-release for automated versioning. The authoritative list of published versions and release notes is on GitHub Releases: <https://github.com/voder-ai/eslint-plugin-traceability/releases>
|
|
432
|
+
- Versioning and Releases: This project uses semantic-release for automated versioning. The authoritative list of published versions and release notes is on GitHub Releases: <https://github.com/voder-ai/eslint-plugin-traceability/releases>
|
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.batchUpdateAnnotations = batchUpdateAnnotations;
|
|
4
4
|
exports.verifyAnnotations = verifyAnnotations;
|
|
5
|
-
/* eslint-disable traceability/valid-annotation-format */
|
|
6
5
|
const update_1 = require("./update");
|
|
7
6
|
const detect_1 = require("./detect");
|
|
8
7
|
/**
|
|
@@ -16,7 +15,6 @@ const detect_1 = require("./detect");
|
|
|
16
15
|
*/
|
|
17
16
|
function batchUpdateAnnotations(codebasePath, mappings) {
|
|
18
17
|
let totalUpdated = 0;
|
|
19
|
-
// @story docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md // @req REQ-MAINT-BATCH - Perform batch updates
|
|
20
18
|
for (const { oldPath, newPath } of mappings) {
|
|
21
19
|
totalUpdated += (0, update_1.updateAnnotationReferences)(codebasePath, oldPath, newPath);
|
|
22
20
|
}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
"use strict";
|
|
3
|
-
/* eslint-disable traceability/valid-annotation-format */
|
|
4
3
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
5
4
|
exports.runMaintenanceCli = runMaintenanceCli;
|
|
6
5
|
const commands_1 = require("./commands");
|
|
@@ -20,7 +19,6 @@ function runMaintenanceCli(rawArgv) {
|
|
|
20
19
|
const { subcommand: command } = initialNormalized;
|
|
21
20
|
if (!command || command === "-h" || command === "--help") {
|
|
22
21
|
// @supports docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md REQ-MAINT-SAFE
|
|
23
|
-
// @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
|
|
24
22
|
printHelp();
|
|
25
23
|
return commands_1.EXIT_OK;
|
|
26
24
|
}
|
|
@@ -29,35 +27,34 @@ function runMaintenanceCli(rawArgv) {
|
|
|
29
27
|
const normalized = initialNormalized;
|
|
30
28
|
try {
|
|
31
29
|
// @supports docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md REQ-MAINT-SAFE
|
|
32
|
-
// @supports docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md REQ-MAINT-SAFE - Catch unexpected errors and surface concise diagnostics without crashing
|
|
33
30
|
switch (command) {
|
|
34
31
|
case "detect":
|
|
35
|
-
// @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
|
|
36
33
|
return (0, commands_1.handleDetect)(normalized);
|
|
37
34
|
case "verify":
|
|
38
|
-
// @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
|
|
39
36
|
return (0, commands_1.handleVerify)(normalized);
|
|
40
37
|
case "report":
|
|
41
|
-
// @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
|
|
42
39
|
return (0, commands_1.handleReport)(normalized);
|
|
43
40
|
case "update": {
|
|
44
|
-
// @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
|
|
45
42
|
const result = (0, commands_1.handleUpdate)(normalized);
|
|
46
43
|
if (result === commands_1.EXIT_USAGE) {
|
|
47
|
-
// @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
|
|
48
45
|
printHelp();
|
|
49
46
|
}
|
|
50
47
|
return result;
|
|
51
48
|
}
|
|
52
49
|
default:
|
|
53
|
-
// @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
|
|
54
51
|
console.error(`Unknown command: ${command}`);
|
|
55
52
|
printHelp();
|
|
56
53
|
return commands_1.EXIT_USAGE;
|
|
57
54
|
}
|
|
58
55
|
}
|
|
59
56
|
catch (error) {
|
|
60
|
-
// @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
|
|
61
58
|
const message = error instanceof Error
|
|
62
59
|
? error.message
|
|
63
60
|
: "Unknown error in maintenance CLI";
|
|
@@ -71,7 +68,7 @@ function runMaintenanceCli(rawArgv) {
|
|
|
71
68
|
* @req REQ-MAINT-SAFE - Provide discoverable CLI usage information
|
|
72
69
|
*/
|
|
73
70
|
function printHelp() {
|
|
74
|
-
// @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
|
|
75
72
|
console.log(`traceability-maint - Traceability annotation maintenance tools
|
|
76
73
|
|
|
77
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
|
|
@@ -5,7 +5,6 @@ exports.handleDetect = handleDetect;
|
|
|
5
5
|
exports.handleVerify = handleVerify;
|
|
6
6
|
exports.handleReport = handleReport;
|
|
7
7
|
exports.handleUpdate = handleUpdate;
|
|
8
|
-
/* eslint-disable traceability/valid-annotation-format */
|
|
9
8
|
/**
|
|
10
9
|
* Subcommand handlers for the traceability-maint CLI.
|
|
11
10
|
*
|
|
@@ -25,7 +24,7 @@ exports.EXIT_OK = 0;
|
|
|
25
24
|
exports.EXIT_STALE = 1;
|
|
26
25
|
exports.EXIT_USAGE = 2;
|
|
27
26
|
/**
|
|
28
|
-
* Handle the `detect` subcommand for stale
|
|
27
|
+
* Handle the `detect` subcommand for stale story annotations.
|
|
29
28
|
* @story docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md
|
|
30
29
|
* @req REQ-MAINT-DETECT - CLI surface for detection of stale annotations
|
|
31
30
|
* @req REQ-MAINT-SAFE - Return specific exit codes for stale vs clean states
|
|
@@ -96,7 +95,7 @@ function handleReport(normalized) {
|
|
|
96
95
|
return exports.EXIT_OK;
|
|
97
96
|
}
|
|
98
97
|
/**
|
|
99
|
-
* Handle the `update` subcommand to rewrite
|
|
98
|
+
* Handle the `update` subcommand to rewrite story annotation references.
|
|
100
99
|
* @story docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md
|
|
101
100
|
* @req REQ-MAINT-UPDATE - CLI surface for updating annotation references
|
|
102
101
|
* @req REQ-MAINT-SAFE - Provide dry-run mode and explicit parameter checks
|
|
@@ -34,7 +34,6 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
34
34
|
})();
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
36
|
exports.detectStaleAnnotations = detectStaleAnnotations;
|
|
37
|
-
/* eslint-disable traceability/valid-annotation-format */
|
|
38
37
|
const fs = __importStar(require("fs"));
|
|
39
38
|
const path = __importStar(require("path"));
|
|
40
39
|
const utils_1 = require("./utils");
|
|
@@ -85,7 +84,7 @@ function processFileForStaleAnnotations(file, workspaceRoot, cwd, stale) {
|
|
|
85
84
|
}
|
|
86
85
|
catch {
|
|
87
86
|
// @supports docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md REQ-MAINT-DETECT
|
|
88
|
-
// @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
|
|
89
88
|
return;
|
|
90
89
|
}
|
|
91
90
|
const regex = /@story\s+([^\s]+)/g;
|
|
@@ -116,7 +115,7 @@ function handleStoryMatch(storyPath, workspaceRoot, cwd, stale) {
|
|
|
116
115
|
const inProjectCandidates = getInProjectCandidates(storyProjectCandidate, storyCodebaseCandidate, workspaceRoot);
|
|
117
116
|
// If both candidates are out-of-project, do not mark as stale and skip FS checks
|
|
118
117
|
if (inProjectCandidates.length === 0) {
|
|
119
|
-
// @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
|
|
120
119
|
return;
|
|
121
120
|
}
|
|
122
121
|
// @story docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md
|
|
@@ -142,7 +141,7 @@ function getInProjectCandidates(storyProjectCandidate, storyCodebaseCandidate, w
|
|
|
142
141
|
}
|
|
143
142
|
catch {
|
|
144
143
|
// @supports docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md REQ-MAINT-DETECT
|
|
145
|
-
// @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
|
|
146
145
|
projectBoundary = {
|
|
147
146
|
isWithinProject: false,
|
|
148
147
|
candidate: storyProjectCandidate,
|
|
@@ -154,7 +153,7 @@ function getInProjectCandidates(storyProjectCandidate, storyCodebaseCandidate, w
|
|
|
154
153
|
}
|
|
155
154
|
catch {
|
|
156
155
|
// @supports docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md REQ-MAINT-DETECT
|
|
157
|
-
// @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
|
|
158
157
|
codebaseBoundary = {
|
|
159
158
|
isWithinProject: false,
|
|
160
159
|
candidate: storyCodebaseCandidate,
|
|
@@ -162,11 +161,11 @@ function getInProjectCandidates(storyProjectCandidate, storyCodebaseCandidate, w
|
|
|
162
161
|
}
|
|
163
162
|
const inProjectCandidates = [];
|
|
164
163
|
if (projectBoundary.isWithinProject) {
|
|
165
|
-
// @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
|
|
166
165
|
inProjectCandidates.push(projectBoundary.candidate);
|
|
167
166
|
}
|
|
168
167
|
if (codebaseBoundary.isWithinProject) {
|
|
169
|
-
// @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
|
|
170
169
|
inProjectCandidates.push(codebaseBoundary.candidate);
|
|
171
170
|
}
|
|
172
171
|
return inProjectCandidates;
|
|
@@ -183,7 +182,7 @@ function anyInProjectCandidateExists(inProjectCandidates) {
|
|
|
183
182
|
(p) => {
|
|
184
183
|
const exists = fs.existsSync(p);
|
|
185
184
|
if (!exists) {
|
|
186
|
-
// @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
|
|
187
186
|
}
|
|
188
187
|
return exists;
|
|
189
188
|
});
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.generateMaintenanceReport = generateMaintenanceReport;
|
|
4
|
-
/* eslint-disable traceability/valid-annotation-format */
|
|
5
4
|
const detect_1 = require("./detect");
|
|
6
5
|
/**
|
|
7
6
|
* Generate a report of maintenance operations performed
|
|
@@ -13,8 +12,8 @@ const detect_1 = require("./detect");
|
|
|
13
12
|
*/
|
|
14
13
|
function generateMaintenanceReport(codebasePath) {
|
|
15
14
|
const staleAnnotations = (0, detect_1.detectStaleAnnotations)(codebasePath);
|
|
16
|
-
// @supports docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md REQ-MAINT-SAFE
|
|
17
|
-
// @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
|
|
18
17
|
if (staleAnnotations.length === 0) {
|
|
19
18
|
return "";
|
|
20
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
|
+
}
|
|
@@ -34,7 +34,6 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
34
34
|
})();
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
36
|
exports.updateAnnotationReferences = updateAnnotationReferences;
|
|
37
|
-
/* eslint-disable traceability/valid-annotation-format */
|
|
38
37
|
const fs = __importStar(require("fs"));
|
|
39
38
|
const utils_1 = require("./utils");
|
|
40
39
|
/**
|
|
@@ -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;
|