feat(provision): upgrade to latest PostGIS spatial-relation stack + 5 RelationSpatial entries + ORM tests#24
Merged
pyramation merged 4 commits intomainfrom Apr 18, 2026
Conversation
Adds a new `spatial-relations.ts` provision module that registers 5
@spatialRelation virtual filters across the agentic-db schema, and
exercises each via `orm.\*.findMany({ where: { <name>: { some: ... } } })`
in the integration suite.
Relations (all `st_dwithin` since every agentic-db geom column is a Point):
1. memories → places @ 5 km "memories near a known place"
2. memories → contacts @ 2 km "memories near where a contact lives"
3. trips → venues @ 1 km "trips whose destination is near a venue"
4. events → venues @ 500 m "events near a specific venue (no FK)"
5. memories → memories @ 1 km self-relation "what else happened near this memory"
Implementation:
- packages/provision/src/schemas/spatial-relations.ts: calls the
metaschema_modules_public.provision_spatial_relation() dispatcher
(shipped in constructive-db#844) for each row; graceful on re-run.
- packages/provision/src/provision.ts: wired after cross-relations.
- packages/integration-tests/__fixtures__/seed/spatial-relations.sql:
bakes matching `@spatialRelation` column comments so tests don't
require the full blueprint pipeline to run.
- packages/integration-tests/__tests__/orm.test.ts:
* registers PostgisSpatialRelationsPlugin in the test preset (the
ConstructivePreset ships the plugin but doesn't auto-enable it)
* adds the RelationSpatial describe-block with one test per entry
* flips bboxIntersects2D back to "expected success" now that
constructive#992 merged (GeoJSON is wrapped with ST_GeomFromGeoJSON)
- test-data.sql: adds MEMORY_FERRY (~260 m from MEMORY_SF) so the
self-relation has a matching "other" row (the plugin excludes the
owner row from self-joins) + places/venues/contacts/events fixtures
chosen for deterministic positive/negative matches.
Relation names are camelCase in both the blueprint and the seeded
tags so PostGraphile's inflection produces `nearbyPlaces`/etc. on
the generated filter input — matching every other field convention
in the schema.
All 36 ORM tests pass locally (5 RelationSpatial + the restored
scalar bboxIntersects2D test + 30 existing).
🤖 Devin AI EngineerI'll be helping with this pull request! Here's what you should know: ✅ I will automatically:
Note: I can only respond to comments from users who have write access to this repository. ⚙️ Control Options:
|
GraphilePostgisPreset (in graphile-postgis@2.11.0) already registers PostgisSpatialRelationsPlugin in its plugins array, and ConstructivePreset extends GraphilePostgisPreset. So `extends: [ConstructivePreset]` is all that's needed — my earlier explicit registration was a leftover from debugging and is redundant. All 36 ORM tests still pass.
ConstructivePreset → GraphilePostgisPreset already pulls graphile-postgis in transitively, and nothing in this package imports it directly after the previous commit removed the explicit plugin registration. Dropping the direct dep in packages/integration-tests/package.json. Tests still 36/36.
This was referenced Apr 18, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Showcases the new cross-table PostGIS spatial-relation feature end-to-end against
agentic-db. Wires 5@spatialRelationentries into the blueprint and exercises each via the ORM integration suite.Dependency bump (to pick up the feature):
@constructive-io/graphql-codegen4.28.0 → 4.30.0@pgpm/metaschema-schema/@pgpm/metaschema-modules0.20.2 → 0.21.0graphile-postgis@2.11.0inpackages/integration-testsNew production code (
packages/provision/src/schemas/spatial-relations.ts): callsmetaschema_modules_public.provision_spatial_relation(...)— the dispatcher shipped inconstructive-db#844— once per relation. All 5 usest_dwithinsince every agentic-db geom column is a Point.memories.location_geoplaces.location_geonearbyPlacesmemories.location_geocontacts.location_geonearbyContactstrips.destination_geovenues.locationnearbyVenuesevents.location_geovenues.locationnearbyVenuesmemories.location_geomemories.location_geonearbyMemoriesRelation names are camelCase (not snake_case) so PostGraphile's inflection produces filter fields like
nearbyPlacesmatching every other field convention in the schema. Operator tokens remain snake_case per the earlier discussion (st_dwithin, etc.).Test fixture (
packages/integration-tests/__fixtures__/seed/spatial-relations.sql): bakes matching@spatialRelationcolumn comments directly so ORM tests don't require the full blueprint pipeline to run. This mirrors whatprovision_spatial_relationwould emit.ORM tests (
orm.test.ts):PostgisSpatialRelationsPluginexplicitly in the test preset —ConstructivePresetships the plugin but does not auto-enable it (opt-in).describe('RelationSpatial via ORM')with 5 tests, one per entry, each with positive + negative matches.bboxIntersects2Dfrom "expected failure" back to "expected success" now thatconstructive#992merged (GeoJSON inputs get wrapped withST_GeomFromGeoJSON).MEMORY_FERRY(~260 m fromMEMORY_SF) + places/venues/contacts/events fixtures for deterministic pos/neg matches.Result: 36/36 ORM tests pass locally.
Review & Testing Checklist for Human
nearbyMemoriestest assumes the plugin excludes the owner row from self-relations (other.pk <> self.pk). That's whyMEMORY_FERRYis used as the filter target — is this the semantic we want to lock in, or should self-relations include the owner row?nearbyPlaces) for relation names so they match PostGraphile's inflection on filter fields. The earlier discussion aboutst_containssnake_case was about operator tokens specifically, but please confirm relation names in camelCase is what you want (it's what the plugin actually consumes for GraphQL field names).packages/provisionhas ~227 pre-existing TypeScript errors from the metaschema 0.20.2→0.21.0 bump (table_ref/ref/source_refproperties were renamed). These are NOT introduced by this PR — they reproduce onmainafter the dep bump. Tests still run fine via ts-jest butpnpm buildis red. Should be addressed as a separate cleanup PR; flagging so it's not a surprise.pnpm-lock.yamlhas large diff (7k insertions / 9.6k deletions) from the dep bump. Expected but not independently verified.eval "$(pgpm env)" && cd packages/integration-tests && pnpm test -- --testPathPattern 'orm.test'should produce36 passed, 36 total.Notes
packages/provision/src/schemas/spatial-relations.ts) is the production path but was not run end-to-end against a realpgpmprovision in this session — the pre-existing build errors inpackages/provisionblocked a full build. The ORM tests cover the feature via the smart-tag fixture file, which emits exactly whatprovision_spatial_relationwould.constructive#993(plugin),constructive-db#843/#844(metaschema + blueprint node),constructive#997/#999(node type registry + skill docs).Link to Devin session: https://app.devin.ai/sessions/c5eeee65a3c546c4ac6753bb05fa03e0
Requested by: @pyramation