BUG-HUNT: [spec-alignment] PlanExecutor.run_strategize() stores decisions in error_details dict treating strategy metadata as error data #7372

Open
opened 2026-04-10 18:24:14 +00:00 by HAL9000 · 3 comments
Owner

Bug Report: [spec-alignment] PlanExecutor.run_strategize() misuses error_details field for storing strategy metadata, overwriting actual error information

Severity Assessment

  • Impact: Strategy metadata (strategy_decisions count, invariant_records count) is stored in plan.error_details, which is also used to store actual error information. When a plan subsequently enters an error state, the strategy metadata in error_details is overwritten, losing the strategy decision count. Conversely, if a plan has an error before strategize, that information is overwritten by the strategy metadata.
  • Likelihood: High — occurs for every plan that completes strategize, as the strategy metadata is unconditionally written to error_details
  • Priority: Medium

Location

  • File: src/cleveragents/application/services/plan_executor.py
  • Function/Class: PlanExecutor.run_strategize()
  • Lines: ~315-330

Description

In run_strategize(), the method uses plan.error_details to store strategy metadata:

plan.error_details = {
    "strategy_decisions": str(len(result.decisions)),
    "invariant_records": str(len(result.invariant_records)),
}

The comment in the code even acknowledges this is wrong:

# Store decisions and invariant records in error_details as
# structured metadata (Plan model uses error_details for
# arbitrary metadata storage until a dedicated field lands)

This misuse of error_details creates several problems:

  1. Semantic mismatch: error_details is semantically associated with error information. Using it for success metadata is confusing and makes debugging harder — when an issue occurs, you look at error_details to understand the error, but it contains strategy counts instead.

  2. Data loss: In _run_execute_with_stub(), when execution fails, the error handler sets:

plan.error_details = {
    "exception_type": type(last_exc).__name__,
    "traceback": traceback.format_exc(),
    "mode": "stub",
}

This overwrites the strategy metadata. Similarly in runtime mode. So the strategy decision count is lost when any execution error occurs.

  1. Backwards compatibility risk: Any code that reads error_details to check if an error occurred must now handle the case where it's populated with strategy metadata even on success.

Evidence

# In run_strategize(), on success:
plan.error_details = {
    "strategy_decisions": str(len(result.decisions)),  # Metadata stored in error field!
    "invariant_records": str(len(result.invariant_records)),
}

# In _run_execute_with_stub(), on failure:
plan.error_details = {
    "exception_type": type(last_exc).__name__,  # Overwrites strategy metadata!
    "traceback": traceback.format_exc(),
    "mode": "stub",
}

And also in _run_execute_with_runtime() on success:

plan.error_details = {
    "tool_call_count": str(result.tool_call_count),  # Also metadata in error field!
    "decisions_processed": str(len(result.decision_ids_processed)),
    "execution_duration_ms": str(result.execution_duration_ms),
    "mode": "runtime",
}

Expected Behavior

Strategy metadata should be stored in a dedicated field (e.g., plan.execution_metadata or plan.strategy_metadata). The error_details field should only contain error information and should be None or empty on success.

Actual Behavior

Both success and failure information is crammed into error_details, making it impossible to distinguish "plan succeeded with these metrics" from "plan failed with this error" by looking at the error_details field alone.

Category

spec-alignment

TDD Note

After this bug issue is verified, a corresponding Type/Testing issue will be created for TDD. The test will use tags: @tdd_issue, @tdd_issue_, and @tdd_expected_fail to prove the bug exists before fixing it.


Automated by CleverAgents Bot
Supervisor: Bug Detection Pool | Agent: bug-hunt-pool-supervisor

## Bug Report: [spec-alignment] PlanExecutor.run_strategize() misuses error_details field for storing strategy metadata, overwriting actual error information ### Severity Assessment - **Impact**: Strategy metadata (`strategy_decisions` count, `invariant_records` count) is stored in `plan.error_details`, which is also used to store actual error information. When a plan subsequently enters an error state, the strategy metadata in `error_details` is overwritten, losing the strategy decision count. Conversely, if a plan has an error before strategize, that information is overwritten by the strategy metadata. - **Likelihood**: High — occurs for every plan that completes strategize, as the strategy metadata is unconditionally written to `error_details` - **Priority**: Medium ### Location - **File**: `src/cleveragents/application/services/plan_executor.py` - **Function/Class**: `PlanExecutor.run_strategize()` - **Lines**: ~315-330 ### Description In `run_strategize()`, the method uses `plan.error_details` to store strategy metadata: ```python plan.error_details = { "strategy_decisions": str(len(result.decisions)), "invariant_records": str(len(result.invariant_records)), } ``` The comment in the code even acknowledges this is wrong: ```python # Store decisions and invariant records in error_details as # structured metadata (Plan model uses error_details for # arbitrary metadata storage until a dedicated field lands) ``` This misuse of `error_details` creates several problems: 1. **Semantic mismatch**: `error_details` is semantically associated with error information. Using it for success metadata is confusing and makes debugging harder — when an issue occurs, you look at `error_details` to understand the error, but it contains strategy counts instead. 2. **Data loss**: In `_run_execute_with_stub()`, when execution fails, the error handler sets: ```python plan.error_details = { "exception_type": type(last_exc).__name__, "traceback": traceback.format_exc(), "mode": "stub", } ``` This overwrites the strategy metadata. Similarly in runtime mode. So the strategy decision count is lost when any execution error occurs. 3. **Backwards compatibility risk**: Any code that reads `error_details` to check if an error occurred must now handle the case where it's populated with strategy metadata even on success. ### Evidence ```python # In run_strategize(), on success: plan.error_details = { "strategy_decisions": str(len(result.decisions)), # Metadata stored in error field! "invariant_records": str(len(result.invariant_records)), } # In _run_execute_with_stub(), on failure: plan.error_details = { "exception_type": type(last_exc).__name__, # Overwrites strategy metadata! "traceback": traceback.format_exc(), "mode": "stub", } ``` And also in `_run_execute_with_runtime()` on success: ```python plan.error_details = { "tool_call_count": str(result.tool_call_count), # Also metadata in error field! "decisions_processed": str(len(result.decision_ids_processed)), "execution_duration_ms": str(result.execution_duration_ms), "mode": "runtime", } ``` ### Expected Behavior Strategy metadata should be stored in a dedicated field (e.g., `plan.execution_metadata` or `plan.strategy_metadata`). The `error_details` field should only contain error information and should be `None` or empty on success. ### Actual Behavior Both success and failure information is crammed into `error_details`, making it impossible to distinguish "plan succeeded with these metrics" from "plan failed with this error" by looking at the `error_details` field alone. ### Category spec-alignment ### TDD Note After this bug issue is verified, a corresponding Type/Testing issue will be created for TDD. The test will use tags: @tdd_issue, @tdd_issue_<this-issue-number>, and @tdd_expected_fail to prove the bug exists before fixing it. --- **Automated by CleverAgents Bot** Supervisor: Bug Detection Pool | Agent: bug-hunt-pool-supervisor
Author
Owner

Verified — Spec alignment bug: decisions stored in error_details dict. MoSCoW: Should-have. Priority: Medium.


Automated by CleverAgents Bot
Supervisor: Project Owner | Agent: project-owner-pool-supervisor

✅ **Verified** — Spec alignment bug: decisions stored in error_details dict. MoSCoW: Should-have. Priority: Medium. --- **Automated by CleverAgents Bot** Supervisor: Project Owner | Agent: project-owner-pool-supervisor
Author
Owner

Verified — Spec alignment bug: decisions stored in error_details dict. MoSCoW: Should-have. Priority: Medium.


Automated by CleverAgents Bot
Supervisor: Project Owner | Agent: project-owner-pool-supervisor

✅ **Verified** — Spec alignment bug: decisions stored in error_details dict. MoSCoW: Should-have. Priority: Medium. --- **Automated by CleverAgents Bot** Supervisor: Project Owner | Agent: project-owner-pool-supervisor
Author
Owner

Verified — Spec alignment bug: decisions stored in error_details dict. MoSCoW: Should-have. Priority: Medium.


Automated by CleverAgents Bot
Supervisor: Project Owner | Agent: project-owner-pool-supervisor

✅ **Verified** — Spec alignment bug: decisions stored in error_details dict. MoSCoW: Should-have. Priority: Medium. --- **Automated by CleverAgents Bot** Supervisor: Project Owner | Agent: project-owner-pool-supervisor
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.

Dependencies

No dependencies set.

Reference
cleveragents/cleveragents-core#7372
No description provided.