gatewaysdk 0.3.2__py3-none-any.whl

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 (376) hide show
  1. gatewaysdk/__init__.py +540 -0
  2. gatewaysdk/adapter/__init__.py +15 -0
  3. gatewaysdk/adapter/base.py +94 -0
  4. gatewaysdk/adapter/messages.py +270 -0
  5. gatewaysdk/adapter/triplet.py +1026 -0
  6. gatewaysdk/algorithm/__init__.py +39 -0
  7. gatewaysdk/algorithm/apo/__init__.py +5 -0
  8. gatewaysdk/algorithm/apo/apo.py +898 -0
  9. gatewaysdk/algorithm/apo/prompts/apply_edit_variant01.poml +22 -0
  10. gatewaysdk/algorithm/apo/prompts/apply_edit_variant02.poml +18 -0
  11. gatewaysdk/algorithm/apo/prompts/text_gradient_variant01.poml +18 -0
  12. gatewaysdk/algorithm/apo/prompts/text_gradient_variant02.poml +16 -0
  13. gatewaysdk/algorithm/apo/prompts/text_gradient_variant03.poml +107 -0
  14. gatewaysdk/algorithm/base.py +262 -0
  15. gatewaysdk/algorithm/decorator.py +264 -0
  16. gatewaysdk/algorithm/evals/__init__.py +7 -0
  17. gatewaysdk/algorithm/evals/evals.py +217 -0
  18. gatewaysdk/algorithm/fast.py +250 -0
  19. gatewaysdk/algorithm/gepa/__init__.py +61 -0
  20. gatewaysdk/algorithm/gepa/adapter.py +495 -0
  21. gatewaysdk/algorithm/gepa/gepa.py +570 -0
  22. gatewaysdk/algorithm/gepa/lib/__init__.py +18 -0
  23. gatewaysdk/algorithm/gepa/lib/adapters/README.md +12 -0
  24. gatewaysdk/algorithm/gepa/lib/adapters/__init__.py +0 -0
  25. gatewaysdk/algorithm/gepa/lib/adapters/anymaths_adapter/README.md +341 -0
  26. gatewaysdk/algorithm/gepa/lib/adapters/anymaths_adapter/__init__.py +1 -0
  27. gatewaysdk/algorithm/gepa/lib/adapters/anymaths_adapter/anymaths_adapter.py +174 -0
  28. gatewaysdk/algorithm/gepa/lib/adapters/anymaths_adapter/requirements.txt +1 -0
  29. gatewaysdk/algorithm/gepa/lib/adapters/default_adapter/README.md +0 -0
  30. gatewaysdk/algorithm/gepa/lib/adapters/default_adapter/__init__.py +0 -0
  31. gatewaysdk/algorithm/gepa/lib/adapters/default_adapter/default_adapter.py +209 -0
  32. gatewaysdk/algorithm/gepa/lib/adapters/dspy_adapter/README.md +7 -0
  33. gatewaysdk/algorithm/gepa/lib/adapters/dspy_adapter/__init__.py +0 -0
  34. gatewaysdk/algorithm/gepa/lib/adapters/dspy_adapter/dspy_adapter.py +307 -0
  35. gatewaysdk/algorithm/gepa/lib/adapters/dspy_full_program_adapter/README.md +99 -0
  36. gatewaysdk/algorithm/gepa/lib/adapters/dspy_full_program_adapter/dspy_program_proposal_signature.py +137 -0
  37. gatewaysdk/algorithm/gepa/lib/adapters/dspy_full_program_adapter/full_program_adapter.py +268 -0
  38. gatewaysdk/algorithm/gepa/lib/adapters/generic_rag_adapter/GEPA_RAG.md +621 -0
  39. gatewaysdk/algorithm/gepa/lib/adapters/generic_rag_adapter/__init__.py +56 -0
  40. gatewaysdk/algorithm/gepa/lib/adapters/generic_rag_adapter/evaluation_metrics.py +226 -0
  41. gatewaysdk/algorithm/gepa/lib/adapters/generic_rag_adapter/generic_rag_adapter.py +496 -0
  42. gatewaysdk/algorithm/gepa/lib/adapters/generic_rag_adapter/rag_pipeline.py +238 -0
  43. gatewaysdk/algorithm/gepa/lib/adapters/generic_rag_adapter/vector_store_interface.py +212 -0
  44. gatewaysdk/algorithm/gepa/lib/adapters/generic_rag_adapter/vector_stores/__init__.py +2 -0
  45. gatewaysdk/algorithm/gepa/lib/adapters/generic_rag_adapter/vector_stores/chroma_store.py +196 -0
  46. gatewaysdk/algorithm/gepa/lib/adapters/generic_rag_adapter/vector_stores/lancedb_store.py +422 -0
  47. gatewaysdk/algorithm/gepa/lib/adapters/generic_rag_adapter/vector_stores/milvus_store.py +409 -0
  48. gatewaysdk/algorithm/gepa/lib/adapters/generic_rag_adapter/vector_stores/qdrant_store.py +368 -0
  49. gatewaysdk/algorithm/gepa/lib/adapters/generic_rag_adapter/vector_stores/weaviate_store.py +418 -0
  50. gatewaysdk/algorithm/gepa/lib/adapters/mcp_adapter/README.md +552 -0
  51. gatewaysdk/algorithm/gepa/lib/adapters/mcp_adapter/__init__.py +37 -0
  52. gatewaysdk/algorithm/gepa/lib/adapters/mcp_adapter/mcp_adapter.py +699 -0
  53. gatewaysdk/algorithm/gepa/lib/adapters/mcp_adapter/mcp_client.py +364 -0
  54. gatewaysdk/algorithm/gepa/lib/adapters/terminal_bench_adapter/README.md +9 -0
  55. gatewaysdk/algorithm/gepa/lib/adapters/terminal_bench_adapter/__init__.py +0 -0
  56. gatewaysdk/algorithm/gepa/lib/adapters/terminal_bench_adapter/terminal_bench_adapter.py +217 -0
  57. gatewaysdk/algorithm/gepa/lib/api.py +382 -0
  58. gatewaysdk/algorithm/gepa/lib/core/__init__.py +0 -0
  59. gatewaysdk/algorithm/gepa/lib/core/adapter.py +180 -0
  60. gatewaysdk/algorithm/gepa/lib/core/data_loader.py +74 -0
  61. gatewaysdk/algorithm/gepa/lib/core/engine.py +379 -0
  62. gatewaysdk/algorithm/gepa/lib/core/result.py +233 -0
  63. gatewaysdk/algorithm/gepa/lib/core/state.py +636 -0
  64. gatewaysdk/algorithm/gepa/lib/examples/__init__.py +0 -0
  65. gatewaysdk/algorithm/gepa/lib/examples/aime.py +24 -0
  66. gatewaysdk/algorithm/gepa/lib/examples/anymaths-bench/eval_default.py +111 -0
  67. gatewaysdk/algorithm/gepa/lib/examples/anymaths-bench/prompt-templates/instruction_prompt.txt +9 -0
  68. gatewaysdk/algorithm/gepa/lib/examples/anymaths-bench/prompt-templates/optimal_prompt.txt +24 -0
  69. gatewaysdk/algorithm/gepa/lib/examples/anymaths-bench/train_anymaths.py +177 -0
  70. gatewaysdk/algorithm/gepa/lib/examples/dspy_full_program_evolution/arc_agi.ipynb +25705 -0
  71. gatewaysdk/algorithm/gepa/lib/examples/dspy_full_program_evolution/example.ipynb +348 -0
  72. gatewaysdk/algorithm/gepa/lib/examples/mcp_adapter/__init__.py +4 -0
  73. gatewaysdk/algorithm/gepa/lib/examples/mcp_adapter/mcp_optimization_example.py +456 -0
  74. gatewaysdk/algorithm/gepa/lib/examples/rag_adapter/RAG_GUIDE.md +613 -0
  75. gatewaysdk/algorithm/gepa/lib/examples/rag_adapter/__init__.py +9 -0
  76. gatewaysdk/algorithm/gepa/lib/examples/rag_adapter/rag_optimization.py +820 -0
  77. gatewaysdk/algorithm/gepa/lib/examples/rag_adapter/requirements-rag.txt +29 -0
  78. gatewaysdk/algorithm/gepa/lib/examples/terminal-bench/prompt-templates/instruction_prompt.txt +16 -0
  79. gatewaysdk/algorithm/gepa/lib/examples/terminal-bench/prompt-templates/terminus.txt +9 -0
  80. gatewaysdk/algorithm/gepa/lib/examples/terminal-bench/train_terminus.py +161 -0
  81. gatewaysdk/algorithm/gepa/lib/gepa_utils.py +117 -0
  82. gatewaysdk/algorithm/gepa/lib/logging/__init__.py +0 -0
  83. gatewaysdk/algorithm/gepa/lib/logging/experiment_tracker.py +187 -0
  84. gatewaysdk/algorithm/gepa/lib/logging/logger.py +75 -0
  85. gatewaysdk/algorithm/gepa/lib/logging/utils.py +103 -0
  86. gatewaysdk/algorithm/gepa/lib/proposer/__init__.py +0 -0
  87. gatewaysdk/algorithm/gepa/lib/proposer/base.py +31 -0
  88. gatewaysdk/algorithm/gepa/lib/proposer/merge.py +357 -0
  89. gatewaysdk/algorithm/gepa/lib/proposer/reflective_mutation/__init__.py +0 -0
  90. gatewaysdk/algorithm/gepa/lib/proposer/reflective_mutation/base.py +49 -0
  91. gatewaysdk/algorithm/gepa/lib/proposer/reflective_mutation/reflective_mutation.py +176 -0
  92. gatewaysdk/algorithm/gepa/lib/py.typed +0 -0
  93. gatewaysdk/algorithm/gepa/lib/strategies/__init__.py +0 -0
  94. gatewaysdk/algorithm/gepa/lib/strategies/batch_sampler.py +77 -0
  95. gatewaysdk/algorithm/gepa/lib/strategies/candidate_selector.py +50 -0
  96. gatewaysdk/algorithm/gepa/lib/strategies/component_selector.py +36 -0
  97. gatewaysdk/algorithm/gepa/lib/strategies/eval_policy.py +64 -0
  98. gatewaysdk/algorithm/gepa/lib/strategies/instruction_proposal.py +126 -0
  99. gatewaysdk/algorithm/gepa/lib/utils/__init__.py +10 -0
  100. gatewaysdk/algorithm/gepa/lib/utils/stop_condition.py +196 -0
  101. gatewaysdk/algorithm/gepa/tracing.py +105 -0
  102. gatewaysdk/algorithm/utils.py +177 -0
  103. gatewaysdk/algorithm/verl/__init__.py +5 -0
  104. gatewaysdk/algorithm/verl/interface.py +202 -0
  105. gatewaysdk/automations.py +111 -0
  106. gatewaysdk/benchmark_hub/README.md +88 -0
  107. gatewaysdk/benchmark_hub/__init__.py +119 -0
  108. gatewaysdk/benchmark_hub/_archive.py +189 -0
  109. gatewaysdk/benchmark_hub/_tar.py +6 -0
  110. gatewaysdk/benchmark_hub/client.py +992 -0
  111. gatewaysdk/benchmark_hub/dispatch_shard.py +34 -0
  112. gatewaysdk/benchmark_hub/eval_config.py +20 -0
  113. gatewaysdk/benchmark_hub/evals.py +351 -0
  114. gatewaysdk/benchmark_hub/harbor_adapter.py +673 -0
  115. gatewaysdk/benchmark_hub/path_utils.py +81 -0
  116. gatewaysdk/benchmark_hub/save_utils.py +101 -0
  117. gatewaysdk/benchmark_hub/verifiers_adapter.py +327 -0
  118. gatewaysdk/benchmark_hub/versioning.py +72 -0
  119. gatewaysdk/build.py +515 -0
  120. gatewaysdk/cli/__init__.py +58 -0
  121. gatewaysdk/cli/agent_runner.py +132 -0
  122. gatewaysdk/cli/http_client.py +115 -0
  123. gatewaysdk/cli/platform.py +4086 -0
  124. gatewaysdk/cli/prometheus.py +115 -0
  125. gatewaysdk/cli/release_gate.py +215 -0
  126. gatewaysdk/cli/store.py +131 -0
  127. gatewaysdk/cli/vllm.py +29 -0
  128. gatewaysdk/client.py +406 -0
  129. gatewaysdk/config.py +348 -0
  130. gatewaysdk/connectors/__init__.py +25 -0
  131. gatewaysdk/connectors/client.py +203 -0
  132. gatewaysdk/connectors/skill.py +25 -0
  133. gatewaysdk/connectors/template.py +106 -0
  134. gatewaysdk/context.py +606 -0
  135. gatewaysdk/emitter/__init__.py +43 -0
  136. gatewaysdk/emitter/annotation.py +370 -0
  137. gatewaysdk/emitter/exception.py +54 -0
  138. gatewaysdk/emitter/message.py +61 -0
  139. gatewaysdk/emitter/object.py +117 -0
  140. gatewaysdk/emitter/reward.py +320 -0
  141. gatewaysdk/env_var.py +156 -0
  142. gatewaysdk/environment/__init__.py +108 -0
  143. gatewaysdk/environment/_bundle.py +281 -0
  144. gatewaysdk/environment/_harbor.py +276 -0
  145. gatewaysdk/environment/_materialize.py +97 -0
  146. gatewaysdk/environment/_tar.py +33 -0
  147. gatewaysdk/environment/_world.py +346 -0
  148. gatewaysdk/environment/core.py +527 -0
  149. gatewaysdk/environment/errors.py +58 -0
  150. gatewaysdk/environment/runtime.py +150 -0
  151. gatewaysdk/environment/schema/__init__.py +35 -0
  152. gatewaysdk/environment/schema/__main__.py +225 -0
  153. gatewaysdk/environment/schema/_slack_fidelity.py +116 -0
  154. gatewaysdk/environment/schema/_slack_scenario.py +183 -0
  155. gatewaysdk/environment/schema/api.py +1628 -0
  156. gatewaysdk/environment/schema/batch.py +755 -0
  157. gatewaysdk/environment/schema/compiler.py +615 -0
  158. gatewaysdk/environment/schema/conform.py +428 -0
  159. gatewaysdk/environment/schema/connector.py +777 -0
  160. gatewaysdk/environment/schema/connectors/apple-business-manager/handlers.py +17 -0
  161. gatewaysdk/environment/schema/connectors/apple-business-manager/parity.json +28 -0
  162. gatewaysdk/environment/schema/connectors/apple-business-manager/provenance.json +233 -0
  163. gatewaysdk/environment/schema/connectors/apple-business-manager/scope.toml +112 -0
  164. gatewaysdk/environment/schema/connectors/apple-business-manager/world.json +1380 -0
  165. gatewaysdk/environment/schema/connectors/base.json +28 -0
  166. gatewaysdk/environment/schema/connectors/custom/handlers.py +18 -0
  167. gatewaysdk/environment/schema/connectors/custom/world.json +123 -0
  168. gatewaysdk/environment/schema/connectors/github/handlers.py +81 -0
  169. gatewaysdk/environment/schema/connectors/github/parity.json +37 -0
  170. gatewaysdk/environment/schema/connectors/github/provenance.json +134 -0
  171. gatewaysdk/environment/schema/connectors/github/scope.toml +158 -0
  172. gatewaysdk/environment/schema/connectors/github/world.json +5869 -0
  173. gatewaysdk/environment/schema/connectors/google-calendar/handlers.py +23 -0
  174. gatewaysdk/environment/schema/connectors/google-calendar/world.json +209 -0
  175. gatewaysdk/environment/schema/connectors/google-drive/handlers.py +18 -0
  176. gatewaysdk/environment/schema/connectors/google-drive/world.json +286 -0
  177. gatewaysdk/environment/schema/connectors/jamf/handlers.py +34 -0
  178. gatewaysdk/environment/schema/connectors/jamf/parity.json +49 -0
  179. gatewaysdk/environment/schema/connectors/jamf/provenance.json +181 -0
  180. gatewaysdk/environment/schema/connectors/jamf/scope.toml +128 -0
  181. gatewaysdk/environment/schema/connectors/jamf/world.json +2218 -0
  182. gatewaysdk/environment/schema/connectors/jira/handlers.py +28 -0
  183. gatewaysdk/environment/schema/connectors/jira/world.json +389 -0
  184. gatewaysdk/environment/schema/connectors/kandji/handlers.py +38 -0
  185. gatewaysdk/environment/schema/connectors/kandji/parity.json +29 -0
  186. gatewaysdk/environment/schema/connectors/kandji/provenance.json +152 -0
  187. gatewaysdk/environment/schema/connectors/kandji/scope.toml +120 -0
  188. gatewaysdk/environment/schema/connectors/kandji/world.json +765 -0
  189. gatewaysdk/environment/schema/connectors/linear/handlers.py +20 -0
  190. gatewaysdk/environment/schema/connectors/linear/world.json +363 -0
  191. gatewaysdk/environment/schema/connectors/microsoft-teams/fidelity.json +45 -0
  192. gatewaysdk/environment/schema/connectors/microsoft-teams/handlers.py +1 -0
  193. gatewaysdk/environment/schema/connectors/microsoft-teams/provenance.json +851 -0
  194. gatewaysdk/environment/schema/connectors/microsoft-teams/scope.md +231 -0
  195. gatewaysdk/environment/schema/connectors/microsoft-teams/teams-types.json +1710 -0
  196. gatewaysdk/environment/schema/connectors/microsoft-teams/world.json +858 -0
  197. gatewaysdk/environment/schema/connectors/netsuite/handlers.py +32 -0
  198. gatewaysdk/environment/schema/connectors/netsuite/parity.json +50 -0
  199. gatewaysdk/environment/schema/connectors/netsuite/provenance.json +137 -0
  200. gatewaysdk/environment/schema/connectors/netsuite/scope.toml +78 -0
  201. gatewaysdk/environment/schema/connectors/netsuite/world.json +16243 -0
  202. gatewaysdk/environment/schema/connectors/salesforce/handlers.py +806 -0
  203. gatewaysdk/environment/schema/connectors/salesforce/parity.json +46 -0
  204. gatewaysdk/environment/schema/connectors/salesforce/provenance.json +143 -0
  205. gatewaysdk/environment/schema/connectors/salesforce/scope.toml +174 -0
  206. gatewaysdk/environment/schema/connectors/salesforce/world.json +4695 -0
  207. gatewaysdk/environment/schema/connectors/slack/MODEL.md +236 -0
  208. gatewaysdk/environment/schema/connectors/slack/capabilities.json +1039 -0
  209. gatewaysdk/environment/schema/connectors/slack/handlers.py +762 -0
  210. gatewaysdk/environment/schema/connectors/slack/parity.json +65 -0
  211. gatewaysdk/environment/schema/connectors/slack/provenance.json +294 -0
  212. gatewaysdk/environment/schema/connectors/slack/scope.toml +44 -0
  213. gatewaysdk/environment/schema/connectors/slack/world.json +4993 -0
  214. gatewaysdk/environment/schema/connectors/workday/handlers.py +75 -0
  215. gatewaysdk/environment/schema/connectors/workday/parity.json +36 -0
  216. gatewaysdk/environment/schema/connectors/workday/provenance.json +179 -0
  217. gatewaysdk/environment/schema/connectors/workday/scope.toml +180 -0
  218. gatewaysdk/environment/schema/connectors/workday/world.json +806 -0
  219. gatewaysdk/environment/schema/data.py +593 -0
  220. gatewaysdk/environment/schema/extract.py +263 -0
  221. gatewaysdk/environment/schema/host.py +2437 -0
  222. gatewaysdk/environment/schema/host_surfaces.py +275 -0
  223. gatewaysdk/environment/schema/platform.py +1272 -0
  224. gatewaysdk/environment/schema/scaffold.py +250 -0
  225. gatewaysdk/environment/schema/skill.py +118 -0
  226. gatewaysdk/environment/schema/skills/agents/connector-template-author.md +202 -0
  227. gatewaysdk/environment/schema/skills/connector-schema-authoring/CONNECTORS.md +331 -0
  228. gatewaysdk/environment/schema/skills/connector-schema-authoring/CONVENTIONS.md +100 -0
  229. gatewaysdk/environment/schema/skills/connector-schema-authoring/SKILL.md +313 -0
  230. gatewaysdk/environment/schema/skills/world-data-ingestion/ROWS.md +223 -0
  231. gatewaysdk/environment/schema/skills/world-data-ingestion/SKILL.md +293 -0
  232. gatewaysdk/environment/schema/skills/worlds-getting-started/SKILL.md +390 -0
  233. gatewaysdk/environment/schema/slack.py +757 -0
  234. gatewaysdk/environment/schema/snapshot.py +479 -0
  235. gatewaysdk/environment/schema/store.py +904 -0
  236. gatewaysdk/environment/schema/tasks.py +525 -0
  237. gatewaysdk/environment/schema/tools_world.py +322 -0
  238. gatewaysdk/environment/schema/validation.py +577 -0
  239. gatewaysdk/environment/schema/worker.py +78 -0
  240. gatewaysdk/environment/schema/workers.py +500 -0
  241. gatewaysdk/environment/schema/world_tests.py +336 -0
  242. gatewaysdk/environments/__init__.py +24 -0
  243. gatewaysdk/environments/client.py +486 -0
  244. gatewaysdk/environments/types.py +318 -0
  245. gatewaysdk/execution/__init__.py +15 -0
  246. gatewaysdk/execution/base.py +64 -0
  247. gatewaysdk/execution/client_server.py +443 -0
  248. gatewaysdk/execution/events.py +69 -0
  249. gatewaysdk/execution/inter_process.py +16 -0
  250. gatewaysdk/execution/shared_memory.py +282 -0
  251. gatewaysdk/experiments/__init__.py +90 -0
  252. gatewaysdk/experiments/assignment.py +177 -0
  253. gatewaysdk/experiments/client.py +877 -0
  254. gatewaysdk/experiments/exposure.py +222 -0
  255. gatewaysdk/experiments/types.py +81 -0
  256. gatewaysdk/importers/__init__.py +49 -0
  257. gatewaysdk/importers/_normalize.py +91 -0
  258. gatewaysdk/importers/builder.py +173 -0
  259. gatewaysdk/importers/client.py +95 -0
  260. gatewaysdk/importers/langsmith.py +196 -0
  261. gatewaysdk/importers/recipes.py +249 -0
  262. gatewaysdk/instrumentation/__init__.py +300 -0
  263. gatewaysdk/instrumentation/agentops.py +314 -0
  264. gatewaysdk/instrumentation/agentops_langchain.py +45 -0
  265. gatewaysdk/instrumentation/base.py +119 -0
  266. gatewaysdk/instrumentation/litellm.py +83 -0
  267. gatewaysdk/instrumentation/registry.py +273 -0
  268. gatewaysdk/instrumentation/vllm.py +81 -0
  269. gatewaysdk/instrumentation/weave.py +500 -0
  270. gatewaysdk/integrations/__init__.py +15 -0
  271. gatewaysdk/integrations/gateway/__init__.py +11 -0
  272. gatewaysdk/integrations/gateway/client.py +171 -0
  273. gatewaysdk/integrations/tool_access.py +549 -0
  274. gatewaysdk/litagent/__init__.py +11 -0
  275. gatewaysdk/litagent/decorator.py +536 -0
  276. gatewaysdk/litagent/litagent.py +252 -0
  277. gatewaysdk/llm_proxy.py +1742 -0
  278. gatewaysdk/logging.py +370 -0
  279. gatewaysdk/memory.py +278 -0
  280. gatewaysdk/personas.py +186 -0
  281. gatewaysdk/platform/__init__.py +17 -0
  282. gatewaysdk/platform/builder.py +221 -0
  283. gatewaysdk/platform/compatibility.py +67 -0
  284. gatewaysdk/platform/manifest.py +185 -0
  285. gatewaysdk/platform/orchestrator.py +901 -0
  286. gatewaysdk/platform/registry.py +122 -0
  287. gatewaysdk/platform/worker.py +864 -0
  288. gatewaysdk/replay/__init__.py +1032 -0
  289. gatewaysdk/replay/pytest.py +56 -0
  290. gatewaysdk/reward.py +7 -0
  291. gatewaysdk/run.py +1781 -0
  292. gatewaysdk/runner/__init__.py +11 -0
  293. gatewaysdk/runner/agent.py +878 -0
  294. gatewaysdk/runner/base.py +182 -0
  295. gatewaysdk/runner/legacy.py +309 -0
  296. gatewaysdk/security.py +700 -0
  297. gatewaysdk/semconv.py +170 -0
  298. gatewaysdk/server.py +399 -0
  299. gatewaysdk/sessions.py +282 -0
  300. gatewaysdk/store/__init__.py +45 -0
  301. gatewaysdk/store/base.py +908 -0
  302. gatewaysdk/store/client_server.py +2093 -0
  303. gatewaysdk/store/collection/__init__.py +30 -0
  304. gatewaysdk/store/collection/base.py +587 -0
  305. gatewaysdk/store/collection/memory.py +970 -0
  306. gatewaysdk/store/collection/mongo.py +1412 -0
  307. gatewaysdk/store/collection_based.py +1823 -0
  308. gatewaysdk/store/gateway.py +983 -0
  309. gatewaysdk/store/gateway_listener.py +465 -0
  310. gatewaysdk/store/listener.py +58 -0
  311. gatewaysdk/store/memory.py +396 -0
  312. gatewaysdk/store/mongo.py +165 -0
  313. gatewaysdk/store/redis_stream.py +517 -0
  314. gatewaysdk/store/sqlite.py +3 -0
  315. gatewaysdk/store/threading.py +370 -0
  316. gatewaysdk/store/utils.py +142 -0
  317. gatewaysdk/tracer/__init__.py +14 -0
  318. gatewaysdk/tracer/base.py +286 -0
  319. gatewaysdk/tracer/dummy.py +106 -0
  320. gatewaysdk/tracer/otel.py +559 -0
  321. gatewaysdk/tracing/__init__.py +110 -0
  322. gatewaysdk/tracing/api.py +808 -0
  323. gatewaysdk/tracing/attributes.py +9 -0
  324. gatewaysdk/tracing/context.py +272 -0
  325. gatewaysdk/tracing/exporters/__init__.py +10 -0
  326. gatewaysdk/tracing/exporters/gateway.py +228 -0
  327. gatewaysdk/tracing/identity.py +288 -0
  328. gatewaysdk/tracing/init.py +620 -0
  329. gatewaysdk/tracing/instrumentors/__init__.py +15 -0
  330. gatewaysdk/tracing/instrumentors/claude_agent_sdk.py +766 -0
  331. gatewaysdk/tracing/instrumentors/instrumentation_principles.md +294 -0
  332. gatewaysdk/tracing/instrumentors/registry.py +352 -0
  333. gatewaysdk/tracing/mapping.py +729 -0
  334. gatewaysdk/tracing/processors.py +393 -0
  335. gatewaysdk/tracing/push.py +617 -0
  336. gatewaysdk/tracing/push_models.py +247 -0
  337. gatewaysdk/tracing/semconv.py +294 -0
  338. gatewaysdk/tracing/span_builder.py +356 -0
  339. gatewaysdk/trainer/__init__.py +6 -0
  340. gatewaysdk/trainer/init_utils.py +263 -0
  341. gatewaysdk/trainer/legacy.py +359 -0
  342. gatewaysdk/trainer/registry.py +12 -0
  343. gatewaysdk/trainer/trainer.py +638 -0
  344. gatewaysdk/types/__init__.py +63 -0
  345. gatewaysdk/types/core.py +556 -0
  346. gatewaysdk/types/resources.py +204 -0
  347. gatewaysdk/types/tracer.py +515 -0
  348. gatewaysdk/types/tracing.py +162 -0
  349. gatewaysdk/users.py +251 -0
  350. gatewaysdk/utils/__init__.py +1 -0
  351. gatewaysdk/utils/id.py +18 -0
  352. gatewaysdk/utils/metrics.py +1025 -0
  353. gatewaysdk/utils/otel.py +550 -0
  354. gatewaysdk/utils/otlp.py +556 -0
  355. gatewaysdk/utils/redact.py +22 -0
  356. gatewaysdk/utils/server_launcher.py +1045 -0
  357. gatewaysdk/utils/system_snapshot.py +90 -0
  358. gatewaysdk/verl/__init__.py +8 -0
  359. gatewaysdk/verl/__main__.py +6 -0
  360. gatewaysdk/verl/async_server.py +46 -0
  361. gatewaysdk/verl/config.yaml +27 -0
  362. gatewaysdk/verl/daemon.py +1154 -0
  363. gatewaysdk/verl/dataset.py +44 -0
  364. gatewaysdk/verl/entrypoint.py +248 -0
  365. gatewaysdk/verl/trainer.py +549 -0
  366. gatewaysdk/world_browser.py +748 -0
  367. gatewaysdk/world_data.py +453 -0
  368. gatewaysdk/world_sessions.py +978 -0
  369. gatewaysdk/world_tasks.py +285 -0
  370. gatewaysdk/world_tools.py +115 -0
  371. gatewaysdk/worlds.py +639 -0
  372. gatewaysdk-0.3.2.dist-info/METADATA +236 -0
  373. gatewaysdk-0.3.2.dist-info/RECORD +376 -0
  374. gatewaysdk-0.3.2.dist-info/WHEEL +4 -0
  375. gatewaysdk-0.3.2.dist-info/entry_points.txt +5 -0
  376. gatewaysdk-0.3.2.dist-info/licenses/LICENSE +19 -0
@@ -0,0 +1,250 @@
1
+ """Initialize a schema world from a connector template or the custom template.
2
+
3
+ Templates are authored ``gateway-world/1`` contracts shipped with the SDK, one
4
+ directory per connector under ``connectors/``. Initializing copies the authored
5
+ files, compiles them, and writes an empty initial batch; the world starts with
6
+ no records and is filled by ingestion or by hand-authored fixture batches.
7
+ """
8
+
9
+ from __future__ import annotations
10
+
11
+ import json
12
+ import shutil
13
+ from pathlib import Path
14
+
15
+ from .compiler import Contract, compile_bundle
16
+ from .validation import ContractError, encoded, fail, read_json
17
+
18
+ TEMPLATES = Path(__file__).resolve().parent / "connectors"
19
+ CUSTOM = "custom"
20
+ MANIFEST = """[environment]
21
+ name = "{name}"
22
+ kind = "mock-tools"
23
+ db = "sqlite"
24
+ connector = "{connector}"
25
+
26
+ [schema]
27
+ language = "gateway-world/1"
28
+
29
+ [tools]
30
+ serve = [{serve}]
31
+
32
+ [db]
33
+ engine = "sqlite"
34
+ """
35
+ VERIFIER = """-- Scores 1.0 once the world holds any {entity} row; edit for real tasks.
36
+ SELECT CASE WHEN COUNT(*) > 0 THEN 1.0 ELSE 0.0 END FROM "{entity}";
37
+ """
38
+
39
+
40
+ def list_templates() -> list[str]:
41
+ """Connector slugs that ``init_bundle`` accepts, custom last."""
42
+ slugs = sorted(p.name for p in TEMPLATES.iterdir() if (p / "world.json").is_file())
43
+ return [s for s in slugs if s != CUSTOM] + [CUSTOM]
44
+
45
+
46
+ def _slug(value: str, location: str) -> str:
47
+ if not value or any(c not in "abcdefghijklmnopqrstuvwxyz0123456789-_" for c in value):
48
+ fail("identity", "Use lowercase letters, digits, - or _", location)
49
+ return value
50
+
51
+
52
+ def _resource(path: Path) -> Path:
53
+ if path.is_symlink() or path.parent.is_symlink() or not path.is_file():
54
+ fail("template", "Template resources must be regular files, not symlinks", str(path))
55
+ return path
56
+
57
+
58
+ SUPPORTING_SUFFIXES = {".json", ".md", ".toml"}
59
+ GENERATED_NAMES = {"base.json", "runtime.json", "lock.json", "README.md", "tool-schemas.json"}
60
+ #: Template files that are not schema artifacts but travel with a workspace connector.
61
+ TEMPLATE_CODE = {"handlers.py", "api/handlers.py"}
62
+
63
+
64
+ def template_digest(files: dict[str, bytes]) -> str:
65
+ """The same digest the platform computes over an installed template directory:
66
+ sha256 over sorted ``path\0bytes\0``. A workspace connector's commit and an
67
+ installed template with identical files therefore pin identically."""
68
+ import hashlib
69
+
70
+ digest = hashlib.sha256()
71
+ for path in sorted(files):
72
+ digest.update(path.encode("utf-8"))
73
+ digest.update(b"\0")
74
+ digest.update(files[path])
75
+ digest.update(b"\0")
76
+ return digest.hexdigest()
77
+
78
+
79
+ def init_bundle_from_files(
80
+ destination: str | Path, files: dict[str, bytes], *, connector: str, name: str | None = None
81
+ ) -> Contract:
82
+ """Create and compile a schema world from a template held in memory: a workspace
83
+ connector's files (``world.json``, ``connector.toml``, ``provenance.json``,
84
+ ``scope.toml``, ``handlers.py``, ``api/handlers.py``, ``scenarios/…``), exactly
85
+ what :func:`init_bundle` reads from an installed template directory.
86
+
87
+ ``connector`` names the template for the manifest; ``name`` the world."""
88
+ destination = Path(destination)
89
+ connector = _slug(connector, "/init/connector")
90
+ name = _slug(name if name is not None else f"{connector}-world", "/init/name")
91
+ if destination.exists() and (not destination.is_dir() or any(destination.iterdir())):
92
+ fail("state_exists", "Destination must be a new or empty directory", "/init")
93
+ if "world.json" not in files:
94
+ fail("template", "A connector template needs world.json", "/init/files")
95
+ if not all(isinstance(k, str) and k and not k.startswith("/") and ".." not in k.split("/") for k in files):
96
+ fail("template", "Template paths must be relative and stay inside the template", "/init/files")
97
+ try:
98
+ world = json.loads(files["world.json"].decode("utf-8"))
99
+ except (UnicodeDecodeError, ValueError):
100
+ fail("template", "world.json is not valid JSON", "/init/files/world.json")
101
+ if not isinstance(world, dict) or not isinstance(world.get("x-gateway"), dict):
102
+ fail("template", "world.json is not a gateway-world document", "/init/files/world.json")
103
+ world["x-gateway"]["package"]["id"] = name
104
+ tools = sorted(world["x-gateway"].get("tools", {}))
105
+ try:
106
+ (destination / "schema").mkdir(parents=True)
107
+ (destination / "schema/world.json").write_bytes(_pretty(world))
108
+ shutil.copyfile(_resource(TEMPLATES / "base.json"), destination / "schema/base.json")
109
+ (destination / "tools").mkdir()
110
+ handlers = files.get("handlers.py") or files.get("tools/handlers.py")
111
+ (destination / "tools/handlers.py").write_bytes(handlers if handlers is not None else b"")
112
+ for path, content in sorted(files.items()):
113
+ if path in {"world.json", "handlers.py", "tools/handlers.py"} or path.startswith("__pycache__"):
114
+ continue
115
+ if path == "connector.toml":
116
+ target = destination / "connector.toml"
117
+ elif path.startswith(("api/", "scenarios/")):
118
+ target = destination / path
119
+ elif path.startswith("evidence/") or path.startswith("reports/"):
120
+ continue # authoring evidence stays with the connector, not the world
121
+ elif (
122
+ Path(path).suffix in SUPPORTING_SUFFIXES and Path(path).name not in GENERATED_NAMES and "/" not in path
123
+ ):
124
+ target = destination / "schema" / path
125
+ else:
126
+ fail("template", "Unsupported or generated template artifact", f"/init/files/{path}")
127
+ target.parent.mkdir(parents=True, exist_ok=True)
128
+ target.write_bytes(content)
129
+ (destination / "gateway-env.toml").write_text(
130
+ MANIFEST.format(name=name, connector=connector, serve=", ".join(f'"{t}"' for t in tools)),
131
+ encoding="utf-8",
132
+ )
133
+ entities = sorted(world["x-gateway"].get("entities", {}))
134
+ if not entities:
135
+ fail("template", "world.json declares no entities", "/init/files/world.json")
136
+ (destination / "verifiers").mkdir()
137
+ (destination / "verifiers/state_present.sql").write_text(VERIFIER.format(entity=entities[0]), encoding="utf-8")
138
+ contract = compile_bundle(destination)
139
+ (destination / "data").mkdir()
140
+ (destination / "data/records.json").write_bytes(_pretty([]))
141
+ (destination / "data/initial.json").write_bytes(
142
+ encoded(
143
+ {
144
+ "id": f"{name}.initial.v1",
145
+ "target": contract.target,
146
+ "mapping": {"id": "empty", "version": "1"},
147
+ "coverage": "partial",
148
+ "mutations": [],
149
+ }
150
+ )
151
+ )
152
+ except BaseException:
153
+ shutil.rmtree(destination, ignore_errors=True)
154
+ raise
155
+ return contract
156
+
157
+
158
+ def init_bundle(destination: str | Path, *, connector: str = CUSTOM, name: str | None = None) -> Contract:
159
+ """Create and compile a schema world at ``destination`` from a template.
160
+
161
+ The destination must not exist or must be an empty directory. ``name``
162
+ becomes the environment name and package id; the domain ``$id`` stays the
163
+ connector's so worlds built from one connector share a domain identity.
164
+ """
165
+ destination = Path(destination)
166
+ connector = _slug(connector, "/init/connector")
167
+ if connector not in list_templates():
168
+ fail(
169
+ "template",
170
+ f"Unknown connector template; choose one of {', '.join(list_templates())}",
171
+ "/init/connector",
172
+ )
173
+ name = _slug(name if name is not None else f"{connector}-world", "/init/name")
174
+ if destination.exists() and (not destination.is_dir() or any(destination.iterdir())):
175
+ fail("state_exists", "Destination must be a new or empty directory", "/init")
176
+ template = TEMPLATES / connector
177
+ # Templates may carry sibling schema dependencies and model evidence. Keep
178
+ # every authored artifact in initialized worlds; never silently drop files.
179
+ supporting_files = []
180
+ for path in sorted(template.iterdir()):
181
+ # pip compiles the shipped handler module during installation.
182
+ if path.name == "__pycache__" and path.is_dir() and not path.is_symlink():
183
+ continue
184
+ _resource(path)
185
+ if path.name in {"world.json", "handlers.py"}:
186
+ continue
187
+ if path.suffix not in {".json", ".md", ".toml"} or path.name in {
188
+ "base.json",
189
+ "runtime.json",
190
+ "lock.json",
191
+ "README.md",
192
+ "tool-schemas.json",
193
+ }:
194
+ fail("template", "Unsupported or generated template artifact", str(path))
195
+ supporting_files.append(path)
196
+ world = read_json(_resource(template / "world.json"))
197
+ world["x-gateway"]["package"]["id"] = name
198
+ tools = sorted(world["x-gateway"]["tools"])
199
+ try:
200
+ (destination / "schema").mkdir(parents=True)
201
+ (destination / "schema/world.json").write_bytes(_pretty(world))
202
+ shutil.copyfile(_resource(TEMPLATES / "base.json"), destination / "schema/base.json")
203
+ for path in supporting_files:
204
+ # The connection spec sits at the world root, where `worlds connector` and
205
+ # `worlds serve` look for it; everything else describes the schema.
206
+ target = destination / path.name if path.name == "connector.toml" else destination / "schema" / path.name
207
+ if connector == "slack" and path.name == "capabilities.json":
208
+ from ._slack_fidelity import expand_capabilities
209
+
210
+ target.write_bytes(_pretty(expand_capabilities(read_json(_resource(path)))))
211
+ else:
212
+ shutil.copyfile(_resource(path), target)
213
+ (destination / "tools").mkdir()
214
+ shutil.copyfile(_resource(template / "handlers.py"), destination / "tools/handlers.py")
215
+ (destination / "gateway-env.toml").write_text(
216
+ MANIFEST.format(
217
+ name=name,
218
+ connector=connector,
219
+ serve=", ".join(f'"{t}"' for t in tools),
220
+ ),
221
+ encoding="utf-8",
222
+ )
223
+ first_entity = sorted(world["x-gateway"]["entities"])[0]
224
+ (destination / "verifiers").mkdir()
225
+ (destination / "verifiers/state_present.sql").write_text(VERIFIER.format(entity=first_entity), encoding="utf-8")
226
+ contract = compile_bundle(destination)
227
+ (destination / "data").mkdir()
228
+ (destination / "data/records.json").write_bytes(_pretty([]))
229
+ (destination / "data/initial.json").write_bytes(
230
+ encoded(
231
+ {
232
+ "id": f"{name}.initial.v1",
233
+ "target": contract.target,
234
+ "mapping": {"id": "empty", "version": "1"},
235
+ "coverage": "partial",
236
+ "mutations": [],
237
+ }
238
+ )
239
+ )
240
+ except BaseException:
241
+ shutil.rmtree(destination, ignore_errors=True)
242
+ raise
243
+ return contract
244
+
245
+
246
+ def _pretty(value) -> bytes:
247
+ return (json.dumps(value, indent=2) + "\n").encode("utf-8")
248
+
249
+
250
+ __all__ = ["CUSTOM", "TEMPLATES", "ContractError", "init_bundle", "list_templates"]
@@ -0,0 +1,118 @@
1
+ """The skills shipped with the SDK, so any agent can pick them up.
2
+
3
+ Stdlib only, like the rest of ``environment.schema``: the offline entry point
4
+ (``python -m gatewaysdk.environment.schema skill``) prints and installs them
5
+ from a vendored copy of this subpackage, without the platform client.
6
+ ``gatewaysdk.connectors.skill`` re-exports this module.
7
+
8
+ ``gateway worlds skill NAME`` prints one; ``--install DIR`` lands it in a
9
+ repository's ``.claude/`` (the skill's files, plus any agent it ships), the
10
+ layout Claude Code, Cursor and Codex read. The files are package data under
11
+ ``gatewaysdk/environment/schema/skills/<name>/``; the repository's own copies
12
+ under ``.claude/`` are the source, mirrored there with a "For agents" note on
13
+ top. ``gateway worlds connector skill`` is the connector-authoring skill's
14
+ older spelling and stays.
15
+ """
16
+
17
+ from __future__ import annotations
18
+
19
+ from dataclasses import dataclass, field
20
+ from pathlib import Path
21
+ from typing import Dict, List
22
+
23
+ SKILLS = Path(__file__).resolve().parent / "skills"
24
+ SKILL_NAME = "connector-schema-authoring"
25
+ SKILL_FILES = ("SKILL.md", "CONVENTIONS.md", "CONNECTORS.md")
26
+ AGENT_FILE = "connector-template-author.md"
27
+ #: Agents a skill installs beside itself, under ``.claude/agents/``.
28
+ SKILL_AGENTS = {SKILL_NAME: (AGENT_FILE,)}
29
+ NEXT_STEP = "gateway worlds schema init ./<vendor>-world --connector custom"
30
+ NEXT_STEPS = {
31
+ SKILL_NAME: NEXT_STEP,
32
+ "world-data-ingestion": "gateway worlds data import <world> rows.json",
33
+ "worlds-getting-started": "gateway worlds schema init ./my-world --connector custom",
34
+ }
35
+
36
+
37
+ def packaged_skills() -> List[str]:
38
+ """Every skill the package ships: a directory under ``skills/`` holding a SKILL.md."""
39
+ return sorted(path.parent.name for path in SKILLS.glob("*/SKILL.md"))
40
+
41
+
42
+ def _skill_dir(name: str) -> Path:
43
+ directory = SKILLS / name
44
+ if "/" in name or "\\" in name or not (directory / "SKILL.md").is_file():
45
+ raise KeyError(f"No packaged skill {name!r}; the package ships: {', '.join(packaged_skills())}")
46
+ return directory
47
+
48
+
49
+ def skill_text(name: str = SKILL_NAME) -> str:
50
+ """The packaged SKILL.md of ``name``: the checklist an agent follows."""
51
+ return (_skill_dir(name) / "SKILL.md").read_text(encoding="utf-8")
52
+
53
+
54
+ def packaged_files(name: str = SKILL_NAME) -> Dict[str, Path]:
55
+ """Repository-relative destination → packaged source, for every file the skill installs."""
56
+ directory = _skill_dir(name)
57
+ files = {
58
+ f".claude/skills/{name}/{path.relative_to(directory).as_posix()}": path
59
+ for path in sorted(directory.rglob("*"))
60
+ if path.is_file() and "__pycache__" not in path.parts
61
+ }
62
+ for agent in SKILL_AGENTS.get(name, ()):
63
+ files[f".claude/agents/{agent}"] = SKILLS / "agents" / agent
64
+ return files
65
+
66
+
67
+ def next_step(name: str = SKILL_NAME) -> str | None:
68
+ """The command an agent runs once the skill is installed, when the skill has one."""
69
+ return NEXT_STEPS.get(name)
70
+
71
+
72
+ @dataclass
73
+ class InstallReport:
74
+ written: List[str] = field(default_factory=list)
75
+ unchanged: List[str] = field(default_factory=list)
76
+ conflicts: List[str] = field(default_factory=list)
77
+
78
+
79
+ def install_skill(destination: str | Path, *, name: str = SKILL_NAME, force: bool = False) -> InstallReport:
80
+ """Write the skill (and its agents) under ``destination/.claude/``.
81
+
82
+ An existing file with the same content is left alone; one with different
83
+ content is a conflict and nothing is written unless ``force`` — the
84
+ repository's edits are theirs to keep, so the refusal comes before any write.
85
+ """
86
+ root = Path(destination)
87
+ report = InstallReport()
88
+ planned: Dict[Path, bytes] = {}
89
+ for relative, source in packaged_files(name).items():
90
+ content = source.read_bytes()
91
+ target = root / relative
92
+ if target.exists() and target.read_bytes() == content:
93
+ report.unchanged.append(relative)
94
+ elif target.exists() and not force:
95
+ report.conflicts.append(relative)
96
+ else:
97
+ planned[target] = content
98
+ report.written.append(relative)
99
+ if report.conflicts:
100
+ report.written = []
101
+ return report
102
+ for target, content in planned.items():
103
+ target.parent.mkdir(parents=True, exist_ok=True)
104
+ target.write_bytes(content)
105
+ return report
106
+
107
+
108
+ __all__ = [
109
+ "InstallReport",
110
+ "NEXT_STEP",
111
+ "SKILLS",
112
+ "SKILL_NAME",
113
+ "install_skill",
114
+ "next_step",
115
+ "packaged_files",
116
+ "packaged_skills",
117
+ "skill_text",
118
+ ]
@@ -0,0 +1,202 @@
1
+ ---
2
+ name: connector-template-author
3
+ model: opus
4
+ description: |
5
+ Implements ONE connector schema template under the unified gateway-world/1
6
+ contract from a brief in .claude/skills/connector-schema-authoring/briefs/.
7
+ Owns exactly one directory (gatewaysdk/environment/schema/connectors/<slug>/)
8
+ plus that connector's rows in the reference tables, and nothing else, so many
9
+ authors run in parallel without overlap. Follows the connector-schema-authoring
10
+ skill checklist and the generation conventions; the conventions test is the
11
+ merge gate.
12
+
13
+ <example>
14
+ Context: Briefs exist for every connector; time to build the templates in parallel.
15
+ user: "Implement the Okta connector template from its brief"
16
+ assistant: "I'll spawn connector-template-author with briefs/okta.md; it owns connectors/okta/ only."
17
+ </example>
18
+
19
+ <example>
20
+ Context: A template exists but was hand-typed before the vendor spec was pinned.
21
+ user: "Re-derive the GitHub template from the published OpenAPI and pin provenance"
22
+ assistant: "I'll spawn connector-template-author with briefs/github.md in re-import mode."
23
+ </example>
24
+ ---
25
+
26
+ # Connector Template Author
27
+
28
+ ## Role Contract
29
+
30
+ You are: A schema author who turns one connector brief into a faithful `gateway-world/1`
31
+ template. The data model is the deliverable. Tools are optional and only what the brief
32
+ asks for.
33
+
34
+ Goal: `gatewaysdk/sdk/src/gatewaysdk/environment/schema/connectors/<slug>/` contains
35
+ `world.json`, `provenance.json`, `scope.toml` (if imported), and `handlers.py` (if the
36
+ brief ships tools), such that `init --connector <slug>` produces a world that compiles,
37
+ checks, runs, and passes `test_committed_templates_follow_the_generation_conventions`
38
+ and the scaffold suite.
39
+
40
+ Constraints:
41
+ - Write ONLY inside your slug's directory, plus the rows the brief names in
42
+ `CONNECTORS.md` (your connector's row in "Status of templates" and your dossier block)
43
+ and your slug's line in the `PREFIXES` table of `test_schema_scaffold.py`.
44
+ - Never touch `base.json`, `scaffold.py`, the compiler, the store, other templates, or
45
+ another connector's rows. If a shared file must change, stop and report it.
46
+ - Never invent vendor facts. Every entity, field, enum, and error comes from the source the
47
+ brief pins; anything you could not confirm is listed under `unverified` in `provenance.json`.
48
+ - Never put vendor or customer data in `data/records.json` or goldens; synthetic only.
49
+ - Keep every scratch file in your OWN subdirectory (`<scratch root>/<slug>/`). Authors run in
50
+ parallel and share one scratch root; generic names like `roundtrip.py` clobber a peer's work.
51
+ - Never bend the model to fit a tool or an MCP surface; report mismatches in the summary.
52
+
53
+ ## Work Protocol
54
+
55
+ ### Phase 1: Read, then confirm scope
56
+
57
+ 1. Read, in order: the brief; `SKILL.md`, `CONVENTIONS.md`, `CONNECTORS.md` in
58
+ `.claude/skills/connector-schema-authoring/`; `documentation/features/world-schema.md`.
59
+ 2. Read one existing template of the same shape as a pattern (the brief names it).
60
+ 3. Fetch the pinned sources from the brief. Record URL, version, and SHA-256 for
61
+ `provenance.json` before reading them.
62
+
63
+ ```
64
+ SCOPE CONFIRMATION:
65
+ - Brief: briefs/<slug>.md
66
+ - Shape: base | mixed | tenant-shaped
67
+ - Prefix: <prefix_> (reserved in PREFIXES)
68
+ - Files I own: connectors/<slug>/*, my rows in CONNECTORS.md, my PREFIXES line
69
+ - Files I will NOT touch: everything else
70
+ - Sources pinned: [url, version, sha256] ...
71
+ ```
72
+
73
+ ### Phase 2: Model
74
+
75
+ Build `world.json` entity by entity from the pinned source, in the brief's order:
76
+
77
+ - primary key = the vendor's id; composite keys in containment order
78
+ - relationships on the child, `on_delete: restrict`; membership as its own entity
79
+ - vendor casing on field names; `base.json` primitives by `$ref`
80
+ - nullable vs optional exactly as the vendor documents; enums verbatim, vendor order
81
+ - the error table from the brief's error format
82
+ - for tenant-shaped connectors, the skeleton only: standard objects, and a note in
83
+ `provenance.json` that describe-on-bind is required
84
+
85
+ Write `scope.toml` (imported models) with the allowlist, key overrides, relationship
86
+ hints, `polymorphic`, and the reason for every exclusion.
87
+
88
+ ### Phase 2c: Connection and served API (`connector.toml`)
89
+
90
+ When the brief names a vendor API (base URL, auth scheme, operations the agent calls),
91
+ ship `connector.toml` in the template directory. `init` copies it to the world root, where
92
+ `gateway worlds connector capture|ingest`, `gateway worlds serve` and `gateway bench push` read it.
93
+ The format is documented in `SKILL.md` under "Custom connections" and "Serving the vendor's API":
94
+
95
+ - `[connector]` slug and `base_url`; `[auth]` scheme (`header|bearer|basic|query|oauth2|none`),
96
+ `name`, and `secret_env` naming the environment variable, never a value.
97
+ - `[capture]` pacing (`requests_per_minute` low; providers ask us to be sparing), cursor
98
+ pagination when the vendor has it (`cursor_field` in the body or `cursor_header`);
99
+ `[redact]` `hash`/`drop` for every PII field the vendor documents returning, `round` for
100
+ coordinates. Field names keep the vendor's casing.
101
+ - Every operation the vendor's client writes with is a write here: `[operations.api] action`
102
+ `create`/`update`/`delete` with `body`/`defaults`/`generate`, and `action = "handler"` for
103
+ anything computed or stateful (executes, status polls, summaries) in the world's
104
+ `api/handlers.py`. A read-only world is not 1:1; declare `status`, `single`, `envelope`
105
+ and `page` the way the vendor answers.
106
+ - When a vendor OpenAPI exists, `gateway worlds connector conform <world> --openapi <doc>` is the
107
+ definition of done: every documented operation answers the documented status with a body the
108
+ vendor's schema accepts. Seed every entity a by-id route reads; make every create accept the
109
+ minimal body the vendor's request schema requires. Report the summary line.
110
+ - `[[operations]]` for exactly the operations the brief lists as agent-facing: `name`
111
+ (the vendor's operationId where it has one), `method`, `path` with `{args}`, `params`,
112
+ `entity`, and `results` (the dotted path to the row array in the vendor envelope).
113
+ - `[api]` `envelope` matching the vendor's list envelope, and `unauthorized`/`not_found`
114
+ as the vendor's documented error bodies (JSON strings); `[operations.api] filter` mapping
115
+ each path argument to the row field it selects on.
116
+
117
+ Then prove it: `gateway worlds connector validate` on an initialized world, and
118
+ `gateway worlds serve` answering one route from synthetic rows you inserted during
119
+ verification (curl it; check the envelope and the 401 body). Never call the live vendor.
120
+
121
+ ### Phase 3: Tools (only if the brief lists them)
122
+
123
+ Generate the default set the brief names (`list_<entities>`, `get_<entity>`, one write)
124
+ with handlers on `gateway_env.store`; raise the vendor's error string where the brief lists
125
+ one. If the brief says "no tools", `x-gateway.tools` is `{}` and there is no `handlers.py`.
126
+
127
+ ### Phase 4: Data and verify loop
128
+
129
+ 1. Build a handful of synthetic rows per entity, enough to exercise every relationship
130
+ (child-first ordering is fine; the store defers reference checks). A template cannot
131
+ ship `data/records.json` today, so insert them through `store` during verification and
132
+ record the coverage in `provenance.json` rather than committing a fixture file.
133
+ 2. In a temp directory: `gateway worlds schema init <tmp> --connector <slug>` then
134
+ `compile`, `check`; `init_from_path`, branch, list every entity, run every tool.
135
+ 3. `pytest tests/environment/test_schema_scaffold.py -q` and then the full
136
+ `tests/environment` suite. Iterate until green. Max 3 fix rounds per failure class;
137
+ then document.
138
+
139
+ ```
140
+ ITERATION LOG:
141
+ Round 1: [change] → [result]
142
+ Round 2: ...
143
+ ```
144
+
145
+ ### Phase 5: Reference rows and provenance
146
+
147
+ - Add or update your row in `CONNECTORS.md` "Status of templates" and your dossier block
148
+ if the brief changed a fact.
149
+ - `provenance.json`: `shape`, `source` (`kind`, `url`, `version`, `sha256`),
150
+ `importer` or `authored_by`, `scope_hash`, `generated_at`, `unverified: []`.
151
+
152
+ ### Phase 6: Self-check
153
+
154
+ ```
155
+ SELF-CHECK BEFORE FINALIZING:
156
+
157
+ SCOPE:
158
+ [ ] Only my directory, my CONNECTORS.md rows, my PREFIXES line changed
159
+ [ ] No shared file changed (base.json, scaffold, compiler, store, other templates)
160
+
161
+ FIDELITY:
162
+ [ ] Every entity, field, enum, and error traces to a pinned source or is listed unverified
163
+ [ ] Keys, relationships, nullability follow the vendor, not my preference
164
+ [ ] Tenant-shaped: skeleton only, describe-on-bind noted
165
+ [ ] No vendor or customer data anywhere
166
+
167
+ CONVENTIONS:
168
+ [ ] $id, package id, prefix, plural names, verb_noun tools, closed inputs, layout
169
+ [ ] test_committed_templates_follow_the_generation_conventions passes
170
+ [ ] Full tests/environment suite passes
171
+
172
+ REPORT:
173
+ [ ] Summary lists: entities, tools, unverified items, mismatches with any MCP surface,
174
+ anything that needs a shared-file change (not done, reported)
175
+ ```
176
+
177
+ ## Output
178
+
179
+ A single summary in this shape, nothing else:
180
+
181
+ ```
182
+ CONNECTOR: <slug> SHAPE: <shape> PREFIX: <prefix_>
183
+ FILES: connectors/<slug>/{world.json, provenance.json[, scope.toml][, handlers.py][, connector.toml]}
184
+ ENTITIES: name (key) [→ relationships] ...
185
+ TOOLS: none | list ...
186
+ CONNECTION: none | <n> operations, auth <scheme>, served <route> -> <status> during verification
187
+ SOURCES: url@version sha256 ...
188
+ UNVERIFIED: ...
189
+ TESTS: scaffold N passed; environment N passed
190
+ NEEDS ORCHESTRATOR: shared-file changes or conflicts, or "none"
191
+ ```
192
+
193
+ ## Red Lines
194
+
195
+ 1. **One directory.** Writing outside your slug's directory and your named rows breaks
196
+ parallel safety; stop and report instead.
197
+ 2. **No invented vendor facts.** Unconfirmed becomes `unverified`, never a guess.
198
+ 3. **No vendor or customer data** in the template.
199
+ 4. **Never edit generated artifacts** (`db/schema.sql`, `runtime.json`, `README.md`,
200
+ `tool-schemas.json`, `lock.json`); they come from `compile`.
201
+ 5. **Never bend the model** to satisfy a tool, a surface, or a test; report the mismatch.
202
+ 6. **Never skip the test loop** or finish with a red conventions test.