From adcc619509733aef6f9ad2322d0022bb329b7022 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 28 Dec 2025 03:53:09 +0000 Subject: [PATCH 1/2] Initial plan From d8c1cf7ca4a71fc6d7c155f1c925b127f87023c0 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 28 Dec 2025 03:58:12 +0000 Subject: [PATCH 2/2] fix: Address review feedback - add Stories to dependency check, fix query security, and fix chained OPTIONAL MATCH Co-authored-by: spuentesp <112034353+spuentesp@users.noreply.github.com> --- .../src/monitor_data/tools/neo4j_tools.py | 28 ++++++++++++------- .../tests/test_tools/test_universe_tools.py | 4 +-- 2 files changed, 20 insertions(+), 12 deletions(-) diff --git a/packages/data-layer/src/monitor_data/tools/neo4j_tools.py b/packages/data-layer/src/monitor_data/tools/neo4j_tools.py index 8791c69..b73a1a6 100644 --- a/packages/data-layer/src/monitor_data/tools/neo4j_tools.py +++ b/packages/data-layer/src/monitor_data/tools/neo4j_tools.py @@ -405,11 +405,11 @@ def neo4j_update_universe( return result set_clause = ", ".join(set_clauses) - update_query = f""" - MATCH (u:Universe {{id: $id}}) - SET {set_clause} - RETURN u - """ + update_query = ( + "MATCH (u:Universe {id: $id})\n" + "SET " + set_clause + "\n" + "RETURN u" + ) result = client.execute_write(update_query, update_params) u = result[0]["u"] @@ -463,19 +463,27 @@ def neo4j_delete_universe(universe_id: UUID, force: bool = False) -> Dict[str, A MATCH (u:Universe {id: $id}) OPTIONAL MATCH (u)-[:HAS_SOURCE]->(s:Source) OPTIONAL MATCH (u)-[:HAS_AXIOM]->(a:Axiom) + OPTIONAL MATCH (u)-[:HAS_STORY]->(st:Story) OPTIONAL MATCH (u)<-[:IN_UNIVERSE]-(e) WHERE e:EntityArchetype OR e:EntityInstance RETURN count(DISTINCT s) AS sources, count(DISTINCT a) AS axioms, + count(DISTINCT st) AS stories, count(DISTINCT e) AS entities """ dep_result = client.execute_read(dependency_query, {"id": str(universe_id)}) deps = dep_result[0] - if deps["sources"] > 0 or deps["axioms"] > 0 or deps["entities"] > 0: + if ( + deps["sources"] > 0 + or deps["axioms"] > 0 + or deps["stories"] > 0 + or deps["entities"] > 0 + ): raise ValueError( f"Universe {universe_id} has dependent data: " - f"{deps['sources']} sources, {deps['axioms']} axioms, {deps['entities']} entities. " + f"{deps['sources']} sources, {deps['axioms']} axioms, " + f"{deps['stories']} stories, {deps['entities']} entities. " f"Use force=True to cascade delete." ) @@ -487,9 +495,9 @@ def neo4j_delete_universe(universe_id: UUID, force: bool = False) -> Dict[str, A OPTIONAL MATCH (u)-[:HAS_SOURCE]->(source:Source) OPTIONAL MATCH (u)-[:HAS_AXIOM]->(axiom:Axiom) OPTIONAL MATCH (u)-[:HAS_STORY]->(story:Story) - // Collect story dependencies (1 level deep from Story) - OPTIONAL MATCH (story)-[:HAS_SCENE]->(scene:Scene) - OPTIONAL MATCH (story)-[:HAS_THREAD]->(thread:PlotThread) + // Collect story dependencies (1 level deep from Story), matched from universe + OPTIONAL MATCH (u)-[:HAS_STORY]->(:Story)-[:HAS_SCENE]->(scene:Scene) + OPTIONAL MATCH (u)-[:HAS_STORY]->(:Story)-[:HAS_THREAD]->(thread:PlotThread) // Collect entities with IN_UNIVERSE relationship OPTIONAL MATCH (u)<-[:IN_UNIVERSE]-(entity) WHERE entity:EntityArchetype OR entity:EntityInstance diff --git a/packages/data-layer/tests/test_tools/test_universe_tools.py b/packages/data-layer/tests/test_tools/test_universe_tools.py index 79055b8..bdc3392 100644 --- a/packages/data-layer/tests/test_tools/test_universe_tools.py +++ b/packages/data-layer/tests/test_tools/test_universe_tools.py @@ -309,7 +309,7 @@ def test_delete_universe_success( # Mock universe exists mock_neo4j_client.execute_read.side_effect = [ [{"u": universe_data}], # verify exists - [{"sources": 0, "axioms": 0, "entities": 0}], # no dependencies + [{"sources": 0, "axioms": 0, "stories": 0, "entities": 0}], # no dependencies ] # Mock deletion @@ -332,7 +332,7 @@ def test_delete_universe_with_dependencies_no_force( # Mock universe exists with dependencies mock_neo4j_client.execute_read.side_effect = [ [{"u": universe_data}], # verify exists - [{"sources": 2, "axioms": 3, "entities": 5}], # has dependencies + [{"sources": 2, "axioms": 3, "stories": 1, "entities": 5}], # has dependencies ] universe_id = UUID(universe_data["id"])