claude-mpm 5.4.41__py3-none-any.whl → 5.6.72__py3-none-any.whl
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.
Potentially problematic release.
This version of claude-mpm might be problematic. Click here for more details.
- claude_mpm/VERSION +1 -1
- claude_mpm/agents/CLAUDE_MPM_OUTPUT_STYLE.md +66 -241
- claude_mpm/agents/CLAUDE_MPM_RESEARCH_OUTPUT_STYLE.md +413 -0
- claude_mpm/agents/CLAUDE_MPM_TEACHER_OUTPUT_STYLE.md +109 -1925
- claude_mpm/agents/PM_INSTRUCTIONS.md +161 -298
- claude_mpm/agents/WORKFLOW.md +2 -0
- claude_mpm/agents/templates/circuit-breakers.md +26 -17
- claude_mpm/auth/__init__.py +35 -0
- claude_mpm/auth/callback_server.py +328 -0
- claude_mpm/auth/models.py +104 -0
- claude_mpm/auth/oauth_manager.py +266 -0
- claude_mpm/auth/providers/__init__.py +12 -0
- claude_mpm/auth/providers/base.py +165 -0
- claude_mpm/auth/providers/google.py +261 -0
- claude_mpm/auth/token_storage.py +252 -0
- claude_mpm/cli/__init__.py +5 -1
- claude_mpm/cli/commands/agents.py +2 -4
- claude_mpm/cli/commands/agents_reconcile.py +197 -0
- claude_mpm/cli/commands/autotodos.py +566 -0
- claude_mpm/cli/commands/commander.py +216 -0
- claude_mpm/cli/commands/configure.py +620 -21
- claude_mpm/cli/commands/configure_agent_display.py +3 -1
- claude_mpm/cli/commands/hook_errors.py +60 -60
- claude_mpm/cli/commands/mcp.py +29 -17
- claude_mpm/cli/commands/mcp_command_router.py +39 -0
- claude_mpm/cli/commands/mcp_service_commands.py +304 -0
- claude_mpm/cli/commands/monitor.py +2 -2
- claude_mpm/cli/commands/mpm_init/core.py +15 -8
- claude_mpm/cli/commands/oauth.py +481 -0
- claude_mpm/cli/commands/profile.py +9 -10
- claude_mpm/cli/commands/run.py +35 -3
- claude_mpm/cli/commands/skill_source.py +51 -2
- claude_mpm/cli/commands/skills.py +182 -32
- claude_mpm/cli/executor.py +129 -16
- claude_mpm/cli/helpers.py +1 -1
- claude_mpm/cli/interactive/__init__.py +10 -0
- claude_mpm/cli/interactive/agent_wizard.py +30 -50
- claude_mpm/cli/interactive/questionary_styles.py +65 -0
- claude_mpm/cli/interactive/skill_selector.py +481 -0
- claude_mpm/cli/parsers/base_parser.py +89 -1
- claude_mpm/cli/parsers/commander_parser.py +116 -0
- claude_mpm/cli/parsers/mcp_parser.py +79 -0
- claude_mpm/cli/parsers/oauth_parser.py +165 -0
- claude_mpm/cli/parsers/profile_parser.py +0 -1
- claude_mpm/cli/parsers/run_parser.py +10 -0
- claude_mpm/cli/parsers/skill_source_parser.py +4 -0
- claude_mpm/cli/parsers/skills_parser.py +2 -3
- claude_mpm/cli/startup.py +662 -524
- claude_mpm/cli/startup_display.py +76 -7
- claude_mpm/cli/startup_logging.py +2 -2
- claude_mpm/cli/utils.py +7 -3
- claude_mpm/commander/__init__.py +78 -0
- claude_mpm/commander/adapters/__init__.py +60 -0
- claude_mpm/commander/adapters/auggie.py +260 -0
- claude_mpm/commander/adapters/base.py +288 -0
- claude_mpm/commander/adapters/claude_code.py +392 -0
- claude_mpm/commander/adapters/codex.py +237 -0
- claude_mpm/commander/adapters/communication.py +366 -0
- claude_mpm/commander/adapters/example_usage.py +310 -0
- claude_mpm/commander/adapters/mpm.py +389 -0
- claude_mpm/commander/adapters/registry.py +204 -0
- claude_mpm/commander/api/__init__.py +16 -0
- claude_mpm/commander/api/app.py +121 -0
- claude_mpm/commander/api/errors.py +133 -0
- claude_mpm/commander/api/routes/__init__.py +8 -0
- claude_mpm/commander/api/routes/events.py +184 -0
- claude_mpm/commander/api/routes/inbox.py +171 -0
- claude_mpm/commander/api/routes/messages.py +148 -0
- claude_mpm/commander/api/routes/projects.py +271 -0
- claude_mpm/commander/api/routes/sessions.py +226 -0
- claude_mpm/commander/api/routes/work.py +296 -0
- claude_mpm/commander/api/schemas.py +186 -0
- claude_mpm/commander/chat/__init__.py +7 -0
- claude_mpm/commander/chat/cli.py +149 -0
- claude_mpm/commander/chat/commands.py +122 -0
- claude_mpm/commander/chat/repl.py +1821 -0
- claude_mpm/commander/config.py +51 -0
- claude_mpm/commander/config_loader.py +115 -0
- claude_mpm/commander/core/__init__.py +10 -0
- claude_mpm/commander/core/block_manager.py +325 -0
- claude_mpm/commander/core/response_manager.py +323 -0
- claude_mpm/commander/daemon.py +603 -0
- claude_mpm/commander/env_loader.py +59 -0
- claude_mpm/commander/events/__init__.py +26 -0
- claude_mpm/commander/events/manager.py +392 -0
- claude_mpm/commander/frameworks/__init__.py +12 -0
- claude_mpm/commander/frameworks/base.py +233 -0
- claude_mpm/commander/frameworks/claude_code.py +58 -0
- claude_mpm/commander/frameworks/mpm.py +57 -0
- claude_mpm/commander/git/__init__.py +5 -0
- claude_mpm/commander/git/worktree_manager.py +212 -0
- claude_mpm/commander/inbox/__init__.py +16 -0
- claude_mpm/commander/inbox/dedup.py +128 -0
- claude_mpm/commander/inbox/inbox.py +224 -0
- claude_mpm/commander/inbox/models.py +70 -0
- claude_mpm/commander/instance_manager.py +865 -0
- claude_mpm/commander/llm/__init__.py +6 -0
- claude_mpm/commander/llm/openrouter_client.py +167 -0
- claude_mpm/commander/llm/summarizer.py +70 -0
- claude_mpm/commander/memory/__init__.py +45 -0
- claude_mpm/commander/memory/compression.py +347 -0
- claude_mpm/commander/memory/embeddings.py +230 -0
- claude_mpm/commander/memory/entities.py +310 -0
- claude_mpm/commander/memory/example_usage.py +290 -0
- claude_mpm/commander/memory/integration.py +325 -0
- claude_mpm/commander/memory/search.py +381 -0
- claude_mpm/commander/memory/store.py +657 -0
- claude_mpm/commander/models/__init__.py +18 -0
- claude_mpm/commander/models/events.py +127 -0
- claude_mpm/commander/models/project.py +162 -0
- claude_mpm/commander/models/work.py +214 -0
- claude_mpm/commander/parsing/__init__.py +20 -0
- claude_mpm/commander/parsing/extractor.py +132 -0
- claude_mpm/commander/parsing/output_parser.py +270 -0
- claude_mpm/commander/parsing/patterns.py +100 -0
- claude_mpm/commander/persistence/__init__.py +11 -0
- claude_mpm/commander/persistence/event_store.py +274 -0
- claude_mpm/commander/persistence/state_store.py +403 -0
- claude_mpm/commander/persistence/work_store.py +164 -0
- claude_mpm/commander/polling/__init__.py +13 -0
- claude_mpm/commander/polling/event_detector.py +104 -0
- claude_mpm/commander/polling/output_buffer.py +49 -0
- claude_mpm/commander/polling/output_poller.py +153 -0
- claude_mpm/commander/project_session.py +268 -0
- claude_mpm/commander/proxy/__init__.py +12 -0
- claude_mpm/commander/proxy/formatter.py +89 -0
- claude_mpm/commander/proxy/output_handler.py +191 -0
- claude_mpm/commander/proxy/relay.py +155 -0
- claude_mpm/commander/registry.py +410 -0
- claude_mpm/commander/runtime/__init__.py +10 -0
- claude_mpm/commander/runtime/executor.py +191 -0
- claude_mpm/commander/runtime/monitor.py +346 -0
- claude_mpm/commander/session/__init__.py +6 -0
- claude_mpm/commander/session/context.py +81 -0
- claude_mpm/commander/session/manager.py +59 -0
- claude_mpm/commander/tmux_orchestrator.py +362 -0
- claude_mpm/commander/web/__init__.py +1 -0
- claude_mpm/commander/work/__init__.py +30 -0
- claude_mpm/commander/work/executor.py +207 -0
- claude_mpm/commander/work/queue.py +405 -0
- claude_mpm/commander/workflow/__init__.py +27 -0
- claude_mpm/commander/workflow/event_handler.py +241 -0
- claude_mpm/commander/workflow/notifier.py +146 -0
- claude_mpm/commands/mpm-config.md +8 -0
- claude_mpm/commands/mpm-doctor.md +8 -0
- claude_mpm/commands/mpm-help.md +8 -0
- claude_mpm/commands/mpm-init.md +8 -0
- claude_mpm/commands/mpm-monitor.md +8 -0
- claude_mpm/commands/mpm-organize.md +8 -0
- claude_mpm/commands/mpm-postmortem.md +8 -0
- claude_mpm/commands/mpm-session-resume.md +9 -1
- claude_mpm/commands/mpm-status.md +8 -0
- claude_mpm/commands/mpm-ticket-view.md +8 -0
- claude_mpm/commands/mpm-version.md +8 -0
- claude_mpm/commands/mpm.md +8 -0
- claude_mpm/config/agent_presets.py +8 -7
- claude_mpm/config/skill_sources.py +16 -0
- claude_mpm/constants.py +6 -0
- claude_mpm/core/claude_runner.py +154 -2
- claude_mpm/core/config.py +35 -22
- claude_mpm/core/config_constants.py +74 -9
- claude_mpm/core/constants.py +56 -12
- claude_mpm/core/hook_manager.py +53 -4
- claude_mpm/core/interactive_session.py +12 -11
- claude_mpm/core/logger.py +26 -9
- claude_mpm/core/logging_utils.py +39 -13
- claude_mpm/core/network_config.py +148 -0
- claude_mpm/core/oneshot_session.py +7 -6
- claude_mpm/core/optimized_startup.py +3 -1
- claude_mpm/core/output_style_manager.py +66 -18
- claude_mpm/core/shared/config_loader.py +3 -1
- claude_mpm/core/socketio_pool.py +47 -15
- claude_mpm/core/unified_config.py +54 -8
- claude_mpm/core/unified_paths.py +95 -90
- claude_mpm/dashboard/static/svelte-build/_app/immutable/assets/0.C33zOoyM.css +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/assets/2.CW1J-YuA.css +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/1WZnGYqX.js +24 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/67pF3qNn.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/6RxdMKe4.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/8cZrfX0h.js +60 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/9a6T2nm-.js +7 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/B443AUzu.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/B8AwtY2H.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BF15LAsF.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BQaXIfA_.js +331 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BRcwIQNr.js +4 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{uj46x2Wr.js → BSNlmTZj.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BV6nKitt.js +43 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BViJ8lZt.js +128 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BcQ-Q0FE.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Bpyvgze_.js +30 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BzTRqg-z.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/C0Fr8dve.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/C3rbW_a-.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/C8WYN38h.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/C9I8FlXH.js +61 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CIQcWgO2.js +36 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CIctN7YN.js +7 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CKrS_JZW.js +145 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CR6P9C4A.js +89 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CRRR9MD_.js +2 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CRcR2DqT.js +334 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CSXtMOf0.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CT-sbxSk.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CWm6DJsp.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CmKTTxBW.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CpqQ1Kzn.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Cu_Erd72.js +261 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/D2nGpDRe.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/D9iCMida.js +267 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/D9ykgMoY.js +10 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DL2Ldur1.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DPfltzjH.js +165 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{N4qtv3Hx.js → DR8nis88.js} +2 -2
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DUliQN2b.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DVp1hx9R.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DXlhR01x.js +122 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/D_lyTybS.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DngoTTgh.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DqkmHtDC.js +220 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DsDh8EYs.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DypDmXgd.js +139 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Gi6I4Gst.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/IPYC-LnN.js +162 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/JTLiF7dt.js +24 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/JpevfAFt.js +68 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{DjhvlsAc.js → NqQ1dWOy.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/R8CEIRAd.js +2 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Zxy7qc-l.js +64 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/q9Hm6zAU.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/qtd3IeO4.js +15 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/ulBFON_C.js +65 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/wQVh1CoA.js +10 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/entry/app.Dr7t0z2J.js +2 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/entry/start.BGhZHUS3.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/nodes/{0.CAGBuiOw.js → 0.RgBboRvH.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/nodes/1.DG-KkbDf.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/nodes/2.D_jnf-x6.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/version.json +1 -1
- claude_mpm/dashboard/static/svelte-build/index.html +11 -11
- claude_mpm/dashboard-svelte/node_modules/katex/src/fonts/generate_fonts.py +58 -0
- claude_mpm/dashboard-svelte/node_modules/katex/src/metrics/extract_tfms.py +114 -0
- claude_mpm/dashboard-svelte/node_modules/katex/src/metrics/extract_ttfs.py +122 -0
- claude_mpm/dashboard-svelte/node_modules/katex/src/metrics/format_json.py +28 -0
- claude_mpm/dashboard-svelte/node_modules/katex/src/metrics/parse_tfm.py +211 -0
- claude_mpm/experimental/cli_enhancements.py +2 -1
- claude_mpm/hooks/claude_hooks/INTEGRATION_EXAMPLE.md +243 -0
- claude_mpm/hooks/claude_hooks/README_AUTO_PAUSE.md +403 -0
- claude_mpm/hooks/claude_hooks/__pycache__/auto_pause_handler.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/event_handlers.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/hook_handler.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/memory_integration.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/response_tracking.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/auto_pause_handler.py +485 -0
- claude_mpm/hooks/claude_hooks/event_handlers.py +466 -136
- claude_mpm/hooks/claude_hooks/hook_handler.py +204 -104
- claude_mpm/hooks/claude_hooks/hook_wrapper.sh +6 -11
- claude_mpm/hooks/claude_hooks/installer.py +291 -59
- claude_mpm/hooks/claude_hooks/memory_integration.py +52 -32
- claude_mpm/hooks/claude_hooks/response_tracking.py +43 -60
- claude_mpm/hooks/claude_hooks/services/__init__.py +21 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/__init__.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/connection_manager_http.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/container.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/protocols.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/state_manager.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/subagent_processor.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/connection_manager.py +41 -26
- claude_mpm/hooks/claude_hooks/services/connection_manager_http.py +38 -105
- claude_mpm/hooks/claude_hooks/services/container.py +326 -0
- claude_mpm/hooks/claude_hooks/services/protocols.py +328 -0
- claude_mpm/hooks/claude_hooks/services/state_manager.py +25 -38
- claude_mpm/hooks/claude_hooks/services/subagent_processor.py +75 -77
- claude_mpm/hooks/kuzu_memory_hook.py +5 -5
- claude_mpm/hooks/session_resume_hook.py +89 -1
- claude_mpm/hooks/templates/pre_tool_use_simple.py +6 -6
- claude_mpm/hooks/templates/pre_tool_use_template.py +16 -8
- claude_mpm/init.py +224 -4
- claude_mpm/mcp/__init__.py +9 -0
- claude_mpm/mcp/google_workspace_server.py +610 -0
- claude_mpm/scripts/claude-hook-handler.sh +46 -19
- claude_mpm/services/agents/agent_recommendation_service.py +8 -8
- claude_mpm/services/agents/agent_selection_service.py +2 -2
- claude_mpm/services/agents/cache_git_manager.py +1 -1
- claude_mpm/services/agents/deployment/agent_discovery_service.py +3 -1
- claude_mpm/services/agents/deployment/agent_format_converter.py +25 -13
- claude_mpm/services/agents/deployment/agent_template_builder.py +37 -17
- claude_mpm/services/agents/deployment/async_agent_deployment.py +31 -27
- claude_mpm/services/agents/deployment/deployment_reconciler.py +577 -0
- claude_mpm/services/agents/deployment/local_template_deployment.py +3 -1
- claude_mpm/services/agents/deployment/multi_source_deployment_service.py +36 -8
- claude_mpm/services/agents/deployment/remote_agent_discovery_service.py +50 -26
- claude_mpm/services/agents/deployment/startup_reconciliation.py +138 -0
- claude_mpm/services/agents/git_source_manager.py +21 -2
- claude_mpm/services/agents/loading/framework_agent_loader.py +75 -2
- claude_mpm/services/agents/single_tier_deployment_service.py +4 -4
- claude_mpm/services/agents/sources/git_source_sync_service.py +116 -5
- claude_mpm/services/agents/startup_sync.py +5 -2
- claude_mpm/services/cli/__init__.py +3 -0
- claude_mpm/services/cli/incremental_pause_manager.py +561 -0
- claude_mpm/services/cli/session_resume_helper.py +10 -2
- claude_mpm/services/command_deployment_service.py +44 -26
- claude_mpm/services/delegation_detector.py +175 -0
- claude_mpm/services/diagnostics/checks/agent_sources_check.py +30 -0
- claude_mpm/services/diagnostics/checks/configuration_check.py +24 -0
- claude_mpm/services/diagnostics/checks/installation_check.py +22 -0
- claude_mpm/services/diagnostics/checks/mcp_services_check.py +23 -0
- claude_mpm/services/diagnostics/doctor_reporter.py +31 -1
- claude_mpm/services/diagnostics/models.py +14 -1
- claude_mpm/services/event_log.py +325 -0
- claude_mpm/services/hook_installer_service.py +77 -8
- claude_mpm/services/infrastructure/__init__.py +4 -0
- claude_mpm/services/infrastructure/context_usage_tracker.py +291 -0
- claude_mpm/services/infrastructure/resume_log_generator.py +24 -5
- claude_mpm/services/mcp_config_manager.py +99 -19
- claude_mpm/services/mcp_service_registry.py +294 -0
- claude_mpm/services/monitor/daemon_manager.py +15 -4
- claude_mpm/services/monitor/management/lifecycle.py +8 -3
- claude_mpm/services/monitor/server.py +111 -16
- claude_mpm/services/pm_skills_deployer.py +302 -94
- claude_mpm/services/profile_manager.py +10 -4
- claude_mpm/services/skills/git_skill_source_manager.py +192 -29
- claude_mpm/services/skills/selective_skill_deployer.py +211 -46
- claude_mpm/services/skills/skill_discovery_service.py +74 -4
- claude_mpm/services/skills_deployer.py +192 -70
- claude_mpm/services/socketio/handlers/hook.py +14 -7
- claude_mpm/services/socketio/server/main.py +12 -4
- claude_mpm/skills/__init__.py +2 -1
- claude_mpm/skills/bundled/collaboration/brainstorming/SKILL.md +79 -0
- claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/SKILL.md +178 -0
- claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/agent-prompts.md +577 -0
- claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/coordination-patterns.md +467 -0
- claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/examples.md +537 -0
- claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/troubleshooting.md +730 -0
- claude_mpm/skills/bundled/collaboration/git-worktrees.md +317 -0
- claude_mpm/skills/bundled/collaboration/requesting-code-review/SKILL.md +112 -0
- claude_mpm/skills/bundled/collaboration/requesting-code-review/references/code-reviewer-template.md +146 -0
- claude_mpm/skills/bundled/collaboration/requesting-code-review/references/review-examples.md +412 -0
- claude_mpm/skills/bundled/collaboration/stacked-prs.md +251 -0
- claude_mpm/skills/bundled/collaboration/writing-plans/SKILL.md +81 -0
- claude_mpm/skills/bundled/collaboration/writing-plans/references/best-practices.md +362 -0
- claude_mpm/skills/bundled/collaboration/writing-plans/references/plan-structure-templates.md +312 -0
- claude_mpm/skills/bundled/debugging/root-cause-tracing/SKILL.md +152 -0
- claude_mpm/skills/bundled/debugging/root-cause-tracing/references/advanced-techniques.md +668 -0
- claude_mpm/skills/bundled/debugging/root-cause-tracing/references/examples.md +587 -0
- claude_mpm/skills/bundled/debugging/root-cause-tracing/references/integration.md +438 -0
- claude_mpm/skills/bundled/debugging/root-cause-tracing/references/tracing-techniques.md +391 -0
- claude_mpm/skills/bundled/debugging/systematic-debugging/CREATION-LOG.md +119 -0
- claude_mpm/skills/bundled/debugging/systematic-debugging/SKILL.md +148 -0
- claude_mpm/skills/bundled/debugging/systematic-debugging/references/anti-patterns.md +483 -0
- claude_mpm/skills/bundled/debugging/systematic-debugging/references/examples.md +452 -0
- claude_mpm/skills/bundled/debugging/systematic-debugging/references/troubleshooting.md +449 -0
- claude_mpm/skills/bundled/debugging/systematic-debugging/references/workflow.md +411 -0
- claude_mpm/skills/bundled/debugging/systematic-debugging/test-academic.md +14 -0
- claude_mpm/skills/bundled/debugging/systematic-debugging/test-pressure-1.md +58 -0
- claude_mpm/skills/bundled/debugging/systematic-debugging/test-pressure-2.md +68 -0
- claude_mpm/skills/bundled/debugging/systematic-debugging/test-pressure-3.md +69 -0
- claude_mpm/skills/bundled/debugging/verification-before-completion/SKILL.md +131 -0
- claude_mpm/skills/bundled/debugging/verification-before-completion/references/gate-function.md +325 -0
- claude_mpm/skills/bundled/debugging/verification-before-completion/references/integration-and-workflows.md +490 -0
- claude_mpm/skills/bundled/debugging/verification-before-completion/references/red-flags-and-failures.md +425 -0
- claude_mpm/skills/bundled/debugging/verification-before-completion/references/verification-patterns.md +499 -0
- claude_mpm/skills/bundled/infrastructure/env-manager/INTEGRATION.md +611 -0
- claude_mpm/skills/bundled/infrastructure/env-manager/README.md +596 -0
- claude_mpm/skills/bundled/infrastructure/env-manager/SKILL.md +260 -0
- claude_mpm/skills/bundled/infrastructure/env-manager/examples/nextjs-env-structure.md +315 -0
- claude_mpm/skills/bundled/infrastructure/env-manager/references/frameworks.md +436 -0
- claude_mpm/skills/bundled/infrastructure/env-manager/references/security.md +433 -0
- claude_mpm/skills/bundled/infrastructure/env-manager/references/synchronization.md +452 -0
- claude_mpm/skills/bundled/infrastructure/env-manager/references/troubleshooting.md +404 -0
- claude_mpm/skills/bundled/infrastructure/env-manager/references/validation.md +420 -0
- claude_mpm/skills/bundled/main/artifacts-builder/SKILL.md +86 -0
- claude_mpm/skills/bundled/main/internal-comms/SKILL.md +43 -0
- claude_mpm/skills/bundled/main/internal-comms/examples/3p-updates.md +47 -0
- claude_mpm/skills/bundled/main/internal-comms/examples/company-newsletter.md +65 -0
- claude_mpm/skills/bundled/main/internal-comms/examples/faq-answers.md +30 -0
- claude_mpm/skills/bundled/main/internal-comms/examples/general-comms.md +16 -0
- claude_mpm/skills/bundled/main/mcp-builder/SKILL.md +160 -0
- claude_mpm/skills/bundled/main/mcp-builder/reference/design_principles.md +412 -0
- claude_mpm/skills/bundled/main/mcp-builder/reference/evaluation.md +602 -0
- claude_mpm/skills/bundled/main/mcp-builder/reference/mcp_best_practices.md +915 -0
- claude_mpm/skills/bundled/main/mcp-builder/reference/node_mcp_server.md +916 -0
- claude_mpm/skills/bundled/main/mcp-builder/reference/python_mcp_server.md +752 -0
- claude_mpm/skills/bundled/main/mcp-builder/reference/workflow.md +1237 -0
- claude_mpm/skills/bundled/main/skill-creator/SKILL.md +189 -0
- claude_mpm/skills/bundled/main/skill-creator/references/best-practices.md +500 -0
- claude_mpm/skills/bundled/main/skill-creator/references/creation-workflow.md +464 -0
- claude_mpm/skills/bundled/main/skill-creator/references/examples.md +619 -0
- claude_mpm/skills/bundled/main/skill-creator/references/progressive-disclosure.md +437 -0
- claude_mpm/skills/bundled/main/skill-creator/references/skill-structure.md +231 -0
- claude_mpm/skills/bundled/php/espocrm-development/SKILL.md +170 -0
- claude_mpm/skills/bundled/php/espocrm-development/references/architecture.md +602 -0
- claude_mpm/skills/bundled/php/espocrm-development/references/common-tasks.md +821 -0
- claude_mpm/skills/bundled/php/espocrm-development/references/development-workflow.md +742 -0
- claude_mpm/skills/bundled/php/espocrm-development/references/frontend-customization.md +726 -0
- claude_mpm/skills/bundled/php/espocrm-development/references/hooks-and-services.md +764 -0
- claude_mpm/skills/bundled/php/espocrm-development/references/testing-debugging.md +831 -0
- claude_mpm/skills/bundled/pm/mpm/SKILL.md +38 -0
- claude_mpm/skills/bundled/pm/mpm-agent-update-workflow/SKILL.md +75 -0
- claude_mpm/skills/bundled/pm/mpm-bug-reporting/SKILL.md +248 -0
- claude_mpm/skills/bundled/pm/mpm-circuit-breaker-enforcement/SKILL.md +476 -0
- claude_mpm/skills/bundled/pm/mpm-config/SKILL.md +29 -0
- claude_mpm/skills/bundled/pm/mpm-delegation-patterns/SKILL.md +167 -0
- claude_mpm/skills/bundled/pm/mpm-doctor/SKILL.md +53 -0
- claude_mpm/skills/bundled/pm/mpm-git-file-tracking/SKILL.md +113 -0
- claude_mpm/skills/bundled/pm/mpm-help/SKILL.md +35 -0
- claude_mpm/skills/bundled/pm/mpm-init/SKILL.md +125 -0
- claude_mpm/skills/bundled/pm/mpm-monitor/SKILL.md +32 -0
- claude_mpm/skills/bundled/pm/mpm-organize/SKILL.md +121 -0
- claude_mpm/skills/bundled/pm/mpm-postmortem/SKILL.md +22 -0
- claude_mpm/skills/bundled/pm/mpm-pr-workflow/SKILL.md +124 -0
- claude_mpm/skills/bundled/pm/mpm-session-management/SKILL.md +312 -0
- claude_mpm/skills/bundled/pm/mpm-session-pause/SKILL.md +170 -0
- claude_mpm/skills/bundled/pm/mpm-session-resume/SKILL.md +31 -0
- claude_mpm/skills/bundled/pm/mpm-status/SKILL.md +37 -0
- claude_mpm/skills/bundled/pm/mpm-teaching-mode/SKILL.md +657 -0
- claude_mpm/skills/bundled/pm/mpm-ticket-view/SKILL.md +110 -0
- claude_mpm/skills/bundled/pm/mpm-ticketing-integration/SKILL.md +154 -0
- claude_mpm/skills/bundled/pm/mpm-tool-usage-guide/SKILL.md +386 -0
- claude_mpm/skills/bundled/pm/mpm-verification-protocols/SKILL.md +198 -0
- claude_mpm/skills/bundled/pm/mpm-version/SKILL.md +21 -0
- claude_mpm/skills/bundled/react/flexlayout-react.md +742 -0
- claude_mpm/skills/bundled/rust/desktop-applications/SKILL.md +226 -0
- claude_mpm/skills/bundled/rust/desktop-applications/references/architecture-patterns.md +901 -0
- claude_mpm/skills/bundled/rust/desktop-applications/references/native-gui-frameworks.md +901 -0
- claude_mpm/skills/bundled/rust/desktop-applications/references/platform-integration.md +775 -0
- claude_mpm/skills/bundled/rust/desktop-applications/references/state-management.md +937 -0
- claude_mpm/skills/bundled/rust/desktop-applications/references/tauri-framework.md +770 -0
- claude_mpm/skills/bundled/rust/desktop-applications/references/testing-deployment.md +961 -0
- claude_mpm/skills/bundled/security-scanning.md +112 -0
- claude_mpm/skills/bundled/tauri/tauri-async-patterns.md +495 -0
- claude_mpm/skills/bundled/tauri/tauri-build-deploy.md +599 -0
- claude_mpm/skills/bundled/tauri/tauri-command-patterns.md +535 -0
- claude_mpm/skills/bundled/tauri/tauri-error-handling.md +613 -0
- claude_mpm/skills/bundled/tauri/tauri-event-system.md +648 -0
- claude_mpm/skills/bundled/tauri/tauri-file-system.md +673 -0
- claude_mpm/skills/bundled/tauri/tauri-frontend-integration.md +767 -0
- claude_mpm/skills/bundled/tauri/tauri-performance.md +669 -0
- claude_mpm/skills/bundled/tauri/tauri-state-management.md +573 -0
- claude_mpm/skills/bundled/tauri/tauri-testing.md +384 -0
- claude_mpm/skills/bundled/tauri/tauri-window-management.md +628 -0
- claude_mpm/skills/bundled/testing/condition-based-waiting/SKILL.md +119 -0
- claude_mpm/skills/bundled/testing/condition-based-waiting/references/patterns-and-implementation.md +253 -0
- claude_mpm/skills/bundled/testing/test-driven-development/SKILL.md +145 -0
- claude_mpm/skills/bundled/testing/test-driven-development/references/anti-patterns.md +543 -0
- claude_mpm/skills/bundled/testing/test-driven-development/references/examples.md +741 -0
- claude_mpm/skills/bundled/testing/test-driven-development/references/integration.md +470 -0
- claude_mpm/skills/bundled/testing/test-driven-development/references/philosophy.md +458 -0
- claude_mpm/skills/bundled/testing/test-driven-development/references/workflow.md +639 -0
- claude_mpm/skills/bundled/testing/test-quality-inspector/SKILL.md +458 -0
- claude_mpm/skills/bundled/testing/test-quality-inspector/examples/example-inspection-report.md +411 -0
- claude_mpm/skills/bundled/testing/test-quality-inspector/references/assertion-quality.md +317 -0
- claude_mpm/skills/bundled/testing/test-quality-inspector/references/inspection-checklist.md +270 -0
- claude_mpm/skills/bundled/testing/test-quality-inspector/references/red-flags.md +436 -0
- claude_mpm/skills/bundled/testing/testing-anti-patterns/SKILL.md +140 -0
- claude_mpm/skills/bundled/testing/testing-anti-patterns/references/completeness-anti-patterns.md +572 -0
- claude_mpm/skills/bundled/testing/testing-anti-patterns/references/core-anti-patterns.md +411 -0
- claude_mpm/skills/bundled/testing/testing-anti-patterns/references/detection-guide.md +569 -0
- claude_mpm/skills/bundled/testing/testing-anti-patterns/references/tdd-connection.md +695 -0
- claude_mpm/skills/bundled/testing/webapp-testing/SKILL.md +184 -0
- claude_mpm/skills/bundled/testing/webapp-testing/decision-tree.md +459 -0
- claude_mpm/skills/bundled/testing/webapp-testing/playwright-patterns.md +479 -0
- claude_mpm/skills/bundled/testing/webapp-testing/reconnaissance-pattern.md +687 -0
- claude_mpm/skills/bundled/testing/webapp-testing/server-management.md +758 -0
- claude_mpm/skills/bundled/testing/webapp-testing/troubleshooting.md +868 -0
- claude_mpm/skills/registry.py +295 -90
- claude_mpm/skills/skill_manager.py +29 -23
- claude_mpm/templates/.pre-commit-config.yaml +112 -0
- claude_mpm/utils/agent_dependency_loader.py +103 -4
- claude_mpm/utils/robust_installer.py +45 -24
- claude_mpm-5.6.72.dist-info/METADATA +416 -0
- {claude_mpm-5.4.41.dist-info → claude_mpm-5.6.72.dist-info}/RECORD +477 -159
- {claude_mpm-5.4.41.dist-info → claude_mpm-5.6.72.dist-info}/WHEEL +1 -1
- {claude_mpm-5.4.41.dist-info → claude_mpm-5.6.72.dist-info}/entry_points.txt +2 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/assets/0.B_FtCwCQ.css +0 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/assets/2.Cl_eSA4x.css +0 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BgChzWQ1.js +0 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CIXEwuWe.js +0 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CWc5urbQ.js +0 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DMkZpdF2.js +0 -2
- claude_mpm/dashboard/static/svelte-build/_app/immutable/entry/app.DTL5mJO-.js +0 -2
- claude_mpm/dashboard/static/svelte-build/_app/immutable/entry/start.DzuEhzqh.js +0 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/nodes/1.DFLC8jdE.js +0 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/nodes/2.DPvEihJJ.js +0 -10
- claude_mpm/hooks/claude_hooks/__pycache__/installer.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/connection_manager.cpython-311.pyc +0 -0
- claude_mpm-5.4.41.dist-info/METADATA +0 -998
- {claude_mpm-5.4.41.dist-info → claude_mpm-5.6.72.dist-info}/licenses/LICENSE +0 -0
- {claude_mpm-5.4.41.dist-info → claude_mpm-5.6.72.dist-info}/licenses/LICENSE-FAQ.md +0 -0
- {claude_mpm-5.4.41.dist-info → claude_mpm-5.6.72.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,411 @@
|
|
|
1
|
+
# Core Testing Anti-Patterns
|
|
2
|
+
|
|
3
|
+
The three most critical testing anti-patterns that violate fundamental testing principles. These patterns test mock behavior instead of real behavior, pollute production code with test concerns, or mock without understanding dependencies.
|
|
4
|
+
|
|
5
|
+
## Anti-Pattern 1: Testing Mock Behavior
|
|
6
|
+
|
|
7
|
+
**The violation:**
|
|
8
|
+
```typescript
|
|
9
|
+
// ❌ BAD: Testing that the mock exists
|
|
10
|
+
test('renders sidebar', () => {
|
|
11
|
+
render(<Page />);
|
|
12
|
+
expect(screen.getByTestId('sidebar-mock')).toBeInTheDocument();
|
|
13
|
+
});
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
**Why this is wrong:**
|
|
17
|
+
- You're verifying the mock works, not that the component works
|
|
18
|
+
- Test passes when mock is present, fails when it's not
|
|
19
|
+
- Tells you nothing about real behavior
|
|
20
|
+
- False confidence - production may still be broken
|
|
21
|
+
|
|
22
|
+
**your human partner's correction:** "Are we testing the behavior of a mock?"
|
|
23
|
+
|
|
24
|
+
**The fix:**
|
|
25
|
+
```typescript
|
|
26
|
+
// ✅ GOOD: Test real component or don't mock it
|
|
27
|
+
test('renders sidebar', () => {
|
|
28
|
+
render(<Page />); // Don't mock sidebar
|
|
29
|
+
expect(screen.getByRole('navigation')).toBeInTheDocument();
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
// OR if sidebar must be mocked for isolation:
|
|
33
|
+
// Don't assert on the mock - test Page's behavior with sidebar present
|
|
34
|
+
test('page layout includes sidebar area', () => {
|
|
35
|
+
render(<Page />); // Sidebar mocked for speed
|
|
36
|
+
expect(screen.getByRole('main')).toHaveClass('with-sidebar-layout');
|
|
37
|
+
});
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
### Detection Strategy
|
|
41
|
+
|
|
42
|
+
**Red flags:**
|
|
43
|
+
- Assertions check for `*-mock` in test IDs
|
|
44
|
+
- Test IDs contain "mock", "stub", "fake"
|
|
45
|
+
- Test fails when you remove the mock
|
|
46
|
+
- Can't explain what real behavior you're testing
|
|
47
|
+
|
|
48
|
+
**Gate Function:**
|
|
49
|
+
|
|
50
|
+
```
|
|
51
|
+
BEFORE asserting on any mock element:
|
|
52
|
+
Ask: "Am I testing real component behavior or just mock existence?"
|
|
53
|
+
|
|
54
|
+
IF testing mock existence:
|
|
55
|
+
STOP - Delete the assertion or unmock the component
|
|
56
|
+
|
|
57
|
+
Ask: "What would this test verify in production?"
|
|
58
|
+
|
|
59
|
+
IF answer is "nothing" or unclear:
|
|
60
|
+
STOP - Rethink what you're testing
|
|
61
|
+
|
|
62
|
+
Test real behavior instead
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
### When Mocking is Appropriate
|
|
66
|
+
|
|
67
|
+
**Good reasons to mock:**
|
|
68
|
+
- Isolate slow external dependencies (network, filesystem, DB)
|
|
69
|
+
- Control non-deterministic behavior (time, randomness)
|
|
70
|
+
- Simulate error conditions hard to trigger
|
|
71
|
+
- Speed up test execution
|
|
72
|
+
|
|
73
|
+
**Bad reasons to mock:**
|
|
74
|
+
- "Might be slow" (without measuring)
|
|
75
|
+
- "To be safe"
|
|
76
|
+
- "Everyone mocks this"
|
|
77
|
+
- To avoid understanding dependencies
|
|
78
|
+
|
|
79
|
+
**Rule:** Mock at the boundary of slow/external operations, not high-level application logic.
|
|
80
|
+
|
|
81
|
+
## Anti-Pattern 2: Test-Only Methods in Production
|
|
82
|
+
|
|
83
|
+
**The violation:**
|
|
84
|
+
```typescript
|
|
85
|
+
// ❌ BAD: destroy() only used in tests
|
|
86
|
+
class Session {
|
|
87
|
+
async destroy() { // Looks like production API!
|
|
88
|
+
await this._workspaceManager?.destroyWorkspace(this.id);
|
|
89
|
+
await this._messageRouter?.cleanup();
|
|
90
|
+
this._isDestroyed = true;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// In tests
|
|
95
|
+
afterEach(() => session.destroy());
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
**Why this is wrong:**
|
|
99
|
+
- Production class polluted with test-only code
|
|
100
|
+
- Dangerous if accidentally called in production
|
|
101
|
+
- Violates YAGNI (You Aren't Gonna Need It)
|
|
102
|
+
- Violates separation of concerns
|
|
103
|
+
- Confuses object lifecycle with entity lifecycle
|
|
104
|
+
- Creates maintenance burden (unused code in production)
|
|
105
|
+
|
|
106
|
+
**The fix:**
|
|
107
|
+
```typescript
|
|
108
|
+
// ✅ GOOD: Test utilities handle test cleanup
|
|
109
|
+
// Session has no destroy() - it's stateless in production
|
|
110
|
+
|
|
111
|
+
// In test-utils/session-helpers.ts
|
|
112
|
+
export async function cleanupSession(session: Session) {
|
|
113
|
+
const workspace = session.getWorkspaceInfo();
|
|
114
|
+
if (workspace) {
|
|
115
|
+
await workspaceManager.destroyWorkspace(workspace.id);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
const router = session.getMessageRouter();
|
|
119
|
+
if (router) {
|
|
120
|
+
await router.cleanup();
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// In tests
|
|
125
|
+
afterEach(() => cleanupSession(session));
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
### When Test Utilities Make Sense
|
|
129
|
+
|
|
130
|
+
**Good candidates for test utilities:**
|
|
131
|
+
- Setup/teardown operations
|
|
132
|
+
- Test data builders
|
|
133
|
+
- Assertion helpers
|
|
134
|
+
- Test-specific configurations
|
|
135
|
+
- Lifecycle management for tests
|
|
136
|
+
|
|
137
|
+
**Keep in production:**
|
|
138
|
+
- Methods used by application code
|
|
139
|
+
- Proper public API
|
|
140
|
+
- Business logic
|
|
141
|
+
- Real lifecycle methods (close, dispose)
|
|
142
|
+
|
|
143
|
+
**Key distinction:** If it's never called outside test files, it shouldn't be in production code.
|
|
144
|
+
|
|
145
|
+
### Detection Strategy
|
|
146
|
+
|
|
147
|
+
**Red flags:**
|
|
148
|
+
- Method only called in `*.test.*` or `*.spec.*` files
|
|
149
|
+
- Method name suggests testing (reset, clear, destroy, mock)
|
|
150
|
+
- Comments say "for testing only"
|
|
151
|
+
- Method has no production use case
|
|
152
|
+
|
|
153
|
+
**Gate Function:**
|
|
154
|
+
|
|
155
|
+
```
|
|
156
|
+
BEFORE adding any method to production class:
|
|
157
|
+
Ask: "Is this only used by tests?"
|
|
158
|
+
|
|
159
|
+
IF yes:
|
|
160
|
+
STOP - Don't add it
|
|
161
|
+
Put it in test utilities instead (test-utils/, test-helpers/)
|
|
162
|
+
|
|
163
|
+
Ask: "Does this class own this resource's lifecycle?"
|
|
164
|
+
|
|
165
|
+
IF no:
|
|
166
|
+
STOP - Wrong class for this method
|
|
167
|
+
Resource owner should manage lifecycle
|
|
168
|
+
|
|
169
|
+
Ask: "Would production code ever call this?"
|
|
170
|
+
|
|
171
|
+
IF no:
|
|
172
|
+
STOP - Belongs in test utilities
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
### Refactoring Existing Test-Only Methods
|
|
176
|
+
|
|
177
|
+
**Step-by-step:**
|
|
178
|
+
|
|
179
|
+
1. **Identify** - Find methods only called in test files
|
|
180
|
+
2. **Extract** - Create test utility function with same logic
|
|
181
|
+
3. **Migrate** - Update tests to use utility
|
|
182
|
+
4. **Remove** - Delete test-only method from production
|
|
183
|
+
5. **Verify** - Production builds/bundles are cleaner
|
|
184
|
+
|
|
185
|
+
**Example refactoring:**
|
|
186
|
+
|
|
187
|
+
```typescript
|
|
188
|
+
// Before: Production class polluted
|
|
189
|
+
class Database {
|
|
190
|
+
async reset() { /* only for tests */ }
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
// After: Clean separation
|
|
194
|
+
// database.ts - production
|
|
195
|
+
class Database {
|
|
196
|
+
// No reset() method
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
// test-utils/database.ts - tests only
|
|
200
|
+
export async function resetTestDatabase(db: Database) {
|
|
201
|
+
// Use public API to achieve reset
|
|
202
|
+
await db.executeRaw('TRUNCATE ALL TABLES');
|
|
203
|
+
}
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
## Anti-Pattern 3: Mocking Without Understanding
|
|
207
|
+
|
|
208
|
+
**The violation:**
|
|
209
|
+
```typescript
|
|
210
|
+
// ❌ BAD: Mock breaks test logic
|
|
211
|
+
test('detects duplicate server', async () => {
|
|
212
|
+
// Mock prevents config write that test depends on!
|
|
213
|
+
vi.mock('ToolCatalog', () => ({
|
|
214
|
+
discoverAndCacheTools: vi.fn().mockResolvedValue(undefined)
|
|
215
|
+
}));
|
|
216
|
+
|
|
217
|
+
await addServer(config);
|
|
218
|
+
await addServer(config); // Should throw - but won't!
|
|
219
|
+
// Test expects duplicate detection, but mock broke it
|
|
220
|
+
});
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
**Why this is wrong:**
|
|
224
|
+
- Mocked method had side effect test depended on (writing config)
|
|
225
|
+
- Over-mocking to "be safe" breaks actual behavior
|
|
226
|
+
- Test passes for wrong reason or fails mysteriously
|
|
227
|
+
- You're testing mock behavior, not real behavior
|
|
228
|
+
|
|
229
|
+
**The fix:**
|
|
230
|
+
```typescript
|
|
231
|
+
// ✅ GOOD: Mock at correct level
|
|
232
|
+
test('detects duplicate server', async () => {
|
|
233
|
+
// Mock the slow part, preserve behavior test needs
|
|
234
|
+
vi.mock('MCPServerManager'); // Just mock slow server startup
|
|
235
|
+
// Config writing preserved - duplicate detection works
|
|
236
|
+
|
|
237
|
+
await addServer(config); // Config written
|
|
238
|
+
await expect(addServer(config)).rejects.toThrow('already exists');
|
|
239
|
+
});
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
### Understanding Dependencies Before Mocking
|
|
243
|
+
|
|
244
|
+
**Questions to ask BEFORE mocking:**
|
|
245
|
+
|
|
246
|
+
1. **What does the real method do?**
|
|
247
|
+
- Read the implementation
|
|
248
|
+
- Check for side effects
|
|
249
|
+
- Identify return values
|
|
250
|
+
- Note error conditions
|
|
251
|
+
|
|
252
|
+
2. **What side effects exist?**
|
|
253
|
+
- Filesystem writes
|
|
254
|
+
- Database updates
|
|
255
|
+
- Cache modifications
|
|
256
|
+
- State changes
|
|
257
|
+
- Event emissions
|
|
258
|
+
|
|
259
|
+
3. **What does THIS test need?**
|
|
260
|
+
- Which side effects matter?
|
|
261
|
+
- What behavior am I testing?
|
|
262
|
+
- What can be safely isolated?
|
|
263
|
+
|
|
264
|
+
4. **Where should I mock?**
|
|
265
|
+
- At the boundary of slow operations
|
|
266
|
+
- Below the logic being tested
|
|
267
|
+
- At external system interfaces
|
|
268
|
+
|
|
269
|
+
### Dependency Analysis Example
|
|
270
|
+
|
|
271
|
+
```typescript
|
|
272
|
+
// Analyzing: Should I mock discoverAndCacheTools()?
|
|
273
|
+
|
|
274
|
+
// 1. Read implementation
|
|
275
|
+
async function discoverAndCacheTools(serverConfig) {
|
|
276
|
+
const tools = await fetchToolsFromServer(serverConfig); // Slow
|
|
277
|
+
await cacheTools(serverConfig.id, tools); // Side effect!
|
|
278
|
+
return tools;
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
// 2. Identify side effects
|
|
282
|
+
// - Network call (slow)
|
|
283
|
+
// - Cache write (side effect tests may depend on)
|
|
284
|
+
|
|
285
|
+
// 3. Determine test needs
|
|
286
|
+
test('server registration prevents duplicates', () => {
|
|
287
|
+
// Needs: Config persistence to detect duplicate
|
|
288
|
+
// Doesn't need: Actual tool discovery (slow)
|
|
289
|
+
});
|
|
290
|
+
|
|
291
|
+
// 4. Mock at correct level
|
|
292
|
+
// ✅ Mock network, preserve cache
|
|
293
|
+
vi.mock('server-connection', () => ({
|
|
294
|
+
fetchToolsFromServer: vi.fn().mockResolvedValue([])
|
|
295
|
+
}));
|
|
296
|
+
// cacheTools() runs - test logic intact
|
|
297
|
+
```
|
|
298
|
+
|
|
299
|
+
### Gate Function
|
|
300
|
+
|
|
301
|
+
```
|
|
302
|
+
BEFORE mocking any method:
|
|
303
|
+
STOP - Don't mock yet
|
|
304
|
+
|
|
305
|
+
1. Ask: "What side effects does the real method have?"
|
|
306
|
+
Action: Read implementation, list all side effects
|
|
307
|
+
|
|
308
|
+
2. Ask: "Does this test depend on any of those side effects?"
|
|
309
|
+
Action: Identify which side effects test logic needs
|
|
310
|
+
|
|
311
|
+
3. Ask: "Do I fully understand what this test needs?"
|
|
312
|
+
Action: Write down test's dependencies
|
|
313
|
+
|
|
314
|
+
IF depends on side effects:
|
|
315
|
+
Mock at lower level (the actual slow/external operation)
|
|
316
|
+
OR use test doubles that preserve necessary behavior
|
|
317
|
+
NOT the high-level method the test depends on
|
|
318
|
+
|
|
319
|
+
IF unsure what test depends on:
|
|
320
|
+
Run test with real implementation FIRST
|
|
321
|
+
Observe what actually needs to happen
|
|
322
|
+
THEN add minimal mocking at the right level
|
|
323
|
+
|
|
324
|
+
Red flags:
|
|
325
|
+
- "I'll mock this to be safe"
|
|
326
|
+
- "This might be slow, better mock it"
|
|
327
|
+
- Mocking without reading implementation
|
|
328
|
+
- Mocking without understanding dependency chain
|
|
329
|
+
```
|
|
330
|
+
|
|
331
|
+
### Levels of Mocking
|
|
332
|
+
|
|
333
|
+
**Choose the right level:**
|
|
334
|
+
|
|
335
|
+
```typescript
|
|
336
|
+
// ❌ Too high - breaks test logic
|
|
337
|
+
vi.mock('UserService'); // Mocks everything, including state changes
|
|
338
|
+
|
|
339
|
+
// ❌ Too high - over-mocking
|
|
340
|
+
vi.mock('DatabaseAdapter'); // Could use in-memory DB instead
|
|
341
|
+
|
|
342
|
+
// ✅ Right level - isolates slow operation
|
|
343
|
+
vi.mock('HTTPClient'); // Mock network, preserve business logic
|
|
344
|
+
|
|
345
|
+
// ✅ Right level - controls non-determinism
|
|
346
|
+
vi.spyOn(Date, 'now').mockReturnValue(fixedTimestamp);
|
|
347
|
+
```
|
|
348
|
+
|
|
349
|
+
**Mocking hierarchy (top to bottom):**
|
|
350
|
+
1. **Application logic** - Never mock (this is what you're testing)
|
|
351
|
+
2. **Business layer** - Rarely mock (needed for test assertions)
|
|
352
|
+
3. **Adapter layer** - Sometimes mock (if slow, use test doubles)
|
|
353
|
+
4. **I/O boundaries** - Usually mock (network, filesystem, external APIs)
|
|
354
|
+
5. **Infrastructure** - Always mock (actual servers, databases in unit tests)
|
|
355
|
+
|
|
356
|
+
### Common Mocking Mistakes
|
|
357
|
+
|
|
358
|
+
**Mistake 1: Mocking what you're testing**
|
|
359
|
+
```typescript
|
|
360
|
+
// ❌ BAD
|
|
361
|
+
test('user registration validates email', () => {
|
|
362
|
+
vi.mock('UserValidator'); // You're testing this!
|
|
363
|
+
await registerUser(email);
|
|
364
|
+
});
|
|
365
|
+
|
|
366
|
+
// ✅ GOOD
|
|
367
|
+
test('user registration validates email', () => {
|
|
368
|
+
vi.mock('EmailService'); // Mock email sending, test validation
|
|
369
|
+
await expect(registerUser('invalid')).rejects.toThrow();
|
|
370
|
+
});
|
|
371
|
+
```
|
|
372
|
+
|
|
373
|
+
**Mistake 2: Mocking too broadly**
|
|
374
|
+
```typescript
|
|
375
|
+
// ❌ BAD - mocks entire module
|
|
376
|
+
vi.mock('./user-service');
|
|
377
|
+
|
|
378
|
+
// ✅ GOOD - mocks specific slow operation
|
|
379
|
+
vi.mock('./email-client', () => ({
|
|
380
|
+
sendEmail: vi.fn() // Just the network call
|
|
381
|
+
}));
|
|
382
|
+
```
|
|
383
|
+
|
|
384
|
+
**Mistake 3: Mocking based on assumptions**
|
|
385
|
+
```typescript
|
|
386
|
+
// ❌ BAD - assumption without measurement
|
|
387
|
+
// "Database queries are slow, better mock"
|
|
388
|
+
vi.mock('./database');
|
|
389
|
+
|
|
390
|
+
// ✅ GOOD - measure first
|
|
391
|
+
// Run test unmocked: 2ms (fast enough!)
|
|
392
|
+
// Don't mock unless proven slow
|
|
393
|
+
```
|
|
394
|
+
|
|
395
|
+
## Prevention Through TDD
|
|
396
|
+
|
|
397
|
+
**How TDD prevents these anti-patterns:**
|
|
398
|
+
|
|
399
|
+
1. **Write test first** → Forces you to think about what you're actually testing
|
|
400
|
+
2. **Watch it fail** → Confirms test tests real behavior, not mocks
|
|
401
|
+
3. **Minimal implementation** → No test-only methods creep in
|
|
402
|
+
4. **Real dependencies** → You see what the test actually needs before mocking
|
|
403
|
+
|
|
404
|
+
**If you're testing mock behavior, you violated TDD** - you added mocks without watching test fail against real code first.
|
|
405
|
+
|
|
406
|
+
**TDD workflow prevents:**
|
|
407
|
+
- Testing mock behavior (test fails for real reasons first)
|
|
408
|
+
- Test-only methods (minimal implementation doesn't add them)
|
|
409
|
+
- Uninformed mocking (you understand needs before mocking)
|
|
410
|
+
|
|
411
|
+
See [test-driven-development skill](../../test-driven-development/) for complete TDD workflow.
|