On this page
Rewrite
A rewrite is Skryba's complete detector-directed transformation of one input text. It is not a single model response. Skryba generates several candidates for each chunk, measures every candidate with the configured detector ensemble and the quality judge, then selects the least detectable candidate that passes quality, style, and language checks.
Shape
skryba rewrite --json and --report serialize a RewriteResult:
text: selected chunk texts joined with a blank line;profile: the resolvedstyleandlanguagenames and thestyle_instructionandlanguage_instructionthe catalog held for them when the run started;chunks[]: the source chunk, selectedCandidateScore, all generated candidates, andused_source_fallback;- each candidate: strategy index and name, text, ensemble
ai_probability,quality_score(the weakest judged dimension),quality_passed, full quality evaluation includingstyle_matchedandlanguage_matched, and per-detector results.
The complete wire field list is in the CLI reference.
Lifecycle
- Resolve
--styleand--languagein the catalog; refuse a name it does not hold, before any credential is read. Reject empty input, a zero candidate count, a zero chunk limit, nonfinite or negative temperature, or minimum quality outside0..=1. Skryba imposes no temperature ceiling; the model route owns any upper bound. The candidate count, chunk limit, temperature, seed and minimum quality are the caller's; none has a default. - Split the input into chunks.
- For each chunk, sample
--candidatesstrategy indices from the policy, using--seed. - Ask the chosen generator for one rewrite per sampled strategy: one Brama chat completion each under
--generator brama, or onester generateprocess each under--generator local, with the person's own--adapterattached (training boundary). The required profile applies to every candidate and overrides a conflicting strategy or learned voice. - Drop any local candidate
ster generatereturned as whitespace, naming it on stderr; the group is then smaller than--candidates. - Score all generated candidates with every configured detector and ask the Brama-backed quality judge to evaluate them, once each. Each distinct candidate text is measured once and shared by every position holding that text, so duplicate candidates do not pay for duplicate measurements within the group.
- Keep only candidates whose six quality dimensions meet their thresholds, whose
critical_erroris false, and whosestyle_matchedandlanguage_matchedare true. - Select the survivor with the lowest
ai_probability. If none survives, judge the original chunk against the requested profile. Only if both profile checks pass, detector-score it and select a syntheticsource-fallbackcandidate. Otherwise fail with the chunk number, requested profile, source match booleans, candidate rejection counts, and source judge issues. - Join selected texts. Print text or JSON and optionally write
--outputand--reportfiles.
Candidates are processed chunk by chunk. Detector calls for a candidate set run concurrently, while each detector still keeps its own cache and the pause --detector-interval-ms states, if any. Brama candidates are generated concurrently too; local candidates are generated one after another on purpose, because each ster generate maps the checkpoint and a parallel group would hold one copy of the weights per candidate.
Selection invariants
- Quality, required style, and output language are hard gates for generated candidates, not ranking preferences.
- Detectability decides only among candidates that passed every gate.
- A detector failure fails the rewrite; Skryba never changes the ensemble silently.
- The original is not an unconditional fallback. It must already satisfy the requested style and language; it need not pass every numeric quality threshold.
- A profile refusal happens before final output and report writes. Existing destination files remain untouched; earlier model calls and detector-cache writes are not rolled back.
--seedcontrols strategy sampling, not remote model determinism. It is not the local generator's seed either: eachster generateis seeded with its own candidate index,0for the first candidate in a chunk, so the local route repeats itself without--seedreaching it.--policyis loaded and validated; a missing or invalid policy is an error, not a fallback to the built-in policy.
Refusals
style "<NAME>" is not in <CATALOG>; available styles: <NAMES>; add it with `skryba style add <NAME> --instruction <TEXT>`— and the same sentence forlanguage; exit1before the pipeline runs.--minimum-quality is required: the quality score a rewrite must reach is the caller's to stateinput text cannot be emptycandidate count must be positivemaximum words per chunk must be positivetemperature must be a finite number of at least 0; a ceiling is the route's own, and Brama states its refusal in its own wordsminimum quality must be between 0 and 1BRAMA_TOKEN_ROLE is required for Brama inference: ROLE#FIELD of the vault role holding the client token— on the local route too, because the quality judge is Brama's. See credential boundary for Stado resolution and the explicit owner-only file alternative;BRAMA_TOKENis not read.--generator local needs --local-model naming the checkpoint Ster maps--generator local needs --local-max-new-tokens; Ster assumes no token budget--local-max-new-tokens must be positivechunk <N>: no candidate passed every check for the requested style '<STYLE>' and language '<LANGUAGE>'; source fallback refused ...— no candidate passed the combined gates, and the original cannot fulfill the profile either. A candidate may match style and language but fail content quality. Style, language, and all-quality rejection counts may overlap; they are not separate candidate groups.
The earlier offline rewrite walkthrough used stand-ins. It is historical output, not evidence that the current style and language contract passes real model and detector flows.
Maintained as part of the website-owned Skryba documentation corpus.