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
20 changes: 17 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
# Wayfinder

Wayfinder is a local-first model router and native macOS chat app. It scores each
request locally, chooses a configured destination, and keeps delivery policy
separate from the application making the request.
Wayfinder is a local-first model router and native Apple AI environment. It
scores each request locally, chooses an eligible destination, and keeps delivery
policy separate from the application making the request.

The production router is implemented in Rust. Wayfinder Desktop embeds that
router inside the signed application bundle; no Python runtime, package, or
Expand All @@ -24,6 +24,18 @@ The native Swift macOS app provides:
Desktop releases use SemVer and `desktop-v*` tags. See
[`macos/WayfinderMac/Packaging/RELEASE.md`](macos/WayfinderMac/Packaging/RELEASE.md).

### Wayfinder for iPhone and iPad

Native standalone iPhone and iPad apps are planned for v0.2.0. They embed the
same authoritative Rust routing core and execute approved on-device or direct
cloud providers without requiring a Mac or localhost gateway. Optional Mac
pairing follows in v0.2.1 as an additional provider.

The governing contracts are
[`WF-ROADMAP-0016`](roadmaps/WF-ROADMAP-0016-native-mobile-v0.2.md),
[`WF-ADR-0047`](decisions/WF-ADR-0047-native-mobile-independence.md), and
[`WF-ADR-0048`](decisions/WF-ADR-0048-shared-routing-core-apple-embedding.md).

### Rust gateway

The Rust workspace contains the deterministic scoring core, configuration
Expand Down Expand Up @@ -83,6 +95,8 @@ node clients/shared/test/parity.mjs

```text
rust/ native router, gateway, providers, and service crates
apple/ planned shared Apple packages after bridge validation
ios/ planned native iPhone and iPad product
macos/WayfinderMac/ native Swift macOS app and release packaging
clients/ retained thin-client contract code and fixtures
decisions/ architecture decisions
Expand Down
9 changes: 9 additions & 0 deletions decisions/WF-ADR-0042-desktop-menu-bar-client.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,13 @@ Accepted
> notarized, stapled app in a ZIP; the universal DMG and automatic-updater decisions below remain
> historical Tauri targets, not v0.1.0 requirements. The optional ChatGPT account provider requires
> the separately installed verified ChatGPT app. Wayfinder does not bundle Codex in this release.
>
> Rust-only amendment (WF-ADR-0046): Python, PyPI, and delegated-command language below records the
> migration history. Rust is now the sole production router and gateway.
>
> Mobile amendment (WF-ADR-0047/0048): this ADR remains the macOS constitution. Native iPhone and
> iPad are independently useful, embed the shared pure routing core, own their credentials and
> threads, and do not run or require this desktop gateway. That is not a second routing algorithm.

## Category

Expand Down Expand Up @@ -203,3 +210,5 @@ menu-bar utility and keeps the binary small.
- WF-DESIGN-0012 (the popover design contract) · WF-ROADMAP-0009 (the delivery plan)
- WF-DESIGN-0018 (external verified ChatGPT-app provider boundary)
- WF-ROADMAP-0015 (Apple Silicon desktop v0.1.0 release contract)
- WF-ADR-0046 (Rust-only runtime)
- WF-ADR-0047 / WF-ADR-0048 (native mobile independence and shared routing core)
15 changes: 14 additions & 1 deletion decisions/WF-ADR-0045-rust-gateway-helper-architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,24 @@ tags: [rust, gateway, router, helper, macos, compatibility, security, packaging]

## Status

Accepted for staged implementation; Rust is not yet accepted as the default backend.
Superseded for runtime-selection and migration state by WF-ADR-0046. Retained
as the architecture and threat-model record for the separately running macOS
gateway helper.

> Desktop v0.1.0 release amendment (WF-ROADMAP-0015): the native app explicitly ships its bundled
> Rust gateway as a thin arm64 helper on Apple Silicon. This desktop-product selection does not make
> Rust the default for standalone, Homebrew, container, or PyPI installations and does not authorize
> Python removal. The originally accepted universal arm64/x86_64 artifact remains a future broader
> distribution gate rather than a requirement for the first desktop release.
>
> Rust-only cutover (WF-ADR-0046): Python coexistence, delegation, PyPI, and
> Python verification gates below are historical migration constraints, not
> current runtime requirements.
>
> Mobile amendment (WF-ADR-0048): the rejection of an in-process Swift/Rust
> bridge remains correct for the macOS gateway-first product. Native iPhone and
> iPad have no gateway helper and therefore embed a separately extracted pure
> routing core through generated bindings.

## Category

Expand Down Expand Up @@ -328,3 +339,5 @@ omitted from a default-readiness recommendation.
- WF-ADR-0042/0044 (thin native client and CLI-owned configuration)
- `docs/rust-migration-capability-matrix.md`
- WF-ROADMAP-0015 (Apple Silicon desktop v0.1.0 release contract)
- WF-ADR-0046 (completed Rust-only cutover)
- WF-ADR-0048 (mobile shared-core embedding)
7 changes: 7 additions & 0 deletions decisions/WF-ADR-0046-rust-only-runtime.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,3 +53,10 @@ contract and its own tests; a hidden compatibility fallback is not allowed.
The deterministic decision path remains offline, keyless, and free of delivery
dependencies (WF-ADR-0001). This decision does not broaden the credential broker,
change Automatic routing preferences, or make Apple a global default.

## Mobile amendment

WF-ADR-0047 and WF-ADR-0048 extend the Rust-only decision to native mobile:
Wayfinder extracts a pure routing library from this workspace and embeds it in
iPhone and iPad rather than running the gateway executable or recreating the
algorithm in Swift. The macOS product remains gateway-first.
137 changes: 137 additions & 0 deletions decisions/WF-ADR-0047-native-mobile-independence.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
---
schema_version: 1
id: WF-ADR-0047
type: decision
status: accepted
date: 2026-07-24
tags: [ios, ipados, native, mobile, pairing, routing, privacy]
---

# iPhone and iPad are independent Wayfinder products; pairing is optional

## Context

Wayfinder Desktop v0.1.0 established a native macOS Chat experience over a
bundled Rust gateway. A companion-only mobile app would inherit the Mac's
availability, trust, and lifecycle without giving an iPhone or iPad an
independently useful product.

Mobile devices can legitimately execute work in two domains without a Mac:

- Apple's on-device Foundation Models framework when the current device reports
it available; and
- approved hosted providers called directly with a Keychain-held API key or an
official provider account flow.

A trusted Mac can still contribute larger local models and desktop-only account
helpers, but that is an extension of the eligible destination set rather than
the foundation of mobile Wayfinder.

## Decision

Wayfinder v0.2.0 ships as a fully native iPhone and iPad application. It embeds
the authoritative deterministic routing core, owns local threads and
configuration, executes approved providers, and remains useful when every Mac
is off.

The product has three execution domains:

1. **On this device** — execution occurs on the current iPhone or iPad.
2. **Direct cloud** — the current device contacts an approved hosted provider.
3. **Paired Wayfinder host** — an optional trusted Mac or self-hosted Wayfinder
runtime contributes destinations through a bounded provider adapter.

Pairing is deferred from the v0.2.0 release gate to v0.2.1. It is represented as
a provider and never owns the mobile app's settings, credentials, conversations,
or identity.

## Product invariants

- First launch leads with standalone use. Connecting a Mac is secondary.
- Chat, routing, direct provider setup, Apple on-device execution, and thread
retention never require a Mac or a localhost gateway.
- Connecting an account or adding a key publishes eligible destinations but
never silently changes `Automatic` or rewrites a user route.
- A paired host joins a route only after explicit per-host opt-in.
- Removing or powering off a paired host cannot prevent launch, thread access,
direct cloud execution, or on-device execution.
- Existing macOS behavior remains gateway-first. Mobile work does not broaden
the macOS credential broker or replace its ChatGPT/Codex helper boundary.

## Execution-boundary truth

Every destination declares one current content-execution boundary:

- `on-device` — prompt content remains on the current iPhone or iPad;
- `local-network` — a trusted nearby Wayfinder device receives the request;
- `hosted` — a cloud provider receives the request.

Transport and execution are recorded separately for paired hosts. A request
sent to a Mac and then to ChatGPT is **hosted via the Mac**. A request sent to a
Mac-local Qwen instance is **Mac local over the local network**. Neither is
described as on-device on the phone.

The runtime enforces three user postures:

| Posture | Eligible boundaries |
| --- | --- |
| On-Device Only | `on-device` |
| Local Devices | `on-device`, `local-network` |
| Hosted Allowed | all |

No failure may cross a denied boundary. A pinned destination fails specifically
rather than silently switching.

## Platform experience

After onboarding, iPhone launches into a `TabView` with separate navigation
stacks for Chat, Threads, Destinations, and Settings. iPad uses an adaptive
`NavigationSplitView` with transcript and composer as the primary surface and
an optional route inspector.

The macOS window hierarchy is not copied into a smaller display. Standard Apple
navigation, forms, lists, sheets, typography, accessibility, and platform
materials take precedence over custom chrome.

## Consequences

### Positive

- Mobile Wayfinder has a clear value proposition even with no Mac or signal.
- A Mac can add capabilities without becoming a synchronization or identity
authority.
- Privacy language follows actual prompt movement.
- The same deterministic product signature applies across Apple devices.

### Negative

- iOS must own provider execution, credentials, persistence, and lifecycle
behavior rather than reusing the desktop HTTP process shape.
- Direct providers may require native Swift adapters even when desktop delivery
remains implemented in Rust.
- Pairing requires a separate authenticated protocol and revocation model.

## Rejected alternatives

### Companion-only iOS client

Rejected because onboarding, routing, Chat, and retention would all fail when a
Mac is unavailable.

### Internal localhost gateway on iOS

Rejected because it preserves a desktop deployment shape rather than a mobile
product boundary. iOS embeds the routing library and calls provider adapters
directly.

### Mac as the mobile configuration authority

Rejected because pairing must remain optional and revocable. Mobile
configuration and threads are locally owned.

## Related

- WF-ADR-0048 — shared routing core and Apple embedding
- WF-DESIGN-0019 — provider, authentication, and credential contract
- WF-ROADMAP-0016 — native mobile v0.2 delivery
- `docs/apple-platform-capability-matrix.md`
147 changes: 147 additions & 0 deletions decisions/WF-ADR-0048-shared-routing-core-apple-embedding.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
---
schema_version: 1
id: WF-ADR-0048
type: decision
status: accepted-for-phase-0-spikes
date: 2026-07-24
tags: [rust, swift, ios, ipados, ffi, routing, providers, persistence]
---

# Share one pure Rust routing core and embed it natively on Apple platforms

## Context

WF-ADR-0046 made Rust Wayfinder's sole router and gateway runtime. The current
workspace still combines pure deterministic routing with host, HTTP-server,
provider, service, and macOS integration responsibilities.

iOS cannot run the macOS helper topology and should not launch an internal
loopback server merely to preserve it. Reimplementing score, thresholds,
exclusions, tie-breaks, or receipts in Swift would create a second routing
authority.

## Decision

Extract a platform-neutral Rust library that owns all authoritative route
planning. The gateway and the mobile bridge consume that same library and
shared fixtures.

Target ownership:

```text
rust/crates/
wayfinder-routing-core/ pure deterministic planning and receipts
wayfinder-runtime-contracts/ requests, destinations, errors, usage
wayfinder-provider-core/ portable provider orchestration where proven
wayfinder-apple-ffi/ generated Swift-facing bridge
wayfinder-gateway/ Axum/server host consuming the same core
```

`wayfinder-routing-core` performs no filesystem, Keychain, process, UI,
HTTP-server, Apple-framework, or provider-secret work. Eligibility inputs are
typed destination snapshots supplied by the host runtime. It owns:

- compatibility exclusions and stable reason codes;
- score and threshold semantics;
- tier and ordered-route selection;
- stable tie-breaks and fallback planning;
- route explanations and compact receipts.

The mobile app calls the library in-process. The macOS product may remain a
thin client over its bundled gateway for v0.2.

## Bridge contract

Phase 0 tests generated UniFFI Swift bindings first. A narrow generated C ABI is
the fallback only if UniFFI fails measured device, simulator, concurrency,
cancellation, binary-size, or maintenance gates.

The runtime bridge remains small:

```swift
protocol WayfinderRoutingEngine: Sendable {
func validate(configuration: RoutingConfiguration) async throws
func score(_ request: RoutingRequest) async throws -> ComplexityResult
func plan(
_ request: RoutingRequest,
candidates: [DestinationSnapshot]
) async throws -> RoutePlan
func explain(_ plan: RoutePlan) async throws -> RouteExplanation
}
```

Do not hand-maintain a broad JSON-over-FFI runtime. JSON remains the canonical
portable fixture and debugging format. Provider streaming belongs to the
execution layer, not the pure scorer.

## Provider execution placement gate

The routing-core language is decided; provider execution placement is not.
Phase 0 compares:

1. shared Rust HTTP execution with a narrow Swift credential callback; and
2. Rust route planning with Swift `URLSession` provider execution.

The selected v0.2 path must demonstrate:

- correct cancellation before and during streaming;
- fragmented SSE and terminal-event behavior;
- system TLS and ATS compatibility;
- bounded memory and event queues;
- usable error classification;
- acceptable binary size and launch cost;
- no secret crossing an unnecessary language boundary.

Apple frameworks, Authentication Services, Keychain, and Apple on-device model
execution remain in Swift regardless of this result. A Swift provider adapter
is acceptable when it implements the shared contracts and fixtures.

## Accepted mobile foundation choices

- **Deployment floor:** iOS 18 and iPadOS 18. Foundation Models remains
separately availability-gated to the OS/device states that actually support
it.
- **Route configuration:** typed native data with a versioned export/import
schema; mobile does not edit desktop TOML.
- **Provider catalog:** executable adapters are built in and reviewed. Remote
signed metadata may update labels and model catalogs only after a separate
schema/signature implementation.
- **Credential backup:** provider secrets use device-only Keychain
accessibility by default and are not silently synchronized.
- **Mac adoption:** shared Apple packages are introduced incrementally after
the mobile seams are proven; the existing macOS target is not moved first.

## Decisions still requiring measured Phase 0 artifacts

| Decision | Required artifact | Gate |
| --- | --- | --- |
| UniFFI vs generated C ABI | simulator and physical-device bridge spike | typed call, errors, concurrency, lifetime, size |
| Rust HTTP vs Swift `URLSession` | two execution spikes | streaming, cancellation, TLS, memory, size |
| SwiftData vs SQLite | persistence prototype | migration, deterministic tests, export/delete |

These are bounded choices inside the accepted architecture. None may change
mobile independence or introduce a Swift routing implementation.

## Parity and release gates

- Gateway and embedded calls consume the same golden corpus.
- Serialized decisions and reason codes are byte-identical where serialization
applies.
- Simulator and physical-device architecture builds are required.
- Malformed/oversized input, version skew, concurrency, callback release, and
cancellation races fail safely.
- Core extraction lands without provider or UI behavior changes.
- XCFramework/bridge work lands separately from the extraction.

## Consequences

The router remains one inspectable authority while each Apple host can use the
native lifecycle and security APIs appropriate to it. The cost is an explicit
FFI build/test lane and shared-contract discipline across Swift and Rust.

## Related

- WF-ADR-0046 — Rust-only runtime
- WF-ADR-0047 — native mobile independence
- WF-DESIGN-0019 — provider and authentication framework
- WF-ROADMAP-0016 — mobile delivery sequence
Loading
Loading