alysis-code 0.13.0__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 (458) hide show
  1. alysis_code/__init__.py +3 -0
  2. alysis_code/__main__.py +4 -0
  3. alysis_code/_build_info.py +14 -0
  4. alysis_code/account_login.py +468 -0
  5. alysis_code/agent/README.md +35 -0
  6. alysis_code/agent/__init__.py +11 -0
  7. alysis_code/agent/acceptance_contract.py +2217 -0
  8. alysis_code/agent/blast_radius.py +1403 -0
  9. alysis_code/agent/cache_keepalive.py +227 -0
  10. alysis_code/agent/completion_certificate.py +366 -0
  11. alysis_code/agent/completion_gate.py +306 -0
  12. alysis_code/agent/empty_response_stall.py +403 -0
  13. alysis_code/agent/errors.py +28 -0
  14. alysis_code/agent/llm_calls.py +475 -0
  15. alysis_code/agent/mutation_classification.py +227 -0
  16. alysis_code/agent/prompt_context.py +2508 -0
  17. alysis_code/agent/read_ledger.py +253 -0
  18. alysis_code/agent/regression_baseline.py +642 -0
  19. alysis_code/agent/reproduction_first.py +610 -0
  20. alysis_code/agent/sensitive_output.py +629 -0
  21. alysis_code/agent/session.py +3218 -0
  22. alysis_code/agent/steering.py +191 -0
  23. alysis_code/agent/subagent_execution.py +5177 -0
  24. alysis_code/agent/subagent_workspace.py +666 -0
  25. alysis_code/agent/tools_assembly.py +4728 -0
  26. alysis_code/agent/turn/__init__.py +101 -0
  27. alysis_code/agent/turn/core.py +8483 -0
  28. alysis_code/agent/turn/events.py +113 -0
  29. alysis_code/agent/turn/exploration.py +590 -0
  30. alysis_code/agent/turn/interventions.py +65 -0
  31. alysis_code/agent/turn/read_cache.py +420 -0
  32. alysis_code/agent/turn/snapshot.py +179 -0
  33. alysis_code/agent/turn_contract.py +661 -0
  34. alysis_code/agent/turn_path.py +129 -0
  35. alysis_code/agent/verification.py +2885 -0
  36. alysis_code/agent/verification_commands.py +512 -0
  37. alysis_code/agent/verification_evidence.py +738 -0
  38. alysis_code/agent_loop.py +693 -0
  39. alysis_code/agent_runtimes/__init__.py +51 -0
  40. alysis_code/agent_runtimes/base.py +114 -0
  41. alysis_code/agent_runtimes/builtins.py +129 -0
  42. alysis_code/agent_runtimes/codex_cli.py +664 -0
  43. alysis_code/agent_runtimes/host.py +263 -0
  44. alysis_code/agent_runtimes/registry.py +64 -0
  45. alysis_code/agent_runtimes/service.py +150 -0
  46. alysis_code/agentbox_client.py +416 -0
  47. alysis_code/agentbox_integration.py +310 -0
  48. alysis_code/alysis_cloud.py +152 -0
  49. alysis_code/approval_scope.py +276 -0
  50. alysis_code/assets/README.md +33 -0
  51. alysis_code/assets/__init__.py +126 -0
  52. alysis_code/assets/asset_read_core.py +281 -0
  53. alysis_code/assets/budget_allocator.py +456 -0
  54. alysis_code/assets/comprehender.py +759 -0
  55. alysis_code/assets/index.py +654 -0
  56. alysis_code/assets/ingestion.py +275 -0
  57. alysis_code/assets/legacy_migration.py +413 -0
  58. alysis_code/assets/models.py +263 -0
  59. alysis_code/assets/ocr.py +239 -0
  60. alysis_code/assets/owl/ascii/f-000.txt +13 -0
  61. alysis_code/assets/owl/ascii/f-001.txt +13 -0
  62. alysis_code/assets/owl/ascii/f-002.txt +13 -0
  63. alysis_code/assets/owl/ascii/f-003.txt +13 -0
  64. alysis_code/assets/owl/ascii/f-004.txt +13 -0
  65. alysis_code/assets/owl/ascii/f-005.txt +13 -0
  66. alysis_code/assets/owl/ascii/f-006.txt +13 -0
  67. alysis_code/assets/owl/ascii/f-007.txt +13 -0
  68. alysis_code/assets/owl/ascii/f-008.txt +13 -0
  69. alysis_code/assets/owl/ascii/f-009.txt +13 -0
  70. alysis_code/assets/owl/ascii/f-010.txt +13 -0
  71. alysis_code/assets/owl/ascii/f-011.txt +13 -0
  72. alysis_code/assets/owl/ascii/f-012.txt +13 -0
  73. alysis_code/assets/owl/ascii/f-013.txt +13 -0
  74. alysis_code/assets/owl/ascii/f-014.txt +13 -0
  75. alysis_code/assets/owl/ascii/f-015.txt +13 -0
  76. alysis_code/assets/owl/ascii/f-016.txt +13 -0
  77. alysis_code/assets/owl/ascii/f-017.txt +13 -0
  78. alysis_code/assets/owl/ascii/f-018.txt +13 -0
  79. alysis_code/assets/owl/ascii/f-019.txt +13 -0
  80. alysis_code/assets/owl/ascii/f-020.txt +13 -0
  81. alysis_code/assets/owl/index.html +98 -0
  82. alysis_code/assets/owl/show-owl.sh +761 -0
  83. alysis_code/assets/paths.py +49 -0
  84. alysis_code/assets/plan_binding.py +326 -0
  85. alysis_code/assets/planner_context.py +466 -0
  86. alysis_code/assets/planner_tools.py +184 -0
  87. alysis_code/assets/prompts.py +101 -0
  88. alysis_code/assets/replanner_context.py +239 -0
  89. alysis_code/assets/surface.py +521 -0
  90. alysis_code/assets/untrusted_content.py +48 -0
  91. alysis_code/assets/usage_logger.py +94 -0
  92. alysis_code/assets/worker_mirror.py +428 -0
  93. alysis_code/assets/worker_section.py +303 -0
  94. alysis_code/assets/worker_tools.py +468 -0
  95. alysis_code/atomic_io.py +83 -0
  96. alysis_code/auth_diagnostics.py +272 -0
  97. alysis_code/background_runner.py +366 -0
  98. alysis_code/branding.py +270 -0
  99. alysis_code/budget_policy.py +390 -0
  100. alysis_code/build_identity.py +465 -0
  101. alysis_code/builtin_hooks/__init__.py +7 -0
  102. alysis_code/builtin_hooks/notify_done_windows.py +65 -0
  103. alysis_code/bwrap_etc.py +76 -0
  104. alysis_code/cancellation.py +41 -0
  105. alysis_code/capabilities.py +137 -0
  106. alysis_code/chatgpt_codex_static_provider.py +133 -0
  107. alysis_code/cli.py +51 -0
  108. alysis_code/cli_impl/__init__.py +1 -0
  109. alysis_code/cli_impl/assets_cli.py +537 -0
  110. alysis_code/cli_impl/assets_modal.py +412 -0
  111. alysis_code/cli_impl/chat/__init__.py +156 -0
  112. alysis_code/cli_impl/chat/commands.py +2616 -0
  113. alysis_code/cli_impl/chat/loop.py +4508 -0
  114. alysis_code/cli_impl/chat/mid_turn_policy.py +125 -0
  115. alysis_code/cli_impl/chat/rendering.py +444 -0
  116. alysis_code/cli_impl/chat/state.py +124 -0
  117. alysis_code/cli_impl/chat_resume.py +830 -0
  118. alysis_code/cli_impl/chat_slash_completer.py +258 -0
  119. alysis_code/cli_impl/commands/__init__.py +11 -0
  120. alysis_code/cli_impl/commands/_shared.py +89 -0
  121. alysis_code/cli_impl/commands/auth.py +623 -0
  122. alysis_code/cli_impl/commands/chat_resume_helpers.py +1531 -0
  123. alysis_code/cli_impl/commands/chat_state.py +158 -0
  124. alysis_code/cli_impl/commands/chat_status.py +1248 -0
  125. alysis_code/cli_impl/commands/chat_terminal.py +942 -0
  126. alysis_code/cli_impl/commands/chat_tui_panels.py +1018 -0
  127. alysis_code/cli_impl/commands/cli_common.py +1223 -0
  128. alysis_code/cli_impl/commands/cli_surface.py +77 -0
  129. alysis_code/cli_impl/commands/config.py +131 -0
  130. alysis_code/cli_impl/commands/conventions.py +85 -0
  131. alysis_code/cli_impl/commands/execution_helpers.py +350 -0
  132. alysis_code/cli_impl/commands/extensions.py +401 -0
  133. alysis_code/cli_impl/commands/forge.py +1282 -0
  134. alysis_code/cli_impl/commands/forge_asset_view.py +121 -0
  135. alysis_code/cli_impl/commands/forge_helpers.py +1215 -0
  136. alysis_code/cli_impl/commands/hooks.py +737 -0
  137. alysis_code/cli_impl/commands/ide_bridge.py +31 -0
  138. alysis_code/cli_impl/commands/mcp.py +700 -0
  139. alysis_code/cli_impl/commands/profile.py +453 -0
  140. alysis_code/cli_impl/commands/prompt_helpers.py +307 -0
  141. alysis_code/cli_impl/commands/report.py +88 -0
  142. alysis_code/cli_impl/commands/root.py +1118 -0
  143. alysis_code/cli_impl/commands/sandbox.py +184 -0
  144. alysis_code/cli_impl/commands/server.py +54 -0
  145. alysis_code/cli_impl/commands/sessions.py +252 -0
  146. alysis_code/cli_impl/commands/skills.py +404 -0
  147. alysis_code/cli_impl/commands/startup.py +946 -0
  148. alysis_code/cli_impl/commands/tools.py +335 -0
  149. alysis_code/cli_impl/commands/update.py +364 -0
  150. alysis_code/cli_impl/commands/welcome.py +972 -0
  151. alysis_code/cli_impl/config_menu.py +3882 -0
  152. alysis_code/cli_impl/forge.py +4509 -0
  153. alysis_code/cli_impl/forge_recovery.py +485 -0
  154. alysis_code/cli_impl/setup_wizard.py +2409 -0
  155. alysis_code/cli_impl/tui/__init__.py +58 -0
  156. alysis_code/cli_impl/tui/app.py +4551 -0
  157. alysis_code/cli_impl/tui/config.py +32 -0
  158. alysis_code/cli_impl/tui/config_flow.py +2754 -0
  159. alysis_code/cli_impl/tui/config_overlay.py +566 -0
  160. alysis_code/cli_impl/tui/content.py +78 -0
  161. alysis_code/cli_impl/tui/footer.py +218 -0
  162. alysis_code/cli_impl/tui/forge_status.py +136 -0
  163. alysis_code/cli_impl/tui/markdown.py +244 -0
  164. alysis_code/cli_impl/tui/owl.py +109 -0
  165. alysis_code/cli_impl/tui/plan_meta.py +477 -0
  166. alysis_code/cli_impl/tui/setup_app.py +519 -0
  167. alysis_code/cli_impl/tui/setup_flow.py +1622 -0
  168. alysis_code/cli_impl/tui/state.py +101 -0
  169. alysis_code/cli_impl/tui/subagent_identity.py +66 -0
  170. alysis_code/cli_impl/tui/subagent_panel.py +186 -0
  171. alysis_code/cli_impl/tui/surface.py +796 -0
  172. alysis_code/cli_impl/tui/transcript.py +514 -0
  173. alysis_code/cli_impl/tui/update_prompt.py +79 -0
  174. alysis_code/cli_impl/tui/workspace_guard.py +384 -0
  175. alysis_code/clipboard.py +172 -0
  176. alysis_code/code_review.py +1211 -0
  177. alysis_code/compaction/__init__.py +28 -0
  178. alysis_code/compaction/conversation_compactor.py +2932 -0
  179. alysis_code/compaction/importance.py +177 -0
  180. alysis_code/compaction/settings.py +297 -0
  181. alysis_code/compaction/tool_output_offload.py +447 -0
  182. alysis_code/config.py +3509 -0
  183. alysis_code/conflict_auto_resolver.py +895 -0
  184. alysis_code/context/__init__.py +1 -0
  185. alysis_code/context/tool_schema_budgeter.py +220 -0
  186. alysis_code/crash_diagnostics.py +282 -0
  187. alysis_code/custom_tools/README.md +34 -0
  188. alysis_code/custom_tools/__init__.py +43 -0
  189. alysis_code/custom_tools/discovery.py +903 -0
  190. alysis_code/custom_tools/runtime.py +1516 -0
  191. alysis_code/custom_tools/session.py +227 -0
  192. alysis_code/custom_tools/trust.py +232 -0
  193. alysis_code/diff_paths.py +113 -0
  194. alysis_code/direction_change.py +293 -0
  195. alysis_code/dispatch_timing.py +306 -0
  196. alysis_code/durable_service_manager.py +1236 -0
  197. alysis_code/edit_discipline.py +659 -0
  198. alysis_code/error_text.py +73 -0
  199. alysis_code/execution_budget.py +411 -0
  200. alysis_code/execution_context.py +915 -0
  201. alysis_code/execution_deadline.py +1065 -0
  202. alysis_code/execution_shared.py +1904 -0
  203. alysis_code/extensions/README.md +30 -0
  204. alysis_code/extensions/__init__.py +93 -0
  205. alysis_code/extensions/activation.py +138 -0
  206. alysis_code/extensions/install.py +1436 -0
  207. alysis_code/extensions/manifest.py +487 -0
  208. alysis_code/extensions/models.py +74 -0
  209. alysis_code/extensions/paths.py +56 -0
  210. alysis_code/extensions/registry.json +4 -0
  211. alysis_code/extensions/registry.py +52 -0
  212. alysis_code/extensions/state.py +83 -0
  213. alysis_code/extensions/workspace_trust.py +101 -0
  214. alysis_code/failed_task_evidence.py +369 -0
  215. alysis_code/failure_category.py +315 -0
  216. alysis_code/feedback_report.py +1647 -0
  217. alysis_code/file_classification.py +485 -0
  218. alysis_code/forge.py +2064 -0
  219. alysis_code/forge_completion.py +362 -0
  220. alysis_code/forge_events.py +475 -0
  221. alysis_code/frontmatter_utils.py +95 -0
  222. alysis_code/git_evidence.py +1181 -0
  223. alysis_code/git_ops.py +560 -0
  224. alysis_code/git_safe.py +62 -0
  225. alysis_code/git_worktrees.py +190 -0
  226. alysis_code/hooks/README.md +33 -0
  227. alysis_code/hooks/__init__.py +67 -0
  228. alysis_code/hooks/audit.py +171 -0
  229. alysis_code/hooks/config.py +225 -0
  230. alysis_code/hooks/dispatcher.py +1110 -0
  231. alysis_code/hooks/models.py +447 -0
  232. alysis_code/hooks/trust.py +202 -0
  233. alysis_code/host_actions.py +543 -0
  234. alysis_code/host_browser.py +103 -0
  235. alysis_code/ide/__init__.py +5 -0
  236. alysis_code/ide/activity_events.py +399 -0
  237. alysis_code/ide/approvals.py +337 -0
  238. alysis_code/ide/artifacts.py +153 -0
  239. alysis_code/ide/browser_egress_proxy.py +1076 -0
  240. alysis_code/ide/cdp_websocket_transport.py +1192 -0
  241. alysis_code/ide/change_ledger.py +1721 -0
  242. alysis_code/ide/context_blocks.py +979 -0
  243. alysis_code/ide/event_stream.py +531 -0
  244. alysis_code/ide/forge_protocol.py +3112 -0
  245. alysis_code/ide/forge_request_ledger.py +737 -0
  246. alysis_code/ide/health.py +965 -0
  247. alysis_code/ide/managed_browser.py +2251 -0
  248. alysis_code/ide/management_protocol.py +3414 -0
  249. alysis_code/ide/mcp_oauth_coordinator.py +744 -0
  250. alysis_code/ide/mcp_oauth_lifecycle.py +1504 -0
  251. alysis_code/ide/prompt_queue.py +1070 -0
  252. alysis_code/ide/protocol.py +191 -0
  253. alysis_code/ide/resumable_swarm.py +1543 -0
  254. alysis_code/ide/session_search.py +295 -0
  255. alysis_code/ide/stdio_bridge.py +9935 -0
  256. alysis_code/ide/structured_state.py +1579 -0
  257. alysis_code/ide/swarm_protocol.py +816 -0
  258. alysis_code/integration_gate.py +506 -0
  259. alysis_code/interactive_input_guard.py +39 -0
  260. alysis_code/interactive_plan_mode.py +26 -0
  261. alysis_code/internal_artifacts.py +179 -0
  262. alysis_code/knowledge_base.py +1409 -0
  263. alysis_code/knowledge_capture.py +1190 -0
  264. alysis_code/knowledge_librarian.py +605 -0
  265. alysis_code/language_policy.py +34 -0
  266. alysis_code/litellm_static_provider.py +535 -0
  267. alysis_code/llm/__init__.py +1 -0
  268. alysis_code/llm/anthropic_messages.py +2288 -0
  269. alysis_code/llm/base.py +71 -0
  270. alysis_code/llm/cache_capabilities.py +985 -0
  271. alysis_code/llm/cache_control_blocks.py +244 -0
  272. alysis_code/llm/cache_policy.py +388 -0
  273. alysis_code/llm/factory.py +373 -0
  274. alysis_code/llm/gemini_generate_content.py +2652 -0
  275. alysis_code/llm/gemini_interactions.py +739 -0
  276. alysis_code/llm/metadata.py +450 -0
  277. alysis_code/llm/openai_compat.py +2947 -0
  278. alysis_code/llm/openai_responses.py +2604 -0
  279. alysis_code/llm/protocols.py +609 -0
  280. alysis_code/llm/provider_limits.py +525 -0
  281. alysis_code/llm/request_plan.py +389 -0
  282. alysis_code/llm/request_shape.py +238 -0
  283. alysis_code/llm/streaming.py +108 -0
  284. alysis_code/llm/temperature_compat.py +78 -0
  285. alysis_code/llm/types.py +195 -0
  286. alysis_code/llm/usage_normalization.py +222 -0
  287. alysis_code/llm_error_display.py +315 -0
  288. alysis_code/logging_redaction.py +326 -0
  289. alysis_code/managed_host_deadline.py +196 -0
  290. alysis_code/mcp/README.md +33 -0
  291. alysis_code/mcp/__init__.py +24 -0
  292. alysis_code/mcp/client.py +1137 -0
  293. alysis_code/mcp/config.py +597 -0
  294. alysis_code/mcp/errors.py +113 -0
  295. alysis_code/mcp/forge_scope.py +154 -0
  296. alysis_code/mcp/jsonrpc.py +214 -0
  297. alysis_code/mcp/manager.py +2308 -0
  298. alysis_code/mcp/models.py +666 -0
  299. alysis_code/mcp/oauth.py +972 -0
  300. alysis_code/mcp/oauth_runtime.py +310 -0
  301. alysis_code/mcp/oauth_store.py +276 -0
  302. alysis_code/mcp/prompts.py +329 -0
  303. alysis_code/mcp/resources.py +295 -0
  304. alysis_code/mcp/roots.py +106 -0
  305. alysis_code/mcp/server_requests.py +75 -0
  306. alysis_code/mcp/token_store.py +859 -0
  307. alysis_code/mcp/transport_http.py +1338 -0
  308. alysis_code/mcp/transport_stdio.py +1267 -0
  309. alysis_code/mcp/untrusted_content.py +119 -0
  310. alysis_code/merge_conflict_reviewer.py +729 -0
  311. alysis_code/model_catalog/__init__.py +1 -0
  312. alysis_code/model_catalog/chatgpt_codex_subscription_snapshot.json +186 -0
  313. alysis_code/model_catalog/litellm_model_prices_snapshot.json +44715 -0
  314. alysis_code/model_catalog/litellm_model_prices_snapshot.meta.json +17 -0
  315. alysis_code/model_metadata_policy.py +223 -0
  316. alysis_code/model_metadata_utils.py +103 -0
  317. alysis_code/model_registry.py +1420 -0
  318. alysis_code/model_router.py +147 -0
  319. alysis_code/permission_policy.py +1016 -0
  320. alysis_code/personas.py +451 -0
  321. alysis_code/pipeline_facts.py +233 -0
  322. alysis_code/plan_assistant.py +4763 -0
  323. alysis_code/plan_mode.py +393 -0
  324. alysis_code/plan_reconciliation.py +1228 -0
  325. alysis_code/plan_repair.py +652 -0
  326. alysis_code/plan_validation.py +1099 -0
  327. alysis_code/planning_constraints.py +904 -0
  328. alysis_code/policy.py +95 -0
  329. alysis_code/preview_server.py +457 -0
  330. alysis_code/process_reaping.py +566 -0
  331. alysis_code/profile_presets.py +1834 -0
  332. alysis_code/profiles.py +666 -0
  333. alysis_code/provider_auth/__init__.py +29 -0
  334. alysis_code/provider_auth/base.py +99 -0
  335. alysis_code/provider_auth/openai_codex.py +951 -0
  336. alysis_code/provider_auth/registry.py +76 -0
  337. alysis_code/provider_auth/store.py +125 -0
  338. alysis_code/provider_diagnostics.py +1209 -0
  339. alysis_code/provider_model_catalog.py +685 -0
  340. alysis_code/provider_telemetry.py +1699 -0
  341. alysis_code/provider_url.py +75 -0
  342. alysis_code/reasoning_contracts.py +911 -0
  343. alysis_code/remote_sync.py +350 -0
  344. alysis_code/replanning.py +1195 -0
  345. alysis_code/repo_scan.py +1152 -0
  346. alysis_code/request_estimation.py +296 -0
  347. alysis_code/review_gate.py +617 -0
  348. alysis_code/run_lock.py +1141 -0
  349. alysis_code/run_outcome.py +58 -0
  350. alysis_code/run_provenance.py +774 -0
  351. alysis_code/run_state.py +445 -0
  352. alysis_code/runtime_artifacts.py +116 -0
  353. alysis_code/runtime_context_features.py +78 -0
  354. alysis_code/runtime_kind.py +52 -0
  355. alysis_code/safety/__init__.py +11 -0
  356. alysis_code/safety/mcp_sanitize.py +29 -0
  357. alysis_code/safety/safe_http.py +297 -0
  358. alysis_code/safety/subagent_report.py +184 -0
  359. alysis_code/sandbox_doctor.py +682 -0
  360. alysis_code/sandbox_runner.py +1025 -0
  361. alysis_code/sandbox_settings.py +423 -0
  362. alysis_code/serialized_paths.py +355 -0
  363. alysis_code/server/__init__.py +3 -0
  364. alysis_code/server/app.py +367 -0
  365. alysis_code/server/auth.py +34 -0
  366. alysis_code/server/job_config.py +30 -0
  367. alysis_code/server/settings.py +215 -0
  368. alysis_code/server/store.py +193 -0
  369. alysis_code/server/worker_runner.py +657 -0
  370. alysis_code/service_persistence.py +355 -0
  371. alysis_code/session_artifacts.py +108 -0
  372. alysis_code/session_metrics.py +331 -0
  373. alysis_code/session_store.py +624 -0
  374. alysis_code/skills/README.md +34 -0
  375. alysis_code/skills/__init__.py +104 -0
  376. alysis_code/skills/conventions.py +84 -0
  377. alysis_code/skills/discovery.py +176 -0
  378. alysis_code/skills/eval_models.py +232 -0
  379. alysis_code/skills/eval_runner.py +372 -0
  380. alysis_code/skills/evals.py +1344 -0
  381. alysis_code/skills/install.py +293 -0
  382. alysis_code/skills/loader.py +118 -0
  383. alysis_code/skills/matching.py +103 -0
  384. alysis_code/skills/models.py +71 -0
  385. alysis_code/skills/paths.py +56 -0
  386. alysis_code/skills/prompting.py +500 -0
  387. alysis_code/skills/scaffold.py +142 -0
  388. alysis_code/skills/state.py +441 -0
  389. alysis_code/skills/transactions.py +125 -0
  390. alysis_code/skills/validation.py +304 -0
  391. alysis_code/step_budget.py +238 -0
  392. alysis_code/subagent_labels.py +49 -0
  393. alysis_code/subagents.py +1072 -0
  394. alysis_code/surface/__init__.py +80 -0
  395. alysis_code/surface/base.py +305 -0
  396. alysis_code/surface/console.py +387 -0
  397. alysis_code/surface/events.py +372 -0
  398. alysis_code/surface/hidden_surface.py +529 -0
  399. alysis_code/surface/noop_surface.py +219 -0
  400. alysis_code/surface/rich_surface.py +1555 -0
  401. alysis_code/surface/styles.py +67 -0
  402. alysis_code/surface/theme.py +455 -0
  403. alysis_code/surface/types.py +100 -0
  404. alysis_code/swarm_backend.py +926 -0
  405. alysis_code/swarm_orchestrator.py +4020 -0
  406. alysis_code/swarm_scheduler.py +441 -0
  407. alysis_code/swarm_trace.py +429 -0
  408. alysis_code/swarm_worker.py +2119 -0
  409. alysis_code/swarm_write_guard.py +348 -0
  410. alysis_code/task_dependencies.py +170 -0
  411. alysis_code/task_readiness.py +992 -0
  412. alysis_code/task_scope.py +2148 -0
  413. alysis_code/terminal_manager.py +762 -0
  414. alysis_code/terminal_ownership.py +460 -0
  415. alysis_code/text_normalization.py +30 -0
  416. alysis_code/token_budget.py +97 -0
  417. alysis_code/tools/README.md +34 -0
  418. alysis_code/tools/__init__.py +1 -0
  419. alysis_code/tools/artifacts.py +127 -0
  420. alysis_code/tools/availability.py +188 -0
  421. alysis_code/tools/fs.py +1456 -0
  422. alysis_code/tools/git.py +461 -0
  423. alysis_code/tools/history.py +229 -0
  424. alysis_code/tools/http_timeout.py +78 -0
  425. alysis_code/tools/image_generation.py +552 -0
  426. alysis_code/tools/registry.py +2936 -0
  427. alysis_code/tools/repo_map.py +476 -0
  428. alysis_code/tools/search.py +563 -0
  429. alysis_code/tools/shell.py +135 -0
  430. alysis_code/tools/symbols.py +1350 -0
  431. alysis_code/tools/test_discovery.py +643 -0
  432. alysis_code/tools/web.py +482 -0
  433. alysis_code/tools/web_search.py +2012 -0
  434. alysis_code/tools/web_search_dashscope.py +557 -0
  435. alysis_code/tools/web_search_ddgs.py +221 -0
  436. alysis_code/tools/web_search_provider_adapters.py +1429 -0
  437. alysis_code/tools/web_search_tavily.py +194 -0
  438. alysis_code/updates.py +933 -0
  439. alysis_code/usage_tracker.py +1990 -0
  440. alysis_code/verification_command_analysis.py +1004 -0
  441. alysis_code/verification_contract.py +574 -0
  442. alysis_code/verification_failure_summary.py +273 -0
  443. alysis_code/verification_repair.py +385 -0
  444. alysis_code/verify_gate.py +3129 -0
  445. alysis_code/web_research.py +1872 -0
  446. alysis_code/web_search_adapters.py +66 -0
  447. alysis_code/web_search_policy.py +27 -0
  448. alysis_code/workspace_binding.py +389 -0
  449. alysis_code/workspace_binding_ui.py +408 -0
  450. alysis_code/workspace_context.py +273 -0
  451. alysis_code/workspace_isolation.py +138 -0
  452. alysis_code/workspace_provisioning.py +455 -0
  453. alysis_code-0.13.0.dist-info/METADATA +507 -0
  454. alysis_code-0.13.0.dist-info/RECORD +458 -0
  455. alysis_code-0.13.0.dist-info/WHEEL +4 -0
  456. alysis_code-0.13.0.dist-info/entry_points.txt +3 -0
  457. alysis_code-0.13.0.dist-info/licenses/LICENSE +176 -0
  458. alysis_code-0.13.0.dist-info/licenses/NOTICE +4 -0
@@ -0,0 +1,512 @@
1
+ from __future__ import annotations
2
+
3
+ import re
4
+ import shlex
5
+ from dataclasses import dataclass
6
+ from pathlib import Path
7
+
8
+ from ..config import (
9
+ strip_verify_runner_prefix,
10
+ )
11
+ from ..verification_command_analysis import (
12
+ VerificationCommandEvidentiaryCapability,
13
+ analyze_verification_command,
14
+ )
15
+ from .prompt_context import _normalized_verify_commands
16
+
17
+
18
+ def _normalize_shell_command_for_match(raw: str) -> str:
19
+ return " ".join(str(raw or "").casefold().split())
20
+
21
+
22
+ _VERIFICATION_ENV_ASSIGNMENT_RE = re.compile(r"^[a-z_][a-z0-9_]*=.*$")
23
+
24
+
25
+ _DISALLOWED_VERIFICATION_SHELL_TOKENS = {"||", "&&", ";", "|", "&"}
26
+
27
+
28
+ _NON_VERIFICATION_META_OPTIONS = {"--help", "-h", "--version"}
29
+
30
+
31
+ _PYTEST_NON_VERIFICATION_OPTIONS = {"--fixtures", "--markers", "--collect-only", "--co"}
32
+
33
+
34
+ _PYTEST_NON_EXECUTING_OPTIONS = {"--setup-plan"}
35
+
36
+
37
+ _CARGO_TEST_NON_EXECUTING_OPTIONS = {"--no-run", "--list"}
38
+
39
+
40
+ _GO_TEST_NON_EXECUTING_OPTIONS = {"-c", "-list"}
41
+
42
+
43
+ _RUFF_CHECK_NON_EXECUTING_OPTIONS = {"--fix", "--fix-only"}
44
+
45
+
46
+ _MYPY_NON_EXECUTING_OPTIONS = {"--install-types"}
47
+
48
+
49
+ _PYTEST_REPORTER_OPTIONS = {"-q", "--quiet", "--verbose"}
50
+
51
+
52
+ @dataclass(frozen=True)
53
+ class VerificationCommandShape:
54
+ family: str
55
+ args: tuple[str, ...]
56
+ options: tuple[str, ...]
57
+ positionals: tuple[str, ...]
58
+
59
+
60
+ def _command_options_include(options: tuple[str, ...], flag: str) -> bool:
61
+ return any(option == flag or option.startswith(f"{flag}=") for option in options)
62
+
63
+
64
+ def _verification_shape_is_real_execution_mode(shape: VerificationCommandShape) -> bool:
65
+ if shape.family == "pytest":
66
+ return not any(
67
+ _command_options_include(shape.options, flag) for flag in _PYTEST_NON_EXECUTING_OPTIONS
68
+ )
69
+ if shape.family == "cargo:test":
70
+ return not any(
71
+ _command_options_include(shape.options, flag)
72
+ for flag in _CARGO_TEST_NON_EXECUTING_OPTIONS
73
+ )
74
+ if shape.family == "go:test":
75
+ if any(
76
+ _command_options_include(shape.options, flag) for flag in _GO_TEST_NON_EXECUTING_OPTIONS
77
+ ):
78
+ return False
79
+ for idx, arg in enumerate(shape.args):
80
+ if arg == "-run":
81
+ if idx + 1 >= len(shape.args):
82
+ return False
83
+ if shape.args[idx + 1] == "^$":
84
+ return False
85
+ elif arg.startswith("-run=") and arg.partition("=")[2] == "^$":
86
+ return False
87
+ return True
88
+ if shape.family == "ruff:check":
89
+ return not any(
90
+ _command_options_include(shape.options, flag)
91
+ for flag in _RUFF_CHECK_NON_EXECUTING_OPTIONS
92
+ )
93
+ if shape.family == "mypy":
94
+ return not any(
95
+ _command_options_include(shape.options, flag) for flag in _MYPY_NON_EXECUTING_OPTIONS
96
+ )
97
+ return True
98
+
99
+
100
+ def _looks_like_env_assignment_token(part: str) -> bool:
101
+ return bool(_VERIFICATION_ENV_ASSIGNMENT_RE.match(part))
102
+
103
+
104
+ def _strip_verification_env_prefix(parts: list[str]) -> list[str] | None:
105
+ if not parts:
106
+ return None
107
+ out = list(parts)
108
+ if out[0] == "env":
109
+ out = out[1:]
110
+ if not out or out[0].startswith("-"):
111
+ return None
112
+ while out and _looks_like_env_assignment_token(out[0]):
113
+ out = out[1:]
114
+ return out or None
115
+
116
+
117
+ def _strip_verification_runner_prefix(parts: list[str]) -> list[str] | None:
118
+ return strip_verify_runner_prefix(parts)
119
+
120
+
121
+ def _normalize_and_unwrap_verification_command(raw: str) -> str | None:
122
+ normalized = _normalize_shell_command_for_match(raw)
123
+ if not normalized:
124
+ return None
125
+
126
+ while True:
127
+ wrapped = _unwrap_shell_wrapper_command(normalized)
128
+ if not wrapped or wrapped == normalized:
129
+ break
130
+ normalized = wrapped
131
+ return normalized
132
+
133
+
134
+ def _has_disallowed_shell_control_flow(raw: str) -> bool:
135
+ analysis = analyze_verification_command(raw, trusted=True)
136
+ return analysis.shell_control_flow in {"unsafe", "pipeline"} or analysis.rejection_reason in {
137
+ "disallowed_shell_control_flow",
138
+ "unsafe_pipeline",
139
+ }
140
+
141
+
142
+ def _top_level_shell_chain_segments(raw: str) -> tuple[list[str], tuple[str, ...]] | None:
143
+ command = str(raw or "")
144
+ segments: list[str] = []
145
+ separators: list[str] = []
146
+ start = 0
147
+ quote: str | None = None
148
+ escaped = False
149
+ index = 0
150
+ while index < len(command):
151
+ char = command[index]
152
+ if escaped:
153
+ escaped = False
154
+ index += 1
155
+ continue
156
+ if char == "\\" and quote != "'":
157
+ escaped = True
158
+ index += 1
159
+ continue
160
+ if quote is not None:
161
+ if char == quote:
162
+ quote = None
163
+ index += 1
164
+ continue
165
+ if char in {"'", '"'}:
166
+ quote = char
167
+ index += 1
168
+ continue
169
+ if command.startswith("&&", index) or command.startswith("||", index):
170
+ segments.append(command[start:index].strip())
171
+ separators.append(command[index : index + 2])
172
+ index += 2
173
+ start = index
174
+ continue
175
+ if char in {";", "|", "&"}:
176
+ segments.append(command[start:index].strip())
177
+ separators.append(char)
178
+ index += 1
179
+ start = index
180
+ continue
181
+ index += 1
182
+ if quote is not None:
183
+ return None
184
+ if not separators:
185
+ return None
186
+ segments.append(command[start:].strip())
187
+ return segments, tuple(separators)
188
+
189
+
190
+ def _expand_simple_verify_command_chain(
191
+ raw: str,
192
+ *,
193
+ workspace_root: Path | None = None,
194
+ ) -> list[str]:
195
+ split = _top_level_shell_chain_segments(raw)
196
+ if split is None:
197
+ return [raw]
198
+ segments, separators = split
199
+ if any(separator not in {"&&", ";"} for separator in separators):
200
+ return [raw]
201
+ if any(not segment for segment in segments):
202
+ return [raw]
203
+
204
+ expanded: list[str] = []
205
+ for segment in segments:
206
+ analysis = analyze_verification_command(segment, workspace_root=workspace_root)
207
+ if (
208
+ analysis.rejection_reason
209
+ or analysis.shell_control_flow != "none"
210
+ or analysis.evidentiary_capability != VerificationCommandEvidentiaryCapability.ASSERTIVE
211
+ ):
212
+ return [raw]
213
+ expanded.append(segment)
214
+ return expanded
215
+
216
+
217
+ def _canonicalize_verification_command_for_match(raw: str) -> str | None:
218
+ analysis = analyze_verification_command(raw, trusted=True)
219
+ if analysis.rejection_reason:
220
+ return None
221
+ return analysis.canonical_command
222
+
223
+
224
+ def _split_verification_shape_args(args: list[str]) -> tuple[tuple[str, ...], tuple[str, ...]]:
225
+ options: list[str] = []
226
+ positionals: list[str] = []
227
+ for arg in args:
228
+ if arg == "--":
229
+ continue
230
+ if arg.startswith("-") and arg != "-":
231
+ options.append(arg)
232
+ continue
233
+ positionals.append(arg)
234
+ return tuple(options), tuple(positionals)
235
+
236
+
237
+ def _parse_verification_command_shape(raw: str) -> VerificationCommandShape | None:
238
+ canonical = _canonicalize_verification_command_for_match(raw)
239
+ if not canonical:
240
+ return None
241
+ try:
242
+ parts = shlex.split(canonical, posix=True)
243
+ except ValueError:
244
+ return None
245
+ if not parts:
246
+ return None
247
+
248
+ head = parts[0]
249
+ tail = parts[1:]
250
+ family: str
251
+ args: list[str]
252
+
253
+ if head in {"pytest", "py.test"}:
254
+ family = "pytest"
255
+ args = tail
256
+ elif head == "unittest":
257
+ family = "unittest"
258
+ args = tail
259
+ elif head == "mypy":
260
+ family = "mypy"
261
+ args = tail
262
+ elif head == "go" and tail and tail[0] == "test":
263
+ family = "go:test"
264
+ args = tail[1:]
265
+ elif head == "cargo" and tail and tail[0] in {"test", "check"}:
266
+ family = f"cargo:{tail[0]}"
267
+ args = tail[1:]
268
+ elif head in {"npm", "pnpm", "yarn"} and tail and tail[0] == "test":
269
+ family = f"{head}:test"
270
+ args = tail[1:]
271
+ elif head in {"make", "just"} and tail and tail[0] in {"test", "check", "verify"}:
272
+ family = f"{head}:{tail[0]}"
273
+ args = tail[1:]
274
+ elif head == "ruff" and tail and tail[0] == "check":
275
+ family = "ruff:check"
276
+ args = tail[1:]
277
+ else:
278
+ return None
279
+
280
+ options, positionals = _split_verification_shape_args(args)
281
+ if _NON_VERIFICATION_META_OPTIONS & set(options):
282
+ return None
283
+ if family == "pytest" and _PYTEST_NON_VERIFICATION_OPTIONS & set(options):
284
+ return None
285
+ shape = VerificationCommandShape(
286
+ family=family,
287
+ args=tuple(args),
288
+ options=options,
289
+ positionals=positionals,
290
+ )
291
+ if not _verification_shape_is_real_execution_mode(shape):
292
+ return None
293
+ return shape
294
+
295
+
296
+ def _verification_command_shapes_match(
297
+ *,
298
+ observed: VerificationCommandShape,
299
+ expected: VerificationCommandShape,
300
+ ) -> bool:
301
+ if observed.family != expected.family:
302
+ return False
303
+ observed_options = set(observed.options)
304
+ expected_options = set(expected.options)
305
+ if observed.family == "pytest":
306
+ observed_options = {
307
+ option for option in observed_options if not _pytest_option_is_reporter_variant(option)
308
+ }
309
+ expected_options = {
310
+ option for option in expected_options if not _pytest_option_is_reporter_variant(option)
311
+ }
312
+ return expected_options.issubset(observed_options)
313
+
314
+
315
+ def _pytest_option_is_reporter_variant(option: str) -> bool:
316
+ return option in _PYTEST_REPORTER_OPTIONS or bool(re.fullmatch(r"-v+", option))
317
+
318
+
319
+ def _effective_verification_command_matches(
320
+ *,
321
+ normalized_cmd: str,
322
+ known_verification_commands: list[str],
323
+ ) -> bool:
324
+ observed_canonical = _canonicalize_verification_command_for_match(normalized_cmd)
325
+ if observed_canonical:
326
+ for configured in known_verification_commands:
327
+ expected_canonical = _canonicalize_verification_command_for_match(configured)
328
+ if expected_canonical and observed_canonical == expected_canonical:
329
+ return True
330
+
331
+ observed = _parse_verification_command_shape(normalized_cmd)
332
+ if observed is None:
333
+ return False
334
+ return any(
335
+ _verification_command_shapes_match(observed=observed, expected=expected)
336
+ for expected in (
337
+ _parse_verification_command_shape(configured)
338
+ for configured in known_verification_commands
339
+ )
340
+ if expected is not None
341
+ )
342
+
343
+
344
+ def _verify_run_commands_match_effective_contract(
345
+ *,
346
+ requested_commands: list[str],
347
+ effective_verification_commands: list[str],
348
+ ) -> list[str]:
349
+ known = _normalized_verify_commands(effective_verification_commands)
350
+ if not known:
351
+ return []
352
+ incompatible: list[str] = []
353
+ for command in requested_commands:
354
+ normalized_command = _normalize_shell_command_for_match(command)
355
+ if any(
356
+ normalized_command == _normalize_shell_command_for_match(configured)
357
+ for configured in known
358
+ ):
359
+ continue
360
+ if not _effective_verification_command_matches(
361
+ normalized_cmd=normalized_command,
362
+ known_verification_commands=known,
363
+ ):
364
+ incompatible.append(command)
365
+ return incompatible
366
+
367
+
368
+ def _matching_effective_verification_commands(
369
+ *,
370
+ observed_command: str,
371
+ effective_verification_commands: list[str] | None,
372
+ ) -> set[str]:
373
+ known = _normalized_verify_commands(effective_verification_commands or [])
374
+ if not known:
375
+ return set()
376
+ normalized_observed = _normalize_shell_command_for_match(observed_command)
377
+ exact_matches = {
378
+ configured
379
+ for configured in known
380
+ if normalized_observed == _normalize_shell_command_for_match(configured)
381
+ }
382
+ if exact_matches:
383
+ return exact_matches
384
+ observed_canonical = _canonicalize_verification_command_for_match(normalized_observed)
385
+ if observed_canonical:
386
+ exact_matches: set[str] = set()
387
+ for configured in known:
388
+ configured_canonical = _canonicalize_verification_command_for_match(configured)
389
+ if configured_canonical and configured_canonical == observed_canonical:
390
+ exact_matches.add(configured)
391
+ if exact_matches:
392
+ return exact_matches
393
+
394
+ observed = _parse_verification_command_shape(normalized_observed)
395
+ if observed is None:
396
+ return set()
397
+ matches: set[str] = set()
398
+ for configured in known:
399
+ expected = _parse_verification_command_shape(configured)
400
+ if expected is None:
401
+ continue
402
+ if _verification_command_shapes_match(observed=observed, expected=expected):
403
+ matches.add(configured)
404
+ return matches
405
+
406
+
407
+ def _unwrap_shell_wrapper_command(normalized_cmd: str) -> str | None:
408
+ if not normalized_cmd:
409
+ return None
410
+ try:
411
+ parts = shlex.split(normalized_cmd, posix=True)
412
+ except ValueError:
413
+ return None
414
+ if not parts:
415
+ return None
416
+
417
+ head = parts[0]
418
+ if head in {"bash", "sh", "zsh"}:
419
+ if len(parts) == 3 and parts[1] == "-lc":
420
+ return _normalize_shell_command_for_match(parts[2])
421
+ return None
422
+ if head == "fish":
423
+ if len(parts) == 3 and parts[1] == "-c":
424
+ return _normalize_shell_command_for_match(parts[2])
425
+ return None
426
+ if head == "cmd":
427
+ if len(parts) == 3 and parts[1] == "/c":
428
+ return _normalize_shell_command_for_match(parts[2])
429
+ return None
430
+ if head in {"powershell", "pwsh"}:
431
+ if len(parts) == 3 and parts[1] == "-command":
432
+ return _normalize_shell_command_for_match(parts[2])
433
+ return None
434
+ return None
435
+
436
+
437
+ def _looks_like_verification_entrypoint(parts: list[str]) -> bool:
438
+ if not parts:
439
+ return False
440
+ head = Path(parts[0]).name
441
+ head_lower = head.lower()
442
+ if head_lower in {
443
+ "pytest",
444
+ "py.test",
445
+ "tox",
446
+ "nox",
447
+ "vitest",
448
+ "jest",
449
+ "mypy",
450
+ "flake8",
451
+ "pylint",
452
+ "ruff",
453
+ "mix",
454
+ "sbt",
455
+ "swift",
456
+ "composer",
457
+ }:
458
+ return True
459
+ if len(parts) >= 2 and head_lower in {
460
+ "make",
461
+ "just",
462
+ "npm",
463
+ "pnpm",
464
+ "yarn",
465
+ "cargo",
466
+ "go",
467
+ "mvn",
468
+ "mvnw",
469
+ "gradle",
470
+ "gradlew",
471
+ "dotnet",
472
+ }:
473
+ return parts[1] in {"test", "check", "verify"}
474
+ if len(parts) >= 2 and head_lower in {"python", "python3"} and parts[1] == "-m":
475
+ return len(parts) >= 3 and parts[2] in {"pytest", "unittest"}
476
+ if len(parts) >= 2 and head_lower == "ruby":
477
+ return any(part.endswith("_test.rb") for part in parts[1:])
478
+ if len(parts) >= 2 and head_lower in {"sh", "bash"}:
479
+ return any("test" in Path(part).name for part in parts[1:])
480
+ return False
481
+
482
+
483
+ def _marker_fallback_is_verification_attempt(normalized_cmd: str) -> bool:
484
+ analysis = analyze_verification_command(normalized_cmd, trusted=True)
485
+ if analysis.rejection_reason:
486
+ return False
487
+ if analysis.command_family is not None:
488
+ return True
489
+ canonical = analysis.canonical_command
490
+ if not canonical:
491
+ return False
492
+ try:
493
+ parts = shlex.split(canonical, posix=True)
494
+ except ValueError:
495
+ return False
496
+ return _looks_like_verification_entrypoint(parts)
497
+
498
+
499
+ def _shell_command_is_verification_attempt(
500
+ cmd: str,
501
+ *,
502
+ known_verification_commands: list[str] | None,
503
+ ) -> bool:
504
+ from .verification_evidence import classify_verification_evidence
505
+
506
+ evidence = classify_verification_evidence(
507
+ cmd,
508
+ known_verification_commands=known_verification_commands,
509
+ exit_code=0,
510
+ real_execution=True,
511
+ )
512
+ return bool(evidence.allowed_to_satisfy_contract)