From b1586c5e250aef843df93328411147fa84d47ac4 Mon Sep 17 00:00:00 2001 From: avi Date: Mon, 5 Oct 2026 01:33:17 -0500 Subject: [PATCH 01/10] chore: sync lockfile version to 0.1.12 --- package-lock.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index 6feb28d..656e3fc 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "folio", - "version": "0.1.10", + "version": "0.1.12", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "folio", - "version": "0.1.10", + "version": "0.1.12", "license": "MIT", "dependencies": { "@tiptap/core": "^2.27.2", From bb758580d7732467a7f64742abc48a59afea6a5b Mon Sep 17 00:00:00 2001 From: avi Date: Mon, 5 Oct 2026 06:28:41 -0500 Subject: [PATCH 02/10] fix(build): prepackage hook rebuilds dist before electron-builder Root cause of 0.1.8-0.1.12 shipping stale code: electron-builder packs whatever dist/ happens to contain; dist was last built 2026-10-04 10:02, so releases 0.1.8..0.1.12 all carried byte-identical bundles that predate the systemd-run handoff fix (12977e1) and the curl downloader (9afe49c). prepackage guarantees a fresh build on every npm run package. --- package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/package.json b/package.json index c5472ce..56ffb18 100644 --- a/package.json +++ b/package.json @@ -15,6 +15,7 @@ "dev": "concurrently -k \"npm run build:watch\" \"wait-on dist/main.js && npm run electron\"", "start": "npm run build && npm run electron", "lint": "tsc --noEmit", + "prepackage": "npm run build", "test": "node tests/run-project-test.mjs && node tests/run-chapters-test.mjs && node tests/run-wikilinks-test.mjs && node tests/run-office-export-test.mjs && node tests/run-migration-test.mjs && node tests/run-editor-test.mjs && node tests/run-fullbook-test.mjs && node tests/run-print-test.mjs && node tests/run-update-import-test.mjs && node tests/run-update-installer-test.mjs && node tests/run-snapshots-test.mjs && node tests/run-search-test.mjs", "package": "electron-builder" }, From 173a9799d0014fad624d67ef7d5bef73c298831e Mon Sep 17 00:00:00 2001 From: avi Date: Mon, 5 Oct 2026 06:28:47 -0500 Subject: [PATCH 03/10] chore(release): bump to 0.1.13 --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 656e3fc..d051b88 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "folio", - "version": "0.1.12", + "version": "0.1.13", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "folio", - "version": "0.1.12", + "version": "0.1.13", "license": "MIT", "dependencies": { "@tiptap/core": "^2.27.2", diff --git a/package.json b/package.json index 56ffb18..52e63b2 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "folio", - "version": "0.1.12", + "version": "0.1.13", "description": "A simple, local, open-source desktop writing app.", "productName": "Folio", "author": "Folio Contributors", From ea2ca08efd6c5237b6b1279016fc704ea38eb585 Mon Sep 17 00:00:00 2001 From: avi Date: Mon, 5 Oct 2026 10:34:11 -0500 Subject: [PATCH 04/10] chore(release): bump to 0.1.14 --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index d051b88..f0c51fa 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "folio", - "version": "0.1.13", + "version": "0.1.14", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "folio", - "version": "0.1.13", + "version": "0.1.14", "license": "MIT", "dependencies": { "@tiptap/core": "^2.27.2", diff --git a/package.json b/package.json index 52e63b2..099acf8 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "folio", - "version": "0.1.13", + "version": "0.1.14", "description": "A simple, local, open-source desktop writing app.", "productName": "Folio", "author": "Folio Contributors", From 44b4737a20cb56fcd2d9e67ef3a9ed7b49cd4793 Mon Sep 17 00:00:00 2001 From: avi Date: Mon, 5 Oct 2026 10:42:41 -0500 Subject: [PATCH 05/10] fix(build): emit linux x86_64 tar.gz on every package run The in-app updater installs the release asset matched by pickAsset (tar.gz + linux + x86_64/amd64); the config only built AppImage+deb, so plain 'npm run package' produced no updatable asset and required a second electron-builder invocation plus a manual rename (as done for 0.1.13). --- electron-builder.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/electron-builder.yml b/electron-builder.yml index d8f3b67..4abacd6 100644 --- a/electron-builder.yml +++ b/electron-builder.yml @@ -21,6 +21,11 @@ linux: target: - AppImage - deb + # tar.gz is what the in-app updater installs (pickAsset looks for a + # linux x86_64/amd64 tarball); arch must be x64 so the asset name ends + # in -linux-x86_64 like every published release. + - target: tar.gz + arch: x64 # OS file associations: double-click / "Open with Folio" on Markdown and # plain-text files imports them as books (see folio:openPathOrImport and From ced074a3a05c1c8eb3bb44070a04b7714e4a2229 Mon Sep 17 00:00:00 2001 From: avi Date: Mon, 5 Oct 2026 17:48:04 -0500 Subject: [PATCH 06/10] fix(single-instance): quit when the lock is lost MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit requestSingleInstanceLock() without a quit on failure means the second process falls through to whenReady() and opens a duplicate window (what Avi saw: two Folios from one icon click). Now the loser forwards to the running window (second-instance) and exits. Pairs with the launcher TMPDIR pin — uwsm per-scope /tmp made the singleton socket invisible, so the lock never even failed before. --- src/main/index.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main/index.ts b/src/main/index.ts index e666950..3596ddb 100644 --- a/src/main/index.ts +++ b/src/main/index.ts @@ -1423,4 +1423,8 @@ if (app.requestSingleInstanceLock()) { } if (f) openFromArg(f); }); +} else { + // Lost the lock: another Folio is already running. Without this quit the + // second process falls through to whenReady() and opens a duplicate window. + app.quit(); } From 328b24d5a64e7d55bb02b8ebc98cb84a12c5ce81 Mon Sep 17 00:00:00 2001 From: avi Date: Mon, 5 Oct 2026 17:48:04 -0500 Subject: [PATCH 07/10] chore(release): bump to 0.1.15 --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index f0c51fa..4e45214 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "folio", - "version": "0.1.14", + "version": "0.1.15", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "folio", - "version": "0.1.14", + "version": "0.1.15", "license": "MIT", "dependencies": { "@tiptap/core": "^2.27.2", diff --git a/package.json b/package.json index 099acf8..85cbb3f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "folio", - "version": "0.1.14", + "version": "0.1.15", "description": "A simple, local, open-source desktop writing app.", "productName": "Folio", "author": "Folio Contributors", From aebfa2630883203417801415c0a40699323f9d15 Mon Sep 17 00:00:00 2001 From: avi Date: Mon, 5 Oct 2026 18:11:24 -0500 Subject: [PATCH 08/10] fix(updater): relaunch survives the handoff unit's cgroup sweep v0.1.15 update proved the pipeline end-to-end (download, verify, swap OK) but the app never reopened: the handoff runs in a systemd transient unit whose default KillMode=control-group sweeps the process tree when the script exits, killing the backgrounded relaunch before Electron started. Two fixes: start the unit with KillMode=process, and setsid the relaunch (nohup fallback) so it detaches from the unit session entirely. --- src/main/index.ts | 5 +++++ src/main/update.ts | 9 ++++++++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/src/main/index.ts b/src/main/index.ts index 3596ddb..c9557a1 100644 --- a/src/main/index.ts +++ b/src/main/index.ts @@ -1354,6 +1354,11 @@ handleIpc("folio:performUpdate", async () => { execFileSync("systemd-run", [ "--user", "--quiet", "--collect", `--description=Folio updater handoff`, + // Default KillMode=control-group means the unit's cgroup is swept + // when the script exits — that killed the backgrounded relaunch + // before Electron got to start (v0.1.15 update: swap OK, app died). + // KillMode=process lets the script exit while its child app lives. + "--property=KillMode=process", "/bin/sh", script, ], { timeout: 10_000, stdio: "ignore" }); handedOff = true; diff --git a/src/main/update.ts b/src/main/update.ts index 738245b..9493643 100644 --- a/src/main/update.ts +++ b/src/main/update.ts @@ -224,7 +224,14 @@ export function buildInstallerScript(spec: InstallerSpec): string { ' rm -rf "$NEW"', "fi", 'say "relaunching"', - '"$RELAUNCH" >/dev/null 2>&1 &', + // Detach fully: setsid moves the relaunch into its own session so it + // survives this script's exit and any cgroup sweep of the transient + // unit (systemd KillMode). Fallback chain for missing setsid. + 'if command -v setsid >/dev/null 2>&1; then', + ' setsid "$RELAUNCH" >/dev/null 2>&1 < /dev/null &', + 'else', + ' nohup "$RELAUNCH" >/dev/null 2>&1 < /dev/null &', + "fi", "", ].join("\n"); } From 6c8b82940a0a7cab181c21f96c26af21bcd652c6 Mon Sep 17 00:00:00 2001 From: avi Date: Mon, 5 Oct 2026 18:11:24 -0500 Subject: [PATCH 09/10] chore(release): bump to 0.1.16 --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 4e45214..beef7ee 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "folio", - "version": "0.1.15", + "version": "0.1.16", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "folio", - "version": "0.1.15", + "version": "0.1.16", "license": "MIT", "dependencies": { "@tiptap/core": "^2.27.2", diff --git a/package.json b/package.json index 85cbb3f..88f1ca5 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "folio", - "version": "0.1.15", + "version": "0.1.16", "description": "A simple, local, open-source desktop writing app.", "productName": "Folio", "author": "Folio Contributors", From 67ca9cbb768c1b73c6a2bce294ce82372206bbaf Mon Sep 17 00:00:00 2001 From: avi Date: Mon, 5 Oct 2026 19:03:41 -0500 Subject: [PATCH 10/10] chore(release): bump to 0.1.17 --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index beef7ee..6b4b766 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "folio", - "version": "0.1.16", + "version": "0.1.17", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "folio", - "version": "0.1.16", + "version": "0.1.17", "license": "MIT", "dependencies": { "@tiptap/core": "^2.27.2", diff --git a/package.json b/package.json index 88f1ca5..3ffd369 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "folio", - "version": "0.1.16", + "version": "0.1.17", "description": "A simple, local, open-source desktop writing app.", "productName": "Folio", "author": "Folio Contributors",