Skip to content

v5.24.0

Choose a tag to compare

@github-actions github-actions released this 28 Sep 15:00
· 72 commits to main since this release
c8dcab9

Red-team fixes (#165)

@Adam13y showed that one same-title write could retire any verified
fact, 216 times out of 216, and that nothing listed the swap afterwards. The entries below
from "An automatic write" on are the fixes. Rerun with his own harness against this release: an
automatic write now retires a verified fact 0 times in 36 for every attack shape, down from 36; a
write that omits an exclusive key, 0 in 36; and knowl conflicts lists every retirement that
still happens. A direct write shaped like a correction still retires the fact, because a real
correction must, but it no longer goes unseen. A planted item kept beside a fact can still rank
above it in search; that is tracked in #323.

Defaults changed

A fresh knowl init used to run with most of Knowl switched off, and nothing told anyone the
features existed. These now default on, or to shadow — which records what a mechanism would
have done and shows the agent nothing. An explicit value in .knowl/config.json still wins, and
none of these keys is written into existing configs, so a repository that set one keeps it.

Key Was Now Turn it back off
impact.enabled off on knowl config set impact.enabled false
impact.gate off shadow knowl config set impact.gate off
capture.nudge off shadow knowl config set capture.nudge off
capture.events off shadow knowl config set capture.events off
capture.checkpoint off shadow (new value) knowl config set capture.checkpoint off
search.transcripts.enabled off on knowl config set search.transcripts.enabled false
search.transcripts.fallback off on knowl config set search.transcripts.fallback false
hooks.transport command mcp knowl config set hooks.transport command, then knowl init <host>

hooks.transport: mcp only changes Claude Code and Codex, the two hosts that can run a hook as an
MCP tool call; every other host keeps command hooks. When the knowl MCP server is not registered
for the host, session start rewrites its hooks back to commands and says so on the session card,
and knowl doctor / knowl doctor --fix report and repair the same mismatch.

search.vector.provider is gone: local was the only value it ever accepted. Configs that still
carry it load as before, and knowl upgrade removes it.

Update notice on the session card

knowl serve refreshes the daily update-check cache when it starts, and the session-start card
names a newer release once: Knowl <current> → <latest> is available: npm install -g @dat999zx/knowl. Tell the user. Hooks read the cache and never touch the network. The existing
opt-outs (updateCheck.enabled: false, KNOWL_NO_UPDATE_CHECK, NO_UPDATE_NOTIFIER) cover both.

An automatic write can no longer retire a verified fact

Session capture, transcript approval, raw ingest and truth derivation used to retire or rewrite any
item they matched on subject. A sentence a model lifted from a transcript or a pasted README could
replace a fact someone had verified, and nothing listed the swap afterwards (#165). Those four
paths now keep their atom beside an observed/user_stated item instead. Direct writes
(knowl_store, knowl store, knowl decide, knowl_ingest_atoms) are unchanged. Replayed over
140 real supersessions, this blocks none of them. Raw ingest also stops rewriting such an item in
place, which previously kept no copy of the old content.

An item marked exclusive is no longer retired by a write that leaves its key out

conflictExclusive only refused a second write that carried the same key, so a same-subject write
that simply omitted it retired the exclusive item anyway (#165). The two are now kept side by side;
retire the exclusive one deliberately with supersedes. One of 140 real supersessions in this
repository's own store would have needed that. The correction may carry the same exclusive key: it
used to be refused because the item it named still held the key, and now only a holder it does not
retire refuses it.

knowl decide with AI, and truth derivation, no longer rewrite an exclusive item

With AI configured, knowl decide merges through a model comparison, and a model-judged update
rewrote an exclusive item in place while an auto-resolved contradiction retired it. Truth
derivation likewise overwrote an exclusive state item that nobody had verified (#165). A merge
now keeps its atom beside the exclusive item; derivation leaves it unchanged and does not write the
derived value.

knowl conflicts lists retired verified facts and the pairs the write path keeps side by side

A same-subject write that retired a verified fact told only its writer, and knowl conflicts
compared active items only, so the retired fact had nothing to pair with (#165). It now also
lists observed/user_stated items retired in the last 14 days with what replaced each, and
same-subject active pairs with a verified side, which the new write guards keep side by side
instead of superseding. On this repository's own store both lists hold a handful of rows.

knowl conflicts says whether a listed retirement still stands

A retired fact stayed listed for its whole 14 days with what replaced it, even after someone had
undone the swap by superseding that replacement, so it read as a live swap a second reader might
"fix" again. Each retirement's replacement now carries its status. Rows whose replacement has
itself been replaced stay listed, but after the rest, newest first in each group; that state also
follows a plain second write on the subject, so it means "look again", not "resolved". On this
repository's own store, 2 of the 5 listed retirements are in that state, both from a later verified
edit of the same fact rather than an undo.

A restatement that drops a fact's values no longer retires it

A same-subject write that removed a fact's numbers, versions or names and added none of its own
used to supersede it, so "retained for 35 days" could be replaced by "retained for the value in
the runbook" and the value vanished from results (#165). The two are now kept side by side.
Values written as ordinary words are not detected. A correction to a value the old text already
mentions, such as narrowing "Node 18 and Node 20" to "Node 20", is kept side by side too; retire
the old one with supersedes. Replayed over 140 real supersessions, this fires on none of them.

Creating a skill no longer retires a different skill, and supersedes retires the item it names

A skill's index entry is titled with its package name, so creating deploy-app-staging read as
a correction of deploy-app and retired it: both packages stayed on disk, but only one was
indexed, and runs of the other were no longer counted. File-backed skills from different
packages now stay side by side. Separately, a write that named one item in supersedes but
closely matched another retired the match and left the named item active; the named item is now
the one retired, and the match is reported as left beside it. knowl decide had the same fault.