ouroboros-ai 0.27.3.dev2__tar.gz → 0.27.3.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.

Files changed (645) hide show
  1. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/PKG-INFO +1 -1
  2. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/_version.py +2 -2
  3. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/cli/commands/mcp.py +30 -11
  4. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/orchestrator/session.py +84 -1
  5. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/persistence/event_store.py +158 -1
  6. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/cli/test_mcp_startup_cleanup.py +124 -2
  7. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/orchestrator/test_session.py +33 -0
  8. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/persistence/test_event_store.py +58 -0
  9. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/.claude/settings.json +0 -0
  10. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/.claude-plugin/.mcp.json +0 -0
  11. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/.claude-plugin/marketplace.json +0 -0
  12. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/.claude-plugin/plugin.json +0 -0
  13. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/.env.example +0 -0
  14. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
  15. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/.github/ISSUE_TEMPLATE/config.yml +0 -0
  16. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/.github/ISSUE_TEMPLATE/feature_request.yml +0 -0
  17. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/.github/ISSUE_TEMPLATE/question.yml +0 -0
  18. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/.github/workflows/dev-publish.yml +0 -0
  19. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/.github/workflows/lint.yml +0 -0
  20. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/.github/workflows/release.yml +0 -0
  21. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/.github/workflows/test.yml +0 -0
  22. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/.gitignore +0 -0
  23. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/.mcp.json +0 -0
  24. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/.ouroboros/mechanical.toml +0 -0
  25. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/.ouroboros/seeds/seed_73827177a2a3.yaml +0 -0
  26. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/.ouroboros/seeds/seed_78c8e6e41813.yaml +0 -0
  27. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/.pre-commit-config.yaml +0 -0
  28. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/.python-version +0 -0
  29. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/CHANGELOG.md +0 -0
  30. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/CLAUDE.md +0 -0
  31. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/CODE_OF_CONDUCT.md +0 -0
  32. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/CONTRIBUTING.md +0 -0
  33. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/HANDOFF.md +0 -0
  34. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/LICENSE +0 -0
  35. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/README.ko.md +0 -0
  36. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/README.md +0 -0
  37. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/SECURITY.md +0 -0
  38. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/UNINSTALL.md +0 -0
  39. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/commands/cancel.md +0 -0
  40. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/commands/evaluate.md +0 -0
  41. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/commands/evolve.md +0 -0
  42. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/commands/help.md +0 -0
  43. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/commands/interview.md +0 -0
  44. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/commands/ralph.md +0 -0
  45. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/commands/run.md +0 -0
  46. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/commands/seed.md +0 -0
  47. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/commands/setup.md +0 -0
  48. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/commands/status.md +0 -0
  49. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/commands/tutorial.md +0 -0
  50. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/commands/unstuck.md +0 -0
  51. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/commands/welcome.md +0 -0
  52. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/crates/ouroboros-tui/.gitignore +0 -0
  53. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/crates/ouroboros-tui/Cargo.lock +0 -0
  54. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/crates/ouroboros-tui/Cargo.toml +0 -0
  55. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/crates/ouroboros-tui/README.md +0 -0
  56. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/crates/ouroboros-tui/src/db.rs +0 -0
  57. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/crates/ouroboros-tui/src/main.rs +0 -0
  58. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/crates/ouroboros-tui/src/mock.rs +0 -0
  59. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/crates/ouroboros-tui/src/state.rs +0 -0
  60. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/crates/ouroboros-tui/src/views/dashboard.rs +0 -0
  61. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/crates/ouroboros-tui/src/views/execution.rs +0 -0
  62. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/crates/ouroboros-tui/src/views/lineage.rs +0 -0
  63. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/crates/ouroboros-tui/src/views/logs.rs +0 -0
  64. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/crates/ouroboros-tui/src/views/mod.rs +0 -0
  65. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/crates/ouroboros-tui/src/views/session_selector.rs +0 -0
  66. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/docs/README.md +0 -0
  67. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/docs/api/README.md +0 -0
  68. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/docs/api/core.md +0 -0
  69. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/docs/api/mcp.md +0 -0
  70. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/docs/architecture.md +0 -0
  71. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/docs/cli-reference.md +0 -0
  72. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/docs/config-reference.md +0 -0
  73. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/docs/contributing/architecture-overview.md +0 -0
  74. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/docs/contributing/findings-registry.md +0 -0
  75. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/docs/contributing/issue-quality-policy.md +0 -0
  76. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/docs/contributing/key-patterns.md +0 -0
  77. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/docs/contributing/testing-guide.md +0 -0
  78. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/docs/examples/mcp-config.yaml +0 -0
  79. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/docs/getting-started.md +0 -0
  80. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/docs/guides/evaluation-pipeline.md +0 -0
  81. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/docs/guides/evolution-loop.md +0 -0
  82. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/docs/guides/issue-176-subagent-mcp-inheritance.md +0 -0
  83. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/docs/guides/mcp-bridge.md +0 -0
  84. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/docs/guides/seed-authoring.md +0 -0
  85. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/docs/guides/tui-usage.md +0 -0
  86. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/docs/images/PLACEHOLDER_README.md +0 -0
  87. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/docs/images/ouroboros.png +0 -0
  88. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/docs/platform-support.md +0 -0
  89. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/docs/runtime-capability-matrix.md +0 -0
  90. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/docs/runtime-guides/claude-code.md +0 -0
  91. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/docs/runtime-guides/codex.md +0 -0
  92. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/docs/runtime-guides/opencode.md +0 -0
  93. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/examples/coordinator_test_seed.yaml +0 -0
  94. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/examples/dummy_seed.yaml +0 -0
  95. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/examples/parallel_subac_test_seed.yaml +0 -0
  96. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/examples/subac_test_seed.yaml +0 -0
  97. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/examples/task_manager/README.md +0 -0
  98. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/examples/task_manager/__init__.py +0 -0
  99. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/examples/task_manager/__main__.py +0 -0
  100. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/examples/task_manager/cli.py +0 -0
  101. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/examples/task_manager/models.py +0 -0
  102. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/examples/task_manager/storage.py +0 -0
  103. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/examples/test_display.py +0 -0
  104. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/hooks/hooks.json +0 -0
  105. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/llms-full.txt +0 -0
  106. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/llms.txt +0 -0
  107. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/project-context.md +0 -0
  108. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/pyproject.toml +0 -0
  109. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/scripts/drift-monitor.py +0 -0
  110. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/scripts/install.sh +0 -0
  111. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/scripts/keyword-detector.py +0 -0
  112. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/scripts/mcp-serve.sh +0 -0
  113. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/scripts/ralph-rewind.py +0 -0
  114. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/scripts/ralph.py +0 -0
  115. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/scripts/ralph.sh +0 -0
  116. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/scripts/session-start.py +0 -0
  117. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/scripts/sync-plugin-version.py +0 -0
  118. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/scripts/version-check.py +0 -0
  119. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/skills/brownfield/SKILL.md +0 -0
  120. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/skills/cancel/SKILL.md +0 -0
  121. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/skills/evaluate/SKILL.md +0 -0
  122. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/skills/evolve/SKILL.md +0 -0
  123. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/skills/help/SKILL.md +0 -0
  124. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/skills/interview/SKILL.md +0 -0
  125. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/skills/pm/SKILL.md +0 -0
  126. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/skills/publish/SKILL.md +0 -0
  127. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/skills/qa/SKILL.md +0 -0
  128. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/skills/ralph/SKILL.md +0 -0
  129. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/skills/run/SKILL.md +0 -0
  130. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/skills/seed/SKILL.md +0 -0
  131. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/skills/setup/SKILL.md +0 -0
  132. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/skills/status/SKILL.md +0 -0
  133. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/skills/tutorial/SKILL.md +0 -0
  134. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/skills/unstuck/SKILL.md +0 -0
  135. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/skills/update/SKILL.md +0 -0
  136. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/skills/welcome/SKILL.md +0 -0
  137. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/__init__.py +0 -0
  138. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/__main__.py +0 -0
  139. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/agents/__init__.py +0 -0
  140. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/agents/advocate.md +0 -0
  141. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/agents/analysis-agent.md +0 -0
  142. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/agents/architect.md +0 -0
  143. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/agents/breadth-keeper.md +0 -0
  144. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/agents/code-executor.md +0 -0
  145. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/agents/codebase-explorer.md +0 -0
  146. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/agents/consensus-reviewer.md +0 -0
  147. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/agents/contrarian.md +0 -0
  148. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/agents/evaluator.md +0 -0
  149. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/agents/hacker.md +0 -0
  150. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/agents/judge.md +0 -0
  151. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/agents/loader.py +0 -0
  152. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/agents/ontologist.md +0 -0
  153. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/agents/ontology-analyst.md +0 -0
  154. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/agents/qa-judge.md +0 -0
  155. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/agents/research-agent.md +0 -0
  156. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/agents/researcher.md +0 -0
  157. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/agents/seed-architect.md +0 -0
  158. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/agents/seed-closer.md +0 -0
  159. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/agents/semantic-evaluator.md +0 -0
  160. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/agents/simplifier.md +0 -0
  161. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/agents/socratic-interviewer.md +0 -0
  162. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/bigbang/__init__.py +0 -0
  163. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/bigbang/ambiguity.py +0 -0
  164. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/bigbang/brownfield.py +0 -0
  165. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/bigbang/explore.py +0 -0
  166. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/bigbang/interview.py +0 -0
  167. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/bigbang/pm_completion.py +0 -0
  168. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/bigbang/pm_document.py +0 -0
  169. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/bigbang/pm_interview.py +0 -0
  170. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/bigbang/pm_seed.py +0 -0
  171. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/bigbang/question_classifier.py +0 -0
  172. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/bigbang/seed_generator.py +0 -0
  173. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/cli/__init__.py +0 -0
  174. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/cli/commands/__init__.py +0 -0
  175. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/cli/commands/cancel.py +0 -0
  176. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/cli/commands/config.py +0 -0
  177. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/cli/commands/init.py +0 -0
  178. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/cli/commands/pm.py +0 -0
  179. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/cli/commands/run.py +0 -0
  180. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/cli/commands/setup.py +0 -0
  181. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/cli/commands/status.py +0 -0
  182. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/cli/commands/tui.py +0 -0
  183. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/cli/commands/uninstall.py +0 -0
  184. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/cli/formatters/__init__.py +0 -0
  185. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/cli/formatters/panels.py +0 -0
  186. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/cli/formatters/progress.py +0 -0
  187. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/cli/formatters/prompting.py +0 -0
  188. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/cli/formatters/tables.py +0 -0
  189. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/cli/formatters/workflow_display.py +0 -0
  190. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/cli/jsonc.py +0 -0
  191. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/cli/main.py +0 -0
  192. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/codex/__init__.py +0 -0
  193. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/codex/artifacts.py +0 -0
  194. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/codex/ouroboros.md +0 -0
  195. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/codex_permissions.py +0 -0
  196. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/config/__init__.py +0 -0
  197. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/config/loader.py +0 -0
  198. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/config/models.py +0 -0
  199. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/core/__init__.py +0 -0
  200. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/core/ac_tree.py +0 -0
  201. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/core/context.py +0 -0
  202. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/core/errors.py +0 -0
  203. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/core/file_lock.py +0 -0
  204. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/core/git_workflow.py +0 -0
  205. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/core/initial_context.py +0 -0
  206. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/core/json_utils.py +0 -0
  207. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/core/lineage.py +0 -0
  208. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/core/ontology_aspect.py +0 -0
  209. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/core/ontology_questions.py +0 -0
  210. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/core/project_paths.py +0 -0
  211. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/core/retry.py +0 -0
  212. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/core/security.py +0 -0
  213. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/core/seed.py +0 -0
  214. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/core/text.py +0 -0
  215. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/core/ttl_cache.py +0 -0
  216. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/core/types.py +0 -0
  217. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/core/worktree.py +0 -0
  218. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/evaluation/__init__.py +0 -0
  219. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/evaluation/artifact_collector.py +0 -0
  220. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/evaluation/consensus.py +0 -0
  221. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/evaluation/json_utils.py +0 -0
  222. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/evaluation/languages.py +0 -0
  223. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/evaluation/mechanical.py +0 -0
  224. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/evaluation/models.py +0 -0
  225. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/evaluation/pipeline.py +0 -0
  226. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/evaluation/semantic.py +0 -0
  227. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/evaluation/trigger.py +0 -0
  228. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/evaluation/verification_artifacts.py +0 -0
  229. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/events/__init__.py +0 -0
  230. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/events/base.py +0 -0
  231. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/events/decomposition.py +0 -0
  232. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/events/evaluation.py +0 -0
  233. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/events/interview.py +0 -0
  234. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/events/lineage.py +0 -0
  235. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/events/ontology.py +0 -0
  236. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/evolution/__init__.py +0 -0
  237. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/evolution/convergence.py +0 -0
  238. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/evolution/loop.py +0 -0
  239. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/evolution/projector.py +0 -0
  240. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/evolution/reflect.py +0 -0
  241. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/evolution/regression.py +0 -0
  242. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/evolution/wonder.py +0 -0
  243. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/execution/__init__.py +0 -0
  244. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/execution/atomicity.py +0 -0
  245. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/execution/decomposition.py +0 -0
  246. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/execution/double_diamond.py +0 -0
  247. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/execution/subagent.py +0 -0
  248. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/mcp/__init__.py +0 -0
  249. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/mcp/bridge/__init__.py +0 -0
  250. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/mcp/bridge/bridge.py +0 -0
  251. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/mcp/bridge/config.py +0 -0
  252. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/mcp/bridge/factory.py +0 -0
  253. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/mcp/client/__init__.py +0 -0
  254. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/mcp/client/adapter.py +0 -0
  255. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/mcp/client/manager.py +0 -0
  256. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/mcp/client/protocol.py +0 -0
  257. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/mcp/errors.py +0 -0
  258. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/mcp/job_manager.py +0 -0
  259. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/mcp/resources/__init__.py +0 -0
  260. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/mcp/resources/handlers.py +0 -0
  261. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/mcp/server/__init__.py +0 -0
  262. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/mcp/server/adapter.py +0 -0
  263. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/mcp/server/protocol.py +0 -0
  264. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/mcp/server/security.py +0 -0
  265. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/mcp/tools/__init__.py +0 -0
  266. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/mcp/tools/ac_tree_hud_handler.py +0 -0
  267. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/mcp/tools/ac_tree_hud_render.py +0 -0
  268. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/mcp/tools/authoring_handlers.py +0 -0
  269. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/mcp/tools/bridge_mixin.py +0 -0
  270. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/mcp/tools/brownfield_handler.py +0 -0
  271. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/mcp/tools/dashboard.py +0 -0
  272. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/mcp/tools/definitions.py +0 -0
  273. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/mcp/tools/evaluation_handlers.py +0 -0
  274. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/mcp/tools/evolution_handlers.py +0 -0
  275. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/mcp/tools/execution_handlers.py +0 -0
  276. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/mcp/tools/job_handlers.py +0 -0
  277. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/mcp/tools/pm_handler.py +0 -0
  278. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/mcp/tools/qa.py +0 -0
  279. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/mcp/tools/query_handlers.py +0 -0
  280. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/mcp/tools/registry.py +0 -0
  281. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/mcp/types.py +0 -0
  282. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/observability/__init__.py +0 -0
  283. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/observability/drift.py +0 -0
  284. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/observability/logging.py +0 -0
  285. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/observability/retrospective.py +0 -0
  286. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/orchestrator/__init__.py +0 -0
  287. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/orchestrator/adapter.py +0 -0
  288. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/orchestrator/capabilities.py +0 -0
  289. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/orchestrator/codex_cli_runtime.py +0 -0
  290. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/orchestrator/command_dispatcher.py +0 -0
  291. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/orchestrator/control_plane.py +0 -0
  292. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/orchestrator/coordinator.py +0 -0
  293. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/orchestrator/dependency_analyzer.py +0 -0
  294. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/orchestrator/events.py +0 -0
  295. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/orchestrator/execution_runtime_scope.py +0 -0
  296. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/orchestrator/execution_strategy.py +0 -0
  297. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/orchestrator/heartbeat.py +0 -0
  298. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/orchestrator/level_context.py +0 -0
  299. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/orchestrator/mcp_config.py +0 -0
  300. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/orchestrator/mcp_tools.py +0 -0
  301. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/orchestrator/opencode_event_normalizer.py +0 -0
  302. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/orchestrator/opencode_runtime.py +0 -0
  303. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/orchestrator/parallel_executor.py +0 -0
  304. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/orchestrator/parallel_executor_models.py +0 -0
  305. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/orchestrator/policy.py +0 -0
  306. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/orchestrator/runner.py +0 -0
  307. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/orchestrator/runtime_factory.py +0 -0
  308. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/orchestrator/runtime_message_projection.py +0 -0
  309. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/orchestrator/workflow_state.py +0 -0
  310. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/persistence/__init__.py +0 -0
  311. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/persistence/brownfield.py +0 -0
  312. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/persistence/checkpoint.py +0 -0
  313. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/persistence/migrations/__init__.py +0 -0
  314. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/persistence/migrations/runner.py +0 -0
  315. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/persistence/migrations/scripts/001_initial.sql +0 -0
  316. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/persistence/migrations/scripts/002_brownfield.sql +0 -0
  317. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/persistence/schema.py +0 -0
  318. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/persistence/uow.py +0 -0
  319. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/plugin/__init__.py +0 -0
  320. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/plugin/agents/__init__.py +0 -0
  321. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/plugin/agents/pool.py +0 -0
  322. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/plugin/agents/registry.py +0 -0
  323. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/plugin/orchestration/__init__.py +0 -0
  324. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/plugin/orchestration/router.py +0 -0
  325. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/plugin/orchestration/scheduler.py +0 -0
  326. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/plugin/skills/__init__.py +0 -0
  327. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/plugin/skills/docs.py +0 -0
  328. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/plugin/skills/executor.py +0 -0
  329. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/plugin/skills/keywords.py +0 -0
  330. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/plugin/skills/registry.py +0 -0
  331. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/pm/__init__.py +0 -0
  332. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/pm/handoff.py +0 -0
  333. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/pm/renderer.py +0 -0
  334. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/providers/__init__.py +0 -0
  335. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/providers/anthropic_adapter.py +0 -0
  336. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/providers/base.py +0 -0
  337. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/providers/claude_code_adapter.py +0 -0
  338. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/providers/codex_cli_adapter.py +0 -0
  339. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/providers/codex_cli_stream.py +0 -0
  340. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/providers/factory.py +0 -0
  341. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/providers/gemini_cli_adapter.py +0 -0
  342. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/providers/litellm_adapter.py +0 -0
  343. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/providers/opencode_adapter.py +0 -0
  344. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/py.typed +0 -0
  345. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/resilience/__init__.py +0 -0
  346. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/resilience/lateral.py +0 -0
  347. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/resilience/stagnation.py +0 -0
  348. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/routing/__init__.py +0 -0
  349. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/routing/complexity.py +0 -0
  350. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/routing/downgrade.py +0 -0
  351. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/routing/escalation.py +0 -0
  352. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/routing/router.py +0 -0
  353. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/routing/tiers.py +0 -0
  354. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/secondary/__init__.py +0 -0
  355. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/secondary/scheduler.py +0 -0
  356. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/secondary/todo_registry.py +0 -0
  357. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/strategies/__init__.py +0 -0
  358. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/strategies/devil_advocate.py +0 -0
  359. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/tui/__init__.py +0 -0
  360. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/tui/app.py +0 -0
  361. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/tui/components/__init__.py +0 -0
  362. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/tui/components/agents_panel.py +0 -0
  363. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/tui/components/event_log.py +0 -0
  364. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/tui/components/progress.py +0 -0
  365. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/tui/components/token_tracker.py +0 -0
  366. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/tui/events.py +0 -0
  367. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/tui/screens/__init__.py +0 -0
  368. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/tui/screens/confirm_rewind.py +0 -0
  369. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/tui/screens/dashboard.py +0 -0
  370. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/tui/screens/dashboard_v2.py +0 -0
  371. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/tui/screens/dashboard_v3.py +0 -0
  372. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/tui/screens/debug.py +0 -0
  373. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/tui/screens/execution.py +0 -0
  374. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/tui/screens/hud_dashboard.py +0 -0
  375. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/tui/screens/lineage_detail.py +0 -0
  376. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/tui/screens/lineage_selector.py +0 -0
  377. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/tui/screens/logs.py +0 -0
  378. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/tui/screens/session_selector.py +0 -0
  379. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/tui/widgets/__init__.py +0 -0
  380. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/tui/widgets/ac_progress.py +0 -0
  381. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/tui/widgets/ac_tree.py +0 -0
  382. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/tui/widgets/agent_activity.py +0 -0
  383. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/tui/widgets/cost_tracker.py +0 -0
  384. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/tui/widgets/drift_meter.py +0 -0
  385. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/tui/widgets/lineage_tree.py +0 -0
  386. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/tui/widgets/parallel_graph.py +0 -0
  387. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/tui/widgets/phase_progress.py +0 -0
  388. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/verification/__init__.py +0 -0
  389. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/verification/extractor.py +0 -0
  390. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/verification/models.py +0 -0
  391. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/src/ouroboros/verification/verifier.py +0 -0
  392. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/__init__.py +0 -0
  393. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/conftest.py +0 -0
  394. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/e2e/__init__.py +0 -0
  395. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/e2e/conftest.py +0 -0
  396. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/e2e/mcp_bridge_test_config.yaml +0 -0
  397. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/e2e/test_cli_commands.py +0 -0
  398. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/e2e/test_full_workflow.py +0 -0
  399. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/e2e/test_session_persistence.py +0 -0
  400. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/fixtures/test_atomicity_seed.yml +0 -0
  401. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/integration/__init__.py +0 -0
  402. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/integration/conftest.py +0 -0
  403. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/integration/mcp/__init__.py +0 -0
  404. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/integration/mcp/bridge/__init__.py +0 -0
  405. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/integration/mcp/bridge/test_bridge_server_to_server.py +0 -0
  406. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/integration/mcp/conftest.py +0 -0
  407. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/integration/mcp/test_client_adapter.py +0 -0
  408. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/integration/mcp/test_client_manager.py +0 -0
  409. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/integration/mcp/test_server_adapter.py +0 -0
  410. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/integration/plugin/test_orchestration.py +0 -0
  411. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/integration/test_codex_cli_passthrough_smoke.py +0 -0
  412. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/integration/test_codex_skill_fallback.py +0 -0
  413. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/integration/test_codex_skill_smoke.py +0 -0
  414. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/integration/test_entry_point.py +0 -0
  415. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/__init__.py +0 -0
  416. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/agents/__init__.py +0 -0
  417. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/agents/test_loader.py +0 -0
  418. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/bigbang/__init__.py +0 -0
  419. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/bigbang/test_ambiguity.py +0 -0
  420. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/bigbang/test_brownfield.py +0 -0
  421. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/bigbang/test_classifier_context.py +0 -0
  422. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/bigbang/test_decide_later_items.py +0 -0
  423. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/bigbang/test_explore.py +0 -0
  424. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/bigbang/test_interview.py +0 -0
  425. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/bigbang/test_interview_async_io.py +0 -0
  426. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/bigbang/test_interview_no_web_search_hint.py +0 -0
  427. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/bigbang/test_interview_research_prefix.py +0 -0
  428. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/bigbang/test_pm_completion.py +0 -0
  429. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/bigbang/test_pm_document_generator.py +0 -0
  430. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/bigbang/test_pm_document_writer.py +0 -0
  431. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/bigbang/test_pm_interview.py +0 -0
  432. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/bigbang/test_pm_interview_brownfield_db.py +0 -0
  433. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/bigbang/test_pm_seed_ac12.py +0 -0
  434. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/bigbang/test_pm_seed_save.py +0 -0
  435. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/bigbang/test_question_classifier.py +0 -0
  436. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/bigbang/test_seed_generator.py +0 -0
  437. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/cli/__init__.py +0 -0
  438. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/cli/commands/test_tui_command.py +0 -0
  439. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/cli/formatters/__init__.py +0 -0
  440. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/cli/formatters/test_console.py +0 -0
  441. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/cli/formatters/test_panels.py +0 -0
  442. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/cli/formatters/test_progress.py +0 -0
  443. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/cli/formatters/test_prompting.py +0 -0
  444. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/cli/formatters/test_tables.py +0 -0
  445. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/cli/formatters/test_workflow_display.py +0 -0
  446. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/cli/test_cancel.py +0 -0
  447. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/cli/test_config.py +0 -0
  448. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/cli/test_init_pm_seed_detection.py +0 -0
  449. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/cli/test_init_runtime.py +0 -0
  450. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/cli/test_jsonc.py +0 -0
  451. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/cli/test_main.py +0 -0
  452. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/cli/test_mcp_nested_guard.py +0 -0
  453. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/cli/test_pm.py +0 -0
  454. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/cli/test_pm_brownfield.py +0 -0
  455. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/cli/test_pm_completion.py +0 -0
  456. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/cli/test_pm_interactive_logging.py +0 -0
  457. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/cli/test_pm_missing_litellm.py +0 -0
  458. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/cli/test_pm_overwrite.py +0 -0
  459. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/cli/test_pm_runtime_adapter.py +0 -0
  460. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/cli/test_pm_select_repos.py +0 -0
  461. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/cli/test_run_qa.py +0 -0
  462. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/cli/test_setup.py +0 -0
  463. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/cli/test_uninstall.py +0 -0
  464. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/config/__init__.py +0 -0
  465. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/config/test_loader.py +0 -0
  466. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/config/test_loader_env.py +0 -0
  467. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/config/test_models.py +0 -0
  468. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/core/__init__.py +0 -0
  469. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/core/test_ac_tree.py +0 -0
  470. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/core/test_context.py +0 -0
  471. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/core/test_errors.py +0 -0
  472. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/core/test_file_lock.py +0 -0
  473. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/core/test_git_workflow.py +0 -0
  474. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/core/test_initial_context.py +0 -0
  475. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/core/test_lineage.py +0 -0
  476. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/core/test_ontology_aspect.py +0 -0
  477. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/core/test_ontology_questions.py +0 -0
  478. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/core/test_retry.py +0 -0
  479. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/core/test_security.py +0 -0
  480. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/core/test_seed.py +0 -0
  481. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/core/test_ttl_cache.py +0 -0
  482. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/core/test_types.py +0 -0
  483. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/core/test_worktree.py +0 -0
  484. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/evaluation/__init__.py +0 -0
  485. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/evaluation/test_artifact_collector_file_prefix.py +0 -0
  486. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/evaluation/test_consensus.py +0 -0
  487. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/evaluation/test_json_utils.py +0 -0
  488. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/evaluation/test_languages.py +0 -0
  489. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/evaluation/test_mechanical.py +0 -0
  490. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/evaluation/test_models.py +0 -0
  491. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/evaluation/test_pipeline_trigger_consensus.py +0 -0
  492. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/evaluation/test_review_fixes.py +0 -0
  493. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/evaluation/test_semantic.py +0 -0
  494. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/evaluation/test_trigger.py +0 -0
  495. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/evaluation/test_trigger_consensus.py +0 -0
  496. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/evaluation/test_verification_artifacts.py +0 -0
  497. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/events/__init__.py +0 -0
  498. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/events/test_base.py +0 -0
  499. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/events/test_decomposition_events.py +0 -0
  500. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/evolution/test_wonder_scope.py +0 -0
  501. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/execution/__init__.py +0 -0
  502. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/execution/test_atomicity.py +0 -0
  503. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/execution/test_decomposition.py +0 -0
  504. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/execution/test_double_diamond.py +0 -0
  505. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/execution/test_subagent_isolation.py +0 -0
  506. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/mcp/__init__.py +0 -0
  507. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/mcp/bridge/__init__.py +0 -0
  508. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/mcp/bridge/test_bridge.py +0 -0
  509. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/mcp/bridge/test_config.py +0 -0
  510. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/mcp/bridge/test_factory.py +0 -0
  511. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/mcp/bridge/test_handler_wiring.py +0 -0
  512. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/mcp/bridge/test_stability.py +0 -0
  513. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/mcp/client/__init__.py +0 -0
  514. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/mcp/client/test_adapter.py +0 -0
  515. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/mcp/client/test_adapter_transport_lifecycle.py +0 -0
  516. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/mcp/client/test_manager.py +0 -0
  517. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/mcp/conftest.py +0 -0
  518. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/mcp/server/__init__.py +0 -0
  519. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/mcp/server/test_adapter.py +0 -0
  520. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/mcp/server/test_security.py +0 -0
  521. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/mcp/test_errors.py +0 -0
  522. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/mcp/test_job_manager.py +0 -0
  523. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/mcp/test_types.py +0 -0
  524. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/mcp/tools/__init__.py +0 -0
  525. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/mcp/tools/conftest.py +0 -0
  526. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/mcp/tools/test_ac_tree_hud_footer.py +0 -0
  527. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/mcp/tools/test_ac_tree_hud_handler.py +0 -0
  528. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/mcp/tools/test_ac_tree_hud_handler_completed.py +0 -0
  529. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/mcp/tools/test_ac_tree_hud_handler_cursor_changed.py +0 -0
  530. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/mcp/tools/test_ac_tree_hud_handler_invalid_session.py +0 -0
  531. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/mcp/tools/test_ac_tree_hud_handler_no_execution.py +0 -0
  532. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/mcp/tools/test_ac_tree_hud_handler_waiting.py +0 -0
  533. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/mcp/tools/test_ac_tree_hud_max_nodes.py +0 -0
  534. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/mcp/tools/test_ac_tree_hud_render_depth2.py +0 -0
  535. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/mcp/tools/test_ac_tree_hud_render_depth3.py +0 -0
  536. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/mcp/tools/test_ac_tree_hud_status_icons.py +0 -0
  537. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/mcp/tools/test_ac_tree_hud_truncation.py +0 -0
  538. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/mcp/tools/test_brownfield_handler.py +0 -0
  539. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/mcp/tools/test_definitions.py +0 -0
  540. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/mcp/tools/test_evaluation_handler.py +0 -0
  541. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/mcp/tools/test_interview_parallel_scoring.py +0 -0
  542. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/mcp/tools/test_interview_scoring_guard.py +0 -0
  543. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/mcp/tools/test_mcp_manager_wiring.py +0 -0
  544. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/mcp/tools/test_pm_handler.py +0 -0
  545. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/mcp/tools/test_pm_handler_generate.py +0 -0
  546. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/mcp/tools/test_pm_handler_pending_reframe.py +0 -0
  547. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/mcp/tools/test_qa_integration.py +0 -0
  548. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/mcp/tools/test_qa_parser.py +0 -0
  549. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/mcp/tools/test_registry.py +0 -0
  550. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/mcp/tools/test_traceback_reporting.py +0 -0
  551. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/observability/__init__.py +0 -0
  552. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/observability/test_drift.py +0 -0
  553. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/observability/test_logging.py +0 -0
  554. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/observability/test_retrospective.py +0 -0
  555. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/orchestrator/__init__.py +0 -0
  556. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/orchestrator/test_adapter.py +0 -0
  557. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/orchestrator/test_capabilities.py +0 -0
  558. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/orchestrator/test_codex_cli_runtime.py +0 -0
  559. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/orchestrator/test_codex_recursion_guard.py +0 -0
  560. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/orchestrator/test_command_dispatcher.py +0 -0
  561. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/orchestrator/test_control_plane.py +0 -0
  562. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/orchestrator/test_coordinator.py +0 -0
  563. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/orchestrator/test_dependency_analyzer.py +0 -0
  564. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/orchestrator/test_events.py +0 -0
  565. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/orchestrator/test_execution_runtime_scope.py +0 -0
  566. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/orchestrator/test_execution_strategy.py +0 -0
  567. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/orchestrator/test_inflight_cancellation.py +0 -0
  568. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/orchestrator/test_level_context.py +0 -0
  569. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/orchestrator/test_mcp_config.py +0 -0
  570. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/orchestrator/test_mcp_tools.py +0 -0
  571. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/orchestrator/test_opencode_runtime.py +0 -0
  572. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/orchestrator/test_parallel_executor.py +0 -0
  573. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/orchestrator/test_parallel_executor_atomic_judgment.py +0 -0
  574. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/orchestrator/test_parallel_executor_recursive_depth.py +0 -0
  575. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/orchestrator/test_parallel_executor_retry_resume.py +0 -0
  576. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/orchestrator/test_policy.py +0 -0
  577. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/orchestrator/test_runner.py +0 -0
  578. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/orchestrator/test_runner_cancellation.py +0 -0
  579. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/orchestrator/test_runtime_factory.py +0 -0
  580. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/orchestrator/test_runtime_message_projection.py +0 -0
  581. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/orchestrator/test_workflow_state.py +0 -0
  582. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/persistence/__init__.py +0 -0
  583. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/persistence/test_brownfield_store.py +0 -0
  584. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/persistence/test_checkpoint.py +0 -0
  585. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/persistence/test_schema.py +0 -0
  586. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/persistence/test_uow.py +0 -0
  587. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/plugin/__init__.py +0 -0
  588. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/plugin/agents/__init__.py +0 -0
  589. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/plugin/agents/test_registry.py +0 -0
  590. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/plugin/orchestration/__init__.py +0 -0
  591. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/plugin/orchestration/test_model_router.py +0 -0
  592. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/plugin/skills/__init__.py +0 -0
  593. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/plugin/skills/test_keywords.py +0 -0
  594. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/plugin/skills/test_registry.py +0 -0
  595. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/pm/__init__.py +0 -0
  596. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/pm/test_renderer.py +0 -0
  597. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/providers/__init__.py +0 -0
  598. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/providers/test_base.py +0 -0
  599. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/providers/test_claude_code_adapter.py +0 -0
  600. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/providers/test_codex_cli_adapter.py +0 -0
  601. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/providers/test_factory.py +0 -0
  602. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/providers/test_gemini_cli_adapter.py +0 -0
  603. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/providers/test_litellm_adapter.py +0 -0
  604. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/providers/test_opencode_adapter.py +0 -0
  605. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/resilience/__init__.py +0 -0
  606. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/resilience/test_lateral.py +0 -0
  607. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/resilience/test_stagnation.py +0 -0
  608. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/routing/__init__.py +0 -0
  609. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/routing/test_complexity.py +0 -0
  610. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/routing/test_downgrade.py +0 -0
  611. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/routing/test_escalation.py +0 -0
  612. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/routing/test_router.py +0 -0
  613. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/routing/test_tiers.py +0 -0
  614. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/scripts/test_keyword_detector.py +0 -0
  615. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/scripts/test_version_check.py +0 -0
  616. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/secondary/__init__.py +0 -0
  617. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/secondary/test_scheduler.py +0 -0
  618. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/secondary/test_todo_registry.py +0 -0
  619. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/test_artifact_collector.py +0 -0
  620. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/test_codex_artifacts.py +0 -0
  621. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/test_convergence.py +0 -0
  622. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/test_dashboard.py +0 -0
  623. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/test_dependencies_configured.py +0 -0
  624. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/test_evolve_rewind.py +0 -0
  625. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/test_evolve_step.py +0 -0
  626. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/test_graceful_shutdown.py +0 -0
  627. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/test_main_entry_point.py +0 -0
  628. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/test_module_structure.py +0 -0
  629. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/test_project_initialization.py +0 -0
  630. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/test_projector_rewind.py +0 -0
  631. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/test_ralph_parser.py +0 -0
  632. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/test_ralph_rewind.py +0 -0
  633. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/test_regression.py +0 -0
  634. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/test_tooling_configuration.py +0 -0
  635. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/test_verification.py +0 -0
  636. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/tui/__init__.py +0 -0
  637. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/tui/test_app.py +0 -0
  638. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/tui/test_cancelled_display.py +0 -0
  639. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/tui/test_events.py +0 -0
  640. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/tui/test_lineage_viewer.py +0 -0
  641. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/tui/test_screens.py +0 -0
  642. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/tui/test_session_selector_replay.py +0 -0
  643. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tests/unit/tui/test_widgets.py +0 -0
  644. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/tools/sync_github_project.py +0 -0
  645. {ouroboros_ai-0.27.3.dev2 → ouroboros_ai-0.27.3.dev3}/uv.lock +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ouroboros-ai
3
- Version: 0.27.3.dev2
3
+ Version: 0.27.3.dev3
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.27.3.dev2'
22
- __version_tuple__ = version_tuple = (0, 27, 3, 'dev2')
21
+ __version__ = version = '0.27.3.dev3'
22
+ __version_tuple__ = version_tuple = (0, 27, 3, 'dev3')
23
23
 
24
24
  __commit_id__ = commit_id = None
@@ -140,22 +140,35 @@ async def _run_mcp_server(
140
140
  else:
141
141
  event_store = EventStore()
142
142
 
143
- # Auto-cancel orphaned sessions on startup.
144
- # Sessions left in RUNNING/PAUSED state for >1 hour are considered orphaned
145
- # (e.g., from a previous crash). Cancel them before accepting new requests.
146
- # NOTE: find_orphaned_sessions now checks for active runtime processes first,
147
- # so sessions with live claude/codex agents won't be cancelled even if stale.
143
+ cleanup_task: asyncio.Task[None] | None = None
144
+
145
+ # Initialize the event store up front because the MCP server uses it for
146
+ # request handling. Orphan cleanup is intentionally deferred into the
147
+ # background so large SQLite histories do not block the initial MCP
148
+ # handshake on startup (#304).
148
149
  try:
149
150
  await event_store.initialize()
150
- repo = SessionRepository(event_store)
151
- cancelled = await repo.cancel_orphaned_sessions()
152
- if cancelled:
153
- _stderr_console.print(
154
- f"[yellow]Auto-cancelled {len(cancelled)} orphaned session(s)[/yellow]"
155
- )
156
151
  except Exception as e:
157
152
  # Auto-cleanup is best-effort — don't prevent server from starting
158
153
  _stderr_console.print(f"[yellow]Warning: auto-cleanup failed: {e}[/yellow]")
154
+ else:
155
+ repo = SessionRepository(event_store)
156
+
157
+ async def _run_startup_cleanup() -> None:
158
+ try:
159
+ cancelled = await repo.cancel_orphaned_sessions()
160
+ if cancelled:
161
+ _stderr_console.print(
162
+ f"[yellow]Auto-cancelled {len(cancelled)} orphaned session(s)[/yellow]"
163
+ )
164
+ except Exception as e:
165
+ # Auto-cleanup is best-effort — don't prevent server startup
166
+ _stderr_console.print(f"[yellow]Warning: auto-cleanup failed: {e}[/yellow]")
167
+
168
+ cleanup_task = asyncio.create_task(
169
+ _run_startup_cleanup(),
170
+ name="ouroboros-mcp-startup-cleanup",
171
+ )
159
172
 
160
173
  # Auto-discover and connect MCP bridge for server-to-server communication
161
174
  from ouroboros.mcp.bridge import create_bridge_from_env
@@ -224,6 +237,12 @@ async def _run_mcp_server(
224
237
  try:
225
238
  await server.serve(transport=transport, host=host, port=port)
226
239
  finally:
240
+ if cleanup_task is not None and not cleanup_task.done():
241
+ cleanup_task.cancel()
242
+ try:
243
+ await cleanup_task
244
+ except asyncio.CancelledError:
245
+ pass
227
246
  _cleanup_pid_file()
228
247
 
229
248
 
@@ -34,7 +34,7 @@ from ouroboros.events.base import BaseEvent, sanitize_event_data_for_persistence
34
34
  from ouroboros.observability.logging import get_logger
35
35
 
36
36
  if TYPE_CHECKING:
37
- from ouroboros.persistence.event_store import EventStore
37
+ from ouroboros.persistence.event_store import EventStore, SessionActivitySnapshot
38
38
 
39
39
  log = get_logger(__name__)
40
40
 
@@ -352,6 +352,70 @@ class SessionRepository:
352
352
 
353
353
  return progress
354
354
 
355
+ @staticmethod
356
+ def _coerce_snapshot_datetime(value: object) -> datetime | None:
357
+ """Normalize timestamp values returned by snapshot queries."""
358
+ if isinstance(value, datetime):
359
+ if value.tzinfo is None:
360
+ return value.replace(tzinfo=UTC)
361
+ return value
362
+ if isinstance(value, str) and value:
363
+ parsed = datetime.fromisoformat(value)
364
+ if parsed.tzinfo is None:
365
+ return parsed.replace(tzinfo=UTC)
366
+ return parsed
367
+ return None
368
+
369
+ @classmethod
370
+ def _status_from_snapshot(cls, snapshot: SessionActivitySnapshot) -> SessionStatus:
371
+ """Derive session status from a snapshot row."""
372
+ status = cls._status_from_event(snapshot.status_event_type, {})
373
+ if status is not None:
374
+ return status
375
+
376
+ runtime_status = cls._coerce_runtime_status(snapshot.runtime_status)
377
+ if runtime_status is not None:
378
+ return runtime_status
379
+
380
+ return SessionStatus.RUNNING
381
+
382
+ async def _find_orphaned_sessions_via_snapshots(
383
+ self,
384
+ snapshots: list[SessionActivitySnapshot],
385
+ alive_sessions: set[str],
386
+ staleness_threshold: timedelta,
387
+ now: datetime,
388
+ ) -> list[SessionTracker]:
389
+ """Detect orphaned sessions from pre-aggregated session snapshots."""
390
+ orphaned: list[SessionTracker] = []
391
+
392
+ for snapshot in snapshots:
393
+ status = self._status_from_snapshot(snapshot)
394
+ if status not in (SessionStatus.RUNNING, SessionStatus.PAUSED):
395
+ continue
396
+
397
+ if snapshot.session_id in alive_sessions:
398
+ log.info(
399
+ "orchestrator.orphan_detection.heartbeat_alive",
400
+ session_id=snapshot.session_id,
401
+ )
402
+ continue
403
+
404
+ last_activity = self._coerce_snapshot_datetime(snapshot.last_activity)
405
+ if last_activity is None:
406
+ last_activity = self._coerce_snapshot_datetime(snapshot.start_time)
407
+ if last_activity is None:
408
+ continue
409
+
410
+ if (now - last_activity) <= staleness_threshold:
411
+ continue
412
+
413
+ result = await self.reconstruct_session(snapshot.session_id)
414
+ if result.is_ok:
415
+ orphaned.append(result.value)
416
+
417
+ return orphaned
418
+
355
419
  @staticmethod
356
420
  def _merge_event_streams(
357
421
  primary_events: list[BaseEvent],
@@ -892,6 +956,24 @@ class SessionRepository:
892
956
  orphaned: list[SessionTracker] = []
893
957
 
894
958
  try:
959
+ get_snapshots = getattr(self._event_store, "get_session_activity_snapshots", None)
960
+ if callable(get_snapshots):
961
+ snapshots = await get_snapshots()
962
+ if isinstance(snapshots, list):
963
+ orphaned = await self._find_orphaned_sessions_via_snapshots(
964
+ snapshots,
965
+ alive_sessions,
966
+ staleness_threshold,
967
+ now,
968
+ )
969
+ log.info(
970
+ "orchestrator.orphan_detection.complete",
971
+ total_sessions=len(snapshots),
972
+ orphaned_count=len(orphaned),
973
+ strategy="snapshot",
974
+ )
975
+ return orphaned
976
+
895
977
  # Get all session start events to enumerate sessions
896
978
  start_events = await self._event_store.get_all_sessions()
897
979
 
@@ -955,6 +1037,7 @@ class SessionRepository:
955
1037
  "orchestrator.orphan_detection.complete",
956
1038
  total_sessions=len(start_events),
957
1039
  orphaned_count=len(orphaned),
1040
+ strategy="replay",
958
1041
  )
959
1042
 
960
1043
  except Exception as e:
@@ -4,12 +4,15 @@ Provides async methods for appending and replaying events using SQLAlchemy Core
4
4
  with aiosqlite backend.
5
5
  """
6
6
 
7
+ from __future__ import annotations
8
+
7
9
  import asyncio
8
10
  from collections.abc import Mapping
11
+ from dataclasses import dataclass
9
12
  import logging
10
13
  from pathlib import Path
11
14
 
12
- from sqlalchemy import event, or_, select, text
15
+ from sqlalchemy import and_, event, func, or_, select, text
13
16
  from sqlalchemy.ext.asyncio import AsyncEngine, create_async_engine
14
17
 
15
18
  from ouroboros.core.errors import PersistenceError
@@ -439,6 +442,147 @@ class EventStore:
439
442
  details={"event_type": "orchestrator.session.%"},
440
443
  ) from e
441
444
 
445
+ async def get_session_activity_snapshots(self) -> list[SessionActivitySnapshot]:
446
+ """Return one session snapshot row per session aggregate.
447
+
448
+ The snapshot includes session identity from the start event, the most
449
+ recent session activity timestamp, and the latest status-bearing event
450
+ or runtime_status payload when present. This avoids replaying every
451
+ event for every session just to detect stale active sessions.
452
+ """
453
+ if self._engine is None:
454
+ raise PersistenceError(
455
+ "EventStore not initialized. Call initialize() first.",
456
+ operation="get_session_activity_snapshots",
457
+ )
458
+
459
+ status_expr = func.coalesce(
460
+ func.json_extract(events_table.c.payload, "$.progress.runtime_status"),
461
+ func.json_extract(events_table.c.payload, "$.runtime_status"),
462
+ )
463
+
464
+ started_ranked = (
465
+ select(
466
+ events_table.c.aggregate_id.label("session_id"),
467
+ func.json_extract(events_table.c.payload, "$.execution_id").label("execution_id"),
468
+ func.json_extract(events_table.c.payload, "$.seed_id").label("seed_id"),
469
+ func.json_extract(events_table.c.payload, "$.start_time").label("start_time"),
470
+ func.row_number()
471
+ .over(
472
+ partition_by=events_table.c.aggregate_id,
473
+ order_by=(events_table.c.timestamp.asc(), events_table.c.id.asc()),
474
+ )
475
+ .label("rn"),
476
+ )
477
+ .where(events_table.c.aggregate_type == "session")
478
+ .where(events_table.c.event_type == "orchestrator.session.started")
479
+ .subquery()
480
+ )
481
+
482
+ latest_activity_ranked = (
483
+ select(
484
+ events_table.c.aggregate_id.label("session_id"),
485
+ events_table.c.timestamp.label("last_activity"),
486
+ func.row_number()
487
+ .over(
488
+ partition_by=events_table.c.aggregate_id,
489
+ order_by=(events_table.c.timestamp.desc(), events_table.c.id.desc()),
490
+ )
491
+ .label("rn"),
492
+ )
493
+ .where(events_table.c.aggregate_type == "session")
494
+ .subquery()
495
+ )
496
+
497
+ latest_status_ranked = (
498
+ select(
499
+ events_table.c.aggregate_id.label("session_id"),
500
+ events_table.c.event_type.label("status_event_type"),
501
+ status_expr.label("runtime_status"),
502
+ func.row_number()
503
+ .over(
504
+ partition_by=events_table.c.aggregate_id,
505
+ order_by=(events_table.c.timestamp.desc(), events_table.c.id.desc()),
506
+ )
507
+ .label("rn"),
508
+ )
509
+ .where(events_table.c.aggregate_type == "session")
510
+ .where(
511
+ or_(
512
+ events_table.c.event_type.in_(
513
+ (
514
+ "orchestrator.session.completed",
515
+ "orchestrator.session.failed",
516
+ "orchestrator.session.paused",
517
+ "orchestrator.session.cancelled",
518
+ )
519
+ ),
520
+ and_(
521
+ events_table.c.event_type.in_(
522
+ (
523
+ "orchestrator.progress.updated",
524
+ "workflow.progress.updated",
525
+ )
526
+ ),
527
+ status_expr.is_not(None),
528
+ ),
529
+ )
530
+ )
531
+ .subquery()
532
+ )
533
+
534
+ try:
535
+ async with self._engine.begin() as conn:
536
+ query = (
537
+ select(
538
+ started_ranked.c.session_id,
539
+ started_ranked.c.execution_id,
540
+ started_ranked.c.seed_id,
541
+ started_ranked.c.start_time,
542
+ latest_activity_ranked.c.last_activity,
543
+ latest_status_ranked.c.status_event_type,
544
+ latest_status_ranked.c.runtime_status,
545
+ )
546
+ .select_from(started_ranked)
547
+ .join(
548
+ latest_activity_ranked,
549
+ and_(
550
+ latest_activity_ranked.c.session_id == started_ranked.c.session_id,
551
+ latest_activity_ranked.c.rn == 1,
552
+ ),
553
+ )
554
+ .outerjoin(
555
+ latest_status_ranked,
556
+ and_(
557
+ latest_status_ranked.c.session_id == started_ranked.c.session_id,
558
+ latest_status_ranked.c.rn == 1,
559
+ ),
560
+ )
561
+ .where(started_ranked.c.rn == 1)
562
+ .order_by(started_ranked.c.session_id.asc())
563
+ )
564
+
565
+ result = await conn.execute(query)
566
+ rows = result.mappings().all()
567
+ return [
568
+ SessionActivitySnapshot(
569
+ session_id=row["session_id"],
570
+ execution_id=row.get("execution_id"),
571
+ seed_id=row.get("seed_id"),
572
+ start_time=row.get("start_time"),
573
+ last_activity=row.get("last_activity"),
574
+ status_event_type=row.get("status_event_type"),
575
+ runtime_status=row.get("runtime_status"),
576
+ )
577
+ for row in rows
578
+ ]
579
+ except Exception as e:
580
+ raise PersistenceError(
581
+ f"Failed to fetch session activity snapshots: {e}",
582
+ operation="select",
583
+ table="events",
584
+ ) from e
585
+
442
586
  async def query_events(
443
587
  self,
444
588
  aggregate_id: str | None = None,
@@ -666,3 +810,16 @@ class EventStore:
666
810
  if self._engine is not None:
667
811
  await self._engine.dispose()
668
812
  self._engine = None
813
+
814
+
815
+ @dataclass(frozen=True, slots=True)
816
+ class SessionActivitySnapshot:
817
+ """Session start/activity/status summary used by orphan detection."""
818
+
819
+ session_id: str
820
+ execution_id: str | None
821
+ seed_id: str | None
822
+ start_time: str | None
823
+ last_activity: object
824
+ status_event_type: str | None
825
+ runtime_status: str | None
@@ -10,6 +10,7 @@ MCP server startup in _run_mcp_server(), ensuring:
10
10
 
11
11
  from __future__ import annotations
12
12
 
13
+ import asyncio
13
14
  from datetime import UTC, datetime, timedelta
14
15
  from unittest.mock import AsyncMock, MagicMock, patch
15
16
 
@@ -77,6 +78,11 @@ class TestMCPStartupAutoCleanup:
77
78
  """Test that startup with no orphaned sessions skips cancellation."""
78
79
  mock_es, mock_repo, mock_server = self._create_patches(cancelled_sessions=[])
79
80
 
81
+ async def serve_side_effect(*args, **kwargs) -> None:
82
+ await asyncio.sleep(0)
83
+
84
+ mock_server.serve.side_effect = serve_side_effect
85
+
80
86
  with (
81
87
  patch(
82
88
  "ouroboros.persistence.event_store.EventStore",
@@ -96,8 +102,53 @@ class TestMCPStartupAutoCleanup:
96
102
  await _run_mcp_server("localhost", 8080, "stdio")
97
103
 
98
104
  mock_repo.cancel_orphaned_sessions.assert_called_once()
105
+ mock_es.initialize.assert_awaited_once()
99
106
  mock_server.serve.assert_called_once()
100
107
 
108
+ @pytest.mark.asyncio
109
+ async def test_startup_does_not_wait_for_background_cleanup(self) -> None:
110
+ """Server startup should not wait for orphan cleanup to finish."""
111
+ cleanup_started = asyncio.Event()
112
+ allow_cleanup_finish = asyncio.Event()
113
+ serve_started = asyncio.Event()
114
+
115
+ mock_es = AsyncMock()
116
+ mock_es.initialize = AsyncMock()
117
+ mock_repo = AsyncMock()
118
+
119
+ async def slow_cleanup() -> list:
120
+ cleanup_started.set()
121
+ await allow_cleanup_finish.wait()
122
+ return []
123
+
124
+ mock_repo.cancel_orphaned_sessions = AsyncMock(side_effect=slow_cleanup)
125
+
126
+ mock_server = MagicMock()
127
+ mock_server.info.tools = []
128
+
129
+ async def serve_side_effect(*args, **kwargs) -> None:
130
+ serve_started.set()
131
+ allow_cleanup_finish.set()
132
+ await asyncio.sleep(0)
133
+
134
+ mock_server.serve = AsyncMock(side_effect=serve_side_effect)
135
+
136
+ with (
137
+ patch("ouroboros.persistence.event_store.EventStore", return_value=mock_es),
138
+ patch("ouroboros.orchestrator.session.SessionRepository", return_value=mock_repo),
139
+ patch(
140
+ "ouroboros.mcp.server.adapter.create_ouroboros_server",
141
+ return_value=mock_server,
142
+ ),
143
+ ):
144
+ from ouroboros.cli.commands.mcp import _run_mcp_server
145
+
146
+ await _run_mcp_server("localhost", 8080, "stdio")
147
+
148
+ assert cleanup_started.is_set()
149
+ assert serve_started.is_set()
150
+ mock_server.serve.assert_awaited_once()
151
+
101
152
  @pytest.mark.asyncio
102
153
  async def test_orphans_detected_and_cancelled(self) -> None:
103
154
  """Test that orphaned sessions are cancelled on startup."""
@@ -131,6 +182,12 @@ class TestMCPStartupAutoCleanup:
131
182
  ),
132
183
  patch("ouroboros.cli.commands.mcp._stderr_console") as mock_console,
133
184
  ):
185
+
186
+ async def serve_side_effect(*args, **kwargs) -> None:
187
+ await asyncio.sleep(0)
188
+
189
+ mock_server.serve.side_effect = serve_side_effect
190
+
134
191
  from ouroboros.cli.commands.mcp import _run_mcp_server
135
192
 
136
193
  await _run_mcp_server("localhost", 8080, "stdio")
@@ -139,6 +196,50 @@ class TestMCPStartupAutoCleanup:
139
196
  mock_console.print.assert_any_call("[yellow]Auto-cancelled 2 orphaned session(s)[/yellow]")
140
197
  mock_server.serve.assert_called_once()
141
198
 
199
+ @pytest.mark.asyncio
200
+ async def test_pending_background_cleanup_is_cancelled_on_shutdown(self) -> None:
201
+ """Server shutdown should cancel an unfinished startup cleanup task."""
202
+ cleanup_started = asyncio.Event()
203
+ cleanup_cancelled = asyncio.Event()
204
+
205
+ mock_es = AsyncMock()
206
+ mock_es.initialize = AsyncMock()
207
+ mock_repo = AsyncMock()
208
+
209
+ async def slow_cleanup() -> list:
210
+ cleanup_started.set()
211
+ try:
212
+ await asyncio.Event().wait()
213
+ except asyncio.CancelledError:
214
+ cleanup_cancelled.set()
215
+ raise
216
+
217
+ mock_repo.cancel_orphaned_sessions = AsyncMock(side_effect=slow_cleanup)
218
+
219
+ mock_server = MagicMock()
220
+ mock_server.info.tools = []
221
+
222
+ async def serve_side_effect(*args, **kwargs) -> None:
223
+ await cleanup_started.wait()
224
+
225
+ mock_server.serve = AsyncMock(side_effect=serve_side_effect)
226
+
227
+ with (
228
+ patch("ouroboros.persistence.event_store.EventStore", return_value=mock_es),
229
+ patch("ouroboros.orchestrator.session.SessionRepository", return_value=mock_repo),
230
+ patch(
231
+ "ouroboros.mcp.server.adapter.create_ouroboros_server",
232
+ return_value=mock_server,
233
+ ),
234
+ ):
235
+ from ouroboros.cli.commands.mcp import _run_mcp_server
236
+
237
+ await _run_mcp_server("localhost", 8080, "stdio")
238
+
239
+ assert cleanup_started.is_set()
240
+ assert cleanup_cancelled.is_set()
241
+ mock_server.serve.assert_awaited_once()
242
+
142
243
  @pytest.mark.asyncio
143
244
  async def test_cleanup_failure_does_not_prevent_startup(self) -> None:
144
245
  """Test that auto-cleanup failure doesn't block server startup."""
@@ -156,6 +257,12 @@ class TestMCPStartupAutoCleanup:
156
257
  ),
157
258
  patch("ouroboros.cli.commands.mcp._stderr_console") as mock_console,
158
259
  ):
260
+
261
+ async def serve_side_effect(*args, **kwargs) -> None:
262
+ await asyncio.sleep(0)
263
+
264
+ mock_server.serve.side_effect = serve_side_effect
265
+
159
266
  from ouroboros.cli.commands.mcp import _run_mcp_server
160
267
 
161
268
  await _run_mcp_server("localhost", 8080, "stdio")
@@ -186,6 +293,12 @@ class TestMCPStartupAutoCleanup:
186
293
  ),
187
294
  patch("ouroboros.cli.commands.mcp._stderr_console") as mock_console,
188
295
  ):
296
+
297
+ async def serve_side_effect(*args, **kwargs) -> None:
298
+ await asyncio.sleep(0)
299
+
300
+ mock_server.serve.side_effect = serve_side_effect
301
+
189
302
  from ouroboros.cli.commands.mcp import _run_mcp_server
190
303
 
191
304
  await _run_mcp_server("localhost", 8080, "stdio")
@@ -216,7 +329,11 @@ class TestMCPStartupAutoCleanup:
216
329
 
217
330
  mock_server = MagicMock()
218
331
  mock_server.info.tools = []
219
- mock_server.serve = AsyncMock()
332
+
333
+ async def serve_side_effect(*args, **kwargs) -> None:
334
+ await asyncio.sleep(0)
335
+
336
+ mock_server.serve = AsyncMock(side_effect=serve_side_effect)
220
337
 
221
338
  with (
222
339
  patch(
@@ -236,7 +353,7 @@ class TestMCPStartupAutoCleanup:
236
353
 
237
354
  await _run_mcp_server("localhost", 8080, "stdio")
238
355
 
239
- assert call_order == ["initialize", "cancel_orphaned"]
356
+ assert call_order[:2] == ["initialize", "cancel_orphaned"]
240
357
 
241
358
  @pytest.mark.asyncio
242
359
  async def test_runtime_backend_is_forwarded_to_server_factory(self) -> None:
@@ -332,6 +449,11 @@ class TestMCPStartupAutoCleanup:
332
449
 
333
450
  mock_es, mock_repo, mock_server = self._create_patches(cancelled_sessions=single_orphan)
334
451
 
452
+ async def serve_side_effect(*args, **kwargs) -> None:
453
+ await asyncio.sleep(0)
454
+
455
+ mock_server.serve.side_effect = serve_side_effect
456
+
335
457
  with (
336
458
  patch(
337
459
  "ouroboros.persistence.event_store.EventStore",
@@ -1085,6 +1085,39 @@ class TestFindOrphanedSessions:
1085
1085
 
1086
1086
  assert result == []
1087
1087
 
1088
+ @pytest.mark.asyncio
1089
+ async def test_prefers_snapshot_query_over_full_replay(
1090
+ self,
1091
+ repository: SessionRepository,
1092
+ mock_event_store: AsyncMock,
1093
+ ) -> None:
1094
+ """Snapshot query should avoid session-by-session replay on large stores."""
1095
+ from ouroboros.persistence.event_store import SessionActivitySnapshot
1096
+
1097
+ old_time = datetime.now(UTC) - timedelta(hours=2)
1098
+ mock_event_store.get_session_activity_snapshots = AsyncMock(
1099
+ return_value=[
1100
+ SessionActivitySnapshot(
1101
+ session_id="sess_1",
1102
+ execution_id="exec_sess_1",
1103
+ seed_id="seed_sess_1",
1104
+ start_time=old_time.isoformat(),
1105
+ last_activity=old_time,
1106
+ status_event_type=None,
1107
+ runtime_status=None,
1108
+ )
1109
+ ]
1110
+ )
1111
+
1112
+ start_event = self._make_start_event("sess_1", timestamp=old_time)
1113
+ mock_event_store.replay.return_value = [start_event]
1114
+
1115
+ result = await repository.find_orphaned_sessions()
1116
+
1117
+ assert len(result) == 1
1118
+ mock_event_store.get_session_activity_snapshots.assert_awaited_once()
1119
+ mock_event_store.get_all_sessions.assert_not_called()
1120
+
1088
1121
  @pytest.mark.asyncio
1089
1122
  async def test_failed_session_not_orphaned(
1090
1123
  self,
@@ -553,6 +553,64 @@ class TestEventStoreErrorHandling:
553
553
  await store.replay("test", "test-123")
554
554
 
555
555
 
556
+ class TestSessionActivitySnapshots:
557
+ """Test aggregated session snapshot queries for orphan detection."""
558
+
559
+ async def test_returns_latest_status_and_activity(self, event_store: EventStore) -> None:
560
+ await event_store.append(
561
+ BaseEvent(
562
+ type="orchestrator.session.started",
563
+ aggregate_type="session",
564
+ aggregate_id="sess-running",
565
+ data={
566
+ "execution_id": "exec-running",
567
+ "seed_id": "seed-running",
568
+ "start_time": "2026-04-01T00:00:00+00:00",
569
+ },
570
+ )
571
+ )
572
+ await event_store.append(
573
+ BaseEvent(
574
+ type="orchestrator.progress.updated",
575
+ aggregate_type="session",
576
+ aggregate_id="sess-running",
577
+ data={"progress": {"step": 2}},
578
+ )
579
+ )
580
+ await event_store.append(
581
+ BaseEvent(
582
+ type="orchestrator.session.started",
583
+ aggregate_type="session",
584
+ aggregate_id="sess-completed",
585
+ data={
586
+ "execution_id": "exec-completed",
587
+ "seed_id": "seed-completed",
588
+ "start_time": "2026-04-01T01:00:00+00:00",
589
+ },
590
+ )
591
+ )
592
+ await event_store.append(
593
+ BaseEvent(
594
+ type="orchestrator.progress.updated",
595
+ aggregate_type="session",
596
+ aggregate_id="sess-completed",
597
+ data={"progress": {"runtime_status": "completed"}},
598
+ )
599
+ )
600
+
601
+ snapshots = await event_store.get_session_activity_snapshots()
602
+ by_id = {snapshot.session_id: snapshot for snapshot in snapshots}
603
+
604
+ assert set(by_id) == {"sess-running", "sess-completed"}
605
+ assert by_id["sess-running"].execution_id == "exec-running"
606
+ assert by_id["sess-running"].seed_id == "seed-running"
607
+ assert by_id["sess-running"].status_event_type is None
608
+ assert by_id["sess-running"].runtime_status is None
609
+ assert by_id["sess-running"].last_activity is not None
610
+ assert by_id["sess-completed"].status_event_type == "orchestrator.progress.updated"
611
+ assert by_id["sess-completed"].runtime_status == "completed"
612
+
613
+
556
614
  class TestGetAllSessions:
557
615
  """Test get_all_sessions returns all session lifecycle events."""
558
616