monomind 1.8.0 → 1.9.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/design/design-monodesign.md +121 -0
- package/.claude/agents/github/issue-tracker.md +12 -12
- package/.claude/agents/github/pr-manager.md +10 -10
- package/.claude/agents/github/release-manager.md +49 -105
- package/.claude/agents/github/repo-architect.md +73 -92
- package/.claude/agents/github/sync-coordinator.md +55 -123
- package/.claude/agents/marketing/marketing-competitive-content.md +155 -0
- package/.claude/agents/marketing/marketing-content-creator.md +13 -0
- package/.claude/agents/marketing/marketing-cro-specialist.md +147 -0
- package/.claude/agents/marketing/marketing-email-specialist.md +90 -0
- package/.claude/agents/marketing/marketing-launch-strategist.md +129 -0
- package/.claude/agents/marketing/marketing-pricing-strategist.md +127 -0
- package/.claude/agents/specialists/integration-architect.md +94 -0
- package/.claude/commands/agents/README.md +4 -0
- package/.claude/commands/agents/agent-capabilities.md +6 -2
- package/.claude/commands/agents/agent-coordination.md +4 -0
- package/.claude/commands/agents/agent-spawning.md +4 -0
- package/.claude/commands/agents/agent-types.md +6 -2
- package/.claude/commands/analysis/README.md +14 -5
- package/.claude/commands/analysis/bottleneck-detect.md +30 -123
- package/.claude/commands/analysis/performance-bottlenecks.md +14 -14
- package/.claude/commands/analysis/performance-report.md +38 -11
- package/.claude/commands/analysis/token-efficiency.md +13 -16
- package/.claude/commands/analysis/token-usage.md +34 -12
- package/.claude/commands/automation/README.md +15 -5
- package/.claude/commands/automation/auto-agent.md +49 -85
- package/.claude/commands/automation/self-healing.md +20 -18
- package/.claude/commands/automation/session-memory.md +28 -29
- package/.claude/commands/automation/smart-agents.md +17 -9
- package/.claude/commands/automation/smart-spawn.md +52 -11
- package/.claude/commands/automation/workflow-select.md +46 -11
- package/.claude/commands/browse.md +5 -0
- package/.claude/commands/coordination/README.md +9 -5
- package/.claude/commands/coordination/agent-spawn.md +53 -9
- package/.claude/commands/coordination/swarm-init.md +39 -42
- package/.claude/commands/coordination/task-orchestrate.md +65 -11
- package/.claude/commands/github/README.md +21 -8
- package/.claude/commands/github/github-modes.md +9 -5
- package/.claude/commands/github/issue-tracker.md +34 -33
- package/.claude/commands/github/pr-manager.md +20 -17
- package/.claude/commands/github/release-manager.md +37 -49
- package/.claude/commands/github/repo-architect.md +39 -41
- package/.claude/commands/github/sync-coordinator.md +45 -49
- package/.claude/commands/hive-mind/README.md +42 -17
- package/.claude/commands/hive-mind/hive-mind-consensus.md +68 -4
- package/.claude/commands/hive-mind/hive-mind-init.md +55 -5
- package/.claude/commands/hive-mind/hive-mind-memory.md +69 -4
- package/.claude/commands/hive-mind/hive-mind-spawn.md +71 -10
- package/.claude/commands/hive-mind/hive-mind-status.md +52 -4
- package/.claude/commands/hive-mind/hive-mind-stop.md +51 -4
- package/.claude/commands/hive-mind/hive-mind.md +74 -14
- package/.claude/commands/hooks/README.md +62 -7
- package/.claude/commands/hooks/overview.md +94 -35
- package/.claude/commands/hooks/post-edit.md +48 -87
- package/.claude/commands/hooks/post-task.md +37 -87
- package/.claude/commands/hooks/pre-edit.md +52 -84
- package/.claude/commands/hooks/pre-task.md +46 -81
- package/.claude/commands/hooks/session-end.md +49 -85
- package/.claude/commands/hooks/setup.md +87 -58
- package/.claude/commands/mastermind/_repeat.md +308 -0
- package/.claude/commands/mastermind/architect.md +49 -0
- package/.claude/commands/mastermind/brain.md +98 -0
- package/.claude/commands/mastermind/build.md +22 -0
- package/.claude/commands/mastermind/content.md +22 -0
- package/.claude/commands/mastermind/createorg.md +94 -0
- package/.claude/commands/mastermind/finance.md +22 -0
- package/.claude/commands/mastermind/idea.md +22 -0
- package/.claude/commands/mastermind/marketing.md +22 -0
- package/.claude/commands/mastermind/master.md +379 -0
- package/.claude/commands/mastermind/ops.md +22 -0
- package/.claude/commands/mastermind/release.md +22 -0
- package/.claude/commands/mastermind/research.md +22 -0
- package/.claude/commands/mastermind/review.md +22 -0
- package/.claude/commands/mastermind/runorg.md +106 -0
- package/.claude/commands/mastermind/sales.md +22 -0
- package/.claude/commands/mastermind/techport.md +17 -0
- package/.claude/commands/memory/README.md +75 -5
- package/.claude/commands/memory/memory-search.md +63 -11
- package/.claude/commands/monitoring/README.md +64 -4
- package/.claude/commands/monitoring/agent-metrics.md +50 -10
- package/.claude/commands/monitoring/agents.md +59 -32
- package/.claude/commands/monitoring/status.md +96 -34
- package/.claude/commands/monograph/README.md +102 -0
- package/.claude/commands/monograph/monograph-build.md +79 -0
- package/.claude/commands/monograph/monograph-search.md +96 -0
- package/.claude/commands/monograph/monograph-stats.md +53 -0
- package/.claude/commands/monograph/monograph-watch.md +63 -0
- package/.claude/commands/monograph/monograph-wiki.md +91 -0
- package/.claude/commands/monomind/createtask.md +277 -0
- package/.claude/commands/{monomind-do.md → monomind/do.md} +21 -8
- package/.claude/commands/monomind/help.md +118 -0
- package/.claude/commands/{monomind-idea.md → monomind/idea.md} +22 -28
- package/.claude/commands/{monomind-improve.md → monomind/improve.md} +21 -27
- package/.claude/commands/monomind/memory.md +230 -0
- package/.claude/commands/monomind/repeat.md +201 -0
- package/.claude/commands/monomind/review.md +313 -0
- package/.claude/commands/monomind/specialagents.md +125 -0
- package/.claude/commands/monomind/swarm.md +161 -0
- package/.claude/commands/monomind/understand.md +148 -0
- package/.claude/commands/optimization/README.md +69 -5
- package/.claude/commands/optimization/auto-topology.md +66 -43
- package/.claude/commands/optimization/parallel-execution.md +65 -39
- package/.claude/commands/optimization/performance-optimize.md +79 -0
- package/.claude/commands/pair/README.md +48 -230
- package/.claude/commands/pair/examples.md +85 -441
- package/.claude/commands/pair/modes.md +77 -303
- package/.claude/commands/pair/session.md +76 -359
- package/.claude/commands/sparc/analyzer.md +9 -26
- package/.claude/commands/sparc/architect.md +8 -25
- package/.claude/commands/sparc/ask.md +27 -68
- package/.claude/commands/sparc/batch-executor.md +8 -25
- package/.claude/commands/sparc/code.md +12 -53
- package/.claude/commands/sparc/coder.md +8 -25
- package/.claude/commands/sparc/debug.md +12 -53
- package/.claude/commands/sparc/debugger.md +8 -25
- package/.claude/commands/sparc/designer.md +8 -25
- package/.claude/commands/sparc/devops.md +16 -57
- package/.claude/commands/sparc/docs-writer.md +12 -53
- package/.claude/commands/sparc/documenter.md +8 -25
- package/.claude/commands/sparc/innovator.md +8 -25
- package/.claude/commands/sparc/integration.md +12 -53
- package/.claude/commands/sparc/mcp.md +12 -53
- package/.claude/commands/sparc/memory-manager.md +28 -25
- package/.claude/commands/sparc/optimizer.md +8 -25
- package/.claude/commands/sparc/orchestrator.md +35 -97
- package/.claude/commands/sparc/post-deployment-monitoring-mode.md +13 -54
- package/.claude/commands/sparc/refinement-optimization-mode.md +13 -54
- package/.claude/commands/sparc/researcher.md +8 -25
- package/.claude/commands/sparc/reviewer.md +8 -25
- package/.claude/commands/sparc/security-review.md +13 -54
- package/.claude/commands/sparc/sparc-modes.md +97 -151
- package/.claude/commands/sparc/sparc.md +16 -56
- package/.claude/commands/sparc/spec-pseudocode.md +13 -54
- package/.claude/commands/sparc/supabase-admin.md +19 -66
- package/.claude/commands/sparc/swarm-coordinator.md +21 -25
- package/.claude/commands/sparc/tdd.md +8 -25
- package/.claude/commands/sparc/tester.md +8 -25
- package/.claude/commands/sparc/tutorial.md +12 -53
- package/.claude/commands/sparc/workflow-manager.md +8 -25
- package/.claude/commands/sparc.md +76 -130
- package/.claude/commands/stream-chain/pipeline.md +72 -77
- package/.claude/commands/stream-chain/run.md +133 -47
- package/.claude/commands/swarm/README.md +37 -12
- package/.claude/commands/swarm/analysis.md +47 -69
- package/.claude/commands/swarm/development.md +45 -69
- package/.claude/commands/swarm/examples.md +77 -142
- package/.claude/commands/swarm/maintenance.md +47 -74
- package/.claude/commands/swarm/optimization.md +54 -87
- package/.claude/commands/swarm/research.md +47 -107
- package/.claude/commands/swarm/swarm-analysis.md +58 -4
- package/.claude/commands/swarm/swarm-background.md +61 -4
- package/.claude/commands/swarm/swarm-modes.md +63 -4
- package/.claude/commands/swarm/swarm-monitor.md +50 -4
- package/.claude/commands/swarm/swarm-status.md +40 -4
- package/.claude/commands/swarm/swarm-strategies.md +73 -5
- package/.claude/commands/swarm/swarm.md +70 -18
- package/.claude/commands/swarm/testing.md +51 -102
- package/.claude/commands/tokens.md +6 -1
- package/.claude/commands/training/README.md +36 -6
- package/.claude/commands/training/model-update.md +68 -15
- package/.claude/commands/training/neural-patterns.md +54 -55
- package/.claude/commands/training/neural-train.md +70 -16
- package/.claude/commands/training/pattern-learn.md +60 -16
- package/.claude/commands/training/specialization.md +78 -49
- package/.claude/commands/truth/start.md +87 -109
- package/.claude/commands/ts.md +7 -2
- package/.claude/commands/verify/check.md +90 -34
- package/.claude/commands/verify/start.md +71 -94
- package/.claude/commands/workflows/README.md +62 -6
- package/.claude/commands/workflows/development.md +69 -61
- package/.claude/commands/workflows/research.md +73 -47
- package/.claude/commands/workflows/workflow-create.md +75 -16
- package/.claude/commands/workflows/workflow-execute.md +94 -16
- package/.claude/commands/workflows/workflow-export.md +81 -16
- package/.claude/helpers/control-start.cjs +91 -0
- package/.claude/helpers/extras-registry.json +4104 -1991
- package/.claude/helpers/graphify-freshen.cjs +44 -13
- package/.claude/helpers/hook-handler.cjs +256 -1
- package/.claude/helpers/learning-service.mjs +0 -0
- package/.claude/helpers/loop-tracker.cjs +107 -0
- package/.claude/helpers/metrics-db.mjs +0 -0
- package/.claude/helpers/router.cjs +48 -68
- package/.claude/helpers/skill-registry.json +89 -104
- package/.claude/helpers/statusline.cjs +33 -2
- package/.claude/helpers/swarm-hooks.sh +0 -0
- package/.claude/scheduled_tasks.lock +1 -0
- package/.claude/settings.json +15 -0
- package/.claude/skills/.monomind/data/ranked-context.json +5 -0
- package/.claude/skills/.monomind/sessions/current.json +13 -0
- package/.claude/skills/.monomind/sessions/session-1777829336455.json +15 -0
- package/.claude/skills/.monomind/sessions/session-1777831614725.json +15 -0
- package/.claude/skills/.monomind/sessions/session-1777832095857.json +15 -0
- package/.claude/skills/.monomind/sessions/session-1777839814183.json +15 -0
- package/.claude/skills/.monomind/sessions/session-1777841847131.json +15 -0
- package/.claude/skills/.monomind/sessions/session-1777843309463.json +15 -0
- package/.claude/skills/.monomind/sessions/session-1777880867159.json +15 -0
- package/.claude/skills/.monomind/sessions/session-1777881884593.json +15 -0
- package/.claude/skills/.monomind/sessions/session-1777884090471.json +15 -0
- package/.claude/skills/.monomind/sessions/session-1777884808221.json +15 -0
- package/.claude/skills/.monomind/sessions/session-1777885672155.json +15 -0
- package/.claude/skills/.monomind/sessions/session-1777886852818.json +15 -0
- package/.claude/skills/.monomind/sessions/session-1777896532690.json +15 -0
- package/.claude/skills/agentdb-advanced/SKILL.md +11 -12
- package/.claude/skills/agentdb-learning/SKILL.md +20 -21
- package/.claude/skills/agentdb-memory-patterns/SKILL.md +28 -30
- package/.claude/skills/agentdb-optimization/SKILL.md +11 -12
- package/.claude/skills/agentdb-vector-search/SKILL.md +37 -41
- package/.claude/skills/{v3-integration-deep → agentic-integration}/SKILL.md +20 -13
- package/.claude/skills/agentic-jujutsu/SKILL.md +22 -22
- package/.claude/skills/{v3-cli-modernization → cli-modernization}/SKILL.md +17 -8
- package/.claude/skills/{v3-core-implementation → core-implementation}/SKILL.md +33 -8
- package/.claude/skills/{v3-ddd-architecture → ddd-architecture}/SKILL.md +18 -25
- package/.claude/skills/github-code-review/SKILL.md +82 -83
- package/.claude/skills/github-multi-repo/SKILL.md +42 -46
- package/.claude/skills/github-project-management/SKILL.md +83 -88
- package/.claude/skills/github-release-management/SKILL.md +12 -18
- package/.claude/skills/github-workflow-automation/SKILL.md +70 -74
- package/.claude/skills/hooks-automation/SKILL.md +9 -13
- package/.claude/skills/mastermind/_intake.md +83 -0
- package/.claude/skills/mastermind/_protocol.md +275 -0
- package/.claude/skills/mastermind/architect.md +847 -0
- package/.claude/skills/mastermind/build.md +158 -0
- package/.claude/skills/mastermind/content.md +185 -0
- package/.claude/skills/mastermind/createorg.md +318 -0
- package/.claude/skills/mastermind/finance.md +154 -0
- package/.claude/skills/mastermind/idea.md +158 -0
- package/.claude/skills/mastermind/marketing.md +216 -0
- package/.claude/skills/mastermind/monotask.md +350 -0
- package/.claude/skills/mastermind/ops.md +156 -0
- package/.claude/skills/mastermind/references/copywriting-frameworks.md +181 -0
- package/.claude/skills/mastermind/references/persuasion-psychology.md +158 -0
- package/.claude/skills/mastermind/release.md +156 -0
- package/.claude/skills/mastermind/research.md +156 -0
- package/.claude/skills/mastermind/review.md +157 -0
- package/.claude/skills/mastermind/runorg.md +308 -0
- package/.claude/skills/mastermind/sales.md +158 -0
- package/.claude/skills/mastermind/techport.md +743 -0
- package/.claude/skills/{v3-mcp-optimization → mcp-optimization}/SKILL.md +35 -14
- package/.claude/skills/{v3-memory-unification → memory-unification}/SKILL.md +20 -4
- package/.claude/skills/monodesign/SKILL.md +302 -0
- package/.claude/skills/monodesign/reference/adapt.md +190 -0
- package/.claude/skills/monodesign/reference/animate.md +175 -0
- package/.claude/skills/monodesign/reference/antipatterns-catalog.md +187 -0
- package/.claude/skills/monodesign/reference/audit.md +133 -0
- package/.claude/skills/monodesign/reference/bolder.md +113 -0
- package/.claude/skills/monodesign/reference/brand-workflow.md +180 -0
- package/.claude/skills/monodesign/reference/brand.md +114 -0
- package/.claude/skills/monodesign/reference/clarify.md +174 -0
- package/.claude/skills/monodesign/reference/cognitive-load.md +106 -0
- package/.claude/skills/monodesign/reference/color-and-contrast.md +105 -0
- package/.claude/skills/monodesign/reference/colorize.md +154 -0
- package/.claude/skills/monodesign/reference/component-specs.md +260 -0
- package/.claude/skills/monodesign/reference/component-states.md +274 -0
- package/.claude/skills/monodesign/reference/component-system.md +358 -0
- package/.claude/skills/monodesign/reference/copy-formulas.md +160 -0
- package/.claude/skills/monodesign/reference/craft.md +193 -0
- package/.claude/skills/monodesign/reference/critique.md +213 -0
- package/.claude/skills/monodesign/reference/delight.md +302 -0
- package/.claude/skills/monodesign/reference/design-principles.md +246 -0
- package/.claude/skills/monodesign/reference/distill.md +111 -0
- package/.claude/skills/monodesign/reference/document.md +427 -0
- package/.claude/skills/monodesign/reference/extract.md +69 -0
- package/.claude/skills/monodesign/reference/harden.md +347 -0
- package/.claude/skills/monodesign/reference/heuristics-scoring.md +234 -0
- package/.claude/skills/monodesign/reference/image-prompts.md +118 -0
- package/.claude/skills/monodesign/reference/interaction-design.md +195 -0
- package/.claude/skills/monodesign/reference/layout.md +141 -0
- package/.claude/skills/monodesign/reference/live.md +622 -0
- package/.claude/skills/monodesign/reference/motion-design.md +109 -0
- package/.claude/skills/monodesign/reference/onboard.md +234 -0
- package/.claude/skills/monodesign/reference/optimize.md +258 -0
- package/.claude/skills/monodesign/reference/overdrive.md +130 -0
- package/.claude/skills/monodesign/reference/personas.md +179 -0
- package/.claude/skills/monodesign/reference/polish.md +233 -0
- package/.claude/skills/monodesign/reference/pre-delivery-checklist.md +108 -0
- package/.claude/skills/monodesign/reference/product.md +62 -0
- package/.claude/skills/monodesign/reference/quieter.md +99 -0
- package/.claude/skills/monodesign/reference/responsive-design.md +114 -0
- package/.claude/skills/monodesign/reference/shape.md +151 -0
- package/.claude/skills/monodesign/reference/spatial-design.md +100 -0
- package/.claude/skills/monodesign/reference/teach.md +156 -0
- package/.claude/skills/monodesign/reference/token-architecture.md +222 -0
- package/.claude/skills/monodesign/reference/typeset.md +124 -0
- package/.claude/skills/monodesign/reference/typography.md +159 -0
- package/.claude/skills/monodesign/reference/ux-research.md +143 -0
- package/.claude/skills/monodesign/reference/ux-rules.md +211 -0
- package/.claude/skills/monodesign/reference/ux-writing.md +107 -0
- package/.claude/skills/monomotion/SKILL.md +145 -0
- package/.claude/skills/monomotion/rules/api-control.md +139 -0
- package/.claude/skills/monomotion/rules/effects.md +109 -0
- package/.claude/skills/monomotion/rules/integration.md +140 -0
- package/.claude/skills/monomotion/rules/scroll.md +131 -0
- package/.claude/skills/monomotion/rules/sequencing.md +105 -0
- package/.claude/skills/monomotion/rules/svg.md +101 -0
- package/.claude/skills/monomotion/rules/text.md +119 -0
- package/.claude/skills/pair-programming/SKILL.md +1 -1
- package/.claude/skills/performance-analysis/SKILL.md +3 -3
- package/.claude/skills/{v3-performance-optimization → performance-optimization}/SKILL.md +16 -8
- package/.claude/skills/reasoningbank-agentdb/SKILL.md +17 -19
- package/.claude/skills/reasoningbank-intelligence/SKILL.md +4 -6
- package/.claude/skills/{v3-security-overhaul → security-hardening}/SKILL.md +13 -3
- package/.claude/skills/skill-builder/SKILL.md +19 -19
- package/.claude/skills/sparc-methodology/SKILL.md +55 -211
- package/.claude/skills/stop-slop/SKILL.md +67 -0
- package/.claude/skills/stop-slop/references/examples.md +61 -0
- package/.claude/skills/stop-slop/references/phrases.md +130 -0
- package/.claude/skills/stop-slop/references/structures.md +136 -0
- package/.claude/skills/swarm-advanced/SKILL.md +13 -43
- package/.claude/skills/{v3-swarm-coordination → swarm-coordination}/SKILL.md +39 -21
- package/.claude/skills/swarm-orchestration/SKILL.md +12 -12
- package/.claude/skills/verification-quality/SKILL.md +5 -5
- package/.claude/statusline-command.sh +0 -0
- package/.claude/statusline.sh +0 -0
- package/.claude-plugin/scripts/install.sh +0 -0
- package/.claude-plugin/scripts/uninstall.sh +0 -0
- package/.claude-plugin/scripts/verify.sh +0 -0
- package/README.md +5 -5
- package/package.json +17 -17
- package/packages/@monomind/cli/README.md +441 -0
- package/packages/@monomind/cli/bin/cli.js +78 -13
- package/packages/@monomind/cli/bin/mcp-server.js +0 -0
- package/packages/@monomind/cli/dist/src/agents/halt-signal.js +33 -7
- package/packages/@monomind/cli/dist/src/agents/managed-agent.js +5 -2
- package/packages/@monomind/cli/dist/src/agents/prompt-experiment.d.ts +3 -2
- package/packages/@monomind/cli/dist/src/agents/prompt-experiment.js +1 -1
- package/packages/@monomind/cli/dist/src/agents/prompt-version-manager.d.ts +5 -2
- package/packages/@monomind/cli/dist/src/agents/prompt-version-manager.js +26 -4
- package/packages/@monomind/cli/dist/src/agents/specialization-scorer.js +17 -9
- package/packages/@monomind/cli/dist/src/agents/trigger-scanner.d.ts +5 -3
- package/packages/@monomind/cli/dist/src/agents/trigger-scanner.js +58 -10
- package/packages/@monomind/cli/dist/src/agents/version-store.d.ts +0 -1
- package/packages/@monomind/cli/dist/src/agents/version-store.js +44 -21
- package/packages/@monomind/cli/dist/src/autopilot-state.js +79 -28
- package/packages/@monomind/cli/dist/src/benchmarks/benchmark-runner.d.ts +7 -2
- package/packages/@monomind/cli/dist/src/benchmarks/benchmark-runner.js +20 -8
- package/packages/@monomind/cli/dist/src/benchmarks/metric-evaluators.d.ts +2 -1
- package/packages/@monomind/cli/dist/src/benchmarks/metric-evaluators.js +25 -2
- package/packages/@monomind/cli/dist/src/commands/agent.js +6 -4
- package/packages/@monomind/cli/dist/src/commands/appliance-advanced.js +23 -0
- package/packages/@monomind/cli/dist/src/commands/autopilot.js +3 -3
- package/packages/@monomind/cli/dist/src/commands/benchmark.js +119 -8
- package/packages/@monomind/cli/dist/src/commands/claims.js +22 -14
- package/packages/@monomind/cli/dist/src/commands/config.js +32 -0
- package/packages/@monomind/cli/dist/src/commands/daemon.js +13 -11
- package/packages/@monomind/cli/dist/src/commands/deployment.js +21 -2
- package/packages/@monomind/cli/dist/src/commands/doctor.js +5 -4
- package/packages/@monomind/cli/dist/src/commands/embeddings.js +124 -48
- package/packages/@monomind/cli/dist/src/commands/hive-mind.js +15 -14
- package/packages/@monomind/cli/dist/src/commands/hooks.js +45 -41
- package/packages/@monomind/cli/dist/src/commands/index.d.ts +2 -0
- package/packages/@monomind/cli/dist/src/commands/index.js +20 -7
- package/packages/@monomind/cli/dist/src/commands/init.js +53 -19
- package/packages/@monomind/cli/dist/src/commands/mcp.js +31 -44
- package/packages/@monomind/cli/dist/src/commands/memory.js +47 -15
- package/packages/@monomind/cli/dist/src/commands/migrate.js +156 -108
- package/packages/@monomind/cli/dist/src/commands/monograph.d.ts +8 -0
- package/packages/@monomind/cli/dist/src/commands/monograph.js +526 -0
- package/packages/@monomind/cli/dist/src/commands/neural.js +96 -56
- package/packages/@monomind/cli/dist/src/commands/performance.js +30 -8
- package/packages/@monomind/cli/dist/src/commands/plugins.js +13 -37
- package/packages/@monomind/cli/dist/src/commands/process.js +25 -2
- package/packages/@monomind/cli/dist/src/commands/providers.js +37 -5
- package/packages/@monomind/cli/dist/src/commands/replay.js +4 -4
- package/packages/@monomind/cli/dist/src/commands/route.js +37 -5
- package/packages/@monomind/cli/dist/src/commands/ruvector/import.js +12 -2
- package/packages/@monomind/cli/dist/src/commands/ruvector/init.js +15 -0
- package/packages/@monomind/cli/dist/src/commands/ruvector/status.js +16 -3
- package/packages/@monomind/cli/dist/src/commands/security.js +342 -193
- package/packages/@monomind/cli/dist/src/commands/session.js +51 -8
- package/packages/@monomind/cli/dist/src/commands/start.js +18 -4
- package/packages/@monomind/cli/dist/src/commands/swarm.js +47 -36
- package/packages/@monomind/cli/dist/src/commands/tokens.js +11 -11
- package/packages/@monomind/cli/dist/src/commands/transfer-store.js +1 -1
- package/packages/@monomind/cli/dist/src/commands/workflow.js +31 -4
- package/packages/@monomind/cli/dist/src/config-adapter.d.ts +2 -1
- package/packages/@monomind/cli/dist/src/consensus/audit-writer.js +46 -13
- package/packages/@monomind/cli/dist/src/consensus/vote-signer.d.ts +0 -3
- package/packages/@monomind/cli/dist/src/consensus/vote-signer.js +9 -1
- package/packages/@monomind/cli/dist/src/dlq/dlq-reader.d.ts +4 -2
- package/packages/@monomind/cli/dist/src/dlq/dlq-reader.js +25 -8
- package/packages/@monomind/cli/dist/src/dlq/dlq-replayer.d.ts +10 -3
- package/packages/@monomind/cli/dist/src/dlq/dlq-replayer.js +50 -16
- package/packages/@monomind/cli/dist/src/dlq/dlq-writer.js +27 -5
- package/packages/@monomind/cli/dist/src/eval/dataset-manager.d.ts +2 -2
- package/packages/@monomind/cli/dist/src/eval/dataset-manager.js +26 -16
- package/packages/@monomind/cli/dist/src/eval/trace-collector.js +23 -3
- package/packages/@monomind/cli/dist/src/index.js +12 -10
- package/packages/@monomind/cli/dist/src/init/claudemd-generator.js +8 -8
- package/packages/@monomind/cli/dist/src/init/executor.js +153 -70
- package/packages/@monomind/cli/dist/src/init/helpers-generator.js +35 -22
- package/packages/@monomind/cli/dist/src/init/mcp-generator.js +3 -3
- package/packages/@monomind/cli/dist/src/init/settings-generator.js +10 -3
- package/packages/@monomind/cli/dist/src/init/shared-instructions-generator.js +18 -3
- package/packages/@monomind/cli/dist/src/init/statusline-generator.js +3 -1
- package/packages/@monomind/cli/dist/src/init/types.d.ts +35 -11
- package/packages/@monomind/cli/dist/src/init/types.js +5 -9
- package/packages/@monomind/cli/dist/src/interactive/interrupt.js +8 -3
- package/packages/@monomind/cli/dist/src/mcp/tool-registry.js +38 -4
- package/packages/@monomind/cli/dist/src/mcp-client.js +10 -4
- package/packages/@monomind/cli/dist/src/mcp-server.d.ts +9 -2
- package/packages/@monomind/cli/dist/src/mcp-server.js +182 -35
- package/packages/@monomind/cli/dist/src/mcp-tools/agent-tools.js +66 -34
- package/packages/@monomind/cli/dist/src/mcp-tools/agentdb-tools.js +34 -7
- package/packages/@monomind/cli/dist/src/mcp-tools/analyze-tools.js +25 -16
- package/packages/@monomind/cli/dist/src/mcp-tools/auto-install.js +4 -6
- package/packages/@monomind/cli/dist/src/mcp-tools/autopilot-tools.js +12 -2
- package/packages/@monomind/cli/dist/src/mcp-tools/browser-tools.js +199 -20
- package/packages/@monomind/cli/dist/src/mcp-tools/claims-tools.js +68 -18
- package/packages/@monomind/cli/dist/src/mcp-tools/config-tools.js +33 -5
- package/packages/@monomind/cli/dist/src/mcp-tools/coordination-tools.js +59 -4
- package/packages/@monomind/cli/dist/src/mcp-tools/daa-tools.js +46 -10
- package/packages/@monomind/cli/dist/src/mcp-tools/embeddings-tools.js +46 -5
- package/packages/@monomind/cli/dist/src/mcp-tools/github-tools.js +29 -16
- package/packages/@monomind/cli/dist/src/mcp-tools/guidance-tools.js +38 -10
- package/packages/@monomind/cli/dist/src/mcp-tools/hive-mind-tools.js +96 -33
- package/packages/@monomind/cli/dist/src/mcp-tools/hooks-tools.js +70 -37
- package/packages/@monomind/cli/dist/src/mcp-tools/memory-tools.js +29 -13
- package/packages/@monomind/cli/dist/src/mcp-tools/monograph-tools.js +5867 -56
- package/packages/@monomind/cli/dist/src/mcp-tools/neural-tools.js +121 -37
- package/packages/@monomind/cli/dist/src/mcp-tools/performance-tools.js +21 -8
- package/packages/@monomind/cli/dist/src/mcp-tools/progress-tools.js +10 -8
- package/packages/@monomind/cli/dist/src/mcp-tools/request-tracker.js +4 -1
- package/packages/@monomind/cli/dist/src/mcp-tools/ruvllm-tools.js +19 -8
- package/packages/@monomind/cli/dist/src/mcp-tools/session-tools.js +57 -17
- package/packages/@monomind/cli/dist/src/mcp-tools/swarm-tools.js +35 -17
- package/packages/@monomind/cli/dist/src/mcp-tools/system-tools.js +4 -3
- package/packages/@monomind/cli/dist/src/mcp-tools/task-tools.js +53 -13
- package/packages/@monomind/cli/dist/src/mcp-tools/terminal-tools.js +63 -14
- package/packages/@monomind/cli/dist/src/mcp-tools/transfer-tools.js +21 -16
- package/packages/@monomind/cli/dist/src/mcp-tools/workflow-tools.js +92 -23
- package/packages/@monomind/cli/dist/src/memory/ewc-consolidation.js +41 -10
- package/packages/@monomind/cli/dist/src/memory/intelligence.d.ts +2 -2
- package/packages/@monomind/cli/dist/src/memory/intelligence.js +39 -13
- package/packages/@monomind/cli/dist/src/memory/memory-bridge.d.ts +1 -0
- package/packages/@monomind/cli/dist/src/memory/memory-bridge.js +149 -56
- package/packages/@monomind/cli/dist/src/memory/memory-initializer.js +107 -45
- package/packages/@monomind/cli/dist/src/memory/sona-optimizer.d.ts +8 -1
- package/packages/@monomind/cli/dist/src/memory/sona-optimizer.js +25 -8
- package/packages/@monomind/cli/dist/src/observability/replay-reader.d.ts +40 -0
- package/packages/@monomind/cli/dist/src/observability/replay-reader.js +138 -0
- package/packages/@monomind/cli/dist/src/orchestration/routing-modes.js +35 -5
- package/packages/@monomind/cli/dist/src/parser.d.ts +8 -0
- package/packages/@monomind/cli/dist/src/parser.js +48 -14
- package/packages/@monomind/cli/dist/src/plugins/manager.js +112 -19
- package/packages/@monomind/cli/dist/src/plugins/store/discovery.d.ts +1 -1
- package/packages/@monomind/cli/dist/src/plugins/store/discovery.js +80 -62
- package/packages/@monomind/cli/dist/src/production/circuit-breaker.js +8 -1
- package/packages/@monomind/cli/dist/src/production/error-handler.d.ts +4 -2
- package/packages/@monomind/cli/dist/src/production/error-handler.js +27 -5
- package/packages/@monomind/cli/dist/src/production/monitoring.js +8 -4
- package/packages/@monomind/cli/dist/src/production/rate-limiter.js +30 -22
- package/packages/@monomind/cli/dist/src/ruvector/agent-wasm.js +2 -2
- package/packages/@monomind/cli/dist/src/ruvector/coverage-router.js +19 -9
- package/packages/@monomind/cli/dist/src/ruvector/diff-classifier.d.ts +1 -0
- package/packages/@monomind/cli/dist/src/ruvector/diff-classifier.js +26 -6
- package/packages/@monomind/cli/dist/src/ruvector/enhanced-model-router.js +24 -2
- package/packages/@monomind/cli/dist/src/ruvector/index.d.ts +1 -2
- package/packages/@monomind/cli/dist/src/ruvector/index.js +2 -2
- package/packages/@monomind/cli/dist/src/ruvector/model-router.d.ts +4 -2
- package/packages/@monomind/cli/dist/src/ruvector/model-router.js +30 -6
- package/packages/@monomind/cli/dist/src/ruvector/moe-router.d.ts +7 -0
- package/packages/@monomind/cli/dist/src/ruvector/moe-router.js +35 -12
- package/packages/@monomind/cli/dist/src/ruvector/q-learning-router.d.ts +7 -1
- package/packages/@monomind/cli/dist/src/ruvector/q-learning-router.js +40 -9
- package/packages/@monomind/cli/dist/src/services/claim-service.d.ts +3 -1
- package/packages/@monomind/cli/dist/src/services/claim-service.js +33 -2
- package/packages/@monomind/cli/dist/src/services/config-file-manager.d.ts +16 -2
- package/packages/@monomind/cli/dist/src/services/config-file-manager.js +105 -17
- package/packages/@monomind/cli/dist/src/services/container-worker-pool.js +51 -11
- package/packages/@monomind/cli/dist/src/services/headless-worker-executor.d.ts +7 -0
- package/packages/@monomind/cli/dist/src/services/headless-worker-executor.js +188 -45
- package/packages/@monomind/cli/dist/src/services/registry-api.js +62 -9
- package/packages/@monomind/cli/dist/src/services/ruvector-training.js +8 -0
- package/packages/@monomind/cli/dist/src/services/worker-daemon.d.ts +4 -1
- package/packages/@monomind/cli/dist/src/services/worker-daemon.js +112 -28
- package/packages/@monomind/cli/dist/src/services/worker-queue.d.ts +9 -2
- package/packages/@monomind/cli/dist/src/services/worker-queue.js +86 -5
- package/packages/@monomind/cli/dist/src/suggest.js +9 -0
- package/packages/@monomind/cli/dist/src/swarm/flow-enforcer.d.ts +5 -3
- package/packages/@monomind/cli/dist/src/swarm/flow-enforcer.js +17 -5
- package/packages/@monomind/cli/dist/src/swarm/flow-visualizer.d.ts +3 -0
- package/packages/@monomind/cli/dist/src/swarm/flow-visualizer.js +30 -6
- package/packages/@monomind/cli/dist/src/transfer/anonymization/index.js +5 -3
- package/packages/@monomind/cli/dist/src/transfer/export.js +5 -3
- package/packages/@monomind/cli/dist/src/transfer/ipfs/client.js +84 -7
- package/packages/@monomind/cli/dist/src/transfer/ipfs/upload.js +13 -4
- package/packages/@monomind/cli/dist/src/transfer/storage/gcs.js +19 -10
- package/packages/@monomind/cli/dist/src/transfer/store/discovery.d.ts +9 -2
- package/packages/@monomind/cli/dist/src/transfer/store/discovery.js +68 -13
- package/packages/@monomind/cli/dist/src/transfer/store/download.d.ts +15 -6
- package/packages/@monomind/cli/dist/src/transfer/store/download.js +113 -24
- package/packages/@monomind/cli/dist/src/transfer/store/publish.d.ts +1 -1
- package/packages/@monomind/cli/dist/src/transfer/store/publish.js +13 -14
- package/packages/@monomind/cli/dist/src/transfer/store/registry.d.ts +3 -3
- package/packages/@monomind/cli/dist/src/transfer/store/registry.js +32 -16
- package/packages/@monomind/cli/dist/src/update/checker.js +17 -4
- package/packages/@monomind/cli/dist/src/update/executor.js +25 -20
- package/packages/@monomind/cli/dist/src/update/rate-limiter.d.ts +11 -0
- package/packages/@monomind/cli/dist/src/update/rate-limiter.js +23 -3
- package/packages/@monomind/cli/dist/src/utils/parse-jsonl.d.ts +6 -0
- package/packages/@monomind/cli/dist/src/utils/parse-jsonl.js +22 -0
- package/packages/@monomind/cli/dist/src/workflow/condition-evaluator.js +37 -3
- package/packages/@monomind/cli/dist/src/workflow/dag-builder.js +27 -11
- package/packages/@monomind/cli/dist/src/workflow/dag-executor.js +51 -13
- package/packages/@monomind/cli/dist/src/workflow/dsl-schema.d.ts +3 -0
- package/packages/@monomind/cli/dist/src/workflow/dsl-schema.js +6 -2
- package/packages/@monomind/cli/dist/src/workflow/template-engine.js +7 -0
- package/packages/@monomind/cli/dist/src/workflow/workflow-executor.js +95 -14
- package/packages/@monomind/cli/package.json +5 -3
- package/packages/@monomind/guidance/README.md +1192 -0
- package/packages/@monomind/shared/README.md +322 -0
- package/packages/@monomind/shared/dist/types/consensus-audit.d.ts +3 -1
- package/packages/README.md +513 -0
- package/.claude/agents/design/design-brand-guardian.md +0 -323
- package/.claude/agents/design/design-image-prompt-engineer.md +0 -237
- package/.claude/agents/design/design-inclusive-visuals-specialist.md +0 -72
- package/.claude/agents/design/design-ui-designer.md +0 -384
- package/.claude/agents/design/design-ux-architect.md +0 -470
- package/.claude/agents/design/design-ux-researcher.md +0 -330
- package/.claude/agents/design/design-visual-storyteller.md +0 -150
- package/.claude/agents/design/design-whimsy-injector.md +0 -439
- package/.claude/agents/v3/integration-architect.md +0 -338
- package/.claude/commands/analysis/COMMAND_COMPLIANCE_REPORT.md +0 -54
- package/.claude/commands/coordination/init.md +0 -44
- package/.claude/commands/coordination/orchestrate.md +0 -43
- package/.claude/commands/coordination/spawn.md +0 -45
- package/.claude/commands/github/code-review-swarm.md +0 -550
- package/.claude/commands/github/code-review.md +0 -25
- package/.claude/commands/github/github-swarm.md +0 -121
- package/.claude/commands/github/issue-triage.md +0 -25
- package/.claude/commands/github/multi-repo-swarm.md +0 -519
- package/.claude/commands/github/pr-enhance.md +0 -26
- package/.claude/commands/github/project-board-sync.md +0 -471
- package/.claude/commands/github/release-swarm.md +0 -590
- package/.claude/commands/github/repo-analyze.md +0 -25
- package/.claude/commands/github/swarm-issue.md +0 -482
- package/.claude/commands/github/swarm-pr.md +0 -310
- package/.claude/commands/github/workflow-automation.md +0 -468
- package/.claude/commands/hive-mind/hive-mind-metrics.md +0 -8
- package/.claude/commands/hive-mind/hive-mind-resume.md +0 -8
- package/.claude/commands/hive-mind/hive-mind-sessions.md +0 -8
- package/.claude/commands/hive-mind/hive-mind-wizard.md +0 -8
- package/.claude/commands/list-agents.md +0 -17
- package/.claude/commands/memory/memory-persist.md +0 -25
- package/.claude/commands/memory/memory-usage.md +0 -25
- package/.claude/commands/memory/neural.md +0 -47
- package/.claude/commands/metrics.md +0 -11
- package/.claude/commands/monitoring/real-time-view.md +0 -25
- package/.claude/commands/monitoring/swarm-monitor.md +0 -25
- package/.claude/commands/monomind-createtask.md +0 -302
- package/.claude/commands/monomind-help.md +0 -103
- package/.claude/commands/monomind-memory.md +0 -107
- package/.claude/commands/monomind-repeat.md +0 -149
- package/.claude/commands/monomind-swarm.md +0 -205
- package/.claude/commands/optimization/cache-manage.md +0 -25
- package/.claude/commands/optimization/topology-optimize.md +0 -25
- package/.claude/commands/pair/commands.md +0 -546
- package/.claude/commands/pair/config.md +0 -510
- package/.claude/commands/pair/start.md +0 -209
- package/.claude/commands/use-agent.md +0 -67
- package/.claude/skills/monomind-createtask/SKILL.md +0 -269
- package/.claude/skills/monomind-task-engine/SKILL.md +0 -358
- /package/.claude/agents/{v3 → specialists}/memory-specialist.md +0 -0
- /package/.claude/agents/{v3 → specialists}/performance-engineer.md +0 -0
- /package/.claude/agents/{v3 → specialists}/queen-coordinator.md +0 -0
- /package/.claude/agents/{v3 → specialists}/security-architect.md +0 -0
|
@@ -18,10 +18,53 @@
|
|
|
18
18
|
*/
|
|
19
19
|
import * as path from 'path';
|
|
20
20
|
import * as crypto from 'crypto';
|
|
21
|
+
/**
|
|
22
|
+
* Validate a deserialized embedding before use in cosineSim/HNSW math.
|
|
23
|
+
*
|
|
24
|
+
* SECURITY: stored embeddings come from the same write path that any agent or
|
|
25
|
+
* imported pattern bundle can use. Without validation, an attacker can store an
|
|
26
|
+
* embedding of `[1e9 numbers]` (50 MB JSON parse cost), inject NaN values that
|
|
27
|
+
* poison ranking via NaN-comparison undefined behavior, or pass huge dimensions
|
|
28
|
+
* that make cosineSim O(N) per row blow up. The 1000-row search cap then
|
|
29
|
+
* amplifies a single poisoned row into multi-GB allocations on every search.
|
|
30
|
+
*
|
|
31
|
+
* Returns the parsed embedding when valid, or null when the JSON should be
|
|
32
|
+
* skipped (caller treats it like "no embedding stored").
|
|
33
|
+
*/
|
|
34
|
+
const MAX_EMBEDDING_DIMS = 8192;
|
|
35
|
+
const MAX_EMBEDDING_JSON_BYTES = MAX_EMBEDDING_DIMS * 32; // ~256KB ceiling
|
|
36
|
+
export function safeParseEmbedding(raw) {
|
|
37
|
+
if (typeof raw !== 'string' || raw.length === 0)
|
|
38
|
+
return null;
|
|
39
|
+
if (raw.length > MAX_EMBEDDING_JSON_BYTES)
|
|
40
|
+
return null;
|
|
41
|
+
let parsed;
|
|
42
|
+
try {
|
|
43
|
+
parsed = JSON.parse(raw);
|
|
44
|
+
}
|
|
45
|
+
catch {
|
|
46
|
+
return null;
|
|
47
|
+
}
|
|
48
|
+
if (!Array.isArray(parsed))
|
|
49
|
+
return null;
|
|
50
|
+
if (parsed.length === 0 || parsed.length > MAX_EMBEDDING_DIMS)
|
|
51
|
+
return null;
|
|
52
|
+
for (let i = 0; i < parsed.length; i++) {
|
|
53
|
+
const v = parsed[i];
|
|
54
|
+
if (typeof v !== 'number' || !Number.isFinite(v))
|
|
55
|
+
return null;
|
|
56
|
+
}
|
|
57
|
+
return parsed;
|
|
58
|
+
}
|
|
21
59
|
// ===== Lazy singleton =====
|
|
60
|
+
// registryInstance is typed as `any` because ControllerRegistry lives in @monomind/memory
|
|
61
|
+
// and cross-package type resolution is currently broken. When that is fixed, replace with
|
|
62
|
+
// the real import: import type { ControllerRegistry } from '@monomind/memory'.
|
|
22
63
|
let registryPromise = null;
|
|
23
64
|
let registryInstance = null;
|
|
24
65
|
let bridgeAvailable = null;
|
|
66
|
+
/** Backpressure flag for A-MEM Zettelkasten linking — see bridgeStoreEntry. */
|
|
67
|
+
let _amemInFlight = false;
|
|
25
68
|
/**
|
|
26
69
|
* Resolve database path with path traversal protection.
|
|
27
70
|
* Only allows paths within or below the project's .swarm directory,
|
|
@@ -34,9 +77,10 @@ function getDbPath(customPath) {
|
|
|
34
77
|
if (customPath === ':memory:')
|
|
35
78
|
return ':memory:';
|
|
36
79
|
const resolved = path.resolve(customPath);
|
|
37
|
-
// Ensure the path doesn't escape the working directory
|
|
80
|
+
// Ensure the path doesn't escape the working directory (path-separator-aware check)
|
|
38
81
|
const cwd = process.cwd();
|
|
39
|
-
|
|
82
|
+
const rel = path.relative(cwd, resolved);
|
|
83
|
+
if (rel.startsWith('..') || path.isAbsolute(rel)) {
|
|
40
84
|
return path.join(swarmDir, 'memory.db'); // fallback to safe default
|
|
41
85
|
}
|
|
42
86
|
return resolved;
|
|
@@ -49,7 +93,7 @@ function generateId(prefix) {
|
|
|
49
93
|
}
|
|
50
94
|
/**
|
|
51
95
|
* Lazily initialize the ControllerRegistry singleton.
|
|
52
|
-
* Returns null if @
|
|
96
|
+
* Returns null if @monomind/memory is not available.
|
|
53
97
|
*/
|
|
54
98
|
async function getRegistry(dbPath) {
|
|
55
99
|
if (bridgeAvailable === false)
|
|
@@ -59,7 +103,7 @@ async function getRegistry(dbPath) {
|
|
|
59
103
|
if (!registryPromise) {
|
|
60
104
|
registryPromise = (async () => {
|
|
61
105
|
try {
|
|
62
|
-
const { ControllerRegistry } = await import('@
|
|
106
|
+
const { ControllerRegistry } = await import('@monomind/memory');
|
|
63
107
|
const registry = new ControllerRegistry();
|
|
64
108
|
// Suppress noisy console.log during init
|
|
65
109
|
const origLog = console.log;
|
|
@@ -117,7 +161,7 @@ function bm25Score(queryTerms, docContent, avgDocLength, docCount, termDocFreqs)
|
|
|
117
161
|
const docLength = docWords.length;
|
|
118
162
|
let score = 0;
|
|
119
163
|
for (const term of queryTerms) {
|
|
120
|
-
const tf = docWords.filter(w => w === term
|
|
164
|
+
const tf = docWords.filter(w => w === term).length;
|
|
121
165
|
if (tf === 0)
|
|
122
166
|
continue;
|
|
123
167
|
const df = termDocFreqs.get(term) || 1;
|
|
@@ -229,6 +273,7 @@ async function logAttestation(registry, operation, entryId, metadata) {
|
|
|
229
273
|
// Non-fatal — attestation is observability, not correctness
|
|
230
274
|
}
|
|
231
275
|
}
|
|
276
|
+
const _dbInitialized = new WeakSet();
|
|
232
277
|
/**
|
|
233
278
|
* Get the AgentDB database handle and ensure memory_entries table exists.
|
|
234
279
|
* Returns null if not available.
|
|
@@ -238,6 +283,8 @@ function getDb(registry) {
|
|
|
238
283
|
if (!agentdb?.database)
|
|
239
284
|
return null;
|
|
240
285
|
const db = agentdb.database;
|
|
286
|
+
if (_dbInitialized.has(db))
|
|
287
|
+
return { db, agentdb };
|
|
241
288
|
// Ensure memory_entries table exists (idempotent)
|
|
242
289
|
try {
|
|
243
290
|
db.exec(`CREATE TABLE IF NOT EXISTS memory_entries (
|
|
@@ -286,6 +333,7 @@ function getDb(registry) {
|
|
|
286
333
|
catch {
|
|
287
334
|
// Table already exists or db is read-only — that's fine
|
|
288
335
|
}
|
|
336
|
+
_dbInitialized.add(db);
|
|
289
337
|
return { db, agentdb };
|
|
290
338
|
}
|
|
291
339
|
// ===== Bridge functions — match memory-initializer.ts signatures =====
|
|
@@ -302,7 +350,16 @@ export async function bridgeStoreEntry(options) {
|
|
|
302
350
|
if (!ctx)
|
|
303
351
|
return null;
|
|
304
352
|
try {
|
|
305
|
-
const { key, value, namespace = 'default', tags = [], ttl } = options;
|
|
353
|
+
const { key, value, namespace = 'default', tags: rawTags = [], ttl } = options;
|
|
354
|
+
// SECURITY: cap tags array length and per-tag length. Without these, any
|
|
355
|
+
// memory_store caller (every spawned agent) could submit
|
|
356
|
+
// tags: new Array(1e5).fill("x".repeat(1e4)) → ~1GB persisted blob,
|
|
357
|
+
// re-parsed on every bridgeGetEntry. Mirrors the embedding/BM25 caps.
|
|
358
|
+
const MAX_TAGS = 32;
|
|
359
|
+
const MAX_TAG_LEN = 64;
|
|
360
|
+
const tags = Array.isArray(rawTags)
|
|
361
|
+
? rawTags.filter(t => typeof t === 'string' && t.length > 0 && t.length <= MAX_TAG_LEN).slice(0, MAX_TAGS)
|
|
362
|
+
: [];
|
|
306
363
|
const id = generateId('entry');
|
|
307
364
|
const now = Date.now();
|
|
308
365
|
// Phase 5: MutationGuard validation before write
|
|
@@ -345,11 +402,7 @@ export async function bridgeStoreEntry(options) {
|
|
|
345
402
|
const stmt = ctx.db.prepare(insertSql);
|
|
346
403
|
stmt.run(id, key, namespace, value, embeddingJson, dimensions || null, model, tags.length > 0 ? JSON.stringify(tags) : null, '{}', now, now, now, // created_at, updated_at, event_at (bi-temporal: default eventAt = ingestion time)
|
|
347
404
|
ttl ? now + (ttl * 1000) : null);
|
|
348
|
-
// Phase 2: Write-through to TieredCache
|
|
349
|
-
const safeNs = String(namespace).replace(/:/g, '_');
|
|
350
|
-
const safeKey = String(key).replace(/:/g, '_');
|
|
351
|
-
const cacheKey = `entry:${safeNs}:${safeKey}`;
|
|
352
|
-
await cacheSet(registry, cacheKey, { id, key, namespace, content: value, embedding: embeddingJson });
|
|
405
|
+
// Phase 2: Write-through to TieredCache deferred — full entry populated on first read
|
|
353
406
|
// Phase 4: AttestationLog write audit
|
|
354
407
|
await logAttestation(registry, 'store', id, { key, namespace, hasEmbedding: !!embeddingJson });
|
|
355
408
|
const storeResult = {
|
|
@@ -362,31 +415,42 @@ export async function bridgeStoreEntry(options) {
|
|
|
362
415
|
};
|
|
363
416
|
// A-MEM: Post-write Zettelkasten linking — find top-3 semantic neighbors and create causal edges
|
|
364
417
|
// Source: https://arxiv.org/abs/2502.12110
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
418
|
+
//
|
|
419
|
+
// Backpressure: limit concurrent A-MEM linking to 1 per process. Without this
|
|
420
|
+
// a burst of N concurrent stores triggers N full-corpus searches in flight,
|
|
421
|
+
// each O(rows × dims) on cosineSim, which combined with poisoned embeddings
|
|
422
|
+
// can wedge the process. We drop new linking work if one is already running.
|
|
423
|
+
if (!_amemInFlight) {
|
|
424
|
+
_amemInFlight = true;
|
|
425
|
+
void (async () => {
|
|
426
|
+
try {
|
|
427
|
+
const neighbors = await bridgeSearchEntries({
|
|
428
|
+
query: options.value,
|
|
429
|
+
namespace: options.namespace,
|
|
430
|
+
limit: 3,
|
|
431
|
+
threshold: 0.7,
|
|
432
|
+
dbPath: options.dbPath,
|
|
433
|
+
});
|
|
434
|
+
if (neighbors?.results) {
|
|
435
|
+
for (const neighbor of neighbors.results) {
|
|
436
|
+
if (neighbor.id !== id) {
|
|
437
|
+
await bridgeRecordCausalEdge({
|
|
438
|
+
sourceId: id,
|
|
439
|
+
targetId: neighbor.id,
|
|
440
|
+
relation: 'similar',
|
|
441
|
+
weight: neighbor.score,
|
|
442
|
+
dbPath: options.dbPath,
|
|
443
|
+
});
|
|
444
|
+
}
|
|
384
445
|
}
|
|
385
446
|
}
|
|
386
447
|
}
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
448
|
+
catch { /* non-critical background operation */ }
|
|
449
|
+
finally {
|
|
450
|
+
_amemInFlight = false;
|
|
451
|
+
}
|
|
452
|
+
})();
|
|
453
|
+
}
|
|
390
454
|
return storeResult;
|
|
391
455
|
}
|
|
392
456
|
catch {
|
|
@@ -438,23 +502,25 @@ export async function bridgeSearchEntries(options) {
|
|
|
438
502
|
catch {
|
|
439
503
|
return null;
|
|
440
504
|
}
|
|
441
|
-
// Phase 2: Compute BM25 term stats for the corpus
|
|
442
|
-
|
|
505
|
+
// Phase 2: Compute BM25 term stats for the corpus.
|
|
506
|
+
// Cap query terms to 32 — bm25Score is O(terms × rows × words/row), so an
|
|
507
|
+
// attacker passing "x ".repeat(10000) would otherwise burn multi-second CPU per
|
|
508
|
+
// search, and the post-store fan-out (bridgeStoreEntry IIFE) amplifies this.
|
|
509
|
+
const MAX_QUERY_TERMS = 32;
|
|
510
|
+
const queryTerms = Array.from(new Set(queryStr.toLowerCase().split(/\s+/).filter(t => t.length > 1))).slice(0, MAX_QUERY_TERMS);
|
|
443
511
|
const { termDocFreqs, avgDocLength } = computeTermDocFreqs(queryTerms, rows);
|
|
444
512
|
const docCount = rows.length;
|
|
445
513
|
const results = [];
|
|
446
514
|
for (const row of rows) {
|
|
447
515
|
let semanticScore = 0;
|
|
448
516
|
let bm25ScoreVal = 0;
|
|
449
|
-
// Semantic scoring via cosine similarity
|
|
517
|
+
// Semantic scoring via cosine similarity (validated to reject oversized,
|
|
518
|
+
// NaN-poisoned, or non-array embeddings — see safeParseEmbedding above).
|
|
450
519
|
if (queryEmbedding && row.embedding) {
|
|
451
|
-
|
|
452
|
-
|
|
520
|
+
const embedding = safeParseEmbedding(row.embedding);
|
|
521
|
+
if (embedding && embedding.length === queryEmbedding.length) {
|
|
453
522
|
semanticScore = cosineSim(queryEmbedding, embedding);
|
|
454
523
|
}
|
|
455
|
-
catch {
|
|
456
|
-
// Invalid embedding
|
|
457
|
-
}
|
|
458
524
|
}
|
|
459
525
|
// Phase 2: BM25 keyword scoring (replaces String.includes fallback)
|
|
460
526
|
if (queryTerms.length > 0 && row.content) {
|
|
@@ -473,7 +539,7 @@ export async function bridgeSearchEntries(options) {
|
|
|
473
539
|
? `semantic:${semanticScore.toFixed(3)}+bm25:${bm25ScoreVal.toFixed(3)}`
|
|
474
540
|
: `bm25:${bm25ScoreVal.toFixed(3)}`;
|
|
475
541
|
results.push({
|
|
476
|
-
id: String(row.id)
|
|
542
|
+
id: String(row.id),
|
|
477
543
|
key: row.key || String(row.id).substring(0, 15),
|
|
478
544
|
content: (row.content || '').substring(0, 60) + ((row.content || '').length > 60 ? '...' : ''),
|
|
479
545
|
score,
|
|
@@ -505,7 +571,11 @@ export async function bridgeListEntries(options) {
|
|
|
505
571
|
if (!ctx)
|
|
506
572
|
return null;
|
|
507
573
|
try {
|
|
508
|
-
const
|
|
574
|
+
const rawLimit = options.limit ?? 20;
|
|
575
|
+
const rawOffset = options.offset ?? 0;
|
|
576
|
+
const limit = Math.max(1, Math.min(Number.isFinite(rawLimit) ? rawLimit : 20, 500));
|
|
577
|
+
const offset = Math.max(0, Number.isFinite(rawOffset) ? rawOffset : 0);
|
|
578
|
+
const { namespace } = options;
|
|
509
579
|
const nsFilter = namespace ? `AND namespace = ?` : '';
|
|
510
580
|
const nsParams = namespace ? [namespace] : [];
|
|
511
581
|
// Count
|
|
@@ -531,13 +601,13 @@ export async function bridgeListEntries(options) {
|
|
|
531
601
|
const rows = stmt.all(...nsParams, limit, offset);
|
|
532
602
|
for (const row of rows) {
|
|
533
603
|
entries.push({
|
|
534
|
-
id: String(row.id)
|
|
604
|
+
id: String(row.id),
|
|
535
605
|
key: row.key || String(row.id).substring(0, 15),
|
|
536
606
|
namespace: row.namespace || 'default',
|
|
537
607
|
size: (row.content || '').length,
|
|
538
608
|
accessCount: row.access_count ?? 0,
|
|
539
|
-
createdAt: row.created_at
|
|
540
|
-
updatedAt: row.updated_at
|
|
609
|
+
createdAt: row.created_at ? new Date(row.created_at).toISOString() : new Date().toISOString(),
|
|
610
|
+
updatedAt: row.updated_at ? new Date(row.updated_at).toISOString() : new Date().toISOString(),
|
|
541
611
|
hasEmbedding: !!(row.embedding && String(row.embedding).length > 10),
|
|
542
612
|
});
|
|
543
613
|
}
|
|
@@ -624,10 +694,16 @@ export async function bridgeGetEntry(options) {
|
|
|
624
694
|
}
|
|
625
695
|
catch { /* non-critical */ }
|
|
626
696
|
}
|
|
697
|
+
// Bounded tags read — refuse to JSON.parse a multi-MB tags blob that an
|
|
698
|
+
// older write may have persisted before the write-side cap was added.
|
|
699
|
+
const MAX_TAGS_JSON_BYTES = 32 * 64 + 256;
|
|
627
700
|
let tags = [];
|
|
628
|
-
if (row.tags) {
|
|
701
|
+
if (row.tags && typeof row.tags === 'string' && row.tags.length <= MAX_TAGS_JSON_BYTES) {
|
|
629
702
|
try {
|
|
630
|
-
|
|
703
|
+
const parsed = JSON.parse(row.tags);
|
|
704
|
+
if (Array.isArray(parsed)) {
|
|
705
|
+
tags = parsed.filter((t) => typeof t === 'string' && t.length <= 64).slice(0, 32);
|
|
706
|
+
}
|
|
631
707
|
}
|
|
632
708
|
catch { /* invalid */ }
|
|
633
709
|
}
|
|
@@ -637,8 +713,8 @@ export async function bridgeGetEntry(options) {
|
|
|
637
713
|
namespace: row.namespace || 'default',
|
|
638
714
|
content: row.content || '',
|
|
639
715
|
accessCount: (row.access_count ?? 0) + 1,
|
|
640
|
-
createdAt: row.created_at
|
|
641
|
-
updatedAt: row.updated_at
|
|
716
|
+
createdAt: row.created_at ? new Date(row.created_at).toISOString() : new Date().toISOString(),
|
|
717
|
+
updatedAt: row.updated_at ? new Date(row.updated_at).toISOString() : new Date().toISOString(),
|
|
642
718
|
hasEmbedding: !!(row.embedding && String(row.embedding).length > 10),
|
|
643
719
|
tags,
|
|
644
720
|
};
|
|
@@ -837,11 +913,13 @@ export async function bridgeSearchHNSW(queryEmbedding, options, dbPath) {
|
|
|
837
913
|
if (!row.embedding)
|
|
838
914
|
continue;
|
|
839
915
|
try {
|
|
840
|
-
const emb =
|
|
916
|
+
const emb = safeParseEmbedding(row.embedding);
|
|
917
|
+
if (!emb || emb.length !== queryEmbedding.length)
|
|
918
|
+
continue;
|
|
841
919
|
const score = cosineSim(queryEmbedding, emb);
|
|
842
920
|
if (score >= threshold) {
|
|
843
921
|
results.push({
|
|
844
|
-
id: String(row.id)
|
|
922
|
+
id: String(row.id),
|
|
845
923
|
key: row.key || String(row.id).substring(0, 15),
|
|
846
924
|
content: (row.content || '').substring(0, 60) +
|
|
847
925
|
((row.content || '').length > 60 ? '...' : ''),
|
|
@@ -873,6 +951,13 @@ export async function bridgeAddToHNSW(id, embedding, entry, dbPath) {
|
|
|
873
951
|
if (!ctx)
|
|
874
952
|
return null;
|
|
875
953
|
try {
|
|
954
|
+
if (!Array.isArray(embedding) || embedding.length === 0 || embedding.length > MAX_EMBEDDING_DIMS) {
|
|
955
|
+
return null;
|
|
956
|
+
}
|
|
957
|
+
for (const v of embedding) {
|
|
958
|
+
if (typeof v !== 'number' || !Number.isFinite(v))
|
|
959
|
+
return null;
|
|
960
|
+
}
|
|
876
961
|
const now = Date.now();
|
|
877
962
|
const embeddingJson = JSON.stringify(embedding);
|
|
878
963
|
ctx.db.prepare(`
|
|
@@ -1439,6 +1524,11 @@ export async function bridgeConsolidate(params) {
|
|
|
1439
1524
|
* - update: calls bulkUpdate(table, updates, conditions) on episodes table
|
|
1440
1525
|
*/
|
|
1441
1526
|
export async function bridgeBatchOperation(params) {
|
|
1527
|
+
const MAX_BATCH_ENTRIES = 500;
|
|
1528
|
+
const MAX_ENTRY_CONTENT_BYTES = 1 * 1024 * 1024;
|
|
1529
|
+
if (!Array.isArray(params.entries) || params.entries.length > MAX_BATCH_ENTRIES) {
|
|
1530
|
+
return { success: false, error: 'Batch too large or entries not an array' };
|
|
1531
|
+
}
|
|
1442
1532
|
const registry = await getRegistry();
|
|
1443
1533
|
if (!registry)
|
|
1444
1534
|
return null;
|
|
@@ -1450,10 +1540,13 @@ export async function bridgeBatchOperation(params) {
|
|
|
1450
1540
|
switch (params.operation) {
|
|
1451
1541
|
case 'insert': {
|
|
1452
1542
|
// insertEpisodes expects [{content, metadata?, embedding?}]
|
|
1453
|
-
const episodes = params.entries.map((e) =>
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
1543
|
+
const episodes = params.entries.map((e) => {
|
|
1544
|
+
const rawContent = e.value || e.content || JSON.stringify(e);
|
|
1545
|
+
const content = typeof rawContent === 'string' && rawContent.length <= MAX_ENTRY_CONTENT_BYTES
|
|
1546
|
+
? rawContent
|
|
1547
|
+
: typeof rawContent === 'string' ? rawContent.slice(0, MAX_ENTRY_CONTENT_BYTES) : '';
|
|
1548
|
+
return { content, metadata: e.metadata || { key: e.key } };
|
|
1549
|
+
});
|
|
1457
1550
|
result = await batch.insertEpisodes(episodes);
|
|
1458
1551
|
break;
|
|
1459
1552
|
}
|
|
@@ -10,6 +10,36 @@
|
|
|
10
10
|
*/
|
|
11
11
|
import * as fs from 'fs';
|
|
12
12
|
import * as path from 'path';
|
|
13
|
+
/**
|
|
14
|
+
* Local validator for stored embeddings — rejects oversized JSON, NaN/Infinity
|
|
15
|
+
* values, non-arrays, and out-of-bound dimensions before they reach cosineSim
|
|
16
|
+
* or HNSW math (which would otherwise OOM or poison ranking with NaN).
|
|
17
|
+
*/
|
|
18
|
+
const _MAX_EMBEDDING_DIMS = 8192;
|
|
19
|
+
const _MAX_EMBEDDING_JSON_BYTES = _MAX_EMBEDDING_DIMS * 32;
|
|
20
|
+
function safeParseEmbeddingLocal(raw) {
|
|
21
|
+
if (typeof raw !== 'string' || raw.length === 0)
|
|
22
|
+
return null;
|
|
23
|
+
if (raw.length > _MAX_EMBEDDING_JSON_BYTES)
|
|
24
|
+
return null;
|
|
25
|
+
let parsed;
|
|
26
|
+
try {
|
|
27
|
+
parsed = JSON.parse(raw);
|
|
28
|
+
}
|
|
29
|
+
catch {
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
32
|
+
if (!Array.isArray(parsed))
|
|
33
|
+
return null;
|
|
34
|
+
if (parsed.length === 0 || parsed.length > _MAX_EMBEDDING_DIMS)
|
|
35
|
+
return null;
|
|
36
|
+
for (let i = 0; i < parsed.length; i++) {
|
|
37
|
+
const v = parsed[i];
|
|
38
|
+
if (typeof v !== 'number' || !Number.isFinite(v))
|
|
39
|
+
return null;
|
|
40
|
+
}
|
|
41
|
+
return parsed;
|
|
42
|
+
}
|
|
13
43
|
// ADR-053: Lazy import of AgentDB v1 bridge
|
|
14
44
|
let _bridge;
|
|
15
45
|
async function getBridge() {
|
|
@@ -334,9 +364,14 @@ export async function getHNSWIndex(options) {
|
|
|
334
364
|
}
|
|
335
365
|
// Prevent concurrent initialization
|
|
336
366
|
if (hnswInitializing) {
|
|
337
|
-
// Wait for initialization to complete
|
|
338
|
-
|
|
367
|
+
// Wait for initialization to complete (max 5s)
|
|
368
|
+
let waitIterations = 0;
|
|
369
|
+
while (hnswInitializing && waitIterations < 500) {
|
|
339
370
|
await new Promise(resolve => setTimeout(resolve, 10));
|
|
371
|
+
waitIterations++;
|
|
372
|
+
}
|
|
373
|
+
if (hnswInitializing) {
|
|
374
|
+
throw new Error('HNSW initialization timed out after 5s');
|
|
340
375
|
}
|
|
341
376
|
return hnswIndex;
|
|
342
377
|
}
|
|
@@ -401,6 +436,13 @@ export async function getHNSWIndex(options) {
|
|
|
401
436
|
}
|
|
402
437
|
if (fs.existsSync(dbPath)) {
|
|
403
438
|
try {
|
|
439
|
+
// Reject symlinks and oversized DB files. Without this a symlink at the
|
|
440
|
+
// dbPath pointing at /dev/zero or a 100GB sparse file would OOM the CLI
|
|
441
|
+
// on the next memory operation.
|
|
442
|
+
const stat = fs.lstatSync(dbPath);
|
|
443
|
+
if (stat.isSymbolicLink() || stat.size > 256 * 1024 * 1024) {
|
|
444
|
+
return null;
|
|
445
|
+
}
|
|
404
446
|
const initSqlJs = (await import('sql.js')).default;
|
|
405
447
|
const SQL = await initSqlJs();
|
|
406
448
|
const fileBuffer = fs.readFileSync(dbPath);
|
|
@@ -417,7 +459,9 @@ export async function getHNSWIndex(options) {
|
|
|
417
459
|
const [id, key, ns, content, embeddingJson] = row;
|
|
418
460
|
if (embeddingJson) {
|
|
419
461
|
try {
|
|
420
|
-
const embedding =
|
|
462
|
+
const embedding = safeParseEmbeddingLocal(embeddingJson);
|
|
463
|
+
if (!embedding)
|
|
464
|
+
continue;
|
|
421
465
|
const vector = new Float32Array(embedding);
|
|
422
466
|
await db.insert({
|
|
423
467
|
id: String(id),
|
|
@@ -461,7 +505,9 @@ function saveHNSWMetadata() {
|
|
|
461
505
|
const swarmDir = path.join(process.cwd(), '.swarm');
|
|
462
506
|
const metadataPath = path.join(swarmDir, 'hnsw.metadata.json');
|
|
463
507
|
const metadata = Array.from(hnswIndex.entries.entries());
|
|
464
|
-
|
|
508
|
+
const tmp = metadataPath + '.tmp';
|
|
509
|
+
fs.writeFileSync(tmp, JSON.stringify(metadata));
|
|
510
|
+
fs.renameSync(tmp, metadataPath);
|
|
465
511
|
}
|
|
466
512
|
catch {
|
|
467
513
|
// Silently fail - metadata save is best-effort
|
|
@@ -799,10 +845,11 @@ export function flashAttentionSearch(query, vectors, options = {}) {
|
|
|
799
845
|
* Initial metadata to insert after schema creation
|
|
800
846
|
*/
|
|
801
847
|
export function getInitialMetadata(backend) {
|
|
848
|
+
const safeBackend = backend.replace(/'/g, "''");
|
|
802
849
|
return `
|
|
803
850
|
INSERT OR REPLACE INTO metadata (key, value) VALUES
|
|
804
851
|
('schema_version', '3.0.0'),
|
|
805
|
-
('backend', '${
|
|
852
|
+
('backend', '${safeBackend}'),
|
|
806
853
|
('created_at', '${new Date().toISOString()}'),
|
|
807
854
|
('sql_js', 'true'),
|
|
808
855
|
('vector_embeddings', 'enabled'),
|
|
@@ -863,9 +910,11 @@ export async function ensureSchemaColumns(dbPath) {
|
|
|
863
910
|
}
|
|
864
911
|
}
|
|
865
912
|
if (modified) {
|
|
866
|
-
// Save updated database
|
|
913
|
+
// Save updated database (atomic to avoid corruption on crash)
|
|
867
914
|
const data = db.export();
|
|
868
|
-
|
|
915
|
+
const tmp = dbPath + '.tmp';
|
|
916
|
+
fs.writeFileSync(tmp, Buffer.from(data));
|
|
917
|
+
fs.renameSync(tmp, dbPath);
|
|
869
918
|
}
|
|
870
919
|
db.close();
|
|
871
920
|
return { success: true, columnsAdded };
|
|
@@ -931,7 +980,7 @@ export async function checkAndMigrateLegacy(options) {
|
|
|
931
980
|
* a singleton ControllerRegistry and initializes it with the given dbPath.
|
|
932
981
|
* After this call, all enabled controllers are ready for immediate use.
|
|
933
982
|
*
|
|
934
|
-
* Failures are isolated: if @
|
|
983
|
+
* Failures are isolated: if @monomind/memory or agentdb is not installed,
|
|
935
984
|
* this returns an empty result without throwing.
|
|
936
985
|
*/
|
|
937
986
|
async function activateControllerRegistry(dbPath, verbose) {
|
|
@@ -1032,15 +1081,20 @@ export async function initializeMemoryDatabase(options) {
|
|
|
1032
1081
|
db.run(MEMORY_SCHEMA);
|
|
1033
1082
|
// Insert initial metadata
|
|
1034
1083
|
db.run(getInitialMetadata(backend));
|
|
1035
|
-
// Save to file
|
|
1084
|
+
// Save to file atomically — direct writeFileSync to dbPath would corrupt
|
|
1085
|
+
// the SQLite file if the process crashes mid-write. tmp+rename is atomic on POSIX.
|
|
1036
1086
|
const data = db.export();
|
|
1037
1087
|
const buffer = Buffer.from(data);
|
|
1038
|
-
|
|
1088
|
+
const dbTmp = dbPath + '.tmp';
|
|
1089
|
+
fs.writeFileSync(dbTmp, buffer);
|
|
1090
|
+
fs.renameSync(dbTmp, dbPath);
|
|
1039
1091
|
// Close database
|
|
1040
1092
|
db.close();
|
|
1041
|
-
// Also create schema file for reference
|
|
1093
|
+
// Also create schema file for reference (atomic)
|
|
1042
1094
|
const schemaPath = path.join(dbDir, 'schema.sql');
|
|
1043
|
-
|
|
1095
|
+
const schemaTmp = schemaPath + '.tmp';
|
|
1096
|
+
fs.writeFileSync(schemaTmp, MEMORY_SCHEMA + '\n' + getInitialMetadata(backend));
|
|
1097
|
+
fs.renameSync(schemaTmp, schemaPath);
|
|
1044
1098
|
// ADR-053: Activate ControllerRegistry so controllers (ReasoningBank,
|
|
1045
1099
|
// SkillLibrary, ExplainableRecall, etc.) are instantiated during init
|
|
1046
1100
|
const controllerResult = await activateControllerRegistry(dbPath, verbose);
|
|
@@ -1086,9 +1140,11 @@ export async function initializeMemoryDatabase(options) {
|
|
|
1086
1140
|
};
|
|
1087
1141
|
}
|
|
1088
1142
|
else {
|
|
1089
|
-
// Fall back to schema file approach
|
|
1143
|
+
// Fall back to schema file approach (atomic writes)
|
|
1090
1144
|
const schemaPath = path.join(dbDir, 'schema.sql');
|
|
1091
|
-
|
|
1145
|
+
const schemaTmpFb = schemaPath + '.tmp';
|
|
1146
|
+
fs.writeFileSync(schemaTmpFb, MEMORY_SCHEMA + '\n' + getInitialMetadata(backend));
|
|
1147
|
+
fs.renameSync(schemaTmpFb, schemaPath);
|
|
1092
1148
|
// Create minimal valid SQLite file
|
|
1093
1149
|
const sqliteHeader = Buffer.alloc(4096, 0);
|
|
1094
1150
|
// SQLite format 3 header
|
|
@@ -1101,7 +1157,9 @@ export async function initializeMemoryDatabase(options) {
|
|
|
1101
1157
|
sqliteHeader[25] = 0x40;
|
|
1102
1158
|
sqliteHeader[26] = 0x20; // min embedded payload
|
|
1103
1159
|
sqliteHeader[27] = 0x20; // leaf payload
|
|
1104
|
-
|
|
1160
|
+
const dbTmpFb = dbPath + '.tmp';
|
|
1161
|
+
fs.writeFileSync(dbTmpFb, sqliteHeader);
|
|
1162
|
+
fs.renameSync(dbTmpFb, dbPath);
|
|
1105
1163
|
// ADR-053: Activate ControllerRegistry even on fallback path
|
|
1106
1164
|
const controllerResult = await activateControllerRegistry(dbPath, verbose);
|
|
1107
1165
|
return {
|
|
@@ -1224,9 +1282,11 @@ export async function applyTemporalDecay(dbPath) {
|
|
|
1224
1282
|
`;
|
|
1225
1283
|
db.run(decayQuery, [now, now, now]);
|
|
1226
1284
|
const changes = db.getRowsModified();
|
|
1227
|
-
// Save
|
|
1285
|
+
// Save atomically
|
|
1228
1286
|
const data = db.export();
|
|
1229
|
-
|
|
1287
|
+
const dbTmpDecay = path_ + '.tmp';
|
|
1288
|
+
fs.writeFileSync(dbTmpDecay, Buffer.from(data));
|
|
1289
|
+
fs.renameSync(dbTmpDecay, path_);
|
|
1230
1290
|
db.close();
|
|
1231
1291
|
return {
|
|
1232
1292
|
success: true,
|
|
@@ -1398,6 +1458,13 @@ export async function loadEmbeddingModel(options) {
|
|
|
1398
1458
|
* Uses ONNX model if available, falls back to deterministic hash
|
|
1399
1459
|
*/
|
|
1400
1460
|
export async function generateEmbedding(text) {
|
|
1461
|
+
// Cap input text — caller may pass arbitrarily large content. Without this
|
|
1462
|
+
// cap, the hash-fallback below burns O(text.length × dimension) sin() calls
|
|
1463
|
+
// per call, and ONNX tokenization can saturate memory on multi-MB inputs.
|
|
1464
|
+
if (typeof text !== 'string')
|
|
1465
|
+
text = String(text ?? '');
|
|
1466
|
+
if (text.length > 16 * 1024)
|
|
1467
|
+
text = text.slice(0, 16 * 1024);
|
|
1401
1468
|
// ADR-053: Try AgentDB v1 bridge first
|
|
1402
1469
|
const bridge = await getBridge();
|
|
1403
1470
|
if (bridge) {
|
|
@@ -1652,9 +1719,11 @@ export async function verifyMemoryInit(dbPath, options) {
|
|
|
1652
1719
|
}
|
|
1653
1720
|
// Cleanup test entry
|
|
1654
1721
|
db.run(`DELETE FROM memory_entries WHERE id = ?`, [testId]);
|
|
1655
|
-
// Save changes
|
|
1722
|
+
// Save changes atomically
|
|
1656
1723
|
const data = db.export();
|
|
1657
|
-
|
|
1724
|
+
const dbTmpHealth = dbPath + '.tmp';
|
|
1725
|
+
fs.writeFileSync(dbTmpHealth, Buffer.from(data));
|
|
1726
|
+
fs.renameSync(dbTmpHealth, dbPath);
|
|
1658
1727
|
db.close();
|
|
1659
1728
|
const passed = tests.filter(t => t.passed).length;
|
|
1660
1729
|
const failed = tests.filter(t => !t.passed).length;
|
|
@@ -1744,19 +1813,22 @@ export async function storeEntry(options) {
|
|
|
1744
1813
|
now,
|
|
1745
1814
|
ttl ? now + (ttl * 1000) : null
|
|
1746
1815
|
]);
|
|
1747
|
-
// Save
|
|
1816
|
+
// Save atomically
|
|
1748
1817
|
const data = db.export();
|
|
1749
|
-
|
|
1818
|
+
const dbTmpStore = dbPath + '.tmp';
|
|
1819
|
+
fs.writeFileSync(dbTmpStore, Buffer.from(data));
|
|
1820
|
+
fs.renameSync(dbTmpStore, dbPath);
|
|
1750
1821
|
db.close();
|
|
1751
|
-
// Add to HNSW index for faster future searches
|
|
1822
|
+
// Add to HNSW index for faster future searches (validated to reject malformed embeddings)
|
|
1752
1823
|
if (embeddingJson) {
|
|
1753
|
-
const embResult =
|
|
1754
|
-
|
|
1755
|
-
id,
|
|
1756
|
-
|
|
1757
|
-
|
|
1758
|
-
|
|
1759
|
-
|
|
1824
|
+
const embResult = safeParseEmbeddingLocal(embeddingJson);
|
|
1825
|
+
if (embResult)
|
|
1826
|
+
await addToHNSWIndex(id, embResult, {
|
|
1827
|
+
id,
|
|
1828
|
+
key,
|
|
1829
|
+
namespace,
|
|
1830
|
+
content: value
|
|
1831
|
+
});
|
|
1760
1832
|
}
|
|
1761
1833
|
return {
|
|
1762
1834
|
success: true,
|
|
@@ -1834,13 +1906,10 @@ export async function searchEntries(options) {
|
|
|
1834
1906
|
const [id, key, ns, content, embeddingJson] = row;
|
|
1835
1907
|
let score = 0;
|
|
1836
1908
|
if (embeddingJson) {
|
|
1837
|
-
|
|
1838
|
-
|
|
1909
|
+
const embedding = safeParseEmbeddingLocal(embeddingJson);
|
|
1910
|
+
if (embedding && embedding.length === queryEmbedding.length) {
|
|
1839
1911
|
score = cosineSim(queryEmbedding, embedding);
|
|
1840
1912
|
}
|
|
1841
|
-
catch {
|
|
1842
|
-
// Invalid embedding, use keyword score
|
|
1843
|
-
}
|
|
1844
1913
|
}
|
|
1845
1914
|
// Fallback to keyword matching
|
|
1846
1915
|
if (score < threshold) {
|
|
@@ -2032,15 +2101,6 @@ export async function getEntry(options) {
|
|
|
2032
2101
|
return { success: true, found: false };
|
|
2033
2102
|
}
|
|
2034
2103
|
const [id, entryKey, ns, content, embedding, accessCount, createdAt, updatedAt, tagsJson] = result[0].values[0];
|
|
2035
|
-
// Update access count
|
|
2036
|
-
db.run(`
|
|
2037
|
-
UPDATE memory_entries
|
|
2038
|
-
SET access_count = access_count + 1, last_accessed_at = strftime('%s', 'now') * 1000
|
|
2039
|
-
WHERE id = ?
|
|
2040
|
-
`, [String(id)]);
|
|
2041
|
-
// Save updated database
|
|
2042
|
-
const data = db.export();
|
|
2043
|
-
fs.writeFileSync(dbPath, Buffer.from(data));
|
|
2044
2104
|
db.close();
|
|
2045
2105
|
let tags = [];
|
|
2046
2106
|
if (tagsJson) {
|
|
@@ -2167,9 +2227,11 @@ export async function deleteEntry(options) {
|
|
|
2167
2227
|
// Get remaining count
|
|
2168
2228
|
const countResult = db.exec(`SELECT COUNT(*) FROM memory_entries WHERE status = 'active'`);
|
|
2169
2229
|
const remainingEntries = countResult[0]?.values?.[0]?.[0] || 0;
|
|
2170
|
-
// Save updated database
|
|
2230
|
+
// Save updated database atomically
|
|
2171
2231
|
const data = db.export();
|
|
2172
|
-
|
|
2232
|
+
const dbTmpDelete = dbPath + '.tmp';
|
|
2233
|
+
fs.writeFileSync(dbTmpDelete, Buffer.from(data));
|
|
2234
|
+
fs.renameSync(dbTmpDelete, dbPath);
|
|
2173
2235
|
db.close();
|
|
2174
2236
|
// Clean up in-memory HNSW index so ghost vectors don't appear in searches.
|
|
2175
2237
|
// Remove the entry from the HNSW entries map and invalidate the index.
|