xtrm-tools 2.3.0 → 2.4.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 (284) hide show
  1. package/README.md +132 -111
  2. package/cli/dist/index.cjs +142 -53
  3. package/cli/dist/index.cjs.map +1 -1
  4. package/cli/package.json +1 -1
  5. package/config/pi/extensions/beads.ts +24 -0
  6. package/hooks/beads-gate-core.mjs +6 -4
  7. package/hooks/beads-memory-gate.mjs +12 -5
  8. package/hooks/hooks.json +126 -0
  9. package/package.json +3 -1
  10. package/skills/test-planning/SKILL.md +208 -0
  11. package/skills/test-planning/evals/evals.json +23 -0
  12. package/skills/using-xtrm/SKILL.md +5 -27
  13. package/project-skills/tdd-guard/.claude/hooks/tdd-guard-pretool-bridge.cjs +0 -103
  14. package/project-skills/tdd-guard/.claude/settings.json +0 -38
  15. package/project-skills/tdd-guard/.claude/skills/using-tdd-guard/SKILL.md +0 -79
  16. package/project-skills/tdd-guard/CLAUDE.md +0 -98
  17. package/project-skills/tdd-guard/CONTRIBUTING.md +0 -38
  18. package/project-skills/tdd-guard/DEVELOPMENT.md +0 -127
  19. package/project-skills/tdd-guard/LICENSE +0 -21
  20. package/project-skills/tdd-guard/README.md +0 -398
  21. package/project-skills/tdd-guard/docs/adr/001-claude-session-subdirectory.md +0 -52
  22. package/project-skills/tdd-guard/docs/adr/002-secure-claude-binary-path.md +0 -56
  23. package/project-skills/tdd-guard/docs/adr/003-remove-configurable-data-directory.md +0 -56
  24. package/project-skills/tdd-guard/docs/adr/004-monorepo-architecture.md +0 -64
  25. package/project-skills/tdd-guard/docs/adr/005-claude-project-dir-support.md +0 -55
  26. package/project-skills/tdd-guard/docs/adr/006-phpunit-separate-repository.md +0 -93
  27. package/project-skills/tdd-guard/docs/adr/007-golangci-lint-path-support.md +0 -83
  28. package/project-skills/tdd-guard/docs/adr/008-storybook-reporter-design.md +0 -182
  29. package/project-skills/tdd-guard/docs/assets/tdd-guard-demo-screenshot.gif +0 -0
  30. package/project-skills/tdd-guard/docs/config-migration.md +0 -143
  31. package/project-skills/tdd-guard/docs/configuration.md +0 -137
  32. package/project-skills/tdd-guard/docs/custom-instructions.md +0 -43
  33. package/project-skills/tdd-guard/docs/enforcement.md +0 -46
  34. package/project-skills/tdd-guard/docs/ignore-patterns.md +0 -81
  35. package/project-skills/tdd-guard/docs/linting.md +0 -109
  36. package/project-skills/tdd-guard/docs/quick-commands.md +0 -52
  37. package/project-skills/tdd-guard/docs/session-management.md +0 -75
  38. package/project-skills/tdd-guard/docs/storybook-vitest-addon.md +0 -120
  39. package/project-skills/tdd-guard/docs/validation-model.md +0 -63
  40. package/project-skills/tdd-guard/eslint.config.mjs +0 -140
  41. package/project-skills/tdd-guard/package-lock.json +0 -16937
  42. package/project-skills/tdd-guard/package.json +0 -102
  43. package/project-skills/tdd-guard/reporters/go/README.md +0 -67
  44. package/project-skills/tdd-guard/reporters/go/cmd/tdd-guard-go/main.go +0 -127
  45. package/project-skills/tdd-guard/reporters/go/cmd/tdd-guard-go/main_test.go +0 -280
  46. package/project-skills/tdd-guard/reporters/go/go.mod +0 -3
  47. package/project-skills/tdd-guard/reporters/go/go.sum +0 -0
  48. package/project-skills/tdd-guard/reporters/go/internal/formatter/formatter.go +0 -126
  49. package/project-skills/tdd-guard/reporters/go/internal/formatter/formatter_test.go +0 -264
  50. package/project-skills/tdd-guard/reporters/go/internal/io/tee_reader.go +0 -26
  51. package/project-skills/tdd-guard/reporters/go/internal/io/tee_reader_test.go +0 -37
  52. package/project-skills/tdd-guard/reporters/go/internal/parser/mixed_reader.go +0 -94
  53. package/project-skills/tdd-guard/reporters/go/internal/parser/mixed_reader_test.go +0 -198
  54. package/project-skills/tdd-guard/reporters/go/internal/parser/parser.go +0 -245
  55. package/project-skills/tdd-guard/reporters/go/internal/parser/parser_test.go +0 -547
  56. package/project-skills/tdd-guard/reporters/go/internal/storage/storage.go +0 -35
  57. package/project-skills/tdd-guard/reporters/go/internal/storage/storage_test.go +0 -113
  58. package/project-skills/tdd-guard/reporters/go/internal/transformer/transformer.go +0 -103
  59. package/project-skills/tdd-guard/reporters/go/internal/transformer/transformer_test.go +0 -303
  60. package/project-skills/tdd-guard/reporters/jest/README.md +0 -102
  61. package/project-skills/tdd-guard/reporters/jest/package.json +0 -38
  62. package/project-skills/tdd-guard/reporters/jest/src/JestReporter.test-data.ts +0 -199
  63. package/project-skills/tdd-guard/reporters/jest/src/JestReporter.test.ts +0 -302
  64. package/project-skills/tdd-guard/reporters/jest/src/JestReporter.ts +0 -201
  65. package/project-skills/tdd-guard/reporters/jest/src/index.ts +0 -4
  66. package/project-skills/tdd-guard/reporters/jest/src/types.ts +0 -42
  67. package/project-skills/tdd-guard/reporters/jest/tsconfig.json +0 -11
  68. package/project-skills/tdd-guard/reporters/phpunit/.php-cs-fixer.php +0 -28
  69. package/project-skills/tdd-guard/reporters/phpunit/README.md +0 -97
  70. package/project-skills/tdd-guard/reporters/phpunit/SYNC_README.md +0 -29
  71. package/project-skills/tdd-guard/reporters/phpunit/composer.json +0 -55
  72. package/project-skills/tdd-guard/reporters/phpunit/phpunit.xml.dist +0 -19
  73. package/project-skills/tdd-guard/reporters/phpunit/psalm.xml +0 -44
  74. package/project-skills/tdd-guard/reporters/phpunit/src/Event/ErroredTestSubscriber.php +0 -28
  75. package/project-skills/tdd-guard/reporters/phpunit/src/Event/FailedTestSubscriber.php +0 -28
  76. package/project-skills/tdd-guard/reporters/phpunit/src/Event/IncompleteTestSubscriber.php +0 -28
  77. package/project-skills/tdd-guard/reporters/phpunit/src/Event/PassedTestSubscriber.php +0 -27
  78. package/project-skills/tdd-guard/reporters/phpunit/src/Event/SkippedTestSubscriber.php +0 -28
  79. package/project-skills/tdd-guard/reporters/phpunit/src/Event/TestRunnerFinishedSubscriber.php +0 -24
  80. package/project-skills/tdd-guard/reporters/phpunit/src/PathValidator.php +0 -88
  81. package/project-skills/tdd-guard/reporters/phpunit/src/Storage.php +0 -26
  82. package/project-skills/tdd-guard/reporters/phpunit/src/TddGuardExtension.php +0 -33
  83. package/project-skills/tdd-guard/reporters/phpunit/src/TddGuardListener.php +0 -158
  84. package/project-skills/tdd-guard/reporters/phpunit/src/TddGuardSubscriber.php +0 -35
  85. package/project-skills/tdd-guard/reporters/phpunit/src/TestResultCollector.php +0 -105
  86. package/project-skills/tdd-guard/reporters/phpunit/tests/PathValidatorTest.php +0 -74
  87. package/project-skills/tdd-guard/reporters/phpunit/tests/TddGuardExtensionFailedTest.php +0 -241
  88. package/project-skills/tdd-guard/reporters/phpunit/tests/TddGuardExtensionTest.php +0 -84
  89. package/project-skills/tdd-guard/reporters/phpunit/tests/TddGuardStorageLocationTest.php +0 -71
  90. package/project-skills/tdd-guard/reporters/pytest/README.md +0 -77
  91. package/project-skills/tdd-guard/reporters/pytest/pyproject.toml +0 -43
  92. package/project-skills/tdd-guard/reporters/pytest/pytest.ini.example +0 -7
  93. package/project-skills/tdd-guard/reporters/pytest/tdd_guard_pytest/__init__.py +0 -1
  94. package/project-skills/tdd-guard/reporters/pytest/tdd_guard_pytest/pytest_reporter.py +0 -134
  95. package/project-skills/tdd-guard/reporters/pytest/tests/__init__.py +0 -1
  96. package/project-skills/tdd-guard/reporters/pytest/tests/conftest.py +0 -3
  97. package/project-skills/tdd-guard/reporters/pytest/tests/helpers.py +0 -293
  98. package/project-skills/tdd-guard/reporters/pytest/tests/test_config_option.py +0 -38
  99. package/project-skills/tdd-guard/reporters/pytest/tests/test_path_validation.py +0 -59
  100. package/project-skills/tdd-guard/reporters/pytest/tests/test_plugin_config.py +0 -32
  101. package/project-skills/tdd-guard/reporters/pytest/tests/test_project_root.py +0 -296
  102. package/project-skills/tdd-guard/reporters/pytest/tests/test_pytest_reporter.py +0 -137
  103. package/project-skills/tdd-guard/reporters/rspec/Gemfile +0 -3
  104. package/project-skills/tdd-guard/reporters/rust/Cargo.lock +0 -458
  105. package/project-skills/tdd-guard/reporters/rust/Cargo.toml +0 -33
  106. package/project-skills/tdd-guard/reporters/rust/Makefile.example +0 -95
  107. package/project-skills/tdd-guard/reporters/rust/README.md +0 -88
  108. package/project-skills/tdd-guard/reporters/rust/src/error_parser.rs +0 -309
  109. package/project-skills/tdd-guard/reporters/rust/src/main.rs +0 -464
  110. package/project-skills/tdd-guard/reporters/rust/src/parser.rs +0 -225
  111. package/project-skills/tdd-guard/reporters/rust/src/transformer.rs +0 -409
  112. package/project-skills/tdd-guard/reporters/storybook/README.md +0 -108
  113. package/project-skills/tdd-guard/reporters/storybook/package-lock.json +0 -9482
  114. package/project-skills/tdd-guard/reporters/storybook/package.json +0 -43
  115. package/project-skills/tdd-guard/reporters/storybook/src/StorybookReporter.test-data.ts +0 -22
  116. package/project-skills/tdd-guard/reporters/storybook/src/StorybookReporter.test.ts +0 -190
  117. package/project-skills/tdd-guard/reporters/storybook/src/StorybookReporter.ts +0 -88
  118. package/project-skills/tdd-guard/reporters/storybook/src/index.ts +0 -12
  119. package/project-skills/tdd-guard/reporters/storybook/src/types.ts +0 -37
  120. package/project-skills/tdd-guard/reporters/storybook/tsconfig.json +0 -11
  121. package/project-skills/tdd-guard/reporters/test/artifacts/go/failing/go.mod +0 -3
  122. package/project-skills/tdd-guard/reporters/test/artifacts/go/failing/single_failing_test.go +0 -13
  123. package/project-skills/tdd-guard/reporters/test/artifacts/go/import/go.mod +0 -3
  124. package/project-skills/tdd-guard/reporters/test/artifacts/go/import/single_import_error_test.go +0 -17
  125. package/project-skills/tdd-guard/reporters/test/artifacts/go/passing/go.mod +0 -3
  126. package/project-skills/tdd-guard/reporters/test/artifacts/go/passing/single_passing_test.go +0 -13
  127. package/project-skills/tdd-guard/reporters/test/artifacts/jest/single-failing.test.js +0 -5
  128. package/project-skills/tdd-guard/reporters/test/artifacts/jest/single-import-error.test.js +0 -8
  129. package/project-skills/tdd-guard/reporters/test/artifacts/jest/single-passing.test.js +0 -5
  130. package/project-skills/tdd-guard/reporters/test/artifacts/phpunit/SingleFailingTest.php +0 -11
  131. package/project-skills/tdd-guard/reporters/test/artifacts/phpunit/SingleImportErrorTest.php +0 -14
  132. package/project-skills/tdd-guard/reporters/test/artifacts/phpunit/SinglePassingTest.php +0 -11
  133. package/project-skills/tdd-guard/reporters/test/artifacts/pytest/test_single_failing.py +0 -3
  134. package/project-skills/tdd-guard/reporters/test/artifacts/pytest/test_single_import_error.py +0 -6
  135. package/project-skills/tdd-guard/reporters/test/artifacts/pytest/test_single_passing.py +0 -3
  136. package/project-skills/tdd-guard/reporters/test/artifacts/rust/failing/Cargo.lock +0 -7
  137. package/project-skills/tdd-guard/reporters/test/artifacts/rust/failing/Cargo.toml +0 -4
  138. package/project-skills/tdd-guard/reporters/test/artifacts/rust/failing/src/lib.rs +0 -14
  139. package/project-skills/tdd-guard/reporters/test/artifacts/rust/import/Cargo.lock +0 -7
  140. package/project-skills/tdd-guard/reporters/test/artifacts/rust/import/Cargo.toml +0 -4
  141. package/project-skills/tdd-guard/reporters/test/artifacts/rust/import/src/lib.rs +0 -13
  142. package/project-skills/tdd-guard/reporters/test/artifacts/rust/passing/Cargo.lock +0 -7
  143. package/project-skills/tdd-guard/reporters/test/artifacts/rust/passing/Cargo.toml +0 -4
  144. package/project-skills/tdd-guard/reporters/test/artifacts/rust/passing/src/lib.rs +0 -14
  145. package/project-skills/tdd-guard/reporters/test/artifacts/storybook/Calculator.js +0 -4
  146. package/project-skills/tdd-guard/reporters/test/artifacts/storybook/single-failing.stories.js +0 -15
  147. package/project-skills/tdd-guard/reporters/test/artifacts/storybook/single-import-error.stories.js +0 -14
  148. package/project-skills/tdd-guard/reporters/test/artifacts/storybook/single-passing.stories.js +0 -15
  149. package/project-skills/tdd-guard/reporters/test/artifacts/vitest/single-failing.test.js +0 -7
  150. package/project-skills/tdd-guard/reporters/test/artifacts/vitest/single-import-error.test.js +0 -9
  151. package/project-skills/tdd-guard/reporters/test/artifacts/vitest/single-passing.test.js +0 -7
  152. package/project-skills/tdd-guard/reporters/test/factories/go.ts +0 -59
  153. package/project-skills/tdd-guard/reporters/test/factories/helpers.ts +0 -48
  154. package/project-skills/tdd-guard/reporters/test/factories/index.ts +0 -7
  155. package/project-skills/tdd-guard/reporters/test/factories/jest.ts +0 -51
  156. package/project-skills/tdd-guard/reporters/test/factories/phpunit.ts +0 -63
  157. package/project-skills/tdd-guard/reporters/test/factories/pytest.ts +0 -41
  158. package/project-skills/tdd-guard/reporters/test/factories/rust.ts +0 -158
  159. package/project-skills/tdd-guard/reporters/test/factories/storybook.ts +0 -198
  160. package/project-skills/tdd-guard/reporters/test/factories/vitest.ts +0 -51
  161. package/project-skills/tdd-guard/reporters/test/reporters.integration.test.ts +0 -735
  162. package/project-skills/tdd-guard/reporters/test/types.ts +0 -28
  163. package/project-skills/tdd-guard/reporters/vitest/README.md +0 -64
  164. package/project-skills/tdd-guard/reporters/vitest/package.json +0 -35
  165. package/project-skills/tdd-guard/reporters/vitest/src/VitestReporter.test-data.ts +0 -85
  166. package/project-skills/tdd-guard/reporters/vitest/src/VitestReporter.test.ts +0 -446
  167. package/project-skills/tdd-guard/reporters/vitest/src/VitestReporter.ts +0 -110
  168. package/project-skills/tdd-guard/reporters/vitest/src/index.ts +0 -4
  169. package/project-skills/tdd-guard/reporters/vitest/src/types.ts +0 -39
  170. package/project-skills/tdd-guard/reporters/vitest/tsconfig.json +0 -11
  171. package/project-skills/tdd-guard/src/cli/buildContext.test.ts +0 -200
  172. package/project-skills/tdd-guard/src/cli/buildContext.ts +0 -48
  173. package/project-skills/tdd-guard/src/cli/tdd-guard.test.ts +0 -159
  174. package/project-skills/tdd-guard/src/cli/tdd-guard.ts +0 -48
  175. package/project-skills/tdd-guard/src/config/Config.test.ts +0 -538
  176. package/project-skills/tdd-guard/src/config/Config.ts +0 -172
  177. package/project-skills/tdd-guard/src/contracts/schemas/guardSchemas.test.ts +0 -58
  178. package/project-skills/tdd-guard/src/contracts/schemas/guardSchemas.ts +0 -8
  179. package/project-skills/tdd-guard/src/contracts/schemas/lintSchemas.test.ts +0 -347
  180. package/project-skills/tdd-guard/src/contracts/schemas/lintSchemas.ts +0 -61
  181. package/project-skills/tdd-guard/src/contracts/schemas/pytestSchemas.test.ts +0 -24
  182. package/project-skills/tdd-guard/src/contracts/schemas/pytestSchemas.ts +0 -7
  183. package/project-skills/tdd-guard/src/contracts/schemas/reporterSchemas.test.ts +0 -377
  184. package/project-skills/tdd-guard/src/contracts/schemas/reporterSchemas.ts +0 -75
  185. package/project-skills/tdd-guard/src/contracts/schemas/toolSchemas.test.ts +0 -563
  186. package/project-skills/tdd-guard/src/contracts/schemas/toolSchemas.ts +0 -140
  187. package/project-skills/tdd-guard/src/contracts/types/ClientType.ts +0 -1
  188. package/project-skills/tdd-guard/src/contracts/types/ConfigOptions.ts +0 -12
  189. package/project-skills/tdd-guard/src/contracts/types/Context.ts +0 -16
  190. package/project-skills/tdd-guard/src/contracts/types/ModelClient.ts +0 -3
  191. package/project-skills/tdd-guard/src/contracts/types/ValidationResult.ts +0 -6
  192. package/project-skills/tdd-guard/src/guard/GuardManager.test.ts +0 -336
  193. package/project-skills/tdd-guard/src/guard/GuardManager.ts +0 -83
  194. package/project-skills/tdd-guard/src/hooks/HookEvents.test.ts +0 -107
  195. package/project-skills/tdd-guard/src/hooks/HookEvents.ts +0 -39
  196. package/project-skills/tdd-guard/src/hooks/fileTypeDetection.ts +0 -16
  197. package/project-skills/tdd-guard/src/hooks/postToolLint.test.ts +0 -327
  198. package/project-skills/tdd-guard/src/hooks/postToolLint.ts +0 -165
  199. package/project-skills/tdd-guard/src/hooks/processHookData.test.ts +0 -465
  200. package/project-skills/tdd-guard/src/hooks/processHookData.ts +0 -203
  201. package/project-skills/tdd-guard/src/hooks/sessionHandler.test.ts +0 -136
  202. package/project-skills/tdd-guard/src/hooks/sessionHandler.ts +0 -31
  203. package/project-skills/tdd-guard/src/hooks/userPromptHandler.test.ts +0 -131
  204. package/project-skills/tdd-guard/src/hooks/userPromptHandler.ts +0 -55
  205. package/project-skills/tdd-guard/src/index.ts +0 -19
  206. package/project-skills/tdd-guard/src/linters/Linter.ts +0 -5
  207. package/project-skills/tdd-guard/src/linters/eslint/ESLint.test.ts +0 -183
  208. package/project-skills/tdd-guard/src/linters/eslint/ESLint.ts +0 -82
  209. package/project-skills/tdd-guard/src/linters/golangci/GolangciLint.test.ts +0 -170
  210. package/project-skills/tdd-guard/src/linters/golangci/GolangciLint.ts +0 -148
  211. package/project-skills/tdd-guard/src/processors/index.ts +0 -1
  212. package/project-skills/tdd-guard/src/processors/lintProcessor.ts +0 -77
  213. package/project-skills/tdd-guard/src/processors/testResults/TestResultsProcessor.test.ts +0 -303
  214. package/project-skills/tdd-guard/src/processors/testResults/TestResultsProcessor.ts +0 -255
  215. package/project-skills/tdd-guard/src/providers/LinterProvider.test.ts +0 -43
  216. package/project-skills/tdd-guard/src/providers/LinterProvider.ts +0 -20
  217. package/project-skills/tdd-guard/src/providers/ModelClientProvider.test.ts +0 -68
  218. package/project-skills/tdd-guard/src/providers/ModelClientProvider.ts +0 -22
  219. package/project-skills/tdd-guard/src/storage/FileStorage.test.ts +0 -76
  220. package/project-skills/tdd-guard/src/storage/FileStorage.ts +0 -108
  221. package/project-skills/tdd-guard/src/storage/MemoryStorage.ts +0 -57
  222. package/project-skills/tdd-guard/src/storage/Storage.test.ts +0 -227
  223. package/project-skills/tdd-guard/src/storage/Storage.ts +0 -17
  224. package/project-skills/tdd-guard/src/validation/context/context.test.ts +0 -364
  225. package/project-skills/tdd-guard/src/validation/context/context.ts +0 -155
  226. package/project-skills/tdd-guard/src/validation/models/AnthropicApi.test.ts +0 -171
  227. package/project-skills/tdd-guard/src/validation/models/AnthropicApi.ts +0 -49
  228. package/project-skills/tdd-guard/src/validation/models/ClaudeAgentSdk.test.ts +0 -167
  229. package/project-skills/tdd-guard/src/validation/models/ClaudeAgentSdk.ts +0 -54
  230. package/project-skills/tdd-guard/src/validation/models/ClaudeCli.test.ts +0 -239
  231. package/project-skills/tdd-guard/src/validation/models/ClaudeCli.ts +0 -57
  232. package/project-skills/tdd-guard/src/validation/prompts/file-types.ts +0 -52
  233. package/project-skills/tdd-guard/src/validation/prompts/operations/edit.ts +0 -58
  234. package/project-skills/tdd-guard/src/validation/prompts/operations/multi-edit.ts +0 -54
  235. package/project-skills/tdd-guard/src/validation/prompts/operations/write.ts +0 -54
  236. package/project-skills/tdd-guard/src/validation/prompts/response.ts +0 -40
  237. package/project-skills/tdd-guard/src/validation/prompts/rules.ts +0 -51
  238. package/project-skills/tdd-guard/src/validation/prompts/system-prompt.ts +0 -10
  239. package/project-skills/tdd-guard/src/validation/prompts/tools/lint-results.ts +0 -15
  240. package/project-skills/tdd-guard/src/validation/prompts/tools/test-output.ts +0 -14
  241. package/project-skills/tdd-guard/src/validation/prompts/tools/todos.ts +0 -9
  242. package/project-skills/tdd-guard/src/validation/validator.test.ts +0 -268
  243. package/project-skills/tdd-guard/src/validation/validator.ts +0 -159
  244. package/project-skills/tdd-guard/test/artifacts/go/.golangci.yml +0 -6
  245. package/project-skills/tdd-guard/test/artifacts/go/with-issues/file-with-issues.go +0 -12
  246. package/project-skills/tdd-guard/test/artifacts/go/with-issues/go.mod +0 -3
  247. package/project-skills/tdd-guard/test/artifacts/go/without-issues/file-without-issues.go +0 -7
  248. package/project-skills/tdd-guard/test/artifacts/go/without-issues/go.mod +0 -3
  249. package/project-skills/tdd-guard/test/artifacts/javascript/eslint.config.js +0 -20
  250. package/project-skills/tdd-guard/test/artifacts/javascript/file-with-issues.js +0 -12
  251. package/project-skills/tdd-guard/test/artifacts/javascript/file-without-issues.js +0 -10
  252. package/project-skills/tdd-guard/test/hooks/fileTypeDetection.test.ts +0 -26
  253. package/project-skills/tdd-guard/test/hooks/processHookData.fileType.test.ts +0 -46
  254. package/project-skills/tdd-guard/test/hooks/processHookData.python.test.ts +0 -68
  255. package/project-skills/tdd-guard/test/integration/test-context.test.ts +0 -66
  256. package/project-skills/tdd-guard/test/integration/validator.core.test.ts +0 -96
  257. package/project-skills/tdd-guard/test/integration/validator.scenarios.test.ts +0 -497
  258. package/project-skills/tdd-guard/test/utils/assertions.ts +0 -29
  259. package/project-skills/tdd-guard/test/utils/factories/contextFactory.ts +0 -30
  260. package/project-skills/tdd-guard/test/utils/factories/editFactory.ts +0 -82
  261. package/project-skills/tdd-guard/test/utils/factories/helpers.test.ts +0 -46
  262. package/project-skills/tdd-guard/test/utils/factories/helpers.ts +0 -46
  263. package/project-skills/tdd-guard/test/utils/factories/lintFactory.ts +0 -352
  264. package/project-skills/tdd-guard/test/utils/factories/modelClientProviderFactory.ts +0 -21
  265. package/project-skills/tdd-guard/test/utils/factories/multiEditFactory.ts +0 -79
  266. package/project-skills/tdd-guard/test/utils/factories/operations.ts +0 -57
  267. package/project-skills/tdd-guard/test/utils/factories/reporterFactory.ts +0 -55
  268. package/project-skills/tdd-guard/test/utils/factories/scenarios/index.ts +0 -22
  269. package/project-skills/tdd-guard/test/utils/factories/scenarios/languages/python.ts +0 -745
  270. package/project-skills/tdd-guard/test/utils/factories/scenarios/languages/typescript.ts +0 -767
  271. package/project-skills/tdd-guard/test/utils/factories/scenarios/types.ts +0 -77
  272. package/project-skills/tdd-guard/test/utils/factories/scenarios/utils.ts +0 -15
  273. package/project-skills/tdd-guard/test/utils/factories/sessionStartFactory.ts +0 -36
  274. package/project-skills/tdd-guard/test/utils/factories/testDefaults.ts +0 -90
  275. package/project-skills/tdd-guard/test/utils/factories/testResultsFactory.ts +0 -234
  276. package/project-skills/tdd-guard/test/utils/factories/todoFactory.ts +0 -99
  277. package/project-skills/tdd-guard/test/utils/factories/userPromptSubmitFactory.ts +0 -39
  278. package/project-skills/tdd-guard/test/utils/factories/writeFactory.ts +0 -70
  279. package/project-skills/tdd-guard/test/utils/index.ts +0 -131
  280. package/project-skills/tdd-guard/tsconfig.build.json +0 -16
  281. package/project-skills/tdd-guard/tsconfig.eslint.json +0 -17
  282. package/project-skills/tdd-guard/tsconfig.json +0 -32
  283. package/project-skills/tdd-guard/tsconfig.node.json +0 -10
  284. 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
- }