Desktop: enable the openknowledge.ai update proxy for the stable…#376
Closed
inkeep-oss-sync[bot] wants to merge 7 commits into
Closed
Desktop: enable the openknowledge.ai update proxy for the stable…#376inkeep-oss-sync[bot] wants to merge 7 commits into
inkeep-oss-sync[bot] wants to merge 7 commits into
Conversation
…ift toast (#2242) * fix(desktop): shut down stale server on app update to stop version-drift toast The desktop spawns its CRDT server detached so it survives app-quit (precedent #1261). But app updates install via app-quit too — either the silent `autoInstallOnAppQuit` path or a drag-replace — and only the "Relaunch now" button ran `prepareForRelaunch` → `stopAllOwnedServers`. So on the common update paths the old-version server kept running, the relaunched app attached to it, read the older version off `server.lock`, and showed the "this project is running an older version… restart it" toast on nearly every update. Hook the teardown to `before-quit-for-update` — the native autoUpdater signal that fires on BOTH install paths and ONLY on an update install, never a plain quit. New `WindowManager.signalStopAllOwnedServers()` sends a synchronous best-effort SIGTERM to every detached server this desktop spawned (the "Relaunch now" path already drained them, so it no-ops there). The event can't hold the quit open, but the server's own SIGTERM handler flushes pending writes and releases its lock in ~25ms (measured) — far inside the multi-second reinstall+relaunch window — so the new app spawns fresh instead of re-attaching. A normal quit never fires the event, so it still leaves the server running, as designed. The signalling loop is extracted as the pure `signalDetachedServerStop` helper with unit coverage (normal kill, ESRCH already-gone, non-ESRCH failure keeps going, empty no-op), since `WindowManager`'s teardown methods have no unit harness. * fix(desktop): also reap ephemeral servers on update + dedup utility-fork loop Address both reviewer "Consider" findings on #2242: 1. Ephemeral single-file (`ok <file>`) session servers are tracked on `ctx.ephemeral` (keyed by file path, not project root) and so weren't reaped by the new before-quit-for-update teardown — they'd orphan on the silent `autoInstallOnAppQuit` path (process + temp dir until reboot), the way the async sibling `stopAllOwnedServers` already prevents. Signal their pids too. Temp-dir removal is the async half this best-effort path can't do; the orphaned process (which holds the bundle binary) is what matters and dies on the SIGTERM. 2. The utility-fork SIGKILL loop was duplicated near-verbatim across both teardown methods. Extract the shared pure `signalStopOwnedUtilityForks` helper and call it from both, so the predicate + error handling can't drift — and the branch gains unit coverage (3 new tests). * test(desktop): cover signalStopAllOwnedServers orchestrator end-to-end Re-review follow-up: the extracted helpers were unit-tested but the orchestrator entry point `signalStopAllOwnedServers()` (wired to before-quit-for-update) had no direct coverage of its composition — collecting detached pids from `spawnedDetachedPids` + ephemeral pids from `windowsByPath`, draining the map, merging. Add a test through the existing ephemeral harness: seed a detached pid + an open ephemeral session, assert both receive SIGTERM, and assert a second call doesn't re-signal the detached pid (map drained). Guards against a future field-rename in the collection chain that would pass the helper tests but break orchestration. --------- GitOrigin-RevId: ab2b0fe9c2a6d159d9b3f3ccb3183fc170ae952d
…251) pickLatestBetaDmgUrl returned the first -beta.N release in GitHub's "List releases" array order, trusting it to be newest-first. It isn't: the API has been observed returning an older beta ahead of newer ones, and the bug surfaced the moment betas crossed from single- to double-digit (beta.9 was served while beta.10-13 existed), stalling /download/beta and the /updates/beta auto-update feed on a stale build. Pick the newest beta by numeric (major, minor, patch, beta) rank instead of position. Fixes both surfaces, since the updates route derives its tag from the same resolver. Adds regression tests for the older-first array order and the beta.9-vs-beta.10 lexical trap. GitOrigin-RevId: 353c018fe8860fd1ad02051f36989f6d2c97715c
GitOrigin-RevId: aa53d68b0739a9b4e289a10c46ab732544579bfa
* feat: align macOS File menu with the in-app project switcher Group the File menu's project actions (Recent project, New project, Switch project, Open folder) directly under "New from template..." in the same order as the bottom-left ProjectSwitcher, and update the switcher's action order to match. Rename "Create new project..." to "New project..." and "Open recent" to "Recent project" so both surfaces read identically. Wiring, accelerators, and behavior unchanged. * chore: centralize project menu labels, refresh stale references Address PR review feedback: - Fold the dual-surface 'New project' / 'Open folder' labels into MENU_LABELS so menu-label-parity.test.ts guards menu<->switcher wording drift (matching the existing shared-label pattern); normalize their ellipsis to the same escape the sibling labels use. - Add contiguity assertions to the menu order test so a separator inserted mid-section would be caught, not just relative ordering. - Refresh stale 'Create New Project...' references to the renamed label at the onNewProject call sites (index.ts, App.tsx, CreateProjectMenuTrigger, NavigatorApp) and in the onNewProject JSDoc. GitOrigin-RevId: ac7db1562d92e3ba8230ff7b17daa106d33d9e2a
…cs (PRD-7194) (#2248)
* fix(open-knowledge): stop dead-link check flagging freshly-written docs
`links({ kind: "dead" })` reported recently-created docs as dead even
though their target files existed and the backlink edge was already
registered. Dead-link resolution decided existence solely from the
caller-supplied admitted set (the file-watcher's file index), which lags
behind in-session writes. The same backlink index, meanwhile, registers
a new doc as a live forward node the instant `onStoreDocument` runs — so
the graph simultaneously held a backlink FOR the doc and reported it as a
dead link, an internal inconsistency that only cleared on a server
re-index/restart.
`getDeadLinks` now treats a target as existing when it is admitted OR is
a live forward node in the graph (`state.forward.has(target)`). A
genuinely-missing target is never a forward node (only `state.backward`
carries it), so this never hides a real dead link; a freshly-written doc
becomes a valid link target immediately within the same session.
Fixes PRD-7194.
* test(open-knowledge): pin dead-link deletion inverse + document existence contract
Address claude[bot] review on #2248 (both low-risk suggestions):
- Add a companion test asserting that after `deleteDocument` drops a doc
from `state.forward`, `getDeadLinks` reports it dead again when it's also
absent from the admitted set — guards against a future refactor that
retains stale forward entries and silently swallows real dead links.
- Add JSDoc to `getDeadLinks` making the existence contract explicit:
existence is `admittedDocs ∪ keys(state.forward)`, an additive second
oracle, not a narrowing of the admitted set.
---------
GitOrigin-RevId: 6834ae8bfb71348f858c05c55abc489b883733fa
…chain (#2254) * test(open-knowledge): folder-rename regression coverage for PRD-7045 chain PRD-7045 (folder rename corruption chain: duplicate folder, stale relative links, blank WYSIWYG, perceived data loss) is already fixed in code — each facet by a separate PR that merged before the 6/12 UX session that reported it: - duplicate folder + spontaneous reappearance → #740 (removalRedirectGuard + recentlyRemovedDocs, phantom-resurrection defense) - blank WYSIWYG while source shows content → #1011 / PRD-6673 (spine moves the file on disk before captureAndCloseDocuments, so the redirected client loads real content instead of an empty Y.Doc) - stale relative ../ links / orphaned inbound links → #1473 / PRD-6839 (folder rename enumerates descendant docs from disk, not the lagging index) But the regression suites only covered FILE rename, while PRD-7045's reported symptom is specifically a FOLDER rename. This adds folder-level coverage so the chain can't silently regress: removal-phantom-resurrection.test.ts (QA-FOLDER): a folder rename arms the removal cache for every descendant doc — a reconnect to ANY old descendant docName is redirected (resurrection vector severed for each), and every doc's body survives the move (the blank-WYSIWYG facet at the disk layer). api-folder-rename-disk-enum.test.ts: inbound links in every shape — wiki, root-relative, dot-relative, and ../ / ../../ from nested sources — are rewritten to the new folder with zero stale references; and relative links authored INSIDE the folder (sibling ../, descendant ./sub/, outbound ../) still resolve to a real file after the move (no orphans). Test-only; no behavior change. * test(open-knowledge): tighten folder-rename link assertions (review) Address claude[bot] review on #2254: - Pin full link shapes (`[banana](sub/banana.md)` etc.) instead of loose `toContain('sub/banana.md')` substrings, so an incorrect re-relativization (e.g. `../recipes/sub/banana.md`) would now fail. Note the rewrite normalizes a leading `./` away while resolution stays correct. - Assert the old `foods/` directory is gone after the rename, matching the pre-existing describe block's self-containedness. * test(open-knowledge): harden QA-FOLDER seed against CI watcher lag QA-FOLDER failed twice on the merge tier with `pollUntilAsync timed out after 8000ms` during seeding — the chokidar watcher lagged past 8s before `/api/documents` reflected the fresh nested file, under a shard also running the OK_TEST_STORE_FAULT disk-failure-simulation suites. The folder rename enumerates descendants from disk and the guard keys off the spine-populated cache + existsSync, so the index-appearance wait is the only fragile part. Make `seedDoc`'s index-wait timeout overridable (default unchanged at 8000 so sibling tests keep their timing), pass 20000 for QA-FOLDER's two seeds, and raise that test's deadline to 60s to fit two generous seeds + the rename. * test(open-knowledge): seed QA-FOLDER via agent-write-md (deterministic) The prior fix (bigger seedDoc timeout) still flaked: QA-FOLDER hit the 20s index-wait in the full test:integration job (990 tests / 220 files), where the chokidar watcher lags past any fixed timeout under event-loop contention. Replace the watcher-poll seed with `POST /api/agent-write-md` (`position: 'replace'`), the same deterministic seed the Playwright tests use: it lands the doc on disk AND in the index synchronously within the awaited request, and routes through `writeTracker` so the watcher fires no later `add` event for the path. The latter also closes a reverse-race — a post-rename `add` for an old descendant path would otherwise invalidate the spine's removal-cache entry (`onUpstreamAdd` → `recentlyRemovedDocs.delete`) and flake the redirect assertion. Bonus: the seed loads a live Y.Doc, so the body-preservation check now exercises the same "editor connected at rename" path PRD-6673 fixed. seedDoc reverts to its original signature. --------- GitOrigin-RevId: 5366010ca559145626a177bc7b2f9acca5e6593d
…259) Add 'latest' to the proxy-feed channel set so stable builds fetch updates through openknowledge.ai/updates/stable and stable updates are counted per version. Follows the verified end-to-end beta update (beta.13 -> beta.14) through the proxy. Stable resolves via GitHub's authoritative releases/latest alias (no version-sort dependency), and a feed failure still reverts to the GitHub provider for the session. GitOrigin-RevId: 56ff072a229b345f1d961f30b8285d7b567f3b85
Contributor
There was a problem hiding this comment.
Automated approval from agents-private public-mirror-sync (run: https://github.com/inkeep/agents-private/actions/runs/28394344505). Source of truth is the monorepo; direct edits on inkeep/open-knowledge are overwritten on next sync.
Contributor
Author
|
Auto-closed by public-mirror-sync: a newer sync run is rebuilding copybara/sync with accumulated changes from agents-private. A fresh PR will be opened momentarily. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Desktop: enable the openknowledge.ai update proxy for the stable (
latest) channel too. Stable builds now fetch updates throughopenknowledge.ai/updates/stable, which 302s to the byte-identical GitHub asset (preserving the manifest sha512 and the macOS signature) so stable updates are counted per version. This follows the verified end-to-end beta update (beta.13 to beta.14) through the proxy. The stable path resolves via GitHub's authoritativereleases/latestalias, and a feed failure still reverts to the GitHub provider for the session, so auto-update reliability never drops below GitHub-direct.Align the macOS File menu with the in-app project switcher. The File menu's project actions now sit together directly under "New from template…" and read in the same order as the bottom-left switcher: Recent project, New project, Switch project, Open folder. "Create new project…" is renamed "New project…" and the recents submenu is renamed "Recent project" to match the switcher's labels. The switcher's own action order is updated to the same sequence (New project, Switch project, Open folder) so both surfaces are consistent. Wiring, accelerators, and behavior are unchanged.
Fix
links({ kind: "dead" })falsely reporting freshly-written docs as dead. The dead-link check decided a target existed only from the file-watcher's file index, which lags behind in-session writes, so a doc the link graph had just registered a backlink for could still be flagged dead until a server restart. Dead-link resolution now also treats any doc the graph already holds as a live node (its body has been indexed) as a valid target, so a newly-written doc is a valid link target immediately — without changing how genuinely-missing targets are reported.