@monoes/monomindcli 1.10.56 → 1.11.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/.claude/agents/core/coordinator.md +71 -0
- package/.claude/agents/generated/case-analyst.md +50 -0
- package/.claude/agents/generated/copy-editor.md +45 -0
- package/.claude/agents/generated/court-reporter.md +50 -0
- package/.claude/agents/generated/defender.md +51 -0
- package/.claude/agents/generated/editor-in-chief.md +45 -0
- package/.claude/agents/generated/fact-checker.md +45 -0
- package/.claude/agents/generated/judge.md +51 -0
- package/.claude/agents/generated/prosecutor.md +51 -0
- package/.claude/agents/generated/reporter.md +45 -0
- package/.claude/commands/hooks/README.md +1 -1
- package/.claude/commands/hooks/overview.md +1 -1
- package/.claude/commands/mastermind/_repeat.md +1 -1
- package/.claude/commands/mastermind/do.md +3 -1
- package/.claude/commands/mastermind/help.md +2 -2
- package/.claude/commands/mastermind/master.md +39 -6
- package/.claude/commands/mastermind/memory.md +1 -1
- package/.claude/commands/memory/memory-search.md +2 -2
- package/.claude/commands/monitoring/status.md +1 -1
- package/.claude/commands/{browse.md → monobrowse.md} +2 -2
- package/.claude/commands/sparc.md +1 -1
- package/.claude/helpers/handlers/graph-status-handler.cjs +1 -1
- package/.claude/helpers/loop-tracker.cjs +1 -1
- package/.claude/skills/agent-browser-testing/SKILL.md +1 -1
- package/.claude/skills/hooks-automation/SKILL.md +0 -3
- package/.claude/skills/mastermind/build.md +1 -1
- package/.claude/skills/mastermind/code-quality-reviewer-prompt.md +60 -0
- package/.claude/skills/mastermind/content.md +1 -1
- package/.claude/skills/mastermind/createorg.md +79 -2
- package/.claude/skills/mastermind/design.md +3 -1
- package/.claude/skills/mastermind/finance.md +1 -1
- package/.claude/skills/mastermind/implementer-prompt.md +109 -0
- package/.claude/skills/mastermind/marketing.md +1 -1
- package/.claude/skills/mastermind/ops.md +1 -1
- package/.claude/skills/mastermind/plan.md +20 -2
- package/.claude/skills/mastermind/release.md +1 -1
- package/.claude/skills/mastermind/research.md +1 -1
- package/.claude/skills/mastermind/review.md +1 -1
- package/.claude/skills/mastermind/sales.md +1 -1
- package/.claude/skills/mastermind/spec-reviewer-prompt.md +63 -0
- package/.claude/skills/sparc-methodology/SKILL.md +3 -3
- package/.claude/skills/swarm-advanced/SKILL.md +1 -4
- package/README.md +18 -32
- package/dist/src/agents/registry-builder.d.ts +1 -7
- package/dist/src/agents/registry-builder.d.ts.map +1 -1
- package/dist/src/agents/registry-builder.js +10 -6
- package/dist/src/agents/registry-builder.js.map +1 -1
- package/dist/src/benchmarks/benchmark-runner.d.ts +59 -12
- package/dist/src/benchmarks/benchmark-runner.d.ts.map +1 -1
- package/dist/src/benchmarks/benchmark-runner.js +67 -13
- package/dist/src/benchmarks/benchmark-runner.js.map +1 -1
- package/dist/src/benchmarks/metric-evaluators.d.ts.map +1 -1
- package/dist/src/benchmarks/metric-evaluators.js.map +1 -1
- package/dist/src/benchmarks/pretrain/index.d.ts +0 -13
- package/dist/src/benchmarks/pretrain/index.d.ts.map +1 -1
- package/dist/src/benchmarks/pretrain/index.js.map +1 -1
- package/dist/src/commands/agent-wasm.d.ts +2 -2
- package/dist/src/commands/agent-wasm.js +5 -5
- package/dist/src/commands/agent.d.ts.map +1 -1
- package/dist/src/commands/agent.js +1 -6
- package/dist/src/commands/agent.js.map +1 -1
- package/dist/src/commands/analyze.d.ts +1 -1
- package/dist/src/commands/analyze.d.ts.map +1 -1
- package/dist/src/commands/analyze.js +8 -18
- package/dist/src/commands/analyze.js.map +1 -1
- package/dist/src/commands/doctor.d.ts.map +1 -1
- package/dist/src/commands/doctor.js +53 -3
- package/dist/src/commands/doctor.js.map +1 -1
- package/dist/src/commands/embeddings.d.ts.map +1 -1
- package/dist/src/commands/embeddings.js +9 -33
- package/dist/src/commands/embeddings.js.map +1 -1
- package/dist/src/commands/hooks.d.ts.map +1 -1
- package/dist/src/commands/hooks.js +24 -76
- package/dist/src/commands/hooks.js.map +1 -1
- package/dist/src/commands/index.d.ts +4 -6
- package/dist/src/commands/index.d.ts.map +1 -1
- package/dist/src/commands/index.js +8 -15
- package/dist/src/commands/index.js.map +1 -1
- package/dist/src/commands/init.js +2 -2
- package/dist/src/commands/init.js.map +1 -1
- package/dist/src/commands/issues.d.ts.map +1 -1
- package/dist/src/commands/issues.js +16 -11
- package/dist/src/commands/issues.js.map +1 -1
- package/dist/src/commands/mcp.d.ts +1 -1
- package/dist/src/commands/memory.js +6 -6
- package/dist/src/commands/memory.js.map +1 -1
- package/dist/src/commands/migrate.d.ts.map +1 -1
- package/dist/src/commands/migrate.js +1 -2
- package/dist/src/commands/migrate.js.map +1 -1
- package/dist/src/commands/monograph.d.ts.map +1 -1
- package/dist/src/commands/monograph.js +18 -11
- package/dist/src/commands/monograph.js.map +1 -1
- package/dist/src/commands/monovector/backup.d.ts +11 -0
- package/dist/src/commands/monovector/backup.d.ts.map +1 -0
- package/dist/src/commands/{ruvector → monovector}/backup.js +25 -25
- package/dist/src/commands/monovector/backup.js.map +1 -0
- package/dist/src/commands/monovector/benchmark.d.ts +11 -0
- package/dist/src/commands/monovector/benchmark.d.ts.map +1 -0
- package/dist/src/commands/{ruvector → monovector}/benchmark.js +14 -14
- package/dist/src/commands/monovector/benchmark.js.map +1 -0
- package/dist/src/commands/monovector/import.d.ts +18 -0
- package/dist/src/commands/monovector/import.d.ts.map +1 -0
- package/dist/src/commands/{ruvector → monovector}/import.js +21 -21
- package/dist/src/commands/monovector/import.js.map +1 -0
- package/dist/src/commands/{ruvector → monovector}/index.d.ts +6 -6
- package/dist/src/commands/monovector/index.d.ts.map +1 -0
- package/dist/src/commands/{ruvector → monovector}/index.js +22 -22
- package/dist/src/commands/monovector/index.js.map +1 -0
- package/dist/src/commands/monovector/init.d.ts +11 -0
- package/dist/src/commands/monovector/init.d.ts.map +1 -0
- package/dist/src/commands/{ruvector → monovector}/init.js +36 -36
- package/dist/src/commands/monovector/init.js.map +1 -0
- package/dist/src/commands/monovector/migrate.d.ts +11 -0
- package/dist/src/commands/monovector/migrate.d.ts.map +1 -0
- package/dist/src/commands/{ruvector → monovector}/migrate.js +16 -16
- package/dist/src/commands/monovector/migrate.js.map +1 -0
- package/dist/src/commands/{ruvector → monovector}/optimize.d.ts +2 -2
- package/dist/src/commands/monovector/optimize.d.ts.map +1 -0
- package/dist/src/commands/{ruvector → monovector}/optimize.js +10 -10
- package/dist/src/commands/monovector/optimize.js.map +1 -0
- package/dist/src/commands/monovector/setup.d.ts +18 -0
- package/dist/src/commands/monovector/setup.d.ts.map +1 -0
- package/dist/src/commands/{ruvector → monovector}/setup.js +77 -77
- package/dist/src/commands/monovector/setup.js.map +1 -0
- package/dist/src/commands/{ruvector → monovector}/status.d.ts +2 -2
- package/dist/src/commands/monovector/status.d.ts.map +1 -0
- package/dist/src/commands/{ruvector → monovector}/status.js +34 -34
- package/dist/src/commands/monovector/status.js.map +1 -0
- package/dist/src/commands/neural.d.ts +1 -1
- package/dist/src/commands/neural.d.ts.map +1 -1
- package/dist/src/commands/neural.js +31 -608
- package/dist/src/commands/neural.js.map +1 -1
- package/dist/src/commands/performance.d.ts.map +1 -1
- package/dist/src/commands/performance.js +7 -10
- package/dist/src/commands/performance.js.map +1 -1
- package/dist/src/commands/plugins.d.ts.map +1 -1
- package/dist/src/commands/plugins.js +3 -4
- package/dist/src/commands/plugins.js.map +1 -1
- package/dist/src/commands/process.d.ts.map +1 -1
- package/dist/src/commands/process.js +5 -12
- package/dist/src/commands/process.js.map +1 -1
- package/dist/src/commands/progress.d.ts.map +1 -1
- package/dist/src/commands/progress.js +16 -16
- package/dist/src/commands/progress.js.map +1 -1
- package/dist/src/commands/replay.d.ts.map +1 -1
- package/dist/src/commands/replay.js.map +1 -1
- package/dist/src/commands/route.d.ts +2 -2
- package/dist/src/commands/route.js +23 -23
- package/dist/src/commands/route.js.map +1 -1
- package/dist/src/commands/status.d.ts.map +1 -1
- package/dist/src/commands/status.js +0 -3
- package/dist/src/commands/status.js.map +1 -1
- package/dist/src/commands/swarm.d.ts.map +1 -1
- package/dist/src/commands/swarm.js +2 -3
- package/dist/src/commands/swarm.js.map +1 -1
- package/dist/src/commands/update.d.ts +1 -1
- package/dist/src/config-adapter.d.ts.map +1 -1
- package/dist/src/config-adapter.js +27 -0
- package/dist/src/config-adapter.js.map +1 -1
- package/dist/src/consensus/audit-writer.d.ts +44 -17
- package/dist/src/consensus/audit-writer.d.ts.map +1 -1
- package/dist/src/consensus/audit-writer.js.map +1 -1
- package/dist/src/dlq/dlq-replayer.d.ts +1 -1
- package/dist/src/dlq/dlq-replayer.d.ts.map +1 -1
- package/dist/src/index.d.ts +1 -1
- package/dist/src/index.js +5 -5
- package/dist/src/index.js.map +1 -1
- package/dist/src/init/claudemd-generator.d.ts.map +1 -1
- package/dist/src/init/claudemd-generator.js +10 -14
- package/dist/src/init/claudemd-generator.js.map +1 -1
- package/dist/src/init/executor.d.ts.map +1 -1
- package/dist/src/init/executor.js +17 -27
- package/dist/src/init/executor.js.map +1 -1
- package/dist/src/init/helpers-generator.d.ts +1 -1
- package/dist/src/init/helpers-generator.js +2 -2
- package/dist/src/init/types.d.ts +1 -1
- package/dist/src/init/types.d.ts.map +1 -1
- package/dist/src/mcp-client.d.ts.map +1 -1
- package/dist/src/mcp-client.js +1 -7
- package/dist/src/mcp-client.js.map +1 -1
- package/dist/src/mcp-server.d.ts.map +1 -1
- package/dist/src/mcp-server.js +9 -1
- package/dist/src/mcp-server.js.map +1 -1
- package/dist/src/mcp-tools/agent-tools.d.ts.map +1 -1
- package/dist/src/mcp-tools/agent-tools.js +1 -52
- package/dist/src/mcp-tools/agent-tools.js.map +1 -1
- package/dist/src/mcp-tools/analyze-tools.js +5 -5
- package/dist/src/mcp-tools/analyze-tools.js.map +1 -1
- package/dist/src/mcp-tools/auto-install.d.ts +4 -4
- package/dist/src/mcp-tools/autopilot-tools.d.ts +1 -1
- package/dist/src/mcp-tools/browser-tools.d.ts +1 -1
- package/dist/src/mcp-tools/browser-tools.d.ts.map +1 -1
- package/dist/src/mcp-tools/browser-tools.js +6 -5
- package/dist/src/mcp-tools/browser-tools.js.map +1 -1
- package/dist/src/mcp-tools/claims-tools.d.ts +1 -1
- package/dist/src/mcp-tools/coordination-tools.d.ts +1 -1
- package/dist/src/mcp-tools/coordination-tools.d.ts.map +1 -1
- package/dist/src/mcp-tools/coordination-tools.js +51 -54
- package/dist/src/mcp-tools/coordination-tools.js.map +1 -1
- package/dist/src/mcp-tools/daa-tools.d.ts +1 -1
- package/dist/src/mcp-tools/daa-tools.d.ts.map +1 -1
- package/dist/src/mcp-tools/daa-tools.js.map +1 -1
- package/dist/src/mcp-tools/embeddings-tools.js +10 -10
- package/dist/src/mcp-tools/embeddings-tools.js.map +1 -1
- package/dist/src/mcp-tools/guidance-tools.d.ts +1 -1
- package/dist/src/mcp-tools/guidance-tools.d.ts.map +1 -1
- package/dist/src/mcp-tools/guidance-tools.js +0 -24
- package/dist/src/mcp-tools/guidance-tools.js.map +1 -1
- package/dist/src/mcp-tools/hive-mind-tools.js.map +1 -1
- package/dist/src/mcp-tools/hooks-tools.d.ts.map +1 -1
- package/dist/src/mcp-tools/hooks-tools.js +189 -446
- package/dist/src/mcp-tools/hooks-tools.js.map +1 -1
- package/dist/src/mcp-tools/index.d.ts +0 -2
- package/dist/src/mcp-tools/index.d.ts.map +1 -1
- package/dist/src/mcp-tools/index.js +0 -2
- package/dist/src/mcp-tools/index.js.map +1 -1
- package/dist/src/mcp-tools/monograph-compat.d.ts +334 -0
- package/dist/src/mcp-tools/monograph-compat.d.ts.map +1 -0
- package/dist/src/mcp-tools/monograph-compat.js +1108 -0
- package/dist/src/mcp-tools/monograph-compat.js.map +1 -0
- package/dist/src/mcp-tools/monograph-tools.d.ts.map +1 -1
- package/dist/src/mcp-tools/monograph-tools.js +76 -34
- package/dist/src/mcp-tools/monograph-tools.js.map +1 -1
- package/dist/src/mcp-tools/neural-tools.d.ts +2 -2
- package/dist/src/mcp-tools/neural-tools.js +2 -2
- package/dist/src/mcp-tools/neural-tools.js.map +1 -1
- package/dist/src/mcp-tools/progress-tools.d.ts +1 -1
- package/dist/src/mcp-tools/ruvllm-tools.d.ts +2 -2
- package/dist/src/mcp-tools/ruvllm-tools.js +3 -3
- package/dist/src/mcp-tools/terminal-tools.d.ts +1 -1
- package/dist/src/mcp-tools/terminal-tools.d.ts.map +1 -1
- package/dist/src/mcp-tools/terminal-tools.js +29 -19
- package/dist/src/mcp-tools/terminal-tools.js.map +1 -1
- package/dist/src/mcp-tools/transfer-tools.d.ts +1 -1
- package/dist/src/mcp-tools/wasm-agent-tools.d.ts +1 -1
- package/dist/src/mcp-tools/wasm-agent-tools.js +2 -2
- package/dist/src/memory/intelligence.d.ts.map +1 -1
- package/dist/src/memory/intelligence.js +14 -8
- package/dist/src/memory/intelligence.js.map +1 -1
- package/dist/src/memory/memory-bridge.d.ts +17 -2
- package/dist/src/memory/memory-bridge.d.ts.map +1 -1
- package/dist/src/memory/memory-bridge.js +76 -23
- package/dist/src/memory/memory-bridge.js.map +1 -1
- package/dist/src/memory/memory-initializer.d.ts +2 -2
- package/dist/src/memory/memory-initializer.d.ts.map +1 -1
- package/dist/src/memory/memory-initializer.js +37 -39
- package/dist/src/memory/memory-initializer.js.map +1 -1
- package/dist/src/monovector/capabilities.d.ts +34 -0
- package/dist/src/monovector/capabilities.d.ts.map +1 -0
- package/dist/src/monovector/capabilities.js +37 -0
- package/dist/src/monovector/capabilities.js.map +1 -0
- package/dist/src/monovector/command-outcomes.d.ts +37 -0
- package/dist/src/monovector/command-outcomes.d.ts.map +1 -0
- package/dist/src/monovector/command-outcomes.js +87 -0
- package/dist/src/monovector/command-outcomes.js.map +1 -0
- package/dist/src/monovector/coverage-router.d.ts +103 -0
- package/dist/src/monovector/coverage-router.d.ts.map +1 -0
- package/dist/src/monovector/coverage-router.js +337 -0
- package/dist/src/monovector/coverage-router.js.map +1 -0
- package/dist/src/monovector/coverage-tools.d.ts +14 -0
- package/dist/src/monovector/coverage-tools.d.ts.map +1 -0
- package/dist/src/monovector/coverage-tools.js +112 -0
- package/dist/src/monovector/coverage-tools.js.map +1 -0
- package/dist/src/{ruvector → monovector}/diff-classifier.d.ts +2 -2
- package/dist/src/monovector/diff-classifier.d.ts.map +1 -0
- package/dist/src/monovector/diff-classifier.js.map +1 -0
- package/dist/src/monovector/index.d.ts +61 -0
- package/dist/src/monovector/index.d.ts.map +1 -0
- package/dist/src/monovector/index.js +67 -0
- package/dist/src/monovector/index.js.map +1 -0
- package/dist/src/monovector/init-state.d.ts +35 -0
- package/dist/src/monovector/init-state.d.ts.map +1 -0
- package/dist/src/monovector/init-state.js +36 -0
- package/dist/src/monovector/init-state.js.map +1 -0
- package/dist/src/monovector/route-outcomes.d.ts +55 -0
- package/dist/src/monovector/route-outcomes.d.ts.map +1 -0
- package/dist/src/monovector/route-outcomes.js +137 -0
- package/dist/src/monovector/route-outcomes.js.map +1 -0
- package/dist/src/parser.js +3 -3
- package/dist/src/parser.js.map +1 -1
- package/dist/src/plugins/store/discovery.d.ts.map +1 -1
- package/dist/src/plugins/store/discovery.js +0 -31
- package/dist/src/plugins/store/discovery.js.map +1 -1
- package/dist/src/production/circuit-breaker.d.ts +26 -6
- package/dist/src/production/circuit-breaker.d.ts.map +1 -1
- package/dist/src/production/circuit-breaker.js.map +1 -1
- package/dist/src/production/error-handler.d.ts +55 -30
- package/dist/src/production/error-handler.d.ts.map +1 -1
- package/dist/src/production/error-handler.js.map +1 -1
- package/dist/src/production/index.d.ts +3 -20
- package/dist/src/production/index.d.ts.map +1 -1
- package/dist/src/production/index.js +3 -15
- package/dist/src/production/index.js.map +1 -1
- package/dist/src/production/monitoring.d.ts +54 -34
- package/dist/src/production/monitoring.d.ts.map +1 -1
- package/dist/src/production/monitoring.js +12 -14
- package/dist/src/production/monitoring.js.map +1 -1
- package/dist/src/production/rate-limiter.d.ts +64 -19
- package/dist/src/production/rate-limiter.d.ts.map +1 -1
- package/dist/src/production/rate-limiter.js +5 -5
- package/dist/src/production/rate-limiter.js.map +1 -1
- package/dist/src/production/retry.d.ts.map +1 -1
- package/dist/src/production/retry.js +4 -2
- package/dist/src/production/retry.js.map +1 -1
- package/dist/src/runtime/headless.d.ts +3 -3
- package/dist/src/services/claim-service.d.ts +50 -59
- package/dist/src/services/claim-service.d.ts.map +1 -1
- package/dist/src/services/claim-service.js +83 -50
- package/dist/src/services/claim-service.js.map +1 -1
- package/dist/src/services/config-file-manager.d.ts.map +1 -1
- package/dist/src/services/config-file-manager.js +8 -1
- package/dist/src/services/config-file-manager.js.map +1 -1
- package/dist/src/services/worker-daemon.d.ts.map +1 -1
- package/dist/src/services/worker-daemon.js +4 -0
- package/dist/src/services/worker-daemon.js.map +1 -1
- package/dist/src/transfer/ipfs/upload.d.ts +1 -1
- package/dist/src/transfer/storage/gcs.d.ts +1 -1
- package/dist/src/types.d.ts +13 -0
- package/dist/src/types.d.ts.map +1 -1
- package/dist/src/types.js.map +1 -1
- package/dist/src/ui/collector.mjs +51 -11
- package/dist/src/ui/dashboard.html +313 -88
- package/dist/src/ui/server.mjs +163 -8
- package/dist/src/update/checker.d.ts +1 -1
- package/dist/src/update/index.d.ts +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +13 -13
- package/scripts/publish-registry.ts +0 -1
- package/.claude/commands/monomind/adr.md +0 -11
- package/.claude/commands/monomind/budget.md +0 -7
- package/.claude/commands/monomind/createtask.md +0 -277
- package/.claude/commands/monomind/do.md +0 -498
- package/.claude/commands/monomind/graph-status.md +0 -7
- package/.claude/commands/monomind/help.md +0 -118
- package/.claude/commands/monomind/idea.md +0 -273
- package/.claude/commands/monomind/improve.md +0 -352
- package/.claude/commands/monomind/loops.md +0 -7
- package/.claude/commands/monomind/memory.md +0 -230
- package/.claude/commands/monomind/repeat.md +0 -257
- package/.claude/commands/monomind/review.md +0 -317
- package/.claude/commands/monomind/specialagents.md +0 -125
- package/.claude/commands/monomind/swarm.md +0 -161
- package/.claude/commands/monomind/understand.md +0 -139
- package/.claude/commands/training/README.md +0 -39
- package/.claude/commands/training/neural-patterns.md +0 -73
- package/.claude/commands/training/neural-train.md +0 -79
- package/dist/src/commands/appliance-advanced.d.ts +0 -9
- package/dist/src/commands/appliance-advanced.d.ts.map +0 -1
- package/dist/src/commands/appliance-advanced.js +0 -238
- package/dist/src/commands/appliance-advanced.js.map +0 -1
- package/dist/src/commands/appliance.d.ts +0 -8
- package/dist/src/commands/appliance.d.ts.map +0 -1
- package/dist/src/commands/appliance.js +0 -406
- package/dist/src/commands/appliance.js.map +0 -1
- package/dist/src/commands/ruvector/backup.d.ts +0 -11
- package/dist/src/commands/ruvector/backup.d.ts.map +0 -1
- package/dist/src/commands/ruvector/backup.js.map +0 -1
- package/dist/src/commands/ruvector/benchmark.d.ts +0 -11
- package/dist/src/commands/ruvector/benchmark.d.ts.map +0 -1
- package/dist/src/commands/ruvector/benchmark.js.map +0 -1
- package/dist/src/commands/ruvector/import.d.ts +0 -18
- package/dist/src/commands/ruvector/import.d.ts.map +0 -1
- package/dist/src/commands/ruvector/import.js.map +0 -1
- package/dist/src/commands/ruvector/index.d.ts.map +0 -1
- package/dist/src/commands/ruvector/index.js.map +0 -1
- package/dist/src/commands/ruvector/init.d.ts +0 -11
- package/dist/src/commands/ruvector/init.d.ts.map +0 -1
- package/dist/src/commands/ruvector/init.js.map +0 -1
- package/dist/src/commands/ruvector/migrate.d.ts +0 -11
- package/dist/src/commands/ruvector/migrate.d.ts.map +0 -1
- package/dist/src/commands/ruvector/migrate.js.map +0 -1
- package/dist/src/commands/ruvector/optimize.d.ts.map +0 -1
- package/dist/src/commands/ruvector/optimize.js.map +0 -1
- package/dist/src/commands/ruvector/setup.d.ts +0 -18
- package/dist/src/commands/ruvector/setup.d.ts.map +0 -1
- package/dist/src/commands/ruvector/setup.js.map +0 -1
- package/dist/src/commands/ruvector/status.d.ts.map +0 -1
- package/dist/src/commands/ruvector/status.js.map +0 -1
- package/dist/src/ruvector/agent-wasm.d.ts +0 -182
- package/dist/src/ruvector/agent-wasm.d.ts.map +0 -1
- package/dist/src/ruvector/agent-wasm.js +0 -316
- package/dist/src/ruvector/agent-wasm.js.map +0 -1
- package/dist/src/ruvector/ast-analyzer.d.ts +0 -67
- package/dist/src/ruvector/ast-analyzer.d.ts.map +0 -1
- package/dist/src/ruvector/ast-analyzer.js +0 -277
- package/dist/src/ruvector/ast-analyzer.js.map +0 -1
- package/dist/src/ruvector/coverage-router.d.ts +0 -160
- package/dist/src/ruvector/coverage-router.d.ts.map +0 -1
- package/dist/src/ruvector/coverage-router.js +0 -539
- package/dist/src/ruvector/coverage-router.js.map +0 -1
- package/dist/src/ruvector/coverage-tools.d.ts +0 -33
- package/dist/src/ruvector/coverage-tools.d.ts.map +0 -1
- package/dist/src/ruvector/coverage-tools.js +0 -157
- package/dist/src/ruvector/coverage-tools.js.map +0 -1
- package/dist/src/ruvector/diff-classifier.d.ts.map +0 -1
- package/dist/src/ruvector/diff-classifier.js.map +0 -1
- package/dist/src/ruvector/enhanced-model-router.d.ts +0 -146
- package/dist/src/ruvector/enhanced-model-router.d.ts.map +0 -1
- package/dist/src/ruvector/enhanced-model-router.js +0 -551
- package/dist/src/ruvector/enhanced-model-router.js.map +0 -1
- package/dist/src/ruvector/flash-attention.d.ts +0 -195
- package/dist/src/ruvector/flash-attention.d.ts.map +0 -1
- package/dist/src/ruvector/flash-attention.js +0 -643
- package/dist/src/ruvector/flash-attention.js.map +0 -1
- package/dist/src/ruvector/graph-analyzer.d.ts +0 -187
- package/dist/src/ruvector/graph-analyzer.d.ts.map +0 -1
- package/dist/src/ruvector/graph-analyzer.js +0 -929
- package/dist/src/ruvector/graph-analyzer.js.map +0 -1
- package/dist/src/ruvector/index.d.ts +0 -56
- package/dist/src/ruvector/index.d.ts.map +0 -1
- package/dist/src/ruvector/index.js +0 -58
- package/dist/src/ruvector/index.js.map +0 -1
- package/dist/src/ruvector/lora-adapter.d.ts +0 -218
- package/dist/src/ruvector/lora-adapter.d.ts.map +0 -1
- package/dist/src/ruvector/lora-adapter.js +0 -455
- package/dist/src/ruvector/lora-adapter.js.map +0 -1
- package/dist/src/ruvector/model-router.d.ts +0 -222
- package/dist/src/ruvector/model-router.d.ts.map +0 -1
- package/dist/src/ruvector/model-router.js +0 -512
- package/dist/src/ruvector/model-router.js.map +0 -1
- package/dist/src/ruvector/moe-router.d.ts +0 -213
- package/dist/src/ruvector/moe-router.d.ts.map +0 -1
- package/dist/src/ruvector/moe-router.js +0 -649
- package/dist/src/ruvector/moe-router.js.map +0 -1
- package/dist/src/ruvector/q-learning-router.d.ts +0 -217
- package/dist/src/ruvector/q-learning-router.d.ts.map +0 -1
- package/dist/src/ruvector/q-learning-router.js +0 -712
- package/dist/src/ruvector/q-learning-router.js.map +0 -1
- package/dist/src/ruvector/ruvllm-wasm.d.ts +0 -179
- package/dist/src/ruvector/ruvllm-wasm.d.ts.map +0 -1
- package/dist/src/ruvector/ruvllm-wasm.js +0 -363
- package/dist/src/ruvector/ruvllm-wasm.js.map +0 -1
- package/dist/src/ruvector/semantic-router.d.ts +0 -77
- package/dist/src/ruvector/semantic-router.d.ts.map +0 -1
- package/dist/src/ruvector/semantic-router.js +0 -178
- package/dist/src/ruvector/semantic-router.js.map +0 -1
- package/dist/src/ruvector/vector-db.d.ts +0 -69
- package/dist/src/ruvector/vector-db.d.ts.map +0 -1
- package/dist/src/ruvector/vector-db.js +0 -243
- package/dist/src/ruvector/vector-db.js.map +0 -1
- package/dist/src/services/ruvector-training.d.ts +0 -222
- package/dist/src/services/ruvector-training.d.ts.map +0 -1
- package/dist/src/services/ruvector-training.js +0 -696
- package/dist/src/services/ruvector-training.js.map +0 -1
- package/dist/src/ui/.monomind/loops/loop-1779095996252-mdjpp.json +0 -11
- package/dist/src/ui/data/agent-avatars.html +0 -763
- package/dist/src/ui/data/agent-avatars.json +0 -966
- package/dist/src/ui/data/avatars/account-strategist.svg +0 -58
- package/dist/src/ui/data/avatars/accounts-payable.svg +0 -54
- package/dist/src/ui/data/avatars/adaptive-coordinator.svg +0 -55
- package/dist/src/ui/data/avatars/adaptive-coordinator2.svg +0 -54
- package/dist/src/ui/data/avatars/ai-citation.svg +0 -57
- package/dist/src/ui/data/avatars/ai-engineer.svg +0 -61
- package/dist/src/ui/data/avatars/analytics-reporter.svg +0 -53
- package/dist/src/ui/data/avatars/api-tester.svg +0 -53
- package/dist/src/ui/data/avatars/architecture.svg +0 -54
- package/dist/src/ui/data/avatars/automation-governance.svg +0 -55
- package/dist/src/ui/data/avatars/backend-dev.svg +0 -53
- package/dist/src/ui/data/avatars/benchmarker.svg +0 -54
- package/dist/src/ui/data/avatars/blockchain-auditor.svg +0 -53
- package/dist/src/ui/data/avatars/byzantine-coord.svg +0 -57
- package/dist/src/ui/data/avatars/case-analyst.svg +0 -57
- package/dist/src/ui/data/avatars/cicd-engineer.svg +0 -55
- package/dist/src/ui/data/avatars/cloud-architect.svg +0 -54
- package/dist/src/ui/data/avatars/code-review-swarm.svg +0 -57
- package/dist/src/ui/data/avatars/coder-v119.svg +0 -57
- package/dist/src/ui/data/avatars/coder.svg +0 -58
- package/dist/src/ui/data/avatars/collective-coord.svg +0 -54
- package/dist/src/ui/data/avatars/compliance-auditor.svg +0 -58
- package/dist/src/ui/data/avatars/consensus-coordinator.svg +0 -54
- package/dist/src/ui/data/avatars/content-creator.svg +0 -54
- package/dist/src/ui/data/avatars/crdt-synchronizer.svg +0 -53
- package/dist/src/ui/data/avatars/cro-specialist.svg +0 -58
- package/dist/src/ui/data/avatars/data-consolidator.svg +0 -54
- package/dist/src/ui/data/avatars/data-engineer.svg +0 -53
- package/dist/src/ui/data/avatars/database-optimizer.svg +0 -61
- package/dist/src/ui/data/avatars/deal-strategist.svg +0 -54
- package/dist/src/ui/data/avatars/defender.svg +0 -53
- package/dist/src/ui/data/avatars/devops-automator.svg +0 -56
- package/dist/src/ui/data/avatars/discovery-coach.svg +0 -54
- package/dist/src/ui/data/avatars/email-marketing.svg +0 -57
- package/dist/src/ui/data/avatars/embedded-firmware.svg +0 -61
- package/dist/src/ui/data/avatars/evidence-collector.svg +0 -57
- package/dist/src/ui/data/avatars/experiment-tracker.svg +0 -53
- package/dist/src/ui/data/avatars/feedback-synthesizer.svg +0 -54
- package/dist/src/ui/data/avatars/finance-tracker.svg +0 -54
- package/dist/src/ui/data/avatars/frontend-developer.svg +0 -54
- package/dist/src/ui/data/avatars/game-audio-engineer.svg +0 -59
- package/dist/src/ui/data/avatars/game-designer.svg +0 -54
- package/dist/src/ui/data/avatars/gossip-coordinator.svg +0 -54
- package/dist/src/ui/data/avatars/hierarchical-coord.svg +0 -54
- package/dist/src/ui/data/avatars/incident-commander.svg +0 -57
- package/dist/src/ui/data/avatars/infrastructure.svg +0 -54
- package/dist/src/ui/data/avatars/input-validator.svg +0 -53
- package/dist/src/ui/data/avatars/ios-developer.svg +0 -54
- package/dist/src/ui/data/avatars/issue-tracker.svg +0 -53
- package/dist/src/ui/data/avatars/judge.svg +0 -55
- package/dist/src/ui/data/avatars/launch-strategist.svg +0 -54
- package/dist/src/ui/data/avatars/legal-compliance.svg +0 -53
- package/dist/src/ui/data/avatars/level-designer.svg +0 -53
- package/dist/src/ui/data/avatars/load-balancer.svg +0 -57
- package/dist/src/ui/data/avatars/mcp-builder.svg +0 -53
- package/dist/src/ui/data/avatars/memory-coordinator.svg +0 -55
- package/dist/src/ui/data/avatars/mesh-coordinator.svg +0 -55
- package/dist/src/ui/data/avatars/ml-developer.svg +0 -58
- package/dist/src/ui/data/avatars/mobile-app-builder.svg +0 -53
- package/dist/src/ui/data/avatars/mobile-dev.svg +0 -54
- package/dist/src/ui/data/avatars/model-qa.svg +0 -58
- package/dist/src/ui/data/avatars/narrative-designer.svg +0 -58
- package/dist/src/ui/data/avatars/outbound-strategist.svg +0 -55
- package/dist/src/ui/data/avatars/path-validator.svg +0 -54
- package/dist/src/ui/data/avatars/payment-agent.svg +0 -53
- package/dist/src/ui/data/avatars/perf-analyzer.svg +0 -58
- package/dist/src/ui/data/avatars/pipeline-analyst.svg +0 -54
- package/dist/src/ui/data/avatars/planner.svg +0 -55
- package/dist/src/ui/data/avatars/pr-manager.svg +0 -54
- package/dist/src/ui/data/avatars/pricing-strategist.svg +0 -54
- package/dist/src/ui/data/avatars/product-manager.svg +0 -54
- package/dist/src/ui/data/avatars/production-validator.svg +0 -54
- package/dist/src/ui/data/avatars/project-shepherd.svg +0 -54
- package/dist/src/ui/data/avatars/proposal-strategist.svg +0 -54
- package/dist/src/ui/data/avatars/prosecutor.svg +0 -57
- package/dist/src/ui/data/avatars/pseudocode.svg +0 -53
- package/dist/src/ui/data/avatars/queen-coordinator.svg +0 -55
- package/dist/src/ui/data/avatars/quorum-manager.svg +0 -53
- package/dist/src/ui/data/avatars/raft-manager.svg +0 -53
- package/dist/src/ui/data/avatars/reality-checker.svg +0 -58
- package/dist/src/ui/data/avatars/recruitment.svg +0 -58
- package/dist/src/ui/data/avatars/refinement.svg +0 -53
- package/dist/src/ui/data/avatars/release-manager.svg +0 -54
- package/dist/src/ui/data/avatars/repo-architect.svg +0 -54
- package/dist/src/ui/data/avatars/researcher.svg +0 -58
- package/dist/src/ui/data/avatars/resource-allocator.svg +0 -53
- package/dist/src/ui/data/avatars/reviewer.svg +0 -53
- package/dist/src/ui/data/avatars/safe-executor.svg +0 -53
- package/dist/src/ui/data/avatars/sales-coach.svg +0 -53
- package/dist/src/ui/data/avatars/sales-engineer.svg +0 -58
- package/dist/src/ui/data/avatars/scout-explorer.svg +0 -58
- package/dist/src/ui/data/avatars/security-architect.svg +0 -54
- package/dist/src/ui/data/avatars/security-auditor.svg +0 -55
- package/dist/src/ui/data/avatars/senior-developer.svg +0 -58
- package/dist/src/ui/data/avatars/senior-pm.svg +0 -58
- package/dist/src/ui/data/avatars/seo-specialist.svg +0 -57
- package/dist/src/ui/data/avatars/social-media.svg +0 -54
- package/dist/src/ui/data/avatars/solidity-engineer.svg +0 -58
- package/dist/src/ui/data/avatars/sparc-coder.svg +0 -58
- package/dist/src/ui/data/avatars/sparc-coord.svg +0 -56
- package/dist/src/ui/data/avatars/specification.svg +0 -57
- package/dist/src/ui/data/avatars/sprint-prioritizer.svg +0 -53
- package/dist/src/ui/data/avatars/sre.svg +0 -54
- package/dist/src/ui/data/avatars/studio-operations.svg +0 -53
- package/dist/src/ui/data/avatars/studio-producer.svg +0 -55
- package/dist/src/ui/data/avatars/support-responder.svg +0 -56
- package/dist/src/ui/data/avatars/system-architect.svg +0 -54
- package/dist/src/ui/data/avatars/task-orchestrator.svg +0 -56
- package/dist/src/ui/data/avatars/technical-artist.svg +0 -53
- package/dist/src/ui/data/avatars/technical-writer.svg +0 -59
- package/dist/src/ui/data/avatars/tester.svg +0 -53
- package/dist/src/ui/data/avatars/threat-detection.svg +0 -61
- package/dist/src/ui/data/avatars/trend-researcher.svg +0 -54
- package/dist/src/ui/data/avatars/trial-director.svg +0 -55
- package/dist/src/ui/data/avatars/unity-architect.svg +0 -54
- package/dist/src/ui/data/avatars/visionos-engineer.svg +0 -57
- package/dist/src/ui/data/avatars/worker-specialist.svg +0 -55
- package/dist/src/ui/data/avatars/workflow-architect.svg +0 -57
- package/dist/src/ui/data/avatars/workflow-automation.svg +0 -54
- package/dist/src/ui/data/avatars/zk-steward.svg +0 -54
- package/dist/src/ui/data/known-projects.json +0 -1
- /package/dist/src/{ruvector → monovector}/diff-classifier.js +0 -0
|
@@ -0,0 +1,1108 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Monograph Compatibility Layer
|
|
3
|
+
*
|
|
4
|
+
* Provides the ~27 high-level functions that the CLI calls but that are NOT
|
|
5
|
+
* exported by @monoes/monograph@1.1.0 (which only exports low-level primitives).
|
|
6
|
+
*
|
|
7
|
+
* All implementations are composed from the real published primitives.
|
|
8
|
+
* Where primitives are insufficient, behaviour degrades honestly with correctly-
|
|
9
|
+
* shaped return values so that handler code that accesses specific fields never throws.
|
|
10
|
+
*
|
|
11
|
+
* Import pattern:
|
|
12
|
+
* - Real primitives: from '@monoes/monograph'
|
|
13
|
+
* - These compat functions: from './monograph-compat.js'
|
|
14
|
+
*/
|
|
15
|
+
import { join } from 'path';
|
|
16
|
+
import { existsSync, readFileSync, writeFileSync, mkdirSync } from 'fs';
|
|
17
|
+
import { homedir } from 'os';
|
|
18
|
+
import { execSync } from 'child_process';
|
|
19
|
+
import { createServer } from 'http';
|
|
20
|
+
import { performance } from 'perf_hooks';
|
|
21
|
+
import { openDb, closeDb, ftsSearch, getNode, getNodesForFile, getEdgesForSource, getEdgesForTarget, countNodes, countEdges, snapshotFromDb, toHtml, MonographError, } from '@monoes/monograph';
|
|
22
|
+
// ─── Tier 1: Fully implementable from primitives ───────────────────────────────
|
|
23
|
+
// 1. hybridQuery
|
|
24
|
+
// BM25-only at monograph@1.1.0 (no vector storage). score = -rank (descending, .toFixed-safe).
|
|
25
|
+
// NOTE: no vector merge is possible at 1.1.0 — pure BM25.
|
|
26
|
+
export async function hybridQuery(db, query, opts = {}) {
|
|
27
|
+
const limit = opts.limit ?? 20;
|
|
28
|
+
const label = opts.label;
|
|
29
|
+
const hits = ftsSearch(db, query, limit, label);
|
|
30
|
+
return hits.map(h => ({
|
|
31
|
+
id: h.id,
|
|
32
|
+
name: h.name,
|
|
33
|
+
label: h.label,
|
|
34
|
+
filePath: h.filePath ?? null,
|
|
35
|
+
score: -h.rank, // descending: higher = better
|
|
36
|
+
}));
|
|
37
|
+
}
|
|
38
|
+
// Also export a positional overload so commands/monograph.ts semanticSearch import
|
|
39
|
+
// can simply redirect here without changing call sites.
|
|
40
|
+
// semanticSearch(db, query, limit?, label?) -> same shape as hybridQuery results
|
|
41
|
+
export function semanticSearch(db, query, limit, label) {
|
|
42
|
+
// At 1.1.0 with no embeddings, semantic degrades to BM25.
|
|
43
|
+
// score = -rank so callers using .score.toFixed() work correctly.
|
|
44
|
+
const hits = ftsSearch(db, query, limit ?? 20, label);
|
|
45
|
+
return hits.map(h => ({
|
|
46
|
+
id: h.id,
|
|
47
|
+
name: h.name,
|
|
48
|
+
label: h.label,
|
|
49
|
+
normLabel: h.normLabel,
|
|
50
|
+
filePath: h.filePath ?? null,
|
|
51
|
+
score: -h.rank,
|
|
52
|
+
}));
|
|
53
|
+
}
|
|
54
|
+
// Helper: resolve a node by name (and optional filePath)
|
|
55
|
+
function resolveNode(db, name, filePath) {
|
|
56
|
+
if (filePath) {
|
|
57
|
+
const candidates = getNodesForFile(db, filePath);
|
|
58
|
+
const match = candidates.find(n => n.name === name);
|
|
59
|
+
if (match)
|
|
60
|
+
return match;
|
|
61
|
+
}
|
|
62
|
+
// Fall back to FTS/name scan
|
|
63
|
+
const row = db.prepare('SELECT * FROM nodes WHERE name = ? LIMIT 1').get(name);
|
|
64
|
+
if (!row)
|
|
65
|
+
return undefined;
|
|
66
|
+
return {
|
|
67
|
+
id: row.id,
|
|
68
|
+
label: row.label,
|
|
69
|
+
name: row.name,
|
|
70
|
+
normLabel: row.norm_label,
|
|
71
|
+
filePath: row.file_path ?? null,
|
|
72
|
+
startLine: row.start_line ?? undefined,
|
|
73
|
+
endLine: row.end_line ?? undefined,
|
|
74
|
+
communityId: row.community_id ?? undefined,
|
|
75
|
+
isExported: !!row.is_exported,
|
|
76
|
+
language: row.language ?? undefined,
|
|
77
|
+
properties: row.properties ? JSON.parse(row.properties) : undefined,
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
// 2. getMonographContext
|
|
81
|
+
export function getMonographContext(db, opts) {
|
|
82
|
+
const node = resolveNode(db, opts.name, opts.filePath);
|
|
83
|
+
if (!node) {
|
|
84
|
+
return {
|
|
85
|
+
target: { id: '', name: opts.name, label: 'Unknown', filePath: opts.filePath ?? null },
|
|
86
|
+
callers: [], callees: [], imports: [], importedBy: [],
|
|
87
|
+
community: null, processes: [],
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
const outEdges = getEdgesForSource(db, node.id);
|
|
91
|
+
const inEdges = getEdgesForTarget(db, node.id);
|
|
92
|
+
const resolve = (id) => {
|
|
93
|
+
const n = getNode(db, id);
|
|
94
|
+
if (!n)
|
|
95
|
+
return null;
|
|
96
|
+
return { id: n.id, name: n.name, label: n.label, filePath: n.filePath ?? null };
|
|
97
|
+
};
|
|
98
|
+
const callees = outEdges.filter(e => e.relation === 'CALLS').map(e => resolve(e.targetId)).filter(Boolean);
|
|
99
|
+
const callers = inEdges.filter(e => e.relation === 'CALLS').map(e => resolve(e.sourceId)).filter(Boolean);
|
|
100
|
+
const imports = outEdges.filter(e => e.relation === 'IMPORTS').map(e => resolve(e.targetId)).filter(Boolean);
|
|
101
|
+
const importedBy = inEdges.filter(e => e.relation === 'IMPORTS').map(e => resolve(e.sourceId)).filter(Boolean);
|
|
102
|
+
const processRelations = new Set(['STEP_IN_PROCESS', 'ENTRY_POINT_OF']);
|
|
103
|
+
const processEdges = [...outEdges, ...inEdges].filter(e => processRelations.has(e.relation));
|
|
104
|
+
const processes = [];
|
|
105
|
+
for (const e of processEdges) {
|
|
106
|
+
const pid = e.relation === 'STEP_IN_PROCESS' ? e.targetId : e.sourceId;
|
|
107
|
+
const pn = getNode(db, pid);
|
|
108
|
+
if (pn)
|
|
109
|
+
processes.push(pn.name);
|
|
110
|
+
}
|
|
111
|
+
return {
|
|
112
|
+
target: {
|
|
113
|
+
id: node.id, name: node.name, label: node.label,
|
|
114
|
+
filePath: node.filePath ?? null, communityId: node.communityId,
|
|
115
|
+
},
|
|
116
|
+
callers, callees, imports, importedBy,
|
|
117
|
+
community: node.communityId ?? null,
|
|
118
|
+
processes: [...new Set(processes)],
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
// 3. getMonographImpact — reverse BFS over CALLS edges
|
|
122
|
+
export function getMonographImpact(db, opts) {
|
|
123
|
+
const node = resolveNode(db, opts.name, opts.filePath);
|
|
124
|
+
if (!node) {
|
|
125
|
+
return {
|
|
126
|
+
target: { id: '', name: opts.name, label: 'Unknown', filePath: opts.filePath ?? null },
|
|
127
|
+
impactedSymbols: [], totalImpacted: 0, riskScore: 0, maxDepthReached: 0,
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
const maxDepth = Math.min(6, Math.max(1, (opts.depth ?? 3)));
|
|
131
|
+
const visited = new Map(); // id -> depth
|
|
132
|
+
const queue = [{ id: node.id, depth: 0 }];
|
|
133
|
+
let maxDepthReached = 0;
|
|
134
|
+
while (queue.length > 0) {
|
|
135
|
+
const item = queue.shift();
|
|
136
|
+
if (item.depth >= maxDepth) {
|
|
137
|
+
maxDepthReached = Math.max(maxDepthReached, item.depth);
|
|
138
|
+
continue;
|
|
139
|
+
}
|
|
140
|
+
const inEdges = getEdgesForTarget(db, item.id);
|
|
141
|
+
for (const e of inEdges) {
|
|
142
|
+
if (e.relation !== 'CALLS')
|
|
143
|
+
continue;
|
|
144
|
+
if (!visited.has(e.sourceId)) {
|
|
145
|
+
const d = item.depth + 1;
|
|
146
|
+
visited.set(e.sourceId, d);
|
|
147
|
+
maxDepthReached = Math.max(maxDepthReached, d);
|
|
148
|
+
queue.push({ id: e.sourceId, depth: d });
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
const impactedSymbols = [];
|
|
153
|
+
let crossFileCount = 0;
|
|
154
|
+
for (const [id, depth] of visited) {
|
|
155
|
+
const n = getNode(db, id);
|
|
156
|
+
if (!n)
|
|
157
|
+
continue;
|
|
158
|
+
const fp = n.filePath ?? null;
|
|
159
|
+
if (fp !== (node.filePath ?? null))
|
|
160
|
+
crossFileCount++;
|
|
161
|
+
impactedSymbols.push({ id: n.id, name: n.name, label: n.label, filePath: fp, depth });
|
|
162
|
+
}
|
|
163
|
+
const total = impactedSymbols.length;
|
|
164
|
+
const crossFraction = total > 0 ? crossFileCount / total : 0;
|
|
165
|
+
const riskScore = Math.min(100, Math.round(total * (1 + crossFraction)));
|
|
166
|
+
return {
|
|
167
|
+
target: { id: node.id, name: node.name, label: node.label, filePath: node.filePath ?? null },
|
|
168
|
+
impactedSymbols,
|
|
169
|
+
totalImpacted: total,
|
|
170
|
+
riskScore,
|
|
171
|
+
maxDepthReached,
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
// 4. getMonographRename — always dry-run, never writes
|
|
175
|
+
export function getMonographRename(db, opts) {
|
|
176
|
+
const nodes = [];
|
|
177
|
+
if (opts.filePath) {
|
|
178
|
+
const candidates = getNodesForFile(db, opts.filePath);
|
|
179
|
+
nodes.push(...candidates.filter(n => n.name === opts.oldName));
|
|
180
|
+
}
|
|
181
|
+
if (nodes.length === 0) {
|
|
182
|
+
const rows = db.prepare('SELECT * FROM nodes WHERE name = ?').all(opts.oldName);
|
|
183
|
+
nodes.push(...rows.map((r) => resolveNode(db, r.name)));
|
|
184
|
+
}
|
|
185
|
+
const occurrences = [];
|
|
186
|
+
const files = new Set();
|
|
187
|
+
for (const node of nodes) {
|
|
188
|
+
if (!node)
|
|
189
|
+
continue;
|
|
190
|
+
occurrences.push({ filePath: node.filePath ?? null, line: node.startLine ?? null, kind: 'definition' });
|
|
191
|
+
if (node.filePath)
|
|
192
|
+
files.add(node.filePath);
|
|
193
|
+
const outEdges = getEdgesForSource(db, node.id);
|
|
194
|
+
const inEdges = getEdgesForTarget(db, node.id);
|
|
195
|
+
for (const e of [...outEdges, ...inEdges]) {
|
|
196
|
+
const refId = e.sourceId === node.id ? e.targetId : e.sourceId;
|
|
197
|
+
const refNode = getNode(db, refId);
|
|
198
|
+
if (refNode) {
|
|
199
|
+
occurrences.push({ filePath: refNode.filePath ?? null, line: refNode.startLine ?? null, kind: e.relation });
|
|
200
|
+
if (refNode.filePath)
|
|
201
|
+
files.add(refNode.filePath);
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
return {
|
|
206
|
+
oldName: opts.oldName,
|
|
207
|
+
newName: opts.newName,
|
|
208
|
+
occurrences,
|
|
209
|
+
fileCount: files.size,
|
|
210
|
+
dryRun: true,
|
|
211
|
+
};
|
|
212
|
+
}
|
|
213
|
+
// 5. detectMonographChanges
|
|
214
|
+
export function detectMonographChanges(db, opts, repoPath) {
|
|
215
|
+
const base = opts.baseBranch ?? 'main';
|
|
216
|
+
let changedFiles = [];
|
|
217
|
+
try {
|
|
218
|
+
const out = execSync(`git diff --name-only ${base}...HEAD`, {
|
|
219
|
+
cwd: repoPath, encoding: 'utf-8',
|
|
220
|
+
}).trim();
|
|
221
|
+
changedFiles = out.split('\n').filter(Boolean);
|
|
222
|
+
}
|
|
223
|
+
catch {
|
|
224
|
+
// git error — return empty
|
|
225
|
+
}
|
|
226
|
+
if (opts.includeTests === false) {
|
|
227
|
+
changedFiles = changedFiles.filter(f => !f.includes('test') && !f.includes('spec') && !f.includes('__tests__'));
|
|
228
|
+
}
|
|
229
|
+
const affectedSymbols = [];
|
|
230
|
+
const seenIds = new Set();
|
|
231
|
+
for (const rel of changedFiles) {
|
|
232
|
+
const abs = join(repoPath, rel);
|
|
233
|
+
const nodes = getNodesForFile(db, abs);
|
|
234
|
+
for (const n of nodes) {
|
|
235
|
+
if (!seenIds.has(n.id)) {
|
|
236
|
+
seenIds.add(n.id);
|
|
237
|
+
affectedSymbols.push({ id: n.id, name: n.name, label: n.label, filePath: n.filePath ?? abs });
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
return { baseBranch: base, changedFiles, affectedSymbols, symbolCount: affectedSymbols.length };
|
|
242
|
+
}
|
|
243
|
+
// 6. getMonographRouteMap
|
|
244
|
+
export function getMonographRouteMap(db, opts) {
|
|
245
|
+
const rows = db.prepare("SELECT * FROM nodes WHERE label = 'Route'").all();
|
|
246
|
+
const includeMiddleware = opts.includeMiddleware ?? false;
|
|
247
|
+
let routes = [];
|
|
248
|
+
for (const row of rows) {
|
|
249
|
+
let props = {};
|
|
250
|
+
try {
|
|
251
|
+
props = row.properties ? JSON.parse(row.properties) : {};
|
|
252
|
+
}
|
|
253
|
+
catch { /* skip */ }
|
|
254
|
+
const routePath = props.path ?? row.name ?? '';
|
|
255
|
+
const method = (props.method ?? 'ANY').toUpperCase();
|
|
256
|
+
if (!includeMiddleware && method === 'USE')
|
|
257
|
+
continue;
|
|
258
|
+
if (opts.prefix && !routePath.includes(opts.prefix))
|
|
259
|
+
continue;
|
|
260
|
+
if (opts.method && method !== opts.method.toUpperCase())
|
|
261
|
+
continue;
|
|
262
|
+
// Resolve handler via HANDLES_ROUTE edges
|
|
263
|
+
const outEdges = getEdgesForSource(db, row.id);
|
|
264
|
+
const handlerEdge = outEdges.find(e => e.relation === 'HANDLES_ROUTE');
|
|
265
|
+
let handlerName = null;
|
|
266
|
+
if (handlerEdge) {
|
|
267
|
+
const hn = getNode(db, handlerEdge.targetId);
|
|
268
|
+
if (hn)
|
|
269
|
+
handlerName = hn.name;
|
|
270
|
+
}
|
|
271
|
+
routes.push({
|
|
272
|
+
path: routePath,
|
|
273
|
+
method,
|
|
274
|
+
handler: handlerName,
|
|
275
|
+
filePath: row.file_path ?? null,
|
|
276
|
+
line: row.start_line ?? null,
|
|
277
|
+
});
|
|
278
|
+
}
|
|
279
|
+
return { routes, total: routes.length };
|
|
280
|
+
}
|
|
281
|
+
// 7. getMonographApiImpact — forward BFS from route handler
|
|
282
|
+
export function getMonographApiImpact(db, opts) {
|
|
283
|
+
const rows = db.prepare("SELECT * FROM nodes WHERE label = 'Route'").all();
|
|
284
|
+
let handlerNodeId = null;
|
|
285
|
+
let handlerName = null;
|
|
286
|
+
for (const row of rows) {
|
|
287
|
+
let props = {};
|
|
288
|
+
try {
|
|
289
|
+
props = row.properties ? JSON.parse(row.properties) : {};
|
|
290
|
+
}
|
|
291
|
+
catch { /* skip */ }
|
|
292
|
+
const rp = props.path ?? row.name ?? '';
|
|
293
|
+
const rm = (props.method ?? 'ANY').toUpperCase();
|
|
294
|
+
if (rp !== opts.routePath)
|
|
295
|
+
continue;
|
|
296
|
+
if (opts.method && rm !== opts.method.toUpperCase())
|
|
297
|
+
continue;
|
|
298
|
+
const outEdges = getEdgesForSource(db, row.id);
|
|
299
|
+
const he = outEdges.find(e => e.relation === 'HANDLES_ROUTE');
|
|
300
|
+
if (he) {
|
|
301
|
+
const hn = getNode(db, he.targetId);
|
|
302
|
+
if (hn) {
|
|
303
|
+
handlerNodeId = hn.id;
|
|
304
|
+
handlerName = hn.name;
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
break;
|
|
308
|
+
}
|
|
309
|
+
if (!handlerNodeId) {
|
|
310
|
+
return { route: opts.routePath, handler: null, impactedSymbols: [], totalImpacted: 0, riskScore: 0 };
|
|
311
|
+
}
|
|
312
|
+
// Forward BFS over CALLS
|
|
313
|
+
const visited = new Map();
|
|
314
|
+
const queue = [{ id: handlerNodeId, depth: 0 }];
|
|
315
|
+
let crossFileCount = 0;
|
|
316
|
+
const handlerNode = getNode(db, handlerNodeId);
|
|
317
|
+
const handlerFile = handlerNode?.filePath ?? null;
|
|
318
|
+
while (queue.length > 0) {
|
|
319
|
+
const item = queue.shift();
|
|
320
|
+
if (item.depth >= 3)
|
|
321
|
+
continue;
|
|
322
|
+
const outEdges = getEdgesForSource(db, item.id);
|
|
323
|
+
for (const e of outEdges) {
|
|
324
|
+
if (e.relation !== 'CALLS')
|
|
325
|
+
continue;
|
|
326
|
+
if (!visited.has(e.targetId)) {
|
|
327
|
+
const d = item.depth + 1;
|
|
328
|
+
visited.set(e.targetId, d);
|
|
329
|
+
const n = getNode(db, e.targetId);
|
|
330
|
+
if (n && (n.filePath ?? null) !== handlerFile)
|
|
331
|
+
crossFileCount++;
|
|
332
|
+
queue.push({ id: e.targetId, depth: d });
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
const impactedSymbols = [];
|
|
337
|
+
for (const [id, depth] of visited) {
|
|
338
|
+
const n = getNode(db, id);
|
|
339
|
+
if (n)
|
|
340
|
+
impactedSymbols.push({ id: n.id, name: n.name, label: n.label, filePath: n.filePath ?? null, depth });
|
|
341
|
+
}
|
|
342
|
+
const total = impactedSymbols.length;
|
|
343
|
+
const crossFraction = total > 0 ? crossFileCount / total : 0;
|
|
344
|
+
const riskScore = Math.min(100, Math.round(total * (1 + crossFraction)));
|
|
345
|
+
return { route: opts.routePath, handler: handlerName, impactedSymbols, totalImpacted: total, riskScore };
|
|
346
|
+
}
|
|
347
|
+
// 8. getMonographStaleness
|
|
348
|
+
export async function getMonographStaleness(repoPath) {
|
|
349
|
+
const dbPath = join(repoPath, '.monomind', 'monograph.db');
|
|
350
|
+
let lastCommit = null;
|
|
351
|
+
if (existsSync(dbPath)) {
|
|
352
|
+
const db = openDb(dbPath);
|
|
353
|
+
try {
|
|
354
|
+
const meta = db.prepare("SELECT value FROM index_meta WHERE key = 'lastCommit'").get();
|
|
355
|
+
lastCommit = meta?.value ?? null;
|
|
356
|
+
}
|
|
357
|
+
finally {
|
|
358
|
+
closeDb(db);
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
let currentHead = null;
|
|
362
|
+
let commitsBehind = 0;
|
|
363
|
+
let changedFiles = [];
|
|
364
|
+
let firstDivergingCommitTime;
|
|
365
|
+
try {
|
|
366
|
+
currentHead = execSync('git rev-parse HEAD', { cwd: repoPath, encoding: 'utf-8' }).trim();
|
|
367
|
+
}
|
|
368
|
+
catch { /* no git */ }
|
|
369
|
+
if (lastCommit && currentHead) {
|
|
370
|
+
try {
|
|
371
|
+
const countOut = execSync(`git rev-list --count ${lastCommit}..HEAD`, { cwd: repoPath, encoding: 'utf-8' }).trim();
|
|
372
|
+
commitsBehind = parseInt(countOut, 10) || 0;
|
|
373
|
+
}
|
|
374
|
+
catch { /* diverged/missing */ }
|
|
375
|
+
try {
|
|
376
|
+
const diffOut = execSync(`git diff --name-only ${lastCommit}...HEAD`, { cwd: repoPath, encoding: 'utf-8' }).trim();
|
|
377
|
+
changedFiles = diffOut.split('\n').filter(Boolean);
|
|
378
|
+
}
|
|
379
|
+
catch { /* skip */ }
|
|
380
|
+
if (commitsBehind > 0) {
|
|
381
|
+
try {
|
|
382
|
+
firstDivergingCommitTime = execSync(`git show -s --format=%cI ${lastCommit}..HEAD -- | head -1`, {
|
|
383
|
+
cwd: repoPath, encoding: 'utf-8',
|
|
384
|
+
}).trim() || undefined;
|
|
385
|
+
}
|
|
386
|
+
catch { /* skip */ }
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
return {
|
|
390
|
+
isStale: commitsBehind > 0,
|
|
391
|
+
lastCommit,
|
|
392
|
+
currentHead,
|
|
393
|
+
commitsBehind,
|
|
394
|
+
changedFiles,
|
|
395
|
+
...(firstDivergingCommitTime ? { firstDivergingCommitTime } : {}),
|
|
396
|
+
};
|
|
397
|
+
}
|
|
398
|
+
// 9. runDoctor
|
|
399
|
+
export async function runDoctor(repoPath) {
|
|
400
|
+
const checks = [];
|
|
401
|
+
// Node version
|
|
402
|
+
const nodeVer = process.versions.node;
|
|
403
|
+
const [nodeMaj] = nodeVer.split('.').map(Number);
|
|
404
|
+
checks.push({
|
|
405
|
+
name: 'Node.js version',
|
|
406
|
+
status: nodeMaj >= 20 ? 'ok' : 'warn',
|
|
407
|
+
message: `${nodeVer}${nodeMaj < 20 ? ' (recommend >=20)' : ''}`,
|
|
408
|
+
});
|
|
409
|
+
// DB health
|
|
410
|
+
const dbPath = join(repoPath, '.monomind', 'monograph.db');
|
|
411
|
+
if (!existsSync(dbPath)) {
|
|
412
|
+
checks.push({ name: 'Monograph DB', status: 'warn', message: 'DB not found. Run monograph build first.' });
|
|
413
|
+
}
|
|
414
|
+
else {
|
|
415
|
+
let dbOk = false;
|
|
416
|
+
let nodeCount = 0;
|
|
417
|
+
try {
|
|
418
|
+
const db = openDb(dbPath);
|
|
419
|
+
nodeCount = countNodes(db);
|
|
420
|
+
closeDb(db);
|
|
421
|
+
dbOk = true;
|
|
422
|
+
}
|
|
423
|
+
catch (e) {
|
|
424
|
+
checks.push({ name: 'Monograph DB', status: 'fail', message: `Cannot open DB: ${e.message}` });
|
|
425
|
+
}
|
|
426
|
+
if (dbOk) {
|
|
427
|
+
checks.push({
|
|
428
|
+
name: 'Monograph DB',
|
|
429
|
+
status: nodeCount > 0 ? 'ok' : 'warn',
|
|
430
|
+
message: nodeCount > 0 ? `${nodeCount} nodes indexed` : 'DB is empty — run monograph build',
|
|
431
|
+
});
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
// Disk space (best-effort)
|
|
435
|
+
try {
|
|
436
|
+
const dfOut = execSync('df -k .', { cwd: repoPath, encoding: 'utf-8' });
|
|
437
|
+
const lines = dfOut.trim().split('\n');
|
|
438
|
+
const dataLine = lines[1] ?? '';
|
|
439
|
+
const parts = dataLine.split(/\s+/);
|
|
440
|
+
const availKb = parseInt(parts[3] ?? '0', 10);
|
|
441
|
+
const availMb = availKb / 1024;
|
|
442
|
+
checks.push({
|
|
443
|
+
name: 'Disk space',
|
|
444
|
+
status: availMb > 500 ? 'ok' : 'warn',
|
|
445
|
+
message: `${availMb.toFixed(0)} MB available`,
|
|
446
|
+
});
|
|
447
|
+
}
|
|
448
|
+
catch {
|
|
449
|
+
checks.push({ name: 'Disk space', status: 'warn', message: 'Could not check disk space' });
|
|
450
|
+
}
|
|
451
|
+
const healthy = checks.every(c => c.status !== 'fail');
|
|
452
|
+
return { healthy, checks };
|
|
453
|
+
}
|
|
454
|
+
// 10a. getProcessesResource
|
|
455
|
+
export function getProcessesResource(db) {
|
|
456
|
+
const rows = db.prepare("SELECT * FROM nodes WHERE label = 'Process'").all();
|
|
457
|
+
const processes = rows.map((row) => {
|
|
458
|
+
const inEdges = getEdgesForTarget(db, row.id);
|
|
459
|
+
const steps = inEdges
|
|
460
|
+
.filter(e => e.relation === 'STEP_IN_PROCESS')
|
|
461
|
+
.map(e => {
|
|
462
|
+
const n = getNode(db, e.sourceId);
|
|
463
|
+
return n ? { id: n.id, name: n.name, filePath: n.filePath ?? null } : null;
|
|
464
|
+
})
|
|
465
|
+
.filter(Boolean);
|
|
466
|
+
return { id: row.id, name: row.name, steps };
|
|
467
|
+
});
|
|
468
|
+
return { processes };
|
|
469
|
+
}
|
|
470
|
+
// 10b. getCommunitiesResource
|
|
471
|
+
export function getCommunitiesResource(db) {
|
|
472
|
+
let communities = [];
|
|
473
|
+
try {
|
|
474
|
+
const rows = db.prepare('SELECT * FROM communities ORDER BY id').all();
|
|
475
|
+
communities = rows.map((row) => {
|
|
476
|
+
const memberRows = db.prepare('SELECT name FROM nodes WHERE community_id = ? AND label NOT IN (\'File\',\'Folder\',\'Community\') LIMIT 20').all(row.id);
|
|
477
|
+
return {
|
|
478
|
+
id: row.id,
|
|
479
|
+
label: row.label ?? `community-${row.id}`,
|
|
480
|
+
size: row.size ?? 0,
|
|
481
|
+
cohesionScore: row.cohesion_score ?? null,
|
|
482
|
+
members: memberRows.map((m) => m.name),
|
|
483
|
+
};
|
|
484
|
+
});
|
|
485
|
+
}
|
|
486
|
+
catch {
|
|
487
|
+
// communities table may not exist
|
|
488
|
+
}
|
|
489
|
+
return { communities };
|
|
490
|
+
}
|
|
491
|
+
// 10c. getSchemaResource
|
|
492
|
+
export function getSchemaResource(db) {
|
|
493
|
+
const labels = db.prepare('SELECT DISTINCT label FROM nodes ORDER BY label').all().map((r) => r.label);
|
|
494
|
+
const relations = db.prepare('SELECT DISTINCT relation FROM edges ORDER BY relation').all().map((r) => r.relation);
|
|
495
|
+
const nc = countNodes(db);
|
|
496
|
+
const ec = countEdges(db);
|
|
497
|
+
let communityCount = 0;
|
|
498
|
+
try {
|
|
499
|
+
communityCount = db.prepare('SELECT COUNT(*) as n FROM communities').get().n;
|
|
500
|
+
}
|
|
501
|
+
catch { /* no communities table */ }
|
|
502
|
+
return { labels, relations, nodeCount: nc, edgeCount: ec, communityCount };
|
|
503
|
+
}
|
|
504
|
+
// 10d. getGraphResource
|
|
505
|
+
export function getGraphResource(db) {
|
|
506
|
+
let nodes = [];
|
|
507
|
+
let edges = [];
|
|
508
|
+
try {
|
|
509
|
+
const snap = snapshotFromDb(db);
|
|
510
|
+
// snapshotFromDb returns a graphology graph; export via raw SQL for a stable shape
|
|
511
|
+
nodes = db.prepare('SELECT * FROM nodes LIMIT 2000').all();
|
|
512
|
+
edges = db.prepare('SELECT * FROM edges LIMIT 10000').all();
|
|
513
|
+
}
|
|
514
|
+
catch {
|
|
515
|
+
nodes = db.prepare('SELECT * FROM nodes LIMIT 2000').all();
|
|
516
|
+
edges = db.prepare('SELECT * FROM edges LIMIT 10000').all();
|
|
517
|
+
}
|
|
518
|
+
return { nodes, edges };
|
|
519
|
+
}
|
|
520
|
+
// ─── Tier 2: Best-effort / correctly-shaped degradation ───────────────────────
|
|
521
|
+
// 11. getMonographCypher — minimal single-hop MATCH evaluator
|
|
522
|
+
// IMPORTANT: does NOT delegate to toCypher() which serializes the graph.
|
|
523
|
+
// Returns {rows, error?, queryTime} so handlers can do Object.keys(rows[0]) and result.queryTime.
|
|
524
|
+
export function getMonographCypher(db, query) {
|
|
525
|
+
const t0 = performance.now();
|
|
526
|
+
// Block writes
|
|
527
|
+
const writePattern = /\b(CREATE|MERGE|SET|DELETE|REMOVE|DROP)\b/i;
|
|
528
|
+
if (writePattern.test(query)) {
|
|
529
|
+
return { rows: [], error: 'write ops not allowed', queryTime: performance.now() - t0 };
|
|
530
|
+
}
|
|
531
|
+
// Parse a single-hop MATCH:
|
|
532
|
+
// MATCH (a[:Label] [{name:"x"}])-[:REL]->(b[:Label]) RETURN a.prop, b.prop, ...
|
|
533
|
+
// OR: MATCH (a[:Label] [{name:"x"}]) RETURN a.prop, ...
|
|
534
|
+
const matchRe = /MATCH\s*\((\w+)(?::(\w+))?(?:\s*\{([^}]*)\})?\)(?:\s*-\[:(\w+)\]->\s*\((\w+)(?::(\w+))?\))?\s*RETURN\s+(.+)/i;
|
|
535
|
+
const m = query.match(matchRe);
|
|
536
|
+
if (!m) {
|
|
537
|
+
return {
|
|
538
|
+
rows: [],
|
|
539
|
+
error: 'unsupported query (compat supports single-hop MATCH only)',
|
|
540
|
+
queryTime: performance.now() - t0,
|
|
541
|
+
};
|
|
542
|
+
}
|
|
543
|
+
const [, aVar, aLabel, aProps, rel, bVar, bLabel, returnClause] = m;
|
|
544
|
+
// Parse anchor properties {name:"x", ...}
|
|
545
|
+
const anchorParams = {};
|
|
546
|
+
if (aProps) {
|
|
547
|
+
const propRe = /(\w+)\s*:\s*["']([^"']*)["']/g;
|
|
548
|
+
let pm;
|
|
549
|
+
while ((pm = propRe.exec(aProps)) !== null) {
|
|
550
|
+
anchorParams[pm[1]] = pm[2];
|
|
551
|
+
}
|
|
552
|
+
}
|
|
553
|
+
// Parse RETURN columns
|
|
554
|
+
const returnCols = returnClause.split(',').map(s => s.trim());
|
|
555
|
+
// Helper to map aliasVar.field -> SQL column
|
|
556
|
+
const fieldToCol = {
|
|
557
|
+
id: 'id', name: 'name', label: 'label', filePath: 'file_path',
|
|
558
|
+
startLine: 'start_line', endLine: 'end_line', communityId: 'community_id',
|
|
559
|
+
isExported: 'is_exported', language: 'language',
|
|
560
|
+
};
|
|
561
|
+
try {
|
|
562
|
+
let rows;
|
|
563
|
+
if (rel && bVar) {
|
|
564
|
+
// Two-node pattern with relationship
|
|
565
|
+
let sql = 'SELECT n1.id as n1_id, n1.name as n1_name, n1.label as n1_label, n1.file_path as n1_file_path, n1.start_line as n1_start_line, n2.id as n2_id, n2.name as n2_name, n2.label as n2_label, n2.file_path as n2_file_path, n2.start_line as n2_start_line FROM nodes n1 JOIN edges e ON e.source_id = n1.id JOIN nodes n2 ON n2.id = e.target_id WHERE e.relation = ?';
|
|
566
|
+
const params = [rel];
|
|
567
|
+
if (aLabel) {
|
|
568
|
+
sql += ' AND n1.label = ?';
|
|
569
|
+
params.push(aLabel);
|
|
570
|
+
}
|
|
571
|
+
if (bLabel) {
|
|
572
|
+
sql += ' AND n2.label = ?';
|
|
573
|
+
params.push(bLabel);
|
|
574
|
+
}
|
|
575
|
+
for (const [k, v] of Object.entries(anchorParams)) {
|
|
576
|
+
const col = fieldToCol[k] ?? k;
|
|
577
|
+
sql += ` AND n1.${col} = ?`;
|
|
578
|
+
params.push(v);
|
|
579
|
+
}
|
|
580
|
+
sql += ' LIMIT 100';
|
|
581
|
+
const rawRows = db.prepare(sql).all(...params);
|
|
582
|
+
rows = rawRows.map((r) => {
|
|
583
|
+
const out = {};
|
|
584
|
+
for (const col of returnCols) {
|
|
585
|
+
const dotIdx = col.indexOf('.');
|
|
586
|
+
if (dotIdx === -1) {
|
|
587
|
+
out[col] = null;
|
|
588
|
+
continue;
|
|
589
|
+
}
|
|
590
|
+
const varPart = col.slice(0, dotIdx);
|
|
591
|
+
const fieldPart = col.slice(dotIdx + 1);
|
|
592
|
+
const prefix = varPart === aVar ? 'n1' : varPart === bVar ? 'n2' : null;
|
|
593
|
+
if (!prefix) {
|
|
594
|
+
out[col] = null;
|
|
595
|
+
continue;
|
|
596
|
+
}
|
|
597
|
+
const dbCol = fieldToCol[fieldPart] ?? fieldPart;
|
|
598
|
+
out[col] = r[`${prefix}_${dbCol}`] ?? r[`${prefix}_${fieldPart}`] ?? null;
|
|
599
|
+
}
|
|
600
|
+
return out;
|
|
601
|
+
});
|
|
602
|
+
}
|
|
603
|
+
else {
|
|
604
|
+
// Single-node pattern
|
|
605
|
+
let sql = 'SELECT * FROM nodes n1 WHERE 1=1';
|
|
606
|
+
const params = [];
|
|
607
|
+
if (aLabel) {
|
|
608
|
+
sql += ' AND n1.label = ?';
|
|
609
|
+
params.push(aLabel);
|
|
610
|
+
}
|
|
611
|
+
for (const [k, v] of Object.entries(anchorParams)) {
|
|
612
|
+
const col = fieldToCol[k] ?? k;
|
|
613
|
+
sql += ` AND n1.${col} = ?`;
|
|
614
|
+
params.push(v);
|
|
615
|
+
}
|
|
616
|
+
sql += ' LIMIT 100';
|
|
617
|
+
const rawRows = db.prepare(sql).all(...params);
|
|
618
|
+
rows = rawRows.map((r) => {
|
|
619
|
+
const out = {};
|
|
620
|
+
for (const col of returnCols) {
|
|
621
|
+
const dotIdx = col.indexOf('.');
|
|
622
|
+
if (dotIdx === -1) {
|
|
623
|
+
out[col] = r[col] ?? null;
|
|
624
|
+
continue;
|
|
625
|
+
}
|
|
626
|
+
const fieldPart = col.slice(dotIdx + 1);
|
|
627
|
+
const dbCol = fieldToCol[fieldPart] ?? fieldPart;
|
|
628
|
+
out[col] = r[dbCol] ?? r[fieldPart] ?? null;
|
|
629
|
+
}
|
|
630
|
+
return out;
|
|
631
|
+
});
|
|
632
|
+
}
|
|
633
|
+
return { rows, queryTime: performance.now() - t0 };
|
|
634
|
+
}
|
|
635
|
+
catch (err) {
|
|
636
|
+
return {
|
|
637
|
+
rows: [],
|
|
638
|
+
error: `Query error: ${err.message}`,
|
|
639
|
+
queryTime: performance.now() - t0,
|
|
640
|
+
};
|
|
641
|
+
}
|
|
642
|
+
}
|
|
643
|
+
// 12. augmentContext
|
|
644
|
+
export async function augmentContext(opts) {
|
|
645
|
+
const { topK = 10, format = 'markdown', query, repoPath } = opts;
|
|
646
|
+
const dbPath = join(repoPath, '.monomind', 'monograph.db');
|
|
647
|
+
if (!existsSync(dbPath))
|
|
648
|
+
return format === 'json' ? '[]' : '(no knowledge graph found — run monograph build)';
|
|
649
|
+
const db = openDb(dbPath);
|
|
650
|
+
try {
|
|
651
|
+
const hits = ftsSearch(db, query, topK);
|
|
652
|
+
if (hits.length === 0)
|
|
653
|
+
return format === 'json' ? '[]' : '(no results)';
|
|
654
|
+
if (format === 'json') {
|
|
655
|
+
const result = hits.map(h => {
|
|
656
|
+
const outEdges = getEdgesForSource(db, h.id);
|
|
657
|
+
const inEdges = getEdgesForTarget(db, h.id);
|
|
658
|
+
return {
|
|
659
|
+
id: h.id, name: h.name, label: h.label, filePath: h.filePath ?? null,
|
|
660
|
+
score: -h.rank,
|
|
661
|
+
callers: inEdges.filter(e => e.relation === 'CALLS').map(e => e.sourceId),
|
|
662
|
+
callees: outEdges.filter(e => e.relation === 'CALLS').map(e => e.targetId),
|
|
663
|
+
};
|
|
664
|
+
});
|
|
665
|
+
return JSON.stringify(result, null, 2);
|
|
666
|
+
}
|
|
667
|
+
// Markdown
|
|
668
|
+
const lines = [`## Monograph Context — "${query}"\n`];
|
|
669
|
+
for (const h of hits) {
|
|
670
|
+
lines.push(`### ${h.label}: ${h.name}`);
|
|
671
|
+
if (h.filePath)
|
|
672
|
+
lines.push(`*File:* \`${h.filePath}\``);
|
|
673
|
+
lines.push(`*Score:* ${(-h.rank).toFixed(4)}`);
|
|
674
|
+
const outEdges = getEdgesForSource(db, h.id);
|
|
675
|
+
const inEdges = getEdgesForTarget(db, h.id);
|
|
676
|
+
const callees = outEdges.filter(e => e.relation === 'CALLS').slice(0, 5);
|
|
677
|
+
const callers = inEdges.filter(e => e.relation === 'CALLS').slice(0, 5);
|
|
678
|
+
if (callees.length > 0) {
|
|
679
|
+
lines.push(`*Calls:* ${callees.map(e => { const n = getNode(db, e.targetId); return n?.name ?? e.targetId; }).join(', ')}`);
|
|
680
|
+
}
|
|
681
|
+
if (callers.length > 0) {
|
|
682
|
+
lines.push(`*Called by:* ${callers.map(e => { const n = getNode(db, e.sourceId); return n?.name ?? e.sourceId; }).join(', ')}`);
|
|
683
|
+
}
|
|
684
|
+
lines.push('');
|
|
685
|
+
}
|
|
686
|
+
return lines.join('\n');
|
|
687
|
+
}
|
|
688
|
+
finally {
|
|
689
|
+
closeDb(db);
|
|
690
|
+
}
|
|
691
|
+
}
|
|
692
|
+
// 13. injectAiContext
|
|
693
|
+
export async function injectAiContext(opts) {
|
|
694
|
+
const { repoPath, targets = ['claude', 'agents-md'] } = opts;
|
|
695
|
+
const SENTINEL_START = '<!-- monograph:start -->';
|
|
696
|
+
const SENTINEL_END = '<!-- monograph:end -->';
|
|
697
|
+
const block = `${SENTINEL_START}\n## Monograph Knowledge Graph\n\nMonograph provides code intelligence via graph-based search.\nTools: monograph_query, monograph_context, monograph_impact, monograph_route_map, monograph_cypher.\n${SENTINEL_END}`;
|
|
698
|
+
const updated = [];
|
|
699
|
+
const fileMaps = {
|
|
700
|
+
'claude': join(repoPath, 'CLAUDE.md'),
|
|
701
|
+
'agents-md': join(repoPath, 'AGENTS.md'),
|
|
702
|
+
};
|
|
703
|
+
for (const target of targets) {
|
|
704
|
+
const fp = fileMaps[target];
|
|
705
|
+
if (!fp)
|
|
706
|
+
continue;
|
|
707
|
+
try {
|
|
708
|
+
let content = existsSync(fp) ? readFileSync(fp, 'utf-8') : '';
|
|
709
|
+
if (content.includes(SENTINEL_START)) {
|
|
710
|
+
content = content.replace(new RegExp(`${SENTINEL_START}[\\s\\S]*?${SENTINEL_END}`, 'g'), block);
|
|
711
|
+
}
|
|
712
|
+
else {
|
|
713
|
+
content = content.trimEnd() + '\n\n' + block + '\n';
|
|
714
|
+
}
|
|
715
|
+
writeFileSync(fp, content, 'utf-8');
|
|
716
|
+
updated.push(fp);
|
|
717
|
+
}
|
|
718
|
+
catch { /* skip unwritable */ }
|
|
719
|
+
}
|
|
720
|
+
return { updated };
|
|
721
|
+
}
|
|
722
|
+
// 14. getToolMap
|
|
723
|
+
export function getToolMap(db, opts) {
|
|
724
|
+
// Look for Route or nodes with HANDLES_TOOL edges
|
|
725
|
+
const rows = db.prepare("SELECT * FROM nodes WHERE label IN ('Route', 'Tool')").all();
|
|
726
|
+
const results = [];
|
|
727
|
+
for (const row of rows) {
|
|
728
|
+
const toolName = row.name;
|
|
729
|
+
if (opts.tool && !toolName.includes(opts.tool))
|
|
730
|
+
continue;
|
|
731
|
+
const outEdges = getEdgesForSource(db, row.id);
|
|
732
|
+
const handleEdge = outEdges.find(e => e.relation === 'HANDLES_TOOL' || e.relation === 'HANDLES_ROUTE');
|
|
733
|
+
let handlerName = null;
|
|
734
|
+
if (handleEdge) {
|
|
735
|
+
const hn = getNode(db, handleEdge.targetId);
|
|
736
|
+
if (hn)
|
|
737
|
+
handlerName = hn.name;
|
|
738
|
+
}
|
|
739
|
+
results.push({ tool: toolName, handler: handlerName, filePath: row.file_path ?? null, line: row.start_line ?? null });
|
|
740
|
+
}
|
|
741
|
+
return results;
|
|
742
|
+
}
|
|
743
|
+
// 15. getShapeCheck
|
|
744
|
+
export function getShapeCheck(db, _repoPath, opts) {
|
|
745
|
+
// Best-effort: attempt to find Route nodes and compare declared response keys.
|
|
746
|
+
// If property data lacks key info, return honest empty (handler handles this gracefully).
|
|
747
|
+
const rows = db.prepare("SELECT * FROM nodes WHERE label = 'Route'").all();
|
|
748
|
+
let checked = 0;
|
|
749
|
+
const mismatches = [];
|
|
750
|
+
for (const row of rows) {
|
|
751
|
+
const routePath = row.name;
|
|
752
|
+
if (opts.route && !routePath.includes(opts.route))
|
|
753
|
+
continue;
|
|
754
|
+
if (opts.file && !(row.file_path ?? '').includes(opts.file))
|
|
755
|
+
continue;
|
|
756
|
+
checked++;
|
|
757
|
+
let props = {};
|
|
758
|
+
try {
|
|
759
|
+
props = row.properties ? JSON.parse(row.properties) : {};
|
|
760
|
+
}
|
|
761
|
+
catch { /* skip */ }
|
|
762
|
+
const producerKeys = Array.isArray(props.responseKeys) ? props.responseKeys : [];
|
|
763
|
+
if (producerKeys.length === 0)
|
|
764
|
+
continue; // no key data available
|
|
765
|
+
// Find ACCESSES edges to see what consumers expect
|
|
766
|
+
const inEdges = getEdgesForTarget(db, row.id);
|
|
767
|
+
const consumerKeys = inEdges
|
|
768
|
+
.filter(e => e.relation === 'ACCESSES')
|
|
769
|
+
.map(e => {
|
|
770
|
+
const n = getNode(db, e.sourceId);
|
|
771
|
+
return n?.name ?? null;
|
|
772
|
+
})
|
|
773
|
+
.filter(Boolean);
|
|
774
|
+
const missing = consumerKeys.filter(k => !producerKeys.includes(k));
|
|
775
|
+
if (missing.length > 0) {
|
|
776
|
+
mismatches.push({ route: routePath, producerKeys, consumerKeys, missing });
|
|
777
|
+
}
|
|
778
|
+
}
|
|
779
|
+
return { mismatches, checked, ok: mismatches.length === 0 };
|
|
780
|
+
}
|
|
781
|
+
// 16. generateSkillFiles
|
|
782
|
+
export async function generateSkillFiles(repoPath, outputDir) {
|
|
783
|
+
const dbPath = join(repoPath, '.monomind', 'monograph.db');
|
|
784
|
+
if (!existsSync(dbPath))
|
|
785
|
+
return { communityCount: 0, filesWritten: [] };
|
|
786
|
+
const outDir = outputDir ?? join(repoPath, '.monomind', 'skills');
|
|
787
|
+
mkdirSync(outDir, { recursive: true });
|
|
788
|
+
const db = openDb(dbPath);
|
|
789
|
+
try {
|
|
790
|
+
const communityIds = db.prepare(`
|
|
791
|
+
SELECT DISTINCT community_id FROM nodes
|
|
792
|
+
WHERE community_id IS NOT NULL
|
|
793
|
+
AND label NOT IN ('File', 'Folder', 'Community', 'Concept')
|
|
794
|
+
ORDER BY community_id
|
|
795
|
+
`).all();
|
|
796
|
+
const filesWritten = [];
|
|
797
|
+
for (const { community_id } of communityIds) {
|
|
798
|
+
// Derive name from folder distribution
|
|
799
|
+
const pathRows = db.prepare(`
|
|
800
|
+
SELECT file_path FROM nodes
|
|
801
|
+
WHERE community_id = ? AND file_path IS NOT NULL
|
|
802
|
+
AND label NOT IN ('File', 'Folder', 'Community', 'Concept')
|
|
803
|
+
LIMIT 20
|
|
804
|
+
`).all(community_id);
|
|
805
|
+
let name = `community-${community_id}`;
|
|
806
|
+
const folderCounts = new Map();
|
|
807
|
+
const genericFolders = new Set(['src', 'lib', 'core', 'utils', 'common', 'shared', 'helpers', 'dist']);
|
|
808
|
+
for (const row of pathRows) {
|
|
809
|
+
const parts = row.file_path.replace(/\\/g, '/').split('/').filter(Boolean);
|
|
810
|
+
if (parts.length >= 2) {
|
|
811
|
+
const folder = parts[parts.length - 2].toLowerCase();
|
|
812
|
+
if (!genericFolders.has(folder)) {
|
|
813
|
+
folderCounts.set(folder, (folderCounts.get(folder) ?? 0) + 1);
|
|
814
|
+
}
|
|
815
|
+
}
|
|
816
|
+
}
|
|
817
|
+
let bestCount = 0;
|
|
818
|
+
for (const [folder, count] of folderCounts) {
|
|
819
|
+
if (count > bestCount) {
|
|
820
|
+
bestCount = count;
|
|
821
|
+
name = folder;
|
|
822
|
+
}
|
|
823
|
+
}
|
|
824
|
+
const symbolRows = db.prepare(`
|
|
825
|
+
SELECT name FROM nodes
|
|
826
|
+
WHERE community_id = ? AND is_exported = 1
|
|
827
|
+
AND label NOT IN ('File', 'Folder', 'Community', 'Concept')
|
|
828
|
+
ORDER BY name LIMIT 50
|
|
829
|
+
`).all(community_id);
|
|
830
|
+
const symbols = symbolRows.map((r) => r.name);
|
|
831
|
+
const content = `# Community: ${name}\n\nCommunity ID: ${community_id}\n\n## Exported Symbols\n\n${symbols.map(s => `- ${s}`).join('\n') || '(none)'}\n`;
|
|
832
|
+
const fp = join(outDir, `${name}-${community_id}.md`);
|
|
833
|
+
writeFileSync(fp, content, 'utf-8');
|
|
834
|
+
filesWritten.push(fp);
|
|
835
|
+
}
|
|
836
|
+
return { communityCount: communityIds.length, filesWritten };
|
|
837
|
+
}
|
|
838
|
+
finally {
|
|
839
|
+
closeDb(db);
|
|
840
|
+
}
|
|
841
|
+
}
|
|
842
|
+
// 17. installSkillsForPlatform
|
|
843
|
+
export async function installSkillsForPlatform(repoPath, communities, opts) {
|
|
844
|
+
const platformDirs = {
|
|
845
|
+
claude: join(repoPath, '.claude', 'skills'),
|
|
846
|
+
cursor: join(repoPath, '.cursor', 'rules'),
|
|
847
|
+
vscode: join(repoPath, '.vscode'),
|
|
848
|
+
zed: join(repoPath, '.zed'),
|
|
849
|
+
};
|
|
850
|
+
const outputDir = platformDirs[opts.platform] ?? join(repoPath, `.${opts.platform}`, 'skills');
|
|
851
|
+
mkdirSync(outputDir, { recursive: true });
|
|
852
|
+
const filesWritten = [];
|
|
853
|
+
for (const c of communities) {
|
|
854
|
+
const content = `# ${c.name}\n\n## Exported Symbols\n\n${c.symbols.map(s => `- ${s}`).join('\n') || '(none)'}\n`;
|
|
855
|
+
const fp = join(outputDir, `${c.name}.md`);
|
|
856
|
+
writeFileSync(fp, content, 'utf-8');
|
|
857
|
+
filesWritten.push(fp);
|
|
858
|
+
}
|
|
859
|
+
return { platform: opts.platform, outputDir, filesWritten };
|
|
860
|
+
}
|
|
861
|
+
// 18. runEmbed — embeddings unsupported at 1.1.0; throws so handler catches gracefully
|
|
862
|
+
export async function runEmbed(_db, _opts) {
|
|
863
|
+
throw new MonographError('Embeddings are not supported in @monoes/monograph@1.1.0 — upgrade to a version with native vector storage, or install @huggingface/transformers and a compat build.');
|
|
864
|
+
}
|
|
865
|
+
// ─── Groups (Tier 2) ──────────────────────────────────────────────────────────
|
|
866
|
+
// Helper: read group config (groups.json or group.yaml)
|
|
867
|
+
function readGroupConfig(configPath) {
|
|
868
|
+
if (!existsSync(configPath))
|
|
869
|
+
return [];
|
|
870
|
+
try {
|
|
871
|
+
const raw = readFileSync(configPath, 'utf-8');
|
|
872
|
+
if (configPath.endsWith('.json')) {
|
|
873
|
+
const parsed = JSON.parse(raw);
|
|
874
|
+
return Array.isArray(parsed) ? parsed : (parsed.repos ?? parsed.groups ?? []);
|
|
875
|
+
}
|
|
876
|
+
// YAML — try js-yaml if available, else basic key:value parse
|
|
877
|
+
try {
|
|
878
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
879
|
+
const yaml = require('js-yaml');
|
|
880
|
+
const parsed = yaml.load(raw);
|
|
881
|
+
return Array.isArray(parsed) ? parsed : (parsed?.repos ?? parsed?.groups ?? []);
|
|
882
|
+
}
|
|
883
|
+
catch {
|
|
884
|
+
return []; // js-yaml not available
|
|
885
|
+
}
|
|
886
|
+
}
|
|
887
|
+
catch {
|
|
888
|
+
return [];
|
|
889
|
+
}
|
|
890
|
+
}
|
|
891
|
+
// 19. getGroupList
|
|
892
|
+
export async function getGroupList(configPath) {
|
|
893
|
+
const repos = readGroupConfig(configPath);
|
|
894
|
+
const result = [];
|
|
895
|
+
for (const repo of repos) {
|
|
896
|
+
const repoPath = repo.path ?? '';
|
|
897
|
+
const dbPath = join(repoPath, '.monomind', 'monograph.db');
|
|
898
|
+
let nodeCount = 0;
|
|
899
|
+
let indexedAt = null;
|
|
900
|
+
if (existsSync(dbPath)) {
|
|
901
|
+
try {
|
|
902
|
+
const db = openDb(dbPath);
|
|
903
|
+
nodeCount = countNodes(db);
|
|
904
|
+
const meta = db.prepare("SELECT value FROM index_meta WHERE key = 'indexedAt'").get();
|
|
905
|
+
indexedAt = meta?.value ?? null;
|
|
906
|
+
closeDb(db);
|
|
907
|
+
}
|
|
908
|
+
catch { /* skip */ }
|
|
909
|
+
}
|
|
910
|
+
result.push({ repo: repo.name ?? repoPath, path: repoPath, nodeCount, indexedAt });
|
|
911
|
+
}
|
|
912
|
+
return result;
|
|
913
|
+
}
|
|
914
|
+
// 20. runGroupQuery
|
|
915
|
+
export async function runGroupQuery(configPath, query, limit) {
|
|
916
|
+
const repos = readGroupConfig(configPath);
|
|
917
|
+
const K = 60;
|
|
918
|
+
const perRepo = limit ?? 20;
|
|
919
|
+
const allResults = [];
|
|
920
|
+
for (let i = 0; i < repos.length; i++) {
|
|
921
|
+
const repo = repos[i];
|
|
922
|
+
const repoPath = repo.path ?? '';
|
|
923
|
+
const dbPath = join(repoPath, '.monomind', 'monograph.db');
|
|
924
|
+
if (!existsSync(dbPath))
|
|
925
|
+
continue;
|
|
926
|
+
try {
|
|
927
|
+
const db = openDb(dbPath);
|
|
928
|
+
const hits = ftsSearch(db, query, perRepo);
|
|
929
|
+
closeDb(db);
|
|
930
|
+
hits.forEach(h => {
|
|
931
|
+
allResults.push({
|
|
932
|
+
id: h.id, name: h.name, label: h.label, filePath: h.filePath ?? null,
|
|
933
|
+
repo: repo.name ?? repoPath, rank: h.rank, repoIdx: i,
|
|
934
|
+
});
|
|
935
|
+
});
|
|
936
|
+
}
|
|
937
|
+
catch { /* skip inaccessible repo */ }
|
|
938
|
+
}
|
|
939
|
+
// RRF merge
|
|
940
|
+
const scores = new Map();
|
|
941
|
+
const meta = new Map();
|
|
942
|
+
allResults.forEach((r, i) => {
|
|
943
|
+
const key = `${r.repo}:${r.id}`;
|
|
944
|
+
scores.set(key, (scores.get(key) ?? 0) + 1 / (K + r.rank));
|
|
945
|
+
if (!meta.has(key))
|
|
946
|
+
meta.set(key, r);
|
|
947
|
+
});
|
|
948
|
+
return [...scores.entries()]
|
|
949
|
+
.sort((a, b) => b[1] - a[1])
|
|
950
|
+
.slice(0, perRepo)
|
|
951
|
+
.map(([key, score]) => {
|
|
952
|
+
const r = meta.get(key);
|
|
953
|
+
return { id: r.id, name: r.name, label: r.label, filePath: r.filePath, repo: r.repo, score };
|
|
954
|
+
});
|
|
955
|
+
}
|
|
956
|
+
// 21. runGroupSync
|
|
957
|
+
export async function runGroupSync(configPath) {
|
|
958
|
+
const repos = readGroupConfig(configPath);
|
|
959
|
+
if (repos.length === 0)
|
|
960
|
+
return { repos: 0, contracts: 0, written: [] };
|
|
961
|
+
let contractCount = 0;
|
|
962
|
+
const written = [];
|
|
963
|
+
for (const repo of repos) {
|
|
964
|
+
const repoPath = repo.path ?? '';
|
|
965
|
+
const dbPath = join(repoPath, '.monomind', 'monograph.db');
|
|
966
|
+
if (!existsSync(dbPath))
|
|
967
|
+
continue;
|
|
968
|
+
try {
|
|
969
|
+
const db = openDb(dbPath);
|
|
970
|
+
const routes = db.prepare("SELECT * FROM nodes WHERE label = 'Route'").all();
|
|
971
|
+
contractCount += routes.length;
|
|
972
|
+
closeDb(db);
|
|
973
|
+
}
|
|
974
|
+
catch { /* skip */ }
|
|
975
|
+
}
|
|
976
|
+
// Write contracts registry if we found any
|
|
977
|
+
const configDir = configPath.replace(/[^/\\]+$/, '');
|
|
978
|
+
const contractsPath = join(configDir, 'contracts.json');
|
|
979
|
+
try {
|
|
980
|
+
writeFileSync(contractsPath, JSON.stringify({ synced: new Date().toISOString(), contracts: contractCount }, null, 2));
|
|
981
|
+
written.push(contractsPath);
|
|
982
|
+
}
|
|
983
|
+
catch { /* skip */ }
|
|
984
|
+
return { repos: repos.length, contracts: contractCount, written };
|
|
985
|
+
}
|
|
986
|
+
// 22. getGroupContracts
|
|
987
|
+
export async function getGroupContracts(configPath) {
|
|
988
|
+
const repos = readGroupConfig(configPath);
|
|
989
|
+
const result = [];
|
|
990
|
+
for (const repo of repos) {
|
|
991
|
+
const repoPath = repo.path ?? '';
|
|
992
|
+
const dbPath = join(repoPath, '.monomind', 'monograph.db');
|
|
993
|
+
if (!existsSync(dbPath))
|
|
994
|
+
continue;
|
|
995
|
+
try {
|
|
996
|
+
const db = openDb(dbPath);
|
|
997
|
+
const exported = db.prepare("SELECT * FROM nodes WHERE is_exported = 1 AND label NOT IN ('File','Folder','Community','Concept') LIMIT 100").all();
|
|
998
|
+
closeDb(db);
|
|
999
|
+
for (const n of exported) {
|
|
1000
|
+
result.push({
|
|
1001
|
+
groupName: repo.name ?? repoPath,
|
|
1002
|
+
symbol: n.name,
|
|
1003
|
+
filePath: n.file_path ?? null,
|
|
1004
|
+
line: n.start_line ?? null,
|
|
1005
|
+
});
|
|
1006
|
+
}
|
|
1007
|
+
}
|
|
1008
|
+
catch { /* skip */ }
|
|
1009
|
+
}
|
|
1010
|
+
return result;
|
|
1011
|
+
}
|
|
1012
|
+
// 23. getGroupStatus
|
|
1013
|
+
export async function getGroupStatus(configPath) {
|
|
1014
|
+
const repos = readGroupConfig(configPath);
|
|
1015
|
+
if (repos.length === 0) {
|
|
1016
|
+
return { totalGroups: 0, indexedGroups: 0, stalledGroups: 0, groups: [] };
|
|
1017
|
+
}
|
|
1018
|
+
const groups = [];
|
|
1019
|
+
for (const repo of repos) {
|
|
1020
|
+
const repoPath = repo.path ?? '';
|
|
1021
|
+
const dbPath = join(repoPath, '.monomind', 'monograph.db');
|
|
1022
|
+
const name = repo.name ?? repoPath;
|
|
1023
|
+
if (!existsSync(dbPath)) {
|
|
1024
|
+
groups.push({ name, indexed: false, stale: false, contractCount: 0 });
|
|
1025
|
+
continue;
|
|
1026
|
+
}
|
|
1027
|
+
try {
|
|
1028
|
+
const db = openDb(dbPath);
|
|
1029
|
+
const nc = countNodes(db);
|
|
1030
|
+
const contracts = db.prepare("SELECT COUNT(*) as n FROM nodes WHERE label = 'Route'").get();
|
|
1031
|
+
const meta = db.prepare("SELECT value FROM index_meta WHERE key = 'lastCommit'").get();
|
|
1032
|
+
closeDb(db);
|
|
1033
|
+
groups.push({
|
|
1034
|
+
name,
|
|
1035
|
+
indexed: nc > 0,
|
|
1036
|
+
stale: false, // we'd need git to detect; default false
|
|
1037
|
+
contractCount: contracts?.n ?? 0,
|
|
1038
|
+
...(meta?.value ? { lastSync: meta.value } : {}),
|
|
1039
|
+
});
|
|
1040
|
+
}
|
|
1041
|
+
catch {
|
|
1042
|
+
groups.push({ name, indexed: false, stale: false, contractCount: 0 });
|
|
1043
|
+
}
|
|
1044
|
+
}
|
|
1045
|
+
const indexedGroups = groups.filter(g => g.indexed).length;
|
|
1046
|
+
const stalledGroups = groups.filter(g => g.stale).length;
|
|
1047
|
+
return { totalGroups: groups.length, indexedGroups, stalledGroups, groups };
|
|
1048
|
+
}
|
|
1049
|
+
// ─── Tier 3: Minimal-real / graceful ─────────────────────────────────────────
|
|
1050
|
+
// 24. serveMonograph — minimal node:http server with module-singleton
|
|
1051
|
+
let _httpServer = null;
|
|
1052
|
+
let _serverUrl = null;
|
|
1053
|
+
export async function serveMonograph(opts) {
|
|
1054
|
+
const port = opts.port ?? 7374;
|
|
1055
|
+
if (_httpServer) {
|
|
1056
|
+
return { status: 'already_running', url: _serverUrl ?? `http://localhost:${port}` };
|
|
1057
|
+
}
|
|
1058
|
+
const nodes = opts.db.prepare('SELECT * FROM nodes LIMIT 500').all();
|
|
1059
|
+
const edges = opts.db.prepare('SELECT * FROM edges LIMIT 3000').all();
|
|
1060
|
+
const html = toHtml(nodes, edges);
|
|
1061
|
+
_httpServer = createServer((req, res) => {
|
|
1062
|
+
res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });
|
|
1063
|
+
res.end(html);
|
|
1064
|
+
});
|
|
1065
|
+
await new Promise((resolve, reject) => {
|
|
1066
|
+
_httpServer.listen(port, () => resolve()).on('error', reject);
|
|
1067
|
+
});
|
|
1068
|
+
_serverUrl = `http://localhost:${port}`;
|
|
1069
|
+
if (opts.open) {
|
|
1070
|
+
try {
|
|
1071
|
+
const platform = process.platform;
|
|
1072
|
+
const cmd = platform === 'darwin' ? 'open' : platform === 'win32' ? 'start' : 'xdg-open';
|
|
1073
|
+
execSync(`${cmd} ${_serverUrl}`, { stdio: 'ignore' });
|
|
1074
|
+
}
|
|
1075
|
+
catch { /* best-effort */ }
|
|
1076
|
+
}
|
|
1077
|
+
return { status: 'started', url: _serverUrl };
|
|
1078
|
+
}
|
|
1079
|
+
// 25. getWikiToolResult — graceful: no wiki table in 1.1.0
|
|
1080
|
+
export function getWikiToolResult(_db, _opts) {
|
|
1081
|
+
return { pages: [], note: 'wiki requires monograph >1.1.0' };
|
|
1082
|
+
}
|
|
1083
|
+
// 26. runWikiBuildTool — graceful
|
|
1084
|
+
export async function runWikiBuildTool(_db, _opts) {
|
|
1085
|
+
return { generated: 0, skipped: 0, note: 'wiki generation requires monograph >1.1.0' };
|
|
1086
|
+
}
|
|
1087
|
+
// 27. listRepos — reads ~/.monograph/registry.json
|
|
1088
|
+
export function listRepos() {
|
|
1089
|
+
const registryPath = join(homedir(), '.monograph', 'registry.json');
|
|
1090
|
+
if (!existsSync(registryPath))
|
|
1091
|
+
return [];
|
|
1092
|
+
try {
|
|
1093
|
+
const raw = readFileSync(registryPath, 'utf-8');
|
|
1094
|
+
const parsed = JSON.parse(raw);
|
|
1095
|
+
const repos = Array.isArray(parsed) ? parsed : (parsed.repos ?? []);
|
|
1096
|
+
return repos.map((r) => ({
|
|
1097
|
+
name: r.name ?? r.path ?? '',
|
|
1098
|
+
path: r.path ?? '',
|
|
1099
|
+
...(r.lastIndexed ? { lastIndexed: r.lastIndexed } : {}),
|
|
1100
|
+
...(r.nodeCount != null ? { nodeCount: r.nodeCount } : {}),
|
|
1101
|
+
...(r.edgeCount != null ? { edgeCount: r.edgeCount } : {}),
|
|
1102
|
+
}));
|
|
1103
|
+
}
|
|
1104
|
+
catch {
|
|
1105
|
+
return [];
|
|
1106
|
+
}
|
|
1107
|
+
}
|
|
1108
|
+
//# sourceMappingURL=monograph-compat.js.map
|