fix(actors): distinguish namespace/name from provider/model in actor name parsing #11255
Merged
CoreRasurae
merged 5 commits from 2026-05-23 13:31:18 +00:00
bugfix/m3-namespace-provider-name-collision into master
Dismiss Review
Are you sure you want to dismiss this review?
Labels
Clear labels
auto/needs-reevaluation
controller-managed
overdue
auto/blocked-by-deps
auto/ci-timeout
auto/claimed-implementer
auto/claimed-merge
auto/claimed-reviewer
auto/driver-down
auto/invariant-violation
auto/last-attempt-tier-0
auto/last-attempt-tier-1
auto/last-attempt-tier-2
auto/last-attempt-tier-min
Automation Tracking
auto/needs-conflict-resolution
auto/needs-implementer
auto/postmortem
auto/ready-to-merge
auto/restart-throttled
auto/revert
auto/sentinel
auto/stale-inactivity
auto/unstable
Blocked
Needs Feedback
Signed-off: Owner
Signed-off: Scrum Master
Signed-off: Tech Lead
Spike
Controller deferred this PR; awaiting Phase 6+ scope-evaluator or operator re-enablement.
Auto-agents controller manages this PR/issue (see tools/controller/deploy/RUNBOOK.md). Remove this label to abandon controller management.
PR blocked by an open issue dependency. Operator must close the dep (or remove the dependency link) before the merge driver can act. Auto-cleared by merge_drive when no open deps remain.
Most recent merge cycle hit CI timeout. Driver excludes this PR while last merge_cycle row is < 30 min old; label persists thereafter as visible history.
Currently being processed by an implementer worker.
Currently being processed by the merge driver.
Currently being processed by a reviewer worker.
Merge driver heartbeat stale; pipeline halted. Closed automatically on next clean tick.
Detected master commit violating the strict merge invariant. Tracked as an issue (not a PR label); kept here for label completeness.
In-cycle escalation: most recent attempt ran at the Tier 0 slot (`tier-0`). Slot's model defined in .opencode/models/tiers.yaml.
In-cycle escalation: most recent attempt ran at the Tier 1 slot (`tier-1`). Slot's model defined in .opencode/models/tiers.yaml.
In-cycle escalation: most recent attempt ran at the Tier 2 slot (`tier-2`). Slot's model defined in .opencode/models/tiers.yaml. Gated behind IMPLEMENTER_ESCALATION_TIER2_ENABLED.
In-cycle escalation: most recent attempt ran at the Tier -1 slot (`tier-min`). Slot's model defined in .opencode/models/tiers.yaml. Suffix is ``-min`` (not ``--1``) so the Forgejo UI reads naturally.
Tracking issues used by the AI Automation system for agents to communicate and report.
Rebase conflict needs LLM conflict-resolver.
Failing CI needs implementer attention.
Documenting a driver incident or rollback.
Reviewer has APPROVED this PR and no later REQUEST_CHANGES is outstanding. The merge driver requires this label to even consider a PR for merging. Set by the reviewer worker on APPROVE; cleared on REQUEST_CHANGES.
Train repeatedly lost master-tempo races. Driver excludes via merge_cycle until cooldown elapses; label persists as visible history.
Revert PR backing out an invariant violation. Fast-tracked through the merge driver.
Sentinel PR duplicated from upstream into a personal fork by tools/duplicate_prs_to_fork.py for pipeline testing. Lives only in the fork; the canonical pipeline never sees it.
No implementer activity for N days. Flagged for human review. Auto-cleared on next push to head branch.
Repeatedly fails on current master (>= 3 ci-fail-on-rebased-sha releases in 12 h). Excluded from driver until human triage.
A ticket in a blocked state and unable to complete until some other task is completed first.
Bounty
$100
A bounty of $100 for any open-source contributor who provides a MR that solves this issue
Bounty
$1000
A bounty of $1000 for any open-source contributor who provides a MR that solves this issue
Bounty
$10000
A bounty of $10000 for any open-source contributor who provides a MR that solves this issue
Bounty
$20
A bounty of $20 for any open-source contributor who provides a MR that solves this issue
Bounty
$2000
A bounty of $2000 for any open-source contributor who provides a MR that solves this issue
Bounty
$250
A bounty of $250 for any open-source contributor who provides a MR that solves this issue
Bounty
$50
A bounty of $50 for any open-source contributor who provides a MR that solves this issue
Bounty
$500
A bounty of $500 for any open-source contributor who provides a MR that solves this issue
Bounty
$5000
A bounty of $5000 for any open-source contributor who provides a MR that solves this issue
Bounty
$750
A bounty of $750 for any open-source contributor who provides a MR that solves this issue
MoSCoW
Could have
Could have feature in order to satisfy the epic/legendary.
MoSCoW
Must have
Must have feature in order to satisfy the epic/legendary.
MoSCoW
Should have
Should have feature in order to satisfy the epic/legendary.
There are questions in the ticket that can not be completed until the project owner provides clarity.
Points
1
1 man-hours worth of work for an expert with no learning curve.
Points
13
13 man-hours worth of work for an expert with no learning curve.
Points
2
2 man-hours worth of work for an expert with no learning curve.
Points
21
21 man-hours worth of work for an expert with no learning curve.
Points
3
3 man-hours worth of work for an expert with no learning curve.
Points
34
34 man-hours worth of work for an expert with no learning curve.
Points
5
5 man-hours worth of work for an expert with no learning curve.
Points
55
55 man-hours worth of work for an expert with no learning curve.
Points
8
8 man-hours worth of work for an expert with no learning curve.
Points
88
88 man-hours worth of work for an expert with no learning curve.
Priority
Backlog
This ticket has backlogged priority and is not to be worked on yet
Priority
CI Blocker
Critical priority issue that blocks CI/CD pipeline and prevents PR merges
Priority
Critical
The priority is critical
Priority
High
The priority is high
Priority
Low
The priority is low
Priority
Medium
The priority is medium
When an epic or legendary is in review it must be signed off by owner, tech lead, and scrum master before being marked as completed.
When an epic or legendary is in review it must be signed off by owner, tech lead, and scrum master before being marked as completed.
When an epic or legendary is in review it must be signed off by owner, tech lead, and scrum master before being marked as completed.
A ticket for learning a tool or technology that is needed to be able to do future planning and design.
State
Completed
The ticket has been fully implemented, completed, and merged with the source code. This label should only be applied once a ticket is closed.
State
Duplicate
A ticket that represents the same content as an existing ticket.
State
In Progress
A ticket that is actively being developed.
State
In Review
A ticket that has had some code completed to implement but is waiting to pass peer review and is not yet merged in.
State
Paused
This ticket's work started but wasn't finished. It's on hold (likely in a feature branch) and will be resumed later, either due to a blocker or a delay.
State
Unverified
All new tickets start in this state. A developer may set it to show the ticket is unverified. This means we haven't agreed to work on it. It will either move to a verified state or be closed as wontdo.
State
Verified
The issue has been verified by a developer as legitimate. It will be worked on and verified tickets are now considered part of the backlog.
State
Wont Do
This ticket has been decided it wont be done. This may mean the bug has been determined to not be real (cant verify) or the feature is one we have decided we dont want to adopt.
Type
Automation
Any edits or discussion about the AI automated coding system.
Type
Bug
Something that doesnt work as intended.
Type
Discussion
Anytime a ticket represents a discussion about a subject and doesnt fall into one of the other categories.
Type
Documentation
An error or improvement needed in the documentation.
Type
Epic
Any first tier epic. That is, an epic which contains only issues as children and will not have sub-epics.
Type
Feature
Some new functionality not present.
Type
Legendary
A type of Epic which will contain other Epics.
Type
Refactor
A code change that restructures existing code without changing its external behavior.
Type
Support
Someone needs help using the project.
Type
Task
A generic task that doesnt fit into the other type categories.
Type
Testing
Work exclusively focusing on fixing or expanding testing.
Projects
Clear projects
No project
Assignees
aditya (Aditya Chhabra)
aleenaumair (Aleena Umair)
brent.edwards (Brent Edwards)
CoreRasurae (Luis Mendes)
drew (Drew Morris)
eugen.thaci (Eugen Thaci)
freemo (Jeffrey Phillips Freeman)
HAL9000 (HAL 9000)
HAL9001 (HAL9001)
hamza.khyari (Hamza Khyari)
hurui200320 (Rui Hu)
justin.morris
khird (Kyle Hird)
org.cleveragents
Clear assignees
No Assignees
HAL9000
Notifications
Due Date
No due date set.
Blocks
#11254 Bug: namespace prefix confused with provider name when executing a plan
cleveragents/cleveragents-core
Reference: cleveragents/cleveragents-core#11255
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Delete Branch "bugfix/m3-namespace-provider-name-collision"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Description
Fixes #11254 — when action YAML references actors using namespace/name format (e.g.
strategy_actor: local/my-strategist),_parse_actor_name()incorrectly treated the namespace prefix as a provider name, causingValueError: Unknown provider type: local.Changes
_is_known_provider(): New utility function that checks whether a slash-separated first segment matches a knownProviderTypevalue (openai,anthropic, etc.)._parse_actor_name(): When the first segment IS a known provider, preserves existing behaviour (provider/model). When it is NOT a known provider, treats the input as namespace/name and returns the full name as the model identifier with the default provider. Callers SHOULD pre-resolve namespace/name references via the actor registry before calling this function.PlanLifecycleService.resolve_actor_provider_model(): New method that resolves a namespaced actor name (e.g.local/my-strategist) toprovider/modelformat by looking up the actor record and extracting itsproviderandmodelfields.Caller pre-resolution:
StrategyActor,LLMStrategizeActor, andLLMExecuteActornow pre-resolve actor names through the lifecycle service before calling_parse_actor_name(), ensuring namespace/name references are correctly mapped to their underlying LLM providers.Testing
_parse_actor_name()implementations_is_known_provider()Closes #11254
PR Review: Request Changes
Reviewer: Brent Edwards
Date: 2026-05-21
Review Type: First review
Outcome: REQUEST_CHANGES
CI Gate — BLOCKING
The
coverage (pull_request)CI job is failing after 20+ minutes. All other required checks pass:Per company policy, all 5 required-for-merge CI gates must pass (lint, typecheck, security, unit_tests, coverage) before the PR can be approved or merged. The failing coverage job is a hard blocker. Please fix the coverage failure and push a new commit.
Issue #11254 Scope — Incomplete Coverage
Issue #11254 lists 6 affected call sites for the
ValueError: Unknown provider type: localbug:StrategyActor._execute_with_llm()strategy_actor.py:454-467LLMStrategizeActor.execute()llm_actors.py:147-161LLMExecuteActor.execute()llm_actors.py:376-393SessionWorkflow._resolve_llm()session_workflow.py:383-391validate_namespaced_actor()cli/commands/plan.py:119-137from_config()action.py:638-644The PR correctly updates the three
PlanLifecycleService-aware actors (StrategyActor,LLMStrategizeActor,LLMExecuteActor) with pre-resolution viaresolve_actor_provider_model(). However,SessionWorkflow._resolve_llm()(line 365-391 insession_workflow.py) is explicitly listed in the issue as an affected call site and is not updated.The
_is_known_provider()check added to_parse_actor_name()will prevent theValueErrorcrash inSessionWorkflow(it now silently falls back toopenai/<full_actor_name>), but this is incorrect behavior — the model field will contain the namespace/name string (e.g."local/strategist") rather than the resolved model from the actor registry.Required fix: Either:
SessionWorkflow._resolve_llm()(requires giving it lifecycle service access), orSessionWorkflowis intentionally out of scope for this PR, add an explicit advisory docstring to_resolve_llm()warning that namespace/name format is not supported there, and add aFIXME: #11254reference.The issue description does not carve out
SessionWorkflowas out-of-scope, so option (a) is preferred.Non-blocking Observations
# type: ignore[union-attr]workarounds — Thehasattr(self._lifecycle, "resolve_actor_provider_model")guards followed by# type: ignore[union-attr]casts (e.g.llm_actors.py:171-172) are technically not# type: ignoresuppressions, but they do serve the same purpose as a suppression. The contributing guide says "zero tolerance for# type: ignore" — while this pattern is not a literal# type: ignore, consider whether a protocol refinement orcast()fromtypingwould be cleaner.Coverage gap root cause — The failing coverage job is likely caused by uncovered branches in the new code: the
logger.debug("…first segment is not a known provider…")path (strategy_resolution.py:157-161), theexcept Exceptionblock inresolve_actor_provider_model()(plan_lifecycle_service.py:757-762), or theactor is Nonepath (plan_lifecycle_service.py:765-767). Please add Behave scenarios to exercise these paths.What Was Done Well
_is_known_provider()utility is a clean and reusable way to distinguish the two conventions — correctly implemented in bothstrategy_resolution.pyandllm_actors.py.resolve_actor_provider_model()method is a proper service-layer solution with appropriate null-checking and logging.Summary
This PR is a solid fix for the core bug described in #11254 for the three
PlanLifecycleService-aware actors. However, it cannot be approved because: (1) the coverage CI job is failing, which is a hard merge gate, and (2)SessionWorkflow._resolve_llm()— explicitly listed as an affected call site in the issue — is not addressed, leaving that code path silently producing incorrect LLM configurations instead of crashing.Please address the coverage failure and either extend the fix to
SessionWorkflow._resolve_llm()or explicitly document its limitation.Automated by CleverAgents Bot
Supervisor: PR Review | Agent: pr-review-worker
6fd4b9bce6tode73ef9c3bde73ef9c3bto4427845446PR #11255 Review —
fix(actors): distinguish namespace/name from provider/model in actor name parsingContext & Prior Review
brent.edwards submitted
REQUEST_CHANGESciting: (1) failingcoverageCI job, and (2)SessionWorkflow._resolve_llm()not addressed. Both concerns are resolved in the current push —session_workflow.pyandcli/commands/session.pyare both updated, and CI now shows success. This is a fresh assessment of the current HEAD (44278454).🔴 Blocking Issues
1.
# type: ignore[union-attr]used 3 times — zero tolerance violatedProject policy: zero inline type suppressions, no exceptions. This PR adds three:
strategy_actor.py—self._lifecycle.resolve_actor_provider_model( # type: ignore[union-attr]llm_actors.py(LLMStrategizeActor) — same patternllm_actors.py(LLMExecuteActor) — same patternThe suppression is needed because
_lifecycleis typed as a protocol/abstract that doesn't declareresolve_actor_provider_model. The correct fix is to add this method to the relevant interface/protocol rather than suppressing the type error at the call site.2. Multiple inline imports inside functions — project import rules violated
Project rules require all imports at the top of the file. The only permitted exception is
if TYPE_CHECKING:. This PR adds inline imports in at least 5 locations:llm_actors.py—_is_known_provider()importsProviderTypeinlinestrategy_resolution.py—_is_known_provider()importsProviderTypeinlineplan_lifecycle_service.py—resolve_actor_provider_model()imports_is_known_providerinlinea2a/facade.py—_build_actor_resolver_for_session_workflow()importsget_container,_is_known_provider,NotFoundErrorinline inside atrycli/commands/session.py—_build_actor_resolver()importsget_container,_is_known_provider,NotFoundErrorinline inside atryIf circular imports prevent top-level placement, the solution is to restructure the dependency graph — not use inline imports.
3.
_is_known_providerduplicated identically across two modulesAn identical implementation exists in both
llm_actors.pyandstrategy_resolution.py:If the logic ever changes, both copies must be updated in sync.
llm_actors.pyshould import_is_known_providerfromstrategy_resolution.pyrather than defining its own copy.4. Missing
@tdd_issue @tdd_issue_11254tags on all new BDD scenariosThis is a
Type/Bugfix. Notdd/m3-*capture branch for issue #11254 exists on the remote and none of the new scenarios inllm_actors_coverage.feature,strategy_actor_llm.feature, orplan_lifecycle_service_coverage_boost_r4.featurecarry@tdd_issue @tdd_issue_11254tags. Per the TDD bug-fix workflow, the fix PR must include these two tags (without@tdd_expected_fail) as the permanent regression guard. CI will block on their absence.🟠 Code Quality
5.
_build_actor_resolverlogic duplicated infacade.pyandsession.pyA2aLocalFacade._build_actor_resolver_for_session_workflow()and_build_actor_resolver()incli/commands/session.pyimplement near-identical logic — both fetchactor_servicefrom the container, build the sameresolve()closure, and fall back on failure. The only difference is the fallback value (Nonevs_null_actor_resolver). This should be a single shared utility.6.
except (NotFoundError, Exception)is redundantIn both
resolve()closures (facade.pyandsession.py):Exceptionis a superclass ofNotFoundError— listing both is redundant. Useexcept Exceptionalone, or narrow to the specific exceptions expected.7. Outer
except Exceptionswallows initialisation failures silentlyIn
_build_actor_resolver()(session.py) and_build_actor_resolver_for_session_workflow()(facade.py), any failure during container/service setup is caught with no log entry:If the DI container is misconfigured, this degrades silently. A
logger.warning(...)should be added to make startup failures observable.🟡 Metadata
8. Issue #11254 still in
State/Verified— should beState/In ReviewThe linked issue must be moved to
State/In Reviewwhen a PR is submitted. Issue #11254 is still showingState/Verified.9.
docs/CHANGELOG.mdnot updatedCHANGELOG.mdis updated butdocs/CHANGELOG.mdis not. The preceding PR (#11246) updated both. Please verify whether both files require entries for every change and update accordingly.10. Commit body does not mention
SessionWorkflowandsession.pyThe commit message body lists
StrategyActor,LLMStrategizeActor, andLLMExecuteActoras updated callers but omitsSessionWorkflowandcli/commands/session.py, which are also materially changed in this commit. The body should reflect all affected call sites.✅ What Is Correct
bugfix/m3-namespace-provider-name-collision✅v3.2.0matches linked issue ✅Priority/Critical+Type/Bug✅ISSUES CLOSED: #11254✅ProviderTypeis aStrEnum—__members__.values()comparison is correct ✅resolve_actor_provider_model()onPlanLifecycleServiceis well-structured with null-checking and logging ✅_null_actor_resolverapplies Null Object pattern correctly ✅SessionWorkflowandcli/commands/session.pyare addressed — brent.edwards' primary concern is resolved ✅Summary
# type: ignore[union-attr]— 3 instances, zero tolerance violated_is_known_providerduplicated identically inllm_actors.pyandstrategy_resolution.py@tdd_issue @tdd_issue_11254tags on all new BDD scenarios_build_actor_resolverlogic duplicated infacade.pyandsession.pyexcept (NotFoundError, Exception)is redundantexcept Exceptionin resolver builders swallows errors with no logState/Verified— should beState/In Reviewdocs/CHANGELOG.mdnot updatedSessionWorkflowandsession.pyfrom list of updated callersPlease address the 🔴 items and re-request review.
4427845446toeaa84799d8Re-Review Summary (Round 2) — PR #11255
Excellent progress — 8 of 10 previous findings fully resolved, 1 partially, 1 still open. The implementation is correct and the core quality issues are addressed. Approving with two remaining comments.
✅ Resolved from Previous Review
# type: ignore[union-attr]— 3 instancesresolve_actor_provider_modeladded toLifecycleServiceprotocol (strategy_resolution.py) andPlanLifecycleProtocol(llm_actors.py) — all suppressions removedProviderTypenow top-level instrategy_resolution.py;_is_known_providertop-level inllm_actors.py,plan_lifecycle_service.py,facade.py,session.py;_parse_actor_nametop-level insession_workflow.py_is_known_providerduplicatedstrategy_resolution.py;llm_actors.pyimports from thereexcept (NotFoundError, Exception)redundantexcept Exceptionexcept Exceptionsilentlogger.warning("actor_resolver_unavailable", exc_info=True)added in bothfacade.pyandsession.pyState/VerifiedState/In Reviewdocs/CHANGELOG.mdnot updatedSessionWorkflow⚠️ Partially Resolved
Finding 4 — 2 scenarios in
plan_lifecycle_service_coverage_boost_r4.featurestill missing@tdd_issue @tdd_issue_11254The 4 core regression scenarios correctly carry the tags. The following 2 do not:
If these scenarios exercise code paths introduced specifically by this bug fix, they should carry the tags as part of the regression guard. If they are considered pure coverage scenarios unrelated to the bug, that should be made explicit via a comment. Please clarify and tag if applicable in a follow-up.
🟠 Still Open
Finding 5 —
_build_actor_resolverclosure logic duplicated infacade.pyandsession.pyThe resolver closure (checking
_is_known_provider, callingactor_service.get_actor, returningf"{actor.provider}/{actor.model}") is still identical in both_build_actor_resolver_for_session_workflow()and_build_actor_resolver(). Theget_containerinline import for lazy initialization is defensible, but the resolver closure itself should be extracted to a shared utility to prevent divergence. Please address in a follow-up issue.Summary
@tdd_issue @tdd_issue_11254inplan_lifecycle_service_coverage_boost_r4.feature_build_actor_resolverclosure duplicated infacade.pyandsession.pyThe fix is sound and production-ready. The two remaining items are non-blocking and can be addressed in follow-up issues.
eaa84799d8toa351d3726ba351d3726btofb1b6ffdaefb1b6ffdaeto696426ec8d696426ec8dto3e13411fcf6b121bf64etocdbe504b2c25430e5a9fto190606d7e6