From b540566fd640496d65f92b09880a9046b8c19a6a Mon Sep 17 00:00:00 2001 From: Wolfgang Schoenberger <221313372+wolfiesch@users.noreply.github.com> Date: Sun, 19 Jul 2026 19:34:04 -0700 Subject: [PATCH] release: ship T4 Code 0.1.30 --- .github/ISSUE_TEMPLATE/bug_report.yml | 2 +- README.md | 25 ++++++++++--------- SECURITY.md | 2 +- apps/desktop/package.json | 2 +- apps/desktop/src/target-manager.ts | 2 +- apps/desktop/test/bundled-runtime.test.ts | 6 ++--- apps/desktop/test/doctor.test.ts | 4 +-- apps/mobile/capacitor.config.json | 2 +- apps/mobile/package.json | 2 +- apps/site/package.json | 2 +- apps/site/src/release.ts | 18 ++++++------- apps/site/test/release.test.ts | 24 +++++++++--------- apps/web/package.json | 2 +- apps/web/src/platform/browser-shell-port.ts | 2 +- compat/omp-app-matrix.json | 24 ++++++++++-------- docs/CURRENT_RELEASE_NOTES.md | 8 +++--- e2e/site-mobile-docs.spec.ts | 2 +- package.json | 2 +- packages/client/package.json | 2 +- packages/client/src/omp-client-frames.ts | 2 +- packages/fixture-server/package.json | 2 +- packages/protocol/package.json | 2 +- .../test/fixtures/platform-boundaries.ts | 4 +-- packages/remote/package.json | 2 +- packages/service-manager/package.json | 2 +- packages/ui/package.json | 2 +- scripts/check-release-consistency.test.mjs | 20 +++++++-------- 27 files changed, 87 insertions(+), 82 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml index 1d257d6..708bf9d 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -10,7 +10,7 @@ body: id: version attributes: label: T4 Code version - placeholder: "0.1.29" + placeholder: "0.1.30" validations: required: true - type: dropdown diff --git a/README.md b/README.md index d8eaee4..f68d5e1 100644 --- a/README.md +++ b/README.md @@ -4,13 +4,13 @@ T4 Code is a free, open-source (MIT) desktop app for [Oh My Pi](https://github.c ![T4 Code main window](docs/assets/t4-code-main.png) -[**Download v0.1.29**](https://github.com/LycaonLLC/t4-code/releases/tag/v0.1.29) · [**Docs**](https://t4code.net/docs) · [**Get the source**](#build-from-source) +[**Download v0.1.30**](https://github.com/LycaonLLC/t4-code/releases/tag/v0.1.30) · [**Docs**](https://t4code.net/docs) · [**Get the source**](#build-from-source) ## Requirements -T4 Code needs an OMP build with desktop appserver support. For v0.1.29, use the public integration build below. +T4 Code needs an OMP build with desktop appserver support. For v0.1.30, use the public integration build below. -T4 Code v0.1.29 was verified with OMP 17.0.5 built from [`04229b1f`](https://github.com/lyc-aon/oh-my-pi/commit/04229b1f46547ac7c0617e55a993496ec9725f46), tagged [`t4code-17.0.5-appserver-7`](https://github.com/lyc-aon/oh-my-pi/tree/t4code-17.0.5-appserver-7). That public integration is based on the official upstream [`v17.0.5`](https://github.com/can1357/oh-my-pi/tree/v17.0.5) tag at [`9fd6e971`](https://github.com/can1357/oh-my-pi/commit/9fd6e97113f5ed3a847e66d346970efdf8afcad9). It adds a privacy-safe command that lets the desktop app reveal a known local project folder without exposing arbitrary paths. It also includes fast lazy session indexing, cross-session attention and transcript search, the negotiated browser-preview command surface, redacted Codex transport diagnostics, the versioned Agent View lifecycle contract, session-owned cancellation, lock-aware session observation, complete transcript reconciliation, the cooperative `/continue-in-t4` handoff, and deterministic session ordering. Fork CI verifies the exact upstream base, ancestry, release gates, and published binaries. The official upstream v17.0.5 tag has no `appserver` command, so it cannot host T4 Code. The verified runtime is a normal build from the public `lyc-aon/oh-my-pi` source. T4 Code vendors `@oh-my-pi/app-wire` 0.6.2 from integration commit [`04229b1f`](https://github.com/lyc-aon/oh-my-pi/commit/04229b1f46547ac7c0617e55a993496ec9725f46), source tree `8400a3af618e8af11cccf6b20aadcf3a22baf9a1`. +T4 Code v0.1.30 was verified with OMP 17.0.5 built from [`09835b92`](https://github.com/lyc-aon/oh-my-pi/commit/09835b929cd028e7e3f800b3e4203e3d1f37931c), tagged [`t4code-17.0.5-appserver-8`](https://github.com/lyc-aon/oh-my-pi/tree/t4code-17.0.5-appserver-8). That public integration is based on the official upstream [`v17.0.5`](https://github.com/can1357/oh-my-pi/tree/v17.0.5) tag at [`9fd6e971`](https://github.com/can1357/oh-my-pi/commit/9fd6e97113f5ed3a847e66d346970efdf8afcad9). It recovers safely from a crashed backend whose old process ID still appears alive, while preserving a responsive owner. It also includes privacy-safe project reveal, fast lazy session indexing, cross-session attention and transcript search, the negotiated browser-preview command surface, redacted Codex transport diagnostics, the versioned Agent View lifecycle contract, session-owned cancellation, lock-aware session observation, complete transcript reconciliation, the cooperative `/continue-in-t4` handoff, and deterministic session ordering. Fork CI verifies the exact upstream base, ancestry, release gates, and published binaries. The official upstream v17.0.5 tag has no `appserver` command, so it cannot host T4 Code. The verified runtime is a normal build from the public `lyc-aon/oh-my-pi` source. T4 Code vendors `@oh-my-pi/app-wire` 0.6.2 from integration commit [`04229b1f`](https://github.com/lyc-aon/oh-my-pi/commit/04229b1f46547ac7c0617e55a993496ec9725f46), source tree `8400a3af618e8af11cccf6b20aadcf3a22baf9a1`. The current source tree uses the same published `@oh-my-pi/app-wire` 0.6.2 contract. It supplies privacy-safe local project reveal, bounded cross-session transcript search, historical context, and the browser-preview wire contract. @@ -20,14 +20,15 @@ The current source tree uses the same published `@oh-my-pi/app-wire` 0.6.2 contr | Linux | x86_64 | `.deb`, AppImage | | macOS | Apple Silicon (arm64) | `.dmg`, `.zip` (**signed and notarized**) | -No Windows build and no Intel Mac build in v0.1.29. The iOS TestFlight build is coming soon. +No Windows build and no Intel Mac build in v0.1.30. The iOS TestFlight build is coming soon. -## What changed in v0.1.29 +## What changed in v0.1.30 - The session rail now matches the Codex desktop organization model: search, activity filters, sort controls, collapsible projects, flat and grouped views, and persistent preferences. - Project menus can create sessions, open folders in the system file manager, collapse a group, or hide it from the rail. Hidden projects remain recoverable through the filter menu. - The whole workspace received a visual polish pass, with denser information hierarchy, clearer transcript rows, and empty panes that keep their header and close control visible. - macOS upgrades retry temporary service-stop failures instead of leaving the bundled backend half-updated. +- A crashed backend can no longer trap launchd in a restart loop when its stale process ID still appears alive. - OMP app-wire 0.6.2 adds the narrow host command used to reveal only a project path already known to the session catalog. ![An OMP TUI session followed in T4 Code: the transcript fills in read-only under an "Active in another app" banner, /continue-in-t4 runs in the terminal, T4 takes over, and the composer accepts input again.](docs/assets/t4-code-tui-handoff.gif) @@ -46,7 +47,7 @@ No Windows build and no Intel Mac build in v0.1.29. The iOS TestFlight build is ### Android 1. On the Android phone, sign in to Tailscale with an account that can reach the T4 Code host. -2. Download [`T4-Code-0.1.29-android.apk`](https://github.com/LycaonLLC/t4-code/releases/download/v0.1.29/T4-Code-0.1.29-android.apk). +2. Download [`T4-Code-0.1.30-android.apk`](https://github.com/LycaonLLC/t4-code/releases/download/v0.1.30/T4-Code-0.1.30-android.apk). 3. If Android asks, allow your browser or file manager to install unknown apps, then install the APK. 4. Open T4 Code and enter the host's HTTPS Tailscale address, including its port. The app saves the address; you can add more hosts later and switch between them. @@ -55,8 +56,8 @@ The APK does not contain an appserver or expose one to the public internet. It c ### Linux (Debian/Ubuntu) ```sh -wget https://github.com/LycaonLLC/t4-code/releases/download/v0.1.29/T4-Code-0.1.29-linux-amd64.deb -sudo apt install ./T4-Code-0.1.29-linux-amd64.deb +wget https://github.com/LycaonLLC/t4-code/releases/download/v0.1.30/T4-Code-0.1.30-linux-amd64.deb +sudo apt install ./T4-Code-0.1.30-linux-amd64.deb ``` Use `apt install` rather than `dpkg -i` so system dependencies resolve automatically. @@ -64,14 +65,14 @@ Use `apt install` rather than `dpkg -i` so system dependencies resolve automatic ### Linux (AppImage) ```sh -wget https://github.com/LycaonLLC/t4-code/releases/download/v0.1.29/T4-Code-0.1.29-linux-x86_64.AppImage -chmod +x T4-Code-0.1.29-linux-x86_64.AppImage -./T4-Code-0.1.29-linux-x86_64.AppImage +wget https://github.com/LycaonLLC/t4-code/releases/download/v0.1.30/T4-Code-0.1.30-linux-x86_64.AppImage +chmod +x T4-Code-0.1.30-linux-x86_64.AppImage +./T4-Code-0.1.30-linux-x86_64.AppImage ``` ### macOS (Apple Silicon) -1. Download [`T4-Code-0.1.29-mac-arm64.dmg`](https://github.com/LycaonLLC/t4-code/releases/download/v0.1.29/T4-Code-0.1.29-mac-arm64.dmg) (or [`T4-Code-0.1.29-mac-arm64.zip`](https://github.com/LycaonLLC/t4-code/releases/download/v0.1.29/T4-Code-0.1.29-mac-arm64.zip)). +1. Download [`T4-Code-0.1.30-mac-arm64.dmg`](https://github.com/LycaonLLC/t4-code/releases/download/v0.1.30/T4-Code-0.1.30-mac-arm64.dmg) (or [`T4-Code-0.1.30-mac-arm64.zip`](https://github.com/LycaonLLC/t4-code/releases/download/v0.1.30/T4-Code-0.1.30-mac-arm64.zip)). 2. Drag `T4 Code.app` into `/Applications`. 3. Open T4 Code normally. The release workflow verifies the pinned publisher, hardened runtime, secure timestamp, Apple notarization, stapled ticket, and Gatekeeper acceptance before publication. diff --git a/SECURITY.md b/SECURITY.md index 1c2bfdf..09378b6 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -26,5 +26,5 @@ We read every report and will reply to tell you what happens next. This is a sma - T4 Code is a desktop client. The OMP runtime is a separate project; runtime vulnerabilities belong at . - Pairing credentials are encrypted with the OS keychain via Electron `safeStorage`. Reports about credential handling, the pairing flow, or the `t4-code://` deep-link handler are especially welcome. -- The macOS v0.1.29 build is signed with Apple Developer ID and notarized by Apple. Reports of certificate, Team ID, hardened-runtime, timestamp, Gatekeeper, or stapled-ticket drift are security-relevant. +- The macOS v0.1.30 build is signed with Apple Developer ID and notarized by Apple. Reports of certificate, Team ID, hardened-runtime, timestamp, Gatekeeper, or stapled-ticket drift are security-relevant. - Starting with v0.1.24, the release workflow requires the pinned Developer ID identity, hardened runtime, Apple notarization, a stapled ticket, and a successful Gatekeeper assessment before publishing macOS artifacts. diff --git a/apps/desktop/package.json b/apps/desktop/package.json index 433b7f4..d9a4e9c 100644 --- a/apps/desktop/package.json +++ b/apps/desktop/package.json @@ -1,6 +1,6 @@ { "name": "@t4-code/desktop", - "version": "0.1.29", + "version": "0.1.30", "private": true, "type": "module", "main": "dist-electron/main.cjs", diff --git a/apps/desktop/src/target-manager.ts b/apps/desktop/src/target-manager.ts index 7c5bb48..5a00ca2 100644 --- a/apps/desktop/src/target-manager.ts +++ b/apps/desktop/src/target-manager.ts @@ -383,7 +383,7 @@ export class DesktopTargetManager { capabilities: requestedCapabilities, requestedFeatures: REQUESTED_FEATURES, compatibilityRequestedFeatures: COMPATIBILITY_FEATURES, - client: { name: "T4 Code", version: "0.1.29", build: "desktop", platform: process.platform }, + client: { name: "T4 Code", version: "0.1.30", build: "desktop", platform: process.platform }, reconnect: { baseMs: 250, maxMs: 10_000 }, }; const client = createOmpClient(clientOptions); diff --git a/apps/desktop/test/bundled-runtime.test.ts b/apps/desktop/test/bundled-runtime.test.ts index fc9b2dc..c3ec0fb 100644 --- a/apps/desktop/test/bundled-runtime.test.ts +++ b/apps/desktop/test/bundled-runtime.test.ts @@ -16,7 +16,7 @@ describe("bundled OMP runtime", () => { const sha256 = createHash("sha256").update(bytes).digest("hex"); await writeFile(join(runtimeRoot, "omp"), bytes); await writeFile(join(runtimeRoot, "manifest.json"), JSON.stringify({ - version: 1, tag: "t4code-17.0.5-appserver-7", platform: "darwin", arch: "arm64", + version: 1, tag: "t4code-17.0.5-appserver-8", platform: "darwin", arch: "arm64", executable: "omp", size: bytes.length, sha256, })); @@ -35,7 +35,7 @@ describe("bundled OMP runtime", () => { await mkdir(runtimeRoot, { recursive: true }); await writeFile(join(runtimeRoot, "omp"), "wrong"); await writeFile(join(runtimeRoot, "manifest.json"), JSON.stringify({ - version: 1, tag: "t4code-17.0.5-appserver-7", platform: "darwin", arch: "arm64", + version: 1, tag: "t4code-17.0.5-appserver-8", platform: "darwin", arch: "arm64", executable: "omp", size: 5, sha256: "0".repeat(64), })); @@ -58,7 +58,7 @@ describe("bundled OMP runtime", () => { await writeFile(join(runtimeRoot, "omp"), signedBytes); await writeFile(join(runtimeRoot, "manifest.json"), JSON.stringify({ version: 1, - tag: "t4code-17.0.5-appserver-7", + tag: "t4code-17.0.5-appserver-8", platform: "darwin", arch: "arm64", executable: "omp", diff --git a/apps/desktop/test/doctor.test.ts b/apps/desktop/test/doctor.test.ts index 0f345a3..6a71151 100644 --- a/apps/desktop/test/doctor.test.ts +++ b/apps/desktop/test/doctor.test.ts @@ -41,9 +41,9 @@ describe("T4 setup doctor", () => { const source = await readSourceContract(); expect(source.ompVersion).toBe("17.0.5"); - expect(source.ompTag).toBe("t4code-17.0.5-appserver-7"); + expect(source.ompTag).toBe("t4code-17.0.5-appserver-8"); expect(source.ompUrl).toBe( - "https://github.com/lyc-aon/oh-my-pi/tree/t4code-17.0.5-appserver-7", + "https://github.com/lyc-aon/oh-my-pi/tree/t4code-17.0.5-appserver-8", ); }); diff --git a/apps/mobile/capacitor.config.json b/apps/mobile/capacitor.config.json index a78f508..7755eff 100644 --- a/apps/mobile/capacitor.config.json +++ b/apps/mobile/capacitor.config.json @@ -3,7 +3,7 @@ "appName": "T4 Code", "webDir": "dist", "loggingBehavior": "debug", - "appendUserAgent": " T4CodeMobile/0.1.29", + "appendUserAgent": " T4CodeMobile/0.1.30", "android": { "path": "android", "minWebViewVersion": 60, diff --git a/apps/mobile/package.json b/apps/mobile/package.json index 8a75bfb..50e5b7b 100644 --- a/apps/mobile/package.json +++ b/apps/mobile/package.json @@ -1,6 +1,6 @@ { "name": "@t4-code/mobile", - "version": "0.1.29", + "version": "0.1.30", "private": true, "type": "module", "scripts": { diff --git a/apps/site/package.json b/apps/site/package.json index fde46ff..b47f379 100644 --- a/apps/site/package.json +++ b/apps/site/package.json @@ -1,6 +1,6 @@ { "name": "@t4-code/site", - "version": "0.1.29", + "version": "0.1.30", "private": true, "type": "module", "scripts": { diff --git a/apps/site/src/release.ts b/apps/site/src/release.ts index 4d557f4..cadce8b 100644 --- a/apps/site/src/release.ts +++ b/apps/site/src/release.ts @@ -6,15 +6,15 @@ export const DOCS_URL = `${SITE_URL}/docs`; export const REPO_URL = "https://github.com/LycaonLLC/t4-code"; export const OMP_URL = "https://github.com/can1357/oh-my-pi"; export const OMP_RUNTIME_VERSION = "17.0.5"; -export const OMP_RUNTIME_COMMIT = "04229b1f46547ac7c0617e55a993496ec9725f46"; -export const OMP_RUNTIME_TAG = "t4code-17.0.5-appserver-7"; +export const OMP_RUNTIME_COMMIT = "09835b929cd028e7e3f800b3e4203e3d1f37931c"; +export const OMP_RUNTIME_TAG = "t4code-17.0.5-appserver-8"; export const OMP_RUNTIME_URL = `https://github.com/lyc-aon/oh-my-pi/tree/${OMP_RUNTIME_TAG}`; export const OMP_UPSTREAM_TAG = "v17.0.5"; export const OMP_UPSTREAM_COMMIT = "9fd6e97113f5ed3a847e66d346970efdf8afcad9"; export const OMP_UPSTREAM_URL = `${OMP_URL}/tree/${OMP_UPSTREAM_TAG}`; export const APP_WIRE_VERSION = "0.6.2"; -export const RELEASE_TAG = "v0.1.29"; -export const RELEASE_VERSION = "0.1.29"; +export const RELEASE_TAG = "v0.1.30"; +export const RELEASE_VERSION = "0.1.30"; export const RELEASES_URL = `${REPO_URL}/releases/tag/${RELEASE_TAG}`; export const RELEASE_MANIFEST_URL = `${SITE_URL}/releases/latest.json`; @@ -49,11 +49,11 @@ function asset( } export const RELEASE_ASSETS: readonly ReleaseAsset[] = [ - asset("android", "apk", "universal", "T4-Code-0.1.29-android.apk", "Android APK"), - asset("linux", "deb", "x86_64", "T4-Code-0.1.29-linux-amd64.deb", "Linux .deb"), - asset("linux", "appimage", "x86_64", "T4-Code-0.1.29-linux-x86_64.AppImage", "Linux AppImage"), - asset("mac", "dmg", "arm64", "T4-Code-0.1.29-mac-arm64.dmg", "macOS .dmg"), - asset("mac", "zip", "arm64", "T4-Code-0.1.29-mac-arm64.zip", "macOS .zip"), + asset("android", "apk", "universal", "T4-Code-0.1.30-android.apk", "Android APK"), + asset("linux", "deb", "x86_64", "T4-Code-0.1.30-linux-amd64.deb", "Linux .deb"), + asset("linux", "appimage", "x86_64", "T4-Code-0.1.30-linux-x86_64.AppImage", "Linux AppImage"), + asset("mac", "dmg", "arm64", "T4-Code-0.1.30-mac-arm64.dmg", "macOS .dmg"), + asset("mac", "zip", "arm64", "T4-Code-0.1.30-mac-arm64.zip", "macOS .zip"), ]; export function assetsFor(platform: Platform): readonly ReleaseAsset[] { diff --git a/apps/site/test/release.test.ts b/apps/site/test/release.test.ts index 4e0c557..71cab20 100644 --- a/apps/site/test/release.test.ts +++ b/apps/site/test/release.test.ts @@ -1,4 +1,4 @@ -// Release contract guard: exact v0.1.29 asset names and URLs, and the +// Release contract guard: exact v0.1.30 asset names and URLs, and the // platform-detection rule the hero download button relies on. import { describe, expect, it } from "vite-plus/test"; import { @@ -20,13 +20,13 @@ import { } from "../src/release.ts"; describe("release assets", () => { - it("carries the five contracted v0.1.29 filenames", () => { + it("carries the five contracted v0.1.30 filenames", () => { expect(RELEASE_ASSETS.map((a) => a.filename)).toEqual([ - "T4-Code-0.1.29-android.apk", - "T4-Code-0.1.29-linux-amd64.deb", - "T4-Code-0.1.29-linux-x86_64.AppImage", - "T4-Code-0.1.29-mac-arm64.dmg", - "T4-Code-0.1.29-mac-arm64.zip", + "T4-Code-0.1.30-android.apk", + "T4-Code-0.1.30-linux-amd64.deb", + "T4-Code-0.1.30-linux-x86_64.AppImage", + "T4-Code-0.1.30-mac-arm64.dmg", + "T4-Code-0.1.30-mac-arm64.zip", ]); }); @@ -38,8 +38,8 @@ describe("release assets", () => { it("targets the public LycaonLLC repo", () => { expect(REPO_URL).toBe("https://github.com/LycaonLLC/t4-code"); - expect(RELEASE_TAG).toBe("v0.1.29"); - expect(RELEASE_VERSION).toBe("0.1.29"); + expect(RELEASE_TAG).toBe("v0.1.30"); + expect(RELEASE_VERSION).toBe("0.1.30"); expect(RELEASE_MANIFEST_URL).toBe("https://t4code.net/releases/latest.json"); }); @@ -61,10 +61,10 @@ describe("release assets", () => { describe("OMP integration contract", () => { it("pins the verified runtime tag, commit, and app-wire package", () => { - expect(OMP_RUNTIME_TAG).toBe("t4code-17.0.5-appserver-7"); - expect(OMP_RUNTIME_COMMIT).toBe("04229b1f46547ac7c0617e55a993496ec9725f46"); + expect(OMP_RUNTIME_TAG).toBe("t4code-17.0.5-appserver-8"); + expect(OMP_RUNTIME_COMMIT).toBe("09835b929cd028e7e3f800b3e4203e3d1f37931c"); expect(OMP_RUNTIME_URL).toBe( - "https://github.com/lyc-aon/oh-my-pi/tree/t4code-17.0.5-appserver-7", + "https://github.com/lyc-aon/oh-my-pi/tree/t4code-17.0.5-appserver-8", ); expect(OMP_UPSTREAM_TAG).toBe("v17.0.5"); expect(OMP_UPSTREAM_COMMIT).toBe("9fd6e97113f5ed3a847e66d346970efdf8afcad9"); diff --git a/apps/web/package.json b/apps/web/package.json index 31d29b3..bdc96cd 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -1,6 +1,6 @@ { "name": "@t4-code/web", - "version": "0.1.29", + "version": "0.1.30", "private": true, "type": "module", "scripts": { diff --git a/apps/web/src/platform/browser-shell-port.ts b/apps/web/src/platform/browser-shell-port.ts index 18d0ea8..7312635 100644 --- a/apps/web/src/platform/browser-shell-port.ts +++ b/apps/web/src/platform/browser-shell-port.ts @@ -305,7 +305,7 @@ export function createBrowserShellPort( }, client: { name: "T4 Code", - version: "0.1.29", + version: "0.1.30", build: mobilePlatform ?? "browser", platform: mobilePlatform ?? (platform === "darwin" ? "darwin" : "linux"), }, diff --git a/compat/omp-app-matrix.json b/compat/omp-app-matrix.json index b284827..1b69411 100644 --- a/compat/omp-app-matrix.json +++ b/compat/omp-app-matrix.json @@ -21,14 +21,14 @@ "package": "omp", "version": "17.0.5", "sourceRepository": "https://github.com/lyc-aon/oh-my-pi", - "sourceCommit": "04229b1f46547ac7c0617e55a993496ec9725f46", - "sourceUrl": "https://github.com/lyc-aon/oh-my-pi/commit/04229b1f46547ac7c0617e55a993496ec9725f46", - "sourceTag": "t4code-17.0.5-appserver-7", + "sourceCommit": "09835b929cd028e7e3f800b3e4203e3d1f37931c", + "sourceUrl": "https://github.com/lyc-aon/oh-my-pi/commit/09835b929cd028e7e3f800b3e4203e3d1f37931c", + "sourceTag": "t4code-17.0.5-appserver-8", "artifacts": { "darwin-arm64": { "name": "omp-darwin-arm64", "size": 120777424, - "sha256": "b57dd2c77bc7727a66df5bce8419e071300643d2a04fcba878e1b41cb0298fc0" + "sha256": "3ecb5f40be627f7f0f15035822017f8e2c8afaa4a46978f0874a6be8acb3f2fa" } }, "upstreamRepository": "https://github.com/can1357/oh-my-pi", @@ -96,7 +96,8 @@ "browser-preview-contract", "hardened-preview-frame-decoding", "complete-preview-command-surface", - "privacy-safe-local-project-reveal" + "privacy-safe-local-project-reveal", + "stale-appserver-owner-recovery" ], "upstreamTagContainsIntegrationPatches": false }, @@ -104,14 +105,14 @@ "package": "omp", "version": "17.0.5", "sourceRepository": "https://github.com/lyc-aon/oh-my-pi", - "sourceCommit": "04229b1f46547ac7c0617e55a993496ec9725f46", - "sourceUrl": "https://github.com/lyc-aon/oh-my-pi/commit/04229b1f46547ac7c0617e55a993496ec9725f46", - "sourceTag": "t4code-17.0.5-appserver-7", + "sourceCommit": "09835b929cd028e7e3f800b3e4203e3d1f37931c", + "sourceUrl": "https://github.com/lyc-aon/oh-my-pi/commit/09835b929cd028e7e3f800b3e4203e3d1f37931c", + "sourceTag": "t4code-17.0.5-appserver-8", "artifacts": { "darwin-arm64": { "name": "omp-darwin-arm64", "size": 120777424, - "sha256": "b57dd2c77bc7727a66df5bce8419e071300643d2a04fcba878e1b41cb0298fc0" + "sha256": "3ecb5f40be627f7f0f15035822017f8e2c8afaa4a46978f0874a6be8acb3f2fa" } }, "upstreamRepository": "https://github.com/can1357/oh-my-pi", @@ -179,12 +180,13 @@ "browser-preview-contract", "hardened-preview-frame-decoding", "complete-preview-command-surface", - "privacy-safe-local-project-reveal" + "privacy-safe-local-project-reveal", + "stale-appserver-owner-recovery" ], "upstreamTagContainsIntegrationPatches": false }, "desktop": { "package": "@t4-code/protocol", - "version": "0.1.29" + "version": "0.1.30" } } diff --git a/docs/CURRENT_RELEASE_NOTES.md b/docs/CURRENT_RELEASE_NOTES.md index ea3473c..2afc9a9 100644 --- a/docs/CURRENT_RELEASE_NOTES.md +++ b/docs/CURRENT_RELEASE_NOTES.md @@ -1,6 +1,6 @@ ## A session rail built for large libraries -T4 Code v0.1.29 makes a large session library easier to navigate. The rail now supports text search, activity filters, newest/oldest sorting, grouped and flat layouts, collapsible project folders, and saved display preferences. Those controls follow the Codex desktop organization model while keeping OMP as the source of truth. +T4 Code v0.1.30 makes a large session library easier to navigate. The rail now supports text search, activity filters, newest/oldest sorting, grouped and flat layouts, collapsible project folders, and saved display preferences. Those controls follow the Codex desktop organization model while keeping OMP as the source of truth. Project menus can create a session in that folder, reveal the folder in the system file manager, collapse the group, or hide it from the rail. Hidden projects are not deleted and can be restored from the filter menu. The reveal action is deliberately narrow: the host accepts only project paths already present in its session catalog. @@ -12,11 +12,13 @@ The workspace shell, transcript, home pane, composer, and supporting panes now s When a bundled OMP upgrade temporarily fails to stop the existing macOS service, T4 Code now retries the stop-and-replace sequence. This avoids leaving the installed backend half-updated during normal desktop upgrades while preserving the existing signed-runtime checks. +The bundled backend now also recovers from an inactive Unix socket when the crashed owner's process ID still appears alive. It confirms the endpoint is unreachable more than once and revalidates every ownership file before reclaiming it, while leaving a responsive backend untouched. + ## Runtime provenance -T4 Code v0.1.29 vendors app-wire 0.6.2 from integration commit [04229b1f](https://github.com/lyc-aon/oh-my-pi/commit/04229b1f46547ac7c0617e55a993496ec9725f46), source tree `8400a3af618e8af11cccf6b20aadcf3a22baf9a1`. The client contract remains `omp-app/1`. +T4 Code v0.1.30 vendors app-wire 0.6.2 from integration commit [04229b1f](https://github.com/lyc-aon/oh-my-pi/commit/04229b1f46547ac7c0617e55a993496ec9725f46), source tree `8400a3af618e8af11cccf6b20aadcf3a22baf9a1`. The client contract remains `omp-app/1`. -The verified OMP 17.0.5 runtime is built from commit [04229b1f](https://github.com/lyc-aon/oh-my-pi/commit/04229b1f46547ac7c0617e55a993496ec9725f46) and tagged [t4code-17.0.5-appserver-7](https://github.com/lyc-aon/oh-my-pi/tree/t4code-17.0.5-appserver-7). It adds privacy-safe local project reveal to the existing appserver capabilities, including lazy session indexing, cross-session attention and transcript search, and the negotiated browser-preview command surface. Unsupported optional capabilities remain hidden when the host does not advertise them. +The verified OMP 17.0.5 runtime is built from commit [09835b92](https://github.com/lyc-aon/oh-my-pi/commit/09835b929cd028e7e3f800b3e4203e3d1f37931c) and tagged [t4code-17.0.5-appserver-8](https://github.com/lyc-aon/oh-my-pi/tree/t4code-17.0.5-appserver-8). It adds stale-owner recovery to the existing appserver capabilities, including privacy-safe local project reveal, lazy session indexing, cross-session attention and transcript search, and the negotiated browser-preview command surface. Unsupported optional capabilities remain hidden when the host does not advertise them. The integration is based on the official upstream [v17.0.5 tag](https://github.com/can1357/oh-my-pi/tree/v17.0.5), commit [9fd6e971](https://github.com/can1357/oh-my-pi/commit/9fd6e97113f5ed3a847e66d346970efdf8afcad9). Official upstream OMP v17.0.5 has no `appserver` command and cannot host T4 Code. diff --git a/e2e/site-mobile-docs.spec.ts b/e2e/site-mobile-docs.spec.ts index 15aa8b4..37c3d1d 100644 --- a/e2e/site-mobile-docs.spec.ts +++ b/e2e/site-mobile-docs.spec.ts @@ -130,7 +130,7 @@ test("offers the Android APK without hiding desktop downloads", async ({ page }) await expect(androidDownload).toBeVisible(); await expect(androidDownload).toHaveAttribute( "href", - "https://github.com/LycaonLLC/t4-code/releases/download/v0.1.29/T4-Code-0.1.29-android.apk", + "https://github.com/LycaonLLC/t4-code/releases/download/v0.1.30/T4-Code-0.1.30-android.apk", ); await expect(page.getByRole("link", { name: /Linux/u }).first()).toBeVisible(); await expect(page.getByRole("link", { name: /macOS/u }).first()).toBeVisible(); diff --git a/package.json b/package.json index 42a359a..7eae63d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@t4-code/root", - "version": "0.1.29", + "version": "0.1.30", "private": true, "type": "module", "scripts": { diff --git a/packages/client/package.json b/packages/client/package.json index 84412e3..d867a24 100644 --- a/packages/client/package.json +++ b/packages/client/package.json @@ -1,6 +1,6 @@ { "name": "@t4-code/client", - "version": "0.1.29", + "version": "0.1.30", "private": true, "type": "module", "exports": { diff --git a/packages/client/src/omp-client-frames.ts b/packages/client/src/omp-client-frames.ts index ba9df39..f056747 100644 --- a/packages/client/src/omp-client-frames.ts +++ b/packages/client/src/omp-client-frames.ts @@ -84,7 +84,7 @@ export function sendClientHello( } catch { fatal(); return; } const encoded = encodeOutgoingMessage(provider, { kind: "hello", - client: options.client ?? { name: "t4-code", version: "0.1.29", build: "client", platform: "electron" }, + client: options.client ?? { name: "t4-code", version: "0.1.30", build: "client", platform: "electron" }, requestedFeatures: [...(options.requestedFeatures ?? ["resume"])], savedCursors, ...(options.capabilities === undefined ? {} : { capabilities: options.capabilities }), diff --git a/packages/fixture-server/package.json b/packages/fixture-server/package.json index 9c2e574..a410979 100644 --- a/packages/fixture-server/package.json +++ b/packages/fixture-server/package.json @@ -1,6 +1,6 @@ { "name": "@t4-code/fixture-server", - "version": "0.1.29", + "version": "0.1.30", "private": true, "type": "module", "exports": { diff --git a/packages/protocol/package.json b/packages/protocol/package.json index 0cf95a3..5836c06 100644 --- a/packages/protocol/package.json +++ b/packages/protocol/package.json @@ -1,6 +1,6 @@ { "name": "@t4-code/protocol", - "version": "0.1.29", + "version": "0.1.30", "private": true, "type": "module", "exports": { diff --git a/packages/protocol/test/fixtures/platform-boundaries.ts b/packages/protocol/test/fixtures/platform-boundaries.ts index 06c6347..abbe59e 100644 --- a/packages/protocol/test/fixtures/platform-boundaries.ts +++ b/packages/protocol/test/fixtures/platform-boundaries.ts @@ -25,7 +25,7 @@ export const androidUpdateFixtures = Object.freeze({ }, { currentVersion: "0.1.22", - latestVersion: "0.1.29", + latestVersion: "0.1.30", checkedAt: 1_721_234_567_890, phase: "available", revision: 7, @@ -33,7 +33,7 @@ export const androidUpdateFixtures = Object.freeze({ }, { currentVersion: "0.1.22", - latestVersion: "0.1.29", + latestVersion: "0.1.30", phase: "installer", revision: 8, message: "Installer opened.\nReview Android's prompt.", diff --git a/packages/remote/package.json b/packages/remote/package.json index c8ed356..40d2b64 100644 --- a/packages/remote/package.json +++ b/packages/remote/package.json @@ -1,6 +1,6 @@ { "name": "@t4-code/remote", - "version": "0.1.29", + "version": "0.1.30", "private": true, "type": "module", "exports": { diff --git a/packages/service-manager/package.json b/packages/service-manager/package.json index e34fbc4..f1102cb 100644 --- a/packages/service-manager/package.json +++ b/packages/service-manager/package.json @@ -1,6 +1,6 @@ { "name": "@t4-code/service-manager", - "version": "0.1.29", + "version": "0.1.30", "private": true, "type": "module", "exports": { diff --git a/packages/ui/package.json b/packages/ui/package.json index 92cf4e7..d95d188 100644 --- a/packages/ui/package.json +++ b/packages/ui/package.json @@ -1,6 +1,6 @@ { "name": "@t4-code/ui", - "version": "0.1.29", + "version": "0.1.30", "private": true, "type": "module", "exports": { diff --git a/scripts/check-release-consistency.test.mjs b/scripts/check-release-consistency.test.mjs index bcc513a..4d53645 100644 --- a/scripts/check-release-consistency.test.mjs +++ b/scripts/check-release-consistency.test.mjs @@ -82,14 +82,14 @@ test("rejects duplicate keys in JSON release contracts", () => { test("keeps verified and published runtime records aligned after promotion", () => { const matrix = JSON.parse(files.get("compat/omp-app-matrix.json")); - assert.equal(matrix.verifiedRuntime.sourceTag, "t4code-17.0.5-appserver-7"); + assert.equal(matrix.verifiedRuntime.sourceTag, "t4code-17.0.5-appserver-8"); assert.deepEqual(matrix.publishedRuntime, matrix.verifiedRuntime); }); test("rejects a tag that differs from the package version", () => { assert.ok( collectReleaseConsistencyErrors(files, "v9.9.9").some((error) => - error.includes("release tag v9.9.9 does not match v0.1.29"), + error.includes("release tag v9.9.9 does not match v0.1.30"), ), ); }); @@ -118,7 +118,7 @@ test("tagged releases reject published provenance drift", () => { for (const [field, mutate] of appWireCases) { const drifted = changedRuntime("publishedAppWire", mutate); assert.ok( - collectReleaseConsistencyErrors(drifted, "v0.1.29").some((error) => + collectReleaseConsistencyErrors(drifted, "v0.1.30").some((error) => error.includes( `published app-wire ${field} must match current app-wire for tagged releases`, ), @@ -161,7 +161,7 @@ test("tagged releases reject published provenance drift", () => { for (const [field, mutate] of runtimeCases) { const drifted = changedRuntime("publishedRuntime", mutate); assert.ok( - collectReleaseConsistencyErrors(drifted, "v0.1.29").some((error) => + collectReleaseConsistencyErrors(drifted, "v0.1.30").some((error) => error.includes( `published runtime ${field} must match current verified runtime for tagged releases`, ), @@ -173,7 +173,7 @@ test("tagged releases reject published provenance drift", () => { runtime.artifactSha256 = "0".repeat(64); }); assert.ok( - collectReleaseConsistencyErrors(extended, "v0.1.29").some((error) => + collectReleaseConsistencyErrors(extended, "v0.1.30").some((error) => error.includes( "published runtime must exactly match current verified runtime for tagged releases", ), @@ -183,15 +183,15 @@ test("tagged releases reject published provenance drift", () => { test("rejects workspace, site, README, and runtime version drift", () => { const cases = [ - ["apps/web/package.json", (text) => text.replace('"version": "0.1.29"', '"version": "0.1.3"')], + ["apps/web/package.json", (text) => text.replace('"version": "0.1.30"', '"version": "0.1.3"')], [ "apps/site/src/release.ts", - (text) => text.replace('RELEASE_TAG = "v0.1.29"', 'RELEASE_TAG = "v0.1.3"'), + (text) => text.replace('RELEASE_TAG = "v0.1.30"', 'RELEASE_TAG = "v0.1.3"'), ], - ["README.md", (text) => text.replace("Download v0.1.29", "Download v0.1.3")], + ["README.md", (text) => text.replace("Download v0.1.30", "Download v0.1.3")], [ "apps/desktop/src/target-manager.ts", - (text) => text.replace('version: "0.1.29"', 'version: "0.1.3"'), + (text) => text.replace('version: "0.1.30"', 'version: "0.1.3"'), ], [ "apps/site/src/docs/content.ts", @@ -461,7 +461,7 @@ test("rejects stale README release URLs while allowing historical prose", () => const staleLink = changed("README.md", (text) => `${text}\n[Old release](${oldReleaseUrl})\n`); assert.ok( collectReleaseConsistencyErrors(staleLink).some((error) => - error.includes("release URL for v0.1.3; expected v0.1.29"), + error.includes("release URL for v0.1.3; expected v0.1.30"), ), ); assert.deepEqual(collectReleaseConsistencyErrors(files), []);