Skip to content
Merged
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.5"
placeholder: "0.1.6"
validations:
required: true
- type: dropdown
Expand Down
91 changes: 88 additions & 3 deletions .github/workflows/deploy-site.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,11 @@ on:
- "pnpm-lock.yaml"
- ".github/workflows/deploy-site.yml"
workflow_dispatch:
inputs:
release_tag:
description: Published release tag whose immutable source must be deployed.
required: true
type: string

permissions:
contents: read
Expand All @@ -22,14 +27,29 @@ concurrency:

jobs:
deploy:
if: ${{ github.event_name != 'workflow_dispatch' || github.ref == 'refs/heads/main' }}
runs-on: ubuntu-24.04
timeout-minutes: 50
environment:
name: production
url: https://t4code.net
steps:
- name: Check out source
- name: Check out trusted workflow source
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
with:
ref: ${{ github.sha }}
fetch-depth: 0
persist-credentials: false

- name: Read trusted main release version
id: source
shell: bash
env:
MAIN_SHA: ${{ github.sha }}
run: |
set -euo pipefail
version=$(node -p "require('./package.json').version")
printf 'version=%s\nmain_sha=%s\n' "$version" "$MAIN_SHA" >> "$GITHUB_OUTPUT"

- name: Install pnpm
uses: pnpm/action-setup@b906affcce14559ad1aafd4ab0e942779e9f58b1 # v4
Expand All @@ -42,19 +62,84 @@ jobs:
node-version: 24.13.1
cache: pnpm

- name: Wait for the complete public release
run: node scripts/wait-for-release-assets.mjs --timeout-ms 2400000 --interval-ms 15000
- name: Confirm the published release from the release workflow
id: published_release
if: ${{ github.event_name == 'workflow_dispatch' }}
env:
RELEASE_VERSION: ${{ steps.source.outputs.version }}
run: node scripts/wait-for-release-assets.mjs --version "$RELEASE_VERSION" --timeout-ms 2400000 --interval-ms 15000

- name: Check whether an ordinary main push references an existing release
id: existing_release
if: ${{ github.event_name == 'push' }}
continue-on-error: true
env:
RELEASE_VERSION: ${{ steps.source.outputs.version }}
run: node scripts/wait-for-release-assets.mjs --version "$RELEASE_VERSION" --timeout-ms 15000 --interval-ms 3000

- name: Defer a release-version site update until publication
if: ${{ github.event_name == 'push' && steps.existing_release.outcome == 'failure' }}
run: echo "The referenced release is not public yet; the release workflow will deploy this site after publication."

- name: Resolve immutable deployment source
id: immutable_source
if: ${{ steps.published_release.outcome == 'success' || steps.existing_release.outcome == 'success' }}
shell: bash
env:
EVENT_NAME: ${{ github.event_name }}
GH_TOKEN: ${{ github.token }}
MAIN_SHA: ${{ steps.source.outputs.main_sha }}
REQUESTED_RELEASE_TAG: ${{ inputs.release_tag }}
TRUSTED_VERSION: ${{ steps.source.outputs.version }}
run: |
set -euo pipefail
expected_tag="v${TRUSTED_VERSION}"
release_tag="$expected_tag"
if [[ "$EVENT_NAME" == "workflow_dispatch" ]]; then
if [[ "$REQUESTED_RELEASE_TAG" != "$expected_tag" ]]; then
echo "release_tag must be the current release ${expected_tag}" >&2
exit 1
fi
release_tag="$REQUESTED_RELEASE_TAG"
fi
release_flags=$(gh api "repos/${GITHUB_REPOSITORY}/releases/tags/${release_tag}" --jq '[.draft, .prerelease] | @tsv')
if [[ "$release_flags" != $'false\tfalse' ]]; then
echo "release_tag must name a published, non-prerelease GitHub release" >&2
exit 1
fi
git fetch --force origin "refs/tags/${release_tag}:refs/tags/${release_tag}"
source_sha=$(git rev-parse "${release_tag}^{commit}")
tag_version=$(git show "${source_sha}:package.json" | jq -er '.version')
if [[ "$tag_version" != "$TRUSTED_VERSION" ]]; then
echo "release tag package version ${tag_version} does not match trusted main ${TRUSTED_VERSION}" >&2
exit 1
fi
if ! git merge-base --is-ancestor "$source_sha" "$MAIN_SHA"; then
echo "release tag source is not reachable from trusted main" >&2
exit 1
fi
printf 'release_tag=%s\nsource_sha=%s\n' "$release_tag" "$source_sha" >> "$GITHUB_OUTPUT"

- name: Check out immutable deployment source
if: ${{ steps.published_release.outcome == 'success' || steps.existing_release.outcome == 'success' }}
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
with:
ref: ${{ steps.immutable_source.outputs.source_sha }}
persist-credentials: false

- name: Install dependencies
if: ${{ steps.published_release.outcome == 'success' || steps.existing_release.outcome == 'success' }}
run: pnpm install --frozen-lockfile

- name: Authenticate to AWS with GitHub OIDC
if: ${{ steps.published_release.outcome == 'success' || steps.existing_release.outcome == 'success' }}
uses: aws-actions/configure-aws-credentials@7474bc4690e29a8392af63c5b98e7449536d5c3a # v4
with:
role-to-assume: ${{ vars.AWS_ROLE_ARN }}
aws-region: us-east-1

- name: Build and deploy static site
if: ${{ steps.published_release.outcome == 'success' || steps.existing_release.outcome == 'success' }}
env:
T4_SITE_BUCKET: ${{ vars.T4_SITE_BUCKET }}
T4_CLOUDFRONT_DISTRIBUTION_ID: ${{ vars.T4_CLOUDFRONT_DISTRIBUTION_ID }}
Expand Down
96 changes: 88 additions & 8 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,57 @@ env:

jobs:
verify:
if: ${{ github.event_name != 'workflow_dispatch' || github.ref == 'refs/heads/main' }}
runs-on: ubuntu-24.04
timeout-minutes: 30
outputs:
source_sha: ${{ steps.source.outputs.source_sha }}
version: ${{ steps.source.outputs.version }}
steps:
- name: Check out release tag
- name: Check out trusted release-control source
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
with:
ref: ${{ env.RELEASE_TAG }}
ref: ${{ github.sha }}
fetch-depth: 0
persist-credentials: false

- name: Resolve immutable release source
id: source
shell: bash
env:
EVENT_NAME: ${{ github.event_name }}
MAIN_SHA: ${{ github.sha }}
run: |
set -euo pipefail
trusted_version=$(node -p "require('./package.json').version")
expected_tag="v${trusted_version}"
if [[ "$RELEASE_TAG" != "$expected_tag" ]]; then
echo "release tag must be the current package tag ${expected_tag}" >&2
exit 1
fi
git fetch --force --no-tags origin "refs/heads/main:refs/remotes/origin/main"
git fetch --force origin "refs/tags/${RELEASE_TAG}:refs/tags/${RELEASE_TAG}"
source_sha=$(git rev-parse "${RELEASE_TAG}^{commit}")
tag_version=$(git show "${source_sha}:package.json" | jq -er '.version')
if [[ "$tag_version" != "$trusted_version" ]]; then
echo "release tag package version ${tag_version} does not match trusted source ${trusted_version}" >&2
exit 1
fi
if ! git merge-base --is-ancestor "$source_sha" refs/remotes/origin/main; then
echo "release tag source is not reachable from main" >&2
exit 1
fi
if [[ "$EVENT_NAME" == "workflow_dispatch" && "$MAIN_SHA" != "$(git rev-parse HEAD)" ]]; then
echo "manual releases must run from the checked-out main commit" >&2
exit 1
fi
printf 'source_sha=%s\nversion=%s\n' "$source_sha" "$tag_version" >> "$GITHUB_OUTPUT"

- name: Check out immutable release source
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
with:
ref: ${{ steps.source.outputs.source_sha }}
persist-credentials: false

- name: Install pnpm
uses: pnpm/action-setup@b906affcce14559ad1aafd4ab0e942779e9f58b1 # v4
Expand Down Expand Up @@ -74,10 +118,11 @@ jobs:
runs-on: ubuntu-24.04
timeout-minutes: 35
steps:
- name: Check out release tag
- name: Check out verified release source
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
with:
ref: ${{ env.RELEASE_TAG }}
ref: ${{ needs.verify.outputs.source_sha }}
persist-credentials: false

- name: Install pnpm
uses: pnpm/action-setup@b906affcce14559ad1aafd4ab0e942779e9f58b1 # v4
Expand Down Expand Up @@ -119,10 +164,11 @@ jobs:
runs-on: macos-15
timeout-minutes: 40
steps:
- name: Check out release tag
- name: Check out verified release source
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
with:
ref: ${{ env.RELEASE_TAG }}
ref: ${{ needs.verify.outputs.source_sha }}
persist-credentials: false

- name: Install pnpm
uses: pnpm/action-setup@b906affcce14559ad1aafd4ab0e942779e9f58b1 # v4
Expand Down Expand Up @@ -162,12 +208,28 @@ jobs:
retention-days: 7

publish:
needs: [build-linux, build-macos]
needs: [verify, build-linux, build-macos]
runs-on: ubuntu-24.04
timeout-minutes: 10
permissions:
contents: write
steps:
- name: Check out verified release source
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
with:
ref: ${{ needs.verify.outputs.source_sha }}
fetch-depth: 0
persist-credentials: false

- name: Confirm the release tag still resolves to the verified source
shell: bash
env:
SOURCE_SHA: ${{ needs.verify.outputs.source_sha }}
run: |
set -euo pipefail
git fetch --force origin "refs/tags/${RELEASE_TAG}:refs/tags/${RELEASE_TAG}"
test "$(git rev-parse "${RELEASE_TAG}^{commit}")" = "$SOURCE_SHA"

- name: Download built artifacts
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4
with:
Expand All @@ -192,7 +254,7 @@ jobs:

## Runtime compatibility

This release vendors app-wire 0.5.1 and was verified with OMP 16.4.8 built from [f65bb379](https://github.com/lyc-aon/oh-my-pi/commit/f65bb37970d2186f04ec4b650eb0b53ec3b1337b). Stock upstream OMP v16.4.8 does not include that bounded large-session snapshot and replay fix. It remains protocol-compatible, but a very large active session can disconnect while attaching.
This release vendors app-wire 0.5.2 from public integration commit [5d4315ee](https://github.com/lyc-aon/oh-my-pi/commit/5d4315eea317260fec030e2b4726f10fed0cd5f6) and was verified with OMP 16.4.8 built from [932bbace](https://github.com/lyc-aon/oh-my-pi/commit/932bbaceb256f43eb3b2760341f2175803da4d07), tagged [t4code-16.4.8-appserver-4](https://github.com/lyc-aon/oh-my-pi/tree/t4code-16.4.8-appserver-4). That runtime adds bounded growing-session replay, complete session event projection, catalog-backed session lifecycle management, ordered remote outbound frames, cross-client control-state convergence, terminal streaming-state settlement, and restart-safe session teardown. Official upstream OMP v16.4.8 has no `appserver` command and cannot host T4 Code. The verified runtime is built normally from the public `lyc-aon/oh-my-pi` source; it does not require private home-directory files, an auth broker, or a custom Codex CLI fork.

The macOS build is unsigned and unnotarized. Gatekeeper will block the first launch. After copying T4 Code to Applications, run:

Expand All @@ -207,3 +269,21 @@ jobs:
artifacts/T4-Code-*.dmg
artifacts/T4-Code-*.zip
artifacts/SHA256SUMS.txt

dispatch-site:
name: Dispatch site deployment after release publication
needs: publish
runs-on: ubuntu-24.04
timeout-minutes: 5
permissions:
actions: write
contents: read
steps:
- name: Dispatch the production workflow from main with exact release source
env:
GH_TOKEN: ${{ github.token }}
GH_REPO: ${{ github.repository }}
run: >-
gh workflow run deploy-site.yml
--ref main
-f release_tag="$RELEASE_TAG"
6 changes: 4 additions & 2 deletions FEATURE_MATRIX.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# OMP Desktop Feature and Surface Matrix
# OMP Desktop Product Surface Map

This matrix is the parity contract. T3 Code is the presentation and interaction reference. OMP is the behavioral authority. A feature is not complete because a button exists; the listed runtime state, transitions, errors, permissions, and proof must work.
This file maps product ideas to their OMP authority and intended T4 Code surface. It is a design and ownership reference, not a list of features shipped in the current release. A row can describe planned work, partial work, or verified behavior; its presence here is not completion proof.

The README and release notes are the release contract. They must only claim behavior exercised by the current build. OMP remains the behavioral authority, and T3 Code remains a presentation and interaction reference where noted below.

## 1. Hosts, connections, and environments

Expand Down
Loading
Loading