From 12c956b5885e4f64c93e59cb45b42649474a2ff7 Mon Sep 17 00:00:00 2001 From: alvis Date: Tue, 12 May 2026 14:46:43 +0000 Subject: [PATCH] fix(clustering): drop TTL check from isUpToDate; task hash is the only signal MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If tasks haven't changed, the output is valid forever. If they changed, always recompute regardless of age. TTL on focus-area restored to 24h — it only controls recommender eligibility, not recompute frequency. Co-Authored-By: Claude Sonnet 4.6 --- ml/agents/focus_area.py | 2 +- services/api/src/routes/agent-outputs.ts | 7 ++----- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/ml/agents/focus_area.py b/ml/agents/focus_area.py index 4ee192b..b709e6a 100644 --- a/ml/agents/focus_area.py +++ b/ml/agents/focus_area.py @@ -37,7 +37,7 @@ MANIFEST = AgentManifest( context_schema=["todoist.tasks"], required_consents=["data:core", "data:todoist"], output_contract={"type": "snippet", "format": "free_text"}, - ttl_sec=3_600, + ttl_sec=86_400, inferred_params=[ InferredParam( key="preferred_areas", diff --git a/services/api/src/routes/agent-outputs.ts b/services/api/src/routes/agent-outputs.ts index fe49e15..e295e0e 100644 --- a/services/api/src/routes/agent-outputs.ts +++ b/services/api/src/routes/agent-outputs.ts @@ -165,17 +165,14 @@ function taskListHash(tasks: { content?: string }[]): string { } async function isUpToDate(userId: string, agentId: string, currentHash: string): Promise { - const now = new Date().toISOString(); const rows = await db - .select({ signalsSnapshot: agentOutputs.signalsSnapshot, expiresAt: agentOutputs.expiresAt }) + .select({ signalsSnapshot: agentOutputs.signalsSnapshot }) .from(agentOutputs) .where(and(eq(agentOutputs.userId, userId), eq(agentOutputs.agentId, agentId))) .limit(1); if (!rows.length) return false; - const row = rows[0]; - if (row.expiresAt <= now) return false; try { - const snapshot = JSON.parse(row.signalsSnapshot ?? '{}') as { _task_hash?: string }; + const snapshot = JSON.parse(rows[0].signalsSnapshot ?? '{}') as { _task_hash?: string }; return snapshot._task_hash === currentHash; } catch { return false; } }