Skip to content

okl 0.9.0

Latest

Choose a tag to compare

@emeraldleaf emeraldleaf released this 25 Oct 22:49
0809add

okl now needs Python 3.11 or newer: 3.10 is past end of life, and no filelock or pillow
release that installs on it is free of the advisories open against it (0.8.9 stays
installable there). The relevance floor weighs a one-word match by how common the word is,
which refuses three of the six no-match prompts instead of one at no recall cost; okl recap --report says how a session went; okl seed --refresh takes a pack's newer lessons without
the rest of the pack; the reranker's model leaves the system temp directory; and a
check-time model load stays offline after an online one in the same process.

  • okl needs Python 3.11 or newer (#285). Python 3.10 reached end of life on 2026-10-01, and the libraries the hybrid and rerank extras pull in have moved on: no release of filelock or pillow that installs on 3.10 is free of the advisories open against it (filelock 4.1.0 has six, one high; pillow 12.3.0 has twelve, one critical), and the fixes need 3.11. On 3.10, pip keeps installing 0.8.9, the last release for it. The files okl copies into a repo still run on 3.10, since they run on that repo's Python. For contributors: CI drops its 3.10 job, adds 3.15 (released 2026-10-09), and checks that uv.lock matches pyproject.toml (it had drifted for weeks, which is where the alerts came from), and Dependabot now updates both through its uv ecosystem.
  • The relevance floor weighs a one-word match by how common the word is (#277, REPORT §4v). A record that shares one word with the task in its title or symptom is briefed on that word only when at most one record in twenty carries it; a word in five or fewer records always counts, so a small store keeps the old rule; two shared words and a one-word alias admit as before. Measured by the probe at one commit against the control: no recall row moved (held-out, authored or the probe's own) and three of the six no-match prompts are now refused at a three-lesson budget, where one was ("give me a doc for that too" 11 → 2, the search prompt 12 → 6). The share is a scan of the store per check, 12 ms at 323 records. The pipeline diagrams and the README's floor sentence name the rule; evals/common_word_grid.py is the selection grid and evals/probe_rephrase.py --common-share the probe's switch.
  • okl recap --report: how a session went (#279). From the local store's own logs and git, over a window (--since as ISO 8601 or 90m, 6h, 2d; otherwise the transcript's start, otherwise a day): prompts briefed and the lessons shown most, lessons shown while stale, lessons recorded and retired with their reasons, check runs with every failure named, commits, the lessons that govern files changed in the window, and what is stale now. Markdown by default, --format json for scripts. It says what it does not cover yet: corrections made with okl update, which carry no timestamp, and anything a shared service logged. 0.4 s on this repo's store.
  • okl seed --refresh: pick up a pack's newer lessons without taking the rest of the pack. A store that was seeded with the starter subset could not receive the symptoms and aliases the packs gained (REPORT §4o, §4p) except by importing whole packs, which pours a .NET or geospatial pack into a Python repo. --refresh re-imports only the records the store already holds, from the packs they came from, keeps their verification as every re-seed does, writes an edge only when both ends were refreshed, finds the bundled packs from the store's own seed ids when no path is given, and names the packs it was seeded from that are not bundled (a repo's own file) so they can be passed by path.
  • Two retrieval follow-ups measured, nothing changed in behaviour (REPORT §4u). The admission rule §4t proposed for the reranker (first-stage cosine and second-stage rank together) is settled on the selection set: no line admits a lifted lesson without admitting chat filler (evals/admission_grid.py). The floor's two-word rule for a candidate only the semantic arm returned was pre-registered and measured: it admits the one lesson it was built for and the cutoff still drops it behind fifteen kept records, so the knob (core.SEMANTIC_WORD_FLOOR) ships at None, beside core.FETCH_MULTIPLIER and evals/window_grid.py, which found both neutral on the selection set. The probe gains --semantic-words. The next retrieval question is the order among kept records, not the floor.
  • The reranker's model is cached under the cache home, not the system temp directory. fastembed's default cache is $TMPDIR/fastembed_cache, which macOS prunes on its own schedule, so a model that loaded offline one day was "not cached" the next and okl check --rerank fell back to the first-stage order. okl embed now fetches it to $XDG_CACHE_HOME/okl/models (~/.cache/okl/models), or to FASTEMBED_CACHE_PATH when that is set. The embedder is unaffected (model2vec reads the Hugging Face hub cache). Run okl embed once online after upgrading; the old copy in the temp directory is not read.
  • A check-time model load stays offline after an online one in the same process (#290). huggingface_hub reads HF_HUB_OFFLINE once, at import, so in a process whose first load was online (okl embed fetching the reranker), later loads that set the variable still went to the network first: twelve connection attempts before the cache answered, and a test suite that stalled for minutes when the network was slow. The CLI was unaffected, since each command is its own process. okl's offline switch now sets huggingface_hub's own constant beside the variable and restores both, honouring TRANSFORMERS_OFFLINE as the library does.