ouroboros-ai 0.27.3.dev1__tar.gz → 0.27.3.dev2__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.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/PKG-INFO +27 -17
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/README.ko.md +2 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/README.md +3 -1
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/docs/cli-reference.md +0 -4
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/docs/getting-started.md +2 -1
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/pyproject.toml +17 -11
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/_version.py +2 -2
- ouroboros_ai-0.27.3.dev2/src/ouroboros/cli/formatters/prompting.py +38 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/config/loader.py +20 -1
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/core/file_lock.py +5 -5
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/mcp/server/adapter.py +60 -7
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/orchestrator/mcp_tools.py +2 -1
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/providers/litellm_adapter.py +12 -0
- ouroboros_ai-0.27.3.dev2/tests/unit/cli/formatters/test_prompting.py +45 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/config/test_loader_env.py +16 -0
- ouroboros_ai-0.27.3.dev2/tests/unit/core/test_file_lock.py +52 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/mcp/server/test_adapter.py +29 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/providers/test_litellm_adapter.py +20 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/test_dependencies_configured.py +19 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/uv.lock +506 -17
- ouroboros_ai-0.27.3.dev1/src/ouroboros/cli/formatters/prompting.py +0 -68
- ouroboros_ai-0.27.3.dev1/tests/unit/cli/formatters/test_prompting.py +0 -32
- ouroboros_ai-0.27.3.dev1/tests/unit/core/test_file_lock.py +0 -17
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/.claude/settings.json +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/.claude-plugin/.mcp.json +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/.claude-plugin/marketplace.json +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/.claude-plugin/plugin.json +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/.env.example +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/.github/ISSUE_TEMPLATE/config.yml +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/.github/ISSUE_TEMPLATE/feature_request.yml +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/.github/ISSUE_TEMPLATE/question.yml +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/.github/workflows/dev-publish.yml +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/.github/workflows/lint.yml +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/.github/workflows/release.yml +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/.github/workflows/test.yml +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/.gitignore +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/.mcp.json +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/.ouroboros/mechanical.toml +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/.ouroboros/seeds/seed_73827177a2a3.yaml +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/.ouroboros/seeds/seed_78c8e6e41813.yaml +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/.pre-commit-config.yaml +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/.python-version +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/CHANGELOG.md +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/CLAUDE.md +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/CODE_OF_CONDUCT.md +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/CONTRIBUTING.md +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/HANDOFF.md +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/LICENSE +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/SECURITY.md +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/UNINSTALL.md +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/commands/cancel.md +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/commands/evaluate.md +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/commands/evolve.md +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/commands/help.md +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/commands/interview.md +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/commands/ralph.md +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/commands/run.md +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/commands/seed.md +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/commands/setup.md +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/commands/status.md +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/commands/tutorial.md +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/commands/unstuck.md +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/commands/welcome.md +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/crates/ouroboros-tui/.gitignore +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/crates/ouroboros-tui/Cargo.lock +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/crates/ouroboros-tui/Cargo.toml +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/crates/ouroboros-tui/README.md +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/crates/ouroboros-tui/src/db.rs +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/crates/ouroboros-tui/src/main.rs +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/crates/ouroboros-tui/src/mock.rs +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/crates/ouroboros-tui/src/state.rs +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/crates/ouroboros-tui/src/views/dashboard.rs +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/crates/ouroboros-tui/src/views/execution.rs +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/crates/ouroboros-tui/src/views/lineage.rs +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/crates/ouroboros-tui/src/views/logs.rs +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/crates/ouroboros-tui/src/views/mod.rs +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/crates/ouroboros-tui/src/views/session_selector.rs +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/docs/README.md +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/docs/api/README.md +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/docs/api/core.md +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/docs/api/mcp.md +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/docs/architecture.md +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/docs/config-reference.md +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/docs/contributing/architecture-overview.md +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/docs/contributing/findings-registry.md +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/docs/contributing/issue-quality-policy.md +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/docs/contributing/key-patterns.md +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/docs/contributing/testing-guide.md +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/docs/examples/mcp-config.yaml +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/docs/guides/evaluation-pipeline.md +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/docs/guides/evolution-loop.md +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/docs/guides/issue-176-subagent-mcp-inheritance.md +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/docs/guides/mcp-bridge.md +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/docs/guides/seed-authoring.md +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/docs/guides/tui-usage.md +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/docs/images/PLACEHOLDER_README.md +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/docs/images/ouroboros.png +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/docs/platform-support.md +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/docs/runtime-capability-matrix.md +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/docs/runtime-guides/claude-code.md +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/docs/runtime-guides/codex.md +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/docs/runtime-guides/opencode.md +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/examples/coordinator_test_seed.yaml +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/examples/dummy_seed.yaml +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/examples/parallel_subac_test_seed.yaml +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/examples/subac_test_seed.yaml +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/examples/task_manager/README.md +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/examples/task_manager/__init__.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/examples/task_manager/__main__.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/examples/task_manager/cli.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/examples/task_manager/models.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/examples/task_manager/storage.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/examples/test_display.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/hooks/hooks.json +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/llms-full.txt +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/llms.txt +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/project-context.md +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/scripts/drift-monitor.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/scripts/install.sh +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/scripts/keyword-detector.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/scripts/mcp-serve.sh +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/scripts/ralph-rewind.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/scripts/ralph.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/scripts/ralph.sh +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/scripts/session-start.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/scripts/sync-plugin-version.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/scripts/version-check.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/skills/brownfield/SKILL.md +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/skills/cancel/SKILL.md +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/skills/evaluate/SKILL.md +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/skills/evolve/SKILL.md +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/skills/help/SKILL.md +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/skills/interview/SKILL.md +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/skills/pm/SKILL.md +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/skills/publish/SKILL.md +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/skills/qa/SKILL.md +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/skills/ralph/SKILL.md +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/skills/run/SKILL.md +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/skills/seed/SKILL.md +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/skills/setup/SKILL.md +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/skills/status/SKILL.md +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/skills/tutorial/SKILL.md +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/skills/unstuck/SKILL.md +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/skills/update/SKILL.md +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/skills/welcome/SKILL.md +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/__init__.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/__main__.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/agents/__init__.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/agents/advocate.md +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/agents/analysis-agent.md +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/agents/architect.md +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/agents/breadth-keeper.md +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/agents/code-executor.md +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/agents/codebase-explorer.md +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/agents/consensus-reviewer.md +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/agents/contrarian.md +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/agents/evaluator.md +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/agents/hacker.md +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/agents/judge.md +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/agents/loader.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/agents/ontologist.md +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/agents/ontology-analyst.md +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/agents/qa-judge.md +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/agents/research-agent.md +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/agents/researcher.md +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/agents/seed-architect.md +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/agents/seed-closer.md +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/agents/semantic-evaluator.md +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/agents/simplifier.md +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/agents/socratic-interviewer.md +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/bigbang/__init__.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/bigbang/ambiguity.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/bigbang/brownfield.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/bigbang/explore.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/bigbang/interview.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/bigbang/pm_completion.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/bigbang/pm_document.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/bigbang/pm_interview.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/bigbang/pm_seed.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/bigbang/question_classifier.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/bigbang/seed_generator.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/cli/__init__.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/cli/commands/__init__.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/cli/commands/cancel.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/cli/commands/config.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/cli/commands/init.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/cli/commands/mcp.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/cli/commands/pm.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/cli/commands/run.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/cli/commands/setup.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/cli/commands/status.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/cli/commands/tui.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/cli/commands/uninstall.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/cli/formatters/__init__.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/cli/formatters/panels.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/cli/formatters/progress.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/cli/formatters/tables.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/cli/formatters/workflow_display.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/cli/jsonc.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/cli/main.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/codex/__init__.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/codex/artifacts.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/codex/ouroboros.md +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/codex_permissions.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/config/__init__.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/config/models.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/core/__init__.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/core/ac_tree.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/core/context.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/core/errors.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/core/git_workflow.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/core/initial_context.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/core/json_utils.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/core/lineage.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/core/ontology_aspect.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/core/ontology_questions.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/core/project_paths.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/core/retry.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/core/security.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/core/seed.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/core/text.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/core/ttl_cache.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/core/types.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/core/worktree.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/evaluation/__init__.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/evaluation/artifact_collector.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/evaluation/consensus.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/evaluation/json_utils.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/evaluation/languages.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/evaluation/mechanical.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/evaluation/models.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/evaluation/pipeline.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/evaluation/semantic.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/evaluation/trigger.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/evaluation/verification_artifacts.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/events/__init__.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/events/base.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/events/decomposition.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/events/evaluation.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/events/interview.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/events/lineage.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/events/ontology.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/evolution/__init__.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/evolution/convergence.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/evolution/loop.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/evolution/projector.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/evolution/reflect.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/evolution/regression.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/evolution/wonder.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/execution/__init__.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/execution/atomicity.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/execution/decomposition.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/execution/double_diamond.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/execution/subagent.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/mcp/__init__.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/mcp/bridge/__init__.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/mcp/bridge/bridge.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/mcp/bridge/config.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/mcp/bridge/factory.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/mcp/client/__init__.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/mcp/client/adapter.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/mcp/client/manager.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/mcp/client/protocol.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/mcp/errors.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/mcp/job_manager.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/mcp/resources/__init__.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/mcp/resources/handlers.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/mcp/server/__init__.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/mcp/server/protocol.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/mcp/server/security.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/mcp/tools/__init__.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/mcp/tools/ac_tree_hud_handler.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/mcp/tools/ac_tree_hud_render.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/mcp/tools/authoring_handlers.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/mcp/tools/bridge_mixin.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/mcp/tools/brownfield_handler.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/mcp/tools/dashboard.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/mcp/tools/definitions.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/mcp/tools/evaluation_handlers.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/mcp/tools/evolution_handlers.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/mcp/tools/execution_handlers.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/mcp/tools/job_handlers.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/mcp/tools/pm_handler.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/mcp/tools/qa.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/mcp/tools/query_handlers.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/mcp/tools/registry.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/mcp/types.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/observability/__init__.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/observability/drift.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/observability/logging.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/observability/retrospective.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/orchestrator/__init__.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/orchestrator/adapter.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/orchestrator/capabilities.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/orchestrator/codex_cli_runtime.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/orchestrator/command_dispatcher.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/orchestrator/control_plane.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/orchestrator/coordinator.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/orchestrator/dependency_analyzer.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/orchestrator/events.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/orchestrator/execution_runtime_scope.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/orchestrator/execution_strategy.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/orchestrator/heartbeat.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/orchestrator/level_context.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/orchestrator/mcp_config.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/orchestrator/opencode_event_normalizer.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/orchestrator/opencode_runtime.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/orchestrator/parallel_executor.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/orchestrator/parallel_executor_models.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/orchestrator/policy.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/orchestrator/runner.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/orchestrator/runtime_factory.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/orchestrator/runtime_message_projection.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/orchestrator/session.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/orchestrator/workflow_state.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/persistence/__init__.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/persistence/brownfield.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/persistence/checkpoint.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/persistence/event_store.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/persistence/migrations/__init__.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/persistence/migrations/runner.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/persistence/migrations/scripts/001_initial.sql +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/persistence/migrations/scripts/002_brownfield.sql +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/persistence/schema.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/persistence/uow.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/plugin/__init__.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/plugin/agents/__init__.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/plugin/agents/pool.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/plugin/agents/registry.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/plugin/orchestration/__init__.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/plugin/orchestration/router.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/plugin/orchestration/scheduler.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/plugin/skills/__init__.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/plugin/skills/docs.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/plugin/skills/executor.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/plugin/skills/keywords.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/plugin/skills/registry.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/pm/__init__.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/pm/handoff.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/pm/renderer.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/providers/__init__.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/providers/anthropic_adapter.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/providers/base.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/providers/claude_code_adapter.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/providers/codex_cli_adapter.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/providers/codex_cli_stream.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/providers/factory.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/providers/gemini_cli_adapter.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/providers/opencode_adapter.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/py.typed +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/resilience/__init__.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/resilience/lateral.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/resilience/stagnation.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/routing/__init__.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/routing/complexity.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/routing/downgrade.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/routing/escalation.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/routing/router.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/routing/tiers.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/secondary/__init__.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/secondary/scheduler.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/secondary/todo_registry.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/strategies/__init__.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/strategies/devil_advocate.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/tui/__init__.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/tui/app.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/tui/components/__init__.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/tui/components/agents_panel.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/tui/components/event_log.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/tui/components/progress.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/tui/components/token_tracker.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/tui/events.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/tui/screens/__init__.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/tui/screens/confirm_rewind.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/tui/screens/dashboard.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/tui/screens/dashboard_v2.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/tui/screens/dashboard_v3.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/tui/screens/debug.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/tui/screens/execution.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/tui/screens/hud_dashboard.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/tui/screens/lineage_detail.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/tui/screens/lineage_selector.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/tui/screens/logs.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/tui/screens/session_selector.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/tui/widgets/__init__.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/tui/widgets/ac_progress.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/tui/widgets/ac_tree.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/tui/widgets/agent_activity.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/tui/widgets/cost_tracker.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/tui/widgets/drift_meter.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/tui/widgets/lineage_tree.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/tui/widgets/parallel_graph.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/tui/widgets/phase_progress.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/verification/__init__.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/verification/extractor.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/verification/models.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/verification/verifier.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/__init__.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/conftest.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/e2e/__init__.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/e2e/conftest.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/e2e/mcp_bridge_test_config.yaml +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/e2e/test_cli_commands.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/e2e/test_full_workflow.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/e2e/test_session_persistence.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/fixtures/test_atomicity_seed.yml +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/integration/__init__.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/integration/conftest.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/integration/mcp/__init__.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/integration/mcp/bridge/__init__.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/integration/mcp/bridge/test_bridge_server_to_server.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/integration/mcp/conftest.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/integration/mcp/test_client_adapter.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/integration/mcp/test_client_manager.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/integration/mcp/test_server_adapter.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/integration/plugin/test_orchestration.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/integration/test_codex_cli_passthrough_smoke.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/integration/test_codex_skill_fallback.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/integration/test_codex_skill_smoke.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/integration/test_entry_point.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/__init__.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/agents/__init__.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/agents/test_loader.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/bigbang/__init__.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/bigbang/test_ambiguity.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/bigbang/test_brownfield.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/bigbang/test_classifier_context.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/bigbang/test_decide_later_items.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/bigbang/test_explore.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/bigbang/test_interview.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/bigbang/test_interview_async_io.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/bigbang/test_interview_no_web_search_hint.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/bigbang/test_interview_research_prefix.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/bigbang/test_pm_completion.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/bigbang/test_pm_document_generator.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/bigbang/test_pm_document_writer.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/bigbang/test_pm_interview.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/bigbang/test_pm_interview_brownfield_db.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/bigbang/test_pm_seed_ac12.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/bigbang/test_pm_seed_save.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/bigbang/test_question_classifier.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/bigbang/test_seed_generator.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/cli/__init__.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/cli/commands/test_tui_command.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/cli/formatters/__init__.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/cli/formatters/test_console.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/cli/formatters/test_panels.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/cli/formatters/test_progress.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/cli/formatters/test_tables.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/cli/formatters/test_workflow_display.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/cli/test_cancel.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/cli/test_config.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/cli/test_init_pm_seed_detection.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/cli/test_init_runtime.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/cli/test_jsonc.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/cli/test_main.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/cli/test_mcp_nested_guard.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/cli/test_mcp_startup_cleanup.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/cli/test_pm.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/cli/test_pm_brownfield.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/cli/test_pm_completion.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/cli/test_pm_interactive_logging.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/cli/test_pm_missing_litellm.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/cli/test_pm_overwrite.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/cli/test_pm_runtime_adapter.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/cli/test_pm_select_repos.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/cli/test_run_qa.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/cli/test_setup.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/cli/test_uninstall.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/config/__init__.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/config/test_loader.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/config/test_models.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/core/__init__.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/core/test_ac_tree.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/core/test_context.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/core/test_errors.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/core/test_git_workflow.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/core/test_initial_context.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/core/test_lineage.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/core/test_ontology_aspect.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/core/test_ontology_questions.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/core/test_retry.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/core/test_security.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/core/test_seed.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/core/test_ttl_cache.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/core/test_types.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/core/test_worktree.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/evaluation/__init__.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/evaluation/test_artifact_collector_file_prefix.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/evaluation/test_consensus.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/evaluation/test_json_utils.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/evaluation/test_languages.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/evaluation/test_mechanical.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/evaluation/test_models.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/evaluation/test_pipeline_trigger_consensus.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/evaluation/test_review_fixes.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/evaluation/test_semantic.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/evaluation/test_trigger.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/evaluation/test_trigger_consensus.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/evaluation/test_verification_artifacts.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/events/__init__.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/events/test_base.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/events/test_decomposition_events.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/evolution/test_wonder_scope.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/execution/__init__.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/execution/test_atomicity.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/execution/test_decomposition.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/execution/test_double_diamond.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/execution/test_subagent_isolation.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/mcp/__init__.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/mcp/bridge/__init__.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/mcp/bridge/test_bridge.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/mcp/bridge/test_config.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/mcp/bridge/test_factory.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/mcp/bridge/test_handler_wiring.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/mcp/bridge/test_stability.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/mcp/client/__init__.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/mcp/client/test_adapter.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/mcp/client/test_adapter_transport_lifecycle.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/mcp/client/test_manager.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/mcp/conftest.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/mcp/server/__init__.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/mcp/server/test_security.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/mcp/test_errors.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/mcp/test_job_manager.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/mcp/test_types.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/mcp/tools/__init__.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/mcp/tools/conftest.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/mcp/tools/test_ac_tree_hud_footer.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/mcp/tools/test_ac_tree_hud_handler.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/mcp/tools/test_ac_tree_hud_handler_completed.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/mcp/tools/test_ac_tree_hud_handler_cursor_changed.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/mcp/tools/test_ac_tree_hud_handler_invalid_session.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/mcp/tools/test_ac_tree_hud_handler_no_execution.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/mcp/tools/test_ac_tree_hud_handler_waiting.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/mcp/tools/test_ac_tree_hud_max_nodes.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/mcp/tools/test_ac_tree_hud_render_depth2.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/mcp/tools/test_ac_tree_hud_render_depth3.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/mcp/tools/test_ac_tree_hud_status_icons.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/mcp/tools/test_ac_tree_hud_truncation.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/mcp/tools/test_brownfield_handler.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/mcp/tools/test_definitions.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/mcp/tools/test_evaluation_handler.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/mcp/tools/test_interview_parallel_scoring.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/mcp/tools/test_interview_scoring_guard.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/mcp/tools/test_mcp_manager_wiring.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/mcp/tools/test_pm_handler.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/mcp/tools/test_pm_handler_generate.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/mcp/tools/test_pm_handler_pending_reframe.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/mcp/tools/test_qa_integration.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/mcp/tools/test_qa_parser.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/mcp/tools/test_registry.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/mcp/tools/test_traceback_reporting.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/observability/__init__.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/observability/test_drift.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/observability/test_logging.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/observability/test_retrospective.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/orchestrator/__init__.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/orchestrator/test_adapter.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/orchestrator/test_capabilities.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/orchestrator/test_codex_cli_runtime.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/orchestrator/test_codex_recursion_guard.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/orchestrator/test_command_dispatcher.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/orchestrator/test_control_plane.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/orchestrator/test_coordinator.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/orchestrator/test_dependency_analyzer.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/orchestrator/test_events.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/orchestrator/test_execution_runtime_scope.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/orchestrator/test_execution_strategy.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/orchestrator/test_inflight_cancellation.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/orchestrator/test_level_context.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/orchestrator/test_mcp_config.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/orchestrator/test_mcp_tools.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/orchestrator/test_opencode_runtime.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/orchestrator/test_parallel_executor.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/orchestrator/test_parallel_executor_atomic_judgment.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/orchestrator/test_parallel_executor_recursive_depth.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/orchestrator/test_parallel_executor_retry_resume.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/orchestrator/test_policy.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/orchestrator/test_runner.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/orchestrator/test_runner_cancellation.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/orchestrator/test_runtime_factory.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/orchestrator/test_runtime_message_projection.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/orchestrator/test_session.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/orchestrator/test_workflow_state.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/persistence/__init__.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/persistence/test_brownfield_store.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/persistence/test_checkpoint.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/persistence/test_event_store.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/persistence/test_schema.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/persistence/test_uow.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/plugin/__init__.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/plugin/agents/__init__.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/plugin/agents/test_registry.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/plugin/orchestration/__init__.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/plugin/orchestration/test_model_router.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/plugin/skills/__init__.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/plugin/skills/test_keywords.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/plugin/skills/test_registry.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/pm/__init__.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/pm/test_renderer.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/providers/__init__.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/providers/test_base.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/providers/test_claude_code_adapter.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/providers/test_codex_cli_adapter.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/providers/test_factory.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/providers/test_gemini_cli_adapter.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/providers/test_opencode_adapter.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/resilience/__init__.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/resilience/test_lateral.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/resilience/test_stagnation.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/routing/__init__.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/routing/test_complexity.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/routing/test_downgrade.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/routing/test_escalation.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/routing/test_router.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/routing/test_tiers.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/scripts/test_keyword_detector.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/scripts/test_version_check.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/secondary/__init__.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/secondary/test_scheduler.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/secondary/test_todo_registry.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/test_artifact_collector.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/test_codex_artifacts.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/test_convergence.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/test_dashboard.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/test_evolve_rewind.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/test_evolve_step.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/test_graceful_shutdown.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/test_main_entry_point.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/test_module_structure.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/test_project_initialization.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/test_projector_rewind.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/test_ralph_parser.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/test_ralph_rewind.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/test_regression.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/test_tooling_configuration.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/test_verification.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/tui/__init__.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/tui/test_app.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/tui/test_cancelled_display.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/tui/test_events.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/tui/test_lineage_viewer.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/tui/test_screens.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/tui/test_session_selector_replay.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/tui/test_widgets.py +0 -0
- {ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tools/sync_github_project.py +0 -0
|
@@ -1,32 +1,40 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: ouroboros-ai
|
|
3
|
-
Version: 0.27.3.
|
|
3
|
+
Version: 0.27.3.dev2
|
|
4
4
|
Summary: Specification-first workflow engine for AI coding agents. Works with Claude Code and Codex CLI.
|
|
5
5
|
Author-email: Q00 <jqyu.lee@gmail.com>
|
|
6
6
|
License-File: LICENSE
|
|
7
7
|
Requires-Python: >=3.12
|
|
8
|
-
Requires-Dist: aiosqlite
|
|
9
|
-
Requires-Dist:
|
|
10
|
-
Requires-Dist:
|
|
11
|
-
Requires-Dist:
|
|
12
|
-
Requires-Dist:
|
|
13
|
-
Requires-Dist:
|
|
14
|
-
Requires-Dist:
|
|
8
|
+
Requires-Dist: aiosqlite<1.0.0,>=0.20.0
|
|
9
|
+
Requires-Dist: prompt-toolkit<4.0.0,>=3.0.0
|
|
10
|
+
Requires-Dist: pydantic<3.0.0,>=2.0.0
|
|
11
|
+
Requires-Dist: pyyaml<7.0.0,>=6.0.0
|
|
12
|
+
Requires-Dist: rich<15.0.0,>=13.0.0
|
|
13
|
+
Requires-Dist: sqlalchemy[asyncio]<3.0.0,>=2.0.0
|
|
14
|
+
Requires-Dist: structlog<26.0.0,>=24.0.0
|
|
15
|
+
Requires-Dist: typer<1.0.0,>=0.12.0
|
|
15
16
|
Provides-Extra: all
|
|
16
|
-
Requires-Dist: anthropic
|
|
17
|
-
Requires-Dist: claude-agent-sdk
|
|
17
|
+
Requires-Dist: anthropic<1.0.0,>=0.52.0; extra == 'all'
|
|
18
|
+
Requires-Dist: claude-agent-sdk<1.0.0,>=0.1.0; extra == 'all'
|
|
18
19
|
Requires-Dist: litellm<=1.82.6,>=1.80.0; extra == 'all'
|
|
19
|
-
Requires-Dist: mcp
|
|
20
|
-
Requires-Dist:
|
|
20
|
+
Requires-Dist: mcp<2.0.0,>=1.26.0; extra == 'all'
|
|
21
|
+
Requires-Dist: pandas<3.0.0,>=2.2.0; extra == 'all'
|
|
22
|
+
Requires-Dist: plotly<7.0.0,>=5.24.0; extra == 'all'
|
|
23
|
+
Requires-Dist: streamlit<2.0.0,>=1.40.0; extra == 'all'
|
|
24
|
+
Requires-Dist: textual<9.0.0,>=1.0.0; extra == 'all'
|
|
21
25
|
Provides-Extra: claude
|
|
22
|
-
Requires-Dist: anthropic
|
|
23
|
-
Requires-Dist: claude-agent-sdk
|
|
26
|
+
Requires-Dist: anthropic<1.0.0,>=0.52.0; extra == 'claude'
|
|
27
|
+
Requires-Dist: claude-agent-sdk<1.0.0,>=0.1.0; extra == 'claude'
|
|
28
|
+
Provides-Extra: dashboard
|
|
29
|
+
Requires-Dist: pandas<3.0.0,>=2.2.0; extra == 'dashboard'
|
|
30
|
+
Requires-Dist: plotly<7.0.0,>=5.24.0; extra == 'dashboard'
|
|
31
|
+
Requires-Dist: streamlit<2.0.0,>=1.40.0; extra == 'dashboard'
|
|
24
32
|
Provides-Extra: litellm
|
|
25
33
|
Requires-Dist: litellm<=1.82.6,>=1.80.0; extra == 'litellm'
|
|
26
34
|
Provides-Extra: mcp
|
|
27
|
-
Requires-Dist: mcp
|
|
35
|
+
Requires-Dist: mcp<2.0.0,>=1.26.0; extra == 'mcp'
|
|
28
36
|
Provides-Extra: tui
|
|
29
|
-
Requires-Dist: textual
|
|
37
|
+
Requires-Dist: textual<9.0.0,>=1.0.0; extra == 'tui'
|
|
30
38
|
Description-Content-Type: text/markdown
|
|
31
39
|
|
|
32
40
|
<p align="right">
|
|
@@ -128,10 +136,12 @@ pip install ouroboros-ai[claude] # + Claude Code deps
|
|
|
128
136
|
pip install ouroboros-ai[litellm] # + LiteLLM multi-provider
|
|
129
137
|
pip install ouroboros-ai[mcp] # + MCP server/client support
|
|
130
138
|
pip install ouroboros-ai[tui] # + Textual terminal UI
|
|
131
|
-
pip install ouroboros-ai[all] # everything
|
|
139
|
+
pip install ouroboros-ai[all] # everything (claude + litellm + mcp + tui + dashboard)
|
|
132
140
|
ouroboros setup # configure runtime
|
|
133
141
|
```
|
|
134
142
|
|
|
143
|
+
Legacy compatibility: `ouroboros-ai[dashboard]` is still accepted as a compatibility alias while extras migrate.
|
|
144
|
+
|
|
135
145
|
See runtime guides: [Claude Code](./docs/runtime-guides/claude-code.md) · [Codex CLI](./docs/runtime-guides/codex.md)
|
|
136
146
|
|
|
137
147
|
</details>
|
|
@@ -125,6 +125,8 @@ pip install ouroboros-ai[all] # 전부
|
|
|
125
125
|
ouroboros setup # 런타임 설정
|
|
126
126
|
```
|
|
127
127
|
|
|
128
|
+
호환성 참고: extras 전환 기간 동안 `ouroboros-ai[dashboard]`도 no-op alias로 계속 허용됩니다.
|
|
129
|
+
|
|
128
130
|
런타임별 가이드: [Claude Code](./docs/runtime-guides/claude-code.md) · [Codex CLI](./docs/runtime-guides/codex.md)
|
|
129
131
|
|
|
130
132
|
</details>
|
|
@@ -97,10 +97,12 @@ pip install ouroboros-ai[claude] # + Claude Code deps
|
|
|
97
97
|
pip install ouroboros-ai[litellm] # + LiteLLM multi-provider
|
|
98
98
|
pip install ouroboros-ai[mcp] # + MCP server/client support
|
|
99
99
|
pip install ouroboros-ai[tui] # + Textual terminal UI
|
|
100
|
-
pip install ouroboros-ai[all] # everything
|
|
100
|
+
pip install ouroboros-ai[all] # everything (claude + litellm + mcp + tui + dashboard)
|
|
101
101
|
ouroboros setup # configure runtime
|
|
102
102
|
```
|
|
103
103
|
|
|
104
|
+
Legacy compatibility: `ouroboros-ai[dashboard]` is still accepted as a compatibility alias while extras migrate.
|
|
105
|
+
|
|
104
106
|
See runtime guides: [Claude Code](./docs/runtime-guides/claude-code.md) · [Codex CLI](./docs/runtime-guides/codex.md)
|
|
105
107
|
|
|
106
108
|
</details>
|
|
@@ -160,10 +160,6 @@ ouroboros init start --resume interview_20260116_120000
|
|
|
160
160
|
ouroboros init
|
|
161
161
|
```
|
|
162
162
|
|
|
163
|
-
> **Interactive multiline input:** when `init` or other interview-style commands prompt for a
|
|
164
|
-
> longer response, press `Ctrl+D` (macOS/Linux) or `Ctrl+Z` then Enter (Windows) to submit the
|
|
165
|
-
> full response. Plain Enter inserts a newline.
|
|
166
|
-
|
|
167
163
|
### `init list`
|
|
168
164
|
|
|
169
165
|
List all interview sessions.
|
|
@@ -82,13 +82,14 @@ pip install ouroboros-ai[claude] # + Claude Code runtime deps (anthropic, c
|
|
|
82
82
|
pip install ouroboros-ai[litellm] # + LiteLLM multi-provider support (100+ models)
|
|
83
83
|
pip install ouroboros-ai[mcp] # + MCP server/client runtime support
|
|
84
84
|
pip install ouroboros-ai[tui] # + Textual terminal UI
|
|
85
|
-
pip install ouroboros-ai[all] # Everything (claude + litellm + mcp + tui)
|
|
85
|
+
pip install ouroboros-ai[all] # Everything (claude + litellm + mcp + tui + dashboard)
|
|
86
86
|
|
|
87
87
|
ouroboros --version # verify CLI
|
|
88
88
|
```
|
|
89
89
|
|
|
90
90
|
> **Which extra do I need?** If you only use Claude Code as your runtime, `ouroboros-ai[claude]` is sufficient.
|
|
91
91
|
> For multi-model support via LiteLLM, use `ouroboros-ai[litellm]` or just grab everything with `ouroboros-ai[all]`.
|
|
92
|
+
> Legacy note: `ouroboros-ai[dashboard]` is still accepted as a compatibility extra during the extras transition.
|
|
92
93
|
|
|
93
94
|
**One-liner alternative** (auto-detects your runtime and installs matching extras):
|
|
94
95
|
```bash
|
|
@@ -8,21 +8,27 @@ authors = [
|
|
|
8
8
|
]
|
|
9
9
|
requires-python = ">=3.12"
|
|
10
10
|
dependencies = [
|
|
11
|
-
"aiosqlite>=0.20.0",
|
|
12
|
-
"pydantic>=2.0.0",
|
|
13
|
-
"
|
|
14
|
-
"
|
|
15
|
-
"
|
|
16
|
-
"
|
|
17
|
-
"
|
|
11
|
+
"aiosqlite>=0.20.0,<1.0.0",
|
|
12
|
+
"pydantic>=2.0.0,<3.0.0",
|
|
13
|
+
"prompt-toolkit>=3.0.0,<4.0.0",
|
|
14
|
+
"pyyaml>=6.0.0,<7.0.0",
|
|
15
|
+
"rich>=13.0.0,<15.0.0",
|
|
16
|
+
"sqlalchemy[asyncio]>=2.0.0,<3.0.0",
|
|
17
|
+
"structlog>=24.0.0,<26.0.0",
|
|
18
|
+
"typer>=0.12.0,<1.0.0",
|
|
18
19
|
]
|
|
19
20
|
|
|
20
21
|
[project.optional-dependencies]
|
|
21
|
-
claude = ["claude-agent-sdk>=0.1.0", "anthropic>=0.52.0"]
|
|
22
|
+
claude = ["claude-agent-sdk>=0.1.0,<1.0.0", "anthropic>=0.52.0,<1.0.0"]
|
|
22
23
|
litellm = ["litellm>=1.80.0,<=1.82.6"]
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
24
|
+
dashboard = [
|
|
25
|
+
"streamlit>=1.40.0,<2.0.0",
|
|
26
|
+
"plotly>=5.24.0,<7.0.0",
|
|
27
|
+
"pandas>=2.2.0,<3.0.0",
|
|
28
|
+
]
|
|
29
|
+
mcp = ["mcp>=1.26.0,<2.0.0"]
|
|
30
|
+
tui = ["textual>=1.0.0,<9.0.0"]
|
|
31
|
+
all = ["ouroboros-ai[claude,litellm,mcp,tui,dashboard]"]
|
|
26
32
|
|
|
27
33
|
[project.scripts]
|
|
28
34
|
ouroboros = "ouroboros.cli.main:app"
|
|
@@ -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.27.3.
|
|
22
|
-
__version_tuple__ = version_tuple = (0, 27, 3, '
|
|
21
|
+
__version__ = version = '0.27.3.dev2'
|
|
22
|
+
__version_tuple__ = version_tuple = (0, 27, 3, 'dev2')
|
|
23
23
|
|
|
24
24
|
__commit_id__ = commit_id = None
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
"""Prompt helpers for interactive CLI input."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from prompt_toolkit import PromptSession
|
|
6
|
+
from prompt_toolkit.key_binding import KeyBindings, KeyPressEvent
|
|
7
|
+
from prompt_toolkit.patch_stdout import patch_stdout
|
|
8
|
+
|
|
9
|
+
from ouroboros.cli.formatters import console
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
async def multiline_prompt_async(prompt_text: str) -> str:
|
|
13
|
+
"""Get multiline-safe input while allowing logs above the active prompt."""
|
|
14
|
+
bindings = KeyBindings()
|
|
15
|
+
|
|
16
|
+
@bindings.add("c-j")
|
|
17
|
+
def insert_newline(event: KeyPressEvent) -> None:
|
|
18
|
+
event.current_buffer.insert_text("\n")
|
|
19
|
+
|
|
20
|
+
@bindings.add("c-m")
|
|
21
|
+
def submit(event: KeyPressEvent) -> None:
|
|
22
|
+
event.current_buffer.validate_and_handle()
|
|
23
|
+
|
|
24
|
+
console.print(f"[bold green]{prompt_text}[/] [dim](Enter: submit, Ctrl+J: newline)[/]")
|
|
25
|
+
|
|
26
|
+
session: PromptSession[str] = PromptSession(
|
|
27
|
+
message="> ",
|
|
28
|
+
multiline=True,
|
|
29
|
+
prompt_continuation=" ",
|
|
30
|
+
key_bindings=bindings,
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
# prompt_toolkit proxies both stdout and stderr above the prompt.
|
|
34
|
+
with patch_stdout(raw=True):
|
|
35
|
+
return await session.prompt_async()
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
__all__ = ["multiline_prompt_async"]
|
|
@@ -54,6 +54,8 @@ from ouroboros.core.errors import ConfigError # noqa: E402
|
|
|
54
54
|
_CODEX_LLM_BACKENDS = frozenset({"codex", "codex_cli", "opencode", "opencode_cli"})
|
|
55
55
|
_OPENCODE_BACKENDS = frozenset({"opencode", "opencode_cli"})
|
|
56
56
|
_CODEX_DEFAULT_MODEL = "default"
|
|
57
|
+
_PLACEHOLDER_API_KEY_PREFIX = "YOUR_"
|
|
58
|
+
_PLACEHOLDER_API_KEY_SUFFIX = "_API_KEY"
|
|
57
59
|
_DEFAULT_CONSENSUS_MODELS = (
|
|
58
60
|
"openrouter/openai/gpt-4o",
|
|
59
61
|
"openrouter/anthropic/claude-opus-4-6",
|
|
@@ -82,6 +84,16 @@ def _parse_env_value(raw_value: str) -> str:
|
|
|
82
84
|
return candidate.rstrip()
|
|
83
85
|
|
|
84
86
|
|
|
87
|
+
def _is_placeholder_api_key(value: str) -> bool:
|
|
88
|
+
"""Treat common template placeholders as unset."""
|
|
89
|
+
candidate = value.strip()
|
|
90
|
+
return bool(
|
|
91
|
+
candidate
|
|
92
|
+
and candidate.startswith(_PLACEHOLDER_API_KEY_PREFIX)
|
|
93
|
+
and candidate.endswith(_PLACEHOLDER_API_KEY_SUFFIX)
|
|
94
|
+
)
|
|
95
|
+
|
|
96
|
+
|
|
85
97
|
def _load_env_file(path: Path) -> None:
|
|
86
98
|
if not path.exists():
|
|
87
99
|
return
|
|
@@ -99,7 +111,14 @@ def _load_env_file(path: Path) -> None:
|
|
|
99
111
|
key = key.strip()
|
|
100
112
|
if not key or any(ch.isspace() for ch in key):
|
|
101
113
|
continue
|
|
102
|
-
|
|
114
|
+
|
|
115
|
+
parsed_value = _parse_env_value(raw_value)
|
|
116
|
+
if not parsed_value or _is_placeholder_api_key(parsed_value):
|
|
117
|
+
continue
|
|
118
|
+
|
|
119
|
+
current_value = os.environ.get(key)
|
|
120
|
+
if current_value is None or _is_placeholder_api_key(current_value):
|
|
121
|
+
os.environ[key] = parsed_value
|
|
103
122
|
|
|
104
123
|
|
|
105
124
|
for env_path in (Path(".env"), Path.home() / ".ouroboros" / ".env"):
|
|
@@ -15,14 +15,14 @@ else: # pragma: no branch
|
|
|
15
15
|
|
|
16
16
|
|
|
17
17
|
@contextmanager
|
|
18
|
-
def file_lock(file_path: Path, exclusive: bool = True) -> Iterator[None]:
|
|
18
|
+
def file_lock(file_path: Path, exclusive: bool = True) -> Iterator[None]:
|
|
19
19
|
"""Context manager for cross-platform file locking."""
|
|
20
20
|
lock_path = file_path.with_suffix(file_path.suffix + ".lock")
|
|
21
21
|
lock_path.parent.mkdir(parents=True, exist_ok=True)
|
|
22
22
|
|
|
23
23
|
with lock_path.open("a+", encoding="utf-8") as handle:
|
|
24
24
|
_ensure_lockfile_content(handle)
|
|
25
|
-
_acquire_lock(handle)
|
|
25
|
+
_acquire_lock(handle, exclusive=exclusive)
|
|
26
26
|
try:
|
|
27
27
|
yield
|
|
28
28
|
finally:
|
|
@@ -37,13 +37,13 @@ def _ensure_lockfile_content(handle: TextIO) -> None:
|
|
|
37
37
|
handle.seek(0)
|
|
38
38
|
|
|
39
39
|
|
|
40
|
-
def _acquire_lock(handle: TextIO) -> None:
|
|
40
|
+
def _acquire_lock(handle: TextIO, *, exclusive: bool = True) -> None:
|
|
41
41
|
if os.name == "nt": # pragma: no cover - exercised on Windows
|
|
42
42
|
handle.seek(0)
|
|
43
|
-
msvcrt.locking(handle.fileno(), msvcrt.LK_LOCK, 1)
|
|
43
|
+
msvcrt.locking(handle.fileno(), msvcrt.LK_RLCK if not exclusive else msvcrt.LK_LOCK, 1)
|
|
44
44
|
return
|
|
45
45
|
|
|
46
|
-
fcntl.flock(handle.fileno(), fcntl.LOCK_EX)
|
|
46
|
+
fcntl.flock(handle.fileno(), fcntl.LOCK_EX if exclusive else fcntl.LOCK_SH)
|
|
47
47
|
|
|
48
48
|
|
|
49
49
|
def _release_lock(handle: TextIO) -> None:
|
|
@@ -8,8 +8,10 @@ handling, and server lifecycle.
|
|
|
8
8
|
import asyncio
|
|
9
9
|
from collections.abc import Sequence
|
|
10
10
|
import inspect
|
|
11
|
+
import keyword
|
|
11
12
|
import os
|
|
12
13
|
from pathlib import Path
|
|
14
|
+
import re
|
|
13
15
|
from typing import Any
|
|
14
16
|
|
|
15
17
|
import structlog
|
|
@@ -105,13 +107,50 @@ def _build_tool_signature(parameters: tuple[MCPToolParameter, ...]) -> inspect.S
|
|
|
105
107
|
By setting __signature__ with explicit parameters, FastMCP generates the
|
|
106
108
|
correct schema and clients can send flat argument dicts.
|
|
107
109
|
"""
|
|
110
|
+
signature, _ = _build_tool_signature_with_aliases(parameters)
|
|
111
|
+
return signature
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
def _to_safe_signature_name(name: str) -> str:
|
|
115
|
+
"""Return a valid Python identifier for a tool parameter name."""
|
|
116
|
+
if name.isidentifier() and not keyword.iskeyword(name):
|
|
117
|
+
return name
|
|
118
|
+
|
|
119
|
+
# Replace invalid characters with underscore and avoid starting with a digit.
|
|
120
|
+
sanitized = re.sub(r"[^0-9a-zA-Z_]", "_", name)
|
|
121
|
+
sanitized = re.sub(r"_+", "_", sanitized).strip("_")
|
|
122
|
+
if not sanitized or sanitized[0].isdigit():
|
|
123
|
+
sanitized = f"_{sanitized or 'param'}"
|
|
124
|
+
|
|
125
|
+
if keyword.iskeyword(sanitized):
|
|
126
|
+
sanitized = f"_{sanitized}"
|
|
127
|
+
|
|
128
|
+
return sanitized
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
def _build_tool_signature_with_aliases(
|
|
132
|
+
parameters: tuple[MCPToolParameter, ...],
|
|
133
|
+
) -> tuple[inspect.Signature, dict[str, str]]:
|
|
134
|
+
"""Build signature plus map from schema args to original MCP parameter names."""
|
|
135
|
+
|
|
108
136
|
sig_params = []
|
|
137
|
+
alias_counts: dict[str, int] = {}
|
|
138
|
+
alias_to_original: dict[str, str] = {}
|
|
139
|
+
|
|
109
140
|
for p in parameters:
|
|
141
|
+
parameter_name = _to_safe_signature_name(p.name)
|
|
142
|
+
alias_count = alias_counts.get(parameter_name, 0) + 1
|
|
143
|
+
alias_counts[parameter_name] = alias_count
|
|
144
|
+
if alias_count > 1:
|
|
145
|
+
parameter_name = f"{parameter_name}_{alias_count}"
|
|
146
|
+
|
|
147
|
+
alias_to_original[parameter_name] = p.name
|
|
148
|
+
|
|
110
149
|
python_type = _TOOL_TYPE_MAP.get(p.type, Any)
|
|
111
150
|
if p.required:
|
|
112
151
|
sig_params.append(
|
|
113
152
|
inspect.Parameter(
|
|
114
|
-
name=
|
|
153
|
+
name=parameter_name,
|
|
115
154
|
kind=inspect.Parameter.KEYWORD_ONLY,
|
|
116
155
|
annotation=python_type,
|
|
117
156
|
)
|
|
@@ -120,13 +159,14 @@ def _build_tool_signature(parameters: tuple[MCPToolParameter, ...]) -> inspect.S
|
|
|
120
159
|
default = p.default if p.default is not None else None
|
|
121
160
|
sig_params.append(
|
|
122
161
|
inspect.Parameter(
|
|
123
|
-
name=
|
|
162
|
+
name=parameter_name,
|
|
124
163
|
kind=inspect.Parameter.KEYWORD_ONLY,
|
|
125
164
|
default=default,
|
|
126
165
|
annotation=python_type | None,
|
|
127
166
|
)
|
|
128
167
|
)
|
|
129
|
-
|
|
168
|
+
|
|
169
|
+
return inspect.Signature(parameters=sig_params), alias_to_original
|
|
130
170
|
|
|
131
171
|
|
|
132
172
|
_PROJECT_ROOT_MARKERS = (
|
|
@@ -200,11 +240,13 @@ def _project_dir_from_artifact(artifact: str) -> str | None:
|
|
|
200
240
|
from pathlib import Path
|
|
201
241
|
import re
|
|
202
242
|
|
|
203
|
-
# Match quoted paths (spaces allowed)
|
|
243
|
+
# Match quoted paths (spaces allowed) and unquoted paths.
|
|
204
244
|
# Examples: Write: /foo/bar.py | File: "/path with spaces/bar.py"
|
|
205
245
|
write_matches: list[str] = []
|
|
206
|
-
for m in re.finditer(r'(?:Write|Edit|File): (?:"([^"]+)"|(
|
|
207
|
-
|
|
246
|
+
for m in re.finditer(r'(?:Write|Edit|File): (?:"([^"]+)"|(.+))', artifact):
|
|
247
|
+
path_candidate = m.group(1) or m.group(2)
|
|
248
|
+
if path_candidate:
|
|
249
|
+
write_matches.append(path_candidate.strip())
|
|
208
250
|
for path_str in write_matches:
|
|
209
251
|
candidate = Path(path_str).parent
|
|
210
252
|
for _ in range(10):
|
|
@@ -529,7 +571,18 @@ class MCPServerAdapter:
|
|
|
529
571
|
and isinstance(kwargs["kwargs"], dict)
|
|
530
572
|
):
|
|
531
573
|
kwargs = kwargs["kwargs"]
|
|
532
|
-
|
|
574
|
+
|
|
575
|
+
_, alias_to_original = _build_tool_signature_with_aliases(
|
|
576
|
+
h.definition.parameters,
|
|
577
|
+
)
|
|
578
|
+
normalized_kwargs: dict[str, Any] = {}
|
|
579
|
+
for alias_key, original_key in alias_to_original.items():
|
|
580
|
+
if alias_key in kwargs:
|
|
581
|
+
normalized_kwargs[original_key] = kwargs[alias_key]
|
|
582
|
+
for key, value in kwargs.items():
|
|
583
|
+
normalized_kwargs.setdefault(key, value)
|
|
584
|
+
|
|
585
|
+
result = await h.handle(normalized_kwargs)
|
|
533
586
|
if result.is_ok:
|
|
534
587
|
# Convert MCPToolResult to FastMCP format
|
|
535
588
|
tool_result = result.value
|
{ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/orchestrator/mcp_tools.py
RENAMED
|
@@ -2059,6 +2059,7 @@ class MCPToolProvider:
|
|
|
2059
2059
|
|
|
2060
2060
|
try:
|
|
2061
2061
|
# Retry transient failures with bounded backoff
|
|
2062
|
+
# Use retry_async for retries on transient failures
|
|
2062
2063
|
result = await self._call_with_retry(
|
|
2063
2064
|
tool_info=tool_info,
|
|
2064
2065
|
arguments=arguments or {},
|
|
@@ -2090,7 +2091,7 @@ class MCPToolProvider:
|
|
|
2090
2091
|
) -> Result[MCPToolResult, MCPToolError]:
|
|
2091
2092
|
"""Call tool with retry logic for transient failures.
|
|
2092
2093
|
|
|
2093
|
-
Uses
|
|
2094
|
+
Uses retry_async for exponential backoff retries on:
|
|
2094
2095
|
- Connection errors
|
|
2095
2096
|
- Timeout errors (if marked retriable)
|
|
2096
2097
|
- Other transient MCPClientErrors
|
{ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/src/ouroboros/providers/litellm_adapter.py
RENAMED
|
@@ -160,6 +160,18 @@ class LiteLLMAdapter:
|
|
|
160
160
|
if configured_api_key:
|
|
161
161
|
return configured_api_key
|
|
162
162
|
|
|
163
|
+
# Unknown/custom models may still be routed through OpenRouter via credentials.
|
|
164
|
+
provider_name = self._extract_provider(model)
|
|
165
|
+
if provider_name not in {"openrouter", "openai", "anthropic", "google"}:
|
|
166
|
+
credentials = self._load_credentials_config()
|
|
167
|
+
configured = (
|
|
168
|
+
credentials.providers.get("openrouter") if credentials is not None else None
|
|
169
|
+
)
|
|
170
|
+
if configured is not None:
|
|
171
|
+
configured_api_key = self._normalize_api_key(configured.api_key)
|
|
172
|
+
if configured_api_key:
|
|
173
|
+
return configured_api_key
|
|
174
|
+
|
|
163
175
|
# Default to OpenRouter for unknown models
|
|
164
176
|
return self._normalize_api_key(os.environ.get("OPENROUTER_API_KEY"))
|
|
165
177
|
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
"""Tests for interactive prompt helpers."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import sys
|
|
6
|
+
from unittest.mock import AsyncMock, MagicMock, patch
|
|
7
|
+
|
|
8
|
+
import pytest
|
|
9
|
+
|
|
10
|
+
from ouroboros.cli.formatters.prompting import multiline_prompt_async
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
@pytest.mark.asyncio
|
|
14
|
+
async def test_multiline_prompt_async_patches_stdout_and_stderr() -> None:
|
|
15
|
+
"""The shared prompt helper should proxy both stdout and stderr during input."""
|
|
16
|
+
session = MagicMock()
|
|
17
|
+
session.prompt_async = AsyncMock()
|
|
18
|
+
|
|
19
|
+
async def fake_prompt_async() -> str:
|
|
20
|
+
assert sys.stdout is not sys.__stdout__
|
|
21
|
+
assert sys.stderr is not sys.__stderr__
|
|
22
|
+
return "line 1\nline 2"
|
|
23
|
+
|
|
24
|
+
session.prompt_async.side_effect = fake_prompt_async
|
|
25
|
+
|
|
26
|
+
with (
|
|
27
|
+
patch(
|
|
28
|
+
"ouroboros.cli.formatters.prompting.PromptSession", return_value=session
|
|
29
|
+
) as mock_session,
|
|
30
|
+
patch("ouroboros.cli.formatters.prompting.console.print"),
|
|
31
|
+
):
|
|
32
|
+
result = await multiline_prompt_async("Prompt here")
|
|
33
|
+
|
|
34
|
+
assert result == "line 1\nline 2"
|
|
35
|
+
session.prompt_async.assert_awaited_once()
|
|
36
|
+
|
|
37
|
+
kwargs = mock_session.call_args.kwargs
|
|
38
|
+
assert kwargs["message"] == "> "
|
|
39
|
+
assert kwargs["multiline"] is True
|
|
40
|
+
assert kwargs["prompt_continuation"] == " "
|
|
41
|
+
|
|
42
|
+
key_bindings = kwargs["key_bindings"]
|
|
43
|
+
bound_keys = {tuple(binding.keys) for binding in key_bindings.bindings}
|
|
44
|
+
assert ("c-j",) in bound_keys
|
|
45
|
+
assert ("c-m",) in bound_keys
|
|
@@ -34,3 +34,19 @@ def test_load_env_file_does_not_override_existing_values(
|
|
|
34
34
|
_load_env_file(env_file)
|
|
35
35
|
|
|
36
36
|
assert os.environ["FIRST"] == "existing"
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def test_load_env_file_skips_template_placeholders(tmp_path: Path, monkeypatch) -> None:
|
|
40
|
+
"""Template placeholders should not block later env values from loading."""
|
|
41
|
+
repo_env = tmp_path / "repo.env"
|
|
42
|
+
home_env = tmp_path / "home.env"
|
|
43
|
+
|
|
44
|
+
repo_env.write_text("OPENROUTER_API_KEY=YOUR_OPENROUTER_API_KEY")
|
|
45
|
+
home_env.write_text("OPENROUTER_API_KEY=real-key")
|
|
46
|
+
|
|
47
|
+
monkeypatch.delenv("OPENROUTER_API_KEY", raising=False)
|
|
48
|
+
|
|
49
|
+
_load_env_file(repo_env)
|
|
50
|
+
_load_env_file(home_env)
|
|
51
|
+
|
|
52
|
+
assert os.environ["OPENROUTER_API_KEY"] == "real-key"
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
"""Tests for stdlib-backed file locking."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
from unittest.mock import MagicMock
|
|
7
|
+
|
|
8
|
+
import ouroboros.core.file_lock as file_lock_module
|
|
9
|
+
from ouroboros.core.file_lock import _acquire_lock, _release_lock, file_lock
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def test_file_lock_creates_lockfile(tmp_path: Path) -> None:
|
|
13
|
+
target = tmp_path / "state.json"
|
|
14
|
+
target.write_text("{}")
|
|
15
|
+
|
|
16
|
+
with file_lock(target):
|
|
17
|
+
lock_path = target.with_suffix(".json.lock")
|
|
18
|
+
assert lock_path.exists()
|
|
19
|
+
assert lock_path.read_text() == "0"
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def test_file_lock_exclusive_false_acquires_shared_lock(tmp_path: Path) -> None:
|
|
23
|
+
"""Shared (non-exclusive) locks should allow concurrent readers."""
|
|
24
|
+
target = tmp_path / "data.json"
|
|
25
|
+
target.write_text("{}")
|
|
26
|
+
|
|
27
|
+
with file_lock(target, exclusive=False):
|
|
28
|
+
lock_path = target.with_suffix(".json.lock")
|
|
29
|
+
assert lock_path.exists()
|
|
30
|
+
# A second shared lock on the same file should not block
|
|
31
|
+
with file_lock(target, exclusive=False):
|
|
32
|
+
assert lock_path.exists()
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def test_file_lock_windows_shared_uses_read_lock_mode(monkeypatch, tmp_path: Path) -> None:
|
|
36
|
+
"""On Windows, non-exclusive lock requests should use a shared/read mode."""
|
|
37
|
+
target = tmp_path / "shared.json"
|
|
38
|
+
target.write_text("{}")
|
|
39
|
+
with target.open("a+", encoding="utf-8") as handle:
|
|
40
|
+
fd = handle.fileno()
|
|
41
|
+
mock_msvcrt = MagicMock()
|
|
42
|
+
mock_msvcrt.LK_LOCK = 1
|
|
43
|
+
mock_msvcrt.LK_RLCK = 2
|
|
44
|
+
mock_msvcrt.LK_UNLCK = 3
|
|
45
|
+
monkeypatch.setattr(file_lock_module, "msvcrt", mock_msvcrt, raising=False)
|
|
46
|
+
monkeypatch.setattr(file_lock_module.os, "name", "nt")
|
|
47
|
+
|
|
48
|
+
_acquire_lock(handle, exclusive=False)
|
|
49
|
+
_release_lock(handle)
|
|
50
|
+
|
|
51
|
+
mock_msvcrt.locking.assert_any_call(fd, mock_msvcrt.LK_RLCK, 1)
|
|
52
|
+
mock_msvcrt.locking.assert_any_call(fd, mock_msvcrt.LK_UNLCK, 1)
|
|
@@ -11,6 +11,7 @@ from ouroboros.mcp.errors import MCPResourceNotFoundError, MCPServerError
|
|
|
11
11
|
from ouroboros.mcp.server.adapter import (
|
|
12
12
|
VALID_TRANSPORTS,
|
|
13
13
|
MCPServerAdapter,
|
|
14
|
+
_build_tool_signature_with_aliases,
|
|
14
15
|
_extract_feedback_metadata_from_artifact,
|
|
15
16
|
_project_dir_from_artifact,
|
|
16
17
|
_project_dir_from_seed,
|
|
@@ -119,6 +120,34 @@ class TestMCPServerAdapter:
|
|
|
119
120
|
|
|
120
121
|
assert _project_dir_from_artifact(artifact) == str(project_dir)
|
|
121
122
|
|
|
123
|
+
def test_project_dir_from_artifact_handles_spaces_in_paths(self, tmp_path) -> None:
|
|
124
|
+
"""Artifact extraction should detect spaced file paths."""
|
|
125
|
+
project_dir = tmp_path / "my project"
|
|
126
|
+
nested_dir = project_dir / "src" / "components"
|
|
127
|
+
nested_dir.mkdir(parents=True)
|
|
128
|
+
(project_dir / "pyproject.toml").write_text("[build-system]")
|
|
129
|
+
|
|
130
|
+
artifact = f"Edit: {nested_dir / 'app.tsx'}"
|
|
131
|
+
|
|
132
|
+
assert _project_dir_from_artifact(artifact) == str(project_dir)
|
|
133
|
+
|
|
134
|
+
def test_build_tool_signature_sanitizes_non_identifier_parameter_names(self) -> None:
|
|
135
|
+
"""Invalid MCP parameter names are sanitized to valid Python signatures."""
|
|
136
|
+
parameters = (
|
|
137
|
+
MCPToolParameter(name="file-path", type=ToolInputType.STRING),
|
|
138
|
+
MCPToolParameter(name="max.tokens", type=ToolInputType.INTEGER),
|
|
139
|
+
MCPToolParameter(name="class", type=ToolInputType.BOOLEAN),
|
|
140
|
+
)
|
|
141
|
+
|
|
142
|
+
signature, aliases = _build_tool_signature_with_aliases(parameters)
|
|
143
|
+
names = tuple(param.name for param in signature.parameters.values())
|
|
144
|
+
assert names == ("file_path", "max_tokens", "_class")
|
|
145
|
+
assert aliases == {
|
|
146
|
+
"file_path": "file-path",
|
|
147
|
+
"max_tokens": "max.tokens",
|
|
148
|
+
"_class": "class",
|
|
149
|
+
}
|
|
150
|
+
|
|
122
151
|
def test_extract_feedback_metadata_from_artifact_parses_structured_warning(self) -> None:
|
|
123
152
|
"""Execution artifacts should expose structured evaluation feedback metadata."""
|
|
124
153
|
artifact = """
|
{ouroboros_ai-0.27.3.dev1 → ouroboros_ai-0.27.3.dev2}/tests/unit/providers/test_litellm_adapter.py
RENAMED
|
@@ -128,6 +128,26 @@ class TestLiteLLMAdapterGetApiKey:
|
|
|
128
128
|
|
|
129
129
|
assert result == "or-key"
|
|
130
130
|
|
|
131
|
+
def test_unknown_model_uses_openrouter_credentials_fallback(self) -> None:
|
|
132
|
+
"""Unknown models can resolve credentials from the openrouter provider."""
|
|
133
|
+
adapter = LiteLLMAdapter()
|
|
134
|
+
credentials = CredentialsConfig(
|
|
135
|
+
providers={
|
|
136
|
+
"openrouter": ProviderCredentials(
|
|
137
|
+
api_key="cred-openrouter-key",
|
|
138
|
+
base_url="https://openrouter.example/v1",
|
|
139
|
+
),
|
|
140
|
+
}
|
|
141
|
+
)
|
|
142
|
+
|
|
143
|
+
with (
|
|
144
|
+
patch.dict("os.environ", {}, clear=True),
|
|
145
|
+
patch.object(adapter, "_load_credentials_config", return_value=credentials),
|
|
146
|
+
):
|
|
147
|
+
result = adapter._get_api_key("acme/gpt-4-custom")
|
|
148
|
+
|
|
149
|
+
assert result == "cred-openrouter-key"
|
|
150
|
+
|
|
131
151
|
def test_missing_env_var_returns_none(self) -> None:
|
|
132
152
|
"""Returns None if no environment variable is set."""
|
|
133
153
|
adapter = LiteLLMAdapter()
|