rename: the apps say Inkwell — web, desktop, Android and server strings
Android / Build, or is the channel already serving this? (push) Successful in 4s
CI & Build / Build now, or wait for Android? (push) Successful in 4s
CI & Build / Python lint (push) Successful in 2s
CI & Build / TypeScript typecheck (push) Successful in 11s
Desktop (Tauri) / Build, or is the channel already serving this? (push) Successful in 3s
CI & Build / Python tests (push) Successful in 15s
CI & Build / integration (push) Successful in 58s
CI & Build / Build & push image (push) Skipped
Desktop (Tauri) / Windows installer (cross-compiled) (push) Successful in 4m17s
Desktop (Tauri) / Tauri desktop (Linux) (push) Successful in 7m50s
Desktop (Tauri) / Update manifest (push) Successful in 5s
Android / Kotlin + Rust (APK) (push) Successful in 11m37s

ThoughtSync is renamed Inkwell ("Fabled Inkwell" in full; Scribe note 5071).
This is step 1 of milestone 481: every string a person reads in the running
apps. Identities installed clients depend on are deliberately untouched — the
Tauri productName (it derives the .deb Package: field), identifier and binary
name, applicationId, X-ThoughtSync-* headers, the export's app marker, env vars,
module and crate names.

- web: title, PWA manifest (name "Fabled Inkwell", short_name "Inkwell"),
  offline page, icon labels, build labels, prompts, notification title
- server: site_name default, import error, link-preview User-Agent
- 0030: a stored site_name of exactly the old default follows the rename. The
  Settings page saves every key, so most servers hold "ThoughtSync" without an
  admin ever having chosen it; a name they typed is left alone
- desktop: window title, default device name, local-mode site name, log line
- android: app_name and the strings that name the app
- core: probe and compatibility messages

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-06 13:16:14 -04:00
co-authored by Claude Opus 5.5
parent fb469ed73a
commit f806e35d41
30 changed files with 108 additions and 57 deletions
+5 -5
View File
@@ -1,4 +1,4 @@
//! HTTP transport to a ThoughtSync server.
//! HTTP transport to an Inkwell server.
//!
//! Covers the compatibility handshake (M10.6) and device-token auth (M10.7a). The
//! engine that moves notes — push, pull, cursor — grows on top of the same client,
@@ -151,8 +151,8 @@ fn unexpected_status(base_url: &str, status: StatusCode) -> String {
/// Ask a server who it is and whether we can sync with it.
///
/// `Err` means we never got a usable answer (bad address, unreachable, not a
/// ThoughtSync server). A server that answers but is *incompatible* comes back `Ok`
/// `Err` means we never got a usable answer (bad address, unreachable, not an
/// Inkwell server). A server that answers but is *incompatible* comes back `Ok`
/// with a verdict — that distinction matters, because the two need very different
/// messages: one is "check what you typed", the other is "update something".
pub async fn probe(raw_url: &str) -> Result<ProbeResult, String> {
@@ -170,12 +170,12 @@ pub async fn probe(raw_url: &str) -> Result<ProbeResult, String> {
return Err(unexpected_status(&base_url, status));
}
// Something answered 200 that isn't a ThoughtSync server (a router login page, a
// Something answered 200 that isn't an Inkwell server (a router login page, a
// captive portal). Report the address, not the parse error, which would mean
// nothing to the person reading it.
let server: ServerInfo = response.json().await.map_err(|_| {
format!(
"{base_url} responded, but not with ThoughtSync's configuration. \
"{base_url} responded, but not with Inkwell's configuration. \
Is that the right address?"
)
})?;
+4 -4
View File
@@ -146,7 +146,7 @@ pub fn evaluate(info: &ServerInfo) -> Compatibility {
return incompatible(
&format!(
"This server requires client protocol v{floor} or newer; this app \
speaks v{CLIENT_PROTOCOL_VERSION}. Update ThoughtSync."
speaks v{CLIENT_PROTOCOL_VERSION}. Update Inkwell."
),
true,
);
@@ -234,7 +234,7 @@ pub fn normalize_base_url(raw: &str) -> Option<String> {
let with_scheme = match trimmed.split_once("://") {
Some((scheme, rest)) => {
// Anything that isn't HTTP(S) (ftp://, file://, a stray "foo://") can't
// be a ThoughtSync server; reject rather than fail confusingly later.
// be an Inkwell server; reject rather than fail confusingly later.
let scheme = scheme.to_ascii_lowercase();
if scheme != "http" && scheme != "https" {
return None;
@@ -259,7 +259,7 @@ mod tests {
/// A server matching this client exactly, which each test then degrades.
fn current_server() -> ServerInfo {
ServerInfo {
site_name: Some("ThoughtSync".into()),
site_name: Some("Inkwell".into()),
version: Some("0.1.0".into()),
sync_protocol_version: Some(CLIENT_PROTOCOL_VERSION),
min_client_protocol_version: Some(CLIENT_PROTOCOL_VERSION),
@@ -282,7 +282,7 @@ mod tests {
fn server_without_protocol_fields_is_too_old() {
// A pre-M10.6 server: /api/config parses, but carries no protocol block.
let info = ServerInfo {
site_name: Some("ThoughtSync".into()),
site_name: Some("Inkwell".into()),
version: Some("0.0.9".into()),
..Default::default()
};