---
name: fidelity-translator
description: Translate safety-critical and regulated technical documents between any language pair, with the rigor those documents require. Built for aerospace, pharma, medical-device, legal, automotive, and nuclear documentation — Flight Operations Manuals, Standard Operating Procedures, Instructions for Use, regulatory submissions, contracts, certification dossiers. Triggers on any "translate" / "перекласти" / "übersetzen" / "翻译" / "翻訳" / "traducir" / "traduire" verb applied to a multi-page document, or any upload of a PDF/DOCX that contains regulatory-style content (numbered sections, WARNING/CAUTION callouts, figure/table cross-references, regulatory citations). Auto-detects source language from the document's content. Output is always a Word (.docx) that visually matches the source document family (configurable house style — formal-monochrome by default), with original engineering diagrams embedded and figure labels translated below each one. Uses Opus 4.6 for translation on safety-critical content with self-critique and back-translation passes, and maintains a per-project learning glossary that grows with every document so terminology stays consistent across the whole document family — the longer you use it on one product line, the better it gets at that product line. Distinct from generic translation: this skill optimizes for fidelity, terminology consistency, and verifiability, not for speed or fluency.
---

# fidelity-translator

A translation pipeline for documents where mistranslation has consequences — aerospace, pharma, medical device, legal, automotive, nuclear. The skill optimises for three things general-purpose translation does not: **terminology consistency across a document family**, **verifiability of safety-critical content**, and **fidelity to the source's structural conventions** (section numbering, figure references, regulatory citations, hazard callouts).

It is not a replacement for a certified human translator on documents that legally require one. It is what you reach for when you have hundreds of pages of regulated documentation, a small in-house terminology base, and limited human-reviewer time — and you want the AI's first draft to be one a domain expert can actually edit, rather than one they need to rewrite.

## What this skill is for

- A flight operations manual that must round-trip cleanly between English and the operator's working language.
- A pharmaceutical Standard Operating Procedure that has to match the active-substance terminology used in the existing dossier.
- An IFU (Instructions for Use) being submitted in a new jurisdiction where the regulator expects local-language WARNING/CAUTION wording that maps to ICH/ICAO/ISO conventions.
- A multi-hundred-page automotive safety case (ISO 26262) where every numbered hazard reference must survive the translation intact.
- A contract or certification dossier where a misrendered modal verb ("shall" vs "should") changes legal force.

## What this skill is not for

- A single sentence or paragraph (translate inline — this pipeline is overkill).
- A scanned PDF with no extractable text layer (run OCR first, then re-submit).
- A certified or sworn legal translation (the output is a working translation; a human-certified translator must sign off if legal certification is required — every output carries a disclaimer to this effect).
- Creative or marketing translation (this skill is tuned for register-formal, terminology-consistent, structurally-faithful output, which is the wrong register for ad copy).

## Languages

The skill auto-detects the source language by sampling the first ~20,000 characters of body text and running script-ratio detection plus a language-ID model (`langdetect` if installed, otherwise an Opus classification call on the sample). It defaults to translating into English unless:

- The user specifies an explicit target ("translate to German", "перекласти на українську", "übersetze ins Spanische")
- The project config (`project.yaml`, see below) declares a default target
- The detected source IS English — in which case the skill must ask for the target language unless the project config has one set

Language pairs known to be tested and tuned:

- English ↔ Ukrainian
- English ↔ German
- English ↔ French
- English ↔ Spanish
- English ↔ Mandarin (Simplified)
- English ↔ Japanese
- English ↔ Korean
- English ↔ Portuguese (BR and PT variants)

Other pairs work but with reduced terminology coverage in the default glossary seeds. See *Adding a new language pair* at the bottom of this file.

## Domains it ships defaults for

Each domain ships a seed glossary, a hazard-callout mapping, and a register guideline. The user picks one in `project.yaml`; if none is set, the skill asks at Step 0.

- **aerospace** — UAS/UAV, propulsion, avionics, regulatory bodies (EASA, FAA, ICAO, NATO STANAG), document types (AFM, FOM, AMM, ICD)
- **pharma** — active substances, dosage forms, ICH terminology, EMA/FDA references, SOP/IFU/SmPC structures
- **medical-device** — MDR/IVDR, ISO 13485, IFU, DHF references, hazard analysis terminology
- **legal** — modal verbs, clause structures, jurisdiction-specific authority terms, statute citation forms
- **automotive** — ISO 26262 ASIL levels, AUTOSAR, type-approval, ECE regulations
- **nuclear** — IAEA terminology, safety classification, operational limits and conditions
- **general** — fallback; no domain-specific glossary seed, basic hazard mapping only

## Inputs

- **PDF** (text-extractable) — primary input
- **.docx** — direct text + image extraction
- **.txt** / `.md` — plain text
- **.html** — text extraction, image references preserved

Scanned PDFs without an extractable text layer are flagged and the skill stops. The user is told to run OCR (tesseract, paddleOCR, or commercial) first.

## Output

A single `.docx` at the project's output directory (default `./translations/`):

```
<output_dir>/<original_basename>__<source_lang_code>_to_<target_lang_code>.docx
```

Language codes are ISO 639-1 (`en`, `de`, `uk`, `ja`, `zh`, etc.). Example:

- `UAV_Flight_Operations_Manual__uk_to_en.docx`
- `SOP_Tablet_Coating_2026__en_to_de.docx`

For partial scopes (a single chapter, a page range), append a scope suffix:

- `<basename>__uk_to_en__ch01.docx`
- `<basename>__uk_to_en__p001-030.docx`

Alongside the .docx, the skill writes:

- `<basename>__uk_to_en__verification.json` — deterministic verification report
- `<basename>__uk_to_en__glossary_proposals.md` — new terms surfaced during the run, for review/merge
- `<basename>__uk_to_en__bilingual.pdf` (optional, on `--bilingual` flag) — 2-column side-by-side review document

## Project configuration

A `project.yaml` file in the working directory (or any ancestor up to the user's home) configures defaults. Example:

```yaml
project: uav-flight-manual
domain: aerospace
source_language: uk          # ISO 639-1 or "auto"
target_language: en
glossary: ./glossary.md      # relative to this file
output_dir: ./translations/
house_style: formal-monochrome   # or: modern, custom (then house_style_config below)
model_translation: opus-4-6
model_critique: opus-4-6
model_back_translation: sonnet-4-6
verify_back_translation: safety-critical-only  # or: all, none
hazard_icon: ./assets/hazard.png  # optional; auto-generated SVG triangle if absent
disclaimer_template: ./disclaimer.md  # optional override
```

All fields are optional. With no `project.yaml`, the skill prompts at Step 0 for `domain`, `source_language` (if auto-detection is ambiguous), and `target_language`.

## House style — defaults

The deliverable must visually resemble the source document family, not a modern Microsoft Office document. The renderer (`scripts/build_docx.py`) enforces this; **do not** revert these conventions in iterations.

The default house style (`formal-monochrome`) is calibrated for regulatory/aviation/pharma documentation:

- **Font:** Times New Roman 12 pt throughout. No Calibri. No Arial. (Override with `house_style_config.font_family`.)
- **Colour:** monochrome — black ink on white. No coloured headings, no shaded callouts, no theme accents. The Heading 1/2/3/4 styles are applied (so Word's navigation pane / TOC fields work), but their default blue colour is overridden to black at both the style and run level.
- **Tables:** plain `Table Grid` style with explicit thin black borders on every cell. No fill colour, no banded rows, no shading.
- **Callouts (WARNING / CAUTION / NOTE and their target-language equivalents):** rendered as a 2-column bordered table — hazard triangle icon on the left (~1.6 cm wide), bold-centered label and justified body on the right. Same monochrome treatment as everything else. Default icon is a generated SVG triangle; override via `project.yaml`.
- **Lists:** numbered and bulleted lists are rendered with explicit number/bullet prefix text and hanging indent. Word's auto-incrementing `List Number` style is **not** used — it continues numbering across separate lists, which breaks figure-keyed component lists.
- **Page markers:** at the end of each source page, the markdown carries `*[p. NN of source]*` rendered as a centered italic line. This is how reviewers cross-reference the source.

Alternative built-in styles:

- `modern` — Calibri / Aptos, blue Heading 1, banded tables, coloured callout boxes (use for internal-only working translations where regulatory mimicry isn't needed).
- `custom` — fully configurable; supply a `house_style_config` block in `project.yaml`.

## Image policy

The skill's posture on images is **always embed, sometimes label-translate**.

- **Embedding** (placing the source image into the output .docx) is free — it's a file copy into the ZIP archive. Always do it. The reviewer expects to see what the source page showed.
- **Label translation** (sending an image to Opus to extract source-language text annotations into a label table below the figure) costs ~$0.10–0.30 per image. For a typical 300-page regulatory document, only a fraction of extracted images are real diagrams with translatable text — the rest are photographs, CAD exploded views with numeric pointers, sub-50px decorative icons, or stamps. So the full-document label-translation cost is typically on the order of $1–5.
- **Filter** (in `extract_doc.py`): images below 200×150 px are flagged `translate: False` by default, since they're almost always icons or bullet markers. They are still embedded if the markdown references them.
- **Opt-out:** for fast/draft translations the user can request `--no-label-translation`, in which case all `translate: True` flags are downgraded and no Opus calls are made for images.

When the chapter has any image that survived the size filter, the skill should briefly tell the user how many images are being label-translated, and continue without further confirmation unless the count is over 30 (in which case ask).

## Bootstrapping the glossary from an existing translation pair

On a brand-new project, the live glossary is empty (or only contains the domain seed). This is the cold-start problem: the first few documents through the pipeline get the benefit of the seed but not of any project-specific terminology decisions, and consistency only really kicks in after the second or third document.

If the user has an existing bilingual document pair — one source document and its already-translated counterpart, produced by a human translator, a previous tool, or an older version of this skill — that pair can be mined for terminology to pre-populate the project glossary before the first new translation runs. This is the single highest-leverage thing a user can do on day one.

The bootstrap script (`scripts/bootstrap_glossary.py`) takes a source/target pair, sentence-aligns them deterministically (Gale-Church length-ratio algorithm, the same approach professional CAT tools have used for 30 years), then surfaces aligned segment pairs in batches that the skill sends to Opus 4.6 with a structured terminology-extraction prompt. The output is a list of proposed glossary entries with provenance ("extracted from `<source>` ↔ `<target>` alignment, batch N, confidence 4/5"), surfaced via the standard `glossary__proposals.md` review flow.

A typical 200-page bilingual pair yields 100–400 proposed glossary entries and costs $1–3 in Opus calls; a 30-page pair yields 30–80 entries and costs under $1. As a side effect, the script can also export a TMX file (`--tmx-out`) for import into Trados / MemoQ / OmegaT.

The skill **should suggest the bootstrap** whenever it detects a first-time project — either no `project.yaml`, or `project.yaml` exists but the live glossary is empty (or has fewer than ~20 entries beyond the domain seed). The suggestion is offered at Step -1, before the normal preflight, and the user can accept, decline ("just translate, no bootstrap"), or defer ("ask me again next time").

If the user has multiple bilingual pairs, the bootstrap can be run multiple times — proposals accumulate, conflicts are surfaced for review, the live glossary grows monotonically with human approval.

## Workflow

The skill executes a chained pipeline. Step -1 is the cold-start bootstrap offer (first-run projects only). Step 0 is the user-facing preflight (always required). Step 1 identifies the file. Steps 2–3 are deterministic. Step 4 is the bulk Claude inference. Steps 5–7 are verification and assembly.

### Step -1 — Cold-start bootstrap offer (first-run projects only)

Trigger condition: the user is about to translate their first document for this project AND one of:

- No `project.yaml` exists in this directory (or any ancestor up to `~`)
- A `project.yaml` exists but `project.glossary` does not yet exist
- The live glossary exists but has fewer than ~20 entries beyond the domain seed (signal: glossary file mtime within a few minutes of project.yaml mtime, or no proposals files ever appended)

When triggered, offer the bootstrap **before** the normal Step 0 preflight:

```
▶ Using **fidelity-translator** (safety-critical document translation)

I notice this looks like your first translation for project <project_name>.
Your live glossary at <glossary_path> has <N> entries (or doesn't exist yet),
so your first run won't yet benefit from project-specific terminology decisions.

**Optional bootstrap (recommended for new projects):** if you have an existing
bilingual document pair — one source document plus its already-translated
counterpart from a previous human translator, vendor, or tool — I can mine
that pair for terminology and pre-populate your glossary before the new
translation starts. Typically yields 100-400 glossary entries from a 200-page
pair, at a cost of $1-3 in Opus calls.

Three options:
  (a) "bootstrap from <source.pdf> + <target.pdf>"  — run the cold-start pass
  (b) "just translate"                              — skip bootstrap, proceed to Step 0
  (c) "skip and don't ask again for this project"   — write a marker to project.yaml

What would you like?
```

If the user chooses (a):

1. Confirm the source/target documents exist and read
2. Run `python3 scripts/bootstrap_glossary.py <source> <target> <work_dir> [--tmx-out <tmx>]`
3. Iterate the extraction batches the script wrote to `<work_dir>/extraction_batches/`, send each to Opus 4.6 (or Sonnet 4.6 if `--draft`), parse the structured JSON responses, deduplicate entries across batches, detect conflicts (same source term → different target proposals), write the result to `<glossary>__proposals.md`
4. Surface the proposals file to the user for review — count, sample entries, conflict list
5. Wait for the user to merge accepted proposals into the live glossary (they can do this manually by editing the file, or by replying "merge all" / "merge all confidence ≥ 4" / etc.)
6. Continue to Step 0 (the regular preflight for the new document)

If the user chooses (b): proceed directly to Step 0.

If the user chooses (c): append `bootstrap_offered: declined` to `project.yaml` (or create the file) and proceed to Step 0. Do not re-offer for this project. The user can manually run the bootstrap later by invoking the script directly or by removing the marker.

The bootstrap is **opt-in**, never forced. It is also **safe to run multiple times** — proposals accumulate, conflicts are surfaced, the human always controls what enters the live glossary.

### When to fire this skill (and when not to)

Fire automatically on any of these signals:

- An attached or referenced PDF / .docx that turns out to be a regulated technical document (numbered sections, WARNING/CAUTION/NOTE callouts in any language, regulatory citations, figure/table cross-references)
- An ask containing a translation verb in any language ("translate" / "перекласти" / "übersetzen" / "翻译" / "翻訳" / "traducir" / "traduire") applied to a multi-page or multi-paragraph source
- Document-type names appearing in the ask: AFM, FOM, AMM, ICD, CDR, SOP, IFU, SmPC, DHF, type approval, safety case, certification dossier, regulatory submission

Do **not** fire (translate inline in chat instead, and say so) when:

- The source is a single sentence or short paragraph and the user just wants a quick rendering, not a deliverable
- The user explicitly asks for a chat-only translation ("just tell me what this says")
- The source is a screenshot of text only — the skill's pipeline assumes text-extractable PDF/.docx
- The source is creative or marketing content (this skill's register is wrong for that)

When you decide *not* to use the skill on something that could plausibly qualify, say so out loud — one line, e.g. *"Quick inline translation — skipping the fidelity-translator pipeline since it's a single paragraph."* That way the user always knows which mode they're getting.

Users can also force the skill explicitly: "use the fidelity-translator skill on this" / "run the fidelity translator" / "use the full pipeline". Always honour that, even on a short source.

### Step 0 — Preflight announcement (REQUIRED)

Before kicking off any work — extraction, translation, anything that costs tokens or wall time — post a short structured preview of what the skill will do, what resources it will consume, and ask the user to confirm. This serves three purposes: (1) the user knows that the **fidelity-translator skill** is firing rather than a generic Claude translation, (2) the user knows what's about to happen so they're not surprised by a long-running job or a bill, and (3) people running the skill for the first time learn what the workflow actually is.

The preflight has five sections, in this exact order. The first line is a **skill banner** that names the skill explicitly so its activation is visible — never omit it:

```
▶ Using **fidelity-translator** (safety-critical document translation)

**Translating: <document name>** (<N> pages, ~<W> words, <I> images)
Direction: <SOURCE_LANG> → <TARGET_LANG>  (auto-detected from <signal>; override with "translate to <language>")
Domain: <DOMAIN>  (from project.yaml; or "general" if no config)
Glossary: <PATH>  (<N existing terms> | new file will be created)

What I'll do:
1. Extract text and images from the source, detecting chapter boundaries
2. Identify domain terms in each chunk and pin <TARGET_LANG> equivalents
   from the running glossary before translating (reduces terminology drift)
3. Translate chapter-by-chapter with Opus 4.6, running parallel subagents
   so chapters finish concurrently
4. For safety-critical content (WARNING / CAUTION callouts, operating limits,
   emergency procedures, modal-verb clauses in legal text): apply a
   self-critique and refine pass on top of the first draft
5. Cross-reference every chunk against the project glossary and propose new
   term additions for review at the end
6. Run deterministic verification (section IDs, numerical values, figure /
   table references, regulatory citations, hazard categories) and back-
   translate safety-critical segments with Sonnet 4.6 (round-trip
   <SOURCE> → <TARGET> → <SOURCE>) to catch meaning drift
7. Assemble a Word document in <output_dir> matching the source's
   <house_style> layout (Times New Roman, bordered tables, monochrome
   callouts by default), with the original diagrams embedded and label
   translations under each one
8. Append new term proposals to <GLOSSARY_PATH> for your review/merge

Estimated cost: ~$<N> in Opus calls, ~$<M> in image label translation
Estimated wall time: ~<T> minutes

Reply "go" to proceed, "skip images" to disable label translation,
"draft only" to skip the self-critique and back-translation passes,
or "cancel" to stop.
```

Always wait for the "go" (or equivalent) before moving on. Long-running jobs that surprise the user are the most common cause of negative feedback for this skill.

### Step 1 — Source identification & extraction

Run `scripts/extract_doc.py <source> <work_dir>`. This:

- Branches by file extension (PDF / DOCX / TXT / HTML / MD)
- For PDF: uses `pdfinfo` to count pages, `pdftotext -layout` per page, `pdfimages -all` for images
- For DOCX: uses `python-docx` to walk the body, extract images from the ZIP archive
- For TXT/MD: passes through with chapter/heading detection via Markdown heading syntax
- Writes `text.json` (page-by-page text), copies images to `<work_dir>/images/` (renamed with page/size metadata), writes `manifest.json` (source, page count, detected languages, chapters, image inventory)

Heuristics for chapter detection are multilingual: `CHAPTER N`, `РОЗДІЛ N`, `KAPITEL N`, `CAPÍTULO N`, `CHAPITRE N`, `第N章`, `第N节`, `章N`. If no chapter markers are found, the whole document is treated as one chunk.

If the PDF has no extractable text layer (`pdftotext` returns near-empty), the skill stops and tells the user to OCR the source first.

### Step 2 — Chunking and glossary pin

For each chapter (or each ~3000-word block if no chapters):

- Scan the chunk for any source-language term that appears in the project glossary; build a "pinned terms" mini-table for that chunk
- The pinned mini-table is prepended to the chunk before sending to the translator, so the model sees both the glossary anchor and the surrounding context

This is the single biggest lever on terminology consistency. Without it, Opus is perfectly capable of rendering the same source term three different ways across three chapters.

### Step 3 — First-draft translation

Spawn one translator subagent per chunk, in parallel (typically 4–10 concurrent depending on chunk count). Each subagent receives:

- The chunk text (with pinned glossary mini-table at top)
- The style guide (`references/style_guide.md` + the per-domain addendum)
- A directive to preserve all section IDs, figure/table references, regulatory citations, and numerical values verbatim
- A directive to translate WARNING/CAUTION/NOTE callouts (and their target-language equivalents) with maximum fidelity — never paraphrase

Each subagent returns Markdown for its chunk. Translated chunks are written to `<work_dir>/translated/<chunk_id>.md`.

### Step 4 — Self-critique on safety-critical content

For chunks containing any of:

- WARNING / CAUTION / DANGER hazard callouts (in the source language)
- Operating limits or do-not-exceed values
- Emergency procedures
- Modal-verb clauses in legal text ("shall", "must", "is forbidden")
- Pharmaceutical dosage or administration instructions
- Numerical safety thresholds (pressure, temperature, voltage, ASIL/SIL/DAL levels)

…run a separate critique subagent with the source chunk and the draft translation as input. The critique agent's prompt is "find any meaning-drift, modal-verb-downgrade, or numerical/categorical errors in this translation". Its output is either "no issues" or a list of specific corrections. If corrections are returned, a refine subagent applies them and the chunk is re-emitted.

This is opt-out via `--draft-only`; default-on for safety-critical chunks.

### Step 5 — Deterministic verification

Run `scripts/verify_chunk.py <source.json> <chunk.md>` per chunk. This is pure regex — no LLM calls. It checks:

- **Section IDs** — every `NN.M.M.M` in the source appears in the target
- **Numbers** — every numerical value in the source appears in the target (with locale-aware date and decimal conversion handled by `babel`)
- **Figure / table references** — every "Fig. NN.M" / "Table NN.M" (in the source's language) maps to a reference in the target's language equivalent
- **Regulatory citations** — every citation pattern (§, Art., No., №, FAR/EASA-style identifiers) is preserved
- **Hazard categories** — count of WARNING/CAUTION/NOTE in source matches count of target-language equivalents, **and the ordered sequence matches** (catches per-callout category swaps even when counts are balanced)

Failures are written to `<chunk>.verify.json` and surfaced to the user as a punch list. The translation is not blocked — the user decides whether to re-translate, hand-edit, or accept.

### Step 6 — Back-translation verification (safety-critical only by default)

For chunks flagged in Step 4 (safety-critical), spawn a back-translation subagent (Sonnet 4.6 — cheaper, fluency-tuned) that translates the target chunk back into the source language. Compute embedding similarity between original source chunk and back-translated source; if below 0.85, flag for human review.

This is the single most expensive verification step. Default is "safety-critical only"; turn off with `--no-back-translation` or extend to whole-document with `verify_back_translation: all` in `project.yaml`.

### Step 7 — Assemble Word document

Run `scripts/build_docx.py <work_dir> <output.docx> --house-style <style>`. This:

- Loads `manifest.json` and `translated/order.json`
- Renders the preface (translation notice + disclaimer)
- Iterates chunks in order, rendering Markdown → DOCX with full house style enforcement (font, monochrome, bordered tables, callouts as 2-col tables with hazard icon)
- Embeds every referenced image; if a `<image>.labels.json` file sits alongside the image, renders a label-translation table below the image
- Inserts page break between chunks
- Saves to `<output_dir>/<basename>__<src>_to_<tgt>.docx`

### Step 8 — Glossary update

Append new term proposals (terms the translator subagents flagged as not-in-glossary-but-recurring) to `<glossary>__proposals.md` for human review. Do NOT auto-merge into the live glossary — the user owns terminology decisions. Conflicts (same source term → different target proposals across chunks) are surfaced with their per-chunk vote counts so the user can pick one.

## Glossary lifecycle

The glossary lives at `project.glossary` (default `./glossary.md`) and is the single source of terminology truth for the project. Its shape:

```markdown
# <Project> Glossary — <SRC>↔<TGT>

| <SRC> | <TGT> | Notes / context |
|---|---|---|
| <source term> | <target term> | <when to use, alternates, regulatory basis> |
```

- **Read** at the start of every translation
- **Pinned** per chunk during Step 2
- **Proposals appended** after each run to a sibling `<glossary>__proposals.md` for review
- **Conflicts** (same source → different target proposals) resolved by majority vote in the proposal file; the human can override later by editing the live glossary directly
- **Human edits to the glossary are sticky** — once a human writes a target for a source term, it is respected by future runs even if Opus would have chosen a different rendering

Seeds for the supported domains live under `references/glossary_seeds/<domain>__<src>_<tgt>.md` (e.g. `aerospace__uk_en.md`, `pharma__en_de.md`). On first run for a project, the relevant seed is copied to `project.glossary` if it doesn't exist. After that, the seed is no longer consulted.

The glossary can also be **bootstrapped on day one** from an existing bilingual document pair — see *Bootstrapping the glossary from an existing translation pair* above. This is the recommended onboarding path for any project that has at least one existing source-target document pair.

## Adding a new language pair

To extend to a language pair not in the tested list:

1. Add hazard mapping to `references/hazard_mappings.yaml`:
   ```yaml
   <lang_code>:
     WARNING: [<local equivalent>]
     CAUTION: [<local equivalent>]
     NOTE:    [<local equivalent>]
     DANGER:  [<local equivalent>]  # if used in that language's regulatory tradition
   ```
2. Add chapter regex to `extract_doc.py` `CHAPTER_PATTERNS` list.
3. Add a figure/table reference regex pair to `verify_chunk.py` `FIG_TABLE_PATTERNS` dict.
4. (Optional but recommended) seed a glossary at `references/glossary_seeds/<domain>__<src>_<tgt>.md` for each domain you'll use.
5. Add a short locale note to `references/style_guide.md` covering decimals, dates, quotes, and modal-verb conventions for the new pair.

The skill works without any of the above (defaulting to English-pair behaviour), but accuracy improves materially with each addition.

## Adding a new domain

To extend to a new vertical (e.g. maritime, rail signaling, defence electronics):

1. Add the domain key to the `VALID_DOMAINS` set in `scripts/project_config.py`.
2. Drop a glossary seed at `references/glossary_seeds/<domain>__<src>_<tgt>.md`.
3. Add a domain block to `references/style_guide.md` covering register, regulatory bodies, and citation conventions.
4. (Optional) extend `scripts/build_docx.py` `STYLES` dict if the domain uses a distinctive house style worth offering as a preset.

## Costs (rough order of magnitude)

For a 300-page regulatory document with ~80,000 source words and ~300 extracted images:

- Translation (Opus 4.6, parallel chunks): $8–15
- Self-critique on ~15% of chunks (safety-critical): $1–2
- Back-translation on safety-critical chunks (Sonnet 4.6): $0.50–1.50
- Image label translation (~5–10 % of images survive size filter): $1–5
- Deterministic verification: $0 (no LLM calls)

Total: typically $10–25 per document. Wall time: 8–25 minutes depending on chunk count and parallelism.

For the optional cold-start bootstrap from a bilingual pair (Step -1, one-time per project):

- Sentence alignment (Gale-Church): $0 (deterministic)
- Terminology extraction (Opus 4.6 over aligned batches): $1–3 for a 200-page pair, $0.30–1 for a 30-page pair
- TMX export (optional): $0 (deterministic)

Drafting mode (`--draft-only --no-back-translation --no-label-translation`) brings translation cost to $5–10 and time to 5–10 minutes, at the cost of losing the safety-critical refinement and image labels.

## What this skill does *not* do (and why)

- **It does not auto-merge glossary proposals.** Terminology decisions belong to the human. The skill surfaces proposals; the human merges.
- **It does not block on verification failures.** The verification report is informational. Some failures are false positives (e.g. a section number that legitimately got renumbered because of a merged chapter). The human reviewer decides.
- **It does not OCR scanned PDFs.** OCR quality varies wildly and a bad OCR upstream poisons the whole pipeline. Use a dedicated OCR tool (tesseract, paddleOCR, ABBYY) first.
- **It does not produce certified or sworn translations.** Every output carries a disclaimer to this effect.
- **It does not "improve" the source.** If the source contains an error, the translation faithfully reproduces it (flagged with a `[translator note]` if the chunk-level critique catches it).
- **It does not auto-merge bootstrap proposals either.** The cold-start bootstrap (Step -1) writes proposals to the same review file the regular runs use; the human still merges what they want.

## License and credits

Distributed under the MIT License. Built on the Anthropic Agent Skills format.

The skill was forged on real Ukrainian-to-English aerospace regulatory documents — Flight Operations Manuals, Maintenance Manuals, and certification dossiers for an unmanned aircraft platform — and has been generalised since. The architecture is general; the testbed was specific.
