Skip to content

Commit 7f968ca

Browse files
authored
Keep Linux update startup within health deadline (#34)
Signed-off-by: Joseph Yaksich <gitcommit90@users.noreply.github.com> Co-authored-by: Joseph Yaksich <gitcommit90@users.noreply.github.com>
1 parent 0e7c66d commit 7f968ca

9 files changed

Lines changed: 32 additions & 18 deletions

File tree

CHANGELOG.md

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,19 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## [Unreleased]
99

10+
## [0.0.25] - 2026-07-29
11+
12+
### Fixed
13+
14+
- Linux systemd updates now open the health port before initializing every
15+
retained resident memory database. Large existing workspaces no longer miss
16+
the updater's bounded startup window and roll back an otherwise healthy
17+
release while the same durable memory initialization continues in the
18+
background.
19+
- Includes the Windows host-terminal, Windows WSL identity, Linux LXC network
20+
recovery, and honest lifecycle/command failure corrections prepared in
21+
`0.0.24`; `0.0.24` was never tagged or published.
22+
1023
## [0.0.24] - 2026-07-29
1124

1225
### Fixed
@@ -751,7 +764,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
751764
notarization, stapled tickets, Gatekeeper verification, persistent
752765
Application Support, and isolated Apple container machines.
753766

754-
[Unreleased]: https://github.com/gitcommit90/1Helm/compare/v0.0.24...HEAD
767+
[Unreleased]: https://github.com/gitcommit90/1Helm/compare/v0.0.25...HEAD
768+
[0.0.25]: https://github.com/gitcommit90/1Helm/compare/v0.0.23...v0.0.25
755769
[0.0.24]: https://github.com/gitcommit90/1Helm/compare/v0.0.23...v0.0.24
756770
[0.0.23]: https://github.com/gitcommit90/1Helm/compare/v0.0.22...v0.0.23
757771
[0.0.22]: https://github.com/gitcommit90/1Helm/releases/tag/v0.0.22

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -307,7 +307,7 @@ A fresh data directory opens first-run setup. The source runtime defaults to
307307
| `PORT` | `8123` | HTTP/WebSocket control-plane port. |
308308
| `CTRL_DATA_DIR` | `./data` | Databases, routing state, uploads, and narrow workspace mirrors. |
309309
| `HELM_CHANNEL_COMPUTER_BACKEND` | `apple` on macOS, `lxc` on Linux, `wsl` on Windows | Host isolation backend; `native` and `mock` are explicit development/test overrides. |
310-
| `HELM_CHANNEL_MACHINE_IMAGE` | `local/1helm-channel-machine:0.0.24` | Versioned channel-machine image contract. |
310+
| `HELM_CHANNEL_MACHINE_IMAGE` | `local/1helm-channel-machine:0.0.25` | Versioned channel-machine image contract. |
311311

312312
### Agent-first JSON CLI
313313

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "1helm",
33
"productName": "1Helm",
4-
"version": "0.0.24",
4+
"version": "0.0.25",
55
"private": true,
66
"type": "module",
77
"license": "AGPL-3.0-only",

src/server/channel-computers.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ const APPLE_RUNTIME_VERSION = "1.1.0";
6767
export const APPLE_RUNTIME_PACKAGE = `container-${APPLE_RUNTIME_VERSION}-installer-signed.pkg`;
6868
export const APPLE_RUNTIME_URL = `https://github.com/apple/container/releases/download/${APPLE_RUNTIME_VERSION}/${APPLE_RUNTIME_PACKAGE}`;
6969
export const APPLE_RUNTIME_SHA256 = "0ca1c42a2269c2557efb1d82b1b38ac553e6a3a3da1b1179c439bcee1e7d6714";
70-
export const DEFAULT_CHANNEL_IMAGE = process.env.HELM_CHANNEL_MACHINE_IMAGE || "local/1helm-channel-machine:0.0.24";
70+
export const DEFAULT_CHANNEL_IMAGE = process.env.HELM_CHANNEL_MACHINE_IMAGE || "local/1helm-channel-machine:0.0.25";
7171
const CONTAINER_CANDIDATES = [process.env.HELM_CONTAINER_CLI, "/usr/local/bin/container", "/opt/homebrew/bin/container", "container"].filter(Boolean) as string[];
7272
const LXC_RUNTIME_VERSION = "1helm-lxc-runtime-v1";
7373
const LXC_HELPER_CANDIDATES = [

src/server/db.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1009,7 +1009,7 @@ export function migrate(): void {
10091009
const platformBackend = process.platform === "darwin" ? "apple" : process.platform === "win32" ? "wsl" : "lxc";
10101010
const configuredBackend = String(process.env.HELM_CHANNEL_COMPUTER_BACKEND || platformBackend);
10111011
const backend = ["apple", "lxc", "wsl", "native", "mock"].includes(configuredBackend) ? configuredBackend : platformBackend;
1012-
const image = String(process.env.HELM_CHANNEL_MACHINE_IMAGE || "local/1helm-channel-machine:0.0.24");
1012+
const image = String(process.env.HELM_CHANNEL_MACHINE_IMAGE || "local/1helm-channel-machine:0.0.25");
10131013
// Earlier Linux/Windows releases persisted the compatibility `native`
10141014
// seam into every channel row. A production host update must actually
10151015
// move those rows onto the platform isolation backend; changing the unit's

src/server/index.ts

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ import { markdownToDocx } from "./docx.ts";
7777
import { configurePhoton, continuePhotonConversation, deliverPhotonEvent, photonConversation, photonConversations, photonStatus, registerPhotonDispatcher, startPhotonConnector, stopPhotonConnector } from "./photon.ts";
7878
import { photonSetupStatus, startPhotonSetup } from "./photon-auth.ts";
7979
import { completeGmailConnection, gmailConnectionStatus, saveGmailOAuthClient, startGmailConnection } from "./gmail.ts";
80-
import { cancelMnemosyneRuntimePreparation, ensureAgentMemory, mnemosyneAvailable, prepareMnemosyneRuntime } from "./memory.ts";
80+
import { cancelMnemosyneRuntimePreparation, mnemosyneAvailable, prepareMnemosyneRuntime } from "./memory.ts";
8181
import { attachCoworkClient, coworkPresence, coworkViewerUsernames, flushCoworkDocuments, normalizeCoworkFolderPath, normalizeCoworkPath } from "./cowork-collaboration.ts";
8282
import { runImprovementPass, scheduleAgentReview, startImprovementLoop } from "./improvements.ts";
8383
import { runThreadAuditPass, startThreadAuditLoop } from "./thread-audit.ts";
@@ -2245,7 +2245,6 @@ async function bootstrap(): Promise<void> {
22452245
run("DELETE FROM bot_computers WHERE computer_id=? AND bot_id IN (SELECT bot_id FROM agents WHERE kind='channel')", computerId);
22462246
for (const channel of q("SELECT id FROM channels WHERE kind='channel' AND status<>'deleted'")) {
22472247
ensureChannelWorkspace(Number(channel.id));
2248-
const agent = agentForChannel(Number(channel.id)); if (agent) ensureAgentMemory(agent);
22492248
}
22502249
startImprovementLoop();
22512250
startThreadAuditLoop();
@@ -2260,13 +2259,11 @@ async function bootstrap(): Promise<void> {
22602259
const address = server.address();
22612260
const port = typeof address === "object" && address ? address.port : PORT;
22622261
console.log(`1Helm on 1Helm → http://${HOST === "0.0.0.0" ? "localhost" : HOST}:${port} (local agent on ${agentPort}) data: ${DATA_DIR}`);
2263-
void memoryRuntime.then((ready) => {
2264-
if (!ready) return;
2265-
for (const channel of q("SELECT id FROM channels WHERE kind='channel' AND status<>'deleted'")) {
2266-
const agent = agentForChannel(Number(channel.id));
2267-
if (agent) ensureAgentMemory(agent);
2268-
}
2269-
}).catch((error) => console.warn(`1Helm could not prepare durable memory: ${(error as Error).message}`));
2262+
// Runtime preparation remains asynchronous. Resident databases initialize
2263+
// when agents are created and lazily on their first memory operation; a
2264+
// retained fleet must never synchronously serialize Python init work on the
2265+
// server event loop before or after the health port opens.
2266+
void memoryRuntime.catch((error) => console.warn(`1Helm could not prepare durable memory: ${(error as Error).message}`));
22702267
void queueLinuxHostContractMigration(DATA_DIR).catch((error) => console.warn(`1Helm could not queue its Linux host-contract migration: ${(error as Error).message}`));
22712268
});
22722269
}

test/channel-computers.mjs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,7 @@ test("Apple channel-computer contract preserves isolation, files, wakes, archive
168168
test("runtime digest and packaged image recipe stay pinned", async () => {
169169
assert.equal(computers.APPLE_RUNTIME_SHA256, "0ca1c42a2269c2557efb1d82b1b38ac553e6a3a3da1b1179c439bcee1e7d6714");
170170
assert.match(computers.APPLE_RUNTIME_URL, /\/1\.1\.0\/container-1\.1\.0-installer-signed\.pkg$/);
171-
assert.equal(computers.DEFAULT_CHANNEL_IMAGE, "local/1helm-channel-machine:0.0.24");
171+
assert.equal(computers.DEFAULT_CHANNEL_IMAGE, "local/1helm-channel-machine:0.0.25");
172172
const packaging = await readFile(join(root, "scripts", "package-mac-dmg.cjs"), "utf8");
173173
assert.match(packaging, /container\(\?:\$\|\\\/\)/, "release packaging includes container/ image assets");
174174
const image = await readFile(join(root, "container", "Containerfile"), "utf8");

test/desktop.mjs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,9 @@ test("desktop entrypoint keeps the renderer sandboxed and data on the Mac", asyn
110110
assert.match(nativeUpdater, /autoUpdater\.quitAndInstall\(false, true\)/);
111111
assert.match(source, /1helm-native-update-ready/, "Electron replaces the app only after the local host runtime has quiesced");
112112
assert.match(server, /shutdown\(true\).*1helm-native-update-ready/s, "the host update API closes server work before handing installation back to Electron");
113+
const bootstrap = server.slice(server.indexOf("async function bootstrap"), server.indexOf("void bootstrap()"));
114+
assert.doesNotMatch(bootstrap, /ensureAgentMemory\(/, "retained resident memory initialization cannot block the event loop during a bounded host update");
115+
assert.match(bootstrap, /void memoryRuntime\.catch/, "optional memory-runtime preparation remains asynchronous during startup");
113116
assert.match(server, /\["native-macos", "native-windows"\]\.includes\(update\.mode\)/, "both packaged host updaters quiesce the local server before replacement");
114117
assert.match(nativeUpdater, /update\.electronjs\.org\/gitcommit90\/1Helm\/\$\{feedPlatform\}/);
115118
assert.match(nativeUpdater, /win32-x64/, "Windows checks and installs on its host through the native updater");
@@ -200,7 +203,7 @@ test("desktop entrypoint keeps the renderer sandboxed and data on the Mac", asyn
200203
assert.match(await readFile(join(root, "src", "client", "app.ts"), "utf8"), /mailto:build@1helm\.com/, "the in-app Feedback surface exposes the company contact address");
201204
assert.match(terminalBrowser, /HELM_CHANNEL_COMPUTER_BACKEND: "native"/, "the terminal browser contract uses the explicit development backend on CI hosts without an installed LXC runtime");
202205
const serverRuntime = await readFile(join(root, "src", "server", "index.ts"), "utf8");
203-
assert.match(serverRuntime, /const memoryRuntime = prepareMnemosyneRuntime\(\);[\s\S]*server\.listen\([\s\S]*memoryRuntime\.then/, "the HTTP server becomes ready before optional memory installation and initializes agent databases afterward");
206+
assert.match(serverRuntime, /const memoryRuntime = prepareMnemosyneRuntime\(\);[\s\S]*server\.listen\([\s\S]*void memoryRuntime\.catch/, "the HTTP server becomes ready without synchronously initializing every retained agent database");
204207
const memoryBridge = await readFile(join(root, "scripts", "mnemosyne-bridge.py"), "utf8");
205208
assert.match(memoryBridge, /sys\.version_info < \(3, 10\)/);
206209
assert.match(memoryBridge, /zip_longest/);

0 commit comments

Comments
 (0)