claude-mpm 5.4.64__py3-none-any.whl → 5.4.96__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.

Files changed (163) hide show
  1. claude_mpm/VERSION +1 -1
  2. claude_mpm/agents/CLAUDE_MPM_FOUNDERS_OUTPUT_STYLE.md +405 -0
  3. claude_mpm/agents/CLAUDE_MPM_OUTPUT_STYLE.md +66 -241
  4. claude_mpm/agents/CLAUDE_MPM_TEACHER_OUTPUT_STYLE.md +107 -1928
  5. claude_mpm/agents/PM_INSTRUCTIONS.md +82 -686
  6. claude_mpm/cli/__init__.py +5 -1
  7. claude_mpm/cli/commands/agents.py +2 -4
  8. claude_mpm/cli/commands/agents_reconcile.py +197 -0
  9. claude_mpm/cli/commands/autotodos.py +526 -0
  10. claude_mpm/cli/commands/configure.py +620 -21
  11. claude_mpm/cli/commands/monitor.py +2 -2
  12. claude_mpm/cli/commands/mpm_init/core.py +2 -2
  13. claude_mpm/cli/commands/skills.py +166 -14
  14. claude_mpm/cli/executor.py +89 -0
  15. claude_mpm/cli/interactive/__init__.py +10 -0
  16. claude_mpm/cli/interactive/agent_wizard.py +30 -50
  17. claude_mpm/cli/interactive/questionary_styles.py +65 -0
  18. claude_mpm/cli/interactive/skill_selector.py +481 -0
  19. claude_mpm/cli/parsers/base_parser.py +59 -1
  20. claude_mpm/cli/startup.py +202 -367
  21. claude_mpm/cli/startup_display.py +72 -5
  22. claude_mpm/cli/startup_logging.py +2 -2
  23. claude_mpm/commands/mpm-session-resume.md +1 -1
  24. claude_mpm/constants.py +1 -0
  25. claude_mpm/core/claude_runner.py +2 -2
  26. claude_mpm/core/hook_manager.py +51 -3
  27. claude_mpm/core/interactive_session.py +7 -7
  28. claude_mpm/core/output_style_manager.py +21 -13
  29. claude_mpm/core/unified_config.py +50 -8
  30. claude_mpm/core/unified_paths.py +30 -13
  31. claude_mpm/dashboard/static/svelte-build/_app/immutable/assets/0.C33zOoyM.css +1 -0
  32. claude_mpm/dashboard/static/svelte-build/_app/immutable/assets/2.CW1J-YuA.css +1 -0
  33. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{Cs_tUR18.js → 1WZnGYqX.js} +1 -1
  34. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{CDuw-vjf.js → 67pF3qNn.js} +1 -1
  35. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{bTOqqlTd.js → 6RxdMKe4.js} +1 -1
  36. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{DwBR2MJi.js → 8cZrfX0h.js} +1 -1
  37. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{ZGh7QtNv.js → 9a6T2nm-.js} +1 -1
  38. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{D9lljYKQ.js → B443AUzu.js} +1 -1
  39. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{RJiighC3.js → B8AwtY2H.js} +1 -1
  40. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{uuIeMWc-.js → BF15LAsF.js} +1 -1
  41. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{D3k0OPJN.js → BRcwIQNr.js} +1 -1
  42. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{CyWMqx4W.js → BV6nKitt.js} +1 -1
  43. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{CiIAseT4.js → BViJ8lZt.js} +5 -5
  44. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{CBBdVcY8.js → BcQ-Q0FE.js} +1 -1
  45. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{BovzEFCE.js → Bpyvgze_.js} +1 -1
  46. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BzTRqg-z.js +1 -0
  47. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/C0Fr8dve.js +1 -0
  48. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{eNVUfhuA.js → C3rbW_a-.js} +1 -1
  49. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{GYwsonyD.js → C8WYN38h.js} +1 -1
  50. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{BIF9m_hv.js → C9I8FlXH.js} +1 -1
  51. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{B0uc0UOD.js → CIQcWgO2.js} +3 -3
  52. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{Be7GpZd6.js → CIctN7YN.js} +1 -1
  53. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{Bh0LDWpI.js → CKrS_JZW.js} +2 -2
  54. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{DUrLdbGD.js → CR6P9C4A.js} +1 -1
  55. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{B7xVLGWV.js → CRRR9MD_.js} +1 -1
  56. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CRcR2DqT.js +334 -0
  57. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{Dhb8PKl3.js → CSXtMOf0.js} +1 -1
  58. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{BPYeabCQ.js → CT-sbxSk.js} +1 -1
  59. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{sQeU3Y1z.js → CWm6DJsp.js} +1 -1
  60. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{CnA0NrzZ.js → CpqQ1Kzn.js} +1 -1
  61. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{C4B-KCzX.js → D2nGpDRe.js} +1 -1
  62. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{DGkLK5U1.js → D9iCMida.js} +1 -1
  63. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{BofRWZRR.js → D9ykgMoY.js} +1 -1
  64. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{DmxopI1J.js → DL2Ldur1.js} +1 -1
  65. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{C30mlcqg.js → DPfltzjH.js} +1 -1
  66. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{Vzk33B_K.js → DR8nis88.js} +2 -2
  67. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{DI7hHRFL.js → DUliQN2b.js} +1 -1
  68. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{C4JcI4KD.js → DXlhR01x.js} +1 -1
  69. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{bT1r9zLR.js → D_lyTybS.js} +1 -1
  70. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{DZX00Y4g.js → DngoTTgh.js} +1 -1
  71. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{CzZX-COe.js → DqkmHtDC.js} +1 -1
  72. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{B7RN905-.js → DsDh8EYs.js} +1 -1
  73. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{DLVjFsZ3.js → DypDmXgd.js} +1 -1
  74. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{iEWssX7S.js → IPYC-LnN.js} +1 -1
  75. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/JTLiF7dt.js +24 -0
  76. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{DaimHw_p.js → JpevfAFt.js} +1 -1
  77. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{DY1XQ8fi.js → R8CEIRAd.js} +1 -1
  78. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{Dle-35c7.js → Zxy7qc-l.js} +2 -2
  79. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/q9Hm6zAU.js +1 -0
  80. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{C_Usid8X.js → qtd3IeO4.js} +2 -2
  81. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{CzeYkLYB.js → ulBFON_C.js} +2 -2
  82. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{Cfqx1Qun.js → wQVh1CoA.js} +1 -1
  83. claude_mpm/dashboard/static/svelte-build/_app/immutable/entry/{app.D6-I5TpK.js → app.Dr7t0z2J.js} +2 -2
  84. claude_mpm/dashboard/static/svelte-build/_app/immutable/entry/start.BGhZHUS3.js +1 -0
  85. claude_mpm/dashboard/static/svelte-build/_app/immutable/nodes/{0.m1gL8KXf.js → 0.RgBboRvH.js} +1 -1
  86. claude_mpm/dashboard/static/svelte-build/_app/immutable/nodes/{1.CgNOuw-d.js → 1.DG-KkbDf.js} +1 -1
  87. claude_mpm/dashboard/static/svelte-build/_app/immutable/nodes/2.D_jnf-x6.js +1 -0
  88. claude_mpm/dashboard/static/svelte-build/_app/version.json +1 -1
  89. claude_mpm/dashboard/static/svelte-build/index.html +9 -9
  90. claude_mpm/hooks/claude_hooks/INTEGRATION_EXAMPLE.md +243 -0
  91. claude_mpm/hooks/claude_hooks/README_AUTO_PAUSE.md +403 -0
  92. claude_mpm/hooks/claude_hooks/__pycache__/auto_pause_handler.cpython-311.pyc +0 -0
  93. claude_mpm/hooks/claude_hooks/__pycache__/event_handlers.cpython-311.pyc +0 -0
  94. claude_mpm/hooks/claude_hooks/__pycache__/hook_handler.cpython-311.pyc +0 -0
  95. claude_mpm/hooks/claude_hooks/__pycache__/response_tracking.cpython-311.pyc +0 -0
  96. claude_mpm/hooks/claude_hooks/auto_pause_handler.py +486 -0
  97. claude_mpm/hooks/claude_hooks/event_handlers.py +216 -11
  98. claude_mpm/hooks/claude_hooks/hook_handler.py +28 -4
  99. claude_mpm/hooks/claude_hooks/response_tracking.py +3 -1
  100. claude_mpm/hooks/claude_hooks/services/__pycache__/connection_manager.cpython-311.pyc +0 -0
  101. claude_mpm/hooks/claude_hooks/services/__pycache__/subagent_processor.cpython-311.pyc +0 -0
  102. claude_mpm/hooks/claude_hooks/services/connection_manager.py +20 -0
  103. claude_mpm/hooks/claude_hooks/services/subagent_processor.py +30 -6
  104. claude_mpm/hooks/session_resume_hook.py +85 -1
  105. claude_mpm/init.py +1 -1
  106. claude_mpm/services/agents/cache_git_manager.py +1 -1
  107. claude_mpm/services/agents/deployment/deployment_reconciler.py +577 -0
  108. claude_mpm/services/agents/deployment/remote_agent_discovery_service.py +3 -0
  109. claude_mpm/services/agents/deployment/startup_reconciliation.py +138 -0
  110. claude_mpm/services/agents/startup_sync.py +5 -2
  111. claude_mpm/services/cli/__init__.py +3 -0
  112. claude_mpm/services/cli/incremental_pause_manager.py +561 -0
  113. claude_mpm/services/cli/session_resume_helper.py +10 -2
  114. claude_mpm/services/delegation_detector.py +175 -0
  115. claude_mpm/services/diagnostics/checks/agent_sources_check.py +30 -0
  116. claude_mpm/services/diagnostics/checks/configuration_check.py +24 -0
  117. claude_mpm/services/diagnostics/checks/installation_check.py +22 -0
  118. claude_mpm/services/diagnostics/checks/mcp_services_check.py +23 -0
  119. claude_mpm/services/diagnostics/doctor_reporter.py +31 -1
  120. claude_mpm/services/diagnostics/models.py +14 -1
  121. claude_mpm/services/event_log.py +317 -0
  122. claude_mpm/services/infrastructure/__init__.py +4 -0
  123. claude_mpm/services/infrastructure/context_usage_tracker.py +291 -0
  124. claude_mpm/services/infrastructure/resume_log_generator.py +24 -5
  125. claude_mpm/services/monitor/daemon_manager.py +15 -4
  126. claude_mpm/services/monitor/management/lifecycle.py +8 -2
  127. claude_mpm/services/monitor/server.py +106 -16
  128. claude_mpm/services/pm_skills_deployer.py +177 -83
  129. claude_mpm/services/skills/git_skill_source_manager.py +5 -1
  130. claude_mpm/services/skills/selective_skill_deployer.py +114 -26
  131. claude_mpm/services/socketio/handlers/hook.py +14 -7
  132. claude_mpm/services/socketio/server/main.py +12 -4
  133. claude_mpm/skills/bundled/pm/mpm-agent-update-workflow/SKILL.md +75 -0
  134. claude_mpm/skills/bundled/pm/mpm-bug-reporting/SKILL.md +248 -0
  135. claude_mpm/skills/bundled/pm/mpm-circuit-breaker-enforcement/SKILL.md +476 -0
  136. claude_mpm/skills/bundled/pm/mpm-session-management/SKILL.md +312 -0
  137. claude_mpm/skills/bundled/pm/mpm-teaching-mode/SKILL.md +657 -0
  138. claude_mpm/skills/bundled/pm/mpm-tool-usage-guide/SKILL.md +386 -0
  139. claude_mpm/skills/skill_manager.py +4 -4
  140. claude_mpm/utils/agent_dependency_loader.py +103 -4
  141. claude_mpm/utils/robust_installer.py +45 -24
  142. claude_mpm-5.4.96.dist-info/METADATA +377 -0
  143. {claude_mpm-5.4.64.dist-info → claude_mpm-5.4.96.dist-info}/RECORD +153 -131
  144. claude_mpm/dashboard/static/svelte-build/_app/immutable/assets/0.DWzvg0-y.css +0 -1
  145. claude_mpm/dashboard/static/svelte-build/_app/immutable/assets/2.ThTw9_ym.css +0 -1
  146. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/4TdZjIqw.js +0 -1
  147. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/5shd3_w0.js +0 -24
  148. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BKjSRqUr.js +0 -1
  149. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Da0KfYnO.js +0 -1
  150. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Dfy6j1xT.js +0 -323
  151. claude_mpm/dashboard/static/svelte-build/_app/immutable/entry/start.NWzMBYRp.js +0 -1
  152. claude_mpm/dashboard/static/svelte-build/_app/immutable/nodes/2.C0GcWctS.js +0 -1
  153. claude_mpm-5.4.64.dist-info/METADATA +0 -999
  154. /claude_mpm/skills/bundled/pm/{pm-delegation-patterns → mpm-delegation-patterns}/SKILL.md +0 -0
  155. /claude_mpm/skills/bundled/pm/{pm-git-file-tracking → mpm-git-file-tracking}/SKILL.md +0 -0
  156. /claude_mpm/skills/bundled/pm/{pm-pr-workflow → mpm-pr-workflow}/SKILL.md +0 -0
  157. /claude_mpm/skills/bundled/pm/{pm-ticketing-integration → mpm-ticketing-integration}/SKILL.md +0 -0
  158. /claude_mpm/skills/bundled/pm/{pm-verification-protocols → mpm-verification-protocols}/SKILL.md +0 -0
  159. {claude_mpm-5.4.64.dist-info → claude_mpm-5.4.96.dist-info}/WHEEL +0 -0
  160. {claude_mpm-5.4.64.dist-info → claude_mpm-5.4.96.dist-info}/entry_points.txt +0 -0
  161. {claude_mpm-5.4.64.dist-info → claude_mpm-5.4.96.dist-info}/licenses/LICENSE +0 -0
  162. {claude_mpm-5.4.64.dist-info → claude_mpm-5.4.96.dist-info}/licenses/LICENSE-FAQ.md +0 -0
  163. {claude_mpm-5.4.64.dist-info → claude_mpm-5.4.96.dist-info}/top_level.txt +0 -0
@@ -44,7 +44,6 @@ from typing import Any, Dict, List, Set, Tuple
44
44
  import yaml
45
45
 
46
46
  from claude_mpm.core.logging_config import get_logger
47
- from claude_mpm.services.skills.skill_to_agent_mapper import SkillToAgentMapper
48
47
 
49
48
  logger = get_logger(__name__)
50
49
 
@@ -60,26 +59,20 @@ CORE_SKILLS = {
60
59
  "universal-debugging-verification-before-completion",
61
60
  "universal-verification-pre-merge",
62
61
  "universal-verification-screenshot",
63
-
64
62
  # Universal testing patterns (2 skills)
65
63
  "universal-testing-test-driven-development",
66
64
  "universal-testing-testing-anti-patterns",
67
-
68
65
  # Universal architecture and design (1 skill)
69
66
  "universal-architecture-software-patterns",
70
-
71
67
  # Universal infrastructure (3 skills)
72
68
  "universal-infrastructure-env-manager",
73
69
  "universal-infrastructure-docker",
74
70
  "universal-infrastructure-github-actions",
75
-
76
71
  # Universal collaboration (1 skill)
77
72
  "universal-collaboration-stacked-prs",
78
-
79
73
  # Universal emergency/operations (1 skill)
80
74
  "toolchains-universal-emergency-release",
81
75
  "toolchains-universal-dependency-audit",
82
-
83
76
  # Common language toolchains (6 skills)
84
77
  "toolchains-typescript-core",
85
78
  "toolchains-python-core",
@@ -87,17 +80,14 @@ CORE_SKILLS = {
87
80
  "toolchains-python-tooling-mypy",
88
81
  "toolchains-typescript-testing-vitest",
89
82
  "toolchains-python-frameworks-flask",
90
-
91
83
  # Common web frameworks (4 skills)
92
84
  "toolchains-javascript-frameworks-nextjs",
93
85
  "toolchains-nextjs-core",
94
86
  "toolchains-typescript-frameworks-nodejs-backend",
95
87
  "toolchains-javascript-frameworks-react-state-machine",
96
-
97
88
  # Common testing tools (2 skills)
98
89
  "toolchains-javascript-testing-playwright",
99
90
  "toolchains-typescript-testing-jest",
100
-
101
91
  # Common data/UI tools (3 skills)
102
92
  "universal-data-xlsx",
103
93
  "toolchains-ui-styling-tailwind",
@@ -224,18 +214,90 @@ def get_skills_from_mapping(agent_ids: List[str]) -> Set[str]:
224
214
  return set()
225
215
 
226
216
 
217
+ def extract_skills_from_content(agent_file: Path) -> Set[str]:
218
+ """Extract skill names from [SKILL: skill-name] markers in agent file content.
219
+
220
+ This function complements frontmatter skill extraction by finding inline
221
+ skill references in the agent's markdown content body.
222
+
223
+ Supports multiple formats:
224
+ - Bold marker: **[SKILL: skill-name]**
225
+ - Plain marker: [SKILL: skill-name]
226
+ - Backtick list: - `skill-name` - Description
227
+ - With spaces: [SKILL: skill-name ]
228
+
229
+ Args:
230
+ agent_file: Path to agent markdown file
231
+
232
+ Returns:
233
+ Set of skill names found in content body
234
+
235
+ Example:
236
+ >>> skills = extract_skills_from_content(Path("pm.md"))
237
+ >>> # Finds skills from markers like **[SKILL: mpm-delegation-patterns]**
238
+ >>> # Also finds from lists like - `mpm-teaching-mode` - Description
239
+ >>> print(f"Found {len(skills)} skills in content")
240
+ """
241
+ try:
242
+ content = agent_file.read_text(encoding="utf-8")
243
+ except Exception as e:
244
+ logger.warning(f"Failed to read {agent_file}: {e}")
245
+ return set()
246
+
247
+ skills = set()
248
+
249
+ # Pattern 1: [SKILL: skill-name] markers (with optional markdown bold)
250
+ # Handles: **[SKILL: skill-name]** or [SKILL: skill-name]
251
+ # Pattern breakdown:
252
+ # - \*{0,2}: Optional bold markdown (0-2 asterisks)
253
+ # - \[SKILL:\s*: Opening bracket with optional whitespace
254
+ # - ([a-zA-Z0-9_-]+): Skill name (capture group)
255
+ # - \s*\]: Closing bracket with optional whitespace
256
+ # - \*{0,2}: Optional closing bold markdown
257
+ pattern1 = r"\*{0,2}\[SKILL:\s*([a-zA-Z0-9_-]+)\s*\]\*{0,2}"
258
+ matches1 = re.findall(pattern1, content, re.IGNORECASE)
259
+ skills.update(matches1)
260
+
261
+ # Pattern 2: Backtick list items with mpm-* or toolchains-* skills
262
+ # Handles: - `mpm-skill-name` - Description
263
+ # Pattern breakdown:
264
+ # - ^-\s+: Start with dash and whitespace (list item)
265
+ # - `: Opening backtick
266
+ # - ((?:mpm-|toolchains-|universal-)[a-zA-Z0-9_-]+): Skill name starting with prefix
267
+ # - `: Closing backtick
268
+ # - \s+-: Followed by whitespace and dash (description separator)
269
+ pattern2 = r"^-\s+`((?:mpm-|toolchains-|universal-)[a-zA-Z0-9_-]+)`\s+-"
270
+ matches2 = re.findall(pattern2, content, re.MULTILINE | re.IGNORECASE)
271
+ skills.update(matches2)
272
+
273
+ if skills:
274
+ logger.debug(
275
+ f"Found {len(skills)} skills from content markers in {agent_file.name}"
276
+ )
277
+
278
+ return skills
279
+
280
+
227
281
  def get_required_skills_from_agents(agents_dir: Path) -> Set[str]:
228
282
  """Extract all skills referenced by deployed agents.
229
283
 
230
- MAJOR CHANGE (Phase 3): Now ONLY uses frontmatter-declared skills.
284
+ MAJOR CHANGE (Phase 3): Now uses TWO sources for skill discovery:
285
+ 1. Frontmatter-declared skills (skills: field)
286
+ 2. Content body markers ([SKILL: skill-name])
287
+
231
288
  The static skill_to_agent_mapping.yaml is DEPRECATED. Each agent must
232
- declare its skills in frontmatter or it gets zero skills deployed.
289
+ declare its skills via frontmatter OR inline markers.
233
290
 
234
291
  This change:
235
292
  - Eliminates dual-source complexity (frontmatter + mapping)
236
293
  - Makes skill requirements explicit per agent
237
- - Enables per-agent customization via frontmatter
294
+ - Enables per-agent customization via frontmatter or inline markers
238
295
  - Removes dependency on static YAML mapping
296
+ - Fixes PM skills being removed as orphaned (they use inline markers)
297
+
298
+ Special handling for PM_INSTRUCTIONS.md:
299
+ - Also scans .claude-mpm/PM_INSTRUCTIONS.md for skill markers
300
+ - PM instructions are not in agents_dir but contain [SKILL: ...] references
239
301
 
240
302
  Args:
241
303
  agents_dir: Path to deployed agents directory (e.g., .claude/agents/)
@@ -254,37 +316,63 @@ def get_required_skills_from_agents(agents_dir: Path) -> Set[str]:
254
316
 
255
317
  # Scan all agent markdown files
256
318
  agent_files = list(agents_dir.glob("*.md"))
257
- logger.debug(f"Scanning {len(agent_files)} agent files in {agents_dir}")
258
319
 
259
- # ONLY use frontmatter skills - no more mapping inference
320
+ # Special case: Add PM_INSTRUCTIONS.md if it exists
321
+ # PM instructions live in .claude-mpm/ not .claude/agents/
322
+ pm_instructions = agents_dir.parent.parent / ".claude-mpm" / "PM_INSTRUCTIONS.md"
323
+ if pm_instructions.exists():
324
+ agent_files.append(pm_instructions)
325
+ logger.debug("Added PM_INSTRUCTIONS.md for skill scanning")
326
+
327
+ logger.debug(f"Scanning {len(agent_files)} agent files (including PM instructions)")
328
+
329
+ # Use TWO sources: frontmatter AND content markers
260
330
  frontmatter_skills = set()
331
+ content_skills = set()
261
332
 
262
333
  for agent_file in agent_files:
263
334
  agent_id = agent_file.stem
264
335
 
336
+ # Source 1: Extract from frontmatter
265
337
  frontmatter = parse_agent_frontmatter(agent_file)
266
- agent_skills = get_skills_from_agent(frontmatter)
338
+ agent_fm_skills = get_skills_from_agent(frontmatter)
267
339
 
268
- if agent_skills:
269
- frontmatter_skills.update(agent_skills)
340
+ if agent_fm_skills:
341
+ frontmatter_skills.update(agent_fm_skills)
270
342
  logger.debug(
271
- f"Agent {agent_id}: {len(agent_skills)} skills from frontmatter"
343
+ f"Agent {agent_id}: {len(agent_fm_skills)} skills from frontmatter"
272
344
  )
273
- else:
274
- logger.debug(f"Agent {agent_id}: No skills declared in frontmatter")
345
+
346
+ # Source 2: Extract from content body [SKILL: ...] markers
347
+ agent_content_skills = extract_skills_from_content(agent_file)
348
+
349
+ if agent_content_skills:
350
+ content_skills.update(agent_content_skills)
351
+ logger.debug(
352
+ f"Agent {agent_id}: {len(agent_content_skills)} skills from content markers"
353
+ )
354
+
355
+ if not agent_fm_skills and not agent_content_skills:
356
+ logger.debug(
357
+ f"Agent {agent_id}: No skills declared (checked frontmatter + content)"
358
+ )
359
+
360
+ # Combine both sources
361
+ all_skills = frontmatter_skills | content_skills
275
362
 
276
363
  logger.info(
277
- f"Found {len(frontmatter_skills)} unique skills from agent frontmatter "
278
- f"(static mapping no longer used)"
364
+ f"Found {len(all_skills)} unique skills "
365
+ f"({len(frontmatter_skills)} from frontmatter, "
366
+ f"{len(content_skills)} from content markers)"
279
367
  )
280
368
 
281
369
  # Normalize skill paths: convert slashes to dashes for compatibility with deployment
282
370
  # Some skills may use slash format, normalize to dashes
283
- normalized_skills = {skill.replace("/", "-") for skill in frontmatter_skills}
371
+ normalized_skills = {skill.replace("/", "-") for skill in all_skills}
284
372
 
285
- if normalized_skills != frontmatter_skills:
373
+ if normalized_skills != all_skills:
286
374
  logger.debug(
287
- f"Normalized {len(frontmatter_skills)} skills to {len(normalized_skills)} "
375
+ f"Normalized {len(all_skills)} skills to {len(normalized_skills)} "
288
376
  "(converted slashes to dashes)"
289
377
  )
290
378
 
@@ -118,7 +118,8 @@ class HookEventHandler(BaseEventHandler):
118
118
  self.server.active_sessions[session_id] = {
119
119
  "session_id": session_id,
120
120
  "start_time": datetime.now(timezone.utc).isoformat(),
121
- "agent": agent_type,
121
+ "current_agent": agent_type, # Current active agent
122
+ "agents": [agent_type], # All agents used in this session
122
123
  "status": ServiceState.RUNNING,
123
124
  "prompt": data.get("prompt", "")[:100], # First 100 chars
124
125
  "last_activity": datetime.now(timezone.utc).isoformat(),
@@ -169,7 +170,8 @@ class HookEventHandler(BaseEventHandler):
169
170
  self.server.active_sessions[session_id] = {
170
171
  "session_id": session_id,
171
172
  "start_time": datetime.now(timezone.utc).isoformat(),
172
- "agent": "pm", # Default to PM
173
+ "current_agent": "pm", # Current active agent
174
+ "agents": ["pm"], # All agents used in this session
173
175
  "status": ServiceState.RUNNING,
174
176
  "prompt": data.get("prompt_text", "")[:100],
175
177
  "working_directory": data.get("working_directory", ""),
@@ -200,11 +202,16 @@ class HookEventHandler(BaseEventHandler):
200
202
  # Update session with new agent
201
203
  if hasattr(self.server, "active_sessions"):
202
204
  if session_id in self.server.active_sessions:
203
- self.server.active_sessions[session_id]["agent"] = agent_type
204
- self.server.active_sessions[session_id]["status"] = "delegated"
205
- self.server.active_sessions[session_id]["last_activity"] = datetime.now(
206
- timezone.utc
207
- ).isoformat()
205
+ session = self.server.active_sessions[session_id]
206
+ session["current_agent"] = agent_type
207
+ session["status"] = "delegated"
208
+ session["last_activity"] = datetime.now(timezone.utc).isoformat()
209
+
210
+ # Add to agents list if not already present
211
+ if "agents" not in session:
212
+ session["agents"] = []
213
+ if agent_type not in session["agents"]:
214
+ session["agents"].append(agent_type)
208
215
 
209
216
  self.logger.debug(
210
217
  f"Updated session delegation: session={session_id[:8]}..., agent={agent_type}"
@@ -383,7 +383,8 @@ class SocketIOServer(SocketIOServiceInterface):
383
383
  self.active_sessions[session_id] = {
384
384
  "session_id": session_id,
385
385
  "start_time": datetime.now(timezone.utc).isoformat(),
386
- "agent": "pm", # Default to PM, will be updated if delegated
386
+ "current_agent": "pm", # Current active agent
387
+ "agents": ["pm"], # All agents used in this session
387
388
  "status": ServiceState.RUNNING,
388
389
  "launch_method": launch_method,
389
390
  "working_dir": working_dir,
@@ -419,8 +420,15 @@ class SocketIOServer(SocketIOServiceInterface):
419
420
  """Notify agent delegation."""
420
421
  # Update active session with current agent
421
422
  if self.session_id and self.session_id in self.active_sessions:
422
- self.active_sessions[self.session_id]["agent"] = agent
423
- self.active_sessions[self.session_id]["status"] = status
423
+ session = self.active_sessions[self.session_id]
424
+ session["current_agent"] = agent
425
+ session["status"] = status
426
+
427
+ # Add to agents list if not already present
428
+ if "agents" not in session:
429
+ session["agents"] = []
430
+ if agent not in session["agents"]:
431
+ session["agents"].append(agent)
424
432
 
425
433
  if self.broadcaster:
426
434
  self.broadcaster.agent_delegated(agent, task, status)
@@ -480,7 +488,7 @@ class SocketIOServer(SocketIOServiceInterface):
480
488
  start_time = datetime.fromisoformat(session_data["start_time"])
481
489
  if start_time.timestamp() < cutoff_time:
482
490
  sessions_to_remove.append(session_id)
483
- except Exception:
491
+ except Exception: # nosec B110 - Silently skip malformed timestamps
484
492
  pass
485
493
 
486
494
  for session_id in sessions_to_remove:
@@ -0,0 +1,75 @@
1
+ # PM Skill: Agent Update Workflow
2
+
3
+ ## Trigger Patterns
4
+ - "update agent", "fix agent", "improve agent", "modify agent"
5
+ - "change {agent-name} agent", "edit agent instructions"
6
+ - Any request to modify agent behavior
7
+
8
+ ## FUNDAMENTAL RULE: Official vs Custom Agents
9
+
10
+ ### Official MPM Agents (NEVER edit deployed copies)
11
+ **Source**: `~/.claude-mpm/cache/agents/` (from bobmatnyc/claude-mpm-agents repo)
12
+ **Deployed**: `.claude/agents/` - READ-ONLY for official agents
13
+
14
+ **Detection**: Check if agent exists in `~/.claude-mpm/cache/agents/`
15
+ - If YES → Official agent → Follow Official Agent Workflow
16
+ - If NO → Custom agent → Can edit `.claude/agents/` directly
17
+
18
+ ### Custom/Localized Agents
19
+ - Created specifically for project
20
+ - Can be edited directly in `.claude/agents/`
21
+ - Not part of official MPM agent set
22
+
23
+ ## Official Agent Update Workflow
24
+
25
+ ### Step 1: Identify Agent Source
26
+ ```bash
27
+ ls ~/.claude-mpm/cache/agents/ # Find the source file
28
+ ```
29
+
30
+ ### Step 2: Update Source
31
+ Edit the agent source in `~/.claude-mpm/cache/agents/{agent-name}.md`
32
+ (or appropriate path based on agent structure)
33
+
34
+ ### Step 3: Rebuild and Redeploy
35
+ Use MPM deployment tools:
36
+ ```bash
37
+ # Redeploy specific agent
38
+ mpm agents deploy {agent-name}
39
+
40
+ # Or redeploy all agents
41
+ mpm agents deploy --all
42
+ ```
43
+
44
+ ### Step 4: Validate (claude-mpm project only)
45
+ When working in the claude-mpm project itself:
46
+ ```bash
47
+ # Run deepeval against deployed agent instructions
48
+ deepeval test --agent {agent-name}
49
+ ```
50
+
51
+ ## Circuit Breaker
52
+
53
+ **BLOCK** if attempting to edit `.claude/agents/{official-agent}.md` directly:
54
+ - Official agents in deployed location are BUILD OUTPUTS
55
+ - Must update source → rebuild → redeploy
56
+ - Violation = architectural breach
57
+
58
+ ## Examples
59
+
60
+ ### ❌ WRONG (Editing deployed official agent)
61
+ ```
62
+ Edit: .claude/agents/web-qa.md # VIOLATION - this is a built output
63
+ ```
64
+
65
+ ### ✅ CORRECT (Updating source and redeploying)
66
+ ```
67
+ 1. Edit: ~/.claude-mpm/cache/agents/web-qa.md # Update source
68
+ 2. Run: mpm agents deploy web-qa # Rebuild/redeploy
69
+ 3. Validate: deepeval test --agent web-qa # (in claude-mpm project)
70
+ ```
71
+
72
+ ### ✅ CORRECT (Custom agent - can edit directly)
73
+ ```
74
+ Edit: .claude/agents/my-custom-agent.md # OK - not an official agent
75
+ ```
@@ -0,0 +1,248 @@
1
+ ---
2
+ name: pm-bug-reporting
3
+ version: "1.0.0"
4
+ description: Bug reporting protocol for PM and agents to file GitHub issues
5
+ when_to_use: Framework bugs, agent errors, skill content errors detected
6
+ category: pm-workflow
7
+ tags: [bug-reporting, github, issues, pm-required]
8
+ ---
9
+
10
+ # PM Bug Reporting Protocol
11
+
12
+ ## When to Report Bugs
13
+
14
+ Report bugs when you encounter:
15
+ - **PM instruction errors** or missing guidance
16
+ - **Agent malfunction** or incorrect behavior
17
+ - **Skill content errors** or outdated information
18
+ - **Framework crashes** or unexpected behavior
19
+ - **Missing or incorrect documentation**
20
+ - **Configuration errors** or invalid defaults
21
+
22
+ ## GitHub Repositories
23
+
24
+ Route bugs to the correct repository:
25
+
26
+ | Bug Type | Repository | Owner/Repo |
27
+ |----------|------------|------------|
28
+ | Core MPM (CLI, startup, config, orchestration) | claude-mpm | bobmatnyc/claude-mpm |
29
+ | Agent bugs (wrong behavior, errors, missing capabilities) | claude-mpm-agents | bobmatnyc/claude-mpm-agents |
30
+ | Skill bugs (wrong info, outdated, missing content) | claude-mpm-skills | bobmatnyc/claude-mpm-skills |
31
+
32
+ ## Bug Report Template
33
+
34
+ When creating an issue, include:
35
+
36
+ ### Title
37
+ Brief, descriptive title (50 chars max)
38
+ - ✅ "PM delegates to non-existent agent"
39
+ - ✅ "Research skill missing web search examples"
40
+ - ❌ "Bug in system"
41
+ - ❌ "Fix this"
42
+
43
+ ### Labels
44
+ Always include:
45
+ - `bug` (required)
46
+ - `agent-reported` (required)
47
+ - Additional context labels:
48
+ - `high-priority` - Critical functionality broken
49
+ - `documentation` - Documentation error
50
+ - `agent-error` - Agent-specific issue
51
+ - `skill-error` - Skill content issue
52
+
53
+ ### Body Structure
54
+ ```markdown
55
+ ## What Happened
56
+ [Clear description of the bug]
57
+
58
+ ## Expected Behavior
59
+ [What should have happened]
60
+
61
+ ## Steps to Reproduce
62
+ 1. [First step]
63
+ 2. [Second step]
64
+ 3. [Third step]
65
+
66
+ ## Context
67
+ - Agent: [agent name if applicable]
68
+ - Skill: [skill name if applicable]
69
+ - Error Message: [full error if available]
70
+ - Version: [MPM version if known]
71
+
72
+ ## Impact
73
+ [How this affects users/workflow]
74
+ ```
75
+
76
+ ## Using gh CLI
77
+
78
+ ### Prerequisites Check
79
+ ```bash
80
+ gh auth status
81
+ ```
82
+
83
+ If not authenticated:
84
+ ```bash
85
+ gh auth login
86
+ ```
87
+
88
+ ### Creating Issues
89
+
90
+ **Delegate to ticketing agent** with:
91
+ ```
92
+ Task:
93
+ agent: ticketing
94
+ task: Create GitHub issue for [bug type]
95
+ context: |
96
+ Repository: bobmatnyc/claude-mpm[-agents|-skills]
97
+ Title: [brief title]
98
+ Labels: bug, agent-reported
99
+ Body: |
100
+ ## What Happened
101
+ [description]
102
+
103
+ ## Expected Behavior
104
+ [expected]
105
+
106
+ ## Steps to Reproduce
107
+ 1. [step 1]
108
+ 2. [step 2]
109
+
110
+ ## Context
111
+ - Agent: [agent name]
112
+ - Error: [error message]
113
+
114
+ ## Impact
115
+ [impact description]
116
+ ```
117
+
118
+ ## Examples
119
+
120
+ ### Core MPM Bug
121
+ ```
122
+ Task:
123
+ agent: ticketing
124
+ task: Create GitHub issue for core MPM bug
125
+ context: |
126
+ Repository: bobmatnyc/claude-mpm
127
+ Title: PM fails to load configuration on startup
128
+ Labels: bug, agent-reported, high-priority
129
+ Body: |
130
+ ## What Happened
131
+ PM fails to initialize when configuration.yaml contains invalid syntax.
132
+ No clear error message shown to user.
133
+
134
+ ## Expected Behavior
135
+ PM should display clear YAML syntax error with line number and fix suggestion.
136
+
137
+ ## Steps to Reproduce
138
+ 1. Add invalid YAML to .claude-mpm/configuration.yaml
139
+ 2. Run `mpm`
140
+ 3. Observe generic error without details
141
+
142
+ ## Context
143
+ - Component: Configuration loader
144
+ - Error: "Failed to load configuration"
145
+ - Version: 5.4.x
146
+
147
+ ## Impact
148
+ Users cannot diagnose configuration errors, requiring manual YAML validation.
149
+ ```
150
+
151
+ ### Agent Bug
152
+ ```
153
+ Task:
154
+ agent: ticketing
155
+ task: Create GitHub issue for agent bug
156
+ context: |
157
+ Repository: bobmatnyc/claude-mpm-agents
158
+ Title: Research agent fails to search with special characters
159
+ Labels: bug, agent-reported, agent-error
160
+ Body: |
161
+ ## What Happened
162
+ Research agent throws error when search query contains quotes or special chars.
163
+
164
+ ## Expected Behavior
165
+ Search queries should be properly escaped and executed.
166
+
167
+ ## Steps to Reproduce
168
+ 1. Delegate to research: "Search for 'React hooks'"
169
+ 2. Research agent attempts search
170
+ 3. Error: "Invalid search query"
171
+
172
+ ## Context
173
+ - Agent: research
174
+ - Error: grep command fails with unescaped quotes
175
+
176
+ ## Impact
177
+ Cannot search for quoted phrases or technical terms with special characters.
178
+ ```
179
+
180
+ ### Skill Bug
181
+ ```
182
+ Task:
183
+ agent: ticketing
184
+ task: Create GitHub issue for skill content error
185
+ context: |
186
+ Repository: bobmatnyc/claude-mpm-skills
187
+ Title: Git workflow skill contains outdated branch strategy
188
+ Labels: bug, agent-reported, documentation, skill-error
189
+ Body: |
190
+ ## What Happened
191
+ Skill recommends `git flow` branching model, which project no longer uses.
192
+ Current standard is trunk-based development.
193
+
194
+ ## Expected Behavior
195
+ Skill should document current trunk-based workflow.
196
+
197
+ ## Context
198
+ - Skill: git-workflow.md
199
+ - Section: "Branching Strategy"
200
+ - Line: 45-60
201
+
202
+ ## Impact
203
+ Agents follow outdated branching model, creating workflow friction.
204
+ ```
205
+
206
+ ## Escalation Path
207
+
208
+ When ticketing agent is unavailable or gh CLI fails:
209
+
210
+ 1. **Log locally** for manual reporting:
211
+ ```
212
+ echo "[BUG] $(date): [description]" >> .claude-mpm/logs/bugs.log
213
+ ```
214
+
215
+ 2. **Report to PM** for alternative action:
216
+ ```
217
+ PM should create ticket in primary ticketing system (Linear/JIRA)
218
+ with note to create GitHub issue once available
219
+ ```
220
+
221
+ 3. **User notification**:
222
+ ```
223
+ "Bug detected: [description]. Logged for manual GitHub issue creation."
224
+ ```
225
+
226
+ ## Success Criteria
227
+
228
+ Bug reporting successful when:
229
+ - ✅ Issue created in correct repository
230
+ - ✅ All required labels applied (`bug`, `agent-reported`)
231
+ - ✅ Body follows template structure
232
+ - ✅ Title is clear and concise
233
+ - ✅ Context includes agent/skill name if applicable
234
+ - ✅ Issue URL returned for tracking
235
+
236
+ ## PM Enforcement
237
+
238
+ PM MUST:
239
+ - Detect bugs during agent interactions
240
+ - Delegate bug reporting to ticketing agent
241
+ - NOT attempt to create GitHub issues directly
242
+ - Follow escalation path if ticketing unavailable
243
+ - Log all bug reports for audit trail
244
+
245
+ ## Related Skills
246
+ - [pm-ticketing-integration.md](pm-ticketing-integration.md) - Ticket delegation patterns
247
+ - [pm-delegation-patterns.md](pm-delegation-patterns.md) - General delegation guidance
248
+ - [ticketing-examples.md](ticketing-examples.md) - Ticketing delegation examples