@planu/cli 0.23.2 → 0.25.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/config/ai-model-pricing.json +81 -0
- package/dist/config/framework-registry/csharp-aspnet.json +67 -0
- package/dist/config/framework-registry/dart-flutter.json +61 -0
- package/dist/config/framework-registry/go-gin.json +62 -0
- package/dist/config/framework-registry/index.json +164 -0
- package/dist/config/framework-registry/java-springboot.json +67 -0
- package/dist/config/framework-registry/php-laravel.json +67 -0
- package/dist/config/framework-registry/python-django.json +72 -0
- package/dist/config/framework-registry/python-fastapi.json +72 -0
- package/dist/config/framework-registry/ruby-rails.json +67 -0
- package/dist/config/framework-registry/rust-actix.json +61 -0
- package/dist/config/framework-registry/swift-swiftui.json +67 -0
- package/dist/config/framework-registry/typescript-angular.json +67 -0
- package/dist/config/framework-registry/typescript-astro.json +61 -0
- package/dist/config/framework-registry/typescript-express.json +67 -0
- package/dist/config/framework-registry/typescript-nestjs.json +62 -0
- package/dist/config/framework-registry/typescript-nextjs.json +82 -0
- package/dist/config/framework-registry/typescript-nuxt.json +67 -0
- package/dist/config/framework-registry/typescript-react.json +77 -0
- package/dist/config/framework-registry/typescript-remix.json +61 -0
- package/dist/config/framework-registry/typescript-sveltekit.json +67 -0
- package/dist/config/framework-registry/typescript-vue.json +72 -0
- package/dist/config/license-plans.json +23 -3
- package/dist/engine/agile-config-builder.d.ts.map +1 -1
- package/dist/engine/agile-config-builder.js +3 -0
- package/dist/engine/agile-config-builder.js.map +1 -1
- package/dist/engine/ai-cost-estimator/core.d.ts +8 -0
- package/dist/engine/ai-cost-estimator/core.d.ts.map +1 -0
- package/dist/engine/ai-cost-estimator/core.js +257 -0
- package/dist/engine/ai-cost-estimator/core.js.map +1 -0
- package/dist/engine/ai-cost-estimator/index.d.ts +4 -0
- package/dist/engine/ai-cost-estimator/index.d.ts.map +1 -0
- package/dist/engine/ai-cost-estimator/index.js +5 -0
- package/dist/engine/ai-cost-estimator/index.js.map +1 -0
- package/dist/engine/ai-cost-estimator/model-pricing.d.ts +31 -0
- package/dist/engine/ai-cost-estimator/model-pricing.d.ts.map +1 -0
- package/dist/engine/ai-cost-estimator/model-pricing.js +96 -0
- package/dist/engine/ai-cost-estimator/model-pricing.js.map +1 -0
- package/dist/engine/ai-cost-estimator/token-estimator.d.ts +37 -0
- package/dist/engine/ai-cost-estimator/token-estimator.d.ts.map +1 -0
- package/dist/engine/ai-cost-estimator/token-estimator.js +194 -0
- package/dist/engine/ai-cost-estimator/token-estimator.js.map +1 -0
- package/dist/engine/ci-generator/context-builders.d.ts +4 -0
- package/dist/engine/ci-generator/context-builders.d.ts.map +1 -0
- package/dist/engine/ci-generator/context-builders.js +129 -0
- package/dist/engine/ci-generator/context-builders.js.map +1 -0
- package/dist/engine/ci-generator/index.d.ts +7 -0
- package/dist/engine/ci-generator/index.d.ts.map +1 -0
- package/dist/engine/ci-generator/index.js +44 -0
- package/dist/engine/ci-generator/index.js.map +1 -0
- package/dist/engine/ci-generator/stack-detector.d.ts +21 -0
- package/dist/engine/ci-generator/stack-detector.d.ts.map +1 -0
- package/dist/engine/ci-generator/stack-detector.js +203 -0
- package/dist/engine/ci-generator/stack-detector.js.map +1 -0
- package/dist/engine/ci-generator/yaml-builder.d.ts +8 -0
- package/dist/engine/ci-generator/yaml-builder.d.ts.map +1 -0
- package/dist/engine/ci-generator/yaml-builder.js +285 -0
- package/dist/engine/ci-generator/yaml-builder.js.map +1 -0
- package/dist/engine/dashboard/data-loader.d.ts +21 -0
- package/dist/engine/dashboard/data-loader.d.ts.map +1 -0
- package/dist/engine/dashboard/data-loader.js +196 -0
- package/dist/engine/dashboard/data-loader.js.map +1 -0
- package/dist/engine/dashboard/index.d.ts +5 -0
- package/dist/engine/dashboard/index.d.ts.map +1 -0
- package/dist/engine/dashboard/index.js +6 -0
- package/dist/engine/dashboard/index.js.map +1 -0
- package/dist/engine/dashboard/routes.d.ts +4 -0
- package/dist/engine/dashboard/routes.d.ts.map +1 -0
- package/dist/engine/dashboard/routes.js +120 -0
- package/dist/engine/dashboard/routes.js.map +1 -0
- package/dist/engine/dashboard/server.d.ts +14 -0
- package/dist/engine/dashboard/server.d.ts.map +1 -0
- package/dist/engine/dashboard/server.js +88 -0
- package/dist/engine/dashboard/server.js.map +1 -0
- package/dist/engine/dashboard/templates-layout.d.ts +11 -0
- package/dist/engine/dashboard/templates-layout.d.ts.map +1 -0
- package/dist/engine/dashboard/templates-layout.js +305 -0
- package/dist/engine/dashboard/templates-layout.js.map +1 -0
- package/dist/engine/dashboard/templates-project.d.ts +10 -0
- package/dist/engine/dashboard/templates-project.d.ts.map +1 -0
- package/dist/engine/dashboard/templates-project.js +163 -0
- package/dist/engine/dashboard/templates-project.js.map +1 -0
- package/dist/engine/dashboard/templates.d.ts +3 -0
- package/dist/engine/dashboard/templates.d.ts.map +1 -0
- package/dist/engine/dashboard/templates.js +4 -0
- package/dist/engine/dashboard/templates.js.map +1 -0
- package/dist/engine/focus-tracker.d.ts.map +1 -1
- package/dist/engine/focus-tracker.js +1 -0
- package/dist/engine/focus-tracker.js.map +1 -1
- package/dist/engine/hooks/core.d.ts +26 -0
- package/dist/engine/hooks/core.d.ts.map +1 -0
- package/dist/engine/hooks/core.js +164 -0
- package/dist/engine/hooks/core.js.map +1 -0
- package/dist/engine/hooks/git-hook-generator.d.ts +14 -0
- package/dist/engine/hooks/git-hook-generator.d.ts.map +1 -0
- package/dist/engine/hooks/git-hook-generator.js +119 -0
- package/dist/engine/hooks/git-hook-generator.js.map +1 -0
- package/dist/engine/hooks/index.d.ts +5 -0
- package/dist/engine/hooks/index.d.ts.map +1 -0
- package/dist/engine/hooks/index.js +6 -0
- package/dist/engine/hooks/index.js.map +1 -0
- package/dist/engine/hooks/templates.d.ts +14 -0
- package/dist/engine/hooks/templates.d.ts.map +1 -0
- package/dist/engine/hooks/templates.js +138 -0
- package/dist/engine/hooks/templates.js.map +1 -0
- package/dist/engine/hooks/triggers.d.ts +27 -0
- package/dist/engine/hooks/triggers.d.ts.map +1 -0
- package/dist/engine/hooks/triggers.js +104 -0
- package/dist/engine/hooks/triggers.js.map +1 -0
- package/dist/engine/license-validator/core.d.ts +1 -0
- package/dist/engine/license-validator/core.d.ts.map +1 -1
- package/dist/engine/license-validator/core.js +10 -1
- package/dist/engine/license-validator/core.js.map +1 -1
- package/dist/engine/license-validator/fingerprint.d.ts +3 -0
- package/dist/engine/license-validator/fingerprint.d.ts.map +1 -0
- package/dist/engine/license-validator/fingerprint.js +17 -0
- package/dist/engine/license-validator/fingerprint.js.map +1 -0
- package/dist/engine/license-validator.d.ts +2 -1
- package/dist/engine/license-validator.d.ts.map +1 -1
- package/dist/engine/license-validator.js +2 -1
- package/dist/engine/license-validator.js.map +1 -1
- package/dist/engine/registry/core.d.ts +32 -0
- package/dist/engine/registry/core.d.ts.map +1 -0
- package/dist/engine/registry/core.js +85 -0
- package/dist/engine/registry/core.js.map +1 -0
- package/dist/engine/registry/index.d.ts +6 -0
- package/dist/engine/registry/index.d.ts.map +1 -0
- package/dist/engine/registry/index.js +8 -0
- package/dist/engine/registry/index.js.map +1 -0
- package/dist/engine/registry/loader.d.ts +18 -0
- package/dist/engine/registry/loader.d.ts.map +1 -0
- package/dist/engine/registry/loader.js +81 -0
- package/dist/engine/registry/loader.js.map +1 -0
- package/dist/engine/registry/matcher.d.ts +19 -0
- package/dist/engine/registry/matcher.d.ts.map +1 -0
- package/dist/engine/registry/matcher.js +150 -0
- package/dist/engine/registry/matcher.js.map +1 -0
- package/dist/engine/registry/reporter.d.ts +10 -0
- package/dist/engine/registry/reporter.d.ts.map +1 -0
- package/dist/engine/registry/reporter.js +132 -0
- package/dist/engine/registry/reporter.js.map +1 -0
- package/dist/engine/registry/validator.d.ts +17 -0
- package/dist/engine/registry/validator.d.ts.map +1 -0
- package/dist/engine/registry/validator.js +103 -0
- package/dist/engine/registry/validator.js.map +1 -0
- package/dist/engine/spec-changelog/core.d.ts +16 -0
- package/dist/engine/spec-changelog/core.d.ts.map +1 -0
- package/dist/engine/spec-changelog/core.js +175 -0
- package/dist/engine/spec-changelog/core.js.map +1 -0
- package/dist/engine/spec-changelog/diff.d.ts +18 -0
- package/dist/engine/spec-changelog/diff.d.ts.map +1 -0
- package/dist/engine/spec-changelog/diff.js +116 -0
- package/dist/engine/spec-changelog/diff.js.map +1 -0
- package/dist/engine/spec-changelog/index.d.ts +3 -0
- package/dist/engine/spec-changelog/index.d.ts.map +1 -0
- package/dist/engine/spec-changelog/index.js +4 -0
- package/dist/engine/spec-changelog/index.js.map +1 -0
- package/dist/engine/spec-coverage/core.d.ts +14 -0
- package/dist/engine/spec-coverage/core.d.ts.map +1 -0
- package/dist/engine/spec-coverage/core.js +132 -0
- package/dist/engine/spec-coverage/core.js.map +1 -0
- package/dist/engine/spec-coverage/criteria-mapper.d.ts +18 -0
- package/dist/engine/spec-coverage/criteria-mapper.d.ts.map +1 -0
- package/dist/engine/spec-coverage/criteria-mapper.js +306 -0
- package/dist/engine/spec-coverage/criteria-mapper.js.map +1 -0
- package/dist/engine/spec-coverage/index.d.ts +4 -0
- package/dist/engine/spec-coverage/index.d.ts.map +1 -0
- package/dist/engine/spec-coverage/index.js +5 -0
- package/dist/engine/spec-coverage/index.js.map +1 -0
- package/dist/engine/spec-coverage/test-finder.d.ts +17 -0
- package/dist/engine/spec-coverage/test-finder.d.ts.map +1 -0
- package/dist/engine/spec-coverage/test-finder.js +250 -0
- package/dist/engine/spec-coverage/test-finder.js.map +1 -0
- package/dist/engine/spec-templates/catalog-extra.d.ts +4 -0
- package/dist/engine/spec-templates/catalog-extra.d.ts.map +1 -0
- package/dist/engine/spec-templates/catalog-extra.js +367 -0
- package/dist/engine/spec-templates/catalog-extra.js.map +1 -0
- package/dist/engine/spec-templates/catalog.d.ts +4 -0
- package/dist/engine/spec-templates/catalog.d.ts.map +1 -0
- package/dist/engine/spec-templates/catalog.js +386 -0
- package/dist/engine/spec-templates/catalog.js.map +1 -0
- package/dist/engine/spec-templates/index.d.ts +4 -0
- package/dist/engine/spec-templates/index.d.ts.map +1 -0
- package/dist/engine/spec-templates/index.js +5 -0
- package/dist/engine/spec-templates/index.js.map +1 -0
- package/dist/engine/spec-templates/query.d.ts +14 -0
- package/dist/engine/spec-templates/query.d.ts.map +1 -0
- package/dist/engine/spec-templates/query.js +56 -0
- package/dist/engine/spec-templates/query.js.map +1 -0
- package/dist/engine/spec-templates/renderer.d.ts +19 -0
- package/dist/engine/spec-templates/renderer.d.ts.map +1 -0
- package/dist/engine/spec-templates/renderer.js +45 -0
- package/dist/engine/spec-templates/renderer.js.map +1 -0
- package/dist/engine/usage-tracker/trial.d.ts +4 -4
- package/dist/engine/usage-tracker/trial.d.ts.map +1 -1
- package/dist/engine/usage-tracker/trial.js +4 -4
- package/dist/engine/usage-tracker/trial.js.map +1 -1
- package/dist/engine/webhook/event-handlers.d.ts +25 -0
- package/dist/engine/webhook/event-handlers.d.ts.map +1 -0
- package/dist/engine/webhook/event-handlers.js +89 -0
- package/dist/engine/webhook/event-handlers.js.map +1 -0
- package/dist/engine/webhook/index.d.ts +4 -0
- package/dist/engine/webhook/index.d.ts.map +1 -0
- package/dist/engine/webhook/index.js +5 -0
- package/dist/engine/webhook/index.js.map +1 -0
- package/dist/engine/webhook/server.d.ts +18 -0
- package/dist/engine/webhook/server.d.ts.map +1 -0
- package/dist/engine/webhook/server.js +187 -0
- package/dist/engine/webhook/server.js.map +1 -0
- package/dist/engine/webhook/signature.d.ts +16 -0
- package/dist/engine/webhook/signature.d.ts.map +1 -0
- package/dist/engine/webhook/signature.js +49 -0
- package/dist/engine/webhook/signature.js.map +1 -0
- package/dist/index.js +18 -0
- package/dist/index.js.map +1 -1
- package/dist/storage/hooks-store.d.ts +34 -0
- package/dist/storage/hooks-store.d.ts.map +1 -0
- package/dist/storage/hooks-store.js +128 -0
- package/dist/storage/hooks-store.js.map +1 -0
- package/dist/storage/index.d.ts +1 -0
- package/dist/storage/index.d.ts.map +1 -1
- package/dist/storage/index.js +1 -0
- package/dist/storage/index.js.map +1 -1
- package/dist/tools/activate-license.d.ts.map +1 -1
- package/dist/tools/activate-license.js +5 -2
- package/dist/tools/activate-license.js.map +1 -1
- package/dist/tools/check-spec-accuracy.d.ts +7 -0
- package/dist/tools/check-spec-accuracy.d.ts.map +1 -0
- package/dist/tools/check-spec-accuracy.js +28 -0
- package/dist/tools/check-spec-accuracy.js.map +1 -0
- package/dist/tools/ci-generator.d.ts +7 -0
- package/dist/tools/ci-generator.d.ts.map +1 -0
- package/dist/tools/ci-generator.js +49 -0
- package/dist/tools/ci-generator.js.map +1 -0
- package/dist/tools/create-spec.d.ts.map +1 -1
- package/dist/tools/create-spec.js +4 -0
- package/dist/tools/create-spec.js.map +1 -1
- package/dist/tools/dashboard.d.ts +6 -0
- package/dist/tools/dashboard.d.ts.map +1 -0
- package/dist/tools/dashboard.js +48 -0
- package/dist/tools/dashboard.js.map +1 -0
- package/dist/tools/detect-drift.d.ts.map +1 -1
- package/dist/tools/detect-drift.js +6 -0
- package/dist/tools/detect-drift.js.map +1 -1
- package/dist/tools/estimate-ai-cost.d.ts +8 -0
- package/dist/tools/estimate-ai-cost.d.ts.map +1 -0
- package/dist/tools/estimate-ai-cost.js +29 -0
- package/dist/tools/estimate-ai-cost.js.map +1 -0
- package/dist/tools/license-gate.d.ts.map +1 -1
- package/dist/tools/license-gate.js +27 -20
- package/dist/tools/license-gate.js.map +1 -1
- package/dist/tools/license-status.d.ts.map +1 -1
- package/dist/tools/license-status.js +3 -0
- package/dist/tools/license-status.js.map +1 -1
- package/dist/tools/list-specs.d.ts.map +1 -1
- package/dist/tools/list-specs.js +15 -0
- package/dist/tools/list-specs.js.map +1 -1
- package/dist/tools/manage-hooks.d.ts +5 -0
- package/dist/tools/manage-hooks.d.ts.map +1 -0
- package/dist/tools/manage-hooks.js +247 -0
- package/dist/tools/manage-hooks.js.map +1 -0
- package/dist/tools/reconcile-spec.d.ts.map +1 -1
- package/dist/tools/reconcile-spec.js +24 -0
- package/dist/tools/reconcile-spec.js.map +1 -1
- package/dist/tools/register-ai-cost-tools.d.ts +3 -0
- package/dist/tools/register-ai-cost-tools.d.ts.map +1 -0
- package/dist/tools/register-ai-cost-tools.js +25 -0
- package/dist/tools/register-ai-cost-tools.js.map +1 -0
- package/dist/tools/register-changelog-tools.d.ts +3 -0
- package/dist/tools/register-changelog-tools.d.ts.map +1 -0
- package/dist/tools/register-changelog-tools.js +23 -0
- package/dist/tools/register-changelog-tools.js.map +1 -0
- package/dist/tools/register-ci-tools.d.ts +3 -0
- package/dist/tools/register-ci-tools.d.ts.map +1 -0
- package/dist/tools/register-ci-tools.js +50 -0
- package/dist/tools/register-ci-tools.js.map +1 -0
- package/dist/tools/register-coverage-tools.d.ts +7 -0
- package/dist/tools/register-coverage-tools.d.ts.map +1 -0
- package/dist/tools/register-coverage-tools.js +27 -0
- package/dist/tools/register-coverage-tools.js.map +1 -0
- package/dist/tools/register-dashboard-tools.d.ts +3 -0
- package/dist/tools/register-dashboard-tools.d.ts.map +1 -0
- package/dist/tools/register-dashboard-tools.js +29 -0
- package/dist/tools/register-dashboard-tools.js.map +1 -0
- package/dist/tools/register-hooks-tools.d.ts +3 -0
- package/dist/tools/register-hooks-tools.d.ts.map +1 -0
- package/dist/tools/register-hooks-tools.js +107 -0
- package/dist/tools/register-hooks-tools.js.map +1 -0
- package/dist/tools/register-registry-tools.d.ts +3 -0
- package/dist/tools/register-registry-tools.d.ts.map +1 -0
- package/dist/tools/register-registry-tools.js +43 -0
- package/dist/tools/register-registry-tools.js.map +1 -0
- package/dist/tools/register-template-tools.d.ts +8 -0
- package/dist/tools/register-template-tools.d.ts.map +1 -0
- package/dist/tools/register-template-tools.js +71 -0
- package/dist/tools/register-template-tools.js.map +1 -0
- package/dist/tools/register-webhook-tools.d.ts +3 -0
- package/dist/tools/register-webhook-tools.d.ts.map +1 -0
- package/dist/tools/register-webhook-tools.js +49 -0
- package/dist/tools/register-webhook-tools.js.map +1 -0
- package/dist/tools/schemas/index.d.ts +1 -0
- package/dist/tools/schemas/index.d.ts.map +1 -1
- package/dist/tools/schemas/index.js +1 -0
- package/dist/tools/schemas/index.js.map +1 -1
- package/dist/tools/schemas/registry.d.ts +41 -0
- package/dist/tools/schemas/registry.d.ts.map +1 -0
- package/dist/tools/schemas/registry.js +62 -0
- package/dist/tools/schemas/registry.js.map +1 -0
- package/dist/tools/spec-coverage.d.ts +3 -0
- package/dist/tools/spec-coverage.d.ts.map +1 -0
- package/dist/tools/spec-coverage.js +176 -0
- package/dist/tools/spec-coverage.js.map +1 -0
- package/dist/tools/spec-history.d.ts +3 -0
- package/dist/tools/spec-history.d.ts.map +1 -0
- package/dist/tools/spec-history.js +67 -0
- package/dist/tools/spec-history.js.map +1 -0
- package/dist/tools/spec-templates.d.ts +10 -0
- package/dist/tools/spec-templates.d.ts.map +1 -0
- package/dist/tools/spec-templates.js +155 -0
- package/dist/tools/spec-templates.js.map +1 -0
- package/dist/tools/update-registry.d.ts +8 -0
- package/dist/tools/update-registry.d.ts.map +1 -0
- package/dist/tools/update-registry.js +53 -0
- package/dist/tools/update-registry.js.map +1 -0
- package/dist/tools/update-status.d.ts.map +1 -1
- package/dist/tools/update-status.js +24 -0
- package/dist/tools/update-status.js.map +1 -1
- package/dist/tools/webhook.d.ts +6 -0
- package/dist/tools/webhook.d.ts.map +1 -0
- package/dist/tools/webhook.js +150 -0
- package/dist/tools/webhook.js.map +1 -0
- package/dist/types/ai-cost.d.ts +98 -0
- package/dist/types/ai-cost.d.ts.map +1 -0
- package/dist/types/ai-cost.js +4 -0
- package/dist/types/ai-cost.js.map +1 -0
- package/dist/types/analysis.d.ts +64 -0
- package/dist/types/analysis.d.ts.map +1 -1
- package/dist/types/changelog.d.ts +49 -0
- package/dist/types/changelog.d.ts.map +1 -0
- package/dist/types/changelog.js +3 -0
- package/dist/types/changelog.js.map +1 -0
- package/dist/types/ci.d.ts +105 -0
- package/dist/types/ci.d.ts.map +1 -0
- package/dist/types/ci.js +3 -0
- package/dist/types/ci.js.map +1 -0
- package/dist/types/coverage.d.ts +95 -0
- package/dist/types/coverage.d.ts.map +1 -0
- package/dist/types/coverage.js +4 -0
- package/dist/types/coverage.js.map +1 -0
- package/dist/types/hooks.d.ts +139 -0
- package/dist/types/hooks.d.ts.map +1 -0
- package/dist/types/hooks.js +3 -0
- package/dist/types/hooks.js.map +1 -0
- package/dist/types/index.d.ts +8 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js +8 -0
- package/dist/types/index.js.map +1 -1
- package/dist/types/licensing.d.ts +6 -0
- package/dist/types/licensing.d.ts.map +1 -1
- package/dist/types/registry.d.ts +90 -0
- package/dist/types/registry.d.ts.map +1 -0
- package/dist/types/registry.js +5 -0
- package/dist/types/registry.js.map +1 -0
- package/dist/types/spec-templates.d.ts +87 -0
- package/dist/types/spec-templates.d.ts.map +1 -0
- package/dist/types/spec-templates.js +3 -0
- package/dist/types/spec-templates.js.map +1 -0
- package/dist/types/ui.d.ts +76 -0
- package/dist/types/ui.d.ts.map +1 -1
- package/dist/types/webhook.d.ts +62 -0
- package/dist/types/webhook.d.ts.map +1 -0
- package/dist/types/webhook.js +4 -0
- package/dist/types/webhook.js.map +1 -0
- package/package.json +1 -1
- package/src/config/ai-model-pricing.json +81 -0
- package/src/config/framework-registry/csharp-aspnet.json +67 -0
- package/src/config/framework-registry/dart-flutter.json +61 -0
- package/src/config/framework-registry/go-gin.json +62 -0
- package/src/config/framework-registry/index.json +164 -0
- package/src/config/framework-registry/java-springboot.json +67 -0
- package/src/config/framework-registry/php-laravel.json +67 -0
- package/src/config/framework-registry/python-django.json +72 -0
- package/src/config/framework-registry/python-fastapi.json +72 -0
- package/src/config/framework-registry/ruby-rails.json +67 -0
- package/src/config/framework-registry/rust-actix.json +61 -0
- package/src/config/framework-registry/swift-swiftui.json +67 -0
- package/src/config/framework-registry/typescript-angular.json +67 -0
- package/src/config/framework-registry/typescript-astro.json +61 -0
- package/src/config/framework-registry/typescript-express.json +67 -0
- package/src/config/framework-registry/typescript-nestjs.json +62 -0
- package/src/config/framework-registry/typescript-nextjs.json +82 -0
- package/src/config/framework-registry/typescript-nuxt.json +67 -0
- package/src/config/framework-registry/typescript-react.json +77 -0
- package/src/config/framework-registry/typescript-remix.json +61 -0
- package/src/config/framework-registry/typescript-sveltekit.json +67 -0
- package/src/config/framework-registry/typescript-vue.json +72 -0
- package/src/config/license-plans.json +23 -3
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
// engine/spec-changelog/core.ts — Changelog entry creation and persistence
|
|
2
|
+
import { readFile, writeFile } from 'node:fs/promises';
|
|
3
|
+
import { join } from 'node:path';
|
|
4
|
+
const CHANGELOG_FILENAME = 'CHANGELOG.md';
|
|
5
|
+
const CHANGELOG_VERSION_COMMENT = '<!-- changelog-version: 1 -->';
|
|
6
|
+
/** Format a single changelog entry as Markdown. */
|
|
7
|
+
export function formatEntry(entry, specId) {
|
|
8
|
+
const lines = [];
|
|
9
|
+
lines.push(`## ${entry.timestamp} — ${entry.type}`);
|
|
10
|
+
lines.push('');
|
|
11
|
+
lines.push(`**Tool**: ${entry.triggeredBy}`);
|
|
12
|
+
lines.push(`**Descripcion**: ${entry.description}`);
|
|
13
|
+
lines.push('');
|
|
14
|
+
if (entry.before !== undefined && entry.after !== undefined) {
|
|
15
|
+
if (entry.type === 'status_changed') {
|
|
16
|
+
lines.push(`**Antes**: ${entry.before.status} | **Despues**: ${entry.after.status}`);
|
|
17
|
+
lines.push(`**Progreso**: ${entry.before.completedCount}/${entry.before.criteriaCount} → ${entry.after.completedCount}/${entry.after.criteriaCount}`);
|
|
18
|
+
}
|
|
19
|
+
else {
|
|
20
|
+
lines.push(`**Criterios antes**: ${entry.before.criteriaCount} | **Criterios despues**: ${entry.after.criteriaCount}`);
|
|
21
|
+
if (entry.type === 'progress_updated') {
|
|
22
|
+
lines.push(`**Progreso**: ${entry.before.completedCount}/${entry.before.criteriaCount} → ${entry.after.completedCount}/${entry.after.criteriaCount}`);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
lines.push('');
|
|
26
|
+
}
|
|
27
|
+
if (entry.diff !== undefined) {
|
|
28
|
+
const { added, removed, modified } = entry.diff;
|
|
29
|
+
const hasCriteriaChanges = added.length > 0 || removed.length > 0 || modified.length > 0;
|
|
30
|
+
if (hasCriteriaChanges) {
|
|
31
|
+
lines.push('### Criterios modificados');
|
|
32
|
+
for (const item of added) {
|
|
33
|
+
lines.push(`\u2795 ${item}`);
|
|
34
|
+
}
|
|
35
|
+
for (const item of removed) {
|
|
36
|
+
lines.push(`\u2796 ${item}`);
|
|
37
|
+
}
|
|
38
|
+
for (const item of modified) {
|
|
39
|
+
lines.push(`\u270f\ufe0f ${item.after} (antes: ${item.before})`);
|
|
40
|
+
}
|
|
41
|
+
lines.push('');
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
lines.push('---');
|
|
45
|
+
lines.push('');
|
|
46
|
+
void specId; // referenced in header externally
|
|
47
|
+
return lines.join('\n');
|
|
48
|
+
}
|
|
49
|
+
/** Build the full CHANGELOG.md header for a spec. */
|
|
50
|
+
function buildHeader(specId, specTitle) {
|
|
51
|
+
const title = specTitle ? `${specId}: ${specTitle}` : specId;
|
|
52
|
+
return [CHANGELOG_VERSION_COMMENT, '', `# Changelog — ${title}`, '', ''].join('\n');
|
|
53
|
+
}
|
|
54
|
+
/** Parse the timestamp from the first entry in a CHANGELOG.md content. */
|
|
55
|
+
export function parseFirstEntryTimestamp(content) {
|
|
56
|
+
// Matches lines like: ## 2026-03-04T14:23:00Z — reconciled
|
|
57
|
+
const match = /^## (\d{4}-\d{2}-\d{2}T[\d:.]+Z) —/m.exec(content);
|
|
58
|
+
return match?.[1] ?? null;
|
|
59
|
+
}
|
|
60
|
+
/** Parse changelog entries from a CHANGELOG.md content string. */
|
|
61
|
+
export function parseChangelogEntries(content, specId) {
|
|
62
|
+
const entries = [];
|
|
63
|
+
// Split on section headers: ## <timestamp> — <type>
|
|
64
|
+
const sectionRegex = /^## (\d{4}-\d{2}-\d{2}T[\d:.]+Z) — (\w+)/gm;
|
|
65
|
+
const matches = [...content.matchAll(sectionRegex)];
|
|
66
|
+
for (const match of matches) {
|
|
67
|
+
const timestamp = match[1];
|
|
68
|
+
const type = match[2];
|
|
69
|
+
if (timestamp === undefined || type === undefined) {
|
|
70
|
+
continue;
|
|
71
|
+
}
|
|
72
|
+
const sectionStart = match.index;
|
|
73
|
+
const nextMatch = matches[matches.indexOf(match) + 1];
|
|
74
|
+
const sectionEnd = nextMatch?.index ?? content.length;
|
|
75
|
+
const sectionContent = content.slice(sectionStart, sectionEnd);
|
|
76
|
+
// Extract tool name
|
|
77
|
+
const toolMatch = /\*\*Tool\*\*: (.+)/.exec(sectionContent);
|
|
78
|
+
const triggeredBy = toolMatch?.[1]?.trim() ?? 'unknown';
|
|
79
|
+
// Extract description
|
|
80
|
+
const descMatch = /\*\*Descripcion\*\*: (.+)/.exec(sectionContent);
|
|
81
|
+
const description = descMatch?.[1]?.trim() ?? '';
|
|
82
|
+
entries.push({
|
|
83
|
+
timestamp,
|
|
84
|
+
type: type,
|
|
85
|
+
description,
|
|
86
|
+
triggeredBy,
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
void specId;
|
|
90
|
+
return entries;
|
|
91
|
+
}
|
|
92
|
+
/** Read the CHANGELOG.md for a spec directory. Returns null if not found. */
|
|
93
|
+
export async function readChangelog(options) {
|
|
94
|
+
const { specDir, specId } = options;
|
|
95
|
+
const filePath = join(specDir, CHANGELOG_FILENAME);
|
|
96
|
+
try {
|
|
97
|
+
const content = await readFile(filePath, 'utf-8');
|
|
98
|
+
const entries = parseChangelogEntries(content, specId);
|
|
99
|
+
return { specId, entries };
|
|
100
|
+
}
|
|
101
|
+
catch {
|
|
102
|
+
return null;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
/** Read only the timestamp of the last (most recent) changelog entry. Optimized for list_specs. */
|
|
106
|
+
export async function readLastModifiedTimestamp(specDir) {
|
|
107
|
+
const filePath = join(specDir, CHANGELOG_FILENAME);
|
|
108
|
+
try {
|
|
109
|
+
const content = await readFile(filePath, 'utf-8');
|
|
110
|
+
return parseFirstEntryTimestamp(content);
|
|
111
|
+
}
|
|
112
|
+
catch {
|
|
113
|
+
return null;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
/** Append a new entry to the CHANGELOG.md for a spec. Creates the file if it doesn't exist. */
|
|
117
|
+
export async function appendChangelogEntry(options) {
|
|
118
|
+
const { specDir, specId, entry } = options;
|
|
119
|
+
const filePath = join(specDir, CHANGELOG_FILENAME);
|
|
120
|
+
try {
|
|
121
|
+
let existingContent = '';
|
|
122
|
+
let hasHeader = false;
|
|
123
|
+
try {
|
|
124
|
+
existingContent = await readFile(filePath, 'utf-8');
|
|
125
|
+
hasHeader = existingContent.includes(CHANGELOG_VERSION_COMMENT);
|
|
126
|
+
}
|
|
127
|
+
catch {
|
|
128
|
+
// File doesn't exist yet — will create fresh
|
|
129
|
+
}
|
|
130
|
+
const entryMarkdown = formatEntry(entry, specId);
|
|
131
|
+
let newContent;
|
|
132
|
+
if (!hasHeader) {
|
|
133
|
+
newContent = buildHeader(specId) + entryMarkdown + existingContent;
|
|
134
|
+
}
|
|
135
|
+
else {
|
|
136
|
+
// Insert after the header block (after the # Changelog line)
|
|
137
|
+
const insertAfterPattern = /^# Changelog[^\n]*\n\n/m;
|
|
138
|
+
const match = insertAfterPattern.exec(existingContent);
|
|
139
|
+
if (match) {
|
|
140
|
+
const insertAt = match.index + match[0].length;
|
|
141
|
+
newContent =
|
|
142
|
+
existingContent.slice(0, insertAt) + entryMarkdown + existingContent.slice(insertAt);
|
|
143
|
+
}
|
|
144
|
+
else {
|
|
145
|
+
// Fallback: append after existing content
|
|
146
|
+
newContent = existingContent + entryMarkdown;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
await writeFile(filePath, newContent, 'utf-8');
|
|
150
|
+
return true;
|
|
151
|
+
}
|
|
152
|
+
catch (error) {
|
|
153
|
+
console.error(`[spec-changelog] Failed to write CHANGELOG.md for ${specId}:`, error);
|
|
154
|
+
return false;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
/** Format a relative date string (e.g. "hace 2 dias") for a timestamp. */
|
|
158
|
+
export function formatRelativeDate(timestamp) {
|
|
159
|
+
const date = new Date(timestamp);
|
|
160
|
+
const now = new Date();
|
|
161
|
+
const diffMs = now.getTime() - date.getTime();
|
|
162
|
+
const diffDays = Math.floor(diffMs / (1000 * 60 * 60 * 24));
|
|
163
|
+
if (diffDays === 0) {
|
|
164
|
+
return 'hoy';
|
|
165
|
+
}
|
|
166
|
+
if (diffDays === 1) {
|
|
167
|
+
return 'hace 1 dia';
|
|
168
|
+
}
|
|
169
|
+
if (diffDays <= 30) {
|
|
170
|
+
return `hace ${diffDays} dias`;
|
|
171
|
+
}
|
|
172
|
+
// Older than 30 days: return ISO date portion
|
|
173
|
+
return timestamp.slice(0, 10);
|
|
174
|
+
}
|
|
175
|
+
//# sourceMappingURL=core.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"core.js","sourceRoot":"","sources":["../../../src/engine/spec-changelog/core.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { CriteriaDiff } from '../../types/index.js';
|
|
2
|
+
/** Normalize a criteria text for comparison (trim, collapse whitespace). */
|
|
3
|
+
export declare function normalizeCriteriaText(text: string): string;
|
|
4
|
+
/**
|
|
5
|
+
* Compute a simple similarity score (0–1) between two strings.
|
|
6
|
+
* Uses character bigram overlap.
|
|
7
|
+
*/
|
|
8
|
+
export declare function similarityScore(a: string, b: string): number;
|
|
9
|
+
/**
|
|
10
|
+
* Compute semantic diff between two sets of criteria texts.
|
|
11
|
+
* Returns added, removed, and modified criteria.
|
|
12
|
+
*/
|
|
13
|
+
export declare function computeCriteriaDiff(before: string[], after: string[]): CriteriaDiff;
|
|
14
|
+
/**
|
|
15
|
+
* Returns true if the diff contains any actual changes.
|
|
16
|
+
*/
|
|
17
|
+
export declare function hasDiffChanges(diff: CriteriaDiff): boolean;
|
|
18
|
+
//# sourceMappingURL=diff.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"diff.d.ts","sourceRoot":"","sources":["../../../src/engine/spec-changelog/diff.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAEzD,4EAA4E;AAC5E,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAO1D;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CA8B5D;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,YAAY,CA0EnF;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,YAAY,GAAG,OAAO,CAE1D"}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
// engine/spec-changelog/diff.ts — Semantic diff calculation for spec criteria
|
|
2
|
+
/** Normalize a criteria text for comparison (trim, collapse whitespace). */
|
|
3
|
+
export function normalizeCriteriaText(text) {
|
|
4
|
+
return text
|
|
5
|
+
.replace(/^#+\s+/, '') // remove markdown headers
|
|
6
|
+
.replace(/\*\*/g, '') // remove bold markers
|
|
7
|
+
.replace(/\s+/g, ' ') // collapse whitespace
|
|
8
|
+
.trim()
|
|
9
|
+
.toLowerCase();
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Compute a simple similarity score (0–1) between two strings.
|
|
13
|
+
* Uses character bigram overlap.
|
|
14
|
+
*/
|
|
15
|
+
export function similarityScore(a, b) {
|
|
16
|
+
if (a.length === 0 && b.length === 0) {
|
|
17
|
+
return 0;
|
|
18
|
+
}
|
|
19
|
+
if (a === b) {
|
|
20
|
+
return 1;
|
|
21
|
+
}
|
|
22
|
+
if (a.length === 0 || b.length === 0) {
|
|
23
|
+
return 0;
|
|
24
|
+
}
|
|
25
|
+
const buildBigrams = (str) => {
|
|
26
|
+
const bigrams = new Set();
|
|
27
|
+
for (let i = 0; i < str.length - 1; i++) {
|
|
28
|
+
bigrams.add(str.slice(i, i + 2));
|
|
29
|
+
}
|
|
30
|
+
return bigrams;
|
|
31
|
+
};
|
|
32
|
+
const bigramsA = buildBigrams(a);
|
|
33
|
+
const bigramsB = buildBigrams(b);
|
|
34
|
+
let intersection = 0;
|
|
35
|
+
for (const bigram of bigramsA) {
|
|
36
|
+
if (bigramsB.has(bigram)) {
|
|
37
|
+
intersection++;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
return (2 * intersection) / (bigramsA.size + bigramsB.size);
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Compute semantic diff between two sets of criteria texts.
|
|
44
|
+
* Returns added, removed, and modified criteria.
|
|
45
|
+
*/
|
|
46
|
+
export function computeCriteriaDiff(before, after) {
|
|
47
|
+
const normalizedBefore = before.map(normalizeCriteriaText);
|
|
48
|
+
const normalizedAfter = after.map(normalizeCriteriaText);
|
|
49
|
+
const SIMILARITY_THRESHOLD = 0.6;
|
|
50
|
+
const matchedBeforeIndices = new Set();
|
|
51
|
+
const matchedAfterIndices = new Set();
|
|
52
|
+
const modified = [];
|
|
53
|
+
// Find modifications: pairs with high similarity but not identical
|
|
54
|
+
for (let i = 0; i < normalizedBefore.length; i++) {
|
|
55
|
+
const nb = normalizedBefore[i];
|
|
56
|
+
/* v8 ignore next 2 — noUncheckedIndexedAccess guard; array built with .map() so never undefined */
|
|
57
|
+
if (nb === undefined) {
|
|
58
|
+
continue;
|
|
59
|
+
}
|
|
60
|
+
let bestScore = 0;
|
|
61
|
+
let bestJ = -1;
|
|
62
|
+
for (let j = 0; j < normalizedAfter.length; j++) {
|
|
63
|
+
if (matchedAfterIndices.has(j)) {
|
|
64
|
+
continue;
|
|
65
|
+
}
|
|
66
|
+
const na = normalizedAfter[j];
|
|
67
|
+
/* v8 ignore next 2 — noUncheckedIndexedAccess guard; array built with .map() so never undefined */
|
|
68
|
+
if (na === undefined) {
|
|
69
|
+
continue;
|
|
70
|
+
}
|
|
71
|
+
const score = similarityScore(nb, na);
|
|
72
|
+
if (score > bestScore) {
|
|
73
|
+
bestScore = score;
|
|
74
|
+
bestJ = j;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
if (bestScore >= SIMILARITY_THRESHOLD && bestJ !== -1) {
|
|
78
|
+
matchedBeforeIndices.add(i);
|
|
79
|
+
matchedAfterIndices.add(bestJ);
|
|
80
|
+
const beforeText = before[i];
|
|
81
|
+
const afterText = after[bestJ];
|
|
82
|
+
// Only report as modified if texts actually differ
|
|
83
|
+
if (beforeText !== undefined && afterText !== undefined && beforeText !== afterText) {
|
|
84
|
+
modified.push({ before: beforeText, after: afterText });
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
// Removed: unmatched before items
|
|
89
|
+
const removed = [];
|
|
90
|
+
for (let i = 0; i < before.length; i++) {
|
|
91
|
+
if (!matchedBeforeIndices.has(i)) {
|
|
92
|
+
const text = before[i];
|
|
93
|
+
if (text !== undefined) {
|
|
94
|
+
removed.push(text);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
// Added: unmatched after items
|
|
99
|
+
const added = [];
|
|
100
|
+
for (let j = 0; j < after.length; j++) {
|
|
101
|
+
if (!matchedAfterIndices.has(j)) {
|
|
102
|
+
const text = after[j];
|
|
103
|
+
if (text !== undefined) {
|
|
104
|
+
added.push(text);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
return { added, removed, modified };
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Returns true if the diff contains any actual changes.
|
|
112
|
+
*/
|
|
113
|
+
export function hasDiffChanges(diff) {
|
|
114
|
+
return diff.added.length > 0 || diff.removed.length > 0 || diff.modified.length > 0;
|
|
115
|
+
}
|
|
116
|
+
//# sourceMappingURL=diff.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"diff.js","sourceRoot":"","sources":["../../../src/engine/spec-changelog/diff.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/engine/spec-changelog/index.ts"],"names":[],"mappings":"AACA,cAAc,WAAW,CAAC;AAC1B,cAAc,WAAW,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/engine/spec-changelog/index.ts"],"names":[],"mappings":"AAAA,2EAA2E;AAC3E,cAAc,WAAW,CAAC;AAC1B,cAAc,WAAW,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { SpecCoverageResult, SpecCoverageStore, CoverageGrade } from '../../types/index.js';
|
|
2
|
+
/**
|
|
3
|
+
* Runs the full spec coverage analysis for one spec.
|
|
4
|
+
* Reads the HU.md, discovers test files, maps tests to criteria, calculates
|
|
5
|
+
* score and grade, persists results, and returns the result object.
|
|
6
|
+
*/
|
|
7
|
+
export declare function analyzeSpecCoverage(projectId: string, specId: string, huPath: string, projectPath: string): Promise<SpecCoverageResult>;
|
|
8
|
+
/**
|
|
9
|
+
* Loads persisted coverage results from storage for a project.
|
|
10
|
+
* Returns null if no data exists or the file is corrupted.
|
|
11
|
+
*/
|
|
12
|
+
export declare function loadCoverageStore(projectId: string): Promise<SpecCoverageStore | null>;
|
|
13
|
+
export declare function calculateGrade(score: number): CoverageGrade;
|
|
14
|
+
//# sourceMappingURL=core.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"core.d.ts","sourceRoot":"","sources":["../../../src/engine/spec-coverage/core.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EACV,kBAAkB,EAClB,iBAAiB,EACjB,aAAa,EAEd,MAAM,sBAAsB,CAAC;AAe9B;;;;GAIG;AACH,wBAAsB,mBAAmB,CACvC,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,kBAAkB,CAAC,CA4D7B;AAED;;;GAGG;AACH,wBAAsB,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,GAAG,IAAI,CAAC,CAa5F;AAMD,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,aAAa,CAW3D"}
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
// engine/spec-coverage/core.ts — Orchestrator for spec coverage analysis.
|
|
2
|
+
// Coordinates test-finder, criteria-mapper, scoring, and persistence.
|
|
3
|
+
import { readFile } from 'node:fs/promises';
|
|
4
|
+
import { join } from 'node:path';
|
|
5
|
+
import { readJson, writeJson, projectDataDir } from '../../storage/base-store.js';
|
|
6
|
+
import { findTestFiles, detectTestRunners, readTestFileContent } from './test-finder.js';
|
|
7
|
+
import { extractCriteria, mapTestsToCriterion } from './criteria-mapper.js';
|
|
8
|
+
// ---------------------------------------------------------------------------
|
|
9
|
+
// Constants
|
|
10
|
+
// ---------------------------------------------------------------------------
|
|
11
|
+
const COVERAGE_FILE = 'spec-coverage.json';
|
|
12
|
+
// ---------------------------------------------------------------------------
|
|
13
|
+
// Public API
|
|
14
|
+
// ---------------------------------------------------------------------------
|
|
15
|
+
/**
|
|
16
|
+
* Runs the full spec coverage analysis for one spec.
|
|
17
|
+
* Reads the HU.md, discovers test files, maps tests to criteria, calculates
|
|
18
|
+
* score and grade, persists results, and returns the result object.
|
|
19
|
+
*/
|
|
20
|
+
export async function analyzeSpecCoverage(projectId, specId, huPath, projectPath) {
|
|
21
|
+
// 1. Read HU.md content
|
|
22
|
+
const huContent = await readHuFile(huPath);
|
|
23
|
+
// 2. Extract acceptance criteria
|
|
24
|
+
const rawCriteria = extractCriteria(huContent);
|
|
25
|
+
if (rawCriteria.length === 0) {
|
|
26
|
+
throw new Error(`No acceptance criteria found in HU.md for spec ${specId}. ` +
|
|
27
|
+
`Expected format: "- [ ] **AC-01**: description"`);
|
|
28
|
+
}
|
|
29
|
+
// 3. Find test files
|
|
30
|
+
const testFiles = await findTestFiles(projectPath);
|
|
31
|
+
// 4. Load test file contents (needed for criteria mapping)
|
|
32
|
+
const testContents = new Map();
|
|
33
|
+
await Promise.all(testFiles.map(async (tf) => {
|
|
34
|
+
const content = await readTestFileContent(projectPath, tf.file);
|
|
35
|
+
testContents.set(tf.file, content);
|
|
36
|
+
}));
|
|
37
|
+
// 5. Map each criterion to tests
|
|
38
|
+
const criteria = rawCriteria.map((rc) => mapTestsToCriterion(rc, testFiles, testContents, specId));
|
|
39
|
+
// 6. Detect test runners
|
|
40
|
+
const detectedRunners = await detectTestRunners(projectPath);
|
|
41
|
+
// 7. Calculate score and grade
|
|
42
|
+
const coveredCriteria = criteria.filter((c) => c.status === 'covered').length;
|
|
43
|
+
const superficialCriteria = criteria.filter((c) => c.status === 'superficial').length;
|
|
44
|
+
const uncoveredCriteria = criteria.filter((c) => c.status === 'uncovered').length;
|
|
45
|
+
const totalCriteria = criteria.length;
|
|
46
|
+
// Only high/medium confidence (covered) counts toward the score
|
|
47
|
+
const score = totalCriteria > 0 ? Math.round((coveredCriteria / totalCriteria) * 100) : 0;
|
|
48
|
+
const grade = calculateGrade(score);
|
|
49
|
+
const result = {
|
|
50
|
+
specId,
|
|
51
|
+
analyzedAt: new Date().toISOString(),
|
|
52
|
+
score,
|
|
53
|
+
grade,
|
|
54
|
+
totalCriteria,
|
|
55
|
+
coveredCriteria,
|
|
56
|
+
superficialCriteria,
|
|
57
|
+
uncoveredCriteria,
|
|
58
|
+
detectedRunners,
|
|
59
|
+
criteria,
|
|
60
|
+
};
|
|
61
|
+
// 8. Persist (best-effort — never throw on persistence failure)
|
|
62
|
+
await persistResult(projectId, specId, result);
|
|
63
|
+
return result;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Loads persisted coverage results from storage for a project.
|
|
67
|
+
* Returns null if no data exists or the file is corrupted.
|
|
68
|
+
*/
|
|
69
|
+
export async function loadCoverageStore(projectId) {
|
|
70
|
+
const filePath = join(projectDataDir(projectId), COVERAGE_FILE);
|
|
71
|
+
const defaultStore = { version: 1, updatedAt: '', specs: {} };
|
|
72
|
+
try {
|
|
73
|
+
const store = await readJson(filePath, defaultStore);
|
|
74
|
+
/* c8 ignore next 3 — defensive guard for corrupted files */
|
|
75
|
+
if (typeof store.specs !== 'object') {
|
|
76
|
+
return null;
|
|
77
|
+
}
|
|
78
|
+
return store;
|
|
79
|
+
}
|
|
80
|
+
catch {
|
|
81
|
+
return null;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
// ---------------------------------------------------------------------------
|
|
85
|
+
// Scoring helpers
|
|
86
|
+
// ---------------------------------------------------------------------------
|
|
87
|
+
export function calculateGrade(score) {
|
|
88
|
+
if (score >= 90) {
|
|
89
|
+
return 'A';
|
|
90
|
+
}
|
|
91
|
+
if (score >= 75) {
|
|
92
|
+
return 'B';
|
|
93
|
+
}
|
|
94
|
+
if (score >= 50) {
|
|
95
|
+
return 'C';
|
|
96
|
+
}
|
|
97
|
+
return 'D';
|
|
98
|
+
}
|
|
99
|
+
// ---------------------------------------------------------------------------
|
|
100
|
+
// Internal helpers
|
|
101
|
+
// ---------------------------------------------------------------------------
|
|
102
|
+
async function readHuFile(huPath) {
|
|
103
|
+
try {
|
|
104
|
+
return await readFile(huPath, 'utf-8');
|
|
105
|
+
}
|
|
106
|
+
catch (err) {
|
|
107
|
+
throw new Error(`Cannot read HU.md at "${huPath}": ${err instanceof Error ? err.message : String(err)}`, { cause: err });
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
async function persistResult(projectId, specId, result) {
|
|
111
|
+
const filePath = join(projectDataDir(projectId), COVERAGE_FILE);
|
|
112
|
+
try {
|
|
113
|
+
const existing = await readJson(filePath, {
|
|
114
|
+
version: 1,
|
|
115
|
+
updatedAt: '',
|
|
116
|
+
specs: {},
|
|
117
|
+
});
|
|
118
|
+
const updated = {
|
|
119
|
+
version: 1,
|
|
120
|
+
updatedAt: new Date().toISOString(),
|
|
121
|
+
specs: {
|
|
122
|
+
...existing.specs,
|
|
123
|
+
[specId]: result,
|
|
124
|
+
},
|
|
125
|
+
};
|
|
126
|
+
await writeJson(filePath, updated);
|
|
127
|
+
}
|
|
128
|
+
catch {
|
|
129
|
+
// Persistence failure is non-fatal — analysis result is still returned
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
//# sourceMappingURL=core.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"core.js","sourceRoot":"","sources":["../../../src/engine/spec-coverage/core.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { CriterionCoverage, CoverageTestFile, RawCriterion } from '../../types/index.js';
|
|
2
|
+
/**
|
|
3
|
+
* Parses HU.md content and returns a list of acceptance criteria with their
|
|
4
|
+
* identifiers and descriptions. Supports flexible AC formats:
|
|
5
|
+
* - `- [ ] **AC-01**: text`
|
|
6
|
+
* - `- **AC-01**: text`
|
|
7
|
+
* - `AC-01: text`
|
|
8
|
+
* - `- AC-01 text`
|
|
9
|
+
*/
|
|
10
|
+
export declare function extractCriteria(huContent: string): readonly RawCriterion[];
|
|
11
|
+
/**
|
|
12
|
+
* Maps a list of test files to a single criterion using the 3 strategies
|
|
13
|
+
* defined in SPEC-068. Returns the full CriterionCoverage for that criterion.
|
|
14
|
+
*/
|
|
15
|
+
export declare function mapTestsToCriterion(criterion: RawCriterion, testFiles: readonly CoverageTestFile[], testContents: ReadonlyMap<string, string>, specId: string): CriterionCoverage;
|
|
16
|
+
/** Extracts 3–5 meaningful keywords from an AC description text. */
|
|
17
|
+
export declare function extractKeywords(text: string): readonly string[];
|
|
18
|
+
//# sourceMappingURL=criteria-mapper.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"criteria-mapper.d.ts","sourceRoot":"","sources":["../../../src/engine/spec-coverage/criteria-mapper.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACV,iBAAiB,EAIjB,gBAAgB,EAChB,YAAY,EACb,MAAM,sBAAsB,CAAC;AAiF9B;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,YAAY,EAAE,CAmC1E;AAMD;;;GAGG;AACH,wBAAgB,mBAAmB,CACjC,SAAS,EAAE,YAAY,EACvB,SAAS,EAAE,SAAS,gBAAgB,EAAE,EACtC,YAAY,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,EACzC,MAAM,EAAE,MAAM,GACb,iBAAiB,CAsCnB;AAsFD,oEAAoE;AACpE,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,MAAM,EAAE,CAkB/D"}
|