Skip to content

fix(server): skip the update backup when no migrations are pending - #1711

Merged
donjor merged 3 commits into
hyprwsfrom
fix/launcher-skip-backup-no-migrations
Oct 11, 2026
Merged

donjor merged 3 commits into
hyprwsfrom
fix/launcher-skip-backup-no-migrations

Conversation

@donjor-agent

@donjor-agent donjor-agent Bot commented Oct 11, 2026

Copy link
Copy Markdown

🤖 claude/anthropic claude-opus-5-5 (medium)

Problem

The service launcher copies the whole database before every update trial, after the old server stops.
On a 22 GB database that is about 91 s of downtime, even when the update adds no migrations.

Change

  1. Launcher runs the target's __service-preflight
  2. Preflight reports pending migrations
  3. Launcher backs up only if some are pending
  4. Preflight failure still backs up
  5. Launcher context stripped from every child

Step 5 closes the path that overwrote a live statev2.sqlite from a test run.

Scope and approval

Refs #1707, settled in the #1705 profile.
The downtime goal needs the launcher from this build, so its VM proof follows the next nightly.

Verification

Check Result
Launcher, preflight, context tests 19/19 pass
tsc --noEmit on apps/server exit 0
vp run fork:ci exit 0

Claude Opus 5.5 in Claude Code, hosted by T3 Code.

Fork trailers

Fork-Domain: upstream-fixes
Fork-Tier: bugfix
Fork-Upstreamable: no

Fork-Domain: upstream-fixes
Fork-Tier: bugfix
Fork-Upstreamable: yes
A trial child keeps its pending launcher context for life, so anything it spawns inherits a pending update for the live database. The preflight runtime now runs without that context; a test that read it overwrote ~/.t3/userdata/statev2.sqlite. Covers #1707.

Fork-Domain: upstream-fixes
Fork-Tier: bugfix
Fork-Upstreamable: no
The server moves T3_SERVICE_LAUNCHER_CONTEXT out of process.env at entry, so agents, providers, and test runs it spawns no longer inherit a pending update pointing at the live database. The server test setup clears it too. Covers #1707.

Fork-Domain: upstream-fixes
Fork-Tier: bugfix
Fork-Upstreamable: no
@rsi-software-agent

rsi-software-agent Bot commented Oct 11, 2026 •

Copy link
Copy Markdown

🩺 Aftercare: 🔵 1 finding remains on a55fe92

Reviewed 11 Oct 07:29 UTC in 8 min; advisory, never blocks merge.
Push to fix; reply A1: <reason> to dispute.

Details

A1 Measure 22 GB update downtime after the next nightly ships this launcher
Issue #1707's under-10-second downtime condition has not been demonstrated with this launcher. The PR explicitly defers that proof until the next nightly. Fix: Install the next nightly's launcher in the QA VM, run the no-migration update against the 22 GB database, and record measured downtime on #1707 before closing that condition.

Head Result Time Check
a55fe92 ✅ review passed: fixed: none; held: none; new: A1; withdrawn: none; no item resolved; files (12): apps/server/src/bin.ts, apps/server/src/cloud/serviceLauncherClient.ts, …and 10 more 8 min run

@donjor-agent

donjor-agent Bot commented Oct 11, 2026

Copy link
Copy Markdown
Author

🤖 claude/anthropic claude-opus-5-5 (medium)

A1: the old launcher runs the backup, so this needs a nightly with this build as the from-version; tracked as the #1705 re-run after merge.

@donjor
donjor merged commit 985c342 into hyprws Oct 11, 2026
@donjor
donjor deleted the fix/launcher-skip-backup-no-migrations branch October 11, 2026 20:46
donjor added a commit that referenced this pull request Oct 12, 2026
…1711)

## Problem

The service launcher copies the whole database before every update trial, after the old server stops.
On a 22 GB database that is about 91 s of downtime, even when the update adds no migrations.

## Change

1. Launcher runs the target's `__service-preflight`
2. Preflight reports pending migrations
3. Launcher backs up only if some are pending
4. Preflight failure still backs up
5. Launcher context stripped from every child

Step 5 closes the path that overwrote a live `statev2.sqlite` from a test run.

## Scope and approval

Refs #1707, settled in the #1705 profile.
The downtime goal needs the launcher from this build, so its VM proof follows the next nightly.

## Verification

| Check | Result |
| --- | --- |
| Launcher, preflight, context tests | 19/19 pass |
| `tsc --noEmit` on `apps/server` | exit 0 |
| `vp run fork:ci` | exit 0 |

Claude Opus 5.5 in Claude Code, hosted by T3 Code.

## Fork trailers

Fork-Domain: upstream-fixes
Fork-Tier: bugfix
Fork-Upstreamable: no
Co-authored-by: donjor <[email protected]>
donjor added a commit that referenced this pull request Oct 12, 2026
…1711)

## Problem

The service launcher copies the whole database before every update trial, after the old server stops.
On a 22 GB database that is about 91 s of downtime, even when the update adds no migrations.

## Change

1. Launcher runs the target's `__service-preflight`
2. Preflight reports pending migrations
3. Launcher backs up only if some are pending
4. Preflight failure still backs up
5. Launcher context stripped from every child

Step 5 closes the path that overwrote a live `statev2.sqlite` from a test run.

## Scope and approval

Refs #1707, settled in the #1705 profile.
The downtime goal needs the launcher from this build, so its VM proof follows the next nightly.

## Verification

| Check | Result |
| --- | --- |
| Launcher, preflight, context tests | 19/19 pass |
| `tsc --noEmit` on `apps/server` | exit 0 |
| `vp run fork:ci` | exit 0 |

Claude Opus 5.5 in Claude Code, hosted by T3 Code.

## Fork trailers

Fork-Domain: upstream-fixes
Fork-Tier: bugfix
Fork-Upstreamable: no
Co-authored-by: donjor <[email protected]>
donjor added a commit that referenced this pull request Oct 13, 2026
…1711)

## Problem

The service launcher copies the whole database before every update trial, after the old server stops.
On a 22 GB database that is about 91 s of downtime, even when the update adds no migrations.

## Change

1. Launcher runs the target's `__service-preflight`
2. Preflight reports pending migrations
3. Launcher backs up only if some are pending
4. Preflight failure still backs up
5. Launcher context stripped from every child

Step 5 closes the path that overwrote a live `statev2.sqlite` from a test run.

## Scope and approval

Refs #1707, settled in the #1705 profile.
The downtime goal needs the launcher from this build, so its VM proof follows the next nightly.

## Verification

| Check | Result |
| --- | --- |
| Launcher, preflight, context tests | 19/19 pass |
| `tsc --noEmit` on `apps/server` | exit 0 |
| `vp run fork:ci` | exit 0 |

Claude Opus 5.5 in Claude Code, hosted by T3 Code.

## Fork trailers

Fork-Domain: upstream-fixes
Fork-Tier: bugfix
Fork-Upstreamable: no
Co-authored-by: donjor <[email protected]>
donjor added a commit that referenced this pull request Oct 15, 2026
…1711)

## Problem

The service launcher copies the whole database before every update trial, after the old server stops.
On a 22 GB database that is about 91 s of downtime, even when the update adds no migrations.

## Change

1. Launcher runs the target's `__service-preflight`
2. Preflight reports pending migrations
3. Launcher backs up only if some are pending
4. Preflight failure still backs up
5. Launcher context stripped from every child

Step 5 closes the path that overwrote a live `statev2.sqlite` from a test run.

## Scope and approval

Refs #1707, settled in the #1705 profile.
The downtime goal needs the launcher from this build, so its VM proof follows the next nightly.

## Verification

| Check | Result |
| --- | --- |
| Launcher, preflight, context tests | 19/19 pass |
| `tsc --noEmit` on `apps/server` | exit 0 |
| `vp run fork:ci` | exit 0 |

Claude Opus 5.5 in Claude Code, hosted by T3 Code.

## Fork trailers

Fork-Domain: upstream-fixes
Fork-Tier: bugfix
Fork-Upstreamable: no
Co-authored-by: donjor <[email protected]>
donjor added a commit that referenced this pull request Oct 15, 2026
…1711)

## Problem

The service launcher copies the whole database before every update trial, after the old server stops.
On a 22 GB database that is about 91 s of downtime, even when the update adds no migrations.

## Change

1. Launcher runs the target's `__service-preflight`
2. Preflight reports pending migrations
3. Launcher backs up only if some are pending
4. Preflight failure still backs up
5. Launcher context stripped from every child

Step 5 closes the path that overwrote a live `statev2.sqlite` from a test run.

## Scope and approval

Refs #1707, settled in the #1705 profile.
The downtime goal needs the launcher from this build, so its VM proof follows the next nightly.

## Verification

| Check | Result |
| --- | --- |
| Launcher, preflight, context tests | 19/19 pass |
| `tsc --noEmit` on `apps/server` | exit 0 |
| `vp run fork:ci` | exit 0 |

Claude Opus 5.5 in Claude Code, hosted by T3 Code.

## Fork trailers

Fork-Domain: upstream-fixes
Fork-Tier: bugfix
Fork-Upstreamable: no
Co-authored-by: donjor <[email protected]>
donjor added a commit that referenced this pull request Oct 16, 2026
…1711)

## Problem

The service launcher copies the whole database before every update trial, after the old server stops.
On a 22 GB database that is about 91 s of downtime, even when the update adds no migrations.

## Change

1. Launcher runs the target's `__service-preflight`
2. Preflight reports pending migrations
3. Launcher backs up only if some are pending
4. Preflight failure still backs up
5. Launcher context stripped from every child

Step 5 closes the path that overwrote a live `statev2.sqlite` from a test run.

## Scope and approval

Refs #1707, settled in the #1705 profile.
The downtime goal needs the launcher from this build, so its VM proof follows the next nightly.

## Verification

| Check | Result |
| --- | --- |
| Launcher, preflight, context tests | 19/19 pass |
| `tsc --noEmit` on `apps/server` | exit 0 |
| `vp run fork:ci` | exit 0 |

Claude Opus 5.5 in Claude Code, hosted by T3 Code.

## Fork trailers

Fork-Domain: upstream-fixes
Fork-Tier: bugfix
Fork-Upstreamable: no
Co-authored-by: donjor <[email protected]>
donjor added a commit that referenced this pull request Oct 16, 2026
…1711)

## Problem

The service launcher copies the whole database before every update trial, after the old server stops.
On a 22 GB database that is about 91 s of downtime, even when the update adds no migrations.

## Change

1. Launcher runs the target's `__service-preflight`
2. Preflight reports pending migrations
3. Launcher backs up only if some are pending
4. Preflight failure still backs up
5. Launcher context stripped from every child

Step 5 closes the path that overwrote a live `statev2.sqlite` from a test run.

## Scope and approval

Refs #1707, settled in the #1705 profile.
The downtime goal needs the launcher from this build, so its VM proof follows the next nightly.

## Verification

| Check | Result |
| --- | --- |
| Launcher, preflight, context tests | 19/19 pass |
| `tsc --noEmit` on `apps/server` | exit 0 |
| `vp run fork:ci` | exit 0 |

Claude Opus 5.5 in Claude Code, hosted by T3 Code.

## Fork trailers

Fork-Domain: upstream-fixes
Fork-Tier: bugfix
Fork-Upstreamable: no
Co-authored-by: donjor <[email protected]>
donjor added a commit that referenced this pull request Oct 18, 2026
…1711)

## Problem

The service launcher copies the whole database before every update trial, after the old server stops.
On a 22 GB database that is about 91 s of downtime, even when the update adds no migrations.

## Change

1. Launcher runs the target's `__service-preflight`
2. Preflight reports pending migrations
3. Launcher backs up only if some are pending
4. Preflight failure still backs up
5. Launcher context stripped from every child

Step 5 closes the path that overwrote a live `statev2.sqlite` from a test run.

## Scope and approval

Refs #1707, settled in the #1705 profile.
The downtime goal needs the launcher from this build, so its VM proof follows the next nightly.

## Verification

| Check | Result |
| --- | --- |
| Launcher, preflight, context tests | 19/19 pass |
| `tsc --noEmit` on `apps/server` | exit 0 |
| `vp run fork:ci` | exit 0 |

Claude Opus 5.5 in Claude Code, hosted by T3 Code.

## Fork trailers

Fork-Domain: upstream-fixes
Fork-Tier: bugfix
Fork-Upstreamable: no
Co-authored-by: donjor <[email protected]>
donjor added a commit that referenced this pull request Oct 18, 2026
…1711)

## Problem

The service launcher copies the whole database before every update trial, after the old server stops.
On a 22 GB database that is about 91 s of downtime, even when the update adds no migrations.

## Change

1. Launcher runs the target's `__service-preflight`
2. Preflight reports pending migrations
3. Launcher backs up only if some are pending
4. Preflight failure still backs up
5. Launcher context stripped from every child

Step 5 closes the path that overwrote a live `statev2.sqlite` from a test run.

## Scope and approval

Refs #1707, settled in the #1705 profile.
The downtime goal needs the launcher from this build, so its VM proof follows the next nightly.

## Verification

| Check | Result |
| --- | --- |
| Launcher, preflight, context tests | 19/19 pass |
| `tsc --noEmit` on `apps/server` | exit 0 |
| `vp run fork:ci` | exit 0 |

Claude Opus 5.5 in Claude Code, hosted by T3 Code.

## Fork trailers

Fork-Domain: upstream-fixes
Fork-Tier: bugfix
Fork-Upstreamable: no
Co-authored-by: donjor <[email protected]>
donjor added a commit that referenced this pull request Oct 18, 2026
…1711)

## Problem

The service launcher copies the whole database before every update trial, after the old server stops.
On a 22 GB database that is about 91 s of downtime, even when the update adds no migrations.

## Change

1. Launcher runs the target's `__service-preflight`
2. Preflight reports pending migrations
3. Launcher backs up only if some are pending
4. Preflight failure still backs up
5. Launcher context stripped from every child

Step 5 closes the path that overwrote a live `statev2.sqlite` from a test run.

## Scope and approval

Refs #1707, settled in the #1705 profile.
The downtime goal needs the launcher from this build, so its VM proof follows the next nightly.

## Verification

| Check | Result |
| --- | --- |
| Launcher, preflight, context tests | 19/19 pass |
| `tsc --noEmit` on `apps/server` | exit 0 |
| `vp run fork:ci` | exit 0 |

Claude Opus 5.5 in Claude Code, hosted by T3 Code.

## Fork trailers

Fork-Domain: upstream-fixes
Fork-Tier: bugfix
Fork-Upstreamable: no
Co-authored-by: donjor <[email protected]>
donjor added a commit that referenced this pull request Oct 19, 2026
…1711)

## Problem

The service launcher copies the whole database before every update trial, after the old server stops.
On a 22 GB database that is about 91 s of downtime, even when the update adds no migrations.

## Change

1. Launcher runs the target's `__service-preflight`
2. Preflight reports pending migrations
3. Launcher backs up only if some are pending
4. Preflight failure still backs up
5. Launcher context stripped from every child

Step 5 closes the path that overwrote a live `statev2.sqlite` from a test run.

## Scope and approval

Refs #1707, settled in the #1705 profile.
The downtime goal needs the launcher from this build, so its VM proof follows the next nightly.

## Verification

| Check | Result |
| --- | --- |
| Launcher, preflight, context tests | 19/19 pass |
| `tsc --noEmit` on `apps/server` | exit 0 |
| `vp run fork:ci` | exit 0 |

Claude Opus 5.5 in Claude Code, hosted by T3 Code.

## Fork trailers

Fork-Domain: upstream-fixes
Fork-Tier: bugfix
Fork-Upstreamable: no
Co-authored-by: donjor <[email protected]>
donjor added a commit that referenced this pull request Oct 19, 2026
…1711)

## Problem

The service launcher copies the whole database before every update trial, after the old server stops.
On a 22 GB database that is about 91 s of downtime, even when the update adds no migrations.

## Change

1. Launcher runs the target's `__service-preflight`
2. Preflight reports pending migrations
3. Launcher backs up only if some are pending
4. Preflight failure still backs up
5. Launcher context stripped from every child

Step 5 closes the path that overwrote a live `statev2.sqlite` from a test run.

## Scope and approval

Refs #1707, settled in the #1705 profile.
The downtime goal needs the launcher from this build, so its VM proof follows the next nightly.

## Verification

| Check | Result |
| --- | --- |
| Launcher, preflight, context tests | 19/19 pass |
| `tsc --noEmit` on `apps/server` | exit 0 |
| `vp run fork:ci` | exit 0 |

Claude Opus 5.5 in Claude Code, hosted by T3 Code.

## Fork trailers

Fork-Domain: upstream-fixes
Fork-Tier: bugfix
Fork-Upstreamable: no
Co-authored-by: donjor <[email protected]>
donjor added a commit that referenced this pull request Oct 19, 2026
…1711)

## Problem

The service launcher copies the whole database before every update trial, after the old server stops.
On a 22 GB database that is about 91 s of downtime, even when the update adds no migrations.

## Change

1. Launcher runs the target's `__service-preflight`
2. Preflight reports pending migrations
3. Launcher backs up only if some are pending
4. Preflight failure still backs up
5. Launcher context stripped from every child

Step 5 closes the path that overwrote a live `statev2.sqlite` from a test run.

## Scope and approval

Refs #1707, settled in the #1705 profile.
The downtime goal needs the launcher from this build, so its VM proof follows the next nightly.

## Verification

| Check | Result |
| --- | --- |
| Launcher, preflight, context tests | 19/19 pass |
| `tsc --noEmit` on `apps/server` | exit 0 |
| `vp run fork:ci` | exit 0 |

Claude Opus 5.5 in Claude Code, hosted by T3 Code.

## Fork trailers

Fork-Domain: upstream-fixes
Fork-Tier: bugfix
Fork-Upstreamable: no
Co-authored-by: donjor <[email protected]>
donjor added a commit that referenced this pull request Oct 20, 2026
…1711)

## Problem

The service launcher copies the whole database before every update trial, after the old server stops.
On a 22 GB database that is about 91 s of downtime, even when the update adds no migrations.

## Change

1. Launcher runs the target's `__service-preflight`
2. Preflight reports pending migrations
3. Launcher backs up only if some are pending
4. Preflight failure still backs up
5. Launcher context stripped from every child

Step 5 closes the path that overwrote a live `statev2.sqlite` from a test run.

## Scope and approval

Refs #1707, settled in the #1705 profile.
The downtime goal needs the launcher from this build, so its VM proof follows the next nightly.

## Verification

| Check | Result |
| --- | --- |
| Launcher, preflight, context tests | 19/19 pass |
| `tsc --noEmit` on `apps/server` | exit 0 |
| `vp run fork:ci` | exit 0 |

Claude Opus 5.5 in Claude Code, hosted by T3 Code.

## Fork trailers

Fork-Domain: upstream-fixes
Fork-Tier: bugfix
Fork-Upstreamable: no
Co-authored-by: donjor <[email protected]>
donjor added a commit that referenced this pull request Oct 20, 2026
…1711)

## Problem

The service launcher copies the whole database before every update trial, after the old server stops.
On a 22 GB database that is about 91 s of downtime, even when the update adds no migrations.

## Change

1. Launcher runs the target's `__service-preflight`
2. Preflight reports pending migrations
3. Launcher backs up only if some are pending
4. Preflight failure still backs up
5. Launcher context stripped from every child

Step 5 closes the path that overwrote a live `statev2.sqlite` from a test run.

## Scope and approval

Refs #1707, settled in the #1705 profile.
The downtime goal needs the launcher from this build, so its VM proof follows the next nightly.

## Verification

| Check | Result |
| --- | --- |
| Launcher, preflight, context tests | 19/19 pass |
| `tsc --noEmit` on `apps/server` | exit 0 |
| `vp run fork:ci` | exit 0 |

Claude Opus 5.5 in Claude Code, hosted by T3 Code.

## Fork trailers

Fork-Domain: upstream-fixes
Fork-Tier: bugfix
Fork-Upstreamable: no
Co-authored-by: donjor <[email protected]>
donjor added a commit that referenced this pull request Oct 20, 2026
…1711)

## Problem

The service launcher copies the whole database before every update trial, after the old server stops.
On a 22 GB database that is about 91 s of downtime, even when the update adds no migrations.

## Change

1. Launcher runs the target's `__service-preflight`
2. Preflight reports pending migrations
3. Launcher backs up only if some are pending
4. Preflight failure still backs up
5. Launcher context stripped from every child

Step 5 closes the path that overwrote a live `statev2.sqlite` from a test run.

## Scope and approval

Refs #1707, settled in the #1705 profile.
The downtime goal needs the launcher from this build, so its VM proof follows the next nightly.

## Verification

| Check | Result |
| --- | --- |
| Launcher, preflight, context tests | 19/19 pass |
| `tsc --noEmit` on `apps/server` | exit 0 |
| `vp run fork:ci` | exit 0 |

Claude Opus 5.5 in Claude Code, hosted by T3 Code.

## Fork trailers

Fork-Domain: upstream-fixes
Fork-Tier: bugfix
Fork-Upstreamable: no
Co-authored-by: donjor <[email protected]>
donjor added a commit that referenced this pull request Oct 20, 2026
…1711)

## Problem

The service launcher copies the whole database before every update trial, after the old server stops.
On a 22 GB database that is about 91 s of downtime, even when the update adds no migrations.

## Change

1. Launcher runs the target's `__service-preflight`
2. Preflight reports pending migrations
3. Launcher backs up only if some are pending
4. Preflight failure still backs up
5. Launcher context stripped from every child

Step 5 closes the path that overwrote a live `statev2.sqlite` from a test run.

## Scope and approval

Refs #1707, settled in the #1705 profile.
The downtime goal needs the launcher from this build, so its VM proof follows the next nightly.

## Verification

| Check | Result |
| --- | --- |
| Launcher, preflight, context tests | 19/19 pass |
| `tsc --noEmit` on `apps/server` | exit 0 |
| `vp run fork:ci` | exit 0 |

Claude Opus 5.5 in Claude Code, hosted by T3 Code.

## Fork trailers

Fork-Domain: upstream-fixes
Fork-Tier: bugfix
Fork-Upstreamable: no
Co-authored-by: donjor <[email protected]>
donjor added a commit that referenced this pull request Oct 20, 2026
…1711)

## Problem

The service launcher copies the whole database before every update trial, after the old server stops.
On a 22 GB database that is about 91 s of downtime, even when the update adds no migrations.

## Change

1. Launcher runs the target's `__service-preflight`
2. Preflight reports pending migrations
3. Launcher backs up only if some are pending
4. Preflight failure still backs up
5. Launcher context stripped from every child

Step 5 closes the path that overwrote a live `statev2.sqlite` from a test run.

## Scope and approval

Refs #1707, settled in the #1705 profile.
The downtime goal needs the launcher from this build, so its VM proof follows the next nightly.

## Verification

| Check | Result |
| --- | --- |
| Launcher, preflight, context tests | 19/19 pass |
| `tsc --noEmit` on `apps/server` | exit 0 |
| `vp run fork:ci` | exit 0 |

Claude Opus 5.5 in Claude Code, hosted by T3 Code.

## Fork trailers

Fork-Domain: upstream-fixes
Fork-Tier: bugfix
Fork-Upstreamable: no
Co-authored-by: donjor <[email protected]>
donjor added a commit that referenced this pull request Oct 21, 2026
…1711)

## Problem

The service launcher copies the whole database before every update trial, after the old server stops.
On a 22 GB database that is about 91 s of downtime, even when the update adds no migrations.

## Change

1. Launcher runs the target's `__service-preflight`
2. Preflight reports pending migrations
3. Launcher backs up only if some are pending
4. Preflight failure still backs up
5. Launcher context stripped from every child

Step 5 closes the path that overwrote a live `statev2.sqlite` from a test run.

## Scope and approval

Refs #1707, settled in the #1705 profile.
The downtime goal needs the launcher from this build, so its VM proof follows the next nightly.

## Verification

| Check | Result |
| --- | --- |
| Launcher, preflight, context tests | 19/19 pass |
| `tsc --noEmit` on `apps/server` | exit 0 |
| `vp run fork:ci` | exit 0 |

Claude Opus 5.5 in Claude Code, hosted by T3 Code.

## Fork trailers

Fork-Domain: upstream-fixes
Fork-Tier: bugfix
Fork-Upstreamable: no
Co-authored-by: donjor <[email protected]>
rsi-software-agent Bot pushed a commit that referenced this pull request Oct 29, 2026
…1711)

## Problem

The service launcher copies the whole database before every update trial, after the old server stops.
On a 22 GB database that is about 91 s of downtime, even when the update adds no migrations.

## Change

1. Launcher runs the target's `__service-preflight`
2. Preflight reports pending migrations
3. Launcher backs up only if some are pending
4. Preflight failure still backs up
5. Launcher context stripped from every child

Step 5 closes the path that overwrote a live `statev2.sqlite` from a test run.

## Scope and approval

Refs #1707, settled in the #1705 profile.
The downtime goal needs the launcher from this build, so its VM proof follows the next nightly.

## Verification

| Check | Result |
| --- | --- |
| Launcher, preflight, context tests | 19/19 pass |
| `tsc --noEmit` on `apps/server` | exit 0 |
| `vp run fork:ci` | exit 0 |

Claude Opus 5.5 in Claude Code, hosted by T3 Code.

## Fork trailers

Fork-Domain: upstream-fixes
Fork-Tier: bugfix
Fork-Upstreamable: no
Co-authored-by: donjor <[email protected]>
rsi-software-agent Bot pushed a commit that referenced this pull request Oct 29, 2026
…1711)

## Problem

The service launcher copies the whole database before every update trial, after the old server stops.
On a 22 GB database that is about 91 s of downtime, even when the update adds no migrations.

## Change

1. Launcher runs the target's `__service-preflight`
2. Preflight reports pending migrations
3. Launcher backs up only if some are pending
4. Preflight failure still backs up
5. Launcher context stripped from every child

Step 5 closes the path that overwrote a live `statev2.sqlite` from a test run.

## Scope and approval

Refs #1707, settled in the #1705 profile.
The downtime goal needs the launcher from this build, so its VM proof follows the next nightly.

## Verification

| Check | Result |
| --- | --- |
| Launcher, preflight, context tests | 19/19 pass |
| `tsc --noEmit` on `apps/server` | exit 0 |
| `vp run fork:ci` | exit 0 |

Claude Opus 5.5 in Claude Code, hosted by T3 Code.

## Fork trailers

Fork-Domain: upstream-fixes
Fork-Tier: bugfix
Fork-Upstreamable: no
Co-authored-by: donjor <[email protected]>
rsi-software-agent Bot pushed a commit that referenced this pull request Oct 29, 2026
…ding (#1711)

Fork-Domain: upstream-fixes
Fork-Tier: bugfix
Fork-Upstreamable: no
rsi-software-agent Bot pushed a commit that referenced this pull request Oct 29, 2026
…1711)

## Problem

The service launcher copies the whole database before every update trial, after the old server stops.
On a 22 GB database that is about 91 s of downtime, even when the update adds no migrations.

## Change

1. Launcher runs the target's `__service-preflight`
2. Preflight reports pending migrations
3. Launcher backs up only if some are pending
4. Preflight failure still backs up
5. Launcher context stripped from every child

Step 5 closes the path that overwrote a live `statev2.sqlite` from a test run.

## Scope and approval

Refs #1707, settled in the #1705 profile.
The downtime goal needs the launcher from this build, so its VM proof follows the next nightly.

## Verification

| Check | Result |
| --- | --- |
| Launcher, preflight, context tests | 19/19 pass |
| `tsc --noEmit` on `apps/server` | exit 0 |
| `vp run fork:ci` | exit 0 |

Claude Opus 5.5 in Claude Code, hosted by T3 Code.

## Fork trailers

Squashes:

- 3d6a528 fix(server): skip the update backup when no migrations are pending (#1711) (#1711)
- 858784c fixup! fix(server): skip the update backup when no migrations are pending (#1711) (#1711)

Fork-Domain: upstream-fixes
Fork-Tier: bugfix
Fork-Upstreamable: no
Co-authored-by: donjor <[email protected]>
rsi-software-agent Bot pushed a commit that referenced this pull request Oct 30, 2026
…1711)

## Problem

The service launcher copies the whole database before every update trial, after the old server stops.
On a 22 GB database that is about 91 s of downtime, even when the update adds no migrations.

## Change

1. Launcher runs the target's `__service-preflight`
2. Preflight reports pending migrations
3. Launcher backs up only if some are pending
4. Preflight failure still backs up
5. Launcher context stripped from every child

Step 5 closes the path that overwrote a live `statev2.sqlite` from a test run.

## Scope and approval

Refs #1707, settled in the #1705 profile.
The downtime goal needs the launcher from this build, so its VM proof follows the next nightly.

## Verification

| Check | Result |
| --- | --- |
| Launcher, preflight, context tests | 19/19 pass |
| `tsc --noEmit` on `apps/server` | exit 0 |
| `vp run fork:ci` | exit 0 |

Claude Opus 5.5 in Claude Code, hosted by T3 Code.

## Fork trailers

Squashes:

- 3d6a528 fix(server): skip the update backup when no migrations are pending (#1711) (#1711)
- 858784c fixup! fix(server): skip the update backup when no migrations are pending (#1711) (#1711)

Fork-Domain: upstream-fixes
Fork-Tier: bugfix
Fork-Upstreamable: no
Co-authored-by: donjor <[email protected]>
rsi-software-agent Bot pushed a commit that referenced this pull request Oct 30, 2026
…1711)

## Problem

The service launcher copies the whole database before every update trial, after the old server stops.
On a 22 GB database that is about 91 s of downtime, even when the update adds no migrations.

## Change

1. Launcher runs the target's `__service-preflight`
2. Preflight reports pending migrations
3. Launcher backs up only if some are pending
4. Preflight failure still backs up
5. Launcher context stripped from every child

Step 5 closes the path that overwrote a live `statev2.sqlite` from a test run.

## Scope and approval

Refs #1707, settled in the #1705 profile.
The downtime goal needs the launcher from this build, so its VM proof follows the next nightly.

## Verification

| Check | Result |
| --- | --- |
| Launcher, preflight, context tests | 19/19 pass |
| `tsc --noEmit` on `apps/server` | exit 0 |
| `vp run fork:ci` | exit 0 |

Claude Opus 5.5 in Claude Code, hosted by T3 Code.

## Fork trailers

Squashes:

- 3d6a528 fix(server): skip the update backup when no migrations are pending (#1711) (#1711)
- 858784c fixup! fix(server): skip the update backup when no migrations are pending (#1711) (#1711)

Fork-Domain: upstream-fixes
Fork-Tier: bugfix
Fork-Upstreamable: no
Co-authored-by: donjor <[email protected]>
rsi-software-agent Bot pushed a commit that referenced this pull request Oct 30, 2026
…1711)

## Problem

The service launcher copies the whole database before every update trial, after the old server stops.
On a 22 GB database that is about 91 s of downtime, even when the update adds no migrations.

## Change

1. Launcher runs the target's `__service-preflight`
2. Preflight reports pending migrations
3. Launcher backs up only if some are pending
4. Preflight failure still backs up
5. Launcher context stripped from every child

Step 5 closes the path that overwrote a live `statev2.sqlite` from a test run.

## Scope and approval

Refs #1707, settled in the #1705 profile.
The downtime goal needs the launcher from this build, so its VM proof follows the next nightly.

## Verification

| Check | Result |
| --- | --- |
| Launcher, preflight, context tests | 19/19 pass |
| `tsc --noEmit` on `apps/server` | exit 0 |
| `vp run fork:ci` | exit 0 |

Claude Opus 5.5 in Claude Code, hosted by T3 Code.

## Fork trailers

Squashes:

- 3d6a528 fix(server): skip the update backup when no migrations are pending (#1711) (#1711)
- 858784c fixup! fix(server): skip the update backup when no migrations are pending (#1711) (#1711)

Fork-Domain: upstream-fixes
Fork-Tier: bugfix
Fork-Upstreamable: no
Co-authored-by: donjor <[email protected]>
rsi-software-agent Bot pushed a commit that referenced this pull request Oct 31, 2026
…1711)

## Problem

The service launcher copies the whole database before every update trial, after the old server stops.
On a 22 GB database that is about 91 s of downtime, even when the update adds no migrations.

## Change

1. Launcher runs the target's `__service-preflight`
2. Preflight reports pending migrations
3. Launcher backs up only if some are pending
4. Preflight failure still backs up
5. Launcher context stripped from every child

Step 5 closes the path that overwrote a live `statev2.sqlite` from a test run.

## Scope and approval

Refs #1707, settled in the #1705 profile.
The downtime goal needs the launcher from this build, so its VM proof follows the next nightly.

## Verification

| Check | Result |
| --- | --- |
| Launcher, preflight, context tests | 19/19 pass |
| `tsc --noEmit` on `apps/server` | exit 0 |
| `vp run fork:ci` | exit 0 |

Claude Opus 5.5 in Claude Code, hosted by T3 Code.

## Fork trailers

Squashes:

- 3d6a528 fix(server): skip the update backup when no migrations are pending (#1711) (#1711)
- 858784c fixup! fix(server): skip the update backup when no migrations are pending (#1711) (#1711)

Fork-Domain: upstream-fixes
Fork-Tier: bugfix
Fork-Upstreamable: no
Co-authored-by: donjor <[email protected]>
donjor added a commit that referenced this pull request Nov 6, 2026
…1711)

## Problem

The service launcher copies the whole database before every update trial, after the old server stops.
On a 22 GB database that is about 91 s of downtime, even when the update adds no migrations.

## Change

1. Launcher runs the target's `__service-preflight`
2. Preflight reports pending migrations
3. Launcher backs up only if some are pending
4. Preflight failure still backs up
5. Launcher context stripped from every child

Step 5 closes the path that overwrote a live `statev2.sqlite` from a test run.

## Scope and approval

Refs #1707, settled in the #1705 profile.
The downtime goal needs the launcher from this build, so its VM proof follows the next nightly.

## Verification

| Check | Result |
| --- | --- |
| Launcher, preflight, context tests | 19/19 pass |
| `tsc --noEmit` on `apps/server` | exit 0 |
| `vp run fork:ci` | exit 0 |

Claude Opus 5.5 in Claude Code, hosted by T3 Code.

## Fork trailers

Squashes:

- 3d6a528 fix(server): skip the update backup when no migrations are pending (#1711) (#1711)
- 858784c fixup! fix(server): skip the update backup when no migrations are pending (#1711) (#1711)

Fork-Domain: upstream-fixes
Fork-Tier: bugfix
Fork-Upstreamable: no
Co-authored-by: donjor <[email protected]>
rsi-software-agent Bot pushed a commit that referenced this pull request Nov 6, 2026
…1711)

## Problem

The service launcher copies the whole database before every update trial, after the old server stops.
On a 22 GB database that is about 91 s of downtime, even when the update adds no migrations.

## Change

1. Launcher runs the target's `__service-preflight`
2. Preflight reports pending migrations
3. Launcher backs up only if some are pending
4. Preflight failure still backs up
5. Launcher context stripped from every child

Step 5 closes the path that overwrote a live `statev2.sqlite` from a test run.

## Scope and approval

Refs #1707, settled in the #1705 profile.
The downtime goal needs the launcher from this build, so its VM proof follows the next nightly.

## Verification

| Check | Result |
| --- | --- |
| Launcher, preflight, context tests | 19/19 pass |
| `tsc --noEmit` on `apps/server` | exit 0 |
| `vp run fork:ci` | exit 0 |

Claude Opus 5.5 in Claude Code, hosted by T3 Code.

## Fork trailers

Squashes:

- 3d6a528 fix(server): skip the update backup when no migrations are pending (#1711) (#1711)
- 858784c fixup! fix(server): skip the update backup when no migrations are pending (#1711) (#1711)

Fork-Domain: upstream-fixes
Fork-Tier: bugfix
Fork-Upstreamable: no
Co-authored-by: donjor <[email protected]>
rsi-software-agent Bot pushed a commit that referenced this pull request Nov 6, 2026
…1711)

## Problem

The service launcher copies the whole database before every update trial, after the old server stops.
On a 22 GB database that is about 91 s of downtime, even when the update adds no migrations.

## Change

1. Launcher runs the target's `__service-preflight`
2. Preflight reports pending migrations
3. Launcher backs up only if some are pending
4. Preflight failure still backs up
5. Launcher context stripped from every child

Step 5 closes the path that overwrote a live `statev2.sqlite` from a test run.

## Scope and approval

Refs #1707, settled in the #1705 profile.
The downtime goal needs the launcher from this build, so its VM proof follows the next nightly.

## Verification

| Check | Result |
| --- | --- |
| Launcher, preflight, context tests | 19/19 pass |
| `tsc --noEmit` on `apps/server` | exit 0 |
| `vp run fork:ci` | exit 0 |

Claude Opus 5.5 in Claude Code, hosted by T3 Code.

## Fork trailers

Squashes:

- 3d6a528 fix(server): skip the update backup when no migrations are pending (#1711) (#1711)
- 858784c fixup! fix(server): skip the update backup when no migrations are pending (#1711) (#1711)

Fork-Domain: upstream-fixes
Fork-Tier: bugfix
Fork-Upstreamable: no
Co-authored-by: donjor <[email protected]>
rsi-software-agent Bot pushed a commit that referenced this pull request Nov 6, 2026
…1711)

## Problem

The service launcher copies the whole database before every update trial, after the old server stops.
On a 22 GB database that is about 91 s of downtime, even when the update adds no migrations.

## Change

1. Launcher runs the target's `__service-preflight`
2. Preflight reports pending migrations
3. Launcher backs up only if some are pending
4. Preflight failure still backs up
5. Launcher context stripped from every child

Step 5 closes the path that overwrote a live `statev2.sqlite` from a test run.

## Scope and approval

Refs #1707, settled in the #1705 profile.
The downtime goal needs the launcher from this build, so its VM proof follows the next nightly.

## Verification

| Check | Result |
| --- | --- |
| Launcher, preflight, context tests | 19/19 pass |
| `tsc --noEmit` on `apps/server` | exit 0 |
| `vp run fork:ci` | exit 0 |

Claude Opus 5.5 in Claude Code, hosted by T3 Code.

## Fork trailers

Squashes:

- 3d6a528 fix(server): skip the update backup when no migrations are pending (#1711) (#1711)
- 858784c fixup! fix(server): skip the update backup when no migrations are pending (#1711) (#1711)

Fork-Domain: upstream-fixes
Fork-Tier: bugfix
Fork-Upstreamable: no
Co-authored-by: donjor <[email protected]>
rsi-software-agent Bot pushed a commit that referenced this pull request Nov 6, 2026
…1711)

## Problem

The service launcher copies the whole database before every update trial, after the old server stops.
On a 22 GB database that is about 91 s of downtime, even when the update adds no migrations.

## Change

1. Launcher runs the target's `__service-preflight`
2. Preflight reports pending migrations
3. Launcher backs up only if some are pending
4. Preflight failure still backs up
5. Launcher context stripped from every child

Step 5 closes the path that overwrote a live `statev2.sqlite` from a test run.

## Scope and approval

Refs #1707, settled in the #1705 profile.
The downtime goal needs the launcher from this build, so its VM proof follows the next nightly.

## Verification

| Check | Result |
| --- | --- |
| Launcher, preflight, context tests | 19/19 pass |
| `tsc --noEmit` on `apps/server` | exit 0 |
| `vp run fork:ci` | exit 0 |

Claude Opus 5.5 in Claude Code, hosted by T3 Code.

## Fork trailers

Squashes:

- 3d6a528 fix(server): skip the update backup when no migrations are pending (#1711) (#1711)
- 858784c fixup! fix(server): skip the update backup when no migrations are pending (#1711) (#1711)

Fork-Domain: upstream-fixes
Fork-Tier: bugfix
Fork-Upstreamable: no
Co-authored-by: donjor <[email protected]>
rsi-software-agent Bot pushed a commit that referenced this pull request Nov 6, 2026
…1711)

## Problem

The service launcher copies the whole database before every update trial, after the old server stops.
On a 22 GB database that is about 91 s of downtime, even when the update adds no migrations.

## Change

1. Launcher runs the target's `__service-preflight`
2. Preflight reports pending migrations
3. Launcher backs up only if some are pending
4. Preflight failure still backs up
5. Launcher context stripped from every child

Step 5 closes the path that overwrote a live `statev2.sqlite` from a test run.

## Scope and approval

Refs #1707, settled in the #1705 profile.
The downtime goal needs the launcher from this build, so its VM proof follows the next nightly.

## Verification

| Check | Result |
| --- | --- |
| Launcher, preflight, context tests | 19/19 pass |
| `tsc --noEmit` on `apps/server` | exit 0 |
| `vp run fork:ci` | exit 0 |

Claude Opus 5.5 in Claude Code, hosted by T3 Code.

## Fork trailers

Squashes:

- 3d6a528 fix(server): skip the update backup when no migrations are pending (#1711) (#1711)
- 858784c fixup! fix(server): skip the update backup when no migrations are pending (#1711) (#1711)

Fork-Domain: upstream-fixes
Fork-Tier: bugfix
Fork-Upstreamable: no
Co-authored-by: donjor <[email protected]>
rsi-software-agent Bot pushed a commit that referenced this pull request Nov 6, 2026
…1711)

## Problem

The service launcher copies the whole database before every update trial, after the old server stops.
On a 22 GB database that is about 91 s of downtime, even when the update adds no migrations.

## Change

1. Launcher runs the target's `__service-preflight`
2. Preflight reports pending migrations
3. Launcher backs up only if some are pending
4. Preflight failure still backs up
5. Launcher context stripped from every child

Step 5 closes the path that overwrote a live `statev2.sqlite` from a test run.

## Scope and approval

Refs #1707, settled in the #1705 profile.
The downtime goal needs the launcher from this build, so its VM proof follows the next nightly.

## Verification

| Check | Result |
| --- | --- |
| Launcher, preflight, context tests | 19/19 pass |
| `tsc --noEmit` on `apps/server` | exit 0 |
| `vp run fork:ci` | exit 0 |

Claude Opus 5.5 in Claude Code, hosted by T3 Code.

## Fork trailers

Squashes:

- 3d6a528 fix(server): skip the update backup when no migrations are pending (#1711) (#1711)
- 858784c fixup! fix(server): skip the update backup when no migrations are pending (#1711) (#1711)

Fork-Domain: upstream-fixes
Fork-Tier: bugfix
Fork-Upstreamable: no
Co-authored-by: donjor <[email protected]>
rsi-software-agent Bot pushed a commit that referenced this pull request Nov 7, 2026
…1711)

## Problem

The service launcher copies the whole database before every update trial, after the old server stops.
On a 22 GB database that is about 91 s of downtime, even when the update adds no migrations.

## Change

1. Launcher runs the target's `__service-preflight`
2. Preflight reports pending migrations
3. Launcher backs up only if some are pending
4. Preflight failure still backs up
5. Launcher context stripped from every child

Step 5 closes the path that overwrote a live `statev2.sqlite` from a test run.

## Scope and approval

Refs #1707, settled in the #1705 profile.
The downtime goal needs the launcher from this build, so its VM proof follows the next nightly.

## Verification

| Check | Result |
| --- | --- |
| Launcher, preflight, context tests | 19/19 pass |
| `tsc --noEmit` on `apps/server` | exit 0 |
| `vp run fork:ci` | exit 0 |

Claude Opus 5.5 in Claude Code, hosted by T3 Code.

## Fork trailers

Squashes:

- 3d6a528 fix(server): skip the update backup when no migrations are pending (#1711) (#1711)
- 858784c fixup! fix(server): skip the update backup when no migrations are pending (#1711) (#1711)

Fork-Domain: upstream-fixes
Fork-Tier: bugfix
Fork-Upstreamable: no
Co-authored-by: donjor <[email protected]>
rsi-software-agent Bot pushed a commit that referenced this pull request Nov 7, 2026
…1711)

## Problem

The service launcher copies the whole database before every update trial, after the old server stops.
On a 22 GB database that is about 91 s of downtime, even when the update adds no migrations.

## Change

1. Launcher runs the target's `__service-preflight`
2. Preflight reports pending migrations
3. Launcher backs up only if some are pending
4. Preflight failure still backs up
5. Launcher context stripped from every child

Step 5 closes the path that overwrote a live `statev2.sqlite` from a test run.

## Scope and approval

Refs #1707, settled in the #1705 profile.
The downtime goal needs the launcher from this build, so its VM proof follows the next nightly.

## Verification

| Check | Result |
| --- | --- |
| Launcher, preflight, context tests | 19/19 pass |
| `tsc --noEmit` on `apps/server` | exit 0 |
| `vp run fork:ci` | exit 0 |

Claude Opus 5.5 in Claude Code, hosted by T3 Code.

## Fork trailers

Squashes:

- 3d6a528 fix(server): skip the update backup when no migrations are pending (#1711) (#1711)
- 858784c fixup! fix(server): skip the update backup when no migrations are pending (#1711) (#1711)

Fork-Domain: upstream-fixes
Fork-Tier: bugfix
Fork-Upstreamable: no
Co-authored-by: donjor <[email protected]>
rsi-software-agent Bot pushed a commit that referenced this pull request Nov 7, 2026
…1711)

## Problem

The service launcher copies the whole database before every update trial, after the old server stops.
On a 22 GB database that is about 91 s of downtime, even when the update adds no migrations.

## Change

1. Launcher runs the target's `__service-preflight`
2. Preflight reports pending migrations
3. Launcher backs up only if some are pending
4. Preflight failure still backs up
5. Launcher context stripped from every child

Step 5 closes the path that overwrote a live `statev2.sqlite` from a test run.

## Scope and approval

Refs #1707, settled in the #1705 profile.
The downtime goal needs the launcher from this build, so its VM proof follows the next nightly.

## Verification

| Check | Result |
| --- | --- |
| Launcher, preflight, context tests | 19/19 pass |
| `tsc --noEmit` on `apps/server` | exit 0 |
| `vp run fork:ci` | exit 0 |

Claude Opus 5.5 in Claude Code, hosted by T3 Code.

## Fork trailers

Squashes:

- 3d6a528 fix(server): skip the update backup when no migrations are pending (#1711) (#1711)
- 858784c fixup! fix(server): skip the update backup when no migrations are pending (#1711) (#1711)

Fork-Domain: upstream-fixes
Fork-Tier: bugfix
Fork-Upstreamable: no
Co-authored-by: donjor <[email protected]>
rsi-software-agent Bot pushed a commit that referenced this pull request Nov 8, 2026
…1711)

## Problem

The service launcher copies the whole database before every update trial, after the old server stops.
On a 22 GB database that is about 91 s of downtime, even when the update adds no migrations.

## Change

1. Launcher runs the target's `__service-preflight`
2. Preflight reports pending migrations
3. Launcher backs up only if some are pending
4. Preflight failure still backs up
5. Launcher context stripped from every child

Step 5 closes the path that overwrote a live `statev2.sqlite` from a test run.

## Scope and approval

Refs #1707, settled in the #1705 profile.
The downtime goal needs the launcher from this build, so its VM proof follows the next nightly.

## Verification

| Check | Result |
| --- | --- |
| Launcher, preflight, context tests | 19/19 pass |
| `tsc --noEmit` on `apps/server` | exit 0 |
| `vp run fork:ci` | exit 0 |

Claude Opus 5.5 in Claude Code, hosted by T3 Code.

## Fork trailers

Squashes:

- 3d6a528 fix(server): skip the update backup when no migrations are pending (#1711) (#1711)
- 858784c fixup! fix(server): skip the update backup when no migrations are pending (#1711) (#1711)

Fork-Domain: upstream-fixes
Fork-Tier: bugfix
Fork-Upstreamable: no
Co-authored-by: donjor <[email protected]>
rsi-software-agent Bot pushed a commit that referenced this pull request Nov 8, 2026
…1711)

## Problem

The service launcher copies the whole database before every update trial, after the old server stops.
On a 22 GB database that is about 91 s of downtime, even when the update adds no migrations.

## Change

1. Launcher runs the target's `__service-preflight`
2. Preflight reports pending migrations
3. Launcher backs up only if some are pending
4. Preflight failure still backs up
5. Launcher context stripped from every child

Step 5 closes the path that overwrote a live `statev2.sqlite` from a test run.

## Scope and approval

Refs #1707, settled in the #1705 profile.
The downtime goal needs the launcher from this build, so its VM proof follows the next nightly.

## Verification

| Check | Result |
| --- | --- |
| Launcher, preflight, context tests | 19/19 pass |
| `tsc --noEmit` on `apps/server` | exit 0 |
| `vp run fork:ci` | exit 0 |

Claude Opus 5.5 in Claude Code, hosted by T3 Code.

## Fork trailers

Squashes:

- 3d6a528 fix(server): skip the update backup when no migrations are pending (#1711) (#1711)
- 858784c fixup! fix(server): skip the update backup when no migrations are pending (#1711) (#1711)

Fork-Domain: upstream-fixes
Fork-Tier: bugfix
Fork-Upstreamable: no
Co-authored-by: donjor <[email protected]>
rsi-software-agent Bot pushed a commit that referenced this pull request Nov 9, 2026
…1711)

## Problem

The service launcher copies the whole database before every update trial, after the old server stops.
On a 22 GB database that is about 91 s of downtime, even when the update adds no migrations.

## Change

1. Launcher runs the target's `__service-preflight`
2. Preflight reports pending migrations
3. Launcher backs up only if some are pending
4. Preflight failure still backs up
5. Launcher context stripped from every child

Step 5 closes the path that overwrote a live `statev2.sqlite` from a test run.

## Scope and approval

Refs #1707, settled in the #1705 profile.
The downtime goal needs the launcher from this build, so its VM proof follows the next nightly.

## Verification

| Check | Result |
| --- | --- |
| Launcher, preflight, context tests | 19/19 pass |
| `tsc --noEmit` on `apps/server` | exit 0 |
| `vp run fork:ci` | exit 0 |

Claude Opus 5.5 in Claude Code, hosted by T3 Code.

## Fork trailers

Squashes:

- 3d6a528 fix(server): skip the update backup when no migrations are pending (#1711) (#1711)
- 858784c fixup! fix(server): skip the update backup when no migrations are pending (#1711) (#1711)

Fork-Domain: upstream-fixes
Fork-Tier: bugfix
Fork-Upstreamable: no
Co-authored-by: donjor <[email protected]>
donjor added a commit that referenced this pull request Nov 9, 2026
## Problem

A client **Update server** moves the service to the new runtime but leaves the `install.sh` `t3` symlink on the old one.
After the `.957` update, `t3 --version` on PATH still printed `.933`, without the `--mcp-*` device-approval flags.
Only `t3 update` repoints that link.

## Change

| Piece | Detail |
| --- | --- |
| Logic | new `launcherRepoint.fork.ts` |
| Reuse | upstream's `repointLauncher` and ownership rule |
| Load | lazy; a static import closes a module cycle |
| Candidates | `T3CODE_INSTALL_BIN_DIR`, PATH, `~/.local/bin` |
| Owned only | links into this home's `runtime/versions` |
| When | after the service launcher accepts the handoff |
| Failure | logged; the update still proceeds |
| Seam | two `fork-hook` lines in `selfUpdate.ts` |
| Scan | `selfUpdate.ts`, `cli/update.ts` in upstream-fixes |

The launcher waits for a handoff delay, then gives a 5s terminate grace, so the repoint finishes inside the uninterruptible handoff.
Windows has no boot service, so client updates never reach it there.

## Scope and approval

Refs #1639: Jordon asked for the client update to move the PATH `t3`.
The Task's live condition needs a nightly carrying this change, so it stays open after merge.

## Close conditions

### Behavior

- [x] **Owned link:** repointed to the target
- [x] **Foreign link:** untouched
- [x] **Plain executable copy:** untouched
- [x] **Failed preflight:** link unchanged
- [x] **No owned link:** update unchanged

### Fork shape

- [x] **Seam:** `fork-hook` lines in `selfUpdate.ts`
- [x] **Logic:** in the `.fork.ts` file
- [x] **Domain:** `upstream-fixes`
- [x] **Tier:** `bugfix`
- [x] **Upstreamable:** `yes`
- [x] **Gate:** `vp run fork:ci` passes

## Verification

| Check | Result |
| --- | --- |
| `vp test run` fork + `selfUpdate` tests | 16 passed |
| Hook line commented out | seam test fails |
| `vp run typecheck` (server) | exit 0 |
| `vp lint` changed files | exit 0 |
| `vp run fork:ci` | exit 0 |
| `vp run build:bundle` (server) | exit 0 |
| `ExternalMcpServer.auth.fork.test.ts` | passes; failed on the static import |

Not checked: a live client update; that waits for the next nightly.

Claude Opus 5.5 via Claude Code in T3 Code.

## Fork trailers

Squashes:

- eea26eee63e fix(server): a client server update repoints the install.sh t3 launcher (#1641) (#1641)
- 45fa9325b9d fix(server): skip the update backup when no migrations are pending (#1711) (#1711)
- a721ea1af61 fix(web): show server update progress through reconnect (#1713) (#1713)
- e0fa16f9431 fix(server): t3 update waits for a pending remote update (#1837) (#1837)
- d49f790900d fix(server): a stop during the migration backup no longer kills the update (#1873) (#1873)
- ac8a04f75eb fix(server): t3 pair leaves a running server's schema alone (#1958) (#1958)

Fork-Domain: upstream-fixes
Fork-Tier: bugfix
Fork-Upstreamable: no
Co-authored-by: donjor <[email protected]>
Co-authored-by: donjor <[email protected]>
rsi-software-agent Bot pushed a commit that referenced this pull request Nov 9, 2026
## Problem

A client **Update server** moves the service to the new runtime but leaves the `install.sh` `t3` symlink on the old one.
After the `.957` update, `t3 --version` on PATH still printed `.933`, without the `--mcp-*` device-approval flags.
Only `t3 update` repoints that link.

## Change

| Piece | Detail |
| --- | --- |
| Logic | new `launcherRepoint.fork.ts` |
| Reuse | upstream's `repointLauncher` and ownership rule |
| Load | lazy; a static import closes a module cycle |
| Candidates | `T3CODE_INSTALL_BIN_DIR`, PATH, `~/.local/bin` |
| Owned only | links into this home's `runtime/versions` |
| When | after the service launcher accepts the handoff |
| Failure | logged; the update still proceeds |
| Seam | two `fork-hook` lines in `selfUpdate.ts` |
| Scan | `selfUpdate.ts`, `cli/update.ts` in upstream-fixes |

The launcher waits for a handoff delay, then gives a 5s terminate grace, so the repoint finishes inside the uninterruptible handoff.
Windows has no boot service, so client updates never reach it there.

## Scope and approval

Refs #1639: Jordon asked for the client update to move the PATH `t3`.
The Task's live condition needs a nightly carrying this change, so it stays open after merge.

## Close conditions

### Behavior

- [x] **Owned link:** repointed to the target
- [x] **Foreign link:** untouched
- [x] **Plain executable copy:** untouched
- [x] **Failed preflight:** link unchanged
- [x] **No owned link:** update unchanged

### Fork shape

- [x] **Seam:** `fork-hook` lines in `selfUpdate.ts`
- [x] **Logic:** in the `.fork.ts` file
- [x] **Domain:** `upstream-fixes`
- [x] **Tier:** `bugfix`
- [x] **Upstreamable:** `yes`
- [x] **Gate:** `vp run fork:ci` passes

## Verification

| Check | Result |
| --- | --- |
| `vp test run` fork + `selfUpdate` tests | 16 passed |
| Hook line commented out | seam test fails |
| `vp run typecheck` (server) | exit 0 |
| `vp lint` changed files | exit 0 |
| `vp run fork:ci` | exit 0 |
| `vp run build:bundle` (server) | exit 0 |
| `ExternalMcpServer.auth.fork.test.ts` | passes; failed on the static import |

Not checked: a live client update; that waits for the next nightly.

Claude Opus 5.5 via Claude Code in T3 Code.

## Fork trailers

Squashes:

- eea26eee63e fix(server): a client server update repoints the install.sh t3 launcher (#1641) (#1641)
- 45fa9325b9d fix(server): skip the update backup when no migrations are pending (#1711) (#1711)
- a721ea1af61 fix(web): show server update progress through reconnect (#1713) (#1713)
- e0fa16f9431 fix(server): t3 update waits for a pending remote update (#1837) (#1837)
- d49f790900d fix(server): a stop during the migration backup no longer kills the update (#1873) (#1873)
- ac8a04f75eb fix(server): t3 pair leaves a running server's schema alone (#1958) (#1958)

Fork-Domain: upstream-fixes
Fork-Tier: bugfix
Fork-Upstreamable: no
Co-authored-by: donjor <[email protected]>
Co-authored-by: donjor <[email protected]>
rsi-software-agent Bot pushed a commit that referenced this pull request Nov 9, 2026
## Problem

A client **Update server** moves the service to the new runtime but leaves the `install.sh` `t3` symlink on the old one.
After the `.957` update, `t3 --version` on PATH still printed `.933`, without the `--mcp-*` device-approval flags.
Only `t3 update` repoints that link.

## Change

| Piece | Detail |
| --- | --- |
| Logic | new `launcherRepoint.fork.ts` |
| Reuse | upstream's `repointLauncher` and ownership rule |
| Load | lazy; a static import closes a module cycle |
| Candidates | `T3CODE_INSTALL_BIN_DIR`, PATH, `~/.local/bin` |
| Owned only | links into this home's `runtime/versions` |
| When | after the service launcher accepts the handoff |
| Failure | logged; the update still proceeds |
| Seam | two `fork-hook` lines in `selfUpdate.ts` |
| Scan | `selfUpdate.ts`, `cli/update.ts` in upstream-fixes |

The launcher waits for a handoff delay, then gives a 5s terminate grace, so the repoint finishes inside the uninterruptible handoff.
Windows has no boot service, so client updates never reach it there.

## Scope and approval

Refs #1639: Jordon asked for the client update to move the PATH `t3`.
The Task's live condition needs a nightly carrying this change, so it stays open after merge.

## Close conditions

### Behavior

- [x] **Owned link:** repointed to the target
- [x] **Foreign link:** untouched
- [x] **Plain executable copy:** untouched
- [x] **Failed preflight:** link unchanged
- [x] **No owned link:** update unchanged

### Fork shape

- [x] **Seam:** `fork-hook` lines in `selfUpdate.ts`
- [x] **Logic:** in the `.fork.ts` file
- [x] **Domain:** `upstream-fixes`
- [x] **Tier:** `bugfix`
- [x] **Upstreamable:** `yes`
- [x] **Gate:** `vp run fork:ci` passes

## Verification

| Check | Result |
| --- | --- |
| `vp test run` fork + `selfUpdate` tests | 16 passed |
| Hook line commented out | seam test fails |
| `vp run typecheck` (server) | exit 0 |
| `vp lint` changed files | exit 0 |
| `vp run fork:ci` | exit 0 |
| `vp run build:bundle` (server) | exit 0 |
| `ExternalMcpServer.auth.fork.test.ts` | passes; failed on the static import |

Not checked: a live client update; that waits for the next nightly.

Claude Opus 5.5 via Claude Code in T3 Code.

## Fork trailers

Squashes:

- eea26eee63e fix(server): a client server update repoints the install.sh t3 launcher (#1641) (#1641)
- 45fa9325b9d fix(server): skip the update backup when no migrations are pending (#1711) (#1711)
- a721ea1af61 fix(web): show server update progress through reconnect (#1713) (#1713)
- e0fa16f9431 fix(server): t3 update waits for a pending remote update (#1837) (#1837)
- d49f790900d fix(server): a stop during the migration backup no longer kills the update (#1873) (#1873)
- ac8a04f75eb fix(server): t3 pair leaves a running server's schema alone (#1958) (#1958)

Fork-Domain: upstream-fixes
Fork-Tier: bugfix
Fork-Upstreamable: no
Co-authored-by: donjor <[email protected]>
Co-authored-by: donjor <[email protected]>
rsi-software-agent Bot pushed a commit that referenced this pull request Nov 9, 2026
## Problem

A client **Update server** moves the service to the new runtime but leaves the `install.sh` `t3` symlink on the old one.
After the `.957` update, `t3 --version` on PATH still printed `.933`, without the `--mcp-*` device-approval flags.
Only `t3 update` repoints that link.

## Change

| Piece | Detail |
| --- | --- |
| Logic | new `launcherRepoint.fork.ts` |
| Reuse | upstream's `repointLauncher` and ownership rule |
| Load | lazy; a static import closes a module cycle |
| Candidates | `T3CODE_INSTALL_BIN_DIR`, PATH, `~/.local/bin` |
| Owned only | links into this home's `runtime/versions` |
| When | after the service launcher accepts the handoff |
| Failure | logged; the update still proceeds |
| Seam | two `fork-hook` lines in `selfUpdate.ts` |
| Scan | `selfUpdate.ts`, `cli/update.ts` in upstream-fixes |

The launcher waits for a handoff delay, then gives a 5s terminate grace, so the repoint finishes inside the uninterruptible handoff.
Windows has no boot service, so client updates never reach it there.

## Scope and approval

Refs #1639: Jordon asked for the client update to move the PATH `t3`.
The Task's live condition needs a nightly carrying this change, so it stays open after merge.

## Close conditions

### Behavior

- [x] **Owned link:** repointed to the target
- [x] **Foreign link:** untouched
- [x] **Plain executable copy:** untouched
- [x] **Failed preflight:** link unchanged
- [x] **No owned link:** update unchanged

### Fork shape

- [x] **Seam:** `fork-hook` lines in `selfUpdate.ts`
- [x] **Logic:** in the `.fork.ts` file
- [x] **Domain:** `upstream-fixes`
- [x] **Tier:** `bugfix`
- [x] **Upstreamable:** `yes`
- [x] **Gate:** `vp run fork:ci` passes

## Verification

| Check | Result |
| --- | --- |
| `vp test run` fork + `selfUpdate` tests | 16 passed |
| Hook line commented out | seam test fails |
| `vp run typecheck` (server) | exit 0 |
| `vp lint` changed files | exit 0 |
| `vp run fork:ci` | exit 0 |
| `vp run build:bundle` (server) | exit 0 |
| `ExternalMcpServer.auth.fork.test.ts` | passes; failed on the static import |

Not checked: a live client update; that waits for the next nightly.

Claude Opus 5.5 via Claude Code in T3 Code.

## Fork trailers

Squashes:

- eea26eee63e fix(server): a client server update repoints the install.sh t3 launcher (#1641) (#1641)
- 45fa9325b9d fix(server): skip the update backup when no migrations are pending (#1711) (#1711)
- a721ea1af61 fix(web): show server update progress through reconnect (#1713) (#1713)
- e0fa16f9431 fix(server): t3 update waits for a pending remote update (#1837) (#1837)
- d49f790900d fix(server): a stop during the migration backup no longer kills the update (#1873) (#1873)
- ac8a04f75eb fix(server): t3 pair leaves a running server's schema alone (#1958) (#1958)

Fork-Domain: upstream-fixes
Fork-Tier: bugfix
Fork-Upstreamable: no
Co-authored-by: donjor <[email protected]>
Co-authored-by: donjor <[email protected]>
rsi-software-agent Bot pushed a commit that referenced this pull request Nov 9, 2026
## Problem

A client **Update server** moves the service to the new runtime but leaves the `install.sh` `t3` symlink on the old one.
After the `.957` update, `t3 --version` on PATH still printed `.933`, without the `--mcp-*` device-approval flags.
Only `t3 update` repoints that link.

## Change

| Piece | Detail |
| --- | --- |
| Logic | new `launcherRepoint.fork.ts` |
| Reuse | upstream's `repointLauncher` and ownership rule |
| Load | lazy; a static import closes a module cycle |
| Candidates | `T3CODE_INSTALL_BIN_DIR`, PATH, `~/.local/bin` |
| Owned only | links into this home's `runtime/versions` |
| When | after the service launcher accepts the handoff |
| Failure | logged; the update still proceeds |
| Seam | two `fork-hook` lines in `selfUpdate.ts` |
| Scan | `selfUpdate.ts`, `cli/update.ts` in upstream-fixes |

The launcher waits for a handoff delay, then gives a 5s terminate grace, so the repoint finishes inside the uninterruptible handoff.
Windows has no boot service, so client updates never reach it there.

## Scope and approval

Refs #1639: Jordon asked for the client update to move the PATH `t3`.
The Task's live condition needs a nightly carrying this change, so it stays open after merge.

## Close conditions

### Behavior

- [x] **Owned link:** repointed to the target
- [x] **Foreign link:** untouched
- [x] **Plain executable copy:** untouched
- [x] **Failed preflight:** link unchanged
- [x] **No owned link:** update unchanged

### Fork shape

- [x] **Seam:** `fork-hook` lines in `selfUpdate.ts`
- [x] **Logic:** in the `.fork.ts` file
- [x] **Domain:** `upstream-fixes`
- [x] **Tier:** `bugfix`
- [x] **Upstreamable:** `yes`
- [x] **Gate:** `vp run fork:ci` passes

## Verification

| Check | Result |
| --- | --- |
| `vp test run` fork + `selfUpdate` tests | 16 passed |
| Hook line commented out | seam test fails |
| `vp run typecheck` (server) | exit 0 |
| `vp lint` changed files | exit 0 |
| `vp run fork:ci` | exit 0 |
| `vp run build:bundle` (server) | exit 0 |
| `ExternalMcpServer.auth.fork.test.ts` | passes; failed on the static import |

Not checked: a live client update; that waits for the next nightly.

Claude Opus 5.5 via Claude Code in T3 Code.

## Fork trailers

Squashes:

- eea26eee63e fix(server): a client server update repoints the install.sh t3 launcher (#1641) (#1641)
- 45fa9325b9d fix(server): skip the update backup when no migrations are pending (#1711) (#1711)
- a721ea1af61 fix(web): show server update progress through reconnect (#1713) (#1713)
- e0fa16f9431 fix(server): t3 update waits for a pending remote update (#1837) (#1837)
- d49f790900d fix(server): a stop during the migration backup no longer kills the update (#1873) (#1873)
- ac8a04f75eb fix(server): t3 pair leaves a running server's schema alone (#1958) (#1958)

Fork-Domain: upstream-fixes
Fork-Tier: bugfix
Fork-Upstreamable: no
Co-authored-by: donjor <[email protected]>
Co-authored-by: donjor <[email protected]>
rsi-software-agent Bot pushed a commit that referenced this pull request Nov 10, 2026
## Problem

A client **Update server** moves the service to the new runtime but leaves the `install.sh` `t3` symlink on the old one.
After the `.957` update, `t3 --version` on PATH still printed `.933`, without the `--mcp-*` device-approval flags.
Only `t3 update` repoints that link.

## Change

| Piece | Detail |
| --- | --- |
| Logic | new `launcherRepoint.fork.ts` |
| Reuse | upstream's `repointLauncher` and ownership rule |
| Load | lazy; a static import closes a module cycle |
| Candidates | `T3CODE_INSTALL_BIN_DIR`, PATH, `~/.local/bin` |
| Owned only | links into this home's `runtime/versions` |
| When | after the service launcher accepts the handoff |
| Failure | logged; the update still proceeds |
| Seam | two `fork-hook` lines in `selfUpdate.ts` |
| Scan | `selfUpdate.ts`, `cli/update.ts` in upstream-fixes |

The launcher waits for a handoff delay, then gives a 5s terminate grace, so the repoint finishes inside the uninterruptible handoff.
Windows has no boot service, so client updates never reach it there.

## Scope and approval

Refs #1639: Jordon asked for the client update to move the PATH `t3`.
The Task's live condition needs a nightly carrying this change, so it stays open after merge.

## Close conditions

### Behavior

- [x] **Owned link:** repointed to the target
- [x] **Foreign link:** untouched
- [x] **Plain executable copy:** untouched
- [x] **Failed preflight:** link unchanged
- [x] **No owned link:** update unchanged

### Fork shape

- [x] **Seam:** `fork-hook` lines in `selfUpdate.ts`
- [x] **Logic:** in the `.fork.ts` file
- [x] **Domain:** `upstream-fixes`
- [x] **Tier:** `bugfix`
- [x] **Upstreamable:** `yes`
- [x] **Gate:** `vp run fork:ci` passes

## Verification

| Check | Result |
| --- | --- |
| `vp test run` fork + `selfUpdate` tests | 16 passed |
| Hook line commented out | seam test fails |
| `vp run typecheck` (server) | exit 0 |
| `vp lint` changed files | exit 0 |
| `vp run fork:ci` | exit 0 |
| `vp run build:bundle` (server) | exit 0 |
| `ExternalMcpServer.auth.fork.test.ts` | passes; failed on the static import |

Not checked: a live client update; that waits for the next nightly.

Claude Opus 5.5 via Claude Code in T3 Code.

## Fork trailers

Squashes:

- eea26eee63e fix(server): a client server update repoints the install.sh t3 launcher (#1641) (#1641)
- 45fa9325b9d fix(server): skip the update backup when no migrations are pending (#1711) (#1711)
- a721ea1af61 fix(web): show server update progress through reconnect (#1713) (#1713)
- e0fa16f9431 fix(server): t3 update waits for a pending remote update (#1837) (#1837)
- d49f790900d fix(server): a stop during the migration backup no longer kills the update (#1873) (#1873)
- ac8a04f75eb fix(server): t3 pair leaves a running server's schema alone (#1958) (#1958)

Fork-Domain: upstream-fixes
Fork-Tier: bugfix
Fork-Upstreamable: no
Co-authored-by: donjor <[email protected]>
Co-authored-by: donjor <[email protected]>
rsi-software-agent Bot pushed a commit that referenced this pull request Nov 10, 2026
## Problem

A client **Update server** moves the service to the new runtime but leaves the `install.sh` `t3` symlink on the old one.
After the `.957` update, `t3 --version` on PATH still printed `.933`, without the `--mcp-*` device-approval flags.
Only `t3 update` repoints that link.

## Change

| Piece | Detail |
| --- | --- |
| Logic | new `launcherRepoint.fork.ts` |
| Reuse | upstream's `repointLauncher` and ownership rule |
| Load | lazy; a static import closes a module cycle |
| Candidates | `T3CODE_INSTALL_BIN_DIR`, PATH, `~/.local/bin` |
| Owned only | links into this home's `runtime/versions` |
| When | after the service launcher accepts the handoff |
| Failure | logged; the update still proceeds |
| Seam | two `fork-hook` lines in `selfUpdate.ts` |
| Scan | `selfUpdate.ts`, `cli/update.ts` in upstream-fixes |

The launcher waits for a handoff delay, then gives a 5s terminate grace, so the repoint finishes inside the uninterruptible handoff.
Windows has no boot service, so client updates never reach it there.

## Scope and approval

Refs #1639: Jordon asked for the client update to move the PATH `t3`.
The Task's live condition needs a nightly carrying this change, so it stays open after merge.

## Close conditions

### Behavior

- [x] **Owned link:** repointed to the target
- [x] **Foreign link:** untouched
- [x] **Plain executable copy:** untouched
- [x] **Failed preflight:** link unchanged
- [x] **No owned link:** update unchanged

### Fork shape

- [x] **Seam:** `fork-hook` lines in `selfUpdate.ts`
- [x] **Logic:** in the `.fork.ts` file
- [x] **Domain:** `upstream-fixes`
- [x] **Tier:** `bugfix`
- [x] **Upstreamable:** `yes`
- [x] **Gate:** `vp run fork:ci` passes

## Verification

| Check | Result |
| --- | --- |
| `vp test run` fork + `selfUpdate` tests | 16 passed |
| Hook line commented out | seam test fails |
| `vp run typecheck` (server) | exit 0 |
| `vp lint` changed files | exit 0 |
| `vp run fork:ci` | exit 0 |
| `vp run build:bundle` (server) | exit 0 |
| `ExternalMcpServer.auth.fork.test.ts` | passes; failed on the static import |

Not checked: a live client update; that waits for the next nightly.

Claude Opus 5.5 via Claude Code in T3 Code.

## Fork trailers

Squashes:

- eea26eee63e fix(server): a client server update repoints the install.sh t3 launcher (#1641) (#1641)
- 45fa9325b9d fix(server): skip the update backup when no migrations are pending (#1711) (#1711)
- a721ea1af61 fix(web): show server update progress through reconnect (#1713) (#1713)
- e0fa16f9431 fix(server): t3 update waits for a pending remote update (#1837) (#1837)
- d49f790900d fix(server): a stop during the migration backup no longer kills the update (#1873) (#1873)
- ac8a04f75eb fix(server): t3 pair leaves a running server's schema alone (#1958) (#1958)

Fork-Domain: upstream-fixes
Fork-Tier: bugfix
Fork-Upstreamable: no
Co-authored-by: donjor <[email protected]>
Co-authored-by: donjor <[email protected]>
rsi-software-agent Bot pushed a commit that referenced this pull request Nov 10, 2026
## Problem

A client **Update server** moves the service to the new runtime but leaves the `install.sh` `t3` symlink on the old one.
After the `.957` update, `t3 --version` on PATH still printed `.933`, without the `--mcp-*` device-approval flags.
Only `t3 update` repoints that link.

## Change

| Piece | Detail |
| --- | --- |
| Logic | new `launcherRepoint.fork.ts` |
| Reuse | upstream's `repointLauncher` and ownership rule |
| Load | lazy; a static import closes a module cycle |
| Candidates | `T3CODE_INSTALL_BIN_DIR`, PATH, `~/.local/bin` |
| Owned only | links into this home's `runtime/versions` |
| When | after the service launcher accepts the handoff |
| Failure | logged; the update still proceeds |
| Seam | two `fork-hook` lines in `selfUpdate.ts` |
| Scan | `selfUpdate.ts`, `cli/update.ts` in upstream-fixes |

The launcher waits for a handoff delay, then gives a 5s terminate grace, so the repoint finishes inside the uninterruptible handoff.
Windows has no boot service, so client updates never reach it there.

## Scope and approval

Refs #1639: Jordon asked for the client update to move the PATH `t3`.
The Task's live condition needs a nightly carrying this change, so it stays open after merge.

## Close conditions

### Behavior

- [x] **Owned link:** repointed to the target
- [x] **Foreign link:** untouched
- [x] **Plain executable copy:** untouched
- [x] **Failed preflight:** link unchanged
- [x] **No owned link:** update unchanged

### Fork shape

- [x] **Seam:** `fork-hook` lines in `selfUpdate.ts`
- [x] **Logic:** in the `.fork.ts` file
- [x] **Domain:** `upstream-fixes`
- [x] **Tier:** `bugfix`
- [x] **Upstreamable:** `yes`
- [x] **Gate:** `vp run fork:ci` passes

## Verification

| Check | Result |
| --- | --- |
| `vp test run` fork + `selfUpdate` tests | 16 passed |
| Hook line commented out | seam test fails |
| `vp run typecheck` (server) | exit 0 |
| `vp lint` changed files | exit 0 |
| `vp run fork:ci` | exit 0 |
| `vp run build:bundle` (server) | exit 0 |
| `ExternalMcpServer.auth.fork.test.ts` | passes; failed on the static import |

Not checked: a live client update; that waits for the next nightly.

Claude Opus 5.5 via Claude Code in T3 Code.

## Fork trailers

Squashes:

- eea26eee63e fix(server): a client server update repoints the install.sh t3 launcher (#1641) (#1641)
- 45fa9325b9d fix(server): skip the update backup when no migrations are pending (#1711) (#1711)
- a721ea1af61 fix(web): show server update progress through reconnect (#1713) (#1713)
- e0fa16f9431 fix(server): t3 update waits for a pending remote update (#1837) (#1837)
- d49f790900d fix(server): a stop during the migration backup no longer kills the update (#1873) (#1873)
- ac8a04f75eb fix(server): t3 pair leaves a running server's schema alone (#1958) (#1958)

Fork-Domain: upstream-fixes
Fork-Tier: bugfix
Fork-Upstreamable: no
Co-authored-by: donjor <[email protected]>
Co-authored-by: donjor <[email protected]>
rsi-software-agent Bot pushed a commit that referenced this pull request Nov 10, 2026
## Problem

A client **Update server** moves the service to the new runtime but leaves the `install.sh` `t3` symlink on the old one.
After the `.957` update, `t3 --version` on PATH still printed `.933`, without the `--mcp-*` device-approval flags.
Only `t3 update` repoints that link.

## Change

| Piece | Detail |
| --- | --- |
| Logic | new `launcherRepoint.fork.ts` |
| Reuse | upstream's `repointLauncher` and ownership rule |
| Load | lazy; a static import closes a module cycle |
| Candidates | `T3CODE_INSTALL_BIN_DIR`, PATH, `~/.local/bin` |
| Owned only | links into this home's `runtime/versions` |
| When | after the service launcher accepts the handoff |
| Failure | logged; the update still proceeds |
| Seam | two `fork-hook` lines in `selfUpdate.ts` |
| Scan | `selfUpdate.ts`, `cli/update.ts` in upstream-fixes |

The launcher waits for a handoff delay, then gives a 5s terminate grace, so the repoint finishes inside the uninterruptible handoff.
Windows has no boot service, so client updates never reach it there.

## Scope and approval

Refs #1639: Jordon asked for the client update to move the PATH `t3`.
The Task's live condition needs a nightly carrying this change, so it stays open after merge.

## Close conditions

### Behavior

- [x] **Owned link:** repointed to the target
- [x] **Foreign link:** untouched
- [x] **Plain executable copy:** untouched
- [x] **Failed preflight:** link unchanged
- [x] **No owned link:** update unchanged

### Fork shape

- [x] **Seam:** `fork-hook` lines in `selfUpdate.ts`
- [x] **Logic:** in the `.fork.ts` file
- [x] **Domain:** `upstream-fixes`
- [x] **Tier:** `bugfix`
- [x] **Upstreamable:** `yes`
- [x] **Gate:** `vp run fork:ci` passes

## Verification

| Check | Result |
| --- | --- |
| `vp test run` fork + `selfUpdate` tests | 16 passed |
| Hook line commented out | seam test fails |
| `vp run typecheck` (server) | exit 0 |
| `vp lint` changed files | exit 0 |
| `vp run fork:ci` | exit 0 |
| `vp run build:bundle` (server) | exit 0 |
| `ExternalMcpServer.auth.fork.test.ts` | passes; failed on the static import |

Not checked: a live client update; that waits for the next nightly.

Claude Opus 5.5 via Claude Code in T3 Code.

## Fork trailers

Squashes:

- eea26eee63e fix(server): a client server update repoints the install.sh t3 launcher (#1641) (#1641)
- 45fa9325b9d fix(server): skip the update backup when no migrations are pending (#1711) (#1711)
- a721ea1af61 fix(web): show server update progress through reconnect (#1713) (#1713)
- e0fa16f9431 fix(server): t3 update waits for a pending remote update (#1837) (#1837)
- d49f790900d fix(server): a stop during the migration backup no longer kills the update (#1873) (#1873)
- ac8a04f75eb fix(server): t3 pair leaves a running server's schema alone (#1958) (#1958)

Fork-Domain: upstream-fixes
Fork-Tier: bugfix
Fork-Upstreamable: no
Co-authored-by: donjor <[email protected]>
Co-authored-by: donjor <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant