imperal-sdk 6.5.2__tar.gz → 6.6.0__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 (484) hide show
  1. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/.github/workflows/publish.yml +22 -0
  2. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/CHANGELOG.md +29 -0
  3. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/PKG-INFO +1 -1
  4. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/sdk-reference.json +1 -1
  5. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/sdk_claims.json +1 -1
  6. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/__init__.py +1 -1
  7. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/code_index.py +78 -3
  8. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/code_links.py +52 -0
  9. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/ir/actions.py +16 -2
  10. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/runtime/interpreter.py +10 -5
  11. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/runtime/verbs.py +2 -0
  12. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/runtime/test_interpreter.py +1 -1
  13. imperal_sdk-6.6.0/tests/runtime/test_one_step_rule.py +52 -0
  14. imperal_sdk-6.6.0/tests/test_code_contracts_reached.py +32 -0
  15. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/test_code_index_indexer.py +1 -1
  16. imperal_sdk-6.6.0/tests/test_field_test_1113.py +49 -0
  17. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/.cm.txt +0 -0
  18. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/.github/workflows/identity-contract.yml +0 -0
  19. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/.github/workflows/test.yml +0 -0
  20. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/.gitignore +0 -0
  21. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/LICENSE +0 -0
  22. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/README.md +0 -0
  23. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/docs/sdl-facets.md +0 -0
  24. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/pyproject.toml +0 -0
  25. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/sdl_roles.json +0 -0
  26. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/.codebase-index-cache.pkl +0 -0
  27. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/_gateway.py +0 -0
  28. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/_http_retry.py +0 -0
  29. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/_shared_http.py +0 -0
  30. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/adversarial_oracle.py +0 -0
  31. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/ai/__init__.py +0 -0
  32. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/ai/client.py +0 -0
  33. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/app.py +0 -0
  34. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/apps/__init__.py +0 -0
  35. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/apps/client.py +0 -0
  36. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/auth/__init__.py +0 -0
  37. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/auth/client.py +0 -0
  38. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/auth/middleware.py +0 -0
  39. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/auto_ui.py +0 -0
  40. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/billing/__init__.py +0 -0
  41. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/billing/client.py +0 -0
  42. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/bom_extractor.py +0 -0
  43. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/cache/__init__.py +0 -0
  44. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/cache/client.py +0 -0
  45. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/cache/protocol.py +0 -0
  46. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/catalog.py +0 -0
  47. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/chat/__init__.py +0 -0
  48. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/chat/action_result.py +0 -0
  49. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/chat/error_codes.py +0 -0
  50. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/chat/exceptions.py +0 -0
  51. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/chat/extension.py +0 -0
  52. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/chat/filters.py +0 -0
  53. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/chat/guards.py +0 -0
  54. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/chat/kernel_primitives.py +0 -0
  55. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/chat/narration.py +0 -0
  56. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/chat/narration_guard.py +0 -0
  57. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/chat/prompt.py +0 -0
  58. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/chat/refusal.py +0 -0
  59. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/cli/__init__.py +0 -0
  60. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/cli/linter.py +0 -0
  61. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/cli/main.py +0 -0
  62. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/code_langs.py +0 -0
  63. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/config/__init__.py +0 -0
  64. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/config/client.py +0 -0
  65. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/context.py +0 -0
  66. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/conversations/__init__.py +0 -0
  67. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/conversations/client.py +0 -0
  68. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/core.py +0 -0
  69. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/cross_surface_bus.py +0 -0
  70. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/devtools/__init__.py +0 -0
  71. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/devtools/contract_checks.py +0 -0
  72. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/devtools/generate_api_surface.py +0 -0
  73. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/devtools/generate_reference.py +0 -0
  74. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/devtools/generate_sdk_claims.py +0 -0
  75. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/devtools/reference/__init__.py +0 -0
  76. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/devtools/reference/_flags.py +0 -0
  77. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/devtools/reference/_introspect.py +0 -0
  78. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/devtools/reference/client_methods.py +0 -0
  79. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/devtools/reference/dataclasses_kind.py +0 -0
  80. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/devtools/reference/decorators.py +0 -0
  81. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/devtools/reference/sdl_funcs.py +0 -0
  82. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/devtools/reference/sdl_roles.py +0 -0
  83. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/devtools/reference/ui_components.py +0 -0
  84. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/devtools/validate_identity_contract.py +0 -0
  85. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/dwell_guard.py +0 -0
  86. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/errors.py +0 -0
  87. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/extension.py +0 -0
  88. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/extensions/__init__.py +0 -0
  89. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/extensions/client.py +0 -0
  90. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/gnc_guard.py +0 -0
  91. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/http/__init__.py +0 -0
  92. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/http/client.py +0 -0
  93. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/ir/__init__.py +0 -0
  94. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/ir/_impl.py +0 -0
  95. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/ir/custom_roles.py +0 -0
  96. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/ir/migrate.py +0 -0
  97. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/ir/produce.py +0 -0
  98. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/ir/schema.py +0 -0
  99. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/ir/skeleton.py +0 -0
  100. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/ir/ui.py +0 -0
  101. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/ir/ui_children.py +0 -0
  102. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/ir/ui_template.py +0 -0
  103. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/ir/validator.py +0 -0
  104. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/manifest.py +0 -0
  105. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/manifest_schema.py +0 -0
  106. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/manifest_schema_ui.py +0 -0
  107. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/notify/__init__.py +0 -0
  108. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/notify/client.py +0 -0
  109. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/oauth_state.py +0 -0
  110. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/oauth_tokens.py +0 -0
  111. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/pipes.py +0 -0
  112. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/prompts/__init__.py +0 -0
  113. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/prompts/icnli_integrity_rules.txt +0 -0
  114. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/prompts/kernel_formatting_rule.txt +0 -0
  115. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/prompts/kernel_proactivity_rule.txt +0 -0
  116. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/protocols.py +0 -0
  117. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/rbac/__init__.py +0 -0
  118. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/rbac/client.py +0 -0
  119. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/rpc/__init__.py +0 -0
  120. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/rpc/codec.py +0 -0
  121. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/rpc/contract.py +0 -0
  122. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/runtime/__init__.py +0 -0
  123. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/runtime/_platform.py +0 -0
  124. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/runtime/canon.py +0 -0
  125. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/runtime/engine.py +0 -0
  126. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/runtime/executor.py +0 -0
  127. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/runtime/hosted_client.py +0 -0
  128. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/runtime/llm_provider.py +0 -0
  129. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/runtime/local_engine.py +0 -0
  130. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/runtime/message_adapter.py +0 -0
  131. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/runtime/template.py +0 -0
  132. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/schema/marathon_ram.sql +0 -0
  133. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/schemas/action_result.schema.json +0 -0
  134. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/schemas/actions/__init__.py +0 -0
  135. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/schemas/actions/ai_complete.json +0 -0
  136. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/schemas/actions/call.json +0 -0
  137. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/schemas/actions/conditional.json +0 -0
  138. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/schemas/actions/navigate.json +0 -0
  139. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/schemas/actions/open.json +0 -0
  140. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/schemas/actions/send.json +0 -0
  141. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/schemas/actions/store_create.json +0 -0
  142. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/schemas/actions/store_delete.json +0 -0
  143. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/schemas/actions/store_get.json +0 -0
  144. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/schemas/actions/store_list.json +0 -0
  145. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/schemas/actions/store_update.json +0 -0
  146. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/schemas/balance_info.schema.json +0 -0
  147. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/schemas/chat_result.schema.json +0 -0
  148. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/schemas/completion_result.schema.json +0 -0
  149. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/schemas/document.schema.json +0 -0
  150. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/schemas/event.schema.json +0 -0
  151. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/schemas/file_info.schema.json +0 -0
  152. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/schemas/function_call.schema.json +0 -0
  153. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/schemas/http_response.schema.json +0 -0
  154. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/schemas/imperal.schema.json +0 -0
  155. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/schemas/ir.schema.json +0 -0
  156. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/schemas/limits_result.schema.json +0 -0
  157. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/schemas/metered_event.schema.json +0 -0
  158. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/schemas/subscription_info.schema.json +0 -0
  159. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/schemas/ui_children/__init__.py +0 -0
  160. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/schemas/ui_children/accordion.json +0 -0
  161. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/schemas/ui_children/datatable_columns.json +0 -0
  162. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/schemas/ui_children/datatable_rows.json +0 -0
  163. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/schemas/ui_children/menu.json +0 -0
  164. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/schemas/ui_children/select.json +0 -0
  165. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/schemas/ui_children/tabs.json +0 -0
  166. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/schemas/ui_children/timeline.json +0 -0
  167. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/schemas/ui_children/tree.json +0 -0
  168. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/sdl/__init__.py +0 -0
  169. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/sdl/_generate_roles_json.py +0 -0
  170. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/sdl/entity.py +0 -0
  171. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/sdl/facet_resolve.py +0 -0
  172. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/sdl/facets/__init__.py +0 -0
  173. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/sdl/facets/catalog.py +0 -0
  174. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/sdl/facets/comm.py +0 -0
  175. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/sdl/facets/content.py +0 -0
  176. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/sdl/facets/device.py +0 -0
  177. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/sdl/facets/event.py +0 -0
  178. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/sdl/facets/geo.py +0 -0
  179. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/sdl/facets/identity.py +0 -0
  180. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/sdl/facets/media.py +0 -0
  181. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/sdl/facets/metric.py +0 -0
  182. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/sdl/facets/money.py +0 -0
  183. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/sdl/facets/net.py +0 -0
  184. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/sdl/facets/people.py +0 -0
  185. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/sdl/facets/quantity.py +0 -0
  186. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/sdl/facets/rating.py +0 -0
  187. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/sdl/facets/security.py +0 -0
  188. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/sdl/facets/task.py +0 -0
  189. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/sdl/facets/time.py +0 -0
  190. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/sdl/field.py +0 -0
  191. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/sdl/roles.py +0 -0
  192. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/search.py +0 -0
  193. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/secrets/__init__.py +0 -0
  194. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/secrets/client.py +0 -0
  195. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/secrets/exceptions.py +0 -0
  196. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/secrets/panel_handler.py +0 -0
  197. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/secrets/spec.py +0 -0
  198. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/security/__init__.py +0 -0
  199. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/security/call_token.py +0 -0
  200. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/security/deactivation_guard.py +0 -0
  201. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/signals/__init__.py +0 -0
  202. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/signals/client.py +0 -0
  203. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/skeleton/__init__.py +0 -0
  204. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/skeleton/client.py +0 -0
  205. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/storage/__init__.py +0 -0
  206. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/storage/client.py +0 -0
  207. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/store/__init__.py +0 -0
  208. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/store/client.py +0 -0
  209. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/store/exceptions.py +0 -0
  210. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/testing/__init__.py +0 -0
  211. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/testing/autonomous_mock.py +0 -0
  212. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/testing/mock_context.py +0 -0
  213. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/testing/mock_secrets.py +0 -0
  214. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/transport.py +0 -0
  215. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/typed_context.py +0 -0
  216. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/types/__init__.py +0 -0
  217. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/types/action_result.py +0 -0
  218. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/types/chat_result.py +0 -0
  219. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/types/client_contracts.py +0 -0
  220. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/types/contracts.py +0 -0
  221. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/types/contributions.py +0 -0
  222. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/types/events.py +0 -0
  223. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/types/health.py +0 -0
  224. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/types/identity.py +0 -0
  225. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/types/metered_event.py +0 -0
  226. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/types/models.py +0 -0
  227. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/types/pagination.py +0 -0
  228. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/types/store_contracts.py +0 -0
  229. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/ui/__init__.py +0 -0
  230. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/ui/actions.py +0 -0
  231. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/ui/base.py +0 -0
  232. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/ui/canvas.py +0 -0
  233. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/ui/data.py +0 -0
  234. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/ui/display.py +0 -0
  235. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/ui/feedback.py +0 -0
  236. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/ui/graph.py +0 -0
  237. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/ui/input_components.py +0 -0
  238. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/ui/interactive.py +0 -0
  239. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/ui/layout.py +0 -0
  240. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/ui/liquid.py +0 -0
  241. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/ui/signals.py +0 -0
  242. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/ui/stage.py +0 -0
  243. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/ui/theme.py +0 -0
  244. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/universal/__init__.py +0 -0
  245. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/universal/image.py +0 -0
  246. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/universal/index.py +0 -0
  247. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/universal/kinds.py +0 -0
  248. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/universal/legacy.py +0 -0
  249. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/universal/mail.py +0 -0
  250. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/universal/office.py +0 -0
  251. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/universal/pdf.py +0 -0
  252. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/universal/textual.py +0 -0
  253. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/universal/view.py +0 -0
  254. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/users/__init__.py +0 -0
  255. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/users/client.py +0 -0
  256. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/validator.py +0 -0
  257. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/validator_v1_6_0.py +0 -0
  258. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/src/imperal_sdk/vault_ram_client.py +0 -0
  259. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/conftest.py +0 -0
  260. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/contract/__init__.py +0 -0
  261. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/contract/test_action_schemas.py +0 -0
  262. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/contract/test_artifacts_freshness.py +0 -0
  263. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/contract/test_contract_checks_selftest.py +0 -0
  264. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/contract/test_generate_sdk_claims.py +0 -0
  265. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/contract/test_identity_nonempty.py +0 -0
  266. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/contract/test_ir_schema_fresh.py +0 -0
  267. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/contract/test_meter_lua_contract.py +0 -0
  268. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/contract/test_metered_event_contract.py +0 -0
  269. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/contract/test_notify_wire_payload.py +0 -0
  270. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/contract/test_public_docstrings_engine_neutral.py +0 -0
  271. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/contract/test_reference_completeness.py +0 -0
  272. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/contract/test_reference_no_leak.py +0 -0
  273. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/contract/test_sample_contract_shape.py +0 -0
  274. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/contract/test_sdk_matches_kernel_contract.py +0 -0
  275. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/contracts/__init__.py +0 -0
  276. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/contracts/test_store_contracts.py +0 -0
  277. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/fixtures/contract/kernel-contract.sample.json +0 -0
  278. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/fixtures/ir/README.md +0 -0
  279. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/fixtures/ir/archive_ended.ir.json +0 -0
  280. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/fixtures/ir/link_saver.ir.json +0 -0
  281. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/fixtures/ir/test_fixtures_valid.py +0 -0
  282. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/fixtures/openapi/auth-gateway.json +0 -0
  283. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/fixtures/openapi/registry.json +0 -0
  284. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/fixtures/openapi/sharelock-cases.json +0 -0
  285. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/fixtures/universal/exif.jpg +0 -0
  286. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/fixtures/universal/invoice.doc +0 -0
  287. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/fixtures/universal/locked.pdf +0 -0
  288. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/fixtures/universal/two_pages.pdf +0 -0
  289. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/fixtures/universal/with_attachment.eml +0 -0
  290. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/ir/__init__.py +0 -0
  291. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/ir/test_custom_roles.py +0 -0
  292. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/ir/test_ir_impl.py +0 -0
  293. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/ir/test_ir_mapping_real_ext.py +0 -0
  294. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/ir/test_ir_migrate.py +0 -0
  295. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/ir/test_ir_produce.py +0 -0
  296. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/ir/test_ir_schema.py +0 -0
  297. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/ir/test_ir_skeleton.py +0 -0
  298. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/ir/test_ir_ui.py +0 -0
  299. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/ir/test_ir_ui_produce.py +0 -0
  300. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/ir/test_ir_validator.py +0 -0
  301. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/ir/test_ir_versions.py +0 -0
  302. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/ir/test_ui_children.py +0 -0
  303. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/ir/test_ui_template.py +0 -0
  304. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/rpc/__init__.py +0 -0
  305. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/rpc/test_boundary_seal.py +0 -0
  306. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/rpc/test_codec.py +0 -0
  307. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/rpc/test_contract.py +0 -0
  308. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/runtime/__init__.py +0 -0
  309. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/runtime/test_canon.py +0 -0
  310. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/runtime/test_canon_template.py +0 -0
  311. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/runtime/test_engine_abc.py +0 -0
  312. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/runtime/test_engine_parity.py +0 -0
  313. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/runtime/test_executor_neutral.py +0 -0
  314. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/runtime/test_hosted_client.py +0 -0
  315. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/runtime/test_llm_provider_config_store.py +0 -0
  316. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/runtime/test_llm_provider_ctx_injection.py +0 -0
  317. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/runtime/test_local_engine.py +0 -0
  318. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/runtime/test_platform_shim.py +0 -0
  319. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/runtime/test_template.py +0 -0
  320. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/runtime/test_verb_ai.py +0 -0
  321. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/runtime/test_verb_call_directives.py +0 -0
  322. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/runtime/test_verb_conditional.py +0 -0
  323. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/runtime/test_verb_store.py +0 -0
  324. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/store/__init__.py +0 -0
  325. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/store/test_list_users_client.py +0 -0
  326. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/store/test_query_all_client.py +0 -0
  327. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/test_action_result_time_travel.py +0 -0
  328. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/test_action_result_typed.py +0 -0
  329. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/test_agent_presence.py +0 -0
  330. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/test_app_engine.py +0 -0
  331. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/test_as_user.py +0 -0
  332. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/test_auth.py +0 -0
  333. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/test_autonomous_mock.py +0 -0
  334. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/test_billing.py +0 -0
  335. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/test_cache_client.py +0 -0
  336. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/test_cache_model.py +0 -0
  337. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/test_call_token.py +0 -0
  338. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/test_callable_surface_single_source.py +0 -0
  339. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/test_chat_extension_deprecation.py +0 -0
  340. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/test_chat_extension_no_llm_router.py +0 -0
  341. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/test_chat_filters.py +0 -0
  342. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/test_chat_function_background_flag.py +0 -0
  343. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/test_chat_guards.py +0 -0
  344. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/test_chat_guards_bleed.py +0 -0
  345. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/test_chat_prompt.py +0 -0
  346. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/test_chat_result.py +0 -0
  347. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/test_cli.py +0 -0
  348. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/test_cli_sdk_commands.py +0 -0
  349. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/test_client_contracts.py +0 -0
  350. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/test_client_emit_neutral.py +0 -0
  351. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/test_code_index_configs.py +0 -0
  352. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/test_code_index_contracts.py +0 -0
  353. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/test_code_langs.py +0 -0
  354. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/test_code_links.py +0 -0
  355. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/test_code_web.py +0 -0
  356. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/test_config_client.py +0 -0
  357. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/test_context.py +0 -0
  358. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/test_context_background_task.py +0 -0
  359. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/test_context_deliver_chat_message.py +0 -0
  360. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/test_context_guards.py +0 -0
  361. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/test_contracts.py +0 -0
  362. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/test_contracts_live.py +0 -0
  363. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/test_contributions.py +0 -0
  364. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/test_core_primitives.py +0 -0
  365. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/test_data_model_kwarg.py +0 -0
  366. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/test_document_contract.py +0 -0
  367. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/test_emits_decorator.py +0 -0
  368. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/test_error_codes.py +0 -0
  369. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/test_errors.py +0 -0
  370. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/test_event_schema_v2.py +0 -0
  371. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/test_events_health.py +0 -0
  372. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/test_extension.py +0 -0
  373. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/test_extension_pipes.py +0 -0
  374. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/test_extension_v2.py +0 -0
  375. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/test_extensions_emit.py +0 -0
  376. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/test_gateway_namespaces.py +0 -0
  377. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/test_http_json_and_mock.py +0 -0
  378. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/test_http_retry.py +0 -0
  379. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/test_http_timeout_override.py +0 -0
  380. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/test_id_shape_guard.py +0 -0
  381. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/test_identity_contract.py +0 -0
  382. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/test_imperal_schema_v2.py +0 -0
  383. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/test_import_light.py +0 -0
  384. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/test_init_onboarding.py +0 -0
  385. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/test_kernel_primitives.py +0 -0
  386. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/test_liquid_ui.py +0 -0
  387. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/test_manifest.py +0 -0
  388. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/test_manifest_file_sinks.py +0 -0
  389. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/test_manifest_linter.py +0 -0
  390. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/test_manifest_no_orchestrator_tool.py +0 -0
  391. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/test_manifest_oauth.py +0 -0
  392. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/test_manifest_panels.py +0 -0
  393. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/test_manifest_roundtrip_gate.py +0 -0
  394. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/test_manifest_schema.py +0 -0
  395. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/test_manifest_v2_events.py +0 -0
  396. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/test_manifest_v2_other_sections.py +0 -0
  397. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/test_manifest_v2_webhooks.py +0 -0
  398. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/test_manifest_validator_v2.py +0 -0
  399. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/test_mock_context.py +0 -0
  400. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/test_models.py +0 -0
  401. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/test_narration_emission.py +0 -0
  402. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/test_narration_guard.py +0 -0
  403. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/test_oauth_authorize_url.py +0 -0
  404. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/test_oauth_tokens_shared.py +0 -0
  405. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/test_openai_max_completion_tokens.py +0 -0
  406. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/test_pagination.py +0 -0
  407. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/test_panel_rendering_contract.py +0 -0
  408. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/test_panel_swr_caching.py +0 -0
  409. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/test_panels.py +0 -0
  410. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/test_phase_a_dead_removal.py +0 -0
  411. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/test_phase_a_drift.py +0 -0
  412. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/test_phase_a_text.py +0 -0
  413. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/test_sdk_version_stamp.py +0 -0
  414. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/test_sdl_entity.py +0 -0
  415. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/test_sdl_entity_marker.py +0 -0
  416. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/test_sdl_exports.py +0 -0
  417. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/test_sdl_facet_catalog.py +0 -0
  418. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/test_sdl_facet_collisions.py +0 -0
  419. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/test_sdl_facet_comm.py +0 -0
  420. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/test_sdl_facet_content.py +0 -0
  421. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/test_sdl_facet_device.py +0 -0
  422. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/test_sdl_facet_event.py +0 -0
  423. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/test_sdl_facet_exports.py +0 -0
  424. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/test_sdl_facet_field.py +0 -0
  425. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/test_sdl_facet_geo.py +0 -0
  426. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/test_sdl_facet_identity.py +0 -0
  427. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/test_sdl_facet_media.py +0 -0
  428. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/test_sdl_facet_metric.py +0 -0
  429. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/test_sdl_facet_money.py +0 -0
  430. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/test_sdl_facet_net.py +0 -0
  431. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/test_sdl_facet_people.py +0 -0
  432. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/test_sdl_facet_quantity.py +0 -0
  433. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/test_sdl_facet_rating.py +0 -0
  434. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/test_sdl_facet_resolve.py +0 -0
  435. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/test_sdl_facet_security.py +0 -0
  436. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/test_sdl_facet_task.py +0 -0
  437. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/test_sdl_facet_time.py +0 -0
  438. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/test_sdl_facets_catalog.py +0 -0
  439. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/test_sdl_facets_doc.py +0 -0
  440. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/test_sdl_facets_pkg.py +0 -0
  441. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/test_sdl_field.py +0 -0
  442. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/test_sdl_roles.py +0 -0
  443. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/test_sdl_roles_json.py +0 -0
  444. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/test_sdl_roles_of_facets.py +0 -0
  445. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/test_sdl_vocab_version.py +0 -0
  446. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/test_search_provider.py +0 -0
  447. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/test_secret_scope_decorator.py +0 -0
  448. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/test_secret_spec_scope.py +0 -0
  449. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/test_skeleton_decorator.py +0 -0
  450. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/test_spec_validation.py +0 -0
  451. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/test_stage.py +0 -0
  452. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/test_surface_adaptation.py +0 -0
  453. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/test_sync_async_parity.py +0 -0
  454. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/test_transport_isolation.py +0 -0
  455. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/test_ui.py +0 -0
  456. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/test_ui_canvas.py +0 -0
  457. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/test_ui_fileupload_enhanced.py +0 -0
  458. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/test_ui_html.py +0 -0
  459. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/test_ui_image_enhanced.py +0 -0
  460. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/test_ui_modal.py +0 -0
  461. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/test_ui_open.py +0 -0
  462. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/test_ui_signals.py +0 -0
  463. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/test_ui_theme.py +0 -0
  464. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/test_universal_code_langs.py +0 -0
  465. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/test_universal_index.py +0 -0
  466. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/test_universal_kinds.py +0 -0
  467. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/test_universal_office.py +0 -0
  468. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/test_universal_pdf_mail.py +0 -0
  469. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/test_universal_views_text.py +0 -0
  470. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/test_user.py +0 -0
  471. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/test_v7_emit_refusal.py +0 -0
  472. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/test_validator.py +0 -0
  473. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/test_validator_drift.py +0 -0
  474. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/test_validator_pep563.py +0 -0
  475. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/test_validator_v1_6_0_rules.py +0 -0
  476. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/test_validator_v25.py +0 -0
  477. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/test_write_arg_bleed.py +0 -0
  478. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/tools/__init__.py +0 -0
  479. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/tools/test_generate_api_surface.py +0 -0
  480. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/tools/test_generate_reference.py +0 -0
  481. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/tools/test_reference_description.py +0 -0
  482. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/tools/test_reference_flags.py +0 -0
  483. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/tools/test_reference_typegraph.py +0 -0
  484. {imperal_sdk-6.5.2 → imperal_sdk-6.6.0}/tests/ui/test_input_type_enum.py +0 -0
@@ -75,6 +75,28 @@ jobs:
75
75
  # on publish success.
76
76
  skip-existing: true
77
77
 
78
+ move-stable:
79
+ name: Move the stable branch to this release
80
+ needs: publish
81
+ runs-on: ubuntu-latest
82
+ permissions:
83
+ contents: write
84
+ steps:
85
+ - uses: actions/checkout@v4
86
+ with:
87
+ fetch-depth: 0
88
+ # The `stable` branch is what every install from git names (webbee autoupdate, `pipx reinstall`, `uv tool
89
+ # upgrade`): moved here to the release just published -- only forward, a re-run of an older tag leaves it.
90
+ - name: Move
91
+ run: |
92
+ if git ls-remote --exit-code origin refs/heads/stable >/dev/null; then
93
+ git fetch -q origin stable
94
+ if git merge-base --is-ancestor HEAD FETCH_HEAD; then
95
+ echo "stable is already at or past this release"; exit 0
96
+ fi
97
+ fi
98
+ git push origin "HEAD:refs/heads/stable"
99
+
78
100
  # When a tag push triggered us (and there is no Release yet), also
79
101
  # create the GitHub Release so the version page is populated. No-op
80
102
  # when the trigger was already release:published.
@@ -2,6 +2,35 @@
2
2
 
3
3
  All notable changes to `imperal-sdk` are documented here.
4
4
 
5
+ ## 6.6.0 - 2026-11-13
6
+
7
+ From the imperal-mcp 0.9.14 field test.
8
+
9
+ ### Added
10
+ - `Symbol.doc`: a symbol carries its docstring or the comment above it; Python, TypeScript and JavaScript symbols also
11
+ take scope_facts' definitions (module constants such as `PANEL_ORIGIN`), so the local index and the vault's are one
12
+ extractor's.
13
+ - A project's own route decorator that names a URL path (`@door("/v1/x", methods=["GET"])`, `path=`, `method=`) declares
14
+ an endpoint; a decorator that names no path (`@lru_cache(128)`) does not.
15
+ - IR runner: `{{args.x}}` names the function's parameters, like `{{event.x}}` (the spec and every agent wrote `args`;
16
+ it resolved to "" and a stored link came back empty).
17
+
18
+ ### Fixed
19
+ - A function held by a `const` inside a function (an arrow handler inside a React component) is a definition; search
20
+ never found `completeSignIn`/`handleLogin` although outline saw them. `EXTRACTOR_VERSION` 5: the vault asks every
21
+ older blob again.
22
+ - IR: one rule for the checker and the runner. `validate_step` requires a step `id` and names verb fields placed at the
23
+ step root ("must go under 'args'"); `run_steps` validates every step before it runs; `store.create` without
24
+ `args.data` says so instead of `KeyError: 'data'`.
25
+
26
+ ## 6.5.3 - 2026-11-06
27
+
28
+ ### Added
29
+ - `code_links.contracts_reached(symbols, endpoints, callers_of)`: the endpoints a change reaches, meaning a handler
30
+ that is one of the symbols or calls one through up to 3 callers, each with its call chain. Field report 06.11 #3:
31
+ `contract_slice(session_for_sid)` returned nothing, because the endpoint's handler calls it and endpoints were matched
32
+ by their own text only. The kernel and the MCP use this one algorithm.
33
+
5
34
  ## 6.5.2 - 2026-11-06
6
35
 
7
36
  ### Fixed
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: imperal-sdk
3
- Version: 6.5.2
3
+ Version: 6.6.0
4
4
  Summary: SDK for building Imperal Cloud extensions
5
5
  Author: Imperal, Inc.
6
6
  Author-email: Valentin Scerbacov <valentin@imperal.io>
@@ -1,5 +1,5 @@
1
1
  {
2
- "sdk_version": "6.5.2",
2
+ "sdk_version": "6.6.0",
3
3
  "symbols": {
4
4
  "ActionResult": {
5
5
  "action_vocab_safe": false,
@@ -1,5 +1,5 @@
1
1
  {
2
- "_sdk_version": "6.5.2",
2
+ "_sdk_version": "6.6.0",
3
3
  "constants": {
4
4
  "max_call_depth": {
5
5
  "counts_root": true,
@@ -1,7 +1,7 @@
1
1
  """Imperal Cloud SDK — build extensions for the Imperal platform."""
2
2
  from typing import TYPE_CHECKING
3
3
 
4
- __version__ = "6.5.2"
4
+ __version__ = "6.6.0"
5
5
 
6
6
  # 5.2.2 (2026-06-11): the package root resolves its public surface lazily
7
7
  # (PEP 562). The eager imports pulled the HTTP transport (Context / client
@@ -12,6 +12,7 @@ import base64
12
12
  import hashlib
13
13
  import os
14
14
  import re
15
+ import dataclasses
15
16
  from dataclasses import asdict, dataclass, field
16
17
  from typing import Iterable
17
18
 
@@ -26,6 +27,7 @@ class Symbol:
26
27
  start_line: int
27
28
  end_line: int
28
29
  signature: str = ""
30
+ doc: str = "" # its docstring / the comment above it (from scope_facts) -- search answers carry it
29
31
 
30
32
 
31
33
  @dataclass
@@ -227,6 +229,33 @@ def _endpoint_refs(fn, call) -> tuple:
227
229
  return tuple(sorted(refs))
228
230
 
229
231
 
232
+ def _known_route_decorator(dec: "ast.Call") -> bool:
233
+ """@x.get / @x.route / @x.api_route: the frameworks' own route decorators (read below by their verb)."""
234
+ return isinstance(dec.func, ast.Attribute) and (dec.func.attr.lower() in _HTTP_METHODS
235
+ or dec.func.attr.lower() in ("route", "api_route"))
236
+
237
+
238
+ def _decorator_path(dec: "ast.Call") -> str:
239
+ """The URL path a decorator call declares: its first argument or path= / route= / rule=, when it starts with
240
+ "/" ("" for any decorator that names no path -- @lru_cache(128), @retry("x"))."""
241
+ cand = [dec.args[0]] if dec.args else []
242
+ cand += [k.value for k in dec.keywords if k.arg in ("path", "route", "rule")]
243
+ for c in cand:
244
+ got = _literal_string(c)
245
+ if isinstance(got, str) and got.startswith("/") and len(got) > 1 and " " not in got:
246
+ return got
247
+ return ""
248
+
249
+
250
+ def _method_kw(dec: "ast.Call") -> list:
251
+ """method="POST" as one keyword (the plural methods=[...] is _methods_kw's)."""
252
+ for k in dec.keywords:
253
+ if k.arg == "method":
254
+ got = _literal_string(k.value)
255
+ return [got.lower()] if got else []
256
+ return []
257
+
258
+
230
259
  def _python_contracts(path: str, text: str):
231
260
  try:
232
261
  tree = ast.parse(text)
@@ -247,6 +276,17 @@ def _python_contracts(path: str, text: str):
247
276
  node.lineno, _endpoint_refs(funcs.get(handler), node)))
248
277
  if isinstance(node, (ast.FunctionDef, ast.AsyncFunctionDef)):
249
278
  for dec in node.decorator_list:
279
+ if isinstance(dec, ast.Call) and not _known_route_decorator(dec):
280
+ # any other decorator that names a path is the project's own route declarer (live 2026-11-13:
281
+ # the gateway's @door("/v1/panel/redirect", methods=["GET"]) had no endpoint)
282
+ route = _decorator_path(dec)
283
+ if route:
284
+ for method in (_methods_kw(dec) or _method_kw(dec) or ["get"]):
285
+ if method in _HTTP_METHODS:
286
+ endpoints.append(EndpointEvidence(
287
+ method.upper(), _route_of(prefixes, "", route), node.name, path,
288
+ getattr(dec, "lineno", node.lineno), _endpoint_refs(node, dec)))
289
+ continue
250
290
  if not isinstance(dec, ast.Call) or not isinstance(dec.func, ast.Attribute):
251
291
  continue
252
292
  verb = dec.func.attr.lower()
@@ -683,9 +723,11 @@ def _lang_for(path: str) -> str:
683
723
  # 3 (2026-11-04): a blob is sent without its text -- facts with descriptions (``Def.doc``, ``BlobFacts.doc``), its
684
724
  # line hashes and size; a config as its parsed keys. The vault asks every version of an older extractor again, so the
685
725
  # text it held is replaced by the index (owner 2026-11-04: the vault holds the index, never the code)
686
- EXTRACTOR_VERSION = "4"
726
+ EXTRACTOR_VERSION = "5"
687
727
  # 4 (2026-11-06): Go, Rust, Java, Kotlin, C#, PHP, Ruby carry imports and references (``code_langs``); TS/JS default
688
728
  # exports, CommonJS exports, dynamic import(); Vue / Svelte / Astro components -- every older blob is asked again
729
+ # 5 (2026-11-13): a function held by a const inside a function (an arrow handler in a React component) is a
730
+ # definition with its doc; a bare route decorator (@door("/x")) declares an endpoint
689
731
  MAX_FILE_BYTES = 10 * 1024 * 1024 # one file in the code index (Cloud OS: shared vault, many users)
690
732
  MAX_REPO_FILES = 20_000
691
733
  INDEXABLE_EXT = (".py", ".pyi", ".ts", ".tsx", ".mts", ".cts", ".js", ".jsx", ".mjs", ".cjs", ".vue", ".svelte",
@@ -1646,8 +1688,10 @@ def _ts_walk(sc: _Scope, node, scope: list, ctx: str, local: set, exported: bool
1646
1688
  continue
1647
1689
  name, value = decl.child_by_field_name("name"), decl.child_by_field_name("value")
1648
1690
  typ = decl.child_by_field_name("type")
1649
- if name is not None and name.type == "identifier" and (not scope or scope[-1][1] == "class"):
1650
- fn_value = value is not None and value.type in _TS_FUNCTION_VALUES
1691
+ fn_value = value is not None and value.type in _TS_FUNCTION_VALUES
1692
+ # a function held by a const INSIDE a function is a definition too (live 2026-11-13: completeSignIn and
1693
+ # handleLogin inside a React component were never found by search_code, outline saw them)
1694
+ if name is not None and name.type == "identifier" and (not scope or scope[-1][1] == "class" or fn_value):
1651
1695
  if not scope or fn_value:
1652
1696
  nm = sc.text(name)
1653
1697
  parent = scope[-1] if scope else None
@@ -2240,9 +2284,40 @@ def parse_file(path: str, text: str) -> FileIndex | None:
2240
2284
  stack.extend(node.children)
2241
2285
  except Exception:
2242
2286
  return fi # parse error -> line-only, fail-soft
2287
+ if lang in _SCOPE_FACT_LANGS:
2288
+ _with_scope_defs(fi, path, text)
2243
2289
  return fi
2244
2290
 
2245
2291
 
2292
+ # the languages scope_facts reads: their symbols also take its definitions (nested arrow functions, module constants)
2293
+ # and descriptions, so the local index and the vault's index are one extractor's (2026-11-13)
2294
+ _SCOPE_FACT_LANGS = frozenset({"python", "typescript", "tsx", "javascript"})
2295
+ _SCOPE_DEF_KINDS = frozenset({"function", "method", "class", "type"})
2296
+
2297
+
2298
+ def _with_scope_defs(fi: "FileIndex", path: str, text: str) -> None:
2299
+ try:
2300
+ fx = scope_facts(path, text)
2301
+ except Exception:
2302
+ return
2303
+ if fx is None:
2304
+ return
2305
+ lines = text.split("\n")
2306
+ have = {(s.name, s.start_line): i for i, s in enumerate(fi.symbols)}
2307
+ for d in fx.defs:
2308
+ at = have.get((d.name, d.start_line))
2309
+ if at is not None:
2310
+ if d.doc and not fi.symbols[at].doc:
2311
+ fi.symbols[at] = dataclasses.replace(fi.symbols[at], doc=d.doc)
2312
+ continue
2313
+ # a module-level constant is a definition worth finding (PANEL_ORIGIN); a local variable is not
2314
+ if d.kind in _SCOPE_DEF_KINDS or (d.kind == "variable" and d.qualname == d.name):
2315
+ sig = (lines[d.start_line - 1] if 0 < d.start_line <= len(lines) else "")[:200]
2316
+ fi.symbols.append(Symbol(name=d.name, kind=d.kind, path=path, start_line=d.start_line,
2317
+ end_line=d.end_line, signature=sig, doc=d.doc))
2318
+ have[(d.name, d.start_line)] = len(fi.symbols) - 1
2319
+
2320
+
2246
2321
  def build_index(root: str, files: list[str]) -> ProjectIndex:
2247
2322
  idx = ProjectIndex()
2248
2323
  base = os.path.realpath(root)
@@ -831,3 +831,55 @@ def impact_summary(symbols, resolved, users: int, by_name: int, same_file: int =
831
831
  elif not users:
832
832
  head += " and no other file mentions the name"
833
833
  return head
834
+
835
+
836
+ # ── contracts reached through callers (field report 06.11 #3) ────────────────────────────────
837
+
838
+ def _bare(name) -> str:
839
+ """A definition's own name: ``path::Class.method`` -> ``method``."""
840
+ return str(name or "").split("::")[-1].rsplit(".", 1)[-1]
841
+
842
+
843
+ def contracts_reached(symbols, endpoints, callers_of, depth: int = 3, k: int = 50) -> list:
844
+ """The endpoints a change to ``symbols`` reaches: an endpoint whose handler IS one of them, or calls one of them
845
+ through up to ``depth`` callers. ``endpoints``: the catalog's records (``handler`` = the handler's qualname);
846
+ ``callers_of(names) -> {name: [qualnames of the definitions that call it]}`` asks the code graph (graph_slice).
847
+ Each endpoint returned carries ``via`` ("handler" | "caller") and ``chain`` (``mint_ticket -> session_for_sid``).
848
+ Field report 06.11 #3: contract_slice(session_for_sid) answered nothing -- the endpoint's handler CALLS it, and
849
+ endpoints were matched by their own text only. One algorithm for every client (kernel, MCP). PURE but for
850
+ ``callers_of``; never raises on a failing one (what was reached so far stands)."""
851
+ chain: dict = {}
852
+ for s in symbols or []:
853
+ b = _bare(s)
854
+ if b:
855
+ chain.setdefault(b, [b])
856
+ frontier = list(chain)
857
+ for _ in range(max(0, int(depth))):
858
+ if not frontier:
859
+ break
860
+ try:
861
+ got = callers_of(list(frontier)) or {}
862
+ except Exception:
863
+ break
864
+ nxt = []
865
+ for name in frontier:
866
+ for caller in got.get(name) or []:
867
+ c = _bare(caller)
868
+ if c and c not in chain:
869
+ chain[c] = [c] + chain[name]
870
+ nxt.append(c)
871
+ frontier = nxt
872
+ out, seen = [], set()
873
+ for e in endpoints or []:
874
+ if not isinstance(e, dict):
875
+ continue
876
+ h = _bare(e.get("handler"))
877
+ if h not in chain:
878
+ continue
879
+ key = (e.get("repo") or e.get("repo_key"), e.get("method"), e.get("route") or e.get("key"), h)
880
+ if key in seen:
881
+ continue
882
+ seen.add(key)
883
+ out.append({**e, "via": "handler" if len(chain[h]) == 1 else "caller", "chain": " -> ".join(chain[h])})
884
+ out.sort(key=lambda e: (len(str(e["chain"]).split(" -> ")), str(e.get("route") or e.get("key") or "")))
885
+ return out[:max(1, int(k))]
@@ -146,11 +146,25 @@ def validate_step(step: dict) -> list[str]:
146
146
  op = step.get("op")
147
147
  if op not in ACTION_SCHEMAS:
148
148
  return [f"unknown op {op!r}; valid verbs: {sorted(ACTION_SCHEMAS)}"]
149
+ # the runner needs an id on every step (runtime/interpreter.run_steps); one validator for both, so a step that
150
+ # validates also runs (2026-11-13: validate passed a step smoke then refused with "step missing required 'id'")
151
+ errs: list[str] = []
152
+ sid = step.get("id")
153
+ if not isinstance(sid, str) or not sid.strip():
154
+ errs.append("step needs an 'id' (a non-empty string other steps and conditionals can name)")
149
155
 
150
156
  if op == "conditional":
151
157
  # conditional is pure control-flow — its fields (if/then/else) live at
152
158
  # the step ROOT, not under args. Validate the step dict itself.
153
- return _validate_object(step, ACTION_SCHEMAS["conditional"])
159
+ return errs + _validate_object(step, ACTION_SCHEMAS["conditional"])
154
160
 
155
161
  args = step.get("args", {})
156
- return _validate_object(args, ACTION_SCHEMAS[op])
162
+ if not isinstance(args, dict):
163
+ return errs + [f"'args' must be an object, got {type(args).__name__}"]
164
+ misplaced = sorted(k for k in step if k not in ("id", "op", "args", "if", "then", "else")
165
+ and k in (ACTION_SCHEMAS[op].get("properties") or {}))
166
+ if misplaced:
167
+ # live 2026-11-13: {op, kind, data} at the step root read as "missing data" although data was right there
168
+ return errs + [f"{', '.join(misplaced)} must go under 'args': "
169
+ f"{{\"id\": ..., \"op\": \"{op}\", \"args\": {{{', '.join(repr(k) + ': ...' for k in misplaced)}}}}}"]
170
+ return errs + _validate_object(args, ACTION_SCHEMAS[op])
@@ -15,12 +15,17 @@ from .verbs import eval_conditional, run_store, run_ai, run_call, make_directive
15
15
 
16
16
  async def run_steps(steps: list[dict], ctx: Any, *, event: dict | None = None) -> dict:
17
17
  """Execute a non-Turing declarative steps[] flow. Returns {steps, prev}."""
18
- # Guard: all steps must have an "id"
19
- for step in steps:
20
- if "id" not in step:
21
- raise ValueError(f"step missing required 'id': {step!r}")
18
+ # one validator for the checker and the runner: every problem of every step, named, before anything runs
19
+ from imperal_sdk.ir.actions import validate_step
20
+ problems = [f"step {s.get('id') or i + 1}: {e}" for i, s in enumerate(steps)
21
+ for e in (validate_step(s) if isinstance(s, dict) else ["a step must be an object"])]
22
+ if problems:
23
+ raise ValueError("invalid steps: " + "; ".join(problems))
22
24
  by_id = {s["id"]: s for s in steps}
23
- tcx: dict[str, Any] = {"event": event or {}, "steps": {}, "prev": {}}
25
+ # `args` names the function's parameters too: the IR spec and every agent write {{args.x}}; it resolved to "" and
26
+ # a stored link came back with an empty url (2026-11-13). `event` stays the canonical name.
27
+ params = event or {}
28
+ tcx: dict[str, Any] = {"event": params, "args": params, "steps": {}, "prev": {}}
24
29
  # linear walk with conditional jumps
25
30
  order = [s["id"] for s in steps]
26
31
  budget = max(64, len(steps) * 8)
@@ -48,6 +48,8 @@ async def run_store(op: str, args: dict, store) -> dict:
48
48
  """
49
49
  coll = args.get("kind", "")
50
50
  if op == "create":
51
+ if not isinstance(args.get("data"), dict):
52
+ raise ValueError("store.create needs args.data (an object of the fields to store)")
51
53
  doc = await store.create(coll, args["data"])
52
54
  doc_id = doc.get("id") if isinstance(doc, dict) else getattr(doc, "id", None)
53
55
  return {"id": doc_id}
@@ -161,5 +161,5 @@ async def test_step_missing_id_raises():
161
161
  steps = [
162
162
  {"op": "send", "args": {"message": "no id here"}},
163
163
  ]
164
- with pytest.raises(ValueError, match="missing required 'id'"):
164
+ with pytest.raises(ValueError, match="needs an 'id'"):
165
165
  await run_steps(steps, ctx=_ctx(caps))
@@ -0,0 +1,52 @@
1
+ """2026-11-13 (imperal-mcp tester): validate_ir and smoke_ir disagreed about one step, and {{args.x}} stored "".
2
+ One rule now: a step that validates also runs, a step that does not run says why before anything runs."""
3
+ import pytest
4
+
5
+ from imperal_sdk.ir.actions import validate_step
6
+ from imperal_sdk.runtime.interpreter import run_steps
7
+
8
+
9
+ class _Store:
10
+ def __init__(self):
11
+ self.docs = []
12
+
13
+ async def create(self, coll, data):
14
+ self.docs.append((coll, data))
15
+ return {"id": f"d{len(self.docs)}"}
16
+
17
+
18
+ class _Ctx:
19
+ def __init__(self):
20
+ self.store = _Store()
21
+
22
+
23
+ SHAPES = [
24
+ ({"op": "store.create", "kind": "link", "data": {"url": "x"}}, False), # verb keys at the root, no id
25
+ ({"id": "s", "op": "store.create", "kind": "link", "data": {"url": "x"}}, False), # verb keys at the root
26
+ ({"op": "store.create", "args": {"kind": "link", "data": {"url": "x"}}}, False), # no id
27
+ ({"id": "s", "op": "store.create", "args": {"kind": "link", "data": {"url": "x"}}}, True),
28
+ ]
29
+
30
+
31
+ @pytest.mark.parametrize("step,ok", SHAPES)
32
+ @pytest.mark.asyncio
33
+ async def test_validate_and_run_agree(step, ok):
34
+ assert (validate_step(step) == []) is ok
35
+ if ok:
36
+ await run_steps([step], _Ctx())
37
+ else:
38
+ with pytest.raises(ValueError):
39
+ await run_steps([step], _Ctx())
40
+
41
+
42
+ def test_a_misplaced_key_is_named_with_where_it_goes():
43
+ errs = validate_step({"id": "s", "op": "store.create", "kind": "link", "data": {"url": "x"}})
44
+ assert any("must go under 'args'" in e and "data" in e for e in errs)
45
+
46
+
47
+ @pytest.mark.asyncio
48
+ async def test_args_names_the_functions_parameters():
49
+ ctx = _Ctx()
50
+ await run_steps([{"id": "s", "op": "store.create", "args": {"kind": "link", "data": {"url": "{{args.url}}"}}}],
51
+ ctx, event={"url": "https://imperal.io"})
52
+ assert ctx.store.docs == [("link", {"url": "https://imperal.io"})]
@@ -0,0 +1,32 @@
1
+ """Field report 06.11 #3: the endpoints a change reaches -- its handler, or a handler that calls it."""
2
+ from imperal_sdk.code_links import contracts_reached
3
+
4
+ EPS = [{"repo": "gw", "method": "POST", "route": "/v1/terminal/tickets", "handler": "mint_terminal_ticket",
5
+ "path": "app/routers/terminal.py"},
6
+ {"repo": "gw", "method": "GET", "route": "/v1/health", "handler": "health", "path": "app/routers/health.py"},
7
+ {"repo": "gw", "method": "POST", "route": "/v1/login", "handler": "Auth.login", "path": "app/routers/auth.py"}]
8
+ GRAPH = {"session_for_sid": ["app/routers/terminal.py::mint_terminal_ticket", "app/writers/auth.py::_write_auth_login"],
9
+ "_write_auth_login": ["Auth.login"]}
10
+
11
+
12
+ def callers(names):
13
+ return {n: GRAPH.get(n, []) for n in names}
14
+
15
+
16
+ def test_an_endpoint_whose_handler_calls_the_symbol_is_reached_with_its_chain():
17
+ got = contracts_reached(["session_for_sid"], EPS, callers)
18
+ assert [(e["route"], e["via"], e["chain"]) for e in got] == [
19
+ ("/v1/terminal/tickets", "caller", "mint_terminal_ticket -> session_for_sid"),
20
+ ("/v1/login", "caller", "login -> _write_auth_login -> session_for_sid")]
21
+
22
+
23
+ def test_the_handler_itself_and_the_depth_bound():
24
+ assert contracts_reached(["app/routers/health.py::health"], EPS, callers)[0]["via"] == "handler"
25
+ assert [e["route"] for e in contracts_reached(["session_for_sid"], EPS, callers, depth=1)] == ["/v1/terminal/tickets"]
26
+
27
+
28
+ def test_a_failing_graph_keeps_what_was_reached_and_nothing_is_invented():
29
+ def boom(names):
30
+ raise RuntimeError("vault down")
31
+ assert contracts_reached(["mint_terminal_ticket"], EPS, boom)[0]["via"] == "handler"
32
+ assert contracts_reached(["nothing_calls_me"], EPS, callers) == []
@@ -95,7 +95,7 @@ def test_one_table_and_the_old_private_names_stay_aliases():
95
95
  assert indexer.DEF_NODES["typescript"]["type_alias_declaration"] == "type"
96
96
  assert indexer.DEF_NODES["typescript"]["enum_declaration"] == "class"
97
97
  assert indexer._DEF_NODES is indexer.DEF_NODES and indexer._get_language is indexer.language
98
- assert indexer.EXTRACTOR_VERSION == "4" and indexer.MAX_FILE_BYTES == 10 * 1024 * 1024
98
+ assert indexer.EXTRACTOR_VERSION == "5" and indexer.MAX_FILE_BYTES == 10 * 1024 * 1024
99
99
  assert indexer.MAX_REPO_FILES == 20_000
100
100
 
101
101
 
@@ -0,0 +1,49 @@
1
+ """imperal-mcp field test 2026-11-13: what search_code, impact_of_change and contract_slice missed."""
2
+ import pytest
3
+
4
+ pytest.importorskip("tree_sitter")
5
+
6
+ from imperal_sdk.code_index import extract_contracts, parse_file, scope_facts # noqa: E402
7
+ from imperal_sdk.code_links import Linker # noqa: E402
8
+
9
+ TSX = '''/** Login page of the panel. */
10
+ export default function LoginPage() {
11
+ /** Finish the sign-in after the code is approved. */
12
+ const completeSignIn = async () => { return 1 };
13
+ const handleLogin = () => { completeSignIn() };
14
+ const count = 3;
15
+ return null
16
+ }
17
+ '''
18
+
19
+
20
+ def test_arrow_functions_inside_a_component_are_definitions_with_their_docs():
21
+ defs = {d.qualname: d for d in scope_facts("src/app/page.tsx", TSX).defs}
22
+ assert "LoginPage.completeSignIn" in defs and "LoginPage.handleLogin" in defs
23
+ assert "LoginPage.count" not in defs # a local value is no definition
24
+ syms = {s.name: s for s in parse_file("src/app/page.tsx", TSX).symbols}
25
+ assert {"LoginPage", "completeSignIn", "handleLogin"} <= set(syms) and "count" not in syms
26
+ assert syms["completeSignIn"].doc.startswith("Finish the sign-in") and syms["LoginPage"].doc
27
+
28
+
29
+ def test_a_python_module_constant_is_a_symbol_and_functions_carry_their_docstring():
30
+ py = 'PANEL_ORIGIN = "https://x"\n\n\ndef build_url(p):\n """Join the panel origin with a path."""\n return PANEL_ORIGIN + p\n'
31
+ syms = {s.name: s for s in parse_file("app/config.py", py).symbols}
32
+ assert syms["PANEL_ORIGIN"].kind == "variable" and syms["build_url"].doc.startswith("Join the panel")
33
+
34
+
35
+ def test_an_import_alone_is_named_by_name_never_hidden():
36
+ # an import with no use stays no resolved user (as in the vault: test_reexport_alias_...), but impact names it
37
+ from imperal_sdk.code_links import impact
38
+ files = {"config.py": 'PANEL_ORIGIN = "https://x"\n', "onlyimport.py": "from config import PANEL_ORIGIN\n"}
39
+ out = impact(Linker({p: scope_facts(p, t) for p, t in files.items()}), ["PANEL_ORIGIN"])
40
+ assert [b["path"] for b in out.get("by_name") or []] == ["onlyimport.py"]
41
+
42
+
43
+ def test_a_projects_own_route_decorator_declares_an_endpoint():
44
+ src = ('@door("/v1/panel/redirect", methods=["GET"])\nasync def redirect(r):\n return 1\n\n'
45
+ '@door(path="/v1/x", method="POST")\ndef make_x(r):\n return 2\n\n'
46
+ '@lru_cache(128)\ndef cached():\n return 3\n\n@retry("again")\ndef r2():\n return 4\n')
47
+ eps, _ = extract_contracts("app/routes.py", src, "python")
48
+ assert sorted((e.method, e.route, e.handler) for e in eps) == [
49
+ ("GET", "/v1/panel/redirect", "redirect"), ("POST", "/v1/x", "make_x")]
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes