From d801e0edc29592e193e6c5c3fc4196d223beba7e Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 18 Dec 2025 01:42:15 +0000 Subject: [PATCH 1/3] Fix missing backend exports causing ImportError The backends/__init__.py file was empty, preventing the CLI from importing BeadsBackend and GitHubBackend. Added proper __all__ exports for all three backend implementations (Beads, GitHub, Notion). This fixes the ImportError that occurred when running any em command. --- src/entity_manager/backends/__init__.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/entity_manager/backends/__init__.py b/src/entity_manager/backends/__init__.py index e69de29..7d3512b 100644 --- a/src/entity_manager/backends/__init__.py +++ b/src/entity_manager/backends/__init__.py @@ -0,0 +1,7 @@ +"""Backend implementations for entity manager.""" + +from entity_manager.backends.beads import BeadsBackend +from entity_manager.backends.github import GitHubBackend +from entity_manager.backends.notion import NotionBackend + +__all__ = ["BeadsBackend", "GitHubBackend", "NotionBackend"] From e2962c930e79c3589a7e0c5c6bb809de5e067dd8 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 18 Dec 2025 01:57:20 +0000 Subject: [PATCH 2/3] Fix critical bugs in BeadsBackend and CLI Found while testing with actual beads installation: 1. **BeadsBackend ID conversion bug**: The _entity_id_to_bead_id function was incorrectly prepending "bd-" to all IDs. Beads uses configurable project prefixes (e.g., "entity-manager-abc"), not just "bd-xxx". Fixed to return IDs as-is. 2. **BeadsBackend read() response handling**: The bd show command returns a list, not a dict. Updated to handle both formats. 3. **BeadsBackend link type mapping**: Added proper mapping from entity manager link types (blocked-by, blocking, parent, etc.) to beads dependency types (blocks, related, parent-child). 4. **CLI delete() naming collision**: The delete function was calling the list() command function instead of built-in list(), causing AttributeError. Fixed by using builtins.list(). 5. **Updated .gitignore**: Added beads artifacts and test coverage files. All fixes verified with working beads installation. --- .gitignore | 11 +++++++ src/entity_manager/backends/beads.py | 46 +++++++++++++++++++--------- src/entity_manager/cli.py | 4 ++- 3 files changed, 45 insertions(+), 16 deletions(-) diff --git a/.gitignore b/.gitignore index 033df5f..32cf4ad 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,13 @@ .venv __pycache__ +.beads +.entity-manager +.coverage +coverage.xml +htmlcov/ +*.pyc +*.pyo +*.egg-info/ +dist/ +build/ +.pytest_cache/ diff --git a/src/entity_manager/backends/beads.py b/src/entity_manager/backends/beads.py index 336ac37..d4f7fb0 100644 --- a/src/entity_manager/backends/beads.py +++ b/src/entity_manager/backends/beads.py @@ -90,7 +90,7 @@ def _bead_to_entity(self, bead: dict[str, Any]) -> Entity: labels[label] = "" entity = Entity( - id=str(bead["id"]), # Using the hash ID directly (bd-a1b2 format), converted to str + id=str(bead["id"]), # Using the bead ID directly (e.g., "entity-manager-abc" or "bd-a1b2") title=bead.get("title", ""), description=bead.get("description", ""), labels=labels, @@ -116,14 +116,11 @@ def _entity_id_to_bead_id(self, entity_id: str) -> str: entity_id: Entity ID (string) Returns: - Beads ID string (bd-xxxx format) + Beads ID string (project-prefix-hash format) """ - # If already in beads format, return as-is - if entity_id.startswith("bd-"): - return entity_id - - # Otherwise, assume it's a bead hash ID without the bd- prefix - return f"bd-{entity_id}" + # Beads IDs are already in the correct format (e.g., "entity-manager-abc" or "bd-a1b2") + # No conversion needed - return as-is + return entity_id def create( self, @@ -162,7 +159,11 @@ def read(self, entity_id: str) -> Entity: logger.info("Reading beads issue", entity_id=bead_id) result = self._run_bd_command(["show", bead_id, "--json"]) - if isinstance(result, dict): + if isinstance(result, list) and len(result) > 0: + entity = self._bead_to_entity(result[0]) + logger.debug("Beads issue read successfully", entity_id=bead_id) + return entity + elif isinstance(result, dict): entity = self._bead_to_entity(result) logger.debug("Beads issue read successfully", entity_id=bead_id) return entity @@ -268,9 +269,16 @@ def add_link(self, source_id: str, target_ids: list[str], link_type: str) -> Non # Map entity manager link types to beads dependency types # beads supports: blocks, related, parent-child, discovered-from - beads_type = link_type - if link_type == "relates_to": - beads_type = "related" + link_type_lower = link_type.lower().replace("_", "-").replace(" ", "-") + beads_type_map = { + "relates-to": "related", + "blocked-by": "blocks", + "blocking": "blocks", # Inverse relationship + "parent": "parent-child", + "child": "parent-child", + "children": "parent-child", + } + beads_type = beads_type_map.get(link_type_lower, link_type_lower) for target_id in target_ids: target_bead_id = self._entity_id_to_bead_id(target_id) @@ -288,9 +296,17 @@ def remove_link(self, source_id: str, target_ids: list[str], link_type: str, rec link_type=link_type, ) - beads_type = link_type - if link_type == "relates_to": - beads_type = "related" + # Map entity manager link types to beads dependency types + link_type_lower = link_type.lower().replace("_", "-").replace(" ", "-") + beads_type_map = { + "relates-to": "related", + "blocked-by": "blocks", + "blocking": "blocks", # Inverse relationship + "parent": "parent-child", + "child": "parent-child", + "children": "parent-child", + } + beads_type = beads_type_map.get(link_type_lower, link_type_lower) for target_id in target_ids: target_bead_id = self._entity_id_to_bead_id(target_id) diff --git a/src/entity_manager/cli.py b/src/entity_manager/cli.py index 02cddac..fbf2427 100644 --- a/src/entity_manager/cli.py +++ b/src/entity_manager/cli.py @@ -135,8 +135,10 @@ def update( @app.command def delete(*entity_ids: str) -> None: """Delete one or more entities.""" + import builtins + backend = get_backend() - backend.delete(list(entity_ids)) + backend.delete(builtins.list(entity_ids)) print(f"Deleted {len(entity_ids)} entity(ies)") From fc408254bb8509c9cc35cd96b5787dea67833328 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 18 Dec 2025 01:58:58 +0000 Subject: [PATCH 3/3] Add beads test artifacts to .gitignore Added AGENTS.md, @AGENTS.md, and .gitattributes to .gitignore as these were created during beads testing and are not part of the project. --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index 32cf4ad..08489f5 100644 --- a/.gitignore +++ b/.gitignore @@ -11,3 +11,6 @@ htmlcov/ dist/ build/ .pytest_cache/ +AGENTS.md +@AGENTS.md +.gitattributes