UAT: Plan.effective_profile_snapshot never populated on plan creation — audit trail incomplete #2819

Open
opened 2026-04-04 20:39:57 +00:00 by freemo · 0 comments
Owner

Metadata

  • Branch: fix/plan-lifecycle-effective-profile-snapshot-never-populated
  • Commit Message: fix(plan-lifecycle): populate effective_profile_snapshot at plan creation time to satisfy audit trail requirement
  • Milestone: v3.7.0
  • Parent Epic: #372

Bug Report

Background

The Plan domain model in src/cleveragents/domain/models/core/plan.py defines an effective_profile_snapshot field intended to capture a frozen JSON snapshot of the automation profile at plan creation time. This field is central to the spec's audit and reproducibility requirements: once a plan is created, the exact profile settings in effect must be preserved so that the plan can be reproduced or audited even if the profile definition changes later.

The field definition itself acknowledges the problem with an explicit code comment:

effective_profile_snapshot: str = Field(
    default="{}",
    description=(
        "Frozen JSON snapshot of the automation profile at plan creation time"
    ),
)
# NOTE: The default '{}' exists for backward compatibility with code
# paths that create Plan objects before the snapshot is populated.
# New plans SHOULD explicitly set this field to the resolved profile
# JSON at creation time; the empty default does not satisfy the spec
# intent of capturing a frozen profile for audit purposes.

Despite this note, PlanLifecycleService.use_action() in src/cleveragents/application/services/plan_lifecycle_service.py never sets effective_profile_snapshot when constructing a new Plan. The resolved AutomationProfileRef is available as resolved_profile at that point, but its full JSON snapshot is never captured.

Files Affected

  • src/cleveragents/domain/models/core/plan.pyPlan.effective_profile_snapshot field
  • src/cleveragents/application/services/plan_lifecycle_service.pyPlanLifecycleService.use_action()

Current Behavior

When PlanLifecycleService.use_action() constructs a new Plan(...), the effective_profile_snapshot argument is never passed. The field defaults to "{}" (empty JSON object) for every plan ever created. The resolved AutomationProfileRef is stored in plan.automation_profile (a reference), but the full profile settings snapshot is silently discarded.

Evidence: The Plan(...) constructor call in use_action() does not include effective_profile_snapshot=..., even though resolved_profile (an AutomationProfileRef) is available in scope at that point.

Expected Behavior (from spec)

Per docs/specification.md, plans must persist a frozen snapshot of the automation profile at creation time for audit and reproducibility purposes. The spec states that the profile is "locked to the plan" at creation time. Concretely:

  1. When use_action() creates a new Plan, it must serialize the resolved AutomationProfileRef to JSON and pass it as effective_profile_snapshot.
  2. All newly created plans must have a non-empty effective_profile_snapshot containing the full profile settings in effect at creation time.
  3. If the automation profile definition changes after plan creation, the snapshot must still reflect the original settings.

Impact

  1. Audit trail is broken: effective_profile_snapshot is always "{}" for all plans, making it useless for audit purposes.
  2. Reproducibility is lost: If the automation profile definition changes after plan creation, there is no record of what profile settings were in effect when the plan was created.
  3. Spec violation: This directly violates the spec's audit/reproducibility requirement for the plan lifecycle.

Subtasks

  • Locate the Plan(...) constructor call in PlanLifecycleService.use_action() and identify the resolved_profile variable
  • Serialize the resolved AutomationProfileRef to JSON (using .model_dump_json() or equivalent) and pass it as effective_profile_snapshot in the Plan(...) constructor
  • Verify that the effective_profile_snapshot field is correctly populated for all new plans created via use_action()
  • Add or update Behave unit test scenarios in features/ to assert that effective_profile_snapshot is non-empty and matches the resolved profile after plan creation
  • Ensure all nox stages pass (nox -e lint, nox -e typecheck, nox -e unit_tests, nox -e coverage_report)
  • Confirm test coverage remains ≥ 97%

Definition of Done

  • PlanLifecycleService.use_action() sets effective_profile_snapshot to the JSON-serialized resolved automation profile at plan creation time
  • No plan created via use_action() has effective_profile_snapshot == "{}"
  • Behave feature file covers the snapshot-population behaviour with at least one scenario
  • All nox stages pass
  • Coverage >= 97%

Automated by CleverAgents Bot
Supervisor: UAT Testing | Agent: ca-uat-tester

## Metadata - **Branch**: `fix/plan-lifecycle-effective-profile-snapshot-never-populated` - **Commit Message**: `fix(plan-lifecycle): populate effective_profile_snapshot at plan creation time to satisfy audit trail requirement` - **Milestone**: v3.7.0 - **Parent Epic**: #372 ## Bug Report ### Background The `Plan` domain model in `src/cleveragents/domain/models/core/plan.py` defines an `effective_profile_snapshot` field intended to capture a frozen JSON snapshot of the automation profile at plan creation time. This field is central to the spec's audit and reproducibility requirements: once a plan is created, the exact profile settings in effect must be preserved so that the plan can be reproduced or audited even if the profile definition changes later. The field definition itself acknowledges the problem with an explicit code comment: ```python effective_profile_snapshot: str = Field( default="{}", description=( "Frozen JSON snapshot of the automation profile at plan creation time" ), ) # NOTE: The default '{}' exists for backward compatibility with code # paths that create Plan objects before the snapshot is populated. # New plans SHOULD explicitly set this field to the resolved profile # JSON at creation time; the empty default does not satisfy the spec # intent of capturing a frozen profile for audit purposes. ``` Despite this note, `PlanLifecycleService.use_action()` in `src/cleveragents/application/services/plan_lifecycle_service.py` never sets `effective_profile_snapshot` when constructing a new `Plan`. The resolved `AutomationProfileRef` is available as `resolved_profile` at that point, but its full JSON snapshot is never captured. ### Files Affected - `src/cleveragents/domain/models/core/plan.py` — `Plan.effective_profile_snapshot` field - `src/cleveragents/application/services/plan_lifecycle_service.py` — `PlanLifecycleService.use_action()` ### Current Behavior When `PlanLifecycleService.use_action()` constructs a new `Plan(...)`, the `effective_profile_snapshot` argument is never passed. The field defaults to `"{}"` (empty JSON object) for every plan ever created. The resolved `AutomationProfileRef` is stored in `plan.automation_profile` (a reference), but the full profile settings snapshot is silently discarded. **Evidence**: The `Plan(...)` constructor call in `use_action()` does not include `effective_profile_snapshot=...`, even though `resolved_profile` (an `AutomationProfileRef`) is available in scope at that point. ### Expected Behavior (from spec) Per `docs/specification.md`, plans must persist a frozen snapshot of the automation profile at creation time for audit and reproducibility purposes. The spec states that the profile is "locked to the plan" at creation time. Concretely: 1. When `use_action()` creates a new `Plan`, it must serialize the resolved `AutomationProfileRef` to JSON and pass it as `effective_profile_snapshot`. 2. All newly created plans must have a non-empty `effective_profile_snapshot` containing the full profile settings in effect at creation time. 3. If the automation profile definition changes after plan creation, the snapshot must still reflect the original settings. ### Impact 1. **Audit trail is broken**: `effective_profile_snapshot` is always `"{}"` for all plans, making it useless for audit purposes. 2. **Reproducibility is lost**: If the automation profile definition changes after plan creation, there is no record of what profile settings were in effect when the plan was created. 3. **Spec violation**: This directly violates the spec's audit/reproducibility requirement for the plan lifecycle. ## Subtasks - [ ] Locate the `Plan(...)` constructor call in `PlanLifecycleService.use_action()` and identify the `resolved_profile` variable - [ ] Serialize the resolved `AutomationProfileRef` to JSON (using `.model_dump_json()` or equivalent) and pass it as `effective_profile_snapshot` in the `Plan(...)` constructor - [ ] Verify that the `effective_profile_snapshot` field is correctly populated for all new plans created via `use_action()` - [ ] Add or update Behave unit test scenarios in `features/` to assert that `effective_profile_snapshot` is non-empty and matches the resolved profile after plan creation - [ ] Ensure all nox stages pass (`nox -e lint`, `nox -e typecheck`, `nox -e unit_tests`, `nox -e coverage_report`) - [ ] Confirm test coverage remains ≥ 97% ## Definition of Done - [ ] `PlanLifecycleService.use_action()` sets `effective_profile_snapshot` to the JSON-serialized resolved automation profile at plan creation time - [ ] No plan created via `use_action()` has `effective_profile_snapshot == "{}"` - [ ] Behave feature file covers the snapshot-population behaviour with at least one scenario - [ ] All nox stages pass - [ ] Coverage >= 97% --- **Automated by CleverAgents Bot** Supervisor: UAT Testing | Agent: ca-uat-tester
freemo added this to the v3.7.0 milestone 2026-04-04 20:40:03 +00:00
freemo removed this from the v3.7.0 milestone 2026-04-07 00:42:10 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Blocks
Reference
cleveragents/cleveragents-core#2819
No description provided.