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.
- package/README.md +132 -111
- package/cli/dist/index.cjs +142 -53
- package/cli/dist/index.cjs.map +1 -1
- package/cli/package.json +1 -1
- package/config/pi/extensions/beads.ts +24 -0
- package/hooks/beads-gate-core.mjs +6 -4
- package/hooks/beads-memory-gate.mjs +12 -5
- package/hooks/hooks.json +126 -0
- package/package.json +3 -1
- package/skills/test-planning/SKILL.md +208 -0
- package/skills/test-planning/evals/evals.json +23 -0
- package/skills/using-xtrm/SKILL.md +5 -27
- package/project-skills/tdd-guard/.claude/hooks/tdd-guard-pretool-bridge.cjs +0 -103
- package/project-skills/tdd-guard/.claude/settings.json +0 -38
- package/project-skills/tdd-guard/.claude/skills/using-tdd-guard/SKILL.md +0 -79
- package/project-skills/tdd-guard/CLAUDE.md +0 -98
- package/project-skills/tdd-guard/CONTRIBUTING.md +0 -38
- package/project-skills/tdd-guard/DEVELOPMENT.md +0 -127
- package/project-skills/tdd-guard/LICENSE +0 -21
- package/project-skills/tdd-guard/README.md +0 -398
- package/project-skills/tdd-guard/docs/adr/001-claude-session-subdirectory.md +0 -52
- package/project-skills/tdd-guard/docs/adr/002-secure-claude-binary-path.md +0 -56
- package/project-skills/tdd-guard/docs/adr/003-remove-configurable-data-directory.md +0 -56
- package/project-skills/tdd-guard/docs/adr/004-monorepo-architecture.md +0 -64
- package/project-skills/tdd-guard/docs/adr/005-claude-project-dir-support.md +0 -55
- package/project-skills/tdd-guard/docs/adr/006-phpunit-separate-repository.md +0 -93
- package/project-skills/tdd-guard/docs/adr/007-golangci-lint-path-support.md +0 -83
- package/project-skills/tdd-guard/docs/adr/008-storybook-reporter-design.md +0 -182
- package/project-skills/tdd-guard/docs/assets/tdd-guard-demo-screenshot.gif +0 -0
- package/project-skills/tdd-guard/docs/config-migration.md +0 -143
- package/project-skills/tdd-guard/docs/configuration.md +0 -137
- package/project-skills/tdd-guard/docs/custom-instructions.md +0 -43
- package/project-skills/tdd-guard/docs/enforcement.md +0 -46
- package/project-skills/tdd-guard/docs/ignore-patterns.md +0 -81
- package/project-skills/tdd-guard/docs/linting.md +0 -109
- package/project-skills/tdd-guard/docs/quick-commands.md +0 -52
- package/project-skills/tdd-guard/docs/session-management.md +0 -75
- package/project-skills/tdd-guard/docs/storybook-vitest-addon.md +0 -120
- package/project-skills/tdd-guard/docs/validation-model.md +0 -63
- package/project-skills/tdd-guard/eslint.config.mjs +0 -140
- package/project-skills/tdd-guard/package-lock.json +0 -16937
- package/project-skills/tdd-guard/package.json +0 -102
- package/project-skills/tdd-guard/reporters/go/README.md +0 -67
- package/project-skills/tdd-guard/reporters/go/cmd/tdd-guard-go/main.go +0 -127
- package/project-skills/tdd-guard/reporters/go/cmd/tdd-guard-go/main_test.go +0 -280
- package/project-skills/tdd-guard/reporters/go/go.mod +0 -3
- package/project-skills/tdd-guard/reporters/go/go.sum +0 -0
- package/project-skills/tdd-guard/reporters/go/internal/formatter/formatter.go +0 -126
- package/project-skills/tdd-guard/reporters/go/internal/formatter/formatter_test.go +0 -264
- package/project-skills/tdd-guard/reporters/go/internal/io/tee_reader.go +0 -26
- package/project-skills/tdd-guard/reporters/go/internal/io/tee_reader_test.go +0 -37
- package/project-skills/tdd-guard/reporters/go/internal/parser/mixed_reader.go +0 -94
- package/project-skills/tdd-guard/reporters/go/internal/parser/mixed_reader_test.go +0 -198
- package/project-skills/tdd-guard/reporters/go/internal/parser/parser.go +0 -245
- package/project-skills/tdd-guard/reporters/go/internal/parser/parser_test.go +0 -547
- package/project-skills/tdd-guard/reporters/go/internal/storage/storage.go +0 -35
- package/project-skills/tdd-guard/reporters/go/internal/storage/storage_test.go +0 -113
- package/project-skills/tdd-guard/reporters/go/internal/transformer/transformer.go +0 -103
- package/project-skills/tdd-guard/reporters/go/internal/transformer/transformer_test.go +0 -303
- package/project-skills/tdd-guard/reporters/jest/README.md +0 -102
- package/project-skills/tdd-guard/reporters/jest/package.json +0 -38
- package/project-skills/tdd-guard/reporters/jest/src/JestReporter.test-data.ts +0 -199
- package/project-skills/tdd-guard/reporters/jest/src/JestReporter.test.ts +0 -302
- package/project-skills/tdd-guard/reporters/jest/src/JestReporter.ts +0 -201
- package/project-skills/tdd-guard/reporters/jest/src/index.ts +0 -4
- package/project-skills/tdd-guard/reporters/jest/src/types.ts +0 -42
- package/project-skills/tdd-guard/reporters/jest/tsconfig.json +0 -11
- package/project-skills/tdd-guard/reporters/phpunit/.php-cs-fixer.php +0 -28
- package/project-skills/tdd-guard/reporters/phpunit/README.md +0 -97
- package/project-skills/tdd-guard/reporters/phpunit/SYNC_README.md +0 -29
- package/project-skills/tdd-guard/reporters/phpunit/composer.json +0 -55
- package/project-skills/tdd-guard/reporters/phpunit/phpunit.xml.dist +0 -19
- package/project-skills/tdd-guard/reporters/phpunit/psalm.xml +0 -44
- package/project-skills/tdd-guard/reporters/phpunit/src/Event/ErroredTestSubscriber.php +0 -28
- package/project-skills/tdd-guard/reporters/phpunit/src/Event/FailedTestSubscriber.php +0 -28
- package/project-skills/tdd-guard/reporters/phpunit/src/Event/IncompleteTestSubscriber.php +0 -28
- package/project-skills/tdd-guard/reporters/phpunit/src/Event/PassedTestSubscriber.php +0 -27
- package/project-skills/tdd-guard/reporters/phpunit/src/Event/SkippedTestSubscriber.php +0 -28
- package/project-skills/tdd-guard/reporters/phpunit/src/Event/TestRunnerFinishedSubscriber.php +0 -24
- package/project-skills/tdd-guard/reporters/phpunit/src/PathValidator.php +0 -88
- package/project-skills/tdd-guard/reporters/phpunit/src/Storage.php +0 -26
- package/project-skills/tdd-guard/reporters/phpunit/src/TddGuardExtension.php +0 -33
- package/project-skills/tdd-guard/reporters/phpunit/src/TddGuardListener.php +0 -158
- package/project-skills/tdd-guard/reporters/phpunit/src/TddGuardSubscriber.php +0 -35
- package/project-skills/tdd-guard/reporters/phpunit/src/TestResultCollector.php +0 -105
- package/project-skills/tdd-guard/reporters/phpunit/tests/PathValidatorTest.php +0 -74
- package/project-skills/tdd-guard/reporters/phpunit/tests/TddGuardExtensionFailedTest.php +0 -241
- package/project-skills/tdd-guard/reporters/phpunit/tests/TddGuardExtensionTest.php +0 -84
- package/project-skills/tdd-guard/reporters/phpunit/tests/TddGuardStorageLocationTest.php +0 -71
- package/project-skills/tdd-guard/reporters/pytest/README.md +0 -77
- package/project-skills/tdd-guard/reporters/pytest/pyproject.toml +0 -43
- package/project-skills/tdd-guard/reporters/pytest/pytest.ini.example +0 -7
- package/project-skills/tdd-guard/reporters/pytest/tdd_guard_pytest/__init__.py +0 -1
- package/project-skills/tdd-guard/reporters/pytest/tdd_guard_pytest/pytest_reporter.py +0 -134
- package/project-skills/tdd-guard/reporters/pytest/tests/__init__.py +0 -1
- package/project-skills/tdd-guard/reporters/pytest/tests/conftest.py +0 -3
- package/project-skills/tdd-guard/reporters/pytest/tests/helpers.py +0 -293
- package/project-skills/tdd-guard/reporters/pytest/tests/test_config_option.py +0 -38
- package/project-skills/tdd-guard/reporters/pytest/tests/test_path_validation.py +0 -59
- package/project-skills/tdd-guard/reporters/pytest/tests/test_plugin_config.py +0 -32
- package/project-skills/tdd-guard/reporters/pytest/tests/test_project_root.py +0 -296
- package/project-skills/tdd-guard/reporters/pytest/tests/test_pytest_reporter.py +0 -137
- package/project-skills/tdd-guard/reporters/rspec/Gemfile +0 -3
- package/project-skills/tdd-guard/reporters/rust/Cargo.lock +0 -458
- package/project-skills/tdd-guard/reporters/rust/Cargo.toml +0 -33
- package/project-skills/tdd-guard/reporters/rust/Makefile.example +0 -95
- package/project-skills/tdd-guard/reporters/rust/README.md +0 -88
- package/project-skills/tdd-guard/reporters/rust/src/error_parser.rs +0 -309
- package/project-skills/tdd-guard/reporters/rust/src/main.rs +0 -464
- package/project-skills/tdd-guard/reporters/rust/src/parser.rs +0 -225
- package/project-skills/tdd-guard/reporters/rust/src/transformer.rs +0 -409
- package/project-skills/tdd-guard/reporters/storybook/README.md +0 -108
- package/project-skills/tdd-guard/reporters/storybook/package-lock.json +0 -9482
- package/project-skills/tdd-guard/reporters/storybook/package.json +0 -43
- package/project-skills/tdd-guard/reporters/storybook/src/StorybookReporter.test-data.ts +0 -22
- package/project-skills/tdd-guard/reporters/storybook/src/StorybookReporter.test.ts +0 -190
- package/project-skills/tdd-guard/reporters/storybook/src/StorybookReporter.ts +0 -88
- package/project-skills/tdd-guard/reporters/storybook/src/index.ts +0 -12
- package/project-skills/tdd-guard/reporters/storybook/src/types.ts +0 -37
- package/project-skills/tdd-guard/reporters/storybook/tsconfig.json +0 -11
- package/project-skills/tdd-guard/reporters/test/artifacts/go/failing/go.mod +0 -3
- package/project-skills/tdd-guard/reporters/test/artifacts/go/failing/single_failing_test.go +0 -13
- package/project-skills/tdd-guard/reporters/test/artifacts/go/import/go.mod +0 -3
- package/project-skills/tdd-guard/reporters/test/artifacts/go/import/single_import_error_test.go +0 -17
- package/project-skills/tdd-guard/reporters/test/artifacts/go/passing/go.mod +0 -3
- package/project-skills/tdd-guard/reporters/test/artifacts/go/passing/single_passing_test.go +0 -13
- package/project-skills/tdd-guard/reporters/test/artifacts/jest/single-failing.test.js +0 -5
- package/project-skills/tdd-guard/reporters/test/artifacts/jest/single-import-error.test.js +0 -8
- package/project-skills/tdd-guard/reporters/test/artifacts/jest/single-passing.test.js +0 -5
- package/project-skills/tdd-guard/reporters/test/artifacts/phpunit/SingleFailingTest.php +0 -11
- package/project-skills/tdd-guard/reporters/test/artifacts/phpunit/SingleImportErrorTest.php +0 -14
- package/project-skills/tdd-guard/reporters/test/artifacts/phpunit/SinglePassingTest.php +0 -11
- package/project-skills/tdd-guard/reporters/test/artifacts/pytest/test_single_failing.py +0 -3
- package/project-skills/tdd-guard/reporters/test/artifacts/pytest/test_single_import_error.py +0 -6
- package/project-skills/tdd-guard/reporters/test/artifacts/pytest/test_single_passing.py +0 -3
- package/project-skills/tdd-guard/reporters/test/artifacts/rust/failing/Cargo.lock +0 -7
- package/project-skills/tdd-guard/reporters/test/artifacts/rust/failing/Cargo.toml +0 -4
- package/project-skills/tdd-guard/reporters/test/artifacts/rust/failing/src/lib.rs +0 -14
- package/project-skills/tdd-guard/reporters/test/artifacts/rust/import/Cargo.lock +0 -7
- package/project-skills/tdd-guard/reporters/test/artifacts/rust/import/Cargo.toml +0 -4
- package/project-skills/tdd-guard/reporters/test/artifacts/rust/import/src/lib.rs +0 -13
- package/project-skills/tdd-guard/reporters/test/artifacts/rust/passing/Cargo.lock +0 -7
- package/project-skills/tdd-guard/reporters/test/artifacts/rust/passing/Cargo.toml +0 -4
- package/project-skills/tdd-guard/reporters/test/artifacts/rust/passing/src/lib.rs +0 -14
- package/project-skills/tdd-guard/reporters/test/artifacts/storybook/Calculator.js +0 -4
- package/project-skills/tdd-guard/reporters/test/artifacts/storybook/single-failing.stories.js +0 -15
- package/project-skills/tdd-guard/reporters/test/artifacts/storybook/single-import-error.stories.js +0 -14
- package/project-skills/tdd-guard/reporters/test/artifacts/storybook/single-passing.stories.js +0 -15
- package/project-skills/tdd-guard/reporters/test/artifacts/vitest/single-failing.test.js +0 -7
- package/project-skills/tdd-guard/reporters/test/artifacts/vitest/single-import-error.test.js +0 -9
- package/project-skills/tdd-guard/reporters/test/artifacts/vitest/single-passing.test.js +0 -7
- package/project-skills/tdd-guard/reporters/test/factories/go.ts +0 -59
- package/project-skills/tdd-guard/reporters/test/factories/helpers.ts +0 -48
- package/project-skills/tdd-guard/reporters/test/factories/index.ts +0 -7
- package/project-skills/tdd-guard/reporters/test/factories/jest.ts +0 -51
- package/project-skills/tdd-guard/reporters/test/factories/phpunit.ts +0 -63
- package/project-skills/tdd-guard/reporters/test/factories/pytest.ts +0 -41
- package/project-skills/tdd-guard/reporters/test/factories/rust.ts +0 -158
- package/project-skills/tdd-guard/reporters/test/factories/storybook.ts +0 -198
- package/project-skills/tdd-guard/reporters/test/factories/vitest.ts +0 -51
- package/project-skills/tdd-guard/reporters/test/reporters.integration.test.ts +0 -735
- package/project-skills/tdd-guard/reporters/test/types.ts +0 -28
- package/project-skills/tdd-guard/reporters/vitest/README.md +0 -64
- package/project-skills/tdd-guard/reporters/vitest/package.json +0 -35
- package/project-skills/tdd-guard/reporters/vitest/src/VitestReporter.test-data.ts +0 -85
- package/project-skills/tdd-guard/reporters/vitest/src/VitestReporter.test.ts +0 -446
- package/project-skills/tdd-guard/reporters/vitest/src/VitestReporter.ts +0 -110
- package/project-skills/tdd-guard/reporters/vitest/src/index.ts +0 -4
- package/project-skills/tdd-guard/reporters/vitest/src/types.ts +0 -39
- package/project-skills/tdd-guard/reporters/vitest/tsconfig.json +0 -11
- package/project-skills/tdd-guard/src/cli/buildContext.test.ts +0 -200
- package/project-skills/tdd-guard/src/cli/buildContext.ts +0 -48
- package/project-skills/tdd-guard/src/cli/tdd-guard.test.ts +0 -159
- package/project-skills/tdd-guard/src/cli/tdd-guard.ts +0 -48
- package/project-skills/tdd-guard/src/config/Config.test.ts +0 -538
- package/project-skills/tdd-guard/src/config/Config.ts +0 -172
- package/project-skills/tdd-guard/src/contracts/schemas/guardSchemas.test.ts +0 -58
- package/project-skills/tdd-guard/src/contracts/schemas/guardSchemas.ts +0 -8
- package/project-skills/tdd-guard/src/contracts/schemas/lintSchemas.test.ts +0 -347
- package/project-skills/tdd-guard/src/contracts/schemas/lintSchemas.ts +0 -61
- package/project-skills/tdd-guard/src/contracts/schemas/pytestSchemas.test.ts +0 -24
- package/project-skills/tdd-guard/src/contracts/schemas/pytestSchemas.ts +0 -7
- package/project-skills/tdd-guard/src/contracts/schemas/reporterSchemas.test.ts +0 -377
- package/project-skills/tdd-guard/src/contracts/schemas/reporterSchemas.ts +0 -75
- package/project-skills/tdd-guard/src/contracts/schemas/toolSchemas.test.ts +0 -563
- package/project-skills/tdd-guard/src/contracts/schemas/toolSchemas.ts +0 -140
- package/project-skills/tdd-guard/src/contracts/types/ClientType.ts +0 -1
- package/project-skills/tdd-guard/src/contracts/types/ConfigOptions.ts +0 -12
- package/project-skills/tdd-guard/src/contracts/types/Context.ts +0 -16
- package/project-skills/tdd-guard/src/contracts/types/ModelClient.ts +0 -3
- package/project-skills/tdd-guard/src/contracts/types/ValidationResult.ts +0 -6
- package/project-skills/tdd-guard/src/guard/GuardManager.test.ts +0 -336
- package/project-skills/tdd-guard/src/guard/GuardManager.ts +0 -83
- package/project-skills/tdd-guard/src/hooks/HookEvents.test.ts +0 -107
- package/project-skills/tdd-guard/src/hooks/HookEvents.ts +0 -39
- package/project-skills/tdd-guard/src/hooks/fileTypeDetection.ts +0 -16
- package/project-skills/tdd-guard/src/hooks/postToolLint.test.ts +0 -327
- package/project-skills/tdd-guard/src/hooks/postToolLint.ts +0 -165
- package/project-skills/tdd-guard/src/hooks/processHookData.test.ts +0 -465
- package/project-skills/tdd-guard/src/hooks/processHookData.ts +0 -203
- package/project-skills/tdd-guard/src/hooks/sessionHandler.test.ts +0 -136
- package/project-skills/tdd-guard/src/hooks/sessionHandler.ts +0 -31
- package/project-skills/tdd-guard/src/hooks/userPromptHandler.test.ts +0 -131
- package/project-skills/tdd-guard/src/hooks/userPromptHandler.ts +0 -55
- package/project-skills/tdd-guard/src/index.ts +0 -19
- package/project-skills/tdd-guard/src/linters/Linter.ts +0 -5
- package/project-skills/tdd-guard/src/linters/eslint/ESLint.test.ts +0 -183
- package/project-skills/tdd-guard/src/linters/eslint/ESLint.ts +0 -82
- package/project-skills/tdd-guard/src/linters/golangci/GolangciLint.test.ts +0 -170
- package/project-skills/tdd-guard/src/linters/golangci/GolangciLint.ts +0 -148
- package/project-skills/tdd-guard/src/processors/index.ts +0 -1
- package/project-skills/tdd-guard/src/processors/lintProcessor.ts +0 -77
- package/project-skills/tdd-guard/src/processors/testResults/TestResultsProcessor.test.ts +0 -303
- package/project-skills/tdd-guard/src/processors/testResults/TestResultsProcessor.ts +0 -255
- package/project-skills/tdd-guard/src/providers/LinterProvider.test.ts +0 -43
- package/project-skills/tdd-guard/src/providers/LinterProvider.ts +0 -20
- package/project-skills/tdd-guard/src/providers/ModelClientProvider.test.ts +0 -68
- package/project-skills/tdd-guard/src/providers/ModelClientProvider.ts +0 -22
- package/project-skills/tdd-guard/src/storage/FileStorage.test.ts +0 -76
- package/project-skills/tdd-guard/src/storage/FileStorage.ts +0 -108
- package/project-skills/tdd-guard/src/storage/MemoryStorage.ts +0 -57
- package/project-skills/tdd-guard/src/storage/Storage.test.ts +0 -227
- package/project-skills/tdd-guard/src/storage/Storage.ts +0 -17
- package/project-skills/tdd-guard/src/validation/context/context.test.ts +0 -364
- package/project-skills/tdd-guard/src/validation/context/context.ts +0 -155
- package/project-skills/tdd-guard/src/validation/models/AnthropicApi.test.ts +0 -171
- package/project-skills/tdd-guard/src/validation/models/AnthropicApi.ts +0 -49
- package/project-skills/tdd-guard/src/validation/models/ClaudeAgentSdk.test.ts +0 -167
- package/project-skills/tdd-guard/src/validation/models/ClaudeAgentSdk.ts +0 -54
- package/project-skills/tdd-guard/src/validation/models/ClaudeCli.test.ts +0 -239
- package/project-skills/tdd-guard/src/validation/models/ClaudeCli.ts +0 -57
- package/project-skills/tdd-guard/src/validation/prompts/file-types.ts +0 -52
- package/project-skills/tdd-guard/src/validation/prompts/operations/edit.ts +0 -58
- package/project-skills/tdd-guard/src/validation/prompts/operations/multi-edit.ts +0 -54
- package/project-skills/tdd-guard/src/validation/prompts/operations/write.ts +0 -54
- package/project-skills/tdd-guard/src/validation/prompts/response.ts +0 -40
- package/project-skills/tdd-guard/src/validation/prompts/rules.ts +0 -51
- package/project-skills/tdd-guard/src/validation/prompts/system-prompt.ts +0 -10
- package/project-skills/tdd-guard/src/validation/prompts/tools/lint-results.ts +0 -15
- package/project-skills/tdd-guard/src/validation/prompts/tools/test-output.ts +0 -14
- package/project-skills/tdd-guard/src/validation/prompts/tools/todos.ts +0 -9
- package/project-skills/tdd-guard/src/validation/validator.test.ts +0 -268
- package/project-skills/tdd-guard/src/validation/validator.ts +0 -159
- package/project-skills/tdd-guard/test/artifacts/go/.golangci.yml +0 -6
- package/project-skills/tdd-guard/test/artifacts/go/with-issues/file-with-issues.go +0 -12
- package/project-skills/tdd-guard/test/artifacts/go/with-issues/go.mod +0 -3
- package/project-skills/tdd-guard/test/artifacts/go/without-issues/file-without-issues.go +0 -7
- package/project-skills/tdd-guard/test/artifacts/go/without-issues/go.mod +0 -3
- package/project-skills/tdd-guard/test/artifacts/javascript/eslint.config.js +0 -20
- package/project-skills/tdd-guard/test/artifacts/javascript/file-with-issues.js +0 -12
- package/project-skills/tdd-guard/test/artifacts/javascript/file-without-issues.js +0 -10
- package/project-skills/tdd-guard/test/hooks/fileTypeDetection.test.ts +0 -26
- package/project-skills/tdd-guard/test/hooks/processHookData.fileType.test.ts +0 -46
- package/project-skills/tdd-guard/test/hooks/processHookData.python.test.ts +0 -68
- package/project-skills/tdd-guard/test/integration/test-context.test.ts +0 -66
- package/project-skills/tdd-guard/test/integration/validator.core.test.ts +0 -96
- package/project-skills/tdd-guard/test/integration/validator.scenarios.test.ts +0 -497
- package/project-skills/tdd-guard/test/utils/assertions.ts +0 -29
- package/project-skills/tdd-guard/test/utils/factories/contextFactory.ts +0 -30
- package/project-skills/tdd-guard/test/utils/factories/editFactory.ts +0 -82
- package/project-skills/tdd-guard/test/utils/factories/helpers.test.ts +0 -46
- package/project-skills/tdd-guard/test/utils/factories/helpers.ts +0 -46
- package/project-skills/tdd-guard/test/utils/factories/lintFactory.ts +0 -352
- package/project-skills/tdd-guard/test/utils/factories/modelClientProviderFactory.ts +0 -21
- package/project-skills/tdd-guard/test/utils/factories/multiEditFactory.ts +0 -79
- package/project-skills/tdd-guard/test/utils/factories/operations.ts +0 -57
- package/project-skills/tdd-guard/test/utils/factories/reporterFactory.ts +0 -55
- package/project-skills/tdd-guard/test/utils/factories/scenarios/index.ts +0 -22
- package/project-skills/tdd-guard/test/utils/factories/scenarios/languages/python.ts +0 -745
- package/project-skills/tdd-guard/test/utils/factories/scenarios/languages/typescript.ts +0 -767
- package/project-skills/tdd-guard/test/utils/factories/scenarios/types.ts +0 -77
- package/project-skills/tdd-guard/test/utils/factories/scenarios/utils.ts +0 -15
- package/project-skills/tdd-guard/test/utils/factories/sessionStartFactory.ts +0 -36
- package/project-skills/tdd-guard/test/utils/factories/testDefaults.ts +0 -90
- package/project-skills/tdd-guard/test/utils/factories/testResultsFactory.ts +0 -234
- package/project-skills/tdd-guard/test/utils/factories/todoFactory.ts +0 -99
- package/project-skills/tdd-guard/test/utils/factories/userPromptSubmitFactory.ts +0 -39
- package/project-skills/tdd-guard/test/utils/factories/writeFactory.ts +0 -70
- package/project-skills/tdd-guard/test/utils/index.ts +0 -131
- package/project-skills/tdd-guard/tsconfig.build.json +0 -16
- package/project-skills/tdd-guard/tsconfig.eslint.json +0 -17
- package/project-skills/tdd-guard/tsconfig.json +0 -32
- package/project-skills/tdd-guard/tsconfig.node.json +0 -10
- package/project-skills/tdd-guard/vitest.config.ts +0 -85
|
@@ -1,538 +0,0 @@
|
|
|
1
|
-
import { describe, test, expect, beforeEach, afterEach } from 'vitest'
|
|
2
|
-
import {
|
|
3
|
-
Config,
|
|
4
|
-
DEFAULT_MODEL_VERSION,
|
|
5
|
-
DEFAULT_CLIENT,
|
|
6
|
-
DEFAULT_DATA_DIR,
|
|
7
|
-
} from './Config'
|
|
8
|
-
import { ClientType } from '../contracts/types/ClientType'
|
|
9
|
-
import path from 'path'
|
|
10
|
-
|
|
11
|
-
describe('Config', () => {
|
|
12
|
-
const originalEnv = process.env
|
|
13
|
-
|
|
14
|
-
beforeEach(() => {
|
|
15
|
-
process.env = { ...originalEnv }
|
|
16
|
-
})
|
|
17
|
-
|
|
18
|
-
afterEach(() => {
|
|
19
|
-
process.env = originalEnv
|
|
20
|
-
})
|
|
21
|
-
|
|
22
|
-
describe('dataDir', () => {
|
|
23
|
-
const projectRoot = '/test/project'
|
|
24
|
-
const projectDataDir = path.join(projectRoot, DEFAULT_DATA_DIR)
|
|
25
|
-
let config: Config
|
|
26
|
-
|
|
27
|
-
beforeEach(() => {
|
|
28
|
-
config = new Config({ projectRoot })
|
|
29
|
-
})
|
|
30
|
-
|
|
31
|
-
test('defaults to relative path when no projectRoot provided', () => {
|
|
32
|
-
const defaultConfig = new Config()
|
|
33
|
-
expect(defaultConfig.dataDir).toBe(DEFAULT_DATA_DIR)
|
|
34
|
-
})
|
|
35
|
-
|
|
36
|
-
test('uses projectRoot to construct absolute dataDir', () => {
|
|
37
|
-
expect(config.dataDir).toBe(projectDataDir)
|
|
38
|
-
})
|
|
39
|
-
|
|
40
|
-
test('testResultsFilePath returns test.json path within dataDir', () => {
|
|
41
|
-
expect(config.testResultsFilePath).toBe(
|
|
42
|
-
path.join(projectDataDir, 'test.json')
|
|
43
|
-
)
|
|
44
|
-
})
|
|
45
|
-
|
|
46
|
-
test('todosFilePath returns todos.json path within dataDir', () => {
|
|
47
|
-
expect(config.todosFilePath).toBe(path.join(projectDataDir, 'todos.json'))
|
|
48
|
-
})
|
|
49
|
-
|
|
50
|
-
test('modificationsFilePath returns modifications.json path within dataDir', () => {
|
|
51
|
-
expect(config.modificationsFilePath).toBe(
|
|
52
|
-
path.join(projectDataDir, 'modifications.json')
|
|
53
|
-
)
|
|
54
|
-
})
|
|
55
|
-
|
|
56
|
-
test('lintFilePath returns lint.json path within dataDir', () => {
|
|
57
|
-
expect(config.lintFilePath).toBe(path.join(projectDataDir, 'lint.json'))
|
|
58
|
-
})
|
|
59
|
-
|
|
60
|
-
test('configFilePath returns config.json path within dataDir', () => {
|
|
61
|
-
expect(config.configFilePath).toBe(
|
|
62
|
-
path.join(projectDataDir, 'config.json')
|
|
63
|
-
)
|
|
64
|
-
})
|
|
65
|
-
|
|
66
|
-
test('instructionsFilePath returns instructions.md path within dataDir', () => {
|
|
67
|
-
expect(config.instructionsFilePath).toBe(
|
|
68
|
-
path.join(projectDataDir, 'instructions.md')
|
|
69
|
-
)
|
|
70
|
-
})
|
|
71
|
-
|
|
72
|
-
describe('CLAUDE_PROJECT_DIR', () => {
|
|
73
|
-
let originalCwd: typeof process.cwd
|
|
74
|
-
|
|
75
|
-
beforeEach(() => {
|
|
76
|
-
originalCwd = process.cwd
|
|
77
|
-
})
|
|
78
|
-
|
|
79
|
-
afterEach(() => {
|
|
80
|
-
process.cwd = originalCwd
|
|
81
|
-
delete process.env.CLAUDE_PROJECT_DIR
|
|
82
|
-
})
|
|
83
|
-
|
|
84
|
-
test('uses CLAUDE_PROJECT_DIR when available and no projectRoot provided', () => {
|
|
85
|
-
const claudeProjectDir = '/claude/project/root'
|
|
86
|
-
process.env.CLAUDE_PROJECT_DIR = claudeProjectDir
|
|
87
|
-
process.cwd = () => '/claude/project/root/src'
|
|
88
|
-
|
|
89
|
-
const configWithClaudeDir = new Config()
|
|
90
|
-
|
|
91
|
-
expect(configWithClaudeDir.dataDir).toBe(
|
|
92
|
-
path.join(claudeProjectDir, DEFAULT_DATA_DIR)
|
|
93
|
-
)
|
|
94
|
-
})
|
|
95
|
-
|
|
96
|
-
test('projectRoot option takes precedence over CLAUDE_PROJECT_DIR', () => {
|
|
97
|
-
const claudeProjectDir = '/claude/project/root'
|
|
98
|
-
const explicitProjectRoot = '/explicit/project/root'
|
|
99
|
-
process.env.CLAUDE_PROJECT_DIR = claudeProjectDir
|
|
100
|
-
|
|
101
|
-
const configWithBoth = new Config({ projectRoot: explicitProjectRoot })
|
|
102
|
-
|
|
103
|
-
expect(configWithBoth.dataDir).toBe(
|
|
104
|
-
path.join(explicitProjectRoot, DEFAULT_DATA_DIR)
|
|
105
|
-
)
|
|
106
|
-
})
|
|
107
|
-
|
|
108
|
-
test('throws error when CLAUDE_PROJECT_DIR is not an absolute path', () => {
|
|
109
|
-
process.env.CLAUDE_PROJECT_DIR = 'relative/path'
|
|
110
|
-
|
|
111
|
-
expect(() => new Config()).toThrow(
|
|
112
|
-
'CLAUDE_PROJECT_DIR must be an absolute path'
|
|
113
|
-
)
|
|
114
|
-
})
|
|
115
|
-
|
|
116
|
-
test('throws error when cwd is outside CLAUDE_PROJECT_DIR', () => {
|
|
117
|
-
process.env.CLAUDE_PROJECT_DIR = '/project/root'
|
|
118
|
-
process.cwd = () => '/some/other/path'
|
|
119
|
-
|
|
120
|
-
expect(() => new Config()).toThrow(
|
|
121
|
-
'CLAUDE_PROJECT_DIR must contain the current working directory'
|
|
122
|
-
)
|
|
123
|
-
})
|
|
124
|
-
|
|
125
|
-
test('uses CLAUDE_PROJECT_DIR when cwd is deeply nested within it', () => {
|
|
126
|
-
process.env.CLAUDE_PROJECT_DIR = '/project/root'
|
|
127
|
-
process.cwd = () => '/project/root/src/nested/deeply'
|
|
128
|
-
|
|
129
|
-
const configWithNestedCwd = new Config()
|
|
130
|
-
|
|
131
|
-
expect(configWithNestedCwd.dataDir).toBe(
|
|
132
|
-
'/project/root/.claude/tdd-guard/data'
|
|
133
|
-
)
|
|
134
|
-
})
|
|
135
|
-
|
|
136
|
-
test('throws error when CLAUDE_PROJECT_DIR contains path traversal', () => {
|
|
137
|
-
process.env.CLAUDE_PROJECT_DIR = '/some/path/../../../other'
|
|
138
|
-
process.cwd = () => '/other/location'
|
|
139
|
-
|
|
140
|
-
expect(() => new Config()).toThrow(
|
|
141
|
-
'CLAUDE_PROJECT_DIR must not contain path traversal'
|
|
142
|
-
)
|
|
143
|
-
})
|
|
144
|
-
})
|
|
145
|
-
})
|
|
146
|
-
|
|
147
|
-
describe('useSystemClaude', () => {
|
|
148
|
-
test('can be set via options', () => {
|
|
149
|
-
const config = new Config({ useSystemClaude: true })
|
|
150
|
-
|
|
151
|
-
expect(config.useSystemClaude).toBe(true)
|
|
152
|
-
})
|
|
153
|
-
|
|
154
|
-
test('options take precedence over env var', () => {
|
|
155
|
-
process.env.USE_SYSTEM_CLAUDE = 'false'
|
|
156
|
-
|
|
157
|
-
const config = new Config({ useSystemClaude: true })
|
|
158
|
-
|
|
159
|
-
expect(config.useSystemClaude).toBe(true)
|
|
160
|
-
})
|
|
161
|
-
|
|
162
|
-
test('falls back to env var when not in options', () => {
|
|
163
|
-
process.env.USE_SYSTEM_CLAUDE = 'true'
|
|
164
|
-
|
|
165
|
-
const config = new Config({})
|
|
166
|
-
|
|
167
|
-
expect(config.useSystemClaude).toBe(true)
|
|
168
|
-
})
|
|
169
|
-
|
|
170
|
-
test('defaults to false when neither options nor env var are set', () => {
|
|
171
|
-
delete process.env.USE_SYSTEM_CLAUDE
|
|
172
|
-
|
|
173
|
-
const config = new Config()
|
|
174
|
-
|
|
175
|
-
expect(config.useSystemClaude).toBe(false)
|
|
176
|
-
})
|
|
177
|
-
|
|
178
|
-
test('returns false for non-true env values', () => {
|
|
179
|
-
// Test with 'false'
|
|
180
|
-
process.env.USE_SYSTEM_CLAUDE = 'false'
|
|
181
|
-
let config = new Config()
|
|
182
|
-
expect(config.useSystemClaude).toBe(false)
|
|
183
|
-
|
|
184
|
-
// Test with empty string
|
|
185
|
-
process.env.USE_SYSTEM_CLAUDE = ''
|
|
186
|
-
config = new Config()
|
|
187
|
-
expect(config.useSystemClaude).toBe(false)
|
|
188
|
-
})
|
|
189
|
-
})
|
|
190
|
-
|
|
191
|
-
describe('anthropicApiKey', () => {
|
|
192
|
-
test('can be set via options', () => {
|
|
193
|
-
const config = new Config({ anthropicApiKey: 'options-api-key' })
|
|
194
|
-
|
|
195
|
-
expect(config.anthropicApiKey).toBe('options-api-key')
|
|
196
|
-
})
|
|
197
|
-
|
|
198
|
-
test('options take precedence over env var', () => {
|
|
199
|
-
process.env.TDD_GUARD_ANTHROPIC_API_KEY = 'env-api-key'
|
|
200
|
-
|
|
201
|
-
const config = new Config({ anthropicApiKey: 'options-api-key' })
|
|
202
|
-
|
|
203
|
-
expect(config.anthropicApiKey).toBe('options-api-key')
|
|
204
|
-
})
|
|
205
|
-
|
|
206
|
-
test('falls back to env var when not in options', () => {
|
|
207
|
-
process.env.TDD_GUARD_ANTHROPIC_API_KEY = 'env-api-key'
|
|
208
|
-
|
|
209
|
-
const config = new Config()
|
|
210
|
-
|
|
211
|
-
expect(config.anthropicApiKey).toBe('env-api-key')
|
|
212
|
-
})
|
|
213
|
-
|
|
214
|
-
test('returns undefined when neither options nor env var are set', () => {
|
|
215
|
-
delete process.env.TDD_GUARD_ANTHROPIC_API_KEY
|
|
216
|
-
|
|
217
|
-
const config = new Config()
|
|
218
|
-
|
|
219
|
-
expect(config.anthropicApiKey).toBeUndefined()
|
|
220
|
-
})
|
|
221
|
-
})
|
|
222
|
-
|
|
223
|
-
describe('modelType', () => {
|
|
224
|
-
test('can be set via options', () => {
|
|
225
|
-
const config = new Config({ modelType: 'anthropic_api' })
|
|
226
|
-
|
|
227
|
-
expect(config.modelType).toBe('anthropic_api')
|
|
228
|
-
})
|
|
229
|
-
|
|
230
|
-
test('options take precedence over env vars', () => {
|
|
231
|
-
process.env.MODEL_TYPE = 'claude_cli'
|
|
232
|
-
|
|
233
|
-
const config = new Config({ modelType: 'anthropic_api' })
|
|
234
|
-
|
|
235
|
-
expect(config.modelType).toBe('anthropic_api')
|
|
236
|
-
})
|
|
237
|
-
|
|
238
|
-
test('options take precedence even in test mode with TEST_MODEL_TYPE', () => {
|
|
239
|
-
process.env.MODEL_TYPE = 'claude_cli'
|
|
240
|
-
process.env.TEST_MODEL_TYPE = 'test_model'
|
|
241
|
-
|
|
242
|
-
const config = new Config({ mode: 'test', modelType: 'anthropic_api' })
|
|
243
|
-
|
|
244
|
-
expect(config.modelType).toBe('anthropic_api')
|
|
245
|
-
})
|
|
246
|
-
|
|
247
|
-
test('falls back to MODEL_TYPE env var in production mode', () => {
|
|
248
|
-
process.env.MODEL_TYPE = 'anthropic_api'
|
|
249
|
-
|
|
250
|
-
const config = new Config()
|
|
251
|
-
|
|
252
|
-
expect(config.modelType).toBe('anthropic_api')
|
|
253
|
-
})
|
|
254
|
-
|
|
255
|
-
test('uses TEST_MODEL_TYPE in test mode when available', () => {
|
|
256
|
-
process.env.MODEL_TYPE = 'claude_cli'
|
|
257
|
-
process.env.TEST_MODEL_TYPE = 'anthropic_api'
|
|
258
|
-
|
|
259
|
-
const config = new Config({ mode: 'test' })
|
|
260
|
-
|
|
261
|
-
expect(config.modelType).toBe('anthropic_api')
|
|
262
|
-
})
|
|
263
|
-
|
|
264
|
-
test('falls back to MODEL_TYPE in test mode when TEST_MODEL_TYPE is not set', () => {
|
|
265
|
-
process.env.MODEL_TYPE = 'anthropic_api'
|
|
266
|
-
delete process.env.TEST_MODEL_TYPE
|
|
267
|
-
|
|
268
|
-
const config = new Config({ mode: 'test' })
|
|
269
|
-
|
|
270
|
-
expect(config.modelType).toBe('anthropic_api')
|
|
271
|
-
})
|
|
272
|
-
|
|
273
|
-
test('defaults to claude_cli when no env vars are set', () => {
|
|
274
|
-
delete process.env.MODEL_TYPE
|
|
275
|
-
delete process.env.TEST_MODEL_TYPE
|
|
276
|
-
|
|
277
|
-
const config = new Config()
|
|
278
|
-
|
|
279
|
-
expect(config.modelType).toBe('claude_cli')
|
|
280
|
-
})
|
|
281
|
-
})
|
|
282
|
-
|
|
283
|
-
describe('validationClient', () => {
|
|
284
|
-
test.each<ClientType>(['sdk', 'cli', 'api'])(
|
|
285
|
-
'returns %s when VALIDATION_CLIENT env var is set to %s',
|
|
286
|
-
(value) => {
|
|
287
|
-
process.env.VALIDATION_CLIENT = value
|
|
288
|
-
|
|
289
|
-
const config = new Config()
|
|
290
|
-
|
|
291
|
-
expect(config.validationClient).toBe(value)
|
|
292
|
-
}
|
|
293
|
-
)
|
|
294
|
-
|
|
295
|
-
describe('options.validationClient precedence', () => {
|
|
296
|
-
test.each([
|
|
297
|
-
{ env: 'VALIDATION_CLIENT', envValue: 'cli', optionValue: 'api' },
|
|
298
|
-
{ env: 'VALIDATION_CLIENT', envValue: 'sdk', optionValue: 'cli' },
|
|
299
|
-
{ env: 'MODEL_TYPE', envValue: 'anthropic_api', optionValue: 'sdk' },
|
|
300
|
-
{ env: 'MODEL_TYPE', envValue: 'claude_cli', optionValue: 'api' },
|
|
301
|
-
])(
|
|
302
|
-
'takes precedence over $env=$envValue (returns $optionValue)',
|
|
303
|
-
({ env, envValue, optionValue }) => {
|
|
304
|
-
process.env[env] = envValue
|
|
305
|
-
|
|
306
|
-
const config = new Config({
|
|
307
|
-
validationClient: optionValue as 'api' | 'cli' | 'sdk',
|
|
308
|
-
})
|
|
309
|
-
|
|
310
|
-
expect(config.validationClient).toBe(optionValue)
|
|
311
|
-
}
|
|
312
|
-
)
|
|
313
|
-
})
|
|
314
|
-
|
|
315
|
-
describe('case normalization', () => {
|
|
316
|
-
describe('VALIDATION_CLIENT', () => {
|
|
317
|
-
const testCases = [
|
|
318
|
-
['API', 'api'],
|
|
319
|
-
['Api', 'api'],
|
|
320
|
-
['api', 'api'],
|
|
321
|
-
['CLI', 'cli'],
|
|
322
|
-
['Cli', 'cli'],
|
|
323
|
-
['cli', 'cli'],
|
|
324
|
-
['SDK', 'sdk'],
|
|
325
|
-
['Sdk', 'sdk'],
|
|
326
|
-
['sdk', 'sdk'],
|
|
327
|
-
]
|
|
328
|
-
|
|
329
|
-
test.each(testCases)(
|
|
330
|
-
'normalizes env var %s to %s',
|
|
331
|
-
(input, expected) => {
|
|
332
|
-
process.env.VALIDATION_CLIENT = input
|
|
333
|
-
|
|
334
|
-
const config = new Config()
|
|
335
|
-
|
|
336
|
-
expect(config.validationClient).toBe(expected)
|
|
337
|
-
}
|
|
338
|
-
)
|
|
339
|
-
|
|
340
|
-
test.each(testCases)(
|
|
341
|
-
'normalizes option %s to %s',
|
|
342
|
-
(input, expected) => {
|
|
343
|
-
const config = new Config({
|
|
344
|
-
validationClient: input as ClientType,
|
|
345
|
-
})
|
|
346
|
-
|
|
347
|
-
expect(config.validationClient).toBe(expected)
|
|
348
|
-
}
|
|
349
|
-
)
|
|
350
|
-
})
|
|
351
|
-
|
|
352
|
-
describe('MODEL_TYPE (legacy)', () => {
|
|
353
|
-
const modelTypeCases = [
|
|
354
|
-
['ANTHROPIC_API', 'api'],
|
|
355
|
-
['Anthropic_Api', 'api'],
|
|
356
|
-
['anthropic_api', 'api'],
|
|
357
|
-
['CLAUDE_CLI', 'cli'],
|
|
358
|
-
['Claude_Cli', 'cli'],
|
|
359
|
-
['claude_cli', 'cli'],
|
|
360
|
-
]
|
|
361
|
-
|
|
362
|
-
test.each(modelTypeCases)(
|
|
363
|
-
'normalizes env var %s to %s when VALIDATION_CLIENT not set',
|
|
364
|
-
(modelType, expectedClient) => {
|
|
365
|
-
delete process.env.VALIDATION_CLIENT
|
|
366
|
-
process.env.MODEL_TYPE = modelType
|
|
367
|
-
|
|
368
|
-
const config = new Config()
|
|
369
|
-
|
|
370
|
-
expect(config.validationClient).toBe(expectedClient)
|
|
371
|
-
}
|
|
372
|
-
)
|
|
373
|
-
|
|
374
|
-
test.each(modelTypeCases)(
|
|
375
|
-
'normalizes option %s to %s when validationClient not set',
|
|
376
|
-
(modelType, expectedClient) => {
|
|
377
|
-
delete process.env.VALIDATION_CLIENT
|
|
378
|
-
delete process.env.MODEL_TYPE
|
|
379
|
-
|
|
380
|
-
const config = new Config({ modelType })
|
|
381
|
-
|
|
382
|
-
expect(config.validationClient).toBe(expectedClient)
|
|
383
|
-
}
|
|
384
|
-
)
|
|
385
|
-
})
|
|
386
|
-
})
|
|
387
|
-
|
|
388
|
-
test.each([
|
|
389
|
-
['anthropic_api', 'api'],
|
|
390
|
-
['claude_cli', 'cli'],
|
|
391
|
-
] as const)(
|
|
392
|
-
'uses %s from MODEL_TYPE=%s when VALIDATION_CLIENT not set',
|
|
393
|
-
(modelType, expectedClient) => {
|
|
394
|
-
delete process.env.VALIDATION_CLIENT
|
|
395
|
-
process.env.MODEL_TYPE = modelType
|
|
396
|
-
|
|
397
|
-
const config = new Config()
|
|
398
|
-
|
|
399
|
-
expect(config.validationClient).toBe(expectedClient)
|
|
400
|
-
}
|
|
401
|
-
)
|
|
402
|
-
|
|
403
|
-
test('uses api from options.modelType=anthropic_api when validationClient not set', () => {
|
|
404
|
-
delete process.env.VALIDATION_CLIENT
|
|
405
|
-
delete process.env.MODEL_TYPE
|
|
406
|
-
|
|
407
|
-
const config = new Config({ modelType: 'anthropic_api' })
|
|
408
|
-
|
|
409
|
-
expect(config.validationClient).toBe('api')
|
|
410
|
-
})
|
|
411
|
-
|
|
412
|
-
test('uses cli from options.modelType=claude_cli when validationClient not set', () => {
|
|
413
|
-
delete process.env.VALIDATION_CLIENT
|
|
414
|
-
delete process.env.MODEL_TYPE
|
|
415
|
-
|
|
416
|
-
const config = new Config({ modelType: 'claude_cli' })
|
|
417
|
-
|
|
418
|
-
expect(config.validationClient).toBe('cli')
|
|
419
|
-
})
|
|
420
|
-
|
|
421
|
-
test('uses DEFAULT_CLIENT when nothing is set', () => {
|
|
422
|
-
delete process.env.VALIDATION_CLIENT
|
|
423
|
-
delete process.env.MODEL_TYPE
|
|
424
|
-
|
|
425
|
-
const config = new Config()
|
|
426
|
-
|
|
427
|
-
expect(config.validationClient).toBe(DEFAULT_CLIENT)
|
|
428
|
-
})
|
|
429
|
-
})
|
|
430
|
-
|
|
431
|
-
describe('modelVersion', () => {
|
|
432
|
-
test('returns default model version when no configuration provided', () => {
|
|
433
|
-
const config = new Config()
|
|
434
|
-
|
|
435
|
-
expect(config.modelVersion).toBeDefined()
|
|
436
|
-
expect(config.modelVersion).toBe(DEFAULT_MODEL_VERSION)
|
|
437
|
-
})
|
|
438
|
-
|
|
439
|
-
test('can be set via options', () => {
|
|
440
|
-
const config = new Config({ modelVersion: 'claude-opus-4-1' })
|
|
441
|
-
|
|
442
|
-
expect(config.modelVersion).toBe('claude-opus-4-1')
|
|
443
|
-
})
|
|
444
|
-
|
|
445
|
-
test('options take precedence over env var', () => {
|
|
446
|
-
process.env.TDD_GUARD_MODEL_VERSION = 'claude-haiku-3-0'
|
|
447
|
-
|
|
448
|
-
const config = new Config({ modelVersion: 'claude-opus-4-1' })
|
|
449
|
-
|
|
450
|
-
expect(config.modelVersion).toBe('claude-opus-4-1')
|
|
451
|
-
})
|
|
452
|
-
|
|
453
|
-
test('falls back to env var when not in options', () => {
|
|
454
|
-
process.env.TDD_GUARD_MODEL_VERSION = 'claude-haiku-3-0'
|
|
455
|
-
|
|
456
|
-
const config = new Config()
|
|
457
|
-
|
|
458
|
-
expect(config.modelVersion).toBe('claude-haiku-3-0')
|
|
459
|
-
})
|
|
460
|
-
})
|
|
461
|
-
|
|
462
|
-
describe('linterType', () => {
|
|
463
|
-
test('returns undefined when no configuration provided', () => {
|
|
464
|
-
delete process.env.LINTER_TYPE
|
|
465
|
-
|
|
466
|
-
const config = new Config()
|
|
467
|
-
|
|
468
|
-
expect(config.linterType).toBeUndefined()
|
|
469
|
-
})
|
|
470
|
-
|
|
471
|
-
test('returns eslint when LINTER_TYPE env var is set to eslint', () => {
|
|
472
|
-
process.env.LINTER_TYPE = 'eslint'
|
|
473
|
-
|
|
474
|
-
const config = new Config()
|
|
475
|
-
|
|
476
|
-
expect(config.linterType).toBe('eslint')
|
|
477
|
-
})
|
|
478
|
-
|
|
479
|
-
test('returns golangci-lint when LINTER_TYPE env var is set to golangci-lint', () => {
|
|
480
|
-
process.env.LINTER_TYPE = 'golangci-lint'
|
|
481
|
-
|
|
482
|
-
const config = new Config()
|
|
483
|
-
|
|
484
|
-
expect(config.linterType).toBe('golangci-lint')
|
|
485
|
-
})
|
|
486
|
-
|
|
487
|
-
test('returns value from ConfigOptions when linterType is provided', () => {
|
|
488
|
-
const config = new Config({ linterType: 'eslint' })
|
|
489
|
-
|
|
490
|
-
expect(config.linterType).toBe('eslint')
|
|
491
|
-
})
|
|
492
|
-
|
|
493
|
-
test('returns golangci-lint from ConfigOptions when provided', () => {
|
|
494
|
-
const config = new Config({ linterType: 'golangci-lint' })
|
|
495
|
-
|
|
496
|
-
expect(config.linterType).toBe('golangci-lint')
|
|
497
|
-
})
|
|
498
|
-
|
|
499
|
-
test('ConfigOptions takes precedence over env var', () => {
|
|
500
|
-
process.env.LINTER_TYPE = 'pylint'
|
|
501
|
-
|
|
502
|
-
const config = new Config({ linterType: 'eslint' })
|
|
503
|
-
|
|
504
|
-
expect(config.linterType).toBe('eslint')
|
|
505
|
-
})
|
|
506
|
-
|
|
507
|
-
test('returns undefined for empty string env var', () => {
|
|
508
|
-
process.env.LINTER_TYPE = ''
|
|
509
|
-
|
|
510
|
-
const config = new Config()
|
|
511
|
-
|
|
512
|
-
expect(config.linterType).toBeUndefined()
|
|
513
|
-
})
|
|
514
|
-
|
|
515
|
-
test('returns future linter types when configured', () => {
|
|
516
|
-
// Test that the system is extensible for future linter types
|
|
517
|
-
process.env.LINTER_TYPE = 'pylint'
|
|
518
|
-
|
|
519
|
-
const config = new Config()
|
|
520
|
-
|
|
521
|
-
expect(config.linterType).toBe('pylint')
|
|
522
|
-
})
|
|
523
|
-
|
|
524
|
-
test('returns linterType in lowercase when env var is uppercase', () => {
|
|
525
|
-
process.env.LINTER_TYPE = 'ESLINT'
|
|
526
|
-
|
|
527
|
-
const config = new Config()
|
|
528
|
-
|
|
529
|
-
expect(config.linterType).toBe('eslint')
|
|
530
|
-
})
|
|
531
|
-
|
|
532
|
-
test('returns linterType in lowercase when ConfigOptions is uppercase', () => {
|
|
533
|
-
const config = new Config({ linterType: 'ESLINT' })
|
|
534
|
-
|
|
535
|
-
expect(config.linterType).toBe('eslint')
|
|
536
|
-
})
|
|
537
|
-
})
|
|
538
|
-
})
|
|
@@ -1,172 +0,0 @@
|
|
|
1
|
-
import path from 'path'
|
|
2
|
-
import { ConfigOptions } from '../contracts/types/ConfigOptions'
|
|
3
|
-
import { ClientType } from '../contracts/types/ClientType'
|
|
4
|
-
|
|
5
|
-
const TEST_RESULTS_FILENAME = 'test.json'
|
|
6
|
-
const TODOS_FILENAME = 'todos.json'
|
|
7
|
-
const MODIFICATIONS_FILENAME = 'modifications.json'
|
|
8
|
-
const LINT_FILENAME = 'lint.json'
|
|
9
|
-
const CONFIG_FILENAME = 'config.json'
|
|
10
|
-
const INSTRUCTIONS_FILENAME = 'instructions.md'
|
|
11
|
-
|
|
12
|
-
export const DEFAULT_MODEL_VERSION = 'claude-sonnet-4-0'
|
|
13
|
-
export const DEFAULT_CLIENT: ClientType = 'sdk'
|
|
14
|
-
export const DEFAULT_DATA_DIR = path.join('.claude', 'tdd-guard', 'data')
|
|
15
|
-
|
|
16
|
-
const VALID_CLIENTS = new Set<string>(['api', 'cli', 'sdk'])
|
|
17
|
-
const MODEL_TYPE_TO_CLIENT: Record<string, ClientType> = {
|
|
18
|
-
anthropic_api: 'api',
|
|
19
|
-
claude_cli: 'cli',
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
export class Config {
|
|
23
|
-
readonly dataDir: string
|
|
24
|
-
readonly useSystemClaude: boolean
|
|
25
|
-
readonly anthropicApiKey: string | undefined
|
|
26
|
-
readonly modelType: string
|
|
27
|
-
readonly linterType: string | undefined
|
|
28
|
-
readonly modelVersion: string
|
|
29
|
-
readonly validationClient: ClientType
|
|
30
|
-
|
|
31
|
-
constructor(options?: ConfigOptions) {
|
|
32
|
-
const mode = options?.mode ?? 'production'
|
|
33
|
-
|
|
34
|
-
this.dataDir = this.getDataDir(options)
|
|
35
|
-
this.useSystemClaude = this.getUseSystemClaude(options)
|
|
36
|
-
this.anthropicApiKey = this.getAnthropicApiKey(options)
|
|
37
|
-
this.modelType = this.getModelType(options, mode)
|
|
38
|
-
this.linterType = this.getLinterType(options)
|
|
39
|
-
this.modelVersion = this.getModelVersion(options)
|
|
40
|
-
this.validationClient = this.getValidationClient(options)
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
private getDataDir(options?: ConfigOptions): string {
|
|
44
|
-
// Determine the base directory
|
|
45
|
-
const baseDir = options?.projectRoot ?? this.getValidatedClaudeProjectDir()
|
|
46
|
-
|
|
47
|
-
// If we have a base directory, construct the full path
|
|
48
|
-
if (baseDir) {
|
|
49
|
-
return path.join(baseDir, DEFAULT_DATA_DIR)
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
// Default to relative path
|
|
53
|
-
return DEFAULT_DATA_DIR
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
private getUseSystemClaude(options?: ConfigOptions): boolean {
|
|
57
|
-
return options?.useSystemClaude ?? process.env.USE_SYSTEM_CLAUDE === 'true'
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
private getAnthropicApiKey(options?: ConfigOptions): string | undefined {
|
|
61
|
-
return options?.anthropicApiKey ?? process.env.TDD_GUARD_ANTHROPIC_API_KEY
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
private getModelType(
|
|
65
|
-
options: ConfigOptions | undefined,
|
|
66
|
-
mode: string
|
|
67
|
-
): string {
|
|
68
|
-
return (
|
|
69
|
-
options?.modelType ?? this.getEnvironmentModelType(mode) ?? 'claude_cli'
|
|
70
|
-
)
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
private getEnvironmentModelType(mode: string): string | undefined {
|
|
74
|
-
if (mode === 'test' && process.env.TEST_MODEL_TYPE) {
|
|
75
|
-
return process.env.TEST_MODEL_TYPE
|
|
76
|
-
}
|
|
77
|
-
return process.env.MODEL_TYPE
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
get testResultsFilePath(): string {
|
|
81
|
-
return path.join(this.dataDir, TEST_RESULTS_FILENAME)
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
get todosFilePath(): string {
|
|
85
|
-
return path.join(this.dataDir, TODOS_FILENAME)
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
get modificationsFilePath(): string {
|
|
89
|
-
return path.join(this.dataDir, MODIFICATIONS_FILENAME)
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
get lintFilePath(): string {
|
|
93
|
-
return path.join(this.dataDir, LINT_FILENAME)
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
get configFilePath(): string {
|
|
97
|
-
return path.join(this.dataDir, CONFIG_FILENAME)
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
get instructionsFilePath(): string {
|
|
101
|
-
return path.join(this.dataDir, INSTRUCTIONS_FILENAME)
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
private getLinterType(options?: ConfigOptions): string | undefined {
|
|
105
|
-
if (options && 'linterType' in options) {
|
|
106
|
-
return options.linterType?.toLowerCase()
|
|
107
|
-
}
|
|
108
|
-
const envValue = process.env.LINTER_TYPE?.toLowerCase()
|
|
109
|
-
return envValue && envValue.trim() !== '' ? envValue : undefined
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
private getModelVersion(options?: ConfigOptions): string {
|
|
113
|
-
return (
|
|
114
|
-
options?.modelVersion ??
|
|
115
|
-
process.env.TDD_GUARD_MODEL_VERSION ??
|
|
116
|
-
DEFAULT_MODEL_VERSION
|
|
117
|
-
)
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
private getValidationClient(options?: ConfigOptions): ClientType {
|
|
121
|
-
return (
|
|
122
|
-
getClientType(options) ?? getLegacyClientType(options) ?? DEFAULT_CLIENT
|
|
123
|
-
)
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
private getValidatedClaudeProjectDir(): string | null {
|
|
127
|
-
const projectDir = process.env.CLAUDE_PROJECT_DIR
|
|
128
|
-
if (!projectDir) {
|
|
129
|
-
return null
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
// Validate that CLAUDE_PROJECT_DIR is an absolute path
|
|
133
|
-
if (!path.isAbsolute(projectDir)) {
|
|
134
|
-
throw new Error('CLAUDE_PROJECT_DIR must be an absolute path')
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
// Validate that CLAUDE_PROJECT_DIR does not contain path traversal
|
|
138
|
-
if (projectDir.includes('..')) {
|
|
139
|
-
throw new Error('CLAUDE_PROJECT_DIR must not contain path traversal')
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
// Validate that current working directory is within CLAUDE_PROJECT_DIR
|
|
143
|
-
const cwd = process.cwd()
|
|
144
|
-
if (!cwd.startsWith(projectDir)) {
|
|
145
|
-
throw new Error(
|
|
146
|
-
'CLAUDE_PROJECT_DIR must contain the current working directory'
|
|
147
|
-
)
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
return projectDir
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
function getClientType(options?: ConfigOptions): ClientType | undefined {
|
|
155
|
-
const directValue = options?.validationClient ?? process.env.VALIDATION_CLIENT
|
|
156
|
-
const normalizedValue = directValue?.toLowerCase()
|
|
157
|
-
return isValidClient(normalizedValue) ? normalizedValue : undefined
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
function getLegacyClientType(options?: ConfigOptions): ClientType | undefined {
|
|
161
|
-
const modelType = options?.modelType ?? process.env.MODEL_TYPE
|
|
162
|
-
return mapModelTypeToClient(modelType)
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
function isValidClient(value?: string): value is ClientType {
|
|
166
|
-
return VALID_CLIENTS.has(value ?? '')
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
function mapModelTypeToClient(modelType?: string): ClientType | undefined {
|
|
170
|
-
const normalizedType = modelType?.toLowerCase()
|
|
171
|
-
return normalizedType ? MODEL_TYPE_TO_CLIENT[normalizedType] : undefined
|
|
172
|
-
}
|