On this page

Architecture

Skryba is one Rust process with three external boundaries — Brama, the detector APIs, and its fleet database — and one local binary it spawns: ster, which owns every weight in the product. It keeps no database file of its own.

input
  ├─ draft import ────────> fleet database: drafts
  ├─ style / language ────> fleet database: choices (the catalog)
  ├─ score ───────────────> detector ensemble ──> fleet database: scores
  ├─ rewrite/train ───────> fleet database: choices (resolve the profile)
  │                        Brama generator
  │                        Brama quality judge
  │                        detector ensemble ──> fleet database: scores
  ├─ rewrite --generator local
  │                        spawn `ster generate` (adapter attached) ──> candidate text
  │                        Brama quality judge
  │                        detector ensemble ──> fleet database: scores
  ├─ benchmark ───────────> fleet database: choices + Brama generator + quality judge
  ├─ writing-style ───────> fleet database: passages, preferences
  │                         ├─ export ──> Ster export file
  │                         └─ train ───> Ster export file
  │                                       ──> spawn `ster tune sft|dpo` ──> LoRA adapter
  └─ database check|drop-schema

The fleet database is stado database resolve skryba: Stado names the credential item skryba-database, Skarbiec hands its pooler_url and ca_certificate to the skryba-database-client bearer, and Skryba connects over TLS verified against that CA (database).

The writing-style branch calls no model and no detector: add, keep, export and status read the person's own files and write their own rows and their own export, and train writes the export and then spawns a process. The process it spawns is another matter — Ster resolves the checkpoint and fetches it from the Hugging Face hub when it is not already cached, so train and rewrite --generator local reach a network through Ster even though no Skryba code does. The same holds for model credentials: Skryba reads none of its own here, and Ster reads Hugging Face's own cached token file ($HF_HOME/token, by default ~/.cache/huggingface/token) when it fetches a private repository.

What Skryba owns

  • CLI command parsing and local validation;
  • detector credentials, provider adapters, selection, normalization, caller-declared request pacing, and cache namespacing; detector and Brama calls are not retried automatically;
  • chunking, candidate generation instructions, quality gating, source fallback, and least-detectable selection;
  • the style and language catalog: the names a rewrite may require and the instruction each stands for, seeded once and then changed only by skryba style and skryba language;
  • the version-1 native GRPO policy and its atomic JSON persistence;
  • curated-corpus checksum and word-count verification;
  • the source drafts: whole-file UTF-8 validation, source identity, immutable version retention, and exact text supplied to Score or Rewrite;
  • the writing-style rows: ingesting the person's prose, recording the pairs they resolved, writing the two files Ster trains on, and driving the ster run that turns one of them into an adapter — locating the binary, building its argv, and reporting the command it ran;
  • the tables of its schema in the fleet database, created on first use.

What Skryba does not own

  • model serving, provider subscriptions, or direct model credentials: Brama owns inference routing;
  • the database, its placement and its credential: Stado's database plane declares skryba, Supabase hosts it, Skarbiec holds the credential item;
  • local weights and the gradient: Ster maps the checkpoint, runs the passes, writes the LoRA adapter, and generates from it. Skryba links no tensor library and maps no checkpoint in its own process; it writes the training file and drives the installed ster binary — writing-style train runs ster tune, and rewrite --generator local runs ster generate (training boundary);
  • detector vendors' models or verdict semantics beyond normalization;
  • commissioned human work: paying a person to rewrite, verify, or record text runs on the HandToHuman marketplace ledger (handtohuman market), never through Skryba;
  • desktop workflow interpretation: Skryba Desktop is a process launcher and view over this CLI.

Module boundaries

Module Responsibility
src/main.rs, src/cli/ CLI schema, dispatch, input/output files, database check and drop-schema
src/app/fleet/ resolving the fleet database through Stado and Skarbiec, the TLS connection, the schema, unnamed statements for the transaction pooler
src/app/drafts/ validated source-document import and draft retention
src/app/profiles/ the style and language catalog: seeds, table, validation, profile resolution
src/app/brama/ authenticated /v1/chat/completions client
src/text/detectors/ four provider clients, probability normalization, rate limiting, score cache
src/text/humanizer/ chunking, candidate generation, quality gate, selection
src/text/quality.rs judge prompt, schema parsing, weakest-dimension score, pass rule
src/text/style/ the resolved profile and the instruction block the generator and judge receive
src/text/writing_style/ the writer's own text: passages and preferences, prose ingestion, Ster export shapes
src/learning/policy.rs strategies, sampling, GRPO/Adam update, policy persistence
src/learning/training.rs training data readers and training loop
src/learning/benchmark/ curated-corpus verification and docs-quality benchmark
src/learning/ster/ locating the installed ster binary, ster tune argv and streaming, ster generate as a rewrite generator
release/docs-paths.sh the docs-paths release gate: every src/…/*.rs file this documentation names must be a file of the tree being released

.wisent-release.json pins this documentation corpus (src/content/docs.json of skryba-landing at one committed revision) as the release input landing-docs, and declares the docs-paths gate as a lint gate reading it, so a Skryba release build or installation refuses a tree whose files the documentation still names after they moved, listing each missing path. A gate run without the input staged is refused, never skipped. After the pages change, the new revision is pinned with stado release catalog pin-input --name landing-docs --source <skryba-landing> --revision <REV> --path src/content/docs.json <skryba>.

Trust boundaries

Input and local files

Text, policies, and corpora are untrusted caller input. CLI paths expand a leading ~ from the home environment or user database; if neither names a home, the command refuses that path with the cause instead of panicking or writing under a literal ~. Paths without a leading ~ are unchanged. Policy and corpus readers validate structure before use.

Brama

The source and candidate text cross the Brama boundary for generation or judging. BRAMA_TOKEN_ROLE=ROLE#FIELD selects the client credential resolved through Stado; optional agent authentication pairs SKRYBA_AGENT_ID with SKRYBA_AGENT_AUTH_SECRET_ROLE. An explicitly selected owner-only credentials file is available without Stado. Secret-valued BRAMA_TOKEN is not read. A response is not trusted: completion presence, truncation, judge JSON shape, numeric ranges, and critical errors are checked locally.

Detector APIs

Source and candidate text cross every selected detector boundary. Each result is accepted only when a recognized field normalizes to [0,1]; a partial ensemble is not accepted.

The fleet database

Drafts, the person's writing, the catalog and detector scores cross into the skryba Supabase project over TLS. The connection string never sits in a file Skryba owns: it is read from Skarbiec on every run with the skryba-database-client bearer, whose grant covers only pooler_url and ca_certificate of skryba-database.

The writer's own files

writing-style add reads paths the person named. A named file is read whatever its extension and needs no model. A named folder is shown to the selected model route one folder at a time — the names of its files and subfolders, never their contents — and only the files it names as prose and the subfolders it names to open are read; symbolic links are not followed. The prose goes to the fleet database and nowhere else: no detector call. It crosses one more boundary on request — writing-style train writes the person's own passages into the export file and hands that path to a local ster process, which reads them to compute a gradient.

The spawned ster process

ster is resolved by search, not configuration: every PATH entry first, then ~/.cargo/bin, ~/.local/bin, ~/.stado/bin, /opt/homebrew/bin, and /usr/local/bin — the same order Skryba Desktop uses to find skryba. A missing binary is one sentence naming the install command. What crosses into that process is the export file path, the checkpoint name, and the training knobs; what comes back is an exit status, an adapter on disk, and Ster's own output, which is never reworded. train streams both of Ster's streams to Skryba's stderr, so its progress is live and Skryba's stdout stays the single report object every command answers in; rewrite --generator local captures Ster's stdout instead, because there the completion is the output. A zero exit that wrote no adapter is refused rather than reported as success.

Durable state

The scores table contains hashes and probabilities, not original text. The drafts table deliberately retains whole imported documents so Score and Rewrite can reuse them; the passages and preferences tables are the other deliberate exception: they keep the person's prose, because a hash cannot be trained on. The choices table holds names and instructions the person wrote or kept; every rewrite report copies the instructions it used, so a report stays readable after the catalog changes. Policy JSON contains strategy instructions and optimizer state. The Ster export and the LoRA adapter are files, at paths the operator names: Skryba writes the export, Ster writes the adapter, and neither is cleaned up afterwards — the export is kept beside the adapter on purpose, so the file that produced it stays next to it. None of these contains an API key. Credentials remain in the process environment (or, for Desktop launches, the user's ~/.config/skryba/env) and in Skarbiec.

Maintained as part of the website-owned Skryba documentation corpus.