refactor(focus-area): output all clusters as context; remove scoring and preferred_areas
The agent no longer picks a winner — it summarises every cluster so the
orchestrator can decide what's relevant. Scoring by overdue count overlapped
with the overdue-task agent. preferred_areas (project-ID based, broken label
matching) removed entirely.
Output format: numbered list of areas with task titles included.
Snapshot: {cluster_count, clusters: [{label, task_count, tasks}]}.
Version bumped to 3.0.0; inferred_params cleared.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -627,86 +627,37 @@ class TestTimeOfDaySnippet:
|
||||
assert {"quiet_start", "quiet_end", "peak_hours", "tz"}.issubset(keys)
|
||||
|
||||
|
||||
# ── focus-area: preferred_areas wiring ───────────────────────────────────────
|
||||
# ── focus-area: cluster summary output ───────────────────────────────────────
|
||||
|
||||
class TestFocusAreaPreferredAreas:
|
||||
class TestFocusAreaOutput:
|
||||
agent = FocusAreaAgent()
|
||||
|
||||
def _task(self, content: str, project_id: str, is_overdue: bool = False) -> dict:
|
||||
return {"id": "t1", "content": content, "is_overdue": is_overdue,
|
||||
def _task(self, content: str, project_id: str) -> dict:
|
||||
return {"id": "t1", "content": content, "is_overdue": False,
|
||||
"task_age_days": 2.0, "priority": 1, "project_id": project_id}
|
||||
|
||||
def test_preferred_area_wins_tie(self):
|
||||
tasks = [
|
||||
self._task("Work thing", "work"),
|
||||
self._task("Home thing", "home"),
|
||||
]
|
||||
out = self.agent.compute(_inp(tasks=tasks, agent_prefs={"preferred_areas": ["work"]}))
|
||||
assert "work" in out.prompt_text
|
||||
assert "matches the user's stated focus preferences" in out.prompt_text
|
||||
|
||||
def test_no_preferred_areas_uses_congestion_score(self):
|
||||
tasks = [
|
||||
self._task("W1", "work"),
|
||||
self._task("H1", "home"),
|
||||
self._task("H2", "home"),
|
||||
]
|
||||
out = self.agent.compute(_inp(tasks=tasks))
|
||||
# home has more tasks → wins without any preference
|
||||
assert "home" in out.prompt_text
|
||||
|
||||
def test_snapshot_includes_preferred_areas(self):
|
||||
tasks = [self._task("T", "work")]
|
||||
out = self.agent.compute(_inp(tasks=tasks, agent_prefs={"preferred_areas": ["work"]}))
|
||||
assert out.signals_snapshot["preferred_areas"] == ["work"]
|
||||
|
||||
def test_version_bumped(self):
|
||||
def test_version(self):
|
||||
from ml.agents.focus_area import MANIFEST as FA_MANIFEST
|
||||
assert FA_MANIFEST.version == "2.1.0"
|
||||
assert FA_MANIFEST.version == "3.0.0"
|
||||
|
||||
def test_snapshot_uses_cluster_keys(self):
|
||||
def test_all_clusters_in_output(self):
|
||||
tasks = [self._task("Work thing", "work"), self._task("Home thing", "home")]
|
||||
out = self.agent.compute(_inp(tasks=tasks))
|
||||
assert "work" in out.prompt_text.lower()
|
||||
assert "home" in out.prompt_text.lower()
|
||||
|
||||
def test_task_titles_in_output(self):
|
||||
tasks = [self._task("Buy milk", "personal")]
|
||||
out = self.agent.compute(_inp(tasks=tasks))
|
||||
assert '"Buy milk"' in out.prompt_text
|
||||
|
||||
def test_snapshot_shape(self):
|
||||
tasks = [self._task("T", "work")]
|
||||
out = self.agent.compute(_inp(tasks=tasks))
|
||||
assert "top_cluster_label" in out.signals_snapshot
|
||||
assert "cluster_count" in out.signals_snapshot
|
||||
assert "strategy" in out.signals_snapshot
|
||||
public_keys = {k for k in out.signals_snapshot if not k.startswith("_")}
|
||||
assert public_keys == {"cluster_count", "clusters"}
|
||||
assert isinstance(out.signals_snapshot["clusters"], list)
|
||||
|
||||
|
||||
# ── focus-area: preferred_areas inference from task_completions (#113) ────────
|
||||
|
||||
class TestFocusAreaPreferredAreasInference:
|
||||
from ml.agents.focus_area import MANIFEST as _FA_MANIFEST
|
||||
|
||||
def _completion(self, project_id: str) -> TaskCompletion:
|
||||
return _completion(project_id, lateness_days=0.0)
|
||||
|
||||
def test_cold_start_no_completions(self):
|
||||
history = _history(completions=[])
|
||||
def test_no_inferred_params(self):
|
||||
from ml.agents.focus_area import MANIFEST as FA_MANIFEST
|
||||
result = run_inference(FA_MANIFEST, history)
|
||||
assert result["preferred_areas"] == []
|
||||
|
||||
def test_top_two_projects_returned(self):
|
||||
completions = (
|
||||
[_completion("p1", 0)] * 8
|
||||
+ [_completion("p2", 0)] * 5
|
||||
+ [_completion("p3", 0)] * 2
|
||||
)
|
||||
history = _history(completions=completions)
|
||||
from ml.agents.focus_area import MANIFEST as FA_MANIFEST
|
||||
result = run_inference(FA_MANIFEST, history)
|
||||
assert result["preferred_areas"] == ["p1", "p2"]
|
||||
|
||||
def test_single_project_returns_one(self):
|
||||
completions = [_completion("work", 0)] * 6
|
||||
history = _history(completions=completions)
|
||||
from ml.agents.focus_area import MANIFEST as FA_MANIFEST
|
||||
result = run_inference(FA_MANIFEST, history)
|
||||
assert result["preferred_areas"] == ["work"]
|
||||
|
||||
def test_none_project_id_ignored(self):
|
||||
completions = [_completion(None, 0)] * 5 + [_completion("real", 0)] * 3
|
||||
history = _history(completions=completions)
|
||||
from ml.agents.focus_area import MANIFEST as FA_MANIFEST
|
||||
result = run_inference(FA_MANIFEST, history)
|
||||
assert result["preferred_areas"] == ["real"]
|
||||
assert FA_MANIFEST.inferred_params == []
|
||||
|
||||
Reference in New Issue
Block a user