forge-autonomy 2.7.37__tar.gz → 2.7.38__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 (337) hide show
  1. {forge_autonomy-2.7.37/forge_autonomy.egg-info → forge_autonomy-2.7.38}/PKG-INFO +1 -1
  2. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/installed_lifecycle.py +3 -0
  3. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38/forge_autonomy.egg-info}/PKG-INFO +1 -1
  4. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/product-version.json +1 -1
  5. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/tests/test_installed_forge_update.py +376 -4
  6. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/tests/test_installed_lifecycle.py +17 -0
  7. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/MANIFEST.in +0 -0
  8. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/README.md +0 -0
  9. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/__init__.py +0 -0
  10. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/__main__.py +0 -0
  11. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/_version.py +0 -0
  12. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/action_derivation_canary_closure.py +0 -0
  13. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/action_derivation_evidence.py +0 -0
  14. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/action_derivation_qualification.py +0 -0
  15. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/action_derivation_reattempt.py +0 -0
  16. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/ai_architect/__init__.py +0 -0
  17. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/ai_architect/provider_registry.py +0 -0
  18. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/api/installed-health-component-registry-1.0.json +0 -0
  19. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/api/operations-read-openapi-v1.json +0 -0
  20. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/api/operations-read-postman-v1.json +0 -0
  21. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/api/server-openapi-v1.json +0 -0
  22. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/api/server-postman-v1.json +0 -0
  23. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/architecture/__init__.py +0 -0
  24. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/architecture/advisor.py +0 -0
  25. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/architecture/presentation.py +0 -0
  26. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/architecture/workspace.py +0 -0
  27. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/autonomous_orchestrator.py +0 -0
  28. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/business/__init__.py +0 -0
  29. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/business/advisor.py +0 -0
  30. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/business/ingress.py +0 -0
  31. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/business/presentation.py +0 -0
  32. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/business/workspace.py +0 -0
  33. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/canary.py +0 -0
  34. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/capabilities/__init__.py +0 -0
  35. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/capabilities/delegation.py +0 -0
  36. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/completion/__init__.py +0 -0
  37. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/completion/assessor.py +0 -0
  38. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/completion/host_control_observer.py +0 -0
  39. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/completion/mission.py +0 -0
  40. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/completion/repository_observer.py +0 -0
  41. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/constitutional/__init__.py +0 -0
  42. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/constitutional/assessor.py +0 -0
  43. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/core/__init__.py +0 -0
  44. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/core/json_store.py +0 -0
  45. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/decision_evidence/__init__.py +0 -0
  46. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/decision_evidence/repository.py +0 -0
  47. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/dispatcher/__init__.py +0 -0
  48. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/dispatcher/dispatcher.py +0 -0
  49. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/ep_simulator.py +0 -0
  50. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/execution/__init__.py +0 -0
  51. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/execution/loop.py +0 -0
  52. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/execution/presentation.py +0 -0
  53. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/execution_host_configuration.py +0 -0
  54. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/foundation/__init__.py +0 -0
  55. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/foundation/loader.py +0 -0
  56. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/generation_two.py +0 -0
  57. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/generation_two_execution.py +0 -0
  58. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/governance/__init__.py +0 -0
  59. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/governance/execution_policy.py +0 -0
  60. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/governance/profiles.py +0 -0
  61. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/governance_authority.py +0 -0
  62. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/installed_health.py +0 -0
  63. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/intake.py +0 -0
  64. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/integration/__init__.py +0 -0
  65. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/integration/coordinator.py +0 -0
  66. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/integration/repository.py +0 -0
  67. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/knowledge/__init__.py +0 -0
  68. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/knowledge/consumer.py +0 -0
  69. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/knowledge/registry.py +0 -0
  70. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/lifecycle/__init__.py +0 -0
  71. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/lifecycle/store.py +0 -0
  72. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/mission_amendment.py +0 -0
  73. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/mission_cli.py +0 -0
  74. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/mission_scheduler.py +0 -0
  75. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/models/__init__.py +0 -0
  76. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/models/action.py +0 -0
  77. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/models/action_derivation.py +0 -0
  78. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/models/agent_policy.py +0 -0
  79. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/models/ai_architect_provider.py +0 -0
  80. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/models/ai_architect_session.py +0 -0
  81. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/models/ai_provider_registry.py +0 -0
  82. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/models/architecture_mission.py +0 -0
  83. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/models/architecture_reasoning.py +0 -0
  84. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/models/architecture_review.py +0 -0
  85. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/models/codex_runtime_prompt.py +0 -0
  86. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/models/constitutional_validation.py +0 -0
  87. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/models/criterion_assessment.py +0 -0
  88. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/models/criterion_observation.py +0 -0
  89. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/models/decision_evidence.py +0 -0
  90. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/models/execution_host.py +0 -0
  91. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/models/foundation.py +0 -0
  92. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/models/historical_intent.py +0 -0
  93. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/models/integration.py +0 -0
  94. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/models/intent.py +0 -0
  95. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/models/intent_authoring.py +0 -0
  96. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/models/mission.py +0 -0
  97. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/models/mission_candidate.py +0 -0
  98. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/models/mission_completion.py +0 -0
  99. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/models/mission_planner.py +0 -0
  100. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/models/mission_recommendation.py +0 -0
  101. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/models/phase_completion.py +0 -0
  102. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/models/planning.py +0 -0
  103. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/models/producer.py +0 -0
  104. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/models/prompt_artifact.py +0 -0
  105. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/models/proposal.py +0 -0
  106. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/models/runtime_prompt.py +0 -0
  107. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/models/solution_template.py +0 -0
  108. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/operations_read_api.py +0 -0
  109. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/operator_identity.py +0 -0
  110. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/planner/__init__.py +0 -0
  111. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/planner/action_derivation.py +0 -0
  112. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/planner/codex_cli_session.py +0 -0
  113. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/planner/durable_derivation.py +0 -0
  114. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/planner/engine.py +0 -0
  115. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/planner/openai_responses.py +0 -0
  116. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/planner/provider_adapter.py +0 -0
  117. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/planning/__init__.py +0 -0
  118. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/planning/loader.py +0 -0
  119. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/planning/registry.py +0 -0
  120. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/portfolio_intelligence.py +0 -0
  121. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/preserved_lifecycle.py +0 -0
  122. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/programme_authorization.py +0 -0
  123. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/prompts/__init__.py +0 -0
  124. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/prompts/codex_cli.py +0 -0
  125. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/prompts/generator.py +0 -0
  126. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/proposals/__init__.py +0 -0
  127. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/proposals/generator.py +0 -0
  128. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/provider_context.py +0 -0
  129. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/provider_security.py +0 -0
  130. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/qualification/__init__.py +0 -0
  131. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/qualification/bootstrap_sequence.py +0 -0
  132. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/qualification/criterion_completion.py +0 -0
  133. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/qualification/generation_one.py +0 -0
  134. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/qualification/installed_smoke.py +0 -0
  135. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/qualification/server_runtime.py +0 -0
  136. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/recommendations/__init__.py +0 -0
  137. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/recommendations/engine.py +0 -0
  138. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/repository_truth.py +0 -0
  139. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/review/__init__.py +0 -0
  140. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/review/engine.py +0 -0
  141. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/runtime/__init__.py +0 -0
  142. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/runtime/bootstrap.py +0 -0
  143. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/runtime/data_root.py +0 -0
  144. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/runtime/database.py +0 -0
  145. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/runtime/dynamic_mission.py +0 -0
  146. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/runtime/evidence.py +0 -0
  147. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/runtime/execution_context.py +0 -0
  148. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/runtime/health.py +0 -0
  149. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/runtime/mission_controller.py +0 -0
  150. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/runtime/operational_reset.py +0 -0
  151. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/runtime/runner.py +0 -0
  152. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/runtime/service.py +0 -0
  153. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/scheduler/__init__.py +0 -0
  154. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/scheduler/adapter.py +0 -0
  155. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/scheduler/ep_http_adapter.py +0 -0
  156. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/scheduler/ep_v12.py +0 -0
  157. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/scheduler/scheduler.py +0 -0
  158. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/schemas/capability-registry-1.0.schema.json +0 -0
  159. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/schemas/capability.schema.json +0 -0
  160. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/schemas/common.schema.json +0 -0
  161. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/schemas/decision-evidence-1.0.schema.json +0 -0
  162. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/schemas/engineering-goal-0.5.schema.json +0 -0
  163. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/schemas/engineering-increment-proposal-0.5.schema.json +0 -0
  164. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/schemas/engineering-mode.schema.json +0 -0
  165. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/schemas/engineering-plan-0.5.schema.json +0 -0
  166. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/schemas/engineering-platform-peer-configuration-1.0.schema.json +0 -0
  167. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/schemas/engineering-platform-peer-configuration-1.1.schema.json +0 -0
  168. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/schemas/engineering-prompt-artifact-0.7.schema.json +0 -0
  169. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/schemas/engineering-proposal-0.6.schema.json +0 -0
  170. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/schemas/evidence-reference-0.5.schema.json +0 -0
  171. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/schemas/foundation-document.schema.json +0 -0
  172. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/schemas/governance-profile.schema.json +0 -0
  173. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/schemas/knowledge-source-0.4.schema.json +0 -0
  174. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/schemas/knowledge-source.schema.json +0 -0
  175. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/schemas/mission-candidate-1.0.schema.json +0 -0
  176. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/schemas/mission-candidate-1.1.schema.json +0 -0
  177. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/schemas/phase-completion-1.0.schema.json +0 -0
  178. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/schemas/planning-document-0.5.schema.json +0 -0
  179. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/schemas/repository-catalog.schema.json +0 -0
  180. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/schemas/repository.schema.json +0 -0
  181. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/schemas/solution-template-1.0.schema.json +0 -0
  182. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/schemas/workspace.schema.json +0 -0
  183. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/secure_store.py +0 -0
  184. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/server_runtime.py +0 -0
  185. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/solutions/__init__.py +0 -0
  186. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/solutions/catalogue.py +0 -0
  187. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/solutions/generator.py +0 -0
  188. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/state/__init__.py +0 -0
  189. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/state/mission_state.py +0 -0
  190. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge/workspace/__init__.py +0 -0
  191. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge_autonomy.egg-info/SOURCES.txt +0 -0
  192. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge_autonomy.egg-info/dependency_links.txt +0 -0
  193. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge_autonomy.egg-info/entry_points.txt +0 -0
  194. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/forge_autonomy.egg-info/top_level.txt +0 -0
  195. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/pyproject.toml +0 -0
  196. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/schemas/capability-registry-1.0.schema.json +0 -0
  197. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/schemas/capability.schema.json +0 -0
  198. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/schemas/common.schema.json +0 -0
  199. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/schemas/decision-evidence-1.0.schema.json +0 -0
  200. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/schemas/engineering-goal-0.5.schema.json +0 -0
  201. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/schemas/engineering-increment-proposal-0.5.schema.json +0 -0
  202. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/schemas/engineering-mode.schema.json +0 -0
  203. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/schemas/engineering-plan-0.5.schema.json +0 -0
  204. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/schemas/engineering-prompt-artifact-0.7.schema.json +0 -0
  205. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/schemas/engineering-proposal-0.6.schema.json +0 -0
  206. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/schemas/evidence-reference-0.5.schema.json +0 -0
  207. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/schemas/foundation-document.schema.json +0 -0
  208. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/schemas/governance-profile.schema.json +0 -0
  209. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/schemas/knowledge-source-0.4.schema.json +0 -0
  210. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/schemas/knowledge-source.schema.json +0 -0
  211. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/schemas/mission-candidate-1.0.schema.json +0 -0
  212. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/schemas/mission-candidate-1.1.schema.json +0 -0
  213. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/schemas/phase-completion-1.0.schema.json +0 -0
  214. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/schemas/planning-document-0.5.schema.json +0 -0
  215. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/schemas/repository-catalog.schema.json +0 -0
  216. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/schemas/repository.schema.json +0 -0
  217. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/schemas/solution-template-1.0.schema.json +0 -0
  218. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/schemas/workspace.schema.json +0 -0
  219. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/setup.cfg +0 -0
  220. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/tests/test_action_derivation.py +0 -0
  221. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/tests/test_action_derivation_canary_closure.py +0 -0
  222. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/tests/test_action_derivation_evidence.py +0 -0
  223. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/tests/test_action_derivation_qualification.py +0 -0
  224. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/tests/test_adaptive_action_sizing_design.py +0 -0
  225. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/tests/test_agent_policy.py +0 -0
  226. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/tests/test_aggregate_health_roadmap.py +0 -0
  227. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/tests/test_ai_architect_provider.py +0 -0
  228. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/tests/test_ai_architect_session.py +0 -0
  229. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/tests/test_ai_development_projection.py +0 -0
  230. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/tests/test_ai_provider_registry.py +0 -0
  231. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/tests/test_architecture_reasoning.py +0 -0
  232. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/tests/test_architecture_review_engine.py +0 -0
  233. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/tests/test_architecture_workspace.py +0 -0
  234. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/tests/test_autonomous_orchestrator.py +0 -0
  235. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/tests/test_bootstrap_adapter.py +0 -0
  236. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/tests/test_bootstrap_mission_canary.py +0 -0
  237. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/tests/test_bootstrap_mission_runner.py +0 -0
  238. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/tests/test_bootstrap_mission_scheduler.py +0 -0
  239. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/tests/test_bootstrap_sequence_qualification.py +0 -0
  240. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/tests/test_business_governance_ingress.py +0 -0
  241. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/tests/test_business_workspace.py +0 -0
  242. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/tests/test_canonical_data_root.py +0 -0
  243. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/tests/test_capability_delegation.py +0 -0
  244. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/tests/test_codex_cli_runtime_prompt.py +0 -0
  245. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/tests/test_codex_cli_session.py +0 -0
  246. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/tests/test_constitutional_validation.py +0 -0
  247. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/tests/test_criterion_assessment_contract.py +0 -0
  248. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/tests/test_criterion_ep_http_boundary.py +0 -0
  249. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/tests/test_criterion_planning_context.py +0 -0
  250. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/tests/test_decision_evidence.py +0 -0
  251. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/tests/test_default_project_quality_policy.py +0 -0
  252. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/tests/test_distribution_identity.py +0 -0
  253. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/tests/test_durable_action_derivation.py +0 -0
  254. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/tests/test_dynamic_mission_capability.py +0 -0
  255. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/tests/test_engineering_action_architecture.py +0 -0
  256. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/tests/test_engineering_intent_authoring.py +0 -0
  257. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/tests/test_engineering_intent_lifecycle.py +0 -0
  258. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/tests/test_engineering_mission.py +0 -0
  259. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/tests/test_engineering_planning.py +0 -0
  260. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/tests/test_engineering_prompt_artifacts.py +0 -0
  261. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/tests/test_engineering_proposals.py +0 -0
  262. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/tests/test_ep_http_adapter.py +0 -0
  263. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/tests/test_ep_simulator.py +0 -0
  264. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/tests/test_ep_simulator_rolling_planning.py +0 -0
  265. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/tests/test_execution_context.py +0 -0
  266. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/tests/test_execution_host_configuration.py +0 -0
  267. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/tests/test_execution_host_contract.py +0 -0
  268. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/tests/test_execution_loop.py +0 -0
  269. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/tests/test_existing_release_reconciliation.py +0 -0
  270. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/tests/test_forge_console_admin_parity_contract.py +0 -0
  271. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/tests/test_forge_console_configuration_contract.py +0 -0
  272. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/tests/test_forge_console_hosting_contract.py +0 -0
  273. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/tests/test_forge_operations_console_roadmap.py +0 -0
  274. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/tests/test_forge_outer_loop_ci_roadmap.py +0 -0
  275. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/tests/test_forge_v1_bootstrap_scheduler_contract.py +0 -0
  276. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/tests/test_forge_v1_implementation_dag.py +0 -0
  277. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/tests/test_foundation_loader.py +0 -0
  278. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/tests/test_foundation_models.py +0 -0
  279. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/tests/test_generation_one_bootstrap_qualification.py +0 -0
  280. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/tests/test_generation_two_execution.py +0 -0
  281. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/tests/test_generation_two_mission_intake.py +0 -0
  282. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/tests/test_governance_authority.py +0 -0
  283. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/tests/test_governed_coverage.py +0 -0
  284. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/tests/test_historical_engineering_intent.py +0 -0
  285. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/tests/test_host_control_completion.py +0 -0
  286. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/tests/test_inner_loop_ci_contract.py +0 -0
  287. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/tests/test_installed_dynamic_mission_runtime.py +0 -0
  288. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/tests/test_integration_coordination.py +0 -0
  289. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/tests/test_knowledge_consumption.py +0 -0
  290. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/tests/test_live_project_roadmap_contract.py +0 -0
  291. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/tests/test_mission_completion_evaluator.py +0 -0
  292. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/tests/test_mission_controller.py +0 -0
  293. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/tests/test_mission_dispatcher.py +0 -0
  294. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/tests/test_mission_planner.py +0 -0
  295. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/tests/test_mission_recommendation_engine.py +0 -0
  296. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/tests/test_mission_recommendation_lifecycle.py +0 -0
  297. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/tests/test_mission_runtime_projection.py +0 -0
  298. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/tests/test_mission_runtime_scheduler.py +0 -0
  299. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/tests/test_mission_state_store.py +0 -0
  300. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/tests/test_mission_status.py +0 -0
  301. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/tests/test_openai_action_derivation.py +0 -0
  302. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/tests/test_operational_reset.py +0 -0
  303. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/tests/test_operations_health.py +0 -0
  304. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/tests/test_operations_read_api.py +0 -0
  305. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/tests/test_operator_identity.py +0 -0
  306. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/tests/test_phase_completion.py +0 -0
  307. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/tests/test_platform_contract_documents.py +0 -0
  308. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/tests/test_portfolio_intelligence_operation.py +0 -0
  309. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/tests/test_preserved_lifecycle.py +0 -0
  310. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/tests/test_producer_contract.py +0 -0
  311. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/tests/test_product_version_operations.py +0 -0
  312. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/tests/test_production_release_workflow.py +0 -0
  313. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/tests/test_productization_reconciliation.py +0 -0
  314. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/tests/test_programme_authorization.py +0 -0
  315. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/tests/test_provider_context.py +0 -0
  316. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/tests/test_provider_security.py +0 -0
  317. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/tests/test_pypi_distribution_readback.py +0 -0
  318. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/tests/test_recovered_partial_completion.py +0 -0
  319. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/tests/test_release_operation.py +0 -0
  320. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/tests/test_repository_truth.py +0 -0
  321. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/tests/test_role_aware_conversations_contract.py +0 -0
  322. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/tests/test_runtime_bootstrap.py +0 -0
  323. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/tests/test_runtime_database.py +0 -0
  324. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/tests/test_runtime_evidence.py +0 -0
  325. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/tests/test_runtime_health.py +0 -0
  326. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/tests/test_runtime_instance_persistence.py +0 -0
  327. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/tests/test_runtime_prompt_generation.py +0 -0
  328. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/tests/test_runtime_service.py +0 -0
  329. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/tests/test_runtime_status_projection.py +0 -0
  330. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/tests/test_scheduler_dependency_boundary.py +0 -0
  331. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/tests/test_schemas.py +0 -0
  332. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/tests/test_secure_store.py +0 -0
  333. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/tests/test_server_api_contract.py +0 -0
  334. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/tests/test_server_runtime.py +0 -0
  335. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/tests/test_solution_templates.py +0 -0
  336. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/tests/test_substantive_mission_completion.py +0 -0
  337. {forge_autonomy-2.7.37 → forge_autonomy-2.7.38}/tests/test_terminal_continuation_replay.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: forge-autonomy
3
- Version: 2.7.37
3
+ Version: 2.7.38
4
4
  Summary: Forge mission planning, producer contracts, and evidence interpretation runtime.
5
5
  Author: Forge maintainers
6
6
  License-Expression: Apache-2.0
@@ -52,6 +52,9 @@ SUPPORTED_TRANSITIONS = {
52
52
  ("2.7.32", "2.7.33"): (39, 39),
53
53
  ("2.7.33", "2.7.34"): (39, 39),
54
54
  ("2.7.34", "2.7.35"): (39, 39),
55
+ ("2.7.35", "2.7.38"): (39, 39),
56
+ ("2.7.36", "2.7.38"): (39, 39),
57
+ ("2.7.37", "2.7.38"): (39, 39),
55
58
  }
56
59
  SAME_SCHEMA_39_TRANSITIONS = frozenset(
57
60
  transition for transition, schemas in SUPPORTED_TRANSITIONS.items() if schemas == (39, 39)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: forge-autonomy
3
- Version: 2.7.37
3
+ Version: 2.7.38
4
4
  Summary: Forge mission planning, producer contracts, and evidence interpretation runtime.
5
5
  Author: Forge maintainers
6
6
  License-Expression: Apache-2.0
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "product": "forge",
3
3
  "schema_version": 1,
4
- "version": "2.7.37"
4
+ "version": "2.7.38"
5
5
  }
@@ -3,8 +3,10 @@
3
3
  from __future__ import annotations
4
4
 
5
5
  import base64
6
+ from contextlib import redirect_stdout
6
7
  import importlib.util
7
8
  from hashlib import sha256
9
+ from io import StringIO
8
10
  import json
9
11
  import os
10
12
  from pathlib import Path
@@ -18,6 +20,7 @@ import zipfile
18
20
 
19
21
  from forge.runtime import RuntimeBootstrap
20
22
  import forge.runtime.database as runtime_database
23
+ from forge.installed_lifecycle import SUPPORTED_TRANSITIONS as PACKAGED_TRANSITIONS
21
24
  from forge.runtime.operational_reset import MAINTENANCE_TABLES
22
25
 
23
26
 
@@ -294,7 +297,7 @@ class InstalledForgeUpdateTests(unittest.TestCase):
294
297
  "github_release": {"draft": False},
295
298
  },
296
299
  }, sort_keys=True), encoding="utf-8")
297
- if version in {"2.7.25", "2.7.26", "2.7.27", "2.7.28", "2.7.29", "2.7.30", "2.7.31", "2.7.32", "2.7.33", "2.7.34", "2.7.35"}:
300
+ if version in {"2.7.25", "2.7.26", "2.7.27", "2.7.28", "2.7.29", "2.7.30", "2.7.31", "2.7.32", "2.7.33", "2.7.34", "2.7.35", "2.7.38"}:
298
301
  # Captured from the actual installed-composition command used by
299
302
  # both workflow stages; only the synthetic wheel binding changes.
300
303
  summary = json.loads((Path(__file__).parent / "fixtures" /
@@ -304,7 +307,7 @@ class InstalledForgeUpdateTests(unittest.TestCase):
304
307
  document = json.loads(receipt.read_text())
305
308
  document["qualification"]["criterion_completion"] = summary
306
309
  document["publication_receipt"]["criterion_completion"] = summary
307
- if version in {"2.7.34", "2.7.35"}:
310
+ if version in {"2.7.34", "2.7.35", "2.7.38"}:
308
311
  server_runtime = {
309
312
  "qualification": "FORGE_SERVER_RUNTIME_V1_INSTALLED_ARTIFACT",
310
313
  "version": version,
@@ -317,12 +320,19 @@ class InstalledForgeUpdateTests(unittest.TestCase):
317
320
  "production_ep_contacted": False,
318
321
  "production_provider_contacted": False,
319
322
  }
320
- if version == "2.7.35":
323
+ if version in {"2.7.35", "2.7.38"}:
321
324
  server_runtime.update({
322
325
  "lifecycle_update_assessment": "PASS",
323
326
  "lifecycle_uninstall_dispatcher": "PASS",
324
327
  "lifecycle_uninstall_replay": "PASS",
325
328
  })
329
+ if version == "2.7.38":
330
+ server_runtime.update({
331
+ "lifecycle_preserve": "PASS",
332
+ "lifecycle_restore": "PASS",
333
+ "lifecycle_purge": "PASS",
334
+ "lifecycle_filesystem_security": "PASS",
335
+ })
326
336
  document["qualification"]["server_runtime"] = server_runtime
327
337
  document["publication_receipt"]["server_runtime"] = server_runtime
328
338
  receipt.write_text(json.dumps(document, sort_keys=True))
@@ -339,6 +349,364 @@ class InstalledForgeUpdateTests(unittest.TestCase):
339
349
  })
340
350
  return request
341
351
 
352
+ def test_standalone_transition_registry_matches_packaged_policy(self):
353
+ self.assertEqual(update.SUPPORTED_TRANSITIONS, PACKAGED_TRANSITIONS)
354
+
355
+ def test_2735_2736_and_2737_have_direct_same_schema_paths_to_2738(self):
356
+ for existing in ("2.7.35", "2.7.36", "2.7.37"):
357
+ with self.subTest(existing=existing):
358
+ request = self._normal_release_request("2.7.38", existing)
359
+ request = update.UpdateRequest(**{
360
+ **request.__dict__,
361
+ "installed_source": "d" * 40,
362
+ "installed_artifact_digest": "sha256:" + "e" * 64,
363
+ "assessment_digest": "sha256:" + "f" * 64,
364
+ })
365
+ self.assertEqual(update.transition_schemas(request), (39, 39))
366
+ self.assertEqual(update.validate_qualified_artifact(request)["release_route"], "NORMAL")
367
+
368
+ def _assessment_request_2738(self, existing_version="2.7.35"):
369
+ self._same_schema39_transition(
370
+ existing_version=existing_version,
371
+ target_version="2.7.38",
372
+ )
373
+ self.request = update.UpdateRequest(**{
374
+ **self.request.__dict__,
375
+ "installed_source": "d" * 40,
376
+ "installed_artifact_digest": "sha256:" + "e" * 64,
377
+ })
378
+ return self.request
379
+
380
+ def test_2738_standalone_assessment_is_read_only_and_exactly_bound(self):
381
+ request = self._assessment_request_2738()
382
+ before = {
383
+ path.relative_to(self.data_root).as_posix(): update.file_digest(path)
384
+ for path in self.data_root.rglob("*") if path.is_file()
385
+ }
386
+ result = update.assess_update(request)
387
+ after = {
388
+ path.relative_to(self.data_root).as_posix(): update.file_digest(path)
389
+ for path in self.data_root.rglob("*") if path.is_file()
390
+ }
391
+ self.assertEqual(result["state"], "UPDATE_AVAILABLE")
392
+ self.assertFalse(result["mutating"])
393
+ self.assertEqual(result["operation_id"], request.operation_id)
394
+ self.assertEqual(result["request_digest"], request.assessment_request_digest)
395
+ self.assertEqual(result["selected_installation"]["source_revision"], "d" * 40)
396
+ self.assertEqual(result["candidate"]["version"], "2.7.38")
397
+ self.assertEqual(before, after)
398
+
399
+ def test_2738_stale_assessment_fails_before_operation_or_resolver_effect(self):
400
+ request = self._assessment_request_2738()
401
+ assessment = update.assess_update(request)
402
+ stale = update.UpdateRequest(**{
403
+ **request.__dict__,
404
+ "installed_source": "f" * 40,
405
+ "assessment_digest": assessment["assessment_digest"],
406
+ })
407
+ resolver_before = self.resolver.read_bytes()
408
+ controller = update.InstalledForgeUpdateController(stale, process_reader=lambda: ())
409
+ with self.assertRaisesRegex(update.InstalledForgeUpdateError, "assessment"):
410
+ controller.run()
411
+ self.assertFalse(controller.operation_root.exists())
412
+ self.assertEqual(self.resolver.read_bytes(), resolver_before)
413
+
414
+ def test_2738_assessment_rejects_permissive_and_hardlinked_instance_entries(self):
415
+ request = self._assessment_request_2738()
416
+ unsafe = self.data_root / "unsafe-file"
417
+ unsafe.write_text("unsafe", encoding="utf-8")
418
+ unsafe.chmod(0o666)
419
+ result = update.assess_update(request)
420
+ self.assertEqual(result["state"], "UNKNOWN")
421
+ self.assertIn("group/world-writable", result["evidence"]["error"])
422
+ unsafe.chmod(0o600)
423
+ foreign = self.root / "foreign"
424
+ foreign.write_text("foreign", encoding="utf-8")
425
+ unsafe.unlink()
426
+ unsafe.hardlink_to(foreign)
427
+ result = update.assess_update(request)
428
+ self.assertEqual(result["state"], "UNKNOWN")
429
+ self.assertIn("hardlinked", result["evidence"]["error"])
430
+
431
+ def test_2738_assessment_schema_and_foreign_artifact_controls_fail_closed(self):
432
+ request = self._assessment_request_2738()
433
+ with sqlite3.connect(self.data_root / "forge.db") as connection:
434
+ connection.execute("PRAGMA user_version=38")
435
+ schema = update.assess_update(request)
436
+ self.assertEqual(schema["state"], "INCOMPATIBLE")
437
+ self.assertEqual(schema["reason_codes"], ["RUNTIME_SCHEMA_OUTSIDE_BOUNDED_TRANSITION"])
438
+ changed = update.UpdateRequest(**{
439
+ **request.__dict__,
440
+ "wheel_sha256": "sha256:" + "0" * 64,
441
+ })
442
+ foreign = update.assess_update(changed)
443
+ self.assertEqual(foreign["state"], "UNKNOWN")
444
+ self.assertIn("wheel digest", foreign["evidence"]["error"])
445
+
446
+ def test_2738_run_orchestration_binds_assessment_and_terminal_receipt(self):
447
+ request = self._assessment_request_2738()
448
+ assessment = update.assess_update(request)
449
+ request = update.UpdateRequest(**{
450
+ **request.__dict__, "assessment_digest": assessment["assessment_digest"],
451
+ })
452
+ controller = update.InstalledForgeUpdateController(request, process_reader=lambda: ())
453
+ before = update.database_snapshot(self.data_root / "forge.db")
454
+
455
+ def advance(state, phase, **evidence):
456
+ return {**state, **evidence, "phase": phase}
457
+
458
+ with (
459
+ patch.object(update, "reconcile_terminal_dispatcher_for_update",
460
+ side_effect=lambda _request, snapshot, _database: snapshot),
461
+ patch.object(controller, "_stage", side_effect=lambda state: advance(state, "STAGED")),
462
+ patch.object(controller, "_adopt_resolver",
463
+ side_effect=lambda state: advance(state, "ADOPTED", before=before)),
464
+ patch.object(controller, "_backup", side_effect=lambda state, _before: advance(
465
+ state, "BACKED_UP", backup={"status": "PASS", "path": str(controller.backup_path)},
466
+ )),
467
+ patch.object(controller, "_qualify_copy", side_effect=lambda state, _before: advance(
468
+ state, "MIGRATION_QUALIFIED", migration_qualification={"status": "PASS"},
469
+ )),
470
+ patch.object(controller, "_migrate_live", side_effect=lambda state, _before: (
471
+ advance(state, "MIGRATED", live_migration={"status": "PASS"}), before,
472
+ )),
473
+ patch.object(controller, "_activate", side_effect=lambda state, _after: advance(
474
+ state, "ACTIVATED", installed_readback={
475
+ "preservation": {"status": "PASS"},
476
+ "database_snapshot_digest": before["snapshot_digest"],
477
+ },
478
+ )),
479
+ ):
480
+ receipt = controller.run()
481
+
482
+ self.assertEqual(receipt["state"], "COMPLETE")
483
+ self.assertEqual(receipt["assessment_digest"], assessment["assessment_digest"])
484
+ self.assertEqual(receipt["installed_source"], request.installed_source)
485
+ self.assertEqual(receipt["installed_artifact_digest"], request.installed_artifact_digest)
486
+ self.assertEqual(receipt["credential_disposition"], "PRESERVED_UNCHANGED")
487
+ self.assertEqual(update._read_json(controller.receipt_path), receipt)
488
+ self.assertEqual(update._read_json(controller.state_path)["phase"], "COMPLETE")
489
+
490
+ def test_cli_assessment_success_mutation_success_and_error_are_machine_readable(self):
491
+ request = self._assessment_request_2738()
492
+ options = {
493
+ "operation-id": request.operation_id,
494
+ "version": request.version,
495
+ "product-source": request.product_source,
496
+ "wheel": request.wheel,
497
+ "wheel-sha256": request.wheel_sha256,
498
+ "qualification-receipt": request.qualification_receipt,
499
+ "qualification-receipt-sha256": request.qualification_receipt_sha256,
500
+ "controller-source": request.controller_source,
501
+ "controller-sha256": request.controller_sha256,
502
+ "data-root": request.data_root,
503
+ "runtime-root": request.runtime_root,
504
+ "runtime-id": request.runtime_id,
505
+ "installation-id": request.installation_id,
506
+ "peer-configuration-digest": request.peer_configuration_digest,
507
+ "resolver": request.resolver,
508
+ "resolver-sha256": request.resolver_sha256,
509
+ "existing-interpreter": request.existing_interpreter,
510
+ "existing-version": request.existing_version,
511
+ "base-python": request.base_python,
512
+ "installed-source": request.installed_source,
513
+ "installed-artifact-digest": request.installed_artifact_digest,
514
+ }
515
+ argv = [item for key, value in options.items() for item in (f"--{key}", value)]
516
+ assessment = update.assess_update(request)
517
+ output = StringIO()
518
+ with redirect_stdout(output):
519
+ self.assertEqual(update.main([*argv, "--assess-only"]), 0)
520
+ self.assertEqual(json.loads(output.getvalue()), assessment)
521
+
522
+ mutation_argv = [*argv, "--assessment-digest", assessment["assessment_digest"]]
523
+ completed = {"state": "COMPLETE", "operation_id": request.operation_id}
524
+ output = StringIO()
525
+ with (
526
+ patch.object(update.InstalledForgeUpdateController, "run", return_value=completed),
527
+ redirect_stdout(output),
528
+ ):
529
+ self.assertEqual(update.main(mutation_argv), 0)
530
+ self.assertEqual(json.loads(output.getvalue()), completed)
531
+
532
+ output = StringIO()
533
+ with (
534
+ patch.object(update.InstalledForgeUpdateController, "run",
535
+ side_effect=update.InstalledForgeUpdateError("blocked")),
536
+ redirect_stdout(output),
537
+ ):
538
+ self.assertEqual(update.main([*mutation_argv, "--reconcile-staged-controller"]), 1)
539
+ self.assertEqual(json.loads(output.getvalue()), {"status": "ERROR", "error": "blocked"})
540
+
541
+ def test_controller_input_and_utility_failures_are_fail_closed(self):
542
+ invalid = (
543
+ ({"operation_id": "../escape"}, "filesystem-safe"),
544
+ ({"wheel_sha256": "bad"}, "wheel digest"),
545
+ ({"product_source": "short"}, "source revisions"),
546
+ ({"wheel": "relative.whl"}, "absolute"),
547
+ ({"version": "2.7.38", "installed_source": "short",
548
+ "installed_artifact_digest": "sha256:" + "e" * 64}, "installed source"),
549
+ ({"version": "2.7.38", "installed_source": "d" * 40,
550
+ "installed_artifact_digest": "bad"}, "installed artifact"),
551
+ )
552
+ for changes, message in invalid:
553
+ with self.subTest(changes=changes):
554
+ request = update.UpdateRequest(**{**self.request.__dict__, **changes})
555
+ with self.assertRaisesRegex(update.InstalledForgeUpdateError, message):
556
+ request.validate_structure()
557
+
558
+ with self.assertRaisesRegex(update.InstalledForgeUpdateError, "absolute"):
559
+ update._safe_directory(Path("relative"))
560
+ with self.assertRaisesRegex(update.InstalledForgeUpdateError, "unavailable"):
561
+ update._safe_directory(self.root / "missing")
562
+ with self.assertRaisesRegex(update.InstalledForgeUpdateError, "not a symlink"):
563
+ update._resolved_link(self.resolver)
564
+ with self.assertRaisesRegex(update.InstalledForgeUpdateError, "required regular file"):
565
+ update.file_digest(self.root / "missing.bin")
566
+ with self.assertRaisesRegex(update.InstalledForgeUpdateError, "required regular file"):
567
+ update._read_regular_bytes(self.root)
568
+
569
+ guarded = self.root / "guarded-tree"
570
+ guarded.mkdir()
571
+ (guarded / "link").symlink_to(self.resolver)
572
+ with self.assertRaisesRegex(update.InstalledForgeUpdateError, "symbolic link"):
573
+ update._assert_private_owned_tree(guarded)
574
+ (guarded / "link").unlink()
575
+ os.mkfifo(guarded / "special")
576
+ with self.assertRaisesRegex(update.InstalledForgeUpdateError, "special entry"):
577
+ update._assert_private_owned_tree(guarded)
578
+
579
+ malformed = self.root / "malformed.json"
580
+ malformed.write_text("{", encoding="utf-8")
581
+ with self.assertRaisesRegex(update.InstalledForgeUpdateError, "unreadable"):
582
+ update._read_json(malformed)
583
+ malformed.write_text("[]", encoding="utf-8")
584
+ with self.assertRaisesRegex(update.InstalledForgeUpdateError, "not an object"):
585
+ update._read_json(malformed)
586
+
587
+ failure = update.subprocess.CalledProcessError(
588
+ 1, ["tool"], output="bounded stdout", stderr="bounded stderr",
589
+ )
590
+ with patch.object(update.subprocess, "run", side_effect=failure):
591
+ with self.assertRaisesRegex(update.InstalledForgeUpdateError, "bounded stderr"):
592
+ update._run(("tool",), cwd=self.root)
593
+ with patch.object(update, "_run", return_value=SimpleNamespace(stdout="not-json")):
594
+ with self.assertRaisesRegex(update.InstalledForgeUpdateError, "malformed"):
595
+ update.installed_identity(Path(sys.executable), cwd=self.root)
596
+ with patch.object(update, "_run", return_value=SimpleNamespace(stdout="[]")):
597
+ with self.assertRaisesRegex(update.InstalledForgeUpdateError, "malformed"):
598
+ update.installed_identity(Path(sys.executable), cwd=self.root)
599
+
600
+ def test_validated_wheel_installation_is_exact_and_tamper_evident(self):
601
+ wheel_bytes, manifest = update._validated_wheel(self.request)
602
+ slot = self.root / "candidate-slot"
603
+ site_packages = slot / "lib" / "python3.14" / "site-packages"
604
+ site_packages.mkdir(parents=True)
605
+ (slot / "bin").mkdir()
606
+ update._install_validated_wheel(slot, wheel_bytes, manifest)
607
+ evidence = update._verify_candidate_files(slot, manifest)
608
+ self.assertEqual(evidence["installed_file_count"], len(manifest))
609
+ self.assertEqual((slot / "bin" / "forge").stat().st_mode & 0o777, 0o700)
610
+ (site_packages / "forge" / "__init__.py").write_text("tampered", encoding="utf-8")
611
+ with self.assertRaisesRegex(update.InstalledForgeUpdateError, "changed="):
612
+ update._verify_candidate_files(slot, manifest)
613
+
614
+ def test_2738_qualification_copy_is_durable_and_replayable(self):
615
+ request = self._assessment_request_2738()
616
+ controller = update.InstalledForgeUpdateController(
617
+ update.UpdateRequest(**{
618
+ **request.__dict__,
619
+ "assessment_digest": update.assess_update(request)["assessment_digest"],
620
+ }),
621
+ process_reader=lambda: (),
622
+ )
623
+ before = update.database_snapshot(self.data_root / "forge.db")
624
+ update._copy_sqlite_backup(self.data_root / "forge.db", controller.backup_path)
625
+ state = controller._state()
626
+ with patch.object(update, "_candidate_migrate", return_value={
627
+ "initialized": True, "storage_schema": "39", "product_version": "2.7.38",
628
+ }):
629
+ qualified = controller._qualify_copy(state, before)
630
+ replayed = controller._qualify_copy(qualified, before)
631
+ self.assertEqual(qualified["phase"], "MIGRATION_QUALIFIED")
632
+ self.assertEqual(qualified["migration_qualification"]["status"], "PASS")
633
+ self.assertEqual(replayed, qualified)
634
+
635
+ def test_2738_activation_uses_exact_candidate_and_readiness_identity(self):
636
+ request = self._assessment_request_2738()
637
+ request = update.UpdateRequest(**{
638
+ **request.__dict__,
639
+ "assessment_digest": update.assess_update(request)["assessment_digest"],
640
+ })
641
+ controller = update.InstalledForgeUpdateController(request, process_reader=lambda: ())
642
+ candidate = controller.slot / "bin" / "forge"
643
+ candidate.parent.mkdir(parents=True)
644
+ candidate.write_text("candidate", encoding="utf-8")
645
+ python = controller.slot / "bin" / "python"
646
+ python.write_text("python", encoding="utf-8")
647
+ controller.stable_resolver.parent.mkdir(parents=True)
648
+ controller.stable_resolver.symlink_to("../current")
649
+ self.resolver.unlink()
650
+ self.resolver.symlink_to(controller.stable_resolver)
651
+ before = update.database_snapshot(self.data_root / "forge.db")
652
+ state = {"phase": "MIGRATED", "before": before}
653
+ identity = {
654
+ "version": "2.7.38",
655
+ "distribution_version": "2.7.38",
656
+ "sys_executable": str(python),
657
+ "module": str(controller.slot / "forge" / "__init__.py"),
658
+ }
659
+ status = {
660
+ "product_version": "2.7.38",
661
+ "data_root": str(self.data_root),
662
+ "instance_id": self.runtime_id,
663
+ "storage_schema": "39",
664
+ }
665
+ with (
666
+ patch.object(update, "installed_identity", return_value=identity),
667
+ patch.object(update, "_run", side_effect=(
668
+ SimpleNamespace(stdout="2.7.38\n"),
669
+ SimpleNamespace(stdout=json.dumps(status)),
670
+ )),
671
+ patch.object(update, "verify_preservation", return_value={"status": "PASS"}),
672
+ ):
673
+ activated = controller._activate(state, before)
674
+ self.assertEqual(activated["phase"], "ACTIVATED")
675
+ self.assertEqual(activated["installed_readback"]["status"], status)
676
+ self.assertEqual(self.resolver.resolve(), candidate.resolve())
677
+
678
+ def test_completed_replay_rechecks_receipt_backup_and_slot_evidence(self):
679
+ request = self._assessment_request_2738()
680
+ request = update.UpdateRequest(**{
681
+ **request.__dict__,
682
+ "assessment_digest": update.assess_update(request)["assessment_digest"],
683
+ })
684
+ controller = update.InstalledForgeUpdateController(request, process_reader=lambda: ())
685
+ update._copy_sqlite_backup(self.data_root / "forge.db", controller.backup_path)
686
+ receipt = {
687
+ "state": "COMPLETE",
688
+ "request_digest": request.digest,
689
+ "backup": {
690
+ "path": str(controller.backup_path),
691
+ "sha256": update.file_digest(controller.backup_path),
692
+ },
693
+ }
694
+ update._atomic_json(controller.receipt_path, receipt)
695
+ state = {
696
+ "phase": "COMPLETE",
697
+ "request_digest": request.digest,
698
+ "receipt_sha256": update.file_digest(controller.receipt_path),
699
+ }
700
+ with patch.object(update, "_qualified_artifact", return_value=(
701
+ {"wheel_manifest_digest": "sha256:" + "a" * 64}, b"", {},
702
+ )):
703
+ with self.assertRaisesRegex(update.InstalledForgeUpdateError, "required regular file"):
704
+ controller._verify_complete(state, receipt)
705
+
706
+ controller.database = self.root / "missing-forge.db"
707
+ with self.assertRaisesRegex(update.InstalledForgeUpdateError, "database is unavailable"):
708
+ controller._restore_database_writable()
709
+
342
710
  def test_2725_requires_exact_qualifying_and_published_installed_composition(self):
343
711
  request = self._normal_release_request("2.7.25", "2.7.24")
344
712
  self.assertEqual(update.validate_qualified_artifact(request)["release_route"], "NORMAL")
@@ -395,8 +763,12 @@ class InstalledForgeUpdateTests(unittest.TestCase):
395
763
  wrong_transition = update.UpdateRequest(**{
396
764
  **request.__dict__, "existing_version": "2.7.21",
397
765
  })
766
+ self.assertEqual(
767
+ update.validate_qualified_artifact(wrong_transition)["release_route"],
768
+ "NORMAL",
769
+ )
398
770
  with self.assertRaises(update.InstalledForgeUpdateError):
399
- update.validate_qualified_artifact(wrong_transition)
771
+ wrong_transition.validate()
400
772
 
401
773
  def test_real_schema37_to_38_migration_preserves_history_and_bindings(self) -> None:
402
774
  self._installed_schema37()
@@ -137,6 +137,23 @@ class UpdateAssessmentTests(InstalledLifecycleFixture):
137
137
  def test_valid_unsupported_transition_is_incompatible(self) -> None:
138
138
  self.assertEqual(self.assessment("3.0.0")["state"], "INCOMPATIBLE")
139
139
 
140
+ def test_declared_server_baselines_assess_directly_to_2738(self) -> None:
141
+ wheel, digest = _write_wheel(self.root, "2.7.38")
142
+ for installed in ("2.7.35", "2.7.36", "2.7.37"):
143
+ data_root = self.instances_root / installed
144
+ database = RuntimeBootstrap(data_root=data_root, forge_version=installed).open()
145
+ runtime_id = database.runtime_identity.runtime_id
146
+ installation_id = database.metadata["installation_id"]
147
+ database.close()
148
+ result = assess_update(UpdateAssessmentRequest(
149
+ data_root=str(data_root), runtime_id=runtime_id, installation_id=installation_id,
150
+ installed_version=installed, installed_source="a" * 40,
151
+ installed_artifact_digest="sha256:" + "b" * 64,
152
+ candidate_version="2.7.38", candidate_source="c" * 40,
153
+ candidate_wheel=str(wheel), candidate_artifact_digest=digest,
154
+ ))
155
+ self.assertEqual(result["state"], "UPDATE_AVAILABLE", installed)
156
+
140
157
  def test_identity_or_artifact_uncertainty_fails_closed(self) -> None:
141
158
  self.assertEqual(self.assessment(runtime_id="runtime-wrong")["state"], "UNKNOWN")
142
159
  result = self.assessment(candidate_artifact_digest="sha256:" + "0" * 64)