eslint-plugin-traceability 1.10.1 → 1.11.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (70) hide show
  1. package/CHANGELOG.md +2 -2
  2. package/README.md +3 -2
  3. package/lib/src/maintenance/cli.js +12 -12
  4. package/lib/src/maintenance/detect.js +19 -19
  5. package/lib/src/maintenance/flags.js +111 -25
  6. package/lib/src/rules/helpers/require-story-core.d.ts +55 -9
  7. package/lib/src/rules/helpers/require-story-core.js +85 -62
  8. package/lib/src/rules/helpers/require-story-helpers.d.ts +27 -48
  9. package/lib/src/rules/helpers/require-story-helpers.js +154 -116
  10. package/lib/src/rules/helpers/require-story-io.js +51 -31
  11. package/lib/src/rules/helpers/require-story-visitors.js +47 -6
  12. package/lib/src/rules/helpers/valid-annotation-format-validators.js +5 -1
  13. package/lib/src/rules/helpers/valid-annotation-options.d.ts +9 -0
  14. package/lib/src/rules/helpers/valid-annotation-options.js +67 -20
  15. package/lib/src/rules/helpers/valid-annotation-utils.js +31 -31
  16. package/lib/src/rules/helpers/valid-story-reference-helpers.js +19 -19
  17. package/lib/src/rules/prefer-implements-annotation.js +29 -1
  18. package/lib/src/rules/require-story-annotation.js +15 -0
  19. package/lib/src/rules/require-test-traceability.js +1 -6
  20. package/lib/src/utils/annotation-checker.js +32 -8
  21. package/lib/src/utils/reqAnnotationDetection.js +36 -22
  22. package/lib/tests/cli-error-handling.test.js +1 -0
  23. package/lib/tests/config/eslint-config-validation.test.d.ts +8 -0
  24. package/lib/tests/config/eslint-config-validation.test.js +8 -0
  25. package/lib/tests/config/flat-config-presets-integration.test.js +1 -3
  26. package/lib/tests/config/require-story-annotation-config.test.d.ts +9 -0
  27. package/lib/tests/config/require-story-annotation-config.test.js +9 -0
  28. package/lib/tests/integration/cli-integration.test.js +9 -1
  29. package/lib/tests/maintenance/batch.test.js +1 -0
  30. package/lib/tests/maintenance/cli.test.js +1 -0
  31. package/lib/tests/maintenance/detect-isolated.test.js +1 -0
  32. package/lib/tests/maintenance/detect.test.js +1 -0
  33. package/lib/tests/maintenance/index.test.js +1 -0
  34. package/lib/tests/maintenance/report.test.js +1 -0
  35. package/lib/tests/maintenance/update-isolated.test.js +1 -0
  36. package/lib/tests/maintenance/update.test.js +1 -0
  37. package/lib/tests/perf/maintenance-cli-large-workspace.test.d.ts +1 -0
  38. package/lib/tests/perf/maintenance-cli-large-workspace.test.js +130 -0
  39. package/lib/tests/perf/maintenance-large-workspace.test.d.ts +1 -0
  40. package/lib/tests/perf/maintenance-large-workspace.test.js +149 -0
  41. package/lib/tests/plugin-default-export-and-configs.test.js +2 -0
  42. package/lib/tests/plugin-setup-error.test.d.ts +1 -0
  43. package/lib/tests/plugin-setup-error.test.js +1 -0
  44. package/lib/tests/plugin-setup.test.js +1 -1
  45. package/lib/tests/rules/auto-fix-behavior-008.test.js +39 -0
  46. package/lib/tests/rules/error-reporting.test.js +1 -0
  47. package/lib/tests/rules/prefer-implements-annotation.test.js +8 -0
  48. package/lib/tests/rules/require-branch-annotation.test.js +2 -0
  49. package/lib/tests/rules/require-story-core-edgecases.test.js +1 -0
  50. package/lib/tests/rules/require-story-core.autofix.test.js +10 -3
  51. package/lib/tests/rules/require-story-core.test.js +14 -7
  52. package/lib/tests/rules/require-story-helpers-edgecases.test.d.ts +1 -0
  53. package/lib/tests/rules/require-story-helpers-edgecases.test.js +2 -1
  54. package/lib/tests/rules/require-story-helpers.test.js +18 -11
  55. package/lib/tests/rules/require-story-io-behavior.test.d.ts +1 -0
  56. package/lib/tests/rules/require-story-io-behavior.test.js +1 -0
  57. package/lib/tests/rules/require-story-io.edgecases.test.d.ts +1 -0
  58. package/lib/tests/rules/require-story-io.edgecases.test.js +1 -0
  59. package/lib/tests/rules/require-story-visitors-edgecases.test.d.ts +1 -0
  60. package/lib/tests/rules/require-story-visitors-edgecases.test.js +1 -0
  61. package/lib/tests/rules/valid-story-reference.test.js +2 -0
  62. package/lib/tests/utils/annotation-checker.test.js +2 -1
  63. package/lib/tests/utils/branch-annotation-helpers.test.js +2 -1
  64. package/lib/tests/utils/require-story-core-test-helpers.d.ts +1 -1
  65. package/lib/tests/utils/require-story-core-test-helpers.js +16 -16
  66. package/lib/tests/utils/temp-dir-helpers.js +1 -1
  67. package/package.json +9 -2
  68. package/user-docs/api-reference.md +123 -12
  69. package/user-docs/examples.md +41 -0
  70. package/user-docs/migration-guide.md +36 -3
package/CHANGELOG.md CHANGED
@@ -1,9 +1,9 @@
1
- ## [1.10.1](https://github.com/voder-ai/eslint-plugin-traceability/compare/v1.10.0...v1.10.1) (2025-12-05)
1
+ ## [1.11.1](https://github.com/voder-ai/eslint-plugin-traceability/compare/v1.11.0...v1.11.1) (2025-12-05)
2
2
 
3
3
 
4
4
  ### Bug Fixes
5
5
 
6
- * support JSDoc tag coexistence for annotation parsing ([31e9416](https://github.com/voder-ai/eslint-plugin-traceability/commit/31e9416d201fd347051bc44521d3d3b840a244a1))
6
+ * expose valid-annotation-format autofix toggle and align docs ([32e7636](https://github.com/voder-ai/eslint-plugin-traceability/commit/32e7636e9b8f784b84f694a13e9e06d6120e38b3))
7
7
 
8
8
  # Changelog
9
9
 
package/README.md CHANGED
@@ -54,6 +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/require-test-traceability` Enforces traceability conventions in test files by requiring file-level `@supports` annotations, story references in `describe` blocks, and `[REQ-...]` prefixes in `it`/`test` names. (See the rule documentation in the plugin's user guide.)
57
58
  - `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
59
 
59
60
  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).
@@ -82,7 +83,7 @@ export default [
82
83
 
83
84
  ```js
84
85
  /**
85
- * @story stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
86
+ * @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
86
87
  * // Point this to your own project's story/requirements file, not to this plugin's internal docs.
87
88
  * @req REQ-ANNOTATION-REQUIRED
88
89
  */
@@ -241,4 +242,4 @@ For the canonical, user-facing security policy (including how to report vulnerab
241
242
  - Contribution guide: <https://github.com/voder-ai/eslint-plugin-traceability/blob/main/CONTRIBUTING.md>
242
243
  - Issue tracker: <https://github.com/voder-ai/eslint-plugin-traceability/issues>
243
244
  - Changelog: [CHANGELOG.md](CHANGELOG.md)
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>
245
+ - 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>
@@ -18,8 +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
- // @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
21
+ // @supports docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md REQ-MAINT-SAFE
22
+ // @supports 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
23
23
  printHelp();
24
24
  return commands_1.EXIT_OK;
25
25
  }
@@ -27,36 +27,36 @@ function runMaintenanceCli(rawArgv) {
27
27
  // receive the subcommand name and its raw argument vector unchanged.
28
28
  const normalized = initialNormalized;
29
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
30
+ // @supports docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md REQ-MAINT-SAFE
31
+ // @supports 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
- // @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
34
+ // @supports 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
- // @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
37
+ // @supports 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
- // @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
40
+ // @supports 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
- // @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
43
+ // @supports 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
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
46
+ // @supports 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
- // @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
52
+ // @supports 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
- // @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
59
+ // @supports 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
60
60
  const message = error instanceof Error
61
61
  ? error.message
62
62
  : "Unknown error in maintenance CLI";
@@ -70,7 +70,7 @@ function runMaintenanceCli(rawArgv) {
70
70
  * @req REQ-MAINT-SAFE - Provide discoverable CLI usage information
71
71
  */
72
72
  function printHelp() {
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
73
+ // @supports 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
74
74
  console.log(`traceability-maint - Traceability annotation maintenance tools
75
75
 
76
76
  Usage:
@@ -54,9 +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
+ // @supports docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md REQ-MAINT-DETECT
58
+ // @supports docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md REQ-MAINT-SAFE
59
+ // @supports docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md REQ-MAINT-DETECT
60
60
  return [];
61
61
  }
62
62
  const stale = new Set();
@@ -79,12 +79,12 @@ function processFileForStaleAnnotations(file, workspaceRoot, cwd, stale) {
79
79
  // @story docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md
80
80
  // @req REQ-MAINT-DETECT - Handle file read errors gracefully
81
81
  try {
82
- // @implements docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md REQ-MAINT-DETECT
82
+ // @supports docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md REQ-MAINT-DETECT
83
83
  content = fs.readFileSync(file, "utf8");
84
84
  }
85
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
86
+ // @supports docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md REQ-MAINT-DETECT
87
+ // @supports docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md REQ-MAINT-SAFE - Swallow file read failures without aborting detection
88
88
  return;
89
89
  }
90
90
  const regex = /@story\s+([^\s]+)/g;
@@ -103,7 +103,7 @@ function handleStoryMatch(storyPath, workspaceRoot, cwd, stale) {
103
103
  // @story docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md
104
104
  // @req REQ-MAINT-DETECT REQ-SECURITY-VALIDATION - Skip traversal/absolute-unsafe or invalid-extension story paths before any filesystem or boundary checks
105
105
  if ((0, storyReferenceUtils_1.isUnsafeStoryPath)(storyPath)) {
106
- // @implements docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md REQ-MAINT-DETECT
106
+ // @supports docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md REQ-MAINT-DETECT
107
107
  return;
108
108
  }
109
109
  // @story docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md
@@ -115,7 +115,7 @@ function handleStoryMatch(storyPath, workspaceRoot, cwd, stale) {
115
115
  const inProjectCandidates = getInProjectCandidates(storyProjectCandidate, storyCodebaseCandidate, workspaceRoot);
116
116
  // If both candidates are out-of-project, do not mark as stale and skip FS checks
117
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
118
+ // @supports docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md REQ-MAINT-DETECT - No in-project candidates means nothing to check or mark stale
119
119
  return;
120
120
  }
121
121
  // @story docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md
@@ -124,7 +124,7 @@ function handleStoryMatch(storyPath, workspaceRoot, cwd, stale) {
124
124
  // @story docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md
125
125
  // @req REQ-MAINT-DETECT - Mark story as stale if any in-project candidate exists conceptually but none exist on disk
126
126
  if (!anyExists) {
127
- // @implements docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md REQ-MAINT-DETECT
127
+ // @supports docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md REQ-MAINT-DETECT
128
128
  stale.add(storyPath);
129
129
  }
130
130
  }
@@ -136,24 +136,24 @@ function getInProjectCandidates(storyProjectCandidate, storyCodebaseCandidate, w
136
136
  let projectBoundary;
137
137
  let codebaseBoundary;
138
138
  try {
139
- // @implements docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md REQ-MAINT-DETECT
139
+ // @supports docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md REQ-MAINT-DETECT
140
140
  projectBoundary = (0, storyReferenceUtils_1.enforceProjectBoundary)(storyProjectCandidate, workspaceRoot);
141
141
  }
142
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
143
+ // @supports docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md REQ-MAINT-DETECT
144
+ // @supports docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md REQ-MAINT-SAFE - Treat boundary enforcement failures as out-of-project
145
145
  projectBoundary = {
146
146
  isWithinProject: false,
147
147
  candidate: storyProjectCandidate,
148
148
  };
149
149
  }
150
150
  try {
151
- // @implements docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md REQ-MAINT-DETECT
151
+ // @supports docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md REQ-MAINT-DETECT
152
152
  codebaseBoundary = (0, storyReferenceUtils_1.enforceProjectBoundary)(storyCodebaseCandidate, workspaceRoot);
153
153
  }
154
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
155
+ // @supports docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md REQ-MAINT-DETECT
156
+ // @supports docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md REQ-MAINT-SAFE - Treat boundary enforcement failures as out-of-project
157
157
  codebaseBoundary = {
158
158
  isWithinProject: false,
159
159
  candidate: storyCodebaseCandidate,
@@ -161,11 +161,11 @@ function getInProjectCandidates(storyProjectCandidate, storyCodebaseCandidate, w
161
161
  }
162
162
  const inProjectCandidates = [];
163
163
  if (projectBoundary.isWithinProject) {
164
- // @implements docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md REQ-MAINT-DETECT - Collect project-relative in-project candidate
164
+ // @supports docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md REQ-MAINT-DETECT - Collect project-relative in-project candidate
165
165
  inProjectCandidates.push(projectBoundary.candidate);
166
166
  }
167
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
168
+ // @supports docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md REQ-MAINT-DETECT - Collect workspace-root-relative in-project candidate
169
169
  inProjectCandidates.push(codebaseBoundary.candidate);
170
170
  }
171
171
  return inProjectCandidates;
@@ -177,12 +177,12 @@ function getInProjectCandidates(storyProjectCandidate, storyCodebaseCandidate, w
177
177
  function anyInProjectCandidateExists(inProjectCandidates) {
178
178
  return inProjectCandidates.some(
179
179
  /**
180
- * @implements docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md REQ-MAINT-DETECT REQ-MAINT-SAFE
180
+ * @supports docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md REQ-MAINT-DETECT REQ-MAINT-SAFE
181
181
  */
182
182
  (p) => {
183
183
  const exists = fs.existsSync(p);
184
184
  if (!exists) {
185
- // @implements docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md REQ-MAINT-SAFE - Safely handle non-existent candidate without throwing
185
+ // @supports docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md REQ-MAINT-SAFE - Safely handle non-existent candidate without throwing
186
186
  }
187
187
  return exists;
188
188
  });
@@ -60,43 +60,129 @@ function createDefaultFlags() {
60
60
  };
61
61
  }
62
62
  /**
63
- * Handle a single CLI argument and update the flags accordingly.
63
+ * Safely check if the next argument value exists and is a string.
64
64
  *
65
65
  * @story docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md
66
66
  * @req REQ-MAINT-SAFE - Provide predictable, minimal argument parsing
67
67
  */
68
- function applyFlag(flags, args, index) {
69
- const arg = args[index];
70
- if (arg === "--root" && typeof args[index + 1] === "string") {
71
- flags.root = path_1.default.resolve(args[index + 1]);
72
- return index + 1;
68
+ function isNextValueString(args, index) {
69
+ return typeof args[index + 1] === "string";
70
+ }
71
+ /**
72
+ * Handle the --root flag, updating the root path if present.
73
+ *
74
+ * @story docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md
75
+ * @req REQ-MAINT-SAFE - Provide predictable, minimal argument parsing
76
+ */
77
+ function handleRootFlag(flags, args, index) {
78
+ if (args[index] !== "--root" || !isNextValueString(args, index)) {
79
+ return index;
80
+ }
81
+ flags.root = path_1.default.resolve(args[index + 1]);
82
+ return index + 1;
83
+ }
84
+ /**
85
+ * Handle the --json flag, toggling JSON output when present.
86
+ *
87
+ * @story docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md
88
+ * @req REQ-MAINT-SAFE - Provide predictable, minimal argument parsing
89
+ */
90
+ function handleJsonFlag(flags, args, index) {
91
+ if (args[index] !== "--json") {
92
+ return index;
73
93
  }
74
- if (arg === "--json") {
75
- flags.json = true;
94
+ flags.json = true;
95
+ return index;
96
+ }
97
+ /**
98
+ * Handle the --format flag, validating and setting the output format.
99
+ *
100
+ * @story docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md
101
+ * @req REQ-MAINT-SAFE - Provide predictable, minimal argument parsing
102
+ */
103
+ function handleFormatFlag(flags, args, index) {
104
+ if (args[index] !== "--format" || !isNextValueString(args, index)) {
76
105
  return index;
77
106
  }
78
- if (arg === "--format" && typeof args[index + 1] === "string") {
79
- const value = args[index + 1];
80
- if (value === "text" || value === "json") {
81
- flags.format = value;
82
- }
83
- else {
84
- throw new Error(`Invalid format: ${value}. Expected 'text' or 'json'.`);
85
- }
86
- return index + 1;
107
+ const value = args[index + 1];
108
+ if (value === "text" || value === "json") {
109
+ flags.format = value;
110
+ }
111
+ else {
112
+ throw new Error(`Invalid format: ${value}. Expected 'text' or 'json'.`);
87
113
  }
88
- if (arg === "--from" && typeof args[index + 1] === "string") {
89
- flags.from = args[index + 1];
90
- return index + 1;
114
+ return index + 1;
115
+ }
116
+ /**
117
+ * Handle the --from flag, capturing the starting reference if present.
118
+ *
119
+ * @story docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md
120
+ * @req REQ-MAINT-SAFE - Provide predictable, minimal argument parsing
121
+ */
122
+ function handleFromFlag(flags, args, index) {
123
+ if (args[index] !== "--from" || !isNextValueString(args, index)) {
124
+ return index;
91
125
  }
92
- if (arg === "--to" && typeof args[index + 1] === "string") {
93
- flags.to = args[index + 1];
94
- return index + 1;
126
+ flags.from = args[index + 1];
127
+ return index + 1;
128
+ }
129
+ /**
130
+ * Handle the --to flag, capturing the ending reference if present.
131
+ *
132
+ * @story docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md
133
+ * @req REQ-MAINT-SAFE - Provide predictable, minimal argument parsing
134
+ */
135
+ function handleToFlag(flags, args, index) {
136
+ if (args[index] !== "--to" || !isNextValueString(args, index)) {
137
+ return index;
95
138
  }
96
- if (arg === "--dry-run") {
97
- flags.dryRun = true;
139
+ flags.to = args[index + 1];
140
+ return index + 1;
141
+ }
142
+ /**
143
+ * Handle the --dry-run flag, enabling dry-run mode when present.
144
+ *
145
+ * @story docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md
146
+ * @req REQ-MAINT-SAFE - Provide predictable, minimal argument parsing
147
+ */
148
+ function handleDryRunFlag(flags, args, index) {
149
+ if (args[index] !== "--dry-run") {
98
150
  return index;
99
151
  }
152
+ flags.dryRun = true;
153
+ return index;
154
+ }
155
+ /**
156
+ * Handle a single CLI argument and update the flags accordingly.
157
+ *
158
+ * @story docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md
159
+ * @req REQ-MAINT-SAFE - Provide predictable, minimal argument parsing
160
+ */
161
+ function applyFlag(flags, args, index) {
162
+ const afterRoot = handleRootFlag(flags, args, index);
163
+ if (afterRoot !== index) {
164
+ return afterRoot;
165
+ }
166
+ const afterJson = handleJsonFlag(flags, args, index);
167
+ if (afterJson !== index) {
168
+ return afterJson;
169
+ }
170
+ const afterFormat = handleFormatFlag(flags, args, index);
171
+ if (afterFormat !== index) {
172
+ return afterFormat;
173
+ }
174
+ const afterFrom = handleFromFlag(flags, args, index);
175
+ if (afterFrom !== index) {
176
+ return afterFrom;
177
+ }
178
+ const afterTo = handleToFlag(flags, args, index);
179
+ if (afterTo !== index) {
180
+ return afterTo;
181
+ }
182
+ const afterDryRun = handleDryRunFlag(flags, args, index);
183
+ if (afterDryRun !== index) {
184
+ return afterDryRun;
185
+ }
100
186
  return index;
101
187
  }
102
188
  /**
@@ -1,35 +1,81 @@
1
- import type { Rule } from "eslint";
2
1
  /**
3
2
  * Create a fixer function that inserts a @story annotation before the target node.
4
3
  * @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
5
4
  * @req REQ-AUTOFIX - Provide automatic fix function for missing @story annotations
6
5
  */
7
- export declare function createAddStoryFix(target: any): (fixer: any) => any;
6
+ export declare function createAddStoryFix(target: any, annotationTemplate: string): (fixer: any) => any;
8
7
  /**
9
8
  * Create a fixer function for class method annotations.
10
9
  * @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
11
10
  * @req REQ-AUTOFIX - Provide automatic fix for class method annotations
12
11
  */
13
- export declare function createMethodFix(node: any): (fixer: any) => any;
12
+ export declare function createMethodFix(node: any, annotationTemplate: string): (fixer: any) => any;
14
13
  /**
15
14
  * Default set of node types to check for missing @story annotations.
16
15
  * @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
17
16
  * @req REQ-ANNOTATION-REQUIRED - Provide sensible default scope for rule checks
18
17
  */
19
18
  export declare const DEFAULT_SCOPE: string[];
19
+ /**
20
+ * Path to the story file for function-annotation helpers.
21
+ * @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
22
+ * @req REQ-ANNOTATION-REQUIRED - Provide a single source of truth for the canonical story path used by helper modules
23
+ */
24
+ export declare const STORY_PATH = "docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md";
20
25
  /**
21
26
  * Allowed values for export priority option.
22
27
  */
23
28
  export declare const EXPORT_PRIORITY_VALUES: string[];
29
+ import type { Rule } from "eslint";
30
+ type CoreReportOptions = {
31
+ annotationTemplateOverride?: string;
32
+ autoFixToggle?: boolean;
33
+ };
34
+ type ReportDeps = {
35
+ hasStoryAnnotation: (_sourceCode: any, _node: any) => boolean;
36
+ getReportedFunctionName: (_node: any) => string;
37
+ resolveAnnotationTargetNode: (_sourceCode: any, _node: any, _passedTarget: any) => any;
38
+ getNameNodeForReport: (_node: any) => any;
39
+ buildTemplateConfig: (_options?: CoreReportOptions) => {
40
+ effectiveTemplate: string;
41
+ allowFix: boolean;
42
+ };
43
+ extractName: (_node: any) => string;
44
+ getAnnotationTemplate: (_override?: string) => string;
45
+ shouldApplyAutoFix: (_autoFix: boolean | undefined) => boolean;
46
+ createAddStoryFix: (_target: any, _annotationTemplate: string) => any;
47
+ createMethodFix: (_node: any, _annotationTemplate: string) => any;
48
+ };
24
49
  /**
25
- * Report a missing @story annotation for a general function-like node.
50
+ * Core helper to report a missing @story annotation for a function-like node.
51
+ * Delegates actual behavior to injected dependencies so higher-level helpers
52
+ * can remain small while sharing error-reporting behavior.
26
53
  * @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
27
- * @req REQ-AUTOFIX - Report missing annotation and provide autofix using createAddStoryFix
54
+ * @story docs/stories/007.0-DEV-ERROR-REPORTING.story.md
55
+ * @story docs/stories/008.0-DEV-AUTO-FIX.story.md
56
+ * @req REQ-ANNOTATION-REQUIRED
57
+ * @req REQ-AUTOFIX-MISSING
58
+ * @req REQ-ERROR-SPECIFIC
28
59
  */
29
- export declare function reportMissing(context: Rule.RuleContext, sourceCode: any, node: any, target?: any): void;
60
+ export declare function coreReportMissing(deps: ReportDeps, context: Rule.RuleContext, sourceCode: any, config: {
61
+ node: any;
62
+ target?: any;
63
+ options?: CoreReportOptions;
64
+ }): void;
30
65
  /**
31
- * Report missing @story annotation for methods
66
+ * Core helper to report a missing @story annotation for a method-like node.
67
+ * Delegates actual behavior to injected dependencies while keeping this
68
+ * module focused on core error-reporting behavior.
32
69
  * @story docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md
33
- * @req REQ-AUTOFIX - Provide automatic fix for class method annotations
70
+ * @story docs/stories/007.0-DEV-ERROR-REPORTING.story.md
71
+ * @story docs/stories/008.0-DEV-AUTO-FIX.story.md
72
+ * @req REQ-ANNOTATION-REQUIRED
73
+ * @req REQ-AUTOFIX-MISSING
74
+ * @req REQ-ERROR-SPECIFIC
34
75
  */
35
- export declare function reportMethod(context: Rule.RuleContext, sourceCode: any, node: any, target?: any): void;
76
+ export declare function coreReportMethod(deps: ReportDeps, context: Rule.RuleContext, sourceCode: any, config: {
77
+ node: any;
78
+ target?: any;
79
+ options?: CoreReportOptions;
80
+ }): void;
81
+ export {};