eslint-plugin-traceability 1.6.4 → 1.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. package/README.md +38 -1
  2. package/lib/src/index.d.ts +28 -25
  3. package/lib/src/index.js +49 -31
  4. package/lib/src/maintenance/cli.d.ts +12 -0
  5. package/lib/src/maintenance/cli.js +279 -0
  6. package/lib/src/maintenance/detect.js +30 -15
  7. package/lib/src/maintenance/update.js +42 -34
  8. package/lib/src/maintenance/utils.js +30 -30
  9. package/lib/src/rules/helpers/require-story-io.js +51 -15
  10. package/lib/src/rules/helpers/require-story-visitors.js +5 -16
  11. package/lib/src/rules/helpers/valid-annotation-options.d.ts +118 -0
  12. package/lib/src/rules/helpers/valid-annotation-options.js +167 -0
  13. package/lib/src/rules/helpers/valid-annotation-utils.d.ts +68 -0
  14. package/lib/src/rules/helpers/valid-annotation-utils.js +103 -0
  15. package/lib/src/rules/helpers/valid-story-reference-helpers.d.ts +67 -0
  16. package/lib/src/rules/helpers/valid-story-reference-helpers.js +92 -0
  17. package/lib/src/rules/require-story-annotation.js +9 -14
  18. package/lib/src/rules/valid-annotation-format.js +168 -180
  19. package/lib/src/rules/valid-req-reference.js +139 -29
  20. package/lib/src/rules/valid-story-reference.d.ts +7 -0
  21. package/lib/src/rules/valid-story-reference.js +38 -80
  22. package/lib/src/utils/annotation-checker.js +2 -145
  23. package/lib/src/utils/branch-annotation-helpers.js +12 -3
  24. package/lib/src/utils/reqAnnotationDetection.d.ts +6 -0
  25. package/lib/src/utils/reqAnnotationDetection.js +152 -0
  26. package/lib/tests/maintenance/cli.test.d.ts +1 -0
  27. package/lib/tests/maintenance/cli.test.js +172 -0
  28. package/lib/tests/maintenance/detect-isolated.test.js +68 -1
  29. package/lib/tests/maintenance/report.test.js +2 -2
  30. package/lib/tests/rules/require-branch-annotation.test.js +3 -2
  31. package/lib/tests/rules/require-req-annotation.test.js +57 -68
  32. package/lib/tests/rules/require-story-annotation.test.js +13 -28
  33. package/lib/tests/rules/require-story-core-edgecases.test.js +3 -58
  34. package/lib/tests/rules/require-story-core.autofix.test.js +5 -41
  35. package/lib/tests/rules/valid-annotation-format.test.js +328 -51
  36. package/lib/tests/utils/annotation-checker.test.d.ts +23 -0
  37. package/lib/tests/utils/annotation-checker.test.js +24 -17
  38. package/lib/tests/utils/require-story-core-test-helpers.d.ts +10 -0
  39. package/lib/tests/utils/require-story-core-test-helpers.js +75 -0
  40. package/lib/tests/utils/ts-language-options.d.ts +22 -0
  41. package/lib/tests/utils/ts-language-options.js +27 -0
  42. package/package.json +12 -3
@@ -1,16 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- const STORY_EXAMPLE_PATH = "docs/stories/005.0-DEV-EXAMPLE.story.md";
4
- /**
5
- * Constant to represent the "tag not found" index when searching
6
- * for @story or @req within a comment.
7
- *
8
- * @story docs/stories/005.0-DEV-ANNOTATION-VALIDATION.story.md
9
- * @story docs/stories/008.0-DEV-AUTO-FIX.story.md
10
- * @req REQ-AUTOFIX-FORMAT - Provide safe, minimal automatic fixes for common format issues
11
- * @req REQ-AUTOFIX-PRESERVE - Avoid risky text replacements when the annotation tag cannot be located
12
- */
13
- const TAG_NOT_FOUND_INDEX = -1;
3
+ const valid_annotation_options_1 = require("./helpers/valid-annotation-options");
4
+ const valid_annotation_utils_1 = require("./helpers/valid-annotation-utils");
14
5
  /**
15
6
  * Normalize a raw comment line to make annotation parsing more robust.
16
7
  *
@@ -35,92 +26,57 @@ function normalizeCommentLine(rawLine) {
35
26
  return trimmed.slice(annotationMatch.index);
36
27
  }
37
28
  /**
38
- * Collapse internal whitespace in an annotation value so that multi-line
39
- * annotations are treated as a single logical value.
40
- *
41
- * Example:
42
- * "docs/stories/005.0-DEV-ANNOTATION-VALIDATION.story.md" across
43
- * multiple lines will be collapsed before validation.
44
- *
45
- * @story docs/stories/005.0-DEV-ANNOTATION-VALIDATION.story.md
46
- * @story docs/stories/008.0-DEV-AUTO-FIX.story.md
47
- * @req REQ-MULTILINE-SUPPORT - Handle annotations split across multiple lines
48
- * @req REQ-AUTOFIX-FORMAT - Provide safe, minimal automatic fixes for common format issues
49
- */
50
- function collapseAnnotationValue(value) {
51
- return value.replace(/\s+/g, "");
52
- }
53
- /**
54
- * Build a detailed error message for invalid @story annotations.
55
- *
56
- * @story docs/stories/005.0-DEV-ANNOTATION-VALIDATION.story.md
57
- * @story docs/stories/008.0-DEV-AUTO-FIX.story.md
58
- * @req REQ-ERROR-SPECIFICITY - Provide specific error messages for different format violations
59
- * @req REQ-AUTOFIX-FORMAT - Provide safe, minimal automatic fixes for common format issues
60
- */
61
- function buildStoryErrorMessage(kind, value) {
62
- if (kind === "missing") {
63
- return `Missing story path for @story annotation. Expected a path like "${STORY_EXAMPLE_PATH}".`;
64
- }
65
- return `Invalid story path "${value ?? ""}" for @story annotation. Expected a path like "${STORY_EXAMPLE_PATH}".`;
66
- }
67
- /**
68
- * Build a detailed error message for invalid @req annotations.
29
+ * Report an invalid @story annotation without applying a fix.
69
30
  *
70
31
  * @story docs/stories/005.0-DEV-ANNOTATION-VALIDATION.story.md
71
32
  * @story docs/stories/008.0-DEV-AUTO-FIX.story.md
72
- * @req REQ-ERROR-SPECIFICITY - Provide specific error messages for different format violations
73
33
  * @req REQ-AUTOFIX-FORMAT - Provide safe, minimal automatic fixes for common format issues
74
34
  */
75
- function buildReqErrorMessage(kind, value) {
76
- if (kind === "missing") {
77
- return 'Missing requirement ID for @req annotation. Expected an identifier like "REQ-EXAMPLE".';
78
- }
79
- return `Invalid requirement ID "${value ?? ""}" for @req annotation. Expected an identifier like "REQ-EXAMPLE" (uppercase letters, numbers, and dashes only).`;
35
+ function reportInvalidStoryFormat(context, comment, collapsed, options) {
36
+ context.report({
37
+ node: comment,
38
+ messageId: "invalidStoryFormat",
39
+ data: { details: (0, valid_annotation_utils_1.buildStoryErrorMessage)("invalid", collapsed, options) },
40
+ });
80
41
  }
81
42
  /**
82
- * Attempt a minimal, safe auto-fix for common @story path suffix issues.
43
+ * Compute the text replacement for an invalid @story annotation within a comment.
83
44
  *
84
- * Only handles:
85
- * - missing ".md"
86
- * - missing ".story.md"
87
- * and skips any paths with traversal segments (e.g. "..").
45
+ * This helper:
46
+ * - finds the @story tag in the raw comment text,
47
+ * - computes the character range of its value,
48
+ * - and returns an ESLint fix that replaces only that range.
88
49
  *
89
- * Returns the fixed path when safe, or null if no fix should be applied.
50
+ * Returns null when the tag or value cannot be safely located.
90
51
  *
91
52
  * @story docs/stories/008.0-DEV-AUTO-FIX.story.md
92
- * @req REQ-AUTOFIX-FORMAT - Provide safe, minimal automatic fixes for common format issues
93
- * @req REQ-AUTOFIX-SAFE - Auto-fix must be conservative and never broaden the referenced path
94
- * @req REQ-AUTOFIX-PRESERVE - Preserve surrounding formatting when normalizing story path suffixes
53
+ * @req REQ-AUTOFIX-SAFE
54
+ * @req REQ-AUTOFIX-PRESERVE
95
55
  */
96
- function getFixedStoryPath(original) {
97
- if (original.includes("..")) {
56
+ function createStoryFix(context, comment, fixed) {
57
+ const sourceCode = context.getSourceCode();
58
+ const commentText = sourceCode.getText(comment);
59
+ const search = "@story";
60
+ const tagIndex = commentText.indexOf(search);
61
+ if (tagIndex === valid_annotation_utils_1.TAG_NOT_FOUND_INDEX) {
98
62
  return null;
99
63
  }
100
- if (/\.story\.md$/.test(original)) {
64
+ const afterTagIndex = tagIndex + search.length;
65
+ const rest = commentText.slice(afterTagIndex);
66
+ const valueMatch = rest.match(/[^\S\r\n]*([^\r\n*]+)/);
67
+ if (!valueMatch || valueMatch.index === undefined) {
101
68
  return null;
102
69
  }
103
- if (/\.story$/.test(original)) {
104
- return `${original}.md`;
105
- }
106
- if (/\.md$/.test(original)) {
107
- return original.replace(/\.md$/, ".story.md");
108
- }
109
- return `${original}.story.md`;
110
- }
111
- /**
112
- * Report an invalid @story annotation without applying a fix.
113
- *
114
- * @story docs/stories/005.0-DEV-ANNOTATION-VALIDATION.story.md
115
- * @story docs/stories/008.0-DEV-AUTO-FIX.story.md
116
- * @req REQ-AUTOFIX-FORMAT - Provide safe, minimal automatic fixes for common format issues
117
- */
118
- function reportInvalidStoryFormat(context, comment, collapsed) {
119
- context.report({
120
- node: comment,
121
- messageId: "invalidStoryFormat",
122
- data: { details: buildStoryErrorMessage("invalid", collapsed) },
123
- });
70
+ const valueStartInComment = afterTagIndex +
71
+ valueMatch.index +
72
+ (valueMatch[0].length - valueMatch[1].length);
73
+ const valueEndInComment = valueStartInComment + valueMatch[1].length;
74
+ const start = comment.range[0];
75
+ const fixRange = [
76
+ start + valueStartInComment,
77
+ start + valueEndInComment,
78
+ ];
79
+ return () => (fixer) => fixer.replaceTextRange(fixRange, fixed);
124
80
  }
125
81
  /**
126
82
  * Report an invalid @story annotation and attempt a minimal, safe auto-fix
@@ -141,37 +97,18 @@ function reportInvalidStoryFormat(context, comment, collapsed) {
141
97
  * @req REQ-AUTOFIX-PRESERVE - Auto-fix must preserve surrounding formatting and comments
142
98
  */
143
99
  function reportInvalidStoryFormatWithFix(context, comment, collapsed, fixed) {
144
- const sourceCode = context.getSourceCode();
145
- const commentText = sourceCode.getText(comment);
146
- const search = "@story";
147
- const tagIndex = commentText.indexOf(search);
148
- if (tagIndex === TAG_NOT_FOUND_INDEX) {
149
- reportInvalidStoryFormat(context, comment, collapsed);
150
- return;
151
- }
152
- const afterTagIndex = tagIndex + search.length;
153
- const rest = commentText.slice(afterTagIndex);
154
- const valueMatch = rest.match(/[^\S\r\n]*([^\r\n*]+)/);
155
- if (!valueMatch || valueMatch.index === undefined) {
156
- reportInvalidStoryFormat(context, comment, collapsed);
100
+ const fixFactory = createStoryFix(context, comment, fixed);
101
+ if (!fixFactory) {
102
+ reportInvalidStoryFormat(context, comment, collapsed, (0, valid_annotation_options_1.getResolvedDefaults)());
157
103
  return;
158
104
  }
159
- const valueStartInComment = afterTagIndex +
160
- valueMatch.index +
161
- (valueMatch[0].length - valueMatch[1].length);
162
- const valueEndInComment = valueStartInComment + valueMatch[1].length;
163
- const start = comment.range[0];
164
- const fixRange = [
165
- start + valueStartInComment,
166
- start + valueEndInComment,
167
- ];
168
105
  context.report({
169
106
  node: comment,
170
107
  messageId: "invalidStoryFormat",
171
- data: { details: buildStoryErrorMessage("invalid", collapsed) },
172
- fix(fixer) {
173
- return fixer.replaceTextRange(fixRange, fixed);
108
+ data: {
109
+ details: (0, valid_annotation_utils_1.buildStoryErrorMessage)("invalid", collapsed, (0, valid_annotation_options_1.getResolvedDefaults)()),
174
110
  },
111
+ fix: fixFactory(),
175
112
  });
176
113
  }
177
114
  /**
@@ -183,32 +120,34 @@ function reportInvalidStoryFormatWithFix(context, comment, collapsed, fixed) {
183
120
  * @req REQ-PATH-FORMAT - Validate @story paths follow expected patterns
184
121
  * @req REQ-ERROR-SPECIFICITY - Provide specific error messages for different format violations
185
122
  * @req REQ-AUTOFIX-FORMAT - Provide safe, minimal automatic fixes for common format issues
123
+ * @req REQ-REGEX-VALIDATION - Validate configurable story regex patterns and fall back safely
124
+ * @req REQ-BACKWARD-COMP - Preserve behavior when invalid regex config is supplied
186
125
  */
187
- function validateStoryAnnotation(context, comment, rawValue) {
126
+ function validateStoryAnnotation(context, comment, rawValue, options) {
188
127
  const trimmed = rawValue.trim();
189
128
  if (!trimmed) {
190
129
  context.report({
191
130
  node: comment,
192
131
  messageId: "invalidStoryFormat",
193
- data: { details: buildStoryErrorMessage("missing", null) },
132
+ data: { details: (0, valid_annotation_utils_1.buildStoryErrorMessage)("missing", null, options) },
194
133
  });
195
134
  return;
196
135
  }
197
- const collapsed = collapseAnnotationValue(trimmed);
198
- const pathPattern = /^docs\/stories\/[0-9]+\.[0-9]+-DEV-[\w-]+\.story\.md$/;
136
+ const collapsed = (0, valid_annotation_utils_1.collapseAnnotationValue)(trimmed);
137
+ const pathPattern = options.storyPattern;
199
138
  if (pathPattern.test(collapsed)) {
200
139
  return;
201
140
  }
202
141
  if (/\s/.test(trimmed)) {
203
- reportInvalidStoryFormat(context, comment, collapsed);
142
+ reportInvalidStoryFormat(context, comment, collapsed, options);
204
143
  return;
205
144
  }
206
- const fixed = getFixedStoryPath(collapsed);
145
+ const fixed = (0, valid_annotation_utils_1.getFixedStoryPath)(collapsed);
207
146
  if (fixed && pathPattern.test(fixed)) {
208
147
  reportInvalidStoryFormatWithFix(context, comment, collapsed, fixed);
209
148
  return;
210
149
  }
211
- reportInvalidStoryFormat(context, comment, collapsed);
150
+ reportInvalidStoryFormat(context, comment, collapsed, options);
212
151
  }
213
152
  /**
214
153
  * Validate a @req annotation value and report detailed errors when needed.
@@ -217,27 +156,101 @@ function validateStoryAnnotation(context, comment, rawValue) {
217
156
  * @story docs/stories/008.0-DEV-AUTO-FIX.story.md
218
157
  * @req REQ-REQ-FORMAT - Validate @req identifiers follow expected patterns
219
158
  * @req REQ-ERROR-SPECIFICITY - Provide specific error messages for different format violations
159
+ * @req REQ-REGEX-VALIDATION - Validate configurable requirement regex patterns and fall back safely
160
+ * @req REQ-BACKWARD-COMP - Preserve behavior when invalid regex config is supplied
220
161
  */
221
- function validateReqAnnotation(context, comment, rawValue) {
162
+ function validateReqAnnotation(context, comment, rawValue, options) {
222
163
  const trimmed = rawValue.trim();
223
164
  if (!trimmed) {
224
165
  context.report({
225
166
  node: comment,
226
167
  messageId: "invalidReqFormat",
227
- data: { details: buildReqErrorMessage("missing", null) },
168
+ data: { details: (0, valid_annotation_utils_1.buildReqErrorMessage)("missing", null, options) },
228
169
  });
229
170
  return;
230
171
  }
231
- const collapsed = collapseAnnotationValue(trimmed);
232
- const reqPattern = /^REQ-[A-Z0-9-]+$/;
172
+ const collapsed = (0, valid_annotation_utils_1.collapseAnnotationValue)(trimmed);
173
+ const reqPattern = options.reqPattern;
233
174
  if (!reqPattern.test(collapsed)) {
234
175
  context.report({
235
176
  node: comment,
236
177
  messageId: "invalidReqFormat",
237
- data: { details: buildReqErrorMessage("invalid", collapsed) },
178
+ data: { details: (0, valid_annotation_utils_1.buildReqErrorMessage)("invalid", collapsed, options) },
238
179
  });
239
180
  }
240
181
  }
182
+ /**
183
+ * Finalize and validate the currently pending annotation, if any.
184
+ *
185
+ * @story docs/stories/005.0-DEV-ANNOTATION-VALIDATION.story.md
186
+ * @story docs/stories/008.0-DEV-AUTO-FIX.story.md
187
+ * @req REQ-SYNTAX-VALIDATION - Validate annotation syntax matches specification
188
+ * @req REQ-AUTOFIX-FORMAT - Provide safe, minimal automatic fixes for common format issues
189
+ */
190
+ function finalizePendingAnnotation(context, comment, options, pending) {
191
+ if (!pending) {
192
+ return null;
193
+ }
194
+ // @story docs/stories/005.0-DEV-ANNOTATION-VALIDATION.story.md
195
+ // @story docs/stories/008.0-DEV-AUTO-FIX.story.md
196
+ // @req REQ-SYNTAX-VALIDATION - Dispatch validation based on annotation type
197
+ // @req REQ-AUTOFIX-FORMAT - Provide safe, minimal automatic fixes for common format issues
198
+ if (pending.type === "story") {
199
+ validateStoryAnnotation(context, comment, pending.value, options);
200
+ }
201
+ else {
202
+ validateReqAnnotation(context, comment, pending.value, options);
203
+ }
204
+ return null;
205
+ }
206
+ /**
207
+ * Process a single normalized comment line and update the pending annotation state.
208
+ *
209
+ * @story docs/stories/005.0-DEV-ANNOTATION-VALIDATION.story.md
210
+ * @story docs/stories/008.0-DEV-AUTO-FIX.story.md
211
+ * @req REQ-SYNTAX-VALIDATION - Start new pending annotation when a tag is found
212
+ * @req REQ-MULTILINE-SUPPORT - Treat subsequent lines as continuation for pending annotation
213
+ * @req REQ-AUTOFIX-FORMAT - Provide safe, minimal automatic fixes for common format issues
214
+ */
215
+ function processCommentLine({ normalized, pending, context, comment, options, }) {
216
+ if (!normalized) {
217
+ return pending;
218
+ }
219
+ const isStory = /@story\b/.test(normalized);
220
+ const isReq = /@req\b/.test(normalized);
221
+ // @story docs/stories/005.0-DEV-ANNOTATION-VALIDATION.story.md
222
+ // @story docs/stories/008.0-DEV-AUTO-FIX.story.md
223
+ // @req REQ-SYNTAX-VALIDATION - Start new pending annotation when a tag is found
224
+ // @req REQ-AUTOFIX-FORMAT - Provide safe, minimal automatic fixes for common format issues
225
+ if (isStory || isReq) {
226
+ finalizePendingAnnotation(context, comment, options, pending);
227
+ const value = normalized.replace(/^@story\b|^@req\b/, "").trim();
228
+ return {
229
+ type: isStory ? "story" : "req",
230
+ value,
231
+ hasValue: value.trim().length > 0,
232
+ };
233
+ }
234
+ // @story docs/stories/005.0-DEV-ANNOTATION-VALIDATION.story.md
235
+ // @story docs/stories/008.0-DEV-AUTO-FIX.story.md
236
+ // @req REQ-MULTILINE-SUPPORT - Treat subsequent lines as continuation for pending annotation
237
+ // @req REQ-AUTOFIX-FORMAT - Provide safe, minimal automatic fixes for common format issues
238
+ if (pending) {
239
+ const continuation = normalized.trim();
240
+ if (!continuation) {
241
+ return pending;
242
+ }
243
+ const updatedValue = pending.value
244
+ ? `${pending.value} ${continuation}`
245
+ : continuation;
246
+ return {
247
+ ...pending,
248
+ value: updatedValue,
249
+ hasValue: pending.hasValue || continuation.length > 0,
250
+ };
251
+ }
252
+ return pending;
253
+ }
241
254
  /**
242
255
  * Process a single comment node and validate any @story/@req annotations it contains.
243
256
  *
@@ -251,70 +264,20 @@ function validateReqAnnotation(context, comment, rawValue) {
251
264
  * @req REQ-FLEXIBLE-PARSING - Support reasonable variations in whitespace and formatting
252
265
  * @req REQ-AUTOFIX-FORMAT - Provide safe, minimal automatic fixes for common format issues
253
266
  */
254
- function processComment(context, comment) {
267
+ function processComment(context, comment, options) {
255
268
  const rawLines = (comment.value || "").split(/\r?\n/);
256
269
  let pending = null;
257
- /**
258
- * Finalize and validate the currently pending annotation, if any.
259
- *
260
- * @story docs/stories/005.0-DEV-ANNOTATION-VALIDATION.story.md
261
- * @story docs/stories/008.0-DEV-AUTO-FIX.story.md
262
- * @req REQ-SYNTAX-VALIDATION - Validate annotation syntax matches specification
263
- * @req REQ-AUTOFIX-FORMAT - Provide safe, minimal automatic fixes for common format issues
264
- */
265
- function finalizePending() {
266
- if (!pending) {
267
- return;
268
- }
269
- // @story docs/stories/005.0-DEV-ANNOTATION-VALIDATION.story.md
270
- // @story docs/stories/008.0-DEV-AUTO-FIX.story.md
271
- // @req REQ-SYNTAX-VALIDATION - Dispatch validation based on annotation type
272
- // @req REQ-AUTOFIX-FORMAT - Provide safe, minimal automatic fixes for common format issues
273
- if (pending.type === "story") {
274
- validateStoryAnnotation(context, comment, pending.value);
275
- }
276
- else {
277
- validateReqAnnotation(context, comment, pending.value);
278
- }
279
- pending = null;
280
- }
281
270
  rawLines.forEach((rawLine) => {
282
271
  const normalized = normalizeCommentLine(rawLine);
283
- if (!normalized) {
284
- return;
285
- }
286
- const isStory = /@story\b/.test(normalized);
287
- const isReq = /@req\b/.test(normalized);
288
- // @story docs/stories/005.0-DEV-ANNOTATION-VALIDATION.story.md
289
- // @story docs/stories/008.0-DEV-AUTO-FIX.story.md
290
- // @req REQ-SYNTAX-VALIDATION - Start new pending annotation when a tag is found
291
- // @req REQ-AUTOFIX-FORMAT - Provide safe, minimal automatic fixes for common format issues
292
- if (isStory || isReq) {
293
- finalizePending();
294
- const value = normalized.replace(/^@story\b|^@req\b/, "").trim();
295
- pending = {
296
- type: isStory ? "story" : "req",
297
- value,
298
- hasValue: value.trim().length > 0,
299
- };
300
- return;
301
- }
302
- // @story docs/stories/005.0-DEV-ANNOTATION-VALIDATION.story.md
303
- // @story docs/stories/008.0-DEV-AUTO-FIX.story.md
304
- // @req REQ-MULTILINE-SUPPORT - Treat subsequent lines as continuation for pending annotation
305
- // @req REQ-AUTOFIX-FORMAT - Provide safe, minimal automatic fixes for common format issues
306
- if (pending) {
307
- const continuation = normalized.trim();
308
- if (!continuation) {
309
- return;
310
- }
311
- pending.value = pending.value
312
- ? `${pending.value} ${continuation}`
313
- : continuation;
314
- pending.hasValue = pending.hasValue || continuation.length > 0;
315
- }
272
+ pending = processCommentLine({
273
+ normalized,
274
+ pending,
275
+ context,
276
+ comment,
277
+ options,
278
+ });
316
279
  });
317
- finalizePending();
280
+ finalizePendingAnnotation(context, comment, options, pending);
318
281
  }
319
282
  exports.default = {
320
283
  meta: {
@@ -338,8 +301,14 @@ exports.default = {
338
301
  * @req REQ-ERROR-CONSISTENCY - Use shared "Invalid annotation format: {{details}}." message pattern across rules
339
302
  */
340
303
  invalidReqFormat: "Invalid annotation format: {{details}}.",
304
+ /**
305
+ * @story docs/stories/010.1-DEV-CONFIGURABLE-PATTERNS.story.md
306
+ * @req REQ-REGEX-VALIDATION - Surface configuration errors for invalid regex patterns
307
+ * @req REQ-BACKWARD-COMP - Preserve behavior by falling back to default patterns on error
308
+ */
309
+ invalidRuleConfiguration: "Invalid configuration for valid-annotation-format: {{details}}",
341
310
  },
342
- schema: [],
311
+ schema: (0, valid_annotation_options_1.getRuleSchema)(),
343
312
  /**
344
313
  * This rule's fixable support is limited to safe @story path suffix normalization per Story 008.0.
345
314
  * Fixes are limited strictly to adjusting the suffix portion of the @story path (e.g., adding
@@ -348,32 +317,51 @@ exports.default = {
348
317
  * @story docs/stories/008.0-DEV-AUTO-FIX.story.md
349
318
  * @req REQ-AUTOFIX-SAFE
350
319
  * @req REQ-AUTOFIX-PRESERVE
320
+ * @req REQ-REGEX-VALIDATION - Ensure regex configuration does not affect fix safety
321
+ * @req REQ-BACKWARD-COMP - Maintain previous auto-fix behavior under invalid configs
351
322
  */
352
323
  fixable: "code",
353
324
  },
354
325
  /**
355
326
  * @story docs/stories/005.0-DEV-ANNOTATION-VALIDATION.story.md
356
327
  * @story docs/stories/008.0-DEV-AUTO-FIX.story.md
328
+ * @story docs/stories/010.1-DEV-CONFIGURABLE-PATTERNS.story.md
357
329
  * @req REQ-SYNTAX-VALIDATION - Ensure rule create function validates annotations syntax
358
330
  * @req REQ-FORMAT-SPECIFICATION - Implement formatting checks per specification
359
331
  * @req REQ-AUTOFIX-FORMAT - Provide safe, minimal automatic fixes for common format issues
332
+ * @req REQ-REGEX-VALIDATION - Derive validation regexes from shared options helper
333
+ * @req REQ-BACKWARD-COMP - Fall back to default patterns and continue validation on config errors
360
334
  */
361
335
  create(context) {
362
336
  const sourceCode = context.getSourceCode();
337
+ const options = (0, valid_annotation_options_1.resolveOptions)(context.options || []);
338
+ const optionErrors = (0, valid_annotation_options_1.getOptionErrors)();
363
339
  return {
364
340
  /**
365
341
  * Program-level handler that inspects all comments for @story and @req tags
366
342
  *
367
343
  * @story docs/stories/005.0-DEV-ANNOTATION-VALIDATION.story.md
368
344
  * @story docs/stories/008.0-DEV-AUTO-FIX.story.md
345
+ * @story docs/stories/010.1-DEV-CONFIGURABLE-PATTERNS.story.md
369
346
  * @req REQ-PATH-FORMAT - Validate @story paths follow expected patterns
370
347
  * @req REQ-REQ-FORMAT - Validate @req identifiers follow expected patterns
371
348
  * @req REQ-AUTOFIX-FORMAT - Provide safe, minimal automatic fixes for common format issues
349
+ * @req REQ-REGEX-VALIDATION - Surface regex configuration errors without blocking validation
350
+ * @req REQ-BACKWARD-COMP - Continue validating comments using default patterns on error
372
351
  */
373
- Program() {
352
+ Program(node) {
353
+ if (optionErrors && optionErrors.length > 0) {
354
+ optionErrors.forEach((details) => {
355
+ context.report({
356
+ node,
357
+ messageId: "invalidRuleConfiguration",
358
+ data: { details },
359
+ });
360
+ });
361
+ }
374
362
  const comments = sourceCode.getAllComments() || [];
375
363
  comments.forEach((comment) => {
376
- processComment(context, comment);
364
+ processComment(context, comment, options);
377
365
  });
378
366
  },
379
367
  };