xtrm-tools 2.3.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 (284) hide show
  1. package/README.md +127 -111
  2. package/cli/dist/index.cjs +107 -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,327 +0,0 @@
1
- import { describe, it, expect, vi } from 'vitest'
2
- import { handlePostToolLint, PostToolLintHandler, DEFAULT_RESULT } from './postToolLint'
3
- import { testData } from '@testUtils'
4
- import { Linter } from '../linters/Linter'
5
- import { MemoryStorage } from '../storage/MemoryStorage'
6
- import { LintData, LintResult } from '../contracts/schemas/lintSchemas'
7
- import { HookData } from '../contracts/schemas/toolSchemas'
8
- import { TestResult } from '../contracts/schemas/reporterSchemas'
9
- import { ValidationResult } from '../contracts/types/ValidationResult'
10
-
11
- describe('postToolLint', () => {
12
- describe('PostToolLintHandler', () => {
13
- it('uses null linter by default', () => {
14
- const storage = new MemoryStorage()
15
- const handler = new PostToolLintHandler(storage)
16
- expect(handler['linter']).toBeNull()
17
- })
18
-
19
- it('accepts Linter instance in constructor', () => {
20
- const storage = new MemoryStorage()
21
- const testLinter = new TestLinter()
22
- const handler = new PostToolLintHandler(storage, testLinter)
23
- expect(handler['linter']).toBe(testLinter)
24
- })
25
-
26
- it('accepts null linter in constructor', () => {
27
- const storage = new MemoryStorage()
28
- const handler = new PostToolLintHandler(storage, null)
29
- expect(handler['linter']).toBeNull()
30
- })
31
- })
32
-
33
- it('should return default result for PreToolUse hooks', async () => {
34
- const { result, parsedLint } = await runLintAndGetResult({
35
- lintResult: testData.lintResultWithoutErrors(),
36
- operation: { hook_event_name: 'PreToolUse' }
37
- })
38
-
39
- expect(result).toEqual(DEFAULT_RESULT)
40
- expect(parsedLint).toBeNull()
41
- })
42
-
43
-
44
- describe('when processing tool operations', () => {
45
- it('runs lint and saves results for Edit operations', async () => {
46
- const { parsedLint } = await runLintAndGetResult()
47
-
48
- expect(parsedLint).not.toBeNull()
49
- expect(parsedLint!.files).toEqual([])
50
- expect(parsedLint!.errorCount).toBe(0)
51
- expect(parsedLint!.warningCount).toBe(0)
52
- })
53
-
54
- it('runs lint and saves results for Write operations', async () => {
55
- const { parsedLint } = await runLintAndGetResult({
56
- operation: { tool_name: 'Write' }
57
- })
58
-
59
- expect(parsedLint).not.toBeNull()
60
- expect(parsedLint!.hasNotifiedAboutLintIssues).toBe(false)
61
- })
62
-
63
- it('runs lint and saves results for MultiEdit operations', async () => {
64
- const { parsedLint } = await runLintAndGetResult({
65
- operation: { tool_name: 'MultiEdit' }
66
- })
67
-
68
- expect(parsedLint).not.toBeNull()
69
- expect(parsedLint!.hasNotifiedAboutLintIssues).toBe(false)
70
- })
71
-
72
- it('returns default result and does not save lint data when operation has no file paths', async () => {
73
- const { result, parsedLint } = await runLintAndGetResult({
74
- operation: {
75
- tool_name: 'TodoWrite',
76
- tool_input: { todos: [] }
77
- }
78
- })
79
-
80
- expect(result).toEqual(DEFAULT_RESULT)
81
- expect(parsedLint).toBeNull()
82
- })
83
-
84
- it('processes MultiEdit operations even when some edits lack file_path', async () => {
85
- const { parsedLint } = await runLintAndGetResult({
86
- operation: {
87
- tool_name: 'MultiEdit',
88
- tool_input: {
89
- edits: [
90
- { old_string: 'a', new_string: 'b' }, // missing file_path
91
- { file_path: '/test/file.ts', old_string: 'c', new_string: 'd' }
92
- ]
93
- }
94
- }
95
- })
96
-
97
- // Should still process the edit that has a file_path
98
- expect(parsedLint).not.toBeNull()
99
- expect(parsedLint!.hasNotifiedAboutLintIssues).toBe(false)
100
- })
101
- })
102
-
103
- it('should always save lint data to storage', async () => {
104
- const lintData = testData.lintResultWithError()
105
-
106
- const { parsedLint } = await runLintAndGetResult({ lintResult: lintData })
107
-
108
- expect(parsedLint!.issues).toEqual(lintData.issues)
109
- expect(parsedLint!.errorCount).toBe(1)
110
- })
111
-
112
- describe('when lint issues exist', () => {
113
- describe('and notification flag is false', () => {
114
- it('does not block the operation', async () => {
115
- const { result } = await runLintAndGetResult({
116
- lintResult: testData.lintResultWithError()
117
- })
118
-
119
- expect(result).toEqual(DEFAULT_RESULT)
120
- })
121
-
122
- it('saves hasNotifiedAboutLintIssues as false', async () => {
123
- const { parsedLint } = await runLintAndGetResult({
124
- lintResult: testData.lintResultWithError()
125
- })
126
-
127
- expect(parsedLint!.hasNotifiedAboutLintIssues).toBe(false)
128
- })
129
- })
130
-
131
- describe('and notification flag is true', () => {
132
- it('blocks with detailed lint errors', async () => {
133
- const { result } = await runLintAndGetResult({
134
- lintResult: testData.lintResultWithError(),
135
- initialLintData: testData.lintDataWithNotificationFlag()
136
- })
137
-
138
- expect(result.decision).toBe('block')
139
- expect(result.reason).toContain('Lint issues detected:')
140
- })
141
-
142
- it('preserves the notification flag', async () => {
143
- const { parsedLint } = await runLintAndGetResult({
144
- lintResult: testData.lintResultWithError(),
145
- initialLintData: testData.lintDataWithNotificationFlag()
146
- })
147
-
148
- expect(parsedLint!.hasNotifiedAboutLintIssues).toBe(true)
149
- })
150
- })
151
-
152
- describe('and tests are failing (red phase)', () => {
153
- it('saves lint data without blocking', async () => {
154
- const lintData = testData.lintResultWithError()
155
-
156
- const { parsedLint } = await runLintAndGetResult({
157
- lintResult: lintData,
158
- initialTestData: testData.failedTestResults()
159
- })
160
-
161
- expect(parsedLint!.issues).toEqual(lintData.issues)
162
- expect(parsedLint!.errorCount).toBe(1)
163
- expect(parsedLint!.hasNotifiedAboutLintIssues).toBe(false)
164
- })
165
- })
166
- })
167
-
168
- describe('when storage errors occur', () => {
169
- it('should treat storage read errors as no stored lint data', async () => {
170
- // This test requires manual setup to spy on storage
171
- const storage = new MemoryStorage()
172
- const testLinter = new TestLinter(testData.lintResultWithoutErrors())
173
-
174
- // Make storage.getLint() throw an error only on the first call
175
- const getLintSpy = vi.spyOn(storage, 'getLint')
176
- getLintSpy.mockRejectedValueOnce(new Error('Storage error'))
177
-
178
- const hookData = JSON.stringify({
179
- ...testData.editOperation(),
180
- hook_event_name: 'PostToolUse'
181
- })
182
-
183
- const result = await handlePostToolLint(hookData, storage, testLinter)
184
-
185
- // Should not block (treats error as no stored data)
186
- expect(result).toEqual(DEFAULT_RESULT)
187
-
188
- // Reset the spy and check that storage now contains the new lint data
189
- getLintSpy.mockRestore()
190
- const savedLint = await storage.getLint()
191
- expect(savedLint).toBeTruthy()
192
- const parsedLint = JSON.parse(savedLint!)
193
- expect(parsedLint.hasNotifiedAboutLintIssues).toBe(false)
194
- expect(parsedLint.issues).toEqual([])
195
- })
196
- })
197
-
198
- describe('when linter is null', () => {
199
- it('skips linting and returns default result', async () => {
200
- const storage = new MemoryStorage()
201
- const handler = new PostToolLintHandler(storage, null)
202
- const hookData = {
203
- ...testData.editOperation(),
204
- hook_event_name: 'PostToolUse'
205
- }
206
-
207
- const result = await handler.handle(JSON.stringify(hookData))
208
-
209
- expect(result).toEqual(DEFAULT_RESULT)
210
- const savedLint = await storage.getLint()
211
- expect(savedLint).toBeNull()
212
- })
213
- })
214
-
215
- describe('when no lint issues exist', () => {
216
- describe('and previous state had notification flag set', () => {
217
- it('resets hasNotifiedAboutLintIssues to false', async () => {
218
- const { parsedLint } = await runLintAndGetResult({
219
- lintResult: testData.lintResultWithoutErrors(),
220
- initialLintData: testData.lintDataWithNotificationFlag()
221
- })
222
-
223
- expect(parsedLint!.hasNotifiedAboutLintIssues).toBe(false)
224
- })
225
-
226
- describe('and tests are passing', () => {
227
- it('does not block', async () => {
228
- const { result } = await runLintAndGetResult({
229
- lintResult: testData.lintResultWithoutErrors(),
230
- initialLintData: testData.lintDataWithNotificationFlag(),
231
- initialTestData: testData.passingTestResults()
232
- })
233
-
234
- expect(result).toEqual(DEFAULT_RESULT)
235
- })
236
- })
237
- })
238
-
239
- describe('and previous state had issues and notification flag', () => {
240
- it('resets hasNotifiedAboutLintIssues to false when issues are resolved', async () => {
241
- const { parsedLint } = await runLintAndGetResult({
242
- lintResult: testData.lintResultWithoutErrors(),
243
- initialLintData: testData.lintData({
244
- files: ['/src/example.ts'],
245
- issues: [testData.lintIssue({ file: '/src/example.ts', line: 1, column: 1, message: "Error" })],
246
- hasNotifiedAboutLintIssues: true
247
- })
248
- })
249
-
250
- expect(parsedLint!.hasNotifiedAboutLintIssues).toBe(false)
251
- })
252
- })
253
-
254
- it('saves clean lint data', async () => {
255
- const { parsedLint } = await runLintAndGetResult({
256
- lintResult: testData.lintResultWithoutErrors()
257
- })
258
-
259
- expect(parsedLint!.issues).toEqual([])
260
- expect(parsedLint!.errorCount).toBe(0)
261
- expect(parsedLint!.warningCount).toBe(0)
262
- })
263
- })
264
- })
265
-
266
- // Test helper functions
267
- interface LintTestOptions {
268
- lintResult?: Omit<LintData, 'hasNotifiedAboutLintIssues'>
269
- operation?: Partial<HookData>
270
- storage?: MemoryStorage
271
- initialLintData?: LintData
272
- initialTestData?: TestResult
273
- }
274
-
275
- async function runLintAndGetResult(options: LintTestOptions = {}): Promise<{
276
- result: ValidationResult,
277
- parsedLint: LintData | null,
278
- storage: MemoryStorage
279
- }> {
280
- const { lintResult, operation = {}, storage: existingStorage, initialLintData, initialTestData } = options
281
- const storage = existingStorage ?? new MemoryStorage()
282
-
283
- // Set up initial storage state if provided
284
- if (initialLintData) {
285
- await storage.saveLint(JSON.stringify(initialLintData))
286
- }
287
- if (initialTestData) {
288
- await storage.saveTest(JSON.stringify(initialTestData))
289
- }
290
-
291
- const testLinter = new TestLinter(lintResult ?? testData.lintResultWithoutErrors())
292
-
293
- let baseOperation
294
- if (operation.tool_name === 'Write') {
295
- baseOperation = testData.writeOperation()
296
- } else if (operation.tool_name === 'MultiEdit') {
297
- baseOperation = testData.multiEditOperation()
298
- } else {
299
- baseOperation = testData.editOperation()
300
- }
301
-
302
- const hookData = JSON.stringify({
303
- ...baseOperation,
304
- hook_event_name: 'PostToolUse',
305
- ...operation
306
- })
307
-
308
- const result = await handlePostToolLint(hookData, storage, testLinter)
309
-
310
- const savedLint = await storage.getLint()
311
- const parsedLint = savedLint ? JSON.parse(savedLint) : null
312
-
313
- return { result, parsedLint, storage }
314
- }
315
-
316
- // Test Linter implementation with configurable behavior
317
- class TestLinter implements Linter {
318
- private readonly lintResult: LintResult
319
-
320
- constructor(lintResult?: LintResult) {
321
- this.lintResult = lintResult ?? testData.lintResultWithoutErrors()
322
- }
323
-
324
- async lint(): Promise<LintResult> {
325
- return this.lintResult
326
- }
327
- }
@@ -1,165 +0,0 @@
1
- import { ValidationResult } from '../contracts/types/ValidationResult'
2
- import { HookData, HookDataSchema } from '../contracts/schemas/toolSchemas'
3
- import { LintData, LintDataSchema, LintResult } from '../contracts/schemas/lintSchemas'
4
- import { Storage } from '../storage/Storage'
5
- import { Linter } from '../linters/Linter'
6
-
7
- export const DEFAULT_RESULT: ValidationResult = {
8
- decision: undefined,
9
- reason: ''
10
- }
11
-
12
- export class PostToolLintHandler {
13
- private readonly linter: Linter | null
14
- private readonly storage: Storage
15
-
16
- constructor(storage: Storage, linter?: Linter | null) {
17
- this.storage = storage
18
- this.linter = linter ?? null
19
- }
20
-
21
- async handle(hookData: string): Promise<ValidationResult> {
22
- // If no linter is configured, skip linting
23
- if (!this.linter) {
24
- return DEFAULT_RESULT
25
- }
26
- return handlePostToolLint(hookData, this.storage, this.linter)
27
- }
28
- }
29
-
30
- function parseAndValidateHookData(hookData: string): HookData | null {
31
- try {
32
- const parsedData = JSON.parse(hookData)
33
- const hookResult = HookDataSchema.safeParse(parsedData)
34
-
35
- if (!hookResult.success) {
36
- return null
37
- }
38
-
39
- // Only process PostToolUse hooks
40
- if (hookResult.data.hook_event_name !== 'PostToolUse') {
41
- return null
42
- }
43
-
44
- return hookResult.data
45
- } catch {
46
- return null
47
- }
48
- }
49
-
50
- async function getStoredLintData(storage: Storage): Promise<LintData | null> {
51
- try {
52
- const lintDataStr = await storage.getLint()
53
- if (lintDataStr) {
54
- return LintDataSchema.parse(JSON.parse(lintDataStr))
55
- }
56
- } catch {
57
- // Treat any error as no stored data
58
- }
59
- return null
60
- }
61
-
62
- function createLintData(
63
- lintResults: LintResult,
64
- storedLintData: LintData | null
65
- ): LintData {
66
- const hasIssues = lintResults.errorCount > 0 || lintResults.warningCount > 0
67
-
68
- return {
69
- ...lintResults,
70
- hasNotifiedAboutLintIssues: hasIssues
71
- ? (storedLintData?.hasNotifiedAboutLintIssues ?? false) // Preserve flag when issues exist
72
- : false // Reset flag when no issues
73
- }
74
- }
75
-
76
- function createBlockResult(lintData: LintData): ValidationResult {
77
- const formattedIssues = formatLintIssues(lintData.issues)
78
- const summary = `\n✖ ${lintData.errorCount + lintData.warningCount} problems (${lintData.errorCount} errors, ${lintData.warningCount} warnings)`
79
-
80
- return {
81
- decision: 'block',
82
- reason: `Lint issues detected:${formattedIssues}\n${summary}\n\nPlease fix these issues before proceeding.`
83
- }
84
- }
85
-
86
- function formatLintIssues(issues: LintData['issues']): string {
87
- const issuesByFile = new Map<string, string[]>()
88
-
89
- for (const issue of issues) {
90
- if (!issuesByFile.has(issue.file)) {
91
- issuesByFile.set(issue.file, [])
92
- }
93
- const ruleInfo = issue.rule ? ` ${issue.rule}` : ''
94
- issuesByFile.get(issue.file)!.push(
95
- ` ${issue.line}:${issue.column} ${issue.severity} ${issue.message}${ruleInfo}`
96
- )
97
- }
98
-
99
- let formattedIssues = ''
100
- for (const [file, fileIssues] of issuesByFile) {
101
- formattedIssues += `\n${file}\n${fileIssues.join('\n')}`
102
- }
103
-
104
- return formattedIssues
105
- }
106
-
107
- export async function handlePostToolLint(
108
- hookData: string,
109
- storage: Storage,
110
- linter: Linter
111
- ): Promise<ValidationResult> {
112
- const validatedHookData = parseAndValidateHookData(hookData)
113
- if (!validatedHookData) {
114
- return DEFAULT_RESULT
115
- }
116
-
117
- // Extract file paths from tool operation
118
- const filePaths = extractFilePaths(validatedHookData)
119
- if (filePaths.length === 0) {
120
- return DEFAULT_RESULT
121
- }
122
-
123
- // Get current lint data to check hasNotifiedAboutLintIssues state
124
- const storedLintData = await getStoredLintData(storage)
125
-
126
- // Run linting on the files
127
- const lintResults = await linter.lint(filePaths)
128
-
129
- // Create and save lint data
130
- const lintData = createLintData(lintResults, storedLintData)
131
- await storage.saveLint(JSON.stringify(lintData))
132
-
133
- const hasIssues = lintResults.errorCount > 0 || lintResults.warningCount > 0
134
-
135
- // Block if:
136
- // 1. PreToolUse has notified (flag is true)
137
- // 2. There are still issues
138
- if (storedLintData?.hasNotifiedAboutLintIssues && hasIssues) {
139
- return createBlockResult(lintData)
140
- }
141
-
142
- return DEFAULT_RESULT
143
- }
144
-
145
- function extractFilePaths(hookData: HookData): string[] {
146
- const toolInput = hookData.tool_input
147
- if (!toolInput || typeof toolInput !== 'object') return []
148
-
149
- const paths: string[] = []
150
-
151
- if ('file_path' in toolInput && typeof toolInput.file_path === 'string') {
152
- paths.push(toolInput.file_path)
153
- }
154
-
155
- // Handle multi-edit operations
156
- if ('edits' in toolInput && Array.isArray(toolInput.edits)) {
157
- for (const edit of toolInput.edits) {
158
- if ('file_path' in edit && typeof edit.file_path === 'string') {
159
- paths.push(edit.file_path)
160
- }
161
- }
162
- }
163
-
164
- return [...new Set(paths)] // Remove duplicates
165
- }