ouroboros-ai 0.26.5.dev3__tar.gz → 0.26.5.dev5__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.

Files changed (569) hide show
  1. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/PKG-INFO +1 -1
  2. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/_version.py +2 -2
  3. ouroboros_ai-0.26.5.dev5/src/ouroboros/bigbang/pm_completion.py +61 -0
  4. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/cli/commands/pm.py +50 -4
  5. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/mcp/tools/pm_handler.py +22 -18
  6. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/orchestrator/codex_cli_runtime.py +53 -14
  7. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/orchestrator/runner.py +40 -0
  8. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/orchestrator/session.py +48 -0
  9. ouroboros_ai-0.26.5.dev5/tests/unit/bigbang/test_pm_completion.py +76 -0
  10. ouroboros_ai-0.26.5.dev5/tests/unit/cli/test_pm_completion.py +117 -0
  11. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/cli/test_pm_interactive_logging.py +13 -0
  12. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/mcp/tools/test_pm_handler.py +22 -18
  13. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/orchestrator/test_codex_cli_runtime.py +41 -1
  14. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/orchestrator/test_runner.py +95 -0
  15. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/orchestrator/test_session.py +19 -0
  16. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/.claude/settings.json +0 -0
  17. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/.claude-plugin/.mcp.json +0 -0
  18. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/.claude-plugin/marketplace.json +0 -0
  19. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/.claude-plugin/plugin.json +0 -0
  20. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/.env.example +0 -0
  21. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
  22. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/.github/ISSUE_TEMPLATE/config.yml +0 -0
  23. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/.github/ISSUE_TEMPLATE/feature_request.yml +0 -0
  24. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/.github/ISSUE_TEMPLATE/question.yml +0 -0
  25. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/.github/workflows/dev-publish.yml +0 -0
  26. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/.github/workflows/lint.yml +0 -0
  27. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/.github/workflows/release.yml +0 -0
  28. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/.github/workflows/test.yml +0 -0
  29. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/.gitignore +0 -0
  30. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/.mcp.json +0 -0
  31. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/.ouroboros/mechanical.toml +0 -0
  32. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/.pre-commit-config.yaml +0 -0
  33. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/.python-version +0 -0
  34. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/CHANGELOG.md +0 -0
  35. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/CLAUDE.md +0 -0
  36. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/CODE_OF_CONDUCT.md +0 -0
  37. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/CONTRIBUTING.md +0 -0
  38. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/HANDOFF.md +0 -0
  39. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/LICENSE +0 -0
  40. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/README.ko.md +0 -0
  41. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/README.md +0 -0
  42. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/SECURITY.md +0 -0
  43. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/UNINSTALL.md +0 -0
  44. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/commands/cancel.md +0 -0
  45. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/commands/evaluate.md +0 -0
  46. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/commands/evolve.md +0 -0
  47. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/commands/help.md +0 -0
  48. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/commands/interview.md +0 -0
  49. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/commands/ralph.md +0 -0
  50. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/commands/run.md +0 -0
  51. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/commands/seed.md +0 -0
  52. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/commands/setup.md +0 -0
  53. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/commands/status.md +0 -0
  54. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/commands/tutorial.md +0 -0
  55. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/commands/unstuck.md +0 -0
  56. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/commands/welcome.md +0 -0
  57. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/crates/ouroboros-tui/.gitignore +0 -0
  58. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/crates/ouroboros-tui/Cargo.lock +0 -0
  59. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/crates/ouroboros-tui/Cargo.toml +0 -0
  60. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/crates/ouroboros-tui/README.md +0 -0
  61. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/crates/ouroboros-tui/src/db.rs +0 -0
  62. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/crates/ouroboros-tui/src/main.rs +0 -0
  63. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/crates/ouroboros-tui/src/mock.rs +0 -0
  64. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/crates/ouroboros-tui/src/state.rs +0 -0
  65. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/crates/ouroboros-tui/src/views/dashboard.rs +0 -0
  66. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/crates/ouroboros-tui/src/views/execution.rs +0 -0
  67. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/crates/ouroboros-tui/src/views/lineage.rs +0 -0
  68. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/crates/ouroboros-tui/src/views/logs.rs +0 -0
  69. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/crates/ouroboros-tui/src/views/mod.rs +0 -0
  70. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/crates/ouroboros-tui/src/views/session_selector.rs +0 -0
  71. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/docs/README.md +0 -0
  72. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/docs/api/README.md +0 -0
  73. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/docs/api/core.md +0 -0
  74. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/docs/api/mcp.md +0 -0
  75. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/docs/architecture.md +0 -0
  76. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/docs/cli-reference.md +0 -0
  77. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/docs/config-reference.md +0 -0
  78. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/docs/contributing/architecture-overview.md +0 -0
  79. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/docs/contributing/findings-registry.md +0 -0
  80. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/docs/contributing/issue-quality-policy.md +0 -0
  81. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/docs/contributing/key-patterns.md +0 -0
  82. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/docs/contributing/testing-guide.md +0 -0
  83. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/docs/examples/mcp-config.yaml +0 -0
  84. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/docs/getting-started.md +0 -0
  85. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/docs/guides/evaluation-pipeline.md +0 -0
  86. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/docs/guides/evolution-loop.md +0 -0
  87. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/docs/guides/issue-176-subagent-mcp-inheritance.md +0 -0
  88. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/docs/guides/seed-authoring.md +0 -0
  89. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/docs/guides/tui-usage.md +0 -0
  90. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/docs/images/PLACEHOLDER_README.md +0 -0
  91. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/docs/images/ouroboros.png +0 -0
  92. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/docs/platform-support.md +0 -0
  93. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/docs/runtime-capability-matrix.md +0 -0
  94. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/docs/runtime-guides/claude-code.md +0 -0
  95. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/docs/runtime-guides/codex.md +0 -0
  96. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/examples/coordinator_test_seed.yaml +0 -0
  97. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/examples/dummy_seed.yaml +0 -0
  98. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/examples/parallel_subac_test_seed.yaml +0 -0
  99. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/examples/subac_test_seed.yaml +0 -0
  100. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/examples/task_manager/README.md +0 -0
  101. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/examples/task_manager/__init__.py +0 -0
  102. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/examples/task_manager/__main__.py +0 -0
  103. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/examples/task_manager/cli.py +0 -0
  104. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/examples/task_manager/models.py +0 -0
  105. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/examples/task_manager/storage.py +0 -0
  106. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/examples/test_display.py +0 -0
  107. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/hooks/hooks.json +0 -0
  108. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/llms-full.txt +0 -0
  109. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/llms.txt +0 -0
  110. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/project-context.md +0 -0
  111. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/pyproject.toml +0 -0
  112. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/scripts/drift-monitor.py +0 -0
  113. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/scripts/install.sh +0 -0
  114. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/scripts/keyword-detector.py +0 -0
  115. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/scripts/mcp-serve.sh +0 -0
  116. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/scripts/ralph-rewind.py +0 -0
  117. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/scripts/ralph.py +0 -0
  118. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/scripts/ralph.sh +0 -0
  119. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/scripts/session-start.py +0 -0
  120. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/scripts/sync-plugin-version.py +0 -0
  121. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/scripts/version-check.py +0 -0
  122. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/skills/brownfield/SKILL.md +0 -0
  123. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/skills/cancel/SKILL.md +0 -0
  124. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/skills/evaluate/SKILL.md +0 -0
  125. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/skills/evolve/SKILL.md +0 -0
  126. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/skills/help/SKILL.md +0 -0
  127. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/skills/interview/SKILL.md +0 -0
  128. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/skills/pm/SKILL.md +0 -0
  129. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/skills/qa/SKILL.md +0 -0
  130. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/skills/ralph/SKILL.md +0 -0
  131. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/skills/run/SKILL.md +0 -0
  132. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/skills/seed/SKILL.md +0 -0
  133. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/skills/setup/SKILL.md +0 -0
  134. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/skills/status/SKILL.md +0 -0
  135. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/skills/tutorial/SKILL.md +0 -0
  136. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/skills/unstuck/SKILL.md +0 -0
  137. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/skills/update/SKILL.md +0 -0
  138. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/skills/welcome/SKILL.md +0 -0
  139. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/__init__.py +0 -0
  140. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/__main__.py +0 -0
  141. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/agents/__init__.py +0 -0
  142. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/agents/advocate.md +0 -0
  143. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/agents/analysis-agent.md +0 -0
  144. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/agents/architect.md +0 -0
  145. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/agents/breadth-keeper.md +0 -0
  146. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/agents/code-executor.md +0 -0
  147. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/agents/codebase-explorer.md +0 -0
  148. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/agents/consensus-reviewer.md +0 -0
  149. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/agents/contrarian.md +0 -0
  150. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/agents/evaluator.md +0 -0
  151. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/agents/hacker.md +0 -0
  152. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/agents/judge.md +0 -0
  153. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/agents/loader.py +0 -0
  154. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/agents/ontologist.md +0 -0
  155. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/agents/ontology-analyst.md +0 -0
  156. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/agents/qa-judge.md +0 -0
  157. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/agents/research-agent.md +0 -0
  158. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/agents/researcher.md +0 -0
  159. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/agents/seed-architect.md +0 -0
  160. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/agents/seed-closer.md +0 -0
  161. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/agents/semantic-evaluator.md +0 -0
  162. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/agents/simplifier.md +0 -0
  163. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/agents/socratic-interviewer.md +0 -0
  164. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/bigbang/__init__.py +0 -0
  165. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/bigbang/ambiguity.py +0 -0
  166. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/bigbang/brownfield.py +0 -0
  167. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/bigbang/explore.py +0 -0
  168. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/bigbang/interview.py +0 -0
  169. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/bigbang/pm_document.py +0 -0
  170. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/bigbang/pm_interview.py +0 -0
  171. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/bigbang/pm_seed.py +0 -0
  172. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/bigbang/question_classifier.py +0 -0
  173. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/bigbang/seed_generator.py +0 -0
  174. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/cli/__init__.py +0 -0
  175. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/cli/commands/__init__.py +0 -0
  176. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/cli/commands/cancel.py +0 -0
  177. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/cli/commands/config.py +0 -0
  178. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/cli/commands/init.py +0 -0
  179. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/cli/commands/mcp.py +0 -0
  180. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/cli/commands/run.py +0 -0
  181. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/cli/commands/setup.py +0 -0
  182. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/cli/commands/status.py +0 -0
  183. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/cli/commands/tui.py +0 -0
  184. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/cli/commands/uninstall.py +0 -0
  185. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/cli/formatters/__init__.py +0 -0
  186. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/cli/formatters/panels.py +0 -0
  187. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/cli/formatters/progress.py +0 -0
  188. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/cli/formatters/prompting.py +0 -0
  189. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/cli/formatters/tables.py +0 -0
  190. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/cli/formatters/workflow_display.py +0 -0
  191. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/cli/main.py +0 -0
  192. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/codex/__init__.py +0 -0
  193. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/codex/artifacts.py +0 -0
  194. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/codex/ouroboros.md +0 -0
  195. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/codex_permissions.py +0 -0
  196. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/config/__init__.py +0 -0
  197. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/config/loader.py +0 -0
  198. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/config/models.py +0 -0
  199. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/core/__init__.py +0 -0
  200. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/core/ac_tree.py +0 -0
  201. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/core/context.py +0 -0
  202. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/core/errors.py +0 -0
  203. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/core/file_lock.py +0 -0
  204. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/core/git_workflow.py +0 -0
  205. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/core/lineage.py +0 -0
  206. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/core/ontology_aspect.py +0 -0
  207. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/core/ontology_questions.py +0 -0
  208. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/core/project_paths.py +0 -0
  209. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/core/security.py +0 -0
  210. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/core/seed.py +0 -0
  211. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/core/text.py +0 -0
  212. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/core/types.py +0 -0
  213. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/core/worktree.py +0 -0
  214. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/evaluation/__init__.py +0 -0
  215. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/evaluation/artifact_collector.py +0 -0
  216. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/evaluation/consensus.py +0 -0
  217. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/evaluation/json_utils.py +0 -0
  218. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/evaluation/languages.py +0 -0
  219. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/evaluation/mechanical.py +0 -0
  220. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/evaluation/models.py +0 -0
  221. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/evaluation/pipeline.py +0 -0
  222. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/evaluation/semantic.py +0 -0
  223. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/evaluation/trigger.py +0 -0
  224. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/evaluation/verification_artifacts.py +0 -0
  225. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/events/__init__.py +0 -0
  226. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/events/base.py +0 -0
  227. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/events/decomposition.py +0 -0
  228. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/events/evaluation.py +0 -0
  229. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/events/interview.py +0 -0
  230. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/events/lineage.py +0 -0
  231. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/events/ontology.py +0 -0
  232. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/evolution/__init__.py +0 -0
  233. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/evolution/convergence.py +0 -0
  234. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/evolution/loop.py +0 -0
  235. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/evolution/projector.py +0 -0
  236. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/evolution/reflect.py +0 -0
  237. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/evolution/regression.py +0 -0
  238. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/evolution/wonder.py +0 -0
  239. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/execution/__init__.py +0 -0
  240. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/execution/atomicity.py +0 -0
  241. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/execution/decomposition.py +0 -0
  242. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/execution/double_diamond.py +0 -0
  243. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/execution/subagent.py +0 -0
  244. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/mcp/__init__.py +0 -0
  245. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/mcp/client/__init__.py +0 -0
  246. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/mcp/client/adapter.py +0 -0
  247. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/mcp/client/manager.py +0 -0
  248. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/mcp/client/protocol.py +0 -0
  249. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/mcp/errors.py +0 -0
  250. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/mcp/job_manager.py +0 -0
  251. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/mcp/resources/__init__.py +0 -0
  252. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/mcp/resources/handlers.py +0 -0
  253. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/mcp/server/__init__.py +0 -0
  254. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/mcp/server/adapter.py +0 -0
  255. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/mcp/server/protocol.py +0 -0
  256. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/mcp/server/security.py +0 -0
  257. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/mcp/tools/__init__.py +0 -0
  258. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/mcp/tools/authoring_handlers.py +0 -0
  259. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/mcp/tools/brownfield_handler.py +0 -0
  260. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/mcp/tools/dashboard.py +0 -0
  261. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/mcp/tools/definitions.py +0 -0
  262. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/mcp/tools/evaluation_handlers.py +0 -0
  263. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/mcp/tools/evolution_handlers.py +0 -0
  264. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/mcp/tools/execution_handlers.py +0 -0
  265. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/mcp/tools/job_handlers.py +0 -0
  266. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/mcp/tools/qa.py +0 -0
  267. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/mcp/tools/query_handlers.py +0 -0
  268. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/mcp/tools/registry.py +0 -0
  269. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/mcp/types.py +0 -0
  270. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/observability/__init__.py +0 -0
  271. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/observability/drift.py +0 -0
  272. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/observability/logging.py +0 -0
  273. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/observability/retrospective.py +0 -0
  274. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/orchestrator/__init__.py +0 -0
  275. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/orchestrator/adapter.py +0 -0
  276. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/orchestrator/command_dispatcher.py +0 -0
  277. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/orchestrator/coordinator.py +0 -0
  278. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/orchestrator/dependency_analyzer.py +0 -0
  279. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/orchestrator/events.py +0 -0
  280. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/orchestrator/execution_runtime_scope.py +0 -0
  281. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/orchestrator/execution_strategy.py +0 -0
  282. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/orchestrator/heartbeat.py +0 -0
  283. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/orchestrator/level_context.py +0 -0
  284. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/orchestrator/mcp_config.py +0 -0
  285. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/orchestrator/mcp_tools.py +0 -0
  286. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/orchestrator/parallel_executor.py +0 -0
  287. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/orchestrator/parallel_executor_models.py +0 -0
  288. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/orchestrator/runtime_factory.py +0 -0
  289. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/orchestrator/runtime_message_projection.py +0 -0
  290. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/orchestrator/workflow_state.py +0 -0
  291. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/persistence/__init__.py +0 -0
  292. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/persistence/brownfield.py +0 -0
  293. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/persistence/checkpoint.py +0 -0
  294. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/persistence/event_store.py +0 -0
  295. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/persistence/migrations/__init__.py +0 -0
  296. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/persistence/migrations/runner.py +0 -0
  297. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/persistence/migrations/scripts/001_initial.sql +0 -0
  298. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/persistence/migrations/scripts/002_brownfield.sql +0 -0
  299. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/persistence/schema.py +0 -0
  300. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/persistence/uow.py +0 -0
  301. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/plugin/__init__.py +0 -0
  302. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/plugin/agents/__init__.py +0 -0
  303. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/plugin/agents/pool.py +0 -0
  304. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/plugin/agents/registry.py +0 -0
  305. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/plugin/orchestration/__init__.py +0 -0
  306. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/plugin/orchestration/router.py +0 -0
  307. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/plugin/orchestration/scheduler.py +0 -0
  308. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/plugin/skills/__init__.py +0 -0
  309. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/plugin/skills/docs.py +0 -0
  310. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/plugin/skills/executor.py +0 -0
  311. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/plugin/skills/keywords.py +0 -0
  312. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/plugin/skills/registry.py +0 -0
  313. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/pm/__init__.py +0 -0
  314. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/pm/renderer.py +0 -0
  315. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/providers/__init__.py +0 -0
  316. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/providers/anthropic_adapter.py +0 -0
  317. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/providers/base.py +0 -0
  318. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/providers/claude_code_adapter.py +0 -0
  319. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/providers/codex_cli_adapter.py +0 -0
  320. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/providers/codex_cli_stream.py +0 -0
  321. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/providers/factory.py +0 -0
  322. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/providers/litellm_adapter.py +0 -0
  323. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/py.typed +0 -0
  324. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/resilience/__init__.py +0 -0
  325. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/resilience/lateral.py +0 -0
  326. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/resilience/stagnation.py +0 -0
  327. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/routing/__init__.py +0 -0
  328. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/routing/complexity.py +0 -0
  329. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/routing/downgrade.py +0 -0
  330. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/routing/escalation.py +0 -0
  331. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/routing/router.py +0 -0
  332. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/routing/tiers.py +0 -0
  333. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/secondary/__init__.py +0 -0
  334. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/secondary/scheduler.py +0 -0
  335. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/secondary/todo_registry.py +0 -0
  336. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/strategies/__init__.py +0 -0
  337. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/strategies/devil_advocate.py +0 -0
  338. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/tui/__init__.py +0 -0
  339. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/tui/app.py +0 -0
  340. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/tui/components/__init__.py +0 -0
  341. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/tui/components/agents_panel.py +0 -0
  342. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/tui/components/event_log.py +0 -0
  343. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/tui/components/progress.py +0 -0
  344. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/tui/components/token_tracker.py +0 -0
  345. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/tui/events.py +0 -0
  346. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/tui/screens/__init__.py +0 -0
  347. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/tui/screens/confirm_rewind.py +0 -0
  348. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/tui/screens/dashboard.py +0 -0
  349. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/tui/screens/dashboard_v2.py +0 -0
  350. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/tui/screens/dashboard_v3.py +0 -0
  351. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/tui/screens/debug.py +0 -0
  352. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/tui/screens/execution.py +0 -0
  353. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/tui/screens/hud_dashboard.py +0 -0
  354. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/tui/screens/lineage_detail.py +0 -0
  355. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/tui/screens/lineage_selector.py +0 -0
  356. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/tui/screens/logs.py +0 -0
  357. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/tui/screens/session_selector.py +0 -0
  358. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/tui/widgets/__init__.py +0 -0
  359. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/tui/widgets/ac_progress.py +0 -0
  360. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/tui/widgets/ac_tree.py +0 -0
  361. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/tui/widgets/agent_activity.py +0 -0
  362. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/tui/widgets/cost_tracker.py +0 -0
  363. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/tui/widgets/drift_meter.py +0 -0
  364. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/tui/widgets/lineage_tree.py +0 -0
  365. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/tui/widgets/parallel_graph.py +0 -0
  366. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/tui/widgets/phase_progress.py +0 -0
  367. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/verification/__init__.py +0 -0
  368. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/verification/extractor.py +0 -0
  369. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/verification/models.py +0 -0
  370. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/src/ouroboros/verification/verifier.py +0 -0
  371. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/__init__.py +0 -0
  372. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/conftest.py +0 -0
  373. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/e2e/__init__.py +0 -0
  374. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/e2e/conftest.py +0 -0
  375. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/e2e/test_cli_commands.py +0 -0
  376. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/e2e/test_full_workflow.py +0 -0
  377. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/e2e/test_session_persistence.py +0 -0
  378. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/fixtures/test_atomicity_seed.yml +0 -0
  379. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/integration/__init__.py +0 -0
  380. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/integration/conftest.py +0 -0
  381. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/integration/mcp/__init__.py +0 -0
  382. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/integration/mcp/conftest.py +0 -0
  383. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/integration/mcp/test_client_adapter.py +0 -0
  384. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/integration/mcp/test_client_manager.py +0 -0
  385. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/integration/mcp/test_server_adapter.py +0 -0
  386. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/integration/plugin/test_orchestration.py +0 -0
  387. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/integration/test_codex_cli_passthrough_smoke.py +0 -0
  388. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/integration/test_codex_skill_fallback.py +0 -0
  389. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/integration/test_codex_skill_smoke.py +0 -0
  390. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/integration/test_entry_point.py +0 -0
  391. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/__init__.py +0 -0
  392. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/agents/__init__.py +0 -0
  393. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/agents/test_loader.py +0 -0
  394. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/bigbang/__init__.py +0 -0
  395. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/bigbang/test_ambiguity.py +0 -0
  396. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/bigbang/test_brownfield.py +0 -0
  397. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/bigbang/test_classifier_context.py +0 -0
  398. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/bigbang/test_decide_later_items.py +0 -0
  399. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/bigbang/test_explore.py +0 -0
  400. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/bigbang/test_interview.py +0 -0
  401. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/bigbang/test_pm_document_generator.py +0 -0
  402. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/bigbang/test_pm_document_writer.py +0 -0
  403. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/bigbang/test_pm_interview.py +0 -0
  404. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/bigbang/test_pm_interview_brownfield_db.py +0 -0
  405. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/bigbang/test_pm_seed_ac12.py +0 -0
  406. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/bigbang/test_pm_seed_save.py +0 -0
  407. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/bigbang/test_question_classifier.py +0 -0
  408. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/bigbang/test_seed_generator.py +0 -0
  409. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/cli/__init__.py +0 -0
  410. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/cli/formatters/__init__.py +0 -0
  411. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/cli/formatters/test_console.py +0 -0
  412. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/cli/formatters/test_panels.py +0 -0
  413. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/cli/formatters/test_progress.py +0 -0
  414. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/cli/formatters/test_prompting.py +0 -0
  415. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/cli/formatters/test_tables.py +0 -0
  416. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/cli/formatters/test_workflow_display.py +0 -0
  417. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/cli/test_cancel.py +0 -0
  418. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/cli/test_config.py +0 -0
  419. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/cli/test_init_pm_seed_detection.py +0 -0
  420. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/cli/test_init_runtime.py +0 -0
  421. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/cli/test_main.py +0 -0
  422. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/cli/test_mcp_nested_guard.py +0 -0
  423. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/cli/test_mcp_startup_cleanup.py +0 -0
  424. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/cli/test_pm.py +0 -0
  425. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/cli/test_pm_brownfield.py +0 -0
  426. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/cli/test_pm_missing_litellm.py +0 -0
  427. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/cli/test_pm_overwrite.py +0 -0
  428. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/cli/test_pm_select_repos.py +0 -0
  429. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/cli/test_run_qa.py +0 -0
  430. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/cli/test_setup.py +0 -0
  431. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/cli/test_uninstall.py +0 -0
  432. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/config/__init__.py +0 -0
  433. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/config/test_loader.py +0 -0
  434. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/config/test_models.py +0 -0
  435. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/core/__init__.py +0 -0
  436. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/core/test_ac_tree.py +0 -0
  437. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/core/test_context.py +0 -0
  438. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/core/test_errors.py +0 -0
  439. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/core/test_git_workflow.py +0 -0
  440. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/core/test_lineage.py +0 -0
  441. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/core/test_ontology_aspect.py +0 -0
  442. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/core/test_ontology_questions.py +0 -0
  443. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/core/test_security.py +0 -0
  444. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/core/test_seed.py +0 -0
  445. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/core/test_types.py +0 -0
  446. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/core/test_worktree.py +0 -0
  447. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/evaluation/__init__.py +0 -0
  448. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/evaluation/test_consensus.py +0 -0
  449. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/evaluation/test_json_utils.py +0 -0
  450. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/evaluation/test_languages.py +0 -0
  451. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/evaluation/test_mechanical.py +0 -0
  452. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/evaluation/test_models.py +0 -0
  453. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/evaluation/test_semantic.py +0 -0
  454. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/evaluation/test_trigger.py +0 -0
  455. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/evaluation/test_verification_artifacts.py +0 -0
  456. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/events/__init__.py +0 -0
  457. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/events/test_base.py +0 -0
  458. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/events/test_decomposition_events.py +0 -0
  459. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/evolution/test_wonder_scope.py +0 -0
  460. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/execution/__init__.py +0 -0
  461. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/execution/test_atomicity.py +0 -0
  462. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/execution/test_decomposition.py +0 -0
  463. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/execution/test_double_diamond.py +0 -0
  464. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/execution/test_subagent_isolation.py +0 -0
  465. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/mcp/__init__.py +0 -0
  466. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/mcp/client/__init__.py +0 -0
  467. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/mcp/client/test_adapter.py +0 -0
  468. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/mcp/client/test_manager.py +0 -0
  469. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/mcp/conftest.py +0 -0
  470. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/mcp/server/__init__.py +0 -0
  471. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/mcp/server/test_adapter.py +0 -0
  472. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/mcp/server/test_security.py +0 -0
  473. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/mcp/test_errors.py +0 -0
  474. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/mcp/test_job_manager.py +0 -0
  475. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/mcp/test_types.py +0 -0
  476. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/mcp/tools/__init__.py +0 -0
  477. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/mcp/tools/conftest.py +0 -0
  478. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/mcp/tools/test_brownfield_handler.py +0 -0
  479. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/mcp/tools/test_definitions.py +0 -0
  480. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/mcp/tools/test_pm_handler_generate.py +0 -0
  481. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/mcp/tools/test_pm_handler_pending_reframe.py +0 -0
  482. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/mcp/tools/test_qa_integration.py +0 -0
  483. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/mcp/tools/test_registry.py +0 -0
  484. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/observability/__init__.py +0 -0
  485. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/observability/test_drift.py +0 -0
  486. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/observability/test_logging.py +0 -0
  487. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/observability/test_retrospective.py +0 -0
  488. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/orchestrator/__init__.py +0 -0
  489. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/orchestrator/test_adapter.py +0 -0
  490. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/orchestrator/test_codex_recursion_guard.py +0 -0
  491. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/orchestrator/test_command_dispatcher.py +0 -0
  492. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/orchestrator/test_coordinator.py +0 -0
  493. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/orchestrator/test_dependency_analyzer.py +0 -0
  494. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/orchestrator/test_events.py +0 -0
  495. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/orchestrator/test_execution_runtime_scope.py +0 -0
  496. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/orchestrator/test_execution_strategy.py +0 -0
  497. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/orchestrator/test_inflight_cancellation.py +0 -0
  498. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/orchestrator/test_level_context.py +0 -0
  499. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/orchestrator/test_mcp_config.py +0 -0
  500. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/orchestrator/test_mcp_tools.py +0 -0
  501. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/orchestrator/test_parallel_executor.py +0 -0
  502. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/orchestrator/test_parallel_executor_retry_resume.py +0 -0
  503. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/orchestrator/test_runner_cancellation.py +0 -0
  504. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/orchestrator/test_runtime_factory.py +0 -0
  505. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/orchestrator/test_runtime_message_projection.py +0 -0
  506. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/orchestrator/test_workflow_state.py +0 -0
  507. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/persistence/__init__.py +0 -0
  508. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/persistence/test_brownfield_store.py +0 -0
  509. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/persistence/test_checkpoint.py +0 -0
  510. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/persistence/test_event_store.py +0 -0
  511. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/persistence/test_schema.py +0 -0
  512. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/persistence/test_uow.py +0 -0
  513. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/plugin/__init__.py +0 -0
  514. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/plugin/agents/__init__.py +0 -0
  515. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/plugin/agents/test_registry.py +0 -0
  516. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/plugin/orchestration/__init__.py +0 -0
  517. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/plugin/orchestration/test_model_router.py +0 -0
  518. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/plugin/skills/__init__.py +0 -0
  519. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/plugin/skills/test_keywords.py +0 -0
  520. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/plugin/skills/test_registry.py +0 -0
  521. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/pm/__init__.py +0 -0
  522. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/pm/test_renderer.py +0 -0
  523. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/providers/__init__.py +0 -0
  524. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/providers/test_base.py +0 -0
  525. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/providers/test_claude_code_adapter.py +0 -0
  526. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/providers/test_codex_cli_adapter.py +0 -0
  527. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/providers/test_factory.py +0 -0
  528. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/providers/test_litellm_adapter.py +0 -0
  529. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/resilience/__init__.py +0 -0
  530. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/resilience/test_lateral.py +0 -0
  531. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/resilience/test_stagnation.py +0 -0
  532. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/routing/__init__.py +0 -0
  533. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/routing/test_complexity.py +0 -0
  534. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/routing/test_downgrade.py +0 -0
  535. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/routing/test_escalation.py +0 -0
  536. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/routing/test_router.py +0 -0
  537. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/routing/test_tiers.py +0 -0
  538. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/scripts/test_keyword_detector.py +0 -0
  539. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/scripts/test_version_check.py +0 -0
  540. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/secondary/__init__.py +0 -0
  541. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/secondary/test_scheduler.py +0 -0
  542. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/secondary/test_todo_registry.py +0 -0
  543. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/test_artifact_collector.py +0 -0
  544. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/test_codex_artifacts.py +0 -0
  545. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/test_convergence.py +0 -0
  546. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/test_dashboard.py +0 -0
  547. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/test_dependencies_configured.py +0 -0
  548. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/test_evolve_rewind.py +0 -0
  549. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/test_evolve_step.py +0 -0
  550. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/test_graceful_shutdown.py +0 -0
  551. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/test_main_entry_point.py +0 -0
  552. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/test_module_structure.py +0 -0
  553. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/test_project_initialization.py +0 -0
  554. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/test_projector_rewind.py +0 -0
  555. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/test_ralph_parser.py +0 -0
  556. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/test_ralph_rewind.py +0 -0
  557. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/test_regression.py +0 -0
  558. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/test_tooling_configuration.py +0 -0
  559. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/test_verification.py +0 -0
  560. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/tui/__init__.py +0 -0
  561. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/tui/test_app.py +0 -0
  562. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/tui/test_cancelled_display.py +0 -0
  563. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/tui/test_events.py +0 -0
  564. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/tui/test_lineage_viewer.py +0 -0
  565. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/tui/test_screens.py +0 -0
  566. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/tui/test_session_selector_replay.py +0 -0
  567. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tests/unit/tui/test_widgets.py +0 -0
  568. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/tools/sync_github_project.py +0 -0
  569. {ouroboros_ai-0.26.5.dev3 → ouroboros_ai-0.26.5.dev5}/uv.lock +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ouroboros-ai
3
- Version: 0.26.5.dev3
3
+ Version: 0.26.5.dev5
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
@@ -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.dev3'
22
- __version_tuple__ = version_tuple = (0, 26, 5, 'dev3')
21
+ __version__ = version = '0.26.5.dev5'
22
+ __version_tuple__ = version_tuple = (0, 26, 5, 'dev5')
23
23
 
24
24
  __commit_id__ = commit_id = None
@@ -0,0 +1,61 @@
1
+ """Shared PM interview completion helpers."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from typing import Any
6
+
7
+ from ouroboros.bigbang.interview import InterviewState
8
+ from ouroboros.bigbang.pm_interview import PMInterviewEngine
9
+ from ouroboros.core.errors import ValidationError
10
+ from ouroboros.core.types import Result
11
+
12
+
13
+ async def maybe_complete_pm_interview(
14
+ state: InterviewState,
15
+ engine: PMInterviewEngine,
16
+ ) -> Result[tuple[InterviewState, dict[str, Any] | None], ValidationError]:
17
+ """Run PM ambiguity completion logic and mark the interview complete if ready."""
18
+ completion = await engine.check_completion(state)
19
+ if completion is None:
20
+ return Result.ok((state, None))
21
+
22
+ complete_result = await engine.complete_interview(state)
23
+ if complete_result.is_err:
24
+ return Result.err(complete_result.error)
25
+
26
+ return Result.ok((complete_result.value, completion))
27
+
28
+
29
+ def build_pm_completion_summary(
30
+ *,
31
+ session_id: str,
32
+ completion: dict[str, Any] | None,
33
+ stored_ambiguity_score: float | None = None,
34
+ deferred_count: int,
35
+ decide_later_count: int,
36
+ decide_later_summary: str,
37
+ ) -> str:
38
+ """Build human-readable PM completion text for CLI and MCP flows."""
39
+ lines = [f"Interview complete. Session ID: {session_id}"]
40
+
41
+ if completion is not None:
42
+ lines.append(f"Rounds completed: {completion['rounds_completed']}")
43
+ lines.append(f"Completion reason: {completion['completion_reason']}")
44
+
45
+ ambiguity_score = (
46
+ completion.get("ambiguity_score") if completion is not None else stored_ambiguity_score
47
+ )
48
+ if ambiguity_score is not None:
49
+ lines.append(f"Ambiguity score: {ambiguity_score:.2f}")
50
+
51
+ lines.append("")
52
+ lines.append(f"Deferred items: {deferred_count}")
53
+ lines.append(f"Decide-later items: {decide_later_count}")
54
+
55
+ if decide_later_summary:
56
+ lines.append("")
57
+ lines.append(decide_later_summary)
58
+
59
+ lines.append("")
60
+ lines.append(f'Generate PM with: action="generate", session_id="{session_id}"')
61
+ return "\n".join(lines)
@@ -17,6 +17,10 @@ from rich.prompt import Confirm, Prompt
17
17
  import typer
18
18
 
19
19
  from ouroboros.bigbang.interview import InterviewRound
20
+ from ouroboros.bigbang.pm_completion import (
21
+ build_pm_completion_summary,
22
+ maybe_complete_pm_interview,
23
+ )
20
24
  from ouroboros.cli.formatters import console
21
25
  from ouroboros.cli.formatters.panels import print_error, print_info, print_success, print_warning
22
26
  from ouroboros.cli.formatters.prompting import multiline_prompt_async
@@ -479,15 +483,30 @@ async def _run_pm_interview(
479
483
  # so extraction never sees a question the user didn't answer.
480
484
  if state.rounds and state.rounds[-1].user_response is None:
481
485
  state.rounds.pop()
486
+
487
+ completion = await engine.check_completion(state)
482
488
  complete_result = await engine.complete_interview(state)
483
- if isinstance(complete_result, Result) and complete_result.is_err:
489
+ if complete_result.is_err:
484
490
  print_error(f"Failed to complete interview: {complete_result.error}")
485
- elif isinstance(complete_result, Result):
486
- state = complete_result.value
491
+ break
492
+
493
+ state = complete_result.value
487
494
  save_result = await engine.save_state(state)
488
- if isinstance(save_result, Result) and save_result.is_err:
495
+ if save_result.is_err:
489
496
  print_error(f"Failed to save completed state: {save_result.error}")
497
+ break
490
498
  _save_cli_pm_meta(state.interview_id, engine)
499
+
500
+ decide_later_summary = engine.format_decide_later_summary()
501
+ summary_text = build_pm_completion_summary(
502
+ session_id=state.interview_id,
503
+ completion=completion,
504
+ stored_ambiguity_score=state.ambiguity_score,
505
+ deferred_count=len(engine.deferred_items),
506
+ decide_later_count=len(engine.decide_later_items),
507
+ decide_later_summary=decide_later_summary,
508
+ )
509
+ console.print(f"\n[bold green]{summary_text}[/]\n")
491
510
  break
492
511
 
493
512
  # Pop the unanswered round before recording so record_response
@@ -534,6 +553,33 @@ async def _run_pm_interview(
534
553
  break
535
554
  if isinstance(record_result, Result):
536
555
  state = record_result.value
556
+
557
+ state.clear_stored_ambiguity()
558
+ completion_result = await maybe_complete_pm_interview(state, engine)
559
+ if completion_result.is_err:
560
+ print_error(f"Failed to complete interview: {completion_result.error}")
561
+ break
562
+
563
+ state, completion = completion_result.value
564
+ if completion is not None:
565
+ save_result = await engine.save_state(state)
566
+ if save_result.is_err:
567
+ print_error(f"Failed to save completed state: {save_result.error}")
568
+ break
569
+ _save_cli_pm_meta(state.interview_id, engine)
570
+
571
+ decide_later_summary = engine.format_decide_later_summary()
572
+ summary_text = build_pm_completion_summary(
573
+ session_id=state.interview_id,
574
+ completion=completion,
575
+ stored_ambiguity_score=state.ambiguity_score,
576
+ deferred_count=len(engine.deferred_items),
577
+ decide_later_count=len(engine.decide_later_items),
578
+ decide_later_summary=decide_later_summary,
579
+ )
580
+ console.print(f"\n[bold green]{summary_text}[/]\n")
581
+ break
582
+
537
583
  save_result = await engine.save_state(state)
538
584
  if isinstance(save_result, Result) and save_result.is_err:
539
585
  print_error(f"Failed to save state: {save_result.error}")
@@ -30,6 +30,10 @@ from ouroboros.bigbang.interview import (
30
30
  InterviewRound,
31
31
  InterviewState,
32
32
  )
33
+ from ouroboros.bigbang.pm_completion import (
34
+ build_pm_completion_summary,
35
+ maybe_complete_pm_interview,
36
+ )
33
37
  from ouroboros.bigbang.pm_document import save_pm_document
34
38
  from ouroboros.bigbang.pm_interview import PMInterviewEngine
35
39
  from ouroboros.config import get_clarification_model
@@ -944,10 +948,17 @@ class PMInterviewHandler:
944
948
  # Completion is determined by engine ambiguity scoring.
945
949
  # When complete, auto-generate the PM document immediately
946
950
  # (no separate "generate" call needed from the skill).
947
- completion = await _check_completion(state, engine)
951
+ completion_result = await maybe_complete_pm_interview(state, engine)
952
+ if completion_result.is_err:
953
+ return Result.err(
954
+ MCPToolError(
955
+ f"Failed to complete interview: {completion_result.error}",
956
+ tool_name="ouroboros_pm_interview",
957
+ )
958
+ )
959
+
960
+ state, completion = completion_result.value
948
961
  if completion is not None:
949
- # Mark interview as complete
950
- await engine.complete_interview(state)
951
962
  save_result = await engine.save_state(state)
952
963
  if isinstance(save_result, Result) and save_result.is_err:
953
964
  return Result.err(
@@ -1012,22 +1023,15 @@ class PMInterviewHandler:
1012
1023
  )
1013
1024
 
1014
1025
  decide_later_summary = engine.format_decide_later_summary()
1015
- summary_text = (
1016
- f"Interview complete. PM document generated.\n\n"
1017
- f"Session ID: {session_id}\n"
1018
- f"Rounds completed: {completion['rounds_completed']}\n"
1019
- f"Completion reason: {completion['completion_reason']}\n"
1020
- )
1021
- if completion.get("ambiguity_score") is not None:
1022
- summary_text += f"Ambiguity score: {completion['ambiguity_score']:.2f}\n"
1023
- summary_text += (
1024
- f"\nPM document: {pm_path}\n"
1025
- f"Seed: {seed_path}\n"
1026
- f"\nDeferred items: {len(seed.deferred_items)}\n"
1027
- f"Decide-later items: {len(seed.decide_later_items)}\n"
1026
+ summary_text = build_pm_completion_summary(
1027
+ session_id=session_id,
1028
+ completion=completion,
1029
+ stored_ambiguity_score=getattr(state, "ambiguity_score", None),
1030
+ deferred_count=len(engine.deferred_items),
1031
+ decide_later_count=len(engine.decide_later_items),
1032
+ decide_later_summary=decide_later_summary,
1028
1033
  )
1029
- if decide_later_summary:
1030
- summary_text += f"\n{decide_later_summary}\n"
1034
+ summary_text += f"\n\nPM document: {pm_path}\nSeed: {seed_path}"
1031
1035
 
1032
1036
  response_meta = {
1033
1037
  "session_id": session_id,
@@ -694,13 +694,6 @@ class CodexCliRuntime:
694
694
  ) -> list[str]:
695
695
  """Build the CLI command args. Prompt is fed via stdin separately."""
696
696
  command = [self._cli_path, "exec"]
697
- if resume_session_id:
698
- if not _SAFE_SESSION_ID_PATTERN.match(resume_session_id):
699
- raise ValueError(
700
- f"Invalid resume_session_id: contains disallowed characters: "
701
- f"{resume_session_id!r}"
702
- )
703
- command.extend(["resume", resume_session_id])
704
697
 
705
698
  command.extend(
706
699
  [
@@ -718,8 +711,28 @@ class CodexCliRuntime:
718
711
  command.extend(["--model", normalized_model])
719
712
 
720
713
  command.extend(self._build_permission_args())
714
+ if resume_session_id:
715
+ if not _SAFE_SESSION_ID_PATTERN.match(resume_session_id):
716
+ raise ValueError(
717
+ f"Invalid resume_session_id: contains disallowed characters: "
718
+ f"{resume_session_id!r}"
719
+ )
720
+ command.extend(["resume", resume_session_id])
721
721
  return command
722
722
 
723
+ def _build_resume_retry_metadata(self, resume_session_id: str | None) -> dict[str, Any]:
724
+ """Return retry metadata for resume failures that happen before reconnect."""
725
+ if not resume_session_id:
726
+ return {}
727
+ return {
728
+ "recoverable": True,
729
+ "recovery": {
730
+ "kind": "resume_retry",
731
+ "reason": "resume_bootstrap_failed",
732
+ "resume_session_id": resume_session_id,
733
+ },
734
+ }
735
+
723
736
  def _resolve_resume_session_id(
724
737
  self,
725
738
  current_handle: RuntimeHandle | None,
@@ -1432,11 +1445,25 @@ class CodexCliRuntime:
1432
1445
 
1433
1446
  composed_prompt = self._compose_prompt(prompt, system_prompt, tools)
1434
1447
  attempted_resume_session_id = self._resolve_resume_session_id(current_handle)
1435
- command = self._build_command(
1436
- output_last_message_path=str(output_path),
1437
- resume_session_id=attempted_resume_session_id,
1438
- prompt=composed_prompt,
1439
- )
1448
+ try:
1449
+ command = self._build_command(
1450
+ output_last_message_path=str(output_path),
1451
+ resume_session_id=attempted_resume_session_id,
1452
+ prompt=composed_prompt,
1453
+ )
1454
+ except Exception as e:
1455
+ yield AgentMessage(
1456
+ type="result",
1457
+ content=f"Failed to prepare {self._display_name}: {e}",
1458
+ data={
1459
+ "subtype": "error",
1460
+ "error_type": type(e).__name__,
1461
+ **self._build_resume_retry_metadata(attempted_resume_session_id),
1462
+ },
1463
+ resume_handle=current_handle,
1464
+ )
1465
+ output_path.unlink(missing_ok=True)
1466
+ return
1440
1467
 
1441
1468
  log.info(
1442
1469
  f"{self._log_namespace}.task_started",
@@ -1447,6 +1474,7 @@ class CodexCliRuntime:
1447
1474
 
1448
1475
  stderr_lines: list[str] = []
1449
1476
  last_content = ""
1477
+ saw_runtime_event = False
1450
1478
  yielded_final = False # Track if a final (type="result") message was already emitted
1451
1479
  process: Any | None = None
1452
1480
  process_finished = False
@@ -1467,7 +1495,11 @@ class CodexCliRuntime:
1467
1495
  yield AgentMessage(
1468
1496
  type="result",
1469
1497
  content=f"{self._display_name} not found: {e}",
1470
- data={"subtype": "error", "error_type": type(e).__name__},
1498
+ data={
1499
+ "subtype": "error",
1500
+ "error_type": type(e).__name__,
1501
+ **self._build_resume_retry_metadata(attempted_resume_session_id),
1502
+ },
1471
1503
  resume_handle=current_handle,
1472
1504
  )
1473
1505
  output_path.unlink(missing_ok=True)
@@ -1476,7 +1508,11 @@ class CodexCliRuntime:
1476
1508
  yield AgentMessage(
1477
1509
  type="result",
1478
1510
  content=f"Failed to start {self._display_name}: {e}",
1479
- data={"subtype": "error", "error_type": type(e).__name__},
1511
+ data={
1512
+ "subtype": "error",
1513
+ "error_type": type(e).__name__,
1514
+ **self._build_resume_retry_metadata(attempted_resume_session_id),
1515
+ },
1480
1516
  resume_handle=current_handle,
1481
1517
  )
1482
1518
  output_path.unlink(missing_ok=True)
@@ -1515,6 +1551,7 @@ class CodexCliRuntime:
1515
1551
  event = self._parse_json_event(line)
1516
1552
  if event is None:
1517
1553
  continue
1554
+ saw_runtime_event = True
1518
1555
 
1519
1556
  previous_handle = current_handle
1520
1557
  session_rebound = False
@@ -1652,6 +1689,8 @@ class CodexCliRuntime:
1652
1689
  data["session_id"] = current_handle.native_session_id
1653
1690
  if returncode != 0:
1654
1691
  data["error_type"] = self._runtime_error_type
1692
+ if attempted_resume_session_id and not saw_runtime_event:
1693
+ data.update(self._build_resume_retry_metadata(attempted_resume_session_id))
1655
1694
 
1656
1695
  yield AgentMessage(
1657
1696
  type="result",
@@ -653,6 +653,29 @@ class OrchestratorRunner:
653
653
  }
654
654
  return event.model_copy(update={"data": event_data})
655
655
 
656
+ @staticmethod
657
+ def _is_recoverable_resume_failure(message: AgentMessage) -> bool:
658
+ """Return True when a final resume error should leave the session resumable."""
659
+ if not (message.is_final and message.is_error):
660
+ return False
661
+
662
+ data = message.data
663
+ metadata_candidates = (
664
+ data,
665
+ data.get("meta") if isinstance(data.get("meta"), dict) else None,
666
+ data.get("mcp_meta") if isinstance(data.get("mcp_meta"), dict) else None,
667
+ )
668
+ for metadata in metadata_candidates:
669
+ if not isinstance(metadata, dict):
670
+ continue
671
+ if metadata.get("recoverable") is True:
672
+ return True
673
+ if metadata.get("is_retriable") is True or metadata.get("retriable") is True:
674
+ return True
675
+
676
+ recovery = data.get("recovery")
677
+ return isinstance(recovery, dict) and recovery.get("kind") == "resume_retry"
678
+
656
679
  def _should_emit_progress_event(
657
680
  self,
658
681
  message: AgentMessage,
@@ -1852,6 +1875,7 @@ Note: This is a resumed session. Please continue from where execution was interr
1852
1875
  messages_processed = tracker.messages_processed
1853
1876
  final_message = ""
1854
1877
  success = False
1878
+ recoverable_resume_failure = False
1855
1879
 
1856
1880
  # Create workflow state tracker for progress display
1857
1881
  from ouroboros.orchestrator.workflow_state import WorkflowStateTracker
@@ -1996,6 +2020,7 @@ Note: This is a resumed session. Please continue from where execution was interr
1996
2020
  if message.is_final:
1997
2021
  final_message = message.content
1998
2022
  success = not message.is_error
2023
+ recoverable_resume_failure = self._is_recoverable_resume_failure(message)
1999
2024
 
2000
2025
  duration = (datetime.now(UTC) - start_time).total_seconds()
2001
2026
 
@@ -2014,6 +2039,21 @@ Note: This is a resumed session. Please continue from where execution was interr
2014
2039
  border_style="green",
2015
2040
  )
2016
2041
  )
2042
+ elif recoverable_resume_failure:
2043
+ await self._session_repo.mark_paused(
2044
+ session_id,
2045
+ reason=final_message,
2046
+ resume_hint=(
2047
+ "Retry the same --resume session after fixing the runtime/tooling issue."
2048
+ ),
2049
+ )
2050
+ self._console.print(
2051
+ Panel(
2052
+ Text(final_message[:1000], style="yellow"),
2053
+ title="[yellow]Resumed Execution Paused[/yellow]",
2054
+ border_style="yellow",
2055
+ )
2056
+ )
2017
2057
  else:
2018
2058
  await self._session_repo.mark_failed(session_id, final_message)
2019
2059
  self._console.print(
@@ -604,6 +604,54 @@ class SessionRepository:
604
604
  )
605
605
  )
606
606
 
607
+ async def mark_paused(
608
+ self,
609
+ session_id: str,
610
+ reason: str,
611
+ resume_hint: str | None = None,
612
+ ) -> Result[None, PersistenceError]:
613
+ """Mark session as paused and resumable.
614
+
615
+ Args:
616
+ session_id: Session being paused.
617
+ reason: Why the session was paused.
618
+ resume_hint: Optional retry guidance.
619
+
620
+ Returns:
621
+ Result indicating success or failure.
622
+ """
623
+ event = BaseEvent(
624
+ type="orchestrator.session.paused",
625
+ aggregate_type="session",
626
+ aggregate_id=session_id,
627
+ data={
628
+ "reason": reason,
629
+ "resume_hint": resume_hint,
630
+ "paused_at": datetime.now(UTC).isoformat(),
631
+ },
632
+ )
633
+
634
+ try:
635
+ await self._event_store.append(event)
636
+ log.info(
637
+ "orchestrator.session.paused",
638
+ session_id=session_id,
639
+ reason=reason,
640
+ )
641
+ return Result.ok(None)
642
+ except Exception as e:
643
+ log.exception(
644
+ "orchestrator.session.pause_failed",
645
+ session_id=session_id,
646
+ error=str(e),
647
+ )
648
+ return Result.err(
649
+ PersistenceError(
650
+ message=f"Failed to mark session paused: {e}",
651
+ details={"session_id": session_id},
652
+ )
653
+ )
654
+
607
655
  async def mark_cancelled(
608
656
  self,
609
657
  session_id: str,
@@ -0,0 +1,76 @@
1
+ """Tests for shared PM completion helpers."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from types import SimpleNamespace
6
+ from unittest.mock import AsyncMock, MagicMock
7
+
8
+ import pytest
9
+
10
+ from ouroboros.bigbang.pm_completion import (
11
+ build_pm_completion_summary,
12
+ maybe_complete_pm_interview,
13
+ )
14
+ from ouroboros.core.types import Result
15
+
16
+
17
+ @pytest.mark.asyncio
18
+ async def test_maybe_complete_pm_interview_returns_none_when_not_ready() -> None:
19
+ """No completion metadata means the interview should continue."""
20
+ state = SimpleNamespace(interview_id="sess-1")
21
+ engine = MagicMock()
22
+ engine.check_completion = AsyncMock(return_value=None)
23
+ engine.complete_interview = AsyncMock()
24
+
25
+ result = await maybe_complete_pm_interview(state, engine)
26
+
27
+ assert result.is_ok
28
+ assert result.value == (state, None)
29
+ engine.complete_interview.assert_not_awaited()
30
+
31
+
32
+ @pytest.mark.asyncio
33
+ async def test_maybe_complete_pm_interview_marks_complete_when_ready() -> None:
34
+ """Ready interviews should be marked complete through the shared helper."""
35
+ state = SimpleNamespace(interview_id="sess-1")
36
+ completed_state = SimpleNamespace(interview_id="sess-1", status="completed")
37
+ engine = MagicMock()
38
+ engine.check_completion = AsyncMock(
39
+ return_value={
40
+ "interview_complete": True,
41
+ "completion_reason": "ambiguity_resolved",
42
+ "rounds_completed": 5,
43
+ "ambiguity_score": 0.18,
44
+ }
45
+ )
46
+ engine.complete_interview = AsyncMock(return_value=Result.ok(completed_state))
47
+
48
+ result = await maybe_complete_pm_interview(state, engine)
49
+
50
+ assert result.is_ok
51
+ assert result.value == (
52
+ completed_state,
53
+ {
54
+ "interview_complete": True,
55
+ "completion_reason": "ambiguity_resolved",
56
+ "rounds_completed": 5,
57
+ "ambiguity_score": 0.18,
58
+ },
59
+ )
60
+ engine.complete_interview.assert_awaited_once_with(state)
61
+
62
+
63
+ def test_build_pm_completion_summary_uses_stored_score_fallback() -> None:
64
+ """Forced completion should still surface the stored ambiguity score."""
65
+ summary = build_pm_completion_summary(
66
+ session_id="sess-1",
67
+ completion=None,
68
+ stored_ambiguity_score=0.34,
69
+ deferred_count=1,
70
+ decide_later_count=2,
71
+ decide_later_summary="Items to decide later:\n 1. Example",
72
+ )
73
+
74
+ assert "Interview complete. Session ID: sess-1" in summary
75
+ assert "Ambiguity score: 0.34" in summary
76
+ assert 'Generate PM with: action="generate", session_id="sess-1"' in summary
@@ -0,0 +1,117 @@
1
+ """Regression tests for PM CLI completion and ambiguity persistence."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from pathlib import Path
6
+ from types import SimpleNamespace
7
+ from unittest.mock import AsyncMock, MagicMock, patch
8
+
9
+ import pytest
10
+
11
+ from ouroboros.bigbang.interview import InterviewRound
12
+ from ouroboros.cli.commands.pm import _run_pm_interview
13
+ from ouroboros.core.types import Result
14
+
15
+
16
+ def _resume_state(*, pending_question: str = "Current question?") -> SimpleNamespace:
17
+ """Create a minimal resumable PM interview state."""
18
+ return SimpleNamespace(
19
+ interview_id="sess-123",
20
+ rounds=[InterviewRound(round_number=1, question=pending_question, user_response=None)],
21
+ is_complete=False,
22
+ ambiguity_score=None,
23
+ clear_stored_ambiguity=MagicMock(),
24
+ mark_updated=MagicMock(),
25
+ )
26
+
27
+
28
+ @pytest.mark.asyncio
29
+ async def test_run_pm_interview_auto_completes_after_answer(tmp_path: Path) -> None:
30
+ """A normal answer should auto-complete when ambiguity is resolved."""
31
+ state = _resume_state()
32
+ updated_state = SimpleNamespace(**{**state.__dict__})
33
+ completed_state = SimpleNamespace(**{**updated_state.__dict__, "is_complete": True})
34
+ engine = MagicMock()
35
+ engine.load_state = AsyncMock(return_value=Result.ok(state))
36
+ engine.record_response = AsyncMock(return_value=Result.ok(updated_state))
37
+ engine.save_state = AsyncMock(return_value=Result.ok(tmp_path / "state.json"))
38
+ engine.format_decide_later_summary.return_value = ""
39
+ engine._install_pm_steering = MagicMock()
40
+
41
+ completion = {
42
+ "interview_complete": True,
43
+ "completion_reason": "ambiguity_resolved",
44
+ "rounds_completed": 1,
45
+ "ambiguity_score": 0.18,
46
+ }
47
+
48
+ with (
49
+ patch("ouroboros.providers.litellm_adapter.LiteLLMAdapter", return_value=object()),
50
+ patch("ouroboros.bigbang.pm_interview.PMInterviewEngine.create", return_value=engine),
51
+ patch(
52
+ "ouroboros.cli.commands.pm.multiline_prompt_async",
53
+ new_callable=AsyncMock,
54
+ return_value="Final answer",
55
+ ),
56
+ patch("ouroboros.cli.commands.pm._save_cli_pm_meta"),
57
+ patch(
58
+ "ouroboros.cli.commands.pm.maybe_complete_pm_interview",
59
+ new_callable=AsyncMock,
60
+ return_value=Result.ok((completed_state, completion)),
61
+ ) as mock_complete,
62
+ patch("ouroboros.cli.commands.pm.console.print") as mock_print,
63
+ patch("ouroboros.cli.commands.pm.print_success"),
64
+ ):
65
+ await _run_pm_interview(resume_id="sess-123", model="test-model", debug=False)
66
+
67
+ updated_state.clear_stored_ambiguity.assert_called_once()
68
+ mock_complete.assert_awaited_once_with(updated_state, engine)
69
+ assert engine.save_state.await_count == 2
70
+ assert engine.save_state.await_args_list[-1].args == (completed_state,)
71
+
72
+ printed = "\n".join(str(call.args[0]) for call in mock_print.call_args_list if call.args)
73
+ assert "Interview complete. Session ID: sess-123" in printed
74
+ assert "Ambiguity score: 0.18" in printed
75
+
76
+
77
+ @pytest.mark.asyncio
78
+ async def test_run_pm_interview_done_path_persists_stored_ambiguity(tmp_path: Path) -> None:
79
+ """Forced completion via done should still store and display ambiguity."""
80
+ state = _resume_state()
81
+ completed_state = SimpleNamespace(
82
+ **{**state.__dict__, "is_complete": True, "ambiguity_score": 0.34}
83
+ )
84
+ engine = MagicMock()
85
+ engine.load_state = AsyncMock(return_value=Result.ok(state))
86
+ engine.complete_interview = AsyncMock(return_value=Result.ok(completed_state))
87
+ engine.save_state = AsyncMock(return_value=Result.ok(tmp_path / "state.json"))
88
+ engine.format_decide_later_summary.return_value = ""
89
+ engine._install_pm_steering = MagicMock()
90
+
91
+ async def fake_check_completion(current_state: SimpleNamespace) -> None:
92
+ current_state.ambiguity_score = 0.34
93
+ return None
94
+
95
+ engine.check_completion = AsyncMock(side_effect=fake_check_completion)
96
+
97
+ with (
98
+ patch("ouroboros.providers.litellm_adapter.LiteLLMAdapter", return_value=object()),
99
+ patch("ouroboros.bigbang.pm_interview.PMInterviewEngine.create", return_value=engine),
100
+ patch(
101
+ "ouroboros.cli.commands.pm.multiline_prompt_async",
102
+ new_callable=AsyncMock,
103
+ return_value="done",
104
+ ),
105
+ patch("ouroboros.cli.commands.pm._save_cli_pm_meta"),
106
+ patch("ouroboros.cli.commands.pm.console.print") as mock_print,
107
+ patch("ouroboros.cli.commands.pm.print_success"),
108
+ ):
109
+ await _run_pm_interview(resume_id="sess-123", model="test-model", debug=False)
110
+
111
+ engine.complete_interview.assert_awaited_once_with(state)
112
+ assert engine.save_state.await_count == 2
113
+ assert engine.save_state.await_args_list[-1].args == (completed_state,)
114
+
115
+ printed = "\n".join(str(call.args[0]) for call in mock_print.call_args_list if call.args)
116
+ assert "Interview complete. Session ID: sess-123" in printed
117
+ assert "Ambiguity score: 0.34" in printed