eslint-plugin-traceability 1.7.1 → 1.8.1

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 (39) hide show
  1. package/CHANGELOG.md +82 -0
  2. package/README.md +76 -37
  3. package/SECURITY.md +132 -0
  4. package/lib/src/index.d.ts +6 -35
  5. package/lib/src/index.js +8 -5
  6. package/lib/src/maintenance/batch.d.ts +5 -0
  7. package/lib/src/maintenance/batch.js +5 -0
  8. package/lib/src/maintenance/cli.js +34 -212
  9. package/lib/src/maintenance/commands.d.ts +32 -0
  10. package/lib/src/maintenance/commands.js +139 -0
  11. package/lib/src/maintenance/detect.d.ts +2 -0
  12. package/lib/src/maintenance/detect.js +4 -0
  13. package/lib/src/maintenance/flags.d.ts +99 -0
  14. package/lib/src/maintenance/flags.js +121 -0
  15. package/lib/src/maintenance/report.d.ts +2 -0
  16. package/lib/src/maintenance/report.js +2 -0
  17. package/lib/src/maintenance/update.d.ts +4 -0
  18. package/lib/src/maintenance/update.js +4 -0
  19. package/lib/src/rules/helpers/require-story-io.d.ts +3 -0
  20. package/lib/src/rules/helpers/require-story-io.js +20 -6
  21. package/lib/src/rules/helpers/valid-annotation-options.js +15 -4
  22. package/lib/src/rules/helpers/valid-annotation-utils.js +5 -0
  23. package/lib/src/rules/helpers/valid-story-reference-helpers.d.ts +3 -4
  24. package/lib/src/utils/reqAnnotationDetection.d.ts +4 -1
  25. package/lib/src/utils/reqAnnotationDetection.js +43 -15
  26. package/lib/tests/config/flat-config-presets-integration.test.d.ts +1 -0
  27. package/lib/tests/config/flat-config-presets-integration.test.js +75 -0
  28. package/lib/tests/maintenance/cli.test.js +89 -0
  29. package/lib/tests/plugin-default-export-and-configs.test.js +0 -2
  30. package/lib/tests/rules/prefer-implements-annotation.test.js +28 -0
  31. package/lib/tests/rules/require-req-annotation.test.js +8 -1
  32. package/lib/tests/rules/require-story-annotation.test.js +9 -4
  33. package/lib/tests/utils/ts-language-options.d.ts +1 -7
  34. package/lib/tests/utils/ts-language-options.js +8 -5
  35. package/package.json +11 -7
  36. package/user-docs/api-reference.md +527 -0
  37. package/user-docs/eslint-9-setup-guide.md +722 -0
  38. package/user-docs/examples.md +74 -0
  39. package/user-docs/migration-guide.md +174 -0
@@ -0,0 +1,527 @@
1
+ # API Reference
2
+
3
+ Created autonomously by [voder.ai](https://voder.ai).
4
+ Applies to eslint-plugin-traceability 1.x releases. For the current published version and detailed changelog, see GitHub Releases: <https://github.com/voder-ai/eslint-plugin-traceability/releases>.
5
+
6
+ Supported runtime: Node.js >=18.18.0, ESLint ^9.0.0
7
+
8
+ Security and dependency hygiene for the published package are enforced by the same CI scripts described in the project README (including `npm audit --omit=dev --audit-level=high` and `dry-aged-deps` checks) to prevent known-vulnerable or stale runtime dependencies from being shipped; additional internal review and maintenance practices exist but are out of scope for normal usage of this plugin.
9
+
10
+ ## Rules
11
+
12
+ Each rule enforces traceability conventions in your code. Below is a summary of each rule exposed by this plugin.
13
+
14
+ In addition to the core `@story` and `@req` annotations, the plugin also understands `@implements` for code that fulfills requirements from multiple stories—for example:
15
+ `@implements docs/stories/010.0-PAYMENTS.story.md#REQ-PAYMENTS-REFUND`.
16
+ For a detailed explanation of `@implements` behavior and validation, see [Migration Guide](migration-guide.md) (section **3.1 Multi-story @implements annotations**) and the corresponding `valid-annotation-format` and `valid-req-reference` rule documentation in the plugin's internal docs.
17
+
18
+ The `prefer-implements-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 `@implements` usage. For rule details and migration guidance, see `docs/rules/prefer-implements-annotation.md`.
19
+
20
+ ### traceability/require-story-annotation
21
+
22
+ Description: Ensures every function declaration has a JSDoc comment with an `@story` annotation referencing the related user story. When you adopt multi-story `@implements` annotations as described in `docs/stories/010.2-DEV-MULTI-STORY-SUPPORT.story.md` and `REQ-REQUIRE-ACCEPTS-IMPLEMENTS`, this rule also accepts `@implements` as an alternative way to prove story coverage, so either `@story` or at least one `@implements` 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 currently fixed but structured for future configurability, and fixes are strictly limited to adding this placeholder annotation without altering the function body or changing any runtime behavior. Selective enabling of different auto-fix behaviors (such as applying fixes only to certain scopes or node types) is planned for a future version.
23
+
24
+ Options:
25
+
26
+ - `scope` (string[], optional) – Controls which function-like node types are required to have @story annotations. Allowed values: "FunctionDeclaration", "FunctionExpression", "MethodDefinition", "TSDeclareFunction", "TSMethodSignature". Default: ["FunctionDeclaration", "FunctionExpression", "MethodDefinition", "TSDeclareFunction", "TSMethodSignature"].
27
+ - `exportPriority` ("all" | "exported" | "non-exported", optional) – Controls whether the rule checks all functions, only exported ones, or only non-exported ones. Default: "all".
28
+
29
+ Default Severity: `error`
30
+ Example:
31
+
32
+ ```javascript
33
+ /**
34
+ * @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
35
+ * @req REQ-ANNOTATION-REQUIRED
36
+ */
37
+ function initAuth() {
38
+ // authentication logic
39
+ }
40
+ ```
41
+
42
+ ### traceability/require-req-annotation
43
+
44
+ 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 `@implements` annotations as described in `docs/stories/010.2-DEV-MULTI-STORY-SUPPORT.story.md` and `REQ-REQUIRE-ACCEPTS-IMPLEMENTS`, this rule also treats `@implements 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.
45
+
46
+ 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.
47
+
48
+ Options:
49
+
50
+ - `scope` (string[], optional) – Controls which function-like node types are required to have @req annotations. Allowed values: "FunctionDeclaration", "FunctionExpression", "MethodDefinition", "TSDeclareFunction", "TSMethodSignature". Default: ["FunctionDeclaration", "FunctionExpression", "MethodDefinition", "TSDeclareFunction", "TSMethodSignature"].
51
+ - `exportPriority` ("all" | "exported" | "non-exported", optional) – Controls whether the rule checks all functions, only exported ones, or only non-exported ones. Default: "all".
52
+
53
+ Default Severity: `error`
54
+ Example (with both `@story` and `@req`, as typically used when both rules are enabled):
55
+
56
+ ```javascript
57
+ /**
58
+ * @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
59
+ * @req REQ-ANNOTATION-REQUIRED
60
+ */
61
+ function initAuth() {
62
+ // authentication logic
63
+ }
64
+ ```
65
+
66
+ ### traceability/require-branch-annotation
67
+
68
+ Description: Ensures significant code branches (if/else, loops, switch cases, try/catch) have both `@story` and `@req` annotations in preceding comments.
69
+ Options:
70
+
71
+ - `branchTypes` (string[], optional) – AST node types that are treated as significant branches for annotation enforcement. Allowed values: "IfStatement", "SwitchCase", "TryStatement", "CatchClause", "ForStatement", "ForOfStatement", "ForInStatement", "WhileStatement", "DoWhileStatement". Default: ["IfStatement", "SwitchCase", "TryStatement", "CatchClause", "ForStatement", "ForOfStatement", "ForInStatement", "WhileStatement", "DoWhileStatement"]. If an invalid branch type is provided, the rule reports a configuration error for each invalid value.
72
+
73
+ Default Severity: `error`
74
+ Example:
75
+
76
+ ```javascript
77
+ // @story docs/stories/004.0-DEV-BRANCH-ANNOTATIONS.story.md
78
+ // @req REQ-BRANCH-DETECTION
79
+ if (error) {
80
+ handleError();
81
+ }
82
+ ```
83
+
84
+ ### traceability/valid-annotation-format
85
+
86
+ 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.
87
+
88
+ Options:
89
+
90
+ This rule accepts an optional configuration object. The primary configuration shape is **nested**:
91
+
92
+ - `story` (object, optional) – Configuration for `@story` values.
93
+ - `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. Defaults to the value returned by `getDefaultStoryPattern()`, which is equivalent to `^docs/stories/.*\.story\.md$`, aligning with the standard `docs/stories/<name>.story.md` convention.
94
+ - `example` (string, optional) – A short example `@story` path shown in error messages when `story.pattern` is configured. Defaults to the value returned by `getDefaultStoryExample()`, `"docs/stories/001.0-EXAMPLE.story.md"`. This value is used **only** for guidance and does not affect validation.
95
+ - `req` (object, optional) – Configuration for `@req` values.
96
+ - `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`.
97
+ - `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 is purely informational and does not participate in matching.
98
+
99
+ For backward compatibility, the rule also supports **flat shorthand** fields that map directly to the nested properties:
100
+
101
+ - `storyPathPattern` (string, optional) – Shorthand for `story.pattern`. If `story.pattern` is provided, it takes precedence over `storyPathPattern`.
102
+ - `storyPathExample` (string, optional) – Shorthand for `story.example`. If `story.example` is provided, it takes precedence over `storyPathExample`.
103
+ - `requirementIdPattern` (string, optional) – Shorthand for `req.pattern`. If `req.pattern` is provided, it takes precedence over `requirementIdPattern`.
104
+ - `requirementIdExample` (string, optional) – Shorthand for `req.example`. If `req.example` is provided, it takes precedence over `requirementIdExample`.
105
+
106
+ Behavior notes:
107
+
108
+ - Patterns are compiled with the `u` flag; invalid patterns cause a rule configuration error.
109
+ - When options are omitted, the rule behaves exactly as in earlier versions, relying on its built‑in defaults and path‑suffix normalization logic only.
110
+ - 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.
111
+
112
+ #### Migration and mixed usage
113
+
114
+ The `valid-annotation-format` rule is intentionally **backward compatible** with existing code that only uses `@story` and `@req`. You can:
115
+
116
+ - Continue using `@story` + `@req` for single-story functions and modules.
117
+ - Introduce `@implements` incrementally for integration code that implements requirements from multiple stories.
118
+ - Mix both styles in the same comment block when needed; the rule validates the format of each annotation independently.
119
+
120
+ Deep requirement checking for both `@req` and `@implements` is handled by the `valid-req-reference` rule in the plugin's internal docs. For step-by-step guidance on when and how to migrate, see:
121
+
122
+ - **Migration guide:** [Migration Guide](migration-guide.md) (section **3.1 Multi-story `@implements` annotations**)
123
+ - **Rule docs:** The `valid-annotation-format` and `valid-req-reference` rule documentation in the plugin's internal docs.
124
+
125
+ Default Severity: `error`
126
+ Example:
127
+
128
+ ```javascript
129
+ /**
130
+ * @story docs/stories/005.0-DEV-VALIDATION.story.md
131
+ * @req REQ-FORMAT-VALIDATION
132
+ */
133
+ function example() {
134
+ // ...
135
+ }
136
+ ```
137
+
138
+ ### traceability/valid-story-reference
139
+
140
+ Description: Checks that the file paths in `@story` annotations point to existing story markdown files.
141
+ Options:
142
+ Configure rule behavior using an options object with these properties:
143
+
144
+ - `storyDirectories` (string[], optional) – One or more directories (relative to the project root) to search for story files. Defaults to `["docs/stories", "stories"]`.
145
+ - `allowAbsolutePaths` (boolean, optional) – When `true`, allows absolute story paths (e.g., `/absolute/path/to/story.story.md`). Defaults to `false`.
146
+ - `requireStoryExtension` (boolean, optional) – When `true` (default), requires the story path to end with `.story.md`. Set to `false` to allow other extensions.
147
+
148
+ Example configuration:
149
+
150
+ ```json
151
+ {
152
+ "rules": {
153
+ "traceability/valid-story-reference": [
154
+ "error",
155
+ {
156
+ "storyDirectories": ["docs/stories", "stories"],
157
+ "allowAbsolutePaths": false,
158
+ "requireStoryExtension": true
159
+ }
160
+ ]
161
+ }
162
+ }
163
+ ```
164
+
165
+ Default Severity: `error`
166
+ Example:
167
+
168
+ ```javascript
169
+ /**
170
+ * @story docs/stories/006.0-DEV-STORY-EXISTS.story.md
171
+ * @req REQ-STORY-EXISTS
172
+ */
173
+ function example() {
174
+ // ...
175
+ }
176
+ ```
177
+
178
+ ### traceability/valid-req-reference
179
+
180
+ Description: Verifies that the IDs used in `@req` annotations match known requirement identifiers.
181
+ Options: None
182
+ Default Severity: `error`
183
+ Example:
184
+
185
+ ```javascript
186
+ /**
187
+ * @story docs/stories/007.0-DEV-REQ-REFERENCE.story.md
188
+ * @req REQ-VALID-REFERENCE
189
+ */
190
+ function example() {
191
+ // ...
192
+ }
193
+ ```
194
+
195
+ ## Configuration Presets
196
+
197
+ The plugin provides two built-in presets for easy configuration:
198
+
199
+ ### recommended
200
+
201
+ Enables the **six core traceability rules** with severities tuned for common usage (most at `error`, with
202
+ `traceability/valid-annotation-format` at `warn` to reduce noise). This `warn` level for `traceability/valid-annotation-format` is intentional to keep early adoption noise low, but you can safely raise it to `error` in projects that want strict enforcement of annotation formatting.
203
+
204
+ The `prefer-implements-annotation` migration rule is **not included** in this (or any) preset and remains disabled by default. If you want to encourage or enforce multi-story `@implements` annotations, you must enable `traceability/prefer-implements-annotation` explicitly in your ESLint configuration and choose an appropriate severity (for example, `"warn"` during migration or `"error"` once fully adopted).
205
+
206
+ Core rules enabled by the `recommended` preset:
207
+
208
+ - `traceability/require-story-annotation`: `error`
209
+ - `traceability/require-req-annotation`: `error`
210
+ - `traceability/require-branch-annotation`: `error`
211
+ - `traceability/valid-annotation-format`: `warn`
212
+ - `traceability/valid-story-reference`: `error`
213
+ - `traceability/valid-req-reference`: `error`
214
+
215
+ Usage:
216
+
217
+ ```javascript
218
+ import js from "@eslint/js";
219
+ import traceability from "eslint-plugin-traceability";
220
+
221
+ export default [js.configs.recommended, traceability.configs.recommended];
222
+ ```
223
+
224
+ ### strict
225
+
226
+ Currently mirrors the **recommended** preset, reserved for future stricter policies. As with the `recommended` preset, the `traceability/prefer-implements-annotation` rule is **not** enabled here by default and must be configured manually if desired.
227
+
228
+ Usage:
229
+
230
+ ```javascript
231
+ import js from "@eslint/js";
232
+ import traceability from "eslint-plugin-traceability";
233
+
234
+ export default [js.configs.recommended, traceability.configs.strict];
235
+ ```
236
+
237
+ ## Maintenance API and CLI
238
+
239
+ The plugin exposes a small maintenance API and a companion CLI, `traceability-maint`, for bulk operations on `@story` annotations. These tools are intentionally minimal and focused on stale **story** references only; requirement-level maintenance and more advanced filtering are planned but **not yet implemented**. All maintenance functions operate only on the local filesystem under the provided root directory; they do not make any network calls or interact with external services.
240
+
241
+ ### Programmatic Maintenance API
242
+
243
+ The maintenance functions are available via the plugin’s `maintenance` export. You can either import the named `maintenance` export directly and destructure the functions you need, or import the default plugin export and access the same functions from `traceability.maintenance`:
244
+
245
+ ```ts
246
+ // Option 1: Named `maintenance` export
247
+ import { maintenance } from "eslint-plugin-traceability";
248
+
249
+ const {
250
+ detectStaleAnnotations,
251
+ updateAnnotationReferences,
252
+ batchUpdateAnnotations,
253
+ verifyAnnotations,
254
+ generateMaintenanceReport,
255
+ } = maintenance;
256
+
257
+ // Option 2: Default plugin export
258
+ import traceability from "eslint-plugin-traceability";
259
+
260
+ const {
261
+ detectStaleAnnotations: detectStaleAnnotations2,
262
+ updateAnnotationReferences: updateAnnotationReferences2,
263
+ batchUpdateAnnotations: batchUpdateAnnotations2,
264
+ verifyAnnotations: verifyAnnotations2,
265
+ generateMaintenanceReport: generateMaintenanceReport2,
266
+ } = traceability.maintenance;
267
+ ```
268
+
269
+ The current maintenance API operates on a **single workspace root** and scans all files beneath that directory. It does not yet accept include/exclude globs or explicit story/requirement lists.
270
+
271
+ #### `detectStaleAnnotations(rootDir)`
272
+
273
+ Scans the workspace for `@story` annotations that point to missing or out-of-project story files.
274
+
275
+ **Parameters:**
276
+
277
+ - `rootDir` (string, required) – Workspace root to scan. This is resolved against `process.cwd()`.
278
+
279
+ **Returns:**
280
+
281
+ - `string[]` – A de-duplicated list of stale story paths exactly as they appear in `@story` annotations.
282
+
283
+ **Behavior notes:**
284
+
285
+ - The function recursively walks all files under `rootDir`.
286
+ - Story paths that would escape the workspace (e.g., path traversal or unsafe absolute paths) are ignored rather than treated as stale.
287
+ - If `rootDir` does not exist or is not a directory, an empty array is returned.
288
+
289
+ #### `updateAnnotationReferences(rootDir, oldPath, newPath)`
290
+
291
+ Performs a targeted text replacement of `@story` values across the workspace.
292
+
293
+ **Parameters:**
294
+
295
+ - `rootDir` (string, required) – Workspace root to update in-place.
296
+ - `oldPath` (string, required) – The story path to search for after `@story`.
297
+ - `newPath` (string, required) – The replacement story path.
298
+
299
+ **Returns:**
300
+
301
+ - `number` – The count of `@story` annotations that were updated.
302
+
303
+ **Behavior notes:**
304
+
305
+ - Only `@story` annotations are modified; `@req` annotations are never changed.
306
+ - Files are only written when the content actually changes.
307
+ - If `rootDir` does not exist or is not a directory, the function returns `0` without modifying anything.
308
+
309
+ #### `batchUpdateAnnotations(rootDir, mappings)`
310
+
311
+ Runs multiple `updateAnnotationReferences` operations in sequence.
312
+
313
+ **Parameters:**
314
+
315
+ - `rootDir` (string, required)
316
+ - `mappings` (array, required) – Array of objects `{ oldPath: string; newPath: string }`.
317
+
318
+ **Returns:**
319
+
320
+ - `number` – The total number of `@story` annotations updated across all mappings.
321
+
322
+ **Behavior notes:**
323
+
324
+ - There is no special batching logic; this helper simply loops over the provided mappings.
325
+ - For each mapping, it calls `updateAnnotationReferences(rootDir, oldPath, newPath)` and sums the counts.
326
+
327
+ #### `verifyAnnotations(rootDir)`
328
+
329
+ Checks whether any stale `@story` annotations exist under the workspace.
330
+
331
+ **Parameters:**
332
+
333
+ - `rootDir` (string, required)
334
+
335
+ **Returns:**
336
+
337
+ - `boolean` – `true` if **no** stale annotations are found, `false` otherwise.
338
+
339
+ **Behavior notes:**
340
+
341
+ - Internally, this function calls `detectStaleAnnotations(rootDir)` and returns `stale.length === 0`.
342
+ - Verification is currently limited to story references; requirement IDs are not re-validated here.
343
+
344
+ #### `generateMaintenanceReport(rootDir)`
345
+
346
+ Generates a simple, text-only report of stale `@story` annotations.
347
+
348
+ **Parameters:**
349
+
350
+ - `rootDir` (string, required)
351
+
352
+ **Returns:**
353
+
354
+ - `string` – A newline-separated list of stale story paths, or an empty string if none are found.
355
+
356
+ **Behavior notes:**
357
+
358
+ - This function is intentionally simple and is used by the CLI to produce human-readable output.
359
+ - It does not write to the filesystem or perform any updates.
360
+
361
+ ### `traceability-maint` CLI
362
+
363
+ The `traceability-maint` CLI wraps the maintenance API for use in scripts and CI. It is typically available via `npx traceability-maint` or as an npm script.
364
+
365
+ These tools are intentionally minimal and focused on stale **story** references only; requirement-level maintenance and more advanced filtering are planned but **not yet implemented**. The CLI currently focuses on stale `@story` annotations only. It does **not** build or consume a separate index file, and it does not yet support requirement-level maintenance.
366
+
367
+ #### General usage
368
+
369
+ ```bash
370
+ traceability-maint <command> [options]
371
+ ```
372
+
373
+ Common options:
374
+
375
+ - `--root <dir>` – Workspace root to scan (defaults to the current working directory).
376
+ - `--json` – For commands that support it, emit machine-readable JSON instead of human-readable text.
377
+ - `--format <text|json>` – Output format for the `report` command only (default: `text`).
378
+ - `--from <oldPath>` – Old story path for the `update` command.
379
+ - `--to <newPath>` – New story path for the `update` command.
380
+ - `--dry-run` – For `update`, estimate impact without modifying any files.
381
+ - `-h`, `--help` – Show command help and exit.
382
+
383
+ Exit codes:
384
+
385
+ - `0` – Success (no stale annotations for detection/verification commands, or command completed successfully).
386
+ - `1` – Stale or invalid annotations detected.
387
+ - `2` – Usage or configuration error (e.g., unknown command, missing required flags).
388
+
389
+ The CLI follows the same security posture as the rest of the plugin: it does not perform network requests, does not invoke the shell with dynamically constructed input, and limits its effects to the local filesystem under the configured root. Its runtime dependencies are covered by the same `npm audit --omit=dev --audit-level=high` and `dry-aged-deps` checks described in the project README.
390
+
391
+ #### Commands
392
+
393
+ ##### `detect`
394
+
395
+ Detects `@story` annotations that reference missing story files under the chosen workspace root.
396
+
397
+ ```bash
398
+ traceability-maint detect --root .
399
+ ```
400
+
401
+ - Output (text):
402
+ - When no stale annotations are found: prints `No stale @story annotations found.`
403
+ - When stale annotations are found: prints each stale story path on its own line, followed by a short summary.
404
+ - Output (JSON with `--json`):
405
+
406
+ ```json
407
+ {
408
+ "root": "/absolute/path/to/workspace",
409
+ "stale": ["missing.story.md", "old/renamed.story.md"]
410
+ }
411
+ ```
412
+
413
+ - Exit code:
414
+ - `0` if no stale annotations are found.
415
+ - `1` if any stale annotations are detected.
416
+
417
+ ##### `verify`
418
+
419
+ Runs a simple verification check using the same logic as `detect` and reports whether any stale `@story` annotations exist.
420
+
421
+ ```bash
422
+ traceability-maint verify --root .
423
+ ```
424
+
425
+ - Output (text):
426
+ - `All traceability annotations under <root> are valid.` when no stale annotations are found.
427
+ - A short message indicating that stale or invalid annotations were detected, with guidance to run `detect` or `report` for details.
428
+ - Exit code:
429
+ - `0` if all annotations pass verification.
430
+ - `1` if any stale annotations are found.
431
+
432
+ > Note: The `verify` command does **not** currently support `--json` output.
433
+
434
+ ##### `report`
435
+
436
+ Generates a plain-text or JSON report of stale story references.
437
+
438
+ ```bash
439
+ # Human-readable text report (default)
440
+ traceability-maint report --root .
441
+
442
+ # JSON report suitable for CI
443
+ traceability-maint report --root . --format json
444
+ ```
445
+
446
+ - Output (text, default):
447
+ - When there are no stale annotations: `No stale @story annotations found. Nothing to report.`
448
+ - When stale annotations exist, a small Markdown-style report, including a header and a list of stale story paths.
449
+ - Output (JSON with `--format json`):
450
+
451
+ ```json
452
+ {
453
+ "root": "/absolute/path/to/workspace",
454
+ "report": "missing.story.md\nold/renamed.story.md"
455
+ }
456
+ ```
457
+
458
+ - Exit code:
459
+ - Always `0` (report generation is considered successful even when stale annotations are present).
460
+
461
+ ##### `update`
462
+
463
+ Updates `@story` annotations that reference a specific path.
464
+
465
+ ```bash
466
+ # Perform an in-place update
467
+ traceability-maint update --root . --from old.path.story.md --to new.path.story.md
468
+
469
+ # Estimate impact without modifying files
470
+ traceability-maint update --root . --from old.path.story.md --to new.path.story.md --dry-run
471
+ ```
472
+
473
+ Required options:
474
+
475
+ - `--from <oldPath>` – The existing story path to replace.
476
+ - `--to <newPath>` – The new story path.
477
+
478
+ Optional options:
479
+
480
+ - `--root <dir>` – Workspace root (defaults to current directory).
481
+ - `--dry-run` – Show an estimated impact without modifying files.
482
+ - `--json` – JSON output for both normal and dry-run modes.
483
+
484
+ Behavior:
485
+
486
+ - When `--dry-run` is **not** provided, the command:
487
+ - Replaces `@story <oldPath>` with `@story <newPath>` across the workspace.
488
+ - Prints a short summary (or a JSON object with `root`, `from`, `to`, and `updated` fields when `--json` is used).
489
+ - Exits with code `0`.
490
+ - When `--dry-run` **is** provided, the command:
491
+ - Does **not** modify any files.
492
+ - Uses `generateMaintenanceReport` to estimate the number of stale annotations before changes.
493
+ - Prints a human-readable summary, or a JSON object of the form:
494
+
495
+ ```json
496
+ {
497
+ "mode": "dry-run",
498
+ "root": "/absolute/path/to/workspace",
499
+ "from": "old.path.story.md",
500
+ "to": "new.path.story.md",
501
+ "estimatedStaleCount": 3
502
+ }
503
+ ```
504
+
505
+ - Exits with code `0`.
506
+
507
+ If `--from` or `--to` is missing, the CLI prints an error, shows the help text, and exits with code `2`.
508
+
509
+ ### Minimal CLI integration example
510
+
511
+ `package.json`:
512
+
513
+ ```json
514
+ {
515
+ "scripts": {
516
+ "traceability:detect": "traceability-maint detect --root .",
517
+ "traceability:verify": "traceability-maint verify --root .",
518
+ "traceability:report": "traceability-maint report --root . --format json > traceability-report.json"
519
+ }
520
+ }
521
+ ```
522
+
523
+ In CI:
524
+
525
+ ```bash
526
+ npm run traceability:verify
527
+ ```