From ae64a684600f83f24eaa98e94c302063db7a7fd1 Mon Sep 17 00:00:00 2001 From: Guillermo Casanova Date: Thu, 1 Oct 2026 09:35:52 -0300 Subject: [PATCH] fix(ssh): record the archive lock owner's real PID String.replaceAll treats $$ in a string replacement as an escaped $, so the runner embedded in the SSH launch script wrote a literal $ as the archive lock owner. A replacer function keeps the value literal. --- packages/ssh/src/tunnel.test.ts | 6 ++++++ packages/ssh/src/tunnel.ts | 3 ++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/packages/ssh/src/tunnel.test.ts b/packages/ssh/src/tunnel.test.ts index a3c049323bce..99be6ea80c2b 100644 --- a/packages/ssh/src/tunnel.test.ts +++ b/packages/ssh/src/tunnel.test.ts @@ -242,6 +242,12 @@ describe("ssh tunnel scripts", () => { assert.notInclude(script, "npx"); }); + it("embeds the runner in the launch script byte for byte", () => { + const runner = buildRemoteT3RunnerScript(ARCHIVE); + assert.include(runner, 'printf \'%s\\n\' "$$" > "$T3_LOCK/pid.tmp"'); + assert.include(buildRemoteLaunchScript(ARCHIVE), runner); + }); + it("uses the remote t3 runner for launch and pairing scripts", () => { const target = { alias: "devbox", diff --git a/packages/ssh/src/tunnel.ts b/packages/ssh/src/tunnel.ts index 0473ffeceae2..b055df438d33 100644 --- a/packages/ssh/src/tunnel.ts +++ b/packages/ssh/src/tunnel.ts @@ -243,7 +243,8 @@ function applyScriptPlaceholders( ): string { let result = template; for (const [token, value] of Object.entries(replacements)) { - result = result.replaceAll(`@@${token}@@`, value); + // A replacer function keeps `$$` and other `$` patterns in the value literal. + result = result.replaceAll(`@@${token}@@`, () => value); } return result; }