Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/ISSUE_TEMPLATE/bug_report.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ body:
id: version
attributes:
label: T4 Code version
placeholder: "0.1.30"
placeholder: "0.1.31"
validations:
required: true
- type: dropdown
Expand Down
170 changes: 5 additions & 165 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,6 @@ jobs:
official_omp_gate0: ${{ steps.classify.outputs.official_omp_gate0 }}
tooling: ${{ steps.classify.outputs.tooling }}
android_debug: ${{ steps.classify.outputs.android_debug }}
flutter: ${{ steps.classify.outputs.flutter }}
flutter_android: ${{ steps.classify.outputs.flutter_android }}
flutter_apple: ${{ steps.classify.outputs.flutter_apple }}
steps:
- name: Check out source and base history
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
Expand Down Expand Up @@ -87,13 +84,13 @@ jobs:
run: pnpm exec playwright install --with-deps chromium

- name: Check source and types
run: pnpm check:release && pnpm check:provenance && pnpm lint && pnpm --filter '!@t4-code/flutter' -r typecheck
run: pnpm check

- name: Run tests
run: pnpm --filter '!@t4-code/flutter' -r test
run: pnpm test

- name: Build all workspaces
run: pnpm --filter '!@t4-code/flutter' -r build
run: pnpm build

- name: Run built-app end-to-end tests
run: pnpm test:e2e
Expand Down Expand Up @@ -373,161 +370,10 @@ jobs:
- name: Verify unsigned Android debug application
run: pnpm --filter @t4-code/mobile check:android:debug

flutter:
needs: changes
if: ${{ github.event_name != 'pull_request' || needs.changes.outputs.flutter == 'true' }}
runs-on: ubuntu-24.04
timeout-minutes: 30
steps:
- name: Check out source
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4

- name: Install pnpm
uses: pnpm/action-setup@b906affcce14559ad1aafd4ab0e942779e9f58b1 # v4
with:
version: 11.10.0

- name: Install Node.js
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4
with:
node-version: 24.13.1
cache: pnpm

- name: Install Flutter
uses: subosito/flutter-action@1a449444c387b1966244ae4d4f8c696479add0b2 # v2
with:
flutter-version: 3.44.6
channel: stable
cache: true

- name: Install dependencies
run: pnpm install --frozen-lockfile

- name: Check Flutter source
run: pnpm check:flutter

- name: Run Flutter tests with coverage gate
run: pnpm --filter @t4-code/flutter test:coverage

- name: Build Flutter web application
run: pnpm build:flutter:web

flutter-android:
needs: changes
if: ${{ github.event_name != 'pull_request' || needs.changes.outputs.flutter_android == 'true' }}
runs-on: ubuntu-24.04
timeout-minutes: 35
steps:
- name: Check out source
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4

- name: Install Java
uses: actions/setup-java@c1e323688fd81a25caa38c78aa6df2d33d3e20d9 # v4
with:
distribution: temurin
java-version: "21"
cache: gradle

- name: Install Flutter
uses: subosito/flutter-action@1a449444c387b1966244ae4d4f8c696479add0b2 # v2
with:
flutter-version: 3.44.6
channel: stable
cache: true

- name: Build Flutter Android application
working-directory: apps/flutter
run: flutter build apk --debug

- name: Run Flutter Android native tests
working-directory: apps/flutter/android
run: ./gradlew app:testDebugUnitTest

- name: Enable Android emulator acceleration
run: sudo chmod 666 /dev/kvm

- name: Run Flutter Android device smoke test
uses: ReactiveCircus/android-emulator-runner@a421e43855164a8197daf9d8d40fe71c6996bb0d # v2
with:
api-level: 35
arch: x86_64
profile: pixel_6
script: cd apps/flutter && flutter test integration_test/app_smoke_test.dart -d emulator-5554

flutter-apple:
needs: changes
if: ${{ github.event_name != 'pull_request' || needs.changes.outputs.flutter_apple == 'true' }}
runs-on: macos-15
timeout-minutes: 40
steps:
- name: Check out source
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4

- name: Install Flutter
uses: subosito/flutter-action@1a449444c387b1966244ae4d4f8c696479add0b2 # v2
with:
flutter-version: 3.44.6
channel: stable
cache: true

- name: Build Flutter iOS simulator application
working-directory: apps/flutter
run: flutter build ios --simulator --debug

- name: Run Flutter iOS launch smoke test
working-directory: apps/flutter
shell: bash
run: |
set -euo pipefail
DEVICE_ID="$(xcrun simctl list devices available -j | python3 -c 'import json,sys; data=json.load(sys.stdin); print(next(device["udid"] for devices in data["devices"].values() for device in devices if device["name"].startswith("iPhone")))')"
BUNDLE_ID="com.lycaonsolutions.t4code"
xcrun simctl boot "$DEVICE_ID" 2>/dev/null || true
xcrun simctl bootstatus "$DEVICE_ID" -b
xcrun simctl install "$DEVICE_ID" build/ios/iphonesimulator/Runner.app
trap 'xcrun simctl terminate "$DEVICE_ID" "$BUNDLE_ID" 2>/dev/null || true' EXIT
launch_output="$(xcrun simctl launch --terminate-running-process "$DEVICE_ID" "$BUNDLE_ID")"
app_pid="$(sed -nE 's/^.*: ([0-9]+)$/\1/p' <<<"$launch_output" | tail -n 1)"
[[ "$app_pid" =~ ^[0-9]+$ ]]
sleep 5
kill -0 "$app_pid"

- name: Install pnpm
uses: pnpm/action-setup@b906affcce14559ad1aafd4ab0e942779e9f58b1 # v4
with:
version: 11.10.0

- name: Install Node.js
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4
with:
node-version: 24.13.1
cache: pnpm

- name: Install Bun
uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0
with:
bun-version: 1.3.14

- name: Install T4 dependencies
run: pnpm install --frozen-lockfile

- name: Build standalone T4 host for Flutter macOS
run: pnpm build:host

- name: Build Flutter macOS application
working-directory: apps/flutter
run: flutter build macos --debug

- name: Verify bundled Flutter macOS host
run: test -x apps/flutter/build/macos/Build/Products/Debug/t4code.app/Contents/Resources/runtime/t4-host

- name: Run Flutter macOS native tests
working-directory: apps/flutter/macos
run: xcodebuild test -workspace Runner.xcworkspace -scheme Runner -configuration Debug -destination 'platform=macOS' CODE_SIGNING_ALLOWED=NO

verify:
name: verify
if: ${{ always() }}
needs: [changes, core, legacy-bridge-continuity, official-omp-gate0, cluster, tooling, android-debug, flutter, flutter-android, flutter-apple]
needs: [changes, core, legacy-bridge-continuity, official-omp-gate0, cluster, tooling, android-debug]
runs-on: ubuntu-24.04
timeout-minutes: 5
steps:
Expand All @@ -541,9 +387,6 @@ jobs:
CLUSTER_RESULT: ${{ needs.cluster.result }}
TOOLING_RESULT: ${{ needs.tooling.result }}
ANDROID_RESULT: ${{ needs.android-debug.result }}
FLUTTER_RESULT: ${{ needs.flutter.result }}
FLUTTER_ANDROID_RESULT: ${{ needs.flutter-android.result }}
FLUTTER_APPLE_RESULT: ${{ needs.flutter-apple.result }}
run: |
set -euo pipefail
test "$CHANGES_RESULT" = success
Expand All @@ -553,10 +396,7 @@ jobs:
"$OFFICIAL_OMP_GATE0_RESULT" \
"$CLUSTER_RESULT" \
"$TOOLING_RESULT" \
"$ANDROID_RESULT" \
"$FLUTTER_RESULT" \
"$FLUTTER_ANDROID_RESULT" \
"$FLUTTER_APPLE_RESULT"
"$ANDROID_RESULT"
do
case "$result" in
success|skipped) ;;
Expand Down
32 changes: 2 additions & 30 deletions .github/workflows/deploy-site.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ on:
branches: [main, master]
paths:
- "apps/site/**"
- "apps/flutter/**"
- "apps/web/**"
- "packages/**"
- "scripts/check-release-publication.mjs"
- "scripts/build-demo.mjs"
Expand Down Expand Up @@ -65,13 +65,6 @@ jobs:
with:
node-version: 24.13.1

- name: Install Flutter
uses: subosito/flutter-action@1a449444c387b1966244ae4d4f8c696479add0b2 # v2
with:
flutter-version: 3.44.6
channel: stable
cache: true

- name: Install dependencies
run: pnpm install --frozen-lockfile

Expand All @@ -81,28 +74,7 @@ jobs:
role-to-assume: ${{ vars.AWS_ROLE_ARN }}
aws-region: us-east-1

- name: Check whether the live demo permits the Flutter renderer
id: demo_csp
shell: bash
run: |
set -euo pipefail
headers=$(curl --fail --silent --show-error --head https://t4code.net/demo)
if printf '%s\n' "$headers" \
| tr -d '\r' \
| grep -i '^content-security-policy:' \
| grep -Fq "'wasm-unsafe-eval'"; then
echo "ready=true" >> "$GITHUB_OUTPUT"
else
echo "ready=false" >> "$GITHUB_OUTPUT"
echo "::warning::Flutter demo deployment is deferred until the demo CloudFront CSP permits wasm-unsafe-eval."
fi

- name: Defer Flutter demo until its response policy is active
if: ${{ steps.demo_csp.outputs.ready != 'true' }}
run: echo "Apply infra/site/cloudformation.yml, then rerun this workflow from a main push."

- name: Build and deploy current Flutter demo
if: ${{ steps.demo_csp.outputs.ready == 'true' }}
- name: Build and deploy current React demo
env:
T4_SITE_BUCKET: ${{ vars.T4_SITE_BUCKET }}
T4_CLOUDFRONT_DISTRIBUTION_ID: ${{ vars.T4_CLOUDFRONT_DISTRIBUTION_ID }}
Expand Down
6 changes: 3 additions & 3 deletions .woodpecker.yml
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,9 @@ steps:
commands:
- export PATH="$PWD/.ci:$PATH"
- corepack enable
- pnpm check:release && pnpm check:provenance && pnpm lint && pnpm --filter '!@t4-code/flutter' -r typecheck
- VP_RUN_CONCURRENCY_LIMIT=1 pnpm --filter '!@t4-code/flutter' -r test
- pnpm --filter '!@t4-code/flutter' -r build
- pnpm check
- VP_RUN_CONCURRENCY_LIMIT=1 pnpm test
- pnpm build
- pnpm exec playwright install --with-deps chromium
- pnpm test:e2e
- pnpm test:packaging
Expand Down
2 changes: 1 addition & 1 deletion FEATURE_MATRIX.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ OMP authority: `packages/coding-agent/src/session/agent-session.ts`, `session-ma
| List/recent/search/filter | session store and metadata | Codex-parity left rail: By project or In one list; Priority, Last updated, or Manual order; real project/session dragging with keyboard fallbacks; title/project/host search; attention/running/unread/error filters; pinned shortcuts; five-row Show more; project aliases; reversible hidden projects; bulk read/archive; local-only Finder reveal; direct pin/archive controls | `Rail.tsx`, `session-tree.ts`, workspace store, management helpers, browser tests | Launch |
| New session | `/new` | Create in selected project/host; model/profile defaults visible before first prompt | draft routes and composer draft store | Launch |
| Fast switch and tabs | session IDs and snapshots | One-click/keyboard switch; preserve draft, scroll anchor, panel widths/tabs, terminal focus; no white flash | T3 routes, `composerDraftStore`, `rightPanelStore`, terminal store | Launch |
| Tail-first transcript history | Bounded `transcript.page` range reads plus the existing live attach cursor | Paint a small newest page on cold open; prepend older pages without moving the reading anchor or live cursor | T4-owned host, web client, and thin OMP bridge implemented; Flutter local cache planned | Launch |
| Tail-first transcript history | Bounded `transcript.page` range reads plus the existing live attach cursor | Paint a small newest page on cold open; prepend older pages without moving the reading anchor or live cursor | T4-owned host, React client, and thin OMP bridge implemented; offline display cache remains planned | Launch |
| Resume | `/resume` | Open existing session by stable ID/path; recover moved/missing files with explicit error | thread routing and reconnect supervisor | Launch |
| Rename | `/rename` | Inline rename with optimistic state and rollback | sidebar row actions | Launch |
| Move working directory/session | `/move` | Native/remote path picker, validation, explicit impact message | environment picker patterns | Parity |
Expand Down
11 changes: 7 additions & 4 deletions PRODUCT_BRIEF.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@

## Product

T4 Code is a Flutter desktop, mobile, and web workspace for official Oh My Pi (OMP). It makes
T4 Code is an Electron desktop workspace with a shared React compatibility client for official Oh
My Pi (OMP). It makes
projects, concurrent sessions, live streaming, tools, terminal activity, task agents, reviews, files,
settings, and local or remote execution easier to operate without reimplementing OMP behavior.

Expand All @@ -17,8 +18,8 @@ settings, and local or remote execution easier to operate without reimplementing
- Browser and app preview remains a focused workspace rather than a permanent sixth pane.
- Keyboard shortcuts, Quick Open, workspace menus, and transcript links use one action registry so
availability and behavior do not diverge.
- Quick Open searches through bounded authorized operations. Flutter never receives or chooses an
absolute path it does not already own.
- Quick Open searches through bounded authorized operations. The renderer never receives or
chooses an absolute path it does not already own.
- The Universal Working Set lets a user deliberately stage exact material from a file preview,
transcript message, review diff, selected terminal text, or browser accessibility snapshot. The
user can inspect and remove each item before it joins one ordinary OMP prompt; it does not become
Expand All @@ -28,7 +29,9 @@ settings, and local or remote execution easier to operate without reimplementing

## Product modes

T4 Code presents one client experience across four execution profiles:
T4 Code presents one desktop-first client experience across four execution profiles. The
responsive browser/PWA and React/Capacitor Android builds are compatibility clients for paired
hosts; they do not promise native desktop parity.

- **T4 Local:** native execution on this macOS or Linux computer.
- **Personal Hub:** a managed installation on one Linux machine.
Expand Down
Loading
Loading