ouroboros-ai 0.2.2__tar.gz → 0.2.3__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of ouroboros-ai might be problematic. Click here for more details.
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/PKG-INFO +1 -1
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/pyproject.toml +1 -1
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/src/ouroboros/bigbang/ambiguity.py +39 -62
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/tests/unit/bigbang/test_ambiguity.py +23 -29
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/uv.lock +1 -1
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/.gitignore +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/.pre-commit-config.yaml +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/.python-version +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/CHANGELOG.md +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/LICENSE +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/PR-43-CODE-REVIEW-REPORT.md +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/README.md +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/_bmad-output/implementation-artifacts/github-issue-mapping.yaml +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/_bmad-output/implementation-artifacts/sprint-status.yaml +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/_bmad-output/implementation-artifacts/stories/0-1-project-initialization-with-uv.md +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/_bmad-output/implementation-artifacts/stories/0-2-core-types-and-error-handling.md +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/_bmad-output/implementation-artifacts/stories/0-3-event-store-with-sqlalchemy-core.md +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/_bmad-output/implementation-artifacts/stories/0-4-configuration-and-credentials-management.md +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/_bmad-output/implementation-artifacts/stories/0-5-llm-provider-adapter-with-litellm.md +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/_bmad-output/implementation-artifacts/stories/0-6-cli-skeleton-with-typer-and-rich.md +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/_bmad-output/implementation-artifacts/stories/0-7-structured-logging-with-structlog.md +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/_bmad-output/implementation-artifacts/stories/0-8-checkpoint-and-recovery-system.md +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/_bmad-output/implementation-artifacts/stories/0-9-context-compression-engine.md +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/_bmad-output/implementation-artifacts/stories/1-1-interview-protocol-engine.md +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/_bmad-output/implementation-artifacts/stories/1-2-ambiguity-score-calculation.md +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/_bmad-output/implementation-artifacts/stories/1-3-immutable-seed-generation.md +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/_bmad-output/implementation-artifacts/stories/2-1-three-tier-model-configuration.md +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/_bmad-output/implementation-artifacts/stories/2-2-complexity-based-routing.md +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/_bmad-output/implementation-artifacts/stories/2-3-escalation-on-failure.md +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/_bmad-output/implementation-artifacts/stories/2-4-downgrade-on-success.md +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/_bmad-output/implementation-artifacts/stories/3-1-double-diamond-cycle-implementation.md +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/_bmad-output/implementation-artifacts/stories/3-2-hierarchical-ac-decomposition.md +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/_bmad-output/implementation-artifacts/stories/3-3-atomicity-detection.md +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/_bmad-output/implementation-artifacts/stories/3-4-subagent-isolation.md +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/_bmad-output/implementation-artifacts/stories/4-1-stagnation-detection-4-patterns.md +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/_bmad-output/implementation-artifacts/stories/4-2-lateral-thinking-personas.md +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/_bmad-output/implementation-artifacts/stories/4-3-persona-rotation-strategy.md +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/_bmad-output/implementation-artifacts/stories/5-1-stage-1-mechanical-verification.md +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/_bmad-output/implementation-artifacts/stories/5-2-stage-2-semantic-evaluation.md +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/_bmad-output/implementation-artifacts/stories/5-3-stage-3-multi-model-consensus.md +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/_bmad-output/implementation-artifacts/stories/5-4-consensus-trigger-matrix.md +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/_bmad-output/implementation-artifacts/stories/6-1-drift-measurement-engine.md +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/_bmad-output/implementation-artifacts/stories/6-2-automatic-retrospective.md +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/_bmad-output/implementation-artifacts/stories/7-1-todo-registry.md +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/_bmad-output/implementation-artifacts/stories/7-2-secondary-loop-batch-processing.md +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/_bmad-output/planning-artifacts/architecture.md +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/_bmad-output/planning-artifacts/bmm-workflow-status.yaml +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/_bmad-output/planning-artifacts/epics.md +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/_bmad-output/update-stories.sh +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/docs/running-with-claude-code.md +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/project-context.md +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/requirement/1_EXECUTIVE_SUMMARY.md +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/requirement/2_FULL_SPECIFICATION.md +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/requirement/3_CONFIG_TEMPLATE.yaml +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/requirement/4_REDDIT_EXAMPLE.md +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/src/ouroboros/__init__.py +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/src/ouroboros/__main__.py +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/src/ouroboros/bigbang/__init__.py +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/src/ouroboros/bigbang/interview.py +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/src/ouroboros/bigbang/seed_generator.py +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/src/ouroboros/cli/__init__.py +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/src/ouroboros/cli/commands/__init__.py +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/src/ouroboros/cli/commands/config.py +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/src/ouroboros/cli/commands/init.py +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/src/ouroboros/cli/commands/run.py +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/src/ouroboros/cli/commands/status.py +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/src/ouroboros/cli/formatters/__init__.py +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/src/ouroboros/cli/formatters/panels.py +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/src/ouroboros/cli/formatters/progress.py +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/src/ouroboros/cli/formatters/tables.py +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/src/ouroboros/cli/main.py +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/src/ouroboros/config/__init__.py +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/src/ouroboros/config/loader.py +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/src/ouroboros/config/models.py +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/src/ouroboros/core/__init__.py +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/src/ouroboros/core/ac_tree.py +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/src/ouroboros/core/context.py +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/src/ouroboros/core/errors.py +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/src/ouroboros/core/security.py +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/src/ouroboros/core/seed.py +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/src/ouroboros/core/types.py +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/src/ouroboros/evaluation/__init__.py +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/src/ouroboros/evaluation/consensus.py +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/src/ouroboros/evaluation/mechanical.py +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/src/ouroboros/evaluation/models.py +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/src/ouroboros/evaluation/pipeline.py +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/src/ouroboros/evaluation/semantic.py +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/src/ouroboros/evaluation/trigger.py +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/src/ouroboros/events/__init__.py +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/src/ouroboros/events/base.py +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/src/ouroboros/events/decomposition.py +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/src/ouroboros/events/evaluation.py +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/src/ouroboros/execution/__init__.py +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/src/ouroboros/execution/atomicity.py +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/src/ouroboros/execution/decomposition.py +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/src/ouroboros/execution/double_diamond.py +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/src/ouroboros/execution/subagent.py +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/src/ouroboros/observability/__init__.py +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/src/ouroboros/observability/drift.py +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/src/ouroboros/observability/logging.py +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/src/ouroboros/observability/retrospective.py +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/src/ouroboros/orchestrator/__init__.py +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/src/ouroboros/orchestrator/adapter.py +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/src/ouroboros/orchestrator/events.py +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/src/ouroboros/orchestrator/runner.py +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/src/ouroboros/orchestrator/session.py +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/src/ouroboros/persistence/__init__.py +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/src/ouroboros/persistence/checkpoint.py +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/src/ouroboros/persistence/event_store.py +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/src/ouroboros/persistence/migrations/__init__.py +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/src/ouroboros/persistence/migrations/runner.py +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/src/ouroboros/persistence/migrations/scripts/001_initial.sql +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/src/ouroboros/persistence/schema.py +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/src/ouroboros/persistence/uow.py +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/src/ouroboros/providers/__init__.py +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/src/ouroboros/providers/base.py +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/src/ouroboros/providers/claude_code_adapter.py +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/src/ouroboros/providers/litellm_adapter.py +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/src/ouroboros/py.typed +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/src/ouroboros/resilience/__init__.py +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/src/ouroboros/resilience/lateral.py +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/src/ouroboros/resilience/stagnation.py +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/src/ouroboros/routing/__init__.py +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/src/ouroboros/routing/complexity.py +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/src/ouroboros/routing/downgrade.py +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/src/ouroboros/routing/escalation.py +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/src/ouroboros/routing/router.py +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/src/ouroboros/routing/tiers.py +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/src/ouroboros/secondary/__init__.py +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/src/ouroboros/secondary/scheduler.py +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/src/ouroboros/secondary/todo_registry.py +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/tests/conftest.py +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/tests/integration/test_entry_point.py +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/tests/unit/bigbang/__init__.py +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/tests/unit/bigbang/test_interview.py +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/tests/unit/bigbang/test_seed_generator.py +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/tests/unit/cli/__init__.py +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/tests/unit/cli/formatters/__init__.py +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/tests/unit/cli/formatters/test_console.py +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/tests/unit/cli/formatters/test_panels.py +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/tests/unit/cli/formatters/test_progress.py +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/tests/unit/cli/formatters/test_tables.py +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/tests/unit/cli/test_main.py +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/tests/unit/config/__init__.py +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/tests/unit/config/test_loader.py +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/tests/unit/config/test_models.py +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/tests/unit/core/__init__.py +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/tests/unit/core/test_ac_tree.py +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/tests/unit/core/test_context.py +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/tests/unit/core/test_errors.py +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/tests/unit/core/test_security.py +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/tests/unit/core/test_seed.py +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/tests/unit/core/test_types.py +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/tests/unit/evaluation/__init__.py +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/tests/unit/evaluation/test_consensus.py +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/tests/unit/evaluation/test_mechanical.py +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/tests/unit/evaluation/test_models.py +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/tests/unit/evaluation/test_semantic.py +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/tests/unit/evaluation/test_trigger.py +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/tests/unit/events/__init__.py +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/tests/unit/events/test_base.py +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/tests/unit/events/test_decomposition_events.py +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/tests/unit/execution/__init__.py +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/tests/unit/execution/test_atomicity.py +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/tests/unit/execution/test_decomposition.py +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/tests/unit/execution/test_double_diamond.py +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/tests/unit/execution/test_subagent_isolation.py +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/tests/unit/observability/__init__.py +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/tests/unit/observability/test_drift.py +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/tests/unit/observability/test_logging.py +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/tests/unit/observability/test_retrospective.py +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/tests/unit/orchestrator/__init__.py +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/tests/unit/orchestrator/test_adapter.py +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/tests/unit/orchestrator/test_events.py +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/tests/unit/orchestrator/test_runner.py +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/tests/unit/orchestrator/test_session.py +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/tests/unit/persistence/__init__.py +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/tests/unit/persistence/test_checkpoint.py +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/tests/unit/persistence/test_event_store.py +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/tests/unit/persistence/test_schema.py +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/tests/unit/persistence/test_uow.py +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/tests/unit/providers/__init__.py +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/tests/unit/providers/test_base.py +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/tests/unit/providers/test_litellm_adapter.py +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/tests/unit/resilience/__init__.py +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/tests/unit/resilience/test_lateral.py +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/tests/unit/resilience/test_stagnation.py +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/tests/unit/routing/__init__.py +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/tests/unit/routing/test_complexity.py +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/tests/unit/routing/test_downgrade.py +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/tests/unit/routing/test_escalation.py +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/tests/unit/routing/test_router.py +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/tests/unit/routing/test_tiers.py +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/tests/unit/secondary/__init__.py +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/tests/unit/secondary/test_scheduler.py +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/tests/unit/secondary/test_todo_registry.py +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/tests/unit/test_dependencies_configured.py +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/tests/unit/test_main_entry_point.py +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/tests/unit/test_module_structure.py +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/tests/unit/test_project_initialization.py +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/tests/unit/test_tooling_configuration.py +0 -0
- {ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/tools/sync_github_project.py +0 -0
|
@@ -9,6 +9,8 @@ The scoring algorithm evaluates three key components:
|
|
|
9
9
|
- Success Criteria Clarity (30%): How measurable the success criteria are
|
|
10
10
|
"""
|
|
11
11
|
|
|
12
|
+
import json
|
|
13
|
+
import re
|
|
12
14
|
from dataclasses import dataclass
|
|
13
15
|
from typing import Any
|
|
14
16
|
|
|
@@ -139,6 +141,7 @@ class AmbiguityScorer:
|
|
|
139
141
|
temperature: float = SCORING_TEMPERATURE
|
|
140
142
|
initial_max_tokens: int = 2048
|
|
141
143
|
max_retries: int | None = None # None = unlimited retries
|
|
144
|
+
max_format_error_retries: int = 5 # Stop after N format errors (non-truncation)
|
|
142
145
|
|
|
143
146
|
async def score(
|
|
144
147
|
self, state: InterviewState
|
|
@@ -303,38 +306,19 @@ class AmbiguityScorer:
|
|
|
303
306
|
Returns:
|
|
304
307
|
System prompt string.
|
|
305
308
|
"""
|
|
306
|
-
return """You are an expert requirements analyst
|
|
307
|
-
|
|
308
|
-
Your task is to assess how clear and unambiguous the requirements are based on an interview conversation.
|
|
309
|
+
return """You are an expert requirements analyst. Evaluate the clarity of software requirements.
|
|
309
310
|
|
|
310
311
|
Evaluate three components:
|
|
311
|
-
1. Goal Clarity (40%
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
2. Constraint Clarity (30% weight): Are constraints and limitations specified?
|
|
316
|
-
- Clear: "Must use Python 3.14+, no external database dependencies"
|
|
317
|
-
- Unclear: No mention of technical constraints or limitations
|
|
318
|
-
|
|
319
|
-
3. Success Criteria Clarity (30% weight): Are success criteria measurable?
|
|
320
|
-
- Clear: "Tasks can be created, edited, deleted; supports filtering by status"
|
|
321
|
-
- Unclear: "The tool should be easy to use"
|
|
322
|
-
|
|
323
|
-
For each component, provide:
|
|
324
|
-
- A clarity score between 0.0 (completely unclear) and 1.0 (perfectly clear)
|
|
325
|
-
- A brief justification (1-2 sentences max) explaining the score
|
|
312
|
+
1. Goal Clarity (40%): Is the goal specific and well-defined?
|
|
313
|
+
2. Constraint Clarity (30%): Are constraints and limitations specified?
|
|
314
|
+
3. Success Criteria Clarity (30%): Are success criteria measurable?
|
|
326
315
|
|
|
327
|
-
|
|
316
|
+
Score each from 0.0 (unclear) to 1.0 (perfectly clear). Scores above 0.8 require very specific requirements.
|
|
328
317
|
|
|
329
|
-
|
|
330
|
-
GOAL_CLARITY_SCORE: <score>
|
|
331
|
-
GOAL_CLARITY_JUSTIFICATION: <justification in 1-2 sentences>
|
|
332
|
-
CONSTRAINT_CLARITY_SCORE: <score>
|
|
333
|
-
CONSTRAINT_CLARITY_JUSTIFICATION: <justification in 1-2 sentences>
|
|
334
|
-
SUCCESS_CRITERIA_CLARITY_SCORE: <score>
|
|
335
|
-
SUCCESS_CRITERIA_CLARITY_JUSTIFICATION: <justification in 1-2 sentences>
|
|
318
|
+
RESPOND ONLY WITH VALID JSON. No other text before or after.
|
|
336
319
|
|
|
337
|
-
|
|
320
|
+
Required JSON format:
|
|
321
|
+
{"goal_clarity_score": 0.0, "goal_clarity_justification": "string", "constraint_clarity_score": 0.0, "constraint_clarity_justification": "string", "success_criteria_clarity_score": 0.0, "success_criteria_clarity_justification": "string"}"""
|
|
338
322
|
|
|
339
323
|
def _build_scoring_user_prompt(self, context: str) -> str:
|
|
340
324
|
"""Build user prompt with interview context.
|
|
@@ -365,27 +349,23 @@ Analyze each component and provide scores with justifications."""
|
|
|
365
349
|
Raises:
|
|
366
350
|
ValueError: If response cannot be parsed.
|
|
367
351
|
"""
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
key = prefix[:-1].lower() # Remove colon and lowercase
|
|
386
|
-
value = line[len(prefix) :].strip()
|
|
387
|
-
scores[key] = value
|
|
388
|
-
break
|
|
352
|
+
# Extract JSON from response (handle markdown code blocks)
|
|
353
|
+
text = response.strip()
|
|
354
|
+
|
|
355
|
+
# Try to find JSON in markdown code block
|
|
356
|
+
json_match = re.search(r"```(?:json)?\s*(\{.*?\})\s*```", text, re.DOTALL)
|
|
357
|
+
if json_match:
|
|
358
|
+
text = json_match.group(1)
|
|
359
|
+
else:
|
|
360
|
+
# Try to find raw JSON object
|
|
361
|
+
json_match = re.search(r"\{.*\}", text, re.DOTALL)
|
|
362
|
+
if json_match:
|
|
363
|
+
text = json_match.group(0)
|
|
364
|
+
|
|
365
|
+
try:
|
|
366
|
+
data = json.loads(text)
|
|
367
|
+
except json.JSONDecodeError as e:
|
|
368
|
+
raise ValueError(f"Invalid JSON response: {e}") from e
|
|
389
369
|
|
|
390
370
|
# Validate all required fields are present
|
|
391
371
|
required_fields = [
|
|
@@ -398,35 +378,32 @@ Analyze each component and provide scores with justifications."""
|
|
|
398
378
|
]
|
|
399
379
|
|
|
400
380
|
for field_name in required_fields:
|
|
401
|
-
if field_name not in
|
|
381
|
+
if field_name not in data:
|
|
402
382
|
raise ValueError(f"Missing required field: {field_name}")
|
|
403
383
|
|
|
404
|
-
# Parse
|
|
405
|
-
def
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
return max(0.0, min(1.0, score)) # Clamp to [0, 1]
|
|
409
|
-
except ValueError as e:
|
|
410
|
-
raise ValueError(f"Invalid score value: {value}") from e
|
|
384
|
+
# Parse and clamp scores
|
|
385
|
+
def clamp_score(value: Any) -> float:
|
|
386
|
+
score = float(value)
|
|
387
|
+
return max(0.0, min(1.0, score))
|
|
411
388
|
|
|
412
389
|
return ScoreBreakdown(
|
|
413
390
|
goal_clarity=ComponentScore(
|
|
414
391
|
name="Goal Clarity",
|
|
415
|
-
clarity_score=
|
|
392
|
+
clarity_score=clamp_score(data["goal_clarity_score"]),
|
|
416
393
|
weight=GOAL_CLARITY_WEIGHT,
|
|
417
|
-
justification=
|
|
394
|
+
justification=str(data["goal_clarity_justification"]),
|
|
418
395
|
),
|
|
419
396
|
constraint_clarity=ComponentScore(
|
|
420
397
|
name="Constraint Clarity",
|
|
421
|
-
clarity_score=
|
|
398
|
+
clarity_score=clamp_score(data["constraint_clarity_score"]),
|
|
422
399
|
weight=CONSTRAINT_CLARITY_WEIGHT,
|
|
423
|
-
justification=
|
|
400
|
+
justification=str(data["constraint_clarity_justification"]),
|
|
424
401
|
),
|
|
425
402
|
success_criteria_clarity=ComponentScore(
|
|
426
403
|
name="Success Criteria Clarity",
|
|
427
|
-
clarity_score=
|
|
404
|
+
clarity_score=clamp_score(data["success_criteria_clarity_score"]),
|
|
428
405
|
weight=SUCCESS_CRITERIA_CLARITY_WEIGHT,
|
|
429
|
-
justification=
|
|
406
|
+
justification=str(data["success_criteria_clarity_justification"]),
|
|
430
407
|
),
|
|
431
408
|
)
|
|
432
409
|
|
|
@@ -46,13 +46,17 @@ def create_valid_scoring_response(
|
|
|
46
46
|
success_score: float = 0.8,
|
|
47
47
|
success_justification: str = "Success criteria are measurable.",
|
|
48
48
|
) -> str:
|
|
49
|
-
"""Create a valid LLM scoring response string."""
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
49
|
+
"""Create a valid LLM scoring response string in JSON format."""
|
|
50
|
+
import json
|
|
51
|
+
|
|
52
|
+
return json.dumps({
|
|
53
|
+
"goal_clarity_score": goal_score,
|
|
54
|
+
"goal_clarity_justification": goal_justification,
|
|
55
|
+
"constraint_clarity_score": constraint_score,
|
|
56
|
+
"constraint_clarity_justification": constraint_justification,
|
|
57
|
+
"success_criteria_clarity_score": success_score,
|
|
58
|
+
"success_criteria_clarity_justification": success_justification,
|
|
59
|
+
})
|
|
56
60
|
|
|
57
61
|
|
|
58
62
|
def create_interview_state_with_rounds(
|
|
@@ -665,41 +669,31 @@ class TestAmbiguityScorerParseResponse:
|
|
|
665
669
|
mock_adapter = MagicMock()
|
|
666
670
|
scorer = AmbiguityScorer(llm_adapter=mock_adapter)
|
|
667
671
|
|
|
668
|
-
|
|
669
|
-
|
|
672
|
+
# JSON with missing field
|
|
673
|
+
response = '{"goal_clarity_score": 0.9, "goal_clarity_justification": "Good goal."}'
|
|
670
674
|
|
|
671
675
|
with pytest.raises(ValueError, match="Missing required field"):
|
|
672
676
|
scorer._parse_scoring_response(response)
|
|
673
677
|
|
|
674
|
-
def
|
|
675
|
-
"""_parse_scoring_response raises error for invalid
|
|
678
|
+
def test_parse_response_invalid_json(self) -> None:
|
|
679
|
+
"""_parse_scoring_response raises error for invalid JSON."""
|
|
676
680
|
mock_adapter = MagicMock()
|
|
677
681
|
scorer = AmbiguityScorer(llm_adapter=mock_adapter)
|
|
678
682
|
|
|
679
|
-
response = ""
|
|
680
|
-
GOAL_CLARITY_JUSTIFICATION: Test
|
|
681
|
-
CONSTRAINT_CLARITY_SCORE: 0.8
|
|
682
|
-
CONSTRAINT_CLARITY_JUSTIFICATION: Test
|
|
683
|
-
SUCCESS_CRITERIA_CLARITY_SCORE: 0.7
|
|
684
|
-
SUCCESS_CRITERIA_CLARITY_JUSTIFICATION: Test"""
|
|
683
|
+
response = "This is not valid JSON at all"
|
|
685
684
|
|
|
686
|
-
with pytest.raises(ValueError, match="Invalid
|
|
685
|
+
with pytest.raises(ValueError, match="Invalid JSON response"):
|
|
687
686
|
scorer._parse_scoring_response(response)
|
|
688
687
|
|
|
689
|
-
def
|
|
690
|
-
"""_parse_scoring_response handles
|
|
688
|
+
def test_parse_response_with_markdown_code_block(self) -> None:
|
|
689
|
+
"""_parse_scoring_response handles JSON in markdown code block."""
|
|
691
690
|
mock_adapter = MagicMock()
|
|
692
691
|
scorer = AmbiguityScorer(llm_adapter=mock_adapter)
|
|
693
692
|
|
|
694
|
-
response = """
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
CONSTRAINT_CLARITY_SCORE: 0.75
|
|
699
|
-
CONSTRAINT_CLARITY_JUSTIFICATION: Good constraints.
|
|
700
|
-
|
|
701
|
-
SUCCESS_CRITERIA_CLARITY_SCORE: 0.65
|
|
702
|
-
SUCCESS_CRITERIA_CLARITY_JUSTIFICATION: Clear criteria.
|
|
693
|
+
response = """Here is the analysis:
|
|
694
|
+
```json
|
|
695
|
+
{"goal_clarity_score": 0.85, "goal_clarity_justification": "Clear goal with details.", "constraint_clarity_score": 0.75, "constraint_clarity_justification": "Good constraints.", "success_criteria_clarity_score": 0.65, "success_criteria_clarity_justification": "Clear criteria."}
|
|
696
|
+
```
|
|
703
697
|
"""
|
|
704
698
|
|
|
705
699
|
breakdown = scorer._parse_scoring_response(response)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/_bmad-output/implementation-artifacts/sprint-status.yaml
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ouroboros_ai-0.2.2 → ouroboros_ai-0.2.3}/_bmad-output/planning-artifacts/bmm-workflow-status.yaml
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|