eslint-plugin-traceability 1.11.0 → 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 (84) hide show
  1. package/CHANGELOG.md +3 -4
  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/flags.js +111 -25
  7. package/lib/src/maintenance/update.js +1 -14
  8. package/lib/src/rules/helpers/require-story-core.d.ts +67 -0
  9. package/lib/src/rules/helpers/require-story-core.js +142 -23
  10. package/lib/src/rules/helpers/require-story-helpers.d.ts +9 -88
  11. package/lib/src/rules/helpers/require-story-helpers.js +118 -166
  12. package/lib/src/rules/helpers/require-story-io.js +51 -31
  13. package/lib/src/rules/helpers/valid-annotation-format-internal.d.ts +12 -13
  14. package/lib/src/rules/helpers/valid-annotation-format-internal.js +21 -16
  15. package/lib/src/rules/helpers/valid-annotation-format-validators.d.ts +29 -3
  16. package/lib/src/rules/helpers/valid-annotation-format-validators.js +29 -3
  17. package/lib/src/rules/helpers/valid-annotation-options.d.ts +3 -0
  18. package/lib/src/rules/helpers/valid-annotation-options.js +64 -21
  19. package/lib/src/rules/helpers/valid-annotation-utils.d.ts +3 -3
  20. package/lib/src/rules/helpers/valid-annotation-utils.js +10 -10
  21. package/lib/src/rules/helpers/valid-req-reference-helpers.d.ts +11 -0
  22. package/lib/src/rules/helpers/valid-req-reference-helpers.js +362 -0
  23. package/lib/src/rules/prefer-implements-annotation.js +7 -7
  24. package/lib/src/rules/require-story-annotation.d.ts +2 -0
  25. package/lib/src/rules/require-story-annotation.js +1 -1
  26. package/lib/src/rules/valid-req-reference.d.ts +4 -0
  27. package/lib/src/rules/valid-req-reference.js +5 -349
  28. package/lib/src/rules/valid-story-reference.d.ts +1 -1
  29. package/lib/src/rules/valid-story-reference.js +17 -10
  30. package/lib/src/utils/annotation-checker.js +31 -7
  31. package/lib/src/utils/branch-annotation-helpers.d.ts +2 -2
  32. package/lib/src/utils/branch-annotation-helpers.js +4 -4
  33. package/lib/src/utils/reqAnnotationDetection.js +36 -22
  34. package/lib/tests/cli-error-handling.test.js +2 -1
  35. package/lib/tests/config/eslint-config-validation.test.d.ts +8 -0
  36. package/lib/tests/config/eslint-config-validation.test.js +81 -0
  37. package/lib/tests/config/flat-config-presets-integration.test.js +1 -3
  38. package/lib/tests/config/require-story-annotation-config.test.d.ts +9 -0
  39. package/lib/tests/config/require-story-annotation-config.test.js +9 -0
  40. package/lib/tests/fixtures/stale/example.js +1 -1
  41. package/lib/tests/fixtures/update/example.js +1 -1
  42. package/lib/tests/integration/cli-integration.test.js +9 -1
  43. package/lib/tests/integration/dogfooding-validation.test.d.ts +1 -0
  44. package/lib/tests/integration/dogfooding-validation.test.js +94 -0
  45. package/lib/tests/maintenance/batch.test.js +1 -0
  46. package/lib/tests/maintenance/cli.test.js +38 -0
  47. package/lib/tests/maintenance/detect-isolated.test.js +6 -5
  48. package/lib/tests/maintenance/detect.test.js +1 -0
  49. package/lib/tests/maintenance/index.test.js +1 -0
  50. package/lib/tests/maintenance/report.test.js +1 -0
  51. package/lib/tests/maintenance/update-isolated.test.js +1 -0
  52. package/lib/tests/maintenance/update.test.js +1 -0
  53. package/lib/tests/perf/maintenance-cli-large-workspace.test.js +18 -0
  54. package/lib/tests/perf/require-branch-annotation-large-file.test.d.ts +1 -0
  55. package/lib/tests/perf/require-branch-annotation-large-file.test.js +67 -0
  56. package/lib/tests/plugin-default-export-and-configs.test.js +2 -0
  57. package/lib/tests/plugin-setup-error.test.d.ts +1 -0
  58. package/lib/tests/plugin-setup-error.test.js +1 -0
  59. package/lib/tests/plugin-setup.test.js +12 -1
  60. package/lib/tests/rules/auto-fix-behavior-008.test.js +16 -0
  61. package/lib/tests/rules/error-reporting.test.js +1 -0
  62. package/lib/tests/rules/prefer-implements-annotation.test.js +8 -0
  63. package/lib/tests/rules/require-branch-annotation.test.js +34 -0
  64. package/lib/tests/rules/require-story-core-edgecases.test.js +1 -0
  65. package/lib/tests/rules/require-story-core.autofix.test.js +1 -0
  66. package/lib/tests/rules/require-story-core.test.js +1 -0
  67. package/lib/tests/rules/require-story-helpers-edgecases.test.d.ts +1 -0
  68. package/lib/tests/rules/require-story-helpers-edgecases.test.js +1 -0
  69. package/lib/tests/rules/require-story-helpers.test.js +4 -3
  70. package/lib/tests/rules/require-story-io-behavior.test.d.ts +1 -0
  71. package/lib/tests/rules/require-story-io-behavior.test.js +1 -0
  72. package/lib/tests/rules/require-story-io.edgecases.test.d.ts +1 -0
  73. package/lib/tests/rules/require-story-io.edgecases.test.js +1 -0
  74. package/lib/tests/rules/require-story-visitors-edgecases.test.d.ts +1 -0
  75. package/lib/tests/rules/require-story-visitors-edgecases.test.js +1 -0
  76. package/lib/tests/rules/valid-annotation-format-internal.test.d.ts +8 -0
  77. package/lib/tests/rules/valid-annotation-format-internal.test.js +47 -0
  78. package/lib/tests/rules/valid-story-reference.test.js +2 -0
  79. package/lib/tests/utils/annotation-checker.test.js +2 -1
  80. package/lib/tests/utils/branch-annotation-helpers.test.js +2 -1
  81. package/package.json +2 -2
  82. package/user-docs/api-reference.md +115 -8
  83. package/user-docs/examples.md +1 -1
  84. package/user-docs/migration-guide.md +35 -2
@@ -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
@@ -119,6 +119,9 @@ export declare function getRuleSchema(): {
119
119
  requirementIdExample: {
120
120
  type: string;
121
121
  };
122
+ autoFix: {
123
+ type: string;
124
+ };
122
125
  };
123
126
  additionalProperties: boolean;
124
127
  }[];
@@ -105,46 +105,88 @@ function resolveExample(nestedExample, flatExample, defaultExample) {
105
105
  }
106
106
  return defaultExample;
107
107
  }
108
- /**
109
- * Resolve user options into concrete, validated configuration.
110
- * Falls back to existing defaults when options are not provided or invalid.
111
- */
112
- function resolveOptions(rawOptions) {
113
- optionErrors = [];
114
- const user = normalizeUserOptions(rawOptions);
115
- const nestedStoryPattern = user?.story?.pattern;
116
- const flatStoryPattern = user?.storyPathPattern;
117
- const nestedStoryExample = user?.story?.example;
118
- const flatStoryExample = user?.storyPathExample;
119
- const nestedReqPattern = user?.req?.pattern;
120
- const flatReqPattern = user?.requirementIdPattern;
121
- const nestedReqExample = user?.req?.example;
122
- const flatReqExample = user?.requirementIdExample;
108
+ function getUserOptions(rawOptions) {
109
+ return normalizeUserOptions(rawOptions);
110
+ }
111
+ function resolveAutoFixFlag(user) {
123
112
  const autoFixFlag = user?.autoFix;
124
- const autoFix = typeof autoFixFlag === "boolean" ? autoFixFlag : true;
125
- const storyPattern = resolvePattern({
113
+ return typeof autoFixFlag === "boolean" ? autoFixFlag : true;
114
+ }
115
+ function resolveStoryPattern(nestedStoryPattern, flatStoryPattern) {
116
+ return resolvePattern({
126
117
  nestedPattern: nestedStoryPattern,
127
118
  nestedFieldName: "story.pattern",
128
119
  flatPattern: flatStoryPattern,
129
120
  flatFieldName: "storyPathPattern",
130
121
  defaultPattern: getDefaultStoryPattern(),
131
122
  });
132
- const reqPattern = resolvePattern({
123
+ }
124
+ function resolveReqPattern(nestedReqPattern, flatReqPattern) {
125
+ return resolvePattern({
133
126
  nestedPattern: nestedReqPattern,
134
127
  nestedFieldName: "req.pattern",
135
128
  flatPattern: flatReqPattern,
136
129
  flatFieldName: "requirementIdPattern",
137
130
  defaultPattern: getDefaultReqPattern(),
138
131
  });
139
- const storyExample = resolveExample(nestedStoryExample, flatStoryExample, getDefaultStoryExample());
140
- const reqExample = resolveExample(nestedReqExample, flatReqExample, getDefaultReqExample());
141
- resolvedDefaults = {
132
+ }
133
+ function resolveStoryExample(nestedStoryExample, flatStoryExample) {
134
+ return resolveExample(nestedStoryExample, flatStoryExample, getDefaultStoryExample());
135
+ }
136
+ function resolveReqExample(nestedReqExample, flatReqExample) {
137
+ return resolveExample(nestedReqExample, flatReqExample, getDefaultReqExample());
138
+ }
139
+ function getStoryPatternInputs(user) {
140
+ return {
141
+ nestedStoryPattern: user?.story?.pattern,
142
+ flatStoryPattern: user?.storyPathPattern,
143
+ };
144
+ }
145
+ function getStoryExampleInputs(user) {
146
+ return {
147
+ nestedStoryExample: user?.story?.example,
148
+ flatStoryExample: user?.storyPathExample,
149
+ };
150
+ }
151
+ function getReqPatternInputs(user) {
152
+ return {
153
+ nestedReqPattern: user?.req?.pattern,
154
+ flatReqPattern: user?.requirementIdPattern,
155
+ };
156
+ }
157
+ function getReqExampleInputs(user) {
158
+ return {
159
+ nestedReqExample: user?.req?.example,
160
+ flatReqExample: user?.requirementIdExample,
161
+ };
162
+ }
163
+ function resolveOptionsInternal(user) {
164
+ const { nestedStoryPattern, flatStoryPattern } = getStoryPatternInputs(user);
165
+ const { nestedStoryExample, flatStoryExample } = getStoryExampleInputs(user);
166
+ const { nestedReqPattern, flatReqPattern } = getReqPatternInputs(user);
167
+ const { nestedReqExample, flatReqExample } = getReqExampleInputs(user);
168
+ const autoFix = resolveAutoFixFlag(user);
169
+ const storyPattern = resolveStoryPattern(nestedStoryPattern, flatStoryPattern);
170
+ const reqPattern = resolveReqPattern(nestedReqPattern, flatReqPattern);
171
+ const storyExample = resolveStoryExample(nestedStoryExample, flatStoryExample);
172
+ const reqExample = resolveReqExample(nestedReqExample, flatReqExample);
173
+ return {
142
174
  storyPattern,
143
175
  storyExample,
144
176
  reqPattern,
145
177
  reqExample,
146
178
  autoFix,
147
179
  };
180
+ }
181
+ /**
182
+ * Resolve user options into concrete, validated configuration.
183
+ * Falls back to existing defaults when options are not provided or invalid.
184
+ */
185
+ function resolveOptions(rawOptions) {
186
+ optionErrors = [];
187
+ const user = getUserOptions(rawOptions);
188
+ const resolved = resolveOptionsInternal(user);
189
+ resolvedDefaults = resolved;
148
190
  return resolvedDefaults;
149
191
  }
150
192
  /**
@@ -175,6 +217,7 @@ function getRuleSchema() {
175
217
  storyPathExample: { type: "string" },
176
218
  requirementIdPattern: { type: "string" },
177
219
  requirementIdExample: { type: "string" },
220
+ autoFix: { type: "boolean" },
178
221
  },
179
222
  additionalProperties: false,
180
223
  },
@@ -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;