codeframe-ai 0.9.4__tar.gz → 0.9.5__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 (226) hide show
  1. {codeframe_ai-0.9.4/codeframe_ai.egg-info → codeframe_ai-0.9.5}/PKG-INFO +3 -2
  2. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/README.md +2 -1
  3. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/adapters/llm/base.py +7 -5
  4. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/cli/app.py +90 -23
  5. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/adapters/streaming_chat.py +10 -3
  6. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/config.py +3 -0
  7. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/prd_discovery.py +325 -37
  8. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/lib/metrics_tracker.py +9 -0
  9. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/ui/routers/discovery_v2.py +48 -0
  10. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5/codeframe_ai.egg-info}/PKG-INFO +3 -2
  11. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/pyproject.toml +1 -1
  12. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/LICENSE +0 -0
  13. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/__init__.py +0 -0
  14. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/__main__.py +0 -0
  15. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/adapters/__init__.py +0 -0
  16. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/adapters/e2b/__init__.py +0 -0
  17. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/adapters/e2b/adapter.py +0 -0
  18. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/adapters/e2b/budget.py +0 -0
  19. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/adapters/e2b/credential_scanner.py +0 -0
  20. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/adapters/llm/__init__.py +0 -0
  21. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/adapters/llm/anthropic.py +0 -0
  22. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/adapters/llm/errors.py +0 -0
  23. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/adapters/llm/mock.py +0 -0
  24. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/adapters/llm/openai.py +0 -0
  25. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/agents/__init__.py +0 -0
  26. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/agents/dependency_resolver.py +0 -0
  27. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/auth/__init__.py +0 -0
  28. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/auth/api_key_router.py +0 -0
  29. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/auth/api_keys.py +0 -0
  30. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/auth/dependencies.py +0 -0
  31. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/auth/manager.py +0 -0
  32. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/auth/models.py +0 -0
  33. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/auth/router.py +0 -0
  34. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/auth/schemas.py +0 -0
  35. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/auth/scopes.py +0 -0
  36. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/auth/stream_tickets.py +0 -0
  37. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/cli/__init__.py +0 -0
  38. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/cli/__main__.py +0 -0
  39. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/cli/api_client.py +0 -0
  40. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/cli/auth.py +0 -0
  41. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/cli/auth_commands.py +0 -0
  42. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/cli/config_commands.py +0 -0
  43. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/cli/dashboard_commands.py +0 -0
  44. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/cli/engines_commands.py +0 -0
  45. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/cli/env_commands.py +0 -0
  46. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/cli/helpers.py +0 -0
  47. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/cli/hooks_commands.py +0 -0
  48. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/cli/import_commands.py +0 -0
  49. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/cli/pr_commands.py +0 -0
  50. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/cli/proof_commands.py +0 -0
  51. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/cli/stats_commands.py +0 -0
  52. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/cli/telemetry_runtime.py +0 -0
  53. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/cli/validators.py +0 -0
  54. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/config/rate_limits.py +0 -0
  55. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/__init__.py +0 -0
  56. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/adapters/__init__.py +0 -0
  57. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/adapters/agent_adapter.py +0 -0
  58. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/adapters/builtin.py +0 -0
  59. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/adapters/claude_code.py +0 -0
  60. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/adapters/codex.py +0 -0
  61. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/adapters/git_utils.py +0 -0
  62. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/adapters/kilocode.py +0 -0
  63. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/adapters/opencode.py +0 -0
  64. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/adapters/subprocess_adapter.py +0 -0
  65. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/adapters/verification_wrapper.py +0 -0
  66. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/agent.py +0 -0
  67. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/agent_env.py +0 -0
  68. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/agents_config.py +0 -0
  69. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/api_key_service.py +0 -0
  70. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/artifacts.py +0 -0
  71. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/atomic_io.py +0 -0
  72. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/blocker_detection.py +0 -0
  73. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/blockers.py +0 -0
  74. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/checkpoints.py +0 -0
  75. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/claude_code_guard.py +0 -0
  76. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/conductor.py +0 -0
  77. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/config_watcher.py +0 -0
  78. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/context.py +0 -0
  79. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/context_packager.py +0 -0
  80. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/cost_tracker.py +0 -0
  81. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/credentials.py +0 -0
  82. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/dangerous_commands.py +0 -0
  83. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/dependency_analyzer.py +0 -0
  84. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/dependency_graph.py +0 -0
  85. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/diagnostic_agent.py +0 -0
  86. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/diagnostics.py +0 -0
  87. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/editor.py +0 -0
  88. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/engine_registry.py +0 -0
  89. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/engine_stats.py +0 -0
  90. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/env_provenance.py +0 -0
  91. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/environment.py +0 -0
  92. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/events.py +0 -0
  93. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/executor.py +0 -0
  94. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/fix_tracker.py +0 -0
  95. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/gates.py +0 -0
  96. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/git.py +0 -0
  97. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/github_connect_service.py +0 -0
  98. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/github_integration_config.py +0 -0
  99. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/github_issues_service.py +0 -0
  100. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/hook_trust.py +0 -0
  101. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/hooks.py +0 -0
  102. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/importers/__init__.py +0 -0
  103. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/importers/ralph.py +0 -0
  104. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/installer.py +0 -0
  105. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/llm_json.py +0 -0
  106. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/llm_resolution.py +0 -0
  107. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/models.py +0 -0
  108. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/notifications_config.py +0 -0
  109. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/path_safety.py +0 -0
  110. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/planner.py +0 -0
  111. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/prd.py +0 -0
  112. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/prd_stress_test.py +0 -0
  113. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/progress.py +0 -0
  114. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/proof/__init__.py +0 -0
  115. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/proof/capture.py +0 -0
  116. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/proof/evidence.py +0 -0
  117. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/proof/ledger.py +0 -0
  118. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/proof/models.py +0 -0
  119. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/proof/obligations.py +0 -0
  120. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/proof/report.py +0 -0
  121. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/proof/runner.py +0 -0
  122. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/proof/scope.py +0 -0
  123. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/proof/stubs.py +0 -0
  124. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/quick_fixes.py +0 -0
  125. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/react_agent.py +0 -0
  126. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/reconciliation.py +0 -0
  127. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/replay.py +0 -0
  128. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/review.py +0 -0
  129. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/run_control.py +0 -0
  130. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/runtime.py +0 -0
  131. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/sandbox/__init__.py +0 -0
  132. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/sandbox/context.py +0 -0
  133. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/sandbox/worktree.py +0 -0
  134. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/schedule.py +0 -0
  135. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/spend_limit.py +0 -0
  136. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/stall_detector.py +0 -0
  137. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/stall_monitor.py +0 -0
  138. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/state_machine.py +0 -0
  139. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/streaming.py +0 -0
  140. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/task_tree.py +0 -0
  141. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/tasks.py +0 -0
  142. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/tech_stack.py +0 -0
  143. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/telemetry.py +0 -0
  144. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/templates.py +0 -0
  145. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/tools.py +0 -0
  146. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/usage_recording.py +0 -0
  147. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/workspace.py +0 -0
  148. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/worktrees.py +0 -0
  149. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/git/__init__.py +0 -0
  150. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/git/github_integration.py +0 -0
  151. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/lib/__init__.py +0 -0
  152. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/lib/audit_logger.py +0 -0
  153. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/lib/quality/__init__.py +0 -0
  154. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/lib/quality/complexity_analyzer.py +0 -0
  155. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/lib/quality/owasp_patterns.py +0 -0
  156. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/lib/quality/security_scanner.py +0 -0
  157. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/lib/rate_limiter.py +0 -0
  158. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/notifications/__init__.py +0 -0
  159. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/notifications/webhook.py +0 -0
  160. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/planning/__init__.py +0 -0
  161. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/planning/prd_templates.py +0 -0
  162. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/planning/task_scheduler.py +0 -0
  163. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/planning/task_templates.py +0 -0
  164. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/platform_store/__init__.py +0 -0
  165. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/platform_store/database.py +0 -0
  166. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/platform_store/repositories/__init__.py +0 -0
  167. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/platform_store/repositories/api_key_repository.py +0 -0
  168. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/platform_store/repositories/audit_repository.py +0 -0
  169. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/platform_store/repositories/base.py +0 -0
  170. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/platform_store/repositories/interactive_sessions.py +0 -0
  171. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/platform_store/repositories/token_repository.py +0 -0
  172. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/platform_store/repositories/workspace_registry_repository.py +0 -0
  173. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/platform_store/schema_manager.py +0 -0
  174. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/templates/AGENTS.md.default +0 -0
  175. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/tui/__init__.py +0 -0
  176. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/tui/app.py +0 -0
  177. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/tui/data_service.py +0 -0
  178. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/ui/__init__.py +0 -0
  179. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/ui/dependencies.py +0 -0
  180. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/ui/models.py +0 -0
  181. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/ui/response_models.py +0 -0
  182. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/ui/routers/__init__.py +0 -0
  183. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/ui/routers/_helpers.py +0 -0
  184. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/ui/routers/batches_v2.py +0 -0
  185. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/ui/routers/blockers_v2.py +0 -0
  186. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/ui/routers/checkpoints_v2.py +0 -0
  187. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/ui/routers/costs_v2.py +0 -0
  188. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/ui/routers/diagnose_v2.py +0 -0
  189. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/ui/routers/environment_v2.py +0 -0
  190. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/ui/routers/events_v2.py +0 -0
  191. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/ui/routers/gates_v2.py +0 -0
  192. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/ui/routers/git_v2.py +0 -0
  193. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/ui/routers/github_integrations_v2.py +0 -0
  194. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/ui/routers/interactive_sessions_v2.py +0 -0
  195. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/ui/routers/pr_v2.py +0 -0
  196. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/ui/routers/prd_v2.py +0 -0
  197. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/ui/routers/proof_v2.py +0 -0
  198. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/ui/routers/review_v2.py +0 -0
  199. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/ui/routers/schedule_v2.py +0 -0
  200. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/ui/routers/session_chat_ws.py +0 -0
  201. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/ui/routers/settings_v2.py +0 -0
  202. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/ui/routers/tasks_v2.py +0 -0
  203. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/ui/routers/templates_v2.py +0 -0
  204. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/ui/routers/terminal_ws.py +0 -0
  205. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/ui/routers/workspace_v2.py +0 -0
  206. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/ui/server.py +0 -0
  207. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/ui/shared.py +0 -0
  208. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/ui/streaming_utils.py +0 -0
  209. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe_ai.egg-info/SOURCES.txt +0 -0
  210. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe_ai.egg-info/dependency_links.txt +0 -0
  211. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe_ai.egg-info/entry_points.txt +0 -0
  212. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe_ai.egg-info/requires.txt +0 -0
  213. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe_ai.egg-info/top_level.txt +0 -0
  214. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/setup.cfg +0 -0
  215. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/tests/test_ambient_workspace_guard.py +0 -0
  216. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/tests/test_claude_review_workflow_1011.py +0 -0
  217. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/tests/test_deploy_audit_gate_1131.py +0 -0
  218. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/tests/test_deploy_config.py +0 -0
  219. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/tests/test_design_partners_619.py +0 -0
  220. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/tests/test_lifecycle_gates_948.py +0 -0
  221. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/tests/test_offline_default_946.py +0 -0
  222. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/tests/test_ops_hygiene_969.py +0 -0
  223. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/tests/test_pm2_scoping_912.py +0 -0
  224. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/tests/test_roadmap_status_1246.py +0 -0
  225. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/tests/test_root_docs_950.py +0 -0
  226. {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/tests/test_workflow_lint_wiring_1122.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: codeframe-ai
3
- Version: 0.9.4
3
+ Version: 0.9.5
4
4
  Summary: A project delivery system that orchestrates frontier coding agents: Think, Build, Prove, Ship.
5
5
  Author-email: Frank Bria <hello@codeframe.sh>
6
6
  License: AGPL-3.0-or-later
@@ -159,7 +159,7 @@ THE CLOSED LOOP
159
159
  ---
160
160
 
161
161
  > [!NOTE]
162
- > **CodeFRAME is in public beta (`0.9.4`).** The vision and the Golden Path CLI
162
+ > **CodeFRAME is in public beta (`0.9.5`).** The vision and the Golden Path CLI
163
163
  > (`cf init/prd/tasks/work/proof/pr`) and v2 API are stable enough to build on;
164
164
  > the web UI and anything marked "in progress" in
165
165
  > [`docs/PRODUCT_ROADMAP.md`](docs/PRODUCT_ROADMAP.md) are still moving, and
@@ -385,6 +385,7 @@ cf status # Workspace status
385
385
  # Requirements
386
386
  cf prd generate # AI-guided Socratic PRD creation
387
387
  cf prd generate --template lean # Use a specific template
388
+ cf prd generate --max-questions 6 # Cap discovery (default 10; /done finishes early)
388
389
  cf prd add <file.md> # Import existing PRD
389
390
  cf prd show # Display current PRD
390
391
 
@@ -74,7 +74,7 @@ THE CLOSED LOOP
74
74
  ---
75
75
 
76
76
  > [!NOTE]
77
- > **CodeFRAME is in public beta (`0.9.4`).** The vision and the Golden Path CLI
77
+ > **CodeFRAME is in public beta (`0.9.5`).** The vision and the Golden Path CLI
78
78
  > (`cf init/prd/tasks/work/proof/pr`) and v2 API are stable enough to build on;
79
79
  > the web UI and anything marked "in progress" in
80
80
  > [`docs/PRODUCT_ROADMAP.md`](docs/PRODUCT_ROADMAP.md) are still moving, and
@@ -300,6 +300,7 @@ cf status # Workspace status
300
300
  # Requirements
301
301
  cf prd generate # AI-guided Socratic PRD creation
302
302
  cf prd generate --template lean # Use a specific template
303
+ cf prd generate --max-questions 6 # Cap discovery (default 10; /done finishes early)
303
304
  cf prd add <file.md> # Import existing PRD
304
305
  cf prd show # Display current PRD
305
306
 
@@ -60,12 +60,14 @@ class Purpose(str, Enum):
60
60
  SUPERVISION = "supervision" # Supervisor decisions (blocker triage, tactical resolution)
61
61
 
62
62
 
63
- # Default model aliases (use valid Anthropic model identifiers)
64
- DEFAULT_PLANNING_MODEL = "claude-sonnet-4-5"
65
- DEFAULT_EXECUTION_MODEL = "claude-sonnet-4-5"
63
+ # Default model aliases (use valid Anthropic model identifiers). The Sonnet tier
64
+ # moved to 5.5 before claude-sonnet-4-5 retires on 2026-11-30 (#1348); Haiku 4.5
65
+ # stays the generation default until it has an announced retirement date.
66
+ DEFAULT_PLANNING_MODEL = "claude-sonnet-5-5"
67
+ DEFAULT_EXECUTION_MODEL = "claude-sonnet-5-5"
66
68
  DEFAULT_GENERATION_MODEL = "claude-haiku-4-5"
67
- DEFAULT_CORRECTION_MODEL = "claude-sonnet-4-5" # Use same tier; override via CODEFRAME_CORRECTION_MODEL for a stronger model
68
- DEFAULT_SUPERVISION_MODEL = "claude-sonnet-4-5" # Use same tier; override via CODEFRAME_SUPERVISION_MODEL for a stronger model
69
+ DEFAULT_CORRECTION_MODEL = "claude-sonnet-5-5" # Use same tier; override via CODEFRAME_CORRECTION_MODEL for a stronger model
70
+ DEFAULT_SUPERVISION_MODEL = "claude-sonnet-5-5" # Use same tier; override via CODEFRAME_SUPERVISION_MODEL for a stronger model
69
71
 
70
72
 
71
73
  @dataclass
@@ -214,14 +214,54 @@ def _load_brief_file(path: Path) -> str:
214
214
  return brief
215
215
 
216
216
 
217
+ def _finish_non_interactive(session, question: dict) -> bool:
218
+ """--brief-file after MAX_ANSWER_ATTEMPTS: finish if an answer is in, else stop.
219
+
220
+ There is no list to desynchronise, so repeated rejection means the brief does
221
+ not cover what is being asked. With an answer in, finishing beats failing:
222
+ the PRD lists what is still uncovered (#1443, #1450).
223
+ """
224
+ answered = session.answered_count
225
+ if not answered:
226
+ console.print(
227
+ "[red]Error:[/red] giving up in non-interactive mode. The stand-in "
228
+ "answered from the brief five times without being accepted, which "
229
+ "usually means the brief does not cover what this question asks:\n\n"
230
+ f" {escape(question.get('text', ''))}\n\n"
231
+ "Extend the brief to cover it, or run interactively."
232
+ )
233
+ raise typer.Exit(1)
234
+ console.print(
235
+ f"[yellow]Finishing discovery with the {answered} answer"
236
+ f"{'' if answered == 1 else 's'} accepted so far; the PRD will list "
237
+ "what is still uncovered as open questions.[/yellow]"
238
+ )
239
+ session.finish_now()
240
+ return True
241
+
242
+
243
+ def _offer_finish(session) -> bool:
244
+ """Interactive: offer to finish now when an answer is in (#1450)."""
245
+ if not session.answered_count or not typer.confirm(
246
+ "Finish discovery now and generate the PRD from what's been answered?",
247
+ default=True,
248
+ ):
249
+ return False
250
+ session.finish_now()
251
+ return True
252
+
253
+
217
254
  def _handle_answer_attempts_exhausted(session, answers: "_AnswerSource", question: dict) -> bool:
218
255
  """React to MAX_ANSWER_ATTEMPTS rejections on one question (#1114).
219
256
 
220
- Returns True to keep trying, False when the caller should stop.
257
+ Returns True to keep trying, False when the caller should stop. When it
258
+ finishes discovery instead (#1450), the session is complete on return and
259
+ the caller goes on to generate the PRD.
221
260
 
222
- Non-interactive runs stop: a canned list that has desynchronised will not
223
- resynchronise by being fed more of itself. Interactive runs are told what is
224
- happening and offered the pause they would otherwise have to discover.
261
+ A canned --answers-file stops: a list that has desynchronised will not
262
+ resynchronise by being fed more of itself. Otherwise, once an answer has
263
+ been accepted, finishing is the better exit. Interactive runs are asked;
264
+ --brief-file finishes.
225
265
  """
226
266
  console.print(
227
267
  f"\n[yellow]That question has been answered {MAX_ANSWER_ATTEMPTS} times "
@@ -237,29 +277,22 @@ def _handle_answer_attempts_exhausted(session, answers: "_AnswerSource", questio
237
277
  )
238
278
  raise typer.Exit(1)
239
279
  if not answers.interactive:
240
- # --brief-file: there is no list to desynchronise, so repeated rejection
241
- # means the brief does not cover what is being asked.
242
- console.print(
243
- "[red]Error:[/red] giving up in non-interactive mode. The stand-in "
244
- "answered from the brief five times without being accepted, which "
245
- "usually means the brief does not cover what this question asks:\n\n"
246
- f" {escape(question.get('text', ''))}\n\n"
247
- "Extend the brief to cover it, or run interactively."
248
- )
249
- raise typer.Exit(1)
280
+ return _finish_non_interactive(session, question)
250
281
 
251
282
  console.print(
252
283
  "[dim]Questions often have two parts; make sure the answer covers all of "
253
284
  "them. You can also type /pause to save and come back.[/dim]"
254
285
  )
255
- if not typer.confirm("Keep trying this question?", default=True):
256
- blocker_id = session.pause_discovery("Stuck on a question")
257
- console.print("\n[green]✓[/green] Session paused")
258
- console.print(
259
- f"To resume: [cyan]cf prd generate --resume {blocker_id[:8]}[/cyan]"
260
- )
261
- return False
262
- return True
286
+ if typer.confirm("Keep trying this question?", default=True):
287
+ return True
288
+ if _offer_finish(session):
289
+ return True
290
+ blocker_id = session.pause_discovery("Stuck on a question")
291
+ console.print("\n[green]✓[/green] Session paused")
292
+ console.print(
293
+ f"To resume: [cyan]cf prd generate --resume {blocker_id[:8]}[/cyan]"
294
+ )
295
+ return False
263
296
 
264
297
 
265
298
  def _load_answers_file(path: Path) -> list[str]:
@@ -1615,6 +1648,17 @@ def prd_generate(
1615
1648
  "survives a rejected answer."
1616
1649
  ),
1617
1650
  ),
1651
+ max_questions: Optional[int] = typer.Option(
1652
+ None,
1653
+ "--max-questions",
1654
+ min=1,
1655
+ help=(
1656
+ "Finish discovery after this many answers, for this run only "
1657
+ "(like --template, repeat it on --resume). Set "
1658
+ "discovery_max_questions in .codeframe/config.yaml to make it "
1659
+ "stick; the default is 10."
1660
+ ),
1661
+ ),
1618
1662
  ) -> None:
1619
1663
  """Generate a PRD through AI-driven Socratic discovery.
1620
1664
 
@@ -1631,7 +1675,11 @@ def prd_generate(
1631
1675
  - Determines when enough information has been gathered
1632
1676
  - Generates the final PRD from the conversation
1633
1677
 
1678
+ Discovery stops after --max-questions answers, or sooner once coverage
1679
+ stops improving; areas still uncovered become open questions in the PRD.
1680
+
1634
1681
  Special commands during discovery:
1682
+ /done - Finish now and generate the PRD from what's been answered
1635
1683
  /pause - Save progress and exit (creates a blocker for resume)
1636
1684
  /quit - Exit without saving
1637
1685
  /help - Show available commands
@@ -1750,6 +1798,10 @@ def prd_generate(
1750
1798
  console.print("\n[dim]Set the API key named above to use AI discovery.[/dim]")
1751
1799
  raise typer.Exit(1)
1752
1800
 
1801
+ if max_questions is not None:
1802
+ session.max_questions = max_questions
1803
+ session.complete_if_capped()
1804
+
1753
1805
  console.print("\n[bold]Starting AI-driven PRD discovery...[/bold]")
1754
1806
  console.print("[dim]The AI will ask questions to understand your project.[/dim]")
1755
1807
  console.print("[dim]Type /help for available commands[/dim]\n")
@@ -1787,7 +1839,10 @@ def prd_generate(
1787
1839
  progress_bar = "█" * int(pct // 5)
1788
1840
  progress_empty = "░" * (20 - len(progress_bar))
1789
1841
 
1790
- console.print(f"[dim]Question {question['question_number']} | Coverage: {pct}%[/dim]")
1842
+ console.print(
1843
+ f"[dim]Question {question['question_number']} of at most "
1844
+ f"{progress.get('max_questions')} | Coverage: {pct}%[/dim]"
1845
+ )
1791
1846
  console.print(f"[dim]{progress_bar}{progress_empty}[/dim]\n")
1792
1847
 
1793
1848
  # Show question
@@ -1803,6 +1858,8 @@ def prd_generate(
1803
1858
  session, answers, question
1804
1859
  ):
1805
1860
  return
1861
+ if session.is_complete():
1862
+ break
1806
1863
  attempts = 1
1807
1864
 
1808
1865
  answer = answers.ask(question["text"])
@@ -1814,12 +1871,22 @@ def prd_generate(
1814
1871
  # Handle special commands
1815
1872
  if answer.lower() == "/help":
1816
1873
  console.print("\n[bold]Available commands:[/bold]")
1874
+ console.print(" /done - Finish now and generate the PRD")
1817
1875
  console.print(" /pause - Save progress and exit")
1818
1876
  console.print(" /quit - Exit without saving")
1819
1877
  console.print(" /help - Show this help")
1820
1878
  console.print()
1821
1879
  continue
1822
1880
 
1881
+ if answer.lower() == "/done":
1882
+ if not session.answered_count:
1883
+ console.print(
1884
+ "[yellow]Answer at least one question before finishing.[/yellow]"
1885
+ )
1886
+ continue
1887
+ session.finish_now()
1888
+ break
1889
+
1823
1890
  if answer.lower() == "/quit":
1824
1891
  if typer.confirm("Exit without saving?"):
1825
1892
  console.print("Cancelled.")
@@ -22,7 +22,13 @@ from enum import Enum
22
22
  from pathlib import Path
23
23
  from typing import AsyncIterator, Callable, Optional
24
24
 
25
- from codeframe.adapters.llm.base import LLMProvider, Tool, ToolCall, ToolResult
25
+ from codeframe.adapters.llm.base import (
26
+ DEFAULT_PLANNING_MODEL,
27
+ LLMProvider,
28
+ Tool,
29
+ ToolCall,
30
+ ToolResult,
31
+ )
26
32
  from codeframe.core.spend_limit import SpendLimitExceeded
27
33
  from codeframe.core.usage_recording import charge_budget, check_budget, mark_unrecorded
28
34
  from codeframe.lib.metrics_tracker import MetricsTracker
@@ -36,10 +42,11 @@ from codeframe.core.tools import (
36
42
  logger = logging.getLogger(__name__)
37
43
 
38
44
  # ---------------------------------------------------------------------------
39
- # Default model (matches DEFAULT_PLANNING_MODEL in base.py)
45
+ # Default model: the planning default, so it moves with base.py instead of
46
+ # drifting onto a retired ID (#1348)
40
47
  # ---------------------------------------------------------------------------
41
48
 
42
- _DEFAULT_MODEL = "claude-sonnet-4-5"
49
+ _DEFAULT_MODEL = DEFAULT_PLANNING_MODEL
43
50
 
44
51
  # Maximum token budget for conversation history passed to the API.
45
52
  # claude-sonnet-4 context window is 200k; leave 20k for response headroom.
@@ -225,6 +225,9 @@ class EnvironmentConfig:
225
225
  # Settings page (issue #554) — UI-managed agent settings
226
226
  max_cost_usd: Optional[float] = None
227
227
 
228
+ # PRD discovery question cap (#1443); None means the default of 10.
229
+ discovery_max_questions: Optional[int] = None
230
+
228
231
  def validate(self) -> list[str]:
229
232
  """Validate configuration values.
230
233