eslint-plugin-traceability 1.8.0 → 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.
- package/CHANGELOG.md +5 -5
- package/README.md +28 -29
- package/SECURITY.md +135 -0
- package/lib/src/index.d.ts +6 -35
- package/lib/src/index.js +8 -5
- package/lib/src/maintenance/cli.js +12 -16
- package/lib/src/maintenance/detect.js +28 -1
- package/lib/src/rules/helpers/require-story-io.d.ts +2 -2
- package/lib/src/rules/helpers/require-story-io.js +13 -13
- package/lib/src/rules/helpers/valid-annotation-format-internal.d.ts +2 -2
- package/lib/src/rules/helpers/valid-annotation-format-internal.js +3 -3
- package/lib/src/rules/helpers/valid-annotation-utils.d.ts +5 -0
- package/lib/src/rules/helpers/valid-annotation-utils.js +43 -5
- package/lib/src/rules/helpers/valid-implements-utils.d.ts +11 -11
- package/lib/src/rules/helpers/valid-implements-utils.js +11 -11
- package/lib/src/rules/helpers/valid-story-reference-helpers.js +19 -0
- package/lib/src/rules/prefer-implements-annotation.d.ts +7 -7
- package/lib/src/rules/prefer-implements-annotation.js +21 -21
- package/lib/src/rules/valid-annotation-format.js +50 -24
- package/lib/src/rules/valid-req-reference.js +9 -9
- package/lib/src/utils/annotation-checker.js +3 -1
- package/lib/src/utils/reqAnnotationDetection.d.ts +2 -2
- package/lib/src/utils/reqAnnotationDetection.js +28 -28
- package/lib/tests/config/flat-config-presets-integration.test.d.ts +1 -0
- package/lib/tests/config/flat-config-presets-integration.test.js +75 -0
- package/lib/tests/maintenance/batch.test.js +11 -11
- package/lib/tests/maintenance/cli.test.js +34 -27
- package/lib/tests/maintenance/report.test.js +7 -7
- package/lib/tests/plugin-default-export-and-configs.test.js +0 -2
- package/lib/tests/rules/prefer-implements-annotation.test.js +48 -15
- package/lib/tests/rules/require-branch-annotation.test.js +15 -36
- package/lib/tests/rules/require-req-annotation.test.js +31 -104
- package/lib/tests/rules/require-story-annotation.test.js +3 -3
- package/lib/tests/rules/require-story-io-behavior.test.js +2 -7
- package/lib/tests/rules/require-story-io.edgecases.test.js +2 -7
- package/lib/tests/rules/require-story-visitors-edgecases.test.js +8 -8
- package/lib/tests/rules/valid-annotation-format.test.js +23 -23
- package/lib/tests/rules/valid-req-reference.test.js +9 -9
- package/lib/tests/rules/valid-story-reference.test.js +4 -43
- package/lib/tests/utils/annotation-checker.test.js +2 -6
- package/lib/tests/utils/fsTestHelpers.d.ts +7 -0
- package/lib/tests/utils/fsTestHelpers.js +26 -0
- package/lib/tests/utils/ioTestHelpers.d.ts +7 -0
- package/lib/tests/utils/ioTestHelpers.js +24 -0
- package/lib/tests/utils/temp-dir-helpers.d.ts +14 -0
- package/lib/tests/utils/temp-dir-helpers.js +61 -0
- package/package.json +8 -7
- package/user-docs/api-reference.md +37 -20
- package/user-docs/eslint-9-setup-guide.md +89 -6
- package/user-docs/migration-guide.md +37 -21
- package/docs/ci-cd-pipeline.md +0 -224
- package/docs/cli-integration.md +0 -22
- package/docs/code-quality-refactor-opportunities-2025-12-03.md +0 -78
- package/docs/config-presets.md +0 -38
- package/docs/conventional-commits-guide.md +0 -185
- package/docs/custom-rules-development-guide.md +0 -659
- package/docs/decisions/0001-allow-dynamic-require-for-built-plugins.md +0 -26
- package/docs/decisions/001-typescript-for-eslint-plugin.accepted.md +0 -111
- package/docs/decisions/002-jest-for-eslint-testing.accepted.md +0 -137
- package/docs/decisions/003-code-quality-ratcheting-plan.md +0 -48
- package/docs/decisions/004-automated-version-bumping-for-ci-cd.md +0 -196
- package/docs/decisions/005-github-actions-validation-tooling.accepted.md +0 -144
- package/docs/decisions/006-semantic-release-for-automated-publishing.accepted.md +0 -227
- package/docs/decisions/007-github-releases-over-changelog.accepted.md +0 -216
- package/docs/decisions/008-ci-audit-flags.accepted.md +0 -60
- package/docs/decisions/009-security-focused-lint-rules.accepted.md +0 -64
- package/docs/decisions/010-implements-annotation-for-multi-story-requirements.proposed.md +0 -184
- package/docs/decisions/adr-0001-console-usage-for-cli-guards.md +0 -190
- package/docs/decisions/adr-accept-dev-dep-risk-glob.md +0 -40
- package/docs/decisions/adr-commit-branch-tests.md +0 -54
- package/docs/decisions/adr-maintenance-cli-interface.md +0 -140
- package/docs/decisions/adr-pre-push-parity.md +0 -112
- package/docs/decisions/code-quality-ratcheting-plan.md +0 -53
- package/docs/dependency-health.md +0 -238
- package/docs/eslint-9-setup-guide.md +0 -517
- package/docs/eslint-plugin-development-guide.md +0 -487
- package/docs/functionality-coverage-2025-12-03.md +0 -250
- package/docs/jest-testing-guide.md +0 -100
- package/docs/rules/prefer-implements-annotation.md +0 -219
- package/docs/rules/require-branch-annotation.md +0 -71
- package/docs/rules/require-req-annotation.md +0 -203
- package/docs/rules/require-story-annotation.md +0 -159
- package/docs/rules/valid-annotation-format.md +0 -418
- package/docs/rules/valid-req-reference.md +0 -153
- package/docs/rules/valid-story-reference.md +0 -120
- package/docs/security-incidents/2025-11-17-glob-cli-incident.md +0 -45
- package/docs/security-incidents/2025-11-18-brace-expansion-redos.md +0 -45
- package/docs/security-incidents/2025-11-18-bundled-dev-deps-accepted-risk.md +0 -93
- package/docs/security-incidents/2025-11-18-tar-race-condition.md +0 -43
- package/docs/security-incidents/2025-12-03-dependency-health-review.md +0 -58
- package/docs/security-incidents/SECURITY-INCIDENT-2025-11-18-semantic-release-bundled-npm.known-error.md +0 -104
- package/docs/security-incidents/SECURITY-INCIDENT-TEMPLATE.md +0 -37
- package/docs/security-incidents/dependency-override-rationale.md +0 -57
- package/docs/security-incidents/dev-deps-high.json +0 -116
- package/docs/security-incidents/handling-procedure.md +0 -54
- package/docs/stories/001.0-DEV-PLUGIN-SETUP.story.md +0 -92
- package/docs/stories/002.0-DEV-ESLINT-CONFIG.story.md +0 -82
- package/docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md +0 -112
- package/docs/stories/004.0-DEV-BRANCH-ANNOTATIONS.story.md +0 -153
- package/docs/stories/005.0-DEV-ANNOTATION-VALIDATION.story.md +0 -138
- package/docs/stories/006.0-DEV-FILE-VALIDATION.story.md +0 -144
- package/docs/stories/007.0-DEV-ERROR-REPORTING.story.md +0 -163
- package/docs/stories/008.0-DEV-AUTO-FIX.story.md +0 -150
- package/docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md +0 -117
- package/docs/stories/010.0-DEV-DEEP-VALIDATION.story.md +0 -124
- package/docs/stories/010.1-DEV-CONFIGURABLE-PATTERNS.story.md +0 -149
- package/docs/stories/010.2-DEV-MULTI-STORY-SUPPORT.story.md +0 -216
- package/docs/stories/010.3-DEV-MIGRATE-TO-IMPLEMENTS.story.md +0 -236
- package/docs/stories/developer-story.map.md +0 -120
- package/docs/ts-jest-presets-guide.md +0 -548
package/CHANGELOG.md
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
|
|
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
|
-
*
|
|
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
|
-
-
|
|
79
|
-
-
|
|
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
|
@@ -35,22 +35,30 @@ This example shows the recommended starting point using the plugin's recommended
|
|
|
35
35
|
import js from "@eslint/js";
|
|
36
36
|
import traceability from "eslint-plugin-traceability";
|
|
37
37
|
|
|
38
|
-
export default [
|
|
38
|
+
export default [
|
|
39
|
+
js.configs.recommended,
|
|
40
|
+
{
|
|
41
|
+
plugins: {
|
|
42
|
+
traceability,
|
|
43
|
+
},
|
|
44
|
+
},
|
|
45
|
+
...traceability.configs.recommended,
|
|
46
|
+
];
|
|
39
47
|
```
|
|
40
48
|
|
|
41
49
|
### Available Rules
|
|
42
50
|
|
|
43
|
-
- `traceability/require-story-annotation` Enforces presence of `@story` annotations. (
|
|
44
|
-
- `traceability/require-req-annotation` Enforces presence of `@req` annotations. (
|
|
45
|
-
- `traceability/require-branch-annotation` Enforces presence of branch annotations. (
|
|
46
|
-
- `traceability/valid-annotation-format` Enforces correct format of traceability annotations. (
|
|
47
|
-
- `traceability/valid-story-reference` Validates that `@story` references point to existing story files. (
|
|
48
|
-
- `traceability/valid-req-reference` Validates that `@req` references point to existing requirement IDs. (
|
|
49
|
-
- `traceability/prefer-implements-annotation` Recommends migration from legacy `@story`/`@req` annotations to `@
|
|
51
|
+
- `traceability/require-story-annotation` Enforces presence of `@story` annotations. (See the rule documentation in the plugin's user guide.)
|
|
52
|
+
- `traceability/require-req-annotation` Enforces presence of `@req` annotations. (See the rule documentation in the plugin's user guide.)
|
|
53
|
+
- `traceability/require-branch-annotation` Enforces presence of branch annotations. (See the rule documentation in the plugin's user guide.)
|
|
54
|
+
- `traceability/valid-annotation-format` Enforces correct format of traceability annotations. (See the rule documentation in the plugin's user guide.)
|
|
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
|
+
- `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 `@supports` (opt-in; disabled by default in the presets and must be explicitly enabled). (See the rule documentation in the plugin's user guide.)
|
|
50
58
|
|
|
51
|
-
Configuration options: For detailed per-rule options (such as scopes, branch types, and story directory settings), see the individual rule docs in
|
|
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).
|
|
52
60
|
|
|
53
|
-
For development and contribution guidelines, see the
|
|
61
|
+
For development and contribution guidelines, see the contribution guide in the repository.
|
|
54
62
|
|
|
55
63
|
## Quick Start
|
|
56
64
|
|
|
@@ -61,8 +69,12 @@ For development and contribution guidelines, see the [ESLint Plugin Development
|
|
|
61
69
|
import traceability from "eslint-plugin-traceability";
|
|
62
70
|
|
|
63
71
|
export default [
|
|
64
|
-
|
|
65
|
-
|
|
72
|
+
{
|
|
73
|
+
plugins: {
|
|
74
|
+
traceability,
|
|
75
|
+
},
|
|
76
|
+
},
|
|
77
|
+
...traceability.configs.recommended,
|
|
66
78
|
];
|
|
67
79
|
```
|
|
68
80
|
|
|
@@ -124,8 +136,8 @@ npx traceability-maint report --root . --format json
|
|
|
124
136
|
# Update references when a story file is renamed
|
|
125
137
|
npx traceability-maint update \
|
|
126
138
|
--root . \
|
|
127
|
-
--from "
|
|
128
|
-
--to "
|
|
139
|
+
--from "stories/feature-authentication.story.md" \
|
|
140
|
+
--to "stories/feature-auth-v2.story.md"
|
|
129
141
|
```
|
|
130
142
|
|
|
131
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.
|
|
@@ -183,6 +195,8 @@ These tests verify end-to-end behavior of the plugin via the ESLint CLI.
|
|
|
183
195
|
|
|
184
196
|
## Security and Dependency Health
|
|
185
197
|
|
|
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
|
+
|
|
186
200
|
### What end users can expect from production dependencies
|
|
187
201
|
|
|
188
202
|
- The published `eslint-plugin-traceability` package is intended to ship **only with production dependencies that have no known high‑severity vulnerabilities** at release time.
|
|
@@ -217,29 +231,14 @@ These tests verify end-to-end behavior of the plugin via the ESLint CLI.
|
|
|
217
231
|
- The issue is confined to the CI environment that prepares and publishes releases.
|
|
218
232
|
- It **cannot impact** the runtime behavior or dependency graph of the `eslint-plugin-traceability` package you install or use in your own projects.
|
|
219
233
|
|
|
220
|
-
### Optional deeper background
|
|
221
|
-
|
|
222
|
-
For readers who want more context on the dependency and security model (not required to use the plugin):
|
|
223
|
-
|
|
224
|
-
- Dependency health overview: [docs/dependency-health.md](docs/dependency-health.md)
|
|
225
|
-
- Detailed incident note about the semantic‑release/npm toolchain risk:
|
|
226
|
-
[docs/security-incidents/SECURITY-INCIDENT-2025-11-18-semantic-release-bundled-npm.known-error.md](docs/security-incidents/SECURITY-INCIDENT-2025-11-18-semantic-release-bundled-npm.known-error.md)
|
|
227
|
-
|
|
228
|
-
These documents are informational and describe internal processes and known toolchain limitations; they do not change the guarantees described above for end users.
|
|
229
|
-
|
|
230
234
|
## Documentation Links
|
|
231
235
|
|
|
232
236
|
- ESLint v9 Setup Guide: [user-docs/eslint-9-setup-guide.md](user-docs/eslint-9-setup-guide.md)
|
|
233
|
-
- Plugin Development Guide: [docs/eslint-plugin-development-guide.md](docs/eslint-plugin-development-guide.md)
|
|
234
237
|
- API Reference: [user-docs/api-reference.md](user-docs/api-reference.md)
|
|
235
238
|
- Examples: [user-docs/examples.md](user-docs/examples.md)
|
|
236
239
|
- Migration Guide: [user-docs/migration-guide.md](user-docs/migration-guide.md)
|
|
237
240
|
- Full README: <https://github.com/voder-ai/eslint-plugin-traceability#readme>
|
|
238
|
-
- Rule: require-story-annotation: [docs/rules/require-story-annotation.md](docs/rules/require-story-annotation.md)
|
|
239
|
-
- Rule: require-req-annotation: [docs/rules/require-req-annotation.md](docs/rules/require-req-annotation.md)
|
|
240
|
-
- Rule: require-branch-annotation: [docs/rules/require-branch-annotation.md](docs/rules/require-branch-annotation.md)
|
|
241
241
|
- Contribution guide: <https://github.com/voder-ai/eslint-plugin-traceability/blob/main/CONTRIBUTING.md>
|
|
242
242
|
- Issue tracker: <https://github.com/voder-ai/eslint-plugin-traceability/issues>
|
|
243
|
-
- Configuration Presets: [docs/config-presets.md](docs/config-presets.md)
|
|
244
243
|
- Changelog: [CHANGELOG.md](CHANGELOG.md)
|
|
245
244
|
- Versioning and Releases: This project uses semantic-release for automated versioning. The authoritative list of published versions and release notes is on GitHub Releases: <https://github.com/voder-ai/eslint-plugin-traceability/releases>
|
package/SECURITY.md
ADDED
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
# Security Policy
|
|
2
|
+
|
|
3
|
+
This document describes how security is handled for `eslint-plugin-traceability`, including how to report vulnerabilities, what guarantees apply to production dependencies, and how we manage known risks in our dev-only release tooling.
|
|
4
|
+
|
|
5
|
+
> This file is **user-facing** documentation. Internal implementation details and deeper discussion live in the project’s internal documentation and decision records.
|
|
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
|
+
|
|
9
|
+
## Reporting a Vulnerability
|
|
10
|
+
|
|
11
|
+
If you believe you have found a security vulnerability in this project:
|
|
12
|
+
|
|
13
|
+
1. **Do not open a public GitHub issue.**
|
|
14
|
+
2. Instead, open a private security advisory via the GitHub Security tab for this repository:
|
|
15
|
+
- Navigate to: `Security` → `Advisories` → `Report a vulnerability`.
|
|
16
|
+
3. Provide as much detail as you can (steps to reproduce, impact, affected environments). A maintainer will review and coordinate a fix and disclosure timeline with you.
|
|
17
|
+
|
|
18
|
+
If you cannot use GitHub Security Advisories, you may alternatively open a **minimal** issue that does not disclose details and ask for a private contact channel.
|
|
19
|
+
|
|
20
|
+
## Supported Versions
|
|
21
|
+
|
|
22
|
+
This project uses [semantic-release](https://github.com/semantic-release/semantic-release) for automated versioning and publishing.
|
|
23
|
+
|
|
24
|
+
- The **latest published version** on npm and GitHub Releases is considered supported.
|
|
25
|
+
- Older versions are not actively maintained; security fixes are applied to the current release line and then published automatically.
|
|
26
|
+
- To benefit from security fixes, users should stay reasonably up-to-date with the latest versions of `eslint-plugin-traceability`.
|
|
27
|
+
|
|
28
|
+
Authoritative release information is available on GitHub Releases:
|
|
29
|
+
|
|
30
|
+
- <https://github.com/voder-ai/eslint-plugin-traceability/releases>
|
|
31
|
+
|
|
32
|
+
## Production Dependency Guarantees
|
|
33
|
+
|
|
34
|
+
The `eslint-plugin-traceability` package has **no runtime dependencies**; it ships only its compiled plugin and CLI code plus documentation. Nevertheless, we treat any future production dependencies with care and enforce the following guarantees at release time:
|
|
35
|
+
|
|
36
|
+
- Before a release is published, CI runs:
|
|
37
|
+
- `npm audit --omit=dev --audit-level=high`
|
|
38
|
+
- A release is allowed to proceed only when:
|
|
39
|
+
- There are **no known high-severity vulnerabilities** reported in the **production (runtime) dependency tree**.
|
|
40
|
+
|
|
41
|
+
In other words:
|
|
42
|
+
|
|
43
|
+
- The published npm package is intended to ship **without known high‑severity vulnerabilities in its production dependencies** at the moment it is released.
|
|
44
|
+
- Dev-only tooling and CI infrastructure are kept separate from what you install via `npm install eslint-plugin-traceability`.
|
|
45
|
+
|
|
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.
|
|
49
|
+
|
|
50
|
+
## Dependency Maturity and `dry-aged-deps`
|
|
51
|
+
|
|
52
|
+
In addition to `npm audit`, we use [`dry-aged-deps`](https://github.com/voder-ai/dry-aged-deps) to guide dependency upgrades for both production and development dependencies.
|
|
53
|
+
|
|
54
|
+
Current high-level policy:
|
|
55
|
+
|
|
56
|
+
- **Minimum age:** new versions are generally required to be **at least 7 days old** before adoption.
|
|
57
|
+
- **No known vulnerabilities:** versions with _any_ known vulnerability (even low severity) are not considered "safe" upgrade candidates.
|
|
58
|
+
|
|
59
|
+
`dry-aged-deps` is advisory only:
|
|
60
|
+
|
|
61
|
+
- It does **not** modify `package.json` or install anything automatically.
|
|
62
|
+
- It produces machine-readable reports that are stored as CI artifacts and referenced in internal security/incident documentation.
|
|
63
|
+
|
|
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.
|
|
65
|
+
|
|
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.
|
|
67
|
+
|
|
68
|
+
## Dev-Only Release Tooling Risk (semantic-release / npm / glob / brace-expansion)
|
|
69
|
+
|
|
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?
|
|
73
|
+
|
|
74
|
+
During the incident period, the **older** dev dependency stack had the following characteristics:
|
|
75
|
+
|
|
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:
|
|
78
|
+
- `glob` CLI command injection: [GHSA-5j98-mcp5-4vw2](https://github.com/advisories/GHSA-5j98-mcp5-4vw2)
|
|
79
|
+
- `brace-expansion` ReDoS: [GHSA-v6h2-p8h4-qcjw](https://github.com/advisories/GHSA-v6h2-p8h4-qcjw)
|
|
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.
|
|
83
|
+
|
|
84
|
+
### What is _not_ affected?
|
|
85
|
+
|
|
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.
|
|
89
|
+
- End-user projects that install and run `eslint-plugin-traceability` or `traceability-maint` **do not execute** this bundled tooling.
|
|
90
|
+
- `npm audit --omit=dev --audit-level=high` has continued to report **0 high‑severity vulnerabilities** for the production dependency tree at release time.
|
|
91
|
+
|
|
92
|
+
These guarantees remain in effect with the updated, vulnerability-free toolchain.
|
|
93
|
+
|
|
94
|
+
### Historical Risk Acceptance
|
|
95
|
+
|
|
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.
|
|
97
|
+
|
|
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)
|
|
101
|
+
|
|
102
|
+
### Compensating Controls
|
|
103
|
+
|
|
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:
|
|
105
|
+
|
|
106
|
+
1. **Environment Isolation**
|
|
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.
|
|
110
|
+
|
|
111
|
+
2. **Least-Privilege Permissions for Release**
|
|
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.
|
|
114
|
+
|
|
115
|
+
3. **Strict Input Handling**
|
|
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.
|
|
119
|
+
|
|
120
|
+
4. **Audit and Monitoring**
|
|
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.
|
|
124
|
+
|
|
125
|
+
5. **Guarded semantic-release Invocation (CI-Only)**
|
|
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.
|
|
128
|
+
|
|
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.
|
|
130
|
+
|
|
131
|
+
---
|
|
132
|
+
|
|
133
|
+
## Attribution
|
|
134
|
+
|
|
135
|
+
Created autonomously by [voder.ai](https://voder.ai).
|
package/lib/src/index.d.ts
CHANGED
|
@@ -17,6 +17,11 @@ import { detectStaleAnnotations, updateAnnotationReferences, batchUpdateAnnotati
|
|
|
17
17
|
declare const RULE_NAMES: readonly ["require-story-annotation", "require-req-annotation", "require-branch-annotation", "valid-annotation-format", "valid-story-reference", "valid-req-reference", "prefer-implements-annotation"];
|
|
18
18
|
type RuleName = (typeof RULE_NAMES)[number];
|
|
19
19
|
declare const rules: Record<RuleName, Rule.RuleModule>;
|
|
20
|
+
declare const plugin: {
|
|
21
|
+
rules: typeof rules;
|
|
22
|
+
configs?: unknown;
|
|
23
|
+
maintenance?: unknown;
|
|
24
|
+
};
|
|
20
25
|
/**
|
|
21
26
|
* @story docs/stories/007.0-DEV-ERROR-REPORTING.story.md
|
|
22
27
|
* @req REQ-ERROR-SEVERITY - Map rule types to appropriate ESLint severity levels (errors vs warnings)
|
|
@@ -25,17 +30,11 @@ declare const rules: Record<RuleName, Rule.RuleModule>;
|
|
|
25
30
|
*/
|
|
26
31
|
declare const configs: {
|
|
27
32
|
recommended: {
|
|
28
|
-
plugins: {
|
|
29
|
-
traceability: {};
|
|
30
|
-
};
|
|
31
33
|
rules: {
|
|
32
34
|
[x: string]: "error" | "warn";
|
|
33
35
|
};
|
|
34
36
|
}[];
|
|
35
37
|
strict: {
|
|
36
|
-
plugins: {
|
|
37
|
-
traceability: {};
|
|
38
|
-
};
|
|
39
38
|
rules: {
|
|
40
39
|
[x: string]: "error" | "warn";
|
|
41
40
|
};
|
|
@@ -53,32 +52,4 @@ declare const maintenance: {
|
|
|
53
52
|
generateMaintenanceReport: typeof generateMaintenanceReport;
|
|
54
53
|
};
|
|
55
54
|
export { rules, configs, maintenance };
|
|
56
|
-
|
|
57
|
-
rules: Record<"require-story-annotation" | "require-req-annotation" | "require-branch-annotation" | "valid-annotation-format" | "valid-story-reference" | "valid-req-reference" | "prefer-implements-annotation", Rule.RuleModule>;
|
|
58
|
-
configs: {
|
|
59
|
-
recommended: {
|
|
60
|
-
plugins: {
|
|
61
|
-
traceability: {};
|
|
62
|
-
};
|
|
63
|
-
rules: {
|
|
64
|
-
[x: string]: "error" | "warn";
|
|
65
|
-
};
|
|
66
|
-
}[];
|
|
67
|
-
strict: {
|
|
68
|
-
plugins: {
|
|
69
|
-
traceability: {};
|
|
70
|
-
};
|
|
71
|
-
rules: {
|
|
72
|
-
[x: string]: "error" | "warn";
|
|
73
|
-
};
|
|
74
|
-
}[];
|
|
75
|
-
};
|
|
76
|
-
maintenance: {
|
|
77
|
-
detectStaleAnnotations: typeof detectStaleAnnotations;
|
|
78
|
-
updateAnnotationReferences: typeof updateAnnotationReferences;
|
|
79
|
-
batchUpdateAnnotations: typeof batchUpdateAnnotations;
|
|
80
|
-
verifyAnnotations: typeof verifyAnnotations;
|
|
81
|
-
generateMaintenanceReport: typeof generateMaintenanceReport;
|
|
82
|
-
};
|
|
83
|
-
};
|
|
84
|
-
export default _default;
|
|
55
|
+
export default plugin;
|
package/lib/src/index.js
CHANGED
|
@@ -73,6 +73,9 @@ RULE_NAMES.forEach(
|
|
|
73
73
|
};
|
|
74
74
|
}
|
|
75
75
|
});
|
|
76
|
+
const plugin = {
|
|
77
|
+
rules,
|
|
78
|
+
};
|
|
76
79
|
/**
|
|
77
80
|
* @story docs/stories/007.0-DEV-ERROR-REPORTING.story.md
|
|
78
81
|
* @req REQ-ERROR-SEVERITY - Map rule types to appropriate ESLint severity levels (errors vs warnings)
|
|
@@ -86,18 +89,16 @@ const TRACEABILITY_RULE_SEVERITIES = {
|
|
|
86
89
|
"traceability/valid-annotation-format": "warn",
|
|
87
90
|
"traceability/valid-story-reference": "error",
|
|
88
91
|
"traceability/valid-req-reference": "error",
|
|
89
|
-
"traceability/prefer-implements-annotation": "warn",
|
|
90
92
|
};
|
|
91
93
|
/**
|
|
92
94
|
* @story docs/stories/007.0-DEV-ERROR-REPORTING.story.md
|
|
93
95
|
* @req REQ-PLUGIN-STRUCTURE - Provide foundational plugin export and registration
|
|
94
96
|
* @req REQ-ERROR-SEVERITY - Map rule types to appropriate ESLint severity levels (errors vs warnings)
|
|
97
|
+
* @story docs/stories/002.0-DEV-ESLINT-CONFIG.story.md
|
|
98
|
+
* @req REQ-CONFIG-PRESETS - Provide flat-config presets that self-register the plugin and core rules
|
|
95
99
|
*/
|
|
96
100
|
function createTraceabilityFlatConfig() {
|
|
97
101
|
return {
|
|
98
|
-
plugins: {
|
|
99
|
-
traceability: {},
|
|
100
|
-
},
|
|
101
102
|
rules: {
|
|
102
103
|
...TRACEABILITY_RULE_SEVERITIES,
|
|
103
104
|
},
|
|
@@ -114,6 +115,7 @@ const configs = {
|
|
|
114
115
|
strict: [createTraceabilityFlatConfig()],
|
|
115
116
|
};
|
|
116
117
|
exports.configs = configs;
|
|
118
|
+
plugin.configs = configs;
|
|
117
119
|
/**
|
|
118
120
|
* @story docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md
|
|
119
121
|
* @req REQ-MAINTENANCE-API-EXPORT - Expose maintenance utilities alongside core plugin exports
|
|
@@ -126,4 +128,5 @@ const maintenance = {
|
|
|
126
128
|
generateMaintenanceReport: maintenance_1.generateMaintenanceReport,
|
|
127
129
|
};
|
|
128
130
|
exports.maintenance = maintenance;
|
|
129
|
-
|
|
131
|
+
plugin.maintenance = maintenance;
|
|
132
|
+
exports.default = plugin;
|
|
@@ -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
|
-
|
|
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
|
-
// @
|
|
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
|
-
// @
|
|
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
|
-
// @
|
|
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
|
-
// @
|
|
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
|
-
// @
|
|
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
|
-
// @
|
|
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(
|
|
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 @
|
|
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 @
|
|
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 @
|
|
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 @
|
|
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("@
|
|
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 @
|
|
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 @
|
|
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 "@
|
|
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 @
|
|
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("@
|
|
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 @
|
|
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 @
|
|
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 @
|
|
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 @
|
|
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("@
|
|
169
|
+
(textBefore.includes("@story") || textBefore.includes("@supports"))) {
|
|
170
170
|
return true;
|
|
171
171
|
}
|
|
172
172
|
}
|