feat(ios): W3 UI layer + integration CI + ntfy docs

T-iOS-11: TerminalScreen/KeyBar/TerminalViewModel + KeyByteMap (byte-for-byte keybar.ts, arrows excluded from UIKeyCommand to preserve DECCKM)
T-iOS-12: PairingScreen/VM — confirm-before-network (zero-call assertions), §5.4 four-tier warnings, Host construction per contract ruling
T-iOS-13: SessionListScreen/VM — Tunables-paced polling with leak-free teardown, optimistic kill+rollback, pending via overlay (LiveSessionInfo has no pending field)
T-iOS-14: GateBanner/PlanGateSheet/AwayDigestView/GateViewModel — three-way mapping from SessionCore Affordance single source, tap-epoch guard, per-epoch haptics
T-iOS-16: IntegrationTests vs real Node server (10 tests: origin guards, mirror, kill-close vs exit-frame differential, 16MiB+ESC/C0 replay) + ios.yml own-sources coverage gate (red-once demoed)
T-iOS-17: ios/README.md ntfy chapter (read-only verification, file:line cites)
Verified: 224 unit + 10 integration tests green; 5/5 semantic spot-checks; zero Owns violations
This commit is contained in:
Yaojia Wang
2026-07-05 00:13:14 +02:00
parent 5c8c87fb7a
commit 5098643355
33 changed files with 5946 additions and 616 deletions

View File

@@ -1,5 +1,19 @@
# iOS CI skeleton (T-iOS-1). T-iOS-16 hardens this: real Node-server
# integration tests + the per-package 80% coverage gate (PLAN_IOS_CLIENT §9).
# iOS CI (T-iOS-16; hardens the T-iOS-1 skeleton). Three layers, PLAN_IOS_CLIENT §9:
#
# 1. package-tests — per-package `swift test` + OWN-SOURCES coverage gate
# (>= 80%, plan §9). NOTE: the plan §9 raw llvm-cov command reads export
# TOTALS, which count statically-linked DEPENDENCY sources compiled into
# the test binary (a known flaw, fix assigned to T-iOS-16). The corrected
# per-package filter lives in ios/IntegrationTests/scripts/coverage-gate.sh
# (jq keeps only Packages/<P>/Sources/, excluding *Placeholder*).
# 2. app-tests — xcodegen + xcodebuild test (WebTermTests bundle,
# iPhone 16 simulator): ViewModels/components of the app glue layer.
# 3. integration-tests — Swift Testing against the REAL Node server. The
# ServerHarness self-bootstraps `tsx src/server.ts` on an ephemeral
# loopback port (127.0.0.1:<free-port> is always in the derived Origin
# whitelist, src/config.ts:187-226 — no ALLOWED_ORIGINS needed). This layer
# is the standing anti-drift gate between the Swift-replicated protocol
# and the server implementation — hence the src/** path triggers below.
name: ios
on:
@@ -7,12 +21,22 @@ on:
paths:
- "ios/**"
- ".github/workflows/ios.yml"
# integration layer guards client<->server protocol drift:
- "src/**"
- "package.json"
- "package-lock.json"
pull_request:
paths:
- "ios/**"
- ".github/workflows/ios.yml"
- "src/**"
- "package.json"
- "package-lock.json"
jobs:
# Layer 1: pure-SwiftPM package tests + the 80% own-sources coverage gate.
# The gate covers exactly the 4 gated packages (plan §9); TestSupport runs
# tests below without a gate (test doubles are excluded from the gate).
package-tests:
runs-on: macos-15
strategy:
@@ -23,10 +47,20 @@ jobs:
- uses: actions/checkout@v4
- name: Select Xcode 16.3
run: sudo xcode-select -s /Applications/Xcode_16.3.app/Contents/Developer
- name: swift test (${{ matrix.package }})
run: swift test --package-path ios/Packages/${{ matrix.package }}
- name: swift test + own-sources coverage gate (>= 80%)
run: ios/IntegrationTests/scripts/coverage-gate.sh ${{ matrix.package }}
app-build:
testsupport-tests:
runs-on: macos-15
steps:
- uses: actions/checkout@v4
- name: Select Xcode 16.3
run: sudo xcode-select -s /Applications/Xcode_16.3.app/Contents/Developer
- name: swift test (TestSupport — no coverage gate, plan §9 gates 4 packages)
run: swift test --package-path ios/Packages/TestSupport
# Layer 2: app-target unit tests (WebTermTests, hosted by the app).
app-tests:
runs-on: macos-15
steps:
- uses: actions/checkout@v4
@@ -36,10 +70,25 @@ jobs:
run: brew install xcodegen
- name: Generate project
run: cd ios && xcodegen generate
- name: Build (iPhone 16 simulator)
- name: xcodebuild test (WebTermTests, iPhone 16 simulator)
run: |
xcodebuild -project ios/WebTerm.xcodeproj -scheme WebTerm \
-destination 'platform=iOS Simulator,name=iPhone 16' \
CODE_SIGNING_ALLOWED=NO build
- name: swift test (IntegrationTests scaffold)
CODE_SIGNING_ALLOWED=NO test
# Layer 3: contract tests against the real Node server (T-iOS-16 test list).
# npm ci compiles node-pty (needs the Xcode toolchain — present on the
# runner); the Swift ServerHarness then boots the server itself.
integration-tests:
runs-on: macos-15
steps:
- uses: actions/checkout@v4
- name: Select Xcode 16.3
run: sudo xcode-select -s /Applications/Xcode_16.3.app/Contents/Developer
- uses: actions/setup-node@v4
with:
node-version: 22
- name: npm ci (builds node-pty native module)
run: npm ci
- name: swift test vs real server (ServerHarness boots tsx src/server.ts)
run: swift test --package-path ios/IntegrationTests