Quality machinery
Most “AI writing” tooling guarantees the floor: no em-dash tics, no “delve”, no rule-of-three spam. WRITING AGENT enforces that floor and builds machinery for the ceiling - a thesis, a voice, a risk.
The floor: no slop, enforced twice
Section titled “The floor: no slop, enforced twice”- In every prompt - a fixed lexicon of banned verbs, adjectives, transitions, intensifiers, stock phrases, and openers (plus no em-dashes, no fabrications, concrete over abstract) injected into every writer, humanizer, and critic call. The critic flags violations as blocking, not nits.
- Deterministically - a lexicon-based AI-tell scanner finds offending sentences without an LLM’s opinion. The surgical humanizer rewrites only flagged sentences, with each rewrite guarded (citations, numbers, and length preserved; tell actually gone) before splicing. Approved prose is never wholesale regenerated.
The ceiling
Section titled “The ceiling”A thesis worth disagreeing with
Section titled “A thesis worth disagreeing with”Articles open with a generated contestable claim - stakes, arguments, a steelmanned counterargument with rebuttal, and non-goals - injected into every writer and critic call. Coverage without advancement is a blocking issue, and the writer is told to engage the steelmanned counterargument head-on rather than dodge it.
An insight bar
Section titled “An insight bar”The critic scores every draft 1–5 on insight (plus clarity, structure, evidence).
Approval requires insight ≥ min_insight - a correct-but-generic draft gets a
sharpening revision note instead of a pass. Deterministic structural metrics
(paragraph uniformity, rule-of-three density, specificity density) feed the critic as
computed evidence it can’t hallucinate around.
Divergent drafts, judged side by side
Section titled “Divergent drafts, judged side by side”First attempts sample multiple variants at different temperatures. A dedicated
judge reads them side by side and picks the winner - far more reliable than
comparing each draft’s jittery 1–5 self-score - and the winner’s biggest remaining
weakness feeds the refinement pass. In manual runs you pick instead. Selection
pressure for boldness, not convergence to the safest median. (tournament_judge,
default on; route the judge node cross-family for an independent eye.)
Claims checked against their sources
Section titled “Claims checked against their sources”For articles, every in-text [N] citation carrying a specific claim - a stat,
date, quote, or named attribution - is checked against the actual source text it
cites. Under deep research (full page text) an unsupported claim is blocking;
with thin search snippets it’s surfaced as a non-blocking nit, so a good draft is
never tanked on weak evidence. This turns the critic’s evidence opinion into a
structural check. (verify_claims, default on.)
A voice to match
Section titled “A voice to match”Drop admired paragraphs in voice/ - or /praise a committed unit you loved - and
they’re injected into every writer call as a model to match (showing voice beats
describing it). Praised passages also feed the learner as positive exemplars.
Write in any field - the craft engine
Section titled “Write in any field - the craft engine”The same pipeline writes technical explainers, fiction, academic papers, journalism, copy,
poetry, or screenplays - because the anti-slop/craft contract is data, not one hard-coded
“researcher voice.” A selectable register (one of 11) inverts the rules per genre:
fiction keeps the em-dash, academic requires hedging, copy keeps the exclamation. Each
register ships few-shot exemplars + a gold style corpus as a default “match this” anchor,
plus genre-aware deterministic metrics the model can’t argue with - so it runs well even on a
weak model. Pin it with /set register technical (or leave it to infer), and tune field
(structure) and citation_style to taste. (plan §22.)
Personas & emotion - composed, not stacked (the compositor)
Section titled “Personas & emotion - composed, not stacked (the compositor)”Voice layers - register ⊃ field ⊃ persona ⊃ emotion ⊃ skills - are resolved by a single
compositor that selects one voice and logs why, never piles them on (more layers is worse
on a weak model). Choose a persona (one of 46 - 18 archetypes like wry-skeptic /
hard-boiled-minimalist, plus 28 public-domain manners like shakespearean / wildean /
poe-gothic; no living authors, original-pastiche exemplars) and it’s dropped-with-a-log if it
clashes with the register. Choose an emotion (one of 12) and - instead of a
cliché-generating “fear = racing heart” dictionary - its anti-cliché deny-list is wired into
the detector (“her heart raced” gets flagged) alongside a show-don’t-name cue. Set them with
/set persona wildean / /set emotion grief - see Settings.
(plan §23.)
A skeptical reader, in the loop
Section titled “A skeptical reader, in the loop”After a run, a table read cold-reads the whole piece as a skeptical
target-audience reader - where it gets boring, where trust breaks, what’s never made
concrete, what’s missing - into table_read.md. In autonomous runs you can let it
close the loop: table_read_revise applies the single highest-impact fix as one
bounded, version-snapshotted revision (off by default, since it edits finished prose).
Clean references & figures, owned by the producer
Section titled “Clean references & figures, owned by the producer”After assembly a pure-Python pass (no LLM, ~0 tokens) takes sourcing and figures away from the writer so they come out clean and consistent:
- one end
## Referenceslist ranked by influence (0–100) - weighted cite count plus title overlap with the thesis and headings, dated, most-influential first (rank_references); - the inline
[N]markers are stripped from the body after scoring, so the prose reads clean and all sourcing lives in the end list (strip_inline_citations); - stray mid-article reference dumps are pulled back out, and generated diagrams are
deterministically reconciled into the manuscript - embedded once, de-duplicated (a
diagram the model still drew, its self-numbered caption, and a redundant embedded SVG),
and anything unused or dropped is logged to
rejected.jsonl(reviewable in the web dashboard’s Rejected tab) rather than silently discarded.
Re-run the whole pass on an already-finished piece with polish - references, citations,
figures, and a re-export, with no model call.
Evidence report - proof, not vibes
Section titled “Evidence report - proof, not vibes”Every article also ships an evidence_report.md: the thesis it argues plus every source
ranked by influence (0–100), generated deterministically from the finished manuscript (no model
call). It turns the otherwise-invisible trust machinery into something a reader can check.
Regenerate any time with evidence (or Project.evidence_report()).
The learning loop
Section titled “The learning loop”After every finished piece, the learner distills what the critic kept flagging into
craft skills (markdown files) and a watch-list injected into future critic
calls. It also mines the model’s own preference data - which draft won a
side-by-side judging and why, and which revisions fixed a flaw - for the generalizable
craft principle behind each. Like critic findings, that data is model-judged, so it
enters as candidate skills only and must still earn promotion; it never bypasses
the gate. Thirteen built-in craft skills seed the system (seed-skills).
The system gets better with use by accumulating this on-disk memory - not by retraining or fine-tuning the model. The weights never change; what changes is the craft skills and watch-list the agents are handed each run.
Ablation duels - a causal efficacy signal
Section titled “Ablation duels - a causal efficacy signal”The old efficacy signal was confounded: every applied skill got the same
chapter-level credit, with no counterfactual to say whether the skill actually helped.
v2 fixes that. With skill_duels on (opt-in, default off), whenever a unit still
has an undecided skill the writer drafts one extra variant with that skill held
out - same prompt, same temperature, only the skill differs - and the critic compares
it against the full-skill draft. That is a true cause-and-effect (counterfactual) test
of whether the skill earned its place.
Promotion and retirement are then driven by a smoothed, sample-gated duel win-rate
measured against a 0.5 coin-flip (50/50) - not against the old “first-pass lift”
baseline, which is now only the fallback when no duels exist yet. A skill needs ≥5
duels before it can be decided (MIN_DUELS); a win-rate ≥0.55 promotes
candidate → trusted (TRUST_WR) and ≤0.45 retires it (RETIRE_WR). Cost is
bounded: a draft is only added (never substituted) while a skill is undecided, and the
whole mechanism is off by default. /skills surfaces this as a duels (vs 50/50)
column alongside first-pass lift.
Distillation & guarded watch-list
Section titled “Distillation & guarded watch-list”skill_distill(opt-in, default off) - after learning, deterministically retires near-duplicate skills (textual Jaccard similarity ≥ 0.85), keeping the best duel-scored one in each cluster. It is non-destructive (sets a status field; the markdown stays) and keeps skill retrieval sharp as the library grows.watch_blocking(default on) - watch-list violations now block only clear, concrete ones; borderline or stylistic hits are downgraded to a nit. Set itfalseto make the watch-list fully advisory (nit only).