aigroup-workflow 2.2.0 → 2.2.2
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/.claude/commands/fix-build.md +10 -5
- package/.claude/commands/init-project.md +13 -8
- package/.claude/commands/plan.md +15 -8
- package/.claude/commands/review.md +12 -6
- package/.claude/commands/tdd.md +11 -5
- package/.claude/commands/workflow-start.md +20 -11
- package/.claude/settings.json +28 -0
- package/.codex/agents/architect.toml +207 -0
- package/.codex/agents/build-error-resolver.toml +110 -0
- package/.codex/agents/code-reviewer.toml +233 -0
- package/.codex/agents/doc-updater.toml +103 -0
- package/.codex/agents/e2e-runner.toml +103 -0
- package/.codex/agents/get-current-datetime.toml +23 -0
- package/.codex/agents/init-architect.toml +181 -0
- package/.codex/agents/planner.toml +208 -0
- package/.codex/agents/refactor-cleaner.toml +81 -0
- package/.codex/agents/rust-reviewer.toml +90 -0
- package/.codex/agents/security-reviewer.toml +104 -0
- package/.codex/agents/tdd-guide.toml +87 -0
- package/AGENTS.md +2 -2
- package/CLAUDE.md +23 -1
- package/LICENSE +20 -20
- package/README.md +333 -333
- package/agents/a11y-architect.md +141 -141
- package/agents/architect.md +211 -211
- package/agents/build-error-resolver.md +114 -114
- package/agents/chief-of-staff.md +151 -151
- package/agents/code-architect.md +71 -71
- package/agents/code-explorer.md +69 -69
- package/agents/code-reviewer.md +237 -237
- package/agents/code-simplifier.md +47 -47
- package/agents/comment-analyzer.md +45 -45
- package/agents/conversation-analyzer.md +52 -52
- package/agents/cpp-build-resolver.md +90 -90
- package/agents/cpp-reviewer.md +72 -72
- package/agents/csharp-reviewer.md +101 -101
- package/agents/dart-build-resolver.md +201 -201
- package/agents/database-reviewer.md +91 -91
- package/agents/doc-updater.md +107 -107
- package/agents/docs-lookup.md +68 -68
- package/agents/e2e-runner.md +107 -107
- package/agents/flutter-reviewer.md +243 -243
- package/agents/gan-evaluator.md +209 -209
- package/agents/gan-generator.md +131 -131
- package/agents/gan-planner.md +99 -99
- package/agents/get-current-datetime.md +26 -26
- package/agents/go-build-resolver.md +94 -94
- package/agents/go-reviewer.md +76 -76
- package/agents/harness-optimizer.md +35 -35
- package/agents/healthcare-reviewer.md +83 -83
- package/agents/java-build-resolver.md +153 -153
- package/agents/java-reviewer.md +92 -92
- package/agents/kotlin-build-resolver.md +118 -118
- package/agents/kotlin-reviewer.md +159 -159
- package/agents/loop-operator.md +36 -36
- package/agents/opensource-forker.md +198 -198
- package/agents/opensource-packager.md +249 -249
- package/agents/opensource-sanitizer.md +188 -188
- package/agents/performance-optimizer.md +446 -446
- package/agents/planner.md +212 -212
- package/agents/pr-test-analyzer.md +45 -45
- package/agents/python-reviewer.md +98 -98
- package/agents/pytorch-build-resolver.md +120 -120
- package/agents/refactor-cleaner.md +85 -85
- package/agents/rust-build-resolver.md +148 -148
- package/agents/rust-reviewer.md +94 -94
- package/agents/security-reviewer.md +108 -108
- package/agents/seo-specialist.md +59 -59
- package/agents/silent-failure-hunter.md +50 -50
- package/agents/tdd-guide.md +91 -91
- package/agents/type-design-analyzer.md +41 -41
- package/agents/typescript-reviewer.md +112 -112
- package/cli/commands/update.mjs +1 -1
- package/cli/utils/scaffold.mjs +53 -0
- package/docs/rules/agents.md +166 -50
- package/docs/rules/cpp/coding-style.md +44 -44
- package/docs/rules/cpp/hooks.md +39 -39
- package/docs/rules/cpp/patterns.md +51 -51
- package/docs/rules/cpp/security.md +51 -51
- package/docs/rules/cpp/testing.md +44 -44
- package/docs/rules/csharp/coding-style.md +72 -72
- package/docs/rules/csharp/hooks.md +25 -25
- package/docs/rules/csharp/patterns.md +50 -50
- package/docs/rules/csharp/security.md +58 -58
- package/docs/rules/csharp/testing.md +46 -46
- package/docs/rules/dart/coding-style.md +159 -159
- package/docs/rules/dart/hooks.md +66 -66
- package/docs/rules/dart/patterns.md +261 -261
- package/docs/rules/dart/security.md +135 -135
- package/docs/rules/dart/testing.md +215 -215
- package/docs/rules/golang/coding-style.md +32 -32
- package/docs/rules/golang/hooks.md +17 -17
- package/docs/rules/golang/patterns.md +45 -45
- package/docs/rules/golang/security.md +34 -34
- package/docs/rules/golang/testing.md +31 -31
- package/docs/rules/java/coding-style.md +114 -114
- package/docs/rules/java/hooks.md +18 -18
- package/docs/rules/java/patterns.md +146 -146
- package/docs/rules/java/security.md +100 -100
- package/docs/rules/java/testing.md +131 -131
- package/docs/rules/kotlin/coding-style.md +86 -86
- package/docs/rules/kotlin/hooks.md +17 -17
- package/docs/rules/kotlin/patterns.md +146 -146
- package/docs/rules/kotlin/security.md +82 -82
- package/docs/rules/kotlin/testing.md +128 -128
- package/docs/rules/perl/coding-style.md +46 -46
- package/docs/rules/perl/hooks.md +22 -22
- package/docs/rules/perl/patterns.md +76 -76
- package/docs/rules/perl/security.md +69 -69
- package/docs/rules/perl/testing.md +54 -54
- package/docs/rules/php/coding-style.md +40 -40
- package/docs/rules/php/hooks.md +24 -24
- package/docs/rules/php/patterns.md +33 -33
- package/docs/rules/php/security.md +37 -37
- package/docs/rules/php/testing.md +39 -39
- package/docs/rules/python/coding-style.md +42 -42
- package/docs/rules/python/hooks.md +19 -19
- package/docs/rules/python/patterns.md +39 -39
- package/docs/rules/python/security.md +30 -30
- package/docs/rules/python/testing.md +38 -38
- package/docs/rules/rust/coding-style.md +151 -151
- package/docs/rules/rust/hooks.md +16 -16
- package/docs/rules/rust/patterns.md +168 -168
- package/docs/rules/rust/security.md +141 -141
- package/docs/rules/rust/testing.md +154 -154
- package/docs/rules/swift/coding-style.md +47 -47
- package/docs/rules/swift/hooks.md +20 -20
- package/docs/rules/swift/patterns.md +66 -66
- package/docs/rules/swift/security.md +33 -33
- package/docs/rules/swift/testing.md +45 -45
- package/docs/rules/typescript/coding-style.md +199 -199
- package/docs/rules/typescript/hooks.md +22 -22
- package/docs/rules/typescript/patterns.md +52 -52
- package/docs/rules/typescript/security.md +28 -28
- package/docs/rules/typescript/testing.md +18 -18
- package/docs/rules/web/coding-style.md +96 -96
- package/docs/rules/web/design-quality.md +62 -62
- package/docs/rules/web/hooks.md +120 -120
- package/docs/rules/web/patterns.md +79 -79
- package/docs/rules/web/performance.md +64 -64
- package/docs/rules/web/security.md +57 -57
- package/docs/rules/web/testing.md +55 -55
- package/docs/templates/README.md +36 -36
- package/docs/templates/ai-project-final.md +124 -124
- package/docs/templates/ai-project.md +105 -105
- package/docs/templates/api.md +157 -157
- package/docs/templates/bug.md +62 -62
- package/docs/templates/code-review.md +87 -87
- package/docs/templates/generic.md +116 -116
- package/docs/templates/implementation-plan.md +1 -1
- package/docs/templates/meeting.md +68 -68
- package/docs/templates/prd.md +98 -98
- package/docs/templates/ui.md +134 -134
- package/docs/workflow-pipeline.md +11 -10
- package/package.json +40 -39
- package/scripts/hooks/checks/orchestration-artifacts.cjs +28 -23
- package/scripts/hooks/checks/workflow-state.cjs +4 -5
- package/scripts/orchestration/lib/orchestrator.cjs +344 -117
- package/scripts/orchestration/lib/validate.cjs +145 -0
- package/scripts/orchestration/session.cjs +88 -44
- package/skills/SUPERPOWERS-LICENSE +21 -21
- package/skills/ai-ml/fine-tuning-expert/SKILL.md +162 -162
- package/skills/ai-ml/fine-tuning-expert/references/dataset-preparation.md +540 -540
- package/skills/ai-ml/fine-tuning-expert/references/deployment-optimization.md +673 -673
- package/skills/ai-ml/fine-tuning-expert/references/evaluation-metrics.md +597 -597
- package/skills/ai-ml/fine-tuning-expert/references/hyperparameter-tuning.md +565 -565
- package/skills/ai-ml/fine-tuning-expert/references/lora-peft.md +347 -347
- package/skills/ai-ml/ml-pipeline/SKILL.md +159 -159
- package/skills/ai-ml/ml-pipeline/references/experiment-tracking.md +833 -833
- package/skills/ai-ml/ml-pipeline/references/feature-engineering.md +631 -631
- package/skills/ai-ml/ml-pipeline/references/model-validation.md +978 -978
- package/skills/ai-ml/ml-pipeline/references/pipeline-orchestration.md +907 -907
- package/skills/ai-ml/ml-pipeline/references/training-pipelines.md +782 -782
- package/skills/ai-ml/rag-architect/SKILL.md +194 -194
- package/skills/ai-ml/rag-architect/references/chunking-strategies.md +878 -878
- package/skills/ai-ml/rag-architect/references/embedding-models.md +561 -561
- package/skills/ai-ml/rag-architect/references/rag-evaluation.md +833 -833
- package/skills/ai-ml/rag-architect/references/retrieval-optimization.md +795 -795
- package/skills/ai-ml/rag-architect/references/vector-databases.md +589 -589
- package/skills/ai-ml/spark-engineer/SKILL.md +148 -148
- package/skills/ai-ml/spark-engineer/references/partitioning-caching.md +543 -543
- package/skills/ai-ml/spark-engineer/references/performance-tuning.md +544 -544
- package/skills/ai-ml/spark-engineer/references/rdd-operations.md +599 -599
- package/skills/ai-ml/spark-engineer/references/spark-sql-dataframes.md +474 -474
- package/skills/ai-ml/spark-engineer/references/streaming-patterns.md +786 -786
- package/skills/backend/api-designer/SKILL.md +217 -217
- package/skills/backend/api-designer/references/error-handling.md +541 -541
- package/skills/backend/api-designer/references/openapi.md +824 -824
- package/skills/backend/api-designer/references/pagination.md +494 -494
- package/skills/backend/api-designer/references/rest-patterns.md +335 -335
- package/skills/backend/api-designer/references/versioning.md +391 -391
- package/skills/backend/architecture-designer/SKILL.md +117 -117
- package/skills/backend/architecture-designer/references/adr-template.md +116 -116
- package/skills/backend/architecture-designer/references/architecture-patterns.md +111 -111
- package/skills/backend/architecture-designer/references/database-selection.md +102 -102
- package/skills/backend/architecture-designer/references/nfr-checklist.md +112 -112
- package/skills/backend/architecture-designer/references/system-design.md +100 -100
- package/skills/backend/code-documenter/SKILL.md +147 -147
- package/skills/backend/code-documenter/references/api-docs-fastapi-django.md +166 -166
- package/skills/backend/code-documenter/references/api-docs-nestjs-express.md +220 -220
- package/skills/backend/code-documenter/references/coverage-reports.md +125 -125
- package/skills/backend/code-documenter/references/documentation-systems.md +333 -333
- package/skills/backend/code-documenter/references/interactive-api-docs.md +531 -531
- package/skills/backend/code-documenter/references/python-docstrings.md +121 -121
- package/skills/backend/code-documenter/references/typescript-jsdoc.md +145 -145
- package/skills/backend/code-documenter/references/user-guides-tutorials.md +530 -530
- package/skills/backend/debugging-wizard/SKILL.md +105 -105
- package/skills/backend/debugging-wizard/references/common-patterns.md +132 -132
- package/skills/backend/debugging-wizard/references/debugging-tools.md +140 -140
- package/skills/backend/debugging-wizard/references/quick-fixes.md +177 -177
- package/skills/backend/debugging-wizard/references/strategies.md +142 -142
- package/skills/backend/debugging-wizard/references/systematic-debugging.md +367 -367
- package/skills/backend/feature-forge/SKILL.md +98 -98
- package/skills/backend/feature-forge/references/acceptance-criteria.md +104 -104
- package/skills/backend/feature-forge/references/ears-syntax.md +99 -99
- package/skills/backend/feature-forge/references/interview-questions.md +150 -150
- package/skills/backend/feature-forge/references/pre-discovery-subagents.md +54 -54
- package/skills/backend/feature-forge/references/specification-template.md +103 -103
- package/skills/backend/fullstack-guardian/SKILL.md +105 -105
- package/skills/backend/fullstack-guardian/references/api-design-standards.md +307 -307
- package/skills/backend/fullstack-guardian/references/architecture-decisions.md +350 -350
- package/skills/backend/fullstack-guardian/references/backend-patterns.md +237 -237
- package/skills/backend/fullstack-guardian/references/common-patterns.md +134 -134
- package/skills/backend/fullstack-guardian/references/deliverables-checklist.md +354 -354
- package/skills/backend/fullstack-guardian/references/design-template.md +91 -91
- package/skills/backend/fullstack-guardian/references/error-handling.md +135 -135
- package/skills/backend/fullstack-guardian/references/frontend-patterns.md +340 -340
- package/skills/backend/fullstack-guardian/references/integration-patterns.md +333 -333
- package/skills/backend/fullstack-guardian/references/security-checklist.md +106 -106
- package/skills/backend/graphql-architect/SKILL.md +146 -146
- package/skills/backend/graphql-architect/references/federation.md +418 -418
- package/skills/backend/graphql-architect/references/migration-from-rest.md +1141 -1141
- package/skills/backend/graphql-architect/references/resolvers.md +425 -425
- package/skills/backend/graphql-architect/references/schema-design.md +393 -393
- package/skills/backend/graphql-architect/references/security.md +569 -569
- package/skills/backend/graphql-architect/references/subscriptions.md +510 -510
- package/skills/backend/legacy-modernizer/SKILL.md +137 -137
- package/skills/backend/legacy-modernizer/references/legacy-testing.md +381 -381
- package/skills/backend/legacy-modernizer/references/migration-strategies.md +423 -423
- package/skills/backend/legacy-modernizer/references/refactoring-patterns.md +395 -395
- package/skills/backend/legacy-modernizer/references/strangler-fig-pattern.md +281 -281
- package/skills/backend/legacy-modernizer/references/system-assessment.md +487 -487
- package/skills/backend/microservices-architect/SKILL.md +164 -164
- package/skills/backend/microservices-architect/references/communication.md +499 -499
- package/skills/backend/microservices-architect/references/data.md +721 -721
- package/skills/backend/microservices-architect/references/decomposition.md +344 -344
- package/skills/backend/microservices-architect/references/observability.md +805 -805
- package/skills/backend/microservices-architect/references/patterns.md +603 -603
- package/skills/database/database-optimizer/SKILL.md +147 -147
- package/skills/database/database-optimizer/references/index-strategies.md +331 -331
- package/skills/database/database-optimizer/references/monitoring-analysis.md +501 -501
- package/skills/database/database-optimizer/references/mysql-tuning.md +452 -452
- package/skills/database/database-optimizer/references/postgresql-tuning.md +413 -413
- package/skills/database/database-optimizer/references/query-optimization.md +251 -251
- package/skills/database/postgres-pro/SKILL.md +152 -152
- package/skills/database/postgres-pro/references/extensions.md +404 -404
- package/skills/database/postgres-pro/references/jsonb.md +321 -321
- package/skills/database/postgres-pro/references/maintenance.md +481 -481
- package/skills/database/postgres-pro/references/performance.md +265 -265
- package/skills/database/postgres-pro/references/replication.md +446 -446
- package/skills/database/sql-pro/SKILL.md +129 -129
- package/skills/database/sql-pro/references/database-design.md +402 -402
- package/skills/database/sql-pro/references/dialect-differences.md +419 -419
- package/skills/database/sql-pro/references/optimization.md +384 -384
- package/skills/database/sql-pro/references/query-patterns.md +285 -285
- package/skills/database/sql-pro/references/window-functions.md +328 -328
- package/skills/dotnet/csharp-developer/SKILL.md +125 -125
- package/skills/dotnet/csharp-developer/references/aspnet-core.md +394 -394
- package/skills/dotnet/csharp-developer/references/blazor.md +553 -553
- package/skills/dotnet/csharp-developer/references/entity-framework.md +409 -409
- package/skills/dotnet/csharp-developer/references/modern-csharp.md +248 -248
- package/skills/dotnet/csharp-developer/references/performance.md +498 -498
- package/skills/dotnet/dotnet-core-expert/SKILL.md +138 -138
- package/skills/dotnet/dotnet-core-expert/references/authentication.md +546 -546
- package/skills/dotnet/dotnet-core-expert/references/clean-architecture.md +455 -455
- package/skills/dotnet/dotnet-core-expert/references/cloud-native.md +548 -548
- package/skills/dotnet/dotnet-core-expert/references/entity-framework.md +440 -440
- package/skills/dotnet/dotnet-core-expert/references/minimal-apis.md +319 -319
- package/skills/frontend/angular-architect/SKILL.md +152 -152
- package/skills/frontend/angular-architect/references/components.md +297 -297
- package/skills/frontend/angular-architect/references/ngrx.md +401 -401
- package/skills/frontend/angular-architect/references/routing.md +361 -361
- package/skills/frontend/angular-architect/references/rxjs.md +319 -319
- package/skills/frontend/angular-architect/references/testing.md +405 -405
- package/skills/frontend/design-commands/design.md +91 -91
- package/skills/frontend/design-commands/handoff.md +97 -97
- package/skills/frontend/design-commands/prototype.md +120 -120
- package/skills/frontend/design-commands/spec.md +160 -160
- package/skills/frontend/design-commands/style.md +78 -78
- package/skills/frontend/flutter-expert/SKILL.md +138 -138
- package/skills/frontend/flutter-expert/references/bloc-state.md +259 -259
- package/skills/frontend/flutter-expert/references/gorouter-navigation.md +119 -119
- package/skills/frontend/flutter-expert/references/performance.md +99 -99
- package/skills/frontend/flutter-expert/references/project-structure.md +118 -118
- package/skills/frontend/flutter-expert/references/riverpod-state.md +130 -130
- package/skills/frontend/flutter-expert/references/widget-patterns.md +123 -123
- package/skills/frontend/nextjs-developer/SKILL.md +143 -143
- package/skills/frontend/nextjs-developer/references/app-router.md +311 -311
- package/skills/frontend/nextjs-developer/references/data-fetching.md +482 -482
- package/skills/frontend/nextjs-developer/references/deployment.md +545 -545
- package/skills/frontend/nextjs-developer/references/server-actions.md +462 -462
- package/skills/frontend/nextjs-developer/references/server-components.md +384 -384
- package/skills/frontend/react-expert/SKILL.md +149 -149
- package/skills/frontend/react-expert/references/hooks-patterns.md +162 -162
- package/skills/frontend/react-expert/references/migration-class-to-modern.md +1119 -1119
- package/skills/frontend/react-expert/references/performance.md +168 -168
- package/skills/frontend/react-expert/references/react-19-features.md +174 -174
- package/skills/frontend/react-expert/references/server-components.md +143 -143
- package/skills/frontend/react-expert/references/state-management.md +171 -171
- package/skills/frontend/react-expert/references/testing-react.md +174 -174
- package/skills/frontend/react-native-expert/SKILL.md +185 -185
- package/skills/frontend/react-native-expert/references/expo-router.md +187 -187
- package/skills/frontend/react-native-expert/references/list-optimization.md +204 -204
- package/skills/frontend/react-native-expert/references/platform-handling.md +188 -188
- package/skills/frontend/react-native-expert/references/project-structure.md +171 -171
- package/skills/frontend/react-native-expert/references/storage-hooks.md +173 -173
- package/skills/frontend/senior-frontend/SKILL.md +477 -477
- package/skills/frontend/senior-frontend/references/frontend_best_practices.md +806 -806
- package/skills/frontend/senior-frontend/references/nextjs_optimization_guide.md +724 -724
- package/skills/frontend/senior-frontend/references/react_patterns.md +746 -746
- package/skills/frontend/senior-frontend/scripts/bundle_analyzer.py +407 -407
- package/skills/frontend/senior-frontend/scripts/component_generator.py +329 -329
- package/skills/frontend/senior-frontend/scripts/frontend_scaffolder.py +1005 -1005
- package/skills/frontend/ui-ux-pro-max/SKILL.md +386 -386
- package/skills/frontend/ui-ux-pro-max/data/charts.csv +26 -26
- package/skills/frontend/ui-ux-pro-max/data/colors.csv +97 -97
- package/skills/frontend/ui-ux-pro-max/data/icons.csv +101 -101
- package/skills/frontend/ui-ux-pro-max/data/landing.csv +31 -31
- package/skills/frontend/ui-ux-pro-max/data/products.csv +96 -96
- package/skills/frontend/ui-ux-pro-max/data/react-performance.csv +45 -45
- package/skills/frontend/ui-ux-pro-max/data/stacks/astro.csv +54 -54
- package/skills/frontend/ui-ux-pro-max/data/stacks/flutter.csv +53 -53
- package/skills/frontend/ui-ux-pro-max/data/stacks/html-tailwind.csv +56 -56
- package/skills/frontend/ui-ux-pro-max/data/stacks/jetpack-compose.csv +53 -53
- package/skills/frontend/ui-ux-pro-max/data/stacks/nextjs.csv +53 -53
- package/skills/frontend/ui-ux-pro-max/data/stacks/nuxt-ui.csv +51 -51
- package/skills/frontend/ui-ux-pro-max/data/stacks/nuxtjs.csv +59 -59
- package/skills/frontend/ui-ux-pro-max/data/stacks/react-native.csv +52 -52
- package/skills/frontend/ui-ux-pro-max/data/stacks/react.csv +54 -54
- package/skills/frontend/ui-ux-pro-max/data/stacks/shadcn.csv +61 -61
- package/skills/frontend/ui-ux-pro-max/data/stacks/svelte.csv +54 -54
- package/skills/frontend/ui-ux-pro-max/data/stacks/swiftui.csv +51 -51
- package/skills/frontend/ui-ux-pro-max/data/stacks/vue.csv +50 -50
- package/skills/frontend/ui-ux-pro-max/data/styles.csv +68 -68
- package/skills/frontend/ui-ux-pro-max/data/typography.csv +57 -57
- package/skills/frontend/ui-ux-pro-max/data/ui-reasoning.csv +101 -101
- package/skills/frontend/ui-ux-pro-max/data/ux-guidelines.csv +99 -99
- package/skills/frontend/ui-ux-pro-max/data/web-interface.csv +31 -31
- package/skills/frontend/ui-ux-pro-max/scripts/core.py +253 -253
- package/skills/frontend/ui-ux-pro-max/scripts/design_system.py +1067 -1067
- package/skills/frontend/ui-ux-pro-max/scripts/search.py +114 -114
- package/skills/frontend/vue-expert/SKILL.md +98 -98
- package/skills/frontend/vue-expert/references/build-tooling.md +480 -480
- package/skills/frontend/vue-expert/references/components.md +448 -448
- package/skills/frontend/vue-expert/references/composition-api.md +299 -299
- package/skills/frontend/vue-expert/references/mobile-hybrid.md +636 -636
- package/skills/frontend/vue-expert/references/nuxt.md +669 -669
- package/skills/frontend/vue-expert/references/state-management.md +449 -449
- package/skills/frontend/vue-expert/references/typescript.md +584 -584
- package/skills/frontend/vue-expert-js/SKILL.md +167 -167
- package/skills/frontend/vue-expert-js/references/component-architecture.md +219 -219
- package/skills/frontend/vue-expert-js/references/composables-patterns.md +183 -183
- package/skills/frontend/vue-expert-js/references/jsdoc-typing.md +535 -535
- package/skills/frontend/vue-expert-js/references/state-management.md +249 -249
- package/skills/frontend/vue-expert-js/references/testing-patterns.md +237 -237
- package/skills/go-rust-cpp/cpp-pro/SKILL.md +115 -115
- package/skills/go-rust-cpp/cpp-pro/references/build-tooling.md +440 -440
- package/skills/go-rust-cpp/cpp-pro/references/concurrency.md +437 -437
- package/skills/go-rust-cpp/cpp-pro/references/memory-performance.md +397 -397
- package/skills/go-rust-cpp/cpp-pro/references/modern-cpp.md +304 -304
- package/skills/go-rust-cpp/cpp-pro/references/templates.md +357 -357
- package/skills/go-rust-cpp/golang-pro/SKILL.md +122 -122
- package/skills/go-rust-cpp/golang-pro/references/concurrency.md +329 -329
- package/skills/go-rust-cpp/golang-pro/references/generics.md +442 -442
- package/skills/go-rust-cpp/golang-pro/references/interfaces.md +432 -432
- package/skills/go-rust-cpp/golang-pro/references/project-structure.md +477 -477
- package/skills/go-rust-cpp/golang-pro/references/testing.md +451 -451
- package/skills/go-rust-cpp/rust-engineer/SKILL.md +167 -167
- package/skills/go-rust-cpp/rust-engineer/references/async.md +458 -458
- package/skills/go-rust-cpp/rust-engineer/references/error-handling.md +334 -334
- package/skills/go-rust-cpp/rust-engineer/references/ownership.md +278 -278
- package/skills/go-rust-cpp/rust-engineer/references/testing.md +470 -470
- package/skills/go-rust-cpp/rust-engineer/references/traits.md +413 -413
- package/skills/infra/cli-developer/SKILL.md +113 -113
- package/skills/infra/cli-developer/references/design-patterns.md +221 -221
- package/skills/infra/cli-developer/references/go-cli.md +540 -540
- package/skills/infra/cli-developer/references/node-cli.md +383 -383
- package/skills/infra/cli-developer/references/python-cli.md +422 -422
- package/skills/infra/cli-developer/references/ux-patterns.md +448 -448
- package/skills/infra/cloud-architect/SKILL.md +216 -216
- package/skills/infra/cloud-architect/references/aws.md +394 -394
- package/skills/infra/cloud-architect/references/azure.md +562 -562
- package/skills/infra/cloud-architect/references/cost.md +582 -582
- package/skills/infra/cloud-architect/references/gcp.md +633 -633
- package/skills/infra/cloud-architect/references/multi-cloud.md +483 -483
- package/skills/infra/devops-engineer/SKILL.md +144 -144
- package/skills/infra/devops-engineer/references/deployment-strategies.md +241 -241
- package/skills/infra/devops-engineer/references/docker-patterns.md +113 -113
- package/skills/infra/devops-engineer/references/github-actions.md +139 -139
- package/skills/infra/devops-engineer/references/incident-response.md +331 -331
- package/skills/infra/devops-engineer/references/kubernetes.md +154 -154
- package/skills/infra/devops-engineer/references/platform-engineering.md +417 -417
- package/skills/infra/devops-engineer/references/release-automation.md +527 -527
- package/skills/infra/devops-engineer/references/terraform-iac.md +141 -141
- package/skills/infra/kubernetes-specialist/SKILL.md +241 -241
- package/skills/infra/kubernetes-specialist/references/configuration.md +452 -452
- package/skills/infra/kubernetes-specialist/references/cost-optimization.md +458 -458
- package/skills/infra/kubernetes-specialist/references/custom-operators.md +563 -563
- package/skills/infra/kubernetes-specialist/references/gitops.md +530 -530
- package/skills/infra/kubernetes-specialist/references/helm-charts.md +912 -912
- package/skills/infra/kubernetes-specialist/references/multi-cluster.md +507 -507
- package/skills/infra/kubernetes-specialist/references/networking.md +447 -447
- package/skills/infra/kubernetes-specialist/references/service-mesh.md +459 -459
- package/skills/infra/kubernetes-specialist/references/storage.md +535 -535
- package/skills/infra/kubernetes-specialist/references/troubleshooting.md +414 -414
- package/skills/infra/kubernetes-specialist/references/workloads.md +377 -377
- package/skills/infra/mcp-developer/SKILL.md +143 -143
- package/skills/infra/mcp-developer/references/protocol.md +244 -244
- package/skills/infra/mcp-developer/references/python-sdk.md +367 -367
- package/skills/infra/mcp-developer/references/resources.md +554 -554
- package/skills/infra/mcp-developer/references/tools.md +480 -480
- package/skills/infra/mcp-developer/references/typescript-sdk.md +350 -350
- package/skills/infra/monitoring-expert/SKILL.md +176 -176
- package/skills/infra/monitoring-expert/references/alerting-rules.md +141 -141
- package/skills/infra/monitoring-expert/references/application-profiling.md +331 -331
- package/skills/infra/monitoring-expert/references/capacity-planning.md +344 -344
- package/skills/infra/monitoring-expert/references/dashboards.md +126 -126
- package/skills/infra/monitoring-expert/references/opentelemetry.md +123 -123
- package/skills/infra/monitoring-expert/references/performance-testing.md +269 -269
- package/skills/infra/monitoring-expert/references/prometheus-metrics.md +136 -136
- package/skills/infra/monitoring-expert/references/structured-logging.md +142 -142
- package/skills/infra/sre-engineer/SKILL.md +181 -181
- package/skills/infra/sre-engineer/references/automation-toil.md +492 -492
- package/skills/infra/sre-engineer/references/error-budget-policy.md +334 -334
- package/skills/infra/sre-engineer/references/incident-chaos.md +576 -576
- package/skills/infra/sre-engineer/references/monitoring-alerting.md +424 -424
- package/skills/infra/sre-engineer/references/slo-sli-management.md +238 -238
- package/skills/infra/terraform-engineer/SKILL.md +143 -143
- package/skills/infra/terraform-engineer/references/best-practices.md +583 -583
- package/skills/infra/terraform-engineer/references/module-patterns.md +297 -297
- package/skills/infra/terraform-engineer/references/providers.md +452 -452
- package/skills/infra/terraform-engineer/references/state-management.md +371 -371
- package/skills/infra/terraform-engineer/references/testing.md +486 -486
- package/skills/infra/websocket-engineer/SKILL.md +168 -168
- package/skills/infra/websocket-engineer/references/alternatives.md +391 -391
- package/skills/infra/websocket-engineer/references/patterns.md +400 -400
- package/skills/infra/websocket-engineer/references/protocol.md +195 -195
- package/skills/infra/websocket-engineer/references/scaling.md +333 -333
- package/skills/infra/websocket-engineer/references/security.md +474 -474
- package/skills/java/java-architect/SKILL.md +132 -132
- package/skills/java/java-architect/references/jpa-optimization.md +393 -393
- package/skills/java/java-architect/references/reactive-webflux.md +356 -356
- package/skills/java/java-architect/references/spring-boot-setup.md +269 -269
- package/skills/java/java-architect/references/spring-security.md +445 -445
- package/skills/java/java-architect/references/testing-patterns.md +500 -500
- package/skills/java/kotlin-specialist/SKILL.md +147 -147
- package/skills/java/kotlin-specialist/references/android-compose.md +419 -419
- package/skills/java/kotlin-specialist/references/coroutines-flow.md +276 -276
- package/skills/java/kotlin-specialist/references/dsl-idioms.md +421 -421
- package/skills/java/kotlin-specialist/references/ktor-server.md +426 -426
- package/skills/java/kotlin-specialist/references/multiplatform-kmp.md +380 -380
- package/skills/java/spring-boot-engineer/SKILL.md +195 -195
- package/skills/java/spring-boot-engineer/references/cloud.md +498 -498
- package/skills/java/spring-boot-engineer/references/data.md +381 -381
- package/skills/java/spring-boot-engineer/references/security.md +459 -459
- package/skills/java/spring-boot-engineer/references/testing.md +545 -545
- package/skills/java/spring-boot-engineer/references/web.md +295 -295
- package/skills/javascript/javascript-pro/SKILL.md +132 -132
- package/skills/javascript/javascript-pro/references/async-patterns.md +334 -334
- package/skills/javascript/javascript-pro/references/browser-apis.md +398 -398
- package/skills/javascript/javascript-pro/references/modern-syntax.md +272 -272
- package/skills/javascript/javascript-pro/references/modules.md +357 -357
- package/skills/javascript/javascript-pro/references/node-essentials.md +471 -471
- package/skills/javascript/nestjs-expert/SKILL.md +206 -206
- package/skills/javascript/nestjs-expert/references/authentication.md +166 -166
- package/skills/javascript/nestjs-expert/references/controllers-routing.md +111 -111
- package/skills/javascript/nestjs-expert/references/dtos-validation.md +153 -153
- package/skills/javascript/nestjs-expert/references/migration-from-express.md +1237 -1237
- package/skills/javascript/nestjs-expert/references/services-di.md +140 -140
- package/skills/javascript/nestjs-expert/references/testing-patterns.md +186 -186
- package/skills/javascript/typescript-pro/SKILL.md +145 -145
- package/skills/javascript/typescript-pro/references/advanced-types.md +259 -259
- package/skills/javascript/typescript-pro/references/configuration.md +445 -445
- package/skills/javascript/typescript-pro/references/patterns.md +484 -484
- package/skills/javascript/typescript-pro/references/type-guards.md +352 -352
- package/skills/javascript/typescript-pro/references/utility-types.md +329 -329
- package/skills/php/laravel-specialist/SKILL.md +262 -262
- package/skills/php/laravel-specialist/references/eloquent.md +351 -351
- package/skills/php/laravel-specialist/references/livewire.md +512 -512
- package/skills/php/laravel-specialist/references/queues.md +423 -423
- package/skills/php/laravel-specialist/references/routing.md +362 -362
- package/skills/php/laravel-specialist/references/testing.md +522 -522
- package/skills/php/php-pro/SKILL.md +206 -206
- package/skills/php/php-pro/references/async-patterns.md +412 -412
- package/skills/php/php-pro/references/laravel-patterns.md +377 -377
- package/skills/php/php-pro/references/modern-php-features.md +323 -323
- package/skills/php/php-pro/references/symfony-patterns.md +466 -466
- package/skills/php/php-pro/references/testing-quality.md +466 -466
- package/skills/product/competitive-analysis/SKILL.md +257 -257
- package/skills/product/meeting-notes/SKILL.md +266 -266
- package/skills/product/prd-template/SKILL.md +150 -150
- package/skills/product/stakeholder-update/SKILL.md +225 -225
- package/skills/product/user-research-synthesis/SKILL.md +235 -235
- package/skills/python/django-expert/SKILL.md +162 -162
- package/skills/python/django-expert/references/authentication.md +145 -145
- package/skills/python/django-expert/references/drf-serializers.md +148 -148
- package/skills/python/django-expert/references/models-orm.md +151 -151
- package/skills/python/django-expert/references/testing-django.md +204 -204
- package/skills/python/django-expert/references/viewsets-views.md +153 -153
- package/skills/python/fastapi-expert/SKILL.md +185 -185
- package/skills/python/fastapi-expert/references/async-sqlalchemy.md +146 -146
- package/skills/python/fastapi-expert/references/authentication.md +159 -159
- package/skills/python/fastapi-expert/references/endpoints-routing.md +142 -142
- package/skills/python/fastapi-expert/references/migration-from-django.md +996 -996
- package/skills/python/fastapi-expert/references/pydantic-v2.md +135 -135
- package/skills/python/fastapi-expert/references/testing-async.md +159 -159
- package/skills/python/pandas-pro/SKILL.md +178 -178
- package/skills/python/pandas-pro/references/aggregation-groupby.md +545 -545
- package/skills/python/pandas-pro/references/data-cleaning.md +500 -500
- package/skills/python/pandas-pro/references/dataframe-operations.md +420 -420
- package/skills/python/pandas-pro/references/merging-joining.md +596 -596
- package/skills/python/pandas-pro/references/performance-optimization.md +597 -597
- package/skills/python/python-pro/SKILL.md +177 -177
- package/skills/python/python-pro/references/async-patterns.md +356 -356
- package/skills/python/python-pro/references/packaging.md +460 -460
- package/skills/python/python-pro/references/standard-library.md +378 -378
- package/skills/python/python-pro/references/testing.md +404 -404
- package/skills/python/python-pro/references/type-system.md +290 -290
- package/skills/quality/chaos-engineer/SKILL.md +182 -182
- package/skills/quality/chaos-engineer/references/chaos-tools.md +511 -511
- package/skills/quality/chaos-engineer/references/experiment-design.md +229 -229
- package/skills/quality/chaos-engineer/references/game-days.md +434 -434
- package/skills/quality/chaos-engineer/references/infrastructure-chaos.md +348 -348
- package/skills/quality/chaos-engineer/references/kubernetes-chaos.md +432 -432
- package/skills/quality/code-reviewer/SKILL.md +119 -119
- package/skills/quality/code-reviewer/references/common-issues.md +142 -142
- package/skills/quality/code-reviewer/references/feedback-examples.md +144 -144
- package/skills/quality/code-reviewer/references/receiving-feedback.md +238 -238
- package/skills/quality/code-reviewer/references/report-template.md +109 -109
- package/skills/quality/code-reviewer/references/review-checklist.md +88 -88
- package/skills/quality/code-reviewer/references/spec-compliance-review.md +258 -258
- package/skills/quality/playwright-expert/SKILL.md +169 -169
- package/skills/quality/playwright-expert/references/api-mocking.md +140 -140
- package/skills/quality/playwright-expert/references/configuration.md +155 -155
- package/skills/quality/playwright-expert/references/debugging-flaky.md +150 -150
- package/skills/quality/playwright-expert/references/page-object-model.md +152 -152
- package/skills/quality/playwright-expert/references/selectors-locators.md +119 -119
- package/skills/quality/secure-code-guardian/SKILL.md +191 -191
- package/skills/quality/secure-code-guardian/references/authentication.md +136 -136
- package/skills/quality/secure-code-guardian/references/input-validation.md +146 -146
- package/skills/quality/secure-code-guardian/references/owasp-prevention.md +135 -135
- package/skills/quality/secure-code-guardian/references/security-headers.md +133 -133
- package/skills/quality/secure-code-guardian/references/xss-csrf.md +157 -157
- package/skills/quality/security-reviewer/SKILL.md +103 -103
- package/skills/quality/security-reviewer/references/infrastructure-security.md +268 -268
- package/skills/quality/security-reviewer/references/penetration-testing.md +268 -268
- package/skills/quality/security-reviewer/references/report-template.md +170 -170
- package/skills/quality/security-reviewer/references/sast-tools.md +117 -117
- package/skills/quality/security-reviewer/references/secret-scanning.md +125 -125
- package/skills/quality/security-reviewer/references/vulnerability-patterns.md +152 -152
- package/skills/quality/senior-qa/README.md +196 -196
- package/skills/quality/senior-qa/SKILL.md +399 -399
- package/skills/quality/senior-qa/references/qa_best_practices.md +964 -964
- package/skills/quality/senior-qa/references/test_automation_patterns.md +1009 -1009
- package/skills/quality/senior-qa/references/testing_strategies.md +649 -649
- package/skills/quality/senior-qa/scripts/coverage_analyzer.py +836 -836
- package/skills/quality/senior-qa/scripts/e2e_test_scaffolder.py +820 -820
- package/skills/quality/senior-qa/scripts/test_suite_generator.py +605 -605
- package/skills/quality/tdd-guide/HOW_TO_USE.md +313 -313
- package/skills/quality/tdd-guide/README.md +680 -680
- package/skills/quality/tdd-guide/SKILL.md +122 -122
- package/skills/quality/tdd-guide/assets/expected_output.json +77 -77
- package/skills/quality/tdd-guide/assets/sample_input_python.json +39 -39
- package/skills/quality/tdd-guide/assets/sample_input_typescript.json +36 -36
- package/skills/quality/tdd-guide/references/ci-integration.md +195 -195
- package/skills/quality/tdd-guide/references/framework-guide.md +206 -206
- package/skills/quality/tdd-guide/references/tdd-best-practices.md +128 -128
- package/skills/quality/tdd-guide/scripts/coverage_analyzer.py +434 -434
- package/skills/quality/tdd-guide/scripts/fixture_generator.py +440 -440
- package/skills/quality/tdd-guide/scripts/format_detector.py +384 -384
- package/skills/quality/tdd-guide/scripts/framework_adapter.py +428 -428
- package/skills/quality/tdd-guide/scripts/metrics_calculator.py +456 -456
- package/skills/quality/tdd-guide/scripts/output_formatter.py +354 -354
- package/skills/quality/tdd-guide/scripts/tdd_workflow.py +474 -474
- package/skills/quality/tdd-guide/scripts/test_generator.py +438 -438
- package/skills/quality/test-master/SKILL.md +94 -94
- package/skills/quality/test-master/references/automation-frameworks.md +294 -294
- package/skills/quality/test-master/references/e2e-testing.md +128 -128
- package/skills/quality/test-master/references/integration-testing.md +120 -120
- package/skills/quality/test-master/references/performance-testing.md +118 -118
- package/skills/quality/test-master/references/qa-methodology.md +247 -247
- package/skills/quality/test-master/references/security-testing.md +127 -127
- package/skills/quality/test-master/references/tdd-iron-laws.md +174 -174
- package/skills/quality/test-master/references/test-reports.md +104 -104
- package/skills/quality/test-master/references/testing-anti-patterns.md +231 -231
- package/skills/quality/test-master/references/unit-testing.md +113 -113
- package/skills/ruby/rails-expert/SKILL.md +154 -154
- package/skills/ruby/rails-expert/references/active-record.md +244 -244
- package/skills/ruby/rails-expert/references/api-development.md +401 -401
- package/skills/ruby/rails-expert/references/background-jobs.md +272 -272
- package/skills/ruby/rails-expert/references/hotwire-turbo.md +228 -228
- package/skills/ruby/rails-expert/references/rspec-testing.md +367 -367
- package/skills/swift/swift-expert/SKILL.md +163 -163
- package/skills/swift/swift-expert/references/async-concurrency.md +360 -360
- package/skills/swift/swift-expert/references/memory-performance.md +377 -377
- package/skills/swift/swift-expert/references/protocol-oriented.md +354 -354
- package/skills/swift/swift-expert/references/swiftui-patterns.md +291 -291
- package/skills/swift/swift-expert/references/testing-patterns.md +399 -399
- package/skills/workflow/brainstorming/SKILL.md +164 -164
- package/skills/workflow/brainstorming/scripts/frame-template.html +214 -214
- package/skills/workflow/brainstorming/scripts/helper.js +88 -88
- package/skills/workflow/brainstorming/scripts/server.cjs +354 -354
- package/skills/workflow/brainstorming/scripts/start-server.sh +148 -148
- package/skills/workflow/brainstorming/scripts/stop-server.sh +56 -56
- package/skills/workflow/brainstorming/spec-document-reviewer-prompt.md +49 -49
- package/skills/workflow/brainstorming/visual-companion.md +287 -287
- package/skills/workflow/documentation/SKILL.md +45 -45
- package/skills/workflow/entropy-management/SKILL.md +115 -115
- package/skills/workflow/executing-plans/SKILL.md +70 -70
- package/skills/workflow/finishing-a-development-branch/SKILL.md +200 -200
- package/skills/workflow/receiving-code-review/SKILL.md +213 -213
- package/skills/workflow/requesting-code-review/SKILL.md +105 -105
- package/skills/workflow/requesting-code-review/code-reviewer.md +146 -146
- package/skills/workflow/requirement-engineering/SKILL.md +111 -111
- package/skills/workflow/systematic-debugging/CREATION-LOG.md +119 -119
- package/skills/workflow/systematic-debugging/SKILL.md +296 -296
- package/skills/workflow/systematic-debugging/condition-based-waiting-example.ts +158 -158
- package/skills/workflow/systematic-debugging/condition-based-waiting.md +115 -115
- package/skills/workflow/systematic-debugging/defense-in-depth.md +122 -122
- package/skills/workflow/systematic-debugging/find-polluter.sh +63 -63
- package/skills/workflow/systematic-debugging/root-cause-tracing.md +169 -169
- package/skills/workflow/systematic-debugging/test-academic.md +14 -14
- package/skills/workflow/systematic-debugging/test-pressure-1.md +58 -58
- package/skills/workflow/systematic-debugging/test-pressure-2.md +68 -68
- package/skills/workflow/systematic-debugging/test-pressure-3.md +69 -69
- package/skills/workflow/using-git-worktrees/SKILL.md +218 -218
- package/skills/workflow/verification-before-completion/SKILL.md +139 -139
- package/skills/workflow/writing-plans/SKILL.md +151 -151
- package/skills/workflow/writing-plans/plan-document-reviewer-prompt.md +49 -49
- package/skills/workflow/writing-skills/SKILL.md +655 -655
- package/skills/workflow/writing-skills/anthropic-best-practices.md +1150 -1150
- package/skills/workflow/writing-skills/examples/CLAUDE_MD_TESTING.md +189 -189
- package/skills/workflow/writing-skills/persuasion-principles.md +187 -187
- package/skills/workflow/writing-skills/render-graphs.js +168 -168
- package/skills/workflow/writing-skills/testing-skills-with-subagents.md +384 -384
|
@@ -1,456 +1,456 @@
|
|
|
1
|
-
"""
|
|
2
|
-
Metrics calculation module.
|
|
3
|
-
|
|
4
|
-
Calculate comprehensive test and code quality metrics including complexity,
|
|
5
|
-
test quality scoring, and test execution analysis.
|
|
6
|
-
"""
|
|
7
|
-
|
|
8
|
-
from typing import Dict, List, Any, Optional
|
|
9
|
-
import re
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
class MetricsCalculator:
|
|
13
|
-
"""Calculate comprehensive test and code quality metrics."""
|
|
14
|
-
|
|
15
|
-
def __init__(self):
|
|
16
|
-
"""Initialize metrics calculator."""
|
|
17
|
-
self.metrics = {}
|
|
18
|
-
|
|
19
|
-
def calculate_all_metrics(
|
|
20
|
-
self,
|
|
21
|
-
source_code: str,
|
|
22
|
-
test_code: str,
|
|
23
|
-
coverage_data: Optional[Dict[str, Any]] = None,
|
|
24
|
-
execution_data: Optional[Dict[str, Any]] = None
|
|
25
|
-
) -> Dict[str, Any]:
|
|
26
|
-
"""
|
|
27
|
-
Calculate all available metrics.
|
|
28
|
-
|
|
29
|
-
Args:
|
|
30
|
-
source_code: Source code to analyze
|
|
31
|
-
test_code: Test code to analyze
|
|
32
|
-
coverage_data: Coverage report data
|
|
33
|
-
execution_data: Test execution results
|
|
34
|
-
|
|
35
|
-
Returns:
|
|
36
|
-
Complete metrics dictionary
|
|
37
|
-
"""
|
|
38
|
-
metrics = {
|
|
39
|
-
'complexity': self.calculate_complexity(source_code),
|
|
40
|
-
'test_quality': self.calculate_test_quality(test_code),
|
|
41
|
-
'coverage': coverage_data or {},
|
|
42
|
-
'execution': execution_data or {}
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
self.metrics = metrics
|
|
46
|
-
return metrics
|
|
47
|
-
|
|
48
|
-
def calculate_complexity(self, code: str) -> Dict[str, Any]:
|
|
49
|
-
"""
|
|
50
|
-
Calculate code complexity metrics.
|
|
51
|
-
|
|
52
|
-
Args:
|
|
53
|
-
code: Source code to analyze
|
|
54
|
-
|
|
55
|
-
Returns:
|
|
56
|
-
Complexity metrics (cyclomatic, cognitive, testability score)
|
|
57
|
-
"""
|
|
58
|
-
cyclomatic = self._cyclomatic_complexity(code)
|
|
59
|
-
cognitive = self._cognitive_complexity(code)
|
|
60
|
-
testability = self._testability_score(code, cyclomatic)
|
|
61
|
-
|
|
62
|
-
return {
|
|
63
|
-
'cyclomatic_complexity': cyclomatic,
|
|
64
|
-
'cognitive_complexity': cognitive,
|
|
65
|
-
'testability_score': testability,
|
|
66
|
-
'assessment': self._complexity_assessment(cyclomatic, cognitive)
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
def _cyclomatic_complexity(self, code: str) -> int:
|
|
70
|
-
"""
|
|
71
|
-
Calculate cyclomatic complexity (simplified).
|
|
72
|
-
|
|
73
|
-
Counts decision points: if, for, while, case, catch, &&, ||
|
|
74
|
-
"""
|
|
75
|
-
# Count decision points
|
|
76
|
-
decision_points = 0
|
|
77
|
-
|
|
78
|
-
# Control flow keywords
|
|
79
|
-
keywords = ['if', 'for', 'while', 'case', 'catch', 'except']
|
|
80
|
-
for keyword in keywords:
|
|
81
|
-
# Use word boundaries to avoid matching substrings
|
|
82
|
-
pattern = r'\b' + keyword + r'\b'
|
|
83
|
-
decision_points += len(re.findall(pattern, code))
|
|
84
|
-
|
|
85
|
-
# Logical operators
|
|
86
|
-
decision_points += len(re.findall(r'\&\&|\|\|', code))
|
|
87
|
-
|
|
88
|
-
# Base complexity is 1
|
|
89
|
-
return decision_points + 1
|
|
90
|
-
|
|
91
|
-
def _cognitive_complexity(self, code: str) -> int:
|
|
92
|
-
"""
|
|
93
|
-
Calculate cognitive complexity (simplified).
|
|
94
|
-
|
|
95
|
-
Similar to cyclomatic but penalizes nesting and non-obvious flow.
|
|
96
|
-
"""
|
|
97
|
-
lines = code.split('\n')
|
|
98
|
-
cognitive_score = 0
|
|
99
|
-
nesting_level = 0
|
|
100
|
-
|
|
101
|
-
for line in lines:
|
|
102
|
-
stripped = line.strip()
|
|
103
|
-
|
|
104
|
-
# Increase nesting level
|
|
105
|
-
if any(keyword in stripped for keyword in ['if ', 'for ', 'while ', 'def ', 'function ', 'class ']):
|
|
106
|
-
cognitive_score += (1 + nesting_level)
|
|
107
|
-
if stripped.endswith(':') or stripped.endswith('{'):
|
|
108
|
-
nesting_level += 1
|
|
109
|
-
|
|
110
|
-
# Decrease nesting level
|
|
111
|
-
if stripped.startswith('}') or (stripped and not stripped.startswith(' ') and nesting_level > 0):
|
|
112
|
-
nesting_level = max(0, nesting_level - 1)
|
|
113
|
-
|
|
114
|
-
# Penalize complex conditions
|
|
115
|
-
if '&&' in stripped or '||' in stripped:
|
|
116
|
-
cognitive_score += 1
|
|
117
|
-
|
|
118
|
-
return cognitive_score
|
|
119
|
-
|
|
120
|
-
def _testability_score(self, code: str, cyclomatic: int) -> float:
|
|
121
|
-
"""
|
|
122
|
-
Calculate testability score (0-100).
|
|
123
|
-
|
|
124
|
-
Based on:
|
|
125
|
-
- Complexity (lower is better)
|
|
126
|
-
- Dependencies (fewer is better)
|
|
127
|
-
- Pure functions (more is better)
|
|
128
|
-
"""
|
|
129
|
-
score = 100.0
|
|
130
|
-
|
|
131
|
-
# Penalize high complexity
|
|
132
|
-
if cyclomatic > 10:
|
|
133
|
-
score -= (cyclomatic - 10) * 5
|
|
134
|
-
elif cyclomatic > 5:
|
|
135
|
-
score -= (cyclomatic - 5) * 2
|
|
136
|
-
|
|
137
|
-
# Penalize many dependencies
|
|
138
|
-
imports = len(re.findall(r'import |require\(|from .* import', code))
|
|
139
|
-
if imports > 10:
|
|
140
|
-
score -= (imports - 10) * 2
|
|
141
|
-
|
|
142
|
-
# Reward small functions
|
|
143
|
-
functions = len(re.findall(r'def |function ', code))
|
|
144
|
-
lines = len(code.split('\n'))
|
|
145
|
-
if functions > 0:
|
|
146
|
-
avg_function_size = lines / functions
|
|
147
|
-
if avg_function_size < 20:
|
|
148
|
-
score += 10
|
|
149
|
-
elif avg_function_size > 50:
|
|
150
|
-
score -= 10
|
|
151
|
-
|
|
152
|
-
return max(0.0, min(100.0, score))
|
|
153
|
-
|
|
154
|
-
def _complexity_assessment(self, cyclomatic: int, cognitive: int) -> str:
|
|
155
|
-
"""Generate complexity assessment."""
|
|
156
|
-
if cyclomatic <= 5 and cognitive <= 10:
|
|
157
|
-
return "Low complexity - easy to test"
|
|
158
|
-
elif cyclomatic <= 10 and cognitive <= 20:
|
|
159
|
-
return "Medium complexity - moderately testable"
|
|
160
|
-
elif cyclomatic <= 15 and cognitive <= 30:
|
|
161
|
-
return "High complexity - challenging to test"
|
|
162
|
-
else:
|
|
163
|
-
return "Very high complexity - consider refactoring"
|
|
164
|
-
|
|
165
|
-
def calculate_test_quality(self, test_code: str) -> Dict[str, Any]:
|
|
166
|
-
"""
|
|
167
|
-
Calculate test quality metrics.
|
|
168
|
-
|
|
169
|
-
Args:
|
|
170
|
-
test_code: Test code to analyze
|
|
171
|
-
|
|
172
|
-
Returns:
|
|
173
|
-
Test quality metrics
|
|
174
|
-
"""
|
|
175
|
-
assertions = self._count_assertions(test_code)
|
|
176
|
-
test_functions = self._count_test_functions(test_code)
|
|
177
|
-
isolation_score = self._isolation_score(test_code)
|
|
178
|
-
naming_quality = self._naming_quality(test_code)
|
|
179
|
-
test_smells = self._detect_test_smells(test_code)
|
|
180
|
-
|
|
181
|
-
avg_assertions = assertions / test_functions if test_functions > 0 else 0
|
|
182
|
-
|
|
183
|
-
return {
|
|
184
|
-
'total_tests': test_functions,
|
|
185
|
-
'total_assertions': assertions,
|
|
186
|
-
'avg_assertions_per_test': round(avg_assertions, 2),
|
|
187
|
-
'isolation_score': isolation_score,
|
|
188
|
-
'naming_quality': naming_quality,
|
|
189
|
-
'test_smells': test_smells,
|
|
190
|
-
'quality_score': self._calculate_quality_score(
|
|
191
|
-
avg_assertions, isolation_score, naming_quality, test_smells
|
|
192
|
-
)
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
def _count_assertions(self, test_code: str) -> int:
|
|
196
|
-
"""Count assertion statements."""
|
|
197
|
-
# Common assertion patterns
|
|
198
|
-
patterns = [
|
|
199
|
-
r'\bassert[A-Z]\w*\(', # JUnit: assertTrue, assertEquals
|
|
200
|
-
r'\bexpect\(', # Jest/Vitest: expect()
|
|
201
|
-
r'\bassert\s+', # Python: assert
|
|
202
|
-
r'\.should\.', # Chai: should
|
|
203
|
-
r'\.to\.', # Chai: expect().to
|
|
204
|
-
]
|
|
205
|
-
|
|
206
|
-
count = 0
|
|
207
|
-
for pattern in patterns:
|
|
208
|
-
count += len(re.findall(pattern, test_code))
|
|
209
|
-
|
|
210
|
-
return count
|
|
211
|
-
|
|
212
|
-
def _count_test_functions(self, test_code: str) -> int:
|
|
213
|
-
"""Count test functions."""
|
|
214
|
-
patterns = [
|
|
215
|
-
r'\btest_\w+', # Python: test_*
|
|
216
|
-
r'\bit\(', # Jest/Mocha: it()
|
|
217
|
-
r'\btest\(', # Jest: test()
|
|
218
|
-
r'@Test', # JUnit: @Test
|
|
219
|
-
r'\bdef test_', # Python def test_
|
|
220
|
-
]
|
|
221
|
-
|
|
222
|
-
count = 0
|
|
223
|
-
for pattern in patterns:
|
|
224
|
-
count += len(re.findall(pattern, test_code))
|
|
225
|
-
|
|
226
|
-
return max(1, count) # At least 1 to avoid division by zero
|
|
227
|
-
|
|
228
|
-
def _isolation_score(self, test_code: str) -> float:
|
|
229
|
-
"""
|
|
230
|
-
Calculate test isolation score (0-100).
|
|
231
|
-
|
|
232
|
-
Higher score = better isolation (fewer shared dependencies)
|
|
233
|
-
"""
|
|
234
|
-
score = 100.0
|
|
235
|
-
|
|
236
|
-
# Penalize global state
|
|
237
|
-
globals_used = len(re.findall(r'\bglobal\s+\w+', test_code))
|
|
238
|
-
score -= globals_used * 10
|
|
239
|
-
|
|
240
|
-
# Penalize shared setup without proper cleanup
|
|
241
|
-
setup_count = len(re.findall(r'beforeAll|beforeEach|setUp', test_code))
|
|
242
|
-
cleanup_count = len(re.findall(r'afterAll|afterEach|tearDown', test_code))
|
|
243
|
-
if setup_count > cleanup_count:
|
|
244
|
-
score -= (setup_count - cleanup_count) * 5
|
|
245
|
-
|
|
246
|
-
# Reward mocking
|
|
247
|
-
mocks = len(re.findall(r'mock|stub|spy', test_code, re.IGNORECASE))
|
|
248
|
-
score += min(mocks * 2, 10)
|
|
249
|
-
|
|
250
|
-
return max(0.0, min(100.0, score))
|
|
251
|
-
|
|
252
|
-
def _naming_quality(self, test_code: str) -> float:
|
|
253
|
-
"""
|
|
254
|
-
Calculate test naming quality score (0-100).
|
|
255
|
-
|
|
256
|
-
Better names are descriptive and follow conventions.
|
|
257
|
-
"""
|
|
258
|
-
test_names = re.findall(r'(?:it|test|def test_)\s*\(?\s*["\']?([^"\')\n]+)', test_code)
|
|
259
|
-
|
|
260
|
-
if not test_names:
|
|
261
|
-
return 50.0
|
|
262
|
-
|
|
263
|
-
score = 0
|
|
264
|
-
for name in test_names:
|
|
265
|
-
name_score = 0
|
|
266
|
-
|
|
267
|
-
# Check length (too short or too long is bad)
|
|
268
|
-
if 20 <= len(name) <= 80:
|
|
269
|
-
name_score += 30
|
|
270
|
-
elif 10 <= len(name) < 20 or 80 < len(name) <= 100:
|
|
271
|
-
name_score += 15
|
|
272
|
-
|
|
273
|
-
# Check for descriptive words
|
|
274
|
-
descriptive_words = ['should', 'when', 'given', 'returns', 'throws', 'handles']
|
|
275
|
-
if any(word in name.lower() for word in descriptive_words):
|
|
276
|
-
name_score += 30
|
|
277
|
-
|
|
278
|
-
# Check for underscores or camelCase (not just letters)
|
|
279
|
-
if '_' in name or re.search(r'[a-z][A-Z]', name):
|
|
280
|
-
name_score += 20
|
|
281
|
-
|
|
282
|
-
# Avoid generic names
|
|
283
|
-
generic = ['test1', 'test2', 'testit', 'mytest']
|
|
284
|
-
if name.lower() not in generic:
|
|
285
|
-
name_score += 20
|
|
286
|
-
|
|
287
|
-
score += name_score
|
|
288
|
-
|
|
289
|
-
return min(100.0, score / len(test_names))
|
|
290
|
-
|
|
291
|
-
def _detect_test_smells(self, test_code: str) -> List[Dict[str, str]]:
|
|
292
|
-
"""Detect common test smells."""
|
|
293
|
-
smells = []
|
|
294
|
-
|
|
295
|
-
# Test smell 1: No assertions
|
|
296
|
-
if 'assert' not in test_code.lower() and 'expect' not in test_code.lower():
|
|
297
|
-
smells.append({
|
|
298
|
-
'smell': 'missing_assertions',
|
|
299
|
-
'description': 'Tests without assertions',
|
|
300
|
-
'severity': 'high'
|
|
301
|
-
})
|
|
302
|
-
|
|
303
|
-
# Test smell 2: Too many assertions
|
|
304
|
-
test_count = self._count_test_functions(test_code)
|
|
305
|
-
assertion_count = self._count_assertions(test_code)
|
|
306
|
-
avg_assertions = assertion_count / test_count if test_count > 0 else 0
|
|
307
|
-
if avg_assertions > 5:
|
|
308
|
-
smells.append({
|
|
309
|
-
'smell': 'assertion_roulette',
|
|
310
|
-
'description': f'Too many assertions per test (avg: {avg_assertions:.1f})',
|
|
311
|
-
'severity': 'medium'
|
|
312
|
-
})
|
|
313
|
-
|
|
314
|
-
# Test smell 3: Sleeps in tests
|
|
315
|
-
if 'sleep' in test_code.lower() or 'wait' in test_code.lower():
|
|
316
|
-
smells.append({
|
|
317
|
-
'smell': 'sleepy_test',
|
|
318
|
-
'description': 'Tests using sleep/wait (potential flakiness)',
|
|
319
|
-
'severity': 'high'
|
|
320
|
-
})
|
|
321
|
-
|
|
322
|
-
# Test smell 4: Conditional logic in tests
|
|
323
|
-
if re.search(r'\bif\s*\(', test_code):
|
|
324
|
-
smells.append({
|
|
325
|
-
'smell': 'conditional_test_logic',
|
|
326
|
-
'description': 'Tests contain conditional logic',
|
|
327
|
-
'severity': 'medium'
|
|
328
|
-
})
|
|
329
|
-
|
|
330
|
-
return smells
|
|
331
|
-
|
|
332
|
-
def _calculate_quality_score(
|
|
333
|
-
self,
|
|
334
|
-
avg_assertions: float,
|
|
335
|
-
isolation: float,
|
|
336
|
-
naming: float,
|
|
337
|
-
smells: List[Dict[str, str]]
|
|
338
|
-
) -> float:
|
|
339
|
-
"""Calculate overall test quality score."""
|
|
340
|
-
score = 0.0
|
|
341
|
-
|
|
342
|
-
# Assertions (30 points)
|
|
343
|
-
if 1 <= avg_assertions <= 3:
|
|
344
|
-
score += 30
|
|
345
|
-
elif 0 < avg_assertions < 1 or 3 < avg_assertions <= 5:
|
|
346
|
-
score += 20
|
|
347
|
-
else:
|
|
348
|
-
score += 10
|
|
349
|
-
|
|
350
|
-
# Isolation (30 points)
|
|
351
|
-
score += isolation * 0.3
|
|
352
|
-
|
|
353
|
-
# Naming (20 points)
|
|
354
|
-
score += naming * 0.2
|
|
355
|
-
|
|
356
|
-
# Smells (20 points - deduct based on severity)
|
|
357
|
-
smell_penalty = 0
|
|
358
|
-
for smell in smells:
|
|
359
|
-
if smell['severity'] == 'high':
|
|
360
|
-
smell_penalty += 10
|
|
361
|
-
elif smell['severity'] == 'medium':
|
|
362
|
-
smell_penalty += 5
|
|
363
|
-
else:
|
|
364
|
-
smell_penalty += 2
|
|
365
|
-
|
|
366
|
-
score = max(0, score - smell_penalty)
|
|
367
|
-
|
|
368
|
-
return round(min(100.0, score), 2)
|
|
369
|
-
|
|
370
|
-
def analyze_execution_metrics(
|
|
371
|
-
self,
|
|
372
|
-
execution_data: Dict[str, Any]
|
|
373
|
-
) -> Dict[str, Any]:
|
|
374
|
-
"""
|
|
375
|
-
Analyze test execution metrics.
|
|
376
|
-
|
|
377
|
-
Args:
|
|
378
|
-
execution_data: Test execution results with timing
|
|
379
|
-
|
|
380
|
-
Returns:
|
|
381
|
-
Execution analysis
|
|
382
|
-
"""
|
|
383
|
-
tests = execution_data.get('tests', [])
|
|
384
|
-
|
|
385
|
-
if not tests:
|
|
386
|
-
return {}
|
|
387
|
-
|
|
388
|
-
# Calculate timing statistics
|
|
389
|
-
timings = [test.get('duration', 0) for test in tests]
|
|
390
|
-
total_time = sum(timings)
|
|
391
|
-
avg_time = total_time / len(tests) if tests else 0
|
|
392
|
-
|
|
393
|
-
# Identify slow tests (>100ms for unit tests)
|
|
394
|
-
slow_tests = [
|
|
395
|
-
test for test in tests
|
|
396
|
-
if test.get('duration', 0) > 100
|
|
397
|
-
]
|
|
398
|
-
|
|
399
|
-
# Identify flaky tests (if failure history available)
|
|
400
|
-
flaky_tests = [
|
|
401
|
-
test for test in tests
|
|
402
|
-
if test.get('failure_rate', 0) > 0.1 # Failed >10% of time
|
|
403
|
-
]
|
|
404
|
-
|
|
405
|
-
return {
|
|
406
|
-
'total_tests': len(tests),
|
|
407
|
-
'total_time_ms': round(total_time, 2),
|
|
408
|
-
'avg_time_ms': round(avg_time, 2),
|
|
409
|
-
'slow_tests': len(slow_tests),
|
|
410
|
-
'slow_test_details': slow_tests[:5], # Top 5
|
|
411
|
-
'flaky_tests': len(flaky_tests),
|
|
412
|
-
'flaky_test_details': flaky_tests,
|
|
413
|
-
'pass_rate': self._calculate_pass_rate(tests)
|
|
414
|
-
}
|
|
415
|
-
|
|
416
|
-
def _calculate_pass_rate(self, tests: List[Dict[str, Any]]) -> float:
|
|
417
|
-
"""Calculate test pass rate."""
|
|
418
|
-
if not tests:
|
|
419
|
-
return 0.0
|
|
420
|
-
|
|
421
|
-
passed = sum(1 for test in tests if test.get('status') == 'passed')
|
|
422
|
-
return round((passed / len(tests)) * 100, 2)
|
|
423
|
-
|
|
424
|
-
def generate_metrics_summary(self) -> str:
|
|
425
|
-
"""Generate human-readable metrics summary."""
|
|
426
|
-
if not self.metrics:
|
|
427
|
-
return "No metrics calculated yet."
|
|
428
|
-
|
|
429
|
-
lines = ["# Test Metrics Summary\n"]
|
|
430
|
-
|
|
431
|
-
# Complexity
|
|
432
|
-
if 'complexity' in self.metrics:
|
|
433
|
-
comp = self.metrics['complexity']
|
|
434
|
-
lines.append(f"## Code Complexity")
|
|
435
|
-
lines.append(f"- Cyclomatic Complexity: {comp['cyclomatic_complexity']}")
|
|
436
|
-
lines.append(f"- Cognitive Complexity: {comp['cognitive_complexity']}")
|
|
437
|
-
lines.append(f"- Testability Score: {comp['testability_score']:.1f}/100")
|
|
438
|
-
lines.append(f"- Assessment: {comp['assessment']}\n")
|
|
439
|
-
|
|
440
|
-
# Test Quality
|
|
441
|
-
if 'test_quality' in self.metrics:
|
|
442
|
-
qual = self.metrics['test_quality']
|
|
443
|
-
lines.append(f"## Test Quality")
|
|
444
|
-
lines.append(f"- Total Tests: {qual['total_tests']}")
|
|
445
|
-
lines.append(f"- Assertions per Test: {qual['avg_assertions_per_test']}")
|
|
446
|
-
lines.append(f"- Isolation Score: {qual['isolation_score']:.1f}/100")
|
|
447
|
-
lines.append(f"- Naming Quality: {qual['naming_quality']:.1f}/100")
|
|
448
|
-
lines.append(f"- Quality Score: {qual['quality_score']:.1f}/100\n")
|
|
449
|
-
|
|
450
|
-
if qual['test_smells']:
|
|
451
|
-
lines.append(f"### Test Smells Detected:")
|
|
452
|
-
for smell in qual['test_smells']:
|
|
453
|
-
lines.append(f"- {smell['description']} (severity: {smell['severity']})")
|
|
454
|
-
lines.append("")
|
|
455
|
-
|
|
456
|
-
return "\n".join(lines)
|
|
1
|
+
"""
|
|
2
|
+
Metrics calculation module.
|
|
3
|
+
|
|
4
|
+
Calculate comprehensive test and code quality metrics including complexity,
|
|
5
|
+
test quality scoring, and test execution analysis.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from typing import Dict, List, Any, Optional
|
|
9
|
+
import re
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class MetricsCalculator:
|
|
13
|
+
"""Calculate comprehensive test and code quality metrics."""
|
|
14
|
+
|
|
15
|
+
def __init__(self):
|
|
16
|
+
"""Initialize metrics calculator."""
|
|
17
|
+
self.metrics = {}
|
|
18
|
+
|
|
19
|
+
def calculate_all_metrics(
|
|
20
|
+
self,
|
|
21
|
+
source_code: str,
|
|
22
|
+
test_code: str,
|
|
23
|
+
coverage_data: Optional[Dict[str, Any]] = None,
|
|
24
|
+
execution_data: Optional[Dict[str, Any]] = None
|
|
25
|
+
) -> Dict[str, Any]:
|
|
26
|
+
"""
|
|
27
|
+
Calculate all available metrics.
|
|
28
|
+
|
|
29
|
+
Args:
|
|
30
|
+
source_code: Source code to analyze
|
|
31
|
+
test_code: Test code to analyze
|
|
32
|
+
coverage_data: Coverage report data
|
|
33
|
+
execution_data: Test execution results
|
|
34
|
+
|
|
35
|
+
Returns:
|
|
36
|
+
Complete metrics dictionary
|
|
37
|
+
"""
|
|
38
|
+
metrics = {
|
|
39
|
+
'complexity': self.calculate_complexity(source_code),
|
|
40
|
+
'test_quality': self.calculate_test_quality(test_code),
|
|
41
|
+
'coverage': coverage_data or {},
|
|
42
|
+
'execution': execution_data or {}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
self.metrics = metrics
|
|
46
|
+
return metrics
|
|
47
|
+
|
|
48
|
+
def calculate_complexity(self, code: str) -> Dict[str, Any]:
|
|
49
|
+
"""
|
|
50
|
+
Calculate code complexity metrics.
|
|
51
|
+
|
|
52
|
+
Args:
|
|
53
|
+
code: Source code to analyze
|
|
54
|
+
|
|
55
|
+
Returns:
|
|
56
|
+
Complexity metrics (cyclomatic, cognitive, testability score)
|
|
57
|
+
"""
|
|
58
|
+
cyclomatic = self._cyclomatic_complexity(code)
|
|
59
|
+
cognitive = self._cognitive_complexity(code)
|
|
60
|
+
testability = self._testability_score(code, cyclomatic)
|
|
61
|
+
|
|
62
|
+
return {
|
|
63
|
+
'cyclomatic_complexity': cyclomatic,
|
|
64
|
+
'cognitive_complexity': cognitive,
|
|
65
|
+
'testability_score': testability,
|
|
66
|
+
'assessment': self._complexity_assessment(cyclomatic, cognitive)
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
def _cyclomatic_complexity(self, code: str) -> int:
|
|
70
|
+
"""
|
|
71
|
+
Calculate cyclomatic complexity (simplified).
|
|
72
|
+
|
|
73
|
+
Counts decision points: if, for, while, case, catch, &&, ||
|
|
74
|
+
"""
|
|
75
|
+
# Count decision points
|
|
76
|
+
decision_points = 0
|
|
77
|
+
|
|
78
|
+
# Control flow keywords
|
|
79
|
+
keywords = ['if', 'for', 'while', 'case', 'catch', 'except']
|
|
80
|
+
for keyword in keywords:
|
|
81
|
+
# Use word boundaries to avoid matching substrings
|
|
82
|
+
pattern = r'\b' + keyword + r'\b'
|
|
83
|
+
decision_points += len(re.findall(pattern, code))
|
|
84
|
+
|
|
85
|
+
# Logical operators
|
|
86
|
+
decision_points += len(re.findall(r'\&\&|\|\|', code))
|
|
87
|
+
|
|
88
|
+
# Base complexity is 1
|
|
89
|
+
return decision_points + 1
|
|
90
|
+
|
|
91
|
+
def _cognitive_complexity(self, code: str) -> int:
|
|
92
|
+
"""
|
|
93
|
+
Calculate cognitive complexity (simplified).
|
|
94
|
+
|
|
95
|
+
Similar to cyclomatic but penalizes nesting and non-obvious flow.
|
|
96
|
+
"""
|
|
97
|
+
lines = code.split('\n')
|
|
98
|
+
cognitive_score = 0
|
|
99
|
+
nesting_level = 0
|
|
100
|
+
|
|
101
|
+
for line in lines:
|
|
102
|
+
stripped = line.strip()
|
|
103
|
+
|
|
104
|
+
# Increase nesting level
|
|
105
|
+
if any(keyword in stripped for keyword in ['if ', 'for ', 'while ', 'def ', 'function ', 'class ']):
|
|
106
|
+
cognitive_score += (1 + nesting_level)
|
|
107
|
+
if stripped.endswith(':') or stripped.endswith('{'):
|
|
108
|
+
nesting_level += 1
|
|
109
|
+
|
|
110
|
+
# Decrease nesting level
|
|
111
|
+
if stripped.startswith('}') or (stripped and not stripped.startswith(' ') and nesting_level > 0):
|
|
112
|
+
nesting_level = max(0, nesting_level - 1)
|
|
113
|
+
|
|
114
|
+
# Penalize complex conditions
|
|
115
|
+
if '&&' in stripped or '||' in stripped:
|
|
116
|
+
cognitive_score += 1
|
|
117
|
+
|
|
118
|
+
return cognitive_score
|
|
119
|
+
|
|
120
|
+
def _testability_score(self, code: str, cyclomatic: int) -> float:
|
|
121
|
+
"""
|
|
122
|
+
Calculate testability score (0-100).
|
|
123
|
+
|
|
124
|
+
Based on:
|
|
125
|
+
- Complexity (lower is better)
|
|
126
|
+
- Dependencies (fewer is better)
|
|
127
|
+
- Pure functions (more is better)
|
|
128
|
+
"""
|
|
129
|
+
score = 100.0
|
|
130
|
+
|
|
131
|
+
# Penalize high complexity
|
|
132
|
+
if cyclomatic > 10:
|
|
133
|
+
score -= (cyclomatic - 10) * 5
|
|
134
|
+
elif cyclomatic > 5:
|
|
135
|
+
score -= (cyclomatic - 5) * 2
|
|
136
|
+
|
|
137
|
+
# Penalize many dependencies
|
|
138
|
+
imports = len(re.findall(r'import |require\(|from .* import', code))
|
|
139
|
+
if imports > 10:
|
|
140
|
+
score -= (imports - 10) * 2
|
|
141
|
+
|
|
142
|
+
# Reward small functions
|
|
143
|
+
functions = len(re.findall(r'def |function ', code))
|
|
144
|
+
lines = len(code.split('\n'))
|
|
145
|
+
if functions > 0:
|
|
146
|
+
avg_function_size = lines / functions
|
|
147
|
+
if avg_function_size < 20:
|
|
148
|
+
score += 10
|
|
149
|
+
elif avg_function_size > 50:
|
|
150
|
+
score -= 10
|
|
151
|
+
|
|
152
|
+
return max(0.0, min(100.0, score))
|
|
153
|
+
|
|
154
|
+
def _complexity_assessment(self, cyclomatic: int, cognitive: int) -> str:
|
|
155
|
+
"""Generate complexity assessment."""
|
|
156
|
+
if cyclomatic <= 5 and cognitive <= 10:
|
|
157
|
+
return "Low complexity - easy to test"
|
|
158
|
+
elif cyclomatic <= 10 and cognitive <= 20:
|
|
159
|
+
return "Medium complexity - moderately testable"
|
|
160
|
+
elif cyclomatic <= 15 and cognitive <= 30:
|
|
161
|
+
return "High complexity - challenging to test"
|
|
162
|
+
else:
|
|
163
|
+
return "Very high complexity - consider refactoring"
|
|
164
|
+
|
|
165
|
+
def calculate_test_quality(self, test_code: str) -> Dict[str, Any]:
|
|
166
|
+
"""
|
|
167
|
+
Calculate test quality metrics.
|
|
168
|
+
|
|
169
|
+
Args:
|
|
170
|
+
test_code: Test code to analyze
|
|
171
|
+
|
|
172
|
+
Returns:
|
|
173
|
+
Test quality metrics
|
|
174
|
+
"""
|
|
175
|
+
assertions = self._count_assertions(test_code)
|
|
176
|
+
test_functions = self._count_test_functions(test_code)
|
|
177
|
+
isolation_score = self._isolation_score(test_code)
|
|
178
|
+
naming_quality = self._naming_quality(test_code)
|
|
179
|
+
test_smells = self._detect_test_smells(test_code)
|
|
180
|
+
|
|
181
|
+
avg_assertions = assertions / test_functions if test_functions > 0 else 0
|
|
182
|
+
|
|
183
|
+
return {
|
|
184
|
+
'total_tests': test_functions,
|
|
185
|
+
'total_assertions': assertions,
|
|
186
|
+
'avg_assertions_per_test': round(avg_assertions, 2),
|
|
187
|
+
'isolation_score': isolation_score,
|
|
188
|
+
'naming_quality': naming_quality,
|
|
189
|
+
'test_smells': test_smells,
|
|
190
|
+
'quality_score': self._calculate_quality_score(
|
|
191
|
+
avg_assertions, isolation_score, naming_quality, test_smells
|
|
192
|
+
)
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
def _count_assertions(self, test_code: str) -> int:
|
|
196
|
+
"""Count assertion statements."""
|
|
197
|
+
# Common assertion patterns
|
|
198
|
+
patterns = [
|
|
199
|
+
r'\bassert[A-Z]\w*\(', # JUnit: assertTrue, assertEquals
|
|
200
|
+
r'\bexpect\(', # Jest/Vitest: expect()
|
|
201
|
+
r'\bassert\s+', # Python: assert
|
|
202
|
+
r'\.should\.', # Chai: should
|
|
203
|
+
r'\.to\.', # Chai: expect().to
|
|
204
|
+
]
|
|
205
|
+
|
|
206
|
+
count = 0
|
|
207
|
+
for pattern in patterns:
|
|
208
|
+
count += len(re.findall(pattern, test_code))
|
|
209
|
+
|
|
210
|
+
return count
|
|
211
|
+
|
|
212
|
+
def _count_test_functions(self, test_code: str) -> int:
|
|
213
|
+
"""Count test functions."""
|
|
214
|
+
patterns = [
|
|
215
|
+
r'\btest_\w+', # Python: test_*
|
|
216
|
+
r'\bit\(', # Jest/Mocha: it()
|
|
217
|
+
r'\btest\(', # Jest: test()
|
|
218
|
+
r'@Test', # JUnit: @Test
|
|
219
|
+
r'\bdef test_', # Python def test_
|
|
220
|
+
]
|
|
221
|
+
|
|
222
|
+
count = 0
|
|
223
|
+
for pattern in patterns:
|
|
224
|
+
count += len(re.findall(pattern, test_code))
|
|
225
|
+
|
|
226
|
+
return max(1, count) # At least 1 to avoid division by zero
|
|
227
|
+
|
|
228
|
+
def _isolation_score(self, test_code: str) -> float:
|
|
229
|
+
"""
|
|
230
|
+
Calculate test isolation score (0-100).
|
|
231
|
+
|
|
232
|
+
Higher score = better isolation (fewer shared dependencies)
|
|
233
|
+
"""
|
|
234
|
+
score = 100.0
|
|
235
|
+
|
|
236
|
+
# Penalize global state
|
|
237
|
+
globals_used = len(re.findall(r'\bglobal\s+\w+', test_code))
|
|
238
|
+
score -= globals_used * 10
|
|
239
|
+
|
|
240
|
+
# Penalize shared setup without proper cleanup
|
|
241
|
+
setup_count = len(re.findall(r'beforeAll|beforeEach|setUp', test_code))
|
|
242
|
+
cleanup_count = len(re.findall(r'afterAll|afterEach|tearDown', test_code))
|
|
243
|
+
if setup_count > cleanup_count:
|
|
244
|
+
score -= (setup_count - cleanup_count) * 5
|
|
245
|
+
|
|
246
|
+
# Reward mocking
|
|
247
|
+
mocks = len(re.findall(r'mock|stub|spy', test_code, re.IGNORECASE))
|
|
248
|
+
score += min(mocks * 2, 10)
|
|
249
|
+
|
|
250
|
+
return max(0.0, min(100.0, score))
|
|
251
|
+
|
|
252
|
+
def _naming_quality(self, test_code: str) -> float:
|
|
253
|
+
"""
|
|
254
|
+
Calculate test naming quality score (0-100).
|
|
255
|
+
|
|
256
|
+
Better names are descriptive and follow conventions.
|
|
257
|
+
"""
|
|
258
|
+
test_names = re.findall(r'(?:it|test|def test_)\s*\(?\s*["\']?([^"\')\n]+)', test_code)
|
|
259
|
+
|
|
260
|
+
if not test_names:
|
|
261
|
+
return 50.0
|
|
262
|
+
|
|
263
|
+
score = 0
|
|
264
|
+
for name in test_names:
|
|
265
|
+
name_score = 0
|
|
266
|
+
|
|
267
|
+
# Check length (too short or too long is bad)
|
|
268
|
+
if 20 <= len(name) <= 80:
|
|
269
|
+
name_score += 30
|
|
270
|
+
elif 10 <= len(name) < 20 or 80 < len(name) <= 100:
|
|
271
|
+
name_score += 15
|
|
272
|
+
|
|
273
|
+
# Check for descriptive words
|
|
274
|
+
descriptive_words = ['should', 'when', 'given', 'returns', 'throws', 'handles']
|
|
275
|
+
if any(word in name.lower() for word in descriptive_words):
|
|
276
|
+
name_score += 30
|
|
277
|
+
|
|
278
|
+
# Check for underscores or camelCase (not just letters)
|
|
279
|
+
if '_' in name or re.search(r'[a-z][A-Z]', name):
|
|
280
|
+
name_score += 20
|
|
281
|
+
|
|
282
|
+
# Avoid generic names
|
|
283
|
+
generic = ['test1', 'test2', 'testit', 'mytest']
|
|
284
|
+
if name.lower() not in generic:
|
|
285
|
+
name_score += 20
|
|
286
|
+
|
|
287
|
+
score += name_score
|
|
288
|
+
|
|
289
|
+
return min(100.0, score / len(test_names))
|
|
290
|
+
|
|
291
|
+
def _detect_test_smells(self, test_code: str) -> List[Dict[str, str]]:
|
|
292
|
+
"""Detect common test smells."""
|
|
293
|
+
smells = []
|
|
294
|
+
|
|
295
|
+
# Test smell 1: No assertions
|
|
296
|
+
if 'assert' not in test_code.lower() and 'expect' not in test_code.lower():
|
|
297
|
+
smells.append({
|
|
298
|
+
'smell': 'missing_assertions',
|
|
299
|
+
'description': 'Tests without assertions',
|
|
300
|
+
'severity': 'high'
|
|
301
|
+
})
|
|
302
|
+
|
|
303
|
+
# Test smell 2: Too many assertions
|
|
304
|
+
test_count = self._count_test_functions(test_code)
|
|
305
|
+
assertion_count = self._count_assertions(test_code)
|
|
306
|
+
avg_assertions = assertion_count / test_count if test_count > 0 else 0
|
|
307
|
+
if avg_assertions > 5:
|
|
308
|
+
smells.append({
|
|
309
|
+
'smell': 'assertion_roulette',
|
|
310
|
+
'description': f'Too many assertions per test (avg: {avg_assertions:.1f})',
|
|
311
|
+
'severity': 'medium'
|
|
312
|
+
})
|
|
313
|
+
|
|
314
|
+
# Test smell 3: Sleeps in tests
|
|
315
|
+
if 'sleep' in test_code.lower() or 'wait' in test_code.lower():
|
|
316
|
+
smells.append({
|
|
317
|
+
'smell': 'sleepy_test',
|
|
318
|
+
'description': 'Tests using sleep/wait (potential flakiness)',
|
|
319
|
+
'severity': 'high'
|
|
320
|
+
})
|
|
321
|
+
|
|
322
|
+
# Test smell 4: Conditional logic in tests
|
|
323
|
+
if re.search(r'\bif\s*\(', test_code):
|
|
324
|
+
smells.append({
|
|
325
|
+
'smell': 'conditional_test_logic',
|
|
326
|
+
'description': 'Tests contain conditional logic',
|
|
327
|
+
'severity': 'medium'
|
|
328
|
+
})
|
|
329
|
+
|
|
330
|
+
return smells
|
|
331
|
+
|
|
332
|
+
def _calculate_quality_score(
|
|
333
|
+
self,
|
|
334
|
+
avg_assertions: float,
|
|
335
|
+
isolation: float,
|
|
336
|
+
naming: float,
|
|
337
|
+
smells: List[Dict[str, str]]
|
|
338
|
+
) -> float:
|
|
339
|
+
"""Calculate overall test quality score."""
|
|
340
|
+
score = 0.0
|
|
341
|
+
|
|
342
|
+
# Assertions (30 points)
|
|
343
|
+
if 1 <= avg_assertions <= 3:
|
|
344
|
+
score += 30
|
|
345
|
+
elif 0 < avg_assertions < 1 or 3 < avg_assertions <= 5:
|
|
346
|
+
score += 20
|
|
347
|
+
else:
|
|
348
|
+
score += 10
|
|
349
|
+
|
|
350
|
+
# Isolation (30 points)
|
|
351
|
+
score += isolation * 0.3
|
|
352
|
+
|
|
353
|
+
# Naming (20 points)
|
|
354
|
+
score += naming * 0.2
|
|
355
|
+
|
|
356
|
+
# Smells (20 points - deduct based on severity)
|
|
357
|
+
smell_penalty = 0
|
|
358
|
+
for smell in smells:
|
|
359
|
+
if smell['severity'] == 'high':
|
|
360
|
+
smell_penalty += 10
|
|
361
|
+
elif smell['severity'] == 'medium':
|
|
362
|
+
smell_penalty += 5
|
|
363
|
+
else:
|
|
364
|
+
smell_penalty += 2
|
|
365
|
+
|
|
366
|
+
score = max(0, score - smell_penalty)
|
|
367
|
+
|
|
368
|
+
return round(min(100.0, score), 2)
|
|
369
|
+
|
|
370
|
+
def analyze_execution_metrics(
|
|
371
|
+
self,
|
|
372
|
+
execution_data: Dict[str, Any]
|
|
373
|
+
) -> Dict[str, Any]:
|
|
374
|
+
"""
|
|
375
|
+
Analyze test execution metrics.
|
|
376
|
+
|
|
377
|
+
Args:
|
|
378
|
+
execution_data: Test execution results with timing
|
|
379
|
+
|
|
380
|
+
Returns:
|
|
381
|
+
Execution analysis
|
|
382
|
+
"""
|
|
383
|
+
tests = execution_data.get('tests', [])
|
|
384
|
+
|
|
385
|
+
if not tests:
|
|
386
|
+
return {}
|
|
387
|
+
|
|
388
|
+
# Calculate timing statistics
|
|
389
|
+
timings = [test.get('duration', 0) for test in tests]
|
|
390
|
+
total_time = sum(timings)
|
|
391
|
+
avg_time = total_time / len(tests) if tests else 0
|
|
392
|
+
|
|
393
|
+
# Identify slow tests (>100ms for unit tests)
|
|
394
|
+
slow_tests = [
|
|
395
|
+
test for test in tests
|
|
396
|
+
if test.get('duration', 0) > 100
|
|
397
|
+
]
|
|
398
|
+
|
|
399
|
+
# Identify flaky tests (if failure history available)
|
|
400
|
+
flaky_tests = [
|
|
401
|
+
test for test in tests
|
|
402
|
+
if test.get('failure_rate', 0) > 0.1 # Failed >10% of time
|
|
403
|
+
]
|
|
404
|
+
|
|
405
|
+
return {
|
|
406
|
+
'total_tests': len(tests),
|
|
407
|
+
'total_time_ms': round(total_time, 2),
|
|
408
|
+
'avg_time_ms': round(avg_time, 2),
|
|
409
|
+
'slow_tests': len(slow_tests),
|
|
410
|
+
'slow_test_details': slow_tests[:5], # Top 5
|
|
411
|
+
'flaky_tests': len(flaky_tests),
|
|
412
|
+
'flaky_test_details': flaky_tests,
|
|
413
|
+
'pass_rate': self._calculate_pass_rate(tests)
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
def _calculate_pass_rate(self, tests: List[Dict[str, Any]]) -> float:
|
|
417
|
+
"""Calculate test pass rate."""
|
|
418
|
+
if not tests:
|
|
419
|
+
return 0.0
|
|
420
|
+
|
|
421
|
+
passed = sum(1 for test in tests if test.get('status') == 'passed')
|
|
422
|
+
return round((passed / len(tests)) * 100, 2)
|
|
423
|
+
|
|
424
|
+
def generate_metrics_summary(self) -> str:
|
|
425
|
+
"""Generate human-readable metrics summary."""
|
|
426
|
+
if not self.metrics:
|
|
427
|
+
return "No metrics calculated yet."
|
|
428
|
+
|
|
429
|
+
lines = ["# Test Metrics Summary\n"]
|
|
430
|
+
|
|
431
|
+
# Complexity
|
|
432
|
+
if 'complexity' in self.metrics:
|
|
433
|
+
comp = self.metrics['complexity']
|
|
434
|
+
lines.append(f"## Code Complexity")
|
|
435
|
+
lines.append(f"- Cyclomatic Complexity: {comp['cyclomatic_complexity']}")
|
|
436
|
+
lines.append(f"- Cognitive Complexity: {comp['cognitive_complexity']}")
|
|
437
|
+
lines.append(f"- Testability Score: {comp['testability_score']:.1f}/100")
|
|
438
|
+
lines.append(f"- Assessment: {comp['assessment']}\n")
|
|
439
|
+
|
|
440
|
+
# Test Quality
|
|
441
|
+
if 'test_quality' in self.metrics:
|
|
442
|
+
qual = self.metrics['test_quality']
|
|
443
|
+
lines.append(f"## Test Quality")
|
|
444
|
+
lines.append(f"- Total Tests: {qual['total_tests']}")
|
|
445
|
+
lines.append(f"- Assertions per Test: {qual['avg_assertions_per_test']}")
|
|
446
|
+
lines.append(f"- Isolation Score: {qual['isolation_score']:.1f}/100")
|
|
447
|
+
lines.append(f"- Naming Quality: {qual['naming_quality']:.1f}/100")
|
|
448
|
+
lines.append(f"- Quality Score: {qual['quality_score']:.1f}/100\n")
|
|
449
|
+
|
|
450
|
+
if qual['test_smells']:
|
|
451
|
+
lines.append(f"### Test Smells Detected:")
|
|
452
|
+
for smell in qual['test_smells']:
|
|
453
|
+
lines.append(f"- {smell['description']} (severity: {smell['severity']})")
|
|
454
|
+
lines.append("")
|
|
455
|
+
|
|
456
|
+
return "\n".join(lines)
|