Skip to content

0.8.0-dev7: :AFFECTS edge resolution + target/subject consistency#8

Merged
stevenca merged 1 commit into
mainfrom
fix/0.8.0-dev7-affects-edge-resolution
Jun 2, 2026
Merged

0.8.0-dev7: :AFFECTS edge resolution + target/subject consistency#8
stevenca merged 1 commit into
mainfrom
fix/0.8.0-dev7-affects-edge-resolution

Conversation

@stevenca

@stevenca stevenca commented Jun 2, 2026

Copy link
Copy Markdown
Owner

Summary

Second small polish to the dev5 pipeline, caught by deployment verification.

The dev5+dev6 deploys produced 31 :ReflexEvent nodes (real data, including 28 from Meraki MS switches after the dev6 fix landed), but none of them connected to their :Device nodes via :AFFECTS.

Root cause: the link_down handler preferred payload[\"device_id\"] over payload[\"device\"], which produced targets like 'meraki:Q4CD-Y6FW-EKVS|Port 9' — a Neo4j node-id form that no Device node had as its name or platform_id.

Fix (two-sided, low-risk)

  1. Handler side: link_down now prefers payload[\"device\"] (human name) over payload[\"device_id\"]. Falls back to device_id when device is absent (legacy publishers, traps).
  2. Sink side: Neo4jReflexEventSink AFFECTS-edge MATCH now resolves on three identifiers: d.name, d.platform_id, AND d.id — the third catches node-id-form targets if a future publisher emits them.

The handler fix makes the target consistent with the subject token; the sink fix makes the edge resolution forgiving of any remaining identifier-form drift.

Tests

  • 2 new cases in `tests/reflex/test_handlers.py` covering both ordering preferences.

Backfill plan

After deploy, run this Cypher once to retrofit the 31 already-captured events:
```cypher
MATCH (e:ReflexEvent) WHERE NOT (e)-[:AFFECTS]->(:Device)
WITH e, split(e.target, '|')[0] AS device_key
MATCH (d:Device)
WHERE d.name = device_key OR d.platform_id = device_key OR d.id = device_key
MERGE (e)-[:AFFECTS]->(d)
RETURN count(*) AS backfilled
```

Test plan

  • CI: all 8 jobs pass
  • Deploy
  • Run the backfill Cypher
  • Confirm `MATCH (e:ReflexEvent)-[:AFFECTS]->(d:Device) RETURN count(*)` returns 31+
  • Verify next genuine SNMP-detected flap lands with its `:AFFECTS` edge already attached

Made with Cursor

Second small polish to the dev5 pipeline. The dev5+dev6 deploys
produced 31 :ReflexEvent nodes (real data) but none of them connected
to their :Device nodes via :AFFECTS.

Root cause: link_down handler preferred payload['device_id'] over
payload['device'], producing targets like 'meraki:Q4CD-Y6FW-EKVS|Port 9'
- a Neo4j node-id form that no Device node had as its name or
platform_id.

Two-sided fix:
1. link_down handler now prefers payload['device'] (human name) over
   payload['device_id'] so the target string matches the subject token
   built by the publisher. Falls back to device_id when device is absent
   (legacy publishers, traps).
2. Neo4jReflexEventSink AFFECTS-edge MATCH now resolves devices on
   three identifiers: d.name, d.platform_id, AND d.id - the latter
   catches node-id-form targets if a future publisher emits them.

Tests: 2 new cases covering both ordering preferences.

CHANGELOG includes a Cypher snippet to backfill the existing 31 nodes
with :AFFECTS edges after deploy.

Co-authored-by: Cursor <cursoragent@cursor.com>
@stevenca stevenca merged commit d44cbc0 into main Jun 2, 2026
8 checks passed
@stevenca stevenca deleted the fix/0.8.0-dev7-affects-edge-resolution branch June 2, 2026 13:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant