eslint-plugin-traceability 1.8.1 → 1.8.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 (44) hide show
  1. package/CHANGELOG.md +4 -4
  2. package/README.md +4 -4
  3. package/SECURITY.md +40 -37
  4. package/lib/src/maintenance/cli.js +12 -16
  5. package/lib/src/maintenance/detect.js +28 -1
  6. package/lib/src/rules/helpers/require-story-io.d.ts +2 -2
  7. package/lib/src/rules/helpers/require-story-io.js +13 -13
  8. package/lib/src/rules/helpers/valid-annotation-format-internal.d.ts +2 -2
  9. package/lib/src/rules/helpers/valid-annotation-format-internal.js +3 -3
  10. package/lib/src/rules/helpers/valid-annotation-utils.d.ts +5 -0
  11. package/lib/src/rules/helpers/valid-annotation-utils.js +43 -5
  12. package/lib/src/rules/helpers/valid-implements-utils.d.ts +11 -11
  13. package/lib/src/rules/helpers/valid-implements-utils.js +11 -11
  14. package/lib/src/rules/helpers/valid-story-reference-helpers.js +19 -0
  15. package/lib/src/rules/prefer-implements-annotation.d.ts +7 -7
  16. package/lib/src/rules/prefer-implements-annotation.js +21 -21
  17. package/lib/src/rules/valid-annotation-format.js +50 -24
  18. package/lib/src/rules/valid-req-reference.js +9 -9
  19. package/lib/src/utils/annotation-checker.js +3 -1
  20. package/lib/src/utils/reqAnnotationDetection.d.ts +2 -2
  21. package/lib/src/utils/reqAnnotationDetection.js +28 -28
  22. package/lib/tests/maintenance/batch.test.js +11 -11
  23. package/lib/tests/maintenance/cli.test.js +34 -27
  24. package/lib/tests/maintenance/report.test.js +7 -7
  25. package/lib/tests/rules/prefer-implements-annotation.test.js +27 -22
  26. package/lib/tests/rules/require-branch-annotation.test.js +15 -36
  27. package/lib/tests/rules/require-req-annotation.test.js +31 -104
  28. package/lib/tests/rules/require-story-annotation.test.js +3 -3
  29. package/lib/tests/rules/require-story-io-behavior.test.js +2 -7
  30. package/lib/tests/rules/require-story-io.edgecases.test.js +2 -7
  31. package/lib/tests/rules/require-story-visitors-edgecases.test.js +8 -8
  32. package/lib/tests/rules/valid-annotation-format.test.js +23 -23
  33. package/lib/tests/rules/valid-req-reference.test.js +9 -9
  34. package/lib/tests/rules/valid-story-reference.test.js +4 -43
  35. package/lib/tests/utils/annotation-checker.test.js +2 -6
  36. package/lib/tests/utils/fsTestHelpers.d.ts +7 -0
  37. package/lib/tests/utils/fsTestHelpers.js +26 -0
  38. package/lib/tests/utils/ioTestHelpers.d.ts +7 -0
  39. package/lib/tests/utils/ioTestHelpers.js +24 -0
  40. package/lib/tests/utils/temp-dir-helpers.d.ts +14 -0
  41. package/lib/tests/utils/temp-dir-helpers.js +61 -0
  42. package/package.json +3 -2
  43. package/user-docs/api-reference.md +12 -15
  44. package/user-docs/migration-guide.md +21 -21
package/CHANGELOG.md CHANGED
@@ -1,9 +1,9 @@
1
- ## [1.8.1](https://github.com/voder-ai/eslint-plugin-traceability/compare/v1.8.0...v1.8.1) (2025-12-04)
1
+ ## [1.8.2](https://github.com/voder-ai/eslint-plugin-traceability/compare/v1.8.1...v1.8.2) (2025-12-04)
2
2
 
3
3
 
4
4
  ### Bug Fixes
5
5
 
6
- * disable prefer-implements-annotation in default presets ([89c62e9](https://github.com/voder-ai/eslint-plugin-traceability/commit/89c62e907be95030f89e6a3ab6df24a4ba32ab62))
6
+ * rename multi-story annotation from [@implements](https://github.com/implements) to [@supports](https://github.com/supports) ([8c5d089](https://github.com/voder-ai/eslint-plugin-traceability/commit/8c5d08997efb4e5ab8f565db462633b15232ded0))
7
7
 
8
8
  # Changelog
9
9
 
@@ -75,8 +75,8 @@ The following entries were maintained manually before the adoption of semantic-r
75
75
  - `valid-annotation-format`
76
76
  - `valid-story-reference`
77
77
  - `valid-req-reference`
78
- - Documentation for all rules under `docs/rules`.
79
- - Configuration presets in `docs/config-presets.md`.
78
+ - Developer documentation for all rules in this repository.
79
+ - Developer documentation for configuration presets in this repository.
80
80
  - Example usage in `README.md`.
81
81
  - Pre-commit and pre-push hooks with formatting, linting, and tests.
82
82
  - Comprehensive tests covering core validation rules.
package/README.md CHANGED
@@ -54,7 +54,7 @@ export default [
54
54
  - `traceability/valid-annotation-format` Enforces correct format of traceability annotations. (See the rule documentation in the plugin's user guide.)
55
55
  - `traceability/valid-story-reference` Validates that `@story` references point to existing story files. (See the rule documentation in the plugin's user guide.)
56
56
  - `traceability/valid-req-reference` Validates that `@req` references point to existing requirement IDs. (See the rule documentation in the plugin's user guide.)
57
- - `traceability/prefer-implements-annotation` Recommends migration from legacy `@story`/`@req` annotations to `@implements` (opt-in; disabled by default in the presets and must be explicitly enabled). (See the rule documentation in the plugin's user guide.)
57
+ - `traceability/prefer-implements-annotation` Recommends migration from legacy `@story`/`@req` annotations to `@supports` (opt-in; disabled by default in the presets and must be explicitly enabled). (See the rule documentation in the plugin's user guide.)
58
58
 
59
59
  Configuration options: For detailed per-rule options (such as scopes, branch types, and story directory settings), see the individual rule docs in the plugin's user guide and the consolidated [API Reference](user-docs/api-reference.md).
60
60
 
@@ -136,8 +136,8 @@ npx traceability-maint report --root . --format json
136
136
  # Update references when a story file is renamed
137
137
  npx traceability-maint update \
138
138
  --root . \
139
- --from "docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md" \
140
- --to "docs/stories/003.0-DEV-FN-ANNOTATIONS.story.md"
139
+ --from "stories/feature-authentication.story.md" \
140
+ --to "stories/feature-auth-v2.story.md"
141
141
  ```
142
142
 
143
143
  For a full description of options and JSON payloads, see the [Maintenance API and CLI](user-docs/api-reference.md#maintenance-api-and-cli) section in the API Reference.
@@ -195,7 +195,7 @@ These tests verify end-to-end behavior of the plugin via the ESLint CLI.
195
195
 
196
196
  ## Security and Dependency Health
197
197
 
198
- For the canonical, user-facing security policy (including how to report vulnerabilities), see [SECURITY.md](SECURITY.md). The additional files under `docs/` referenced below provide deeper background and implementation details for interested readers.
198
+ For the canonical, user-facing security policy (including how to report vulnerabilities), see [SECURITY.md](SECURITY.md). Internal implementation details and deeper discussion live in the project’s internal documentation and decision records, which are intended for maintainers rather than end users.
199
199
 
200
200
  ### What end users can expect from production dependencies
201
201
 
package/SECURITY.md CHANGED
@@ -4,6 +4,8 @@ This document describes how security is handled for `eslint-plugin-traceability`
4
4
 
5
5
  > This file is **user-facing** documentation. Internal implementation details and deeper discussion live in the project’s internal documentation and decision records.
6
6
 
7
+ For a consolidated implementation overview of security tooling and checks (maintainer and automated-assessor focused), maintainers can refer to the project's internal security overview documentation; this level of detail is not required for normal end users of the plugin.
8
+
7
9
  ## Reporting a Vulnerability
8
10
 
9
11
  If you believe you have found a security vulnerability in this project:
@@ -41,7 +43,9 @@ In other words:
41
43
  - The published npm package is intended to ship **without known high‑severity vulnerabilities in its production dependencies** at the moment it is released.
42
44
  - Dev-only tooling and CI infrastructure are kept separate from what you install via `npm install eslint-plugin-traceability`.
43
45
 
44
- For more detail on how these checks are wired into CI, see the internal dependency health and security documentation for this project.
46
+ For more detail on how these checks are wired into CI, maintainers can refer to the project’s internal dependency health and security documentation; this level of detail is not required for normal end users of the plugin.
47
+
48
+ Maintainer-focused CI/CD security summary: release workflows enforce several security checks end-to-end. For production dependencies, `npm audit --omit=dev --audit-level=high` is **release-blocking** and must report no high-severity issues before publishing proceeds. For broader dependency health, `npm run safety:deps` (dry-aged-deps) and `npm run audit:dev-high` (dev-only `npm audit` with stricter thresholds) are **advisory**: they generate machine-readable reports to guide upgrades and risk review but do not, by themselves, block a release. Secret scanning is performed with `npm run security:secrets` (secretlint); this is treated as **release-blocking** in CI/CD so that accidental credential or secret leaks are caught before artifacts are published.
45
49
 
46
50
  ## Dependency Maturity and `dry-aged-deps`
47
51
 
@@ -59,71 +63,70 @@ Current high-level policy:
59
63
 
60
64
  When `dry-aged-deps` reports that there are **no safe upgrades available** under these thresholds, we may temporarily accept residual risk in dev-only tooling while keeping production dependencies clean and fully audited.
61
65
 
62
- For maintainers, the full process is described in the project’s internal dependency health and security guidelines.
66
+ For maintainers, the full process is described in the project’s internal dependency health and security guidelines; end users typically do not need to consult those documents.
63
67
 
64
68
  ## Dev-Only Release Tooling Risk (semantic-release / npm / glob / brace-expansion)
65
69
 
66
- There is a known, documented risk in the **dev-only release toolchain** used by this project. It does **not** affect the runtime behavior of the published ESLint plugin or CLI, but it is relevant to how releases are built in CI.
70
+ This section documents a **historical** dev-only risk in an older semantic-release/npm toolchain that has since been fully resolved by upgrading the release toolchain to a vulnerability-free stack.
71
+
72
+ ### What was affected?
67
73
 
68
- ### What is affected?
74
+ During the incident period, the **older** dev dependency stack had the following characteristics:
69
75
 
70
- - The dev dependency `@semantic-release/npm@10.0.6` bundles `npm@9.5.0`, which in turn includes vulnerable versions of `glob` and `brace-expansion`.
71
- - The relevant advisories are:
76
+ - The dev dependency `@semantic-release/npm@10.0.6` bundled `npm@9.5.0`, which in turn included vulnerable versions of `glob` and `brace-expansion`.
77
+ - The relevant advisories were:
72
78
  - `glob` CLI command injection: [GHSA-5j98-mcp5-4vw2](https://github.com/advisories/GHSA-5j98-mcp5-4vw2)
73
79
  - `brace-expansion` ReDoS: [GHSA-v6h2-p8h4-qcjw](https://github.com/advisories/GHSA-v6h2-p8h4-qcjw)
74
- - These vulnerable packages exist **only inside the npm binary bundled within `@semantic-release/npm`** and are used solely during automated publishing from CI.
80
+ - These vulnerable packages existed **only inside the npm binary bundled within `@semantic-release/npm`** and were used solely during automated publishing from CI.
81
+
82
+ The current release toolchain no longer relies on this vulnerable bundled npm stack, and these specific advisories are no longer present in our dev dependencies.
75
83
 
76
84
  ### What is _not_ affected?
77
85
 
78
- - The published `eslint-plugin-traceability` package has **no runtime dependencies** on this bundled npm or its `glob`/`brace-expansion` copies.
86
+ Throughout the incident period, and continuing after the upgrade:
87
+
88
+ - The published `eslint-plugin-traceability` package has **no runtime dependencies** on any bundled npm or its `glob`/`brace-expansion` copies.
79
89
  - End-user projects that install and run `eslint-plugin-traceability` or `traceability-maint` **do not execute** this bundled tooling.
80
- - `npm audit --omit=dev --audit-level=high` continues to report **0 high‑severity vulnerabilities** for the production dependency tree at release time.
90
+ - `npm audit --omit=dev --audit-level=high` has continued to report **0 high‑severity vulnerabilities** for the production dependency tree at release time.
81
91
 
82
- ### Why is this risk currently accepted?
92
+ These guarantees remain in effect with the updated, vulnerability-free toolchain.
83
93
 
84
- Under our `dry-aged-deps` policy (7‑day minimum age, no known vulnerabilities):
94
+ ### Historical Risk Acceptance
85
95
 
86
- - There is currently **no recommended, dryaged‑safe upgrade path** for the semantic-release/npm toolchain that would fully eliminate these bundled vulnerabilities.
87
- - We therefore treat this as a **known error in dev-only tooling** rather than a production risk.
96
+ While the older `@semantic-release/npm@10.0.6` stack was in use and no safe, `dry-aged-deps`–approved upgrade path existed, this dev-only risk was **explicitly accepted** as a known error under the `dry-aged-deps` policy. It is **no longer** an active known error following the toolchain upgrade.
88
97
 
89
- This acceptance is documented in detail in the project’s internal security incident records and architectural decision records.
98
+ The full historical record and resolution details are documented in:
99
+
100
+ - A detailed historical incident report in this repository’s internal security incident documentation (maintainer-facing only)
90
101
 
91
102
  ### Compensating Controls
92
103
 
93
- To keep this dev-only risk tightly contained, we apply several compensating controls:
104
+ While the older toolchain was in place, we applied several compensating controls to tightly contain the dev-only risk. The same general isolation and audit practices continue to apply to the updated, vulnerability-free release toolchain:
94
105
 
95
106
  1. **Environment Isolation**
96
- - The vulnerable tooling is used **only** in the GitHub Actions CI workflow (`.github/workflows/ci-cd.yml`).
97
- - It runs in a single, controlled job that executes on pushes to the `main` branch, not for pull requests.
98
- - The job runs on GitHub-hosted runners and does not have access to internal infrastructure.
107
+ - The vulnerable tooling was used **only** in the GitHub Actions CI workflow (`.github/workflows/ci-cd.yml`).
108
+ - It ran in a single, controlled job that executed on pushes to the `main` branch, not for pull requests.
109
+ - The job ran on GitHub-hosted runners and did not have access to internal infrastructure.
99
110
 
100
111
  2. **Least-Privilege Permissions for Release**
101
- - Workflow-level permissions default to `contents: read`.
102
- - Elevated permissions (`contents: write`, `issues: write`, `pull-requests: write`, `id-token: write`) are scoped to the release job/step that runs semantic-release and are not used for general CI tasks.
112
+ - Workflow-level permissions defaulted to `contents: read`.
113
+ - Elevated permissions (`contents: write`, `issues: write`, `pull-requests: write`, `id-token: write`) were scoped to the release job/step that ran semantic-release and were not used for general CI tasks.
103
114
 
104
115
  3. **Strict Input Handling**
105
- - The CI configuration and project scripts **never invoke the `glob` CLI** with the dangerous `-c/--cmd` flags.
106
- - The semantic-release/npm toolchain does **not** receive untrusted user input for glob patterns or environment variables.
107
- - Release jobs operate only on the repository contents of this project plus standard CI-provided environment variables.
116
+ - The CI configuration and project scripts **never invoked the `glob` CLI** with the dangerous `-c/--cmd` flags.
117
+ - The semantic-release/npm toolchain did **not** receive untrusted user input for glob patterns or environment variables.
118
+ - Release jobs operated only on the repository contents of this project plus standard CI-provided environment variables.
108
119
 
109
120
  4. **Audit and Monitoring**
110
- - Dev-only vulnerabilities are tracked via `npm run audit:dev-high`, which writes a machine-readable report to `ci/npm-audit.json` for each CI run.
111
- - `dry-aged-deps` reports (`ci/dry-aged-deps.json`) are stored as CI artifacts to document when no safe upgrade path exists under the configured thresholds.
112
- - A nightly `dependency-health` workflow re-runs dev-dependency audits to keep this risk under continuous review.
121
+ - Dev-only vulnerabilities were tracked via `npm run audit:dev-high`, which wrote a machine-readable report to `ci/npm-audit.json` for each CI run.
122
+ - `dry-aged-deps` reports (`ci/dry-aged-deps.json`) were stored as CI artifacts to document when no safe upgrade path existed under the configured thresholds.
123
+ - A nightly `dependency-health` workflow re-ran dev-dependency audits to keep this type of risk under continuous review.
113
124
 
114
125
  5. **Guarded semantic-release Invocation (CI-Only)**
115
- - semantic-release is invoked **only from CI**, and guarded to ensure it runs under the intended safe context (GitHub Actions, push to `main`, CI environment).
116
- - Local developers are not expected to run semantic-release directly; publishing is handled automatically by CI after all quality and security checks pass.
117
-
118
- ### Upgrade Plan
119
-
120
- We intend to migrate away from the affected semantic-release/npm toolchain as soon as a safe, dry‑aged‑deps–approved upgrade path is available:
121
-
122
- 1. Continue monitoring `dry-aged-deps` output for `@semantic-release/npm`, `semantic-release`, and related packages.
123
- 2. When a newer, vulnerability-free version remains stable for at least 7 days and passes our audit checks, update the dev dependencies accordingly.
124
- 3. After migration, convert the existing known-error record into a resolved incident that documents the fix and new baseline.
126
+ - semantic-release was invoked **only from CI**, and guarded to ensure it ran under the intended safe context (GitHub Actions, push to `main`, CI environment).
127
+ - Local developers were not expected to run semantic-release directly; publishing was handled automatically by CI after all quality and security checks passed.
125
128
 
126
- Until then, the risk remains **limited to CI release automation** and does not change the guarantees we provide for production dependencies or end-user environments.
129
+ With the upgraded release toolchain, these controls continue to constrain dev-only tooling and help ensure that vulnerabilities in CI infrastructure do not impact the security properties of the published package.
127
130
 
128
131
  ---
129
132
 
@@ -18,10 +18,8 @@ function runMaintenanceCli(rawArgv) {
18
18
  const initialNormalized = (0, flags_1.normalizeCliArgs)(rawArgv);
19
19
  const { subcommand: command } = initialNormalized;
20
20
  if (!command || command === "-h" || command === "--help") {
21
- /**
22
- * @story docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md
23
- * @req REQ-MAINT-SAFE - Handle help requests safely and provide discoverable usage output
24
- */
21
+ // @implements docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md REQ-MAINT-SAFE
22
+ // @implements docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md REQ-MAINT-SAFE - Branch to show usage when no command or help flag is provided; handle help requests safely and provide discoverable usage output
25
23
  printHelp();
26
24
  return commands_1.EXIT_OK;
27
25
  }
@@ -29,37 +27,36 @@ function runMaintenanceCli(rawArgv) {
29
27
  // receive the subcommand name and its raw argument vector unchanged.
30
28
  const normalized = initialNormalized;
31
29
  try {
30
+ // @implements docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md REQ-MAINT-SAFE
31
+ // @implements docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md REQ-MAINT-SAFE - Catch unexpected errors and surface concise diagnostics without crashing
32
32
  switch (command) {
33
33
  case "detect":
34
- // @story docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md @req REQ-MAINT-DETECT - Dispatch to detection handler
34
+ // @implements docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md REQ-MAINT-DETECT - Branch to dispatch to detection handler when 'detect' is requested; dispatch to detection handler
35
35
  return (0, commands_1.handleDetect)(normalized);
36
36
  case "verify":
37
- // @story docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md @req REQ-MAINT-VERIFY - Dispatch to verification handler
37
+ // @implements docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md REQ-MAINT-VERIFY - Branch to dispatch to verification handler when 'verify' is requested; dispatch to verification handler
38
38
  return (0, commands_1.handleVerify)(normalized);
39
39
  case "report":
40
- // @story docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md @req REQ-MAINT-REPORT - Dispatch to reporting handler
40
+ // @implements docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md REQ-MAINT-REPORT - Branch to dispatch to reporting handler when 'report' is requested; dispatch to reporting handler
41
41
  return (0, commands_1.handleReport)(normalized);
42
42
  case "update": {
43
- // @story docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md @req REQ-MAINT-UPDATE - Dispatch to update handler
43
+ // @implements docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md REQ-MAINT-UPDATE - Branch to dispatch to update handler when 'update' is requested; dispatch to update handler
44
44
  const result = (0, commands_1.handleUpdate)(normalized);
45
- // @story docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md @req REQ-MAINT-SAFE - Print help on usage errors from update
46
45
  if (result === commands_1.EXIT_USAGE) {
46
+ // @implements docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md REQ-MAINT-SAFE - Print help on usage errors from update; help branch for update usage errors
47
47
  printHelp();
48
48
  }
49
49
  return result;
50
50
  }
51
51
  default:
52
- // @story docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md @req REQ-MAINT-SAFE - Handle unknown commands safely with diagnostics
52
+ // @implements docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md REQ-MAINT-SAFE - Branch for unknown commands to emit diagnostics and safe usage guidance; handle unknown commands safely with diagnostics
53
53
  console.error(`Unknown command: ${command}`);
54
54
  printHelp();
55
55
  return commands_1.EXIT_USAGE;
56
56
  }
57
57
  }
58
58
  catch (error) {
59
- /**
60
- * @story docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md
61
- * @req REQ-MAINT-SAFE - Catch unexpected errors and surface concise diagnostics without crashing
62
- */
59
+ // @implements docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md REQ-MAINT-SAFE - Catch-all error branch to prevent crashes and provide concise diagnostics; catch unexpected errors and surface concise diagnostics without crashing
63
60
  const message = error instanceof Error
64
61
  ? error.message
65
62
  : "Unknown error in maintenance CLI";
@@ -73,8 +70,7 @@ function runMaintenanceCli(rawArgv) {
73
70
  * @req REQ-MAINT-SAFE - Provide discoverable CLI usage information
74
71
  */
75
72
  function printHelp() {
76
- // @story docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md
77
- // @req REQ-MAINT-SAFE - Provide discoverable CLI usage information
73
+ // @implements docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md REQ-MAINT-SAFE - Help branch ensures users can discover maintenance CLI usage safely; provide discoverable CLI usage information
78
74
  console.log(`traceability-maint - Traceability annotation maintenance tools
79
75
 
80
76
  Usage:
@@ -54,6 +54,9 @@ function detectStaleAnnotations(codebasePath) {
54
54
  // @req REQ-MAINT-DETECT - Return empty result if workspaceRoot does not exist or is not a directory
55
55
  if (!fs.existsSync(workspaceRoot) ||
56
56
  !fs.statSync(workspaceRoot).isDirectory()) {
57
+ // @implements docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md REQ-MAINT-DETECT
58
+ // @implements docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md REQ-MAINT-SAFE
59
+ // @implements docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md REQ-MAINT-DETECT
57
60
  return [];
58
61
  }
59
62
  const stale = new Set();
@@ -76,9 +79,12 @@ function processFileForStaleAnnotations(file, workspaceRoot, cwd, stale) {
76
79
  // @story docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md
77
80
  // @req REQ-MAINT-DETECT - Handle file read errors gracefully
78
81
  try {
82
+ // @implements docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md REQ-MAINT-DETECT
79
83
  content = fs.readFileSync(file, "utf8");
80
84
  }
81
85
  catch {
86
+ // @implements docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md REQ-MAINT-DETECT
87
+ // @implements docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md REQ-MAINT-SAFE - Swallow file read failures without aborting detection
82
88
  return;
83
89
  }
84
90
  const regex = /@story\s+([^\s]+)/g;
@@ -97,6 +103,7 @@ function handleStoryMatch(storyPath, workspaceRoot, cwd, stale) {
97
103
  // @story docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md
98
104
  // @req REQ-MAINT-DETECT REQ-SECURITY-VALIDATION - Skip traversal/absolute-unsafe or invalid-extension story paths before any filesystem or boundary checks
99
105
  if ((0, storyReferenceUtils_1.isUnsafeStoryPath)(storyPath)) {
106
+ // @implements docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md REQ-MAINT-DETECT
100
107
  return;
101
108
  }
102
109
  // @story docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md
@@ -108,6 +115,7 @@ function handleStoryMatch(storyPath, workspaceRoot, cwd, stale) {
108
115
  const inProjectCandidates = getInProjectCandidates(storyProjectCandidate, storyCodebaseCandidate, workspaceRoot);
109
116
  // If both candidates are out-of-project, do not mark as stale and skip FS checks
110
117
  if (inProjectCandidates.length === 0) {
118
+ // @implements docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md REQ-MAINT-DETECT - No in-project candidates means nothing to check or mark stale
111
119
  return;
112
120
  }
113
121
  // @story docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md
@@ -116,6 +124,7 @@ function handleStoryMatch(storyPath, workspaceRoot, cwd, stale) {
116
124
  // @story docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md
117
125
  // @req REQ-MAINT-DETECT - Mark story as stale if any in-project candidate exists conceptually but none exist on disk
118
126
  if (!anyExists) {
127
+ // @implements docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md REQ-MAINT-DETECT
119
128
  stale.add(storyPath);
120
129
  }
121
130
  }
@@ -127,18 +136,24 @@ function getInProjectCandidates(storyProjectCandidate, storyCodebaseCandidate, w
127
136
  let projectBoundary;
128
137
  let codebaseBoundary;
129
138
  try {
139
+ // @implements docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md REQ-MAINT-DETECT
130
140
  projectBoundary = (0, storyReferenceUtils_1.enforceProjectBoundary)(storyProjectCandidate, workspaceRoot);
131
141
  }
132
142
  catch {
143
+ // @implements docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md REQ-MAINT-DETECT
144
+ // @implements docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md REQ-MAINT-SAFE - Treat boundary enforcement failures as out-of-project
133
145
  projectBoundary = {
134
146
  isWithinProject: false,
135
147
  candidate: storyProjectCandidate,
136
148
  };
137
149
  }
138
150
  try {
151
+ // @implements docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md REQ-MAINT-DETECT
139
152
  codebaseBoundary = (0, storyReferenceUtils_1.enforceProjectBoundary)(storyCodebaseCandidate, workspaceRoot);
140
153
  }
141
154
  catch {
155
+ // @implements docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md REQ-MAINT-DETECT
156
+ // @implements docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md REQ-MAINT-SAFE - Treat boundary enforcement failures as out-of-project
142
157
  codebaseBoundary = {
143
158
  isWithinProject: false,
144
159
  candidate: storyCodebaseCandidate,
@@ -146,9 +161,11 @@ function getInProjectCandidates(storyProjectCandidate, storyCodebaseCandidate, w
146
161
  }
147
162
  const inProjectCandidates = [];
148
163
  if (projectBoundary.isWithinProject) {
164
+ // @implements docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md REQ-MAINT-DETECT - Collect project-relative in-project candidate
149
165
  inProjectCandidates.push(projectBoundary.candidate);
150
166
  }
151
167
  if (codebaseBoundary.isWithinProject) {
168
+ // @implements docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md REQ-MAINT-DETECT - Collect workspace-root-relative in-project candidate
152
169
  inProjectCandidates.push(codebaseBoundary.candidate);
153
170
  }
154
171
  return inProjectCandidates;
@@ -158,5 +175,15 @@ function getInProjectCandidates(storyProjectCandidate, storyCodebaseCandidate, w
158
175
  * @req REQ-MAINT-DETECT - Check on-disk existence of in-project candidates
159
176
  */
160
177
  function anyInProjectCandidateExists(inProjectCandidates) {
161
- return inProjectCandidates.some((p) => fs.existsSync(p));
178
+ return inProjectCandidates.some(
179
+ /**
180
+ * @implements docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md REQ-MAINT-DETECT REQ-MAINT-SAFE
181
+ */
182
+ (p) => {
183
+ const exists = fs.existsSync(p);
184
+ if (!exists) {
185
+ // @implements docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md REQ-MAINT-SAFE - Safely handle non-existent candidate without throwing
186
+ }
187
+ return exists;
188
+ });
162
189
  }
@@ -29,10 +29,10 @@ export declare function linesBeforeHasStory(sourceCode: any, node: any, lookback
29
29
  export declare function parentChainHasStory(sourceCode: any, node: any): boolean;
30
30
  /**
31
31
  * Fallback: inspect text immediately preceding the node in sourceCode.getText to find @story
32
- * Also accepts @implements annotations as satisfying story presence for this rule.
32
+ * Also accepts @supports annotations as satisfying story presence for this rule.
33
33
  * @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
34
34
  * @story docs/stories/010.2-DEV-MULTI-STORY-SUPPORT.story.md
35
35
  * @req REQ-ANNOTATION-REQUIRED - Provide fallback textual inspection when other heuristics fail
36
- * @req REQ-REQUIRE-ACCEPTS-IMPLEMENTS - Treat @implements annotations as satisfying story presence in fallback checks
36
+ * @req REQ-REQUIRE-ACCEPTS-IMPLEMENTS - Treat @supports annotations as satisfying story presence in fallback checks
37
37
  */
38
38
  export declare function fallbackTextBeforeHasStory(sourceCode: any, node: any): boolean;
@@ -23,17 +23,17 @@ exports.LOOKBACK_LINES = 4;
23
23
  exports.FALLBACK_WINDOW = 800;
24
24
  /**
25
25
  * Shared predicate to determine if a given comment node contains an @story marker.
26
- * Also treats @implements annotations as satisfying story presence checks.
26
+ * Also treats @supports annotations as satisfying story presence checks.
27
27
  * @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
28
28
  * @story docs/stories/010.2-DEV-MULTI-STORY-SUPPORT.story.md
29
29
  * @req REQ-ANNOTATION-REQUIRED - Centralize @story detection logic for comment value inspection
30
- * @req REQ-REQUIRE-ACCEPTS-IMPLEMENTS - Treat @implements annotations as satisfying story presence checks
30
+ * @req REQ-REQUIRE-ACCEPTS-IMPLEMENTS - Treat @supports annotations as satisfying story presence checks
31
31
  */
32
32
  function commentContainsStory(comment) {
33
33
  if (typeof comment?.value !== "string") {
34
34
  return false;
35
35
  }
36
- return (comment.value.includes("@story") || comment.value.includes("@implements"));
36
+ return (comment.value.includes("@story") || comment.value.includes("@supports"));
37
37
  }
38
38
  /**
39
39
  * Safely extract the physical source lines array from sourceCode for scanning.
@@ -61,20 +61,20 @@ function getNodeStartLine(node) {
61
61
  * Generic helper to scan a range of physical source lines for the presence of an @story marker.
62
62
  * @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
63
63
  * @req REQ-ANNOTATION-REQUIRED - Reuse line scanning logic for story annotations across helpers
64
- * @req REQ-REQUIRE-ACCEPTS-IMPLEMENTS - Accept @implements annotations as valid markers during line scanning
64
+ * @req REQ-REQUIRE-ACCEPTS-IMPLEMENTS - Accept @supports annotations as valid markers during line scanning
65
65
  */
66
66
  function scanLinesForMarker(lines, from, to) {
67
- // Walk each physical line in the configured lookback window to search for an inline @story or @implements marker.
67
+ // Walk each physical line in the configured lookback window to search for an inline @story or @supports marker.
68
68
  // @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
69
69
  // @req REQ-ANNOTATION-REQUIRED - Scan preceding lines for existing story annotations
70
70
  for (let i = from; i < to; i++) {
71
71
  const text = lines[i];
72
- // Treat any line containing "@story" or "@implements" as evidence that the function is already annotated.
72
+ // Treat any line containing "@story" or "@supports" as evidence that the function is already annotated.
73
73
  // @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
74
74
  // @req REQ-ANNOTATION-REQUIRED - Detect explicit @story markers in raw source text
75
- // @req REQ-REQUIRE-ACCEPTS-IMPLEMENTS - Detect explicit @implements markers in raw source text
75
+ // @req REQ-REQUIRE-ACCEPTS-IMPLEMENTS - Detect explicit @supports markers in raw source text
76
76
  if (typeof text === "string" &&
77
- (text.includes("@story") || text.includes("@implements"))) {
77
+ (text.includes("@story") || text.includes("@supports"))) {
78
78
  return true;
79
79
  }
80
80
  }
@@ -134,11 +134,11 @@ function parentChainHasStory(sourceCode, node) {
134
134
  }
135
135
  /**
136
136
  * Fallback: inspect text immediately preceding the node in sourceCode.getText to find @story
137
- * Also accepts @implements annotations as satisfying story presence for this rule.
137
+ * Also accepts @supports annotations as satisfying story presence for this rule.
138
138
  * @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
139
139
  * @story docs/stories/010.2-DEV-MULTI-STORY-SUPPORT.story.md
140
140
  * @req REQ-ANNOTATION-REQUIRED - Provide fallback textual inspection when other heuristics fail
141
- * @req REQ-REQUIRE-ACCEPTS-IMPLEMENTS - Treat @implements annotations as satisfying story presence in fallback checks
141
+ * @req REQ-REQUIRE-ACCEPTS-IMPLEMENTS - Treat @supports annotations as satisfying story presence in fallback checks
142
142
  */
143
143
  function fallbackTextBeforeHasStory(sourceCode, node) {
144
144
  // Skip fallback text inspection when the sourceCode API or node range information is not available.
@@ -161,12 +161,12 @@ function fallbackTextBeforeHasStory(sourceCode, node) {
161
161
  // @req REQ-ANNOTATION-REQUIRED - Restrict fallback text scanning to a safe, fixed-size window
162
162
  const start = Math.max(0, range[0] - exports.FALLBACK_WINDOW);
163
163
  const textBefore = sourceCode.getText().slice(start, range[0]);
164
- // Detect any @story or @implements marker that appears within the bounded fallback window.
164
+ // Detect any @story or @supports marker that appears within the bounded fallback window.
165
165
  // @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
166
166
  // @req REQ-ANNOTATION-REQUIRED - Recognize story annotations discovered via fallback text scanning
167
- // @req REQ-REQUIRE-ACCEPTS-IMPLEMENTS - Recognize @implements annotations discovered via fallback text scanning
167
+ // @req REQ-REQUIRE-ACCEPTS-IMPLEMENTS - Recognize @supports annotations discovered via fallback text scanning
168
168
  if (typeof textBefore === "string" &&
169
- (textBefore.includes("@story") || textBefore.includes("@implements"))) {
169
+ (textBefore.includes("@story") || textBefore.includes("@supports"))) {
170
170
  return true;
171
171
  }
172
172
  }
@@ -7,7 +7,7 @@
7
7
  * @req REQ-MULTILINE-SUPPORT - Handle annotations split across multiple lines
8
8
  * @req REQ-FLEXIBLE-PARSING - Support reasonable variations in whitespace and formatting
9
9
  * @req REQ-AUTOFIX-FORMAT - Provide safe, minimal automatic fixes for common format issues
10
- * @req REQ-IMPLEMENTS-PARSE - Parse @implements annotations without affecting @story/@req
10
+ * @req REQ-SUPPORTS-PARSE - Parse @supports annotations without affecting @story/@req
11
11
  * @req REQ-MIXED-SUPPORT - Support mixed @story/@req/@implements usage in comments
12
12
  */
13
13
  /**
@@ -24,7 +24,7 @@ export interface PendingAnnotation {
24
24
  * This function trims whitespace, keeps any annotation tags that appear
25
25
  * later in the line, and supports common JSDoc styles such as leading "*".
26
26
  *
27
- * It detects @story, @req, and @implements tags while preserving the rest
27
+ * It detects @story, @req, and @supports tags while preserving the rest
28
28
  * of the line for downstream logic.
29
29
  */
30
30
  export declare function normalizeCommentLine(rawLine: string): string;
@@ -8,7 +8,7 @@
8
8
  * @req REQ-MULTILINE-SUPPORT - Handle annotations split across multiple lines
9
9
  * @req REQ-FLEXIBLE-PARSING - Support reasonable variations in whitespace and formatting
10
10
  * @req REQ-AUTOFIX-FORMAT - Provide safe, minimal automatic fixes for common format issues
11
- * @req REQ-IMPLEMENTS-PARSE - Parse @implements annotations without affecting @story/@req
11
+ * @req REQ-SUPPORTS-PARSE - Parse @supports annotations without affecting @story/@req
12
12
  * @req REQ-MIXED-SUPPORT - Support mixed @story/@req/@implements usage in comments
13
13
  */
14
14
  Object.defineProperty(exports, "__esModule", { value: true });
@@ -19,7 +19,7 @@ exports.normalizeCommentLine = normalizeCommentLine;
19
19
  * This function trims whitespace, keeps any annotation tags that appear
20
20
  * later in the line, and supports common JSDoc styles such as leading "*".
21
21
  *
22
- * It detects @story, @req, and @implements tags while preserving the rest
22
+ * It detects @story, @req, and @supports tags while preserving the rest
23
23
  * of the line for downstream logic.
24
24
  */
25
25
  function normalizeCommentLine(rawLine) {
@@ -27,7 +27,7 @@ function normalizeCommentLine(rawLine) {
27
27
  if (!trimmed) {
28
28
  return "";
29
29
  }
30
- const annotationMatch = trimmed.match(/@story\b|@req\b|@implements\b/);
30
+ const annotationMatch = trimmed.match(/@story\b|@req\b|@supports\b/);
31
31
  if (!annotationMatch || annotationMatch.index === undefined) {
32
32
  const withoutLeadingStar = trimmed.replace(/^\*\s?/, "");
33
33
  return withoutLeadingStar;
@@ -42,7 +42,10 @@ export declare function collapseAnnotationValue(value: string): string;
42
42
  *
43
43
  * Returns the fixed path when safe, or null if no fix should be applied.
44
44
  *
45
+ * @story docs/stories/005.0-DEV-ANNOTATION-VALIDATION.story.md
45
46
  * @story docs/stories/008.0-DEV-AUTO-FIX.story.md
47
+ * @story docs/stories/010.1-REQ-STORY-PATH-STRICTNESS.story.md
48
+ * @story docs/stories/010.2-REQ-STORY-PATH-AUTOFIX.story.md
46
49
  * @req REQ-AUTOFIX-FORMAT - Provide safe, minimal automatic fixes for common format issues
47
50
  * @req REQ-AUTOFIX-SAFE - Auto-fix must be conservative and never broaden the referenced path
48
51
  * @req REQ-AUTOFIX-PRESERVE - Preserve surrounding formatting when normalizing story path suffixes
@@ -53,6 +56,7 @@ export declare function getFixedStoryPath(original: string): string | null;
53
56
  *
54
57
  * @story docs/stories/005.0-DEV-ANNOTATION-VALIDATION.story.md
55
58
  * @story docs/stories/008.0-DEV-AUTO-FIX.story.md
59
+ * @story docs/stories/010.1-REQ-STORY-PATH-STRICTNESS.story.md
56
60
  * @req REQ-ERROR-SPECIFICITY - Provide specific error messages for different format violations
57
61
  * @req REQ-AUTOFIX-FORMAT - Provide safe, minimal automatic fixes for common format issues
58
62
  */
@@ -62,6 +66,7 @@ export declare function buildStoryErrorMessage(kind: "missing" | "invalid", valu
62
66
  *
63
67
  * @story docs/stories/005.0-DEV-ANNOTATION-VALIDATION.story.md
64
68
  * @story docs/stories/008.0-DEV-AUTO-FIX.story.md
69
+ * @story docs/stories/010.1-REQ-STORY-PATH-STRICTNESS.story.md
65
70
  * @req REQ-ERROR-SPECIFICITY - Provide specific error messages for different format violations
66
71
  * @req REQ-AUTOFIX-FORMAT - Provide safe, minimal automatic fixes for common format issues
67
72
  */