Skip to content

Conversation

@frankbria
Copy link
Owner

@frankbria frankbria commented Jan 13, 2026

Summary

  • Fix interface mismatch between LeadAgent and worker agents where LeadAgent passed minimal dict (id/title/description only) but FrontendWorkerAgent and TestWorkerAgent expected Task objects with additional fields like project_id and task_number
  • Standardize all worker agents to accept Dict[str, Any] input, matching the existing pattern in BackendWorkerAgent and ReviewWorkerAgent
  • LeadAgent now uses task.to_dict() for complete task data instead of manually creating a minimal dict

Changes

File Change
codeframe/agents/lead_agent.py Use task.to_dict() instead of minimal dict
codeframe/agents/frontend_worker_agent.py Accept Dict[str, Any] instead of Task
codeframe/agents/test_worker_agent.py Accept Dict[str, Any] instead of Task
tests/agents/test_worker_task_dict_interface.py New test file (6 tests)
tests/agents/test_*_worker*.py Updated fixtures to use dicts

Test plan

  • All 467 agent tests passing
  • 6 new dict interface tests added
  • Ruff lint check passes
  • Integration test in CI

Summary by CodeRabbit

  • Refactor

    • Worker agents now accept task payloads as dictionaries (fields extracted for processing); internal handling standardized to dict-based task data.
    • Lead agent now forwards full task data when assigning work, which may affect agent selection.
  • Tests

    • Updated tests to use dictionary task inputs and added a comprehensive test suite validating the dict-based task interface.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 13, 2026

Walkthrough

Worker agents (FrontendWorkerAgent, TestWorkerAgent) now accept task inputs as dictionaries (Dict[str, Any]) instead of Task objects; LeadAgent now forwards full task data via task.to_dict(). Internal flows extract task_id/title/description from dicts and construct Task objects only when required (e.g., blockers).

Changes

Cohort / File(s) Summary
Worker agent signatures & internals
codeframe/agents/frontend_worker_agent.py, codeframe/agents/test_worker_agent.py
execute_task and _run_and_check_linting signatures changed to accept Dict[str, Any]; internal code extracts task_id, task_title, task_description from the dict and uses those fields for logging, broadcasts, linting, git workflow payloads, and blocker-related Task construction.
LeadAgent task payload
codeframe/agents/lead_agent.py
_assign_and_execute_task now uses task.to_dict() (full task dict) instead of a minimal partial dict when dispatching to worker agents/agent-type resolver.
Tests — updated inputs
tests/agents/test_frontend_worker_agent.py, tests/agents/test_frontend_worker_auto_commit.py, tests/agents/test_test_worker_agent.py, tests/agents/test_test_worker_auto_commit.py
Replaced Task model instances with dict-based task fixtures and adjusted test assertions/accessors to use dict key lookups; added project_id to test payloads where applicable.
Tests — new coverage
tests/agents/test_worker_task_dict_interface.py
New test module verifying LeadAgent emits complete task dicts, worker agents accept dict inputs, dict field access patterns, and Task.to_dict() contains required fields; extensive mocks and async test flows added.

Sequence Diagram(s)

(omitted — changes are refactor/signature updates without new multi-component control flow warranting a diagram)

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Poem

🐰 Hop, hop — dicts now dance from Lead to Worker bright,
Keys prance in logs and broadcasts, neat and light.
I nibble fields, assemble blockers with care,
Tasks flow as maps — a tidy, furry affair! ✨

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main change: standardizing worker agent task interfaces from Task objects to dictionaries, which is the primary objective of this PR.
Docstring Coverage ✅ Passed Docstring coverage is 90.63% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix/worker-agent-task-dict-interface

🧹 Recent nitpick comments
codeframe/agents/frontend_worker_agent.py (1)

102-117: Consider defensive handling for required dict keys.

Lines 103-105 use bracket notation (task["id"], task["title"], task["description"]) which will raise KeyError if any key is missing. While the caller (LeadAgent) should always provide these via task.to_dict(), defensive coding with .get() and validation could improve robustness.

💡 Optional: Add validation for required fields
         # Extract commonly used fields from task dict
-        task_id = task["id"]
-        task_title = task["title"]
-        task_description = task["description"]
+        task_id = task.get("id")
+        task_title = task.get("title", "")
+        task_description = task.get("description", "")
+
+        if task_id is None:
+            raise ValueError("Task dict must contain 'id' field")
codeframe/agents/test_worker_agent.py (1)

743-873: Consider extracting shared blocker workflow methods to base class.

The create_blocker, wait_for_blocker_resolution, and create_blocker_and_wait methods appear to be duplicated between FrontendWorkerAgent and TestWorkerAgent. Consider extracting these to the WorkerAgent base class to reduce duplication.

This is not blocking for this PR, which correctly focuses on the dict interface standardization.

📜 Recent review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 638714a and 4831820.

📒 Files selected for processing (8)
  • codeframe/agents/frontend_worker_agent.py
  • codeframe/agents/lead_agent.py
  • codeframe/agents/test_worker_agent.py
  • tests/agents/test_frontend_worker_agent.py
  • tests/agents/test_frontend_worker_auto_commit.py
  • tests/agents/test_test_worker_agent.py
  • tests/agents/test_test_worker_auto_commit.py
  • tests/agents/test_worker_task_dict_interface.py
🚧 Files skipped from review as they are similar to previous changes (3)
  • tests/agents/test_frontend_worker_auto_commit.py
  • tests/agents/test_worker_task_dict_interface.py
  • codeframe/agents/lead_agent.py
🧰 Additional context used
📓 Path-based instructions (1)
codeframe/**/*.py

📄 CodeRabbit inference engine (CLAUDE.md)

codeframe/**/*.py: Use Python 3.11+ for backend development
Use FastAPI framework for backend API development
Use SQLite with async support (aiosqlite) for database operations
Use tiktoken for token counting
Run linting with ruff check .
Import and use domain-specific repositories from codeframe/persistence/repositories/ for data access instead of direct database calls

Files:

  • codeframe/agents/frontend_worker_agent.py
  • codeframe/agents/test_worker_agent.py
🧠 Learnings (3)
📓 Common learnings
Learnt from: CR
Repo: frankbria/codeframe PR: 0
File: docs/CLAUDE.md:0-0
Timestamp: 2025-11-25T19:08:37.203Z
Learning: Implement Lead Agent for orchestration and Worker Agents for specialization (Backend, Frontend, Test, Review) with maturity levels D1-D4
📚 Learning: 2026-01-11T23:33:31.895Z
Learnt from: CR
Repo: frankbria/codeframe PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-11T23:33:31.895Z
Learning: Applies to tests/e2e/**/*.{ts,test.ts} : Use TEST_PROJECT_IDS.ACTIVE for tests requiring pre-seeded active phase with agents

Applied to files:

  • tests/agents/test_test_worker_auto_commit.py
📚 Learning: 2025-12-17T19:21:30.131Z
Learnt from: frankbria
Repo: frankbria/codeframe PR: 128
File: tests/agents/test_bottleneck_detection.py:486-500
Timestamp: 2025-12-17T19:21:30.131Z
Learning: In tests/agents/*.py, when testing bottleneck detection logic, ensure that tests exercising detect_bottlenecks are async and mock _get_agent_workload to return a value below AGENT_OVERLOAD_THRESHOLD (5) while providing a non-empty tasks list to prevent early return. This guarantees the code path for low workload is exercised and behavior under threshold is verified.

Applied to files:

  • tests/agents/test_test_worker_auto_commit.py
  • tests/agents/test_test_worker_agent.py
  • tests/agents/test_frontend_worker_agent.py
🧬 Code graph analysis (4)
codeframe/agents/frontend_worker_agent.py (1)
codeframe/core/models.py (3)
  • Task (257-305)
  • id (230-231)
  • title (242-243)
codeframe/agents/test_worker_agent.py (1)
codeframe/core/models.py (4)
  • project_id (234-235)
  • Task (257-305)
  • id (230-231)
  • title (242-243)
tests/agents/test_test_worker_agent.py (4)
tests/agents/test_test_worker_auto_commit.py (1)
  • test_agent (32-45)
tests/agents/test_worker_task_dict_interface.py (1)
  • test_agent (244-255)
codeframe/agents/test_worker_agent.py (1)
  • _broadcast_test_result (719-741)
tests/agents/test_frontend_worker_agent.py (1)
  • sample_task (44-63)
tests/agents/test_frontend_worker_agent.py (1)
codeframe/core/models.py (1)
  • AgentMaturity (25-31)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: Backend Unit Tests
  • GitHub Check: Frontend Unit Tests
  • GitHub Check: E2E Smoke Tests (Chromium)
  • GitHub Check: opencode-review
🔇 Additional comments (12)
tests/agents/test_test_worker_auto_commit.py (3)

11-11: LGTM!

Import correctly updated to remove Task (now replaced by dicts) while retaining AgentMaturity which is still used in the test_agent fixture.


60-79: Dict structure looks correct.

The task dictionary contains all required fields and properly aligns with the new dict-based interface. Note that project_id is specified both in the dict (line 62) and as an explicit parameter to execute_task() (line 94). This redundancy is harmless but worth being aware of for consistency—verify which source the agent implementation prioritizes.


130-149: LGTM!

Task dictionary is consistent with the first test case and correctly supports the self-correction scenario being tested.

codeframe/agents/frontend_worker_agent.py (3)

108-117: LGTM - Task object construction for blocker workflow.

The internal Task object is correctly constructed from the incoming dict for blocker-related workflows. The use of .get() with defaults for optional fields is appropriate.


185-192: LGTM - Explicit field selection for git_workflow.

The explicit dict construction provides clear control over which fields are passed to git_workflow.commit_task_changes(). While the incoming task is already a dict, this approach documents the expected interface.


455-472: LGTM - Consistent dict-based interface for linting method.

The _run_and_check_linting method signature and implementation are consistent with the execute_task refactor. The task_id extraction and usage throughout logging, DB operations, and broadcasts is correct.

tests/agents/test_frontend_worker_agent.py (2)

43-63: LGTM - Well-structured dict fixture matching task.to_dict() output.

The sample_task fixture correctly mirrors the Task.to_dict() output structure with all expected fields. The docstring clearly indicates this alignment with LeadAgent's usage pattern.


342-360: LGTM - Test coverage for JSON specification parsing.

The inline dict correctly structures a task with JSON-encoded description for testing the component spec parsing path.

codeframe/agents/test_worker_agent.py (2)

101-127: LGTM - Consistent dict-based interface implementation.

The execute_task method follows the same pattern as FrontendWorkerAgent:

  • Extracts required fields using bracket notation
  • Creates internal Task object for blocker workflows
  • Uses .get() with defaults for optional fields

This consistency across worker agents aligns well with the PR objective.


429-446: LGTM - Linting method consistent with FrontendWorkerAgent.

The _run_and_check_linting implementation follows the same dict-based pattern, ensuring consistency across worker agents.

tests/agents/test_test_worker_agent.py (2)

30-49: LGTM - Dict fixture consistent with frontend tests.

The sample_task fixture correctly returns a dict with all expected fields from Task.to_dict(). The structure is consistent with the fixture in test_frontend_worker_agent.py.


398-402: LGTM - Correct dict access pattern in test.

The test correctly uses sample_task["id"] to access the task ID from the dict fixture, aligning with the refactored interface.


Comment @coderabbitai help to get the list of available commands and usage tips.

@macroscopeapp
Copy link

macroscopeapp bot commented Jan 13, 2026

Standardize worker agents to accept task dictionaries by updating FrontendWorkerAgent.execute_task, FrontendWorkerAgent._run_and_check_linting, TestWorkerAgent.execute_task, TestWorkerAgent._run_and_check_linting, and passing Task.to_dict() from LeadAgent._assign_and_execute_task

Workers now treat tasks as dicts, accessing fields via subscripting and get(), and LeadAgent forwards full task dictionaries via Task.to_dict(). Logging, WebSocket payloads, and DB writes use dict-derived id, title, and description. New tests validate the dict interface across agents.

📍Where to Start

Start with FrontendWorkerAgent.execute_task in frontend_worker_agent.py, then review TestWorkerAgent.execute_task in test_worker_agent.py and the dict handoff in LeadAgent._assign_and_execute_task in lead_agent.py.


Macroscope summarized 4831820.

@github-actions
Copy link
Contributor

PR Review: Standardize Worker Agent Task Dict Interface

Summary

This PR fixes an interface mismatch where LeadAgent passed minimal task dicts (only id/title/description) to FrontendWorkerAgent and TestWorkerAgent, while those agents expected Task objects. The fix standardizes all worker agents to accept input.

✅ Strengths

1. Fixes Real Bug

  • Issue: FrontendWorkerAgent and TestWorkerAgent couldn't access critical fields like , ,
  • Solution: Use in LeadAgent to pass complete task data
  • Impact: Worker agents now have full task context for blocker creation, git commits, etc.

2. Consistent with Existing Patterns

  • BackendWorkerAgent already accepts
  • ReviewWorkerAgent already accepts
  • FrontendWorkerAgent and TestWorkerAgent now follow same pattern

3. Maintains Backward Compatibility

  • Both agents still create Task objects for (lines 107-117 in frontend_worker_agent.py)
  • Other methods using continue to work unchanged
  • Smart adaptation: Accept dict at entry point, preserve Task object internally

4. Good Test Coverage

  • 6 new tests in
  • Tests verify LeadAgent passes complete dict to workers
  • Tests verify workers correctly extract fields from dicts

⚠️ Minor Concerns

1. Base Class Signature Mismatch (Non-blocking)

  • WorkerAgent base class has (line 285-287)
  • But BackendWorkerAgent, ReviewWorkerAgent, and now FrontendWorkerAgent/TestWorkerAgent override with
  • The base class already handles both Task objects and dicts internally (lines 332-340), so this works, but type hints don't match

Recommendation: Consider updating base class signature to or adding a type alias for consistency. This is not a blocker for this PR.

2. Missing Fields in Task Object Creation
When creating Task objects from dicts (lines 107-117 in frontend_worker_agent.py):

Several fields from Task model are not included:

    • defaults to TaskStatus.TODO
    • defaults to 0
    • defaults to 0
  • , - defaults to None

Recommendation: Verify these defaults are acceptable. If these fields are needed for blocker creation or git operations, extract them from the dict.

3. Type Annotation for project_id Parameter
All worker agents now have:

But is also available in . Having it as a parameter could lead to confusion about which source of truth to use.

Recommendation: Consider removing the parameter entirely and always use . Alternatively, document clearly that the parameter takes precedence.

🔍 Code Quality

Positive:

  • Clean separation of concerns (dict input → Task object for internal use)
  • Good error handling (try/except around broadcasts)
  • Consistent with existing worker agent patterns
  • Updated all test fixtures to use dicts instead of Task objects

Minor Issues:

  • Variable shadowing in test_worker_agent.py line 525: in lint result call should use consistent naming
  • In frontend_worker_agent.py line 191-192, comment says "Task is already a dict" but the code manually constructs another dict - this is correct but the comment is slightly misleading

🧪 Test Coverage

Comprehensive:

  • 6 new tests covering LeadAgent task dict creation
  • Existing test fixtures updated to use dicts (test_frontend_worker_agent.py, test_test_worker_agent.py)
  • Tests verify complete task dict is passed (not just id/title/description)

Suggestion: Consider adding a test that verifies Task object created from dict has correct fields, especially if the missing fields (status, priority, etc.) are important.

🚀 Recommendation

Approve with Minor Suggestions:

  1. ✅ The core fix is sound and solves a real bug
  2. ✅ Test coverage is good
  3. ✅ Pattern is consistent with BackendWorkerAgent and ReviewWorkerAgent
  4. ℹ️ Consider the minor suggestions above for future iterations (not blocking)

This PR improves code quality by standardizing interfaces and fixing a bug where worker agents were missing critical task context. The changes are minimal, focused, and well-tested.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (5)
codeframe/agents/test_worker_agent.py (1)

196-203: Redundant dict construction — task is already a dict.

Since task is now a Dict[str, Any] input, reconstructing task_dict with the same fields is unnecessary. You can pass task directly or use a slice.

♻️ Simplify by passing task directly
-                    # Task is already a dict, extract fields for git_workflow
-                    task_dict = {
-                        "id": task_id,
-                        "project_id": task.get("project_id"),
-                        "task_number": task.get("task_number", ""),
-                        "title": task_title,
-                        "description": task_description,
-                    }
-
-                    commit_sha = self.git_workflow.commit_task_changes(
-                        task=task_dict, files_modified=files_modified, agent_id=self.agent_id
-                    )
+                    commit_sha = self.git_workflow.commit_task_changes(
+                        task=task, files_modified=files_modified, agent_id=self.agent_id
+                    )
tests/agents/test_frontend_worker_auto_commit.py (1)

11-11: Unused import: Task is no longer used in this file.

After migrating to dict-based tasks, the Task class is not instantiated or referenced. Consider removing the unused import.

♻️ Remove unused import
-from codeframe.core.models import Task, AgentMaturity
+from codeframe.core.models import AgentMaturity
tests/agents/test_frontend_worker_agent.py (1)

342-360: Minor inconsistency: Missing optional fields compared to sample_task fixture.

This task dict is missing several fields present in the sample_task fixture (e.g., depends_on, can_parallelize, requires_mcp, estimated_tokens, actual_tokens). While this works because FrontendWorkerAgent.execute_task uses .get() for optional fields, consider using consistent field sets across test fixtures for maintainability.

codeframe/agents/frontend_worker_agent.py (2)

91-117: Consider defensive handling for missing required dict keys.

The code extracts task["id"], task["title"], and task["description"] using direct dictionary access (lines 103-105), which will raise KeyError if any key is missing. While callers (LeadAgent via task.to_dict()) should always provide these, consider either:

  1. Using .get() with appropriate defaults/error handling, or
  2. Adding explicit validation with clear error messages

This would provide better debugging when integration issues arise.

♻️ Optional defensive validation
         # Extract commonly used fields from task dict
+        required_fields = ["id", "title", "description"]
+        missing = [f for f in required_fields if f not in task]
+        if missing:
+            raise ValueError(f"Task dict missing required fields: {missing}")
+
         task_id = task["id"]
         task_title = task["title"]
         task_description = task["description"]

185-192: Redundant task_dict construction.

The task parameter is already a dictionary. This code creates a new task_dict with a subset of fields, but task itself could be passed directly to git_workflow.commit_task_changes if that method accepts the full dict. If the subset is intentional (to avoid passing unnecessary fields), this is fine, but consider documenting why.

📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2da47ba and 638714a.

📒 Files selected for processing (8)
  • codeframe/agents/frontend_worker_agent.py
  • codeframe/agents/lead_agent.py
  • codeframe/agents/test_worker_agent.py
  • tests/agents/test_frontend_worker_agent.py
  • tests/agents/test_frontend_worker_auto_commit.py
  • tests/agents/test_test_worker_agent.py
  • tests/agents/test_test_worker_auto_commit.py
  • tests/agents/test_worker_task_dict_interface.py
🧰 Additional context used
📓 Path-based instructions (1)
codeframe/**/*.py

📄 CodeRabbit inference engine (CLAUDE.md)

codeframe/**/*.py: Use Python 3.11+ for backend development
Use FastAPI framework for backend API development
Use SQLite with async support (aiosqlite) for database operations
Use tiktoken for token counting
Run linting with ruff check .
Import and use domain-specific repositories from codeframe/persistence/repositories/ for data access instead of direct database calls

Files:

  • codeframe/agents/lead_agent.py
  • codeframe/agents/test_worker_agent.py
  • codeframe/agents/frontend_worker_agent.py
🧠 Learnings (1)
📚 Learning: 2025-12-17T19:21:30.131Z
Learnt from: frankbria
Repo: frankbria/codeframe PR: 128
File: tests/agents/test_bottleneck_detection.py:486-500
Timestamp: 2025-12-17T19:21:30.131Z
Learning: In tests/agents/*.py, when testing bottleneck detection logic, ensure that tests exercising detect_bottlenecks are async and mock _get_agent_workload to return a value below AGENT_OVERLOAD_THRESHOLD (5) while providing a non-empty tasks list to prevent early return. This guarantees the code path for low workload is exercised and behavior under threshold is verified.

Applied to files:

  • tests/agents/test_test_worker_auto_commit.py
  • tests/agents/test_test_worker_agent.py
  • tests/agents/test_worker_task_dict_interface.py
  • tests/agents/test_frontend_worker_agent.py
  • tests/agents/test_frontend_worker_auto_commit.py
🧬 Code graph analysis (4)
codeframe/agents/lead_agent.py (1)
codeframe/core/models.py (5)
  • to_dict (88-105)
  • to_dict (197-210)
  • to_dict (249-253)
  • to_dict (284-305)
  • to_dict (631-640)
codeframe/agents/test_worker_agent.py (2)
codeframe/core/models.py (4)
  • project_id (234-235)
  • Task (257-305)
  • id (230-231)
  • title (242-243)
codeframe/persistence/database.py (1)
  • update_task_commit_sha (426-428)
tests/agents/test_worker_task_dict_interface.py (1)
codeframe/core/models.py (2)
  • title (242-243)
  • id (230-231)
codeframe/agents/frontend_worker_agent.py (1)
codeframe/core/models.py (4)
  • project_id (234-235)
  • Task (257-305)
  • id (230-231)
  • title (242-243)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: opencode-review
  • GitHub Check: E2E Smoke Tests (Chromium)
  • GitHub Check: Macroscope - Correctness Check
🔇 Additional comments (21)
codeframe/agents/test_worker_agent.py (2)

101-127: Clean interface migration with proper Task reconstruction.

The dict-based interface aligns with BackendWorkerAgent and ReviewWorkerAgent. The internal Task object construction for self.current_task preserves blocker workflow compatibility while accepting the standardized dict input.


429-446: LGTM — consistent dict-based signature for linting method.

The _run_and_check_linting method signature update aligns with the parent execute_task change. Task ID extraction is handled correctly.

codeframe/agents/lead_agent.py (1)

2201-2203: Good fix — task.to_dict() provides complete task data.

Using task.to_dict() instead of a minimal dict ensures downstream workers receive all required fields (project_id, task_number, etc.) that they previously expected from Task objects.

tests/agents/test_test_worker_agent.py (2)

30-50: LGTM — fixture properly mirrors Task.to_dict() output.

The dict-based fixture includes all required fields (project_id, task_number, issue_id, etc.) that the updated execute_task method expects. This aligns with how LeadAgent now passes task data.


401-401: Correct update to dict key access.

Using sample_task["id"] is consistent with the fixture change from Task object to dict.

tests/agents/test_test_worker_auto_commit.py (2)

60-79: Test fixture updated correctly to dict format.

The dict includes all fields matching Task.to_dict() output. One minor note: depends_on: None differs from the Task model's default of "", but the implementation handles both gracefully via .get() and conditional checks.


130-149: Consistent dict structure across test cases.

Both test fixtures follow the same complete dict structure, ensuring consistent coverage of the dict-based interface.

tests/agents/test_frontend_worker_auto_commit.py (2)

61-80: LGTM — comprehensive dict-based test fixture.

The fixture includes all fields that Task.to_dict() produces, properly testing the updated execute_task interface.


123-142: Consistent fixture pattern maintained.

Both test cases use the same complete dict structure, ensuring thorough coverage of the dict-based interface.

tests/agents/test_frontend_worker_agent.py (3)

44-63: LGTM! Well-structured task dictionary fixture.

The sample_task fixture now correctly returns a dictionary matching the Task.to_dict() output format, which aligns with the PR objective of standardizing worker agents to accept Dict[str, Any] input. All essential fields are present including project_id, task_number, and other fields that were previously missing when LeadAgent passed minimal dicts.


375-387: Acceptable for error handling test.

The reduced field set is appropriate here since the test focuses on error handling when _create_component_files raises an exception, not on field access patterns.


445-457: Acceptable for file conflict test.

Similar to the error handling test, this reduced field set is appropriate since the test focuses on the "file already exists" error scenario.

tests/agents/test_worker_task_dict_interface.py (5)

1-13: Well-documented test module with clear purpose.

The docstring clearly explains the test objectives and the interface mismatch being addressed. This provides excellent context for future maintainers.


25-141: Comprehensive integration test for LeadAgent task dict creation.

This test effectively validates the critical fix: ensuring _assign_and_execute_task passes complete task dictionaries with all required fields (project_id, task_number, etc.) instead of minimal dicts. The assertions on lines 118-140 provide strong contract verification.

One consideration: The test accesses the private method _assign_and_execute_task directly. This is acceptable for verifying internal behavior changes, but be aware that refactoring the private method may break this test.


143-231: Good coverage for FrontendWorkerAgent dict interface.

The tests verify that execute_task accepts dict input without raising AttributeError for property access patterns (e.g., task.id vs task["id"]). The mock for _generate_react_component appropriately isolates the interface contract test from LLM dependencies.


233-331: Good coverage for TestWorkerAgent dict interface.

The nested mocking of both _generate_pytest_tests and _execute_and_correct_tests appropriately isolates the dict interface test. The test structure mirrors the FrontendWorkerAgent tests for consistency.


334-376: No issues found. The Task class is a standard dataclass with all required fields defined with appropriate defaults. The test correctly instantiates Task using keyword arguments, and the to_dict() method properly converts the status enum to its string value as expected by the assertions.

codeframe/agents/frontend_worker_agent.py (4)

107-117: Good approach: Creating Task object for backward compatibility.

Constructing a Task object for self.current_task maintains compatibility with the blocker creation workflow that depends on self.current_task.id and self.current_task.project_id. This is a sound design choice that allows incremental migration without breaking existing functionality.


228-230: Good: Renamed exception variable to avoid shadowing.

Renaming the inner exception to broadcast_err prevents shadowing the outer e exception variable, improving code clarity.


455-472: Consistent signature update for _run_and_check_linting.

The internal method signature correctly updated to accept Dict[str, Any], and task_id is extracted at the start of the method. This maintains consistency with execute_task.


584-713: Blocker methods still rely on self.current_task (Task object).

The create_blocker, wait_for_blocker_resolution, and create_blocker_and_wait methods access self.current_task.project_id and self.current_task.id. This works because execute_task now constructs a Task object and assigns it to self.current_task (lines 108-117).

However, if these blocker methods are ever called outside of an execute_task context (or if current_task is not set), the code will fail. The current design is acceptable given the flow, but consider documenting this dependency.

@frankbria frankbria linked an issue Jan 13, 2026 that may be closed by this pull request
Fix interface mismatch between LeadAgent and worker agents where:
- LeadAgent was passing minimal dict with only id/title/description
- FrontendWorkerAgent and TestWorkerAgent expected Task objects

Changes:
- LeadAgent now uses task.to_dict() for complete task data
- FrontendWorkerAgent.execute_task accepts Dict[str, Any]
- TestWorkerAgent.execute_task accepts Dict[str, Any]
- Updated all tests to use dict input instead of Task objects

This fixes AttributeError when workers accessed task.project_id,
task.task_number, etc. for git workflow operations.
@frankbria frankbria force-pushed the fix/worker-agent-task-dict-interface branch from 638714a to 4831820 Compare January 13, 2026 21:06
@github-actions
Copy link
Contributor

PR Review: Standardize Worker Agent Task Dict Interface

Overall Assessment: ✅ Approve with Minor Suggestions

This PR correctly fixes an interface mismatch where FrontendWorkerAgent and TestWorkerAgent couldn't access critical task fields (like project_id, task_number) because LeadAgent was passing minimal dicts. The standardization to Dict[str, Any] across all worker agents is consistent with BackendWorkerAgent and ReviewWorkerAgent patterns.


✅ Strengths

1. Fixes Real Bug

  • Using task.to_dict() in LeadAgent ensures workers receive complete task data
  • Test coverage validates that all required fields are present

2. Backward Compatibility Maintained

  • Both agents create Task objects internally for self.current_task (lines 107-117, 118-127)
  • Blocker methods continue to work unchanged

3. Good Test Coverage

  • 6 new tests verify LeadAgent emits complete dicts
  • Tests verify workers correctly extract fields from dicts
  • All existing test fixtures properly updated

⚠️ Minor Issues

1. Redundant Task Dict Construction (Non-blocking)

In frontend_worker_agent.py:186-192 and `test_worker_agent.py:197-203:

# Current code - creates new dict from existing dict
task_dict = {
    "id": task_id,
    "project_id": task.get("project_id"),
    "task_number": task.get("task_number", ""),
    "title": task_title,
    "description": task_description,
}

Since task is already a Dict[str, Any] with all required fields, you could pass it directly to commit_task_changes(). The git workflow's commit_task_changes method (workflow_manager.py:321-338) validates that required fields exist, so the subset construction is unnecessary unless there's a specific reason to limit the fields passed.

Suggestion: Consider passing task directly or documenting why the subset is intentional.


2. Unused Imports (Cleanup Opportunity)

  • tests/agents/test_frontend_worker_auto_commit.py:11 - Task imported but not used
  • tests/agents/test_test_worker_auto_commit.py:11 - Same issue

These can be removed since test fixtures now use dicts instead of Task objects.


3. Missing Defensive Validation (Optional)

In frontend_worker_agent.py:103-105 and test_worker_agent.py:113-115:

task_id = task["id"]
task_title = task["title"]
task_description = task["description"]

Direct dictionary access raises KeyError if fields are missing. While callers (LeadAgent via task.to_dict()) should always provide these, consider:

required_fields = ["id", "title", "description"]
missing = [f for f in required_fields if f not in task]
if missing:
    raise ValueError(f"Task dict missing required fields: {missing}")

This provides better debugging for integration issues.


🔍 Code Quality

Positive:

  • Clean separation of concerns (dict input → Task object for internal use)
  • Consistent with existing worker agent patterns
  • Good error handling with try/except around broadcasts
  • Well-documented test module with clear objectives

Minor:

  • In frontend_worker_agent.py:191, comment says "Task is already a dict" but then manually constructs another dict - the comment is slightly misleading (it should say "Extract fields for git workflow")

🧪 Test Coverage

Comprehensive:

  • 6 new tests covering LeadAgent task dict creation and worker agent dict interfaces
  • Existing test fixtures updated to use dicts
  • Tests verify complete task dict is passed (not just id/title/description)

Minor Gap: Consider adding a test verifying Task object created from dict has correct defaults for fields like status, priority, etc., especially if these fields are used elsewhere.


✅ Recommendation

Approve with Minor Suggestions:

  1. ✅ The core fix is sound and solves a real bug
  2. ✅ Test coverage is good (467 tests passing per PR description)
  3. ✅ Pattern is consistent with BackendWorkerAgent and ReviewWorkerAgent
  4. ℹ️ Consider the minor cleanup suggestions above for future iterations (not blocking)

This PR improves code quality by standardizing interfaces and fixing a bug where worker agents were missing critical task context. The changes are minimal, focused, and well-tested.

@github-actions
Copy link
Contributor

PR review posted: #267 (comment)

Summary: Approve with minor suggestions

✅ The fix correctly addresses the interface mismatch - LeadAgent now passes complete task dicts via task.to_dict() and both FrontendWorkerAgent and TestWorkerAgent accept Dict[str, Any] input.

✅ Backward compatibility is maintained by creating Task objects internally for self.current_task.

✅ Good test coverage (6 new tests, 467 total passing).

Minor suggestions for future cleanup:

  1. Redundant dict construction could be simplified in both agents
  2. Unused Task imports in test files
  3. Optional defensive validation for missing dict keys

The PR is ready to merge.

New%20session%20-%202026-01-13T21%3A06%3A38.995Z
opencode session  |  github run

@frankbria frankbria merged commit a107395 into main Jan 13, 2026
13 checks passed
@frankbria frankbria deleted the fix/worker-agent-task-dict-interface branch January 13, 2026 21:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[P1] FrontendWorkerAgent receives dict instead of Task object

2 participants