smart-spatial-system 0.2.2__tar.gz → 0.2.4__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {smart_spatial_system-0.2.2/smart_spatial_system.egg-info → smart_spatial_system-0.2.4}/PKG-INFO +1 -1
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/config/plugins/distance_calculator.example.yaml +1 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/config/plugins/distance_calculator.yaml +1 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/config/plugins/nearest_neighbor.example.yaml +1 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/config/plugins/nearest_neighbor.yaml +1 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/orchestrator/planning/llm_spec_generator.py +228 -7
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/orchestrator/planning/op_catalog.py +8 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/plugins/distance_calculator.py +68 -1
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/plugins/feature_scoring.py +23 -1
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/plugins/nearest_neighbor.py +25 -1
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/pyproject.toml +1 -1
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/smart_spatial_system/application/services/query_execution/accessibility_query_spec.py +11 -1
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4/smart_spatial_system.egg-info}/PKG-INFO +1 -1
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/tests/test_distance_calculator.py +60 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/tests/test_feature_scoring.py +44 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/tests/test_llm_spec_generator.py +313 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/tests/test_nearest_neighbor.py +44 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/tests/test_op_catalog_semantic_aliases.py +13 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/LICENSE +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/README.md +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/api/__init__.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/api/auth.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/api/main.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/api/routers/__init__.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/api/routers/data_source_connectors.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/api/routers/data_sources.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/api/routers/plugins_settings.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/api/routers/projects.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/api/routers/query_planner.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/api/routers/requests_outputs.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/api/routers/system.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/api/routers/uploads.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/api/routers/weights.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/api/support.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/config/__init__.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/config/plugins/__init__.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/config/plugins/area_perimeter_calc.example.yaml +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/config/plugins/area_perimeter_calc.yaml +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/config/plugins/attribute_statistics.example.yaml +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/config/plugins/attribute_statistics.yaml +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/config/plugins/band_math.example.yaml +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/config/plugins/band_math.yaml +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/config/plugins/buffer_analysis.example.yaml +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/config/plugins/buffer_analysis.yaml +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/config/plugins/centroid_extractor.example.yaml +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/config/plugins/centroid_extractor.yaml +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/config/plugins/core_vector.example.yaml +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/config/plugins/core_vector.yaml +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/config/plugins/crs_transformer.example.yaml +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/config/plugins/crs_transformer.yaml +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/config/plugins/data_writer_exporter.example.yaml +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/config/plugins/data_writer_exporter.yaml +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/config/plugins/dissolve_aggregator.example.yaml +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/config/plugins/dissolve_aggregator.yaml +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/config/plugins/feature_enrichment.example.yaml +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/config/plugins/feature_enrichment.yaml +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/config/plugins/feature_scoring.example.yaml +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/config/plugins/feature_scoring.yaml +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/config/plugins/geocoding_resolver.example.yaml +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/config/plugins/geocoding_resolver.yaml +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/config/plugins/geometry_validator.example.yaml +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/config/plugins/geometry_validator.yaml +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/config/plugins/local_raster_loader.example.yaml +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/config/plugins/local_raster_loader.yaml +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/config/plugins/local_vector_loader.example.yaml +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/config/plugins/local_vector_loader.yaml +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/config/plugins/ndvi_calculator.example.yaml +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/config/plugins/ndvi_calculator.yaml +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/config/plugins/postgis_connector.example.yaml +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/config/plugins/postgis_connector.yaml +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/config/plugins/raster_clip_mask.example.yaml +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/config/plugins/raster_clip_mask.yaml +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/config/plugins/raster_reclassify.example.yaml +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/config/plugins/raster_reclassify.yaml +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/config/plugins/raster_statistics.example.yaml +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/config/plugins/raster_statistics.yaml +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/config/plugins/raster_threshold.example.yaml +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/config/plugins/raster_threshold.yaml +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/config/plugins/raster_to_vector.example.yaml +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/config/plugins/raster_to_vector.yaml +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/config/plugins/risk_enrichment.example.yaml +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/config/plugins/risk_enrichment.yaml +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/config/plugins/slope_aspect.yaml +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/config/plugins/spatial_intersection.example.yaml +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/config/plugins/spatial_intersection.yaml +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/config/plugins/spatial_join.example.yaml +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/config/plugins/spatial_join.yaml +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/config/plugins/spatial_predicate.example.yaml +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/config/plugins/spatial_predicate.yaml +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/config/plugins/spatial_query_filter.example.yaml +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/config/plugins/spatial_query_filter.yaml +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/config/plugins/spectral_indices.example.yaml +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/config/plugins/spectral_indices.yaml +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/config/plugins/wms_wfs_fetcher.example.yaml +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/config/plugins/wms_wfs_fetcher.yaml +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/config/plugins/zonal_statistics.example.yaml +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/config/plugins/zonal_statistics.yaml +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/orchestrator/__init__.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/orchestrator/audit.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/orchestrator/capability_registry.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/orchestrator/capability_router.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/orchestrator/capability_scoring.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/orchestrator/data_source_service.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/orchestrator/error_contract.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/orchestrator/feedback.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/orchestrator/feedback_proposal_service.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/orchestrator/input_error_mapping.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/orchestrator/input_reference_resolver.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/orchestrator/kernel_artifacts.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/orchestrator/learning_signals.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/orchestrator/llm_client.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/orchestrator/llm_gate.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/orchestrator/llm_intent_planner.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/orchestrator/loader_plugin_contract.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/orchestrator/map_layer_service.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/orchestrator/map_layers.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/orchestrator/models.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/orchestrator/natural_query_runner.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/orchestrator/output_service.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/orchestrator/output_storage.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/orchestrator/pipeline_executor.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/orchestrator/plan_builder.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/orchestrator/planning/__init__.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/orchestrator/planning/capability_resolver.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/orchestrator/planning/dag.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/orchestrator/planning/dag_executor.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/orchestrator/planning/error_mapping.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/orchestrator/planning/kernel_execution_bridge.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/orchestrator/planning/kernel_plan_adapter.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/orchestrator/planning/llm_query_spec.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/orchestrator/planning/output_parity.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/orchestrator/planning/planner.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/orchestrator/planning/postgis_semantic_resolver.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/orchestrator/planning/query_spec_contract.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/orchestrator/planning/report_spec.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/orchestrator/planning/runner.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/orchestrator/planning/semantic_planning_context.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/orchestrator/planning/spec.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/orchestrator/plugin_config_store.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/orchestrator/plugin_error_mapping.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/orchestrator/plugin_modules.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/orchestrator/plugin_runtime_service.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/orchestrator/plugin_state.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/orchestrator/production_response.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/orchestrator/project_service.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/orchestrator/project_store.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/orchestrator/provider_error_mapping.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/orchestrator/query_execution_service.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/orchestrator/query_parser.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/orchestrator/request_history_service.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/orchestrator/response_assembler.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/orchestrator/response_builder.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/orchestrator/router_decision.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/orchestrator/routing_aware_natural_query_runner.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/orchestrator/routing_aware_plan_builder.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/orchestrator/runtime_paths.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/orchestrator/service.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/orchestrator/statistics.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/orchestrator/upload_service.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/orchestrator/upload_storage.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/orchestrator/weight_proposals.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/orchestrator/weight_store_persistence.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/orchestrator/weighted_router.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/plugins/__init__.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/plugins/_shared/__init__.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/plugins/_shared/local_path_validation.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/plugins/_shared/numeric_validation.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/plugins/_shared/plugin_config.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/plugins/area_perimeter_calc.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/plugins/attribute_statistics.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/plugins/band_math.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/plugins/buffer_analysis.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/plugins/centroid_extractor.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/plugins/core_vector.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/plugins/crs_transformer.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/plugins/data_writer_exporter.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/plugins/dissolve_aggregator.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/plugins/feature_enrichment.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/plugins/geocoding_resolver.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/plugins/geometry_validator.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/plugins/local_raster_loader.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/plugins/local_vector_loader.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/plugins/ndvi_analysis.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/plugins/ndvi_calculator.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/plugins/pdf_renderer.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/plugins/postgis_connector.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/plugins/raster_clip_mask.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/plugins/raster_reclassify.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/plugins/raster_statistics.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/plugins/raster_threshold.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/plugins/raster_to_vector.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/plugins/real_estate_scoring.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/plugins/real_estate_spatial_enrichment.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/plugins/report_builder.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/plugins/risk_enrichment.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/plugins/slope_aspect.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/plugins/spatial_intersection.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/plugins/spatial_join.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/plugins/spatial_predicate.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/plugins/spatial_query_filter.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/plugins/spectral_indices.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/plugins/wms_wfs_fetcher.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/plugins/zonal_statistics.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/setup.cfg +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/smart_spatial_system/__init__.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/smart_spatial_system/__main__.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/smart_spatial_system/application/__init__.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/smart_spatial_system/application/services/__init__.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/smart_spatial_system/application/services/data_source_service.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/smart_spatial_system/application/services/feedback_proposal_service.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/smart_spatial_system/application/services/llm_intent_adapter.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/smart_spatial_system/application/services/map_layer_service.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/smart_spatial_system/application/services/output_service.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/smart_spatial_system/application/services/planning_execution_policy.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/smart_spatial_system/application/services/planning_response_adapter.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/smart_spatial_system/application/services/plugin_runtime_service.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/smart_spatial_system/application/services/project_service.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/smart_spatial_system/application/services/query_execution/__init__.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/smart_spatial_system/application/services/query_execution/direct_query_dispatch.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/smart_spatial_system/application/services/query_execution/natural_query_context.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/smart_spatial_system/application/services/query_execution/natural_query_dispatch.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/smart_spatial_system/application/services/query_execution/natural_query_execution.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/smart_spatial_system/application/services/query_execution/natural_query_failure.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/smart_spatial_system/application/services/query_execution/natural_query_persistence.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/smart_spatial_system/application/services/query_execution/planning_context.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/smart_spatial_system/application/services/query_execution/planning_execution.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/smart_spatial_system/application/services/query_execution/planning_persistence.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/smart_spatial_system/application/services/query_execution/planning_response.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/smart_spatial_system/application/services/query_execution/postgis_planning_context.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/smart_spatial_system/application/services/query_execution/real_estate_analysis_inspector.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/smart_spatial_system/application/services/query_execution/real_estate_classifier.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/smart_spatial_system/application/services/query_execution/real_estate_context.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/smart_spatial_system/application/services/query_execution/real_estate_document_renderer.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/smart_spatial_system/application/services/query_execution/real_estate_missing_inputs.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/smart_spatial_system/application/services/query_execution/real_estate_ranking_artifacts.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/smart_spatial_system/application/services/query_execution/real_estate_ranking_direct_handler.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/smart_spatial_system/application/services/query_execution/real_estate_ranking_execution.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/smart_spatial_system/application/services/query_execution/real_estate_ranking_query_spec.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/smart_spatial_system/application/services/query_execution/real_estate_ranking_response.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/smart_spatial_system/application/services/query_execution/real_estate_report_payload.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/smart_spatial_system/application/services/query_execution/real_estate_scoring.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/smart_spatial_system/application/services/query_execution_service.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/smart_spatial_system/application/services/query_spec_enrichment.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/smart_spatial_system/application/services/real_estate_spatial_helpers.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/smart_spatial_system/application/services/request_history_service.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/smart_spatial_system/application/services/system_status_query_handler.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/smart_spatial_system/application/services/upload_service.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/smart_spatial_system/application/services/vector_display_handler.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/smart_spatial_system/application/services/vector_geojson_helpers.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/smart_spatial_system/application/services/vector_query_classifier.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/smart_spatial_system/cli.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/smart_spatial_system/domain/__init__.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/smart_spatial_system/domain/contracts/__init__.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/smart_spatial_system/domain/models/__init__.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/smart_spatial_system/infrastructure/__init__.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/smart_spatial_system/infrastructure/stores/__init__.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/smart_spatial_system/interfaces/__init__.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/smart_spatial_system/interfaces/api/__init__.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/smart_spatial_system/interfaces/api/routers/__init__.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/smart_spatial_system/plugins/__init__.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/smart_spatial_system/runtime/__init__.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/smart_spatial_system/shared/__init__.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/smart_spatial_system/workflows/__init__.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/smart_spatial_system/workflows/ndvi/__init__.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/smart_spatial_system/workflows/real_estate/__init__.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/smart_spatial_system.egg-info/SOURCES.txt +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/smart_spatial_system.egg-info/dependency_links.txt +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/smart_spatial_system.egg-info/entry_points.txt +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/smart_spatial_system.egg-info/requires.txt +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/smart_spatial_system.egg-info/top_level.txt +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/templates/__init__.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/templates/reports/__init__.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/templates/reports/real_estate_report.html +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/tests/test_accessibility_query_spec.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/tests/test_api_auth.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/tests/test_api_contract_smoke.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/tests/test_api_data_source_connectors_e2e.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/tests/test_api_map_layers.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/tests/test_api_mvp.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/tests/test_api_outputs.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/tests/test_api_projects.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/tests/test_api_structured_error_normalization.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/tests/test_api_upload_plugin_resolver.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/tests/test_api_uploads.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/tests/test_area_perimeter_calc.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/tests/test_attribute_statistics.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/tests/test_band_math.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/tests/test_buffer_analysis.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/tests/test_centroid_extractor.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/tests/test_cli.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/tests/test_crs_transformer.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/tests/test_data_source_service.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/tests/test_data_writer_exporter.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/tests/test_deterministic_planner.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/tests/test_dissolve_aggregator.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/tests/test_document_file_report_contract.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/tests/test_end_to_end_natural_query_pipeline.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/tests/test_error_contract.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/tests/test_feature_enrichment.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/tests/test_frontend_api_surface_contract.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/tests/test_geocoding_resolver.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/tests/test_geocoding_resolver_error_redaction.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/tests/test_geometry_validator.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/tests/test_input_error_mapping.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/tests/test_input_reference_resolver.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/tests/test_input_reference_resolver_contract.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/tests/test_kernel_artifacts.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/tests/test_kernel_execution_bridge.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/tests/test_kernel_plan_adapter.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/tests/test_llm_intent_adapter.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/tests/test_llm_raster_queryspec_normalization.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/tests/test_llm_spec_generator_prenormalize.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/tests/test_llm_spec_generator_semantic_context.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/tests/test_llm_spec_generator_semantic_query_database_enrich.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/tests/test_llm_spec_generator_semantic_queryspec_repair.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/tests/test_loader_plugin_contract.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/tests/test_local_path_validation.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/tests/test_local_raster_loader.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/tests/test_local_raster_loader_contract.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/tests/test_local_vector_loader.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/tests/test_local_vector_loader_contract.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/tests/test_map_layer_contract.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/tests/test_map_layer_service.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/tests/test_ndvi_calculator.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/tests/test_numeric_validation.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/tests/test_orchestrator_audit.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/tests/test_orchestrator_audit_integration.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/tests/test_orchestrator_data_source_service_integration.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/tests/test_orchestrator_feedback.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/tests/test_orchestrator_feedback_integration.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/tests/test_orchestrator_keyword_scoring_router.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/tests/test_orchestrator_learning_signals.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/tests/test_orchestrator_learning_signals_integration.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/tests/test_orchestrator_llm_gate.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/tests/test_orchestrator_llm_gate_integration.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/tests/test_orchestrator_map_layer_service_integration.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/tests/test_orchestrator_natural_query_pipeline.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/tests/test_orchestrator_output_service_integration.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/tests/test_orchestrator_production_response.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/tests/test_orchestrator_production_response_integration.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/tests/test_orchestrator_project_service_integration.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/tests/test_orchestrator_query_execution_service_integration.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/tests/test_orchestrator_registry_router.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/tests/test_orchestrator_router_decision.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/tests/test_orchestrator_router_decision_integration.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/tests/test_orchestrator_routing_aware_plan_builder.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/tests/test_orchestrator_runtime_paths.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/tests/test_orchestrator_service.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/tests/test_orchestrator_service_domain_boundary_contract.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/tests/test_orchestrator_service_integration.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/tests/test_orchestrator_service_postgis_dedup_contract.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/tests/test_orchestrator_statistics.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/tests/test_orchestrator_statistics_integration.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/tests/test_orchestrator_upload_service_integration.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/tests/test_orchestrator_weight_proposals.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/tests/test_orchestrator_weight_proposals_integration.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/tests/test_orchestrator_weight_store_persistence.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/tests/test_orchestrator_weight_store_persistence_integration.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/tests/test_orchestrator_weighted_router.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/tests/test_orchestrator_weighted_router_integration.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/tests/test_output_service.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/tests/test_output_storage.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/tests/test_pdf_renderer.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/tests/test_phase3_kernel_registry_coverage.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/tests/test_phase3_output_parity.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/tests/test_phase3_postgis_provider_kernel_execution.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/tests/test_planning_dag_executor.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/tests/test_planning_dag_executor_async_capability.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/tests/test_planning_error_mapping.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/tests/test_planning_execution_policy.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/tests/test_planning_raster_op_catalog_mapping.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/tests/test_planning_raster_queryspec_execution.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/tests/test_planning_registry_backed_raster_execution.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/tests/test_planning_registry_backed_real_estate_execution.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/tests/test_planning_runner.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/tests/test_plugin_boundary_contract.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/tests/test_plugin_config.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/tests/test_plugin_config_store.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/tests/test_plugin_error_mapping.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/tests/test_plugin_modules.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/tests/test_postgis_connector.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/tests/test_postgis_connector_percent_escape.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/tests/test_postgis_semantic_resolver.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/tests/test_project_service.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/tests/test_project_store.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/tests/test_provider_error_mapping.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/tests/test_query_dispatch_domain_boundary_contract.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/tests/test_query_execution_postgis_planning_context.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/tests/test_query_execution_service.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/tests/test_query_execution_service_domain_import_boundary_contract.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/tests/test_query_response_shape_golden.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/tests/test_query_spec_enrichment.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/tests/test_raster_capability_registry_contract.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/tests/test_raster_clip_mask.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/tests/test_raster_reclassify.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/tests/test_raster_statistics.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/tests/test_raster_threshold.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/tests/test_raster_to_vector.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/tests/test_real_estate_ranking_bridge.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/tests/test_real_estate_ranking_golden.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/tests/test_real_estate_ranking_query_spec_planning.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/tests/test_real_estate_scoring_plugin.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/tests/test_real_estate_spatial_enrichment_plugin.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/tests/test_real_estate_spatial_helpers.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/tests/test_report_builder.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/tests/test_report_spec.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/tests/test_request_document_download_contract.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/tests/test_response_assembler.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/tests/test_response_output_contract.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/tests/test_risk_enrichment.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/tests/test_runtime_paths.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/tests/test_semantic_planning_context.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/tests/test_service_auto_postgis_semantic_context.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/tests/test_service_planning_artifacts.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/tests/test_service_postgis_runtime_connection_injection.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/tests/test_service_semantic_planning_context.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/tests/test_service_strict_loader_contract.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/tests/test_service_structured_error_normalization.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/tests/test_slope_aspect.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/tests/test_spatial_intersection.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/tests/test_spatial_join.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/tests/test_spatial_query_filter.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/tests/test_spectral_indices.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/tests/test_system_status_query_handler.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/tests/test_upload_service.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/tests/test_upload_storage.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/tests/test_vector_display_handler.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/tests/test_vector_geojson_helpers.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/tests/test_vector_query_classifier.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/tests/test_wms_wfs_fetcher.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/tests/test_wms_wfs_fetcher_error_redaction.py +0 -0
- {smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/tests/test_zonal_statistics.py +0 -0
|
@@ -1023,6 +1023,25 @@ Pending operations, not executable yet:
|
|
|
1023
1023
|
{pending}
|
|
1024
1024
|
|
|
1025
1025
|
Important mappings:
|
|
1026
|
+
- CRITICAL - any distance/nearest-neighbor operation (filter_by_distance,
|
|
1027
|
+
spatial_nearest, nearest_neighbor, distance_to) needs BOTH of its vector
|
|
1028
|
+
inputs reprojected with crs_transform first, not just the source/site
|
|
1029
|
+
layer. Distance is computed from raw geometry coordinates with zero CRS
|
|
1030
|
+
awareness - if one layer is reprojected to a metric CRS and the other is
|
|
1031
|
+
left in whatever CRS it was uploaded in (commonly EPSG:4326), the
|
|
1032
|
+
"distance" returned is a number between two points in DIFFERENT CRSs,
|
|
1033
|
+
meaningless but not an error by itself. Reproject EVERY layer that feeds
|
|
1034
|
+
a distance operation to the SAME target CRS, and pass that CRS as both
|
|
1035
|
+
source_crs and target_crs on the distance operation itself - this lets
|
|
1036
|
+
the operation catch a mismatch and raise instead of returning a bogus
|
|
1037
|
+
value:
|
|
1038
|
+
crs_transform(sites) -> sites_metric (target_crs="EPSG:31256")
|
|
1039
|
+
crs_transform(metro) -> metro_metric (target_crs="EPSG:31256")
|
|
1040
|
+
spatial_nearest(source=sites_metric, target=metro_metric,
|
|
1041
|
+
params={{"source_crs": "EPSG:31256", "target_crs": "EPSG:31256"}})
|
|
1042
|
+
WRONG: spatial_nearest(source=sites_metric, target=metro) - "metro" was
|
|
1043
|
+
never reprojected, so its coordinates are still in the original CRS.
|
|
1044
|
+
|
|
1026
1045
|
- "nearer than X meters to POI":
|
|
1027
1046
|
op="filter_by_distance"
|
|
1028
1047
|
inputs={{"vector": "<source>", "reference": "<poi>"}}
|
|
@@ -1052,6 +1071,21 @@ Important mappings:
|
|
|
1052
1071
|
- "score/rank":
|
|
1053
1072
|
use score_features then rank_features.
|
|
1054
1073
|
|
|
1074
|
+
- CRITICAL - every scoring factor MUST include an explicit "type". There is
|
|
1075
|
+
NO default - a factor with no "type" is rejected, it does not fall back
|
|
1076
|
+
to anything. (An earlier version of this system defaulted a missing
|
|
1077
|
+
"type" to "boolean" silently; for a distance field that meant every
|
|
1078
|
+
score came out 0.0 for every feature, with no error - that default no
|
|
1079
|
+
longer exists.) Valid types: "boolean", "boolean_bonus",
|
|
1080
|
+
"inverse_distance", "risk_level", "inverse_level", "threshold",
|
|
1081
|
+
"condition", "direct", "numeric", "inverse_numeric". A distance field
|
|
1082
|
+
(anything you computed with spatial_nearest/nearest_neighbor/distance_to)
|
|
1083
|
+
needs "type": "inverse_distance" and a numeric "max_distance":
|
|
1084
|
+
{{"name": "near_metro", "field": "distance_to_metro",
|
|
1085
|
+
"type": "inverse_distance", "max_distance": 800, "weight": 1}}
|
|
1086
|
+
WRONG (missing "type" - rejected, not defaulted):
|
|
1087
|
+
{{"field": "distance_to_metro", "weight": -1}}
|
|
1088
|
+
|
|
1055
1089
|
- CRITICAL - scoring against MORE THAN ONE computed field (e.g. distance to
|
|
1056
1090
|
several different amenities/references): each computation must be CHAINED
|
|
1057
1091
|
onto the previous one's output, not all computed separately from the
|
|
@@ -1667,12 +1701,12 @@ def _validate_operation_input_roles(spec: QuerySpec) -> None:
|
|
|
1667
1701
|
_NEAREST_OPS_WITH_DISTANCE_FIELD = {"spatial_nearest", "nearest_neighbor", "filter_by_distance"}
|
|
1668
1702
|
|
|
1669
1703
|
|
|
1670
|
-
def
|
|
1704
|
+
def _extract_scoring_factors(params: dict[str, Any]) -> list[dict[str, Any]]:
|
|
1671
1705
|
"""
|
|
1672
|
-
Pull the
|
|
1673
|
-
|
|
1674
|
-
|
|
1675
|
-
|
|
1706
|
+
Pull the raw factor dicts out of a score_features op's params, across
|
|
1707
|
+
the shapes _normalize_scoring_spec (in plugins/feature_scoring.py)
|
|
1708
|
+
accepts: top-level "factors", or "scoring_spec.factors", or the older
|
|
1709
|
+
nested "scoring_spec.scoring.factors".
|
|
1676
1710
|
"""
|
|
1677
1711
|
factors = params.get("factors")
|
|
1678
1712
|
|
|
@@ -1688,10 +1722,19 @@ def _extract_scoring_factor_fields(params: dict[str, Any]) -> list[str]:
|
|
|
1688
1722
|
if not isinstance(factors, list):
|
|
1689
1723
|
return []
|
|
1690
1724
|
|
|
1725
|
+
return [factor for factor in factors if isinstance(factor, dict)]
|
|
1726
|
+
|
|
1727
|
+
|
|
1728
|
+
def _extract_scoring_factor_fields(params: dict[str, Any]) -> list[str]:
|
|
1729
|
+
"""
|
|
1730
|
+
Pull the "field" name out of every factor a score_features op's
|
|
1731
|
+
params declare - see _extract_scoring_factors for the shapes this
|
|
1732
|
+
covers.
|
|
1733
|
+
"""
|
|
1691
1734
|
return [
|
|
1692
1735
|
str(factor["field"])
|
|
1693
|
-
for factor in
|
|
1694
|
-
if
|
|
1736
|
+
for factor in _extract_scoring_factors(params)
|
|
1737
|
+
if factor.get("field")
|
|
1695
1738
|
]
|
|
1696
1739
|
|
|
1697
1740
|
|
|
@@ -1751,6 +1794,64 @@ def _ancestor_refs(start_ref: str, ops_by_output: dict[str, OperationSpec]) -> s
|
|
|
1751
1794
|
return seen
|
|
1752
1795
|
|
|
1753
1796
|
|
|
1797
|
+
# Kept in sync by hand with plugins/feature_scoring.py's _score_factor -
|
|
1798
|
+
# there is no single source of truth to generate this from (unlike
|
|
1799
|
+
# OP_CATALOG for operations), so a new factor type added there needs
|
|
1800
|
+
# adding here too.
|
|
1801
|
+
_VALID_SCORING_FACTOR_TYPES = {
|
|
1802
|
+
"boolean",
|
|
1803
|
+
"boolean_bonus",
|
|
1804
|
+
"inverse_distance",
|
|
1805
|
+
"risk_level",
|
|
1806
|
+
"inverse_level",
|
|
1807
|
+
"threshold",
|
|
1808
|
+
"condition",
|
|
1809
|
+
"direct",
|
|
1810
|
+
"numeric",
|
|
1811
|
+
"inverse_numeric",
|
|
1812
|
+
}
|
|
1813
|
+
|
|
1814
|
+
|
|
1815
|
+
def _validate_score_features_factor_types(spec: QuerySpec) -> None:
|
|
1816
|
+
"""
|
|
1817
|
+
Catch a score_features factor with no "type" before the plan is
|
|
1818
|
+
returned, not when it silently scores everything 0.0.
|
|
1819
|
+
|
|
1820
|
+
plugins/feature_scoring.py's _score_factor has no default for a
|
|
1821
|
+
missing "type" (it raises) - but that only fires at execution time,
|
|
1822
|
+
several steps and possibly minutes of API-billed retries away from
|
|
1823
|
+
the generation step that produced the bad spec. This catches the
|
|
1824
|
+
identical condition immediately, with the same "there is no safe
|
|
1825
|
+
default" reasoning, right where the LLM's output is still available
|
|
1826
|
+
to name in the error.
|
|
1827
|
+
"""
|
|
1828
|
+
for op in spec.operations:
|
|
1829
|
+
if op.op != "score_features":
|
|
1830
|
+
continue
|
|
1831
|
+
|
|
1832
|
+
for factor in _extract_scoring_factors(op.params):
|
|
1833
|
+
factor_type = factor.get("type")
|
|
1834
|
+
field_name = factor.get("field") or factor.get("name") or "<unnamed>"
|
|
1835
|
+
|
|
1836
|
+
if not factor_type:
|
|
1837
|
+
raise LLMSpecGenerationError(
|
|
1838
|
+
f"score_features (output={op.output!r}) has a factor "
|
|
1839
|
+
f"for field {field_name!r} with no 'type'. There is no "
|
|
1840
|
+
"safe default - every factor must specify one "
|
|
1841
|
+
f"explicitly: {sorted(_VALID_SCORING_FACTOR_TYPES)!r}. "
|
|
1842
|
+
"A distance field almost always wants "
|
|
1843
|
+
"'inverse_distance' with 'max_distance' set."
|
|
1844
|
+
)
|
|
1845
|
+
|
|
1846
|
+
if factor_type not in _VALID_SCORING_FACTOR_TYPES:
|
|
1847
|
+
raise LLMSpecGenerationError(
|
|
1848
|
+
f"score_features (output={op.output!r}) has a factor "
|
|
1849
|
+
f"for field {field_name!r} with unsupported type "
|
|
1850
|
+
f"{factor_type!r}. Valid types: "
|
|
1851
|
+
f"{sorted(_VALID_SCORING_FACTOR_TYPES)!r}."
|
|
1852
|
+
)
|
|
1853
|
+
|
|
1854
|
+
|
|
1754
1855
|
def _validate_score_features_field_chaining(spec: QuerySpec) -> None:
|
|
1755
1856
|
"""
|
|
1756
1857
|
Catch a score_features op reading from a ref that never accumulated a
|
|
@@ -1820,6 +1921,124 @@ def _validate_score_features_field_chaining(spec: QuerySpec) -> None:
|
|
|
1820
1921
|
)
|
|
1821
1922
|
|
|
1822
1923
|
|
|
1924
|
+
# The two vector-bearing input roles for each distance/nearest-neighbor
|
|
1925
|
+
# operation, in (this-layer, other-layer) order - used to check that both
|
|
1926
|
+
# were reprojected to the same CRS, not just one of them.
|
|
1927
|
+
_DISTANCE_OPS_VECTOR_ROLES = {
|
|
1928
|
+
"spatial_nearest": ("source", "target"),
|
|
1929
|
+
"nearest_neighbor": ("source", "target"),
|
|
1930
|
+
"filter_by_distance": ("vector", "reference"),
|
|
1931
|
+
"distance_to": ("vector", "target"),
|
|
1932
|
+
}
|
|
1933
|
+
|
|
1934
|
+
|
|
1935
|
+
def _crs_transform_target_crs(
|
|
1936
|
+
ref: str, ops_by_output: dict[str, OperationSpec]
|
|
1937
|
+
) -> str | None:
|
|
1938
|
+
"""
|
|
1939
|
+
The target_crs a ref was reprojected to - either directly (ref is the
|
|
1940
|
+
output of a crs_transform operation), or inherited by walking back
|
|
1941
|
+
through a chain of distance/nearest-neighbor operations on their
|
|
1942
|
+
source side, since those operations don't reproject and so preserve
|
|
1943
|
+
whatever CRS their source input was already in.
|
|
1944
|
+
|
|
1945
|
+
That chain-walk matters for exactly the case
|
|
1946
|
+
accessibility_query_spec.py's own multi-amenity chain produces (and
|
|
1947
|
+
any equivalent LLM-generated chain): only the FIRST spatial_nearest
|
|
1948
|
+
step's source is directly a crs_transform output -
|
|
1949
|
+
"sites_metric" -> spatial_nearest(metro) -> "sites_with_metro" ->
|
|
1950
|
+
spatial_nearest(schools, source="sites_with_metro") -> ... - every
|
|
1951
|
+
later step's source is the previous step's output, not a
|
|
1952
|
+
crs_transform output. An earlier version of this function checked
|
|
1953
|
+
only the literal ref and treated every one of those later steps as
|
|
1954
|
+
"not traceable", which made this validator raise on a plan that was
|
|
1955
|
+
completely correct - caught by testing this exact function against
|
|
1956
|
+
accessibility_query_spec.py's own generated chain, not by inspection.
|
|
1957
|
+
|
|
1958
|
+
Still deliberately narrow on the OTHER side, though: this only walks
|
|
1959
|
+
through the vector-preserving "source" role of a chain of distance
|
|
1960
|
+
ops, never through a join, a filter combining two layers, or any
|
|
1961
|
+
other operation that doesn't obviously preserve a single input's CRS -
|
|
1962
|
+
those remain untraceable (None), which is the conservative direction
|
|
1963
|
+
to be wrong in.
|
|
1964
|
+
"""
|
|
1965
|
+
op = ops_by_output.get(ref)
|
|
1966
|
+
if op is None:
|
|
1967
|
+
return None
|
|
1968
|
+
|
|
1969
|
+
if op.op == "crs_transform":
|
|
1970
|
+
target_crs = op.params.get("target_crs")
|
|
1971
|
+
return str(target_crs) if target_crs else None
|
|
1972
|
+
|
|
1973
|
+
roles = _DISTANCE_OPS_VECTOR_ROLES.get(op.op)
|
|
1974
|
+
if roles is not None:
|
|
1975
|
+
this_role, _other_role = roles
|
|
1976
|
+
upstream_ref = op.inputs.get(this_role)
|
|
1977
|
+
if upstream_ref:
|
|
1978
|
+
return _crs_transform_target_crs(str(upstream_ref), ops_by_output)
|
|
1979
|
+
|
|
1980
|
+
return None
|
|
1981
|
+
|
|
1982
|
+
|
|
1983
|
+
def _validate_distance_op_crs_symmetry(spec: QuerySpec) -> None:
|
|
1984
|
+
"""
|
|
1985
|
+
Catch a distance/nearest-neighbor operation whose two vector inputs
|
|
1986
|
+
were reprojected asymmetrically - one just-reprojected via
|
|
1987
|
+
crs_transform, the other not (or reprojected to a different CRS).
|
|
1988
|
+
|
|
1989
|
+
Distance here is computed from raw geometry coordinates with zero CRS
|
|
1990
|
+
awareness (see calculate_distances/find_nearest_neighbors). Reprojecting
|
|
1991
|
+
only the source/site layer and leaving the target/amenity layer in its
|
|
1992
|
+
original CRS - typically EPSG:4326 from the source upload - produces a
|
|
1993
|
+
"distance" between two points in different CRSs: a large, consistent,
|
|
1994
|
+
completely bogus number, not an error, because nothing before this
|
|
1995
|
+
check ever compared the two layers' actual CRSs.
|
|
1996
|
+
|
|
1997
|
+
Deliberately conservative, same posture as
|
|
1998
|
+
_validate_score_features_field_chaining: only fires when this module
|
|
1999
|
+
can see BOTH refs' immediate CRS provenance disagree (see
|
|
2000
|
+
_crs_transform_target_crs's docstring for exactly what "immediate"
|
|
2001
|
+
means here). A ref this module can't trace to a crs_transform output
|
|
2002
|
+
at all - already in a metric CRS from its source, for instance - is
|
|
2003
|
+
left unvalidated rather than guessed at.
|
|
2004
|
+
"""
|
|
2005
|
+
ops_by_output: dict[str, OperationSpec] = {
|
|
2006
|
+
op.output: op for op in spec.operations if op.output
|
|
2007
|
+
}
|
|
2008
|
+
|
|
2009
|
+
for op in spec.operations:
|
|
2010
|
+
roles = _DISTANCE_OPS_VECTOR_ROLES.get(op.op)
|
|
2011
|
+
if roles is None:
|
|
2012
|
+
continue
|
|
2013
|
+
|
|
2014
|
+
this_role, other_role = roles
|
|
2015
|
+
this_ref = op.inputs.get(this_role)
|
|
2016
|
+
other_ref = op.inputs.get(other_role)
|
|
2017
|
+
if not this_ref or not other_ref:
|
|
2018
|
+
continue
|
|
2019
|
+
|
|
2020
|
+
this_crs = _crs_transform_target_crs(str(this_ref), ops_by_output)
|
|
2021
|
+
other_crs = _crs_transform_target_crs(str(other_ref), ops_by_output)
|
|
2022
|
+
|
|
2023
|
+
if this_crs is None and other_crs is None:
|
|
2024
|
+
continue
|
|
2025
|
+
|
|
2026
|
+
if this_crs == other_crs:
|
|
2027
|
+
continue
|
|
2028
|
+
|
|
2029
|
+
raise LLMSpecGenerationError(
|
|
2030
|
+
f"{op.op!r} (output={op.output!r}) reads {this_role}={this_ref!r} "
|
|
2031
|
+
f"(reprojected to {this_crs!r}) and {other_role}={other_ref!r} "
|
|
2032
|
+
f"(reprojected to {other_crs!r}) - these do not match. Every "
|
|
2033
|
+
"layer feeding a distance/nearest-neighbor operation must be "
|
|
2034
|
+
"reprojected with crs_transform to the SAME target CRS before "
|
|
2035
|
+
"the operation runs, or the resulting distance is computed "
|
|
2036
|
+
"between points in two different CRSs and is meaningless. See "
|
|
2037
|
+
"the 'any distance/nearest-neighbor operation needs BOTH of "
|
|
2038
|
+
"its vector inputs reprojected' guidance."
|
|
2039
|
+
)
|
|
2040
|
+
|
|
2041
|
+
|
|
1823
2042
|
class LLMQuerySpecGenerator:
|
|
1824
2043
|
def __init__(
|
|
1825
2044
|
self,
|
|
@@ -1868,7 +2087,9 @@ class LLMQuerySpecGenerator:
|
|
|
1868
2087
|
spec = query_spec_from_dict(data, raw_query_fallback=raw_query)
|
|
1869
2088
|
spec = normalize_llm_query_spec_for_planning(spec)
|
|
1870
2089
|
_validate_operation_input_roles(spec)
|
|
2090
|
+
_validate_score_features_factor_types(spec)
|
|
1871
2091
|
_validate_score_features_field_chaining(spec)
|
|
2092
|
+
_validate_distance_op_crs_symmetry(spec)
|
|
1872
2093
|
return spec
|
|
1873
2094
|
|
|
1874
2095
|
|
{smart_spatial_system-0.2.2 → smart_spatial_system-0.2.4}/orchestrator/planning/op_catalog.py
RENAMED
|
@@ -85,6 +85,10 @@ _NEAREST_PARAM_MAP = {
|
|
|
85
85
|
"precision": "precision",
|
|
86
86
|
"include_target_geometry": "include_target_geometry",
|
|
87
87
|
"source_crs": "source_crs",
|
|
88
|
+
# Passing both source_crs and target_crs lets find_nearest_neighbors
|
|
89
|
+
# catch a source/target CRS mismatch and raise instead of silently
|
|
90
|
+
# computing a meaningless planar distance - see its docstring.
|
|
91
|
+
"target_crs": "target_crs",
|
|
88
92
|
# Lets a plan chain several nearest-neighbour steps over the same
|
|
89
93
|
# features, each writing its own distance field - see the capability's
|
|
90
94
|
# docstring.
|
|
@@ -342,6 +346,10 @@ OP_CATALOG: dict[str, OpDescriptor] = {
|
|
|
342
346
|
"precision": "precision",
|
|
343
347
|
"drop_failed": "drop_failed",
|
|
344
348
|
"source_crs": "source_crs",
|
|
349
|
+
# Passing both source_crs and target_crs lets calculate_distances
|
|
350
|
+
# catch a source/target CRS mismatch and raise instead of
|
|
351
|
+
# silently computing a meaningless planar distance.
|
|
352
|
+
"target_crs": "target_crs",
|
|
345
353
|
"metadata": "metadata",
|
|
346
354
|
},
|
|
347
355
|
output_type="vector",
|
|
@@ -713,6 +713,51 @@ def _is_geographic_crs(value: Any) -> bool:
|
|
|
713
713
|
}
|
|
714
714
|
|
|
715
715
|
|
|
716
|
+
def _raise_if_crs_mismatch(
|
|
717
|
+
*,
|
|
718
|
+
source_crs: str | None,
|
|
719
|
+
target_crs: str | None,
|
|
720
|
+
capability_name: str,
|
|
721
|
+
) -> None:
|
|
722
|
+
"""
|
|
723
|
+
Raise if source_crs and target_crs are both supplied and don't match.
|
|
724
|
+
|
|
725
|
+
Distance/nearest-neighbor calculation here works on raw geometry
|
|
726
|
+
coordinates with zero CRS awareness - it has no way to notice on its
|
|
727
|
+
own that source_features and target_features are in different CRSs
|
|
728
|
+
(e.g. only the source layer was reprojected with crs_transform before
|
|
729
|
+
this call, or the two calls in a plan used different target CRSs).
|
|
730
|
+
Left unchecked, that produces a number - not an error - that is
|
|
731
|
+
physically meaningless: a planar distance between a point in metres
|
|
732
|
+
and a point in degrees, indistinguishable from a real distance
|
|
733
|
+
without inspecting the value by hand. This is opt-in (only checked
|
|
734
|
+
when the caller supplies BOTH hints) rather than required, so callers
|
|
735
|
+
that don't pass CRS hints at all keep today's behaviour unchanged.
|
|
736
|
+
|
|
737
|
+
Comparison is a normalized (stripped, uppercased) string match, not
|
|
738
|
+
true CRS equivalence - "EPSG:4326" and "CRS:84" describe the same CRS
|
|
739
|
+
but won't match each other here. That is a deliberately conservative
|
|
740
|
+
trade-off: false negatives (a real mismatch expressed as equivalent-
|
|
741
|
+
but-differently-spelled CRSs, missed) are possible, but false
|
|
742
|
+
positives (correctly matching CRSs rejected) are not, since this
|
|
743
|
+
module has no CRS-equivalence table to consult.
|
|
744
|
+
"""
|
|
745
|
+
if not source_crs or not target_crs:
|
|
746
|
+
return
|
|
747
|
+
|
|
748
|
+
if str(source_crs).strip().upper() == str(target_crs).strip().upper():
|
|
749
|
+
return
|
|
750
|
+
|
|
751
|
+
raise ValueError(
|
|
752
|
+
f"{capability_name}: source_crs={source_crs!r} and "
|
|
753
|
+
f"target_crs={target_crs!r} do not match. Computing distance "
|
|
754
|
+
"between features in two different CRSs produces a meaningless "
|
|
755
|
+
"number, not an error - reproject both source_features and "
|
|
756
|
+
"target_features to the same CRS with crs_transform first, then "
|
|
757
|
+
"pass matching source_crs/target_crs here."
|
|
758
|
+
)
|
|
759
|
+
|
|
760
|
+
|
|
716
761
|
def _make_distance_feature(
|
|
717
762
|
*,
|
|
718
763
|
source_feature: dict[str, Any],
|
|
@@ -846,6 +891,7 @@ def _build_vector_metadata(features: list[dict[str, Any]]) -> dict[str, Any]:
|
|
|
846
891
|
"precision",
|
|
847
892
|
"drop_failed",
|
|
848
893
|
"source_crs",
|
|
894
|
+
"target_crs",
|
|
849
895
|
"metadata",
|
|
850
896
|
],
|
|
851
897
|
output_kind="vector",
|
|
@@ -871,6 +917,7 @@ def calculate_distances(
|
|
|
871
917
|
precision: int | None = None,
|
|
872
918
|
drop_failed: bool | None = None,
|
|
873
919
|
source_crs: str | None = None,
|
|
920
|
+
target_crs: str | None = None,
|
|
874
921
|
metadata: dict[str, Any] | None = None,
|
|
875
922
|
) -> VectorOut:
|
|
876
923
|
"""
|
|
@@ -890,7 +937,19 @@ def calculate_distances(
|
|
|
890
937
|
drop_failed:
|
|
891
938
|
If True, failed source/pair results are removed.
|
|
892
939
|
source_crs:
|
|
893
|
-
CRS hint
|
|
940
|
+
CRS hint for source_features.
|
|
941
|
+
target_crs:
|
|
942
|
+
CRS hint for target_features.
|
|
943
|
+
|
|
944
|
+
Distance here is computed from raw geometry coordinates with
|
|
945
|
+
no CRS awareness at all - if source_features and
|
|
946
|
+
target_features are actually in different CRSs, the result is
|
|
947
|
+
a number, not an error: meaningless, but indistinguishable
|
|
948
|
+
from a real distance without inspecting it by hand. Supplying
|
|
949
|
+
both source_crs and target_crs lets this function catch that
|
|
950
|
+
case and raise instead of returning it. Neither hint changes
|
|
951
|
+
how distance is computed; only crs_transform actually
|
|
952
|
+
reprojects data.
|
|
894
953
|
metadata:
|
|
895
954
|
Optional metadata to merge.
|
|
896
955
|
|
|
@@ -920,8 +979,15 @@ def calculate_distances(
|
|
|
920
979
|
)
|
|
921
980
|
|
|
922
981
|
final_source_crs = pick_first(source_crs, config.get("source_crs"), default=None)
|
|
982
|
+
final_target_crs = pick_first(target_crs, config.get("target_crs"), default=None)
|
|
923
983
|
warn_if_geographic_crs = bool(config.get("warn_if_geographic_crs", True))
|
|
924
984
|
|
|
985
|
+
_raise_if_crs_mismatch(
|
|
986
|
+
source_crs=final_source_crs,
|
|
987
|
+
target_crs=final_target_crs,
|
|
988
|
+
capability_name="calculate_distances",
|
|
989
|
+
)
|
|
990
|
+
|
|
925
991
|
preserve_properties = bool(config.get("preserve_properties", True))
|
|
926
992
|
fields = _configured_fields(config)
|
|
927
993
|
|
|
@@ -1102,6 +1168,7 @@ def calculate_distances(
|
|
|
1102
1168
|
"coordinate_precision": final_precision,
|
|
1103
1169
|
"drop_failed": final_drop_failed,
|
|
1104
1170
|
"source_crs": final_source_crs,
|
|
1171
|
+
"target_crs": final_target_crs,
|
|
1105
1172
|
"planar_only": True,
|
|
1106
1173
|
"warning": geographic_warning,
|
|
1107
1174
|
"source_feature_count": len(source_items),
|
|
@@ -228,7 +228,29 @@ def _score_factor(properties: dict[str, Any], factor: dict[str, Any]) -> tuple[f
|
|
|
228
228
|
if not isinstance(factor, dict):
|
|
229
229
|
raise ValueError("Each scoring factor must be a dict.")
|
|
230
230
|
|
|
231
|
-
|
|
231
|
+
raw_factor_type = factor.get("type")
|
|
232
|
+
if not raw_factor_type:
|
|
233
|
+
# A missing "type" used to default to "boolean" silently. For any
|
|
234
|
+
# factor scoring a non-boolean field - a distance, most commonly -
|
|
235
|
+
# that produces a wrong, near-constant score (0.0 whenever the
|
|
236
|
+
# field is falsy, which for a distance means "exactly zero") with
|
|
237
|
+
# no error at all: this is how a whole batch of LLM-generated
|
|
238
|
+
# scoring specs that omitted "type" on a distance factor came out
|
|
239
|
+
# 0.0 for every feature, indistinguishable from a real degenerate
|
|
240
|
+
# result. "boolean" is a valid, explicit choice (still supported
|
|
241
|
+
# below) - it must never be the unstated default for a field whose
|
|
242
|
+
# actual meaning this function has no way to guess.
|
|
243
|
+
field_name = factor.get("field") or factor.get("name") or "<unnamed>"
|
|
244
|
+
raise ValueError(
|
|
245
|
+
f"Scoring factor for field {field_name!r} has no 'type'. There "
|
|
246
|
+
"is no safe default - specify one explicitly: 'boolean', "
|
|
247
|
+
"'boolean_bonus', 'inverse_distance', 'risk_level', "
|
|
248
|
+
"'inverse_level', 'threshold', 'condition', 'direct', "
|
|
249
|
+
"'numeric', or 'inverse_numeric'. A distance field almost "
|
|
250
|
+
"always wants 'inverse_distance' with 'max_distance' set."
|
|
251
|
+
)
|
|
252
|
+
|
|
253
|
+
factor_type = str(raw_factor_type)
|
|
232
254
|
name = str(factor.get("name") or factor.get("field") or factor_type)
|
|
233
255
|
field = str(factor.get("field") or "")
|
|
234
256
|
value = _get_property(properties, field) if field else None
|
|
@@ -45,6 +45,7 @@ from plugins.distance_calculator import (
|
|
|
45
45
|
_calculate_distance,
|
|
46
46
|
_geometry_bbox,
|
|
47
47
|
_is_geographic_crs,
|
|
48
|
+
_raise_if_crs_mismatch,
|
|
48
49
|
_validate_engine,
|
|
49
50
|
)
|
|
50
51
|
|
|
@@ -356,6 +357,7 @@ def _build_vector_metadata(features: list[dict[str, Any]]) -> dict[str, Any]:
|
|
|
356
357
|
"drop_unmatched",
|
|
357
358
|
"include_target_geometry",
|
|
358
359
|
"source_crs",
|
|
360
|
+
"target_crs",
|
|
359
361
|
"metadata",
|
|
360
362
|
],
|
|
361
363
|
output_kind="vector",
|
|
@@ -383,6 +385,7 @@ def find_nearest_neighbors(
|
|
|
383
385
|
drop_unmatched: bool | None = None,
|
|
384
386
|
include_target_geometry: bool | None = None,
|
|
385
387
|
source_crs: str | None = None,
|
|
388
|
+
target_crs: str | None = None,
|
|
386
389
|
distance_field: str | None = None,
|
|
387
390
|
metadata: dict[str, Any] | None = None,
|
|
388
391
|
) -> VectorOut:
|
|
@@ -407,7 +410,20 @@ def find_nearest_neighbors(
|
|
|
407
410
|
include_target_geometry:
|
|
408
411
|
If True, target geometry is copied into output properties.
|
|
409
412
|
source_crs:
|
|
410
|
-
CRS hint
|
|
413
|
+
CRS hint for source_features.
|
|
414
|
+
target_crs:
|
|
415
|
+
CRS hint for target_features.
|
|
416
|
+
|
|
417
|
+
Distance here is computed from raw geometry coordinates with no
|
|
418
|
+
CRS awareness at all - if source_features and target_features
|
|
419
|
+
are actually in different CRSs (e.g. only one of them was
|
|
420
|
+
reprojected with crs_transform before this call), the result
|
|
421
|
+
is a number, not an error: meaningless, but indistinguishable
|
|
422
|
+
from a real distance without inspecting it by hand. Supplying
|
|
423
|
+
both source_crs and target_crs lets this function catch that
|
|
424
|
+
case and raise instead of returning it - see the raise below.
|
|
425
|
+
Neither hint changes how distance is computed; only
|
|
426
|
+
crs_transform actually reprojects data.
|
|
411
427
|
distance_field:
|
|
412
428
|
Optional output field name for the computed distance,
|
|
413
429
|
overriding the configured default (config/plugins/
|
|
@@ -460,8 +476,15 @@ def find_nearest_neighbors(
|
|
|
460
476
|
)
|
|
461
477
|
|
|
462
478
|
final_source_crs = pick_first(source_crs, config.get("source_crs"), default=None)
|
|
479
|
+
final_target_crs = pick_first(target_crs, config.get("target_crs"), default=None)
|
|
463
480
|
warn_if_geographic_crs = bool(config.get("warn_if_geographic_crs", True))
|
|
464
481
|
|
|
482
|
+
_raise_if_crs_mismatch(
|
|
483
|
+
source_crs=final_source_crs,
|
|
484
|
+
target_crs=final_target_crs,
|
|
485
|
+
capability_name="find_nearest_neighbors",
|
|
486
|
+
)
|
|
487
|
+
|
|
465
488
|
preserve_properties = bool(config.get("preserve_properties", True))
|
|
466
489
|
fields = _configured_fields(config)
|
|
467
490
|
|
|
@@ -594,6 +617,7 @@ def find_nearest_neighbors(
|
|
|
594
617
|
"drop_unmatched": final_drop_unmatched,
|
|
595
618
|
"include_target_geometry": final_include_target_geometry,
|
|
596
619
|
"source_crs": final_source_crs,
|
|
620
|
+
"target_crs": final_target_crs,
|
|
597
621
|
"planar_only": True,
|
|
598
622
|
"warning": geographic_warning,
|
|
599
623
|
"source_feature_count": len(source_items),
|
|
@@ -12,7 +12,7 @@ build-backend = "setuptools.build_meta"
|
|
|
12
12
|
# "Open design questions" for why a namespace migration was deliberately
|
|
13
13
|
# not done here.
|
|
14
14
|
name = "smart_spatial_system"
|
|
15
|
-
version = "0.2.
|
|
15
|
+
version = "0.2.4"
|
|
16
16
|
description = "Plugin-based GeoAI backend: natural-language questions become QuerySpecs, DAG plans, and map/table/report outputs."
|
|
17
17
|
readme = "README.md"
|
|
18
18
|
requires-python = ">=3.11"
|
|
@@ -191,7 +191,17 @@ def build_accessibility_query_spec(
|
|
|
191
191
|
OperationSpec(
|
|
192
192
|
op="nearest_neighbor",
|
|
193
193
|
inputs={"source": current_sites_ref, "target": amenity_metric_ref},
|
|
194
|
-
|
|
194
|
+
# Both sides were just reprojected to target_crs above, so
|
|
195
|
+
# these are always equal here - passed anyway so
|
|
196
|
+
# find_nearest_neighbors' own source/target CRS mismatch
|
|
197
|
+
# check (plugins/distance_calculator.py) protects this
|
|
198
|
+
# call too, not only hand-written or LLM-generated plans.
|
|
199
|
+
params={
|
|
200
|
+
"k": 1,
|
|
201
|
+
"distance_field": amenity.distance_field,
|
|
202
|
+
"source_crs": target_crs,
|
|
203
|
+
"target_crs": target_crs,
|
|
204
|
+
},
|
|
195
205
|
output=enriched_ref,
|
|
196
206
|
)
|
|
197
207
|
)
|