Spatial Processing

Ported and adapted to gist's SpatialEvaluationRun + the v0.2 relationship lifecycle (which the starter pack's simple detected/resolved model did not have).

Purpose

Convert stored GeoJSON into repeatable spatial facts.

Initial geometry support

  • Point · LineString · Polygon (GeoJSON). MultiPoint / MultiLineString / MultiPolygon in enum.

Processing sequence

flowchart TD
    CHANGE[Feature created or geometry changed]
    TRIG[Trigger definition fires]
    RUN[Open SpatialEvaluationRun]
    VALIDATE[Validate GeoJSON]
    SELECT[Select applicable spatial rules]
    EVAL[Evaluate geometry in EPSG:7856]
    MATCH{Relationship?}
    REL[Persist / update SpatialRelationship - lifecycle]
    EVT[Create SpatialEvent]
    DISC[Apply disclosure profile]
    DELIV[EventDelivery: POST to Orchestrator]
    ACK[Acknowledgement]
    RECON[Reconciliation check]
    AUDIT[Record provenance - AuditEvent]
    CHANGE --> TRIG --> RUN --> VALIDATE --> SELECT --> EVAL --> MATCH
    MATCH -- No --> AUDIT
    MATCH -- Yes --> REL --> EVT --> DISC --> DELIV --> ACK --> RECON
    REL --> AUDIT
    EVT --> AUDIT
    ACK --> AUDIT

A SpatialEvaluationRun wraps each evaluation and records candidate_count, match_count, error_count and metrics — the demo's EVAL-2026-0101 (8 candidates, 4 matches).

Initial predicates

  • intersects · within · contains · near (distance threshold).
  • Later: touches · crosses · overlaps · buffered proximity.

Coordinate reference system

  • Storage / exchange CRS: EPSG:4326 — all seeded geometry, GeoJSON in and out.
  • Analysis CRS: EPSG:7856 — every metric operation (distance, buffer, overlap area, simplification) transforms into a projected CRS first. The demo's RP-2026-001 near PIPE-44 = 197.474 m is a projected metric distance under the 250 m threshold.

Evidence captured

A SpatialRelationship records source, target, rule, relationship type, distance/overlap where relevant, and lifecycle timestamps (first_detected_at, last_confirmed_at, changed_at, ceased_at, resolved_at), plus an evidence payload and the evaluation_run_id.

Relationship lifecycle

A relationship is evidence, not merely a map calculation — it persists so it can be audited and reconciled. When geometry changes, the engine retains history and advances the lifecycle rather than deleting:

stateDiagram-v2
    [*] --> detected
    detected --> active: confirmed
    active --> changed: geometry changed, still related
    changed --> active: re-confirmed
    active --> ceased: no longer related after change
    detected --> ignored: not material
    active --> acknowledged: reviewer accepts
    acknowledged --> resolved: coordination complete
    ceased --> resolved
    resolved --> [*]
    ceased --> [*]

The demo seeds this: RP-2026-002 → ML-1032 once intersected, then ceased after the Eastern Bypass was realigned east (evaluation run EVAL-2026-0088) — history retained, not deleted.

Reconciliation rule

When a relationship disappears after a geometry change, retain the historical evidence and mark the active relationship ceased/resolved rather than deleting it — then a ReconciliationCheck verifies the downstream (Orchestrator) view still agrees (page 07).