You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
An image's open no longer holds a read of a file it is making. Persistence notes at construction whether its file exists; until the
writer's first open, a read of a file that did not answers from memory
alone, since the file holds nothing yet, while a file that did is
waited for, or opened by the read, as before, so a warm start's first
frame still has the list. On the Pixel 9 the sample's cold start with an
empty store slept 23 ms of its first composition behind the file's
creation, written through to flash; its first frame now comes 26 ms
sooner, level with the Apollo Kotlin twin's, and the list 24 ms sooner,
255 ms from the launch against the twin's 327 (BENCHMARKS.md,
9 October).
A response is read where it is parsed. The Kotlin environment awaits the
transport's payload on the ingest dispatcher and the Swift environment on
a concurrent task, so the store's thread is entered once, for the commit,
rather than first when the bytes arrive: a response that lands while the
main thread draws a frame is parsed before the frame ends, not after it.
On the Pixel 9 the sample's first page, 686 KB, is parsed and normalized
in about 5 ms of a worker's time, inside the cold start's first frame.
The Kotlin twin of the exchange, kotlin/samples/exchange: an Exchange
over baton.Transport in common Kotlin, the wrapper a production
endpoint needs and the library does not ship. Credentials are the base
transport's, read per attempt; a 401 is replayed once after challenged(); a query or a subscription refused with a 5xx or by a lost
connection is sent again with a doubling, jittered wait, as many times as attempts allows and never past deadline; a mutation is never sent
twice; a stream that delivered is not sent again. The Kotlin GitHub
sample sends through it, as the Swift one sends through examples/Exchange, and docs/recipes/exchange.md has its Kotlin half,
quoting the compiled loop. ExchangeTests in the runtime's JVM tests
prove it over baton-testing's doubles and a loopback server: the
replayed challenge carries the renewed token, a second challenge fails,
a 503 then a 200 is sent twice, the attempts bound the sends, a deadline
that expires during the backoff fails at once, a mutation refused with a
503 is sent once, a cancelled consumer ends the held attempt, an
environment over an exchange reads ready after a retry, and a held
mutation's optimistic layer stands through a retry beside it.
The Android sample tells the environment the process's lifecycle: Activation in kotlin/samples/android observes ProcessLifecycleOwner,
sets isActive false when the last activity stops and true when the
first starts, and calls revalidate() on the return; the view model
closes it before the environment ends. docs/recipes/views.md quotes it
as the Kotlin half of the lifecycle section of docs/recipes/uikit.md,
which now links it.
Kotlin's TransportError carries the connection's own failure as its cause when there was no response: HttpTransport, OkHttpTransport
and the socket clients pass the exception they caught, so a wrapper can
tell a connection that was lost or timed out, which a retry may mend,
from a request the transport could not make, which would repeat. A
status 0 with no cause is still the latter.
A Baton app is a client of the server of fate's GraphQL template as it
ships: responses recorded from it under spec/fate/ prove its posts
connection, node(id:), postAdd with @prependNode and the
graphql-sse stream of fateLiveNode, whose JSON payload lands at the
subscription root and updates no record.
The Kotlin runtime runs spec/relay/ and spec/fate/ as the Swift
runtime does, so a fixture under either directory now holds both
runtimes, as docs/principles/two-runtimes-one-compiler.md asks. jvmRelayTest compiles spec/relay/sources with spec/relay/baton.json
through the Gradle plugin, which now names the Kotlin package, and runs
every case and script but the unsupported ones under the same statuses as BatonRelayTests: the responses committed as payloads into a bare store,
the dump compared with Relay's, a check step's answer compared, and each reads row read by walking the generated lens, with throws and result rows lifted as the Swift target's generated reads lift them; a
case with a status runs as a known issue that fails once it passes. jvmFateTest proves the fate recordings through the Kotlin host FateDocuments.kt, the twin of FateDocuments.swift. Each harness runs
in a JVM of its own, since the registry numbers types by name per process
and Relay's test schema and fate's both declare a User. CI runs both.
The Kotlin Rick and Morty sample has the episode screen, an episode's
cast, and the location screen, a location's residents, the Swift
documents verbatim; a character's episodes and its origin and last known
location open them, and a cast member or a resident opens the character,
through a stack of destinations the desktop's pane and the Android app
keep, which Back pops and a recreation restores.
The Kotlin GitHub sample has the triage screen: the viewer's assigned
and created searches over the SearchResultItem union with @alias
spreads, an issue row that carries its repository's name as the Swift
row does, a pull request row, a refresh of the searches and a refresh of
the rows through nodes(ids:), behind a switch in the bar beside the
repository. Its tests show both searches, the refresh asking for the
rows' ids in order, and a row selecting its issue.
The Kotlin store's thread check says the violation, "the store is used
off the thread that made it", where it stated the rule.
The Kotlin runtime's floors are recorded, docs/decisions/kotlin-floors.md: Android 6 (API 23), the lowest the
Compose runtime and AndroidX SQLite allow; Java 21 class files on the
JVM and on Android, the JDK the release builds with; and the current
Kotlin, 2.4.20. The runtime's four published modules pin the JDK 21
toolchain in their builds, where the JVM target had followed whichever
JDK ran the build: a local build on JDK 26 wrote Java 26 class files
where the release wrote Java 21.
The recipes say Kotlin where they said Swift alone: porting-from-relay.md has a Kotlin column beside the Swift one for
every Relay word, discover-once.md the Kotlin twin of its refresh, derived-state.md the snapshotFlow shape and a link to views.md,
which links back. The Gradle recipe and the Kotlin README say that
Baton needs no R8 or ProGuard rules and ships none, since the runtime,
its modules and the generated Kotlin use no reflection, no serialization
and no lookup by name.
docs/terminology.md has its Kotlin part on every entry that has a
Swift one, as its preamble promised: the thirty-four that lacked one,
from Spread and Required to Pagination and the edge directives, say how
the Kotlin runtime and its generated Kotlin spell the concept and what
differs from Swift, a getter that throws, a Result for @catch, a Hold, a Flow, a suspend function. docs/recipes/testing.md has
its Kotlin half: the test dispatcher an environment takes outside a
composition, and each of the Swift snippets beside its Kotlin twin over baton-testing.
docs/comparison.md is current at 0.14: the at-a-glance table carries
the Kotlin runtime's numbers on the Pixel 9 beside the Swift runtime's on
the Mac, the Apollo Kotlin head-to-head is a table of its own, the cons
say what the Kotlin runtime is and is not rather than that there is none,
the image con no longer names a row the writer replaced, which 0.8.0
fixed, and identity says what baton.json configures. kotlin/README.md
says baton-testing builds for Android, as it has since 0.14.0.
docs/recipes/agents.md, the page a coding agent reads first when it
integrates Baton into an app: the reading order, the shape of a screen
in Swift and Kotlin, what never to write, the compiler's diagnostics and
what to run, and a review checklist. The README links it from "Try it
on your app" and "Written by people, or by models".
docs/why-graphql.md, for iOS and Android engineers who build on REST:
the plumbing a REST screen needs, what GraphQL removes of it, what only
Relay's fragments and store remove, what Baton adds, what stays the
app's, and what it costs. The README's first paragraph links it.