Files
cleveragents-core/features/actor_service_coverage.feature
hurui200320 8dc55655e9
CI / push-validation (push) Successful in 41s
CI / helm (push) Successful in 42s
CI / benchmark-publish (push) Failing after 56s
CI / build (push) Successful in 1m6s
CI / lint (push) Successful in 1m13s
CI / quality (push) Successful in 1m34s
CI / typecheck (push) Successful in 2m12s
CI / security (push) Successful in 2m13s
CI / e2e_tests (push) Successful in 3m45s
CI / integration_tests (push) Successful in 3m57s
CI / unit_tests (push) Successful in 4m53s
CI / docker (push) Successful in 1m34s
CI / coverage (push) Successful in 11m27s
CI / status-check (push) Successful in 3s
CI / benchmark-publish (pull_request) Has been skipped
CI / helm (pull_request) Successful in 32s
CI / push-validation (pull_request) Successful in 33s
CI / build (pull_request) Successful in 53s
CI / lint (pull_request) Successful in 59s
CI / quality (pull_request) Successful in 1m28s
CI / security (pull_request) Successful in 1m29s
CI / typecheck (pull_request) Successful in 1m32s
CI / e2e_tests (pull_request) Successful in 4m1s
CI / integration_tests (pull_request) Successful in 5m4s
CI / unit_tests (pull_request) Successful in 5m51s
CI / docker (pull_request) Successful in 1m27s
CI / coverage (pull_request) Successful in 11m51s
CI / status-check (pull_request) Successful in 3s
feat(actor): make built-in actors virtual, resolved on-demand from provider registry
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
2026-04-30 10:56:21 +00:00

116 lines
5.4 KiB
Gherkin

Feature: Actor service coverage
As a developer
I want actor service behaviors covered
So that custom and built-in actors are validated
Scenario: Normalizes missing prefix to local
Given an actor service with stubbed dependencies
When I normalize actor name "custom"
Then the normalized actor name should be "local/custom"
Scenario Outline: Invalid actor names are rejected
Given an actor service with stubbed dependencies
When I try to normalize actor name "<name>" without allowing built-ins
Then a ValidationError should be raised containing "<message>"
Examples:
| name | message |
| | cannot be empty |
| local/extra/slash/name | exactly one '/' separator |
| /missing-id | include both prefix and identifier |
| remote/model | 'local/<id>' naming pattern |
Scenario: Listing actors returns stored entries
Given an actor service with stubbed dependencies
And existing actors named "local/first" and "local/second"
When I list all actors
Then I should receive actors ["local/first", "local/second"]
Scenario: Getting an unknown actor raises not found
Given an actor service with stubbed dependencies
When I attempt to fetch actor "vendor/model"
Then a NotFoundError should be raised for the actor
Scenario: Upserting with non-local namespace always raises ValidationError
Given an actor service with stubbed dependencies
And a built-in actor named "vendor/model" already exists
When I attempt to upsert "vendor/model" as custom
Then a ValidationError should be raised for non-local namespace
Scenario: Upserting with set_default marks actor as default
Given an actor service with stubbed dependencies
And an actor named "local/defaultable" exists
When I upsert "local/defaultable" with set_default
Then the stored actor "local/defaultable" should be default
Scenario: Removing missing actors raises not found
Given an actor service with stubbed dependencies
When I try to remove actor "local/missing"
Then a NotFoundError should be raised for the actor
Scenario: Removing protected actors surfaces business rule violation
Given an actor service with stubbed dependencies
And a built-in actor named "local/protected" already exists
When I try to remove actor "local/protected"
Then a BusinessRuleViolation should be raised
Scenario: Setting default actor requires existing entry
Given an actor service with stubbed dependencies
When I set default actor "local/absent"
Then a NotFoundError should be raised for the actor
Scenario: Setting default actor updates repository default
Given an actor service with stubbed dependencies
And an actor named "local/current" exists
When I set default actor "local/current"
Then the stored actor "local/current" should be default
Scenario: Ensuring default mock actor returns existing default
Given an actor service with stubbed dependencies
And an actor named "local/existing-default" exists as default
When I ensure the default mock actor with env value "true"
Then the returned actor name should be "local/existing-default"
And no additional actors should be created
Scenario: Ensuring default mock actor promotes existing mock
Given an actor service with stubbed dependencies
And a mock actor named "local/mock-default" exists without default flag
When I ensure the default mock actor with env value "1"
Then the returned actor name should be "local/mock-default"
And the stored actor "local/mock-default" should be default
Scenario: Ensuring default mock actor creates a new default when missing
Given an actor service with stubbed dependencies
When I ensure the default mock actor with env value "yes"
Then the returned actor name should be "local/mock-default"
And the stored actor "local/mock-default" should be default
Scenario: Ensuring default mock actor is a no-op when env disabled
Given an actor service with stubbed dependencies
And any existing actors are cleared
When I ensure the default mock actor with env value "0"
Then the result should be None
Scenario: Ensuring default mock actor is idempotent
Given an actor service with stubbed dependencies
When I ensure the default mock actor with env value "true"
Then the returned actor name should be "local/mock-default"
And the stored actor "local/mock-default" should be default
When I ensure the default mock actor with env value "true" again
Then the returned actor name should be "local/mock-default"
And only one "local/mock-default" actor should exist
Scenario: Ensuring default mock actor with existing default is safe
Given an actor service with stubbed dependencies
And an actor named "local/existing-default" exists as default
When I ensure the default mock actor with env value "true"
Then the returned actor name should be "local/existing-default"
And the stored actor "local/existing-default" should be default
And only one default actor should exist
Scenario: Ensuring default mock actor creates exactly one actor
Given an actor service with stubbed dependencies
When I ensure the default mock actor with env value "true"
Then exactly one actor should exist
And the stored actor "local/mock-default" should be default