Parlance Editor — User Guide

A complete reference for the Parlance visual editor. The editor runs locally against your project's data/ directory; every change is written to disk as human-readable JSON so your narrative data stays in git.


Table of Contents

  1. Starting the editor
  2. Layout overview
  3. Entity types
  4. Entity list & search
  5. Entity detail — view & edit
  6. Dialogue canvas
  7. Quest canvas
  8. Quest dependency graph
  9. Location map
  10. Validation panel
  11. Reports — coverage & reference index
  12. Playtest mode
  13. Undo / redo and navigation history
  14. Data format & git workflow
  15. Localization & VO
  16. Review — reading someone else's branch

1. Starting the editor

Launch Parlance and point it at a project folder. A project is just a directory of narrative files — most often the data/ directory inside your game's own repository, so the story is versioned alongside the game that reads it. Nothing is imported and nothing is copied into a library: the editor reads and writes those files in place.

A folder counts as a project if it contains a parlance.config.json, a data/ directory, or a schema/ directory. Open an empty folder and the editor scaffolds the standard layout on first save; parlance init <dir> does the same from the command line.

Start with the demo

The Mistfall Inn ships with the editor: a complete, tiny murder mystery — one night, one body, three suspects, three endings — with no art and no engine required. It exists so your first session is spent on something real instead of an empty directory.

Open it and start with The Common Room under Locations, or go straight to dlg_examine_body and press ▶ Play. Each of its parts is demonstrating something specific; examples/mistfall-inn/README.md maps features to the scenes that show them off.

Where your files live

<your game repo>/
  data/    the narrative — what your game reads at runtime
  tests/   route fixtures; a shipping game never loads these
  lore/    Markdown canon docs, read-only in the editor
  review/  review threads; invisible to the runtime and the validator

Full detail, including how to relocate any of those directories, is in §14 and in the setup guide's per-project configuration section.

Running from source

Contributors and self-hosters can run the editor as a local host plus web client instead of the packaged app. That path — prerequisites, the two dev-server processes and their ports, pointing the host at a project, production builds, and packaging — is documented in SETUP_AND_MANAGEMENT.md §§2–3, which is where the build-level detail lives so this guide can stay about using the editor.

Everything in this guide applies identically either way: the same editor, the same validator, the same files on disk.


2. Layout overview

┌────────────┬──────────────┬──────────────────────────────────────┐
│ Header: title, breadcrumb (Type › entity), ⌘K hint, Undo/Redo, AI │
├────────────┼──────────────┼──────────────────────────────────────┤
│ Type       │ Entity list  │ Main panel                           │
│ sidebar    │ pane         │ (fills remaining width)               │
│ (icon +    │ Search,      │                                      │
│ label +    │ group, +New, │ Entity detail form                   │
│ count per  │ entities     │   — or —                             │
│ type;      │              │ Dialogue canvas                      │
│ Reports    │              │   — or —                             │
│ pinned to  │              │ Quest canvas / dependency graph      │
│ the        │              │   — or —                             │
│ footer)    │              │ Location map / Reports panel         │
├────────────┴──────────────┴──────────────────────────────────────┤
│ Validation bar (collapsed to a status row by default; click to expand) │
└────────────────────────────────────────────────────────────────────────┘

The left side is a fixed type sidebar — one row per entity type, each with an icon, label, and a live entity count, always in the same place (it never reflows). Reports is pinned to the sidebar's footer, showing the total error/warning count once the project has any. Click a row to load that type's list in the pane beside it (search, group, create, and the entities themselves). The « button collapses the whole panel — sidebar and list — to a thin 32px rail to maximise canvas width; » expands it again. The collapsed/expanded choice is remembered across sessions.

Selecting an entity from the list loads the main panel. For dialogues and quests the main panel is a visual canvas rather than a form; for locations, selecting no entity shows the location map (§9).

Command palette (Cmd/Ctrl+K). Opens a searchable palette from anywhere in the app — even while a text field is focused. Type to fuzzy-match against every entity across every type (by name, id, or title) and jump straight to it, or run a curated action (Create new <Type>, Open Reports). This is the fastest way to get anywhere once a project has more than a handful of entities; ↑/↓ to move, Enter to open, Esc to close.

Breadcrumb. The header shows <Type> › <entityId> for whatever you're currently viewing. Click the type segment to jump back to that type's list.

Text Size. The dropdown next to Undo/Redo (90%–150%) scales font size across the whole editor — chrome, canvas, the Play panel transcript, everything. It does not scale layout: buttons, icons, and panel widths stay put, so at higher sizes a few fixed-width labels (the type sidebar's, in particular) may elide with rather than grow to fit. That's a deliberate trade-off — the alternative is scaling the whole UI, which cannot be made to render within the actual window at every size (ask if you want the history).

Resizable side panels. The node inspector and the Play panel (§6, §12) both have a drag handle on their left edge — drag to resize, double-click to reset to the default width, or focus it and use / (Shift for a bigger step) and Home to reset. Width is remembered per panel across reloads. The canvas always keeps a minimum width, so a dragged-wide panel yields if you narrow the window.

Persisted UI preferences. Several view choices are saved to the browser's localStorage so they stick across reloads: entity-panel collapsed state, detail default (edit form vs. raw JSON), dialogue node density, per-canvas minimap visibility (dialogue / quest / quest-dependency / location map), the validation-bar collapsed state, Text Size, and both resizable panel widths. (See the setup guide for the exact keys.)


3. Entity types

Type What it represents Key fields
Skills Stat names used in checks (wit, empathy, …) id, name, description; optional cluster
Variables Global state values — flags (bool), counters (int), text (string) id, kind, default
Factions Groups whose reputation the player can influence id, reputationRange.min/max
Characters NPCs and the player id, optional archetype, optional stats (skill → int)
Dialogues Conversation graphs nodes, choices, checks, onEnter effects
Quests Staged tasks with trigger/completion conditions stages, outcomes, dependencies
Locations Named places referenced from quests / lore id, name, optional zone
Endings Named story endings id, name, summary, unlockedBy, optional kind (success / failure / neutral)
Codex Player-facing knowledge entries (codex / bestiary / glossary) id, name, body, optional category, unlockedBy? (absent = always unlocked)
Items Things the player can carry. Possession is runtime state; this registry gives an item a player-facing identity id, name; optional description, tags
Portraits Character portrait registry (referenced from dialogue nodes) id, character, tags
Cutscenes Manifest: opaque engine asset key + effects applied on completion (effect-triggered via play_cutscene) id, asset, skippable, effectsOnComplete, entersDialogue?

All types share a stable string id used as the cross-reference key everywhere. The sidebar row for each type shows a live count of how many entities it holds.



5. Entity detail — view & edit

Selecting any non-dialogue, non-quest entity opens the detail panel. The toolbar's JSON / Edit toggle switches views; your choice persists across reloads.

If the entity has a loreRef field pointing to a Markdown file, a Lore button appears in the toolbar. Click it to open an inline Markdown viewer of the referenced canon doc — useful for keeping the entity's narrative context visible while editing.

Edit mode (default)

Fields are grouped into labelled sections in a fixed order — Identity, Description, Relationships, Logic, Structure, and (if the type has them) a Metadata section that starts collapsed, since loreRef and tags are low-priority housekeeping fields you don't need open by default. Section headers only appear when a form genuinely has more than one section, so small entities (e.g. a skill) still just show a flat list.

Most fields get a real editor, not a generic fallback:

Click Save to write the change to disk. If the file changed on disk since you loaded it (e.g., another tool edited it), a 409 conflict error is shown and the save is blocked — click Reload to see the latest version.

JSON mode

Shows the entity's raw JSON with syntax colouring — useful for a quick read-only glance, or for copying the exact on-disk representation. Below the JSON, any validation issues scoped to that entity are listed.

Click Delete (then Confirm delete) to remove the entity permanently.

Flow (flags, counters, items)

When the selected entity is a variable or an item, a Flow panel at the bottom of the detail pane shows every place that variable is used, split by direction:

Each row names the owning entity and the exact path (e.g. nodes/node_cleared/onEnter[0]) and is clickable — it jumps you straight to that entity. If a variable is only ever written or only ever read, the panel says so: a flag nothing checks, or a condition that gates on a flag nothing sets, is usually a wiring mistake worth catching early.

Creating a flag inline

You don't have to define a flag before you can reference it. In any condition or effect picker (a flag / counter / item field), type a name that doesn't exist yet and choose the + New flag "…" row that appears. The name is slugified to a valid id, the variable is created immediately, and the field is set to it — no trip to the Variables list. Fill in its description later.


6. Dialogue canvas

Flow map (all dialogues)

Selecting the Dialogues type without opening a specific dialogue shows the flow map — every dialogue as a single node, laid out left-to-right, with edges for the cross-scene jumps between them:

Each node shows the dialogue's title, id, speaker, and word count; a START badge marks dialogues with no incoming jump (reached by a ladder default, a quest, or a cutscene from elsewhere). Click a node to open that dialogue's node graph. "Auto layout" re-runs the dagre arrangement; positions you drag are saved. It's the project-level companion to the quest dependency graph.

Node graph (one dialogue)

Opening a dialogue from the entity list loads a node graph. Each node represents a moment in the conversation; directed edges represent the paths a player can take. The graph flows left-to-right: the entry node sits on the left and the conversation reads forward across the canvas.

Graph vs. Text

The Graph · Text toggle (toolbar, top-left) switches between the visual canvas and an editable script view — the whole scene as text, for authors who'd rather type than click. Node headers are == node_id [entry] [end] ==, an optional author note is a > … line under the header, prose follows, choices are - choice_id: "text" -> target, node/choice effects are + set_flag x = true, and checks are check wit >= 12 -> pass / fail.

The script is a lossless representation: saving reproduces the dialogue exactly, changing only what you edited (a byte-level round-trip is enforced by tests over every dialogue). A syntax error blocks the save and points at the line — it never writes partial data. Rich logic (nested conditions, all effect types) is expressible in the compact grammar, but the graph's builders remain the friendliest way to author it; use whichever fits the moment.

Canvas controls

Action How
Pan Click and drag on empty canvas
Zoom Scroll wheel, or use the Controls cluster (bottom-left)
Fit all Fit-view button in Controls, or "Auto layout" in the toolbar
Select node Click a node
Deselect Click empty canvas
Drag node Drag the node header to reposition (saved automatically)
Delete node Select it → "Delete node" button in the toolbar
Delete edge Select the edge → Delete key
Connect a next (choiceless advance) Drag from the node's dedicated continue handle (only shown on nodes with no choices) to the target node

Node density toggle (Compact · Card · Script) in the toolbar controls how much of each node's text is shown:

The chosen density is remembered across sessions. Switching density reflows new / unpositioned nodes; nodes you've manually arranged keep their saved positions — click Auto layout to reflow everything to the current density and direction.

Map toggles the minimap (bottom-right) on/off — handy when it overlaps a node you're working on. Auto layout re-runs the automatic left-to-right layout for the whole graph.

Node positions are persisted per-dialogue in a *.layout.json sidecar file. These sidecars are gitignored — your graph arrangement is a local, personal concern that is never committed. Deleting one just makes the editor re-run auto-layout next time.

Share build

⇪ Share build (canvas toolbar) downloads a self-contained HTML file of the current scene — play-<id>.html. It's a complete, serverless playable: double-clicking it runs the scene in any browser, through the same core engine the editor uses (checks roll, showIf gates, effects apply, scenes route). No install, no host, nothing to set up. Hand it to a writer or playtester to get feedback on a scene without walking them through running the editor.

Adding nodes

Click + Node in the toolbar. A new blank node appears to the right of the graph. Click it to open the inspector, then fill in the text.

Connecting nodes

Each choice has a source handle on its right side — a small dot. Drag from that handle to the target handle (left edge) of the destination node.

A node with no choices instead shows a single continue handle — drag it to another node to set that node's next field: a choiceless advance, for a listen-only beat (narration, an overheard line) that shouldn't cost a synthetic "Continue" choice. A node can have next or choices or be isEnd, never more than one — the inspector's Next field disables itself with a hint when the node already has choices, and vice versa. next edges draw as a thin unlabelled line, distinct from goto/check edges, and — like choice gotos — can point back at the node's own dialogue only; the runtime never chases a next chain automatically, each advance is one discrete, player-facing step (a Continue → button in Play mode, §12).

To remove a connection, select the edge and press Delete.

Node inspector (right panel)

Click a node to open its inspector.

Node section:

Choice section: Select a choice to expand it.

Skill checks and conditions are shown automatically. On the canvas, a choice with an active check shows a skill / difficulty badge (e.g. wit / 10), and a choice gated by a showIf shows a condition summary (e.g. wit >= 6), derived from the structured fields. You do not need to type a [Wit]-style prefix into the choice text — the badge is generated for you, and the text stays clean prose that serializes verbatim to JSON.

Effects reference

Type What it does
set_flag Sets a boolean flag to true/false
adjust_reputation Adds a delta to a faction's reputation, clamped to its declared range
adjust_counter Adds a delta to a named counter (unbounded)
give_item Adds an item id to the player's inventory
take_item Removes an item id from inventory (no-op if not held)
advance_quest Marks a quest stage complete (engine handles progression; no-op in playtest)
set_active_dialogue Queues a specific dialogue for a character (push-based scene switch)
play_cutscene Queues a cutscene manifest (pendingCutscene); the host plays its asset, applies effectsOnComplete, then enters entersDialogue if set
set_text Sets a text variable to a literal string, substituted wherever {variable} appears in player-facing text. Pick the variable from the dropdown (or create one inline) and type the value.

Dialogue metadata (inspector, top section)

Pacing (inspector, with no node selected)

Below the metadata, a Pacing grid gives the shape of the scene at a glance, so you can tell a two-beat exchange from a sprawling branch without counting:


7. Quest canvas

Selecting a quest from the entity list opens a stage graph. Stages flow left-to-right; edges represent after dependencies between them. The quest canvas shares the same dark controls and Map minimap toggle as the dialogue canvas.

Quest structure

A quest has:

Quest inspector

Click a stage or outcome node to open the inspector:

Journal objectives (stage inspector)

A stage's inspector has two prose fields, and the difference between them is the whole point of the journal:

Under Objectives (journal) each row carries:

Control What it does
▲ / ▼ reorder — array order is authoring order, and the journal renders in it
id field unique within the stage; used by the validator and by diffs, never shown to the player
text area the intention line, in the protagonist's voice
show if optional visibility gate, using the same condition builder as everywhere else

An objective with no show if reads "always visible". Gate on knowledge and acquaintance — has she met this character, does she know this place — so a route only appears if she could actually name it.

Objectives are display-only: there is deliberately no effects builder and no goto here. Complete When below still decides when the stage is done, no matter which route the player took.

Every edit — add, retype, reorder, delete — goes through the normal save path, so Cmd/Ctrl+Z restores the previous JSON exactly.

Two warnings you may see in the validation panel:

Quest-level Journal Name (the player-facing title, falling back to name) and Tags are edited on the quest's own entity form, not on the canvas. Tags drive the journal's grouping — main vs. side is a tag, never a checkbox — and are linted against a controlled vocabulary; an unrecognised tag is a warning.


8. Quest dependency graph

Selecting Quests in the sidebar without opening a specific quest shows the quest dependency graph — all quests laid out in a DAG showing which quests are prerequisites for others.

Each node shows:

Click a quest node to jump to that quest's detail canvas.


9. Location map

Selecting Locations in the sidebar without opening a specific location shows the location map — every location laid out as a graph, mirroring the quest dependency graph.

Edges represent traversal:

Each node shows the location's id, name, zone, and exit count. Click a node (or pick it from the entity list) to open its detail form. The map shares the same Auto layout and Map minimap toggle as the other canvases.


10. Validation panel

A bar at the bottom of the editor shows the live validation state. Every save triggers a full re-validation of the project; results are pushed to all open editor windows via WebSocket.

By default the bar is collapsed to a single status row — it still shows the live error / warning counts and per-code filter chips, so project health stays glanceable, but the issue list stays out of the way. Click "Validation ▸" (or any status chip) to expand it and see all issues; the expanded / collapsed choice is remembered across sessions. Issues are sorted errors first, then warnings. Each row shows:

Common codes:

Code Meaning
SCHEMA Field fails JSON Schema validation
REF References an id that doesn't exist
DUP Duplicate id detected (entity ids, dialogue nodes/choices, or a location's spawns/exits/interactables)
FLOW Dialogue has an unreachable node or dead-end choice
GATE Active check missing onSuccess / onFailure destination
QUEST Quest stage issue — including stage/outcome effects with no completeWhen/reachedWhen (they can never fire; quest resolution only fires condition-gated items)
FLAG Flag written but never read, or read but never written
REP Reputation reference to unknown faction
ENDING Ending is unreachable
COVERAGE Character has no dialogue
REACH Dialogue node unreachable from entry
LORE loreRef points to a file that doesn't exist
LOC Location graph issue — bad exit spawn, a spawn nothing arrives at, more than one default spawn, gate/gateType mismatch, unreachable location, npc interactable missing its character
CUT Cutscene issue — unknown entersDialogue, never-triggered cutscene, or ambiguous ordering (two play_cutscene effects on one node)
LADDER Character dialogue-ladder shape issue — a dead rung (an unconditional rung before the end shadows the rungs below it), a stuck rung (an unconditional, top-priority, effectful rung re-fires forever on every re-entry), or no fallthrough (the last rung is gated, so the character may resolve to no dialogue). A dangling dialogues[].dialogue is a REF error. All warning-level; none blocks a save.
PROG Progression config (progression.json) issue — malformed thresholds (not strictly increasing), pointsPerLevel/maxSkill < 1 (error), a starting skill already at the ceiling, or the soft-cap sanity warning (authored XP grants enough points to max every skill).
XP grant_xp issue — non-positive amount (warning), or grant_xp authored outside a quest outcome (advisory; the convention is XP from quests only).
CHECK Priced/oneshot check discipline — a priced (default) active check whose failure doesn't proceed (no onFailure branch), or a priced-gate failure that sets a flag some character ladder reads (advisory). oneshot checks are exempt from the proceed requirement.

The Reports row (sidebar footer) also shows the total issue count, coloured red for errors or yellow for warnings.


11. Reports — coverage & reference index

Click Reports (pinned to the sidebar footer) to open the Reports panel.

The panel has two columns:

Left — Coverage & structural issues

Issues are grouped by code category. Each row is clickable and navigates to the affected entity (same as the validation panel). Use this view to:

Right — Reference index

A searchable index of every id in the project. Type a flag id, character id, skill id, etc. to see:

Each entry is clickable and navigates to the exact entity. This is the "find usages" feature — useful for safely renaming or removing a variable.


12. Playtest mode

Playtest mode lets you walk through a dialogue interactively with a live simulated GameState, right inside the canvas view.

Opening playtest

  1. Open any dialogue in the canvas.
  2. Click the ▶ Play button in the canvas toolbar (top-left).

The node inspector closes and a Play panel appears on the right side. The active node is highlighted with a green glow on the canvas; visited nodes are dimmed.

Starting state editor

Before starting, the panel shows the Starting State editor:

Click ▶ Start Session to begin. You can also click ▶ Play again (it acts as a toggle) to close the panel and return to the editor.

Editing while playing (auto-reload)

A running session stays live when you edit the dialogue it's playing. Change node text, add or delete a node, rewire an edge — the session keeps your accumulated game state (flags, XP, quests, reputation) and re-reads the scene, recomputing which choices are visible at the current node. If the node you were standing on is deleted, the session snaps back to the entry node with state intact rather than dead-ending. This makes the tight loop — tweak a line, see it in context, tweak again — instant, without restarting from the top each time.

Transcript

Once a session is running, the transcript shows each step top to bottom:

Past steps are shown above the current step. Each past step has a ↩ rewind here link that truncates the timeline back to that point.

Continuing into the next scene

Once a conversation ends, if there's somewhere for the player to go next, a section appears below the transcript:

This is how you playtest across a scene boundary without manually reopening the next dialogue and re-entering its starting state by hand.

Check affordances

For active-check choices, two extra buttons appear alongside the normal choice button:

These let you test both branches of a check without needing to set skills to extreme values.

Toolbar controls (while session is running)

Button Action
seed:XXXXXXXX Displays the current session seed (read-only)
↺ Restart Resets to step 0, same seed and starting state
⟳ Reroll Appears after a check step. Rewinds one step and re-runs the same choice with seed+1. Use this to flip a pass to a fail (or vice versa) without manually changing skills.
✕ Stop Closes the play panel and returns to edit mode

State inspector

At the bottom of the play panel, a live State table shows the current values of all flags, reputation, and skills referenced in the dialogue. Values that changed on the most recent transition are highlighted in purple.

Determinism guarantee

The session uses a seeded RNG (mulberry32(seed + stepIndex)). A session is fully reproducible: given the same seed and starting state, every choice leads to the same rolls and the same outcomes. Rewind + replay gives identical results. The seed only changes when you click ⟳ Reroll (seed+1) or 🎲 Randomize before a new session.

What playtest does NOT change

Playtest is read-only. It never writes to any dialogue file or layout file. You can verify this — the dialogue JSON and .layout.json are byte-identical before and after any play session.

advance_quest effects fire in the transcript (they appear in the applied list) but are a no-op in playtest — quest stage tracking is the responsibility of the host game engine.


13. Undo / redo and navigation history

There are two independent histories, and they do different things:

Undo / redo (edit history). The ↩ Undo and ↪ Redo buttons in the top toolbar undo/redo saves (Cmd/Ctrl+Z, Shift+Cmd/Ctrl+Z, or Ctrl+Y). Up to 100 operations are kept per session. Each save records a { before, after } snapshot of the entity; Undo replays before, Redo replays after. This history is in-memory only — it clears on page reload. Canvas layout changes (node drag) are not in the undo stack — they write directly to the layout sidecar and are not undoable.

Back / forward (navigation history). The and buttons (next to Undo/Redo) move through your selection history — which type and entity you were viewing — like a browser's back/forward. Shortcuts: Alt+← / Alt+→, or Cmd/Ctrl+[ / Cmd/Ctrl+] (the Xcode/VS Code "Go Back" convention). This is purely navigational: it changes what's shown, never your data.

For a third way to get around — jumping directly to a distant entity rather than stepping through history — use the command palette (Cmd/Ctrl+K, §2).


14. Data format & git workflow

File layout

data/
  skills/          one JSON file per entity
  variables/
  factions/
  characters/
  dialogues/       dlg_arrival.json
                   dlg_arrival.layout.json            ← canvas positions (gitignored)
  quests/
  locations/
  endings/
  codex/
  items.json       flat registries (items, portraits)
  portraits.json
  cutscenes/       one JSON file per cutscene
tests/
  routes/          rt_*.json — scripted playthroughs with assertions
  snapshots/       snap_*.json — saved states to resume from
schema/            JSON Schemas; editor loads these for validation + forms
lore/              Markdown canon docs (read-only in the editor)
review/            review requests + comment threads (§16)

data/ holds narrative content only. Routes and snapshots are regression fixtures — a shipping game never loads them — so they live beside it rather than inside it.

Why this layout matters

Stale-load detection

If two editors (or a script) write to the same file concurrently, the host detects the conflict via a hash check and returns a 409. The editor surfaces this as "File changed on disk — reload to see latest version". Reload to pull the latest before saving again.

Validation on every save

Every PUT re-runs the full validator and broadcasts updated issues to all open editor windows via WebSocket. You always see live validation without manually refreshing.


15. Localization & VO

The Localization entry in the sidebar footer (globe icon) opens the translation and voice-over pipeline. It's a read-and-export surface: content stays authored in the base language on the entities themselves, and localized strings live in catalog files alongside your data.

What it shows

The pipeline

  1. Download source catalog — a flat key → source text JSON of everything translatable, for translator reference.
  2. Enter a language code and Locale template — a key → "" file (with any existing translations for that locale already filled in) to hand off.
  3. Translators fill in the blanks and return the file; drop it at data/locales/<lang>.json. Reload — the coverage bar fills in.
  4. VO template works the same way for data/vo/<lang>.json, mapping voiceable keys to opaque audio asset keys (the engine resolves them, exactly like cutscene manifest assets — Parlance never touches the audio).

Keys

A string's key mirrors the reference-index path, e.g. dialogue/dlg_arrival/nodes/node_open/text or quest/qst_inquest/summary. Keys are stable as long as the underlying ids are; renaming an entity, node, or choice id orphans its translation, which shows up as a stale key on the coverage bar so you know to remap it.


16. Review — reading someone else's branch

The Review entry in the sidebar footer is where narrative work gets read, questioned, and signed off. It needs nothing but git: comments live in the repository, on the branch they are about, so a two-person team on plain clones gets working review with no server anywhere.

Author or reviewer is decided for you

There is no mode to switch. For whichever branch you pick as Head, you are its author if it is the branch you currently have checked out, and a reviewer if it isn't. The badge under the branch pickers says which, and what follows from it:

AUTHORING (checked out) REVIEWING (not checked out)
You are looking at your working files a read-only snapshot of the branch
Comments written straight into review/ queued locally until you Sync
Story files yours to edit read-only
Suggestions Apply in one click propose only
Verdict — (you don't sign off your own work) Approve / Request changes

Reviewers never check the branch out, so their own working copy stays clean and on whatever they were doing. Check out to edit switches you to the branch when you want to become its author; it refuses if you have uncommitted changes rather than stashing them behind your back.

Reading the changes

Pick a Base and Head and press Show changes for a narrative diff — not a file diff. It reports what happened to the story: "2 nodes added, 1 line edited, ladder reordered", each entity's before/after lines, flags introduced or retired, and the validation delta.

Both branch pickers are searchable: type any part of a name — several words, in any order — rather than scrolling a list that grows with every branch the team has ever pushed. Local branches are listed before remote ones, and the branch you have checked out is marked, since main and origin/main are otherwise the same word and picking the wrong one silently swaps AUTHORING for REVIEWING.

Each changed entity carries a button to open it. As the author that is Open, which draws the dialogue on the canvas with this branch's changes marked. As a reviewer the canvas can't help — it draws your checked-out working tree, which is a different branch — so the button is Play, and it takes you to the scene read-only in the tab below. Entity types with no read-only viewer yet (characters, quests, …) show the button disabled.

Playing the branch

Play the branch runs the branch's own content — the snapshot read from git, not your files. This is the point of reviewer mode: you hear the scene as it actually plays before saying anything about it. Everything from Playtest mode (§12) works here, including the seed, rewind, and forced check outcomes.

The Scene picker offers every dialogue on the branch, searchable by title or id. Once you have pressed Show changes, the ones this branch touched are grouped first and annotated with what happened to them ("1 line edited") — the annotation is searchable too, so typing line edited narrows the list to just those scenes.

The rest of the project stays in the list on purpose. A branch that edits a quest, a flag, or a character ladder changes how a scene behaves without touching that scene's own file, so the dialogues worth playing are often ones that show up as unchanged — and reading an edit in context usually means playing the scenes on either side of it.

When the scene you are playing is one the branch changed, its before/after lines sit above the transcript, so you can watch it play and see what moved without switching back to Changes.

Expand Log under the transcript and each line grows a 💬. Clicking it opens a comment already anchored to the node or choice you just heard, so the thread lands on a spot in the story rather than on a line number.

Comments, suggestions, verdicts

Comments hang on an anchor — a node, a choice, a field — or on the review itself for notes that belong to no single line. Anchors use the same keys as localization, so renaming a node doesn't silently orphan the discussion: the thread is flagged stale anchor and listed under Unanchored, and Reports carries the same warning.

On a text anchor you can attach a suggested replacement. That is the reviewer's edit: they propose the words, and the author applies them with one button. Reviewers cannot change story files directly — the branch isn't on their disk, and keeping content edits to one writer is what keeps review data conflict-free.

Approve or Request changes records a verdict against the commit you read. If the author pushes more work afterwards, the review says so — "the branch has moved since this verdict" — rather than showing a stale tick over unread lines. Nothing enforces a verdict; with no server there is nothing that could. It is a note between colleagues, and a record of who read what.

Syncing, and merging

As a reviewer your comments sit in a local queue (inside .git/, so they can never be committed by accident) and the review shows how many are unsynced. Sync comments fetches, merges your notes into whatever is already on the branch, commits, and pushes — your working tree is never touched. Concurrent reviewers don't conflict: comment threads are separate files, and same-thread replies merge by union.

Once a review is approved and you are on its base branch with a clean tree, Merge brings the branch in and pushes. It merges cleanly or not at all — on any conflict it aborts completely and asks you to resolve it in git, rather than leaving a half-finished merge inside a narrative editor. A merged branch carries its review files into the base branch; that is the archive, which is why reviews are never deleted.

What this deliberately isn't

Parlance is not a git client. It has no branch creation, no conflict resolution, no history editing, and no GitHub pull-request sync. Branches, conflicts, and history stay in the tools built for them.