@claude-flow/cli 3.32.8 → 3.32.10
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/analysis/analyze-code-quality.md +178 -178
- package/.claude/agents/analysis/code-analyzer.md +209 -209
- package/.claude/agents/analysis/code-review/analyze-code-quality.md +178 -178
- package/.claude/agents/architecture/arch-system-design.md +156 -156
- package/.claude/agents/architecture/system-design/arch-system-design.md +154 -154
- package/.claude/agents/browser/browser-agent.yaml +182 -182
- package/.claude/agents/consensus/byzantine-coordinator.md +62 -62
- package/.claude/agents/consensus/crdt-synchronizer.md +996 -996
- package/.claude/agents/consensus/gossip-coordinator.md +62 -62
- package/.claude/agents/consensus/performance-benchmarker.md +850 -850
- package/.claude/agents/consensus/quorum-manager.md +822 -822
- package/.claude/agents/consensus/raft-manager.md +62 -62
- package/.claude/agents/consensus/security-manager.md +621 -621
- package/.claude/agents/core/planner.md +374 -374
- package/.claude/agents/custom/test-long-runner.md +44 -44
- package/.claude/agents/data/data-ml-model.md +444 -444
- package/.claude/agents/data/ml/data-ml-model.md +192 -192
- package/.claude/agents/development/backend/dev-backend-api.md +141 -141
- package/.claude/agents/development/dev-backend-api.md +344 -344
- package/.claude/agents/devops/ci-cd/ops-cicd-github.md +163 -163
- package/.claude/agents/devops/ops-cicd-github.md +164 -164
- package/.claude/agents/documentation/api-docs/docs-api-openapi.md +173 -173
- package/.claude/agents/documentation/docs-api-openapi.md +354 -354
- package/.claude/agents/flow-nexus/app-store.md +87 -87
- package/.claude/agents/flow-nexus/authentication.md +68 -68
- package/.claude/agents/flow-nexus/challenges.md +80 -80
- package/.claude/agents/flow-nexus/neural-network.md +87 -87
- package/.claude/agents/flow-nexus/payments.md +82 -82
- package/.claude/agents/flow-nexus/sandbox.md +75 -75
- package/.claude/agents/flow-nexus/swarm.md +75 -75
- package/.claude/agents/flow-nexus/user-tools.md +95 -95
- package/.claude/agents/flow-nexus/workflow.md +83 -83
- package/.claude/agents/github/code-review-swarm.md +377 -377
- package/.claude/agents/github/github-modes.md +172 -172
- package/.claude/agents/github/issue-tracker.md +575 -575
- package/.claude/agents/github/multi-repo-swarm.md +552 -552
- package/.claude/agents/github/pr-manager.md +437 -437
- package/.claude/agents/github/project-board-sync.md +508 -508
- package/.claude/agents/github/release-manager.md +604 -604
- package/.claude/agents/github/release-swarm.md +582 -582
- package/.claude/agents/github/repo-architect.md +397 -397
- package/.claude/agents/github/swarm-issue.md +572 -572
- package/.claude/agents/github/swarm-pr.md +427 -427
- package/.claude/agents/github/sync-coordinator.md +451 -451
- package/.claude/agents/github/workflow-automation.md +902 -902
- package/.claude/agents/goal/agent.md +815 -815
- package/.claude/agents/optimization/benchmark-suite.md +664 -664
- package/.claude/agents/optimization/load-balancer.md +430 -430
- package/.claude/agents/optimization/performance-monitor.md +671 -671
- package/.claude/agents/optimization/resource-allocator.md +673 -673
- package/.claude/agents/optimization/topology-optimizer.md +807 -807
- package/.claude/agents/payments/agentic-payments.md +126 -126
- package/.claude/agents/sona/sona-learning-optimizer.md +74 -74
- package/.claude/agents/sparc/architecture.md +698 -698
- package/.claude/agents/sparc/pseudocode.md +519 -519
- package/.claude/agents/sparc/refinement.md +801 -801
- package/.claude/agents/sparc/specification.md +477 -477
- package/.claude/agents/specialized/mobile/spec-mobile-react-native.md +224 -224
- package/.claude/agents/specialized/spec-mobile-react-native.md +226 -226
- package/.claude/agents/sublinear/consensus-coordinator.md +337 -337
- package/.claude/agents/sublinear/matrix-optimizer.md +184 -184
- package/.claude/agents/sublinear/pagerank-analyzer.md +298 -298
- package/.claude/agents/sublinear/performance-optimizer.md +367 -367
- package/.claude/agents/sublinear/trading-predictor.md +245 -245
- package/.claude/agents/swarm/adaptive-coordinator.md +1126 -1126
- package/.claude/agents/swarm/hierarchical-coordinator.md +709 -709
- package/.claude/agents/swarm/mesh-coordinator.md +962 -962
- package/.claude/agents/templates/automation-smart-agent.md +204 -204
- package/.claude/agents/templates/base-template-generator.md +289 -289
- package/.claude/agents/templates/coordinator-swarm-init.md +89 -89
- package/.claude/agents/templates/github-pr-manager.md +176 -176
- package/.claude/agents/templates/implementer-sparc-coder.md +258 -258
- package/.claude/agents/templates/memory-coordinator.md +186 -186
- package/.claude/agents/templates/orchestrator-task.md +138 -138
- package/.claude/agents/templates/performance-analyzer.md +198 -198
- package/.claude/agents/templates/sparc-coordinator.md +513 -513
- package/.claude/agents/testing/production-validator.md +394 -394
- package/.claude/agents/testing/tdd-london-swarm.md +243 -243
- package/.claude/agents/v3/aidefence-guardian.md +282 -282
- package/.claude/agents/v3/claims-authorizer.md +208 -208
- package/.claude/agents/v3/collective-intelligence-coordinator.md +993 -993
- package/.claude/agents/v3/ddd-domain-expert.md +220 -220
- package/.claude/agents/v3/injection-analyst.md +236 -236
- package/.claude/agents/v3/performance-engineer.md +1233 -1233
- package/.claude/agents/v3/pii-detector.md +151 -151
- package/.claude/agents/v3/reasoningbank-learner.md +213 -213
- package/.claude/agents/v3/security-architect-aidefence.md +410 -410
- package/.claude/agents/v3/security-architect.md +867 -867
- package/.claude/agents/v3/swarm-memory-manager.md +157 -157
- package/.claude/agents/v3/v3-integration-architect.md +205 -205
- package/.claude/commands/agents/README.md +50 -50
- package/.claude/commands/agents/agent-capabilities.md +140 -140
- package/.claude/commands/agents/agent-coordination.md +28 -28
- package/.claude/commands/agents/agent-spawning.md +28 -28
- package/.claude/commands/agents/agent-types.md +216 -216
- package/.claude/commands/agents/health.md +139 -139
- package/.claude/commands/agents/list.md +100 -100
- package/.claude/commands/agents/logs.md +130 -130
- package/.claude/commands/agents/metrics.md +122 -122
- package/.claude/commands/agents/pool.md +127 -127
- package/.claude/commands/agents/spawn.md +140 -140
- package/.claude/commands/agents/status.md +115 -115
- package/.claude/commands/agents/stop.md +102 -102
- package/.claude/commands/analysis/COMMAND_COMPLIANCE_REPORT.md +53 -53
- package/.claude/commands/analysis/README.md +9 -9
- package/.claude/commands/analysis/bottleneck-detect.md +162 -162
- package/.claude/commands/analysis/performance-bottlenecks.md +58 -58
- package/.claude/commands/analysis/performance-report.md +25 -25
- package/.claude/commands/analysis/token-efficiency.md +44 -44
- package/.claude/commands/analysis/token-usage.md +25 -25
- package/.claude/commands/automation/README.md +9 -9
- package/.claude/commands/automation/auto-agent.md +122 -122
- package/.claude/commands/automation/self-healing.md +105 -105
- package/.claude/commands/automation/session-memory.md +89 -89
- package/.claude/commands/automation/smart-agents.md +72 -72
- package/.claude/commands/automation/smart-spawn.md +25 -25
- package/.claude/commands/automation/workflow-select.md +25 -25
- package/.claude/commands/claude-flow-help.md +103 -103
- package/.claude/commands/claude-flow-memory.md +107 -107
- package/.claude/commands/claude-flow-swarm.md +205 -205
- package/.claude/commands/coordination/README.md +9 -9
- package/.claude/commands/coordination/agent-spawn.md +25 -25
- package/.claude/commands/coordination/init.md +44 -44
- package/.claude/commands/coordination/orchestrate.md +43 -43
- package/.claude/commands/coordination/spawn.md +45 -45
- package/.claude/commands/coordination/swarm-init.md +85 -85
- package/.claude/commands/coordination/task-orchestrate.md +25 -25
- package/.claude/commands/github/README.md +11 -11
- package/.claude/commands/github/code-review-swarm.md +513 -513
- package/.claude/commands/github/code-review.md +25 -25
- package/.claude/commands/github/github-modes.md +146 -146
- package/.claude/commands/github/github-swarm.md +121 -121
- package/.claude/commands/github/issue-tracker.md +291 -291
- package/.claude/commands/github/issue-triage.md +25 -25
- package/.claude/commands/github/multi-repo-swarm.md +518 -518
- package/.claude/commands/github/pr-enhance.md +26 -26
- package/.claude/commands/github/pr-manager.md +169 -169
- package/.claude/commands/github/project-board-sync.md +470 -470
- package/.claude/commands/github/release-manager.md +339 -339
- package/.claude/commands/github/release-swarm.md +543 -543
- package/.claude/commands/github/repo-analyze.md +25 -25
- package/.claude/commands/github/repo-architect.md +366 -366
- package/.claude/commands/github/swarm-issue.md +484 -484
- package/.claude/commands/github/swarm-pr.md +287 -287
- package/.claude/commands/github/sync-coordinator.md +302 -302
- package/.claude/commands/github/workflow-automation.md +441 -441
- package/.claude/commands/hive-mind/README.md +17 -17
- package/.claude/commands/hive-mind/hive-mind-consensus.md +8 -8
- package/.claude/commands/hive-mind/hive-mind-init.md +18 -18
- package/.claude/commands/hive-mind/hive-mind-memory.md +8 -8
- package/.claude/commands/hive-mind/hive-mind-metrics.md +8 -8
- package/.claude/commands/hive-mind/hive-mind-resume.md +8 -8
- package/.claude/commands/hive-mind/hive-mind-sessions.md +8 -8
- package/.claude/commands/hive-mind/hive-mind-spawn.md +21 -21
- package/.claude/commands/hive-mind/hive-mind-status.md +8 -8
- package/.claude/commands/hive-mind/hive-mind-stop.md +8 -8
- package/.claude/commands/hive-mind/hive-mind-wizard.md +8 -8
- package/.claude/commands/hive-mind/hive-mind.md +27 -27
- package/.claude/commands/hooks/README.md +11 -11
- package/.claude/commands/hooks/overview.md +57 -57
- package/.claude/commands/hooks/post-edit.md +117 -117
- package/.claude/commands/hooks/post-task.md +112 -112
- package/.claude/commands/hooks/pre-edit.md +113 -113
- package/.claude/commands/hooks/pre-task.md +111 -111
- package/.claude/commands/hooks/session-end.md +118 -118
- package/.claude/commands/hooks/setup.md +102 -102
- package/.claude/commands/memory/README.md +9 -9
- package/.claude/commands/memory/memory-persist.md +25 -25
- package/.claude/commands/memory/memory-search.md +25 -25
- package/.claude/commands/memory/memory-usage.md +25 -25
- package/.claude/commands/memory/neural.md +47 -47
- package/.claude/commands/monitoring/README.md +9 -9
- package/.claude/commands/monitoring/agent-metrics.md +25 -25
- package/.claude/commands/monitoring/agents.md +44 -44
- package/.claude/commands/monitoring/real-time-view.md +25 -25
- package/.claude/commands/monitoring/status.md +46 -46
- package/.claude/commands/monitoring/swarm-monitor.md +25 -25
- package/.claude/commands/optimization/README.md +9 -9
- package/.claude/commands/optimization/auto-topology.md +61 -61
- package/.claude/commands/optimization/cache-manage.md +25 -25
- package/.claude/commands/optimization/parallel-execute.md +25 -25
- package/.claude/commands/optimization/parallel-execution.md +49 -49
- package/.claude/commands/optimization/topology-optimize.md +25 -25
- package/.claude/commands/pair/README.md +260 -260
- package/.claude/commands/pair/commands.md +545 -545
- package/.claude/commands/pair/config.md +509 -509
- package/.claude/commands/pair/examples.md +511 -511
- package/.claude/commands/pair/modes.md +347 -347
- package/.claude/commands/pair/session.md +406 -406
- package/.claude/commands/pair/start.md +208 -208
- package/.claude/commands/sparc/analyzer.md +51 -51
- package/.claude/commands/sparc/architect.md +53 -53
- package/.claude/commands/sparc/ask.md +97 -97
- package/.claude/commands/sparc/batch-executor.md +54 -54
- package/.claude/commands/sparc/code.md +89 -89
- package/.claude/commands/sparc/coder.md +54 -54
- package/.claude/commands/sparc/debug.md +83 -83
- package/.claude/commands/sparc/debugger.md +54 -54
- package/.claude/commands/sparc/designer.md +53 -53
- package/.claude/commands/sparc/devops.md +109 -109
- package/.claude/commands/sparc/docs-writer.md +80 -80
- package/.claude/commands/sparc/documenter.md +54 -54
- package/.claude/commands/sparc/innovator.md +54 -54
- package/.claude/commands/sparc/integration.md +83 -83
- package/.claude/commands/sparc/mcp.md +117 -117
- package/.claude/commands/sparc/memory-manager.md +54 -54
- package/.claude/commands/sparc/optimizer.md +54 -54
- package/.claude/commands/sparc/orchestrator.md +131 -131
- package/.claude/commands/sparc/post-deployment-monitoring-mode.md +83 -83
- package/.claude/commands/sparc/refinement-optimization-mode.md +83 -83
- package/.claude/commands/sparc/researcher.md +54 -54
- package/.claude/commands/sparc/reviewer.md +54 -54
- package/.claude/commands/sparc/security-review.md +80 -80
- package/.claude/commands/sparc/sparc-modes.md +174 -174
- package/.claude/commands/sparc/sparc.md +111 -111
- package/.claude/commands/sparc/spec-pseudocode.md +80 -80
- package/.claude/commands/sparc/supabase-admin.md +348 -348
- package/.claude/commands/sparc/swarm-coordinator.md +54 -54
- package/.claude/commands/sparc/tdd.md +54 -54
- package/.claude/commands/sparc/tester.md +54 -54
- package/.claude/commands/sparc/tutorial.md +79 -79
- package/.claude/commands/sparc/workflow-manager.md +54 -54
- package/.claude/commands/sparc.md +166 -166
- package/.claude/commands/stream-chain/pipeline.md +120 -120
- package/.claude/commands/stream-chain/run.md +69 -69
- package/.claude/commands/swarm/README.md +15 -15
- package/.claude/commands/swarm/analysis.md +95 -95
- package/.claude/commands/swarm/development.md +96 -96
- package/.claude/commands/swarm/examples.md +168 -168
- package/.claude/commands/swarm/maintenance.md +102 -102
- package/.claude/commands/swarm/optimization.md +117 -117
- package/.claude/commands/swarm/research.md +136 -136
- package/.claude/commands/swarm/swarm-analysis.md +8 -8
- package/.claude/commands/swarm/swarm-background.md +8 -8
- package/.claude/commands/swarm/swarm-init.md +19 -19
- package/.claude/commands/swarm/swarm-modes.md +8 -8
- package/.claude/commands/swarm/swarm-monitor.md +8 -8
- package/.claude/commands/swarm/swarm-spawn.md +19 -19
- package/.claude/commands/swarm/swarm-status.md +8 -8
- package/.claude/commands/swarm/swarm-strategies.md +8 -8
- package/.claude/commands/swarm/swarm.md +87 -87
- package/.claude/commands/swarm/testing.md +131 -131
- package/.claude/commands/training/README.md +9 -9
- package/.claude/commands/training/model-update.md +25 -25
- package/.claude/commands/training/neural-patterns.md +107 -107
- package/.claude/commands/training/neural-train.md +75 -75
- package/.claude/commands/training/pattern-learn.md +25 -25
- package/.claude/commands/training/specialization.md +62 -62
- package/.claude/commands/truth/start.md +142 -142
- package/.claude/commands/verify/check.md +49 -49
- package/.claude/commands/verify/start.md +127 -127
- package/.claude/commands/workflows/README.md +9 -9
- package/.claude/commands/workflows/development.md +77 -77
- package/.claude/commands/workflows/research.md +62 -62
- package/.claude/commands/workflows/workflow-create.md +25 -25
- package/.claude/commands/workflows/workflow-execute.md +25 -25
- package/.claude/commands/workflows/workflow-export.md +25 -25
- package/.claude/eval/human-relevance-frozen-v1.json +17 -17
- package/.claude/evolve-proof/generation-0.json +211 -211
- package/.claude/evolve-proof/real-generation-0.json +406 -406
- package/.claude/evolve-proof/real-generation-1.json +406 -406
- package/.claude/helpers/README.md +96 -96
- package/.claude/helpers/adr-compliance.sh +186 -186
- package/.claude/helpers/auto-commit.sh +178 -178
- package/.claude/helpers/auto-memory-hook.mjs +430 -430
- package/.claude/helpers/checkpoint-manager.sh +251 -251
- package/.claude/helpers/daemon-manager.sh +252 -252
- package/.claude/helpers/ddd-tracker.sh +144 -144
- package/.claude/helpers/github-safe.js +156 -156
- package/.claude/helpers/github-setup.sh +45 -45
- package/.claude/helpers/guidance-hook.sh +13 -13
- package/.claude/helpers/guidance-hooks.sh +102 -102
- package/.claude/helpers/health-monitor.sh +108 -108
- package/.claude/helpers/helpers.manifest.json +6 -6
- package/.claude/helpers/hook-handler.cjs +565 -565
- package/.claude/helpers/intelligence.cjs +1058 -1058
- package/.claude/helpers/learning-hooks.sh +329 -329
- package/.claude/helpers/learning-optimizer.sh +127 -127
- package/.claude/helpers/learning-service.mjs +1144 -1144
- package/.claude/helpers/memory.js +83 -83
- package/.claude/helpers/metrics-db.mjs +503 -503
- package/.claude/helpers/pattern-consolidator.sh +86 -86
- package/.claude/helpers/perf-worker.sh +160 -160
- package/.claude/helpers/post-commit +16 -16
- package/.claude/helpers/pre-commit +26 -26
- package/.claude/helpers/quick-start.sh +19 -19
- package/.claude/helpers/router.js +105 -105
- package/.claude/helpers/security-scanner.sh +127 -127
- package/.claude/helpers/session.js +157 -157
- package/.claude/helpers/setup-mcp.sh +18 -18
- package/.claude/helpers/standard-checkpoint-hooks.sh +189 -189
- package/.claude/helpers/statusline-hook.sh +21 -21
- package/.claude/helpers/statusline.cjs +1060 -1006
- package/.claude/helpers/statusline.js +340 -340
- package/.claude/helpers/swarm-comms.sh +353 -353
- package/.claude/helpers/swarm-hooks.sh +761 -761
- package/.claude/helpers/swarm-monitor.sh +210 -210
- package/.claude/helpers/sync-v3-metrics.sh +245 -245
- package/.claude/helpers/update-v3-progress.sh +165 -165
- package/.claude/helpers/v3-quick-status.sh +57 -57
- package/.claude/helpers/v3.sh +110 -110
- package/.claude/helpers/validate-v3-config.sh +215 -215
- package/.claude/helpers/worker-manager.sh +170 -170
- package/.claude/proven-config.manifest.json +37 -37
- package/.claude/proven-config.signed.json +41 -41
- package/.claude/settings.json +182 -182
- package/.claude/skills/agentdb-advanced/SKILL.md +550 -550
- package/.claude/skills/agentdb-learning/SKILL.md +545 -545
- package/.claude/skills/agentdb-memory-patterns/SKILL.md +339 -339
- package/.claude/skills/agentdb-optimization/SKILL.md +509 -509
- package/.claude/skills/agentdb-vector-search/SKILL.md +339 -339
- package/.claude/skills/browser/SKILL.md +204 -204
- package/.claude/skills/dual-mode/README.md +71 -71
- package/.claude/skills/dual-mode/dual-collect.md +103 -103
- package/.claude/skills/dual-mode/dual-coordinate.md +85 -85
- package/.claude/skills/dual-mode/dual-spawn.md +81 -81
- package/.claude/skills/flow-nexus-neural/SKILL.md +727 -727
- package/.claude/skills/flow-nexus-platform/SKILL.md +1154 -1154
- package/.claude/skills/flow-nexus-swarm/SKILL.md +604 -604
- package/.claude/skills/github-code-review/SKILL.md +1125 -1125
- package/.claude/skills/github-multi-repo/SKILL.md +862 -862
- package/.claude/skills/github-project-management/SKILL.md +1262 -1262
- package/.claude/skills/github-release-management/SKILL.md +1064 -1064
- package/.claude/skills/github-workflow-automation/SKILL.md +1047 -1047
- package/.claude/skills/hooks-automation/SKILL.md +1201 -1201
- package/.claude/skills/pair-programming/SKILL.md +1202 -1202
- package/.claude/skills/reasoningbank-agentdb/SKILL.md +446 -446
- package/.claude/skills/reasoningbank-intelligence/SKILL.md +201 -201
- package/.claude/skills/skill-builder/SKILL.md +910 -910
- package/.claude/skills/sparc-methodology/SKILL.md +1106 -1106
- package/.claude/skills/stream-chain/SKILL.md +560 -560
- package/.claude/skills/swarm-advanced/SKILL.md +970 -970
- package/.claude/skills/swarm-orchestration/SKILL.md +179 -179
- package/.claude/skills/v3-cli-modernization/SKILL.md +871 -871
- package/.claude/skills/v3-core-implementation/SKILL.md +796 -796
- package/.claude/skills/v3-ddd-architecture/SKILL.md +441 -441
- package/.claude/skills/v3-integration-deep/SKILL.md +240 -240
- package/.claude/skills/v3-mcp-optimization/SKILL.md +776 -776
- package/.claude/skills/v3-memory-unification/SKILL.md +173 -173
- package/.claude/skills/v3-performance-optimization/SKILL.md +389 -389
- package/.claude/skills/v3-security-overhaul/SKILL.md +81 -81
- package/.claude/skills/v3-swarm-coordination/SKILL.md +339 -339
- package/.claude/skills/verification-quality/SKILL.md +691 -691
- package/README.md +419 -419
- package/bin/cli.js +314 -314
- package/bin/mcp-server.js +224 -224
- package/bin/preinstall.cjs +2 -2
- package/catalog-manifest.json +2 -2
- package/dist/src/autopilot-state.js +24 -7
- package/dist/src/benchmarks/gaia-critic.js +24 -24
- package/dist/src/business-pods/bbs-budget-tracker.js +53 -53
- package/dist/src/commands/completions.js +409 -409
- package/dist/src/commands/daemon.js +44 -44
- package/dist/src/commands/doctor.js +267 -20
- package/dist/src/commands/embeddings.js +26 -26
- package/dist/src/commands/hive-mind.js +97 -97
- package/dist/src/commands/hooks.js +74 -11
- package/dist/src/commands/init.js +202 -34
- package/dist/src/commands/memory.js +12 -1
- package/dist/src/commands/ruvector/backup.js +23 -23
- package/dist/src/commands/ruvector/benchmark.js +31 -31
- package/dist/src/commands/ruvector/import.js +14 -14
- package/dist/src/commands/ruvector/init.js +115 -115
- package/dist/src/commands/ruvector/migrate.js +99 -99
- package/dist/src/commands/ruvector/optimize.js +51 -51
- package/dist/src/commands/ruvector/setup.js +624 -624
- package/dist/src/commands/ruvector/status.js +38 -38
- package/dist/src/config/proven-config.js +2 -2
- package/dist/src/funnel/disclosure.js +13 -2
- package/dist/src/funnel/message-transport.d.ts +11 -4
- package/dist/src/funnel/message-transport.js +11 -4
- package/dist/src/funnel/messages.d.ts +12 -10
- package/dist/src/funnel/messages.js +83 -11
- package/dist/src/init/claudemd-generator.js +231 -231
- package/dist/src/init/executor.js +453 -453
- package/dist/src/init/helper-signing.js +2 -2
- package/dist/src/init/helpers-generator.js +751 -751
- package/dist/src/init/statusline-generator.js +24 -24
- package/dist/src/mcp-tools/agentdb-tools.js +15 -15
- package/dist/src/mcp-tools/browser-intent-tools.js +19 -19
- package/dist/src/mcp-tools/browser-tools.js +8 -0
- package/dist/src/mcp-tools/hooks-tools.js +21 -0
- package/dist/src/mcp-tools/memory-tools.js +4 -3
- package/dist/src/memory/graph-edge-writer.d.ts +9 -0
- package/dist/src/memory/graph-edge-writer.js +35 -22
- package/dist/src/memory/memory-bridge.js +189 -93
- package/dist/src/memory/memory-initializer.js +479 -407
- package/dist/src/memory/rabitq-index.js +5 -5
- package/dist/src/parser.js +25 -9
- package/dist/src/proxy/verify.js +2 -2
- package/dist/src/runtime/headless.js +28 -28
- package/dist/src/services/distill-tuning.js +7 -7
- package/dist/src/services/headless-worker-executor.js +84 -84
- package/dist/src/services/memory-distillation.js +4 -4
- package/dist/src/services/worker-daemon.js +7 -4
- package/dist/src/transfer/deploy-seraphine.js +23 -23
- package/package.json +137 -135
- package/plugins/ruflo-metaharness/.claude-plugin/plugin.json +32 -32
- package/plugins/ruflo-metaharness/README.md +72 -72
- package/plugins/ruflo-metaharness/agents/metaharness-architect.md +58 -58
- package/plugins/ruflo-metaharness/commands/ruflo-metaharness.md +48 -48
- package/plugins/ruflo-metaharness/scripts/_darwin.mjs +210 -210
- package/plugins/ruflo-metaharness/scripts/_harness.mjs +330 -330
- package/plugins/ruflo-metaharness/scripts/_invoke.mjs +231 -231
- package/plugins/ruflo-metaharness/scripts/_redblue.mjs +143 -143
- package/plugins/ruflo-metaharness/scripts/_similarity.mjs +161 -161
- package/plugins/ruflo-metaharness/scripts/_spike-similarity.mjs +223 -223
- package/plugins/ruflo-metaharness/scripts/audit-list.mjs +158 -158
- package/plugins/ruflo-metaharness/scripts/audit-trend.mjs +272 -272
- package/plugins/ruflo-metaharness/scripts/bench-parse-mcp-scan.mjs +146 -146
- package/plugins/ruflo-metaharness/scripts/bench-recordpair-overhead.mjs +186 -186
- package/plugins/ruflo-metaharness/scripts/bench-similarity.mjs +177 -177
- package/plugins/ruflo-metaharness/scripts/bench.mjs +95 -95
- package/plugins/ruflo-metaharness/scripts/drift-from-history.mjs +363 -363
- package/plugins/ruflo-metaharness/scripts/evolve.mjs +404 -404
- package/plugins/ruflo-metaharness/scripts/genome.mjs +80 -80
- package/plugins/ruflo-metaharness/scripts/gepa.mjs +153 -153
- package/plugins/ruflo-metaharness/scripts/learn.mjs +127 -127
- package/plugins/ruflo-metaharness/scripts/mcp-scan.mjs +111 -111
- package/plugins/ruflo-metaharness/scripts/mint.mjs +126 -126
- package/plugins/ruflo-metaharness/scripts/oia-audit.mjs +228 -228
- package/plugins/ruflo-metaharness/scripts/redblue.mjs +286 -286
- package/plugins/ruflo-metaharness/scripts/router-parallel-analyze.mjs +250 -250
- package/plugins/ruflo-metaharness/scripts/score.mjs +92 -92
- package/plugins/ruflo-metaharness/scripts/security-bench.mjs +174 -174
- package/plugins/ruflo-metaharness/scripts/similarity.mjs +158 -158
- package/plugins/ruflo-metaharness/scripts/smoke.sh +2356 -2356
- package/plugins/ruflo-metaharness/scripts/test-graceful-degradation.mjs +165 -165
- package/plugins/ruflo-metaharness/scripts/test-mcp-tools.mjs +472 -472
- package/plugins/ruflo-metaharness/scripts/test-parallel-pipeline.mjs +204 -204
- package/plugins/ruflo-metaharness/scripts/test-pipeline-roundtrip.mjs +586 -586
- package/plugins/ruflo-metaharness/scripts/test-similarity.mjs +334 -334
- package/plugins/ruflo-metaharness/scripts/test-with-openrouter.mjs +229 -229
- package/plugins/ruflo-metaharness/scripts/threat-model.mjs +59 -59
- package/plugins/ruflo-metaharness/skills/harness-bench/SKILL.md +64 -64
- package/plugins/ruflo-metaharness/skills/harness-drift-from-history/SKILL.md +65 -65
- package/plugins/ruflo-metaharness/skills/harness-evolve/SKILL.md +131 -131
- package/plugins/ruflo-metaharness/skills/harness-genome/SKILL.md +54 -54
- package/plugins/ruflo-metaharness/skills/harness-gepa/SKILL.md +65 -65
- package/plugins/ruflo-metaharness/skills/harness-learn/SKILL.md +65 -65
- package/plugins/ruflo-metaharness/skills/harness-mcp-scan/SKILL.md +49 -49
- package/plugins/ruflo-metaharness/skills/harness-mint/SKILL.md +72 -72
- package/plugins/ruflo-metaharness/skills/harness-oia-audit/SKILL.md +79 -79
- package/plugins/ruflo-metaharness/skills/harness-score/SKILL.md +66 -66
- package/plugins/ruflo-metaharness/skills/harness-security-bench/SKILL.md +101 -101
- package/plugins/ruflo-metaharness/skills/harness-similarity/SKILL.md +67 -67
- package/plugins/ruflo-metaharness/skills/harness-threat-model/SKILL.md +41 -41
- package/scripts/postinstall.cjs +153 -153
|
@@ -1,330 +1,330 @@
|
|
|
1
|
-
// _harness.mjs — shared invocation helper for the metaharness/harness CLIs.
|
|
2
|
-
//
|
|
3
|
-
// All ruflo-metaharness skills shell out to the upstream CLI rather than
|
|
4
|
-
// linking the library — this honors ADR-150's architectural constraint
|
|
5
|
-
// (MetaHarness must remain a removable augmentation, never a required
|
|
6
|
-
// runtime dep) while still giving us "deep integration" through a single
|
|
7
|
-
// vetted bridge that every skill imports from.
|
|
8
|
-
//
|
|
9
|
-
// CONTRACT
|
|
10
|
-
// - `runMetaharness(args, opts)` — invoke the `metaharness` binary
|
|
11
|
-
// - `runHarness(args, opts)` — invoke the sibling `harness` binary
|
|
12
|
-
// - both return `{ stdout, stderr, exitCode, json|null, durationMs, degraded, reason? }`
|
|
13
|
-
// - `--json` flag is appended automatically when `opts.json !== false`
|
|
14
|
-
// - subprocess hard timeout (default 60s) — captured in opts.timeoutMs
|
|
15
|
-
// - when the package cannot be resolved/installed, returns degraded result
|
|
16
|
-
// with `degraded: true, reason: 'metaharness-not-available'` — never
|
|
17
|
-
// throws (ADR-150 graceful-degradation rule #3). A subprocess killed by
|
|
18
|
-
// the timeout reports `reason: 'metaharness-timeout'` instead (matches
|
|
19
|
-
// the sibling _darwin/_redblue helpers).
|
|
20
|
-
//
|
|
21
|
-
// SECURITY + PERF (supersedes the iter-27 npx-with-@latest-dist-tag path)
|
|
22
|
-
// =========================================================================
|
|
23
|
-
// The pre-consolidation implementation shelled to `npx -y` with the @latest
|
|
24
|
-
// dist-tag. Two problems, both fixed here:
|
|
25
|
-
// 1. SECURITY (HIGH): @latest means a compromised upstream publish executes
|
|
26
|
-
// arbitrary code on user machines on the very next skill invocation.
|
|
27
|
-
// The version is now PINNED to METAHARNESS_PIN_VERSION (tilde range —
|
|
28
|
-
// patch updates only) and only bumped deliberately, in lock-step with
|
|
29
|
-
// optionalDependencies in @claude-flow/cli + ruflo package.json.
|
|
30
|
-
// 2. PERF: @latest forced an npm-registry metadata check on EVERY call.
|
|
31
|
-
// Resolution is now (a) an already-installed local metaharness
|
|
32
|
-
// satisfying the pin (walk-up node_modules — free), then (b) a ONE-TIME
|
|
33
|
-
// `npm install --prefix ~/.ruflo/metaharness-cache-<pin>` versioned
|
|
34
|
-
// cache (same proven pattern as _redblue.mjs / gepa.mjs), after which
|
|
35
|
-
// every call is a plain `node <abs-path-to-cli>` spawn — zero network.
|
|
36
|
-
//
|
|
37
|
-
// BOTH BINARIES: the `metaharness` package ships two bins (`metaharness`
|
|
38
|
-
// and `harness`); their entry paths are read from the resolved package.json
|
|
39
|
-
// bin map rather than hardcoded, so upstream layout changes inside the
|
|
40
|
-
// pinned range cannot silently break us.
|
|
41
|
-
|
|
42
|
-
import { spawnSync, spawn } from 'node:child_process';
|
|
43
|
-
import { existsSync, readFileSync } from 'node:fs';
|
|
44
|
-
import { join } from 'node:path';
|
|
45
|
-
import {
|
|
46
|
-
classifyDegraded,
|
|
47
|
-
ensureCachedInstall,
|
|
48
|
-
findLocalPackageDir,
|
|
49
|
-
injectJson,
|
|
50
|
-
makeDegradedEmitter,
|
|
51
|
-
parseTrailingJson,
|
|
52
|
-
} from './_invoke.mjs';
|
|
53
|
-
|
|
54
|
-
const DEFAULT_TIMEOUT_MS = 60_000;
|
|
55
|
-
|
|
56
|
-
// Pinned semver range. Bump in lock-step with optionalDependencies in
|
|
57
|
-
// @claude-flow/cli/package.json + ruflo/package.json. NEVER @latest.
|
|
58
|
-
const METAHARNESS_PKG = 'metaharness';
|
|
59
|
-
const METAHARNESS_PIN_VERSION = '~0.3.0';
|
|
60
|
-
|
|
61
|
-
const REASON_NOT_AVAILABLE = 'metaharness-not-available';
|
|
62
|
-
|
|
63
|
-
/**
|
|
64
|
-
* Resolve absolute paths for the two bins shipped by the metaharness
|
|
65
|
-
* package. Memoized per process — the whole point is that after the first
|
|
66
|
-
* resolution (or one-time cache install) every call is local-only.
|
|
67
|
-
*/
|
|
68
|
-
let RESOLVED = null;
|
|
69
|
-
function resolveMetaharnessBins() {
|
|
70
|
-
if (RESOLVED) return RESOLVED;
|
|
71
|
-
// (a) already-installed local copy satisfying the pin — free.
|
|
72
|
-
const localDir = findLocalPackageDir(METAHARNESS_PKG, METAHARNESS_PIN_VERSION);
|
|
73
|
-
if (localDir) {
|
|
74
|
-
const bins = readBinMap(localDir);
|
|
75
|
-
if (bins) return (RESOLVED = { ok: true, bins, source: 'local' });
|
|
76
|
-
}
|
|
77
|
-
// (b) one-time versioned cache install of the pinned range.
|
|
78
|
-
const cached = ensureCachedInstall({ pkg: METAHARNESS_PKG, pinVersion: METAHARNESS_PIN_VERSION });
|
|
79
|
-
if (!cached.ok) {
|
|
80
|
-
return (RESOLVED = {
|
|
81
|
-
ok: false,
|
|
82
|
-
reason: REASON_NOT_AVAILABLE,
|
|
83
|
-
stderr: cached.stderr ?? cached.error ?? '',
|
|
84
|
-
stdout: cached.stdout ?? '',
|
|
85
|
-
});
|
|
86
|
-
}
|
|
87
|
-
const bins = readBinMap(cached.pkgDir);
|
|
88
|
-
if (!bins) {
|
|
89
|
-
return (RESOLVED = {
|
|
90
|
-
ok: false,
|
|
91
|
-
reason: REASON_NOT_AVAILABLE,
|
|
92
|
-
stderr: `metaharness package at ${cached.pkgDir} is missing the expected bin map (metaharness + harness)`,
|
|
93
|
-
stdout: '',
|
|
94
|
-
});
|
|
95
|
-
}
|
|
96
|
-
return (RESOLVED = { ok: true, bins, source: 'cache' });
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
/** Read both bin entry points from the package's bin map. */
|
|
100
|
-
function readBinMap(pkgDir) {
|
|
101
|
-
try {
|
|
102
|
-
const pj = JSON.parse(readFileSync(join(pkgDir, 'package.json'), 'utf-8'));
|
|
103
|
-
const bin = pj.bin || {};
|
|
104
|
-
if (!bin.metaharness || !bin.harness) return null;
|
|
105
|
-
const metaharness = join(pkgDir, bin.metaharness);
|
|
106
|
-
const harness = join(pkgDir, bin.harness);
|
|
107
|
-
if (!existsSync(metaharness) || !existsSync(harness)) return null;
|
|
108
|
-
return { metaharness, harness };
|
|
109
|
-
} catch {
|
|
110
|
-
return null;
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
function degradedResult(resolved, start) {
|
|
115
|
-
return {
|
|
116
|
-
stdout: resolved.stdout ?? '',
|
|
117
|
-
stderr: resolved.stderr ?? '',
|
|
118
|
-
exitCode: 127,
|
|
119
|
-
json: null,
|
|
120
|
-
durationMs: Date.now() - start,
|
|
121
|
-
degraded: true,
|
|
122
|
-
reason: resolved.reason ?? REASON_NOT_AVAILABLE,
|
|
123
|
-
};
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
/**
|
|
127
|
-
* Async variant (iter 56) — used by oia-audit.mjs to parallelize its 5
|
|
128
|
-
* subprocess calls, dropping worst-case wall-clock from 5×TIMEOUT to
|
|
129
|
-
* 1×TIMEOUT. Identical return shape to the sync path.
|
|
130
|
-
*/
|
|
131
|
-
function execBinAsync(binName, args, opts = {}) {
|
|
132
|
-
const start = Date.now();
|
|
133
|
-
const resolved = resolveMetaharnessBins();
|
|
134
|
-
if (!resolved.ok) return Promise.resolve(degradedResult(resolved, start));
|
|
135
|
-
return new Promise((resolve) => {
|
|
136
|
-
const timeoutMs = opts.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
137
|
-
const wantJson = opts.json !== false;
|
|
138
|
-
const argv = injectJson(args, wantJson);
|
|
139
|
-
const p = spawn('node', [resolved.bins[binName], ...argv], {
|
|
140
|
-
stdio: ['ignore', 'pipe', 'pipe'],
|
|
141
|
-
cwd: opts.cwd,
|
|
142
|
-
env: { ...process.env, ...(opts.env || {}) },
|
|
143
|
-
shell: false,
|
|
144
|
-
});
|
|
145
|
-
let stdout = '', stderr = '';
|
|
146
|
-
p.stdout?.on('data', (d) => { stdout += d.toString(); });
|
|
147
|
-
p.stderr?.on('data', (d) => { stderr += d.toString(); });
|
|
148
|
-
let timedOut = false;
|
|
149
|
-
const timer = setTimeout(() => {
|
|
150
|
-
timedOut = true;
|
|
151
|
-
try { p.kill('SIGTERM'); } catch { /* ignore */ }
|
|
152
|
-
}, timeoutMs);
|
|
153
|
-
p.on('error', (e) => {
|
|
154
|
-
clearTimeout(timer);
|
|
155
|
-
resolve({
|
|
156
|
-
stdout, stderr: stderr + String(e?.message ?? e),
|
|
157
|
-
exitCode: 127, json: null, durationMs: Date.now() - start,
|
|
158
|
-
degraded: true, reason: REASON_NOT_AVAILABLE,
|
|
159
|
-
});
|
|
160
|
-
});
|
|
161
|
-
p.on('close', (code) => {
|
|
162
|
-
clearTimeout(timer);
|
|
163
|
-
const durationMs = Date.now() - start;
|
|
164
|
-
const classified = classifyDegraded(stderr, timedOut ? null : code, 'metaharness');
|
|
165
|
-
if (classified.degraded) {
|
|
166
|
-
resolve({
|
|
167
|
-
stdout, stderr,
|
|
168
|
-
exitCode: code ?? 127, json: null, durationMs,
|
|
169
|
-
degraded: true, reason: classified.reason,
|
|
170
|
-
});
|
|
171
|
-
return;
|
|
172
|
-
}
|
|
173
|
-
resolve({
|
|
174
|
-
stdout, stderr,
|
|
175
|
-
exitCode: code ?? 0,
|
|
176
|
-
json: wantJson ? parseTrailingJson(stdout) : null,
|
|
177
|
-
durationMs,
|
|
178
|
-
degraded: false,
|
|
179
|
-
});
|
|
180
|
-
});
|
|
181
|
-
});
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
/** Sync invocation of one of the two resolved bins via `node <abs-path>`. */
|
|
185
|
-
function execBin(binName, args, opts = {}) {
|
|
186
|
-
const start = Date.now();
|
|
187
|
-
const resolved = resolveMetaharnessBins();
|
|
188
|
-
if (!resolved.ok) return degradedResult(resolved, start);
|
|
189
|
-
const timeoutMs = opts.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
190
|
-
const wantJson = opts.json !== false;
|
|
191
|
-
const argv = injectJson(args, wantJson);
|
|
192
|
-
const r = spawnSync('node', [resolved.bins[binName], ...argv], {
|
|
193
|
-
stdio: ['ignore', 'pipe', 'pipe'],
|
|
194
|
-
encoding: 'utf-8',
|
|
195
|
-
timeout: timeoutMs,
|
|
196
|
-
cwd: opts.cwd, // iter 27 — let callers redirect $CWD (mint.mjs needs this)
|
|
197
|
-
env: { ...process.env, ...(opts.env || {}) },
|
|
198
|
-
shell: false,
|
|
199
|
-
});
|
|
200
|
-
const durationMs = Date.now() - start;
|
|
201
|
-
const stdout = r.stdout || '';
|
|
202
|
-
const stderr = r.stderr || '';
|
|
203
|
-
const classified = classifyDegraded(stderr, r.status, 'metaharness');
|
|
204
|
-
if (classified.degraded) {
|
|
205
|
-
return {
|
|
206
|
-
stdout, stderr,
|
|
207
|
-
exitCode: r.status ?? 127,
|
|
208
|
-
json: null,
|
|
209
|
-
durationMs,
|
|
210
|
-
degraded: true,
|
|
211
|
-
reason: classified.reason,
|
|
212
|
-
};
|
|
213
|
-
}
|
|
214
|
-
return {
|
|
215
|
-
stdout, stderr,
|
|
216
|
-
exitCode: r.status ?? 0,
|
|
217
|
-
json: wantJson ? parseTrailingJson(stdout) : null,
|
|
218
|
-
durationMs,
|
|
219
|
-
degraded: false,
|
|
220
|
-
};
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
export function runMetaharness(args, opts) {
|
|
224
|
-
return execBin('metaharness', args, opts);
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
export function runHarness(args, opts) {
|
|
228
|
-
// The `harness` binary ships inside the same `metaharness` package —
|
|
229
|
-
// resolved from the package.json bin map above.
|
|
230
|
-
return execBin('harness', args, opts);
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
export function runMetaharnessAsync(args, opts) {
|
|
234
|
-
return execBinAsync('metaharness', args, opts);
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
export function runHarnessAsync(args, opts) {
|
|
238
|
-
return execBinAsync('harness', args, opts);
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
/**
|
|
242
|
-
* iter 63 — single source of truth for severity ranks across the
|
|
243
|
-
* metaharness plugin family. Pre-iter-63, three scripts (oia-audit,
|
|
244
|
-
* audit-trend, mcp-scan) maintained their own SEVERITY_RANK literal,
|
|
245
|
-
* each missing different keys, each producing different NaN-compare
|
|
246
|
-
* behavior on unknown severities. Iter 62 fixed oia-audit; iter 63
|
|
247
|
-
* propagates the fix and consolidates.
|
|
248
|
-
*
|
|
249
|
-
* Mapping rationale:
|
|
250
|
-
* clean / info → 0 (no harm)
|
|
251
|
-
* low → 1
|
|
252
|
-
* medium / warn → 2
|
|
253
|
-
* high / error → 3
|
|
254
|
-
* critical → 4 (explicit elevation above high)
|
|
255
|
-
*
|
|
256
|
-
* `rankSeverity(s)` is the safe accessor — returns 0 for any unknown
|
|
257
|
-
* string instead of `undefined`, eliminating the NaN-compare hazard
|
|
258
|
-
* (`undefined > 3` evaluates to false → unknown severities silently
|
|
259
|
-
* ignored in reduce expressions).
|
|
260
|
-
*/
|
|
261
|
-
export const SEVERITY_RANK = Object.freeze({
|
|
262
|
-
clean: 0, info: 0,
|
|
263
|
-
low: 1,
|
|
264
|
-
medium: 2, warn: 2,
|
|
265
|
-
high: 3, error: 3,
|
|
266
|
-
critical: 4,
|
|
267
|
-
});
|
|
268
|
-
|
|
269
|
-
export function rankSeverity(s) {
|
|
270
|
-
if (s == null) return 0;
|
|
271
|
-
return SEVERITY_RANK[String(s).toLowerCase()] ?? 0;
|
|
272
|
-
}
|
|
273
|
-
|
|
274
|
-
/**
|
|
275
|
-
* iter 50 — parse `harness mcp-scan` text output into structured findings.
|
|
276
|
-
*
|
|
277
|
-
* Upstream `harness mcp-scan` emits plain text even with --json:
|
|
278
|
-
*
|
|
279
|
-
* harness mcp-scan — <path>
|
|
280
|
-
*
|
|
281
|
-
* [INFO] No MCP security issues found
|
|
282
|
-
* Policy is default-deny with safe capability grants and an audit log.
|
|
283
|
-
*
|
|
284
|
-
* Result: INFO (1 finding, 0 high)
|
|
285
|
-
*
|
|
286
|
-
* Closes the iter-49-flagged gap where audit-trend.mjs reads
|
|
287
|
-
* `json.findings` expecting an array, but mcp-scan's r.json was null.
|
|
288
|
-
* Used by BOTH mcp-scan.mjs (the wrapper) and oia-audit.mjs (composite
|
|
289
|
-
* audit) so the structured-findings invariant holds across the pipeline.
|
|
290
|
-
*/
|
|
291
|
-
export function parseMcpScanText(stdout) {
|
|
292
|
-
const findings = [];
|
|
293
|
-
const lines = (stdout || '').split('\n');
|
|
294
|
-
let current = null;
|
|
295
|
-
for (const line of lines) {
|
|
296
|
-
const m = /^\s*\[([A-Z]+)\]\s+(.+?)\s*$/.exec(line);
|
|
297
|
-
if (m) {
|
|
298
|
-
if (current) findings.push(current);
|
|
299
|
-
current = { severity: m[1].toLowerCase(), message: m[2] };
|
|
300
|
-
} else if (current && /^\s{6,}\S/.test(line)) {
|
|
301
|
-
const cont = line.trim();
|
|
302
|
-
if (cont) current.message += ' ' + cont;
|
|
303
|
-
} else if (current && line.trim() === '') {
|
|
304
|
-
findings.push(current);
|
|
305
|
-
current = null;
|
|
306
|
-
}
|
|
307
|
-
}
|
|
308
|
-
if (current) findings.push(current);
|
|
309
|
-
const resultMatch = /Result:\s+([A-Z]+)\s+\((\d+)\s+finding/i.exec(stdout);
|
|
310
|
-
const summary = resultMatch ? {
|
|
311
|
-
overallSeverity: resultMatch[1].toLowerCase(),
|
|
312
|
-
totalCount: parseInt(resultMatch[2], 10),
|
|
313
|
-
} : null;
|
|
314
|
-
return { findings, summary };
|
|
315
|
-
}
|
|
316
|
-
|
|
317
|
-
// Convenience emitter for skill scripts — keep the boilerplate out of
|
|
318
|
-
// each skill so they focus on argument parsing + exit-code semantics.
|
|
319
|
-
// Exit 0 — ADR-150 architectural constraint says ruflo continues to
|
|
320
|
-
// function when MetaHarness is absent. Skills emit a structured
|
|
321
|
-
// degraded payload rather than failing.
|
|
322
|
-
export const emitDegradedJsonAndExit = makeDegradedEmitter(METAHARNESS_PKG, METAHARNESS_PIN_VERSION);
|
|
323
|
-
|
|
324
|
-
export const METAHARNESS_VERSION_PIN = `${METAHARNESS_PKG}@${METAHARNESS_PIN_VERSION}`;
|
|
325
|
-
|
|
326
|
-
/** Expose resolution for diagnostics/tests (which path served the bins). */
|
|
327
|
-
export function metaharnessResolution() {
|
|
328
|
-
const r = resolveMetaharnessBins();
|
|
329
|
-
return r.ok ? { ok: true, source: r.source, bins: r.bins } : { ok: false, reason: r.reason };
|
|
330
|
-
}
|
|
1
|
+
// _harness.mjs — shared invocation helper for the metaharness/harness CLIs.
|
|
2
|
+
//
|
|
3
|
+
// All ruflo-metaharness skills shell out to the upstream CLI rather than
|
|
4
|
+
// linking the library — this honors ADR-150's architectural constraint
|
|
5
|
+
// (MetaHarness must remain a removable augmentation, never a required
|
|
6
|
+
// runtime dep) while still giving us "deep integration" through a single
|
|
7
|
+
// vetted bridge that every skill imports from.
|
|
8
|
+
//
|
|
9
|
+
// CONTRACT
|
|
10
|
+
// - `runMetaharness(args, opts)` — invoke the `metaharness` binary
|
|
11
|
+
// - `runHarness(args, opts)` — invoke the sibling `harness` binary
|
|
12
|
+
// - both return `{ stdout, stderr, exitCode, json|null, durationMs, degraded, reason? }`
|
|
13
|
+
// - `--json` flag is appended automatically when `opts.json !== false`
|
|
14
|
+
// - subprocess hard timeout (default 60s) — captured in opts.timeoutMs
|
|
15
|
+
// - when the package cannot be resolved/installed, returns degraded result
|
|
16
|
+
// with `degraded: true, reason: 'metaharness-not-available'` — never
|
|
17
|
+
// throws (ADR-150 graceful-degradation rule #3). A subprocess killed by
|
|
18
|
+
// the timeout reports `reason: 'metaharness-timeout'` instead (matches
|
|
19
|
+
// the sibling _darwin/_redblue helpers).
|
|
20
|
+
//
|
|
21
|
+
// SECURITY + PERF (supersedes the iter-27 npx-with-@latest-dist-tag path)
|
|
22
|
+
// =========================================================================
|
|
23
|
+
// The pre-consolidation implementation shelled to `npx -y` with the @latest
|
|
24
|
+
// dist-tag. Two problems, both fixed here:
|
|
25
|
+
// 1. SECURITY (HIGH): @latest means a compromised upstream publish executes
|
|
26
|
+
// arbitrary code on user machines on the very next skill invocation.
|
|
27
|
+
// The version is now PINNED to METAHARNESS_PIN_VERSION (tilde range —
|
|
28
|
+
// patch updates only) and only bumped deliberately, in lock-step with
|
|
29
|
+
// optionalDependencies in @claude-flow/cli + ruflo package.json.
|
|
30
|
+
// 2. PERF: @latest forced an npm-registry metadata check on EVERY call.
|
|
31
|
+
// Resolution is now (a) an already-installed local metaharness
|
|
32
|
+
// satisfying the pin (walk-up node_modules — free), then (b) a ONE-TIME
|
|
33
|
+
// `npm install --prefix ~/.ruflo/metaharness-cache-<pin>` versioned
|
|
34
|
+
// cache (same proven pattern as _redblue.mjs / gepa.mjs), after which
|
|
35
|
+
// every call is a plain `node <abs-path-to-cli>` spawn — zero network.
|
|
36
|
+
//
|
|
37
|
+
// BOTH BINARIES: the `metaharness` package ships two bins (`metaharness`
|
|
38
|
+
// and `harness`); their entry paths are read from the resolved package.json
|
|
39
|
+
// bin map rather than hardcoded, so upstream layout changes inside the
|
|
40
|
+
// pinned range cannot silently break us.
|
|
41
|
+
|
|
42
|
+
import { spawnSync, spawn } from 'node:child_process';
|
|
43
|
+
import { existsSync, readFileSync } from 'node:fs';
|
|
44
|
+
import { join } from 'node:path';
|
|
45
|
+
import {
|
|
46
|
+
classifyDegraded,
|
|
47
|
+
ensureCachedInstall,
|
|
48
|
+
findLocalPackageDir,
|
|
49
|
+
injectJson,
|
|
50
|
+
makeDegradedEmitter,
|
|
51
|
+
parseTrailingJson,
|
|
52
|
+
} from './_invoke.mjs';
|
|
53
|
+
|
|
54
|
+
const DEFAULT_TIMEOUT_MS = 60_000;
|
|
55
|
+
|
|
56
|
+
// Pinned semver range. Bump in lock-step with optionalDependencies in
|
|
57
|
+
// @claude-flow/cli/package.json + ruflo/package.json. NEVER @latest.
|
|
58
|
+
const METAHARNESS_PKG = 'metaharness';
|
|
59
|
+
const METAHARNESS_PIN_VERSION = '~0.3.0';
|
|
60
|
+
|
|
61
|
+
const REASON_NOT_AVAILABLE = 'metaharness-not-available';
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Resolve absolute paths for the two bins shipped by the metaharness
|
|
65
|
+
* package. Memoized per process — the whole point is that after the first
|
|
66
|
+
* resolution (or one-time cache install) every call is local-only.
|
|
67
|
+
*/
|
|
68
|
+
let RESOLVED = null;
|
|
69
|
+
function resolveMetaharnessBins() {
|
|
70
|
+
if (RESOLVED) return RESOLVED;
|
|
71
|
+
// (a) already-installed local copy satisfying the pin — free.
|
|
72
|
+
const localDir = findLocalPackageDir(METAHARNESS_PKG, METAHARNESS_PIN_VERSION);
|
|
73
|
+
if (localDir) {
|
|
74
|
+
const bins = readBinMap(localDir);
|
|
75
|
+
if (bins) return (RESOLVED = { ok: true, bins, source: 'local' });
|
|
76
|
+
}
|
|
77
|
+
// (b) one-time versioned cache install of the pinned range.
|
|
78
|
+
const cached = ensureCachedInstall({ pkg: METAHARNESS_PKG, pinVersion: METAHARNESS_PIN_VERSION });
|
|
79
|
+
if (!cached.ok) {
|
|
80
|
+
return (RESOLVED = {
|
|
81
|
+
ok: false,
|
|
82
|
+
reason: REASON_NOT_AVAILABLE,
|
|
83
|
+
stderr: cached.stderr ?? cached.error ?? '',
|
|
84
|
+
stdout: cached.stdout ?? '',
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
const bins = readBinMap(cached.pkgDir);
|
|
88
|
+
if (!bins) {
|
|
89
|
+
return (RESOLVED = {
|
|
90
|
+
ok: false,
|
|
91
|
+
reason: REASON_NOT_AVAILABLE,
|
|
92
|
+
stderr: `metaharness package at ${cached.pkgDir} is missing the expected bin map (metaharness + harness)`,
|
|
93
|
+
stdout: '',
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
return (RESOLVED = { ok: true, bins, source: 'cache' });
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/** Read both bin entry points from the package's bin map. */
|
|
100
|
+
function readBinMap(pkgDir) {
|
|
101
|
+
try {
|
|
102
|
+
const pj = JSON.parse(readFileSync(join(pkgDir, 'package.json'), 'utf-8'));
|
|
103
|
+
const bin = pj.bin || {};
|
|
104
|
+
if (!bin.metaharness || !bin.harness) return null;
|
|
105
|
+
const metaharness = join(pkgDir, bin.metaharness);
|
|
106
|
+
const harness = join(pkgDir, bin.harness);
|
|
107
|
+
if (!existsSync(metaharness) || !existsSync(harness)) return null;
|
|
108
|
+
return { metaharness, harness };
|
|
109
|
+
} catch {
|
|
110
|
+
return null;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
function degradedResult(resolved, start) {
|
|
115
|
+
return {
|
|
116
|
+
stdout: resolved.stdout ?? '',
|
|
117
|
+
stderr: resolved.stderr ?? '',
|
|
118
|
+
exitCode: 127,
|
|
119
|
+
json: null,
|
|
120
|
+
durationMs: Date.now() - start,
|
|
121
|
+
degraded: true,
|
|
122
|
+
reason: resolved.reason ?? REASON_NOT_AVAILABLE,
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Async variant (iter 56) — used by oia-audit.mjs to parallelize its 5
|
|
128
|
+
* subprocess calls, dropping worst-case wall-clock from 5×TIMEOUT to
|
|
129
|
+
* 1×TIMEOUT. Identical return shape to the sync path.
|
|
130
|
+
*/
|
|
131
|
+
function execBinAsync(binName, args, opts = {}) {
|
|
132
|
+
const start = Date.now();
|
|
133
|
+
const resolved = resolveMetaharnessBins();
|
|
134
|
+
if (!resolved.ok) return Promise.resolve(degradedResult(resolved, start));
|
|
135
|
+
return new Promise((resolve) => {
|
|
136
|
+
const timeoutMs = opts.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
137
|
+
const wantJson = opts.json !== false;
|
|
138
|
+
const argv = injectJson(args, wantJson);
|
|
139
|
+
const p = spawn('node', [resolved.bins[binName], ...argv], {
|
|
140
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
141
|
+
cwd: opts.cwd,
|
|
142
|
+
env: { ...process.env, ...(opts.env || {}) },
|
|
143
|
+
shell: false,
|
|
144
|
+
});
|
|
145
|
+
let stdout = '', stderr = '';
|
|
146
|
+
p.stdout?.on('data', (d) => { stdout += d.toString(); });
|
|
147
|
+
p.stderr?.on('data', (d) => { stderr += d.toString(); });
|
|
148
|
+
let timedOut = false;
|
|
149
|
+
const timer = setTimeout(() => {
|
|
150
|
+
timedOut = true;
|
|
151
|
+
try { p.kill('SIGTERM'); } catch { /* ignore */ }
|
|
152
|
+
}, timeoutMs);
|
|
153
|
+
p.on('error', (e) => {
|
|
154
|
+
clearTimeout(timer);
|
|
155
|
+
resolve({
|
|
156
|
+
stdout, stderr: stderr + String(e?.message ?? e),
|
|
157
|
+
exitCode: 127, json: null, durationMs: Date.now() - start,
|
|
158
|
+
degraded: true, reason: REASON_NOT_AVAILABLE,
|
|
159
|
+
});
|
|
160
|
+
});
|
|
161
|
+
p.on('close', (code) => {
|
|
162
|
+
clearTimeout(timer);
|
|
163
|
+
const durationMs = Date.now() - start;
|
|
164
|
+
const classified = classifyDegraded(stderr, timedOut ? null : code, 'metaharness');
|
|
165
|
+
if (classified.degraded) {
|
|
166
|
+
resolve({
|
|
167
|
+
stdout, stderr,
|
|
168
|
+
exitCode: code ?? 127, json: null, durationMs,
|
|
169
|
+
degraded: true, reason: classified.reason,
|
|
170
|
+
});
|
|
171
|
+
return;
|
|
172
|
+
}
|
|
173
|
+
resolve({
|
|
174
|
+
stdout, stderr,
|
|
175
|
+
exitCode: code ?? 0,
|
|
176
|
+
json: wantJson ? parseTrailingJson(stdout) : null,
|
|
177
|
+
durationMs,
|
|
178
|
+
degraded: false,
|
|
179
|
+
});
|
|
180
|
+
});
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
/** Sync invocation of one of the two resolved bins via `node <abs-path>`. */
|
|
185
|
+
function execBin(binName, args, opts = {}) {
|
|
186
|
+
const start = Date.now();
|
|
187
|
+
const resolved = resolveMetaharnessBins();
|
|
188
|
+
if (!resolved.ok) return degradedResult(resolved, start);
|
|
189
|
+
const timeoutMs = opts.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
190
|
+
const wantJson = opts.json !== false;
|
|
191
|
+
const argv = injectJson(args, wantJson);
|
|
192
|
+
const r = spawnSync('node', [resolved.bins[binName], ...argv], {
|
|
193
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
194
|
+
encoding: 'utf-8',
|
|
195
|
+
timeout: timeoutMs,
|
|
196
|
+
cwd: opts.cwd, // iter 27 — let callers redirect $CWD (mint.mjs needs this)
|
|
197
|
+
env: { ...process.env, ...(opts.env || {}) },
|
|
198
|
+
shell: false,
|
|
199
|
+
});
|
|
200
|
+
const durationMs = Date.now() - start;
|
|
201
|
+
const stdout = r.stdout || '';
|
|
202
|
+
const stderr = r.stderr || '';
|
|
203
|
+
const classified = classifyDegraded(stderr, r.status, 'metaharness');
|
|
204
|
+
if (classified.degraded) {
|
|
205
|
+
return {
|
|
206
|
+
stdout, stderr,
|
|
207
|
+
exitCode: r.status ?? 127,
|
|
208
|
+
json: null,
|
|
209
|
+
durationMs,
|
|
210
|
+
degraded: true,
|
|
211
|
+
reason: classified.reason,
|
|
212
|
+
};
|
|
213
|
+
}
|
|
214
|
+
return {
|
|
215
|
+
stdout, stderr,
|
|
216
|
+
exitCode: r.status ?? 0,
|
|
217
|
+
json: wantJson ? parseTrailingJson(stdout) : null,
|
|
218
|
+
durationMs,
|
|
219
|
+
degraded: false,
|
|
220
|
+
};
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
export function runMetaharness(args, opts) {
|
|
224
|
+
return execBin('metaharness', args, opts);
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
export function runHarness(args, opts) {
|
|
228
|
+
// The `harness` binary ships inside the same `metaharness` package —
|
|
229
|
+
// resolved from the package.json bin map above.
|
|
230
|
+
return execBin('harness', args, opts);
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
export function runMetaharnessAsync(args, opts) {
|
|
234
|
+
return execBinAsync('metaharness', args, opts);
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
export function runHarnessAsync(args, opts) {
|
|
238
|
+
return execBinAsync('harness', args, opts);
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
/**
|
|
242
|
+
* iter 63 — single source of truth for severity ranks across the
|
|
243
|
+
* metaharness plugin family. Pre-iter-63, three scripts (oia-audit,
|
|
244
|
+
* audit-trend, mcp-scan) maintained their own SEVERITY_RANK literal,
|
|
245
|
+
* each missing different keys, each producing different NaN-compare
|
|
246
|
+
* behavior on unknown severities. Iter 62 fixed oia-audit; iter 63
|
|
247
|
+
* propagates the fix and consolidates.
|
|
248
|
+
*
|
|
249
|
+
* Mapping rationale:
|
|
250
|
+
* clean / info → 0 (no harm)
|
|
251
|
+
* low → 1
|
|
252
|
+
* medium / warn → 2
|
|
253
|
+
* high / error → 3
|
|
254
|
+
* critical → 4 (explicit elevation above high)
|
|
255
|
+
*
|
|
256
|
+
* `rankSeverity(s)` is the safe accessor — returns 0 for any unknown
|
|
257
|
+
* string instead of `undefined`, eliminating the NaN-compare hazard
|
|
258
|
+
* (`undefined > 3` evaluates to false → unknown severities silently
|
|
259
|
+
* ignored in reduce expressions).
|
|
260
|
+
*/
|
|
261
|
+
export const SEVERITY_RANK = Object.freeze({
|
|
262
|
+
clean: 0, info: 0,
|
|
263
|
+
low: 1,
|
|
264
|
+
medium: 2, warn: 2,
|
|
265
|
+
high: 3, error: 3,
|
|
266
|
+
critical: 4,
|
|
267
|
+
});
|
|
268
|
+
|
|
269
|
+
export function rankSeverity(s) {
|
|
270
|
+
if (s == null) return 0;
|
|
271
|
+
return SEVERITY_RANK[String(s).toLowerCase()] ?? 0;
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
/**
|
|
275
|
+
* iter 50 — parse `harness mcp-scan` text output into structured findings.
|
|
276
|
+
*
|
|
277
|
+
* Upstream `harness mcp-scan` emits plain text even with --json:
|
|
278
|
+
*
|
|
279
|
+
* harness mcp-scan — <path>
|
|
280
|
+
*
|
|
281
|
+
* [INFO] No MCP security issues found
|
|
282
|
+
* Policy is default-deny with safe capability grants and an audit log.
|
|
283
|
+
*
|
|
284
|
+
* Result: INFO (1 finding, 0 high)
|
|
285
|
+
*
|
|
286
|
+
* Closes the iter-49-flagged gap where audit-trend.mjs reads
|
|
287
|
+
* `json.findings` expecting an array, but mcp-scan's r.json was null.
|
|
288
|
+
* Used by BOTH mcp-scan.mjs (the wrapper) and oia-audit.mjs (composite
|
|
289
|
+
* audit) so the structured-findings invariant holds across the pipeline.
|
|
290
|
+
*/
|
|
291
|
+
export function parseMcpScanText(stdout) {
|
|
292
|
+
const findings = [];
|
|
293
|
+
const lines = (stdout || '').split('\n');
|
|
294
|
+
let current = null;
|
|
295
|
+
for (const line of lines) {
|
|
296
|
+
const m = /^\s*\[([A-Z]+)\]\s+(.+?)\s*$/.exec(line);
|
|
297
|
+
if (m) {
|
|
298
|
+
if (current) findings.push(current);
|
|
299
|
+
current = { severity: m[1].toLowerCase(), message: m[2] };
|
|
300
|
+
} else if (current && /^\s{6,}\S/.test(line)) {
|
|
301
|
+
const cont = line.trim();
|
|
302
|
+
if (cont) current.message += ' ' + cont;
|
|
303
|
+
} else if (current && line.trim() === '') {
|
|
304
|
+
findings.push(current);
|
|
305
|
+
current = null;
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
if (current) findings.push(current);
|
|
309
|
+
const resultMatch = /Result:\s+([A-Z]+)\s+\((\d+)\s+finding/i.exec(stdout);
|
|
310
|
+
const summary = resultMatch ? {
|
|
311
|
+
overallSeverity: resultMatch[1].toLowerCase(),
|
|
312
|
+
totalCount: parseInt(resultMatch[2], 10),
|
|
313
|
+
} : null;
|
|
314
|
+
return { findings, summary };
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
// Convenience emitter for skill scripts — keep the boilerplate out of
|
|
318
|
+
// each skill so they focus on argument parsing + exit-code semantics.
|
|
319
|
+
// Exit 0 — ADR-150 architectural constraint says ruflo continues to
|
|
320
|
+
// function when MetaHarness is absent. Skills emit a structured
|
|
321
|
+
// degraded payload rather than failing.
|
|
322
|
+
export const emitDegradedJsonAndExit = makeDegradedEmitter(METAHARNESS_PKG, METAHARNESS_PIN_VERSION);
|
|
323
|
+
|
|
324
|
+
export const METAHARNESS_VERSION_PIN = `${METAHARNESS_PKG}@${METAHARNESS_PIN_VERSION}`;
|
|
325
|
+
|
|
326
|
+
/** Expose resolution for diagnostics/tests (which path served the bins). */
|
|
327
|
+
export function metaharnessResolution() {
|
|
328
|
+
const r = resolveMetaharnessBins();
|
|
329
|
+
return r.ok ? { ok: true, source: r.source, bins: r.bins } : { ok: false, reason: r.reason };
|
|
330
|
+
}
|