fix(cli): implement --execution-env-priority on project context set #1135
Merged
hamza.khyari
merged 1 commits from 2026-03-30 14:53:55 +00:00
bugfix/m8-project-exec-env-priority 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.
Milestone
No items
No Milestone
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
hamza.khyari
Notifications
Due Date
No due date set.
Dependencies
No dependencies set.
Reference: cleveragents/cleveragents-core#1135
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/m8-project-exec-env-priority"
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?
Summary
Implement the missing
--execution-env-priorityflag onproject context setper issue #1079 / spec WF17.Changes
project.py: Addedexecution_env_priority: str | Nonefield toContextConfigdomain modelproject_context.py: Added--execution-env-priorityCLI flag withfallback/overridevalidation againstExecutionEnvPriorityenum. Persists incontext_policy_jsonblob alongsideexecution_environment. Added display inproject context showoutput.Behavior
project context set local/myproj --execution-env-priority overridevalidates and persistsproject context set local/myproj --execution-env-priority invalidrejects with errorexecution_environment(merged blob)project context showdisplays both environment and priority in a new sectionQuality Gates
nox -s typechecknox -s lintCloses #1079
Review: APPROVED with Comments
Good implementation that correctly addresses the core issue — the critical blob-merge fix (loading existing
context_policy_jsonbefore writing) prevents previously-set fields from being silently dropped. The PR follows existing patterns, has a clean CHANGELOG entry, and includes 9 BDD scenarios. Approving, but please note the following items.Issues to Address
No milestone assigned. The branch is prefixed
bugfix/m8-*, suggesting it belongs to Milestone 8. Per CONTRIBUTING.md requirement #11, a milestone is mandatory. Please assign before merge.Merge conflicts.
mergeable: false— needs a rebase against master.Test fidelity gap. The BDD step
step_call_set_with_priorityre-implements the enum validation and persistence logic inline rather than calling the actualcontext_setCLI function. If the real CLI code diverges from this simulation, the tests will still pass. Consider invoking the actual CLI code path (viaCliRunner) for at least one scenario to ensure the wiring is correct.Loose domain typing.
execution_env_priority: str | NoneinContextConfig(project.py) should beExecutionEnvPriority | Noneto enforce invariants at the model level. Currently, validation is only at the CLI boundary, meaning any code that constructsContextConfigdirectly can set arbitrary strings.Minor Notes
No test for
context_showoutput. The new display section added to the show command is untested.The merge dict ordering
{**existing, **policy.model_dump(), **extra_fields}meanspolicy.model_dump()defaults could overwrite previously persisted non-default settings. This is pre-existing behavior (not a regression from this PR), but worth noting for a future hardening pass.d9c61e28ceto46951e7243New commits pushed, approval review dismissed automatically according to repository settings
46951e7243to411a80c643411a80c643to8a8a949106Review: fix(cli): implement --execution-env-priority on project context set
Approved with comments. Solid implementation with decent test coverage.
Issues to Address
1. No milestone assigned (Medium)
Per CONTRIBUTING.md, every PR must be assigned to a milestone.
2. Unrelated merge commits (Medium)
Branch contains 10 unrelated merge commits from master. Should be rebased.
3. BDD tests don't invoke the actual CLI (Medium)
The test steps inline the validation logic (
ExecutionEnvPriority(priority.lower())) and directly manipulate the DB rather than usingCliRunnerto invoke the actualcontext_setTyper command. This means the command wiring is untested — a regression in argument binding would be missed. At least one scenario should useCliRunner.4. Type safety gap (Low)
ContextConfig.execution_env_priorityisstr | Noneinstead ofExecutionEnvPriority | None. The CLI validates via the enum, but the domain model accepts any string.What's Good
--execution-env-priorityoption with clear help text.ExecutionEnvPriorityenum with proper error message andtyper.Exit(1)._load_policy_jsonnull-coalescing (or {}) prevents NoneType errors on first use.existing = _load_policy_json(...)preserves previously set fields — critical and correctly implemented.context_showupdated to display the new field.Day 48 Planning Review — Bug Fix PR for #1079
The implementation adds
--execution-env-prioritytoproject context setwith 9 BDD scenarios. The single-commit structure and Conventional Changelog format are correct.Blocking issues:
Merge conflicts (
mergeable: false) — rebase onto master required.No milestone assigned — CONTRIBUTING.md requires a milestone on all PRs. The branch name says
m8-but the linked bug #1079 is in v3.5.0. Set the PR milestone to match the issue milestone.Test fidelity gap — As @freemo noted in reviews #2709 and #2788, the BDD steps re-implement validation logic inline instead of invoking the actual CLI via
CliRunner. This means a wiring regression (e.g., the CLI flag not being passed through to the service) would not be caught. At minimum, add one end-to-end scenario that exercises the real CLI path.Domain typing —
ContextConfig.execution_env_priorityisstr | Noneinstead ofExecutionEnvPriority | None. Per the spec and CONTRIBUTING.md's type safety requirements, the domain model should use the enum type. CLI boundary validation is correct but the domain should enforce it too.No
@tdd_expected_failremoval in diff — Verify whether bug #1079 has a TDD counterpart with an expected-fail test. If so, it must be removed in this PR. If no TDD test exists, that's a separate concern.Requested changes: Rebase, set milestone, add CLI integration test, address typing concern.
PR Review: !1135 (Ticket #1079)
Verdict: Request Changes
The PR adds the
--execution-env-priorityflag toproject context setwith validation, persistence, display incontext_show, and propagation toplan use. The commit structure (single atomic commit, Conventional Changelog format) is clean and the core idea is correct. However, the review uncovered 2 novel critical correctness bugs, several unaddressed issues from previous reviews, and significant test quality gaps that prevent merging.Critical Issues
C1. Data loss in
context_set:_write_policy()clobbers previously stored fields before merge readsrc/cleveragents/cli/commands/project_context.py, lines 643 → 676–688_write_policy(session_factory, project, policy, acms), which completely replaces the JSON blob withpolicy.model_dump() + acms_config, stripping any previously stored top-level keys likeexecution_environmentandexecution_env_priority. Then on line 678,existing = _load_policy_json(...)reads the already-clobbered blob, so the "merge" on line 679 has nothing to merge with.project context set local/proj --execution-environment container, then laterproject context set local/proj --execution-env-priority override. The second call clobbersexecution_environmentat line 643 before the merge logic on line 678 can preserve it. Anycontext setcall without--execution-environmentsilently loses a previously-set environment.existing = _load_policy_json(...)before line 643's_write_policy()call, or consolidate into a single write that builds the full blob (policy + acms + extra_fields + preserved existing keys) before writing once.C2. Propagated project-level priority is overwritten by fallback default in
plan.pysrc/cleveragents/cli/commands/plan.py, lines 1704–1734 (propagation) vs. lines 1791–1794 (fallback)plan.execution_env_priorityto the project-level value (e.g.,OVERRIDE). However, the existing fallback logic on lines 1791–1794 then unconditionally overwrites it:execution_environment, not the plan's current value. Since the user provided--execution-environmentbut not--execution-env-priority, theeliffires and replaces the propagatedOVERRIDEwithFALLBACK.elif execution_environment and plan.execution_env_priority is None:. Or move the propagation block to after the existing CLI-override handling so it only fills gaps.C3. BDD and Robot E2E tests do not exercise actual CLI code paths
features/steps/project_exec_env_priority_steps.py, lines 137–147;robot/helper_wf17_project_exec_env_priority.py, lines 16–60step_call_set_with_priorityre-implements the enum validation and direct DB persistence inline rather than invoking the actualcontext_setTyper command. The Robot E2E helpers only validateExecutionEnvPriorityenum construction and JSON round-trips in-memory. Neither test suite exercises the actual CLI wiring, argument parsing, persistence path, or display logic. This means bugs C1 and C2 above are not caught by any test.CliRunnerin BDD steps — this PR deviates from the established testing convention.CliRunnerto invoke the actualcontext_setcommand (with a mocked DI container), consistent with established patterns. Rewrite Robot helpers to invoke the actual CLI binary via subprocess.Major Issues
M1. Plan propagation logic (AC3) is completely untested
features/project_exec_env_priority.feature, lines 60–63plan.py(lines 1704–1734) that reads project-level settings and applies them to plan objects is never exercised. AC3 of ticket #1079 has zero test coverage.execution_env_priority = "override", then invokesplan use(or its internals) without--execution-env-priority, and asserts the plan object has the propagated value.M2.
context_showomits execution environment fields in non-rich output formatssrc/cleveragents/cli/commands/project_context.py, lines 749–756 vs. 792–805datadict used for JSON/YAML/plain output does not includeexecution_environmentorexecution_env_priority. Only the rich output path reads these from the raw blob.project context show --format jsonwill not display the new fields, partially violating AC2 ("retrievable via project context show").datadict by reading the raw blob before the format branching.M3. Domain type safety gap:
ContextConfig.execution_env_priorityisstr | Nonesrc/cleveragents/domain/models/core/project.py, line 272ExecutionEnvPriority | None(plan.py:699), butContextConfigusesstr | None. Any code constructingContextConfigdirectly can set arbitrary strings. Per CONTRIBUTING.md's type safety requirements and the project's Pyright strict mode, the domain model should enforce the enum constraint.execution_env_priority: ExecutionEnvPriority | None = Field(default=None, ...).M4. Bare
except Exception: passviolates error handling guidelinessrc/cleveragents/cli/commands/plan.py, lines 1733–1734AttributeError,TypeError, database corruption, and import failures. Creates a partial-state risk: ifplan.execution_environment = proj_envsucceeds butExecutionEnvPriority(proj_priority)fails, the plan has an environment set but no priority. Per CONTRIBUTING.md: "Do not suppress errors" and "No Silent Failures."except (ImportError, KeyError, ValueError) as exc: logger.debug("Project context propagation skipped: %s", exc).M5.
execution_environmentnot validated during propagationsrc/cleveragents/cli/commands/plan.py, lines 1721–1723proj_envis read from the JSON blob and assigned directly toplan.execution_environmentwithout validating against theExecutionEnvironmentenum. In contrast,proj_priorityIS validated on line 1729. If the blob contains a corrupted or invalid environment string, it propagates an invalid value to the plan.proj_envthroughExecutionEnvironment(proj_env)before assignment.M6. No milestone assigned on PR
milestoneisnullbut ticket #1079 is in milestone v3.5.0. Per CONTRIBUTING.md: "Every PR must be assigned to the same milestone as its linked issue(s)."M7. Merge conflicts — branch needs rebase
mergeable: false)master.M8.
context_showexecution environment display is untestedsrc/cleveragents/cli/commands/project_context.py, lines 792–805context_showvia CliRunner and asserts the output contains the priority value.M9. No
@tdd_issue_1079test exists in codebase@tdd_expected_failfrom WF17 project-level override test case" (checked off), but notdd_issue_1079tag exists anywhere. Per CONTRIBUTING.md, a bug fix PR without a corresponding TDD test may be blocked by CI.Minor Issues
m1. Double-write + redundant DB read in
context_setwhen extra_fields presentsrc/cleveragents/cli/commands/project_context.py, lines 643, 676–688--execution-environmentor--execution-env-priorityis provided, the function writes the blob twice (line 643 and line 679) with 3 reads + 2 writes and 5 separate sessions. The first write is immediately overwritten.m2. Triple DB read in
context_showsrc/cleveragents/cli/commands/project_context.py, lines 739, 740, 794_read_policy,_read_acms_config, and the new_load_policy_jsoneach independently read the same row, creating 3 sessions. Pre-existing pattern worsened by this PR.m3. Silent exception swallow in
context_showfor execution env displaysrc/cleveragents/cli/commands/project_context.py, lines 793–796except Exception: raw_blob = Nonesilently hides DB errors when loading the execution environment section. Inconsistent with earlier calls in the same function (lines 739–740) that don't use try/except.m4. Cross-module import of private function
_load_policy_jsonsrc/cleveragents/cli/commands/plan.py, line 1710plan.pyimports_load_policy_json(underscore-prefixed private function) fromproject_context.py, creating tight coupling.load_policy_json(public API) or extract to a shared service layer.m5. Lazy imports of domain enums inside function bodies
src/cleveragents/cli/commands/project_context.py, lines 648, 663ExecutionEnvironmentandExecutionEnvPriorityare imported inside thecontext_setfunction body. Per CONTRIBUTING.md: "Ensure all imports are at the top of the Python file." These enums have no circular dependency risk.m6. Propagation only uses first project link
src/cleveragents/cli/commands/plan.py, line 1716proj_name = project_links[0].project_name— multi-project plans only inherit from the first project. If the first project has no settings but the second does, propagation silently fails.Nits
n1. Misleading BDD scenario title: Feature file line 60 — "Project-level priority propagates to plan when no plan-level override" only tests blob persistence, not propagation. Rename to reflect actual behavior.
n2. Missing case-sensitivity test: No scenario tests mixed-case input (e.g., "OVERRIDE") which the CLI normalizes via
.lower().n3. Missing error path test: No scenario tests setting priority on a nonexistent project.
n4. Temp DB files not cleaned up in steps:
features/steps/project_exec_env_priority_steps.pyline 59 —tempfile.mkstempfiles are never explicitly deleted. Usecontext.add_cleanup.Summary
The PR achieves the core functional intent — adding
--execution-env-prioritytoproject context set— but has significant correctness and quality issues:_write_policyclobber; C2: propagated priority overwritten by fallback default) directly undermine the PR's stated purpose. These bugs are undetected because the tests bypass the actual CLI code.Recommended action: Fix the two critical correctness bugs, rewrite tests to use CliRunner, rebase onto master, set milestone, and address the type safety gap.
Review: REQUEST CHANGES
Critical: Merge Conflict Markers in CHANGELOG.md
The diff shows unresolved merge conflict markers in
CHANGELOG.md:This will break the build. The conflict must be resolved before this PR can be merged.
Missing Milestone
Per CONTRIBUTING.md §Pull Request Process item 11: "Every PR must be assigned to the correct milestone." This PR has no milestone assigned. Since it closes #1079 and the companion PR #1136 is assigned to v3.5.0, this should likely be assigned to the same milestone.
Code Review Notes
The implementation is otherwise well-structured:
ContextConfig.execution_env_priorityfield added correctly with proper description.ExecutionEnvPriorityenum validation incontext_setis clean — validates and rejects invalid values.extra_fieldspattern correctly preserves existing fields when setting priority alone.context showdisplay — Properly renders the execution environment section.Minor Issues
Silent exception suppression in
plan.py(use_action): Theexcept Exception: passblock at the project context propagation silently swallows all errors. Per CONTRIBUTING.md §Exception Propagation: "Do not suppress errors." At minimum, log atdebuglevel.Cross-module import in CLI layer:
from cleveragents.cli.commands.project_context import _load_policy_jsoncreates a dependency between CLI command modules. Consider moving_load_policy_jsonto a shared service or utility module.E2E Robot test is not a true E2E test:
helper_wf17_project_exec_env_priority.pyonly tests enum validation and JSON round-trip — it doesn't actually invoke the CLI. Consider adding a true CLI invocation test.8a8a949106to704f6a7a11704f6a7a11to269a59d39e269a59d39etocf78730c31cf78730c31tob7aa2a4c17b7aa2a4c17toa35fe08d3fa35fe08d3fto295cbb7f80295cbb7f80to741c9560ea741c9560eato49015c6bee