@unerr-ai/unerr 0.1.0 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/__tests__/architecture-guard.test.js +122 -0
- package/dist/__tests__/arg-validator.test.js +205 -0
- package/dist/__tests__/ast-extractor.test.js +203 -0
- package/dist/__tests__/auto-bootstrap.test.js +280 -0
- package/dist/__tests__/background-indexer.test.js +228 -0
- package/dist/__tests__/blast-radius-engine.test.js +200 -0
- package/dist/__tests__/bridge-isolation.test.js +37 -0
- package/dist/__tests__/budget-enforcer.test.js +53 -0
- package/dist/__tests__/cfg-test-detection-perf.test.js +82 -0
- package/dist/__tests__/change-narrative.test.js +190 -0
- package/dist/__tests__/check-commit.test.js +258 -0
- package/dist/__tests__/checksum.test.js +34 -0
- package/dist/__tests__/commit-watcher.test.js +154 -0
- package/dist/__tests__/community-detection.test.js +179 -0
- package/dist/__tests__/community-tools.test.js +299 -0
- package/dist/__tests__/components.test.js +449 -0
- package/dist/__tests__/compression-log.test.js +174 -0
- package/dist/__tests__/compression-quality-monitor.test.js +40 -0
- package/dist/__tests__/config-healer.test.js +165 -0
- package/dist/__tests__/context-ledger.test.js +58 -0
- package/dist/__tests__/convention-detector.test.js +99 -0
- package/dist/__tests__/convention-learner.test.js +86 -0
- package/dist/__tests__/correction-detector.test.js +330 -0
- package/dist/__tests__/daemon-autostart-install.test.js +283 -0
- package/dist/__tests__/daemon-bridge.test.js +222 -0
- package/dist/__tests__/daemon-dashboard.test.js +202 -0
- package/dist/__tests__/daemon-registry.test.js +240 -0
- package/dist/__tests__/daemon-supervisor.test.js +318 -0
- package/dist/__tests__/daemon-version-check.test.js +275 -0
- package/dist/__tests__/decision-point-detector.test.js +98 -0
- package/dist/__tests__/deep-link.test.js +143 -0
- package/dist/__tests__/disallowed-tools.test.js +115 -0
- package/dist/__tests__/drift-tracker.test.js +582 -0
- package/dist/__tests__/durability-scorer.test.js +152 -0
- package/dist/__tests__/efficiency-tracker.test.js +65 -0
- package/dist/__tests__/enrich.test.js +144 -0
- package/dist/__tests__/entity-rewind.test.js +248 -0
- package/dist/__tests__/ephemeral.test.js +111 -0
- package/dist/__tests__/exploration-cost.test.js +93 -0
- package/dist/__tests__/fact-generator.test.js +197 -0
- package/dist/__tests__/file-l0-graph.test.js +244 -0
- package/dist/__tests__/file-logger.test.js +82 -0
- package/dist/__tests__/file-outline.test.js +141 -0
- package/dist/__tests__/file-read-protocol.test.js +188 -0
- package/dist/__tests__/format-encoder.test.js +233 -0
- package/dist/__tests__/git-attribution.test.js +259 -0
- package/dist/__tests__/graph-temporal-joiner.test.js +219 -0
- package/dist/__tests__/health-grade-enhanced.test.js +138 -0
- package/dist/__tests__/health-map-data.test.js +173 -0
- package/dist/__tests__/helpers/mcp-harness.js +45 -0
- package/dist/__tests__/helpers/mcp-harness.test.js +68 -0
- package/dist/__tests__/hook-dedup.test.js +112 -0
- package/dist/__tests__/hook-runner.test.js +253 -0
- package/dist/__tests__/indexer-cfg.test.js +185 -0
- package/dist/__tests__/indexer-cross-file.test.js +172 -0
- package/dist/__tests__/indexer-extraction.test.js +245 -0
- package/dist/__tests__/indexer-incremental.test.js +232 -0
- package/dist/__tests__/indexer-language-expansion.test.js +165 -0
- package/dist/__tests__/init-push.test.js +131 -0
- package/dist/__tests__/instruction-writer.test.js +179 -0
- package/dist/__tests__/intelligence-integration.test.js +217 -0
- package/dist/__tests__/intent-correlator.test.js +175 -0
- package/dist/__tests__/intent-detector.test.js +235 -0
- package/dist/__tests__/intent-encoder.test.js +167 -0
- package/dist/__tests__/java-build-tool-detection.test.js +174 -0
- package/dist/__tests__/layer3-sprint-q.test.js +160 -0
- package/dist/__tests__/layer3-sprint-r.test.js +91 -0
- package/dist/__tests__/layer3-sprint-s.test.js +183 -0
- package/dist/__tests__/layer3-sprint-t.test.js +201 -0
- package/dist/__tests__/layer3-sprint-u.test.js +174 -0
- package/dist/__tests__/layer4-sprint-ba2.test.js +354 -0
- package/dist/__tests__/layer4-sprint-ba4.test.js +84 -0
- package/dist/__tests__/layer4-sprint-vs.test.js +105 -0
- package/dist/__tests__/ledger-chains.test.js +162 -0
- package/dist/__tests__/lifecycle-machine.test.js +226 -0
- package/dist/__tests__/local-chat-provider.test.js +170 -0
- package/dist/__tests__/local-convention-detector.test.js +308 -0
- package/dist/__tests__/local-embeddings.test.js +422 -0
- package/dist/__tests__/local-graph.test.js +540 -0
- package/dist/__tests__/local-indexer.test.js +228 -0
- package/dist/__tests__/local-intelligence-l3.test.js +332 -0
- package/dist/__tests__/local-llm.test.js +253 -0
- package/dist/__tests__/local-mode-offline.test.js +187 -0
- package/dist/__tests__/local-mode-stats.test.js +273 -0
- package/dist/__tests__/local-mode-tui.test.js +343 -0
- package/dist/__tests__/local-parse.test.js +199 -0
- package/dist/__tests__/log-tailer.test.js +208 -0
- package/dist/__tests__/loop-breaker.test.js +276 -0
- package/dist/__tests__/loop-miner.test.js +226 -0
- package/dist/__tests__/mcp-config.test.js +126 -0
- package/dist/__tests__/mcp-content-json.test.js +10 -0
- package/dist/__tests__/mcp-envelope.test.js +124 -0
- package/dist/__tests__/metrics-store.test.js +223 -0
- package/dist/__tests__/native-watcher.test.js +191 -0
- package/dist/__tests__/navigation-hooks-agent-aware.test.js +145 -0
- package/dist/__tests__/negative-knowledge.test.js +116 -0
- package/dist/__tests__/network-boundary.test.js +190 -0
- package/dist/__tests__/network-firewall.test.js +112 -0
- package/dist/__tests__/nudge-invariants.test.js +160 -0
- package/dist/__tests__/nudge-v2.test.js +225 -0
- package/dist/__tests__/offline-rewind.test.js +251 -0
- package/dist/__tests__/open-threads.test.js +89 -0
- package/dist/__tests__/output-compressor.test.js +93 -0
- package/dist/__tests__/pending-violations.test.js +112 -0
- package/dist/__tests__/persistence-effectiveness.test.js +143 -0
- package/dist/__tests__/provider-factory.test.js +42 -0
- package/dist/__tests__/providers.test.js +24 -0
- package/dist/__tests__/proxy.test.js +314 -0
- package/dist/__tests__/query-router.test.js +1018 -0
- package/dist/__tests__/reasoning-quality-route.test.js +138 -0
- package/dist/__tests__/redactor.test.js +120 -0
- package/dist/__tests__/resource-monitor.test.js +57 -0
- package/dist/__tests__/response-envelope.test.js +100 -0
- package/dist/__tests__/risk-classifier.test.js +101 -0
- package/dist/__tests__/risk-signal-scope.test.js +75 -0
- package/dist/__tests__/rule-evaluator.test.js +280 -0
- package/dist/__tests__/scip-decoder.test.js +49 -0
- package/dist/__tests__/scip-downloader.test.js +201 -0
- package/dist/__tests__/scip-merger.test.js +103 -0
- package/dist/__tests__/search-index.test.js +422 -0
- package/dist/__tests__/semantic-enrichment.test.js +360 -0
- package/dist/__tests__/session-brief-builder.test.js +187 -0
- package/dist/__tests__/session-context.test.js +221 -0
- package/dist/__tests__/session-continuity.test.js +144 -0
- package/dist/__tests__/session-dedup.test.js +74 -0
- package/dist/__tests__/session-event-wiring.test.js +206 -0
- package/dist/__tests__/session-events.test.js +149 -0
- package/dist/__tests__/session-legend.test.js +20 -0
- package/dist/__tests__/session-persistence.test.js +131 -0
- package/dist/__tests__/session-resume-block.test.js +107 -0
- package/dist/__tests__/session-resume.test.js +97 -0
- package/dist/__tests__/session-summary-writer.test.js +134 -0
- package/dist/__tests__/shadow-ledger.test.js +203 -0
- package/dist/__tests__/shell-classifier.test.js +151 -0
- package/dist/__tests__/shell-compression-floor.test.js +189 -0
- package/dist/__tests__/shell-compression-v2.test.js +339 -0
- package/dist/__tests__/shell-compressor.test.js +35 -0
- package/dist/__tests__/shell-hooks.test.js +128 -0
- package/dist/__tests__/shell-strategies.test.js +644 -0
- package/dist/__tests__/shell-tee.test.js +133 -0
- package/dist/__tests__/signal-dedup.test.js +158 -0
- package/dist/__tests__/signal-reinforcer.test.js +77 -0
- package/dist/__tests__/signal-scorer.test.js +251 -0
- package/dist/__tests__/signal-show-store.test.js +108 -0
- package/dist/__tests__/smart-truncate.test.js +215 -0
- package/dist/__tests__/snapshot-v2.test.js +113 -0
- package/dist/__tests__/sprint-l1-local-mode.test.js +130 -0
- package/dist/__tests__/sprint-l10-boot.test.js +220 -0
- package/dist/__tests__/sprint-l9-offline-commands.test.js +189 -0
- package/dist/__tests__/sprint-q-persistent-context.test.js +198 -0
- package/dist/__tests__/sprint-s1-wiring.test.js +215 -0
- package/dist/__tests__/sprint-s2-wiring.test.js +256 -0
- package/dist/__tests__/sprint-s3-wiring.test.js +195 -0
- package/dist/__tests__/sprint-s4-wiring.test.js +213 -0
- package/dist/__tests__/sprint-s6-hooks.test.js +222 -0
- package/dist/__tests__/sprint-s7-persistent.test.js +263 -0
- package/dist/__tests__/sprint-s8-value.test.js +167 -0
- package/dist/__tests__/sprint-s9-behavioral.test.js +179 -0
- package/dist/__tests__/sprint3-intelligence.test.js +297 -0
- package/dist/__tests__/sprint5-mcp-server.test.js +136 -0
- package/dist/__tests__/startup-display.test.js +302 -0
- package/dist/__tests__/startup-log-file.test.js +97 -0
- package/dist/__tests__/stash-manager.test.js +229 -0
- package/dist/__tests__/state-detector.test.js +92 -0
- package/dist/__tests__/status-dashboard.test.js +142 -0
- package/dist/__tests__/temporal-facts.test.js +292 -0
- package/dist/__tests__/temporal-routes.test.js +142 -0
- package/dist/__tests__/test-detector.test.js +174 -0
- package/dist/__tests__/theme.test.js +72 -0
- package/dist/__tests__/timeline-agents.test.js +122 -0
- package/dist/__tests__/timeline-bootstrap.test.js +176 -0
- package/dist/__tests__/timeline-filters.test.js +193 -0
- package/dist/__tests__/timeline-markers.test.js +151 -0
- package/dist/__tests__/timeline-routes.test.js +156 -0
- package/dist/__tests__/timeline-store.test.js +171 -0
- package/dist/__tests__/token-counter.test.js +86 -0
- package/dist/__tests__/token-estimator.test.js +96 -0
- package/dist/__tests__/token-flow-api.test.js +239 -0
- package/dist/__tests__/token-flow-instrumentation.test.js +437 -0
- package/dist/__tests__/token-flow-persistence.test.js +356 -0
- package/dist/__tests__/token-flow-routes.test.js +199 -0
- package/dist/__tests__/token-flow.test.js +695 -0
- package/dist/__tests__/tool-clusters.test.js +177 -0
- package/dist/__tests__/transport-mux.test.js +283 -0
- package/dist/__tests__/turn-segmenter.test.js +166 -0
- package/dist/__tests__/uninstall.test.js +141 -0
- package/dist/__tests__/warm-start-policy.test.js +271 -0
- package/dist/__tests__/wire-cap-nudge.test.js +77 -0
- package/dist/__tests__/worker-pool.test.js +101 -0
- package/dist/behaviors/agent-llm-bridge.js +166 -0
- package/dist/behaviors/architecture-guard.js +256 -0
- package/dist/behaviors/auto-doc.js +247 -0
- package/dist/behaviors/cascade-guard.js +289 -0
- package/dist/behaviors/change-narrative.js +270 -0
- package/dist/behaviors/convention-drift.js +290 -0
- package/dist/behaviors/framework.js +235 -0
- package/dist/behaviors/guard-formatter.js +44 -0
- package/dist/behaviors/incomplete-work.js +270 -0
- package/dist/behaviors/loop-breaker.js +300 -0
- package/dist/behaviors/session-continuity.js +208 -0
- package/dist/cli.js +996 -710
- package/dist/commands/branches.js +97 -0
- package/dist/commands/check-commit.js +225 -0
- package/dist/commands/compress-output.js +64 -0
- package/dist/commands/config-verify.js +243 -0
- package/dist/commands/daemon.js +905 -0
- package/dist/commands/dashboard.js +52 -0
- package/dist/commands/debug.js +200 -0
- package/dist/commands/enrich.js +184 -0
- package/dist/commands/exec.js +233 -0
- package/dist/commands/gain.js +156 -0
- package/dist/commands/hook.js +88 -0
- package/dist/commands/index.js +88 -0
- package/dist/commands/init.js +74 -0
- package/dist/commands/install.js +505 -0
- package/dist/commands/learn.js +116 -0
- package/dist/commands/manifest.js +193 -0
- package/dist/commands/rewind.js +103 -0
- package/dist/commands/serve.js +19 -0
- package/dist/commands/setup-wizard.js +414 -0
- package/dist/commands/skills.js +64 -0
- package/dist/commands/stats.js +20 -0
- package/dist/commands/status.js +654 -0
- package/dist/commands/timeline.js +139 -0
- package/dist/commands/uninstall.js +230 -0
- package/dist/components/App.js +109 -0
- package/dist/components/Banner.js +12 -0
- package/dist/components/ConfirmPrompt.js +25 -0
- package/dist/components/DriftSummary.js +23 -0
- package/dist/components/GradeBadge.js +15 -0
- package/dist/components/HealthCard.js +18 -0
- package/dist/components/InkSpinner.js +22 -0
- package/dist/components/InputBox.js +17 -0
- package/dist/components/KeyValue.js +13 -0
- package/dist/components/MessageList.js +14 -0
- package/dist/components/ProgressBar.js +26 -0
- package/dist/components/Section.js +16 -0
- package/dist/components/SessionSummaryCard.js +73 -0
- package/dist/components/StartupDisplay.js +24 -0
- package/dist/components/StatusDashboard.js +57 -0
- package/dist/components/StatusLine.js +8 -0
- package/dist/components/StepLine.js +22 -0
- package/dist/components/Theme.js +20 -0
- package/dist/components/ToolProgress.js +8 -0
- package/dist/components/ViolationList.js +21 -0
- package/dist/components/render.js +13 -0
- package/dist/config/agent-registry.js +237 -0
- package/dist/config/claude-settings-hooks.js +304 -0
- package/dist/config/hook-installer.js +65 -0
- package/dist/config/instruction-writer.js +388 -0
- package/dist/config/mcp-config-writer.js +266 -0
- package/dist/config/settings.js +174 -0
- package/dist/config/tool-detector.js +42 -0
- package/dist/config/value-surfacing.js +119 -0
- package/dist/core/context-assembly.js +108 -0
- package/dist/core/conversation.js +33 -0
- package/dist/core/local-chat-provider.js +475 -0
- package/dist/core/provider-factory.js +55 -0
- package/dist/core/providers.js +90 -0
- package/dist/core/query-engine.js +174 -0
- package/dist/daemon/api.js +312 -0
- package/dist/daemon/autostart.js +119 -0
- package/dist/daemon/bootstrap.js +39 -0
- package/dist/daemon/client.js +164 -0
- package/dist/daemon/detect-ci.js +81 -0
- package/dist/daemon/platform-linux.js +146 -0
- package/dist/daemon/platform-macos.js +134 -0
- package/dist/daemon/platform-windows.js +116 -0
- package/dist/daemon/process-manager.js +299 -0
- package/dist/daemon/protocol.js +23 -0
- package/dist/daemon/registry.js +270 -0
- package/dist/daemon/settings-schema.js +72 -0
- package/dist/daemon/system-health.js +134 -0
- package/dist/daemon/version-checker.js +262 -0
- package/dist/daemon/warm-start.js +223 -0
- package/dist/entrypoints/cli.js +1043 -0
- package/dist/entrypoints/daemon.js +380 -0
- package/dist/entrypoints/repl.js +147 -0
- package/dist/hooks/adapters/claude-code.js +90 -0
- package/dist/hooks/adapters/cline.js +100 -0
- package/dist/hooks/adapters/cursor.js +98 -0
- package/dist/hooks/hook-dedup.js +79 -0
- package/dist/hooks/hook-runner.js +113 -0
- package/dist/hooks/navigation-hooks.js +175 -0
- package/dist/hooks/prompt-hooks.js +63 -0
- package/dist/hooks/shell-hooks.js +47 -0
- package/dist/ignore.js +111 -0
- package/dist/intelligence/approach-suggester.js +61 -0
- package/dist/intelligence/ast-extractor.js +2615 -0
- package/dist/intelligence/ast-worker.js +34 -0
- package/dist/intelligence/background-indexer.js +121 -0
- package/dist/intelligence/blast-radius.js +200 -0
- package/dist/intelligence/community-detection.js +691 -0
- package/dist/intelligence/community-detector.js +184 -0
- package/dist/intelligence/computation-scheduler.js +75 -0
- package/dist/intelligence/confidence-propagation.js +47 -0
- package/dist/intelligence/convention-detector.js +242 -0
- package/dist/intelligence/convention-learner.js +205 -0
- package/dist/intelligence/convention-matcher.js +205 -0
- package/dist/intelligence/cozo-schema.js +376 -0
- package/dist/intelligence/decision-point-detector.js +90 -0
- package/dist/intelligence/deep-dive-tools.js +586 -0
- package/dist/intelligence/durability-scorer.js +84 -0
- package/dist/intelligence/exploration-cost.js +204 -0
- package/dist/intelligence/exploration-pattern-tracker.js +61 -0
- package/dist/intelligence/fact-generator.js +322 -0
- package/dist/intelligence/facts-schema.js +90 -0
- package/dist/intelligence/file-intelligence.js +59 -0
- package/dist/intelligence/graph-holder.js +220 -0
- package/dist/intelligence/graph-temporal-joiner.js +238 -0
- package/dist/intelligence/health-grade.js +423 -0
- package/dist/intelligence/health-grader.js +200 -0
- package/dist/intelligence/health-map-data.js +259 -0
- package/dist/intelligence/import-symbols.js +136 -0
- package/dist/intelligence/incremental-indexer.js +658 -0
- package/dist/intelligence/indexer/centrality.js +62 -0
- package/dist/intelligence/indexer/cfg-context.js +95 -0
- package/dist/intelligence/indexer/confidence.js +34 -0
- package/dist/intelligence/indexer/cross-file-resolver.js +104 -0
- package/dist/intelligence/indexer/edge-repair.js +89 -0
- package/dist/intelligence/indexer/entity-key.js +17 -0
- package/dist/intelligence/indexer/export-map.js +132 -0
- package/dist/intelligence/indexer/git-cochange.js +128 -0
- package/dist/intelligence/indexer/graph-patch.js +147 -0
- package/dist/intelligence/indexer/incremental.js +78 -0
- package/dist/intelligence/indexer/ingest.js +160 -0
- package/dist/intelligence/indexer/language-detect.js +226 -0
- package/dist/intelligence/indexer/metadata.js +63 -0
- package/dist/intelligence/indexer/mutation-tracker.js +79 -0
- package/dist/intelligence/indexer/orchestrator.js +155 -0
- package/dist/intelligence/indexer/plugin-interface.js +31 -0
- package/dist/intelligence/indexer/plugins/csharp.js +440 -0
- package/dist/intelligence/indexer/plugins/go.js +335 -0
- package/dist/intelligence/indexer/plugins/java.js +370 -0
- package/dist/intelligence/indexer/plugins/python.js +358 -0
- package/dist/intelligence/indexer/plugins/regex-fallback.js +82 -0
- package/dist/intelligence/indexer/plugins/ruby.js +290 -0
- package/dist/intelligence/indexer/plugins/rust.js +484 -0
- package/dist/intelligence/indexer/plugins/tier2-generic.js +310 -0
- package/dist/intelligence/indexer/plugins/typescript.js +456 -0
- package/dist/intelligence/indexer/resource-monitor.js +93 -0
- package/dist/intelligence/indexer/scip/decoder.js +253 -0
- package/dist/intelligence/indexer/scip/detector.js +232 -0
- package/dist/intelligence/indexer/scip/downloader.js +427 -0
- package/dist/intelligence/indexer/scip/fallback.js +34 -0
- package/dist/intelligence/indexer/scip/merger.js +109 -0
- package/dist/intelligence/indexer/scip/orchestrator.js +433 -0
- package/dist/intelligence/indexer/scip/runner.js +98 -0
- package/dist/intelligence/indexer/snapshot.js +66 -0
- package/dist/intelligence/indexer/test-detector.js +196 -0
- package/dist/intelligence/indexer/watch-integration.js +61 -0
- package/dist/intelligence/indexer/worker.js +85 -0
- package/dist/intelligence/local-convention-detector.js +437 -0
- package/dist/intelligence/local-embeddings.js +190 -0
- package/dist/intelligence/local-graph.js +1946 -0
- package/dist/intelligence/local-indexer.js +1575 -0
- package/dist/intelligence/local-llm.js +163 -0
- package/dist/intelligence/local-rule-generator.js +154 -0
- package/dist/intelligence/local-snapshot.js +213 -0
- package/dist/intelligence/negative-knowledge.js +103 -0
- package/dist/intelligence/persistent-db.js +85 -0
- package/dist/intelligence/query-router.js +2556 -0
- package/dist/intelligence/risk-classifier.js +116 -0
- package/dist/intelligence/rule-evaluator.js +380 -0
- package/dist/intelligence/rule-generator.js +49 -0
- package/dist/intelligence/search-index.js +173 -0
- package/dist/intelligence/semantic/docstring-extractor.js +67 -0
- package/dist/intelligence/semantic/embedding-store.js +52 -0
- package/dist/intelligence/semantic/enrichment-orchestrator.js +48 -0
- package/dist/intelligence/semantic/git-message-miner.js +114 -0
- package/dist/intelligence/semantic/identifier-tokenizer.js +51 -0
- package/dist/intelligence/semantic/node2vec-embeddings.js +71 -0
- package/dist/intelligence/semantic/node2vec-walks.js +103 -0
- package/dist/intelligence/semantic/path-domain-inference.js +112 -0
- package/dist/intelligence/semantic/similarity-engine.js +60 -0
- package/dist/intelligence/semantic/tfidf-vectors.js +88 -0
- package/dist/intelligence/session-brief-builder.js +159 -0
- package/dist/intelligence/session-context.js +221 -0
- package/dist/intelligence/session-health-monitor.js +211 -0
- package/dist/intelligence/session-narrative.js +197 -0
- package/dist/intelligence/session-pattern-analyzer.js +218 -0
- package/dist/intelligence/signal-scorer.js +390 -0
- package/dist/intelligence/signal-show-store.js +182 -0
- package/dist/intelligence/smart-truncate.js +158 -0
- package/dist/intelligence/subgraph-cache.js +88 -0
- package/dist/intelligence/temporal-facts.js +494 -0
- package/dist/intelligence/token-estimator.js +100 -0
- package/dist/intelligence/tool-injector.js +87 -0
- package/dist/intelligence/tree-sitter-loader.js +71 -0
- package/dist/intelligence/worker-pool.js +116 -0
- package/dist/proxy/arg-validator.js +79 -0
- package/dist/proxy/auto-bootstrap.js +167 -0
- package/dist/proxy/bridge.js +147 -0
- package/dist/proxy/budget-enforcer.js +70 -0
- package/dist/proxy/compression-quality-monitor.js +160 -0
- package/dist/proxy/compression-stats.js +51 -0
- package/dist/proxy/context-rot-detector.js +137 -0
- package/dist/proxy/drift-detector.js +139 -0
- package/dist/proxy/efficiency-tracker.js +79 -0
- package/dist/proxy/fact-ranking.js +154 -0
- package/dist/proxy/format-encoder.js +266 -0
- package/dist/proxy/http-transport.js +90 -0
- package/dist/proxy/lifecycle-actor.js +55 -0
- package/dist/proxy/lifecycle-machine.js +187 -0
- package/dist/proxy/log-tailer.js +265 -0
- package/dist/proxy/model-pricing.js +98 -0
- package/dist/proxy/network-firewall.js +141 -0
- package/dist/proxy/nudge-state.js +93 -0
- package/dist/proxy/output-compressor.js +185 -0
- package/dist/proxy/pid-lock.js +291 -0
- package/dist/proxy/proxy-context.js +11 -0
- package/dist/proxy/proxy.js +2633 -0
- package/dist/proxy/response-enrichment.js +32 -0
- package/dist/proxy/response-envelope.js +313 -0
- package/dist/proxy/session-dedup.js +82 -0
- package/dist/proxy/session-legend.js +30 -0
- package/dist/proxy/session-persistence.js +210 -0
- package/dist/proxy/session-resume.js +94 -0
- package/dist/proxy/session-stats.js +513 -0
- package/dist/proxy/shell-classifier.js +1346 -0
- package/dist/proxy/shell-compression-log.js +93 -0
- package/dist/proxy/shell-compressor.js +390 -0
- package/dist/proxy/shell-graph-boost.js +202 -0
- package/dist/proxy/shell-monitor-map.js +18 -0
- package/dist/proxy/shell-stats.js +54 -0
- package/dist/proxy/shell-strategies/cloud.js +215 -0
- package/dist/proxy/shell-strategies/diff.js +159 -0
- package/dist/proxy/shell-strategies/error-diagnostic.js +796 -0
- package/dist/proxy/shell-strategies/filter-dsl.js +358 -0
- package/dist/proxy/shell-strategies/git-status.js +177 -0
- package/dist/proxy/shell-strategies/key-value.js +193 -0
- package/dist/proxy/shell-strategies/log-text.js +154 -0
- package/dist/proxy/shell-strategies/omni.js +188 -0
- package/dist/proxy/shell-strategies/progress.js +55 -0
- package/dist/proxy/shell-strategies/redact.js +76 -0
- package/dist/proxy/shell-strategies/structured.js +241 -0
- package/dist/proxy/shell-strategies/tabular.js +243 -0
- package/dist/proxy/shell-strategies/test-results-types.js +13 -0
- package/dist/proxy/shell-strategies/test-results.js +784 -0
- package/dist/proxy/shell-strategies/tree-paths.js +144 -0
- package/dist/proxy/shell-strategies/yaml.js +182 -0
- package/dist/proxy/shell-tee.js +111 -0
- package/dist/proxy/signal-dedup.js +171 -0
- package/dist/proxy/startup-renderer.js +158 -0
- package/dist/proxy/task-token-display.js +38 -0
- package/dist/proxy/token-counter.js +61 -0
- package/dist/proxy/tool-clusters.js +273 -0
- package/dist/proxy/tool-definitions.js +525 -0
- package/dist/proxy/transport-mux.js +229 -0
- package/dist/proxy/wire-cap.js +268 -0
- package/dist/schemas/api/skills.js +19 -0
- package/dist/schemas/common/errors.js +7 -0
- package/dist/schemas/common/headers.js +5 -0
- package/dist/schemas/entities/edge.js +25 -0
- package/dist/schemas/entities/entity.js +22 -0
- package/dist/schemas/entities/rule.js +18 -0
- package/dist/schemas/index.js +14 -0
- package/dist/server/event-bus.js +59 -0
- package/dist/server/http.js +156 -0
- package/dist/server/middleware.js +70 -0
- package/dist/server/routes/drift.js +97 -0
- package/dist/server/routes/intelligence.js +1217 -0
- package/dist/server/routes/reasoning-quality.js +444 -0
- package/dist/server/routes/session.js +86 -0
- package/dist/server/routes/stream.js +120 -0
- package/dist/server/routes/system.js +73 -0
- package/dist/server/routes/temporal.js +170 -0
- package/dist/server/routes/timeline.js +232 -0
- package/dist/server/routes/token-flow.js +403 -0
- package/dist/skills/effectiveness-tracker.js +93 -0
- package/dist/skills/local-pack.js +380 -0
- package/dist/skills/resolver.js +495 -0
- package/dist/state-detector.js +83 -0
- package/dist/timeline/intent-detector.js +263 -0
- package/dist/timeline/loop-miner.js +140 -0
- package/dist/timeline/open-threads.js +49 -0
- package/dist/timeline/signal-reinforcer.js +62 -0
- package/dist/timeline/timeline-bootstrap.js +151 -0
- package/dist/timeline/timeline-store.js +618 -0
- package/dist/tools/coding/bash.js +49 -0
- package/dist/tools/coding/file-edit.js +72 -0
- package/dist/tools/coding/file-outline.js +227 -0
- package/dist/tools/coding/file-read-protocol.js +425 -0
- package/dist/tools/coding/file-read.js +35 -0
- package/dist/tools/coding/file-write.js +43 -0
- package/dist/tools/coding/glob-tool.js +109 -0
- package/dist/tools/coding/grep.js +162 -0
- package/dist/tools/coding/index.js +27 -0
- package/dist/tools/intelligence/index.js +269 -0
- package/dist/tools/intelligence/record-fact.js +48 -0
- package/dist/tools/intelligence/timeline-markers.js +130 -0
- package/dist/tools/registry.js +47 -0
- package/dist/tools/types.js +8 -0
- package/dist/tracking/auto-snapshot-triggers.js +246 -0
- package/dist/tracking/branch-context.js +115 -0
- package/dist/tracking/branch-snapshot.js +217 -0
- package/dist/tracking/causal-bridge.js +317 -0
- package/dist/tracking/circuit-breaker.js +147 -0
- package/dist/tracking/commit-watcher.js +114 -0
- package/dist/tracking/context-ledger.js +119 -0
- package/dist/tracking/correction-detector.js +324 -0
- package/dist/tracking/drift-tracker.js +874 -0
- package/dist/tracking/durability-tracker.js +94 -0
- package/dist/tracking/entity-rewind.js +200 -0
- package/dist/tracking/file-hash-state.js +114 -0
- package/dist/tracking/git-attribution.js +132 -0
- package/dist/tracking/git-trailers.js +171 -0
- package/dist/tracking/intelligence-counter.js +46 -0
- package/dist/tracking/intent-correlator.js +202 -0
- package/dist/tracking/intent-encoder.js +52 -0
- package/dist/tracking/intent-token-tracker.js +159 -0
- package/dist/tracking/ledger-archiver.js +94 -0
- package/dist/tracking/ledger-chains.js +245 -0
- package/dist/tracking/metrics-store.js +361 -0
- package/dist/tracking/native-watcher.js +131 -0
- package/dist/tracking/offline-rewind.js +295 -0
- package/dist/tracking/pending-violations.js +74 -0
- package/dist/tracking/persistence-effectiveness.js +167 -0
- package/dist/tracking/prompt-durability.js +202 -0
- package/dist/tracking/quality-signals.js +213 -0
- package/dist/tracking/redactor.js +73 -0
- package/dist/tracking/rewind-engine.js +161 -0
- package/dist/tracking/session-history.js +128 -0
- package/dist/tracking/session-receipt.js +88 -0
- package/dist/tracking/session-summary-writer.js +157 -0
- package/dist/tracking/shadow-ledger.js +321 -0
- package/dist/tracking/stash-manager.js +258 -0
- package/dist/tracking/timeline-fork.js +213 -0
- package/dist/tracking/timeline.js +69 -0
- package/dist/tracking/token-flow.js +276 -0
- package/dist/tracking/turn-segmenter.js +122 -0
- package/dist/tracking/weekly-accumulator.js +179 -0
- package/dist/tracking/working-snapshots.js +188 -0
- package/dist/tracking/workspace-manifest.js +176 -0
- package/dist/transport/http.js +102 -0
- package/dist/ui/assets/index-BsMTQdhX.js +10 -0
- package/dist/ui/index.html +1 -1
- package/dist/utils/counterfactual.js +65 -0
- package/dist/utils/deep-link.js +34 -0
- package/dist/utils/detect.js +193 -0
- package/dist/utils/exec.js +73 -0
- package/dist/utils/file-logger.js +87 -0
- package/dist/utils/format-error.js +29 -0
- package/dist/utils/git.js +181 -0
- package/dist/utils/log.js +57 -0
- package/dist/utils/logger.js +35 -0
- package/dist/utils/mcp-content-json.js +8 -0
- package/dist/utils/session-logger.js +154 -0
- package/dist/utils/startup-log.js +512 -0
- package/dist/utils/ui.js +56 -0
- package/package.json +5 -3
- package/scripts/postinstall.mjs +312 -0
- package/dist/ui/assets/index-B-0HTtUR.js +0 -10
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import * as fs from "node:fs";
|
|
2
|
+
import * as path from "node:path";
|
|
3
|
+
import { gitQuery } from "../utils/exec.js";
|
|
4
|
+
export async function listLocalBranches(cwd) {
|
|
5
|
+
const raw = await gitQuery([
|
|
6
|
+
"branch",
|
|
7
|
+
"-a",
|
|
8
|
+
"--format=%(HEAD)|%(refname:short)|%(upstream:track)|%(committerdate:relative)",
|
|
9
|
+
], cwd);
|
|
10
|
+
if (!raw)
|
|
11
|
+
return [];
|
|
12
|
+
const driftCounts = loadBranchDriftCounts(cwd);
|
|
13
|
+
const branches = [];
|
|
14
|
+
for (const line of raw.split("\n")) {
|
|
15
|
+
const trimmed = line.trim();
|
|
16
|
+
if (!trimmed)
|
|
17
|
+
continue;
|
|
18
|
+
const parts = trimmed.split("|");
|
|
19
|
+
const isCurrent = parts[0] === "*";
|
|
20
|
+
const name = parts[1] ?? "";
|
|
21
|
+
const tracking = parts[2] ?? "";
|
|
22
|
+
const lastCommit = parts[3] ?? "";
|
|
23
|
+
if (!name)
|
|
24
|
+
continue;
|
|
25
|
+
branches.push({
|
|
26
|
+
name,
|
|
27
|
+
isCurrent,
|
|
28
|
+
lastCommit,
|
|
29
|
+
tracking,
|
|
30
|
+
driftEntityCount: driftCounts.get(name) ?? 0,
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
return branches;
|
|
34
|
+
}
|
|
35
|
+
function loadBranchDriftCounts(cwd) {
|
|
36
|
+
const counts = new Map();
|
|
37
|
+
const branchDir = path.join(cwd, ".unerr", "state", "branch-overlays");
|
|
38
|
+
if (!fs.existsSync(branchDir))
|
|
39
|
+
return counts;
|
|
40
|
+
try {
|
|
41
|
+
const entries = fs.readdirSync(branchDir, { withFileTypes: true });
|
|
42
|
+
for (const entry of entries) {
|
|
43
|
+
if (!entry.isDirectory())
|
|
44
|
+
continue;
|
|
45
|
+
const overlayPath = path.join(branchDir, entry.name, "overlay_snapshot.json");
|
|
46
|
+
if (!fs.existsSync(overlayPath))
|
|
47
|
+
continue;
|
|
48
|
+
try {
|
|
49
|
+
const raw = fs.readFileSync(overlayPath, "utf-8");
|
|
50
|
+
const snapshot = JSON.parse(raw);
|
|
51
|
+
if (snapshot.branch && snapshot.entities) {
|
|
52
|
+
counts.set(snapshot.branch, snapshot.entities.length);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
catch {
|
|
56
|
+
// Skip corrupt snapshots
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
catch {
|
|
61
|
+
// Non-blocking
|
|
62
|
+
}
|
|
63
|
+
return counts;
|
|
64
|
+
}
|
|
65
|
+
export function registerBranchesCommand(program) {
|
|
66
|
+
program
|
|
67
|
+
.command("branches")
|
|
68
|
+
.description("Show branches for this repository")
|
|
69
|
+
.action(async () => {
|
|
70
|
+
try {
|
|
71
|
+
const cwd = process.cwd();
|
|
72
|
+
const branches = await listLocalBranches(cwd);
|
|
73
|
+
if (branches.length === 0) {
|
|
74
|
+
process.stderr.write("[unerr] No branches found.\n");
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
let withDrift = 0;
|
|
78
|
+
process.stderr.write("\n");
|
|
79
|
+
for (const branch of branches) {
|
|
80
|
+
const marker = branch.isCurrent ? "* " : " ";
|
|
81
|
+
const trackingSuffix = branch.tracking ? ` ${branch.tracking}` : "";
|
|
82
|
+
let driftSuffix = "";
|
|
83
|
+
if (branch.driftEntityCount > 0) {
|
|
84
|
+
driftSuffix = ` (${branch.driftEntityCount} drift entities)`;
|
|
85
|
+
withDrift++;
|
|
86
|
+
}
|
|
87
|
+
process.stderr.write(`${marker}${branch.name.padEnd(30)} ${branch.lastCommit}${trackingSuffix}${driftSuffix}\n`);
|
|
88
|
+
}
|
|
89
|
+
process.stderr.write(`\n ${branches.length} branches · ${withDrift} with drift overlays\n\n`);
|
|
90
|
+
}
|
|
91
|
+
catch (error) {
|
|
92
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
93
|
+
console.error(`Error: ${message}`);
|
|
94
|
+
process.exit(1);
|
|
95
|
+
}
|
|
96
|
+
});
|
|
97
|
+
}
|
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* unerr check-commit — Pre-commit convention validation.
|
|
3
|
+
*
|
|
4
|
+
* Called by the pre-commit git hook to check staged changes
|
|
5
|
+
* against project conventions. Non-blocking by default.
|
|
6
|
+
*
|
|
7
|
+
* Sprint 4 (Task 4.2): Full convention checking implementation.
|
|
8
|
+
*
|
|
9
|
+
* Flow:
|
|
10
|
+
* 1. Load CozoDB graph from local snapshot
|
|
11
|
+
* 2. Get staged files from git
|
|
12
|
+
* 3. Evaluate rules against each staged file
|
|
13
|
+
* 4. Display violations with formatted output
|
|
14
|
+
* 5. Exit 1 if blocking mode and violations found
|
|
15
|
+
*
|
|
16
|
+
* Exit codes:
|
|
17
|
+
* 0 — All checks pass (or no checks available)
|
|
18
|
+
* 1 — Violations found (only when blocking mode is enabled)
|
|
19
|
+
*/
|
|
20
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
21
|
+
import { extname, join } from "node:path";
|
|
22
|
+
import { gunzipSync } from "node:zlib";
|
|
23
|
+
import pc from "picocolors";
|
|
24
|
+
import { getStagedFiles } from "../utils/git.js";
|
|
25
|
+
import { logInfo } from "../utils/log.js";
|
|
26
|
+
import { detail, fail, info, section, success, warn } from "../utils/ui.js";
|
|
27
|
+
/** File extensions we can evaluate rules against. */
|
|
28
|
+
const SUPPORTED_EXTENSIONS = new Set([
|
|
29
|
+
".ts",
|
|
30
|
+
".tsx",
|
|
31
|
+
".js",
|
|
32
|
+
".jsx",
|
|
33
|
+
".py",
|
|
34
|
+
".go",
|
|
35
|
+
]);
|
|
36
|
+
export function registerCheckCommitCommand(program) {
|
|
37
|
+
program
|
|
38
|
+
.command("check-commit")
|
|
39
|
+
.description("Check staged changes against project conventions (pre-commit hook)")
|
|
40
|
+
.option("--blocking", "Exit with code 1 on violations (default: non-blocking)")
|
|
41
|
+
.option("--verbose", "Show detailed output including passing files")
|
|
42
|
+
.action(async (opts) => {
|
|
43
|
+
const cwd = process.cwd();
|
|
44
|
+
// ── Blocking mode detection ──────────────────────────────────
|
|
45
|
+
let blockingMode = opts.blocking ?? false;
|
|
46
|
+
const settingsPath = join(cwd, ".unerr", "settings.json");
|
|
47
|
+
if (!blockingMode && existsSync(settingsPath)) {
|
|
48
|
+
try {
|
|
49
|
+
const settings = JSON.parse(readFileSync(settingsPath, "utf-8"));
|
|
50
|
+
blockingMode = settings.hooks?.precommit?.blocking ?? false;
|
|
51
|
+
}
|
|
52
|
+
catch {
|
|
53
|
+
/* ignore malformed settings */
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
logInfo("check-commit invoked", { blocking: blockingMode });
|
|
57
|
+
// ── Config gating ────────────────────────────────────────────
|
|
58
|
+
const configPath = join(cwd, ".unerr", "config.json");
|
|
59
|
+
if (!existsSync(configPath)) {
|
|
60
|
+
logInfo("check-commit: no .unerr/config.json, skipping");
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
let repoId;
|
|
64
|
+
try {
|
|
65
|
+
const config = JSON.parse(readFileSync(configPath, "utf-8"));
|
|
66
|
+
if (!config.repoId) {
|
|
67
|
+
logInfo("check-commit: no repoId in config, skipping");
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
repoId = config.repoId;
|
|
71
|
+
}
|
|
72
|
+
catch {
|
|
73
|
+
logInfo("check-commit: invalid config.json, skipping");
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
// ── Get staged files ─────────────────────────────────────────
|
|
77
|
+
const stagedFiles = await getStagedFiles(cwd);
|
|
78
|
+
if (stagedFiles.length === 0) {
|
|
79
|
+
logInfo("check-commit: no staged files");
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
// Filter to supported file types
|
|
83
|
+
const checkableFiles = stagedFiles.filter((f) => SUPPORTED_EXTENSIONS.has(extname(f)));
|
|
84
|
+
if (checkableFiles.length === 0) {
|
|
85
|
+
if (opts.verbose) {
|
|
86
|
+
section("unerr pre-commit check");
|
|
87
|
+
detail(`${stagedFiles.length} staged file${stagedFiles.length !== 1 ? "s" : ""} — none with supported extensions`);
|
|
88
|
+
}
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
// ── Load graph ───────────────────────────────────────────────
|
|
92
|
+
const snapshotsDir = join(cwd, ".unerr", "snapshots");
|
|
93
|
+
const manifestsDir = join(cwd, ".unerr", "manifests");
|
|
94
|
+
const localGraph = await loadGraphForCheckCommit(repoId, snapshotsDir, manifestsDir);
|
|
95
|
+
if (!localGraph) {
|
|
96
|
+
if (opts.verbose) {
|
|
97
|
+
section("unerr pre-commit check");
|
|
98
|
+
detail("No local graph available — skipping convention checks");
|
|
99
|
+
}
|
|
100
|
+
logInfo("check-commit: no graph available, skipping");
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
// Check if any rules exist
|
|
104
|
+
if (!(await localGraph.hasRules())) {
|
|
105
|
+
if (opts.verbose) {
|
|
106
|
+
section("unerr pre-commit check");
|
|
107
|
+
detail("No rules defined — skipping convention checks");
|
|
108
|
+
}
|
|
109
|
+
logInfo("check-commit: no rules in graph, skipping");
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
// ── Evaluate rules per file ──────────────────────────────────
|
|
113
|
+
const { evaluateRules } = await import("../intelligence/rule-evaluator.js");
|
|
114
|
+
const allFileViolations = [];
|
|
115
|
+
let totalRulesEvaluated = 0;
|
|
116
|
+
let filesChecked = 0;
|
|
117
|
+
for (const filePath of checkableFiles) {
|
|
118
|
+
const absPath = join(cwd, filePath);
|
|
119
|
+
if (!existsSync(absPath))
|
|
120
|
+
continue;
|
|
121
|
+
let content;
|
|
122
|
+
try {
|
|
123
|
+
content = readFileSync(absPath, "utf-8");
|
|
124
|
+
}
|
|
125
|
+
catch {
|
|
126
|
+
continue; // Skip unreadable files
|
|
127
|
+
}
|
|
128
|
+
const rules = await localGraph.getRules(filePath);
|
|
129
|
+
if (rules.length === 0)
|
|
130
|
+
continue;
|
|
131
|
+
filesChecked++;
|
|
132
|
+
totalRulesEvaluated += rules.length;
|
|
133
|
+
try {
|
|
134
|
+
const result = await evaluateRules(rules, filePath, content, localGraph);
|
|
135
|
+
if (result.violations.length > 0) {
|
|
136
|
+
allFileViolations.push({
|
|
137
|
+
filePath,
|
|
138
|
+
violations: result.violations,
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
catch (err) {
|
|
143
|
+
logInfo(`check-commit: rule evaluation failed for ${filePath}`, err);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
const totalViolations = allFileViolations.reduce((sum, fv) => sum + fv.violations.length, 0);
|
|
147
|
+
// ── Display results ──────────────────────────────────────────
|
|
148
|
+
section("unerr pre-commit check");
|
|
149
|
+
if (totalViolations === 0) {
|
|
150
|
+
success(`${filesChecked} file${filesChecked !== 1 ? "s" : ""} checked, ${totalRulesEvaluated} rules evaluated — all clear`);
|
|
151
|
+
process.exitCode = 0;
|
|
152
|
+
return;
|
|
153
|
+
}
|
|
154
|
+
// Display violations grouped by file
|
|
155
|
+
for (const fv of allFileViolations) {
|
|
156
|
+
fail(`${fv.filePath}`);
|
|
157
|
+
for (const v of fv.violations) {
|
|
158
|
+
const location = v.line ? `:${v.line}` : "";
|
|
159
|
+
const severityColor = v.severity === "error"
|
|
160
|
+
? pc.red
|
|
161
|
+
: v.severity === "warning"
|
|
162
|
+
? pc.yellow
|
|
163
|
+
: pc.dim;
|
|
164
|
+
info(`${severityColor(`[${v.severity}]`)} ${v.message}${location ? pc.dim(` (line ${v.line})`) : ""}`);
|
|
165
|
+
if (v.matchedCode && opts.verbose) {
|
|
166
|
+
detail(` → ${v.matchedCode.slice(0, 80)}`);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
// Summary line
|
|
171
|
+
const errorCount = allFileViolations.reduce((sum, fv) => sum + fv.violations.filter((v) => v.severity === "error").length, 0);
|
|
172
|
+
const warningCount = totalViolations - errorCount;
|
|
173
|
+
const errorSuffix = errorCount > 0
|
|
174
|
+
? ` (${errorCount} error${errorCount !== 1 ? "s" : ""})`
|
|
175
|
+
: "";
|
|
176
|
+
const warnSuffix = warningCount > 0
|
|
177
|
+
? ` (${warningCount} warning${warningCount !== 1 ? "s" : ""})`
|
|
178
|
+
: "";
|
|
179
|
+
warn(`${totalViolations} violation${totalViolations !== 1 ? "s" : ""} found${errorSuffix}${warnSuffix}`);
|
|
180
|
+
if (blockingMode) {
|
|
181
|
+
fail("Commit blocked — fix violations or use --no-verify to bypass");
|
|
182
|
+
process.exitCode = 1;
|
|
183
|
+
}
|
|
184
|
+
else {
|
|
185
|
+
detail("Non-blocking mode — commit will proceed");
|
|
186
|
+
detail("Enable blocking: set hooks.precommit.blocking=true in .unerr/settings.json");
|
|
187
|
+
process.exitCode = 0;
|
|
188
|
+
}
|
|
189
|
+
});
|
|
190
|
+
}
|
|
191
|
+
// ── Graph Loading ────────────────────────────────────────────────────
|
|
192
|
+
/**
|
|
193
|
+
* Load CozoDB graph for standalone check-commit (proxy may not be running).
|
|
194
|
+
* Returns null if no snapshot available.
|
|
195
|
+
*/
|
|
196
|
+
async function loadGraphForCheckCommit(repoId, snapshotsDir, manifestsDir) {
|
|
197
|
+
// Check manifest exists
|
|
198
|
+
const manifestPath = join(manifestsDir, `${repoId}.json`);
|
|
199
|
+
if (!existsSync(manifestPath))
|
|
200
|
+
return null;
|
|
201
|
+
// Find snapshot file
|
|
202
|
+
let snapshotPath = join(snapshotsDir, `${repoId}.msgpack.gz`);
|
|
203
|
+
if (!existsSync(snapshotPath)) {
|
|
204
|
+
snapshotPath = join(snapshotsDir, `${repoId}.msgpack`);
|
|
205
|
+
}
|
|
206
|
+
if (!existsSync(snapshotPath))
|
|
207
|
+
return null;
|
|
208
|
+
try {
|
|
209
|
+
// Dynamic imports to keep cold start fast when no check needed
|
|
210
|
+
const { default: CozoDbConstructor } = await import("cozo-node");
|
|
211
|
+
const { CozoGraphStore } = await import("../intelligence/local-graph.js");
|
|
212
|
+
const { unpack } = await import("msgpackr");
|
|
213
|
+
const db = new CozoDbConstructor();
|
|
214
|
+
const localGraph = await CozoGraphStore.create(db);
|
|
215
|
+
const raw = readFileSync(snapshotPath);
|
|
216
|
+
const buffer = snapshotPath.endsWith(".gz") ? gunzipSync(raw) : raw;
|
|
217
|
+
const envelope = unpack(buffer);
|
|
218
|
+
await localGraph.loadSnapshot(envelope);
|
|
219
|
+
return localGraph;
|
|
220
|
+
}
|
|
221
|
+
catch (err) {
|
|
222
|
+
logInfo("check-commit: failed to load graph", err);
|
|
223
|
+
return null;
|
|
224
|
+
}
|
|
225
|
+
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `unerr compress-output` — stdin→stdout compression for CLI hooks.
|
|
3
|
+
*
|
|
4
|
+
* S6.4: Reads text from stdin, compresses with the output compressor,
|
|
5
|
+
* writes compressed output to stdout. When graph is available, passes
|
|
6
|
+
* entity risk map for graph-aware prioritization.
|
|
7
|
+
*
|
|
8
|
+
* Usage (in hooks): echo "$OUTPUT" | unerr compress-output
|
|
9
|
+
*/
|
|
10
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
11
|
+
import { join } from "node:path";
|
|
12
|
+
import { compressOutput, } from "../proxy/output-compressor.js";
|
|
13
|
+
/**
|
|
14
|
+
* Load entity risk map from the local graph state if available.
|
|
15
|
+
* Returns empty map if graph is not initialized.
|
|
16
|
+
*/
|
|
17
|
+
function loadEntityRiskMap(cwd) {
|
|
18
|
+
const riskMap = new Map();
|
|
19
|
+
try {
|
|
20
|
+
const unerrDir = join(cwd, ".unerr");
|
|
21
|
+
const configPath = join(unerrDir, "config.json");
|
|
22
|
+
if (!existsSync(configPath))
|
|
23
|
+
return riskMap;
|
|
24
|
+
const config = JSON.parse(readFileSync(configPath, "utf-8"));
|
|
25
|
+
if (!config.repoId)
|
|
26
|
+
return riskMap;
|
|
27
|
+
const riskCachePath = join(unerrDir, "state", "entity_risk_cache.json");
|
|
28
|
+
if (!existsSync(riskCachePath))
|
|
29
|
+
return riskMap;
|
|
30
|
+
const data = JSON.parse(readFileSync(riskCachePath, "utf-8"));
|
|
31
|
+
for (const [key, info] of Object.entries(data)) {
|
|
32
|
+
riskMap.set(key, info);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
catch {
|
|
36
|
+
// Risk map loading is best-effort — compression works without it
|
|
37
|
+
}
|
|
38
|
+
return riskMap;
|
|
39
|
+
}
|
|
40
|
+
export function registerCompressOutputCommand(program) {
|
|
41
|
+
program
|
|
42
|
+
.command("compress-output")
|
|
43
|
+
.description("Compress text from stdin using graph-aware compression (for hooks)")
|
|
44
|
+
.option("--budget <tokens>", "Token budget", "2000")
|
|
45
|
+
.option("--no-graph", "Skip loading graph risk map")
|
|
46
|
+
.action(async (opts) => {
|
|
47
|
+
const budget = Number.parseInt(opts.budget, 10) || 2000;
|
|
48
|
+
let input = "";
|
|
49
|
+
for await (const chunk of process.stdin) {
|
|
50
|
+
input += chunk;
|
|
51
|
+
}
|
|
52
|
+
if (input.length === 0) {
|
|
53
|
+
process.exit(0);
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
// S6.4: Load entity risk map from graph when available
|
|
57
|
+
const entityRiskMap = opts.graph !== false ? loadEntityRiskMap(process.cwd()) : undefined;
|
|
58
|
+
const result = compressOutput(input, {
|
|
59
|
+
tokenBudget: budget,
|
|
60
|
+
entityRiskMap: entityRiskMap && entityRiskMap.size > 0 ? entityRiskMap : undefined,
|
|
61
|
+
});
|
|
62
|
+
process.stdout.write(result.output);
|
|
63
|
+
});
|
|
64
|
+
}
|
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* unerr config verify — P5.6-ADV-04: Self-healing MCP configuration.
|
|
3
|
+
* Checks and repairs MCP config for supported IDEs (VS Code, Cursor, etc.)
|
|
4
|
+
*/
|
|
5
|
+
import * as fs from "node:fs";
|
|
6
|
+
import * as os from "node:os";
|
|
7
|
+
import * as path from "node:path";
|
|
8
|
+
const IDE_CONFIG_PATHS = {
|
|
9
|
+
vscode: path.join(os.homedir(), ".vscode", "settings.json"),
|
|
10
|
+
cursor: path.join(os.homedir(), ".cursor", "mcp.json"),
|
|
11
|
+
windsurf: path.join(os.homedir(), ".windsurf", "mcp.json"),
|
|
12
|
+
"claude-code": path.join(os.homedir(), ".claude", "claude_desktop_config.json"),
|
|
13
|
+
};
|
|
14
|
+
function loadConfig() {
|
|
15
|
+
const configPath = path.join(process.cwd(), ".unerr", "config.json");
|
|
16
|
+
if (!fs.existsSync(configPath))
|
|
17
|
+
return null;
|
|
18
|
+
return JSON.parse(fs.readFileSync(configPath, "utf-8"));
|
|
19
|
+
}
|
|
20
|
+
export function checkIdeConfig(ideName, configPath) {
|
|
21
|
+
const issues = [];
|
|
22
|
+
if (!fs.existsSync(configPath)) {
|
|
23
|
+
return {
|
|
24
|
+
found: false,
|
|
25
|
+
configured: false,
|
|
26
|
+
issues: [`${ideName} config not found at ${configPath}`],
|
|
27
|
+
needsMigration: false,
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
try {
|
|
31
|
+
const raw = fs.readFileSync(configPath, "utf-8");
|
|
32
|
+
const config = JSON.parse(raw);
|
|
33
|
+
if (!config.mcpServers) {
|
|
34
|
+
issues.push(`${ideName}: No mcpServers section found`);
|
|
35
|
+
return { found: true, configured: false, issues, needsMigration: false };
|
|
36
|
+
}
|
|
37
|
+
const unerrServer = config.mcpServers.unerr;
|
|
38
|
+
if (!unerrServer) {
|
|
39
|
+
issues.push(`${ideName}: No unerr MCP server configured`);
|
|
40
|
+
return { found: true, configured: false, issues, needsMigration: false };
|
|
41
|
+
}
|
|
42
|
+
// Check if still pointing to remote URL (needs migration to local proxy)
|
|
43
|
+
if (unerrServer.url && !unerrServer.command) {
|
|
44
|
+
issues.push(`${ideName}: unerr MCP config points to remote URL — should use local proxy`);
|
|
45
|
+
return { found: true, configured: true, issues, needsMigration: true };
|
|
46
|
+
}
|
|
47
|
+
// Check if using local proxy correctly (direct binary or npx)
|
|
48
|
+
if (unerrServer.command === "unerr" &&
|
|
49
|
+
unerrServer.args?.includes("--mcp")) {
|
|
50
|
+
return { found: true, configured: true, issues, needsMigration: false };
|
|
51
|
+
}
|
|
52
|
+
// Legacy: npx @unerr/unerr format (needs migration to direct binary)
|
|
53
|
+
if (unerrServer.command === "npx" &&
|
|
54
|
+
(unerrServer.args?.includes("@unerr/unerr") ||
|
|
55
|
+
unerrServer.args?.includes("@unerr/unerr-mcp"))) {
|
|
56
|
+
issues.push(`${ideName}: using npx with unpublished package — should use direct 'unerr' binary`);
|
|
57
|
+
return { found: true, configured: true, issues, needsMigration: true };
|
|
58
|
+
}
|
|
59
|
+
issues.push(`${ideName}: unerr MCP config has unexpected format`);
|
|
60
|
+
return { found: true, configured: true, issues, needsMigration: true };
|
|
61
|
+
}
|
|
62
|
+
catch {
|
|
63
|
+
issues.push(`${ideName}: Failed to parse config at ${configPath}`);
|
|
64
|
+
return { found: true, configured: false, issues, needsMigration: false };
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
export function repairIdeConfig(ideName, configPath, mode = "proxy") {
|
|
68
|
+
try {
|
|
69
|
+
const dir = path.dirname(configPath);
|
|
70
|
+
if (!fs.existsSync(dir)) {
|
|
71
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
72
|
+
}
|
|
73
|
+
let config = {};
|
|
74
|
+
if (fs.existsSync(configPath)) {
|
|
75
|
+
const raw = fs.readFileSync(configPath, "utf-8");
|
|
76
|
+
config = JSON.parse(raw);
|
|
77
|
+
}
|
|
78
|
+
if (!config.mcpServers)
|
|
79
|
+
config.mcpServers = {};
|
|
80
|
+
if (mode === "standalone") {
|
|
81
|
+
// Sprint 5.4: Standalone read-only MCP server
|
|
82
|
+
const graphPath = resolveGraphPath();
|
|
83
|
+
config.mcpServers.unerr = {
|
|
84
|
+
command: "unerr",
|
|
85
|
+
args: ["--mcp"],
|
|
86
|
+
env: graphPath ? { UNERR_GRAPH_PATH: graphPath } : {},
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
else {
|
|
90
|
+
// Local proxy — direct binary
|
|
91
|
+
config.mcpServers.unerr = {
|
|
92
|
+
command: "unerr",
|
|
93
|
+
args: ["--mcp"],
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
fs.writeFileSync(configPath, `${JSON.stringify(config, null, 2)}\n`);
|
|
97
|
+
return true;
|
|
98
|
+
}
|
|
99
|
+
catch {
|
|
100
|
+
return false;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Sprint 5.4: Resolve the graph snapshot path.
|
|
105
|
+
* Looks in the repo's .unerr/snapshots/ directory.
|
|
106
|
+
*/
|
|
107
|
+
function resolveGraphPath() {
|
|
108
|
+
const snapshotsDir = path.join(process.cwd(), ".unerr", "snapshots");
|
|
109
|
+
if (!fs.existsSync(snapshotsDir))
|
|
110
|
+
return null;
|
|
111
|
+
const files = fs
|
|
112
|
+
.readdirSync(snapshotsDir)
|
|
113
|
+
.filter((f) => f.endsWith(".msgpack.gz") || f.endsWith(".msgpack"))
|
|
114
|
+
.map((f) => ({
|
|
115
|
+
name: f,
|
|
116
|
+
path: path.join(snapshotsDir, f),
|
|
117
|
+
mtime: fs.statSync(path.join(snapshotsDir, f)).mtimeMs,
|
|
118
|
+
}))
|
|
119
|
+
.sort((a, b) => b.mtime - a.mtime);
|
|
120
|
+
return files[0]?.path ?? null;
|
|
121
|
+
}
|
|
122
|
+
export function registerConfigVerifyCommand(program) {
|
|
123
|
+
const configCmd = program
|
|
124
|
+
.command("config")
|
|
125
|
+
.description("Manage unerr configuration");
|
|
126
|
+
configCmd
|
|
127
|
+
.command("verify")
|
|
128
|
+
.description("Check and optionally repair MCP configuration for IDEs")
|
|
129
|
+
.option("--silent", "Only output errors")
|
|
130
|
+
.option("--repair", "Automatically repair misconfigured IDEs")
|
|
131
|
+
.option("--ide <ide>", "Check specific IDE (vscode, cursor, windsurf, claude-code)")
|
|
132
|
+
.option("--mode <mode>", "Server mode: proxy (full) or standalone (read-only)", "proxy")
|
|
133
|
+
.action(async (opts) => {
|
|
134
|
+
const idesToCheck = opts.ide
|
|
135
|
+
? { [opts.ide]: IDE_CONFIG_PATHS[opts.ide] ?? "" }
|
|
136
|
+
: IDE_CONFIG_PATHS;
|
|
137
|
+
let allGood = true;
|
|
138
|
+
for (const [ideName, configPath] of Object.entries(idesToCheck)) {
|
|
139
|
+
if (!configPath) {
|
|
140
|
+
if (!opts.silent)
|
|
141
|
+
console.log(` Unknown IDE: ${ideName}`);
|
|
142
|
+
continue;
|
|
143
|
+
}
|
|
144
|
+
const result = checkIdeConfig(ideName, configPath);
|
|
145
|
+
if (result.configured && result.issues.length === 0) {
|
|
146
|
+
if (!opts.silent)
|
|
147
|
+
console.log(` ✓ ${ideName}: configured correctly`);
|
|
148
|
+
}
|
|
149
|
+
else {
|
|
150
|
+
allGood = false;
|
|
151
|
+
for (const issue of result.issues) {
|
|
152
|
+
console.log(` ✗ ${issue}`);
|
|
153
|
+
}
|
|
154
|
+
if (opts.repair) {
|
|
155
|
+
const serverMode = (opts.mode === "standalone" ? "standalone" : "proxy");
|
|
156
|
+
const repaired = repairIdeConfig(ideName, configPath, serverMode);
|
|
157
|
+
if (repaired) {
|
|
158
|
+
console.log(` ✓ ${ideName}: repaired`);
|
|
159
|
+
}
|
|
160
|
+
else {
|
|
161
|
+
console.log(` ✗ ${ideName}: repair failed`);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
if (!allGood && !opts.repair) {
|
|
167
|
+
console.log("\n Run with --repair to fix issues automatically.");
|
|
168
|
+
}
|
|
169
|
+
if (allGood && !opts.silent) {
|
|
170
|
+
console.log("\n All IDE configurations look good!");
|
|
171
|
+
}
|
|
172
|
+
});
|
|
173
|
+
// Show MCP config for manual copy-paste
|
|
174
|
+
configCmd
|
|
175
|
+
.command("show")
|
|
176
|
+
.description("Show MCP config snippet for an agent (for manual setup)")
|
|
177
|
+
.argument("[agent]", "Agent name (e.g. cursor, claude-code, kiro) or 'all'")
|
|
178
|
+
.action(async (agent) => {
|
|
179
|
+
const { generateConfigSnippet, getConfigInfo } = await import("../config/mcp-config-writer.js");
|
|
180
|
+
const { AGENT_REGISTRY } = await import("../config/agent-registry.js");
|
|
181
|
+
const { ideDisplayName } = await import("../utils/detect.js");
|
|
182
|
+
if (!agent || agent === "all") {
|
|
183
|
+
console.log("\n Supported agents and their MCP config paths:\n");
|
|
184
|
+
for (const a of AGENT_REGISTRY) {
|
|
185
|
+
console.log(` ${a.name.padEnd(22)} ${a.projectConfigPath}`);
|
|
186
|
+
}
|
|
187
|
+
console.log("\n Usage: unerr install <agent>\n Example: unerr install kiro\n");
|
|
188
|
+
return;
|
|
189
|
+
}
|
|
190
|
+
const agentDef = AGENT_REGISTRY.find((a) => a.id === agent || a.name.toLowerCase() === agent.toLowerCase());
|
|
191
|
+
if (!agentDef) {
|
|
192
|
+
console.error(` Unknown agent: ${agent}\n Available: ${AGENT_REGISTRY.map((a) => a.id).join(", ")}`);
|
|
193
|
+
process.exit(1);
|
|
194
|
+
}
|
|
195
|
+
const info = getConfigInfo(agentDef.id);
|
|
196
|
+
const snippet = generateConfigSnippet(agentDef.id);
|
|
197
|
+
console.log(`\n ${agentDef.name} — ${agentDef.description}`);
|
|
198
|
+
console.log(` Config path: ${info?.path}\n`);
|
|
199
|
+
console.log(" Add this to your config:\n");
|
|
200
|
+
console.log(snippet
|
|
201
|
+
.split("\n")
|
|
202
|
+
.map((l) => ` ${l}`)
|
|
203
|
+
.join("\n"));
|
|
204
|
+
console.log("");
|
|
205
|
+
});
|
|
206
|
+
// Git hooks sub-command
|
|
207
|
+
configCmd
|
|
208
|
+
.command("install-hooks")
|
|
209
|
+
.description("Install git hooks for automatic MCP config verification")
|
|
210
|
+
.action(async () => {
|
|
211
|
+
const gitDir = path.join(process.cwd(), ".git");
|
|
212
|
+
if (!fs.existsSync(gitDir)) {
|
|
213
|
+
console.error("Not a git repository");
|
|
214
|
+
process.exit(1);
|
|
215
|
+
}
|
|
216
|
+
const hooksDir = path.join(gitDir, "hooks");
|
|
217
|
+
if (!fs.existsSync(hooksDir)) {
|
|
218
|
+
fs.mkdirSync(hooksDir, { recursive: true });
|
|
219
|
+
}
|
|
220
|
+
const hookScript = `#!/bin/sh
|
|
221
|
+
# unerr auto-verify MCP config
|
|
222
|
+
if command -v unerr &> /dev/null; then
|
|
223
|
+
unerr config verify --silent 2>/dev/null || true
|
|
224
|
+
fi
|
|
225
|
+
`;
|
|
226
|
+
for (const hookName of ["post-checkout", "post-merge"]) {
|
|
227
|
+
const hookPath = path.join(hooksDir, hookName);
|
|
228
|
+
if (fs.existsSync(hookPath)) {
|
|
229
|
+
const existing = fs.readFileSync(hookPath, "utf-8");
|
|
230
|
+
if (existing.includes("unerr config verify")) {
|
|
231
|
+
console.log(` ✓ ${hookName}: already installed`);
|
|
232
|
+
continue;
|
|
233
|
+
}
|
|
234
|
+
fs.appendFileSync(hookPath, `\n${hookScript}`);
|
|
235
|
+
}
|
|
236
|
+
else {
|
|
237
|
+
fs.writeFileSync(hookPath, hookScript);
|
|
238
|
+
fs.chmodSync(hookPath, "755");
|
|
239
|
+
}
|
|
240
|
+
console.log(` ✓ ${hookName}: installed`);
|
|
241
|
+
}
|
|
242
|
+
});
|
|
243
|
+
}
|