aboutsummaryrefslogtreecommitdiff
path: root/.ai/scripts/drill-deck-sync
diff options
context:
space:
mode:
authorCraig Jennings <c@cjennings.net>2026-05-30 13:17:47 -0500
committerCraig Jennings <c@cjennings.net>2026-05-30 13:17:47 -0500
commit0234e52b727b34ade93961eb05b5638685f4406f (patch)
treeb7ee5f66a9fceb3fd4d9b1d2ba8c44e89dde76c5 /.ai/scripts/drill-deck-sync
parent038d59b7e548d2323f43dcd92ba14cba876d840d (diff)
downloadrulesets-0234e52b727b34ade93961eb05b5638685f4406f.tar.gz
rulesets-0234e52b727b34ade93961eb05b5638685f4406f.zip
chore(scripts): add drill-deck stats, diff-ids, and sync wrapper
I incorporated the flashcard-tooling bundle from the work project's deck-review workflow, validated there against a 93-card deck. Three scripts now live under .ai/scripts/: drill-deck-stats.py (pre-rewrite inventory plus a gate that warns on stray *** Answer headers, missing :ID:, non-prompt headings, and #+TITLE jargon like "org-drill"), drill-deck-diff-ids.py (SRS-state preservation check that flags any :ID: lost across a rewrite), and drill-deck-sync (bash wrapper chaining stats, optional diff-ids, then drill-to-anki, writing to ~/sync/phone/anki/ only when the gates pass). The drill-deck-review.org workflow gains a Helper Scripts section and references the scripts from its phases. I reconciled its output-path prose with the drill-to-anki default that just moved to ~/sync/phone/anki/, so it no longer claims the script still defaults to ~/sync/org/drill/. I added tests for both Python scripts (pure logic plus CLI gate behavior) and a bats suite for the wrapper's guard paths. The clean end-to-end sync path stays uncovered since it needs uv-resolved genanki.
Diffstat (limited to '.ai/scripts/drill-deck-sync')
-rwxr-xr-x.ai/scripts/drill-deck-sync98
1 files changed, 98 insertions, 0 deletions
diff --git a/.ai/scripts/drill-deck-sync b/.ai/scripts/drill-deck-sync
new file mode 100755
index 0000000..8e51cdd
--- /dev/null
+++ b/.ai/scripts/drill-deck-sync
@@ -0,0 +1,98 @@
+#!/usr/bin/env bash
+# drill-deck-sync: stats check + regenerate Anki apkg + place at ~/sync/phone/anki/
+#
+# Wraps drill-deck-stats.py + drill-to-anki.py (and optionally
+# drill-deck-diff-ids.py) for the canonical "rewrote the deck, now ship
+# it" step in the drill-deck-review workflow.
+#
+# Usage:
+# drill-deck-sync <source.org>
+# drill-deck-sync <source.org> --diff-against <previous-version.org>
+#
+# Exits non-zero when the stats check warns, when --diff-against shows
+# any disappeared / appeared IDs, or when drill-to-anki.py fails. The
+# Anki apkg is not written when any gate fails.
+
+set -euo pipefail
+
+usage() {
+ cat >&2 <<'EOF'
+usage: drill-deck-sync <source.org> [--diff-against <previous-version.org>]
+EOF
+ exit 2
+}
+
+if [[ $# -lt 1 ]]; then
+ usage
+fi
+
+SOURCE="$1"
+shift
+
+DIFF_AGAINST=""
+while [[ $# -gt 0 ]]; do
+ case "$1" in
+ --diff-against)
+ [[ $# -ge 2 ]] || usage
+ DIFF_AGAINST="$2"
+ shift 2
+ ;;
+ -h|--help)
+ usage
+ ;;
+ *)
+ echo "unknown arg: $1" >&2
+ usage
+ ;;
+ esac
+done
+
+if [[ ! -f "$SOURCE" ]]; then
+ echo "error: $SOURCE not found" >&2
+ exit 2
+fi
+
+SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
+STATS="$SCRIPT_DIR/drill-deck-stats.py"
+DIFF_IDS="$SCRIPT_DIR/drill-deck-diff-ids.py"
+TO_ANKI="$SCRIPT_DIR/drill-to-anki.py"
+
+for helper in "$STATS" "$DIFF_IDS" "$TO_ANKI"; do
+ if [[ ! -f "$helper" ]]; then
+ echo "error: helper $helper not found" >&2
+ exit 2
+ fi
+done
+
+echo "=== drill-deck-sync: $SOURCE ==="
+echo
+echo "--- stats ---"
+if ! python3 "$STATS" "$SOURCE"; then
+ echo
+ echo "stats check failed — fix warnings before sync, or call drill-to-anki.py directly to override" >&2
+ exit 1
+fi
+echo
+
+if [[ -n "$DIFF_AGAINST" ]]; then
+ if [[ ! -f "$DIFF_AGAINST" ]]; then
+ echo "error: $DIFF_AGAINST not found" >&2
+ exit 2
+ fi
+ echo "--- ID preservation ---"
+ if ! python3 "$DIFF_IDS" "$DIFF_AGAINST" "$SOURCE"; then
+ echo
+ echo "ID preservation check failed — SRS state may have been lost" >&2
+ exit 1
+ fi
+ echo
+fi
+
+BASENAME="$(basename "$SOURCE" .org)"
+OUTPUT="$HOME/sync/phone/anki/${BASENAME}.apkg"
+
+echo "--- regenerate apkg ---"
+mkdir -p "$(dirname "$OUTPUT")"
+"$TO_ANKI" "$SOURCE" --output "$OUTPUT"
+echo
+echo "deck synced to $OUTPUT"