eslint-plugin-traceability 1.21.0 → 1.22.0

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 (83) hide show
  1. package/CHANGELOG.md +7 -2
  2. package/README.md +6 -6
  3. package/lib/src/maintenance/batch.js +0 -1
  4. package/lib/src/maintenance/cli.js +8 -10
  5. package/lib/src/maintenance/commands.d.ts +2 -2
  6. package/lib/src/maintenance/commands.js +2 -2
  7. package/lib/src/maintenance/detect.js +7 -7
  8. package/lib/src/maintenance/report.js +2 -2
  9. package/lib/src/maintenance/storyParser.d.ts +16 -0
  10. package/lib/src/maintenance/storyParser.js +167 -0
  11. package/lib/src/rules/helpers/pattern-validators.d.ts +42 -0
  12. package/lib/src/rules/helpers/pattern-validators.js +65 -0
  13. package/lib/src/rules/helpers/prefer-implements-inline.d.ts +16 -0
  14. package/lib/src/rules/helpers/prefer-implements-inline.js +146 -0
  15. package/lib/src/rules/helpers/require-story-comment-detection.d.ts +47 -0
  16. package/lib/src/rules/helpers/require-story-comment-detection.js +141 -0
  17. package/lib/src/rules/helpers/require-story-core.d.ts +6 -6
  18. package/lib/src/rules/helpers/require-story-core.js +10 -10
  19. package/lib/src/rules/helpers/require-story-helpers.d.ts +5 -63
  20. package/lib/src/rules/helpers/require-story-helpers.js +29 -337
  21. package/lib/src/rules/helpers/require-story-io.js +1 -0
  22. package/lib/src/rules/helpers/require-story-name-extraction.d.ts +35 -0
  23. package/lib/src/rules/helpers/require-story-name-extraction.js +107 -0
  24. package/lib/src/rules/helpers/require-story-node-utils.d.ts +43 -0
  25. package/lib/src/rules/helpers/require-story-node-utils.js +115 -0
  26. package/lib/src/rules/helpers/require-test-traceability-helpers.js +1 -0
  27. package/lib/src/rules/helpers/valid-annotation-format-internal.d.ts +2 -2
  28. package/lib/src/rules/helpers/valid-annotation-format-internal.js +13 -5
  29. package/lib/src/rules/helpers/valid-annotation-format-validators.d.ts +14 -14
  30. package/lib/src/rules/helpers/valid-annotation-format-validators.js +31 -22
  31. package/lib/src/rules/helpers/valid-annotation-options.d.ts +0 -10
  32. package/lib/src/rules/helpers/valid-annotation-options.js +22 -92
  33. package/lib/src/rules/helpers/valid-annotation-utils.js +1 -0
  34. package/lib/src/rules/helpers/valid-req-reference-helpers.js +1 -1
  35. package/lib/src/rules/no-redundant-annotation.js +4 -238
  36. package/lib/src/rules/prefer-implements-annotation.d.ts +12 -0
  37. package/lib/src/rules/prefer-implements-annotation.js +9 -164
  38. package/lib/src/rules/require-traceability.d.ts +8 -0
  39. package/lib/src/rules/require-traceability.js +8 -0
  40. package/lib/src/rules/valid-annotation-format.js +14 -10
  41. package/lib/src/utils/annotation-checker.d.ts +3 -2
  42. package/lib/src/utils/annotation-checker.js +4 -2
  43. package/lib/src/utils/branch-annotation-catch-helpers.d.ts +22 -0
  44. package/lib/src/utils/branch-annotation-catch-helpers.js +70 -0
  45. package/lib/src/utils/branch-annotation-helpers.js +11 -187
  46. package/lib/src/utils/branch-annotation-if-helpers.d.ts +1 -0
  47. package/lib/src/utils/branch-annotation-if-helpers.js +59 -0
  48. package/lib/src/utils/branch-annotation-indent-helpers.d.ts +1 -1
  49. package/lib/src/utils/branch-annotation-switch-helpers.d.ts +8 -2
  50. package/lib/src/utils/branch-annotation-switch-helpers.js +10 -4
  51. package/lib/src/utils/branch-validation.d.ts +9 -0
  52. package/lib/src/utils/branch-validation.js +58 -0
  53. package/lib/src/utils/comment-text-helpers.d.ts +31 -0
  54. package/lib/src/utils/comment-text-helpers.js +54 -0
  55. package/lib/src/utils/redundancy-detector.d.ts +85 -0
  56. package/lib/src/utils/redundancy-detector.js +235 -0
  57. package/lib/src/utils/reqAnnotationDetection.js +1 -0
  58. package/lib/tests/config/eslint-config-validation.test.js +1 -0
  59. package/lib/tests/config/flat-config-presets-integration.test.js +1 -0
  60. package/lib/tests/config/require-story-annotation-config.test.js +1 -0
  61. package/lib/tests/fixtures/stale/example.js +1 -0
  62. package/lib/tests/fixtures/update/example.js +1 -0
  63. package/lib/tests/integration/annotation-placement-inside-prettier.integration.test.js +1 -0
  64. package/lib/tests/integration/catch-annotation-prettier.integration.test.js +1 -0
  65. package/lib/tests/integration/else-if-annotation-prettier.integration.test.js +1 -0
  66. package/lib/tests/integration/prettier-test-helpers.js +1 -0
  67. package/lib/tests/integration/require-traceability-test-callbacks.integration.test.js +1 -0
  68. package/lib/tests/maintenance/detect-isolated.test.js +1 -0
  69. package/lib/tests/maintenance/storyParser.test.d.ts +8 -0
  70. package/lib/tests/maintenance/storyParser.test.js +505 -0
  71. package/lib/tests/perf/maintenance-large-workspace.test.js +1 -0
  72. package/lib/tests/perf/valid-annotation-format-large-file.test.js +1 -0
  73. package/lib/tests/plugin-setup.test.js +1 -0
  74. package/lib/tests/rules/error-reporting.test.js +1 -0
  75. package/lib/tests/rules/no-redundant-annotation.test.js +1 -0
  76. package/lib/tests/rules/require-story-helpers.test.js +3 -2
  77. package/lib/tests/rules/require-test-traceability.test.js +1 -0
  78. package/lib/tests/rules/valid-req-reference.test.js +2 -0
  79. package/lib/tests/utils/branch-annotation-catch-insert-position.test.js +1 -0
  80. package/lib/tests/utils/branch-annotation-else-if-insert-position.test.js +1 -0
  81. package/lib/tests/utils/branch-annotation-helpers.test.js +1 -0
  82. package/package.json +18 -10
  83. package/user-docs/api-reference.md +2 -2
package/CHANGELOG.md CHANGED
@@ -1,9 +1,14 @@
1
- # [1.21.0](https://github.com/voder-ai/eslint-plugin-traceability/compare/v1.20.0...v1.21.0) (2025-12-19)
1
+ # [1.22.0](https://github.com/voder-ai/eslint-plugin-traceability/compare/v1.21.1...v1.22.0) (2026-01-10)
2
+
3
+
4
+ ### Bug Fixes
5
+
6
+ * move voder-ai to optionalDependencies to allow CI without GitHub Packages access ([1a674cb](https://github.com/voder-ai/eslint-plugin-traceability/commit/1a674cb65d5223c75710910817393667435bfcd8))
2
7
 
3
8
 
4
9
  ### Features
5
10
 
6
- * support inside-brace placement for function-level rules ([064b1a4](https://github.com/voder-ai/eslint-plugin-traceability/commit/064b1a4e7627b5e35afd074752724ab5958e9d8b))
11
+ * **ci:** add post-deployment verification step ([00d3d21](https://github.com/voder-ai/eslint-plugin-traceability/commit/00d3d214f21e18bfc26e3de4fbcb0bd9f0aa8f28))
7
12
 
8
13
  # Changelog
9
14
 
package/README.md CHANGED
@@ -121,15 +121,15 @@ Traceability annotations are typically placed immediately adjacent to the code t
121
121
 
122
122
  - **Function-level (`traceability/require-story-annotation`, `traceability/require-req-annotation`)**
123
123
 
124
- Function-level rules continue to accept annotations:
125
- - As JSDoc blocks immediately preceding the function, or
126
- - As line comments placed directly before the function declaration or expression.
124
+ Function-level rules support both before-function and inside-body placement, controlled by the same `annotationPlacement` option described above:
125
+ - `"before"` – Annotations are written as JSDoc blocks immediately preceding the function, or as line comments placed directly before the function declaration or expression.
126
+ - `"inside"` Annotations are expected to appear on the first comment-only lines inside function and method bodies; comments before the function are ignored for block-bodied functions in this mode, while TypeScript declarations and signature-only nodes still rely on before-node annotations.
127
127
 
128
- This placement is stable and supported for all current versions. Future versions may introduce an **inside-brace** placement mode for function bodies (similar to branch blocks) to align function annotations with the branch-level `"inside"` standard, but that behaviour is not yet implemented in the current release.
128
+ For full details and migration guidance between placement styles, see the [API Reference](user-docs/api-reference.md) and the migration guide ([user-docs/migration-guide.md](user-docs/migration-guide.md)).
129
129
 
130
130
  For full configuration details and migration guidance between placement styles, see:
131
131
 
132
- - `traceability/require-branch-annotation` rule docs: [docs/rules/require-branch-annotation.md](docs/rules/require-branch-annotation.md)
132
+ - `traceability/require-branch-annotation` rule docs: [docs/rules/require-branch-annotation.md](https://github.com/voder-ai/eslint-plugin-traceability/blob/main/docs/rules/require-branch-annotation.md)
133
133
  - Migration guide: [user-docs/migration-guide.md](user-docs/migration-guide.md)
134
134
 
135
135
  ### Available Rules
@@ -280,7 +280,7 @@ Removing "duplicate" annotations would break the verification workflow by forcin
280
280
 
281
281
  ## Verification Workflow Guide
282
282
 
283
- For detailed verification workflows, examples, and best practices, see the [Verification Workflow Guide](docs/verification-workflow-guide.md).
283
+ For detailed verification workflows, examples, and best practices, see the [Verification Workflow Guide](https://github.com/voder-ai/eslint-plugin-traceability/blob/main/docs/verification-workflow-guide.md).
284
284
 
285
285
  ## API Reference
286
286
 
@@ -15,7 +15,6 @@ const detect_1 = require("./detect");
15
15
  */
16
16
  function batchUpdateAnnotations(codebasePath, mappings) {
17
17
  let totalUpdated = 0;
18
- // @story docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md // @req REQ-MAINT-BATCH - Perform batch updates
19
18
  for (const { oldPath, newPath } of mappings) {
20
19
  totalUpdated += (0, update_1.updateAnnotationReferences)(codebasePath, oldPath, newPath);
21
20
  }
@@ -19,7 +19,6 @@ function runMaintenanceCli(rawArgv) {
19
19
  const { subcommand: command } = initialNormalized;
20
20
  if (!command || command === "-h" || command === "--help") {
21
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
22
  printHelp();
24
23
  return commands_1.EXIT_OK;
25
24
  }
@@ -28,35 +27,34 @@ function runMaintenanceCli(rawArgv) {
28
27
  const normalized = initialNormalized;
29
28
  try {
30
29
  // @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
30
  switch (command) {
33
31
  case "detect":
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
32
+ // @supports docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md REQ-MAINT-DETECT
35
33
  return (0, commands_1.handleDetect)(normalized);
36
34
  case "verify":
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
35
+ // @supports docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md REQ-MAINT-VERIFY
38
36
  return (0, commands_1.handleVerify)(normalized);
39
37
  case "report":
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
38
+ // @supports docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md REQ-MAINT-REPORT
41
39
  return (0, commands_1.handleReport)(normalized);
42
40
  case "update": {
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
41
+ // @supports docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md REQ-MAINT-UPDATE
44
42
  const result = (0, commands_1.handleUpdate)(normalized);
45
43
  if (result === commands_1.EXIT_USAGE) {
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
44
+ // @supports docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md REQ-MAINT-SAFE
47
45
  printHelp();
48
46
  }
49
47
  return result;
50
48
  }
51
49
  default:
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
50
+ // @supports docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md REQ-MAINT-SAFE
53
51
  console.error(`Unknown command: ${command}`);
54
52
  printHelp();
55
53
  return commands_1.EXIT_USAGE;
56
54
  }
57
55
  }
58
56
  catch (error) {
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
57
+ // @supports docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md REQ-MAINT-SAFE
60
58
  const message = error instanceof Error
61
59
  ? error.message
62
60
  : "Unknown error in maintenance CLI";
@@ -70,7 +68,7 @@ function runMaintenanceCli(rawArgv) {
70
68
  * @req REQ-MAINT-SAFE - Provide discoverable CLI usage information
71
69
  */
72
70
  function printHelp() {
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
71
+ // @supports docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md REQ-MAINT-SAFE
74
72
  console.log(`traceability-maint - Traceability annotation maintenance tools
75
73
 
76
74
  Usage:
@@ -3,7 +3,7 @@ export declare const EXIT_OK = 0;
3
3
  export declare const EXIT_STALE = 1;
4
4
  export declare const EXIT_USAGE = 2;
5
5
  /**
6
- * Handle the `detect` subcommand for stale @story annotations.
6
+ * Handle the `detect` subcommand for stale story annotations.
7
7
  * @story docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md
8
8
  * @req REQ-MAINT-DETECT - CLI surface for detection of stale annotations
9
9
  * @req REQ-MAINT-SAFE - Return specific exit codes for stale vs clean states
@@ -27,7 +27,7 @@ export declare function handleVerify(normalized: NormalizedCliArgs): number;
27
27
  */
28
28
  export declare function handleReport(normalized: NormalizedCliArgs): number;
29
29
  /**
30
- * Handle the `update` subcommand to rewrite @story annotation references.
30
+ * Handle the `update` subcommand to rewrite story annotation references.
31
31
  * @story docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md
32
32
  * @req REQ-MAINT-UPDATE - CLI surface for updating annotation references
33
33
  * @req REQ-MAINT-SAFE - Provide dry-run mode and explicit parameter checks
@@ -24,7 +24,7 @@ exports.EXIT_OK = 0;
24
24
  exports.EXIT_STALE = 1;
25
25
  exports.EXIT_USAGE = 2;
26
26
  /**
27
- * Handle the `detect` subcommand for stale @story annotations.
27
+ * Handle the `detect` subcommand for stale story annotations.
28
28
  * @story docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md
29
29
  * @req REQ-MAINT-DETECT - CLI surface for detection of stale annotations
30
30
  * @req REQ-MAINT-SAFE - Return specific exit codes for stale vs clean states
@@ -95,7 +95,7 @@ function handleReport(normalized) {
95
95
  return exports.EXIT_OK;
96
96
  }
97
97
  /**
98
- * Handle the `update` subcommand to rewrite @story annotation references.
98
+ * Handle the `update` subcommand to rewrite story annotation references.
99
99
  * @story docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md
100
100
  * @req REQ-MAINT-UPDATE - CLI surface for updating annotation references
101
101
  * @req REQ-MAINT-SAFE - Provide dry-run mode and explicit parameter checks
@@ -84,7 +84,7 @@ function processFileForStaleAnnotations(file, workspaceRoot, cwd, stale) {
84
84
  }
85
85
  catch {
86
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
87
+ // @supports docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md REQ-MAINT-SAFE
88
88
  return;
89
89
  }
90
90
  const regex = /@story\s+([^\s]+)/g;
@@ -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
- // @supports 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
119
119
  return;
120
120
  }
121
121
  // @story docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md
@@ -141,7 +141,7 @@ function getInProjectCandidates(storyProjectCandidate, storyCodebaseCandidate, w
141
141
  }
142
142
  catch {
143
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
144
+ // @supports docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md REQ-MAINT-SAFE
145
145
  projectBoundary = {
146
146
  isWithinProject: false,
147
147
  candidate: storyProjectCandidate,
@@ -153,7 +153,7 @@ function getInProjectCandidates(storyProjectCandidate, storyCodebaseCandidate, w
153
153
  }
154
154
  catch {
155
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
156
+ // @supports docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md REQ-MAINT-SAFE
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
- // @supports 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
165
165
  inProjectCandidates.push(projectBoundary.candidate);
166
166
  }
167
167
  if (codebaseBoundary.isWithinProject) {
168
- // @supports 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
169
169
  inProjectCandidates.push(codebaseBoundary.candidate);
170
170
  }
171
171
  return inProjectCandidates;
@@ -182,7 +182,7 @@ function anyInProjectCandidateExists(inProjectCandidates) {
182
182
  (p) => {
183
183
  const exists = fs.existsSync(p);
184
184
  if (!exists) {
185
- // @supports 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
186
186
  }
187
187
  return exists;
188
188
  });
@@ -12,8 +12,8 @@ const detect_1 = require("./detect");
12
12
  */
13
13
  function generateMaintenanceReport(codebasePath) {
14
14
  const staleAnnotations = (0, detect_1.detectStaleAnnotations)(codebasePath);
15
- // @supports docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md REQ-MAINT-SAFE - When no stale annotations are found, return empty string to indicate no actions required
16
- // @supports docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md REQ-MAINT-REPORT - When stale annotations exist, produce a newline-separated report
15
+ // @supports docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md REQ-MAINT-SAFE
16
+ // @supports docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md REQ-MAINT-REPORT
17
17
  if (staleAnnotations.length === 0) {
18
18
  return "";
19
19
  }
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Extract requirement IDs from story file content
3
+ * @story docs/stories/010.0-DEV-DEEP-VALIDATION.story.md
4
+ * @req REQ-DEEP-PARSE - Parse story file content to identify available requirements
5
+ * @req REQ-DEEP-FORMAT - Support finding requirement IDs in multiple markdown contexts
6
+ * @req REQ-DEEP-SECTION - Handle requirements in different story file sections
7
+ */
8
+ export declare function extractRequirementsFromStoryFile(filePath: string): Set<string>;
9
+ /**
10
+ * Extract requirement IDs from story file content string
11
+ * @story docs/stories/010.0-DEV-DEEP-VALIDATION.story.md
12
+ * @req REQ-DEEP-PARSE - Parse story file content to identify available requirements
13
+ * @req REQ-DEEP-FORMAT - Support finding requirement IDs in multiple markdown contexts
14
+ * @req REQ-DEEP-SECTION - Handle requirements in different story file sections
15
+ */
16
+ export declare function extractRequirementsFromContent(content: string): Set<string>;
@@ -0,0 +1,167 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.extractRequirementsFromStoryFile = extractRequirementsFromStoryFile;
37
+ exports.extractRequirementsFromContent = extractRequirementsFromContent;
38
+ /**
39
+ * Parser for extracting requirements from story files
40
+ * @story docs/stories/010.0-DEV-DEEP-VALIDATION.story.md
41
+ * @req REQ-DEEP-PARSE - Parse story file content to identify available requirements
42
+ * @req REQ-DEEP-FORMAT - Support finding requirement IDs in multiple markdown contexts
43
+ * @req REQ-DEEP-SECTION - Handle requirements in different story file sections
44
+ */
45
+ const fs = __importStar(require("fs"));
46
+ /**
47
+ * Extract requirement IDs from story file content
48
+ * @story docs/stories/010.0-DEV-DEEP-VALIDATION.story.md
49
+ * @req REQ-DEEP-PARSE - Parse story file content to identify available requirements
50
+ * @req REQ-DEEP-FORMAT - Support finding requirement IDs in multiple markdown contexts
51
+ * @req REQ-DEEP-SECTION - Handle requirements in different story file sections
52
+ */
53
+ function extractRequirementsFromStoryFile(filePath) {
54
+ try {
55
+ const content = fs.readFileSync(filePath, "utf8");
56
+ return extractRequirementsFromContent(content);
57
+ }
58
+ catch {
59
+ // @story docs/stories/010.0-DEV-DEEP-VALIDATION.story.md
60
+ // @req REQ-DEEP-PARSE - Handle file read errors gracefully
61
+ return new Set();
62
+ }
63
+ }
64
+ /**
65
+ * Extract requirement IDs from story file content string
66
+ * @story docs/stories/010.0-DEV-DEEP-VALIDATION.story.md
67
+ * @req REQ-DEEP-PARSE - Parse story file content to identify available requirements
68
+ * @req REQ-DEEP-FORMAT - Support finding requirement IDs in multiple markdown contexts
69
+ * @req REQ-DEEP-SECTION - Handle requirements in different story file sections
70
+ */
71
+ function extractRequirementsFromContent(content) {
72
+ const requirements = new Set();
73
+ // Strategy 1: Extract from structured sections (## Requirements, ## Acceptance Criteria)
74
+ // @story docs/stories/010.0-DEV-DEEP-VALIDATION.story.md
75
+ // @req REQ-DEEP-SECTION - Handle requirements in different story file sections
76
+ const sectionRequirements = extractFromSections(content);
77
+ sectionRequirements.forEach((req) => requirements.add(req));
78
+ // Strategy 2: Fallback to regex-based extraction for REQ-XXX-YYY patterns anywhere in file
79
+ // @story docs/stories/010.0-DEV-DEEP-VALIDATION.story.md
80
+ // @req REQ-DEEP-FORMAT - Support finding requirement IDs in multiple markdown contexts
81
+ const regexRequirements = extractWithRegex(content);
82
+ regexRequirements.forEach((req) => requirements.add(req));
83
+ return requirements;
84
+ }
85
+ /**
86
+ * Extract requirements from structured markdown sections
87
+ * @story docs/stories/010.0-DEV-DEEP-VALIDATION.story.md
88
+ * @req REQ-DEEP-SECTION - Handle requirements in different story file sections
89
+ * @req REQ-DEEP-FORMAT - Support finding requirement IDs in multiple markdown contexts
90
+ */
91
+ function extractFromSections(content) {
92
+ const requirements = new Set();
93
+ const lines = content.split("\n");
94
+ let inRequirementsSection = false;
95
+ let inAcceptanceCriteriaSection = false;
96
+ for (const line of lines) {
97
+ // Detect section headers
98
+ if (line.match(/^##\s+Requirements/i)) {
99
+ // @story docs/stories/010.0-DEV-DEEP-VALIDATION.story.md
100
+ // @req REQ-DEEP-SECTION - Parse ## Requirements sections
101
+ inRequirementsSection = true;
102
+ inAcceptanceCriteriaSection = false;
103
+ continue;
104
+ }
105
+ else if (line.match(/^##\s+Acceptance\s+Criteria/i)) {
106
+ // @story docs/stories/010.0-DEV-DEEP-VALIDATION.story.md
107
+ // @req REQ-DEEP-SECTION - Parse ## Acceptance Criteria sections
108
+ inAcceptanceCriteriaSection = true;
109
+ inRequirementsSection = false;
110
+ continue;
111
+ }
112
+ else if (line.match(/^##\s+/)) {
113
+ // New section that's not Requirements or Acceptance Criteria
114
+ inRequirementsSection = false;
115
+ inAcceptanceCriteriaSection = false;
116
+ continue;
117
+ }
118
+ // Extract requirements from active sections
119
+ if (inRequirementsSection || inAcceptanceCriteriaSection) {
120
+ // @story docs/stories/010.0-DEV-DEEP-VALIDATION.story.md
121
+ // @req REQ-DEEP-FORMAT - Extract requirement IDs from list items
122
+ const reqIds = extractReqIdsFromLine(line);
123
+ reqIds.forEach((req) => requirements.add(req));
124
+ }
125
+ }
126
+ return requirements;
127
+ }
128
+ /**
129
+ * Extract requirement IDs from a single line
130
+ * @story docs/stories/010.0-DEV-DEEP-VALIDATION.story.md
131
+ * @req REQ-DEEP-FORMAT - Support finding requirement IDs in multiple markdown contexts
132
+ */
133
+ function extractReqIdsFromLine(line) {
134
+ const requirements = [];
135
+ // Pattern 1: - **REQ-XXX-YYY**: Description
136
+ // @story docs/stories/010.0-DEV-DEEP-VALIDATION.story.md
137
+ // @req REQ-DEEP-FORMAT - Extract from bold requirement format
138
+ const boldPattern = /\*\*(REQ-[A-Z0-9-]+)\*\*/g;
139
+ let match;
140
+ while ((match = boldPattern.exec(line)) !== null) {
141
+ requirements.push(match[1]);
142
+ }
143
+ // Pattern 2: REQ-XXX-YYY anywhere in the line (not already captured)
144
+ // @story docs/stories/010.0-DEV-DEEP-VALIDATION.story.md
145
+ // @req REQ-DEEP-FORMAT - Extract from plain text mentions
146
+ const plainPattern = /\b(REQ-[A-Z0-9-]+)\b/g;
147
+ while ((match = plainPattern.exec(line)) !== null) {
148
+ if (!requirements.includes(match[1])) {
149
+ requirements.push(match[1]);
150
+ }
151
+ }
152
+ return requirements;
153
+ }
154
+ /**
155
+ * Extract requirements using regex fallback (for content outside structured sections)
156
+ * @story docs/stories/010.0-DEV-DEEP-VALIDATION.story.md
157
+ * @req REQ-DEEP-FORMAT - Support finding requirement IDs in multiple markdown contexts
158
+ */
159
+ function extractWithRegex(content) {
160
+ const requirements = new Set();
161
+ const regex = /\b(REQ-[A-Z0-9-]+)\b/g;
162
+ let match;
163
+ while ((match = regex.exec(content)) !== null) {
164
+ requirements.add(match[1]);
165
+ }
166
+ return requirements;
167
+ }
@@ -0,0 +1,42 @@
1
+ /**
2
+ * Pattern validation helpers for valid-annotation-format options.
3
+ *
4
+ * @story docs/stories/010.1-DEV-CONFIGURABLE-PATTERNS.story.md
5
+ * @req REQ-REGEX-VALIDATION - Validate that configured patterns are valid regular expressions
6
+ */
7
+ /**
8
+ * Build an error message for an invalid regex pattern.
9
+ *
10
+ * @supports docs/stories/010.1-DEV-CONFIGURABLE-PATTERNS.story.md REQ-REGEX-VALIDATION
11
+ */
12
+ export declare function buildInvalidRegexError(field: string, pattern: string): string;
13
+ /**
14
+ * Arguments for the resolvePattern helper.
15
+ */
16
+ export interface ResolvePatternArgs {
17
+ nestedPattern: string | undefined;
18
+ nestedFieldName: string;
19
+ flatPattern: string | undefined;
20
+ flatFieldName: string;
21
+ defaultPattern: RegExp;
22
+ errors?: string[];
23
+ }
24
+ /**
25
+ * Resolve a user-configured regex pattern, handling both nested and flat
26
+ * configuration shapes and accumulating validation errors.
27
+ *
28
+ * @story docs/stories/010.1-DEV-CONFIGURABLE-PATTERNS.story.md
29
+ * @req REQ-PATTERN-CONFIG
30
+ * @req REQ-REGEX-VALIDATION
31
+ * @req REQ-BACKWARD-COMPAT
32
+ */
33
+ export declare function resolvePattern({ nestedPattern, nestedFieldName, flatPattern, flatFieldName, defaultPattern, errors, }: ResolvePatternArgs): RegExp;
34
+ /**
35
+ * Resolve an example string, preferring nested over flat configuration,
36
+ * and falling back to the provided default when necessary.
37
+ *
38
+ * @story docs/stories/010.1-DEV-CONFIGURABLE-PATTERNS.story.md
39
+ * @req REQ-EXAMPLE-MESSAGES
40
+ * @req REQ-BACKWARD-COMPAT
41
+ */
42
+ export declare function resolveExample(nestedExample: string | undefined, flatExample: string | undefined, defaultExample: string): string;
@@ -0,0 +1,65 @@
1
+ "use strict";
2
+ /**
3
+ * Pattern validation helpers for valid-annotation-format options.
4
+ *
5
+ * @story docs/stories/010.1-DEV-CONFIGURABLE-PATTERNS.story.md
6
+ * @req REQ-REGEX-VALIDATION - Validate that configured patterns are valid regular expressions
7
+ */
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.buildInvalidRegexError = buildInvalidRegexError;
10
+ exports.resolvePattern = resolvePattern;
11
+ exports.resolveExample = resolveExample;
12
+ /**
13
+ * Build an error message for an invalid regex pattern.
14
+ *
15
+ * @supports docs/stories/010.1-DEV-CONFIGURABLE-PATTERNS.story.md REQ-REGEX-VALIDATION
16
+ */
17
+ function buildInvalidRegexError(field, pattern) {
18
+ return `Invalid regular expression for option "${field}": "${pattern}"`;
19
+ }
20
+ /**
21
+ * Resolve a user-configured regex pattern, handling both nested and flat
22
+ * configuration shapes and accumulating validation errors.
23
+ *
24
+ * @story docs/stories/010.1-DEV-CONFIGURABLE-PATTERNS.story.md
25
+ * @req REQ-PATTERN-CONFIG
26
+ * @req REQ-REGEX-VALIDATION
27
+ * @req REQ-BACKWARD-COMPAT
28
+ */
29
+ function resolvePattern({ nestedPattern, nestedFieldName, flatPattern, flatFieldName, defaultPattern, errors, }) {
30
+ const effective = typeof nestedPattern === "string"
31
+ ? { value: nestedPattern, field: nestedFieldName }
32
+ : typeof flatPattern === "string"
33
+ ? { value: flatPattern, field: flatFieldName }
34
+ : null;
35
+ if (!effective) {
36
+ return defaultPattern;
37
+ }
38
+ try {
39
+ return new RegExp(effective.value);
40
+ }
41
+ catch {
42
+ const error = buildInvalidRegexError(effective.field, effective.value);
43
+ if (errors) {
44
+ errors.push(error);
45
+ }
46
+ return defaultPattern;
47
+ }
48
+ }
49
+ /**
50
+ * Resolve an example string, preferring nested over flat configuration,
51
+ * and falling back to the provided default when necessary.
52
+ *
53
+ * @story docs/stories/010.1-DEV-CONFIGURABLE-PATTERNS.story.md
54
+ * @req REQ-EXAMPLE-MESSAGES
55
+ * @req REQ-BACKWARD-COMPAT
56
+ */
57
+ function resolveExample(nestedExample, flatExample, defaultExample) {
58
+ if (typeof nestedExample === "string" && nestedExample.trim()) {
59
+ return nestedExample;
60
+ }
61
+ if (typeof flatExample === "string" && flatExample.trim()) {
62
+ return flatExample;
63
+ }
64
+ return defaultExample;
65
+ }
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Inline comment processing for prefer-implements-annotation rule.
3
+ * Handles migration of inline comment story and requirement patterns to supports format.
4
+ *
5
+ * @story docs/stories/010.3-DEV-MIGRATE-TO-SUPPORTS.story.md
6
+ * @req REQ-MIGRATE-INLINE
7
+ */
8
+ import type { Rule } from "eslint";
9
+ export type LineComment = {
10
+ type: "Line";
11
+ } & any;
12
+ /**
13
+ * Scan sequences of Line comments for inline legacy story and requirement patterns
14
+ * and report diagnostics with optional auto-fixes.
15
+ */
16
+ export declare function processInlineComments(context: Rule.RuleContext, lineComments: LineComment[]): void;