<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <id>https://www.kotoshu.org/news/</id>
  <title>Kotoshu — News</title>
  <link href="https://www.kotoshu.org/news/"/>
  <link href="https://www.kotoshu.org/news/atom.xml" rel="self"/>
  <updated>2026-09-15T00:00:00.000Z</updated>
  <author><name>Ribose Inc.</name></author>
  <entry>
    <id>https://www.kotoshu.org/news/gem-1-0-6-fixes/</id>
    <title>kotoshu 1.0.6: four fixes and an honest library</title>
    <link href="https://www.kotoshu.org/news/gem-1-0-6-fixes/"/>
    <published>2026-09-15T00:00:00.000Z</published>
    <updated>2026-09-15T00:00:00.000Z</updated>
    <summary>Expired caches resolve instead of raising, the dictionary catalog reaches its repo again, a suggestion crash on tied scores is gone, and every URL the library builds now points somewhere live.</summary>
    <content type="html">&lt;p&gt;Expired caches resolve instead of raising, the dictionary catalog reaches its repo again, a suggestion crash on tied scores is gone, and every URL the library builds now points somewhere live.&lt;/p&gt;
&lt;p&gt;1. An expired-but-present cache resolves: &lt;code&gt;Kotoshu.correct?&lt;/code&gt; no longer raises &lt;code&gt;ResourceNotSetupError&lt;/code&gt; for a language whose cached dictionary metadata predates bookkeeping, and &lt;code&gt;kotoshu setup --list&lt;/code&gt; agrees with resolve. TTL now means refresh-at-setup, never absence-at-read.&lt;/p&gt;
&lt;p&gt;2. &lt;code&gt;Dictionaries::Catalog&lt;/code&gt; fetches from the &lt;code&gt;v1&lt;/code&gt; branch - every catalog download had been a 404 against a branch the dictionary repository abandoned. &lt;code&gt;NgramSuggest&lt;/code&gt; no longer crashes with &lt;code&gt;comparison of Array with Array&lt;/code&gt; when tied root scores span mixed dictionary entry shapes; the sort compares scores only. The deprecated dictionaries URL default and a dead model-URL fallback joined the fix.&lt;/p&gt;
&lt;p&gt;3. The typo layer hardened: a prebuilt matrix now carries the sha of the exact full-tier vocabulary it was derived over, and an arm that does not pair with the cached tier derives instead of answering wrong slates. The signature file parses for the first time, all 32 example walkthroughs run, and &lt;code&gt;kotoshu-lsp&lt;/code&gt; 0.1.2 floors on the 1.0 engine line.&lt;/p&gt;</content>
  </entry>
  <entry>
    <id>https://www.kotoshu.org/news/gem-1-0-5-instant-arming/</id>
    <title>kotoshu 1.0.5: typo arming becomes a download</title>
    <link href="https://www.kotoshu.org/news/gem-1-0-5-instant-arming/"/>
    <published>2026-09-14T00:00:00.000Z</published>
    <updated>2026-09-14T00:00:00.000Z</updated>
    <summary>The typo-retrieval layer now ships prebuilt matrices for all six full-feature languages, setup backfills them on existing installs, and the engine records how it armed - plus a weekly guard against stale extension pins. The Rust crate follows at 0.2.1.</summary>
    <content type="html">&lt;p&gt;The typo-retrieval layer now ships prebuilt matrices for all six full-feature languages, setup backfills them on existing installs, and the engine records how it armed - plus a weekly guard against stale extension pins. The Rust crate follows at 0.2.1.&lt;/p&gt;
&lt;p&gt;1. &lt;code&gt;kotoshu setup LANG --typo&lt;/code&gt; now ends with the language's 26 MB KTM1 matrix in the cache, and an install set up before the matrices existed picks one up on its next setup run instead of deriving the index at load time. Arming measures about half a second where deriving took 25 to 45 seconds, and German - the language where the hybrid's benchmark win is largest - arms in 511 ms against 44.9 s derived.&lt;/p&gt;
&lt;p&gt;2. The engine records which path won: &lt;code&gt;Kotoshu::Typo::Engine#armed_via&lt;/code&gt; answers &lt;code&gt;:matrix&lt;/code&gt; or &lt;code&gt;:derived&lt;/code&gt;, &lt;code&gt;Kotoshu::ResourceManager.setup?(lang, resource: :typo_matrix)&lt;/code&gt; probes the artifact, and &lt;code&gt;kotoshu setup --list&lt;/code&gt; prints per-resource detail such as &lt;code&gt;en: spelling, model, typo, typo-matrix&lt;/code&gt;. A stale extension can no longer silently fall back to deriving - a weekly workflow compares the extension's kotoshu-rs pin against main and fails loudly with the fix recipe, and the release verify job installs the shipped gem and asserts the native surface before green-lighting a cut.&lt;/p&gt;
&lt;p&gt;3. The Rust crate follows at 0.2.1 with the public matrix surface (&lt;code&gt;TypoEngine::from_matrix&lt;/code&gt;, &lt;code&gt;TypoIndex::parse_ktm1&lt;/code&gt;/&lt;code&gt;write_rows&lt;/code&gt;), and the model registry grew a fetchability gate: every primary, mirror, and vocab URL is probed with ranged requests on each pull request and before every release, so a dead mirror can never reach a tag again.&lt;/p&gt;</content>
  </entry>
  <entry>
    <id>https://www.kotoshu.org/news/typo-retrieval-live/</id>
    <title>The hybrid typo-retrieval layer is live across the ecosystem</title>
    <link href="https://www.kotoshu.org/news/typo-retrieval-live/"/>
    <published>2026-09-14T00:00:00.000Z</published>
    <updated>2026-09-14T00:00:00.000Z</updated>
    <summary>A 0.481 MB character bi-encoder now retrieves the twenty nearest vocabulary entries for a misspelling and the fastText full tier rescores them, with the layer wired end to end: registry v1.7.0 carries the artifacts, kotoshu 1.0.3 fetches them with one setup flag, and the Rust crate and WebAssembly package expose the same engine.</summary>
    <content type="html">&lt;p&gt;A 0.481 MB character bi-encoder now retrieves the twenty nearest vocabulary entries for a misspelling and the fastText full tier rescores them, with the layer wired end to end: registry v1.7.0 carries the artifacts, kotoshu 1.0.3 fetches them with one setup flag, and the Rust crate and WebAssembly package expose the same engine.&lt;/p&gt;
&lt;p&gt;1. The registry v1.7.0 release promotes the typo bi-encoder from an opt-in mirror to a first-class artifact pair, generated by the descriptor-driven release flow with the validator enforcing that the model and its character vocabulary travel together. kotoshu 1.0.3 adds &lt;code&gt;kotoshu setup LANG --typo&lt;/code&gt;: one flag fetches the pair plus the full tier, reports the layer as cached on later runs, and arms it behind KOTOSHU_TYPO_RETRIEVAL with a byte-identical passthrough when off.&lt;/p&gt;
&lt;p&gt;2. The engine reproduces the frozen benchmark exactly through the shipped path - top1 0.118772 and top5 0.269829 on the 2,509 real English pairs, identical to the measured verdict - at 1.8 ms per query after the index builds eagerly with the Ruby GVL released (a 25-second derivation no longer pauses any thread). The pure-Rust forward pass matches onnxruntime to cosine 1.0. kotoshu-native 0.1.1 on PyPI now carries all 21 platform wheels, and the crate 0.2.0 and @kotoshu/wasm 1.1.0 cut the same surface for Cargo and npm. Prebuilt 26 MB KTM1 matrices - one per full-feature language, served by the registry - arm the same engine in about half a second instead of a 25-to-45-second index derivation.&lt;/p&gt;</content>
  </entry>
  <entry>
    <id>https://www.kotoshu.org/news/gem-1-0-2/</id>
    <title>kotoshu 1.0.2: the Rust engine installs precompiled</title>
    <link href="https://www.kotoshu.org/news/gem-1-0-2/"/>
    <published>2026-09-12T00:00:00.000Z</published>
    <updated>2026-09-12T00:00:00.000Z</updated>
    <summary>gem install kotoshu now resolves a precompiled native platform gem on Linux, macOS, and Windows, so the Rust engine runs with no compiler toolchain, and the backend default became auto: use the native engine when it loads, fall back to pure Ruby when it does not.</summary>
    <content type="html">&lt;p&gt;gem install kotoshu now resolves a precompiled native platform gem on Linux, macOS, and Windows, so the Rust engine runs with no compiler toolchain, and the backend default became auto: use the native engine when it loads, fall back to pure Ruby when it does not.&lt;/p&gt;
&lt;p&gt;1. Five platform gems ship alongside the pure-Ruby gem — x86_64-linux, aarch64-linux, arm64-darwin, x86_64-darwin, and x64-mingw-ucrt — each carrying the compiled extension inside the gem and built natively on its own runner. The CI matrix proves every one by installing the platform gem into a toolchain-free environment and asserting that the native engine engages. RubyGems picks the platform gem automatically on a matching machine, and every other platform, including musl Linux, resolves the pure-Ruby gem exactly as before.&lt;/p&gt;
&lt;p&gt;2. The backend setting now defaults to auto, which selects the native engine when the extension loads and silently uses pure Ruby when it does not; KOTOSHU_BACKEND=native and KOTOSHU_BACKEND=ruby still force an engine explicitly. No output changes anywhere: both engines remain pinned to the frozen 2,630-vector conformance contract. The Docker CI image follows in the same arc by dropping its build-tool layer in favor of the platform gem.&lt;/p&gt;</content>
  </entry>
  <entry>
    <id>https://www.kotoshu.org/news/gem-1-0-1/</id>
    <title>kotoshu 1.0.1: deterministic ranking by construction</title>
    <link href="https://www.kotoshu.org/news/gem-1-0-1/"/>
    <published>2026-09-12T00:00:00.000Z</published>
    <updated>2026-09-12T00:00:00.000Z</updated>
    <summary>The gem now embeds the frozen Kelly frequency tiers, so a machine with a cold cache ranks suggestions exactly like the frozen conformance vectors, without any download, CI seeding, or dataset switch at cache expiry.</summary>
    <content type="html">&lt;p&gt;The gem now embeds the frozen Kelly frequency tiers, so a machine with a cold cache ranks suggestions exactly like the frozen conformance vectors, without any download, CI seeding, or dataset switch at cache expiry.&lt;/p&gt;
&lt;p&gt;1. This release closes the last dataset-divergence path. The frequency provider now falls back from the cache to the frozen embedded tiers before the local YAML file, and the embedded table is generated from the same arrays the Rust engine compiles in, with provenance and the upstream checksum stored inside the file. The empty-cache conformance comparison over all 2,630 vectors passes byte for byte with no cache present at all.&lt;/p&gt;
&lt;p&gt;2. The patch also threads the baseline suggestion-skip through the Jekyll generator, so baselined builds stop paying the sweep for covered words, matching the CLI and Rake paths. kotoshu-server 1.0.1 fixes its runtime floor, because the ~&amp;gt; 0.6 cap it had shipped with silently excluded the 1.x gem.&lt;/p&gt;</content>
  </entry>
  <entry>
    <id>https://www.kotoshu.org/news/evidence-2026-09/</id>
    <title>Synthetic typo corpora, published error budgets, and suggestion reporting</title>
    <link href="https://www.kotoshu.org/news/evidence-2026-09/"/>
    <published>2026-09-12T00:00:00.000Z</published>
    <updated>2026-09-12T00:00:00.000Z</updated>
    <summary>Four new 5,000-pair dictionary-grounded typo corpora, a published per-tier error budget, one-click wrong-suggestion reporting in the playground, and a rebuilt Docker CI image.</summary>
    <content type="html">&lt;p&gt;Four new 5,000-pair dictionary-grounded typo corpora, a published per-tier error budget, one-click wrong-suggestion reporting in the playground, and a rebuilt Docker CI image.&lt;/p&gt;
&lt;p&gt;1. The synthetic corpora are verifiable by construction: every correction is a dictionary stem, every misspelling is reachable by a declared keyboard-noise operation, and the whole file is a seeded pure function of the dictionary pin. The headline measurement is that even the full tier can embed only about 1.5% of these realistic misspellings, which quantifies the gap between embedding tiers and actual misspellings and motivates the dictionary sweep.&lt;/p&gt;
&lt;p&gt;2. The performance documentation now carries the tier error budget, listing worst-case rank correlation and top-1 agreement across all 55 languages next to the gates that enforce them, so every claim about a cheaper tier carries its measured number.&lt;/p&gt;
&lt;p&gt;3. The playground popover gained a report link: one click opens a pre-filled issue with the word, the offered suggestions, the language, and the engine version, and nothing else. Verified reports feed the corpora.&lt;/p&gt;
&lt;p&gt;4. The Docker CI image could not install kotoshu at all once the native extension shipped; a newly added version guard caught the failure on its first run, and the image now builds the Rust accelerator properly.&lt;/p&gt;</content>
  </entry>
  <entry>
    <id>https://www.kotoshu.org/news/kotoshu-1-0/</id>
    <title>kotoshu 1.0.0: the stability freeze</title>
    <link href="https://www.kotoshu.org/news/kotoshu-1-0/"/>
    <published>2026-09-10T00:00:00.000Z</published>
    <updated>2026-09-10T00:00:00.000Z</updated>
    <summary>The coordinated 1.0 cut: the Ruby gem, @kotoshu/wasm, and kotoshu-server all reach 1.0.0 with the public surface frozen and the 2,630-vector Ruby==Rust conformance contract gated in CI on both sides.</summary>
    <content type="html">&lt;p&gt;The coordinated 1.0 cut: the Ruby gem, @kotoshu/wasm, and kotoshu-server all reach 1.0.0 with the public surface frozen and the 2,630-vector Ruby==Rust conformance contract gated in CI on both sides.&lt;/p&gt;
&lt;p&gt;1. Version 1.0 freezes the strict two-stage resource model, in which setup is never implicit and the hot path never downloads; the CLI exit codes 0 through 3 and the JSON and SARIF output shapes; the kotoshu.resources/v1 registry schema and the /v1 HTTP prefix; the extension points for custom dictionary types and suggestion algorithms; and the behavioral contract itself, which is the set of 2,630 frozen conformance vectors that the Ruby and Rust engines must both match byte for byte, now enforced by CI jobs in both repositories.&lt;/p&gt;
&lt;p&gt;2. The last blocker before the cut was found by running the audit checklist, not by a user: suggestion ranking silently changed when the frequency cache passed its 7-day TTL, because the reader fell back to a differently-curated local dataset. Fixed, tested with the cache deliberately expired, and the compare job added so the invariant can never drift silently again.&lt;/p&gt;
&lt;p&gt;3. At 1.0 the gem is on RubyGems, @kotoshu/wasm is on npm with loadPack language packs for English, German, and Portuguese, and kotoshu-server ships model-aware checking. The GitHub action runs in six repositories including this one, and kotoshu-lsp, PyPI, crates.io, the Go client, and the zero-install playground complete the channel picture.&lt;/p&gt;</content>
  </entry>
  <entry>
    <id>https://www.kotoshu.org/news/gem-0-11-1/</id>
    <title>kotoshu 0.11.1: baselines that work on real repositories</title>
    <link href="https://www.kotoshu.org/news/gem-0-11-1/"/>
    <published>2026-09-10T00:00:00.000Z</published>
    <updated>2026-09-10T00:00:00.000Z</updated>
    <summary>The baseline command now accepts directories and globs, ignores the personal dictionary, and skips the suggestion sweep, and check --baseline no longer generates suggestions for the occurrences it suppresses.</summary>
    <content type="html">&lt;p&gt;The baseline command now accepts directories and globs, ignores the personal dictionary, and skips the suggestion sweep, and check --baseline no longer generates suggestions for the occurrences it suppresses.&lt;/p&gt;
&lt;p&gt;1. Dogfooding action-kotoshu@v2 on the gem repository itself surfaced four defects in baseline init, all fixed: directories and globs expand exactly like check directory mode; a target matching no file is refused with the same File not found instead of silently vanishing; the personal dictionary is never consulted, so baselines freeze what every machine sees; and file reads scrub invalid bytes.&lt;/p&gt;
&lt;p&gt;2. The baseline generator also skips the suggestion sweep whose output it was discarding, which turned 49 CPU-minutes over the gem repository into 84 seconds. The gate side received the same treatment, so check --baseline only generates suggestions for occurrences that will surface. On this repository's own CI gate, 1,905 covered occurrences no longer generate suggestions, and the check phase dropped from 13 minutes to 14 seconds with identical output.&lt;/p&gt;
&lt;p&gt;3. The gem repository now runs its own spellcheck workflow — the sixth repo in the rollout and the first Ruby one, closing the loop that found these bugs.&lt;/p&gt;</content>
  </entry>
  <entry>
    <id>https://www.kotoshu.org/news/wasm-0-5-0/</id>
    <title>loadPack ships in @kotoshu/wasm 0.5.0</title>
    <link href="https://www.kotoshu.org/news/wasm-0-5-0/"/>
    <published>2026-09-10T00:00:00.000Z</published>
    <updated>2026-09-10T00:00:00.000Z</updated>
    <summary>A single language pack now carries the dictionary, the embedding tier, the vocabulary, and the bucket table, and one loadPack call turns one fetch into the complete set of engine handles.</summary>
    <content type="html">&lt;p&gt;A single language pack now carries the dictionary, the embedding tier, the vocabulary, and the bucket table, and one loadPack call turns one fetch into the complete set of engine handles.&lt;/p&gt;
&lt;p&gt;1. loadPack(packBytes) parses the KPK1 container, verifies the checksum of every section before constructing anything, and returns dictionary and model handles, with the model already bucket-attached when the pack carries a bucket table. The package published through keyless publishing after the owner cleared a publishing-policy setting on the npm side.&lt;/p&gt;
&lt;p&gt;2. The playground uses it for English, German, and Portuguese, so three or more round trips collapse into one, and per-artifact loading remains the fallback for languages without a pack.&lt;/p&gt;</content>
  </entry>
  <entry>
    <id>https://www.kotoshu.org/news/registry-v1-6-0/</id>
    <title>Language packs and the typo-biencoder hybrid in registry v1.6.0</title>
    <link href="https://www.kotoshu.org/news/registry-v1-6-0/"/>
    <published>2026-09-10T00:00:00.000Z</published>
    <updated>2026-09-10T00:00:00.000Z</updated>
    <summary>One fetch now loads a whole language through KPK1 packs for English, German, and Portuguese, and the typo-biencoder hybrid becomes the first alternative model to beat the full tier on every gate.</summary>
    <content type="html">&lt;p&gt;One fetch now loads a whole language through KPK1 packs for English, German, and Portuguese, and the typo-biencoder hybrid becomes the first alternative model to beat the full tier on every gate.&lt;/p&gt;
&lt;p&gt;1. A language pack concatenates the dictionary files, the mini tier, the vocabulary, and the bucket table into one KPK1 artifact with per-section checksum footers, so three round trips become one. loadPack on the wasm surface and pack mode in @kotoshu/worker both fall back to per-artifact loading when no pack exists.&lt;/p&gt;
&lt;p&gt;2. The model bake-off closed with a winner: the 0.48 MB typo-biencoder hybrid, which retrieves with the tiny bi-encoder and rescores with fastText, beats the full tier on every real-pair component at 3 to 4 ms per lookup. English gains +6.3 points on top-5 with a confidence interval of +4.9 to +7.7 over 2,509 pairs, German gains +28.6, Spanish gains +10, and no component regresses. The hybrid is registered opt-in as kotoshu://models/typo/typo-biencoder, and the candidates rejected on measurement along the way were int4, the MiniLM rerank, ModernBERT, and the standalone bi-encoder.&lt;/p&gt;
&lt;p&gt;3. The registry now carries 383 release assets, and the lid primary URLs work again after pointing at unattached assets since v1.5.0.&lt;/p&gt;</content>
  </entry>
  <entry>
    <id>https://www.kotoshu.org/news/worker-0-1-0/</id>
    <title>The engine worker ships as @kotoshu/worker 0.1.0</title>
    <link href="https://www.kotoshu.org/news/worker-0-1-0/"/>
    <published>2026-09-09T00:00:00.000Z</published>
    <updated>2026-09-09T00:00:00.000Z</updated>
    <summary>The playground worker protocol ships on npm as createEngine, covering load, check, suggest-batch, semantic, and detect, with the same pinned resources, the same caching, and no install step.</summary>
    <content type="html">&lt;p&gt;The playground worker protocol ships on npm as createEngine, covering load, check, suggest-batch, semantic, and detect, with the same pinned resources, the same caching, and no install step.&lt;/p&gt;
&lt;p&gt;1. @kotoshu/worker exposes createEngine(onMessage), which speaks the full protocol the playground runs: dictionary loading with progress, batched priority suggestions, the opt-in semantic tier with buckets, and language detection, plus a ready new Worker() entry and the pure semantic-merge half. It runs in the browser and in Node.&lt;/p&gt;
&lt;p&gt;2. CI now enforces what docs used to claim: latency gates (en 56 ms average vs the 120 ms budget, pt 346 vs 700) and frozen wasm memory ceilings (en 46.9/64 MB resident with tier and buckets).&lt;/p&gt;</content>
  </entry>
  <entry>
    <id>https://www.kotoshu.org/news/registry-v1-5-0/</id>
    <title>Bucket tables for 47 languages in registry v1.5.0</title>
    <link href="https://www.kotoshu.org/news/registry-v1-5-0/"/>
    <published>2026-09-08T00:00:00.000Z</published>
    <updated>2026-09-08T00:00:00.000Z</updated>
    <summary>Model-generated candidates now reach out-of-vocabulary misspellings in 45 more languages, and eight languages were rejected on measurement with full evidence ladders.</summary>
    <content type="html">&lt;p&gt;Model-generated candidates now reach out-of-vocabulary misspellings in 45 more languages, and eight languages were rejected on measurement with full evidence ladders.&lt;/p&gt;
&lt;p&gt;1. Forty-five new bucket-table siblings of 10 to 12 MB each let semanticSuggest embed the out-of-vocabulary n-grams the vocabulary lacks, in every language the fidelity gates passed. French rose from 0.696 to 1.000, Spanish from 0.667 to 1.000, and Russian from 0.623 to 1.000 in out-of-vocabulary resolution on real-corpus probes.&lt;/p&gt;
&lt;p&gt;2. Eight languages (ar, cs, fa, he, ja, pl, vi, zh) were rejected on measurement, with the gates never weakened; full ladder evidence is committed for a future decision. Serbian and Swedish ship at K=65536 with a recorded size deviation.&lt;/p&gt;
&lt;p&gt;3. The registry now holds 213 resources at revision 7, and the playground picks up every addition automatically.&lt;/p&gt;</content>
  </entry>
  <entry>
    <id>https://www.kotoshu.org/news/gem-0-11-0/</id>
    <title>All staged languages reachable; Korean and Nepali gain full support in kotoshu 0.11.0</title>
    <link href="https://www.kotoshu.org/news/gem-0-11-0/"/>
    <published>2026-09-07T00:00:00.000Z</published>
    <updated>2026-09-07T00:00:00.000Z</updated>
    <summary>setup no longer gates on a module, so 95 staged languages work out of the box with script-aware fallbacks, and Korean and Nepali join the full-feature 35.</summary>
    <content type="html">&lt;p&gt;setup no longer gates on a module, so 95 staged languages work out of the box with script-aware fallbacks, and Korean and Nepali join the full-feature 35.&lt;/p&gt;
&lt;p&gt;1. The basic tier (plan 107) derives AVAILABLE_LANGUAGES from the dictionaries manifest instead of a hardcoded module list, so every staged language installs and checks, with script-aware tokenizers and per-script keyboard fallbacks applied automatically. Modules are now upgrades rather than gates, and nn is wired as the 33rd full-feature language.&lt;/p&gt;
&lt;p&gt;2. Korean and Nepali reach full feature (plan 108) through a Hangul eojeol tokenizer on the Dubeolsik 2-set grid (KS X 5002) and a Devanagari tokenizer that keeps matras and conjuncts whole on the InScript grid, covering the last big-population languages without support. The total is 35 full-feature languages, with live specimen round trips in both scripts.&lt;/p&gt;
&lt;p&gt;3. The cut also carries the 1.0 public-surface cleanup: the global DictCommand leak is fixed, dead command classes and unused aliases are removed (1,095 lines), and the experimental checkers are documented. The suite runs 3,985 examples with conformance untouched.&lt;/p&gt;</content>
  </entry>
  <entry>
    <id>https://www.kotoshu.org/news/server-0-1-2/</id>
    <title>/v1/detect covers 169 languages in kotoshu-server 0.1.2</title>
    <link href="https://www.kotoshu.org/news/server-0-1-2/"/>
    <published>2026-09-07T00:00:00.000Z</published>
    <updated>2026-09-07T00:00:00.000Z</updated>
    <summary>Detection prefers the lid-176 model through the gem 0.10.0 native path, and the engine field reports which detector served the answer.</summary>
    <content type="html">&lt;p&gt;Detection prefers the lid-176 model through the gem 0.10.0 native path, and the engine field reports which detector served the answer.&lt;/p&gt;
&lt;p&gt;1. POST /v1/detect returns { language, confidence, engine }: lid-176 (176 languages, lazy model setup on first request) when kotoshu &amp;gt;= 0.10.0 and the native extension can load the model; heuristic (the 7-language fallback) otherwise - old gems, KOTOSHU_BACKEND=ruby, offline setup failures, or KOTOSHU_DETECT=heuristic. Setup failures log once and degrade; never a 5xx.&lt;/p&gt;
&lt;p&gt;2. The release also fixes a pre-existing failing build on main, where App::VERSION had drifted from the release-workflow bumps, and documents the engine field in the README and the OpenAPI schema.&lt;/p&gt;</content>
  </entry>
  <entry>
    <id>https://www.kotoshu.org/news/gem-0-10-0/</id>
    <title>Personal dictionaries in the check path and native detection in kotoshu 0.10.0</title>
    <link href="https://www.kotoshu.org/news/gem-0-10-0/"/>
    <published>2026-09-07T00:00:00.000Z</published>
    <updated>2026-09-07T00:00:00.000Z</updated>
    <summary>kotoshu check finally consults the personal dictionary, and Kotoshu.detect_language identifies 176 languages through the pure-Rust lid reader.</summary>
    <content type="html">&lt;p&gt;kotoshu check finally consults the personal dictionary, and Kotoshu.detect_language identifies 176 languages through the pure-Rust lid reader.&lt;/p&gt;
&lt;p&gt;1. The personal dictionary reaches the check path (plan 105): a word added with kotoshu personal add stops being an error on the next check - case-insensitive, no metadata, one load per process, mirroring the editor integration. Opt out with --no-personal or KOTOSHU_PERSONAL_DICTIONARY=false. Until now the README story was false on the CLI path.&lt;/p&gt;
&lt;p&gt;2. Kotoshu.detect_language -&amp;gt; { code, score } (plan 106): the lid-176 model through the native extension, ~42 microseconds warm, 55/55 parity with the reference on the frozen corpus (en 0.87, de 0.99, ja 0.998, ar 0.97 live). Pure-Ruby installs keep the 7-language heuristic; kotoshu-server /v1/detect upgrades to the 176-language path in 0.1.2.&lt;/p&gt;</content>
  </entry>
  <entry>
    <id>https://www.kotoshu.org/news/gem-0-9-3/</id>
    <title>Twelve more languages ship in the gem with kotoshu 0.9.3</title>
    <link href="https://www.kotoshu.org/news/gem-0-9-3/"/>
    <published>2026-09-07T00:00:00.000Z</published>
    <updated>2026-09-07T00:00:00.000Z</updated>
    <summary>Full-feature batch 3 reaches RubyGems with 32 languages carrying modules and keyboards, plus the right-to-left tokenizer fix, on the 0.9.2 indexed-sweep base.</summary>
    <content type="html">&lt;p&gt;Full-feature batch 3 reaches RubyGems with 32 languages carrying modules and keyboards, plus the right-to-left tokenizer fix, on the 0.9.2 indexed-sweep base.&lt;/p&gt;
&lt;p&gt;1. Cut from main after PR #151: ar, id, fa, he, bg, sr, hr, sk, sl, lt, lv, et as full-feature modules (national keyboard grids, AVAILABLE_LANGUAGES 20 to 32, 49 engine-verified specimens). The script-aware word regex fix means kotoshu check -l ar|fa|he extracts real words from RTL documents.&lt;/p&gt;
&lt;p&gt;2. The release sits on the 0.9.2 sweep index, so the new languages get the indexed sweep from the first install, and gem install kotoshu now resolves 0.9.3 for lsp and server users too.&lt;/p&gt;</content>
  </entry>
  <entry>
    <id>https://www.kotoshu.org/news/wasm-0-4-0/</id>
    <title>Language detection and OOV bucket tables in @kotoshu/wasm 0.4.0</title>
    <link href="https://www.kotoshu.org/news/wasm-0-4-0/"/>
    <published>2026-09-07T00:00:00.000Z</published>
    <updated>2026-09-07T00:00:00.000Z</updated>
    <summary>loadLid and detectLanguage bring 176-language identification, and bucket-backed out-of-vocabulary embedding lets Teh reach The through the model path.</summary>
    <content type="html">&lt;p&gt;loadLid and detectLanguage bring 176-language identification, and bucket-backed out-of-vocabulary embedding lets Teh reach The through the model path.&lt;/p&gt;
&lt;p&gt;1. The lid-176 model (~1 MB + vocab) ships through the registry v1.4.0 mirror. The playground detect control loads it once, scores the editor text, and proposes a language switch — never auto-switches an explicit choice.&lt;/p&gt;
&lt;p&gt;2. Bucket-table siblings for English and German close the model-side Teh gap: n-grams absent from the vocabulary fall back to hashed bucket rows, while in-vocabulary behavior stays byte-identical.&lt;/p&gt;</content>
  </entry>
  <entry>
    <id>https://www.kotoshu.org/news/full-feature-32/</id>
    <title>Twelve more full-feature languages bring the total to 32</title>
    <link href="https://www.kotoshu.org/news/full-feature-32/"/>
    <published>2026-09-07T00:00:00.000Z</published>
    <updated>2026-09-07T00:00:00.000Z</updated>
    <summary>Arabic, Indonesian, Persian, Hebrew, and eight European languages join the full-feature set: gem modules, national keyboards, and engine-verified specimens.</summary>
    <content type="html">&lt;p&gt;Arabic, Indonesian, Persian, Hebrew, and eight European languages join the full-feature set: gem modules, national keyboards, and engine-verified specimens.&lt;/p&gt;
&lt;p&gt;1. Plan 100 batch 3 promotes ar, id, fa, he, bg, sr, hr, sk, sl, lt, lv, and et from the degraded path to full feature. Enumeration was data-driven: every language present in both the dictionaries manifest and the models registry that lacked a module, ranked by speakers. ko and ne rank higher by speakers but need Hangul jamo and Devanagari tokenizers outside this batch.&lt;/p&gt;
&lt;p&gt;2. Six national keyboard grids (Arabic 101, Persian ISIRI 9147, Hebrew SI-1452, Bulgarian BDS, Serbian Cyrillic, Croatian/Slovenian QWERTZ) plus five parameterized Latin family members. AVAILABLE_LANGUAGES grows 20 to 32. A real bug fixed on the way: the script-aware word regex never reached the ar/fa/he tokenizers, so Kotoshu.check extracted zero words from RTL documents — those tokenizers now declare their script sets (fa includes ZWNJ).&lt;/p&gt;
&lt;p&gt;3. Forty-nine specimen pairs engine-verified across the twelve languages, plus RTL sentence round trips. Suite 3,887 examples, 0 failures.&lt;/p&gt;</content>
  </entry>
  <entry>
    <id>https://www.kotoshu.org/news/action-v2/</id>
    <title>GitHub Action v2 adds gem directory mode and baselines</title>
    <link href="https://www.kotoshu.org/news/action-v2/"/>
    <published>2026-09-07T00:00:00.000Z</published>
    <updated>2026-09-07T00:00:00.000Z</updated>
    <summary>The files input now walks the whole repository tree, and baselines, include/exclude, and SARIF suppression notes ship in the wrapper that CI actually runs.</summary>
    <content type="html">&lt;p&gt;The files input now walks the whole repository tree, and baselines, include/exclude, and SARIF suppression notes ship in the wrapper that CI actually runs.&lt;/p&gt;
&lt;p&gt;1. Version 1 expanded globs in bash and had no baseline input, even after the gem shipped directory mode and baselines in 0.8.0. Version 2 passes paths straight to kotoshu check, adds baseline, include, exclude, show_suppressed, and category inputs, and merges per-file SARIF runs so upload-sarif accepts the report.&lt;/p&gt;
&lt;p&gt;2. A self-test workflow runs the action against a fixture repository with two misspellings and a committed baseline: baselined entries pass as notes, new errors fail, and gitignored files stay out. The action requires gem 0.8.0 or newer, and the v2 tag was cut by the owner.&lt;/p&gt;</content>
  </entry>
  <entry>
    <id>https://www.kotoshu.org/news/gem-0-9-2/</id>
    <title>The sweep index reaches Ruby in kotoshu 0.9.2</title>
    <link href="https://www.kotoshu.org/news/gem-0-9-2/"/>
    <published>2026-09-07T00:00:00.000Z</published>
    <updated>2026-09-07T00:00:00.000Z</updated>
    <summary>Per-word sweep invariants now live in a lazily memoized per-dictionary index, which gives 2.2x on the English average and up to 6x on short words, with byte-identical outputs.</summary>
    <content type="html">&lt;p&gt;Per-word sweep invariants now live in a lazily memoized per-dictionary index, which gives 2.2x on the English average and up to 6x on short words, with byte-identical outputs.&lt;/p&gt;
&lt;p&gt;1. This release is the twin of the wasm 0.3.2 release: Kotoshu::Suggestions::SweepIndex memoizes character lengths, Soundex codes, and length buckets on the dictionary, built at the first sweep. The edit-distance strategy draws its length window from the buckets with word-list order restored so ranking tie order is untouched, the phonetic strategy compares memoized codes, and the n-gram gate reads indexed lengths; the strategies also stop copying the whole word list per sweep.&lt;/p&gt;
&lt;p&gt;2. Warm benchmarks on full cached dictionaries under MRI 3.4.8 show the English average dropping from 1,472 to 661 ms per suggest (2.2x), the Spanish average from 2,591 to 1,396 ms (1.9x), and short words gaining up to 6.2x, with Teh at 185 ms, wrold at 656 ms, and gatoss at 1,249 ms. Mutation safety is explicit: every add_word, remove_word, clear, and merge path resets the memo, pinned by specs on real Hunspell and PlainText dictionaries.&lt;/p&gt;
&lt;p&gt;3. Outputs byte-identical across 14 en+es combinations; the 2,630 conformance vectors untouched and replay green; suite 3,795 examples, 0 failures; rubocop clean over 447 files. Soundex now lives once in Algorithms::Soundex, shared by strategy and index.&lt;/p&gt;</content>
  </entry>
  <entry>
    <id>https://www.kotoshu.org/news/wasm-0-3-2/</id>
    <title>The per-dictionary sweep index ships in @kotoshu/wasm 0.3.2</title>
    <link href="https://www.kotoshu.org/news/wasm-0-3-2/"/>
    <published>2026-09-07T00:00:00.000Z</published>
    <updated>2026-09-07T00:00:00.000Z</updated>
    <summary>Per-word sweep invariants now live in a per-dictionary index built once at the first sweep, so heavy dictionaries gain another 1.2 to 6x, Portuguese foremost.</summary>
    <content type="html">&lt;p&gt;Per-word sweep invariants now live in a per-dictionary index built once at the first sweep, so heavy dictionaries gain another 1.2 to 6x, Portuguese foremost.&lt;/p&gt;
&lt;p&gt;1. The 0.3.1 rewrite still walked the whole word list per sweep, decoding each word before its gate — the length window, the Soundex code, the n-gram length bound — all values that never change with the query. 0.3.2 builds them once per dictionary: char lengths, Soundex codes packed into four bytes, and length buckets that let the edit-distance sweep touch only its two-length window (word-list order restored before the ranking sort, so tie order and outputs are untouched).&lt;/p&gt;
&lt;p&gt;2. Benchmarks over the pinned dictionaries show the average per sweep dropping for Portuguese from 1,398 to 423 ms with the worst case from 1,931 to 656 ms, for Spanish from 522 to 89 ms, for Norwegian from 346 to 277 ms, for German from 184 to 148 ms, for Russian from 226 to 205 ms, for Italian from 144 to 127 ms, and for English from 52 to 45 ms. The one remaining heavy case is a short French word whose length window covers a dense slice of the French vocabulary, which is the floor for this algorithm as frozen by the conformance contract.&lt;/p&gt;
&lt;p&gt;3. Conformance unchanged at 2,630 vectors, outputs byte-identical; every transposed-word typo in the benchmark still recovers its intended word in the top five.&lt;/p&gt;</content>
  </entry>
  <entry>
    <id>https://www.kotoshu.org/news/gem-0-9-1/</id>
    <title>The sweep fix reaches Ruby in kotoshu 0.9.1</title>
    <link href="https://www.kotoshu.org/news/gem-0-9-1/"/>
    <published>2026-09-07T00:00:00.000Z</published>
    <updated>2026-09-07T00:00:00.000Z</updated>
    <summary>Pure-Ruby suggestions drop from tens of seconds to under a second on full dictionaries, and the Damerau sweep ships for gem users, so Teh suggests The in first place.</summary>
    <content type="html">&lt;p&gt;Pure-Ruby suggestions drop from tens of seconds to under a second on full dictionaries, and the Damerau sweep ships for gem users, so Teh suggests The in first place.&lt;/p&gt;
&lt;p&gt;1. The patch release carries both suggestion-quality changes for gem users. The Damerau edit sweep charges transpositions one step, enumerates substitutions and insertions over the aff TRY string, and validates forms through affix-aware lookup, which puts Teh to The and definately to definitely in first place. The sweep-performance port builds one word index per generate instead of scanning the dictionary per keyboard variant, adds a length pre-gate ahead of the n-gram scan, computes Jaccard in one pass without the intermediate key-union array, and builds Soundex in reused buffers.&lt;/p&gt;
&lt;p&gt;2. Benchmarked on full en_US (48,262 words, MRI 3.4.8, pure-Ruby backend): Teh 20.6 s to 0.59 s, mispellings 140.2 s to 0.75 s, recieve 36.2 s to 0.70 s, definately 55.7 s to 0.87 s, asdfghjkl 39.6 s to 0.86 s. Suggestion outputs are byte-identical — the 2,630 conformance vectors are untouched, and equivalence fuzz against the old algorithms (6,004 find-word inputs, 22,011 soundex inputs, 2,986 similarity pairs) found zero mismatches.&lt;/p&gt;
&lt;p&gt;3. The dictionary data files that had ridden along under docs/verification-evidence are no longer packaged — the gem is 269 library files, no stray hunspell data. Suite 3,777 examples, 0 failures; rubocop clean.&lt;/p&gt;</content>
  </entry>
  <entry>
    <id>https://www.kotoshu.org/news/wasm-0-3-1/</id>
    <title>Suggestion sweeps complete in under a second with @kotoshu/wasm 0.3.1</title>
    <link href="https://www.kotoshu.org/news/wasm-0-3-1/"/>
    <published>2026-09-07T00:00:00.000Z</published>
    <updated>2026-09-07T00:00:00.000Z</updated>
    <summary>The suggestion sweep is 10 to 200x faster on full dictionaries, returning the same suggestions byte for byte in milliseconds instead of seconds.</summary>
    <content type="html">&lt;p&gt;The suggestion sweep is 10 to 200x faster on full dictionaries, returning the same suggestions byte for byte in milliseconds instead of seconds.&lt;/p&gt;
&lt;p&gt;1. A full-en_US sweep had been taking seconds, with Teh at 3.6 s, recieve at 17.3 s, and mispellings at 38.4 s measured over the published 0.3.0 module, because four allocation and scan patterns compounded per dictionary word: find_word scanned the whole word list per keyboard variant with a lowercase allocation per word, the n-gram strategy built a map of String trigrams per dictionary word, Soundex allocated a String per word, and the edit loops allocated a fresh char vector per word.&lt;/p&gt;
&lt;p&gt;2. The sweep now builds one word index per call (exact set plus lowercase-form map, borrowed for words already lowercase), packs trigrams into fixed-width integer keys in a reused scratch map with a length pre-gate, compares fixed Soundex keys, and reuses char buffers. Outputs are byte-identical: the 2630 conformance vectors all pass, and the benchmark set returns the same lists — Teh 320 ms, mispellings 189 ms, definately 145 ms, recieve 93 ms.&lt;/p&gt;
&lt;p&gt;3. The playground also sweeps as one batch now: the misspellings pane sends a single message for all its words, the worker walks the queue with a yield between words so a popover click jumps ahead, and a fresh check replaces the pending batch instead of stacking behind it.&lt;/p&gt;</content>
  </entry>
  <entry>
    <id>https://www.kotoshu.org/news/wasm-0-3-0/</id>
    <title>The Damerau sweep ranks the right word first in @kotoshu/wasm 0.3.0</title>
    <link href="https://www.kotoshu.org/news/wasm-0-3-0/"/>
    <published>2026-09-07T00:00:00.000Z</published>
    <updated>2026-09-07T00:00:00.000Z</updated>
    <summary>The Damerau edit sweep and model-generated candidates reach the browser: Teh now suggests The first, definately suggests definitely, and the playground shows every load and inference step.</summary>
    <content type="html">&lt;p&gt;The Damerau edit sweep and model-generated candidates reach the browser: Teh now suggests The first, definately suggests definitely, and the playground shows every load and inference step.&lt;/p&gt;
&lt;p&gt;1. The engine-side fix changes the suggestion sweep to enumerate adjacent transpositions at cost 1, substitutions and insertions over the aff TRY string, and deletions, each validated through affix-aware lookup so that dictionary forms like &lt;code&gt;definite/IYVP&lt;/code&gt; surface with their surface spelling. The root causes fixed were that the sweep had only ever enumerated stems, so suffixed words like &lt;code&gt;definitely&lt;/code&gt; could not appear at any distance; that the INITCAP form &lt;code&gt;The&lt;/code&gt; was lookup-valid but charged case plus transposition as two steps; and that the phonetic and keyboard strategies carried private edit-distance copies that still charged swaps double. Acceptance on full en_US, byte-identical across both engines: &lt;code&gt;Teh&lt;/code&gt; to &lt;code&gt;The&lt;/code&gt; at rank 1, &lt;code&gt;definately&lt;/code&gt; to &lt;code&gt;definitely&lt;/code&gt; at rank 1, with &lt;code&gt;recieve&lt;/code&gt; to &lt;code&gt;receive&lt;/code&gt; and &lt;code&gt;wrold&lt;/code&gt; to &lt;code&gt;world&lt;/code&gt; unregressed.&lt;/p&gt;
&lt;p&gt;2. &lt;code&gt;semanticSuggest(model, word, k)&lt;/code&gt; joins the wasm surface: the int8 tier embeds an out-of-vocabulary word through its character n-grams and returns the nearest vocabulary words — candidate generation the edit-distance sweep cannot produce. The playground merges those neighbors into suggestion lists ahead of its context rerank, labeled with their cosine.&lt;/p&gt;
&lt;p&gt;3. The playground itself grew instrumentation: every artifact download — engine, dictionary, the optional semantic tier — reports a phase-labeled byte bar, checking reports the busy dot and elapsed milliseconds, the misspellings pane sweeps with per-word spinners and a done-of-total count, and the suggestion popover closes with a sweep and rerank timing footer. 2630 conformance vectors regenerated for the new sweep, zero divergence between the Ruby and Rust engines.&lt;/p&gt;</content>
  </entry>
  <entry>
    <id>https://www.kotoshu.org/news/server-lsp-0-1-1/</id>
    <title>kotoshu-server and kotoshu-lsp 0.1.1 republish with their real contents</title>
    <link href="https://www.kotoshu.org/news/server-lsp-0-1-1/"/>
    <published>2026-09-06T00:00:00.000Z</published>
    <updated>2026-09-06T00:00:00.000Z</updated>
    <summary>The two ecosystem gems republish with their actual contents after the empty 0.1.0 cuts: kotoshu-server brings semantic models over HTTP, and kotoshu-lsp brings a personal dictionary that un-flags words.</summary>
    <content type="html">&lt;p&gt;The two ecosystem gems republish with their actual contents after the empty 0.1.0 cuts: kotoshu-server brings semantic models over HTTP, and kotoshu-lsp brings a personal dictionary that un-flags words.&lt;/p&gt;
&lt;p&gt;1. kotoshu-server 0.1.1 makes &lt;code&gt;gem install kotoshu-server&lt;/code&gt; work. The 0.1.0 cut had been published with an empty file list because its gemspec collected files through &lt;code&gt;git ls-files&lt;/code&gt; in a build environment without git. Version 0.1.1 ships the real server: &lt;code&gt;/v1/check&lt;/code&gt; with the optional &lt;code&gt;model&lt;/code&gt; flag providing cascade-guarded ONNX reranking memoized per language, &lt;code&gt;/v1/languages&lt;/code&gt; reporting model availability, and boot-time opt-in through &lt;code&gt;KOTOSHU_SERVER_MODEL_LANGS&lt;/code&gt; and &lt;code&gt;KOTOSHU_SERVER_MODEL_TIER&lt;/code&gt;, bringing semantic quality to every SDK user with no implicit downloads.&lt;/p&gt;
&lt;p&gt;2. kotoshu-lsp 0.1.1 reads the personal dictionary at &lt;code&gt;~/.config/kotoshu/personal.dic&lt;/code&gt;, reloads it when the file changes, and answers &lt;code&gt;kotoshu.addToPersonalDictionary&lt;/code&gt; server-side, so adding a word republishes diagnostics in any LSP editor and the flag clears immediately. The first-diagnostic column bug (a −11 offset on didOpen) is fixed as well.&lt;/p&gt;
&lt;p&gt;3. Both published through RubyGems trusted publishing — the OIDC exchange, the version bump, and the push all ran in CI with no stored credentials. The empty 0.1.0s stay listed: rubygems does not allow self-yanking versions older than 30 days; install unpinned and you get 0.1.1.&lt;/p&gt;</content>
  </entry>
  <entry>
    <id>https://www.kotoshu.org/news/gem-0-9-0/</id>
    <title>kotoshu 0.9.0 adds Norwegian and fixes dictionary corruption</title>
    <link href="https://www.kotoshu.org/news/gem-0-9-0/"/>
    <published>2026-09-06T00:00:00.000Z</published>
    <updated>2026-09-06T00:00:00.000Z</updated>
    <summary>Norwegian Bokmål and the no alias join the twenty language modules, and the long-reported remove_word corruption bug is fixed on RubyGems.</summary>
    <content type="html">&lt;p&gt;Norwegian Bokmål and the no alias join the twenty language modules, and the long-reported remove_word corruption bug is fixed on RubyGems.&lt;/p&gt;
&lt;p&gt;1. Norwegian joins the module roster: registry v1.3.0 ships nb converted from fastText’s Bokmål-dominated cc.no while nn keeps cc.nn — and the gem now resolves both &lt;code&gt;nb&lt;/code&gt; and the ISO macro-language &lt;code&gt;no&lt;/code&gt; to the same Bokmål module, with å æ ø tokenizing as word characters through the shared Latin tokenizer.&lt;/p&gt;
&lt;p&gt;2. The dictionary-mutation bugs first reported in PR #93 are fixed and released: remove_word deleted the wrong word after a prior removal, the PlainText length index drifted out of sync on add and remove, and the suggest hot path could download implicitly — it is now cache-only with offline mode enforced, and &lt;code&gt;KOTOSHU_OFFLINE&lt;/code&gt; genuinely works through default configuration.&lt;/p&gt;
&lt;p&gt;3. Also in the cut: &lt;code&gt;NearestNeighbor&lt;/code&gt; accepts the full cosine range (in-vocabulary words no longer crash semantic analysis on rounding drift or true negatives), and the plan corpus — every TODO.impl record from 01 to 98 — is finally tracked in the repository.&lt;/p&gt;</content>
  </entry>
  <entry>
    <id>https://www.kotoshu.org/news/gem-0-8-0/</id>
    <title>kotoshu 0.8.0 ships the integrations wave</title>
    <link href="https://www.kotoshu.org/news/gem-0-8-0/"/>
    <published>2026-09-06T00:00:00.000Z</published>
    <updated>2026-09-06T00:00:00.000Z</updated>
    <summary>The wave-1 program reaches RubyGems in one cut, bringing Unicode word detection for Greek and Cyrillic, directory-mode checking, baselines, inline ignores, and framework integrations for Rails, RSpec, Rake, and Jekyll.</summary>
    <content type="html">&lt;p&gt;The wave-1 program reaches RubyGems in one cut, bringing Unicode word detection for Greek and Cyrillic, directory-mode checking, baselines, inline ignores, and framework integrations for Rails, RSpec, Rake, and Jekyll.&lt;/p&gt;
&lt;p&gt;1. kotoshu 0.8.0 puts the whole wave-1 program on RubyGems in one cut: the thirteen language modules and nineteen keyboard layouts, directory-mode checking, CI baselines, inline ignore directives, a pre-commit hook, and four framework integrations, with no new runtime dependencies anywhere. The release also repairs remote &lt;code&gt;kotoshu setup&lt;/code&gt; for staged languages through a sublayout-first, flat-fallback strategy, lets &lt;code&gt;kotoshu/tasks&lt;/code&gt; and &lt;code&gt;kotoshu/jekyll&lt;/code&gt; load standalone, and compares baseline paths canonically.&lt;/p&gt;
&lt;p&gt;2. Unicode word detection is the headline fix: word extraction had accepted only ASCII letters, so Greek and Ukrainian users could not check any text through the CLI. Extraction now follows the configured language’s tokenizer, using Greek for &lt;code&gt;el&lt;/code&gt; and Cyrillic for &lt;code&gt;uk&lt;/code&gt; with the in-word apostrophe kept (Мар’яна), and Latin capitals such as Å and Ä for Latin languages, while languages without a script tokenizer keep the historical behavior and the frozen conformance vectors are unchanged. Swedish dictionary loading is fixed alongside: &lt;code&gt;COMPOUNDRULE )k&lt;/code&gt; uses &lt;code&gt;)&lt;/code&gt; itself as a flag character, and every flag is now escaped at compile time so the affix reader no longer raises.&lt;/p&gt;
&lt;p&gt;3. Directory mode — &lt;code&gt;kotoshu check DIR [DIR ...]&lt;/code&gt; — checks every file with a known text extension under &lt;code&gt;--include&lt;/code&gt; / &lt;code&gt;--exclude&lt;/code&gt; control, honoring &lt;code&gt;.gitignore&lt;/code&gt; and &lt;code&gt;.ignore&lt;/code&gt; through a standard glob subset (last-match wins, anchoring, nested scoping; files inside ignored directories cannot be re-included) and skipping hidden files plus &lt;code&gt;.git&lt;/code&gt;, &lt;code&gt;node_modules&lt;/code&gt;, &lt;code&gt;vendor&lt;/code&gt;, and &lt;code&gt;target&lt;/code&gt; by default. JSON and SARIF emit one combined document with per-file entries, &lt;code&gt;--baseline&lt;/code&gt; applies per file, and single-file and stdin behavior is byte-identical to before.&lt;/p&gt;
&lt;p&gt;4. Ignores and baselines arrive as a pair: &lt;code&gt;kotoshu:disable-line&lt;/code&gt;, &lt;code&gt;disable-next-line [WORDS]&lt;/code&gt;, and the nestable &lt;code&gt;disable-file&lt;/code&gt; / &lt;code&gt;enable-file&lt;/code&gt; block are recognized in each format’s comment syntax, with suppressed words moving to &lt;code&gt;suppressed_errors&lt;/code&gt; — listed by &lt;code&gt;--show-suppressed&lt;/code&gt; and marked in result JSON and SARIF. &lt;code&gt;kotoshu baseline init&lt;/code&gt; records existing debt count-based, so baselines survive reformatting; &lt;code&gt;check --baseline&lt;/code&gt; lets covered errors pass, fails new ones, and reports stale entries as the debt shrinks.&lt;/p&gt;
&lt;p&gt;5. The integrations are opt-in and dependency-free: an ActiveModel &lt;code&gt;SpellingValidator&lt;/code&gt; that raises one validation error per misspelling with the top suggestion in the message (real ActiveModel standalone — Rails not required), RSpec matchers whose failures list each misspelling and its suggestions, a Rake task over repository text files, and a safe Jekyll generator that fails the build on new spelling errors while a &lt;code&gt;.kotoshu-baseline.json&lt;/code&gt; in the site source keeps baselined debt from blocking builds. The pre-commit hook (id &lt;code&gt;kotoshu&lt;/code&gt;, &lt;code&gt;language: system&lt;/code&gt;) ships too — honestly documented as requiring Ruby and the gem on PATH.&lt;/p&gt;
&lt;p&gt;6. Norwegian is not in this cut. The registry added nb at v1.3.0 today, but the gem-side &lt;code&gt;no&lt;/code&gt; → &lt;code&gt;nb&lt;/code&gt; alias and the Norwegian language module are next-cut work; 0.8.0’s thirteen new modules are the wave-1 thirteen and no more.&lt;/p&gt;</content>
  </entry>
  <entry>
    <id>https://www.kotoshu.org/news/wasm-0-2-0/</id>
    <title>Semantic reranking in the browser with @kotoshu/wasm 0.2.0</title>
    <link href="https://www.kotoshu.org/news/wasm-0-2-0/"/>
    <published>2026-09-06T00:00:00.000Z</published>
    <updated>2026-09-06T00:00:00.000Z</updated>
    <summary>The wasm engine gains the semantic path with loadModel and rerank over the int8 tiers, and CORS-open mirrors put all 55 languages within reach of a browser tab.</summary>
    <content type="html">&lt;p&gt;The wasm engine gains the semantic path with loadModel and rerank over the int8 tiers, and CORS-open mirrors put all 55 languages within reach of a browser tab.&lt;/p&gt;
&lt;p&gt;1. &lt;code&gt;loadModel(model_bytes, vocab_bytes)&lt;/code&gt; loads an int8-per-row embedding tier — mini ~3 MB, fluency ~15 MB — from ONNX bytes plus its &lt;code&gt;.vocab.json&lt;/code&gt; sibling, returning a &lt;code&gt;KotoshuModel&lt;/code&gt; that is the wasm twin of the gem’s ONNX provider, scored in pure Rust. &lt;code&gt;rerank(model, word, context)&lt;/code&gt; returns the mean-cosine context score in [-1, 1] — 0.0 when the word or every token is out of vocabulary — so suggestion lists can be reordered in the browser the way the server does it. TypeScript declarations ship in the package.&lt;/p&gt;
&lt;p&gt;2. The mirrors make that fetchable: registry mirror URLs send &lt;code&gt;Access-Control-Allow-Origin: *&lt;/code&gt; while GitHub release assets send no CORS header at all, so a browser tab can resolve a model tier for any of the 55 languages and pull it without a server in between. Version 0.2.0 was built and signed by the kotoshu-rs release workflow with a provenance attestation and zero dependencies.&lt;/p&gt;
&lt;p&gt;3. The Ruby API got its hosted reference the same morning: the YARD documentation is live at kotoshu.github.io/kotoshu/ — served from the site domain, deployed from the gem repository’s main branch — and already covers the 0.8.0 surfaces: model tiers and the confidence cascade, inline ignores, CI baselines, and the pre-commit hook.&lt;/p&gt;</content>
  </entry>
  <entry>
    <id>https://www.kotoshu.org/news/models-v1-3-0/</id>
    <title>Semantic models cover 55 languages; Norwegian Bokmål arrives</title>
    <link href="https://www.kotoshu.org/news/models-v1-3-0/"/>
    <published>2026-09-06T00:00:00.000Z</published>
    <updated>2026-09-06T00:00:00.000Z</updated>
    <summary>The registry adds Norwegian Bokmål, with nb converted from fastText’s cc.no while nn keeps cc.nn, for a total of 55 languages and 165 tiered models behind the same eval gates.</summary>
    <content type="html">&lt;p&gt;The registry adds Norwegian Bokmål, with nb converted from fastText’s cc.no while nn keeps cc.nn, for a total of 55 languages and 165 tiered models behind the same eval gates.&lt;/p&gt;
&lt;p&gt;1. Registry v1.3.0 ships nb × 3 tiers — mini 2.9 MiB, fluency 14.5 MiB, full 114.4 MiB — bringing the registry to 55 languages, 165 resources, and 7.1 GiB at ONNX opset 11, behind the same measured per-tier evals that gate every other language.&lt;/p&gt;
&lt;p&gt;2. fastText publishes no &lt;code&gt;cc.nb&lt;/code&gt;: the nb models are converted from &lt;code&gt;cc.no&lt;/code&gt; and carry Bokmål provenance — &lt;code&gt;models/nb/metadata.json&lt;/code&gt; records the source URL and sha256 of &lt;code&gt;cc.no.300.vec&lt;/code&gt; — while &lt;code&gt;nn&lt;/code&gt; ships separately from &lt;code&gt;cc.nn&lt;/code&gt;, so both written standards of Norwegian are in the registry under their own codes.&lt;/p&gt;
&lt;p&gt;3. The registry itself carries no &lt;code&gt;no&lt;/code&gt; entries: the ISO macro-language code resolves to &lt;code&gt;nb&lt;/code&gt; on the engine side, and that alias — with the Norwegian language module — is next-cut gem work, not part of 0.8.0.&lt;/p&gt;
&lt;p&gt;4. That answers the no→nb/nn question this record left as an owner decision at v1.2.0, and it exhausts the convertible pool: what remains — fi sourcing and the nds resource-spec call — is owner decision, not pending work.&lt;/p&gt;</content>
  </entry>
  <entry>
    <id>https://www.kotoshu.org/news/models-v1-2-0/</id>
    <title>Semantic models cover 54 languages</title>
    <link href="https://www.kotoshu.org/news/models-v1-2-0/"/>
    <published>2026-09-05T00:00:00.000Z</published>
    <updated>2026-09-05T00:00:00.000Z</updated>
    <summary>The models registry grows from 22 to 54 languages, with 32 new languages shipped including the first right-to-left languages, behind unchanged eval gates.</summary>
    <content type="html">&lt;p&gt;The models registry grows from 22 to 54 languages, with 32 new languages shipped including the first right-to-left languages, behind unchanged eval gates.&lt;/p&gt;
&lt;p&gt;1. Registry v1.2.0 ships 32 new languages × 3 tiers for a total of 54 languages and 162 registry resources. Arabic, Persian, and Hebrew arrive as the registry’s first right-to-left languages, with new dictionaries verified against upstream license headers where none existed.&lt;/p&gt;
&lt;p&gt;2. The gates did not move, with fluency held at rank correlation 0.97 and top-1 0.95 and mini at 0.90 and 0.85, never weakened, and the whole batch clears them comfortably, with fluency at 0.9999 to 1.0000 correlation and mini near-lossless. The keyboard-aware evaluation grew ten more curated national grids so the newcomer languages are judged on their own keyboards.&lt;/p&gt;
&lt;p&gt;3. Not everything that converts ships. The nds language passed both gates but is ISO 639-2 only, while the registry’s language contract is two-letter codes; fi has no license-clear Hunspell source upstream; and fo, rw, ie, fur, and tlh have no fastText Common Crawl vectors at all. Every drop is recorded with its reason in the README.&lt;/p&gt;
&lt;p&gt;4. The candidate pool is now exhausted: every convertible language either ships or is dropped for a stated reason, so the coverage backlog is empty. What remains, namely the no→nb/nn alias, fi sourcing, and the nds Resource Spec call, is an owner decision rather than pending work.&lt;/p&gt;</content>
  </entry>
  <entry>
    <id>https://www.kotoshu.org/news/full-feature-19/</id>
    <title>Nineteen languages reach full-feature support</title>
    <link href="https://www.kotoshu.org/news/full-feature-19/"/>
    <published>2026-09-05T00:00:00.000Z</published>
    <updated>2026-09-05T00:00:00.000Z</updated>
    <summary>Thirteen language modules and a wave of keyboard layouts land in the gem, and full-feature support grows from six languages to nineteen.</summary>
    <content type="html">&lt;p&gt;Thirteen language modules and a wave of keyboard layouts land in the gem, and full-feature support grows from six languages to nineteen.&lt;/p&gt;
&lt;p&gt;1. Language modules for ca, cs, da, el, hu, it, nl, pl, ro, sv, tr, uk, and vi — thin compositions over the shared Latin tokenizer and normalizer, with real care where the script demands it: Turkish dotless-i case folding, Greek final-sigma and accent normalization, and Greek and Cyrillic script tokenizers that keep non-Latin words whole.&lt;/p&gt;
&lt;p&gt;2. Keyboard layouts grow from five to nineteen: the Turkish-Q, Ukrainian-JCUKEN, and Greek-Phonetic national grids are mirrored from the models-repo eval harness with a drift spec guarding the mirror, and an eleven-member Latin family carries the real Nordic å/æ/ø and å/ä/ö keys over the qwerty and qwertz base grids.&lt;/p&gt;
&lt;p&gt;3. The CLI learns directory mode — &lt;code&gt;kotoshu check DIR&lt;/code&gt; walks trees, honors &lt;code&gt;.gitignore&lt;/code&gt; and &lt;code&gt;.ignore&lt;/code&gt;, and applies baselines per file — with baselines wired into CI so existing errors never block a build while new ones still fail it.&lt;/p&gt;
&lt;p&gt;4. Framework integrations with no new runtime dependencies: a Rails/ActiveModel spelling validator, RSpec matchers that print each misspelling with its suggestions, a Rake task over repository text files, and a Jekyll generator that fails the build on new spelling errors.&lt;/p&gt;</content>
  </entry>
  <entry>
    <id>https://www.kotoshu.org/news/models-v1-1-0/</id>
    <title>Semantic models cover 22 languages</title>
    <link href="https://www.kotoshu.org/news/models-v1-1-0/"/>
    <published>2026-09-05T00:00:00.000Z</published>
    <updated>2026-09-05T00:00:00.000Z</updated>
    <summary>The models registry grows from 9 to 22 languages, with thirteen new FastText reranking tiers shipped behind the same eval gates.</summary>
    <content type="html">&lt;p&gt;The models registry grows from 9 to 22 languages, with thirteen new FastText reranking tiers shipped behind the same eval gates.&lt;/p&gt;
&lt;p&gt;1. Registry v1.1.0 adds ca, cs, da, el, hu, it, nl, pl, ro, sv, tr, uk, and vi — every batch-one language whose dictionary exists — for a total of 22 languages × 3 tiers, 66 registry resources.&lt;/p&gt;
&lt;p&gt;2. The gates did not move: every fluency tier holds rank correlation 0.9999 with top-1 of at least 0.958, every mini tier is near-lossless, and a language that fails its gates ships nothing.&lt;/p&gt;
&lt;p&gt;3. The keyboard-aware eval grew with them — QWERTY/QWERTZ supplements plus curated Turkish-Q, Ukrainian ЙЦУКЕН, and Greek-phonetic noise grids — so newcomer languages are judged on their own keyboards.&lt;/p&gt;
&lt;p&gt;4. The released registry.json is byte-identical to the committed one: local rebuilds reproduce the CI sha256 exactly, so future expansions are verifiable, not trusted.&lt;/p&gt;</content>
  </entry>
  <entry>
    <id>https://www.kotoshu.org/news/keyless-publishing/</id>
    <title>Keyless publishing on every channel</title>
    <link href="https://www.kotoshu.org/news/keyless-publishing/"/>
    <published>2026-09-05T00:00:00.000Z</published>
    <updated>2026-09-05T00:00:00.000Z</updated>
    <summary>Releases now reach npm, RubyGems, and crates.io through CI-held OIDC trust — no long-lived tokens stored anywhere.</summary>
    <content type="html">&lt;p&gt;Releases now reach npm, RubyGems, and crates.io through CI-held OIDC trust — no long-lived tokens stored anywhere.&lt;/p&gt;
&lt;p&gt;1. npm publishes &lt;code&gt;@kotoshu/client&lt;/code&gt; and &lt;code&gt;@kotoshu/wasm&lt;/code&gt; keyless: the release workflow exchanges GitHub’s OIDC identity for registry trust, and every artifact carries a provenance attestation.&lt;/p&gt;
&lt;p&gt;2. crates.io trusted publishing (RFC 3691) is registered and verified for the &lt;code&gt;kotoshu&lt;/code&gt; crate — the exchange was proven by a smoke dispatch before the first release. The first publish of a crate still needs a token; keyless covers 0.1.1 onward.&lt;/p&gt;
&lt;p&gt;3. RubyGems is wired the same way — the gem’s release workflow plus the owner-side registration — so &lt;code&gt;gem push&lt;/code&gt; never runs on a stored credential.&lt;/p&gt;</content>
  </entry>
  <entry>
    <id>https://www.kotoshu.org/news/gem-0-7-0/</id>
    <title>kotoshu 0.7.0 ships model tiers and the native extension</title>
    <link href="https://www.kotoshu.org/news/gem-0-7-0/"/>
    <published>2026-09-05T00:00:00.000Z</published>
    <updated>2026-09-05T00:00:00.000Z</updated>
    <summary>The biggest gem release so far brings tiered models with a registry, the native extension, and a conformance-frozen engine.</summary>
    <content type="html">&lt;p&gt;The biggest gem release so far brings tiered models with a registry, the native extension, and a conformance-frozen engine.&lt;/p&gt;
&lt;p&gt;1. The model tiers are &lt;code&gt;full&lt;/code&gt; at about 120 MB, &lt;code&gt;fluency&lt;/code&gt; at about 15 MB as the new default, and &lt;code&gt;mini&lt;/code&gt; at about 3 MB, and they resolve through the models repository’s registry with SHA-256-verified primary, mirror, and vocab downloads. &lt;code&gt;KOTOSHU_MODEL_TIER&lt;/code&gt;, &lt;code&gt;setup --model --tier&lt;/code&gt;, and a tier-less legacy-cache bridge keep older caches loading.&lt;/p&gt;
&lt;p&gt;2. The optional native extension compiles the Rust core into the gem, &lt;code&gt;KOTOSHU_BACKEND=ruby|native|auto&lt;/code&gt; selects it, and the Ruby and Rust engines agree on all 2,630 frozen conformance vectors.&lt;/p&gt;
&lt;p&gt;3. A confidence cascade skips the ONNX rerank when the composite strategies are already confident — semantic quality where it matters, plain speed where it does not.&lt;/p&gt;
&lt;p&gt;4. Hunspell correctness: CHECKCOMPOUNDPATTERN replacement support, dot-split casing, INITCAP ngram-root skip, and AF alias flag parsing. The integrational suite runs 176 examples with zero failures.&lt;/p&gt;</content>
  </entry>
  <entry>
    <id>https://www.kotoshu.org/news/npm-and-crates-io-live/</id>
    <title>The engine ships on npm and crates.io</title>
    <link href="https://www.kotoshu.org/news/npm-and-crates-io-live/"/>
    <published>2026-09-05T00:00:00.000Z</published>
    <updated>2026-09-05T00:00:00.000Z</updated>
    <summary>@kotoshu/client and @kotoshu/wasm are on npm and the kotoshu crate is on crates.io, all at 0.1.0.</summary>
    <content type="html">&lt;p&gt;@kotoshu/client and @kotoshu/wasm are on npm and the kotoshu crate is on crates.io, all at 0.1.0.&lt;/p&gt;
&lt;p&gt;1. &lt;code&gt;@kotoshu/client&lt;/code&gt; 0.1.0 is the typed HTTP client for Node 18+, Deno, Bun, and browsers, covering check, suggest, detect, and correct.&lt;/p&gt;
&lt;p&gt;2. &lt;code&gt;@kotoshu/wasm&lt;/code&gt; 0.1.0 is the whole engine compiled to WebAssembly at 291 KiB gzipped; a consumer constructs a dictionary from &lt;code&gt;.aff&lt;/code&gt;/&lt;code&gt;.dic&lt;/code&gt; contents and checks words in-process and offline.&lt;/p&gt;
&lt;p&gt;3. &lt;code&gt;kotoshu&lt;/code&gt; 0.1.0 on crates.io is the Rust core itself, exposing &lt;code&gt;Dictionary::load&lt;/code&gt;, &lt;code&gt;correct&lt;/code&gt;, ranked &lt;code&gt;suggest&lt;/code&gt;, the batch C ABI, and the models registry behind the &lt;code&gt;resources&lt;/code&gt; feature.&lt;/p&gt;</content>
  </entry>
  <entry>
    <id>https://www.kotoshu.org/news/pypi-live/</id>
    <title>Python packages ship on PyPI</title>
    <link href="https://www.kotoshu.org/news/pypi-live/"/>
    <published>2026-09-04T00:00:00.000Z</published>
    <updated>2026-09-04T00:00:00.000Z</updated>
    <summary>The Python HTTP client and the maturin wheel that embeds the Rust engine both ship at 0.1.0.</summary>
    <content type="html">&lt;p&gt;The Python HTTP client and the maturin wheel that embeds the Rust engine both ship at 0.1.0.&lt;/p&gt;
&lt;p&gt;1. &lt;code&gt;kotoshu&lt;/code&gt; 0.1.0 is the Python client, exposing &lt;code&gt;Client.check&lt;/code&gt;, &lt;code&gt;suggest&lt;/code&gt;, &lt;code&gt;detect&lt;/code&gt;, and &lt;code&gt;correct&lt;/code&gt; over the HTTP API with the same result types the other SDKs use.&lt;/p&gt;
&lt;p&gt;2. &lt;code&gt;kotoshu-native&lt;/code&gt; 0.1.0 is a maturin-built wheel embedding the Rust engine. &lt;code&gt;KOTOSHU_BACKEND=native|http|auto&lt;/code&gt; picks the backend, and word-level checking runs fully offline with no server involved.&lt;/p&gt;
&lt;p&gt;3. Result handling is identical across backends: the same &lt;code&gt;Suggestion&lt;/code&gt; rows come back whether the engine runs in-process or over the wire.&lt;/p&gt;</content>
  </entry>
  <entry>
    <id>https://www.kotoshu.org/news/engine-correctness-wave/</id>
    <title>Engine correctness wave: compound semantics and green conformance</title>
    <link href="https://www.kotoshu.org/news/engine-correctness-wave/"/>
    <published>2026-09-04T00:00:00.000Z</published>
    <updated>2026-09-04T00:00:00.000Z</updated>
    <summary>CHECKCOMPOUNDPATTERN replacement semantics are ported, and all 2,630 conformance vectors pass in both the Ruby and the Rust engine.</summary>
    <content type="html">&lt;p&gt;CHECKCOMPOUNDPATTERN replacement semantics are ported, and all 2,630 conformance vectors pass in both the Ruby and the Rust engine.&lt;/p&gt;
&lt;p&gt;1. The gem’s CHECKCOMPOUNDPATTERN replacement semantics, the subtlest rule in the compound family, are ported to the Rust core, with the conformance vector pack regenerated from the gem’s engine.&lt;/p&gt;
&lt;p&gt;2. All 2,630 frozen vectors, comprising 1,315 &lt;code&gt;correct&lt;/code&gt; and 1,315 &lt;code&gt;suggest&lt;/code&gt; cases, pass in the Ruby engine, the Rust engine, and over the C ABI. Both sides of the conformance suite run in CI, so behavior cannot drift.&lt;/p&gt;</content>
  </entry>
  <entry>
    <id>https://www.kotoshu.org/news/models-registry-v1-0-1/</id>
    <title>Models registry v1.0.1 serves nine languages in three tiers</title>
    <link href="https://www.kotoshu.org/news/models-registry-v1-0-1/"/>
    <published>2026-09-03T00:00:00.000Z</published>
    <updated>2026-09-03T00:00:00.000Z</updated>
    <summary>FastText-ONNX embedding models for nine languages ship in full, fluency, and mini tiers.</summary>
    <content type="html">&lt;p&gt;FastText-ONNX embedding models for nine languages ship in full, fluency, and mini tiers.&lt;/p&gt;
&lt;p&gt;1. One registry, addressed as &lt;code&gt;kotoshu://models/{lang}/{tier}&lt;/code&gt;, resolves every model with SHA-256 checksums, license, and minimum engine version; clients try the primary URL, then the mirror, then the vocab.&lt;/p&gt;
&lt;p&gt;2. Per-tier evaluation reports are published for each language. &lt;code&gt;fluency&lt;/code&gt; is int8 with the top 50,000 words and near-lossless, while &lt;code&gt;mini&lt;/code&gt; is the wasm and edge tier at about 3 MB.&lt;/p&gt;
&lt;p&gt;3. The &lt;code&gt;full&lt;/code&gt; tier at about 120 MB also serves from a media-host mirror, so the first setup does not lean on release bandwidth.&lt;/p&gt;</content>
  </entry>
  <entry>
    <id>https://www.kotoshu.org/news/site-launch/</id>
    <title>kotoshu.org goes live</title>
    <link href="https://www.kotoshu.org/news/site-launch/"/>
    <published>2026-09-01T00:00:00.000Z</published>
    <updated>2026-09-01T00:00:00.000Z</updated>
    <summary>The ecosystem site opens as a catalog of the project, its languages, and its documentation.</summary>
    <content type="html">&lt;p&gt;The ecosystem site opens as a catalog of the project, its languages, and its documentation.&lt;/p&gt;
&lt;p&gt;1. The site carries one page per audience, one page per language, seven documentation pages, and a playground that runs the real engine against any kotoshu-server.&lt;/p&gt;
&lt;p&gt;2. The design treats the site itself as a dictionary, with headwords, part-of-speech lines, and numbered senses throughout.&lt;/p&gt;</content>
  </entry>
  <entry>
    <id>https://www.kotoshu.org/news/ring-around-the-gem/</id>
    <title>The ecosystem around the gem: LSP, server, Go client, and Action</title>
    <link href="https://www.kotoshu.org/news/ring-around-the-gem/"/>
    <published>2026-08-01T00:00:00.000Z</published>
    <updated>2026-08-01T00:00:00.000Z</updated>
    <summary>kotoshu-lsp, kotoshu-server, kotoshu-go, and action-kotoshu all reach their first releases.</summary>
    <content type="html">&lt;p&gt;kotoshu-lsp, kotoshu-server, kotoshu-go, and action-kotoshu all reach their first releases.&lt;/p&gt;
&lt;p&gt;1. &lt;code&gt;kotoshu-lsp&lt;/code&gt; provides diagnostics, quick-fixes, and hover suggestions in any editor that speaks LSP.&lt;/p&gt;
&lt;p&gt;2. &lt;code&gt;kotoshu-server&lt;/code&gt; provides seven JSON endpoints over Rack, Sinatra, and Puma, forming the deployment surface for every SDK.&lt;/p&gt;
&lt;p&gt;3. &lt;code&gt;kotoshu-go&lt;/code&gt; and &lt;code&gt;action-kotoshu&lt;/code&gt; provide a Go client with context-aware methods and a GitHub Action that lands SARIF in the Security tab.&lt;/p&gt;</content>
  </entry>
</feed>
