eslint-plugin-traceability 1.11.1 → 1.11.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 (46) hide show
  1. package/CHANGELOG.md +2 -2
  2. package/README.md +1 -1
  3. package/lib/src/index.d.ts +12 -1
  4. package/lib/src/index.js +43 -6
  5. package/lib/src/maintenance/commands.js +2 -3
  6. package/lib/src/maintenance/update.js +1 -14
  7. package/lib/src/rules/helpers/require-story-core.d.ts +12 -4
  8. package/lib/src/rules/helpers/require-story-core.js +59 -30
  9. package/lib/src/rules/helpers/require-story-helpers.d.ts +7 -41
  10. package/lib/src/rules/helpers/require-story-helpers.js +13 -70
  11. package/lib/src/rules/helpers/valid-annotation-format-internal.d.ts +12 -13
  12. package/lib/src/rules/helpers/valid-annotation-format-internal.js +21 -16
  13. package/lib/src/rules/helpers/valid-annotation-format-validators.d.ts +29 -3
  14. package/lib/src/rules/helpers/valid-annotation-format-validators.js +29 -3
  15. package/lib/src/rules/helpers/valid-annotation-utils.d.ts +3 -3
  16. package/lib/src/rules/helpers/valid-annotation-utils.js +10 -10
  17. package/lib/src/rules/helpers/valid-req-reference-helpers.d.ts +11 -0
  18. package/lib/src/rules/helpers/valid-req-reference-helpers.js +362 -0
  19. package/lib/src/rules/prefer-implements-annotation.js +7 -7
  20. package/lib/src/rules/require-story-annotation.d.ts +2 -0
  21. package/lib/src/rules/require-story-annotation.js +1 -1
  22. package/lib/src/rules/valid-req-reference.d.ts +4 -0
  23. package/lib/src/rules/valid-req-reference.js +5 -349
  24. package/lib/src/rules/valid-story-reference.d.ts +1 -1
  25. package/lib/src/rules/valid-story-reference.js +17 -10
  26. package/lib/src/utils/branch-annotation-helpers.d.ts +2 -2
  27. package/lib/src/utils/branch-annotation-helpers.js +4 -4
  28. package/lib/tests/cli-error-handling.test.js +1 -1
  29. package/lib/tests/config/eslint-config-validation.test.js +73 -0
  30. package/lib/tests/fixtures/stale/example.js +1 -1
  31. package/lib/tests/fixtures/update/example.js +1 -1
  32. package/lib/tests/integration/dogfooding-validation.test.d.ts +1 -0
  33. package/lib/tests/integration/dogfooding-validation.test.js +94 -0
  34. package/lib/tests/maintenance/cli.test.js +37 -0
  35. package/lib/tests/maintenance/detect-isolated.test.js +5 -5
  36. package/lib/tests/perf/maintenance-cli-large-workspace.test.js +18 -0
  37. package/lib/tests/perf/require-branch-annotation-large-file.test.d.ts +1 -0
  38. package/lib/tests/perf/require-branch-annotation-large-file.test.js +67 -0
  39. package/lib/tests/plugin-setup.test.js +12 -1
  40. package/lib/tests/rules/require-branch-annotation.test.js +33 -1
  41. package/lib/tests/rules/valid-annotation-format-internal.test.d.ts +8 -0
  42. package/lib/tests/rules/valid-annotation-format-internal.test.js +47 -0
  43. package/package.json +2 -2
  44. package/user-docs/api-reference.md +5 -5
  45. package/user-docs/examples.md +2 -1
  46. package/user-docs/migration-guide.md +2 -2
@@ -23,38 +23,34 @@ const require_story_core_1 = require("./require-story-core");
23
23
  Object.defineProperty(exports, "DEFAULT_SCOPE", { enumerable: true, get: function () { return require_story_core_1.DEFAULT_SCOPE; } });
24
24
  Object.defineProperty(exports, "EXPORT_PRIORITY_VALUES", { enumerable: true, get: function () { return require_story_core_1.EXPORT_PRIORITY_VALUES; } });
25
25
  Object.defineProperty(exports, "STORY_PATH", { enumerable: true, get: function () { return require_story_core_1.STORY_PATH; } });
26
- /**
27
- * Derive the annotation template, optionally using an override.
28
- * When override is a non-empty string, its trimmed value is used.
29
- * Otherwise, the default template is returned.
30
- */
31
26
  function getAnnotationTemplate(override) {
32
27
  if (typeof override === "string" && override.trim().length > 0) {
33
28
  return override.trim();
34
29
  }
35
30
  return `/** @story ${require_story_core_1.STORY_PATH} */`;
36
31
  }
37
- /**
38
- * Determine whether auto-fix should be applied.
39
- * Explicit false disables auto-fix; all other values enable it.
40
- */
41
32
  function shouldApplyAutoFix(autoFix) {
42
33
  if (autoFix === false) {
43
34
  return false;
44
35
  }
45
36
  return true;
46
37
  }
38
+ /**
39
+ * Build the effective annotation template and autofix toggle
40
+ * from the provided report options.
41
+ */
42
+ function buildTemplateConfig(options) {
43
+ const effectiveTemplate = getAnnotationTemplate(options?.annotationTemplateOverride);
44
+ const allowFix = shouldApplyAutoFix(options?.autoFixToggle);
45
+ return { effectiveTemplate, allowFix };
46
+ }
47
47
  /**
48
48
  * Determine if a node is in an export declaration
49
49
  * @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
50
50
  * @req REQ-ANNOTATION-REQUIRED - Check node ancestry to find export declarations
51
- * @param {any} node - AST node to check for export ancestry
52
- * @returns {boolean} true if node is within an export declaration
53
51
  */
54
52
  function isExportedNode(node) {
55
53
  let p = node.parent;
56
- // @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
57
- // @req REQ-ANNOTATION-REQUIRED - Walk parent chain to find Export declarations
58
54
  while (p) {
59
55
  if (p.type === "ExportNamedDeclaration" ||
60
56
  p.type === "ExportDefaultDeclaration") {
@@ -68,9 +64,6 @@ function isExportedNode(node) {
68
64
  * Check whether the JSDoc associated with node contains @story
69
65
  * @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
70
66
  * @req REQ-ANNOTATION-REQUIRED - Extract JSDoc based detection into helper
71
- * @param {any} sourceCode - ESLint sourceCode object
72
- * @param {any} node - AST node to inspect
73
- * @returns {boolean} true if JSDoc contains @story
74
67
  */
75
68
  function jsdocHasStory(sourceCode, node) {
76
69
  if (typeof sourceCode?.getJSDocComment !== "function") {
@@ -85,9 +78,6 @@ function jsdocHasStory(sourceCode, node) {
85
78
  * Check whether comments returned by sourceCode.getCommentsBefore contain @story
86
79
  * @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
87
80
  * @req REQ-ANNOTATION-REQUIRED - Extract comment-before detection into helper
88
- * @param {any} sourceCode - ESLint sourceCode object
89
- * @param {any} node - AST node to inspect
90
- * @returns {boolean} true if any preceding comment contains @story
91
81
  */
92
82
  function commentsBeforeHasStory(sourceCode, node) {
93
83
  if (typeof sourceCode?.getCommentsBefore !== "function") {
@@ -101,8 +91,6 @@ function commentsBeforeHasStory(sourceCode, node) {
101
91
  * Check whether leadingComments attached to the node contain @story
102
92
  * @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
103
93
  * @req REQ-ANNOTATION-REQUIRED - Extract leadingComments detection into helper
104
- * @param {any} node - AST node to inspect
105
- * @returns {boolean} true if any leading comment contains @story
106
94
  */
107
95
  function leadingCommentsHasStory(node) {
108
96
  const leadingComments = (node && node.leadingComments) || [];
@@ -114,9 +102,6 @@ function leadingCommentsHasStory(node) {
114
102
  * Consolidates a variety of heuristics through smaller helpers.
115
103
  * @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
116
104
  * @req REQ-ANNOTATION-REQUIRED - Detect existing story annotations in JSDoc or comments
117
- * @param {any} sourceCode - ESLint sourceCode object
118
- * @param {any} node - AST node to inspect for existing annotations
119
- * @returns {boolean} true if @story annotation already present
120
105
  */
121
106
  function hasStoryAnnotation(sourceCode, node) {
122
107
  try {
@@ -139,8 +124,10 @@ function hasStoryAnnotation(sourceCode, node) {
139
124
  return true;
140
125
  }
141
126
  }
142
- catch {
143
- /* noop */
127
+ catch (error) {
128
+ if (process.env.TRACEABILITY_DEBUG === "1") {
129
+ console.error("[traceability] hasStoryAnnotation failed for node", error?.message ?? error);
130
+ }
144
131
  }
145
132
  return false;
146
133
  }
@@ -148,9 +135,6 @@ function hasStoryAnnotation(sourceCode, node) {
148
135
  * Determine AST node where annotation should be inserted
149
136
  * @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
150
137
  * @req REQ-ANNOTATION-REQUIRED - Determine correct insertion target for annotation
151
- * @param {any} sourceCode - ESLint sourceCode object (unused but kept for parity)
152
- * @param {any} node - function-like AST node to resolve target for
153
- * @returns {any} AST node that should receive the annotation
154
138
  */
155
139
  function resolveTargetNode(sourceCode, node) {
156
140
  if (node.type === "TSMethodSignature") {
@@ -178,11 +162,8 @@ function resolveTargetNode(sourceCode, node) {
178
162
  }
179
163
  /**
180
164
  * Extract a direct Identifier name when available on the given node.
181
- * This focuses only on plain Identifier nodes and ignores container shapes.
182
165
  * @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
183
166
  * @req REQ-ANNOTATION-REQUIRED - Extract direct Identifier-based names from nodes
184
- * @param {any} node - AST node to inspect
185
- * @returns {string | null} identifier name or null when not applicable
186
167
  */
187
168
  function getDirectIdentifierName(node) {
188
169
  if (node &&
@@ -195,11 +176,8 @@ function getDirectIdentifierName(node) {
195
176
  }
196
177
  /**
197
178
  * Normalize container nodes that expose names via id/key properties.
198
- * Supports common function and method containers, including literal keys.
199
179
  * @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
200
180
  * @req REQ-ANNOTATION-REQUIRED - Normalize container id/key-based names into a single helper
201
- * @param {any} node - AST node that may contain id/key name information
202
- * @returns {string | null} resolved container name or null when unavailable
203
181
  */
204
182
  function getContainerKeyOrIdName(node) {
205
183
  if (!node) {
@@ -226,11 +204,8 @@ function getContainerKeyOrIdName(node) {
226
204
  }
227
205
  /**
228
206
  * Small utility to walk the node and its parents to extract an Identifier or key name.
229
- * Walks up the parent chain and inspects common properties (id, key, name, Identifier nodes).
230
207
  * @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
231
208
  * @req REQ-ANNOTATION-REQUIRED - Walk node and parents to find Identifier/Key name
232
- * @param {any} node - AST node to extract a name from
233
- * @returns {string} extracted name or "(anonymous)" when no name found
234
209
  */
235
210
  function extractName(node) {
236
211
  let current = node;
@@ -251,15 +226,6 @@ function extractName(node) {
251
226
  }
252
227
  return "(anonymous)";
253
228
  }
254
- /**
255
- * Check if this node is within scope and matches exportPriority
256
- * @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
257
- * @req REQ-ANNOTATION-REQUIRED - Determine whether a node should be processed by rule
258
- * @param {any} node - AST node to evaluate
259
- * @param {string[]} scope - allowed node types
260
- * @param {string} [exportPriority='all'] - 'all' | 'exported' | 'non-exported' (default: 'all')
261
- * @returns {boolean} whether node should be processed
262
- */
263
229
  function shouldProcessNode(node, scope, exportPriority = "all") {
264
230
  if (!scope.includes(node.type)) {
265
231
  return false;
@@ -275,11 +241,8 @@ function shouldProcessNode(node, scope, exportPriority = "all") {
275
241
  }
276
242
  /**
277
243
  * Resolve the effective function name to report for a node.
278
- * Normalizes id/key handling before delegating to extractName.
279
244
  * @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
280
245
  * @req REQ-ANNOTATION-REQUIRED - Centralize reported function name resolution
281
- * @param {any} node - AST node used to derive the function name
282
- * @returns {string} resolved function name
283
246
  */
284
247
  function getReportedFunctionName(node) {
285
248
  const candidate = node && (node.id || node.key) ? node.id || node.key : node;
@@ -287,11 +250,8 @@ function getReportedFunctionName(node) {
287
250
  }
288
251
  /**
289
252
  * Determine the most appropriate AST node to anchor error location for a report.
290
- * Prefers Identifier nodes from id/key properties when available.
291
253
  * @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
292
254
  * @req REQ-ANNOTATION-REQUIRED - Normalize name node selection for error reporting
293
- * @param {any} node - AST node used for error anchoring
294
- * @returns {any} node to use as the report location
295
255
  */
296
256
  function getNameNodeForReport(node) {
297
257
  if (node?.id?.type === "Identifier") {
@@ -307,27 +267,10 @@ function getNameNodeForReport(node) {
307
267
  * respecting an explicitly passed target when provided.
308
268
  * @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
309
269
  * @req REQ-ANNOTATION-REQUIRED - Centralize annotation target node resolution
310
- * @param {any} sourceCode - ESLint sourceCode object
311
- * @param {any} node - original function-like AST node
312
- * @param {any} passedTarget - optional explicit annotation target
313
- * @returns {any} node that should receive the annotation
314
270
  */
315
271
  function resolveAnnotationTargetNode(sourceCode, node, passedTarget) {
316
272
  return passedTarget ?? resolveTargetNode(sourceCode, node);
317
273
  }
318
- /**
319
- * Build the effective annotation template and autofix toggle
320
- * from the provided report options.
321
- * @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
322
- * @req REQ-ANNOTATION-REQUIRED - Normalize template and autofix configuration
323
- * @param {ReportOptions} [options] - optional report configuration
324
- * @returns {{ effectiveTemplate: string; allowFix: boolean }} template and autofix flags
325
- */
326
- function buildTemplateConfig(options) {
327
- const effectiveTemplate = getAnnotationTemplate(options?.annotationTemplateOverride);
328
- const allowFix = shouldApplyAutoFix(options?.autoFixToggle);
329
- return { effectiveTemplate, allowFix };
330
- }
331
274
  function reportMissing(context, sourceCode, config) {
332
275
  (0, require_story_core_1.coreReportMissing)({
333
276
  hasStoryAnnotation,
@@ -1,14 +1,7 @@
1
1
  /**
2
2
  * Internal helpers and types for the valid-annotation-format rule.
3
3
  *
4
- * @story docs/stories/005.0-DEV-ANNOTATION-VALIDATION.story.md
5
- * @story docs/stories/008.0-DEV-AUTO-FIX.story.md
6
- * @story docs/stories/010.2-DEV-MULTI-STORY-SUPPORT.story.md
7
- * @req REQ-MULTILINE-SUPPORT - Handle annotations split across multiple lines
8
- * @req REQ-FLEXIBLE-PARSING - Support reasonable variations in whitespace and formatting
9
- * @req REQ-AUTOFIX-FORMAT - Provide safe, minimal automatic fixes for common format issues
10
- * @req REQ-SUPPORTS-PARSE - Parse @supports annotations without affecting @story/@req
11
- * @req REQ-MIXED-SUPPORT - Support mixed @story/@req/@implements usage in comments
4
+ * @supports docs/stories/024.0-DEV-IGNORE-INLINE-CODE-REFS.story.md REQ-IGNORE-INLINE-CODE REQ-PRESERVE-BOUNDARIES REQ-CENTRALIZED-FILTER
12
5
  */
13
6
  /**
14
7
  * Pending annotation state tracked while iterating through comment lines.
@@ -21,8 +14,10 @@ export interface PendingAnnotation {
21
14
  /**
22
15
  * Normalize a raw comment line to make annotation parsing more robust.
23
16
  *
24
- * This function trims whitespace, keeps any annotation tags that appear
25
- * later in the line, and supports common JSDoc styles such as leading "*".
17
+ * This function trims whitespace, strips any inline code spans wrapped in
18
+ * backticks (replacing them with spaces of equal length to preserve character
19
+ * boundaries), keeps any annotation tags that appear later in the line, and
20
+ * supports common JSDoc styles such as leading "*".
26
21
  *
27
22
  * It detects @story, @req, and @supports tags while preserving the rest
28
23
  * of the line for downstream logic.
@@ -34,8 +29,12 @@ export declare function normalizeCommentLine(rawLine: string): string;
34
29
  * This is used to distinguish regular JSDoc tags (e.g. @param, @returns) from
35
30
  * traceability-related annotations such as @story, @req, and @supports.
36
31
  *
37
- * @supports docs/stories/022.0-DEV-JSDOC-COEXISTENCE.story.md
38
- * @req REQ-JSDOC-BOUNDARY-DETECTION
39
- * @req REQ-JSDOC-TAG-COEXISTENCE
32
+ * Supports coexistence with JSDoc by:
33
+ * - Detecting boundaries between traceability tags and other tags
34
+ * - Allowing regular JSDoc tags to live alongside traceability annotations
35
+ *
36
+ * Related requirements:
37
+ * - REQ-JSDOC-BOUNDARY-DETECTION
38
+ * - REQ-JSDOC-TAG-COEXISTENCE
40
39
  */
41
40
  export declare function isNonTraceabilityJSDocTagLine(normalized: string): boolean;
@@ -2,14 +2,7 @@
2
2
  /**
3
3
  * Internal helpers and types for the valid-annotation-format rule.
4
4
  *
5
- * @story docs/stories/005.0-DEV-ANNOTATION-VALIDATION.story.md
6
- * @story docs/stories/008.0-DEV-AUTO-FIX.story.md
7
- * @story docs/stories/010.2-DEV-MULTI-STORY-SUPPORT.story.md
8
- * @req REQ-MULTILINE-SUPPORT - Handle annotations split across multiple lines
9
- * @req REQ-FLEXIBLE-PARSING - Support reasonable variations in whitespace and formatting
10
- * @req REQ-AUTOFIX-FORMAT - Provide safe, minimal automatic fixes for common format issues
11
- * @req REQ-SUPPORTS-PARSE - Parse @supports annotations without affecting @story/@req
12
- * @req REQ-MIXED-SUPPORT - Support mixed @story/@req/@implements usage in comments
5
+ * @supports docs/stories/024.0-DEV-IGNORE-INLINE-CODE-REFS.story.md REQ-IGNORE-INLINE-CODE REQ-PRESERVE-BOUNDARIES REQ-CENTRALIZED-FILTER
13
6
  */
14
7
  Object.defineProperty(exports, "__esModule", { value: true });
15
8
  exports.normalizeCommentLine = normalizeCommentLine;
@@ -17,8 +10,10 @@ exports.isNonTraceabilityJSDocTagLine = isNonTraceabilityJSDocTagLine;
17
10
  /**
18
11
  * Normalize a raw comment line to make annotation parsing more robust.
19
12
  *
20
- * This function trims whitespace, keeps any annotation tags that appear
21
- * later in the line, and supports common JSDoc styles such as leading "*".
13
+ * This function trims whitespace, strips any inline code spans wrapped in
14
+ * backticks (replacing them with spaces of equal length to preserve character
15
+ * boundaries), keeps any annotation tags that appear later in the line, and
16
+ * supports common JSDoc styles such as leading "*".
22
17
  *
23
18
  * It detects @story, @req, and @supports tags while preserving the rest
24
19
  * of the line for downstream logic.
@@ -28,12 +23,18 @@ function normalizeCommentLine(rawLine) {
28
23
  if (!trimmed) {
29
24
  return "";
30
25
  }
31
- const annotationMatch = trimmed.match(/@story\b|@req\b|@supports\b/);
26
+ // @supports docs/stories/024.0-DEV-IGNORE-INLINE-CODE-REFS.story.md REQ-IGNORE-INLINE-CODE REQ-PRESERVE-BOUNDARIES REQ-CENTRALIZED-FILTER
27
+ // Strip backtick-wrapped content while preserving character positions by
28
+ // replacing each matched segment with spaces of the same length.
29
+ // This ensures annotations that appear outside code spans are still
30
+ // detected at their original indices.
31
+ const filtered = trimmed.replace(/`[^`]*`/g, (match) => " ".repeat(match.length));
32
+ const annotationMatch = filtered.match(/@story\b|@req\b|@supports\b/);
32
33
  if (!annotationMatch || annotationMatch.index === undefined) {
33
- const withoutLeadingStar = trimmed.replace(/^\*\s?/, "");
34
+ const withoutLeadingStar = filtered.replace(/^\*\s?/, "");
34
35
  return withoutLeadingStar;
35
36
  }
36
- return trimmed.slice(annotationMatch.index);
37
+ return filtered.slice(annotationMatch.index);
37
38
  }
38
39
  /**
39
40
  * Detect whether a normalized comment line starts with a non-traceability JSDoc tag.
@@ -41,9 +42,13 @@ function normalizeCommentLine(rawLine) {
41
42
  * This is used to distinguish regular JSDoc tags (e.g. @param, @returns) from
42
43
  * traceability-related annotations such as @story, @req, and @supports.
43
44
  *
44
- * @supports docs/stories/022.0-DEV-JSDOC-COEXISTENCE.story.md
45
- * @req REQ-JSDOC-BOUNDARY-DETECTION
46
- * @req REQ-JSDOC-TAG-COEXISTENCE
45
+ * Supports coexistence with JSDoc by:
46
+ * - Detecting boundaries between traceability tags and other tags
47
+ * - Allowing regular JSDoc tags to live alongside traceability annotations
48
+ *
49
+ * Related requirements:
50
+ * - REQ-JSDOC-BOUNDARY-DETECTION
51
+ * - REQ-JSDOC-TAG-COEXISTENCE
47
52
  */
48
53
  function isNonTraceabilityJSDocTagLine(normalized) {
49
54
  const trimmed = normalized.trimStart();
@@ -2,9 +2,15 @@
2
2
  * Validators and helper functions for the valid-annotation-format rule.
3
3
  *
4
4
  * This module contains the core validation logic that was originally
5
- * embedded in src/rules/valid-annotation-format.ts. It is extracted
6
- * here to keep the main rule module smaller and easier to read while
7
- * preserving existing behavior.
5
+ * embedded in src/rules/valid-annotation-format.ts. The logic is extracted
6
+ * into this helper to keep the main rule implementation smaller and easier
7
+ * to read while still preserving all existing behavior.
8
+ *
9
+ * The implementation in this module supports:
10
+ * - validation of @story annotations
11
+ * - validation of @req annotations
12
+ * - validation of @implements/@supports-style annotations
13
+ * - safe, minimal auto-fixes for certain invalid formats
8
14
  *
9
15
  * @story docs/stories/005.0-DEV-ANNOTATION-VALIDATION.story.md
10
16
  * @story docs/stories/007.0-DEV-ERROR-REPORTING.story.md
@@ -29,6 +35,8 @@ import type { PendingAnnotation } from "./valid-annotation-format-internal";
29
35
  /**
30
36
  * Report an invalid @story annotation without applying a fix.
31
37
  *
38
+ * The invalid @story annotation is detected and reported but left unchanged.
39
+ *
32
40
  * @story docs/stories/005.0-DEV-ANNOTATION-VALIDATION.story.md
33
41
  * @story docs/stories/008.0-DEV-AUTO-FIX.story.md
34
42
  * @story docs/stories/010.2-DEV-MULTI-STORY-SUPPORT.story.md
@@ -55,6 +63,9 @@ export declare function createStoryFix(context: any, comment: any, fixed: string
55
63
  * for common path suffix issues by locating and replacing the path text
56
64
  * within the original comment.
57
65
  *
66
+ * Reporting includes both the original invalid value and, where applicable,
67
+ * a suggested corrected story path that only adjusts the suffix.
68
+ *
58
69
  * @story docs/stories/005.0-DEV-ANNOTATION-VALIDATION.story.md
59
70
  * @story docs/stories/008.0-DEV-AUTO-FIX.story.md
60
71
  * @story docs/stories/010.2-DEV-MULTI-STORY-SUPPORT.story.md
@@ -68,6 +79,12 @@ export declare function reportInvalidStoryFormatWithFix(context: any, comment: a
68
79
  * Validate a @story annotation value and report detailed errors when needed.
69
80
  * Where safe and unambiguous, apply an automatic fix for missing suffixes.
70
81
  *
82
+ * Processing of @story values includes:
83
+ * - trimming whitespace,
84
+ * - collapsing multi-line text,
85
+ * - matching against the configured story regex,
86
+ * - and attempting a conservative suffix-only correction when possible.
87
+ *
71
88
  * @story docs/stories/005.0-DEV-ANNOTATION-VALIDATION.story.md
72
89
  * @story docs/stories/008.0-DEV-AUTO-FIX.story.md
73
90
  * @story docs/stories/010.2-DEV-MULTI-STORY-SUPPORT.story.md
@@ -82,6 +99,11 @@ export declare function validateStoryAnnotation(context: any, comment: any, rawV
82
99
  /**
83
100
  * Validate a @req annotation value and report detailed errors when needed.
84
101
  *
102
+ * This behavior covers:
103
+ * - detecting missing identifiers,
104
+ * - collapsing multi-line requirement identifiers,
105
+ * - and validating the final identifier against the configured regex.
106
+ *
85
107
  * @story docs/stories/005.0-DEV-ANNOTATION-VALIDATION.story.md
86
108
  * @story docs/stories/008.0-DEV-AUTO-FIX.story.md
87
109
  * @story docs/stories/010.2-DEV-MULTI-STORY-SUPPORT.story.md
@@ -115,6 +137,10 @@ export declare function validateImplementsAnnotation(context: any, comment: any,
115
137
  /**
116
138
  * Finalize and validate the currently pending annotation, if any.
117
139
  *
140
+ * Pending annotation state is produced by earlier parsing of multi-line
141
+ * comments. This function dispatches that accumulated value to the
142
+ * appropriate validator and then clears the pending state.
143
+ *
118
144
  * @story docs/stories/005.0-DEV-ANNOTATION-VALIDATION.story.md
119
145
  * @story docs/stories/008.0-DEV-AUTO-FIX.story.md
120
146
  * @story docs/stories/010.2-DEV-MULTI-STORY-SUPPORT.story.md
@@ -3,9 +3,15 @@
3
3
  * Validators and helper functions for the valid-annotation-format rule.
4
4
  *
5
5
  * This module contains the core validation logic that was originally
6
- * embedded in src/rules/valid-annotation-format.ts. It is extracted
7
- * here to keep the main rule module smaller and easier to read while
8
- * preserving existing behavior.
6
+ * embedded in src/rules/valid-annotation-format.ts. The logic is extracted
7
+ * into this helper to keep the main rule implementation smaller and easier
8
+ * to read while still preserving all existing behavior.
9
+ *
10
+ * The implementation in this module supports:
11
+ * - validation of @story annotations
12
+ * - validation of @req annotations
13
+ * - validation of @implements/@supports-style annotations
14
+ * - safe, minimal auto-fixes for certain invalid formats
9
15
  *
10
16
  * @story docs/stories/005.0-DEV-ANNOTATION-VALIDATION.story.md
11
17
  * @story docs/stories/007.0-DEV-ERROR-REPORTING.story.md
@@ -39,6 +45,8 @@ const valid_annotation_options_1 = require("./valid-annotation-options");
39
45
  /**
40
46
  * Report an invalid @story annotation without applying a fix.
41
47
  *
48
+ * The invalid @story annotation is detected and reported but left unchanged.
49
+ *
42
50
  * @story docs/stories/005.0-DEV-ANNOTATION-VALIDATION.story.md
43
51
  * @story docs/stories/008.0-DEV-AUTO-FIX.story.md
44
52
  * @story docs/stories/010.2-DEV-MULTI-STORY-SUPPORT.story.md
@@ -99,6 +107,9 @@ function createStoryFix(context, comment, fixed) {
99
107
  * for common path suffix issues by locating and replacing the path text
100
108
  * within the original comment.
101
109
  *
110
+ * Reporting includes both the original invalid value and, where applicable,
111
+ * a suggested corrected story path that only adjusts the suffix.
112
+ *
102
113
  * @story docs/stories/005.0-DEV-ANNOTATION-VALIDATION.story.md
103
114
  * @story docs/stories/008.0-DEV-AUTO-FIX.story.md
104
115
  * @story docs/stories/010.2-DEV-MULTI-STORY-SUPPORT.story.md
@@ -128,6 +139,12 @@ function reportInvalidStoryFormatWithFix(context, comment, collapsed, fixed) {
128
139
  * Validate a @story annotation value and report detailed errors when needed.
129
140
  * Where safe and unambiguous, apply an automatic fix for missing suffixes.
130
141
  *
142
+ * Processing of @story values includes:
143
+ * - trimming whitespace,
144
+ * - collapsing multi-line text,
145
+ * - matching against the configured story regex,
146
+ * - and attempting a conservative suffix-only correction when possible.
147
+ *
131
148
  * @story docs/stories/005.0-DEV-ANNOTATION-VALIDATION.story.md
132
149
  * @story docs/stories/008.0-DEV-AUTO-FIX.story.md
133
150
  * @story docs/stories/010.2-DEV-MULTI-STORY-SUPPORT.story.md
@@ -179,6 +196,11 @@ function validateStoryAnnotation(context, comment, rawValue, options) {
179
196
  /**
180
197
  * Validate a @req annotation value and report detailed errors when needed.
181
198
  *
199
+ * This behavior covers:
200
+ * - detecting missing identifiers,
201
+ * - collapsing multi-line requirement identifiers,
202
+ * - and validating the final identifier against the configured regex.
203
+ *
182
204
  * @story docs/stories/005.0-DEV-ANNOTATION-VALIDATION.story.md
183
205
  * @story docs/stories/008.0-DEV-AUTO-FIX.story.md
184
206
  * @story docs/stories/010.2-DEV-MULTI-STORY-SUPPORT.story.md
@@ -247,6 +269,10 @@ function validateImplementsAnnotation(context, comment, rawValue, options) {
247
269
  /**
248
270
  * Finalize and validate the currently pending annotation, if any.
249
271
  *
272
+ * Pending annotation state is produced by earlier parsing of multi-line
273
+ * comments. This function dispatches that accumulated value to the
274
+ * appropriate validator and then clears the pending state.
275
+ *
250
276
  * @story docs/stories/005.0-DEV-ANNOTATION-VALIDATION.story.md
251
277
  * @story docs/stories/008.0-DEV-AUTO-FIX.story.md
252
278
  * @story docs/stories/010.2-DEV-MULTI-STORY-SUPPORT.story.md
@@ -44,7 +44,7 @@ export declare function collapseAnnotationValue(value: string): string;
44
44
  *
45
45
  * @story docs/stories/005.0-DEV-ANNOTATION-VALIDATION.story.md
46
46
  * @story docs/stories/008.0-DEV-AUTO-FIX.story.md
47
- * @story docs/stories/010.1-REQ-STORY-PATH-STRICTNESS.story.md
47
+ * @story docs/stories/010.1-DEV-CONFIGURABLE-PATTERNS.story.md
48
48
  * @story docs/stories/010.2-REQ-STORY-PATH-AUTOFIX.story.md
49
49
  * @req REQ-AUTOFIX-FORMAT - Provide safe, minimal automatic fixes for common format issues
50
50
  * @req REQ-AUTOFIX-SAFE - Auto-fix must be conservative and never broaden the referenced path
@@ -56,7 +56,7 @@ export declare function getFixedStoryPath(original: string): string | null;
56
56
  *
57
57
  * @story docs/stories/005.0-DEV-ANNOTATION-VALIDATION.story.md
58
58
  * @story docs/stories/008.0-DEV-AUTO-FIX.story.md
59
- * @story docs/stories/010.1-REQ-STORY-PATH-STRICTNESS.story.md
59
+ * @story docs/stories/010.1-DEV-CONFIGURABLE-PATTERNS.story.md
60
60
  * @req REQ-ERROR-SPECIFICITY - Provide specific error messages for different format violations
61
61
  * @req REQ-AUTOFIX-FORMAT - Provide safe, minimal automatic fixes for common format issues
62
62
  */
@@ -66,7 +66,7 @@ export declare function buildStoryErrorMessage(kind: "missing" | "invalid", valu
66
66
  *
67
67
  * @story docs/stories/005.0-DEV-ANNOTATION-VALIDATION.story.md
68
68
  * @story docs/stories/008.0-DEV-AUTO-FIX.story.md
69
- * @story docs/stories/010.1-REQ-STORY-PATH-STRICTNESS.story.md
69
+ * @story docs/stories/010.1-DEV-CONFIGURABLE-PATTERNS.story.md
70
70
  * @req REQ-ERROR-SPECIFICITY - Provide specific error messages for different format violations
71
71
  * @req REQ-AUTOFIX-FORMAT - Provide safe, minimal automatic fixes for common format issues
72
72
  */
@@ -54,19 +54,19 @@ function collapseAnnotationValue(value) {
54
54
  *
55
55
  * @story docs/stories/005.0-DEV-ANNOTATION-VALIDATION.story.md
56
56
  * @story docs/stories/008.0-DEV-AUTO-FIX.story.md
57
- * @story docs/stories/010.1-REQ-STORY-PATH-STRICTNESS.story.md
57
+ * @story docs/stories/010.1-DEV-CONFIGURABLE-PATTERNS.story.md
58
58
  * @story docs/stories/010.2-REQ-STORY-PATH-AUTOFIX.story.md
59
59
  * @req REQ-AUTOFIX-FORMAT - Provide safe, minimal automatic fixes for common format issues
60
60
  * @req REQ-AUTOFIX-SAFE - Auto-fix must be conservative and never broaden the referenced path
61
61
  * @req REQ-AUTOFIX-PRESERVE - Preserve surrounding formatting when normalizing story path suffixes
62
62
  */
63
63
  function getFixedStoryPath(original) {
64
- // @story docs/stories/010.1-REQ-STORY-PATH-STRICTNESS.story.md | REQ-AUTOFIX-SAFE - Reject auto-fix when the path contains ".." traversal segments to avoid broadening the reference.
64
+ // @story docs/stories/010.1-DEV-CONFIGURABLE-PATTERNS.story.md | REQ-AUTOFIX-SAFE - Reject auto-fix when the path contains ".." traversal segments to avoid broadening the reference.
65
65
  // @supports docs/stories/005.0-DEV-ANNOTATION-VALIDATION.story.md REQ-REQ-FORMAT REQ-ERROR-SPECIFICITY - Enforces correctness of the story identifier by rejecting paths that use unsafe traversal segments.
66
66
  if (original.includes("..")) {
67
67
  // @supports docs/stories/005.0-DEV-ANNOTATION-VALIDATION.story.md REQ-REQ-FORMAT
68
68
  // @supports docs/stories/008.0-DEV-AUTO-FIX.story.md REQ-AUTOFIX-SAFE
69
- // @supports docs/stories/010.1-REQ-STORY-PATH-STRICTNESS.story.md REQ-AUTOFIX-SAFE
69
+ // @supports docs/stories/010.1-DEV-CONFIGURABLE-PATTERNS.story.md REQ-AUTOFIX-SAFE
70
70
  return null;
71
71
  }
72
72
  // @story docs/stories/005.0-DEV-ANNOTATION-VALIDATION.story.md | REQ-AUTOFIX-FORMAT - Leave correctly formatted ".story.md" paths unchanged so diagnostics are not hidden by redundant fixes.
@@ -74,7 +74,7 @@ function getFixedStoryPath(original) {
74
74
  if (/\.story\.md$/.test(original)) {
75
75
  // @supports docs/stories/005.0-DEV-ANNOTATION-VALIDATION.story.md REQ-REQ-FORMAT
76
76
  // @supports docs/stories/008.0-DEV-AUTO-FIX.story.md REQ-AUTOFIX-FORMAT
77
- // @supports docs/stories/010.1-REQ-STORY-PATH-STRICTNESS.story.md REQ-AUTOFIX-FORMAT
77
+ // @supports docs/stories/010.1-DEV-CONFIGURABLE-PATTERNS.story.md REQ-AUTOFIX-FORMAT
78
78
  return null;
79
79
  }
80
80
  // @story docs/stories/008.0-DEV-AUTO-FIX.story.md | REQ-AUTOFIX-FORMAT REQ-AUTOFIX-PRESERVE - When ".story" is present but ".md" is missing, append only the extension without altering the base path.
@@ -105,7 +105,7 @@ function getFixedStoryPath(original) {
105
105
  *
106
106
  * @story docs/stories/005.0-DEV-ANNOTATION-VALIDATION.story.md
107
107
  * @story docs/stories/008.0-DEV-AUTO-FIX.story.md
108
- * @story docs/stories/010.1-REQ-STORY-PATH-STRICTNESS.story.md
108
+ * @story docs/stories/010.1-DEV-CONFIGURABLE-PATTERNS.story.md
109
109
  * @req REQ-ERROR-SPECIFICITY - Provide specific error messages for different format violations
110
110
  * @req REQ-AUTOFIX-FORMAT - Provide safe, minimal automatic fixes for common format issues
111
111
  */
@@ -115,11 +115,11 @@ function buildStoryErrorMessage(kind, value, options) {
115
115
  // @supports docs/stories/005.0-DEV-ANNOTATION-VALIDATION.story.md REQ-REQ-FORMAT REQ-ERROR-SPECIFICITY - Enforces presence of the story identifier by emitting a targeted message when the @story value is absent.
116
116
  if (kind === "missing") {
117
117
  // @supports docs/stories/005.0-DEV-ANNOTATION-VALIDATION.story.md REQ-ERROR-SPECIFICITY
118
- // @supports docs/stories/010.1-REQ-STORY-PATH-STRICTNESS.story.md REQ-ERROR-SPECIFICITY
118
+ // @supports docs/stories/010.1-DEV-CONFIGURABLE-PATTERNS.story.md REQ-ERROR-SPECIFICITY
119
119
  return `Missing story path for @story annotation. Expected a path like "${example}".`;
120
120
  }
121
121
  // @supports docs/stories/005.0-DEV-ANNOTATION-VALIDATION.story.md REQ-ERROR-SPECIFICITY
122
- // @supports docs/stories/010.1-REQ-STORY-PATH-STRICTNESS.story.md REQ-ERROR-SPECIFICITY
122
+ // @supports docs/stories/010.1-DEV-CONFIGURABLE-PATTERNS.story.md REQ-ERROR-SPECIFICITY
123
123
  return `Invalid story path "${value ?? ""}" for @story annotation. Expected a path like "${example}".`;
124
124
  }
125
125
  /**
@@ -127,7 +127,7 @@ function buildStoryErrorMessage(kind, value, options) {
127
127
  *
128
128
  * @story docs/stories/005.0-DEV-ANNOTATION-VALIDATION.story.md
129
129
  * @story docs/stories/008.0-DEV-AUTO-FIX.story.md
130
- * @story docs/stories/010.1-REQ-STORY-PATH-STRICTNESS.story.md
130
+ * @story docs/stories/010.1-DEV-CONFIGURABLE-PATTERNS.story.md
131
131
  * @req REQ-ERROR-SPECIFICITY - Provide specific error messages for different format violations
132
132
  * @req REQ-AUTOFIX-FORMAT - Provide safe, minimal automatic fixes for common format issues
133
133
  */
@@ -137,10 +137,10 @@ function buildReqErrorMessage(kind, value, options) {
137
137
  // @supports docs/stories/005.0-DEV-ANNOTATION-VALIDATION.story.md REQ-REQ-FORMAT REQ-ERROR-SPECIFICITY - Enforces presence of the requirement identifier by emitting a specific message when the @req value is missing.
138
138
  if (kind === "missing") {
139
139
  // @supports docs/stories/005.0-DEV-ANNOTATION-VALIDATION.story.md REQ-ERROR-SPECIFICITY
140
- // @supports docs/stories/010.1-REQ-STORY-PATH-STRICTNESS.story.md REQ-ERROR-SPECIFICITY
140
+ // @supports docs/stories/010.1-DEV-CONFIGURABLE-PATTERNS.story.md REQ-ERROR-SPECIFICITY
141
141
  return `Missing requirement ID for @req annotation. Expected an identifier like "${example}".`;
142
142
  }
143
143
  // @supports docs/stories/005.0-DEV-ANNOTATION-VALIDATION.story.md REQ-ERROR-SPECIFICITY
144
- // @supports docs/stories/010.1-REQ-STORY-PATH-STRICTNESS.story.md REQ-ERROR-SPECIFICITY
144
+ // @supports docs/stories/010.1-DEV-CONFIGURABLE-PATTERNS.story.md REQ-ERROR-SPECIFICITY
145
145
  return `Invalid requirement ID "${value ?? ""}" for @req annotation. Expected an identifier like "${example}" (uppercase letters, numbers, and dashes only).`;
146
146
  }
@@ -0,0 +1,11 @@
1
+ import type { Rule } from "eslint";
2
+ /**
3
+ * Factory used by the valid-req-reference rule to construct its Program
4
+ * visitor. Keeping this in a helper module allows the rule entrypoint
5
+ * itself to remain small and focused on meta configuration while the
6
+ * heavier deep-validation logic is encapsulated here.
7
+ *
8
+ * @supports docs/stories/010.0-DEV-DEEP-VALIDATION.story.md REQ-DEEP-PARSE REQ-DEEP-MATCH REQ-DEEP-CACHE
9
+ * @supports docs/stories/010.2-DEV-MULTI-STORY-SUPPORT.story.md REQ-SUPPORTS-VALIDATE REQ-MIXED-SUPPORT REQ-SCOPED-IDS
10
+ */
11
+ export declare function createValidReqReferenceProgramVisitor(context: Rule.RuleContext): () => void;