multi-forge 1.1.3__tar.gz → 1.1.4__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (541) hide show
  1. {multi_forge-1.1.3 → multi_forge-1.1.4}/.gitignore +4 -0
  2. {multi_forge-1.1.3 → multi_forge-1.1.4}/PKG-INFO +4 -2
  3. {multi_forge-1.1.3 → multi_forge-1.1.4}/pyproject.toml +10 -6
  4. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/backend/adapters/litellm.py +14 -10
  5. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/cli/hooks/direct_commands.py +4 -6
  6. multi_forge-1.1.4/src/forge/cli/session_derived_preflight.py +41 -0
  7. multi_forge-1.1.4/src/forge/cli/session_effort_hint.py +78 -0
  8. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/cli/session_fork.py +13 -4
  9. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/cli/session_launch_args.py +5 -1
  10. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/cli/session_lifecycle.py +20 -19
  11. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/cli/session_model.py +54 -2
  12. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/cli/session_resume_modes.py +3 -2
  13. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/cli/status_line.py +3 -1
  14. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/cli/statusline/context.py +28 -5
  15. multi_forge-1.1.4/src/forge/cli/statusline/effort.py +37 -0
  16. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/cli/statusline/formatting.py +34 -77
  17. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/cli/statusline/names.py +1 -2
  18. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/cli/statusline/palette.py +1 -7
  19. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/cli/statusline/registry.py +30 -48
  20. multi_forge-1.1.4/src/forge/cli/statusline/routing.py +50 -0
  21. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/cli/statusline/sources.py +10 -1
  22. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/config/defaults/templates/openrouter-deepseek.yaml +3 -0
  23. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/config/defaults/templates/openrouter-kimi.yaml +4 -2
  24. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/config/defaults/templates/openrouter-minimax.yaml +3 -1
  25. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/data/model_catalog.yaml +72 -0
  26. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/data/model_routes.yaml +126 -0
  27. multi_forge-1.1.4/src/forge/core/effort_observation.py +31 -0
  28. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/invoker/codex.py +8 -2
  29. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/invoker/codex_fork.py +3 -2
  30. multi_forge-1.1.4/src/forge/core/llm/clients/effort.py +19 -0
  31. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/llm/clients/litellm.py +41 -17
  32. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/llm/clients/openai_compat.py +2 -3
  33. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/llm/clients/openrouter.py +12 -1
  34. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/llm/protocols.py +6 -0
  35. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/ops/claude_session.py +55 -0
  36. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/ops/codex_interactive.py +47 -1
  37. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/ops/session.py +11 -0
  38. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/ops/session_fork_preflight.py +2 -0
  39. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/ops/session_model.py +60 -10
  40. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/reactive/env.py +19 -1
  41. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/reactive/reviewer_runtime.py +6 -1
  42. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/reactive/reviewer_settings.py +15 -15
  43. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/reactive/session_runner.py +24 -15
  44. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/reactive/supervisor_auth.py +8 -6
  45. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/run_id.py +30 -1
  46. multi_forge-1.1.4/src/forge/core/worker_controls.py +74 -0
  47. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/policy/semantic/supervisor.py +2 -0
  48. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/policy/team/handlers.py +1 -0
  49. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/proxy/client_adapter.py +5 -0
  50. multi_forge-1.1.4/src/forge/proxy/effort_observation.py +60 -0
  51. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/proxy/passthrough.py +5 -0
  52. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/proxy/passthrough_ingress.py +76 -2
  53. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/proxy/reasoning.py +38 -24
  54. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/proxy/runtime_truth.py +90 -12
  55. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/proxy/server.py +24 -5
  56. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/review/engine.py +5 -2
  57. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/review/models.py +3 -0
  58. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/session/claude/invoke.py +2 -0
  59. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/session/codex_invoke.py +60 -5
  60. multi_forge-1.1.4/src/forge/session/derived_overrides.py +160 -0
  61. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/session/exceptions.py +10 -0
  62. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/session/launch_confirmation.py +8 -3
  63. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/session/manager.py +19 -18
  64. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/session/memory_writer.py +2 -0
  65. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/session/overrides.py +28 -4
  66. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/session/rewind.py +3 -1
  67. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/session/shadow_curation.py +2 -0
  68. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/session/transfer.py +64 -22
  69. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/sidecar/container.py +17 -3
  70. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/skills/qa/resources/checklist/4-proxy.md +3 -0
  71. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/skills/qa/resources/checklist.md +2 -2
  72. {multi_forge-1.1.3 → multi_forge-1.1.4}/LICENSE +0 -0
  73. {multi_forge-1.1.3 → multi_forge-1.1.4}/NOTICE +0 -0
  74. {multi_forge-1.1.3 → multi_forge-1.1.4}/README.md +0 -0
  75. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/agents/.gitkeep +0 -0
  76. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/commands/.gitkeep +0 -0
  77. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/__init__.py +0 -0
  78. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/backend/__init__.py +0 -0
  79. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/backend/adapters/__init__.py +0 -0
  80. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/backend/creation.py +0 -0
  81. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/backend/registry.py +0 -0
  82. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/backend/remote/__init__.py +0 -0
  83. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/backend/remote/base.py +0 -0
  84. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/backend/remote/openrouter.py +0 -0
  85. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/backend/sources.py +0 -0
  86. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/cli/__init__.py +0 -0
  87. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/cli/activity.py +0 -0
  88. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/cli/auth.py +0 -0
  89. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/cli/backend.py +0 -0
  90. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/cli/claude.py +0 -0
  91. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/cli/codex.py +0 -0
  92. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/cli/config_cmd.py +0 -0
  93. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/cli/consumer_lane_freeze.py +0 -0
  94. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/cli/editor.py +0 -0
  95. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/cli/extensions.py +0 -0
  96. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/cli/gc.py +0 -0
  97. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/cli/guards.py +0 -0
  98. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/cli/hooks/__init__.py +0 -0
  99. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/cli/hooks/_group.py +0 -0
  100. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/cli/hooks/_helpers.py +0 -0
  101. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/cli/hooks/authority.py +0 -0
  102. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/cli/hooks/codex_patch.py +0 -0
  103. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/cli/hooks/codex_policy.py +0 -0
  104. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/cli/hooks/codex_policy_feedback.py +0 -0
  105. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/cli/hooks/codex_stop.py +0 -0
  106. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/cli/hooks/codex_transfer.py +0 -0
  107. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/cli/hooks/commands.py +0 -0
  108. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/cli/hooks/policy.py +0 -0
  109. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/cli/hooks/protocols.py +0 -0
  110. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/cli/hooks/read_hygiene.py +0 -0
  111. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/cli/hooks/verification.py +0 -0
  112. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/cli/info.py +0 -0
  113. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/cli/logs.py +0 -0
  114. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/cli/main.py +0 -0
  115. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/cli/memory.py +0 -0
  116. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/cli/memory_report.py +0 -0
  117. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/cli/memory_writer.py +0 -0
  118. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/cli/model.py +0 -0
  119. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/cli/output.py +0 -0
  120. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/cli/policy.py +0 -0
  121. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/cli/proxy.py +0 -0
  122. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/cli/proxy_audit.py +0 -0
  123. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/cli/proxy_costs.py +0 -0
  124. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/cli/runtime.py +0 -0
  125. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/cli/search.py +0 -0
  126. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/cli/session.py +0 -0
  127. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/cli/session_adopt.py +0 -0
  128. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/cli/session_authority.py +0 -0
  129. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/cli/session_authority_options.py +0 -0
  130. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/cli/session_codex.py +0 -0
  131. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/cli/session_delete.py +0 -0
  132. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/cli/session_lane.py +0 -0
  133. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/cli/session_manage.py +0 -0
  134. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/cli/session_memory.py +0 -0
  135. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/cli/session_repair.py +0 -0
  136. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/cli/session_rewind.py +0 -0
  137. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/cli/session_route_recovery.py +0 -0
  138. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/cli/session_routing.py +0 -0
  139. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/cli/session_supervisor_options.py +0 -0
  140. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/cli/statusline/__init__.py +0 -0
  141. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/cli/statusline/rendering.py +0 -0
  142. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/cli/statusline/throttle.py +0 -0
  143. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/cli/statusline/types.py +0 -0
  144. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/cli/supervisor_auth.py +0 -0
  145. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/cli/telemetry.py +0 -0
  146. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/cli/trace.py +0 -0
  147. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/cli/transfer.py +0 -0
  148. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/cli/workflow.py +0 -0
  149. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/cli/workspace.py +0 -0
  150. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/config/__init__.py +0 -0
  151. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/config/dataclass_utils.py +0 -0
  152. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/config/defaults/__init__.py +0 -0
  153. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/config/defaults/backends/__init__.py +0 -0
  154. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/config/defaults/backends/litellm.yaml +0 -0
  155. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/config/defaults/templates/__init__.py +0 -0
  156. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/config/defaults/templates/anthropic-passthrough.yaml +0 -0
  157. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/config/defaults/templates/codex-responses-local.yaml +0 -0
  158. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/config/defaults/templates/litellm-anthropic-local.yaml +0 -0
  159. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/config/defaults/templates/litellm-anthropic.yaml +0 -0
  160. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/config/defaults/templates/litellm-gemini-flash-local.yaml +0 -0
  161. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/config/defaults/templates/litellm-gemini-local.yaml +0 -0
  162. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/config/defaults/templates/litellm-gemini-test.yaml +0 -0
  163. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/config/defaults/templates/litellm-gemini.yaml +0 -0
  164. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/config/defaults/templates/litellm-openai-codex-local.yaml +0 -0
  165. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/config/defaults/templates/litellm-openai-local.yaml +0 -0
  166. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/config/defaults/templates/litellm-openai.yaml +0 -0
  167. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/config/defaults/templates/openrouter-anthropic.yaml +0 -0
  168. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/config/defaults/templates/openrouter-gemini-flash.yaml +0 -0
  169. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/config/defaults/templates/openrouter-gemini.yaml +0 -0
  170. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/config/defaults/templates/openrouter-glm.yaml +0 -0
  171. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/config/defaults/templates/openrouter-openai-codex.yaml +0 -0
  172. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/config/defaults/templates/openrouter-openai.yaml +0 -0
  173. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/config/defaults/templates/openrouter-qwen.yaml +0 -0
  174. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/config/loader.py +0 -0
  175. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/config/schema.py +0 -0
  176. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/__init__.py +0 -0
  177. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/auth/__init__.py +0 -0
  178. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/auth/capabilities.py +0 -0
  179. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/auth/credentials_file.py +0 -0
  180. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/auth/protocols.py +0 -0
  181. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/auth/secrets.py +0 -0
  182. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/auth/template_secrets.py +0 -0
  183. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/backend_dependency.py +0 -0
  184. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/credential_registry.py +0 -0
  185. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/data/__init__.py +0 -0
  186. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/data/model_practices.yaml +0 -0
  187. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/data/system_prompt_addendums/__init__.py +0 -0
  188. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/data/system_prompt_addendums/gemini.md +0 -0
  189. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/data/system_prompt_addendums/openai.md +0 -0
  190. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/effort.py +0 -0
  191. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/identifiers.py +0 -0
  192. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/invoker/__init__.py +0 -0
  193. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/invoker/_lifecycle.py +0 -0
  194. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/invoker/claude.py +0 -0
  195. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/invoker/codex_stream.py +0 -0
  196. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/invoker/types.py +0 -0
  197. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/judgments/__init__.py +0 -0
  198. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/judgments/openrouter.py +0 -0
  199. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/judgments/types.py +0 -0
  200. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/judgments/usage.py +0 -0
  201. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/lanes.py +0 -0
  202. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/llm/__init__.py +0 -0
  203. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/llm/clients/__init__.py +0 -0
  204. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/llm/clients/base.py +0 -0
  205. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/llm/credentials.py +0 -0
  206. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/llm/detection.py +0 -0
  207. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/llm/errors.py +0 -0
  208. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/llm/openrouter_policy.py +0 -0
  209. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/llm/types.py +0 -0
  210. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/logging.py +0 -0
  211. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/metric_formatting.py +0 -0
  212. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/models/__init__.py +0 -0
  213. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/models/catalog.py +0 -0
  214. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/models/direct_model.py +0 -0
  215. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/models/model_practices.py +0 -0
  216. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/models/model_reference.py +0 -0
  217. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/models/model_routes.py +0 -0
  218. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/models/types.py +0 -0
  219. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/naming.py +0 -0
  220. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/native_review_types.py +0 -0
  221. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/ops/__init__.py +0 -0
  222. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/ops/backend_reconcile.py +0 -0
  223. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/ops/codex_adopt.py +0 -0
  224. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/ops/codex_bridge.py +0 -0
  225. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/ops/codex_enrollment.py +0 -0
  226. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/ops/codex_session.py +0 -0
  227. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/ops/codex_thread_index.py +0 -0
  228. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/ops/context.py +0 -0
  229. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/ops/gc.py +0 -0
  230. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/ops/policy.py +0 -0
  231. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/ops/provider_trace.py +0 -0
  232. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/ops/proxy.py +0 -0
  233. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/ops/resolution.py +0 -0
  234. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/ops/session_active.py +0 -0
  235. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/ops/session_adopt.py +0 -0
  236. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/ops/session_authority.py +0 -0
  237. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/ops/session_authority_launch.py +0 -0
  238. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/ops/session_context.py +0 -0
  239. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/ops/session_fork_execution.py +0 -0
  240. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/ops/session_model_routing.py +0 -0
  241. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/ops/session_repair.py +0 -0
  242. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/ops/session_routing.py +0 -0
  243. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/ops/transfer.py +0 -0
  244. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/ops/usage_summary.py +0 -0
  245. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/ops/workspace.py +0 -0
  246. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/paths.py +0 -0
  247. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/process.py +0 -0
  248. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/provider_types.py +0 -0
  249. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/reactive/__init__.py +0 -0
  250. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/reactive/codex_reviewer_home.py +0 -0
  251. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/reactive/cost_tracking.py +0 -0
  252. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/reactive/headless_json.py +0 -0
  253. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/reactive/llm_call.py +0 -0
  254. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/reactive/proxy.py +0 -0
  255. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/reactive/routing.py +0 -0
  256. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/reactive/structured_output.py +0 -0
  257. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/reactive/tagger.py +0 -0
  258. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/reactive/throttle.py +0 -0
  259. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/reactive/watchdog.py +0 -0
  260. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/runtime/__init__.py +0 -0
  261. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/runtime/codex_feedback.py +0 -0
  262. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/runtime/codex_preflight.py +0 -0
  263. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/runtime/codex_preflight_cache.py +0 -0
  264. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/runtime/codex_review_source.py +0 -0
  265. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/runtime/codex_rollouts.py +0 -0
  266. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/runtime/codex_turn_enrollment.py +0 -0
  267. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/runtime/launch_args.py +0 -0
  268. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/runtime/registry.py +0 -0
  269. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/runtime_vocab.py +0 -0
  270. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/state/__init__.py +0 -0
  271. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/state/exceptions.py +0 -0
  272. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/state/io.py +0 -0
  273. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/state/lock.py +0 -0
  274. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/state/retention.py +0 -0
  275. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/state/timestamps.py +0 -0
  276. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/state/versioned_store.py +0 -0
  277. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/telemetry/__init__.py +0 -0
  278. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/telemetry/caps.py +0 -0
  279. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/telemetry/downstream.py +0 -0
  280. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/telemetry/downstream_retention.py +0 -0
  281. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/telemetry/jsonl_io.py +0 -0
  282. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/telemetry/upstream.py +0 -0
  283. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/telemetry/vocabulary.py +0 -0
  284. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/tiers.py +0 -0
  285. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/transcript.py +0 -0
  286. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/typing_helpers.py +0 -0
  287. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/usage/__init__.py +0 -0
  288. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/usage/billing.py +0 -0
  289. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/usage/correlation.py +0 -0
  290. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/usage/emit.py +0 -0
  291. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/usage/ledger.py +0 -0
  292. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/usage/measurement.py +0 -0
  293. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/usage/vocabulary.py +0 -0
  294. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/wire_shapes.py +0 -0
  295. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/workqueue/__init__.py +0 -0
  296. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/workqueue/queue.py +0 -0
  297. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/core/workqueue/types.py +0 -0
  298. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/install/__init__.py +0 -0
  299. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/install/codex_hooks.py +0 -0
  300. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/install/doctor.py +0 -0
  301. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/install/exceptions.py +0 -0
  302. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/install/hook_dispatcher.py +0 -0
  303. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/install/hook_migration.py +0 -0
  304. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/install/hooks.py +0 -0
  305. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/install/installer.py +0 -0
  306. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/install/models.py +0 -0
  307. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/install/module_planning.py +0 -0
  308. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/install/ownership.py +0 -0
  309. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/install/path_policy.py +0 -0
  310. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/install/preset.py +0 -0
  311. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/install/project_compat.py +0 -0
  312. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/install/project_registry.py +0 -0
  313. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/install/runtime_removal.py +0 -0
  314. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/install/settings_merge.py +0 -0
  315. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/install/settings_rollback.py +0 -0
  316. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/install/skill_cache.py +0 -0
  317. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/install/skill_compiler.py +0 -0
  318. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/install/skill_planning.py +0 -0
  319. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/install/skill_validation.py +0 -0
  320. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/install/tracking.py +0 -0
  321. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/install/unmanaged.py +0 -0
  322. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/install/version.py +0 -0
  323. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/policy/__init__.py +0 -0
  324. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/policy/action_identity.py +0 -0
  325. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/policy/deterministic/__init__.py +0 -0
  326. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/policy/deterministic/base.py +0 -0
  327. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/policy/deterministic/coding_standards.py +0 -0
  328. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/policy/deterministic/registry.py +0 -0
  329. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/policy/deterministic/tdd.py +0 -0
  330. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/policy/diff.py +0 -0
  331. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/policy/engine.py +0 -0
  332. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/policy/protocols.py +0 -0
  333. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/policy/queries.py +0 -0
  334. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/policy/semantic/__init__.py +0 -0
  335. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/policy/semantic/attempts.py +0 -0
  336. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/policy/semantic/deadline.py +0 -0
  337. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/policy/semantic/identity.py +0 -0
  338. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/policy/semantic/native_codex.py +0 -0
  339. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/policy/semantic/plan_check.py +0 -0
  340. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/policy/semantic/plan_source.py +0 -0
  341. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/policy/semantic/shadow.py +0 -0
  342. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/policy/semantic/shadow_runner.py +0 -0
  343. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/policy/semantic/stop_review.py +0 -0
  344. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/policy/semantic/turn_evidence.py +0 -0
  345. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/policy/semantic/verdict.py +0 -0
  346. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/policy/store.py +0 -0
  347. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/policy/supervisor_lane_degrade.py +0 -0
  348. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/policy/team/__init__.py +0 -0
  349. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/policy/team/config.py +0 -0
  350. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/policy/team/prompts.py +0 -0
  351. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/policy/types.py +0 -0
  352. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/proxy/__init__.py +0 -0
  353. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/proxy/accounting_persistence.py +0 -0
  354. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/proxy/audit_logger.py +0 -0
  355. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/proxy/base_client.py +0 -0
  356. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/proxy/client_factory.py +0 -0
  357. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/proxy/converters.py +0 -0
  358. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/proxy/cost_logger.py +0 -0
  359. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/proxy/cost_tracker.py +0 -0
  360. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/proxy/data_models.py +0 -0
  361. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/proxy/error_hints.py +0 -0
  362. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/proxy/intercept.py +0 -0
  363. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/proxy/metrics.py +0 -0
  364. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/proxy/model_routes.py +0 -0
  365. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/proxy/ports.py +0 -0
  366. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/proxy/provider_trace_logger.py +0 -0
  367. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/proxy/proxies.py +0 -0
  368. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/proxy/proxy_identity.py +0 -0
  369. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/proxy/proxy_orchestrator.py +0 -0
  370. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/proxy/proxy_startup.py +0 -0
  371. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/proxy/request_id.py +0 -0
  372. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/proxy/response_headers.py +0 -0
  373. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/proxy/responses_ingress.py +0 -0
  374. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/proxy/responses_passthrough.py +0 -0
  375. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/proxy/sse_framing.py +0 -0
  376. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/proxy/stream_relay.py +0 -0
  377. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/proxy/utils.py +0 -0
  378. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/review/__init__.py +0 -0
  379. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/review/adversarial.py +0 -0
  380. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/review/backend_readiness.py +0 -0
  381. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/review/consensus.py +0 -0
  382. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/review/resources/__init__.py +0 -0
  383. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/review/resources/code_consensus_evaluation.md +0 -0
  384. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/review/resources/code_debate_evaluation.md +0 -0
  385. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/review/resources/codereview-performance.md +0 -0
  386. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/review/resources/codereview-quick.md +0 -0
  387. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/review/resources/codereview-security.md +0 -0
  388. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/review/resources/codereview.md +0 -0
  389. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/review/resources/consensus_evaluation.md +0 -0
  390. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/review/resources/debate_evaluation.md +0 -0
  391. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/review/resources/docreview-quick.md +0 -0
  392. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/review/resources/docreview.md +0 -0
  393. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/review/resources/thinkdeep.md +0 -0
  394. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/review/routing.py +0 -0
  395. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/review/synthesis.py +0 -0
  396. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/review/worker_preparation.py +0 -0
  397. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/runtime_config.py +0 -0
  398. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/search/__init__.py +0 -0
  399. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/search/bm25_store.py +0 -0
  400. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/search/cleanup.py +0 -0
  401. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/search/content_store.py +0 -0
  402. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/search/engine.py +0 -0
  403. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/search/exceptions.py +0 -0
  404. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/search/extractor.py +0 -0
  405. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/search/index_state.py +0 -0
  406. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/search/store.py +0 -0
  407. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/search/tokenizer.py +0 -0
  408. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/session/__init__.py +0 -0
  409. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/session/active.py +0 -0
  410. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/session/addendum.py +0 -0
  411. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/session/artifacts.py +0 -0
  412. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/session/authority.py +0 -0
  413. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/session/claude/__init__.py +0 -0
  414. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/session/claude/cleanup.py +0 -0
  415. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/session/claude/paths.py +0 -0
  416. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/session/claude/relocate.py +0 -0
  417. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/session/cleanup.py +0 -0
  418. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/session/cleanup_content.py +0 -0
  419. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/session/cleanup_dependencies.py +0 -0
  420. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/session/cleanup_git.py +0 -0
  421. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/session/cleanup_state.py +0 -0
  422. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/session/codex_handoff.py +0 -0
  423. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/session/config.py +0 -0
  424. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/session/consumer_lanes.py +0 -0
  425. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/session/context_limit.py +0 -0
  426. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/session/context_rendering.py +0 -0
  427. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/session/deletion.py +0 -0
  428. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/session/effective.py +0 -0
  429. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/session/events.py +0 -0
  430. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/session/git.py +0 -0
  431. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/session/hooks/__init__.py +0 -0
  432. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/session/hooks/models.py +0 -0
  433. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/session/hooks/producers.py +0 -0
  434. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/session/hooks/session_start.py +0 -0
  435. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/session/identity.py +0 -0
  436. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/session/index.py +0 -0
  437. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/session/launch.py +0 -0
  438. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/session/launchability.py +0 -0
  439. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/session/memory_inheritance.py +0 -0
  440. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/session/model_pin.py +0 -0
  441. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/session/models.py +0 -0
  442. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/session/passport.py +0 -0
  443. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/session/plan_resolution.py +0 -0
  444. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/session/prev_sessions.py +0 -0
  445. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/session/project_memory.py +0 -0
  446. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/session/purge_native.py +0 -0
  447. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/session/routing.py +0 -0
  448. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/session/store.py +0 -0
  449. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/session/validation.py +0 -0
  450. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/session/verification_config.py +0 -0
  451. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/session/workers.py +0 -0
  452. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/session/workspace.py +0 -0
  453. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/session/worktree/__init__.py +0 -0
  454. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/session/worktree/cleanup.py +0 -0
  455. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/session/worktree/config_copy.py +0 -0
  456. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/session/worktree/create.py +0 -0
  457. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/sidecar/__init__.py +0 -0
  458. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/forge/sidecar/docker.py +0 -0
  459. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/skills/analyze/content.md +0 -0
  460. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/skills/analyze/forge-skill.yaml +0 -0
  461. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/skills/challenge/content.md +0 -0
  462. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/skills/challenge/forge-skill.yaml +0 -0
  463. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/skills/consensus/content.md +0 -0
  464. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/skills/consensus/forge-skill.yaml +0 -0
  465. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/skills/consensus/resources/synthesis.md +0 -0
  466. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/skills/debate/content.md +0 -0
  467. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/skills/debate/forge-skill.yaml +0 -0
  468. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/skills/panel/content.md +0 -0
  469. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/skills/panel/forge-skill.yaml +0 -0
  470. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/skills/panel/resources/synthesis.md +0 -0
  471. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/skills/qa/SKILL.md +0 -0
  472. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/skills/qa/resources/checklist/0-enable.md +0 -0
  473. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/skills/qa/resources/checklist/1-preflight.md +0 -0
  474. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/skills/qa/resources/checklist/10-resume.md +0 -0
  475. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/skills/qa/resources/checklist/11-config.md +0 -0
  476. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/skills/qa/resources/checklist/12-search.md +0 -0
  477. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/skills/qa/resources/checklist/13-policy.md +0 -0
  478. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/skills/qa/resources/checklist/14-workflow.md +0 -0
  479. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/skills/qa/resources/checklist/15-skills.md +0 -0
  480. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/skills/qa/resources/checklist/16-memory.md +0 -0
  481. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/skills/qa/resources/checklist/17-info.md +0 -0
  482. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/skills/qa/resources/checklist/18-disable.md +0 -0
  483. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/skills/qa/resources/checklist/19-uninstall.md +0 -0
  484. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/skills/qa/resources/checklist/2-extension.md +0 -0
  485. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/skills/qa/resources/checklist/20-cleanup.md +0 -0
  486. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/skills/qa/resources/checklist/3-authentication.md +0 -0
  487. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/skills/qa/resources/checklist/5-session.md +0 -0
  488. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/skills/qa/resources/checklist/6-hook.md +0 -0
  489. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/skills/qa/resources/checklist/7-costs.md +0 -0
  490. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/skills/qa/resources/checklist/8-status-line.md +0 -0
  491. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/skills/qa/resources/checklist/9-direct-commands.md +0 -0
  492. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/skills/qa/resources/coverage-map.md +0 -0
  493. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/skills/qa/resources/execution-budget.json +0 -0
  494. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/skills/qa/resources/report-template.md +0 -0
  495. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/skills/qa/resources/runtime-matrix.json +0 -0
  496. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/skills/qa/scripts/qa-artifact.py +0 -0
  497. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/skills/qa/scripts/qa-run-metrics.py +0 -0
  498. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/skills/qa/scripts/qa-selection.py +0 -0
  499. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/skills/qa/scripts/start-container.sh +0 -0
  500. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/skills/qa/scripts/walkthrough-state.py +0 -0
  501. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/skills/review/content.md +0 -0
  502. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/skills/review/forge-skill.yaml +0 -0
  503. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/skills/review/references/claude-4.6.md +0 -0
  504. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/skills/review/references/claude-4.8.md +0 -0
  505. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/skills/review/references/gemini-3.1.md +0 -0
  506. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/skills/review/references/gpt-5.5.md +0 -0
  507. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/skills/review/references/skills-writing-guide.md +0 -0
  508. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/skills/review/resources/code-anthropic.md +0 -0
  509. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/skills/review/resources/code-gemini.md +0 -0
  510. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/skills/review/resources/code-openai.md +0 -0
  511. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/skills/review/resources/code.md +0 -0
  512. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/skills/review-docs/content.md +0 -0
  513. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/skills/review-docs/forge-skill.yaml +0 -0
  514. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/skills/review-docs/resources/docs-anthropic.md +0 -0
  515. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/skills/review-docs/resources/docs-gemini.md +0 -0
  516. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/skills/review-docs/resources/docs-openai.md +0 -0
  517. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/skills/review-docs/resources/docs.md +0 -0
  518. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/skills/smoke-test/content.md +0 -0
  519. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/skills/smoke-test/forge-skill.yaml +0 -0
  520. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/skills/smoke-test/scripts/smoke-test.sh +0 -0
  521. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/skills/understand/content.md +0 -0
  522. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/skills/understand/forge-skill.yaml +0 -0
  523. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/skills/understand/resources/code-anthropic.md +0 -0
  524. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/skills/understand/resources/code-gemini.md +0 -0
  525. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/skills/understand/resources/code-openai.md +0 -0
  526. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/skills/understand/resources/code.md +0 -0
  527. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/skills/understand/resources/docs-anthropic.md +0 -0
  528. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/skills/understand/resources/docs-gemini.md +0 -0
  529. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/skills/understand/resources/docs-openai.md +0 -0
  530. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/skills/understand/resources/docs.md +0 -0
  531. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/skills/walkthrough/SKILL.md +0 -0
  532. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/skills/walkthrough/resources/checklist.md +0 -0
  533. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/skills/walkthrough/resources/journey-map.md +0 -0
  534. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/skills/walkthrough/scripts/claude-wrapper.sh +0 -0
  535. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/skills/walkthrough/scripts/cleanup-owned.sh +0 -0
  536. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/skills/walkthrough/scripts/package-identity.py +0 -0
  537. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/skills/walkthrough/scripts/protected-paths.py +0 -0
  538. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/skills/walkthrough/scripts/run-in-repo.sh +0 -0
  539. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/skills/walkthrough/scripts/setup-test-repo.sh +0 -0
  540. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/skills/walkthrough/scripts/walkthrough-report.py +0 -0
  541. {multi_forge-1.1.3 → multi_forge-1.1.4}/src/skills/walkthrough/scripts/walkthrough-state.py +0 -0
@@ -8,10 +8,14 @@
8
8
 
9
9
  # Virtual environment
10
10
  .venv/
11
+ .venv-python-*/
11
12
  venv/
12
13
  ENV/
13
14
  env/
14
15
 
16
+ # Local Python matrix reports; retained acceptance summaries live with their card.
17
+ /.test-evidence/
18
+
15
19
  # Environment variables
16
20
  .env
17
21
  .envrc
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: multi-forge
3
- Version: 1.1.3
3
+ Version: 1.1.4
4
4
  Summary: Multi-runtime agent toolkit: proxy routing, cost control, session management, policy enforcement, and workflow orchestration
5
5
  Project-URL: Homepage, https://github.com/hapa1i/multi-forge
6
6
  Project-URL: Repository, https://github.com/hapa1i/multi-forge
@@ -30,11 +30,13 @@ Requires-Dist: click>=8.3.1
30
30
  Requires-Dist: coolname<6,>=5.0.0
31
31
  Requires-Dist: cryptography>=50.0.0
32
32
  Requires-Dist: dacite>=1.8.0
33
+ Requires-Dist: dnspython>=2.9.0
33
34
  Requires-Dist: expression<6,>=5.6.0
34
35
  Requires-Dist: fastapi-sso<1,>=0.19.0
35
36
  Requires-Dist: fastapi<0.137,>=0.136.3
37
+ Requires-Dist: filelock>=4.2.1
36
38
  Requires-Dist: httpx>=0.25.0
37
- Requires-Dist: litellm==1.102.0
39
+ Requires-Dist: litellm==1.102.2
38
40
  Requires-Dist: multidict<7,>=6.9.1
39
41
  Requires-Dist: oauthlib<5,>=4.0.0
40
42
  Requires-Dist: openai>=1.0.0
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "multi-forge"
3
- version = "1.1.3"
3
+ version = "1.1.4"
4
4
  description = "Multi-runtime agent toolkit: proxy routing, cost control, session management, policy enforcement, and workflow orchestration"
5
5
  readme = "README.md"
6
6
  license = "Apache-2.0"
@@ -42,7 +42,7 @@ dependencies = [
42
42
  # Proxy dependencies (previously optional, now core). Forge owns the
43
43
  # default-Uvicorn LiteLLM startup set because the upstream `proxy` extra
44
44
  # caps cryptography below Forge's patched floor. This set is start/health
45
- # validated through LiteLLM 1.102.0; run scripts/test-wheel-runtime.sh before
45
+ # validated through LiteLLM 1.102.2; run scripts/test-wheel-runtime.sh before
46
46
  # raising the ceiling. Alternate servers, databases, and cloud integrations
47
47
  # remain outside Forge's runtime path.
48
48
  "aiohttp>=3.14.4,<4",
@@ -53,11 +53,15 @@ dependencies = [
53
53
  # Exclude the compromised CA trust roots from clean installations too.
54
54
  "certifi>=2026.10.19",
55
55
  "cryptography>=50.0.0",
56
+ # Keep email-validator's transitive DNS security floor in wheel metadata despite no direct Forge import.
57
+ "dnspython>=2.9.0",
56
58
  # LiteLLM 1.95 imports outbound-credential tagged unions at startup.
57
59
  "expression>=5.6.0,<6",
58
60
  # Keep FastAPI's lock-proven route-tree behavior; upgrade it separately.
59
61
  "fastapi>=0.136.3,<0.137",
60
62
  "fastapi-sso>=0.19.0,<1",
63
+ # Keep huggingface-hub's transitive file-lock security floor in wheel metadata despite no direct Forge import.
64
+ "filelock>=4.2.1",
61
65
  # Runtime security floors belong in wheel metadata, not only uv constraints.
62
66
  "multidict>=6.9.1,<7",
63
67
  "oauthlib>=4.0.0,<5",
@@ -75,7 +79,7 @@ dependencies = [
75
79
  "watchfiles>=0.20",
76
80
  "websockets>=15.0.1,<16",
77
81
  # Packaged Gemini 3.8 Flash metadata and the verified proxy runtime.
78
- "litellm==1.102.0",
82
+ "litellm==1.102.2",
79
83
  ]
80
84
 
81
85
  [project.scripts]
@@ -165,8 +169,7 @@ build-constraint-dependencies = [
165
169
  "trove-classifiers==2026.9.21.13",
166
170
  ]
167
171
  constraint-dependencies = [
168
- "filelock>=3.20.3",
169
- "virtualenv>=21.14.12",
172
+ "virtualenv>=21.14.13",
170
173
  "mcp>=1.28.1",
171
174
  "Pygments>=2.20.0",
172
175
  "pyasn1>=0.6.4",
@@ -185,8 +188,9 @@ dev = [
185
188
  "pytest-cov>=4.1.0",
186
189
  "pytest-asyncio>=0.23.0",
187
190
  "pytest-mock>=3.15.1",
191
+ "pytest-xdist>=3.8.0",
188
192
  "ruff>=0.15.0",
189
- "black>=26.5.0",
193
+ "black>=26.10.1",
190
194
  "mypy>=1.13.0",
191
195
  "pyright>=1.1.0",
192
196
  "pytest-rerunfailures>=14.0",
@@ -24,6 +24,8 @@ from forge.backend.registry import ManagedBackendProcess
24
24
  from forge.core.paths import get_forge_home
25
25
  from forge.core.state import now_iso
26
26
 
27
+ STARTUP_HEALTH_TIMEOUT_S = 30.0
28
+
27
29
 
28
30
  class LiteLLMAdapter(BackendAdapter):
29
31
  """Adapter for managing LiteLLM backend processes.
@@ -38,7 +40,7 @@ class LiteLLMAdapter(BackendAdapter):
38
40
  which checks BackendDependency.required_env_vars before starting.
39
41
  """
40
42
 
41
- def _wait_for_health(self, port: int, timeout: float = 15.0) -> bool:
43
+ def _wait_for_health(self, port: int, timeout: float = STARTUP_HEALTH_TIMEOUT_S) -> bool:
42
44
  """Wait for backend to become healthy.
43
45
 
44
46
  Uses /health/liveliness (not /health) because the full health endpoint
@@ -53,18 +55,20 @@ class LiteLLMAdapter(BackendAdapter):
53
55
  Returns:
54
56
  True if healthy within timeout, False otherwise
55
57
  """
56
- start_time = time.time()
58
+ deadline = time.monotonic() + timeout
57
59
  url = f"http://localhost:{port}/health/liveliness"
58
60
 
59
- while time.time() - start_time < timeout:
60
- try:
61
- with httpx.Client(timeout=httpx.Timeout(2.0)) as client:
62
- response = client.get(url)
61
+ with httpx.Client(timeout=httpx.Timeout(2.0)) as client:
62
+ while (remaining := deadline - time.monotonic()) > 0:
63
+ try:
64
+ response = client.get(url, timeout=min(2.0, remaining))
63
65
  if response.status_code == 200:
64
66
  return True
65
- except (httpx.RequestError, httpx.TimeoutException):
66
- pass
67
- time.sleep(0.5)
67
+ except httpx.RequestError:
68
+ pass
69
+ remaining = deadline - time.monotonic()
70
+ if remaining > 0:
71
+ time.sleep(min(0.5, remaining))
68
72
 
69
73
  return False
70
74
 
@@ -107,7 +111,7 @@ class LiteLLMAdapter(BackendAdapter):
107
111
  start_new_session=True, # Detach from parent
108
112
  )
109
113
 
110
- if not self._wait_for_health(port, timeout=10):
114
+ if not self._wait_for_health(port, timeout=STARTUP_HEALTH_TIMEOUT_S):
111
115
  try:
112
116
  os.killpg(proc.pid, signal.SIGKILL)
113
117
  except ProcessLookupError:
@@ -213,10 +213,7 @@ def _handle_session_model(argv: list[str]) -> None:
213
213
 
214
214
  from forge.core.ops.context import ExecutionContext
215
215
  from forge.core.ops.session import ForgeOpError
216
- from forge.core.ops.session_model import (
217
- MODEL_REPORT_LIMITATIONS,
218
- get_session_model_report,
219
- )
216
+ from forge.core.ops.session_model import get_session_model_report
220
217
  from forge.session.exceptions import ForgeSessionError
221
218
 
222
219
  try:
@@ -232,10 +229,11 @@ def _handle_session_model(argv: list[str]) -> None:
232
229
  return
233
230
  from forge.cli.session_model import session_model_summary_rows
234
231
 
232
+ payload = report.to_dict()
235
233
  lines = ["Session model:"]
236
- lines.extend(f" {field}: {value}" for field, value in session_model_summary_rows(report.to_dict()))
234
+ lines.extend(f" {field}: {value}" for field, value in session_model_summary_rows(payload))
237
235
  lines.append("Limitations:")
238
- lines.extend(f" - {limitation}" for limitation in MODEL_REPORT_LIMITATIONS)
236
+ lines.extend(f" - {limitation}" for limitation in payload["limitations"])
239
237
  click.echo(json.dumps({"decision": "block", "reason": "\n".join(lines)}))
240
238
 
241
239
 
@@ -0,0 +1,41 @@
1
+ """Early structural admission and recovery for CLI session derivation."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import sys
6
+
7
+ from forge.cli.output import err_console, handle_session_error, print_error, print_tip
8
+ from forge.session.derived_overrides import validate_derived_session_overrides
9
+ from forge.session.exceptions import (
10
+ ForgeSessionError,
11
+ ManifestCorruptedError,
12
+ ManifestValidationError,
13
+ )
14
+ from forge.session.models import SessionState
15
+
16
+
17
+ def handle_derived_session_error(error: ForgeSessionError) -> None:
18
+ """Keep strict manifest failures on the explicit repair/restoration path."""
19
+ if isinstance(error, (ManifestCorruptedError, ManifestValidationError)):
20
+ # The legacy version diagnostic embeds deletion advice in its reason.
21
+ reason = error.reason.removesuffix(" Delete this session and recreate it.")
22
+ print_error(f"Invalid session manifest at '{error.path}': {reason}")
23
+ print_tip(
24
+ "Repair the named manifest explicitly or restore a known-good copy before retrying.", console=err_console
25
+ )
26
+ sys.exit(1)
27
+ handle_session_error(error)
28
+
29
+
30
+ def preflight_resume(state: SessionState, *, fresh: bool, force_resumable: bool) -> None:
31
+ """Validate only resume paths that will derive a child, before realizing routing."""
32
+ from forge.cli.session import _peek_active_session_entry
33
+
34
+ if not fresh and (
35
+ not force_resumable or _peek_active_session_entry(state.name, forge_root=state.forge_root) is None
36
+ ):
37
+ return
38
+ try:
39
+ validate_derived_session_overrides(state)
40
+ except ForgeSessionError as error:
41
+ handle_derived_session_error(error)
@@ -0,0 +1,78 @@
1
+ """Launch-only guidance for translated managed Claude sessions."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import shlex
6
+ from pathlib import Path
7
+
8
+ import click
9
+
10
+ from forge.cli.output import err_console, print_tip
11
+ from forge.core.ops.claude_session import ClaudeLaunchReady
12
+ from forge.core.wire_shapes import ANTHROPIC_PASSTHROUGH
13
+ from forge.session.artifacts import resolve_forge_root
14
+
15
+
16
+ def print_derived_effort_hint(event: ClaudeLaunchReady) -> None:
17
+ """Explain derived effort using the existing launch-time proxy snapshot."""
18
+ ctx = click.get_current_context(silent=True)
19
+ runtime = event.runtime
20
+ if (
21
+ ctx is None
22
+ or ctx.parent is None
23
+ or ctx.parent.command.name != "session"
24
+ or ctx.command.name not in {"start", "resume", "fork", "incognito"}
25
+ or ctx.params.get("effort") is not None
26
+ or ctx.params.get("no_launch")
27
+ or ctx.params.get("json_output")
28
+ or ctx.params.get("json")
29
+ or not (event.template or event.proxy_id)
30
+ or runtime is None
31
+ or not runtime.is_proxy
32
+ or runtime.wire_shape is None
33
+ or runtime.wire_shape == ANTHROPIC_PASSTHROUGH
34
+ ):
35
+ return
36
+ if event.template is not None and runtime.template != event.template:
37
+ return
38
+ if event.proxy_id is not None and runtime.proxy_id != event.proxy_id:
39
+ return
40
+ proxy_runtime = runtime.raw.get("runtime")
41
+ defaults = proxy_runtime.get("llm_defaults_by_tier") if isinstance(proxy_runtime, dict) else None
42
+ defaults = defaults if isinstance(defaults, dict) else {}
43
+ projected_tier = event.model_route.selected_tier if event.model_route else None
44
+ minimum = "the selected tier minimum"
45
+ floors = []
46
+ for tier in ("haiku", "sonnet", "opus"):
47
+ if projected_tier is not None and projected_tier != tier:
48
+ continue
49
+ tier_defaults = defaults.get(tier)
50
+ floor = tier_defaults.get("reasoning_effort") if isinstance(tier_defaults, dict) else None
51
+ if isinstance(floor, str) and floor in {"none", "minimal", "low", "medium", "high", "xhigh", "max"}:
52
+ floors.append(f"{tier}: {floor}")
53
+ if floors:
54
+ label = "configured minimums: " if projected_tier is None else ""
55
+ minimum += f" ({label}{', '.join(floors)})"
56
+
57
+ # Creation has already committed, including unnamed forks and fresh resumes.
58
+ # Durable route intent makes a short resume command sufficient on the next launch.
59
+ args = ["forge", "session", "resume", event.session]
60
+ guidance = "After exiting, opt in to client effort with:"
61
+ if event.incognito:
62
+ args = ["forge", "session", "incognito", "--proxy", event.proxy_id or event.template or ""]
63
+ if event.model_route is not None:
64
+ args.extend(["--model", event.model_route.requested_model, "--model-tier", event.model_route.selected_tier])
65
+ elif event.direct_model is not None:
66
+ args.extend(["--model", event.direct_model])
67
+ guidance = "This incognito session is deleted on exit. Opt in on a new incognito launch with:"
68
+ args.extend(["--effort", "<level>"])
69
+ command = shlex.join(args)
70
+ if not event.incognito and event.forge_root and Path(event.forge_root).resolve() != resolve_forge_root(Path.cwd()):
71
+ command = f"cd {shlex.quote(event.forge_root)} && {command}"
72
+ print_tip(
73
+ f"Effort is derived from thinking and {minimum}.",
74
+ guidance,
75
+ commands=[command],
76
+ blank_before=False,
77
+ console=err_console,
78
+ )
@@ -17,12 +17,13 @@ from forge.cli.session import ( # noqa: E402
17
17
  _print_routing_summary,
18
18
  _resolve_routing_from_cli,
19
19
  console,
20
- handle_session_error,
21
20
  )
22
21
  from forge.cli.session_authority_options import (
23
22
  authority_creation_options,
24
23
  parse_creation_authority,
25
24
  )
25
+ from forge.cli.session_derived_preflight import handle_derived_session_error
26
+ from forge.cli.session_effort_hint import ClaudeLaunchReady, print_derived_effort_hint
26
27
  from forge.cli.session_launch_args import (
27
28
  RuntimePassthroughCommand,
28
29
  checked_launch_args,
@@ -116,6 +117,9 @@ class _ClaudeForkCliPresenter:
116
117
  def before_launch(self, forge_root: Path) -> None:
117
118
  _warn_before_claude_launch(forge_root)
118
119
 
120
+ def on_launch_ready(self, event: ClaudeLaunchReady) -> None:
121
+ print_derived_effort_hint(event)
122
+
119
123
  def on_routing_payload(self, payload: dict[str, Any]) -> None:
120
124
  _render_model_route_payload(payload)
121
125
 
@@ -327,7 +331,12 @@ def _render_fork_execution_error(error: ForkExecutionError) -> None:
327
331
  default=None,
328
332
  help=_MODEL_TIER_HELP,
329
333
  )
330
- @click.option("--incognito", "-i", is_flag=True, help="Attempt guarded purge of the fork after runtime exit")
334
+ @click.option(
335
+ "--incognito",
336
+ "-i",
337
+ is_flag=True,
338
+ help="Attempt guarded purge of the fork after runtime exit",
339
+ )
331
340
  @click.option("--worktree", "-w", is_flag=True, help="Create git worktree for fork isolation")
332
341
  @click.option("--branch", "-b", help="Override branch name (implies --worktree)")
333
342
  @click.option("--no-launch", is_flag=True, help="Create fork without launching Claude")
@@ -556,7 +565,7 @@ def fork(
556
565
  print_error(f"session '{parent}' not found")
557
566
  sys.exit(1)
558
567
  except ForgeSessionError as e:
559
- handle_session_error(e)
568
+ handle_derived_session_error(e)
560
569
  return
561
570
 
562
571
  for notice in preflight.notices:
@@ -741,7 +750,7 @@ def fork(
741
750
  print_error(f"session '{parent}' not found")
742
751
  sys.exit(1)
743
752
  except ForgeSessionError as e:
744
- handle_session_error(e)
753
+ handle_derived_session_error(e)
745
754
  return
746
755
 
747
756
  for event in execution.events:
@@ -72,7 +72,11 @@ def checked_launch_args(
72
72
  print_error("--effort and runtime arguments after '--' apply only to a launch; drop them or --no-launch")
73
73
  sys.exit(1)
74
74
  try:
75
- return validate_launch_args(args, runtime=runtime, advisory=authority is not None and authority.is_advisory)
75
+ return validate_launch_args(
76
+ args,
77
+ runtime=runtime,
78
+ advisory=authority is not None and authority.is_advisory,
79
+ )
76
80
  except LaunchArgsError as e:
77
81
  print_error(str(e))
78
82
  sys.exit(1)
@@ -36,6 +36,10 @@ from forge.cli.session import ( # noqa: E402
36
36
  logger,
37
37
  )
38
38
  from forge.cli.session import session as _session_untyped # noqa: E402
39
+ from forge.cli.session_derived_preflight import (
40
+ handle_derived_session_error,
41
+ preflight_resume,
42
+ )
39
43
  from forge.core.models.direct_model import (
40
44
  resolve_direct_model_pin,
41
45
  token_estimate_multiplier_for_direct_model,
@@ -106,6 +110,7 @@ from forge.session.transfer import ResumeStrategy, parse_lineage_depth
106
110
 
107
111
  session = cast(click.Group, _session_untyped) # type: ignore[has-type] # circular re-export
108
112
 
113
+ from forge.cli import session_effort_hint as effort_hint # noqa: E402
109
114
  from forge.cli.session_authority_options import ( # noqa: E402
110
115
  authority_creation_options,
111
116
  parse_creation_authority,
@@ -618,6 +623,9 @@ class _ClaudeStartCliPresenter:
618
623
  def before_launch(self, forge_root: Path) -> None:
619
624
  _warn_before_claude_launch(forge_root)
620
625
 
626
+ def on_launch_ready(self, event: effort_hint.ClaudeLaunchReady) -> None:
627
+ effort_hint.print_derived_effort_hint(event)
628
+
621
629
  def on_routing_payload(self, payload: dict[str, Any]) -> None:
622
630
  _render_model_route_payload(payload)
623
631
 
@@ -690,6 +698,9 @@ class _ClaudeResumeCliPresenter:
690
698
  def before_launch(self, forge_root: Path) -> None:
691
699
  _warn_before_claude_launch(forge_root)
692
700
 
701
+ def on_launch_ready(self, event: effort_hint.ClaudeLaunchReady) -> None:
702
+ effort_hint.print_derived_effort_hint(event)
703
+
693
704
  def on_routing_payload(self, payload: dict[str, Any]) -> None:
694
705
  _render_model_route_payload(payload)
695
706
 
@@ -1542,10 +1553,10 @@ def resume(
1542
1553
  )
1543
1554
  sys.exit(1)
1544
1555
  except ForgeSessionError as e:
1545
- handle_session_error(e)
1556
+ (handle_derived_session_error if fresh or force else handle_session_error)(e)
1546
1557
  return
1547
1558
  except ForgeSessionError as e:
1548
- handle_session_error(e)
1559
+ (handle_derived_session_error if fresh or force else handle_session_error)(e)
1549
1560
  return
1550
1561
 
1551
1562
  from forge.session.launchability import require_session_worktree
@@ -1597,8 +1608,10 @@ def resume(
1597
1608
 
1598
1609
  enforce_target_project_compatibility(Path(target_forge_root))
1599
1610
 
1600
- # Validate against the session this resume will launch: a --fresh child takes
1601
- # explicit authority or inherits advisory authority; other modes keep the manifest's.
1611
+ preflight_resume(manifest, fresh=fresh, force_resumable=force and _has_confirmed_claude_session(manifest))
1612
+
1613
+ # A --fresh child can select authority explicitly. Active --force relaunch
1614
+ # applies advisory-only inheritance when it creates the child below.
1602
1615
  launched_authority = manifest.intent.authority
1603
1616
  if fresh:
1604
1617
  launched_authority = authority if authority_explicit else inherited_authority(manifest.intent.authority)
@@ -1855,7 +1868,7 @@ def resume(
1855
1868
  render_model_route=render_model_route,
1856
1869
  launch_args=launch_args,
1857
1870
  )
1858
- elif _is_resumable_session(manifest):
1871
+ else:
1859
1872
  active_entry = _get_active_session_entry(name, forge_root=manifest.forge_root)
1860
1873
  if active_entry is not None and not force:
1861
1874
  print_error(
@@ -1901,18 +1914,6 @@ def resume(
1901
1914
  render_model_route=render_model_route,
1902
1915
  launch_args=launch_args,
1903
1916
  )
1904
- else:
1905
- _launch_as_child(
1906
- manager=manager,
1907
- parent_name=name,
1908
- parent=manifest,
1909
- routing=routing,
1910
- direct=direct,
1911
- direct_model_override=normalized_direct_model,
1912
- model_route_selection=model_route_selection,
1913
- render_model_route=render_model_route,
1914
- launch_args=launch_args,
1915
- )
1916
1917
 
1917
1918
 
1918
1919
  def _launch_in_place(
@@ -2079,7 +2080,7 @@ def _launch_as_child(
2079
2080
  try:
2080
2081
  parent, child = manager.relaunch_session(parent_name, forge_root=parent.forge_root)
2081
2082
  except ForgeSessionError as e:
2082
- handle_session_error(e)
2083
+ handle_derived_session_error(e)
2083
2084
  return
2084
2085
 
2085
2086
  context_limit = (
@@ -2233,7 +2234,7 @@ def _resume_fresh(
2233
2234
  authority_explicit=authority_explicit,
2234
2235
  )
2235
2236
  except ForgeSessionError as e:
2236
- handle_session_error(e)
2237
+ handle_derived_session_error(e)
2237
2238
  return
2238
2239
  except ValueError as e:
2239
2240
  print_error(str(e))
@@ -8,6 +8,7 @@ from typing import Any
8
8
 
9
9
  import click
10
10
  from rich.table import Table
11
+ from rich.text import Text
11
12
 
12
13
  from forge.cli.output import err_console, print_error
13
14
  from forge.cli.session import console
@@ -45,7 +46,7 @@ def show_cmd(session_name: str | None, as_json: bool) -> None:
45
46
  table.add_column("Field", style="bold")
46
47
  table.add_column("Value")
47
48
  for field, value in session_model_summary_rows(payload):
48
- table.add_row(field, value)
49
+ table.add_row(field, Text(value))
49
50
  console.print(table)
50
51
  console.print("\n[bold]Limitations[/bold]")
51
52
  for limitation in payload["limitations"]:
@@ -100,16 +101,67 @@ def session_model_summary_rows(payload: dict[str, Any]) -> list[tuple[str, str]]
100
101
  ("Runtime", payload["runtime"]),
101
102
  ("Active", "yes" if payload["active"] else "no"),
102
103
  ("Intent", payload["route_intent"]["kind"]),
103
- ("Committed route", commit["kind"] if commit and commit["kind"] else "unavailable"),
104
+ (
105
+ "Committed route",
106
+ commit["kind"] if commit and commit["kind"] else "unavailable",
107
+ ),
104
108
  ("Route evidence", commit["evidence_source"] if commit else "none"),
105
109
  ("History", payload["history_status"] or "no claim"),
106
110
  ("Live proxy", live["evidence_source"]),
107
111
  ("Default tier", live["default_tier"] or "-"),
108
112
  ("Launch marking entries", str(len(payload["marking"]["launch_entries"]))),
109
113
  ("Live marking entries", str(len(payload["marking"]["live_proxy_entries"]))),
114
+ *_effort_summary_rows(payload["effort"]),
110
115
  ]
111
116
 
112
117
 
118
+ def _effort_summary_rows(effort: dict[str, Any]) -> list[tuple[str, str]]:
119
+ if effort["status"] != "observed":
120
+ reason = str(effort["reason"] or "unavailable").replace("_", " ")
121
+ return [("Effort", f"unknown ({reason})")]
122
+
123
+ rows = [
124
+ ("Effort launch", effort["launch_id"]),
125
+ ("Effort backend", effort["backend_id"] or "unknown"),
126
+ ]
127
+ for tier in ("opus", "sonnet", "haiku"):
128
+ record = effort["observations"].get(tier)
129
+ if record is None:
130
+ continue
131
+ label = tier.capitalize()
132
+ opt_in = "yes" if record["opt_in"] else "no"
133
+ applicable = "yes" if record["client_applicable"] else "no"
134
+ used = "yes" if record["source"] == "client" else "no"
135
+ supported = ", ".join(record["supported"]) if record["supported"] is not None else "not catalogued"
136
+ applied = "dropped" if record["wire"] == "dropped" else record["applied"] or "unset"
137
+ rows.extend(
138
+ [
139
+ (f"{label} effort", applied),
140
+ (f"{label} requested", record["requested"] or "unset"),
141
+ (
142
+ f"{label} client effort",
143
+ f"opt-in: {opt_in}; applicable: {applicable}; used: {used}",
144
+ ),
145
+ (f"{label} thinking", record["thinking"] or "unset"),
146
+ (f"{label} derived", record["derived"] or "unset"),
147
+ (f"{label} minimum", record["floor"] or "unset"),
148
+ (f"{label} pre-clamp", record["pre_clamp"] or "unset"),
149
+ (f"{label} supported", supported),
150
+ (
151
+ f"{label} resolved",
152
+ f"{record['resolved'] or 'unset'} ({record['source']})",
153
+ ),
154
+ (f"{label} tier source", record["tier_source"]),
155
+ (f"{label} model", record["mapped_model"]),
156
+ (f"{label} wire", record["wire"] or "unset"),
157
+ (f"{label} observed", record["observed_at"]),
158
+ ]
159
+ )
160
+ if record["note"]:
161
+ rows.append((f"{label} note", record["note"]))
162
+ return rows
163
+
164
+
113
165
  def _model_slot_summary(snapshots: object) -> str:
114
166
  if not isinstance(snapshots, list):
115
167
  return "-"
@@ -6,6 +6,7 @@ import sys
6
6
  from pathlib import Path
7
7
 
8
8
  from forge.cli.output import console, handle_session_error, print_error_with_tip
9
+ from forge.cli.session_derived_preflight import handle_derived_session_error
9
10
  from forge.cli.session_routing import ResolvedRouting
10
11
  from forge.core.ops.claude_session import ClaudeResumeAction, ResumeLaunchPlan
11
12
  from forge.core.ops.session_model_routing import ResolvedModelRoute
@@ -67,7 +68,7 @@ def _resume_fresh_rewind(
67
68
  instance_sink=published_instances.append,
68
69
  )
69
70
  except ForgeSessionError as e:
70
- handle_session_error(e)
71
+ handle_derived_session_error(e)
71
72
  return
72
73
 
73
74
  instance_id = published_instances[0] if published_instances else None
@@ -218,7 +219,7 @@ def _resume_fresh_native(
218
219
  instance_sink=published_instances.append,
219
220
  )
220
221
  except ForgeSessionError as e:
221
- handle_session_error(e)
222
+ handle_derived_session_error(e)
222
223
  return
223
224
 
224
225
  instance_id = published_instances[0] if published_instances else None
@@ -79,7 +79,9 @@ def status_line() -> None:
79
79
  logger.debug("status-line: required sources=%s", sorted(source.value for source in plan.sources))
80
80
 
81
81
  if StatusSource.PROXY in plan.sources:
82
- is_proxy, runtime, is_proxy_authoritative = status_sources.detect_proxy()
82
+ is_proxy, runtime, is_proxy_authoritative = status_sources.detect_proxy(
83
+ include_effort=any(segment.name == "model" for segment in plan.segments)
84
+ )
83
85
  else:
84
86
  is_proxy, runtime, is_proxy_authoritative = False, None, False
85
87