eslint-plugin-traceability 1.8.1 → 1.8.2

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.
Files changed (44) hide show
  1. package/CHANGELOG.md +4 -4
  2. package/README.md +4 -4
  3. package/SECURITY.md +40 -37
  4. package/lib/src/maintenance/cli.js +12 -16
  5. package/lib/src/maintenance/detect.js +28 -1
  6. package/lib/src/rules/helpers/require-story-io.d.ts +2 -2
  7. package/lib/src/rules/helpers/require-story-io.js +13 -13
  8. package/lib/src/rules/helpers/valid-annotation-format-internal.d.ts +2 -2
  9. package/lib/src/rules/helpers/valid-annotation-format-internal.js +3 -3
  10. package/lib/src/rules/helpers/valid-annotation-utils.d.ts +5 -0
  11. package/lib/src/rules/helpers/valid-annotation-utils.js +43 -5
  12. package/lib/src/rules/helpers/valid-implements-utils.d.ts +11 -11
  13. package/lib/src/rules/helpers/valid-implements-utils.js +11 -11
  14. package/lib/src/rules/helpers/valid-story-reference-helpers.js +19 -0
  15. package/lib/src/rules/prefer-implements-annotation.d.ts +7 -7
  16. package/lib/src/rules/prefer-implements-annotation.js +21 -21
  17. package/lib/src/rules/valid-annotation-format.js +50 -24
  18. package/lib/src/rules/valid-req-reference.js +9 -9
  19. package/lib/src/utils/annotation-checker.js +3 -1
  20. package/lib/src/utils/reqAnnotationDetection.d.ts +2 -2
  21. package/lib/src/utils/reqAnnotationDetection.js +28 -28
  22. package/lib/tests/maintenance/batch.test.js +11 -11
  23. package/lib/tests/maintenance/cli.test.js +34 -27
  24. package/lib/tests/maintenance/report.test.js +7 -7
  25. package/lib/tests/rules/prefer-implements-annotation.test.js +27 -22
  26. package/lib/tests/rules/require-branch-annotation.test.js +15 -36
  27. package/lib/tests/rules/require-req-annotation.test.js +31 -104
  28. package/lib/tests/rules/require-story-annotation.test.js +3 -3
  29. package/lib/tests/rules/require-story-io-behavior.test.js +2 -7
  30. package/lib/tests/rules/require-story-io.edgecases.test.js +2 -7
  31. package/lib/tests/rules/require-story-visitors-edgecases.test.js +8 -8
  32. package/lib/tests/rules/valid-annotation-format.test.js +23 -23
  33. package/lib/tests/rules/valid-req-reference.test.js +9 -9
  34. package/lib/tests/rules/valid-story-reference.test.js +4 -43
  35. package/lib/tests/utils/annotation-checker.test.js +2 -6
  36. package/lib/tests/utils/fsTestHelpers.d.ts +7 -0
  37. package/lib/tests/utils/fsTestHelpers.js +26 -0
  38. package/lib/tests/utils/ioTestHelpers.d.ts +7 -0
  39. package/lib/tests/utils/ioTestHelpers.js +24 -0
  40. package/lib/tests/utils/temp-dir-helpers.d.ts +14 -0
  41. package/lib/tests/utils/temp-dir-helpers.js +61 -0
  42. package/package.json +3 -2
  43. package/user-docs/api-reference.md +12 -15
  44. package/user-docs/migration-guide.md +21 -21
@@ -38,12 +38,16 @@ function createStoryFix(context, comment, fixed) {
38
38
  const commentText = sourceCode.getText(comment);
39
39
  const search = "@story";
40
40
  const tagIndex = commentText.indexOf(search);
41
+ // @story docs/stories/008.0-DEV-AUTO-FIX.story.md
42
+ // @req REQ-AUTOFIX-SAFE - Skip auto-fix when @story tag cannot be reliably located
41
43
  if (tagIndex === valid_annotation_utils_1.TAG_NOT_FOUND_INDEX) {
42
44
  return null;
43
45
  }
44
46
  const afterTagIndex = tagIndex + search.length;
45
47
  const rest = commentText.slice(afterTagIndex);
46
48
  const valueMatch = rest.match(/[^\S\r\n]*([^\r\n*]+)/);
49
+ // @story docs/stories/008.0-DEV-AUTO-FIX.story.md
50
+ // @req REQ-AUTOFIX-SAFE - Abort auto-fix when story value range cannot be safely determined
47
51
  if (!valueMatch || valueMatch.index === undefined) {
48
52
  return null;
49
53
  }
@@ -79,6 +83,8 @@ function createStoryFix(context, comment, fixed) {
79
83
  */
80
84
  function reportInvalidStoryFormatWithFix(context, comment, collapsed, fixed) {
81
85
  const fixFactory = createStoryFix(context, comment, fixed);
86
+ // @story docs/stories/008.0-DEV-AUTO-FIX.story.md
87
+ // @req REQ-AUTOFIX-SAFE - Fall back to reporting without fix when safe fix cannot be created
82
88
  if (!fixFactory) {
83
89
  reportInvalidStoryFormat(context, comment, collapsed, (0, valid_annotation_options_1.getResolvedDefaults)());
84
90
  return;
@@ -108,6 +114,8 @@ function reportInvalidStoryFormatWithFix(context, comment, collapsed, fixed) {
108
114
  */
109
115
  function validateStoryAnnotation(context, comment, rawValue, options) {
110
116
  const trimmed = rawValue.trim();
117
+ // @story docs/stories/005.0-DEV-ANNOTATION-VALIDATION.story.md
118
+ // @req REQ-PATH-FORMAT - Treat missing @story value as a specific validation error
111
119
  if (!trimmed) {
112
120
  context.report({
113
121
  node: comment,
@@ -118,14 +126,20 @@ function validateStoryAnnotation(context, comment, rawValue, options) {
118
126
  }
119
127
  const collapsed = (0, valid_annotation_utils_1.collapseAnnotationValue)(trimmed);
120
128
  const pathPattern = options.storyPattern;
129
+ // @story docs/stories/005.0-DEV-ANNOTATION-VALIDATION.story.md
130
+ // @req REQ-PATH-FORMAT - Accept @story value when it matches configured storyPattern
121
131
  if (pathPattern.test(collapsed)) {
122
132
  return;
123
133
  }
134
+ // @story docs/stories/005.0-DEV-ANNOTATION-VALIDATION.story.md
135
+ // @req REQ-PATH-FORMAT - Reject @story values containing internal whitespace as invalid
124
136
  if (/\s/.test(trimmed)) {
125
137
  reportInvalidStoryFormat(context, comment, collapsed, options);
126
138
  return;
127
139
  }
128
140
  const fixed = (0, valid_annotation_utils_1.getFixedStoryPath)(collapsed);
141
+ // @story docs/stories/008.0-DEV-AUTO-FIX.story.md
142
+ // @req REQ-AUTOFIX-FORMAT - Apply suffix-only auto-fix when it yields a pattern-compliant path
129
143
  if (fixed && pathPattern.test(fixed)) {
130
144
  reportInvalidStoryFormatWithFix(context, comment, collapsed, fixed);
131
145
  return;
@@ -146,6 +160,8 @@ function validateStoryAnnotation(context, comment, rawValue, options) {
146
160
  */
147
161
  function validateReqAnnotation(context, comment, rawValue, options) {
148
162
  const trimmed = rawValue.trim();
163
+ // @story docs/stories/005.0-DEV-ANNOTATION-VALIDATION.story.md
164
+ // @req REQ-REQ-FORMAT - Treat missing @req value as a specific validation error
149
165
  if (!trimmed) {
150
166
  context.report({
151
167
  node: comment,
@@ -156,6 +172,8 @@ function validateReqAnnotation(context, comment, rawValue, options) {
156
172
  }
157
173
  const collapsed = (0, valid_annotation_utils_1.collapseAnnotationValue)(trimmed);
158
174
  const reqPattern = options.reqPattern;
175
+ // @story docs/stories/005.0-DEV-ANNOTATION-VALIDATION.story.md
176
+ // @req REQ-REQ-FORMAT - Flag @req identifiers that do not match the configured pattern
159
177
  if (!reqPattern.test(collapsed)) {
160
178
  context.report({
161
179
  node: comment,
@@ -165,10 +183,10 @@ function validateReqAnnotation(context, comment, rawValue, options) {
165
183
  }
166
184
  }
167
185
  /**
168
- * Validate an @implements annotation value and report detailed errors when needed.
186
+ * Validate an @supports annotation value and report detailed errors when needed.
169
187
  *
170
188
  * Expected format:
171
- * @implements <storyPath> <REQ-ID> [<REQ-ID> ...]
189
+ * @supports <storyPath> <REQ-ID> [<REQ-ID> ...]
172
190
  *
173
191
  * Validation rules:
174
192
  * - Value must include at least a story path and one requirement ID.
@@ -179,7 +197,7 @@ function validateReqAnnotation(context, comment, rawValue, options) {
179
197
  * requirement ID issues reuse the existing "invalidReqFormat" message.
180
198
  *
181
199
  * @story docs/stories/010.2-DEV-MULTI-STORY-SUPPORT.story.md
182
- * @req REQ-IMPLEMENTS-PARSE - Parse @implements annotations without affecting @story/@req
200
+ * @req REQ-SUPPORTS-PARSE - Parse @supports annotations without affecting @story/@req
183
201
  * @req REQ-FORMAT-VALIDATION - Validate @implements story path and requirement IDs
184
202
  * @req REQ-MIXED-SUPPORT - Support mixed @story/@req/@implements usage in comments
185
203
  */
@@ -207,15 +225,15 @@ function validateImplementsAnnotation(context, comment, rawValue, options) {
207
225
  * @req REQ-MIXED-SUPPORT - Support mixed @story/@req/@implements usage in comments
208
226
  */
209
227
  function finalizePendingAnnotation(context, comment, options, pending) {
228
+ // @story docs/stories/005.0-DEV-ANNOTATION-VALIDATION.story.md
229
+ // @req REQ-MULTILINE-SUPPORT - Do nothing when there is no pending multi-line annotation to finalize
210
230
  if (!pending) {
211
231
  return null;
212
232
  }
213
233
  // @story docs/stories/005.0-DEV-ANNOTATION-VALIDATION.story.md
214
- // @story docs/stories/008.0-DEV-AUTO-FIX.story.md
215
- // @story docs/stories/010.2-DEV-MULTI-STORY-SUPPORT.story.md
216
- // @req REQ-SYNTAX-VALIDATION - Dispatch validation based on annotation type
217
- // @req REQ-AUTOFIX-FORMAT - Provide safe, minimal automatic fixes for common format issues
218
- // @req REQ-MIXED-SUPPORT - Support mixed @story/@req/@implements usage in comments
234
+ // @req REQ-SYNTAX-VALIDATION - Dispatch to @story or @req validator based on pending annotation type
235
+ // @req REQ-AUTOFIX-FORMAT - Route to story validator which may apply safe auto-fixes
236
+ // @req REQ-MIXED-SUPPORT - Ensure @story and @req annotations are handled independently
219
237
  if (pending.type === "story") {
220
238
  validateStoryAnnotation(context, comment, pending.value, options);
221
239
  }
@@ -233,20 +251,24 @@ function finalizePendingAnnotation(context, comment, options, pending) {
233
251
  * @req REQ-SYNTAX-VALIDATION - Start new pending annotation when a tag is found
234
252
  * @req REQ-MULTILINE-SUPPORT - Treat subsequent lines as continuation for pending annotation
235
253
  * @req REQ-AUTOFIX-FORMAT - Provide safe, minimal automatic fixes for common format issues
236
- * @req REQ-IMPLEMENTS-PARSE - Parse @implements annotations without affecting @story/@req
254
+ * @req REQ-IMPLEMENTS-PARSE - Parse @supports annotations without affecting @story/@req
237
255
  * @req REQ-FORMAT-VALIDATION - Validate @implements story path and requirement IDs
238
256
  * @req REQ-MIXED-SUPPORT - Support mixed @story/@req/@implements usage in comments
239
257
  */
240
258
  function processCommentLine({ normalized, pending, context, comment, options, }) {
259
+ // @story docs/stories/005.0-DEV-ANNOTATION-VALIDATION.story.md
260
+ // @req REQ-FLEXIBLE-PARSING - Ignore empty normalized lines without affecting pending state
241
261
  if (!normalized) {
242
262
  return pending;
243
263
  }
244
264
  const isStory = /@story\b/.test(normalized);
245
265
  const isReq = /@req\b/.test(normalized);
246
- const isImplements = /@implements\b/.test(normalized);
247
- // Handle @implements as an immediate, single-line annotation
266
+ const isImplements = /@supports\b/.test(normalized);
267
+ // Handle @supports as an immediate, single-line annotation
268
+ // @story docs/stories/010.2-DEV-MULTI-STORY-SUPPORT.story.md
269
+ // @req REQ-IMPLEMENTS-PARSE - Immediately validate @supports without starting multi-line state
248
270
  if (isImplements) {
249
- const implementsValue = normalized.replace(/^@implements\b/, "").trim();
271
+ const implementsValue = normalized.replace(/^@supports\b/, "").trim();
250
272
  validateImplementsAnnotation(context, comment, implementsValue, options);
251
273
  return pending;
252
274
  }
@@ -268,11 +290,13 @@ function processCommentLine({ normalized, pending, context, comment, options, })
268
290
  // @story docs/stories/005.0-DEV-ANNOTATION-VALIDATION.story.md
269
291
  // @story docs/stories/008.0-DEV-AUTO-FIX.story.md
270
292
  // @story docs/stories/010.2-DEV-MULTI-STORY-SUPPORT.story.md
271
- // @req REQ-MULTILINE-SUPPORT - Treat subsequent lines as continuation for pending annotation
272
- // @req REQ-AUTOFIX-FORMAT - Provide safe, minimal automatic fixes for common format issues
273
- // @req REQ-MIXED-SUPPORT - Support mixed @story/@req/@implements usage in comments
293
+ // @req REQ-MULTILINE-SUPPORT - Extend value of existing pending annotation across lines
294
+ // @req REQ-AUTOFIX-FORMAT - Maintain complete logical value for downstream validation and fixes
295
+ // @req REQ-MIXED-SUPPORT - Leave non-annotation lines untouched when no pending state exists
274
296
  if (pending) {
275
297
  const continuation = normalized.trim();
298
+ // @story docs/stories/005.0-DEV-ANNOTATION-VALIDATION.story.md
299
+ // @req REQ-MULTILINE-SUPPORT - Skip blank continuation lines without altering pending annotation
276
300
  if (!continuation) {
277
301
  return pending;
278
302
  }
@@ -288,13 +312,13 @@ function processCommentLine({ normalized, pending, context, comment, options, })
288
312
  return pending;
289
313
  }
290
314
  /**
291
- * Process a single comment node and validate any @story/@req/@implements annotations it contains.
315
+ * Process a single comment node and validate any @story/@req/@supports annotations it contains.
292
316
  *
293
317
  * Supports @story and @req annotations whose values span multiple lines within the same
294
318
  * comment block, collapsing whitespace so that the logical value can be
295
319
  * validated against the configured patterns.
296
320
  *
297
- * @implements annotations are validated immediately per-line and are not
321
+ * @supports annotations are validated immediately per-line and are not
298
322
  * accumulated into pending multi-line state.
299
323
  *
300
324
  * @story docs/stories/005.0-DEV-ANNOTATION-VALIDATION.story.md
@@ -303,7 +327,7 @@ function processCommentLine({ normalized, pending, context, comment, options, })
303
327
  * @req REQ-MULTILINE-SUPPORT - Handle annotations split across multiple lines
304
328
  * @req REQ-FLEXIBLE-PARSING - Support reasonable variations in whitespace and formatting
305
329
  * @req REQ-AUTOFIX-FORMAT - Provide safe, minimal automatic fixes for common format issues
306
- * @req REQ-IMPLEMENTS-PARSE - Parse @implements annotations without affecting @story/@req
330
+ * @req REQ-IMPLEMENTS-PARSE - Parse @supports annotations without affecting @story/@req
307
331
  * @req REQ-FORMAT-VALIDATION - Validate @implements story path and requirement IDs
308
332
  * @req REQ-MIXED-SUPPORT - Support mixed @story/@req/@implements usage in comments
309
333
  */
@@ -326,7 +350,7 @@ exports.default = {
326
350
  meta: {
327
351
  type: "problem",
328
352
  docs: {
329
- description: "Validate format and syntax of @story, @req, and @implements annotations",
353
+ description: "Validate format and syntax of @story, @req, and @supports annotations",
330
354
  recommended: "error",
331
355
  },
332
356
  messages: {
@@ -346,8 +370,8 @@ exports.default = {
346
370
  invalidReqFormat: "Invalid annotation format: {{details}}.",
347
371
  /**
348
372
  * @story docs/stories/010.2-DEV-MULTI-STORY-SUPPORT.story.md
349
- * @req REQ-ERROR-SPECIFIC - Provide specific details about invalid @implements annotation format
350
- * @req REQ-ERROR-CONTEXT - Include human-readable details about the expected @implements annotation format
373
+ * @req REQ-ERROR-SPECIFIC - Provide specific details about invalid @supports annotation format
374
+ * @req REQ-ERROR-CONTEXT - Include human-readable details about the expected @supports annotation format
351
375
  * @req REQ-ERROR-CONSISTENCY - Use shared "Invalid annotation format: {{details}}." message pattern across rules
352
376
  * @req REQ-FORMAT-VALIDATION - Validate @implements story path and requirement IDs
353
377
  */
@@ -383,7 +407,7 @@ exports.default = {
383
407
  * @req REQ-AUTOFIX-FORMAT - Provide safe, minimal automatic fixes for common format issues
384
408
  * @req REQ-REGEX-VALIDATION - Derive validation regexes from shared options helper
385
409
  * @req REQ-BACKWARD-COMP - Fall back to default patterns and continue validation on config errors
386
- * @req REQ-IMPLEMENTS-PARSE - Parse @implements annotations without affecting @story/@req
410
+ * @req REQ-IMPLEMENTS-PARSE - Parse @supports annotations without affecting @story/@req
387
411
  * @req REQ-FORMAT-VALIDATION - Validate @implements story path and requirement IDs
388
412
  * @req REQ-MIXED-SUPPORT - Support mixed @story/@req/@implements usage in comments
389
413
  */
@@ -393,7 +417,7 @@ exports.default = {
393
417
  const optionErrors = (0, valid_annotation_options_1.getOptionErrors)();
394
418
  return {
395
419
  /**
396
- * Program-level handler that inspects all comments for @story, @req, and @implements tags
420
+ * Program-level handler that inspects all comments for @story, @req, and @supports tags
397
421
  *
398
422
  * @story docs/stories/005.0-DEV-ANNOTATION-VALIDATION.story.md
399
423
  * @story docs/stories/008.0-DEV-AUTO-FIX.story.md
@@ -404,11 +428,13 @@ exports.default = {
404
428
  * @req REQ-AUTOFIX-FORMAT - Provide safe, minimal automatic fixes for common format issues
405
429
  * @req REQ-REGEX-VALIDATION - Surface regex configuration errors without blocking validation
406
430
  * @req REQ-BACKWARD-COMP - Continue validating comments using default patterns on error
407
- * @req REQ-IMPLEMENTS-PARSE - Parse @implements annotations without affecting @story/@req
431
+ * @req REQ-IMPLEMENTS-PARSE - Parse @supports annotations without affecting @story/@req
408
432
  * @req REQ-FORMAT-VALIDATION - Validate @implements story path and requirement IDs
409
433
  * @req REQ-MIXED-SUPPORT - Support mixed @story/@req/@implements usage in comments
410
434
  */
411
435
  Program(node) {
436
+ // @story docs/stories/010.1-DEV-CONFIGURABLE-PATTERNS.story.md
437
+ // @req REQ-REGEX-VALIDATION - Report any configuration errors discovered while resolving options
412
438
  if (optionErrors && optionErrors.length > 0) {
413
439
  optionErrors.forEach((details) => {
414
440
  context.report({
@@ -15,7 +15,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
15
15
  const fs_1 = __importDefault(require("fs"));
16
16
  const path_1 = __importDefault(require("path"));
17
17
  /**
18
- * Token index configuration for @implements annotations.
18
+ * Token index configuration for @supports annotations.
19
19
  * This clarifies the expected positions of the story path and first requirement ID
20
20
  * and avoids hard-coded "magic number" indices in parsing logic.
21
21
  * @story docs/stories/010.2-DEV-MULTI-STORY-SUPPORT.story.md
@@ -175,11 +175,11 @@ function validateReqLine(opts) {
175
175
  });
176
176
  }
177
177
  /**
178
- * Parse an @implements annotation line into its story path and requirement IDs.
179
- * Expects the format: "@implements <storyPath> <REQ-ID-1> <REQ-ID-2> ..."
178
+ * Parse a @supports annotation line into its story path and requirement IDs.
179
+ * Expects the format: "@supports <storyPath> <REQ-ID-1> <REQ-ID-2> ..."
180
180
  * Invalid formats (missing storyPath or reqIds) are ignored by this deep rule.
181
181
  * @story docs/stories/010.2-DEV-MULTI-STORY-SUPPORT.story.md
182
- * @req REQ-IMPLEMENTS-VALIDATE - Support validation of @implements annotations
182
+ * @req REQ-IMPLEMENTS-VALIDATE - Support validation of @supports annotations
183
183
  * @req REQ-MIXED-SUPPORT - Allow mixed @story/@req/@implements usage in the same comment
184
184
  * @req REQ-SCOPED-IDS - Treat requirement IDs as scoped to the referenced story file
185
185
  */
@@ -193,12 +193,12 @@ function parseImplementsLine(line) {
193
193
  return { storyPath, reqIds };
194
194
  }
195
195
  /**
196
- * Validate an @implements annotation line against the referenced story content.
196
+ * Validate an @supports annotation line against the referenced story content.
197
197
  * Performs path validation, file reading, caching, and requirement existence checks
198
198
  * for each requirement ID listed on the line.
199
199
  * @story docs/stories/010.2-DEV-MULTI-STORY-SUPPORT.story.md
200
- * @req REQ-IMPLEMENTS-VALIDATE - Validate that all @implements requirement IDs exist
201
- * @req REQ-MIXED-SUPPORT - Ensure @implements can coexist with @story/@req annotations
200
+ * @req REQ-IMPLEMENTS-VALIDATE - Validate that all @supports requirement IDs exist
201
+ * @req REQ-MIXED-SUPPORT - Ensure @supports can coexist with @story/@req annotations
202
202
  * @req REQ-SCOPED-IDS - Validate requirement IDs in the scope of their explicit story
203
203
  */
204
204
  function validateImplementsLine(opts) {
@@ -234,7 +234,7 @@ function validateImplementsLine(opts) {
234
234
  * @req REQ-DEEP-PARSE - Parse annotation lines for @story and @req tags
235
235
  * @req REQ-DEEP-MATCH - Dispatch @req lines for validation against story requirements
236
236
  * @story docs/stories/010.2-DEV-MULTI-STORY-SUPPORT.story.md
237
- * @req REQ-IMPLEMENTS-VALIDATE - Dispatch @implements lines for validation
237
+ * @req REQ-IMPLEMENTS-VALIDATE - Dispatch @supports lines for validation
238
238
  * @req REQ-MIXED-SUPPORT - Support mixed annotation types without interfering with each other
239
239
  */
240
240
  function handleAnnotationLine(opts) {
@@ -247,7 +247,7 @@ function handleAnnotationLine(opts) {
247
247
  validateReqLine({ comment, context, line, storyPath, cwd, reqCache });
248
248
  return storyPath;
249
249
  }
250
- else if (line.startsWith("@implements")) {
250
+ else if (line.startsWith("@supports")) {
251
251
  validateImplementsLine({ comment, context, line, cwd, reqCache });
252
252
  return storyPath;
253
253
  }
@@ -76,13 +76,15 @@ function getFixTargetNode(node) {
76
76
  * Returned function is a proper named function so no inline arrow is used.
77
77
  * @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
78
78
  * @req REQ-ANNOTATION-AUTOFIX - Provide autofix for missing @req annotation
79
+ * @implements docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md REQ-ANNOTATION-AUTOFIX REQ-ANNOTATION-REPORTING
79
80
  */
80
81
  function createMissingReqFix(node) {
81
82
  const target = getFixTargetNode(node);
82
83
  /**
83
84
  * Fixer used to insert a default @req annotation before the chosen target node.
84
85
  * @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
85
- * @req REQ-ANNOTATION-AUTOFIX - Provide autofix for missing @req annotation
86
+ * @req REQ-ANNOTATION-AUTOFIX - Implement autofix insertion for missing @req
87
+ * @req REQ-ANNOTATION-REPORTING - Support actionable fix in reported problem
86
88
  */
87
89
  return function missingReqFix(fixer) {
88
90
  return fixer.insertTextBefore(target, "/** @req <REQ-ID> */\n");
@@ -1,9 +1,9 @@
1
1
  /**
2
2
  * Helper to determine whether a JSDoc or any nearby comments contain a requirement annotation.
3
- * Treats both @req and @implements annotations as evidence of requirement coverage.
3
+ * Treats both @req and @supports annotations as evidence of requirement coverage.
4
4
  * @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
5
5
  * @story docs/stories/010.2-DEV-MULTI-STORY-SUPPORT.story.md
6
6
  * @req REQ-ANNOTATION-REQ-DETECTION - Determine presence of @req annotation
7
- * @req REQ-REQUIRE-ACCEPTS-IMPLEMENTS - Accept @implements as requirement coverage
7
+ * @req REQ-REQUIRE-ACCEPTS-IMPLEMENTS - Accept @supports as requirement coverage
8
8
  */
9
9
  export declare function hasReqAnnotation(jsdoc: any, comments: any[], context?: any, node?: any): boolean;
@@ -9,23 +9,23 @@ exports.hasReqAnnotation = hasReqAnnotation;
9
9
  const require_story_io_1 = require("../rules/helpers/require-story-io");
10
10
  /**
11
11
  * Predicate helper to check whether a comment contains a requirement annotation.
12
- * Treats both @req and @implements annotations as satisfying requirement presence checks.
12
+ * Treats both @req and @supports annotations as satisfying requirement presence checks.
13
13
  * @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
14
14
  * @story docs/stories/010.2-DEV-MULTI-STORY-SUPPORT.story.md
15
15
  * @req REQ-ANNOTATION-REQ-DETECTION - Detect @req tag inside a comment
16
- * @req REQ-REQUIRE-ACCEPTS-IMPLEMENTS - Accept @implements as requirement annotation
16
+ * @req REQ-REQUIRE-ACCEPTS-IMPLEMENTS - Accept @supports as requirement annotation
17
17
  */
18
18
  function commentContainsReq(c) {
19
19
  return (c &&
20
20
  typeof c.value === "string" &&
21
- (c.value.includes("@req") || c.value.includes("@implements")));
21
+ (c.value.includes("@req") || c.value.includes("@supports")));
22
22
  }
23
23
  /**
24
24
  * Line-based helper adapted from linesBeforeHasStory to detect requirement annotations.
25
- * Lines containing either @req or @implements are treated as annotated.
25
+ * Lines containing either @req or @supports are treated as annotated.
26
26
  * @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
27
27
  * @req REQ-ANNOTATION-REQ-DETECTION - Detect @req in preceding source lines
28
- * @req REQ-REQUIRE-ACCEPTS-IMPLEMENTS - Accept @implements in preceding source lines
28
+ * @req REQ-REQUIRE-ACCEPTS-IMPLEMENTS - Accept @supports in preceding source lines
29
29
  */
30
30
  function linesBeforeHasReq(sourceCode, node) {
31
31
  const lines = sourceCode && sourceCode.lines;
@@ -40,18 +40,18 @@ function linesBeforeHasReq(sourceCode, node) {
40
40
  }
41
41
  const from = Math.max(0, startLine - 1 - require_story_io_1.LOOKBACK_LINES);
42
42
  const to = Math.max(0, startLine - 1);
43
- // Scan each physical line in the configured lookback window for @req or @implements markers.
43
+ // Scan each physical line in the configured lookback window for @req or @supports markers.
44
44
  // @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
45
45
  // @req REQ-ANNOTATION-REQ-DETECTION - Search preceding lines for @req text
46
- // @req REQ-REQUIRE-ACCEPTS-IMPLEMENTS - Search preceding lines for @implements text
46
+ // @req REQ-REQUIRE-ACCEPTS-IMPLEMENTS - Search preceding lines for @supports text
47
47
  for (let i = from; i < to; i++) {
48
48
  const text = lines[i];
49
- // When a line contains @req or @implements we treat the function as already annotated.
49
+ // When a line contains @req or @supports we treat the function as already annotated.
50
50
  // @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
51
51
  // @req REQ-ANNOTATION-REQ-DETECTION - Detect @req marker in raw source lines
52
- // @req REQ-REQUIRE-ACCEPTS-IMPLEMENTS - Detect @implements marker in raw source lines
52
+ // @req REQ-REQUIRE-ACCEPTS-IMPLEMENTS - Detect @supports marker in raw source lines
53
53
  if (typeof text === "string" &&
54
- (text.includes("@req") || text.includes("@implements"))) {
54
+ (text.includes("@req") || text.includes("@supports"))) {
55
55
  return true;
56
56
  }
57
57
  }
@@ -59,34 +59,34 @@ function linesBeforeHasReq(sourceCode, node) {
59
59
  }
60
60
  /**
61
61
  * Parent-chain helper adapted from parentChainHasStory to detect requirement annotations.
62
- * Accepts both @req and @implements in parent-chain comments as satisfying requirement presence.
62
+ * Accepts both @req and @supports in parent-chain comments as satisfying requirement presence.
63
63
  * @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
64
64
  * @req REQ-ANNOTATION-REQ-DETECTION - Detect @req in parent-chain comments
65
- * @req REQ-REQUIRE-ACCEPTS-IMPLEMENTS - Accept @implements in parent-chain comments
65
+ * @req REQ-REQUIRE-ACCEPTS-IMPLEMENTS - Accept @supports in parent-chain comments
66
66
  */
67
67
  function parentChainHasReq(sourceCode, node) {
68
68
  let p = node && node.parent;
69
69
  // Walk up the parent chain and inspect comments attached to each ancestor.
70
- // Accept both @req and @implements markers when local comments are absent.
70
+ // Accept both @req and @supports markers when local comments are absent.
71
71
  // @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
72
72
  // @req REQ-ANNOTATION-REQ-DETECTION - Traverse parent nodes when local comments are absent
73
- // @req REQ-REQUIRE-ACCEPTS-IMPLEMENTS - Allow @implements to satisfy requirement on parents
73
+ // @req REQ-REQUIRE-ACCEPTS-IMPLEMENTS - Allow @supports to satisfy requirement on parents
74
74
  while (p) {
75
75
  const pComments = typeof sourceCode?.getCommentsBefore === "function"
76
76
  ? sourceCode.getCommentsBefore(p) || []
77
77
  : [];
78
- // Look for @req or @implements in comments immediately preceding each parent node.
78
+ // Look for @req or @supports in comments immediately preceding each parent node.
79
79
  // @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
80
80
  // @req REQ-ANNOTATION-REQ-DETECTION - Detect @req markers in parent comments
81
- // @req REQ-REQUIRE-ACCEPTS-IMPLEMENTS - Detect @implements markers in parent comments
81
+ // @req REQ-REQUIRE-ACCEPTS-IMPLEMENTS - Detect @supports markers in parent comments
82
82
  if (Array.isArray(pComments) && pComments.some(commentContainsReq)) {
83
83
  return true;
84
84
  }
85
85
  const pLeading = p.leadingComments || [];
86
- // Also inspect leadingComments attached directly to the parent node, accepting @req or @implements.
86
+ // Also inspect leadingComments attached directly to the parent node, accepting @req or @supports.
87
87
  // @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
88
88
  // @req REQ-ANNOTATION-REQ-DETECTION - Detect @req markers in parent leadingComments
89
- // @req REQ-REQUIRE-ACCEPTS-IMPLEMENTS - Detect @implements markers in parent leadingComments
89
+ // @req REQ-REQUIRE-ACCEPTS-IMPLEMENTS - Detect @supports markers in parent leadingComments
90
90
  if (Array.isArray(pLeading) && pLeading.some(commentContainsReq)) {
91
91
  return true;
92
92
  }
@@ -96,11 +96,11 @@ function parentChainHasReq(sourceCode, node) {
96
96
  }
97
97
  /**
98
98
  * Fallback text window helper adapted from fallbackTextBeforeHasStory to detect requirement annotations.
99
- * Treats both @req and @implements in the fallback text window as requirement presence.
99
+ * Treats both @req and @supports in the fallback text window as requirement presence.
100
100
  * @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
101
101
  * @story docs/stories/010.2-DEV-MULTI-STORY-SUPPORT.story.md
102
102
  * @req REQ-ANNOTATION-REQ-DETECTION - Detect @req in fallback text window before node
103
- * @req REQ-REQUIRE-ACCEPTS-IMPLEMENTS - Accept @implements in fallback text window before node
103
+ * @req REQ-REQUIRE-ACCEPTS-IMPLEMENTS - Accept @supports in fallback text window before node
104
104
  */
105
105
  function fallbackTextBeforeHasReq(sourceCode, node) {
106
106
  // Guard against unsupported sourceCode or nodes without a usable range.
@@ -120,13 +120,13 @@ function fallbackTextBeforeHasReq(sourceCode, node) {
120
120
  try {
121
121
  const start = Math.max(0, range[0] - require_story_io_1.FALLBACK_WINDOW);
122
122
  const textBefore = sourceCode.getText().slice(start, range[0]);
123
- // Detect @req or @implements in the bounded text window immediately preceding the node.
123
+ // Detect @req or @supports in the bounded text window immediately preceding the node.
124
124
  // @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
125
125
  // @story docs/stories/010.2-DEV-MULTI-STORY-SUPPORT.story.md
126
126
  // @req REQ-ANNOTATION-REQ-DETECTION - Detect @req marker in fallback text window
127
- // @req REQ-REQUIRE-ACCEPTS-IMPLEMENTS - Detect @implements marker in fallback text window
127
+ // @req REQ-REQUIRE-ACCEPTS-IMPLEMENTS - Detect @supports marker in fallback text window
128
128
  if (typeof textBefore === "string" &&
129
- (textBefore.includes("@req") || textBefore.includes("@implements"))) {
129
+ (textBefore.includes("@req") || textBefore.includes("@supports"))) {
130
130
  return true;
131
131
  }
132
132
  }
@@ -140,11 +140,11 @@ function fallbackTextBeforeHasReq(sourceCode, node) {
140
140
  }
141
141
  /**
142
142
  * Helper to determine whether a JSDoc or any nearby comments contain a requirement annotation.
143
- * Treats both @req and @implements annotations as evidence of requirement coverage.
143
+ * Treats both @req and @supports annotations as evidence of requirement coverage.
144
144
  * @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
145
145
  * @story docs/stories/010.2-DEV-MULTI-STORY-SUPPORT.story.md
146
146
  * @req REQ-ANNOTATION-REQ-DETECTION - Determine presence of @req annotation
147
- * @req REQ-REQUIRE-ACCEPTS-IMPLEMENTS - Accept @implements as requirement coverage
147
+ * @req REQ-REQUIRE-ACCEPTS-IMPLEMENTS - Accept @supports as requirement coverage
148
148
  */
149
149
  function hasReqAnnotation(jsdoc, comments, context, node) {
150
150
  try {
@@ -154,7 +154,7 @@ function hasReqAnnotation(jsdoc, comments, context, node) {
154
154
  // Prefer robust, location-based heuristics when sourceCode and node are available.
155
155
  // @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
156
156
  // @req REQ-ANNOTATION-REQ-DETECTION - Use multiple heuristics to detect @req markers around the node
157
- // @req REQ-REQUIRE-ACCEPTS-IMPLEMENTS - Use multiple heuristics to detect @implements markers around the node
157
+ // @req REQ-REQUIRE-ACCEPTS-IMPLEMENTS - Use multiple heuristics to detect @supports markers around the node
158
158
  if (sourceCode && node) {
159
159
  if (linesBeforeHasReq(sourceCode, node) ||
160
160
  parentChainHasReq(sourceCode, node) ||
@@ -168,13 +168,13 @@ function hasReqAnnotation(jsdoc, comments, context, node) {
168
168
  // @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
169
169
  // @req REQ-ANNOTATION-REQ-DETECTION - Fail gracefully when advanced detection heuristics throw
170
170
  }
171
- // BRANCH requirement detection on JSDoc or comments, accepting both @req and @implements.
171
+ // BRANCH requirement detection on JSDoc or comments, accepting both @req and @supports.
172
172
  // @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
173
173
  // @story docs/stories/010.2-DEV-MULTI-STORY-SUPPORT.story.md
174
174
  // @req REQ-ANNOTATION-REQ-DETECTION
175
175
  // @req REQ-REQUIRE-ACCEPTS-IMPLEMENTS
176
176
  return ((jsdoc &&
177
177
  typeof jsdoc.value === "string" &&
178
- (jsdoc.value.includes("@req") || jsdoc.value.includes("@implements"))) ||
178
+ (jsdoc.value.includes("@req") || jsdoc.value.includes("@supports"))) ||
179
179
  comments.some(commentContainsReq));
180
180
  }
@@ -41,39 +41,39 @@ Object.defineProperty(exports, "__esModule", { value: true });
41
41
  */
42
42
  const fs = __importStar(require("fs"));
43
43
  const path = __importStar(require("path"));
44
- const os = __importStar(require("os"));
44
+ const temp_dir_helpers_1 = require("../utils/temp-dir-helpers");
45
45
  const batch_1 = require("../../src/maintenance/batch");
46
46
  describe("batchUpdateAnnotations (Story 009.0-DEV-MAINTENANCE-TOOLS)", () => {
47
- let tmpDir;
47
+ let temp;
48
48
  beforeAll(() => {
49
- tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "batch-test-"));
49
+ temp = (0, temp_dir_helpers_1.createTempDir)("batch-test-");
50
50
  });
51
51
  afterAll(() => {
52
- fs.rmSync(tmpDir, { recursive: true, force: true });
52
+ temp.cleanup();
53
53
  });
54
54
  it("[REQ-MAINT-BATCH] should return 0 when no mappings applied", () => {
55
- const count = (0, batch_1.batchUpdateAnnotations)(tmpDir, []);
55
+ const count = (0, batch_1.batchUpdateAnnotations)(temp.dir, []);
56
56
  expect(count).toBe(0);
57
57
  });
58
58
  });
59
59
  describe("verifyAnnotations (Story 009.0-DEV-MAINTENANCE-TOOLS)", () => {
60
- let tmpDir;
60
+ let temp;
61
61
  beforeAll(() => {
62
- tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "verify-test-"));
62
+ temp = (0, temp_dir_helpers_1.createTempDir)("verify-test-");
63
63
  const tsContent = `
64
64
  /**
65
65
  * Tests for: my-story.story.md
66
66
  * @story my-story.story.md
67
67
  */
68
68
  `;
69
- fs.writeFileSync(path.join(tmpDir, "test.ts"), tsContent);
70
- fs.writeFileSync(path.join(tmpDir, "my-story.story.md"), "# Dummy Story");
69
+ fs.writeFileSync(path.join(temp.dir, "test.ts"), tsContent);
70
+ fs.writeFileSync(path.join(temp.dir, "my-story.story.md"), "# Dummy Story");
71
71
  });
72
72
  afterAll(() => {
73
- fs.rmSync(tmpDir, { recursive: true, force: true });
73
+ temp.cleanup();
74
74
  });
75
75
  it("[REQ-MAINT-VERIFY] should return true when annotations are valid", () => {
76
- const valid = (0, batch_1.verifyAnnotations)(tmpDir);
76
+ const valid = (0, batch_1.verifyAnnotations)(temp.dir);
77
77
  expect(valid).toBe(true);
78
78
  });
79
79
  });