@shrkcrft/inspector 0.1.0-alpha.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +15 -0
- package/dist/acceptance-replay.d.ts +63 -0
- package/dist/acceptance-replay.d.ts.map +1 -0
- package/dist/acceptance-replay.js +240 -0
- package/dist/action-hint-diagnostics.d.ts +32 -0
- package/dist/action-hint-diagnostics.d.ts.map +1 -0
- package/dist/action-hint-diagnostics.js +133 -0
- package/dist/adoption-check.d.ts +28 -0
- package/dist/adoption-check.d.ts.map +1 -0
- package/dist/adoption-check.js +181 -0
- package/dist/adoption-checkpoint.d.ts +97 -0
- package/dist/adoption-checkpoint.d.ts.map +1 -0
- package/dist/adoption-checkpoint.js +209 -0
- package/dist/adoption-merge-preview.d.ts +28 -0
- package/dist/adoption-merge-preview.d.ts.map +1 -0
- package/dist/adoption-merge-preview.js +254 -0
- package/dist/adoption-report-renderer.d.ts +33 -0
- package/dist/adoption-report-renderer.d.ts.map +1 -0
- package/dist/adoption-report-renderer.js +257 -0
- package/dist/adoption-state.d.ts +100 -0
- package/dist/adoption-state.d.ts.map +1 -0
- package/dist/adoption-state.js +296 -0
- package/dist/adoption-three-way.d.ts +46 -0
- package/dist/adoption-three-way.d.ts.map +1 -0
- package/dist/adoption-three-way.js +181 -0
- package/dist/agent-brief.d.ts +77 -0
- package/dist/agent-brief.d.ts.map +1 -0
- package/dist/agent-brief.js +490 -0
- package/dist/agent-contract-gate.d.ts +108 -0
- package/dist/agent-contract-gate.d.ts.map +1 -0
- package/dist/agent-contract-gate.js +412 -0
- package/dist/agent-contract-templates.d.ts +63 -0
- package/dist/agent-contract-templates.d.ts.map +1 -0
- package/dist/agent-contract-templates.js +346 -0
- package/dist/agent-contract.d.ts +65 -0
- package/dist/agent-contract.d.ts.map +1 -0
- package/dist/agent-contract.js +555 -0
- package/dist/agent-handoff.d.ts +123 -0
- package/dist/agent-handoff.d.ts.map +1 -0
- package/dist/agent-handoff.js +470 -0
- package/dist/agent-instructions.d.ts +2 -0
- package/dist/agent-instructions.d.ts.map +1 -0
- package/dist/agent-instructions.js +21 -0
- package/dist/agent-orchestration.d.ts +61 -0
- package/dist/agent-orchestration.d.ts.map +1 -0
- package/dist/agent-orchestration.js +285 -0
- package/dist/agent-task-prep.d.ts +31 -0
- package/dist/agent-task-prep.d.ts.map +1 -0
- package/dist/agent-task-prep.js +73 -0
- package/dist/ai-readiness.d.ts +30 -0
- package/dist/ai-readiness.d.ts.map +1 -0
- package/dist/ai-readiness.js +279 -0
- package/dist/api-report.d.ts +51 -0
- package/dist/api-report.d.ts.map +1 -0
- package/dist/api-report.js +254 -0
- package/dist/apply-dispatch-trace.d.ts +93 -0
- package/dist/apply-dispatch-trace.d.ts.map +1 -0
- package/dist/apply-dispatch-trace.js +283 -0
- package/dist/apply-gate-result.d.ts +52 -0
- package/dist/apply-gate-result.d.ts.map +1 -0
- package/dist/apply-gate-result.js +44 -0
- package/dist/architecture-map.d.ts +118 -0
- package/dist/architecture-map.d.ts.map +1 -0
- package/dist/architecture-map.js +543 -0
- package/dist/area-explore.d.ts +75 -0
- package/dist/area-explore.d.ts.map +1 -0
- package/dist/area-explore.js +438 -0
- package/dist/area-map.d.ts +57 -0
- package/dist/area-map.d.ts.map +1 -0
- package/dist/area-map.js +214 -0
- package/dist/asset-provenance.d.ts +123 -0
- package/dist/asset-provenance.d.ts.map +1 -0
- package/dist/asset-provenance.js +209 -0
- package/dist/barrel-operations.d.ts +45 -0
- package/dist/barrel-operations.d.ts.map +1 -0
- package/dist/barrel-operations.js +159 -0
- package/dist/boundaries-changed-only.d.ts +62 -0
- package/dist/boundaries-changed-only.d.ts.map +1 -0
- package/dist/boundaries-changed-only.js +97 -0
- package/dist/boundary-suggestions.d.ts +20 -0
- package/dist/boundary-suggestions.d.ts.map +1 -0
- package/dist/boundary-suggestions.js +51 -0
- package/dist/bundle-diff.d.ts +98 -0
- package/dist/bundle-diff.d.ts.map +1 -0
- package/dist/bundle-diff.js +531 -0
- package/dist/bundle-replay.d.ts +68 -0
- package/dist/bundle-replay.d.ts.map +1 -0
- package/dist/bundle-replay.js +273 -0
- package/dist/bundle-validate-html.d.ts +11 -0
- package/dist/bundle-validate-html.d.ts.map +1 -0
- package/dist/bundle-validate-html.js +60 -0
- package/dist/change-intent.d.ts +36 -0
- package/dist/change-intent.d.ts.map +1 -0
- package/dist/change-intent.js +259 -0
- package/dist/changed-preflight.d.ts +59 -0
- package/dist/changed-preflight.d.ts.map +1 -0
- package/dist/changed-preflight.js +358 -0
- package/dist/changed-scope.d.ts +112 -0
- package/dist/changed-scope.d.ts.map +1 -0
- package/dist/changed-scope.js +172 -0
- package/dist/changes-summary.d.ts +87 -0
- package/dist/changes-summary.d.ts.map +1 -0
- package/dist/changes-summary.js +323 -0
- package/dist/check-result-v1.d.ts +90 -0
- package/dist/check-result-v1.d.ts.map +1 -0
- package/dist/check-result-v1.js +335 -0
- package/dist/ci-integrity-report.d.ts +38 -0
- package/dist/ci-integrity-report.d.ts.map +1 -0
- package/dist/ci-integrity-report.js +324 -0
- package/dist/ci-permissions-fix.d.ts +38 -0
- package/dist/ci-permissions-fix.d.ts.map +1 -0
- package/dist/ci-permissions-fix.js +382 -0
- package/dist/ci-permissions.d.ts +51 -0
- package/dist/ci-permissions.d.ts.map +1 -0
- package/dist/ci-permissions.js +431 -0
- package/dist/ci-predict.d.ts +42 -0
- package/dist/ci-predict.d.ts.map +1 -0
- package/dist/ci-predict.js +300 -0
- package/dist/ci-scaffold.d.ts +47 -0
- package/dist/ci-scaffold.d.ts.map +1 -0
- package/dist/ci-scaffold.js +638 -0
- package/dist/codemod-assist.d.ts +97 -0
- package/dist/codemod-assist.d.ts.map +1 -0
- package/dist/codemod-assist.js +261 -0
- package/dist/command-recommender.d.ts +25 -0
- package/dist/command-recommender.d.ts.map +1 -0
- package/dist/command-recommender.js +145 -0
- package/dist/command-suggester.d.ts +61 -0
- package/dist/command-suggester.d.ts.map +1 -0
- package/dist/command-suggester.js +159 -0
- package/dist/command-taxonomy.d.ts +38 -0
- package/dist/command-taxonomy.d.ts.map +1 -0
- package/dist/command-taxonomy.js +164 -0
- package/dist/compliance-evidence.d.ts +58 -0
- package/dist/compliance-evidence.d.ts.map +1 -0
- package/dist/compliance-evidence.js +260 -0
- package/dist/compliance-profiles.d.ts +42 -0
- package/dist/compliance-profiles.d.ts.map +1 -0
- package/dist/compliance-profiles.js +171 -0
- package/dist/construct-adoption-diff.d.ts +55 -0
- package/dist/construct-adoption-diff.d.ts.map +1 -0
- package/dist/construct-adoption-diff.js +331 -0
- package/dist/construct-adoption.d.ts +71 -0
- package/dist/construct-adoption.d.ts.map +1 -0
- package/dist/construct-adoption.js +331 -0
- package/dist/construct-inference.d.ts +44 -0
- package/dist/construct-inference.d.ts.map +1 -0
- package/dist/construct-inference.js +391 -0
- package/dist/construct-registry.d.ts +32 -0
- package/dist/construct-registry.d.ts.map +1 -0
- package/dist/construct-registry.js +198 -0
- package/dist/contract-file-rule.d.ts +37 -0
- package/dist/contract-file-rule.d.ts.map +1 -0
- package/dist/contract-file-rule.js +99 -0
- package/dist/contract-template-registry.d.ts +28 -0
- package/dist/contract-template-registry.d.ts.map +1 -0
- package/dist/contract-template-registry.js +161 -0
- package/dist/contradictions.d.ts +52 -0
- package/dist/contradictions.d.ts.map +1 -0
- package/dist/contradictions.js +391 -0
- package/dist/convention-registry.d.ts +44 -0
- package/dist/convention-registry.d.ts.map +1 -0
- package/dist/convention-registry.js +195 -0
- package/dist/coverage-report.d.ts +25 -0
- package/dist/coverage-report.d.ts.map +1 -0
- package/dist/coverage-report.js +190 -0
- package/dist/custom-checks.d.ts +146 -0
- package/dist/custom-checks.d.ts.map +1 -0
- package/dist/custom-checks.js +260 -0
- package/dist/dashboard/dashboard-data.d.ts +59 -0
- package/dist/dashboard/dashboard-data.d.ts.map +1 -0
- package/dist/dashboard/dashboard-data.js +653 -0
- package/dist/dashboard-export.d.ts +67 -0
- package/dist/dashboard-export.d.ts.map +1 -0
- package/dist/dashboard-export.js +203 -0
- package/dist/decision-records.d.ts +47 -0
- package/dist/decision-records.d.ts.map +1 -0
- package/dist/decision-records.js +255 -0
- package/dist/demo-package.d.ts +49 -0
- package/dist/demo-package.d.ts.map +1 -0
- package/dist/demo-package.js +305 -0
- package/dist/demo-script.d.ts +25 -0
- package/dist/demo-script.d.ts.map +1 -0
- package/dist/demo-script.js +198 -0
- package/dist/demo-workflow.d.ts +28 -0
- package/dist/demo-workflow.d.ts.map +1 -0
- package/dist/demo-workflow.js +178 -0
- package/dist/dev-cycle.d.ts +41 -0
- package/dist/dev-cycle.d.ts.map +1 -0
- package/dist/dev-cycle.js +94 -0
- package/dist/dev-session-html.d.ts +13 -0
- package/dist/dev-session-html.d.ts.map +1 -0
- package/dist/dev-session-html.js +223 -0
- package/dist/dev-session-report.d.ts +11 -0
- package/dist/dev-session-report.d.ts.map +1 -0
- package/dist/dev-session-report.js +206 -0
- package/dist/dev-session.d.ts +257 -0
- package/dist/dev-session.d.ts.map +1 -0
- package/dist/dev-session.js +568 -0
- package/dist/diagnostics-suggest.d.ts +17 -0
- package/dist/diagnostics-suggest.d.ts.map +1 -0
- package/dist/diagnostics-suggest.js +69 -0
- package/dist/docs-check.d.ts +40 -0
- package/dist/docs-check.d.ts.map +1 -0
- package/dist/docs-check.js +221 -0
- package/dist/doctor-acknowledgements.d.ts +69 -0
- package/dist/doctor-acknowledgements.d.ts.map +1 -0
- package/dist/doctor-acknowledgements.js +150 -0
- package/dist/doctor-result.d.ts +51 -0
- package/dist/doctor-result.d.ts.map +1 -0
- package/dist/doctor-result.js +7 -0
- package/dist/doctor-suppressions.d.ts +91 -0
- package/dist/doctor-suppressions.d.ts.map +1 -0
- package/dist/doctor-suppressions.js +238 -0
- package/dist/drift-baseline.d.ts +29 -0
- package/dist/drift-baseline.d.ts.map +1 -0
- package/dist/drift-baseline.js +80 -0
- package/dist/drift.d.ts +38 -0
- package/dist/drift.d.ts.map +1 -0
- package/dist/drift.js +107 -0
- package/dist/entrypoint-matrix.d.ts +61 -0
- package/dist/entrypoint-matrix.d.ts.map +1 -0
- package/dist/entrypoint-matrix.js +221 -0
- package/dist/examples-check.d.ts +36 -0
- package/dist/examples-check.d.ts.map +1 -0
- package/dist/examples-check.js +168 -0
- package/dist/execution-graph.d.ts +98 -0
- package/dist/execution-graph.d.ts.map +1 -0
- package/dist/execution-graph.js +484 -0
- package/dist/export-bundle.d.ts +10 -0
- package/dist/export-bundle.d.ts.map +1 -0
- package/dist/export-bundle.js +90 -0
- package/dist/failure-diagnostics.d.ts +63 -0
- package/dist/failure-diagnostics.d.ts.map +1 -0
- package/dist/failure-diagnostics.js +243 -0
- package/dist/feature-bundle.d.ts +111 -0
- package/dist/feature-bundle.d.ts.map +1 -0
- package/dist/feature-bundle.js +211 -0
- package/dist/feedback-actions-v2.d.ts +65 -0
- package/dist/feedback-actions-v2.d.ts.map +1 -0
- package/dist/feedback-actions-v2.js +183 -0
- package/dist/feedback-ingestion.d.ts +96 -0
- package/dist/feedback-ingestion.d.ts.map +1 -0
- package/dist/feedback-ingestion.js +400 -0
- package/dist/fix-preview.d.ts +82 -0
- package/dist/fix-preview.d.ts.map +1 -0
- package/dist/fix-preview.js +365 -0
- package/dist/fuzzy-impact.d.ts +50 -0
- package/dist/fuzzy-impact.d.ts.map +1 -0
- package/dist/fuzzy-impact.js +446 -0
- package/dist/generated-code.d.ts +97 -0
- package/dist/generated-code.d.ts.map +1 -0
- package/dist/generated-code.js +395 -0
- package/dist/git-helpers.d.ts +38 -0
- package/dist/git-helpers.d.ts.map +1 -0
- package/dist/git-helpers.js +173 -0
- package/dist/golden-output.d.ts +33 -0
- package/dist/golden-output.d.ts.map +1 -0
- package/dist/golden-output.js +92 -0
- package/dist/grounding/build-grounding.d.ts +53 -0
- package/dist/grounding/build-grounding.d.ts.map +1 -0
- package/dist/grounding/build-grounding.js +51 -0
- package/dist/grounding/nx-projects.d.ts +29 -0
- package/dist/grounding/nx-projects.d.ts.map +1 -0
- package/dist/grounding/nx-projects.js +109 -0
- package/dist/grounding/validate-extracted-plan.d.ts +20 -0
- package/dist/grounding/validate-extracted-plan.d.ts.map +1 -0
- package/dist/grounding/validate-extracted-plan.js +127 -0
- package/dist/healing-plan.d.ts +33 -0
- package/dist/healing-plan.d.ts.map +1 -0
- package/dist/healing-plan.js +346 -0
- package/dist/helper-registry.d.ts +90 -0
- package/dist/helper-registry.d.ts.map +1 -0
- package/dist/helper-registry.js +529 -0
- package/dist/impact-analysis.d.ts +150 -0
- package/dist/impact-analysis.d.ts.map +1 -0
- package/dist/impact-analysis.js +697 -0
- package/dist/impact-graph-render.d.ts +51 -0
- package/dist/impact-graph-render.d.ts.map +1 -0
- package/dist/impact-graph-render.js +139 -0
- package/dist/impact-graph.d.ts +17 -0
- package/dist/impact-graph.d.ts.map +1 -0
- package/dist/impact-graph.js +119 -0
- package/dist/impact-render.d.ts +22 -0
- package/dist/impact-render.d.ts.map +1 -0
- package/dist/impact-render.js +422 -0
- package/dist/import-graph-analysis.d.ts +28 -0
- package/dist/import-graph-analysis.d.ts.map +1 -0
- package/dist/import-graph-analysis.js +193 -0
- package/dist/import-hygiene.d.ts +93 -0
- package/dist/import-hygiene.d.ts.map +1 -0
- package/dist/import-hygiene.js +366 -0
- package/dist/index.d.ts +224 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +234 -0
- package/dist/ingest-adoption.d.ts +50 -0
- package/dist/ingest-adoption.d.ts.map +1 -0
- package/dist/ingest-adoption.js +183 -0
- package/dist/ingest-apply.d.ts +80 -0
- package/dist/ingest-apply.d.ts.map +1 -0
- package/dist/ingest-apply.js +227 -0
- package/dist/ingest-body-extractor.d.ts +28 -0
- package/dist/ingest-body-extractor.d.ts.map +1 -0
- package/dist/ingest-body-extractor.js +129 -0
- package/dist/ingest-drafts.d.ts +16 -0
- package/dist/ingest-drafts.d.ts.map +1 -0
- package/dist/ingest-drafts.js +482 -0
- package/dist/inspector-cache.d.ts +41 -0
- package/dist/inspector-cache.d.ts.map +1 -0
- package/dist/inspector-cache.js +104 -0
- package/dist/install-smoke.d.ts +44 -0
- package/dist/install-smoke.d.ts.map +1 -0
- package/dist/install-smoke.js +31 -0
- package/dist/knowledge-authoring.d.ts +151 -0
- package/dist/knowledge-authoring.d.ts.map +1 -0
- package/dist/knowledge-authoring.js +586 -0
- package/dist/knowledge-graph.d.ts +76 -0
- package/dist/knowledge-graph.d.ts.map +1 -0
- package/dist/knowledge-graph.js +336 -0
- package/dist/knowledge-lint.d.ts +97 -0
- package/dist/knowledge-lint.d.ts.map +1 -0
- package/dist/knowledge-lint.js +302 -0
- package/dist/knowledge-rename.d.ts +38 -0
- package/dist/knowledge-rename.d.ts.map +1 -0
- package/dist/knowledge-rename.js +88 -0
- package/dist/knowledge-stale.d.ts +124 -0
- package/dist/knowledge-stale.d.ts.map +1 -0
- package/dist/knowledge-stale.js +892 -0
- package/dist/languages/command-inference.d.ts +27 -0
- package/dist/languages/command-inference.d.ts.map +1 -0
- package/dist/languages/command-inference.js +214 -0
- package/dist/languages/dependency-scan.d.ts +33 -0
- package/dist/languages/dependency-scan.d.ts.map +1 -0
- package/dist/languages/dependency-scan.js +343 -0
- package/dist/languages/index.d.ts +14 -0
- package/dist/languages/index.d.ts.map +1 -0
- package/dist/languages/index.js +13 -0
- package/dist/languages/language-boundaries.d.ts +30 -0
- package/dist/languages/language-boundaries.d.ts.map +1 -0
- package/dist/languages/language-boundaries.js +176 -0
- package/dist/languages/language-cache.d.ts +54 -0
- package/dist/languages/language-cache.d.ts.map +1 -0
- package/dist/languages/language-cache.js +236 -0
- package/dist/languages/language-detection.d.ts +30 -0
- package/dist/languages/language-detection.d.ts.map +1 -0
- package/dist/languages/language-detection.js +584 -0
- package/dist/languages/language-id.d.ts +15 -0
- package/dist/languages/language-id.d.ts.map +1 -0
- package/dist/languages/language-id.js +15 -0
- package/dist/languages/language-runner.d.ts +90 -0
- package/dist/languages/language-runner.d.ts.map +1 -0
- package/dist/languages/language-runner.js +346 -0
- package/dist/languages/polyglot-boundary.d.ts +80 -0
- package/dist/languages/polyglot-boundary.d.ts.map +1 -0
- package/dist/languages/polyglot-boundary.js +373 -0
- package/dist/languages/polyglot-ci.d.ts +25 -0
- package/dist/languages/polyglot-ci.d.ts.map +1 -0
- package/dist/languages/polyglot-ci.js +278 -0
- package/dist/languages/test-impact.d.ts +19 -0
- package/dist/languages/test-impact.d.ts.map +1 -0
- package/dist/languages/test-impact.js +157 -0
- package/dist/loader-diagnostics.d.ts +40 -0
- package/dist/loader-diagnostics.d.ts.map +1 -0
- package/dist/loader-diagnostics.js +49 -0
- package/dist/memory-diff.d.ts +60 -0
- package/dist/memory-diff.d.ts.map +1 -0
- package/dist/memory-diff.js +302 -0
- package/dist/migration-profile-registry.d.ts +26 -0
- package/dist/migration-profile-registry.d.ts.map +1 -0
- package/dist/migration-profile-registry.js +135 -0
- package/dist/migration-readiness.d.ts +101 -0
- package/dist/migration-readiness.d.ts.map +1 -0
- package/dist/migration-readiness.js +253 -0
- package/dist/monorepo-onboarding.d.ts +51 -0
- package/dist/monorepo-onboarding.d.ts.map +1 -0
- package/dist/monorepo-onboarding.js +235 -0
- package/dist/onboarding-adoption-diff.d.ts +53 -0
- package/dist/onboarding-adoption-diff.d.ts.map +1 -0
- package/dist/onboarding-adoption-diff.js +285 -0
- package/dist/onboarding-adoption.d.ts +136 -0
- package/dist/onboarding-adoption.d.ts.map +1 -0
- package/dist/onboarding-adoption.js +702 -0
- package/dist/onboarding-agent-import.d.ts +40 -0
- package/dist/onboarding-agent-import.d.ts.map +1 -0
- package/dist/onboarding-agent-import.js +114 -0
- package/dist/onboarding-diff.d.ts +39 -0
- package/dist/onboarding-diff.d.ts.map +1 -0
- package/dist/onboarding-diff.js +240 -0
- package/dist/onboarding-drafts-merge.d.ts +71 -0
- package/dist/onboarding-drafts-merge.d.ts.map +1 -0
- package/dist/onboarding-drafts-merge.js +174 -0
- package/dist/onboarding-drafts.d.ts +42 -0
- package/dist/onboarding-drafts.d.ts.map +1 -0
- package/dist/onboarding-drafts.js +268 -0
- package/dist/onboarding-report.d.ts +8 -0
- package/dist/onboarding-report.d.ts.map +1 -0
- package/dist/onboarding-report.js +239 -0
- package/dist/onboarding.d.ts +134 -0
- package/dist/onboarding.d.ts.map +1 -0
- package/dist/onboarding.js +729 -0
- package/dist/ownership.d.ts +38 -0
- package/dist/ownership.d.ts.map +1 -0
- package/dist/ownership.js +102 -0
- package/dist/pack-author-ux.d.ts +58 -0
- package/dist/pack-author-ux.d.ts.map +1 -0
- package/dist/pack-author-ux.js +219 -0
- package/dist/pack-author.d.ts +94 -0
- package/dist/pack-author.d.ts.map +1 -0
- package/dist/pack-author.js +208 -0
- package/dist/pack-compatibility.d.ts +21 -0
- package/dist/pack-compatibility.d.ts.map +1 -0
- package/dist/pack-compatibility.js +114 -0
- package/dist/pack-contributions-inventory.d.ts +121 -0
- package/dist/pack-contributions-inventory.d.ts.map +1 -0
- package/dist/pack-contributions-inventory.js +732 -0
- package/dist/pack-docs.d.ts +11 -0
- package/dist/pack-docs.d.ts.map +1 -0
- package/dist/pack-docs.js +101 -0
- package/dist/pack-doctor.d.ts +50 -0
- package/dist/pack-doctor.d.ts.map +1 -0
- package/dist/pack-doctor.js +302 -0
- package/dist/pack-helper-registry.d.ts +29 -0
- package/dist/pack-helper-registry.d.ts.map +1 -0
- package/dist/pack-helper-registry.js +144 -0
- package/dist/pack-pending.d.ts +68 -0
- package/dist/pack-pending.d.ts.map +1 -0
- package/dist/pack-pending.js +189 -0
- package/dist/pack-quality-score.d.ts +44 -0
- package/dist/pack-quality-score.d.ts.map +1 -0
- package/dist/pack-quality-score.js +155 -0
- package/dist/pack-release-check.d.ts +24 -0
- package/dist/pack-release-check.d.ts.map +1 -0
- package/dist/pack-release-check.js +258 -0
- package/dist/pack-signature-status.d.ts +72 -0
- package/dist/pack-signature-status.d.ts.map +1 -0
- package/dist/pack-signature-status.js +222 -0
- package/dist/pack-symbol-compat.d.ts +73 -0
- package/dist/pack-symbol-compat.d.ts.map +1 -0
- package/dist/pack-symbol-compat.js +519 -0
- package/dist/pack-test-runner.d.ts +59 -0
- package/dist/pack-test-runner.d.ts.map +1 -0
- package/dist/pack-test-runner.js +211 -0
- package/dist/pipeline-command-dictionary.d.ts +2 -0
- package/dist/pipeline-command-dictionary.d.ts.map +1 -0
- package/dist/pipeline-command-dictionary.js +20 -0
- package/dist/pipeline-lint.d.ts +30 -0
- package/dist/pipeline-lint.d.ts.map +1 -0
- package/dist/pipeline-lint.js +134 -0
- package/dist/plan-dependency-graph.d.ts +25 -0
- package/dist/plan-dependency-graph.d.ts.map +1 -0
- package/dist/plan-dependency-graph.js +195 -0
- package/dist/plan-review.d.ts +64 -0
- package/dist/plan-review.d.ts.map +1 -0
- package/dist/plan-review.js +242 -0
- package/dist/plan-simulation.d.ts +108 -0
- package/dist/plan-simulation.d.ts.map +1 -0
- package/dist/plan-simulation.js +767 -0
- package/dist/playbook-registry.d.ts +25 -0
- package/dist/playbook-registry.d.ts.map +1 -0
- package/dist/playbook-registry.js +148 -0
- package/dist/playbook-script.d.ts +60 -0
- package/dist/playbook-script.d.ts.map +1 -0
- package/dist/playbook-script.js +161 -0
- package/dist/plugin-lifecycle-profile-registry.d.ts +52 -0
- package/dist/plugin-lifecycle-profile-registry.d.ts.map +1 -0
- package/dist/plugin-lifecycle-profile-registry.js +202 -0
- package/dist/plugin-lifecycle.d.ts +132 -0
- package/dist/plugin-lifecycle.d.ts.map +1 -0
- package/dist/plugin-lifecycle.js +477 -0
- package/dist/policy-engine.d.ts +101 -0
- package/dist/policy-engine.d.ts.map +1 -0
- package/dist/policy-engine.js +321 -0
- package/dist/policy-override-audit.d.ts +18 -0
- package/dist/policy-override-audit.d.ts.map +1 -0
- package/dist/policy-override-audit.js +54 -0
- package/dist/policy-overrides.d.ts +35 -0
- package/dist/policy-overrides.d.ts.map +1 -0
- package/dist/policy-overrides.js +84 -0
- package/dist/policy-test.d.ts +83 -0
- package/dist/policy-test.d.ts.map +1 -0
- package/dist/policy-test.js +342 -0
- package/dist/pr-summary.d.ts +34 -0
- package/dist/pr-summary.d.ts.map +1 -0
- package/dist/pr-summary.js +220 -0
- package/dist/product-coherence.d.ts +21 -0
- package/dist/product-coherence.d.ts.map +1 -0
- package/dist/product-coherence.js +158 -0
- package/dist/profile-registry.d.ts +42 -0
- package/dist/profile-registry.d.ts.map +1 -0
- package/dist/profile-registry.js +104 -0
- package/dist/project-coupling-audit.d.ts +64 -0
- package/dist/project-coupling-audit.d.ts.map +1 -0
- package/dist/project-coupling-audit.js +282 -0
- package/dist/project-overview.d.ts +14 -0
- package/dist/project-overview.d.ts.map +1 -0
- package/dist/project-overview.js +27 -0
- package/dist/propose-knowledge.d.ts +64 -0
- package/dist/propose-knowledge.d.ts.map +1 -0
- package/dist/propose-knowledge.js +367 -0
- package/dist/quality-baseline.d.ts +123 -0
- package/dist/quality-baseline.d.ts.map +1 -0
- package/dist/quality-baseline.js +433 -0
- package/dist/quality-html.d.ts +7 -0
- package/dist/quality-html.d.ts.map +1 -0
- package/dist/quality-html.js +64 -0
- package/dist/quality-report.d.ts +49 -0
- package/dist/quality-report.d.ts.map +1 -0
- package/dist/quality-report.js +296 -0
- package/dist/query-resolver.d.ts +38 -0
- package/dist/query-resolver.d.ts.map +1 -0
- package/dist/query-resolver.js +163 -0
- package/dist/ranker-explainability.d.ts +91 -0
- package/dist/ranker-explainability.d.ts.map +1 -0
- package/dist/ranker-explainability.js +550 -0
- package/dist/reference-lookup.d.ts +8 -0
- package/dist/reference-lookup.d.ts.map +1 -0
- package/dist/reference-lookup.js +18 -0
- package/dist/registration-hint-registry.d.ts +55 -0
- package/dist/registration-hint-registry.d.ts.map +1 -0
- package/dist/registration-hint-registry.js +327 -0
- package/dist/registry-lifecycle.d.ts +47 -0
- package/dist/registry-lifecycle.d.ts.map +1 -0
- package/dist/registry-lifecycle.js +214 -0
- package/dist/release-readiness.d.ts +64 -0
- package/dist/release-readiness.d.ts.map +1 -0
- package/dist/release-readiness.js +456 -0
- package/dist/release-smoke.d.ts +138 -0
- package/dist/release-smoke.d.ts.map +1 -0
- package/dist/release-smoke.js +459 -0
- package/dist/release-train.d.ts +33 -0
- package/dist/release-train.d.ts.map +1 -0
- package/dist/release-train.js +104 -0
- package/dist/repo-memory.d.ts +95 -0
- package/dist/repo-memory.d.ts.map +1 -0
- package/dist/repo-memory.js +614 -0
- package/dist/report-site.d.ts +92 -0
- package/dist/report-site.d.ts.map +1 -0
- package/dist/report-site.js +658 -0
- package/dist/reposet.d.ts +56 -0
- package/dist/reposet.d.ts.map +1 -0
- package/dist/reposet.js +160 -0
- package/dist/repository-intelligence.d.ts +145 -0
- package/dist/repository-intelligence.d.ts.map +1 -0
- package/dist/repository-intelligence.js +729 -0
- package/dist/repository-knowledge-model.d.ts +218 -0
- package/dist/repository-knowledge-model.d.ts.map +1 -0
- package/dist/repository-knowledge-model.js +939 -0
- package/dist/repository-map.d.ts +72 -0
- package/dist/repository-map.d.ts.map +1 -0
- package/dist/repository-map.js +332 -0
- package/dist/repository-stats.d.ts +66 -0
- package/dist/repository-stats.d.ts.map +1 -0
- package/dist/repository-stats.js +329 -0
- package/dist/review-comment-renderer.d.ts +59 -0
- package/dist/review-comment-renderer.d.ts.map +1 -0
- package/dist/review-comment-renderer.js +181 -0
- package/dist/review-comment-v2.d.ts +9 -0
- package/dist/review-comment-v2.d.ts.map +1 -0
- package/dist/review-comment-v2.js +178 -0
- package/dist/review-html.d.ts +13 -0
- package/dist/review-html.d.ts.map +1 -0
- package/dist/review-html.js +79 -0
- package/dist/review-packet-v2.d.ts +29 -0
- package/dist/review-packet-v2.d.ts.map +1 -0
- package/dist/review-packet-v2.js +81 -0
- package/dist/review-packet-v3.d.ts +22 -0
- package/dist/review-packet-v3.d.ts.map +1 -0
- package/dist/review-packet-v3.js +181 -0
- package/dist/review-packet.d.ts +49 -0
- package/dist/review-packet.d.ts.map +1 -0
- package/dist/review-packet.js +129 -0
- package/dist/risk-signals.d.ts +28 -0
- package/dist/risk-signals.d.ts.map +1 -0
- package/dist/risk-signals.js +68 -0
- package/dist/role-views.d.ts +50 -0
- package/dist/role-views.d.ts.map +1 -0
- package/dist/role-views.js +334 -0
- package/dist/rounds.d.ts +52 -0
- package/dist/rounds.d.ts.map +1 -0
- package/dist/rounds.js +172 -0
- package/dist/rule-drift.d.ts +42 -0
- package/dist/rule-drift.d.ts.map +1 -0
- package/dist/rule-drift.js +148 -0
- package/dist/rule-quality.d.ts +73 -0
- package/dist/rule-quality.d.ts.map +1 -0
- package/dist/rule-quality.js +356 -0
- package/dist/rule-scaffold.d.ts +71 -0
- package/dist/rule-scaffold.d.ts.map +1 -0
- package/dist/rule-scaffold.js +258 -0
- package/dist/safety-audit-deep.d.ts +38 -0
- package/dist/safety-audit-deep.d.ts.map +1 -0
- package/dist/safety-audit-deep.js +162 -0
- package/dist/safety-audit.d.ts +91 -0
- package/dist/safety-audit.d.ts.map +1 -0
- package/dist/safety-audit.js +138 -0
- package/dist/safety-html.d.ts +7 -0
- package/dist/safety-html.d.ts.map +1 -0
- package/dist/safety-html.js +70 -0
- package/dist/scaffold-coverage.d.ts +46 -0
- package/dist/scaffold-coverage.d.ts.map +1 -0
- package/dist/scaffold-coverage.js +273 -0
- package/dist/scaffold-patterns.d.ts +38 -0
- package/dist/scaffold-patterns.d.ts.map +1 -0
- package/dist/scaffold-patterns.js +282 -0
- package/dist/schema-inventory.d.ts +55 -0
- package/dist/schema-inventory.d.ts.map +1 -0
- package/dist/schema-inventory.js +301 -0
- package/dist/search-index.d.ts +75 -0
- package/dist/search-index.d.ts.map +1 -0
- package/dist/search-index.js +531 -0
- package/dist/search-tuning-explain.d.ts +68 -0
- package/dist/search-tuning-explain.d.ts.map +1 -0
- package/dist/search-tuning-explain.js +207 -0
- package/dist/search-tuning-registry.d.ts +54 -0
- package/dist/search-tuning-registry.d.ts.map +1 -0
- package/dist/search-tuning-registry.js +303 -0
- package/dist/self-audit.d.ts +59 -0
- package/dist/self-audit.d.ts.map +1 -0
- package/dist/self-audit.js +192 -0
- package/dist/self-config-doctor-v2.d.ts +57 -0
- package/dist/self-config-doctor-v2.d.ts.map +1 -0
- package/dist/self-config-doctor-v2.js +653 -0
- package/dist/self-config-doctor.d.ts +47 -0
- package/dist/self-config-doctor.d.ts.map +1 -0
- package/dist/self-config-doctor.js +432 -0
- package/dist/sharkcraft-inspector.d.ts +73 -0
- package/dist/sharkcraft-inspector.d.ts.map +1 -0
- package/dist/sharkcraft-inspector.js +745 -0
- package/dist/spec/spec-cross-validate.d.ts +17 -0
- package/dist/spec/spec-cross-validate.d.ts.map +1 -0
- package/dist/spec/spec-cross-validate.js +53 -0
- package/dist/spec/spec-discovery.d.ts +27 -0
- package/dist/spec/spec-discovery.d.ts.map +1 -0
- package/dist/spec/spec-discovery.js +78 -0
- package/dist/spec/spec-review.d.ts +36 -0
- package/dist/spec/spec-review.d.ts.map +1 -0
- package/dist/spec/spec-review.js +37 -0
- package/dist/stability-map.d.ts +62 -0
- package/dist/stability-map.d.ts.map +1 -0
- package/dist/stability-map.js +404 -0
- package/dist/start-here.d.ts +49 -0
- package/dist/start-here.d.ts.map +1 -0
- package/dist/start-here.js +259 -0
- package/dist/surface-profile-detect.d.ts +42 -0
- package/dist/surface-profile-detect.d.ts.map +1 -0
- package/dist/surface-profile-detect.js +76 -0
- package/dist/symbol-index.d.ts +108 -0
- package/dist/symbol-index.d.ts.map +1 -0
- package/dist/symbol-index.js +483 -0
- package/dist/task-decompose.d.ts +38 -0
- package/dist/task-decompose.d.ts.map +1 -0
- package/dist/task-decompose.js +154 -0
- package/dist/task-packet.d.ts +104 -0
- package/dist/task-packet.d.ts.map +1 -0
- package/dist/task-packet.js +156 -0
- package/dist/task-ranker.d.ts +51 -0
- package/dist/task-ranker.d.ts.map +1 -0
- package/dist/task-ranker.js +410 -0
- package/dist/task-risk.d.ts +84 -0
- package/dist/task-risk.d.ts.map +1 -0
- package/dist/task-risk.js +731 -0
- package/dist/task-routing-hint-registry.d.ts +36 -0
- package/dist/task-routing-hint-registry.d.ts.map +1 -0
- package/dist/task-routing-hint-registry.js +186 -0
- package/dist/template-authoring.d.ts +113 -0
- package/dist/template-authoring.d.ts.map +1 -0
- package/dist/template-authoring.js +521 -0
- package/dist/template-body-inference-v2.d.ts +19 -0
- package/dist/template-body-inference-v2.d.ts.map +1 -0
- package/dist/template-body-inference-v2.js +468 -0
- package/dist/template-body-inference.d.ts +59 -0
- package/dist/template-body-inference.d.ts.map +1 -0
- package/dist/template-body-inference.js +277 -0
- package/dist/template-drift.d.ts +39 -0
- package/dist/template-drift.d.ts.map +1 -0
- package/dist/template-drift.js +353 -0
- package/dist/template-lint.d.ts +31 -0
- package/dist/template-lint.d.ts.map +1 -0
- package/dist/template-lint.js +113 -0
- package/dist/test-definitions.d.ts +41 -0
- package/dist/test-definitions.d.ts.map +1 -0
- package/dist/test-definitions.js +6 -0
- package/dist/test-impact.d.ts +30 -0
- package/dist/test-impact.d.ts.map +1 -0
- package/dist/test-impact.js +173 -0
- package/dist/test-runner.d.ts +87 -0
- package/dist/test-runner.d.ts.map +1 -0
- package/dist/test-runner.js +560 -0
- package/dist/uncertainty-report.d.ts +46 -0
- package/dist/uncertainty-report.d.ts.map +1 -0
- package/dist/uncertainty-report.js +108 -0
- package/dist/uncertainty.d.ts +38 -0
- package/dist/uncertainty.d.ts.map +1 -0
- package/dist/uncertainty.js +115 -0
- package/dist/universal-search.d.ts +64 -0
- package/dist/universal-search.d.ts.map +1 -0
- package/dist/universal-search.js +347 -0
- package/dist/upgrade-advisor.d.ts +22 -0
- package/dist/upgrade-advisor.d.ts.map +1 -0
- package/dist/upgrade-advisor.js +109 -0
- package/dist/why-file.d.ts +75 -0
- package/dist/why-file.d.ts.map +1 -0
- package/dist/why-file.js +202 -0
- package/dist/workflow-simulation.d.ts +46 -0
- package/dist/workflow-simulation.d.ts.map +1 -0
- package/dist/workflow-simulation.js +154 -0
- package/package.json +65 -0
|
@@ -0,0 +1,277 @@
|
|
|
1
|
+
import { existsSync, readFileSync, statSync } from 'node:fs';
|
|
2
|
+
import * as nodePath from 'node:path';
|
|
3
|
+
const DEFAULT_MAX_BYTES = 20_000;
|
|
4
|
+
const DEFAULT_MAX_LINES = 200;
|
|
5
|
+
/** Maximum count of single-letter / domain-y string literals before we bail. */
|
|
6
|
+
const MAX_DOMAIN_LITERALS = 12;
|
|
7
|
+
/**
|
|
8
|
+
* Read a sample file and produce a minimal, runnable draft template body by
|
|
9
|
+
* replacing concrete identifiers with `<name>` / `<className>` placeholders.
|
|
10
|
+
*
|
|
11
|
+
* Never throws — returns `{ scaffold: null, reason }` on any structural reason
|
|
12
|
+
* to skip. Callers should fall back to the non-scaffolded candidate.
|
|
13
|
+
*/
|
|
14
|
+
export function inferTemplateBody(options) {
|
|
15
|
+
const full = nodePath.isAbsolute(options.sample)
|
|
16
|
+
? options.sample
|
|
17
|
+
: nodePath.join(options.projectRoot, options.sample);
|
|
18
|
+
if (!existsSync(full)) {
|
|
19
|
+
return { scaffold: null, reason: `sample not found: ${options.sample}` };
|
|
20
|
+
}
|
|
21
|
+
const stat = statSync(full);
|
|
22
|
+
const maxBytes = options.maxBytes ?? DEFAULT_MAX_BYTES;
|
|
23
|
+
const maxLines = options.maxLines ?? DEFAULT_MAX_LINES;
|
|
24
|
+
if (stat.size > maxBytes) {
|
|
25
|
+
return {
|
|
26
|
+
scaffold: null,
|
|
27
|
+
reason: `sample too large (${stat.size} > ${maxBytes} bytes)`,
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
const raw = readFileSync(full, 'utf8');
|
|
31
|
+
const lineCount = raw.split(/\r?\n/).length;
|
|
32
|
+
if (lineCount > maxLines) {
|
|
33
|
+
return {
|
|
34
|
+
scaffold: null,
|
|
35
|
+
reason: `sample too long (${lineCount} > ${maxLines} lines)`,
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
// ── Identify the construct token from filename. ────────────────────────
|
|
39
|
+
// file basename → "user.service.ts" → kebab name "user", construct "service".
|
|
40
|
+
const baseName = nodePath.basename(full);
|
|
41
|
+
const constructForKind = constructTokenForKind(options.kind);
|
|
42
|
+
const kebabName = extractKebabName(baseName, constructForKind);
|
|
43
|
+
if (!kebabName) {
|
|
44
|
+
return {
|
|
45
|
+
scaffold: null,
|
|
46
|
+
reason: `could not derive a base name from "${baseName}"`,
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
// ── Detect dominant class / function identifier. ────────────────────────
|
|
50
|
+
const classMatch = findFirstClass(raw);
|
|
51
|
+
const fnMatch = findFirstFunction(raw);
|
|
52
|
+
const componentMatch = findFirstComponent(raw);
|
|
53
|
+
const warnings = [];
|
|
54
|
+
// ── Domain-literal complexity guard. ────────────────────────────────────
|
|
55
|
+
const literals = countStringLiterals(raw);
|
|
56
|
+
if (literals > MAX_DOMAIN_LITERALS) {
|
|
57
|
+
return {
|
|
58
|
+
scaffold: null,
|
|
59
|
+
reason: `sample contains ${literals} string literals — too domain-specific to scaffold`,
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
// ── Complex-imports guard. ──────────────────────────────────────────────
|
|
63
|
+
const imports = extractImports(raw);
|
|
64
|
+
const safeImports = imports.every(isSafeImport);
|
|
65
|
+
if (!safeImports) {
|
|
66
|
+
warnings.push('Sample imports complex paths (relative or local aliases) — scaffold preserves them as TODOs.');
|
|
67
|
+
}
|
|
68
|
+
if (imports.length > 6) {
|
|
69
|
+
warnings.push(`Sample has ${imports.length} imports; scaffold keeps them with TODO placeholders.`);
|
|
70
|
+
}
|
|
71
|
+
// ── Build placeholder-substituted body. ────────────────────────────────
|
|
72
|
+
let body = raw;
|
|
73
|
+
const variables = [
|
|
74
|
+
{
|
|
75
|
+
name: 'name',
|
|
76
|
+
description: 'kebab-case base name (e.g. user, order, billing)',
|
|
77
|
+
default: kebabName,
|
|
78
|
+
},
|
|
79
|
+
];
|
|
80
|
+
// Replace class name with <ClassName> placeholder if it exists.
|
|
81
|
+
if (classMatch) {
|
|
82
|
+
const ph = '<className>';
|
|
83
|
+
body = replaceWholeWord(body, classMatch.name, ph);
|
|
84
|
+
variables.push({
|
|
85
|
+
name: 'className',
|
|
86
|
+
description: 'PascalCase class identifier',
|
|
87
|
+
default: classMatch.name,
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
// For utilities: replace top-level function name with <fnName>.
|
|
91
|
+
if (options.kind === 'utility' && fnMatch && !classMatch) {
|
|
92
|
+
const ph = '<fnName>';
|
|
93
|
+
body = replaceWholeWord(body, fnMatch.name, ph);
|
|
94
|
+
variables.push({
|
|
95
|
+
name: 'fnName',
|
|
96
|
+
description: 'camelCase function identifier',
|
|
97
|
+
default: fnMatch.name,
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
// For components: replace component name with <ComponentName>.
|
|
101
|
+
if (options.kind === 'component' && componentMatch && !classMatch) {
|
|
102
|
+
const ph = '<componentName>';
|
|
103
|
+
body = replaceWholeWord(body, componentMatch.name, ph);
|
|
104
|
+
variables.push({
|
|
105
|
+
name: 'componentName',
|
|
106
|
+
description: 'PascalCase component identifier',
|
|
107
|
+
default: componentMatch.name,
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
// Replace kebab base name everywhere it appears as a whole token.
|
|
111
|
+
// Skip the construct token portion (e.g. "service") to avoid clobbering.
|
|
112
|
+
body = replaceWholeWord(body, kebabName, '<name>');
|
|
113
|
+
// ── Confidence ─────────────────────────────────────────────────────────
|
|
114
|
+
let confidence = 'high';
|
|
115
|
+
if (!classMatch && options.kind === 'service') {
|
|
116
|
+
confidence = 'medium';
|
|
117
|
+
warnings.push('No class declaration found in sample — service shape is a best guess.');
|
|
118
|
+
}
|
|
119
|
+
if (!fnMatch && options.kind === 'utility') {
|
|
120
|
+
confidence = 'medium';
|
|
121
|
+
warnings.push('No top-level function found in sample — utility shape is a best guess.');
|
|
122
|
+
}
|
|
123
|
+
if (!safeImports || imports.length > 6) {
|
|
124
|
+
confidence = confidence === 'high' ? 'medium' : confidence;
|
|
125
|
+
}
|
|
126
|
+
// ── Final scaffold ─────────────────────────────────────────────────────
|
|
127
|
+
const baseId = options.baseId ?? `inferred.typescript.${options.kind}`;
|
|
128
|
+
const targetPath = suggestedTargetPath(options.kind, constructForKind);
|
|
129
|
+
const name = displayNameForKind(options.kind);
|
|
130
|
+
const description = descriptionForKind(options.kind);
|
|
131
|
+
return {
|
|
132
|
+
scaffold: {
|
|
133
|
+
id: baseId,
|
|
134
|
+
name,
|
|
135
|
+
description,
|
|
136
|
+
variables,
|
|
137
|
+
targetPath,
|
|
138
|
+
content: body,
|
|
139
|
+
confidence,
|
|
140
|
+
sample: nodePath.relative(options.projectRoot, full),
|
|
141
|
+
warnings,
|
|
142
|
+
},
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
// ── Helpers ──────────────────────────────────────────────────────────────
|
|
146
|
+
function constructTokenForKind(kind) {
|
|
147
|
+
switch (kind) {
|
|
148
|
+
case 'service':
|
|
149
|
+
return 'service';
|
|
150
|
+
case 'utility':
|
|
151
|
+
return 'util';
|
|
152
|
+
case 'test':
|
|
153
|
+
return 'spec';
|
|
154
|
+
case 'component':
|
|
155
|
+
return 'component';
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
function suggestedTargetPath(kind, construct) {
|
|
159
|
+
switch (kind) {
|
|
160
|
+
case 'service':
|
|
161
|
+
return `src/services/<name>.${construct}.ts`;
|
|
162
|
+
case 'utility':
|
|
163
|
+
return `src/utils/<name>.${construct}.ts`;
|
|
164
|
+
case 'test':
|
|
165
|
+
return `tests/<name>.${construct}.ts`;
|
|
166
|
+
case 'component':
|
|
167
|
+
return `src/components/<componentName>/<componentName>.${construct}.tsx`;
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
function displayNameForKind(kind) {
|
|
171
|
+
switch (kind) {
|
|
172
|
+
case 'service':
|
|
173
|
+
return 'TypeScript service';
|
|
174
|
+
case 'utility':
|
|
175
|
+
return 'TypeScript utility';
|
|
176
|
+
case 'test':
|
|
177
|
+
return 'TypeScript spec';
|
|
178
|
+
case 'component':
|
|
179
|
+
return 'TypeScript component';
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
function descriptionForKind(kind) {
|
|
183
|
+
switch (kind) {
|
|
184
|
+
case 'service':
|
|
185
|
+
return 'Generate a new service modeled on the most representative sample in src/services/.';
|
|
186
|
+
case 'utility':
|
|
187
|
+
return 'Generate a new utility module modeled on src/utils/.';
|
|
188
|
+
case 'test':
|
|
189
|
+
return 'Generate a new spec/test file modeled on the project test layout.';
|
|
190
|
+
case 'component':
|
|
191
|
+
return 'Generate a new UI component modeled on existing components.';
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
function extractKebabName(filename, construct) {
|
|
195
|
+
// Strip extension and the construct suffix.
|
|
196
|
+
// Accepts forms like:
|
|
197
|
+
// user.service.ts → user
|
|
198
|
+
// format-email.util.ts → format-email
|
|
199
|
+
// user.spec.ts / user.test.ts → user
|
|
200
|
+
// Greeting.component.tsx → greeting
|
|
201
|
+
const noExt = filename.replace(/\.(tsx?|jsx?)$/i, '');
|
|
202
|
+
let base = noExt;
|
|
203
|
+
if (construct === 'spec') {
|
|
204
|
+
base = base.replace(/\.(spec|test)$/i, '');
|
|
205
|
+
}
|
|
206
|
+
else {
|
|
207
|
+
const re = new RegExp(`\\.${construct}$`, 'i');
|
|
208
|
+
base = base.replace(re, '');
|
|
209
|
+
}
|
|
210
|
+
if (!base || base === noExt)
|
|
211
|
+
return null;
|
|
212
|
+
// Normalize to kebab-case for the default value.
|
|
213
|
+
const kebab = base
|
|
214
|
+
.replace(/([a-z0-9])([A-Z])/g, '$1-$2')
|
|
215
|
+
.replace(/_+/g, '-')
|
|
216
|
+
.toLowerCase();
|
|
217
|
+
if (!/^[a-z0-9][a-z0-9-]*$/.test(kebab))
|
|
218
|
+
return null;
|
|
219
|
+
return kebab;
|
|
220
|
+
}
|
|
221
|
+
function findFirstClass(src) {
|
|
222
|
+
const m = /\bclass\s+([A-Z][A-Za-z0-9_]*)/m.exec(src);
|
|
223
|
+
return m ? { name: m[1] } : null;
|
|
224
|
+
}
|
|
225
|
+
function findFirstFunction(src) {
|
|
226
|
+
// Try `export function name`, `export const name = (`, `function name`.
|
|
227
|
+
const exportFn = /\bexport\s+function\s+([a-zA-Z_][A-Za-z0-9_]*)/m.exec(src);
|
|
228
|
+
if (exportFn)
|
|
229
|
+
return { name: exportFn[1] };
|
|
230
|
+
const exportConst = /\bexport\s+const\s+([a-zA-Z_][A-Za-z0-9_]*)\s*=\s*(?:async\s*)?\(/m.exec(src);
|
|
231
|
+
if (exportConst)
|
|
232
|
+
return { name: exportConst[1] };
|
|
233
|
+
const plainFn = /\bfunction\s+([a-zA-Z_][A-Za-z0-9_]*)/m.exec(src);
|
|
234
|
+
if (plainFn)
|
|
235
|
+
return { name: plainFn[1] };
|
|
236
|
+
return null;
|
|
237
|
+
}
|
|
238
|
+
function findFirstComponent(src) {
|
|
239
|
+
// `export const Foo: FC = ` / `export function Foo(` / `export default function Foo`.
|
|
240
|
+
const m = /\bexport\s+(?:default\s+)?(?:function|const)\s+([A-Z][A-Za-z0-9_]*)/m.exec(src);
|
|
241
|
+
return m ? { name: m[1] } : null;
|
|
242
|
+
}
|
|
243
|
+
function countStringLiterals(src) {
|
|
244
|
+
let count = 0;
|
|
245
|
+
// Naive but bounded: count single/double/backtick strings of length > 2.
|
|
246
|
+
const re = /(['"`])(?:\\.|(?!\1).){3,}\1/g;
|
|
247
|
+
while (re.exec(src))
|
|
248
|
+
count += 1;
|
|
249
|
+
if (count > MAX_DOMAIN_LITERALS)
|
|
250
|
+
return count;
|
|
251
|
+
return count;
|
|
252
|
+
}
|
|
253
|
+
function extractImports(src) {
|
|
254
|
+
const out = [];
|
|
255
|
+
const re = /\bimport\s+(?:.|\n)*?from\s+['"]([^'"]+)['"]\s*;?/g;
|
|
256
|
+
let m;
|
|
257
|
+
while ((m = re.exec(src)))
|
|
258
|
+
out.push(m[1]);
|
|
259
|
+
return out;
|
|
260
|
+
}
|
|
261
|
+
function isSafeImport(spec) {
|
|
262
|
+
// Node built-ins, framework packages, and bare specifiers are safe.
|
|
263
|
+
// Relative imports / aliased imports require user attention.
|
|
264
|
+
if (spec.startsWith('.') || spec.startsWith('/'))
|
|
265
|
+
return false;
|
|
266
|
+
if (spec.startsWith('@') && spec.includes('/'))
|
|
267
|
+
return true;
|
|
268
|
+
if (/^[a-z][a-z0-9-]*(?:\/[^?]+)?$/i.test(spec))
|
|
269
|
+
return true;
|
|
270
|
+
return false;
|
|
271
|
+
}
|
|
272
|
+
function replaceWholeWord(src, needle, replacement) {
|
|
273
|
+
// Escape regex specials in `needle`, then replace whole-token matches.
|
|
274
|
+
const esc = needle.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
275
|
+
const re = new RegExp(`\\b${esc}\\b`, 'g');
|
|
276
|
+
return src.replace(re, replacement);
|
|
277
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import type { ISharkcraftInspection } from './sharkcraft-inspector.js';
|
|
2
|
+
export declare const TEMPLATE_DRIFT_SCHEMA = "sharkcraft.template-drift/v1";
|
|
3
|
+
export declare enum TemplateDriftStatus {
|
|
4
|
+
Pass = "pass",
|
|
5
|
+
Warn = "warn",
|
|
6
|
+
Fail = "fail"
|
|
7
|
+
}
|
|
8
|
+
export interface ITemplateDriftIssue {
|
|
9
|
+
severity: 'info' | 'warning' | 'error';
|
|
10
|
+
code: string;
|
|
11
|
+
message: string;
|
|
12
|
+
suggestedFix?: string;
|
|
13
|
+
}
|
|
14
|
+
export interface ITemplateDriftEntry {
|
|
15
|
+
templateId: string;
|
|
16
|
+
templateName?: string;
|
|
17
|
+
status: TemplateDriftStatus;
|
|
18
|
+
samplePaths: readonly string[];
|
|
19
|
+
issues: ReadonlyArray<ITemplateDriftIssue>;
|
|
20
|
+
}
|
|
21
|
+
export interface ITemplateDriftReport {
|
|
22
|
+
schema: typeof TEMPLATE_DRIFT_SCHEMA;
|
|
23
|
+
generatedAt: string;
|
|
24
|
+
totalTemplates: number;
|
|
25
|
+
pass: number;
|
|
26
|
+
warn: number;
|
|
27
|
+
fail: number;
|
|
28
|
+
entries: ReadonlyArray<ITemplateDriftEntry>;
|
|
29
|
+
}
|
|
30
|
+
export interface ITemplateDriftCheckOptions {
|
|
31
|
+
/** When set, only the template with this id is verified. */
|
|
32
|
+
templateId?: string;
|
|
33
|
+
/** When set, only templates contributed by this pack are verified. */
|
|
34
|
+
packId?: string;
|
|
35
|
+
/** Sample variable values for templates with required vars (key→string). */
|
|
36
|
+
sampleVars?: Readonly<Record<string, string>>;
|
|
37
|
+
}
|
|
38
|
+
export declare function buildTemplateDriftReport(inspection: ISharkcraftInspection, options?: ITemplateDriftCheckOptions): ITemplateDriftReport;
|
|
39
|
+
//# sourceMappingURL=template-drift.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"template-drift.d.ts","sourceRoot":"","sources":["../src/template-drift.ts"],"names":[],"mappings":"AAqBA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AAEvE,eAAO,MAAM,qBAAqB,iCAAiC,CAAC;AAEpE,oBAAY,mBAAmB;IAC7B,IAAI,SAAS;IACb,IAAI,SAAS;IACb,IAAI,SAAS;CACd;AAED,MAAM,WAAW,mBAAmB;IAClC,QAAQ,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAAC;IACvC,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,mBAAmB;IAClC,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,mBAAmB,CAAC;IAC5B,WAAW,EAAE,SAAS,MAAM,EAAE,CAAC;IAC/B,MAAM,EAAE,aAAa,CAAC,mBAAmB,CAAC,CAAC;CAC5C;AAED,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,OAAO,qBAAqB,CAAC;IACrC,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,MAAM,CAAC;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,aAAa,CAAC,mBAAmB,CAAC,CAAC;CAC7C;AAED,MAAM,WAAW,0BAA0B;IACzC,4DAA4D;IAC5D,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,sEAAsE;IACtE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,4EAA4E;IAC5E,UAAU,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;CAC/C;AAkSD,wBAAgB,wBAAwB,CACtC,UAAU,EAAE,qBAAqB,EACjC,OAAO,GAAE,0BAA+B,GACvC,oBAAoB,CA8DtB"}
|
|
@@ -0,0 +1,353 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Template drift verification.
|
|
3
|
+
*
|
|
4
|
+
* For each registered template (local + pack), produces a sample dry-run
|
|
5
|
+
* to verify:
|
|
6
|
+
* - target paths align with the registered path conventions.
|
|
7
|
+
* - no forbidden legacy patterns (templates declare these via
|
|
8
|
+
* plugin contract templates).
|
|
9
|
+
* - referenced barrels exist when an `export` op points at them.
|
|
10
|
+
* - insert / replace anchors are non-empty (and exist when target is
|
|
11
|
+
* also created in the same template).
|
|
12
|
+
* - related construct / template / helper / playbook / policy ids
|
|
13
|
+
* resolve.
|
|
14
|
+
*
|
|
15
|
+
* Read-only — no shell, no network, no source writes.
|
|
16
|
+
*
|
|
17
|
+
* Schema: sharkcraft.template-drift/v1
|
|
18
|
+
*/
|
|
19
|
+
import { existsSync } from 'node:fs';
|
|
20
|
+
import * as nodePath from 'node:path';
|
|
21
|
+
export const TEMPLATE_DRIFT_SCHEMA = 'sharkcraft.template-drift/v1';
|
|
22
|
+
export var TemplateDriftStatus;
|
|
23
|
+
(function (TemplateDriftStatus) {
|
|
24
|
+
TemplateDriftStatus["Pass"] = "pass";
|
|
25
|
+
TemplateDriftStatus["Warn"] = "warn";
|
|
26
|
+
TemplateDriftStatus["Fail"] = "fail";
|
|
27
|
+
})(TemplateDriftStatus || (TemplateDriftStatus = {}));
|
|
28
|
+
const SAMPLE_NAME = 'sample-feature';
|
|
29
|
+
/**
|
|
30
|
+
* Templates can declare their own forbidden-path fragments via
|
|
31
|
+
* `template.metadata.forbiddenPathFragments` (optional). The engine no
|
|
32
|
+
* longer hardcodes per-template fragments.
|
|
33
|
+
*/
|
|
34
|
+
function buildSampleValues(template, override) {
|
|
35
|
+
const values = {};
|
|
36
|
+
for (const v of template.variables ?? []) {
|
|
37
|
+
const name = v.name ?? v.key ?? '';
|
|
38
|
+
if (!name)
|
|
39
|
+
continue;
|
|
40
|
+
if (override && override[name] !== undefined)
|
|
41
|
+
values[name] = override[name];
|
|
42
|
+
else if (v.default !== undefined) {
|
|
43
|
+
values[name] = String(v.default);
|
|
44
|
+
}
|
|
45
|
+
else if (name.toLowerCase() === 'name' || name === 'pluginName' || name === 'pluginKey') {
|
|
46
|
+
values[name] = SAMPLE_NAME;
|
|
47
|
+
}
|
|
48
|
+
else {
|
|
49
|
+
values[name] = 'sample';
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
return values;
|
|
53
|
+
}
|
|
54
|
+
function describeForbiddenPaths(template) {
|
|
55
|
+
const meta = template.metadata;
|
|
56
|
+
if (meta?.forbiddenPathFragments && Array.isArray(meta.forbiddenPathFragments)) {
|
|
57
|
+
return meta.forbiddenPathFragments;
|
|
58
|
+
}
|
|
59
|
+
return [];
|
|
60
|
+
}
|
|
61
|
+
function safeRender(template, values) {
|
|
62
|
+
const paths = [];
|
|
63
|
+
const warnings = [];
|
|
64
|
+
const ops = [];
|
|
65
|
+
try {
|
|
66
|
+
if (typeof template.files === 'function') {
|
|
67
|
+
const files = template.files(values);
|
|
68
|
+
for (const f of files) {
|
|
69
|
+
paths.push(f.targetPath);
|
|
70
|
+
ops.push({ kind: 'create', target: f.targetPath });
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
if (typeof template.changes === 'function') {
|
|
74
|
+
const changes = template.changes(values);
|
|
75
|
+
for (const c of changes) {
|
|
76
|
+
paths.push(c.targetPath);
|
|
77
|
+
ops.push({
|
|
78
|
+
kind: c.operation.kind,
|
|
79
|
+
target: c.targetPath,
|
|
80
|
+
...((c.operation.kind === 'insert-after' || c.operation.kind === 'insert-before')
|
|
81
|
+
? { anchor: c.operation.anchor }
|
|
82
|
+
: {}),
|
|
83
|
+
...((c.operation.kind === 'export')
|
|
84
|
+
? { from: c.operation.from }
|
|
85
|
+
: {}),
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
if (typeof template.files !== 'function' &&
|
|
90
|
+
typeof template.changes !== 'function' &&
|
|
91
|
+
template.targetPath) {
|
|
92
|
+
const tp = typeof template.targetPath === 'function' ? template.targetPath(values) : template.targetPath;
|
|
93
|
+
paths.push(tp);
|
|
94
|
+
ops.push({ kind: 'create', target: tp });
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
catch (e) {
|
|
98
|
+
warnings.push(`render threw: ${e.message}`);
|
|
99
|
+
}
|
|
100
|
+
return { paths, warnings, ops };
|
|
101
|
+
}
|
|
102
|
+
function checkPathConventions(inspection, paths) {
|
|
103
|
+
const issues = [];
|
|
104
|
+
// Path conventions are name patterns; we only flag a path that obviously
|
|
105
|
+
// mismatches every applicable convention. The conservative default: if no
|
|
106
|
+
// convention names match any sample path, emit one info issue per path.
|
|
107
|
+
const svc = inspection.pathService;
|
|
108
|
+
const conventions = svc && typeof svc.list === 'function' ? svc.list() : [];
|
|
109
|
+
if (conventions.length === 0)
|
|
110
|
+
return issues;
|
|
111
|
+
for (const p of paths) {
|
|
112
|
+
let matched = false;
|
|
113
|
+
for (const c of conventions) {
|
|
114
|
+
const pattern = c.pattern;
|
|
115
|
+
if (!pattern)
|
|
116
|
+
continue;
|
|
117
|
+
// very lightweight substring check — these are heuristics.
|
|
118
|
+
const cleaned = pattern.replace(/\{.*?\}/g, '').replace(/[.*+?^${}()|[\]\\]/g, '');
|
|
119
|
+
if (cleaned.length > 4 && p.includes(cleaned)) {
|
|
120
|
+
matched = true;
|
|
121
|
+
break;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
if (!matched) {
|
|
125
|
+
issues.push({
|
|
126
|
+
severity: 'info',
|
|
127
|
+
code: 'path-no-convention',
|
|
128
|
+
message: `Sample path "${p}" does not match any registered path convention.`,
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
return issues;
|
|
133
|
+
}
|
|
134
|
+
function checkForbiddenFragments(template, paths) {
|
|
135
|
+
const issues = [];
|
|
136
|
+
const forbidden = describeForbiddenPaths(template);
|
|
137
|
+
if (forbidden.length === 0)
|
|
138
|
+
return issues;
|
|
139
|
+
for (const p of paths) {
|
|
140
|
+
for (const frag of forbidden) {
|
|
141
|
+
if (p.includes(frag)) {
|
|
142
|
+
issues.push({
|
|
143
|
+
severity: 'error',
|
|
144
|
+
code: 'forbidden-legacy-path',
|
|
145
|
+
message: `Sample path "${p}" contains forbidden legacy fragment "${frag}". Update the template to use canonical paths.`,
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
return issues;
|
|
151
|
+
}
|
|
152
|
+
function checkBarrelTargets(projectRoot, ops) {
|
|
153
|
+
const issues = [];
|
|
154
|
+
for (const op of ops) {
|
|
155
|
+
if (op.kind !== 'export')
|
|
156
|
+
continue;
|
|
157
|
+
const full = nodePath.join(projectRoot, op.target);
|
|
158
|
+
if (!existsSync(full)) {
|
|
159
|
+
issues.push({
|
|
160
|
+
severity: 'warning',
|
|
161
|
+
code: 'missing-barrel',
|
|
162
|
+
message: `export op references missing barrel "${op.target}".`,
|
|
163
|
+
suggestedFix: 'Create the barrel before applying, or update the template target.',
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
return issues;
|
|
168
|
+
}
|
|
169
|
+
function checkRelatedIds(inspection, template) {
|
|
170
|
+
const issues = [];
|
|
171
|
+
for (const id of template.related ?? []) {
|
|
172
|
+
// related ids are knowledge / construct / template / playbook — try
|
|
173
|
+
// them all.
|
|
174
|
+
const knowledge = inspection.index.get(id);
|
|
175
|
+
const tmpl = inspection.templates.find((t) => t.id === id);
|
|
176
|
+
if (!knowledge && !tmpl) {
|
|
177
|
+
issues.push({
|
|
178
|
+
severity: 'info',
|
|
179
|
+
code: 'related-id-unresolved',
|
|
180
|
+
message: `related id "${id}" not found in knowledge or template registries.`,
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
return issues;
|
|
185
|
+
}
|
|
186
|
+
function checkAnchorsNonEmpty(ops) {
|
|
187
|
+
const issues = [];
|
|
188
|
+
for (const op of ops) {
|
|
189
|
+
if ((op.kind === 'insert-after' || op.kind === 'insert-before') && !op.anchor) {
|
|
190
|
+
issues.push({
|
|
191
|
+
severity: 'error',
|
|
192
|
+
code: 'missing-anchor',
|
|
193
|
+
message: `${op.kind} op on "${op.target}" has no anchor.`,
|
|
194
|
+
});
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
return issues;
|
|
198
|
+
}
|
|
199
|
+
/**
|
|
200
|
+
* Verify the template's `producedAnchors[]` metadata is consistent with
|
|
201
|
+
* the rendered output. For every declared producer, the body of the target
|
|
202
|
+
* file must contain the anchor literal. Missing producers surface as
|
|
203
|
+
* `missing-produced-anchor` issues (warning by default).
|
|
204
|
+
*/
|
|
205
|
+
function checkProducedAnchors(template, values) {
|
|
206
|
+
const issues = [];
|
|
207
|
+
const declared = template.metadata?.producedAnchors;
|
|
208
|
+
if (!declared || declared.length === 0)
|
|
209
|
+
return issues;
|
|
210
|
+
const rendered = new Map(); // path → body
|
|
211
|
+
try {
|
|
212
|
+
if (typeof template.files === 'function') {
|
|
213
|
+
for (const f of template.files(values))
|
|
214
|
+
rendered.set(f.targetPath, f.content);
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
catch {
|
|
218
|
+
// render errors already surfaced by safeRender; skip here.
|
|
219
|
+
}
|
|
220
|
+
for (const decl of declared) {
|
|
221
|
+
// `in` may be a glob or a literal path. We do a substring/glob-ish match.
|
|
222
|
+
const candidates = [...rendered.entries()].filter(([p]) => pathMatchesPattern(p, decl.in));
|
|
223
|
+
if (candidates.length === 0) {
|
|
224
|
+
issues.push({
|
|
225
|
+
severity: 'warning',
|
|
226
|
+
code: 'produced-anchor-target-missing',
|
|
227
|
+
message: `producedAnchors entry "${decl.anchor}" refers to "${decl.in}", but the template did not render any file matching that pattern.`,
|
|
228
|
+
});
|
|
229
|
+
continue;
|
|
230
|
+
}
|
|
231
|
+
const anyMatch = candidates.some(([, body]) => body.includes(decl.anchor));
|
|
232
|
+
if (!anyMatch) {
|
|
233
|
+
issues.push({
|
|
234
|
+
severity: 'error',
|
|
235
|
+
code: 'missing-produced-anchor',
|
|
236
|
+
message: `Template declares producedAnchor "${decl.anchor}" in "${decl.in}", but the rendered file does not contain it.`,
|
|
237
|
+
suggestedFix: `Add the anchor literal to the rendered ${decl.in} or remove the declaration.`,
|
|
238
|
+
});
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
return issues;
|
|
242
|
+
}
|
|
243
|
+
/**
|
|
244
|
+
* Verify the template's `requiredAnchors[]` metadata against the union
|
|
245
|
+
* of all `producedAnchors[]` from every registered template (local + pack).
|
|
246
|
+
* Surfaces `missing-required-anchor` when no producer exists.
|
|
247
|
+
*/
|
|
248
|
+
function checkRequiredAnchors(template, allProduced) {
|
|
249
|
+
const issues = [];
|
|
250
|
+
const required = template.metadata?.requiredAnchors;
|
|
251
|
+
if (!required || required.length === 0)
|
|
252
|
+
return issues;
|
|
253
|
+
for (const decl of required) {
|
|
254
|
+
let found = false;
|
|
255
|
+
for (const [pattern, anchors] of allProduced) {
|
|
256
|
+
if (pathMatchesPattern(pattern, decl.in) || pathMatchesPattern(decl.in, pattern)) {
|
|
257
|
+
if (anchors.has(decl.anchor)) {
|
|
258
|
+
found = true;
|
|
259
|
+
break;
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
if (!found) {
|
|
264
|
+
issues.push({
|
|
265
|
+
severity: 'warning',
|
|
266
|
+
code: 'missing-required-anchor',
|
|
267
|
+
message: `Template requires anchor "${decl.anchor}" in "${decl.in}", but no other template declares it as a producer.`,
|
|
268
|
+
suggestedFix: `Add producedAnchors metadata to the scaffold that creates "${decl.in}", or declare a registration hint.`,
|
|
269
|
+
});
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
return issues;
|
|
273
|
+
}
|
|
274
|
+
function pathMatchesPattern(path, pattern) {
|
|
275
|
+
if (pattern === path)
|
|
276
|
+
return true;
|
|
277
|
+
if (!pattern.includes('*'))
|
|
278
|
+
return path === pattern;
|
|
279
|
+
const escaped = pattern.replace(/[.+?^${}()|[\]\\]/g, '\\$&').replace(/\*/g, '.*');
|
|
280
|
+
return new RegExp(`^${escaped}$`).test(path);
|
|
281
|
+
}
|
|
282
|
+
function classify(issues) {
|
|
283
|
+
if (issues.some((i) => i.severity === 'error'))
|
|
284
|
+
return TemplateDriftStatus.Fail;
|
|
285
|
+
if (issues.some((i) => i.severity === 'warning'))
|
|
286
|
+
return TemplateDriftStatus.Warn;
|
|
287
|
+
return TemplateDriftStatus.Pass;
|
|
288
|
+
}
|
|
289
|
+
export function buildTemplateDriftReport(inspection, options = {}) {
|
|
290
|
+
const entries = [];
|
|
291
|
+
const all = inspection.templates;
|
|
292
|
+
const filtered = options.templateId ? all.filter((t) => t.id === options.templateId) : all;
|
|
293
|
+
// Build the cross-template anchor producer map ONCE so each entry
|
|
294
|
+
// can look up "is anchor X declared by some template?".
|
|
295
|
+
const allProduced = new Map();
|
|
296
|
+
for (const t of all) {
|
|
297
|
+
const declared = t.metadata?.producedAnchors;
|
|
298
|
+
if (!declared || declared.length === 0)
|
|
299
|
+
continue;
|
|
300
|
+
for (const decl of declared) {
|
|
301
|
+
const existing = allProduced.get(decl.in) ?? new Set();
|
|
302
|
+
const next = new Set(existing);
|
|
303
|
+
next.add(decl.anchor);
|
|
304
|
+
allProduced.set(decl.in, next);
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
for (const t of filtered) {
|
|
308
|
+
const values = buildSampleValues(t, options.sampleVars);
|
|
309
|
+
const { paths, warnings: renderWarnings, ops } = safeRender(t, values);
|
|
310
|
+
const renderIssues = renderWarnings.map((w) => ({
|
|
311
|
+
severity: 'warning',
|
|
312
|
+
code: 'render-warning',
|
|
313
|
+
message: w,
|
|
314
|
+
}));
|
|
315
|
+
const allIssues = [
|
|
316
|
+
...renderIssues,
|
|
317
|
+
...checkForbiddenFragments(t, paths),
|
|
318
|
+
...checkPathConventions(inspection, paths),
|
|
319
|
+
...checkBarrelTargets(inspection.projectRoot, ops),
|
|
320
|
+
...checkRelatedIds(inspection, t),
|
|
321
|
+
...checkAnchorsNonEmpty(ops),
|
|
322
|
+
...checkProducedAnchors(t, values),
|
|
323
|
+
...checkRequiredAnchors(t, allProduced),
|
|
324
|
+
];
|
|
325
|
+
entries.push({
|
|
326
|
+
templateId: t.id,
|
|
327
|
+
templateName: t.name,
|
|
328
|
+
status: classify(allIssues),
|
|
329
|
+
samplePaths: paths,
|
|
330
|
+
issues: allIssues,
|
|
331
|
+
});
|
|
332
|
+
}
|
|
333
|
+
let pass = 0;
|
|
334
|
+
let warn = 0;
|
|
335
|
+
let fail = 0;
|
|
336
|
+
for (const e of entries) {
|
|
337
|
+
if (e.status === TemplateDriftStatus.Pass)
|
|
338
|
+
pass += 1;
|
|
339
|
+
else if (e.status === TemplateDriftStatus.Warn)
|
|
340
|
+
warn += 1;
|
|
341
|
+
else
|
|
342
|
+
fail += 1;
|
|
343
|
+
}
|
|
344
|
+
return {
|
|
345
|
+
schema: TEMPLATE_DRIFT_SCHEMA,
|
|
346
|
+
generatedAt: new Date().toISOString(),
|
|
347
|
+
totalTemplates: filtered.length,
|
|
348
|
+
pass,
|
|
349
|
+
warn,
|
|
350
|
+
fail,
|
|
351
|
+
entries,
|
|
352
|
+
};
|
|
353
|
+
}
|