aboutsummaryrefslogtreecommitdiff
path: root/.ai/scripts/tests/test_drill_deck_diff_ids.py
diff options
context:
space:
mode:
authorCraig Jennings <c@cjennings.net>2026-05-31 12:19:34 -0500
committerCraig Jennings <c@cjennings.net>2026-05-31 12:19:34 -0500
commitddf48dc7ac780da1aacdff4e03f1d7da255b8f39 (patch)
tree99926b681a9ea6d4210d0dcd1bd8e8a6d47d7d9e /.ai/scripts/tests/test_drill_deck_diff_ids.py
parentb46619cd17ed4e36f2e59c1b600078521b2049ef (diff)
downloadrulesets-ddf48dc7ac780da1aacdff4e03f1d7da255b8f39.tar.gz
rulesets-ddf48dc7ac780da1aacdff4e03f1d7da255b8f39.zip
feat: add rename-ai-artifact tool and rename the drill-deck family to flashcard
Renaming an .ai artifact by hand is the kind of mechanical job that gets done incompletely: the canonical copy moves but the mirror doesn't, a reference in the INDEX is missed, a trigger phrase points at the old name. I'd also assumed a rename was costly because references scatter, when the index update is trivial and the drift check already guards it. So I built the discipline into a script instead of re-deriving it each time. scripts/rename-ai-artifact.sh takes old and new basenames, moves the file in both the canonical and mirror trees, and rewrites every reference repo-wide on a token boundary so renaming "foo" can't corrupt "foobar" or "foo-bar". It rewrites the underscore module-name variant too (a hyphenated script imported as foo_bar via importlib), leaves the archived session records under sessions/ alone because they're history, and runs workflow-integrity + sync-check at the end to prove no drift. rename-artifact.org documents it and indexes the triggers. Then I used the tool to do the rename that prompted it: the org-drill deck workflow and its helpers are now flashcard-named, since "flashcard" is the word you'd actually search for. The renamed set is flashcard-review.org plus flashcard-stats.py, flashcard-sync, flashcard-to-anki.py, and flashcard-diff-ids.py, with their tests, every reference, and the INDEX entry updated. The deck is still an org-drill deck under the hood, so the ":drill:" tag handling and the "drill deck" trigger phrases stay. I added "review/update the flashcards" alongside them. Tests: 9 bats for the rename tool (including the prefix-collision and history-preservation edges), and the renamed script suites all pass under make test.
Diffstat (limited to '.ai/scripts/tests/test_drill_deck_diff_ids.py')
-rw-r--r--.ai/scripts/tests/test_drill_deck_diff_ids.py109
1 files changed, 0 insertions, 109 deletions
diff --git a/.ai/scripts/tests/test_drill_deck_diff_ids.py b/.ai/scripts/tests/test_drill_deck_diff_ids.py
deleted file mode 100644
index 15fb148..0000000
--- a/.ai/scripts/tests/test_drill_deck_diff_ids.py
+++ /dev/null
@@ -1,109 +0,0 @@
-"""Tests for drill-deck-diff-ids.py: :ID: extraction + SRS-state diff CLI.
-
-Plain python3 script (no third-party deps), so card_id_map imports directly;
-the disappeared/appeared reporting is exercised through the CLI.
-"""
-from __future__ import annotations
-
-import importlib.util
-import subprocess
-import sys
-from pathlib import Path
-
-import pytest
-
-SCRIPT = Path(__file__).resolve().parents[1] / "drill-deck-diff-ids.py"
-
-
-@pytest.fixture(scope="module")
-def diff_ids():
- spec = importlib.util.spec_from_file_location("drill_deck_diff_ids", SCRIPT)
- assert spec and spec.loader
- module = importlib.util.module_from_spec(spec)
- spec.loader.exec_module(module)
- return module
-
-
-DECK_A = """* Section
-** What is DeepSat? :drill:
-:PROPERTIES:
-:ID: id-1
-:END:
-Body.
-** Who founded it? :drill:
-:PROPERTIES:
-:ID: id-2
-:END:
-Body.
-"""
-
-# id-2 dropped, id-3 added relative to DECK_A
-DECK_B = """* Section
-** What is DeepSat? :drill:
-:PROPERTIES:
-:ID: id-1
-:END:
-Body.
-** When was it founded? :drill:
-:PROPERTIES:
-:ID: id-3
-:END:
-Body.
-"""
-
-
-def test_card_id_map_extracts_id_to_heading(diff_ids, tmp_path):
- f = tmp_path / "a.org"
- f.write_text(DECK_A)
- m = diff_ids.card_id_map(f)
- assert set(m) == {"id-1", "id-2"}
- assert m["id-1"] == "What is DeepSat?"
-
-
-def _run(before, after):
- return subprocess.run(
- [sys.executable, str(SCRIPT), str(before), str(after)],
- capture_output=True, text=True,
- )
-
-
-def test_cli_identical_decks_exit_zero(tmp_path):
- a = tmp_path / "a.org"
- a.write_text(DECK_A)
- b = tmp_path / "b.org"
- b.write_text(DECK_A)
- r = _run(a, b)
- assert r.returncode == 0
- assert "preserved" in r.stdout.lower()
-
-
-def test_cli_dropped_id_warns_and_exits_one(tmp_path):
- a = tmp_path / "a.org"
- a.write_text(DECK_A)
- b = tmp_path / "b.org"
- b.write_text(DECK_B)
- r = _run(a, b)
- assert r.returncode == 1
- assert "disappeared" in r.stdout.lower()
- assert "id-2" in r.stdout
-
-
-DECK_ONE = """* Section
-** What is DeepSat? :drill:
-:PROPERTIES:
-:ID: id-1
-:END:
-Body.
-"""
-
-
-def test_cli_appeared_only_notes_new_ids_and_exits_one(tmp_path):
- # before has id-1; after adds id-2 and drops nothing.
- before = tmp_path / "before.org"
- before.write_text(DECK_ONE)
- after = tmp_path / "after.org"
- after.write_text(DECK_A)
- r = _run(before, after)
- assert r.returncode == 1
- assert "appeared" in r.stdout.lower()
- assert "id-2" in r.stdout