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.
- {codeframe_ai-0.9.4/codeframe_ai.egg-info → codeframe_ai-0.9.5}/PKG-INFO +3 -2
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/README.md +2 -1
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/adapters/llm/base.py +7 -5
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/cli/app.py +90 -23
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/adapters/streaming_chat.py +10 -3
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/config.py +3 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/prd_discovery.py +325 -37
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/lib/metrics_tracker.py +9 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/ui/routers/discovery_v2.py +48 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5/codeframe_ai.egg-info}/PKG-INFO +3 -2
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/pyproject.toml +1 -1
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/LICENSE +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/__init__.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/__main__.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/adapters/__init__.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/adapters/e2b/__init__.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/adapters/e2b/adapter.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/adapters/e2b/budget.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/adapters/e2b/credential_scanner.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/adapters/llm/__init__.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/adapters/llm/anthropic.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/adapters/llm/errors.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/adapters/llm/mock.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/adapters/llm/openai.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/agents/__init__.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/agents/dependency_resolver.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/auth/__init__.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/auth/api_key_router.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/auth/api_keys.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/auth/dependencies.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/auth/manager.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/auth/models.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/auth/router.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/auth/schemas.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/auth/scopes.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/auth/stream_tickets.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/cli/__init__.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/cli/__main__.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/cli/api_client.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/cli/auth.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/cli/auth_commands.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/cli/config_commands.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/cli/dashboard_commands.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/cli/engines_commands.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/cli/env_commands.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/cli/helpers.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/cli/hooks_commands.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/cli/import_commands.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/cli/pr_commands.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/cli/proof_commands.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/cli/stats_commands.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/cli/telemetry_runtime.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/cli/validators.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/config/rate_limits.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/__init__.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/adapters/__init__.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/adapters/agent_adapter.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/adapters/builtin.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/adapters/claude_code.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/adapters/codex.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/adapters/git_utils.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/adapters/kilocode.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/adapters/opencode.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/adapters/subprocess_adapter.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/adapters/verification_wrapper.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/agent.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/agent_env.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/agents_config.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/api_key_service.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/artifacts.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/atomic_io.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/blocker_detection.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/blockers.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/checkpoints.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/claude_code_guard.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/conductor.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/config_watcher.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/context.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/context_packager.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/cost_tracker.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/credentials.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/dangerous_commands.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/dependency_analyzer.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/dependency_graph.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/diagnostic_agent.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/diagnostics.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/editor.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/engine_registry.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/engine_stats.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/env_provenance.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/environment.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/events.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/executor.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/fix_tracker.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/gates.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/git.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/github_connect_service.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/github_integration_config.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/github_issues_service.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/hook_trust.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/hooks.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/importers/__init__.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/importers/ralph.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/installer.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/llm_json.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/llm_resolution.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/models.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/notifications_config.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/path_safety.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/planner.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/prd.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/prd_stress_test.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/progress.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/proof/__init__.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/proof/capture.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/proof/evidence.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/proof/ledger.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/proof/models.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/proof/obligations.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/proof/report.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/proof/runner.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/proof/scope.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/proof/stubs.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/quick_fixes.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/react_agent.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/reconciliation.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/replay.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/review.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/run_control.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/runtime.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/sandbox/__init__.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/sandbox/context.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/sandbox/worktree.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/schedule.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/spend_limit.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/stall_detector.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/stall_monitor.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/state_machine.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/streaming.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/task_tree.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/tasks.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/tech_stack.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/telemetry.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/templates.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/tools.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/usage_recording.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/workspace.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/core/worktrees.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/git/__init__.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/git/github_integration.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/lib/__init__.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/lib/audit_logger.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/lib/quality/__init__.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/lib/quality/complexity_analyzer.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/lib/quality/owasp_patterns.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/lib/quality/security_scanner.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/lib/rate_limiter.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/notifications/__init__.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/notifications/webhook.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/planning/__init__.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/planning/prd_templates.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/planning/task_scheduler.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/planning/task_templates.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/platform_store/__init__.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/platform_store/database.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/platform_store/repositories/__init__.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/platform_store/repositories/api_key_repository.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/platform_store/repositories/audit_repository.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/platform_store/repositories/base.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/platform_store/repositories/interactive_sessions.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/platform_store/repositories/token_repository.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/platform_store/repositories/workspace_registry_repository.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/platform_store/schema_manager.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/templates/AGENTS.md.default +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/tui/__init__.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/tui/app.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/tui/data_service.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/ui/__init__.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/ui/dependencies.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/ui/models.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/ui/response_models.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/ui/routers/__init__.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/ui/routers/_helpers.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/ui/routers/batches_v2.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/ui/routers/blockers_v2.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/ui/routers/checkpoints_v2.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/ui/routers/costs_v2.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/ui/routers/diagnose_v2.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/ui/routers/environment_v2.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/ui/routers/events_v2.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/ui/routers/gates_v2.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/ui/routers/git_v2.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/ui/routers/github_integrations_v2.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/ui/routers/interactive_sessions_v2.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/ui/routers/pr_v2.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/ui/routers/prd_v2.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/ui/routers/proof_v2.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/ui/routers/review_v2.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/ui/routers/schedule_v2.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/ui/routers/session_chat_ws.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/ui/routers/settings_v2.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/ui/routers/tasks_v2.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/ui/routers/templates_v2.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/ui/routers/terminal_ws.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/ui/routers/workspace_v2.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/ui/server.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/ui/shared.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe/ui/streaming_utils.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe_ai.egg-info/SOURCES.txt +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe_ai.egg-info/dependency_links.txt +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe_ai.egg-info/entry_points.txt +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe_ai.egg-info/requires.txt +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/codeframe_ai.egg-info/top_level.txt +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/setup.cfg +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/tests/test_ambient_workspace_guard.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/tests/test_claude_review_workflow_1011.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/tests/test_deploy_audit_gate_1131.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/tests/test_deploy_config.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/tests/test_design_partners_619.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/tests/test_lifecycle_gates_948.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/tests/test_offline_default_946.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/tests/test_ops_hygiene_969.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/tests/test_pm2_scoping_912.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/tests/test_roadmap_status_1246.py +0 -0
- {codeframe_ai-0.9.4 → codeframe_ai-0.9.5}/tests/test_root_docs_950.py +0 -0
- {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.
|
|
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.
|
|
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.
|
|
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
|
-
|
|
65
|
-
|
|
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-
|
|
68
|
-
DEFAULT_SUPERVISION_MODEL = "claude-sonnet-
|
|
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
|
-
|
|
223
|
-
resynchronise by being fed more of itself.
|
|
224
|
-
|
|
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
|
-
|
|
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
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
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(
|
|
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
|
|
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
|
|
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 =
|
|
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
|
|