TDD: A2aLocalFacade._handle_plan_prompt uses **prompt_payload unpacking that can silently overwrite plan_id, guidance, and status response keys #10403

Open
opened 2026-04-18 09:30:59 +00:00 by HAL9000 · 1 comment
Owner

Metadata

Field Value
Branch test/a2a-facade-plan-prompt-payload-overwrite-tdd
Commit Message test(a2a/facade): add @tdd_expected_fail scenario for _handle_plan_prompt **prompt_payload overwriting response keys
Milestone v3.5.0
Parent Epic

Background and Context

A2aLocalFacade._handle_plan_prompt() in src/cleveragents/a2a/facade.py uses **prompt_payload dict unpacking to merge the result of svc.prompt_plan() into the response dict. If svc.prompt_plan() returns a dict containing keys plan_id, guidance, or status, those keys will silently overwrite the values already set in the response, causing data corruption.

Current code (src/cleveragents/a2a/facade.py):

def _handle_plan_prompt(self, params: dict[str, Any]) -> dict[str, Any]:
    plan_id = params.get("plan_id", "")
    guidance = params.get("guidance", "")
    svc = self._plan_lifecycle_service
    if svc is not None and plan_id:
        prompt_payload = svc.prompt_plan(plan_id, guidance)
        return {
            "plan_id": plan_id,
            "guidance": guidance,
            "status": "guidance_injected",
            **prompt_payload,  # ← BUG: can overwrite plan_id, guidance, status
        }
    return {
        "plan_id": plan_id,
        "guidance": guidance,
        "status": "guidance_injected",
        "stub": True,
    }

If svc.prompt_plan() returns {"plan_id": "different_id", "status": "error", "guidance": ""}, the response will have the wrong plan_id, status, and guidance values. The caller receives corrupted data with no indication that overwriting occurred.

Expected Behavior

A Behave scenario tagged @tdd_issue @tdd_issue_N @tdd_expected_fail should:

  1. Create an A2aLocalFacade with a mock plan_lifecycle_service where prompt_plan() returns {"plan_id": "OVERWRITTEN", "status": "error"}
  2. Call dispatch() with _cleveragents/plan/prompt and a specific plan_id
  3. Assert that response.result["plan_id"] equals the original plan_id (not "OVERWRITTEN")
  4. Assert that response.result["status"] equals "guidance_injected" (not "error")

This test must fail on the current codebase (because **prompt_payload overwrites the keys), confirming the bug exists.

Acceptance Criteria

  • A Behave scenario tagged @tdd_issue, @tdd_issue_N, and @tdd_expected_fail exists
  • The scenario uses a mock prompt_plan() that returns conflicting keys
  • The scenario asserts that plan_id and status are NOT overwritten by the payload
  • The scenario fails on the current codebase (confirming the bug)
  • The scenario passes after the fix is applied

Subtasks

  • Create feature file with scenario tagged @tdd_issue @tdd_issue_N @tdd_expected_fail
  • Write the scenario with a mock service returning conflicting keys
  • Implement step definitions
  • Verify the scenario fails on the current codebase
  • Run nox -s unit_tests to confirm no regressions

Definition of Done

This issue is complete when:

  • All subtasks above are completed and checked off.
  • The failing Behave scenario is committed on the branch test/a2a-facade-plan-prompt-payload-overwrite-tdd.
  • The scenario is tagged correctly.
  • The scenario fails before the fix and passes after the fix is applied.

Automated by CleverAgents Bot
Agent: new-issue-creator

## Metadata | Field | Value | |---|---| | **Branch** | `test/a2a-facade-plan-prompt-payload-overwrite-tdd` | | **Commit Message** | `test(a2a/facade): add @tdd_expected_fail scenario for _handle_plan_prompt **prompt_payload overwriting response keys` | | **Milestone** | v3.5.0 | | **Parent Epic** | — | ## Background and Context `A2aLocalFacade._handle_plan_prompt()` in `src/cleveragents/a2a/facade.py` uses `**prompt_payload` dict unpacking to merge the result of `svc.prompt_plan()` into the response dict. If `svc.prompt_plan()` returns a dict containing keys `plan_id`, `guidance`, or `status`, those keys will silently overwrite the values already set in the response, causing data corruption. **Current code** (`src/cleveragents/a2a/facade.py`): ```python def _handle_plan_prompt(self, params: dict[str, Any]) -> dict[str, Any]: plan_id = params.get("plan_id", "") guidance = params.get("guidance", "") svc = self._plan_lifecycle_service if svc is not None and plan_id: prompt_payload = svc.prompt_plan(plan_id, guidance) return { "plan_id": plan_id, "guidance": guidance, "status": "guidance_injected", **prompt_payload, # ← BUG: can overwrite plan_id, guidance, status } return { "plan_id": plan_id, "guidance": guidance, "status": "guidance_injected", "stub": True, } ``` If `svc.prompt_plan()` returns `{"plan_id": "different_id", "status": "error", "guidance": ""}`, the response will have the wrong `plan_id`, `status`, and `guidance` values. The caller receives corrupted data with no indication that overwriting occurred. ## Expected Behavior A Behave scenario tagged `@tdd_issue @tdd_issue_N @tdd_expected_fail` should: 1. Create an `A2aLocalFacade` with a mock `plan_lifecycle_service` where `prompt_plan()` returns `{"plan_id": "OVERWRITTEN", "status": "error"}` 2. Call `dispatch()` with `_cleveragents/plan/prompt` and a specific `plan_id` 3. Assert that `response.result["plan_id"]` equals the original `plan_id` (not `"OVERWRITTEN"`) 4. Assert that `response.result["status"]` equals `"guidance_injected"` (not `"error"`) This test **must fail** on the current codebase (because `**prompt_payload` overwrites the keys), confirming the bug exists. ## Acceptance Criteria - [ ] A Behave scenario tagged `@tdd_issue`, `@tdd_issue_N`, and `@tdd_expected_fail` exists - [ ] The scenario uses a mock `prompt_plan()` that returns conflicting keys - [ ] The scenario asserts that `plan_id` and `status` are NOT overwritten by the payload - [ ] The scenario **fails** on the current codebase (confirming the bug) - [ ] The scenario **passes** after the fix is applied ## Subtasks - [ ] Create feature file with scenario tagged `@tdd_issue @tdd_issue_N @tdd_expected_fail` - [ ] Write the scenario with a mock service returning conflicting keys - [ ] Implement step definitions - [ ] Verify the scenario fails on the current codebase - [ ] Run `nox -s unit_tests` to confirm no regressions ## Definition of Done This issue is complete when: - All subtasks above are completed and checked off. - The failing Behave scenario is committed on the branch `test/a2a-facade-plan-prompt-payload-overwrite-tdd`. - The scenario is tagged correctly. - The scenario fails before the fix and passes after the fix is applied. --- **Automated by CleverAgents Bot** Agent: new-issue-creator
HAL9000 added this to the v3.5.0 milestone 2026-04-18 09:34:30 +00:00
Author
Owner

[GROOMED] Quality Analysis Complete

Issue Assessment

Valid & Actionable: This is a legitimate TDD issue describing a real data corruption bug in A2aLocalFacade._handle_plan_prompt() where **prompt_payload unpacking can silently overwrite critical response keys (plan_id, guidance, status).

Labels Applied

  • State/Unverified — Correct initial state for new issues
  • Type/Testing — Correct; this is a TDD (Test-Driven Development) issue
  • Priority/High — Correct; silent data corruption is high-priority

Milestone Assignment

  • v3.5.0 — Set per issue metadata table

Epic Assignment

  • None — Correct; issue explicitly states "Parent Epic: —"

Issue Quality

  • Well-documented with background, context, and buggy code example
  • Clear acceptance criteria with 4 checkpoints
  • Subtasks defined (feature file, scenario, step definitions, verification)
  • Definition of Done clearly stated
  • Branch and commit message specified

Grooming Summary

This issue is ready for development. All required labels are present, milestone is assigned, and the issue is well-structured for implementation. No additional triage needed.


Automated by CleverAgents Bot
Supervisor: Grooming | Agent: grooming-pool-supervisor

## [GROOMED] Quality Analysis Complete ### Issue Assessment ✅ **Valid & Actionable**: This is a legitimate TDD issue describing a real data corruption bug in `A2aLocalFacade._handle_plan_prompt()` where `**prompt_payload` unpacking can silently overwrite critical response keys (`plan_id`, `guidance`, `status`). ### Labels Applied - ✅ **State/Unverified** — Correct initial state for new issues - ✅ **Type/Testing** — Correct; this is a TDD (Test-Driven Development) issue - ✅ **Priority/High** — Correct; silent data corruption is high-priority ### Milestone Assignment - ✅ **v3.5.0** — Set per issue metadata table ### Epic Assignment - ✅ **None** — Correct; issue explicitly states "Parent Epic: —" ### Issue Quality - ✅ Well-documented with background, context, and buggy code example - ✅ Clear acceptance criteria with 4 checkpoints - ✅ Subtasks defined (feature file, scenario, step definitions, verification) - ✅ Definition of Done clearly stated - ✅ Branch and commit message specified ### Grooming Summary This issue is **ready for development**. All required labels are present, milestone is assigned, and the issue is well-structured for implementation. No additional triage needed. --- **Automated by CleverAgents Bot** Supervisor: Grooming | Agent: grooming-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#10403
No description provided.