Three CI gates were failing on this PR; this commit addresses the root
causes for each:
* lint (ruff format): drop the blank line between the docstring close
and first statement in step_pr_create_with_error, and add the missing
second blank line between step_pr_check_remove_link_persisted and the
"Data integrity BDD step extensions" section comment block.
* unit_tests: two scenarios were inverted by `@tdd_expected_fail` on
post-fix assertions, masking unrelated test-logic problems.
- Remove `@tdd_expected_fail` from both `@tdd_issue_8179` scenarios in
project_repository.feature - they describe post-fix behaviour and
must report PASS as PASS, not as inverted-FAIL.
- Drop the "Given project exists" precondition from the Update-non-
existent scenario; the Background already initialises the in-memory
DB and creating the same project being "updated as non-existent" is
self-contradictory (caused the prior scenario to silently report
inverted-PASS while actually never raising).
- Update the OperationalError scenario in database_repository_coverage
to assert the post-fix invariant: the repository no longer calls
session.rollback() itself; that responsibility is delegated to the
outer UnitOfWork. Step text + assertion both flipped.
ISSUES CLOSED: #8179
Replace the DB-persistence approach for built-in actors with in-memory virtual
resolution. Built-in actors (e.g. openai/gpt-4o, anthropic/claude-sonnet) are
now resolved on-demand from ProviderRegistry at query time and merged with
persisted custom actors — no database writes occur for built-in actors.
Key changes:
- Add ActorRegistry._resolve_virtual_builtin_actors(): generates virtual Actor
objects in-memory from configured providers (is_built_in=True, id=None)
- ActorRegistry.list()/list_actors(): merges virtual built-ins with custom DB
actors; custom actors win on name collision; result sorted alphabetically
- ActorRegistry.get()/get_actor(): DB-first, virtual built-in fallback,
NotFoundError if neither
- ActorRegistry.remove()/remove_actor(): rejects virtual built-in names with
ValidationError
- ActorRegistry.set_default_actor(): stores only the actor name string via new
actor_preferences singleton table; no actor row created for virtual built-ins
- ActorRegistry.get_default_actor(): reads preference name, resolves via
DB→virtual chain, returns actor with is_default=True
- Remove ensure_built_in_actors() entirely — 20+ call sites cleaned up including
plan.py
- Remove ActorRepository.upsert_built_in() — no longer needed
- Remove is_built_in from ActorModel DB column (kept on Actor domain model for
virtual actors)
- New Alembic migration m10_001_virtual_builtin_actors: drops is_built_in column,
adds actor_preferences singleton table
- Add ActorService.set_default_actor_name() and get_default_actor_name() for
preference storage without requiring a DB actor row
- Update 15+ Behave step files and 5 feature files; add new
features/virtual_builtin_actors.feature with 8 scenarios covering list, show,
remove, set-default, get-default, no-DB-writes guarantees
- Rewrite tests/actor/test_registry_builtin_yaml.py: TestEnsureBuiltInActorsWithYaml
→ TestResolveVirtualBuiltinActors plus new TestListActors, TestGetActor,
TestRemoveActor, TestDefaultActor test classes
Quality gates: lint ✓, typecheck ✓, unit_tests ✓ (15674 scenarios), coverage ✓
(97.10%), integration_tests ✓ (1997 tests)
ISSUES CLOSED: #10923