mapify-cli 1.2.0__tar.gz → 1.2.2__tar.gz

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.
Files changed (47) hide show
  1. {mapify_cli-1.2.0 → mapify_cli-1.2.2}/.gitignore +2 -0
  2. {mapify_cli-1.2.0 → mapify_cli-1.2.2}/PKG-INFO +1 -1
  3. {mapify_cli-1.2.0 → mapify_cli-1.2.2}/pyproject.toml +1 -1
  4. {mapify_cli-1.2.0 → mapify_cli-1.2.2}/src/mapify_cli/__init__.py +110 -90
  5. mapify_cli-1.2.2/src/mapify_cli/contradiction_detector.py +723 -0
  6. mapify_cli-1.2.2/src/mapify_cli/entity_extractor.py +723 -0
  7. mapify_cli-1.2.2/src/mapify_cli/graph_query.py +731 -0
  8. {mapify_cli-1.2.0 → mapify_cli-1.2.2}/src/mapify_cli/playbook_manager.py +141 -21
  9. {mapify_cli-1.2.0 → mapify_cli-1.2.2}/src/mapify_cli/recitation_manager.py +86 -42
  10. mapify_cli-1.2.2/src/mapify_cli/relationship_detector.py +633 -0
  11. mapify_cli-1.2.2/src/mapify_cli/schemas.py +197 -0
  12. {mapify_cli-1.2.0 → mapify_cli-1.2.2}/src/mapify_cli/templates/agents/CHANGELOG.md +2 -2
  13. {mapify_cli-1.2.0 → mapify_cli-1.2.2}/src/mapify_cli/templates/agents/curator.md +121 -0
  14. {mapify_cli-1.2.0 → mapify_cli-1.2.2}/src/mapify_cli/templates/agents/reflector.md +109 -0
  15. mapify_cli-1.2.2/src/mapify_cli/templates/hooks/helpers/validate_checkpoint_file.py +349 -0
  16. mapify_cli-1.2.0/src/mapify_cli/templates/agents/test-generator.md +0 -1175
  17. {mapify_cli-1.2.0 → mapify_cli-1.2.2}/.claude/agents/README.md +0 -0
  18. {mapify_cli-1.2.0 → mapify_cli-1.2.2}/.claude/hooks/README.md +0 -0
  19. {mapify_cli-1.2.0 → mapify_cli-1.2.2}/README.md +0 -0
  20. {mapify_cli-1.2.0 → mapify_cli-1.2.2}/docs/context-engineering/README.md +0 -0
  21. {mapify_cli-1.2.0 → mapify_cli-1.2.2}/src/mapify_cli/playbook_query.py +0 -0
  22. {mapify_cli-1.2.0 → mapify_cli-1.2.2}/src/mapify_cli/semantic_search.py +0 -0
  23. {mapify_cli-1.2.0 → mapify_cli-1.2.2}/src/mapify_cli/templates/agents/MCP-PATTERNS.md +0 -0
  24. {mapify_cli-1.2.0 → mapify_cli-1.2.2}/src/mapify_cli/templates/agents/README.md +0 -0
  25. {mapify_cli-1.2.0 → mapify_cli-1.2.2}/src/mapify_cli/templates/agents/actor.md +0 -0
  26. {mapify_cli-1.2.0 → mapify_cli-1.2.2}/src/mapify_cli/templates/agents/documentation-reviewer.md +0 -0
  27. {mapify_cli-1.2.0 → mapify_cli-1.2.2}/src/mapify_cli/templates/agents/evaluator.md +0 -0
  28. {mapify_cli-1.2.0 → mapify_cli-1.2.2}/src/mapify_cli/templates/agents/monitor.md +0 -0
  29. {mapify_cli-1.2.0 → mapify_cli-1.2.2}/src/mapify_cli/templates/agents/predictor.md +0 -0
  30. {mapify_cli-1.2.0 → mapify_cli-1.2.2}/src/mapify_cli/templates/agents/task-decomposer.md +0 -0
  31. {mapify_cli-1.2.0 → mapify_cli-1.2.2}/src/mapify_cli/templates/commands/map-debug.md +0 -0
  32. {mapify_cli-1.2.0 → mapify_cli-1.2.2}/src/mapify_cli/templates/commands/map-efficient.md +0 -0
  33. {mapify_cli-1.2.0 → mapify_cli-1.2.2}/src/mapify_cli/templates/commands/map-fast.md +0 -0
  34. {mapify_cli-1.2.0 → mapify_cli-1.2.2}/src/mapify_cli/templates/commands/map-feature.md +0 -0
  35. {mapify_cli-1.2.0 → mapify_cli-1.2.2}/src/mapify_cli/templates/commands/map-refactor.md +0 -0
  36. {mapify_cli-1.2.0 → mapify_cli-1.2.2}/src/mapify_cli/templates/commands/map-review.md +0 -0
  37. {mapify_cli-1.2.0 → mapify_cli-1.2.2}/src/mapify_cli/templates/hooks/helpers/__init__.py +0 -0
  38. {mapify_cli-1.2.0 → mapify_cli-1.2.2}/src/mapify_cli/templates/hooks/helpers/inject_playbook_bullets.py +0 -0
  39. {mapify_cli-1.2.0 → mapify_cli-1.2.2}/src/mapify_cli/templates/hooks/helpers/quality_gates.py +0 -0
  40. {mapify_cli-1.2.0 → mapify_cli-1.2.2}/src/mapify_cli/templates/hooks/settings.hooks.json +0 -0
  41. {mapify_cli-1.2.0 → mapify_cli-1.2.2}/src/mapify_cli/templates/hooks/stop.sh +0 -0
  42. {mapify_cli-1.2.0 → mapify_cli-1.2.2}/src/mapify_cli/templates/hooks/user-prompt-submit.sh +0 -0
  43. {mapify_cli-1.2.0 → mapify_cli-1.2.2}/src/mapify_cli/templates/hooks/validate-agent-templates.sh +0 -0
  44. {mapify_cli-1.2.0 → mapify_cli-1.2.2}/src/mapify_cli/templates/settings.hooks.json +0 -0
  45. {mapify_cli-1.2.0 → mapify_cli-1.2.2}/src/mapify_cli/tools/__init__.py +0 -0
  46. {mapify_cli-1.2.0 → mapify_cli-1.2.2}/src/mapify_cli/tools/validate_dependencies.py +0 -0
  47. {mapify_cli-1.2.0 → mapify_cli-1.2.2}/src/mapify_cli/workflow_logger.py +0 -0
@@ -62,3 +62,5 @@ mapify_cli_verification_*.json
62
62
 
63
63
  docs/claude-task-master
64
64
  docs/awesome-claude-code
65
+ docs/core
66
+ docs/claude-code-infrastructure-showcase
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mapify-cli
3
- Version: 1.2.0
3
+ Version: 1.2.2
4
4
  Summary: MAP Framework installer - Modular Agentic Planner for Claude Code
5
5
  Project-URL: Homepage, https://github.com/azalio/map-framework
6
6
  Project-URL: Repository, https://github.com/azalio/map-framework.git
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "mapify-cli"
3
- version = "1.2.0"
3
+ version = "1.2.2"
4
4
  description = "MAP Framework installer - Modular Agentic Planner for Claude Code"
5
5
  authors = [{ name = "MAP Framework Contributors" }]
6
6
  readme = "README.md"
@@ -30,6 +30,7 @@ import subprocess
30
30
  import sys
31
31
  import shutil
32
32
  import json
33
+ import sqlite3
33
34
  from pathlib import Path
34
35
  from typing import Optional, List, Dict, Any
35
36
 
@@ -494,7 +495,6 @@ def create_agent_files(project_path: Path, mcp_servers: List[str]) -> None:
494
495
  "evaluator": create_evaluator_content(mcp_servers),
495
496
  "reflector": create_reflector_content(mcp_servers),
496
497
  "curator": create_curator_content(mcp_servers),
497
- "test-generator": create_test_generator_content(mcp_servers),
498
498
  "documentation-reviewer": create_documentation_reviewer_content(mcp_servers)
499
499
  }
500
500
 
@@ -898,62 +898,7 @@ Return JSON with:
898
898
  """
899
899
 
900
900
 
901
- def create_test_generator_content(mcp_servers: List[str]) -> str:
902
- """Create test-generator agent content"""
903
- mcp_section = ""
904
- if any(s in mcp_servers for s in ["cipher", "context7"]):
905
- mcp_section = """
906
- # MCP INTEGRATION
907
-
908
- **Use these tools for test generation:**
909
- """
910
- if "cipher" in mcp_servers:
911
- mcp_section += """
912
- 1. **mcp__cipher__cipher_memory_search** - Find similar test patterns
913
- - Query: "test pattern [feature_type]"
914
- """
915
- if "context7" in mcp_servers:
916
- mcp_section += """
917
- 2. **mcp__context7__get-library-docs** - Verify testing framework usage
918
- - Ensure correct test syntax for language/framework
919
- """
920
-
921
- return f"""---
922
- name: test-generator
923
- description: Generates comprehensive test suites for Actor output
924
- tools: Read, Write, Edit, Bash, Grep, Glob
925
- model: sonnet
926
- ---
927
-
928
- # IDENTITY
929
-
930
- You are a test automation specialist who creates comprehensive, maintainable test suites.
931
- {mcp_section}
932
- # ROLE
933
-
934
- Generate tests for Actor implementations covering:
935
- - Unit tests (individual functions)
936
- - Integration tests (component interactions)
937
- - Edge cases and error handling
938
- - Security-critical paths (100% coverage required)
939
-
940
- ## Test Strategy
941
-
942
- 1. **AAA Pattern**: Arrange, Act, Assert
943
- 2. **Coverage Targets**:
944
- - Critical code: 100%
945
- - High priority: 90%
946
- - Medium priority: 80%
947
- 3. **Edge Cases**: Empty inputs, null values, boundaries
948
-
949
- ## Output Format (JSON)
950
-
951
- Return JSON with:
952
- - approach: Test strategy for this code
953
- - test_files: Array of {{file_path, content, test_type}}
954
- - coverage_analysis: Expected coverage percentage
955
- - testing_notes: Special considerations
956
- """
901
+ # Note: test-generator agent removed
957
902
 
958
903
 
959
904
  def create_documentation_reviewer_content(mcp_servers: List[str]) -> str:
@@ -1171,16 +1116,28 @@ def install_hooks(project_path: Path, with_hooks: bool = True) -> int:
1171
1116
  hooks_count += 1
1172
1117
 
1173
1118
  # Copy helpers directory (Python helper scripts)
1119
+ # IMPORTANT: Only copy/update files from templates, preserve user's custom files
1174
1120
  helpers_src = hooks_template_dir / "helpers"
1175
1121
  if helpers_src.exists() and helpers_src.is_dir():
1176
1122
  helpers_dest = hooks_dir / "helpers"
1177
- if helpers_dest.exists():
1178
- shutil.rmtree(helpers_dest)
1179
- shutil.copytree(helpers_src, helpers_dest)
1180
- # Make Python scripts executable
1181
- for py_file in helpers_dest.glob("*.py"):
1182
- if py_file.name != "__init__.py":
1183
- py_file.chmod(py_file.stat().st_mode | stat.S_IEXEC | stat.S_IXGRP | stat.S_IXOTH)
1123
+ helpers_dest.mkdir(exist_ok=True) # Create dir if doesn't exist
1124
+
1125
+ # Copy each file individually (preserves user files not in templates)
1126
+ for helper_file in helpers_src.rglob("*"):
1127
+ if helper_file.is_file():
1128
+ # Compute relative path from helpers_src
1129
+ rel_path = helper_file.relative_to(helpers_src)
1130
+ dest_file = helpers_dest / rel_path
1131
+
1132
+ # Create parent directory if needed
1133
+ dest_file.parent.mkdir(parents=True, exist_ok=True)
1134
+
1135
+ # Copy template file (overwrites if exists)
1136
+ shutil.copy2(helper_file, dest_file)
1137
+
1138
+ # Make Python scripts executable (except __init__.py)
1139
+ if dest_file.suffix == ".py" and dest_file.name != "__init__.py":
1140
+ dest_file.chmod(dest_file.stat().st_mode | stat.S_IEXEC | stat.S_IXGRP | stat.S_IXOTH)
1184
1141
 
1185
1142
  # Copy README.md
1186
1143
  readme_src = hooks_template_dir / "README.md"
@@ -1290,8 +1247,7 @@ def create_mcp_config(project_path: Path, mcp_servers: List[str]) -> None:
1290
1247
  "orchestrator": [],
1291
1248
  "reflector": [],
1292
1249
  "curator": [],
1293
- "documentation-reviewer": [],
1294
- "test-generator": []
1250
+ "documentation-reviewer": []
1295
1251
  },
1296
1252
  "workflow_settings": {
1297
1253
  "always_retrieve_knowledge": True,
@@ -1381,7 +1337,7 @@ def create_mcp_config(project_path: Path, mcp_servers: List[str]) -> None:
1381
1337
  config["agent_mcp_mappings"][agent].append("claude-reviewer")
1382
1338
 
1383
1339
  if "codex-bridge" in mcp_servers:
1384
- for agent in ["actor", "predictor", "test-generator"]:
1340
+ for agent in ["actor", "predictor"]:
1385
1341
  if agent in config["agent_mcp_mappings"]:
1386
1342
  config["agent_mcp_mappings"][agent].append("codex-bridge")
1387
1343
 
@@ -1707,7 +1663,7 @@ def init(
1707
1663
  tracker.add("create-agents", "Create MAP agents")
1708
1664
  tracker.start("create-agents")
1709
1665
  create_agent_files(project_path, selected_mcp_servers)
1710
- tracker.complete("create-agents", "9 agents")
1666
+ tracker.complete("create-agents", "8 agents")
1711
1667
 
1712
1668
  tracker.add("create-commands", "Create slash commands")
1713
1669
  tracker.start("create-commands")
@@ -1728,6 +1684,36 @@ def init(
1728
1684
  create_mcp_config(project_path, selected_mcp_servers)
1729
1685
  tracker.complete("mcp-config", f"{len(selected_mcp_servers)} servers")
1730
1686
 
1687
+ # Initialize playbook database
1688
+ tracker.add("init-playbook", "Initialize playbook database")
1689
+ tracker.start("init-playbook")
1690
+ try:
1691
+ from mapify_cli.playbook_manager import PlaybookManager
1692
+ playbook_db_path = project_path / ".claude" / "playbook.db"
1693
+ manager = PlaybookManager(db_path=str(playbook_db_path), use_semantic_search=False)
1694
+ manager.close()
1695
+ tracker.complete("init-playbook", "database created")
1696
+ except sqlite3.Error as e:
1697
+ tracker.error("init-playbook", "database error")
1698
+ console.print(f"[red]Error:[/red] Failed to initialize playbook database: {e}")
1699
+ console.print("[yellow]Please check disk space and permissions[/yellow]")
1700
+ raise typer.Exit(1)
1701
+ except PermissionError as e:
1702
+ tracker.error("init-playbook", "permission denied")
1703
+ console.print(f"[red]Error:[/red] Permission denied creating playbook: {e}")
1704
+ console.print("[yellow]Run with appropriate permissions or choose a different directory[/yellow]")
1705
+ raise typer.Exit(1)
1706
+ except OSError as e:
1707
+ tracker.error("init-playbook", "filesystem error")
1708
+ console.print(f"[red]Error:[/red] Could not create playbook directory: {e}")
1709
+ console.print("[yellow]Please check directory permissions[/yellow]")
1710
+ raise typer.Exit(1)
1711
+ except json.JSONDecodeError as e:
1712
+ tracker.error("init-playbook", "invalid JSON")
1713
+ console.print(f"[red]Error:[/red] Corrupted playbook.json file: {e}")
1714
+ console.print("[yellow]Suggestion: Rename or delete .claude/playbook.json and try again[/yellow]")
1715
+ raise typer.Exit(1)
1716
+
1731
1717
  # Initialize git
1732
1718
  if not no_git and git_available:
1733
1719
  tracker.add("git", "Initialize git repository")
@@ -1863,7 +1849,7 @@ def recitation_create(
1863
1849
 
1864
1850
  @recitation_app.command("update")
1865
1851
  def recitation_update(
1866
- subtask_id: int,
1852
+ subtask_id: str,
1867
1853
  status: str,
1868
1854
  error: Optional[str] = typer.Argument(None)
1869
1855
  ):
@@ -2082,13 +2068,22 @@ def playbook_stats():
2082
2068
  """Show playbook statistics"""
2083
2069
  from mapify_cli.playbook_manager import PlaybookManager
2084
2070
 
2085
- playbook_path = Path.cwd() / ".claude" / "playbook.json"
2086
- if not playbook_path.exists():
2087
- console.print_json(data={"error": "Playbook not found"})
2071
+ playbook_db_path = Path.cwd() / ".claude" / "playbook.db"
2072
+ playbook_json_path = Path.cwd() / ".claude" / "playbook.json"
2073
+
2074
+ # Check for playbook.db first (primary storage)
2075
+ if not playbook_db_path.exists():
2076
+ # Backward compatibility: check if old playbook.json exists
2077
+ if playbook_json_path.exists():
2078
+ console.print_json(data={
2079
+ "error": "Found legacy playbook.json. Run 'mapify init' to migrate to playbook.db"
2080
+ })
2081
+ else:
2082
+ console.print_json(data={"error": "Playbook not found. Initialize with 'mapify init'"})
2088
2083
  raise typer.Exit(1)
2089
2084
 
2090
- # Use PlaybookManager to read from SQLite backend
2091
- manager = PlaybookManager(playbook_path)
2085
+ # Use PlaybookManager with db_path (SQLite backend)
2086
+ manager = PlaybookManager(db_path=str(playbook_db_path))
2092
2087
  total = sum(len(section["bullets"]) for section in manager.playbook.get("sections", {}).values())
2093
2088
  stats = {
2094
2089
  "total_bullets": total,
@@ -2101,11 +2096,11 @@ def playbook_stats():
2101
2096
  def playbook_search(query: str, top_k: int = typer.Option(5, help="Number of results")):
2102
2097
  """Search playbook for relevant patterns"""
2103
2098
  from mapify_cli.playbook_manager import PlaybookManager
2104
- playbook_path = Path.cwd() / ".claude" / "playbook.json"
2105
- if not playbook_path.exists():
2099
+ playbook_db_path = Path.cwd() / ".claude" / "playbook.db"
2100
+ if not playbook_db_path.exists():
2106
2101
  console.print("No patterns found (playbook not initialized)")
2107
2102
  return
2108
- manager = PlaybookManager(playbook_path)
2103
+ manager = PlaybookManager(db_path=str(playbook_db_path))
2109
2104
  results = manager.get_relevant_bullets(query, limit=top_k)
2110
2105
  if not results:
2111
2106
  console.print("No patterns found matching your query")
@@ -2116,11 +2111,22 @@ def playbook_search(query: str, top_k: int = typer.Option(5, help="Number of res
2116
2111
  def playbook_sync(threshold: int = typer.Option(5, help="Minimum helpful count")):
2117
2112
  """Show high-quality patterns ready for cross-project sync"""
2118
2113
  from mapify_cli.playbook_manager import PlaybookManager
2119
- playbook_path = Path.cwd() / ".claude" / "playbook.json"
2120
- if not playbook_path.exists():
2121
- console.print_json(data={"status": "error", "message": "Playbook not found"})
2114
+ playbook_db_path = Path.cwd() / ".claude" / "playbook.db"
2115
+ playbook_json_path = Path.cwd() / ".claude" / "playbook.json"
2116
+
2117
+ # Check for playbook.db first (primary storage)
2118
+ if not playbook_db_path.exists():
2119
+ # Backward compatibility: check if old playbook.json exists
2120
+ if playbook_json_path.exists():
2121
+ console.print_json(data={
2122
+ "status": "error",
2123
+ "message": "Found legacy playbook.json. Run 'mapify init' to migrate to playbook.db"
2124
+ })
2125
+ else:
2126
+ console.print_json(data={"status": "error", "message": "Playbook not found. Initialize with 'mapify init'"})
2122
2127
  raise typer.Exit(1)
2123
- manager = PlaybookManager(playbook_path)
2128
+
2129
+ manager = PlaybookManager(db_path=str(playbook_db_path))
2124
2130
  patterns = manager.get_bullets_for_sync(threshold=threshold)
2125
2131
  console.print_json(data={"threshold": threshold, "count": len(patterns), "patterns": [{"id": p.get("id"), "helpful_count": p.get("helpful_count")} for p in patterns]})
2126
2132
 
@@ -2143,9 +2149,16 @@ def playbook_query(
2143
2149
  from mapify_cli.playbook_manager import PlaybookManager
2144
2150
  from mapify_cli.playbook_query import PlaybookQuery, SearchMode
2145
2151
 
2146
- playbook_path = Path.cwd() / ".claude" / "playbook.json"
2147
- if not playbook_path.exists():
2148
- console.print("[yellow]Warning:[/yellow] Playbook not found. Initialize with 'mapify init'")
2152
+ playbook_db_path = Path.cwd() / ".claude" / "playbook.db"
2153
+ playbook_json_path = Path.cwd() / ".claude" / "playbook.json"
2154
+
2155
+ # Check for playbook.db first (primary storage)
2156
+ if not playbook_db_path.exists():
2157
+ # Backward compatibility: check if old playbook.json exists
2158
+ if playbook_json_path.exists():
2159
+ console.print("[yellow]Warning:[/yellow] Found legacy playbook.json. Run 'mapify init' to migrate to playbook.db")
2160
+ else:
2161
+ console.print("[yellow]Warning:[/yellow] Playbook not found. Initialize with 'mapify init'")
2149
2162
  raise typer.Exit(1)
2150
2163
 
2151
2164
  try:
@@ -2167,7 +2180,7 @@ def playbook_query(
2167
2180
  )
2168
2181
 
2169
2182
  # Execute query
2170
- manager = PlaybookManager(playbook_path)
2183
+ manager = PlaybookManager(db_path=str(playbook_db_path))
2171
2184
  response = manager.query(query)
2172
2185
 
2173
2186
  # Format output
@@ -2266,9 +2279,16 @@ def playbook_apply_delta(
2266
2279
  from mapify_cli.tools.validate_dependencies import load_input
2267
2280
  from mapify_cli.playbook_manager import PlaybookManager
2268
2281
 
2269
- playbook_path = Path.cwd() / ".claude" / "playbook.json"
2270
- if not playbook_path.exists():
2271
- console.print("[red]Error:[/red] Playbook not found. Initialize with 'mapify init'")
2282
+ playbook_db_path = Path.cwd() / ".claude" / "playbook.db"
2283
+ playbook_json_path = Path.cwd() / ".claude" / "playbook.json"
2284
+
2285
+ # Check for playbook.db first (primary storage)
2286
+ if not playbook_db_path.exists():
2287
+ # Backward compatibility: check if old playbook.json exists
2288
+ if playbook_json_path.exists():
2289
+ console.print("[red]Error:[/red] Found legacy playbook.json. Run 'mapify init' to migrate to playbook.db")
2290
+ else:
2291
+ console.print("[red]Error:[/red] Playbook not found. Initialize with 'mapify init'")
2272
2292
  raise typer.Exit(1)
2273
2293
 
2274
2294
  try:
@@ -2338,7 +2358,7 @@ def playbook_apply_delta(
2338
2358
  return
2339
2359
 
2340
2360
  # Apply operations
2341
- manager = PlaybookManager(playbook_path)
2361
+ manager = PlaybookManager(db_path=str(playbook_db_path))
2342
2362
  summary = manager.apply_delta(operations)
2343
2363
 
2344
2364
  # Output JSON summary
@@ -2431,4 +2451,4 @@ def main():
2431
2451
 
2432
2452
 
2433
2453
  if __name__ == "__main__":
2434
- main()
2454
+ main()