smart-spatial-system 0.2.0__tar.gz → 0.2.2__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.0/smart_spatial_system.egg-info → smart_spatial_system-0.2.2}/PKG-INFO +1 -1
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/orchestrator/planning/llm_spec_generator.py +312 -64
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/pyproject.toml +1 -1
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2/smart_spatial_system.egg-info}/PKG-INFO +1 -1
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_llm_spec_generator.py +473 -100
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/LICENSE +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/README.md +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/api/__init__.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/api/auth.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/api/main.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/api/routers/__init__.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/api/routers/data_source_connectors.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/api/routers/data_sources.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/api/routers/plugins_settings.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/api/routers/projects.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/api/routers/query_planner.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/api/routers/requests_outputs.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/api/routers/system.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/api/routers/uploads.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/api/routers/weights.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/api/support.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/config/__init__.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/config/plugins/__init__.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/config/plugins/area_perimeter_calc.example.yaml +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/config/plugins/area_perimeter_calc.yaml +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/config/plugins/attribute_statistics.example.yaml +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/config/plugins/attribute_statistics.yaml +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/config/plugins/band_math.example.yaml +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/config/plugins/band_math.yaml +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/config/plugins/buffer_analysis.example.yaml +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/config/plugins/buffer_analysis.yaml +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/config/plugins/centroid_extractor.example.yaml +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/config/plugins/centroid_extractor.yaml +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/config/plugins/core_vector.example.yaml +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/config/plugins/core_vector.yaml +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/config/plugins/crs_transformer.example.yaml +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/config/plugins/crs_transformer.yaml +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/config/plugins/data_writer_exporter.example.yaml +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/config/plugins/data_writer_exporter.yaml +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/config/plugins/dissolve_aggregator.example.yaml +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/config/plugins/dissolve_aggregator.yaml +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/config/plugins/distance_calculator.example.yaml +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/config/plugins/distance_calculator.yaml +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/config/plugins/feature_enrichment.example.yaml +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/config/plugins/feature_enrichment.yaml +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/config/plugins/feature_scoring.example.yaml +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/config/plugins/feature_scoring.yaml +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/config/plugins/geocoding_resolver.example.yaml +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/config/plugins/geocoding_resolver.yaml +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/config/plugins/geometry_validator.example.yaml +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/config/plugins/geometry_validator.yaml +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/config/plugins/local_raster_loader.example.yaml +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/config/plugins/local_raster_loader.yaml +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/config/plugins/local_vector_loader.example.yaml +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/config/plugins/local_vector_loader.yaml +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/config/plugins/ndvi_calculator.example.yaml +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/config/plugins/ndvi_calculator.yaml +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/config/plugins/nearest_neighbor.example.yaml +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/config/plugins/nearest_neighbor.yaml +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/config/plugins/postgis_connector.example.yaml +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/config/plugins/postgis_connector.yaml +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/config/plugins/raster_clip_mask.example.yaml +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/config/plugins/raster_clip_mask.yaml +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/config/plugins/raster_reclassify.example.yaml +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/config/plugins/raster_reclassify.yaml +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/config/plugins/raster_statistics.example.yaml +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/config/plugins/raster_statistics.yaml +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/config/plugins/raster_threshold.example.yaml +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/config/plugins/raster_threshold.yaml +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/config/plugins/raster_to_vector.example.yaml +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/config/plugins/raster_to_vector.yaml +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/config/plugins/risk_enrichment.example.yaml +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/config/plugins/risk_enrichment.yaml +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/config/plugins/slope_aspect.yaml +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/config/plugins/spatial_intersection.example.yaml +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/config/plugins/spatial_intersection.yaml +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/config/plugins/spatial_join.example.yaml +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/config/plugins/spatial_join.yaml +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/config/plugins/spatial_predicate.example.yaml +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/config/plugins/spatial_predicate.yaml +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/config/plugins/spatial_query_filter.example.yaml +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/config/plugins/spatial_query_filter.yaml +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/config/plugins/spectral_indices.example.yaml +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/config/plugins/spectral_indices.yaml +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/config/plugins/wms_wfs_fetcher.example.yaml +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/config/plugins/wms_wfs_fetcher.yaml +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/config/plugins/zonal_statistics.example.yaml +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/config/plugins/zonal_statistics.yaml +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/orchestrator/__init__.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/orchestrator/audit.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/orchestrator/capability_registry.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/orchestrator/capability_router.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/orchestrator/capability_scoring.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/orchestrator/data_source_service.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/orchestrator/error_contract.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/orchestrator/feedback.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/orchestrator/feedback_proposal_service.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/orchestrator/input_error_mapping.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/orchestrator/input_reference_resolver.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/orchestrator/kernel_artifacts.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/orchestrator/learning_signals.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/orchestrator/llm_client.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/orchestrator/llm_gate.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/orchestrator/llm_intent_planner.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/orchestrator/loader_plugin_contract.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/orchestrator/map_layer_service.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/orchestrator/map_layers.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/orchestrator/models.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/orchestrator/natural_query_runner.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/orchestrator/output_service.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/orchestrator/output_storage.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/orchestrator/pipeline_executor.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/orchestrator/plan_builder.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/orchestrator/planning/__init__.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/orchestrator/planning/capability_resolver.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/orchestrator/planning/dag.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/orchestrator/planning/dag_executor.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/orchestrator/planning/error_mapping.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/orchestrator/planning/kernel_execution_bridge.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/orchestrator/planning/kernel_plan_adapter.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/orchestrator/planning/llm_query_spec.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/orchestrator/planning/op_catalog.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/orchestrator/planning/output_parity.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/orchestrator/planning/planner.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/orchestrator/planning/postgis_semantic_resolver.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/orchestrator/planning/query_spec_contract.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/orchestrator/planning/report_spec.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/orchestrator/planning/runner.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/orchestrator/planning/semantic_planning_context.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/orchestrator/planning/spec.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/orchestrator/plugin_config_store.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/orchestrator/plugin_error_mapping.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/orchestrator/plugin_modules.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/orchestrator/plugin_runtime_service.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/orchestrator/plugin_state.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/orchestrator/production_response.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/orchestrator/project_service.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/orchestrator/project_store.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/orchestrator/provider_error_mapping.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/orchestrator/query_execution_service.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/orchestrator/query_parser.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/orchestrator/request_history_service.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/orchestrator/response_assembler.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/orchestrator/response_builder.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/orchestrator/router_decision.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/orchestrator/routing_aware_natural_query_runner.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/orchestrator/routing_aware_plan_builder.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/orchestrator/runtime_paths.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/orchestrator/service.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/orchestrator/statistics.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/orchestrator/upload_service.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/orchestrator/upload_storage.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/orchestrator/weight_proposals.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/orchestrator/weight_store_persistence.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/orchestrator/weighted_router.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/plugins/__init__.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/plugins/_shared/__init__.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/plugins/_shared/local_path_validation.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/plugins/_shared/numeric_validation.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/plugins/_shared/plugin_config.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/plugins/area_perimeter_calc.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/plugins/attribute_statistics.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/plugins/band_math.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/plugins/buffer_analysis.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/plugins/centroid_extractor.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/plugins/core_vector.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/plugins/crs_transformer.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/plugins/data_writer_exporter.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/plugins/dissolve_aggregator.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/plugins/distance_calculator.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/plugins/feature_enrichment.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/plugins/feature_scoring.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/plugins/geocoding_resolver.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/plugins/geometry_validator.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/plugins/local_raster_loader.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/plugins/local_vector_loader.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/plugins/ndvi_analysis.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/plugins/ndvi_calculator.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/plugins/nearest_neighbor.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/plugins/pdf_renderer.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/plugins/postgis_connector.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/plugins/raster_clip_mask.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/plugins/raster_reclassify.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/plugins/raster_statistics.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/plugins/raster_threshold.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/plugins/raster_to_vector.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/plugins/real_estate_scoring.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/plugins/real_estate_spatial_enrichment.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/plugins/report_builder.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/plugins/risk_enrichment.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/plugins/slope_aspect.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/plugins/spatial_intersection.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/plugins/spatial_join.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/plugins/spatial_predicate.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/plugins/spatial_query_filter.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/plugins/spectral_indices.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/plugins/wms_wfs_fetcher.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/plugins/zonal_statistics.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/setup.cfg +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/smart_spatial_system/__init__.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/smart_spatial_system/__main__.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/smart_spatial_system/application/__init__.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/smart_spatial_system/application/services/__init__.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/smart_spatial_system/application/services/data_source_service.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/smart_spatial_system/application/services/feedback_proposal_service.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/smart_spatial_system/application/services/llm_intent_adapter.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/smart_spatial_system/application/services/map_layer_service.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/smart_spatial_system/application/services/output_service.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/smart_spatial_system/application/services/planning_execution_policy.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/smart_spatial_system/application/services/planning_response_adapter.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/smart_spatial_system/application/services/plugin_runtime_service.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/smart_spatial_system/application/services/project_service.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/smart_spatial_system/application/services/query_execution/__init__.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/smart_spatial_system/application/services/query_execution/accessibility_query_spec.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/smart_spatial_system/application/services/query_execution/direct_query_dispatch.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/smart_spatial_system/application/services/query_execution/natural_query_context.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/smart_spatial_system/application/services/query_execution/natural_query_dispatch.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/smart_spatial_system/application/services/query_execution/natural_query_execution.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/smart_spatial_system/application/services/query_execution/natural_query_failure.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/smart_spatial_system/application/services/query_execution/natural_query_persistence.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/smart_spatial_system/application/services/query_execution/planning_context.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/smart_spatial_system/application/services/query_execution/planning_execution.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/smart_spatial_system/application/services/query_execution/planning_persistence.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/smart_spatial_system/application/services/query_execution/planning_response.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/smart_spatial_system/application/services/query_execution/postgis_planning_context.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/smart_spatial_system/application/services/query_execution/real_estate_analysis_inspector.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/smart_spatial_system/application/services/query_execution/real_estate_classifier.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/smart_spatial_system/application/services/query_execution/real_estate_context.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/smart_spatial_system/application/services/query_execution/real_estate_document_renderer.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/smart_spatial_system/application/services/query_execution/real_estate_missing_inputs.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/smart_spatial_system/application/services/query_execution/real_estate_ranking_artifacts.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/smart_spatial_system/application/services/query_execution/real_estate_ranking_direct_handler.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/smart_spatial_system/application/services/query_execution/real_estate_ranking_execution.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/smart_spatial_system/application/services/query_execution/real_estate_ranking_query_spec.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/smart_spatial_system/application/services/query_execution/real_estate_ranking_response.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/smart_spatial_system/application/services/query_execution/real_estate_report_payload.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/smart_spatial_system/application/services/query_execution/real_estate_scoring.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/smart_spatial_system/application/services/query_execution_service.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/smart_spatial_system/application/services/query_spec_enrichment.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/smart_spatial_system/application/services/real_estate_spatial_helpers.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/smart_spatial_system/application/services/request_history_service.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/smart_spatial_system/application/services/system_status_query_handler.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/smart_spatial_system/application/services/upload_service.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/smart_spatial_system/application/services/vector_display_handler.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/smart_spatial_system/application/services/vector_geojson_helpers.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/smart_spatial_system/application/services/vector_query_classifier.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/smart_spatial_system/cli.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/smart_spatial_system/domain/__init__.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/smart_spatial_system/domain/contracts/__init__.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/smart_spatial_system/domain/models/__init__.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/smart_spatial_system/infrastructure/__init__.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/smart_spatial_system/infrastructure/stores/__init__.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/smart_spatial_system/interfaces/__init__.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/smart_spatial_system/interfaces/api/__init__.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/smart_spatial_system/interfaces/api/routers/__init__.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/smart_spatial_system/plugins/__init__.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/smart_spatial_system/runtime/__init__.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/smart_spatial_system/shared/__init__.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/smart_spatial_system/workflows/__init__.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/smart_spatial_system/workflows/ndvi/__init__.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/smart_spatial_system/workflows/real_estate/__init__.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/smart_spatial_system.egg-info/SOURCES.txt +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/smart_spatial_system.egg-info/dependency_links.txt +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/smart_spatial_system.egg-info/entry_points.txt +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/smart_spatial_system.egg-info/requires.txt +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/smart_spatial_system.egg-info/top_level.txt +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/templates/__init__.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/templates/reports/__init__.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/templates/reports/real_estate_report.html +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_accessibility_query_spec.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_api_auth.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_api_contract_smoke.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_api_data_source_connectors_e2e.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_api_map_layers.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_api_mvp.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_api_outputs.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_api_projects.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_api_structured_error_normalization.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_api_upload_plugin_resolver.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_api_uploads.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_area_perimeter_calc.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_attribute_statistics.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_band_math.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_buffer_analysis.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_centroid_extractor.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_cli.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_crs_transformer.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_data_source_service.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_data_writer_exporter.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_deterministic_planner.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_dissolve_aggregator.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_distance_calculator.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_document_file_report_contract.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_end_to_end_natural_query_pipeline.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_error_contract.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_feature_enrichment.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_feature_scoring.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_frontend_api_surface_contract.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_geocoding_resolver.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_geocoding_resolver_error_redaction.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_geometry_validator.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_input_error_mapping.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_input_reference_resolver.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_input_reference_resolver_contract.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_kernel_artifacts.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_kernel_execution_bridge.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_kernel_plan_adapter.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_llm_intent_adapter.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_llm_raster_queryspec_normalization.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_llm_spec_generator_prenormalize.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_llm_spec_generator_semantic_context.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_llm_spec_generator_semantic_query_database_enrich.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_llm_spec_generator_semantic_queryspec_repair.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_loader_plugin_contract.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_local_path_validation.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_local_raster_loader.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_local_raster_loader_contract.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_local_vector_loader.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_local_vector_loader_contract.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_map_layer_contract.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_map_layer_service.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_ndvi_calculator.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_nearest_neighbor.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_numeric_validation.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_op_catalog_semantic_aliases.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_orchestrator_audit.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_orchestrator_audit_integration.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_orchestrator_data_source_service_integration.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_orchestrator_feedback.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_orchestrator_feedback_integration.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_orchestrator_keyword_scoring_router.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_orchestrator_learning_signals.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_orchestrator_learning_signals_integration.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_orchestrator_llm_gate.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_orchestrator_llm_gate_integration.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_orchestrator_map_layer_service_integration.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_orchestrator_natural_query_pipeline.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_orchestrator_output_service_integration.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_orchestrator_production_response.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_orchestrator_production_response_integration.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_orchestrator_project_service_integration.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_orchestrator_query_execution_service_integration.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_orchestrator_registry_router.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_orchestrator_router_decision.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_orchestrator_router_decision_integration.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_orchestrator_routing_aware_plan_builder.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_orchestrator_runtime_paths.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_orchestrator_service.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_orchestrator_service_domain_boundary_contract.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_orchestrator_service_integration.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_orchestrator_service_postgis_dedup_contract.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_orchestrator_statistics.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_orchestrator_statistics_integration.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_orchestrator_upload_service_integration.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_orchestrator_weight_proposals.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_orchestrator_weight_proposals_integration.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_orchestrator_weight_store_persistence.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_orchestrator_weight_store_persistence_integration.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_orchestrator_weighted_router.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_orchestrator_weighted_router_integration.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_output_service.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_output_storage.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_pdf_renderer.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_phase3_kernel_registry_coverage.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_phase3_output_parity.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_phase3_postgis_provider_kernel_execution.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_planning_dag_executor.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_planning_dag_executor_async_capability.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_planning_error_mapping.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_planning_execution_policy.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_planning_raster_op_catalog_mapping.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_planning_raster_queryspec_execution.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_planning_registry_backed_raster_execution.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_planning_registry_backed_real_estate_execution.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_planning_runner.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_plugin_boundary_contract.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_plugin_config.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_plugin_config_store.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_plugin_error_mapping.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_plugin_modules.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_postgis_connector.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_postgis_connector_percent_escape.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_postgis_semantic_resolver.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_project_service.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_project_store.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_provider_error_mapping.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_query_dispatch_domain_boundary_contract.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_query_execution_postgis_planning_context.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_query_execution_service.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_query_execution_service_domain_import_boundary_contract.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_query_response_shape_golden.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_query_spec_enrichment.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_raster_capability_registry_contract.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_raster_clip_mask.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_raster_reclassify.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_raster_statistics.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_raster_threshold.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_raster_to_vector.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_real_estate_ranking_bridge.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_real_estate_ranking_golden.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_real_estate_ranking_query_spec_planning.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_real_estate_scoring_plugin.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_real_estate_spatial_enrichment_plugin.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_real_estate_spatial_helpers.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_report_builder.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_report_spec.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_request_document_download_contract.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_response_assembler.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_response_output_contract.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_risk_enrichment.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_runtime_paths.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_semantic_planning_context.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_service_auto_postgis_semantic_context.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_service_planning_artifacts.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_service_postgis_runtime_connection_injection.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_service_semantic_planning_context.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_service_strict_loader_contract.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_service_structured_error_normalization.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_slope_aspect.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_spatial_intersection.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_spatial_join.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_spatial_query_filter.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_spectral_indices.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_system_status_query_handler.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_upload_service.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_upload_storage.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_vector_display_handler.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_vector_geojson_helpers.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_vector_query_classifier.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_wms_wfs_fetcher.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_wms_wfs_fetcher_error_redaction.py +0 -0
- {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_zonal_statistics.py +0 -0
|
@@ -971,9 +971,34 @@ Return ONLY one JSON object with this shape:
|
|
|
971
971
|
"""
|
|
972
972
|
|
|
973
973
|
|
|
974
|
+
def _op_input_roles_reference() -> str:
|
|
975
|
+
"""
|
|
976
|
+
Every supported operation's required input roles - the exact keys
|
|
977
|
+
"inputs" must use for that operation - generated directly from
|
|
978
|
+
OP_CATALOG's input_map rather than hand-written per-operation
|
|
979
|
+
examples.
|
|
980
|
+
|
|
981
|
+
This exists because a hand-written example is exactly how distance_to
|
|
982
|
+
went undocumented here: "Important mappings" below spells out
|
|
983
|
+
filter_by_distance, filter_points_in_polygon and enrich_risk by hand,
|
|
984
|
+
but nobody added an entry when distance_to (source_features/
|
|
985
|
+
target_features, i.e. inputs "vector"/"target") was added to the
|
|
986
|
+
catalog, and the LLM repeatedly omitted "target" as a result. Deriving
|
|
987
|
+
this list from OP_CATALOG means a future operation can't silently go
|
|
988
|
+
undocumented the same way.
|
|
989
|
+
"""
|
|
990
|
+
lines = []
|
|
991
|
+
for name in list_supported_ops():
|
|
992
|
+
roles = list(get_op(name).input_map)
|
|
993
|
+
role_desc = ", ".join(roles) if roles else "(none)"
|
|
994
|
+
lines.append(f"- {name}: inputs keys = {{{role_desc}}}")
|
|
995
|
+
return "\n".join(lines)
|
|
996
|
+
|
|
997
|
+
|
|
974
998
|
def _domain_guidance() -> str:
|
|
975
999
|
supported = ", ".join(list_supported_ops())
|
|
976
1000
|
pending = ", ".join(list_pending_ops())
|
|
1001
|
+
input_roles = _op_input_roles_reference()
|
|
977
1002
|
|
|
978
1003
|
return f"""
|
|
979
1004
|
You are a planning assistant for a smart spatial analysis system.
|
|
@@ -988,6 +1013,12 @@ Your job:
|
|
|
988
1013
|
Supported operations:
|
|
989
1014
|
{supported}
|
|
990
1015
|
|
|
1016
|
+
Every operation REQUIRES exactly these "inputs" keys - an operation with a
|
|
1017
|
+
missing key fails to plan. This list is generated from the operation
|
|
1018
|
+
catalog itself, so trust it over any example below if the two ever
|
|
1019
|
+
disagree:
|
|
1020
|
+
{input_roles}
|
|
1021
|
+
|
|
991
1022
|
Pending operations, not executable yet:
|
|
992
1023
|
{pending}
|
|
993
1024
|
|
|
@@ -1021,6 +1052,45 @@ Important mappings:
|
|
|
1021
1052
|
- "score/rank":
|
|
1022
1053
|
use score_features then rank_features.
|
|
1023
1054
|
|
|
1055
|
+
- CRITICAL - scoring against MORE THAN ONE computed field (e.g. distance to
|
|
1056
|
+
several different amenities/references): each computation must be CHAINED
|
|
1057
|
+
onto the previous one's output, not all computed separately from the
|
|
1058
|
+
original base vector. score_features.inputs.vector must be the output of
|
|
1059
|
+
the LAST computation in the chain - the only ref that actually carries
|
|
1060
|
+
every field the scoring factors reference. A score_features op reading
|
|
1061
|
+
from the base vector, or from any computation earlier than the last one,
|
|
1062
|
+
is missing every field computed after that point, and every factor
|
|
1063
|
+
referencing a missing field silently scores 0 - this does not raise an
|
|
1064
|
+
error, so a degenerate all-zero/near-zero score on every feature is a
|
|
1065
|
+
sign this happened.
|
|
1066
|
+
|
|
1067
|
+
WRONG - three computations all read "sites", so only one field ever
|
|
1068
|
+
reaches score_features:
|
|
1069
|
+
spatial_nearest(source="sites", target="metro") -> "sites_with_metro"
|
|
1070
|
+
spatial_nearest(source="sites", target="schools") -> "sites_with_schools"
|
|
1071
|
+
spatial_nearest(source="sites", target="parks") -> "sites_with_parks"
|
|
1072
|
+
score_features(vector="sites") - WRONG: none of the three computed
|
|
1073
|
+
distance fields are on "sites" itself.
|
|
1074
|
+
|
|
1075
|
+
CORRECT - each step reads the PREVIOUS step's output, so fields
|
|
1076
|
+
accumulate onto one ref:
|
|
1077
|
+
spatial_nearest(source="sites", target="metro",
|
|
1078
|
+
params={{"distance_field": "distance_to_metro"}}) -> "sites_with_metro"
|
|
1079
|
+
spatial_nearest(source="sites_with_metro", target="schools",
|
|
1080
|
+
params={{"distance_field": "distance_to_schools"}}) -> "sites_with_schools"
|
|
1081
|
+
spatial_nearest(source="sites_with_schools", target="parks",
|
|
1082
|
+
params={{"distance_field": "distance_to_parks"}}) -> "sites_with_parks"
|
|
1083
|
+
score_features(vector="sites_with_parks") - CORRECT: this ref alone
|
|
1084
|
+
carries distance_to_metro, distance_to_schools AND distance_to_parks,
|
|
1085
|
+
because each step's "source" was the previous step's output, not
|
|
1086
|
+
"sites" again. Set params.distance_field on each spatial_nearest call
|
|
1087
|
+
so the fields get distinct names instead of overwriting each other.
|
|
1088
|
+
|
|
1089
|
+
If two computations genuinely cannot be chained (they operate on
|
|
1090
|
+
unrelated feature sets that must be merged by a shared key rather than
|
|
1091
|
+
by being the same features), use join_feature_properties to merge them
|
|
1092
|
+
before scoring instead of chaining.
|
|
1093
|
+
|
|
1024
1094
|
- If user asks for PDF/report but report plugin is not executable yet:
|
|
1025
1095
|
include outputs with kind="report", format="pdf".
|
|
1026
1096
|
Do not invent unsupported operation nodes.
|
|
@@ -1109,64 +1179,6 @@ def build_llm_messages(
|
|
|
1109
1179
|
]
|
|
1110
1180
|
|
|
1111
1181
|
|
|
1112
|
-
def _default_real_estate_scoring_spec() -> dict[str, Any]:
|
|
1113
|
-
"""
|
|
1114
|
-
Default MVP scoring spec for real-estate ranking.
|
|
1115
|
-
|
|
1116
|
-
This is used as a safety fallback when LLM correctly asks for scoring
|
|
1117
|
-
but forgets to provide scoring_spec.
|
|
1118
|
-
|
|
1119
|
-
Notes:
|
|
1120
|
-
- Some fields may be created by previous plugins or future enrichment plugins.
|
|
1121
|
-
- Missing fields simply receive factor score 0 by score_features.
|
|
1122
|
-
"""
|
|
1123
|
-
return {
|
|
1124
|
-
"output_field": "investment_score",
|
|
1125
|
-
"scale": 100,
|
|
1126
|
-
"normalize_weights": True,
|
|
1127
|
-
"factors": [
|
|
1128
|
-
{
|
|
1129
|
-
"name": "near_poi",
|
|
1130
|
-
"field": "distance_to_poi",
|
|
1131
|
-
"type": "inverse_distance",
|
|
1132
|
-
"max_distance": 500,
|
|
1133
|
-
"weight": 0.30,
|
|
1134
|
-
},
|
|
1135
|
-
{
|
|
1136
|
-
"name": "inside_buildable_zone",
|
|
1137
|
-
"field": "inside_buildable_zone",
|
|
1138
|
-
"type": "boolean",
|
|
1139
|
-
"weight": 0.25,
|
|
1140
|
-
},
|
|
1141
|
-
{
|
|
1142
|
-
"name": "near_main_road",
|
|
1143
|
-
"field": "distance_to_road",
|
|
1144
|
-
"type": "inverse_distance",
|
|
1145
|
-
"max_distance": 1000,
|
|
1146
|
-
"weight": 0.20,
|
|
1147
|
-
},
|
|
1148
|
-
{
|
|
1149
|
-
"name": "low_flood_risk",
|
|
1150
|
-
"field": "flood_risk",
|
|
1151
|
-
"type": "risk_level",
|
|
1152
|
-
"weight": 0.10,
|
|
1153
|
-
},
|
|
1154
|
-
{
|
|
1155
|
-
"name": "low_earthquake_risk",
|
|
1156
|
-
"field": "earthquake_risk",
|
|
1157
|
-
"type": "risk_level",
|
|
1158
|
-
"weight": 0.10,
|
|
1159
|
-
},
|
|
1160
|
-
{
|
|
1161
|
-
"name": "low_fire_risk",
|
|
1162
|
-
"field": "fire_risk",
|
|
1163
|
-
"type": "risk_level",
|
|
1164
|
-
"weight": 0.05,
|
|
1165
|
-
},
|
|
1166
|
-
],
|
|
1167
|
-
}
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
1182
|
def _semantic_distance_field(reference_ref: str) -> str:
|
|
1171
1183
|
"""
|
|
1172
1184
|
Pick a semantic distance field based on the reference entity/output name.
|
|
@@ -1216,6 +1228,16 @@ def normalize_llm_query_spec_for_planning(spec: QuerySpec) -> QuerySpec:
|
|
|
1216
1228
|
|
|
1217
1229
|
# Inject enrichment only when LLM did not provide its own scoring spec.
|
|
1218
1230
|
# This keeps old explicit LLM specs stable, but improves weak/missing specs.
|
|
1231
|
+
#
|
|
1232
|
+
# NOTE: since a score_features op missing scoring_spec/factors now
|
|
1233
|
+
# raises (see below) instead of getting a default injected, this flag
|
|
1234
|
+
# can only be True for a spec that is about to raise before this
|
|
1235
|
+
# function returns - so the enrichment-injection code below it is
|
|
1236
|
+
# currently unreachable in any spec that completes normally. Left in
|
|
1237
|
+
# place rather than removed with this fix: ripping it out means also
|
|
1238
|
+
# removing _semantic_distance_field and updating the tests that
|
|
1239
|
+
# exercise it, which is a larger, separate change from the two bugs
|
|
1240
|
+
# this pass fixes.
|
|
1219
1241
|
should_inject_enrichment = any(
|
|
1220
1242
|
op.op == "score_features"
|
|
1221
1243
|
and "scoring_spec" not in op.params
|
|
@@ -1250,8 +1272,23 @@ def normalize_llm_query_spec_for_planning(spec: QuerySpec) -> QuerySpec:
|
|
|
1250
1272
|
|
|
1251
1273
|
if op.op == "score_features":
|
|
1252
1274
|
if "scoring_spec" not in clean_params and "factors" not in clean_params:
|
|
1253
|
-
|
|
1254
|
-
|
|
1275
|
+
# No safe generic default exists here: this used to inject
|
|
1276
|
+
# a hardcoded real-estate scoring_spec (investment_score,
|
|
1277
|
+
# inside_buildable_zone, flood_risk, ...) into ANY
|
|
1278
|
+
# score_features op that omitted one, regardless of the
|
|
1279
|
+
# query's actual domain. For a non-real-estate query that
|
|
1280
|
+
# silently produced a nonsense score column, or crashed
|
|
1281
|
+
# downstream when those fields didn't exist on the data -
|
|
1282
|
+
# indistinguishable from a real real-estate query's own
|
|
1283
|
+
# valid output. The LLM must describe its own domain's
|
|
1284
|
+
# scoring, or this fails loudly right here instead.
|
|
1285
|
+
raise LLMSpecGenerationError(
|
|
1286
|
+
f"score_features operation (output={op.output!r}) has "
|
|
1287
|
+
"neither 'scoring_spec' nor 'factors'. There is no "
|
|
1288
|
+
"domain-neutral default to fall back to - the LLM must "
|
|
1289
|
+
"supply a complete scoring specification for its own "
|
|
1290
|
+
"query."
|
|
1291
|
+
)
|
|
1255
1292
|
|
|
1256
1293
|
scoring_spec = clean_params.get("scoring_spec")
|
|
1257
1294
|
if isinstance(scoring_spec, dict):
|
|
@@ -1495,11 +1532,18 @@ def _inject_report_pipeline(spec: QuerySpec) -> tuple[QuerySpec, list[str]]:
|
|
|
1495
1532
|
"""
|
|
1496
1533
|
repairs: list[str] = []
|
|
1497
1534
|
|
|
1498
|
-
# Find the last rank_features
|
|
1535
|
+
# Find the last rank_features op, so build_report reuses the score/rank
|
|
1536
|
+
# field names that op actually used - not a hardcoded guess. By this
|
|
1537
|
+
# point base normalization has already ensured rank_features carries
|
|
1538
|
+
# score_field/rank_field (either LLM-provided or defaulted from the
|
|
1539
|
+
# upstream score_features op's own output_field), so these are always
|
|
1540
|
+
# present here.
|
|
1499
1541
|
last_rank_output: str | None = None
|
|
1542
|
+
last_rank_op: OperationSpec | None = None
|
|
1500
1543
|
for op in spec.operations:
|
|
1501
1544
|
if op.op == "rank_features" and op.output:
|
|
1502
1545
|
last_rank_output = op.output
|
|
1546
|
+
last_rank_op = op
|
|
1503
1547
|
|
|
1504
1548
|
if not last_rank_output:
|
|
1505
1549
|
# Fallback: use the last operation output.
|
|
@@ -1511,6 +1555,16 @@ def _inject_report_pipeline(spec: QuerySpec) -> tuple[QuerySpec, list[str]]:
|
|
|
1511
1555
|
if not last_rank_output:
|
|
1512
1556
|
return spec, []
|
|
1513
1557
|
|
|
1558
|
+
# Previously hardcoded to "investment_score"/"rank" regardless of what
|
|
1559
|
+
# the plan's own rank_features op used - a non-real-estate plan (e.g.
|
|
1560
|
+
# score_field="accessibility_score") got a report referencing a column
|
|
1561
|
+
# its data never had.
|
|
1562
|
+
score_field = "score"
|
|
1563
|
+
rank_field = "rank"
|
|
1564
|
+
if last_rank_op is not None:
|
|
1565
|
+
score_field = str(last_rank_op.params.get("score_field") or score_field)
|
|
1566
|
+
rank_field = str(last_rank_op.params.get("rank_field") or rank_field)
|
|
1567
|
+
|
|
1514
1568
|
new_ops = list(spec.operations)
|
|
1515
1569
|
|
|
1516
1570
|
# build_report node
|
|
@@ -1519,8 +1573,8 @@ def _inject_report_pipeline(spec: QuerySpec) -> tuple[QuerySpec, list[str]]:
|
|
|
1519
1573
|
op="build_report",
|
|
1520
1574
|
inputs={"vector": last_rank_output},
|
|
1521
1575
|
params={
|
|
1522
|
-
"score_field":
|
|
1523
|
-
"rank_field":
|
|
1576
|
+
"score_field": score_field,
|
|
1577
|
+
"rank_field": rank_field,
|
|
1524
1578
|
},
|
|
1525
1579
|
output=report_output,
|
|
1526
1580
|
))
|
|
@@ -1575,6 +1629,197 @@ def _inject_report_pipeline(spec: QuerySpec) -> tuple[QuerySpec, list[str]]:
|
|
|
1575
1629
|
|
|
1576
1630
|
|
|
1577
1631
|
|
|
1632
|
+
def _validate_operation_input_roles(spec: QuerySpec) -> None:
|
|
1633
|
+
"""
|
|
1634
|
+
Validate every operation's inputs against OP_CATALOG's input_map before
|
|
1635
|
+
handing the spec back to the caller.
|
|
1636
|
+
|
|
1637
|
+
DeterministicPlanner.build() already performs this exact check
|
|
1638
|
+
(_map_inputs in planner.py) and raises PlanningError - so a spec that
|
|
1639
|
+
fails this check was always going to fail anyway. Duplicating the
|
|
1640
|
+
check here means it fails right where the spec was generated, as a
|
|
1641
|
+
specific LLMSpecGenerationError naming the missing role, rather than
|
|
1642
|
+
as a generic PlanningError raised later out of the planner - the same
|
|
1643
|
+
failure, several call frames away from its cause, indistinguishable
|
|
1644
|
+
from any other planning error.
|
|
1645
|
+
|
|
1646
|
+
Every input_map key is a required role: the planner has no notion of
|
|
1647
|
+
an optional one today (see the real_estate_spatial_enrich note in
|
|
1648
|
+
op_catalog.py), so this mirrors _map_inputs's missing_roles check
|
|
1649
|
+
exactly rather than inventing separate required/optional semantics.
|
|
1650
|
+
"""
|
|
1651
|
+
for op in spec.operations:
|
|
1652
|
+
if not is_supported(op.op):
|
|
1653
|
+
continue
|
|
1654
|
+
|
|
1655
|
+
required_roles = get_op(op.op).input_map
|
|
1656
|
+
missing_roles = [role for role in required_roles if role not in op.inputs]
|
|
1657
|
+
|
|
1658
|
+
if missing_roles:
|
|
1659
|
+
raise LLMSpecGenerationError(
|
|
1660
|
+
f"operation {op.op!r} (output={op.output!r}) is missing "
|
|
1661
|
+
f"required input role(s) {missing_roles!r}. It supplied "
|
|
1662
|
+
f"{sorted(op.inputs)!r}; {op.op!r} requires "
|
|
1663
|
+
f"{sorted(required_roles)!r}."
|
|
1664
|
+
)
|
|
1665
|
+
|
|
1666
|
+
|
|
1667
|
+
_NEAREST_OPS_WITH_DISTANCE_FIELD = {"spatial_nearest", "nearest_neighbor", "filter_by_distance"}
|
|
1668
|
+
|
|
1669
|
+
|
|
1670
|
+
def _extract_scoring_factor_fields(params: dict[str, Any]) -> list[str]:
|
|
1671
|
+
"""
|
|
1672
|
+
Pull the "field" name out of every factor a score_features op's
|
|
1673
|
+
params declare, across the shapes _normalize_scoring_spec (in
|
|
1674
|
+
plugins/feature_scoring.py) accepts: top-level "factors", or
|
|
1675
|
+
"scoring_spec.factors", or the older nested "scoring_spec.scoring.factors".
|
|
1676
|
+
"""
|
|
1677
|
+
factors = params.get("factors")
|
|
1678
|
+
|
|
1679
|
+
if not isinstance(factors, list):
|
|
1680
|
+
scoring_spec = params.get("scoring_spec")
|
|
1681
|
+
if isinstance(scoring_spec, dict):
|
|
1682
|
+
inner = scoring_spec.get("scoring")
|
|
1683
|
+
if isinstance(inner, dict) and isinstance(inner.get("factors"), list):
|
|
1684
|
+
factors = inner["factors"]
|
|
1685
|
+
elif isinstance(scoring_spec.get("factors"), list):
|
|
1686
|
+
factors = scoring_spec["factors"]
|
|
1687
|
+
|
|
1688
|
+
if not isinstance(factors, list):
|
|
1689
|
+
return []
|
|
1690
|
+
|
|
1691
|
+
return [
|
|
1692
|
+
str(factor["field"])
|
|
1693
|
+
for factor in factors
|
|
1694
|
+
if isinstance(factor, dict) and factor.get("field")
|
|
1695
|
+
]
|
|
1696
|
+
|
|
1697
|
+
|
|
1698
|
+
def _op_declared_output_fields(op: OperationSpec) -> list[str]:
|
|
1699
|
+
"""
|
|
1700
|
+
Field names an operation declares it writes, from the two mechanisms
|
|
1701
|
+
the system currently has for naming a computed field: an explicit
|
|
1702
|
+
"distance_field" param (spatial_nearest/nearest_neighbor/
|
|
1703
|
+
filter_by_distance), or enrich_feature_properties's rule targets.
|
|
1704
|
+
|
|
1705
|
+
Deliberately narrow: these are the only field-naming mechanisms an LLM
|
|
1706
|
+
plan can currently use, so this stays a precise signal rather than a
|
|
1707
|
+
guess. An op not covered here is simply not a candidate producer -
|
|
1708
|
+
see _validate_score_features_field_chaining's docstring for why that
|
|
1709
|
+
makes this check conservative rather than exhaustive.
|
|
1710
|
+
"""
|
|
1711
|
+
if op.op in _NEAREST_OPS_WITH_DISTANCE_FIELD:
|
|
1712
|
+
field = op.params.get("distance_field")
|
|
1713
|
+
return [str(field)] if field else []
|
|
1714
|
+
|
|
1715
|
+
if op.op == "enrich_feature_properties":
|
|
1716
|
+
rules = op.params.get("rules")
|
|
1717
|
+
if isinstance(rules, list):
|
|
1718
|
+
return [
|
|
1719
|
+
str(rule["target"])
|
|
1720
|
+
for rule in rules
|
|
1721
|
+
if isinstance(rule, dict) and rule.get("target")
|
|
1722
|
+
]
|
|
1723
|
+
|
|
1724
|
+
return []
|
|
1725
|
+
|
|
1726
|
+
|
|
1727
|
+
def _ancestor_refs(start_ref: str, ops_by_output: dict[str, OperationSpec]) -> set[str]:
|
|
1728
|
+
"""
|
|
1729
|
+
Every ref start_ref transitively depends on, by walking operation
|
|
1730
|
+
inputs backward. Stops at any ref that isn't a known operation output
|
|
1731
|
+
(an entity or an initial input), rather than erroring - this function
|
|
1732
|
+
only needs to answer "was this ref produced upstream of start_ref?".
|
|
1733
|
+
"""
|
|
1734
|
+
seen: set[str] = set()
|
|
1735
|
+
stack = [start_ref]
|
|
1736
|
+
|
|
1737
|
+
while stack:
|
|
1738
|
+
ref = stack.pop()
|
|
1739
|
+
if ref in seen:
|
|
1740
|
+
continue
|
|
1741
|
+
seen.add(ref)
|
|
1742
|
+
|
|
1743
|
+
op = ops_by_output.get(ref)
|
|
1744
|
+
if op is None:
|
|
1745
|
+
continue
|
|
1746
|
+
|
|
1747
|
+
for dependency_ref in op.inputs.values():
|
|
1748
|
+
if dependency_ref not in seen:
|
|
1749
|
+
stack.append(str(dependency_ref))
|
|
1750
|
+
|
|
1751
|
+
return seen
|
|
1752
|
+
|
|
1753
|
+
|
|
1754
|
+
def _validate_score_features_field_chaining(spec: QuerySpec) -> None:
|
|
1755
|
+
"""
|
|
1756
|
+
Catch a score_features op reading from a ref that never accumulated a
|
|
1757
|
+
field its own scoring factors need.
|
|
1758
|
+
|
|
1759
|
+
This is the fan-out/chaining gap: an LLM asked to score against
|
|
1760
|
+
distance to several different amenities routinely computes each
|
|
1761
|
+
distance as its own operation off the SAME original vector (a fan-out)
|
|
1762
|
+
instead of chaining each computation onto the previous one's output
|
|
1763
|
+
(an accumulating chain - see the worked example in _domain_guidance).
|
|
1764
|
+
The result plans and executes without error - every required input
|
|
1765
|
+
role is present - but every factor referencing a field that landed on
|
|
1766
|
+
a sibling branch instead of the scored ref silently scores 0. A
|
|
1767
|
+
all-zero/degenerate score on every feature is exactly what that looks
|
|
1768
|
+
like from the outside, with no exception to point at the cause.
|
|
1769
|
+
|
|
1770
|
+
Deliberately conservative to avoid false positives: only fields this
|
|
1771
|
+
module can trace to a specific producing operation (see
|
|
1772
|
+
_op_declared_output_fields) are checked. A factor field that already
|
|
1773
|
+
exists on the raw input data, or that this function doesn't recognize
|
|
1774
|
+
as a producible field, is left unvalidated rather than guessed at -
|
|
1775
|
+
under-catching is the safe failure mode for a check like this, not
|
|
1776
|
+
over-catching.
|
|
1777
|
+
"""
|
|
1778
|
+
ops_by_output: dict[str, OperationSpec] = {
|
|
1779
|
+
op.output: op for op in spec.operations if op.output
|
|
1780
|
+
}
|
|
1781
|
+
|
|
1782
|
+
field_producers: dict[str, list[OperationSpec]] = {}
|
|
1783
|
+
for op in spec.operations:
|
|
1784
|
+
for field in _op_declared_output_fields(op):
|
|
1785
|
+
field_producers.setdefault(field, []).append(op)
|
|
1786
|
+
|
|
1787
|
+
for op in spec.operations:
|
|
1788
|
+
if op.op != "score_features":
|
|
1789
|
+
continue
|
|
1790
|
+
|
|
1791
|
+
needed_fields = _extract_scoring_factor_fields(op.params)
|
|
1792
|
+
if not needed_fields:
|
|
1793
|
+
continue
|
|
1794
|
+
|
|
1795
|
+
scored_ref = op.inputs.get("vector")
|
|
1796
|
+
if not scored_ref:
|
|
1797
|
+
continue
|
|
1798
|
+
|
|
1799
|
+
ancestors = _ancestor_refs(str(scored_ref), ops_by_output)
|
|
1800
|
+
|
|
1801
|
+
for field in needed_fields:
|
|
1802
|
+
producers = field_producers.get(field)
|
|
1803
|
+
if not producers:
|
|
1804
|
+
# Not a field this module can trace to an operation -
|
|
1805
|
+
# could be a pre-existing attribute on the raw data.
|
|
1806
|
+
continue
|
|
1807
|
+
|
|
1808
|
+
if not any(producer.output in ancestors for producer in producers):
|
|
1809
|
+
producer_outputs = [p.output for p in producers]
|
|
1810
|
+
raise LLMSpecGenerationError(
|
|
1811
|
+
f"score_features (output={op.output!r}) scores on field "
|
|
1812
|
+
f"{field!r}, but that field is produced by "
|
|
1813
|
+
f"{producer_outputs!r}, none of which is chained into "
|
|
1814
|
+
f"its input {scored_ref!r} (or anything {scored_ref!r} "
|
|
1815
|
+
"depends on). Each computed field must be chained onto "
|
|
1816
|
+
"the previous operation's output before scoring - see "
|
|
1817
|
+
"the 'scoring against MORE THAN ONE computed field' "
|
|
1818
|
+
"guidance - otherwise this field is silently absent and "
|
|
1819
|
+
"its factor scores 0 for every feature."
|
|
1820
|
+
)
|
|
1821
|
+
|
|
1822
|
+
|
|
1578
1823
|
class LLMQuerySpecGenerator:
|
|
1579
1824
|
def __init__(
|
|
1580
1825
|
self,
|
|
@@ -1621,7 +1866,10 @@ class LLMQuerySpecGenerator:
|
|
|
1621
1866
|
data = _pre_normalize_query_spec_json(data, context=context)
|
|
1622
1867
|
|
|
1623
1868
|
spec = query_spec_from_dict(data, raw_query_fallback=raw_query)
|
|
1624
|
-
|
|
1869
|
+
spec = normalize_llm_query_spec_for_planning(spec)
|
|
1870
|
+
_validate_operation_input_roles(spec)
|
|
1871
|
+
_validate_score_features_field_chaining(spec)
|
|
1872
|
+
return spec
|
|
1625
1873
|
|
|
1626
1874
|
|
|
1627
1875
|
# ------------------------------------------------------------------ #
|
|
@@ -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.2"
|
|
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"
|