feat: add lead policy helpers

This commit is contained in:
Abhimanyu Saharan
2026-02-05 14:37:12 +05:30
parent d0fb0a50f4
commit 78e89427ba
3 changed files with 83 additions and 0 deletions

View File

@@ -0,0 +1,27 @@
from __future__ import annotations
import hashlib
from typing import Mapping
CONFIDENCE_THRESHOLD = 80
def compute_confidence(rubric_scores: Mapping[str, int]) -> int:
return int(sum(rubric_scores.values()))
def approval_required(*, confidence: int, is_external: bool, is_risky: bool) -> bool:
return is_external or is_risky or confidence < CONFIDENCE_THRESHOLD
def infer_planning(signals: Mapping[str, bool]) -> bool:
# Require at least two planning signals to avoid spam on general boards.
truthy = [key for key, value in signals.items() if value]
return len(truthy) >= 2
def task_fingerprint(title: str, description: str | None, board_id: str) -> str:
normalized_title = title.strip().lower()
normalized_desc = (description or "").strip().lower()
seed = f"{board_id}::{normalized_title}::{normalized_desc}"
return hashlib.sha256(seed.encode()).hexdigest()

View File

@@ -0,0 +1,6 @@
import sys
from pathlib import Path
ROOT = Path(__file__).resolve().parents[1]
if str(ROOT) not in sys.path:
sys.path.insert(0, str(ROOT))

View File

@@ -0,0 +1,50 @@
import hashlib
from app.services.lead_policy import (
approval_required,
compute_confidence,
infer_planning,
task_fingerprint,
)
def test_compute_confidence_sums_weights():
rubric = {
"clarity": 20,
"constraints": 15,
"completeness": 10,
"risk": 20,
"dependencies": 10,
"similarity": 5,
}
assert compute_confidence(rubric) == 80
def test_approval_required_for_low_confidence():
assert approval_required(confidence=79, is_external=False, is_risky=False)
assert not approval_required(confidence=85, is_external=False, is_risky=False)
def test_approval_required_for_external_or_risky():
assert approval_required(confidence=90, is_external=True, is_risky=False)
assert approval_required(confidence=90, is_external=False, is_risky=True)
def test_infer_planning_requires_signal_threshold():
signals = {
"goal_gap": True,
"recent_ambiguity": False,
"research_only": False,
"stalled_inbox": False,
}
assert infer_planning(signals) is False
signals["recent_ambiguity"] = True
assert infer_planning(signals) is True
def test_task_fingerprint_deterministic():
fp1 = task_fingerprint("Title", "Desc", "board-1")
fp2 = task_fingerprint("Title", "Desc", "board-1")
assert fp1 == fp2
assert fp1 == hashlib.sha256("board-1::title::desc".encode()).hexdigest()