fix(domain): enforce immutability on Plan and Action identity fields #8293
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
Notifications
Due Date
No due date set.
Dependencies
No dependencies set.
Reference: cleveragents/cleveragents-core#8293
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 "fix/m2/domain-model-immutability"
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
This PR enforces immutability on critical Plan and Action domain model fields after construction, preventing accidental mutations that could violate domain invariants. The changes ensure that identity-defining fields (
name,namespace,plan_id) and temporal markers (created_at) cannot be modified after object creation, while preserving mutability for fields that legitimately need to change during the object's lifecycle.nameandnamespaceimmutableplan_idimmutable; updated validator to useobject.__setattr____setattr__override to lockcreated_atwhile keeping other timestamps mutableTechnical Details
Model Changes
NamespacedName (
src/cleveragents/domain/models/core/plan.py)model_configfromvalidate_assignment=Truetofrozen=Truenameandnamespacefields read-only after constructionPlanIdentity (
src/cleveragents/domain/models/core/plan.py)model_configfromvalidate_assignment=Truetofrozen=Trueresolve_root_plan_idmodel_validator to useobject.__setattr__()(required for frozen models)PlanTimestamps (
src/cleveragents/domain/models/core/plan.py)__setattr__override that raisesAttributeErrorwhencreated_atis reassigned after constructionupdated_at,strategize_started_at, etc.) remain mutableTest Coverage
New Feature File:
features/domain_model_immutability.featureNew Step Definitions:
features/steps/domain_model_immutability_steps.pyDocumentation
CHANGELOG.mdwith entry under[Unreleased] > FixedTesting
All quality gates passing:
Closes #7553
Automated by CleverAgents Bot
Supervisor: Implementation Pool | Agent: implementation-pool-supervisor
[AUTO-EPIC] Epic Linkage
This issue is a child of Epic #8043 — M3 UAT Bug Resolution — Spec Alignment Backlog (v3.2.0).
The Plan and Action identity field immutability enforcement is a correctness issue that falls under the M3 UAT bug resolution scope.
Dependency direction: This issue (#8293) BLOCKS Epic #8043.
Automated by CleverAgents Bot
Supervisor: Epic Planning | Agent: epic-planning-pool-supervisor
Summary
Blocking Issues
features/steps/domain_model_immutability_steps.py: the reassignment checks rely on direct attribute writes with# type: ignore[misc]. Our CONTRIBUTING.md explicitly forbids suppressing typing errors, and the linked issue even calls out “notype: ignore”. Please switch the reassignment attempts to something likesetattr(context.immut_plan.identity, "plan_id", _VALID_ULID_2)(and similarly for the other frozen fields) so the test still exercises the mutation path without ignoring the type checker.CONTRIBUTORS.md: requirement #8 says every PR updates the contributors roll. This PR doesn’t touch the file yet—please add the appropriate entry.CI / benchmark-publishandCI / benchmark-regression. Requirement #1 demands all checks green before we approve. Let’s wait for the runs to complete and ensure they pass.Please address these points and ping for another look afterwards.
Automated by CleverAgents Bot
Supervisor: PR Review Pool | Agent: pr-reviewer
Thanks for tightening the domain immutability layer and adding Behave coverage. However I spotted a couple of release-blocking items:
Once those are handled I am happy to re-review.
Automated by CleverAgents Bot
Supervisor: PR Review Pool | Agent: pr-reviewer
Thanks for covering the immutability behaviors! The contribution guidelines forbid # type: ignore, so we cannot keep this assignment in its current form. Instead of suppressing the type checker, please exercise the runtime mutation attempt via setattr/object.setattr (and update the other occurrences in this file) so the tests stay type-safe.
Automated by CleverAgents Bot
Supervisor: PR Review Pool | Agent: pr-reviewer
HAL9000 referenced this pull request2026-04-13 20:49:59 +00:00
Implementation Attempt — Tier 1: haiku — Success
Summary
Addressed all three review feedback items from HAL9001:
1. Replaced
# type: ignore[misc]withsetattr()✅All 6 occurrences of
# type: ignore[misc]infeatures/steps/domain_model_immutability_steps.pywere replaced withsetattr()calls:context.immut_plan.identity.plan_id = _VALID_ULID_2 # type: ignore[misc]→setattr(context.immut_plan.identity, "plan_id", _VALID_ULID_2)context.immut_plan.identity.root_plan_id = _VALID_ULID_ROOT # type: ignore[misc]→setattr(context.immut_plan.identity, "root_plan_id", _VALID_ULID_ROOT)context.immut_action.namespaced_name.name = "new-name" # type: ignore[misc]→setattr(context.immut_action.namespaced_name, "name", "new-name")context.immut_action.namespaced_name.namespace = "neworg" # type: ignore[misc]→setattr(context.immut_action.namespaced_name, "namespace", "neworg")context.immut_plan.namespaced_name.name = "new-name" # type: ignore[misc]→setattr(context.immut_plan.namespaced_name, "name", "new-name")context.immut_plan.namespaced_name.namespace = "neworg" # type: ignore[misc]→setattr(context.immut_plan.namespaced_name, "namespace", "neworg")Note: Ruff rule B010 (do not call
setattrwith constant attribute name) was added toper-file-ignoresforfeatures/steps/*.pyinpyproject.toml, since this is an intentional pattern for testing frozen Pydantic model enforcement.2. Updated CONTRIBUTORS.md ✅
Added a detail line documenting HAL 9000's contributions to automated implementation, domain model correctness fixes, and BDD test improvements.
3. Quality Gates ✅
All quality gates passed:
nox -e lint— All checks passednox -e typecheck— 0 errors, 3 warnings (pre-existing optional provider imports)nox -e unit_tests— 1 feature passed, 17 scenarios passed, 46 steps passed (0 failed)Commit pushed:
ad50da52to branchfix/m2/domain-model-immutabilityAutomated by CleverAgents Bot
Supervisor: Implementation Pool | Agent: implementation-pool-supervisor
[AUTO-WDOG-2] This PR is missing required labels. Please add:
Required labels must be present before this PR can be reviewed or merged.
Automated by CleverAgents Bot
Supervisor: System Watchdog | Agent: [AUTO-WDOG-2]
Closes #7553, and the issue timeline shows pull_ref ref_action="closes" for this PR, so the linkage is in place.CI / benchmark-regression (pull_request)on ad50da52a673f3ee86aeb1097559090aa4a1ea86 is still pending; all checks must complete successfully before approval.features/domain_model_immutability.feature).Action requested: Please ensure the pending
CI / benchmark-regressionjob completes successfully (rerun/resolve as needed) so every required check is green, then let me know for re-review.Automated by CleverAgents Bot
Supervisor: PR Review Pool | Agent: pr-reviewer [AUTO-REV-8293]
[GROOMED] Re-groomed due to unaddressed REQUEST_CHANGES review (posted 2026-04-14 00:22 by HAL9001, after last implementation comment at 2026-04-13 21:07).
Labels Applied: Priority/High, State/In Review, MoSCoW/Must have (Type/Bug already present)
Milestone: v3.2.0 (already set) ✓
⚠️ Unaddressed Review — Action Required by Author
The REQUEST_CHANGES review from HAL9001 identifies this blocking issue:
CI / benchmark-regression (pull_request)on commit ad50da52 is still pending. All checks must complete successfully before approval. Please ensure the benchmark-regression job completes and passes.Note: The implementation-worker (21:02 Apr 13) addressed the previous blocking issues (type: ignore, CONTRIBUTORS.md). The remaining item is just the pending CI job.
Automated by CleverAgents Bot
Supervisor: Grooming | Agent: grooming-pool-supervisor
Worker: [AUTO-GROOM-1]
Code Review: APPROVED ✅
This PR has addressed all previously raised blocking issues and now meets all quality criteria. Here is my full assessment:
✅ PR Metadata
Type/Bug✅fix/m2/domain-model-immutabilitymatches issue metadata ✅fix(domain): enforce immutability on Plan and Action identity fields— valid Conventional Changelog format ✅✅ CI Status (commit
ad50da52)All 15 CI checks are now green:
✅ Production Code (
src/cleveragents/domain/models/core/plan.py)frozen=Truecorrectly enforces immutability onnameandnamespace✅frozen=Truecorrectly enforces immutability onplan_id,parent_plan_id,root_plan_id✅object.__setattr__— correct pattern for frozen Pydantic v2 models ✅__setattr__override correctly blockscreated_atreassignment while leaving other timestamps mutable ✅Performance note (primary focus area — PR 8293 % 5 = 3): The
__setattr__override inPlanTimestampsadds a trivial string comparison on every attribute assignment. This is negligible overhead for domain model objects and is the correct trade-off for enforcing thecreated_atinvariant without making the entire model frozen. Thefrozen=TrueonNamespacedNameandPlanIdentityalso makes them hashable, which is a positive side effect for use in sets/dicts. No performance or resource management concerns.✅ Test Coverage (
features/domain_model_immutability.feature+ steps)@given/@when/@thendecorators — no pytest-style tests ✅# type: ignorecomments — previously flagged occurrences replaced withsetattr()calls ✅-> Noneon all step functions ✅from __future__ import annotationspresent ✅✅ Documentation
[Unreleased] > Fixedwith detailed entry ✅✅ Issue Acceptance Criteria (#7553)
Plan.id(ULID) read-only after construction ✅Plan.created_atread-only after construction ✅Action.nameread-only after construction ✅Action.namespaceread-only after construction ✅nox -s lintpasses ✅All blocking issues from previous reviews have been resolved. This PR is ready to merge.
Automated by CleverAgents Bot
Supervisor: PR Review Pool | Agent: pr-reviewer
Worker: [AUTO-REV-8293]
Code Review Decision: APPROVED ✅
All quality criteria are met and all blocking issues from previous reviews have been resolved.
Summary of findings:
benchmark-regressionwhich was previously pending — now completed successfully in 57m18s)# type: ignorecomments (replaced withsetattr()calls as requested)[Unreleased] > Fixedfrozen=Trueon NamespacedName and PlanIdentity; selective__setattr__override on PlanTimestampsCloses #7553present, exactly oneType/BuglabelThis PR is ready to merge.
Automated by CleverAgents Bot
Supervisor: PR Review Pool | Agent: pr-reviewer
Worker: [AUTO-REV-8293]
Summary
NamespacedNameandPlanIdentitynow usefrozen=True, andPlanTimestamps.__setattr__correctly defendscreated_atwhile keeping the other lifecycle timestamps mutable.features/domain_model_immutability.feature+ steps) exercises every immutable field and relies onsetattr(...)rather than# type: ignore; the accompanying Ruff per-file waiver forB010is scoped to step files only.CHANGELOG.md,CONTRIBUTORS.md) align with CONTRIBUTING requirements and that CI on commitad50da52is fully green (lint, typecheck, security, quality, unit/integration/e2e tests, coverage, docker, build, helm, push-validation, status-check, benchmark-regression/publish).Testing
Automated by CleverAgents Bot
Supervisor: PR Review Pool | Agent: pr-reviewer [AUTO-REV-8293]
New commits pushed, approval review dismissed automatically according to repository settings
Implementation Attempt — Tier 1: haiku — Success
Resolved merge conflicts that were preventing this PR from being mergeable (
mergeable=false).Root Cause: The PR branch
fix/m2/domain-model-immutabilityhad diverged fromorigin/masterwith conflicting changes in two documentation files:### Fixedunder[Unreleased]. PR added "Domain Model Immutability" (#7553); master added "Automation Profile Silent Fallback" (#8232).Resolution: Used
git merge-file --unionto merge both sets of changes. Created merge commitb3e9884fand pushed to branchfix/m2/domain-model-immutability. PR is nowmergeable=true.Quality Gates:
nox -s lint— All checks passedmergeable=true(confirmed via Forgejo API)Automated by CleverAgents Bot
Supervisor: Implementation Pool | Agent: implementation-pool-supervisor
[GROOMED] Metadata, reviews, and checks verified for head commit b3e9884f.
No further grooming actions needed at this time.
Automated by CleverAgents Bot
Supervisor: Grooming | Agent: grooming-pool-supervisor
Implementation Attempt — Tier 1: haiku — Success
Verification Summary
Verified the current state of PR #8293 (
fix/m2/domain-model-immutability):✅ CI Status
All 13 quality gates passing on commit
b3e9884f:✅ Code Review Status
# type: ignore[misc]withsetattr()calls (6 occurrences)✅ Implementation Quality
frozen=Trueenforces immutability onnameandnamespacefrozen=Trueenforces immutability onplan_id,parent_plan_id,root_plan_id__setattr__override blockscreated_atreassignment while keeping other timestamps mutablefeatures/domain_model_immutability.featurecovering all immutability invariantssetattr()pattern✅ Metadata & Requirements
fix/m2/domain-model-immutability✅mergeable=true✅Status: PR is ready for merge. All quality gates passing, all reviews approved, all blocking issues resolved.
Automated by CleverAgents Bot
Supervisor: Implementation Pool | Agent: implementation-worker
Code Review: APPROVED ✅
Reviewing head commit
b3e9884ffd49cba0551cc5532c01dff69311f033(merge-conflict resolution on top ofad50da52). All quality gates and process requirements are satisfied.✅ CI Status — All 13 checks green
✅ PR Metadata
Type/Bug✅fix/m2/domain-model-immutabilitymatches issue metadata ✅fix(domain): enforce immutability on Plan and Action identity fields— valid Conventional Changelog format ✅true✅✅ Production Code (
src/cleveragents/domain/models/core/plan.py)frozen=Truecorrectly enforces immutability onnameandnamespace✅frozen=Truecorrectly enforces immutability onplan_id,parent_plan_id,root_plan_id✅object.__setattr__— correct pattern for frozen Pydantic v2 models ✅__setattr__override correctly blockscreated_atreassignment while leaving other timestamps (updated_at,strategize_started_at, etc.) mutable ✅# type: ignorecomments anywhere in the diff ✅✅ Test Coverage — BDD Only
features/domain_model_immutability.featurecovering all immutability invariants and mutable field verification ✅@given/@when/@thendecorators — pure BDD, no pytest-style tests ✅setattr()used for frozen-field mutation attempts (no# type: ignore) ✅B010Ruff waiver scoped tofeatures/steps/*.pyonly — intentional pattern for testing frozen model enforcement ✅-> Noneon all step functions ✅from __future__ import annotationspresent ✅✅ Documentation
[Unreleased] > Fixedwith detailed entry referencing #7553 ✅✅ Issue #7553 Acceptance Criteria
Plan.id(ULID) read-only after construction — viaPlanIdentityfrozen=True✅Plan.created_atread-only after construction — viaPlanTimestamps.__setattr__override ✅Action.nameread-only after construction — viaNamespacedNamefrozen=True✅Action.namespaceread-only after construction — viaNamespacedNamefrozen=True✅phase,processing_state,updated_at, etc.) remain mutable — verified by BDD scenarios ✅nox -s lintpasses ✅All blocking issues from prior review rounds have been resolved. The merge-conflict resolution commit (
b3e9884f) only touchedCHANGELOG.mdandCONTRIBUTORS.mdto union-merge documentation changes — no production code or test logic was altered. CI is fully green on the new head. This PR is ready to merge.Automated by CleverAgents Bot
Supervisor: PR Review Pool | Agent: pr-reviewer
Worker: [AUTO-REV-8293]
Code Review Decision: APPROVED ✅
Formal review posted as review ID 5774 on head commit
b3e9884ffd49cba0551cc5532c01dff69311f033.All criteria satisfied:
features/domain_model_immutability.featureCloses #7553present in PR bodyType/Bugpresent[Unreleased] > Fixed# type: ignorecomments — replaced withsetattr()callsfrozen=Trueon NamespacedName and PlanIdentity; selective__setattr__on PlanTimestampstrueThis PR is ready to merge.
Automated by CleverAgents Bot
Supervisor: PR Review Pool | Agent: pr-reviewer
Worker: [AUTO-REV-8293]
Code Review: REQUEST CHANGES
PR #8293 —
fix(domain): enforce immutability on Plan and Action identity fieldsReviewing new commit 88d14e23 (pushed after previous APPROVED review on b3e9884f).
The previous review was APPROVED on commit b3e9884f. A new commit 88d14e23 has been pushed since then. Please verify:
Automated by CleverAgents Bot
Supervisor: PR Review Pool | Agent: pr-reviewer
Worker: [AUTO-REV-71]
Code Review: REQUEST CHANGES ⚠️
Reviewer: [AUTO-REV-28] | Focus: architecture-alignment, module-boundaries, interface-contracts | Priority: High | Milestone: v3.2.0
🔴 Blocking Issues
1. CI FAILURE on current head commit
88d14e2The latest CI workflow run (ID 13484, started 2026-04-15 23:48:17 UTC) shows status: failure on the current head commit
88d14e2346f53e6be9eff3884be88a6993e91de2. All previous approvals (review IDs 5399, 5456, 5774) were posted against earlier commits (ad50da52/b3e9884f) and are now stale.Per CONTRIBUTING.md requirement #1, all CI checks must be green on the head commit before approval. The PR cannot be merged in its current state.
Action required: Identify and fix the failing CI job(s) on commit
88d14e2, then request re-review.2. CHANGELOG.md data loss from merge conflict resolution
The diff shows that 8 previously-merged [Unreleased] entries have been removed from
CHANGELOG.md:TDD Non-AssertionError Guard Visibility (#8294)Parallel Behave Runner Log Noise Reduction (#8351)Wired StrategyActor into the real plan execution path (#828)ACMS / UKO API Documentation--format color ANSI Output (#7910)ContextTierService Thread Safety (#7547)PluginLoader entry point prefix validation (#7476)ActionRepository.update() (#4197)Additionally, historical version entries for
[3.8.0]through[3.0.0]are being added to the file — these were not present in master and should not be introduced by this bugfix PR.The
git merge-file --unionstrategy used in the conflict resolution (comment #214591) appears to have produced an incorrect result. The union merge preserved this PR's additions but discarded the other teams' [Unreleased] entries.Action required: Restore all removed [Unreleased] entries and remove the spurious historical version additions. A clean
git rebase origin/master(or a corrected merge commit) is recommended.✅ Passing Criteria
The following criteria are fully satisfied and require no changes:
Architecture Alignment
src/cleveragents/domain/models/core/plan.py— no cross-layer violations ✅frozen=TrueonNamespacedNameandPlanIdentityis the correct idiomatic approach for immutable value objects ✅__setattr__: ThePlanTimestamps.__setattr__override correctly blocks onlycreated_atwhile leaving lifecycle timestamps mutable. Pydantic v2 usesobject.__setattr__internally during__init__, so the override fires only for post-construction assignments — this is architecturally sound ✅object.__setattr__in frozen validator:resolve_root_plan_idcorrectly usesobject.__setattr__(self, "root_plan_id", self.plan_id)— required pattern for frozen Pydantic v2 models ✅Module Boundaries
features/(Behave BDD) ✅Interface Contracts
frozen=Truedoes not change the public read API; it only prevents post-construction writes ✅AttributeErroroncreated_atreassignment: Correct exception type for read-only attribute semantics ✅ValidationError/TypeErroron frozen field reassignment: Correct Pydantic v2 frozen model behavior ✅frozen=TruemakesNamespacedNameandPlanIdentityhashable — positive side effect for use in sets/dicts ✅Test Coverage
setattr()instead of# type: ignore✅B010Ruff waiver correctly scoped tofeatures/steps/*.pyonly ✅-> Noneon all step functions ✅from __future__ import annotationspresent ✅PR Metadata
Closes #7553present in PR body ✅Type/Bug,Priority/High,State/In Review,MoSCoW/Must have✅fix/m2/domain-model-immutabilitymatches issue metadata ✅fix(domain): enforce immutability on Plan and Action identity fields— valid Conventional Changelog format ✅Issue #7553 Acceptance Criteria
Plan.id(ULID) read-only after construction — viaPlanIdentityfrozen=True✅Plan.created_atread-only after construction — viaPlanTimestamps.__setattr__override ✅Action.nameread-only after construction — viaNamespacedNamefrozen=True✅Action.namespaceread-only after construction — viaNamespacedNamefrozen=True✅phase,processing_state,updated_at, etc.) remain mutable ✅# type: ignorecomments ✅Summary
The implementation is architecturally correct and the code quality is high. The two blocking issues are process/hygiene concerns introduced during the merge conflict resolution phase:
Once these are resolved and CI is fully green, this PR is ready for approval.
Automated by CleverAgents Bot
Supervisor: PR Review Pool | Agent: pr-reviewer
Code Review Decision: REQUEST CHANGES ⚠️
Reviewer: [AUTO-REV-28] | Review ID: 5864 | Head commit:
88d14e2🔴 Blocking Issues (2)
Issue 1 — CI FAILURE on current head commit
The latest CI workflow run (ID 13484) shows status: failure on head commit
88d14e2346f53e6be9eff3884be88a6993e91de2. All previous approvals (review IDs 5399, 5456, 5774) were on earlier commits and are now stale. All CI checks must be green on the head commit before this PR can be approved.Issue 2 — CHANGELOG.md data loss
The diff removes 8 [Unreleased] entries from other merged PRs:
TDD Non-AssertionError Guard Visibility (#8294)Parallel Behave Runner Log Noise Reduction (#8351)Wired StrategyActor into the real plan execution path (#828)ACMS / UKO API Documentation--format color ANSI Output (#7910)ContextTierService Thread Safety (#7547)PluginLoader entry point prefix validation (#7476)ActionRepository.update() (#4197)Additionally, historical version entries
[3.8.0]–[3.0.0]are being added — these should not be introduced by this bugfix PR. Thegit merge-file --unionconflict resolution (comment #214591) produced an incorrect result. Recommend a cleangit rebase origin/master.✅ All Other Criteria Pass
The implementation is architecturally correct:
frozen=TrueonNamespacedNameandPlanIdentity✅__setattr__onPlanTimestampsforcreated_at✅object.__setattr__in frozen validator ✅# type: ignore, full type annotations ✅Closes #7553, correct labels ✅Fix the two blocking issues and request re-review.
Automated by CleverAgents Bot
Supervisor: PR Review Pool | Agent: pr-reviewer
88d14e2346tob3e9884ffdCode Review: APPROVED ✅
Review focus: specification-compliance, requirements-coverage, behavior-correctness
Head commit:
b3e9884ffd49cba0551cc5532c01dff69311f033Stale review context: Previous REQUEST_CHANGES (review #5864) was posted against commit
88d14e2which is no longer the head. The current headb3e9884fhas been re-evaluated fresh.✅ CI Status — All 13 checks green (run 13624, 2026-04-17)
✅ Specification Compliance — Issue #7553 Acceptance Criteria
Plan.id(ULID) read-only after construction: Enforced viaPlanIdentityfrozen=True✅Plan.created_atread-only after construction: Enforced viaPlanTimestamps.__setattr__override raisingAttributeError✅Action.nameread-only after construction: Enforced viaNamespacedNamefrozen=True✅Action.namespaceread-only after construction: Enforced viaNamespacedNamefrozen=True✅phase,processing_state,updated_at,strategize_started_at, etc. all remain assignable ✅nox -s lintpasses ✅✅ Requirements Coverage — BDD Scenarios
17 Behave scenarios in
features/domain_model_immutability.featurecovering:plan_idimmutability and correct construction ✅root_plan_idauto-resolution toplan_idand immutability ✅created_atimmutability (raisesAttributeError) ✅updated_atandstrategize_started_atmutability ✅namespaced_name.nameandnamespaced_name.namespaceimmutability ✅namespaced_name.nameandnamespaced_name.namespaceimmutability ✅phaseandprocessing_statemutability ✅statemutability ✅All step definitions use
setattr()for frozen-field mutation attempts — no# type: ignorecomments anywhere in the diff ✅✅ Behavior Correctness
NamespacedName(frozen=True):nameandnamespaceraiseValidationError/TypeErroron post-construction reassignment ✅PlanIdentity(frozen=True):plan_id,parent_plan_id,root_plan_idraiseValidationError/TypeErroron reassignment ✅resolve_root_plan_idvalidator correctly usesobject.__setattr__— required pattern for frozen Pydantic v2 models ✅PlanTimestamps(selective__setattr__override):created_atraisesAttributeErrorwith descriptive message on post-construction assignment ✅object.__setattr__internally during__init__, so the override fires only for post-construction assignments — architecturally sound ✅super().__setattr__()delegation ✅✅ PR Metadata
Closes #7553present in PR body ✅Type/Bug✅Priority/High,State/In Review,MoSCoW/Must have✅fix(domain): enforce immutability on Plan and Action identity fields— valid Conventional Changelog format ✅fix/m2/domain-model-immutabilitymatches issue metadata ✅true✅✅ Code Quality
# type: ignorecomments — all 6 previously-flagged occurrences replaced withsetattr()calls ✅B010Ruff waiver correctly scoped tofeatures/steps/*.pyonly — intentional pattern for testing frozen model enforcement ✅-> Noneon all step functions ✅from __future__ import annotationspresent ✅[Unreleased] > Fixed✅Note on Previous REQUEST_CHANGES (review #5864)
Review #5864 was posted against commit
88d14e2(now stale — not the current head). The two blocking issues it raised (CI failure on88d14e2and CHANGELOG.md data loss on88d14e2) do not apply to the current headb3e9884f. The current diff shows a clean CHANGELOG.md with only the relevant addition, and CI is fully green on the current head.All quality gates pass. Implementation is architecturally correct and fully satisfies the acceptance criteria of issue #7553. This PR is ready to merge.
Automated by CleverAgents Bot
Supervisor: PR Review Pool | Agent: pr-reviewer
Code Review Decision: APPROVED ✅
Formal review posted as review ID 6088 on head commit
b3e9884ffd49cba0551cc5532c01dff69311f033.Review focus: specification-compliance, requirements-coverage, behavior-correctness
All criteria satisfied:
Plan.id,Plan.created_at,Action.name,Action.namespaceread-only after construction)frozen=TrueonNamespacedNameandPlanIdentity; selective__setattr__onPlanTimestampsforcreated_at;object.__setattr__in frozen validator# type: ignorecomments — replaced withsetattr()callsCloses #7553present in PR bodyType/Bug,Priority/High,State/In Review,MoSCoW/Must have[Unreleased] > FixedtrueNote on stale review #5864: That review was posted against commit
88d14e2(not the current head). Its blocking issues (CI failure and CHANGELOG.md data loss on that commit) do not apply to the current headb3e9884f, which has clean CI and a correct CHANGELOG.md diff.This PR is ready to merge.
Automated by CleverAgents Bot
Supervisor: PR Review Pool | Agent: pr-reviewer
b3e9884ffdtoc6f08ccb04c6f08ccb04to4675ee02a78215e13da9to813faa4853