xtrm-tools 2.2.0 → 2.4.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 (286) hide show
  1. package/README.md +127 -104
  2. package/cli/dist/index.cjs +1078 -970
  3. package/cli/dist/index.cjs.map +1 -1
  4. package/cli/package.json +1 -1
  5. package/config/pi/extensions/beads.ts +33 -5
  6. package/config/pi/extensions/service-skills.ts +17 -9
  7. package/config/pi/install-schema.json +2 -1
  8. package/hooks/beads-gate-core.mjs +6 -4
  9. package/hooks/beads-memory-gate.mjs +12 -5
  10. package/hooks/hooks.json +126 -0
  11. package/package.json +3 -1
  12. package/skills/test-planning/SKILL.md +208 -0
  13. package/skills/test-planning/evals/evals.json +23 -0
  14. package/skills/using-xtrm/SKILL.md +5 -27
  15. package/project-skills/tdd-guard/.claude/hooks/tdd-guard-pretool-bridge.cjs +0 -103
  16. package/project-skills/tdd-guard/.claude/settings.json +0 -38
  17. package/project-skills/tdd-guard/.claude/skills/using-tdd-guard/SKILL.md +0 -79
  18. package/project-skills/tdd-guard/CLAUDE.md +0 -98
  19. package/project-skills/tdd-guard/CONTRIBUTING.md +0 -38
  20. package/project-skills/tdd-guard/DEVELOPMENT.md +0 -127
  21. package/project-skills/tdd-guard/LICENSE +0 -21
  22. package/project-skills/tdd-guard/README.md +0 -398
  23. package/project-skills/tdd-guard/docs/adr/001-claude-session-subdirectory.md +0 -52
  24. package/project-skills/tdd-guard/docs/adr/002-secure-claude-binary-path.md +0 -56
  25. package/project-skills/tdd-guard/docs/adr/003-remove-configurable-data-directory.md +0 -56
  26. package/project-skills/tdd-guard/docs/adr/004-monorepo-architecture.md +0 -64
  27. package/project-skills/tdd-guard/docs/adr/005-claude-project-dir-support.md +0 -55
  28. package/project-skills/tdd-guard/docs/adr/006-phpunit-separate-repository.md +0 -93
  29. package/project-skills/tdd-guard/docs/adr/007-golangci-lint-path-support.md +0 -83
  30. package/project-skills/tdd-guard/docs/adr/008-storybook-reporter-design.md +0 -182
  31. package/project-skills/tdd-guard/docs/assets/tdd-guard-demo-screenshot.gif +0 -0
  32. package/project-skills/tdd-guard/docs/config-migration.md +0 -143
  33. package/project-skills/tdd-guard/docs/configuration.md +0 -137
  34. package/project-skills/tdd-guard/docs/custom-instructions.md +0 -43
  35. package/project-skills/tdd-guard/docs/enforcement.md +0 -46
  36. package/project-skills/tdd-guard/docs/ignore-patterns.md +0 -81
  37. package/project-skills/tdd-guard/docs/linting.md +0 -109
  38. package/project-skills/tdd-guard/docs/quick-commands.md +0 -52
  39. package/project-skills/tdd-guard/docs/session-management.md +0 -75
  40. package/project-skills/tdd-guard/docs/storybook-vitest-addon.md +0 -120
  41. package/project-skills/tdd-guard/docs/validation-model.md +0 -63
  42. package/project-skills/tdd-guard/eslint.config.mjs +0 -140
  43. package/project-skills/tdd-guard/package-lock.json +0 -16937
  44. package/project-skills/tdd-guard/package.json +0 -102
  45. package/project-skills/tdd-guard/reporters/go/README.md +0 -67
  46. package/project-skills/tdd-guard/reporters/go/cmd/tdd-guard-go/main.go +0 -127
  47. package/project-skills/tdd-guard/reporters/go/cmd/tdd-guard-go/main_test.go +0 -280
  48. package/project-skills/tdd-guard/reporters/go/go.mod +0 -3
  49. package/project-skills/tdd-guard/reporters/go/go.sum +0 -0
  50. package/project-skills/tdd-guard/reporters/go/internal/formatter/formatter.go +0 -126
  51. package/project-skills/tdd-guard/reporters/go/internal/formatter/formatter_test.go +0 -264
  52. package/project-skills/tdd-guard/reporters/go/internal/io/tee_reader.go +0 -26
  53. package/project-skills/tdd-guard/reporters/go/internal/io/tee_reader_test.go +0 -37
  54. package/project-skills/tdd-guard/reporters/go/internal/parser/mixed_reader.go +0 -94
  55. package/project-skills/tdd-guard/reporters/go/internal/parser/mixed_reader_test.go +0 -198
  56. package/project-skills/tdd-guard/reporters/go/internal/parser/parser.go +0 -245
  57. package/project-skills/tdd-guard/reporters/go/internal/parser/parser_test.go +0 -547
  58. package/project-skills/tdd-guard/reporters/go/internal/storage/storage.go +0 -35
  59. package/project-skills/tdd-guard/reporters/go/internal/storage/storage_test.go +0 -113
  60. package/project-skills/tdd-guard/reporters/go/internal/transformer/transformer.go +0 -103
  61. package/project-skills/tdd-guard/reporters/go/internal/transformer/transformer_test.go +0 -303
  62. package/project-skills/tdd-guard/reporters/jest/README.md +0 -102
  63. package/project-skills/tdd-guard/reporters/jest/package.json +0 -38
  64. package/project-skills/tdd-guard/reporters/jest/src/JestReporter.test-data.ts +0 -199
  65. package/project-skills/tdd-guard/reporters/jest/src/JestReporter.test.ts +0 -302
  66. package/project-skills/tdd-guard/reporters/jest/src/JestReporter.ts +0 -201
  67. package/project-skills/tdd-guard/reporters/jest/src/index.ts +0 -4
  68. package/project-skills/tdd-guard/reporters/jest/src/types.ts +0 -42
  69. package/project-skills/tdd-guard/reporters/jest/tsconfig.json +0 -11
  70. package/project-skills/tdd-guard/reporters/phpunit/.php-cs-fixer.php +0 -28
  71. package/project-skills/tdd-guard/reporters/phpunit/README.md +0 -97
  72. package/project-skills/tdd-guard/reporters/phpunit/SYNC_README.md +0 -29
  73. package/project-skills/tdd-guard/reporters/phpunit/composer.json +0 -55
  74. package/project-skills/tdd-guard/reporters/phpunit/phpunit.xml.dist +0 -19
  75. package/project-skills/tdd-guard/reporters/phpunit/psalm.xml +0 -44
  76. package/project-skills/tdd-guard/reporters/phpunit/src/Event/ErroredTestSubscriber.php +0 -28
  77. package/project-skills/tdd-guard/reporters/phpunit/src/Event/FailedTestSubscriber.php +0 -28
  78. package/project-skills/tdd-guard/reporters/phpunit/src/Event/IncompleteTestSubscriber.php +0 -28
  79. package/project-skills/tdd-guard/reporters/phpunit/src/Event/PassedTestSubscriber.php +0 -27
  80. package/project-skills/tdd-guard/reporters/phpunit/src/Event/SkippedTestSubscriber.php +0 -28
  81. package/project-skills/tdd-guard/reporters/phpunit/src/Event/TestRunnerFinishedSubscriber.php +0 -24
  82. package/project-skills/tdd-guard/reporters/phpunit/src/PathValidator.php +0 -88
  83. package/project-skills/tdd-guard/reporters/phpunit/src/Storage.php +0 -26
  84. package/project-skills/tdd-guard/reporters/phpunit/src/TddGuardExtension.php +0 -33
  85. package/project-skills/tdd-guard/reporters/phpunit/src/TddGuardListener.php +0 -158
  86. package/project-skills/tdd-guard/reporters/phpunit/src/TddGuardSubscriber.php +0 -35
  87. package/project-skills/tdd-guard/reporters/phpunit/src/TestResultCollector.php +0 -105
  88. package/project-skills/tdd-guard/reporters/phpunit/tests/PathValidatorTest.php +0 -74
  89. package/project-skills/tdd-guard/reporters/phpunit/tests/TddGuardExtensionFailedTest.php +0 -241
  90. package/project-skills/tdd-guard/reporters/phpunit/tests/TddGuardExtensionTest.php +0 -84
  91. package/project-skills/tdd-guard/reporters/phpunit/tests/TddGuardStorageLocationTest.php +0 -71
  92. package/project-skills/tdd-guard/reporters/pytest/README.md +0 -77
  93. package/project-skills/tdd-guard/reporters/pytest/pyproject.toml +0 -43
  94. package/project-skills/tdd-guard/reporters/pytest/pytest.ini.example +0 -7
  95. package/project-skills/tdd-guard/reporters/pytest/tdd_guard_pytest/__init__.py +0 -1
  96. package/project-skills/tdd-guard/reporters/pytest/tdd_guard_pytest/pytest_reporter.py +0 -134
  97. package/project-skills/tdd-guard/reporters/pytest/tests/__init__.py +0 -1
  98. package/project-skills/tdd-guard/reporters/pytest/tests/conftest.py +0 -3
  99. package/project-skills/tdd-guard/reporters/pytest/tests/helpers.py +0 -293
  100. package/project-skills/tdd-guard/reporters/pytest/tests/test_config_option.py +0 -38
  101. package/project-skills/tdd-guard/reporters/pytest/tests/test_path_validation.py +0 -59
  102. package/project-skills/tdd-guard/reporters/pytest/tests/test_plugin_config.py +0 -32
  103. package/project-skills/tdd-guard/reporters/pytest/tests/test_project_root.py +0 -296
  104. package/project-skills/tdd-guard/reporters/pytest/tests/test_pytest_reporter.py +0 -137
  105. package/project-skills/tdd-guard/reporters/rspec/Gemfile +0 -3
  106. package/project-skills/tdd-guard/reporters/rust/Cargo.lock +0 -458
  107. package/project-skills/tdd-guard/reporters/rust/Cargo.toml +0 -33
  108. package/project-skills/tdd-guard/reporters/rust/Makefile.example +0 -95
  109. package/project-skills/tdd-guard/reporters/rust/README.md +0 -88
  110. package/project-skills/tdd-guard/reporters/rust/src/error_parser.rs +0 -309
  111. package/project-skills/tdd-guard/reporters/rust/src/main.rs +0 -464
  112. package/project-skills/tdd-guard/reporters/rust/src/parser.rs +0 -225
  113. package/project-skills/tdd-guard/reporters/rust/src/transformer.rs +0 -409
  114. package/project-skills/tdd-guard/reporters/storybook/README.md +0 -108
  115. package/project-skills/tdd-guard/reporters/storybook/package-lock.json +0 -9482
  116. package/project-skills/tdd-guard/reporters/storybook/package.json +0 -43
  117. package/project-skills/tdd-guard/reporters/storybook/src/StorybookReporter.test-data.ts +0 -22
  118. package/project-skills/tdd-guard/reporters/storybook/src/StorybookReporter.test.ts +0 -190
  119. package/project-skills/tdd-guard/reporters/storybook/src/StorybookReporter.ts +0 -88
  120. package/project-skills/tdd-guard/reporters/storybook/src/index.ts +0 -12
  121. package/project-skills/tdd-guard/reporters/storybook/src/types.ts +0 -37
  122. package/project-skills/tdd-guard/reporters/storybook/tsconfig.json +0 -11
  123. package/project-skills/tdd-guard/reporters/test/artifacts/go/failing/go.mod +0 -3
  124. package/project-skills/tdd-guard/reporters/test/artifacts/go/failing/single_failing_test.go +0 -13
  125. package/project-skills/tdd-guard/reporters/test/artifacts/go/import/go.mod +0 -3
  126. package/project-skills/tdd-guard/reporters/test/artifacts/go/import/single_import_error_test.go +0 -17
  127. package/project-skills/tdd-guard/reporters/test/artifacts/go/passing/go.mod +0 -3
  128. package/project-skills/tdd-guard/reporters/test/artifacts/go/passing/single_passing_test.go +0 -13
  129. package/project-skills/tdd-guard/reporters/test/artifacts/jest/single-failing.test.js +0 -5
  130. package/project-skills/tdd-guard/reporters/test/artifacts/jest/single-import-error.test.js +0 -8
  131. package/project-skills/tdd-guard/reporters/test/artifacts/jest/single-passing.test.js +0 -5
  132. package/project-skills/tdd-guard/reporters/test/artifacts/phpunit/SingleFailingTest.php +0 -11
  133. package/project-skills/tdd-guard/reporters/test/artifacts/phpunit/SingleImportErrorTest.php +0 -14
  134. package/project-skills/tdd-guard/reporters/test/artifacts/phpunit/SinglePassingTest.php +0 -11
  135. package/project-skills/tdd-guard/reporters/test/artifacts/pytest/test_single_failing.py +0 -3
  136. package/project-skills/tdd-guard/reporters/test/artifacts/pytest/test_single_import_error.py +0 -6
  137. package/project-skills/tdd-guard/reporters/test/artifacts/pytest/test_single_passing.py +0 -3
  138. package/project-skills/tdd-guard/reporters/test/artifacts/rust/failing/Cargo.lock +0 -7
  139. package/project-skills/tdd-guard/reporters/test/artifacts/rust/failing/Cargo.toml +0 -4
  140. package/project-skills/tdd-guard/reporters/test/artifacts/rust/failing/src/lib.rs +0 -14
  141. package/project-skills/tdd-guard/reporters/test/artifacts/rust/import/Cargo.lock +0 -7
  142. package/project-skills/tdd-guard/reporters/test/artifacts/rust/import/Cargo.toml +0 -4
  143. package/project-skills/tdd-guard/reporters/test/artifacts/rust/import/src/lib.rs +0 -13
  144. package/project-skills/tdd-guard/reporters/test/artifacts/rust/passing/Cargo.lock +0 -7
  145. package/project-skills/tdd-guard/reporters/test/artifacts/rust/passing/Cargo.toml +0 -4
  146. package/project-skills/tdd-guard/reporters/test/artifacts/rust/passing/src/lib.rs +0 -14
  147. package/project-skills/tdd-guard/reporters/test/artifacts/storybook/Calculator.js +0 -4
  148. package/project-skills/tdd-guard/reporters/test/artifacts/storybook/single-failing.stories.js +0 -15
  149. package/project-skills/tdd-guard/reporters/test/artifacts/storybook/single-import-error.stories.js +0 -14
  150. package/project-skills/tdd-guard/reporters/test/artifacts/storybook/single-passing.stories.js +0 -15
  151. package/project-skills/tdd-guard/reporters/test/artifacts/vitest/single-failing.test.js +0 -7
  152. package/project-skills/tdd-guard/reporters/test/artifacts/vitest/single-import-error.test.js +0 -9
  153. package/project-skills/tdd-guard/reporters/test/artifacts/vitest/single-passing.test.js +0 -7
  154. package/project-skills/tdd-guard/reporters/test/factories/go.ts +0 -59
  155. package/project-skills/tdd-guard/reporters/test/factories/helpers.ts +0 -48
  156. package/project-skills/tdd-guard/reporters/test/factories/index.ts +0 -7
  157. package/project-skills/tdd-guard/reporters/test/factories/jest.ts +0 -51
  158. package/project-skills/tdd-guard/reporters/test/factories/phpunit.ts +0 -63
  159. package/project-skills/tdd-guard/reporters/test/factories/pytest.ts +0 -41
  160. package/project-skills/tdd-guard/reporters/test/factories/rust.ts +0 -158
  161. package/project-skills/tdd-guard/reporters/test/factories/storybook.ts +0 -198
  162. package/project-skills/tdd-guard/reporters/test/factories/vitest.ts +0 -51
  163. package/project-skills/tdd-guard/reporters/test/reporters.integration.test.ts +0 -735
  164. package/project-skills/tdd-guard/reporters/test/types.ts +0 -28
  165. package/project-skills/tdd-guard/reporters/vitest/README.md +0 -64
  166. package/project-skills/tdd-guard/reporters/vitest/package.json +0 -35
  167. package/project-skills/tdd-guard/reporters/vitest/src/VitestReporter.test-data.ts +0 -85
  168. package/project-skills/tdd-guard/reporters/vitest/src/VitestReporter.test.ts +0 -446
  169. package/project-skills/tdd-guard/reporters/vitest/src/VitestReporter.ts +0 -110
  170. package/project-skills/tdd-guard/reporters/vitest/src/index.ts +0 -4
  171. package/project-skills/tdd-guard/reporters/vitest/src/types.ts +0 -39
  172. package/project-skills/tdd-guard/reporters/vitest/tsconfig.json +0 -11
  173. package/project-skills/tdd-guard/src/cli/buildContext.test.ts +0 -200
  174. package/project-skills/tdd-guard/src/cli/buildContext.ts +0 -48
  175. package/project-skills/tdd-guard/src/cli/tdd-guard.test.ts +0 -159
  176. package/project-skills/tdd-guard/src/cli/tdd-guard.ts +0 -48
  177. package/project-skills/tdd-guard/src/config/Config.test.ts +0 -538
  178. package/project-skills/tdd-guard/src/config/Config.ts +0 -172
  179. package/project-skills/tdd-guard/src/contracts/schemas/guardSchemas.test.ts +0 -58
  180. package/project-skills/tdd-guard/src/contracts/schemas/guardSchemas.ts +0 -8
  181. package/project-skills/tdd-guard/src/contracts/schemas/lintSchemas.test.ts +0 -347
  182. package/project-skills/tdd-guard/src/contracts/schemas/lintSchemas.ts +0 -61
  183. package/project-skills/tdd-guard/src/contracts/schemas/pytestSchemas.test.ts +0 -24
  184. package/project-skills/tdd-guard/src/contracts/schemas/pytestSchemas.ts +0 -7
  185. package/project-skills/tdd-guard/src/contracts/schemas/reporterSchemas.test.ts +0 -377
  186. package/project-skills/tdd-guard/src/contracts/schemas/reporterSchemas.ts +0 -75
  187. package/project-skills/tdd-guard/src/contracts/schemas/toolSchemas.test.ts +0 -563
  188. package/project-skills/tdd-guard/src/contracts/schemas/toolSchemas.ts +0 -140
  189. package/project-skills/tdd-guard/src/contracts/types/ClientType.ts +0 -1
  190. package/project-skills/tdd-guard/src/contracts/types/ConfigOptions.ts +0 -12
  191. package/project-skills/tdd-guard/src/contracts/types/Context.ts +0 -16
  192. package/project-skills/tdd-guard/src/contracts/types/ModelClient.ts +0 -3
  193. package/project-skills/tdd-guard/src/contracts/types/ValidationResult.ts +0 -6
  194. package/project-skills/tdd-guard/src/guard/GuardManager.test.ts +0 -336
  195. package/project-skills/tdd-guard/src/guard/GuardManager.ts +0 -83
  196. package/project-skills/tdd-guard/src/hooks/HookEvents.test.ts +0 -107
  197. package/project-skills/tdd-guard/src/hooks/HookEvents.ts +0 -39
  198. package/project-skills/tdd-guard/src/hooks/fileTypeDetection.ts +0 -16
  199. package/project-skills/tdd-guard/src/hooks/postToolLint.test.ts +0 -327
  200. package/project-skills/tdd-guard/src/hooks/postToolLint.ts +0 -165
  201. package/project-skills/tdd-guard/src/hooks/processHookData.test.ts +0 -465
  202. package/project-skills/tdd-guard/src/hooks/processHookData.ts +0 -203
  203. package/project-skills/tdd-guard/src/hooks/sessionHandler.test.ts +0 -136
  204. package/project-skills/tdd-guard/src/hooks/sessionHandler.ts +0 -31
  205. package/project-skills/tdd-guard/src/hooks/userPromptHandler.test.ts +0 -131
  206. package/project-skills/tdd-guard/src/hooks/userPromptHandler.ts +0 -55
  207. package/project-skills/tdd-guard/src/index.ts +0 -19
  208. package/project-skills/tdd-guard/src/linters/Linter.ts +0 -5
  209. package/project-skills/tdd-guard/src/linters/eslint/ESLint.test.ts +0 -183
  210. package/project-skills/tdd-guard/src/linters/eslint/ESLint.ts +0 -82
  211. package/project-skills/tdd-guard/src/linters/golangci/GolangciLint.test.ts +0 -170
  212. package/project-skills/tdd-guard/src/linters/golangci/GolangciLint.ts +0 -148
  213. package/project-skills/tdd-guard/src/processors/index.ts +0 -1
  214. package/project-skills/tdd-guard/src/processors/lintProcessor.ts +0 -77
  215. package/project-skills/tdd-guard/src/processors/testResults/TestResultsProcessor.test.ts +0 -303
  216. package/project-skills/tdd-guard/src/processors/testResults/TestResultsProcessor.ts +0 -255
  217. package/project-skills/tdd-guard/src/providers/LinterProvider.test.ts +0 -43
  218. package/project-skills/tdd-guard/src/providers/LinterProvider.ts +0 -20
  219. package/project-skills/tdd-guard/src/providers/ModelClientProvider.test.ts +0 -68
  220. package/project-skills/tdd-guard/src/providers/ModelClientProvider.ts +0 -22
  221. package/project-skills/tdd-guard/src/storage/FileStorage.test.ts +0 -76
  222. package/project-skills/tdd-guard/src/storage/FileStorage.ts +0 -108
  223. package/project-skills/tdd-guard/src/storage/MemoryStorage.ts +0 -57
  224. package/project-skills/tdd-guard/src/storage/Storage.test.ts +0 -227
  225. package/project-skills/tdd-guard/src/storage/Storage.ts +0 -17
  226. package/project-skills/tdd-guard/src/validation/context/context.test.ts +0 -364
  227. package/project-skills/tdd-guard/src/validation/context/context.ts +0 -155
  228. package/project-skills/tdd-guard/src/validation/models/AnthropicApi.test.ts +0 -171
  229. package/project-skills/tdd-guard/src/validation/models/AnthropicApi.ts +0 -49
  230. package/project-skills/tdd-guard/src/validation/models/ClaudeAgentSdk.test.ts +0 -167
  231. package/project-skills/tdd-guard/src/validation/models/ClaudeAgentSdk.ts +0 -54
  232. package/project-skills/tdd-guard/src/validation/models/ClaudeCli.test.ts +0 -239
  233. package/project-skills/tdd-guard/src/validation/models/ClaudeCli.ts +0 -57
  234. package/project-skills/tdd-guard/src/validation/prompts/file-types.ts +0 -52
  235. package/project-skills/tdd-guard/src/validation/prompts/operations/edit.ts +0 -58
  236. package/project-skills/tdd-guard/src/validation/prompts/operations/multi-edit.ts +0 -54
  237. package/project-skills/tdd-guard/src/validation/prompts/operations/write.ts +0 -54
  238. package/project-skills/tdd-guard/src/validation/prompts/response.ts +0 -40
  239. package/project-skills/tdd-guard/src/validation/prompts/rules.ts +0 -51
  240. package/project-skills/tdd-guard/src/validation/prompts/system-prompt.ts +0 -10
  241. package/project-skills/tdd-guard/src/validation/prompts/tools/lint-results.ts +0 -15
  242. package/project-skills/tdd-guard/src/validation/prompts/tools/test-output.ts +0 -14
  243. package/project-skills/tdd-guard/src/validation/prompts/tools/todos.ts +0 -9
  244. package/project-skills/tdd-guard/src/validation/validator.test.ts +0 -268
  245. package/project-skills/tdd-guard/src/validation/validator.ts +0 -159
  246. package/project-skills/tdd-guard/test/artifacts/go/.golangci.yml +0 -6
  247. package/project-skills/tdd-guard/test/artifacts/go/with-issues/file-with-issues.go +0 -12
  248. package/project-skills/tdd-guard/test/artifacts/go/with-issues/go.mod +0 -3
  249. package/project-skills/tdd-guard/test/artifacts/go/without-issues/file-without-issues.go +0 -7
  250. package/project-skills/tdd-guard/test/artifacts/go/without-issues/go.mod +0 -3
  251. package/project-skills/tdd-guard/test/artifacts/javascript/eslint.config.js +0 -20
  252. package/project-skills/tdd-guard/test/artifacts/javascript/file-with-issues.js +0 -12
  253. package/project-skills/tdd-guard/test/artifacts/javascript/file-without-issues.js +0 -10
  254. package/project-skills/tdd-guard/test/hooks/fileTypeDetection.test.ts +0 -26
  255. package/project-skills/tdd-guard/test/hooks/processHookData.fileType.test.ts +0 -46
  256. package/project-skills/tdd-guard/test/hooks/processHookData.python.test.ts +0 -68
  257. package/project-skills/tdd-guard/test/integration/test-context.test.ts +0 -66
  258. package/project-skills/tdd-guard/test/integration/validator.core.test.ts +0 -96
  259. package/project-skills/tdd-guard/test/integration/validator.scenarios.test.ts +0 -497
  260. package/project-skills/tdd-guard/test/utils/assertions.ts +0 -29
  261. package/project-skills/tdd-guard/test/utils/factories/contextFactory.ts +0 -30
  262. package/project-skills/tdd-guard/test/utils/factories/editFactory.ts +0 -82
  263. package/project-skills/tdd-guard/test/utils/factories/helpers.test.ts +0 -46
  264. package/project-skills/tdd-guard/test/utils/factories/helpers.ts +0 -46
  265. package/project-skills/tdd-guard/test/utils/factories/lintFactory.ts +0 -352
  266. package/project-skills/tdd-guard/test/utils/factories/modelClientProviderFactory.ts +0 -21
  267. package/project-skills/tdd-guard/test/utils/factories/multiEditFactory.ts +0 -79
  268. package/project-skills/tdd-guard/test/utils/factories/operations.ts +0 -57
  269. package/project-skills/tdd-guard/test/utils/factories/reporterFactory.ts +0 -55
  270. package/project-skills/tdd-guard/test/utils/factories/scenarios/index.ts +0 -22
  271. package/project-skills/tdd-guard/test/utils/factories/scenarios/languages/python.ts +0 -745
  272. package/project-skills/tdd-guard/test/utils/factories/scenarios/languages/typescript.ts +0 -767
  273. package/project-skills/tdd-guard/test/utils/factories/scenarios/types.ts +0 -77
  274. package/project-skills/tdd-guard/test/utils/factories/scenarios/utils.ts +0 -15
  275. package/project-skills/tdd-guard/test/utils/factories/sessionStartFactory.ts +0 -36
  276. package/project-skills/tdd-guard/test/utils/factories/testDefaults.ts +0 -90
  277. package/project-skills/tdd-guard/test/utils/factories/testResultsFactory.ts +0 -234
  278. package/project-skills/tdd-guard/test/utils/factories/todoFactory.ts +0 -99
  279. package/project-skills/tdd-guard/test/utils/factories/userPromptSubmitFactory.ts +0 -39
  280. package/project-skills/tdd-guard/test/utils/factories/writeFactory.ts +0 -70
  281. package/project-skills/tdd-guard/test/utils/index.ts +0 -131
  282. package/project-skills/tdd-guard/tsconfig.build.json +0 -16
  283. package/project-skills/tdd-guard/tsconfig.eslint.json +0 -17
  284. package/project-skills/tdd-guard/tsconfig.json +0 -32
  285. package/project-skills/tdd-guard/tsconfig.node.json +0 -10
  286. package/project-skills/tdd-guard/vitest.config.ts +0 -85
@@ -1,465 +0,0 @@
1
- import { describe, it, expect, beforeEach, vi } from 'vitest'
2
- import { processHookData, defaultResult } from './processHookData'
3
- import { testData } from '@testUtils'
4
- import { UserPromptHandler } from './userPromptHandler'
5
- import { GuardManager } from '../guard/GuardManager'
6
- import { MemoryStorage } from '../storage/MemoryStorage'
7
- import { ValidationResult } from '../contracts/types/ValidationResult'
8
- import { Context } from '../contracts/types/Context'
9
-
10
- const BLOCK_RESULT = {
11
- decision: 'block',
12
- reason: 'TDD violation',
13
- } as const
14
-
15
- const WRITE_HOOK_DATA = testData.writeOperation()
16
- const EDIT_HOOK_DATA = testData.editOperation()
17
- const TODO_WRITE_HOOK_DATA = testData.todoWriteOperation()
18
-
19
- describe('processHookData', () => {
20
- let sut: ReturnType<typeof createTestProcessor>
21
-
22
- beforeEach(() => {
23
- sut = createTestProcessor()
24
- })
25
-
26
- it('should return a ValidationResult', async () => {
27
- const hookData = { type: 'test', data: 'some data' }
28
-
29
- const result = await sut.process(hookData)
30
-
31
- expect(result).toBeDefined()
32
- expect(result).toHaveProperty('decision')
33
- expect(result).toHaveProperty('reason')
34
- })
35
-
36
- it('should throw error on invalid JSON', async () => {
37
- const invalidJson = '{ invalid json'
38
-
39
- // For this test, we need to use processHookData directly since we're testing JSON parsing
40
- await expect(processHookData(invalidJson)).rejects.toThrow()
41
- })
42
-
43
- it('should save modifications content to storage when tool is Edit', async () => {
44
- await sut.process(EDIT_HOOK_DATA)
45
-
46
- const savedModifications = await sut.getModifications()
47
- const parsedModifications = JSON.parse(savedModifications!)
48
- expect(parsedModifications).toEqual(EDIT_HOOK_DATA)
49
- })
50
-
51
- it('should save todo content to storage when tool is TodoWrite', async () => {
52
- await sut.process(TODO_WRITE_HOOK_DATA)
53
-
54
- const savedTodo = await sut.getTodo()
55
- const parsedTodo = JSON.parse(savedTodo!)
56
- expect(parsedTodo).toEqual(TODO_WRITE_HOOK_DATA)
57
- })
58
-
59
- it('should save modifications content when tool has content field', async () => {
60
- await sut.process(WRITE_HOOK_DATA)
61
-
62
- const savedModifications = await sut.getModifications()
63
- const parsedModifications = JSON.parse(savedModifications!)
64
- expect(parsedModifications).toEqual(WRITE_HOOK_DATA)
65
- })
66
-
67
- it('should call validator with context built from storage', async () => {
68
- // Pre-populate storage
69
- await sut.populateStorage({
70
- modifications: 'existing modifications',
71
- test: 'existing test',
72
- todo: 'existing todo',
73
- })
74
-
75
- const result = await sut.process(EDIT_HOOK_DATA)
76
-
77
- const actualContext = sut.getValidatorCallArgs()
78
-
79
- // Verify the context, parsing JSON to handle formatting differences
80
- expect({
81
- ...actualContext,
82
- modifications: JSON.parse(actualContext!.modifications),
83
- }).toEqual({
84
- modifications: EDIT_HOOK_DATA,
85
- test: 'existing test',
86
- todo: 'existing todo',
87
- lint: {
88
- errorCount: 0,
89
- warningCount: 0,
90
- hasIssues: false,
91
- totalIssues: 0,
92
- issuesByFile: new Map(),
93
- summary: 'No lint data available'
94
- }
95
- })
96
- expect(result).toEqual(BLOCK_RESULT)
97
- })
98
-
99
- it('should not call validator for TodoWrite operations', async () => {
100
- // Pre-populate storage with existing edits that might cause false blocks
101
- await sut.populateStorage({
102
- modifications: 'existing modifications that might trigger validation',
103
- })
104
-
105
- const result = await sut.process(TODO_WRITE_HOOK_DATA)
106
-
107
- expect(sut.validatorHasBeenCalled()).toBe(false)
108
- expect(result).toEqual(defaultResult)
109
- })
110
-
111
- it('should handle hook data with invalid schema gracefully', async () => {
112
- // Invalid hook data that doesn't match either SimpleHookDataSchema or FullHookEventSchema
113
- const invalidHookData = {
114
- // This doesn't match FullHookEventSchema (missing required fields)
115
- // and has invalid types for SimpleHookDataSchema
116
- tool_name: 123, // Should be string
117
- tool_input: "not an object", // Should be object
118
- }
119
-
120
- const result = await sut.process(invalidHookData)
121
-
122
- // Should return default result without calling validator
123
- expect(sut.validatorHasBeenCalled()).toBe(false)
124
- expect(result).toEqual(defaultResult)
125
- })
126
-
127
- describe('PostToolUse hook handling', () => {
128
- it('should delegate to handlePostToolLint for PostToolUse events', async () => {
129
- const postToolUseHook = {
130
- ...EDIT_HOOK_DATA,
131
- hook_event_name: 'PostToolUse',
132
- tool_output: { success: true }
133
- }
134
-
135
- const result = await sut.process(postToolUseHook)
136
-
137
- // Should not call the validator
138
- expect(sut.validatorHasBeenCalled()).toBe(false)
139
- // Result depends on lint state, but should return a valid result
140
- expect(result).toHaveProperty('decision')
141
- expect(result).toHaveProperty('reason')
142
- })
143
- })
144
-
145
- describe('Ignore patterns filtering', () => {
146
- it('skips validation when using default ignore patterns', async () => {
147
- for (const pattern of GuardManager.DEFAULT_IGNORE_PATTERNS) {
148
- // Convert pattern to file path (e.g., '*.md' -> '/path/to/file.md')
149
- const filePath = pattern.replaceAll('*', '/path/to/file')
150
-
151
- const nonCodeFileData = {
152
- ...EDIT_HOOK_DATA,
153
- tool_input: {
154
- file_path: filePath,
155
- old_string: 'old content',
156
- new_string: 'new content'
157
- }
158
- }
159
-
160
- const result = await sut.process(nonCodeFileData)
161
-
162
- expect(sut.validatorHasBeenCalled()).toBe(false)
163
- expect(result).toEqual(defaultResult)
164
- }
165
- })
166
-
167
- it.each([
168
- {
169
- description: 'files matching custom extensions',
170
- filePath: 'file.custom',
171
- },
172
- {
173
- description: 'files in ignored directories',
174
- filePath: 'build/output.js',
175
- },
176
- {
177
- description: 'files matching glob patterns',
178
- filePath: 'src/api/schema.generated.ts',
179
- },
180
- ])('skips validation when using custom ignore patterns for $description', async ({ filePath }) => {
181
- // Set up custom ignore patterns
182
- const customPatterns = ['*.custom', 'build/**', '**/*.generated.ts']
183
- await sut.storage.saveConfig(JSON.stringify({
184
- guardEnabled: true,
185
- ignorePatterns: customPatterns
186
- }))
187
-
188
- const fileData = {
189
- ...EDIT_HOOK_DATA,
190
- tool_input: {
191
- file_path: filePath,
192
- old_string: 'old content',
193
- new_string: 'new content'
194
- }
195
- }
196
-
197
- const result = await sut.process(fileData)
198
-
199
- expect(sut.validatorHasBeenCalled()).toBe(false)
200
- expect(result).toEqual(defaultResult)
201
- })
202
- })
203
-
204
- describe('PreToolUse lint notification', () => {
205
- it('should block when tests pass, lint issues exist, and not yet notified', async () => {
206
- // Setup: passing tests
207
- await sut.populateStorage({
208
- test: JSON.stringify(testData.passingTestResults())
209
- })
210
-
211
- // Setup: lint issues with notification flag false
212
- await sut.storage.saveLint(JSON.stringify(
213
- testData.lintDataWithError({
214
- hasNotifiedAboutLintIssues: false
215
- })
216
- ))
217
-
218
- const result = await sut.process(EDIT_HOOK_DATA)
219
-
220
- expect(result.decision).toBe('block')
221
- expect(result.reason).toContain('Code quality issues detected')
222
- // Should not call the main validator
223
- expect(sut.validatorHasBeenCalled()).toBe(false)
224
- })
225
-
226
- it('should not block when tests are failing (red phase)', async () => {
227
- // Setup: failing tests
228
- await sut.populateStorage({
229
- test: JSON.stringify(testData.failedTestResults())
230
- })
231
-
232
- // Setup: lint issues with notification flag false
233
- await sut.storage.saveLint(JSON.stringify(
234
- testData.lintDataWithError({
235
- hasNotifiedAboutLintIssues: false
236
- })
237
- ))
238
-
239
- const result = await sut.process(EDIT_HOOK_DATA)
240
-
241
- // Should proceed to normal validation
242
- expect(result).toEqual(BLOCK_RESULT)
243
- expect(sut.validatorHasBeenCalled()).toBe(true)
244
- })
245
-
246
- it('should not block when no lint issues exist', async () => {
247
- // Setup: passing tests
248
- await sut.populateStorage({
249
- test: JSON.stringify(testData.passingTestResults())
250
- })
251
-
252
- // Setup: no lint issues
253
- await sut.storage.saveLint(JSON.stringify(
254
- testData.lintDataWithoutErrors({
255
- hasNotifiedAboutLintIssues: false
256
- })
257
- ))
258
-
259
- const result = await sut.process(EDIT_HOOK_DATA)
260
-
261
- // Should proceed to normal validation
262
- expect(result).toEqual(BLOCK_RESULT)
263
- expect(sut.validatorHasBeenCalled()).toBe(true)
264
- })
265
-
266
- it('should not block when already notified', async () => {
267
- // Setup: passing tests
268
- await sut.populateStorage({
269
- test: JSON.stringify(testData.passingTestResults())
270
- })
271
-
272
- // Setup: lint issues with notification flag true
273
- await sut.storage.saveLint(JSON.stringify(
274
- testData.lintDataWithError({
275
- hasNotifiedAboutLintIssues: true
276
- })
277
- ))
278
-
279
- const result = await sut.process(EDIT_HOOK_DATA)
280
-
281
- // Should proceed to normal validation
282
- expect(result).toEqual(BLOCK_RESULT)
283
- expect(sut.validatorHasBeenCalled()).toBe(true)
284
- })
285
-
286
- it('should set notification flag after blocking', async () => {
287
- // Setup: passing tests
288
- await sut.populateStorage({
289
- test: JSON.stringify(testData.passingTestResults())
290
- })
291
-
292
- // Setup: lint issues with notification flag false
293
- await sut.storage.saveLint(JSON.stringify(
294
- testData.lintDataWithError({
295
- hasNotifiedAboutLintIssues: false
296
- })
297
- ))
298
-
299
- await sut.process(EDIT_HOOK_DATA)
300
-
301
- // Check that the flag was updated
302
- const savedLint = await sut.storage.getLint()
303
- const parsedLint = JSON.parse(savedLint!)
304
- expect(parsedLint.hasNotifiedAboutLintIssues).toBe(true)
305
- })
306
- })
307
-
308
- describe('SessionStart handling', () => {
309
- let result: ValidationResult
310
-
311
- beforeEach(async () => {
312
- // Populate storage with data
313
- await sut.populateStorage({
314
- test: JSON.stringify(testData.passingTestResults()),
315
- todo: JSON.stringify(testData.todoWriteOperation()),
316
- modifications: JSON.stringify(testData.editOperation()),
317
- lint: JSON.stringify(testData.lintDataWithoutErrors()),
318
- config: JSON.stringify({ guardEnabled: true })
319
- })
320
-
321
- const sessionStartData = testData.sessionStart()
322
- result = await sut.process(sessionStartData)
323
- })
324
-
325
- it('should clear transient data when SessionStart event is received', async () => {
326
- // Verify transient data is cleared
327
- expect(await sut.getTest()).toBeNull()
328
- expect(await sut.getTodo()).toBeNull()
329
- expect(await sut.getModifications()).toBeNull()
330
- expect(await sut.getLint()).toBeNull()
331
- })
332
-
333
- it('should preserve config data when SessionStart event is received', async () => {
334
- expect(await sut.getConfig()).toBe(JSON.stringify({ guardEnabled: true }))
335
- })
336
-
337
- it('should return defaultResult when SessionStart event is processed', () => {
338
- expect(result).toEqual(defaultResult)
339
- })
340
- })
341
-
342
- describe('UserPromptHandler integration', () => {
343
- it('should enable TDD Guard when user sends "tdd-guard on"', async () => {
344
- const storage = new MemoryStorage()
345
- const guardManager = new GuardManager(storage)
346
- await guardManager.disable() // Ensure it starts disabled
347
- const userPromptHandler = new UserPromptHandler(guardManager)
348
- const userPromptData = testData.userPromptSubmit({ prompt: 'tdd-guard on' })
349
-
350
- await processHookData(JSON.stringify(userPromptData), {
351
- userPromptHandler
352
- })
353
-
354
- expect(await guardManager.isEnabled()).toBe(true)
355
- })
356
-
357
- it('should disable TDD Guard when user sends "tdd-guard off"', async () => {
358
- const storage = new MemoryStorage()
359
- const guardManager = new GuardManager(storage)
360
- await guardManager.enable() // Ensure it starts enabled
361
- const userPromptHandler = new UserPromptHandler(guardManager)
362
- const userPromptData = testData.userPromptSubmit({ prompt: 'tdd-guard off' })
363
-
364
- await processHookData(JSON.stringify(userPromptData), {
365
- userPromptHandler
366
- })
367
-
368
- expect(await guardManager.isEnabled()).toBe(false)
369
- })
370
-
371
- it('should not proceed with validation when TDD Guard is disabled', async () => {
372
- const storage = new MemoryStorage()
373
- const guardManager = new GuardManager(storage)
374
- await guardManager.disable() // Ensure guard is disabled
375
- const userPromptHandler = new UserPromptHandler(guardManager)
376
- const mockValidator = vi.fn()
377
-
378
- // Try to process an edit operation
379
- const editData = testData.editOperation()
380
-
381
- const result = await processHookData(JSON.stringify(editData), {
382
- storage,
383
- userPromptHandler,
384
- validator: mockValidator
385
- })
386
-
387
- expect(mockValidator).not.toHaveBeenCalled()
388
- expect(result).toEqual(defaultResult)
389
- })
390
-
391
- it('should proceed with validation when TDD Guard is enabled', async () => {
392
- const storage = new MemoryStorage()
393
- const guardManager = new GuardManager(storage)
394
- await guardManager.enable() // Ensure guard is enabled
395
- const userPromptHandler = new UserPromptHandler(guardManager)
396
- const mockValidator = vi.fn().mockResolvedValue(BLOCK_RESULT)
397
-
398
- // Try to process an edit operation
399
- const editData = testData.editOperation()
400
-
401
- const result = await processHookData(JSON.stringify(editData), {
402
- storage,
403
- userPromptHandler,
404
- validator: mockValidator
405
- })
406
-
407
- expect(mockValidator).toHaveBeenCalled()
408
- expect(result).toEqual(BLOCK_RESULT)
409
- })
410
- })
411
- })
412
-
413
- // Test setup helper
414
- function createTestProcessor() {
415
- const storage = new MemoryStorage()
416
- const mockValidator = vi.fn().mockResolvedValue(BLOCK_RESULT)
417
-
418
- // Create a GuardManager and UserPromptHandler that defaults to enabled for tests
419
- const guardManager = new GuardManager(storage)
420
- const userPromptHandler = new UserPromptHandler(guardManager)
421
-
422
- // Helper to process hook data
423
- const process = async (hookData: unknown): Promise<ValidationResult> => {
424
- // Ensure TDD Guard is enabled for tests unless explicitly disabled
425
- await guardManager.enable()
426
-
427
- return processHookData(JSON.stringify(hookData), {
428
- storage,
429
- validator: mockValidator,
430
- userPromptHandler
431
- })
432
- }
433
-
434
- // Pre-populate storage helper
435
- const populateStorage = async (data: {
436
- modifications?: string;
437
- test?: string;
438
- todo?: string;
439
- lint?: string;
440
- config?: string;
441
- }): Promise<void> => {
442
- if (data.modifications) await storage.saveModifications(data.modifications)
443
- if (data.test) await storage.saveTest(data.test)
444
- if (data.todo) await storage.saveTodo(data.todo)
445
- if (data.lint) await storage.saveLint(data.lint)
446
- if (data.config) await storage.saveConfig(data.config)
447
- }
448
-
449
- return {
450
- storage,
451
- process,
452
- populateStorage,
453
-
454
- // Storage accessors
455
- getModifications: (): Promise<string | null> => storage.getModifications(),
456
- getTest: (): Promise<string | null> => storage.getTest(),
457
- getTodo: (): Promise<string | null> => storage.getTodo(),
458
- getLint: (): Promise<string | null> => storage.getLint(),
459
- getConfig: (): Promise<string | null> => storage.getConfig(),
460
-
461
- // Validator checks
462
- validatorHasBeenCalled: (): boolean => mockValidator.mock.calls.length > 0,
463
- getValidatorCallArgs: (): Context | null => mockValidator.mock.calls[0]?.[0] ?? null,
464
- }
465
- }
@@ -1,203 +0,0 @@
1
- import { buildContext } from '../cli/buildContext'
2
- import { HookData, HookEvents } from './HookEvents'
3
- import { PostToolLintHandler } from './postToolLint'
4
- import { detectFileType } from './fileTypeDetection'
5
- import { LinterProvider } from '../providers/LinterProvider'
6
- import { UserPromptHandler } from './userPromptHandler'
7
- import { SessionHandler } from './sessionHandler'
8
- import { GuardManager } from '../guard/GuardManager'
9
- import { Storage } from '../storage/Storage'
10
- import { FileStorage } from '../storage/FileStorage'
11
- import { ValidationResult } from '../contracts/types/ValidationResult'
12
- import { Context } from '../contracts/types/Context'
13
- import { HookDataSchema, isTodoWriteOperation, ToolOperationSchema } from '../contracts/schemas/toolSchemas'
14
- import { PytestResultSchema } from '../contracts/schemas/pytestSchemas'
15
- import { isTestPassing, TestResultSchema } from '../contracts/schemas/reporterSchemas'
16
- import { LintDataSchema } from '../contracts/schemas/lintSchemas'
17
-
18
- export interface ProcessHookDataDeps {
19
- storage?: Storage
20
- validator?: (context: Context) => Promise<ValidationResult>
21
- userPromptHandler?: UserPromptHandler
22
- }
23
-
24
- export const defaultResult: ValidationResult = {
25
- decision: undefined,
26
- reason: '',
27
- }
28
-
29
- function extractFilePath(parsedData: unknown): string | null {
30
- if (!parsedData || typeof parsedData !== 'object') {
31
- return null
32
- }
33
-
34
- const data = parsedData as Record<string, unknown>
35
- const toolInput = data.tool_input
36
-
37
- if (!toolInput || typeof toolInput !== 'object' || !('file_path' in toolInput)) {
38
- return null
39
- }
40
-
41
- const filePath = (toolInput as Record<string, unknown>).file_path
42
- if (typeof filePath !== 'string') {
43
- return null
44
- }
45
-
46
- return filePath
47
- }
48
-
49
- export async function processHookData(
50
- inputData: string,
51
- deps: ProcessHookDataDeps = {}
52
- ): Promise<ValidationResult> {
53
- const parsedData = JSON.parse(inputData)
54
-
55
- // Initialize dependencies
56
- const storage = deps.storage ?? new FileStorage()
57
- const guardManager = new GuardManager(storage)
58
- const userPromptHandler = deps.userPromptHandler ?? new UserPromptHandler(guardManager)
59
-
60
- // Skip validation for ignored files based on patterns
61
- const filePath = extractFilePath(parsedData)
62
- if (filePath && await guardManager.shouldIgnoreFile(filePath)) {
63
- return defaultResult
64
- }
65
- const sessionHandler = new SessionHandler(storage)
66
-
67
- // Process SessionStart events
68
- if (parsedData.hook_event_name === 'SessionStart') {
69
- await sessionHandler.processSessionStart(inputData)
70
- return defaultResult
71
- }
72
-
73
- // Process user commands
74
- const stateResult = await userPromptHandler.processUserCommand(inputData)
75
- if (stateResult) {
76
- return stateResult
77
- }
78
-
79
- // Check if guard is disabled and return early if so
80
- const disabledResult = await userPromptHandler.getDisabledResult()
81
- if (disabledResult) {
82
- return disabledResult
83
- }
84
-
85
- // Create lintHandler with linter from provider
86
- const linterProvider = new LinterProvider()
87
- const linter = linterProvider.getLinter()
88
- const lintHandler = new PostToolLintHandler(storage, linter)
89
-
90
-
91
- const hookResult = HookDataSchema.safeParse(parsedData)
92
- if (!hookResult.success) {
93
- return defaultResult
94
- }
95
-
96
- await processHookEvent(parsedData, storage)
97
-
98
- // Check if this is a PostToolUse event
99
- if (hookResult.data.hook_event_name === 'PostToolUse') {
100
- return await lintHandler.handle(inputData)
101
- }
102
-
103
- if (shouldSkipValidation(hookResult.data)) {
104
- return defaultResult
105
- }
106
-
107
- // For PreToolUse, check if we should notify about lint issues
108
- if (hookResult.data.hook_event_name === 'PreToolUse') {
109
- const lintNotification = await checkLintNotification(storage, hookResult.data)
110
- if (lintNotification.decision === 'block') {
111
- return lintNotification
112
- }
113
- }
114
-
115
- return await performValidation(deps)
116
- }
117
-
118
- async function processHookEvent(parsedData: unknown, storage?: Storage): Promise<void> {
119
- if (storage) {
120
- const hookEvents = new HookEvents(storage)
121
- await hookEvents.processEvent(parsedData)
122
- }
123
- }
124
-
125
- function shouldSkipValidation(hookData: HookData): boolean {
126
- const operationResult = ToolOperationSchema.safeParse({
127
- ...hookData,
128
- tool_input: hookData.tool_input,
129
- })
130
-
131
- return !operationResult.success || isTodoWriteOperation(operationResult.data)
132
- }
133
-
134
- async function performValidation(deps: ProcessHookDataDeps): Promise<ValidationResult> {
135
- if (deps.validator && deps.storage) {
136
- const context = await buildContext(deps.storage)
137
- return await deps.validator(context)
138
- }
139
-
140
- return defaultResult
141
- }
142
-
143
- async function checkLintNotification(storage: Storage, hookData: HookData): Promise<ValidationResult> {
144
- // Get test results to check if tests are passing
145
- let testsPassing = false
146
- try {
147
- const testStr = await storage.getTest()
148
- if (testStr) {
149
- const fileType = detectFileType(hookData)
150
- const testResult = fileType === 'python'
151
- ? PytestResultSchema.safeParse(JSON.parse(testStr))
152
- : TestResultSchema.safeParse(JSON.parse(testStr))
153
- if (testResult.success) {
154
- testsPassing = isTestPassing(testResult.data)
155
- }
156
- }
157
- } catch {
158
- testsPassing = false
159
- }
160
-
161
- // Only proceed if tests are passing
162
- if (!testsPassing) {
163
- return defaultResult
164
- }
165
-
166
- // Get lint data
167
- let lintData
168
- try {
169
- const lintStr = await storage.getLint()
170
- if (lintStr) {
171
- lintData = LintDataSchema.parse(JSON.parse(lintStr))
172
- }
173
- } catch {
174
- return defaultResult
175
- }
176
-
177
- // Only proceed if lint data exists
178
- if (!lintData) {
179
- return defaultResult
180
- }
181
-
182
- const hasIssues = lintData.errorCount > 0 || lintData.warningCount > 0
183
-
184
- // Block if:
185
- // 1. Tests are passing (already checked)
186
- // 2. There are lint issues
187
- // 3. hasNotifiedAboutLintIssues is false (not yet notified)
188
- if (hasIssues && !lintData.hasNotifiedAboutLintIssues) {
189
- // Update the notification flag and save
190
- const updatedLintData = {
191
- ...lintData,
192
- hasNotifiedAboutLintIssues: true
193
- }
194
- await storage.saveLint(JSON.stringify(updatedLintData))
195
-
196
- return {
197
- decision: 'block',
198
- reason: 'Code quality issues detected. You need to fix those first before making any other changes. Remember to exercise system thinking and design awareness to ensure continuous architectural improvements. Consider: design patterns, SOLID principles, DRY, types and interfaces, and architectural improvements. Apply equally to implementation and test code. Use test data factories, helpers, and beforeEach to better organize tests.'
199
- }
200
- }
201
-
202
- return defaultResult
203
- }