add a writer-facing content pipeline under writing/

Dialogue was already plain text, so the gap was never the .yarn files. It was
that the character material a writing session needs was either missing or stored
somewhere a writer could not comfortably work.

Three things were wrong. The writing handbook was not in the repo and was cited
by SC101.yarn as though it were. The best voice material — register, verbal tics,
success/failure/passive samples — was a \n-escaped string inside a JSON field.
The named NPCs had no sheets at all, existing only as their Yarn lines.

writing/ now holds the dialogue-facing layer, at the repo root so it gets no
.meta files and is not a Unity asset:

  STYLE.md          register, the five tone moves, the ban list, branching
                    shapes, the Wrong Truth rule, flag families, candidate rules
  YARN-PRIMER.md    the one page of syntax needed to write a scene
  GLOSSARY.md       in-world and project vocabulary
  voices/           the eleven skill voices, one readable sheet each
  characters/       Bartender, Chevalier Cassian Thal, Bradford Kane
  scenes/           SC-101's brief: intent, beats, checks, constraints
  lore/             the three identity readings and the rules that bind them

STYLE.md is a digest of the Mystery Writing Handbook in the Obsidian vault, with
pointers rather than copies. The vault stays the authoring home for design work,
and Ground Truth — the solution document — deliberately stays out of this repo.

The voice sheets are generated from skill_bible.json but are the source of truth
for the prose. tools/writing/sync_voices.py folds edits back; voicelib.py
guarantees notes -> dict -> notes is identity for all eleven, so --to-json on
unchanged sheets is byte-identical. VoiceSheetSyncTests fails the build on drift
in either direction, and was verified to fail on real drift rather than merely
to pass.

SC101.yarn's header is trimmed from prose rationale to the six rules that bind
while editing that file, with the reasoning moved to the scene brief.

EditMode 42/42. YarnCheck compiles 9 files / 35 nodes.

Co-Authored-By: Claude Opus 5 <[email protected]>
This commit is contained in:
2026-08-25 20:23:42 +02:00
co-authored by Claude Opus 5
parent b915ad78c7
commit f1fadf7909
28 changed files with 2766 additions and 21 deletions
@@ -0,0 +1,88 @@
---
id: chevalier-cassian-thal
name: Chevalier Cassian Thal
chr: —
yarn_file: Assets/Dialogue/Characters/Chevalier Cassian Thal.yarn
status: drafted
scenes: [SC101]
---
# Chevalier Cassian Thal
## Who they are
A knight, of Basel and Cyprus, seated at the table nearer the head than the protagonist is. He
introduces himself with a bow and a half-open fist to the forehead — an old form, performed
without irony. Old money, and comfortable in it. He is here as part of something ("the Knight's
compromise", "our friends of the Vaselian Concordat") and he speaks about it as though everyone
at the table already knows, because in his world everyone does.
He is the scene's mirror: whatever the protagonist has been leaning toward, he names it back at
them, gently, and waits. He is rarely wrong in matters like these, as he will tell you.
## How they speak
Courteous, archaic, warm. Slightly too familiar too quickly — "old chap", "my boy" — which reads
as class rather than affection. He uses `{$player_name_full}`, the formal form, when he is being
precise. He laughs easily and often, including at things that are not jokes.
## Verbal tics
1. Slips into the institutional "we" and "us" without noticing, then does not correct it.
2. Deflects with courtesy rather than refusal — "I am of no right to reveal this."
## What they never say or do
He never threatens and never withholds coldly; every evasion is dressed as politeness. He does
not name the Concordat's business outright, and he never breaks the fiction that the protagonist
already belongs at this table.
## What they know
| They know | True? | Reveals when | Records |
|---|---|---|---|
| He is of Basel and Cyprus | true | on introduction | `$spoke_to_chevalier_cassian_thal` |
| Cyprus connects to something he won't name | true | `<<check provenance Hard>>` succeeds, then the player inquires | `$inquired_about_cyprus` |
| Mr. Doss can explain the Cyprus connection | believed | on inquiring about Cyprus | `$looking_for_doss` |
| Something is about to happen at the table | true | after the protagonist declares a reading | `$declared_candidate_to_chevalier_cassian_thal` |
## What they are wrong about
He is certain he knows what the protagonist is. He is working from whatever the protagonist has
been projecting — which is to say from the lean, which is belief rather than truth. His
confidence is sincere and is not evidence. When he says "I am rarely wrong in matters like
these", that is characterisation, not a hint from the author.
## Their read on the protagonist
He is the game's first mirror mechanic. `SC101_Asks_Candidate_Chevalier_Cassian_Thal_Talk`
computes `top_skill(...)` over the three leans and asks the matching question:
| Leading reading | What he asks |
|---|---|
| Made Asset | whether they observe on behalf of the Vaselian Concordat |
| Journalist | whether he will read his answers in tomorrow's paper |
| Inheritor | whether they are here to settle a parent's debts |
Agreeing reinforces that lean. Denying adds to *both other* leans — a refusal is not neutral, it
is a push toward the alternatives. Denial routes to `SC101_Deny_Candidate`, which recomputes the
winner and, if it has not changed, offers the player the chance to reverse; if it has changed,
he simply asks the new question. The player can be walked around this loop.
`made_asset` is passed first to `top_skill`, which returns its first argument on a tie — so an
even score reads as Made Asset. That bias is deliberate.
## One line that is 100% them
> "Well, then let us hope the ... others follow the Knight's compromise."
## Open threads
The Atlantean cross on the place card (`$saw_knights_atlantean_cross_on_place_card`, found via a
`Hard` PROVENANCE check) is never connected to him in dialogue, though he is a knight and the
symbol is a knight's. That connection is available and unwritten.
His faction, the Vaselian Concordat, and "the Knight's compromise" are named but not explained.
Before writing more of him, confirm his faction row against `[[Lorebook]]` §2 — the vault's
`[[Character Sheet Handbook]]` exists specifically because figures drifting from the faction
tables is a logged, repeated failure in this project.