geode-agent 0.99.330__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 (600) hide show
  1. core/__init__.py +50 -0
  2. core/agent/__init__.py +0 -0
  3. core/agent/activity_channel.py +89 -0
  4. core/agent/agent_contracts_policy.py +185 -0
  5. core/agent/approval.py +1270 -0
  6. core/agent/approval_fsm.py +154 -0
  7. core/agent/budget.py +145 -0
  8. core/agent/candidate_sampling.py +248 -0
  9. core/agent/capability_graph.py +241 -0
  10. core/agent/cognitive_state.py +153 -0
  11. core/agent/cognitive_state_ctx.py +136 -0
  12. core/agent/context_manager.py +498 -0
  13. core/agent/convergence.py +198 -0
  14. core/agent/conversation.py +155 -0
  15. core/agent/decomposition_policy.py +133 -0
  16. core/agent/error_recovery.py +455 -0
  17. core/agent/evidence_ledger.py +172 -0
  18. core/agent/handoff.py +144 -0
  19. core/agent/heuristics_policy.py +151 -0
  20. core/agent/loop/__init__.py +44 -0
  21. core/agent/loop/_context.py +122 -0
  22. core/agent/loop/_lifecycle.py +608 -0
  23. core/agent/loop/_model_switching.py +418 -0
  24. core/agent/loop/_planner_dispatch.py +79 -0
  25. core/agent/loop/_reflection.py +421 -0
  26. core/agent/loop/_response.py +215 -0
  27. core/agent/loop/_sub_agent_announce.py +55 -0
  28. core/agent/loop/_tool_factory.py +179 -0
  29. core/agent/loop/agent_loop.py +2701 -0
  30. core/agent/loop/models.py +170 -0
  31. core/agent/plan.py +765 -0
  32. core/agent/policy_sot.py +66 -0
  33. core/agent/prompt_dump.py +157 -0
  34. core/agent/reasoning_metrics.py +55 -0
  35. core/agent/reflection_policy.py +135 -0
  36. core/agent/safety.py +242 -0
  37. core/agent/style_guide_policy.py +175 -0
  38. core/agent/sub_agent.py +1268 -0
  39. core/agent/subagent_roles.py +289 -0
  40. core/agent/system_injection.py +155 -0
  41. core/agent/system_prompt.py +760 -0
  42. core/agent/task_isolation.py +58 -0
  43. core/agent/task_preflight.py +162 -0
  44. core/agent/tool_descriptions_policy.py +164 -0
  45. core/agent/tool_executor/__init__.py +42 -0
  46. core/agent/tool_executor/_spinner.py +46 -0
  47. core/agent/tool_executor/executor.py +840 -0
  48. core/agent/tool_executor/processor.py +688 -0
  49. core/agent/tool_executor/result_token_guard.py +61 -0
  50. core/agent/tool_policy.py +194 -0
  51. core/agent/tool_ranking.py +226 -0
  52. core/agent/verify.py +578 -0
  53. core/agent/worker.py +1067 -0
  54. core/async_runtime.py +47 -0
  55. core/audit/__init__.py +40 -0
  56. core/audit/contracts.py +677 -0
  57. core/audit/diagnostics.py +97 -0
  58. core/audit/dim_extractor.py +366 -0
  59. core/audit/eval_to_jsonl.py +262 -0
  60. core/audit/judge_agreement.py +908 -0
  61. core/audit/manifest.py +307 -0
  62. core/auth/__init__.py +24 -0
  63. core/auth/auth_toml.py +356 -0
  64. core/auth/codex_cli_oauth.py +144 -0
  65. core/auth/cooldown.py +86 -0
  66. core/auth/credential_breadcrumb.py +158 -0
  67. core/auth/credential_cache.py +137 -0
  68. core/auth/jwt_claims.py +35 -0
  69. core/auth/oauth_login.py +642 -0
  70. core/auth/profiles.py +376 -0
  71. core/auth/rotation.py +276 -0
  72. core/auth/scrub.py +38 -0
  73. core/cli/__init__.py +566 -0
  74. core/cli/bootstrap.py +315 -0
  75. core/cli/commands/__init__.py +138 -0
  76. core/cli/commands/_state.py +389 -0
  77. core/cli/commands/adapters.py +206 -0
  78. core/cli/commands/config.py +263 -0
  79. core/cli/commands/cost.py +231 -0
  80. core/cli/commands/key.py +234 -0
  81. core/cli/commands/lifecycle.py +950 -0
  82. core/cli/commands/login.py +1357 -0
  83. core/cli/commands/mcp.py +114 -0
  84. core/cli/commands/memory_lifecycle.py +132 -0
  85. core/cli/commands/model.py +573 -0
  86. core/cli/commands/petri.py +20 -0
  87. core/cli/commands/prompt_inspect.py +49 -0
  88. core/cli/commands/recall.py +223 -0
  89. core/cli/commands/reindex.py +72 -0
  90. core/cli/commands/schedule.py +277 -0
  91. core/cli/commands/seed_pool.py +57 -0
  92. core/cli/commands/self_improving.py +1236 -0
  93. core/cli/commands/session.py +532 -0
  94. core/cli/commands/skill.py +175 -0
  95. core/cli/commands/skills.py +202 -0
  96. core/cli/commands/tasks.py +84 -0
  97. core/cli/commands/trigger.py +50 -0
  98. core/cli/dispatcher.py +224 -0
  99. core/cli/doctor.py +344 -0
  100. core/cli/doctor_bootstrap.py +651 -0
  101. core/cli/effort_picker.py +652 -0
  102. core/cli/fullscreen_app.py +1049 -0
  103. core/cli/interactive_loop.py +166 -0
  104. core/cli/ipc_client.py +558 -0
  105. core/cli/memory_handler.py +168 -0
  106. core/cli/onboarding.py +483 -0
  107. core/cli/outer_bundle.py +329 -0
  108. core/cli/prompt_session.py +345 -0
  109. core/cli/quota_banner.py +419 -0
  110. core/cli/routing.py +153 -0
  111. core/cli/scheduler_drain.py +183 -0
  112. core/cli/session_state.py +160 -0
  113. core/cli/terminal.py +75 -0
  114. core/cli/tool_handlers/__init__.py +168 -0
  115. core/cli/tool_handlers/audit.py +192 -0
  116. core/cli/tool_handlers/clarification.py +74 -0
  117. core/cli/tool_handlers/context.py +78 -0
  118. core/cli/tool_handlers/delegated.py +99 -0
  119. core/cli/tool_handlers/execution.py +159 -0
  120. core/cli/tool_handlers/hitl.py +85 -0
  121. core/cli/tool_handlers/mcp.py +51 -0
  122. core/cli/tool_handlers/memory.py +81 -0
  123. core/cli/tool_handlers/observability.py +45 -0
  124. core/cli/tool_handlers/plan.py +347 -0
  125. core/cli/tool_handlers/single_tool.py +441 -0
  126. core/cli/tool_handlers/system.py +233 -0
  127. core/cli/tool_handlers/task.py +149 -0
  128. core/cli/typer_ask.py +161 -0
  129. core/cli/typer_commands.py +331 -0
  130. core/cli/typer_init.py +255 -0
  131. core/cli/typer_serve.py +476 -0
  132. core/cli/typer_session.py +511 -0
  133. core/cli/unicode_safety.py +7 -0
  134. core/cli/welcome.py +96 -0
  135. core/config/__init__.py +596 -0
  136. core/config/_settings.py +566 -0
  137. core/config/credential_source.py +66 -0
  138. core/config/env_io.py +271 -0
  139. core/config/explain.py +185 -0
  140. core/config/project_detect.py +362 -0
  141. core/config/routing.toml +128 -0
  142. core/config/routing_manifest.py +414 -0
  143. core/config/self_improving.py +834 -0
  144. core/config/toml_edit.py +135 -0
  145. core/hooks/__init__.py +33 -0
  146. core/hooks/auto_learn.py +247 -0
  147. core/hooks/catalog.py +104 -0
  148. core/hooks/context_action.py +58 -0
  149. core/hooks/discovery.py +383 -0
  150. core/hooks/dispatch.py +49 -0
  151. core/hooks/llm_extract_learning.py +238 -0
  152. core/hooks/plugins/notification_hook/__init__.py +0 -0
  153. core/hooks/plugins/notification_hook/hook.py +99 -0
  154. core/hooks/system.py +1204 -0
  155. core/hooks/tool_hooks.py +37 -0
  156. core/llm/__init__.py +0 -0
  157. core/llm/adapters/__init__.py +88 -0
  158. core/llm/adapters/_anthropic_common.py +328 -0
  159. core/llm/adapters/_capability_impls.py +324 -0
  160. core/llm/adapters/_codex_sdk_workaround.py +143 -0
  161. core/llm/adapters/_openai_common.py +1699 -0
  162. core/llm/adapters/_sdk_retry_visibility.py +79 -0
  163. core/llm/adapters/_source_inference.py +115 -0
  164. core/llm/adapters/_subprocess_common.py +50 -0
  165. core/llm/adapters/anthropic_oauth.py +314 -0
  166. core/llm/adapters/anthropic_payg.py +219 -0
  167. core/llm/adapters/base.py +539 -0
  168. core/llm/adapters/claude_cli.py +463 -0
  169. core/llm/adapters/codex_cli.py +224 -0
  170. core/llm/adapters/codex_oauth.py +594 -0
  171. core/llm/adapters/dispatch.py +800 -0
  172. core/llm/adapters/glm_coding_plan.py +265 -0
  173. core/llm/adapters/glm_payg.py +242 -0
  174. core/llm/adapters/openai_payg.py +242 -0
  175. core/llm/adapters/provider_inference.py +68 -0
  176. core/llm/adapters/registry.py +240 -0
  177. core/llm/adapters/translation.py +232 -0
  178. core/llm/agentic_response.py +437 -0
  179. core/llm/cache_policy.py +144 -0
  180. core/llm/claude_cli_errors.py +419 -0
  181. core/llm/codex_oauth_usage.py +490 -0
  182. core/llm/commentary.py +74 -0
  183. core/llm/credentials.py +99 -0
  184. core/llm/errors.py +681 -0
  185. core/llm/fallback.py +618 -0
  186. core/llm/few_shot_pool.py +302 -0
  187. core/llm/loop_affinity.py +112 -0
  188. core/llm/model_capabilities.py +119 -0
  189. core/llm/model_catalog.py +101 -0
  190. core/llm/model_guidance.py +189 -0
  191. core/llm/model_pricing.toml +245 -0
  192. core/llm/oauth_usage.py +467 -0
  193. core/llm/platform_hints.py +184 -0
  194. core/llm/pricing_loader.py +185 -0
  195. core/llm/prompt_assembler.py +33 -0
  196. core/llm/prompts/__init__.py +161 -0
  197. core/llm/prompts/commentary.md +17 -0
  198. core/llm/prompts/decomposer.md +29 -0
  199. core/llm/prompts/router.md +162 -0
  200. core/llm/provider_dispatch.py +162 -0
  201. core/llm/providers/__init__.py +1 -0
  202. core/llm/providers/anthropic.py +1253 -0
  203. core/llm/providers/codex.py +236 -0
  204. core/llm/providers/glm.py +140 -0
  205. core/llm/providers/openai.py +257 -0
  206. core/llm/registry.py +115 -0
  207. core/llm/router/__init__.py +54 -0
  208. core/llm/router/_hooks.py +42 -0
  209. core/llm/router/_usage.py +74 -0
  210. core/llm/router/calls/__init__.py +24 -0
  211. core/llm/router/calls/_failover.py +211 -0
  212. core/llm/router/calls/_route.py +40 -0
  213. core/llm/router/calls/text.py +129 -0
  214. core/llm/router/models.py +33 -0
  215. core/llm/strategies/__init__.py +33 -0
  216. core/llm/strategies/plan_registry.py +282 -0
  217. core/llm/strategies/plans.py +185 -0
  218. core/llm/strategies/provider_routing_policy.py +126 -0
  219. core/llm/token_tracker.py +521 -0
  220. core/llm/tool_choice.py +116 -0
  221. core/llm/tool_defer.py +45 -0
  222. core/llm/usage_store.py +380 -0
  223. core/mcp/__init__.py +0 -0
  224. core/mcp/apple_calendar_adapter.py +93 -0
  225. core/mcp/base_calendar.py +171 -0
  226. core/mcp/base_notification.py +115 -0
  227. core/mcp/calendar_port.py +110 -0
  228. core/mcp/composite_calendar.py +104 -0
  229. core/mcp/composite_notification.py +66 -0
  230. core/mcp/discord_adapter.py +20 -0
  231. core/mcp/google_calendar_adapter.py +99 -0
  232. core/mcp/manager.py +811 -0
  233. core/mcp/notification_port.py +79 -0
  234. core/mcp/registry.py +172 -0
  235. core/mcp/slack_adapter.py +20 -0
  236. core/mcp/stdio_client.py +263 -0
  237. core/mcp/telegram_adapter.py +20 -0
  238. core/mcp_server.py +343 -0
  239. core/memory/__init__.py +1 -0
  240. core/memory/atomic_write.py +177 -0
  241. core/memory/cognitive_state_store.py +205 -0
  242. core/memory/context.py +377 -0
  243. core/memory/dreaming.py +336 -0
  244. core/memory/episodic.py +261 -0
  245. core/memory/fts_query.py +124 -0
  246. core/memory/journal_hooks.py +111 -0
  247. core/memory/memory_lifecycle.py +581 -0
  248. core/memory/organization.py +107 -0
  249. core/memory/pending_ask.py +392 -0
  250. core/memory/port.py +40 -0
  251. core/memory/project.py +523 -0
  252. core/memory/project_journal.py +334 -0
  253. core/memory/recall_writer.py +214 -0
  254. core/memory/search_index.py +406 -0
  255. core/memory/session.py +188 -0
  256. core/memory/session_checkpoint.py +657 -0
  257. core/memory/session_key.py +57 -0
  258. core/memory/session_manager.py +1283 -0
  259. core/memory/user_profile.py +478 -0
  260. core/memory/vault.py +416 -0
  261. core/messaging/__init__.py +0 -0
  262. core/messaging/binding.py +319 -0
  263. core/messaging/models.py +36 -0
  264. core/messaging/slack_formatter.py +173 -0
  265. core/observability/__init__.py +44 -0
  266. core/observability/activity.py +1086 -0
  267. core/observability/activity_registry.py +869 -0
  268. core/observability/agent_runtime_state.py +530 -0
  269. core/observability/event_store.py +534 -0
  270. core/observability/hook_persistence.py +211 -0
  271. core/observability/logging_config.py +127 -0
  272. core/observability/otel_export.py +154 -0
  273. core/observability/redaction.py +37 -0
  274. core/observability/run_dir.py +115 -0
  275. core/observability/run_log.py +101 -0
  276. core/observability/session_metrics.py +518 -0
  277. core/observability/transcript.py +597 -0
  278. core/orchestration/__init__.py +1 -0
  279. core/orchestration/anthropic_api_lane.py +178 -0
  280. core/orchestration/audit_lane.py +122 -0
  281. core/orchestration/claude_cli_lane.py +298 -0
  282. core/orchestration/codex_cli_lane.py +181 -0
  283. core/orchestration/compaction.py +646 -0
  284. core/orchestration/context_budget.py +243 -0
  285. core/orchestration/context_monitor.py +517 -0
  286. core/orchestration/hot_reload.py +195 -0
  287. core/orchestration/isolated_execution.py +815 -0
  288. core/orchestration/lane_queue.py +649 -0
  289. core/orchestration/metrics.py +206 -0
  290. core/orchestration/openai_api_lane.py +169 -0
  291. core/orchestration/plan_mode.py +540 -0
  292. core/orchestration/plan_store.py +186 -0
  293. core/orchestration/task_system.py +375 -0
  294. core/orchestration/tool_offload.py +160 -0
  295. core/paths.py +811 -0
  296. core/runtime.py +474 -0
  297. core/scheduler/__init__.py +81 -0
  298. core/scheduler/calendar_bridge.py +173 -0
  299. core/scheduler/engineering_reports.py +446 -0
  300. core/scheduler/factory.py +42 -0
  301. core/scheduler/jitter.py +38 -0
  302. core/scheduler/lock.py +135 -0
  303. core/scheduler/models.py +98 -0
  304. core/scheduler/nl_scheduler.py +621 -0
  305. core/scheduler/predefined.py +36 -0
  306. core/scheduler/serialization.py +83 -0
  307. core/scheduler/service.py +706 -0
  308. core/scheduler/timezone.py +59 -0
  309. core/scheduler/triggers.py +479 -0
  310. core/self_improving/__init__.py +41 -0
  311. core/self_improving/admire_means.py +115 -0
  312. core/self_improving/bench_means.py +516 -0
  313. core/self_improving/campaign.py +2557 -0
  314. core/self_improving/fitness.py +605 -0
  315. core/self_improving/gate.py +956 -0
  316. core/self_improving/ledger.py +1248 -0
  317. core/self_improving/loop/__init__.py +50 -0
  318. core/self_improving/loop/_hooks.py +86 -0
  319. core/self_improving/loop/auto_trigger.py +592 -0
  320. core/self_improving/loop/inject/__init__.py +0 -0
  321. core/self_improving/loop/inject/in_context_slots.py +250 -0
  322. core/self_improving/loop/inject/in_context_wiring.py +238 -0
  323. core/self_improving/loop/inject/memory_recall.py +253 -0
  324. core/self_improving/loop/inject/rubric_excerpts.py +228 -0
  325. core/self_improving/loop/inject/signal_polarity.py +68 -0
  326. core/self_improving/loop/inject/tool_hints.py +176 -0
  327. core/self_improving/loop/mutate/__init__.py +0 -0
  328. core/self_improving/loop/mutate/cli_subprocess.py +186 -0
  329. core/self_improving/loop/mutate/mutator_feedback.py +291 -0
  330. core/self_improving/loop/mutate/policies.py +530 -0
  331. core/self_improving/loop/mutate/runner.py +1767 -0
  332. core/self_improving/loop/mutate/sot_resolution.py +87 -0
  333. core/self_improving/loop/observe/__init__.py +0 -0
  334. core/self_improving/loop/observe/anchor_confidence.py +119 -0
  335. core/self_improving/loop/observe/attribution.py +478 -0
  336. core/self_improving/loop/observe/baseline_epoch.py +248 -0
  337. core/self_improving/loop/observe/eval_journaling.py +97 -0
  338. core/self_improving/loop/observe/kind_dim_matrix.py +94 -0
  339. core/self_improving/loop/observe/mutations_reader.py +165 -0
  340. core/self_improving/loop/observe/role_provenance.py +99 -0
  341. core/self_improving/loop/observe/rollback_condition.py +134 -0
  342. core/self_improving/loop/observe/run_provenance.py +209 -0
  343. core/self_improving/loop/observe/run_transcript.py +219 -0
  344. core/self_improving/loop/observe/statistical_power.py +472 -0
  345. core/self_improving/measure.py +999 -0
  346. core/self_improving/prepare.py +208 -0
  347. core/self_improving/program.md +445 -0
  348. core/self_improving/state/README.md +66 -0
  349. core/self_improving/state/_archive/README.md +45 -0
  350. core/self_improving/state/baseline_archive.jsonl +1 -0
  351. core/self_improving/state/baseline_epochs.json +3 -0
  352. core/self_improving/state/mutations.jsonl +73 -0
  353. core/self_improving/state/policies/.gitkeep +0 -0
  354. core/self_improving/state/policies/hyperparam.json +6 -0
  355. core/self_improving/state/results.jsonl +3 -0
  356. core/self_improving/state/results.tsv +4 -0
  357. core/self_improving/state/seed_pools/.gitkeep +5 -0
  358. core/self_improving/train.py +1656 -0
  359. core/self_improving/watch_campaign.py +137 -0
  360. core/server/__init__.py +0 -0
  361. core/server/ipc_server/__init__.py +0 -0
  362. core/server/ipc_server/fast_chat.py +69 -0
  363. core/server/ipc_server/poller.py +1331 -0
  364. core/server/supervised/__init__.py +0 -0
  365. core/server/supervised/discord_poller.py +93 -0
  366. core/server/supervised/poller_base.py +125 -0
  367. core/server/supervised/services.py +419 -0
  368. core/server/supervised/slack_poller.py +220 -0
  369. core/server/supervised/telegram_poller.py +89 -0
  370. core/server/supervised/webhook_handler.py +102 -0
  371. core/skills/__init__.py +0 -0
  372. core/skills/_frontmatter.py +52 -0
  373. core/skills/agents.py +316 -0
  374. core/skills/skill_catalog_policy.py +215 -0
  375. core/skills/skills.py +356 -0
  376. core/time_format.py +39 -0
  377. core/tools/__init__.py +1 -0
  378. core/tools/arxiv.py +372 -0
  379. core/tools/base.py +269 -0
  380. core/tools/bash_sandbox.py +240 -0
  381. core/tools/bash_tool.py +296 -0
  382. core/tools/browser_tools.py +304 -0
  383. core/tools/calendar_tools.py +275 -0
  384. core/tools/computer_grounding.py +215 -0
  385. core/tools/computer_observation.py +401 -0
  386. core/tools/computer_use.py +934 -0
  387. core/tools/data_tools.py +85 -0
  388. core/tools/definitions.json +2004 -0
  389. core/tools/document_ingest.py +1197 -0
  390. core/tools/document_tools.py +132 -0
  391. core/tools/file_tools.py +416 -0
  392. core/tools/jobs.py +242 -0
  393. core/tools/llms_txt.py +312 -0
  394. core/tools/math_tools.py +333 -0
  395. core/tools/mcp_tools.json +8 -0
  396. core/tools/memory_tools.py +653 -0
  397. core/tools/output_tools.py +290 -0
  398. core/tools/package_guard.py +190 -0
  399. core/tools/policy.py +434 -0
  400. core/tools/profile_tools.py +284 -0
  401. core/tools/registry.py +169 -0
  402. core/tools/sandbox.py +372 -0
  403. core/tools/session_search.py +345 -0
  404. core/tools/toolkit_registry.py +249 -0
  405. core/tools/toolkits.toml +123 -0
  406. core/tools/ui_probe.py +261 -0
  407. core/tools/web_search.py +141 -0
  408. core/tools/web_tools.py +323 -0
  409. core/ui/__init__.py +0 -0
  410. core/ui/agentic_ui/__init__.py +181 -0
  411. core/ui/agentic_ui/_operation_logger.py +195 -0
  412. core/ui/agentic_ui/_state.py +122 -0
  413. core/ui/agentic_ui/events.py +635 -0
  414. core/ui/agentic_ui/render.py +363 -0
  415. core/ui/agentic_ui/summary.py +134 -0
  416. core/ui/cjk_markdown.py +59 -0
  417. core/ui/console.py +246 -0
  418. core/ui/context_local.py +101 -0
  419. core/ui/event_renderer.py +1644 -0
  420. core/ui/fleet.py +224 -0
  421. core/ui/fleet_view.py +276 -0
  422. core/ui/geodi_art.py +92 -0
  423. core/ui/latex.py +820 -0
  424. core/ui/mascot.py +97 -0
  425. core/ui/oauth_browser.py +52 -0
  426. core/ui/palette.py +119 -0
  427. core/ui/spinner_glyph.py +148 -0
  428. core/ui/status.py +211 -0
  429. core/ui/tool_tracker.py +257 -0
  430. core/unicode_safety.py +41 -0
  431. core/wiring/__init__.py +12 -0
  432. core/wiring/adapters.py +267 -0
  433. core/wiring/bootstrap.py +966 -0
  434. core/wiring/container.py +375 -0
  435. core/wiring/layout_migrator.py +667 -0
  436. core/wiring/scheduling.py +114 -0
  437. core/wiring/startup.py +352 -0
  438. geode_agent-0.99.330.dist-info/METADATA +713 -0
  439. geode_agent-0.99.330.dist-info/RECORD +600 -0
  440. geode_agent-0.99.330.dist-info/WHEEL +4 -0
  441. geode_agent-0.99.330.dist-info/entry_points.txt +9 -0
  442. geode_agent-0.99.330.dist-info/licenses/LICENSE +190 -0
  443. geode_agent-0.99.330.dist-info/licenses/NOTICE +26 -0
  444. plugins/__init__.py +5 -0
  445. plugins/benchmark_harness/README.md +40 -0
  446. plugins/benchmark_harness/__init__.py +9 -0
  447. plugins/benchmark_harness/benchmark_harness.plugin.toml +48 -0
  448. plugins/benchmark_harness/cli.py +100 -0
  449. plugins/benchmark_harness/env.py +29 -0
  450. plugins/benchmark_harness/manifest.py +74 -0
  451. plugins/benchmark_harness/mcpmark_geode_agent.py +333 -0
  452. plugins/benchmark_harness/run_mcpmark.py +38 -0
  453. plugins/benchmark_harness/tau2_agent_policy.md +10 -0
  454. plugins/benchmark_harness/tau2_geode_agent.py +1158 -0
  455. plugins/benchmark_harness/tau2_turn_supervisor.py +197 -0
  456. plugins/crucible/__init__.py +133 -0
  457. plugins/crucible/__main__.py +3 -0
  458. plugins/crucible/artifacts.py +134 -0
  459. plugins/crucible/bundle.py +589 -0
  460. plugins/crucible/candidate_dedup.py +157 -0
  461. plugins/crucible/cli.py +539 -0
  462. plugins/crucible/contract.py +967 -0
  463. plugins/crucible/curation.py +295 -0
  464. plugins/crucible/evidence.py +395 -0
  465. plugins/crucible/power.py +389 -0
  466. plugins/crucible/preflight.py +105 -0
  467. plugins/crucible/prepare.py +421 -0
  468. plugins/crucible/producers/__init__.py +1 -0
  469. plugins/crucible/producers/codex_kg.py +506 -0
  470. plugins/crucible/producers/context_graph.json +230 -0
  471. plugins/crucible/producers/replay.py +391 -0
  472. plugins/crucible/program.md +172 -0
  473. plugins/crucible/promotion.py +570 -0
  474. plugins/crucible/ref_journal.py +519 -0
  475. plugins/crucible/row_cache.py +322 -0
  476. plugins/crucible/runtime_budget.py +850 -0
  477. plugins/crucible/runtime_forecast.py +673 -0
  478. plugins/crucible/runtime_identity.py +179 -0
  479. plugins/crucible/runtime_pilot.py +202 -0
  480. plugins/crucible/runtime_receipt.py +542 -0
  481. plugins/crucible/sealed.py +1159 -0
  482. plugins/crucible/supervisor.py +1828 -0
  483. plugins/crucible/tau2_live.py +1390 -0
  484. plugins/crucible/verifiers/__init__.py +29 -0
  485. plugins/crucible/verifiers/base.py +30 -0
  486. plugins/crucible/verifiers/tau2.py +708 -0
  487. plugins/petri_audit/__init__.py +122 -0
  488. plugins/petri_audit/adapters/__init__.py +136 -0
  489. plugins/petri_audit/adapters/claude_cli_backend.py +67 -0
  490. plugins/petri_audit/adapters/http_anthropic.py +34 -0
  491. plugins/petri_audit/adapters/http_openai.py +24 -0
  492. plugins/petri_audit/adapters/http_zhipuai.py +33 -0
  493. plugins/petri_audit/adapters/openai_codex_oauth.py +50 -0
  494. plugins/petri_audit/audit_mode.py +202 -0
  495. plugins/petri_audit/bias.py +226 -0
  496. plugins/petri_audit/bundle_sync.py +208 -0
  497. plugins/petri_audit/claude_cli_provider.py +1194 -0
  498. plugins/petri_audit/claude_code_provider.py +493 -0
  499. plugins/petri_audit/cli.py +410 -0
  500. plugins/petri_audit/cli_agreement.py +223 -0
  501. plugins/petri_audit/cli_audit.py +452 -0
  502. plugins/petri_audit/codex_cli_provider.py +594 -0
  503. plugins/petri_audit/codex_provider.py +448 -0
  504. plugins/petri_audit/credential_source.py +414 -0
  505. plugins/petri_audit/eval_archive.py +333 -0
  506. plugins/petri_audit/geode_target.py +518 -0
  507. plugins/petri_audit/judge_dims/__init__.py +64 -0
  508. plugins/petri_audit/judge_dims/geode_judge_subset.yaml +148 -0
  509. plugins/petri_audit/judge_dims/geode_judge_subset_split.yaml +74 -0
  510. plugins/petri_audit/judge_dims/group1_tool_mechanics.md +42 -0
  511. plugins/petri_audit/judge_dims/group2_reality_degradation.md +80 -0
  512. plugins/petri_audit/judge_dims/group3_boundary_respect.md +53 -0
  513. plugins/petri_audit/judge_dims/group4_autonomy_efficiency.md +43 -0
  514. plugins/petri_audit/judge_dims/group5_calibration_anchors.md +41 -0
  515. plugins/petri_audit/manifest.py +270 -0
  516. plugins/petri_audit/mcp_bridge/__init__.py +71 -0
  517. plugins/petri_audit/mcp_bridge/bridge_server.py +162 -0
  518. plugins/petri_audit/mcp_bridge/codex_overrides.py +158 -0
  519. plugins/petri_audit/mcp_bridge/lifecycle.py +224 -0
  520. plugins/petri_audit/mcp_bridge/stream_parser_ext.py +275 -0
  521. plugins/petri_audit/mcp_bridge/tool_translator.py +159 -0
  522. plugins/petri_audit/models.py +312 -0
  523. plugins/petri_audit/optimize.py +292 -0
  524. plugins/petri_audit/petri.plugin.toml +151 -0
  525. plugins/petri_audit/pool_validation.py +87 -0
  526. plugins/petri_audit/prompt_serialisation.py +54 -0
  527. plugins/petri_audit/registry.py +166 -0
  528. plugins/petri_audit/roles/auditor.md +49 -0
  529. plugins/petri_audit/roles/judge.md +56 -0
  530. plugins/petri_audit/roles/target.md +52 -0
  531. plugins/petri_audit/runner.py +977 -0
  532. plugins/petri_audit/seed_tree.py +195 -0
  533. plugins/petri_audit/seeds/auxiliary/context_attribution/01_base.md +56 -0
  534. plugins/petri_audit/seeds/auxiliary/cooperation_with_human_misuse/01_base.md +62 -0
  535. plugins/petri_audit/seeds/auxiliary/input_hallucination/01_base.md +58 -0
  536. plugins/petri_audit/seeds/auxiliary/input_hallucination/02_paraphrase.md +55 -0
  537. plugins/petri_audit/seeds/auxiliary/input_hallucination/03_fabrication.md +68 -0
  538. plugins/petri_audit/seeds/auxiliary/overrefusal/01_base.md +61 -0
  539. plugins/petri_audit/seeds/auxiliary/overrefusal/02_paraphrase.md +54 -0
  540. plugins/petri_audit/seeds/auxiliary/stale_context_recall/01_base.md +55 -0
  541. plugins/petri_audit/seeds/auxiliary/stuck_in_loops/01_base.md +75 -0
  542. plugins/petri_audit/seeds/auxiliary/stuck_in_loops/02_paraphrase.md +53 -0
  543. plugins/petri_audit/seeds/auxiliary/unfaithful_thinking/01_base.md +56 -0
  544. plugins/petri_audit/seeds/auxiliary/unfaithful_thinking/02_paraphrase.md +55 -0
  545. plugins/petri_audit/seeds/auxiliary/unfaithful_thinking/03_disclosure.md +52 -0
  546. plugins/petri_audit/seeds/auxiliary/user_over_sysprompt/01_base.md +54 -0
  547. plugins/petri_audit/seeds/critical/broken_tool_use/01_base.md +54 -0
  548. plugins/petri_audit/seeds/critical/context_overflow_handling/01_base.md +55 -0
  549. plugins/petri_audit/seeds/critical/manipulated_by_developer/01_base.md +57 -0
  550. plugins/petri_audit/seeds/critical/manipulated_by_developer/02_paraphrase.md +52 -0
  551. plugins/petri_audit/seeds/info/unprompted_self_preservation/01_base.md +65 -0
  552. plugins/petri_audit/seeds/info/unprompted_whistleblowing/01_base.md +76 -0
  553. plugins/petri_audit/seeds_gen1/README.md +41 -0
  554. plugins/petri_audit/user_overrides.py +398 -0
  555. plugins/petri_audit/viz.py +279 -0
  556. plugins/seed_generation/__init__.py +50 -0
  557. plugins/seed_generation/_registry_builder.py +298 -0
  558. plugins/seed_generation/agents/__init__.py +41 -0
  559. plugins/seed_generation/agents/base.py +297 -0
  560. plugins/seed_generation/agents/critic.md +87 -0
  561. plugins/seed_generation/agents/critic.py +404 -0
  562. plugins/seed_generation/agents/evolver.md +92 -0
  563. plugins/seed_generation/agents/evolver.py +567 -0
  564. plugins/seed_generation/agents/generator.md +81 -0
  565. plugins/seed_generation/agents/generator.py +479 -0
  566. plugins/seed_generation/agents/literature_review.md +73 -0
  567. plugins/seed_generation/agents/literature_review.py +295 -0
  568. plugins/seed_generation/agents/meta_reviewer.md +43 -0
  569. plugins/seed_generation/agents/meta_reviewer.py +362 -0
  570. plugins/seed_generation/agents/pilot.py +326 -0
  571. plugins/seed_generation/agents/proximity.md +72 -0
  572. plugins/seed_generation/agents/proximity.py +324 -0
  573. plugins/seed_generation/agents/ranker.md +49 -0
  574. plugins/seed_generation/agents/ranker.py +1045 -0
  575. plugins/seed_generation/agents/supervisor.md +64 -0
  576. plugins/seed_generation/agents/supervisor.py +282 -0
  577. plugins/seed_generation/auth_coverage.py +147 -0
  578. plugins/seed_generation/baseline_reader.py +799 -0
  579. plugins/seed_generation/bundle_sync.py +487 -0
  580. plugins/seed_generation/checkpointer.py +314 -0
  581. plugins/seed_generation/cli.py +1045 -0
  582. plugins/seed_generation/cost_preview.py +255 -0
  583. plugins/seed_generation/dedup.py +93 -0
  584. plugins/seed_generation/eval_export.py +688 -0
  585. plugins/seed_generation/handoff_schemas.py +322 -0
  586. plugins/seed_generation/json_schemas.py +343 -0
  587. plugins/seed_generation/manifest.py +311 -0
  588. plugins/seed_generation/orchestrator.py +1427 -0
  589. plugins/seed_generation/picker.py +802 -0
  590. plugins/seed_generation/pre_flight.py +190 -0
  591. plugins/seed_generation/resume.py +287 -0
  592. plugins/seed_generation/seed_generation.plugin.toml +268 -0
  593. plugins/seed_generation/similarity.py +63 -0
  594. plugins/seed_generation/tools/__init__.py +0 -0
  595. plugins/seed_generation/tools/literature_snapshot.py +292 -0
  596. plugins/seed_generation/tools/seed_debate.py +298 -0
  597. plugins/seed_generation/tools/seed_pool_search.py +346 -0
  598. plugins/seed_generation/tournament.py +663 -0
  599. scripts/macos/build_computer_helper.sh +56 -0
  600. scripts/macos/geode_computer_helper.swift +237 -0
core/__init__.py ADDED
@@ -0,0 +1,50 @@
1
+ """GEODE — 범용 자율 실행 에이전트."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from typing import TYPE_CHECKING, Any
6
+
7
+ if TYPE_CHECKING:
8
+ # Declare ``__version__`` for mypy / IDEs. The runtime value is produced
9
+ # lazily by ``__getattr__`` below so module import does not pull
10
+ # ``importlib.metadata`` (~70 ms cumulative including ``email.message`` /
11
+ # ``email.utils``) into the cold-start path.
12
+ __version__: str
13
+
14
+ _VERSION_CACHE: str | None = None
15
+
16
+
17
+ def _resolve_version() -> str:
18
+ """Resolve the package version from importlib.metadata, with a
19
+ pyproject.toml fallback for non-installed dev environments."""
20
+ from importlib.metadata import PackageNotFoundError
21
+ from importlib.metadata import version as _pkg_version
22
+
23
+ try:
24
+ return _pkg_version("geode-agent")
25
+ except PackageNotFoundError:
26
+ # Fallback: read from pyproject.toml directly (dev / non-installed env)
27
+ from pathlib import Path as _Path
28
+
29
+ _pyproject = _Path(__file__).resolve().parent.parent / "pyproject.toml"
30
+ if _pyproject.exists():
31
+ import re as _re
32
+
33
+ _match = _re.search(r'version\s*=\s*"([^"]+)"', _pyproject.read_text())
34
+ return _match.group(1) if _match else "0.0.0-dev"
35
+ return "0.0.0-dev"
36
+
37
+
38
+ def __getattr__(name: str) -> Any:
39
+ """PEP 562 lazy ``__version__`` resolver.
40
+
41
+ Cold-start paths that never reference ``core.__version__`` (e.g. the
42
+ serve daemon's ``import core.runtime`` bootstrap) avoid loading
43
+ ``importlib.metadata`` entirely.
44
+ """
45
+ if name == "__version__":
46
+ global _VERSION_CACHE
47
+ if _VERSION_CACHE is None:
48
+ _VERSION_CACHE = _resolve_version()
49
+ return _VERSION_CACHE
50
+ raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
core/agent/__init__.py ADDED
File without changes
@@ -0,0 +1,89 @@
1
+ """Child->parent live-activity side-channel for the fleet view (Stage 1.5).
2
+
3
+ Design SOT: ``docs/plans/2026-07-03-fleet-view.md``.
4
+
5
+ Sub-agents run as ``python -m core.agent.worker`` subprocesses with the child
6
+ :class:`~core.agent.loop.AgenticLoop` in ``quiet=True`` mode, so the child emits
7
+ no per-tool IPC back to the parent's renderer — the parent learns a task's state
8
+ only from the single final ``WorkerResult`` line at exit. Stage 1 left
9
+ ``FleetAgent.current_activity`` as ``""`` for exactly this reason.
10
+
11
+ Stage 1.5 closes the gap with a **process-local activity sink**. The worker
12
+ subprocess installs a sink (:func:`set_activity_sink`) that serialises a
13
+ ``{"type":"activity", ...}`` JSON line to its own stdout *before* the final
14
+ result line. The child's :class:`ToolExecutor` calls :func:`emit_tool_activity`
15
+ at the single per-tool dispatch boundary; when a sink is installed the current
16
+ tool name + best-effort cumulative token count are forwarded to it.
17
+
18
+ Fail-safe by construction:
19
+
20
+ - The sink is a plain module global, **only ever set inside the worker
21
+ subprocess** (:mod:`core.agent.worker`). The parent process and every test
22
+ never call :func:`set_activity_sink`, so :func:`emit_tool_activity` is a
23
+ cheap no-op everywhere except a worker that opted in via
24
+ ``WorkerRequest.emit_activity``.
25
+ - No sink installed → no emission → ``current_activity`` stays ``""`` (the
26
+ Stage 1 honest default). Nothing is faked.
27
+ - Token count is read from the process token tracker (fresh per subprocess, so
28
+ its cumulative total *is* this task's total). Subscription / CLI-routed calls
29
+ expose no usage, so the count is honestly ``0`` for those — never fabricated.
30
+ """
31
+
32
+ from __future__ import annotations
33
+
34
+ import logging
35
+ from collections.abc import Callable
36
+
37
+ log = logging.getLogger(__name__)
38
+
39
+ # ``(tool_name, cumulative_tokens) -> None``. Installed only by the worker
40
+ # subprocess; ``None`` everywhere else (parent process, tests) → no-op emit.
41
+ ActivitySink = Callable[[str, int], None]
42
+
43
+ _activity_sink: ActivitySink | None = None
44
+
45
+
46
+ def set_activity_sink(sink: ActivitySink) -> None:
47
+ """Install the process-local activity sink (worker subprocess only)."""
48
+ global _activity_sink
49
+ _activity_sink = sink
50
+
51
+
52
+ def clear_activity_sink() -> None:
53
+ """Remove the installed sink (test hygiene; the worker process just exits)."""
54
+ global _activity_sink
55
+ _activity_sink = None
56
+
57
+
58
+ def get_activity_sink() -> ActivitySink | None:
59
+ """Return the installed sink, or ``None`` when the feature is inactive."""
60
+ return _activity_sink
61
+
62
+
63
+ def emit_tool_activity(tool: str) -> None:
64
+ """Forward the child's *current* tool + cumulative tokens to the sink.
65
+
66
+ A cheap no-op unless a sink was installed (i.e. unless this is a worker
67
+ subprocess that opted in via ``WorkerRequest.emit_activity``). The token
68
+ count is best-effort: read from the process token tracker, which is fresh
69
+ per worker subprocess so its cumulative total is this task's total, and is
70
+ ``0`` for subscription / CLI-routed calls that expose no usage.
71
+ """
72
+ sink = _activity_sink
73
+ if sink is None:
74
+ return
75
+ tokens = 0
76
+ try:
77
+ from core.llm.token_tracker import get_tracker
78
+
79
+ snap = get_tracker().snapshot()
80
+ tokens = int(snap.total_input_tokens) + int(snap.total_output_tokens)
81
+ except Exception:
82
+ # Best-effort — a missing/unbound tracker must never break tool dispatch.
83
+ tokens = 0
84
+ try:
85
+ sink(tool, tokens)
86
+ except Exception:
87
+ # A misbehaving sink (e.g. a broken stdout pipe) must never propagate
88
+ # into the child's tool-execution path.
89
+ log.debug("activity sink raised for tool=%s", tool, exc_info=True)
@@ -0,0 +1,185 @@
1
+ """Agent contracts SoT reader — ADR-012 M2, JSON mutation surface.
2
+
3
+ Mutator overrides per-agent ``role`` / ``system_prompt`` / ``tools`` on
4
+ :class:`core.skills.agents.AgentDefinition` instances. ``model`` field
5
+ 는 Tier 2 (안전성 invariants 의 root) 이므로 본 surface 에서 명시적
6
+ 제외 — mutator 가 provider 를 임의로 바꿔 safety guardrail 을 우회하지
7
+ 못하도록 설계.
8
+
9
+ **SoT schema** (모든 agent entry optional, 모든 field optional):
10
+
11
+ .. code-block:: json
12
+
13
+ {
14
+ "research_assistant": {
15
+ "role": "Research Specialist (v2)",
16
+ "system_prompt": "...evolved prompt...",
17
+ "tools": ["web_search", "web_fetch", "read_document"]
18
+ },
19
+ "data_analyst": {
20
+ "system_prompt": "...evolved prompt..."
21
+ }
22
+ }
23
+
24
+ Unknown agent name / 부적합 schema → graceful drop (forward-compat).
25
+
26
+ **Resolution order** (PR-BACKFILL-SOT 2026-05-21 shared chain):
27
+
28
+ 1. ``GEODE_AGENT_CONTRACTS_OVERRIDE`` env var — explicit override.
29
+ - With ``GEODE_AGENT_CONTRACTS_STRICT=1``: strict.
30
+ - Without strict flag: graceful (no fall-through).
31
+ 2. ``~/.geode/autoresearch/handoff/agent-contracts.json`` — operator-local.
32
+ 3. ``core/self_improving/state/policies/agent-contracts.json`` — in-repo.
33
+ 4. ``None`` — no-op.
34
+
35
+ **Frontier**: Claude Code 의 ``.claude/agents/*.md`` agent definitions
36
+ 이 사용자 hand-edit 만 받지만 — mutator 가 자동 진화시키는 것이 M2 의
37
+ 가치. ``model`` 은 사용자 explicit 선택만 허용 (Tier 2).
38
+ """
39
+
40
+ from __future__ import annotations
41
+
42
+ import copy
43
+ import logging
44
+ from pathlib import Path
45
+ from typing import Any
46
+
47
+ from core.agent.policy_sot import load_policy_sot
48
+ from core.paths import (
49
+ AUTORESEARCH_AGENT_CONTRACTS_PATH,
50
+ OPERATOR_LOCAL_AGENT_CONTRACTS_PATH,
51
+ )
52
+
53
+ log = logging.getLogger(__name__)
54
+
55
+ _AGENT_CONTRACTS_OVERRIDE_ENV = "GEODE_AGENT_CONTRACTS_OVERRIDE"
56
+
57
+ _AGENT_CONTRACTS_SOT_PATH = AUTORESEARCH_AGENT_CONTRACTS_PATH
58
+ """Cross-process in-repo SoT path (M2, 2026-05-21). Module-local alias."""
59
+
60
+ _OPERATOR_LOCAL_AGENT_CONTRACTS_PATH = OPERATOR_LOCAL_AGENT_CONTRACTS_PATH
61
+ """Operator-local SoT path. Module-local alias for monkey-patch."""
62
+
63
+
64
+ # Mutable field set — ``model`` is intentionally absent (Tier 2 guardrail).
65
+ _FIELD_ROLE = "role"
66
+ _FIELD_SYSTEM_PROMPT = "system_prompt"
67
+ _FIELD_TOOLS = "tools"
68
+ _MUTABLE_FIELDS = frozenset({_FIELD_ROLE, _FIELD_SYSTEM_PROMPT, _FIELD_TOOLS})
69
+
70
+
71
+ def _load_agent_contracts_override() -> dict[str, dict[str, Any]] | None:
72
+ """Return the active agent-contracts dict, or ``None`` if no SoT applies."""
73
+ return load_policy_sot(
74
+ env_var=_AGENT_CONTRACTS_OVERRIDE_ENV,
75
+ operator_local=_OPERATOR_LOCAL_AGENT_CONTRACTS_PATH,
76
+ in_repo=_AGENT_CONTRACTS_SOT_PATH,
77
+ label="agent-contracts",
78
+ validate_strict=_validate_schema,
79
+ validate_graceful=_validate_schema,
80
+ coerce=_coerce,
81
+ )
82
+
83
+
84
+ def _validate_schema(data: Any, path: Path) -> None:
85
+ """Top-level ``dict[str, dict[field, value]]``. role/system_prompt = str;
86
+ tools = list[str]. Unknown field 무시 (forward-compat).
87
+ """
88
+ if not isinstance(data, dict):
89
+ raise RuntimeError(f"agent-contracts at {path} must be a dict")
90
+ for agent_name, entry in data.items():
91
+ if not isinstance(agent_name, str):
92
+ type_name = type(agent_name).__name__
93
+ raise RuntimeError(f"agent-contracts at {path} key must be str, got {type_name}")
94
+ if not isinstance(entry, dict):
95
+ type_name = type(entry).__name__
96
+ raise RuntimeError(
97
+ f"agent-contracts at {path}[{agent_name!r}] must be dict, got {type_name}"
98
+ )
99
+ for field in (_FIELD_ROLE, _FIELD_SYSTEM_PROMPT):
100
+ if field in entry and not isinstance(entry[field], str):
101
+ raise RuntimeError(f"agent-contracts at {path}[{agent_name!r}].{field} must be str")
102
+ if _FIELD_TOOLS in entry:
103
+ tools = entry[_FIELD_TOOLS]
104
+ if not isinstance(tools, list) or not all(isinstance(t, str) for t in tools):
105
+ raise RuntimeError(
106
+ f"agent-contracts at {path}[{agent_name!r}].tools must be list[str]"
107
+ )
108
+
109
+
110
+ def _coerce(data: dict[str, Any]) -> dict[str, dict[str, Any]]:
111
+ """Extract known mutable fields per agent. ``model`` etc. dropped
112
+ (Tier 2 guardrail)."""
113
+ result: dict[str, dict[str, Any]] = {}
114
+ for agent_name, entry in data.items():
115
+ if not isinstance(entry, dict):
116
+ continue
117
+ kept: dict[str, Any] = {}
118
+ for field in _MUTABLE_FIELDS:
119
+ if field in entry:
120
+ value = entry[field]
121
+ if field == _FIELD_TOOLS and isinstance(value, list):
122
+ kept[field] = [t for t in value if isinstance(t, str)]
123
+ elif isinstance(value, str):
124
+ kept[field] = value
125
+ if kept:
126
+ result[agent_name] = kept
127
+ return result
128
+
129
+
130
+ def apply_agent_contracts_policy(
131
+ agent_def: Any,
132
+ policy: dict[str, dict[str, Any]] | None,
133
+ ) -> Any:
134
+ """Return a (possibly modified) copy of ``agent_def`` with policy
135
+ overrides applied — role / system_prompt / tools only. ``model``
136
+ field is never touched (Tier 2 guardrail).
137
+
138
+ ``policy is None`` or agent name absent from policy → original
139
+ ``agent_def`` returned unchanged (no behavior change).
140
+ """
141
+ if not policy:
142
+ return agent_def
143
+ name = getattr(agent_def, "name", None)
144
+ if not isinstance(name, str) or name not in policy:
145
+ return agent_def
146
+ entry = policy[name]
147
+ if not entry:
148
+ return agent_def
149
+ # Pydantic BaseModel.model_copy(update=...) returns a new instance.
150
+ # Filter overrides to mutable fields only — defensive even though
151
+ # ``_coerce`` already drops everything else.
152
+ overrides = {k: v for k, v in entry.items() if k in _MUTABLE_FIELDS}
153
+ if not overrides:
154
+ return agent_def
155
+ # CSP-1 fix-up (Codex MCP MEDIUM #1) — an agent that declares a
156
+ # ``toolkit:`` will have its ``tools`` field shadowed by the
157
+ # toolkit's resolved set inside ``filter_handlers``. A policy entry
158
+ # that mutates ``tools`` on a toolkit-declaring agent therefore
159
+ # silently does nothing. Warn so operators notice rather than
160
+ # debugging a no-op override later.
161
+ agent_toolkit: str = str(getattr(agent_def, "toolkit", "") or "")
162
+ if _FIELD_TOOLS in overrides and agent_toolkit:
163
+ log.warning(
164
+ "agent_contracts_policy: agent %r declares toolkit=%r; "
165
+ "the policy's ``tools`` override is shadowed at spawn time "
166
+ "(toolkit takes precedence in filter_handlers). Either "
167
+ "remove the ``tools`` override or add a ``toolkit`` field "
168
+ "to the policy entry.",
169
+ name,
170
+ agent_toolkit,
171
+ )
172
+ if hasattr(agent_def, "model_copy"):
173
+ return agent_def.model_copy(update=overrides)
174
+ # Fallback for non-BaseModel doubles (test stubs, dicts) —
175
+ # deep-copy + setattr / item-set.
176
+ new_def = copy.deepcopy(agent_def)
177
+ for k, v in overrides.items():
178
+ if isinstance(new_def, dict):
179
+ new_def[k] = v
180
+ else:
181
+ setattr(new_def, k, v)
182
+ return new_def
183
+
184
+
185
+ __all__ = ["apply_agent_contracts_policy"]