1.0.1 - 2026-08-24
Release Notes
Added
-
A page about which shape to deploy in. docs/deployment-topologies.md
answers three questions the reference pages each answer a piece of: whether to
let a client spawngrooveor to leave one running, what residency actually
buys, and where the same-host boundary comes from.It began as an internal note measured against v0.26.0 and was re-measured
against v1.0.0 before publishing, because the two releases in between changed
exactly what it was about./api/search— which its benchmark named and its
fourth open question argued about — no longer exists. Origin validation, which
it listed as unresolved, ships on by default. All four of its open questions
were settled before 1.0.0, so they appear as outcomes with the ADR that
records each one, rather than as questions.The measurements are new: a resident daemon answers a search in about 200 ms
where the CLI takes about 3.1 seconds. The page splits that three seconds into
three terms and says which two were measured — process and database setup at
about 35 ms, the search itself at about 200 ms — leaving the model load, about
2.9 seconds, as the one derived by subtraction. It also says the thing the
internal note did not: residency is not the same as speed. A first query after hours
idle took 4.6 seconds, and a CLI search running alongside the daemon dragged it
from 200 ms to 2 seconds, which is the page's own "one process, one model"
warning arriving as latency.Nothing in it cites a line number. The version it replaced cited eleven, and
all eleven were wrong within five days.
Fixed
-
The reranker's documented latency was wrong by two orders of magnitude.
--helpand docs/usage.md said rerank adds "300–700 ms per
query on CPU withbge-v2-m3over 50 candidates". Measured against 1.0.0 on
one Windows machine, the same query takes 3.1–3.6 s without it and 74–87 s
with it throughgroove search, and 0.1 s against 74–79 s through a resident
daemon. Residency does not help: the daemon builds the reranker at startup, so
its second and later reranked queries have no model left to load and still take
74–79 s. The cost is the cross-encoder pass over the candidate pool.The number, the
--helpline, and the recommendation table built on the
number are replaced by the measurement and the conditions it was taken under.
Nothing about reranking changed — only what the tool says it costs, and
therefore the advice about when to switch it on. -
docs/mcp-tools.mddated therebuild_indexbound to a version that never
existed. It said the one-at-a-time refusal arrived inv0.28.0; 0.27.0 was
followed by 1.0.0, so there is no such release. The bound shipped in 1.0.0 and
the page now says so.
Internal
-
A Markdown link that no longer resolves now fails the test suite.
grooveseek/tests/docs_links_resolve.rswalks every.mdfile in the
repository and checks two things about each relative destination: that the file
is there, and that an#anchormatches a heading GitHub would generate in it.
It found one, in docs/stability.ja.md, which had
carried the English page's#stablesince it was translated — a link that
opened the right page at the wrong place for anyone who followed it. The
Japanese anchor is#コマンドライン.A throwaway script checked this once by hand during the README split and then
lived in a scratch directory. This is that check in the tree: 70 pages, 489
relative destinations, 35 of them anchored, 17 of those with Japanese
fragments.The anchor half follows
github-slugger, the implementation the remark and
MDX toolchains use to reproduce GitHub's anchors: downcase, delete everything
outside[\p{Word}\- ], then turn spaces into hyphens. The order is what
implementations get wrong —信頼する置き場所 / しない置き場所loses the slash
first and keeps two spaces, so its anchor carries two hyphens, and a slugger
that mapped spaces before stripping punctuation would reject a link this
repository contains. Counted twice, with a second implementation built on a
different principle (Unicode general categories and a line matcher, against
this one'schar::is_alphanumericand a parser): identical on all 792 anchors.Repeats retry their suffix until it is free, so
# Foo,# Foo,# Foo-1
endsfoo,foo-1,foo-1-1rather than handingfoo-1out twice. Which of
the two GitHub itself does is not documented and cannot be measured (POST /markdownrenders headings without ids); the retry is the side that can only
ever accept a missing anchor, where the counter can reject a working link and
stop CI.Pages are parsed rather than matched line by line, which is what makes a
#
inside a fenced TOML block not a heading and a reference-style link still a
link, and destinations are read as the URLs they are before they are read as
paths: the query and the fragment are cut off first (docs/usage.md?plain=1
is a link GitHub's own interface hands out), percent escapes are decoded the
way GitHub decodes them, and a rooted path —/x,\x, or the%2Fthat
decodes into one — is answered as the site-root path it is rather than by
asking a filesystem that differs between CI and a laptop. A fragment is read
in the language of the file it lands on: on a page a heading slug or an anchor
the page names outright with<a name="…">, on anything GitHub renders as
source a line range (#L10is checked against the file's length), and on a
directory the README GitHub shows underneath its file list. Destinations are
resolved lexically, counting depth from the
repository root, so a..that would climb above it is out of bounds wherever
the checkout happens to sit —exists()cannot ask that, and neither can
folding the path absolutely, which merely walks up one directory and back down
into whatever sits beside the checkout. On Actions that is the checkout
itself, since the path iswork/<repo>/<repo>. External
URLs are skipped entirely, on the URI grammar rather than a list of the
schemes seen so far, sotel:andMAILTO:are not looked for on disk — a
guard that can fail because
someone else's server is down stops being read — and what it cannot catch is
written down in the test: a link that resolves while the sentence around it
lies, which is the failure the same README split shipped seven of. -
A doc comment that names something this tree no longer has now fails CI.
cargo doc --no-deps --workspace --all-features --document-private-itemsruns
as the last step of thetestjob, and[workspace.lints.rustdoc]in the root
Cargo.tomldenies every warn-by-default rustdoc lint except one. Until now CI
ran fmt, clippy, check and test, none of which read a doc comment:
transport/http.rsnamedadmin_host_checkfor two days after
ADR-0009 deleted it, and
PR #219 converted references like it into links that nothing was yet checking.Twenty-four references were already broken when the check was switched on, and
the interesting ones were not typos.binary_size_exceededwas the old name of
size_cap_exceeded, cited twice.Refusal::messagehad become
Refusal::response. Six more —GraphNode,inspect,is_multiply_linked
twice,read_checkedtwice,recover_db— sat in module//!headers, where
a bare name does not resolve even to an item defined in the same file; they
are absolute paths now. The rest were prose that rustdoc was reading as a link:
a TOML section[eval], an interval[30,100], anarray<string>that parsed
as an unclosed HTML tag.private_intra_doc_linksis the one lint left atallow. It fires when a
public item's documentation links to a private one and that link resolves —
the item is there, it is simply not in the published set. This crate's Rust API
is Unstable by docs/stability.md and its rustdoc is
published nowhere, so pointing at the private helper that answers the question
is the useful thing to write. A name that no longer exists is a different lint,
and that one is denied: renamingsize_cap_exceededwhile leaving its four
doc references alone fails the build with four errors.--all-featuresis there for the reason clippy runs twice:test-helpersis
default-off and gates documented items, and rustdoc removes a gated item's doc
comment along with the item. Unlike clippy this needs only one run, because the
workspace's only#[cfg(not(feature = ...))]is inbenches/, whichcargo docdoes not document either way.It is a step in an existing job rather than a fourth job.
cargo doc --no-deps
wants exactly the dependency metadatacargo check --all-targetsalready
produced, so it costs one rustdoc pass — 15.8 s over the whole workspace,
measured — instead of a second dependency build, and it adds no cache entry to
a repository whose Actions caches already total 13.6 GB against a 10 GB limit.
Being in that job is also what puts it on all three operating systems, which is
the point:service/{linux,macos,windows}.rsare whole modules behind
#[cfg(target_os = ...)], so a single-OS doc check would never read two of
them.
grooveseek 1.0.1
Download grooveseek 1.0.1
| File | Platform | Checksum |
|---|---|---|
| grooveseek-aarch64-apple-darwin.tar.xz | Apple Silicon macOS | checksum |
| grooveseek-x86_64-pc-windows-msvc.zip | x64 Windows | checksum |
| grooveseek-aarch64-unknown-linux-gnu.tar.xz | ARM64 Linux | checksum |
| grooveseek-x86_64-unknown-linux-gnu.tar.xz | x64 Linux | checksum |
groove-tray 1.0.1
Download groove-tray 1.0.1
| File | Platform | Checksum |
|---|---|---|
| groove-tray-x86_64-pc-windows-msvc.zip | x64 Windows | checksum |
groove-svc 1.0.1
Download groove-svc 1.0.1
| File | Platform | Checksum |
|---|---|---|
| groove-svc-x86_64-pc-windows-msvc.zip | x64 Windows | checksum |