ouroboros-ai 0.26.5.dev6__tar.gz → 0.26.5.dev8__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.
Potentially problematic release.
This version of ouroboros-ai might be problematic. Click here for more details.
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/PKG-INFO +1 -1
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/skills/pm/SKILL.md +5 -1
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/_version.py +2 -2
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/cli/commands/init.py +17 -7
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/cli/commands/pm.py +43 -0
- ouroboros_ai-0.26.5.dev8/src/ouroboros/core/initial_context.py +209 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/mcp/tools/authoring_handlers.py +12 -2
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/mcp/tools/pm_handler.py +13 -3
- ouroboros_ai-0.26.5.dev8/src/ouroboros/pm/handoff.py +18 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/providers/claude_code_adapter.py +44 -8
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/providers/codex_cli_adapter.py +14 -4
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/providers/factory.py +10 -1
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/cli/test_init_pm_seed_detection.py +34 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/cli/test_pm_completion.py +14 -4
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/cli/test_pm_overwrite.py +81 -1
- ouroboros_ai-0.26.5.dev8/tests/unit/core/test_initial_context.py +117 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/mcp/tools/test_definitions.py +46 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/mcp/tools/test_pm_handler_generate.py +45 -4
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/providers/test_claude_code_adapter.py +63 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/providers/test_codex_cli_adapter.py +20 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/providers/test_factory.py +35 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/.claude/settings.json +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/.claude-plugin/.mcp.json +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/.claude-plugin/marketplace.json +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/.claude-plugin/plugin.json +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/.env.example +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/.github/ISSUE_TEMPLATE/config.yml +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/.github/ISSUE_TEMPLATE/feature_request.yml +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/.github/ISSUE_TEMPLATE/question.yml +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/.github/workflows/dev-publish.yml +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/.github/workflows/lint.yml +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/.github/workflows/release.yml +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/.github/workflows/test.yml +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/.gitignore +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/.mcp.json +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/.ouroboros/mechanical.toml +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/.pre-commit-config.yaml +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/.python-version +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/CHANGELOG.md +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/CLAUDE.md +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/CODE_OF_CONDUCT.md +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/CONTRIBUTING.md +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/HANDOFF.md +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/LICENSE +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/README.ko.md +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/README.md +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/SECURITY.md +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/UNINSTALL.md +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/commands/cancel.md +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/commands/evaluate.md +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/commands/evolve.md +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/commands/help.md +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/commands/interview.md +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/commands/ralph.md +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/commands/run.md +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/commands/seed.md +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/commands/setup.md +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/commands/status.md +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/commands/tutorial.md +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/commands/unstuck.md +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/commands/welcome.md +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/crates/ouroboros-tui/.gitignore +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/crates/ouroboros-tui/Cargo.lock +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/crates/ouroboros-tui/Cargo.toml +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/crates/ouroboros-tui/README.md +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/crates/ouroboros-tui/src/db.rs +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/crates/ouroboros-tui/src/main.rs +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/crates/ouroboros-tui/src/mock.rs +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/crates/ouroboros-tui/src/state.rs +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/crates/ouroboros-tui/src/views/dashboard.rs +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/crates/ouroboros-tui/src/views/execution.rs +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/crates/ouroboros-tui/src/views/lineage.rs +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/crates/ouroboros-tui/src/views/logs.rs +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/crates/ouroboros-tui/src/views/mod.rs +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/crates/ouroboros-tui/src/views/session_selector.rs +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/docs/README.md +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/docs/api/README.md +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/docs/api/core.md +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/docs/api/mcp.md +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/docs/architecture.md +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/docs/cli-reference.md +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/docs/config-reference.md +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/docs/contributing/architecture-overview.md +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/docs/contributing/findings-registry.md +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/docs/contributing/issue-quality-policy.md +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/docs/contributing/key-patterns.md +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/docs/contributing/testing-guide.md +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/docs/examples/mcp-config.yaml +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/docs/getting-started.md +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/docs/guides/evaluation-pipeline.md +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/docs/guides/evolution-loop.md +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/docs/guides/issue-176-subagent-mcp-inheritance.md +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/docs/guides/seed-authoring.md +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/docs/guides/tui-usage.md +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/docs/images/PLACEHOLDER_README.md +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/docs/images/ouroboros.png +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/docs/platform-support.md +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/docs/runtime-capability-matrix.md +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/docs/runtime-guides/claude-code.md +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/docs/runtime-guides/codex.md +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/examples/coordinator_test_seed.yaml +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/examples/dummy_seed.yaml +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/examples/parallel_subac_test_seed.yaml +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/examples/subac_test_seed.yaml +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/examples/task_manager/README.md +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/examples/task_manager/__init__.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/examples/task_manager/__main__.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/examples/task_manager/cli.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/examples/task_manager/models.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/examples/task_manager/storage.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/examples/test_display.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/hooks/hooks.json +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/llms-full.txt +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/llms.txt +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/project-context.md +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/pyproject.toml +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/scripts/drift-monitor.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/scripts/install.sh +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/scripts/keyword-detector.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/scripts/mcp-serve.sh +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/scripts/ralph-rewind.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/scripts/ralph.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/scripts/ralph.sh +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/scripts/session-start.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/scripts/sync-plugin-version.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/scripts/version-check.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/skills/brownfield/SKILL.md +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/skills/cancel/SKILL.md +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/skills/evaluate/SKILL.md +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/skills/evolve/SKILL.md +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/skills/help/SKILL.md +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/skills/interview/SKILL.md +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/skills/qa/SKILL.md +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/skills/ralph/SKILL.md +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/skills/run/SKILL.md +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/skills/seed/SKILL.md +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/skills/setup/SKILL.md +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/skills/status/SKILL.md +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/skills/tutorial/SKILL.md +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/skills/unstuck/SKILL.md +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/skills/update/SKILL.md +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/skills/welcome/SKILL.md +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/__init__.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/__main__.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/agents/__init__.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/agents/advocate.md +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/agents/analysis-agent.md +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/agents/architect.md +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/agents/breadth-keeper.md +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/agents/code-executor.md +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/agents/codebase-explorer.md +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/agents/consensus-reviewer.md +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/agents/contrarian.md +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/agents/evaluator.md +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/agents/hacker.md +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/agents/judge.md +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/agents/loader.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/agents/ontologist.md +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/agents/ontology-analyst.md +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/agents/qa-judge.md +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/agents/research-agent.md +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/agents/researcher.md +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/agents/seed-architect.md +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/agents/seed-closer.md +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/agents/semantic-evaluator.md +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/agents/simplifier.md +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/agents/socratic-interviewer.md +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/bigbang/__init__.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/bigbang/ambiguity.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/bigbang/brownfield.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/bigbang/explore.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/bigbang/interview.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/bigbang/pm_completion.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/bigbang/pm_document.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/bigbang/pm_interview.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/bigbang/pm_seed.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/bigbang/question_classifier.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/bigbang/seed_generator.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/cli/__init__.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/cli/commands/__init__.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/cli/commands/cancel.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/cli/commands/config.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/cli/commands/mcp.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/cli/commands/run.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/cli/commands/setup.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/cli/commands/status.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/cli/commands/tui.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/cli/commands/uninstall.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/cli/formatters/__init__.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/cli/formatters/panels.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/cli/formatters/progress.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/cli/formatters/prompting.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/cli/formatters/tables.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/cli/formatters/workflow_display.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/cli/main.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/codex/__init__.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/codex/artifacts.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/codex/ouroboros.md +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/codex_permissions.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/config/__init__.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/config/loader.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/config/models.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/core/__init__.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/core/ac_tree.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/core/context.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/core/errors.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/core/file_lock.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/core/git_workflow.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/core/lineage.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/core/ontology_aspect.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/core/ontology_questions.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/core/project_paths.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/core/security.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/core/seed.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/core/text.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/core/types.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/core/worktree.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/evaluation/__init__.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/evaluation/artifact_collector.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/evaluation/consensus.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/evaluation/json_utils.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/evaluation/languages.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/evaluation/mechanical.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/evaluation/models.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/evaluation/pipeline.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/evaluation/semantic.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/evaluation/trigger.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/evaluation/verification_artifacts.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/events/__init__.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/events/base.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/events/decomposition.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/events/evaluation.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/events/interview.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/events/lineage.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/events/ontology.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/evolution/__init__.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/evolution/convergence.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/evolution/loop.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/evolution/projector.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/evolution/reflect.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/evolution/regression.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/evolution/wonder.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/execution/__init__.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/execution/atomicity.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/execution/decomposition.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/execution/double_diamond.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/execution/subagent.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/mcp/__init__.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/mcp/client/__init__.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/mcp/client/adapter.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/mcp/client/manager.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/mcp/client/protocol.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/mcp/errors.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/mcp/job_manager.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/mcp/resources/__init__.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/mcp/resources/handlers.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/mcp/server/__init__.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/mcp/server/adapter.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/mcp/server/protocol.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/mcp/server/security.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/mcp/tools/__init__.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/mcp/tools/brownfield_handler.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/mcp/tools/dashboard.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/mcp/tools/definitions.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/mcp/tools/evaluation_handlers.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/mcp/tools/evolution_handlers.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/mcp/tools/execution_handlers.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/mcp/tools/job_handlers.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/mcp/tools/qa.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/mcp/tools/query_handlers.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/mcp/tools/registry.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/mcp/types.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/observability/__init__.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/observability/drift.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/observability/logging.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/observability/retrospective.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/orchestrator/__init__.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/orchestrator/adapter.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/orchestrator/codex_cli_runtime.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/orchestrator/command_dispatcher.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/orchestrator/coordinator.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/orchestrator/dependency_analyzer.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/orchestrator/events.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/orchestrator/execution_runtime_scope.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/orchestrator/execution_strategy.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/orchestrator/heartbeat.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/orchestrator/level_context.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/orchestrator/mcp_config.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/orchestrator/mcp_tools.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/orchestrator/parallel_executor.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/orchestrator/parallel_executor_models.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/orchestrator/runner.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/orchestrator/runtime_factory.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/orchestrator/runtime_message_projection.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/orchestrator/session.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/orchestrator/workflow_state.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/persistence/__init__.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/persistence/brownfield.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/persistence/checkpoint.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/persistence/event_store.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/persistence/migrations/__init__.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/persistence/migrations/runner.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/persistence/migrations/scripts/001_initial.sql +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/persistence/migrations/scripts/002_brownfield.sql +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/persistence/schema.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/persistence/uow.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/plugin/__init__.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/plugin/agents/__init__.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/plugin/agents/pool.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/plugin/agents/registry.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/plugin/orchestration/__init__.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/plugin/orchestration/router.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/plugin/orchestration/scheduler.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/plugin/skills/__init__.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/plugin/skills/docs.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/plugin/skills/executor.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/plugin/skills/keywords.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/plugin/skills/registry.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/pm/__init__.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/pm/renderer.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/providers/__init__.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/providers/anthropic_adapter.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/providers/base.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/providers/codex_cli_stream.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/providers/litellm_adapter.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/py.typed +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/resilience/__init__.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/resilience/lateral.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/resilience/stagnation.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/routing/__init__.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/routing/complexity.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/routing/downgrade.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/routing/escalation.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/routing/router.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/routing/tiers.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/secondary/__init__.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/secondary/scheduler.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/secondary/todo_registry.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/strategies/__init__.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/strategies/devil_advocate.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/tui/__init__.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/tui/app.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/tui/components/__init__.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/tui/components/agents_panel.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/tui/components/event_log.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/tui/components/progress.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/tui/components/token_tracker.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/tui/events.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/tui/screens/__init__.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/tui/screens/confirm_rewind.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/tui/screens/dashboard.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/tui/screens/dashboard_v2.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/tui/screens/dashboard_v3.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/tui/screens/debug.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/tui/screens/execution.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/tui/screens/hud_dashboard.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/tui/screens/lineage_detail.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/tui/screens/lineage_selector.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/tui/screens/logs.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/tui/screens/session_selector.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/tui/widgets/__init__.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/tui/widgets/ac_progress.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/tui/widgets/ac_tree.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/tui/widgets/agent_activity.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/tui/widgets/cost_tracker.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/tui/widgets/drift_meter.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/tui/widgets/lineage_tree.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/tui/widgets/parallel_graph.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/tui/widgets/phase_progress.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/verification/__init__.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/verification/extractor.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/verification/models.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/verification/verifier.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/__init__.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/conftest.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/e2e/__init__.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/e2e/conftest.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/e2e/test_cli_commands.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/e2e/test_full_workflow.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/e2e/test_session_persistence.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/fixtures/test_atomicity_seed.yml +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/integration/__init__.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/integration/conftest.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/integration/mcp/__init__.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/integration/mcp/conftest.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/integration/mcp/test_client_adapter.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/integration/mcp/test_client_manager.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/integration/mcp/test_server_adapter.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/integration/plugin/test_orchestration.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/integration/test_codex_cli_passthrough_smoke.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/integration/test_codex_skill_fallback.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/integration/test_codex_skill_smoke.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/integration/test_entry_point.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/__init__.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/agents/__init__.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/agents/test_loader.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/bigbang/__init__.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/bigbang/test_ambiguity.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/bigbang/test_brownfield.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/bigbang/test_classifier_context.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/bigbang/test_decide_later_items.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/bigbang/test_explore.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/bigbang/test_interview.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/bigbang/test_pm_completion.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/bigbang/test_pm_document_generator.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/bigbang/test_pm_document_writer.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/bigbang/test_pm_interview.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/bigbang/test_pm_interview_brownfield_db.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/bigbang/test_pm_seed_ac12.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/bigbang/test_pm_seed_save.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/bigbang/test_question_classifier.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/bigbang/test_seed_generator.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/cli/__init__.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/cli/formatters/__init__.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/cli/formatters/test_console.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/cli/formatters/test_panels.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/cli/formatters/test_progress.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/cli/formatters/test_prompting.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/cli/formatters/test_tables.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/cli/formatters/test_workflow_display.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/cli/test_cancel.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/cli/test_config.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/cli/test_init_runtime.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/cli/test_main.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/cli/test_mcp_nested_guard.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/cli/test_mcp_startup_cleanup.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/cli/test_pm.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/cli/test_pm_brownfield.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/cli/test_pm_interactive_logging.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/cli/test_pm_missing_litellm.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/cli/test_pm_runtime_adapter.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/cli/test_pm_select_repos.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/cli/test_run_qa.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/cli/test_setup.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/cli/test_uninstall.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/config/__init__.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/config/test_loader.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/config/test_models.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/core/__init__.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/core/test_ac_tree.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/core/test_context.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/core/test_errors.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/core/test_git_workflow.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/core/test_lineage.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/core/test_ontology_aspect.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/core/test_ontology_questions.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/core/test_security.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/core/test_seed.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/core/test_types.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/core/test_worktree.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/evaluation/__init__.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/evaluation/test_consensus.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/evaluation/test_json_utils.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/evaluation/test_languages.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/evaluation/test_mechanical.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/evaluation/test_models.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/evaluation/test_semantic.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/evaluation/test_trigger.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/evaluation/test_verification_artifacts.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/events/__init__.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/events/test_base.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/events/test_decomposition_events.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/evolution/test_wonder_scope.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/execution/__init__.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/execution/test_atomicity.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/execution/test_decomposition.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/execution/test_double_diamond.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/execution/test_subagent_isolation.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/mcp/__init__.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/mcp/client/__init__.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/mcp/client/test_adapter.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/mcp/client/test_manager.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/mcp/conftest.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/mcp/server/__init__.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/mcp/server/test_adapter.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/mcp/server/test_security.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/mcp/test_errors.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/mcp/test_job_manager.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/mcp/test_types.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/mcp/tools/__init__.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/mcp/tools/conftest.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/mcp/tools/test_brownfield_handler.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/mcp/tools/test_pm_handler.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/mcp/tools/test_pm_handler_pending_reframe.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/mcp/tools/test_qa_integration.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/mcp/tools/test_registry.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/observability/__init__.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/observability/test_drift.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/observability/test_logging.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/observability/test_retrospective.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/orchestrator/__init__.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/orchestrator/test_adapter.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/orchestrator/test_codex_cli_runtime.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/orchestrator/test_codex_recursion_guard.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/orchestrator/test_command_dispatcher.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/orchestrator/test_coordinator.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/orchestrator/test_dependency_analyzer.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/orchestrator/test_events.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/orchestrator/test_execution_runtime_scope.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/orchestrator/test_execution_strategy.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/orchestrator/test_inflight_cancellation.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/orchestrator/test_level_context.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/orchestrator/test_mcp_config.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/orchestrator/test_mcp_tools.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/orchestrator/test_parallel_executor.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/orchestrator/test_parallel_executor_retry_resume.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/orchestrator/test_runner.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/orchestrator/test_runner_cancellation.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/orchestrator/test_runtime_factory.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/orchestrator/test_runtime_message_projection.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/orchestrator/test_session.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/orchestrator/test_workflow_state.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/persistence/__init__.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/persistence/test_brownfield_store.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/persistence/test_checkpoint.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/persistence/test_event_store.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/persistence/test_schema.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/persistence/test_uow.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/plugin/__init__.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/plugin/agents/__init__.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/plugin/agents/test_registry.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/plugin/orchestration/__init__.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/plugin/orchestration/test_model_router.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/plugin/skills/__init__.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/plugin/skills/test_keywords.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/plugin/skills/test_registry.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/pm/__init__.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/pm/test_renderer.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/providers/__init__.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/providers/test_base.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/providers/test_litellm_adapter.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/resilience/__init__.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/resilience/test_lateral.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/resilience/test_stagnation.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/routing/__init__.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/routing/test_complexity.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/routing/test_downgrade.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/routing/test_escalation.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/routing/test_router.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/routing/test_tiers.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/scripts/test_keyword_detector.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/scripts/test_version_check.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/secondary/__init__.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/secondary/test_scheduler.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/secondary/test_todo_registry.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/test_artifact_collector.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/test_codex_artifacts.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/test_convergence.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/test_dashboard.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/test_dependencies_configured.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/test_evolve_rewind.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/test_evolve_step.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/test_graceful_shutdown.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/test_main_entry_point.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/test_module_structure.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/test_project_initialization.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/test_projector_rewind.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/test_ralph_parser.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/test_ralph_rewind.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/test_regression.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/test_tooling_configuration.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/test_verification.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/tui/__init__.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/tui/test_app.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/tui/test_cancelled_display.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/tui/test_events.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/tui/test_lineage_viewer.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/tui/test_screens.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/tui/test_session_selector_replay.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/tui/test_widgets.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tools/sync_github_project.py +0 -0
- {ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/uv.lock +0 -0
|
@@ -120,6 +120,10 @@ Show the following to the user:
|
|
|
120
120
|
PM document saved: <meta.pm_path>
|
|
121
121
|
(Clipboard에 복사되었습니다)
|
|
122
122
|
|
|
123
|
+
PM seed handoff artifact: <meta.pm_seed_path or meta.seed_path>
|
|
124
|
+
This is not the runnable Seed yet.
|
|
125
|
+
|
|
123
126
|
Next step:
|
|
124
|
-
ooo interview <meta.
|
|
127
|
+
ooo interview <meta.pm_seed_path or meta.seed_path>
|
|
128
|
+
ooo seed
|
|
125
129
|
```
|
|
@@ -18,7 +18,7 @@ version_tuple: tuple[int | str, ...]
|
|
|
18
18
|
commit_id: str | None
|
|
19
19
|
__commit_id__: str | None
|
|
20
20
|
|
|
21
|
-
__version__ = version = '0.26.5.
|
|
22
|
-
__version_tuple__ = version_tuple = (0, 26, 5, '
|
|
21
|
+
__version__ = version = '0.26.5.dev8'
|
|
22
|
+
__version_tuple__ = version_tuple = (0, 26, 5, 'dev8')
|
|
23
23
|
|
|
24
24
|
__commit_id__ = commit_id = None
|
|
@@ -26,6 +26,12 @@ from ouroboros.cli.formatters import console
|
|
|
26
26
|
from ouroboros.cli.formatters.panels import print_error, print_info, print_success, print_warning
|
|
27
27
|
from ouroboros.cli.formatters.prompting import multiline_prompt_async
|
|
28
28
|
from ouroboros.config import get_clarification_model
|
|
29
|
+
from ouroboros.core.initial_context import (
|
|
30
|
+
load_pm_seed_as_context as _load_pm_seed_as_context_result,
|
|
31
|
+
)
|
|
32
|
+
from ouroboros.core.initial_context import (
|
|
33
|
+
resolve_initial_context_input,
|
|
34
|
+
)
|
|
29
35
|
from ouroboros.observability import LoggingConfig, configure_logging
|
|
30
36
|
from ouroboros.providers import create_llm_adapter
|
|
31
37
|
from ouroboros.providers.base import LLMAdapter
|
|
@@ -619,13 +625,10 @@ def _load_pm_seed_as_context(seed_path: Path) -> str:
|
|
|
619
625
|
Returns:
|
|
620
626
|
YAML-formatted string for use as dev interview initial_context.
|
|
621
627
|
"""
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
pm_seed = PMSeed.from_dict(data)
|
|
628
|
-
return pm_seed.to_initial_context()
|
|
628
|
+
result = _load_pm_seed_as_context_result(seed_path)
|
|
629
|
+
if result.is_err:
|
|
630
|
+
raise ValueError(str(result.error))
|
|
631
|
+
return result.value
|
|
629
632
|
|
|
630
633
|
|
|
631
634
|
@app.command()
|
|
@@ -752,6 +755,13 @@ def start(
|
|
|
752
755
|
|
|
753
756
|
context = asyncio.run(multiline_prompt_async("What would you like to build?"))
|
|
754
757
|
|
|
758
|
+
if context:
|
|
759
|
+
resolved_context = resolve_initial_context_input(context, cwd=Path.cwd())
|
|
760
|
+
if resolved_context.is_err:
|
|
761
|
+
print_error(str(resolved_context.error))
|
|
762
|
+
raise typer.Exit(code=1)
|
|
763
|
+
context = resolved_context.value
|
|
764
|
+
|
|
755
765
|
if not resume and not context:
|
|
756
766
|
print_error("Initial context is required when not resuming.")
|
|
757
767
|
raise typer.Exit(code=1)
|
|
@@ -27,6 +27,7 @@ from ouroboros.cli.formatters.prompting import multiline_prompt_async
|
|
|
27
27
|
from ouroboros.config import get_clarification_model, get_llm_backend
|
|
28
28
|
from ouroboros.core.types import Result
|
|
29
29
|
from ouroboros.observability import LoggingConfig, configure_logging
|
|
30
|
+
from ouroboros.pm.handoff import build_pm_dev_handoff_command
|
|
30
31
|
from ouroboros.providers.factory import (
|
|
31
32
|
create_llm_adapter,
|
|
32
33
|
resolve_llm_backend,
|
|
@@ -384,6 +385,32 @@ def _make_message_callback(debug: bool):
|
|
|
384
385
|
return callback
|
|
385
386
|
|
|
386
387
|
|
|
388
|
+
async def _continue_into_dev_interview(
|
|
389
|
+
seed_path: Path,
|
|
390
|
+
*,
|
|
391
|
+
debug: bool,
|
|
392
|
+
llm_backend: str | None,
|
|
393
|
+
) -> None:
|
|
394
|
+
"""Resolve a PM artifact path into interview context and start the dev interview."""
|
|
395
|
+
from ouroboros.cli.commands.init import _run_interview
|
|
396
|
+
from ouroboros.core.initial_context import resolve_initial_context_input
|
|
397
|
+
|
|
398
|
+
resolved_context = resolve_initial_context_input(str(seed_path), cwd=Path.cwd())
|
|
399
|
+
if resolved_context.is_err:
|
|
400
|
+
print_error(f"Failed to load PM seed for dev interview: {resolved_context.error.message}")
|
|
401
|
+
raise typer.Exit(code=1)
|
|
402
|
+
|
|
403
|
+
await _run_interview(
|
|
404
|
+
resolved_context.value,
|
|
405
|
+
resume_id=None,
|
|
406
|
+
state_dir=None,
|
|
407
|
+
use_orchestrator=False,
|
|
408
|
+
debug=debug,
|
|
409
|
+
workflow_runtime_backend=None,
|
|
410
|
+
llm_backend=llm_backend,
|
|
411
|
+
)
|
|
412
|
+
|
|
413
|
+
|
|
387
414
|
async def _run_pm_interview(
|
|
388
415
|
resume_id: str | None,
|
|
389
416
|
model: str,
|
|
@@ -667,6 +694,22 @@ async def _run_pm_interview(
|
|
|
667
694
|
pm_dir = Path(output_dir) if output_dir else Path.cwd() / ".ouroboros"
|
|
668
695
|
pm_path = save_pm_document(seed, output_dir=pm_dir)
|
|
669
696
|
print_success(f"PM document saved: {pm_path}")
|
|
697
|
+
|
|
698
|
+
print_info(
|
|
699
|
+
"The PM seed is a handoff artifact for the dev interview, not the runnable Seed."
|
|
700
|
+
)
|
|
701
|
+
print_info(f"Next: {build_pm_dev_handoff_command(seed_path)}")
|
|
702
|
+
|
|
703
|
+
continue_to_dev = Confirm.ask(
|
|
704
|
+
"Continue into the dev interview now?",
|
|
705
|
+
default=True,
|
|
706
|
+
)
|
|
707
|
+
if continue_to_dev:
|
|
708
|
+
await _continue_into_dev_interview(
|
|
709
|
+
seed_path,
|
|
710
|
+
debug=debug,
|
|
711
|
+
llm_backend=backend,
|
|
712
|
+
)
|
|
670
713
|
else:
|
|
671
714
|
print_error(f"Failed to generate PM: {seed_result.error}")
|
|
672
715
|
elif state.rounds and not state.is_complete:
|
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
"""Helpers for resolving interview initial context from text or files."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
|
|
7
|
+
import yaml
|
|
8
|
+
|
|
9
|
+
from ouroboros.bigbang.pm_seed import PMSeed
|
|
10
|
+
from ouroboros.core.errors import ValidationError
|
|
11
|
+
from ouroboros.core.security import InputValidator
|
|
12
|
+
from ouroboros.core.types import Result
|
|
13
|
+
|
|
14
|
+
_PM_SEED_SUFFIXES = {".json", ".yaml", ".yml"}
|
|
15
|
+
_TEXT_CONTEXT_SUFFIXES = {".md", ".markdown", ".txt", ".rst"}
|
|
16
|
+
_MAX_PATH_CANDIDATE_LENGTH = 240
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def _is_pm_seed_candidate(seed_path: Path, raw_data: object) -> bool:
|
|
20
|
+
"""Return True when a file should be treated as a PM-seed artifact."""
|
|
21
|
+
if seed_path.stem.startswith("pm_seed_"):
|
|
22
|
+
return True
|
|
23
|
+
if isinstance(raw_data, dict):
|
|
24
|
+
pm_id = raw_data.get("pm_id")
|
|
25
|
+
if isinstance(pm_id, str) and pm_id.startswith("pm_seed_"):
|
|
26
|
+
return True
|
|
27
|
+
return False
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def _validate_pm_seed_mapping(
|
|
31
|
+
raw_data: dict[object, object], seed_path: Path
|
|
32
|
+
) -> Result[None, ValidationError]:
|
|
33
|
+
"""Validate the minimum PM-seed contract before conversion."""
|
|
34
|
+
pm_id = raw_data.get("pm_id")
|
|
35
|
+
product_name = raw_data.get("product_name")
|
|
36
|
+
goal = raw_data.get("goal")
|
|
37
|
+
|
|
38
|
+
has_pm_seed_filename = seed_path.stem.startswith("pm_seed_")
|
|
39
|
+
has_pm_seed_id = isinstance(pm_id, str) and pm_id.startswith("pm_seed_")
|
|
40
|
+
|
|
41
|
+
if (
|
|
42
|
+
not isinstance(pm_id, str)
|
|
43
|
+
or (not pm_id.strip())
|
|
44
|
+
or (not has_pm_seed_id and not has_pm_seed_filename)
|
|
45
|
+
):
|
|
46
|
+
return Result.err(
|
|
47
|
+
ValidationError(
|
|
48
|
+
"PM seed file must include a non-empty pm_id and either a 'pm_seed_' filename or pm_id",
|
|
49
|
+
field="initial_context",
|
|
50
|
+
value=str(seed_path),
|
|
51
|
+
)
|
|
52
|
+
)
|
|
53
|
+
|
|
54
|
+
if not isinstance(product_name, str) or not product_name.strip():
|
|
55
|
+
return Result.err(
|
|
56
|
+
ValidationError(
|
|
57
|
+
"PM seed file must include a non-empty product_name",
|
|
58
|
+
field="initial_context",
|
|
59
|
+
value=str(seed_path),
|
|
60
|
+
)
|
|
61
|
+
)
|
|
62
|
+
|
|
63
|
+
if not isinstance(goal, str) or not goal.strip():
|
|
64
|
+
return Result.err(
|
|
65
|
+
ValidationError(
|
|
66
|
+
"PM seed file must include a non-empty goal",
|
|
67
|
+
field="initial_context",
|
|
68
|
+
value=str(seed_path),
|
|
69
|
+
)
|
|
70
|
+
)
|
|
71
|
+
|
|
72
|
+
return Result.ok(None)
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
def _resolve_path_candidate(
|
|
76
|
+
context_candidate: str,
|
|
77
|
+
*,
|
|
78
|
+
cwd: str | Path | None = None,
|
|
79
|
+
) -> Path | None:
|
|
80
|
+
"""Return a plausible file-path candidate, or None for literal text."""
|
|
81
|
+
if "\n" in context_candidate or len(context_candidate) > _MAX_PATH_CANDIDATE_LENGTH:
|
|
82
|
+
return None
|
|
83
|
+
|
|
84
|
+
try:
|
|
85
|
+
candidate_path = Path(context_candidate).expanduser()
|
|
86
|
+
except (OSError, ValueError):
|
|
87
|
+
return None
|
|
88
|
+
|
|
89
|
+
if not candidate_path.is_absolute() and cwd is not None:
|
|
90
|
+
candidate_path = Path(cwd).expanduser() / candidate_path
|
|
91
|
+
|
|
92
|
+
try:
|
|
93
|
+
if candidate_path.exists() and candidate_path.is_file():
|
|
94
|
+
return candidate_path
|
|
95
|
+
except OSError:
|
|
96
|
+
return None
|
|
97
|
+
|
|
98
|
+
return None
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
def load_pm_seed_as_context(seed_path: Path) -> Result[str, ValidationError]:
|
|
102
|
+
"""Load a PMSeed artifact and convert it into dev-interview context."""
|
|
103
|
+
try:
|
|
104
|
+
raw_data = yaml.safe_load(seed_path.read_text(encoding="utf-8"))
|
|
105
|
+
except (OSError, yaml.YAMLError) as exc:
|
|
106
|
+
return Result.err(
|
|
107
|
+
ValidationError(
|
|
108
|
+
f"Failed to load PM seed: {exc}",
|
|
109
|
+
field="initial_context",
|
|
110
|
+
value=str(seed_path),
|
|
111
|
+
)
|
|
112
|
+
)
|
|
113
|
+
|
|
114
|
+
if not isinstance(raw_data, dict):
|
|
115
|
+
return Result.err(
|
|
116
|
+
ValidationError(
|
|
117
|
+
"PM seed file must contain an object mapping",
|
|
118
|
+
field="initial_context",
|
|
119
|
+
value=str(seed_path),
|
|
120
|
+
)
|
|
121
|
+
)
|
|
122
|
+
|
|
123
|
+
validation_result = _validate_pm_seed_mapping(raw_data, seed_path)
|
|
124
|
+
if validation_result.is_err:
|
|
125
|
+
return validation_result
|
|
126
|
+
|
|
127
|
+
pm_seed = PMSeed.from_dict(raw_data)
|
|
128
|
+
context = pm_seed.to_initial_context()
|
|
129
|
+
is_valid, error_message = InputValidator.validate_initial_context(context)
|
|
130
|
+
if not is_valid:
|
|
131
|
+
return Result.err(
|
|
132
|
+
ValidationError(
|
|
133
|
+
error_message,
|
|
134
|
+
field="initial_context",
|
|
135
|
+
value=str(seed_path),
|
|
136
|
+
)
|
|
137
|
+
)
|
|
138
|
+
|
|
139
|
+
return Result.ok(context)
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
def resolve_initial_context_input(
|
|
143
|
+
initial_context: str,
|
|
144
|
+
*,
|
|
145
|
+
cwd: str | Path | None = None,
|
|
146
|
+
) -> Result[str, ValidationError]:
|
|
147
|
+
"""Resolve interview input from literal text or an existing file path."""
|
|
148
|
+
context_candidate = initial_context.strip()
|
|
149
|
+
if not context_candidate:
|
|
150
|
+
return Result.err(
|
|
151
|
+
ValidationError(
|
|
152
|
+
"Initial context cannot be empty",
|
|
153
|
+
field="initial_context",
|
|
154
|
+
value=initial_context,
|
|
155
|
+
)
|
|
156
|
+
)
|
|
157
|
+
|
|
158
|
+
candidate_path = _resolve_path_candidate(context_candidate, cwd=cwd)
|
|
159
|
+
if candidate_path is not None:
|
|
160
|
+
suffix = candidate_path.suffix.lower()
|
|
161
|
+
if suffix in _PM_SEED_SUFFIXES:
|
|
162
|
+
try:
|
|
163
|
+
raw_data = yaml.safe_load(candidate_path.read_text(encoding="utf-8"))
|
|
164
|
+
except (OSError, yaml.YAMLError) as exc:
|
|
165
|
+
return Result.err(
|
|
166
|
+
ValidationError(
|
|
167
|
+
f"Failed to read initial context file: {exc}",
|
|
168
|
+
field="initial_context",
|
|
169
|
+
value=str(candidate_path),
|
|
170
|
+
)
|
|
171
|
+
)
|
|
172
|
+
|
|
173
|
+
if _is_pm_seed_candidate(candidate_path, raw_data):
|
|
174
|
+
return load_pm_seed_as_context(candidate_path)
|
|
175
|
+
|
|
176
|
+
if suffix in _TEXT_CONTEXT_SUFFIXES or suffix in _PM_SEED_SUFFIXES:
|
|
177
|
+
try:
|
|
178
|
+
file_context = candidate_path.read_text(encoding="utf-8")
|
|
179
|
+
except OSError as exc:
|
|
180
|
+
return Result.err(
|
|
181
|
+
ValidationError(
|
|
182
|
+
f"Failed to read initial context file: {exc}",
|
|
183
|
+
field="initial_context",
|
|
184
|
+
value=str(candidate_path),
|
|
185
|
+
)
|
|
186
|
+
)
|
|
187
|
+
|
|
188
|
+
is_valid, error_message = InputValidator.validate_initial_context(file_context)
|
|
189
|
+
if not is_valid:
|
|
190
|
+
return Result.err(
|
|
191
|
+
ValidationError(
|
|
192
|
+
error_message,
|
|
193
|
+
field="initial_context",
|
|
194
|
+
value=str(candidate_path),
|
|
195
|
+
)
|
|
196
|
+
)
|
|
197
|
+
return Result.ok(file_context)
|
|
198
|
+
|
|
199
|
+
is_valid, error_message = InputValidator.validate_initial_context(initial_context)
|
|
200
|
+
if not is_valid:
|
|
201
|
+
return Result.err(
|
|
202
|
+
ValidationError(
|
|
203
|
+
error_message,
|
|
204
|
+
field="initial_context",
|
|
205
|
+
value=initial_context,
|
|
206
|
+
)
|
|
207
|
+
)
|
|
208
|
+
|
|
209
|
+
return Result.ok(initial_context)
|
{ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/mcp/tools/authoring_handlers.py
RENAMED
|
@@ -30,6 +30,7 @@ from ouroboros.bigbang.interview import (
|
|
|
30
30
|
from ouroboros.bigbang.seed_generator import SeedGenerator
|
|
31
31
|
from ouroboros.config import get_clarification_model
|
|
32
32
|
from ouroboros.core.errors import ValidationError
|
|
33
|
+
from ouroboros.core.initial_context import resolve_initial_context_input
|
|
33
34
|
from ouroboros.core.types import Result
|
|
34
35
|
from ouroboros.mcp.errors import MCPServerError, MCPToolError
|
|
35
36
|
from ouroboros.mcp.types import (
|
|
@@ -678,7 +679,16 @@ class InterviewHandler:
|
|
|
678
679
|
# Start new interview
|
|
679
680
|
if initial_context:
|
|
680
681
|
cwd = arguments.get("cwd") or os.getcwd()
|
|
681
|
-
|
|
682
|
+
resolved_context = resolve_initial_context_input(initial_context, cwd=cwd)
|
|
683
|
+
if resolved_context.is_err:
|
|
684
|
+
return Result.err(
|
|
685
|
+
MCPToolError(
|
|
686
|
+
str(resolved_context.error),
|
|
687
|
+
tool_name="ouroboros_interview",
|
|
688
|
+
)
|
|
689
|
+
)
|
|
690
|
+
|
|
691
|
+
result = await engine.start_interview(resolved_context.value, cwd=cwd)
|
|
682
692
|
if result.is_err:
|
|
683
693
|
return Result.err(
|
|
684
694
|
MCPToolError(
|
|
@@ -762,7 +772,7 @@ class InterviewHandler:
|
|
|
762
772
|
await self._emit_event(
|
|
763
773
|
interview_started(
|
|
764
774
|
state.interview_id,
|
|
765
|
-
|
|
775
|
+
resolved_context.value,
|
|
766
776
|
)
|
|
767
777
|
)
|
|
768
778
|
|
|
@@ -48,6 +48,7 @@ from ouroboros.mcp.types import (
|
|
|
48
48
|
ToolInputType,
|
|
49
49
|
)
|
|
50
50
|
from ouroboros.persistence.brownfield import BrownfieldRepo, BrownfieldStore
|
|
51
|
+
from ouroboros.pm.handoff import build_pm_dev_handoff_next_step
|
|
51
52
|
from ouroboros.providers import create_llm_adapter
|
|
52
53
|
|
|
53
54
|
log = structlog.get_logger()
|
|
@@ -1230,6 +1231,7 @@ class PMInterviewHandler:
|
|
|
1230
1231
|
|
|
1231
1232
|
seed = seed_result.value
|
|
1232
1233
|
|
|
1234
|
+
# Save seed to ~/.ouroboros/seeds/ (idempotent — overwrites on retry)
|
|
1233
1235
|
# Save seed and PM document with recovery contract
|
|
1234
1236
|
try:
|
|
1235
1237
|
seed_path = engine.save_pm_seed(seed)
|
|
@@ -1258,6 +1260,8 @@ class PMInterviewHandler:
|
|
|
1258
1260
|
)
|
|
1259
1261
|
)
|
|
1260
1262
|
|
|
1263
|
+
next_step = build_pm_dev_handoff_next_step(seed_path)
|
|
1264
|
+
|
|
1261
1265
|
return Result.ok(
|
|
1262
1266
|
MCPToolResult(
|
|
1263
1267
|
content=(
|
|
@@ -1265,10 +1269,13 @@ class PMInterviewHandler:
|
|
|
1265
1269
|
type=ContentType.TEXT,
|
|
1266
1270
|
text=(
|
|
1267
1271
|
f"PM seed generated: {seed.product_name}\n"
|
|
1268
|
-
f"
|
|
1272
|
+
f"PM seed: {seed_path}\n"
|
|
1269
1273
|
f"PM document: {pm_path}\n\n"
|
|
1274
|
+
"This PM seed is a handoff artifact for the dev interview, "
|
|
1275
|
+
"not the runnable Seed.\n"
|
|
1270
1276
|
f"Deferred items: {len(seed.deferred_items)}\n"
|
|
1271
|
-
f"Decide-later items: {len(seed.decide_later_items)}"
|
|
1277
|
+
f"Decide-later items: {len(seed.decide_later_items)}\n"
|
|
1278
|
+
f"Next: {next_step}"
|
|
1272
1279
|
),
|
|
1273
1280
|
),
|
|
1274
1281
|
),
|
|
@@ -1276,8 +1283,11 @@ class PMInterviewHandler:
|
|
|
1276
1283
|
meta={
|
|
1277
1284
|
"session_id": session_id,
|
|
1278
1285
|
"seed_path": str(seed_path),
|
|
1286
|
+
"pm_seed_path": str(seed_path),
|
|
1279
1287
|
"pm_path": str(pm_path),
|
|
1280
|
-
"
|
|
1288
|
+
"artifact_kind": "pm_seed",
|
|
1289
|
+
"runnable": False,
|
|
1290
|
+
"next_step": next_step,
|
|
1281
1291
|
},
|
|
1282
1292
|
)
|
|
1283
1293
|
)
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"""Shared PM handoff messaging helpers."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def build_pm_dev_handoff_command(seed_path: Path | str) -> str:
|
|
9
|
+
"""Return the canonical command for continuing from a PM seed."""
|
|
10
|
+
return f"ouroboros init start {seed_path}"
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def build_pm_dev_handoff_next_step(seed_path: Path | str) -> str:
|
|
14
|
+
"""Return the canonical PM-to-dev handoff message."""
|
|
15
|
+
return (
|
|
16
|
+
f"Run '{build_pm_dev_handoff_command(seed_path)}' to continue into the dev interview. "
|
|
17
|
+
"The runnable Seed is generated after that dev interview completes."
|
|
18
|
+
)
|
{ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/providers/claude_code_adapter.py
RENAMED
|
@@ -89,9 +89,11 @@ class ClaudeCodeAdapter:
|
|
|
89
89
|
self,
|
|
90
90
|
permission_mode: str = "default",
|
|
91
91
|
cli_path: str | Path | None = None,
|
|
92
|
+
cwd: str | Path | None = None,
|
|
92
93
|
allowed_tools: list[str] | None = None,
|
|
93
94
|
max_turns: int = 1,
|
|
94
95
|
on_message: Callable[[str, str], None] | None = None,
|
|
96
|
+
timeout: float | None = None,
|
|
95
97
|
) -> None:
|
|
96
98
|
"""Initialize Claude Code adapter.
|
|
97
99
|
|
|
@@ -102,23 +104,34 @@ class ClaudeCodeAdapter:
|
|
|
102
104
|
cli_path: Path to the Claude CLI binary. If not provided,
|
|
103
105
|
checks OUROBOROS_CLI_PATH env var, then falls back to
|
|
104
106
|
SDK's bundled CLI.
|
|
105
|
-
|
|
106
|
-
|
|
107
|
+
cwd: Working directory passed to the Claude Agent SDK.
|
|
108
|
+
allowed_tools: Explicit allow-list for Claude tools. ``None`` keeps
|
|
109
|
+
the default permissive mode while still blocking dangerous tools.
|
|
110
|
+
Use ``[]`` to forbid all Claude tools.
|
|
107
111
|
max_turns: Maximum turns for the conversation. Default 1 for
|
|
108
112
|
single-response completions (most MCP use cases).
|
|
109
113
|
on_message: Callback for streaming messages. Called with (type, content):
|
|
110
114
|
- ("thinking", "content") for agent reasoning
|
|
111
115
|
- ("tool", "tool_name") for tool usage
|
|
116
|
+
timeout: Optional application-level timeout in seconds for a
|
|
117
|
+
single completion request. When set, aborts before outer
|
|
118
|
+
transport timeouts and returns a ProviderError.
|
|
112
119
|
"""
|
|
113
120
|
self._permission_mode: str = permission_mode
|
|
114
121
|
self._cli_path: Path | None = self._resolve_cli_path(cli_path)
|
|
115
|
-
self.
|
|
122
|
+
self._cwd: str = str(Path(cwd).expanduser()) if cwd is not None else os.getcwd()
|
|
123
|
+
self._allowed_tools: list[str] | None = (
|
|
124
|
+
list(allowed_tools) if allowed_tools is not None else None
|
|
125
|
+
)
|
|
116
126
|
self._max_turns: int = max_turns
|
|
117
127
|
self._on_message: Callable[[str, str], None] | None = on_message
|
|
128
|
+
self._timeout: float | None = timeout if timeout and timeout > 0 else None
|
|
118
129
|
log.info(
|
|
119
130
|
"claude_code_adapter.initialized",
|
|
120
131
|
permission_mode=permission_mode,
|
|
121
132
|
cli_path=str(self._cli_path) if self._cli_path else None,
|
|
133
|
+
cwd=self._cwd,
|
|
134
|
+
timeout_seconds=self._timeout,
|
|
122
135
|
)
|
|
123
136
|
|
|
124
137
|
def _resolve_cli_path(self, cli_path: str | Path | None) -> Path | None:
|
|
@@ -260,9 +273,15 @@ class ClaudeCodeAdapter:
|
|
|
260
273
|
|
|
261
274
|
for attempt in range(_MAX_RETRIES):
|
|
262
275
|
try:
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
276
|
+
if self._timeout is None:
|
|
277
|
+
result = await self._execute_single_request(
|
|
278
|
+
prompt, config, system_prompt=system_prompt
|
|
279
|
+
)
|
|
280
|
+
else:
|
|
281
|
+
async with asyncio.timeout(self._timeout):
|
|
282
|
+
result = await self._execute_single_request(
|
|
283
|
+
prompt, config, system_prompt=system_prompt
|
|
284
|
+
)
|
|
266
285
|
|
|
267
286
|
if result.is_ok:
|
|
268
287
|
if attempt > 0:
|
|
@@ -290,6 +309,22 @@ class ClaudeCodeAdapter:
|
|
|
290
309
|
# Non-retryable error
|
|
291
310
|
return result
|
|
292
311
|
|
|
312
|
+
except TimeoutError:
|
|
313
|
+
log.warning(
|
|
314
|
+
"claude_code_adapter.request_timed_out",
|
|
315
|
+
timeout_seconds=self._timeout,
|
|
316
|
+
attempt=attempt + 1,
|
|
317
|
+
)
|
|
318
|
+
return Result.err(
|
|
319
|
+
ProviderError(
|
|
320
|
+
message=f"Claude Code request timed out after {self._timeout:.1f}s",
|
|
321
|
+
details={
|
|
322
|
+
"timed_out": True,
|
|
323
|
+
"timeout_seconds": self._timeout,
|
|
324
|
+
"attempt": attempt + 1,
|
|
325
|
+
},
|
|
326
|
+
)
|
|
327
|
+
)
|
|
293
328
|
except Exception as e:
|
|
294
329
|
error_str = str(e)
|
|
295
330
|
error_type = type(e).__name__
|
|
@@ -405,16 +440,17 @@ class ClaudeCodeAdapter:
|
|
|
405
440
|
log.debug("claude_code_adapter.stderr", line=line[:200])
|
|
406
441
|
|
|
407
442
|
options_kwargs: dict = {
|
|
408
|
-
"allowed_tools": self._allowed_tools if self._allowed_tools is not None else [],
|
|
409
443
|
"disallowed_tools": disallowed,
|
|
410
444
|
"max_turns": self._max_turns,
|
|
411
445
|
# Allow MCP and other ~/.claude/ settings to be inherited
|
|
412
446
|
"permission_mode": self._permission_mode,
|
|
413
|
-
"cwd":
|
|
447
|
+
"cwd": self._cwd,
|
|
414
448
|
"cli_path": self._cli_path,
|
|
415
449
|
"stderr": _stderr_callback,
|
|
416
450
|
"env": env_overrides,
|
|
417
451
|
}
|
|
452
|
+
if self._allowed_tools is not None:
|
|
453
|
+
options_kwargs["allowed_tools"] = self._allowed_tools
|
|
418
454
|
|
|
419
455
|
# Pass model from CompletionConfig if specified
|
|
420
456
|
# "default" is not a valid SDK model — treat it as None (use SDK default)
|
{ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/src/ouroboros/providers/codex_cli_adapter.py
RENAMED
|
@@ -81,7 +81,7 @@ class CodexCliLLMAdapter:
|
|
|
81
81
|
self._cli_path = self._resolve_cli_path(cli_path)
|
|
82
82
|
self._cwd = str(Path(cwd).expanduser()) if cwd is not None else os.getcwd()
|
|
83
83
|
self._permission_mode = self._resolve_permission_mode(permission_mode)
|
|
84
|
-
self._allowed_tools = allowed_tools
|
|
84
|
+
self._allowed_tools = list(allowed_tools) if allowed_tools is not None else None
|
|
85
85
|
self._max_turns = max_turns
|
|
86
86
|
self._on_message = on_message
|
|
87
87
|
self._max_retries = max_retries
|
|
@@ -150,12 +150,22 @@ class CodexCliLLMAdapter:
|
|
|
150
150
|
"If you need tools, prefer using only the following tools:\n"
|
|
151
151
|
+ "\n".join(f"- {tool}" for tool in self._allowed_tools)
|
|
152
152
|
)
|
|
153
|
+
elif self._allowed_tools is not None:
|
|
154
|
+
# Explicit empty list means no tools allowed — text-only response
|
|
155
|
+
parts.append("## Tool Constraints")
|
|
156
|
+
parts.append("Do NOT use any tools or MCP calls. Respond with plain text only.")
|
|
153
157
|
|
|
154
158
|
if self._max_turns > 0:
|
|
155
159
|
parts.append("## Execution Budget")
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
160
|
+
if self._allowed_tools == []:
|
|
161
|
+
parts.append(
|
|
162
|
+
"Answer directly in plain text and avoid turning this into a "
|
|
163
|
+
"multi-step tool workflow."
|
|
164
|
+
)
|
|
165
|
+
else:
|
|
166
|
+
parts.append(
|
|
167
|
+
f"Keep the work within at most {self._max_turns} tool-assisted turns if possible."
|
|
168
|
+
)
|
|
159
169
|
|
|
160
170
|
for message in messages:
|
|
161
171
|
if message.role == MessageRole.SYSTEM:
|
|
@@ -94,9 +94,11 @@ def create_llm_adapter(
|
|
|
94
94
|
return ClaudeCodeAdapter(
|
|
95
95
|
permission_mode=resolved_permission_mode,
|
|
96
96
|
cli_path=cli_path,
|
|
97
|
+
cwd=cwd,
|
|
97
98
|
allowed_tools=allowed_tools,
|
|
98
99
|
max_turns=max_turns,
|
|
99
100
|
on_message=on_message,
|
|
101
|
+
timeout=timeout,
|
|
100
102
|
)
|
|
101
103
|
if resolved_backend == "codex":
|
|
102
104
|
return CodexCliLLMAdapter(
|
|
@@ -110,7 +112,14 @@ def create_llm_adapter(
|
|
|
110
112
|
max_retries=max_retries,
|
|
111
113
|
)
|
|
112
114
|
# opencode is rejected at resolve time; this is a defensive fallback
|
|
113
|
-
|
|
115
|
+
try:
|
|
116
|
+
from ouroboros.providers.litellm_adapter import LiteLLMAdapter
|
|
117
|
+
except ImportError as exc:
|
|
118
|
+
msg = (
|
|
119
|
+
"litellm backend requested but litellm is not installed. "
|
|
120
|
+
"Install with: pip install 'ouroboros-ai[litellm]'"
|
|
121
|
+
)
|
|
122
|
+
raise RuntimeError(msg) from exc
|
|
114
123
|
|
|
115
124
|
return LiteLLMAdapter(
|
|
116
125
|
api_key=api_key,
|
{ouroboros_ai-0.26.5.dev6 → ouroboros_ai-0.26.5.dev8}/tests/unit/cli/test_init_pm_seed_detection.py
RENAMED
|
@@ -16,6 +16,7 @@ from ouroboros.cli.commands.init import (
|
|
|
16
16
|
_load_pm_seed_as_context,
|
|
17
17
|
_notify_pm_seed_detected,
|
|
18
18
|
_prompt_pm_seed_selection,
|
|
19
|
+
start,
|
|
19
20
|
)
|
|
20
21
|
|
|
21
22
|
# ---------------------------------------------------------------------------
|
|
@@ -550,3 +551,36 @@ class TestPrdSeedConfirmationFlow:
|
|
|
550
551
|
assert parsed["goal"] == "End-to-end testing"
|
|
551
552
|
assert "Analytics" in parsed["deferred_items"]
|
|
552
553
|
assert "Hosting provider" in parsed["decide_later_items"]
|
|
554
|
+
|
|
555
|
+
|
|
556
|
+
class TestStartCommandPathResolution:
|
|
557
|
+
"""Tests for starting the dev interview from a PM artifact path."""
|
|
558
|
+
|
|
559
|
+
def test_start_resolves_pm_seed_path_before_running_interview(self, tmp_path: Path) -> None:
|
|
560
|
+
seed_path = tmp_path / "pm_seed_taskflow.json"
|
|
561
|
+
seed_path.write_text(
|
|
562
|
+
"""{
|
|
563
|
+
"pm_id": "pm_seed_taskflow",
|
|
564
|
+
"product_name": "TaskFlow",
|
|
565
|
+
"goal": "Help teams manage tasks",
|
|
566
|
+
"constraints": ["Offline support"],
|
|
567
|
+
"success_criteria": ["Tasks sync correctly"],
|
|
568
|
+
"user_stories": [],
|
|
569
|
+
"deferred_items": [],
|
|
570
|
+
"decide_later_items": []
|
|
571
|
+
}
|
|
572
|
+
""",
|
|
573
|
+
encoding="utf-8",
|
|
574
|
+
)
|
|
575
|
+
|
|
576
|
+
with (
|
|
577
|
+
patch.object(Path, "home", return_value=tmp_path),
|
|
578
|
+
patch("ouroboros.cli.commands.init.asyncio.run"),
|
|
579
|
+
patch("ouroboros.cli.commands.init._run_interview") as mock_run_interview,
|
|
580
|
+
patch("ouroboros.cli.commands.init.print_info"),
|
|
581
|
+
):
|
|
582
|
+
start(context=str(seed_path), resume=None)
|
|
583
|
+
|
|
584
|
+
resolved_context = mock_run_interview.call_args.args[0]
|
|
585
|
+
assert "TaskFlow" in resolved_context
|
|
586
|
+
assert str(seed_path) not in resolved_context
|