eslint-plugin-traceability 1.15.0 → 1.16.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 (34) hide show
  1. package/CHANGELOG.md +2 -2
  2. package/README.md +61 -13
  3. package/lib/src/index.js +59 -0
  4. package/lib/src/rules/helpers/require-story-core.js +1 -1
  5. package/lib/src/rules/helpers/require-story-helpers.d.ts +10 -3
  6. package/lib/src/rules/helpers/require-story-helpers.js +66 -7
  7. package/lib/src/rules/no-redundant-annotation.js +73 -55
  8. package/lib/src/rules/require-branch-annotation.js +2 -2
  9. package/lib/src/rules/require-req-annotation.js +2 -2
  10. package/lib/src/rules/require-story-annotation.js +8 -3
  11. package/lib/src/rules/require-traceability.js +8 -9
  12. package/lib/src/utils/annotation-checker.js +23 -4
  13. package/lib/tests/cli-error-handling.test.js +10 -1
  14. package/lib/tests/integration/cli-integration.test.js +5 -0
  15. package/lib/tests/integration/require-traceability-aliases.integration.test.js +126 -0
  16. package/lib/tests/plugin-default-export-and-configs.test.js +23 -0
  17. package/lib/tests/rules/auto-fix-behavior-008.test.js +7 -7
  18. package/lib/tests/rules/error-reporting.test.js +1 -1
  19. package/lib/tests/rules/no-redundant-annotation.test.js +20 -0
  20. package/lib/tests/rules/require-story-annotation.test.js +49 -10
  21. package/lib/tests/rules/require-story-helpers.test.js +32 -0
  22. package/lib/tests/rules/require-story-utils.test.d.ts +7 -0
  23. package/lib/tests/rules/require-story-utils.test.js +158 -0
  24. package/lib/tests/utils/annotation-checker-branches.test.d.ts +5 -0
  25. package/lib/tests/utils/annotation-checker-branches.test.js +103 -0
  26. package/lib/tests/utils/annotation-scope-analyzer.test.js +134 -0
  27. package/lib/tests/utils/branch-annotation-helpers.test.js +66 -0
  28. package/package.json +2 -2
  29. package/user-docs/api-reference.md +71 -15
  30. package/user-docs/examples.md +24 -13
  31. package/user-docs/migration-guide.md +127 -4
  32. package/user-docs/traceability-overview.md +116 -0
  33. package/lib/tests/integration/dogfooding-validation.test.js +0 -129
  34. /package/lib/tests/integration/{dogfooding-validation.test.d.ts → require-traceability-aliases.integration.test.d.ts} +0 -0
@@ -11,19 +11,30 @@ Security and dependency hygiene for the published package are enforced by the sa
11
11
 
12
12
  Each rule enforces traceability conventions in your code. Below is a summary of each rule exposed by this plugin.
13
13
 
14
+ For function-level traceability, new configurations should treat `traceability/require-traceability` as the **canonical** rule: it composes both story and requirement checks and understands both the newer `@supports` style and the legacy `@story` / `@req` pairing. The older keys `traceability/require-story-annotation` and `traceability/require-req-annotation` remain available as **backward-compatible aliases** so existing configs keep working, but they are no longer the primary entry points and are mainly useful when you need to tune severities independently. For new and multi-story scenarios, prefer `@supports` annotations; `@story` and `@req` remain valid and are still appropriate for simple single-story code paths where a consolidated `@supports` tag is not yet required.
15
+
14
16
  In addition to the core `@story` and `@req` annotations, the plugin also understands `@supports` for code that fulfills requirements from multiple stories—for example, a consuming project might use a path like
15
17
  `@supports docs/stories/010.0-PAYMENTS.story.md#REQ-PAYMENTS-REFUND`
16
18
  to indicate that a given function supports a particular requirement from a payments story document within that project’s own `docs/stories` tree. For a detailed explanation of `@supports` behavior and validation, see [Migration Guide](migration-guide.md) (section **3.1 Multi-story @supports annotations**). Additional background on multi-story semantics is available in the project’s internal rule documentation, which is intended for maintainers rather than end users.
17
19
 
18
20
  The `prefer-supports-annotation` rule is an **opt-in migration helper** that is disabled by default and **not** part of any built-in preset. It can be enabled and given a severity like `"warn"` or `"error"` using normal ESLint rule configuration when you want to gradually encourage multi-story `@supports` usage. The legacy rule key `traceability/prefer-implements-annotation` remains available as a **deprecated alias** for backward compatibility, but new configurations should prefer `traceability/prefer-supports-annotation`. Detailed behavior and migration guidance are documented in the project’s internal rule documentation, which is targeted for maintainers; typical end users can rely on the high-level guidance in this API reference and the [Migration Guide](migration-guide.md).
19
21
 
22
+ ### Function-level rules overview
23
+
24
+ For function-level traceability, the plugin exposes a unified rule and two legacy keys:
25
+
26
+ - `traceability/require-traceability` is the **canonical function-level rule** for new configurations. It ensures functions and methods have both story coverage and requirement coverage, and it accepts either `@supports` (preferred) or legacy `@story` / `@req` annotations.
27
+ - `traceability/require-story-annotation` and `traceability/require-req-annotation` are **backward-compatible aliases** that focus on the story and requirement aspects separately. They are retained for existing configurations and share the same underlying implementation model as the unified rule, but new ESLint configs should normally rely on `traceability/require-traceability` rather than enabling these legacy keys directly.
28
+
29
+ All three rule keys can still be configured individually if you need fine-grained control (for example, to tune severities separately), but the recommended and strict presets enable `traceability/require-traceability` by default and keep the legacy keys primarily for projects that adopted them before the unified rule existed.
30
+
20
31
  ### traceability/require-traceability
21
32
 
22
33
  Description: Unified function-level traceability rule that composes the behavior of `traceability/require-story-annotation` and `traceability/require-req-annotation`. When enabled, it enforces that in‑scope functions and methods carry both a story reference (`@story` or an equivalent `@supports` tag) and at least one requirement reference (`@req` or, when configured, `@supports`). The recommended flat‑config presets in this plugin enable `traceability/require-traceability` by default alongside the legacy rule keys for backward compatibility, so that existing configurations referring to `traceability/require-story-annotation` or `traceability/require-req-annotation` continue to work without change.
23
34
 
24
35
  ### traceability/require-story-annotation
25
36
 
26
- Description: Ensures every function declaration has a JSDoc comment with an `@story` annotation referencing the related user story. When you adopt multi-story `@supports` annotations, this rule also accepts `@supports` as an alternative way to prove story coverage, so either `@story` or at least one `@supports` tag will satisfy the presence check. When run with `--fix`, the rule inserts a single-line placeholder JSDoc `@story` annotation above missing functions, methods, TypeScript declare functions, and interface method signatures using a built-in template aligned with Story 008.0. This template is now configurable on a per-rule basis, and the rule exposes an explicit auto-fix toggle so you can choose between diagnostic-only behavior and automatic placeholder insertion. The default template remains aligned with Story 008.0, but you can now customize it per rule configuration and optionally disable auto-fix entirely when you only want diagnostics without edits.
37
+ Description: **Legacy function-level key:** This rule key is retained for backward compatibility and conceptually composes the same checks as `traceability/require-traceability`. New configurations should normally enable `traceability/require-traceability` instead and rely on this key only when you need to tune it independently. Ensures every function declaration has a traceability annotation, preferring `@supports` for story coverage while still accepting legacy `@story` annotations referencing the related user story. When you adopt multi-story `@supports` annotations, this rule also accepts `@supports` as an alternative way to prove story coverage, so either `@story` or at least one `@supports` tag will satisfy the presence check. When run with `--fix`, the rule inserts a single-line placeholder JSDoc `@story` annotation above missing functions, methods, TypeScript declare functions, and interface method signatures using a built-in template aligned with Story 008.0. This template is now configurable on a per-rule basis, and the rule exposes an explicit auto-fix toggle so you can choose between diagnostic-only behavior and automatic placeholder insertion. The default template remains aligned with Story 008.0, but you can now customize it per rule configuration and optionally disable auto-fix entirely when you only want diagnostics without edits.
27
38
 
28
39
  Options:
29
40
 
@@ -32,6 +43,7 @@ Options:
32
43
  - `annotationTemplate` (string, optional) – Overrides the default placeholder JSDoc used when inserting missing `@story` annotations for functions and non-method constructs. When omitted or blank, the built-in template from Story 008.0 is used.
33
44
  - `methodAnnotationTemplate` (string, optional) – Overrides the default placeholder JSDoc used when inserting missing `@story` annotations for class methods and TypeScript method signatures. When omitted or blank, falls back to `annotationTemplate` if provided, otherwise the built-in template.
34
45
  - `autoFix` (boolean, optional) – When set to `false`, disables all automatic fix behavior for this rule while retaining its suggestions and diagnostics. When omitted or `true`, the rule behaves as before, inserting placeholder annotations in `--fix` mode.
46
+ - `excludeTestCallbacks` (boolean, optional) – When `true` (default), excludes anonymous arrow functions that are direct callbacks to common test framework functions (for example, Jest/Mocha/Vitest `describe`/`it`/`test`/`beforeEach`/`afterEach`/`beforeAll`/`afterAll`, plus focused/skipped/concurrent variants such as `fdescribe`, `xdescribe`, `fit`, `xit`, `test.concurrent`, `describe.concurrent`) from function-level annotation requirements. This assumes those test files are already covered by file-level `@supports` annotations and `traceability/require-test-traceability`. When set to `false`, these callbacks are treated like any other arrow function and must be annotated when in-scope.
35
47
 
36
48
  Default Severity: `error`
37
49
  Example:
@@ -46,9 +58,11 @@ function initAuth() {
46
58
  }
47
59
  ```
48
60
 
61
+ Among the supported scopes, anonymous callbacks passed directly to common test framework functions are excluded from annotation requirements by default via `excludeTestCallbacks`; projects that prefer stricter enforcement for these callbacks can disable this exclusion by setting `excludeTestCallbacks: false` in their rule configuration.
62
+
49
63
  ### traceability/require-req-annotation
50
64
 
51
- Description: Ensures that function-like constructs consistently declare their linked requirement using an `@req` annotation in JSDoc. The rule targets the same function-like node types as `traceability/require-story-annotation` (standard function declarations, non-arrow function expressions used as callbacks or assignments, class/object methods, TypeScript declare functions, and interface method signatures), and enforces that each of them has at least one `@req` tag in the nearest associated JSDoc comment. When you adopt multi-story `@supports` annotations, this rule also treats `@supports story-path REQ-ID...` tags as satisfying the requirement coverage check, although deep verification of requirement IDs continues to be handled by `traceability/valid-req-reference`. Arrow functions (`ArrowFunctionExpression`) are not currently checked by this rule.
65
+ Description: **Legacy function-level key:** This rule key is retained for backward compatibility and conceptually composes the same checks as `traceability/require-traceability`. New configurations should normally enable `traceability/require-traceability` instead and rely on this key only when you need to tune it independently. Ensures that function-like constructs consistently declare their linked requirements via traceability annotations, preferring `@supports` when possible while still accepting `@req`. The rule targets the same function-like node types as `traceability/require-story-annotation` (standard function declarations, non-arrow function expressions used as callbacks or assignments, class/object methods, TypeScript declare functions, and interface method signatures), and enforces that each of them has at least one `@req` tag in the nearest associated JSDoc comment. When you adopt multi-story `@supports` annotations, this rule also treats `@supports story-path REQ-ID...` tags as satisfying the requirement coverage check, although deep verification of requirement IDs continues to be handled by `traceability/valid-req-reference`. Arrow functions (`ArrowFunctionExpression`) are not currently checked by this rule.
52
66
 
53
67
  This rule is typically used alongside `traceability/require-story-annotation` so that each function-level traceability block includes both an `@story` and an `@req` annotation, but it can also be enabled independently if you only want to enforce requirement linkage. Unlike `traceability/require-story-annotation`, this rule does not currently provide an auto-fix mode for inserting placeholder `@req` annotations; it only reports missing or malformed requirement annotations on the configured scopes.
54
68
 
@@ -72,7 +86,7 @@ function initAuth() {
72
86
 
73
87
  ### traceability/require-branch-annotation
74
88
 
75
- Description: Ensures significant code branches (if/else chains, loops, switch cases, try/catch) have both `@story` and `@req` annotations in nearby comments. When you adopt multi-story `@supports` annotations, a single `@supports <storyPath> <REQ-ID>...` line placed in any of the valid branch comment locations is treated as satisfying both the story and requirement presence checks for that branch, while detailed format validation of the `@supports` value (including story paths and requirement IDs) continues to be handled by `traceability/valid-annotation-format`, `traceability/valid-story-reference`, and `traceability/valid-req-reference`.
89
+ Description: Ensures significant code branches (if/else chains, loops, switch cases, try/catch) have traceability coverage, typically via a single `@supports` line, while still accepting legacy `@story` and `@req` annotations in nearby comments. When you adopt multi-story `@supports` annotations, a single `@supports <storyPath> <REQ-ID>...` line placed in any of the valid branch comment locations is treated as satisfying both the story and requirement presence checks for that branch, while detailed format validation of the `@supports` value (including story paths and requirement IDs) continues to be handled by `traceability/valid-annotation-format`, `traceability/valid-story-reference`, and `traceability/valid-req-reference`.
76
90
 
77
91
  For most branches, the rule looks for annotations in comments immediately preceding the branch keyword (for example, the line above an `if` or `for` statement). For `catch` clauses and `else if` branches, the rule is formatter-aware and accepts annotations in additional positions that common formatters like Prettier use when they reflow code.
78
92
 
@@ -112,7 +126,7 @@ if (error) {
112
126
 
113
127
  ### traceability/valid-annotation-format
114
128
 
115
- 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.
129
+ Description: Validates that all traceability annotations (`@supports` as the preferred form for new code, plus legacy `@story` and `@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.
116
130
 
117
131
  Options:
118
132
 
@@ -150,21 +164,34 @@ The `valid-annotation-format` rule is intentionally **backward compatible** with
150
164
  Deep requirement checking for both `@req` and `@supports` is handled by the `valid-req-reference` rule in the plugin's internal docs. Advanced edge cases and internal semantics are mainly of interest to maintainers; typical end users can rely on the options and examples in this API reference when configuring the rule for their projects.
151
165
 
152
166
  Default Severity: `error`
153
- Example:
167
+
168
+ Primary example (recommended `@supports` style):
169
+
170
+ ```javascript
171
+ /**
172
+ * @supports docs/stories/005.0-DEV-VALIDATION.story.md#REQ-FORMAT-VALIDATION
173
+ */
174
+ function example() {
175
+ // ...
176
+ }
177
+ ```
178
+
179
+ Legacy example (`@story` + `@req`, still valid but not preferred for new code):
154
180
 
155
181
  ```javascript
156
182
  /**
157
183
  * @story docs/stories/005.0-DEV-VALIDATION.story.md
158
184
  * @req REQ-FORMAT-VALIDATION
159
185
  */
160
- function example() {
186
+ function legacyExample() {
161
187
  // ...
162
188
  }
163
189
  ```
164
190
 
165
191
  ### traceability/valid-story-reference
166
192
 
167
- Description: Checks that the file paths in `@story` annotations point to existing story markdown files.
193
+ Description: Checks that the story file paths used by traceability annotations point to existing story markdown files in an `@supports`‑first world. Modern code typically encodes story paths in `@supports` tags (for example, `@supports docs/stories/010.0-PAYMENTS.story.md#REQ-ID`), but this rule continues to operate on the underlying `@story` values for file‑existence checks, keeping legacy annotations and mixed blocks fully supported.
194
+
168
195
  Options:
169
196
  Configure rule behavior using an options object with these properties:
170
197
 
@@ -190,31 +217,57 @@ Example configuration:
190
217
  ```
191
218
 
192
219
  Default Severity: `error`
193
- Example:
220
+
221
+ Primary example (recommended `@supports` style, with a companion `@story` used for existence checks):
222
+
223
+ ```javascript
224
+ /**
225
+ * @supports docs/stories/006.0-DEV-STORY-EXISTS.story.md#REQ-STORY-EXISTS
226
+ * @story docs/stories/006.0-DEV-STORY-EXISTS.story.md // used for file-existence validation; kept for backward compatibility
227
+ */
228
+ function example() {
229
+ // ...
230
+ }
231
+ ```
232
+
233
+ Legacy-only example (`@story` + `@req`, still supported as an input to this rule):
194
234
 
195
235
  ```javascript
196
236
  /**
197
237
  * @story docs/stories/006.0-DEV-STORY-EXISTS.story.md
198
238
  * @req REQ-STORY-EXISTS
199
239
  */
200
- function example() {
240
+ function legacyExample() {
201
241
  // ...
202
242
  }
203
243
  ```
204
244
 
205
245
  ### traceability/valid-req-reference
206
246
 
207
- Description: Verifies that the IDs used in `@req` annotations match known requirement identifiers.
247
+ Description: Verifies that the requirement IDs used in traceability annotations match known requirement identifiers, whether they appear in modern `@supports` tags or in legacy `@req` annotations.
248
+
208
249
  Options: None
209
250
  Default Severity: `error`
210
- Example:
251
+
252
+ Primary example (recommended `@supports` style with requirement IDs):
253
+
254
+ ```javascript
255
+ /**
256
+ * @supports docs/stories/007.0-DEV-REQ-REFERENCE.story.md#REQ-VALID-REFERENCE REQ-VALID-REFERENCE-EDGE
257
+ */
258
+ function example() {
259
+ // ...
260
+ }
261
+ ```
262
+
263
+ Legacy example (`@story` + `@req`, still valid for backward compatibility):
211
264
 
212
265
  ```javascript
213
266
  /**
214
267
  * @story docs/stories/007.0-DEV-REQ-REFERENCE.story.md
215
268
  * @req REQ-VALID-REFERENCE
216
269
  */
217
- function example() {
270
+ function legacyExample() {
218
271
  // ...
219
272
  }
220
273
  ```
@@ -296,12 +349,14 @@ Behavior notes:
296
349
 
297
350
  Default Severity: `warn`
298
351
 
299
- This rule is **not** enabled in the `recommended` or `strict` presets by default. To use it, add it explicitly to your ESLint configuration with an appropriate severity level:
352
+ This rule is enabled at severity `warn` in both the `recommended` and `strict` presets. You can override its behavior in your own configuration — for example, by raising it to `error` for stricter enforcement, or by explicitly disabling it if you prefer to keep statement-level duplication.
353
+
354
+ Configuration example (override preset severity from `warn` to `error`):
300
355
 
301
356
  ```jsonc
302
357
  {
303
358
  "rules": {
304
- "traceability/no-redundant-annotation": "warn",
359
+ "traceability/no-redundant-annotation": "error",
305
360
  },
306
361
  }
307
362
  ```
@@ -327,7 +382,7 @@ Main behaviors:
327
382
 
328
383
  ```js
329
384
  /**
330
- * @supports docs/stories/010.0-PAYMENTS.story.md#REQ-PAYMENTS-REFUND REQ-PAYMENTS-EDGE
385
+ * @supports docs/stories/010.0-PAYMENTS.story.md#REQ-PAYMENTS-REFUND REQ-PAYMENTS-REFUND-EDGE
331
386
  */
332
387
  ```
333
388
 
@@ -432,6 +487,7 @@ Core rules enabled by the `recommended` preset:
432
487
  - `traceability/valid-story-reference`: `error`
433
488
  - `traceability/valid-req-reference`: `error`
434
489
  - `traceability/require-test-traceability`: `error`
490
+ - `traceability/no-redundant-annotation`: `warn`
435
491
 
436
492
  Usage:
437
493
 
@@ -43,7 +43,21 @@ npx eslint "src/**/*.js"
43
43
 
44
44
  ## 3. CLI Invocation Example
45
45
 
46
- You can use the plugin without a config file by specifying rules inline:
46
+ You can use the plugin without a config file by specifying rules inline. The recommended approach for new setups is to use the unified `traceability/require-traceability` rule:
47
+
48
+ ```bash
49
+ npx eslint --no-eslintrc \
50
+ --rule "traceability/require-traceability:error" \
51
+ sample.js
52
+ ```
53
+
54
+ This unified function-level rule enforces both story and requirement coverage via `@supports` (preferred) or, for backward compatibility, via legacy `@story`/`@req` annotations.
55
+
56
+ Replace `sample.js` with your JavaScript or TypeScript file.
57
+
58
+ ### 3.1 Legacy aliases (for existing configurations)
59
+
60
+ If you have older configurations that already refer to the legacy keys `traceability/require-story-annotation` and `traceability/require-req-annotation`, you can still enable them explicitly to avoid breaking those setups:
47
61
 
48
62
  ```bash
49
63
  npx eslint --no-eslintrc \
@@ -53,9 +67,7 @@ npx eslint --no-eslintrc \
53
67
  ```
54
68
 
55
69
  - `--no-eslintrc` tells ESLint to ignore user configs.
56
- - `--rule` options enable the traceability rules you need.
57
-
58
- Replace `sample.js` with your JavaScript or TypeScript file.
70
+ - `--rule` options enable either the unified rule (recommended for new configurations) or the legacy aliases when you must preserve older setups.
59
71
 
60
72
  ## 4. Linting a Specific Directory
61
73
 
@@ -103,6 +115,9 @@ describe("Story 021.0-DEV-TEST-TRACEABILITY", () => {
103
115
  // Act
104
116
  const result = performOperation(input);
105
117
 
118
+ // Assert
119
+ const result = performOperation(input);
120
+
106
121
  // Assert
107
122
  expect(result).toBe("edge-ok");
108
123
  });
@@ -125,13 +140,11 @@ In this version, annotations are placed immediately before each significant bran
125
140
 
126
141
  ```ts
127
142
  function pickCategory(score: number): string {
128
- // @story docs/stories/004.0-DEV-BRANCH-ANNOTATIONS.story.md
129
- // @req REQ-BRANCH-DETECTION
143
+ // @supports docs/stories/004.0-DEV-BRANCH-ANNOTATIONS.story.md REQ-BRANCH-DETECTION
130
144
  if (score >= 80) {
131
145
  return "high";
132
146
  }
133
- // @story docs/stories/026.0-DEV-ELSE-IF-ANNOTATION-POSITION.story.md
134
- // @req REQ-DUAL-POSITION-DETECTION-ELSE-IF
147
+ // @supports docs/stories/026.0-DEV-ELSE-IF-ANNOTATION-POSITION.story.md REQ-DUAL-POSITION-DETECTION-ELSE-IF
135
148
  else if (score >= 50) {
136
149
  return "medium";
137
150
  }
@@ -156,13 +169,11 @@ Prettier may reflow your `else if` line, wrap the condition, or move comments in
156
169
 
157
170
  ```ts
158
171
  function pickCategory(score: number): string {
159
- // @story docs/stories/004.0-DEV-BRANCH-ANNOTATIONS.story.md
160
- // @req REQ-BRANCH-DETECTION
172
+ // @supports docs/stories/004.0-DEV-BRANCH-ANNOTATIONS.story.md REQ-BRANCH-DETECTION
161
173
  if (score >= 80) {
162
174
  return "high";
163
175
  } else if (score >= 50) {
164
- // @story docs/stories/026.0-DEV-ELSE-IF-ANNOTATION-POSITION.story.md
165
- // @req REQ-DUAL-POSITION-DETECTION-ELSE-IF
176
+ // @supports docs/stories/026.0-DEV-ELSE-IF-ANNOTATION-POSITION.story.md REQ-DUAL-POSITION-DETECTION-ELSE-IF
166
177
  return "medium";
167
178
  } else {
168
179
  return "low";
@@ -173,6 +184,6 @@ function pickCategory(score: number): string {
173
184
  Depending on your Prettier version and configuration, the exact layout of the `else if` line and braces may differ, but as long as your annotations are in one of the supported locations, the rule will accept them.
174
185
 
175
186
  - Notes:
176
- - For most branch types, `traceability/require-branch-annotation` associates comments immediately before the branch keyword (such as `if`, `else`, `switch`, `case`) with that branch.
187
+ - For most branch types, `traceability/require-branch-annotation` associates comments immediately before the branch keyword (such as `if`, `else`, `switch`, `case`) with that branch. Branches can be annotated either with a single `@supports` line (preferred), or with the older `@story`/`@req` pair for backward compatibility. The rule treats a valid `@supports` annotation as satisfying both the story and requirement presence checks.
177
188
  - For `catch` clauses and `else if` branches, the rule is formatter-aware and also looks at comments between the condition and the block, as well as the first comment-only lines inside the block body, so you do not need to fight Prettier if it moves your annotations.
178
189
  - When annotations exist in more than one place around an `else if` branch, the rule prefers comments immediately before the `else if` line, then comments between the condition and the block, and finally comments inside the block body, matching the behavior described in the API reference and stories `025.0` and `026.0`.
@@ -46,7 +46,7 @@ The following diff shows a typical migration in **your own project**, where `doc
46
46
 
47
47
  ### 3.1 Multi-story `@supports` annotations
48
48
 
49
- Starting in v1.x, `eslint-plugin-traceability` supports an additional annotation form for integration code that implements requirements from multiple stories in a consuming project. The following snippet shows one example of how you might structure such an annotation in **your** codebase:
49
+ Starting in v1.x, `eslint-plugin-traceability` introduces and prefers the `@supports` annotation for integration code that implements requirements from multiple stories in a consuming project. The following snippet shows one example of how you might structure such an annotation in **your** codebase:
50
50
 
51
51
  ```js
52
52
  /**
@@ -102,10 +102,20 @@ Aligned with the internal rule behavior, the key cases are:
102
102
  The following are **ignored** by this rule and remain valid:
103
103
  - Comments that contain only `@story` lines,
104
104
  - Comments that contain only `@req` lines,
105
- - Comments that contain only `@supports` lines, and
106
- - Line comments such as `// @story ...`.
105
+ - Comments that contain only `@supports` lines.
107
106
 
108
- These forms are still supported by the plugin and are not modified by `traceability/prefer-supports-annotation`.
107
+ Line comments are treated more selectively:
108
+ - Simple, consecutive line comments such as:
109
+
110
+ ```js
111
+ // @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
112
+ // @req REQ-ANNOTATION-REQUIRED
113
+ function initAuth() {}
114
+ ```
115
+
116
+ that are directly attached to a function, method, or branch and describe exactly one story path plus one or more requirement IDs can now be migrated automatically. When the rule is enabled and you run ESLint with `--fix`, these are consolidated into a single `// @supports ...` line that preserves the same story path and requirement IDs.
117
+
118
+ - More complex inline patterns — for example, mixed traceability and non-traceability content, multiple distinct `@story` paths, or interleaved unrelated comments between `@story` and `@req` lines — are still reported but are **not** auto-fixed. In these cases, the rule continues to treat unsupported inline shapes conservatively, emitting diagnostics and leaving the comments unchanged so you can adjust them manually.
109
119
 
110
120
  A typical migration path is:
111
121
 
@@ -133,6 +143,8 @@ export function initAuth() {
133
143
  }
134
144
  ```
135
145
 
146
+ These `@story` and `@req` forms are treated as a legacy single-story style that remains valid for simple cases, while new multi-story integrations should prefer `@supports` as the primary format.
147
+
136
148
  #### When to introduce `@supports`
137
149
 
138
150
  Adopt `@supports` for **multi-story integration** code, especially when:
@@ -183,6 +195,7 @@ You can introduce `@supports` gradually without breaking existing code:
183
195
 
184
196
  1. Leave existing `@story` and `@req` annotations in place.
185
197
  2. Add `@supports` lines that group requirements by story file.
198
+ Over time, teams are encouraged to converge on `@supports` as the canonical format for multi-story integrations, keeping `@story`/`@req` primarily for simple, single-story cases.
186
199
  3. Run ESLint with `traceability/valid-annotation-format` and `traceability/valid-req-reference` enabled to confirm everything passes.
187
200
  4. Optionally, once you are comfortable, standardize on using `@supports` for multi-story integration functions while keeping `@story` + `@req` for simple, single-story code.
188
201
 
@@ -197,6 +210,116 @@ Versions 1.x of `eslint-plugin-traceability` extend the `traceability/require-br
197
210
 
198
211
  If you previously added suppressions or workaround comments around `else if` branches due to formatter conflicts, you can usually remove those workarounds after upgrading to 1.x as long as your annotations live in one of the supported locations. For new code, you can place annotations either directly above the `else if` or, when you know a formatter will wrap a long condition, on the first comment-only line inside the consequent block body, which is where the rule places auto-fix placeholders by default.
199
212
 
213
+ ### 3.3 Redundant traceability annotation cleanup
214
+
215
+ As you move toward an **`@supports`-first** style while still supporting legacy `@story`/`@req`, v1.x adds `traceability/no-redundant-annotation` to help clean up redundant **statement-level** annotations that often accumulate during migration and refactoring.
216
+
217
+ This rule is enabled as `"warn"` in the built-in recommended presets, so you automatically get guidance without breaking existing builds.
218
+
219
+ At a high level, the rule targets common duplication patterns where multiple adjacent statements or branches repeat the **same story/requirement coverage**, for example:
220
+
221
+ - **Branch + statement duplication** — the `if`/`else` branch is annotated, and the first statement inside the block repeats the exact same coverage.
222
+ - **Sequential simple statements** — back‑to‑back statements each carry identical traceability, even though they form a single logical step.
223
+ - **Trivial returns** — a branch and an immediately returning statement both repeat the same story/requirement pair.
224
+
225
+ In all cases, the rule is conservative:
226
+
227
+ - It **never removes the last annotation** that provides coverage for a given `(story path, requirement ID)` pair.
228
+ - It prefers to keep annotations in the positions that are easiest to reason about (for example, on the controlling branch or on the first statement in a short sequence), and trims only clearly redundant copies.
229
+
230
+ The rule operates over both `@supports` and legacy `@story`/`@req` style annotations, so it continues to work even in mixed codebases during a long-running migration.
231
+
232
+ A simplified example, using an illustrative story path that represents a file in **your** documentation tree:
233
+
234
+ Before (redundant duplication inside a branch):
235
+
236
+ ```js
237
+ if (!user) {
238
+ // @supports docs/stories/010.0-AUTH-SESSION-MANAGEMENT.story.md REQ-UNAUTH-REDIRECT
239
+ // @supports docs/stories/010.0-AUTH-SESSION-MANAGEMENT.story.md REQ-UNAUTH-REDIRECT
240
+ return redirectToLogin();
241
+ }
242
+ ```
243
+
244
+ After (`no-redundant-annotation` auto-fix, coverage preserved but duplication removed):
245
+
246
+ ```js
247
+ if (!user) {
248
+ // @supports docs/stories/010.0-AUTH-SESSION-MANAGEMENT.story.md REQ-UNAUTH-REDIRECT
249
+ return redirectToLogin();
250
+ }
251
+ ```
252
+
253
+ Another example where the branch and first statement are both annotated with the same coverage:
254
+
255
+ Before:
256
+
257
+ ```js
258
+ // @supports docs/stories/020.0-ORDERS-CHECKOUT.story.md REQ-CALCULATE-TOTAL
259
+ if (cart.items.length === 0) {
260
+ // @supports docs/stories/020.0-ORDERS-CHECKOUT.story.md REQ-CALCULATE-TOTAL
261
+ return 0;
262
+ }
263
+ ```
264
+
265
+ After (keep coverage at the branch, drop the redundant inner statement annotation):
266
+
267
+ ```js
268
+ // @supports docs/stories/020.0-ORDERS-CHECKOUT.story.md REQ-CALCULATE-TOTAL
269
+ if (cart.items.length === 0) {
270
+ return 0;
271
+ }
272
+ ```
273
+
274
+ #### Safe migration workflow
275
+
276
+ To use `traceability/no-redundant-annotation` safely during your v1.x migration:
277
+
278
+ 1. **Start from the recommended preset**
279
+
280
+ Make sure your ESLint flat config includes the plugin’s recommended config (which enables this rule as `"warn"`):
281
+
282
+ ```js
283
+ import traceability from "eslint-plugin-traceability";
284
+
285
+ export default [traceability.configs.recommended];
286
+ ```
287
+
288
+ 2. **Run ESLint without auto-fix**
289
+
290
+ Run ESLint without `--fix` to review the warnings:
291
+
292
+ ```bash
293
+ npm run lint
294
+ ```
295
+
296
+ Look for diagnostics from `traceability/no-redundant-annotation` and confirm that the suggested removals match your expectations.
297
+
298
+ 3. **Run with `--fix` once comfortable**
299
+
300
+ When you are satisfied with the behavior, re-run ESLint with auto-fix enabled to apply safe cleanups in bulk:
301
+
302
+ ```bash
303
+ npm run lint -- --fix
304
+ ```
305
+
306
+ 4. **Optionally tighten over time**
307
+
308
+ As your team gets comfortable:
309
+ - You can raise the rule severity to `"error"` for new code, and/or
310
+ - Increase strictness via configuration (see below) to catch more subtle forms of duplication.
311
+
312
+ #### Key configuration knobs
313
+
314
+ The full API reference documents all options, but the most important knobs for migration are:
315
+
316
+ - **`strictness`** — controls how aggressively the rule interprets “redundant.” Lower settings only remove obvious duplication; higher levels consider more complex patterns across nearby statements and branches.
317
+ - **`allowEmphasisDuplication`** — when `true`, allows an explicit “emphasis” annotation to repeat coverage (for example, keeping a second comment in a particularly critical spot) without being reported as redundant.
318
+ - **`maxScopeDepth`** — limits how far into nested blocks the rule looks when deciding what is redundant, which can be useful if you want very local cleanups only.
319
+ - **`alwaysCovered`** — a safety valve that forces the rule to preserve at least one annotation for each `(story, requirement)` pair within the relevant scope, even under stricter modes.
320
+
321
+ For most teams, the defaults in the recommended preset are a good starting point; you can then tune these options incrementally as your traceability style and `@supports` usage stabilize.
322
+
200
323
  ## 4. Test and Validate
201
324
 
202
325
  Run your test suite to confirm everything passes:
@@ -0,0 +1,116 @@
1
+ # Traceability Overview and FAQ
2
+
3
+ Created autonomously by [voder.ai](https://voder.ai).
4
+
5
+ This page gives a high-level overview of how to use `eslint-plugin-traceability` in day-to-day development and answers common questions about annotations, rules, and their relationship to legacy aliases.
6
+
7
+ For detailed rule and option descriptions, see the [API Reference](api-reference.md). For concrete code samples, see the [Examples](examples.md) document.
8
+
9
+ ## Which annotations should I use?
10
+
11
+ The plugin understands three annotation forms:
12
+
13
+ - `@supports` – **Preferred for new code and multi-story integrations.**
14
+ Use this when a function, module, or branch implements requirements from one or more stories. A single `@supports` tag can express both the story path and the requirement IDs it implements.
15
+ - `@story` – Legacy story-level tag.
16
+ Still valid and useful when a function is tied to a single story file and you have not yet migrated to `@supports`.
17
+ - `@req` – Legacy requirement-level tag.
18
+ Pairs naturally with `@story` for simple, single-story scenarios.
19
+
20
+ Recommended usage:
21
+
22
+ - For **new or refactored code**, prefer `@supports` as your primary annotation.
23
+ - For **simple, single-story functions** that already use `@story` + `@req`, you can keep that style; there is no forced cut-over.
24
+ - During migration, you can temporarily have both `@story`/`@req` and `@supports` in the same block; the core rules and the optional `traceability/prefer-supports-annotation` rule are designed to support this.
25
+
26
+ The [Migration Guide](migration-guide.md) explains when and how to introduce `@supports` in more detail, including conservative auto-fix behavior.
27
+
28
+ ## Which ESLint rule should I enable for functions?
29
+
30
+ For function-level checks, think in terms of a single canonical rule plus a small set of supporting rules.
31
+
32
+ - `traceability/require-traceability` – **Canonical function-level rule for new configurations.**
33
+ Ensures that in-scope functions and methods have both story and requirement coverage. It understands both `@supports` (preferred) and legacy `@story` / `@req` annotations.
34
+
35
+ Most users can choose one of these options:
36
+
37
+ 1. **Use the recommended preset** (simplest):
38
+
39
+ ```js
40
+ // eslint.config.js
41
+ import js from "@eslint/js";
42
+ import traceability from "eslint-plugin-traceability";
43
+
44
+ export default [js.configs.recommended, traceability.configs.recommended];
45
+ ```
46
+
47
+ This enables `traceability/require-traceability` and the other core rules with sensible defaults.
48
+
49
+ 2. **Manually enable the unified rule and common helpers** (when you need custom tuning):
50
+
51
+ ```js
52
+ // eslint.config.js
53
+ import traceability from "eslint-plugin-traceability";
54
+
55
+ export default [
56
+ {
57
+ plugins: { traceability },
58
+ rules: {
59
+ // Canonical function-level rule
60
+ "traceability/require-traceability": "error",
61
+
62
+ // Common supporting rules
63
+ "traceability/require-branch-annotation": "warn",
64
+ "traceability/valid-annotation-format": "error",
65
+ "traceability/valid-story-reference": "error",
66
+ "traceability/valid-req-reference": "error",
67
+
68
+ // Optional: enforce test traceability conventions
69
+ "traceability/require-test-traceability": "warn",
70
+ },
71
+ },
72
+ ];
73
+ ```
74
+
75
+ The same guidance is summarized in the README under **"Canonical function-level rule and legacy aliases"**.
76
+
77
+ ## What about the legacy alias rules?
78
+
79
+ Two additional rule keys exist for backward compatibility:
80
+
81
+ - `traceability/require-story-annotation`
82
+ - `traceability/require-req-annotation`
83
+
84
+ Key points:
85
+
86
+ - They are **legacy aliases** that share the same underlying engine as `traceability/require-traceability`.
87
+ - They are kept so that older configurations continue to work without change.
88
+ - New configurations should **not** rely on these keys directly unless you have a specific reason to tune their severities independently.
89
+
90
+ If you are starting from scratch, you can safely ignore the legacy keys and use only `traceability/require-traceability` together with the supporting rules listed above.
91
+
92
+ ## Do I have to migrate existing `@story` / `@req` annotations to `@supports`?
93
+
94
+ No. Existing `@story` + `@req` annotations remain valid and fully supported.
95
+
96
+ Typical migration path:
97
+
98
+ 1. Keep your current `@story` + `@req` annotations for simple, single-story functions.
99
+ 2. Introduce `@supports` gradually for integration code that naturally spans multiple stories.
100
+ 3. Optionally enable `traceability/prefer-supports-annotation` at `"warn"` to get gentle guidance and conservative auto-fixes for straightforward single-story blocks.
101
+ 4. Once you are comfortable, you can tighten enforcement or standardize on `@supports` for new multi-story work.
102
+
103
+ See the [Migration Guide](migration-guide.md#31-multi-story-supports-annotations) for concrete before/after examples.
104
+
105
+ ## Where can I see concrete examples?
106
+
107
+ - **Quick start and minimal config:** See the main [README](../README.md#quick-start).
108
+ - **Full rule list and options:** See the [API Reference](api-reference.md#rules).
109
+ - **End-to-end examples:** See the [Examples](examples.md) document, including:
110
+ - Flat-config snippets using the recommended and strict presets.
111
+ - CLI usage with the unified rule and clearly labeled legacy-alias examples.
112
+ - Test traceability examples using `traceability/require-test-traceability`.
113
+ - Branch annotation patterns that work well with formatters such as Prettier.
114
+ - **Migration guidance:** See the [Migration Guide](migration-guide.md).
115
+
116
+ These resources are designed to be complementary: start with this overview to choose the right annotations and rules, then refer to the API reference and examples when you need exact configuration shapes or runnable code samples.