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.
Files changed (432) hide show
  1. {smart_spatial_system-0.2.0/smart_spatial_system.egg-info → smart_spatial_system-0.2.2}/PKG-INFO +1 -1
  2. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/orchestrator/planning/llm_spec_generator.py +312 -64
  3. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/pyproject.toml +1 -1
  4. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2/smart_spatial_system.egg-info}/PKG-INFO +1 -1
  5. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_llm_spec_generator.py +473 -100
  6. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/LICENSE +0 -0
  7. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/README.md +0 -0
  8. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/api/__init__.py +0 -0
  9. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/api/auth.py +0 -0
  10. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/api/main.py +0 -0
  11. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/api/routers/__init__.py +0 -0
  12. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/api/routers/data_source_connectors.py +0 -0
  13. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/api/routers/data_sources.py +0 -0
  14. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/api/routers/plugins_settings.py +0 -0
  15. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/api/routers/projects.py +0 -0
  16. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/api/routers/query_planner.py +0 -0
  17. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/api/routers/requests_outputs.py +0 -0
  18. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/api/routers/system.py +0 -0
  19. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/api/routers/uploads.py +0 -0
  20. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/api/routers/weights.py +0 -0
  21. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/api/support.py +0 -0
  22. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/config/__init__.py +0 -0
  23. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/config/plugins/__init__.py +0 -0
  24. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/config/plugins/area_perimeter_calc.example.yaml +0 -0
  25. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/config/plugins/area_perimeter_calc.yaml +0 -0
  26. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/config/plugins/attribute_statistics.example.yaml +0 -0
  27. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/config/plugins/attribute_statistics.yaml +0 -0
  28. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/config/plugins/band_math.example.yaml +0 -0
  29. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/config/plugins/band_math.yaml +0 -0
  30. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/config/plugins/buffer_analysis.example.yaml +0 -0
  31. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/config/plugins/buffer_analysis.yaml +0 -0
  32. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/config/plugins/centroid_extractor.example.yaml +0 -0
  33. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/config/plugins/centroid_extractor.yaml +0 -0
  34. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/config/plugins/core_vector.example.yaml +0 -0
  35. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/config/plugins/core_vector.yaml +0 -0
  36. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/config/plugins/crs_transformer.example.yaml +0 -0
  37. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/config/plugins/crs_transformer.yaml +0 -0
  38. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/config/plugins/data_writer_exporter.example.yaml +0 -0
  39. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/config/plugins/data_writer_exporter.yaml +0 -0
  40. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/config/plugins/dissolve_aggregator.example.yaml +0 -0
  41. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/config/plugins/dissolve_aggregator.yaml +0 -0
  42. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/config/plugins/distance_calculator.example.yaml +0 -0
  43. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/config/plugins/distance_calculator.yaml +0 -0
  44. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/config/plugins/feature_enrichment.example.yaml +0 -0
  45. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/config/plugins/feature_enrichment.yaml +0 -0
  46. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/config/plugins/feature_scoring.example.yaml +0 -0
  47. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/config/plugins/feature_scoring.yaml +0 -0
  48. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/config/plugins/geocoding_resolver.example.yaml +0 -0
  49. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/config/plugins/geocoding_resolver.yaml +0 -0
  50. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/config/plugins/geometry_validator.example.yaml +0 -0
  51. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/config/plugins/geometry_validator.yaml +0 -0
  52. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/config/plugins/local_raster_loader.example.yaml +0 -0
  53. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/config/plugins/local_raster_loader.yaml +0 -0
  54. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/config/plugins/local_vector_loader.example.yaml +0 -0
  55. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/config/plugins/local_vector_loader.yaml +0 -0
  56. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/config/plugins/ndvi_calculator.example.yaml +0 -0
  57. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/config/plugins/ndvi_calculator.yaml +0 -0
  58. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/config/plugins/nearest_neighbor.example.yaml +0 -0
  59. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/config/plugins/nearest_neighbor.yaml +0 -0
  60. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/config/plugins/postgis_connector.example.yaml +0 -0
  61. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/config/plugins/postgis_connector.yaml +0 -0
  62. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/config/plugins/raster_clip_mask.example.yaml +0 -0
  63. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/config/plugins/raster_clip_mask.yaml +0 -0
  64. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/config/plugins/raster_reclassify.example.yaml +0 -0
  65. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/config/plugins/raster_reclassify.yaml +0 -0
  66. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/config/plugins/raster_statistics.example.yaml +0 -0
  67. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/config/plugins/raster_statistics.yaml +0 -0
  68. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/config/plugins/raster_threshold.example.yaml +0 -0
  69. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/config/plugins/raster_threshold.yaml +0 -0
  70. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/config/plugins/raster_to_vector.example.yaml +0 -0
  71. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/config/plugins/raster_to_vector.yaml +0 -0
  72. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/config/plugins/risk_enrichment.example.yaml +0 -0
  73. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/config/plugins/risk_enrichment.yaml +0 -0
  74. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/config/plugins/slope_aspect.yaml +0 -0
  75. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/config/plugins/spatial_intersection.example.yaml +0 -0
  76. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/config/plugins/spatial_intersection.yaml +0 -0
  77. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/config/plugins/spatial_join.example.yaml +0 -0
  78. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/config/plugins/spatial_join.yaml +0 -0
  79. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/config/plugins/spatial_predicate.example.yaml +0 -0
  80. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/config/plugins/spatial_predicate.yaml +0 -0
  81. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/config/plugins/spatial_query_filter.example.yaml +0 -0
  82. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/config/plugins/spatial_query_filter.yaml +0 -0
  83. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/config/plugins/spectral_indices.example.yaml +0 -0
  84. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/config/plugins/spectral_indices.yaml +0 -0
  85. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/config/plugins/wms_wfs_fetcher.example.yaml +0 -0
  86. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/config/plugins/wms_wfs_fetcher.yaml +0 -0
  87. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/config/plugins/zonal_statistics.example.yaml +0 -0
  88. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/config/plugins/zonal_statistics.yaml +0 -0
  89. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/orchestrator/__init__.py +0 -0
  90. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/orchestrator/audit.py +0 -0
  91. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/orchestrator/capability_registry.py +0 -0
  92. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/orchestrator/capability_router.py +0 -0
  93. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/orchestrator/capability_scoring.py +0 -0
  94. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/orchestrator/data_source_service.py +0 -0
  95. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/orchestrator/error_contract.py +0 -0
  96. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/orchestrator/feedback.py +0 -0
  97. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/orchestrator/feedback_proposal_service.py +0 -0
  98. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/orchestrator/input_error_mapping.py +0 -0
  99. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/orchestrator/input_reference_resolver.py +0 -0
  100. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/orchestrator/kernel_artifacts.py +0 -0
  101. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/orchestrator/learning_signals.py +0 -0
  102. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/orchestrator/llm_client.py +0 -0
  103. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/orchestrator/llm_gate.py +0 -0
  104. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/orchestrator/llm_intent_planner.py +0 -0
  105. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/orchestrator/loader_plugin_contract.py +0 -0
  106. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/orchestrator/map_layer_service.py +0 -0
  107. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/orchestrator/map_layers.py +0 -0
  108. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/orchestrator/models.py +0 -0
  109. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/orchestrator/natural_query_runner.py +0 -0
  110. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/orchestrator/output_service.py +0 -0
  111. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/orchestrator/output_storage.py +0 -0
  112. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/orchestrator/pipeline_executor.py +0 -0
  113. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/orchestrator/plan_builder.py +0 -0
  114. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/orchestrator/planning/__init__.py +0 -0
  115. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/orchestrator/planning/capability_resolver.py +0 -0
  116. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/orchestrator/planning/dag.py +0 -0
  117. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/orchestrator/planning/dag_executor.py +0 -0
  118. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/orchestrator/planning/error_mapping.py +0 -0
  119. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/orchestrator/planning/kernel_execution_bridge.py +0 -0
  120. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/orchestrator/planning/kernel_plan_adapter.py +0 -0
  121. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/orchestrator/planning/llm_query_spec.py +0 -0
  122. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/orchestrator/planning/op_catalog.py +0 -0
  123. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/orchestrator/planning/output_parity.py +0 -0
  124. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/orchestrator/planning/planner.py +0 -0
  125. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/orchestrator/planning/postgis_semantic_resolver.py +0 -0
  126. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/orchestrator/planning/query_spec_contract.py +0 -0
  127. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/orchestrator/planning/report_spec.py +0 -0
  128. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/orchestrator/planning/runner.py +0 -0
  129. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/orchestrator/planning/semantic_planning_context.py +0 -0
  130. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/orchestrator/planning/spec.py +0 -0
  131. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/orchestrator/plugin_config_store.py +0 -0
  132. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/orchestrator/plugin_error_mapping.py +0 -0
  133. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/orchestrator/plugin_modules.py +0 -0
  134. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/orchestrator/plugin_runtime_service.py +0 -0
  135. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/orchestrator/plugin_state.py +0 -0
  136. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/orchestrator/production_response.py +0 -0
  137. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/orchestrator/project_service.py +0 -0
  138. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/orchestrator/project_store.py +0 -0
  139. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/orchestrator/provider_error_mapping.py +0 -0
  140. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/orchestrator/query_execution_service.py +0 -0
  141. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/orchestrator/query_parser.py +0 -0
  142. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/orchestrator/request_history_service.py +0 -0
  143. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/orchestrator/response_assembler.py +0 -0
  144. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/orchestrator/response_builder.py +0 -0
  145. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/orchestrator/router_decision.py +0 -0
  146. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/orchestrator/routing_aware_natural_query_runner.py +0 -0
  147. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/orchestrator/routing_aware_plan_builder.py +0 -0
  148. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/orchestrator/runtime_paths.py +0 -0
  149. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/orchestrator/service.py +0 -0
  150. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/orchestrator/statistics.py +0 -0
  151. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/orchestrator/upload_service.py +0 -0
  152. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/orchestrator/upload_storage.py +0 -0
  153. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/orchestrator/weight_proposals.py +0 -0
  154. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/orchestrator/weight_store_persistence.py +0 -0
  155. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/orchestrator/weighted_router.py +0 -0
  156. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/plugins/__init__.py +0 -0
  157. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/plugins/_shared/__init__.py +0 -0
  158. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/plugins/_shared/local_path_validation.py +0 -0
  159. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/plugins/_shared/numeric_validation.py +0 -0
  160. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/plugins/_shared/plugin_config.py +0 -0
  161. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/plugins/area_perimeter_calc.py +0 -0
  162. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/plugins/attribute_statistics.py +0 -0
  163. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/plugins/band_math.py +0 -0
  164. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/plugins/buffer_analysis.py +0 -0
  165. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/plugins/centroid_extractor.py +0 -0
  166. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/plugins/core_vector.py +0 -0
  167. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/plugins/crs_transformer.py +0 -0
  168. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/plugins/data_writer_exporter.py +0 -0
  169. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/plugins/dissolve_aggregator.py +0 -0
  170. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/plugins/distance_calculator.py +0 -0
  171. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/plugins/feature_enrichment.py +0 -0
  172. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/plugins/feature_scoring.py +0 -0
  173. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/plugins/geocoding_resolver.py +0 -0
  174. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/plugins/geometry_validator.py +0 -0
  175. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/plugins/local_raster_loader.py +0 -0
  176. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/plugins/local_vector_loader.py +0 -0
  177. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/plugins/ndvi_analysis.py +0 -0
  178. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/plugins/ndvi_calculator.py +0 -0
  179. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/plugins/nearest_neighbor.py +0 -0
  180. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/plugins/pdf_renderer.py +0 -0
  181. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/plugins/postgis_connector.py +0 -0
  182. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/plugins/raster_clip_mask.py +0 -0
  183. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/plugins/raster_reclassify.py +0 -0
  184. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/plugins/raster_statistics.py +0 -0
  185. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/plugins/raster_threshold.py +0 -0
  186. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/plugins/raster_to_vector.py +0 -0
  187. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/plugins/real_estate_scoring.py +0 -0
  188. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/plugins/real_estate_spatial_enrichment.py +0 -0
  189. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/plugins/report_builder.py +0 -0
  190. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/plugins/risk_enrichment.py +0 -0
  191. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/plugins/slope_aspect.py +0 -0
  192. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/plugins/spatial_intersection.py +0 -0
  193. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/plugins/spatial_join.py +0 -0
  194. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/plugins/spatial_predicate.py +0 -0
  195. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/plugins/spatial_query_filter.py +0 -0
  196. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/plugins/spectral_indices.py +0 -0
  197. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/plugins/wms_wfs_fetcher.py +0 -0
  198. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/plugins/zonal_statistics.py +0 -0
  199. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/setup.cfg +0 -0
  200. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/smart_spatial_system/__init__.py +0 -0
  201. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/smart_spatial_system/__main__.py +0 -0
  202. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/smart_spatial_system/application/__init__.py +0 -0
  203. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/smart_spatial_system/application/services/__init__.py +0 -0
  204. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/smart_spatial_system/application/services/data_source_service.py +0 -0
  205. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/smart_spatial_system/application/services/feedback_proposal_service.py +0 -0
  206. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/smart_spatial_system/application/services/llm_intent_adapter.py +0 -0
  207. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/smart_spatial_system/application/services/map_layer_service.py +0 -0
  208. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/smart_spatial_system/application/services/output_service.py +0 -0
  209. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/smart_spatial_system/application/services/planning_execution_policy.py +0 -0
  210. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/smart_spatial_system/application/services/planning_response_adapter.py +0 -0
  211. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/smart_spatial_system/application/services/plugin_runtime_service.py +0 -0
  212. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/smart_spatial_system/application/services/project_service.py +0 -0
  213. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/smart_spatial_system/application/services/query_execution/__init__.py +0 -0
  214. {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
  215. {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
  216. {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
  217. {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
  218. {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
  219. {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
  220. {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
  221. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/smart_spatial_system/application/services/query_execution/planning_context.py +0 -0
  222. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/smart_spatial_system/application/services/query_execution/planning_execution.py +0 -0
  223. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/smart_spatial_system/application/services/query_execution/planning_persistence.py +0 -0
  224. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/smart_spatial_system/application/services/query_execution/planning_response.py +0 -0
  225. {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
  226. {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
  227. {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
  228. {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
  229. {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
  230. {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
  231. {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
  232. {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
  233. {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
  234. {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
  235. {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
  236. {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
  237. {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
  238. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/smart_spatial_system/application/services/query_execution_service.py +0 -0
  239. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/smart_spatial_system/application/services/query_spec_enrichment.py +0 -0
  240. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/smart_spatial_system/application/services/real_estate_spatial_helpers.py +0 -0
  241. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/smart_spatial_system/application/services/request_history_service.py +0 -0
  242. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/smart_spatial_system/application/services/system_status_query_handler.py +0 -0
  243. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/smart_spatial_system/application/services/upload_service.py +0 -0
  244. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/smart_spatial_system/application/services/vector_display_handler.py +0 -0
  245. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/smart_spatial_system/application/services/vector_geojson_helpers.py +0 -0
  246. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/smart_spatial_system/application/services/vector_query_classifier.py +0 -0
  247. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/smart_spatial_system/cli.py +0 -0
  248. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/smart_spatial_system/domain/__init__.py +0 -0
  249. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/smart_spatial_system/domain/contracts/__init__.py +0 -0
  250. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/smart_spatial_system/domain/models/__init__.py +0 -0
  251. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/smart_spatial_system/infrastructure/__init__.py +0 -0
  252. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/smart_spatial_system/infrastructure/stores/__init__.py +0 -0
  253. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/smart_spatial_system/interfaces/__init__.py +0 -0
  254. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/smart_spatial_system/interfaces/api/__init__.py +0 -0
  255. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/smart_spatial_system/interfaces/api/routers/__init__.py +0 -0
  256. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/smart_spatial_system/plugins/__init__.py +0 -0
  257. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/smart_spatial_system/runtime/__init__.py +0 -0
  258. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/smart_spatial_system/shared/__init__.py +0 -0
  259. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/smart_spatial_system/workflows/__init__.py +0 -0
  260. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/smart_spatial_system/workflows/ndvi/__init__.py +0 -0
  261. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/smart_spatial_system/workflows/real_estate/__init__.py +0 -0
  262. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/smart_spatial_system.egg-info/SOURCES.txt +0 -0
  263. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/smart_spatial_system.egg-info/dependency_links.txt +0 -0
  264. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/smart_spatial_system.egg-info/entry_points.txt +0 -0
  265. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/smart_spatial_system.egg-info/requires.txt +0 -0
  266. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/smart_spatial_system.egg-info/top_level.txt +0 -0
  267. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/templates/__init__.py +0 -0
  268. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/templates/reports/__init__.py +0 -0
  269. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/templates/reports/real_estate_report.html +0 -0
  270. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_accessibility_query_spec.py +0 -0
  271. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_api_auth.py +0 -0
  272. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_api_contract_smoke.py +0 -0
  273. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_api_data_source_connectors_e2e.py +0 -0
  274. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_api_map_layers.py +0 -0
  275. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_api_mvp.py +0 -0
  276. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_api_outputs.py +0 -0
  277. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_api_projects.py +0 -0
  278. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_api_structured_error_normalization.py +0 -0
  279. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_api_upload_plugin_resolver.py +0 -0
  280. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_api_uploads.py +0 -0
  281. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_area_perimeter_calc.py +0 -0
  282. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_attribute_statistics.py +0 -0
  283. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_band_math.py +0 -0
  284. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_buffer_analysis.py +0 -0
  285. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_centroid_extractor.py +0 -0
  286. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_cli.py +0 -0
  287. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_crs_transformer.py +0 -0
  288. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_data_source_service.py +0 -0
  289. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_data_writer_exporter.py +0 -0
  290. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_deterministic_planner.py +0 -0
  291. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_dissolve_aggregator.py +0 -0
  292. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_distance_calculator.py +0 -0
  293. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_document_file_report_contract.py +0 -0
  294. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_end_to_end_natural_query_pipeline.py +0 -0
  295. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_error_contract.py +0 -0
  296. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_feature_enrichment.py +0 -0
  297. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_feature_scoring.py +0 -0
  298. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_frontend_api_surface_contract.py +0 -0
  299. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_geocoding_resolver.py +0 -0
  300. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_geocoding_resolver_error_redaction.py +0 -0
  301. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_geometry_validator.py +0 -0
  302. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_input_error_mapping.py +0 -0
  303. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_input_reference_resolver.py +0 -0
  304. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_input_reference_resolver_contract.py +0 -0
  305. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_kernel_artifacts.py +0 -0
  306. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_kernel_execution_bridge.py +0 -0
  307. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_kernel_plan_adapter.py +0 -0
  308. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_llm_intent_adapter.py +0 -0
  309. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_llm_raster_queryspec_normalization.py +0 -0
  310. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_llm_spec_generator_prenormalize.py +0 -0
  311. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_llm_spec_generator_semantic_context.py +0 -0
  312. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_llm_spec_generator_semantic_query_database_enrich.py +0 -0
  313. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_llm_spec_generator_semantic_queryspec_repair.py +0 -0
  314. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_loader_plugin_contract.py +0 -0
  315. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_local_path_validation.py +0 -0
  316. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_local_raster_loader.py +0 -0
  317. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_local_raster_loader_contract.py +0 -0
  318. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_local_vector_loader.py +0 -0
  319. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_local_vector_loader_contract.py +0 -0
  320. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_map_layer_contract.py +0 -0
  321. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_map_layer_service.py +0 -0
  322. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_ndvi_calculator.py +0 -0
  323. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_nearest_neighbor.py +0 -0
  324. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_numeric_validation.py +0 -0
  325. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_op_catalog_semantic_aliases.py +0 -0
  326. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_orchestrator_audit.py +0 -0
  327. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_orchestrator_audit_integration.py +0 -0
  328. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_orchestrator_data_source_service_integration.py +0 -0
  329. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_orchestrator_feedback.py +0 -0
  330. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_orchestrator_feedback_integration.py +0 -0
  331. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_orchestrator_keyword_scoring_router.py +0 -0
  332. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_orchestrator_learning_signals.py +0 -0
  333. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_orchestrator_learning_signals_integration.py +0 -0
  334. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_orchestrator_llm_gate.py +0 -0
  335. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_orchestrator_llm_gate_integration.py +0 -0
  336. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_orchestrator_map_layer_service_integration.py +0 -0
  337. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_orchestrator_natural_query_pipeline.py +0 -0
  338. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_orchestrator_output_service_integration.py +0 -0
  339. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_orchestrator_production_response.py +0 -0
  340. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_orchestrator_production_response_integration.py +0 -0
  341. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_orchestrator_project_service_integration.py +0 -0
  342. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_orchestrator_query_execution_service_integration.py +0 -0
  343. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_orchestrator_registry_router.py +0 -0
  344. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_orchestrator_router_decision.py +0 -0
  345. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_orchestrator_router_decision_integration.py +0 -0
  346. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_orchestrator_routing_aware_plan_builder.py +0 -0
  347. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_orchestrator_runtime_paths.py +0 -0
  348. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_orchestrator_service.py +0 -0
  349. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_orchestrator_service_domain_boundary_contract.py +0 -0
  350. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_orchestrator_service_integration.py +0 -0
  351. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_orchestrator_service_postgis_dedup_contract.py +0 -0
  352. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_orchestrator_statistics.py +0 -0
  353. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_orchestrator_statistics_integration.py +0 -0
  354. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_orchestrator_upload_service_integration.py +0 -0
  355. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_orchestrator_weight_proposals.py +0 -0
  356. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_orchestrator_weight_proposals_integration.py +0 -0
  357. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_orchestrator_weight_store_persistence.py +0 -0
  358. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_orchestrator_weight_store_persistence_integration.py +0 -0
  359. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_orchestrator_weighted_router.py +0 -0
  360. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_orchestrator_weighted_router_integration.py +0 -0
  361. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_output_service.py +0 -0
  362. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_output_storage.py +0 -0
  363. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_pdf_renderer.py +0 -0
  364. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_phase3_kernel_registry_coverage.py +0 -0
  365. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_phase3_output_parity.py +0 -0
  366. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_phase3_postgis_provider_kernel_execution.py +0 -0
  367. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_planning_dag_executor.py +0 -0
  368. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_planning_dag_executor_async_capability.py +0 -0
  369. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_planning_error_mapping.py +0 -0
  370. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_planning_execution_policy.py +0 -0
  371. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_planning_raster_op_catalog_mapping.py +0 -0
  372. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_planning_raster_queryspec_execution.py +0 -0
  373. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_planning_registry_backed_raster_execution.py +0 -0
  374. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_planning_registry_backed_real_estate_execution.py +0 -0
  375. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_planning_runner.py +0 -0
  376. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_plugin_boundary_contract.py +0 -0
  377. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_plugin_config.py +0 -0
  378. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_plugin_config_store.py +0 -0
  379. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_plugin_error_mapping.py +0 -0
  380. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_plugin_modules.py +0 -0
  381. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_postgis_connector.py +0 -0
  382. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_postgis_connector_percent_escape.py +0 -0
  383. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_postgis_semantic_resolver.py +0 -0
  384. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_project_service.py +0 -0
  385. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_project_store.py +0 -0
  386. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_provider_error_mapping.py +0 -0
  387. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_query_dispatch_domain_boundary_contract.py +0 -0
  388. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_query_execution_postgis_planning_context.py +0 -0
  389. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_query_execution_service.py +0 -0
  390. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_query_execution_service_domain_import_boundary_contract.py +0 -0
  391. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_query_response_shape_golden.py +0 -0
  392. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_query_spec_enrichment.py +0 -0
  393. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_raster_capability_registry_contract.py +0 -0
  394. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_raster_clip_mask.py +0 -0
  395. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_raster_reclassify.py +0 -0
  396. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_raster_statistics.py +0 -0
  397. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_raster_threshold.py +0 -0
  398. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_raster_to_vector.py +0 -0
  399. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_real_estate_ranking_bridge.py +0 -0
  400. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_real_estate_ranking_golden.py +0 -0
  401. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_real_estate_ranking_query_spec_planning.py +0 -0
  402. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_real_estate_scoring_plugin.py +0 -0
  403. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_real_estate_spatial_enrichment_plugin.py +0 -0
  404. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_real_estate_spatial_helpers.py +0 -0
  405. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_report_builder.py +0 -0
  406. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_report_spec.py +0 -0
  407. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_request_document_download_contract.py +0 -0
  408. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_response_assembler.py +0 -0
  409. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_response_output_contract.py +0 -0
  410. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_risk_enrichment.py +0 -0
  411. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_runtime_paths.py +0 -0
  412. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_semantic_planning_context.py +0 -0
  413. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_service_auto_postgis_semantic_context.py +0 -0
  414. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_service_planning_artifacts.py +0 -0
  415. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_service_postgis_runtime_connection_injection.py +0 -0
  416. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_service_semantic_planning_context.py +0 -0
  417. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_service_strict_loader_contract.py +0 -0
  418. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_service_structured_error_normalization.py +0 -0
  419. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_slope_aspect.py +0 -0
  420. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_spatial_intersection.py +0 -0
  421. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_spatial_join.py +0 -0
  422. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_spatial_query_filter.py +0 -0
  423. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_spectral_indices.py +0 -0
  424. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_system_status_query_handler.py +0 -0
  425. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_upload_service.py +0 -0
  426. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_upload_storage.py +0 -0
  427. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_vector_display_handler.py +0 -0
  428. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_vector_geojson_helpers.py +0 -0
  429. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_vector_query_classifier.py +0 -0
  430. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_wms_wfs_fetcher.py +0 -0
  431. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_wms_wfs_fetcher_error_redaction.py +0 -0
  432. {smart_spatial_system-0.2.0 → smart_spatial_system-0.2.2}/tests/test_zonal_statistics.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: smart_spatial_system
3
- Version: 0.2.0
3
+ Version: 0.2.2
4
4
  Summary: Plugin-based GeoAI backend: natural-language questions become QuerySpecs, DAG plans, and map/table/report outputs.
5
5
  Author: Araz Shah
6
6
  License-Expression: MIT
@@ -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
- clean_params["scoring_spec"] = _default_real_estate_scoring_spec()
1254
- repairs.append("added default scoring_spec to score_features")
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 output.
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": "investment_score",
1523
- "rank_field": "rank",
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
- return normalize_llm_query_spec_for_planning(spec)
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.0"
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"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: smart_spatial_system
3
- Version: 0.2.0
3
+ Version: 0.2.2
4
4
  Summary: Plugin-based GeoAI backend: natural-language questions become QuerySpecs, DAG plans, and map/table/report outputs.
5
5
  Author: Araz Shah
6
6
  License-Expression: MIT