Repository navigation
Lore 0.4.0
Recall now honors your config everywhere, stops repeating itself during a refactor, and works for prompts that aren't in English.
Recall correctness
staleStatusesis respected everywhere. It only reached prompt-time ranking before; freshness flags and edit-time recall hardcodedsuperseded/obsolete/deprecated. A project-defined status likearchivedwas penalized on prompt recall but treated as live guidance when you edited the file. Both paths now read the config.- Edit-time matches are ranked before they're cut.
maxRecalltruncated in alphabetical path order, so a superseded entry could displace a current one. Live entries now sort first, ties keep store order. - New
staleAfterMonths(default6) — one configurable freshness threshold, replacing the same constant duplicated in two units (STALE_AFTER_MONTHS = 6in recall,STALE_AFTER_DAYS = 183in the linter).
Edit-time recall dedupes per session
The PreToolUse hook fires on every Edit/Write, so a refactor touching one file ten times injected the same learning ten times. Surfaced entries are now remembered for the session in .git/lore-recall-seen.json (local, inside .git, never committed) and not re-injected. Keyed by the hook's session_id; a new session starts clean. Fails open — no session id, no .git, or corrupt state means the learning still surfaces.
Non-English prompts
- Unicode, accent-folding tokenizer.
[a-z0-9_]+splitautenticaciónintoautenticaci+n, quietly degrading recall for anyone prompting in Spanish (or any accented language). Tokens are now\w+with diacritics folded, so an accented prompt also matches a tag written without accents (autenticación↔autenticacion). - Spanish stop words.
para,este,cuando,quiero,necesitoand ~85 more reached the scorer and could prefix-match real vocabulary (para→parameters). Deliberately not stopped:todo/todos/algo, which are real English/domain tokens. - New
stopWordsconfig key — words added to the built-in list, for domain noise (a product name in every prompt) or the three above. - Docs: write tags in the language you prompt in — accents fold, languages don't.
Hardening
- Injected titles are capped at 140 characters and stripped of control characters. Recall's "never inject bodies" promise limits the prompt-injection surface of a shared store — but
title:was injected verbatim and unbounded, so a malicious PR could smuggle an instruction payload through it. - The secret scanner no longer double-reports an Anthropic key (the OpenAI
sk-rule also matched it).
Performance & diagnostics
iter_entriesreads a bounded 8 KB head instead of whole entry files — it only ever needed the frontmatter, and it runs on every prompt and every edit. Constant cost per entry, with a full-read fallback so correctness never depends on the window.- The linter names ignored
.lore.jsonkeys.load_configdeliberately never fails, so a typo likemaxRecalsilently did nothing./lore:lintand/lore:statsnow report unknown keys with a did-you-mean suggestion, plus wrongly-typed values.
Tests
52 → 86. Closes the coverage gaps on run_pretool, the run_hook JSON envelope, --index, and recall-log rotation, and covers every change above (including a regression test that fails against the old English-only stop list).
No behavior change requiring action: every new config key defaults to the previous behavior.
Install / update: /plugin install lore@lore (auto-updates).