Commit Graph
249 Commits
Author SHA1 Message Date
Nucleic ac01589dbf Cloud Infrastructure Setup
Nucleic-Session: 5AC77C62-A729-42E5-A368-1142C3B9E695
2026-06-26 15:07:54 -07:00
Nucleic 7eb60fe672 Cloud Infrastructure Setup
Nucleic-Session: 5AC77C62-A729-42E5-A368-1142C3B9E695
2026-06-26 15:07:50 -07:00
Nucleic 1fdb89e6c1 nvrsion: promote trunk to dev
Nucleic-Promote: 1
2026-06-26 14:28:43 -07:00
Nucleic e618ceb0a9 Merge branch 'dev' into nucleic/trunk 2026-06-26 14:28:43 -07:00
Nucleic b3693f7ce3 Signing Process Optimization
Nucleic-Session: 673CC74C-CCCA-4025-A961-87CC35C28327
2026-06-26 14:17:52 -07:00
Nucleic 24b0b4e8c4 Signing Process Optimization
Nucleic-Session: 673CC74C-CCCA-4025-A961-87CC35C28327
2026-06-26 14:17:18 -07:00
Nucleic 8db01ac703 nvrsion: promote trunk to dev
Nucleic-Promote: 1
2026-06-26 01:29:27 -07:00
Nucleic 4093b3568c Merge branch 'dev' into nucleic/trunk 2026-06-26 01:29:27 -07:00
Nucleic 0847d8fbff Streak Freeze Feature Implementation
Nucleic-Session: 89DB7BC1-F74C-4768-BC7B-25F898265E0E
2026-06-26 01:18:41 -07:00
Nucleic 705d997b78 Streak Freeze Feature Implementation
Nucleic-Session: 89DB7BC1-F74C-4768-BC7B-25F898265E0E
2026-06-26 01:18:36 -07:00
Nucleic cf1176fe96 Streak Freeze Feature Implementation
Nucleic-Session: 89DB7BC1-F74C-4768-BC7B-25F898265E0E
2026-06-26 01:18:29 -07:00
Nucleic e11fda7fa2 Streak Freeze Feature Implementation
Nucleic-Session: 89DB7BC1-F74C-4768-BC7B-25F898265E0E
2026-06-26 01:18:24 -07:00
Nucleic 09d4c80edf Streak Freeze Feature Implementation
Nucleic-Session: 89DB7BC1-F74C-4768-BC7B-25F898265E0E
2026-06-26 01:18:11 -07:00
Nucleic f96e2948ab Streak Freeze Feature Implementation
Nucleic-Session: 89DB7BC1-F74C-4768-BC7B-25F898265E0E
2026-06-26 01:18:03 -07:00
NucleicandClaude Opus 4.8 cfa823bc13 iOS pairing scanner: surface "could not start" + Try Again
On-device logs proved the camera is being blocked by device state, not
the app: every retry showed window=true app=active scene=foregroundActive
yet reason-1 (videoDeviceNotAvailableInBackground) persisted for 6s — the
signature of iPhone Mirroring / a locked tethered device, where iOS
disables the camera (the recurring com.apple.PointerUI log is the Mac
pointer driving the phone).

Rather than sit on a black screen after retries are exhausted, report a
new .couldNotStart state explaining the likely cause (locked / mirrored)
with a "Try Again" button that rebuilds the capture session from scratch
(via .id(retryToken)). App-side capture code is correct; this is a
graceful fallback for an environment that withholds the camera.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-21 17:16:08 -07:00
NucleicandClaude Opus 4.8 765183d25b iOS pairing scanner: delayed bounded retry for reason-1 interruption
On device the camera still reported reason 1 (videoDeviceNotAvailable-
InBackground) even when started from viewDidAppear with the app
foreground-active: the camera assertion isn't granted until the sheet's
presentation transition fully settles (a few hundred ms), and the
back-to-back retries all fired inside that unsettled window.

Add a short delayed retry (0.5s, bounded to 12 attempts) driven by the
interruption notification, plus a proactive +0.6s retry after the view
appears, resetting the counter once the session actually starts. Also log
the window/app/scene activation state to confirm the foreground signals.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-21 17:09:14 -07:00
NucleicandClaude Opus 4.8 07b6769410 iOS pairing scanner: start camera only when foreground (fix black preview)
Root cause (from on-device logs): the session was started from
viewDidLoad while the pairing sheet was still presenting, so iOS
interrupted it with reason 1 (videoDeviceNotAvailableInBackground) and it
never ran (isRunning=false) — a black preview. The CMVideoFormatDescription
-12710 errors were unrelated noise.

Defer startRunning until the camera can actually run: configure the graph
up front, then start only once the view is on screen and the app is
foreground-active (viewDidAppear + a guarded startSessionIfReady). Recover
on AVCaptureSessionInterruptionEnded / didBecomeActive / runtimeError. All
start triggers funnel through the session queue and no-op if already
running, so it's idempotent.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-21 17:00:42 -07:00
NucleicandClaude Opus 4.8 783aac7683 iOS pairing scanner: add capture diagnostics (temporary)
Black preview persists on a real device though the session reports
running, so instrument the capture lifecycle to pinpoint it: logs the
authorization status, the selected device, isRunning/inputs/outputs after
startRunning, and on AVCaptureSessionDidStartRunning the preview layer's
connection (present/active/enabled) plus the view/layer bounds. Also
observes AVCaptureSessionRuntimeError and ...WasInterrupted.

Filterable via os.Logger subsystem com.nucleic.remote / category scanner
(marker "📷"). To be trimmed once the root cause is fixed. Also sets an
explicit .high preset and gates metadataObjectTypes on availability.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-21 16:53:31 -07:00
NucleicandClaude Opus 4.8 b5853eee67 iOS pairing scanner: fix black preview on device
The feed stayed black even when the session reported running: the preview
was a manually-framed sublayer (frame set in viewDidLoad/viewDidLayout,
which raced the async permission callback and could end up zero-sized),
and the session was configured across threads (addInput/Output on main,
startRunning on a queue).

Switch to the canonical AVFoundation pattern: the preview is now the
view's backing layer (CameraPreviewView via layerClass), so it always
fills the view with no frame bookkeeping, and all session configuration +
start/stop run on a dedicated serial queue with delegate/state callbacks
hopped to main.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-21 16:38:00 -07:00
NucleicandClaude Opus 4.8 d8fc4696a8 iOS pairing scanner: handle no-camera / denied gracefully
The QR scanner sat on a silent black screen when the camera couldn't
start: it called AVCaptureDevice.default(for: .video), got nil (e.g. on
the Simulator, which has no camera), and bailed via an early guard with
no UI feedback. It also never requested camera permission (a denied
device stayed black with no recovery) and sized the preview layer only
once in viewDidLoad.

Now it gates on AVCaptureDevice authorization (requesting access when
undetermined, surfacing a Settings link when denied), reports an
"unavailable" state when there's no camera so the UI explains the black
screen, and updates the preview frame in viewDidLayoutSubviews. Camera
runs work on a background queue.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-21 04:45:18 -07:00
NucleicandClaude Opus 4.8 e6ef59e830 iOS remote: transcript fidelity + mid-session controls & model catalog
Bring NucleicRemote closer to desktop parity in two areas (the core
sync loop was already at parity — shared protocol, control scope).

Transcript fidelity (iOS): a client-side TranscriptProjection coalesces
streaming text by messageID and folds each tool call's lifecycle
(start/deltas/complete/result/fileChange) into one expandable card —
fixing the duplicate started+completed rows. Adds Markdown bubbles, the
gold Orchestra card for Task/Agent spawns, and the previously-dropped
usage/cost, rate-limit, file-change, turn-boundary and session-started
rows, plus a context-window % header badge.

Mid-session controls + model catalog (protocol/host/iOS): project the
host ModelCatalog over the wire as WireModelCatalog (in Welcome); add 5
control-scope setters (setSessionModel/Effort/Auto/AutoShip/ShipBranch)
backed by the existing AppStore.mutateSession + SessionController hooks;
enrich WireSessionSummary with model/effort/auto/autoShip/shipBranch/
contextInputTokens (all forward-compatible). The composer gains a model
picker and a catalog-driven effort menu (per-backend caps: Codex→xhigh,
Grok→auto), and the session header gains a model/effort/auto/autoship
control bar.

Tests: CBOR round-trips for the new messages, Welcome.modelCatalog, the
new summary fields, forward-compat decode of old bytes, and the setters
reaching the host. Verified in the Simulator (NUCLEIC_DEMO=1).

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-21 04:03:53 -07:00
NucleicandClaude Opus 4.8 e3b6ccc297 Slow the Orchestra glow: longer pause between pulses
Lengthens the glow pulse period from 0.9s to 2.6s (macOS + iOS), keeping the bold
amplitude — the easeInOut lingers at the baseline, so each pulse now lands
deliberately with a clear gap rather than strobing. The effort-label sparkle keeps
time with it.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
2026-06-21 01:18:17 +00:00
NucleicandClaude Opus 4.8 19c5e20503 Recolor Orchestra gold and make the composer glow more aggressive
Swaps the Orchestra accent from violet to a warm gold (AppTheme.orchestra +
iOS Palette.orchestra), so the composer glow, effort label, and subagent cards all
read gold. Tunes the glow harder — a ~0.9s pulse (was 1.8s) with a thicker stroke
and a bigger outer bloom that swells on the beat — so an Orchestra turn announces
itself. Reduce Motion still holds the glow steady. Against a Control project's
lavender accent, the gold glow stands out cleanly.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
2026-06-21 01:12:24 +00:00
NucleicandClaude Opus 4.8 e03ce837cf Gate Orchestra behind Nucleic Control; lavender Home composer accent
Orchestra is a Nucleic Control capability now:
- Core: SessionController withholds the fan-out consent unless the session's project
  is under Control (resolvedEffort still maps the sentinel to xhigh, so a stray
  selection never reaches a backend verbatim). Covered by a new SessionController test.
- macOS: the effort menu shows Orchestra disabled with a 'Requires Nucleic Control'
  note + tooltip off-control; effectiveEffort demotes a carried-over selection so the
  label/glow never show it active where it can't run.
- Home composer themes lavender (the Control accent) for a Control project — the
  Auto/Merge accents and a persistent ring on the field, tracking the project picker.
- Remote: WireProject carries isNucleicControlled (decode-tolerant) so the iOS effort
  picker gates Orchestra the same way.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
2026-06-21 01:08:07 +00:00
NucleicandClaude Opus 4.8 1c9b120033 Rebrand Ultracode → Orchestra
Renames the orchestration mode's user-facing brand and all code identifiers
(UltracodeStyle→OrchestraStyle, isUltracode→isOrchestra, AppTheme.ultracode→
.orchestra, etc.). The canonical effort sentinel becomes "orchestra"; the legacy
"ultracode" token is still recognized so a persisted/in-flight session keeps
working. Comment referencing Claude Code's own ultracode mode kept accurate.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
2026-06-21 00:37:44 +00:00
Nucleic f90ba73f0b Nucleic: Build A Claude “ultracode”-like System 2026-06-20 17:02:48 -07:00
abkslmandClaude Opus 4.8 49aaf8ca89 Nucleic: restore teal default accent (keep lavender for Control projects only)
dev received an intermediate snapshot of this branch that had the accent
scoping machinery (AppPalette.make(controlled:), controlAccent, RootView's
contextProjectID gate) but NOT the reverts of the base accent back to teal.
Result: the standard palette's base accent AND controlAccent were both
lavender, so control and non-control projects rendered identically lavender.

Re-assert the defaults so the gate is actually visible:
- macOS AppTheme: standard base accent -> teal (0.04,0.52,0.50); controlAccent
  stays lavender (0.45,0.32,0.82). Non-control/home now render teal; only
  Nucleic Control projects get lavender.
- iOS NucleicRemote: Palette.accent + AccentColor.colorset back to flat teal
  (remote has no Control concept).

Merges current dev first so this branch is strictly ahead of it — autoshipping
it back to dev will now override dev's lavender base with teal.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
2026-06-17 19:45:57 -07:00
abkslm e90f5c726f Merge branch 'dev' into nucleic/humble-willow-marten 2026-06-17 19:44:20 -07:00
abkslmandClaude Opus 4.8 fdad762d00 Nucleic: scope lavender accent to Nucleic Control projects only
Make the lavender/purple accent a signal that you are operating inside a
Nucleic Control project; every other project keeps the standard teal tint.

- AppPalette.make gains a 'controlled' flag. When true (and in standard
  color-vision mode) it swaps the teal accent for a cached, nightSoftened
  lavender (controlAccent); otherwise it returns the unchanged palette.
- RootView derives 'controlled' from store.contextProjectID ->
  Project.isNucleicControlled, so the tint follows the active project and
  reverts to teal on the home dashboard / non-control projects. Tracked
  through Observation, so it flips live as you navigate.
- Color-vision (deut/prot/trit) palettes keep their tuned accents; the
  swap only applies in standard mode.
- iOS NucleicRemote reverts to the standard teal: the remote has no
  Nucleic Control concept (the wire protocol doesn't carry it), so it
  can't distinguish controlled projects and stays teal everywhere.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
2026-06-17 19:33:05 -07:00
abkslm bcf91c0ac6 Merge nucleic/humble-willow-marten into dev 2026-06-17 19:25:34 -07:00
abkslmandClaude Opus 4.8 8f672fa76a Nucleic: lavender/purple accent (light + dark shades)
Switch the standard brand accent from deep teal to lavender/purple across
macOS and iOS, with a distinct shade per appearance:

- macOS (AppTheme standard palette): accent -> (0.45, 0.32, 0.82). ~5.4:1
  with white labels in light; nightSoftened() derives the muted dark shade.
- iOS (Palette.accent): now an appearance-aware UIColor — deep violet in
  light, brighter lavender (0.66, 0.55, 0.95) in dark so it lifts off the
  near-black background.
- iOS AccentColor.colorset: add a dark luminosity variant to match.

Accessibility color-vision palettes (deuteranopia/protanopia/tritanopia)
are intentionally left tuned for distinguishability; tritanopia already
renders violet.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
2026-06-17 19:24:56 -07:00
abkslm fe2f931a2e Merge nucleic/plucky-lunar-newt into dev 2026-06-16 03:23:14 -07:00
abkslm e2f18efbd9 Merge nucleic/rustic-north-koala into dev
# Conflicts:
#	Sources/NucleicApp/SessionDetailView.swift
#	ios/NucleicRemote/NucleicRemote/Views/ApprovalCardView.swift
2026-06-16 02:03:44 -07:00
abkslmandClaude Opus 4.8 3954ff13b7 Wrap approval detail and size the box to its content
The first pass put the detail in a ScrollView with fixedSize(horizontal:)
and a fixed maxHeight, so the command was forced onto one long line that
scrolled horizontally and the box always claimed full height — a tall box
with a lot of empty space.

Replace it with an ApprovalDetailBox (macOS + iOS) that wraps the text and
measures its content height via a PreferenceKey, sizing the box to fit and
only scrolling vertically once the content exceeds the max height. No more
horizontal scroll; short commands sit in a snug box.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
2026-06-16 02:00:05 -07:00
abkslm d2817f60fa Merge nucleic/rustic-north-koala into dev 2026-06-16 00:11:11 -07:00
abkslmandClaude Opus 4.8 e31b6a8799 Show full untruncated content in approval requests
Permission requests only ever displayed a summary that was hard-capped:
RiskClassifier.title() slices to 80 chars, and the iOS card used a lossy
compactSummary clipped to 8 lines. The full tool input was present on the
request but never shown, so a long Bash command, file path, or URL was cut
off with "…" and the user couldn't see what they were granting.

- Add RiskClassifier.detail(toolName:input:): the full, untruncated content
  (full command/path/url/query), falling back to the pretty-printed input so
  nothing about an unrecognized tool is hidden.
- Add JSONValue.prettyString() for indented, multi-line display.
- macOS ApprovalBar: render the detail in a bounded, scrollable, selectable
  monospaced block (shown only when it adds beyond the already-shown title).
- iOS ApprovalCardView: replace lossy compactSummary/lineLimit(8) with the
  full content in a bounded scroll view via JSONValue.approvalDetail.
- Tests: assert detail is full and untruncated, with pretty-input fallback.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
2026-06-16 00:10:38 -07:00
abkslm 136a22eb89 Merge nucleic/nimble-north-gecko into dev 2026-06-15 19:19:57 -07:00
abkslm 161b772794 Merge nucleic/eager-dewy-lemur into dev
Animate the Mac streak lightning bolt; intensity (speed, scale, brightness,
rotation jitter, glow) ramps up with streak length.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>

# Conflicts:
#	Sources/NucleicApp/HomeView.swift
2026-06-15 01:28:55 -07:00
abkslm 0dbf40b9bc Merge nucleic/eager-dewy-lemur into dev 2026-06-15 01:23:09 -07:00
abkslm e462a0b4a5 Nucleic: Update Icon Design 2026-06-15 01:23:09 -07:00
abkslmandClaude Opus 4.8 f5902e359d Add In-progress stat card and live list to mobile Home
Surface actively-running sessions on the phone home dashboard: a fourth
"In progress" stat card and a list pinned above the to-dos. Both share one
definition (live sessions with status .running), and list rows link into the
session transcript.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-13 23:16:13 -07:00
abkslmandClaude Opus 4.8 111a5c624a Log header git actions into the session chat
Add a `.note` AgentEvent kind — a system-generated log line — and emit one
into the open session's transcript whenever a control in the header Git menu
is used (merge/squash/rebase outcome, open in Terminal, reveal in Finder,
copy branch/worktree path). Renders as a muted note on both macOS and iOS.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-13 22:51:04 -07:00
abkslmandClaude Opus 4.8 77ca4d1d67 Wrap long permission request text in approval UIs
The macOS ApprovalBar put the title and action buttons on one row, so a
long file-path title got truncated. Stack title above the buttons so it
wraps to as many lines as needed. Bump the iOS card's input summary cap
from 3 to 8 lines. Both made text-selectable.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-13 21:25:57 -07:00
abkslmandClaude Opus 4.8 9d4999bb74 Sandbox: host build/run mode (host_exec tool)
Adds a per-project "Allow host build/run" sandbox capability that lets a
containerized agent request to build and run executables on the host
machine, escaping the Linux sandbox — e.g. compiling and running a macOS
binary the container can't.

- New `host_exec` MCP tool on the approval server, advertised only when the
  session opts in. Pre-allowed via --allowedTools so the call reaches our
  handler directly rather than Claude's permission path: the handler is the
  sole gate, so `auto` mode can never auto-approve it.
- Every host command surfaces an explicit approval (risk .hostExec) and runs
  on the host via /bin/zsh -lc in the session worktree only after approval.
  An explicit "Allow for Session" choice grants the rest of the session;
  auto-approve never sets that — only a deliberate user choice does.
- ProjectSandbox.allowHostExec (off by default) with tolerant decoding so
  rows persisted before the field default to false instead of dropping the
  whole sandbox config.
- Threaded allowHostExec through RunSpec/ResumeSpec/SessionController; Mac
  Project Settings toggle; Mac ApprovalBar "Allow for Session" button; iOS
  risk styling/biometric gate for .hostExec.
- Tests: host_exec advertised/served only when registered + refused
  otherwise; allowHostExec round-trip and legacy-JSON default-to-false.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
2026-06-13 16:52:01 -07:00
abkslm 644851e179 Merge mobile control-scope parity + design language into main
iPhone client gains full control-scope parity with the Mac (start chats, manage
to-dos, manage/integrate sessions), the desktop design language (teal palette,
status colors, cards), and Home/Projects/To-Dos surfaces. Fixes archived chats
leaking into Needs You. See nucleic-m4-state.

# Conflicts:
#	ios/NucleicRemote/NucleicRemote.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved
2026-06-13 02:24:43 -07:00
abkslm 5277583456 NucleicRemote: set development team for device signing + resolve SwiftTerm pins
Adds DEVELOPMENT_TEAM (3XPAYVD6BP) so the app signs to a physical iPhone, and
records the resolved SwiftTerm / swift-argument-parser package pins. Generated by
opening the project in Xcode.
2026-06-13 02:23:45 -07:00
abkslmandClaude Opus 4.8 a70b21cd3e M4+: mirror the desktop design language onto mobile (Home/Projects/To-Dos/Sessions)
Design system: Palette (teal accent + the Mac's categorical status colors, status→color
refined by turn disposition), StatusStyle glyphs/labels, a card surface modifier, app-wide
teal tint.

Fixes the reported bug: Sessions now hides archived chats and uses disposition to split
NEEDS YOU from DONE (a finished-the-work turn no longer shows as needing you). Rows gain
status dots, favorite star, approval-count badge, diffstat; swipe to favorite/archive/delete.

New surfaces, full control-scope parity with the Mac:
- Home: greeting + day-streak flame, GitHub-style activity grid, stat cards, quick to-dos,
  and a start-chat composer (project picker + Auto).
- Projects: per-project session counts → project detail with a scoped composer.
- To-dos: capture, group by project, complete/dispatch/delete.
- Session detail: a control menu (rename, favorite, interrupt, integrate merge/squash/rebase,
  archive, delete).

RemoteStore handles the dashboard event + exposes all control intents; claims control scope.
A NUCLEIC_DEMO/NUCLEIC_TAB env seam seeds mock state for offline UI preview.

iOS app builds for the iOS 27 simulator; Home + Sessions verified rendering via screenshots.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
2026-06-13 02:20:53 -07:00
abkslmandClaude Opus 4.8 c907333df2 M4: make device testing work — LAN IP in QR + automatic iOS signing
- LANAddress.primaryIPv4() (getifaddrs, prefers en*) embedded in the pairing QR via
  beginPairing, so the phone dials the Mac directly instead of relying on Bonjour
  discovery (much more robust on real networks; Bonjour stays a fallback).
- iOS project switches from CODE_SIGNING_ALLOWED=NO to CODE_SIGN_STYLE=Automatic so
  it signs to a physical device once a team is selected in Xcode (simulator still
  builds without a team).

174 tests green; macOS + iOS-simulator builds clean.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
2026-06-13 01:22:12 -07:00
abkslmandClaude Opus 4.8 6f24b42004 M4: NucleicRemote iPhone app — SwiftUI client over the shared protocol
A real iOS Xcode app (ios/NucleicRemote) linking the NucleicProtocol SwiftPM
library as a local package. Builds for the iOS 27 simulator and launches to the
pairing screen.

- Transport: NWFrameChannel (NWConnection) + LANDiscovery (Bonjour _nucleic._tcp).
- Engine: drives NucleicProtocol.SyncClient (Noise XXpsk0 pair / IK reconnect,
  hello/welcome, HostMsg→Event stream).
- State: RemoteStore (ObservableObject) — the single on-device projection of host
  state; IdentityStore persists the device identity (Keychain) + pinned host.
- UI (UX_IOS): attention-first SessionsView, SessionDetailView (transcript/diff +
  status-driven action area / composer), ApprovalCardView with Face ID gate on
  high-risk approvals + allow-always menu, PairingScannerView (AVFoundation QR),
  SettingsView, connection chip. Same status glyphs/semantics as the Mac.

Add-iPhone QR display + server start live on the macOS side (follow-up); push /
Live Activity are M5 (needs the relay). gitignore keeps this .xcodeproj despite
the blanket *.xcodeproj rule.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
2026-06-13 01:12:55 -07:00