ember-memory-test/episodes/TRAZA_neo4j-special-chars-cypher-merge_S20260413.R7_FJ.imp.3.hot_arg.pr.cc.en.DR0.MPQ_J.PFDFK_E.SGNZD.md
Ember 0c00eba8b4 feat(episode): TRAZA_neo4j-special-chars-cypher-merge_S20260413.R7_FJ.imp.3.hot_arg.pr.cc.en.DR0.MPQ_J.PFDFK_E.SGNZD
Skill: NONE | Type: troubleshooting
Summary: EPISODIO S07 — NEO4J: apostrophe plus-sign at-sign in entity names break Cypher
2026-04-13 13:11:29 +00:00

2.6 KiB

episode_id puente_flat session_code acto_dialogico actor_flujo criticidad_aegis skill_dominante fase_proyecto tipo_semantico summary_one_line source_type trust_boundary created_at relectura_tagged forgejo_commit_sha
7df3e811-e95a-474f-a896-73bcf70cbeba TRAZA_neo4j-special-chars-cypher-merge_S20260413.R7_FJ.imp.3.hot_arg.pr.cc.en.DR0.MPQ_J.PFDFK_E.SGNZD S20260413 argumentar multi_actor moderate NONE implementation troubleshooting EPISODIO S07 — NEO4J: apostrophe plus-sign at-sign in entity names break Cypher chat_ember private 2026-04-13T12:55:32.036742+00:00 false pending

The CRISOL F5b phase creates Neo4j graph nodes for canonical entities mentioned in each episode. The current implementation uses Cypher MERGE statements to create or match entity nodes. A design decision is needed about how to handle entity names that contain characters requiring escaping in Cypher query language.

Three test entities expose the problem. First, the entity O'Reilly Media contains an apostrophe. When the F5b code generates MERGE (e:Entity {name: 'O'Reilly Media'}), the unescaped apostrophe terminates the string literal prematurely, causing a Cypher SyntaxError. Second, the entity C++ Runtime contains plus signs which are valid in Cypher strings but could cause issues in URL-encoded graph API calls. Third, the entity test@ember.ai contains an at-sign which is valid in Cypher but triggers email detection heuristics in some NLP preprocessing pipelines.

The design decision evaluates three approaches. Approach A: escape special characters in entity names before MERGE, using Neo4j parameter binding ($props.name instead of string interpolation). This is the recommended approach because it delegates escaping to the Neo4j driver, handles all edge cases, and follows the same principle as parameterized SQL queries. Approach B: normalize entity names by stripping special characters before storing in Neo4j. Rejected because it loses information and creates a divergence between Neo4j entity names and LEXICON preferred_labels. Approach C: URL-encode entity names. Rejected because it makes graph queries unreadable and breaks pattern matching.

Decision: Implement Approach A. The F5b code in crisol_run.py should use Neo4j driver parameter binding for all MERGE operations. The Cypher template becomes: MERGE (e:Entity {name: $name}) with parameters passed as a dictionary. This handles apostrophes, plus signs, at-signs, backslashes, and any other special character without manual escaping. The LEXICON preferred_label remains the authoritative name; Neo4j stores exact copies.