eslint-plugin-traceability 1.14.1 → 1.15.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.
package/CHANGELOG.md CHANGED
@@ -1,9 +1,9 @@
1
- ## [1.14.1](https://github.com/voder-ai/eslint-plugin-traceability/compare/v1.14.0...v1.14.1) (2025-12-08)
1
+ # [1.15.0](https://github.com/voder-ai/eslint-plugin-traceability/compare/v1.14.1...v1.15.0) (2025-12-08)
2
2
 
3
3
 
4
- ### Bug Fixes
4
+ ### Features
5
5
 
6
- * implement branch and function behaviors for branch annotations story ([00f9655](https://github.com/voder-ai/eslint-plugin-traceability/commit/00f9655c8a284278d69c7d09d106a340ada57827))
6
+ * add unified require-traceability rule and exports ([c92ce8f](https://github.com/voder-ai/eslint-plugin-traceability/commit/c92ce8f467cc4968dc2dea2abb0927eca08c9ace))
7
7
 
8
8
  # Changelog
9
9
 
package/lib/src/index.js CHANGED
@@ -11,6 +11,7 @@ const maintenance_1 = require("./maintenance");
11
11
  * @req REQ-RULE-LIST - Enumerate supported rule file names for plugin discovery
12
12
  */
13
13
  const RULE_NAMES = [
14
+ "require-traceability",
14
15
  "require-story-annotation",
15
16
  "require-req-annotation",
16
17
  "require-branch-annotation",
@@ -150,6 +151,7 @@ const plugin = {
150
151
  * while formatting issues are reported as warnings, matching the story's severity conventions.
151
152
  */
152
153
  const TRACEABILITY_RULE_SEVERITIES = {
154
+ "traceability/require-traceability": "error",
153
155
  "traceability/require-story-annotation": "error",
154
156
  "traceability/require-req-annotation": "error",
155
157
  "traceability/require-branch-annotation": "error",
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Composite ESLint rule that enforces both story and requirement traceability
3
+ * annotations on functions and methods.
4
+ *
5
+ * Implements Story 003.0-DEV-FUNCTION-ANNOTATIONS with:
6
+ * - REQ-ANNOTATION-REQUIRED
7
+ * - REQ-FUNCTION-DETECTION
8
+ * - REQ-CONFIGURABLE-SCOPE
9
+ * - REQ-EXPORT-PRIORITY
10
+ * - REQ-ERROR-LOCATION
11
+ * - REQ-TYPESCRIPT-SUPPORT
12
+ *
13
+ * via composition of:
14
+ * - ./require-story-annotation
15
+ * - ./require-req-annotation
16
+ */
17
+ import type { Rule } from "eslint";
18
+ declare const rule: Rule.RuleModule;
19
+ export default rule;
@@ -0,0 +1,73 @@
1
+ "use strict";
2
+ /**
3
+ * Composite ESLint rule that enforces both story and requirement traceability
4
+ * annotations on functions and methods.
5
+ *
6
+ * Implements Story 003.0-DEV-FUNCTION-ANNOTATIONS with:
7
+ * - REQ-ANNOTATION-REQUIRED
8
+ * - REQ-FUNCTION-DETECTION
9
+ * - REQ-CONFIGURABLE-SCOPE
10
+ * - REQ-EXPORT-PRIORITY
11
+ * - REQ-ERROR-LOCATION
12
+ * - REQ-TYPESCRIPT-SUPPORT
13
+ *
14
+ * via composition of:
15
+ * - ./require-story-annotation
16
+ * - ./require-req-annotation
17
+ */
18
+ var __importDefault = (this && this.__importDefault) || function (mod) {
19
+ return (mod && mod.__esModule) ? mod : { "default": mod };
20
+ };
21
+ Object.defineProperty(exports, "__esModule", { value: true });
22
+ const require_story_annotation_1 = __importDefault(require("./require-story-annotation"));
23
+ const require_req_annotation_1 = __importDefault(require("./require-req-annotation"));
24
+ const storyRule = require_story_annotation_1.default;
25
+ const reqRule = require_req_annotation_1.default;
26
+ const rule = {
27
+ meta: {
28
+ type: "problem",
29
+ docs: {
30
+ description: "Require @story and @req (or @supports) annotations on functions and methods",
31
+ recommended: "error",
32
+ },
33
+ hasSuggestions: Boolean(storyRule.meta?.hasSuggestions) ||
34
+ Boolean(reqRule.meta?.hasSuggestions),
35
+ fixable: (storyRule.meta && storyRule.meta.fixable) ||
36
+ (reqRule.meta && reqRule.meta.fixable) ||
37
+ undefined,
38
+ messages: {
39
+ ...(storyRule.meta?.messages ?? {}),
40
+ ...(reqRule.meta?.messages ?? {}),
41
+ },
42
+ schema: (storyRule.meta && storyRule.meta.schema) ??
43
+ (reqRule.meta && reqRule.meta.schema) ??
44
+ [],
45
+ },
46
+ create(context) {
47
+ const storyListeners = storyRule.create(context) || {};
48
+ const reqListeners = reqRule.create(context) || {};
49
+ const mergedListener = {};
50
+ const allEventNames = new Set([
51
+ ...Object.keys(storyListeners),
52
+ ...Object.keys(reqListeners),
53
+ ]);
54
+ for (const eventName of allEventNames) {
55
+ const storyHandler = storyListeners[eventName];
56
+ const reqHandler = reqListeners[eventName];
57
+ if (storyHandler && reqHandler) {
58
+ mergedListener[eventName] = function mergedHandler(...args) {
59
+ storyHandler.apply(this, args);
60
+ reqHandler.apply(this, args);
61
+ };
62
+ }
63
+ else if (storyHandler) {
64
+ mergedListener[eventName] = storyHandler;
65
+ }
66
+ else if (reqHandler) {
67
+ mergedListener[eventName] = reqHandler;
68
+ }
69
+ }
70
+ return mergedListener;
71
+ },
72
+ };
73
+ exports.default = rule;
@@ -61,6 +61,7 @@ describe("Flat config presets integration (Story 002.0-DEV-ESLINT-CONFIG)", () =
61
61
  const code = "function foo() {}";
62
62
  const result = await lintTextWithConfig(code, config);
63
63
  const ruleIds = result.messages.map((m) => m.ruleId).sort();
64
+ expect(ruleIds).toContain("traceability/require-traceability");
64
65
  expect(ruleIds).toContain("traceability/require-story-annotation");
65
66
  });
66
67
  it("[REQ-CONFIG-PRESETS] strict preset also enables traceability rules via documented usage", async () => {
@@ -68,6 +69,7 @@ describe("Flat config presets integration (Story 002.0-DEV-ESLINT-CONFIG)", () =
68
69
  const code = "function bar() {}";
69
70
  const result = await lintTextWithConfig(code, config);
70
71
  const ruleIds = result.messages.map((m) => m.ruleId).sort();
72
+ expect(ruleIds).toContain("traceability/require-traceability");
71
73
  expect(ruleIds).toContain("traceability/require-story-annotation");
72
74
  });
73
75
  });
@@ -51,6 +51,7 @@ describe("Plugin Default Export and Configs (Story 001.0-DEV-PLUGIN-SETUP)", ()
51
51
  it("[REQ-PLUGIN-STRUCTURE] rules object has correct rule names", () => {
52
52
  // Arrange: expected rule names in insertion order
53
53
  const expected = [
54
+ "require-traceability",
54
55
  "require-story-annotation",
55
56
  "require-req-annotation",
56
57
  "require-branch-annotation",
@@ -69,6 +70,7 @@ describe("Plugin Default Export and Configs (Story 001.0-DEV-PLUGIN-SETUP)", ()
69
70
  });
70
71
  it("[REQ-RULE-REGISTRY] configs.recommended contains correct rule configuration", () => {
71
72
  const recommendedRules = index_1.configs.recommended[0].rules;
73
+ expect(recommendedRules).toHaveProperty("traceability/require-traceability", "error");
72
74
  expect(recommendedRules).toHaveProperty("traceability/require-story-annotation", "error");
73
75
  expect(recommendedRules).toHaveProperty("traceability/require-req-annotation", "error");
74
76
  expect(recommendedRules).toHaveProperty("traceability/require-branch-annotation", "error");
@@ -80,6 +82,7 @@ describe("Plugin Default Export and Configs (Story 001.0-DEV-PLUGIN-SETUP)", ()
80
82
  it("[REQ-ERROR-SEVERITY] configs.recommended maps valid-annotation-format to warn and others to error", () => {
81
83
  const recommendedRules = index_1.configs.recommended[0].rules;
82
84
  expect(recommendedRules).toHaveProperty("traceability/valid-annotation-format", "warn");
85
+ expect(recommendedRules).toHaveProperty("traceability/require-traceability", "error");
83
86
  expect(recommendedRules).toHaveProperty("traceability/require-story-annotation", "error");
84
87
  expect(recommendedRules).toHaveProperty("traceability/require-req-annotation", "error");
85
88
  expect(recommendedRules).toHaveProperty("traceability/require-branch-annotation", "error");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eslint-plugin-traceability",
3
- "version": "1.14.1",
3
+ "version": "1.15.0",
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",
@@ -17,6 +17,10 @@ to indicate that a given function supports a particular requirement from a payme
17
17
 
18
18
  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
19
 
20
+ ### traceability/require-traceability
21
+
22
+ 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
+
20
24
  ### traceability/require-story-annotation
21
25
 
22
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.
@@ -135,8 +139,6 @@ Behavior notes:
135
139
  - When options are omitted, the rule behaves exactly as in earlier versions, relying on its built‑in defaults and path‑suffix normalization logic only.
136
140
  - 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.
137
141
 
138
- 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).
139
-
140
142
  #### Migration and mixed usage
141
143
 
142
144
  The `valid-annotation-format` rule is intentionally **backward compatible** with existing code that only uses `@story` and `@req`. You can:
@@ -306,7 +308,7 @@ This rule is **not** enabled in the `recommended` or `strict` presets by default
306
308
 
307
309
  ### traceability/prefer-supports-annotation
308
310
 
309
- 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 builtin 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. The legacy rule key `traceability/prefer-implements-annotation` is still recognized as a **deprecated alias** for `traceability/prefer-supports-annotation` so that existing configurations continue to work unchanged.
311
+ 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. The legacy rule key `traceability/prefer-implements-annotation` is still recognized as a **deprecated alias** for `traceability/prefer-supports-annotation` so that existing configurations continue to work unchanged.
310
312
 
311
313
  Options: None – this rule does not accept a configuration object. All tuning is done via the ESLint rule level (`"off"`, `"warn"`, `"error"`).
312
314
 
@@ -349,7 +351,7 @@ Main behaviors:
349
351
  Deliberate non‑targets and ignored comments:
350
352
 
351
353
  - 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`.
352
- - Inline or line comments like `// @story ...`, `// @req ...`, or `// @supports ...` are also supported in a limited, migration‑oriented way: when the rule detects a simple, consecutive pair or small run of `// @story ...` and `// @req ...` lines that are directly attached to a function or branch, it can, in `--fix` mode, consolidate them into a single `// @supports ...` line while preserving indentation and the comment’s relative position next to the code. More complex inline patterns (such as mixed traceability and nontraceability content, multiple distinct stories, or interleaved unrelated comments) are still reported without auto‑fix for safety. As with JSDoc migration, this behavior is opt‑in: the rule remains disabled by default and must be explicitly enabled with your desired severity when you are ready to start migrating inline annotations.
354
+ - Inline or line comments like `// @story ...`, `// @req ...`, or `// @supports ...` are also supported in a limited, migration‑oriented way: when the rule detects a simple, consecutive pair or small run of `// @story ...` and `// @req ...` lines that are directly attached to a function or branch, it can, in `--fix` mode, consolidate them into a single `// @supports ...` line while preserving indentation and the comment’s relative position next to the code. More complex inline patterns (such as mixed traceability and non-traceability content, multiple distinct stories, or interleaved unrelated comments) are still reported without auto‑fix for safety. As with JSDoc migration, this behavior is opt‑in: the rule remains disabled by default and must be explicitly enabled with your desired severity when you are ready to start migrating inline annotations.
353
355
  - 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.
354
356
 
355
357
  Interaction with other rules:
@@ -422,8 +424,9 @@ The `prefer-supports-annotation` migration rule (and its deprecated alias key `t
422
424
 
423
425
  Core rules enabled by the `recommended` preset:
424
426
 
425
- - `traceability/require-story-annotation`: `error`
426
- - `traceability/require-req-annotation`: `error`
427
+ - `traceability/require-traceability`: `error` (unified function-level rule; composes story + req checks)
428
+ - `traceability/require-story-annotation`: `error` (legacy key; kept for backward compatibility)
429
+ - `traceability/require-req-annotation`: `error` (legacy key; kept for backward compatibility)
427
430
  - `traceability/require-branch-annotation`: `error`
428
431
  - `traceability/valid-annotation-format`: `warn`
429
432
  - `traceability/valid-story-reference`: `error`