diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml index f674259..593976f 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.27" + placeholder: "0.1.28" validations: required: true - type: dropdown diff --git a/README.md b/README.md index c530575..a533d6a 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.27**](https://github.com/LycaonLLC/t4-code/releases/tag/v0.1.27) · [**Docs**](https://t4code.net/docs) · [**Get the source**](#build-from-source) +[**Download v0.1.28**](https://github.com/LycaonLLC/t4-code/releases/tag/v0.1.28) · [**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.27, use the public integration build below. +T4 Code needs an OMP build with desktop appserver support. For v0.1.28, use the public integration build below. -T4 Code v0.1.27 was verified with OMP 17.0.5 built from [`772e5e41`](https://github.com/lyc-aon/oh-my-pi/commit/772e5e41eb1537177349247add96a851721c5bfa), tagged [`t4code-17.0.5-appserver-5`](https://github.com/lyc-aon/oh-my-pi/tree/t4code-17.0.5-appserver-5). 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 faster appserver startup, 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, macOS system-temp aliases, workspace-native build artifacts, retry-safe release metadata, lock-aware session observation, complete transcript reconciliation, missing-lock-only promotion, 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.1 from integration commit [`e3e15c03`](https://github.com/lyc-aon/oh-my-pi/commit/e3e15c03ae95ebbda5f26495cd21213cc53518b1), source tree `e0f32b279eb4b8cbc403e47d765a226bee99c99f`. +T4 Code v0.1.28 was verified with OMP 17.0.5 built from [`25295f6f`](https://github.com/lyc-aon/oh-my-pi/commit/25295f6f2e03033cb545c513f476e7e51532524c), tagged [`t4code-17.0.5-appserver-6`](https://github.com/lyc-aon/oh-my-pi/tree/t4code-17.0.5-appserver-6). 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 opens its socket before indexing session history, reads small previews for the session list, and loads a complete transcript only when that session is first used. It also includes 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.1 from integration commit [`e3e15c03`](https://github.com/lyc-aon/oh-my-pi/commit/e3e15c03ae95ebbda5f26495cd21213cc53518b1), source tree `e0f32b279eb4b8cbc403e47d765a226bee99c99f`. The current source tree advances the vendored contract to `@oh-my-pi/app-wire` 0.6.1 from integration commit [`e3e15c03`](https://github.com/lyc-aon/oh-my-pi/commit/e3e15c03ae95ebbda5f26495cd21213cc53518b1), source tree `e0f32b279eb4b8cbc403e47d765a226bee99c99f`. It supplies bounded cross-session transcript search, historical context, and the browser-preview wire contract. @@ -20,18 +20,15 @@ The current source tree advances the vendored contract to `@oh-my-pi/app-wire` 0 | 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.27. The iOS TestFlight build is coming soon. +No Windows build and no Intel Mac build in v0.1.28. The iOS TestFlight build is coming soon. -## What changed in v0.1.27 +## What changed in v0.1.28 -- Mac packaging now waits for code signing to finish before Apple notarization begins. -- Signed Mac builds now start their bundled OMP backend correctly. Only the OMP executable receives permission to load OMP's native module; the T4 Code app and Electron helpers keep normal library validation enabled. -- The app verifies the backend's exact Developer ID certificate before copying the signed bytes, while packaging still verifies the original public OMP download hash. -- macOS downloads remain signed with the project's pinned Developer ID identity, notarized by Apple, stapled, and checked by Gatekeeper before publication. -- The new attention inbox gathers sessions that need a decision, confirmation, or reply, while keeping the host's state authoritative. -- Session transport health now explains reconnecting, delayed, and degraded connections instead of reducing them to a generic disconnected state. -- Browser preview opens session-linked pages in a permission-gated workspace with bounded captures, coordinate-mapped input, and lease-based concurrency control. -- Bounded transcript and attention projections do less repeated work, improving responsiveness without weakening ordering or safety checks. +- Large session libraries no longer block backend startup. On the measured 831-session Mac profile, initial indexing fell from 59.2 seconds to 4.0 seconds; full transcripts still load when opened. +- The signed Mac app automatically installs the exact backend build recorded in its compatibility matrix, so users do not need a separate developer install. +- Phone access configured through the QR flow now restores itself whenever the desktop app launches, including after a reboot or gateway restart. +- The public site includes a no-install browser demo with fixture sessions, panes, agent views, and browser previews, so people can explore T4 Code before downloading it. +- The left rail has clearer information grouping and larger touch targets while keeping the existing layout and shortcuts. ![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) @@ -49,7 +46,7 @@ No Windows build and no Intel Mac build in v0.1.27. 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.27-android.apk`](https://github.com/LycaonLLC/t4-code/releases/download/v0.1.27/T4-Code-0.1.27-android.apk). +2. Download [`T4-Code-0.1.28-android.apk`](https://github.com/LycaonLLC/t4-code/releases/download/v0.1.28/T4-Code-0.1.28-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. @@ -58,8 +55,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.27/T4-Code-0.1.27-linux-amd64.deb -sudo apt install ./T4-Code-0.1.27-linux-amd64.deb +wget https://github.com/LycaonLLC/t4-code/releases/download/v0.1.28/T4-Code-0.1.28-linux-amd64.deb +sudo apt install ./T4-Code-0.1.28-linux-amd64.deb ``` Use `apt install` rather than `dpkg -i` so system dependencies resolve automatically. @@ -67,14 +64,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.27/T4-Code-0.1.27-linux-x86_64.AppImage -chmod +x T4-Code-0.1.27-linux-x86_64.AppImage -./T4-Code-0.1.27-linux-x86_64.AppImage +wget https://github.com/LycaonLLC/t4-code/releases/download/v0.1.28/T4-Code-0.1.28-linux-x86_64.AppImage +chmod +x T4-Code-0.1.28-linux-x86_64.AppImage +./T4-Code-0.1.28-linux-x86_64.AppImage ``` ### macOS (Apple Silicon) -1. Download [`T4-Code-0.1.27-mac-arm64.dmg`](https://github.com/LycaonLLC/t4-code/releases/download/v0.1.27/T4-Code-0.1.27-mac-arm64.dmg) (or [`T4-Code-0.1.27-mac-arm64.zip`](https://github.com/LycaonLLC/t4-code/releases/download/v0.1.27/T4-Code-0.1.27-mac-arm64.zip)). +1. Download [`T4-Code-0.1.28-mac-arm64.dmg`](https://github.com/LycaonLLC/t4-code/releases/download/v0.1.28/T4-Code-0.1.28-mac-arm64.dmg) (or [`T4-Code-0.1.28-mac-arm64.zip`](https://github.com/LycaonLLC/t4-code/releases/download/v0.1.28/T4-Code-0.1.28-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 3d90860..5e4f414 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.27 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.28 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 54103b6..9db984d 100644 --- a/apps/desktop/package.json +++ b/apps/desktop/package.json @@ -1,6 +1,6 @@ { "name": "@t4-code/desktop", - "version": "0.1.27", + "version": "0.1.28", "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 13705ec..1c08119 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.27", build: "desktop", platform: process.platform }, + client: { name: "T4 Code", version: "0.1.28", 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 9f507d7..16ccba2 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-5", platform: "darwin", arch: "arm64", + version: 1, tag: "t4code-17.0.5-appserver-6", 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-5", platform: "darwin", arch: "arm64", + version: 1, tag: "t4code-17.0.5-appserver-6", 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-5", + tag: "t4code-17.0.5-appserver-6", platform: "darwin", arch: "arm64", executable: "omp", diff --git a/apps/desktop/test/doctor.test.ts b/apps/desktop/test/doctor.test.ts index 32a2b3c..d0dd42d 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-5"); + expect(source.ompTag).toBe("t4code-17.0.5-appserver-6"); expect(source.ompUrl).toBe( - "https://github.com/lyc-aon/oh-my-pi/tree/t4code-17.0.5-appserver-5", + "https://github.com/lyc-aon/oh-my-pi/tree/t4code-17.0.5-appserver-6", ); }); diff --git a/apps/mobile/capacitor.config.json b/apps/mobile/capacitor.config.json index f30a0b5..7d74320 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.27", + "appendUserAgent": " T4CodeMobile/0.1.28", "android": { "path": "android", "minWebViewVersion": 60, diff --git a/apps/mobile/package.json b/apps/mobile/package.json index c9f318a..03afd25 100644 --- a/apps/mobile/package.json +++ b/apps/mobile/package.json @@ -1,6 +1,6 @@ { "name": "@t4-code/mobile", - "version": "0.1.27", + "version": "0.1.28", "private": true, "type": "module", "scripts": { diff --git a/apps/site/package.json b/apps/site/package.json index 557129b..d97a078 100644 --- a/apps/site/package.json +++ b/apps/site/package.json @@ -1,6 +1,6 @@ { "name": "@t4-code/site", - "version": "0.1.27", + "version": "0.1.28", "private": true, "type": "module", "scripts": { diff --git a/apps/site/src/release.ts b/apps/site/src/release.ts index 3af8a68..73ca56e 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 = "772e5e41eb1537177349247add96a851721c5bfa"; -export const OMP_RUNTIME_TAG = "t4code-17.0.5-appserver-5"; +export const OMP_RUNTIME_COMMIT = "25295f6f2e03033cb545c513f476e7e51532524c"; +export const OMP_RUNTIME_TAG = "t4code-17.0.5-appserver-6"; 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.1"; -export const RELEASE_TAG = "v0.1.27"; -export const RELEASE_VERSION = "0.1.27"; +export const RELEASE_TAG = "v0.1.28"; +export const RELEASE_VERSION = "0.1.28"; 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.27-android.apk", "Android APK"), - asset("linux", "deb", "x86_64", "T4-Code-0.1.27-linux-amd64.deb", "Linux .deb"), - asset("linux", "appimage", "x86_64", "T4-Code-0.1.27-linux-x86_64.AppImage", "Linux AppImage"), - asset("mac", "dmg", "arm64", "T4-Code-0.1.27-mac-arm64.dmg", "macOS .dmg"), - asset("mac", "zip", "arm64", "T4-Code-0.1.27-mac-arm64.zip", "macOS .zip"), + asset("android", "apk", "universal", "T4-Code-0.1.28-android.apk", "Android APK"), + asset("linux", "deb", "x86_64", "T4-Code-0.1.28-linux-amd64.deb", "Linux .deb"), + asset("linux", "appimage", "x86_64", "T4-Code-0.1.28-linux-x86_64.AppImage", "Linux AppImage"), + asset("mac", "dmg", "arm64", "T4-Code-0.1.28-mac-arm64.dmg", "macOS .dmg"), + asset("mac", "zip", "arm64", "T4-Code-0.1.28-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 94bf47c..3cb1cdf 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.27 asset names and URLs, and the +// Release contract guard: exact v0.1.28 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.27 filenames", () => { + it("carries the five contracted v0.1.28 filenames", () => { expect(RELEASE_ASSETS.map((a) => a.filename)).toEqual([ - "T4-Code-0.1.27-android.apk", - "T4-Code-0.1.27-linux-amd64.deb", - "T4-Code-0.1.27-linux-x86_64.AppImage", - "T4-Code-0.1.27-mac-arm64.dmg", - "T4-Code-0.1.27-mac-arm64.zip", + "T4-Code-0.1.28-android.apk", + "T4-Code-0.1.28-linux-amd64.deb", + "T4-Code-0.1.28-linux-x86_64.AppImage", + "T4-Code-0.1.28-mac-arm64.dmg", + "T4-Code-0.1.28-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.27"); - expect(RELEASE_VERSION).toBe("0.1.27"); + expect(RELEASE_TAG).toBe("v0.1.28"); + expect(RELEASE_VERSION).toBe("0.1.28"); 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-5"); - expect(OMP_RUNTIME_COMMIT).toBe("772e5e41eb1537177349247add96a851721c5bfa"); + expect(OMP_RUNTIME_TAG).toBe("t4code-17.0.5-appserver-6"); + expect(OMP_RUNTIME_COMMIT).toBe("25295f6f2e03033cb545c513f476e7e51532524c"); expect(OMP_RUNTIME_URL).toBe( - "https://github.com/lyc-aon/oh-my-pi/tree/t4code-17.0.5-appserver-5", + "https://github.com/lyc-aon/oh-my-pi/tree/t4code-17.0.5-appserver-6", ); 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 b490117..5fb33d1 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -1,6 +1,6 @@ { "name": "@t4-code/web", - "version": "0.1.27", + "version": "0.1.28", "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 2b34753..8f332b4 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.27", + version: "0.1.28", build: mobilePlatform ?? "browser", platform: mobilePlatform ?? (platform === "darwin" ? "darwin" : "linux"), }, diff --git a/compat/omp-app-matrix.json b/compat/omp-app-matrix.json index c699bdd..80256a4 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": "772e5e41eb1537177349247add96a851721c5bfa", - "sourceUrl": "https://github.com/lyc-aon/oh-my-pi/commit/772e5e41eb1537177349247add96a851721c5bfa", - "sourceTag": "t4code-17.0.5-appserver-5", + "sourceCommit": "25295f6f2e03033cb545c513f476e7e51532524c", + "sourceUrl": "https://github.com/lyc-aon/oh-my-pi/commit/25295f6f2e03033cb545c513f476e7e51532524c", + "sourceTag": "t4code-17.0.5-appserver-6", "artifacts": { "darwin-arm64": { "name": "omp-darwin-arm64", "size": 120777424, - "sha256": "12dce7a582466ab7068fd5ba9bab9c4697e603dada1519f5a0097ad3eb09466b" + "sha256": "0ab83485470562edbad3f7d828f31c6ce8ac6c19e28767d66a74e1a7b8d46877" } }, "upstreamRepository": "https://github.com/can1357/oh-my-pi", @@ -92,6 +92,7 @@ "cross-session-attention-contract", "cross-session-transcript-search", "fast-appserver-startup", + "lazy-session-transcript-indexing", "browser-preview-contract", "hardened-preview-frame-decoding", "complete-preview-command-surface" @@ -102,14 +103,14 @@ "package": "omp", "version": "17.0.5", "sourceRepository": "https://github.com/lyc-aon/oh-my-pi", - "sourceCommit": "772e5e41eb1537177349247add96a851721c5bfa", - "sourceUrl": "https://github.com/lyc-aon/oh-my-pi/commit/772e5e41eb1537177349247add96a851721c5bfa", - "sourceTag": "t4code-17.0.5-appserver-5", + "sourceCommit": "25295f6f2e03033cb545c513f476e7e51532524c", + "sourceUrl": "https://github.com/lyc-aon/oh-my-pi/commit/25295f6f2e03033cb545c513f476e7e51532524c", + "sourceTag": "t4code-17.0.5-appserver-6", "artifacts": { "darwin-arm64": { "name": "omp-darwin-arm64", "size": 120777424, - "sha256": "12dce7a582466ab7068fd5ba9bab9c4697e603dada1519f5a0097ad3eb09466b" + "sha256": "0ab83485470562edbad3f7d828f31c6ce8ac6c19e28767d66a74e1a7b8d46877" } }, "upstreamRepository": "https://github.com/can1357/oh-my-pi", @@ -173,6 +174,7 @@ "cross-session-attention-contract", "cross-session-transcript-search", "fast-appserver-startup", + "lazy-session-transcript-indexing", "browser-preview-contract", "hardened-preview-frame-decoding", "complete-preview-command-surface" @@ -181,6 +183,6 @@ }, "desktop": { "package": "@t4-code/protocol", - "version": "0.1.27" + "version": "0.1.28" } } diff --git a/docs/CURRENT_RELEASE_NOTES.md b/docs/CURRENT_RELEASE_NOTES.md index 5afe4e7..5739332 100644 --- a/docs/CURRENT_RELEASE_NOTES.md +++ b/docs/CURRENT_RELEASE_NOTES.md @@ -1,6 +1,14 @@ +## Faster startup, reliable phone access, and a browser demo + +T4 Code v0.1.28 makes the normal first-run path substantially easier. The bundled OMP backend now opens its socket before scanning session history, builds the session list from small bounded previews, and loads a full transcript only when that session is first used. On a real Mac profile with 831 sessions, initial indexing fell from 59.2 seconds to 4.0 seconds while preserving complete transcripts on demand. + +Phone access configured through the desktop QR flow now restores itself when the app launches. If the private gateway stopped after a reboot or app update, T4 reinstalls the same verified configuration and waits for a healthy local runtime instead of leaving the saved phone route broken. + +The public site now ships a no-install browser demo with fixture sessions, panes, agent views, and browser previews. The left rail also has clearer grouping and larger touch targets. + ## Signed Mac backend startup -T4 Code v0.1.27 completes the signed Mac backend fix. Packaging now waits for the Promise-based signer to finish before notarization begins. The signed, bundled OMP backend can load OMP's native module, with that permission applied only to the OMP executable inside the app. The top-level T4 Code app and its Electron helpers keep normal library validation enabled. +The v0.1.27 signing fix remains in place. Packaging waits for the Promise-based signer to finish before notarization begins. The signed, bundled OMP backend can load OMP's native module, with that permission applied only to the OMP executable inside the app. The top-level T4 Code app and its Electron helpers keep normal library validation enabled. The v0.1.26 tag did not publish release files: its Mac job stopped when notarization detected that the legacy callback signer had returned before signing finished. No partial v0.1.26 GitHub Release was published. @@ -28,9 +36,9 @@ Session-linked browser previews now open in a dedicated workspace. The client pr ## Runtime provenance -T4 Code v0.1.27 vendors app-wire 0.6.1 from integration commit [e3e15c03](https://github.com/lyc-aon/oh-my-pi/commit/e3e15c03ae95ebbda5f26495cd21213cc53518b1), source tree `e0f32b279eb4b8cbc403e47d765a226bee99c99f`. The client contract remains `omp-app/1`. +T4 Code v0.1.28 vendors app-wire 0.6.1 from integration commit [e3e15c03](https://github.com/lyc-aon/oh-my-pi/commit/e3e15c03ae95ebbda5f26495cd21213cc53518b1), source tree `e0f32b279eb4b8cbc403e47d765a226bee99c99f`. The client contract remains `omp-app/1`. -The verified OMP 17.0.5 runtime is built from commit [772e5e41](https://github.com/lyc-aon/oh-my-pi/commit/772e5e41eb1537177349247add96a851721c5bfa) and tagged [t4code-17.0.5-appserver-5](https://github.com/lyc-aon/oh-my-pi/tree/t4code-17.0.5-appserver-5). It provides the appserver used by the desktop and remote workflows, including faster startup, cross-session attention and transcript search, and the complete 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 [25295f6f](https://github.com/lyc-aon/oh-my-pi/commit/25295f6f2e03033cb545c513f476e7e51532524c) and tagged [t4code-17.0.5-appserver-6](https://github.com/lyc-aon/oh-my-pi/tree/t4code-17.0.5-appserver-6). It provides the appserver used by the desktop and remote workflows, including bounded lazy session indexing, cross-session attention and transcript search, and the complete 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 9752322..903c9d1 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.27/T4-Code-0.1.27-android.apk", + "https://github.com/LycaonLLC/t4-code/releases/download/v0.1.28/T4-Code-0.1.28-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 078a1ce..f94b92f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@t4-code/root", - "version": "0.1.27", + "version": "0.1.28", "private": true, "type": "module", "scripts": { diff --git a/packages/client/package.json b/packages/client/package.json index 0f6d8f5..65280be 100644 --- a/packages/client/package.json +++ b/packages/client/package.json @@ -1,6 +1,6 @@ { "name": "@t4-code/client", - "version": "0.1.27", + "version": "0.1.28", "private": true, "type": "module", "exports": { diff --git a/packages/client/src/omp-client-frames.ts b/packages/client/src/omp-client-frames.ts index e7f81bb..4344b49 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.27", build: "client", platform: "electron" }, + client: options.client ?? { name: "t4-code", version: "0.1.28", 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 acb28dd..a2d6892 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.27", + "version": "0.1.28", "private": true, "type": "module", "exports": { diff --git a/packages/protocol/package.json b/packages/protocol/package.json index ebdf23c..39882a9 100644 --- a/packages/protocol/package.json +++ b/packages/protocol/package.json @@ -1,6 +1,6 @@ { "name": "@t4-code/protocol", - "version": "0.1.27", + "version": "0.1.28", "private": true, "type": "module", "exports": { diff --git a/packages/protocol/test/fixtures/platform-boundaries.ts b/packages/protocol/test/fixtures/platform-boundaries.ts index e74ef41..809cf7f 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.27", + latestVersion: "0.1.28", 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.27", + latestVersion: "0.1.28", phase: "installer", revision: 8, message: "Installer opened.\nReview Android's prompt.", diff --git a/packages/remote/package.json b/packages/remote/package.json index 93ac0ac..112efee 100644 --- a/packages/remote/package.json +++ b/packages/remote/package.json @@ -1,6 +1,6 @@ { "name": "@t4-code/remote", - "version": "0.1.27", + "version": "0.1.28", "private": true, "type": "module", "exports": { diff --git a/packages/service-manager/package.json b/packages/service-manager/package.json index 373d437..f924ff5 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.27", + "version": "0.1.28", "private": true, "type": "module", "exports": { diff --git a/packages/ui/package.json b/packages/ui/package.json index b2364eb..b71108c 100644 --- a/packages/ui/package.json +++ b/packages/ui/package.json @@ -1,6 +1,6 @@ { "name": "@t4-code/ui", - "version": "0.1.27", + "version": "0.1.28", "private": true, "type": "module", "exports": { diff --git a/scripts/check-release-consistency.test.mjs b/scripts/check-release-consistency.test.mjs index daa3e6e..b61b58c 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-5"); + assert.equal(matrix.verifiedRuntime.sourceTag, "t4code-17.0.5-appserver-6"); 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.27"), + error.includes("release tag v9.9.9 does not match v0.1.28"), ), ); }); @@ -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.27").some((error) => + collectReleaseConsistencyErrors(drifted, "v0.1.28").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.27").some((error) => + collectReleaseConsistencyErrors(drifted, "v0.1.28").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.27").some((error) => + collectReleaseConsistencyErrors(extended, "v0.1.28").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.27"', '"version": "0.1.3"')], + ["apps/web/package.json", (text) => text.replace('"version": "0.1.28"', '"version": "0.1.3"')], [ "apps/site/src/release.ts", - (text) => text.replace('RELEASE_TAG = "v0.1.27"', 'RELEASE_TAG = "v0.1.3"'), + (text) => text.replace('RELEASE_TAG = "v0.1.28"', 'RELEASE_TAG = "v0.1.3"'), ], - ["README.md", (text) => text.replace("Download v0.1.27", "Download v0.1.3")], + ["README.md", (text) => text.replace("Download v0.1.28", "Download v0.1.3")], [ "apps/desktop/src/target-manager.ts", - (text) => text.replace('version: "0.1.27"', 'version: "0.1.3"'), + (text) => text.replace('version: "0.1.28"', '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.27"), + error.includes("release URL for v0.1.3; expected v0.1.28"), ), ); assert.deepEqual(collectReleaseConsistencyErrors(files), []);