From 3836fa74edd9ce879ba6b4280988f7ccffe456b1 Mon Sep 17 00:00:00 2001 From: Oliver Le Date: Wed, 15 Apr 2026 02:09:13 -0700 Subject: [PATCH 1/4] fix(types): annotate rank_rules_for_draft to satisfy pyright The return type was list[tuple[object, float]] which made pyright reject attribute access on the unpacked rule (r.state, r.confidence, etc). Switch to the actual Lesson type (or Any if Lesson import is awkward). Unblocks PR #76 (cloud-split) which inherits this CI failure. Signed-off-by: Oliver Le --- src/gradata/hooks/jit_inject.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/gradata/hooks/jit_inject.py b/src/gradata/hooks/jit_inject.py index e2576276..e5fdc49c 100644 --- a/src/gradata/hooks/jit_inject.py +++ b/src/gradata/hooks/jit_inject.py @@ -26,6 +26,7 @@ import time from pathlib import Path +from gradata._types import Lesson from gradata.hooks._base import extract_message, resolve_brain_dir, run_hook from gradata.hooks._profiles import Profile @@ -96,13 +97,13 @@ def _float_env(name: str, default: float) -> float: def rank_rules_for_draft( - lessons: list, + lessons: list[Lesson], draft_text: str, *, k: int = DEFAULT_MAX_RULES, min_confidence: float = DEFAULT_MIN_CONFIDENCE, min_similarity: float = DEFAULT_MIN_SIMILARITY, -) -> list[tuple[object, float]]: +) -> list[tuple[Lesson, float]]: """Score each lesson against draft_text and return top-k above threshold. Returns a list of (lesson, similarity) tuples, highest first. A rule @@ -117,7 +118,7 @@ def rank_rules_for_draft( if not draft_tokens: return [] - scored: list[tuple[object, float]] = [] + scored: list[tuple[Lesson, float]] = [] for lesson in lessons: conf = getattr(lesson, "confidence", 0.0) if conf < min_confidence: From e61d861124cfdf470332511ad8e391cf36e58955 Mon Sep 17 00:00:00 2001 From: Oliver Le Date: Wed, 15 Apr 2026 02:14:39 -0700 Subject: [PATCH 2/4] fix(types): TYPE_CHECKING for Lesson + bool-narrow rule_context return - Move Lesson import into TYPE_CHECKING block (ruff TC001) - Cast scope-applies expression to bool to satisfy pyright reportReturnType - rule_context fix is pre-existing on main, blocking the same CI as PR #76 Signed-off-by: Oliver Le --- src/gradata/hooks/jit_inject.py | 6 +++++- src/gradata/rules/rule_context.py | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/gradata/hooks/jit_inject.py b/src/gradata/hooks/jit_inject.py index e5fdc49c..70f74f51 100644 --- a/src/gradata/hooks/jit_inject.py +++ b/src/gradata/hooks/jit_inject.py @@ -26,10 +26,14 @@ import time from pathlib import Path -from gradata._types import Lesson +from typing import TYPE_CHECKING + from gradata.hooks._base import extract_message, resolve_brain_dir, run_hook from gradata.hooks._profiles import Profile +if TYPE_CHECKING: + from gradata._types import Lesson + try: from gradata.enhancements.self_improvement import parse_lessons except ImportError: diff --git a/src/gradata/rules/rule_context.py b/src/gradata/rules/rule_context.py index 207a6e84..6da3c5ae 100644 --- a/src/gradata/rules/rule_context.py +++ b/src/gradata/rules/rule_context.py @@ -64,7 +64,7 @@ def _rule_matches_domain(rule: GraduatedRule, domain_norm: str) -> bool: if str(scope.get("domain", "")).strip().lower() == domain_norm: return True applies = str(scope.get("applies_to", "")).strip().lower() - return applies == domain_norm or (applies and applies.startswith(f"{domain_norm}:")) + return applies == domain_norm or bool(applies and applies.startswith(f"{domain_norm}:")) class RuleContext: From a188b1241be16724f4cdab4da08ac335a4c06577 Mon Sep 17 00:00:00 2001 From: Oliver Le Date: Wed, 15 Apr 2026 02:20:00 -0700 Subject: [PATCH 3/4] fix(types): group TYPE_CHECKING with stdlib imports (ruff I001) Signed-off-by: Oliver Le --- src/gradata/hooks/jit_inject.py | 1 - 1 file changed, 1 deletion(-) diff --git a/src/gradata/hooks/jit_inject.py b/src/gradata/hooks/jit_inject.py index 70f74f51..58a42e8f 100644 --- a/src/gradata/hooks/jit_inject.py +++ b/src/gradata/hooks/jit_inject.py @@ -25,7 +25,6 @@ import re import time from pathlib import Path - from typing import TYPE_CHECKING from gradata.hooks._base import extract_message, resolve_brain_dir, run_hook From 6a0c44e98e9b7049b82dde288567fa2015ab5af0 Mon Sep 17 00:00:00 2001 From: Oliver Le Date: Wed, 15 Apr 2026 02:38:39 -0700 Subject: [PATCH 4/4] refactor(rule_context): drop redundant bool() wrapper per CR startswith() already returns bool; the 'and applies' short-circuit is also redundant since startswith() on empty string is False for any non-empty pattern. Signed-off-by: Oliver Le --- src/gradata/rules/rule_context.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gradata/rules/rule_context.py b/src/gradata/rules/rule_context.py index 6da3c5ae..58b65db7 100644 --- a/src/gradata/rules/rule_context.py +++ b/src/gradata/rules/rule_context.py @@ -64,7 +64,7 @@ def _rule_matches_domain(rule: GraduatedRule, domain_norm: str) -> bool: if str(scope.get("domain", "")).strip().lower() == domain_norm: return True applies = str(scope.get("applies_to", "")).strip().lower() - return applies == domain_norm or bool(applies and applies.startswith(f"{domain_norm}:")) + return applies == domain_norm or applies.startswith(f"{domain_norm}:") class RuleContext: