v0.71.1
Patch Changes
The Ask AI composer no longer covers the last line of a document as it grows.
Typing a long prompt at the end of any file the editor opens in a text view (
.ts,.py,.json,.yaml,.txtand the rest), or of a.mmdor.mermaiddiagram in source mode, used to let the growing composer cover the line the caret was on. The composer reserved room at the bottom of those editors but the scroll position did not follow it, so the last line slid underneath. It now stays above the composer.Configure semantic-search text chunks per indexing request, character budget, and request timeout from
Settings → Search, so slower local embedding servers can be tuned without patching the installed OpenKnowledge bundle.Clarify that semantic search indexes pages when you search, and show indexed coverage without an idle loading spinner.
The editor header no longer lets its trailing actions cover the file-navigator toggle at narrow widths.
The header lays out a leading rail (the Files toggle) and a trailing rail (Share, sync status, presence, Settings, Resources) as two overlays that measured each other but never negotiated for width. At a phone-width window with the file navigator open the header is about 97 px wide, the trailing rail kept its full width, and it spilled left over the toggle: tapping the toggle activated Settings instead, and two trailing buttons landed over the navigator and could not be tapped at all.
The header now compares the trailing rail's own width against the space the leading rail leaves it. When they do not both fit, the trailing actions collapse into a single More actions button that opens them in a popover; every action keeps its label and behaviour. Where both rails already fit, which is every desktop width, nothing changes.
Sync connection toasts no longer depend on the header's layout. They were hosted inside the presence avatars, so they are now raised into a dedicated host that stays mounted whatever the header does.
The More actions button also carries the sync state it hides. When git sync is in conflict, offline, needs reauthentication, or is paused, the button shows a coloured dot and names that state in its accessible label, so a collapsed header never hides a sync problem.
When the header gets narrower still and cannot seat the leading rail, the trailing button and the document tab strip at the same time, the tab strip now hides instead of drawing a clipped sliver underneath the buttons.
Missing external apps now appear behind “Show N more” in Agent connections settings, including enabled apps and apps with setup to remove. Detected and unknown apps stay visible; all apps appear when none would remain visible or while searching. All three sections announce their expanded state and retain keyboard focus within the group when a focused disclosure disappears.
The Timeline no longer reports "History unavailable", and a folder's timeline card no longer disappears, on branches whose names contain characters git accepts but the history endpoint used to reject.
A branch named
worktree-design+atc-release-packageused to get a 400 from/api/history, which the document Timeline rendered as "History unavailable" and a folder's timeline card rendered as nothing at all — the card was simply absent from the folder overview, with no message.feature-caféand fully non-Latin branch names were rejected the same way. Twenty-one printable-ASCII characters real branch names may contain —+,%,#,=,&,!,$,(,),,,;,'and others — plus every non-ASCII character and any leading underscore are now served.Both surfaces also now log the server's problem type and title to the browser console when a history request fails, so a Timeline that will not load says why.
One class is still rejected: the shared rules refuse any whitespace, including non-ASCII whitespace such as a non-breaking space, which git itself does allow. A branch named that way still gets a 400 and a dead Timeline.
Broken links inside a
log.mdno longer show up as work to do.A project log is an append-only history. Its entries name pages that have since moved, and pages nobody has written yet, so unresolved links are what a log is supposed to accumulate. Until now every one of them was reported as a broken link to repair: in the Problems panel, as a sidebar tint, as an editor squiggle, in
ok audit, and in the advisory an agent gets back from every write or edit. That last one is what made this more than noise, because agents are told to read that advisory and fix what it names, and the only way to fix a stale entry in a log is to edit history that was meant to be permanent.A new project setting, Ignore broken links in log.md under Settings ▸ This project ▸ Preferences ▸ Content rules, leaves those links out of all of it. It is on by default and shared with the project through
config.ymlasvalidation.suppressLogLinkAdvisories. Turn it off and every finding comes straight back, everywhere, with no restart.If you gate CI on
ok audit --errors-onlywithvalidation.links: error, reserved-log findings no longer contribute toerrorCountwhile this default-on setting is enabled. Setvalidation.suppressLogLinkAdvisories: falseto keep the previous gate.The match is deliberately narrow: the stem must be exactly lowercase
log, with a supported Markdown extension, at any depth. The extension's case is not what decides, solog.MDis a reserved log too;LOG.mdandcatalog.mdare ordinary documents and keep their findings. What decides is the file a link is written in, not the file it points at, so a broken link to a log from anywhere else still reports normally.Nothing is hidden from the views you use to inspect links on purpose. The Links panel, the editor's unresolved-link styling,
links({ kind: "dead" }), andGET /api/dead-linksall show a log's unresolved links in both states.For agents, filtered results are now explicitly conditional rather than quietly redefined. When the policy withholds findings, audit, write, and edit responses carry
brokenLinkSuppression, naming the reasonreserved-log-policyand how many final findings were withheld. On write and edit it sits besidebrokenLinks. WhenbrokenLinkSuppressionis absent,brokenLinks: []still means what it always did: every outbound link resolves. When the marker is present, treat the empty list as filtered, not confirmed. No href or path comes back, because none of them is repair work, and the bundled project skill and MCP tool descriptions now say exactly that.Settings → AI tools no longer makes a connected agent look like something is still wrong.
A connected project MCP entry carried an amber follow-up line, announced as a live status update, directly under the checkmark and "Installed". It read like a security step OpenKnowledge was waiting on, and it never went away, because OpenKnowledge cannot tell whether the agent has accepted the entry. Claude Code asks for approval on its own the first time you run it in a project. Codex and GitHub Copilot load a project entry once the folder is trusted, which the CLI asks about on first run in a new folder; their setup dialogs now say so, and Codex's names the remedy. Those rows now show no follow-up line at all.
Cursor keeps one, for the case where you really do have to act: a project-only registration. Cursor lists a new
.cursor/mcp.jsonserver as disabled until you switch it on under Customize → MCPs, and OpenKnowledge cannot see that setting, so when the project entry is the only thing connecting Cursor the row says exactly that and names where to go. A user-level registration, whichok initwrites by default, starts on its own and its row shows no line. It now reads as ordinary muted text instead of an amber status.Fixes a bug where an agent write that Open Knowledge had already confirmed and saved could be silently undone by another program a moment later.
An editor or script holding the older version of a file in its buffer, and saving it after the agent write landed, put the exact bytes that preceded the write back on disk. Open Knowledge saw a file whose content did not match what it last wrote, found the open document unchanged since that save, and concluded the file had been edited outside the app. It applied those bytes as an ordinary external edit, so the acknowledged write disappeared from the open document with nothing to indicate anything had gone wrong.
The server now remembers, for a bounded window, which versions an acknowledged agent save displaced. It stores a local durability snapshot for only those recently displaced documents, including the acknowledged and rejected content needed to recover safely after an app restart. When a file on disk turns out to be one of those displaced versions while a newer save is the current one, the file is no longer applied. The document keeps the acknowledged content and is frozen with a
stale-external-writeconflict reason, so later agent writes fail explicitly instead of building on an unnoticed rollback. The existing conflict view and conflict tools expose both versions and can resolve the document by keeping either one or combining them. Until you choose, the file on disk is left exactly as the other program wrote it: Open Knowledge does not write over it, so there is no save fight between the two.External edits that do not exactly restore a version Open Knowledge itself displaced still reconcile the way they always have. An intentional exact restore of a recently displaced version is indistinguishable from a stale editor save, so it is surfaced for confirmation instead of being applied silently. The record of displaced versions is per branch and is dropped when a document is deleted. Its protection window expires after 30 minutes; expired text is removed from the recovery file only on a later state-persistence event, not by a timer or restart. Unresolved stale-write conflicts remain until they are resolved.
Conflict resolutions can explicitly write an empty string to keep an empty file; only the separate
deletestrategy removes the file. The diff view preserves the selected bytes even when the current Git version in the editor differs from its committed stage.Recovery snapshots contain document text and are written with owner-only permissions. If a snapshot is corrupt, unreadable, or from an incompatible version, the server preserves it and stops opening the project with an actionable recovery message rather than discarding potentially unique edits. A write that discovers a stale file during its final flush returns a distinct 409: its collaborative edit and recovery snapshot are retained, but its disk write is skipped. Further external saves cannot discard that pending edit; explicit resolution is required. Resolve and re-read before retrying.
A terminal tab now shows its shell prompt as soon as it opens. Before this, output the shell printed before the tab was listening could be dropped, leaving the tab on
Starting terminal…until you pressed a key. A tab whose shell never starts at all now saysThe terminal couldn't start.and offersTry again, instead of reporting that the shell stopped unexpectedly.Theme changes now fade semantic app colors, terminal colors, and live HTML previews while preserving reduced-motion preferences and native window chrome settlement.
ok deinitandok uninstallnow allow up to 15 seconds for the Windows identity probe to start PowerShell on busy systems instead of 5 seconds; macOS and Linux keep the existing 5-second timeout.