From b0d722d1a985326fb38e4e7fea237b9c4a2adcfd Mon Sep 17 00:00:00 2001 From: Craig Jennings Date: Thu, 30 Apr 2026 07:55:28 -0500 Subject: docs: record four ADRs for gloss design decisions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The four decisions called out in the brainstorm now have their own files under docs/decisions/, each with Context / Decision / Consequences / Alternatives Considered. - 0001 — storage path default: respects org-directory if set, falls back to user-emacs-directory. - 0002 — auto-fetch on local miss: silent fall-through, network failures surface via the regular error rollup. No y/n prompt for v1. - 0003 — drill direction: every entry exports as twosided. One card per entry, both directions over time, no per-entry override. - 0004 — HTML strip strategy: libxml-parse-html-region. Plain text only, no italic/bold preservation. Online fetch disabled package-wide for the session if libxml is missing. The "Open Questions" section in the design doc is now "Decisions Recorded" with links into the ADRs. --- docs/decisions/0001-storage-path-default.org | 55 ++++++++++++++++++++++++ docs/decisions/0002-auto-fetch-on-local-miss.org | 51 ++++++++++++++++++++++ docs/decisions/0003-drill-direction.org | 49 +++++++++++++++++++++ docs/decisions/0004-html-strip-strategy.org | 54 +++++++++++++++++++++++ 4 files changed, 209 insertions(+) create mode 100644 docs/decisions/0001-storage-path-default.org create mode 100644 docs/decisions/0002-auto-fetch-on-local-miss.org create mode 100644 docs/decisions/0003-drill-direction.org create mode 100644 docs/decisions/0004-html-strip-strategy.org (limited to 'docs/decisions') diff --git a/docs/decisions/0001-storage-path-default.org b/docs/decisions/0001-storage-path-default.org new file mode 100644 index 0000000..539cba7 --- /dev/null +++ b/docs/decisions/0001-storage-path-default.org @@ -0,0 +1,55 @@ +#+TITLE: ADR-1: Storage path default +#+DATE: 2026-04-30 +#+STATUS: Accepted + +* Context + +The glossary is a single org file. The package needs a default location +that integrates with the user's existing org workflow when one exists, +and falls back gracefully otherwise. The choice is visible to users via +the =gloss-file= defcustom and to the file system as the path that gets +auto-created on first save. + +* Decision + +Default =gloss-file= to: + +#+begin_src emacs-lisp +(expand-file-name "gloss.org" (or org-directory user-emacs-directory)) +#+end_src + +If =org-directory= is set, the glossary lives next to the user's other +org files. If it isn't, the glossary lives under =user-emacs-directory= +(typically =~/.emacs.d/=). + +* Consequences + +*Positive.* + +- Users with an established =org-directory= get the glossary in their + org tree without configuration. +- Users without =org-directory= still get a sensible default path that + doesn't require a directory tree to exist. +- The path is writable on every supported platform without privilege. + +*Negative.* + +- =user-emacs-directory= isn't intended for user data — it's + configuration. Users who care will set =gloss-file= explicitly. +- A user who later sets =org-directory= won't see the glossary move. + =gloss-file= is captured at defcustom evaluation time, not on each + call. This is documented in the README troubleshooting section. + +* Alternatives Considered + +*Hardcoded path* — e.g. =~/.gloss.org= or =~/gloss.org=. Rejected: +ignores the org-directory convention; doesn't respect user +preferences for where data lives. + +*XDG_DATA_HOME* — e.g. =~/.local/share/gloss/gloss.org=. Rejected: +correct in spirit but adds a layer the user doesn't otherwise see in +their org workflow. The whole point is "this is one of your org +files." + +*Package-data dir* — e.g. inside the gloss package's install location. +Rejected: data shouldn't live with code; survives reinstalls poorly. diff --git a/docs/decisions/0002-auto-fetch-on-local-miss.org b/docs/decisions/0002-auto-fetch-on-local-miss.org new file mode 100644 index 0000000..399d520 --- /dev/null +++ b/docs/decisions/0002-auto-fetch-on-local-miss.org @@ -0,0 +1,51 @@ +#+TITLE: ADR-2: Auto-fetch on local miss +#+DATE: 2026-04-30 +#+STATUS: Accepted + +* Context + +When the user runs =gloss-lookup= on a term that isn't in the local +cache, the package can either prompt before going online or fall +through silently. The trade-off is between explicit consent (no +surprise network calls) and frictionless typical use. + +* Decision + +Silent fall-through. On a cache miss, =gloss-lookup= calls the online +fetcher without asking. Network failures surface clearly via the +error rollup (see ADR on the error taxonomy in the design doc). + +If a user wants a strict offline mode, they can wrap =gloss-lookup= or +unbind =gloss-fetch-sources= to nil. v1 does not ship a defcustom toggle. + +* Consequences + +*Positive.* + +- The common case (term not in glossary, want a definition) takes + one keystroke (=C-h g g=) instead of two. +- The user-facing message on a network failure is the same shape as + any other failure mode — there's no special "you would have hit + the network" affordance to explain. + +*Negative.* + +- A user on a metered connection or in a restricted environment + might prefer an explicit prompt. v1 doesn't accommodate that. +- A typo on the term means a wasted network call. The cost is small + (one HTTP request to Wiktionary) and the failure is fast. + +* Alternatives Considered + +*y/n prompt before fetch.* Rejected: the answer would be "yes" 99% +of the time, and the prompt becomes friction the user trains +themselves to ignore. The 1% offline case is better handled by +detecting the failure than by pre-asking permission. + +*Defcustom =gloss-auto-fetch=.* Rejected for v1: adds a knob with no +clear default. If shakedown reveals a real need, adding the knob in +v1.1 is straightforward — silent fall-through is the harder default +to walk back. + +*Hard-fail offline.* Rejected: turns "not in glossary" into a fatal +error, which is the wrong shape for what should be a soft fall-through. diff --git a/docs/decisions/0003-drill-direction.org b/docs/decisions/0003-drill-direction.org new file mode 100644 index 0000000..90073aa --- /dev/null +++ b/docs/decisions/0003-drill-direction.org @@ -0,0 +1,49 @@ +#+TITLE: ADR-3: Drill direction +#+DATE: 2026-04-30 +#+STATUS: Accepted + +* Context + +=gloss-drill-export-all= tags every entry for =org-drill=. The card +type controls which direction(s) the drill quizzes — term-to-definition +(recognition), definition-to-term (recall), or both. + +* Decision + +Set =:DRILL_CARD_TYPE: twosided= on every exported entry. +=org-drill='s twosided card type alternates direction on consecutive +visits, so a single entry quizzes both directions over time. + +No per-entry override in v1. Every entry exports as twosided. + +* Consequences + +*Positive.* + +- Tests both recognition and recall over time without doubling the + deck size — one entry, both directions, alternated by =org-drill='s + scheduler. +- No per-entry decision burden during =gloss-add= or + =gloss-drill-export=. + +*Negative.* + +- Some terms make more sense one-directional. A user who saved + "SBIR" → "Small Business Innovation Research" probably wants + recognition only (acronym → expansion), not recall (expansion → + acronym). v1 doesn't accommodate this. +- A future v2 may want a per-entry =:DRILL_CARD_TYPE:= override or a + defcustom for the default. Both are additive changes. + +* Alternatives Considered + +*=:DRILL_CARD_TYPE: simple= (term → definition only).* Rejected: +half the value of the cards, and the user can always skip-back +during drill if they don't want the reverse direction. + +*Two cards per entry, one each direction.* Rejected: doubles the +deck size; adds maintenance burden when an entry is edited (now +two cards diverge). + +*Cloze cards.* Rejected: needs a marked deletion in the body, which +fights the "save once, drill forever" promise. diff --git a/docs/decisions/0004-html-strip-strategy.org b/docs/decisions/0004-html-strip-strategy.org new file mode 100644 index 0000000..4ec7293 --- /dev/null +++ b/docs/decisions/0004-html-strip-strategy.org @@ -0,0 +1,54 @@ +#+TITLE: ADR-4: HTML strip strategy +#+DATE: 2026-04-30 +#+STATUS: Accepted + +* Context + +Wiktionary's REST API returns definition text with HTML markup — +== wrappers, == anchors, transclusion markers, occasional +inline == and ==. The package needs plain text in the saved +glossary entry. The strip strategy must be robust on real responses +(not toy inputs) and shouldn't add a heavyweight dependency. + +* Decision + +Strip via =libxml-parse-html-region=. Take the parsed tree, recurse +through it collecting text nodes, drop everything else. No +preservation of inline formatting (italic, bold, links). + +If the running Emacs wasn't built with libxml2, online fetching is +disabled package-wide for the session with a one-shot user-error. +Manual =gloss-add= still works without libxml. + +* Consequences + +*Positive.* + +- Robust on edge cases — nested tags, malformed HTML, unusual + attributes. The libxml parser handles all of these. +- libxml2 is standard on Linux and macOS; ships with most Emacs + builds. The "missing libxml" path is real but rare. +- ~30 lines of strip code. Maintainable. + +*Negative.* + +- Loses italic/bold/link formatting from definitions. The saved + entry is plain text only. v1 trades fidelity for simplicity. +- A user on a barebones Emacs build (no libxml2) loses online + fetching entirely. The error message tells them why and what to + do, but it's still a hit. + +* Alternatives Considered + +*Regex strip* — pattern-replace =<[^>]+>= and known HTML entities. +Rejected: misses entities the regex didn't anticipate, breaks on +attributes containing =>=, fights when tags are malformed. Looks +simpler but rots fast. + +*Preserve markdown-style inline formatting* — italic → =/.../=, bold +→ =*...*=. Rejected for v1: scope creep on a personal package. +Defensible v1.1 if requested. + +*=shr-render-region=.* Rejected: shr is a renderer, not a stripper. +It produces text-with-faces meant for display, not text for +storage. Wrong shape for the use case. -- cgit v1.2.3