refactor: rename project uatu -> sanderling (#24)

* refactor: rename Go module path uatu -> sanderling

Module path github.com/priyanshujain/uatu -> github.com/priyanshujain/sanderling,
including all imports and the proto go_package option. Generated .pb.go files
rewritten in-place; safe to regenerate with protoc later.

* chore(proto): regenerate driverpb after module path rename

The previous sed-based module rename corrupted the embedded descriptor
byte lengths. buf generate rewrites them cleanly.

* refactor: rename CLI binary uatu -> sanderling

Updates Makefile target + UATU_BIN var, .goreleaser project/build IDs,
.gitignore comment, and all user-facing strings in the CLI help text,
error messages, and tests. Binary is now bin/sanderling.

* refactor(sdk): rename Kotlin package dev.uatu.sdk -> dev.sanderling.sdk

Moves sdk/android/src/{main,test}/kotlin/dev/uatu -> dev/sanderling and
rewrites package declarations, imports, and the Gradle namespace. Class
names (Uatu, UatuRuntime) are renamed in a follow-up commit.

* refactor(sidecar): rename Kotlin package dev.uatu.sidecar -> dev.sanderling.sidecar

Moves sidecar/src/{main,test}/kotlin/dev/uatu -> dev/sanderling and
rewrites package declarations, imports, and the application mainClass.

* refactor: rename Uatu API surface -> Sanderling

- Kotlin: Uatu -> Sanderling, UatuRuntime -> SanderlingRuntime (+ files).
- JS host binding: globalThis.__uatu__ -> __sanderling__ (Go verifier,
  spec-api, tests).
- TS interface: UatuRuntime -> SanderlingRuntime; internal tags
  __uatuFormula / __uatuActionGenerator -> __sanderling* variants.
- Go trace: UatuVersion field + uatu_version JSON tag renamed.
- Socket naming: uatu-agent / uatu-agent-reader -> sanderling-agent*.
- Sample app, docs, inline-JS test strings updated to match.

* refactor(examples): rename examples/folio/uatu -> examples/folio/sanderling

Renames the example spec directory; updates justfile paths + gitignore
entries accordingly. Package.json name/description and @uatu/spec
dependency are renamed in the npm + docs commits.

* chore(build): rename gradle property + rootProject.name uatu -> sanderling

- Renames the uatu.version gradle property and all its -P references in
  Makefile, build.gradle.kts files, and .github/workflows/release.yml.
- settings.gradle.kts rootProject.name = "sanderling".
- Renames .env.local.example header + release-cli workflow job name.

* refactor(proto): rename proto package uatu.driver.v1 -> sanderling.driver.v1

Updates the proto package and java_package, regenerates driver.pb.go +
driver_grpc.pb.go, rewrites Kotlin imports and the gRPC ServiceName
assertion in driver_test.go.

* refactor: rename npm package @uatu/spec -> @sanderling/spec

Renames package name in pkg/spec-api/package.json + lockfile, all
consumer imports (examples/folio spec, testdata, verifier tests), the
esbuild alias in cmd/sanderling/test_run.go, and related doc references.

* docs: rename uatu -> sanderling in README, docs, and URLs

- README + docs/{manual,development}/*: narrative + GitHub + Pages URLs.
- POM + npm package.json repo/homepage/bugs URLs.
- .gitignore + embed_stub + Makefile-comment references updated to
  'make sanderling'.
- Minor narrative comments in cmd/sanderling/test_run.go and
  internal/inspect/server.go.

* refactor: rename remaining internal uatu strings -> sanderling

- SANDERLING_TEST_PHONE/OTP env vars (cmd + bundler tests).
- sanderling-sidecar runtime tmp dir + extracted JAR filename.
- Inspect web UI: @sanderling/inspect-web package, title, theme
  localStorage key, RunList empty-state copy, uatu_version TS field.
- Sample app storage key sanderling.ledger.v1.
- Test data: sanderling_test AVD name + com.example.sanderling_test.
- Release docs tarball name template.
This commit is contained in:
pj authored and GitHub committed 2026-04-21 11:57:49 +07:00
1 parent 13bb2feb82
commit 8ccf95c1cf
111 files changed
+514 -514

No files matched your search

+2 -2
View File
@@ -6,7 +6,7 @@ iosApp/build/
iosApp/iosApp.xcodeproj/
iosApp/iosApp.xcodeproj/**
.DS_Store
uatu/node_modules/
uatu/runs/
sanderling/node_modules/
sanderling/runs/
.playwright-mcp/
web-*.png
+9 -9
View File
@@ -3,14 +3,14 @@
A minimal Kotlin Multiplatform personal-ledger app: login with demo
credentials, create accounts, add credits and debits. Shared UI across
Android, iOS, and Web via Compose Multiplatform. Doubles as the example
uatu runs its property-based specs against.
sanderling runs its property-based specs against.
## Stack
- Kotlin Multiplatform + Compose Multiplatform (shared UI)
- kotlinx.serialization for file-backed persistence
- kotlinx.coroutines for state flows
- uatu `sdk-android` for harness integration on Android
- sanderling `sdk-android` for harness integration on Android
## Prerequisites
@@ -46,13 +46,13 @@ email: [email protected]
password: ledger123
```
## Run a uatu test (Android)
## Run a sanderling test (Android)
```sh
just test
```
If no device is connected, uatu boots the single AVD it finds. With multiple
If no device is connected, sanderling boots the single AVD it finds. With multiple
AVDs, pick one:
```sh
@@ -66,13 +66,13 @@ AVD=Pixel_7
DURATION=5m
```
Traces land in `./uatu/runs/<timestamp>/`.
Traces land in `./sanderling/runs/<timestamp>/`.
## How it connects to uatu
## How it connects to sanderling
- `composeApp/src/androidMain/.../FolioApplication.kt` calls `Uatu.start(this)`
- `composeApp/src/androidMain/.../FolioApplication.kt` calls `Sanderling.start(this)`
and registers snapshot extractors (`logged_in`, `account_count`,
`total_balance`, `route`)
- `uatu/spec.ts` imports `@uatu/spec`, reads those snapshots, asserts
- `sanderling/spec.ts` imports `@sanderling/spec`, reads those snapshots, asserts
properties, and weights the actions the fuzzer picks from
- `just test` invokes `uatu test` against the installed APK
- `just test` invokes `sanderling test` against the installed APK
+3 -3
View File
@@ -10,7 +10,7 @@ plugins {
id("app.cash.sqldelight")
}
val uatuVersion = findProperty("uatu.version") as String? ?: "0.0.0-dev"
val sanderlingVersion = findProperty("sanderling.version") as String? ?: "0.0.0-dev"
val sqldelightVersion = "2.3.2"
kotlin {
@@ -83,7 +83,7 @@ kotlin {
androidMain.dependencies {
implementation("androidx.activity:activity-compose:1.13.0")
implementation("app.cash.sqldelight:android-driver:$sqldelightVersion")
implementation("io.github.priyanshujain:sdk-android:$uatuVersion")
implementation("io.github.priyanshujain:sdk-android:$sanderlingVersion")
}
iosMain.dependencies {
@@ -101,7 +101,7 @@ android {
minSdk = 24
targetSdk = 36
versionCode = 1
versionName = uatuVersion
versionName = sanderlingVersion
}
compileOptions {
@@ -11,18 +11,18 @@ import app.folio.navigation.Navigator
import app.folio.navigation.Route
import app.folio.platform.balanceOf
import app.folio.platform.signedAmount
import dev.uatu.sdk.Uatu
import dev.sanderling.sdk.Sanderling
class FolioApplication : Application() {
override fun onCreate() {
super.onCreate()
AndroidLedgerContext.context = applicationContext
Repository.init()
Uatu.start(this)
Uatu.extract("logged_in") { Repository.session.value != null }
Uatu.extract("account_count") { Repository.accounts.value.size }
Uatu.extract("total_balance") { balanceOf(Repository.transactions.value) }
Uatu.extract("route") {
Sanderling.start(this)
Sanderling.extract("logged_in") { Repository.session.value != null }
Sanderling.extract("account_count") { Repository.accounts.value.size }
Sanderling.extract("total_balance") { balanceOf(Repository.transactions.value) }
Sanderling.extract("route") {
when (Navigator.current.value) {
Route.Login -> "login"
Route.Home -> "home"
@@ -31,10 +31,10 @@ class FolioApplication : Application() {
is Route.AddTransaction -> "add-transaction"
}
}
Uatu.extract("auth_status") {
Sanderling.extract("auth_status") {
if (Repository.session.value != null) "logged-in" else "logged-out"
}
Uatu.extract("accounts") {
Sanderling.extract("accounts") {
val txns = Repository.transactions.value
Repository.accounts.value.map { a ->
val rows = txns.filter { it.accountId == a.id }
@@ -46,14 +46,14 @@ class FolioApplication : Application() {
)
}
}
Uatu.extract("active_account_id") {
Sanderling.extract("active_account_id") {
when (val r = Navigator.current.value) {
is Route.Ledger -> r.accountId
is Route.AddTransaction -> r.accountId
else -> null
}
}
Uatu.extract("ledger_rows") {
Sanderling.extract("ledger_rows") {
val active = when (val r = Navigator.current.value) {
is Route.Ledger -> r.accountId
is Route.AddTransaction -> r.accountId
@@ -72,7 +72,7 @@ class FolioApplication : Application() {
)
}
}
Uatu.extract("ledger_balance") {
Sanderling.extract("ledger_balance") {
val active = when (val r = Navigator.current.value) {
is Route.Ledger -> r.accountId
is Route.AddTransaction -> r.accountId
@@ -81,13 +81,13 @@ class FolioApplication : Application() {
if (active == null) 0L
else balanceOf(Repository.transactions.value.filter { it.accountId == active })
}
Uatu.extract("focused_input") { FocusTracker.current.value }
Uatu.extract("txn_form_type") { AddTransactionUiState.txnFormType.value }
Uatu.extract("txn_form_account_id") {
Sanderling.extract("focused_input") { FocusTracker.current.value }
Sanderling.extract("txn_form_type") { AddTransactionUiState.txnFormType.value }
Sanderling.extract("txn_form_account_id") {
(Navigator.current.value as? Route.AddTransaction)?.accountId
}
Uatu.extract("login_error") { LoginUiState.loginError.value }
Uatu.extract("add_account_error") { AddAccountUiState.addAccountError.value }
Uatu.extract("txn_error") { AddTransactionUiState.txnError.value }
Sanderling.extract("login_error") { LoginUiState.loginError.value }
Sanderling.extract("add_account_error") { AddAccountUiState.addAccountError.value }
Sanderling.extract("txn_error") { AddTransactionUiState.txnError.value }
}
}
@@ -5,7 +5,7 @@ import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.browser.localStorage
private const val STORAGE_KEY = "uatu.ledger.v1"
private const val STORAGE_KEY = "sanderling.ledger.v1"
class WebLedgerStore : LedgerStore {
private val _accounts = MutableStateFlow<List<Account>>(emptyList())
+3 -3
View File
@@ -5,6 +5,6 @@ kotlin.code.style=official
android.useAndroidX=true
android.nonTransitiveRClass=true
# Pin the uatu SDK version consumed by this app. Override with
# `-Puatu.version=<version>`.
uatu.version=0.0.0-dev
# Pin the sanderling SDK version consumed by this app. Override with
# `-Psanderling.version=<version>`.
sanderling.version=0.0.0-dev
+8 -8
View File
@@ -1,11 +1,11 @@
set shell := ["bash", "-cu"]
set dotenv-load := true
uatu := env_var_or_default("UATU", "uatu")
avd := env_var_or_default("AVD", "")
duration := env_var_or_default("DURATION", "1m")
seed := env_var_or_default("SEED", "0")
output := env_var_or_default("OUTPUT", justfile_directory() / "uatu" / "runs")
sanderling := env_var_or_default("SANDERLING", "sanderling")
avd := env_var_or_default("AVD", "")
duration := env_var_or_default("DURATION", "1m")
seed := env_var_or_default("SEED", "0")
output := env_var_or_default("OUTPUT", justfile_directory() / "sanderling" / "runs")
ios_device := env_var_or_default("IOS_DEVICE", "iPhone 17 Pro")
default:
@@ -81,7 +81,7 @@ ios:
xcrun simctl install booted iosApp/build/Build/Products/Debug-iphonesimulator/iosApp.app
xcrun simctl launch booted app.folio
# Run 'uatu test' against the folio app. Uses a connected device if one is
# Run 'sanderling test' against the folio app. Uses a connected device if one is
# online, otherwise boots AVD=<name> if provided.
test:
#!/usr/bin/env bash
@@ -90,8 +90,8 @@ test:
if [[ -n "{{avd}}" ]]; then
avd_flag=(--avd "{{avd}}")
fi
"{{uatu}}" test \
--spec "{{justfile_directory()}}/uatu/spec.ts" \
"{{sanderling}}" test \
--spec "{{justfile_directory()}}/sanderling/spec.ts" \
--bundle-id app.folio \
"${avd_flag[@]}" \
--duration "{{duration}}" \
@@ -6,12 +6,12 @@
"": {
"name": "folio",
"devDependencies": {
"@uatu/spec": "next"
"@sanderling/spec": "next"
}
},
"node_modules/@uatu/spec": {
"node_modules/@sanderling/spec": {
"version": "0.0.1-rc3",
"resolved": "https://registry.npmjs.org/@uatu/spec/-/spec-0.0.1-rc3.tgz",
"resolved": "https://registry.npmjs.org/@sanderling/spec/-/spec-0.0.1-rc3.tgz",
"integrity": "sha512-mCayssOqM2wfzrQDnFGE8FAlUlDzBl1fx2L/MLDIuPrQHBMlUC350xBB8Z7I/DYI98eCWJMqjtw3iU6yVWKtIQ==",
"dev": true,
"license": "Apache-2.0"
+8
View File
@@ -0,0 +1,8 @@
{
"name": "folio",
"private": true,
"description": "Minimal sanderling integration example.",
"devDependencies": {
"@sanderling/spec": "next"
}
}
@@ -13,8 +13,8 @@ import {
taps,
waitOnce,
weighted,
} from "@uatu/spec";
import { noUncaughtExceptions } from "@uatu/spec/defaults/properties";
} from "@sanderling/spec";
import { noUncaughtExceptions } from "@sanderling/spec/defaults/properties";
interface AccountSnapshot {
id: string;
-8
View File
@@ -1,8 +0,0 @@
{
"name": "folio",
"private": true,
"description": "Minimal uatu integration example.",
"devDependencies": {
"@uatu/spec": "next"
}
}