@decibelsystems/tools 2.0.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/LICENSE +21 -0
- package/README.md +342 -0
- package/dist/agentic/compiler.d.ts +21 -0
- package/dist/agentic/compiler.d.ts.map +1 -0
- package/dist/agentic/compiler.js +267 -0
- package/dist/agentic/compiler.js.map +1 -0
- package/dist/agentic/golden.d.ts +25 -0
- package/dist/agentic/golden.d.ts.map +1 -0
- package/dist/agentic/golden.js +255 -0
- package/dist/agentic/golden.js.map +1 -0
- package/dist/agentic/index.d.ts +17 -0
- package/dist/agentic/index.d.ts.map +1 -0
- package/dist/agentic/index.js +153 -0
- package/dist/agentic/index.js.map +1 -0
- package/dist/agentic/linter.d.ts +20 -0
- package/dist/agentic/linter.d.ts.map +1 -0
- package/dist/agentic/linter.js +340 -0
- package/dist/agentic/linter.js.map +1 -0
- package/dist/agentic/renderer.d.ts +17 -0
- package/dist/agentic/renderer.d.ts.map +1 -0
- package/dist/agentic/renderer.js +277 -0
- package/dist/agentic/renderer.js.map +1 -0
- package/dist/agentic/types.d.ts +199 -0
- package/dist/agentic/types.d.ts.map +1 -0
- package/dist/agentic/types.js +8 -0
- package/dist/agentic/types.js.map +1 -0
- package/dist/architectAdrs.d.ts +32 -0
- package/dist/architectAdrs.d.ts.map +1 -0
- package/dist/architectAdrs.js +162 -0
- package/dist/architectAdrs.js.map +1 -0
- package/dist/client/facade-client.d.ts +41 -0
- package/dist/client/facade-client.d.ts.map +1 -0
- package/dist/client/facade-client.js +243 -0
- package/dist/client/facade-client.js.map +1 -0
- package/dist/client/index.d.ts +4 -0
- package/dist/client/index.d.ts.map +1 -0
- package/dist/client/index.js +18 -0
- package/dist/client/index.js.map +1 -0
- package/dist/client/transports.d.ts +78 -0
- package/dist/client/transports.d.ts.map +1 -0
- package/dist/client/transports.js +258 -0
- package/dist/client/transports.js.map +1 -0
- package/dist/client/types.d.ts +49 -0
- package/dist/client/types.d.ts.map +1 -0
- package/dist/client/types.js +8 -0
- package/dist/client/types.js.map +1 -0
- package/dist/config.d.ts +8 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +19 -0
- package/dist/config.js.map +1 -0
- package/dist/daemon.d.ts +77 -0
- package/dist/daemon.d.ts.map +1 -0
- package/dist/daemon.js +374 -0
- package/dist/daemon.js.map +1 -0
- package/dist/daemonConfig.d.ts +43 -0
- package/dist/daemonConfig.d.ts.map +1 -0
- package/dist/daemonConfig.js +113 -0
- package/dist/daemonConfig.js.map +1 -0
- package/dist/dataRoot.d.ts +5 -0
- package/dist/dataRoot.d.ts.map +1 -0
- package/dist/dataRoot.js +23 -0
- package/dist/dataRoot.js.map +1 -0
- package/dist/decibelPaths.d.ts +42 -0
- package/dist/decibelPaths.d.ts.map +1 -0
- package/dist/decibelPaths.js +150 -0
- package/dist/decibelPaths.js.map +1 -0
- package/dist/facades/definitions.d.ts +6 -0
- package/dist/facades/definitions.d.ts.map +1 -0
- package/dist/facades/definitions.js +450 -0
- package/dist/facades/definitions.js.map +1 -0
- package/dist/facades/index.d.ts +27 -0
- package/dist/facades/index.d.ts.map +1 -0
- package/dist/facades/index.js +124 -0
- package/dist/facades/index.js.map +1 -0
- package/dist/facades/types.d.ts +38 -0
- package/dist/facades/types.d.ts.map +1 -0
- package/dist/facades/types.js +8 -0
- package/dist/facades/types.js.map +1 -0
- package/dist/httpServer.d.ts +66 -0
- package/dist/httpServer.d.ts.map +1 -0
- package/dist/httpServer.js +1723 -0
- package/dist/httpServer.js.map +1 -0
- package/dist/kernel.d.ts +87 -0
- package/dist/kernel.d.ts.map +1 -0
- package/dist/kernel.js +256 -0
- package/dist/kernel.js.map +1 -0
- package/dist/lib/agent-services/assumptions.d.ts +16 -0
- package/dist/lib/agent-services/assumptions.d.ts.map +1 -0
- package/dist/lib/agent-services/assumptions.js +284 -0
- package/dist/lib/agent-services/assumptions.js.map +1 -0
- package/dist/lib/agent-services/context-pack.d.ts +6 -0
- package/dist/lib/agent-services/context-pack.d.ts.map +1 -0
- package/dist/lib/agent-services/context-pack.js +354 -0
- package/dist/lib/agent-services/context-pack.js.map +1 -0
- package/dist/lib/agent-services/drift-guard.d.ts +14 -0
- package/dist/lib/agent-services/drift-guard.d.ts.map +1 -0
- package/dist/lib/agent-services/drift-guard.js +355 -0
- package/dist/lib/agent-services/drift-guard.js.map +1 -0
- package/dist/lib/agent-services/index.d.ts +5 -0
- package/dist/lib/agent-services/index.d.ts.map +1 -0
- package/dist/lib/agent-services/index.js +10 -0
- package/dist/lib/agent-services/index.js.map +1 -0
- package/dist/lib/benchmark.d.ts +110 -0
- package/dist/lib/benchmark.d.ts.map +1 -0
- package/dist/lib/benchmark.js +338 -0
- package/dist/lib/benchmark.js.map +1 -0
- package/dist/lib/supabase.d.ts +123 -0
- package/dist/lib/supabase.d.ts.map +1 -0
- package/dist/lib/supabase.js +91 -0
- package/dist/lib/supabase.js.map +1 -0
- package/dist/license.d.ts +30 -0
- package/dist/license.d.ts.map +1 -0
- package/dist/license.js +131 -0
- package/dist/license.js.map +1 -0
- package/dist/projectPaths.d.ts +27 -0
- package/dist/projectPaths.d.ts.map +1 -0
- package/dist/projectPaths.js +86 -0
- package/dist/projectPaths.js.map +1 -0
- package/dist/projectRegistry.d.ts +97 -0
- package/dist/projectRegistry.d.ts.map +1 -0
- package/dist/projectRegistry.js +374 -0
- package/dist/projectRegistry.js.map +1 -0
- package/dist/sentinelIssues.d.ts +65 -0
- package/dist/sentinelIssues.d.ts.map +1 -0
- package/dist/sentinelIssues.js +297 -0
- package/dist/sentinelIssues.js.map +1 -0
- package/dist/server.d.ts +3 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +195 -0
- package/dist/server.js.map +1 -0
- package/dist/test.d.ts +7 -0
- package/dist/test.d.ts.map +1 -0
- package/dist/test.js +77 -0
- package/dist/test.js.map +1 -0
- package/dist/tools/agentic/index.d.ts +7 -0
- package/dist/tools/agentic/index.d.ts.map +1 -0
- package/dist/tools/agentic/index.js +203 -0
- package/dist/tools/agentic/index.js.map +1 -0
- package/dist/tools/architect/index.d.ts +11 -0
- package/dist/tools/architect/index.d.ts.map +1 -0
- package/dist/tools/architect/index.js +506 -0
- package/dist/tools/architect/index.js.map +1 -0
- package/dist/tools/architect.d.ts +19 -0
- package/dist/tools/architect.d.ts.map +1 -0
- package/dist/tools/architect.js +88 -0
- package/dist/tools/architect.js.map +1 -0
- package/dist/tools/auditor/index.d.ts +10 -0
- package/dist/tools/auditor/index.d.ts.map +1 -0
- package/dist/tools/auditor/index.js +310 -0
- package/dist/tools/auditor/index.js.map +1 -0
- package/dist/tools/auditor.d.ts +149 -0
- package/dist/tools/auditor.d.ts.map +1 -0
- package/dist/tools/auditor.js +775 -0
- package/dist/tools/auditor.js.map +1 -0
- package/dist/tools/bench/index.d.ts +3 -0
- package/dist/tools/bench/index.d.ts.map +1 -0
- package/dist/tools/bench/index.js +220 -0
- package/dist/tools/bench/index.js.map +1 -0
- package/dist/tools/bench.d.ts +89 -0
- package/dist/tools/bench.d.ts.map +1 -0
- package/dist/tools/bench.js +826 -0
- package/dist/tools/bench.js.map +1 -0
- package/dist/tools/context/index.d.ts +11 -0
- package/dist/tools/context/index.d.ts.map +1 -0
- package/dist/tools/context/index.js +482 -0
- package/dist/tools/context/index.js.map +1 -0
- package/dist/tools/context.d.ts +146 -0
- package/dist/tools/context.d.ts.map +1 -0
- package/dist/tools/context.js +481 -0
- package/dist/tools/context.js.map +1 -0
- package/dist/tools/coordinator/coordinator.d.ts +168 -0
- package/dist/tools/coordinator/coordinator.d.ts.map +1 -0
- package/dist/tools/coordinator/coordinator.js +535 -0
- package/dist/tools/coordinator/coordinator.js.map +1 -0
- package/dist/tools/coordinator/index.d.ts +12 -0
- package/dist/tools/coordinator/index.d.ts.map +1 -0
- package/dist/tools/coordinator/index.js +381 -0
- package/dist/tools/coordinator/index.js.map +1 -0
- package/dist/tools/corpus/index.d.ts +5 -0
- package/dist/tools/corpus/index.d.ts.map +1 -0
- package/dist/tools/corpus/index.js +105 -0
- package/dist/tools/corpus/index.js.map +1 -0
- package/dist/tools/corpus.d.ts +33 -0
- package/dist/tools/corpus.d.ts.map +1 -0
- package/dist/tools/corpus.js +180 -0
- package/dist/tools/corpus.js.map +1 -0
- package/dist/tools/crit.d.ts +63 -0
- package/dist/tools/crit.d.ts.map +1 -0
- package/dist/tools/crit.js +159 -0
- package/dist/tools/crit.js.map +1 -0
- package/dist/tools/data-inspector.d.ts +189 -0
- package/dist/tools/data-inspector.d.ts.map +1 -0
- package/dist/tools/data-inspector.js +669 -0
- package/dist/tools/data-inspector.js.map +1 -0
- package/dist/tools/deck.d.ts +11 -0
- package/dist/tools/deck.d.ts.map +1 -0
- package/dist/tools/deck.js +188 -0
- package/dist/tools/deck.js.map +1 -0
- package/dist/tools/designer/index.d.ts +11 -0
- package/dist/tools/designer/index.d.ts.map +1 -0
- package/dist/tools/designer/index.js +442 -0
- package/dist/tools/designer/index.js.map +1 -0
- package/dist/tools/designer/lateral-tools.d.ts +6 -0
- package/dist/tools/designer/lateral-tools.d.ts.map +1 -0
- package/dist/tools/designer/lateral-tools.js +190 -0
- package/dist/tools/designer/lateral-tools.js.map +1 -0
- package/dist/tools/designer.d.ts +122 -0
- package/dist/tools/designer.d.ts.map +1 -0
- package/dist/tools/designer.js +495 -0
- package/dist/tools/designer.js.map +1 -0
- package/dist/tools/dojo/index.d.ts +13 -0
- package/dist/tools/dojo/index.d.ts.map +1 -0
- package/dist/tools/dojo/index.js +613 -0
- package/dist/tools/dojo/index.js.map +1 -0
- package/dist/tools/dojo.d.ts +254 -0
- package/dist/tools/dojo.d.ts.map +1 -0
- package/dist/tools/dojo.js +933 -0
- package/dist/tools/dojo.js.map +1 -0
- package/dist/tools/dojoBench.d.ts +49 -0
- package/dist/tools/dojoBench.d.ts.map +1 -0
- package/dist/tools/dojoBench.js +205 -0
- package/dist/tools/dojoBench.js.map +1 -0
- package/dist/tools/dojoGraduated.d.ts +50 -0
- package/dist/tools/dojoGraduated.d.ts.map +1 -0
- package/dist/tools/dojoGraduated.js +174 -0
- package/dist/tools/dojoGraduated.js.map +1 -0
- package/dist/tools/dojoPolicy.d.ts +65 -0
- package/dist/tools/dojoPolicy.d.ts.map +1 -0
- package/dist/tools/dojoPolicy.js +263 -0
- package/dist/tools/dojoPolicy.js.map +1 -0
- package/dist/tools/feedback/index.d.ts +5 -0
- package/dist/tools/feedback/index.d.ts.map +1 -0
- package/dist/tools/feedback/index.js +153 -0
- package/dist/tools/feedback/index.js.map +1 -0
- package/dist/tools/feedback.d.ts +61 -0
- package/dist/tools/feedback.d.ts.map +1 -0
- package/dist/tools/feedback.js +209 -0
- package/dist/tools/feedback.js.map +1 -0
- package/dist/tools/forecast/index.d.ts +8 -0
- package/dist/tools/forecast/index.d.ts.map +1 -0
- package/dist/tools/forecast/index.js +283 -0
- package/dist/tools/forecast/index.js.map +1 -0
- package/dist/tools/forecast.d.ts +147 -0
- package/dist/tools/forecast.d.ts.map +1 -0
- package/dist/tools/forecast.js +417 -0
- package/dist/tools/forecast.js.map +1 -0
- package/dist/tools/friction/index.d.ts +7 -0
- package/dist/tools/friction/index.d.ts.map +1 -0
- package/dist/tools/friction/index.js +265 -0
- package/dist/tools/friction/index.js.map +1 -0
- package/dist/tools/friction.d.ts +82 -0
- package/dist/tools/friction.d.ts.map +1 -0
- package/dist/tools/friction.js +331 -0
- package/dist/tools/friction.js.map +1 -0
- package/dist/tools/git/index.d.ts +9 -0
- package/dist/tools/git/index.d.ts.map +1 -0
- package/dist/tools/git/index.js +237 -0
- package/dist/tools/git/index.js.map +1 -0
- package/dist/tools/git-sentinel/index.d.ts +7 -0
- package/dist/tools/git-sentinel/index.d.ts.map +1 -0
- package/dist/tools/git-sentinel/index.js +178 -0
- package/dist/tools/git-sentinel/index.js.map +1 -0
- package/dist/tools/git-sentinel.d.ts +78 -0
- package/dist/tools/git-sentinel.d.ts.map +1 -0
- package/dist/tools/git-sentinel.js +391 -0
- package/dist/tools/git-sentinel.js.map +1 -0
- package/dist/tools/git.d.ts +134 -0
- package/dist/tools/git.d.ts.map +1 -0
- package/dist/tools/git.js +374 -0
- package/dist/tools/git.js.map +1 -0
- package/dist/tools/guardian/index.d.ts +8 -0
- package/dist/tools/guardian/index.d.ts.map +1 -0
- package/dist/tools/guardian/index.js +171 -0
- package/dist/tools/guardian/index.js.map +1 -0
- package/dist/tools/guardian.d.ts +62 -0
- package/dist/tools/guardian.d.ts.map +1 -0
- package/dist/tools/guardian.js +332 -0
- package/dist/tools/guardian.js.map +1 -0
- package/dist/tools/hygiene/codebase-scanner.d.ts +38 -0
- package/dist/tools/hygiene/codebase-scanner.d.ts.map +1 -0
- package/dist/tools/hygiene/codebase-scanner.js +411 -0
- package/dist/tools/hygiene/codebase-scanner.js.map +1 -0
- package/dist/tools/hygiene/config-scanner.d.ts +33 -0
- package/dist/tools/hygiene/config-scanner.d.ts.map +1 -0
- package/dist/tools/hygiene/config-scanner.js +482 -0
- package/dist/tools/hygiene/config-scanner.js.map +1 -0
- package/dist/tools/hygiene/coverage-scanner.d.ts +41 -0
- package/dist/tools/hygiene/coverage-scanner.d.ts.map +1 -0
- package/dist/tools/hygiene/coverage-scanner.js +331 -0
- package/dist/tools/hygiene/coverage-scanner.js.map +1 -0
- package/dist/tools/hygiene/index.d.ts +7 -0
- package/dist/tools/hygiene/index.d.ts.map +1 -0
- package/dist/tools/hygiene/index.js +291 -0
- package/dist/tools/hygiene/index.js.map +1 -0
- package/dist/tools/hygiene/oracle-hygiene.d.ts +68 -0
- package/dist/tools/hygiene/oracle-hygiene.d.ts.map +1 -0
- package/dist/tools/hygiene/oracle-hygiene.js +324 -0
- package/dist/tools/hygiene/oracle-hygiene.js.map +1 -0
- package/dist/tools/index.d.ts +6 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +130 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/lateral.d.ts +114 -0
- package/dist/tools/lateral.d.ts.map +1 -0
- package/dist/tools/lateral.js +536 -0
- package/dist/tools/lateral.js.map +1 -0
- package/dist/tools/learnings/index.d.ts +5 -0
- package/dist/tools/learnings/index.d.ts.map +1 -0
- package/dist/tools/learnings/index.js +138 -0
- package/dist/tools/learnings/index.js.map +1 -0
- package/dist/tools/learnings.d.ts +41 -0
- package/dist/tools/learnings.d.ts.map +1 -0
- package/dist/tools/learnings.js +149 -0
- package/dist/tools/learnings.js.map +1 -0
- package/dist/tools/oracle/index.d.ts +6 -0
- package/dist/tools/oracle/index.d.ts.map +1 -0
- package/dist/tools/oracle/index.js +217 -0
- package/dist/tools/oracle/index.js.map +1 -0
- package/dist/tools/oracle.d.ts +90 -0
- package/dist/tools/oracle.d.ts.map +1 -0
- package/dist/tools/oracle.js +529 -0
- package/dist/tools/oracle.js.map +1 -0
- package/dist/tools/policy.d.ts +119 -0
- package/dist/tools/policy.d.ts.map +1 -0
- package/dist/tools/policy.js +406 -0
- package/dist/tools/policy.js.map +1 -0
- package/dist/tools/provenance/index.d.ts +4 -0
- package/dist/tools/provenance/index.d.ts.map +1 -0
- package/dist/tools/provenance/index.js +63 -0
- package/dist/tools/provenance/index.js.map +1 -0
- package/dist/tools/provenance.d.ts +75 -0
- package/dist/tools/provenance.d.ts.map +1 -0
- package/dist/tools/provenance.js +224 -0
- package/dist/tools/provenance.js.map +1 -0
- package/dist/tools/rateLimiter.d.ts +45 -0
- package/dist/tools/rateLimiter.d.ts.map +1 -0
- package/dist/tools/rateLimiter.js +91 -0
- package/dist/tools/rateLimiter.js.map +1 -0
- package/dist/tools/registry/index.d.ts +10 -0
- package/dist/tools/registry/index.d.ts.map +1 -0
- package/dist/tools/registry/index.js +506 -0
- package/dist/tools/registry/index.js.map +1 -0
- package/dist/tools/registry.d.ts +3 -0
- package/dist/tools/registry.d.ts.map +1 -0
- package/dist/tools/registry.js +189 -0
- package/dist/tools/registry.js.map +1 -0
- package/dist/tools/roadmap/index.d.ts +11 -0
- package/dist/tools/roadmap/index.d.ts.map +1 -0
- package/dist/tools/roadmap/index.js +364 -0
- package/dist/tools/roadmap/index.js.map +1 -0
- package/dist/tools/roadmap.d.ts +103 -0
- package/dist/tools/roadmap.d.ts.map +1 -0
- package/dist/tools/roadmap.js +407 -0
- package/dist/tools/roadmap.js.map +1 -0
- package/dist/tools/senken.d.ts +11 -0
- package/dist/tools/senken.d.ts.map +1 -0
- package/dist/tools/senken.js +482 -0
- package/dist/tools/senken.js.map +1 -0
- package/dist/tools/sentinel/index.d.ts +21 -0
- package/dist/tools/sentinel/index.d.ts.map +1 -0
- package/dist/tools/sentinel/index.js +1067 -0
- package/dist/tools/sentinel/index.js.map +1 -0
- package/dist/tools/sentinel-scan-data.d.ts +90 -0
- package/dist/tools/sentinel-scan-data.d.ts.map +1 -0
- package/dist/tools/sentinel-scan-data.js +122 -0
- package/dist/tools/sentinel-scan-data.js.map +1 -0
- package/dist/tools/sentinel.d.ts +156 -0
- package/dist/tools/sentinel.d.ts.map +1 -0
- package/dist/tools/sentinel.js +603 -0
- package/dist/tools/sentinel.js.map +1 -0
- package/dist/tools/shared/index.d.ts +5 -0
- package/dist/tools/shared/index.d.ts.map +1 -0
- package/dist/tools/shared/index.js +8 -0
- package/dist/tools/shared/index.js.map +1 -0
- package/dist/tools/shared/project.d.ts +17 -0
- package/dist/tools/shared/project.d.ts.map +1 -0
- package/dist/tools/shared/project.js +36 -0
- package/dist/tools/shared/project.js.map +1 -0
- package/dist/tools/shared/response.d.ts +15 -0
- package/dist/tools/shared/response.d.ts.map +1 -0
- package/dist/tools/shared/response.js +77 -0
- package/dist/tools/shared/response.js.map +1 -0
- package/dist/tools/shared/runTracker.d.ts +87 -0
- package/dist/tools/shared/runTracker.d.ts.map +1 -0
- package/dist/tools/shared/runTracker.js +225 -0
- package/dist/tools/shared/runTracker.js.map +1 -0
- package/dist/tools/shared/validation.d.ts +10 -0
- package/dist/tools/shared/validation.d.ts.map +1 -0
- package/dist/tools/shared/validation.js +26 -0
- package/dist/tools/shared/validation.js.map +1 -0
- package/dist/tools/studio/cloud-spine.d.ts +27 -0
- package/dist/tools/studio/cloud-spine.d.ts.map +1 -0
- package/dist/tools/studio/cloud-spine.js +845 -0
- package/dist/tools/studio/cloud-spine.js.map +1 -0
- package/dist/tools/studio/index.d.ts +154 -0
- package/dist/tools/studio/index.d.ts.map +1 -0
- package/dist/tools/studio/index.js +541 -0
- package/dist/tools/studio/index.js.map +1 -0
- package/dist/tools/testSpec.d.ts +122 -0
- package/dist/tools/testSpec.d.ts.map +1 -0
- package/dist/tools/testSpec.js +525 -0
- package/dist/tools/testSpec.js.map +1 -0
- package/dist/tools/toolsIndex.d.ts +5 -0
- package/dist/tools/toolsIndex.d.ts.map +1 -0
- package/dist/tools/toolsIndex.js +37 -0
- package/dist/tools/toolsIndex.js.map +1 -0
- package/dist/tools/types.d.ts +47 -0
- package/dist/tools/types.d.ts.map +1 -0
- package/dist/tools/types.js +7 -0
- package/dist/tools/types.js.map +1 -0
- package/dist/tools/vector/index.d.ts +13 -0
- package/dist/tools/vector/index.d.ts.map +1 -0
- package/dist/tools/vector/index.js +592 -0
- package/dist/tools/vector/index.js.map +1 -0
- package/dist/tools/vector.d.ts +189 -0
- package/dist/tools/vector.d.ts.map +1 -0
- package/dist/tools/vector.js +570 -0
- package/dist/tools/vector.js.map +1 -0
- package/dist/tools/velocity/index.d.ts +9 -0
- package/dist/tools/velocity/index.d.ts.map +1 -0
- package/dist/tools/velocity/index.js +306 -0
- package/dist/tools/velocity/index.js.map +1 -0
- package/dist/tools/velocity.d.ts +143 -0
- package/dist/tools/velocity.d.ts.map +1 -0
- package/dist/tools/velocity.js +628 -0
- package/dist/tools/velocity.js.map +1 -0
- package/dist/tools/voice/index.d.ts +8 -0
- package/dist/tools/voice/index.d.ts.map +1 -0
- package/dist/tools/voice/index.js +203 -0
- package/dist/tools/voice/index.js.map +1 -0
- package/dist/tools/voice.d.ts +291 -0
- package/dist/tools/voice.d.ts.map +1 -0
- package/dist/tools/voice.js +734 -0
- package/dist/tools/voice.js.map +1 -0
- package/dist/tools/workflow/index.d.ts +8 -0
- package/dist/tools/workflow/index.d.ts.map +1 -0
- package/dist/tools/workflow/index.js +199 -0
- package/dist/tools/workflow/index.js.map +1 -0
- package/dist/tools/workflow.d.ts +123 -0
- package/dist/tools/workflow.d.ts.map +1 -0
- package/dist/tools/workflow.js +647 -0
- package/dist/tools/workflow.js.map +1 -0
- package/dist/transports/bridge.d.ts +22 -0
- package/dist/transports/bridge.d.ts.map +1 -0
- package/dist/transports/bridge.js +177 -0
- package/dist/transports/bridge.js.map +1 -0
- package/dist/transports/http.d.ts +9 -0
- package/dist/transports/http.d.ts.map +1 -0
- package/dist/transports/http.js +35 -0
- package/dist/transports/http.js.map +1 -0
- package/dist/transports/index.d.ts +6 -0
- package/dist/transports/index.d.ts.map +1 -0
- package/dist/transports/index.js +8 -0
- package/dist/transports/index.js.map +1 -0
- package/dist/transports/mcp.d.ts +9 -0
- package/dist/transports/mcp.d.ts.map +1 -0
- package/dist/transports/mcp.js +51 -0
- package/dist/transports/mcp.js.map +1 -0
- package/dist/transports/stdio.d.ts +9 -0
- package/dist/transports/stdio.d.ts.map +1 -0
- package/dist/transports/stdio.js +26 -0
- package/dist/transports/stdio.js.map +1 -0
- package/dist/transports/types.d.ts +27 -0
- package/dist/transports/types.d.ts.map +1 -0
- package/dist/transports/types.js +8 -0
- package/dist/transports/types.js.map +1 -0
- package/dist/types/agent-services.d.ts +193 -0
- package/dist/types/agent-services.d.ts.map +1 -0
- package/dist/types/agent-services.js +8 -0
- package/dist/types/agent-services.js.map +1 -0
- package/dist/types/index.d.ts +2 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +7 -0
- package/dist/types/index.js.map +1 -0
- package/package.json +72 -0
- package/templates/AGENT.md +87 -0
- package/templates/com.decibel.daemon.plist +47 -0
- package/templates/sentinel/ISSUE_TEMPLATE.md +20 -0
|
@@ -0,0 +1,775 @@
|
|
|
1
|
+
// ============================================================================
|
|
2
|
+
// Auditor Domain Tools
|
|
3
|
+
// ============================================================================
|
|
4
|
+
// Code health assessment: smell detection, naming audits, health dashboards.
|
|
5
|
+
// These tools analyze actual source code, complementing Sentinel's work tracking.
|
|
6
|
+
// ============================================================================
|
|
7
|
+
import fs from 'fs/promises';
|
|
8
|
+
import path from 'path';
|
|
9
|
+
import YAML from 'yaml';
|
|
10
|
+
import { resolveProjectPaths } from '../projectRegistry.js';
|
|
11
|
+
import { ensureDir } from '../dataRoot.js';
|
|
12
|
+
// ============================================================================
|
|
13
|
+
// Constants
|
|
14
|
+
// ============================================================================
|
|
15
|
+
const GOD_FILE_THRESHOLD = 400; // Lines
|
|
16
|
+
const NESTING_THRESHOLD = 4; // Levels
|
|
17
|
+
const FUNCTION_LENGTH_THRESHOLD = 50; // Lines
|
|
18
|
+
const MAGIC_NUMBER_PATTERN = /(?<![a-zA-Z_])(?:0x[a-fA-F0-9]+|\d{4,})(?![a-zA-Z_])/g;
|
|
19
|
+
const HARDCODED_URL_PATTERN = /(['"`])(https?:\/\/[^'"`]+)\1/g;
|
|
20
|
+
const TODO_PATTERN = /\/\/\s*(TODO|FIXME|HACK|XXX)/gi;
|
|
21
|
+
const COMMENTED_CODE_PATTERN = /\/\/\s*(const|let|var|function|class|if|for|while|return)\s/g;
|
|
22
|
+
const DEFAULT_CHECKS = [
|
|
23
|
+
'god_file',
|
|
24
|
+
'rule_sprawl',
|
|
25
|
+
'hidden_rules',
|
|
26
|
+
'buried_legacy',
|
|
27
|
+
'hardcoded_values',
|
|
28
|
+
];
|
|
29
|
+
// ============================================================================
|
|
30
|
+
// Helpers
|
|
31
|
+
// ============================================================================
|
|
32
|
+
function makeError(message, details) {
|
|
33
|
+
return { error: message, details };
|
|
34
|
+
}
|
|
35
|
+
// Extension sets by project type
|
|
36
|
+
const EXTENSION_SETS = {
|
|
37
|
+
typescript: ['.ts', '.tsx', '.js', '.jsx'],
|
|
38
|
+
javascript: ['.js', '.jsx', '.mjs', '.cjs'],
|
|
39
|
+
python: ['.py'],
|
|
40
|
+
go: ['.go'],
|
|
41
|
+
rust: ['.rs'],
|
|
42
|
+
all: ['.ts', '.tsx', '.js', '.jsx', '.py', '.go', '.rs'],
|
|
43
|
+
};
|
|
44
|
+
/**
|
|
45
|
+
* Auto-detect project type based on config files present.
|
|
46
|
+
* Returns the appropriate file extensions to scan.
|
|
47
|
+
*/
|
|
48
|
+
async function detectProjectExtensions(projectPath) {
|
|
49
|
+
const checks = [
|
|
50
|
+
{ file: 'package.json', extensions: EXTENSION_SETS.typescript },
|
|
51
|
+
{ file: 'tsconfig.json', extensions: EXTENSION_SETS.typescript },
|
|
52
|
+
{ file: 'pyproject.toml', extensions: EXTENSION_SETS.python },
|
|
53
|
+
{ file: 'requirements.txt', extensions: EXTENSION_SETS.python },
|
|
54
|
+
{ file: 'setup.py', extensions: EXTENSION_SETS.python },
|
|
55
|
+
{ file: 'go.mod', extensions: EXTENSION_SETS.go },
|
|
56
|
+
{ file: 'Cargo.toml', extensions: EXTENSION_SETS.rust },
|
|
57
|
+
];
|
|
58
|
+
for (const check of checks) {
|
|
59
|
+
try {
|
|
60
|
+
await fs.access(path.join(projectPath, check.file));
|
|
61
|
+
return check.extensions;
|
|
62
|
+
}
|
|
63
|
+
catch {
|
|
64
|
+
// File doesn't exist, try next
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
// Default to TypeScript/JavaScript if no config found
|
|
68
|
+
return EXTENSION_SETS.typescript;
|
|
69
|
+
}
|
|
70
|
+
async function getSourceFiles(dir, extensions) {
|
|
71
|
+
const files = [];
|
|
72
|
+
async function scan(currentDir) {
|
|
73
|
+
try {
|
|
74
|
+
const entries = await fs.readdir(currentDir, { withFileTypes: true });
|
|
75
|
+
for (const entry of entries) {
|
|
76
|
+
const fullPath = path.join(currentDir, entry.name);
|
|
77
|
+
// Skip common non-source directories
|
|
78
|
+
if (entry.isDirectory()) {
|
|
79
|
+
if (entry.name.startsWith('.') ||
|
|
80
|
+
entry.name === 'node_modules' ||
|
|
81
|
+
entry.name === 'dist' ||
|
|
82
|
+
entry.name === 'build' ||
|
|
83
|
+
entry.name === 'coverage' ||
|
|
84
|
+
entry.name === '__pycache__' ||
|
|
85
|
+
entry.name === '.venv' ||
|
|
86
|
+
entry.name === 'venv' ||
|
|
87
|
+
entry.name === 'env' ||
|
|
88
|
+
entry.name === 'target') {
|
|
89
|
+
continue;
|
|
90
|
+
}
|
|
91
|
+
await scan(fullPath);
|
|
92
|
+
}
|
|
93
|
+
else if (entry.isFile() && extensions.some(ext => entry.name.endsWith(ext))) {
|
|
94
|
+
files.push(fullPath);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
catch {
|
|
99
|
+
// Directory doesn't exist or can't be read
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
await scan(dir);
|
|
103
|
+
return files;
|
|
104
|
+
}
|
|
105
|
+
function countNestingDepth(content) {
|
|
106
|
+
let maxDepth = 0;
|
|
107
|
+
let currentDepth = 0;
|
|
108
|
+
for (const char of content) {
|
|
109
|
+
if (char === '{') {
|
|
110
|
+
currentDepth++;
|
|
111
|
+
maxDepth = Math.max(maxDepth, currentDepth);
|
|
112
|
+
}
|
|
113
|
+
else if (char === '}') {
|
|
114
|
+
currentDepth = Math.max(0, currentDepth - 1);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
return maxDepth;
|
|
118
|
+
}
|
|
119
|
+
function findLongFunctions(content, filePath) {
|
|
120
|
+
const issues = [];
|
|
121
|
+
const functionPattern = /(?:function\s+(\w+)|(?:const|let|var)\s+(\w+)\s*=\s*(?:async\s*)?\([^)]*\)\s*=>|(\w+)\s*\([^)]*\)\s*\{)/g;
|
|
122
|
+
let match;
|
|
123
|
+
while ((match = functionPattern.exec(content)) !== null) {
|
|
124
|
+
const funcName = match[1] || match[2] || match[3] || 'anonymous';
|
|
125
|
+
const startIndex = match.index;
|
|
126
|
+
const lineNumber = content.substring(0, startIndex).split('\n').length;
|
|
127
|
+
// Find the function body (simplified: count braces)
|
|
128
|
+
let braceCount = 0;
|
|
129
|
+
let started = false;
|
|
130
|
+
let endIndex = startIndex;
|
|
131
|
+
for (let i = startIndex; i < content.length; i++) {
|
|
132
|
+
if (content[i] === '{') {
|
|
133
|
+
braceCount++;
|
|
134
|
+
started = true;
|
|
135
|
+
}
|
|
136
|
+
else if (content[i] === '}') {
|
|
137
|
+
braceCount--;
|
|
138
|
+
if (started && braceCount === 0) {
|
|
139
|
+
endIndex = i;
|
|
140
|
+
break;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
const funcBody = content.substring(startIndex, endIndex);
|
|
145
|
+
const funcLines = funcBody.split('\n').length;
|
|
146
|
+
if (funcLines > FUNCTION_LENGTH_THRESHOLD) {
|
|
147
|
+
issues.push({
|
|
148
|
+
file: filePath,
|
|
149
|
+
line: lineNumber,
|
|
150
|
+
smell: 'god_file', // Using god_file for long functions too
|
|
151
|
+
severity: funcLines > 100 ? 'high' : 'medium',
|
|
152
|
+
message: `Function '${funcName}' is ${funcLines} lines (threshold: ${FUNCTION_LENGTH_THRESHOLD})`,
|
|
153
|
+
suggestion: 'Consider breaking this function into smaller, focused functions',
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
return issues;
|
|
158
|
+
}
|
|
159
|
+
// ============================================================================
|
|
160
|
+
// Triage (Code Smell Detection)
|
|
161
|
+
// ============================================================================
|
|
162
|
+
export async function auditorTriage(input) {
|
|
163
|
+
let resolved;
|
|
164
|
+
try {
|
|
165
|
+
resolved = resolveProjectPaths(input.projectId);
|
|
166
|
+
}
|
|
167
|
+
catch {
|
|
168
|
+
return makeError('Failed to resolve project path');
|
|
169
|
+
}
|
|
170
|
+
// Auto-detect source path: try common patterns if not specified
|
|
171
|
+
let scanPath;
|
|
172
|
+
if (input.path) {
|
|
173
|
+
scanPath = path.isAbsolute(input.path) ? input.path : path.join(resolved.projectPath, input.path);
|
|
174
|
+
}
|
|
175
|
+
else {
|
|
176
|
+
// Try common source directories, fall back to project root
|
|
177
|
+
const candidates = ['src', 'lib', 'app', resolved.id || path.basename(resolved.projectPath)];
|
|
178
|
+
scanPath = resolved.projectPath; // default to project root
|
|
179
|
+
for (const candidate of candidates) {
|
|
180
|
+
try {
|
|
181
|
+
const candidatePath = path.join(resolved.projectPath, candidate);
|
|
182
|
+
const stat = await fs.stat(candidatePath);
|
|
183
|
+
if (stat.isDirectory()) {
|
|
184
|
+
scanPath = candidatePath;
|
|
185
|
+
break;
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
catch {
|
|
189
|
+
// Try next candidate
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
// Auto-detect extensions or use provided
|
|
194
|
+
const extensions = input.extensions || await detectProjectExtensions(resolved.projectPath);
|
|
195
|
+
const checks = input.checks || DEFAULT_CHECKS;
|
|
196
|
+
const issues = [];
|
|
197
|
+
// Get all source files
|
|
198
|
+
const files = await getSourceFiles(scanPath, extensions);
|
|
199
|
+
for (const filePath of files) {
|
|
200
|
+
try {
|
|
201
|
+
const content = await fs.readFile(filePath, 'utf-8');
|
|
202
|
+
const lines = content.split('\n');
|
|
203
|
+
const lineCount = lines.length;
|
|
204
|
+
const relativePath = path.relative(resolved.projectPath, filePath);
|
|
205
|
+
// Check: God File (file too large)
|
|
206
|
+
if (checks.includes('god_file') && lineCount > GOD_FILE_THRESHOLD) {
|
|
207
|
+
issues.push({
|
|
208
|
+
file: relativePath,
|
|
209
|
+
smell: 'god_file',
|
|
210
|
+
severity: lineCount > 600 ? 'high' : 'medium',
|
|
211
|
+
message: `File has ${lineCount} lines (threshold: ${GOD_FILE_THRESHOLD})`,
|
|
212
|
+
suggestion: 'Consider splitting into smaller, focused modules',
|
|
213
|
+
});
|
|
214
|
+
// Also check for long functions within god files
|
|
215
|
+
const longFuncs = findLongFunctions(content, relativePath);
|
|
216
|
+
issues.push(...longFuncs);
|
|
217
|
+
}
|
|
218
|
+
// Check: Rule Sprawl (deep nesting)
|
|
219
|
+
if (checks.includes('rule_sprawl')) {
|
|
220
|
+
const depth = countNestingDepth(content);
|
|
221
|
+
if (depth > NESTING_THRESHOLD) {
|
|
222
|
+
issues.push({
|
|
223
|
+
file: relativePath,
|
|
224
|
+
smell: 'rule_sprawl',
|
|
225
|
+
severity: depth > 6 ? 'high' : 'medium',
|
|
226
|
+
message: `Nesting depth of ${depth} (threshold: ${NESTING_THRESHOLD})`,
|
|
227
|
+
suggestion: 'Consider extracting nested logic into separate functions',
|
|
228
|
+
});
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
// Regex match variable for all pattern checks
|
|
232
|
+
let match;
|
|
233
|
+
// Check: Hidden Rules (magic numbers, hardcoded URLs)
|
|
234
|
+
if (checks.includes('hidden_rules')) {
|
|
235
|
+
// Magic numbers
|
|
236
|
+
while ((match = MAGIC_NUMBER_PATTERN.exec(content)) !== null) {
|
|
237
|
+
const lineNum = content.substring(0, match.index).split('\n').length;
|
|
238
|
+
// Skip common safe numbers
|
|
239
|
+
if (!['1000', '1024', '2048', '3000', '8080'].includes(match[0])) {
|
|
240
|
+
issues.push({
|
|
241
|
+
file: relativePath,
|
|
242
|
+
line: lineNum,
|
|
243
|
+
smell: 'hidden_rules',
|
|
244
|
+
severity: 'low',
|
|
245
|
+
message: `Magic number: ${match[0]}`,
|
|
246
|
+
suggestion: 'Extract to a named constant with documentation',
|
|
247
|
+
});
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
// Hardcoded URLs
|
|
251
|
+
while ((match = HARDCODED_URL_PATTERN.exec(content)) !== null) {
|
|
252
|
+
const lineNum = content.substring(0, match.index).split('\n').length;
|
|
253
|
+
issues.push({
|
|
254
|
+
file: relativePath,
|
|
255
|
+
line: lineNum,
|
|
256
|
+
smell: 'hidden_rules',
|
|
257
|
+
severity: 'medium',
|
|
258
|
+
message: `Hardcoded URL: ${match[2].substring(0, 50)}...`,
|
|
259
|
+
suggestion: 'Move to environment variable or config file',
|
|
260
|
+
});
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
// Check: Hardcoded Values
|
|
264
|
+
if (checks.includes('hardcoded_values')) {
|
|
265
|
+
// Look for common hardcoded patterns
|
|
266
|
+
const apiKeyPattern = /['"`](sk-|api[_-]?key|secret)[^'"`]*['"`]/gi;
|
|
267
|
+
while ((match = apiKeyPattern.exec(content)) !== null) {
|
|
268
|
+
const lineNum = content.substring(0, match.index).split('\n').length;
|
|
269
|
+
issues.push({
|
|
270
|
+
file: relativePath,
|
|
271
|
+
line: lineNum,
|
|
272
|
+
smell: 'hardcoded_values',
|
|
273
|
+
severity: 'high',
|
|
274
|
+
message: 'Potential hardcoded API key or secret',
|
|
275
|
+
suggestion: 'Move to environment variable',
|
|
276
|
+
});
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
// Check: Buried Legacy (TODOs, commented code)
|
|
280
|
+
if (checks.includes('buried_legacy')) {
|
|
281
|
+
while ((match = TODO_PATTERN.exec(content)) !== null) {
|
|
282
|
+
const lineNum = content.substring(0, match.index).split('\n').length;
|
|
283
|
+
issues.push({
|
|
284
|
+
file: relativePath,
|
|
285
|
+
line: lineNum,
|
|
286
|
+
smell: 'buried_legacy',
|
|
287
|
+
severity: 'low',
|
|
288
|
+
message: `${match[1].toUpperCase()} comment found`,
|
|
289
|
+
suggestion: 'Create an issue to track this, or resolve it',
|
|
290
|
+
});
|
|
291
|
+
}
|
|
292
|
+
while ((match = COMMENTED_CODE_PATTERN.exec(content)) !== null) {
|
|
293
|
+
const lineNum = content.substring(0, match.index).split('\n').length;
|
|
294
|
+
issues.push({
|
|
295
|
+
file: relativePath,
|
|
296
|
+
line: lineNum,
|
|
297
|
+
smell: 'buried_legacy',
|
|
298
|
+
severity: 'low',
|
|
299
|
+
message: 'Commented-out code detected',
|
|
300
|
+
suggestion: 'Remove dead code or restore if needed',
|
|
301
|
+
});
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
catch {
|
|
306
|
+
// File read failed, skip
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
// Calculate summary
|
|
310
|
+
const summary = {
|
|
311
|
+
high: issues.filter(i => i.severity === 'high').length,
|
|
312
|
+
medium: issues.filter(i => i.severity === 'medium').length,
|
|
313
|
+
low: issues.filter(i => i.severity === 'low').length,
|
|
314
|
+
};
|
|
315
|
+
return {
|
|
316
|
+
scanned: files.length,
|
|
317
|
+
issues,
|
|
318
|
+
summary,
|
|
319
|
+
};
|
|
320
|
+
}
|
|
321
|
+
// ============================================================================
|
|
322
|
+
// Health Dashboard
|
|
323
|
+
// ============================================================================
|
|
324
|
+
export async function auditorHealth(input) {
|
|
325
|
+
let resolved;
|
|
326
|
+
try {
|
|
327
|
+
resolved = resolveProjectPaths(input.projectId);
|
|
328
|
+
}
|
|
329
|
+
catch {
|
|
330
|
+
return makeError('Failed to resolve project path');
|
|
331
|
+
}
|
|
332
|
+
const projectId = resolved.id || path.basename(resolved.projectPath);
|
|
333
|
+
// Auto-detect extensions or use provided
|
|
334
|
+
const extensions = input.extensions || await detectProjectExtensions(resolved.projectPath);
|
|
335
|
+
// Auto-detect source path, fall back to project root
|
|
336
|
+
let srcPath = resolved.projectPath;
|
|
337
|
+
const candidates = ['src', 'lib', 'app', projectId];
|
|
338
|
+
for (const candidate of candidates) {
|
|
339
|
+
try {
|
|
340
|
+
const candidatePath = path.join(resolved.projectPath, candidate);
|
|
341
|
+
const stat = await fs.stat(candidatePath);
|
|
342
|
+
if (stat.isDirectory()) {
|
|
343
|
+
srcPath = candidatePath;
|
|
344
|
+
break;
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
catch {
|
|
348
|
+
// Try next candidate
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
// Get all source files
|
|
352
|
+
const files = await getSourceFiles(srcPath, extensions);
|
|
353
|
+
let totalLines = 0;
|
|
354
|
+
let maxFileSize = 0;
|
|
355
|
+
let godFiles = 0;
|
|
356
|
+
const fileIssues = new Map();
|
|
357
|
+
for (const filePath of files) {
|
|
358
|
+
try {
|
|
359
|
+
const content = await fs.readFile(filePath, 'utf-8');
|
|
360
|
+
const lineCount = content.split('\n').length;
|
|
361
|
+
const relativePath = path.relative(resolved.projectPath, filePath);
|
|
362
|
+
totalLines += lineCount;
|
|
363
|
+
maxFileSize = Math.max(maxFileSize, lineCount);
|
|
364
|
+
if (lineCount > GOD_FILE_THRESHOLD) {
|
|
365
|
+
godFiles++;
|
|
366
|
+
fileIssues.set(relativePath, (fileIssues.get(relativePath) || 0) + 1);
|
|
367
|
+
}
|
|
368
|
+
// Count other issues
|
|
369
|
+
const depth = countNestingDepth(content);
|
|
370
|
+
if (depth > NESTING_THRESHOLD) {
|
|
371
|
+
fileIssues.set(relativePath, (fileIssues.get(relativePath) || 0) + 1);
|
|
372
|
+
}
|
|
373
|
+
const todoMatches = content.match(TODO_PATTERN);
|
|
374
|
+
if (todoMatches) {
|
|
375
|
+
fileIssues.set(relativePath, (fileIssues.get(relativePath) || 0) + todoMatches.length);
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
catch {
|
|
379
|
+
// Skip unreadable files
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
// Run triage to get smell counts (pass extensions so it doesn't re-detect)
|
|
383
|
+
const triageResult = await auditorTriage({ projectId: input.projectId, extensions });
|
|
384
|
+
const smellCount = 'error' in triageResult
|
|
385
|
+
? { high: 0, medium: 0, low: 0 }
|
|
386
|
+
: triageResult.summary;
|
|
387
|
+
// Get top offenders
|
|
388
|
+
const topOffenders = Array.from(fileIssues.entries())
|
|
389
|
+
.sort((a, b) => b[1] - a[1])
|
|
390
|
+
.slice(0, 5)
|
|
391
|
+
.map(([file, issues]) => ({ file, issues }));
|
|
392
|
+
// Try to compute trends from history
|
|
393
|
+
let trends;
|
|
394
|
+
try {
|
|
395
|
+
const healthLogPath = path.join(resolved.subPath('auditor'), HEALTH_LOG_FILENAME);
|
|
396
|
+
const content = await fs.readFile(healthLogPath, 'utf-8');
|
|
397
|
+
const parsed = YAML.parse(content);
|
|
398
|
+
if (Array.isArray(parsed) && parsed.length >= 2) {
|
|
399
|
+
const entries = parsed;
|
|
400
|
+
const godFilesValues = entries.map(e => e.metrics.godFiles);
|
|
401
|
+
const smellsValues = entries.map(e => e.metrics.smellCount.high + e.metrics.smellCount.medium + e.metrics.smellCount.low);
|
|
402
|
+
// Compare first half average to second half average
|
|
403
|
+
const computeSmellTrend = (values) => {
|
|
404
|
+
const midpoint = Math.floor(values.length / 2);
|
|
405
|
+
const firstAvg = values.slice(0, midpoint).reduce((a, b) => a + b, 0) / midpoint;
|
|
406
|
+
const secondAvg = values.slice(midpoint).reduce((a, b) => a + b, 0) / (values.length - midpoint);
|
|
407
|
+
const change = (secondAvg - firstAvg) / (firstAvg || 1);
|
|
408
|
+
if (change < -0.1)
|
|
409
|
+
return 'improving';
|
|
410
|
+
if (change > 0.1)
|
|
411
|
+
return 'degrading';
|
|
412
|
+
return 'stable';
|
|
413
|
+
};
|
|
414
|
+
trends = {
|
|
415
|
+
godFiles: computeSmellTrend(godFilesValues),
|
|
416
|
+
smells: computeSmellTrend(smellsValues),
|
|
417
|
+
};
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
catch {
|
|
421
|
+
// No history available, trends will be undefined
|
|
422
|
+
}
|
|
423
|
+
return {
|
|
424
|
+
timestamp: new Date().toISOString(),
|
|
425
|
+
project: projectId,
|
|
426
|
+
metrics: {
|
|
427
|
+
totalFiles: files.length,
|
|
428
|
+
totalLines,
|
|
429
|
+
godFiles,
|
|
430
|
+
avgFileSize: files.length > 0 ? Math.round(totalLines / files.length) : 0,
|
|
431
|
+
maxFileSize,
|
|
432
|
+
namingViolations: 0, // Would require naming audit
|
|
433
|
+
smellCount,
|
|
434
|
+
},
|
|
435
|
+
trends,
|
|
436
|
+
topOffenders,
|
|
437
|
+
};
|
|
438
|
+
}
|
|
439
|
+
// ============================================================================
|
|
440
|
+
// Refactor Score
|
|
441
|
+
// ============================================================================
|
|
442
|
+
export async function auditorRefactorScore(input) {
|
|
443
|
+
let resolved;
|
|
444
|
+
try {
|
|
445
|
+
resolved = resolveProjectPaths(input.projectId);
|
|
446
|
+
}
|
|
447
|
+
catch {
|
|
448
|
+
return makeError('Failed to resolve project path');
|
|
449
|
+
}
|
|
450
|
+
const limit = input.limit || 10;
|
|
451
|
+
const projectId = resolved.id || path.basename(resolved.projectPath);
|
|
452
|
+
// Auto-detect extensions or use provided
|
|
453
|
+
const extensions = input.extensions || await detectProjectExtensions(resolved.projectPath);
|
|
454
|
+
// Auto-detect source path, fall back to project root
|
|
455
|
+
let srcPath = resolved.projectPath;
|
|
456
|
+
const candidates_paths = ['src', 'lib', 'app', projectId];
|
|
457
|
+
for (const candidate of candidates_paths) {
|
|
458
|
+
try {
|
|
459
|
+
const candidatePath = path.join(resolved.projectPath, candidate);
|
|
460
|
+
const stat = await fs.stat(candidatePath);
|
|
461
|
+
if (stat.isDirectory()) {
|
|
462
|
+
srcPath = candidatePath;
|
|
463
|
+
break;
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
catch {
|
|
467
|
+
// Try next candidate
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
const files = await getSourceFiles(srcPath, extensions);
|
|
471
|
+
const candidates = [];
|
|
472
|
+
for (const filePath of files) {
|
|
473
|
+
try {
|
|
474
|
+
const content = await fs.readFile(filePath, 'utf-8');
|
|
475
|
+
const lineCount = content.split('\n').length;
|
|
476
|
+
const relativePath = path.relative(resolved.projectPath, filePath);
|
|
477
|
+
const complexity = countNestingDepth(content);
|
|
478
|
+
// Count smells in this file
|
|
479
|
+
let smellCount = 0;
|
|
480
|
+
if (lineCount > GOD_FILE_THRESHOLD)
|
|
481
|
+
smellCount++;
|
|
482
|
+
if (complexity > NESTING_THRESHOLD)
|
|
483
|
+
smellCount++;
|
|
484
|
+
const todoMatches = content.match(TODO_PATTERN);
|
|
485
|
+
if (todoMatches)
|
|
486
|
+
smellCount += todoMatches.length;
|
|
487
|
+
// Calculate score (higher = more urgent to refactor)
|
|
488
|
+
// Formula: (lines/100) * 3 + complexity * 2 + smellCount * 5
|
|
489
|
+
const score = Math.min(100, Math.round((lineCount / 100) * 3 +
|
|
490
|
+
complexity * 2 +
|
|
491
|
+
smellCount * 5));
|
|
492
|
+
// Determine recommendation
|
|
493
|
+
let recommendation = 'refactor';
|
|
494
|
+
if (lineCount > 600)
|
|
495
|
+
recommendation = 'split';
|
|
496
|
+
else if (complexity > 6)
|
|
497
|
+
recommendation = 'simplify';
|
|
498
|
+
else if (smellCount > 5)
|
|
499
|
+
recommendation = 'extract';
|
|
500
|
+
if (score > 20) { // Only include files that need attention
|
|
501
|
+
candidates.push({
|
|
502
|
+
file: relativePath,
|
|
503
|
+
score,
|
|
504
|
+
factors: {
|
|
505
|
+
lines: lineCount,
|
|
506
|
+
complexity,
|
|
507
|
+
smellCount,
|
|
508
|
+
},
|
|
509
|
+
recommendation,
|
|
510
|
+
});
|
|
511
|
+
}
|
|
512
|
+
}
|
|
513
|
+
catch {
|
|
514
|
+
// Skip unreadable files
|
|
515
|
+
}
|
|
516
|
+
}
|
|
517
|
+
// Sort by score descending and limit
|
|
518
|
+
candidates.sort((a, b) => b.score - a.score);
|
|
519
|
+
return {
|
|
520
|
+
candidates: candidates.slice(0, limit),
|
|
521
|
+
totalFiles: files.length,
|
|
522
|
+
};
|
|
523
|
+
}
|
|
524
|
+
// ============================================================================
|
|
525
|
+
// Init (Create naming conventions scaffold)
|
|
526
|
+
// ============================================================================
|
|
527
|
+
export async function auditorInit(input) {
|
|
528
|
+
let resolved;
|
|
529
|
+
try {
|
|
530
|
+
resolved = resolveProjectPaths(input.projectId);
|
|
531
|
+
}
|
|
532
|
+
catch {
|
|
533
|
+
return makeError('Failed to resolve project path');
|
|
534
|
+
}
|
|
535
|
+
const conventionsPath = path.join(resolved.projectPath, 'naming-conventions.yml');
|
|
536
|
+
// Check if already exists
|
|
537
|
+
try {
|
|
538
|
+
await fs.access(conventionsPath);
|
|
539
|
+
return { path: conventionsPath, created: false };
|
|
540
|
+
}
|
|
541
|
+
catch {
|
|
542
|
+
// File doesn't exist, create it
|
|
543
|
+
}
|
|
544
|
+
const scaffold = `# Naming Conventions
|
|
545
|
+
# Generated by Decibel Auditor
|
|
546
|
+
# Customize this file to match your project's conventions
|
|
547
|
+
|
|
548
|
+
entities:
|
|
549
|
+
# Define naming conventions for your core entities
|
|
550
|
+
# user:
|
|
551
|
+
# variable: user, currentUser
|
|
552
|
+
# function_prefix: get_user, create_user, update_user
|
|
553
|
+
# class: User, UserProfile, UserService
|
|
554
|
+
# table: users
|
|
555
|
+
# api_field: user_id, user_email
|
|
556
|
+
|
|
557
|
+
patterns:
|
|
558
|
+
collections: plural (users, orders, items)
|
|
559
|
+
single_item: singular (user, order, item)
|
|
560
|
+
booleans: is_, has_, can_, should_ prefix
|
|
561
|
+
async_functions: async_ prefix or _async suffix (pick one)
|
|
562
|
+
private: _ prefix for internal methods
|
|
563
|
+
constants: UPPER_SNAKE_CASE
|
|
564
|
+
|
|
565
|
+
anti_patterns:
|
|
566
|
+
- data, info, manager, handler, utils (too vague)
|
|
567
|
+
- temp, tmp, foo, bar (temporary names)
|
|
568
|
+
- abbreviations (ok: id, url, api | bad: usr, ord, cfg)
|
|
569
|
+
|
|
570
|
+
file_naming:
|
|
571
|
+
components: PascalCase (UserProfile.tsx)
|
|
572
|
+
utilities: camelCase (formatDate.ts)
|
|
573
|
+
constants: UPPER_SNAKE_CASE or kebab-case
|
|
574
|
+
tests: *.test.ts or *.spec.ts
|
|
575
|
+
`;
|
|
576
|
+
await fs.writeFile(conventionsPath, scaffold, 'utf-8');
|
|
577
|
+
return { path: conventionsPath, created: true };
|
|
578
|
+
}
|
|
579
|
+
// ============================================================================
|
|
580
|
+
// Naming Audit (Placeholder - would need AST parsing for full implementation)
|
|
581
|
+
// ============================================================================
|
|
582
|
+
export async function auditorNamingAudit(input) {
|
|
583
|
+
let resolved;
|
|
584
|
+
try {
|
|
585
|
+
resolved = resolveProjectPaths(input.projectId);
|
|
586
|
+
}
|
|
587
|
+
catch {
|
|
588
|
+
return makeError('Failed to resolve project path');
|
|
589
|
+
}
|
|
590
|
+
const projectId = resolved.id || path.basename(resolved.projectPath);
|
|
591
|
+
// Auto-detect extensions or use provided
|
|
592
|
+
const extensions = input.extensions || await detectProjectExtensions(resolved.projectPath);
|
|
593
|
+
// Auto-detect source path, fall back to project root
|
|
594
|
+
let srcPath = resolved.projectPath;
|
|
595
|
+
const srcCandidates = ['src', 'lib', 'app', projectId];
|
|
596
|
+
for (const candidate of srcCandidates) {
|
|
597
|
+
try {
|
|
598
|
+
const candidatePath = path.join(resolved.projectPath, candidate);
|
|
599
|
+
const stat = await fs.stat(candidatePath);
|
|
600
|
+
if (stat.isDirectory()) {
|
|
601
|
+
srcPath = candidatePath;
|
|
602
|
+
break;
|
|
603
|
+
}
|
|
604
|
+
}
|
|
605
|
+
catch {
|
|
606
|
+
// Try next candidate
|
|
607
|
+
}
|
|
608
|
+
}
|
|
609
|
+
// For now, do basic file naming checks
|
|
610
|
+
const files = await getSourceFiles(srcPath, extensions);
|
|
611
|
+
const violations = [];
|
|
612
|
+
// Common anti-patterns in file names
|
|
613
|
+
const antiPatterns = ['utils', 'helpers', 'misc', 'stuff', 'temp'];
|
|
614
|
+
for (const filePath of files) {
|
|
615
|
+
const fileName = path.basename(filePath, path.extname(filePath));
|
|
616
|
+
const relativePath = path.relative(resolved.projectPath, filePath);
|
|
617
|
+
for (const pattern of antiPatterns) {
|
|
618
|
+
if (fileName.toLowerCase() === pattern || fileName.toLowerCase().includes(pattern)) {
|
|
619
|
+
violations.push({
|
|
620
|
+
file: relativePath,
|
|
621
|
+
line: 0,
|
|
622
|
+
found: fileName,
|
|
623
|
+
expected: 'More specific name describing the file\'s purpose',
|
|
624
|
+
category: 'file',
|
|
625
|
+
});
|
|
626
|
+
}
|
|
627
|
+
}
|
|
628
|
+
}
|
|
629
|
+
return {
|
|
630
|
+
violations,
|
|
631
|
+
stats: {
|
|
632
|
+
checked: files.length,
|
|
633
|
+
passed: files.length - violations.length,
|
|
634
|
+
violations: violations.length,
|
|
635
|
+
},
|
|
636
|
+
};
|
|
637
|
+
}
|
|
638
|
+
// ============================================================================
|
|
639
|
+
// Health Tracking - Log Health Snapshot
|
|
640
|
+
// ============================================================================
|
|
641
|
+
const HEALTH_LOG_FILENAME = 'health-log.yaml';
|
|
642
|
+
export async function auditorLogHealth(input) {
|
|
643
|
+
let resolved;
|
|
644
|
+
try {
|
|
645
|
+
resolved = resolveProjectPaths(input.projectId);
|
|
646
|
+
}
|
|
647
|
+
catch {
|
|
648
|
+
return makeError('Failed to resolve project path');
|
|
649
|
+
}
|
|
650
|
+
// Get current health metrics
|
|
651
|
+
const healthResult = await auditorHealth({ projectId: input.projectId });
|
|
652
|
+
if ('error' in healthResult) {
|
|
653
|
+
return healthResult;
|
|
654
|
+
}
|
|
655
|
+
// Create snapshot
|
|
656
|
+
const snapshot = {
|
|
657
|
+
timestamp: healthResult.timestamp,
|
|
658
|
+
metrics: healthResult.metrics,
|
|
659
|
+
commit: input.commit,
|
|
660
|
+
};
|
|
661
|
+
// Ensure auditor directory exists
|
|
662
|
+
const auditorDir = resolved.subPath('auditor');
|
|
663
|
+
await ensureDir(auditorDir);
|
|
664
|
+
const healthLogPath = path.join(auditorDir, HEALTH_LOG_FILENAME);
|
|
665
|
+
// Read existing log or create new one
|
|
666
|
+
let existingLog = [];
|
|
667
|
+
try {
|
|
668
|
+
const content = await fs.readFile(healthLogPath, 'utf-8');
|
|
669
|
+
const parsed = YAML.parse(content);
|
|
670
|
+
if (Array.isArray(parsed)) {
|
|
671
|
+
existingLog = parsed;
|
|
672
|
+
}
|
|
673
|
+
}
|
|
674
|
+
catch {
|
|
675
|
+
// File doesn't exist or is invalid, start fresh
|
|
676
|
+
}
|
|
677
|
+
// Append new snapshot
|
|
678
|
+
existingLog.push(snapshot);
|
|
679
|
+
// Write back
|
|
680
|
+
await fs.writeFile(healthLogPath, YAML.stringify(existingLog), 'utf-8');
|
|
681
|
+
return {
|
|
682
|
+
logged: true,
|
|
683
|
+
path: healthLogPath,
|
|
684
|
+
snapshot,
|
|
685
|
+
entryCount: existingLog.length,
|
|
686
|
+
};
|
|
687
|
+
}
|
|
688
|
+
// ============================================================================
|
|
689
|
+
// Health Tracking - Get Health History
|
|
690
|
+
// ============================================================================
|
|
691
|
+
function computeTrend(values) {
|
|
692
|
+
if (values.length < 2)
|
|
693
|
+
return 'stable';
|
|
694
|
+
// Compare first half average to second half average
|
|
695
|
+
const midpoint = Math.floor(values.length / 2);
|
|
696
|
+
const firstHalf = values.slice(0, midpoint);
|
|
697
|
+
const secondHalf = values.slice(midpoint);
|
|
698
|
+
const firstAvg = firstHalf.reduce((a, b) => a + b, 0) / firstHalf.length;
|
|
699
|
+
const secondAvg = secondHalf.reduce((a, b) => a + b, 0) / secondHalf.length;
|
|
700
|
+
const change = (secondAvg - firstAvg) / (firstAvg || 1);
|
|
701
|
+
// More than 10% change is considered significant
|
|
702
|
+
if (change < -0.1)
|
|
703
|
+
return 'improving';
|
|
704
|
+
if (change > 0.1)
|
|
705
|
+
return 'degrading';
|
|
706
|
+
return 'stable';
|
|
707
|
+
}
|
|
708
|
+
function computeGrowthTrend(values) {
|
|
709
|
+
if (values.length < 2)
|
|
710
|
+
return 'stable';
|
|
711
|
+
const midpoint = Math.floor(values.length / 2);
|
|
712
|
+
const firstHalf = values.slice(0, midpoint);
|
|
713
|
+
const secondHalf = values.slice(midpoint);
|
|
714
|
+
const firstAvg = firstHalf.reduce((a, b) => a + b, 0) / firstHalf.length;
|
|
715
|
+
const secondAvg = secondHalf.reduce((a, b) => a + b, 0) / secondHalf.length;
|
|
716
|
+
const change = (secondAvg - firstAvg) / (firstAvg || 1);
|
|
717
|
+
if (change > 0.1)
|
|
718
|
+
return 'growing';
|
|
719
|
+
if (change < -0.1)
|
|
720
|
+
return 'shrinking';
|
|
721
|
+
return 'stable';
|
|
722
|
+
}
|
|
723
|
+
export async function auditorHealthHistory(input) {
|
|
724
|
+
let resolved;
|
|
725
|
+
try {
|
|
726
|
+
resolved = resolveProjectPaths(input.projectId);
|
|
727
|
+
}
|
|
728
|
+
catch {
|
|
729
|
+
return makeError('Failed to resolve project path');
|
|
730
|
+
}
|
|
731
|
+
const limit = input.limit || 10;
|
|
732
|
+
const healthLogPath = path.join(resolved.subPath('auditor'), HEALTH_LOG_FILENAME);
|
|
733
|
+
// Read log
|
|
734
|
+
let allEntries = [];
|
|
735
|
+
try {
|
|
736
|
+
const content = await fs.readFile(healthLogPath, 'utf-8');
|
|
737
|
+
const parsed = YAML.parse(content);
|
|
738
|
+
if (Array.isArray(parsed)) {
|
|
739
|
+
allEntries = parsed;
|
|
740
|
+
}
|
|
741
|
+
}
|
|
742
|
+
catch {
|
|
743
|
+
return makeError('No health history found', 'Use auditor_log_health to record snapshots first');
|
|
744
|
+
}
|
|
745
|
+
if (allEntries.length === 0) {
|
|
746
|
+
return makeError('Health log is empty', 'Use auditor_log_health to record snapshots first');
|
|
747
|
+
}
|
|
748
|
+
// Get most recent entries up to limit
|
|
749
|
+
const entries = allEntries.slice(-limit);
|
|
750
|
+
// Compute trends from all entries (not just limited)
|
|
751
|
+
const godFilesValues = allEntries.map(e => e.metrics.godFiles);
|
|
752
|
+
const smellsValues = allEntries.map(e => e.metrics.smellCount.high + e.metrics.smellCount.medium + e.metrics.smellCount.low);
|
|
753
|
+
const linesValues = allEntries.map(e => e.metrics.totalLines);
|
|
754
|
+
const trends = {
|
|
755
|
+
godFiles: computeTrend(godFilesValues),
|
|
756
|
+
smells: computeTrend(smellsValues),
|
|
757
|
+
totalLines: computeGrowthTrend(linesValues),
|
|
758
|
+
};
|
|
759
|
+
return {
|
|
760
|
+
entries,
|
|
761
|
+
trends,
|
|
762
|
+
summary: {
|
|
763
|
+
oldestEntry: allEntries[0].timestamp,
|
|
764
|
+
newestEntry: allEntries[allEntries.length - 1].timestamp,
|
|
765
|
+
totalSnapshots: allEntries.length,
|
|
766
|
+
},
|
|
767
|
+
};
|
|
768
|
+
}
|
|
769
|
+
// ============================================================================
|
|
770
|
+
// Exports
|
|
771
|
+
// ============================================================================
|
|
772
|
+
export function isAuditorError(result) {
|
|
773
|
+
return typeof result === 'object' && result !== null && 'error' in result;
|
|
774
|
+
}
|
|
775
|
+
//# sourceMappingURL=auditor.js.map
|