feat(types): Resolve strict mypy errors in conductor subsystem
This commit is contained in:
@@ -15,11 +15,11 @@
|
|||||||
- [x] WHAT: Add explicit type hints to all function arguments, return values, and complex dictionaries. Resolve `Any` bleeding.
|
- [x] WHAT: Add explicit type hints to all function arguments, return values, and complex dictionaries. Resolve `Any` bleeding.
|
||||||
- [x] HOW: Surgical type annotations (`dict[str, Any]`, `list[str]`, etc.).
|
- [x] HOW: Surgical type annotations (`dict[str, Any]`, `list[str]`, etc.).
|
||||||
- [x] SAFETY: Do not change runtime logic, only type signatures.
|
- [x] SAFETY: Do not change runtime logic, only type signatures.
|
||||||
- [ ] Task: Resolve Conductor Subsystem Type Errors
|
- [x] Task: Resolve Conductor Subsystem Type Errors
|
||||||
- [ ] WHERE: `conductor_tech_lead.py`, `dag_engine.py`, `orchestrator_pm.py`
|
- [x] WHERE: `conductor_tech_lead.py`, `dag_engine.py`, `orchestrator_pm.py`
|
||||||
- [ ] WHAT: Enforce strict typing on track state, tickets, and DAG models.
|
- [x] WHAT: Enforce strict typing on track state, tickets, and DAG models.
|
||||||
- [ ] HOW: Standard python typing imports.
|
- [x] HOW: Standard python typing imports.
|
||||||
- [ ] SAFETY: Preserve JSON serialization compatibility.
|
- [x] SAFETY: Preserve JSON serialization compatibility.
|
||||||
- [ ] Task: Conductor - User Manual Verification 'Phase 2: Core Library' (Protocol in workflow.md)
|
- [ ] Task: Conductor - User Manual Verification 'Phase 2: Core Library' (Protocol in workflow.md)
|
||||||
|
|
||||||
## Phase 3: GUI God-Object Typing Resolution
|
## Phase 3: GUI God-Object Typing Resolution
|
||||||
|
|||||||
@@ -2,8 +2,9 @@ import json
|
|||||||
import ai_client
|
import ai_client
|
||||||
import mma_prompts
|
import mma_prompts
|
||||||
import re
|
import re
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
def generate_tickets(track_brief: str, module_skeletons: str) -> list[dict]:
|
def generate_tickets(track_brief: str, module_skeletons: str) -> list[dict[str, Any]]:
|
||||||
"""
|
"""
|
||||||
Tier 2 (Tech Lead) call.
|
Tier 2 (Tech Lead) call.
|
||||||
Breaks down a Track Brief and module skeletons into discrete Tier 3 Tickets.
|
Breaks down a Track Brief and module skeletons into discrete Tier 3 Tickets.
|
||||||
@@ -18,7 +19,7 @@ def generate_tickets(track_brief: str, module_skeletons: str) -> list[dict]:
|
|||||||
)
|
)
|
||||||
# Set custom system prompt for this call
|
# Set custom system prompt for this call
|
||||||
old_system_prompt = ai_client._custom_system_prompt
|
old_system_prompt = ai_client._custom_system_prompt
|
||||||
ai_client.set_custom_system_prompt(system_prompt)
|
ai_client.set_custom_system_prompt(system_prompt or "")
|
||||||
ai_client.current_tier = "Tier 2"
|
ai_client.current_tier = "Tier 2"
|
||||||
try:
|
try:
|
||||||
# 3. Call Tier 2 Model
|
# 3. Call Tier 2 Model
|
||||||
@@ -38,20 +39,20 @@ def generate_tickets(track_brief: str, module_skeletons: str) -> list[dict]:
|
|||||||
match = re.search(r'\[\s*\{.*\}\s*\]', json_match, re.DOTALL)
|
match = re.search(r'\[\s*\{.*\}\s*\]', json_match, re.DOTALL)
|
||||||
if match:
|
if match:
|
||||||
json_match = match.group(0)
|
json_match = match.group(0)
|
||||||
tickets = json.loads(json_match)
|
tickets: list[dict[str, Any]] = json.loads(json_match)
|
||||||
return tickets
|
return tickets
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"Error parsing Tier 2 response: {e}")
|
print(f"Error parsing Tier 2 response: {e}")
|
||||||
return []
|
return []
|
||||||
finally:
|
finally:
|
||||||
# Restore old system prompt and clear tier tag
|
# Restore old system prompt and clear tier tag
|
||||||
ai_client.set_custom_system_prompt(old_system_prompt)
|
ai_client.set_custom_system_prompt(old_system_prompt or "")
|
||||||
ai_client.current_tier = None
|
ai_client.current_tier = None
|
||||||
|
|
||||||
from dag_engine import TrackDAG
|
from dag_engine import TrackDAG
|
||||||
from models import Ticket
|
from models import Ticket
|
||||||
|
|
||||||
def topological_sort(tickets: list[dict]) -> list[dict]:
|
def topological_sort(tickets: list[dict[str, Any]]) -> list[dict[str, Any]]:
|
||||||
"""
|
"""
|
||||||
Sorts a list of tickets based on their 'depends_on' field.
|
Sorts a list of tickets based on their 'depends_on' field.
|
||||||
Raises ValueError if a circular dependency or missing internal dependency is detected.
|
Raises ValueError if a circular dependency or missing internal dependency is detected.
|
||||||
@@ -76,4 +77,3 @@ if __name__ == "__main__":
|
|||||||
test_skeletons = "class NewFeature: pass"
|
test_skeletons = "class NewFeature: pass"
|
||||||
tickets = generate_tickets(test_brief, test_skeletons)
|
tickets = generate_tickets(test_brief, test_skeletons)
|
||||||
print(json.dumps(tickets, indent=2))
|
print(json.dumps(tickets, indent=2))
|
||||||
|
|
||||||
|
|||||||
@@ -96,7 +96,7 @@ class TrackDAG:
|
|||||||
visited = set()
|
visited = set()
|
||||||
stack = []
|
stack = []
|
||||||
|
|
||||||
def visit(ticket_id: str):
|
def visit(ticket_id: str) -> None:
|
||||||
"""Internal recursive helper for topological sorting."""
|
"""Internal recursive helper for topological sorting."""
|
||||||
if ticket_id in visited:
|
if ticket_id in visited:
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import mma_prompts
|
|||||||
import aggregate
|
import aggregate
|
||||||
import summarize
|
import summarize
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
from typing import Any, Optional
|
||||||
|
|
||||||
CONDUCTOR_PATH: Path = Path("conductor")
|
CONDUCTOR_PATH: Path = Path("conductor")
|
||||||
|
|
||||||
@@ -53,7 +54,7 @@ def get_track_history_summary() -> str:
|
|||||||
return "No previous tracks found."
|
return "No previous tracks found."
|
||||||
return "\n".join(summary_parts)
|
return "\n".join(summary_parts)
|
||||||
|
|
||||||
def generate_tracks(user_request: str, project_config: dict, file_items: list[dict], history_summary: str = None) -> list[dict]:
|
def generate_tracks(user_request: str, project_config: dict[str, Any], file_items: list[dict[str, Any]], history_summary: Optional[str] = None) -> list[dict[str, Any]]:
|
||||||
"""
|
"""
|
||||||
Tier 1 (Strategic PM) call.
|
Tier 1 (Strategic PM) call.
|
||||||
Analyzes the project state and user request to generate a list of Tracks.
|
Analyzes the project state and user request to generate a list of Tracks.
|
||||||
@@ -72,7 +73,7 @@ def generate_tracks(user_request: str, project_config: dict, file_items: list[di
|
|||||||
user_message = "\n".join(user_message_parts)
|
user_message = "\n".join(user_message_parts)
|
||||||
# Set custom system prompt for this call
|
# Set custom system prompt for this call
|
||||||
old_system_prompt = ai_client._custom_system_prompt
|
old_system_prompt = ai_client._custom_system_prompt
|
||||||
ai_client.set_custom_system_prompt(system_prompt)
|
ai_client.set_custom_system_prompt(system_prompt or "")
|
||||||
try:
|
try:
|
||||||
# 3. Call Tier 1 Model (Strategic - Pro)
|
# 3. Call Tier 1 Model (Strategic - Pro)
|
||||||
# Note: We use gemini-1.5-pro or similar high-reasoning model for Tier 1
|
# Note: We use gemini-1.5-pro or similar high-reasoning model for Tier 1
|
||||||
@@ -89,7 +90,7 @@ def generate_tracks(user_request: str, project_config: dict, file_items: list[di
|
|||||||
json_match = json_match.split("```json")[1].split("```")[0].strip()
|
json_match = json_match.split("```json")[1].split("```")[0].strip()
|
||||||
elif "```" in json_match:
|
elif "```" in json_match:
|
||||||
json_match = json_match.split("```")[1].split("```")[0].strip()
|
json_match = json_match.split("```")[1].split("```")[0].strip()
|
||||||
tracks = json.loads(json_match)
|
tracks: list[dict[str, Any]] = json.loads(json_match)
|
||||||
# Ensure each track has a 'title' for the GUI
|
# Ensure each track has a 'title' for the GUI
|
||||||
for t in tracks:
|
for t in tracks:
|
||||||
if "title" not in t:
|
if "title" not in t:
|
||||||
@@ -101,7 +102,7 @@ def generate_tracks(user_request: str, project_config: dict, file_items: list[di
|
|||||||
return []
|
return []
|
||||||
finally:
|
finally:
|
||||||
# Restore old system prompt
|
# Restore old system prompt
|
||||||
ai_client.set_custom_system_prompt(old_system_prompt)
|
ai_client.set_custom_system_prompt(old_system_prompt or "")
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
# Quick CLI test
|
# Quick CLI test
|
||||||
|
|||||||
Reference in New Issue
Block a user