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
|
@@ -10,6 +10,23 @@ import { DEFAULT_STORE_CONFIG } from './registry.js';
|
|
|
10
10
|
* Pattern Downloader
|
|
11
11
|
* Handles secure download and verification of patterns
|
|
12
12
|
*/
|
|
13
|
+
const MAX_DOWNLOAD_CACHE = 500;
|
|
14
|
+
const ALLOWED_GATEWAYS = new Set([
|
|
15
|
+
'https://w3s.link',
|
|
16
|
+
'https://dweb.link',
|
|
17
|
+
'https://ipfs.io',
|
|
18
|
+
'https://cloudflare-ipfs.com',
|
|
19
|
+
'https://gateway.pinata.cloud',
|
|
20
|
+
]);
|
|
21
|
+
function isAllowedGatewayUrl(url) {
|
|
22
|
+
try {
|
|
23
|
+
const parsed = new URL(url);
|
|
24
|
+
return parsed.protocol === 'https:' && ALLOWED_GATEWAYS.has(`${parsed.protocol}//${parsed.host}`);
|
|
25
|
+
}
|
|
26
|
+
catch {
|
|
27
|
+
return false;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
13
30
|
export class PatternDownloader {
|
|
14
31
|
config;
|
|
15
32
|
downloadCache;
|
|
@@ -75,20 +92,45 @@ export class PatternDownloader {
|
|
|
75
92
|
console.log(`[Download] Checksum verified!`);
|
|
76
93
|
}
|
|
77
94
|
}
|
|
78
|
-
// Verify signature if available
|
|
95
|
+
// Verify signature if available — fail closed when requireVerification is set
|
|
79
96
|
if (pattern.signature && pattern.publicKey) {
|
|
80
|
-
const sigVerified = this.verifySignature(content, pattern.signature, pattern.publicKey);
|
|
97
|
+
const sigVerified = await this.verifySignature(content, pattern.signature, pattern.publicKey);
|
|
81
98
|
if (!sigVerified) {
|
|
82
99
|
console.warn(`[Download] Warning: Signature verification failed!`);
|
|
100
|
+
if (this.config.requireVerification) {
|
|
101
|
+
return {
|
|
102
|
+
success: false,
|
|
103
|
+
pattern,
|
|
104
|
+
verified: false,
|
|
105
|
+
size: content.length,
|
|
106
|
+
};
|
|
107
|
+
}
|
|
83
108
|
}
|
|
84
109
|
else {
|
|
85
110
|
console.log(`[Download] Signature verified!`);
|
|
86
111
|
}
|
|
87
112
|
}
|
|
88
|
-
|
|
89
|
-
|
|
113
|
+
else if (this.config.requireVerification) {
|
|
114
|
+
// No signature/key fields supplied while strict verification is on — fail closed
|
|
115
|
+
console.warn(`[Download] Pattern lacks signature; requireVerification rejected`);
|
|
116
|
+
return {
|
|
117
|
+
success: false,
|
|
118
|
+
pattern,
|
|
119
|
+
verified: false,
|
|
120
|
+
size: content.length,
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
// Write to file atomically
|
|
124
|
+
const tmp = outputPath + '.tmp';
|
|
125
|
+
fs.writeFileSync(tmp, content);
|
|
126
|
+
fs.renameSync(tmp, outputPath);
|
|
90
127
|
console.log(`[Download] Written to: ${outputPath}`);
|
|
91
|
-
// Update cache
|
|
128
|
+
// Update cache (evict oldest when at capacity)
|
|
129
|
+
if (this.downloadCache.size >= MAX_DOWNLOAD_CACHE) {
|
|
130
|
+
const oldestKey = this.downloadCache.keys().next().value;
|
|
131
|
+
if (oldestKey !== undefined)
|
|
132
|
+
this.downloadCache.delete(oldestKey);
|
|
133
|
+
}
|
|
92
134
|
this.downloadCache.set(pattern.cid, {
|
|
93
135
|
path: outputPath,
|
|
94
136
|
downloadedAt: Date.now(),
|
|
@@ -125,11 +167,16 @@ export class PatternDownloader {
|
|
|
125
167
|
if (cid.startsWith('gs://')) {
|
|
126
168
|
return this.fetchFromGCS(cid, onProgress);
|
|
127
169
|
}
|
|
170
|
+
if (!isAllowedGatewayUrl(this.config.gateway)) {
|
|
171
|
+
console.error(`[Download] Gateway not in allowlist: ${this.config.gateway}`);
|
|
172
|
+
return null;
|
|
173
|
+
}
|
|
128
174
|
const url = `${this.config.gateway}/ipfs/${cid}`;
|
|
129
175
|
console.log(`[Download] Fetching: ${url}`);
|
|
176
|
+
const MAX_DOWNLOAD_BYTES = 50 * 1024 * 1024; // match client.ts MAX_IPFS_RESPONSE_BYTES
|
|
130
177
|
try {
|
|
131
178
|
// Real HTTP fetch with progress
|
|
132
|
-
const response = await fetch(url);
|
|
179
|
+
const response = await fetch(url, { signal: AbortSignal.timeout(30000) });
|
|
133
180
|
if (!response.ok) {
|
|
134
181
|
console.error(`[Download] HTTP ${response.status}: ${response.statusText}`);
|
|
135
182
|
return null;
|
|
@@ -146,6 +193,10 @@ export class PatternDownloader {
|
|
|
146
193
|
break;
|
|
147
194
|
chunks.push(value);
|
|
148
195
|
downloaded += value.length;
|
|
196
|
+
if (downloaded > MAX_DOWNLOAD_BYTES) {
|
|
197
|
+
await reader.cancel();
|
|
198
|
+
throw new Error(`Response too large: exceeded ${MAX_DOWNLOAD_BYTES} bytes`);
|
|
199
|
+
}
|
|
149
200
|
onProgress({
|
|
150
201
|
bytesDownloaded: downloaded,
|
|
151
202
|
totalBytes: contentLength,
|
|
@@ -157,7 +208,14 @@ export class PatternDownloader {
|
|
|
157
208
|
return buffer;
|
|
158
209
|
}
|
|
159
210
|
// Fallback for responses without content-length or progress
|
|
211
|
+
const cl = parseInt(response.headers.get('content-length') ?? '0', 10);
|
|
212
|
+
if (Number.isFinite(cl) && cl > MAX_DOWNLOAD_BYTES) {
|
|
213
|
+
throw new Error(`Response too large: ${cl} bytes`);
|
|
214
|
+
}
|
|
160
215
|
const arrayBuffer = await response.arrayBuffer();
|
|
216
|
+
if (arrayBuffer.byteLength > MAX_DOWNLOAD_BYTES) {
|
|
217
|
+
throw new Error(`Response too large: ${arrayBuffer.byteLength} bytes`);
|
|
218
|
+
}
|
|
161
219
|
const buffer = Buffer.from(arrayBuffer);
|
|
162
220
|
console.log(`[Download] Downloaded ${buffer.length} bytes from IPFS gateway`);
|
|
163
221
|
return buffer;
|
|
@@ -176,9 +234,16 @@ export class PatternDownloader {
|
|
|
176
234
|
continue;
|
|
177
235
|
try {
|
|
178
236
|
console.log(`[Download] Trying alternative gateway: ${gateway}`);
|
|
179
|
-
const altResponse = await fetch(`${gateway}/ipfs/${cid}
|
|
237
|
+
const altResponse = await fetch(`${gateway}/ipfs/${cid}`, { signal: AbortSignal.timeout(15000) });
|
|
180
238
|
if (altResponse.ok) {
|
|
239
|
+
const altCl = parseInt(altResponse.headers.get('content-length') ?? '0', 10);
|
|
240
|
+
if (Number.isFinite(altCl) && altCl > MAX_DOWNLOAD_BYTES) {
|
|
241
|
+
throw new Error(`Response too large: ${altCl} bytes`);
|
|
242
|
+
}
|
|
181
243
|
const arrayBuffer = await altResponse.arrayBuffer();
|
|
244
|
+
if (arrayBuffer.byteLength > MAX_DOWNLOAD_BYTES) {
|
|
245
|
+
throw new Error(`Response too large: ${arrayBuffer.byteLength} bytes`);
|
|
246
|
+
}
|
|
182
247
|
const buffer = Buffer.from(arrayBuffer);
|
|
183
248
|
console.log(`[Download] Downloaded ${buffer.length} bytes from ${gateway}`);
|
|
184
249
|
return buffer;
|
|
@@ -228,44 +293,68 @@ export class PatternDownloader {
|
|
|
228
293
|
return actualChecksum === expectedChecksum;
|
|
229
294
|
}
|
|
230
295
|
/**
|
|
231
|
-
* Verify content signature using
|
|
296
|
+
* Verify content signature using real Ed25519.
|
|
297
|
+
*
|
|
298
|
+
* CRITICAL FIX: Previously this used HMAC-SHA256 keyed with the *public* key —
|
|
299
|
+
* which is a no-op for security since the key is, by definition, public.
|
|
300
|
+
* Anyone reading the registry could recompute a valid "signature".
|
|
301
|
+
* The fallback at the bottom returned true for length>20, which made the
|
|
302
|
+
* function effectively a length check rather than a signature check.
|
|
303
|
+
* Now uses @noble/ed25519 verifyAsync, the same library used in publish.ts,
|
|
304
|
+
* and fails closed on any error.
|
|
232
305
|
*/
|
|
233
|
-
verifySignature(content, signature, publicKey) {
|
|
306
|
+
async verifySignature(content, signature, publicKey) {
|
|
234
307
|
// Check signature format
|
|
235
308
|
if (!signature.startsWith('ed25519:') || !publicKey.startsWith('ed25519:')) {
|
|
236
309
|
return false;
|
|
237
310
|
}
|
|
238
311
|
try {
|
|
239
|
-
|
|
312
|
+
const ed = await import('@noble/ed25519');
|
|
240
313
|
const sigHex = signature.replace('ed25519:', '');
|
|
241
314
|
const keyHex = publicKey.replace('ed25519:', '');
|
|
242
|
-
//
|
|
243
|
-
const
|
|
244
|
-
|
|
245
|
-
.update(content)
|
|
246
|
-
.digest('hex');
|
|
247
|
-
// Constant-time comparison to prevent timing attacks
|
|
248
|
-
return crypto.timingSafeEqual(Buffer.from(sigHex, 'hex'), Buffer.from(expectedSig, 'hex'));
|
|
315
|
+
// Real Ed25519 signature verification — fail-closed on any mismatch
|
|
316
|
+
const isValid = await ed.verifyAsync(Buffer.from(sigHex, 'hex'), content, Buffer.from(keyHex, 'hex'));
|
|
317
|
+
return isValid === true;
|
|
249
318
|
}
|
|
250
319
|
catch {
|
|
251
|
-
|
|
252
|
-
return signature.length > 20 && publicKey.length > 20;
|
|
320
|
+
return false;
|
|
253
321
|
}
|
|
254
322
|
}
|
|
255
323
|
/**
|
|
256
|
-
* Resolve output path for pattern
|
|
324
|
+
* Resolve output path for pattern.
|
|
325
|
+
*
|
|
326
|
+
* CRITICAL: pattern.name and pattern.version come from registry data fetched
|
|
327
|
+
* over the network. Without strict validation, an attacker who controls the
|
|
328
|
+
* registry response can write to arbitrary paths (e.g. ~/.claude/helpers/
|
|
329
|
+
* hook-handler.cjs) via traversal sequences in pattern.name.
|
|
257
330
|
*/
|
|
258
331
|
resolveOutputPath(pattern, options) {
|
|
332
|
+
// Strict allowlist — no slashes, no dots-only, no traversal
|
|
333
|
+
if (!/^[a-zA-Z0-9_-][a-zA-Z0-9._-]{0,63}$/.test(pattern.name) || pattern.name.includes('..')) {
|
|
334
|
+
throw new Error(`Invalid pattern name: ${pattern.name}`);
|
|
335
|
+
}
|
|
336
|
+
if (!/^[a-zA-Z0-9._-]{1,32}$/.test(pattern.version) || pattern.version.includes('..')) {
|
|
337
|
+
throw new Error(`Invalid pattern version: ${pattern.version}`);
|
|
338
|
+
}
|
|
259
339
|
if (options.output) {
|
|
260
340
|
// If output is a directory, append filename
|
|
261
341
|
if (fs.existsSync(options.output) && fs.statSync(options.output).isDirectory()) {
|
|
262
|
-
|
|
342
|
+
const candidate = path.resolve(path.join(options.output, `${pattern.name}.cfp.json`));
|
|
343
|
+
const root = path.resolve(options.output);
|
|
344
|
+
if (!candidate.startsWith(root + path.sep)) {
|
|
345
|
+
throw new Error('Output path escapes target directory');
|
|
346
|
+
}
|
|
347
|
+
return candidate;
|
|
263
348
|
}
|
|
264
|
-
return options.output;
|
|
349
|
+
return path.resolve(options.output);
|
|
265
350
|
}
|
|
266
|
-
// Default: cache directory
|
|
351
|
+
// Default: cache directory — must remain within cacheDir
|
|
267
352
|
const cacheDir = path.resolve(this.config.cacheDir);
|
|
268
|
-
|
|
353
|
+
const candidate = path.resolve(path.join(cacheDir, `${pattern.name}-${pattern.version}.cfp.json`));
|
|
354
|
+
if (!candidate.startsWith(cacheDir + path.sep)) {
|
|
355
|
+
throw new Error('Output path escapes cache directory');
|
|
356
|
+
}
|
|
357
|
+
return candidate;
|
|
269
358
|
}
|
|
270
359
|
/**
|
|
271
360
|
* Import downloaded pattern
|
|
@@ -37,7 +37,7 @@ export class PatternPublisher {
|
|
|
37
37
|
let signature;
|
|
38
38
|
let publicKey;
|
|
39
39
|
if (options.privateKeyPath && fs.existsSync(options.privateKeyPath)) {
|
|
40
|
-
const signResult = this.signContent(contentBuffer, options.privateKeyPath);
|
|
40
|
+
const signResult = await this.signContent(contentBuffer, options.privateKeyPath);
|
|
41
41
|
signature = signResult.signature;
|
|
42
42
|
publicKey = signResult.publicKey;
|
|
43
43
|
console.log(`[Publish] Content signed`);
|
|
@@ -148,21 +148,20 @@ export class PatternPublisher {
|
|
|
148
148
|
}
|
|
149
149
|
}
|
|
150
150
|
/**
|
|
151
|
-
* Sign content with private key
|
|
151
|
+
* Sign content with Ed25519 private key
|
|
152
152
|
*/
|
|
153
|
-
signContent(content, privateKeyPath) {
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
const
|
|
158
|
-
.
|
|
159
|
-
.update(
|
|
160
|
-
|
|
161
|
-
const
|
|
162
|
-
crypto.createHash('sha256').update(privateKey).digest('hex').slice(0, 32);
|
|
153
|
+
async signContent(content, privateKeyPath) {
|
|
154
|
+
const ed = await import('@noble/ed25519');
|
|
155
|
+
const keyHex = fs.readFileSync(privateKeyPath, 'utf-8').trim();
|
|
156
|
+
// Accept 64-char hex (32-byte seed) directly; otherwise derive via SHA-256
|
|
157
|
+
const privKeyBytes = keyHex.length === 64
|
|
158
|
+
? Buffer.from(keyHex, 'hex')
|
|
159
|
+
: crypto.createHash('sha256').update(keyHex).digest();
|
|
160
|
+
const pubKeyBytes = await ed.getPublicKeyAsync(privKeyBytes);
|
|
161
|
+
const sigBytes = await ed.signAsync(content, privKeyBytes);
|
|
163
162
|
return {
|
|
164
|
-
signature:
|
|
165
|
-
publicKey,
|
|
163
|
+
signature: 'ed25519:' + Buffer.from(sigBytes).toString('hex'),
|
|
164
|
+
publicKey: 'ed25519:' + Buffer.from(pubKeyBytes).toString('hex'),
|
|
166
165
|
};
|
|
167
166
|
}
|
|
168
167
|
/**
|
|
@@ -42,11 +42,11 @@ export declare function deserializeRegistry(json: string): PatternRegistry;
|
|
|
42
42
|
/**
|
|
43
43
|
* Sign registry with private key
|
|
44
44
|
*/
|
|
45
|
-
export declare function signRegistry(registry: PatternRegistry, privateKey: string): PatternRegistry
|
|
45
|
+
export declare function signRegistry(registry: PatternRegistry, privateKey: string): Promise<PatternRegistry>;
|
|
46
46
|
/**
|
|
47
|
-
* Verify registry signature
|
|
47
|
+
* Verify registry signature using real Ed25519
|
|
48
48
|
*/
|
|
49
|
-
export declare function verifyRegistrySignature(registry: PatternRegistry): boolean
|
|
49
|
+
export declare function verifyRegistrySignature(registry: PatternRegistry): Promise<boolean>;
|
|
50
50
|
/**
|
|
51
51
|
* Merge two registries (for sync)
|
|
52
52
|
*/
|
|
@@ -38,7 +38,9 @@ export const DEFAULT_STORE_CONFIG = {
|
|
|
38
38
|
timeout: 30000,
|
|
39
39
|
cacheDir: '.monomind/patterns/cache',
|
|
40
40
|
cacheExpiry: 3600000, // 1 hour
|
|
41
|
-
|
|
41
|
+
// Default to true: tampered downloads must be rejected, not warned about.
|
|
42
|
+
// Override with --allow-unverified flag for explicit developer-only use.
|
|
43
|
+
requireVerification: true,
|
|
42
44
|
minTrustLevel: 'unverified',
|
|
43
45
|
trustedAuthors: [],
|
|
44
46
|
blockedPatterns: [],
|
|
@@ -147,7 +149,7 @@ export function getDefaultCategories() {
|
|
|
147
149
|
* Add a pattern to the registry
|
|
148
150
|
*/
|
|
149
151
|
export function addPatternToRegistry(registry, entry) {
|
|
150
|
-
const updated = { ...registry };
|
|
152
|
+
const updated = { ...registry, patterns: [...registry.patterns], authors: [...registry.authors], categories: registry.categories.map(c => ({ ...c })) };
|
|
151
153
|
// Check for existing pattern with same name
|
|
152
154
|
const existingIndex = updated.patterns.findIndex(p => p.name === entry.name);
|
|
153
155
|
if (existingIndex >= 0) {
|
|
@@ -216,34 +218,48 @@ export function deserializeRegistry(json) {
|
|
|
216
218
|
/**
|
|
217
219
|
* Sign registry with private key
|
|
218
220
|
*/
|
|
219
|
-
export function signRegistry(registry, privateKey) {
|
|
221
|
+
export async function signRegistry(registry, privateKey) {
|
|
220
222
|
const content = JSON.stringify({
|
|
221
223
|
version: registry.version,
|
|
222
224
|
updatedAt: registry.updatedAt,
|
|
223
225
|
patterns: registry.patterns.map(p => p.cid),
|
|
224
226
|
totalPatterns: registry.totalPatterns,
|
|
225
227
|
});
|
|
226
|
-
|
|
227
|
-
const
|
|
228
|
-
.
|
|
229
|
-
.update(
|
|
230
|
-
|
|
228
|
+
const ed = await import('@noble/ed25519');
|
|
229
|
+
const privKeyBytes = privateKey.length === 64
|
|
230
|
+
? Buffer.from(privateKey, 'hex')
|
|
231
|
+
: crypto.createHash('sha256').update(privateKey).digest();
|
|
232
|
+
const pubKeyBytes = await ed.getPublicKeyAsync(privKeyBytes);
|
|
233
|
+
const sigBytes = await ed.signAsync(Buffer.from(content), privKeyBytes);
|
|
231
234
|
return {
|
|
232
235
|
...registry,
|
|
233
|
-
registrySignature:
|
|
234
|
-
registryPublicKey: 'ed25519:' +
|
|
236
|
+
registrySignature: 'ed25519:' + Buffer.from(sigBytes).toString('hex'),
|
|
237
|
+
registryPublicKey: 'ed25519:' + Buffer.from(pubKeyBytes).toString('hex'),
|
|
235
238
|
};
|
|
236
239
|
}
|
|
237
240
|
/**
|
|
238
|
-
* Verify registry signature
|
|
241
|
+
* Verify registry signature using real Ed25519
|
|
239
242
|
*/
|
|
240
|
-
export function verifyRegistrySignature(registry) {
|
|
241
|
-
if (!registry.registrySignature || !registry.registryPublicKey)
|
|
243
|
+
export async function verifyRegistrySignature(registry) {
|
|
244
|
+
if (!registry.registrySignature || !registry.registryPublicKey)
|
|
245
|
+
return false;
|
|
246
|
+
const sigHex = registry.registrySignature.replace(/^ed25519:/, '');
|
|
247
|
+
const pubKeyHex = registry.registryPublicKey.replace(/^ed25519:/, '');
|
|
248
|
+
if (sigHex.length !== 128 || pubKeyHex.length !== 64)
|
|
249
|
+
return false;
|
|
250
|
+
const content = JSON.stringify({
|
|
251
|
+
version: registry.version,
|
|
252
|
+
updatedAt: registry.updatedAt,
|
|
253
|
+
patterns: registry.patterns.map(p => p.cid),
|
|
254
|
+
totalPatterns: registry.totalPatterns,
|
|
255
|
+
});
|
|
256
|
+
try {
|
|
257
|
+
const ed = await import('@noble/ed25519');
|
|
258
|
+
return await ed.verifyAsync(Buffer.from(sigHex, 'hex'), Buffer.from(content), Buffer.from(pubKeyHex, 'hex'));
|
|
259
|
+
}
|
|
260
|
+
catch {
|
|
242
261
|
return false;
|
|
243
262
|
}
|
|
244
|
-
// In production: Use actual Ed25519 verification
|
|
245
|
-
// For now, just check signature exists
|
|
246
|
-
return registry.registrySignature.length === 64;
|
|
247
263
|
}
|
|
248
264
|
/**
|
|
249
265
|
* Merge two registries (for sync)
|
|
@@ -2,8 +2,10 @@
|
|
|
2
2
|
* Update checker for @monomind packages
|
|
3
3
|
* Queries npm registry and compares versions
|
|
4
4
|
*/
|
|
5
|
+
import { createRequire } from 'module';
|
|
5
6
|
import * as semver from 'semver';
|
|
6
|
-
import {
|
|
7
|
+
import { reserveCheck, recordCheck, getCachedVersions } from './rate-limiter.js';
|
|
8
|
+
const require = createRequire(import.meta.url);
|
|
7
9
|
const DEFAULT_CONFIG = {
|
|
8
10
|
enabled: true,
|
|
9
11
|
checkIntervalHours: 24,
|
|
@@ -24,7 +26,15 @@ const MONOMIND_PACKAGES = [
|
|
|
24
26
|
'monomind',
|
|
25
27
|
'@monomind/cli',
|
|
26
28
|
];
|
|
29
|
+
// npm package name regex — covers plain names and @scope/name forms.
|
|
30
|
+
// Validates before using the name in URLs or filesystem paths.
|
|
31
|
+
const NPM_NAME_RE = /^(@[a-z0-9-~][a-z0-9-._~]*\/)?[a-z0-9-~][a-z0-9-._~]*$/i;
|
|
32
|
+
function isValidNpmName(name) {
|
|
33
|
+
return NPM_NAME_RE.test(name) && !name.includes('..') && name.length <= 214;
|
|
34
|
+
}
|
|
27
35
|
async function fetchPackageInfo(packageName) {
|
|
36
|
+
if (!isValidNpmName(packageName))
|
|
37
|
+
return null;
|
|
28
38
|
try {
|
|
29
39
|
const response = await fetch(`https://registry.npmjs.org/${encodeURIComponent(packageName)}`, {
|
|
30
40
|
headers: { Accept: 'application/json' },
|
|
@@ -74,6 +84,8 @@ function shouldAutoUpdate(updateType, priority, config) {
|
|
|
74
84
|
return false;
|
|
75
85
|
}
|
|
76
86
|
export function getInstalledVersion(packageName) {
|
|
87
|
+
if (!isValidNpmName(packageName))
|
|
88
|
+
return null;
|
|
77
89
|
try {
|
|
78
90
|
// Try to find the package in node_modules
|
|
79
91
|
const possiblePaths = [
|
|
@@ -85,7 +97,6 @@ export function getInstalledVersion(packageName) {
|
|
|
85
97
|
try {
|
|
86
98
|
// Use dynamic import with require for package.json
|
|
87
99
|
const resolved = require.resolve(modulePath, { paths: [process.cwd()] });
|
|
88
|
-
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
89
100
|
const pkg = require(resolved);
|
|
90
101
|
return pkg.version;
|
|
91
102
|
}
|
|
@@ -100,8 +111,8 @@ export function getInstalledVersion(packageName) {
|
|
|
100
111
|
}
|
|
101
112
|
}
|
|
102
113
|
export async function checkForUpdates(config = DEFAULT_CONFIG) {
|
|
103
|
-
// Check rate limit
|
|
104
|
-
const rateCheck =
|
|
114
|
+
// Check rate limit and atomically reserve this check slot
|
|
115
|
+
const rateCheck = reserveCheck(config.checkIntervalHours);
|
|
105
116
|
if (!rateCheck.allowed) {
|
|
106
117
|
// Return cached results if available
|
|
107
118
|
const cached = getCachedVersions();
|
|
@@ -158,6 +169,8 @@ export async function checkForUpdates(config = DEFAULT_CONFIG) {
|
|
|
158
169
|
return { results: updates, skipped: false };
|
|
159
170
|
}
|
|
160
171
|
export async function checkSinglePackage(packageName, config = DEFAULT_CONFIG) {
|
|
172
|
+
if (!isValidNpmName(packageName))
|
|
173
|
+
return null;
|
|
161
174
|
const currentVersion = getInstalledVersion(packageName);
|
|
162
175
|
if (!currentVersion) {
|
|
163
176
|
return null;
|
|
@@ -2,10 +2,14 @@
|
|
|
2
2
|
* Update executor - performs actual package updates
|
|
3
3
|
* Includes rollback capability
|
|
4
4
|
*/
|
|
5
|
-
import {
|
|
5
|
+
import { execFile } from 'child_process';
|
|
6
6
|
import * as fs from 'fs';
|
|
7
7
|
import * as path from 'path';
|
|
8
8
|
import * as os from 'os';
|
|
9
|
+
import * as semver from 'semver';
|
|
10
|
+
function execFileAsync(cmd, args) {
|
|
11
|
+
return new Promise((resolve, reject) => execFile(cmd, args, (err) => (err ? reject(err) : resolve())));
|
|
12
|
+
}
|
|
9
13
|
import { validateUpdate } from './validator.js';
|
|
10
14
|
const HISTORY_FILE = path.join(os.homedir(), '.monomind', 'update-history.json');
|
|
11
15
|
const MAX_HISTORY_ENTRIES = 100;
|
|
@@ -31,7 +35,9 @@ function saveHistory(history) {
|
|
|
31
35
|
ensureDir();
|
|
32
36
|
// Keep only last N entries
|
|
33
37
|
const trimmed = history.slice(-MAX_HISTORY_ENTRIES);
|
|
34
|
-
|
|
38
|
+
const tmp = HISTORY_FILE + '.tmp';
|
|
39
|
+
fs.writeFileSync(tmp, JSON.stringify(trimmed, null, 2));
|
|
40
|
+
fs.renameSync(tmp, HISTORY_FILE);
|
|
35
41
|
}
|
|
36
42
|
function recordUpdate(entry) {
|
|
37
43
|
const history = loadHistory();
|
|
@@ -59,13 +65,13 @@ export async function executeUpdate(update, installedPackages, dryRun = false) {
|
|
|
59
65
|
};
|
|
60
66
|
}
|
|
61
67
|
try {
|
|
62
|
-
// Execute npm install
|
|
63
|
-
const
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
});
|
|
68
|
+
// Execute npm install — use execFile to avoid shell injection
|
|
69
|
+
const pkg = update.package;
|
|
70
|
+
const version = update.latestVersion;
|
|
71
|
+
if (!semver.valid(version)) {
|
|
72
|
+
throw new Error(`Invalid version: ${version}`);
|
|
73
|
+
}
|
|
74
|
+
await execFileAsync('npm', ['install', `${pkg}@${version}`, '--save-exact']);
|
|
69
75
|
// Record successful update
|
|
70
76
|
recordUpdate({
|
|
71
77
|
timestamp: new Date().toISOString(),
|
|
@@ -126,11 +132,10 @@ export async function rollbackUpdate(packageName) {
|
|
|
126
132
|
return { success: false, message: 'No update history available' };
|
|
127
133
|
}
|
|
128
134
|
// Find the last successful update for this package (or any if not specified)
|
|
135
|
+
const reversed = [...history].reverse();
|
|
129
136
|
const lastUpdate = packageName
|
|
130
|
-
?
|
|
131
|
-
|
|
132
|
-
.find((h) => h.package === packageName && h.success && h.rollbackAvailable)
|
|
133
|
-
: history.reverse().find((h) => h.success && h.rollbackAvailable);
|
|
137
|
+
? reversed.find((h) => h.package === packageName && h.success && h.rollbackAvailable)
|
|
138
|
+
: reversed.find((h) => h.success && h.rollbackAvailable);
|
|
134
139
|
if (!lastUpdate) {
|
|
135
140
|
return {
|
|
136
141
|
success: false,
|
|
@@ -140,13 +145,13 @@ export async function rollbackUpdate(packageName) {
|
|
|
140
145
|
};
|
|
141
146
|
}
|
|
142
147
|
try {
|
|
143
|
-
// Install the previous version
|
|
144
|
-
const
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
});
|
|
148
|
+
// Install the previous version — use execFile to avoid shell injection
|
|
149
|
+
const pkg = lastUpdate.package;
|
|
150
|
+
const version = lastUpdate.fromVersion;
|
|
151
|
+
if (!semver.valid(version)) {
|
|
152
|
+
throw new Error(`Invalid version: ${version}`);
|
|
153
|
+
}
|
|
154
|
+
await execFileAsync('npm', ['install', `${pkg}@${version}`, '--save-exact']);
|
|
150
155
|
// Record the rollback
|
|
151
156
|
recordUpdate({
|
|
152
157
|
timestamp: new Date().toISOString(),
|
|
@@ -14,6 +14,17 @@ export declare function shouldCheckForUpdates(intervalHours?: number): {
|
|
|
14
14
|
allowed: boolean;
|
|
15
15
|
reason?: string;
|
|
16
16
|
};
|
|
17
|
+
/**
|
|
18
|
+
* Atomically check the daily limit and pre-increment the counter.
|
|
19
|
+
* Returns false if already at the limit. Callers MUST call recordCheck
|
|
20
|
+
* only after a successful reserveCheck, so that limit enforcement and
|
|
21
|
+
* increment happen in the same synchronous turn (no await gap between
|
|
22
|
+
* them), preventing two concurrent callers both seeing "allowed".
|
|
23
|
+
*/
|
|
24
|
+
export declare function reserveCheck(intervalHours?: number): {
|
|
25
|
+
allowed: boolean;
|
|
26
|
+
reason?: string;
|
|
27
|
+
};
|
|
17
28
|
export declare function recordCheck(packageVersions: Record<string, string>): void;
|
|
18
29
|
export declare function getCachedVersions(): Record<string, string>;
|
|
19
30
|
export declare function clearCache(): void;
|
|
@@ -43,7 +43,9 @@ export function loadState() {
|
|
|
43
43
|
}
|
|
44
44
|
export function saveState(state) {
|
|
45
45
|
ensureDir();
|
|
46
|
-
|
|
46
|
+
const tmp = STATE_FILE + '.tmp';
|
|
47
|
+
fs.writeFileSync(tmp, JSON.stringify(state, null, 2));
|
|
48
|
+
fs.renameSync(tmp, STATE_FILE);
|
|
47
49
|
}
|
|
48
50
|
export function shouldCheckForUpdates(intervalHours = DEFAULT_INTERVAL_HOURS) {
|
|
49
51
|
// Skip in CI environments
|
|
@@ -78,10 +80,28 @@ export function shouldCheckForUpdates(intervalHours = DEFAULT_INTERVAL_HOURS) {
|
|
|
78
80
|
}
|
|
79
81
|
return { allowed: true };
|
|
80
82
|
}
|
|
81
|
-
|
|
83
|
+
/**
|
|
84
|
+
* Atomically check the daily limit and pre-increment the counter.
|
|
85
|
+
* Returns false if already at the limit. Callers MUST call recordCheck
|
|
86
|
+
* only after a successful reserveCheck, so that limit enforcement and
|
|
87
|
+
* increment happen in the same synchronous turn (no await gap between
|
|
88
|
+
* them), preventing two concurrent callers both seeing "allowed".
|
|
89
|
+
*/
|
|
90
|
+
export function reserveCheck(intervalHours = DEFAULT_INTERVAL_HOURS) {
|
|
91
|
+
const decision = shouldCheckForUpdates(intervalHours);
|
|
92
|
+
if (!decision.allowed)
|
|
93
|
+
return decision;
|
|
94
|
+
// Increment immediately, before any async work, so concurrent callers
|
|
95
|
+
// see an updated count on their next tick.
|
|
82
96
|
const state = loadState();
|
|
83
|
-
state.lastCheck = new Date().toISOString();
|
|
84
97
|
state.checksToday += 1;
|
|
98
|
+
state.lastCheck = new Date().toISOString();
|
|
99
|
+
saveState(state);
|
|
100
|
+
return { allowed: true };
|
|
101
|
+
}
|
|
102
|
+
export function recordCheck(packageVersions) {
|
|
103
|
+
// Update only package versions; count/timestamp already incremented by reserveCheck
|
|
104
|
+
const state = loadState();
|
|
85
105
|
state.packageVersions = { ...state.packageVersions, ...packageVersions };
|
|
86
106
|
saveState(state);
|
|
87
107
|
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Parse a JSONL (newline-delimited JSON) string, skipping malformed lines.
|
|
3
|
+
* Never throws — bad lines are silently dropped.
|
|
4
|
+
*/
|
|
5
|
+
export function parseJsonl(content) {
|
|
6
|
+
if (!content.trim())
|
|
7
|
+
return [];
|
|
8
|
+
return content
|
|
9
|
+
.split('\n')
|
|
10
|
+
.flatMap((line) => {
|
|
11
|
+
const trimmed = line.trim();
|
|
12
|
+
if (!trimmed)
|
|
13
|
+
return [];
|
|
14
|
+
try {
|
|
15
|
+
return [JSON.parse(trimmed)];
|
|
16
|
+
}
|
|
17
|
+
catch {
|
|
18
|
+
return [];
|
|
19
|
+
}
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=parse-jsonl.js.map
|