ouroboros-ai 0.26.5.dev1__tar.gz → 0.26.5.dev3__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.dev1 → ouroboros_ai-0.26.5.dev3}/PKG-INFO +1 -1
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/skills/pm/SKILL.md +27 -15
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/_version.py +2 -2
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/bigbang/pm_interview.py +98 -45
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/bigbang/question_classifier.py +24 -12
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/cli/commands/init.py +3 -44
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/cli/commands/pm.py +61 -2
- ouroboros_ai-0.26.5.dev3/src/ouroboros/cli/formatters/prompting.py +38 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/mcp/tools/pm_handler.py +236 -38
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/bigbang/test_decide_later_items.py +155 -106
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/bigbang/test_pm_interview.py +52 -145
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/bigbang/test_question_classifier.py +7 -7
- ouroboros_ai-0.26.5.dev3/tests/unit/cli/formatters/test_prompting.py +45 -0
- ouroboros_ai-0.26.5.dev3/tests/unit/cli/test_pm_interactive_logging.py +212 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/mcp/tools/test_pm_handler.py +277 -12
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/.claude/settings.json +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/.claude-plugin/.mcp.json +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/.claude-plugin/marketplace.json +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/.claude-plugin/plugin.json +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/.env.example +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/.github/ISSUE_TEMPLATE/config.yml +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/.github/ISSUE_TEMPLATE/feature_request.yml +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/.github/ISSUE_TEMPLATE/question.yml +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/.github/workflows/dev-publish.yml +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/.github/workflows/lint.yml +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/.github/workflows/release.yml +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/.github/workflows/test.yml +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/.gitignore +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/.mcp.json +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/.ouroboros/mechanical.toml +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/.pre-commit-config.yaml +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/.python-version +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/CHANGELOG.md +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/CLAUDE.md +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/CODE_OF_CONDUCT.md +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/CONTRIBUTING.md +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/HANDOFF.md +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/LICENSE +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/README.ko.md +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/README.md +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/SECURITY.md +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/UNINSTALL.md +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/commands/cancel.md +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/commands/evaluate.md +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/commands/evolve.md +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/commands/help.md +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/commands/interview.md +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/commands/ralph.md +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/commands/run.md +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/commands/seed.md +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/commands/setup.md +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/commands/status.md +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/commands/tutorial.md +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/commands/unstuck.md +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/commands/welcome.md +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/crates/ouroboros-tui/.gitignore +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/crates/ouroboros-tui/Cargo.lock +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/crates/ouroboros-tui/Cargo.toml +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/crates/ouroboros-tui/README.md +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/crates/ouroboros-tui/src/db.rs +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/crates/ouroboros-tui/src/main.rs +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/crates/ouroboros-tui/src/mock.rs +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/crates/ouroboros-tui/src/state.rs +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/crates/ouroboros-tui/src/views/dashboard.rs +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/crates/ouroboros-tui/src/views/execution.rs +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/crates/ouroboros-tui/src/views/lineage.rs +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/crates/ouroboros-tui/src/views/logs.rs +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/crates/ouroboros-tui/src/views/mod.rs +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/crates/ouroboros-tui/src/views/session_selector.rs +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/docs/README.md +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/docs/api/README.md +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/docs/api/core.md +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/docs/api/mcp.md +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/docs/architecture.md +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/docs/cli-reference.md +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/docs/config-reference.md +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/docs/contributing/architecture-overview.md +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/docs/contributing/findings-registry.md +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/docs/contributing/issue-quality-policy.md +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/docs/contributing/key-patterns.md +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/docs/contributing/testing-guide.md +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/docs/examples/mcp-config.yaml +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/docs/getting-started.md +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/docs/guides/evaluation-pipeline.md +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/docs/guides/evolution-loop.md +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/docs/guides/issue-176-subagent-mcp-inheritance.md +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/docs/guides/seed-authoring.md +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/docs/guides/tui-usage.md +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/docs/images/PLACEHOLDER_README.md +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/docs/images/ouroboros.png +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/docs/platform-support.md +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/docs/runtime-capability-matrix.md +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/docs/runtime-guides/claude-code.md +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/docs/runtime-guides/codex.md +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/examples/coordinator_test_seed.yaml +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/examples/dummy_seed.yaml +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/examples/parallel_subac_test_seed.yaml +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/examples/subac_test_seed.yaml +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/examples/task_manager/README.md +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/examples/task_manager/__init__.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/examples/task_manager/__main__.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/examples/task_manager/cli.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/examples/task_manager/models.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/examples/task_manager/storage.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/examples/test_display.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/hooks/hooks.json +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/llms-full.txt +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/llms.txt +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/project-context.md +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/pyproject.toml +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/scripts/drift-monitor.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/scripts/install.sh +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/scripts/keyword-detector.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/scripts/mcp-serve.sh +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/scripts/ralph-rewind.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/scripts/ralph.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/scripts/ralph.sh +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/scripts/session-start.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/scripts/sync-plugin-version.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/scripts/version-check.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/skills/brownfield/SKILL.md +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/skills/cancel/SKILL.md +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/skills/evaluate/SKILL.md +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/skills/evolve/SKILL.md +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/skills/help/SKILL.md +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/skills/interview/SKILL.md +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/skills/qa/SKILL.md +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/skills/ralph/SKILL.md +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/skills/run/SKILL.md +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/skills/seed/SKILL.md +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/skills/setup/SKILL.md +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/skills/status/SKILL.md +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/skills/tutorial/SKILL.md +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/skills/unstuck/SKILL.md +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/skills/update/SKILL.md +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/skills/welcome/SKILL.md +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/__init__.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/__main__.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/agents/__init__.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/agents/advocate.md +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/agents/analysis-agent.md +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/agents/architect.md +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/agents/breadth-keeper.md +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/agents/code-executor.md +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/agents/codebase-explorer.md +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/agents/consensus-reviewer.md +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/agents/contrarian.md +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/agents/evaluator.md +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/agents/hacker.md +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/agents/judge.md +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/agents/loader.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/agents/ontologist.md +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/agents/ontology-analyst.md +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/agents/qa-judge.md +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/agents/research-agent.md +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/agents/researcher.md +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/agents/seed-architect.md +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/agents/seed-closer.md +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/agents/semantic-evaluator.md +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/agents/simplifier.md +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/agents/socratic-interviewer.md +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/bigbang/__init__.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/bigbang/ambiguity.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/bigbang/brownfield.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/bigbang/explore.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/bigbang/interview.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/bigbang/pm_document.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/bigbang/pm_seed.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/bigbang/seed_generator.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/cli/__init__.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/cli/commands/__init__.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/cli/commands/cancel.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/cli/commands/config.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/cli/commands/mcp.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/cli/commands/run.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/cli/commands/setup.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/cli/commands/status.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/cli/commands/tui.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/cli/commands/uninstall.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/cli/formatters/__init__.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/cli/formatters/panels.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/cli/formatters/progress.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/cli/formatters/tables.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/cli/formatters/workflow_display.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/cli/main.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/codex/__init__.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/codex/artifacts.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/codex/ouroboros.md +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/codex_permissions.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/config/__init__.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/config/loader.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/config/models.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/core/__init__.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/core/ac_tree.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/core/context.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/core/errors.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/core/file_lock.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/core/git_workflow.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/core/lineage.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/core/ontology_aspect.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/core/ontology_questions.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/core/project_paths.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/core/security.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/core/seed.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/core/text.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/core/types.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/core/worktree.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/evaluation/__init__.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/evaluation/artifact_collector.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/evaluation/consensus.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/evaluation/json_utils.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/evaluation/languages.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/evaluation/mechanical.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/evaluation/models.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/evaluation/pipeline.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/evaluation/semantic.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/evaluation/trigger.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/evaluation/verification_artifacts.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/events/__init__.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/events/base.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/events/decomposition.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/events/evaluation.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/events/interview.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/events/lineage.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/events/ontology.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/evolution/__init__.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/evolution/convergence.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/evolution/loop.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/evolution/projector.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/evolution/reflect.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/evolution/regression.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/evolution/wonder.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/execution/__init__.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/execution/atomicity.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/execution/decomposition.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/execution/double_diamond.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/execution/subagent.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/mcp/__init__.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/mcp/client/__init__.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/mcp/client/adapter.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/mcp/client/manager.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/mcp/client/protocol.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/mcp/errors.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/mcp/job_manager.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/mcp/resources/__init__.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/mcp/resources/handlers.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/mcp/server/__init__.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/mcp/server/adapter.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/mcp/server/protocol.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/mcp/server/security.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/mcp/tools/__init__.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/mcp/tools/authoring_handlers.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/mcp/tools/brownfield_handler.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/mcp/tools/dashboard.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/mcp/tools/definitions.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/mcp/tools/evaluation_handlers.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/mcp/tools/evolution_handlers.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/mcp/tools/execution_handlers.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/mcp/tools/job_handlers.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/mcp/tools/qa.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/mcp/tools/query_handlers.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/mcp/tools/registry.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/mcp/types.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/observability/__init__.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/observability/drift.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/observability/logging.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/observability/retrospective.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/orchestrator/__init__.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/orchestrator/adapter.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/orchestrator/codex_cli_runtime.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/orchestrator/command_dispatcher.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/orchestrator/coordinator.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/orchestrator/dependency_analyzer.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/orchestrator/events.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/orchestrator/execution_runtime_scope.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/orchestrator/execution_strategy.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/orchestrator/heartbeat.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/orchestrator/level_context.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/orchestrator/mcp_config.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/orchestrator/mcp_tools.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/orchestrator/parallel_executor.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/orchestrator/parallel_executor_models.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/orchestrator/runner.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/orchestrator/runtime_factory.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/orchestrator/runtime_message_projection.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/orchestrator/session.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/orchestrator/workflow_state.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/persistence/__init__.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/persistence/brownfield.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/persistence/checkpoint.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/persistence/event_store.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/persistence/migrations/__init__.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/persistence/migrations/runner.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/persistence/migrations/scripts/001_initial.sql +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/persistence/migrations/scripts/002_brownfield.sql +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/persistence/schema.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/persistence/uow.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/plugin/__init__.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/plugin/agents/__init__.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/plugin/agents/pool.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/plugin/agents/registry.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/plugin/orchestration/__init__.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/plugin/orchestration/router.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/plugin/orchestration/scheduler.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/plugin/skills/__init__.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/plugin/skills/docs.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/plugin/skills/executor.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/plugin/skills/keywords.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/plugin/skills/registry.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/pm/__init__.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/pm/renderer.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/providers/__init__.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/providers/anthropic_adapter.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/providers/base.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/providers/claude_code_adapter.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/providers/codex_cli_adapter.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/providers/codex_cli_stream.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/providers/factory.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/providers/litellm_adapter.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/py.typed +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/resilience/__init__.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/resilience/lateral.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/resilience/stagnation.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/routing/__init__.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/routing/complexity.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/routing/downgrade.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/routing/escalation.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/routing/router.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/routing/tiers.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/secondary/__init__.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/secondary/scheduler.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/secondary/todo_registry.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/strategies/__init__.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/strategies/devil_advocate.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/tui/__init__.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/tui/app.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/tui/components/__init__.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/tui/components/agents_panel.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/tui/components/event_log.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/tui/components/progress.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/tui/components/token_tracker.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/tui/events.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/tui/screens/__init__.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/tui/screens/confirm_rewind.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/tui/screens/dashboard.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/tui/screens/dashboard_v2.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/tui/screens/dashboard_v3.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/tui/screens/debug.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/tui/screens/execution.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/tui/screens/hud_dashboard.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/tui/screens/lineage_detail.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/tui/screens/lineage_selector.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/tui/screens/logs.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/tui/screens/session_selector.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/tui/widgets/__init__.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/tui/widgets/ac_progress.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/tui/widgets/ac_tree.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/tui/widgets/agent_activity.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/tui/widgets/cost_tracker.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/tui/widgets/drift_meter.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/tui/widgets/lineage_tree.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/tui/widgets/parallel_graph.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/tui/widgets/phase_progress.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/verification/__init__.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/verification/extractor.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/verification/models.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/verification/verifier.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/__init__.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/conftest.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/e2e/__init__.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/e2e/conftest.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/e2e/test_cli_commands.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/e2e/test_full_workflow.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/e2e/test_session_persistence.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/fixtures/test_atomicity_seed.yml +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/integration/__init__.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/integration/conftest.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/integration/mcp/__init__.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/integration/mcp/conftest.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/integration/mcp/test_client_adapter.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/integration/mcp/test_client_manager.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/integration/mcp/test_server_adapter.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/integration/plugin/test_orchestration.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/integration/test_codex_cli_passthrough_smoke.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/integration/test_codex_skill_fallback.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/integration/test_codex_skill_smoke.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/integration/test_entry_point.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/__init__.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/agents/__init__.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/agents/test_loader.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/bigbang/__init__.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/bigbang/test_ambiguity.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/bigbang/test_brownfield.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/bigbang/test_classifier_context.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/bigbang/test_explore.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/bigbang/test_interview.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/bigbang/test_pm_document_generator.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/bigbang/test_pm_document_writer.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/bigbang/test_pm_interview_brownfield_db.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/bigbang/test_pm_seed_ac12.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/bigbang/test_pm_seed_save.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/bigbang/test_seed_generator.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/cli/__init__.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/cli/formatters/__init__.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/cli/formatters/test_console.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/cli/formatters/test_panels.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/cli/formatters/test_progress.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/cli/formatters/test_tables.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/cli/formatters/test_workflow_display.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/cli/test_cancel.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/cli/test_config.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/cli/test_init_pm_seed_detection.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/cli/test_init_runtime.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/cli/test_main.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/cli/test_mcp_nested_guard.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/cli/test_mcp_startup_cleanup.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/cli/test_pm.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/cli/test_pm_brownfield.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/cli/test_pm_missing_litellm.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/cli/test_pm_overwrite.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/cli/test_pm_select_repos.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/cli/test_run_qa.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/cli/test_setup.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/cli/test_uninstall.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/config/__init__.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/config/test_loader.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/config/test_models.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/core/__init__.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/core/test_ac_tree.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/core/test_context.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/core/test_errors.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/core/test_git_workflow.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/core/test_lineage.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/core/test_ontology_aspect.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/core/test_ontology_questions.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/core/test_security.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/core/test_seed.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/core/test_types.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/core/test_worktree.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/evaluation/__init__.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/evaluation/test_consensus.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/evaluation/test_json_utils.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/evaluation/test_languages.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/evaluation/test_mechanical.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/evaluation/test_models.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/evaluation/test_semantic.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/evaluation/test_trigger.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/evaluation/test_verification_artifacts.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/events/__init__.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/events/test_base.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/events/test_decomposition_events.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/evolution/test_wonder_scope.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/execution/__init__.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/execution/test_atomicity.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/execution/test_decomposition.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/execution/test_double_diamond.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/execution/test_subagent_isolation.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/mcp/__init__.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/mcp/client/__init__.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/mcp/client/test_adapter.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/mcp/client/test_manager.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/mcp/conftest.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/mcp/server/__init__.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/mcp/server/test_adapter.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/mcp/server/test_security.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/mcp/test_errors.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/mcp/test_job_manager.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/mcp/test_types.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/mcp/tools/__init__.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/mcp/tools/conftest.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/mcp/tools/test_brownfield_handler.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/mcp/tools/test_definitions.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/mcp/tools/test_pm_handler_generate.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/mcp/tools/test_pm_handler_pending_reframe.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/mcp/tools/test_qa_integration.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/mcp/tools/test_registry.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/observability/__init__.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/observability/test_drift.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/observability/test_logging.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/observability/test_retrospective.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/orchestrator/__init__.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/orchestrator/test_adapter.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/orchestrator/test_codex_cli_runtime.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/orchestrator/test_codex_recursion_guard.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/orchestrator/test_command_dispatcher.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/orchestrator/test_coordinator.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/orchestrator/test_dependency_analyzer.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/orchestrator/test_events.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/orchestrator/test_execution_runtime_scope.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/orchestrator/test_execution_strategy.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/orchestrator/test_inflight_cancellation.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/orchestrator/test_level_context.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/orchestrator/test_mcp_config.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/orchestrator/test_mcp_tools.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/orchestrator/test_parallel_executor.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/orchestrator/test_parallel_executor_retry_resume.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/orchestrator/test_runner.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/orchestrator/test_runner_cancellation.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/orchestrator/test_runtime_factory.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/orchestrator/test_runtime_message_projection.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/orchestrator/test_session.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/orchestrator/test_workflow_state.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/persistence/__init__.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/persistence/test_brownfield_store.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/persistence/test_checkpoint.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/persistence/test_event_store.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/persistence/test_schema.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/persistence/test_uow.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/plugin/__init__.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/plugin/agents/__init__.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/plugin/agents/test_registry.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/plugin/orchestration/__init__.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/plugin/orchestration/test_model_router.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/plugin/skills/__init__.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/plugin/skills/test_keywords.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/plugin/skills/test_registry.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/pm/__init__.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/pm/test_renderer.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/providers/__init__.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/providers/test_base.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/providers/test_claude_code_adapter.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/providers/test_codex_cli_adapter.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/providers/test_factory.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/providers/test_litellm_adapter.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/resilience/__init__.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/resilience/test_lateral.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/resilience/test_stagnation.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/routing/__init__.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/routing/test_complexity.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/routing/test_downgrade.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/routing/test_escalation.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/routing/test_router.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/routing/test_tiers.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/scripts/test_keyword_detector.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/scripts/test_version_check.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/secondary/__init__.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/secondary/test_scheduler.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/secondary/test_todo_registry.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/test_artifact_collector.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/test_codex_artifacts.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/test_convergence.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/test_dashboard.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/test_dependencies_configured.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/test_evolve_rewind.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/test_evolve_step.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/test_graceful_shutdown.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/test_main_entry_point.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/test_module_structure.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/test_project_initialization.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/test_projector_rewind.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/test_ralph_parser.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/test_ralph_rewind.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/test_regression.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/test_tooling_configuration.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/test_verification.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/tui/__init__.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/tui/test_app.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/tui/test_cancelled_display.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/tui/test_events.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/tui/test_lineage_viewer.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/tui/test_screens.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/tui/test_session_selector_replay.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tests/unit/tui/test_widgets.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/tools/sync_github_project.py +0 -0
- {ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/uv.lock +0 -0
|
@@ -66,41 +66,53 @@ Then check: does `meta.ask_user_question` exist?
|
|
|
66
66
|
```
|
|
67
67
|
Do NOT modify it. Do NOT add options. Do NOT rephrase the question.
|
|
68
68
|
|
|
69
|
-
- **NO** → This is an interview question. Use `AskUserQuestion` with `meta.question
|
|
69
|
+
- **NO** → This is an interview question. Use `AskUserQuestion` with `meta.question`.
|
|
70
|
+
- If `meta.skip_eligible == true`: add a skip option based on `meta.classification`:
|
|
71
|
+
- `classification == "decide_later"` → add option `{"label": "Decide later", "description": "Skip — will be recorded as an open item in the PRD"}`
|
|
72
|
+
- `classification == "deferred"` → add option `{"label": "Defer to dev", "description": "Skip — this technical decision will be deferred to the development phase"}`
|
|
73
|
+
- Generate 2-3 suggested answers as the other options.
|
|
70
74
|
|
|
71
75
|
**C. Relay answer back:**
|
|
72
76
|
|
|
77
|
+
If the user chose "Decide later" → send `answer="[decide_later]"`.
|
|
78
|
+
If the user chose "Defer to dev" → send `answer="[deferred]"`.
|
|
79
|
+
Otherwise → send the user's answer normally.
|
|
80
|
+
|
|
73
81
|
```
|
|
74
82
|
Tool: ouroboros_pm_interview
|
|
75
83
|
Arguments:
|
|
76
84
|
session_id: <meta.session_id>
|
|
77
|
-
<meta.response_param>: <user's answer>
|
|
85
|
+
<meta.response_param>: <user's answer or "[decide_later]" or "[deferred]">
|
|
78
86
|
```
|
|
79
87
|
|
|
80
88
|
**D. Check completion:**
|
|
81
89
|
|
|
82
|
-
|
|
83
|
-
|
|
90
|
+
Completion is determined ONLY by `meta.is_complete` — NEVER by the response text.
|
|
91
|
+
The MCP response text may sound like the interview is wrapping up, but ignore it.
|
|
84
92
|
|
|
85
|
-
|
|
93
|
+
If `meta.is_complete == true`:
|
|
94
|
+
- If `meta.generation_failed == true` → retry generation:
|
|
95
|
+
```
|
|
96
|
+
Tool: ouroboros_pm_interview
|
|
97
|
+
Arguments:
|
|
98
|
+
session_id: <session_id>
|
|
99
|
+
action: "generate"
|
|
100
|
+
cwd: <current working directory>
|
|
101
|
+
```
|
|
102
|
+
- Otherwise → go to Step 4. The MCP auto-generated the PM document.
|
|
103
|
+
`meta.pm_path` and `meta.seed_path` contain the file paths.
|
|
86
104
|
|
|
87
|
-
|
|
88
|
-
Tool: ouroboros_pm_interview
|
|
89
|
-
Arguments:
|
|
90
|
-
session_id: <session_id>
|
|
91
|
-
action: "generate"
|
|
92
|
-
cwd: <current working directory>
|
|
93
|
-
```
|
|
105
|
+
Otherwise → repeat Step 3, regardless of what the response text says.
|
|
94
106
|
|
|
95
|
-
### Step
|
|
107
|
+
### Step 4: Copy to Clipboard
|
|
96
108
|
|
|
97
|
-
|
|
109
|
+
Read the pm.md file from `meta.pm_path` and copy its contents to the clipboard:
|
|
98
110
|
|
|
99
111
|
```bash
|
|
100
112
|
cat <meta.pm_path> | pbcopy
|
|
101
113
|
```
|
|
102
114
|
|
|
103
|
-
### Step
|
|
115
|
+
### Step 5: Show Result & Next Step
|
|
104
116
|
|
|
105
117
|
Show the following to the user:
|
|
106
118
|
|
|
@@ -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.dev3'
|
|
22
|
+
__version_tuple__ = version_tuple = (0, 26, 5, 'dev3')
|
|
23
23
|
|
|
24
24
|
__commit_id__ = commit_id = None
|
|
@@ -55,18 +55,7 @@ _SEED_DIR = Path.home() / ".ouroboros" / "seeds"
|
|
|
55
55
|
_PM_SYSTEM_PROMPT_PREFIX = """\
|
|
56
56
|
You are a Product Requirements interviewer helping a PM define their product.
|
|
57
57
|
|
|
58
|
-
Focus on
|
|
59
|
-
- What problem does this solve and for whom?
|
|
60
|
-
- What are the business goals and success metrics?
|
|
61
|
-
- What are the user stories and workflows?
|
|
62
|
-
- What constraints exist (timeline, budget, compliance)?
|
|
63
|
-
- What is in scope vs out of scope?
|
|
64
|
-
- What are the acceptance criteria?
|
|
65
|
-
|
|
66
|
-
Do NOT ask about:
|
|
67
|
-
- Implementation details (databases, frameworks, APIs)
|
|
68
|
-
- Architecture decisions (microservices, deployment)
|
|
69
|
-
- Code-level patterns or testing strategies
|
|
58
|
+
Focus on: goal, user stories, constraints, success criteria, assumptions.
|
|
70
59
|
|
|
71
60
|
"""
|
|
72
61
|
|
|
@@ -158,7 +147,8 @@ class PMInterviewEngine:
|
|
|
158
147
|
"""Original question text for questions classified as DECIDE_LATER.
|
|
159
148
|
|
|
160
149
|
These are questions that are premature or unknowable at the PM stage.
|
|
161
|
-
|
|
150
|
+
The main session presents the question to the user with a "decide later"
|
|
151
|
+
option; when chosen, the caller records the item here so the PMSeed
|
|
162
152
|
and PM document can surface them as explicit "decide later" decisions.
|
|
163
153
|
"""
|
|
164
154
|
classifications: list[ClassificationResult] = field(default_factory=list)
|
|
@@ -484,47 +474,39 @@ class PMInterviewEngine:
|
|
|
484
474
|
output_type = classification.output_type
|
|
485
475
|
|
|
486
476
|
if output_type == ClassifierOutputType.DEFERRED:
|
|
487
|
-
#
|
|
488
|
-
|
|
477
|
+
# Return the question to the caller (main session) so the user
|
|
478
|
+
# can choose to defer it themselves. The main session detects
|
|
479
|
+
# classification == "deferred" via response_meta and offers
|
|
480
|
+
# a "skip / defer to dev" option. If the user picks it, the
|
|
481
|
+
# caller calls skip_as_deferred() which records the deferral
|
|
482
|
+
# and appends to deferred_items.
|
|
483
|
+
#
|
|
484
|
+
# Previously this branch auto-answered and recursed, which could
|
|
485
|
+
# trigger MCP 120s timeouts on consecutive DEFERRED runs.
|
|
489
486
|
log.info(
|
|
490
|
-
"pm.
|
|
487
|
+
"pm.question_deferred_candidate",
|
|
491
488
|
question=classification.original_question[:100],
|
|
492
489
|
reasoning=classification.reasoning,
|
|
493
490
|
output_type=output_type,
|
|
494
491
|
)
|
|
495
|
-
|
|
496
|
-
# so the round is properly recorded and the engine advances.
|
|
497
|
-
# This prevents the inner engine from re-generating similar
|
|
498
|
-
# technical questions it doesn't know were already handled.
|
|
499
|
-
await self.record_response(
|
|
500
|
-
state,
|
|
501
|
-
user_response="[Deferred to development phase] "
|
|
502
|
-
"This technical decision will be addressed during the "
|
|
503
|
-
"development interview.",
|
|
504
|
-
question=classification.original_question,
|
|
505
|
-
)
|
|
506
|
-
# Recursively ask for the next real question
|
|
507
|
-
return await self.ask_next_question(state)
|
|
492
|
+
return Result.ok(classification.original_question)
|
|
508
493
|
|
|
509
494
|
if output_type == ClassifierOutputType.DECIDE_LATER:
|
|
510
|
-
#
|
|
511
|
-
|
|
512
|
-
|
|
495
|
+
# Return the question to the caller (main session) so the user
|
|
496
|
+
# can choose "decide later" themselves. The main session detects
|
|
497
|
+
# classification == "decide_later" via response_meta and offers
|
|
498
|
+
# the option. If the user picks it, the caller calls
|
|
499
|
+
# skip_as_decide_later() which records the placeholder and
|
|
500
|
+
# appends to decide_later_items.
|
|
501
|
+
#
|
|
502
|
+
# Previously this branch auto-answered and recursed, which could
|
|
503
|
+
# trigger MCP 120s timeouts on consecutive DECIDE_LATER runs.
|
|
513
504
|
log.info(
|
|
514
505
|
"pm.question_decide_later",
|
|
515
506
|
question=classification.original_question[:100],
|
|
516
|
-
placeholder=placeholder[:100],
|
|
517
507
|
reasoning=classification.reasoning,
|
|
518
508
|
)
|
|
519
|
-
|
|
520
|
-
# engine advances its round count
|
|
521
|
-
await self.record_response(
|
|
522
|
-
state,
|
|
523
|
-
user_response=f"[Decide later] {placeholder}",
|
|
524
|
-
question=classification.original_question,
|
|
525
|
-
)
|
|
526
|
-
# Recursively ask for the next real question
|
|
527
|
-
return await self.ask_next_question(state)
|
|
509
|
+
return Result.ok(classification.original_question)
|
|
528
510
|
|
|
529
511
|
if output_type == ClassifierOutputType.REFRAMED:
|
|
530
512
|
# Use the reframed version and track the mapping
|
|
@@ -595,6 +577,76 @@ class PMInterviewEngine:
|
|
|
595
577
|
|
|
596
578
|
return await self.inner.record_response(state, user_response, question)
|
|
597
579
|
|
|
580
|
+
async def skip_as_decide_later(
|
|
581
|
+
self,
|
|
582
|
+
state: InterviewState,
|
|
583
|
+
question: str,
|
|
584
|
+
) -> Result[InterviewState, ValidationError]:
|
|
585
|
+
"""Skip a question as "decide later" at the user's explicit request.
|
|
586
|
+
|
|
587
|
+
Records the question in ``decide_later_items`` and feeds a placeholder
|
|
588
|
+
response to the inner InterviewEngine so the round is properly recorded
|
|
589
|
+
and the engine advances.
|
|
590
|
+
|
|
591
|
+
This is called when the main session detects that the user chose the
|
|
592
|
+
"decide later" option for a DECIDE_LATER-classified question, instead
|
|
593
|
+
of the old auto-skip behavior inside ``ask_next_question``.
|
|
594
|
+
|
|
595
|
+
Args:
|
|
596
|
+
state: Current interview state.
|
|
597
|
+
question: The question the user chose to decide later.
|
|
598
|
+
|
|
599
|
+
Returns:
|
|
600
|
+
Result containing updated state or ValidationError.
|
|
601
|
+
"""
|
|
602
|
+
if question not in self.decide_later_items:
|
|
603
|
+
self.decide_later_items.append(question)
|
|
604
|
+
|
|
605
|
+
log.info(
|
|
606
|
+
"pm.question_decide_later_by_user",
|
|
607
|
+
question=question[:100],
|
|
608
|
+
)
|
|
609
|
+
|
|
610
|
+
return await self.record_response(
|
|
611
|
+
state,
|
|
612
|
+
user_response="[Decide later] To be determined — user chose to decide later.",
|
|
613
|
+
question=question,
|
|
614
|
+
)
|
|
615
|
+
|
|
616
|
+
async def skip_as_deferred(
|
|
617
|
+
self,
|
|
618
|
+
state: InterviewState,
|
|
619
|
+
question: str,
|
|
620
|
+
) -> Result[InterviewState, ValidationError]:
|
|
621
|
+
"""Skip a question as "deferred to dev" at the user's explicit request.
|
|
622
|
+
|
|
623
|
+
Records the question in ``deferred_items`` and feeds a deferral
|
|
624
|
+
response to the inner InterviewEngine so the round is properly recorded
|
|
625
|
+
and the engine advances.
|
|
626
|
+
|
|
627
|
+
Args:
|
|
628
|
+
state: Current interview state.
|
|
629
|
+
question: The question the user chose to defer.
|
|
630
|
+
|
|
631
|
+
Returns:
|
|
632
|
+
Result containing updated state or ValidationError.
|
|
633
|
+
"""
|
|
634
|
+
if question not in self.deferred_items:
|
|
635
|
+
self.deferred_items.append(question)
|
|
636
|
+
|
|
637
|
+
log.info(
|
|
638
|
+
"pm.question_deferred_by_user",
|
|
639
|
+
question=question[:100],
|
|
640
|
+
)
|
|
641
|
+
|
|
642
|
+
return await self.record_response(
|
|
643
|
+
state,
|
|
644
|
+
user_response="[Deferred to development phase] "
|
|
645
|
+
"This technical decision will be addressed during the "
|
|
646
|
+
"development interview.",
|
|
647
|
+
question=question,
|
|
648
|
+
)
|
|
649
|
+
|
|
598
650
|
async def complete_interview(
|
|
599
651
|
self,
|
|
600
652
|
state: InterviewState,
|
|
@@ -1129,13 +1181,14 @@ Include them as original question text in "decide_later_items":
|
|
|
1129
1181
|
for s in data.get("user_stories", [])
|
|
1130
1182
|
)
|
|
1131
1183
|
|
|
1132
|
-
# Merge
|
|
1184
|
+
# Merge LLM-extracted items with engine-tracked items, deduplicating.
|
|
1185
|
+
# The extraction prompt includes raw items as context so the LLM may
|
|
1186
|
+
# already emit them, but engine-tracked items are authoritative and
|
|
1187
|
+
# must survive even if the extractor omits them.
|
|
1133
1188
|
all_deferred = list(data.get("deferred_items", []))
|
|
1134
1189
|
for item in self.deferred_items:
|
|
1135
1190
|
if item not in all_deferred:
|
|
1136
1191
|
all_deferred.append(item)
|
|
1137
|
-
|
|
1138
|
-
# Merge decide-later items — stored as original question text
|
|
1139
1192
|
all_decide_later = list(data.get("decide_later_items", []))
|
|
1140
1193
|
for item in self.decide_later_items:
|
|
1141
1194
|
if item not in all_decide_later:
|
{ouroboros_ai-0.26.5.dev1 → ouroboros_ai-0.26.5.dev3}/src/ouroboros/bigbang/question_classifier.py
RENAMED
|
@@ -3,9 +3,10 @@
|
|
|
3
3
|
Classifies generated questions as PM-answerable (planning), DEV-only
|
|
4
4
|
(development/technical), or decide-later (premature/unknowable).
|
|
5
5
|
|
|
6
|
-
DEV-only questions are reframed into PM-friendly language or
|
|
7
|
-
the
|
|
8
|
-
|
|
6
|
+
DEV-only questions are reframed into PM-friendly language or returned to
|
|
7
|
+
the user with the option to defer to the development interview phase.
|
|
8
|
+
Decide-later questions are returned to the user with the option to defer
|
|
9
|
+
rather than being automatically skipped.
|
|
9
10
|
|
|
10
11
|
Uses a Sonnet-grade model for accurate judgment and reframing.
|
|
11
12
|
"""
|
|
@@ -51,8 +52,8 @@ class ClassifierOutputType(StrEnum):
|
|
|
51
52
|
|
|
52
53
|
PASSTHROUGH: Planning question forwarded unchanged to the PM.
|
|
53
54
|
REFRAMED: Development question rewritten in PM-friendly language.
|
|
54
|
-
DEFERRED: Deeply technical question
|
|
55
|
-
DECIDE_LATER: Premature question
|
|
55
|
+
DEFERRED: Deeply technical question returned to user with defer option.
|
|
56
|
+
DECIDE_LATER: Premature question returned to user with decide-later option.
|
|
56
57
|
"""
|
|
57
58
|
|
|
58
59
|
PASSTHROUGH = "passthrough"
|
|
@@ -73,8 +74,9 @@ class ClassificationResult:
|
|
|
73
74
|
reasoning: Why the classifier chose this category.
|
|
74
75
|
defer_to_dev: Whether this question should be deferred entirely.
|
|
75
76
|
decide_later: Whether this question is premature and should be
|
|
76
|
-
|
|
77
|
-
placeholder_response:
|
|
77
|
+
returned to the user with the option to defer.
|
|
78
|
+
placeholder_response: Placeholder response for decide-later questions
|
|
79
|
+
(used if the user chooses to defer).
|
|
78
80
|
"""
|
|
79
81
|
|
|
80
82
|
original_question: str
|
|
@@ -90,8 +92,10 @@ class ClassificationResult:
|
|
|
90
92
|
"""Determine the classifier output type for this result.
|
|
91
93
|
|
|
92
94
|
Returns:
|
|
93
|
-
DECIDE_LATER if premature/unknowable question (
|
|
94
|
-
|
|
95
|
+
DECIDE_LATER if premature/unknowable question (returned to user
|
|
96
|
+
with option to defer),
|
|
97
|
+
DEFERRED if deeply technical (returned to user with option to
|
|
98
|
+
defer to dev phase),
|
|
95
99
|
PASSTHROUGH if planning question (forwarded unchanged),
|
|
96
100
|
REFRAMED if development question rewritten for PM.
|
|
97
101
|
"""
|
|
@@ -109,13 +113,20 @@ class ClassificationResult:
|
|
|
109
113
|
|
|
110
114
|
For PASSTHROUGH: returns original_question unchanged.
|
|
111
115
|
For REFRAMED: returns the reframed_question.
|
|
112
|
-
For DEFERRED: returns
|
|
113
|
-
|
|
116
|
+
For DEFERRED: returns original_question (shown to user
|
|
117
|
+
so they can choose to answer or defer to dev).
|
|
118
|
+
For DECIDE_LATER: returns original_question (shown to user
|
|
119
|
+
so they can choose to answer or defer).
|
|
114
120
|
"""
|
|
115
121
|
if self.output_type == ClassifierOutputType.PASSTHROUGH:
|
|
116
122
|
return self.original_question
|
|
117
123
|
if self.output_type == ClassifierOutputType.REFRAMED:
|
|
118
124
|
return self.reframed_question
|
|
125
|
+
if self.output_type in (
|
|
126
|
+
ClassifierOutputType.DECIDE_LATER,
|
|
127
|
+
ClassifierOutputType.DEFERRED,
|
|
128
|
+
):
|
|
129
|
+
return self.original_question
|
|
119
130
|
return ""
|
|
120
131
|
|
|
121
132
|
|
|
@@ -181,7 +192,8 @@ class QuestionClassifier:
|
|
|
181
192
|
|
|
182
193
|
Uses a Sonnet-grade LLM to judge whether questions are appropriate
|
|
183
194
|
for a PM audience, reframes technical questions when possible, and
|
|
184
|
-
identifies premature questions that should be
|
|
195
|
+
identifies premature questions that should be returned to the user
|
|
196
|
+
with the option to defer.
|
|
185
197
|
|
|
186
198
|
Attributes:
|
|
187
199
|
llm_adapter: LLM adapter for classification calls.
|
|
@@ -10,8 +10,6 @@ from pathlib import Path
|
|
|
10
10
|
from typing import Annotated
|
|
11
11
|
|
|
12
12
|
import click
|
|
13
|
-
from prompt_toolkit import PromptSession
|
|
14
|
-
from prompt_toolkit.key_binding import KeyBindings, KeyPressEvent
|
|
15
13
|
from rich.prompt import Confirm, Prompt
|
|
16
14
|
import typer
|
|
17
15
|
import yaml
|
|
@@ -26,6 +24,7 @@ from ouroboros.bigbang.interview import (
|
|
|
26
24
|
from ouroboros.bigbang.seed_generator import SeedGenerator
|
|
27
25
|
from ouroboros.cli.formatters import console
|
|
28
26
|
from ouroboros.cli.formatters.panels import print_error, print_info, print_success, print_warning
|
|
27
|
+
from ouroboros.cli.formatters.prompting import multiline_prompt_async
|
|
29
28
|
from ouroboros.config import get_clarification_model
|
|
30
29
|
from ouroboros.observability import LoggingConfig, configure_logging
|
|
31
30
|
from ouroboros.providers import create_llm_adapter
|
|
@@ -104,46 +103,6 @@ def _make_message_callback(debug: bool):
|
|
|
104
103
|
return callback
|
|
105
104
|
|
|
106
105
|
|
|
107
|
-
async def _multiline_prompt_async(prompt_text: str) -> str:
|
|
108
|
-
"""Get multiline input with proper paste handling.
|
|
109
|
-
|
|
110
|
-
Behavior:
|
|
111
|
-
- Enter: Submit input
|
|
112
|
-
- Ctrl+J: Insert newline
|
|
113
|
-
- Paste: Multiline text is preserved (via bracketed paste mode)
|
|
114
|
-
|
|
115
|
-
Args:
|
|
116
|
-
prompt_text: The prompt to display.
|
|
117
|
-
|
|
118
|
-
Returns:
|
|
119
|
-
The user's input (may contain newlines from paste).
|
|
120
|
-
|
|
121
|
-
Raises:
|
|
122
|
-
EOFError: If end-of-file is reached (e.g., stdin closed).
|
|
123
|
-
KeyboardInterrupt: If user presses Ctrl+C.
|
|
124
|
-
"""
|
|
125
|
-
bindings = KeyBindings()
|
|
126
|
-
|
|
127
|
-
@bindings.add("c-j")
|
|
128
|
-
def insert_newline(event: KeyPressEvent) -> None:
|
|
129
|
-
event.current_buffer.insert_text("\n")
|
|
130
|
-
|
|
131
|
-
@bindings.add("c-m")
|
|
132
|
-
def submit(event: KeyPressEvent) -> None:
|
|
133
|
-
event.current_buffer.validate_and_handle()
|
|
134
|
-
|
|
135
|
-
console.print(f"[bold green]{prompt_text}[/] [dim](Enter: submit, Ctrl+J: newline)[/]")
|
|
136
|
-
|
|
137
|
-
session: PromptSession[str] = PromptSession(
|
|
138
|
-
message="> ",
|
|
139
|
-
multiline=True,
|
|
140
|
-
prompt_continuation=" ",
|
|
141
|
-
key_bindings=bindings,
|
|
142
|
-
)
|
|
143
|
-
|
|
144
|
-
return await session.prompt_async()
|
|
145
|
-
|
|
146
|
-
|
|
147
106
|
def _get_adapter(
|
|
148
107
|
use_orchestrator: bool,
|
|
149
108
|
backend: str | None = None,
|
|
@@ -219,7 +178,7 @@ async def _run_interview_loop(
|
|
|
219
178
|
console.print()
|
|
220
179
|
|
|
221
180
|
# Get user response (multiline-safe for paste)
|
|
222
|
-
response = await
|
|
181
|
+
response = await multiline_prompt_async("Your response")
|
|
223
182
|
|
|
224
183
|
if not response.strip():
|
|
225
184
|
print_error("Response cannot be empty. Please try again.")
|
|
@@ -791,7 +750,7 @@ def start(
|
|
|
791
750
|
)
|
|
792
751
|
console.print()
|
|
793
752
|
|
|
794
|
-
context = asyncio.run(
|
|
753
|
+
context = asyncio.run(multiline_prompt_async("What would you like to build?"))
|
|
795
754
|
|
|
796
755
|
if not resume and not context:
|
|
797
756
|
print_error("Initial context is required when not resuming.")
|
|
@@ -19,8 +19,10 @@ import typer
|
|
|
19
19
|
from ouroboros.bigbang.interview import InterviewRound
|
|
20
20
|
from ouroboros.cli.formatters import console
|
|
21
21
|
from ouroboros.cli.formatters.panels import print_error, print_info, print_success, print_warning
|
|
22
|
+
from ouroboros.cli.formatters.prompting import multiline_prompt_async
|
|
22
23
|
from ouroboros.config import get_clarification_model
|
|
23
24
|
from ouroboros.core.types import Result
|
|
25
|
+
from ouroboros.observability import LoggingConfig, configure_logging
|
|
24
26
|
|
|
25
27
|
app = typer.Typer(
|
|
26
28
|
name="pm",
|
|
@@ -108,6 +110,10 @@ def pm_command(
|
|
|
108
110
|
if model is None:
|
|
109
111
|
model = get_clarification_model()
|
|
110
112
|
|
|
113
|
+
if debug:
|
|
114
|
+
configure_logging(LoggingConfig(log_level="DEBUG"))
|
|
115
|
+
print_info("Debug mode enabled - showing verbose logs")
|
|
116
|
+
|
|
111
117
|
console.print("\n[bold cyan]Ouroboros PM Generator[/] - Product Requirements Document\n")
|
|
112
118
|
|
|
113
119
|
if resume:
|
|
@@ -392,12 +398,13 @@ async def _run_pm_interview(
|
|
|
392
398
|
opening = engine.get_opening_question()
|
|
393
399
|
console.print(f"\n[bold yellow]?[/] {opening}\n")
|
|
394
400
|
|
|
395
|
-
user_answer =
|
|
401
|
+
user_answer = await multiline_prompt_async("Your response")
|
|
396
402
|
|
|
397
403
|
if not user_answer.strip():
|
|
398
404
|
print_error("No response provided. Exiting.")
|
|
399
405
|
raise typer.Exit(code=1)
|
|
400
406
|
|
|
407
|
+
print_info("Starting interview...")
|
|
401
408
|
state_result = await engine.ask_opening_and_start(
|
|
402
409
|
user_response=user_answer,
|
|
403
410
|
brownfield_repos=brownfield_repos if brownfield_repos else None,
|
|
@@ -417,6 +424,7 @@ async def _run_pm_interview(
|
|
|
417
424
|
if state.rounds and state.rounds[-1].user_response is None:
|
|
418
425
|
question = state.rounds[-1].question
|
|
419
426
|
else:
|
|
427
|
+
print_info("Generating next question...")
|
|
420
428
|
q_result = await engine.ask_next_question(state)
|
|
421
429
|
if q_result.is_err:
|
|
422
430
|
print_error(f"Question generation failed: {q_result.error}")
|
|
@@ -439,6 +447,20 @@ async def _run_pm_interview(
|
|
|
439
447
|
|
|
440
448
|
console.print(f"\n[bold yellow]?[/] {question}\n")
|
|
441
449
|
|
|
450
|
+
# Check if this question was classified as skippable —
|
|
451
|
+
# if so, show a hint that the user can defer it.
|
|
452
|
+
classification = engine.get_last_classification()
|
|
453
|
+
if classification == "decide_later":
|
|
454
|
+
console.print(
|
|
455
|
+
"[dim] 💡 This question can be deferred. "
|
|
456
|
+
'Type "decide later" or "skip" to defer it.[/]\n'
|
|
457
|
+
)
|
|
458
|
+
elif classification == "deferred":
|
|
459
|
+
console.print(
|
|
460
|
+
"[dim] 💡 This is a technical question that can be deferred to the dev phase. "
|
|
461
|
+
'Type "defer" or "skip" to defer it.[/]\n'
|
|
462
|
+
)
|
|
463
|
+
|
|
442
464
|
# Persist state + meta AFTER displaying the question but BEFORE
|
|
443
465
|
# waiting for input so that an interruption preserves the pending
|
|
444
466
|
# question and --resume shows the same question.
|
|
@@ -448,7 +470,7 @@ async def _run_pm_interview(
|
|
|
448
470
|
break
|
|
449
471
|
_save_cli_pm_meta(state.interview_id, engine)
|
|
450
472
|
|
|
451
|
-
user_response =
|
|
473
|
+
user_response = await multiline_prompt_async("Your response")
|
|
452
474
|
|
|
453
475
|
# Allow early exit
|
|
454
476
|
if user_response.strip().lower() in ("done", "exit", "quit", "/done"):
|
|
@@ -460,6 +482,8 @@ async def _run_pm_interview(
|
|
|
460
482
|
complete_result = await engine.complete_interview(state)
|
|
461
483
|
if isinstance(complete_result, Result) and complete_result.is_err:
|
|
462
484
|
print_error(f"Failed to complete interview: {complete_result.error}")
|
|
485
|
+
elif isinstance(complete_result, Result):
|
|
486
|
+
state = complete_result.value
|
|
463
487
|
save_result = await engine.save_state(state)
|
|
464
488
|
if isinstance(save_result, Result) and save_result.is_err:
|
|
465
489
|
print_error(f"Failed to save completed state: {save_result.error}")
|
|
@@ -471,10 +495,45 @@ async def _run_pm_interview(
|
|
|
471
495
|
if state.rounds and state.rounds[-1].user_response is None:
|
|
472
496
|
state.rounds.pop()
|
|
473
497
|
|
|
498
|
+
# Handle user-initiated skip (decide later / defer to dev)
|
|
499
|
+
_lower = user_response.strip().lower()
|
|
500
|
+
if classification == "decide_later" and _lower in (
|
|
501
|
+
"decide later",
|
|
502
|
+
"skip",
|
|
503
|
+
"[decide_later]",
|
|
504
|
+
):
|
|
505
|
+
record_result = await engine.skip_as_decide_later(state, question)
|
|
506
|
+
if isinstance(record_result, Result) and record_result.is_err:
|
|
507
|
+
print_error(f"Failed to skip question: {record_result.error}")
|
|
508
|
+
break
|
|
509
|
+
save_result = await engine.save_state(state)
|
|
510
|
+
if isinstance(save_result, Result) and save_result.is_err:
|
|
511
|
+
print_error(f"Failed to save state: {save_result.error}")
|
|
512
|
+
break
|
|
513
|
+
_save_cli_pm_meta(state.interview_id, engine)
|
|
514
|
+
continue
|
|
515
|
+
if classification == "deferred" and _lower in (
|
|
516
|
+
"defer",
|
|
517
|
+
"skip",
|
|
518
|
+
"[deferred]",
|
|
519
|
+
):
|
|
520
|
+
record_result = await engine.skip_as_deferred(state, question)
|
|
521
|
+
if isinstance(record_result, Result) and record_result.is_err:
|
|
522
|
+
print_error(f"Failed to defer question: {record_result.error}")
|
|
523
|
+
break
|
|
524
|
+
save_result = await engine.save_state(state)
|
|
525
|
+
if isinstance(save_result, Result) and save_result.is_err:
|
|
526
|
+
print_error(f"Failed to save state: {save_result.error}")
|
|
527
|
+
break
|
|
528
|
+
_save_cli_pm_meta(state.interview_id, engine)
|
|
529
|
+
continue
|
|
530
|
+
|
|
474
531
|
record_result = await engine.record_response(state, user_response, question)
|
|
475
532
|
if isinstance(record_result, Result) and record_result.is_err:
|
|
476
533
|
print_error(f"Failed to record response: {record_result.error}")
|
|
477
534
|
break
|
|
535
|
+
if isinstance(record_result, Result):
|
|
536
|
+
state = record_result.value
|
|
478
537
|
save_result = await engine.save_state(state)
|
|
479
538
|
if isinstance(save_result, Result) and save_result.is_err:
|
|
480
539
|
print_error(f"Failed to save state: {save_result.error}")
|
|
@@ -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"]
|