feat(agents): p50-lateness tolerance + per-project realness for overdue-task (#115)
Replaces snooze-rate heuristic with p50 of actual task lateness (completedAt − dueAt).
Adds project_realness inference: projects with chronic lateness get realness < 1 and
the agent softens its snippet language from "overdue" to "past target date".
- TaskCompletion added to UserHistory with lateness_days computed property
- _infer_lateness_tolerance: p50 of task_completions, clipped at 0, float
- _infer_project_realness: per-project median lateness normalised by global median
- Both InferredParams use 7d TTL; cold_start = 0.0 / {}
- AgentInferRequest accepts task_completions; endpoint wires them through
- 12 new tests covering punctual/chronic/mixed users and language softening
- Agent bumped to v1.2.0
Closes #115
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -40,7 +40,7 @@ if _repo_root not in sys.path:
|
||||
|
||||
from ml.agents.base import AgentInput # noqa: E402
|
||||
from ml.agents.registry import get_agent, all_agents, all_manifests, get_manifest # noqa: E402
|
||||
from ml.agents.inference import run_inference, FeedbackEvent, UserHistory # noqa: E402
|
||||
from ml.agents.inference import run_inference, FeedbackEvent, TaskCompletion, UserHistory # noqa: E402
|
||||
|
||||
logging_config.configure()
|
||||
|
||||
@@ -141,7 +141,8 @@ class AgentComputeResponse(BaseModel):
|
||||
|
||||
class AgentInferRequest(BaseModel):
|
||||
user_id: str
|
||||
feedback_history: list[dict] = [] # [{action, dwell_ms, created_at}, …]
|
||||
feedback_history: list[dict] = [] # [{action, dwell_ms, created_at}, …]
|
||||
task_completions: list[dict] = [] # [{project_id, completed_at, due_at}, …]
|
||||
|
||||
|
||||
class AgentInferResponse(BaseModel):
|
||||
@@ -284,7 +285,15 @@ async def infer_agent(agent_id: str, req: AgentInferRequest) -> AgentInferRespon
|
||||
)
|
||||
for e in req.feedback_history
|
||||
]
|
||||
history = UserHistory(user_id=req.user_id, events=events)
|
||||
completions = [
|
||||
TaskCompletion(
|
||||
project_id=c.get("project_id"),
|
||||
completed_at=c.get("completed_at", ""),
|
||||
due_at=c.get("due_at", ""),
|
||||
)
|
||||
for c in req.task_completions
|
||||
]
|
||||
history = UserHistory(user_id=req.user_id, events=events, task_completions=completions)
|
||||
|
||||
t0 = __import__("time").monotonic()
|
||||
inferred = run_inference(manifest, history)
|
||||
|
||||
Reference in New Issue
Block a user