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
@@ -11,6 +11,9 @@ Object.defineProperty(exports, "__esModule", { value: true });
11
11
  * @req REQ-ERROR-SPECIFIC - Branch-level missing-annotation error messages are specific and informative
12
12
  * @req REQ-ERROR-CONSISTENCY - Branch-level missing-annotation error messages follow shared conventions
13
13
  * @req REQ-ERROR-SUGGESTION - Branch-level missing-annotation errors include suggestions when applicable
14
+ * @req REQ-NESTED-HANDLING - Nested branch annotations are correctly enforced without duplicative reporting
15
+ * @supports docs/stories/004.0-DEV-BRANCH-ANNOTATIONS.story.md REQ-BRANCH-DETECTION REQ-NESTED-HANDLING
16
+ * @supports docs/stories/007.0-DEV-ERROR-REPORTING.story.md REQ-ERROR-SPECIFIC REQ-ERROR-CONSISTENCY REQ-ERROR-SUGGESTION
14
17
  */
15
18
  const eslint_1 = require("eslint");
16
19
  const require_branch_annotation_1 = __importDefault(require("../../src/rules/require-branch-annotation"));
@@ -120,6 +123,18 @@ while (condition) {
120
123
  // @req REQ-BRANCH-DETECTION
121
124
  case 'a':
122
125
  break;
126
+ }`,
127
+ },
128
+ {
129
+ name: "[REQ-NESTED-HANDLING] nested if-statements with annotations on outer and inner branches",
130
+ code: `// @story docs/stories/004.0-DEV-BRANCH-ANNOTATIONS.story.md
131
+ // @req REQ-BRANCH-DETECTION
132
+ if (outer) {
133
+ // @story docs/stories/004.0-DEV-BRANCH-ANNOTATIONS.story.md
134
+ // @req REQ-NESTED-HANDLING
135
+ if (inner) {
136
+ doWork();
137
+ }
123
138
  }`,
124
139
  },
125
140
  {
@@ -244,6 +259,25 @@ try {
244
259
  // @story <story-file>.story.md
245
260
  case 'a':
246
261
  break;
262
+ }`,
263
+ errors: makeMissingAnnotationErrors("@story", "@req"),
264
+ },
265
+ {
266
+ name: "[REQ-NESTED-HANDLING] missing annotations on nested if-statement inside annotated outer branch",
267
+ code: `// @story docs/stories/004.0-DEV-BRANCH-ANNOTATIONS.story.md
268
+ // @req REQ-BRANCH-DETECTION
269
+ if (outer) {
270
+ if (inner) {
271
+ doWork();
272
+ }
273
+ }`,
274
+ output: `// @story docs/stories/004.0-DEV-BRANCH-ANNOTATIONS.story.md
275
+ // @req REQ-BRANCH-DETECTION
276
+ if (outer) {
277
+ // @story <story-file>.story.md
278
+ if (inner) {
279
+ doWork();
280
+ }
247
281
  }`,
248
282
  errors: makeMissingAnnotationErrors("@story", "@req"),
249
283
  },
@@ -4,6 +4,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
4
4
  * Edge-case tests for: docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
5
5
  * @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
6
6
  * @req REQ-AUTOFIX - Cover additional branch cases in require-story-core (addStoryFixer/reportMissing)
7
+ * @supports docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md REQ-AUTOFIX
7
8
  */
8
9
  const require_story_core_1 = require("../../src/rules/helpers/require-story-core");
9
10
  const require_story_core_test_helpers_1 = require("../utils/require-story-core-test-helpers");
@@ -4,6 +4,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
4
4
  * Tests for: docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
5
5
  * @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
6
6
  * @req REQ-AUTOFIX - Cover additional branch cases in require-story-core (addStoryFixer/reportMissing)
7
+ * @supports docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md REQ-AUTOFIX
7
8
  */
8
9
  const require_story_core_1 = require("../../src/rules/helpers/require-story-core");
9
10
  const require_story_helpers_1 = require("../../src/rules/helpers/require-story-helpers");
@@ -4,6 +4,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
4
4
  * Tests for: docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
5
5
  * @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
6
6
  * @req REQ-AUTOFIX - Verify createMethodFix and reportMethod behaviors
7
+ * @supports docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md REQ-AUTOFIX
7
8
  */
8
9
  const require_story_core_1 = require("../../src/rules/helpers/require-story-core");
9
10
  const require_story_helpers_1 = require("../../src/rules/helpers/require-story-helpers");
@@ -2,5 +2,6 @@
2
2
  * Tests for: docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
3
3
  * @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
4
4
  * @req REQ-HELPERS-EDGE-CASES - Edge-case behavior tests for helpers in require-story-helpers.ts
5
+ * @supports docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md REQ-HELPERS-EDGE-CASES
5
6
  */
6
7
  export {};
@@ -3,6 +3,7 @@
3
3
  * Tests for: docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
4
4
  * @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
5
5
  * @req REQ-HELPERS-EDGE-CASES - Edge-case behavior tests for helpers in require-story-helpers.ts
6
+ * @supports docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md REQ-HELPERS-EDGE-CASES
6
7
  */
7
8
  Object.defineProperty(exports, "__esModule", { value: true });
8
9
  const require_story_helpers_1 = require("../../src/rules/helpers/require-story-helpers");
@@ -4,6 +4,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
4
4
  * Tests for: docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
5
5
  * @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
6
6
  * @req REQ-ANNOTATION-REQUIRED - Verify helper functions in require-story helpers produce correct fixes and reporting behavior
7
+ * @supports docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md REQ-ANNOTATION-REQUIRED
7
8
  */
8
9
  const require_story_core_1 = require("../../src/rules/helpers/require-story-core");
9
10
  const require_story_helpers_1 = require("../../src/rules/helpers/require-story-helpers");
@@ -49,7 +50,7 @@ describe("Require Story Helpers (Story 003.0)", () => {
49
50
  test("reportMissing does not call context.report if JSDoc contains @story", () => {
50
51
  const node = {
51
52
  type: "FunctionDeclaration",
52
- id: { name: "fn" },
53
+ id: { type: "Identifier", name: "fn" },
53
54
  range: [0, 10],
54
55
  };
55
56
  const fakeSource = {
@@ -68,7 +69,7 @@ describe("Require Story Helpers (Story 003.0)", () => {
68
69
  test("reportMissing calls context.report when no JSDoc story present", () => {
69
70
  const node = {
70
71
  type: "FunctionDeclaration",
71
- id: { name: "fn2" },
72
+ id: { type: "Identifier", name: "fn2" },
72
73
  range: [0, 10],
73
74
  };
74
75
  const fakeSource = {
@@ -82,7 +83,7 @@ describe("Require Story Helpers (Story 003.0)", () => {
82
83
  (0, require_story_helpers_1.reportMissing)(context, fakeSource, { node, target: node });
83
84
  expect(context.report).toHaveBeenCalledTimes(1);
84
85
  const call = context.report.mock.calls[0][0];
85
- expect(call.node).toBe(node);
86
+ expect(call.node).toBe(node.id);
86
87
  expect(call.messageId).toBe("missingStory");
87
88
  });
88
89
  /**
@@ -2,5 +2,6 @@
2
2
  * Tests for: docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
3
3
  * @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
4
4
  * @req REQ-IO-BEHAVIOR-EDGE-CASES - Edge-case behavior tests for IO helpers in require-story-io.ts
5
+ * @supports docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md REQ-IO-BEHAVIOR-EDGE-CASES
5
6
  */
6
7
  export {};
@@ -3,6 +3,7 @@
3
3
  * Tests for: docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
4
4
  * @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
5
5
  * @req REQ-IO-BEHAVIOR-EDGE-CASES - Edge-case behavior tests for IO helpers in require-story-io.ts
6
+ * @supports docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md REQ-IO-BEHAVIOR-EDGE-CASES
6
7
  */
7
8
  Object.defineProperty(exports, "__esModule", { value: true });
8
9
  const require_story_io_1 = require("../../src/rules/helpers/require-story-io");
@@ -2,5 +2,6 @@
2
2
  * Tests for: docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
3
3
  * @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
4
4
  * @req REQ-ANNOTATION-REQUIRED - Edge case tests for IO helpers (linesBeforeHasStory/fallbackTextBeforeHasStory/parentChainHasStory)
5
+ * @supports docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md REQ-ANNOTATION-REQUIRED
5
6
  */
6
7
  export {};
@@ -3,6 +3,7 @@
3
3
  * Tests for: docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
4
4
  * @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
5
5
  * @req REQ-ANNOTATION-REQUIRED - Edge case tests for IO helpers (linesBeforeHasStory/fallbackTextBeforeHasStory/parentChainHasStory)
6
+ * @supports docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md REQ-ANNOTATION-REQUIRED
6
7
  */
7
8
  Object.defineProperty(exports, "__esModule", { value: true });
8
9
  const require_story_io_1 = require("../../src/rules/helpers/require-story-io");
@@ -2,5 +2,6 @@
2
2
  * Tests for: docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
3
3
  * @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
4
4
  * @req REQ-VISITORS-BEHAVIOR - Behavior tests for visitors in require-story-visitors.ts
5
+ * @supports docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md REQ-VISITORS-BEHAVIOR
5
6
  */
6
7
  export {};
@@ -3,6 +3,7 @@
3
3
  * Tests for: docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
4
4
  * @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
5
5
  * @req REQ-VISITORS-BEHAVIOR - Behavior tests for visitors in require-story-visitors.ts
6
+ * @supports docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md REQ-VISITORS-BEHAVIOR
6
7
  */
7
8
  Object.defineProperty(exports, "__esModule", { value: true });
8
9
  const require_story_visitors_1 = require("../../src/rules/helpers/require-story-visitors");
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Tests for: docs/stories/024.0-DEV-IGNORE-INLINE-CODE-REFS.story.md
3
+ * @story docs/stories/024.0-DEV-IGNORE-INLINE-CODE-REFS.story.md
4
+ * @req REQ-IGNORE-INLINE-CODE - Strip backtick-wrapped content before annotation detection
5
+ * @req REQ-PRESERVE-BOUNDARIES - Replace backtick-wrapped content with spaces to preserve word boundaries
6
+ * @req REQ-CENTRALIZED-FILTER - Apply backtick filtering in normalizeCommentLine for all rules
7
+ */
8
+ export {};
@@ -0,0 +1,47 @@
1
+ "use strict";
2
+ /**
3
+ * Tests for: docs/stories/024.0-DEV-IGNORE-INLINE-CODE-REFS.story.md
4
+ * @story docs/stories/024.0-DEV-IGNORE-INLINE-CODE-REFS.story.md
5
+ * @req REQ-IGNORE-INLINE-CODE - Strip backtick-wrapped content before annotation detection
6
+ * @req REQ-PRESERVE-BOUNDARIES - Replace backtick-wrapped content with spaces to preserve word boundaries
7
+ * @req REQ-CENTRALIZED-FILTER - Apply backtick filtering in normalizeCommentLine for all rules
8
+ */
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ const globals_1 = require("@jest/globals");
11
+ const valid_annotation_format_internal_1 = require("../../src/rules/helpers/valid-annotation-format-internal");
12
+ (0, globals_1.describe)("normalizeCommentLine inline code filtering (Story 024.0-DEV-IGNORE-INLINE-CODE-REFS)", () => {
13
+ (0, globals_1.it)("[REQ-IGNORE-INLINE-CODE] ignores backtick-wrapped @story in line without real annotations", () => {
14
+ const raw = "This rule uses `@story` and other tags";
15
+ const normalized = (0, valid_annotation_format_internal_1.normalizeCommentLine)(raw);
16
+ (0, globals_1.expect)(normalized).toBe("This rule uses and other tags");
17
+ (0, globals_1.expect)(normalized).not.toMatch(/@story|@req|@supports/);
18
+ });
19
+ (0, globals_1.it)("[REQ-IGNORE-INLINE-CODE] ignores backtick-wrapped @req in line without real annotations", () => {
20
+ const raw = "Legacy pattern `@req` should not be treated as annotation";
21
+ const normalized = (0, valid_annotation_format_internal_1.normalizeCommentLine)(raw);
22
+ (0, globals_1.expect)(normalized).toBe("Legacy pattern should not be treated as annotation");
23
+ (0, globals_1.expect)(normalized).not.toMatch(/@story|@req|@supports/);
24
+ });
25
+ (0, globals_1.it)("[REQ-IGNORE-INLINE-CODE][REQ-PRESERVE-BOUNDARIES] preserves spacing when removing backtick segments", () => {
26
+ const raw = "`@story` + `@req` docs";
27
+ const normalized = (0, valid_annotation_format_internal_1.normalizeCommentLine)(raw);
28
+ (0, globals_1.expect)(normalized).toBe(" + docs");
29
+ (0, globals_1.expect)(normalized).not.toMatch(/@story|@req|@supports/);
30
+ });
31
+ (0, globals_1.it)("[REQ-IGNORE-INLINE-CODE] still detects real @story annotation outside backticks", () => {
32
+ const raw = "using `@supports` and real @story docs/stories/005.0-DEV-ANNOTATION-VALIDATION.story.md";
33
+ const normalized = (0, valid_annotation_format_internal_1.normalizeCommentLine)(raw);
34
+ (0, globals_1.expect)(normalized).toBe("@story docs/stories/005.0-DEV-ANNOTATION-VALIDATION.story.md");
35
+ });
36
+ (0, globals_1.it)("[REQ-IGNORE-INLINE-CODE][REQ-PRESERVE-BOUNDARIES] handles multiple backtick segments on one line", () => {
37
+ const raw = "first `@story` and second `@req` markers";
38
+ const normalized = (0, valid_annotation_format_internal_1.normalizeCommentLine)(raw);
39
+ (0, globals_1.expect)(normalized).toBe("first and second markers");
40
+ (0, globals_1.expect)(normalized).not.toMatch(/@story|@req|@supports/);
41
+ });
42
+ (0, globals_1.it)("[REQ-IGNORE-INLINE-CODE] leaves lines without backticks unchanged apart from existing normalization", () => {
43
+ const raw = " * @story docs/stories/005.0-DEV-ANNOTATION-VALIDATION.story.md";
44
+ const normalized = (0, valid_annotation_format_internal_1.normalizeCommentLine)(raw);
45
+ (0, globals_1.expect)(normalized).toBe("@story docs/stories/005.0-DEV-ANNOTATION-VALIDATION.story.md");
46
+ });
47
+ });
@@ -45,6 +45,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
45
45
  * @req REQ-ERROR-CONTEXT - Verify file-related error messages include contextual information (path, underlying error)
46
46
  * @req REQ-ERROR-CONSISTENCY - Verify file-related error messages follow consistent formatting and identifiers
47
47
  * @req REQ-ERROR-HANDLING - Verify file-related errors are reported via diagnostics instead of uncaught exceptions
48
+ * @supports docs/stories/006.0-DEV-FILE-VALIDATION.story.md REQ-FILE-EXISTENCE REQ-CONFIGURABLE-PATHS
49
+ * @supports docs/stories/007.0-DEV-ERROR-REPORTING.story.md REQ-ERROR-SPECIFIC REQ-ERROR-CONTEXT REQ-ERROR-CONSISTENCY REQ-ERROR-HANDLING
48
50
  */
49
51
  const eslint_1 = require("eslint");
50
52
  const valid_story_reference_1 = __importDefault(require("../../src/rules/valid-story-reference"));
@@ -6,6 +6,7 @@ exports.runAnnotationCheckerTests = runAnnotationCheckerTests;
6
6
  * @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
7
7
  * @req REQ-TYPESCRIPT-SUPPORT - Support TypeScript-specific function syntax
8
8
  * @req REQ-TEST-UTILS-TS-LANG - Shared TS RuleTester language options helper
9
+ * @supports docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md REQ-TYPESCRIPT-SUPPORT REQ-TEST-UTILS-TS-LANG
9
10
  */
10
11
  const eslint_1 = require("eslint");
11
12
  const annotation_checker_1 = require("../../src/utils/annotation-checker");
@@ -52,7 +53,7 @@ const rule = {
52
53
  };
53
54
  },
54
55
  };
55
- describe("annotation-checker helper", () => {
56
+ describe("annotation-checker helper (Story 003.0-DEV-FUNCTION-ANNOTATIONS)", () => {
56
57
  runAnnotationCheckerTests("annotation-checker", {
57
58
  rule,
58
59
  valid: [
@@ -5,9 +5,10 @@ Object.defineProperty(exports, "__esModule", { value: true });
5
5
  * Tests for: docs/stories/004.0-DEV-BRANCH-ANNOTATIONS.story.md
6
6
  * @story docs/stories/004.0-DEV-BRANCH-ANNOTATIONS.story.md
7
7
  * @req REQ-CONFIGURABLE-SCOPE - Allow configuration of branch types for annotation enforcement
8
+ * @supports docs/stories/004.0-DEV-BRANCH-ANNOTATIONS.story.md REQ-CONFIGURABLE-SCOPE
8
9
  */
9
10
  const branch_annotation_helpers_1 = require("../../src/utils/branch-annotation-helpers");
10
- describe("validateBranchTypes helper", () => {
11
+ describe("validateBranchTypes helper (Story 004.0-DEV-BRANCH-ANNOTATIONS)", () => {
11
12
  let context;
12
13
  beforeEach(() => {
13
14
  context = { options: [], report: jest.fn() };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eslint-plugin-traceability",
3
- "version": "1.11.0",
3
+ "version": "1.11.2",
4
4
  "description": "A customizable ESLint plugin that enforces traceability annotations in your code, ensuring each implementation is linked to its requirement or test case.",
5
5
  "main": "lib/src/index.js",
6
6
  "types": "lib/src/index.d.ts",
@@ -29,7 +29,7 @@
29
29
  "lint": "eslint --config eslint.config.js \"src/**/*.{js,ts}\" \"tests/**/*.{js,ts}\" --max-warnings=0",
30
30
  "test": "jest --ci --bail",
31
31
  "ci-verify": "npm run type-check && npm run lint && npm run format:check && npm run duplication && npm run check:traceability && npm test && npm run audit:ci && npm run safety:deps",
32
- "ci-verify:full": "npm run check:traceability && npm run safety:deps && npm run audit:ci && npm run build && npm run type-check && npm run lint-plugin-check && npm run lint -- --max-warnings=0 && npm run duplication && npm run test -- --coverage && npm run format:check && npm audit --omit=dev --audit-level=high && npm run audit:dev-high",
32
+ "ci-verify:full": "npm run check:traceability && npm run safety:deps && npm run audit:ci && npm run build && npm run type-check && npm run lint-plugin-check && npm run lint -- --max-warnings=0 && npm run duplication && npm run test -- --coverage && npm run format:check && npm audit --omit=dev --audit-level=high && npm run audit:dev-high && npm run check:ci-artifacts",
33
33
  "ci-verify:fast": "npm run type-check && npm run check:traceability && npm run duplication && jest --ci --bail --passWithNoTests --testPathPatterns 'tests/(rules|maintenance)'",
34
34
  "format": "prettier --write .",
35
35
  "format:check": "prettier --check \"src/**/*.ts\" \"tests/**/*.ts\"",
@@ -86,19 +86,19 @@ if (error) {
86
86
 
87
87
  ### traceability/valid-annotation-format
88
88
 
89
- Description: Validates that all traceability annotations (`@story`, `@req`) follow the correct JSDoc or inline comment format. When run with `--fix`, the rule limits changes to safe `@story` path suffix normalization only—for example, adding `.md` when the path ends with `.story`, or adding `.story.md` when the base path has no extension—using targeted replacements implemented in the `getFixedStoryPath` and `reportInvalidStoryFormatWithFix` helpers. It does not change directories, infer new story names, or modify any surrounding comment text or whitespace, in line with Story 008.0; more advanced path normalization strategies and selective toggles to enable or disable specific auto-fix behaviors are not yet implemented. You can also disable this suffix-normalization behavior explicitly via the `autoFix` option when you prefer purely diagnostic checks.
89
+ Description: Validates that all traceability annotations (`@story`, `@req`) follow the correct JSDoc or inline comment format. When run with `--fix`, the rule limits changes to safe `@story` path suffix normalization only—for example, adding `.md` when the path ends with `.story`, or adding `.story.md` when the base path has no extension—using targeted replacements implemented in the `getFixedStoryPath` and `reportInvalidStoryFormatWithFix` helpers. It does not change directories, infer new story names, or modify any surrounding comment text or whitespace, in line with Story 008.0. Selective disabling of this suffix-normalization auto-fix behavior is available via the `autoFix` option, which defaults to `true` for backward compatibility.
90
90
 
91
91
  Options:
92
92
 
93
93
  This rule accepts an optional configuration object. The primary configuration shape is **nested**:
94
94
 
95
95
  - `story` (object, optional) – Configuration for `@story` values.
96
- - `pattern` (string, optional) – A JavaScript regular expression **source** (without leading and trailing `/`) that all `@story` values must match. If provided, the rule validates each `@story` against this pattern in addition to its built‑in structural checks. By default, the plugin uses a pattern equivalent to `^docs/stories/.*\.story\.md$`, which matches a typical project convention such as `docs/stories/<name>.story.md`; you can override this to match however your own project organizes story files.
97
- - `example` (string, optional) – A short example `@story` path shown in error messages when `story.pattern` is configured. The built-in default example is `"docs/stories/001.0-EXAMPLE.story.md"`, intended as a generic illustration of a project story file, and does not refer to this plugin’s internal documentation.
96
+ - `pattern` (string, optional) – A JavaScript regular expression **source** (without leading and trailing `/`) that all `@story` values must match. If provided, the rule validates each `@story` against this pattern in addition to its built‑in structural checks. By default, the plugin uses a pattern equivalent to `^docs/stories/[0-9]+\.[0-9]+-DEV-[\w-]+\.story\.md$`, which matches typical project conventions such as `docs/stories/005.0-DEV-EXAMPLE.story.md`; you can override this to match however your own project organizes story files.
97
+ - `example` (string, optional) – A short example `@story` path shown in error messages when `story.pattern` is configured. The built-in default example is `"docs/stories/005.0-DEV-EXAMPLE.story.md"`, intended as a generic illustration of a project story file, and does not refer to this plugin’s internal documentation.
98
98
  - `req` (object, optional) – Configuration for `@req` values.
99
- - `pattern` (string, optional) – A JavaScript regular expression **source** (without leading and trailing `/`) that all `@req` values must match. If provided, the rule validates each `@req` identifier against this pattern. Defaults to the value returned by `getDefaultReqPattern()`, which is equivalent to `^REQ-[A-Z0-9_-]+$`, matching IDs such as `REQ-USER-AUTH` or `REQ-1234`.
100
- - `example` (string, optional) – A short example requirement ID shown in error messages when `req.pattern` is configured. Defaults to the value returned by `getDefaultReqExample()`, `"REQ-USER-AUTH"`. This value is used **only** for guidance and does not affect validation.
101
- - `autoFix` (boolean, optional) – When set to `false`, disables all automatic suffix-normalization fixes while keeping validation and error messages intact. When omitted or `true`, the rule continues to apply safe suffix-only auto-fixes in `--fix` mode.
99
+ - `pattern` (string, optional) – A JavaScript regular expression **source** (without leading and trailing `/`) that all `@req` values must match. If provided, the rule validates each `@req` identifier against this pattern. Defaults to the value returned by `getDefaultReqPattern()`, which is equivalent to `^REQ-[A-Z0-9-]+$`, matching IDs such as `REQ-USER-AUTH` or `REQ-1234`.
100
+ - `example` (string, optional) – A short example requirement ID shown in error messages when `req.pattern` is configured. Defaults to the value returned by `getDefaultReqExample()`, `"REQ-EXAMPLE"`. This value is used **only** for guidance and does not affect validation.
101
+ - `autoFix` (boolean, optional) – When set to `false`, disables all automatic suffix-normalization fixes while keeping validation and error messages intact. When omitted or `true`, the rule continues to apply safe `@story` suffix-only auto-fixes in `--fix` mode.
102
102
 
103
103
  For backward compatibility, the rule also supports **flat shorthand** fields that map directly to the nested properties:
104
104
 
@@ -113,6 +113,8 @@ Behavior notes:
113
113
  - When options are omitted, the rule behaves exactly as in earlier versions, relying on its built‑in defaults and path‑suffix normalization logic only.
114
114
  - The pattern checks are additional validation; they do not change the existing auto‑fix behavior, which remains limited to safe `@story` suffix normalization described above.
115
115
 
116
+ You can customize these validations to match your own naming conventions by overriding `story.pattern`/`storyPathPattern` and `req.pattern`/`requirementIdPattern`. This is useful when you store stories outside `docs/stories`, avoid `DEV` in filenames, or use a different requirement ID scheme instead of the default `REQ-...` format. Any custom values must still be valid JavaScript regular expression **sources** (without surrounding `/` characters).
117
+
116
118
  #### Migration and mixed usage
117
119
 
118
120
  The `valid-annotation-format` rule is intentionally **backward compatible** with existing code that only uses `@story` and `@req`. You can:
@@ -210,16 +212,18 @@ The rule accepts an optional configuration object:
210
212
  - `testFilePatterns` (string[], optional) – **Path-substring patterns** used to identify test files. For each file, the rule normalizes the file path to use forward slashes and then checks whether it contains at least one of the configured pattern strings. This is intentionally simpler than full glob matching and avoids adding extra runtime dependencies. Defaults to `["/tests/", "/test/", "/__tests__", ".test.", ".spec."]`. For most projects, these defaults behave like "any file under a `tests` or `test` directory, or any file whose name includes `.test.` or `.spec.`". If you prefer a different layout, supply custom substrings that uniquely identify your test files.
211
213
  - `requireDescribeStory` (boolean, optional) – When `true` (default), requires that each top-level `describe` block include a story reference somewhere in its description text (for example, a path such as `docs/stories/010.0-PAYMENTS.story.md` or a shorter project-specific alias that your team uses consistently).
212
214
  - `requireTestReqPrefix` (boolean, optional) – When `true` (default), requires each `it`/`test` block name to begin with a requirement identifier in square brackets, such as `[REQ-PAYMENTS-REFUND]`. The exact `REQ-` pattern is shared with the `valid-annotation-format` rule’s requirement ID checks.
213
- - `describePattern` (string, optional) – A JavaScript regular expression **source** (without leading and trailing `/`) that the `describe` description text must match when `requireDescribeStory` is enabled. This lets you enforce a project-specific format such as requiring a canonical story path or a `STORY-` style identifier in the `describe` string. If omitted, a built-in default that loosely matches a typical story path (similar to `docs/stories/<name>.story.md`) is used.
215
+ - `describePattern` (string, optional) – A JavaScript regular expression **source** (without leading and trailing `/`) that the `describe` description text must match when `requireDescribeStory` is enabled. This lets you enforce a project-specific format such as requiring a canonical story path or a `STORY-` style identifier in the `describe` string. If omitted, the default is equivalent to `"Story [0-9]+\\.[0-9]+-"`, which expects the description to include a story label such as `"Story 021.0-DEV-TEST-TRACEABILITY"`. You can override this to instead require full story paths or whatever story-labeling convention your project prefers.
214
216
  - `autoFixTestTemplate` (boolean, optional) – When `true` (default), allows the rule’s `--fix` mode to insert a file-level `@supports` placeholder template at the top of test files that are missing it. The template is intentionally non-semantic and includes TODO-style guidance so humans can later replace it with a real story path and requirement IDs; disabling this option prevents the rule from inserting the template automatically.
215
217
  - `autoFixTestPrefixFormat` (boolean, optional) – When `true` (default), enables safe normalization of malformed `[REQ-XXX]` prefixes in `it`/`test` names during `--fix`. The rule only rewrites prefixes that already contain a recognizable requirement identifier and limits changes to formatting concerns (spacing, square brackets vs. parentheses, underscore and dash usage, and letter casing) without fabricating new IDs or guessing requirement names.
216
218
  - `testSupportsTemplate` (string, optional) – Overrides the default file-level `@supports` placeholder template used when `autoFixTestTemplate` is enabled. This string should be a complete JSDoc-style block (for example, including `/**`, `*`, and `*/`) that encodes your project’s preferred TODO guidance or placeholder story path; it is inserted verbatim at the top of matching test files that lack a `@supports` annotation, and is never interpreted or expanded by the rule.
217
219
 
220
+ You can tune these options to fit your own testing and naming conventions: adjust `testFilePatterns` to match your project’s test layout (including monorepos or non-standard folders), override `describePattern` if you prefer full `docs/stories/...` paths or a different story-labeling scheme in `describe` strings, and change `requireTestReqPrefix` and `autoFixTestPrefixFormat` if you want to relax, enforce, or customize the `[REQ-...]` prefix requirements for test names.
221
+
218
222
  Behavior notes:
219
223
 
220
224
  - The rule only analyzes files whose normalized paths contain at least one of the `testFilePatterns` substrings.
221
225
  - File-level `@supports` annotations are typically placed in a JSDoc block at the top of the file; the rule checks that at least one `@supports` tag is present and that it includes a story/requirement reference (for example, `@supports docs/stories/010.0-PAYMENTS.story.md#REQ-PAYMENTS-REFUND`).
222
- - Top-level `describe` calls (such as `describe("payments refunds docs/stories/010.0-PAYMENTS.story.md", ...)`) are inspected when `requireDescribeStory` is `true`. Their first argument must be a string literal that satisfies `describePattern`.
226
+ - Top-level `describe` calls (such as `describe("Story 010.0-DEV-PAYMENTS", ...)`) are inspected when `requireDescribeStory` is `true`. Their first argument must be a string literal that satisfies `describePattern`.
223
227
  - Test cases declared via `it(...)` or `test(...)` must use a string literal name beginning with a requirement prefix like `[REQ-PAYMENTS-REFUND]` when `requireTestReqPrefix` is `true`.
224
228
 
225
229
  Default Severity: `error`
@@ -242,6 +246,109 @@ describe("Refunds flow docs/stories/010.0-PAYMENTS.story.md", () => {
242
246
  });
243
247
  ```
244
248
 
249
+ ### traceability/prefer-implements-annotation
250
+
251
+ Description: An optional, opt-in migration helper that encourages converting legacy single‑story `@story` + `@req` JSDoc blocks into the newer multi‑story `@supports` format. The rule is **disabled by default** and is **not included in any built‑in preset**; you enable it explicitly and control its behavior entirely via ESLint severity (`"off" | "warn" | "error"`). It does not change what the core rules consider valid—it only adds migration recommendations and safe auto‑fixes on top of existing validation.
252
+
253
+ Options: None – this rule does not accept a configuration object. All tuning is done via the ESLint rule level (`"off"`, `"warn"`, `"error"`).
254
+
255
+ This rule focuses on **single‑story** legacy blocks where automatic migration is unambiguous. It inspects JSDoc comments attached to function‑like constructs and looks for the following patterns:
256
+
257
+ - A single `@story` annotation with one story path.
258
+ - One or more simple `@req` lines in the same block (each with a single requirement ID).
259
+ - No `@supports` annotations yet present in that block.
260
+
261
+ When these conditions are met, the rule recommends replacing the legacy block with a single `@supports` line that encodes the same relationship between the story and its requirements.
262
+
263
+ Main behaviors:
264
+
265
+ 1. **Single‑story legacy blocks → `preferImplements` (auto‑fixable)**
266
+ When a JSDoc block contains exactly one `@story` path and one or more simple `@req` identifiers, and no `@supports` tags, the rule reports a `preferImplements` diagnostic. In `--fix` mode, and when it is safe to do so, it rewrites the block to a consolidated `@supports` annotation of the form:
267
+
268
+ ```js
269
+ /**
270
+ * @supports docs/stories/010.0-PAYMENTS.story.md#REQ-PAYMENTS-REFUND REQ-PAYMENTS-EDGE
271
+ */
272
+ ```
273
+
274
+ Conceptually, the auto‑fix:
275
+ - Extracts the single `@story` value.
276
+ - Collects the requirement IDs from each `@req` line in that block.
277
+ - Emits a single `@supports story-path#REQ-1 REQ-2 ...` line (or your project’s equivalent anchor scheme).
278
+
279
+ All legacy `@story` and `@req` tags in that block are removed as part of the fix, since their meaning is now captured by the `@supports` line. The fix is only applied when the story path and requirement IDs are straightforward to parse; complex or ambiguous shapes are left for manual migration.
280
+
281
+ 2. **Mixed usage with existing `@supports` → `cannotAutoFix` (manual migration)**
282
+ If a JSDoc block already contains at least one `@supports` annotation **and** still has legacy `@story`/`@req` tags, the rule treats this as a mixed‑style block. In this case, it reports a `cannotAutoFix` diagnostic that includes a human‑readable `reason` explaining that the block already uses `@supports` and must be cleaned up manually.
283
+
284
+ The rule **does not** attempt to merge or rewrite mixed blocks automatically, to avoid guessing your intended story/requirement grouping. All annotations in such blocks are left unchanged; you are expected to convert them to your preferred `@supports` shape by hand.
285
+
286
+ 3. **Multiple distinct `@story` paths → `multiStoryDetected` (manual migration)**
287
+ When the same JSDoc block contains **multiple different `@story` paths**, the rule reports a `multiStoryDetected` diagnostic and leaves the block unchanged. This scenario usually indicates integration code that implements requirements from several stories, and the correct multi-story `@supports` representation depends on how your project organizes those relationships.
288
+
289
+ Because there is no universally safe way to automatically group requirements across multiple stories, the rule does **not** attempt any auto‑fix in this case. Instead, it highlights the block so humans can migrate it to one or more explicit `@supports` annotations following your multi‑story conventions.
290
+
291
+ Deliberate non‑targets and ignored comments:
292
+
293
+ - JSDoc blocks that contain **only** `@story`, **only** `@req`, or **only** `@supports` are **not** modified by this rule. They remain valid and continue to be governed solely by the core rules such as `require-story-annotation`, `require-req-annotation`, and `valid-annotation-format`.
294
+ - Inline or line comments like `// @story ...`, `// @req ...`, or `// @supports ...` are intentionally ignored by this migration helper; they are still checked by the underlying validation rules where applicable.
295
+ - Any block that does not match the “single story + simple requirements, no supports” shape is treated conservatively: the rule may report a diagnostic to flag the legacy/mixed pattern, but it will not rewrite comments unless it is clearly safe.
296
+
297
+ Interaction with other rules:
298
+
299
+ - Enabling this rule does **not** change what is required or permitted by:
300
+ - `traceability/valid-annotation-format`
301
+ - `traceability/valid-req-reference`
302
+ - `traceability/require-story-annotation`
303
+ - `traceability/require-req-annotation`
304
+ - All existing `@story` + `@req` blocks that pass those rules are still valid when this rule is off. Turning it on simply adds a migration layer that nudges you toward the consolidated `@supports` style and, where unambiguous, performs structural rewrites on your behalf.
305
+
306
+ Example: single‑story auto‑fix
307
+
308
+ Given this legacy JSDoc block:
309
+
310
+ ```js
311
+ /**
312
+ * @story docs/stories/010.0-PAYMENTS.story.md
313
+ * @req REQ-PAYMENTS-REFUND
314
+ * @req REQ-PAYMENTS-REFUND-EDGE
315
+ */
316
+ function issueRefund() {
317
+ // ...
318
+ }
319
+ ```
320
+
321
+ With `traceability/prefer-implements-annotation` enabled and ESLint run with `--fix`, the rule rewrites it to:
322
+
323
+ ```js
324
+ /**
325
+ * @supports docs/stories/010.0-PAYMENTS.story.md#REQ-PAYMENTS-REFUND REQ-PAYMENTS-REFUND-EDGE
326
+ */
327
+ function issueRefund() {
328
+ // ...
329
+ }
330
+ ```
331
+
332
+ All other function‑level rules (such as `require-story-annotation`, `require-req-annotation`, and `valid-annotation-format`) continue to validate the resulting `@supports` annotation according to your existing configuration.
333
+
334
+ Configuration example (opt‑in at `"warn"`):
335
+
336
+ ```js
337
+ // eslint.config.js (flat config)
338
+ import js from "@eslint/js";
339
+ import traceability from "eslint-plugin-traceability";
340
+
341
+ export default [
342
+ js.configs.recommended,
343
+ traceability.configs.recommended,
344
+ {
345
+ rules: {
346
+ "traceability/prefer-implements-annotation": "warn",
347
+ },
348
+ },
349
+ ];
350
+ ```
351
+
245
352
  ## Configuration Presets
246
353
 
247
354
  The plugin provides two built-in presets for easy configuration:
@@ -84,7 +84,7 @@ Create a Jest test file, for example `tests/dev-test-traceability.spec.ts`:
84
84
  * @supports docs/stories/021.0-DEV-TEST-TRACEABILITY.story.md#REQ-TEST-TRACEABILITY
85
85
  */
86
86
 
87
- describe("docs/stories/021.0-DEV-TEST-TRACEABILITY.story.md", () => {
87
+ describe("Story 021.0-DEV-TEST-TRACEABILITY", () => {
88
88
  it("[REQ-TEST-TRACEABILITY] should handle the primary test scenario", () => {
89
89
  // Arrange
90
90
  const input = "happy-path";
@@ -73,8 +73,41 @@ For teams that want to gradually migrate from `@story` + `@req` to `@supports`,
73
73
  }
74
74
  ```
75
75
 
76
- - When enabled, it offers **conservative auto-fixes** that rewrite eligible `@story` + `@req` combinations into equivalent `@supports` lines, without attempting risky or ambiguous transformations.
77
- - Detailed behavior, limitations, and examples are documented in the project’s internal rule documentation, which is primarily intended for maintainers; most users can rely on this guide and the API reference for day-to-day usage.
76
+ This rule is an **optional migration aid**, not a deprecation notice. `@story` and `@req` remain fully supported, and there is no hard requirement or deadline to migrate existing annotations. Use the rule only where `@supports` gives you clearer, multi-story traceability.
77
+
78
+ When enabled, it offers **conservative auto-fixes** that rewrite eligible `@story` + `@req` combinations into equivalent `@supports` lines, without attempting risky or ambiguous transformations. It intentionally refuses to modify comments that are even slightly unclear, and will instead surface diagnostics that explain what needs manual attention.
79
+
80
+ Aligned with the internal rule behavior, the key cases are:
81
+
82
+ - **Simple, single-story JSDoc blocks**
83
+ For comments that contain exactly one `@story` path and one or more simple `@req` lines, the rule:
84
+ - Reports a recommendation to consolidate them, and
85
+ - In `--fix` mode, converts them into a single `@supports` line that keeps the same story path and requirement IDs.
86
+
87
+ - **Mixed `@story` / `@req` plus existing `@supports`**
88
+ For comments that already contain one or more `@supports` lines alongside `@story` and/or `@req`, the rule:
89
+ - Reports a diagnostic explaining that mixed usage cannot be auto-fixed safely, and
90
+ - Leaves the comment unchanged so you can decide how to migrate it manually.
91
+
92
+ - **Multiple distinct `@story` paths**
93
+ For comments that refer to more than one different `@story` path, the rule:
94
+ - Reports that multiple stories were detected, and
95
+ - Requires you to manually convert them into separate `@supports` lines (one per story path, each followed by the appropriate requirement IDs).
96
+
97
+ - **Intentionally ignored comments**
98
+ The following are **ignored** by this rule and remain valid:
99
+ - Comments that contain only `@story` lines,
100
+ - Comments that contain only `@req` lines,
101
+ - Comments that contain only `@supports` lines, and
102
+ - Line comments such as `// @story ...`.
103
+
104
+ These forms are still supported by the plugin and are not modified by `traceability/prefer-implements-annotation`.
105
+
106
+ A typical migration path is:
107
+
108
+ - Start with the rule set to `"off"` while you introduce `@supports` in new or refactored code.
109
+ - Enable it as `"warn"` to get non-breaking guidance and auto-fixes for straightforward cases.
110
+ - Optionally move to `"error"` once you want to strictly enforce `@supports` usage for all JSDoc blocks that are eligible for safe conversion.
78
111
 
79
112
  #### When to keep `@story` + `@req`
80
113