23 KiB
pi-remote — iOS Native App Spec (v3)
Status: v3 nach ExtensionAPI-Audit. Audit-Ergebnis:
EXTENSION-API-AUDIT.md. Review-Verlauf v1:SPEC-ios-app-review-v1.md.Changelog v2 → v3:
- Audit hat S-07, S-08 und Tree-Read als out-of-the-box machbar bestätigt → von PENDING auf firm SHOULD.
- Tree-Navigation komplett aus iOS entfernt. Gruppe T gestrichen. Begründung: Slash-Command-Dispatch ist in der ExtensionAPI blockiert, Workarounds (Hack oder Re-Implement) sind nicht den Aufwand wert. Tree-Navigation bleibt nativ in pi.
- Spike-0a abgeschlossen, ist nun referenziertes Audit-Dokument.
- Q-A geschlossen: pi-CLI
-p/- Q-C geschlossen: APNs-Setup-Details unter iOS-C-02. Sidecar routet pro Device-Token nach Sandbox (Xcode-Debug) vs. Production (TestFlight/Release).
1. Vision
Eine iOS-App, die laufende pi-Sessions byte-genau spiegelt, wie sie im
SSH-Terminal aussehen — und durch native iOS-Mittel (Touch, Sprache,
Notifications, System-Integration) die Bedienung dieser Terminal-Umgebung
unterwegs angenehm macht.
Kein Hybrid-Rendering. Was im Terminal ANSI ist, bleibt in der App ANSI. Die App fügt eine Augmentation-Schicht hinzu, kein paralleles UI.
Kernszenarien:
- Long-Visit-Sync — Eine Session läuft tagelang. Nutzer "besucht" sie unregelmäßig vom Mac (SSH) und iPhone (App). Beide zeigen jederzeit denselben State. Reattach ist instant.
- Session-Lifecycle vom Phone — Sessions vom iPhone aus spawnen, benennen, switchen und beenden — so easy wie native iOS-Tabs.
2. Principles
- P-1 — Der Terminal-Stream ist die einzige Wahrheit für Inhalt. Strukturierte Events dienen ausschließlich Statusanzeigen, Notifications und Meta-State (z.B. Tree-Navigation). Niemals Re-Rendering von Stream-Inhalt.
- P-2 — SSH-Erfahrung bleibt unverändert. Der Mac-Workflow ändert sich durch dieses Projekt nicht spürbar.
- P-3 — Reconnect ist die wichtigste Operation. Sichtbares Ergebnis < 1s nach App-Wake.
- P-4 — Touch-UX wird zur Terminal-Bedienung gebaut, nicht anstelle von Terminal-Bedienung.
- P-5 — Solo-Use. Multi-User, Sharing, Org-Features sind out of scope.
- P-6 — Server-State wird in tmux gehalten, wo möglich. Kein paralleler State-Store im Sidecar.
3. Architecture
┌──────────────────────────────────────────────────────────┐
│ Server │
│ │
│ pi (Ink TUI) ◄─► tmux session ◄─► SSH-Client (Mac) │
│ │ │
│ │ pipe-pane (raw bytes) │
│ │ send-keys │
│ ▼ │
│ pi-remote sidecar │
│ │ │
│ │ WebSocket (wss://) │
│ │ ├─ raw ANSI stream (binary) │
│ │ ├─ control (send-keys, JSON) │
│ │ └─ side-channel (state, JSON) │
└─────────────────────────┼────────────────────────────────┘
│
▼
┌──────────────────────────┐
│ iOS App │
│ ┌────────────────────┐ │
│ │ SwiftTerm renderer │ │
│ └────────────────────┘ │
│ ┌────────────────────┐ │
│ │ Augmentation layer │ │
│ └────────────────────┘ │
└──────────────────────────┘
Komponenten:
- tmux — Session-Persistenz, Multi-Client-Attach, Pane-Pipe, Send-Keys.
Sessions als stable IDs, Metadaten via tmux User-Options
(
@description,@project, etc.). - Sidecar (
pi-remote-controlerweitert) — Node-Prozess. Spawn / Reattach tmux, exponiert WebSocket-API, hält Ringbuffer für Replay, leitet ExtensionAPI-Metadaten als Side-Channel weiter. - iOS-App — SwiftUI-Shell, SwiftTerm als Renderer-View, eigener Augmentation-Layer.
Datenfluss Stream: pi → tmux pipe-pane → sidecar ringbuffer → WS
(binär, permessage-deflate) → iOS SwiftTerm.
Datenfluss Input: iOS → WS → sidecar → tmux send-keys → tmux pane →
pi stdin. Mac-SSH-Client sieht denselben Input.
Konventionen:
- Terminal-Size: tmux pane fixiert auf 120 × 40. Client rendert mit Pinch-Zoom auf die physische Display-Größe.
- WebSocket-Frames: binär = ANSI-Stream-Chunk; text = JSON-Control (input, side-channel, snapshot-request).
- Alternate-Screen-Buffer wird vom Client erkannt und nicht in den Scrollback-Cache aufgenommen.
- Terminal-Title-Sequences werden ignoriert.
- Mouse-Tracking-Sequenzen werden weitergeleitet, vom Client aber nicht visualisiert (Touch-UX).
4. Server Features (Sidecar)
S-01 — tmux launcher / attach
MUST. CLI pi-remote attach [<session>]. Existiert die Session,
reattach; sonst neu spawnen (tmux new-session -d -s <name> 'pi') und
attach. Default-Session: pi-main. Per Projekt benennbar.
Dependencies: —
S-02 — Raw ANSI WebSocket Stream
MUST. Endpoint /stream/<session>.
- Binäre Frames für ANSI-Bytes aus
tmux pipe-pane. - WebSocket-Extension
permessage-deflateaktiv (3–5× Compression typisch für ANSI). - Eine Verbindung = ein Pane.
- Alternate-Screen-Sequenzen werden durchgereicht; Sidecar markiert sie nicht separat (Client tracked).
Dependencies: S-01
S-03 — Send-Keys-Endpoint
MUST. WS-Text-Frames als JSON: {type:"keys", data:"..."} für
literal-Text, oder {type:"key", name:"escape"|"tab"|"up"|...} für
Spezialtasten. Sidecar mapped auf tmux send-keys oder
tmux send-keys -l. Bracketed-Paste-Frames
({type:"paste", data:"..."}) wrappen automatisch mit \e[200~ ... \e[201~.
Dependencies: S-01
S-04 — Sequence-Cursor & Delta-Replay
MUST. Sidecar nummeriert Chunks ausgehend (monotone u64). Client
sendet bei Reconnect {type:"resume", lastSeq:<n>}. Server liefert ab
lastSeq+1 weiter. Falls Lücke → Snapshot (S-05).
Dependencies: S-02
S-05 — Snapshot-Endpoint
MUST. Wenn lastSeq außerhalb des Ringbuffers liegt:
tmux capture-pane -p -e -S -10000 als Snapshot + neuen Start-Seq.
Snapshot wird komprimiert über WS geliefert.
Dependencies: S-01, S-04
S-06 — Per-Session Disk Buffer
SHOULD. Sidecar persistiert ANSI-Stream pro Session in eine
einzelne Datei /var/lib/pi-remote/buffer/<session>.log.
- Pro Session: hartes Cap = 100MB (configurable). Bei Überlauf wird der Schreibvorgang gestoppt; existierender Inhalt bleibt unangetastet. Neue Bytes ab dem Punkt fehlen im Buffer — Snapshot via S-05 funktioniert weiterhin direkt aus tmux.
- Global: Hartes Total-Cap = 1GB über alle Sessions; wenn
überschritten, schaltet der Sidecar Buffer-Schreiben global ab und
meldet
degradedüber S-13. - Idle-Cleanup: Sessions ohne Output UND ohne Client seit > 30 Tagen → Buffer-Datei wird gelöscht (Session selbst nur falls ebenfalls beendet).
- Disk-Watchdog: Bei freiem Platz < 1GB → Buffer-Schreiben global
aus, Health-Status
degraded. - Konfigurierbar via
~/.config/pi-remote/config.toml.
Dependencies: S-02
S-07 — State Side-Channel
SHOULD. Sidecar abonniert pi-ExtensionAPI-Events (agent_start,
agent_end, tool_execution_start, tool_execution_end,
session_tree, session_compact) und publiziert als JSON-Control-Frames:
{"type":"state","value":"thinking"|"tool"|"idle"|"awaiting-input",
"tool":"Edit"|"Read"|...,"ts":1234567890}
awaiting-input wird abgeleitet aus agent_end + ctx.isIdle(),
da kein explizites Event existiert (siehe Audit §3.1).
Dependencies: S-01
S-08 — Slash-Command-Registry
SHOULD. Endpoint /sessions/<id>/commands liefert JSON-Liste der
verfügbaren Slash-Commands inkl. Beschreibung und Argument-Schema via
pi.getCommands() (laut Audit out-of-the-box verfügbar). Dynamisch —
Extensions die Commands hinzufügen erscheinen automatisch.
Dependencies: S-01
S-09 — Multi-Session-Management
MUST. Sidecar verwaltet mehrere tmux-Sessions parallel, alle robust gegen Sidecar-Restart (tmux überlebt, Sidecar reattached beim Boot).
Endpoints:
GET /sessions— Liste mit Metadaten (Name, Description, Created, letzter Output, Connected-Clients, Pi-State).POST /sessions— neue Session spawnen, Body optional{name, project}.PATCH /sessions/<id>— umbenennen / Description ändern.DELETE /sessions/<id>— Session beenden (tmux kill-session + Buffer optional löschen).
State: Ausschließlich in tmux gehalten. Sessions haben Namen (stable ID), Metadaten via tmux User-Options:
@description— Auto- oder manuell vergeben (siehe S-09a)@project— optional, vom User gesetzt@created— Timestamp
Kein eigener JSON-State-Store im Sidecar.
Dependencies: S-01
S-09a — Auto-Naming via pi
NICE. Nach ~3 User-Messages in einer namenlosen Session triggert der Sidecar einen One-Shot-Call via pi-CLI:
pi -p --provider anthropic --model claude-haiku-4-5 \
--no-tools --no-context-files --no-extensions --no-session \
--thinking off \
"Give a 2-4 word title for: '<transcript>'. Reply with title only."
~2s Latenz, pi's eigene Anthropic-Auth wird verwendet — keine separaten
Credentials nötig. Ergebnis landet als @description in tmux.
Manuelles Umbenennen aus der App jederzeit möglich und überschreibt.
Dependencies: S-09
S-10 — Pairing & Bearer-Token-Auth
MUST. CLI pi-remote pair generiert ein kurzlebiges (5min)
Pairing-Token und druckt einen QR-Code im Terminal (Unicode block
chars, via qrcode-terminal).
QR-Inhalt: pi-remote://<host>:<port>?pair=<token>&fp=<sha256-cert-fp>
iOS-App scannt → tauscht Pairing-Token gegen permanenten Bearer-Token, pinnt den TLS-Fingerprint. Token im Keychain (iOS-G-01).
CLI:
pi-remote auth list— alle Tokenspi-remote auth revoke <name>— Token widerrufenpi-remote auth name <name>— Token umbenennen (z.B. "jay's iPhone")
Dependencies: S-11
S-11 — TLS via Self-Signed + Trust-on-First-Use
MUST. Sidecar generiert beim ersten Start ein selbstsigniertes Cert (ED25519 oder RSA-2048), 10 Jahre gültig, persistent auf Disk. SHA-256-Fingerprint wird in den QR aus S-10 mit aufgenommen. Client pinnt den Fingerprint beim Pairing. Bei Cert-Rotation (z.B. neuer Host) muss re-paired werden.
Kein Let's Encrypt, keine CA, kein Reverse-Proxy nötig.
Dependencies: —
S-12 — Health & Metrics
NICE. /health Endpoint mit Session-Count, Buffer-Size,
Connected-Clients, Disk-Watchdog-Status. Für Monitoring und
Selbst-Debugging.
Dependencies: —
S-13 (Tree-State Side-Channel) wurde in v3 gestrichen. Begründung: siehe Out-of-Scope und Changelog.
5. iOS Client Features
Gruppe A — Rendering & Stream
iOS-A-01 — SwiftTerm-Renderer
MUST. Vollwertiger ANSI-Terminal-View. Renderer-Setup mit Truecolor, 120×40 fixed grid, configurable Font + Theme.
Dependencies: S-02
iOS-A-02 — Sequence-Cursor & Reconnect
MUST. Client speichert lokal pro Session den letzten seq. Bei
WS-Reconnect: schickt {type:"resume", lastSeq}, verarbeitet Delta
oder Snapshot.
Dependencies: S-04, S-05
iOS-A-03 — Stale-Frame-Display
SHOULD. Während Sync nach App-Wake: letzten Frame einfrieren, "syncing…" als subtile Overlay-Pill anzeigen. Kein leerer Screen.
Dependencies: iOS-A-02
iOS-A-04 — Local Scrollback-Cache
SHOULD. App puffert empfangene Bytes lokal pro Session (rolling, default 5MB) für Offline-Scrolling und Suche. Alternate-Screen-Inhalt wird ausgenommen.
Dependencies: iOS-A-01
iOS-A-05 — Themes & Fonts
SHOULD. Eingebaute Themes:
- Default-Dark, Default-Light
- Solarized Light, Solarized Dark
- Monokai, Dracula
- Nord, Gruvbox Dark, Gruvbox Light
- Tomorrow Night
- GitHub Light, GitHub Dark
- System (folgt iOS Light/Dark Mode)
Eingebaute Fonts (gebundlet):
- JetBrains Mono (Default)
- Hack
- SF Mono
- Menlo
- Fira Code
- Cascadia Code
- IBM Plex Mono
- Monaspace Neon
Custom Themes editierbar, iCloud-Sync nur für Custom.
Dependencies: iOS-A-01
Gruppe B — Input & Modifier
iOS-B-01 — Software-Keyboard, Direct-Passthrough
MUST. Standard-iOS-Keyboard. Mode (b) direct-passthrough:
jeder Tastendruck geht sofort als send-keys. Enter sendet \r an
pi → pi behandelt selbst. Kein App-eigenes Compose-Feld.
Shift+Enter (newline) via dediziertem ⇧↵-Button in der Modifier-Bar
(siehe iOS-B-02).
Dependencies: S-03
iOS-B-02 — Modifier-Bar
MUST. Accessory-Bar über der Tastatur:
[Ctrl] [Esc] [Tab] [←] [↑] [↓] [→] [⇧↵] [🎙] [📋]
- Ctrl ganz links — Sticky-Toggle: ein Tap → leuchtet → nächste Taste wird als Ctrl+X gesendet. Beliebige Ctrl-Combos möglich (Ctrl-C, Ctrl-D, Ctrl-L, Ctrl-U, ...).
- Esc — eigener Button, dauerhaft sichtbar.
- Tab — Autocomplete in pi.
- Pfeiltasten (Mitte) — History scrollen, in Menüs navigieren, Input-Cursor bewegen.
⇧↵— Shift+Enter, ein Tap =\n(newline in pi multi-line).🎙— Voice-Input (iOS-C-06).📋— Paste-Button ganz rechts (öffnet Paste-Sheet, iOS-B-08).
Bei knappem Platz (iPhone-Portrait) ist die Bar horizontal scrollbar.
Dependencies: iOS-B-01
iOS-B-03 — Long-Press-Repeat
SHOULD. Long-Press auf Pfeiltasten oder Backspace → repeat mit Beschleunigung.
Dependencies: iOS-B-02
iOS-B-04 — Selection & Copy
MUST. Doppel-Tap → Wort. Tripel-Tap → Zeile. Long-Press + Drag → Range. Native iOS-Copy-Menu.
Dependencies: iOS-A-01
iOS-B-05 — Pinch-Zoom Font
SHOULD. Pinch in der Terminal-View → Font-Size live.
Dependencies: iOS-A-01
iOS-B-06 — Hardware-Keyboard-Support
SHOULD. Externe iPad-Keyboards:
- Caps→Esc-Remap (optional)
- Modifier-Pass-Through (Cmd, Option, Ctrl)
- App-Shortcuts:
- Cmd-K — Clear
- Cmd-T — New session
- Cmd-1..9 — Session switch
- Cmd-F — Scrollback-Search
- Cmd-, — Settings
- Cmd-Shift-P — Slash-Command-Palette
Dependencies: iOS-B-01
iOS-B-07 — Reachability / One-Hand-Mode
NICE. iPhone-Querformat: Modifier-Bar gespiegelt für einhändige Bedienung.
Dependencies: iOS-B-02
iOS-B-08 — Smart Paste (Confirm)
SHOULD. 📋-Button in der Modifier-Bar zeigt Clipboard-Vorschau-
Chip ("📋 12 lines, 847 chars"). Tap → Sheet mit vollem Preview,
Insert / Cancel. Verhindert versehentliches Paste großer Blobs.
Dependencies: iOS-B-01
iOS-B-09 — Bracketed-Paste-Compliance
SHOULD. Client trackt im Stream \e[?2004h / \e[?2004l. Wenn
aktiv, wird bei Paste die {type:"paste"} Variante an S-03 geschickt,
sodass pi den ganzen Block als Paste erkennt.
Dependencies: S-03, iOS-B-08
Gruppe C — Pi-aware Augmentation
iOS-C-01 — Status-Bar
MUST. Top-Bar zeigt: Connection-Status, Session-Name, Pi-State
(● thinking / ⏵ tool: Edit / ▶ awaiting / ⏸ idle) basierend auf
S-07.
Dependencies: S-07
iOS-C-02 — Push-Notification bei Awaiting-Input
MUST. Wenn App im Background und Pi wechselt zu awaiting-input:
Push-Notification "Pi ist fertig · ". Tap → App öffnet in
der richtigen Session.
APNs-Setup:
- Apple Developer Portal: App-ID mit Push-Capability +
APNs Auth-Key (
.p8, einmaliger Download). Notiere Team-ID und Key-ID. - Dieselbe
.p8-Datei funktioniert für Sandbox und Production. - Sidecar-Config (neue Sektion in
~/.config/pi-remote/config.toml):[apns] team_id = "..." key_id = "..." key_path = "/etc/pi-remote/AuthKey_<key-id>.p8" bundle_id = "de.vpsj.pi-remote" - Environment-Routing pro Device:
Xcode-Debug-Builds (lokales Testen via WiFi-Pair) registrieren ihre
Device-Tokens bei der Sandbox; TestFlight- und Release-Builds gehen
gegen Production. Beide gleichzeitig betreibbar, da derselbe Key
funktioniert. Sidecar speichert pro Device-Token ein
environment: "sandbox" | "production"Feld und routet beim Push entsprechend zuapi.sandbox.push.apple.combzw.api.push.apple.com. - Pairing-Erweiterung (S-10): iOS-App schickt beim Pairing
zusätzlich
{deviceToken, environment, deviceName}.environmentbestimmt sich zur Compile-Time aus der Build-Config. - HTTP-Headers:
apns-topic: <bundle-id>apns-push-type: alert(required ab iOS 13)apns-priority: 10apns-collapse-id: session-<id>— verhindert Notification-Spam, neuere State-Wechsel überschreiben ältere im Lock-Screen.
- JWT: ES256-signed mit
.p8-Key, 1h gültig, im Sidecar für ~55min cachen. - Auto-Cleanup: APNs-Response
410 Gone→ Device-Token tot, Sidecar löscht Mapping. App registriert beim nächsten Launch neu. - Library:
@parse/node-apnodernode-apn-http2.
Dependencies: S-07, S-10 (Pairing trägt Device-Token), APNs Auth-Key
iOS-C-03 — Haptic Feedback bei State-Wechseln
NICE. Subtile Vibration bei thinking → idle oder
thinking → awaiting-input.
Dependencies: S-07
iOS-C-04 — Slash-Command-Palette
SHOULD. Long-Press auf die Modifier-Bar → öffnet Sheet mit
nativer Liste aller Slash-Commands (aus S-08), Fuzzy-Search. Tap →
injiziert via send-keys. Commands mit Argumenten → Formular-View.
Dependencies: S-03, S-08
iOS-C-05 — Voice-to-Prompt
NICE. 🎙-Button → Speech-Recognition (lokal, iOS native) →
editable Preview → Send.
Dependencies: iOS-B-01, Mic-Permission
Gruppe D — Session & Navigation
iOS-D-01 — Session-Switcher (MUST)
MUST. Native iOS-Liste der verfügbaren Sessions (via S-09). Spawn / Rename / Kill direkt aus dem Switcher.
Dependencies: S-09
iOS-D-01a — Background Pre-Connect
SHOULD. App connectet im Hintergrund zu allen bekannten Sessions parallel, hält pro Session einen kleinen In-Memory-Stream-Buffer + letzten Frame. Switch = Renderer wechselt instant.
Kosten: ein Socket pro Session, ein paar MB RAM. Akzeptabel solange < ~10 aktive Sessions.
Dependencies: iOS-D-01
iOS-D-01b — Optimistic-Switch mit Stale-Frame
SHOULD. Swipe zu Session B → sofort gecachten Frame zeigen, parallel live-Sync. Niemals leerer Screen, nur kurze "sync"-Pille.
Dependencies: iOS-D-01, iOS-D-01a
iOS-D-01c — Predictive Thumbnails
SHOULD. Im Session-Switcher zeigt jede Session eine kleine Live-
Mini-Vorschau (z.B. 40×12 Zeichen Snapshot via tmux capture-pane).
Beim Öffnen des Switchers werden die Thumbnails aktualisiert.
Dependencies: iOS-D-01
iOS-D-02 — Scrollback-Search
SHOULD. Such-Sheet sucht im lokalen Scrollback-Cache (iOS-A-04) mit Highlight + Jump-to-Match. Auch offline nutzbar.
Dependencies: iOS-A-04
Gruppe E — Background & Lifecycle
iOS-E-01 — WS-Keepalive
MUST. Ping/Pong-Frames im Foreground halten Connection. iOS suspended WS gerne ohne Notification.
Dependencies: S-02
iOS-E-02 — Wake-up-Sync
MUST. App-Foreground-Event triggert sofort Reconnect + Delta-Pull. Spinner falls > 200ms. Ziel < 1s sichtbarer Sync (P-3).
Dependencies: iOS-A-02
Gruppe F — Security
iOS-F-01 — Token im Keychain
MUST. Bearer-Token aus S-10 wird im iOS Keychain gespeichert.
Dependencies: S-10
iOS-F-02 — Face-ID / Touch-ID Gate
SHOULD. Biometrie-Lock vorm Öffnen der App. Opt-in via Setting, default off.
Dependencies: —
iOS-F-03 — TLS-Pinning via QR-Pairing
MUST. Beim Pairing (S-10) wird der Cert-Fingerprint gepinnt. Jede künftige Connection verifiziert dagegen. Re-Pairing bei Cert-Rotation.
Dependencies: S-10, S-11
6. Out of Scope (locked)
- Rich Chat-Rendering. Wir parsen den Stream nicht. ANSI bleibt ANSI.
- Embedded Mini-Terminals / Block-Selection. Es gibt einen Stream.
- Multi-User-Sharing. Solo.
- Org/Team-Features, Cloud-Hosted-Service. Selbstgehostet.
- Inline-Image-Rendering (iTerm2 protocol etc.). Eventuell später.
- Eigenes Mosh. tmux + WebSocket reicht.
- Cross-platform-Clients (Android / Web). Nur iOS nativ. Die bestehende HTML-UI bleibt als separates Artefakt.
- Silent-Push-Background-Wake. iOS coalesced unzuverlässig; manueller Wake-up-Sync (iOS-E-02) reicht.
- Marker-Detection / Jump-to-Marker. Pi liefert keine zuverlässigen Marker.
- Tap-to-Cursor. Ohne Marker-Detection nicht robust machbar.
- Eigener Sidecar-State-Store. State lebt in tmux (P-6).
- Disk-Buffer-Rotation. Ein Cap, drüber hinaus = Daten verloren. Snapshot funktioniert weiter.
- Bookmarks / manuelle Marker. Pi-interne Tools sollen das übernehmen.
- Snippet-Library (Prompts mit Variablen). Pi-interne Tools.
- Tree-View / Tree-Navigation in iOS (jeglicher Form, read-only oder interaktiv). Tree wird ausschließlich nativ in pi bedient. Audit hat gezeigt: Slash-Command-Dispatch ist in der ExtensionAPI nicht sauber zugänglich; Workarounds sind die Komplexität nicht wert.
7. ExtensionAPI-Audit (abgeschlossen)
Das Audit wurde durchgeführt; Ergebnis liegt in
EXTENSION-API-AUDIT.md.
Kernergebnisse:
- S-07, S-08, sowie Tree-Read sind out-of-the-box machbar.
- Tree-Write (Slash-Command-Dispatch wie
/fork,/checkout,/new) ist nicht sauber zugänglich → Gruppe T gestrichen (siehe Out-of-Scope). - Tool-Call-Daten sind vollständig verfügbar (Name, Args, Result).
Kein weiterer Spike vor Phase 1 nötig.
8. Phasen
Phase-Aufwände bewusst weggelassen (sind in v1 gestrichen worden).
- Spike-0 — Stream-PoC —
pi-remote-controlum tmux pipe-pane + WS-Stream erweitern. Verifizieren dass pi sauber in tmux läuft (kein Crash, Alternate-Screen sauber, kein Latency-Problem). - Phase 1 — Sidecar production-ready — S-01 bis S-12 (alle), S-09a optional.
- Phase 2 — iOS-App MVP — Renderer (Gruppe A), Input (Gruppe B ohne Hardware-KB), Status-Bar (iOS-C-01), Session-Switcher (iOS-D-01 + a/b), Reconnect-Lifecycle (Gruppe E), Auth (Gruppe F).
- Phase 3 — iOS-App Augmentation — Slash-Palette (iOS-C-04), Voice (iOS-C-05), Thumbnails (iOS-D-01c), Scrollback-Search (iOS-D-02), Hardware-KB (iOS-B-06).
9. Offene Punkte
Keine offenen Punkte mehr in v3. Q-A und Q-C wurden in dieser Version geschlossen (siehe S-09a bzw. iOS-C-02).