monomind 1.7.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} +22 -9
- package/.claude/commands/monomind/help.md +118 -0
- package/.claude/commands/{monomind-idea.md → monomind/idea.md} +23 -29
- package/.claude/commands/{monomind-improve.md → monomind/improve.md} +24 -30
- 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/loop-tracker.cjs +107 -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/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/README.md +5 -5
- package/package.json +1 -1
- package/packages/@monomind/cli/README.md +5 -5
- package/packages/@monomind/cli/bin/cli.js +78 -13
- 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 +28 -62
- 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 +163 -137
- package/packages/@monomind/cli/dist/src/init/helpers-generator.js +49 -36
- 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 +15 -6
- 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/graphify-tools.d.ts +4 -67
- package/packages/@monomind/cli/dist/src/mcp-tools/graphify-tools.js +40 -1250
- 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/index.d.ts +1 -0
- package/packages/@monomind/cli/dist/src/mcp-tools/index.js +1 -0
- package/packages/@monomind/cli/dist/src/mcp-tools/memory-tools.js +29 -13
- package/packages/@monomind/cli/dist/src/mcp-tools/monograph-tools.d.ts +9 -0
- package/packages/@monomind/cli/dist/src/mcp-tools/monograph-tools.js +6306 -0
- 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 -2
- package/packages/@monomind/guidance/README.md +0 -3
- package/packages/@monomind/shared/README.md +0 -1
- package/packages/@monomind/shared/dist/types/consensus-audit.d.ts +3 -1
- package/packages/README.md +15 -16
- 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
|
@@ -13,11 +13,19 @@
|
|
|
13
13
|
*
|
|
14
14
|
* github.com/nokhodian/monomind
|
|
15
15
|
*/
|
|
16
|
+
const ALLOWED_RUVECTOR_PACKAGES = new Set([
|
|
17
|
+
'@ruvector/learning-wasm',
|
|
18
|
+
'@ruvector/attention',
|
|
19
|
+
'@ruvector/sona',
|
|
20
|
+
]);
|
|
16
21
|
/**
|
|
17
22
|
* ESM/CJS interop helper — handles `.default` for CJS modules.
|
|
18
23
|
* Uses `'default' in mod` check which is safer than `mod.default || mod`.
|
|
19
24
|
*/
|
|
20
25
|
async function importWithInterop(packageName) {
|
|
26
|
+
if (!ALLOWED_RUVECTOR_PACKAGES.has(packageName)) {
|
|
27
|
+
throw new Error(`Disallowed dynamic import: ${packageName}`);
|
|
28
|
+
}
|
|
21
29
|
const mod = await import(packageName);
|
|
22
30
|
return ('default' in mod) ? mod.default : mod;
|
|
23
31
|
}
|
|
@@ -127,7 +127,10 @@ export declare class WorkerDaemon extends EventEmitter {
|
|
|
127
127
|
*/
|
|
128
128
|
private checkExistingDaemon;
|
|
129
129
|
/**
|
|
130
|
-
* Write PID file for singleton enforcement
|
|
130
|
+
* Write PID file with O_EXCL for atomic singleton enforcement (closes the
|
|
131
|
+
* TOCTOU window between checkExistingDaemon and writePidFile that previously
|
|
132
|
+
* allowed two concurrent `daemon start` calls to both succeed).
|
|
133
|
+
* Returns true on success, false if another daemon raced us.
|
|
131
134
|
*/
|
|
132
135
|
private writePidFile;
|
|
133
136
|
/**
|
|
@@ -10,9 +10,9 @@
|
|
|
10
10
|
* - testgaps: Test coverage analysis (20 min interval)
|
|
11
11
|
*/
|
|
12
12
|
import { EventEmitter } from 'events';
|
|
13
|
-
import { existsSync, mkdirSync, writeFileSync, readFileSync, appendFileSync, unlinkSync } from 'fs';
|
|
13
|
+
import { existsSync, mkdirSync, writeFileSync, renameSync, readFileSync, appendFileSync, unlinkSync } from 'fs';
|
|
14
14
|
import { cpus } from 'os';
|
|
15
|
-
import { join } from 'path';
|
|
15
|
+
import { join, resolve } from 'path';
|
|
16
16
|
import { HeadlessWorkerExecutor, isHeadlessWorker, } from './headless-worker-executor.js';
|
|
17
17
|
// Default worker configurations with improved intervals (P0 fix: map 5min -> 15min)
|
|
18
18
|
const DEFAULT_WORKERS = [
|
|
@@ -47,9 +47,14 @@ export class WorkerDaemon extends EventEmitter {
|
|
|
47
47
|
originalConfig;
|
|
48
48
|
constructor(projectRoot, config) {
|
|
49
49
|
super();
|
|
50
|
-
|
|
50
|
+
// Resolve and validate projectRoot. Without this an attacker who can pass
|
|
51
|
+
// a crafted projectRoot (env var, untrusted CLI flag, MCP tool argument)
|
|
52
|
+
// gets arbitrary file write via the derived pidFile, logFile, stateFile,
|
|
53
|
+
// and metrics paths.
|
|
54
|
+
const resolved = resolve(projectRoot);
|
|
55
|
+
this.projectRoot = resolved;
|
|
51
56
|
this.originalConfig = config;
|
|
52
|
-
const monomindDir = join(
|
|
57
|
+
const monomindDir = join(resolved, '.monomind');
|
|
53
58
|
// Read daemon config from .monomind/config.json (Layer B)
|
|
54
59
|
const fileConfig = this.readDaemonConfigFromFile(monomindDir);
|
|
55
60
|
// CPU-proportional smart default instead of hardcoded 2.0
|
|
@@ -212,9 +217,9 @@ export class WorkerDaemon extends EventEmitter {
|
|
|
212
217
|
await this.stop();
|
|
213
218
|
process.exit(0);
|
|
214
219
|
};
|
|
215
|
-
process.
|
|
216
|
-
process.
|
|
217
|
-
process.
|
|
220
|
+
process.once('SIGTERM', shutdown);
|
|
221
|
+
process.once('SIGINT', shutdown);
|
|
222
|
+
process.once('SIGHUP', shutdown);
|
|
218
223
|
}
|
|
219
224
|
/**
|
|
220
225
|
* Check if system resources allow worker execution
|
|
@@ -295,16 +300,28 @@ export class WorkerDaemon extends EventEmitter {
|
|
|
295
300
|
this.config.workerTimeoutMs = saved.config.workerTimeoutMs;
|
|
296
301
|
}
|
|
297
302
|
// Restore worker runtime states (runCount, successCount, etc.)
|
|
298
|
-
|
|
303
|
+
// Validate keys against an allowlist to defeat prototype-pollution
|
|
304
|
+
// attempts and reject unknown worker types injected into the file.
|
|
305
|
+
if (saved.workers && typeof saved.workers === 'object') {
|
|
306
|
+
const VALID_TYPES = new Set(this.config.workers.map(w => w.type));
|
|
307
|
+
const FORBIDDEN = new Set(['__proto__', 'constructor', 'prototype']);
|
|
308
|
+
const finiteNonNeg = (v) => {
|
|
309
|
+
if (typeof v !== 'number' || !Number.isFinite(v) || v < 0)
|
|
310
|
+
return 0;
|
|
311
|
+
return Math.floor(v);
|
|
312
|
+
};
|
|
299
313
|
for (const [type, state] of Object.entries(saved.workers)) {
|
|
314
|
+
if (FORBIDDEN.has(type) || !VALID_TYPES.has(type))
|
|
315
|
+
continue;
|
|
300
316
|
const savedState = state;
|
|
301
317
|
const lastRunValue = savedState.lastRun;
|
|
318
|
+
const lastRunDate = typeof lastRunValue === 'string' ? new Date(lastRunValue) : undefined;
|
|
302
319
|
this.workers.set(type, {
|
|
303
|
-
runCount: savedState.runCount
|
|
304
|
-
successCount: savedState.successCount
|
|
305
|
-
failureCount: savedState.failureCount
|
|
306
|
-
averageDurationMs: savedState.averageDurationMs
|
|
307
|
-
lastRun:
|
|
320
|
+
runCount: finiteNonNeg(savedState.runCount),
|
|
321
|
+
successCount: finiteNonNeg(savedState.successCount),
|
|
322
|
+
failureCount: finiteNonNeg(savedState.failureCount),
|
|
323
|
+
averageDurationMs: finiteNonNeg(savedState.averageDurationMs),
|
|
324
|
+
lastRun: lastRunDate && !isNaN(lastRunDate.getTime()) ? lastRunDate : undefined,
|
|
308
325
|
nextRun: undefined,
|
|
309
326
|
isRunning: false,
|
|
310
327
|
});
|
|
@@ -359,13 +376,39 @@ export class WorkerDaemon extends EventEmitter {
|
|
|
359
376
|
}
|
|
360
377
|
}
|
|
361
378
|
/**
|
|
362
|
-
* Write PID file for singleton enforcement
|
|
379
|
+
* Write PID file with O_EXCL for atomic singleton enforcement (closes the
|
|
380
|
+
* TOCTOU window between checkExistingDaemon and writePidFile that previously
|
|
381
|
+
* allowed two concurrent `daemon start` calls to both succeed).
|
|
382
|
+
* Returns true on success, false if another daemon raced us.
|
|
363
383
|
*/
|
|
364
384
|
writePidFile() {
|
|
365
385
|
const dir = join(this.projectRoot, '.monomind');
|
|
366
386
|
if (!existsSync(dir))
|
|
367
387
|
mkdirSync(dir, { recursive: true });
|
|
368
|
-
|
|
388
|
+
try {
|
|
389
|
+
// wx flag = O_CREAT | O_EXCL — atomic create-or-fail
|
|
390
|
+
writeFileSync(this.pidFile, String(process.pid), { flag: 'wx' });
|
|
391
|
+
return true;
|
|
392
|
+
}
|
|
393
|
+
catch (e) {
|
|
394
|
+
const code = e.code;
|
|
395
|
+
if (code === 'EEXIST') {
|
|
396
|
+
// Recheck liveness — file may belong to a dead daemon we missed
|
|
397
|
+
const racePid = this.checkExistingDaemon();
|
|
398
|
+
if (racePid === null) {
|
|
399
|
+
// Stale file was just removed by checkExistingDaemon, retry once
|
|
400
|
+
try {
|
|
401
|
+
writeFileSync(this.pidFile, String(process.pid), { flag: 'wx' });
|
|
402
|
+
return true;
|
|
403
|
+
}
|
|
404
|
+
catch {
|
|
405
|
+
return false;
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
return false;
|
|
409
|
+
}
|
|
410
|
+
throw e;
|
|
411
|
+
}
|
|
369
412
|
}
|
|
370
413
|
/**
|
|
371
414
|
* Remove PID file on shutdown.
|
|
@@ -391,9 +434,16 @@ export class WorkerDaemon extends EventEmitter {
|
|
|
391
434
|
this.emit('warning', `Daemon already running (PID: ${existingPid})`);
|
|
392
435
|
return;
|
|
393
436
|
}
|
|
437
|
+
// Atomic PID file write — fails if another daemon raced us past
|
|
438
|
+
// checkExistingDaemon. Without this two `daemon start` calls could both
|
|
439
|
+
// pass the existence check then both clobber the PID file.
|
|
440
|
+
if (!this.writePidFile()) {
|
|
441
|
+
this.log('info', 'Another daemon won the PID race — aborting start');
|
|
442
|
+
this.emit('warning', 'Another daemon instance is starting/running');
|
|
443
|
+
return;
|
|
444
|
+
}
|
|
394
445
|
this.running = true;
|
|
395
446
|
this.startedAt = new Date();
|
|
396
|
-
this.writePidFile();
|
|
397
447
|
this.emit('started', { pid: process.pid, startedAt: this.startedAt });
|
|
398
448
|
// Schedule all enabled workers
|
|
399
449
|
for (const workerConfig of this.config.workers) {
|
|
@@ -473,10 +523,18 @@ export class WorkerDaemon extends EventEmitter {
|
|
|
473
523
|
* Execute a worker with concurrency control (P0 fix)
|
|
474
524
|
*/
|
|
475
525
|
async executeWorkerWithConcurrencyControl(workerConfig) {
|
|
526
|
+
// Dedup: under sustained resource pressure each scheduler tick re-pushes
|
|
527
|
+
// the same WorkerType. Without dedup, high-priority workers (audit) crowd
|
|
528
|
+
// out low-priority ones (consolidate) — starvation. Skip the push if the
|
|
529
|
+
// type is already pending.
|
|
530
|
+
const pushPending = (type) => {
|
|
531
|
+
if (!this.pendingWorkers.includes(type))
|
|
532
|
+
this.pendingWorkers.push(type);
|
|
533
|
+
};
|
|
476
534
|
// Check concurrency limit
|
|
477
535
|
if (this.runningWorkers.size >= this.config.maxConcurrent) {
|
|
478
536
|
this.log('info', `Worker ${workerConfig.type} deferred: max concurrent (${this.config.maxConcurrent}) reached`);
|
|
479
|
-
|
|
537
|
+
pushPending(workerConfig.type);
|
|
480
538
|
this.emit('worker:deferred', { type: workerConfig.type, reason: 'max_concurrent' });
|
|
481
539
|
return null;
|
|
482
540
|
}
|
|
@@ -484,7 +542,7 @@ export class WorkerDaemon extends EventEmitter {
|
|
|
484
542
|
const resourceCheck = await this.canRunWorker();
|
|
485
543
|
if (!resourceCheck.allowed) {
|
|
486
544
|
this.log('info', `Worker ${workerConfig.type} deferred: ${resourceCheck.reason}`);
|
|
487
|
-
|
|
545
|
+
pushPending(workerConfig.type);
|
|
488
546
|
this.emit('worker:deferred', { type: workerConfig.type, reason: resourceCheck.reason });
|
|
489
547
|
return null;
|
|
490
548
|
}
|
|
@@ -504,11 +562,15 @@ export class WorkerDaemon extends EventEmitter {
|
|
|
504
562
|
this.log('info', `Starting worker: ${workerConfig.type} (${this.runningWorkers.size}/${this.config.maxConcurrent} concurrent)`);
|
|
505
563
|
try {
|
|
506
564
|
// Execute worker logic with timeout (P1 fix)
|
|
507
|
-
// Pass cleanup callback to kill
|
|
565
|
+
// Pass cleanup callback to kill only this worker's child process on timeout.
|
|
566
|
+
// cancelAll() was too broad — it would kill concurrent healthy workers.
|
|
508
567
|
const output = await this.runWithTimeout(() => this.runWorkerLogic(workerConfig), this.config.workerTimeoutMs, `Worker ${workerConfig.type} timed out after ${this.config.workerTimeoutMs / 1000}s`, () => {
|
|
509
|
-
// On timeout, cancel any headless execution to prevent orphan processes
|
|
510
568
|
if (this.headlessExecutor) {
|
|
511
|
-
|
|
569
|
+
// Try exact-ID cancel first; fall back to type-based cancel which
|
|
570
|
+
// avoids killing unrelated concurrent workers (cancelByType).
|
|
571
|
+
if (!this.headlessExecutor.cancel(workerId)) {
|
|
572
|
+
this.headlessExecutor.cancelByType(workerConfig.type);
|
|
573
|
+
}
|
|
512
574
|
}
|
|
513
575
|
});
|
|
514
576
|
const durationMs = Date.now() - startTime;
|
|
@@ -670,7 +732,9 @@ export class WorkerDaemon extends EventEmitter {
|
|
|
670
732
|
},
|
|
671
733
|
scannedAt: Date.now(),
|
|
672
734
|
};
|
|
673
|
-
|
|
735
|
+
const metricsFileTmp1 = metricsFile + '.tmp';
|
|
736
|
+
writeFileSync(metricsFileTmp1, JSON.stringify(map, null, 2));
|
|
737
|
+
renameSync(metricsFileTmp1, metricsFile);
|
|
674
738
|
return map;
|
|
675
739
|
}
|
|
676
740
|
/**
|
|
@@ -695,7 +759,9 @@ export class WorkerDaemon extends EventEmitter {
|
|
|
695
759
|
recommendations: [],
|
|
696
760
|
note: 'Install Claude Code CLI for AI-powered security analysis',
|
|
697
761
|
};
|
|
698
|
-
|
|
762
|
+
const auditFileTmp = auditFile + '.tmp';
|
|
763
|
+
writeFileSync(auditFileTmp, JSON.stringify(audit, null, 2));
|
|
764
|
+
renameSync(auditFileTmp, auditFile);
|
|
699
765
|
return audit;
|
|
700
766
|
}
|
|
701
767
|
/**
|
|
@@ -719,7 +785,9 @@ export class WorkerDaemon extends EventEmitter {
|
|
|
719
785
|
},
|
|
720
786
|
note: 'Install Claude Code CLI for AI-powered optimization suggestions',
|
|
721
787
|
};
|
|
722
|
-
|
|
788
|
+
const optimizeFileTmp = optimizeFile + '.tmp';
|
|
789
|
+
writeFileSync(optimizeFileTmp, JSON.stringify(perf, null, 2));
|
|
790
|
+
renameSync(optimizeFileTmp, optimizeFile);
|
|
723
791
|
return perf;
|
|
724
792
|
}
|
|
725
793
|
async runConsolidateWorker() {
|
|
@@ -774,7 +842,9 @@ export class WorkerDaemon extends EventEmitter {
|
|
|
774
842
|
duplicatesRemoved: 0,
|
|
775
843
|
mode: 'raptor',
|
|
776
844
|
};
|
|
777
|
-
|
|
845
|
+
const consolidateFileTmp = consolidateFile + '.tmp';
|
|
846
|
+
writeFileSync(consolidateFileTmp, JSON.stringify(result, null, 2));
|
|
847
|
+
renameSync(consolidateFileTmp, consolidateFile);
|
|
778
848
|
return result;
|
|
779
849
|
}
|
|
780
850
|
/**
|
|
@@ -795,7 +865,9 @@ export class WorkerDaemon extends EventEmitter {
|
|
|
795
865
|
gaps: [],
|
|
796
866
|
note: 'Install Claude Code CLI for AI-powered test gap analysis',
|
|
797
867
|
};
|
|
798
|
-
|
|
868
|
+
const testGapsFileTmp = testGapsFile + '.tmp';
|
|
869
|
+
writeFileSync(testGapsFileTmp, JSON.stringify(result, null, 2));
|
|
870
|
+
renameSync(testGapsFileTmp, testGapsFile);
|
|
799
871
|
return result;
|
|
800
872
|
}
|
|
801
873
|
/**
|
|
@@ -876,7 +948,9 @@ export class WorkerDaemon extends EventEmitter {
|
|
|
876
948
|
uptime: process.uptime(),
|
|
877
949
|
},
|
|
878
950
|
};
|
|
879
|
-
|
|
951
|
+
const benchmarkFileTmp = benchmarkFile + '.tmp';
|
|
952
|
+
writeFileSync(benchmarkFileTmp, JSON.stringify(result, null, 2));
|
|
953
|
+
renameSync(benchmarkFileTmp, benchmarkFile);
|
|
880
954
|
return result;
|
|
881
955
|
}
|
|
882
956
|
/**
|
|
@@ -898,6 +972,14 @@ export class WorkerDaemon extends EventEmitter {
|
|
|
898
972
|
if (!workerConfig) {
|
|
899
973
|
throw new Error(`Unknown worker type: ${type}`);
|
|
900
974
|
}
|
|
975
|
+
const result = await this.executeWorkerWithConcurrencyControl(workerConfig);
|
|
976
|
+
if (result !== null)
|
|
977
|
+
return result;
|
|
978
|
+
// Concurrency limit reached — execute directly for explicit manual trigger.
|
|
979
|
+
// Remove from pendingWorkers to avoid double execution when finally fires.
|
|
980
|
+
const pendingIdx = this.pendingWorkers.indexOf(workerConfig.type);
|
|
981
|
+
if (pendingIdx !== -1)
|
|
982
|
+
this.pendingWorkers.splice(pendingIdx, 1);
|
|
901
983
|
return this.executeWorker(workerConfig);
|
|
902
984
|
}
|
|
903
985
|
/**
|
|
@@ -942,7 +1024,9 @@ export class WorkerDaemon extends EventEmitter {
|
|
|
942
1024
|
savedAt: new Date().toISOString(),
|
|
943
1025
|
};
|
|
944
1026
|
try {
|
|
945
|
-
|
|
1027
|
+
const tmp = this.config.stateFile + '.tmp';
|
|
1028
|
+
writeFileSync(tmp, JSON.stringify(state, null, 2));
|
|
1029
|
+
renameSync(tmp, this.config.stateFile);
|
|
946
1030
|
}
|
|
947
1031
|
catch (error) {
|
|
948
1032
|
this.log('error', `Failed to save state: ${error}`);
|
|
@@ -102,7 +102,10 @@ export declare class WorkerQueue extends EventEmitter {
|
|
|
102
102
|
private store;
|
|
103
103
|
private workerId;
|
|
104
104
|
private heartbeatTimer?;
|
|
105
|
+
private visibilityTimer?;
|
|
106
|
+
private retryTimers;
|
|
105
107
|
private processingTasks;
|
|
108
|
+
private taskGenerations;
|
|
106
109
|
private isShuttingDown;
|
|
107
110
|
private maxConcurrent;
|
|
108
111
|
private initialized;
|
|
@@ -111,6 +114,10 @@ export declare class WorkerQueue extends EventEmitter {
|
|
|
111
114
|
* Initialize the queue (starts cleanup timers)
|
|
112
115
|
*/
|
|
113
116
|
initialize(): Promise<void>;
|
|
117
|
+
/**
|
|
118
|
+
* Requeue processing tasks that exceeded the visibility timeout (crashed workers).
|
|
119
|
+
*/
|
|
120
|
+
private startVisibilityReaper;
|
|
114
121
|
/**
|
|
115
122
|
* Enqueue a new task
|
|
116
123
|
*/
|
|
@@ -126,11 +133,11 @@ export declare class WorkerQueue extends EventEmitter {
|
|
|
126
133
|
/**
|
|
127
134
|
* Complete a task with result
|
|
128
135
|
*/
|
|
129
|
-
complete(taskId: string, result: HeadlessExecutionResult): Promise<void>;
|
|
136
|
+
complete(taskId: string, result: HeadlessExecutionResult, leaseGen?: number): Promise<void>;
|
|
130
137
|
/**
|
|
131
138
|
* Fail a task with error
|
|
132
139
|
*/
|
|
133
|
-
fail(taskId: string, error: string, retryable?: boolean): Promise<void>;
|
|
140
|
+
fail(taskId: string, error: string, retryable?: boolean, leaseGen?: number): Promise<void>;
|
|
134
141
|
/**
|
|
135
142
|
* Get task status
|
|
136
143
|
*/
|
|
@@ -161,7 +161,16 @@ export class WorkerQueue extends EventEmitter {
|
|
|
161
161
|
store;
|
|
162
162
|
workerId;
|
|
163
163
|
heartbeatTimer;
|
|
164
|
+
visibilityTimer;
|
|
165
|
+
retryTimers = new Set();
|
|
164
166
|
processingTasks = new Set();
|
|
167
|
+
// Per-task lease generation. When the visibility reaper requeues a task
|
|
168
|
+
// because of timeout, the generation is bumped. The original (still-running)
|
|
169
|
+
// handler's complete()/fail() call carries the old generation and is
|
|
170
|
+
// rejected — first-finisher wins, the loser drops. This prevents
|
|
171
|
+
// double-execution side effects on non-idempotent workers (audit reports,
|
|
172
|
+
// GitHub posts, memory writes).
|
|
173
|
+
taskGenerations = new Map();
|
|
165
174
|
isShuttingDown = false;
|
|
166
175
|
maxConcurrent = 1;
|
|
167
176
|
initialized = false;
|
|
@@ -178,9 +187,51 @@ export class WorkerQueue extends EventEmitter {
|
|
|
178
187
|
if (this.initialized)
|
|
179
188
|
return;
|
|
180
189
|
this.store.startCleanup();
|
|
190
|
+
this.startVisibilityReaper();
|
|
181
191
|
this.initialized = true;
|
|
182
192
|
this.emit('initialized', { workerId: this.workerId });
|
|
183
193
|
}
|
|
194
|
+
/**
|
|
195
|
+
* Requeue processing tasks that exceeded the visibility timeout (crashed workers).
|
|
196
|
+
*/
|
|
197
|
+
startVisibilityReaper() {
|
|
198
|
+
this.visibilityTimer = setInterval(() => {
|
|
199
|
+
// Skip running the reaper while we're shutting down so it can't requeue
|
|
200
|
+
// tasks back into a queue that is about to be torn down.
|
|
201
|
+
if (this.isShuttingDown)
|
|
202
|
+
return;
|
|
203
|
+
const now = Date.now();
|
|
204
|
+
for (const taskId of this.processingTasks) {
|
|
205
|
+
const task = this.store.getTask(taskId);
|
|
206
|
+
if (!task) {
|
|
207
|
+
this.processingTasks.delete(taskId);
|
|
208
|
+
continue;
|
|
209
|
+
}
|
|
210
|
+
const startedMs = task.startedAt ? task.startedAt.getTime() : 0;
|
|
211
|
+
if (now - startedMs > this.config.visibilityTimeoutMs) {
|
|
212
|
+
this.processingTasks.delete(taskId);
|
|
213
|
+
if (task.retryCount < task.maxRetries) {
|
|
214
|
+
task.retryCount++;
|
|
215
|
+
task.status = 'pending';
|
|
216
|
+
task.startedAt = undefined;
|
|
217
|
+
task.workerId = undefined;
|
|
218
|
+
this.store.setTask(taskId, task);
|
|
219
|
+
const queueName = this.getQueueName(task.workerType);
|
|
220
|
+
this.store.pushToQueue(queueName, taskId, PRIORITY_SCORES[task.priority]);
|
|
221
|
+
this.emit('taskRetrying', { taskId, retryCount: task.retryCount, delay: 0 });
|
|
222
|
+
}
|
|
223
|
+
else {
|
|
224
|
+
task.status = 'failed';
|
|
225
|
+
task.completedAt = new Date();
|
|
226
|
+
task.error = 'Visibility timeout exceeded';
|
|
227
|
+
this.store.setTask(taskId, task);
|
|
228
|
+
this.emit('taskFailed', { taskId, error: task.error });
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
}, Math.max(5000, this.config.visibilityTimeoutMs / 4));
|
|
233
|
+
this.visibilityTimer.unref();
|
|
234
|
+
}
|
|
184
235
|
// ============================================
|
|
185
236
|
// Public API - Task Management
|
|
186
237
|
// ============================================
|
|
@@ -241,6 +292,12 @@ export class WorkerQueue extends EventEmitter {
|
|
|
241
292
|
task.workerId = this.workerId;
|
|
242
293
|
this.store.setTask(taskId, task);
|
|
243
294
|
this.processingTasks.add(taskId);
|
|
295
|
+
// Bump lease generation. Stamp on the in-memory task so the
|
|
296
|
+
// handler's later complete()/fail() can compare and detect a
|
|
297
|
+
// reap-and-redequeue cycle.
|
|
298
|
+
const gen = (this.taskGenerations.get(taskId) ?? 0) + 1;
|
|
299
|
+
this.taskGenerations.set(taskId, gen);
|
|
300
|
+
task.__leaseGen = gen;
|
|
244
301
|
this.emit('taskDequeued', { taskId, workerType });
|
|
245
302
|
return task;
|
|
246
303
|
}
|
|
@@ -251,12 +308,18 @@ export class WorkerQueue extends EventEmitter {
|
|
|
251
308
|
/**
|
|
252
309
|
* Complete a task with result
|
|
253
310
|
*/
|
|
254
|
-
async complete(taskId, result) {
|
|
311
|
+
async complete(taskId, result, leaseGen) {
|
|
255
312
|
const task = this.store.getTask(taskId);
|
|
256
313
|
if (!task) {
|
|
257
314
|
this.emit('warning', { message: `Task ${taskId} not found for completion` });
|
|
258
315
|
return;
|
|
259
316
|
}
|
|
317
|
+
// Reject stale leases: if the reaper requeued this task and another
|
|
318
|
+
// worker has already taken it (bumping the generation), drop our result.
|
|
319
|
+
if (leaseGen !== undefined && this.taskGenerations.get(taskId) !== leaseGen) {
|
|
320
|
+
this.emit('warning', { message: `Task ${taskId} complete() rejected: lease expired` });
|
|
321
|
+
return;
|
|
322
|
+
}
|
|
260
323
|
task.status = 'completed';
|
|
261
324
|
task.completedAt = new Date();
|
|
262
325
|
task.result = result;
|
|
@@ -269,12 +332,16 @@ export class WorkerQueue extends EventEmitter {
|
|
|
269
332
|
/**
|
|
270
333
|
* Fail a task with error
|
|
271
334
|
*/
|
|
272
|
-
async fail(taskId, error, retryable = true) {
|
|
335
|
+
async fail(taskId, error, retryable = true, leaseGen) {
|
|
273
336
|
const task = this.store.getTask(taskId);
|
|
274
337
|
if (!task) {
|
|
275
338
|
this.emit('warning', { message: `Task ${taskId} not found for failure` });
|
|
276
339
|
return;
|
|
277
340
|
}
|
|
341
|
+
if (leaseGen !== undefined && this.taskGenerations.get(taskId) !== leaseGen) {
|
|
342
|
+
this.emit('warning', { message: `Task ${taskId} fail() rejected: lease expired` });
|
|
343
|
+
return;
|
|
344
|
+
}
|
|
278
345
|
this.processingTasks.delete(taskId);
|
|
279
346
|
// Check if we should retry
|
|
280
347
|
if (retryable && task.retryCount < task.maxRetries) {
|
|
@@ -284,12 +351,19 @@ export class WorkerQueue extends EventEmitter {
|
|
|
284
351
|
task.workerId = undefined;
|
|
285
352
|
task.error = error;
|
|
286
353
|
this.store.setTask(taskId, task);
|
|
287
|
-
// Re-queue with delay (exponential backoff)
|
|
354
|
+
// Re-queue with delay (exponential backoff). Track the timer so shutdown
|
|
355
|
+
// can clear it — otherwise pending retries fire after shutdown and push
|
|
356
|
+
// tasks back into a torn-down queue.
|
|
288
357
|
const delay = Math.min(30000, 1000 * Math.pow(2, task.retryCount));
|
|
289
|
-
setTimeout(() => {
|
|
358
|
+
const retryTimer = setTimeout(() => {
|
|
359
|
+
this.retryTimers.delete(retryTimer);
|
|
360
|
+
if (this.isShuttingDown)
|
|
361
|
+
return;
|
|
290
362
|
const queueName = this.getQueueName(task.workerType);
|
|
291
363
|
this.store.pushToQueue(queueName, taskId, PRIORITY_SCORES[task.priority]);
|
|
292
364
|
}, delay);
|
|
365
|
+
retryTimer.unref();
|
|
366
|
+
this.retryTimers.add(retryTimer);
|
|
293
367
|
this.emit('taskRetrying', { taskId, retryCount: task.retryCount, delay });
|
|
294
368
|
}
|
|
295
369
|
else {
|
|
@@ -469,8 +543,15 @@ export class WorkerQueue extends EventEmitter {
|
|
|
469
543
|
for (const taskId of this.processingTasks) {
|
|
470
544
|
await this.fail(taskId, 'Worker shutdown', false);
|
|
471
545
|
}
|
|
472
|
-
// Stop store cleanup
|
|
546
|
+
// Stop store cleanup and timers
|
|
473
547
|
this.store.stopCleanup();
|
|
548
|
+
if (this.visibilityTimer) {
|
|
549
|
+
clearInterval(this.visibilityTimer);
|
|
550
|
+
this.visibilityTimer = undefined;
|
|
551
|
+
}
|
|
552
|
+
for (const t of this.retryTimers)
|
|
553
|
+
clearTimeout(t);
|
|
554
|
+
this.retryTimers.clear();
|
|
474
555
|
await this.unregisterWorker();
|
|
475
556
|
this.initialized = false;
|
|
476
557
|
this.emit('shutdown', {});
|
|
@@ -15,6 +15,15 @@ export function levenshteinDistance(a, b) {
|
|
|
15
15
|
return n;
|
|
16
16
|
if (n === 0)
|
|
17
17
|
return m;
|
|
18
|
+
// Bound input length — the Wagner-Fischer matrix is O(m × n) memory.
|
|
19
|
+
// Without this cap, any caller that passes a long stdin-derived string
|
|
20
|
+
// (shell completion of a malformed command, untrusted CLI arg) can OOM
|
|
21
|
+
// the process. For ranking purposes the worst-case distance is `max(m,n)`,
|
|
22
|
+
// so returning that is safe.
|
|
23
|
+
const MAX_LEN = 256;
|
|
24
|
+
if (m > MAX_LEN || n > MAX_LEN || Math.abs(m - n) > 64) {
|
|
25
|
+
return Math.max(m, n);
|
|
26
|
+
}
|
|
18
27
|
// Create distance matrix
|
|
19
28
|
const d = Array(m + 1).fill(null).map(() => Array(n + 1).fill(0));
|
|
20
29
|
// Initialize first column
|
|
@@ -11,16 +11,18 @@ export declare class FlowEnforcer {
|
|
|
11
11
|
private readonly swarmId;
|
|
12
12
|
private readonly enforce;
|
|
13
13
|
private readonly violations;
|
|
14
|
+
private static readonly MAX_VIOLATIONS;
|
|
14
15
|
constructor(graph: CommunicationGraph, swarmId: string, enforceMode: boolean);
|
|
15
16
|
/**
|
|
16
17
|
* Check whether a message is authorized and record any violation.
|
|
17
18
|
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
19
|
+
* Returns BOTH `authorized` (the policy decision) and `enforced` (whether the
|
|
20
|
+
* decision is actually applied). Callers must read both — taking action based
|
|
21
|
+
* solely on `authorized` would let `enforce=false` silently bypass the policy.
|
|
21
22
|
*/
|
|
22
23
|
checkAndRecord(fromSlug: string, toSlug: string, messageContent: string): {
|
|
23
24
|
authorized: boolean;
|
|
25
|
+
enforced: boolean;
|
|
24
26
|
violation?: FlowViolation;
|
|
25
27
|
};
|
|
26
28
|
/** Return all recorded violations */
|
|
@@ -10,6 +10,7 @@ export class FlowEnforcer {
|
|
|
10
10
|
swarmId;
|
|
11
11
|
enforce;
|
|
12
12
|
violations = [];
|
|
13
|
+
static MAX_VIOLATIONS = 1000;
|
|
13
14
|
constructor(graph, swarmId, enforceMode) {
|
|
14
15
|
this.graph = graph;
|
|
15
16
|
this.swarmId = swarmId;
|
|
@@ -18,26 +19,37 @@ export class FlowEnforcer {
|
|
|
18
19
|
/**
|
|
19
20
|
* Check whether a message is authorized and record any violation.
|
|
20
21
|
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
22
|
+
* Returns BOTH `authorized` (the policy decision) and `enforced` (whether the
|
|
23
|
+
* decision is actually applied). Callers must read both — taking action based
|
|
24
|
+
* solely on `authorized` would let `enforce=false` silently bypass the policy.
|
|
24
25
|
*/
|
|
25
26
|
checkAndRecord(fromSlug, toSlug, messageContent) {
|
|
26
27
|
if (this.graph.isAuthorized(fromSlug, toSlug)) {
|
|
27
|
-
return { authorized: true };
|
|
28
|
+
return { authorized: true, enforced: this.enforce };
|
|
28
29
|
}
|
|
29
30
|
const violation = {
|
|
30
31
|
violationId: randomUUID(),
|
|
31
32
|
swarmId: this.swarmId,
|
|
32
33
|
fromAgentSlug: fromSlug,
|
|
33
34
|
toAgentSlug: toSlug,
|
|
35
|
+
// Truncated preview only; for sensitive traffic, redact via a hook before
|
|
36
|
+
// it reaches this enforcer. Cap means an attacker can't fill memory with
|
|
37
|
+
// long messages either.
|
|
34
38
|
messagePreview: messageContent.slice(0, 120),
|
|
35
39
|
detectedAt: new Date().toISOString(),
|
|
36
40
|
action: this.enforce ? 'blocked' : 'logged',
|
|
37
41
|
};
|
|
42
|
+
// FIFO eviction so a sustained attack can't grow violations to GB-scale.
|
|
43
|
+
if (this.violations.length >= FlowEnforcer.MAX_VIOLATIONS) {
|
|
44
|
+
this.violations.shift();
|
|
45
|
+
}
|
|
38
46
|
this.violations.push(violation);
|
|
39
47
|
return {
|
|
40
|
-
|
|
48
|
+
// Policy decision: NOT authorized. Whether the caller blocks the send is
|
|
49
|
+
// governed by `enforced`, which is exposed separately so callers cannot
|
|
50
|
+
// accidentally treat audit-mode as "permitted".
|
|
51
|
+
authorized: false,
|
|
52
|
+
enforced: this.enforce,
|
|
41
53
|
violation,
|
|
42
54
|
};
|
|
43
55
|
}
|
|
@@ -11,6 +11,9 @@ import type { FlowEdge } from '../../../shared/src/types/communication-flow.js';
|
|
|
11
11
|
export declare function toAscii(edges: FlowEdge[], title?: string): string;
|
|
12
12
|
/**
|
|
13
13
|
* Render edges as a DOT language digraph (Graphviz compatible).
|
|
14
|
+
* Slugs are escaped so a malicious slug cannot inject DOT attributes
|
|
15
|
+
* (e.g., URL="javascript:..." would be rendered as a clickable link
|
|
16
|
+
* by Graphviz's SVG output without escaping).
|
|
14
17
|
*/
|
|
15
18
|
export declare function toDOT(edges: FlowEdge[], graphName?: string): string;
|
|
16
19
|
//# sourceMappingURL=flow-visualizer.d.ts.map
|