eslint-plugin-traceability 1.8.0 → 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.
- package/CHANGELOG.md +3 -3
- package/README.md +26 -27
- package/SECURITY.md +132 -0
- package/lib/src/index.d.ts +6 -35
- package/lib/src/index.js +8 -5
- 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/plugin-default-export-and-configs.test.js +0 -2
- package/lib/tests/rules/prefer-implements-annotation.test.js +28 -0
- package/package.json +6 -6
- package/user-docs/api-reference.md +33 -13
- package/user-docs/eslint-9-setup-guide.md +89 -6
- package/user-docs/migration-guide.md +20 -4
- 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
|
@@ -28,6 +28,9 @@ npm install --save-dev eslint@^9.39.1
|
|
|
28
28
|
# Recommended configurations
|
|
29
29
|
npm install --save-dev @eslint/js@^9.39.1
|
|
30
30
|
|
|
31
|
+
# Traceability plugin
|
|
32
|
+
npm install --save-dev eslint-plugin-traceability@^1.0.0
|
|
33
|
+
|
|
31
34
|
# For TypeScript projects
|
|
32
35
|
npm install --save-dev @typescript-eslint/parser@^8.0.0
|
|
33
36
|
npm install --save-dev @typescript-eslint/utils@^8.0.0
|
|
@@ -67,13 +70,48 @@ export default [
|
|
|
67
70
|
|
|
68
71
|
### 4. Enable Traceability Plugin
|
|
69
72
|
|
|
70
|
-
To integrate the traceability plugin, update your `eslint.config.js
|
|
73
|
+
To integrate the traceability plugin with its **recommended** preset, update your `eslint.config.js`:
|
|
74
|
+
|
|
75
|
+
```javascript
|
|
76
|
+
import js from "@eslint/js";
|
|
77
|
+
import traceability from "eslint-plugin-traceability";
|
|
78
|
+
|
|
79
|
+
export default [
|
|
80
|
+
js.configs.recommended,
|
|
81
|
+
{
|
|
82
|
+
plugins: {
|
|
83
|
+
traceability,
|
|
84
|
+
},
|
|
85
|
+
},
|
|
86
|
+
...traceability.configs.recommended,
|
|
87
|
+
];
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
To use the **strict** preset instead:
|
|
71
91
|
|
|
72
92
|
```javascript
|
|
73
93
|
import js from "@eslint/js";
|
|
74
94
|
import traceability from "eslint-plugin-traceability";
|
|
75
95
|
|
|
76
|
-
export default [
|
|
96
|
+
export default [
|
|
97
|
+
js.configs.recommended,
|
|
98
|
+
{
|
|
99
|
+
plugins: {
|
|
100
|
+
traceability,
|
|
101
|
+
},
|
|
102
|
+
},
|
|
103
|
+
...traceability.configs.strict,
|
|
104
|
+
];
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
Note: The `traceability.configs.recommended` and `traceability.configs.strict` presets define rule severities only. They expect the plugin to be registered in a preceding flat-config object via:
|
|
108
|
+
|
|
109
|
+
```javascript
|
|
110
|
+
{
|
|
111
|
+
plugins: {
|
|
112
|
+
traceability,
|
|
113
|
+
},
|
|
114
|
+
}
|
|
77
115
|
```
|
|
78
116
|
|
|
79
117
|
## Configuration File Format
|
|
@@ -137,9 +175,16 @@ Both forms are supported by ESLint 9 as long as the file extension and `package.
|
|
|
137
175
|
```javascript
|
|
138
176
|
// eslint.config.js
|
|
139
177
|
import js from "@eslint/js";
|
|
178
|
+
import traceability from "eslint-plugin-traceability";
|
|
140
179
|
|
|
141
180
|
export default [
|
|
142
181
|
js.configs.recommended,
|
|
182
|
+
{
|
|
183
|
+
plugins: {
|
|
184
|
+
traceability,
|
|
185
|
+
},
|
|
186
|
+
},
|
|
187
|
+
...traceability.configs.recommended,
|
|
143
188
|
{
|
|
144
189
|
files: ["**/*.js", "**/*.mjs"],
|
|
145
190
|
languageOptions: {
|
|
@@ -163,9 +208,16 @@ export default [
|
|
|
163
208
|
// eslint.config.js
|
|
164
209
|
import js from "@eslint/js";
|
|
165
210
|
import typescriptParser from "@typescript-eslint/parser";
|
|
211
|
+
import traceability from "eslint-plugin-traceability";
|
|
166
212
|
|
|
167
213
|
export default [
|
|
168
214
|
js.configs.recommended,
|
|
215
|
+
{
|
|
216
|
+
plugins: {
|
|
217
|
+
traceability,
|
|
218
|
+
},
|
|
219
|
+
},
|
|
220
|
+
...traceability.configs.recommended,
|
|
169
221
|
{
|
|
170
222
|
files: ["**/*.ts", "**/*.tsx"],
|
|
171
223
|
languageOptions: {
|
|
@@ -197,9 +249,16 @@ export default [
|
|
|
197
249
|
// eslint.config.js
|
|
198
250
|
import js from "@eslint/js";
|
|
199
251
|
import typescriptParser from "@typescript-eslint/parser";
|
|
252
|
+
import traceability from "eslint-plugin-traceability";
|
|
200
253
|
|
|
201
254
|
export default [
|
|
202
255
|
js.configs.recommended,
|
|
256
|
+
{
|
|
257
|
+
plugins: {
|
|
258
|
+
traceability,
|
|
259
|
+
},
|
|
260
|
+
},
|
|
261
|
+
...traceability.configs.recommended,
|
|
203
262
|
{
|
|
204
263
|
files: ["**/*.{js,jsx,ts,tsx}"],
|
|
205
264
|
languageOptions: {
|
|
@@ -282,9 +341,16 @@ export default [
|
|
|
282
341
|
// eslint.config.js
|
|
283
342
|
import js from "@eslint/js";
|
|
284
343
|
import typescriptParser from "@typescript-eslint/parser";
|
|
344
|
+
import traceability from "eslint-plugin-traceability";
|
|
285
345
|
|
|
286
346
|
export default [
|
|
287
347
|
js.configs.recommended,
|
|
348
|
+
{
|
|
349
|
+
plugins: {
|
|
350
|
+
traceability,
|
|
351
|
+
},
|
|
352
|
+
},
|
|
353
|
+
...traceability.configs.recommended,
|
|
288
354
|
{
|
|
289
355
|
// Lint all packages in a monorepo/workspace
|
|
290
356
|
files: ["packages/*/src/**/*.{js,ts,tsx}"],
|
|
@@ -479,9 +545,16 @@ Solution: Use combined file patterns or separate override blocks, and import the
|
|
|
479
545
|
// eslint.config.js
|
|
480
546
|
import js from "@eslint/js";
|
|
481
547
|
import typescriptParser from "@typescript-eslint/parser";
|
|
548
|
+
import traceability from "eslint-plugin-traceability";
|
|
482
549
|
|
|
483
550
|
export default [
|
|
484
551
|
js.configs.recommended,
|
|
552
|
+
{
|
|
553
|
+
plugins: {
|
|
554
|
+
traceability,
|
|
555
|
+
},
|
|
556
|
+
},
|
|
557
|
+
...traceability.configs.recommended,
|
|
485
558
|
{
|
|
486
559
|
files: ["**/*.{js,jsx,ts,tsx}"],
|
|
487
560
|
languageOptions: {
|
|
@@ -512,6 +585,7 @@ Here's a complete working configuration for a TypeScript ESLint plugin project:
|
|
|
512
585
|
// eslint.config.js
|
|
513
586
|
import js from "@eslint/js";
|
|
514
587
|
import typescriptParser from "@typescript-eslint/parser";
|
|
588
|
+
import traceability from "eslint-plugin-traceability";
|
|
515
589
|
|
|
516
590
|
// Conditional plugin loading (for plugin development)
|
|
517
591
|
let plugin;
|
|
@@ -524,6 +598,15 @@ try {
|
|
|
524
598
|
|
|
525
599
|
export default [
|
|
526
600
|
js.configs.recommended,
|
|
601
|
+
{
|
|
602
|
+
// Register the traceability plugin for subsequent presets/rules
|
|
603
|
+
plugins: {
|
|
604
|
+
traceability,
|
|
605
|
+
...(plugin.rules ? { traceabilityDev: plugin } : {}),
|
|
606
|
+
},
|
|
607
|
+
},
|
|
608
|
+
// Apply the recommended preset for the published plugin
|
|
609
|
+
...traceability.configs.recommended,
|
|
527
610
|
{
|
|
528
611
|
// Node.js config files (CommonJS)
|
|
529
612
|
files: ["*.config.js", "*.config.mjs", "jest.config.js"],
|
|
@@ -554,7 +637,7 @@ export default [
|
|
|
554
637
|
},
|
|
555
638
|
},
|
|
556
639
|
plugins: {
|
|
557
|
-
...(plugin.rules ? {
|
|
640
|
+
...(plugin.rules ? { traceabilityDev: plugin } : {}),
|
|
558
641
|
},
|
|
559
642
|
rules: {
|
|
560
643
|
"@typescript-eslint/no-unused-vars": "error",
|
|
@@ -568,7 +651,7 @@ export default [
|
|
|
568
651
|
sourceType: "module",
|
|
569
652
|
},
|
|
570
653
|
plugins: {
|
|
571
|
-
...(plugin.rules ? {
|
|
654
|
+
...(plugin.rules ? { traceabilityDev: plugin } : {}),
|
|
572
655
|
},
|
|
573
656
|
},
|
|
574
657
|
{
|
|
@@ -621,6 +704,7 @@ export default [
|
|
|
621
704
|
"@typescript-eslint/parser": "^8.46.4",
|
|
622
705
|
"@typescript-eslint/utils": "^8.46.4",
|
|
623
706
|
"eslint": "^9.39.1",
|
|
707
|
+
"eslint-plugin-traceability": "^1.0.0",
|
|
624
708
|
"typescript": "^5.9.3"
|
|
625
709
|
}
|
|
626
710
|
}
|
|
@@ -635,5 +719,4 @@ export default [
|
|
|
635
719
|
5. **Use file patterns** instead of CLI `--ext` flags
|
|
636
720
|
6. **Structure as array of objects**, each targeting specific file types
|
|
637
721
|
7. **Use `ignores`** instead of `.eslintignore` files
|
|
638
|
-
|
|
639
|
-
This setup provides a solid foundation for ESLint 9 that works reliably across different project types and environments.
|
|
722
|
+
8. **Register plugins explicitly** in flat config before spreading their presets
|
|
@@ -57,6 +57,25 @@ function integrate() {}
|
|
|
57
57
|
|
|
58
58
|
You **do not** need to change existing, single-story annotations that already use `@story` and `@req`. Migration to `@implements` is only recommended when a function or module genuinely implements requirements from more than one story file.
|
|
59
59
|
|
|
60
|
+
#### Optional `prefer-implements-annotation` migration rule
|
|
61
|
+
|
|
62
|
+
For teams that want to gradually migrate from `@story` + `@req` to `@implements`, the plugin provides an optional rule: `traceability/prefer-implements-annotation`.
|
|
63
|
+
|
|
64
|
+
- This rule is **disabled by default** and is **not** included in any built-in presets.
|
|
65
|
+
- You can enable it with any standard ESLint severity (`"off"`, `"warn"`, or `"error"`) in your config, for example:
|
|
66
|
+
|
|
67
|
+
```js
|
|
68
|
+
// excerpt from eslint.config.js
|
|
69
|
+
{
|
|
70
|
+
rules: {
|
|
71
|
+
"traceability/prefer-implements-annotation": "warn",
|
|
72
|
+
},
|
|
73
|
+
}
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
- When enabled, it offers **conservative auto-fixes** that rewrite eligible `@story` + `@req` combinations into equivalent `@implements` lines, without attempting risky or ambiguous transformations.
|
|
77
|
+
- Detailed behavior, limitations, and examples are documented in `docs/rules/prefer-implements-annotation.md`.
|
|
78
|
+
|
|
60
79
|
#### When to keep `@story` + `@req`
|
|
61
80
|
|
|
62
81
|
Keep your current annotations if:
|
|
@@ -130,10 +149,7 @@ You can introduce `@implements` gradually without breaking existing code:
|
|
|
130
149
|
3. Run ESLint with `traceability/valid-annotation-format` and `traceability/valid-req-reference` enabled to confirm everything passes.
|
|
131
150
|
4. Optionally, once you are comfortable, standardize on using `@implements` for multi-story integration functions while keeping `@story` + `@req` for simple, single-story code.
|
|
132
151
|
|
|
133
|
-
For detailed semantics and edge cases (path validation, scoped requirement IDs, and multi-story fixtures), see
|
|
134
|
-
|
|
135
|
-
- Rule docs: [`docs/rules/valid-annotation-format.md`](../docs/rules/valid-annotation-format.md), [`docs/rules/valid-req-reference.md`](../docs/rules/valid-req-reference.md)
|
|
136
|
-
- Story: [`docs/stories/010.2-DEV-MULTI-STORY-SUPPORT.story.md`](../docs/stories/010.2-DEV-MULTI-STORY-SUPPORT.story.md)
|
|
152
|
+
For detailed semantics and edge cases (path validation, scoped requirement IDs, and multi-story fixtures), see the valid-annotation-format and valid-req-reference rule documentation and the multi-story support story in the project documentation.
|
|
137
153
|
|
|
138
154
|
## 4. Test and Validate
|
|
139
155
|
|
package/docs/ci-cd-pipeline.md
DELETED
|
@@ -1,224 +0,0 @@
|
|
|
1
|
-
# CI/CD Pipeline and Continuous Deployment
|
|
2
|
-
|
|
3
|
-
This document describes how continuous integration and continuous deployment are implemented for `eslint-plugin-traceability`, and how it relates to our architecture decisions.
|
|
4
|
-
|
|
5
|
-
- Related ADRs:
|
|
6
|
-
- `docs/decisions/006-semantic-release-for-automated-publishing.accepted.md`
|
|
7
|
-
- `docs/decisions/007-github-releases-over-changelog.accepted.md`
|
|
8
|
-
- `docs/decisions/005-github-actions-validation-tooling.accepted.md`
|
|
9
|
-
|
|
10
|
-
## Overview
|
|
11
|
-
|
|
12
|
-
We use a **single unified GitHub Actions workflow** to run all quality checks and, on successful main-branch builds, to automatically publish new versions to npm and create GitHub Releases.
|
|
13
|
-
|
|
14
|
-
- Workflow file: `.github/workflows/ci-cd.yml`
|
|
15
|
-
- Workflow name: `CI/CD Pipeline`
|
|
16
|
-
- Triggers:
|
|
17
|
-
- `push` to `main`
|
|
18
|
-
- `pull_request` targeting `main`
|
|
19
|
-
- Nightly `schedule` for dependency health checks
|
|
20
|
-
|
|
21
|
-
There are no tag-based triggers and no manual `workflow_dispatch` jobs for releases. Publishing (when needed) always happens as part of the same workflow run that executes the quality gates.
|
|
22
|
-
|
|
23
|
-
## Jobs
|
|
24
|
-
|
|
25
|
-
### 1. `quality-and-deploy`
|
|
26
|
-
|
|
27
|
-
Runs on:
|
|
28
|
-
|
|
29
|
-
- Every `push` to `main`
|
|
30
|
-
- Every `pull_request` targeting `main`
|
|
31
|
-
|
|
32
|
-
Matrix:
|
|
33
|
-
|
|
34
|
-
- Node `18.x`
|
|
35
|
-
- Node `20.x`
|
|
36
|
-
|
|
37
|
-
Key steps (in order):
|
|
38
|
-
|
|
39
|
-
1. **Checkout & Node setup**
|
|
40
|
-
- `actions/checkout@v4` with full history (needed for semantic-release)
|
|
41
|
-
- `actions/setup-node@v4` with `cache: npm`
|
|
42
|
-
|
|
43
|
-
2. **Script validation**
|
|
44
|
-
- `node scripts/validate-scripts-nonempty.js` ensures all npm scripts referenced by CI exist and are non-empty.
|
|
45
|
-
|
|
46
|
-
3. **Install dependencies**
|
|
47
|
-
- `npm ci`
|
|
48
|
-
|
|
49
|
-
4. **Full quality gate**
|
|
50
|
-
- `npm run ci-verify:full`
|
|
51
|
-
- This script is the canonical definition of our quality gates and is also used by the Husky pre-push hook.
|
|
52
|
-
- It runs, in order:
|
|
53
|
-
- `npm run check:traceability`
|
|
54
|
-
- `npm run safety:deps`
|
|
55
|
-
- `npm run audit:ci`
|
|
56
|
-
- `npm run build`
|
|
57
|
-
- `npm run type-check`
|
|
58
|
-
- `npm run lint-plugin-check`
|
|
59
|
-
- `npm run lint -- --max-warnings=0`
|
|
60
|
-
- `npm run duplication`
|
|
61
|
-
- `npm run test -- --coverage`
|
|
62
|
-
- `npm run format:check`
|
|
63
|
-
- `npm audit --omit=dev --audit-level=high`
|
|
64
|
-
- `npm run audit:dev-high`
|
|
65
|
-
|
|
66
|
-
5. **Secret scanning**
|
|
67
|
-
- Only on Node `20.x` matrix entry: `npm run security:secrets` using secretlint.
|
|
68
|
-
|
|
69
|
-
6. **Artifact upload**
|
|
70
|
-
- Always upload:
|
|
71
|
-
- `ci/dry-aged-deps.json`
|
|
72
|
-
- `ci/npm-audit.json`
|
|
73
|
-
- `scripts/traceability-report.md`
|
|
74
|
-
- `ci/` (Jest and audit artifacts)
|
|
75
|
-
|
|
76
|
-
7. **Automated release (semantic-release)**
|
|
77
|
-
|
|
78
|
-
Conditional step:
|
|
79
|
-
|
|
80
|
-
```yaml
|
|
81
|
-
if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/main' && matrix['node-version'] == '20.x' && success() }}
|
|
82
|
-
```
|
|
83
|
-
|
|
84
|
-
- Runs `npx semantic-release` with:
|
|
85
|
-
- GitHub authentication via `GITHUB_TOKEN`
|
|
86
|
-
- npm authentication via `NPM_TOKEN`
|
|
87
|
-
- Configuration is in `.releaserc.json` and uses:
|
|
88
|
-
- `@semantic-release/commit-analyzer`
|
|
89
|
-
- `@semantic-release/release-notes-generator`
|
|
90
|
-
- `@semantic-release/changelog` (writes to `CHANGELOG.md` but we treat GitHub Releases as the user-facing source of truth per ADR 007)
|
|
91
|
-
- `@semantic-release/npm` (publishes to npm)
|
|
92
|
-
- `@semantic-release/github` (creates GitHub Releases)
|
|
93
|
-
|
|
94
|
-
Behavior:
|
|
95
|
-
- On each successful push to `main`, semantic-release:
|
|
96
|
-
- Analyzes commits since the last tag using **Conventional Commits** (see `docs/conventional-commits-guide.md`).
|
|
97
|
-
- Decides whether the release is `major`, `minor`, `patch`, or **no release**.
|
|
98
|
-
- If no relevant commits are found, it logs that no new release is needed and exits successfully.
|
|
99
|
-
- If a release is warranted:
|
|
100
|
-
- Publishes a new version to npm.
|
|
101
|
-
- Creates or updates `CHANGELOG.md`.
|
|
102
|
-
- Creates a Git tag and GitHub Release with generated notes.
|
|
103
|
-
|
|
104
|
-
- Safety behavior:
|
|
105
|
-
- If `NPM_TOKEN` is **not set**, the step logs a message and exits 0 with `new_release_published=false`.
|
|
106
|
-
- If semantic-release fails due to invalid npm token (`EINVALIDNPMTOKEN`) or OTP requirement (`EOTP`), the step logs a warning and exits 0, skipping publish but not failing CI.
|
|
107
|
-
- Any other semantic-release error fails the job.
|
|
108
|
-
|
|
109
|
-
8. **Post-deployment smoke test**
|
|
110
|
-
- Runs only when semantic-release reports that a new release was published:
|
|
111
|
-
|
|
112
|
-
```yaml
|
|
113
|
-
if: steps.semantic-release.outputs.new_release_published == 'true'
|
|
114
|
-
```
|
|
115
|
-
|
|
116
|
-
- Executes:
|
|
117
|
-
|
|
118
|
-
```bash
|
|
119
|
-
chmod +x scripts/smoke-test.sh
|
|
120
|
-
./scripts/smoke-test.sh "${{ steps.semantic-release.outputs.new_release_version }}"
|
|
121
|
-
```
|
|
122
|
-
|
|
123
|
-
- `scripts/smoke-test.sh`:
|
|
124
|
-
- For a published version: waits for the version to appear on npm, then
|
|
125
|
-
- Creates a temp project.
|
|
126
|
-
- Installs `eslint-plugin-traceability@<version>`.
|
|
127
|
-
- Verifies the plugin loads and the installed version matches.
|
|
128
|
-
- Runs a minimal ESLint config using the plugin to confirm it can be loaded.
|
|
129
|
-
|
|
130
|
-
### 2. `dependency-health`
|
|
131
|
-
|
|
132
|
-
Runs only on the nightly `schedule` event.
|
|
133
|
-
|
|
134
|
-
- Checks out code and installs dependencies.
|
|
135
|
-
- Runs `npm run audit:dev-high` to generate a JSON report of high-severity dev-only vulnerabilities.
|
|
136
|
-
- Does **not** publish or run semantic-release.
|
|
137
|
-
|
|
138
|
-
This job is intentionally isolated from the main quality-and-deploy path and has no effect on releases.
|
|
139
|
-
|
|
140
|
-
## Continuous Deployment Behavior
|
|
141
|
-
|
|
142
|
-
- Every push to `main` triggers the `quality-and-deploy` job on Node 18.x and 20.x.
|
|
143
|
-
- The full quality gate (`ci-verify:full`) must pass on both Node versions.
|
|
144
|
-
- If, and only if, the Node 20.x job on `main` succeeds and `NPM_TOKEN` is available, semantic-release is invoked.
|
|
145
|
-
- semantic-release decides whether a new version is required based on commit messages:
|
|
146
|
-
- `feat` → minor version bump
|
|
147
|
-
- `fix` → patch bump
|
|
148
|
-
- `feat!` or `BREAKING CHANGE:` footer → major bump
|
|
149
|
-
- Other types (`docs`, `chore`, `refactor`, `test`, `ci`, etc.) do **not** trigger a release.
|
|
150
|
-
- When a release is published, the smoke test runs immediately in the same workflow execution.
|
|
151
|
-
|
|
152
|
-
There is no separate “publish only” workflow and no manual tagging step required to release. The pipeline from commit → quality gates → publish → smoke test is fully automated.
|
|
153
|
-
|
|
154
|
-
## Local Workflow and Hooks
|
|
155
|
-
|
|
156
|
-
To keep local development aligned with CI:
|
|
157
|
-
|
|
158
|
-
- **Pre-commit** (`.husky/pre-commit`):
|
|
159
|
-
- Runs `npx lint-staged`, which executes Prettier and ESLint with `--fix` on staged files in `src/` and `tests/`.
|
|
160
|
-
- **Pre-push** (`.husky/pre-push`):
|
|
161
|
-
- Runs `npm run ci-verify:full`.
|
|
162
|
-
- This mirrors the CI quality gate so that most issues are caught before code reaches GitHub.
|
|
163
|
-
- Secret scanning (`npm run security:secrets`) currently runs only in CI on the Node 20.x matrix entry and is not part of the pre-push hook, but it uses the same configuration so results stay consistent between local and CI.
|
|
164
|
-
|
|
165
|
-
Local verification commands:
|
|
166
|
-
|
|
167
|
-
- `npm run ci-verify:full`
|
|
168
|
-
- Runs the same broad, end-to-end quality gate used in CI (build, type-check, linting, duplication checks, full Jest test suite with coverage, audits, and formatting checks).
|
|
169
|
-
- This is the closest approximation to the CI pipeline and is what the pre-push hook enforces.
|
|
170
|
-
|
|
171
|
-
- `npm run ci-verify:fast`
|
|
172
|
-
- Runs a **narrower, targeted subset** of checks focused on the rule and maintenance test suites.
|
|
173
|
-
- Uses Jest with:
|
|
174
|
-
|
|
175
|
-
```bash
|
|
176
|
-
jest --testPathPatterns 'tests/(rules|maintenance)'
|
|
177
|
-
```
|
|
178
|
-
|
|
179
|
-
to execute only tests whose paths match `tests/rules` or `tests/maintenance`.
|
|
180
|
-
|
|
181
|
-
- Intended as an **optional, faster pre-flight** command that contributors run manually to iterate quickly on rule changes and core maintenance behavior.
|
|
182
|
-
- Does **not** replace `ci-verify:full` and is **not** used by hooks or CI; it exists purely for faster local feedback.
|
|
183
|
-
|
|
184
|
-
Developers should rely on:
|
|
185
|
-
|
|
186
|
-
- `npm run ci-verify:full` for a full CI-equivalent check (and what will run on push via Husky).
|
|
187
|
-
- `npm run ci-verify` or `npm run ci-verify:fast` for quicker, targeted local feedback loops when working on rules or maintenance logic.
|
|
188
|
-
|
|
189
|
-
## How Semantic Versioning Is Determined
|
|
190
|
-
|
|
191
|
-
semantic-release uses Conventional Commits (see `docs/conventional-commits-guide.md`) to infer version changes:
|
|
192
|
-
|
|
193
|
-
- `feat:` → **minor** version bump.
|
|
194
|
-
- `fix:` → **patch** version bump.
|
|
195
|
-
- `feat!` or `fix!` (or any type with `!`) or a `BREAKING CHANGE:` footer → **major** version bump.
|
|
196
|
-
- Other types (`docs`, `style`, `refactor`, `test`, `chore`, `ci`, `build`, `perf`) → no release.
|
|
197
|
-
|
|
198
|
-
Because releases are determined solely from commit history, it is important that all commits merged to `main` follow the documented Conventional Commits standard.
|
|
199
|
-
|
|
200
|
-
## Supported Runtime and Tooling
|
|
201
|
-
|
|
202
|
-
The pipeline runs against the following Node.js versions:
|
|
203
|
-
|
|
204
|
-
- Node `18.x`
|
|
205
|
-
- Node `20.x`
|
|
206
|
-
|
|
207
|
-
The package itself declares:
|
|
208
|
-
|
|
209
|
-
- `engines.node: ">=18.18.0"`
|
|
210
|
-
- `peerDependencies.eslint: "^9.0.0"`
|
|
211
|
-
|
|
212
|
-
User-facing docs are aligned with these constraints:
|
|
213
|
-
|
|
214
|
-
- README “Prerequisites” section.
|
|
215
|
-
- `user-docs/api-reference.md` "Supported runtime" line.
|
|
216
|
-
|
|
217
|
-
## When Things Go Wrong
|
|
218
|
-
|
|
219
|
-
- If **quality checks fail** (build, tests, lint, type-check, duplication, format, or audits), the workflow fails before any release attempt.
|
|
220
|
-
- If semantic-release encounters a non-token, non-OTP error, the job fails and no release is published.
|
|
221
|
-
- If `NPM_TOKEN` is missing or invalid, or if npm requires an OTP, the workflow succeeds but skips publishing; this is treated as a configuration issue rather than a code failure.
|
|
222
|
-
- If the post-deployment smoke test fails, the job fails even though a package may have been published; this indicates an urgent regression in the published artifact.
|
|
223
|
-
|
|
224
|
-
In all of these cases, the failing run is visible in the `CI/CD Pipeline` workflow on GitHub, and maintainers should fix the underlying issue before merging further changes to `main`.
|
package/docs/cli-integration.md
DELETED
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
# CLI Integration Guide
|
|
2
|
-
|
|
3
|
-
Story: docs/stories/001.0-DEV-PLUGIN-SETUP.story.md
|
|
4
|
-
Requirement: REQ-PLUGIN-STRUCTURE - Validate plugin registers via CLI
|
|
5
|
-
|
|
6
|
-
Integration tests for the ESLint CLI plugin are included in the Jest test suite under `tests/integration/cli-integration.test.ts`.
|
|
7
|
-
|
|
8
|
-
## Running CLI Integration Tests
|
|
9
|
-
|
|
10
|
-
To run only the CLI integration tests:
|
|
11
|
-
|
|
12
|
-
```bash
|
|
13
|
-
npm test -- tests/integration/cli-integration.test.ts
|
|
14
|
-
```
|
|
15
|
-
|
|
16
|
-
To run the full test suite:
|
|
17
|
-
|
|
18
|
-
```bash
|
|
19
|
-
npm test
|
|
20
|
-
```
|
|
21
|
-
|
|
22
|
-
These tests invoke the ESLint CLI with the plugin configured, verifying that rule errors are reported (or not) as expected when code is passed via `stdin`. Ensure your ESLint flat config (`eslint.config.js`) loads the plugin before running these tests.
|
|
@@ -1,78 +0,0 @@
|
|
|
1
|
-
# Code Quality and Security Refactor Opportunities (2025-12-03)
|
|
2
|
-
|
|
3
|
-
Created autonomously by voder.ai
|
|
4
|
-
|
|
5
|
-
This note captures small, low-risk refactors that can be implemented incrementally to further improve maintainability and security without changing public behavior.
|
|
6
|
-
|
|
7
|
-
## 1. Decompose maintenance CLI implementation
|
|
8
|
-
|
|
9
|
-
**Files:**
|
|
10
|
-
|
|
11
|
-
- `src/maintenance/cli.ts`
|
|
12
|
-
|
|
13
|
-
**Motivation:**
|
|
14
|
-
|
|
15
|
-
- `cli.ts` is one of the larger source files and currently owns argument parsing, flag normalization, subcommand dispatch, and user-facing messaging.
|
|
16
|
-
- While it still passes `max-lines` and `max-lines-per-function` rules, splitting responsibilities would improve navigability.
|
|
17
|
-
|
|
18
|
-
**Potential refactors:**
|
|
19
|
-
|
|
20
|
-
- Extract a dedicated `src/maintenance/flags.ts` module responsible solely for:
|
|
21
|
-
- Defining the `CliFlags` shape and defaults.
|
|
22
|
-
- Implementing `applyFlag` / `parseFlags` behavior and validation.
|
|
23
|
-
- Extract a `src/maintenance/commands.ts` module for the four subcommand handlers:
|
|
24
|
-
- `handleDetect`, `handleVerify`, `handleReport`, `handleUpdate`.
|
|
25
|
-
- Keep `runMaintenanceCli` as a small coordination layer that wires parsed arguments to these handlers.
|
|
26
|
-
|
|
27
|
-
## 2. Narrow helper responsibilities in require-story helpers
|
|
28
|
-
|
|
29
|
-
**Files:**
|
|
30
|
-
|
|
31
|
-
- `src/rules/helpers/require-story-helpers.ts`
|
|
32
|
-
- `src/rules/helpers/require-story-core.ts`
|
|
33
|
-
|
|
34
|
-
**Motivation:**
|
|
35
|
-
|
|
36
|
-
- These helpers concentrate multiple kinds of functionality: AST visitor construction, IO behavior, message construction, and small utility predicates.
|
|
37
|
-
- Individual functions are reasonably sized, but the number of exported helpers makes the files dense.
|
|
38
|
-
|
|
39
|
-
**Potential refactors:**
|
|
40
|
-
|
|
41
|
-
- Introduce a dedicated `src/rules/helpers/require-story-io.ts` (already partially present) as the single place for reading and writing files in tests and rules.
|
|
42
|
-
- Move purely structural helpers (e.g., small predicates, formatting helpers) into a `require-story-utils.ts`-style module so each file focuses on a single axis of responsibility.
|
|
43
|
-
|
|
44
|
-
## 3. Revisit targeted ESLint suppressions
|
|
45
|
-
|
|
46
|
-
**Files:**
|
|
47
|
-
|
|
48
|
-
- `src/rules/helpers/valid-story-reference-helpers.ts` (single `no-unused-vars` suppression on a type-only parameter)
|
|
49
|
-
- `src/rules/helpers/valid-annotation-options.ts` (single `max-params` suppression for a central option-normalization helper)
|
|
50
|
-
- `tests/utils/ts-language-options.ts` (single `no-magic-numbers` suppression to allow ECMA version constants)
|
|
51
|
-
|
|
52
|
-
**Motivation:**
|
|
53
|
-
|
|
54
|
-
- Each suppression is currently justified and localized, but a small refactor could remove them entirely, simplifying the lint configuration.
|
|
55
|
-
|
|
56
|
-
**Potential refactors:**
|
|
57
|
-
|
|
58
|
-
- Replace the suppressed `max-params` helper with an options object parameter so callers pass a single argument while preserving type safety.
|
|
59
|
-
- For the `no-unused-vars` case, explore using a `type`-only import or restructuring the function signature so all parameters are meaningfully consumed.
|
|
60
|
-
- Extract ECMA version numbers into named constants in a small shared test utility module to avoid the need for a `no-magic-numbers` override.
|
|
61
|
-
|
|
62
|
-
## 4. Optional: add slim wrappers for Story/Req detection utilities
|
|
63
|
-
|
|
64
|
-
**Files:**
|
|
65
|
-
|
|
66
|
-
- `src/utils/reqAnnotationDetection.ts`
|
|
67
|
-
- `src/utils/annotation-checker.ts`
|
|
68
|
-
|
|
69
|
-
**Motivation:**
|
|
70
|
-
|
|
71
|
-
- These utilities are well-tested but contain a moderate amount of conditional logic for different AST node types.
|
|
72
|
-
|
|
73
|
-
**Potential refactors:**
|
|
74
|
-
|
|
75
|
-
- Introduce thin, strongly-typed wrapper functions for the most common call sites (e.g., “analyze function declaration for traceability annotations”) that hide some of the configuration detail from rule implementations.
|
|
76
|
-
- This would make rule modules slightly smaller and more declarative, leaving the complex branching in a shared, well-tested location.
|
|
77
|
-
|
|
78
|
-
These refactors should be tackled incrementally, one small change at a time, with existing Jest tests and ESLint rules acting as safety nets to ensure behavior remains unchanged.
|
package/docs/config-presets.md
DELETED
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
# Configuration Presets
|
|
2
|
-
|
|
3
|
-
This document describes the built-in configuration presets provided by the `eslint-plugin-traceability` plugin.
|
|
4
|
-
|
|
5
|
-
## Recommended Preset
|
|
6
|
-
|
|
7
|
-
Use the **recommended** preset to enable the core traceability rule set with default settings.
|
|
8
|
-
|
|
9
|
-
```javascript
|
|
10
|
-
// eslint.config.js
|
|
11
|
-
import js from "@eslint/js";
|
|
12
|
-
import traceability from "eslint-plugin-traceability";
|
|
13
|
-
|
|
14
|
-
export default [js.configs.recommended, traceability.configs.recommended];
|
|
15
|
-
```
|
|
16
|
-
|
|
17
|
-
This preset enables the following rules with severities tuned for common usage (most at `error`, with `traceability/valid-annotation-format` at `warn` to reduce noise):
|
|
18
|
-
|
|
19
|
-
- `traceability/require-story-annotation`: `error`
|
|
20
|
-
- `traceability/require-req-annotation`: `error`
|
|
21
|
-
- `traceability/require-branch-annotation`: `error`
|
|
22
|
-
- `traceability/valid-annotation-format`: `warn`
|
|
23
|
-
- `traceability/valid-story-reference`: `error`
|
|
24
|
-
- `traceability/valid-req-reference`: `error`
|
|
25
|
-
|
|
26
|
-
## Strict Preset
|
|
27
|
-
|
|
28
|
-
Use the **strict** preset to enforce the same core rules, with potential future enhancements for stricter policies. Like the recommended preset, it configures `traceability/valid-annotation-format` as a `warn` to avoid excessive noise from format-only issues.
|
|
29
|
-
|
|
30
|
-
```javascript
|
|
31
|
-
// eslint.config.js
|
|
32
|
-
import js from "@eslint/js";
|
|
33
|
-
import traceability from "eslint-plugin-traceability";
|
|
34
|
-
|
|
35
|
-
export default [js.configs.recommended, traceability.configs.strict];
|
|
36
|
-
```
|
|
37
|
-
|
|
38
|
-
The **strict** preset currently mirrors the **recommended** rules, but may include additional constraints in future plugin versions.
|