aboutsummaryrefslogtreecommitdiff
path: root/.ai/scripts/drill-to-anki.py
diff options
context:
space:
mode:
authorCraig Jennings <c@cjennings.net>2026-05-30 15:46:00 -0500
committerCraig Jennings <c@cjennings.net>2026-05-30 15:46:00 -0500
commitb80a9ceb3fc9cdca9798b48fbc4f9ab9c1592b57 (patch)
treebe0f328c6be0ddb8d999730cc6fa07277ebc2ec7 /.ai/scripts/drill-to-anki.py
parent968a39bb3978e6ad499447ce173e2265dee772a2 (diff)
downloadrulesets-b80a9ceb3fc9cdca9798b48fbc4f9ab9c1592b57.tar.gz
rulesets-b80a9ceb3fc9cdca9798b48fbc4f9ab9c1592b57.zip
fix(drill-deck): cut leakage false positives and codify source/date conventions
Health ran the new leakage check on a 43-card deck and hit two false-positive classes. The check read the whole card body, so a =Source: <label> — <url>= citation line inflated the front/back overlap whenever the URL slug repeated the question's words. Range/category cards ("What are the HbA1c ranges across normal, prediabetes, and diabetes?") tripped it too, because the question's categories echo in the answer even though the recalled content is the numbers. drill-deck-stats.py now routes leakage through an is_leaky helper. It strips =Source:= and created-date lines before computing overlap, and exempts a card when the answer carries a numeric range or threshold the question lacks. leakage_ratio itself is unchanged, so the genuine-restatement case still flags. Two body conventions now hold: a =Source:= citation goes at the end of a card after two blank lines, and no created/added date goes on a card. drill-to-anki.py now strips =Created:= / =:CREATED:= lines from the back as a backstop, and the workflow's Phase C removes them from the source during the rewrite. I added tests for the source-strip, the numeric carve-out, and the created-line strip, and documented all of it in drill-deck-review.org.
Diffstat (limited to '.ai/scripts/drill-to-anki.py')
-rwxr-xr-x.ai/scripts/drill-to-anki.py9
1 files changed, 6 insertions, 3 deletions
diff --git a/.ai/scripts/drill-to-anki.py b/.ai/scripts/drill-to-anki.py
index 1050021..9fe954e 100755
--- a/.ai/scripts/drill-to-anki.py
+++ b/.ai/scripts/drill-to-anki.py
@@ -90,15 +90,18 @@ def escape_html(s: str) -> str:
def strip_org_metadata(body_lines: list[str]) -> list[str]:
- """Drop :PROPERTIES: drawers and SCHEDULED/DEADLINE/CLOSED planning lines.
+ """Drop :PROPERTIES: drawers, planning lines, and created-date lines.
Org-drill needs these in the source file (SRS state lives in the
PROPERTIES drawer; SCHEDULED carries the next-review date), but they
- are noise on the back of an Anki card.
+ are noise on the back of an Anki card. A created/added date never
+ belongs on a card, so a stray "Created:" or ":CREATED:" body line is
+ dropped too.
"""
cleaned: list[str] = []
in_drawer = False
planning_re = re.compile(r"^\s*(SCHEDULED|DEADLINE|CLOSED):\s")
+ created_re = re.compile(r"^\s*:?created:?\s", re.IGNORECASE)
drawer_start_re = re.compile(r"^\s*:PROPERTIES:\s*$")
drawer_end_re = re.compile(r"^\s*:END:\s*$")
for line in body_lines:
@@ -109,7 +112,7 @@ def strip_org_metadata(body_lines: list[str]) -> list[str]:
if drawer_start_re.match(line):
in_drawer = True
continue
- if planning_re.match(line):
+ if planning_re.match(line) or created_re.match(line):
continue
cleaned.append(line)
return cleaned